blob: ea15b2e0897191bf770d06a1b3c5392b92a38687 [file] [log] [blame]
Jiarenxiang38dcb052025-03-13 16:40:09 +08001
2import React, { useState, useRef, useEffect } from 'react';
3import { useIntl, FormattedMessage, useAccess, history } from '@umijs/max';
4import { DataNode } from 'antd/es/tree';
5import { Button, message, Modal, Dropdown, FormInstance, Space, Switch } from 'antd';
6import { ActionType, FooterToolbar, PageContainer, ProColumns, ProTable } from '@ant-design/pro-components';
7import { PlusOutlined, EditOutlined, DeleteOutlined, ExclamationCircleOutlined, DownOutlined } from '@ant-design/icons';
8import { getRoleList, removeRole, addRole, updateRole, exportRole, getRoleMenuList, changeRoleStatus, updateRoleDataScope, getDeptTreeSelect, getRole } from '@/services/system/role';
9import UpdateForm from './edit';
10import { getDictValueEnum } from '@/services/system/dict';
11import { formatTreeData } from '@/utils/tree';
12import { getMenuTree } from '@/services/system/menu';
13import DataScopeForm from './components/DataScope';
14
15const { confirm } = Modal;
16
17/**
18 * 添加节点
19 *
20 * @param fields
21 */
22const handleAdd = async (fields: API.System.Role) => {
23 const hide = message.loading('正在添加');
24 try {
25 const resp = await addRole({ ...fields });
26 hide();
27 if (resp.code === 200) {
28 message.success('添加成功');
29 } else {
30 message.error(resp.msg);
31 }
32 return true;
33 } catch (error) {
34 hide();
35 message.error('添加失败请重试!');
36 return false;
37 }
38};
39
40/**
41 * 更新节点
42 *
43 * @param fields
44 */
45const handleUpdate = async (fields: API.System.Role) => {
46 const hide = message.loading('正在更新');
47 try {
48 const resp = await updateRole(fields);
49 hide();
50 if (resp.code === 200) {
51 message.success('更新成功');
52 } else {
53 message.error(resp.msg);
54 }
55 return true;
56 } catch (error) {
57 hide();
58 message.error('配置失败请重试!');
59 return false;
60 }
61};
62
63/**
64 * 删除节点
65 *
66 * @param selectedRows
67 */
68const handleRemove = async (selectedRows: API.System.Role[]) => {
69 const hide = message.loading('正在删除');
70 if (!selectedRows) return true;
71 try {
72 const resp = await removeRole(selectedRows.map((row) => row.roleId).join(','));
73 hide();
74 if (resp.code === 200) {
75 message.success('删除成功,即将刷新');
76 } else {
77 message.error(resp.msg);
78 }
79 return true;
80 } catch (error) {
81 hide();
82 message.error('删除失败,请重试');
83 return false;
84 }
85};
86
87const handleRemoveOne = async (selectedRow: API.System.Role) => {
88 const hide = message.loading('正在删除');
89 if (!selectedRow) return true;
90 try {
91 const params = [selectedRow.roleId];
92 const resp = await removeRole(params.join(','));
93 hide();
94 if (resp.code === 200) {
95 message.success('删除成功,即将刷新');
96 } else {
97 message.error(resp.msg);
98 }
99 return true;
100 } catch (error) {
101 hide();
102 message.error('删除失败,请重试');
103 return false;
104 }
105};
106
107/**
108 * 导出数据
109 *
110 *
111 */
112const handleExport = async () => {
113 const hide = message.loading('正在导出');
114 try {
115 await exportRole();
116 hide();
117 message.success('导出成功');
118 return true;
119 } catch (error) {
120 hide();
121 message.error('导出失败,请重试');
122 return false;
123 }
124};
125
126
127const RoleTableList: React.FC = () => {
128
129 const [messageApi, contextHolder] = message.useMessage();
130 const formTableRef = useRef<FormInstance>();
131
132 const [modalVisible, setModalVisible] = useState<boolean>(false);
133 const [dataScopeModalOpen, setDataScopeModalOpen] = useState<boolean>(false);
134
135 const actionRef = useRef<ActionType>();
136 const [currentRow, setCurrentRow] = useState<API.System.Role>();
137 const [selectedRows, setSelectedRows] = useState<API.System.Role[]>([]);
138
139 const [menuTree, setMenuTree] = useState<DataNode[]>();
140 const [menuIds, setMenuIds] = useState<string[]>([]);
141 const [statusOptions, setStatusOptions] = useState<any>([]);
142
143 const access = useAccess();
144
145 /** 国际化配置 */
146 const intl = useIntl();
147
148 useEffect(() => {
149 getDictValueEnum('sys_normal_disable').then((data) => {
150 setStatusOptions(data);
151 });
152 }, []);
153
154 const showChangeStatusConfirm = (record: API.System.Role) => {
155 let text = record.status === "1" ? "启用" : "停用";
156 const newStatus = record.status === '0' ? '1' : '0';
157 confirm({
158 title: `确认要${text}${record.roleName}角色吗?`,
159 onOk() {
160 changeRoleStatus(record.roleId, newStatus).then(resp => {
161 if (resp.code === 200) {
162 messageApi.open({
163 type: 'success',
164 content: '更新成功!',
165 });
166 actionRef.current?.reload();
167 } else {
168 messageApi.open({
169 type: 'error',
170 content: '更新失败!',
171 });
172 }
173 });
174 },
175 });
176 };
177
178 const columns: ProColumns<API.System.Role>[] = [
179 {
180 title: <FormattedMessage id="system.role.role_id" defaultMessage="角色编号" />,
181 dataIndex: 'roleId',
182 valueType: 'text',
183 },
184 {
185 title: <FormattedMessage id="system.role.role_name" defaultMessage="角色名称" />,
186 dataIndex: 'roleName',
187 valueType: 'text',
188 },
189 {
190 title: <FormattedMessage id="system.role.role_key" defaultMessage="角色权限字符串" />,
191 dataIndex: 'roleKey',
192 valueType: 'text',
193 hideInSearch: true,
194 },
195 {
196 title: <FormattedMessage id="system.role.role_sort" defaultMessage="显示顺序" />,
197 dataIndex: 'roleSort',
198 valueType: 'text',
199 hideInSearch: true,
200 },
201 {
202 title: <FormattedMessage id="system.role.status" defaultMessage="角色状态" />,
203 dataIndex: 'status',
204 valueType: 'select',
205 valueEnum: statusOptions,
206 render: (_, record) => {
207 return (
208 <Switch
209 checked={record.status === '0'}
210 checkedChildren="正常"
211 unCheckedChildren="停用"
212 defaultChecked
213 onClick={() => showChangeStatusConfirm(record)}
214 />)
215 },
216 },
217 {
218 title: <FormattedMessage id="system.role.create_time" defaultMessage="创建时间" />,
219 dataIndex: 'createTime',
220 valueType: 'dateRange',
221 render: (_, record) => {
222 return (<span>{record.createTime.toString()} </span>);
223 },
224 search: {
225 transform: (value) => {
226 return {
227 'params[beginTime]': value[0],
228 'params[endTime]': value[1],
229 };
230 },
231 },
232 },
233 {
234 title: <FormattedMessage id="pages.searchTable.titleOption" defaultMessage="操作" />,
235 dataIndex: 'option',
236 width: '220px',
237 valueType: 'option',
238 render: (_, record) => [
239 <Button
240 type="link"
241 size="small"
242 key="edit"
243 icon=<EditOutlined />
244 hidden={!access.hasPerms('system:role:edit')}
245 onClick={() => {
246 getRoleMenuList(record.roleId).then((res) => {
247 if (res.code === 200) {
248 const treeData = formatTreeData(res.menus);
249 setMenuTree(treeData);
250 setMenuIds(res.checkedKeys.map(item => {
251 return `${item}`
252 }));
253 setModalVisible(true);
254 setCurrentRow(record);
255 } else {
256 message.warning(res.msg);
257 }
258 });
259 }}
260 >
261 编辑
262 </Button>,
263 <Button
264 type="link"
265 size="small"
266 danger
267 key="batchRemove"
268 icon=<DeleteOutlined />
269 hidden={!access.hasPerms('system:role:remove')}
270 onClick={async () => {
271 Modal.confirm({
272 title: '删除',
273 content: '确定删除该项吗?',
274 okText: '确认',
275 cancelText: '取消',
276 onOk: async () => {
277 const success = await handleRemoveOne(record);
278 if (success) {
279 if (actionRef.current) {
280 actionRef.current.reload();
281 }
282 }
283 },
284 });
285 }}
286 >
287 删除
288 </Button>,
289 <Dropdown
290 key="more"
291 menu={{
292 items: [
293 {
294 label: '数据权限',
295 key: 'datascope',
296 disabled: !access.hasPerms('system:role:edit'),
297 },
298 {
299 label: '分配用户',
300 key: 'authUser',
301 disabled: !access.hasPerms('system:role:edit'),
302 },
303 ],
304 onClick: ({ key }: any) => {
305 if (key === 'datascope') {
306 getRole(record.roleId).then(resp => {
307 if(resp.code === 200) {
308 setCurrentRow(resp.data);
309 setDataScopeModalOpen(true);
310 }
311 })
312 getDeptTreeSelect(record.roleId).then(resp => {
313 if (resp.code === 200) {
314 setMenuTree(formatTreeData(resp.depts));
315 setMenuIds(resp.checkedKeys.map((item:number) => {
316 return `${item}`
317 }));
318 }
319 })
320 }
321 else if (key === 'authUser') {
322 history.push(`/system/role-auth/user/${record.roleId}`);
323 }
324 }
325 }}
326 >
327 <a onClick={(e) => e.preventDefault()}>
328 <Space>
329 <DownOutlined />
330 更多
331 </Space>
332 </a>
333 </Dropdown>,
334 ],
335 },
336 ];
337
338 return (
339 <PageContainer>
340 {contextHolder}
341 <div style={{ width: '100%', float: 'right' }}>
342 <ProTable<API.System.Role>
343 headerTitle={intl.formatMessage({
344 id: 'pages.searchTable.title',
345 defaultMessage: '信息',
346 })}
347 actionRef={actionRef}
348 formRef={formTableRef}
349 rowKey="roleId"
350 key="roleList"
351 search={{
352 labelWidth: 120,
353 }}
354 toolBarRender={() => [
355 <Button
356 type="primary"
357 key="add"
358 hidden={!access.hasPerms('system:role:add')}
359 onClick={async () => {
360 getMenuTree().then((res: any) => {
361 if (res.code === 200) {
362 const treeData = formatTreeData(res.data);
363 setMenuTree(treeData);
364 setMenuIds([]);
365 setModalVisible(true);
366 setCurrentRow(undefined);
367 } else {
368 message.warning(res.msg);
369 }
370 });
371 }}
372 >
373 <PlusOutlined /> <FormattedMessage id="pages.searchTable.new" defaultMessage="新建" />
374 </Button>,
375 <Button
376 type="primary"
377 key="remove"
378 danger
379 hidden={selectedRows?.length === 0 || !access.hasPerms('system:role:remove')}
380 onClick={async () => {
381 Modal.confirm({
382 title: '是否确认删除所选数据项?',
383 icon: <ExclamationCircleOutlined />,
384 content: '请谨慎操作',
385 async onOk() {
386 const success = await handleRemove(selectedRows);
387 if (success) {
388 setSelectedRows([]);
389 actionRef.current?.reloadAndRest?.();
390 }
391 },
392 onCancel() { },
393 });
394 }}
395 >
396 <DeleteOutlined />
397 <FormattedMessage id="pages.searchTable.delete" defaultMessage="删除" />
398 </Button>,
399 <Button
400 type="primary"
401 key="export"
402 hidden={!access.hasPerms('system:role:export')}
403 onClick={async () => {
404 handleExport();
405 }}
406 >
407 <PlusOutlined />
408 <FormattedMessage id="pages.searchTable.export" defaultMessage="导出" />
409 </Button>,
410 ]}
411 request={(params) =>
412 getRoleList({ ...params } as API.System.RoleListParams).then((res) => {
413 const result = {
414 data: res.rows,
415 total: res.total,
416 success: true,
417 };
418 return result;
419 })
420 }
421 columns={columns}
422 rowSelection={{
423 onChange: (_, selectedRows) => {
424 setSelectedRows(selectedRows);
425 },
426 }}
427 />
428 </div>
429 {selectedRows?.length > 0 && (
430 <FooterToolbar
431 extra={
432 <div>
433 <FormattedMessage id="pages.searchTable.chosen" defaultMessage="已选择" />
434 <a style={{ fontWeight: 600 }}>{selectedRows.length}</a>
435 <FormattedMessage id="pages.searchTable.item" defaultMessage="项" />
436 </div>
437 }
438 >
439 <Button
440 key="remove"
441 danger
442 hidden={!access.hasPerms('system:role:del')}
443 onClick={async () => {
444 Modal.confirm({
445 title: '删除',
446 content: '确定删除该项吗?',
447 okText: '确认',
448 cancelText: '取消',
449 onOk: async () => {
450 const success = await handleRemove(selectedRows);
451 if (success) {
452 setSelectedRows([]);
453 actionRef.current?.reloadAndRest?.();
454 }
455 },
456 });
457 }}
458 >
459 <FormattedMessage id="pages.searchTable.batchDeletion" defaultMessage="批量删除" />
460 </Button>
461 </FooterToolbar>
462 )}
463 <UpdateForm
464 onSubmit={async (values) => {
465 let success = false;
466 if (values.roleId) {
467 success = await handleUpdate({ ...values } as API.System.Role);
468 } else {
469 success = await handleAdd({ ...values } as API.System.Role);
470 }
471 if (success) {
472 setModalVisible(false);
473 setCurrentRow(undefined);
474 if (actionRef.current) {
475 actionRef.current.reload();
476 }
477 }
478 }}
479 onCancel={() => {
480 setModalVisible(false);
481 setCurrentRow(undefined);
482 }}
483 open={modalVisible}
484 values={currentRow || {}}
485 menuTree={menuTree || []}
486 menuCheckedKeys={menuIds || []}
487 statusOptions={statusOptions}
488 />
489 <DataScopeForm
490 onSubmit={async (values: any) => {
491 const success = await updateRoleDataScope(values);
492 if (success) {
493 setDataScopeModalOpen(false);
494 setSelectedRows([]);
495 setCurrentRow(undefined);
496 message.success('配置成功。');
497 }
498 }}
499 onCancel={() => {
500 setDataScopeModalOpen(false);
501 setSelectedRows([]);
502 setCurrentRow(undefined);
503 }}
504 open={dataScopeModalOpen}
505 values={currentRow || {}}
506 deptTree={menuTree || []}
507 deptCheckedKeys={menuIds || []}
508 />
509 </PageContainer>
510 );
511};
512
513export default RoleTableList;