Browse Source

✨ feat(contract): 重构合同续签管理页面

- 引入ahooks替代react-query优化数据请求逻辑
- 优化UI布局,添加卡片组件和标题层级
- 实现高级搜索功能,支持按合同、状态和日期范围筛选
- 改进表格展示,增加客户名称、续签期限等关键信息
- 优化状态显示,使用带颜色标签直观展示不同续签状态
- 完善表单验证,添加必填项校验和金额格式验证
- 改进日期处理,统一使用dayjs格式化日期显示
- 优化操作体验,添加确认弹窗和加载状态提示

♻️ refactor(contract): 重命名变量和API客户端以符合命名规范

- 将hetongRenewClient重命名为contractRenewClient
- 将hetongClient重命名为contractClient
- 更新相关类型定义,如HetongRenewItem改为ContractRenewItem
- 统一使用中文命名的状态枚举,提高代码可读性

🐛 fix(contract): 修复续签记录操作相关问题

- 修复删除功能未确认直接删除的问题,添加确认弹窗
- 修复分页逻辑错误,确保页码切换正确加载数据
- 修复表单提交后数据未刷新的问题
- 修复日期格式化错误,确保后端能正确接收日期格式

💄 style(contract): 优化续签管理页面样式

- 调整间距和布局,提升页面美观度
- 统一按钮尺寸和图标使用
- 优化表单布局,使用网格系统排列表单项
- 添加分割线区分不同功能区域
- 调整表格列宽,优化内容展示
yourname 9 months ago
parent
commit
de104df74f
1 changed files with 408 additions and 311 deletions
  1. 408 311
      src/client/admin/pages/ContractRenews.tsx

+ 408 - 311
src/client/admin/pages/ContractRenews.tsx

@@ -1,234 +1,314 @@
-import React, { useState } from 'react';
-import { Table, Button, Space, Input, Modal, Form, message, Select, DatePicker } from 'antd';
-import { PlusOutlined, EditOutlined, DeleteOutlined, SearchOutlined } from '@ant-design/icons';
-import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
-import { hetongRenewClient, hetongClient } from '@/client/api';
-import type { InferResponseType } from 'hono/client';
-import dayjs from 'dayjs';
+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 dayjs, { Dayjs } from 'dayjs';
+import { App } from 'antd';
+import type { InferResponseType, InferRequestType } from 'hono/client';
 
 
-// 定义类型
-type HetongRenewItem = InferResponseType<typeof hetongRenewClient.$get, 200>['data'][0];
-type HetongRenewListResponse = InferResponseType<typeof hetongRenewClient.$get, 200>;
-type HetongItem = InferResponseType<typeof hetongClient.$get, 200>['data'][0];
+// API客户端导入
+import { contractRenewClient } from '@/client/api';
+import { contractClient } from '@/client/api';
+
+// 类型定义
+type ContractRenewItem = InferResponseType<typeof contractRenewClient[':id']['$get'], 200>;
+type ContractRenewListResponse = InferResponseType<typeof contractRenewClient.$get, 200>;
+type CreateContractRenewRequest = InferRequestType<typeof contractRenewClient.$post>['json'];
+type UpdateContractRenewRequest = InferRequestType<typeof contractRenewClient[':id']['$put']>['json'];
+type ContractItem = InferResponseType<typeof contractClient[':id']['$get'], 200>;
+type ContractListResponse = InferResponseType<typeof contractClient.$get, 200>;
+
+// 续签状态枚举
+const RenewStatusEnum = {
+  0: { label: '草稿', color: 'gold' },
+  1: { label: '待审核', color: 'blue' },
+  2: { label: '已审核', color: 'green' },
+  3: { label: '已拒绝', color: 'red' },
+};
+
+const { Title } = Typography;
+const { Option } = Select;
+const { confirm } = Modal;
+const { RangePicker } = DatePicker;
 
 
 const ContractRenews: React.FC = () => {
 const ContractRenews: React.FC = () => {
+  const { message: antMessage } = App.useApp();
   const [form] = Form.useForm();
   const [form] = Form.useForm();
-  const [modalVisible, setModalVisible] = useState(false);
-  const [editingKey, setEditingKey] = useState<string | null>(null);
-  const [searchText, setSearchText] = useState('');
-  const [contracts, setContracts] = useState<HetongItem[]>([]);
-  const queryClient = useQueryClient();
-  
+  const [searchForm] = Form.useForm();
+  const [isModalVisible, setIsModalVisible] = useState<boolean>(false);
+  const [currentRecord, setCurrentRecord] = useState<ContractRenewItem | null>(null);
+  const [contracts, setContracts] = useState<ContractItem[]>([]);
+  const [pageSize, setPageSize] = useState<number>(10);
+  const [currentPage, setCurrentPage] = useState<number>(1);
+  const [total, setTotal] = useState<number>(0);
+
   // 获取合同列表
   // 获取合同列表
-  const { data: contractsData } = useQuery(
-    ['contractsForRenew'],
-    async () => {
-      const response = await hetongClient.$get({ query: { page: 1, pageSize: 1000 } });
-      if (response.status !== 200) throw new Error('Failed to fetch contracts');
-      return response.json() as Promise<InferResponseType<typeof hetongClient.$get, 200>>;
-    },
-    {
-      onSuccess: (result) => {
-        setContracts(result.data);
-      },
+  const { run: fetchContracts } = useRequest(async () => {
+    const response = await contractClient.$get({
+      query: { page: 1, pageSize: 1000 }
+    });
+    
+    if (!response.ok) {
+      throw new Error('获取合同列表失败');
     }
     }
-  );
-  
-  // 获取合同续签列表数据
-  const fetchContractRenews = async ({ page, pageSize }: { page: number; pageSize: number }): Promise<HetongRenewListResponse> => {
-    const response = await hetongRenewClient.$get({ query: { page, pageSize, keyword: searchText } });
-    if (response.status !== 200) throw new Error('Failed to fetch contract renews');
-    return response.json() as Promise<HetongRenewListResponse>;
-  };
-  
-  const { data, isLoading: loading, refetch } = useQuery(
-    ['contractRenews', pagination.current, pagination.pageSize, searchText],
-    () => fetchContractRenews({ page: pagination.current, pageSize: pagination.pageSize }),
-    {
-      onSuccess: (result) => {
-        setDataSource(result.data);
-        setPagination({
-          ...pagination,
-          total: result.pagination.total,
-        });
-      },
+    
+    const data = await response.json();
+    return data.data;
+  }, {
+    onSuccess: (data) => {
+      setContracts(data);
+    },
+    onError: (error) => {
+      antMessage.error(`获取合同列表失败: ${error.message}`);
+    },
+    manual: false
+  });
+
+  // 获取续签列表
+  const { loading, run: fetchRenews } = useRequest(async (params: any) => {
+    const response = await contractRenewClient.$get({
+      query: params
+    });
+    
+    if (!response.ok) {
+      throw new Error('获取续签记录失败');
     }
     }
-  );
-  
-  const [dataSource, setDataSource] = useState<HetongRenewItem[]>([]);
-  const [pagination, setPagination] = useState({
-    current: 1,
-    pageSize: 10,
-    total: 0,
+    
+    return response.json();
+  }, {
+    onSuccess: (data: ContractRenewListResponse) => {
+      setTotal(data.pagination.total);
+      return data;
+    },
+    onError: (error) => {
+      antMessage.error(`获取续签记录失败: ${error.message}`);
+    },
+    manual: true
   });
   });
-  
-  // 搜索
-  const handleSearch = () => {
-    setPagination({ ...pagination, current: 1 });
-    refetch();
+
+  // 搜索功能
+  const handleSearch = async () => {
+    try {
+      const values = await searchForm.validateFields();
+      const params: any = {
+        page: currentPage,
+        pageSize,
+      };
+      
+      // 处理搜索参数
+      if (values.contractId) {
+        params.contractId = values.contractId;
+      }
+      
+      if (values.status !== undefined && values.status !== null) {
+        params.status = values.status;
+      }
+      
+      if (values.dateRange && values.dateRange.length > 0) {
+        params.startDate = values.dateRange[0].format('YYYY-MM-DD');
+        params.endDate = values.dateRange[1].format('YYYY-MM-DD');
+      }
+      
+      fetchRenews(params);
+    } catch (error) {
+      antMessage.error('搜索参数验证失败');
+    }
   };
   };
-  
-  // 分页变化
-  const handleTableChange = (pagination: any) => {
-    setPagination(pagination);
-    refetch();
+
+  // 重置搜索
+  const handleReset = () => {
+    searchForm.resetFields();
+    fetchRenews({ page: 1, pageSize });
   };
   };
-  
-  // 显示添加/编辑弹窗
-  const showModal = (record?: HetongRenewItem) => {
-    setModalVisible(true);
+
+  // 分页变化处理
+  const handleTableChange: TableProps<ContractRenewItem>['onChange'] = (pagination) => {
+    setCurrentPage(pagination.current || 1);
+    setPageSize(pagination.pageSize || 10);
+    
+    fetchRenews({
+      page: pagination.current || 1,
+      pageSize: pagination.pageSize || 10,
+    });
+  };
+
+  // 打开新增/编辑模态框
+  const showModal = (record?: ContractRenewItem) => {
+    setCurrentRecord(record || null);
+    
     if (record) {
     if (record) {
-      setEditingKey(record.id);
+      // 编辑模式 - 填充表单
       form.setFieldsValue({
       form.setFieldsValue({
-        id: record.id,
         contractId: record.contractId,
         contractId: record.contractId,
-        amount: record.amount,
-        revenue: record.revenue,
-        endDate: record.endDate ? dayjs(record.endDate) : null,
-        state: record.state,
-        content: record.content,
-        auditStatus: record.auditStatus,
-        auditTime: record.auditTime ? dayjs(record.auditTime) : null,
-        auditReasons: record.auditReasons,
-        userId: record.userId,
-        createdTime: record.createdTime ? dayjs(record.createdTime) : null,
+        renewNo: record.renewNo,
+        renewStartDate: record.renewStartDate ? dayjs(record.renewStartDate) : null,
+        renewEndDate: record.renewEndDate ? dayjs(record.renewEndDate) : null,
+        renewAmount: record.renewAmount,
+        status: record.status,
+        remark: record.remark,
       });
       });
     } else {
     } else {
-      setEditingKey(null);
+      // 新增模式 - 重置表单
       form.resetFields();
       form.resetFields();
     }
     }
+    
+    setIsModalVisible(true);
   };
   };
-  
-  // 关闭弹窗
+
+  // 关闭模态框
   const handleCancel = () => {
   const handleCancel = () => {
-    setModalVisible(false);
+    setIsModalVisible(false);
     form.resetFields();
     form.resetFields();
   };
   };
-  
-  // 创建合同续签记录
-  const createContractRenew = useMutation(
-    async (data: any) => {
-      const response = await hetongRenewClient.$post({ json: data });
-      if (!response.ok) throw new Error('Failed to create contract renew');
-      return response.json();
-    },
-    {
-      onSuccess: () => {
-        message.success('合同续签记录创建成功');
-        queryClient.invalidateQueries({ queryKey: ['contractRenews'] });
-        setModalVisible(false);
-      },
-      onError: () => {
-        message.error('操作失败,请重试');
-      }
-    }
-  );
-  
-  // 更新合同续签记录
-  const updateContractRenew = useMutation(
-    async ({ id, data }: { id: string; data: any }) => {
-      const response = await hetongRenewClient[':id'].$put({ param: { id: parseInt(id, 10) }, json: data });
-      if (!response.ok) throw new Error('Failed to update contract renew');
-      return response.json();
-    },
-    {
-      onSuccess: () => {
-        message.success('合同续签记录更新成功');
-        queryClient.invalidateQueries({ queryKey: ['contractRenews'] });
-        setModalVisible(false);
-      },
-      onError: () => {
-        message.error('操作失败,请重试');
-      }
-    }
-  );
-  
-  // 删除合同续签记录
-  const deleteContractRenew = useMutation(
-    async (id: string) => {
-      const response = await hetongRenewClient[':id'].$delete({ param: { id: parseInt(id, 10) } });
-      if (!response.ok) throw new Error('Failed to delete contract renew');
-      return response.json();
-    },
-    {
-      onSuccess: () => {
-        message.success('合同续签记录删除成功');
-        queryClient.invalidateQueries({ queryKey: ['contractRenews'] });
-      },
-      onError: () => {
-        message.error('删除失败,请重试');
-      }
-    }
-  );
-  
-  // 提交表单
-  const handleSubmit = async () => {
+
+  // 保存续签记录
+  const handleSubmit: FormProps['onFinish'] = async (values) => {
     try {
     try {
-      const values = await form.validateFields();
-      
-      // 处理日期字段
-      if (values.endDate) values.endDate = values.endDate.format('YYYY-MM-DD');
-      if (values.auditTime) values.auditTime = values.auditTime.format('YYYY-MM-DD HH:mm:ss');
-      if (values.createdTime) values.createdTime = values.createdTime.format('YYYY-MM-DD HH:mm:ss');
-      
-      if (editingKey) {
+      // 格式化日期
+      const formattedValues: CreateContractRenewRequest | UpdateContractRenewRequest = {
+        ...values,
+        renewStartDate: values.renewStartDate ? values.renewStartDate.format('YYYY-MM-DD') : undefined,
+        renewEndDate: values.renewEndDate ? values.renewEndDate.format('YYYY-MM-DD') : undefined,
+      };
+
+      if (currentRecord) {
         // 更新操作
         // 更新操作
-        await updateContractRenew.mutateAsync({ id: editingKey, data: values });
+        const response = await contractRenewClient[':id']['$put']({
+          param: { id: currentRecord.id },
+          json: formattedValues as UpdateContractRenewRequest
+        });
+        
+        if (!response.ok) {
+          throw new Error('更新续签记录失败');
+        }
+        antMessage.success('续签记录更新成功');
       } else {
       } else {
         // 创建操作
         // 创建操作
-        await createContractRenew.mutateAsync(values);
+        const response = await contractRenewClient.$post({
+          json: formattedValues as CreateContractRenewRequest
+        });
+        
+        if (!response.ok) {
+          throw new Error('创建续签记录失败');
+        }
+        antMessage.success('续签记录创建成功');
       }
       }
+      
+      setIsModalVisible(false);
+      fetchRenews({ page: currentPage, pageSize }); // 重新加载数据
     } catch (error) {
     } catch (error) {
-      message.error('操作失败,请重试');
+      antMessage.error(`操作失败: ${error instanceof Error ? error.message : '未知错误'}`);
     }
     }
   };
   };
-  
+
+  // 删除续签记录
+  const handleDelete = (id: number) => {
+    confirm({
+      title: '确认删除',
+      content: '您确定要删除这条续签记录吗?此操作不可撤销。',
+      okText: '确认',
+      cancelText: '取消',
+      onOk: async () => {
+        try {
+          const response = await contractRenewClient[':id']['$delete']({
+            param: { id }
+          });
+          
+          if (!response.ok) {
+            throw new Error('删除失败');
+          }
+          
+          antMessage.success('续签记录删除成功');
+          fetchRenews({ page: currentPage, pageSize }); // 重新加载数据
+        } catch (error) {
+          antMessage.error(`删除失败: ${error instanceof Error ? error.message : '未知错误'}`);
+        }
+      },
+    });
+  };
+
+  // 初始化加载数据
+  useEffect(() => {
+    fetchContracts();
+    fetchRenews({ page: 1, pageSize });
+  }, []);
+
   // 表格列定义
   // 表格列定义
   const columns = [
   const columns = [
     {
     {
-      title: '续签ID',
-      dataIndex: 'id',
-      key: 'id',
+      title: '续签编号',
+      dataIndex: 'renewNo',
+      key: 'renewNo',
+      width: 150,
+      sorter: true,
     },
     },
     {
     {
-      title: '合同ID',
-      dataIndex: 'contractId',
-      key: 'contractId',
-      render: (contractId: string) => {
-        const contract = contracts.find(c => c.id === contractId);
-        return contract ? `${contract.id} (${contract.contractNumber})` : contractId;
-      },
+      title: '原合同编号',
+      dataIndex: ['contract', 'contractNo'],
+      key: 'contractNo',
+      width: 150,
+      sorter: true,
     },
     },
     {
     {
-      title: '续签金额',
-      dataIndex: 'amount',
-      key: 'amount',
+      title: '客户名称',
+      dataIndex: ['contract', 'customer', 'name'],
+      key: 'customerName',
+      width: 180,
+    },
+    {
+      title: '续签期限',
+      key: 'period',
+      width: 200,
+      render: (_, record: ContractRenewItem) => (
+        <>
+          {record.renewStartDate ? dayjs(record.renewStartDate).format('YYYY-MM-DD') : '-'}
+          {' 至 '}
+          {record.renewEndDate ? dayjs(record.renewEndDate).format('YYYY-MM-DD') : '-'}
+        </>
+      ),
     },
     },
     {
     {
-      title: '续签状态',
-      dataIndex: 'state',
-      key: 'state',
+      title: '续签金额',
+      dataIndex: 'renewAmount',
+      key: 'renewAmount',
+      width: 120,
+      render: (amount: number) => `¥ ${amount.toFixed(2)}`,
+      sorter: (a: ContractRenewItem, b: ContractRenewItem) => a.renewAmount - b.renewAmount,
     },
     },
     {
     {
-      title: '结束日期',
-      dataIndex: 'endDate',
-      key: 'endDate',
-      render: (date: string) => date ? new Date(date).toLocaleDateString() : '-',
+      title: '状态',
+      dataIndex: 'status',
+      key: 'status',
+      width: 100,
+      filters: Object.entries(RenewStatusEnum).map(([value, { label }]) => ({
+        text: label,
+        value,
+      })),
+      render: (status: number) => {
+        const statusInfo = RenewStatusEnum[status] || { label: '未知', color: 'default' };
+        return <Tag color={statusInfo.color}>{statusInfo.label}</Tag>;
+      },
     },
     },
     {
     {
-      title: '审批状态',
-      dataIndex: 'auditStatus',
-      key: 'auditStatus',
+      title: '创建时间',
+      dataIndex: 'createdAt',
+      key: 'createdAt',
+      width: 160,
+      render: (date: string) => dayjs(date).format('YYYY-MM-DD HH:mm'),
+      sorter: true,
     },
     },
     {
     {
       title: '操作',
       title: '操作',
       key: 'action',
       key: 'action',
-      render: (_: any, record: HetongRenewItem) => (
-        <Space size="middle">
+      width: 150,
+      render: (_: any, record: ContractRenewItem) => (
+        <Space size="small">
           <Button 
           <Button 
             type="text" 
             type="text" 
             icon={<EditOutlined />} 
             icon={<EditOutlined />} 
             onClick={() => showModal(record)}
             onClick={() => showModal(record)}
+            size="small"
           >
           >
             编辑
             编辑
           </Button>
           </Button>
@@ -236,7 +316,8 @@ const ContractRenews: React.FC = () => {
             type="text" 
             type="text" 
             danger 
             danger 
             icon={<DeleteOutlined />} 
             icon={<DeleteOutlined />} 
-            onClick={() => deleteContractRenew.mutate(record.id)}
+            onClick={() => handleDelete(record.id)}
+            size="small"
           >
           >
             删除
             删除
           </Button>
           </Button>
@@ -244,183 +325,199 @@ const ContractRenews: React.FC = () => {
       ),
       ),
     },
     },
   ];
   ];
-  
+
   return (
   return (
-    <div className="p-4">
-      <div className="flex justify-between items-center mb-4">
-        <h2 className="text-xl font-bold">合同续签管理</h2>
+    <div className="p-6">
+      <div className="flex justify-between items-center mb-6">
+        <Title level={2}>合同续签管理</Title>
         <Button 
         <Button 
           type="primary" 
           type="primary" 
           icon={<PlusOutlined />} 
           icon={<PlusOutlined />} 
           onClick={() => showModal()}
           onClick={() => showModal()}
         >
         >
-          添加续签记录
+          新增续签记录
         </Button>
         </Button>
       </div>
       </div>
-      
-      <div className="mb-4">
-        <Input
-          placeholder="搜索合同ID或续签状态"
-          prefix={<SearchOutlined />}
-          value={searchText}
-          onChange={(e) => setSearchText(e.target.value)}
-          onPressEnter={handleSearch}
-          style={{ width: 300 }}
+
+      <Card className="mb-6">
+        <Form
+          form={searchForm}
+          layout="inline"
+          onFinish={handleSearch}
+          className="mb-4"
+        >
+          <Form.Item name="contractId" label="合同">
+            <Select placeholder="选择合同" style={{ width: 200 }}>
+              {contracts.map(contract => (
+                <Option key={contract.id} value={contract.id}>
+                  {contract.contractNo} - {contract.customer?.name}
+                </Option>
+              ))}
+            </Select>
+          </Form.Item>
+          
+          <Form.Item name="status" label="状态">
+            <Select placeholder="选择状态" style={{ width: 150 }}>
+              {Object.entries(RenewStatusEnum).map(([value, { label, color }]) => (
+                <Option key={value} value={Number(value)}>
+                  <Tag color={color} style={{ marginRight: 4 }} />
+                  {label}
+                </Option>
+              ))}
+            </Select>
+          </Form.Item>
+          
+          <Form.Item name="dateRange" label="续签日期">
+            <RangePicker 
+              format="YYYY-MM-DD" 
+              style={{ width: 300 }}
+              placeholder={['开始日期', '结束日期']}
+            />
+          </Form.Item>
+          
+          <Form.Item>
+            <Space>
+              <Button type="primary" htmlType="submit" icon={<SearchOutlined />}>
+                搜索
+              </Button>
+              <Button onClick={handleReset} icon={<ReloadOutlined />}>
+                重置
+              </Button>
+            </Space>
+          </Form.Item>
+        </Form>
+      </Card>
+
+      <Card>
+        <Table<ContractRenewItem>
+          columns={columns}
+          rowKey="id"
+          loading={loading}
+          dataSource={fetchRenews.data?.data || []}
+          pagination={{
+            current: currentPage,
+            pageSize: pageSize,
+            total: total,
+            showSizeChanger: true,
+            showQuickJumper: true,
+            showTotal: (total) => `共 ${total} 条记录`,
+            pageSizeOptions: ['10', '20', '50', '100'],
+          }}
+          onChange={handleTableChange}
+          scroll={{ x: 'max-content' }}
         />
         />
-        <Button type="default" onClick={handleSearch} style={{ marginLeft: 8 }}>
-          搜索
-        </Button>
-      </div>
-      
-      <Table
-        columns={columns}
-        dataSource={dataSource}
-        rowKey="id"
-        loading={loading}
-        pagination={pagination}
-        onChange={handleTableChange}
-        bordered
-      />
-      
+      </Card>
+
+      {/* 新增/编辑模态框 */}
       <Modal
       <Modal
-        title={editingKey ? "编辑合同续签记录" : "添加合同续签记录"}
-        open={modalVisible}
+        title={currentRecord ? '编辑续签记录' : '新增续签记录'}
+        open={isModalVisible}
         onCancel={handleCancel}
         onCancel={handleCancel}
         footer={[
         footer={[
-          <Button key="cancel" onClick={handleCancel}>
+          <Button key="cancel" onClick={handleCancel} icon={<CloseOutlined />}>
             取消
             取消
           </Button>,
           </Button>,
-          <Button key="submit" type="primary" onClick={handleSubmit}>
-            确定
+          <Button key="submit" type="primary" htmlType="submit" form="renewForm" icon={<SaveOutlined />}>
+            保存
           </Button>,
           </Button>,
         ]}
         ]}
+        destroyOnClose
+        centered
         width={700}
         width={700}
       >
       >
-        <Form form={form} layout="vertical">
-          {!editingKey && (
-            <Form.Item
-              name="id"
-              label="续签记录ID"
-              rules={[{ required: true, message: '请输入续签记录ID' }]}
-            >
-              <Input placeholder="请输入续签记录ID" />
-            </Form.Item>
-          )}
-          
+        <Divider orientation="left">续签信息</Divider>
+        <Form
+          id="renewForm"
+          form={form}
+          layout="vertical"
+          onFinish={handleSubmit}
+          initialValues={{ status: 0 }}
+        >
           <Form.Item
           <Form.Item
             name="contractId"
             name="contractId"
-            label="原合同"
-            rules={[{ required: true, message: '请选择原合同' }]}
+            label="关联合同"
+            rules={[{ required: true, message: '请选择关联合同' }]}
           >
           >
-            <Select placeholder="请选择原合同">
+            <Select placeholder="选择合同" style={{ width: '100%' }}>
               {contracts.map(contract => (
               {contracts.map(contract => (
-                <Select.Option key={contract.id} value={contract.id}>
-                  {`${contract.id} - ${contract.contractNumber} (${contract.clientId})`}
-                </Select.Option>
+                <Option key={contract.id} value={contract.id}>
+                  {contract.contractNo} - {contract.customer?.name}
+                </Option>
               ))}
               ))}
             </Select>
             </Select>
           </Form.Item>
           </Form.Item>
           
           
-          <div className="grid grid-cols-2 gap-4">
-            <Form.Item
-              name="amount"
-              label="续签金额"
-            >
-              <Input placeholder="请输入续签金额" />
-            </Form.Item>
-            
-            <Form.Item
-              name="revenue"
-              label="续签收入"
-            >
-              <Input placeholder="请输入续签收入" />
-            </Form.Item>
-          </div>
-          
-          <div className="grid grid-cols-2 gap-4">
-            <Form.Item
-              name="endDate"
-              label="续签结束日期"
-            >
-              <DatePicker format="YYYY-MM-DD" />
-            </Form.Item>
-            
-            <Form.Item
-              name="state"
-              label="续签状态"
-            >
-              <Input placeholder="请输入续签状态:如待审批、已生效等" />
-            </Form.Item>
-          </div>
+          <Form.Item
+            name="renewNo"
+            label="续签编号"
+            rules={[{ required: true, message: '请输入续签编号' }]}
+          >
+            <Input placeholder="请输入续签编号" disabled={!!currentRecord} />
+          </Form.Item>
           
           
           <div className="grid grid-cols-2 gap-4">
           <div className="grid grid-cols-2 gap-4">
             <Form.Item
             <Form.Item
-              name="auditStatus"
-              label="审批情况"
+              name="renewStartDate"
+              label="续签开始日期"
+              rules={[{ required: true, message: '请选择续签开始日期' }]}
             >
             >
-              <Input placeholder="请输入审批情况" />
+              <DatePicker 
+                format="YYYY-MM-DD" 
+                style={{ width: '100%' }} 
+                placeholder="请选择开始日期"
+              />
             </Form.Item>
             </Form.Item>
             
             
             <Form.Item
             <Form.Item
-              name="userId"
-              label="处理用户ID"
+              name="renewEndDate"
+              label="续签结束日期"
+              rules={[{ required: true, message: '请选择续签结束日期' }]}
             >
             >
-              <Input placeholder="请输入处理用户ID" />
+              <DatePicker 
+                format="YYYY-MM-DD" 
+                style={{ width: '100%' }} 
+                placeholder="请选择结束日期"
+              />
             </Form.Item>
             </Form.Item>
           </div>
           </div>
           
           
           <Form.Item
           <Form.Item
-            name="content"
-            label="续签内容描述"
-          >
-            <Input.TextArea rows={4} placeholder="请输入续签内容描述" />
-          </Form.Item>
-          
-          <Form.Item
-            name="auditReasons"
-            label="审批原因"
+            name="renewAmount"
+            label="续签金额"
+            rules={[
+              { required: true, message: '请输入续签金额' },
+              { type: 'number', min: 0, message: '金额必须大于等于0' }
+            ]}
           >
           >
-            <Input.TextArea rows={2} placeholder="请输入审批原因" />
+            <Input 
+              type="number" 
+              placeholder="请输入续签金额" 
+              addonBefore="¥" 
+              precision={2}
+            />
           </Form.Item>
           </Form.Item>
           
           
-          {!editingKey && (
-            <Form.Item
-              name="createdTime"
-              label="记录创建时间"
-              rules={[{ required: true, message: '请选择记录创建时间' }]}
-            >
-              <DatePicker showTime format="YYYY-MM-DD HH:mm:ss" />
-            </Form.Item>
-          )}
-        </Form>
-      </Modal>
-    </div>
-            </Form.Item>
-          </div>
-          
           <Form.Item
           <Form.Item
-            name="content"
-            label="续签内容描述"
+            name="status"
+            label="状态"
+            rules={[{ required: true, message: '请选择状态' }]}
           >
           >
-            <Input.TextArea rows={4} placeholder="请输入续签内容描述" />
+            <Select placeholder="选择状态" style={{ width: '100%' }}>
+              {Object.entries(RenewStatusEnum).map(([value, { label, color }]) => (
+                <Option key={value} value={Number(value)}>
+                  <Tag color={color} style={{ marginRight: 4 }} />
+                  {label}
+                </Option>
+              ))}
+            </Select>
           </Form.Item>
           </Form.Item>
           
           
           <Form.Item
           <Form.Item
-            name="auditReasons"
-            label="审批原因"
+            name="remark"
+            label="备注"
           >
           >
-            <Input.TextArea rows={2} placeholder="请输入审批原因" />
+            <Input.TextArea rows={4} placeholder="请输入备注信息" />
           </Form.Item>
           </Form.Item>
-          
-          {!editingKey && (
-            <Form.Item
-              name="createdTime"
-              label="记录创建时间"
-              rules={[{ required: true, message: '请选择记录创建时间' }]}
-            >
-              <DatePicker showTime format="YYYY-MM-DD HH:mm:ss" />
-            </Form.Item>
-          )}
         </Form>
         </Form>
       </Modal>
       </Modal>
     </div>
     </div>