Przeglądaj źródła

部门树形结构单个加新增按钮

pm 5 miesięcy temu
rodzic
commit
62d8c39a29

+ 49 - 11
src/components/DepartmentManagement.tsx

@@ -26,6 +26,7 @@ export default function DepartmentManagement() {
     status: undefined as number | undefined,
   });
   const [isExpandAll, setIsExpandAll] = useState(true);
+  const [expandedIds, setExpandedIds] = useState<number[]>([]);
   const [refreshTable, setRefreshTable] = useState(true);
   const [userList, setUserList] = useState<UserVO[]>([]);
   const [statusOptions] = useState(() => {
@@ -47,6 +48,9 @@ export default function DepartmentManagement() {
       const validDeptList = (data || []).filter((dept): dept is DeptVO & { id: number } => !!dept.id);
       const treeData = handleTree(validDeptList);
       setList(treeData);
+      // 默认展开所有节点
+      const allIds = getAllNodeIds(treeData);
+      setExpandedIds(allIds);
     } catch (error: any) {
       console.error('获取部门列表失败:', error);
       toast.error(error.message || '获取部门列表失败');
@@ -56,13 +60,35 @@ export default function DepartmentManagement() {
     }
   };
 
+  // 收集所有节点ID
+  const getAllNodeIds = (nodes: TreeNode[]): number[] => {
+    let ids: number[] = [];
+    nodes.forEach(node => {
+      ids.push(node.id);
+      if (node.children && node.children.length > 0) {
+        ids = ids.concat(getAllNodeIds(node.children));
+      }
+    });
+    return ids;
+  };
+
   // 展开/折叠操作
   const toggleExpandAll = () => {
-    setRefreshTable(false);
+    if (isExpandAll) {
+      // 当前是展开状态,点击后折叠所有
+      setExpandedIds([]);
+    } else {
+      // 当前是折叠状态,点击后展开所有
+      setExpandedIds(getAllNodeIds(list));
+    }
     setIsExpandAll(!isExpandAll);
-    setTimeout(() => {
-      setRefreshTable(true);
-    }, 0);
+  };
+
+  // 切换单个节点的展开/折叠状态
+  const toggleNode = (nodeId: number) => {
+    setExpandedIds(prev =>
+      prev.includes(nodeId) ? prev.filter(id => id !== nodeId) : [...prev, nodeId]
+    );
   };
 
   // 搜索按钮操作
@@ -87,6 +113,9 @@ export default function DepartmentManagement() {
         const validDeptList = (data || []).filter((dept): dept is DeptVO & { id: number } => !!dept.id);
         const treeData = handleTree(validDeptList);
         setList(treeData);
+        // 默认展开所有节点
+        const allIds = getAllNodeIds(treeData);
+        setExpandedIds(allIds);
       })
       .catch((error: any) => {
         console.error('获取部门列表失败:', error);
@@ -99,8 +128,8 @@ export default function DepartmentManagement() {
   };
 
   // 添加/修改操作
-  const openForm = (type: string, id?: number) => {
-    formRef.current?.open(type, id);
+  const openForm = (type: string, id?: number, parentId?: number) => {
+    formRef.current?.open(type, id, parentId);
   };
 
   // 删除按钮操作
@@ -140,7 +169,7 @@ export default function DepartmentManagement() {
   const renderTableRows = (nodes: TreeNode[], level: number = 0): React.ReactNode[] => {
     return nodes.map((node) => {
       const hasChildren = node.children && node.children.length > 0;
-      const isExpanded = isExpandAll; // 简化处理,实际可以根据状态控制
+      const isExpanded = expandedIds.includes(node.id);
 
       return (
         <React.Fragment key={node.id}>
@@ -149,9 +178,7 @@ export default function DepartmentManagement() {
               <div className="flex items-center gap-2">
                 {hasChildren ? (
                   <button
-                    onClick={() => {
-                      // 这里可以实现单个节点的展开/折叠
-                    }}
+                    onClick={() => toggleNode(node.id)}
                     className="p-0.5 hover:bg-gray-200 rounded transition-colors"
                   >
                     {isExpanded ? (
@@ -189,6 +216,17 @@ export default function DepartmentManagement() {
                     <span className="ml-1">编辑</span>
                   </Button>
                 </PermissionWrapper>
+                <PermissionWrapper permission="system:dept:create">
+                  <Button
+                    variant="ghost"
+                    size="sm"
+                    onClick={() => openForm('create', undefined, node.id)}
+                    className="h-8 px-2 text-green-600 hover:text-green-700"
+                  >
+                    <Plus className="w-4 h-4" />
+                    <span className="ml-1">新增</span>
+                  </Button>
+                </PermissionWrapper>
                 <PermissionWrapper permission="system:dept:delete">
                   <Button
                     variant="ghost"
@@ -308,7 +346,7 @@ export default function DepartmentManagement() {
                 <TableHead className="w-[80px] text-center">排序</TableHead>
                 <TableHead className="w-[100px] text-center">状态</TableHead>
                 <TableHead className="w-[180px]">创建时间</TableHead>
-                <TableHead className="w-[160px] text-center">操作</TableHead>
+                <TableHead className="w-[220px] text-center">操作</TableHead>
               </TableRow>
             </TableHeader>
             <TableBody>

+ 4 - 3
src/components/dept/DeptForm.tsx

@@ -14,7 +14,7 @@ interface DeptFormProps {
 }
 
 export interface DeptFormRef {
-  open: (type: string, id?: number) => void;
+  open: (type: string, id?: number, parentId?: number) => void;
 }
 
 const DeptForm = forwardRef<DeptFormRef, DeptFormProps>(({ onSuccess }, ref) => {
@@ -30,7 +30,7 @@ const DeptForm = forwardRef<DeptFormRef, DeptFormProps>(({ onSuccess }, ref) =>
   const [statusOptions, setStatusOptions] = useState(getIntDictOptions(DICT_TYPE.COMMON_STATUS));
 
   // 打开弹窗
-  const open = async (type: string, id?: number) => {
+  const open = async (type: string, id?: number, parentId?: number) => {
     setDialogVisible(true);
     setDialogTitle(type === 'create' ? '新增部门' : '编辑部门');
     setFormType(type as 'create' | 'update');
@@ -78,9 +78,10 @@ const DeptForm = forwardRef<DeptFormRef, DeptFormProps>(({ onSuccess }, ref) =>
         setFormLoading(false);
       }
     } else {
+      // 新增时,设置默认父级部门
       form.setFieldsValue({
         name: '',
-        parentId: 0,
+        parentId: parentId ?? 0,
         sort: 0,
         leaderUserId: undefined,
         phone: '',