yinweiwen
2 years ago
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