buttons.tsx 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. import { Button, Form, Input, message, Modal, Popconfirm, Tooltip } from 'antd';
  2. import { useIntl } from '@@/plugin-locale/localeExports';
  3. import { useCallback, useEffect, useState } from 'react';
  4. import { service } from '@/pages/system/Menu';
  5. import type { ProColumns } from '@jetlinks/pro-table';
  6. import ProTable from '@jetlinks/pro-table';
  7. import { DeleteOutlined, EditOutlined, PlusOutlined, SearchOutlined } from '@ant-design/icons';
  8. import type { MenuButtonInfo, MenuItem } from '@/pages/system/Menu/typing';
  9. import Permission from '@/pages/system/Menu/components/permission';
  10. import { useRequest } from '@@/plugin-request/request';
  11. type ButtonsProps = {
  12. data: MenuItem;
  13. onLoad: () => void;
  14. };
  15. export default (props: ButtonsProps) => {
  16. const intl = useIntl();
  17. const [disabled, setDisabled] = useState(false); // 是否为查看
  18. const [buttonItems, setButtonItems] = useState<MenuButtonInfo[]>([]); // button Table数据源
  19. const [visible, setVisible] = useState(false); // Modal显示影藏
  20. const [id, setId] = useState(''); // 缓存ID
  21. const [form] = Form.useForm();
  22. const { data: permissions, run: queryPermissions } = useRequest(service.queryPermission, {
  23. manual: true,
  24. formatResult: (response) => response.result.data,
  25. });
  26. useEffect(() => {
  27. if (visible) {
  28. // 每次打开Modal获取最新权限
  29. queryPermissions({ paging: false });
  30. }
  31. /* eslint-disable */
  32. }, [visible]);
  33. useEffect(() => {
  34. if (props.data) {
  35. setButtonItems(props.data.buttons || []);
  36. }
  37. }, [props.data]);
  38. const resetForm = () => {
  39. form.resetFields();
  40. setId('');
  41. setDisabled(false);
  42. };
  43. // const filterThree = (e: any) => {
  44. // const _data: any = {
  45. // paging: false,
  46. // };
  47. // if (e.target.value) {
  48. // _data.terms = [{ column: 'name', value: e.target.value }];
  49. // }
  50. // queryPermissions(_data);
  51. // };
  52. /**
  53. * 更新菜单信息
  54. * @param data
  55. */
  56. const updateMenuInfo = useCallback(
  57. async (data: MenuButtonInfo[]) => {
  58. if (props.data.id) {
  59. const response = await service.update({
  60. ...props.data,
  61. buttons: data,
  62. });
  63. if (response.status === 200) {
  64. message.success('操作成功!');
  65. props.onLoad();
  66. resetForm();
  67. setVisible(false);
  68. } else {
  69. message.error('操作失败!');
  70. }
  71. }
  72. /* eslint-disable */
  73. },
  74. [props.data],
  75. );
  76. /**
  77. * 删除单个按钮
  78. */
  79. const deleteItem = useCallback(
  80. (buttonId) => {
  81. const filterButtons = buttonItems.filter((item) => item.id !== buttonId);
  82. setButtonItems(filterButtons);
  83. updateMenuInfo(filterButtons);
  84. /* eslint-disable */
  85. },
  86. [buttonItems],
  87. );
  88. /**
  89. * Model title处理,默认新增
  90. * @default 'pages.data.option.add'
  91. */
  92. const handleTitle = useCallback((): string => {
  93. let intlId = 'pages.data.option.add';
  94. if (disabled && id) {
  95. // 查看
  96. intlId = 'pages.data.option.view';
  97. } else if (!disabled && id) {
  98. // 编辑
  99. intlId = 'pages.data.option.edit';
  100. }
  101. return intl.formatMessage({
  102. id: intlId,
  103. });
  104. /* eslint-disable */
  105. }, [disabled, id]);
  106. /**
  107. * 获取表单数据
  108. */
  109. const saveData = useCallback(async () => {
  110. const formData = await form.validateFields();
  111. if (formData) {
  112. if (buttonItems.some((item) => item.id === formData.id)) {
  113. // 编辑
  114. updateMenuInfo(buttonItems.map((item) => (item.id === formData.id ? formData : item)));
  115. } else {
  116. updateMenuInfo([formData, ...buttonItems]);
  117. }
  118. }
  119. /* eslint-disable */
  120. }, [buttonItems]);
  121. const columns: ProColumns<MenuButtonInfo>[] = [
  122. {
  123. title: intl.formatMessage({
  124. id: 'page.system.menu.encoding',
  125. defaultMessage: '编码',
  126. }),
  127. width: 220,
  128. dataIndex: 'id',
  129. },
  130. {
  131. title: intl.formatMessage({
  132. id: 'page.system.menu.name',
  133. defaultMessage: '名称',
  134. }),
  135. width: 300,
  136. dataIndex: 'name',
  137. },
  138. {
  139. title: intl.formatMessage({
  140. id: 'page.system.menu.describe',
  141. defaultMessage: '备注说明',
  142. }),
  143. dataIndex: 'describe',
  144. // render: (_, row) => () => {
  145. // console.log(row)
  146. // return (<> {row.describe || '-'}</>)
  147. // }
  148. },
  149. {
  150. title: intl.formatMessage({
  151. id: 'pages.data.option',
  152. defaultMessage: '操作',
  153. }),
  154. valueType: 'option',
  155. align: 'center',
  156. width: 240,
  157. render: (_, record) => [
  158. <a
  159. key="edit"
  160. onClick={() => {
  161. form.setFieldsValue(record);
  162. setId(record.id);
  163. setDisabled(false);
  164. setVisible(true);
  165. }}
  166. >
  167. <Tooltip
  168. title={intl.formatMessage({
  169. id: 'pages.data.option.edit',
  170. defaultMessage: '编辑',
  171. })}
  172. >
  173. <EditOutlined />
  174. </Tooltip>
  175. </a>,
  176. <a
  177. key="view"
  178. onClick={() => {
  179. form.setFieldsValue(record);
  180. setId(record.id);
  181. setDisabled(true);
  182. setVisible(true);
  183. }}
  184. >
  185. <Tooltip
  186. title={intl.formatMessage({
  187. id: 'pages.data.option.view',
  188. defaultMessage: '查看',
  189. })}
  190. >
  191. <SearchOutlined />
  192. </Tooltip>
  193. </a>,
  194. <Popconfirm
  195. key="unBindUser"
  196. title={intl.formatMessage({
  197. id: 'page.system.menu.table.delete',
  198. defaultMessage: '是否删除该按钮',
  199. })}
  200. onConfirm={() => {
  201. deleteItem(record.id);
  202. }}
  203. >
  204. <Tooltip
  205. title={intl.formatMessage({
  206. id: 'pages.data.option.delete',
  207. defaultMessage: '删除',
  208. })}
  209. >
  210. <a key="delete">
  211. <DeleteOutlined />
  212. </a>
  213. </Tooltip>
  214. </Popconfirm>,
  215. ],
  216. },
  217. ];
  218. return (
  219. <>
  220. <ProTable<MenuButtonInfo>
  221. columns={columns}
  222. dataSource={buttonItems}
  223. search={false}
  224. pagination={false}
  225. toolBarRender={() => [
  226. <Button
  227. onClick={() => {
  228. if (!props.data) {
  229. message.warning('请先新增菜单基本信息');
  230. return;
  231. }
  232. form.resetFields();
  233. setVisible(true);
  234. }}
  235. key="button"
  236. icon={<PlusOutlined />}
  237. type="primary"
  238. >
  239. {intl.formatMessage({
  240. id: 'pages.data.option.add',
  241. defaultMessage: '新增',
  242. })}
  243. </Button>,
  244. ]}
  245. />
  246. <Modal
  247. maskClosable={false}
  248. width={660}
  249. visible={visible}
  250. title={handleTitle()}
  251. onOk={() => {
  252. saveData();
  253. }}
  254. onCancel={() => {
  255. resetForm();
  256. setVisible(false);
  257. }}
  258. >
  259. <Form form={form} labelCol={{ span: 4 }} wrapperCol={{ span: 20 }}>
  260. <Form.Item
  261. name="id"
  262. label={intl.formatMessage({
  263. id: 'pages.system.org.encoding',
  264. defaultMessage: '编码',
  265. })}
  266. required={true}
  267. rules={[
  268. { required: true, message: '请输入编码' },
  269. { max: 64, message: '最多可输入64个字符' },
  270. {
  271. pattern: /^[a-zA-Z0-9`!@#$%^&*()_+\-={}|\\\]\[;':",.\/<>?]+$/,
  272. message: '请输入英文+数字+特殊字符(`!@#$%^&*()_+-={}|\\][;\':",./<>?)',
  273. },
  274. {
  275. validator: (_, value, callback) => {
  276. if (!(!disabled && id) && buttonItems.some((item) => item.id === value)) {
  277. // 判断是否为新增
  278. callback('重复编码');
  279. }
  280. callback();
  281. },
  282. },
  283. ]}
  284. >
  285. <Input disabled={!!(!disabled && id)} />
  286. </Form.Item>
  287. <Form.Item
  288. name="name"
  289. label={intl.formatMessage({
  290. id: 'pages.table.name',
  291. defaultMessage: '名称',
  292. })}
  293. required={true}
  294. rules={[
  295. { required: true, message: '请输入名称' },
  296. { max: 64, message: '最多可输入64个字符' },
  297. ]}
  298. >
  299. <Input disabled={disabled} />
  300. </Form.Item>
  301. <Form.Item
  302. label={intl.formatMessage({
  303. id: 'page.system.menu.permissions',
  304. defaultMessage: '权限',
  305. })}
  306. required={true}
  307. >
  308. <Form.Item name="permissions" rules={[{ required: true, message: '请选择权限' }]}>
  309. <Permission
  310. title={intl.formatMessage({
  311. id: 'page.system.menu.permissions.operate',
  312. defaultMessage: '操作权限',
  313. })}
  314. disabled={disabled}
  315. data={permissions}
  316. />
  317. </Form.Item>
  318. </Form.Item>
  319. <Form.Item
  320. name="describe"
  321. label={intl.formatMessage({
  322. id: 'pages.table.describe',
  323. defaultMessage: '描述',
  324. })}
  325. >
  326. <Input.TextArea disabled={disabled} />
  327. </Form.Item>
  328. </Form>
  329. </Modal>
  330. </>
  331. );
  332. };