/* eslint-disable */ import React, { useState, useEffect, useRef, useContext } from 'react'; import classNames from 'classnames'; import moment from 'moment'; import Empty from '@wisdom-components/empty'; import LoadBox from '@wisdom-components/loadbox'; import { message, Modal, ConfigProvider } from 'antd'; import PropTypes from 'prop-types'; import HistoryView from '@wisdom-components/ec_historyview'; import * as go from '@wisdom-components/gojs'; import GuidedDraggingTool from './js/GuidedDraggingTool'; import TopRotatingTool from './js/RotatingTool'; import BarLink from './js/BarLink'; import WaterFlowControlView from './js/WaterFlowControlView'; import { getSketchPadList, getSketchPadContent, getPointAddress, getHistoryInfo, getStatisticsInfo, } from './apis'; import { deepCopy, hexToRgba, textStyle, querySkipUrl, isJson, stationData, isNumber, } from './js/utils'; import './index.less'; const goJS = go.GraphObject.make; let online = false; let imgUrl = null; let historyInfoParams = []; let twoID = ''; let myDiagram = null; let editionArr = []; // const guidAggre = {}; let bindData = []; const stationList = []; let historyData = []; // 历史数据 let timeData = []; // 历史数据时间列表 let speed = 0; // 历史数据播放当前进度值 let times = 2; // 历史数据播放速度 let play = false; // 历史数据是否播放 let historyParams = {}; const waterFlow = new WaterFlowControlView(); const ConfigurationView = (props) => { const { getPrefixCls } = useContext(ConfigProvider.ConfigContext); const prefixCls = getPrefixCls('ec-configuration-view'); const [isHIModalVisible, setIsHIModalVisible] = useState(false); // 历史曲线模态框 const [spinning, setSpinning] = useState(true); // 画板loading const [spinLoad, setSpinLoad] = useState(false); const [isEmpty, setIsEmpty] = useState(false); // 画板无数据状态 const [description, setDescription] = useState(''); // 画板无数据描述 twoID = `TDG${Date.now().toString(36)}`; const ConfigurationRef = useRef(); const customBack = props.customBack ? props.customBack : () => {}; const { devices = [], config, isZoom = false, flowShow = true, deviceName = [], dataType = '历史', statisticType = [], } = props; let devicesCode = []; const globalConfig = window.globalConfig || config; const siteCodeStr = globalConfig?.userInfo?.LocalSite || globalConfig?.userInfo?.site || ''; let isClose = false; /** **********************************获取工艺图画板信息*********************** */ const getConfiguraList = async () => { const url = globalConfig.mainserver ? globalConfig.mainserver : 'https://panda-water.cn/'; imgUrl = online ? `${url}PandaMonitor/Monitor/` : `/PandaMonitor/Monitor/`; // 获取画板信息 const drawInfo = await getSketchPadList({ name: props.name, siteCode: siteCodeStr, version: '全部', _site: siteCodeStr, }); if (drawInfo.code === 0) { const data = drawInfo.data ? (drawInfo.data.list ? drawInfo.data.list : []) : []; if (data.length > 0) { const num = data.length ? (data[0].num ? data[0].num * 1 : 0) : 0; const siteInfo = data.length ? (data[0].siteInfo ? JSON.parse(data[0].siteInfo) : {}) : {}; for (let i = 0; i < num; i++) { const round = parseInt(i / 26); const remain = i % 26; if (round) { stationList.push(stationData[remain] + round); } else { stationList.push(stationData[remain]); } } const siteInfoArr = Object.getOwnPropertyNames(siteInfo); devicesCode = []; bindData = []; siteInfoArr.forEach((name, index) => { const deviceList = devices[index] || (siteInfo && siteInfo[name] ? siteInfo[name].Code || '' : ''); bindData.push({ code: deviceList, name, type: siteInfo && siteInfo[name] ? siteInfo[name].Type : '', }); devicesCode.push(deviceList); }); getDiagramJson(data[0], siteInfo); } else { setDescription('咦~未查询到工艺图画板信息哦~'); setIsEmpty(true); setSpinning(false); return false; } } else { setDescription('咦~工艺图画板信息报错啦~'); setIsEmpty(true); setSpinning(false); return message.error(drawInfo.msg); } // 获取点表信息 const pointInfo = await getPointAddress({ code: devicesCode.join(','), _site: siteCodeStr, }); editionArr = deepCopy(pointInfo && pointInfo.data ? pointInfo.data : [], []); }; /** *********************************节点展示逻辑****************************** */ const showNodeMethod = (node, list) => { const realVal = list.Value * 1; let switchState; myDiagram.model.setDataProperty(node, 'realVal', realVal); if (node.switch === '是') { switchState = openValState(node.openVal, realVal) ? '开' : '关'; myDiagram.model.setDataProperty(node, 'switchState', switchState); } if (!node.shType) return false; const patt = /[><=]/gi; let shRule = []; try { switch (node.category) { case 'svgCase': // 图片模型 shRule = ruleOperation(node, realVal); if (node.shType === '模型切换') { myDiagram.model.setDataProperty(node, 'imgSrc', shRule ? shRule.attr : node.dtImgSrc); } else if (node.shType === '显隐展示') { myDiagram.model.setDataProperty(node, 'visible', shRule ? shRule.visible : true); } break; case 'nameCase': // 名称模型 if (node.shType === '文本变化') { shRule = ruleOperation(node, realVal); myDiagram.model.setDataProperty( node, 'fontStroke', shRule ? shRule.attr : node.dtFontStroke, ); myDiagram.model.setDataProperty(node, 'text', shRule ? shRule.text : node.dtText); } else { shRule = ruleOperation(node, realVal); myDiagram.model.setDataProperty( node, 'fillColor', hexToRgba(shRule ? shRule.attr : node.fill, node.opacity), ); } break; case 'valCase': // 实时值模型 const division = node.division || false; // 动画翻转 if (node.effect) myDiagram.model.setDataProperty(node, 'flip', go.GraphObject.FlipHorizontal); if (node.shType === '值显示') { myDiagram.model.setDataProperty( node, 'showVal', realVal < 0 ? 0 : division ? realVal.toLocaleString() : realVal, ); } else { myDiagram.model.setDataProperty( node, 'showVal', division ? realVal.toLocaleString() : realVal, ); } // 动画还原 myTimeout(() => { myDiagram.model.setDataProperty(node, 'flip', go.GraphObject.None); }, 100); if (node.stateName) return false; shRule = ruleOperation(node, realVal); myDiagram.model.setDataProperty( node, 'fontStroke', shRule ? shRule.attr : node.fontStroke, ); break; case 'waterCase': // 水池模型 const height = node.height - node.strokeWidth * 2; let waterHight = (realVal * height) / node.poolHight; waterHight = waterHight >= height ? height : waterHight; myDiagram.model.setDataProperty(node, 'waterHight', waterHight); shRule = JSON.parse(node.shRule); shRule.forEach((item) => { const min = item.min && !isNaN(item.min * 1) ? item.min * 1 : 0; const max = item.max && !isNaN(item.max * 1) ? item.max * 1 : 0; if (realVal >= min && realVal < max) myDiagram.model.setDataProperty( node, 'fillColor', hexToRgba(item.attr ? item.attr : node.fill, node.fillAlpha), ); }); break; case 'switchCase': // 开关模型 shRule = ruleOperation(node, realVal); myDiagram.model.setDataProperty( node, 'fillColor', hexToRgba(shRule ? shRule.attr : node.fill, node.opacity), ); myDiagram.model.setDataProperty(node, 'switch', shRule ? '是' : '否'); break; case 'rotateCase': // 状态模型 shRule = ruleOperation(node, realVal); myDiagram.model.setDataProperty(node, 'imgSrc', shRule ? shRule.attr : node.dtImgSrc); break; case 'pointCase': // 点状态模型 shRule = ruleOperation(node, realVal); myDiagram.model.setDataProperty( node, 'fillColor', hexToRgba(shRule ? shRule.attr : node.fill, node.opacity), ); break; case 'blenderCase': // 搅拌机模型 break; case 'HBar': // 合管模型 shRule = ruleOperation(node, realVal); myDiagram.model.setDataProperty(node, 'stroke', shRule ? shRule.attr : node.stroke); myDiagram.model.setDataProperty( node, 'waterStroke', shRule ? shRule.text : node.waterStroke, ); break; case 'speedCase': // 进度条模型 shRule = ruleOperation(node, realVal); myDiagram.model.setDataProperty( node, 'fillColor', hexToRgba(shRule ? shRule.attr : node.fill, node.opacity), ); const { width } = node; let speedWidth = (realVal * width) / node.speedWidth; speedWidth = speedWidth >= width ? width : speedWidth; myDiagram.model.setDataProperty(node, 'lineWidth', speedWidth); break; case 'modelCase': // 模板块模型 shRule = ruleOperation(node, realVal); if (node.shType === '层级展示') { myDiagram.model.setDataProperty( node, 'zOrder', shRule ? shRule.text * 1 || node.dtzOrder : node.dtzOrder, ); } else if (node.shType === '显隐展示') { myDiagram.model.setDataProperty(node, 'visible', shRule ? shRule.visible : true); } break; case 'ellipseCase': // 圆形模型 shRule = ruleOperation(node, realVal); if (node.shType === '层级展示') { myDiagram.model.setDataProperty( node, 'zOrder', shRule ? shRule.text * 1 || node.dtzOrder : node.dtzOrder, ); } else if (node.shType === '显隐展示') { myDiagram.model.setDataProperty(node, 'visible', shRule ? shRule.visible : true); } break; case 'imgCase': // 图片模型 shRule = ruleOperation(node, realVal); if (node.shType === '层级展示') { myDiagram.model.setDataProperty( node, 'zOrder', shRule ? shRule.text * 1 || node.dtzOrder : node.dtzOrder, ); } else if (node.shType === '显隐展示') { myDiagram.model.setDataProperty(node, 'visible', shRule ? shRule.visible : true); } break; case 'groupCase': // 分组模型 shRule = ruleOperation(node, realVal); if (node.shType === '显隐展示') { myDiagram.model.setDataProperty(node, 'visible', shRule ? shRule.visible : true); } break; default: break; } } catch (err) { // console.log(err); } }; /** *********************************节点状态展示逻辑****************************** */ const stateMethod = (node, list) => { const realVal = list.Value * 1; if (!node.shType) return false; let shRule = []; try { switch (node.category) { case 'valCase': // 实时值模型 // 颜色规则 shRule = ruleOperation(node, realVal); myDiagram.model.setDataProperty( node, 'fontStroke', shRule ? shRule.attr : node.fontStroke, ); break; default: break; } } catch (err) { // console.log(err); } }; /** ***********************************展示规则运算********************************* */ const ruleOperation = (node, realVal) => { const patt = /[><=]/gi; const shRule = JSON.parse(node.shRule).find((rule) => { if (rule.val.toString().match(patt)) { const ruleStr = 'if(' + rule.val + '){ return true } else { return false }'; try { return new Function('x', 'X', ruleStr)(realVal, realVal); } catch (err) { return false; } } else { return rule.val.toString().split(',').indexOf(realVal.toString()) > -1; } }); return shRule; }; /** ***********************************运行值规则运算********************************* */ const openValState = (openVal, realVal) => { const patt = /[><=]/gi; if (openVal.toString().match(patt)) { const ruleStr = 'if(' + openVal + '){ return true } else { return false }'; try { return new Function('x', 'X', ruleStr)(realVal, realVal); } catch (err) { return false; } } else { return openVal.toString().split(',').indexOf(realVal.toString()) > -1; } }; /** **************************************合管****************************************** */ const changLinkRouting = (e) => { const link = e.subject; if (link.toNode == null || link.fromNode == null) { return false; } if (link.fromNode.category === 'HBar' || link.toNode.category === 'HBar') { e.subject.routing = go.Link.Normal; } }; /** ************************************创建连接点*********************************** */ // 创建一个port,ID为name,spot控制其怎么被连接,放置于node的什么位置,output/input决定其哪里可以from和to const makePort = (name, spot, output, input) => { // the port is basically just a small transparent square return goJS(go.Shape, 'Circle', { fill: null, // not seen, by default; set to a translucent gray by showSmallPorts, defined below stroke: null, desiredSize: new go.Size(7, 7), alignment: spot, // align the port on the main Shape alignmentFocus: spot, // just inside the Shape portId: name, // declare this object to be a "port" fromSpot: spot, toSpot: spot, // declare where links may connect at this port fromLinkable: output, toLinkable: input, // declare whether the user may draw links to/from here cursor: 'pointer', // show a different cursor to indicate potential link point }); }; /** 动画设置*********************************************** */ const animationSvg = () => { const diagram = myDiagram; const oldskips = diagram.skipsUndoManager; diagram.skipsUndoManager = true; diagram.nodes.map((node) => { const shape = node.findObject('animateSvg'); if (!shape) return false; const gpRule = JSON.parse(node.data.gpRule || '[]').concat(); const amTime = node.data.amTime || 0; if (!amTime) return false; gpRule.map((item) => { mySetInterval(() => { const { time = 0, fill = 100, scale = 1, angle = 0 } = item; myTimeout(() => { shape.opacity = (fill || 100) / 100; shape.scale = (scale || 1) * 1; shape.angle = (angle || 0) * 1; }, 0.01 * amTime * time); }, amTime * 1); }); }); diagram.skipsUndoManager = oldskips; }; const myTimeout = (fn, delay) => { let timer; const stime = +new Date(); const myLoop = () => { if (isClose) return timer && cancelAnimationFrame(timer); const etime = +new Date(); if (stime + delay <= etime) { fn(); return; } timer = requestAnimationFrame(myLoop); }; timer = requestAnimationFrame(myLoop); return () => { cancelAnimationFrame(timer); }; }; const mySetInterval = (fn, interval) => { let timer; let stime = +new Date(); let etime; let myLoop = () => { etime = +new Date(); if (isClose) return timer && cancelAnimationFrame(timer); timer = requestAnimationFrame(myLoop); if (etime - stime >= interval) { stime = etime = +new Date(); fn(); } }; return requestAnimationFrame(myLoop); }; /** ******************************************水池效果****************************** */ const waterSvg = () => { const diagram = myDiagram; // poolWater = setInterval(() => { mySetInterval(() => { const oldskips = diagram.skipsUndoManager; diagram.skipsUndoManager = true; diagram.nodes.each((node) => { const shape = node.findObject('waterSvg'); if (!shape) return false; const range = (shape.range ? shape.range : 0) + 0.5; shape.range = range >= 5 ? 0 : range; shape.geometryString = `F M0 ${shape.range} L${shape.width} ${5 - shape.range} L${ shape.width } ${shape.height} L0 ${shape.height}z`; }); diagram.skipsUndoManager = oldskips; }, 100); }; /** ***********************************水流效果********************************** */ const loop = () => { const diagram = myDiagram; // tubeWater = setInterval(() => { mySetInterval(() => { const oldskips = diagram.skipsUndoManager; diagram.skipsUndoManager = true; diagram.links.each((link) => { const shape = link.findObject('PIPE'); if (!shape) return false; if (link.data.isHavingDash) { link.zOrder = 1; shape.strokeWidth = link.data.defaultWidth || 3; const off = shape.strokeDashOffset - 3; shape.strokeDashOffset = off <= 0 ? 60 : off; } else { link.zOrder = 0; shape.strokeWidth = 0; shape.strokeDashOffset = 0; } }); diagram.skipsUndoManager = oldskips; }, 60); }; /** **************************************泵状态效果*************************** */ const rotateSvg = () => { const diagram = myDiagram; // pumpType = setInterval(() => { mySetInterval(() => { const oldskips = diagram.skipsUndoManager; diagram.skipsUndoManager = true; diagram.nodes.each((node) => { const shape = node.findObject('rotateSvg'); if (!shape) return false; const _node = node.data; if (_node.switchState !== '开' || _node.realVal === '--' || _node.switch !== '是') return false; const off = shape.angle + 60; shape.angle = off <= 360 ? off : 0; }); diagram.skipsUndoManager = oldskips; }, 60); }; /** *********************************搅拌机状态效果************************* */ const blenderSvg = () => { const diagram = myDiagram; // blenderType = setInterval(() => { mySetInterval(() => { const oldskips = diagram.skipsUndoManager; diagram.skipsUndoManager = true; diagram.nodes.each((node) => { const shape = node.findObject('blenderSvg'); if (!shape) return false; const _node = node.data; const srcStr = _node.dtImgSrc.split('/').pop(); if (_node.switchState !== '开' || _node.realVal === '--' || _node.switch !== '是') { shape.source = require(`./images/组态/状态/${srcStr.replace(/[0-9]/gi, 1)}`); return false; } shape.flag = shape.flag || 1; const num = shape.source.match(/\d/)[0] * 1; let _num = 1; if (shape.flag === 1) { _num = num < 5 ? num + 1 : 4; if (num >= 5) shape.flag = 2; } else { _num = num > 1 ? num - 1 : 2; if (num <= 1) shape.flag = 1; } shape.source = require(`./images/组态/状态/${srcStr.replace(/[0-9]/gi, _num)}`); }); diagram.skipsUndoManager = oldskips; }, 100); }; /** *******************将myDiagram.model中的信息展示在画板上*********************** */ const loadDiagramProperties = (e) => { const pos = myDiagram.model.modelData.position; if (pos) myDiagram.initialPosition = go.Point.parse(pos); }; /** *******************绑定角色可见*************************** */ const roleVisibleBinding = () => { return new go.Binding('visible', '', function (data) { if (!data.roles) return true; const roles = data.roles.split(','); const curRoleMap = {}; globalConfig && globalConfig.userInfo && globalConfig.userInfo.roles && globalConfig.userInfo.roles.forEach(function (role) { curRoleMap[role.OID] = role; }); const samerole = roles.filter(function (roleID) { return !!curRoleMap[roleID]; }); return samerole.length > 0; }); }; /** ***********************************节点样式********************************** */ const nodeStyle = () => { return [ new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), { locationSpot: go.Spot.Center, }, ]; }; /** ************************************联网判断******************************* */ const onlineMethod = (pathImg, url) => { const ImgObj = new Image(); ImgObj.src = pathImg; ImgObj.onload = () => { online = ImgObj.fileSize > 0 || (ImgObj.width > 0 && ImgObj.height > 0); getConfiguraList(); }; ImgObj.onerror = () => { online = false; getConfiguraList(); }; }; useEffect(() => { if (!props.name) { setDescription('咦~工艺图配置信息不全哦~'); setIsEmpty(true); setSpinning(false); return false; } const url = globalConfig.mainserver ? globalConfig.mainserver : 'https://panda-water.cn/'; onlineMethod(`${url}civweb4/assets/images/bootPage/熊猫图标.png`, url); return () => { isClose = true; if (myDiagram) { myDiagram.removeDiagramListener('ViewportBoundsChanged', viewportBoundsChang); myDiagram.div = null; myDiagram = null; } }; }, []); useEffect(() => { play = props.play || false; times = props.times || 2; }, [props.play, props.times]); useEffect(() => { speed = props.speed || 0; }, [props.speed]); useEffect(() => { historyParams = props.params; if (dataType === '历史') getHistoryData(false); if (dataType === '统计') getStatisticsData(false); }, [props.params]); // 图片模型翻转 const pictureFlipMethod = (type) => { let flipType = ''; switch (type) { case 'none': flipType = go.GraphObject.None; break; case 'horizontal': flipType = go.GraphObject.FlipHorizontal; break; case 'vertical': flipType = go.GraphObject.FlipVertical; break; case 'both': flipType = go.GraphObject.FlipBoth; break; default: flipType = go.GraphObject.None; break; } return flipType; }; /** ************************************获取画板JSON******************************* */ const getDiagramJson = async (list, siteInfo) => { const response = await getSketchPadContent({ dimension: list.dimension, siteCode: list.siteCode, fileName: list.deployURL.split('\\').pop(), _site: siteCodeStr, }); if (response.code === 0) { if (isClose) return false; const fromJson = response.data ? response.data : { linkFromPortIdProperty: 'fromPort', linkToPortIdProperty: 'toPort', nodeDataArray: [], linkDataArray: [], }; // bindData = []; // devices.forEach((item, index) => { // const name = `设备${stationList[index]}`; // bindData.push({ // code: item, // name, // type: siteInfo && siteInfo[name] ? siteInfo[name].Type : '', // }); // }); diagramRender(typeof fromJson === 'string' ? fromJson : JSON.stringify(fromJson), list); if (dataType === '历史') getHistoryData(true); if (dataType === '统计') getStatisticsData(true); } else { message.error(response.msg); } }; /** ************************************历史数据获取******************************* */ const getHistoryData = async (flag) => { try { if (!myDiagram) return false; setSpinLoad(true); speed = 0; const json = JSON.parse(myDiagram.model.toJson()); const jsonCopy = JSON.parse(JSON.stringify(json)); const acrossTables = []; bindData.map((list) => { let sensors = []; jsonCopy.nodeDataArray.forEach((item) => { item.shName && item.stationName === list.name && sensors.push(item.shName); }); jsonCopy.linkDataArray.forEach((item) => { item.shName && item.stationName === list.name && sensors.push(item.shName); }); if (sensors.length && list.code) acrossTables.push({ deviceType: list.type, sensors: Array.from(new Set(sensors)).join(','), deviceCode: list.code, }); }); const params = { isDilute: false, zoom: '30', unit: 'h', ignoreOutliers: false, isVertical: false, // 是否查询竖表 dateFrom: moment(new Date()).format('yyyy-MM-DD 00:00:00'), dateTo: moment(new Date()).format('yyyy-MM-DD 23:59:59'), ...historyParams, acrossTables, }; const results = await getHistoryInfo(params); historyData = results?.data || []; let timeArr = []; historyData.forEach((item) => { const timeList = item.dataModel.map((list) => { return moment(list.pt).format('yyyy-MM-DD HH:mm:ss'); }); timeArr = timeArr.concat(timeList); }); const _timeData = dataUnique(timeArr); timeData = _timeData.sort(function (a, b) { return new Date(a).getTime() - new Date(b).getTime(); }); chartHistoryDataRender(historyData); if (flag) historyTimeRender(); setSpinLoad(false); } catch (err) { setSpinLoad(false); } }; /** ************************************统计数据获取******************************* */ const getStatisticsData = async (flag) => { try { if (!myDiagram) return false; setSpinLoad(true); speed = 0; const json = JSON.parse(myDiagram.model.toJson()); const jsonCopy = JSON.parse(JSON.stringify(json)); const acrossTables = []; bindData.map((list) => { let sensors = []; jsonCopy.nodeDataArray.forEach((item) => { item.shName && item.stationName === list.name && sensors.push(item.shName); }); jsonCopy.linkDataArray.forEach((item) => { item.shName && item.stationName === list.name && sensors.push(item.shName); }); if (sensors.length && list.code) acrossTables.push({ accountName: list.type, nameTypeList: sensors.map((item) => { const listType = statisticType.find((arr) => { return arr.name === item; }); return { name: item, type: listType?.type || 'Sub', }; }), dateFrom: historyParams.dateFrom || moment(new Date()).format('yyyy-MM-DD 00:00:00'), dateTo: historyParams.dateTo || moment(new Date()).format('yyyy-MM-DD 23:59:59'), deviceCode: list.code, }); }); const params = { pageIndex: 1, pageSize: 999, q_DeviceReports: acrossTables, dateType: 'day', ...historyParams, }; const results = await getStatisticsInfo(params); const res = results?.data?.list || []; let timeArr = []; let statisticsData = []; res.forEach((item) => { const listData = item.dNameDataList.map((list) => { return { code: item.code, eName: item.eName, eShortName: item.eShortName, ...list, }; }); statisticsData = statisticsData.concat(listData); }); historyData = [].concat(statisticsData); historyData.forEach((item) => { const timeList = item.nameDate.map((list) => { return moment(list.time).format('yyyy-MM-DD HH:mm:ss'); }); timeArr = timeArr.concat(timeList); }); const _timeData = dataUnique(timeArr); timeData = _timeData.sort(function (a, b) { return new Date(a).getTime() - new Date(b).getTime(); }); chartStatisticsDataRender(historyData); if (flag) historyTimeRender(); setSpinLoad(false); } catch (err) { setSpinLoad(false); } }; /** ****************************************数据去重******************************* */ const dataUnique = (arr) => { return Array.from(new Set(arr)); }; /** ***********************************图表历史数据处理**************************** */ const chartHistoryDataRender = (mqttData) => { const time = timeData[speed]; loopLoadMethod(time); const json = JSON.parse(myDiagram.model.toJson()); const jsonCopy = JSON.parse(JSON.stringify(json)); const oldJson = deepCopy(jsonCopy); try { jsonCopy.linkDataArray.forEach((item) => { if (!item.shName || item.shType !== '线条展示') return false; mqttData.forEach((list) => { const bindList = bindData.find((arr) => { return arr.code === list.stationCode; }); const pvList = list.dataModel.find((arr) => { return moment(arr.pt).format('yyyy-MM-DD HH:mm:ss') === time; }); if (!bindList || item.stationName !== bindList.name) return false; if ( !pvList || pvList.PV === null || list.sensorName !== item.shName || item.realVal === pvList.pv ) return false; item.realVal = pvList.pv * 1; const shRule = ruleOperation(item, item.realVal); if (shRule) { myDiagram.model.setDataProperty(item, 'stroke', shRule.attr); myDiagram.model.setDataProperty(item, 'waterStroke', shRule.text); } else { myDiagram.model.setDataProperty(item, 'stroke', item.stroke); myDiagram.model.setDataProperty(item, 'waterStroke', item.waterStroke); } }); }); } catch (e) { // 水流展示 } try { jsonCopy.nodeDataArray.forEach((item) => { if (!(item.shName || item.figure === 'updateTime')) return false; const node = myDiagram.model.findNodeDataForKey(item.key); mqttData.forEach((list) => { if (node.figure === 'updateTime') { myDiagram.model.setDataProperty( node, 'text', moment(list.pt).format('yyyy-MM-DD HH:mm:ss'), ); return false; } const bindList = bindData.find((arr) => { return arr.code === list.stationCode; }); const pvList = list.dataModel.find((arr) => { return moment(arr.pt).format('yyyy-MM-DD HH:mm:ss') === time; }); if (!bindList || item.stationName !== bindList.name) return false; if ( (!pvList || pvList.pv === null || list.sensorName !== item.shName || item.realVal === pvList.pv) && list.sensorName !== item.stateName ) return false; pvList.Value = pvList.pv; if (list.sensorName === item.shName) showNodeMethod(node, pvList); if (list.sensorName === item.stateName) stateMethod(node, pvList); }); }); } catch (e) { // 节点展示 } try { const jsonModel = waterFlow.waterFlowControlByDiagramJson(oldJson, myDiagram); if (!jsonModel) return false; const oldLink = myDiagram.model.linkDataArray; const dataLink = []; jsonModel.linkDataArray.forEach((item, index) => { const list = Object.assign({}, oldLink[index]); list.isHavingDash = item.isHavingDash; dataLink.push(list); }); jsonModel.nodeDataArray.forEach((item) => { if (item.category === 'HBar') { const node = myDiagram.model.findNodeDataForKey(item.key); const waterStroke = item.typeDash ? 'transparent' : item.hBarClolor; if (item.typeDash != node.typeDash) { myDiagram.model.setDataProperty(node, 'waterStroke', waterStroke); myDiagram.model.setDataProperty(node, 'typeDash', item.typeDash); } } }); dataLink.forEach((item) => { const node = myDiagram.findLinkForData(item); if (item.isHavingDash != node.data.isHavingDash) myDiagram.model.setDataProperty(node.data, 'isHavingDash', item.isHavingDash); }); } catch (e) { // 水流展示 } }; /** ***********************************图表历史数据处理**************************** */ const chartStatisticsDataRender = (mqttData) => { const time = timeData[speed]; loopLoadMethod(time); const json = JSON.parse(myDiagram.model.toJson()); const jsonCopy = JSON.parse(JSON.stringify(json)); const oldJson = deepCopy(jsonCopy); try { jsonCopy.linkDataArray.forEach((item) => { if (!item.shName || item.shType !== '线条展示') return false; mqttData.forEach((list) => { const bindList = bindData.find((arr) => { return arr.code === list.code; }); const pvList = list.nameDate.find((arr) => { return moment(arr.time).format('yyyy-MM-DD HH:mm:ss') === time; }); if (!bindList || item.stationName !== bindList.name) return false; if ( !pvList || pvList.value === null || list.dName !== item.shName || item.realVal === pvList.value ) return false; item.realVal = pvList.value * 1; const shRule = ruleOperation(item, item.realVal); if (shRule) { myDiagram.model.setDataProperty(item, 'stroke', shRule.attr); myDiagram.model.setDataProperty(item, 'waterStroke', shRule.text); } else { myDiagram.model.setDataProperty(item, 'stroke', item.stroke); myDiagram.model.setDataProperty(item, 'waterStroke', item.waterStroke); } }); }); } catch (e) { // 水流展示 } try { jsonCopy.nodeDataArray.forEach((item) => { if (!(item.shName || item.figure === 'updateTime')) return false; const node = myDiagram.model.findNodeDataForKey(item.key); mqttData.forEach((list) => { if (node.figure === 'updateTime') { myDiagram.model.setDataProperty( node, 'text', moment(list.value).format('yyyy-MM-DD HH:mm:ss'), ); return false; } const bindList = bindData.find((arr) => { return arr.code === list.code; }); const pvList = list.nameDate.find((arr) => { return moment(arr.time).format('yyyy-MM-DD HH:mm:ss') === time; }); if (!bindList || item.stationName !== bindList.name) return false; if ( (!pvList || pvList.value === null || list.dName !== item.shName || item.realVal === pvList.value) && list.dName !== item.stateName ) return false; pvList.Value = pvList.value; if (list.dName === item.shName) showNodeMethod(node, pvList); if (list.dName === item.stateName) stateMethod(node, pvList); }); }); } catch (e) { // 节点展示 } try { const jsonModel = waterFlow.waterFlowControlByDiagramJson(oldJson, myDiagram); if (!jsonModel) return false; const oldLink = myDiagram.model.linkDataArray; const dataLink = []; jsonModel.linkDataArray.forEach((item, index) => { const list = Object.assign({}, oldLink[index]); list.isHavingDash = item.isHavingDash; dataLink.push(list); }); jsonModel.nodeDataArray.forEach((item) => { if (item.category === 'HBar') { const node = myDiagram.model.findNodeDataForKey(item.key); const waterStroke = item.typeDash ? 'transparent' : item.hBarClolor; if (item.typeDash != node.typeDash) { myDiagram.model.setDataProperty(node, 'waterStroke', waterStroke); myDiagram.model.setDataProperty(node, 'typeDash', item.typeDash); } } }); dataLink.forEach((item) => { const node = myDiagram.findLinkForData(item); if (item.isHavingDash != node.data.isHavingDash) myDiagram.model.setDataProperty(node.data, 'isHavingDash', item.isHavingDash); }); } catch (e) { // 水流展示 } }; /** **********************历史数据循环**************************** */ const historyTimeRender = () => { historyInterval(() => { if (!play || !historyData.length || !timeData.length) return false; speed = speed + 1; if (speed >= timeData.length) { play = false; loopLoadMethod(timeData.slice(-1)[0]); return false; } if (dataType === '历史') chartHistoryDataRender(historyData); if (dataType === '统计') chartStatisticsDataRender(historyData); }); }; /** **********************历史数据循环函数**************************** */ const historyInterval = (fn) => { let timer; let stime = +new Date(); let etime; let myLoop = () => { etime = +new Date(); if (isClose) return timer && cancelAnimationFrame(timer); if (etime - stime >= times * 1000) { stime = etime = +new Date(); fn(); } timer = requestAnimationFrame(myLoop); }; return requestAnimationFrame(myLoop); }; // 数据回调 const loopLoadMethod = (time) => { props.callback && props.callback(speed, timeData.length, play, time); }; /** **************************************跳转方法****************************************** */ const menuJumpMethod = (data) => { const opRule = JSON.parse(data.opRule); const widget = opRule && opRule.widget ? opRule.widget : ''; const params = opRule && opRule.params ? (isJson(opRule.params) && JSON.parse(opRule.params)) || {} : {}; const list = querySkipUrl(globalConfig?.widgets || [], widget); if (!list || !widget) return false; window.history.pushState(params, null, `/civbase/${list.product || 'civweb4'}/${list.url}`); }; /** **************************************历史模态渲染****************************************** */ const historyModalRender = (data, list) => { historyInfoParams = [ { deviceCode: list.code, sensors: data.shName, deviceType: list.type, }, ]; setIsHIModalVisible(true); }; // 监听画布zoom变化 const viewportBoundsChang = () => { myDiagram.contentAlignment = go.Spot.Default; myDiagram.contentAlignment = go.Spot.Center; }; /** **********************************画布渲染************************************ */ const diagramRender = (jsonStr, chartInfo) => { myDiagram = goJS( go.Diagram, twoID, // must name or refer to the DIV HTML element { initialContentAlignment: go.Spot.Center, contentAlignment: go.Spot.Center, allowDrop: false, // must be true to accept drops from the Palette 右边的面板允许防止图形 draggingTool: new GuidedDraggingTool(), allowZoom: isZoom ? true : false, allowSelect: false, 'draggingTool.dragsLink': true, isReadOnly: true, autoScale: isZoom ? go.Diagram.None : go.Diagram.Uniform, // 自适应,默认不自适应 initialAutoScale: go.Diagram.Uniform, // 自适应,默认不自适应 'draggingTool.isGridSnapEnabled': true, 'linkingTool.isUnconnectedLinkValid': true, 'animationManager.duration': 100, allowHorizontalScroll: isZoom ? true : false, // padding: 20, allowVerticalScroll: isZoom ? true : false, 'linkingTool.portGravity': 20, 'relinkingTool.isUnconnectedLinkValid': true, 'relinkingTool.portGravity': 20, 'draggingTool.horizontalGuidelineColor': 'blue', 'draggingTool.verticalGuidelineColor': 'blue', 'draggingTool.centerGuidelineColor': 'green', rotatingTool: goJS(TopRotatingTool), // defined below 'rotatingTool.snapAngleMultiple': 15, 'rotatingTool.snapAngleEpsilon': 15, 'undoManager.isEnabled': true, LinkDrawn: changLinkRouting, // LinkReshaped: (e) => { // e.subject.routing = go.Link.Orthogonal; // }, 'linkingTool.direction': go.LinkingTool.ForwardsOnly, }, ); /** **********************************分组模型************************************* */ myDiagram.groupTemplate = ('groupCase', goJS( go.Group, 'Auto', { ungroupable: true, zOrder: 1, visible: true }, { // 设置其可选择 selectable: false, layerName: 'Background', }, new go.Binding('visible', 'visible').makeTwoWay(), goJS( go.Shape, 'RoundedRectangle', // surrounds everything { parameter1: 10, fill: 'transparent', strokeWidth: 0, stroke: 'transparent', }, ), goJS( go.Panel, 'Auto', // position header above the subgraph goJS( go.Placeholder, // represents area for all member parts { background: 'transparent' }, ), ), )); // 自定义矩形 go.Shape.defineFigureGenerator('RoundedRectanglePlus', (shape, w, h) => { // this figure takes one parameter, the size of the corner let p1 = Infinity; // default corner size if (shape !== null) { const param1 = shape.parameter1; if (!isNaN(param1) && param1 >= 0) p1 = param1; // can't be negative or NaN } p1 = Math.min(p1, w / 2); p1 = Math.min(p1, h / 2); // limit by whole height or by half height? const geo = new go.Geometry(); // a single figure consisting of straight lines and quarter-circle arcs geo.add( new go.PathFigure(0, p1) .add(new go.PathSegment(go.PathSegment.Arc, 180, 90, p1, p1, p1, p1)) .add(new go.PathSegment(go.PathSegment.Line, w - p1, 0)) .add(new go.PathSegment(go.PathSegment.Arc, 270, 90, w - p1, p1, p1, p1)) .add(new go.PathSegment(go.PathSegment.Arc, 0, 90, w - p1, h - p1, p1, p1)) .add(new go.PathSegment(go.PathSegment.Arc, 90, 90, p1, h - p1, p1, p1).close()), ); // don't intersect with two top corners when used in an "Auto" Panel geo.spot1 = new go.Spot(0, 0, 0.3 * p1, 0.3 * p1); geo.spot2 = new go.Spot(1, 1, -0.3 * p1, 0); return geo; }); /** *********************************节点模板************************************* */ // 背景模板定义 myDiagram.nodeTemplateMap.add( 'bgCase', goJS( go.Node, 'Spot', { locationSpot: go.Spot.Center, zOrder: 0 }, // new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding('visible', 'visible').makeTwoWay(), new go.Binding('angle').makeTwoWay(), { // 设置其可选择 selectable: false, layerName: 'Background', }, // the main object is a Panel that surrounds a TextBlock with a Shape ~图形:Panel包围着TextBlock goJS( go.Panel, 'Auto', { name: 'PANEL', }, new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify), goJS( go.Picture, { width: 56, height: 56, scale: 1, source: '', background: '#2e3343' }, new go.Binding('source', 'imgSrc', function (v) { const own = myDiagram ? myDiagram.model.findNodeDataForKey('bgCase') : {}; props.bgMethod && props.bgMethod(own); return v ? `/PandaMonitor/Monitor/SketchPad/PreviewResource?name=${v}&_site=${siteCodeStr}` : ''; }).makeTwoWay(), new go.Binding('scale', 'scale').makeTwoWay(), new go.Binding('width', 'width').makeTwoWay(), new go.Binding('height', 'height').makeTwoWay(), new go.Binding('background', 'background').makeTwoWay(), ), ), ), ); // 表格节点定义 myDiagram.nodeTemplateMap.add( 'tableCase', goJS( go.Node, 'Auto', { locationSpot: go.Spot.Center, zOrder: 1 }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding('angle').makeTwoWay(), goJS( go.Shape, { fill: 'white', strokeWidth: 1, stroke: '#808080', }, new go.Binding('stroke').makeTwoWay(), new go.Binding('strokeWidth').makeTwoWay(), ), goJS( go.Panel, 'Table', { padding: 0, defaultRowSeparatorStroke: '#808080', defaultColumnSeparatorStroke: '#808080', defaultRowSeparatorStrokeWidth: 1, defaultColumnSeparatorStrokeWidth: 1, background: '#ffffff', }, new go.Binding('background', 'fillColor').makeTwoWay(), new go.Binding('defaultRowSeparatorStroke', 'stroke').makeTwoWay(), new go.Binding('defaultRowSeparatorStrokeWidth', 'strokeWidth').makeTwoWay(), new go.Binding('defaultColumnSeparatorStroke', 'stroke').makeTwoWay(), new go.Binding('defaultColumnSeparatorStrokeWidth', 'strokeWidth').makeTwoWay(), new go.Binding('itemArray', 'content').makeTwoWay(), { // 表内容 defaultAlignment: go.Spot.Left, itemTemplate: goJS( go.Panel, 'TableRow', new go.Binding('itemArray', 'columns').makeTwoWay(), { itemTemplate: goJS( go.Panel, // each of which as "attr" and "text" properties 'Spot', { background: 'transparent', alignment: go.Spot.Center }, new go.Binding('column').makeTwoWay(), new go.Binding('columnSpan', 'cSpan').makeTwoWay(), new go.Binding('rowSpan', 'rSpan').makeTwoWay(), new go.Binding('padding', 'padding', function (v) { if (v && isNumber(v)) return v; const padding = v ? v.split(',') : null; return padding ? new go.Margin( padding?.[0] * 1 || 0, padding?.[1] * 1 || 0, padding?.[2] * 1 || 0, padding?.[3] * 1 || 0, ) : 0; }).makeTwoWay(), goJS( go.Shape, 'RoundedRectanglePlus', { name: 'SHAPE', fill: 'transparent', stroke: '#ffffff', strokeWidth: 0, parameter1: 0, }, new go.Binding('fill', 'background').makeTwoWay(), new go.Binding('parameter1', 'radius').makeTwoWay(), new go.Binding('stroke', 'bdColor').makeTwoWay(), new go.Binding('strokeWidth', 'bdWidth').makeTwoWay(), new go.Binding('width').makeTwoWay(), new go.Binding('height').makeTwoWay(), ), goJS( go.TextBlock, textStyle(), { editable: true }, { // margin: new go.Margin(2, 10, 10, 2), wrap: go.TextBlock.WrapFit, textAlign: 'center', font: 'bold 12px Helvetica, Arial, sans-serif', stroke: '#454545', }, new go.Binding('text').makeTwoWay(), new go.Binding('font', 'style').makeTwoWay(), new go.Binding('stroke', 'color').makeTwoWay(), new go.Binding('textAlign', 'align').makeTwoWay(), new go.Binding('maxSize', 'width', function (v) { try { return new go.Size(v - 20, NaN); } catch (err) { return new go.Size(NaN, NaN); } }).makeTwoWay(), new go.Binding('minSize', 'width', function (v) { try { return new go.Size(v - 20, NaN); } catch (err) { return new go.Size(NaN, NaN); } }).makeTwoWay(), ), ), }, ), }, ), ), ); // img节点定义 myDiagram.nodeTemplateMap.add( 'imgCase', goJS( go.Node, 'Spot', { locationSpot: go.Spot.Center, zOrder: 1, cursor: 'default' }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('cursor', 'cursor').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding('angle').makeTwoWay(), roleVisibleBinding(), // 绑定角色可见 // the main object is a Panel that surrounds a TextBlock with a Shape ~图形:Panel包围着TextBlock goJS( go.Panel, 'Auto', { name: 'PANEL', }, new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify), new go.Binding('visible', 'visible').makeTwoWay(), goJS( go.Picture, { name: 'animateSvg', width: 56, height: 56, column: 0, scale: 1, source: require('./images/组态/默认.png'), flip: go.GraphObject.None, }, new go.Binding('source', 'imgSrc', function (v) { return !v ? require('./images/组态/默认.png') : `/PandaMonitor/Monitor/SketchPad/PreviewResource?name=${v}&_site=${siteCodeStr}`; }).makeTwoWay(), new go.Binding('flip', 'flip', pictureFlipMethod), new go.Binding('scale', 'scale').makeTwoWay(), new go.Binding('width', 'width').makeTwoWay(), new go.Binding('height', 'height').makeTwoWay(), ), ), { click(e, node) { const { data } = node; const list = bindData.find((item) => { return item.name === data.stationName; }); if (!list) return false; // 画板跳转 switch (data.opType) { case '画板跳转': // 图片模型 break; case '功能跳转': // 功能模型 menuJumpMethod(data); break; case '自定义交互': // 自定义交互 customBack(data); break; default: break; } }, }, ), ); // svg节点定义 myDiagram.nodeTemplateMap.add( 'svgCase', goJS( go.Node, 'Spot', { locationSpot: go.Spot.Center, zOrder: 1, cursor: 'default' }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('cursor', 'cursor').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding('angle').makeTwoWay(), roleVisibleBinding(), // 绑定角色可见 goJS( go.Panel, 'Auto', { name: 'PANEL', }, new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify), new go.Binding('visible', 'visible').makeTwoWay(), goJS( go.Picture, { name: 'animateSvg', width: 56, height: 56, column: 0, scale: 1, source: '', flip: go.GraphObject.None, }, new go.Binding('source', 'imgSrc', (v) => { return `${imgUrl}Model/Preview/${encodeURIComponent(v)}`; }), new go.Binding('scale', 'scale').makeTwoWay(), // new go.Binding('width', 'width').makeTwoWay(), // new go.Binding('height', 'height').makeTwoWay(), new go.Binding('width', 'width', function (v) { return (v * 1).toFixed(1) * 1; }).makeTwoWay(), new go.Binding('height', 'height', function (v) { return (v * 1).toFixed(1) * 1; }).makeTwoWay(), new go.Binding('flip', 'flip', pictureFlipMethod), ), ), { click(e, node) { const { data } = node; // 画板跳转 switch (data.opType) { case '画板跳转': // 图片模型 break; case '功能跳转': // 功能模型 menuJumpMethod(data); break; case '自定义交互': // 自定义交互 customBack(data); break; default: break; } }, }, ), ); // 模板块定义 myDiagram.nodeTemplateMap.add( 'modelCase', goJS( go.Node, 'Auto', nodeStyle(), 'Spot', { locationSpot: go.Spot.Center, zOrder: 1 }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), { // 设置其可改变大小 resizeObjectName: 'SHAPE', }, new go.Binding('angle').makeTwoWay(), roleVisibleBinding(), // 绑定角色可见 goJS( go.Shape, 'RoundedRectanglePlus', { name: 'SHAPE', fill: 'rgba(128,128,128,0.2)', stroke: 'gray', parameter1: 0 }, new go.Binding('visible', 'visible').makeTwoWay(), new go.Binding('parameter1', 'radius').makeTwoWay(), new go.Binding('fill', 'fillColor').makeTwoWay(), new go.Binding('stroke').makeTwoWay(), new go.Binding('strokeWidth').makeTwoWay(), new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify), ), ), ); // 圆形定义 myDiagram.nodeTemplateMap.add( 'ellipseCase', goJS( go.Node, 'Auto', nodeStyle(), 'Spot', { locationSpot: go.Spot.Center, zOrder: 1 }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), { // 设置其可改变大小 resizeObjectName: 'SHAPE', }, new go.Binding('angle').makeTwoWay(), roleVisibleBinding(), // 绑定角色可见 goJS( go.Shape, 'Ellipse', { name: 'SHAPE', fill: 'rgba(128,128,128,0.2)', stroke: 'gray' }, new go.Binding('visible', 'visible').makeTwoWay(), new go.Binding('fill', 'fillColor').makeTwoWay(), new go.Binding('stroke').makeTwoWay(), new go.Binding('strokeWidth').makeTwoWay(), new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify), ), ), ); // 设备名称定义 myDiagram.nodeTemplateMap.add( 'deviceCase', goJS( go.Node, 'Auto', nodeStyle(), 'Spot', { locationSpot: go.Spot.Center, zOrder: 3, cursor: 'default' }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('cursor', 'cursor').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding('angle').makeTwoWay(), roleVisibleBinding(), // 绑定角色可见 goJS( go.Shape, 'RoundedRectanglePlus', { name: 'SHAPE', strokeWidth: 10, stroke: '#000000', parameter1: 0 }, new go.Binding('fill', 'fillColor').makeTwoWay(), new go.Binding('stroke').makeTwoWay(), new go.Binding('strokeWidth').makeTwoWay(), new go.Binding('parameter1', 'radius').makeTwoWay(), new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify), ), goJS( go.TextBlock, textStyle(), { margin: 5, maxSize: new go.Size(NaN, NaN), minSize: new go.Size(NaN, 1), wrap: go.TextBlock.WrapFit, textAlign: 'center', editable: true, font: 'bold 12px Helvetica, Arial, sans-serif', stroke: '#454545', }, new go.Binding('text').makeTwoWay(), new go.Binding('font', 'fontStyle'), new go.Binding('stroke', 'fontStroke').makeTwoWay(), new go.Binding('textAlign', 'fontAlign'), new go.Binding('maxSize', 'textSize'), new go.Binding('minSize', 'textSize'), ), { click(e, node) { const { data } = node; const list = bindData.find((item) => { return item.name === data.stationName; }); if (!list) return false; switch (data.opType) { case '画板跳转': // 图片模型 break; case '功能跳转': // 功能模型 menuJumpMethod(data); break; case '自定义交互': // 自定义交互 customBack(data); break; default: break; } }, }, ), ); // 数据源模型定义 myDiagram.nodeTemplateMap.add( 'dataSource', goJS( go.Node, 'Auto', nodeStyle(), 'Spot', { locationSpot: go.Spot.Center, zOrder: 3, cursor: 'default', visible: false }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('cursor', 'cursor').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding('angle').makeTwoWay(), goJS( go.Shape, 'RoundedRectanglePlus', { name: 'SHAPE', strokeWidth: 10, stroke: '#000000', parameter1: 0 }, new go.Binding('fill', 'fillColor').makeTwoWay(), new go.Binding('stroke').makeTwoWay(), new go.Binding('strokeWidth').makeTwoWay(), new go.Binding('parameter1', 'radius').makeTwoWay(), new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify), ), goJS( go.TextBlock, textStyle(), { maxSize: new go.Size(NaN, NaN), minSize: new go.Size(NaN, 1), wrap: go.TextBlock.WrapFit, textAlign: 'center', editable: true, font: 'bold 12px Helvetica, Arial, sans-serif', stroke: '#454545', }, new go.Binding('text').makeTwoWay(), new go.Binding('font', 'fontStyle'), new go.Binding('stroke', 'fontStroke').makeTwoWay(), new go.Binding('textAlign', 'fontAlign'), new go.Binding('maxSize', 'textSize'), new go.Binding('minSize', 'textSize'), ), ), ); // 源数据模型定义 myDiagram.nodeTemplateMap.add( 'dataCase', goJS( go.Node, 'Auto', nodeStyle(), 'Spot', { locationSpot: go.Spot.Center, zOrder: 3, cursor: 'default' }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('cursor', 'cursor').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding('angle').makeTwoWay(), roleVisibleBinding(), // 绑定角色可见 goJS( go.Shape, 'RoundedRectanglePlus', { name: 'SHAPE', strokeWidth: 10, stroke: '#000000', parameter1: 0 }, new go.Binding('fill', 'fillColor').makeTwoWay(), new go.Binding('stroke').makeTwoWay(), new go.Binding('strokeWidth').makeTwoWay(), new go.Binding('parameter1', 'radius').makeTwoWay(), new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify), ), goJS( go.TextBlock, textStyle(), { // margin: 5, maxSize: new go.Size(NaN, NaN), minSize: new go.Size(NaN, 1), wrap: go.TextBlock.WrapFit, textAlign: 'center', editable: true, font: 'bold 12px Helvetica, Arial, sans-serif', stroke: '#454545', }, new go.Binding('text').makeTwoWay(), new go.Binding('font', 'fontStyle'), new go.Binding('stroke', 'fontStroke').makeTwoWay(), new go.Binding('textAlign', 'fontAlign'), new go.Binding('maxSize', 'textSize'), new go.Binding('minSize', 'textSize'), ), { click(e, node) { const { data } = node; const list = bindData.find((item) => { return item.name === data.stationName; }); if (!list) return false; switch (data.opType) { case '画板跳转': // 图片模型 drawBoardMethod(data); break; case '功能跳转': // 功能模型 menuJumpMethod(data); break; case '视频查看': // 视频查看 break; case '自定义交互': // 自定义交互 customBack(data); break; default: break; } }, }, ), ); // 名称定义 myDiagram.nodeTemplateMap.add( 'nameCase', goJS( go.Node, 'Auto', nodeStyle(), 'Spot', { locationSpot: go.Spot.Center, zOrder: 3, cursor: 'default' }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('cursor', 'cursor').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding('angle').makeTwoWay(), roleVisibleBinding(), // 绑定角色可见 goJS( go.Shape, 'RoundedRectanglePlus', { name: 'SHAPE', strokeWidth: 10, stroke: '#000000', parameter1: 0 }, new go.Binding('fill', 'fillColor').makeTwoWay(), new go.Binding('stroke').makeTwoWay(), new go.Binding('strokeWidth').makeTwoWay(), new go.Binding('parameter1', 'radius').makeTwoWay(), new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify), ), goJS( go.TextBlock, textStyle(), { margin: 5, maxSize: new go.Size(NaN, NaN), minSize: new go.Size(NaN, 1), wrap: go.TextBlock.WrapFit, textAlign: 'center', editable: true, font: 'bold 12px Helvetica, Arial, sans-serif', stroke: '#454545', }, new go.Binding('text').makeTwoWay(), new go.Binding('font', 'fontStyle'), new go.Binding('stroke', 'fontStroke').makeTwoWay(), new go.Binding('textAlign', 'fontAlign'), new go.Binding('maxSize', 'textSize'), new go.Binding('minSize', 'textSize'), ), { click(e, node) { const { data } = node; switch (data.opType) { case '画板跳转': // 图片模型 break; case '功能跳转': // 功能模型 menuJumpMethod(data); break; case '自定义交互': // 自定义交互 customBack(data); break; default: break; } }, }, ), ); // 更新时间定义 myDiagram.nodeTemplateMap.add( 'timeCase', goJS( go.Node, 'Auto', nodeStyle(), 'Spot', { locationSpot: go.Spot.Center, zOrder: 3, cursor: 'default' }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('cursor', 'cursor').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding('angle').makeTwoWay(), roleVisibleBinding(), // 绑定角色可见 goJS( go.Shape, 'RoundedRectanglePlus', { name: 'SHAPE', strokeWidth: 10, stroke: '#000000', parameter1: 0 }, new go.Binding('fill', 'fillColor').makeTwoWay(), new go.Binding('stroke').makeTwoWay(), new go.Binding('strokeWidth').makeTwoWay(), new go.Binding('parameter1', 'radius').makeTwoWay(), new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify), ), goJS( go.TextBlock, textStyle(), { // margin: 5, maxSize: new go.Size(NaN, NaN), minSize: new go.Size(NaN, 1), wrap: go.TextBlock.WrapFit, textAlign: 'center', editable: true, font: 'bold 12px Helvetica, Arial, sans-serif', stroke: '#454545', }, new go.Binding('text').makeTwoWay(), new go.Binding('font', 'fontStyle'), new go.Binding('stroke', 'fontStroke').makeTwoWay(), new go.Binding('textAlign', 'fontAlign'), new go.Binding('maxSize', 'textSize'), new go.Binding('minSize', 'textSize'), ), { // define a tooltip for each node that displays the color as text toolTip: goJS( 'ToolTip', goJS( go.TextBlock, { margin: 2 }, new go.Binding('text', 'timeStr'), new go.Binding('visible', 'toolTip'), ), new go.Binding('visible', 'toolTip'), ), }, ), ); // 公用管定义 myDiagram.nodeTemplateMap.add( 'HBar', goJS( go.Node, 'Auto', nodeStyle(), 'Spot', { locationSpot: go.Spot.Center, zOrder: 1 }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding('angle').makeTwoWay(), { // 设置其可选择 selectable: false, layerName: 'Background', }, roleVisibleBinding(), // 绑定角色可见 goJS( go.Shape, 'Rectangle', { name: 'SHAPE', height: 0, width: 120, fill: '#41BFEC', stroke: null, strokeWidth: 0, minSize: new go.Size(20, 0), maxSize: new go.Size(Infinity, 0), }, new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify), new go.Binding('minSize', 'minSize').makeTwoWay(), new go.Binding('maxSize', 'maxSize').makeTwoWay(), new go.Binding('stroke', 'stroke').makeTwoWay(), new go.Binding('strokeWidth', 'strokeWidth').makeTwoWay(), ), goJS( go.Shape, { isPanelMain: true, stroke: 'white', strokeWidth: 3, height: 0, width: 100, name: 'PIPE', strokeDashArray: [20, 40], }, new go.Binding('width').makeTwoWay(), new go.Binding('stroke', 'waterStroke').makeTwoWay(), new go.Binding('strokeWidth', 'waterWidth').makeTwoWay(), new go.Binding('strokeDashArray', 'strokeDashArray').makeTwoWay(), { portId: '', toLinkable: true, fromLinkable: true, }, ), ), ); // 值定义 myDiagram.nodeTemplateMap.add( 'valCase', goJS( go.Node, 'Auto', nodeStyle(), 'Spot', { locationSpot: go.Spot.Center, zOrder: 2, cursor: 'default' }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('cursor', 'cursor').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding('angle').makeTwoWay(), roleVisibleBinding(), // 绑定角色可见 goJS( go.Panel, 'Horizontal', goJS( go.Panel, 'Auto', goJS( go.Shape, 'RoundedRectanglePlus', { name: 'SHAPE', strokeWidth: 10, stroke: '#000000', parameter1: 0 }, new go.Binding('fill', 'fillColor'), new go.Binding('stroke'), new go.Binding('strokeWidth'), new go.Binding('parameter1', 'radius').makeTwoWay(), new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify), ), goJS( go.TextBlock, textStyle(), { maxSize: new go.Size(NaN, NaN), minSize: new go.Size(NaN, 1), wrap: go.TextBlock.WrapFit, textAlign: 'center', editable: true, font: 'bold 12px Helvetica, Arial, sans-serif', stroke: '#454545', flip: go.GraphObject.None, }, new go.Binding('text', 'showVal'), new go.Binding('font', 'fontStyle'), new go.Binding('stroke', 'fontStroke'), new go.Binding('textAlign', 'fontAlign'), new go.Binding('maxSize', 'textSize'), new go.Binding('minSize', 'textSize'), new go.Binding('flip', 'flip'), ), ), goJS( go.TextBlock, textStyle(), { wrap: go.TextBlock.WrapFit, textAlign: 'center', editable: false, font: 'normal 10px Helvetica,Arial,sans-serif', stroke: '#ffffff', }, new go.Binding('text', 'unitText'), new go.Binding('font', '', (v) => { return `normal ${v?.unitSize || 10}pt ${ v?.unitStyle || 'Helvetica,Arial,sans-serif' }`; }), new go.Binding('stroke', 'unitColor'), new go.Binding('visible', '', (v) => { return (v?.unitSwitch && !!v?.unitText) || false; }), new go.Binding('margin', '', (v) => { const unitGap = v?.unitGap || '0,0,0,5'; if (unitGap && isNumber(unitGap)) return unitGap; const margin = unitGap?.split(',') || null; return margin ? new go.Margin( margin?.[0] * 1 || 0, margin?.[1] * 1 || 0, margin?.[2] * 1 || 0, margin?.[3] * 1 || 0, ) : 0; }), ), ), { click(e, node) { const { data } = node; const list = bindData.find((item) => { return item.name === data.stationName; }); if (!list) return false; // 历史查看 if (data.opType && data.shName) historyModalRender(data, list); }, }, ), ); // 连接点定义 myDiagram.nodeTemplateMap.add( 'linkPort', goJS( go.Node, 'Auto', nodeStyle(), 'Spot', { locationSpot: go.Spot.Center, zOrder: 1 }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding('angle').makeTwoWay(), roleVisibleBinding(), // 绑定角色 goJS( go.Panel, 'Auto', { name: 'PANEL', }, goJS(go.Shape, 'Rectangle', { fill: 'transparent', strokeWidth: 0, width: 8, height: 8, minSize: new go.Size(5, 5), }), ), ), ); // 水池动效 go.Shape.defineFigureGenerator('Pool', (shape, w, h) => { const geo = new go.Geometry(); const fig = new go.PathFigure(0, 0, true); // starting point geo.add(fig); fig.add(new go.PathSegment(go.PathSegment.Line, 0.75 * w, 0)); fig.add(new go.PathSegment(go.PathSegment.Line, w, 0.25 * h)); fig.add(new go.PathSegment(go.PathSegment.Line, w, h)); fig.add(new go.PathSegment(go.PathSegment.Line, 0, h).close()); return geo; }); // 定义水池 myDiagram.nodeTemplateMap.add( 'waterCase', goJS( go.Node, 'Auto', nodeStyle(), 'Spot', { locationSpot: go.Spot.Center, zOrder: 1 }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding('angle').makeTwoWay(), roleVisibleBinding(), // 绑定角色可见 goJS( go.Shape, 'Rectangle', { name: 'SHAPE', alignment: go.Spot.Bottom, alignmentFocus: go.Spot.Bottom, fill: 'transparent', strokeWidth: 10, stroke: 'red', desiredSize: new go.Size(NaN, 26), }, new go.Binding('width').makeTwoWay(), new go.Binding('height').makeTwoWay(), new go.Binding('stroke', 'stroke').makeTwoWay(), new go.Binding('strokeWidth', 'strokeWidth').makeTwoWay(), ), goJS( go.Shape, 'Rectangle', { name: 'SHAPE', alignment: go.Spot.Bottom, alignmentFocus: go.Spot.Bottom, fill: '#ccc', strokeWidth: 10, stroke: 'transparent', desiredSize: new go.Size(NaN, 26), }, new go.Binding('width').makeTwoWay(), new go.Binding('height').makeTwoWay(), new go.Binding('fill', 'waterColor').makeTwoWay(), new go.Binding('strokeWidth', 'strokeWidth').makeTwoWay(), ), goJS( go.Shape, 'Pool', { name: 'waterSvg', alignment: go.Spot.Bottom, alignmentFocus: go.Spot.Bottom, fill: '#DEE0A3', stroke: 'transparent', strokeWidth: 10, minSize: new go.Size(NaN, 5), desiredSize: new go.Size(NaN, 20), }, new go.Binding('width').makeTwoWay(), new go.Binding('height', 'waterHight').makeTwoWay(), new go.Binding('fill', 'fillColor').makeTwoWay(), new go.Binding('strokeWidth', 'strokeWidth').makeTwoWay(), ), ), ); // 定义进度条 myDiagram.nodeTemplateMap.add( 'speedCase', goJS( go.Node, 'Auto', nodeStyle(), 'Spot', { locationSpot: go.Spot.Center, zOrder: 1 }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding('angle').makeTwoWay(), roleVisibleBinding(), // 绑定角色可见 goJS( go.Shape, 'RoundedRectanglePlus', { name: 'SHAPE', alignment: go.Spot.Left, alignmentFocus: go.Spot.Left, strokeWidth: 2, stroke: '#FFFFFF', desiredSize: new go.Size(NaN, 26), fill: 'transparent', parameter1: 5, }, new go.Binding('width').makeTwoWay(), new go.Binding('height').makeTwoWay(), new go.Binding('strokeWidth', 'strokeWidth').makeTwoWay(), new go.Binding('parameter1', 'radius').makeTwoWay(), new go.Binding('stroke', 'stroke').makeTwoWay(), ), goJS( go.Shape, 'RoundedRectanglePlus', { name: 'SHAPE', alignment: go.Spot.Left, alignmentFocus: go.Spot.Left, fill: '#CCCCCC', strokeWidth: 2, stroke: 'transparent', desiredSize: new go.Size(NaN, 26), parameter1: 5, }, new go.Binding('width').makeTwoWay(), new go.Binding('height').makeTwoWay(), new go.Binding('fill', 'waterColor').makeTwoWay(), new go.Binding('parameter1', 'radius').makeTwoWay(), new go.Binding('strokeWidth', 'strokeWidth').makeTwoWay(), ), goJS( go.Shape, 'RoundedRectanglePlus', { name: 'speedSvg', alignment: go.Spot.Left, alignmentFocus: go.Spot.Left, fill: '#DEE0A3', stroke: 'transparent', strokeWidth: 2, minSize: new go.Size(NaN, 5), desiredSize: new go.Size(NaN, 20), parameter1: 5, }, new go.Binding('width', 'lineWidth').makeTwoWay(), new go.Binding('height', 'height').makeTwoWay(), new go.Binding('parameter1', 'radius').makeTwoWay(), new go.Binding('fill', 'fillColor').makeTwoWay(), new go.Binding('strokeWidth', 'strokeWidth'), ), ), ); // 泵状态设置 myDiagram.nodeTemplateMap.add( 'rotateCase', goJS( go.Node, 'Table', nodeStyle(), 'Spot', { locationSpot: go.Spot.Center, zOrder: 2 }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), { // 设置其可改变大小 resizeObjectName: 'SHAPE', rotatable: true, }, roleVisibleBinding(), // 绑定角色可见 goJS( go.Panel, 'Table', { name: 'PANEL', }, goJS( go.Shape, 'Ellipse', // 定义形状 { width: 37, height: 37, fill: 'transparent', stroke: 'transparent', strokeWidth: 1 }, new go.Binding('width', 'widthBox').makeTwoWay(), new go.Binding('height', 'heightBox').makeTwoWay(), ), new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify), goJS( go.Picture, { name: 'rotateSvg', width: 26, height: 26, column: 0, scale: 1, source: require('./images/组态/状态/泵离线.svg'), angle: 0, }, new go.Binding('source', 'imgSrc', (v) => { return require(`./images/组态/状态/${v.split('/').pop()}`); }).makeTwoWay(), new go.Binding('scale', 'scale').makeTwoWay(), new go.Binding('width', 'width').makeTwoWay(), new go.Binding('angle', 'angle').makeTwoWay(), new go.Binding('height', 'height').makeTwoWay(), ), ), ), ); // 点状态设置 myDiagram.nodeTemplateMap.add( 'pointCase', goJS( go.Node, 'Auto', nodeStyle(), 'Spot', { locationSpot: go.Spot.Center, zOrder: 2 }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding('angle').makeTwoWay(), roleVisibleBinding(), // 绑定角色可见 goJS( go.Shape, 'Ellipse', { width: 14, height: 14, name: 'SHAPE', fill: 'rgba(109, 122, 151, 1)', stroke: '#ffffff', }, new go.Binding('fill', 'fillColor').makeTwoWay(), new go.Binding('stroke').makeTwoWay(), new go.Binding('strokeWidth').makeTwoWay(), new go.Binding('height', 'height').makeTwoWay(), new go.Binding('width', 'height').makeTwoWay(), ), ), ); // 开关开设置 myDiagram.nodeTemplateMap.add( 'switchCase', goJS( go.Node, 'Auto', nodeStyle(), 'Spot', { locationSpot: go.Spot.Center, zOrder: 2, cursor: 'default' }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('cursor', 'cursor').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), new go.Binding('angle').makeTwoWay(), roleVisibleBinding(), // 绑定角色可见 goJS( go.Shape, 'RoundedRectanglePlus', { name: 'SHAPE', strokeWidth: 10, stroke: '#000000', parameter1: 5 }, new go.Binding('fill', 'fillColor'), new go.Binding('stroke'), new go.Binding('strokeWidth'), new go.Binding('parameter1', 'radius').makeTwoWay(), new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify), ), goJS( go.TextBlock, textStyle(), { maxSize: new go.Size(NaN, NaN), minSize: new go.Size(NaN, 1), wrap: go.TextBlock.WrapFit, textAlign: 'center', editable: true, font: 'bold 12px Helvetica, Arial, sans-serif', stroke: '#454545', }, new go.Binding('text'), new go.Binding('font', 'fontStyle'), new go.Binding('stroke', 'fontStroke'), new go.Binding('textAlign', 'fontAlign'), new go.Binding('maxSize', 'textSize'), new go.Binding('minSize', 'textSize'), ), { click(e, node) { const { data } = node; }, }, ), ); // 搅拌机状态设置 myDiagram.nodeTemplateMap.add( 'blenderCase', goJS( go.Node, 'Table', nodeStyle(), 'Spot', { locationSpot: go.Spot.Center, zOrder: 2 }, new go.Binding('zOrder', 'zOrder').makeTwoWay(), new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify), { // 设置其可改变大小 resizeObjectName: 'SHAPE', rotatable: true, }, new go.Binding('angle').makeTwoWay(), roleVisibleBinding(), // 绑定角色可见 goJS( go.Panel, 'Auto', { name: 'PANEL', }, new go.Binding('desiredSize', 'size', go.Size.parse).makeTwoWay(go.Size.stringify), goJS( go.Picture, { name: 'blenderSvg', width: 42.5, height: 56, column: 0, scale: 1, source: require('./images/组态/状态/搅拌机双头1.svg'), angle: 0, }, new go.Binding('source', 'imgSrc', (v) => { return require(`./images/组态/状态/${v.split('/').pop()}`); }).makeTwoWay(), new go.Binding('scale', 'scale').makeTwoWay(), new go.Binding('width', 'width').makeTwoWay(), new go.Binding('angle', 'angle').makeTwoWay(), new go.Binding('height', 'height').makeTwoWay(), ), ), ), ); // 连接线装饰模板 const linkSelectionAdornmentTemplate = goJS( go.Adornment, 'Link', goJS(go.Shape, { isPanelMain: true, fill: null, stroke: 'deepskyblue', strokeWidth: 0, }), ); /** *******************************单管连接方式****************************** */ myDiagram.linkTemplate = goJS( BarLink, { curve: go.Link.JumpOver, toShortLength: 0, fromShortLength: 0, layerName: 'Background', routing: go.Link.Orthogonal, // 不同的位置进行不同的routing corner: 2, reshapable: true, resegmentable: true, relinkableFrom: true, relinkableTo: true, zOrder: 1, }, new go.Binding('layerName', 'layerName').makeTwoWay(), new go.Binding('fromSpot', 'fromPort', (d) => { return spotConverter(d); }), new go.Binding('toSpot', 'toPort', (d) => { return spotConverter(d); }), new go.Binding('points').makeTwoWay(), roleVisibleBinding(), // 绑定角色可见 goJS( go.Shape, { isPanelMain: true, stroke: '#41BFEC' /* blue */, strokeWidth: 6, name: 'changecolor' }, new go.Binding('stroke', 'stroke'), new go.Binding('strokeWidth', 'strokeWidth'), ), goJS( go.Shape, { isPanelMain: true, stroke: 'white', strokeWidth: 3, name: 'PIPE', strokeDashArray: [20, 40], }, new go.Binding('strokeWidth', 'waterWidth'), new go.Binding('stroke', 'waterStroke'), ), ); /** *******************************sharpLine线条****************************** */ myDiagram.linkTemplateMap.add( 'sharpLine', goJS( BarLink, { curve: go.Link.JumpOver, resegmentable: true, adjusting: go.Link.Stretch, routing: go.Link.Normal, layerName: 'Background', routing: go.Link.Normal, //不同的位置进行不同的routing corner: 0, reshapable: true, resegmentable: true, relinkableFrom: true, relinkableTo: true, relinkableFrom: true, relinkableTo: true, zOrder: 1, }, new go.Binding('layerName', 'layerName').makeTwoWay(), new go.Binding('fromSpot', 'fromPort', function (d) { return spotConverter(d); }), new go.Binding('toSpot', 'toPort', function (d) { return spotConverter(d); }), new go.Binding('points').makeTwoWay(), roleVisibleBinding(), // 绑定角色可见 // mark each Shape to get the link geometry with isPanelMain: true goJS( go.Shape, { isPanelMain: true, stroke: '#41BFEC' /* blue*/, strokeWidth: 6, name: 'changecolor', }, new go.Binding('stroke', 'stroke'), new go.Binding('strokeWidth', 'strokeWidth'), ), goJS( go.Shape, { isPanelMain: true, stroke: 'white', strokeWidth: 3, name: 'PIPE', strokeDashArray: [20, 40], }, new go.Binding('strokeWidth', 'waterWidth'), new go.Binding('stroke', 'waterStroke'), ), ), ); /** **************************************合管连接方式****************************************** */ // myDiagram.linkTemplateMap.add( // 'linkToLink', // goJS( // 'Link', // { relinkableFrom: true, relinkableTo: true }, // goJS('Shape', { // stroke: '#2D9945', // strokeWidth: 2, // }), // ), // ); const fromJson = JSON.parse(jsonStr); myTimeout(() => { loop(); waterSvg(); rotateSvg(); blenderSvg(); animationSvg(); }, 100); const json = JSON.parse(JSON.stringify(fromJson)); json.linkDataArray.forEach((item) => { item.isHavingDash = flowShow; item.realVal = '--'; item.defaultWidth = item.waterWidth; }); json.nodeDataArray.forEach((item) => { item.showVal = '--'; item.realVal = '--'; item.realType = '离线'; item.Unit = ''; item.switchState = '开'; item.dtImgSrc = item.imgSrc || ''; if (item.category === 'HBar') { item.hBarClolor = item.waterStroke; item.typeDash = false; } if (item.category === 'valCase') { if (item.shType === '') item.showVal = item.text; } if (item.category === 'nameCase') { item.dtFillColor = item.fillColor; item.dtStroke = item.stroke; item.dtFontStroke = item.fontStroke; item.dtText = item.text; } if (item.category === 'modelCase' || item.category === 'ellipseCase') { item.dtzOrder = item.zOrder; } if (item.category == 'deviceCase' && item.shType && deviceName && deviceName.length) { var device = deviceName.find(function (arr, index) { return '设备' + stationList[index] == item.stationName; }); if (device) item.text = device; } // 兼容V1之前版本(部分展示可支持) if (chartInfo.version === 'V1') return false; item.shName = item.showName || ''; item.hbControl = item.authoControl || '否'; if (item.controlType === '开关展示') item.switch = '是'; if (item.category === 'valCase') item.shType = '值显示'; }); // 监听画布变化 myDiagram.addDiagramListener('ViewportBoundsChanged', viewportBoundsChang); myDiagram.model = go.Model.fromJson(json); }; return ( <div className={classNames(prefixCls)} ref={ConfigurationRef}> <div id={twoID} className={classNames('configurationView')}> <LoadBox spinning={spinning} /> {isEmpty && <Empty theme={'dark'} description={description} />} </div> {spinLoad && ( <div className={classNames('configurationLoad')}> <LoadBox spinning={spinLoad} /> </div> )} {/* 历史曲线 */} {isHIModalVisible && ( <Modal centered width={1200} footer={null} open={isHIModalVisible} onOk={() => setIsHIModalVisible(false)} onCancel={() => setIsHIModalVisible(false)} getContainer={ConfigurationRef.current} wrapClassName={classNames(`${prefixCls}-historyInfoModal`)} > <HistoryView deviceParams={historyInfoParams} /> </Modal> )} </div> ); }; ConfigurationView.defaultProps = { name: '', devices: [], deviceName: [], config: {}, isZoom: false, flowShow: true, customBack: () => {}, speed: 0, play: false, times: 2, callback: (speed, total, play, time) => {}, params: {}, statisticType: [], }; ConfigurationView.propTypes = { name: PropTypes.string, devices: PropTypes.array, deviceName: PropTypes.array, config: PropTypes.object, isZoom: PropTypes.bool, flowShow: PropTypes.bool, customBack: PropTypes.func, speed: PropTypes.number, play: PropTypes.bool, times: PropTypes.number, callback: PropTypes.func, params: PropTypes.object, statisticType: PropTypes.array, }; export default ConfigurationView;