可正常启用
This commit is contained in:
parent
a133dbbfad
commit
4baf9d271b
@ -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();
|
||||||
if (editingDepartment) {
|
const data = {
|
||||||
const success = await handleUpdate(editingDepartment.id, {
|
|
||||||
...values,
|
...values,
|
||||||
|
parentId: values.parentId || 0
|
||||||
|
};
|
||||||
|
|
||||||
|
if (editingDepartment) {
|
||||||
|
await request.put(`/api/v1/department/${editingDepartment.id}`, {
|
||||||
|
...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);
|
setModalVisible(false);
|
||||||
fetchDepartments();
|
loadDepartmentTree();
|
||||||
getDepartmentTree().then(setDepartmentTree);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} 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="部门描述"
|
||||||
|
|||||||
@ -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');
|
|
||||||
|
|
||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user