Просмотр исходного кода

♻️ refactor(contract): 重构合同续签页面数据获取逻辑

- 从ahooks的useRequest迁移到@tanstack/react-query的数据获取方案
- 使用useQuery管理合同列表和续签记录的数据获取与缓存
- 添加queryClient实现数据更新后的缓存失效与重新获取
- 优化错误处理,确保错误信息正确显示
- 移除手动调用数据获取的逻辑,改为react-query自动管理

✨ feat(contract): 增强合同续签表格显示信息

- 新增"客户名称"列,显示合同关联客户信息
- 新增"续签开始日期"和"续签结束日期"列,明确续签时间范围
- 新增"续签金额"列,显示续签合同金额
- 优化"状态"列显示,使用标签组件直观展示状态信息
- 优化"操作"列,添加编辑和删除功能按钮
yourname 9 месяцев назад
Родитель
Сommit
13a885bcc0
1 измененных файлов с 113 добавлено и 45 удалено
  1. 113 45
      src/client/admin/pages/ContractRenews.tsx

+ 113 - 45
src/client/admin/pages/ContractRenews.tsx

@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
 import { Table, Button, Space, Tag, Input, DatePicker, Select, Form, message, Modal, Typography, Divider, Card } from 'antd';
 import { PlusOutlined, EditOutlined, DeleteOutlined, SearchOutlined, ReloadOutlined, SaveOutlined, CloseOutlined } from '@ant-design/icons';
 import type { TableProps, FormProps } from 'antd';
-import { useRequest } from 'ahooks';
+import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
 import dayjs, { Dayjs } from 'dayjs';
 import { App } from 'antd';
 import type { InferResponseType, InferRequestType } from 'hono/client';
@@ -34,6 +34,7 @@ const { RangePicker } = DatePicker;
 
 const ContractRenews: React.FC = () => {
   const { message: antMessage } = App.useApp();
+  const queryClient = useQueryClient();
   const [form] = Form.useForm();
   const [searchForm] = Form.useForm();
   const [isModalVisible, setIsModalVisible] = useState<boolean>(false);
@@ -44,49 +45,52 @@ const ContractRenews: React.FC = () => {
   const [total, setTotal] = useState<number>(0);
 
   // 获取合同列表
-  const { run: fetchContracts } = useRequest(async () => {
-    const response = await contractClient.$get({
-      query: { page: 1, pageSize: 1000 }
-    });
-    
-    if (!response.ok) {
-      throw new Error('获取合同列表失败');
-    }
-    
-    const data = await response.json();
-    return data.data;
-  }, {
+  const { data: contractsData } = useQuery({
+    queryKey: ['contracts', 'all'],
+    queryFn: async () => {
+      const response = await contractClient.$get({
+        query: { page: 1, pageSize: 1000 }
+      });
+      
+      if (!response.ok) {
+        throw new Error('获取合同列表失败');
+      }
+      
+      const data = await response.json();
+      return data.data;
+    },
     onSuccess: (data) => {
       setContracts(data);
     },
     onError: (error) => {
-      antMessage.error(`获取合同列表失败: ${error.message}`);
+      antMessage.error(`获取合同列表失败: ${error instanceof Error ? error.message : '未知错误'}`);
     },
-    manual: false
   });
 
-  // 获取续签列表
-  const { loading, run: fetchRenews } = useRequest(async (params: any) => {
-    const response = await contractRenewClient.$get({
-      query: params
+  
+    // 获取续签列表
+    const fetchRenewsData = async (params: any) => {
+      const response = await contractRenewClient.$get({
+        query: params
+      });
+      
+      if (!response.ok) {
+        throw new Error('获取续签记录失败');
+      }
+      
+      return response.json();
+    };
+  
+    const { data: renewsData, isLoading: loading, refetch: fetchRenews } = useQuery({
+      queryKey: ['contractRenews', currentPage, pageSize],
+      queryFn: () => fetchRenewsData({ page: currentPage, pageSize }),
+      onSuccess: (data: ContractRenewListResponse) => {
+        setTotal(data.pagination.total);
+      },
+      onError: (error) => {
+        antMessage.error(`获取续签记录失败: ${error instanceof Error ? error.message : '未知错误'}`);
+      },
     });
-    
-    if (!response.ok) {
-      throw new Error('获取续签记录失败');
-    }
-    
-    return response.json();
-  }, {
-    onSuccess: (data: ContractRenewListResponse) => {
-      setTotal(data.pagination.total);
-      return data;
-    },
-    onError: (error) => {
-      antMessage.error(`获取续签记录失败: ${error.message}`);
-    },
-    manual: true
-  });
-
   // 搜索功能
   const handleSearch = async () => {
     try {
@@ -110,7 +114,7 @@ const ContractRenews: React.FC = () => {
         params.endDate = values.dateRange[1].format('YYYY-MM-DD');
       }
       
-      fetchRenews(params);
+      fetchRenews({ ...params });
     } catch (error) {
       antMessage.error('搜索参数验证失败');
     }
@@ -127,10 +131,8 @@ const ContractRenews: React.FC = () => {
     setCurrentPage(pagination.current || 1);
     setPageSize(pagination.pageSize || 10);
     
-    fetchRenews({
-      page: pagination.current || 1,
-      pageSize: pagination.pageSize || 10,
-    });
+    setCurrentPage(pagination.current || 1);
+    setPageSize(pagination.pageSize || 10);
   };
 
   // 打开新增/编辑模态框
@@ -196,7 +198,7 @@ const ContractRenews: React.FC = () => {
       }
       
       setIsModalVisible(false);
-      fetchRenews({ page: currentPage, pageSize }); // 重新加载数据
+      queryClient.invalidateQueries({ queryKey: ['contractRenews'] }); // 重新加载数据
     } catch (error) {
       antMessage.error(`操作失败: ${error instanceof Error ? error.message : '未知错误'}`);
     }
@@ -220,7 +222,7 @@ const ContractRenews: React.FC = () => {
           }
           
           antMessage.success('续签记录删除成功');
-          fetchRenews({ page: currentPage, pageSize }); // 重新加载数据
+          queryClient.invalidateQueries({ queryKey: ['contractRenews'] }); // 重新加载数据
         } catch (error) {
           antMessage.error(`删除失败: ${error instanceof Error ? error.message : '未知错误'}`);
         }
@@ -230,8 +232,7 @@ const ContractRenews: React.FC = () => {
 
   // 初始化加载数据
   useEffect(() => {
-    fetchContracts();
-    fetchRenews({ page: 1, pageSize });
+    // 初始加载由useQuery自动触发
   }, []);
 
   // 表格列定义
@@ -248,6 +249,73 @@ const ContractRenews: React.FC = () => {
       dataIndex: ['contract', 'contractNo'],
       key: 'contractNo',
       width: 150,
+    },
+    {
+      title: '客户名称',
+      dataIndex: ['contract', 'customer', 'name'],
+      key: 'customerName',
+      width: 180,
+    },
+    {
+      title: '续签开始日期',
+      dataIndex: 'renewStartDate',
+      key: 'renewStartDate',
+      width: 120,
+      render: (date: string) => date ? dayjs(date).format('YYYY-MM-DD') : '-',
+    },
+    {
+      title: '续签结束日期',
+      dataIndex: 'renewEndDate',
+      key: 'renewEndDate',
+      width: 120,
+      render: (date: string) => date ? dayjs(date).format('YYYY-MM-DD') : '-',
+    },
+    {
+      title: '续签金额',
+      dataIndex: 'renewAmount',
+      key: 'renewAmount',
+      width: 100,
+      render: (amount: number) => `¥${amount.toFixed(2)}`,
+    },
+    {
+      title: '状态',
+      dataIndex: 'status',
+      key: 'status',
+      width: 100,
+      render: (status: number) => {
+        const statusInfo = RenewStatusEnum[status];
+        return statusInfo ? (
+          <Tag color={statusInfo.color} key={status}>
+            {statusInfo.label}
+          </Tag>
+        ) : (
+          <Tag color="default">未知</Tag>
+        );
+      },
+    },
+    {
+      title: '操作',
+      key: 'action',
+      width: 150,
+      render: (_: any, record: ContractRenewItem) => (
+        <Space size="middle">
+          <Button
+            type="text"
+            icon={<EditOutlined />}
+            onClick={() => showModal(record)}
+          >
+            编辑
+          </Button>
+          <Button
+            type="text"
+            danger
+            icon={<DeleteOutlined />}
+            onClick={() => handleDelete(record.id)}
+          >
+            删除
+          </Button>
+        </Space>
+      ),
       sorter: true,
     },
     {