可正常启用
This commit is contained in:
parent
9975d4508e
commit
6e79e0faac
@ -1,238 +1,315 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Table, Button, Modal, Form, Input, Space, message, Switch, TreeSelect } from 'antd';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Table, Button, Modal, Form, Input, Space, InputNumber, Switch, TreeSelect, Select } from 'antd';
|
||||
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
|
||||
import type { DepartmentDTO } from './types';
|
||||
import { getDepartmentTree, createDepartment, updateDepartment, deleteDepartment, getNextSort } from './service.ts';
|
||||
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';
|
||||
|
||||
const DepartmentPage: React.FC = () => {
|
||||
const [departments, setDepartments] = useState<DepartmentDTO[]>([]);
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const [editingDepartment, setEditingDepartment] = useState<DepartmentDTO | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const fetchDepartments = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const data = await getDepartmentTree();
|
||||
setDepartments(data || []);
|
||||
console.log("部门", data);
|
||||
} catch (error) {
|
||||
console.error('获取部门列表失败:', error);
|
||||
message.error('获取部门列表失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchDepartments();
|
||||
}, []);
|
||||
|
||||
const handleAdd = () => {
|
||||
setEditingDepartment(null);
|
||||
form.resetFields();
|
||||
form.setFieldsValue({
|
||||
enabled: true,
|
||||
sort: 0
|
||||
});
|
||||
setModalVisible(true);
|
||||
};
|
||||
|
||||
const handleEdit = (record: DepartmentDTO) => {
|
||||
setEditingDepartment(record);
|
||||
form.setFieldsValue({
|
||||
...record,
|
||||
parentId: record.parentId || undefined
|
||||
});
|
||||
setModalVisible(true);
|
||||
};
|
||||
|
||||
const handleDelete = async (id: number) => {
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: '确定要删除这个部门吗?',
|
||||
onOk: async () => {
|
||||
try {
|
||||
await deleteDepartment(id);
|
||||
message.success('删除成功');
|
||||
fetchDepartments();
|
||||
} catch (error) {
|
||||
message.error('删除失败');
|
||||
const {
|
||||
list: departments,
|
||||
pagination,
|
||||
loading,
|
||||
loadData: fetchDepartments,
|
||||
handleCreate,
|
||||
handleUpdate,
|
||||
handleDelete
|
||||
} = useTableData({
|
||||
service: {
|
||||
baseUrl: '/api/v1/department'
|
||||
},
|
||||
defaultParams: {
|
||||
sortField: 'createTime',
|
||||
sortOrder: 'descend'
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
if (editingDepartment) {
|
||||
await updateDepartment(editingDepartment.id, {
|
||||
...values,
|
||||
version: editingDepartment.version
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const [editingDepartment, setEditingDepartment] = useState<DepartmentResponse | null>(null);
|
||||
const [departmentTree, setDepartmentTree] = useState<DepartmentResponse[]>([]);
|
||||
const [users, setUsers] = useState<UserResponse[]>([]);
|
||||
const [form] = Form.useForm();
|
||||
|
||||
useEffect(() => {
|
||||
Promise.all([
|
||||
getDepartmentTree().then(setDepartmentTree),
|
||||
getUsers().then(setUsers)
|
||||
]);
|
||||
}, []);
|
||||
|
||||
const handleAdd = () => {
|
||||
setEditingDepartment(null);
|
||||
form.resetFields();
|
||||
|
||||
// 获取当前最大排序值
|
||||
const maxSort = Math.max(0, ...departments.map(dept => dept.sort));
|
||||
|
||||
form.setFieldsValue({
|
||||
enabled: true,
|
||||
sort: maxSort + 1
|
||||
});
|
||||
message.success('更新成功');
|
||||
} else {
|
||||
await createDepartment(values);
|
||||
message.success('创建成功');
|
||||
}
|
||||
setModalVisible(false);
|
||||
fetchDepartments();
|
||||
} catch (error) {
|
||||
message.error('操作失败');
|
||||
}
|
||||
};
|
||||
setModalVisible(true);
|
||||
};
|
||||
|
||||
const handleParentChange = async (value: number | undefined) => {
|
||||
try {
|
||||
const nextSort = await getNextSort(value);
|
||||
form.setFieldValue('sort', nextSort);
|
||||
} catch (error) {
|
||||
console.error('获取排序号失败:', error);
|
||||
}
|
||||
};
|
||||
const handleEdit = (record: DepartmentResponse) => {
|
||||
setEditingDepartment(record);
|
||||
form.setFieldsValue(record);
|
||||
setModalVisible(true);
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '部门名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: '25%',
|
||||
},
|
||||
{
|
||||
title: '部门编码',
|
||||
dataIndex: 'code',
|
||||
key: 'code',
|
||||
width: '20%',
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
dataIndex: 'sort',
|
||||
key: 'sort',
|
||||
width: '15%',
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'enabled',
|
||||
key: 'enabled',
|
||||
width: '15%',
|
||||
render: (enabled: boolean) => (
|
||||
<Switch checked={enabled} disabled />
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: '25%',
|
||||
render: (_: any, record: DepartmentDTO) => (
|
||||
<Space>
|
||||
<Button
|
||||
type="link"
|
||||
icon={<EditOutlined />}
|
||||
onClick={() => handleEdit(record)}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
danger
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={() => handleDelete(record.id)}
|
||||
disabled={record.parentId === null}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
];
|
||||
const handleSubmit = async () => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
if (editingDepartment) {
|
||||
const success = await handleUpdate(editingDepartment.id, {
|
||||
...values,
|
||||
version: editingDepartment.version
|
||||
});
|
||||
if (success) {
|
||||
setModalVisible(false);
|
||||
fetchDepartments();
|
||||
getDepartmentTree().then(setDepartmentTree);
|
||||
}
|
||||
} else {
|
||||
const success = await handleCreate(values);
|
||||
if (success) {
|
||||
setModalVisible(false);
|
||||
fetchDepartments();
|
||||
getDepartmentTree().then(setDepartmentTree);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('操作失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const getTreeSelectData = (deps: DepartmentDTO[]): any[] => {
|
||||
return deps.map(dept => ({
|
||||
title: dept.name,
|
||||
value: dept.id,
|
||||
children: dept.children && dept.children.length > 0 ? getTreeSelectData(dept.children) : undefined,
|
||||
disabled: editingDepartment ? dept.id === editingDepartment.id : false
|
||||
}));
|
||||
};
|
||||
const columns = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
width: 60,
|
||||
fixed: 'left' as FixedType,
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: '部门编码',
|
||||
dataIndex: 'code',
|
||||
key: 'code',
|
||||
width: 100,
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: '部门名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: 150,
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: '上级部门',
|
||||
dataIndex: 'parentId',
|
||||
key: 'parentId',
|
||||
width: 150,
|
||||
render: (parentId: number) => {
|
||||
const parent = departments.find(dept => dept.id === parentId);
|
||||
return parent?.name || '-';
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '部门描述',
|
||||
dataIndex: 'description',
|
||||
key: 'description',
|
||||
width: 200,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
dataIndex: 'sort',
|
||||
key: 'sort',
|
||||
width: 80,
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: '负责人',
|
||||
dataIndex: 'leaderName',
|
||||
key: 'leaderName',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'enabled',
|
||||
key: 'enabled',
|
||||
width: 80,
|
||||
render: (enabled: boolean) => (
|
||||
<Switch checked={enabled} disabled size="small"/>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 160,
|
||||
fixed: 'right' as FixedType,
|
||||
render: (_: any, record: DepartmentResponse) => (
|
||||
<Space size={0}>
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
icon={<EditOutlined/>}
|
||||
onClick={() => handleEdit(record)}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
danger
|
||||
icon={<DeleteOutlined/>}
|
||||
onClick={() => handleDelete(record.id)}
|
||||
disabled={record.children?.length > 0}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</Space>
|
||||
)
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<div style={{ padding: '24px' }}>
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<Button type="primary" icon={<PlusOutlined />} onClick={handleAdd}>
|
||||
新增部门
|
||||
</Button>
|
||||
</div>
|
||||
return (
|
||||
<div style={{padding: '24px'}}>
|
||||
<div style={{marginBottom: 16}}>
|
||||
<Button type="primary" icon={<PlusOutlined/>} onClick={handleAdd}>
|
||||
新增部门
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Table
|
||||
loading={loading}
|
||||
columns={columns}
|
||||
dataSource={departments}
|
||||
rowKey="id"
|
||||
defaultExpandAllRows
|
||||
pagination={false}
|
||||
size="middle"
|
||||
bordered
|
||||
/>
|
||||
|
||||
<Modal
|
||||
title={editingDepartment ? '编辑部门' : '新增部门'}
|
||||
open={modalVisible}
|
||||
onOk={handleSubmit}
|
||||
onCancel={() => setModalVisible(false)}
|
||||
width={600}
|
||||
destroyOnClose
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
>
|
||||
<Form.Item
|
||||
name="name"
|
||||
label="部门名称"
|
||||
rules={[{ required: true, message: '请输入部门名称' }]}
|
||||
>
|
||||
<Input placeholder="请输入部门名称" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="code"
|
||||
label="部门编码"
|
||||
rules={[{ required: true, message: '请输入部门编码' }]}
|
||||
>
|
||||
<Input placeholder="请输入部门编码" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="parentId"
|
||||
label="上级部门"
|
||||
>
|
||||
<TreeSelect
|
||||
treeData={getTreeSelectData(departments)}
|
||||
placeholder="请选择上级部门"
|
||||
allowClear
|
||||
treeDefaultExpandAll
|
||||
onChange={handleParentChange}
|
||||
disabled={editingDepartment?.parentId === null}
|
||||
<Table
|
||||
loading={loading}
|
||||
columns={columns}
|
||||
dataSource={departments}
|
||||
rowKey="id"
|
||||
scroll={{x: 1500}}
|
||||
pagination={pagination}
|
||||
size="middle"
|
||||
bordered
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="sort"
|
||||
label="排序"
|
||||
>
|
||||
<Input type="number" placeholder="排序号将自动生成" disabled />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="enabled"
|
||||
label="状态"
|
||||
valuePropName="checked"
|
||||
initialValue={true}
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
|
||||
<Modal
|
||||
title={editingDepartment ? '编辑部门' : '新增部门'}
|
||||
open={modalVisible}
|
||||
onOk={handleSubmit}
|
||||
onCancel={() => setModalVisible(false)}
|
||||
width={600}
|
||||
destroyOnClose
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
>
|
||||
<Form.Item
|
||||
name="code"
|
||||
label="部门编码"
|
||||
rules={[
|
||||
{required: true, message: '请输入部门编码'},
|
||||
{pattern: /^[A-Z_]+$/, message: '部门编码只能包含大写字母和下划线'}
|
||||
]}
|
||||
>
|
||||
<Input placeholder="请输入部门编码"/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="name"
|
||||
label="部门名称"
|
||||
rules={[{required: true, message: '请输入部门名称'}]}
|
||||
>
|
||||
<Input placeholder="请输入部门名称"/>
|
||||
</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
|
||||
name="description"
|
||||
label="部门描述"
|
||||
>
|
||||
<Input.TextArea placeholder="请输入部门描述"/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="sort"
|
||||
label="显示排序"
|
||||
rules={[{required: true, message: '请输入显示排序'}]}
|
||||
>
|
||||
<InputNumber
|
||||
style={{width: '100%'}}
|
||||
min={0}
|
||||
placeholder="请输入显示排序"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="leaderId"
|
||||
label="负责人"
|
||||
>
|
||||
<Select
|
||||
placeholder="请选择负责人"
|
||||
allowClear
|
||||
showSearch
|
||||
optionFilterProp="children"
|
||||
onChange={(value, option: any) => {
|
||||
form.setFieldsValue({
|
||||
leaderId: value,
|
||||
leaderName: option?.label
|
||||
});
|
||||
}}
|
||||
>
|
||||
{users.map(user => (
|
||||
<Select.Option
|
||||
key={user.id}
|
||||
value={user.id}
|
||||
label={user.nickname || user.username}
|
||||
>
|
||||
{user.nickname || user.username}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="leaderName" hidden>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="enabled"
|
||||
label="状态"
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch checkedChildren="启用" unCheckedChildren="禁用"/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DepartmentPage;
|
||||
@ -1,33 +1,30 @@
|
||||
import request from '@/utils/request';
|
||||
import type { Page } from '@/types/base/page';
|
||||
import type { DepartmentResponse, DepartmentRequest, DepartmentQuery } from './types';
|
||||
|
||||
export const getDepartments = async (params?: DepartmentQuery) => {
|
||||
return request.get('/api/v1/department', {
|
||||
params,
|
||||
errorMessage: '获取部门列表失败,请刷新重试'
|
||||
});
|
||||
};
|
||||
const BASE_URL = '/api/v1/department';
|
||||
|
||||
export const createDepartment = async (data: DepartmentRequest) => {
|
||||
return request.post('/api/v1/department', data, {
|
||||
errorMessage: '创建部门失败,请稍后重试'
|
||||
});
|
||||
};
|
||||
// 获取部门列表(分页)
|
||||
export const getDepartments = (params?: DepartmentQuery) =>
|
||||
request.get<Page<DepartmentResponse>>(`${BASE_URL}/page`, { params });
|
||||
|
||||
export const updateDepartment = async (id: number, data: DepartmentRequest) => {
|
||||
return request.put(`/api/v1/department/${id}`, data, {
|
||||
errorMessage: '更新部门失败,请稍后重试'
|
||||
});
|
||||
};
|
||||
// 获取部门树
|
||||
export const getDepartmentTree = () =>
|
||||
request.get<DepartmentResponse[]>(`${BASE_URL}/tree`);
|
||||
|
||||
export const deleteDepartment = async (id: number) => {
|
||||
return request.delete(`/api/v1/department/${id}`, {
|
||||
errorMessage: '删除部门失败,请稍后重试'
|
||||
});
|
||||
};
|
||||
// 创建部门
|
||||
export const createDepartment = (data: DepartmentRequest) =>
|
||||
request.post<DepartmentResponse>(BASE_URL, data);
|
||||
|
||||
export const getDepartmentTree = async () => {
|
||||
return request.get('/api/v1/department/tree', {
|
||||
errorMessage: '获取部门树失败,请刷新重试'
|
||||
});
|
||||
};
|
||||
// 更新部门
|
||||
export const updateDepartment = (id: number, data: DepartmentRequest) =>
|
||||
request.put<DepartmentResponse>(`${BASE_URL}/${id}`, data);
|
||||
|
||||
// 删除部门
|
||||
export const deleteDepartment = (id: number) =>
|
||||
request.delete(`${BASE_URL}/${id}`);
|
||||
|
||||
// 获取用户列表(不分页)
|
||||
export const getUsers = () =>
|
||||
request.get<UserResponse[]>('/api/v1/user/list');
|
||||
|
||||
@ -1,21 +1,33 @@
|
||||
export interface DepartmentDTO {
|
||||
id: number;
|
||||
name: string;
|
||||
code: string;
|
||||
description?: string;
|
||||
parentId?: number;
|
||||
sort: number;
|
||||
enabled: boolean;
|
||||
leaderId?: number;
|
||||
leaderName?: string;
|
||||
version?: number;
|
||||
children?: DepartmentDTO[];
|
||||
import type { BaseResponse } from '@/types/base/response';
|
||||
|
||||
export interface DepartmentResponse extends BaseResponse {
|
||||
code: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
parentId?: number;
|
||||
sort: number;
|
||||
enabled: boolean;
|
||||
leaderId?: number;
|
||||
leaderName?: string;
|
||||
children?: DepartmentResponse[];
|
||||
}
|
||||
|
||||
export interface TreeSelectNode {
|
||||
title: string;
|
||||
value: number;
|
||||
key: number;
|
||||
disabled: boolean;
|
||||
children?: TreeSelectNode[];
|
||||
export interface DepartmentRequest {
|
||||
code: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
parentId?: number;
|
||||
sort: number;
|
||||
enabled: boolean;
|
||||
leaderId?: number;
|
||||
leaderName?: string;
|
||||
}
|
||||
|
||||
export interface DepartmentQuery {
|
||||
code?: string;
|
||||
name?: string;
|
||||
parentId?: number;
|
||||
enabled?: boolean;
|
||||
leaderId?: number;
|
||||
leaderName?: string;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user