From 4baf9d271b82d5972da68624bd31d34f2634361a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=9A=E8=BE=B0=E5=85=88=E7=94=9F?= Date: Sun, 1 Dec 2024 17:42:19 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=AF=E6=AD=A3=E5=B8=B8=E5=90=AF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/System/Department/index.tsx | 171 ++++++++++-------- .../src/pages/System/Department/service.ts | 4 +- frontend/src/pages/System/Menu/index.tsx | 11 +- frontend/src/pages/System/User/index.tsx | 28 ++- 4 files changed, 126 insertions(+), 88 deletions(-) diff --git a/frontend/src/pages/System/Department/index.tsx b/frontend/src/pages/System/Department/index.tsx index 06d27b2b..e0bf8742 100644 --- a/frontend/src/pages/System/Department/index.tsx +++ b/frontend/src/pages/System/Department/index.tsx @@ -1,41 +1,55 @@ import React, { useState, useEffect } from 'react'; -import { Table, Button, Modal, Form, Input, Space, InputNumber, Switch, TreeSelect, Select } from 'antd'; +import { Table, Button, Modal, Form, Input, Space, InputNumber, Switch, TreeSelect, Select, message } from 'antd'; import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons'; import type { DepartmentResponse } from './types'; -import { useTableData } from '@/hooks/useTableData'; -import type { FixedType } from 'rc-table/lib/interface'; import { getDepartmentTree } from './service'; import type { UserResponse } from '@/pages/System/User/types'; import { getUsers } from './service'; +import request from '@/utils/request'; +import type { FixedType } from 'rc-table/lib/interface'; + +interface TreeSelectNode { + title: string; + value: number; + disabled?: boolean; + children?: TreeSelectNode[]; +} const DepartmentPage: React.FC = () => { - const { - list: departments, - pagination, - loading, - loadData: fetchDepartments, - handleCreate, - handleUpdate, - handleDelete - } = useTableData({ - service: { - baseUrl: '/api/v1/department' - }, - defaultParams: { - sortField: 'createTime', - sortOrder: 'descend' - } - }); - - const [modalVisible, setModalVisible] = useState(false); - const [editingDepartment, setEditingDepartment] = useState(null); + const [loading, setLoading] = useState(false); const [departmentTree, setDepartmentTree] = useState([]); const [users, setUsers] = useState([]); + const [modalVisible, setModalVisible] = useState(false); + const [editingDepartment, setEditingDepartment] = useState(null); const [form] = Form.useForm(); + // 加载部门树数据 + const loadDepartmentTree = async () => { + setLoading(true); + try { + const response = await getDepartmentTree(); + setDepartmentTree(response || []); + } catch (error) { + message.error('加载部门数据失败'); + } finally { + setLoading(false); + } + }; + + // 获取扁平化的部门列表 + const getFlatDepartments = (departments: DepartmentResponse[]): DepartmentResponse[] => { + return departments.reduce((acc, dept) => { + acc.push(dept); + if (dept.children?.length) { + acc.push(...getFlatDepartments(dept.children)); + } + return acc; + }, [] as DepartmentResponse[]); + }; + useEffect(() => { Promise.all([ - getDepartmentTree().then(setDepartmentTree), + loadDepartmentTree(), getUsers().then(setUsers) ]); }, []); @@ -43,8 +57,10 @@ const DepartmentPage: React.FC = () => { const handleAdd = () => { setEditingDepartment(null); form.resetFields(); - // 获取当前最大排序值 - const maxSort = Math.max(0, ...departments.map(dept => dept.sort)); + + const allDepartments = getFlatDepartments(departmentTree); + const maxSort = Math.max(0, ...allDepartments.map(dept => dept.sort)); + form.setFieldsValue({ enabled: true, sort: maxSort + 1 @@ -54,52 +70,67 @@ const DepartmentPage: React.FC = () => { const handleEdit = (record: DepartmentResponse) => { setEditingDepartment(record); - form.setFieldsValue(record); + form.setFieldsValue({ + ...record, + parentId: record.parentId || undefined + }); setModalVisible(true); }; - // 修改提交处理,确保更新后重新构建树形结构 const handleSubmit = async () => { try { const values = await form.validateFields(); + const data = { + ...values, + parentId: values.parentId || 0 + }; + if (editingDepartment) { - const success = await handleUpdate(editingDepartment.id, { - ...values, + await request.put(`/api/v1/department/${editingDepartment.id}`, { + ...data, version: editingDepartment.version }); - if (success) { - setModalVisible(false); - fetchDepartments(); - getDepartmentTree().then(setDepartmentTree); - } + message.success('更新成功'); } else { - const success = await handleCreate(values); - if (success) { - setModalVisible(false); - fetchDepartments(); - getDepartmentTree().then(setDepartmentTree); - } + await request.post('/api/v1/department', data); + message.success('创建成功'); } + setModalVisible(false); + loadDepartmentTree(); } catch (error) { console.error('操作失败:', error); } }; + const handleDelete = (id: number) => { + Modal.confirm({ + title: '确认删除', + content: '确定要删除该部门吗?', + onOk: async () => { + try { + await request.delete(`/api/v1/department/${id}`); + message.success('删除成功'); + loadDepartmentTree(); + } catch (error) { + message.error('删除失败'); + } + } + }); + }; + const columns = [ { title: '部门名称', dataIndex: 'name', key: 'name', width: 250, - fixed: 'left' as FixedType, - sorter: true + fixed: 'left' as FixedType }, { title: '部门编码', dataIndex: 'code', key: 'code', - width: 120, - sorter: true + width: 120 }, { title: '部门描述', @@ -112,8 +143,7 @@ const DepartmentPage: React.FC = () => { title: '排序', dataIndex: 'sort', key: 'sort', - width: 80, - sorter: true + width: 80 }, { title: '负责人', @@ -151,7 +181,7 @@ const DepartmentPage: React.FC = () => { danger icon={} onClick={() => handleDelete(record.id)} - disabled={record.children?.length > 0} + disabled={Boolean(record.children?.length)} > 删除 @@ -178,7 +208,6 @@ const DepartmentPage: React.FC = () => { size="middle" bordered defaultExpandAllRows - indentSize={24} /> { width={600} destroyOnClose > -
+ + + ({ + title: dept.name, + value: dept.id, + disabled: editingDepartment?.id === dept.id, + children: dept.children?.map(child => ({ + title: child.name, + value: child.id, + disabled: editingDepartment?.id === child.id + })) + }))} + placeholder="不选择则为顶级部门" + allowClear + treeDefaultExpandAll + disabled={Boolean(editingDepartment?.children?.length)} + /> + + { - - ({ - title: dept.name, - value: dept.id, - children: dept.children?.map(child => ({ - title: child.name, - value: child.id - })) - }))} - placeholder="请选择上级部门" - allowClear - treeDefaultExpandAll - disabled={editingDepartment?.children?.length > 0} - /> - - request.delete(`${BASE_URL}/${id}`); // 获取用户列表(不分页) -export const getUsers = () => - request.get('/api/v1/user/list'); +export const getUsers = () => request.get('/api/v1/user/list'); \ No newline at end of file diff --git a/frontend/src/pages/System/Menu/index.tsx b/frontend/src/pages/System/Menu/index.tsx index 3cb52439..d649fd3f 100644 --- a/frontend/src/pages/System/Menu/index.tsx +++ b/frontend/src/pages/System/Menu/index.tsx @@ -79,7 +79,7 @@ const MenuPage: React.FC = () => { const result: MenuResponse[] = []; menuList.forEach(menu => { - menuMap.set(menu.id, { ...menu, children: [] }); + menuMap.set(menu.id, { ...menu }); }); menuList.forEach(menu => { @@ -88,7 +88,9 @@ const MenuPage: React.FC = () => { result.push(node); } else { const parent = menuMap.get(menu.parentId)!; - parent.children = parent.children || []; + if (!parent.children) { + parent.children = []; + } parent.children.push(node); } }); @@ -249,12 +251,11 @@ const MenuPage: React.FC = () => { loading={loading} columns={columns} dataSource={menuTree} - rowKey="id" - scroll={{x: 1500}} + rowKey={(record) => String(record.id)} pagination={false} size="middle" bordered - indentSize={24} + defaultExpandAllRows /> { const { @@ -103,11 +104,24 @@ const UserPage: React.FC = () => { } }; - const getTreeData = (deps: DepartmentDTO[]): any[] => { - return deps.map(dept => ({ + const loadDepartmentTree = async () => { + try { + const data = await getDepartmentTree(); + setDepartments(data); + } catch (error) { + message.error('加载部门数据失败'); + } + }; + + useEffect(() => { + loadDepartmentTree(); + }, []); + + const getTreeData = (departments: DepartmentDTO[]) => { + return departments.map(dept => ({ title: dept.name, value: dept.id, - children: dept.children && dept.children.length > 0 ? getTreeData(dept.children) : undefined + children: dept.children ? getTreeData(dept.children) : undefined })); }; @@ -331,16 +345,14 @@ const UserPage: React.FC = () => { > - +