16 changed files with 1981 additions and 22 deletions
File diff suppressed because one or more lines are too long
@ -0,0 +1,164 @@ |
|||||
|
'use strict' |
||||
|
import React, { Component } from 'react'; |
||||
|
import { Form, Select, DatePicker, Input, InputNumber,} from '@douyinfe/semi-ui'; |
||||
|
import moment from 'moment'; |
||||
|
|
||||
|
import Style from '../../style.less'; |
||||
|
|
||||
|
const FormItem = Form.Item; |
||||
|
const Option = Select.Option; |
||||
|
|
||||
|
class DimensionOption extends Component { |
||||
|
constructor(props) { |
||||
|
super(props); |
||||
|
this.formRef = React.createRef(); |
||||
|
this.state = { |
||||
|
dimensionUnit: props.info ? |
||||
|
props.info.type == "dimension" ? |
||||
|
props.info.dimension.scheme ? props.info.dimension.scheme.unit : "minute" |
||||
|
: null |
||||
|
: null, |
||||
|
dimensionMode: props.info ? |
||||
|
props.info.type == "dimension" ? |
||||
|
props.info.dimension.scheme ? props.info.dimension.scheme.mode : "R" |
||||
|
: null |
||||
|
: null, |
||||
|
showSenior: false, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
getFormItems = (info) => { |
||||
|
const { isEdit } = this.props; |
||||
|
const { dimensionMode } = this.state; |
||||
|
const formItemDimensionLayout = { |
||||
|
labelCol: { span: 7 }, |
||||
|
wrapperCol: { span: 15 } |
||||
|
} |
||||
|
|
||||
|
if (info) { |
||||
|
if (info.type == "dimension") { |
||||
|
|
||||
|
return ( |
||||
|
<div> |
||||
|
<Form |
||||
|
ref={this.formRef} |
||||
|
name="dimensionForm" |
||||
|
id="dimensionForm" |
||||
|
scrollToFirstError |
||||
|
> |
||||
|
<FormItem {...formItemDimensionLayout} label="采集策略" |
||||
|
name={`dimensionName`} |
||||
|
initialValue={info.hasOwnProperty('dimension') && info.dimension.scheme ? info.dimension.scheme.name : info.dimension.name} |
||||
|
> |
||||
|
<Input disabled={true} /> |
||||
|
</FormItem> |
||||
|
<FormItem {...formItemDimensionLayout} label="监测方式" |
||||
|
name={`mode`} |
||||
|
initialValue={info.hasOwnProperty('dimension') && info.dimension.scheme ? info.dimension.scheme.mode : "R"} |
||||
|
> |
||||
|
<Select> |
||||
|
<Option value="R">周期</Option> |
||||
|
<Option value="L">监听</Option> |
||||
|
</Select> |
||||
|
</FormItem> |
||||
|
<FormItem {...formItemDimensionLayout} label="间隔" style={dimensionMode == "R" ? {} : { display: "none" }} |
||||
|
name={`interval_1`} |
||||
|
initialValue={info.hasOwnProperty('dimension') && info.dimension.scheme ? info.dimension.scheme.interval : 30} |
||||
|
> |
||||
|
<InputNumber style={{ width: '75%', marginRight: 0 }} disabled={!isEdit} /> |
||||
|
<Select value={this.state.dimensionUnit} style={{ width: '25%' }} > |
||||
|
<Option value="month">月</Option> |
||||
|
<Option value="week">周</Option> |
||||
|
<Option value="day">日</Option> |
||||
|
<Option value="hour">时</Option> |
||||
|
<Option value="minute">分</Option> |
||||
|
{/* <Options value="second">秒</Options> */} |
||||
|
</Select> |
||||
|
</FormItem> |
||||
|
<FormItem {...formItemDimensionLayout} label="开始时间" |
||||
|
name={`beginTime`} |
||||
|
initialValue={info.hasOwnProperty('dimension') && info.dimension.scheme ? info.dimension.scheme.beginTime ? moment(info.dimension.scheme.beginTime) : moment() : moment()} |
||||
|
|
||||
|
> |
||||
|
<DatePicker |
||||
|
showTime |
||||
|
format="YYYY-MM-DD HH:mm:ss" |
||||
|
placeholder="选择开始时间" |
||||
|
/> |
||||
|
</FormItem> |
||||
|
<FormItem {...formItemDimensionLayout} label="结束时间" |
||||
|
name={`endTime`} |
||||
|
initialValue={info.hasOwnProperty('dimension') && info.dimension.scheme ? info.dimension.scheme.endTime ? moment(info.dimension.scheme.endTime) : null : null} |
||||
|
|
||||
|
> |
||||
|
<DatePicker |
||||
|
showTime |
||||
|
format="YYYY-MM-DD HH:mm:ss" |
||||
|
placeholder="结束时间,未设置表示无期限" |
||||
|
/> |
||||
|
</FormItem> |
||||
|
<FormItem {...formItemDimensionLayout} label="方案数据通知" style={{ display: "none" }} |
||||
|
name={`notifyMode`} |
||||
|
initialValue={info.hasOwnProperty('dimension') && info.dimension.scheme ? info.dimension.scheme.notifyMode.toString() : "1"} |
||||
|
|
||||
|
> |
||||
|
<Select> |
||||
|
<Option value="1">所有设备</Option> |
||||
|
<Option value="2">单个设备</Option> |
||||
|
</Select> |
||||
|
</FormItem> |
||||
|
<FormItem {...formItemDimensionLayout} label="设备数据通知" style={{ display: "none" }} |
||||
|
name={'dimension'} |
||||
|
initialValue={info.hasOwnProperty('dimension') && info.dimension.scheme ? info.dimension.scheme.capabilityNotifyMode.toString() : "1"} |
||||
|
> |
||||
|
<Select> |
||||
|
<Option value="1">组合</Option> |
||||
|
<Option value="2">每次</Option> |
||||
|
</Select> |
||||
|
</FormItem> |
||||
|
</Form> |
||||
|
</div> |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
componentDidMount() { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
UNSAFE_componentWillReceiveProps = (nextProps) => { |
||||
|
if (nextProps.info != this.props.info) { |
||||
|
const { info } = nextProps |
||||
|
const curForm = this.formRef.current |
||||
|
if (curForm) { |
||||
|
this.formRef.current.resetFields(); |
||||
|
} |
||||
|
this.setState({ |
||||
|
dimensionUnit: info ? info.type == "dimension" ? info.hasOwnProperty('dimension') && info.dimension.scheme ? info.dimension.scheme.unit : "minute" : null : null, |
||||
|
dimensionMode: info ? info.type == "dimension" ? info.hasOwnProperty('dimension') && info.dimension.scheme ? info.dimension.scheme.mode : "R" : null : null |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
render() { |
||||
|
const { isEdit, info, height } = this.props; |
||||
|
return ( |
||||
|
<div className={Style.option_modal} id="OptionModal" style={{ height: height - 72 }}> |
||||
|
{ |
||||
|
info ? |
||||
|
<div> |
||||
|
{this.getFormItems(info)} |
||||
|
</div> |
||||
|
: null |
||||
|
} |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default DimensionOption; |
@ -0,0 +1,161 @@ |
|||||
|
import React, { useState, useEffect } from 'react'; |
||||
|
import { PinyinHelper } from '@peace/utils'; |
||||
|
|
||||
|
// const { G6 } = window;
|
||||
|
// import G6 from '@antv/g6';
|
||||
|
|
||||
|
let uniqueId = 0; |
||||
|
|
||||
|
function generateUniqueId() { |
||||
|
return `rc-g6-${uniqueId++}`; |
||||
|
} |
||||
|
|
||||
|
function createG6(__operation) { |
||||
|
const editMap = ({ ...props }) => { |
||||
|
const { |
||||
|
emitChange, changeFinish, width, height, handelNodeClick, handleNodeEnter, |
||||
|
onCollapse, setG6Tree, setG6TreeData, data, targetNode, emitDataChange_, |
||||
|
} = props; |
||||
|
const [treeRef, setTreeRef] = useState(null); |
||||
|
const [isItemClicking, setIsItemClicking] = useState(false); |
||||
|
const [orientation, setOrientation] = useState(false); |
||||
|
const [treeId, setTreeId] = useState(generateUniqueId()); |
||||
|
// let treeId = generateUniqueId();
|
||||
|
const themeKey = localStorage.getItem('theme-name'); |
||||
|
|
||||
|
const selectNode = (node) => { |
||||
|
handelNodeClick && handelNodeClick(node); |
||||
|
}; |
||||
|
const toolTipMsg = (node) => handleNodeEnter(node); |
||||
|
const initTree = (prop) => { |
||||
|
|
||||
|
const { Global } = G6; |
||||
|
|
||||
|
Global.nodeAcitveBoxStyle = { |
||||
|
stroke: '#108EE9', |
||||
|
fill: '#00B5F4', |
||||
|
fillOpacity: 0.2, |
||||
|
lineWidth: 2, |
||||
|
radius: 4, |
||||
|
}; |
||||
|
const grid = themeKey === 'light' ? { |
||||
|
grid: { |
||||
|
cell: 10, |
||||
|
line: { |
||||
|
stroke: '#eee', |
||||
|
}, |
||||
|
}, |
||||
|
} : {}; |
||||
|
const tree = new G6.Tree({ |
||||
|
id: treeId, |
||||
|
fitView: 'cc', |
||||
|
layoutCfg: { |
||||
|
direction: 'TB', |
||||
|
getHGap(/* d */) { |
||||
|
return 10; |
||||
|
}, |
||||
|
getVGap(/* d */) { |
||||
|
return 10; |
||||
|
}, |
||||
|
}, |
||||
|
...grid, |
||||
|
...prop, |
||||
|
}); |
||||
|
tree.addBehaviour('default', ['clickActive']); |
||||
|
tree.addBehaviour('default', ['clickBlankClearActive']); |
||||
|
tree.tooltip({ |
||||
|
title: '标题', // @type {String} 标题
|
||||
|
split: '=>', // @type {String} 分割符号
|
||||
|
dx: 10, // @type {Number} 水平偏移
|
||||
|
dy: 10, // @type {Number} 竖直偏移
|
||||
|
}); |
||||
|
// tree.node().tooltip('采集策略为空,请在左上角【+ 采集策略】添加至少一种采集策略,再进行相关设备的添加配置');
|
||||
|
tree.edge().shape('smooth'); |
||||
|
tree.on('itemclick', (ev) => { |
||||
|
setIsItemClicking(true); |
||||
|
|
||||
|
const { item } = ev; |
||||
|
const { shape } = ev; |
||||
|
if (shape && !shape.hasClass('Button')) { |
||||
|
selectNode(item); |
||||
|
} |
||||
|
}).on('itemunactived', (ev) => { |
||||
|
selectNode(); |
||||
|
}).on('itemmouseenter', (ev) => { |
||||
|
if (ev.itemType !== 'node') { |
||||
|
return; |
||||
|
} |
||||
|
const dd = toolTipMsg(null); |
||||
|
if (dd) { |
||||
|
tree.tooltip({ |
||||
|
split: '!', |
||||
|
dx: 10, |
||||
|
dy: 10, |
||||
|
}); |
||||
|
} else { |
||||
|
tree.tooltip(false); |
||||
|
} |
||||
|
const keyShape = ev.item.getKeyShape(); |
||||
|
keyShape.attr({ |
||||
|
lineWidth: 2, |
||||
|
}); |
||||
|
tree.refresh(); |
||||
|
}).on('itemmouseleave', (ev) => { |
||||
|
if (ev.itemType !== 'node') { |
||||
|
return; |
||||
|
} |
||||
|
const keyShape = ev.item.getKeyShape(); |
||||
|
keyShape.attr({ |
||||
|
lineWidth: 1, |
||||
|
}); |
||||
|
tree.refresh(); |
||||
|
}) |
||||
|
.on('collapse', (ev) => { |
||||
|
onCollapse(ev.item._attrs.model, true); |
||||
|
}) |
||||
|
.on('spreadout', (ev) => { |
||||
|
onCollapse(ev.item._attrs.model, false); |
||||
|
}); |
||||
|
__operation(tree); |
||||
|
setTreeRef(tree); |
||||
|
setG6Tree(tree); |
||||
|
setG6TreeData(data); |
||||
|
}; |
||||
|
useEffect(() => { |
||||
|
initTree(props); |
||||
|
return () => { |
||||
|
treeRef && treeRef.destroy(); |
||||
|
setTreeRef(null); |
||||
|
}; |
||||
|
}, []); |
||||
|
|
||||
|
|
||||
|
useEffect(() => { |
||||
|
treeRef && treeRef.changeSize(width, height); |
||||
|
}, [width, height]); |
||||
|
|
||||
|
useEffect(() => { |
||||
|
if (emitChange == true || data) { |
||||
|
treeRef && treeRef.changeData(data); |
||||
|
treeRef && treeRef.refresh(); |
||||
|
changeFinish(); |
||||
|
} |
||||
|
}, [emitChange, data]); |
||||
|
|
||||
|
return ( |
||||
|
<div id={treeId} /> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
return React.memo(editMap, (prevProps, nextProps) => { |
||||
|
if ((prevProps.emitChange !== nextProps.emitChange) |
||||
|
|| (nextProps.width !== prevProps.width) |
||||
|
|| (nextProps.height !== prevProps.height)) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
export default createG6; |
@ -0,0 +1,97 @@ |
|||||
|
'use strict' |
||||
|
|
||||
|
import React, { useState, useEffect } from 'react'; |
||||
|
// import { useSafeState } from 'ahooks';
|
||||
|
import { Tabs, message, } from '@douyinfe/semi-ui'; |
||||
|
import moment from 'moment'; |
||||
|
import Option from './option'; |
||||
|
import DimensionOption from './dimensionOption'; |
||||
|
import State from './state'; |
||||
|
import { ApiTable } from '$utils'; |
||||
|
import { Request } from '@peace/utils' |
||||
|
|
||||
|
const TabPane = Tabs.TabPane; |
||||
|
|
||||
|
export default ({ ...props }) => { |
||||
|
const { isEdit, devices, info, parentNode, dimensions, height, deviceMetas, dispatch } = props; |
||||
|
const [linkState, setLinkState] = useState(null); |
||||
|
const [alarmMsg, setAlarmMsg] = useState({ new: [], history: [] }); |
||||
|
const [currentDeviceId, setCurrentDeviceId] = useState(null); |
||||
|
const [activeKey, setActiveKey] = useState('1'); |
||||
|
const callback = (key) => { |
||||
|
setActiveKey(key) |
||||
|
} |
||||
|
useEffect(() => { |
||||
|
console.log(3213213, info); |
||||
|
if (info) { |
||||
|
if (info?.linkState) { |
||||
|
setLinkState(info.linkState) |
||||
|
} |
||||
|
// if (info?.device?.id && info.device.id != currentDeviceId) {
|
||||
|
// setCurrentDeviceId(info.device.id);
|
||||
|
// setActiveKey('1');
|
||||
|
// let url = ApiTable.getDevicesLlinkStatus.replace('{deviceId}', info.device.id);
|
||||
|
|
||||
|
// Request.get(url)
|
||||
|
// .then(res => {
|
||||
|
// setLinkState(res.status)
|
||||
|
// }, error => {
|
||||
|
// message.warning('设备在线状态获取失败');
|
||||
|
// });
|
||||
|
|
||||
|
// url = ApiTable.getDeviceAlarms.replace('{deviceId}', info.device.id);
|
||||
|
|
||||
|
// Request.get(url, { limit: 5 })
|
||||
|
// .then(res => {
|
||||
|
// setAlarmMsg({ new: res.new || [], history: res.history || [] })
|
||||
|
// }
|
||||
|
// , error => {
|
||||
|
// message.warning('设备告警信息获取失败');
|
||||
|
// });
|
||||
|
// }
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
}, [info]); |
||||
|
let tab = "属性"; |
||||
|
if (info && info?.type == "equipment") { |
||||
|
tab = "属性" |
||||
|
} else if (info && info?.type == "dimension") { |
||||
|
tab = "采集策略" |
||||
|
} |
||||
|
return ( |
||||
|
<Tabs defaultActiveKey="1" activeKey={activeKey} onChange={callback} style={{ paddingRight: 16 }}> |
||||
|
<TabPane tab={tab} key="1"> |
||||
|
{info && parentNode ? |
||||
|
info.type == "equipment" ? |
||||
|
<Option |
||||
|
isEdit={isEdit} |
||||
|
devices={devices} |
||||
|
info={info} |
||||
|
parentNode={parentNode} |
||||
|
deviceMetas={deviceMetas} |
||||
|
dimensions={dimensions} |
||||
|
height={height} |
||||
|
dispatch={dispatch} |
||||
|
/> |
||||
|
: < DimensionOption |
||||
|
isEdit={isEdit} |
||||
|
info={info} |
||||
|
height={height} |
||||
|
/> |
||||
|
: null |
||||
|
} |
||||
|
</TabPane> |
||||
|
{ |
||||
|
parentNode && info && info.meta && info.meta.filteredResource && (JSON.parse(info.meta.filteredResource.properties).deviceType != 'dau.node') ? |
||||
|
<TabPane tab="状态" key="2"> |
||||
|
<State |
||||
|
linkState={linkState} |
||||
|
alarmMsg={alarmMsg} |
||||
|
/> |
||||
|
</TabPane> : null |
||||
|
} |
||||
|
</Tabs> |
||||
|
) |
||||
|
|
||||
|
} |
@ -0,0 +1,294 @@ |
|||||
|
import React, { useState, useEffect } from 'react'; |
||||
|
import moment from 'moment'; |
||||
|
import { Input, Button, SideSheet, } from '@douyinfe/semi-ui'; |
||||
|
|
||||
|
// import { useSafeState } from 'ahooks';
|
||||
|
|
||||
|
import Immutable from 'immutable'; |
||||
|
import { AuthorizationCode } from '$utils'; |
||||
|
import { Func } from '@peace/utils'; |
||||
|
// import { PlusOutlined } from '@ant-design/icons';
|
||||
|
import { IconPlus } from '@douyinfe/semi-icons'; |
||||
|
import EquipmentOption from './equipment-option'; |
||||
|
import ZuwangMain from './zuwang-main'; |
||||
|
|
||||
|
|
||||
|
const { ModifyEquipmentNetworking } = AuthorizationCode; |
||||
|
|
||||
|
export default function ({ ...props }) { |
||||
|
const { |
||||
|
dispatch, clientHeight, deviceMetasWithFollow, deviceList, dimensionlist, struct, |
||||
|
} = props; |
||||
|
const [g6TreeDirection, setG6TreeDirection] = useState('TB'); |
||||
|
const [devices, setDevices] = useState(null); |
||||
|
const [selectedNode, setSelectedNode] = useState(null); |
||||
|
const [selectedParentNode, setSelectedParentNode] = useState(null); |
||||
|
const [emitDataChange, setEmitDataChange] = useState(false); |
||||
|
const [collapseAll, setCollapseAll] = useState(false); |
||||
|
const [collapsed, setCollapsed] = useState([]); |
||||
|
const [expandAll, setExpandAll] = useState(false); |
||||
|
const [expanded, setExpanded] = useState([]); |
||||
|
const [targetNode, setTargetNode] = useState(''); |
||||
|
const [showOptionModal, setShowOptionModal] = useState(false); |
||||
|
const [clientWidth, setClientWidth] = useState(document.body.clientWidth - 64 - 20 - 16 - 2); |
||||
|
const [dimensions, setDimensions] = useState({}); |
||||
|
const [sensorsId, setSensorsId] = useState([]); |
||||
|
const [sensorsDataItems, setSensorsDataItems] = useState({}); |
||||
|
const [foldAllG6ToCenter, setFoldAllG6ToCenter] = useState(false); |
||||
|
const [inputSearching, setInputSearching] = useState(false); |
||||
|
|
||||
|
useEffect(() => { |
||||
|
if (deviceMetasWithFollow?.devices) { |
||||
|
|
||||
|
if (deviceList?.instances) { |
||||
|
const sensorsId = []; |
||||
|
const sensorsDataItems = {}; |
||||
|
for (const id in deviceList.instances) { |
||||
|
const instances = deviceList.instances[id]; |
||||
|
if (instances.type == 's.d' && instances.instance.properties.deviceType == 'sensor') { |
||||
|
const meta = deviceMetasWithFollow.devices.find((m) => m.id == instances.instance.deviceMetaId); |
||||
|
sensorsDataItems[id] = { |
||||
|
items: {}, |
||||
|
deviceName: instances.name, |
||||
|
}; |
||||
|
if (meta) { |
||||
|
sensorsDataItems[id].items = meta.capabilities[0].properties.reduce((p, n) => { |
||||
|
if (n.category == 'Output') { |
||||
|
p[n.name] = { name: n.showName, unit: n.unit }; |
||||
|
} |
||||
|
return p; |
||||
|
}, {}); |
||||
|
} |
||||
|
sensorsId.push(id); |
||||
|
} |
||||
|
} |
||||
|
setSensorsId(sensorsId); |
||||
|
setSensorsDataItems(sensorsDataItems); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (deviceList?.instances) { |
||||
|
const newInstances = { ...deviceList.instances, ...dimensionlist }; |
||||
|
setDevices({ ...deviceList, instances: newInstances }); |
||||
|
} else if (!devices) { |
||||
|
const data = { instances: {} }; |
||||
|
const uuidNode = guid(); |
||||
|
data.instances[uuidNode] = { |
||||
|
instance: {}, |
||||
|
svg: { |
||||
|
compX: 0, |
||||
|
compY: 0, |
||||
|
isSelected: false, |
||||
|
rotateAng: 0, |
||||
|
scaleX: 1, |
||||
|
scaleY: 1, |
||||
|
x: 2498, |
||||
|
y: 1083, |
||||
|
}, |
||||
|
type: 's.iota', |
||||
|
}; |
||||
|
data.settings = { |
||||
|
grid: { |
||||
|
step: 20, |
||||
|
}, |
||||
|
height: 3072, |
||||
|
padding: 40, |
||||
|
scale: 10, |
||||
|
scrollLeft: 2047, |
||||
|
scrollTop: 1082, |
||||
|
width: 5120, |
||||
|
}; |
||||
|
setDevices(data); |
||||
|
} |
||||
|
}, [deviceList, deviceMetasWithFollow]); |
||||
|
|
||||
|
const guid = () => 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { |
||||
|
const r = Math.random() * 16 | 0; const |
||||
|
v = c == 'x' ? r : (r & 0x3 | 0x8); |
||||
|
return v.toString(16); |
||||
|
}); |
||||
|
|
||||
|
const closeOptionModal = () => { |
||||
|
setShowOptionModal(false); |
||||
|
setSelectedNode(null); |
||||
|
}; |
||||
|
|
||||
|
const _handelNodeClick = (node) => { |
||||
|
if (node) { |
||||
|
const targetId = node.get('model').id; |
||||
|
const selectedNode = { ...devices?.instances[targetId], id: targetId }; |
||||
|
const deviceMetaId = selectedNode?.instance?.deviceMetaId; |
||||
|
const selectedDeviceMetaArr = []; |
||||
|
let selectedDeviceMeta; |
||||
|
if (selectedDeviceMetaArr.length == 0) { |
||||
|
selectedDeviceMeta = deviceMetasWithFollow && deviceMetasWithFollow.devices |
||||
|
? deviceMetasWithFollow.devices.filter((s) => s.id == deviceMetaId)[0] |
||||
|
: []; |
||||
|
} else { |
||||
|
selectedDeviceMeta = selectedDeviceMetaArr[0]; |
||||
|
} |
||||
|
if (selectedNode.type && selectedNode.type != 's.iota') { |
||||
|
// parentNode
|
||||
|
|
||||
|
const parentNode = Object.keys(devices.instances).reduce((p, k) => { |
||||
|
const instance = devices.instances[k]; |
||||
|
if (instance.type == 's.l' && instance.instance.from.ownerSvgId == targetId) { |
||||
|
p = { ...devices.instances[instance.instance.to.ownerSvgId], id: instance.instance.to.ownerSvgId }; |
||||
|
} |
||||
|
return p; |
||||
|
}, null); |
||||
|
|
||||
|
const selectedParentNodeMetaId = parentNode ? parentNode.instance.deviceMetaId : null; |
||||
|
const selectedParentNodeMeta = selectedParentNodeMetaId ? deviceMetasWithFollow.devices.filter((s) => s.id == selectedParentNodeMetaId)[0] : null; |
||||
|
|
||||
|
setSelectedNode({ type: 'equipment', device: selectedNode, meta: selectedDeviceMeta }); |
||||
|
setSelectedParentNode({ type: 'equipment', device: parentNode, meta: selectedParentNodeMeta }); |
||||
|
setShowOptionModal(true); |
||||
|
} else { |
||||
|
setShowOptionModal(false); |
||||
|
setSelectedNode(null); |
||||
|
setSelectedParentNode(null); |
||||
|
} |
||||
|
} else { |
||||
|
setShowOptionModal(false); |
||||
|
setSelectedNode(null); |
||||
|
setSelectedParentNode(null); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
const emitDataChange_ = () => { |
||||
|
setEmitDataChange(true); |
||||
|
}; |
||||
|
|
||||
|
const _finishDataChange = () => { |
||||
|
setEmitDataChange(false); |
||||
|
}; |
||||
|
|
||||
|
const handleNodeEnter = (node) => { |
||||
|
const result = dimensionlist?.dimensions?.length <= 0; |
||||
|
return result; |
||||
|
}; |
||||
|
const onCollapse = (model, collapse) => { |
||||
|
if (collapse) { |
||||
|
setCollapsed(collapsed.concat([model.id])); |
||||
|
setExpanded(expanded.filter((c) => c != model.id)); |
||||
|
} else { |
||||
|
setCollapsed(collapsed.filter((c) => c != model.id)); |
||||
|
setExpanded(expanded.concat([model.id])); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
const resetFoldAllG6ToCenter = () => { |
||||
|
setFoldAllG6ToCenter(false); |
||||
|
}; |
||||
|
|
||||
|
const changeG6TreeDirection = () => { |
||||
|
setG6TreeDirection(g6TreeDirection == 'TB' ? 'LR' : 'TB'); |
||||
|
setShowOptionModal(false); |
||||
|
}; |
||||
|
const containerHeight = clientHeight - 270; |
||||
|
|
||||
|
return ( |
||||
|
<div id="flag" style={{ position: "relative" }}> |
||||
|
<div style={{ |
||||
|
position: 'absolute', top: 10, left: 0, zIndex: 2, |
||||
|
}} |
||||
|
> |
||||
|
<Button |
||||
|
style={{ marginRight: 12, marginBottom: 12, float: 'left' }} |
||||
|
type="primary" theme='solid' |
||||
|
onClick={() => { |
||||
|
setExpandAll(false); |
||||
|
setCollapseAll(true); |
||||
|
setCollapsed([]); |
||||
|
setExpanded([]); |
||||
|
setEmitDataChange(true); |
||||
|
// setFoldAllG6ToCenter(true);
|
||||
|
setTargetNode(''); |
||||
|
document.getElementById('searchInput').value = ''; |
||||
|
}} |
||||
|
> |
||||
|
折叠全部 |
||||
|
</Button> |
||||
|
<Button |
||||
|
type="primary" theme='solid' |
||||
|
style={{ marginRight: 12, marginBottom: 12, float: 'left' }} |
||||
|
onClick={() => { |
||||
|
setCollapseAll(false); |
||||
|
setExpandAll(true); |
||||
|
setCollapsed([]); |
||||
|
setExpanded([]); |
||||
|
setEmitDataChange(true); |
||||
|
setTargetNode(''); |
||||
|
document.getElementById('searchInput').value = ''; |
||||
|
}} |
||||
|
> |
||||
|
展开全部 |
||||
|
</Button> |
||||
|
|
||||
|
<Button type="primary" theme='solid' style={{ marginLeft: 12, marginBottom: 12 }} onClick={changeG6TreeDirection}>组图方向</Button> |
||||
|
<span style={{ float: 'left' }}> |
||||
|
<Input |
||||
|
style={{ width: 200 }} |
||||
|
id="searchInput" |
||||
|
onEnterPress={(e) => { |
||||
|
setTargetNode(e.target.value); |
||||
|
setInputSearching(true); |
||||
|
// localStorage.setItem('inputSearching', true)
|
||||
|
}} |
||||
|
/> |
||||
|
</span> |
||||
|
</div> |
||||
|
{ |
||||
|
devices?.instances |
||||
|
&& ( |
||||
|
<ZuwangMain |
||||
|
data={devices.instances} |
||||
|
collapseAll={collapseAll} |
||||
|
expandAll={expandAll} |
||||
|
collapsed={collapsed} |
||||
|
expanded={expanded} |
||||
|
onCollapse={onCollapse} |
||||
|
width={clientWidth} |
||||
|
height={containerHeight} |
||||
|
emitChange={emitDataChange} |
||||
|
emitDataChange_={emitDataChange_} |
||||
|
changeFinish={_finishDataChange} |
||||
|
handelNodeClick={_handelNodeClick} |
||||
|
targetNode={targetNode} |
||||
|
inputSearching={inputSearching} |
||||
|
setInputSearching={setInputSearching} |
||||
|
struct={struct} |
||||
|
handleNodeEnter={handleNodeEnter} |
||||
|
foldAllG6ToCenter={foldAllG6ToCenter} |
||||
|
resetFoldAllG6ToCenter={resetFoldAllG6ToCenter} |
||||
|
g6TreeDirection={g6TreeDirection} |
||||
|
/> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
<SideSheet |
||||
|
getPopupContainer={() => document.getElementById('flag')} |
||||
|
style={{ position: 'absolute' }} |
||||
|
mask={false} |
||||
|
maskClosable={false} |
||||
|
visible={showOptionModal} |
||||
|
width={480} |
||||
|
onCancel={closeOptionModal} |
||||
|
bodyStyle={{ padding: 8 }} |
||||
|
> |
||||
|
<EquipmentOption |
||||
|
isEdit={false} |
||||
|
struct={struct} |
||||
|
devices={devices} |
||||
|
deviceMetas={deviceMetasWithFollow} |
||||
|
info={selectedNode} |
||||
|
parentNode={selectedParentNode} |
||||
|
dimensions={dimensionlist} |
||||
|
height={containerHeight} |
||||
|
dispatch={dispatch} |
||||
|
/> |
||||
|
</SideSheet> |
||||
|
</div> |
||||
|
); |
||||
|
} |
@ -0,0 +1,650 @@ |
|||||
|
'use strict'; |
||||
|
import React, { Component } from 'react'; |
||||
|
import { Form, Select, Input, InputNumber, Switch, Row, Col, Button, Popconfirm, Collapse, Tag } from '@douyinfe/semi-ui'; |
||||
|
import PerfectScrollbar from 'perfect-scrollbar'; |
||||
|
import Style from '../../style.less'; |
||||
|
import { sort } from '@peace/utils'; |
||||
|
|
||||
|
const FormItem = Form.Item; |
||||
|
|
||||
|
const Panel = Collapse.Panel |
||||
|
|
||||
|
const productTypes = { |
||||
|
"DTU": "DTU", |
||||
|
"gateway": "网关", |
||||
|
"sensor": "传感器", |
||||
|
"acqUnit": "采集单元", |
||||
|
"dau.gateway": '分布式智能云采集网关', |
||||
|
"dau.node": '分布式智能云采集节点', |
||||
|
"tcp.dtu": '工作站' |
||||
|
} |
||||
|
|
||||
|
class Option extends Component { |
||||
|
constructor(props) { |
||||
|
super(props); |
||||
|
this.saving = false; |
||||
|
this.formRef = React.createRef(); |
||||
|
let tempShowSenior = false; |
||||
|
if (props.info && props.devices && props.info.type == "equipment" && props.info.meta && |
||||
|
props.info.meta.interfaces && props.info.meta.interfaces.length && props.info.meta.capabilities && |
||||
|
props.info.meta.capabilities.length && props.parentNode) { |
||||
|
let upInterface = this.getUpLinkInterface(props.info.meta, props.parentNode); |
||||
|
let interfaceMetaId = upInterface ? upInterface.id : null, |
||||
|
capabilityMetaIds = props.info.meta.capabilities.filter(c => c.interfaces.some(i => i.deviceMetaInterfaceId == interfaceMetaId) && c.capabilityCategoryId == 3), |
||||
|
capabilityMetaId = capabilityMetaIds.length > 0 ? capabilityMetaIds[0].id : null; |
||||
|
let targetDimension = interfaceMetaId && capabilityMetaId ? props.info.device.instance.interfaces[interfaceMetaId]?.capabilities[capabilityMetaId]?.dimension : null; |
||||
|
if (targetDimension && targetDimension.dimensionId) { |
||||
|
let devicesKeys = Object.keys(props.devices.instances); |
||||
|
if (devicesKeys.includes(targetDimension.dimensionId) && props.devices.instances[targetDimension.dimensionId].instance && props.devices.instances[targetDimension.dimensionId].instance.mode == "L") { |
||||
|
tempShowSenior = false; |
||||
|
} else { |
||||
|
tempShowSenior = true |
||||
|
} |
||||
|
} else { |
||||
|
tempShowSenior = false |
||||
|
} |
||||
|
} else { |
||||
|
tempShowSenior = false |
||||
|
} |
||||
|
this.state = { |
||||
|
showSenior: tempShowSenior, |
||||
|
selectedFormulaId: null |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
componentDidUpdate() { |
||||
|
this.Ps ? this.Ps.update() : '' |
||||
|
} |
||||
|
|
||||
|
UNSAFE_componentWillReceiveProps = (nextProps) => { |
||||
|
if (nextProps.info != this.props.info) { |
||||
|
const { info, devices } = nextProps |
||||
|
const { current } = this.formRef |
||||
|
if (current) current.resetFields(); |
||||
|
if (info && devices && info.type == "equipment" && info.meta && info.meta.interfaces.length && info.meta.capabilities.length) { |
||||
|
let upInterface = info.meta.interfaces.filter(i => i.directType == 1); |
||||
|
|
||||
|
let interfaceMetaId = upInterface.length > 0 ? upInterface[0].id : null, |
||||
|
capabilityMetaId = info.meta.capabilities[0].id; |
||||
|
let targetDimension = interfaceMetaId ? info.device.instance.interfaces[interfaceMetaId] ? info.device.instance.interfaces[interfaceMetaId].capabilities[capabilityMetaId].dimension : null : null; |
||||
|
if (targetDimension && targetDimension.dimensionId) { |
||||
|
let devicesKeys = Object.keys(devices.instances); |
||||
|
if (devicesKeys.includes(targetDimension.dimensionId) && devices.instances[targetDimension.dimensionId].instance && devices.instances[targetDimension.dimensionId].instance.mode == "L") { |
||||
|
this.setState({ "showSenior": false }); |
||||
|
} else { |
||||
|
this.setState({ "showSenior": true }); |
||||
|
} |
||||
|
} else { |
||||
|
this.setState({ "showSenior": false }); |
||||
|
} |
||||
|
} else { |
||||
|
this.setState({ "showSenior": false }); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
componentDidMount() { |
||||
|
this.Ps = new PerfectScrollbar(document.getElementById('optionModal'), { suppressScrollX: true }) |
||||
|
} |
||||
|
|
||||
|
_enableSelectStrategy(device, parentNode) { |
||||
|
|
||||
|
if (device.capabilities.length == 0) return false; |
||||
|
const parentNodeCapabilities = parentNode.meta && parentNode.meta.capabilities.length > 0 ? |
||||
|
parentNode.meta.capabilities : null; |
||||
|
if ((device.capabilities.some(c => c.capabilityCategoryId == 3)) && (!parentNodeCapabilities || !parentNodeCapabilities.some(c => c.capabilityCategoryId == 3))) { |
||||
|
return true; |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
_renderDimensionType = () => { |
||||
|
const { dimensions } = this.props; |
||||
|
return dimensions.dimensions.map(item => { |
||||
|
return ( |
||||
|
<Select.Option key={item.id} value={item.id}>{item.name}</Select.Option> |
||||
|
) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
getInterfaceToRenderProp(meta, parentNode) { |
||||
|
let up = meta.interfaces.filter(i => i.directType == 1); |
||||
|
if (parentNode.meta) { |
||||
|
up = up.filter(i => parentNode.meta.interfaces.some(pi => pi.interfaceMetaId == i.interfaceMetaId && pi.directType == 2)) |
||||
|
} |
||||
|
if (up.length > 0) { |
||||
|
return up[0]; |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
getUpLinkInterface(meta, parentNode) { |
||||
|
let up = meta.interfaces.filter(i => i.directType == 1); |
||||
|
if (parentNode.meta && parentNode.meta.interfaces) { |
||||
|
up = up.filter(i => parentNode.meta.interfaces.some(pi => pi.interfaceMetaId == i.interfaceMetaId && pi.directType == 2)) |
||||
|
} |
||||
|
if (up.length > 0) { |
||||
|
return up[0]; |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
getChildNodes = (id) => { |
||||
|
const { devices } = this.props; |
||||
|
const existedEquipment = devices.instances |
||||
|
let equipmentKeys = Object.keys(existedEquipment), |
||||
|
childNodes = {}; |
||||
|
for (let eq = 0; eq < equipmentKeys.length; eq++) { |
||||
|
if (existedEquipment[equipmentKeys[eq]].type == 's.l' && existedEquipment[equipmentKeys[eq]].instance.to.ownerSvgId == id) { |
||||
|
childNodes[existedEquipment[equipmentKeys[eq]].instance.from.ownerSvgId] = existedEquipment[existedEquipment[equipmentKeys[eq]].instance.from.ownerSvgId] |
||||
|
} |
||||
|
} |
||||
|
return childNodes; |
||||
|
} |
||||
|
|
||||
|
getParentNodes = (id) => { |
||||
|
const { devices } = this.props; |
||||
|
const existedEquipment = devices.instances |
||||
|
let equipmentKeys = Object.keys(existedEquipment), |
||||
|
childNodes = {}; |
||||
|
for (let eq = 0; eq < equipmentKeys.length; eq++) { |
||||
|
if (existedEquipment[equipmentKeys[eq]].type == 's.l' && existedEquipment[equipmentKeys[eq]].instance.from.ownerSvgId == id) { |
||||
|
childNodes[existedEquipment[equipmentKeys[eq]].instance.to.ownerSvgId] = existedEquipment[existedEquipment[equipmentKeys[eq]].instance.to.ownerSvgId] |
||||
|
} |
||||
|
} |
||||
|
return childNodes; |
||||
|
} |
||||
|
|
||||
|
getFormItems = (info) => { |
||||
|
|
||||
|
const { isEdit } = this.props; |
||||
|
const { showSenior } = this.state; |
||||
|
const formItemLayout = { |
||||
|
labelCol: { span: 7 }, |
||||
|
wrapperCol: { span: 15 } |
||||
|
} |
||||
|
const capabilityMap = { |
||||
|
"dimensionId": "采集策略", |
||||
|
"interval": "间隔", |
||||
|
"repeats": "次数", |
||||
|
"timeout": "超时" |
||||
|
} |
||||
|
const initialCapabilityValue = { |
||||
|
"dimensionId": null, |
||||
|
"interval": 1, |
||||
|
"repeats": 1, |
||||
|
"timeout": 20 |
||||
|
} |
||||
|
const DTURules = [{ required: true, message: '请输入接口id' }, { validator: this.checkDTUNum }]; |
||||
|
const SIMRulies = [{ required: true, message: '请输入11位、13位或19位SIM卡号' }, { validator: this.checkSim }] |
||||
|
const HTTPSERVERIDRules = [{ required: true, message: '请输入' }, { validator: this.checkHttpServerId }] |
||||
|
let about = [], capabilityBox = {}, capabilityPropsBox = [], s = [], otherParameter = []; |
||||
|
if (info) { |
||||
|
if (info.type == "equipment") { |
||||
|
if (info.device.type != "s.iota") { |
||||
|
let device = info.device; |
||||
|
let meta = info.meta; |
||||
|
let properties = device.instance.properties, |
||||
|
interfaces = device.instance.interfaces, |
||||
|
name = device.instance.name; |
||||
|
|
||||
|
about.push({ |
||||
|
"key": "deviceType", |
||||
|
"value": Object.keys(productTypes).includes( |
||||
|
meta.filteredResource ? |
||||
|
JSON.parse(meta.filteredResource.properties).deviceType |
||||
|
: null |
||||
|
) ? |
||||
|
productTypes[JSON.parse(meta.filteredResource.properties).deviceType] |
||||
|
: JSON.parse(meta.filteredResource.properties).deviceType, |
||||
|
"showName": "设备类型", |
||||
|
"name": "设备类型", |
||||
|
"required": true, |
||||
|
"proType": "Constant" |
||||
|
}) |
||||
|
about.push({ "key": "name", "value": name, "showName": "名称", "name": "名称", "proType": "Variable", validator: this.checkExistedName, required: true }); |
||||
|
about.push({ "key": "company", "value": meta.vendor ? meta.vendor.name : '', "showName": "厂商", "name": "厂商", "proType": "Constant" }); |
||||
|
about.push({ "key": "productName", "value": meta.name, "showName": "产品", "name": "产品", "proType": "Constant" }); |
||||
|
about.push({ "key": "model", "value": meta.model, "showName": "型号", "name": "型号", "proType": "Constant" }); |
||||
|
|
||||
|
try { |
||||
|
meta.properties = sort(meta.properties, "showName") |
||||
|
} catch (error) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
for (let i = 0; i < meta.properties.length; i++) { |
||||
|
if (meta.properties[i].name != 'deviceType' |
||||
|
&& meta.properties[i].name != 'module' |
||||
|
&& meta.properties[i].name != 'moduleId' |
||||
|
&& meta.properties[i].name != 'channel' |
||||
|
&& meta.properties[i].name != 'channelId') { |
||||
|
about.push({ |
||||
|
"key": meta.properties[i].name, |
||||
|
"value": properties[meta.properties[i].name], |
||||
|
"showName": meta.properties[i].showName, |
||||
|
"name": meta.properties[i].showName, |
||||
|
"required": meta.properties[i].required, |
||||
|
"proType": meta.properties[i].category, |
||||
|
enum: meta.properties[i].enum, |
||||
|
propertyTypeId: meta.properties[i].propertyTypeId, |
||||
|
unit: meta.properties[i].unit, |
||||
|
max: meta.properties[i].max, |
||||
|
min: meta.properties[i].min, |
||||
|
precision: meta.properties[i].precision, |
||||
|
isOtherParameter: meta.properties[i].isOtherParameter, |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
let interfaceToRender = this.getInterfaceToRenderProp(meta, this.props.parentNode); |
||||
|
if (interfaceToRender) { |
||||
|
let deviceInterface = device.instance.interfaces[interfaceToRender.id]; |
||||
|
const hasChannel = interfaceToRender.interfaceMeta.properties.some(p => p.name == 'channel'); |
||||
|
const hasId = interfaceToRender.interfaceMeta.properties.some(p => p.name == 'id'); |
||||
|
const isSoipSensor = (interfaceToRender.interfaceMeta.interfaceTypeId == 4) && (JSON.parse(meta.filteredResource.properties).deviceType == 'sensor'); |
||||
|
if (hasId && interfaceToRender.interfaceMeta.interfaceTypeId != 11 && meta.filteredResource && (isSoipSensor || ["gateway", 'dau.gateway', 'tcp.dtu'].some(t => t == JSON.parse(meta.filteredResource.properties).deviceType))) { |
||||
|
let SoIPInterfaceMeta = meta.interfaces.filter(face => face.directType == 1); |
||||
|
if (SoIPInterfaceMeta.length) { |
||||
|
let deviceInterface = device.instance.interfaces[SoIPInterfaceMeta[0].id]; |
||||
|
about.push({ "key": "portID", "value": deviceInterface.properties.id, "showName": "接口ID(DTU ID)", "name": "接口ID(DTU ID)", "required": true, "proType": "Variable" }) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
interfaceToRender.interfaceMeta.properties = sort(interfaceToRender.interfaceMeta.properties, "showName") |
||||
|
} catch (error) { |
||||
|
|
||||
|
} |
||||
|
interfaceToRender.interfaceMeta.properties.forEach(p => { |
||||
|
let propType = null, required = null; |
||||
|
if ((p.name == 'id' && interfaceToRender.interfaceMeta.interfaceTypeId != 11) || p.name == 'vendor' || p.name == 'model') return; |
||||
|
if (interfaceToRender.interfaceMeta.interfaceTypeId == 4) { |
||||
|
if (['port', 'escape', 'protocol', 'escapegw'].some(n => p.name == n)) { |
||||
|
propType = 'Constant'; |
||||
|
required = false; |
||||
|
} |
||||
|
} |
||||
|
let initialValue = deviceInterface?.properties[p.name] || null; |
||||
|
let validator; |
||||
|
if (p.name == 'module') { |
||||
|
initialValue = initialValue || device.instance.properties['moduleId']; |
||||
|
if (!hasChannel) { |
||||
|
validator = this.checkExists; |
||||
|
} |
||||
|
} |
||||
|
if (p.name == 'channel') { |
||||
|
initialValue = initialValue || device.instance.properties['channelId']; |
||||
|
validator = this.checkExists; |
||||
|
} |
||||
|
about.push({ |
||||
|
"key": p.name, |
||||
|
"value": initialValue, |
||||
|
"showName": p.showName, |
||||
|
"name": p.showName, |
||||
|
required: required == null ? p.required : required, |
||||
|
validator: validator, |
||||
|
"proType": propType || p.category, |
||||
|
enum: p.enum, |
||||
|
propertyTypeId: p.propertyTypeId, |
||||
|
max: p.max, |
||||
|
min: p.min, |
||||
|
unit: p.unit, |
||||
|
precision: p.precision, |
||||
|
isOtherParameter: p.isOtherParameter |
||||
|
}); |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
let capabilityFormulaProps = {}; |
||||
|
let upLinkInterface = null; |
||||
|
if (meta.capabilities.length && meta.interfaces.length) { |
||||
|
upLinkInterface = this.getUpLinkInterface(meta, this.props.parentNode); |
||||
|
let interfacesMeta = upLinkInterface ? upLinkInterface.id : null, |
||||
|
capabilityIdMetas = meta.capabilities.filter(c => c.interfaces.some(i => i.deviceMetaInterfaceId == interfacesMeta) && c.capabilityCategoryId == 3), |
||||
|
capabilityIdMeta = capabilityIdMetas.length > 0 ? capabilityIdMetas[0].id : null; |
||||
|
if (interfacesMeta && capabilityIdMeta) { |
||||
|
let capabilityDimensions = interfaces[interfacesMeta]?.capabilities[capabilityIdMeta]?.dimension; |
||||
|
let capabilityProps = interfaces[interfacesMeta]?.capabilities[capabilityIdMeta]?.properties; |
||||
|
const capabilityFormula = interfaces[interfacesMeta]?.capabilities[capabilityIdMeta]?.formula; |
||||
|
if (capabilityFormula && capabilityFormula.formulaId) { |
||||
|
capabilityFormulaProps = capabilityFormula.properties; |
||||
|
} |
||||
|
if (capabilityDimensions) { |
||||
|
if (Object.keys(capabilityDimensions).length) { |
||||
|
let capabilityDimensionKeys = Object.keys(capabilityDimensions); |
||||
|
capabilityDimensionKeys.forEach(capItem => { |
||||
|
//interval 会重复要特殊处理
|
||||
|
if(capItem == 'interval'){ |
||||
|
capabilityBox[capItem] = ({ "key": 'dimensionInterval', "value": capabilityDimensions[capItem] ? capabilityDimensions[capItem] : initialCapabilityValue[capItem], "showName": capabilityMap[capItem], "required": true }) |
||||
|
}else{ |
||||
|
capabilityBox[capItem] = ({ "key": capItem, "value": capabilityDimensions[capItem] ? capabilityDimensions[capItem] : initialCapabilityValue[capItem], "showName": capabilityMap[capItem], "required": true }) |
||||
|
} |
||||
|
}) |
||||
|
} else { // 采集
|
||||
|
capabilityBox = { |
||||
|
"dimensionId": { "key": "dimensionId", "value": null, "showName": "采集策略", "name": "采集策略", "required": true }, |
||||
|
"interval": { "key": "dimensionInterval", "value": 1, "showName": "间隔", "name": "间隔", "required": true }, |
||||
|
"repeats": { "key": "repeats", "value": 1, "showName": "次数", "name": "次数", "required": true }, |
||||
|
"timeout": { "key": "timeout", "value": 20, "showName": "超时", "name": "超时", "required": true } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (capabilityProps) { |
||||
|
let capabilityPropsKeys = Object.keys(capabilityProps); |
||||
|
capabilityPropsKeys.forEach(propItem => { |
||||
|
let propItemMetas = meta.capabilities.filter(cap => cap.id == capabilityIdMeta); |
||||
|
if (propItemMetas.length) { |
||||
|
let propItemMeta = propItemMetas[0].properties.filter(m => (m.category == "Variable" || m.name == "formula") && m.name == propItem)[0]; |
||||
|
if (propItemMeta) { |
||||
|
capabilityPropsBox.push({ |
||||
|
"key": propItemMeta.name, |
||||
|
"value": capabilityProps[propItem], |
||||
|
"showName": propItemMeta.showName, |
||||
|
"name": propItemMeta.showName, |
||||
|
"required": true, |
||||
|
isOtherParameter: propItemMeta.isOtherParameter |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
}) |
||||
|
try { |
||||
|
capabilityPropsBox = sort(capabilityPropsBox); |
||||
|
} catch (error) { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
about.forEach((item,index) => { |
||||
|
let validators = item.required ? |
||||
|
[{ required: true, message: `请输入${item.showName}` }] : []; |
||||
|
if (item.validator) { |
||||
|
validators.push({ validator: item.validator }); |
||||
|
} |
||||
|
const precisionProps = item.precision > 0 ? { |
||||
|
precision: item.precision |
||||
|
}: {}; |
||||
|
let parameter = ( |
||||
|
<FormItem |
||||
|
key={`extItem1-${index}`} |
||||
|
{...formItemLayout} |
||||
|
label={item.showName + (item.unit ? '(' + item.unit + ')' : '')} |
||||
|
name={`${item.key}`} |
||||
|
initialValue={item.value} |
||||
|
valuePropName={item.propertyTypeId == 3 ? 'checked' : 'value'} |
||||
|
|
||||
|
> |
||||
|
{ |
||||
|
item.enum ? |
||||
|
<Select disabled={!isEdit || item.proType != "Variable"}> |
||||
|
{ |
||||
|
item.enum.split(',').map(o => <Select.Option key={o}>{o}</Select.Option>) |
||||
|
} |
||||
|
</Select> |
||||
|
: ( |
||||
|
item.propertyTypeId == 3 ? |
||||
|
<Switch checkedChildren={"是"} unCheckedChildren={"否"} disabled={!isEdit || item.proType != "Variable"} /> |
||||
|
: ( |
||||
|
item.propertyTypeId == 1 || (item.propertyTypeId == 2 && item.showName != '模量系数') ? |
||||
|
<InputNumber max={item.max || Infinity} min={item.min || -Infinity} {...precisionProps} disabled={!isEdit || item.proType != "Variable"} /> |
||||
|
: <Input disabled={!isEdit || item.proType != "Variable"} /> |
||||
|
) |
||||
|
) |
||||
|
} |
||||
|
</FormItem> |
||||
|
) |
||||
|
if (item.isOtherParameter) { |
||||
|
otherParameter.push(parameter) |
||||
|
} else { |
||||
|
s.push(parameter) |
||||
|
} |
||||
|
|
||||
|
}) |
||||
|
|
||||
|
if (capabilityPropsBox.length) { |
||||
|
let capabilityFormula = capabilityPropsBox.filter(itemName => itemName.key == "formula"), |
||||
|
capabilityFormulaProps = capabilityPropsBox.filter(itemName => itemName.key != "formula"); |
||||
|
capabilityFormula.length ? |
||||
|
s.push( |
||||
|
<FormItem |
||||
|
key={`extItem2`} |
||||
|
{...formItemLayout} |
||||
|
label={capabilityFormula[0].showName} style={{ marginBottom: 5 }} |
||||
|
name={`${capabilityFormula[0].key}`} |
||||
|
initialValue={capabilityFormula[0].value} |
||||
|
> |
||||
|
<Input disabled={true} /> |
||||
|
</FormItem> |
||||
|
) : null; |
||||
|
let titleParameter = ( |
||||
|
<Row key={`extItem3`} className={Style.optionNames}> |
||||
|
<Col span={8}>参数</Col> |
||||
|
<Col span={16}>值</Col> |
||||
|
</Row> |
||||
|
) |
||||
|
s.push(titleParameter) |
||||
|
capabilityFormulaProps.forEach((item, index) => { |
||||
|
let parameter = ( |
||||
|
<FormItem |
||||
|
key={`extItem4-${index}`} |
||||
|
labelCol={{ span: 7 }} |
||||
|
wrapperCol={{ span: 15 }} |
||||
|
className={ |
||||
|
index == capabilityFormulaProps.length - 1 ? |
||||
|
`${Style.last_moduleOptionItem} ${Style.moduleOptionItem}` : `${Style.moduleOptionItem}` |
||||
|
} |
||||
|
label={item.showName} |
||||
|
name={`${item.key}`} |
||||
|
initialValue={item.value} |
||||
|
> |
||||
|
<Input disabled={!isEdit} /> |
||||
|
</FormItem> |
||||
|
) |
||||
|
s.push(parameter) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// 采集仪等父(上级)节点公式参数
|
||||
|
const formulas = this.props.parentNode.meta ? this.props.parentNode.meta.formulas : [];//.length > 0 ? this.props.parentNode.meta.formulas : meta.formulas;
|
||||
|
|
||||
|
if (formulas.length > 0) { |
||||
|
s.push( |
||||
|
<FormItem |
||||
|
key={`extItem5`} |
||||
|
label="公式" |
||||
|
{...formItemLayout} |
||||
|
style={{ marginTop: 15 }} |
||||
|
name={'up_formula'} |
||||
|
initialValue={properties['up_formula']} |
||||
|
> |
||||
|
<Select size="large" disabled={!isEdit} placeholder="请选择公式" > |
||||
|
{formulas.map(f => <Select.Option key={f.id}>{f.name}</Select.Option>)} |
||||
|
</Select> |
||||
|
</FormItem > |
||||
|
); |
||||
|
|
||||
|
const selectedFormula = formulas.filter(f => f.id == (this.state.selectedFormulaId || properties['up_formula']))[0]; |
||||
|
s.push( |
||||
|
<FormItem |
||||
|
key={`extItem6`} |
||||
|
label="表达式" |
||||
|
{...formItemLayout} |
||||
|
hasFeedback |
||||
|
> |
||||
|
<Input.TextArea disabled value={selectedFormula ? selectedFormula.formula : ''} autosize={{ minRows: 2, maxRows: 6 }} /> |
||||
|
</FormItem> |
||||
|
); |
||||
|
const formulaProperties = selectedFormula ? selectedFormula.properties : []; |
||||
|
|
||||
|
if (formulaProperties.length > 0) { |
||||
|
s.push( |
||||
|
<Row key={`extItem7`} className={Style.formulaNames}> |
||||
|
<Col span={8}>参数</Col> |
||||
|
<Col span={16}>值</Col> |
||||
|
</Row> |
||||
|
) |
||||
|
|
||||
|
formulaProperties.forEach((item,index) => { |
||||
|
const precisionProps = item.precision > 0 ? { |
||||
|
precision: item.precision |
||||
|
}: {}; |
||||
|
s.push( |
||||
|
<FormItem |
||||
|
key={`extItem8-${index}`} |
||||
|
label={item.showName ? item.showName : `${item.name}(${item.showName})`} |
||||
|
labelCol={{ span: 8 }} |
||||
|
wrapperCol={{ span: 12 }} |
||||
|
className={Style.moduleFormuleItem} |
||||
|
name={`formula-p-${item.name}`} |
||||
|
initialValue={ |
||||
|
capabilityFormulaProps[item.name] != null ? |
||||
|
capabilityFormulaProps[item.name] : ( |
||||
|
properties[`formula-p-${item.name}`] != null ? |
||||
|
properties[`formula-p-${item.name}`] : properties[item.name] |
||||
|
) |
||||
|
} |
||||
|
> |
||||
|
{ |
||||
|
item.enum ? |
||||
|
<Select disabled={!isEdit || item.category != "Variable"}> |
||||
|
{ |
||||
|
item.enum.split(',').map(o => <Select.Option key={o}>{o}</Select.Option>) |
||||
|
} |
||||
|
</Select> |
||||
|
: ( |
||||
|
item.propertyTypeId == 3 ? |
||||
|
<Switch checkedChildren={"是"} unCheckedChildren={"否"} disabled={!isEdit || item.category != "Variable"} /> |
||||
|
: ( |
||||
|
item.propertyTypeId == 1 || (item.propertyTypeId == 2 && item.showName != '模量系数') ? |
||||
|
<InputNumber max={item.max || Infinity} min={item.min || -Infinity} {...precisionProps} disabled={!isEdit || item.category != "Variable"} /> |
||||
|
: <Input disabled={!isEdit || item.category != "Variable"} /> |
||||
|
) |
||||
|
) |
||||
|
} |
||||
|
</FormItem> |
||||
|
) |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
if (meta.interfaces.length && this._enableSelectStrategy(meta, this.props.parentNode) && Object.keys(capabilityBox).length) { |
||||
|
|
||||
|
let dimensionMeta = capabilityBox.dimensionId ? |
||||
|
this.props.dimensions.dimensions.filter(dimen => dimen.id == capabilityBox.dimensionId.value) : []; |
||||
|
|
||||
|
|
||||
|
s.push( |
||||
|
<div key={`extItem9`}> |
||||
|
<FormItem |
||||
|
{...formItemLayout} |
||||
|
label={capabilityBox.dimensionId.showName} |
||||
|
name={`${capabilityBox.dimensionId.key}`} |
||||
|
initialValue={dimensionMeta.length ? capabilityBox.dimensionId.value : null} |
||||
|
> |
||||
|
<Select size="large" disabled={!isEdit} placeholder="请选择采集策略"> |
||||
|
{this._renderDimensionType()} |
||||
|
</Select> |
||||
|
</FormItem> |
||||
|
<div style={showSenior ? { display: 'block' } : { display: 'none' }}> |
||||
|
|
||||
|
<FormItem |
||||
|
{...formItemLayout} |
||||
|
label={capabilityBox.repeats.showName} |
||||
|
name={`${capabilityBox.repeats.key}`} |
||||
|
initialValue={capabilityBox.repeats.value} |
||||
|
> |
||||
|
<Input disabled={!isEdit} /> |
||||
|
</FormItem> |
||||
|
<FormItem |
||||
|
{...formItemLayout} |
||||
|
label={capabilityBox.interval.showName} |
||||
|
> |
||||
|
<FormItem |
||||
|
noStyle |
||||
|
name={`${capabilityBox.interval.key}`} |
||||
|
initialValue={capabilityBox.interval.value} |
||||
|
> |
||||
|
<Input disabled={!isEdit} style={{ width: "75%", marginRight: 0 }} /> |
||||
|
</FormItem> |
||||
|
<Select defaultValue="second" disabled={!isEdit} style={{ width: "25%" }}> |
||||
|
<Select.Option value="second">秒</Select.Option> |
||||
|
</Select> |
||||
|
</FormItem> |
||||
|
<FormItem |
||||
|
{...formItemLayout} |
||||
|
label={capabilityBox.timeout.showName} |
||||
|
> |
||||
|
<FormItem |
||||
|
noStyle |
||||
|
name={`${capabilityBox.timeout.key}`} |
||||
|
initialValue={capabilityBox.timeout.value} |
||||
|
> |
||||
|
<Input disabled={!isEdit} style={{ width: "75%", marginRight: 0 }} /> |
||||
|
</FormItem> |
||||
|
<Select defaultValue="second" disabled={!isEdit} style={{ width: "25%" }}> |
||||
|
<Select.Option value="second">秒</Select.Option> |
||||
|
</Select> |
||||
|
{ |
||||
|
isEdit ? |
||||
|
<Tag color="orange">建议按照采集仪下配置设备数量*10填写</Tag> : null |
||||
|
} |
||||
|
</FormItem> |
||||
|
</div> |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
return ( |
||||
|
<div> |
||||
|
{/* <Form |
||||
|
ref={this.formRef} |
||||
|
name="optionForm" |
||||
|
id="optionForm" |
||||
|
layout='horizontal' |
||||
|
scrollToFirstError |
||||
|
> |
||||
|
{s} |
||||
|
<Collapse accordion |
||||
|
style={ |
||||
|
otherParameter.length ? |
||||
|
{ margin: '15px 7px', background: "transparent" } |
||||
|
: { marginTop: 15, background: "transparent", display: "none" } |
||||
|
} |
||||
|
> |
||||
|
<Panel header={'高级'} key="1"> |
||||
|
<div> |
||||
|
{otherParameter} |
||||
|
</div> |
||||
|
</Panel> |
||||
|
</Collapse> |
||||
|
</Form> */} |
||||
|
</div> |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
render() { |
||||
|
const { info, height } = this.props; |
||||
|
|
||||
|
return ( |
||||
|
<div className={Style.option_modal} id="optionModal" style={{ |
||||
|
height: height, |
||||
|
position: 'relative', |
||||
|
}}> |
||||
|
{ |
||||
|
info ? this.getFormItems(info) : null |
||||
|
} |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
export default Option; |
@ -0,0 +1,76 @@ |
|||||
|
'use strict' |
||||
|
import React, { Component } from 'react'; |
||||
|
import { Row, Col, Timeline } from '@douyinfe/semi-ui'; |
||||
|
|
||||
|
|
||||
|
class State extends Component { |
||||
|
constructor(props) { |
||||
|
super(props); |
||||
|
this.state = { |
||||
|
alarmMsgRowStyle: { |
||||
|
marginTop: 7, |
||||
|
}, |
||||
|
alarmMsgColStyle: { |
||||
|
paddingTop: 3, |
||||
|
color: '#909090', |
||||
|
fontSize: 10 |
||||
|
}, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
render() { |
||||
|
const { linkState, alarmMsg } = this.props |
||||
|
const { alarmMsgColStyle } = this.state |
||||
|
|
||||
|
return ( |
||||
|
<div style={{ |
||||
|
// height:,
|
||||
|
// overflow: 'auto'
|
||||
|
}}> |
||||
|
<Row > |
||||
|
<Col span={1}></Col> |
||||
|
<Col span={22}> |
||||
|
<span>在线状态: </span> |
||||
|
{linkState == 1 ? <span style={{ color: 'green' }}>在线</span> |
||||
|
: |
||||
|
linkState == 0 ? <span style={{ color: 'red' }}>离线</span> |
||||
|
: <span style={{ color: '#787878' }}>未知</span> |
||||
|
} |
||||
|
<p style={{ marginTop: 10 }}>实时告警:{alarmMsg.new.length > 0 ? '' : "无"} </p> |
||||
|
{ |
||||
|
alarmMsg.new.length > 0 ? alarmMsg.new.map(s => <Row style={{ marginTop: 7 }}> |
||||
|
<Col span="1"></Col> |
||||
|
<Col span="23" style={{}}>{s.alarmContent}</Col> |
||||
|
<Col span="1"></Col> |
||||
|
<Col span="23" style={alarmMsgColStyle}>产生次数:{s.alarmCount}次</Col> |
||||
|
<Col span="1"></Col> |
||||
|
<Col span="23" style={alarmMsgColStyle}>产生时间:{s.startTime}</Col> |
||||
|
<Col span="1"></Col> |
||||
|
<Col span="23" style={alarmMsgColStyle}>更新时间:{s.endTime}</Col> |
||||
|
</Row>) : null |
||||
|
} |
||||
|
|
||||
|
|
||||
|
<p style={{ marginTop: 21 }}>历史告警:{alarmMsg.history.length > 0 ? '' : "无"} </p> |
||||
|
<Timeline style={{ marginTop: 7, marginLeft: 13 }}> |
||||
|
{ |
||||
|
alarmMsg.history.length > 0 ? alarmMsg.history.map(s => |
||||
|
|
||||
|
<Timeline.Item> |
||||
|
<p> {s.alarmContent} / <span style={alarmMsgColStyle}> {s.startTime}</span></p> |
||||
|
<p style={alarmMsgColStyle}>产生次数:{s.alarmCount}次</p> |
||||
|
<p style={alarmMsgColStyle}>更新时间:{s.endTime}</p> |
||||
|
</Timeline.Item> |
||||
|
|
||||
|
) : null |
||||
|
} |
||||
|
</Timeline> |
||||
|
|
||||
|
</Col> |
||||
|
<Col span={1}></Col> |
||||
|
</Row> |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
export default State; |
@ -0,0 +1,401 @@ |
|||||
|
import React, { useState, useEffect, useBoolean } from 'react'; |
||||
|
// import { useSafeState, useBoolean } from 'ahooks';
|
||||
|
import Immutable from 'immutable'; |
||||
|
import { sort, Request, PinyinHelper } from '@peace/utils'; |
||||
|
import { ApiTable } from '$utils'; |
||||
|
import { connect } from 'react-redux'; |
||||
|
import { message, Tree } from '@douyinfe/semi-ui'; |
||||
|
|
||||
|
import Ps from 'perfect-scrollbar'; |
||||
|
import createG6 from './edit-map'; |
||||
|
|
||||
|
// import { useThingsLinkStatus } from '../../actions/hooks';
|
||||
|
|
||||
|
const Tree_ = createG6((tree) => { |
||||
|
tree.render(); |
||||
|
}); |
||||
|
|
||||
|
const Index = ({ ...props }) => { |
||||
|
const { actions, dispatch, |
||||
|
struct, data, resetFoldAllG6ToCenter, foldAllG6ToCenter, g6TreeDirection, emitChange, emitDataChange_, |
||||
|
width, height, collapseAll, collapsed, expanded, expandAll, changeFinish, targetNode, inputSearching, setInputSearching, |
||||
|
onCollapse, handleNodeEnter, handelNodeClick, |
||||
|
} = props; |
||||
|
const { analysis } = actions |
||||
|
|
||||
|
const [isGetLinkStateDone, setTrue] = useState(false); |
||||
|
const [devicesLinkState, setDevicesLinkState] = useState(null); |
||||
|
const [treeNodeCheckedKeys, setTreeNodeCheckedKeys] = useState([]); |
||||
|
const [currSDids, setCurrSDids] = useState([]); |
||||
|
const [g6Tree, setG6Tree] = useState(null); |
||||
|
const [g6TreeData, setG6TreeData] = useState(null); |
||||
|
const [lastClickNodeKey, setLastClickNodeKey] = useState(null); |
||||
|
const [disCheckedKeys, setDisCheckedKeys] = useState([]); |
||||
|
let intervalLinkStatus = null; |
||||
|
|
||||
|
|
||||
|
|
||||
|
const getThingsLinkStatus = (isCycle = false) => { |
||||
|
const iotaThingId = struct?.thingId; |
||||
|
if (iotaThingId) { |
||||
|
|
||||
|
dispatch(analysis.getIotaThingsLlinkStatus(iotaThingId)).then((res) => { |
||||
|
if (res.payload?.data?.devices.length >= 0) { |
||||
|
setDevicesLinkState(res.payload?.data?.devices || []); |
||||
|
} else { |
||||
|
intervalLinkStatus && clearInterval(intervalLinkStatus); |
||||
|
} |
||||
|
if (!isCycle) { |
||||
|
setTrue(true); |
||||
|
} |
||||
|
}, (error) => { |
||||
|
if (!isCycle) { |
||||
|
message.warning('设备在线状态获取失败') |
||||
|
setTrue(true); |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
}; |
||||
|
useEffect(() => { |
||||
|
getThingsLinkStatus(); |
||||
|
// intervalLinkStatus = setInterval(() => {
|
||||
|
// getThingsLinkStatus(true);
|
||||
|
// }, 4000);
|
||||
|
new Ps('#deviceTree', { suppressScrollX: true }); |
||||
|
return () => { |
||||
|
intervalLinkStatus && clearInterval(intervalLinkStatus); |
||||
|
}; |
||||
|
}, []); |
||||
|
|
||||
|
useEffect(() => { |
||||
|
const nextDeviceIds = Object.keys(data); |
||||
|
if (currSDids.length != nextDeviceIds.length) { |
||||
|
const nextSDids = []; |
||||
|
const checked = [].concat(treeNodeCheckedKeys); |
||||
|
for (const id of nextDeviceIds) { |
||||
|
if ((data[id]?.type == 's.d' || data[id]?.type == 's.iota') && !currSDids.some((c) => c == id)) { |
||||
|
checked.push(id); |
||||
|
} |
||||
|
nextSDids.push(id); |
||||
|
} |
||||
|
emitDataChange_ && emitDataChange_(true); |
||||
|
setTreeNodeCheckedKeys(checked); |
||||
|
setCurrSDids(nextSDids); |
||||
|
} |
||||
|
if (foldAllG6ToCenter && g6Tree) { |
||||
|
toG6Center(width, height, g6TreeDirection); |
||||
|
resetFoldAllG6ToCenter(); |
||||
|
} |
||||
|
}, [data, foldAllG6ToCenter]); |
||||
|
|
||||
|
useEffect(() => { |
||||
|
if (g6Tree) { |
||||
|
toG6Center(width, height, g6TreeDirection); |
||||
|
g6Tree.changeLayout( |
||||
|
new G6.Layout.CompactBoxTree({ direction: g6TreeDirection }), |
||||
|
); |
||||
|
} |
||||
|
}, [g6TreeDirection]); |
||||
|
|
||||
|
useEffect(() => { |
||||
|
if (g6Tree && inputSearching) { |
||||
|
const items = g6Tree.getItems(); |
||||
|
|
||||
|
if (items && items.length) { |
||||
|
items.forEach((item) => { |
||||
|
const { model } = item._attrs; |
||||
|
if (model && model.label && targetNode && ( |
||||
|
model.label.indexOf(targetNode) != -1 || PinyinHelper.isPinyinMatched(model.label, targetNode) |
||||
|
)) { |
||||
|
g6Tree.update(model.id, { |
||||
|
color: '#ff7300', |
||||
|
}); |
||||
|
|
||||
|
g6Tree.focusPoint({ x: model.x, y: model.y }); |
||||
|
} else if (model && model.type == 's.iota') { |
||||
|
g6Tree.update(model.id, { |
||||
|
color: '#108ee9', |
||||
|
}); |
||||
|
} else { |
||||
|
g6Tree.update(model.id, { |
||||
|
color: '#fff', |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
// g6Tree.changeSize(width, height);
|
||||
|
// g6Tree.refresh();
|
||||
|
} |
||||
|
setInputSearching(false); |
||||
|
}, [targetNode, inputSearching]); |
||||
|
|
||||
|
const toG6Center = (width, height, direction = null) => { |
||||
|
let x = 30; let |
||||
|
y = 50; |
||||
|
if (direction == 'LR') { |
||||
|
x = 400; |
||||
|
y = -10; |
||||
|
} |
||||
|
g6Tree.changeSize(width, height); |
||||
|
g6Tree.focusPoint({ x, y }); |
||||
|
}; |
||||
|
|
||||
|
const _finishDataChange = () => { |
||||
|
changeFinish && changeFinish(); |
||||
|
}; |
||||
|
|
||||
|
const _handelNodeClick = (node) => { |
||||
|
handelNodeClick(node); |
||||
|
}; |
||||
|
const _handelNodeEnter = (node) => handleNodeEnter(node); |
||||
|
|
||||
|
const renderTreeNodes = (data, parentId) => { |
||||
|
|
||||
|
const combinTreeNode = (item, parentId) => { |
||||
|
const treeNode = { |
||||
|
label: item.name, |
||||
|
value: item.id, |
||||
|
key: item.id, |
||||
|
disableCheckbox: item.name == '数据中心', |
||||
|
}; |
||||
|
if (item.children) { |
||||
|
treeNode.children = item.children.map((ci) => combinTreeNode(ci, item.id)); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
return treeNode; |
||||
|
}; |
||||
|
return data.map((item) => combinTreeNode(item)); |
||||
|
}; |
||||
|
|
||||
|
const onTreeNodeSelect = (checkedKeys, e, data) => { |
||||
|
if (e.checked) { |
||||
|
const newDisCheckedKeys = []; |
||||
|
disCheckedKeys.forEach((d) => { |
||||
|
if (d != e.node.key) { |
||||
|
newDisCheckedKeys.push(d); |
||||
|
} |
||||
|
}); |
||||
|
setDisCheckedKeys(newDisCheckedKeys); |
||||
|
} else { |
||||
|
setDisCheckedKeys([].concat(disCheckedKeys, [e.node.key])); |
||||
|
} |
||||
|
setTreeNodeCheckedKeys(checkedKeys.checked); |
||||
|
|
||||
|
toG6Center(width, height); |
||||
|
emitDataChange_(); |
||||
|
}; |
||||
|
|
||||
|
const onTreeNodeClick = (nodeKeys, e) => { |
||||
|
const lastClickNodeKey_ = lastClickNodeKey; |
||||
|
if (nodeKeys.length) { |
||||
|
const nodeKey = nodeKeys |
||||
|
|
||||
|
if (g6Tree && treeNodeCheckedKeys.some((cid) => cid == nodeKey)) { |
||||
|
const node = g6Tree.find(nodeKey); |
||||
|
if (node) { |
||||
|
const boxStatsh = node._attrs.boxStash; |
||||
|
g6Tree.update(nodeKey, { |
||||
|
color: '#ff7300', |
||||
|
}); |
||||
|
if (lastClickNodeKey_ && lastClickNodeKey_ != nodeKey) { |
||||
|
const node = g6Tree.find(lastClickNodeKey_); |
||||
|
if (node && node._attrs.model.type == 's.iota') { |
||||
|
g6Tree.update(lastClickNodeKey_, { |
||||
|
color: '#108ee9', |
||||
|
}); |
||||
|
} else if (node) { |
||||
|
g6Tree.update(lastClickNodeKey_, { |
||||
|
color: '#fff', |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
setLastClickNodeKey(nodeKey); |
||||
|
// lastClickNodeKey = nodeKey;
|
||||
|
g6Tree.focusPoint({ x: boxStatsh.centerX, y: boxStatsh.centerY }); |
||||
|
} |
||||
|
} |
||||
|
} else if (lastClickNodeKey_) { |
||||
|
if (g6Tree) { |
||||
|
const node = g6Tree.find(lastClickNodeKey_); |
||||
|
if (node && node._attrs.model.type == 's.iota') { |
||||
|
g6Tree.update(lastClickNodeKey_, { |
||||
|
color: '#108ee9', |
||||
|
}); |
||||
|
} else { |
||||
|
g6Tree.update(lastClickNodeKey_, { |
||||
|
color: '#fff', |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
const formedData = () => { |
||||
|
const deviceInfo = JSON.parse(JSON.stringify(data)); |
||||
|
const deviceIds = Object.keys(deviceInfo); |
||||
|
const node = []; const |
||||
|
link = []; |
||||
|
const defaultTreeNodesCheckedKeys = []; |
||||
|
for (let i = 0; i < deviceIds.length; i++) { |
||||
|
if (deviceInfo[deviceIds[i]].type == 's.iota') { |
||||
|
deviceInfo[deviceIds[i]].name = '数据中心'; |
||||
|
const a = { |
||||
|
...deviceInfo[deviceIds[i]], id: deviceIds[i], label: '数据中心', color: '#108ee9', children: [], |
||||
|
}; |
||||
|
node.push(a); |
||||
|
defaultTreeNodesCheckedKeys.push(a.id); |
||||
|
} else if (deviceInfo[deviceIds[i]].type == 's.d') { |
||||
|
let linkState = null; |
||||
|
if (devicesLinkState) { |
||||
|
linkState = devicesLinkState.find((dls) => dls.deviceId == deviceIds[i]); |
||||
|
if (linkState) { |
||||
|
linkState = linkState.status; |
||||
|
} |
||||
|
} |
||||
|
let linkStateMsg = ''; |
||||
|
let LinlStateColor = '#666666'; |
||||
|
if ((linkState != null || linkState != undefined)) { |
||||
|
if (linkState == 1) { |
||||
|
// linkStateMsg = "(在线)"
|
||||
|
} else if (linkState == 0) { |
||||
|
linkStateMsg = '(离线)'; |
||||
|
LinlStateColor = 'red'; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const a = { |
||||
|
...deviceInfo[deviceIds[i]], |
||||
|
id: deviceIds[i], |
||||
|
label: `${deviceInfo[deviceIds[i]]?.instance?.name || ''}${linkStateMsg}`, |
||||
|
style: { stroke: LinlStateColor }, |
||||
|
children: [], |
||||
|
linkState, |
||||
|
}; |
||||
|
if (collapseAll) { |
||||
|
if (expanded.some((c) => c == deviceIds[i])) { |
||||
|
a.isCollapsed = false; |
||||
|
} else { |
||||
|
a.isCollapsed = true; |
||||
|
} |
||||
|
} |
||||
|
if (expandAll) { |
||||
|
if (collapsed.some((c) => c == deviceIds[i])) { |
||||
|
a.isCollapsed = true; |
||||
|
} else { |
||||
|
a.isCollapsed = false; |
||||
|
} |
||||
|
} |
||||
|
node.push(a); |
||||
|
defaultTreeNodesCheckedKeys.push(a.id); |
||||
|
} else if (deviceInfo[deviceIds[i]]?.type == 's.l') { |
||||
|
const temp = deviceInfo[deviceIds[i]]; |
||||
|
const b = { from: temp?.instance?.from?.ownerSvgId, to: temp?.instance?.to?.ownerSvgId }; |
||||
|
link.push(b); |
||||
|
} |
||||
|
} |
||||
|
const deviceInfos = { |
||||
|
nodes: node, |
||||
|
links: link, |
||||
|
}; |
||||
|
|
||||
|
const parent = deviceInfos.nodes.filter((s) => s.type == 's.iota')[0]?.id; |
||||
|
const nodes = new Map(); |
||||
|
deviceInfos.nodes.forEach((s) => { |
||||
|
nodes.set(s.id, s); |
||||
|
}); |
||||
|
const { links } = deviceInfos; |
||||
|
|
||||
|
function getLeaf (parentId) { |
||||
|
const fromStructs = nodes.get(parentId); |
||||
|
let tempTreeData = []; |
||||
|
links.forEach((m) => { |
||||
|
if (m.to == parentId) { |
||||
|
const node = nodes.get(m.from); |
||||
|
|
||||
|
if (((treeNodeCheckedKeys && treeNodeCheckedKeys.some((c) => c == node.id)) |
||||
|
|
||||
|
|| treeNodeCheckedKeys.length == 0 |
||||
|
) && !disCheckedKeys.some((d) => d == node.id)) { |
||||
|
fromStructs.children.push(node); |
||||
|
} |
||||
|
const nextTempTreeData = getLeaf(m.from); |
||||
|
|
||||
|
tempTreeData = tempTreeData.concat(nextTempTreeData.treeData); |
||||
|
// tempTreeData.push({ name: node.name, id: node.id, children: nextTempTreeData.treeData })
|
||||
|
} |
||||
|
}); |
||||
|
const treeData = [{ name: fromStructs.name, id: fromStructs.id, children: tempTreeData.length ? tempTreeData : null }]; |
||||
|
|
||||
|
fromStructs.children = sort(fromStructs.children); |
||||
|
return { tree_data: fromStructs, treeData, defaultTreeNodesCheckedKeys }; |
||||
|
} |
||||
|
|
||||
|
return getLeaf(parent); |
||||
|
}; |
||||
|
|
||||
|
const treeData = formedData(); |
||||
|
console.log(22, treeData); |
||||
|
console.log(3333, renderTreeNodes(treeData?.treeData || [])); |
||||
|
|
||||
|
return ( |
||||
|
<div id="editMap" style={{ position: 'relative', overflow: 'hidden' }}> |
||||
|
<div |
||||
|
id="deviceTree" |
||||
|
style={{ |
||||
|
position: 'absolute', |
||||
|
top: 50, |
||||
|
zIndex: 999, |
||||
|
maxHeight: height - 50, |
||||
|
overflow: 'auto', |
||||
|
}} |
||||
|
> |
||||
|
<Tree |
||||
|
// showIcon={false}
|
||||
|
multiple |
||||
|
onCheck={(checkedKeys, e) => onTreeNodeSelect(checkedKeys, e, treeData.treeData)} |
||||
|
onSelect={(checkedKeys, e) => { |
||||
|
console.log(4324, checkedKeys, e); |
||||
|
onTreeNodeClick(checkedKeys, e) |
||||
|
}} |
||||
|
defaultValue={treeData.defaultTreeNodesCheckedKeys} |
||||
|
expandAll={false} |
||||
|
// checkStrictly
|
||||
|
// value={checkedKeys}
|
||||
|
treeData={renderTreeNodes(treeData.treeData, null)} |
||||
|
style={{ width: 200, height: 500 }} |
||||
|
/> |
||||
|
</div> |
||||
|
|
||||
|
{isGetLinkStateDone |
||||
|
? ( |
||||
|
<Tree_ |
||||
|
data={treeData.tree_data} |
||||
|
emitChange={emitChange} |
||||
|
changeFinish={_finishDataChange} |
||||
|
emitDataChange_={emitDataChange_} |
||||
|
width={width} |
||||
|
height={height} |
||||
|
targetNode={targetNode} |
||||
|
handelNodeClick={_handelNodeClick} |
||||
|
onCollapse={onCollapse} |
||||
|
handleNodeEnter={_handelNodeEnter} |
||||
|
setG6Tree={(g6Tree) => { setG6Tree(g6Tree); }} |
||||
|
setG6TreeData={(data) => { setG6TreeData(data); }} |
||||
|
/> |
||||
|
) : null} |
||||
|
</div> |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
function mapStateToProps (state) { |
||||
|
const { auth, global, } = state; |
||||
|
return { |
||||
|
user: auth.user, |
||||
|
actions: global.actions, |
||||
|
clientHeight: global.clientHeight, |
||||
|
|
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
export default connect(mapStateToProps)(Index); |
@ -0,0 +1,9 @@ |
|||||
|
|
||||
|
.device-monitor-search { |
||||
|
margin-bottom: 1px; |
||||
|
} |
||||
|
.device-monitor-pro-table { |
||||
|
.ant-card-body { |
||||
|
padding: 0; |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue