page.tsx 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  1. "use client";
  2. import {fetchApi} from "@/app/_modules/func";
  3. import {DeleteOutlined, ExclamationCircleFilled, PlusOutlined, ReloadOutlined,} from "@ant-design/icons";
  4. import type {ActionType, ProColumns, ProFormInstance,} from "@ant-design/pro-components";
  5. import {
  6. ModalForm,
  7. PageContainer,
  8. ProForm,
  9. ProFormDigit,
  10. ProFormRadio,
  11. ProFormSelect,
  12. ProFormText,
  13. ProFormTreeSelect,
  14. ProTable,
  15. } from "@ant-design/pro-components";
  16. import {App, Button, Modal, Space, Tag} from "antd";
  17. import {useRouter} from "next/navigation";
  18. import {
  19. faArrowsUpDown,
  20. faCheck,
  21. faPenToSquare,
  22. faToggleOff,
  23. faToggleOn,
  24. faXmark,
  25. } from "@fortawesome/free-solid-svg-icons";
  26. import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
  27. import {IconMap} from "@/app/_modules/definies";
  28. import {useRef, useState} from "react";
  29. //查询表格数据API
  30. const queryAPI = "/api/system/menu/list";
  31. //新建数据API
  32. const newAPI = "/api/system/menu";
  33. //修改数据API
  34. const modifyAPI = "/api/system/menu";
  35. //查询详情数据API
  36. const queryDetailAPI = "/api/system/menu";
  37. //删除API
  38. const deleteAPI = "/api/system/menu";
  39. export default function SysMenu() {
  40. const { message } = App.useApp();
  41. const { push } = useRouter();
  42. // 添加用于控制删除确认模态框的状态
  43. const [deleteModalVisible, setDeleteModalVisible] = useState(false);
  44. const [deleteRecord, setDeleteRecord] = useState<any>(null);
  45. // 添加用于控制清空确认模态框的状态(如果需要的话)
  46. const [clearModalVisible, setClearModalVisible] = useState(false);
  47. //表格列定义
  48. const columns: ProColumns[] = [
  49. {
  50. title: "菜单名称",
  51. fieldProps: {
  52. placeholder: "请输入菜单名称",
  53. },
  54. dataIndex: "menuName",
  55. order: 2,
  56. },
  57. {
  58. title: "图标",
  59. dataIndex: "icon",
  60. search: false,
  61. },
  62. {
  63. title: "排序",
  64. dataIndex: "orderNum",
  65. search: false,
  66. },
  67. {
  68. title: "权限标识",
  69. dataIndex: "perms",
  70. ellipsis: true,
  71. search: false,
  72. },
  73. {
  74. title: "状态",
  75. fieldProps: {
  76. placeholder: "请选择菜单状态",
  77. },
  78. dataIndex: "status",
  79. valueType: "select",
  80. render: (_, record) => {
  81. return (
  82. <Space>
  83. <Tag
  84. color={record.status === "0" ? "green" : "red"}
  85. icon={
  86. record.status == 0 ? (
  87. <FontAwesomeIcon icon={faCheck} />
  88. ) : (
  89. <FontAwesomeIcon icon={faXmark} />
  90. )
  91. }
  92. >
  93. {_}
  94. </Tag>
  95. </Space>
  96. );
  97. },
  98. valueEnum: {
  99. 0: {
  100. text: "正常",
  101. status: "0",
  102. },
  103. 1: {
  104. text: "停用",
  105. status: "1",
  106. },
  107. },
  108. order: 1,
  109. },
  110. {
  111. title: "创建时间",
  112. dataIndex: "createTime",
  113. valueType: "dateTime",
  114. search: false,
  115. },
  116. {
  117. title: "操作",
  118. key: "option",
  119. search: false,
  120. render: (_, record) => [
  121. <Button
  122. key="modifyBtn"
  123. type="link"
  124. icon={<FontAwesomeIcon icon={faPenToSquare} />}
  125. onClick={() => onClickShowRowModifyModal(record)}
  126. >
  127. 修改
  128. </Button>,
  129. <Button
  130. key="newBtn"
  131. type="link"
  132. icon={<PlusOutlined />}
  133. onClick={() => onClickAdd(record)}
  134. >
  135. 新建
  136. </Button>,
  137. <Button
  138. key="deleteBtn"
  139. type="link"
  140. danger
  141. icon={<DeleteOutlined />}
  142. onClick={() => onClickDeleteRow(record)}
  143. >
  144. 删除
  145. </Button>,
  146. ],
  147. },
  148. ];
  149. //0.查询表格数据
  150. //原始的可展开的所有行的 id
  151. const [defaultExpandKeys, setDefaultExpandKeys] = useState<any[]>([]);
  152. //控制行展开的数据
  153. const [expandKeys, setExpandKeys] = useState<any[]>([]);
  154. const queryTableData = async (params: any, sorter: any, filter: any) => {
  155. const searchParams = {
  156. ...params,
  157. };
  158. const queryParams = new URLSearchParams(searchParams);
  159. Object.keys(sorter).forEach((key) => {
  160. queryParams.append("orderByColumn", key);
  161. if (sorter[key] === "ascend") {
  162. queryParams.append("isAsc", "ascending");
  163. } else {
  164. queryParams.append("isAsc", "descending");
  165. }
  166. });
  167. const body = await fetchApi(`${queryAPI}?${queryParams}`, push);
  168. const firstLevel = getFirstLevel(body.data);
  169. firstLevel.forEach((first) => {
  170. getChildren(body.data, first);
  171. });
  172. const newExpandedKeys: any[] = [];
  173. const render = (treeDatas: any[]) => {
  174. // 获取到所有可展开的父节点
  175. treeDatas.map((item) => {
  176. if (item.children) {
  177. newExpandedKeys.push(item.menuId);
  178. render(item.children);
  179. }
  180. });
  181. return newExpandedKeys;
  182. };
  183. const keys = render(firstLevel);
  184. setDefaultExpandKeys(keys);
  185. setExpandKeys([]);
  186. return firstLevel;
  187. };
  188. const getFirstLevel = (data: any[]) => {
  189. const firstLevel: any[] = [];
  190. for (let index = 0; index < data.length; index++) {
  191. const item = data[index];
  192. if (item.parentId === 0) {
  193. firstLevel.push(item);
  194. }
  195. }
  196. return firstLevel;
  197. };
  198. const getChildren = (data: any[], parentNode: any) => {
  199. for (let index = 0; index < data.length; index++) {
  200. const item = data[index];
  201. if (item.parentId === parentNode.menuId) {
  202. parentNode.children.push(item);
  203. getChildren(data, item);
  204. }
  205. }
  206. if (parentNode.children.length == 0) {
  207. delete parentNode.children;
  208. }
  209. };
  210. //1.新建
  211. const [showAddModal, setShowAddModal] = useState(false);
  212. //新建表单是否带有父节点id
  213. const [rowParentId, setRowParentId] = useState(0);
  214. //点击新建,如果从行点击新建,给定父节点
  215. const onClickAdd = (record?: any) => {
  216. setRowParentId(record.menuId);
  217. setShowAddModal(true);
  218. };
  219. const cancelAddModal = () => {
  220. setShowAddModal(false);
  221. setRowParentId(0);
  222. };
  223. //确定新建数据
  224. const executeAddData = async (values: any) => {
  225. const body = await fetchApi(newAPI, push, {
  226. method: "POST",
  227. headers: {
  228. "Content-Type": "application/json",
  229. },
  230. body: JSON.stringify(values),
  231. });
  232. if (body != undefined) {
  233. if (body.code == 200) {
  234. App.useApp().message.success(body.msg);
  235. if (actionTableRef.current) {
  236. actionTableRef.current.reload();
  237. }
  238. setShowAddModal(false);
  239. return true;
  240. }
  241. App.useApp().message.error(body.msg);
  242. return false;
  243. }
  244. return false;
  245. };
  246. //2.修改
  247. //是否展示修改对话框
  248. const [isShowModifyDataModal, setIsShowModifyDataModal] = useState(false);
  249. //展示修改对话框
  250. const onClickShowRowModifyModal = (record: any) => {
  251. queryRowData(record);
  252. setIsShowModifyDataModal(true);
  253. };
  254. //修改数据表单引用
  255. const modifyFormRef = useRef<ProFormInstance>(null);
  256. //操作当前数据的附加数据
  257. const [operatRowData, setOperateRowData] = useState<{
  258. [key: string]: any;
  259. }>({});
  260. //查询并加载待修改数据的详细信息
  261. const queryRowData = async (record: any) => {
  262. const menuId = record.menuId;
  263. operatRowData["menuId"] = menuId;
  264. setOperateRowData(operatRowData);
  265. if (menuId !== undefined) {
  266. const body = await fetchApi(`${queryDetailAPI}/${menuId}`, push);
  267. if (body !== undefined) {
  268. if (body.code == 200) {
  269. modifyFormRef?.current?.setFieldsValue({
  270. //需要加载到修改表单中的数据
  271. parentId: body.data.parentId,
  272. menuName: body.data.menuName,
  273. orderNum: body.data.orderNum,
  274. path: body.data.path,
  275. isFrame: body.data.isFrame,
  276. menuType: body.data.menuType,
  277. perms: body.data.perms,
  278. icon: body.data.icon,
  279. visible: body.data.visible,
  280. status: body.data.status,
  281. });
  282. setIsCatalog(body.data.menuType === "M");
  283. setIsMenu(body.data.menuType === "C");
  284. setIsButton(body.data.menuType === "F");
  285. }
  286. }
  287. }
  288. };
  289. //确认修改数据
  290. const executeModifyData = async (values: any) => {
  291. values["menuId"] = operatRowData["menuId"];
  292. const body = await fetchApi(modifyAPI, push, {
  293. method: "PUT",
  294. headers: {
  295. "Content-Type": "application/json",
  296. },
  297. body: JSON.stringify(values),
  298. });
  299. if (body !== undefined) {
  300. if (body.code == 200) {
  301. App.useApp().message.success(body.msg);
  302. //刷新列表
  303. if (actionTableRef.current) {
  304. actionTableRef.current.reload();
  305. }
  306. setIsShowModifyDataModal(false);
  307. return true;
  308. }
  309. App.useApp().message.error(body.msg);
  310. return false;
  311. }
  312. };
  313. //3.展开/折叠
  314. //点击展开/折叠按钮
  315. const onClickExpandRow = () => {
  316. if (expandKeys.length > 0) {
  317. setExpandKeys([]);
  318. } else {
  319. setExpandKeys(defaultExpandKeys);
  320. }
  321. };
  322. //处理行的展开/折叠逻辑
  323. const handleExpand = (expanded: boolean, record: any) => {
  324. console.log("has keys:", expandKeys);
  325. let keys = [...expandKeys];
  326. if (expanded) {
  327. keys.push(record.menuId);
  328. } else {
  329. keys = keys.filter((key: number) => key !== record.menuId);
  330. }
  331. console.log("now keys:", keys);
  332. setExpandKeys(keys);
  333. };
  334. //4.导出
  335. //5.选择行
  336. //搜索栏显示状态
  337. const [showSearch, setShowSearch] = useState(true);
  338. //action对象引用
  339. const actionTableRef = useRef<ActionType>(null);
  340. //搜索表单对象引用
  341. const searchTableFormRef = useRef<ProFormInstance>(null!);
  342. const getMenuList = async () => {
  343. const body = await fetchApi(queryAPI, push);
  344. if (body !== undefined) {
  345. const firstLevel = getFirstLevel(body.data);
  346. firstLevel.forEach((first) => {
  347. getChildren(body.data, first);
  348. });
  349. const root: any = {
  350. menuId: 0,
  351. menuName: "根目录",
  352. children: [],
  353. };
  354. firstLevel.forEach((first: any) => {
  355. root.children.push(first as never);
  356. });
  357. return [root];
  358. }
  359. return [];
  360. };
  361. //点击删除按钮
  362. const onClickDeleteRow = (record: any) => {
  363. setDeleteRecord(record);
  364. setDeleteModalVisible(true);
  365. };
  366. //确定删除选中的菜单
  367. const executeDeleteRow = async () => {
  368. if (!deleteRecord) return;
  369. const menuId = deleteRecord.menuId;
  370. const body = await fetchApi(`${deleteAPI}/${menuId}`, push, {
  371. method: "DELETE",
  372. });
  373. if (body !== undefined) {
  374. if (body.code == 200) {
  375. App.useApp().message.success("删除成功");
  376. //刷新列表
  377. if (actionTableRef.current) {
  378. actionTableRef.current.reload();
  379. }
  380. } else {
  381. App.useApp().message.error(body.msg);
  382. }
  383. }
  384. setDeleteModalVisible(false);
  385. setDeleteRecord(null);
  386. };
  387. const [isCatalog, setIsCatalog] = useState(true);
  388. const [isMenu, setIsMenu] = useState(false);
  389. const [isButton, setIsButton] = useState(false);
  390. const onChangeType = (e: any) => {
  391. const type = e.target.value;
  392. setIsCatalog(type === "M");
  393. setIsMenu(type === "C");
  394. setIsButton(type === "F");
  395. };
  396. const IconData = () => {
  397. const iconData = { ...IconMap };
  398. Object.keys(iconData).forEach((key) => {
  399. iconData[key] = (
  400. <>
  401. <span style={{ marginRight: 8 }}>{iconData[key]}</span>
  402. {key}
  403. </>
  404. );
  405. });
  406. return iconData;
  407. };
  408. return (
  409. <PageContainer title={false}>
  410. <ProTable
  411. formRef={searchTableFormRef}
  412. rowKey="menuId"
  413. columns={columns}
  414. expandable={{
  415. expandedRowKeys: expandKeys,
  416. onExpand: handleExpand,
  417. }}
  418. request={async (params: any, sorter: any, filter: any) => {
  419. // 表单搜索项会从 params 传入,传递给后端接口。
  420. const data = await queryTableData(params, sorter, filter);
  421. if (data !== undefined) {
  422. return Promise.resolve({
  423. data: data,
  424. success: true,
  425. total: data.length,
  426. });
  427. }
  428. return Promise.resolve({
  429. data: [],
  430. success: true,
  431. });
  432. }}
  433. pagination={false}
  434. search={
  435. showSearch
  436. ? {
  437. defaultCollapsed: false,
  438. searchText: "搜索",
  439. }
  440. : false
  441. }
  442. dateFormatter="string"
  443. actionRef={actionTableRef}
  444. toolbar={{
  445. actions: [
  446. <ModalForm
  447. key="addmodal"
  448. title="添加菜单"
  449. open={showAddModal}
  450. trigger={
  451. <Button icon={<PlusOutlined />} type="primary">
  452. 新建
  453. </Button>
  454. }
  455. autoFocusFirstInput
  456. modalProps={{
  457. destroyOnHidden: true,
  458. onCancel: () => {
  459. cancelAddModal();
  460. },
  461. }}
  462. submitTimeout={2000}
  463. onFinish={executeAddData}
  464. >
  465. <ProForm.Group>
  466. <ProFormTreeSelect
  467. width="md"
  468. name="parentId"
  469. initialValue={rowParentId}
  470. label="上级菜单"
  471. placeholder="请选择上级菜单"
  472. rules={[{ required: true, message: "请选择上级菜单" }]}
  473. request={getMenuList}
  474. fieldProps={{
  475. filterTreeNode: true,
  476. showSearch: true,
  477. treeNodeFilterProp: "label",
  478. fieldNames: {
  479. label: "menuName",
  480. value: "menuId",
  481. },
  482. }}
  483. />
  484. </ProForm.Group>
  485. <ProForm.Group>
  486. <ProFormRadio.Group
  487. name="menuType"
  488. width="md"
  489. label="类型"
  490. initialValue="M"
  491. fieldProps={{
  492. onChange: (e: any) => onChangeType(e),
  493. }}
  494. options={[
  495. {
  496. label: "目录",
  497. value: "M",
  498. },
  499. {
  500. label: "菜单",
  501. value: "C",
  502. },
  503. {
  504. label: "按钮",
  505. value: "F",
  506. },
  507. ]}
  508. />
  509. </ProForm.Group>
  510. {(isCatalog || isMenu) && (
  511. <ProForm.Group>
  512. <ProFormSelect
  513. width="md"
  514. name="icon"
  515. label="菜单图标"
  516. fieldProps={{
  517. showSearch,
  518. }}
  519. valueEnum={IconData}
  520. placeholder="请选择菜单图标"
  521. rules={[{ required: true, message: "请选择菜单图标" }]}
  522. />
  523. </ProForm.Group>
  524. )}
  525. <ProForm.Group>
  526. <ProFormText
  527. width="md"
  528. name="menuName"
  529. label="菜单名称"
  530. placeholder="请输入菜单名称"
  531. rules={[{ required: true, message: "请输入菜单名称" }]}
  532. />
  533. <ProFormDigit
  534. fieldProps={{ precision: 0 }}
  535. width="md"
  536. name="orderNum"
  537. initialValue="1"
  538. label="排序"
  539. placeholder="请输入排序"
  540. rules={[{ required: true, message: "请输入排序" }]}
  541. />
  542. </ProForm.Group>
  543. {(isCatalog || isMenu) && (
  544. <ProForm.Group>
  545. <ProFormText
  546. width="md"
  547. name="path"
  548. label="路由地址"
  549. placeholder="请输入路由地址"
  550. rules={[{ required: true, message: "请输入路由地址" }]}
  551. />
  552. <ProFormRadio.Group
  553. name="isFrame"
  554. width="md"
  555. label="是否外链"
  556. initialValue="1"
  557. options={[
  558. {
  559. label: "是",
  560. value: "0",
  561. },
  562. {
  563. label: "否",
  564. value: "1",
  565. },
  566. ]}
  567. />
  568. </ProForm.Group>
  569. )}
  570. {isMenu && (
  571. <ProForm.Group>
  572. <ProFormText
  573. width="md"
  574. name="perms"
  575. label="权限字符"
  576. placeholder="请输入权限字符"
  577. />
  578. </ProForm.Group>
  579. )}
  580. <ProForm.Group>
  581. <ProFormRadio.Group
  582. name="visible"
  583. width="md"
  584. label="显示状态"
  585. initialValue="0"
  586. options={[
  587. {
  588. label: "显示",
  589. value: "0",
  590. },
  591. {
  592. label: "隐藏",
  593. value: "1",
  594. },
  595. ]}
  596. />
  597. <ProFormRadio.Group
  598. name="status"
  599. width="md"
  600. label="菜单状态"
  601. initialValue="0"
  602. options={[
  603. {
  604. label: "正常",
  605. value: "0",
  606. },
  607. {
  608. label: "停用",
  609. value: "1",
  610. },
  611. ]}
  612. />
  613. </ProForm.Group>
  614. </ModalForm>,
  615. <Button
  616. key="expand"
  617. icon={<FontAwesomeIcon icon={faArrowsUpDown} />}
  618. onClick={() => onClickExpandRow()}
  619. >
  620. 折叠/展开
  621. </Button>,
  622. ],
  623. settings: [
  624. {
  625. key: "switch",
  626. icon: showSearch ? (
  627. <FontAwesomeIcon icon={faToggleOn} />
  628. ) : (
  629. <FontAwesomeIcon icon={faToggleOff} />
  630. ),
  631. tooltip: showSearch ? "隐藏搜索栏" : "显示搜索栏",
  632. onClick: (key: string | undefined) => {
  633. setShowSearch(!showSearch);
  634. },
  635. },
  636. {
  637. key: "refresh",
  638. tooltip: "刷新",
  639. icon: <ReloadOutlined />,
  640. onClick: (key: string | undefined) => {
  641. if (actionTableRef.current) {
  642. actionTableRef.current.reload();
  643. }
  644. },
  645. },
  646. ],
  647. }}
  648. />
  649. <ModalForm
  650. key="modifymodal"
  651. title="修改菜单"
  652. formRef={modifyFormRef}
  653. open={isShowModifyDataModal}
  654. autoFocusFirstInput
  655. modalProps={{
  656. destroyOnHidden: true,
  657. onCancel: () => {
  658. setIsShowModifyDataModal(false);
  659. },
  660. }}
  661. submitTimeout={2000}
  662. onFinish={executeModifyData}
  663. >
  664. <ProForm.Group>
  665. <ProFormTreeSelect
  666. width="md"
  667. name="parentId"
  668. initialValue={rowParentId}
  669. label="上级菜单"
  670. placeholder="请选择上级菜单"
  671. rules={[{ required: true, message: "请选择上级菜单" }]}
  672. request={getMenuList}
  673. fieldProps={{
  674. filterTreeNode: true,
  675. showSearch: true,
  676. treeNodeFilterProp: "label",
  677. fieldNames: {
  678. label: "menuName",
  679. value: "menuId",
  680. },
  681. }}
  682. />
  683. </ProForm.Group>
  684. <ProForm.Group>
  685. <ProFormRadio.Group
  686. name="menuType"
  687. width="md"
  688. label="类型"
  689. fieldProps={{
  690. onChange: (e: any) => onChangeType(e),
  691. }}
  692. options={[
  693. {
  694. label: "目录",
  695. value: "M",
  696. },
  697. {
  698. label: "菜单",
  699. value: "C",
  700. },
  701. {
  702. label: "按钮",
  703. value: "F",
  704. },
  705. ]}
  706. />
  707. </ProForm.Group>
  708. {(isCatalog || isMenu) && (
  709. <ProForm.Group>
  710. <ProFormSelect
  711. width="md"
  712. name="icon"
  713. label="菜单图标"
  714. fieldProps={{
  715. showSearch,
  716. }}
  717. valueEnum={IconData}
  718. placeholder="请选择菜单图标"
  719. rules={[{ required: true, message: "请选择菜单图标" }]}
  720. />
  721. </ProForm.Group>
  722. )}
  723. <ProForm.Group>
  724. <ProFormText
  725. width="md"
  726. name="menuName"
  727. label="菜单名称"
  728. placeholder="请输入菜单名称"
  729. rules={[{ required: true, message: "请输入菜单名称" }]}
  730. />
  731. <ProFormDigit
  732. fieldProps={{ precision: 0 }}
  733. width="md"
  734. name="orderNum"
  735. initialValue="1"
  736. label="排序"
  737. placeholder="请输入排序"
  738. rules={[{ required: true, message: "请输入排序" }]}
  739. />
  740. </ProForm.Group>
  741. {(isCatalog || isMenu) && (
  742. <ProForm.Group>
  743. <ProFormText
  744. width="md"
  745. name="path"
  746. label="路由地址"
  747. placeholder="请输入路由地址"
  748. rules={[{ required: true, message: "请输入路由地址" }]}
  749. />
  750. <ProFormRadio.Group
  751. name="isFrame"
  752. width="md"
  753. label="是否外链"
  754. initialValue="1"
  755. options={[
  756. {
  757. label: "是",
  758. value: "0",
  759. },
  760. {
  761. label: "否",
  762. value: "1",
  763. },
  764. ]}
  765. />
  766. </ProForm.Group>
  767. )}
  768. {isMenu && (
  769. <ProForm.Group>
  770. <ProFormText
  771. width="md"
  772. name="perms"
  773. label="权限字符"
  774. placeholder="请输入权限字符"
  775. />
  776. </ProForm.Group>
  777. )}
  778. <ProForm.Group>
  779. <ProFormRadio.Group
  780. name="visible"
  781. width="md"
  782. label="显示状态"
  783. initialValue="0"
  784. options={[
  785. {
  786. label: "显示",
  787. value: "0",
  788. },
  789. {
  790. label: "隐藏",
  791. value: "1",
  792. },
  793. ]}
  794. />
  795. <ProFormRadio.Group
  796. name="status"
  797. width="md"
  798. label="菜单状态"
  799. initialValue="0"
  800. options={[
  801. {
  802. label: "正常",
  803. value: "0",
  804. },
  805. {
  806. label: "停用",
  807. value: "1",
  808. },
  809. ]}
  810. />
  811. </ProForm.Group>
  812. </ModalForm>
  813. {/* 删除确认模态框 */}
  814. <Modal
  815. title={
  816. <div style={{ display: 'flex', alignItems: 'center' }}>
  817. <ExclamationCircleFilled style={{ color: '#faad14', marginRight: 8 }} />
  818. <span>系统提示</span>
  819. </div>
  820. }
  821. open={deleteModalVisible}
  822. onOk={executeDeleteRow}
  823. onCancel={() => {
  824. setDeleteModalVisible(false);
  825. setDeleteRecord(null);
  826. }}
  827. okText="确认"
  828. cancelText="取消"
  829. >
  830. <p>{`确定删除菜单名称为“${deleteRecord?.menuName}”的数据项?`}</p>
  831. </Modal>
  832. </PageContainer>
  833. );
  834. }