buttons.tsx 10 KB

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