blob: e09425566d69e87d124b041e8a24e8a2795d7e8c [file] [log] [blame]
Jiarenxiang38dcb052025-03-13 16:40:09 +08001import React, { useEffect, useState } from 'react';
2import {
3 ProForm,
4 ProFormDigit,
5 ProFormText,
6 ProFormRadio,
7 ProFormTreeSelect,
8 ProFormSelect,
9} from '@ant-design/pro-components';
10import { Form, Modal} from 'antd';
11import { useIntl, FormattedMessage } from '@umijs/max';
12import { DataNode } from 'antd/es/tree';
13import { createIcon } from '@/utils/IconUtil';
14import { DictValueEnumObj } from '@/components/DictTag';
15import IconSelector from '@/components/IconSelector';
16
17export type MenuFormData = Record<string, unknown> & Partial<API.System.Menu>;
18
19export type MenuFormProps = {
20 onCancel: (flag?: boolean, formVals?: MenuFormData) => void;
21 onSubmit: (values: MenuFormData) => Promise<void>;
22 open: boolean;
23 values: Partial<API.System.Menu>;
24 visibleOptions: DictValueEnumObj;
25 statusOptions: DictValueEnumObj;
26 menuTree: DataNode[];
27};
28
29const MenuForm: React.FC<MenuFormProps> = (props) => {
30
31 const [form] = Form.useForm();
32
33 const [menuTypeId, setMenuTypeId] = useState<any>('M');
34 const [menuIconName, setMenuIconName] = useState<any>();
35 const [iconSelectorOpen, setIconSelectorOpen] = useState<boolean>(false);
36
37 const { menuTree, visibleOptions, statusOptions } = props;
38
39 useEffect(() => {
40 form.resetFields();
41 setMenuIconName(props.values.icon);
42 form.setFieldsValue({
43 menuId: props.values.menuId,
44 menuName: props.values.menuName,
45 parentId: props.values.parentId,
46 orderNum: props.values.orderNum,
47 path: props.values.path,
48 component: props.values.component,
49 query: props.values.query,
50 isFrame: props.values.isFrame,
51 isCache: props.values.isCache,
52 menuType: props.values.menuType,
53 visible: props.values.visible,
54 status: props.values.status,
55 perms: props.values.perms,
56 icon: props.values.icon,
57 createBy: props.values.createBy,
58 createTime: props.values.createTime,
59 updateBy: props.values.updateBy,
60 updateTime: props.values.updateTime,
61 remark: props.values.remark,
62 });
63 }, [form, props]);
64
65 const intl = useIntl();
66 const handleOk = () => {
67 form.submit();
68 };
69 const handleCancel = () => {
70 props.onCancel();
71 };
72 const handleFinish = async (values: Record<string, any>) => {
73 props.onSubmit(values as MenuFormData);
74 };
75
76 return (
77 <Modal
78 width={640}
79 title={intl.formatMessage({
80 id: 'system.menu.title',
81 defaultMessage: '编辑菜单权限',
82 })}
83 open={props.open}
84 forceRender
85 destroyOnClose
86 onOk={handleOk}
87 onCancel={handleCancel}
88 >
89 <ProForm
90 form={form}
91 grid={true}
92 submitter={false}
93 layout="horizontal"
94 onFinish={handleFinish}>
95 <ProFormDigit
96 name="menuId"
97 label={intl.formatMessage({
98 id: 'system.menu.menu_id',
99 defaultMessage: '菜单编号',
100 })}
101 placeholder="请输入菜单编号"
102 disabled
103 hidden={true}
104 rules={[
105 {
106 required: false,
107 message: <FormattedMessage id="请输入菜单编号!" defaultMessage="请输入菜单编号!" />,
108 },
109 ]}
110 />
111 <ProFormTreeSelect
112 name="parentId"
113 label={intl.formatMessage({
114 id: 'system.menu.parent_id',
115 defaultMessage: '上级菜单',
116 })}
117 params={{menuTree}}
118 request={async () => {
119 return menuTree;
120 }}
121 placeholder="请输入父菜单编号"
122 rules={[
123 {
124 required: true,
125 message: <FormattedMessage id="请输入父菜单编号!" defaultMessage="请输入父菜单编号!" />,
126 },
127 ]}
128 fieldProps = {{
129 defaultValue: 0
130 }}
131 />
132 <ProFormRadio.Group
133 name="menuType"
134 valueEnum={{
135 M: '目录',
136 C: '菜单',
137 F: '按钮',
138 }}
139 label={intl.formatMessage({
140 id: 'system.menu.menu_type',
141 defaultMessage: '菜单类型',
142 })}
143 placeholder="请输入菜单类型"
144 rules={[
145 {
146 required: false,
147 message: <FormattedMessage id="请输入菜单类型!" defaultMessage="请输入菜单类型!" />,
148 },
149 ]}
150 fieldProps={{
151 defaultValue: 'M',
152 onChange: (e) => {
153 setMenuTypeId(e.target.value);
154 },
155 }}
156 />
157 <ProFormSelect
158 name="icon"
159 label={intl.formatMessage({
160 id: 'system.menu.icon',
161 defaultMessage: '菜单图标',
162 })}
163 valueEnum={{}}
164 hidden={menuTypeId === 'F'}
165 addonBefore={createIcon(menuIconName)}
166 fieldProps={{
167 onClick: () => {
168 setIconSelectorOpen(true);
169 },
170 }}
171 placeholder="请输入菜单图标"
172 rules={[
173 {
174 required: false,
175 message: <FormattedMessage id="请输入菜单图标!" defaultMessage="请输入菜单图标!" />,
176 },
177 ]}
178 />
179 <ProFormText
180 name="menuName"
181 label={intl.formatMessage({
182 id: 'system.menu.menu_name',
183 defaultMessage: '菜单名称',
184 })}
185 colProps={{ md: 12, xl: 12 }}
186 placeholder="请输入菜单名称"
187 rules={[
188 {
189 required: true,
190 message: <FormattedMessage id="请输入菜单名称!" defaultMessage="请输入菜单名称!" />,
191 },
192 ]}
193 />
194 <ProFormDigit
195 name="orderNum"
196 label={intl.formatMessage({
197 id: 'system.menu.order_num',
198 defaultMessage: '显示顺序',
199 })}
200 width="lg"
201 colProps={{ md: 12, xl: 12 }}
202 placeholder="请输入显示顺序"
203 rules={[
204 {
205 required: false,
206 message: <FormattedMessage id="请输入显示顺序!" defaultMessage="请输入显示顺序!" />,
207 },
208 ]}
209 fieldProps = {{
210 defaultValue: 1
211 }}
212 />
213 <ProFormRadio.Group
214 name="isFrame"
215 valueEnum={{
216 0: '是',
217 1: '否',
218 }}
219 initialValue="1"
220 label={intl.formatMessage({
221 id: 'system.menu.is_frame',
222 defaultMessage: '是否为外链',
223 })}
224 colProps={{ md: 12, xl: 12 }}
225 placeholder="请输入是否为外链"
226 hidden={menuTypeId === 'F'}
227 rules={[
228 {
229 required: false,
230 message: <FormattedMessage id="请输入是否为外链!" defaultMessage="请输入是否为外链!" />,
231 },
232 ]}
233 fieldProps = {{
234 defaultValue: '1'
235 }}
236 />
237 <ProFormText
238 name="path"
239 label={intl.formatMessage({
240 id: 'system.menu.path',
241 defaultMessage: '路由地址',
242 })}
243 width="lg"
244 colProps={{ md: 12, xl: 12 }}
245 placeholder="请输入路由地址"
246 hidden={menuTypeId === 'F'}
247 rules={[
248 {
249 required: menuTypeId !== 'F',
250 message: <FormattedMessage id="请输入路由地址!" defaultMessage="请输入路由地址!" />,
251 },
252 ]}
253 />
254 <ProFormText
255 name="component"
256 label={intl.formatMessage({
257 id: 'system.menu.component',
258 defaultMessage: '组件路径',
259 })}
260 colProps={{ md: 12, xl: 12 }}
261 placeholder="请输入组件路径"
262 hidden={menuTypeId !== 'C'}
263 rules={[
264 {
265 required: false,
266 message: <FormattedMessage id="请输入组件路径!" defaultMessage="请输入组件路径!" />,
267 },
268 ]}
269 />
270 <ProFormText
271 name="query"
272 label={intl.formatMessage({
273 id: 'system.menu.query',
274 defaultMessage: '路由参数',
275 })}
276 colProps={{ md: 12, xl: 12 }}
277 placeholder="请输入路由参数"
278 hidden={menuTypeId !== 'C'}
279 rules={[
280 {
281 required: false,
282 message: <FormattedMessage id="请输入路由参数!" defaultMessage="请输入路由参数!" />,
283 },
284 ]}
285 />
286 <ProFormText
287 name="perms"
288 label={intl.formatMessage({
289 id: 'system.menu.perms',
290 defaultMessage: '权限标识',
291 })}
292 colProps={{ md: 12, xl: 12 }}
293 placeholder="请输入权限标识"
294 hidden={menuTypeId === 'M'}
295 rules={[
296 {
297 required: false,
298 message: <FormattedMessage id="请输入权限标识!" defaultMessage="请输入权限标识!" />,
299 },
300 ]}
301 />
302 <ProFormRadio.Group
303 name="isCache"
304 valueEnum={{
305 0: '缓存',
306 1: '不缓存',
307 }}
308 label={intl.formatMessage({
309 id: 'system.menu.is_cache',
310 defaultMessage: '是否缓存',
311 })}
312 colProps={{ md: 12, xl: 12 }}
313 placeholder="请输入是否缓存"
314 hidden={menuTypeId !== 'C'}
315 rules={[
316 {
317 required: false,
318 message: <FormattedMessage id="请输入是否缓存!" defaultMessage="请输入是否缓存!" />,
319 },
320 ]}
321 fieldProps = {{
322 defaultValue: 0
323 }}
324 />
325 <ProFormRadio.Group
326 name="visible"
327 valueEnum={visibleOptions}
328 label={intl.formatMessage({
329 id: 'system.menu.visible',
330 defaultMessage: '显示状态',
331 })}
332 colProps={{ md: 12, xl: 12 }}
333 placeholder="请输入显示状态"
334 hidden={menuTypeId === 'F'}
335 rules={[
336 {
337 required: false,
338 message: <FormattedMessage id="请输入显示状态!" defaultMessage="请输入显示状态!" />,
339 },
340 ]}
341 fieldProps = {{
342 defaultValue: '0'
343 }}
344 />
345 <ProFormRadio.Group
346 valueEnum={statusOptions}
347 name="status"
348 label={intl.formatMessage({
349 id: 'system.menu.status',
350 defaultMessage: '菜单状态',
351 })}
352 colProps={{ md: 12, xl: 12 }}
353 placeholder="请输入菜单状态"
354 hidden={menuTypeId === 'F'}
355 rules={[
356 {
357 required: true,
358 message: <FormattedMessage id="请输入菜单状态!" defaultMessage="请输入菜单状态!" />,
359 },
360 ]}
361 fieldProps = {{
362 defaultValue: '0'
363 }}
364 />
365 </ProForm>
366 <Modal
367 width={800}
368 open={iconSelectorOpen}
369 onCancel={() => {
370 setIconSelectorOpen(false);
371 }}
372 footer={null}
373 >
374 <IconSelector
375 onSelect={(name: string) => {
376 form.setFieldsValue({ icon: name });
377 setMenuIconName(name);
378 setIconSelectorOpen(false);
379 }}
380 />
381 </Modal>
382 </Modal>
383 );
384};
385
386export default MenuForm;