index.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. import { addRule, removeRule, rule, updateRule } from '@/services/ant-design-pro/api';
  2. import { PlusOutlined } from '@ant-design/icons';
  3. import type { ActionType, ProColumns, ProDescriptionsItemProps } from '@ant-design/pro-components';
  4. import {
  5. FooterToolbar,
  6. ModalForm,
  7. PageContainer,
  8. ProDescriptions,
  9. ProFormText,
  10. ProFormTextArea,
  11. ProTable,
  12. } from '@ant-design/pro-components';
  13. import { Button, Drawer, Input, message } from 'antd';
  14. import React, { useRef, useState } from 'react';
  15. import { FormattedMessage, useIntl } from 'umi';
  16. import type { FormValueType } from './components/UpdateForm';
  17. import UpdateForm from './components/UpdateForm';
  18. /**
  19. * @en-US Add node
  20. * @zh-CN 添加节点
  21. * @param fields
  22. */
  23. const handleAdd = async (fields: API.RuleListItem) => {
  24. const hide = message.loading('正在添加');
  25. try {
  26. await addRule({ ...fields });
  27. hide();
  28. message.success('Added successfully');
  29. return true;
  30. } catch (error) {
  31. hide();
  32. message.error('Adding failed, please try again!');
  33. return false;
  34. }
  35. };
  36. /**
  37. * @en-US Update node
  38. * @zh-CN 更新节点
  39. *
  40. * @param fields
  41. */
  42. const handleUpdate = async (fields: FormValueType) => {
  43. const hide = message.loading('Configuring');
  44. try {
  45. await updateRule({
  46. name: fields.name,
  47. desc: fields.desc,
  48. key: fields.key,
  49. });
  50. hide();
  51. message.success('Configuration is successful');
  52. return true;
  53. } catch (error) {
  54. hide();
  55. message.error('Configuration failed, please try again!');
  56. return false;
  57. }
  58. };
  59. /**
  60. * Delete node
  61. * @zh-CN 删除节点
  62. *
  63. * @param selectedRows
  64. */
  65. const handleRemove = async (selectedRows: API.RuleListItem[]) => {
  66. const hide = message.loading('正在删除');
  67. if (!selectedRows) return true;
  68. try {
  69. await removeRule({
  70. key: selectedRows.map((row) => row.key),
  71. });
  72. hide();
  73. message.success('Deleted successfully and will refresh soon');
  74. return true;
  75. } catch (error) {
  76. hide();
  77. message.error('Delete failed, please try again');
  78. return false;
  79. }
  80. };
  81. const TableList: React.FC = () => {
  82. /**
  83. * @en-US Pop-up window of new window
  84. * @zh-CN 新建窗口的弹窗
  85. * */
  86. const [createModalVisible, handleModalVisible] = useState<boolean>(false);
  87. /**
  88. * @en-US The pop-up window of the distribution update window
  89. * @zh-CN 分布更新窗口的弹窗
  90. * */
  91. const [updateModalVisible, handleUpdateModalVisible] = useState<boolean>(false);
  92. const [showDetail, setShowDetail] = useState<boolean>(false);
  93. const actionRef = useRef<ActionType>();
  94. const [currentRow, setCurrentRow] = useState<API.RuleListItem>();
  95. const [selectedRowsState, setSelectedRows] = useState<API.RuleListItem[]>([]);
  96. /**
  97. * @en-US International configuration
  98. * @zh-CN 国际化配置
  99. * */
  100. const intl = useIntl();
  101. const columns: ProColumns<API.RuleListItem>[] = [
  102. {
  103. title: (
  104. <FormattedMessage
  105. id="pages.searchTable.updateForm.ruleName.nameLabel"
  106. defaultMessage="Rule name"
  107. />
  108. ),
  109. dataIndex: 'name',
  110. tip: 'The rule name is the unique key',
  111. render: (dom, entity) => {
  112. return (
  113. <a
  114. onClick={() => {
  115. setCurrentRow(entity);
  116. setShowDetail(true);
  117. }}
  118. >
  119. {dom}
  120. </a>
  121. );
  122. },
  123. },
  124. {
  125. title: <FormattedMessage id="pages.searchTable.titleDesc" defaultMessage="Description" />,
  126. dataIndex: 'desc',
  127. valueType: 'textarea',
  128. },
  129. {
  130. title: (
  131. <FormattedMessage
  132. id="pages.searchTable.titleCallNo"
  133. defaultMessage="Number of service calls"
  134. />
  135. ),
  136. dataIndex: 'callNo',
  137. sorter: true,
  138. hideInForm: true,
  139. renderText: (val: string) =>
  140. `${val}${intl.formatMessage({
  141. id: 'pages.searchTable.tenThousand',
  142. defaultMessage: ' 万 ',
  143. })}`,
  144. },
  145. {
  146. title: <FormattedMessage id="pages.searchTable.titleStatus" defaultMessage="Status" />,
  147. dataIndex: 'status',
  148. hideInForm: true,
  149. valueEnum: {
  150. 0: {
  151. text: (
  152. <FormattedMessage
  153. id="pages.searchTable.nameStatus.default"
  154. defaultMessage="Shut down"
  155. />
  156. ),
  157. status: 'Default',
  158. },
  159. 1: {
  160. text: (
  161. <FormattedMessage id="pages.searchTable.nameStatus.running" defaultMessage="Running" />
  162. ),
  163. status: 'Processing',
  164. },
  165. 2: {
  166. text: (
  167. <FormattedMessage id="pages.searchTable.nameStatus.online" defaultMessage="Online" />
  168. ),
  169. status: 'Success',
  170. },
  171. 3: {
  172. text: (
  173. <FormattedMessage
  174. id="pages.searchTable.nameStatus.abnormal"
  175. defaultMessage="Abnormal"
  176. />
  177. ),
  178. status: 'Error',
  179. },
  180. },
  181. },
  182. {
  183. title: (
  184. <FormattedMessage
  185. id="pages.searchTable.titleUpdatedAt"
  186. defaultMessage="Last scheduled time"
  187. />
  188. ),
  189. sorter: true,
  190. dataIndex: 'updatedAt',
  191. valueType: 'dateTime',
  192. renderFormItem: (item, { defaultRender, ...rest }, form) => {
  193. const status = form.getFieldValue('status');
  194. if (`${status}` === '0') {
  195. return false;
  196. }
  197. if (`${status}` === '3') {
  198. return (
  199. <Input
  200. {...rest}
  201. placeholder={intl.formatMessage({
  202. id: 'pages.searchTable.exception',
  203. defaultMessage: 'Please enter the reason for the exception!',
  204. })}
  205. />
  206. );
  207. }
  208. return defaultRender(item);
  209. },
  210. },
  211. {
  212. title: <FormattedMessage id="pages.searchTable.titleOption" defaultMessage="Operating" />,
  213. dataIndex: 'option',
  214. valueType: 'option',
  215. render: (_, record) => [
  216. <a
  217. key="config"
  218. onClick={() => {
  219. handleUpdateModalVisible(true);
  220. setCurrentRow(record);
  221. }}
  222. >
  223. <FormattedMessage id="pages.searchTable.config" defaultMessage="Configuration" />
  224. </a>,
  225. <a key="subscribeAlert" href="https://procomponents.ant.design/">
  226. <FormattedMessage
  227. id="pages.searchTable.subscribeAlert"
  228. defaultMessage="Subscribe to alerts"
  229. />
  230. </a>,
  231. ],
  232. },
  233. ];
  234. return (
  235. <PageContainer>
  236. <ProTable<API.RuleListItem, API.PageParams>
  237. headerTitle={intl.formatMessage({
  238. id: 'pages.searchTable.title',
  239. defaultMessage: 'Enquiry form',
  240. })}
  241. actionRef={actionRef}
  242. rowKey="key"
  243. search={{
  244. labelWidth: 120,
  245. }}
  246. toolBarRender={() => [
  247. <Button
  248. type="primary"
  249. key="primary"
  250. onClick={() => {
  251. handleModalVisible(true);
  252. }}
  253. >
  254. <PlusOutlined /> <FormattedMessage id="pages.searchTable.new" defaultMessage="New" />
  255. </Button>,
  256. ]}
  257. request={rule}
  258. columns={columns}
  259. rowSelection={{
  260. onChange: (_, selectedRows) => {
  261. setSelectedRows(selectedRows);
  262. },
  263. }}
  264. />
  265. {selectedRowsState?.length > 0 && (
  266. <FooterToolbar
  267. extra={
  268. <div>
  269. <FormattedMessage id="pages.searchTable.chosen" defaultMessage="Chosen" />{' '}
  270. <a style={{ fontWeight: 600 }}>{selectedRowsState.length}</a>{' '}
  271. <FormattedMessage id="pages.searchTable.item" defaultMessage="项" />
  272. &nbsp;&nbsp;
  273. <span>
  274. <FormattedMessage
  275. id="pages.searchTable.totalServiceCalls"
  276. defaultMessage="Total number of service calls"
  277. />{' '}
  278. {selectedRowsState.reduce((pre, item) => pre + item.callNo!, 0)}{' '}
  279. <FormattedMessage id="pages.searchTable.tenThousand" defaultMessage="万" />
  280. </span>
  281. </div>
  282. }
  283. >
  284. <Button
  285. onClick={async () => {
  286. await handleRemove(selectedRowsState);
  287. setSelectedRows([]);
  288. actionRef.current?.reloadAndRest?.();
  289. }}
  290. >
  291. <FormattedMessage
  292. id="pages.searchTable.batchDeletion"
  293. defaultMessage="Batch deletion"
  294. />
  295. </Button>
  296. <Button type="primary">
  297. <FormattedMessage
  298. id="pages.searchTable.batchApproval"
  299. defaultMessage="Batch approval"
  300. />
  301. </Button>
  302. </FooterToolbar>
  303. )}
  304. <ModalForm
  305. title={intl.formatMessage({
  306. id: 'pages.searchTable.createForm.newRule',
  307. defaultMessage: 'New rule',
  308. })}
  309. width="400px"
  310. visible={createModalVisible}
  311. onVisibleChange={handleModalVisible}
  312. onFinish={async (value) => {
  313. const success = await handleAdd(value as API.RuleListItem);
  314. if (success) {
  315. handleModalVisible(false);
  316. if (actionRef.current) {
  317. actionRef.current.reload();
  318. }
  319. }
  320. }}
  321. >
  322. <ProFormText
  323. rules={[
  324. {
  325. required: true,
  326. message: (
  327. <FormattedMessage
  328. id="pages.searchTable.ruleName"
  329. defaultMessage="Rule name is required"
  330. />
  331. ),
  332. },
  333. ]}
  334. width="md"
  335. name="name"
  336. />
  337. <ProFormTextArea width="md" name="desc" />
  338. </ModalForm>
  339. <UpdateForm
  340. onSubmit={async (value) => {
  341. const success = await handleUpdate(value);
  342. if (success) {
  343. handleUpdateModalVisible(false);
  344. setCurrentRow(undefined);
  345. if (actionRef.current) {
  346. actionRef.current.reload();
  347. }
  348. }
  349. }}
  350. onCancel={() => {
  351. handleUpdateModalVisible(false);
  352. if (!showDetail) {
  353. setCurrentRow(undefined);
  354. }
  355. }}
  356. updateModalVisible={updateModalVisible}
  357. values={currentRow || {}}
  358. />
  359. <Drawer
  360. width={600}
  361. visible={showDetail}
  362. onClose={() => {
  363. setCurrentRow(undefined);
  364. setShowDetail(false);
  365. }}
  366. closable={false}
  367. >
  368. {currentRow?.name && (
  369. <ProDescriptions<API.RuleListItem>
  370. column={2}
  371. title={currentRow?.name}
  372. request={async () => ({
  373. data: currentRow || {},
  374. })}
  375. params={{
  376. id: currentRow?.name,
  377. }}
  378. columns={columns as ProDescriptionsItemProps<API.RuleListItem>[]}
  379. />
  380. )}
  381. </Drawer>
  382. </PageContainer>
  383. );
  384. };
  385. export default TableList;