15 changed files with 442 additions and 11 deletions
			
			
		| @ -0,0 +1,16 @@ | |||||
|  | 'use strict'; | ||||
|  | 
 | ||||
|  | import { basicAction } from '@peace/utils' | ||||
|  | import { ApiTable } from '$utils' | ||||
|  | 
 | ||||
|  | export function list(query) { | ||||
|  |     return dispatch => basicAction({ | ||||
|  |         type: 'get', | ||||
|  |         dispatch: dispatch, | ||||
|  |         query: query, | ||||
|  |         actionType: 'GET_FACTOR_LIST', | ||||
|  |         url: ApiTable.getFactors, | ||||
|  |         msg: { error: '获取监测原型列表失败' }, | ||||
|  |         reducer: { name: 'factors' } | ||||
|  |     }) | ||||
|  | } | ||||
| @ -0,0 +1,7 @@ | |||||
|  | 'use strict'; | ||||
|  | 
 | ||||
|  | import * as factor from './factors' | ||||
|  | 
 | ||||
|  | export default { | ||||
|  |     ...factor | ||||
|  | } | ||||
| @ -0,0 +1,145 @@ | |||||
|  | import React, { useEffect, useRef } from 'react'; | ||||
|  | import { connect } from 'react-redux'; | ||||
|  | import { Spin, Select, Divider, Space, Button, Modal, Input, Form, Switch, AutoComplete } from 'antd'; | ||||
|  | import ProForm, { ProFormText, ProFormSelect, ProFormTextArea } from '@ant-design/pro-form'; | ||||
|  | import { useState } from 'react'; | ||||
|  | import { InMode, OutMode, ProtocolTypes } from './models'; | ||||
|  | import { PlusOutlined } from '@ant-design/icons'; | ||||
|  | const { Option } = Select; | ||||
|  | 
 | ||||
|  | const ConfigModal = (props) => { | ||||
|  |     const { dispatch, actions, visible, close, editData } = props | ||||
|  |     const formRef = useRef() | ||||
|  |     const inputRef = useRef() | ||||
|  |     const { gateway } = actions | ||||
|  |     const [protocols, setProtocols] = useState([]) | ||||
|  |     const [newProtocol, setNewProtocol] = useState('') | ||||
|  | 
 | ||||
|  |     useEffect(() => { | ||||
|  |         setProtocols([]); | ||||
|  |         dispatch(gateway.getProtocols()).then(res => { | ||||
|  |             if (res.success) { | ||||
|  |                 setProtocols(res.payload.data.sort()) | ||||
|  |             } | ||||
|  |         }) | ||||
|  |     }, []) | ||||
|  | 
 | ||||
|  |     const onNewProtocolChange = (e) => { | ||||
|  |         setNewProtocol(e.target.value) | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     const addNewProtocol = (e) => { | ||||
|  |         e.preventDefault(); | ||||
|  |         setProtocols([...protocols, newProtocol]) | ||||
|  |         setNewProtocol(''); | ||||
|  |         setTimeout(()=>{ | ||||
|  |             inputRef.current?.focus(); | ||||
|  |         }) | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     const batchAdd=(v)=>{ | ||||
|  |          | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     return <Modal | ||||
|  |         title={`${editData ? '编辑' : '新增'}配置`} | ||||
|  |         visible={visible} | ||||
|  |         onOk={() => { | ||||
|  |             formRef.current.validateFields() | ||||
|  |                 .then(v => { | ||||
|  |                     v.id = editData?.id; | ||||
|  |                     if (!v.in_config) { | ||||
|  |                         v.in_config = '{}' | ||||
|  |                     } | ||||
|  |                     if (!v.out_config) { | ||||
|  |                         v.out_config = '{}' | ||||
|  |                     } | ||||
|  |                     dispatch(editData ? gateway.edit([v]) : gateway.add([v])) | ||||
|  |                         .then(res => { | ||||
|  |                             if (res.success) { | ||||
|  |                                 dispatch(gateway.list()) | ||||
|  |                                 close() | ||||
|  |                             } | ||||
|  |                         }) | ||||
|  |                 }) | ||||
|  |         }} | ||||
|  |         onCancel={() => { | ||||
|  |             close() | ||||
|  |         }} | ||||
|  |     > | ||||
|  |         <ProForm | ||||
|  |             formRef={formRef} | ||||
|  |             autoFocusFirstInput | ||||
|  |             Layout={'vertical'} | ||||
|  |             initialValues={ | ||||
|  |                 editData ? | ||||
|  |                     editData : | ||||
|  |                     { | ||||
|  |                         in_mode: InMode[0], | ||||
|  |                         out_mode: OutMode[0], | ||||
|  |                         protocol: ProtocolTypes[0], | ||||
|  |                     } | ||||
|  |             } | ||||
|  |             submitter={false} | ||||
|  |             formKey='config-form' | ||||
|  |             grid={true} | ||||
|  |         > | ||||
|  |             <ProFormText name="name" label="名称" tooltip="最长为 24 位" placeholder="请输入名称" rules={[{ required: true, message: '请输入名称' }]} /> | ||||
|  |             <ProFormSelect | ||||
|  |                 colProps={{ span: 12 }} | ||||
|  |                 label="输入模式" | ||||
|  |                 name="in_mode" | ||||
|  |                 valueEnum={InMode} | ||||
|  |             /> | ||||
|  |             <ProFormSelect | ||||
|  |                 colProps={{ span: 12 }} | ||||
|  |                 label="输出模式" | ||||
|  |                 name="out_mode" | ||||
|  |                 valueEnum={OutMode} | ||||
|  |             /> | ||||
|  |             <ProFormTextArea colProps={{ span: 24 }} name="in_config" label="输入配置" /> | ||||
|  |             <ProFormTextArea colProps={{ span: 24 }} name="out_config" label="输出配置" /> | ||||
|  |             <Form.Item name="protocol" label="协议" rules={[{ required: true }]}> | ||||
|  |                 <Select | ||||
|  |                     style={{ width: 300 }} | ||||
|  |                     placeholder="选择协议" | ||||
|  |                     dropdownRender={menu => ( | ||||
|  |                         <> | ||||
|  |                             {menu} | ||||
|  |                             <Divider style={{ margin: '8px 0' }} /> | ||||
|  |                             <Space style={{ padding: '0 8px 4px' }}> | ||||
|  |                                 <Input | ||||
|  |                                     placeholder="输入新增协议名" | ||||
|  |                                     ref={inputRef} | ||||
|  |                                     value={newProtocol} | ||||
|  |                                     onChange={onNewProtocolChange} | ||||
|  |                                 /> | ||||
|  |                                 <Button type="text" icon={<PlusOutlined />} onClick={addNewProtocol}> | ||||
|  |                                     添加项 | ||||
|  |                                 </Button> | ||||
|  |                             </Space> | ||||
|  |                         </> | ||||
|  |                     )} | ||||
|  |                 > | ||||
|  |                     {protocols.map(item => ( | ||||
|  |                         <Option key={item}>{item}</Option> | ||||
|  |                     ))} | ||||
|  |                 </Select> | ||||
|  | 
 | ||||
|  |             </Form.Item> | ||||
|  |             <ProFormTextArea colProps={{ span: 24 }} | ||||
|  |                 name="protocol_info" label="协议信息" | ||||
|  |             /> | ||||
|  |         </ProForm> | ||||
|  |     </Modal> | ||||
|  | } | ||||
|  | 
 | ||||
|  | function mapStateToProps(state) { | ||||
|  |     const { auth, global } = state; | ||||
|  |     return { | ||||
|  |         user: auth.user, | ||||
|  |         actions: global.actions, | ||||
|  |     }; | ||||
|  | } | ||||
|  | 
 | ||||
|  | export default connect(mapStateToProps)(ConfigModal); | ||||
| @ -0,0 +1,196 @@ | |||||
|  | import React, { useState, useEffect, useRef } from 'react'; | ||||
|  | import { connect } from 'react-redux'; | ||||
|  | import { Spin, Button, Card, Input, Space, Tag, Table } from 'antd'; | ||||
|  | import '../style.less'; | ||||
|  | import { push } from 'react-router-redux' | ||||
|  | import ProTable, { TableDropdown } from '@ant-design/pro-table'; | ||||
|  | import { InMode, OutMode, ProtocolTypes } from './models'; | ||||
|  | import ConfigModal from './ConfigModal'; | ||||
|  | import { request } from 'superagent'; | ||||
|  | 
 | ||||
|  | const FactorProfile = (props) => { | ||||
|  |     const { dispatch, actions, user, loading, factors, total } = props | ||||
|  | 
 | ||||
|  |     const { factor } = actions; | ||||
|  |     const [configModalVis, setConfigModalVis] = useState(false) | ||||
|  |     const [editData, setEditData] = useState(null) | ||||
|  |     const [fdata, setFdata] = useState([]) | ||||
|  | 
 | ||||
|  |     const pageSize = 10 | ||||
|  | 
 | ||||
|  |     useEffect(() => { | ||||
|  |         // dispatch(factor.list())
 | ||||
|  |     }, []) | ||||
|  | 
 | ||||
|  |     const actionRef = useRef(); | ||||
|  |     const columns = [ | ||||
|  |         { | ||||
|  |             dataIndex: 'id', | ||||
|  |             valueType: 'indexBorder', | ||||
|  |             width: 48, | ||||
|  |         }, { | ||||
|  |             title: '名称', | ||||
|  |             dataIndex: 'Name', | ||||
|  |             ellipsis: true | ||||
|  |         }, | ||||
|  |         { | ||||
|  |             title: '编码', | ||||
|  |             dataIndex: 'Proto', | ||||
|  |         }, | ||||
|  |         { | ||||
|  |             title: '监测项', | ||||
|  |             dataIndex: 'Factor_proto_item', | ||||
|  |             ellipsis: true, | ||||
|  |             render: (_, record) => ( | ||||
|  |                 <Space> | ||||
|  |                     {record.Factor_proto_item.map(({ Name }) => ( | ||||
|  |                         <Tag key={Name}> | ||||
|  |                             {Name} | ||||
|  |                         </Tag> | ||||
|  |                     ))} | ||||
|  |                 </Space> | ||||
|  |             ), | ||||
|  |         }, { | ||||
|  |             title: '操作', | ||||
|  |             valueType: 'option', | ||||
|  |             key: 'option', | ||||
|  |             render: (txt, row, _, action) => [ | ||||
|  |                 <Button type="primary" | ||||
|  |                     onClick={() => { | ||||
|  |                         setConfigModalVis(true) | ||||
|  |                         setEditData({ ...row }) | ||||
|  |                     }} | ||||
|  |                 >详情</Button> | ||||
|  |             ], | ||||
|  |         } | ||||
|  |     ] | ||||
|  | 
 | ||||
|  |     const requestList = async (params) => { | ||||
|  |         const ret = await dispatch(factor.list()); | ||||
|  |         console.log(ret) | ||||
|  |         let tmp = [] | ||||
|  |         tmp = ret.payload.data.data; | ||||
|  |         if (!!params.Name) { | ||||
|  |             tmp = tmp.filter(a => a.Name.includes(params.Name)) | ||||
|  |         } | ||||
|  |         if (!!params.Proto) { | ||||
|  |             tmp = tmp.filter(a => a.Proto.includes(params.Proto)) | ||||
|  |         } | ||||
|  |         if(!!params.Factor_proto_item){ | ||||
|  |             tmp = tmp.filter(a => a.Factor_proto_item.some(d=>{ | ||||
|  |                 return d.Name.includes(params.Factor_proto_item) || | ||||
|  |                 d.Field_name.includes(params.Factor_proto_item) || | ||||
|  |                 d.Item_unit.includes(params.Factor_proto_item) | ||||
|  |             })) | ||||
|  |         } | ||||
|  |         let data = tmp.slice(params.pageSize * (params.current - 1), params.pageSize * params.current); | ||||
|  |         data = data.map(d => ({ | ||||
|  |             ...d, | ||||
|  |             key: d.Proto + d.Name | ||||
|  |         })) | ||||
|  |         setFdata(data) | ||||
|  |         return { | ||||
|  |             total: tmp.length, | ||||
|  |             data: data | ||||
|  |         } | ||||
|  |         const query = { | ||||
|  |             limit: params.pageSize, | ||||
|  |             offset: params.pageSize * (params.current - 1) | ||||
|  |         } | ||||
|  |         const res = await dispatch(factor.list(query)); | ||||
|  |         return { | ||||
|  |             ...res, | ||||
|  |             total: res.payload.data ? res.payload.data.total : 0 | ||||
|  |         } | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     const expandRow = (record, index, indent, expanded) => { | ||||
|  |         let cols = [] | ||||
|  |         if (expanded) { | ||||
|  |             cols = [{ | ||||
|  |                 title: '名称', | ||||
|  |                 dataIndex: 'Name', | ||||
|  |                 ellipsis: true | ||||
|  |             }, { | ||||
|  |                 title: '字段', | ||||
|  |                 dataIndex: 'Field_name', | ||||
|  |                 ellipsis: true | ||||
|  |             }, { | ||||
|  |                 title: '单位', | ||||
|  |                 dataIndex: 'Item_unit', | ||||
|  |                 ellipsis: true | ||||
|  |             }, | ||||
|  |             ] | ||||
|  |             return <Table columns={cols} dataSource={record.Factor_proto_item} pagination={false}></Table> | ||||
|  |         } | ||||
|  |     } | ||||
|  |     const [activeExpRow, setActiveExpRow] = React.useState(); | ||||
|  | 
 | ||||
|  |     return ( | ||||
|  |         <div> | ||||
|  |             {/* <Spin tip="biubiubiu~" spinning={loading}> */} | ||||
|  |             <ProTable | ||||
|  |                 columns={columns} | ||||
|  |                 actionRef={actionRef} | ||||
|  |                 toolbar={{ | ||||
|  |                     settings: [] | ||||
|  |                 }} | ||||
|  |                 search={{ | ||||
|  |                     labelWidth: 'auto', | ||||
|  |                 }} | ||||
|  |                 dataSource={fdata} | ||||
|  |                 request={requestList} | ||||
|  |                 manualRequest={false} | ||||
|  |                 options={false} | ||||
|  |                 toolBarRender={() => [ | ||||
|  |                     <Button type="primary" key="primary" onClick={() => { setConfigModalVis(true) }}> | ||||
|  |                         添加配置 | ||||
|  |                     </Button>, | ||||
|  |                 ]} | ||||
|  |                 pagination={{ | ||||
|  |                     pageSize: pageSize, | ||||
|  |                     onChange: (page) => console.log(page), | ||||
|  |                 }} | ||||
|  |                 expandedRowKeys={activeExpRow} | ||||
|  |                 rowExpandable={(record) => { return true; }} | ||||
|  |                 expandedRowRender={expandRow} | ||||
|  |                 onExpand={ | ||||
|  |                     (expanded, record) => { | ||||
|  |                         const keys = []; | ||||
|  |                         if (expanded) { | ||||
|  |                             keys.push(record.Proto + record.Name); | ||||
|  |                         } | ||||
|  |                         console.log(keys); | ||||
|  |                         setActiveExpRow(keys); | ||||
|  |                     } | ||||
|  |                 } | ||||
|  |             > | ||||
|  |             </ProTable> | ||||
|  | 
 | ||||
|  |             { | ||||
|  |                 configModalVis ? | ||||
|  |                     <ConfigModal | ||||
|  |                         visible={true} | ||||
|  |                         close={() => { | ||||
|  |                             setConfigModalVis(false) | ||||
|  |                             setEditData(null) | ||||
|  |                         }} | ||||
|  |                         editData={editData} | ||||
|  |                     /> : '' | ||||
|  |             } | ||||
|  |             {/* </Spin> */} | ||||
|  |         </div> | ||||
|  |     ) | ||||
|  | } | ||||
|  | 
 | ||||
|  | function mapStateToProps(state) { | ||||
|  |     const { auth, global, factors } = state; | ||||
|  |     return { | ||||
|  |         user: auth.user, | ||||
|  |         actions: global.actions, | ||||
|  |         loading: factors.isRequesting, | ||||
|  |         factors: factors.data?.data ?? [], | ||||
|  |     }; | ||||
|  | } | ||||
|  | 
 | ||||
|  | export default connect(mapStateToProps)(FactorProfile); | ||||
| @ -0,0 +1,5 @@ | |||||
|  | 'use strict'; | ||||
|  | 
 | ||||
|  | import FactorProfile from './FactorProfile'; | ||||
|  | 
 | ||||
|  | export { FactorProfile }; | ||||
| @ -0,0 +1,4 @@ | |||||
|  | const GatewayMode = ["tcp", "udp", "mqtt", "http", "dtu"] | ||||
|  | export const InMode = GatewayMode | ||||
|  | export const OutMode = GatewayMode | ||||
|  | export const ProtocolTypes = ["DeviceA", "DeviceB", "DeviceC", "DeviceD"] | ||||
| @ -0,0 +1,15 @@ | |||||
|  | 'use strict'; | ||||
|  | 
 | ||||
|  | import reducers from './reducers'; | ||||
|  | import routes from './routes'; | ||||
|  | import actions from './actions'; | ||||
|  | import { getNavItem } from './nav-item'; | ||||
|  | 
 | ||||
|  | export default { | ||||
|  |     key: 'factor', | ||||
|  |     name: '监测因素', | ||||
|  |     reducers: reducers, | ||||
|  |     routes: routes, | ||||
|  |     actions: actions, | ||||
|  |     getNavItem: getNavItem | ||||
|  | }; | ||||
| @ -0,0 +1,16 @@ | |||||
|  | import React from 'react'; | ||||
|  | import { Link } from 'react-router-dom'; | ||||
|  | import { Menu } from 'antd'; | ||||
|  | import { SettingOutlined } from '@ant-design/icons'; | ||||
|  | 
 | ||||
|  | const SubMenu = Menu.SubMenu; | ||||
|  | 
 | ||||
|  | export function getNavItem(user, dispatch) { | ||||
|  |     return ( | ||||
|  |         <SubMenu key="factor" icon={<SettingOutlined />} title={'监测因素'}> | ||||
|  |             <Menu.Item key="factor_profile"> | ||||
|  |                 <Link to="/factor_profile/list">监测因素列表</Link> | ||||
|  |             </Menu.Item> | ||||
|  |         </SubMenu> | ||||
|  |     ); | ||||
|  | } | ||||
| @ -0,0 +1,5 @@ | |||||
|  | 'use strict'; | ||||
|  | 
 | ||||
|  | export default { | ||||
|  | 
 | ||||
|  | } | ||||
| @ -0,0 +1,12 @@ | |||||
|  | 'use strict'; | ||||
|  | import { FactorProfile} from './containers'; | ||||
|  | 
 | ||||
|  | export default [{ | ||||
|  |     type: 'inner', | ||||
|  |     route: { | ||||
|  |         path: '/factor_profile', | ||||
|  |         key: 'factor', | ||||
|  |         breadcrumb: '监测因素管理', | ||||
|  |         component: FactorProfile | ||||
|  |     } | ||||
|  | }]; | ||||
| @ -0,0 +1,3 @@ | |||||
|  | #example:hover { | ||||
|  |     font-size: larger; | ||||
|  | } | ||||
					Loading…
					
					
				
		Reference in new issue