Bläddra i källkod

feat: 页面优化

BaiLuoYan 1 dag sedan
förälder
incheckning
6d4b88d51d

+ 34 - 18
src/pages/Admin/Dept/components/UserTable.tsx

@@ -2,29 +2,35 @@ import { MEMBER_TYPE_COLORS, MEMBER_TYPE_LABELS, STATUS_ENABLED } from '@/define
 import { BindRolesDrawer } from '@/pages/Admin/_shared/BindRolesDrawer';
 import { UserPermDrawer } from '@/pages/Admin/_shared/UserPermDrawer';
 import { ProductRolesBase, useUserProductRoles } from '@/pages/Admin/_shared/useUserProductRoles';
-import { fetchUpdateUser } from '@/services/user';
+import { fetchUpdateUser, fetchUserList } from '@/services/user';
 import { StopOutlined } from '@ant-design/icons';
-import { DrawerForm, ProColumns, ProFormSelect, ProTable } from '@ant-design/pro-components';
-import { Button, message, Popconfirm, Spin, Tag } from 'antd';
-import { useMemo, useState } from 'react';
+import {
+  ActionType,
+  DrawerForm,
+  ProColumns,
+  ProFormSelect,
+  ProTable,
+} from '@ant-design/pro-components';
+import { Button, message, Popconfirm, Tag } from 'antd';
+import { useMemo, useRef, useState } from 'react';
 
 interface DeptUserTableProps {
-  users: API.UserItem[];
   productRolesBase: ProductRolesBase;
   deptId: number;
+  deptIds: number[];
   deptName: string;
-  noDeptUsers: API.UserItem[];
   onMemberChange: () => void;
 }
 
 export const DeptUserTable = ({
-  users,
   productRolesBase,
   deptId,
+  deptIds,
   deptName,
-  noDeptUsers,
   onMemberChange,
 }: DeptUserTableProps) => {
+  const actionRef = useRef<ActionType>();
+  const [pageUsers, setPageUsers] = useState<API.UserItem[]>([]);
   const [rolesDrawer, setRolesDrawer] = useState<{ open: boolean; userId: number }>({
     open: false,
     userId: 0,
@@ -35,14 +41,9 @@ export const DeptUserTable = ({
   });
   const [refreshKey, setRefreshKey] = useState(0);
 
-  const userIds = useMemo(() => users.map((u) => u.id), [users]);
+  const userIds = useMemo(() => pageUsers.map((u) => u.id), [pageUsers]);
   const { userProductInfo } = useUserProductRoles(userIds, productRolesBase, refreshKey);
 
-  const userOptions = useMemo(
-    () => noDeptUsers.map((u) => ({ label: `${u.username}(${u.nickname})`, value: u.id })),
-    [noDeptUsers],
-  );
-
   const columns: ProColumns<API.UserItem>[] = [
     { title: '用户名', dataIndex: 'username', width: 200 },
     { title: '昵称', dataIndex: 'nickname', width: 200 },
@@ -105,6 +106,7 @@ export const DeptUserTable = ({
               const res = await fetchUpdateUser({ id: r.id, deptId: 0 });
               if (!res.success) return;
               message.success('已移出');
+              actionRef.current?.reload();
               onMemberChange();
             }}
           >
@@ -115,14 +117,26 @@ export const DeptUserTable = ({
     },
   ];
 
+  const noDeptUserOptions = async ({ keyWords }: { keyWords?: string }) => {
+    const res = await fetchUserList({ deptIds: [0], username: keyWords ?? '', pageSize: 50 });
+    return (res.data ?? []).map((u: API.UserItem) => ({
+      label: `${u.username}(${u.nickname})`,
+      value: u.id,
+    }));
+  };
+
   return (
-    <Spin spinning={productRolesBase.loading}>
+    <>
       <ProTable<API.UserItem>
+        actionRef={actionRef}
         columns={columns}
-        dataSource={users}
         rowKey="id"
         search={false}
         options={false}
+        request={async (params, sorter, filter) =>
+          fetchUserList({ ...params, deptIds }, sorter, filter)
+        }
+        onDataSourceChange={setPageUsers}
         pagination={{
           defaultPageSize: 20,
           pageSizeOptions: [10, 20, 50, 100],
@@ -140,6 +154,7 @@ export const DeptUserTable = ({
               const res = await fetchUpdateUser({ id: values.userId, deptId });
               if (!res.success) return false;
               message.success('添加成功');
+              actionRef.current?.reload();
               onMemberChange();
               return true;
             }}
@@ -148,8 +163,9 @@ export const DeptUserTable = ({
             <ProFormSelect
               name="userId"
               label="选择用户"
-              options={userOptions}
               showSearch
+              debounceTime={300}
+              request={noDeptUserOptions}
               rules={[{ required: true, message: '请选择用户' }]}
               placeholder="仅显示未分配部门的用户"
               fieldProps={{ id: 'dept-member-select' }}
@@ -166,6 +182,6 @@ export const DeptUserTable = ({
         {...permDrawer}
         onClose={() => setPermDrawer((p) => ({ ...p, open: false }))}
       />
-    </Spin>
+    </>
   );
 };

+ 2 - 19
src/pages/Admin/Dept/hooks/useDeptPage.ts

@@ -1,25 +1,19 @@
 import { useProductRolesBase } from '@/pages/Admin/_shared/useUserProductRoles';
 import { fetchDeptTree } from '@/services/dept';
-import { fetchUserList } from '@/services/user';
 import { useEffect, useMemo, useState } from 'react';
 import { collectDeptIds, findDeptNode } from '../lib/deptUtils';
 
 export const useDeptPage = () => {
   const [loading, setLoading] = useState(false);
   const [treeData, setTreeData] = useState<API.DeptItem[]>([]);
-  const [allUsers, setAllUsers] = useState<API.UserItem[]>([]);
   const [selectedDeptId, setSelectedDeptId] = useState<number | undefined>();
   const productRolesBase = useProductRolesBase();
 
   const loadData = async () => {
     setLoading(true);
     try {
-      const [treeRes, userRes] = await Promise.all([
-        fetchDeptTree(),
-        fetchUserList({ pageSize: 9999 }),
-      ]);
+      const treeRes = await fetchDeptTree();
       setTreeData(treeRes.data ?? []);
-      setAllUsers(userRes.data ?? []);
     } finally {
       setLoading(false);
     }
@@ -36,18 +30,9 @@ export const useDeptPage = () => {
 
   const selectedDeptIds = useMemo(() => {
     if (!selectedDeptNode) return undefined;
-    return new Set(collectDeptIds(selectedDeptNode));
+    return collectDeptIds(selectedDeptNode);
   }, [selectedDeptNode]);
 
-  const filteredUsers = useMemo(() => {
-    if (!selectedDeptIds) return [];
-    return allUsers.filter((u) => selectedDeptIds.has(u.deptId));
-  }, [allUsers, selectedDeptIds]);
-
-  const noDeptUsers = useMemo(() => {
-    return allUsers.filter((u) => !u.deptId || u.deptId === 0);
-  }, [allUsers]);
-
   return {
     loading,
     treeData,
@@ -55,8 +40,6 @@ export const useDeptPage = () => {
     setSelectedDeptId,
     selectedDeptIds,
     selectedDeptName: selectedDeptNode?.name,
-    filteredUsers,
-    noDeptUsers,
     loadData,
     productRolesBase,
   };

+ 1 - 4
src/pages/Admin/Dept/index.tsx

@@ -17,8 +17,6 @@ export default function DeptPage() {
     setSelectedDeptId,
     selectedDeptIds,
     selectedDeptName,
-    filteredUsers,
-    noDeptUsers,
     loadData,
     productRolesBase,
   } = useDeptPage();
@@ -105,11 +103,10 @@ export default function DeptPage() {
           <div className="flex-1 min-w-0">
             {selectedDeptIds ? (
               <DeptUserTable
-                users={filteredUsers}
                 productRolesBase={productRolesBase}
                 deptId={selectedDeptId!}
+                deptIds={selectedDeptIds}
                 deptName={selectedDeptName ?? ''}
-                noDeptUsers={noDeptUsers}
                 onMemberChange={loadData}
               />
             ) : (

+ 1 - 1
src/services/user/typings.d.ts

@@ -55,7 +55,7 @@ declare namespace API {
     username?: string;
     nickname?: string;
     status?: number;
-    deptId?: number;
+    deptIds?: number[];
     page?: number;
     pageSize?: number;
   }