From 71719ffa0eeb4a28a1b736f87499bcda2847a848 Mon Sep 17 00:00:00 2001
From: wsj <593216709@qq.com>
Date: Wed, 28 Oct 2026 23:04:10 +0800
Subject: [PATCH] feat: claude 修改

---
 src/pages/system/users/index.tsx |  241 +++++++----------------------------------------
 1 files changed, 37 insertions(+), 204 deletions(-)

diff --git a/src/pages/system/users/index.tsx b/src/pages/system/users/index.tsx
index 15711c8..e0e616a 100644
--- a/src/pages/system/users/index.tsx
+++ b/src/pages/system/users/index.tsx
@@ -7,35 +7,20 @@
 } from '@ant-design/icons';
 import { ProTable } from '@ant-design/pro-components';
 import type { ActionType } from '@ant-design/pro-components';
-import {
-  App as AntdApp,
-  Button,
-  Descriptions,
-  Drawer,
-  Form,
-  Input,
-  InputNumber,
-  Modal,
-  Select,
-  Space,
-  Tag,
-  Upload,
-} from 'antd';
+import { App as AntdApp, Button, Modal, Upload } from 'antd';
 import type { UploadFile } from 'antd';
-import { createUserColumns, getEmployeeStatusMeta } from './columns';
+import { createUserColumns } from './columns';
+import UserFormDrawer from './components/UserFormDrawer';
+import type { UserFormMode } from './components/UserFormDrawer';
 import {
-  createEmployee,
   deleteEmployee,
   exportEmployees,
-  getEmployeeDetail,
   getEmployeeList,
   getOrgTree,
   getRoleOptions,
   importEmployees,
-  updateEmployee,
-} from './server';
+} from './service';
 import type {
-  EmployeeFormValues,
   EmployeeListQuery,
   EmployeeVO,
   OrgTreeNode,
@@ -54,15 +39,11 @@
   const actionRef = useRef<ActionType>();
   const lastQueryRef = useRef<TenantEmployeeListRequest>({});
   const { message, modal } = AntdApp.useApp();
-  const [form] = Form.useForm<EmployeeFormValues>();
-  const [orgOptions, setOrgOptions] = useState<SelectOption[]>([]);
+  const [orgTree, setOrgTree] = useState<OrgTreeNode[]>([]);
   const [roleOptions, setRoleOptions] = useState<SelectOption[]>([]);
   const [formOpen, setFormOpen] = useState(false);
-  const [editing, setEditing] = useState<EmployeeVO | null>(null);
-  const [submitting, setSubmitting] = useState(false);
-  const [detail, setDetail] = useState<EmployeeVO | null>(null);
-  const [detailOpen, setDetailOpen] = useState(false);
-  const [detailLoading, setDetailLoading] = useState(false);
+  const [formMode, setFormMode] = useState<UserFormMode>('create');
+  const [activeEmployee, setActiveEmployee] = useState<EmployeeVO | null>(null);
   const [importOpen, setImportOpen] = useState(false);
   const [importFileList, setImportFileList] = useState<UploadFile[]>([]);
   const [importing, setImporting] = useState(false);
@@ -76,7 +57,7 @@
         const [orgs, roles] = await Promise.all([getOrgTree(), getRoleOptions()]);
         if (!active) return;
 
-        setOrgOptions(flattenOrgOptions(orgs));
+        setOrgTree(orgs);
         setRoleOptions(roles.map((role) => ({ label: role.roleName, value: role.id })));
       } catch {
         // 错误已由 request 统一提示
@@ -90,6 +71,8 @@
     };
   }, []);
 
+  const orgOptions = useMemo(() => flattenOrgOptions(orgTree), [orgTree]);
+
   const orgNameMap = useMemo(
     () => new Map(orgOptions.map((option) => [option.value, option.label])),
     [orgOptions],
@@ -101,48 +84,31 @@
   );
 
   const openCreate = useCallback(() => {
-    setEditing(null);
-    form.resetFields();
+    setActiveEmployee(null);
+    setFormMode('create');
     setFormOpen(true);
-  }, [form]);
+  }, []);
 
   const closeForm = useCallback(() => {
     setFormOpen(false);
-    setEditing(null);
+    setActiveEmployee(null);
   }, []);
 
-  const openEdit = useCallback(
-    (record: EmployeeVO) => {
-      setEditing(record);
-      form.setFieldsValue({
-        name: record.name,
-        phone: record.phone,
-        orgId: record.orgId,
-        roleId: record.roleId,
-        position: record.position,
-        email: record.email,
-        holdLimit: record.holdLimit,
-        region: record.region,
-      });
-      setFormOpen(true);
-    },
-    [form],
-  );
+  const handleFormSuccess = useCallback(() => {
+    closeForm();
+    actionRef.current?.reload();
+  }, [closeForm]);
 
-  const handleDetail = useCallback(async (record: EmployeeVO) => {
-    setDetail(null);
-    setDetailOpen(true);
-    setDetailLoading(true);
+  const openEdit = useCallback((record: EmployeeVO) => {
+    setActiveEmployee(record);
+    setFormMode('edit');
+    setFormOpen(true);
+  }, []);
 
-    try {
-      const data = await getEmployeeDetail({ id: record.id });
-      setDetail(data);
-    } catch {
-      // 错误已由 request 统一提示
-      setDetailOpen(false);
-    } finally {
-      setDetailLoading(false);
-    }
+  const openDetail = useCallback((record: EmployeeVO) => {
+    setActiveEmployee(record);
+    setFormMode('detail');
+    setFormOpen(true);
   }, []);
 
   const handleDelete = useCallback(
@@ -162,35 +128,6 @@
     },
     [message, modal],
   );
-
-  const handleSubmit = useCallback(async () => {
-    let values: EmployeeFormValues;
-    try {
-      values = await form.validateFields();
-    } catch {
-      return;
-    }
-
-    setSubmitting(true);
-    try {
-      if (editing) {
-        await updateEmployee({ id: editing.id, ...values });
-        message.success('员工信息已更新');
-      } else {
-        await createEmployee(values);
-        message.success('员工创建成功');
-      }
-
-      setFormOpen(false);
-      setEditing(null);
-      form.resetFields();
-      actionRef.current?.reload();
-    } catch {
-      // 错误已由 request 统一提示
-    } finally {
-      setSubmitting(false);
-    }
-  }, [editing, form, message]);
 
   const handleExport = useCallback(async () => {
     setExporting(true);
@@ -240,11 +177,11 @@
         roleOptions,
         orgNameMap,
         roleNameMap,
-        onDetail: handleDetail,
+        onDetail: openDetail,
         onEdit: openEdit,
         onDelete: handleDelete,
       }),
-    [orgOptions, roleOptions, orgNameMap, roleNameMap, handleDetail, openEdit, handleDelete],
+    [orgOptions, roleOptions, orgNameMap, roleNameMap, openDetail, openEdit, handleDelete],
   );
 
   return (
@@ -253,7 +190,6 @@
         rowKey="id"
         actionRef={actionRef}
         columns={columns}
-        cardProps={{ className: 'table-card' }}
         search={{ labelWidth: 'auto', defaultCollapsed: false }}
         scroll={{ x: 1290 }}
         options={false}
@@ -307,118 +243,15 @@
         }}
       />
 
-      <Drawer
-        title={editing ? '编辑员工' : '新增员工'}
-        width={420}
+      <UserFormDrawer
         open={formOpen}
-        forceRender
+        mode={formMode}
+        record={activeEmployee}
+        orgTree={orgTree}
+        roleOptions={roleOptions}
         onClose={closeForm}
-        footer={
-          <Space style={{ display: 'flex', justifyContent: 'flex-end' }}>
-            <Button onClick={closeForm}>取消</Button>
-            <Button type="primary" loading={submitting} onClick={handleSubmit}>
-              {editing ? '保存' : '创建'}
-            </Button>
-          </Space>
-        }
-      >
-        <Form form={form} layout="vertical" preserve={false}>
-          <Form.Item
-            name="name"
-            label="姓名"
-            rules={[{ required: true, message: '请输入姓名' }]}
-          >
-            <Input placeholder="请输入员工姓名" />
-          </Form.Item>
-          <Form.Item
-            name="phone"
-            label="手机号"
-            rules={[
-              { required: true, message: '请输入手机号' },
-              { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号' },
-            ]}
-          >
-            <Input placeholder="请输入手机号" maxLength={11} />
-          </Form.Item>
-          <Form.Item
-            name="orgId"
-            label="所属组织"
-            rules={[{ required: true, message: '请选择所属组织' }]}
-          >
-            <Select
-              showSearch
-              optionFilterProp="label"
-              options={orgOptions}
-              placeholder="请选择所属组织"
-            />
-          </Form.Item>
-          <Form.Item
-            name="roleId"
-            label="角色"
-            rules={[{ required: true, message: '请选择角色' }]}
-          >
-            <Select
-              showSearch
-              optionFilterProp="label"
-              options={roleOptions}
-              placeholder="请选择角色"
-            />
-          </Form.Item>
-          <Form.Item name="position" label="职位">
-            <Input placeholder="请输入职位" />
-          </Form.Item>
-          <Form.Item name="region" label="负责区域">
-            <Input placeholder="请输入负责区域" />
-          </Form.Item>
-          <Form.Item name="holdLimit" label="客户持有上限">
-            <InputNumber min={0} precision={0} style={{ width: '100%' }} />
-          </Form.Item>
-          <Form.Item
-            name="email"
-            label="邮箱"
-            rules={[{ type: 'email', message: '请输入正确的邮箱' }]}
-          >
-            <Input placeholder="请输入邮箱" />
-          </Form.Item>
-        </Form>
-      </Drawer>
-
-      <Drawer
-        title="员工详情"
-        width={480}
-        open={detailOpen}
-        loading={detailLoading}
-        onClose={() => {
-          setDetailOpen(false);
-          setDetail(null);
-        }}
-      >
-        {detail && (
-          <Descriptions column={1} bordered size="small">
-            <Descriptions.Item label="姓名">{detail.name}</Descriptions.Item>
-            <Descriptions.Item label="手机号">{detail.phone}</Descriptions.Item>
-            <Descriptions.Item label="所属组织">
-              {orgNameMap.get(detail.orgId) ?? `#${detail.orgId}`}
-            </Descriptions.Item>
-            <Descriptions.Item label="角色">
-              {roleNameMap.get(detail.roleId) ?? `#${detail.roleId}`}
-            </Descriptions.Item>
-            <Descriptions.Item label="职位">{detail.position || '-'}</Descriptions.Item>
-            <Descriptions.Item label="邮箱">{detail.email || '-'}</Descriptions.Item>
-            <Descriptions.Item label="负责区域">{detail.region || '-'}</Descriptions.Item>
-            <Descriptions.Item label="客户持有上限">
-              {detail.holdLimit ?? '-'}
-            </Descriptions.Item>
-            <Descriptions.Item label="状态">
-              <Tag color={getEmployeeStatusMeta(detail.status).color} bordered={false}>
-                {getEmployeeStatusMeta(detail.status).text}
-              </Tag>
-            </Descriptions.Item>
-            <Descriptions.Item label="入职日期">{detail.hireDate || '-'}</Descriptions.Item>
-            <Descriptions.Item label="创建时间">{detail.createdAt || '-'}</Descriptions.Item>
-          </Descriptions>
-        )}
-      </Drawer>
+        onSuccess={handleFormSuccess}
+      />
 
       <Modal
         title="导入员工"

--
Gitblit v1.9.3