可正常启用

This commit is contained in:
戚辰先生 2024-12-01 14:44:21 +08:00
parent 9975d4508e
commit 6e79e0faac
3 changed files with 352 additions and 266 deletions

View File

@ -1,238 +1,315 @@
import React, { useEffect, useState } from 'react'; import React, { useState, useEffect } from 'react';
import { Table, Button, Modal, Form, Input, Space, message, Switch, TreeSelect } from 'antd'; import { Table, Button, Modal, Form, Input, Space, InputNumber, Switch, TreeSelect, Select } from 'antd';
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons'; import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
import type { DepartmentDTO } from './types'; import type { DepartmentResponse } from './types';
import { getDepartmentTree, createDepartment, updateDepartment, deleteDepartment, getNextSort } from './service.ts'; 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 DepartmentPage: React.FC = () => {
const [departments, setDepartments] = useState<DepartmentDTO[]>([]); const {
const [modalVisible, setModalVisible] = useState(false); list: departments,
const [editingDepartment, setEditingDepartment] = useState<DepartmentDTO | null>(null); pagination,
const [loading, setLoading] = useState(false); loading,
const [form] = Form.useForm(); loadData: fetchDepartments,
handleCreate,
const fetchDepartments = async () => { handleUpdate,
try { handleDelete
setLoading(true); } = useTableData({
const data = await getDepartmentTree(); service: {
setDepartments(data || []); baseUrl: '/api/v1/department'
console.log("部门", data); },
} catch (error) { defaultParams: {
console.error('获取部门列表失败:', error); sortField: 'createTime',
message.error('获取部门列表失败'); sortOrder: 'descend'
} 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 handleSubmit = async () => { const [modalVisible, setModalVisible] = useState(false);
try { const [editingDepartment, setEditingDepartment] = useState<DepartmentResponse | null>(null);
const values = await form.validateFields(); const [departmentTree, setDepartmentTree] = useState<DepartmentResponse[]>([]);
if (editingDepartment) { const [users, setUsers] = useState<UserResponse[]>([]);
await updateDepartment(editingDepartment.id, { const [form] = Form.useForm();
...values,
version: editingDepartment.version 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('更新成功'); setModalVisible(true);
} else { };
await createDepartment(values);
message.success('创建成功');
}
setModalVisible(false);
fetchDepartments();
} catch (error) {
message.error('操作失败');
}
};
const handleParentChange = async (value: number | undefined) => { const handleEdit = (record: DepartmentResponse) => {
try { setEditingDepartment(record);
const nextSort = await getNextSort(value); form.setFieldsValue(record);
form.setFieldValue('sort', nextSort); setModalVisible(true);
} catch (error) { };
console.error('获取排序号失败:', error);
}
};
const columns = [ const handleSubmit = async () => {
{ try {
title: '部门名称', const values = await form.validateFields();
dataIndex: 'name', if (editingDepartment) {
key: 'name', const success = await handleUpdate(editingDepartment.id, {
width: '25%', ...values,
}, version: editingDepartment.version
{ });
title: '部门编码', if (success) {
dataIndex: 'code', setModalVisible(false);
key: 'code', fetchDepartments();
width: '20%', getDepartmentTree().then(setDepartmentTree);
}, }
{ } else {
title: '排序', const success = await handleCreate(values);
dataIndex: 'sort', if (success) {
key: 'sort', setModalVisible(false);
width: '15%', fetchDepartments();
}, getDepartmentTree().then(setDepartmentTree);
{ }
title: '状态', }
dataIndex: 'enabled', } catch (error) {
key: 'enabled', console.error('操作失败:', error);
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 getTreeSelectData = (deps: DepartmentDTO[]): any[] => { const columns = [
return deps.map(dept => ({ {
title: dept.name, title: 'ID',
value: dept.id, dataIndex: 'id',
children: dept.children && dept.children.length > 0 ? getTreeSelectData(dept.children) : undefined, key: 'id',
disabled: editingDepartment ? dept.id === editingDepartment.id : false 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 ( return (
<div style={{ padding: '24px' }}> <div style={{padding: '24px'}}>
<div style={{ marginBottom: 16 }}> <div style={{marginBottom: 16}}>
<Button type="primary" icon={<PlusOutlined />} onClick={handleAdd}> <Button type="primary" icon={<PlusOutlined/>} onClick={handleAdd}>
</Button> </Button>
</div> </div>
<Table <Table
loading={loading} loading={loading}
columns={columns} columns={columns}
dataSource={departments} dataSource={departments}
rowKey="id" rowKey="id"
defaultExpandAllRows scroll={{x: 1500}}
pagination={false} pagination={pagination}
size="middle" size="middle"
bordered 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}
/> />
</Form.Item>
<Form.Item <Modal
name="sort" title={editingDepartment ? '编辑部门' : '新增部门'}
label="排序" open={modalVisible}
> onOk={handleSubmit}
<Input type="number" placeholder="排序号将自动生成" disabled /> onCancel={() => setModalVisible(false)}
</Form.Item> width={600}
<Form.Item destroyOnClose
name="enabled" >
label="状态" <Form
valuePropName="checked" form={form}
initialValue={true} layout="vertical"
> >
<Switch /> <Form.Item
</Form.Item> name="code"
</Form> label="部门编码"
</Modal> rules={[
</div> {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; export default DepartmentPage;

View File

@ -1,33 +1,30 @@
import request from '@/utils/request'; import request from '@/utils/request';
import type { Page } from '@/types/base/page';
import type { DepartmentResponse, DepartmentRequest, DepartmentQuery } from './types'; import type { DepartmentResponse, DepartmentRequest, DepartmentQuery } from './types';
export const getDepartments = async (params?: DepartmentQuery) => { const BASE_URL = '/api/v1/department';
return request.get('/api/v1/department', {
params,
errorMessage: '获取部门列表失败,请刷新重试'
});
};
export const createDepartment = async (data: DepartmentRequest) => { // 获取部门列表(分页)
return request.post('/api/v1/department', data, { export const getDepartments = (params?: DepartmentQuery) =>
errorMessage: '创建部门失败,请稍后重试' request.get<Page<DepartmentResponse>>(`${BASE_URL}/page`, { params });
});
};
export const updateDepartment = async (id: number, data: DepartmentRequest) => { // 获取部门树
return request.put(`/api/v1/department/${id}`, data, { export const getDepartmentTree = () =>
errorMessage: '更新部门失败,请稍后重试' request.get<DepartmentResponse[]>(`${BASE_URL}/tree`);
});
};
export const deleteDepartment = async (id: number) => { // 创建部门
return request.delete(`/api/v1/department/${id}`, { export const createDepartment = (data: DepartmentRequest) =>
errorMessage: '删除部门失败,请稍后重试' request.post<DepartmentResponse>(BASE_URL, data);
});
}; // 更新部门
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');
export const getDepartmentTree = async () => {
return request.get('/api/v1/department/tree', {
errorMessage: '获取部门树失败,请刷新重试'
});
};

View File

@ -1,21 +1,33 @@
export interface DepartmentDTO { import type { BaseResponse } from '@/types/base/response';
id: number;
name: string; export interface DepartmentResponse extends BaseResponse {
code: string; code: string;
description?: string; name: string;
parentId?: number; description?: string;
sort: number; parentId?: number;
enabled: boolean; sort: number;
leaderId?: number; enabled: boolean;
leaderName?: string; leaderId?: number;
version?: number; leaderName?: string;
children?: DepartmentDTO[]; children?: DepartmentResponse[];
} }
export interface TreeSelectNode { export interface DepartmentRequest {
title: string; code: string;
value: number; name: string;
key: number; description?: string;
disabled: boolean; parentId?: number;
children?: TreeSelectNode[]; sort: number;
enabled: boolean;
leaderId?: number;
leaderName?: string;
}
export interface DepartmentQuery {
code?: string;
name?: string;
parentId?: number;
enabled?: boolean;
leaderId?: number;
leaderName?: string;
} }