| New file | 
 |  |  | 
 |  |  | import React, { useState, useRef, useEffect } from 'react'; | 
 |  |  | import { | 
 |  |  |     ProForm, | 
 |  |  |     ProFormDigit, | 
 |  |  |     ProFormText, | 
 |  |  |     ProFormSelect, | 
 |  |  |     ProFormDateTimePicker | 
 |  |  | } from '@ant-design/pro-components'; | 
 |  |  | import { Form, Modal } from 'antd'; | 
 |  |  | import { FormattedMessage, useIntl } from '@umijs/max'; | 
 |  |  | import moment from 'moment'; | 
 |  |  | import Http from '@/utils/http'; | 
 |  |  |  | 
 |  |  | const Edit = (props) => { | 
 |  |  |     const intl = useIntl(); | 
 |  |  |     const [form] = Form.useForm(); | 
 |  |  |     const { } = props; | 
 |  |  |  | 
 |  |  |     useEffect(() => { | 
 |  |  |         form.resetFields(); | 
 |  |  |         form.setFieldsValue({ | 
 |  |  |             ...props.values | 
 |  |  |         }) | 
 |  |  |     }, [form, props]) | 
 |  |  |  | 
 |  |  |     const handleCancel = () => { | 
 |  |  |         props.onCancel(); | 
 |  |  |     }; | 
 |  |  |  | 
 |  |  |     const handleOk = () => { | 
 |  |  |         form.submit(); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     const handleFinish = async (values) => { | 
 |  |  |         props.onSubmit({ ...values }); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     return ( | 
 |  |  |         <> | 
 |  |  |             <Modal | 
 |  |  |                 title={ | 
 |  |  |                     Object.keys(props.values).length > 0 | 
 |  |  |                         ? intl.formatMessage({ id: 'page.edit', defaultMessage: '编辑' }) | 
 |  |  |                         : intl.formatMessage({ id: 'page.add', defaultMessage: '添加' }) | 
 |  |  |                 } | 
 |  |  |                 width={640} | 
 |  |  |                 forceRender | 
 |  |  |                 destroyOnClose | 
 |  |  |                 open={props.open} | 
 |  |  |                 onCancel={handleCancel} | 
 |  |  |                 onOk={handleOk} | 
 |  |  |             > | 
 |  |  |                 <ProForm | 
 |  |  |                     form={form} | 
 |  |  |                     submitter={false} | 
 |  |  |                     onFinish={handleFinish} | 
 |  |  |                     layout="horizontal" | 
 |  |  |                     grid={true} | 
 |  |  |                 > | 
 |  |  |                     <ProFormDigit | 
 |  |  |                         name="id" | 
 |  |  |                         disabled | 
 |  |  |                         hidden={true} | 
 |  |  |                     /> | 
 |  |  |                     <ProForm.Group> | 
 |  |  |                         <ProFormText | 
 |  |  |                             name="uuid" | 
 |  |  |                             label="编号" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                         /> | 
 |  |  |                         <ProFormSelect | 
 |  |  |                             name="deviceType" | 
 |  |  |                             label="设备类型" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             fieldProps={{ precision: 0 }} | 
 |  |  |                             showSearch | 
 |  |  |                             debounceTime={300} | 
 |  |  |                             request={async ({ keyWords }) => { | 
 |  |  |                                 const resp = await Http.doPostForm('api/deviceType/query', { condition: keyWords }); | 
 |  |  |                                 return resp.data; | 
 |  |  |                             }} | 
 |  |  |                         /> | 
 |  |  |                     </ProForm.Group> | 
 |  |  |                     <ProForm.Group> | 
 |  |  |                         <ProFormSelect | 
 |  |  |                             name="devicePlc" | 
 |  |  |                             label="PLC类型" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             fieldProps={{ precision: 0 }} | 
 |  |  |                             showSearch | 
 |  |  |                             debounceTime={300} | 
 |  |  |                             request={async ({ keyWords }) => { | 
 |  |  |                                 const resp = await Http.doPostForm('api/devicePlc/query', { condition: keyWords }); | 
 |  |  |                                 return resp.data; | 
 |  |  |                             }} | 
 |  |  |                         /> | 
 |  |  |                         <ProFormText | 
 |  |  |                             name="deviceNo" | 
 |  |  |                             label="设备号" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                         /> | 
 |  |  |                     </ProForm.Group> | 
 |  |  |                     <ProForm.Group> | 
 |  |  |                         <ProFormText | 
 |  |  |                             name="ip" | 
 |  |  |                             label="IP地址" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                         /> | 
 |  |  |                         <ProFormDigit | 
 |  |  |                             name="port" | 
 |  |  |                             label="端口" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             fieldProps={{ precision: 0 }} | 
 |  |  |                         /> | 
 |  |  |                     </ProForm.Group> | 
 |  |  |                     <ProForm.Group> | 
 |  |  |                         <ProFormDigit | 
 |  |  |                             name="rack" | 
 |  |  |                             label="机架号" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             fieldProps={{ precision: 0 }} | 
 |  |  |                         /> | 
 |  |  |                         <ProFormDigit | 
 |  |  |                             name="slot" | 
 |  |  |                             label="槽号" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             fieldProps={{ precision: 0 }} | 
 |  |  |                         /> | 
 |  |  |                     </ProForm.Group> | 
 |  |  |                     <ProForm.Group> | 
 |  |  |                         <ProFormSelect | 
 |  |  |                             name="status" | 
 |  |  |                             label="状态" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             options={[ | 
 |  |  |                                 { label: '正常', value: 1 }, | 
 |  |  |                                 { label: '禁用', value: 0 }, | 
 |  |  |                             ]} | 
 |  |  |                         /> | 
 |  |  |                         <ProFormDateTimePicker | 
 |  |  |                             name="createTime" | 
 |  |  |                             label="添加时间" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             transform={(value) => moment(value).toISOString()} | 
 |  |  |                         /> | 
 |  |  |                     </ProForm.Group> | 
 |  |  |                     <ProForm.Group> | 
 |  |  |                         <ProFormSelect | 
 |  |  |                             name="createBy" | 
 |  |  |                             label="添加人员" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             fieldProps={{ precision: 0 }} | 
 |  |  |                             showSearch | 
 |  |  |                             debounceTime={300} | 
 |  |  |                             request={async ({ keyWords }) => { | 
 |  |  |                                 const resp = await Http.doPostForm('api/user/query', { condition: keyWords }); | 
 |  |  |                                 return resp.data; | 
 |  |  |                             }} | 
 |  |  |                         /> | 
 |  |  |                         <ProFormDateTimePicker | 
 |  |  |                             name="updateTime" | 
 |  |  |                             label="修改时间" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             transform={(value) => moment(value).toISOString()} | 
 |  |  |                         /> | 
 |  |  |                     </ProForm.Group> | 
 |  |  |                     <ProForm.Group> | 
 |  |  |                         <ProFormSelect | 
 |  |  |                             name="updateBy" | 
 |  |  |                             label="修改人员" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             fieldProps={{ precision: 0 }} | 
 |  |  |                             showSearch | 
 |  |  |                             debounceTime={300} | 
 |  |  |                             request={async ({ keyWords }) => { | 
 |  |  |                                 const resp = await Http.doPostForm('api/user/query', { condition: keyWords }); | 
 |  |  |                                 return resp.data; | 
 |  |  |                             }} | 
 |  |  |                         /> | 
 |  |  |                         <ProFormText | 
 |  |  |                             name="memo" | 
 |  |  |                             label="备注" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                         /> | 
 |  |  |                     </ProForm.Group> | 
 |  |  |  | 
 |  |  |                 </ProForm> | 
 |  |  |             </Modal> | 
 |  |  |         </> | 
 |  |  |     ) | 
 |  |  | } | 
 |  |  |  | 
 |  |  | export default Edit; | 
 
| New file | 
 |  |  | 
 |  |  |  | 
 |  |  | import React, { useState, useRef, useEffect } from 'react'; | 
 |  |  | import { Button, message, Modal, Tag  } from 'antd'; | 
 |  |  | import { | 
 |  |  |     FooterToolbar, | 
 |  |  |     PageContainer, | 
 |  |  |     ProTable, | 
 |  |  |     LightFilter, | 
 |  |  | } from '@ant-design/pro-components'; | 
 |  |  | import { FormattedMessage, useIntl } from '@umijs/max'; | 
 |  |  | import { PlusOutlined, ExportOutlined } from '@ant-design/icons'; | 
 |  |  | import Http from '@/utils/http'; | 
 |  |  | import Edit from './components/edit' | 
 |  |  | import { TextFilter, SelectFilter, DatetimeRangeFilter, LinkFilter } from '@/components/TableSearch' | 
 |  |  | import { statusMap } from '@/utils/enum-util' | 
 |  |  | import { repairBug } from '@/utils/common-util'; | 
 |  |  |  | 
 |  |  | const TABLE_KEY = 'pro-table-device'; | 
 |  |  |  | 
 |  |  | const handleSave = async (val, intl) => { | 
 |  |  |     const hide = message.loading(intl.formatMessage({ id: 'page.adding', defaultMessage: '正在添加' })); | 
 |  |  |     try { | 
 |  |  |         const resp = await Http.doPost('api/device/save', val); | 
 |  |  |         if (resp.code === 200) { | 
 |  |  |             message.success(intl.formatMessage({ id: 'page.add.success', defaultMessage: '添加成功' })); | 
 |  |  |             return true; | 
 |  |  |         } else { | 
 |  |  |             message.error(resp.msg); | 
 |  |  |             return false; | 
 |  |  |         } | 
 |  |  |     } catch (error) { | 
 |  |  |         message.error(intl.formatMessage({ id: 'page.add.fail', defaultMessage: '添加失败请重试!' })); | 
 |  |  |         return false; | 
 |  |  |     } finally { | 
 |  |  |         hide(); | 
 |  |  |     } | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | const handleUpdate = async (val, intl) => { | 
 |  |  |     const hide = message.loading(intl.formatMessage({ id: 'page.updating', defaultMessage: '正在更新' })); | 
 |  |  |     try { | 
 |  |  |         const resp = await Http.doPost('api/device/update', val); | 
 |  |  |         if (resp.code === 200) { | 
 |  |  |             message.success(intl.formatMessage({ id: 'page.update.success', defaultMessage: '更新成功' })); | 
 |  |  |             return true; | 
 |  |  |         } else { | 
 |  |  |             message.error(resp.msg); | 
 |  |  |             return false; | 
 |  |  |         } | 
 |  |  |     } catch (error) { | 
 |  |  |         message.error(intl.formatMessage({ id: 'page.update.fail', defaultMessage: '更新失败请重试!' })); | 
 |  |  |         return false; | 
 |  |  |     } finally { | 
 |  |  |         hide(); | 
 |  |  |     } | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | const handleRemove = async (rows, intl) => { | 
 |  |  |     if (!rows) return true; | 
 |  |  |     const hide = message.loading(intl.formatMessage({ id: 'page.deleting', defaultMessage: '正在删除' })); | 
 |  |  |     try { | 
 |  |  |         const resp = await Http.doPost('api/device/remove/' + rows.map((row) => row.id).join(',')); | 
 |  |  |         if (resp.code === 200) { | 
 |  |  |             message.success(intl.formatMessage({ id: 'page.delete.success', defaultMessage: '删除成功' })); | 
 |  |  |             return true; | 
 |  |  |         } else { | 
 |  |  |             message.error(resp.msg); | 
 |  |  |             return false; | 
 |  |  |         } | 
 |  |  |     } catch (error) { | 
 |  |  |         message.error(intl.formatMessage({ id: 'page.delete.fail', defaultMessage: '删除失败,请重试!' })); | 
 |  |  |         return false; | 
 |  |  |     } finally { | 
 |  |  |         hide(); | 
 |  |  |     } | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | const handleExport = async (intl) => { | 
 |  |  |     const hide = message.loading(intl.formatMessage({ id: 'page.exporting', defaultMessage: '正在导出' })); | 
 |  |  |     try { | 
 |  |  |         const resp = await Http.doPostBlob('api/device/export'); | 
 |  |  |         const blob = new Blob([resp], { type: 'application/vnd.ms-excel' }); | 
 |  |  |         window.location.href = window.URL.createObjectURL(blob); | 
 |  |  |         message.success(intl.formatMessage({ id: 'page.export.success', defaultMessage: '导出成功' })); | 
 |  |  |         return true; | 
 |  |  |     } catch (error) { | 
 |  |  |         message.error(intl.formatMessage({ id: 'page.export.fail', defaultMessage: '导出失败,请重试' })); | 
 |  |  |         return false; | 
 |  |  |     } finally { | 
 |  |  |         hide(); | 
 |  |  |     } | 
 |  |  | }; | 
 |  |  |  | 
 |  |  |  | 
 |  |  | const Main = () => { | 
 |  |  |     const intl = useIntl(); | 
 |  |  |     const formTableRef = useRef(); | 
 |  |  |     const actionRef = useRef(); | 
 |  |  |     const [selectedRows, setSelectedRows] = useState([]); | 
 |  |  |     const [modalVisible, setModalVisible] = useState(false); | 
 |  |  |     const [currentRow, setCurrentRow] = useState(); | 
 |  |  |     const [searchParam, setSearchParam] = useState({}); | 
 |  |  |  | 
 |  |  |     useEffect(() => { | 
 |  |  |  | 
 |  |  |     }, []); | 
 |  |  |  | 
 |  |  |     const columns = [ | 
 |  |  |         { | 
 |  |  |             title: intl.formatMessage({ | 
 |  |  |                 id: 'page.table.no', | 
 |  |  |                 defaultMessage: 'No' | 
 |  |  |             }), | 
 |  |  |             dataIndex: 'index', | 
 |  |  |             valueType: 'indexBorder', | 
 |  |  |             width: 48, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '编号', | 
 |  |  |             dataIndex: 'uuid', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <TextFilter | 
 |  |  |                 name='uuid' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '设备类型', | 
 |  |  |             dataIndex: 'deviceType$', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <LinkFilter | 
 |  |  |                 name='deviceType' | 
 |  |  |                 major='deviceType' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: 'PLC类型', | 
 |  |  |             dataIndex: 'devicePlc$', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <LinkFilter | 
 |  |  |                 name='devicePlc' | 
 |  |  |                 major='devicePlc' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '设备号', | 
 |  |  |             dataIndex: 'deviceNo', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             copyable: true, | 
 |  |  |             filterDropdown: (props) => <TextFilter | 
 |  |  |                 name='deviceNo' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: 'IP地址', | 
 |  |  |             dataIndex: 'ip', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <TextFilter | 
 |  |  |                 name='ip' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '端口', | 
 |  |  |             dataIndex: 'port', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <TextFilter | 
 |  |  |                 name='port' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '机架号', | 
 |  |  |             dataIndex: 'rack', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <TextFilter | 
 |  |  |                 name='rack' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '槽号', | 
 |  |  |             dataIndex: 'slot', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <TextFilter | 
 |  |  |                 name='slot' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '状态', | 
 |  |  |             dataIndex: 'status$', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <SelectFilter | 
 |  |  |                 name='status' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |                 data={[ | 
 |  |  |                     { label: '正常', value: 1 }, | 
 |  |  |                     { label: '禁用', value: 0 }, | 
 |  |  |                 ]} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '添加时间', | 
 |  |  |             dataIndex: 'createTime$', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <DatetimeRangeFilter | 
 |  |  |                 name='createTime' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '添加人员', | 
 |  |  |             dataIndex: 'createBy$', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <LinkFilter | 
 |  |  |                 name='createBy' | 
 |  |  |                 major='user' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '修改时间', | 
 |  |  |             dataIndex: 'updateTime$', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <DatetimeRangeFilter | 
 |  |  |                 name='updateTime' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '修改人员', | 
 |  |  |             dataIndex: 'updateBy$', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <LinkFilter | 
 |  |  |                 name='updateBy' | 
 |  |  |                 major='user' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '备注', | 
 |  |  |             dataIndex: 'memo', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <TextFilter | 
 |  |  |                 name='memo' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |  | 
 |  |  |         { | 
 |  |  |             title: '操作', | 
 |  |  |             dataIndex: 'option', | 
 |  |  |             width: 140, | 
 |  |  |             valueType: 'option', | 
 |  |  |             render: (_, record) => [ | 
 |  |  |                 <Button | 
 |  |  |                     type="link" | 
 |  |  |                     key="edit" | 
 |  |  |                     onClick={() => { | 
 |  |  |                         setModalVisible(true); | 
 |  |  |                         setCurrentRow(record); | 
 |  |  |                     }} | 
 |  |  |                 > | 
 |  |  |                     <FormattedMessage id='page.edit' defaultMessage='编辑' /> | 
 |  |  |                 </Button>, | 
 |  |  |                 <Button | 
 |  |  |                     type="link" | 
 |  |  |                     danger | 
 |  |  |                     key="batchRemove" | 
 |  |  |                     onClick={async () => { | 
 |  |  |                         Modal.confirm({ | 
 |  |  |                             title: intl.formatMessage({ id: 'page.delete', defaultMessage: '删除' }), | 
 |  |  |                             content: intl.formatMessage({ id: 'page.delete.confirm', defaultMessage: '确定删除该项吗?' }), | 
 |  |  |                             onOk: async () => { | 
 |  |  |                                 const success = await handleRemove([record], intl); | 
 |  |  |                                 if (success) { | 
 |  |  |                                     if (actionRef.current) { | 
 |  |  |                                         actionRef.current.reload(); | 
 |  |  |                                     } | 
 |  |  |                                 } | 
 |  |  |                             }, | 
 |  |  |                         }); | 
 |  |  |                     }} | 
 |  |  |                 > | 
 |  |  |                     <FormattedMessage id='page.delete' defaultMessage='删除' /> | 
 |  |  |                 </Button>, | 
 |  |  |             ], | 
 |  |  |         }, | 
 |  |  |     ]; | 
 |  |  |  | 
 |  |  |     return ( | 
 |  |  |         <PageContainer | 
 |  |  |             header={{ | 
 |  |  |                 breadcrumb: {}, | 
 |  |  |             }} | 
 |  |  |         > | 
 |  |  |             <div style={{ width: '100%', float: 'right' }}> | 
 |  |  |                 <ProTable | 
 |  |  |                     key="device" | 
 |  |  |                     rowKey="id" | 
 |  |  |                     actionRef={actionRef} | 
 |  |  |                     formRef={formTableRef} | 
 |  |  |                     columns={columns} | 
 |  |  |                     cardBordered | 
 |  |  |                     scroll={{ x: 1300 }} | 
 |  |  |                     dateFormatter="string" | 
 |  |  |                     pagination={{ pageSize: 16 }} | 
 |  |  |                     search={false} | 
 |  |  |                     toolbar={{ | 
 |  |  |                         search: { | 
 |  |  |                             onSearch: (value) => { | 
 |  |  |                                 setSearchParam(prevState => ({ | 
 |  |  |                                     ...prevState, | 
 |  |  |                                     condition: value | 
 |  |  |                                 })); | 
 |  |  |                                 actionRef.current?.reload(); | 
 |  |  |                             }, | 
 |  |  |                         }, | 
 |  |  |                         filter: ( | 
 |  |  |                             <LightFilter | 
 |  |  |                                 onValuesChange={(val) => { | 
 |  |  |                                 }} | 
 |  |  |                             > | 
 |  |  |                             </LightFilter> | 
 |  |  |                         ), | 
 |  |  |                         actions: [ | 
 |  |  |                             <Button | 
 |  |  |                                 type="primary" | 
 |  |  |                                 key="save" | 
 |  |  |                                 onClick={async () => { | 
 |  |  |                                     setModalVisible(true) | 
 |  |  |                                 }} | 
 |  |  |                             > | 
 |  |  |                                 <PlusOutlined /> | 
 |  |  |                                 <FormattedMessage id='page.add' defaultMessage='添加' /> | 
 |  |  |                             </Button>, | 
 |  |  |                             <Button | 
 |  |  |                                 key="export" | 
 |  |  |                                 onClick={async () => { | 
 |  |  |                                     handleExport(intl); | 
 |  |  |                                 }} | 
 |  |  |                             > | 
 |  |  |                                 <ExportOutlined /> | 
 |  |  |                                 <FormattedMessage id='page.export' defaultMessage='导出' /> | 
 |  |  |                             </Button>, | 
 |  |  |                         ], | 
 |  |  |                     }} | 
 |  |  |                     request={(params, sorter, filter) => | 
 |  |  |                         Http.doPostPromise('/api/device/page', { ...params, ...searchParam }, (res) => { | 
 |  |  |                             return { | 
 |  |  |                                 data: res.data.records, | 
 |  |  |                                 total: res.data.total, | 
 |  |  |                                 success: true, | 
 |  |  |                             } | 
 |  |  |                         }) | 
 |  |  |                     } | 
 |  |  |                     rowSelection={{ | 
 |  |  |                         onChange: (ids, rows) => { | 
 |  |  |                             setSelectedRows(rows); | 
 |  |  |                         } | 
 |  |  |                     }} | 
 |  |  |                     columnsState={{ | 
 |  |  |                         persistenceKey: TABLE_KEY, | 
 |  |  |                         persistenceType: 'localStorage', | 
 |  |  |                         defaultValue: { | 
 |  |  |                             // memo: { show: repairBug(TABLE_KEY, 'memo', false) }, | 
 |  |  |                             option: { fixed: 'right', disable: true }, | 
 |  |  |                         }, | 
 |  |  |                         onChange(value) { | 
 |  |  |                         }, | 
 |  |  |                     }} | 
 |  |  |                 /> | 
 |  |  |             </div> | 
 |  |  |  | 
 |  |  |             {selectedRows?.length > 0 && ( | 
 |  |  |                 <FooterToolbar | 
 |  |  |                     extra={ | 
 |  |  |                         <div> | 
 |  |  |                             <a style={{ fontWeight: 600 }}>{selectedRows.length}</a> | 
 |  |  |                             <FormattedMessage id='page.selected' defaultMessage=' 项已选择' /> | 
 |  |  |                         </div> | 
 |  |  |                     } | 
 |  |  |                 > | 
 |  |  |                     <Button | 
 |  |  |                         key="remove" | 
 |  |  |                         danger | 
 |  |  |                         onClick={async () => { | 
 |  |  |                             Modal.confirm({ | 
 |  |  |                                 title: intl.formatMessage({ id: 'page.delete', defaultMessage: '删除' }), | 
 |  |  |                                 content: intl.formatMessage({ id: 'page.delete.confirm', defaultMessage: '确定删除该项吗?' }), | 
 |  |  |                                 onOk: async () => { | 
 |  |  |                                     const success = await handleRemove(selectedRows, intl); | 
 |  |  |                                     if (success) { | 
 |  |  |                                         setSelectedRows([]); | 
 |  |  |                                         actionRef.current?.reloadAndRest?.(); | 
 |  |  |                                     } | 
 |  |  |                                 }, | 
 |  |  |                             }); | 
 |  |  |                         }} | 
 |  |  |                     > | 
 |  |  |                         <FormattedMessage id='page.delete.batch' defaultMessage='批量删除' /> | 
 |  |  |                     </Button> | 
 |  |  |                 </FooterToolbar> | 
 |  |  |             )} | 
 |  |  |  | 
 |  |  |             <Edit | 
 |  |  |                 open={modalVisible} | 
 |  |  |                 values={currentRow || {}} | 
 |  |  |                 onCancel={ | 
 |  |  |                     () => { | 
 |  |  |                         setModalVisible(false); | 
 |  |  |                         setCurrentRow(undefined); | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |                 onSubmit={async (values) => { | 
 |  |  |                     let ok = false; | 
 |  |  |                     if (values.id) { | 
 |  |  |                         ok = await handleUpdate({ ...values }, intl) | 
 |  |  |                     } else { | 
 |  |  |                         ok = await handleSave({ ...values }, intl) | 
 |  |  |                     } | 
 |  |  |                     if (ok) { | 
 |  |  |                         setModalVisible(false); | 
 |  |  |                         setCurrentRow(undefined); | 
 |  |  |                         if (actionRef.current) { | 
 |  |  |                             actionRef.current.reload(); | 
 |  |  |                         } | 
 |  |  |                     } | 
 |  |  |                 }} | 
 |  |  |             /> | 
 |  |  |         </PageContainer> | 
 |  |  |     ); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | export default Main; | 
 
| New file | 
 |  |  | 
 |  |  | import React, { useState, useRef, useEffect } from 'react'; | 
 |  |  | import { | 
 |  |  |     ProForm, | 
 |  |  |     ProFormDigit, | 
 |  |  |     ProFormText, | 
 |  |  |     ProFormSelect, | 
 |  |  |     ProFormDateTimePicker | 
 |  |  | } from '@ant-design/pro-components'; | 
 |  |  | import { Form, Modal } from 'antd'; | 
 |  |  | import { FormattedMessage, useIntl } from '@umijs/max'; | 
 |  |  | import moment from 'moment'; | 
 |  |  | import Http from '@/utils/http'; | 
 |  |  |  | 
 |  |  | const Edit = (props) => { | 
 |  |  |     const intl = useIntl(); | 
 |  |  |     const [form] = Form.useForm(); | 
 |  |  |     const { } = props; | 
 |  |  |  | 
 |  |  |     useEffect(() => { | 
 |  |  |         form.resetFields(); | 
 |  |  |         form.setFieldsValue({ | 
 |  |  |             ...props.values | 
 |  |  |         }) | 
 |  |  |     }, [form, props]) | 
 |  |  |  | 
 |  |  |     const handleCancel = () => { | 
 |  |  |         props.onCancel(); | 
 |  |  |     }; | 
 |  |  |  | 
 |  |  |     const handleOk = () => { | 
 |  |  |         form.submit(); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     const handleFinish = async (values) => { | 
 |  |  |         props.onSubmit({ ...values }); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     return ( | 
 |  |  |         <> | 
 |  |  |             <Modal | 
 |  |  |                 title={ | 
 |  |  |                     Object.keys(props.values).length > 0 | 
 |  |  |                         ? intl.formatMessage({ id: 'page.edit', defaultMessage: '编辑' }) | 
 |  |  |                         : intl.formatMessage({ id: 'page.add', defaultMessage: '添加' }) | 
 |  |  |                 } | 
 |  |  |                 width={640} | 
 |  |  |                 forceRender | 
 |  |  |                 destroyOnClose | 
 |  |  |                 open={props.open} | 
 |  |  |                 onCancel={handleCancel} | 
 |  |  |                 onOk={handleOk} | 
 |  |  |             > | 
 |  |  |                 <ProForm | 
 |  |  |                     form={form} | 
 |  |  |                     submitter={false} | 
 |  |  |                     onFinish={handleFinish} | 
 |  |  |                     layout="horizontal" | 
 |  |  |                     grid={true} | 
 |  |  |                 > | 
 |  |  |                     <ProFormDigit | 
 |  |  |                         name="id" | 
 |  |  |                         disabled | 
 |  |  |                         hidden={true} | 
 |  |  |                     /> | 
 |  |  |                     <ProForm.Group> | 
 |  |  |                         <ProFormText | 
 |  |  |                             name="uuid" | 
 |  |  |                             label="编号" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                         /> | 
 |  |  |                         <ProFormText | 
 |  |  |                             name="name" | 
 |  |  |                             label="名称" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                         /> | 
 |  |  |                     </ProForm.Group> | 
 |  |  |                     <ProForm.Group> | 
 |  |  |                         <ProFormText | 
 |  |  |                             name="flag" | 
 |  |  |                             label="标识" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                         /> | 
 |  |  |                         <ProFormSelect | 
 |  |  |                             name="status" | 
 |  |  |                             label="状态" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             options={[ | 
 |  |  |                                 { label: '正常', value: 1 }, | 
 |  |  |                                 { label: '禁用', value: 0 }, | 
 |  |  |                             ]} | 
 |  |  |                         /> | 
 |  |  |                     </ProForm.Group> | 
 |  |  |                     <ProForm.Group> | 
 |  |  |                         <ProFormDateTimePicker | 
 |  |  |                             name="createTime" | 
 |  |  |                             label="添加时间" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             transform={(value) => moment(value).toISOString()} | 
 |  |  |                         /> | 
 |  |  |                         <ProFormSelect | 
 |  |  |                             name="createBy" | 
 |  |  |                             label="添加人员" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             fieldProps={{ precision: 0 }} | 
 |  |  |                             showSearch | 
 |  |  |                             debounceTime={300} | 
 |  |  |                             request={async ({ keyWords }) => { | 
 |  |  |                                 const resp = await Http.doPostForm('api/user/query', { condition: keyWords }); | 
 |  |  |                                 return resp.data; | 
 |  |  |                             }} | 
 |  |  |                         /> | 
 |  |  |                     </ProForm.Group> | 
 |  |  |                     <ProForm.Group> | 
 |  |  |                         <ProFormDateTimePicker | 
 |  |  |                             name="updateTime" | 
 |  |  |                             label="修改时间" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             transform={(value) => moment(value).toISOString()} | 
 |  |  |                         /> | 
 |  |  |                         <ProFormSelect | 
 |  |  |                             name="updateBy" | 
 |  |  |                             label="修改人员" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             fieldProps={{ precision: 0 }} | 
 |  |  |                             showSearch | 
 |  |  |                             debounceTime={300} | 
 |  |  |                             request={async ({ keyWords }) => { | 
 |  |  |                                 const resp = await Http.doPostForm('api/user/query', { condition: keyWords }); | 
 |  |  |                                 return resp.data; | 
 |  |  |                             }} | 
 |  |  |                         /> | 
 |  |  |                     </ProForm.Group> | 
 |  |  |                     <ProForm.Group> | 
 |  |  |                         <ProFormText | 
 |  |  |                             name="memo" | 
 |  |  |                             label="备注" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                         /> | 
 |  |  |                     </ProForm.Group> | 
 |  |  |  | 
 |  |  |                 </ProForm> | 
 |  |  |             </Modal> | 
 |  |  |         </> | 
 |  |  |     ) | 
 |  |  | } | 
 |  |  |  | 
 |  |  | export default Edit; | 
 
| New file | 
 |  |  | 
 |  |  |  | 
 |  |  | import React, { useState, useRef, useEffect } from 'react'; | 
 |  |  | import { Button, message, Modal, Tag  } from 'antd'; | 
 |  |  | import { | 
 |  |  |     FooterToolbar, | 
 |  |  |     PageContainer, | 
 |  |  |     ProTable, | 
 |  |  |     LightFilter, | 
 |  |  | } from '@ant-design/pro-components'; | 
 |  |  | import { FormattedMessage, useIntl } from '@umijs/max'; | 
 |  |  | import { PlusOutlined, ExportOutlined } from '@ant-design/icons'; | 
 |  |  | import Http from '@/utils/http'; | 
 |  |  | import Edit from './components/edit' | 
 |  |  | import { TextFilter, SelectFilter, DatetimeRangeFilter, LinkFilter } from '@/components/TableSearch' | 
 |  |  | import { statusMap } from '@/utils/enum-util' | 
 |  |  | import { repairBug } from '@/utils/common-util'; | 
 |  |  |  | 
 |  |  | const TABLE_KEY = 'pro-table-devicePlc'; | 
 |  |  |  | 
 |  |  | const handleSave = async (val, intl) => { | 
 |  |  |     const hide = message.loading(intl.formatMessage({ id: 'page.adding', defaultMessage: '正在添加' })); | 
 |  |  |     try { | 
 |  |  |         const resp = await Http.doPost('api/devicePlc/save', val); | 
 |  |  |         if (resp.code === 200) { | 
 |  |  |             message.success(intl.formatMessage({ id: 'page.add.success', defaultMessage: '添加成功' })); | 
 |  |  |             return true; | 
 |  |  |         } else { | 
 |  |  |             message.error(resp.msg); | 
 |  |  |             return false; | 
 |  |  |         } | 
 |  |  |     } catch (error) { | 
 |  |  |         message.error(intl.formatMessage({ id: 'page.add.fail', defaultMessage: '添加失败请重试!' })); | 
 |  |  |         return false; | 
 |  |  |     } finally { | 
 |  |  |         hide(); | 
 |  |  |     } | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | const handleUpdate = async (val, intl) => { | 
 |  |  |     const hide = message.loading(intl.formatMessage({ id: 'page.updating', defaultMessage: '正在更新' })); | 
 |  |  |     try { | 
 |  |  |         const resp = await Http.doPost('api/devicePlc/update', val); | 
 |  |  |         if (resp.code === 200) { | 
 |  |  |             message.success(intl.formatMessage({ id: 'page.update.success', defaultMessage: '更新成功' })); | 
 |  |  |             return true; | 
 |  |  |         } else { | 
 |  |  |             message.error(resp.msg); | 
 |  |  |             return false; | 
 |  |  |         } | 
 |  |  |     } catch (error) { | 
 |  |  |         message.error(intl.formatMessage({ id: 'page.update.fail', defaultMessage: '更新失败请重试!' })); | 
 |  |  |         return false; | 
 |  |  |     } finally { | 
 |  |  |         hide(); | 
 |  |  |     } | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | const handleRemove = async (rows, intl) => { | 
 |  |  |     if (!rows) return true; | 
 |  |  |     const hide = message.loading(intl.formatMessage({ id: 'page.deleting', defaultMessage: '正在删除' })); | 
 |  |  |     try { | 
 |  |  |         const resp = await Http.doPost('api/devicePlc/remove/' + rows.map((row) => row.id).join(',')); | 
 |  |  |         if (resp.code === 200) { | 
 |  |  |             message.success(intl.formatMessage({ id: 'page.delete.success', defaultMessage: '删除成功' })); | 
 |  |  |             return true; | 
 |  |  |         } else { | 
 |  |  |             message.error(resp.msg); | 
 |  |  |             return false; | 
 |  |  |         } | 
 |  |  |     } catch (error) { | 
 |  |  |         message.error(intl.formatMessage({ id: 'page.delete.fail', defaultMessage: '删除失败,请重试!' })); | 
 |  |  |         return false; | 
 |  |  |     } finally { | 
 |  |  |         hide(); | 
 |  |  |     } | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | const handleExport = async (intl) => { | 
 |  |  |     const hide = message.loading(intl.formatMessage({ id: 'page.exporting', defaultMessage: '正在导出' })); | 
 |  |  |     try { | 
 |  |  |         const resp = await Http.doPostBlob('api/devicePlc/export'); | 
 |  |  |         const blob = new Blob([resp], { type: 'application/vnd.ms-excel' }); | 
 |  |  |         window.location.href = window.URL.createObjectURL(blob); | 
 |  |  |         message.success(intl.formatMessage({ id: 'page.export.success', defaultMessage: '导出成功' })); | 
 |  |  |         return true; | 
 |  |  |     } catch (error) { | 
 |  |  |         message.error(intl.formatMessage({ id: 'page.export.fail', defaultMessage: '导出失败,请重试' })); | 
 |  |  |         return false; | 
 |  |  |     } finally { | 
 |  |  |         hide(); | 
 |  |  |     } | 
 |  |  | }; | 
 |  |  |  | 
 |  |  |  | 
 |  |  | const Main = () => { | 
 |  |  |     const intl = useIntl(); | 
 |  |  |     const formTableRef = useRef(); | 
 |  |  |     const actionRef = useRef(); | 
 |  |  |     const [selectedRows, setSelectedRows] = useState([]); | 
 |  |  |     const [modalVisible, setModalVisible] = useState(false); | 
 |  |  |     const [currentRow, setCurrentRow] = useState(); | 
 |  |  |     const [searchParam, setSearchParam] = useState({}); | 
 |  |  |  | 
 |  |  |     useEffect(() => { | 
 |  |  |  | 
 |  |  |     }, []); | 
 |  |  |  | 
 |  |  |     const columns = [ | 
 |  |  |         { | 
 |  |  |             title: intl.formatMessage({ | 
 |  |  |                 id: 'page.table.no', | 
 |  |  |                 defaultMessage: 'No' | 
 |  |  |             }), | 
 |  |  |             dataIndex: 'index', | 
 |  |  |             valueType: 'indexBorder', | 
 |  |  |             width: 48, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '编号', | 
 |  |  |             dataIndex: 'uuid', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <TextFilter | 
 |  |  |                 name='uuid' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '名称', | 
 |  |  |             dataIndex: 'name', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             copyable: true, | 
 |  |  |             filterDropdown: (props) => <TextFilter | 
 |  |  |                 name='name' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '标识', | 
 |  |  |             dataIndex: 'flag', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <TextFilter | 
 |  |  |                 name='flag' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '状态', | 
 |  |  |             dataIndex: 'status$', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <SelectFilter | 
 |  |  |                 name='status' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |                 data={[ | 
 |  |  |                     { label: '正常', value: 1 }, | 
 |  |  |                     { label: '禁用', value: 0 }, | 
 |  |  |                 ]} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '添加时间', | 
 |  |  |             dataIndex: 'createTime$', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <DatetimeRangeFilter | 
 |  |  |                 name='createTime' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '添加人员', | 
 |  |  |             dataIndex: 'createBy$', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <LinkFilter | 
 |  |  |                 name='createBy' | 
 |  |  |                 major='user' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '修改时间', | 
 |  |  |             dataIndex: 'updateTime$', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <DatetimeRangeFilter | 
 |  |  |                 name='updateTime' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '修改人员', | 
 |  |  |             dataIndex: 'updateBy$', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <LinkFilter | 
 |  |  |                 name='updateBy' | 
 |  |  |                 major='user' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '备注', | 
 |  |  |             dataIndex: 'memo', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <TextFilter | 
 |  |  |                 name='memo' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |  | 
 |  |  |         { | 
 |  |  |             title: '操作', | 
 |  |  |             dataIndex: 'option', | 
 |  |  |             width: 140, | 
 |  |  |             valueType: 'option', | 
 |  |  |             render: (_, record) => [ | 
 |  |  |                 <Button | 
 |  |  |                     type="link" | 
 |  |  |                     key="edit" | 
 |  |  |                     onClick={() => { | 
 |  |  |                         setModalVisible(true); | 
 |  |  |                         setCurrentRow(record); | 
 |  |  |                     }} | 
 |  |  |                 > | 
 |  |  |                     <FormattedMessage id='page.edit' defaultMessage='编辑' /> | 
 |  |  |                 </Button>, | 
 |  |  |                 <Button | 
 |  |  |                     type="link" | 
 |  |  |                     danger | 
 |  |  |                     key="batchRemove" | 
 |  |  |                     onClick={async () => { | 
 |  |  |                         Modal.confirm({ | 
 |  |  |                             title: intl.formatMessage({ id: 'page.delete', defaultMessage: '删除' }), | 
 |  |  |                             content: intl.formatMessage({ id: 'page.delete.confirm', defaultMessage: '确定删除该项吗?' }), | 
 |  |  |                             onOk: async () => { | 
 |  |  |                                 const success = await handleRemove([record], intl); | 
 |  |  |                                 if (success) { | 
 |  |  |                                     if (actionRef.current) { | 
 |  |  |                                         actionRef.current.reload(); | 
 |  |  |                                     } | 
 |  |  |                                 } | 
 |  |  |                             }, | 
 |  |  |                         }); | 
 |  |  |                     }} | 
 |  |  |                 > | 
 |  |  |                     <FormattedMessage id='page.delete' defaultMessage='删除' /> | 
 |  |  |                 </Button>, | 
 |  |  |             ], | 
 |  |  |         }, | 
 |  |  |     ]; | 
 |  |  |  | 
 |  |  |     return ( | 
 |  |  |         <PageContainer | 
 |  |  |             header={{ | 
 |  |  |                 breadcrumb: {}, | 
 |  |  |             }} | 
 |  |  |         > | 
 |  |  |             <div style={{ width: '100%', float: 'right' }}> | 
 |  |  |                 <ProTable | 
 |  |  |                     key="devicePlc" | 
 |  |  |                     rowKey="id" | 
 |  |  |                     actionRef={actionRef} | 
 |  |  |                     formRef={formTableRef} | 
 |  |  |                     columns={columns} | 
 |  |  |                     cardBordered | 
 |  |  |                     scroll={{ x: 1300 }} | 
 |  |  |                     dateFormatter="string" | 
 |  |  |                     pagination={{ pageSize: 16 }} | 
 |  |  |                     search={false} | 
 |  |  |                     toolbar={{ | 
 |  |  |                         search: { | 
 |  |  |                             onSearch: (value) => { | 
 |  |  |                                 setSearchParam(prevState => ({ | 
 |  |  |                                     ...prevState, | 
 |  |  |                                     condition: value | 
 |  |  |                                 })); | 
 |  |  |                                 actionRef.current?.reload(); | 
 |  |  |                             }, | 
 |  |  |                         }, | 
 |  |  |                         filter: ( | 
 |  |  |                             <LightFilter | 
 |  |  |                                 onValuesChange={(val) => { | 
 |  |  |                                 }} | 
 |  |  |                             > | 
 |  |  |                             </LightFilter> | 
 |  |  |                         ), | 
 |  |  |                         actions: [ | 
 |  |  |                             <Button | 
 |  |  |                                 type="primary" | 
 |  |  |                                 key="save" | 
 |  |  |                                 onClick={async () => { | 
 |  |  |                                     setModalVisible(true) | 
 |  |  |                                 }} | 
 |  |  |                             > | 
 |  |  |                                 <PlusOutlined /> | 
 |  |  |                                 <FormattedMessage id='page.add' defaultMessage='添加' /> | 
 |  |  |                             </Button>, | 
 |  |  |                             <Button | 
 |  |  |                                 key="export" | 
 |  |  |                                 onClick={async () => { | 
 |  |  |                                     handleExport(intl); | 
 |  |  |                                 }} | 
 |  |  |                             > | 
 |  |  |                                 <ExportOutlined /> | 
 |  |  |                                 <FormattedMessage id='page.export' defaultMessage='导出' /> | 
 |  |  |                             </Button>, | 
 |  |  |                         ], | 
 |  |  |                     }} | 
 |  |  |                     request={(params, sorter, filter) => | 
 |  |  |                         Http.doPostPromise('/api/devicePlc/page', { ...params, ...searchParam }, (res) => { | 
 |  |  |                             return { | 
 |  |  |                                 data: res.data.records, | 
 |  |  |                                 total: res.data.total, | 
 |  |  |                                 success: true, | 
 |  |  |                             } | 
 |  |  |                         }) | 
 |  |  |                     } | 
 |  |  |                     rowSelection={{ | 
 |  |  |                         onChange: (ids, rows) => { | 
 |  |  |                             setSelectedRows(rows); | 
 |  |  |                         } | 
 |  |  |                     }} | 
 |  |  |                     columnsState={{ | 
 |  |  |                         persistenceKey: TABLE_KEY, | 
 |  |  |                         persistenceType: 'localStorage', | 
 |  |  |                         defaultValue: { | 
 |  |  |                             // memo: { show: repairBug(TABLE_KEY, 'memo', false) }, | 
 |  |  |                             option: { fixed: 'right', disable: true }, | 
 |  |  |                         }, | 
 |  |  |                         onChange(value) { | 
 |  |  |                         }, | 
 |  |  |                     }} | 
 |  |  |                 /> | 
 |  |  |             </div> | 
 |  |  |  | 
 |  |  |             {selectedRows?.length > 0 && ( | 
 |  |  |                 <FooterToolbar | 
 |  |  |                     extra={ | 
 |  |  |                         <div> | 
 |  |  |                             <a style={{ fontWeight: 600 }}>{selectedRows.length}</a> | 
 |  |  |                             <FormattedMessage id='page.selected' defaultMessage=' 项已选择' /> | 
 |  |  |                         </div> | 
 |  |  |                     } | 
 |  |  |                 > | 
 |  |  |                     <Button | 
 |  |  |                         key="remove" | 
 |  |  |                         danger | 
 |  |  |                         onClick={async () => { | 
 |  |  |                             Modal.confirm({ | 
 |  |  |                                 title: intl.formatMessage({ id: 'page.delete', defaultMessage: '删除' }), | 
 |  |  |                                 content: intl.formatMessage({ id: 'page.delete.confirm', defaultMessage: '确定删除该项吗?' }), | 
 |  |  |                                 onOk: async () => { | 
 |  |  |                                     const success = await handleRemove(selectedRows, intl); | 
 |  |  |                                     if (success) { | 
 |  |  |                                         setSelectedRows([]); | 
 |  |  |                                         actionRef.current?.reloadAndRest?.(); | 
 |  |  |                                     } | 
 |  |  |                                 }, | 
 |  |  |                             }); | 
 |  |  |                         }} | 
 |  |  |                     > | 
 |  |  |                         <FormattedMessage id='page.delete.batch' defaultMessage='批量删除' /> | 
 |  |  |                     </Button> | 
 |  |  |                 </FooterToolbar> | 
 |  |  |             )} | 
 |  |  |  | 
 |  |  |             <Edit | 
 |  |  |                 open={modalVisible} | 
 |  |  |                 values={currentRow || {}} | 
 |  |  |                 onCancel={ | 
 |  |  |                     () => { | 
 |  |  |                         setModalVisible(false); | 
 |  |  |                         setCurrentRow(undefined); | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |                 onSubmit={async (values) => { | 
 |  |  |                     let ok = false; | 
 |  |  |                     if (values.id) { | 
 |  |  |                         ok = await handleUpdate({ ...values }, intl) | 
 |  |  |                     } else { | 
 |  |  |                         ok = await handleSave({ ...values }, intl) | 
 |  |  |                     } | 
 |  |  |                     if (ok) { | 
 |  |  |                         setModalVisible(false); | 
 |  |  |                         setCurrentRow(undefined); | 
 |  |  |                         if (actionRef.current) { | 
 |  |  |                             actionRef.current.reload(); | 
 |  |  |                         } | 
 |  |  |                     } | 
 |  |  |                 }} | 
 |  |  |             /> | 
 |  |  |         </PageContainer> | 
 |  |  |     ); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | export default Main; | 
 
| New file | 
 |  |  | 
 |  |  | import React, { useState, useRef, useEffect } from 'react'; | 
 |  |  | import { | 
 |  |  |     ProForm, | 
 |  |  |     ProFormDigit, | 
 |  |  |     ProFormText, | 
 |  |  |     ProFormSelect, | 
 |  |  |     ProFormDateTimePicker | 
 |  |  | } from '@ant-design/pro-components'; | 
 |  |  | import { Form, Modal } from 'antd'; | 
 |  |  | import { FormattedMessage, useIntl } from '@umijs/max'; | 
 |  |  | import moment from 'moment'; | 
 |  |  | import Http from '@/utils/http'; | 
 |  |  |  | 
 |  |  | const Edit = (props) => { | 
 |  |  |     const intl = useIntl(); | 
 |  |  |     const [form] = Form.useForm(); | 
 |  |  |     const { } = props; | 
 |  |  |  | 
 |  |  |     useEffect(() => { | 
 |  |  |         form.resetFields(); | 
 |  |  |         form.setFieldsValue({ | 
 |  |  |             ...props.values | 
 |  |  |         }) | 
 |  |  |     }, [form, props]) | 
 |  |  |  | 
 |  |  |     const handleCancel = () => { | 
 |  |  |         props.onCancel(); | 
 |  |  |     }; | 
 |  |  |  | 
 |  |  |     const handleOk = () => { | 
 |  |  |         form.submit(); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     const handleFinish = async (values) => { | 
 |  |  |         props.onSubmit({ ...values }); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     return ( | 
 |  |  |         <> | 
 |  |  |             <Modal | 
 |  |  |                 title={ | 
 |  |  |                     Object.keys(props.values).length > 0 | 
 |  |  |                         ? intl.formatMessage({ id: 'page.edit', defaultMessage: '编辑' }) | 
 |  |  |                         : intl.formatMessage({ id: 'page.add', defaultMessage: '添加' }) | 
 |  |  |                 } | 
 |  |  |                 width={640} | 
 |  |  |                 forceRender | 
 |  |  |                 destroyOnClose | 
 |  |  |                 open={props.open} | 
 |  |  |                 onCancel={handleCancel} | 
 |  |  |                 onOk={handleOk} | 
 |  |  |             > | 
 |  |  |                 <ProForm | 
 |  |  |                     form={form} | 
 |  |  |                     submitter={false} | 
 |  |  |                     onFinish={handleFinish} | 
 |  |  |                     layout="horizontal" | 
 |  |  |                     grid={true} | 
 |  |  |                 > | 
 |  |  |                     <ProFormDigit | 
 |  |  |                         name="id" | 
 |  |  |                         disabled | 
 |  |  |                         hidden={true} | 
 |  |  |                     /> | 
 |  |  |                     <ProForm.Group> | 
 |  |  |                         <ProFormText | 
 |  |  |                             name="uuid" | 
 |  |  |                             label="编号" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                         /> | 
 |  |  |                         <ProFormText | 
 |  |  |                             name="name" | 
 |  |  |                             label="名称" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                         /> | 
 |  |  |                     </ProForm.Group> | 
 |  |  |                     <ProForm.Group> | 
 |  |  |                         <ProFormText | 
 |  |  |                             name="flag" | 
 |  |  |                             label="标识" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                         /> | 
 |  |  |                         <ProFormSelect | 
 |  |  |                             name="status" | 
 |  |  |                             label="状态" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             options={[ | 
 |  |  |                                 { label: '正常', value: 1 }, | 
 |  |  |                                 { label: '禁用', value: 0 }, | 
 |  |  |                             ]} | 
 |  |  |                         /> | 
 |  |  |                     </ProForm.Group> | 
 |  |  |                     <ProForm.Group> | 
 |  |  |                         <ProFormDateTimePicker | 
 |  |  |                             name="createTime" | 
 |  |  |                             label="添加时间" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             transform={(value) => moment(value).toISOString()} | 
 |  |  |                         /> | 
 |  |  |                         <ProFormSelect | 
 |  |  |                             name="createBy" | 
 |  |  |                             label="添加人员" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             fieldProps={{ precision: 0 }} | 
 |  |  |                             showSearch | 
 |  |  |                             debounceTime={300} | 
 |  |  |                             request={async ({ keyWords }) => { | 
 |  |  |                                 const resp = await Http.doPostForm('api/user/query', { condition: keyWords }); | 
 |  |  |                                 return resp.data; | 
 |  |  |                             }} | 
 |  |  |                         /> | 
 |  |  |                     </ProForm.Group> | 
 |  |  |                     <ProForm.Group> | 
 |  |  |                         <ProFormDateTimePicker | 
 |  |  |                             name="updateTime" | 
 |  |  |                             label="修改时间" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             transform={(value) => moment(value).toISOString()} | 
 |  |  |                         /> | 
 |  |  |                         <ProFormSelect | 
 |  |  |                             name="updateBy" | 
 |  |  |                             label="修改人员" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                             fieldProps={{ precision: 0 }} | 
 |  |  |                             showSearch | 
 |  |  |                             debounceTime={300} | 
 |  |  |                             request={async ({ keyWords }) => { | 
 |  |  |                                 const resp = await Http.doPostForm('api/user/query', { condition: keyWords }); | 
 |  |  |                                 return resp.data; | 
 |  |  |                             }} | 
 |  |  |                         /> | 
 |  |  |                     </ProForm.Group> | 
 |  |  |                     <ProForm.Group> | 
 |  |  |                         <ProFormText | 
 |  |  |                             name="memo" | 
 |  |  |                             label="备注" | 
 |  |  |                             colProps={{ md: 12, xl: 12 }} | 
 |  |  |                         /> | 
 |  |  |                     </ProForm.Group> | 
 |  |  |  | 
 |  |  |                 </ProForm> | 
 |  |  |             </Modal> | 
 |  |  |         </> | 
 |  |  |     ) | 
 |  |  | } | 
 |  |  |  | 
 |  |  | export default Edit; | 
 
| New file | 
 |  |  | 
 |  |  |  | 
 |  |  | import React, { useState, useRef, useEffect } from 'react'; | 
 |  |  | import { Button, message, Modal, Tag  } from 'antd'; | 
 |  |  | import { | 
 |  |  |     FooterToolbar, | 
 |  |  |     PageContainer, | 
 |  |  |     ProTable, | 
 |  |  |     LightFilter, | 
 |  |  | } from '@ant-design/pro-components'; | 
 |  |  | import { FormattedMessage, useIntl } from '@umijs/max'; | 
 |  |  | import { PlusOutlined, ExportOutlined } from '@ant-design/icons'; | 
 |  |  | import Http from '@/utils/http'; | 
 |  |  | import Edit from './components/edit' | 
 |  |  | import { TextFilter, SelectFilter, DatetimeRangeFilter, LinkFilter } from '@/components/TableSearch' | 
 |  |  | import { statusMap } from '@/utils/enum-util' | 
 |  |  | import { repairBug } from '@/utils/common-util'; | 
 |  |  |  | 
 |  |  | const TABLE_KEY = 'pro-table-deviceType'; | 
 |  |  |  | 
 |  |  | const handleSave = async (val, intl) => { | 
 |  |  |     const hide = message.loading(intl.formatMessage({ id: 'page.adding', defaultMessage: '正在添加' })); | 
 |  |  |     try { | 
 |  |  |         const resp = await Http.doPost('api/deviceType/save', val); | 
 |  |  |         if (resp.code === 200) { | 
 |  |  |             message.success(intl.formatMessage({ id: 'page.add.success', defaultMessage: '添加成功' })); | 
 |  |  |             return true; | 
 |  |  |         } else { | 
 |  |  |             message.error(resp.msg); | 
 |  |  |             return false; | 
 |  |  |         } | 
 |  |  |     } catch (error) { | 
 |  |  |         message.error(intl.formatMessage({ id: 'page.add.fail', defaultMessage: '添加失败请重试!' })); | 
 |  |  |         return false; | 
 |  |  |     } finally { | 
 |  |  |         hide(); | 
 |  |  |     } | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | const handleUpdate = async (val, intl) => { | 
 |  |  |     const hide = message.loading(intl.formatMessage({ id: 'page.updating', defaultMessage: '正在更新' })); | 
 |  |  |     try { | 
 |  |  |         const resp = await Http.doPost('api/deviceType/update', val); | 
 |  |  |         if (resp.code === 200) { | 
 |  |  |             message.success(intl.formatMessage({ id: 'page.update.success', defaultMessage: '更新成功' })); | 
 |  |  |             return true; | 
 |  |  |         } else { | 
 |  |  |             message.error(resp.msg); | 
 |  |  |             return false; | 
 |  |  |         } | 
 |  |  |     } catch (error) { | 
 |  |  |         message.error(intl.formatMessage({ id: 'page.update.fail', defaultMessage: '更新失败请重试!' })); | 
 |  |  |         return false; | 
 |  |  |     } finally { | 
 |  |  |         hide(); | 
 |  |  |     } | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | const handleRemove = async (rows, intl) => { | 
 |  |  |     if (!rows) return true; | 
 |  |  |     const hide = message.loading(intl.formatMessage({ id: 'page.deleting', defaultMessage: '正在删除' })); | 
 |  |  |     try { | 
 |  |  |         const resp = await Http.doPost('api/deviceType/remove/' + rows.map((row) => row.id).join(',')); | 
 |  |  |         if (resp.code === 200) { | 
 |  |  |             message.success(intl.formatMessage({ id: 'page.delete.success', defaultMessage: '删除成功' })); | 
 |  |  |             return true; | 
 |  |  |         } else { | 
 |  |  |             message.error(resp.msg); | 
 |  |  |             return false; | 
 |  |  |         } | 
 |  |  |     } catch (error) { | 
 |  |  |         message.error(intl.formatMessage({ id: 'page.delete.fail', defaultMessage: '删除失败,请重试!' })); | 
 |  |  |         return false; | 
 |  |  |     } finally { | 
 |  |  |         hide(); | 
 |  |  |     } | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | const handleExport = async (intl) => { | 
 |  |  |     const hide = message.loading(intl.formatMessage({ id: 'page.exporting', defaultMessage: '正在导出' })); | 
 |  |  |     try { | 
 |  |  |         const resp = await Http.doPostBlob('api/deviceType/export'); | 
 |  |  |         const blob = new Blob([resp], { type: 'application/vnd.ms-excel' }); | 
 |  |  |         window.location.href = window.URL.createObjectURL(blob); | 
 |  |  |         message.success(intl.formatMessage({ id: 'page.export.success', defaultMessage: '导出成功' })); | 
 |  |  |         return true; | 
 |  |  |     } catch (error) { | 
 |  |  |         message.error(intl.formatMessage({ id: 'page.export.fail', defaultMessage: '导出失败,请重试' })); | 
 |  |  |         return false; | 
 |  |  |     } finally { | 
 |  |  |         hide(); | 
 |  |  |     } | 
 |  |  | }; | 
 |  |  |  | 
 |  |  |  | 
 |  |  | const Main = () => { | 
 |  |  |     const intl = useIntl(); | 
 |  |  |     const formTableRef = useRef(); | 
 |  |  |     const actionRef = useRef(); | 
 |  |  |     const [selectedRows, setSelectedRows] = useState([]); | 
 |  |  |     const [modalVisible, setModalVisible] = useState(false); | 
 |  |  |     const [currentRow, setCurrentRow] = useState(); | 
 |  |  |     const [searchParam, setSearchParam] = useState({}); | 
 |  |  |  | 
 |  |  |     useEffect(() => { | 
 |  |  |  | 
 |  |  |     }, []); | 
 |  |  |  | 
 |  |  |     const columns = [ | 
 |  |  |         { | 
 |  |  |             title: intl.formatMessage({ | 
 |  |  |                 id: 'page.table.no', | 
 |  |  |                 defaultMessage: 'No' | 
 |  |  |             }), | 
 |  |  |             dataIndex: 'index', | 
 |  |  |             valueType: 'indexBorder', | 
 |  |  |             width: 48, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '编号', | 
 |  |  |             dataIndex: 'uuid', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <TextFilter | 
 |  |  |                 name='uuid' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '名称', | 
 |  |  |             dataIndex: 'name', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             copyable: true, | 
 |  |  |             filterDropdown: (props) => <TextFilter | 
 |  |  |                 name='name' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '标识', | 
 |  |  |             dataIndex: 'flag', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <TextFilter | 
 |  |  |                 name='flag' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '状态', | 
 |  |  |             dataIndex: 'status$', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <SelectFilter | 
 |  |  |                 name='status' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |                 data={[ | 
 |  |  |                     { label: '正常', value: 1 }, | 
 |  |  |                     { label: '禁用', value: 0 }, | 
 |  |  |                 ]} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '添加时间', | 
 |  |  |             dataIndex: 'createTime$', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <DatetimeRangeFilter | 
 |  |  |                 name='createTime' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '添加人员', | 
 |  |  |             dataIndex: 'createBy$', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <LinkFilter | 
 |  |  |                 name='createBy' | 
 |  |  |                 major='user' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '修改时间', | 
 |  |  |             dataIndex: 'updateTime$', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <DatetimeRangeFilter | 
 |  |  |                 name='updateTime' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '修改人员', | 
 |  |  |             dataIndex: 'updateBy$', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <LinkFilter | 
 |  |  |                 name='updateBy' | 
 |  |  |                 major='user' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |         { | 
 |  |  |             title: '备注', | 
 |  |  |             dataIndex: 'memo', | 
 |  |  |             valueType: 'text', | 
 |  |  |             hidden: false, | 
 |  |  |             width: 140, | 
 |  |  |             filterDropdown: (props) => <TextFilter | 
 |  |  |                 name='memo' | 
 |  |  |                 {...props} | 
 |  |  |                 actionRef={actionRef} | 
 |  |  |                 setSearchParam={setSearchParam} | 
 |  |  |             />, | 
 |  |  |         }, | 
 |  |  |  | 
 |  |  |         { | 
 |  |  |             title: '操作', | 
 |  |  |             dataIndex: 'option', | 
 |  |  |             width: 140, | 
 |  |  |             valueType: 'option', | 
 |  |  |             render: (_, record) => [ | 
 |  |  |                 <Button | 
 |  |  |                     type="link" | 
 |  |  |                     key="edit" | 
 |  |  |                     onClick={() => { | 
 |  |  |                         setModalVisible(true); | 
 |  |  |                         setCurrentRow(record); | 
 |  |  |                     }} | 
 |  |  |                 > | 
 |  |  |                     <FormattedMessage id='page.edit' defaultMessage='编辑' /> | 
 |  |  |                 </Button>, | 
 |  |  |                 <Button | 
 |  |  |                     type="link" | 
 |  |  |                     danger | 
 |  |  |                     key="batchRemove" | 
 |  |  |                     onClick={async () => { | 
 |  |  |                         Modal.confirm({ | 
 |  |  |                             title: intl.formatMessage({ id: 'page.delete', defaultMessage: '删除' }), | 
 |  |  |                             content: intl.formatMessage({ id: 'page.delete.confirm', defaultMessage: '确定删除该项吗?' }), | 
 |  |  |                             onOk: async () => { | 
 |  |  |                                 const success = await handleRemove([record], intl); | 
 |  |  |                                 if (success) { | 
 |  |  |                                     if (actionRef.current) { | 
 |  |  |                                         actionRef.current.reload(); | 
 |  |  |                                     } | 
 |  |  |                                 } | 
 |  |  |                             }, | 
 |  |  |                         }); | 
 |  |  |                     }} | 
 |  |  |                 > | 
 |  |  |                     <FormattedMessage id='page.delete' defaultMessage='删除' /> | 
 |  |  |                 </Button>, | 
 |  |  |             ], | 
 |  |  |         }, | 
 |  |  |     ]; | 
 |  |  |  | 
 |  |  |     return ( | 
 |  |  |         <PageContainer | 
 |  |  |             header={{ | 
 |  |  |                 breadcrumb: {}, | 
 |  |  |             }} | 
 |  |  |         > | 
 |  |  |             <div style={{ width: '100%', float: 'right' }}> | 
 |  |  |                 <ProTable | 
 |  |  |                     key="deviceType" | 
 |  |  |                     rowKey="id" | 
 |  |  |                     actionRef={actionRef} | 
 |  |  |                     formRef={formTableRef} | 
 |  |  |                     columns={columns} | 
 |  |  |                     cardBordered | 
 |  |  |                     scroll={{ x: 1300 }} | 
 |  |  |                     dateFormatter="string" | 
 |  |  |                     pagination={{ pageSize: 16 }} | 
 |  |  |                     search={false} | 
 |  |  |                     toolbar={{ | 
 |  |  |                         search: { | 
 |  |  |                             onSearch: (value) => { | 
 |  |  |                                 setSearchParam(prevState => ({ | 
 |  |  |                                     ...prevState, | 
 |  |  |                                     condition: value | 
 |  |  |                                 })); | 
 |  |  |                                 actionRef.current?.reload(); | 
 |  |  |                             }, | 
 |  |  |                         }, | 
 |  |  |                         filter: ( | 
 |  |  |                             <LightFilter | 
 |  |  |                                 onValuesChange={(val) => { | 
 |  |  |                                 }} | 
 |  |  |                             > | 
 |  |  |                             </LightFilter> | 
 |  |  |                         ), | 
 |  |  |                         actions: [ | 
 |  |  |                             <Button | 
 |  |  |                                 type="primary" | 
 |  |  |                                 key="save" | 
 |  |  |                                 onClick={async () => { | 
 |  |  |                                     setModalVisible(true) | 
 |  |  |                                 }} | 
 |  |  |                             > | 
 |  |  |                                 <PlusOutlined /> | 
 |  |  |                                 <FormattedMessage id='page.add' defaultMessage='添加' /> | 
 |  |  |                             </Button>, | 
 |  |  |                             <Button | 
 |  |  |                                 key="export" | 
 |  |  |                                 onClick={async () => { | 
 |  |  |                                     handleExport(intl); | 
 |  |  |                                 }} | 
 |  |  |                             > | 
 |  |  |                                 <ExportOutlined /> | 
 |  |  |                                 <FormattedMessage id='page.export' defaultMessage='导出' /> | 
 |  |  |                             </Button>, | 
 |  |  |                         ], | 
 |  |  |                     }} | 
 |  |  |                     request={(params, sorter, filter) => | 
 |  |  |                         Http.doPostPromise('/api/deviceType/page', { ...params, ...searchParam }, (res) => { | 
 |  |  |                             return { | 
 |  |  |                                 data: res.data.records, | 
 |  |  |                                 total: res.data.total, | 
 |  |  |                                 success: true, | 
 |  |  |                             } | 
 |  |  |                         }) | 
 |  |  |                     } | 
 |  |  |                     rowSelection={{ | 
 |  |  |                         onChange: (ids, rows) => { | 
 |  |  |                             setSelectedRows(rows); | 
 |  |  |                         } | 
 |  |  |                     }} | 
 |  |  |                     columnsState={{ | 
 |  |  |                         persistenceKey: TABLE_KEY, | 
 |  |  |                         persistenceType: 'localStorage', | 
 |  |  |                         defaultValue: { | 
 |  |  |                             // memo: { show: repairBug(TABLE_KEY, 'memo', false) }, | 
 |  |  |                             option: { fixed: 'right', disable: true }, | 
 |  |  |                         }, | 
 |  |  |                         onChange(value) { | 
 |  |  |                         }, | 
 |  |  |                     }} | 
 |  |  |                 /> | 
 |  |  |             </div> | 
 |  |  |  | 
 |  |  |             {selectedRows?.length > 0 && ( | 
 |  |  |                 <FooterToolbar | 
 |  |  |                     extra={ | 
 |  |  |                         <div> | 
 |  |  |                             <a style={{ fontWeight: 600 }}>{selectedRows.length}</a> | 
 |  |  |                             <FormattedMessage id='page.selected' defaultMessage=' 项已选择' /> | 
 |  |  |                         </div> | 
 |  |  |                     } | 
 |  |  |                 > | 
 |  |  |                     <Button | 
 |  |  |                         key="remove" | 
 |  |  |                         danger | 
 |  |  |                         onClick={async () => { | 
 |  |  |                             Modal.confirm({ | 
 |  |  |                                 title: intl.formatMessage({ id: 'page.delete', defaultMessage: '删除' }), | 
 |  |  |                                 content: intl.formatMessage({ id: 'page.delete.confirm', defaultMessage: '确定删除该项吗?' }), | 
 |  |  |                                 onOk: async () => { | 
 |  |  |                                     const success = await handleRemove(selectedRows, intl); | 
 |  |  |                                     if (success) { | 
 |  |  |                                         setSelectedRows([]); | 
 |  |  |                                         actionRef.current?.reloadAndRest?.(); | 
 |  |  |                                     } | 
 |  |  |                                 }, | 
 |  |  |                             }); | 
 |  |  |                         }} | 
 |  |  |                     > | 
 |  |  |                         <FormattedMessage id='page.delete.batch' defaultMessage='批量删除' /> | 
 |  |  |                     </Button> | 
 |  |  |                 </FooterToolbar> | 
 |  |  |             )} | 
 |  |  |  | 
 |  |  |             <Edit | 
 |  |  |                 open={modalVisible} | 
 |  |  |                 values={currentRow || {}} | 
 |  |  |                 onCancel={ | 
 |  |  |                     () => { | 
 |  |  |                         setModalVisible(false); | 
 |  |  |                         setCurrentRow(undefined); | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |                 onSubmit={async (values) => { | 
 |  |  |                     let ok = false; | 
 |  |  |                     if (values.id) { | 
 |  |  |                         ok = await handleUpdate({ ...values }, intl) | 
 |  |  |                     } else { | 
 |  |  |                         ok = await handleSave({ ...values }, intl) | 
 |  |  |                     } | 
 |  |  |                     if (ok) { | 
 |  |  |                         setModalVisible(false); | 
 |  |  |                         setCurrentRow(undefined); | 
 |  |  |                         if (actionRef.current) { | 
 |  |  |                             actionRef.current.reload(); | 
 |  |  |                         } | 
 |  |  |                     } | 
 |  |  |                 }} | 
 |  |  |             /> | 
 |  |  |         </PageContainer> | 
 |  |  |     ); | 
 |  |  | }; | 
 |  |  |  | 
 |  |  | export default Main; |