blob: 3a1c5def382bf8c1cd4c6ef9e8190b5accc60ce9 [file] [log] [blame]
Jiarenxiang38dcb052025-03-13 16:40:09 +08001
2import React, { useState, useRef, useEffect } from 'react';
3import { useIntl, FormattedMessage, useAccess } from '@umijs/max';
4import type { FormInstance } from 'antd';
5import { Button, message, Modal } from 'antd';
6import { ActionType, FooterToolbar, PageContainer, ProColumns, ProTable } from '@ant-design/pro-components';
7import { PlusOutlined, DeleteOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
8import { getDeptList, removeDept, addDept, updateDept, getDeptListExcludeChild } from '@/services/system/dept';
9import UpdateForm from './edit';
10import { getDictValueEnum } from '@/services/system/dict';
11import { buildTreeData } from '@/utils/tree';
12import DictTag from '@/components/DictTag';
13
14/**
15 * 添加节点
16 *
17 * @param fields
18 */
19const handleAdd = async (fields: API.System.Dept) => {
20 const hide = message.loading('正在添加');
21 try {
22 const resp = await addDept({ ...fields });
23 hide();
24 if (resp.code === 200) {
25 message.success('添加成功');
26 } else {
27 message.error(resp.msg);
28 }
29 return true;
30 } catch (error) {
31 hide();
32 message.error('添加失败请重试!');
33 return false;
34 }
35};
36
37/**
38 * 更新节点
39 *
40 * @param fields
41 */
42const handleUpdate = async (fields: API.System.Dept) => {
43 const hide = message.loading('正在更新');
44 try {
45 const resp = await updateDept(fields);
46 hide();
47 if (resp.code === 200) {
48 message.success('更新成功');
49 } else {
50 message.error(resp.msg);
51 }
52 return true;
53 } catch (error) {
54 hide();
55 message.error('配置失败请重试!');
56 return false;
57 }
58};
59
60/**
61 * 删除节点
62 *
63 * @param selectedRows
64 */
65const handleRemove = async (selectedRows: API.System.Dept[]) => {
66 const hide = message.loading('正在删除');
67 if (!selectedRows) return true;
68 try {
69 const resp = await removeDept(selectedRows.map((row) => row.deptId).join(','));
70 hide();
71 if (resp.code === 200) {
72 message.success('删除成功,即将刷新');
73 } else {
74 message.error(resp.msg);
75 }
76 return true;
77 } catch (error) {
78 hide();
79 message.error('删除失败,请重试');
80 return false;
81 }
82};
83
84const handleRemoveOne = async (selectedRow: API.System.Dept) => {
85 const hide = message.loading('正在删除');
86 if (!selectedRow) return true;
87 try {
88 const params = [selectedRow.deptId];
89 const resp = await removeDept(params.join(','));
90 hide();
91 if (resp.code === 200) {
92 message.success('删除成功,即将刷新');
93 } else {
94 message.error(resp.msg);
95 }
96 return true;
97 } catch (error) {
98 hide();
99 message.error('删除失败,请重试');
100 return false;
101 }
102};
103
104
105const DeptTableList: React.FC = () => {
106 const formTableRef = useRef<FormInstance>();
107
108 const [modalVisible, setModalVisible] = useState<boolean>(false);
109
110 const actionRef = useRef<ActionType>();
111 const [currentRow, setCurrentRow] = useState<API.System.Dept>();
112 const [selectedRows, setSelectedRows] = useState<API.System.Dept[]>([]);
113
114 const [deptTree, setDeptTree] = useState<any>([]);
115 const [statusOptions, setStatusOptions] = useState<any>([]);
116
117 const access = useAccess();
118
119 /** 国际化配置 */
120 const intl = useIntl();
121
122 useEffect(() => {
123 getDictValueEnum('sys_normal_disable').then((data) => {
124 setStatusOptions(data);
125 });
126 }, []);
127
128 const columns: ProColumns<API.System.Dept>[] = [
129 {
130 title: <FormattedMessage id="system.dept.dept_name" defaultMessage="部门名称" />,
131 dataIndex: 'deptName',
132 valueType: 'text',
133 },
134 {
135 title: <FormattedMessage id="system.dept.order_num" defaultMessage="显示顺序" />,
136 dataIndex: 'orderNum',
137 valueType: 'text',
138 },
139 {
140 title: <FormattedMessage id="system.dept.status" defaultMessage="部门状态" />,
141 dataIndex: 'status',
142 valueType: 'select',
143 valueEnum: statusOptions,
144 render: (_, record) => {
145 return (<DictTag enums={statusOptions} value={record.status} />);
146 },
147 },
148 {
149 title: <FormattedMessage id="pages.searchTable.titleOption" defaultMessage="操作" />,
150 dataIndex: 'option',
151 width: '220px',
152 valueType: 'option',
153 render: (_, record) => [
154 <Button
155 type="link"
156 size="small"
157 key="edit"
158 hidden={!access.hasPerms('system:dept:edit')}
159 onClick={() => {
160 getDeptListExcludeChild(record.deptId).then((res) => {
161 if (res.code === 200) {
162 let depts = buildTreeData(res.data, 'deptId', 'deptName', '', '', '');
163 if(depts.length === 0) {
164 depts = [{ id: 0, title: '无上级', children: undefined, key: 0, value: 0 }];
165 }
166 setDeptTree(depts);
167 setModalVisible(true);
168 setCurrentRow(record);
169 } else {
170 message.warning(res.msg);
171 }
172 });
173 }}
174 >
175 编辑
176 </Button>,
177 <Button
178 type="link"
179 size="small"
180 danger
181 key="batchRemove"
182 hidden={!access.hasPerms('system:dept:remove')}
183 onClick={async () => {
184 Modal.confirm({
185 title: '删除',
186 content: '确定删除该项吗?',
187 okText: '确认',
188 cancelText: '取消',
189 onOk: async () => {
190 const success = await handleRemoveOne(record);
191 if (success) {
192 if (actionRef.current) {
193 actionRef.current.reload();
194 }
195 }
196 },
197 });
198 }}
199 >
200 删除
201 </Button>,
202 ],
203 },
204 ];
205
206 return (
207 <PageContainer>
208 <div style={{ width: '100%', float: 'right' }}>
209 <ProTable<API.System.Dept>
210 headerTitle={intl.formatMessage({
211 id: 'pages.searchTable.title',
212 defaultMessage: '信息',
213 })}
214 actionRef={actionRef}
215 formRef={formTableRef}
216 rowKey="deptId"
217 key="deptList"
218 search={{
219 labelWidth: 120,
220 }}
221 toolBarRender={() => [
222 <Button
223 type="primary"
224 key="add"
225 hidden={!access.hasPerms('system:dept:add')}
226 onClick={async () => {
227 getDeptList().then((res) => {
228 if (res.code === 200) {
229 setDeptTree(buildTreeData(res.data, 'deptId', 'deptName', '', '', ''));
230 setCurrentRow(undefined);
231 setModalVisible(true);
232 } else {
233 message.warning(res.msg);
234 }
235 });
236 }}
237 >
238 <PlusOutlined /> <FormattedMessage id="pages.searchTable.new" defaultMessage="新建" />
239 </Button>,
240 <Button
241 type="primary"
242 key="remove"
243 danger
244 hidden={selectedRows?.length === 0 || !access.hasPerms('system:dept:remove')}
245 onClick={async () => {
246 Modal.confirm({
247 title: '是否确认删除所选数据项?',
248 icon: <ExclamationCircleOutlined />,
249 content: '请谨慎操作',
250 async onOk() {
251 const success = await handleRemove(selectedRows);
252 if (success) {
253 setSelectedRows([]);
254 actionRef.current?.reloadAndRest?.();
255 }
256 },
257 onCancel() {},
258 });
259 }}
260 >
261 <DeleteOutlined />
262 <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" />
263 </Button>,
264 ]}
265 request={(params) =>
266 getDeptList({ ...params } as API.System.DeptListParams).then((res) => {
267 const result = {
268 data: buildTreeData(res.data, 'deptId', '', '', '', ''),
269 total: res.data.length,
270 success: true,
271 };
272 return result;
273 })
274 }
275 columns={columns}
276 rowSelection={{
277 onChange: (_, selectedRows) => {
278 setSelectedRows(selectedRows);
279 },
280 }}
281 />
282 </div>
283 {selectedRows?.length > 0 && (
284 <FooterToolbar
285 extra={
286 <div>
287 <FormattedMessage id="pages.searchTable.chosen" defaultMessage="已选择" />
288 <a style={{ fontWeight: 600 }}>{selectedRows.length}</a>
289 <FormattedMessage id="pages.searchTable.item" defaultMessage="项" />
290 </div>
291 }
292 >
293 <Button
294 key="remove"
295 danger
296 hidden={!access.hasPerms('system:dept:del')}
297 onClick={async () => {
298 Modal.confirm({
299 title: '删除',
300 content: '确定删除该项吗?',
301 okText: '确认',
302 cancelText: '取消',
303 onOk: async () => {
304 const success = await handleRemove(selectedRows);
305 if (success) {
306 setSelectedRows([]);
307 actionRef.current?.reloadAndRest?.();
308 }
309 },
310 });
311 }}
312 >
313 <FormattedMessage id="pages.searchTable.batchDeletion" defaultMessage="批量删除" />
314 </Button>
315 </FooterToolbar>
316 )}
317 <UpdateForm
318 onSubmit={async (values) => {
319 let success = false;
320 if (values.deptId) {
321 success = await handleUpdate({ ...values } as API.System.Dept);
322 } else {
323 success = await handleAdd({ ...values } as API.System.Dept);
324 }
325 if (success) {
326 setModalVisible(false);
327 setCurrentRow(undefined);
328 if (actionRef.current) {
329 actionRef.current.reload();
330 }
331 }
332 }}
333 onCancel={() => {
334 setModalVisible(false);
335 setCurrentRow(undefined);
336 }}
337 open={modalVisible}
338 values={currentRow || {}}
339 deptTree={deptTree}
340 statusOptions={statusOptions}
341 />
342 </PageContainer>
343 );
344};
345
346export default DeptTableList;