index.tsx 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. import { PageContainer } from '@ant-design/pro-components';
  2. import React, { useEffect, useState } from 'react';
  3. import { Button, Card, Form, Input, message, Modal, Space, Table } from 'antd';
  4. import Icon, { PlusCircleOutlined, ReloadOutlined, SearchOutlined } from '@ant-design/icons';
  5. import type { ColumnsType } from 'antd/es/table';
  6. import moment from 'moment/moment';
  7. import Edit from '@/pages/MenuManagement/edit';
  8. import IconMap from '@/components/Icon/IconMap';
  9. import Check from '@/pages/MenuManagement/check';
  10. import { delMenu, queryMenu } from '@/services/menu';
  11. interface DataType {
  12. key: React.ReactNode;
  13. name: string;
  14. menu_type: number;
  15. sequence: number;
  16. hidden: number;
  17. icon: string;
  18. record_id: string;
  19. children?: DataType[];
  20. }
  21. /**
  22. * 菜单管理
  23. * @constructor
  24. */
  25. const MenuManagement: React.FC = () => {
  26. const [loading, setLoading] = useState(false);
  27. const [searchData, setSearchData] = useState<object | null>({});
  28. const [editData, setEditData] = useState(null);
  29. const [form] = Form.useForm();
  30. const [visible, setVisible] = useState(false);
  31. const [dataList, setDataList] = useState([]);
  32. const [tag] = useState('web');
  33. const [checkVisible, setCheckVisible] = useState(false);
  34. const [checkData, setCheckData] = useState<object | null>({});
  35. // 获取列表数据
  36. const getList = () => {
  37. const params: any = {
  38. q: 'tree',
  39. query_all: 1,
  40. ...searchData,
  41. };
  42. queryMenu(params).then((res) => {
  43. if (res && res.code === 0) {
  44. setDataList(res.data.list);
  45. setLoading(false);
  46. }
  47. });
  48. };
  49. // 初始化数据
  50. useEffect(() => {
  51. setLoading(true);
  52. getList();
  53. }, []);
  54. useEffect(() => {
  55. getList();
  56. }, [searchData]);
  57. // 搜索
  58. const onFinish = () => {
  59. form.validateFields().then((data) => {
  60. setLoading(true);
  61. setSearchData(data);
  62. });
  63. };
  64. // 重置
  65. const onReset = () => {
  66. form.resetFields();
  67. setLoading(true);
  68. setSearchData(null);
  69. };
  70. // 新增弹框
  71. const onAdd = () => {
  72. setEditData(null);
  73. setVisible(true);
  74. };
  75. // 打开编辑弹框
  76. const toEdit = (data: any) => {
  77. setEditData(data);
  78. setVisible(true);
  79. };
  80. // 删除
  81. const toDel = (record: any) => {
  82. Modal.confirm({
  83. title: '删除',
  84. content: `确认删除菜单:[${record.name}]`,
  85. onOk: () => {
  86. delMenu(record.record_id)
  87. .then((res) => {
  88. if (res.data && res.data.status === 'OK') {
  89. message.success('删除成功');
  90. getList();
  91. } else {
  92. message.error('删除失败');
  93. }
  94. })
  95. .catch((e) => {
  96. message.error(e?.message);
  97. });
  98. },
  99. });
  100. };
  101. // 编辑弹框回调
  102. const handleEdit = () => {
  103. setVisible(false);
  104. getList();
  105. };
  106. // 查看
  107. const toCheck = (record: any) => {
  108. setCheckVisible(true);
  109. setCheckData(record);
  110. };
  111. // 查看弹框回调
  112. const checkCallback = () => {
  113. setCheckVisible(false);
  114. };
  115. const columns: ColumnsType<DataType> = [
  116. {
  117. title: '序号',
  118. align: 'center',
  119. key: 'index',
  120. render: (_: any, row: any, index: number) => index + 1,
  121. },
  122. {
  123. title: '菜单名称',
  124. dataIndex: 'name',
  125. key: 'name',
  126. },
  127. {
  128. title: '排序值',
  129. dataIndex: 'sequence',
  130. key: 'sequence',
  131. },
  132. {
  133. title: '状态',
  134. dataIndex: 'hidden',
  135. align: 'center',
  136. render: (val) =>
  137. val === 1 ? (
  138. <span style={{ color: '#f50' }}>隐藏</span>
  139. ) : (
  140. <span style={{ color: '#87d068' }}>显示</span>
  141. ),
  142. },
  143. {
  144. title: '图标',
  145. dataIndex: 'icon',
  146. align: 'center',
  147. render: (val) => {
  148. return tag === 'api' ? (
  149. <img src={val} alt="val" style={{ width: 32 }} />
  150. ) : (
  151. <Icon component={IconMap[val] as React.ForwardRefExoticComponent<any>} />
  152. );
  153. },
  154. },
  155. {
  156. title: '访问路由',
  157. dataIndex: 'router',
  158. key: 'router',
  159. },
  160. {
  161. title: '创建时间',
  162. dataIndex: 'created_at',
  163. key: 'created_at',
  164. render: (v) => v && <span>{moment(v).format('YYYY-MM-DD HH:mm')}</span>,
  165. },
  166. {
  167. title: '操作',
  168. key: 'action',
  169. render: (_, record) => (
  170. <Space size="middle">
  171. <a
  172. onClick={() => {
  173. toCheck(record);
  174. }}
  175. >
  176. 查看
  177. </a>
  178. <a
  179. onClick={() => {
  180. toEdit(record);
  181. }}
  182. >
  183. 编辑
  184. </a>
  185. <a
  186. style={{ color: 'red' }}
  187. onClick={() => {
  188. toDel(record);
  189. }}
  190. >
  191. 删除
  192. </a>
  193. </Space>
  194. ),
  195. },
  196. ];
  197. return (
  198. <PageContainer>
  199. <div>
  200. <Card>
  201. <Form form={form} layout="inline" onFinish={onFinish}>
  202. <Form.Item name="name" label="菜单名称">
  203. <Input placeholder="请输入菜单名称" />
  204. </Form.Item>
  205. <Form.Item style={{ marginBottom: '10px' }}>
  206. <Space>
  207. <Button type="primary" htmlType="submit">
  208. <SearchOutlined />
  209. 查询
  210. </Button>
  211. <Button htmlType="button" onClick={onReset}>
  212. <ReloadOutlined />
  213. 重置
  214. </Button>
  215. </Space>
  216. </Form.Item>
  217. </Form>
  218. <Button htmlType="button" type="primary" style={{ margin: '20px 0' }} onClick={onAdd}>
  219. <PlusCircleOutlined />
  220. 新增菜单
  221. </Button>
  222. <Table
  223. columns={columns}
  224. dataSource={dataList}
  225. rowKey={(record) => record.record_id}
  226. loading={loading}
  227. />
  228. {visible && <Edit visible={visible} editCallback={handleEdit} params={editData} />}
  229. {checkVisible && (
  230. <Check visible={checkVisible} checkCallback={checkCallback} params={checkData} />
  231. )}
  232. </Card>
  233. </div>
  234. </PageContainer>
  235. );
  236. };
  237. export default MenuManagement;