import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
import type { Key } from 'react';
|
import { PlusOutlined } from '@ant-design/icons';
|
import { ProTable } from '@ant-design/pro-components';
|
import type { ActionType } from '@ant-design/pro-components';
|
import { App as AntdApp, Button } from 'antd';
|
import { createDepartmentColumns } from './columns';
|
import DepartmentFormDrawer from './components/DepartmentFormDrawer';
|
import { deleteOrg, getLeaderOptions, getOrgTree, toggleOrgStatus } from './server';
|
import type { DepartmentListQuery, OrgVO } from './types';
|
import { collectOrgIds, filterOrgTree } from './utils';
|
|
const Departments = () => {
|
const actionRef = useRef<ActionType>();
|
const { message, modal } = AntdApp.useApp();
|
const [orgTree, setOrgTree] = useState<OrgVO[]>([]);
|
const [expandedRowKeys, setExpandedRowKeys] = useState<Key[]>([]);
|
const [leaderOptions, setLeaderOptions] = useState<{ label: string; value: number }[]>([]);
|
const [formOpen, setFormOpen] = useState(false);
|
const [formMode, setFormMode] = useState<'create' | 'edit'>('create');
|
const [activeOrg, setActiveOrg] = useState<OrgVO | null>(null);
|
const [parentId, setParentId] = useState<number | undefined>();
|
|
useEffect(() => {
|
let active = true;
|
|
const loadLeaders = async () => {
|
try {
|
const result = await getLeaderOptions();
|
if (!active) return;
|
|
setLeaderOptions(
|
(result.records ?? []).map((employee) => ({
|
label: employee.name,
|
value: employee.id,
|
})),
|
);
|
} catch {
|
// 错误已由 request 统一提示
|
}
|
};
|
|
void loadLeaders();
|
|
return () => {
|
active = false;
|
};
|
}, []);
|
|
const leaderNameMap = useMemo(
|
() => new Map(leaderOptions.map((option) => [option.value, option.label])),
|
[leaderOptions],
|
);
|
|
const fetchDepartments = useCallback(async (params: DepartmentListQuery) => {
|
const list = await getOrgTree();
|
setOrgTree(list);
|
setExpandedRowKeys(collectOrgIds(list));
|
|
const data = filterOrgTree(list, params);
|
return { data, total: data.length, success: true };
|
}, []);
|
|
const openCreateRoot = useCallback(() => {
|
setActiveOrg(null);
|
setParentId(undefined);
|
setFormMode('create');
|
setFormOpen(true);
|
}, []);
|
|
const openCreateChild = useCallback((record: OrgVO) => {
|
setActiveOrg(null);
|
setParentId(record.id);
|
setFormMode('create');
|
setFormOpen(true);
|
}, []);
|
|
const openEdit = useCallback((record: OrgVO) => {
|
setActiveOrg(record);
|
setParentId(undefined);
|
setFormMode('edit');
|
setFormOpen(true);
|
}, []);
|
|
const closeForm = useCallback(() => {
|
setFormOpen(false);
|
setActiveOrg(null);
|
}, []);
|
|
const handleFormSuccess = useCallback(() => {
|
closeForm();
|
actionRef.current?.reload();
|
}, [closeForm]);
|
|
const handleToggle = useCallback(
|
(record: OrgVO) => {
|
const nextAction = record.status ? '停用' : '启用';
|
modal.confirm({
|
title: `${nextAction}部门`,
|
content: `确定要${nextAction}部门「${record.orgName}」吗?`,
|
okText: nextAction,
|
cancelText: '取消',
|
okButtonProps: { danger: !!record.status },
|
onOk: async () => {
|
await toggleOrgStatus({ id: record.id });
|
message.success(`部门已${nextAction}`);
|
actionRef.current?.reload();
|
},
|
});
|
},
|
[message, modal],
|
);
|
|
const handleDelete = useCallback(
|
(record: OrgVO) => {
|
modal.confirm({
|
title: '删除部门',
|
content: `确定要删除部门「${record.orgName}」吗?存在子部门时可能无法删除。`,
|
okText: '删除',
|
cancelText: '取消',
|
okButtonProps: { danger: true },
|
onOk: async () => {
|
await deleteOrg({ id: record.id });
|
message.success('部门已删除');
|
actionRef.current?.reload();
|
},
|
});
|
},
|
[message, modal],
|
);
|
|
const columns = useMemo(
|
() =>
|
createDepartmentColumns({
|
leaderNameMap,
|
onCreateChild: openCreateChild,
|
onEdit: openEdit,
|
onToggle: handleToggle,
|
onDelete: handleDelete,
|
}),
|
[leaderNameMap, openCreateChild, openEdit, handleToggle, handleDelete],
|
);
|
|
return (
|
<div className="department-page">
|
<ProTable<OrgVO, DepartmentListQuery>
|
rowKey="id"
|
actionRef={actionRef}
|
columns={columns}
|
search={{ labelWidth: 'auto', defaultCollapsed: false }}
|
scroll={{ x: 1100 }}
|
options={false}
|
pagination={false}
|
expandable={{
|
expandedRowKeys,
|
onExpandedRowsChange: (keys) => setExpandedRowKeys([...keys]),
|
}}
|
toolBarRender={() => [
|
<Button key="create" type="primary" icon={<PlusOutlined />} onClick={openCreateRoot}>
|
新增部门
|
</Button>,
|
]}
|
request={fetchDepartments}
|
/>
|
|
<DepartmentFormDrawer
|
open={formOpen}
|
mode={formMode}
|
record={activeOrg}
|
parentId={parentId}
|
orgTree={orgTree}
|
leaderOptions={leaderOptions}
|
onClose={closeForm}
|
onSuccess={handleFormSuccess}
|
/>
|
</div>
|
);
|
};
|
|
export default Departments;
|