From 6e79e0faacc5567abb3d7112fa9dcdd25d3c16c7 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 14:44:21 +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 | 521 ++++++++++-------- .../src/pages/System/Department/service.ts | 49 +- frontend/src/pages/System/Department/types.ts | 48 +- 3 files changed, 352 insertions(+), 266 deletions(-) diff --git a/frontend/src/pages/System/Department/index.tsx b/frontend/src/pages/System/Department/index.tsx index 9857a1e6..e7f63ff6 100644 --- a/frontend/src/pages/System/Department/index.tsx +++ b/frontend/src/pages/System/Department/index.tsx @@ -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([]); - const [modalVisible, setModalVisible] = useState(false); - const [editingDepartment, setEditingDepartment] = useState(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(null); + const [departmentTree, setDepartmentTree] = useState([]); + const [users, setUsers] = useState([]); + 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) => ( - - ), - }, - { - title: '操作', - key: 'action', - width: '25%', - render: (_: any, record: DepartmentDTO) => ( - - - - - ), - }, - ]; + 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) => ( + + ) + }, + { + title: '操作', + key: 'action', + width: 160, + fixed: 'right' as FixedType, + render: (_: any, record: DepartmentResponse) => ( + + + + + ) + } + ]; - return ( -
-
- -
+ return ( +
+
+ +
- - - setModalVisible(false)} - width={600} - destroyOnClose - > -
- - - - - - - - - - - - - - - - -
- - ); + + setModalVisible(false)} + width={600} + destroyOnClose + > +
+ + + + + + + + + + ({ + 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} + /> + + + + + + + + + + + + + + + + + + + + +
+ + ); }; export default DepartmentPage; \ No newline at end of file diff --git a/frontend/src/pages/System/Department/service.ts b/frontend/src/pages/System/Department/service.ts index 1f1ac5af..6b32e638 100644 --- a/frontend/src/pages/System/Department/service.ts +++ b/frontend/src/pages/System/Department/service.ts @@ -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>(`${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(`${BASE_URL}/tree`); -export const deleteDepartment = async (id: number) => { - return request.delete(`/api/v1/department/${id}`, { - errorMessage: '删除部门失败,请稍后重试' - }); -}; +// 创建部门 +export const createDepartment = (data: DepartmentRequest) => + request.post(BASE_URL, data); -export const getDepartmentTree = async () => { - return request.get('/api/v1/department/tree', { - errorMessage: '获取部门树失败,请刷新重试' - }); -}; \ No newline at end of file +// 更新部门 +export const updateDepartment = (id: number, data: DepartmentRequest) => + request.put(`${BASE_URL}/${id}`, data); + +// 删除部门 +export const deleteDepartment = (id: number) => + request.delete(`${BASE_URL}/${id}`); + +// 获取用户列表(不分页) +export const getUsers = () => + request.get('/api/v1/user/list'); + \ No newline at end of file diff --git a/frontend/src/pages/System/Department/types.ts b/frontend/src/pages/System/Department/types.ts index 6a961940..1b250189 100644 --- a/frontend/src/pages/System/Department/types.ts +++ b/frontend/src/pages/System/Department/types.ts @@ -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; } \ No newline at end of file