Browse Source

结构物添加

master
wenlele 2 years ago
parent
commit
465584b679
  1. 10
      code/web/client/src/layout/components/sider/index.jsx
  2. 47
      code/web/client/src/sections/edition/actions/index.js
  3. 3
      code/web/client/src/sections/edition/components/addModel.jsx
  4. 67
      code/web/client/src/sections/edition/components/plugInModel.jsx
  5. 56
      code/web/client/src/sections/edition/containers/gateway.jsx
  6. 28
      code/web/client/src/sections/edition/containers/plugIn.jsx
  7. 8
      code/web/client/src/utils/webapi.js
  8. 2
      code/web/config.js

10
code/web/client/src/layout/components/sider/index.jsx

@ -24,6 +24,12 @@ const Sider = props => {
}
setItems(nextItems)
scrollbar = new PerfectScrollbar('#page-slider', { suppressScrollX: true });
}, [])
useEffect(() => {
const lastSelectedKeys = localStorage.getItem('fs_iot_auth_selected_sider')
if (lastSelectedKeys) {
setSelectedKeys(JSON.parse(lastSelectedKeys))
@ -32,9 +38,7 @@ const Sider = props => {
if (lastOpenKeys) {
setOpenKeys(JSON.parse(lastOpenKeys))
}
scrollbar = new PerfectScrollbar('#page-slider', { suppressScrollX: true });
}, [])
}, [localStorage.getItem('fs_iot_auth_selected_sider')])
useEffect(() => {
if (scrollbar) {

47
code/web/client/src/sections/edition/actions/index.js

@ -186,7 +186,7 @@ export function getPlugInSet (edgeId, id) {
});
}
export function postAlterPlugIn (edgeId, id,query) {
export function postAlterPlugIn (edgeId, id, query) {
let data = ApiTable.postAlterPlugIn.replace('{edgeId}', edgeId)
return dispatch => basicAction({
type: 'post',
@ -199,6 +199,47 @@ export function postAlterPlugIn (edgeId, id,query) {
}
export function getEdgeList () { //获取网关id和序列号
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
actionType: 'GET_EDGE_LIST',
url: ApiTable.getEdgeList,
msg: { option: '获取网关id和编号' },
});
}
export function getPlugInPlatfromGroups (id) { //获取网关id和序列号
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
actionType: 'GET_PLUGIN_PLATFROM_GROUPS',
url: ApiTable.getPlugInPlatfromGroups.replace('{id}', id),
msg: { option: '获取平台计算和分组配置' },
});
}
export function postAddbind ( edgeId, data) {
return dispatch => basicAction({
type: 'post',
data,
dispatch: dispatch,
actionType: 'POST_ADD_BIND',
url: ApiTable.postAddbind.replace('{edgeId}',edgeId ),
msg: { option: '添加结构物' },
});
}
export function getThingList () { //获取网关id和序列号
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
actionType: 'GET_PLUGIN_PLATFROM_GROUPS',
url: ApiTable.getThingList,
msg: { option: '获取结构物列表' },
});
}
export default {
getGateways,
getGatewayStatus,
@ -217,4 +258,8 @@ export default {
delPlugIn,
getPlugInSet,
postAlterPlugIn,
getEdgeList,
getPlugInPlatfromGroups,
postAddbind,
getThingList,
};

3
code/web/client/src/sections/edition/components/addModel.jsx

@ -7,7 +7,7 @@ import { IconSearch, IconHelpCircle, IconAlertCircle, IconMinusCircle, IconPlusC
import { SkeletonScreen } from "$components";
const AddModel = props => {
const { dispatch, user, error, actions, close, dataToModal, editionData,cancel } = props
const { dispatch, user, error, actions, close, dataToModal, editionData, cancel } = props
const { edition } = actions
const [query, setQuery] = useState({ limit: 10, page: 0 }); //
const [limits, setLimits] = useState()//
@ -125,6 +125,7 @@ const AddModel = props => {
>
{editionData?.map((v, i) => <Form.Select.Option key={'softwareVer' + i} value={v}>{v}</Form.Select.Option>)}
</Form.Select>
<div style={{ display: 'flex', marginBottom: 12 }}>
<div style={{ width: 114, height: 44, padding: '6px 16px 6px 0', textIndent: 38, fontWeight: 600, color: 'var(--semi-color-text-0)', fontSize: 14 }}>设备属性:</div>
<Collapse style={{ width: 270, background: 'var(--semi-color-fill-0)' }}>

67
code/web/client/src/sections/edition/components/plugInModel.jsx

@ -7,18 +7,22 @@ import { IconSearch, IconHelpCircle, IconAlertCircle, IconMinusCircle, IconPlusC
import { SkeletonScreen } from "$components";
const AddModel = props => {
const { dispatch, user, error, actions, close, editionData, searchValue, dataToModal } = props
const { dispatch, user, error, actions, close, editionData, searchValue, dataToModal, cancel } = props
const { edition } = actions
const [query, setQuery] = useState({ limit: 10, page: 0 }); //
const [limits, setLimits] = useState()//
const [detailV, setDetailV] = useState(false)
const [property, setProperty] = useState([{ key: 'hb', value: 'ture' }])
const [type, setType] = useState('group') //
const [type, setType] = useState('antenna') //
const [isEditor, setIsEditor] = useState(false)
const [appearType, setAppearType] = useState('mqtt')
const api = useRef()
useEffect(() => {
if (dataToModal?.Plugin?.id) {
setType(dataToModal?.Plugin?.type)
setAppearType(dataToModal?.AntennaCtx?.type)
}
}, [])
@ -32,20 +36,23 @@ const AddModel = props => {
visible={true}
onOk={() => {
api.current.validate().then(r => {
console.log(r);
r.ctx_res = JSON.parse(r.ctx_res)
if (r.ctx_res) {
// r.ctx_res = JSON.parse(r.ctx_res)
}
if (r.ctx_group_content) {
// r.ctx_group_content='[0]'
}
// delete r.type
if (editionData) {
dispatch(edition.postAlterPlugIn(searchValue, editionData, r)).then(res => {
console.log(res)
if (res.success) {
// close()
close()
}
})
} else {
dispatch(edition.postAddPlugIn(searchValue, r)).then(res => {
if (res.success) {
console.log(res);
// console.log(res);
close()
}
})
@ -54,7 +61,7 @@ const AddModel = props => {
})
}}
width={560}
onCancel={() => close()}
onCancel={() => cancel()}
>
<Form
getFormApi={(formApi) => (api.current = formApi)}
@ -64,7 +71,6 @@ const AddModel = props => {
allowEmpty={true}
style={{ display: 'flex', flexDirection: 'column' }}
onValueChange={(_, v) => {
console.log(v);
if (v?.type) {
setType(v.type)
}
@ -92,7 +98,7 @@ const AddModel = props => {
initValue={dataToModal?.Plugin?.type || type}
rules={[{ required: true, message: "请选择类型" }]}
>
{[{ name: '上报', value: 'group' }, { name: '计算', value: 'antenna' }].map(v => <Form.Select.Option key={v.value} value={v.value}>{v.name}</Form.Select.Option>)}
{[{ name: '上报', value: 'antenna' }, { name: '计算', value: 'group' }].map(v => <Form.Select.Option key={v.value} value={v.value}>{v.name}</Form.Select.Option>)}
</Form.Select>
<Form.TextArea
field='description'
@ -109,9 +115,10 @@ const AddModel = props => {
label='是否启动:'
labelPosition="left"
style={{ marginBottom: 12 }}
initValue={dataToModal?.Plugin?.enable || true}
// checked={dataToModal?.Plugin?.id ? dataToModal?.Plugin?.enable : true}
initValue={dataToModal?.Plugin?.id ? dataToModal?.Plugin?.enable : true}
/>
{type == 'group' ?
{type == 'antenna' ?
<>
<Form.Select
field="ctx_type"
@ -152,42 +159,42 @@ const AddModel = props => {
{appearType == 'mqtt' ?
<>
<Form.Input field='ctx_param_ur' label='URL(必填):' labelPosition="left"
placeholder='127.0.0.1:1883' style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.name || ''}
placeholder='127.0.0.1:1883' style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.AntennaCtx?.params?.ur || ''}
/>
<Form.Input field='ctx_param_clientid' label='ClientlD:' labelPosition="left" placeholder='请输入ClientlD'
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.name || ''}
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.AntennaCtx?.params?.clientid || ''}
/>
<Form.Input field='ctx_param_username' label='用户名:' labelPosition="left" placeholder='请输入用户名'
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.name || ''}
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.AntennaCtx?.params?.username || ''}
/>
<Form.Input field='ctx_param_password' label='密码:' labelPosition="left" placeholder='请输入密码'
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.name || ''}
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.AntennaCtx?.params?.password || ''}
/>
<Form.Input field='ctx_param_topic' label='默认上报主题:' labelPosition="left" placeholder='请输入主题'
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.name || ''}
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.AntennaCtx?.params?.topic || ''}
/>
<Form.Input field='ctx_param_qos' label='默认上报QoS:' labelPosition="left" placeholder='0'
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.name || ''}
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.AntennaCtx?.params?.qos || ''}
/>
</>
: appearType == 'http' ?
<>
<Form.Input field='ctx_param_url' label='请求地址:' labelPosition="left"
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.name || ''}
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.AntennaCtx?.params?.url || ''}
/>
<Form.Input field='ctx_param_method' label='请求方法:' labelPosition="left" placeholder='post'
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.name || ''}
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.AntennaCtx?.params?.method || ''}
/>
<Form.Input field='ctx_param_headers' label='默认请求头:' labelPosition="left"
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.name || JSON.stringify({})}
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.AntennaCtx?.params?.headers || ''}
/>
</>
: <>
<Form.Input field='ctx_param_type' label='数据库类型:' labelPosition="left"
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.name || JSON.stringify({})}
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.AntennaCtx?.params?.type || ''}
/>
<Form.Input field='ctx_param_conn' label='连接字符串:' labelPosition="left"
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.name || JSON.stringify({})}
style={{ width: 180, marginBottom: 12 }} initValue={dataToModal?.AntennaCtx?.params?.conn || ''}
/>
</>
@ -213,14 +220,23 @@ const AddModel = props => {
/>
</>
: <>
<Button style={{ width: 182, marginBottom: 10, marginLeft: 104, color: '#0000009c', border: '1px solid #00000040', }}>获取平台计算和分组配置</Button>
<Button style={{ width: 182, marginBottom: 10, marginLeft: 104, color: '#0000009c', border: '1px solid #00000040', }}
onClick={() => {
dispatch(edition.getPlugInPlatfromGroups(editionData)).then(res => {
// console.log(res)
if (res.success) {
api.current.setValue('ctx_group_content', res.payload.data)
}
})
}}
>获取平台计算和分组配置</Button>
<Form.TextArea
field='ctx_group_content'
label='计算配置:'
labelPosition="left"
placeholder=''
style={{ width: 300, marginBottom: 12 }}
initValue={JSON.stringify(dataToModal?.GroupCtx?.groups) || JSON.stringify([])}
initValue={JSON.stringify(dataToModal?.GroupCtx?.groups) || '[]'}
autosize
rules={[{ required: true, message: "请输入计算配置" }]}
/>
@ -230,7 +246,6 @@ const AddModel = props => {
</Form>
</Modal>
</>
);
}

56
code/web/client/src/sections/edition/containers/gateway.jsx

@ -2,7 +2,7 @@
import React, { useEffect, useState, useRef } from 'react';
import { connect } from 'react-redux';
import { push } from 'react-router-redux';
import { Popconfirm, Button, Popover, Skeleton, Table, Tag, Input, Pagination } from '@douyinfe/semi-ui';
import { Popconfirm, Button, Popover, Skeleton, Table, Tag, Input, Pagination, TagInput, Modal, Select } from '@douyinfe/semi-ui';
import { IconSearch } from '@douyinfe/semi-icons';
import { SkeletonScreen } from "$components";
import GatewayStatusModal from './gatewayStatusModal'
@ -19,6 +19,10 @@ const GatewayManage = props => {
const [addModel, setAddModel] = useState(false)
const [editionData, setEditionData] = useState([])
const [searchValue, setSearchValue] = useState('')
const [addStruc, setAddStruc] = useState(false)
const [edgeId, setEdgeId] = useState('')
const [addStrucData, setAddStrucData] = useState([])
const [thingList, setThingList] = useState([])
useEffect(() => {
@ -29,6 +33,11 @@ const GatewayManage = props => {
setEditionData(data)
}
})
dispatch(edition.getThingList()).then(res => {
if (res.success) {
setThingList(res.payload.data?.data)
}
})
}, [])
const getTableData = (obj) => {
@ -100,7 +109,7 @@ const GatewayManage = props => {
dataIndex: "action",
key: "action",
render: (text, record) => {
return <div style={{ width: 168 }}>
return <div style={{ width: 210 }}>
<Popconfirm
title="提示"
position='leftBottom'
@ -111,7 +120,8 @@ const GatewayManage = props => {
<a style={aStyle}>{record.enabled ? '禁用' : '启用'}</a>
</Popconfirm>
<a style={{ ...aStyle, marginLeft: 15 }} onClick={() => {
localStorage.setItem('fs_iot_auth_selected_sider', JSON.stringify(['plugIn']))
localStorage.setItem('fs_iot_auth_open_sider', JSON.stringify(['edgeGateway']))
history.push({
pathname: '/edgeGateway/plugIn',
query: {
@ -146,7 +156,7 @@ const GatewayManage = props => {
<Popover key={Math.random()} content={renderPopover(record)} trigger='click' position='right'>
<a style={{ ...aStyle, marginLeft: 15 }}>更多...</a>
</Popover>
</div>
</div >
}
}
];
@ -190,8 +200,13 @@ const GatewayManage = props => {
}
})
}}>
<div style={{ ...aStyle }}>重启应用</div>
<div style={{ ...aStyle, marginBottom: 10 }}>重启应用</div>
</Popconfirm>
<div style={{ ...aStyle }} onClick={() => {
setAddStruc(true)
setEdgeId(record.id)
setAddStrucData(record.thingIds)
}}>绑定结构物</div>
</div>)
}
@ -341,6 +356,7 @@ const GatewayManage = props => {
<AddModel
dataToModal={dataToModal}
editionData={editionData}
thingList={thingList}
close={() => {
setAddModel(false);
setDataToModal({})
@ -354,6 +370,36 @@ const GatewayManage = props => {
/>
: ""
}
<Modal
title='添加结构物'
// okText={okText}
visible={addStruc}
onOk={() => {
dispatch(edition.postAddbind(edgeId, { thingIds: addStrucData })).then(res => {
if (res.success) {
getTableData({ ...query, name: searchValue })
setAddStruc(false)
setAddStrucData([])
}
})
}}
width={610}
onCancel={() => {
setAddStrucData([])
setAddStruc(false)
}}
>
<Select filter multiple style={{ width: 500 }} placeholder="请选择结构物" autoClearSearchValue={false} dropdownStyle={{ width: 500 }}
value={addStrucData}
onChange={v => {
console.log(v);
setAddStrucData(v)
}}
>
{thingList?.map(v => <Select.Option key={v.key} value={v.key}>{v.value}</Select.Option>)}
</Select>
</Modal>
</>
);

28
code/web/client/src/sections/edition/containers/plugIn.jsx

@ -13,7 +13,6 @@ import moment from 'moment'
const PlugIn = props => {
console.log(props);
const { dispatch, user, error, actions } = props
const { edition } = actions;
const [query, setQuery] = useState({ limit: 10, page: 0 }); //
@ -35,17 +34,21 @@ const PlugIn = props => {
useEffect(() => {
dispatch(edition.getGateways({})).then(res => {//
dispatch(edition.getEdgeList()).then(res => {//
if (res.success) {
let data = res.payload.data?.data?.map(r => ({ name: r.serialNo, value: r.id }))
let data = res.payload.data?.map(r => ({ name: r.serialNo, value: r.id }))
setSelectData(data)
setSearchValue(data[0]?.value)
getTableData({ id: data[0]?.value, limit: 10, page: 0 })
if (props?.history?.location?.query?.id) {
setSearchValue(props?.history?.location?.query?.id)
getTableData({ id: props?.history?.location?.query?.id, limit: 10, page: 0 })
} else {
setSearchValue(data[0]?.value)
getTableData({ id: data[0]?.value, limit: 10, page: 0 })
}
}
})
if(props){
}
}, [])
@ -209,7 +212,7 @@ const PlugIn = props => {
onSelect={(value, option) => {
console.log(value, option);
setSearchValue(value)
getTableData({ id: value, limit: 1, page: 0 })
getTableData({ id: value, limit: 10, page: 0 })
}}
>
{selectData?.map(r => <Select.Option value={r.value} key={r.value}>{r.name}</Select.Option>)}
@ -252,7 +255,7 @@ const PlugIn = props => {
pageSizeOpts={[10, 20, 30, 40]}
onChange={(page, pageSize) => {
setQuery({ limit: pageSize, page: page - 1 })
getTableData({ limit: pageSize, page: page - 1, name: searchValue })
getTableData({ limit: pageSize, page: page - 1, id: searchValue })
}}
/>
</div> : ""}
@ -272,6 +275,11 @@ const PlugIn = props => {
getTableData({ limit: 10, page: 0, id: searchValue });
setQuery({ limit: 10, page: 0 })
}}
cancel={() => {
setAddModel(false);
setEditionData('')
setDataToModal({})
}}
/>
: ""
}

8
code/web/client/src/utils/webapi.js

@ -21,9 +21,13 @@ export const ApiTable = {
postVersion: 'v1/version', //新增网关版本
getPlugInList: 'v1/edge/{id}/plugins', //插件列表
postAddPlugIn: 'v1/edge/{id}/plugin/new', //新增插件
postAlterPlugIn:'v1/edge/{edgeId}/plugin/{id}', //修改差插件
postAlterPlugIn: 'v1/edge/{edgeId}/plugin/{id}', //修改差插件
delPlugIn: 'v1/edge/{edgeId}/plugin/{id}', //删除网关插件
getPlugInSet:'v1/edge/{edgeId}/plugin/{id}', //获取网关插件信息
getPlugInSet: 'v1/edge/{edgeId}/plugin/{id}', //获取网关插件信息、
getEdgeList: 'v1/edge/list', //获取网关id和序列号
getPlugInPlatfromGroups: 'v1/edge/{id}/plugin/platform_groups', //获取平台计算和分组配置
postAddbind:'v1/edge/{edgeId}/bind', //绑定结构物
getThingList:'v1/thing/list', //获取结构物列表
};
export const RouteTable = {

2
code/web/config.js

@ -84,7 +84,7 @@ if (dev) {
,
logger: product.logger
}
config.logger.filename = path.join(__dirname, 'log', 'development.txt');
config.logger.filename = path.join(__dirname, 'log', 'development.txt')
} else {
config = product;
}

Loading…
Cancel
Save