|
|
@@ -0,0 +1,135 @@
|
|
|
+import { Card, Table, Button, Space, message, Popconfirm } from 'antd';
|
|
|
+import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
|
+import { useNavigate } from 'react-router';
|
|
|
+import { useState } from 'react';
|
|
|
+import { excelTemplateClient } from '@/client/api';
|
|
|
+import type { InferResponseType } from 'hono/client';
|
|
|
+import { PlusOutlined } from '@ant-design/icons';
|
|
|
+
|
|
|
+type TemplateListResponse = InferResponseType<typeof excelTemplateClient.$get, 200>;
|
|
|
+type TemplateItem = TemplateListResponse['data'][0];
|
|
|
+
|
|
|
+function TemplateList() {
|
|
|
+ const navigate = useNavigate();
|
|
|
+ const queryClient = useQueryClient();
|
|
|
+
|
|
|
+ const [pagination, setPagination] = useState({
|
|
|
+ current: 1,
|
|
|
+ pageSize: 10
|
|
|
+ });
|
|
|
+
|
|
|
+ const { data, isLoading } = useQuery({
|
|
|
+ queryKey: ['templates', pagination],
|
|
|
+ queryFn: async () => {
|
|
|
+ const res = await excelTemplateClient.$get({
|
|
|
+ query: {
|
|
|
+ page: pagination.current,
|
|
|
+ pageSize: pagination.pageSize
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (res.status !== 200) {
|
|
|
+ const data = await res.json();
|
|
|
+ throw new Error(data.message);
|
|
|
+ }
|
|
|
+ return await res.json();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ const { mutate: deleteTemplate, isPending: isDeleting } = useMutation({
|
|
|
+ mutationFn: async (id: number) => {
|
|
|
+ const res = await excelTemplateClient[':id'].$delete({
|
|
|
+ param: { id }
|
|
|
+ });
|
|
|
+ if (res.status !== 200) {
|
|
|
+ const data = await res.json();
|
|
|
+ throw new Error(data.message);
|
|
|
+ }
|
|
|
+ return await res.json();
|
|
|
+ },
|
|
|
+ onSuccess: () => {
|
|
|
+ message.success('删除成功');
|
|
|
+ queryClient.invalidateQueries({ queryKey: ['templates'] });
|
|
|
+ },
|
|
|
+ onError: () => {
|
|
|
+ message.error('删除失败');
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ const columns = [
|
|
|
+ {
|
|
|
+ title: '模板名称',
|
|
|
+ dataIndex: 'name',
|
|
|
+ key: 'name'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '创建时间',
|
|
|
+ dataIndex: 'createdAt',
|
|
|
+ key: 'createdAt',
|
|
|
+ render: (date: string) => new Date(date).toLocaleString()
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '操作',
|
|
|
+ key: 'action',
|
|
|
+ render: (_: any, record: TemplateItem) => (
|
|
|
+ <Space>
|
|
|
+ <Button
|
|
|
+ size="small"
|
|
|
+ onClick={() => navigate(`/member/templates/${record.id}`)}
|
|
|
+ >
|
|
|
+ 编辑
|
|
|
+ </Button>
|
|
|
+ <Popconfirm
|
|
|
+ title="确定要删除吗?"
|
|
|
+ onConfirm={() => deleteTemplate(record.id)}
|
|
|
+ okButtonProps={{ loading: isDeleting }}
|
|
|
+ >
|
|
|
+ <Button size="small" danger>
|
|
|
+ 删除
|
|
|
+ </Button>
|
|
|
+ </Popconfirm>
|
|
|
+ </Space>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ ];
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className="p-3 h-full">
|
|
|
+ <Card
|
|
|
+ title="模板列表"
|
|
|
+ extra={
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ icon={<PlusOutlined />}
|
|
|
+ onClick={() => navigate('/member/templates/new')}
|
|
|
+ >
|
|
|
+ 新增模板
|
|
|
+ </Button>
|
|
|
+ }
|
|
|
+ styles={{
|
|
|
+ body: {
|
|
|
+ height: 'calc(100vh - 130px)'
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Table
|
|
|
+ loading={isLoading}
|
|
|
+ columns={columns}
|
|
|
+ dataSource={data?.data || []}
|
|
|
+ rowKey="id"
|
|
|
+ scroll={{ y: 'calc(100vh - 200px)' }}
|
|
|
+ pagination={{
|
|
|
+ ...pagination,
|
|
|
+ total: data?.pagination?.total || 0,
|
|
|
+ showSizeChanger: true,
|
|
|
+ showTotal: (total) => `共 ${total} 条`,
|
|
|
+ onChange: (page, pageSize) => {
|
|
|
+ setPagination({ current: page, pageSize });
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </Card>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+export default TemplateList;
|