Commit 01bb7bfae33c4cd24f78c4bd916d4cef84a4fdb3

Authored by xp.Huang
2 parents 30353c89 1951f17a

Merge branch 'ww' into 'main'

feat: hidden file menu && hidden share button && add preview button && del test components

See merge request huang/thingskit-drawio!12

Too many changes to show.

To preserve performance only 10 of 14 files are displayed.

@@ -16,6 +16,9 @@ @@ -16,6 +16,9 @@
16 <meta name="msapplication-config" content="images/browserconfig.xml"> 16 <meta name="msapplication-config" content="images/browserconfig.xml">
17 <meta name="mobile-web-app-capable" content="yes"> 17 <meta name="mobile-web-app-capable" content="yes">
18 <meta name="theme-color" content="#d89000"> 18 <meta name="theme-color" content="#d89000">
  19 + <!-- 全局变量 -->
  20 + <script src="./js/const/const.js"></script>
  21 +
19 <script src="./plugins/axios.min.js"></script> 22 <script src="./plugins/axios.min.js"></script>
20 <!-- <script src="./js/jquery/jquery-3.3.1.min.js"></script>--> 23 <!-- <script src="./js/jquery/jquery-3.3.1.min.js"></script>-->
21 <!-- <script src="./js/jquery.easyui.min.js"></script>--> 24 <!-- <script src="./js/jquery.easyui.min.js"></script>-->
@@ -32,11 +35,14 @@ @@ -32,11 +35,14 @@
32 <!-- <script type="text/javascript" src="./js/jquery.ztree.exhide.min.js"></script>--> 35 <!-- <script type="text/javascript" src="./js/jquery.ztree.exhide.min.js"></script>-->
33 <!-- <script type="text/javascript" src="./js/jquery.select.zTree.v1.5.min.js"></script>--> 36 <!-- <script type="text/javascript" src="./js/jquery.select.zTree.v1.5.min.js"></script>-->
34 37
35 -<!-- Axios --> 38 + <!-- Axios -->
36 <script src="./plugins/defHttp.js"></script> 39 <script src="./plugins/defHttp.js"></script>
37 40
38 <script src="./js/api/index.js"></script> 41 <script src="./js/api/index.js"></script>
39 42
  43 + <!-- act editor -->
  44 + <script src="./js/plugin/ace/ace.js"></script>
  45 +
40 <script type="text/javascript"> 46 <script type="text/javascript">
41 /** 47 /**
42 * URL Parameters and protocol description are here: 48 * URL Parameters and protocol description are here:
@@ -5,7 +5,7 @@ class ConfigurationNodeApi { @@ -5,7 +5,7 @@ class ConfigurationNodeApi {
5 * @param {string} levelId - 组态资源ID 5 * @param {string} levelId - 组态资源ID
6 */ 6 */
7 static getConfigurationInfo(levelType, levelId) { 7 static getConfigurationInfo(levelType, levelId) {
8 - return defHttp.get(`/yt/configuration/node/${levelType}/${levelId}`) 8 + return defHttp.get(`/yt/configuration/node/${ levelType }/${ levelId }`)
9 } 9 }
10 10
11 /** 11 /**
@@ -22,7 +22,7 @@ class ConfigurationNodeApi { @@ -22,7 +22,7 @@ class ConfigurationNodeApi {
22 * @returns {Promise<*>} 22 * @returns {Promise<*>}
23 */ 23 */
24 static getDeviceAttr(tbDeviceId) { 24 static getDeviceAttr(tbDeviceId) {
25 - return defHttp.get(`/plugins/telemetry/DEVICE/${tbDeviceId}/keys/timeseries`) 25 + return defHttp.get(`/plugins/telemetry/DEVICE/${ tbDeviceId }/keys/timeseries`)
26 } 26 }
27 27
28 /** 28 /**
@@ -32,7 +32,7 @@ class ConfigurationNodeApi { @@ -32,7 +32,7 @@ class ConfigurationNodeApi {
32 * @returns {Promise<*>} 32 * @returns {Promise<*>}
33 */ 33 */
34 static getDeviceUnderTheOrg(deviceType, orgId) { 34 static getDeviceUnderTheOrg(deviceType, orgId) {
35 - return defHttp.get(`/yt/device/list/${deviceType}?organizationId=${orgId}`) 35 + return defHttp.get(`/yt/device/list/${ deviceType }?organizationId=${ orgId }`)
36 } 36 }
37 37
38 /** 38 /**
@@ -41,7 +41,7 @@ class ConfigurationNodeApi { @@ -41,7 +41,7 @@ class ConfigurationNodeApi {
41 * @returns {Promise<*>} 41 * @returns {Promise<*>}
42 */ 42 */
43 static getDeviceChildDevice(deviceId) { 43 static getDeviceChildDevice(deviceId) {
44 - return defHttp.get(`/yt/device/relation?page=1&pageSize=10&fromId=${deviceId}`) 44 + return defHttp.get(`/yt/device/relation?page=1&pageSize=10&fromId=${ deviceId }`)
45 } 45 }
46 46
47 /** 47 /**
@@ -50,7 +50,7 @@ class ConfigurationNodeApi { @@ -50,7 +50,7 @@ class ConfigurationNodeApi {
50 * @returns {Promise<*>} 50 * @returns {Promise<*>}
51 */ 51 */
52 static getMasterDevice(orgId) { 52 static getMasterDevice(orgId) {
53 - return defHttp.get(`/yt/device/list/master/${orgId}`) 53 + return defHttp.get(`/yt/device/list/master/${ orgId }`)
54 } 54 }
55 55
56 /** 56 /**
@@ -60,7 +60,7 @@ class ConfigurationNodeApi { @@ -60,7 +60,7 @@ class ConfigurationNodeApi {
60 * @returns {Promise<*>} 60 * @returns {Promise<*>}
61 */ 61 */
62 static getSlaveDevice(orgId, masterDeviceId) { 62 static getSlaveDevice(orgId, masterDeviceId) {
63 - return defHttp.get(`/yt/device/list/slave/${orgId}?masterId=${masterDeviceId}`) 63 + return defHttp.get(`/yt/device/list/slave/${ orgId }?masterId=${ masterDeviceId }`)
64 } 64 }
65 65
66 /** 66 /**
@@ -72,8 +72,8 @@ class ConfigurationNodeApi { @@ -72,8 +72,8 @@ class ConfigurationNodeApi {
72 72
73 /** 73 /**
74 * @description 编辑动画效果 74 * @description 编辑动画效果
75 - * @param {*} data  
76 - * @returns 75 + * @param {*} data
  76 + * @returns
77 */ 77 */
78 static updateNodeAct(data) { 78 static updateNodeAct(data) {
79 return defHttp.post('/yt/configuration/node/act', data) 79 return defHttp.post('/yt/configuration/node/act', data)
@@ -81,13 +81,49 @@ class ConfigurationNodeApi { @@ -81,13 +81,49 @@ class ConfigurationNodeApi {
81 81
82 /** 82 /**
83 * @description 更新节点绑定信息 83 * @description 更新节点绑定信息
84 - * @param {*} data  
85 - * @returns 84 + * @param {*} data
  85 + * @returns
86 */ 86 */
87 static updateNodeInfo(data) { 87 static updateNodeInfo(data) {
88 return defHttp.post('/yt/configuration/node', data) 88 return defHttp.post('/yt/configuration/node', data)
89 } 89 }
90 90
  91 + /**
  92 + * @description 下发指令 单向
  93 + * @param {string} deviceId - tbDeviceId
  94 + * @param {object} data - 数据
  95 + */
  96 + static sendInstructionOneWay(deviceId, data) {
  97 + return defHttp.post(`/rpc/oneway/${ deviceId }`, data)
  98 + }
  99 +
  100 + /**
  101 + * @description 下发指令 单向
  102 + * @param {string} deviceId - tbDeviceId
  103 + * @param {object} data - 数据
  104 + */
  105 + static sendInstructionTwoWay(deviceId, data) {
  106 + return defHttp.post(`/rpc/twoway/${ deviceId }`, data)
  107 + }
  108 +
  109 + /**
  110 + * @description 下发指令
  111 + * @param {'oneway' | 'twoway'} way
  112 + * @param deviceId
  113 + * @param data
  114 + * @return {*}
  115 + */
  116 + static sendInstruction(way,deviceId, data) {
  117 + return defHttp.post(`/rpc/${way}/${ deviceId }`, data)
  118 + }
  119 +
  120 + /**
  121 + * @description 判断设备是否在线
  122 + * @param deviceId
  123 + * @return {*}
  124 + */
  125 + static deviceIsOnLine(deviceId){
  126 + return defHttp.get(`/plugins/telemetry/DEVICE/${deviceId}/values/attributes?keys=active`)
  127 + }
91 128
92 -  
93 } 129 }
  1 +const GLOBAL_TOKEN = JSON.parse(localStorage.getItem("UNDEFINED__DEVELOPMENT__2.7.1__COMMON__LOCAL__KEY__")).value.JWT_TOKEN.value
  2 +
  3 +const GLOBAL_WS_URL = (() => {
  4 + const { host, href } = location
  5 + const reg = /^https/
  6 + return `${ reg.test(href) ? 'wss' : 'ws' }://${ host }/api/ws/plugins/telemetry?token=${GLOBAL_TOKEN}`
  7 +})()
  8 +
  9 +// const GLOBAL_WS_URL = `ws://47.99.141.212:8080/api/ws/plugins/telemetry?token=${ GLOBAL_TOKEN }`
@@ -5839,41 +5839,62 @@ App.prototype.updateButtonContainer = function() @@ -5839,41 +5839,62 @@ App.prototype.updateButtonContainer = function()
5839 { 5839 {
5840 if (this.shareButton == null) 5840 if (this.shareButton == null)
5841 { 5841 {
  5842 + // TODO 预览模式按钮
5842 this.shareButton = document.createElement('div'); 5843 this.shareButton = document.createElement('div');
5843 this.shareButton.className = 'geBtn gePrimaryBtn'; 5844 this.shareButton.className = 'geBtn gePrimaryBtn';
5844 this.shareButton.style.display = 'inline-block'; 5845 this.shareButton.style.display = 'inline-block';
5845 this.shareButton.style.backgroundColor = '#F2931E'; 5846 this.shareButton.style.backgroundColor = '#F2931E';
5846 this.shareButton.style.borderColor = '#F08705'; 5847 this.shareButton.style.borderColor = '#F08705';
5847 this.shareButton.style.backgroundImage = 'none'; 5848 this.shareButton.style.backgroundImage = 'none';
5848 - this.shareButton.style.padding = '2px 10px 0 10px';  
5849 this.shareButton.style.marginTop = '-10px'; 5849 this.shareButton.style.marginTop = '-10px';
5850 - this.shareButton.style.height = '28px';  
5851 this.shareButton.style.lineHeight = '28px'; 5850 this.shareButton.style.lineHeight = '28px';
5852 this.shareButton.style.minWidth = '0px'; 5851 this.shareButton.style.minWidth = '0px';
5853 this.shareButton.style.cssFloat = 'right'; 5852 this.shareButton.style.cssFloat = 'right';
5854 - this.shareButton.setAttribute('title', mxResources.get('share'));  
5855 -  
5856 - var icon = document.createElement('img');  
5857 - icon.setAttribute('src', this.shareImage);  
5858 - icon.setAttribute('align', 'absmiddle');  
5859 - icon.style.marginRight = '4px';  
5860 - icon.style.marginTop = '-3px';  
5861 - this.shareButton.appendChild(icon);  
5862 -  
5863 - if (!Editor.isDarkMode() && uiTheme != 'atlas')  
5864 - {  
5865 - this.shareButton.style.color = 'black';  
5866 - icon.style.filter = 'invert(100%)';  
5867 - }  
5868 -  
5869 - mxUtils.write(this.shareButton, mxResources.get('share'));  
5870 - 5853 + this.shareButton.setAttribute('title', '预览');
  5854 + mxUtils.write(this.shareButton, '预览');
5871 mxEvent.addListener(this.shareButton, 'click', mxUtils.bind(this, function() 5855 mxEvent.addListener(this.shareButton, 'click', mxUtils.bind(this, function()
5872 { 5856 {
5873 - this.actions.get('share').funct(); 5857 + const href = window.location.href + '&lightbox=1'
  5858 + window.open(href)
5874 })); 5859 }));
5875 -  
5876 this.buttonContainer.appendChild(this.shareButton); 5860 this.buttonContainer.appendChild(this.shareButton);
  5861 +
  5862 +
  5863 + // this.shareButton = document.createElement('div');
  5864 + // this.shareButton.className = 'geBtn gePrimaryBtn';
  5865 + // this.shareButton.style.display = 'inline-block';
  5866 + // this.shareButton.style.backgroundColor = '#F2931E';
  5867 + // this.shareButton.style.borderColor = '#F08705';
  5868 + // this.shareButton.style.backgroundImage = 'none';
  5869 + // this.shareButton.style.padding = '2px 10px 0 10px';
  5870 + // this.shareButton.style.marginTop = '-10px';
  5871 + // this.shareButton.style.height = '28px';
  5872 + // this.shareButton.style.lineHeight = '28px';
  5873 + // this.shareButton.style.minWidth = '0px';
  5874 + // this.shareButton.style.cssFloat = 'right';
  5875 + // this.shareButton.setAttribute('title', mxResources.get('share'));
  5876 + //
  5877 + // var icon = document.createElement('img');
  5878 + // icon.setAttribute('src', this.shareImage);
  5879 + // icon.setAttribute('align', 'absmiddle');
  5880 + // icon.style.marginRight = '4px';
  5881 + // icon.style.marginTop = '-3px';
  5882 + // this.shareButton.appendChild(icon);
  5883 + //
  5884 + // if (!Editor.isDarkMode() && uiTheme != 'atlas')
  5885 + // {
  5886 + // this.shareButton.style.color = 'black';
  5887 + // icon.style.filter = 'invert(100%)';
  5888 + // }
  5889 + //
  5890 + // mxUtils.write(this.shareButton, mxResources.get('share'));
  5891 + //
  5892 + // mxEvent.addListener(this.shareButton, 'click', mxUtils.bind(this, function()
  5893 + // {
  5894 + // this.actions.get('share').funct();
  5895 + // }));
  5896 + //
  5897 + // this.buttonContainer.appendChild(this.shareButton);
5877 } 5898 }
5878 } 5899 }
5879 else if (this.shareButton != null) 5900 else if (this.shareButton != null)
@@ -315,4 +315,6 @@ mxscript(drawDevUrl + 'js/diagramly/sidebar/thingskit/Sidebar-Engine.js'); @@ -315,4 +315,6 @@ mxscript(drawDevUrl + 'js/diagramly/sidebar/thingskit/Sidebar-Engine.js');
315 mxscript(drawDevUrl + 'js/diagramly/sidebar/thingskit/Sidebar-Basic-Components.js'); 315 mxscript(drawDevUrl + 'js/diagramly/sidebar/thingskit/Sidebar-Basic-Components.js');
316 mxscript(drawDevUrl + 'js/diagramly/sidebar/thingskit/Sidebar-Controller-Components.js'); 316 mxscript(drawDevUrl + 'js/diagramly/sidebar/thingskit/Sidebar-Controller-Components.js');
317 mxscript(drawDevUrl + 'js/diagramly/sidebar/thingskit/Sidebar-Valve.js'); 317 mxscript(drawDevUrl + 'js/diagramly/sidebar/thingskit/Sidebar-Valve.js');
318 -mxscript(drawDevUrl + 'js/diagramly/sidebar/thingskit/Sidebar-Fan.js');  
  318 +mxscript(drawDevUrl + 'js/diagramly/sidebar/thingskit/Sidebar-Fan.js');
  319 +
  320 +
@@ -1203,46 +1203,47 @@ @@ -1203,46 +1203,47 @@
1203 // in older browsers. URL param has precedence over the saved setting. 1203 // in older browsers. URL param has precedence over the saved setting.
1204 if (mxClient.IS_CHROMEAPP || isLocalStorage) 1204 if (mxClient.IS_CHROMEAPP || isLocalStorage)
1205 { 1205 {
1206 - this.put('language', new Menu(mxUtils.bind(this, function(menu, parent)  
1207 - {  
1208 - var addLangItem = mxUtils.bind(this, function (id)  
1209 - {  
1210 - var lang = (id == '') ? mxResources.get('automatic') : mxLanguageMap[id];  
1211 - var item = null;  
1212 -  
1213 - if (lang != '')  
1214 - {  
1215 - item = menu.addItem(lang, null, mxUtils.bind(this, function()  
1216 - {  
1217 - mxSettings.setLanguage(id);  
1218 - mxSettings.save();  
1219 -  
1220 - // Shows dialog in new language  
1221 - mxClient.language = id;  
1222 - mxResources.loadDefaultBundle = false;  
1223 - mxResources.add(RESOURCE_BASE);  
1224 -  
1225 - editorUi.alert(mxResources.get('restartForChangeRequired'));  
1226 - }), parent);  
1227 -  
1228 - if (id == mxLanguage || (id == '' && mxLanguage == null))  
1229 - {  
1230 - menu.addCheckmark(item, Editor.checkmarkImage);  
1231 - }  
1232 - }  
1233 -  
1234 - return item;  
1235 - });  
1236 -  
1237 - var item = addLangItem('');  
1238 - menu.addSeparator(parent);  
1239 -  
1240 - // LATER: Sort menu by language name  
1241 - for(var langId in mxLanguageMap)  
1242 - {  
1243 - addLangItem(langId);  
1244 - }  
1245 - }))); 1206 + // TODO switch language 切换语言按钮 多语言切换
  1207 + // this.put('language', new Menu(mxUtils.bind(this, function(menu, parent)
  1208 + // {
  1209 + // var addLangItem = mxUtils.bind(this, function (id)
  1210 + // {
  1211 + // var lang = (id == '') ? mxResources.get('automatic') : mxLanguageMap[id];
  1212 + // var item = null;
  1213 + //
  1214 + // if (lang != '')
  1215 + // {
  1216 + // item = menu.addItem(lang, null, mxUtils.bind(this, function()
  1217 + // {
  1218 + // mxSettings.setLanguage(id);
  1219 + // mxSettings.save();
  1220 + //
  1221 + // // Shows dialog in new language
  1222 + // mxClient.language = id;
  1223 + // mxResources.loadDefaultBundle = false;
  1224 + // mxResources.add(RESOURCE_BASE);
  1225 + //
  1226 + // editorUi.alert(mxResources.get('restartForChangeRequired'));
  1227 + // }), parent);
  1228 + //
  1229 + // if (id == mxLanguage || (id == '' && mxLanguage == null))
  1230 + // {
  1231 + // menu.addCheckmark(item, Editor.checkmarkImage);
  1232 + // }
  1233 + // }
  1234 + //
  1235 + // return item;
  1236 + // });
  1237 + //
  1238 + // var item = addLangItem('');
  1239 + // menu.addSeparator(parent);
  1240 + //
  1241 + // // LATER: Sort menu by language name
  1242 + // for(var langId in mxLanguageMap)
  1243 + // {
  1244 + // addLangItem(langId);
  1245 + // }
  1246 + // })));
1246 1247
1247 // Extends the menubar with the language menu 1248 // Extends the menubar with the language menu
1248 var menusCreateMenuBar = Menus.prototype.createMenubar; 1249 var menusCreateMenuBar = Menus.prototype.createMenubar;
@@ -458,7 +458,6 @@ EditorUi.prototype.initPages = function() @@ -458,7 +458,6 @@ EditorUi.prototype.initPages = function()
458 458
459 // Updates scrollbar positions and backgrounds after validation 459 // Updates scrollbar positions and backgrounds after validation
460 var p = this.currentPage; 460 var p = this.currentPage;
461 - console.log(this)  
462 previewAction(this, this.currentPage) 461 previewAction(this, this.currentPage)
463 462
464 if (p != null && p != lastPage) 463 if (p != null && p != lastPage)
@@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
9 var currentDate = getCurrentDate(); 9 var currentDate = getCurrentDate();
10 var fns = [ 10 var fns = [
11 this.createVertexTemplateEntry('text;strokeColor=none;fillColor=none;html=1;fontSize=24;fontStyle=1;verticalAlign=middle;align=center;', 100, 40, 'Title', 'Title', null, null, 'text heading title'), 11 this.createVertexTemplateEntry('text;strokeColor=none;fillColor=none;html=1;fontSize=24;fontStyle=1;verticalAlign=middle;align=center;', 100, 40, 'Title', 'Title', null, null, 'text heading title'),
  12 + this.createVertexTemplateEntry('text;strokeColor=none;fillColor=none;html=1;fontSize=24;fontStyle=1;verticalAlign=middle;align=center;', 100, 40, '变量', '变量', null, null, '变量'),
12 this.createEdgeTemplateEntry('shape=filledEdge;rounded=1;fixDash=1;endArrow=none;strokeWidth=10;fillColor=#BAFDFF;edgeStyle=orthogonalEdgeStyle;flowAnimation=1;strokeColor=#6666FF;endFill=1;metaEdit=0;backgroundOutline=0;', 60, 40, '', '线条'), 13 this.createEdgeTemplateEntry('shape=filledEdge;rounded=1;fixDash=1;endArrow=none;strokeWidth=10;fillColor=#BAFDFF;edgeStyle=orthogonalEdgeStyle;flowAnimation=1;strokeColor=#6666FF;endFill=1;metaEdit=0;backgroundOutline=0;', 60, 40, '', '线条'),
13 this.addEntry('timestamp date time text label', mxUtils.bind(this, function () { 14 this.addEntry('timestamp date time text label', mxUtils.bind(this, function () {
14 var cell = new mxCell('%date{yyyy-mm-dd ddd HH:MM:ss}%', new mxGeometry(0, 0, 160, 20), 'text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;overflow=hidden;'); 15 var cell = new mxCell('%date{yyyy-mm-dd ddd HH:MM:ss}%', new mxGeometry(0, 0, 160, 20), 'text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;overflow=hidden;');
@@ -4880,7 +4880,9 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -4880,7 +4880,9 @@ DataFormatPanel.prototype.addDataFont = function (container) {
4880 const vertices = ss.vertices || [] 4880 const vertices = ss.vertices || []
4881 4881
4882 console.log(this.editorUi) 4882 console.log(this.editorUi)
4883 - console.log(ss.vertices) 4883 + console.log(vertices)
  4884 +
  4885 + // console.log(vertices[0]?.get('bindType'))
4884 /** 4886 /**
4885 * @description 不是单一节点则不进入数据绑定 4887 * @description 不是单一节点则不进入数据绑定
4886 */ 4888 */
@@ -4932,7 +4934,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -4932,7 +4934,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
4932 4934
4933 /** 4935 /**
4934 * @description 当前节点绑定数据 4936 * @description 当前节点绑定数据
4935 - * @type {null} 4937 + * @type {null | object}
4936 */ 4938 */
4937 let currentNodeData = null 4939 let currentNodeData = null
4938 4940
@@ -4992,21 +4994,21 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -4992,21 +4994,21 @@ DataFormatPanel.prototype.addDataFont = function (container) {
4992 ]; 4994 ];
4993 4995
4994 const dynamicEffectList = [ 4996 const dynamicEffectList = [
4995 - {  
4996 - label: "闪烁",  
4997 - type: enumDynamicEffectType.FLASH,  
4998 - category: enumCategory.ACT  
4999 - }, 4997 + // {
  4998 + // label: "闪烁",
  4999 + // type: enumDynamicEffectType.FLASH,
  5000 + // category: enumCategory.ACT
  5001 + // },
5000 { 5002 {
5001 label: "显示/隐藏", 5003 label: "显示/隐藏",
5002 type: enumDynamicEffectType.DISPLAY, 5004 type: enumDynamicEffectType.DISPLAY,
5003 category: enumCategory.ACT 5005 category: enumCategory.ACT
5004 }, 5006 },
5005 - {  
5006 - label: "旋转",  
5007 - type: enumDynamicEffectType.ROTATE,  
5008 - category: enumCategory.ACT  
5009 - }, 5007 + // {
  5008 + // label: "旋转",
  5009 + // type: enumDynamicEffectType.ROTATE,
  5010 + // category: enumCategory.ACT
  5011 + // },
5010 ]; 5012 ];
5011 5013
5012 const enumDataSourceConst = { 5014 const enumDataSourceConst = {
@@ -5205,7 +5207,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5205,7 +5207,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5205 /** 5207 /**
5206 * @description 生成从设备选择器 5208 * @description 生成从设备选择器
5207 */ 5209 */
5208 - function generatoSlaveDevice() { 5210 + function generatorSlaveDevice() {
5209 slaveDevicePanel = defaultPanel.cloneNode(false) 5211 slaveDevicePanel = defaultPanel.cloneNode(false)
5210 const slaveDeviceSelect = UseLayUi.createSelect({ 5212 const slaveDeviceSelect = UseLayUi.createSelect({
5211 label: '子设备', 5213 label: '子设备',
@@ -5312,9 +5314,23 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5312,9 +5314,23 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5312 } 5314 }
5313 5315
5314 async function echoActionType() { 5316 async function echoActionType() {
5315 - const all = [...(currentNodeData.act ?? []), ...(currentNodeData.event ?? [])] 5317 + const act = currentNodeData.act ?? []
  5318 + const event = currentNodeData.event ?? []
5316 const actionType = {} 5319 const actionType = {}
5317 - for (const item of all) { 5320 + for (const item of act) {
  5321 + if (!item.condition || !item.condition?.length) {
  5322 + $(`.interaction__container input[name="${ item.type }"]`).attr('disabled', true)
  5323 + } else {
  5324 + $(`.interaction__container input[name="${ item.type }"]`).attr('disabled', false)
  5325 + }
  5326 + actionType[item.type] = item.enabled
  5327 + }
  5328 + for (const item of event) {
  5329 + if (!item.content) {
  5330 + $(`.interaction__container input[name="${ item.type }"]`).attr('disabled', true)
  5331 + } else {
  5332 + $(`.interaction__container input[name="${ item.type }"]`).attr('disabled', false)
  5333 + }
5318 actionType[item.type] = item.enabled 5334 actionType[item.type] = item.enabled
5319 } 5335 }
5320 form.val(CONTAINER_FILTER, actionType) 5336 form.val(CONTAINER_FILTER, actionType)
@@ -5324,7 +5340,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5324,7 +5340,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5324 function mount() { 5340 function mount() {
5325 generatorOrgTres() 5341 generatorOrgTres()
5326 generatorDeviceSelect() 5342 generatorDeviceSelect()
5327 - generatoSlaveDevice() 5343 + generatorSlaveDevice()
5328 generatorAttrSelect() 5344 generatorAttrSelect()
5329 echoData() 5345 echoData()
5330 5346
@@ -5352,6 +5368,11 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5352,6 +5368,11 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5352 $(panel).addClass('override__panel--default').append(item) 5368 $(panel).addClass('override__panel--default').append(item)
5353 $(fragment).append(panel) 5369 $(fragment).append(panel)
5354 }) 5370 })
  5371 + // Object.keys(enumInteractionType).forEach(key => {
  5372 + // form.on(`checkbox(${ key })`, event => {
  5373 + // const isChecked = $(event.othis).hasClass('layui-form-checked')
  5374 + // })
  5375 + // })
5355 $(container).append(fragment) 5376 $(container).append(fragment)
5356 } 5377 }
5357 5378
@@ -5430,7 +5451,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5430,7 +5451,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5430 return 5451 return
5431 } 5452 }
5432 // 事件类型 5453 // 事件类型
5433 - const enumenumEventType = { 5454 + const enumEventType = {
5434 DOWN: "按下", 5455 DOWN: "按下",
5435 UP: "抬起", 5456 UP: "抬起",
5436 SINGLE: "单击", 5457 SINGLE: "单击",
@@ -5459,9 +5480,19 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5459,9 +5480,19 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5459 ROW_FILTER: 'interactionRowFilter', 5480 ROW_FILTER: 'interactionRowFilter',
5460 5481
5461 /** 5482 /**
  5483 + * @description json editor
  5484 + */
  5485 + EDITOR_JSON: 'editor__json-',
  5486 +
  5487 + /**
5462 * @description 弹出层保存 filter 5488 * @description 弹出层保存 filter
5463 */ 5489 */
5464 - LAYER_SUBMIT_FILTER: 'interactionLayerSubmit' 5490 + LAYER_SUBMIT_FILTER: 'interactionLayerSubmit',
  5491 +
  5492 + /**
  5493 + * @description ace builder
  5494 + */
  5495 + JSON: 'ace__builder-json'
5465 } 5496 }
5466 5497
5467 5498
@@ -5495,7 +5526,17 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5495,7 +5526,17 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5495 /** 5526 /**
5496 * @description 下发值 5527 * @description 下发值
5497 */ 5528 */
5498 - VALUE: 'value' 5529 + VALUE: 'value',
  5530 +
  5531 + /**
  5532 + * @description 方式
  5533 + */
  5534 + WAY: 'way'
  5535 + }
  5536 +
  5537 + const sendInstructionWay = {
  5538 + ONE_WAR: 'oneway',
  5539 + TWO_WAY: 'twoway'
5499 } 5540 }
5500 5541
5501 /** 5542 /**
@@ -5507,9 +5548,23 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5507,9 +5548,23 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5507 allDeviceOptions = res 5548 allDeviceOptions = res
5508 } 5549 }
5509 5550
5510 - function addRecord() { 5551 + function createEditor(el, datum = {}) {
  5552 + const editor = ace.edit(el, {
  5553 + maxLines: 10, // 最大行数,超过会自动出现滚动条
  5554 + minLines: 5, // 最小行数,还未到最大行数时,编辑器会自动伸缩大小
  5555 + fontSize: 14, // 编辑器内字体大小
  5556 + tabSize: 2, // 制表符设置为 4 个空格大小
  5557 + });
  5558 + editor.session.setMode("ace/mode/json");
  5559 + editor.getSession().on('change', (event, editor) => {
  5560 + $(`#${ el }`).parent().find(`textarea[name="${ enumConst.VALUE }"]`).val(editor.getValue())
  5561 + })
  5562 + editor.setValue(datum[enumConst.VALUE] ? datum[enumConst.VALUE] : "{}")
  5563 + }
  5564 +
  5565 + function addRecord(datum) {
5511 const content = ` 5566 const content = `
5512 - <tr class="layui-form" lay-filter="${ enumActionEl.ROW_FILTER }${ addRowNumber }"> 5567 + <tr class="layui-form" lay-filter="${ getRowFilter(addRowNumber) }">
5513 <td> 5568 <td>
5514 <select name="${ enumConst.DEVICE }" lay-filter="${ enumConst.DEVICE }" lay-verType="tips" lay-verify="required"></select> 5569 <select name="${ enumConst.DEVICE }" lay-filter="${ enumConst.DEVICE }" lay-verType="tips" lay-verify="required"></select>
5515 </td> 5570 </td>
@@ -5517,10 +5572,22 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5517,10 +5572,22 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5517 <select name="${ enumConst.SLAVE_DEVICE }" lay-filter="${ enumConst.SLAVE_DEVICE }" lay-verType="tips"></select> 5572 <select name="${ enumConst.SLAVE_DEVICE }" lay-filter="${ enumConst.SLAVE_DEVICE }" lay-verType="tips"></select>
5518 </td> 5573 </td>
5519 <td> 5574 <td>
5520 - <select name="${ enumConst.ATTR }" lay-verType="tips" lay-verify="required"></select> 5575 + <form action="" style="display: flex">
  5576 + <div class="override__radio-default">
  5577 + <input id="${ getRowFilter(addRowNumber) }${ sendInstructionWay.ONE_WAR }" type="radio" name="${ enumConst.WAY }" lay-ignore value="${ sendInstructionWay.ONE_WAR }" title="单向" checked="">
  5578 + <label for="${ getRowFilter(addRowNumber) }${ sendInstructionWay.ONE_WAR }" class="override__radio-label">单向</label>
  5579 + </div>
  5580 + <div class="override__radio-default">
  5581 + <input id="${ getRowFilter(addRowNumber) }${ sendInstructionWay.TWO_WAY }" type="radio" name="${ enumConst.WAY }" lay-ignore value="${ sendInstructionWay.TWO_WAY }" title="双向">
  5582 + <label for="${ getRowFilter(addRowNumber) }${ sendInstructionWay.TWO_WAY }" class="override__radio-label">双向</label>
  5583 + </div>
  5584 + </form>
5521 </td> 5585 </td>
5522 - <td>  
5523 - <textarea name="${ enumConst.VALUE }" placeholder="请输入命令" lay-verType="tips" class="layui-textarea" ></textarea> 5586 + <td class="${enumActionEl.JSON}">
  5587 + <div style="width: 100%;height: 100%;">
  5588 + <div id="${ enumActionEl.EDITOR_JSON }${ addRowNumber }"></div>
  5589 + <textarea style="display: none" name="${ enumConst.VALUE }" placeholder="请输入命令" lay-verType="tips" class="layui-textarea"></textarea>
  5590 + </div>
5524 </td> 5591 </td>
5525 <td> 5592 <td>
5526 <button type="button" class="layui-btn layui-btn-primary layui-border-red ${ enumActionEl.DEL_ROW_EL }">删除</button> 5593 <button type="button" class="layui-btn layui-btn-primary layui-border-red ${ enumActionEl.DEL_ROW_EL }">删除</button>
@@ -5529,6 +5596,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5529,6 +5596,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5529 ` 5596 `
5530 $(`#${ enumActionEl.DEVICE_DATA_BODY_EL }`).append(content) 5597 $(`#${ enumActionEl.DEVICE_DATA_BODY_EL }`).append(content)
5531 setDeviceOptions(addRowNumber) 5598 setDeviceOptions(addRowNumber)
  5599 + createEditor(`${ enumActionEl.EDITOR_JSON }${ addRowNumber }`, datum)
5532 form.render('select', getRowFilter(addRowNumber)) 5600 form.render('select', getRowFilter(addRowNumber))
5533 addRowNumber++ 5601 addRowNumber++
5534 } 5602 }
@@ -5557,14 +5625,15 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5557,14 +5625,15 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5557 if (!res) return 5625 if (!res) return
5558 const generateOption = UseLayUi.generateOptionTemplate({ dataSource: res }) 5626 const generateOption = UseLayUi.generateOptionTemplate({ dataSource: res })
5559 $(data.elem).parents('tr').find(`select[name="${ enumConst.SLAVE_DEVICE }"]`).html(generateOption) 5627 $(data.elem).parents('tr').find(`select[name="${ enumConst.SLAVE_DEVICE }"]`).html(generateOption)
5560 - } else {  
5561 - updateVariableOptions(data)  
5562 } 5628 }
  5629 + // else {
  5630 + // updateVariableOptions(data)
  5631 + // }
5563 form.render('select') 5632 form.render('select')
5564 }) 5633 })
5565 - form.on(`select(${ enumConst.SLAVE_DEVICE })`, (data) => {  
5566 - updateVariableOptions(data)  
5567 - }) 5634 + // form.on(`select(${ enumConst.SLAVE_DEVICE })`, (data) => {
  5635 + // updateVariableOptions(data)
  5636 + // })
5568 } 5637 }
5569 5638
5570 /** 5639 /**
@@ -5572,6 +5641,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5572,6 +5641,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5572 */ 5641 */
5573 function createDeleteRowListenEvent() { 5642 function createDeleteRowListenEvent() {
5574 $(`.${ enumActionEl.DEL_ROW_EL }`).click((event) => { 5643 $(`.${ enumActionEl.DEL_ROW_EL }`).click((event) => {
  5644 + // $(event.target).parents('tr').find('editor')
5575 $(event.target).parents('tr').remove() 5645 $(event.target).parents('tr').remove()
5576 }) 5646 })
5577 } 5647 }
@@ -5645,17 +5715,18 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5645,17 +5715,18 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5645 * @description 回显每条数据 5715 * @description 回显每条数据
5646 */ 5716 */
5647 function echoEachData(datum = {}, row) { 5717 function echoEachData(datum = {}, row) {
5648 - addRecord() 5718 + addRecord(datum)
5649 const deviceId = datum[enumConst.DEVICE] 5719 const deviceId = datum[enumConst.DEVICE]
5650 const slaveDeviceId = datum[enumConst.SLAVE_DEVICE] 5720 const slaveDeviceId = datum[enumConst.SLAVE_DEVICE]
5651 const queue = [] 5721 const queue = []
5652 5722
5653 if (slaveDeviceId) { 5723 if (slaveDeviceId) {
5654 queue.push(() => getSlaveDeviceByMasterDevice(deviceId, row)) 5724 queue.push(() => getSlaveDeviceByMasterDevice(deviceId, row))
5655 - queue.push(() => getDeviceAttrByDeviceId(slaveDeviceId, row))  
5656 - } else {  
5657 - queue.push(() => getDeviceAttrByDeviceId(deviceId, row)) 5725 + // queue.push(() => getDeviceAttrByDeviceId(slaveDeviceId, row))
5658 } 5726 }
  5727 + // else {
  5728 + // queue.push(() => getDeviceAttrByDeviceId(deviceId, row))
  5729 + // }
5659 5730
5660 Promise 5731 Promise
5661 .all(queue.map(item => item())) 5732 .all(queue.map(item => item()))
@@ -5664,11 +5735,39 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5664,11 +5735,39 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5664 }) 5735 })
5665 } 5736 }
5666 5737
  5738 + function isJson(string) {
  5739 + if (typeof string === 'string') {
  5740 + try {
  5741 + const obj = JSON.parse(string)
  5742 + if (typeof obj === 'object' && obj !== null) {
  5743 + return true
  5744 + }
  5745 + } catch (e) {
  5746 + return false
  5747 + }
  5748 + }
  5749 + return false
  5750 + }
  5751 +
  5752 + function validate(tableData) {
  5753 + let validateFlag = true
  5754 + for (let i = 0; i < tableData.length; i++) {
  5755 + const { value } = tableData[i]
  5756 + if (!isJson(value)) {
  5757 + validateFlag = false
  5758 + layer.tips('下发值不正确', $(`#${ enumActionEl.DEVICE_DATA_BODY_EL } tr`).eq(i).find(`td.${enumActionEl.JSON}`), { tips: 1 })
  5759 + break
  5760 + }
  5761 + }
  5762 + return validateFlag
  5763 + }
  5764 +
5667 /** 5765 /**
5668 * @description 保存 5766 * @description 保存
5669 */ 5767 */
5670 async function submit(callback) { 5768 async function submit(callback) {
5671 const data = Array.from({ length: addRowNumber }).map((_, row) => form.val(getRowFilter(row))).filter(item => Object.keys(item).length) 5769 const data = Array.from({ length: addRowNumber }).map((_, row) => form.val(getRowFilter(row))).filter(item => Object.keys(item).length)
  5770 + if (!validate(data)) return
5672 const formModal = { 5771 const formModal = {
5673 configurationId, 5772 configurationId,
5674 contentId: currentPageId.id, 5773 contentId: currentPageId.id,
@@ -5695,7 +5794,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5695,7 +5794,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5695 <div class="layui-form-item"> 5794 <div class="layui-form-item">
5696 <label class="layui-form-label">事件</label> 5795 <label class="layui-form-label">事件</label>
5697 <div class="layui-input-block"> 5796 <div class="layui-input-block">
5698 - <input type="text" name="event" class="layui-input" value="${ enumenumEventType[type] }" disabled> 5797 + <input type="text" name="event" class="layui-input" value="${ enumEventType[type] }" disabled>
5699 </div> 5798 </div>
5700 </div> 5799 </div>
5701 <div class="layui-form-item"> 5800 <div class="layui-form-item">
@@ -5714,38 +5813,31 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5714,38 +5813,31 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5714 </div> 5813 </div>
5715 </div> 5814 </div>
5716 </div> 5815 </div>
5717 - <div id="tableContent">  
5718 - <table class="layui-table" >  
5719 - <colgroup>  
5720 - <col width="240">  
5721 - <col width="240">  
5722 - <col width="240">  
5723 - <col width="240">  
5724 - <col width="60">  
5725 - </colgroup>  
5726 - <thead>  
5727 - <tr>  
5728 - <th style="text-align:center">选择设备</th>  
5729 - <th style="text-align:center">选择子设备</th>  
5730 - <th style="text-align:center">变量</th>  
5731 - <th style="text-align:center">下发值</th>  
5732 - <th style="text-align:center">操作</th>  
5733 - </tr>  
5734 - </thead>  
5735 - <tbody id="${ enumActionEl.DEVICE_DATA_BODY_EL }"></tbody>  
5736 - </table>  
5737 - <div style="display:flex;justify-content:center;">  
5738 - <button type="button" class="layui-btn layui-btn-primary layui-border-blue" id="${ enumActionEl.ADD_ROW_EL }">添加一条</button>  
5739 - </div> 5816 + </form>
  5817 + <div class="override__table">
  5818 + <table class="layui-table" >
  5819 + <thead>
  5820 + <tr>
  5821 + <th style="text-align:center">选择设备</th>
  5822 + <th style="text-align:center">选择子设备</th>
  5823 + <th style="text-align:center">单向 / 双向</th>
  5824 + <th style="text-align:center">下发值</th>
  5825 + <th style="text-align:center">操作</th>
  5826 + </tr>
  5827 + </thead>
  5828 + <tbody id="${ enumActionEl.DEVICE_DATA_BODY_EL }"></tbody>
  5829 + </table>
  5830 + <div style="display:flex;justify-content:center;">
  5831 + <button type="button" class="layui-btn layui-btn-primary layui-border-blue" id="${ enumActionEl.ADD_ROW_EL }">添加一条</button>
5740 </div> 5832 </div>
5741 - </form>` 5833 + </div>`
5742 5834
5743 layer.open({ 5835 layer.open({
5744 title: '创建交互', 5836 title: '创建交互',
5745 content, 5837 content,
5746 skin: 'event-layer__override', 5838 skin: 'event-layer__override',
5747 - // area: ["800px", "600px"],  
5748 - area: '1100px', 5839 + // area: ["1100px", "700px"],
  5840 + area: '1200px',
5749 btn: ["保存", "取消"], 5841 btn: ["保存", "取消"],
5750 shade: ["0.7", "#fafafa"], 5842 shade: ["0.7", "#fafafa"],
5751 yes(index) { 5843 yes(index) {
@@ -5950,8 +6042,6 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5950,8 +6042,6 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5950 </div> 6042 </div>
5951 </div> 6043 </div>
5952 </div> 6044 </div>
5953 - <div style="height:200px;overflow-y:scroll" id="tableContent">  
5954 - </div>  
5955 </form> 6045 </form>
5956 ` 6046 `
5957 6047
@@ -6014,7 +6104,9 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -6014,7 +6104,9 @@ DataFormatPanel.prototype.addDataFont = function (container) {
6014 DEL_BTN_EL: 'dataDynamicEffectDelBtn', 6104 DEL_BTN_EL: 'dataDynamicEffectDelBtn',
6015 ADD_BTN_EL: 'dataDynamicEffectAddBtn', 6105 ADD_BTN_EL: 'dataDynamicEffectAddBtn',
6016 DISPLAY_SWITCH_EL: 'visibleOrHidden', 6106 DISPLAY_SWITCH_EL: 'visibleOrHidden',
6017 - LAYER_SUBMIT_FILTER: 'dynamicEffectLayerFilter' 6107 + LAYER_SUBMIT_FILTER: 'dynamicEffectLayerFilter',
  6108 + MIN_FILTER: 'dynamicEffectMinFilter',
  6109 + MAX_FILTER: 'dynamicEffectMaxFilter',
6018 } 6110 }
6019 6111
6020 const getRowFilter = (rowNumber) => `${ enumActionEl.ROW_FILTER }${ rowNumber }` 6112 const getRowFilter = (rowNumber) => `${ enumActionEl.ROW_FILTER }${ rowNumber }`
@@ -6033,6 +6125,8 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -6033,6 +6125,8 @@ DataFormatPanel.prototype.addDataFont = function (container) {
6033 GATEWAY: 'GATEWAY' 6125 GATEWAY: 'GATEWAY'
6034 } 6126 }
6035 6127
  6128 + const enumDisplayType = HandleDynamicEffect.enumDisplayType
  6129 +
6036 /** 6130 /**
6037 * @description 设备列表 6131 * @description 设备列表
6038 */ 6132 */
@@ -6075,19 +6169,20 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -6075,19 +6169,20 @@ DataFormatPanel.prototype.addDataFont = function (container) {
6075 * @description 通过组织获取设备 6169 * @description 通过组织获取设备
6076 */ 6170 */
6077 async function getDeviceByOrg(id) { 6171 async function getDeviceByOrg(id) {
  6172 + if (!id) return
6078 const [err, res] = await to(ConfigurationNodeApi.getMasterDevice(id)) 6173 const [err, res] = await to(ConfigurationNodeApi.getMasterDevice(id))
6079 - if (res) {  
6080 - deviceList = res  
6081 - const template = UseLayUi.generateOptionTemplate({ dataSource: res })  
6082 - $(`#${ enumActionEl.DEVICE_EL } select`).html(template)  
6083 - form.render('select', enumActionEl.FORM_FILTER)  
6084 - } 6174 + if (!res) return
  6175 + deviceList = res
  6176 + const template = UseLayUi.generateOptionTemplate({ dataSource: res })
  6177 + $(`#${ enumActionEl.DEVICE_EL } select`).html(template)
  6178 + form.render('select', enumActionEl.FORM_FILTER)
6085 } 6179 }
6086 6180
6087 /** 6181 /**
6088 * @description 通过主设备ID获取从设备 6182 * @description 通过主设备ID获取从设备
6089 */ 6183 */
6090 async function getSlaveDeviceByMasterDevice(orgId, id) { 6184 async function getSlaveDeviceByMasterDevice(orgId, id) {
  6185 + if (!orgId || !id) return
6091 const [err, res] = await to(ConfigurationNodeApi.getSlaveDevice(orgId, id)) 6186 const [err, res] = await to(ConfigurationNodeApi.getSlaveDevice(orgId, id))
6092 if (res) { 6187 if (res) {
6093 const template = UseLayUi.generateOptionTemplate({ dataSource: res }) 6188 const template = UseLayUi.generateOptionTemplate({ dataSource: res })
@@ -6100,6 +6195,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -6100,6 +6195,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
6100 * @description 通过设备ID获取设备属性 6195 * @description 通过设备ID获取设备属性
6101 */ 6196 */
6102 async function getAttrsByDevice(id) { 6197 async function getAttrsByDevice(id) {
  6198 + if (!id) return
6103 const [err, res] = await to(ConfigurationNodeApi.getDeviceAttr(id)) 6199 const [err, res] = await to(ConfigurationNodeApi.getDeviceAttr(id))
6104 if (res) { 6200 if (res) {
6105 const template = UseLayUi.generateOptionTemplate({ dataSource: res }) 6201 const template = UseLayUi.generateOptionTemplate({ dataSource: res })
@@ -6111,8 +6207,8 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -6111,8 +6207,8 @@ DataFormatPanel.prototype.addDataFont = function (container) {
6111 6207
6112 function generatorDisplayOptions() { 6208 function generatorDisplayOptions() {
6113 const options = [ 6209 const options = [
6114 - { name: '显示', id: 'show' },  
6115 - { name: '隐藏', id: 'hidden' } 6210 + { name: '显示', id: enumDisplayType.SHOW },
  6211 + { name: '隐藏', id: enumDisplayType.HIDDEN }
6116 ] 6212 ]
6117 const template = UseLayUi.generateOptionTemplate({ dataSource: options }) 6213 const template = UseLayUi.generateOptionTemplate({ dataSource: options })
6118 return ` 6214 return `
@@ -6132,10 +6228,10 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -6132,10 +6228,10 @@ DataFormatPanel.prototype.addDataFont = function (container) {
6132 <tr class="layui-form" lay-filter="${ getRowFilter(addRowNumber) }"> 6228 <tr class="layui-form" lay-filter="${ getRowFilter(addRowNumber) }">
6133 ${ IS_DISPLAY && `<td>${ generatorDisplayOptions() }</td>` } 6229 ${ IS_DISPLAY && `<td>${ generatorDisplayOptions() }</td>` }
6134 <td> 6230 <td>
6135 - <input lay-verType="tips" lay-verify="required" type="text" name="${ enumConst.MIN }" class="layui-input"> 6231 + <input lay-verType="tips" lay-verify="required" type="number" name="${ enumConst.MIN }" class="layui-input ${ enumActionEl.MIN_FILTER }">
6136 </td> 6232 </td>
6137 <td> 6233 <td>
6138 - <input lay-verType="tips" lay-verify="required" type="text" name="${ enumConst.MAX }" class="layui-input"> 6234 + <input lay-verType="tips" lay-verify="required" type="number" name="${ enumConst.MAX }" class="layui-input ${ enumActionEl.MAX_FILTER }">
6139 </td> 6235 </td>
6140 <td style="text-align: center;"> 6236 <td style="text-align: center;">
6141 <button type="button" class="layui-btn layui-btn-primary layui-border-red ${ enumActionEl.DEL_BTN_EL }">删除</button> 6237 <button type="button" class="layui-btn layui-btn-primary layui-border-red ${ enumActionEl.DEL_BTN_EL }">删除</button>
@@ -6191,9 +6287,35 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -6191,9 +6287,35 @@ DataFormatPanel.prototype.addDataFont = function (container) {
6191 } 6287 }
6192 6288
6193 /** 6289 /**
  6290 + * @description 创建输入监听
  6291 + */
  6292 + function createInputListener() {
  6293 + $(`#${ enumActionEl.TABLE_BODY_EL }`)
  6294 + .on('input', `.${ enumActionEl.MIN_FILTER }`, event => {
  6295 + const minVal = $(event.target).val()
  6296 + const maxVal = $(event.target).parents('tr').find(`input.${ enumActionEl.MAX_FILTER }`).val()
  6297 + if (maxVal !== '' && Number(minVal) > Number(maxVal)) {
  6298 + layer.tips('输入值大于最大值', $(event.target), {
  6299 + tips: 1
  6300 + });
  6301 + }
  6302 + })
  6303 + .on('input', `.${ enumActionEl.MAX_FILTER }`, event => {
  6304 + const maxVal = $(event.target).val()
  6305 + const minVal = $(event.target).parents('tr').find(`input.${ enumActionEl.MIN_FILTER }`).val()
  6306 + if (minVal !== '' && Number(maxVal) < Number(minVal)) {
  6307 + layer.tips('输入值小于最小值', $(event.target), {
  6308 + tips: 1
  6309 + });
  6310 + }
  6311 + })
  6312 + }
  6313 +
  6314 + /**
6194 * @description 创建事件监听 6315 * @description 创建事件监听
6195 */ 6316 */
6196 function createEventListen() { 6317 function createEventListen() {
  6318 + createInputListener()
6197 createSelectLinkageListenEvent() 6319 createSelectLinkageListenEvent()
6198 createAddRowListenEvent() 6320 createAddRowListenEvent()
6199 createDeleteRowListenEvent() 6321 createDeleteRowListenEvent()
@@ -6237,12 +6359,29 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -6237,12 +6359,29 @@ DataFormatPanel.prototype.addDataFont = function (container) {
6237 */ 6359 */
6238 function echoOrgTree(id) { 6360 function echoOrgTree(id) {
6239 const node = UseLayUi.findTreeObjectByField(treeList, id) 6361 const node = UseLayUi.findTreeObjectByField(treeList, id)
6240 - console.log(node)  
6241 $(`#${ enumActionEl.ORG_EL }`).find(`input[name="${ enumConst.ORG_ID }"]`).parent().find('span').html(node?.name) 6362 $(`#${ enumActionEl.ORG_EL }`).find(`input[name="${ enumConst.ORG_ID }"]`).parent().find('span').html(node?.name)
6242 } 6363 }
6243 6364
  6365 + function validate(tableData) {
  6366 + let validateFlag = true
  6367 + for (let i = 0; i < tableData.length; i++) {
  6368 + const { min, max } = tableData[i]
  6369 + if (Number(min) > Number(max)) {
  6370 + validateFlag = false
  6371 + layer.tips('输入值大于最大值', $(`#${ enumActionEl.TABLE_BODY_EL } tr`).eq(i).find(`input[name="${ enumConst.MIN }"]`), { tips: 1 })
  6372 + break
  6373 + } else if (Number(max) < Number(min)) {
  6374 + validateFlag = false
  6375 + layer.tips('输入值小于最小值', $(`#${ enumActionEl.TABLE_BODY_EL } tr`).eq(i).find(`input[name="${ enumConst.MAX }"]`), { tips: 1 })
  6376 + break
  6377 + }
  6378 + }
  6379 + return validateFlag
  6380 + }
  6381 +
6244 async function submit(callback) { 6382 async function submit(callback) {
6245 const tableData = Array.from({ length: addRowNumber }).map((_, index) => form.val(getRowFilter(index))).filter(obj => Object.keys(obj).length) 6383 const tableData = Array.from({ length: addRowNumber }).map((_, index) => form.val(getRowFilter(index))).filter(obj => Object.keys(obj).length)
  6384 + if (!validate(tableData)) return
6246 const formVal = form.val(enumActionEl.FORM_FILTER) 6385 const formVal = form.val(enumActionEl.FORM_FILTER)
6247 const formModel = { 6386 const formModel = {
6248 configurationId, 6387 configurationId,
@@ -6258,6 +6397,10 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -6258,6 +6397,10 @@ DataFormatPanel.prototype.addDataFont = function (container) {
6258 callback() 6397 callback()
6259 } 6398 }
6260 6399
  6400 + function isExistInArea(min, max, value) {
  6401 + return Number(value) >= Number(min) && Number(value) <= Number(max)
  6402 + }
  6403 +
6261 6404
6262 function createLayerForm(type) { 6405 function createLayerForm(type) {
6263 const content = ` 6406 const content = `
@@ -6297,14 +6440,8 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -6297,14 +6440,8 @@ DataFormatPanel.prototype.addDataFont = function (container) {
6297 </div> 6440 </div>
6298 </div> 6441 </div>
6299 </form> 6442 </form>
6300 - <div> 6443 + <div class="override__table">
6301 <table class="layui-table" > 6444 <table class="layui-table" >
6302 - <colgroup>  
6303 - ${ IS_DISPLAY ? '<col width="240">' : '' }  
6304 - <col width="240">  
6305 - <col width="240">  
6306 - <col>  
6307 - </colgroup>  
6308 <thead> 6445 <thead>
6309 <tr> 6446 <tr>
6310 ${ IS_DISPLAY ? '<th style="text-align:center">类型</th>' : '' } 6447 ${ IS_DISPLAY ? '<th style="text-align:center">类型</th>' : '' }
@@ -10568,6 +10705,9 @@ class UseLayUi { @@ -10568,6 +10705,9 @@ class UseLayUi {
10568 UseLayUi.msg(msg, { ...options, icon: 6 }) 10705 UseLayUi.msg(msg, { ...options, icon: 6 })
10569 } 10706 }
10570 10707
  10708 + static errorMsg(msg = '操作失败', options) {
  10709 + UseLayUi.msg(msg, { ...options, icon: 5 })
  10710 + }
10571 } 10711 }
10572 10712
10573 10713
@@ -10910,6 +11050,12 @@ class DispatchCenter { @@ -10910,6 +11050,12 @@ class DispatchCenter {
10910 nodeMapping 11050 nodeMapping
10911 11051
10912 /** 11052 /**
  11053 + * @description cmd ID 与 node 映射关系
  11054 + * @type {Map<number, string>}
  11055 + */
  11056 + cmdIdMapping = new Map()
  11057 +
  11058 + /**
10913 * @description 11059 * @description
10914 */ 11060 */
10915 editorUi 11061 editorUi
@@ -10942,7 +11088,30 @@ class DispatchCenter { @@ -10942,7 +11088,30 @@ class DispatchCenter {
10942 eventBus 11088 eventBus
10943 11089
10944 /** 11090 /**
  11091 + * @description 页面数据
  11092 + */
  11093 + contentData
  11094 +
  11095 + /**
  11096 + * @description 处理数据动效实例
  11097 + * @type {HandleDynamicEffect}
  11098 + */
  11099 + dynamicEffectInstance
  11100 +
  11101 + /**
  11102 + * @description 处理数据交互实例
  11103 + * @type {HandleDataInteraction}
  11104 + */
  11105 + dataInteractionInstance
  11106 +
  11107 + /**
  11108 + * @description cmd id
  11109 + */
  11110 + cmdIdPrimaryKey = 0
  11111 +
  11112 + /**
10945 * @description 当前实例 11113 * @description 当前实例
  11114 + * @type {DispatchCenter}
10946 */ 11115 */
10947 static instance 11116 static instance
10948 11117
@@ -10979,8 +11148,6 @@ class DispatchCenter { @@ -10979,8 +11148,6 @@ class DispatchCenter {
10979 constructor(editorUi, currentPage) { 11148 constructor(editorUi, currentPage) {
10980 this.nodeMapping = new Map() 11149 this.nodeMapping = new Map()
10981 this.editorUi = editorUi 11150 this.editorUi = editorUi
10982 -  
10983 - // mxEvent.addListener(document, (mxClient.IS_POINTER) ? 'pointerup' : 'mouseup', this.pointerUpHandler);  
10984 this.init(editorUi, currentPage) 11151 this.init(editorUi, currentPage)
10985 } 11152 }
10986 11153
@@ -10989,12 +11156,13 @@ class DispatchCenter { @@ -10989,12 +11156,13 @@ class DispatchCenter {
10989 * @param editorUi 11156 * @param editorUi
10990 * @param currentPage 11157 * @param currentPage
10991 */ 11158 */
10992 - init(editorUi, currentPage) { 11159 + async init(editorUi, currentPage) {
10993 this.createEventBus() 11160 this.createEventBus()
10994 this.saveContentInfo(editorUi, currentPage) 11161 this.saveContentInfo(editorUi, currentPage)
10995 - this.createGraphEventListener()  
10996 this.connectSocket() 11162 this.connectSocket()
10997 - this.getContentDataNode() 11163 + await this.getContentDataNode()
  11164 + this.dataInteractionInstance = new HandleDataInteraction(this)
  11165 + this.dynamicEffectInstance = new HandleDynamicEffect(this)
10998 } 11166 }
10999 11167
11000 /** 11168 /**
@@ -11002,15 +11170,7 @@ class DispatchCenter { @@ -11002,15 +11170,7 @@ class DispatchCenter {
11002 */ 11170 */
11003 connectSocket() { 11171 connectSocket() {
11004 const GLOBAL_TOKEN = JSON.parse(localStorage.getItem("UNDEFINED__DEVELOPMENT__2.7.1__COMMON__LOCAL__KEY__")).value.JWT_TOKEN.value 11172 const GLOBAL_TOKEN = JSON.parse(localStorage.getItem("UNDEFINED__DEVELOPMENT__2.7.1__COMMON__LOCAL__KEY__")).value.JWT_TOKEN.value
11005 -  
11006 - // const { host, href } = location  
11007 - // const reg = /^https/  
11008 - // const wsUrl = `${reg.test(href) ? 'wss' : 'ws'}://${host}/api/ws/plugins/telemetry?token=${GLOBAL_TOKEN}`  
11009 -  
11010 - const wsUrl = `ws://47.99.141.212:8080/api/ws/plugins/telemetry?token=${ GLOBAL_TOKEN }`  
11011 - // const wsUrl = `ws://192.168.10.115:8080/api/ws/plugins/telemetry?token=${GLOBAL_TOKEN}`  
11012 -  
11013 - this.socket = Ws.getInstance({ url: wsUrl, onmessageCallback: this.socketOnmessage }) 11173 + this.socket = Ws.getInstance({ url: GLOBAL_WS_URL, onmessageCallback: this.socketOnmessage })
11014 } 11174 }
11015 11175
11016 /** 11176 /**
@@ -11021,7 +11181,7 @@ class DispatchCenter { @@ -11021,7 +11181,7 @@ class DispatchCenter {
11021 */ 11181 */
11022 socketOnmessage(message, event, ws) { 11182 socketOnmessage(message, event, ws) {
11023 const { subscriptionId, data } = message 11183 const { subscriptionId, data } = message
11024 - DispatchCenter.instance.publishEvent(subscriptionId, data) 11184 + DispatchCenter.instance.publishEvent(subscriptionId, data, message, event, ws)
11025 } 11185 }
11026 11186
11027 /** 11187 /**
@@ -11032,39 +11192,6 @@ class DispatchCenter { @@ -11032,39 +11192,6 @@ class DispatchCenter {
11032 } 11192 }
11033 11193
11034 /** 11194 /**
11035 - * @description 创建图层事件监听器  
11036 - */  
11037 - createGraphEventListener() {  
11038 - if (DispatchCenter.eventListenerIsExist) return  
11039 -  
11040 - const graphDblClick = this.graph.dblClick;  
11041 - this.graph.dblClick = (...args) => {  
11042 - this.handleDoubleClickEvent(...args)  
11043 - graphDblClick.apply(this.graph, args)  
11044 - }  
11045 -  
11046 -  
11047 - const graphClick = this.graph.click;  
11048 - this.graph.click = (...args) => {  
11049 - this.handleClickEvent(...args)  
11050 - graphClick.apply(this.graph, args)  
11051 - }  
11052 -  
11053 - const graphFireMouseEvent = this.graph.fireMouseEvent;  
11054 - this.graph.fireMouseEvent = (eventName, event, sender) => {  
11055 - if (eventName === mxEvent.MOUSE_DOWN) {  
11056 - this.handleMouseDownEvent(eventName, event, sender)  
11057 - }  
11058 - if (eventName === mxEvent.MOUSE_UP) {  
11059 - this.handleMouseUpEvent(eventName, event, sender)  
11060 - }  
11061 - graphFireMouseEvent.apply(this.graph, [eventName, event, sender]);  
11062 - };  
11063 -  
11064 - DispatchCenter.eventListenerIsExist = true  
11065 - }  
11066 -  
11067 - /**  
11068 * @description 保存部分页面信息到实例上 11195 * @description 保存部分页面信息到实例上
11069 * @param editorUi 11196 * @param editorUi
11070 * @param currentPage 11197 * @param currentPage
@@ -11084,14 +11211,9 @@ class DispatchCenter { @@ -11084,14 +11211,9 @@ class DispatchCenter {
11084 const { node: { id } = {} } = this.currentPage 11211 const { node: { id } = {} } = this.currentPage
11085 if (!id) return 11212 if (!id) return
11086 const [err, res] = await to(ConfigurationNodeApi.getConfigurationInfo('CONTENT', id)) 11213 const [err, res] = await to(ConfigurationNodeApi.getConfigurationInfo('CONTENT', id))
11087 - const { dataSources, event, act } = res  
11088 - const sendMsg = {  
11089 - tsSubCmds: this.generatorDataSourceMapping(dataSources)  
11090 - }  
11091 - this.generatorEventMapping(event)  
11092 - this.generatorActionEffectMapping(act)  
11093 - this.sendMessageToGetRealTimeData(sendMsg)  
11094 - console.log(this.nodeMapping) 11214 + const { dataSources, event, act } = this.contentData = res
  11215 + const tsSubCmds = this.generatorDataSourceMapping(dataSources)
  11216 + this.sendMessageToGetRealTimeData({ tsSubCmds })
11095 } 11217 }
11096 11218
11097 /** 11219 /**
@@ -11103,61 +11225,43 @@ class DispatchCenter { @@ -11103,61 +11225,43 @@ class DispatchCenter {
11103 } 11225 }
11104 11226
11105 /** 11227 /**
  11228 + * @description 通过传入NodeId获取cmdId
  11229 + * @param nodeId
  11230 + * @return {number}
  11231 + */
  11232 + getCmdId(nodeId) {
  11233 + const cmdId = this.cmdIdPrimaryKey++
  11234 + this.cmdIdMapping.set(cmdId, nodeId)
  11235 + return cmdId
  11236 + }
  11237 +
  11238 + /**
11106 * @description 生成节点映射表 11239 * @description 生成节点映射表
11107 * @param dataSources 11240 * @param dataSources
11108 * @return {{cmdId: number, entityType: string, keys: *, scope: string, entityId: *}[]} 11241 * @return {{cmdId: number, entityType: string, keys: *, scope: string, entityId: *}[]}
11109 */ 11242 */
11110 generatorDataSourceMapping(dataSources = []) { 11243 generatorDataSourceMapping(dataSources = []) {
11111 - return dataSources.map((datum, eventName) => {  
11112 - const { deviceId, attr } = datum 11244 + return dataSources.map((datum) => {
  11245 + const { deviceId, attr, nodeId } = datum
  11246 + const cmdId = this.getCmdId(nodeId)
11113 const sendMsgTemplate = { 11247 const sendMsgTemplate = {
11114 entityType: "DEVICE", 11248 entityType: "DEVICE",
11115 entityId: deviceId, 11249 entityId: deviceId,
11116 scope: "LATEST_TELEMETRY", 11250 scope: "LATEST_TELEMETRY",
11117 - cmdId: eventName, 11251 + cmdId,
11118 keys: attr 11252 keys: attr
11119 } 11253 }
11120 -  
11121 - this.subscribeDataSources(datum, eventName, attr) 11254 + this.subscribeDataSources(datum, cmdId, attr)
11122 return sendMsgTemplate 11255 return sendMsgTemplate
11123 }) 11256 })
11124 } 11257 }
11125 11258
11126 /** 11259 /**
11127 - * @description 事件映射  
11128 - * @param event  
11129 - */  
11130 - generatorEventMapping(event = []) {  
11131 - for (const item of event) {  
11132 - const { content, id: nodeId, enabled, type } = item  
11133 - if (!enabled) continue  
11134 - if (!this.nodeMapping.has(nodeId)) this.nodeMapping.set(nodeId, new Map())  
11135 - const temp = this.nodeMapping.get(nodeId)  
11136 - temp.set(type, content)  
11137 - }  
11138 - }  
11139 -  
11140 - /**  
11141 - * @description 动效映射  
11142 - * @param act  
11143 - */  
11144 - generatorActionEffectMapping(act = []) {  
11145 - for (const item of act) {  
11146 - const { condition, id: nodeId, enabled, type } = item  
11147 - if (!enabled) continue  
11148 - if (!this.nodeMapping.has(nodeId)) this.nodeMapping.set(nodeId, new Map())  
11149 - const temp = this.nodeMapping.get(nodeId)  
11150 - temp.set(type, condition)  
11151 - }  
11152 - }  
11153 -  
11154 - /**  
11155 * @description 分发事件 11260 * @description 分发事件
11156 */ 11261 */
11157 - publishEvent(eventName, data) { 11262 + publishEvent(eventName, data, message, event, ws) {
11158 Object.keys(data).forEach(() => { 11263 Object.keys(data).forEach(() => {
11159 - this.eventBus.emit(eventName, data)  
11160 - 11264 + this.eventBus.emit(eventName, message, event, ws)
11161 }) 11265 })
11162 } 11266 }
11163 11267
@@ -11170,8 +11274,9 @@ class DispatchCenter { @@ -11170,8 +11274,9 @@ class DispatchCenter {
11170 subscribeDataSources(datum, eventName, key) { 11274 subscribeDataSources(datum, eventName, key) {
11171 const node = this.contentAllCell.find(item => item.id === datum.nodeId) 11275 const node = this.contentAllCell.find(item => item.id === datum.nodeId)
11172 this.eventBus.on(eventName, (message) => { 11276 this.eventBus.on(eventName, (message) => {
11173 - this.updatePage(node, () => {  
11174 - const [[timespan, value]] = message[key] 11277 + this.updatePage(() => {
  11278 + const { data } = message
  11279 + const [[timespan, value]] = data[key]
11175 node.setValue(value) 11280 node.setValue(value)
11176 }) 11281 })
11177 }) 11282 })
@@ -11179,19 +11284,132 @@ class DispatchCenter { @@ -11179,19 +11284,132 @@ class DispatchCenter {
11179 11284
11180 /** 11285 /**
11181 * @description 更新页面 11286 * @description 更新页面
11182 - * @param node  
11183 * @param callback 11287 * @param callback
11184 */ 11288 */
11185 - updatePage(node, callback) { 11289 + updatePage(callback) {
11186 this.graph.getModel().beginUpdate() 11290 this.graph.getModel().beginUpdate()
11187 try { 11291 try {
11188 callback() 11292 callback()
11189 - this.graph.insertVertex(node, null); 11293 + this.graph.refresh();
11190 } finally { 11294 } finally {
11191 this.graph.getModel().endUpdate() 11295 this.graph.getModel().endUpdate()
11192 } 11296 }
11193 } 11297 }
11194 11298
  11299 +
  11300 + /**
  11301 + * @description 返回 DispatchCenter 实例 当contentID变化时重新创建实例
  11302 + * @param editorUi
  11303 + * @param currentPage
  11304 + * @return {*}
  11305 + */
  11306 + static getInstance(editorUi, currentPage = {}) {
  11307 + const { node: { id } = {} } = currentPage
  11308 + if (!id) return
  11309 + if (!DispatchCenter.instance || DispatchCenter.rawContentId !== id) {
  11310 + DispatchCenter.instance?.dynamicEffectInstance?.cleanSetInterval?.()
  11311 + DispatchCenter.instance = new DispatchCenter(editorUi, currentPage)
  11312 + DispatchCenter.rawContentId = id
  11313 + }
  11314 +
  11315 + return DispatchCenter.instance
  11316 + }
  11317 +
  11318 +}
  11319 +
  11320 +class HandleDataInteraction {
  11321 + /**
  11322 + * @description 事件分发中心实例
  11323 + * @type {DispatchCenter}
  11324 + */
  11325 + DispatchInstance
  11326 +
  11327 + /**
  11328 + * @description 事件映射
  11329 + * @type {Map<>}
  11330 + */
  11331 + eventMapping = new Map()
  11332 +
  11333 + constructor(DispatchInstance) {
  11334 + this.DispatchInstance = DispatchInstance
  11335 + this.init()
  11336 + }
  11337 +
  11338 + init() {
  11339 + this.generatorEventMapping()
  11340 + this.createGraphEventListener()
  11341 + }
  11342 +
  11343 + /**
  11344 + * @description DispatchCenter 实例中保存的 graph 对象
  11345 + * @return {*}
  11346 + */
  11347 + get graph() {
  11348 + return this.DispatchInstance.graph
  11349 + }
  11350 +
  11351 + /**
  11352 + * @description DispatchCenter 实例中保存的 editorUi 对象
  11353 + * @return {*}
  11354 + */
  11355 + get editorUi() {
  11356 + return this.DispatchInstance.editorUi
  11357 + }
  11358 +
  11359 + /**
  11360 + * @description DispatchCenter 实例中保存的 contentAllCell 对象
  11361 + * @return {*}
  11362 + */
  11363 + get eventList() {
  11364 + const { event = [] } = this.DispatchInstance.contentData
  11365 + return event
  11366 + }
  11367 +
  11368 + /**
  11369 + * @description 事件映射
  11370 + */
  11371 + generatorEventMapping() {
  11372 + const event = this.eventList
  11373 + console.log(event)
  11374 + for (const item of event) {
  11375 + const { content, id: nodeId, enabled, type } = item
  11376 + if (!enabled) continue
  11377 + if (!this.eventMapping.has(nodeId)) this.eventMapping.set(nodeId, new Map())
  11378 + const temp = this.eventMapping.get(nodeId)
  11379 + temp.set(type, content)
  11380 + }
  11381 + }
  11382 +
  11383 + createGraphEventListener() {
  11384 + if (DispatchCenter.eventListenerIsExist) return
  11385 +
  11386 + const graphDblClick = this.graph.dblClick;
  11387 + this.graph.dblClick = (...args) => {
  11388 + this.handleDoubleClickEvent(...args)
  11389 + graphDblClick.apply(this.graph, args)
  11390 + }
  11391 +
  11392 +
  11393 + const graphClick = this.graph.click;
  11394 + this.graph.click = (...args) => {
  11395 + this.handleClickEvent(...args)
  11396 + graphClick.apply(this.graph, args)
  11397 + }
  11398 +
  11399 + const graphFireMouseEvent = this.graph.fireMouseEvent;
  11400 + this.graph.fireMouseEvent = (eventName, event, sender) => {
  11401 + if (eventName === mxEvent.MOUSE_DOWN) {
  11402 + this.handleMouseDownEvent(eventName, event, sender)
  11403 + }
  11404 + if (eventName === mxEvent.MOUSE_UP) {
  11405 + this.handleMouseUpEvent(eventName, event, sender)
  11406 + }
  11407 + graphFireMouseEvent.apply(this.graph, [eventName, event, sender]);
  11408 + };
  11409 +
  11410 + DispatchCenter.eventListenerIsExist = true
  11411 + }
  11412 +
11195 /** 11413 /**
11196 * @description 处理按下事件 11414 * @description 处理按下事件
11197 * @param eventName 11415 * @param eventName
@@ -11200,10 +11418,10 @@ class DispatchCenter { @@ -11200,10 +11418,10 @@ class DispatchCenter {
11200 */ 11418 */
11201 handleMouseDownEvent(eventName, event, sender) { 11419 handleMouseDownEvent(eventName, event, sender) {
11202 const { state: { cell: { id } = {} } = {} } = event 11420 const { state: { cell: { id } = {} } = {} } = event
11203 - const temp = this.nodeMapping.get(id) 11421 + const temp = this.eventMapping.get(id)
11204 if (temp && temp.has(DispatchCenter.enumEventType.DOWN)) { 11422 if (temp && temp.has(DispatchCenter.enumEventType.DOWN)) {
11205 const content = temp.get(DispatchCenter.enumEventType.DOWN) 11423 const content = temp.get(DispatchCenter.enumEventType.DOWN)
11206 - console.log('mouse down event', content) 11424 + this.sendInstruction(content.data)
11207 } 11425 }
11208 } 11426 }
11209 11427
@@ -11215,10 +11433,10 @@ class DispatchCenter { @@ -11215,10 +11433,10 @@ class DispatchCenter {
11215 */ 11433 */
11216 handleMouseUpEvent(eventName, event, sender) { 11434 handleMouseUpEvent(eventName, event, sender) {
11217 const { state: { cell: { id } = {} } = {} } = event 11435 const { state: { cell: { id } = {} } = {} } = event
11218 - const temp = this.nodeMapping.get(id) 11436 + const temp = this.eventMapping.get(id)
11219 if (temp && temp.has(DispatchCenter.enumEventType.UP)) { 11437 if (temp && temp.has(DispatchCenter.enumEventType.UP)) {
11220 const content = temp.get(DispatchCenter.enumEventType.UP) 11438 const content = temp.get(DispatchCenter.enumEventType.UP)
11221 - console.log('mouse up event', content) 11439 + this.sendInstruction(content.data)
11222 } 11440 }
11223 } 11441 }
11224 11442
@@ -11228,7 +11446,7 @@ class DispatchCenter { @@ -11228,7 +11446,7 @@ class DispatchCenter {
11228 */ 11446 */
11229 handleClickEvent(event) { 11447 handleClickEvent(event) {
11230 const { state: { cell: { id } = {} } = {} } = event 11448 const { state: { cell: { id } = {} } = {} } = event
11231 - const temp = this.nodeMapping.get(id) 11449 + const temp = this.eventMapping.get(id)
11232 if (temp && temp.has(DispatchCenter.enumEventType.SINGLE)) { 11450 if (temp && temp.has(DispatchCenter.enumEventType.SINGLE)) {
11233 const content = temp.get(DispatchCenter.enumEventType.SINGLE) 11451 const content = temp.get(DispatchCenter.enumEventType.SINGLE)
11234 const { type, value } = content 11452 const { type, value } = content
@@ -11247,7 +11465,7 @@ class DispatchCenter { @@ -11247,7 +11465,7 @@ class DispatchCenter {
11247 */ 11465 */
11248 handleDoubleClickEvent(event, cell = {}) { 11466 handleDoubleClickEvent(event, cell = {}) {
11249 const { id } = cell 11467 const { id } = cell
11250 - const temp = this.nodeMapping.get(id) 11468 + const temp = this.eventMapping.get(id)
11251 if (temp && temp.has(DispatchCenter.enumEventType.DOUBLE)) { 11469 if (temp && temp.has(DispatchCenter.enumEventType.DOUBLE)) {
11252 const content = temp.get(DispatchCenter.enumEventType.DOUBLE) 11470 const content = temp.get(DispatchCenter.enumEventType.DOUBLE)
11253 const { type, value } = content 11471 const { type, value } = content
@@ -11259,34 +11477,385 @@ class DispatchCenter { @@ -11259,34 +11477,385 @@ class DispatchCenter {
11259 } 11477 }
11260 } 11478 }
11261 11479
  11480 +
  11481 + /**
  11482 + * @description 下发指令
  11483 + * @param list
  11484 + */
  11485 + sendInstruction(list = []) {
  11486 + const queue = []
  11487 + const fn = async (way, deviceId, data) => {
  11488 + const [err, res = {}] = await to(ConfigurationNodeApi.deviceIsOnLine(deviceId))
  11489 + const { value } = res
  11490 + if (value) {
  11491 + await to(ConfigurationNodeApi.sendInstruction(way, deviceId, data))
  11492 + } else {
  11493 + UseLayUi.errorMsg('设备不在线!')
  11494 + }
  11495 + }
  11496 + for (const item of list) {
  11497 + const { deviceId, slaveDeviceId, value, way } = item
  11498 + console.log(item)
  11499 + if (!value || !deviceId) continue
  11500 + const data = {
  11501 + method: "methodThingskit",
  11502 + params: JSON.parse(value)
  11503 + }
  11504 + if (slaveDeviceId) {
  11505 + queue.push(() => {
  11506 + fn(way, slaveDeviceId, data)
  11507 + })
  11508 + } else if (deviceId) {
  11509 + queue.push(() => {
  11510 + fn(way, deviceId, data)
  11511 + })
  11512 + }
  11513 + }
  11514 +
  11515 + Promise.all(queue.map(fn => fn())).then(res => {
  11516 + console.log(res)
  11517 + })
  11518 + }
  11519 +
11262 /** 11520 /**
11263 * @description 跳转页面 11521 * @description 跳转页面
11264 */ 11522 */
11265 jumpPage(page) { 11523 jumpPage(page) {
11266 - // const page = 'ikp4NlRjQpI8WxeSibFj'  
11267 this.editorUi.handleCustomLink(`data:page/id,${ page }`) 11524 this.editorUi.handleCustomLink(`data:page/id,${ page }`)
11268 } 11525 }
  11526 +}
11269 11527
  11528 +class HandleDynamicEffect {
11270 11529
11271 /** 11530 /**
11272 - * @description 返回 DispatchCenter 实例 当contentID变化时重新创建实例  
11273 - * @param editorUi  
11274 - * @param currentPage  
11275 - * @return {*} 11531 + * @description 事件分发中心实例
  11532 + * @type {DispatchCenter}
11276 */ 11533 */
11277 - static getInstance(editorUi, currentPage = {}) {  
11278 - const { node: { id } = {} } = currentPage  
11279 - if (!id) return  
11280 - if (!DispatchCenter.instance || DispatchCenter.rawContentId !== id) {  
11281 - DispatchCenter.instance = new DispatchCenter(editorUi, currentPage)  
11282 - DispatchCenter.rawContentId = id 11534 + DispatchInstance
  11535 +
  11536 + /**
  11537 + * @description 开启的数据动效
  11538 + * @type {any[]}
  11539 + */
  11540 + enableActList
  11541 +
  11542 + /**
  11543 + * @description 动效节点映射
  11544 + * @type {Map<string, Map<string, any>>}
  11545 + */
  11546 + actNodeMapping = new Map()
  11547 +
  11548 + /**
  11549 + * @description cmdID 与 nodeID 关系映射
  11550 + * @type {Map<number, string>}
  11551 + */
  11552 + cmdIdMapping = new Map()
  11553 +
  11554 + /**
  11555 + * @description clear setInterval
  11556 + */
  11557 + cleanSetInterval
  11558 +
  11559 + static enumConst = {
  11560 + MAX: 'max',
  11561 + MIN: 'min',
  11562 + }
  11563 +
  11564 + static enumActType = {
  11565 + FLASH: 'FLASH',
  11566 + DISPLAY: 'DISPLAY',
  11567 + ROTATE: 'ROTATE'
  11568 + }
  11569 +
  11570 + static enumDisplayType = {
  11571 + SHOW: 'show',
  11572 + HIDDEN: 'hidden'
  11573 + }
  11574 +
  11575 + constructor(DispatchInstance) {
  11576 + this.DispatchInstance = DispatchInstance
  11577 + this.init()
  11578 + }
  11579 +
  11580 + init() {
  11581 + this.getEnableActList()
  11582 + this.generatorMappingRelation()
  11583 + }
  11584 +
  11585 + get graph() {
  11586 + return this.DispatchInstance.graph
  11587 + }
  11588 +
  11589 + /**
  11590 + * @description 获取已开启的数据动效
  11591 + */
  11592 + getEnableActList() {
  11593 + const { act = [] } = this.DispatchInstance.contentData
  11594 + this.enableActList = act.filter(item => item.enabled)
  11595 + }
  11596 +
  11597 + /**
  11598 + * @description 生成映射关系 && 初始化推送消息
  11599 + */
  11600 + generatorMappingRelation() {
  11601 + const tsSubCmds = []
  11602 + this.enableActList.forEach(each => {
  11603 + const { id, type, attr, deviceId } = each
  11604 +
  11605 + if (!this.actNodeMapping.has(id)) this.actNodeMapping.set(id, new Map())
  11606 + const temp = this.actNodeMapping.get(id)
  11607 + temp.set(type, each)
  11608 +
  11609 + const cmdId = this.DispatchInstance.getCmdId(id)
  11610 +
  11611 + tsSubCmds.push(this.generatorMessage(deviceId, cmdId, attr))
  11612 +
  11613 + this.subscribeEvent(cmdId, this.dispatch(type))
  11614 + })
  11615 + this.sendMsg({ tsSubCmds })
  11616 + }
  11617 +
  11618 + /**
  11619 + * @description 推送消息
  11620 + * @param msg
  11621 + */
  11622 + sendMsg(msg) {
  11623 + this.DispatchInstance.sendMessageToGetRealTimeData(msg)
  11624 + }
  11625 +
  11626 + /**
  11627 + * @description 订阅事件 绑定回调
  11628 + * @param eventName
  11629 + * @param callback
  11630 + */
  11631 + subscribeEvent(eventName, callback) {
  11632 + this.DispatchInstance.eventBus.on(eventName, callback)
  11633 + }
  11634 +
  11635 + /**
  11636 + * @description 创建消息
  11637 + * @param deviceId
  11638 + * @param cmdId
  11639 + * @param attr
  11640 + * @return {{cmdId, entityType: string, keys, scope: string, entityId}}
  11641 + */
  11642 + generatorMessage(deviceId, cmdId, attr) {
  11643 + return {
  11644 + entityType: "DEVICE",
  11645 + entityId: deviceId,
  11646 + scope: "LATEST_TELEMETRY",
  11647 + cmdId,
  11648 + keys: attr
11283 } 11649 }
  11650 + }
11284 11651
11285 - return DispatchCenter.instance 11652 + /**
  11653 + * @description 分发事件
  11654 + * @param type
  11655 + * @return Function
  11656 + */
  11657 + dispatch(type) {
  11658 + let invoke = () => {
  11659 + }
  11660 + switch (type) {
  11661 + case HandleDynamicEffect.enumActType.ROTATE:
  11662 + // invoke = this.rotate.bind(this)
  11663 + break
  11664 + case HandleDynamicEffect.enumActType.DISPLAY:
  11665 + invoke = this.display.bind(this)
  11666 + break
  11667 + case HandleDynamicEffect.enumActType.FLASH:
  11668 + break
  11669 + }
  11670 + return invoke
  11671 + }
  11672 +
  11673 + /**
  11674 + * @description 旋转
  11675 + * @param message
  11676 + * @param data
  11677 + */
  11678 + rotate(data) {
  11679 + const { subscriptionId } = data
  11680 + console.log(data)
  11681 + const node = this.getNodeByCmdId(subscriptionId)
  11682 + let deg = 0
  11683 + this.cleanSetInterval = RAFSetInterval(() => {
  11684 + // if (deg === 360) deg = 0
  11685 + // deg += 20
  11686 + // let style = node.getStyle()
  11687 + // const reg = /rotation=(-?)\w+(;?)/g
  11688 + // style = style.replace(reg, `rotation=${ deg }`)
  11689 + // // node.setStyle(style)
  11690 + // console.log(node)
  11691 + // this.graph.getModel().beginUpdate()
  11692 + // try {
  11693 + // node.setStyle(style)
  11694 + // // this.graph.refresh();
  11695 + // } finally {
  11696 + // this.graph.getModel().endUpdate()
  11697 + // }
  11698 + this.DispatchInstance.updatePage(() => {
  11699 + if (deg === 360) deg = 0
  11700 + deg += 20
  11701 + let style = node.getStyle()
  11702 + const reg = /rotation=(-?)\w+(;?)/g
  11703 + style = style.replace(reg, `rotation=${ deg }`)
  11704 + node.setStyle(style)
  11705 + this.graph.updateCellStyles(style, node)
  11706 + })
  11707 + }, 100)
  11708 + }
  11709 +
  11710 + /**
  11711 + * @description 显示与隐藏
  11712 + * @param _
  11713 + * @param message
  11714 + */
  11715 + display(message) {
  11716 + const { subscriptionId, data = {} } = message
  11717 + const { flag, condition } = this.validate(subscriptionId, HandleDynamicEffect.enumActType.DISPLAY, data)
  11718 + if (!flag) return
  11719 + const node = this.getNodeByCmdId(subscriptionId)
  11720 + let isShow = false
  11721 + if (node.visible && condition.type === HandleDynamicEffect.enumDisplayType.SHOW) {
  11722 + return
  11723 + } else if (condition.type === HandleDynamicEffect.enumDisplayType.SHOW) {
  11724 + isShow = true
  11725 + } else if (condition.type === HandleDynamicEffect.enumDisplayType.HIDDEN) {
  11726 + isShow = false
  11727 + }
  11728 + this.DispatchInstance.updatePage(() => {
  11729 + node.setVisible(isShow)
  11730 + })
  11731 + }
  11732 +
  11733 + /**
  11734 + * @description 验证是否满足条件列表中的任意一条
  11735 + * @param subscriptionId
  11736 + * @param type
  11737 + * @param value
  11738 + * @return {{flag: boolean, condition: {}}}
  11739 + */
  11740 + validate(subscriptionId, type, value) {
  11741 + const { condition = [], attr } = this.getBindData(subscriptionId, type)
  11742 + const result = { condition: {}, flag: false }
  11743 + for (let i = 0; i < condition.length; i++) {
  11744 + const { min, max } = condition[i]
  11745 + const [timespan, realValue] = value[attr][0]
  11746 + result.flag = this.isExistInArea(min, max, realValue)
  11747 + if (result.flag) {
  11748 + result.condition = condition[i]
  11749 + break
  11750 + }
  11751 + }
  11752 + return result
  11753 + }
  11754 +
  11755 + /**
  11756 + * @description 判断一个数是否在区间范围内
  11757 + * @param min 最小值
  11758 + * @param max 最大值
  11759 + * @param value 值
  11760 + * @return {boolean}
  11761 + */
  11762 + isExistInArea(min, max, value) {
  11763 + return Number(value) >= Number(min) && Number(value) <= Number(max)
  11764 + }
  11765 +
  11766 + /**
  11767 + * @description 获取绑定的数据
  11768 + * @param subscriptionId
  11769 + * @param actionType
  11770 + * @return {*}
  11771 + */
  11772 + getBindData(subscriptionId, actionType) {
  11773 + const nodeId = this.getNodeIdByCmdId(subscriptionId)
  11774 + const temp = this.actNodeMapping.get(nodeId)
  11775 + return temp.get(actionType)
  11776 + }
  11777 +
  11778 + /**
  11779 + * @description 通过cmdID获取节点id
  11780 + * @param subscriptionId
  11781 + * @return {string}
  11782 + */
  11783 + getNodeIdByCmdId(subscriptionId) {
  11784 + return this.DispatchInstance.cmdIdMapping.get(subscriptionId)
11286 } 11785 }
11287 11786
  11787 + /**
  11788 + * @description 通过cmdID 获取节点
  11789 + * @param subscriptionId
  11790 + * @return {*}
  11791 + */
  11792 + getNodeByCmdId(subscriptionId) {
  11793 + const nodeId = this.getNodeIdByCmdId(subscriptionId)
  11794 + return this.DispatchInstance.contentAllCell.find(item => item.id === nodeId)
  11795 + }
  11796 +
  11797 +}
  11798 +
  11799 +class RAFSetTimeoutImp {
  11800 + constructor(callback, time = 0) {
  11801 + this.callback = callback;
  11802 + this.time = time;
  11803 + this.now = Date.now;
  11804 + this.current = this.now();
  11805 + this.old = this.now();
  11806 + const fn = () => {
  11807 + if (this.current - this.old > this.time) {
  11808 + this.callback();
  11809 + this.old = this.now();
  11810 + this.clear();
  11811 + return;
  11812 + }
  11813 + this.current = this.now();
  11814 + this.instance = window.requestAnimationFrame(fn);
  11815 + };
  11816 + this.instance = window.requestAnimationFrame(fn);
  11817 + }
  11818 +
  11819 + clear() {
  11820 + window.cancelAnimationFrame(this.instance);
  11821 + this.instance = null;
  11822 + }
  11823 +};
  11824 +
  11825 +function RAFSetTimeout(callback, time) {
  11826 + const instance = new RAFSetTimeoutImp(callback, time);
  11827 + return instance.clear.bind(instance);
  11828 +}
  11829 +
  11830 +class RAFSetIntervalImp {
  11831 + constructor(callback, time = 0) {
  11832 + this.callback = callback;
  11833 + this.time = time;
  11834 + this.now = Date.now;
  11835 + this.current = this.now();
  11836 + this.old = this.now();
  11837 + const fn = () => {
  11838 + if (this.current - this.old > this.time) {
  11839 + this.callback();
  11840 + this.old = this.now();
  11841 + }
  11842 + this.current = this.now();
  11843 + this.instance = window.requestAnimationFrame(fn);
  11844 + };
  11845 + this.instance = window.requestAnimationFrame(fn);
  11846 + }
  11847 +
  11848 + clear() {
  11849 + window.cancelAnimationFrame(this.instance);
  11850 + }
  11851 +};
  11852 +
  11853 +function RAFSetInterval(callback, time) {
  11854 + const instance = new RAFSetIntervalImp(callback, time);
  11855 + return instance.clear.bind(instance);
11288 } 11856 }
11289 11857
  11858 +
11290 function globalInit() { 11859 function globalInit() {
11291 init() 11860 init()
11292 11861
@@ -11295,14 +11864,14 @@ function globalInit() { @@ -11295,14 +11864,14 @@ function globalInit() {
11295 } 11864 }
11296 11865
11297 function initRealTime() { 11866 function initRealTime() {
11298 - setInterval(() => { 11867 + RAFSetInterval(() => {
11299 const allTimeNode = document.querySelectorAll('.thingKit-component__real-time .real-time__now') 11868 const allTimeNode = document.querySelectorAll('.thingKit-component__real-time .real-time__now')
11300 for (const time of allTimeNode) { 11869 for (const time of allTimeNode) {
11301 const date = new Date() 11870 const date = new Date()
11302 - time.innerHTML = `${ date.getHours() }:${ date.getMinutes() < 10 ? '0' : '' }${ date.getMinutes() }:${ date.getSeconds() < 10 ? '0' : '' }${ date.getSeconds() }` 11871 + time.innerHTML = `${ date.getHours() < 10 ? '0' : '' }${ date.getHours() }:${ date.getMinutes() < 10 ? '0' : '' }${ date.getMinutes() }:${ date.getSeconds() < 10 ? '0' : '' }${ date.getSeconds() }`
11303 } 11872 }
11304 }, 1000) 11873 }, 1000)
11305 } 11874 }
11306 } 11875 }
11307 11876
11308 -globalInit() 11877 +globalInit()
@@ -30,7 +30,9 @@ Menus.prototype.defaultFontSize = '12'; @@ -30,7 +30,9 @@ Menus.prototype.defaultFontSize = '12';
30 /** 30 /**
31 * Sets the default font size. 31 * Sets the default font size.
32 */ 32 */
33 -Menus.prototype.defaultMenuItems = ['file', 'edit', 'view', 'arrange', 'extras', 'help']; 33 +// Menus.prototype.defaultMenuItems = ['file', 'edit', 'view', 'arrange', 'extras', 'help'];
  34 +// TODO 工具栏 文件选项隐藏
  35 +Menus.prototype.defaultMenuItems = ['edit', 'view', 'arrange', 'extras', 'help'];
34 36
35 /** 37 /**
36 * Adds the label menu items to the given menu and parent. 38 * Adds the label menu items to the given menu and parent.