可正常启用

This commit is contained in:
戚辰先生 2024-12-01 17:42:19 +08:00
parent a133dbbfad
commit 4baf9d271b
4 changed files with 126 additions and 88 deletions

View File

@ -1,41 +1,55 @@
import React, { useState, useEffect } from 'react'; 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 { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
import type { DepartmentResponse } from './types'; import type { DepartmentResponse } from './types';
import { useTableData } from '@/hooks/useTableData';
import type { FixedType } from 'rc-table/lib/interface';
import { getDepartmentTree } from './service'; import { getDepartmentTree } from './service';
import type { UserResponse } from '@/pages/System/User/types'; import type { UserResponse } from '@/pages/System/User/types';
import { getUsers } from './service'; 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 DepartmentPage: React.FC = () => {
const { const [loading, setLoading] = useState(false);
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<DepartmentResponse | null>(null);
const [departmentTree, setDepartmentTree] = useState<DepartmentResponse[]>([]); const [departmentTree, setDepartmentTree] = useState<DepartmentResponse[]>([]);
const [users, setUsers] = useState<UserResponse[]>([]); const [users, setUsers] = useState<UserResponse[]>([]);
const [modalVisible, setModalVisible] = useState(false);
const [editingDepartment, setEditingDepartment] = useState<DepartmentResponse | null>(null);
const [form] = Form.useForm(); 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(() => { useEffect(() => {
Promise.all([ Promise.all([
getDepartmentTree().then(setDepartmentTree), loadDepartmentTree(),
getUsers().then(setUsers) getUsers().then(setUsers)
]); ]);
}, []); }, []);
@ -43,8 +57,10 @@ const DepartmentPage: React.FC = () => {
const handleAdd = () => { const handleAdd = () => {
setEditingDepartment(null); setEditingDepartment(null);
form.resetFields(); 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({ form.setFieldsValue({
enabled: true, enabled: true,
sort: maxSort + 1 sort: maxSort + 1
@ -54,52 +70,67 @@ const DepartmentPage: React.FC = () => {
const handleEdit = (record: DepartmentResponse) => { const handleEdit = (record: DepartmentResponse) => {
setEditingDepartment(record); setEditingDepartment(record);
form.setFieldsValue(record); form.setFieldsValue({
...record,
parentId: record.parentId || undefined
});
setModalVisible(true); setModalVisible(true);
}; };
// 修改提交处理,确保更新后重新构建树形结构
const handleSubmit = async () => { const handleSubmit = async () => {
try { try {
const values = await form.validateFields(); const values = await form.validateFields();
const data = {
...values,
parentId: values.parentId || 0
};
if (editingDepartment) { if (editingDepartment) {
const success = await handleUpdate(editingDepartment.id, { await request.put(`/api/v1/department/${editingDepartment.id}`, {
...values, ...data,
version: editingDepartment.version version: editingDepartment.version
}); });
if (success) { message.success('更新成功');
setModalVisible(false);
fetchDepartments();
getDepartmentTree().then(setDepartmentTree);
}
} else { } else {
const success = await handleCreate(values); await request.post('/api/v1/department', data);
if (success) { message.success('创建成功');
setModalVisible(false);
fetchDepartments();
getDepartmentTree().then(setDepartmentTree);
}
} }
setModalVisible(false);
loadDepartmentTree();
} catch (error) { } catch (error) {
console.error('操作失败:', 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 = [ const columns = [
{ {
title: '部门名称', title: '部门名称',
dataIndex: 'name', dataIndex: 'name',
key: 'name', key: 'name',
width: 250, width: 250,
fixed: 'left' as FixedType, fixed: 'left' as FixedType
sorter: true
}, },
{ {
title: '部门编码', title: '部门编码',
dataIndex: 'code', dataIndex: 'code',
key: 'code', key: 'code',
width: 120, width: 120
sorter: true
}, },
{ {
title: '部门描述', title: '部门描述',
@ -112,8 +143,7 @@ const DepartmentPage: React.FC = () => {
title: '排序', title: '排序',
dataIndex: 'sort', dataIndex: 'sort',
key: 'sort', key: 'sort',
width: 80, width: 80
sorter: true
}, },
{ {
title: '负责人', title: '负责人',
@ -151,7 +181,7 @@ const DepartmentPage: React.FC = () => {
danger danger
icon={<DeleteOutlined/>} icon={<DeleteOutlined/>}
onClick={() => handleDelete(record.id)} onClick={() => handleDelete(record.id)}
disabled={record.children?.length > 0} disabled={Boolean(record.children?.length)}
> >
</Button> </Button>
@ -178,7 +208,6 @@ const DepartmentPage: React.FC = () => {
size="middle" size="middle"
bordered bordered
defaultExpandAllRows defaultExpandAllRows
indentSize={24}
/> />
<Modal <Modal
@ -189,10 +218,26 @@ const DepartmentPage: React.FC = () => {
width={600} width={600}
destroyOnClose destroyOnClose
> >
<Form <Form form={form} layout="vertical">
form={form} <Form.Item name="parentId" label="上级部门">
layout="vertical" <TreeSelect
> treeData={departmentTree.map(dept => ({
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)}
/>
</Form.Item>
<Form.Item <Form.Item
name="code" name="code"
label="部门编码" label="部门编码"
@ -212,26 +257,6 @@ const DepartmentPage: React.FC = () => {
<Input placeholder="请输入部门名称"/> <Input placeholder="请输入部门名称"/>
</Form.Item> </Form.Item>
<Form.Item
name="parentId"
label="上级部门"
>
<TreeSelect
treeData={departmentTree.map(dept => ({
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}
/>
</Form.Item>
<Form.Item <Form.Item
name="description" name="description"
label="部门描述" label="部门描述"

View File

@ -1,6 +1,7 @@
import request from '@/utils/request'; import request from '@/utils/request';
import type { Page } from '@/types/base/page'; import type { Page } from '@/types/base/page';
import type { DepartmentResponse, DepartmentRequest, DepartmentQuery } from './types'; import type { DepartmentResponse, DepartmentRequest, DepartmentQuery } from './types';
import {UserResponse} from "@/pages/System/User/types";
const BASE_URL = '/api/v1/department'; const BASE_URL = '/api/v1/department';
@ -25,6 +26,5 @@ export const deleteDepartment = (id: number) =>
request.delete(`${BASE_URL}/${id}`); request.delete(`${BASE_URL}/${id}`);
// 获取用户列表(不分页) // 获取用户列表(不分页)
export const getUsers = () => export const getUsers = () => request.get<UserResponse[]>('/api/v1/user/list');
request.get<UserResponse[]>('/api/v1/user/list');

View File

@ -79,7 +79,7 @@ const MenuPage: React.FC = () => {
const result: MenuResponse[] = []; const result: MenuResponse[] = [];
menuList.forEach(menu => { menuList.forEach(menu => {
menuMap.set(menu.id, { ...menu, children: [] }); menuMap.set(menu.id, { ...menu });
}); });
menuList.forEach(menu => { menuList.forEach(menu => {
@ -88,7 +88,9 @@ const MenuPage: React.FC = () => {
result.push(node); result.push(node);
} else { } else {
const parent = menuMap.get(menu.parentId)!; const parent = menuMap.get(menu.parentId)!;
parent.children = parent.children || []; if (!parent.children) {
parent.children = [];
}
parent.children.push(node); parent.children.push(node);
} }
}); });
@ -249,12 +251,11 @@ const MenuPage: React.FC = () => {
loading={loading} loading={loading}
columns={columns} columns={columns}
dataSource={menuTree} dataSource={menuTree}
rowKey="id" rowKey={(record) => String(record.id)}
scroll={{x: 1500}}
pagination={false} pagination={false}
size="middle" size="middle"
bordered bordered
indentSize={24} defaultExpandAllRows
/> />
<Modal <Modal

View File

@ -9,6 +9,7 @@ import type {FixedType, AlignType, SortOrder} from 'rc-table/lib/interface';
import {Response} from "@/utils/request.ts"; import {Response} from "@/utils/request.ts";
import {TablePaginationConfig} from "antd/es/table"; import {TablePaginationConfig} from "antd/es/table";
import {FilterValue, SorterResult} from "antd/es/table/interface"; import {FilterValue, SorterResult} from "antd/es/table/interface";
import { getDepartmentTree } from '../Department/service'; // 导入部门树接口
const UserPage: React.FC = () => { const UserPage: React.FC = () => {
const { const {
@ -103,11 +104,24 @@ const UserPage: React.FC = () => {
} }
}; };
const getTreeData = (deps: DepartmentDTO[]): any[] => { const loadDepartmentTree = async () => {
return deps.map(dept => ({ try {
const data = await getDepartmentTree();
setDepartments(data);
} catch (error) {
message.error('加载部门数据失败');
}
};
useEffect(() => {
loadDepartmentTree();
}, []);
const getTreeData = (departments: DepartmentDTO[]) => {
return departments.map(dept => ({
title: dept.name, title: dept.name,
value: dept.id, 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 = () => {
> >
<Input placeholder="请输入手机号"/> <Input placeholder="请输入手机号"/>
</Form.Item> </Form.Item>
<Form.Item <Form.Item name="departmentId" label="所属部门">
name="deptId"
label="所属部门"
>
<TreeSelect <TreeSelect
treeData={getTreeData(departments)} treeData={getTreeData(departments)}
placeholder="请选择所属部门" placeholder="请选择所属部门"
allowClear allowClear
treeDefaultExpandAll treeDefaultExpandAll
style={{width: '100%'}} showSearch
treeNodeFilterProp="title"
/> />
</Form.Item> </Form.Item>
<Form.Item <Form.Item