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