Commit 9f945cdfe99a7f908465575e4670768c1a21364b

Authored by xp.Huang
2 parents b22c9db1 5a6f1a86

Merge branch 'feat/new-component-alarm-table' into 'main_dev'

Feat/new component alarm table

See merge request yunteng/thingskit-scada!72
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 5
6 <head> 6 <head>
7 <!-- <title>Flowchart Maker &amp; Online Diagram Software</title>--> 7 <!-- <title>Flowchart Maker &amp; Online Diagram Software</title>-->
8 - <title>thingskit 云组态</title> 8 + <title>云组态</title>
9 <meta charset="utf-8"> 9 <meta charset="utf-8">
10 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 10 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
11 <meta name="Description" 11 <meta name="Description"
@@ -22,26 +22,26 @@ @@ -22,26 +22,26 @@
22 <meta name="mobile-web-app-capable" content="yes"> 22 <meta name="mobile-web-app-capable" content="yes">
23 <meta name="theme-color" content="#d89000"> 23 <meta name="theme-color" content="#d89000">
24 24
25 - <link rel="stylesheet" href="./js/plugin/layui/css/layui.css?v=1681890411146"> 25 + <link rel="stylesheet" href="./js/plugin/layui/css/layui.css?v=1686710985762">
26 26
27 <!-- load configure file --> 27 <!-- load configure file -->
28 - <script src="./js/config/config.js?v=1681890411146"></script> 28 + <script src="./js/config/config.js?v=1686710985762"></script>
29 29
30 <!-- crypto-js --> 30 <!-- crypto-js -->
31 - <script src="./js/plugin/crypto-js/crypto-js.js?v=1681890411146"></script> 31 + <script src="./js/plugin/crypto-js/crypto-js.js?v=1686710985762"></script>
32 32
33 <!-- storage persistent --> 33 <!-- storage persistent -->
34 - <script src="./js/const/persistentStorage.js?v=1681890411146"></script> 34 + <script src="./js/const/persistentStorage.js?v=1686710985762"></script>
35 <!-- Global const --> 35 <!-- Global const -->
36 - <script src="./js/const/const.js?v=1681890411146"></script> 36 + <script src="./js/const/const.js?v=1686710985762"></script>
37 37
38 <!-- Axios --> 38 <!-- Axios -->
39 - <script src="./js/plugin/axios/axios.min.js?v=1681890411146"></script>  
40 - <script src="./js/plugin/axios/DefHttp.js?v=1681890411146"></script>  
41 - <script src="./js/api/index.js?v=1681890411146"></script> 39 + <script src="./js/plugin/axios/axios.min.js?v=1686710985762"></script>
  40 + <script src="./js/plugin/axios/DefHttp.js?v=1686710985762"></script>
  41 + <script src="./js/api/index.js?v=1686710985762"></script>
42 42
43 <!-- load script --> 43 <!-- load script -->
44 - <script src="./js/config/loadScript.js?v=1681890411146"></script> 44 + <script src="./js/config/loadScript.js?v=1686710985762"></script>
45 45
46 <!-- act editor --> 46 <!-- act editor -->
47 <!-- <script src="https://oss.yuntengcloud.com/iotdocs/thingskit-scada/ace.js"></script> --> 47 <!-- <script src="https://oss.yuntengcloud.com/iotdocs/thingskit-scada/ace.js"></script> -->
@@ -54,7 +54,7 @@ @@ -54,7 +54,7 @@
54 <!-- <script src="https://vjs.zencdn.net/7.10.2/video.min.js"></script> --> 54 <!-- <script src="https://vjs.zencdn.net/7.10.2/video.min.js"></script> -->
55 <!-- <script src="https://oss.yuntengcloud.com/iotdocs/thingskit-scada/video.min.js"></script> --> 55 <!-- <script src="https://oss.yuntengcloud.com/iotdocs/thingskit-scada/video.min.js"></script> -->
56 56
57 - <script src="./js/plugin/layui/layui.js?v=1681890411146"></script> 57 + <script src="./js/plugin/layui/layui.js?v=1686710985762"></script>
58 <!-- <link rel="stylesheet" href="https://cdnjs.loli.net/ajax/libs/layui/2.6.8/css/layui.min.css" 58 <!-- <link rel="stylesheet" href="https://cdnjs.loli.net/ajax/libs/layui/2.6.8/css/layui.min.css"
59 integrity="sha512-iQBJbsNHXUcgEIgWThd2dr8tOdKPvICwqjPEZYY81z3eMya44A5MiAqfWSCh+Ee1YzNYkdrI982Qhwgr8LEYOQ==" 59 integrity="sha512-iQBJbsNHXUcgEIgWThd2dr8tOdKPvICwqjPEZYY81z3eMya44A5MiAqfWSCh+Ee1YzNYkdrI982Qhwgr8LEYOQ=="
60 crossorigin="anonymous" referrerpolicy="no-referrer" /> 60 crossorigin="anonymous" referrerpolicy="no-referrer" />
@@ -63,7 +63,7 @@ @@ -63,7 +63,7 @@
63 crossorigin="anonymous" referrerpolicy="no-referrer"></script> --> 63 crossorigin="anonymous" referrerpolicy="no-referrer"></script> -->
64 64
65 <!-- 引入修改样式 --> 65 <!-- 引入修改样式 -->
66 - <link rel="stylesheet" href="./styles/formatChange.css?v=1681890411146"> 66 + <link rel="stylesheet" href="./styles/formatChange.css?v=1686710985762">
67 67
68 <script type="text/javascript"> 68 <script type="text/javascript">
69 /** 69 /**
@@ -306,7 +306,7 @@ @@ -306,7 +306,7 @@
306 var supportedDomain = (hostName.substring(hostName.length - 8, hostName.length) === '.draw.io') || 306 var supportedDomain = (hostName.substring(hostName.length - 8, hostName.length) === '.draw.io') ||
307 (hostName.substring(hostName.length - 13, hostName.length) === '.diagrams.net'); 307 (hostName.substring(hostName.length - 13, hostName.length) === '.diagrams.net');
308 308
309 - const releaseVersion = '1681890411146' 309 + const releaseVersion = '1686710985762'
310 const appMinSrc = Enable_OSS ? `${OSS_Prefix}app.min.js?v=${releaseVersion}` : `js/app.min.js?v=${releaseVersion}` 310 const appMinSrc = Enable_OSS ? `${OSS_Prefix}app.min.js?v=${releaseVersion}` : `js/app.min.js?v=${releaseVersion}`
311 function loadAppJS() { 311 function loadAppJS() {
312 mxscript(appMinSrc, function () { 312 mxscript(appMinSrc, function () {
@@ -591,7 +591,6 @@ @@ -591,7 +591,6 @@
591 <script> 591 <script>
592 592
593 function isMobile() { 593 function isMobile() {
594 - // http://192.168.10.106:8083/thingskit-drawio/?configurationId=5c683cb0-48fb-4062-aabf-a5093eea0446&userId=1262f76c-ec5d-4091-85a1-52c552915d4e&lightbox=1  
595 var urlParams = (function () { 594 var urlParams = (function () {
596 var result = new Object(); 595 var result = new Object();
597 var params = window.location.search.slice(1).split('&'); 596 var params = window.location.search.slice(1).split('&');
@@ -649,7 +648,7 @@ @@ -649,7 +648,7 @@
649 left: 'center', 648 left: 'center',
650 top: 'center', 649 top: 'center',
651 style: { 650 style: {
652 - text: platfromInfo.name || 'ThingsKit Scada', 651 + text: platfromInfo.name || 'Scada',
653 fontSize: isMobile() ? 20 : 70, 652 fontSize: isMobile() ? 20 : 70,
654 fontWeight: 'bold', 653 fontWeight: 'bold',
655 lineDash: [0, 200], 654 lineDash: [0, 200],
@@ -207,7 +207,7 @@ class ConfigurationNodeApi { @@ -207,7 +207,7 @@ class ConfigurationNodeApi {
207 * @returns 207 * @returns
208 */ 208 */
209 static getDictionaryValue(dictCode) { 209 static getDictionaryValue(dictCode) {
210 - return defHttp.post('/yt/dict_item/find', {dictCode}) 210 + return defHttp.post('/yt/dict_item/find', { dictCode })
211 } 211 }
212 212
213 /** 213 /**
@@ -227,4 +227,24 @@ class ConfigurationNodeApi { @@ -227,4 +227,24 @@ class ConfigurationNodeApi {
227 static getThingsModelServiceByDeviceProfileId(id) { 227 static getThingsModelServiceByDeviceProfileId(id) {
228 return defHttp.get('/yt/things_model/get_services/' + id) 228 return defHttp.get('/yt/things_model/get_services/' + id)
229 } 229 }
  230 +
  231 + /**
  232 + *
  233 + * @typedef {object} AlarmListRequestParamsType
  234 + * @property { number } page
  235 + * @property { number } pageSize
  236 + * @property { string } status
  237 + * @property { string } alarmType
  238 + * @property { string } severity
  239 + * @property { string[] } deviceIds
  240 + * @property { string } organizationId
  241 + * @property { string } deviceName
  242 + * @property { string } startTime
  243 + * @property { string } endTime
  244 + * @param {AlarmListRequestParamsType} params
  245 + * @returns
  246 + */
  247 + static getAlarmList(params) {
  248 + return defHttp.post('/yt/alarm/configuration/page', params)
  249 + }
230 } 250 }
@@ -4094,6 +4094,7 @@ App.prototype.loadFile = function (id, sameWindow, file, success, force) { @@ -4094,6 +4094,7 @@ App.prototype.loadFile = function (id, sameWindow, file, success, force) {
4094 return pageSizeControl.apply(this, arguments) 4094 return pageSizeControl.apply(this, arguments)
4095 } 4095 }
4096 Editor.configurationName = response.configurationName + ".drawio"; 4096 Editor.configurationName = response.configurationName + ".drawio";
  4097 + document.title = response.configurationName
4097 if (response.configurationContentList.length > 0) { 4098 if (response.configurationContentList.length > 0) {
4098 response.configurationContentList.forEach((item) => { 4099 response.configurationContentList.forEach((item) => {
4099 Editor.configurationContentId = item.id; 4100 Editor.configurationContentId = item.id;
@@ -277,7 +277,12 @@ @@ -277,7 +277,12 @@
277 /** 277 /**
278 * @description 流量计 278 * @description 流量计
279 */ 279 */
280 - FLOWMETER: 'flowmeter' 280 + FLOWMETER: 'flowmeter',
  281 +
  282 + /**
  283 + * @description 告警列表
  284 + */
  285 + ALARM_LIST: 'alarmList'
281 } 286 }
282 287
283 Sidebar.prototype.enumComponentTypeValue = { 288 Sidebar.prototype.enumComponentTypeValue = {
@@ -373,7 +378,12 @@ @@ -373,7 +378,12 @@
373 /** 378 /**
374 * @description 流量计 379 * @description 流量计
375 */ 380 */
376 - FLOWMETER_PANEL: 'flowmeter' 381 + FLOWMETER_PANEL: 'flowmeter',
  382 +
  383 + /**
  384 + * @description 告警列表
  385 + */
  386 + ALARM_LIST_PANEL: 'alarmListPanel'
377 } 387 }
378 388
379 /** 389 /**
@@ -730,8 +740,8 @@ @@ -730,8 +740,8 @@
730 //更多图形,显示出来的的标题跟id,同时包括图片 740 //更多图形,显示出来的的标题跟id,同时包括图片
731 741
732 // TODO thingsKit 设置数据绑定展示面板 742 // TODO thingsKit 设置数据绑定展示面板
733 - const { LINE_CHART_EXPAND, BAR_CHART_EXPAND, DASHBOARD_CHART_EXPAND, DYNAMIC_EFFECT, DATA_SOURCE, VAR_IMAGE, INTERACTION, VIDEO: VIDEO_PANEL, SWITCH_STATE_SETTING, ONLY_SINGLE_EVENT, RUNNING_AND_STOP, FLOWMETER_PANEL } = this.enumPermissionPanel  
734 - const { LINE, LINE_CHART, REAL_TIME, TITLE, VARIABLE, DEFAULT, BAR_CHART, VIDEO, SWITCH, PARAMS_SETTING_BUTTON, DASHBOARD_CHART, IMAGE, FLOWMETER } = this.enumComponentType 743 + const { LINE_CHART_EXPAND, BAR_CHART_EXPAND, DASHBOARD_CHART_EXPAND, DYNAMIC_EFFECT, DATA_SOURCE, VAR_IMAGE, INTERACTION, VIDEO: VIDEO_PANEL, SWITCH_STATE_SETTING, ONLY_SINGLE_EVENT, RUNNING_AND_STOP, FLOWMETER_PANEL, ALARM_LIST_PANEL } = this.enumPermissionPanel
  744 + const { LINE, LINE_CHART, REAL_TIME, TITLE, VARIABLE, DEFAULT, BAR_CHART, VIDEO, SWITCH, PARAMS_SETTING_BUTTON, DASHBOARD_CHART, IMAGE, FLOWMETER, ALARM_LIST } = this.enumComponentType
735 this.setComponentPermission(LINE, [RUNNING_AND_STOP, DYNAMIC_EFFECT]) 745 this.setComponentPermission(LINE, [RUNNING_AND_STOP, DYNAMIC_EFFECT])
736 this.setComponentPermission(DEFAULT, [DYNAMIC_EFFECT]) 746 this.setComponentPermission(DEFAULT, [DYNAMIC_EFFECT])
737 this.setComponentPermission(REAL_TIME, [DYNAMIC_EFFECT]) 747 this.setComponentPermission(REAL_TIME, [DYNAMIC_EFFECT])
@@ -746,6 +756,7 @@ @@ -746,6 +756,7 @@
746 this.setComponentPermission(PARAMS_SETTING_BUTTON, [DATA_SOURCE, ONLY_SINGLE_EVENT]) 756 this.setComponentPermission(PARAMS_SETTING_BUTTON, [DATA_SOURCE, ONLY_SINGLE_EVENT])
747 this.setComponentPermission(IMAGE, [DATA_SOURCE]) 757 this.setComponentPermission(IMAGE, [DATA_SOURCE])
748 this.setComponentPermission(FLOWMETER, [DATA_SOURCE, FLOWMETER_PANEL]) 758 this.setComponentPermission(FLOWMETER, [DATA_SOURCE, FLOWMETER_PANEL])
  759 + this.setComponentPermission(ALARM_LIST, [ALARM_LIST_PANEL])
749 760
750 var thingskitEntries = [ 761 var thingskitEntries = [
751 { title: mxResources.get('general'), id: 'general', image: IMAGE_PATH + '/sidebar-general.png' }, 762 { title: mxResources.get('general'), id: 'general', image: IMAGE_PATH + '/sidebar-general.png' },
@@ -65,6 +65,17 @@ @@ -65,6 +65,17 @@
65 this.setCellAttributes(cell, { [basicAttr.COMPONENT_TYPE]: componentType.IMAGE }) 65 this.setCellAttributes(cell, { [basicAttr.COMPONENT_TYPE]: componentType.IMAGE })
66 return this.createVertexTemplateFromCells([cell], cell.geometry.width, cell.geometry.height, '图片'); 66 return this.createVertexTemplateFromCells([cell], cell.geometry.width, cell.geometry.height, '图片');
67 })), 67 })),
  68 +
  69 + this.addEntry(this.getTagsForStencil(gn, '告警列表', 'basic').join(' '), mxUtils.bind(this, function () {
  70 + const id = AlarmListComponent.genId()
  71 + const template = AlarmListComponent.createAlarmList(null, 280, 200, id)
  72 + const cell = new mxCell(template, new mxGeometry(0, 0, 280, 200), 'text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;overflow=hidden;');
  73 + cell.setVertex(true)
  74 + const { UUID } = AlarmListComponent.getAttributeKeys()
  75 + this.setCellAttributes(cell, { [basicAttr.COMPONENT_TYPE]: componentType.ALARM_LIST, [UUID]: id })
  76 + console.log(cell)
  77 + return this.createVertexTemplateFromCells([cell], cell.geometry.width, cell.geometry.height, '告警列表');
  78 + })),
68 ]; 79 ];
69 80
70 this.addPaletteFunctions(dt, '基础元件', true, fns); 81 this.addPaletteFunctions(dt, '基础元件', true, fns);
@@ -77,6 +88,13 @@ @@ -77,6 +88,13 @@
77 return cell.getAttribute(basicAttr.COMPONENT_TYPE) === componentType.VIDEO 88 return cell.getAttribute(basicAttr.COMPONENT_TYPE) === componentType.VIDEO
78 } 89 }
79 90
  91 +
  92 + Sidebar.prototype.isAlarmList = function (cell) {
  93 + const basicAttr = Sidebar.prototype.enumCellBasicAttribute
  94 + const componentType = Sidebar.prototype.enumComponentType
  95 + return cell.getAttribute(basicAttr.COMPONENT_TYPE) === componentType.ALARM_LIST
  96 + }
  97 +
80 /** 98 /**
81 * @description charts cell发生resize时改变charts size 99 * @description charts cell发生resize时改变charts size
82 * @type {Function} 100 * @type {Function}
@@ -87,6 +105,12 @@ @@ -87,6 +105,12 @@
87 const { width, height } = rect 105 const { width, height } = rect
88 cell.setAttribute('label', createVideoTemplate(width, height)) 106 cell.setAttribute('label', createVideoTemplate(width, height))
89 } 107 }
  108 +
  109 + if (AlarmListComponent.isAlarmList(cell)) {
  110 + const { width, height } = rect
  111 +
  112 + cell.setAttribute('label', AlarmListComponent.createAlarmList(null, width, height))
  113 + }
90 cellResized.apply(this, arguments) 114 cellResized.apply(this, arguments)
91 } 115 }
92 116
@@ -128,7 +152,7 @@ @@ -128,7 +152,7 @@
128 const allDateNode = document.querySelectorAll('.thingKit-component__real-time .real-time__date') 152 const allDateNode = document.querySelectorAll('.thingKit-component__real-time .real-time__date')
129 for (const time of allTimeNode) { 153 for (const time of allTimeNode) {
130 const date = new Date() 154 const date = new Date()
131 - time.innerHTML = `${date.getHours() < 10 ? '0' : ''}${date.getHours()}:${date.getMinutes() < 10 ? '0' : ''}${date.getMinutes()}:${date.getSeconds() < 10 ? '0' : ''}${date.getSeconds()}` 155 + time.innerHTML = [date.getHours(), date.getMinutes(), date.getSeconds()].map(item => item.toString().padStart(2, 0)).join(':')
132 } 156 }
133 157
134 for (const date of allDateNode) { 158 for (const date of allDateNode) {
@@ -138,4 +162,123 @@ @@ -138,4 +162,123 @@
138 } 162 }
139 163
140 initRealTimeComponent() 164 initRealTimeComponent()
  165 +
141 })(); 166 })();
  167 +
  168 +
  169 +function AlarmListComponent() {
  170 +
  171 +}
  172 +
  173 +/**
  174 + *
  175 + * @param {{deviceName: string, status: string, startTs: string}[]} list
  176 + * @param {number} width
  177 + * @param {number} height
  178 + * @param {string} id
  179 + * @returns
  180 + */
  181 +AlarmListComponent.createAlarmList = function (list, width = 280, height = 200, id) {
  182 +
  183 + list = list || Array.from({ length: 10 }, ((_, index) => ({
  184 + deviceName: `示例设备${index + 1}`, startTs: Date.now(), status: [
  185 + "CLEARED_UNACK",
  186 + "ACTIVE_UNACK",
  187 + "CLEARED_ACK",
  188 + "ACTIVE_ACK"
  189 + ][index % 4]
  190 + })))
  191 +
  192 + id = id || AlarmListComponent.genId()
  193 +
  194 + var template = `
  195 + <div id="${id}" class="alarm-list" style="overflow-y: auto; overflow-x: hidden; width: ${width}px; height: ${height}px;">
  196 + <div class="list-wrapper" style="font-size: 12px;" data-auto-scroll>
  197 + ${AlarmListComponent.createAlarmItem(list)}
  198 + </div>
  199 + </div>
  200 + `
  201 + return template.replace(/\n/g, '')
  202 +}
  203 +
  204 +/**
  205 + *
  206 + * @param {{deviceName: string, status: string, startTs: string}[] | {deviceName: string, status: string, startTs: string}} record
  207 + * @returns
  208 + */
  209 +AlarmListComponent.createAlarmItem = function (record) {
  210 + if (record && !Array.isArray(record)) {
  211 + record = [record]
  212 + }
  213 +
  214 + var itemHeight = 50
  215 +
  216 + function formatTime(time) {
  217 + try {
  218 + var date = new Date(time)
  219 + var year = date.getFullYear()
  220 + var month = date.getMonth() + 1
  221 + var day = date.getDate()
  222 + var hour = date.getHours()
  223 + var minute = date.getMinutes()
  224 + var second = date.getSeconds()
  225 + return `${year}-${month.toString().padStart(2, 0)}-${day.toString().padStart(2, 0)} ${hour.toString().padStart(2, 0)}:${minute.toString().padStart(2, 0)}:${second.toString().padStart(2, 0)}`
  226 + } catch (error) {
  227 + return '暂无时间 '
  228 + }
  229 + }
  230 +
  231 + return (record || []).map(item => {
  232 + var { deviceName, status, startTs } = item || {}
  233 +
  234 + var stateStyle = {
  235 + CLEARED_UNACK: 'color: #cf1322;background: #fff1f0;border-color: #ffa39e;',
  236 + ACTIVE_UNACK: 'color: #d46b08;background: #fff7e6;border-color: #ffd591;',
  237 + CLEARED_ACK: 'color: #08979c;background: #e6fffb;border-color: #87e8de;',
  238 + ACTIVE_ACK: 'color: #389e0d;background: #f6ffed;border-color: #b7eb8f;',
  239 + }
  240 +
  241 + var stateName = {
  242 + CLEARED_UNACK: '清除未确认',
  243 + ACTIVE_UNACK: '激活未确认',
  244 + CLEARED_ACK: '清除已确认',
  245 + ACTIVE_ACK: '激活已确认',
  246 + }
  247 +
  248 + var template = `
  249 + <div class="alarm-list-item" style="height: ${itemHeight}px; box-sizing: border-box; display: flex; flex-direction: column; justify-content: center; border-bottom: 1px solid black; text-align: left; min-width: 280px; width: 100%;">
  250 + <div style="padding: 0 10px;">
  251 + <span style="margin-right: 5px;">设备:</span>
  252 + <span>${deviceName}</span>
  253 + </div>
  254 + <div style="padding: 5px 10px;">
  255 + <span style="margin-right: 5px;">时间:</span>
  256 + <span>${formatTime(startTs)}</span>
  257 + <span style="padding: 5px; border-radius: 5px; margin-left: 5px; border: 1px solid; font-size: 12px; ${stateStyle[status]}">${stateName[status]}</span>
  258 + </div>
  259 + </div>`
  260 + return template
  261 + }).join('').replace(/\n/g, '')
  262 +}
  263 +
  264 +AlarmListComponent.genId = function () {
  265 + return `alarm-list-${Number(Math.random().toString().substring(2)).toString(16)}`
  266 +}
  267 +
  268 +AlarmListComponent.isAlarmList = function (cell) {
  269 + const basicAttr = Sidebar.prototype.enumCellBasicAttribute
  270 + const componentType = Sidebar.prototype.enumComponentType
  271 + return cell.getAttribute(basicAttr.COMPONENT_TYPE) === componentType.ALARM_LIST
  272 +}
  273 +
  274 +AlarmListComponent.getAttributeKeys = function () {
  275 + return {
  276 + UUID: 'uuid',
  277 + }
  278 +}
  279 +
  280 +AlarmListComponent.setAutoScroll = function (cell) {
  281 + // RAFSetInterval(() => {
  282 + // console.log(cell)
  283 + // }, 2000)
  284 +}
@@ -2294,10 +2294,15 @@ EditorUi.prototype.initCanvas = function() @@ -2294,10 +2294,15 @@ EditorUi.prototype.initCanvas = function()
2294 var layout = this.graph.getPageLayout(); 2294 var layout = this.graph.getPageLayout();
2295 var page = this.graph.getPageSize(); 2295 var page = this.graph.getPageSize();
2296 2296
2297 - return new mxRectangle(this.scale * (this.translate.x + layout.x * page.width),  
2298 - this.scale * (this.translate.y + layout.y * page.height),  
2299 - this.scale * layout.width * page.width,  
2300 - this.scale * layout.height * page.height); 2297 + // TODO thingsKit 固定页面尺寸 超出边界后隐藏
  2298 + return new mxRectangle(this.scale * (this.translate.x),
  2299 + this.scale * (this.translate.y),
  2300 + this.scale * page.width,
  2301 + this.scale * page.height)
  2302 + // return new mxRectangle(this.scale * (this.translate.x + layout.x * page.width),
  2303 + // this.scale * (this.translate.y + layout.y * page.height),
  2304 + // this.scale * layout.width * page.width,
  2305 + // this.scale * layout.height * page.height);
2301 }; 2306 };
2302 2307
2303 graph.getPreferredPageSize = function(bounds, width, height) 2308 graph.getPreferredPageSize = function(bounds, width, height)
@@ -3383,9 +3388,25 @@ EditorUi.prototype.lightboxFit = function(maxHeight) @@ -3383,9 +3388,25 @@ EditorUi.prototype.lightboxFit = function(maxHeight)
3383 // LATER: Use initial graph bounds to avoid rounding errors 3388 // LATER: Use initial graph bounds to avoid rounding errors
3384 this.editor.graph.maxFitScale = this.lightboxMaxFitScale; 3389 this.editor.graph.maxFitScale = this.lightboxMaxFitScale;
3385 this.editor.graph.fit(border, null, null, null, null, null, maxHeight); 3390 this.editor.graph.fit(border, null, null, null, null, null, maxHeight);
3386 - this.editor.graph.maxFitScale = null; 3391 + // this.editor.graph.maxFitScale = null;
3387 // TODO thingsKit lightbox 默认缩放为1 3392 // TODO thingsKit lightbox 默认缩放为1
3388 - this.editor.graph.view.setScale(1); 3393 + // console.log(this.editor.graph.view)
  3394 + // this.editor.graph.view.setScale(1);
  3395 + /// TODO thingsKit 设置内容最大化
  3396 + var margin = 2;
  3397 + var max = 3;
  3398 + var graph = this.editor.graph
  3399 +
  3400 + var bounds = graph.getGraphBounds();
  3401 + var cw = graph.container.clientWidth - margin;
  3402 + var ch = graph.container.clientHeight - margin;
  3403 + var w = bounds.width / graph.view.scale;
  3404 + var h = bounds.height / graph.view.scale;
  3405 + var s = Math.min(max, Math.min(cw / w, ch / h));
  3406 +
  3407 + graph.view.scaleAndTranslate(s,
  3408 + (margin + cw - w * s) / (2 * s) - bounds.x / graph.view.scale,
  3409 + (margin + ch - h * s) / (2 * s) - bounds.y / graph.view.scale);
3389 } 3410 }
3390 }; 3411 };
3391 3412
@@ -4903,8 +4903,8 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -4903,8 +4903,8 @@ DataFormatPanel.prototype.addDataFont = function (container) {
4903 const ss = ui.getSelectionState(); 4903 const ss = ui.getSelectionState();
4904 const vertices = ss.vertices || [] 4904 const vertices = ss.vertices || []
4905 const sidebarInstance = ui.sidebar 4905 const sidebarInstance = ui.sidebar
4906 - console.log(vertices)  
4907 - console.log(ui) 4906 + // console.log(vertices)
  4907 + // console.log(ui)
4908 4908
4909 const hasModifyNotSave = editor.status 4909 const hasModifyNotSave = editor.status
4910 4910
@@ -4922,7 +4922,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -4922,7 +4922,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
4922 const graphId = vertices[0].id; 4922 const graphId = vertices[0].id;
4923 4923
4924 // 解构全局属性layui要用到的模块 4924 // 解构全局属性layui要用到的模块
4925 - const { layer, form, jquery: $, colorpicker, upload, element } = layui; 4925 + const { layer, form, jquery: $, colorpicker, upload, element, laydate } = layui;
4926 4926
4927 const CONTAINER_FILTER = 'containerFilter' 4927 const CONTAINER_FILTER = 'containerFilter'
4928 $(container).addClass('layui-form').attr('lay-filter', CONTAINER_FILTER) 4928 $(container).addClass('layui-form').attr('lay-filter', CONTAINER_FILTER)
@@ -4959,8 +4959,8 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -4959,8 +4959,8 @@ DataFormatPanel.prototype.addDataFont = function (container) {
4959 4959
4960 /** 4960 /**
4961 * @description 覆盖当前节点数据 4961 * @description 覆盖当前节点数据
4962 - * @param {'act' | 'dataSources' | 'event'} key  
4963 - * @param {string} 4962 + * @param {'act' | 'dataSources' | 'event'} key
  4963 + * @param {string}
4964 */ 4964 */
4965 function overrideCurrentData(key, uuid = 'id', value = {}) { 4965 function overrideCurrentData(key, uuid = 'id', value = {}) {
4966 if (!currentNodeData[key]) currentNodeData[key] = [] 4966 if (!currentNodeData[key]) currentNodeData[key] = []
@@ -5063,7 +5063,8 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5063,7 +5063,8 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5063 GATEWAY: 'GATEWAY', 5063 GATEWAY: 'GATEWAY',
5064 ADDITIONAL: 'additional', 5064 ADDITIONAL: 'additional',
5065 DEVICE_PROFILE_ID: 'deviceProfileId', 5065 DEVICE_PROFILE_ID: 'deviceProfileId',
5066 - DEVICE_TYPE: 'deviceType' 5066 + DEVICE_TYPE: 'deviceType',
  5067 + SOURCE_OPTION: 'sourceOption'
5067 } 5068 }
5068 5069
5069 /** 5070 /**
@@ -5133,7 +5134,8 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5133,7 +5134,8 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5133 [permissionKey.SWITCH_STATE_SETTING]: createSwitchStateSettingPanel, 5134 [permissionKey.SWITCH_STATE_SETTING]: createSwitchStateSettingPanel,
5134 [permissionKey.ONLY_SINGLE_EVENT]: createParamsSettingButtonPanel, 5135 [permissionKey.ONLY_SINGLE_EVENT]: createParamsSettingButtonPanel,
5135 [permissionKey.RUNNING_AND_STOP]: createRunningAndStopPanel, 5136 [permissionKey.RUNNING_AND_STOP]: createRunningAndStopPanel,
5136 - [permissionKey.FLOWMETER_PANEL]: createFlowmeterPanel 5137 + [permissionKey.FLOWMETER_PANEL]: createFlowmeterPanel,
  5138 + [permissionKey.ALARM_LIST_PANEL]: createAlarmListPanel
5137 } 5139 }
5138 5140
5139 5141
@@ -5143,7 +5145,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5143,7 +5145,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5143 const permission = graph.getAttributeForCell(cell, basicAttr.COMPONENT_TYPE) 5145 const permission = graph.getAttributeForCell(cell, basicAttr.COMPONENT_TYPE)
5144 const needDisplayPanel = sidebarInstance.getComponentPermission(permission) 5146 const needDisplayPanel = sidebarInstance.getComponentPermission(permission)
5145 for (const key of needDisplayPanel) { 5147 for (const key of needDisplayPanel) {
5146 - renderMapping[key]() 5148 + renderMapping[key]?.()
5147 } 5149 }
5148 if (needDisplayPanel.length) createSubmitPanel() 5150 if (needDisplayPanel.length) createSubmitPanel()
5149 UseLayUi.nextTick(() => form.render()) 5151 UseLayUi.nextTick(() => form.render())
@@ -5178,7 +5180,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5178,7 +5180,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5178 const event = currentNodeData.event ?? [] 5180 const event = currentNodeData.event ?? []
5179 const actionType = {} 5181 const actionType = {}
5180 5182
5181 - const hasExistEl = $(`.layui-form[lay-filter="${CONTAINER_FILTER}"]`).find('input[type="checkbox"]') 5183 + const hasExistEl = $(`.interaction__container`).find('input[type="checkbox"]')
5182 $(hasExistEl).each((i) => { 5184 $(hasExistEl).each((i) => {
5183 $(hasExistEl[i]).attr('disabled', true) 5185 $(hasExistEl[i]).attr('disabled', true)
5184 }) 5186 })
@@ -5494,8 +5496,490 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5494,8 +5496,490 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5494 } 5496 }
5495 5497
5496 /** 5498 /**
  5499 + * @description 创建告警列表面板
  5500 + */
  5501 + function createAlarmListPanel() {
  5502 +
  5503 + const enumActionEl = {
  5504 + BIND_DEVICE_ICON: 'bindDevice',
  5505 + DATE_RANGE: 'dateRange',
  5506 + DEVICES_INPUT: 'devicesGroup',
  5507 + AUTO_PLAY: 'autoPlay',
  5508 + START_TIME: 'startTime',
  5509 + END_TIME: 'endTime',
  5510 + }
  5511 +
  5512 + const enumFields = {
  5513 + DEVICE_INFO: 'devicesInfo',
  5514 + AUTO_PLAY: 'autoPlay',
  5515 + INTERVAL: 'interval',
  5516 + START_TIME: 'startTime',
  5517 + END_TIME: 'endTime',
  5518 + }
  5519 +
  5520 + const fragment = document.createDocumentFragment()
  5521 + const title = createTitle('数据绑定')
  5522 + $(title).addClass('override__title--default')
  5523 +
  5524 +
  5525 + const deviceGroupPanel = createPanel()
  5526 + $(deviceGroupPanel).addClass('override__panel--default')
  5527 + $(deviceGroupPanel).append(`<div style="display: flex; justify-content: space-between;"><input style="display: none;" id="${enumActionEl.DEVICES_INPUT}" name="${enumFields.DEVICE_INFO}" /><div>设备绑定</div><i id="${enumActionEl.BIND_DEVICE_ICON}" class="layui-icon-edit layui-icon" style="cursor: pointer;"><i/></div>`)
  5528 +
  5529 + const queryTimeRangePanel = createPanel()
  5530 + $(queryTimeRangePanel).addClass('override__panel--default')
  5531 + $(queryTimeRangePanel).append(`<input style="display: none;" type="number" id="${enumActionEl.START_TIME}" name="${enumFields.START_TIME}"><input style="display: none;" type="number" id="${enumActionEl.END_TIME}" name="${enumFields.END_TIME}">`)
  5532 + $(queryTimeRangePanel).append(`<div class="layui-form-item" style="margin-bottom: 0;"><label class="layui-form-label" style="width: 80px; padding: 9px 0; text-align: left;">查询时间</label><div class="layui-input-block" style="margin-left: 80px;"><input style="text-overflow: ellipsis; overflow: hidden; white-space: nowrap;" class="layui-input" id="${enumActionEl.DATE_RANGE}" autocomplete="off" placeholder="请选择查询日期"></div></div>`)
  5533 +
  5534 + const autoPlayPanel = createPanel()
  5535 + $(autoPlayPanel).addClass('override__panel--default')
  5536 + $(autoPlayPanel).append(`<div class="layui-form-item" style="margin-bottom: 0;" id="${enumActionEl.AUTO_PLAY}"><label class="layui-form-label" style="width: 80px; padding: 9px 0; text-align: left;">自动滚动</label><div class="layui-input-block" style="margin-left: 80px;"><input type="checkbox" name="${enumFields.AUTO_PLAY}" title="开启|关闭" lay-skin="switch"> </div></div>`)
  5537 + // $(autoPlayPanel).append(`<div class="layui-form-item" style="margin-bottom: 0;" id="${enumActionEl.AUTO_PLAY}"><label class="layui-form-label" style="width: 80px; padding: 9px 0; text-align: left;">自动滚动</label><div class="layui-input-block" style="margin-left: 80px;"><input type="radio" name="${enumActionEl.AUTO_PLAY}" value="true" title="开" checked><input type="radio" name="${enumActionEl.AUTO_PLAY}" value="false" title="关"></div></div>`)
  5538 +
  5539 + const playIntervalPanel = createPanel()
  5540 + $(playIntervalPanel).addClass('override__panel--default')
  5541 + $(playIntervalPanel).append(`<div class="layui-form-item" style="margin-bottom: 0;"><label class="layui-form-label" style="width: 80px; padding: 9px 0; text-align: left;">停留时间()</label><div class="layui-input-block" style="margin-left: 80px;"><input class="layui-input" name="${enumFields.INTERVAL}" placeholder="请输入报警停留时间" /></div></div>`)
  5542 +
  5543 + function openBindDeviceLayer() {
  5544 +
  5545 + const enumTableActionEl = {
  5546 + TABLE_ID: 'deviceGroupEl',
  5547 + TREE_CLASS: 'org-tree',
  5548 + ADD_ROW_BUTTON: 'addRow',
  5549 + DELETE_BUTTON: 'delete-btn',
  5550 + SUBMIT_BUTTON: 'deviceGroupsSubmitBtn'
  5551 + }
  5552 +
  5553 + const enumLayFilter = {
  5554 + ROW_FILTER_NAME: 'deviceBindRowFilter',
  5555 + SUBMIT: 'deviceGroupsSubmit'
  5556 + }
  5557 +
  5558 + const enumDeviceKeys = {
  5559 + DEVICE_TYPE: 'deviceType',
  5560 + ORGANIZATION_ID: 'organizationId',
  5561 + DEVICE_PROFILE_ID: 'deviceProfileId',
  5562 + DEVICE_ID: 'deviceId'
  5563 + }
  5564 +
  5565 + let rowCount = 0
  5566 +
  5567 + let deviceType = []
  5568 +
  5569 + let organizationList = []
  5570 +
  5571 + const getRowFilter = () => {
  5572 + rowCount++
  5573 + return `${enumLayFilter.ROW_FILTER_NAME}-${rowCount}`
  5574 + }
  5575 +
  5576 + async function getOrganization(organizationId, rowFilter) {
  5577 + if (!organizationList.length) {
  5578 + const [err, res] = await to(ConfigurationNodeApi.getOrgTree())
  5579 + if (!err) organizationList = res
  5580 + }
  5581 +
  5582 + $(`#${enumTableActionEl.TABLE_ID}`).find(`tbody tr .${enumTableActionEl.TREE_CLASS}`).each((_index, item) => {
  5583 +
  5584 + const rowFilter = $(item).parents(`tr`).attr('lay-filter')
  5585 +
  5586 + if ($(item).data('initialize')) return
  5587 + $(item).data('initialize', true)
  5588 +
  5589 + UseLayUi.createTreeSelect({
  5590 + elem: item,
  5591 + layFilter: enumDeviceKeys.ORGANIZATION_ID,
  5592 + singleUsage: false,
  5593 + hiddenLabel: true,
  5594 + layVerify: 'required',
  5595 + layVerType: 'tips',
  5596 + popupMountToBody: true,
  5597 + treeProps: {
  5598 + data: organizationList,
  5599 + onlyIconControl: true,
  5600 + click(node) {
  5601 + getDevice(rowFilter)
  5602 + },
  5603 + },
  5604 + })
  5605 + })
  5606 +
  5607 + form.render()
  5608 +
  5609 + if (organizationId) {
  5610 + UseLayUi.nextTick(() => {
  5611 + const node = UseLayUi.findTreeObjectByField(organizationList, organizationId)
  5612 + $(`#${enumTableActionEl.TABLE_ID} tr[lay-filter="${rowFilter}"] input[name="${enumDeviceKeys.ORGANIZATION_ID}"]`).val(organizationId).parent().find('span').html(node?.name)
  5613 + })
  5614 + }
  5615 + }
  5616 +
  5617 + async function getDeviceType(value, rowFilter) {
  5618 + if (!deviceType.length) {
  5619 + const [err, res] = await to(ConfigurationNodeApi.getDictionaryValue('device_type'))
  5620 + if (!err) deviceType = res
  5621 + }
  5622 + const template = UseLayUi.generateOptionTemplate({ dataSource: deviceType, labelField: 'itemText', valueField: 'itemValue' })
  5623 + $(`#${enumTableActionEl.TABLE_ID}`).find(`select[name="${enumDeviceKeys.DEVICE_TYPE}"]`).each((_index, target) => {
  5624 + // if ($(target).children()) return
  5625 + if ($(target).data('initialize')) return
  5626 + $(target).data('initialize', true)
  5627 + $(target).html(template)
  5628 + })
  5629 + form.render()
  5630 +
  5631 + if (value) {
  5632 + UseLayUi.nextTick(() => {
  5633 + form.val(rowFilter, { [enumDeviceKeys.DEVICE_TYPE]: value })
  5634 + })
  5635 + }
  5636 + }
  5637 +
  5638 + async function getDeviceProfile(currentRowFilter, record, value) {
  5639 + const { deviceType } = record || form.val(currentRowFilter) || {}
  5640 + if (!deviceType) return
  5641 + const [err, res] = await to(ConfigurationNodeApi.getProduct(deviceType))
  5642 + const deviceProfile = res
  5643 + const template = UseLayUi.generateOptionTemplate({ dataSource: deviceProfile, labelField: 'name', valueField: 'id' })
  5644 + $(`#${enumTableActionEl.TABLE_ID}`).find(`tr[lay-filter="${currentRowFilter}"] select[name="${enumDeviceKeys.DEVICE_PROFILE_ID}"]`).html(template)
  5645 + form.render()
  5646 +
  5647 + if (value) {
  5648 + UseLayUi.nextTick(() => {
  5649 + form.val(currentRowFilter, { [enumDeviceKeys.DEVICE_PROFILE_ID]: value })
  5650 + })
  5651 + }
  5652 + }
  5653 +
  5654 + async function getDevice(currentRowFilter, record, value) {
  5655 + const { deviceProfileId, organizationId, deviceType } = record || form.val(currentRowFilter) || {}
  5656 + if (![deviceProfileId, organizationId, deviceType].every(Boolean)) return
  5657 + const [err, res] = await to(ConfigurationNodeApi.getMeetConditionsDevice({ deviceProfileId, deviceType, organizationId }))
  5658 + if (err) return
  5659 + const template = UseLayUi.generateOptionTemplate({ dataSource: res, labelField: 'name', valueField: 'id', alias: 'alias' })
  5660 + $(`#${enumTableActionEl.TABLE_ID}`).find(`tr[lay-filter="${currentRowFilter}"] select[name="${enumDeviceKeys.DEVICE_ID}"]`).html(template)
  5661 + form.render()
  5662 + if (value) {
  5663 + UseLayUi.nextTick(() => {
  5664 + form.val(currentRowFilter, { [enumDeviceKeys.DEVICE_ID]: value })
  5665 + })
  5666 + }
  5667 + }
  5668 +
  5669 + function echoDeviceBindInfo() {
  5670 + const dataSource = currentNodeData?.dataSources?.find(item => item.nodeId === nodeInfo.id)
  5671 + if (!dataSource) return
  5672 + const record = dataSource.sourceOption
  5673 + const devicesInfo = record.devicesInfo
  5674 + const value = UseLayUi.parseStringToJSON(devicesInfo, [])
  5675 + if (value.length) {
  5676 + $(`#${enumTableActionEl.TABLE_ID}`).find('tbody').empty()
  5677 + }
  5678 + value.forEach((item) => {
  5679 + const template = createRow()
  5680 + const rowFilter = `${enumLayFilter.ROW_FILTER_NAME}-${rowCount}`
  5681 + $(`#${enumTableActionEl.TABLE_ID}`).find('tbody').append(template)
  5682 +
  5683 + // form.render(null, rowFilter)
  5684 + getDeviceType(item[enumDeviceKeys.DEVICE_TYPE], rowFilter)
  5685 + getOrganization(item[enumDeviceKeys.ORGANIZATION_ID], rowFilter)
  5686 + getDeviceProfile(rowFilter, item, item[enumDeviceKeys.DEVICE_PROFILE_ID])
  5687 + getDevice(rowFilter, item, item[enumDeviceKeys.DEVICE_ID])
  5688 + })
  5689 + }
  5690 +
  5691 + function createEventListener(index) {
  5692 +
  5693 + /**
  5694 + * @description 下拉选项定位
  5695 + */
  5696 + $(`#${enumTableActionEl.TABLE_ID}`).on('click', '.layui-form-select', event => {
  5697 + const width = event.currentTarget.offsetWidth || 200
  5698 + const height = event.currentTarget.offsetHeight || 38
  5699 + const offset = $(event.currentTarget).offset()
  5700 + $(event.currentTarget).find('dl').css({
  5701 + position: 'fixed',
  5702 + 'min-width': width + 'px',
  5703 + top: offset.top + height + 'px',
  5704 + left: offset.left + 'px'
  5705 + })
  5706 + })
  5707 +
  5708 + $(`#${enumTableActionEl.ADD_ROW_BUTTON}`).on('click', (event) => {
  5709 + const template = createRow()
  5710 + $(`#${enumTableActionEl.TABLE_ID}`).find('tbody').append(template)
  5711 + getDeviceType()
  5712 + getOrganization()
  5713 + form.render()
  5714 + })
  5715 +
  5716 + $(`#${enumTableActionEl.TABLE_ID}`).on('click', `tr .${enumTableActionEl.DELETE_BUTTON}`, (event) => {
  5717 + $(event.currentTarget).parents('tr').remove()
  5718 + })
  5719 +
  5720 + form.on('select', (data) => {
  5721 + const { elem, value } = data || {}
  5722 + if (!elem) return
  5723 +
  5724 + const key = $(elem).attr('name')
  5725 + const currentRow = $(elem).parents('tr')
  5726 + const currentRowFilter = $(currentRow).attr('lay-filter')
  5727 +
  5728 + if (key === enumDeviceKeys.DEVICE_TYPE) {
  5729 + getDeviceProfile(currentRowFilter)
  5730 + form.val(currentRowFilter, {
  5731 + deviceId: null,
  5732 + deviceProfileId: null
  5733 + })
  5734 + }
  5735 +
  5736 + if (key === enumDeviceKeys.DEVICE_PROFILE_ID) {
  5737 + getDevice(currentRowFilter)
  5738 + form.val(currentRowFilter, {
  5739 + deviceId: null
  5740 + })
  5741 + }
  5742 + })
  5743 +
  5744 + form.on(`submit`, () => {
  5745 + const deviceGroupValues = []
  5746 + $(`#${enumTableActionEl.TABLE_ID}`).find(`tbody tr`).each((_index, item) => {
  5747 + const rowFilter = $(item).attr('lay-filter')
  5748 + const value = form.val(rowFilter)
  5749 + deviceGroupValues.push(value)
  5750 + $(`#${enumActionEl.DEVICES_INPUT}`).val(JSON.stringify(deviceGroupValues))
  5751 + layer.close(index)
  5752 + })
  5753 + })
  5754 + }
  5755 +
  5756 + function createRow() {
  5757 + const template = `
  5758 + <tr lay-filter="${getRowFilter()}" class="layui-form">
  5759 + <td class="layui-form-item" style="margin: 0;">
  5760 + <div>
  5761 + <select lay-verify="required" lay-verType="tips" name="${enumDeviceKeys.DEVICE_TYPE}"></select>
  5762 + </div>
  5763 + </td>
  5764 + <td class="layui-form-item" style="margin: 0;">
  5765 + <div>
  5766 + <select lay-verify="required" lay-verType="tips" name="${enumDeviceKeys.DEVICE_PROFILE_ID}"></select>
  5767 + </div>
  5768 + </td>
  5769 + <td class="layui-form-item" style="margin: 0;">
  5770 + <div class="${enumTableActionEl.TREE_CLASS}" style="width: 100%;">
  5771 + <select lay-verify="required" lay-verType="tips" name="${enumDeviceKeys.ORGANIZATION_ID}"></select>
  5772 + </div>
  5773 + </td>
  5774 + <td class="layui-form-item" style="margin: 0;">
  5775 + <div>
  5776 + <select lay-verify="required" lay-verType="tips" name="${enumDeviceKeys.DEVICE_ID}"></select>
  5777 + </div>
  5778 + </td>
  5779 + <td>
  5780 + <div class="${enumTableActionEl.DELETE_BUTTON}" style="cursor: pointer; color: #1E9FFF;">删除</div>
  5781 + </td>
  5782 + </tr>
  5783 + `
  5784 + return template
  5785 + }
  5786 +
  5787 + layer.open({
  5788 + title: '设备绑定',
  5789 + area: ['800px', '540px'],
  5790 + content: `
  5791 + <div class="override__table layui-form">
  5792 + <table id="${enumTableActionEl.TABLE_ID}" class="layui-table">
  5793 + <colgroup>
  5794 + <col width="150">
  5795 + <col width="150">
  5796 + <col width="150">
  5797 + <col width="150">
  5798 + <col width="100">
  5799 + </colgroup>
  5800 + <thead>
  5801 + <tr>
  5802 + <th>设备类型</th>
  5803 + <th>产品</th>
  5804 + <th>组织</th>
  5805 + <th>设备</th>
  5806 + <th>操作</th>
  5807 + </tr>
  5808 + </thead>
  5809 + <tbody>
  5810 + ${createRow()}
  5811 + </tbody>
  5812 + </table>
  5813 + <div style="display: flex; justify-content: center;">
  5814 + <button id="${enumTableActionEl.ADD_ROW_BUTTON}" type="button" class="layui-btn layui-btn-fluid layui-btn-normal">增加</button>
  5815 + </div>
  5816 + </div>
  5817 + `,
  5818 + async success(el, index) {
  5819 + form.render()
  5820 + await getDeviceType()
  5821 + await getOrganization()
  5822 + createEventListener(index)
  5823 + $(el).addClass('layui-form').find('.layui-layer-btn0').attr('lay-submit', true).attr('lay-filter', enumTableActionEl.SUBMIT_BUTTON)
  5824 + echoDeviceBindInfo()
  5825 + },
  5826 + yes() {
  5827 + return false
  5828 + }
  5829 + })
  5830 + }
  5831 +
  5832 + function createDateRange() {
  5833 + laydate.render({
  5834 + elem: `#${enumActionEl.DATE_RANGE}`,
  5835 + type: 'datetime',
  5836 + range: true,
  5837 + shortcuts: [
  5838 + {
  5839 + text: '过去一小时',
  5840 + value: (() => {
  5841 + const now = Date.now()
  5842 + const date1 = new Date(now - 1000 * 60 * 60)
  5843 + return [date1, new Date(now)]
  5844 + })()
  5845 + },
  5846 + {
  5847 + text: '今天',
  5848 + value: (() => {
  5849 + const date1 = new Date()
  5850 + const date2 = new Date()
  5851 + date1.setHours(0)
  5852 + date1.setMinutes(0)
  5853 + date1.setSeconds(0)
  5854 + date2.setHours(23)
  5855 + date2.setMinutes(59)
  5856 + date2.setSeconds(59)
  5857 + return [date1, date2]
  5858 + })()
  5859 + },
  5860 + {
  5861 + text: '过去七天',
  5862 + value: (() => {
  5863 + const now = Date.now()
  5864 + const date1 = new Date(now - 1000 * 60 * 60 * 24 * 7)
  5865 + return [date1, new Date(now)]
  5866 + })()
  5867 + },
  5868 + {
  5869 + text: '过去三十天',
  5870 + value: (() => {
  5871 + const now = Date.now()
  5872 + const date1 = new Date(now - 1000 * 60 * 60 * 24 * 30)
  5873 + return [date1, new Date(now)]
  5874 + })()
  5875 + },
  5876 + {
  5877 + text: '本月',
  5878 + value: (() => {
  5879 + const date1 = new Date()
  5880 + let date2 = new Date()
  5881 + date1.setDate(1)
  5882 + date1.setHours(0)
  5883 + date1.setMinutes(0)
  5884 + date1.setSeconds(0)
  5885 +
  5886 + date2.setMonth(date2.getMonth() + 1)
  5887 + date2 = new Date(date2.valueOf() - 1000 * 60 * 60 * ((date2.getDate()) * 24))
  5888 + date2.setHours(23)
  5889 + date2.setMinutes(59)
  5890 + date2.setSeconds(59)
  5891 + return [date1, date2]
  5892 + })()
  5893 + },
  5894 + {
  5895 + text: '近半年',
  5896 + value: (() => {
  5897 + const date1 = new Date()
  5898 + const date2 = new Date()
  5899 +
  5900 + date1.getMonth() < 6
  5901 + ? date1.setFullYear(date1.getFullYear() - 1) && date1.setMonth(12 - (6 % (date1.getMonth())))
  5902 + : date1.setMonth(date1.getMonth() - 6)
  5903 +
  5904 + return [date1, date2]
  5905 + })()
  5906 + },
  5907 + {
  5908 + text: '近一年',
  5909 + value: (() => {
  5910 + const date1 = new Date()
  5911 + const date2 = new Date()
  5912 + date1.setFullYear(date1.getFullYear() - 1)
  5913 + return [date1, date2]
  5914 + })()
  5915 + }
  5916 + ],
  5917 + done(value, date, endDate) {
  5918 + const [startTime, endTime] = value.split(' - ')
  5919 + const startTs = new Date(startTime).valueOf()
  5920 + const endTs = new Date(endTime).valueOf()
  5921 +
  5922 + $(`#${enumActionEl.START_TIME}`).val(startTs)
  5923 + $(`#${enumActionEl.END_TIME}`).val(endTs)
  5924 + }
  5925 + })
  5926 + }
  5927 +
  5928 + function formatTimespanToDateString(timespan) {
  5929 + if (isNaN(timespan)) return
  5930 + const date = new Date(Number(timespan))
  5931 + const year = date.getFullYear()
  5932 + const month = (date.getMonth() + 1).toString().padStart(2, 0)
  5933 + const day = date.getDate().toString().padStart(2, 0)
  5934 + const hour = date.getHours().toString().padStart(2, 0)
  5935 + const minute = date.getMinutes().toString().padStart(2, 0)
  5936 + const second = date.getSeconds().toString().padStart(2, 0)
  5937 +
  5938 + return `${year}-${month}-${day} ${hour}:${minute}:${second}`
  5939 + }
  5940 +
  5941 + async function echoData() {
  5942 + const getBindValue = currentNodeData?.dataSources?.find(item => item.nodeId === nodeInfo.id)
  5943 + if (!getBindValue) return
  5944 + const record = getBindValue.sourceOption
  5945 + form.val(CONTAINER_FILTER, record)
  5946 +
  5947 + const startTime = formatTimespanToDateString(record.startTime)
  5948 + const endTime = formatTimespanToDateString(record.endTime)
  5949 + laydate.render({
  5950 + elem: `#${enumActionEl.DATE_RANGE}`,
  5951 + value: `${startTime} - ${endTime}`
  5952 + })
  5953 + }
  5954 +
  5955 + function init() {
  5956 + $(`#${enumActionEl.BIND_DEVICE_ICON}`).on('click', openBindDeviceLayer)
  5957 + form.render()
  5958 +
  5959 + createDateRange()
  5960 +
  5961 + const refreshFN = echoRefreshFn
  5962 + echoRefreshFn = async function () {
  5963 + refreshFN.apply(this, arguments)
  5964 + await echoData()
  5965 + }
  5966 +
  5967 + }
  5968 +
  5969 + fragment.append(title)
  5970 + fragment.append(deviceGroupPanel)
  5971 + fragment.append(queryTimeRangePanel)
  5972 + fragment.append(autoPlayPanel)
  5973 + fragment.append(playIntervalPanel)
  5974 + $(container).append(fragment)
  5975 +
  5976 + UseLayUi.nextTick(init)
  5977 +
  5978 + }
  5979 +
  5980 + /**
5497 * @description 是否是折线图 5981 * @description 是否是折线图
5498 - * @param {boolean} isLineChart 5982 + * @param {boolean} isLineChart
5499 */ 5983 */
5500 function createChartBindPanel(chartType) { 5984 function createChartBindPanel(chartType) {
5501 const fragment = document.createDocumentFragment() 5985 const fragment = document.createDocumentFragment()
@@ -5996,6 +6480,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -5996,6 +6480,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
5996 [componentType.PARAMS_SETTING_BUTTON]: getSwitchSubmitValue, 6480 [componentType.PARAMS_SETTING_BUTTON]: getSwitchSubmitValue,
5997 [componentType.IMAGE]: getSubmitValue, 6481 [componentType.IMAGE]: getSubmitValue,
5998 [componentType.FLOWMETER]: getFlowmeterSubmitValue, 6482 [componentType.FLOWMETER]: getFlowmeterSubmitValue,
  6483 + [componentType.ALARM_LIST]: getAlarmListSubmitValue,
5999 } 6484 }
6000 6485
6001 const cell = vertices[0] 6486 const cell = vertices[0]
@@ -6095,8 +6580,8 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -6095,8 +6580,8 @@ DataFormatPanel.prototype.addDataFont = function (container) {
6095 } 6580 }
6096 6581
6097 /** 6582 /**
6098 - * @description 处理开关组件的保存值  
6099 - * @returns 6583 + * @description 处理开关组件的保存值
  6584 + * @returns
6100 */ 6585 */
6101 function getSwitchSubmitValue(field) { 6586 function getSwitchSubmitValue(field) {
6102 const dataSources = getDataSourceBindValue() 6587 const dataSources = getDataSourceBindValue()
@@ -6133,18 +6618,6 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -6133,18 +6618,6 @@ DataFormatPanel.prototype.addDataFont = function (container) {
6133 6618
6134 function getFlowmeterSubmitValue(field = {}) { 6619 function getFlowmeterSubmitValue(field = {}) {
6135 const additionalKey = HandleDataSource.enumConst 6620 const additionalKey = HandleDataSource.enumConst
6136 - const minValue = field[additionalKey.MIN_VALUE]  
6137 - const maxValue = field[additionalKey.MAX_VALUE]  
6138 -  
6139 - if ([minValue, maxValue].some(item => isNaN(item))) {  
6140 - UseLayUi.topErrorMsg('最大值或最小值不是一个数字!')  
6141 - return false  
6142 - }  
6143 -  
6144 - if (Number(minValue) > Number(maxValue)) {  
6145 - UseLayUi.topErrorMsg('最小值大于最大值!')  
6146 - return false  
6147 - }  
6148 6621
6149 const value = { 6622 const value = {
6150 configurationId, 6623 configurationId,
@@ -6160,8 +6633,8 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -6160,8 +6633,8 @@ DataFormatPanel.prototype.addDataFont = function (container) {
6160 [enumDataSourceConst.ATTR]: field[enumDataSourceConst.ATTR], 6633 [enumDataSourceConst.ATTR]: field[enumDataSourceConst.ATTR],
6161 [enumDataSourceConst.ADDITIONAL]: { 6634 [enumDataSourceConst.ADDITIONAL]: {
6162 [additionalKey.COMPONENT_TYPE]: field[additionalKey.COMPONENT_TYPE], 6635 [additionalKey.COMPONENT_TYPE]: field[additionalKey.COMPONENT_TYPE],
6163 - [additionalKey.MIN_VALUE]: field[additionalKey.MIN_VALUE],  
6164 - [additionalKey.MAX_VALUE]: field[additionalKey.MAX_VALUE], 6636 + // [additionalKey.MIN_VALUE]: field[additionalKey.MIN_VALUE],
  6637 + // [additionalKey.MAX_VALUE]: field[additionalKey.MAX_VALUE],
6165 [additionalKey.BG_COLOR]: field[additionalKey.BG_COLOR], 6638 [additionalKey.BG_COLOR]: field[additionalKey.BG_COLOR],
6166 [additionalKey.WAVE_FIRST_COLOR]: field[additionalKey.WAVE_FIRST_COLOR], 6639 [additionalKey.WAVE_FIRST_COLOR]: field[additionalKey.WAVE_FIRST_COLOR],
6167 [additionalKey.WAVE_SECOND_COLOR]: field[additionalKey.WAVE_SECOND_COLOR], 6640 [additionalKey.WAVE_SECOND_COLOR]: field[additionalKey.WAVE_SECOND_COLOR],
@@ -6171,6 +6644,27 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -6171,6 +6644,27 @@ DataFormatPanel.prototype.addDataFont = function (container) {
6171 } 6644 }
6172 return value 6645 return value
6173 } 6646 }
  6647 +
  6648 + function getAlarmListSubmitValue(filed = {}) {
  6649 + console.log(field?.devicesInfo)
  6650 + if(!field?.devicesInfo) {
  6651 + UseLayUi.errorMsg('请先进行设备绑定!')
  6652 + return
  6653 + }
  6654 + const value = {
  6655 + configurationId,
  6656 + contentId: currentPageId.id,
  6657 + nodeId: graphId,
  6658 + [enumCategory.ACT]: [],
  6659 + [enumCategory.EVENT]: [],
  6660 + [enumCategory.DATA_SOURCE]: {
  6661 + [enumDataSourceConst.ADDITIONAL]: { componentType: 'alarmList' },
  6662 + [enumDataSourceConst.SOURCE_OPTION]: field
  6663 + }
  6664 + }
  6665 +
  6666 + return value
  6667 + }
6174 } 6668 }
6175 6669
6176 /** 6670 /**
@@ -7141,7 +7635,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7141,7 +7635,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7141 } 7635 }
7142 7636
7143 /** 7637 /**
7144 - * @description 7638 + * @description
7145 */ 7639 */
7146 const recordData = { 7640 const recordData = {
7147 enabled: false 7641 enabled: false
@@ -7158,7 +7652,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7158,7 +7652,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7158 7652
7159 // 参数设置 7653 // 参数设置
7160 [enumConst.JSON_COMMAND]: content[enumConst.JSON_COMMAND], 7654 [enumConst.JSON_COMMAND]: content[enumConst.JSON_COMMAND],
7161 - [enumConst.WAY]: content[enumConst.WAY], 7655 + [enumConst.WAY]: content[enumConst.WAY] || enumWayType.ONE_WAY,
7162 [enumConst.COMMAND_TYPE]: content[enumConst.COMMAND_TYPE], 7656 [enumConst.COMMAND_TYPE]: content[enumConst.COMMAND_TYPE],
7163 [enumConst.TCP_COMMAND]: content[enumConst.TCP_COMMAND], 7657 [enumConst.TCP_COMMAND]: content[enumConst.TCP_COMMAND],
7164 [enumConst.TRANSPORTTYPE]: content[enumConst.TRANSPORTTYPE], 7658 [enumConst.TRANSPORTTYPE]: content[enumConst.TRANSPORTTYPE],
@@ -7182,7 +7676,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7182,7 +7676,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7182 7676
7183 /** 7677 /**
7184 * @description 控制form 7678 * @description 控制form
7185 - * @param {enumActionType} value 7679 + * @param {enumActionType} value
7186 */ 7680 */
7187 async function controlFormDisplay(value, isTCP, isCustom) { 7681 async function controlFormDisplay(value, isTCP, isCustom) {
7188 if (value === enumActionType.PAGE) { 7682 if (value === enumActionType.PAGE) {
@@ -7250,7 +7744,6 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7250,7 +7744,6 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7250 return false 7744 return false
7251 } 7745 }
7252 } else { 7746 } else {
7253 - console.log(formVal)  
7254 if (!isJson(formVal[enumConst.JSON_COMMAND])) { 7747 if (!isJson(formVal[enumConst.JSON_COMMAND])) {
7255 UseLayUi.topErrorMsg('命令配置存在错误') 7748 UseLayUi.topErrorMsg('命令配置存在错误')
7256 return false 7749 return false
@@ -7323,7 +7816,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7323,7 +7816,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7323 7816
7324 /** 7817 /**
7325 * @description 生成命令类型选项 7818 * @description 生成命令类型选项
7326 - * @returns 7819 + * @returns
7327 */ 7820 */
7328 function generateCommandTypeOptions() { 7821 function generateCommandTypeOptions() {
7329 const options = [ 7822 const options = [
@@ -7513,7 +8006,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7513,7 +8006,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7513 <label class="layui-form-label" style="width: 120px;">单向/双向 ${createHelpMessage(`单向:服务器向网关设备、直连设备发送指令。发送指令后,设备不会返回任何信息。\n 8006 <label class="layui-form-label" style="width: 120px;">单向/双向 ${createHelpMessage(`单向:服务器向网关设备、直连设备发送指令。发送指令后,设备不会返回任何信息。\n
7514 双向:服务器向网关设备、直连设备发送指令。发送指令后,设备返回响应信息。`, 'way')}</label> 8007 双向:服务器向网关设备、直连设备发送指令。发送指令后,设备返回响应信息。`, 'way')}</label>
7515 <div class="layui-input-block" style="margin-left: 150px;"> 8008 <div class="layui-input-block" style="margin-left: 150px;">
7516 - <input type="radio" name="${enumConst.WAY}" value="${enumWayType.ONE_WAY}" title="单向" checked=""> 8009 + <input type="radio" name="${enumConst.WAY}" value="${enumWayType.ONE_WAY}" title="单向" checked>
7517 <input type="radio" name="${enumConst.WAY}" value="${enumWayType.TWO_WAY}" title="双向"> 8010 <input type="radio" name="${enumConst.WAY}" value="${enumWayType.TWO_WAY}" title="双向">
7518 </div> 8011 </div>
7519 </div> 8012 </div>
@@ -7919,7 +8412,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -7919,7 +8412,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
7919 8412
7920 /** 8413 /**
7921 * @description 8414 * @description
7922 - * @param {} event 8415 + * @param {} event
7923 */ 8416 */
7924 function handleStateSetting(event) { 8417 function handleStateSetting(event) {
7925 8418
@@ -8405,7 +8898,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -8405,7 +8898,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
8405 } 8898 }
8406 8899
8407 /** 8900 /**
8408 - * 8901 + *
8409 * @returns {{orgId: string, attr: string, deviceId: string, devi}} 8902 * @returns {{orgId: string, attr: string, deviceId: string, devi}}
8410 */ 8903 */
8411 function getValue() { 8904 function getValue() {
@@ -8737,7 +9230,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -8737,7 +9230,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
8737 CONTAINER_FILTER: 'imgContainerFilter', 9230 CONTAINER_FILTER: 'imgContainerFilter',
8738 9231
8739 /** 9232 /**
8740 - * @description 9233 + * @description
8741 */ 9234 */
8742 SET_IMG_EL: 'variableImageTableSetImgEl', 9235 SET_IMG_EL: 'variableImageTableSetImgEl',
8743 9236
@@ -8771,7 +9264,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -8771,7 +9264,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
8771 9264
8772 /** 9265 /**
8773 * @description 设置回显 9266 * @description 设置回显
8774 - * @param {} value 9267 + * @param {} value
8775 */ 9268 */
8776 function setValue(value = {}) { 9269 function setValue(value = {}) {
8777 form.val(getFormFilter, value) 9270 form.val(getFormFilter, value)
@@ -8779,7 +9272,7 @@ DataFormatPanel.prototype.addDataFont = function (container) { @@ -8779,7 +9272,7 @@ DataFormatPanel.prototype.addDataFont = function (container) {
8779 9272
8780 /** 9273 /**
8781 * @description 获取值 9274 * @description 获取值
8782 - * @returns 9275 + * @returns
8783 */ 9276 */
8784 function getValue() { 9277 function getValue() {
8785 return form.val(getFormFilter) || {} 9278 return form.val(getFormFilter) || {}
@@ -12650,10 +13143,22 @@ class UseLayUi { @@ -12650,10 +13143,22 @@ class UseLayUi {
12650 ` 13143 `
12651 } 13144 }
12652 13145
  13146 + static parseStringToJSON(string, defaultValue = {}) {
  13147 + try {
  13148 + if (typeof string === 'string') {
  13149 + const value = JSON.parse(string)
  13150 + if (typeof value === 'object') return value
  13151 + }
  13152 + return defaultValue
  13153 + } catch (error) {
  13154 + return defaultValue
  13155 + }
  13156 + }
  13157 +
12653 /** 13158 /**
12654 * @description 生成输入框控件 13159 * @description 生成输入框控件
12655 - * @param {{label: string, value: string, labelWidth: number, numberInput: boolean}} params  
12656 - * @returns 13160 + * @param {{label: string, value: string, labelWidth: number, numberInput: boolean}} params
  13161 + * @returns
12657 */ 13162 */
12658 static createInputTemplate({ label, value, labelWidth = 80, required = false, type = 'TEXT' }) { 13163 static createInputTemplate({ label, value, labelWidth = 80, required = false, type = 'TEXT' }) {
12659 return ` 13164 return `
@@ -12671,19 +13176,19 @@ class UseLayUi { @@ -12671,19 +13176,19 @@ class UseLayUi {
12671 } 13176 }
12672 13177
12673 /** 13178 /**
12674 - * 13179 + *
12675 * @param {{ 13180 * @param {{
12676 - * accessMode: 'r' | 'w', 13181 + * accessMode: 'r' | 'w',
12677 * functionName: string, 13182 * functionName: string,
12678 - * id: string,  
12679 - * identifier: string, 13183 + * id: string,
  13184 + * identifier: string,
12680 * dataType: { 13185 * dataType: {
12681 - * type: 'TEXT' | 'INT' | 'DOUBLE' | 'STRUCT',  
12682 - * specs: { unit: {value: string, label: string},  
12683 - * unitName: string,  
12684 - * valueRange: {min: number, max: number}, 13186 + * type: 'TEXT' | 'INT' | 'DOUBLE' | 'STRUCT',
  13187 + * specs: { unit: {value: string, label: string},
  13188 + * unitName: string,
  13189 + * valueRange: {min: number, max: number},
12685 * length: number 13190 * length: number
12686 - * }}}[]} inputData 13191 + * }}}[]} inputData
12687 * @param {number} labelWidth = 80 13192 * @param {number} labelWidth = 80
12688 * @param {} 13193 * @param {}
12689 */ 13194 */
@@ -12701,20 +13206,20 @@ class UseLayUi { @@ -12701,20 +13206,20 @@ class UseLayUi {
12701 return template 13206 return template
12702 } 13207 }
12703 /** 13208 /**
12704 - * 13209 + *
12705 * @param {{ 13210 * @param {{
12706 - * accessMode: 'r' | 'w', 13211 + * accessMode: 'r' | 'w',
12707 * functionName: string, 13212 * functionName: string,
12708 - * id: string,  
12709 - * identifier: string, 13213 + * id: string,
  13214 + * identifier: string,
12710 * dataType: { 13215 * dataType: {
12711 - * type: 'TEXT' | 'INT' | 'DOUBLE' | 'STRUCT',  
12712 - * specs: { unit: {value: string, label: string},  
12713 - * unitName: string,  
12714 - * valueRange: {min: number, max: number}, 13216 + * type: 'TEXT' | 'INT' | 'DOUBLE' | 'STRUCT',
  13217 + * specs: { unit: {value: string, label: string},
  13218 + * unitName: string,
  13219 + * valueRange: {min: number, max: number},
12715 * length: number 13220 * length: number
12716 - * }}}[]} inputData  
12717 - * @param {Record<string, any>} value = 80 13221 + * }}}[]} inputData
  13222 + * @param {Record<string, any>} value = 80
12718 */ 13223 */
12719 static validateThingsModelInputDataForm(inputData, value, needFormat = false) { 13224 static validateThingsModelInputDataForm(inputData, value, needFormat = false) {
12720 let flag = true 13225 let flag = true
@@ -12817,12 +13322,13 @@ class UseLayUi { @@ -12817,12 +13322,13 @@ class UseLayUi {
12817 13322
12818 /** 13323 /**
12819 * @description generator options template 生产下拉选项模板 13324 * @description generator options template 生产下拉选项模板
12820 - * @param options  
12821 - * @param {object[]} [dataSource] options.dataSource  
12822 - * @param {boolean} [addPlaceholderOption = true] options.addPlaceholderOption  
12823 - * @param {string} [labelField = 'name'] options.labelField  
12824 - * @param {string} [valueField = 'name'] options.valueField  
12825 - * @param {string} [alias] options.alias 13325 + * @typedef {Object} GenerateOptionTemplateParamsType
  13326 + * @property {any[]} [dataSource] options.dataSource
  13327 + * @property {boolean} [addPlaceholderOption = true] options.addPlaceholderOption
  13328 + * @property {string} [labelField = 'name'] options.labelField
  13329 + * @property {string} [valueField = 'name'] options.valueField
  13330 + * @property {string} [alias] options.alias
  13331 + * @param {GenerateOptionTemplateParamsType} options
12826 * @returns {*} 13332 * @returns {*}
12827 */ 13333 */
12828 static generateOptionTemplate(options) { 13334 static generateOptionTemplate(options) {
@@ -12967,17 +13473,21 @@ class UseLayUi { @@ -12967,17 +13473,21 @@ class UseLayUi {
12967 // TODO Tree Select 13473 // TODO Tree Select
12968 /** 13474 /**
12969 * @description create a tree select controls 13475 * @description create a tree select controls
12970 - * @param {string} [options.layFilter] options.layFilter  
12971 - * @param {string} [options.label] options.label  
12972 - * @param {object} [options.treeProps] options.treeProps  
12973 - * @param {HTMLDivElement} [options.elem] options.elem  
12974 - * @param {boolean} [options.singleUsage = true] options.singleUsage  
12975 - * @param {Function} [options.customSetTree = ((record) => ({ id: record.id, title: record.name }))] options.customSetTree  
12976 - * @param {boolean} [options.autoFormatDataSource = true] options.autoFormatDataSource  
12977 - * @param {string} [options.layVerify] options.layVerify  
12978 - * @param {string} [options.layVerType] options.layVerType  
12979 - * @param {boolean} [options.addPlaceholderOption] options.addPlaceholderOption  
12980 - * @param {Function} [options.treeProps.onReady] options.treeProps.onReady 13476 + * @typedef CreateTreeSelectParamsType
  13477 + * @property {string} [layFilter] options.layFilter
  13478 + * @property {string} [label] options.label
  13479 + * @property {object} [treeProps] options.treeProps
  13480 + * @property {HTMLDivElement} [elem] options.elem
  13481 + * @property {boolean} [singleUsage = true] options.singleUsage
  13482 + * @property {Function} [customSetTree = ((record) => ({ id: record.id, title: record.name }))] options.customSetTree
  13483 + * @property {boolean} [autoFormatDataSource = true] options.autoFormatDataSource
  13484 + * @property {string} [layVerify] options.layVerify
  13485 + * @property {string} [layVerType] options.layVerType
  13486 + * @property {boolean} [addPlaceholderOption] options.addPlaceholderOption
  13487 + * @property {boolean} [hiddenLabel] - hiddenLabel
  13488 + * @property {Function} [treeProps.onReady] options.treeProps.onReady
  13489 + * @property {boolean} [popupMountToBody] popupMountToBody
  13490 + * @param {CreateTreeSelectParamsType} options
12981 */ 13491 */
12982 static createTreeSelect(options) { 13492 static createTreeSelect(options) {
12983 const CLASS_NAME = 'things-kit-tree-select' 13493 const CLASS_NAME = 'things-kit-tree-select'
@@ -12998,27 +13508,29 @@ class UseLayUi { @@ -12998,27 +13508,29 @@ class UseLayUi {
12998 childrenField = 'children', 13508 childrenField = 'children',
12999 layVerify, 13509 layVerify,
13000 layVerType, 13510 layVerType,
13001 - addPlaceholderOption 13511 + addPlaceholderOption,
  13512 + hiddenLabel,
  13513 + popupMountToBody
13002 } = options 13514 } = options
13003 13515
13004 let { data = [], click, onReady } = treeProps 13516 let { data = [], click, onReady } = treeProps
13005 13517
13006 let template = ` 13518 let template = `
13007 - <div class="layui-form-item ${CLASS_NAME} ${className}">  
13008 - <label class="layui-form-label">${label}</label> 13519 + <div class="layui-form-item ${CLASS_NAME} ${className}" style="margin-bottom: ${hiddenLabel ? '0' : '15px'};">
  13520 + <label class="layui-form-label" style="display: ${hiddenLabel ? 'none' : 'block'};">${label}</label>
13009 <div class="layui-input-block"> 13521 <div class="layui-input-block">
13010 - <div class="layui-unselect layui-form-select ${SELECT_CLS}">  
13011 - <div class="layui-select-title">  
13012 - <span class="layui-input layui-unselect tree-select__label">请选择</span>  
13013 - <input ${this.dynamicAttr('lay-verify', layVerify)} ${this.dynamicAttr('lay-verType', layVerType)} type="text" style="visibility: hidden; position: absolute; top: 0" name="${layFilter}">  
13014 - <i class="layui-edge"></i> 13522 + <div class="layui-unselect layui-form-select ${SELECT_CLS}">
  13523 + <div class="layui-select-title">
  13524 + <span class="layui-input layui-unselect tree-select__label">请选择</span>
  13525 + <input ${this.dynamicAttr('lay-verify', layVerify)} ${this.dynamicAttr('lay-verType', layVerType)} type="text" style="visibility: hidden; position: absolute; top: 0" name="${layFilter}">
  13526 + <i class="layui-edge"></i>
  13527 + </div>
  13528 + <dl class="layui-anim layui-anim-upbit">
  13529 + <dd>
  13530 + <ul class="tree-select__tree-mount"></ul>
  13531 + </dd>
  13532 + </dl>
13015 </div> 13533 </div>
13016 - <dl class="layui-anim layui-anim-upbit">  
13017 - <dd>  
13018 - <ul class="tree-select__tree-mount"></ul>  
13019 - </dd>  
13020 - </dl>  
13021 - </div>  
13022 </div> 13534 </div>
13023 </div>` 13535 </div>`
13024 13536
@@ -13042,7 +13554,7 @@ class UseLayUi { @@ -13042,7 +13554,7 @@ class UseLayUi {
13042 $(elem).html(template) 13554 $(elem).html(template)
13043 const treeData = UseLayUi.formatTreeDataSource(data, customSetTree, valueField, labelField, childrenField) 13555 const treeData = UseLayUi.formatTreeDataSource(data, customSetTree, valueField, labelField, childrenField)
13044 if (addPlaceholderOption) treeData.unshift({ title: '请选择', id: undefined }) 13556 if (addPlaceholderOption) treeData.unshift({ title: '请选择', id: undefined })
13045 - // mount tree 13557 + // mount tree
13046 tree.render({ 13558 tree.render({
13047 ...treeProps, 13559 ...treeProps,
13048 ...(autoFormatDataSource ? { data: treeData } : {}), 13560 ...(autoFormatDataSource ? { data: treeData } : {}),
@@ -13059,6 +13571,21 @@ class UseLayUi { @@ -13059,6 +13571,21 @@ class UseLayUi {
13059 $(document).find('.layui-form-select').removeClass('layui-form-selected') 13571 $(document).find('.layui-form-select').removeClass('layui-form-selected')
13060 $(this).parents(`.${SELECT_CLS}`).toggleClass("layui-form-selected"); 13572 $(this).parents(`.${SELECT_CLS}`).toggleClass("layui-form-selected");
13061 layui.stope(e); 13573 layui.stope(e);
  13574 + if (popupMountToBody) {
  13575 + const popup = $(this).parents(`.${SELECT_CLS}`).find('.layui-anim')
  13576 + const titleEl = $(this).parents(`.${SELECT_CLS}`).find('.layui-select-title')
  13577 + const offset = $(titleEl).offset()
  13578 + const height = $(titleEl).height()
  13579 + const width = $(titleEl).width()
  13580 +
  13581 + $(popup).css({
  13582 + position: 'fixed',
  13583 + top: `${offset.top + height}px`,
  13584 + 'min-width': width,
  13585 + left: `${offset.left}px`,
  13586 + width
  13587 + })
  13588 + }
13062 }) 13589 })
13063 .on('click', '.layui-anim', (e) => { 13590 .on('click', '.layui-anim', (e) => {
13064 layui.stope(e) 13591 layui.stope(e)
@@ -13213,7 +13740,7 @@ class UseLayUi { @@ -13213,7 +13740,7 @@ class UseLayUi {
13213 class Utils { 13740 class Utils {
13214 /** 13741 /**
13215 * @description 字符串是否能转换为对象 13742 * @description 字符串是否能转换为对象
13216 - * @param {string} value 13743 + * @param {string} value
13217 */ 13744 */
13218 static stringIsJSON(value) { 13745 static stringIsJSON(value) {
13219 try { 13746 try {
@@ -13227,8 +13754,8 @@ class Utils { @@ -13227,8 +13754,8 @@ class Utils {
13227 13754
13228 /** 13755 /**
13229 * @description 字符串转对象 13756 * @description 字符串转对象
13230 - * @param {string} value  
13231 - * @returns 13757 + * @param {string} value
  13758 + * @returns
13232 */ 13759 */
13233 static stringToJSON(value, defaultValue = {}) { 13760 static stringToJSON(value, defaultValue = {}) {
13234 try { 13761 try {
@@ -13769,7 +14296,7 @@ class DispatchCenter { @@ -13769,7 +14296,7 @@ class DispatchCenter {
13769 subList.forEach(item => { 14296 subList.forEach(item => {
13770 const { dataOrigin, additional } = item 14297 const { dataOrigin, additional } = item
13771 if (dataOrigin === 'dataSources') { 14298 if (dataOrigin === 'dataSources') {
13772 - if (additional && (additional || {})?.dataType ) { 14299 + if (additional && (additional || {})?.dataType) {
13773 const { dataType } = additional || {} 14300 const { dataType } = additional || {}
13774 if (dataType === HandleDataSource.enumDataBindType.REAL) { 14301 if (dataType === HandleDataSource.enumDataBindType.REAL) {
13775 this.dataSourceHandlerInstance.updateRealTimeDataSource(message, item) 14302 this.dataSourceHandlerInstance.updateRealTimeDataSource(message, item)
@@ -13821,9 +14348,15 @@ class DispatchCenter { @@ -13821,9 +14348,15 @@ class DispatchCenter {
13821 } 14348 }
13822 14349
13823 afterGetContentDataNode() { 14350 afterGetContentDataNode() {
  14351 + this.handleFlowmeterComponent()
  14352 + this.handleAlarmList()
  14353 + }
  14354 +
  14355 + handleFlowmeterComponent() {
13824 setTimeout(() => { 14356 setTimeout(() => {
13825 const componentType = Sidebar.prototype.enumComponentType 14357 const componentType = Sidebar.prototype.enumComponentType
13826 - const flowmeterComponent = this.contentData.dataSources.filter(item => item.additional && (item.additional || {}).componentType === componentType.FLOWMETER) 14358 + if (!this.contentData?.dataSources) return
  14359 + const flowmeterComponent = this.contentData?.dataSources?.filter(item => item.additional && (item.additional || {}).componentType === componentType.FLOWMETER)
13827 const { MIN_VALUE, MAX_VALUE, BG_COLOR, WAVE_FIRST_COLOR, WAVE_SECOND_COLOR, WAVE_THIRD_COLOR } = HandleDataSource.enumConst 14360 const { MIN_VALUE, MAX_VALUE, BG_COLOR, WAVE_FIRST_COLOR, WAVE_SECOND_COLOR, WAVE_THIRD_COLOR } = HandleDataSource.enumConst
13828 flowmeterComponent.forEach(item => { 14361 flowmeterComponent.forEach(item => {
13829 const { nodeId, additional } = item 14362 const { nodeId, additional } = item
@@ -13853,6 +14386,52 @@ class DispatchCenter { @@ -13853,6 +14386,52 @@ class DispatchCenter {
13853 }, 10); 14386 }, 10);
13854 } 14387 }
13855 14388
  14389 +
  14390 + // 处理告警列表
  14391 + async handleAlarmList() {
  14392 + const componentType = Sidebar.prototype.enumComponentType
  14393 + if (!this.contentData?.dataSources) return
  14394 + const alarmList = this.contentData?.dataSources?.filter(item => item.additional && (item.additional || {}).componentType === componentType.ALARM_LIST)
  14395 + const allCell = Object.entries(this.graph?.getModel()?.cells || {}).map(([_, item]) => item) || []
  14396 + const { UUID } = AlarmListComponent.getAttributeKeys()
  14397 + const { jquery: $ } = layui
  14398 + for (const item of alarmList || []) {
  14399 + const { nodeId, sourceOption } = item || {}
  14400 + const { devicesInfo, autoPlay, interval, startTime, endTime } = sourceOption || {}
  14401 + const node = allCell.find(item => item.id === nodeId)
  14402 + const deviceIds = UseLayUi.parseStringToJSON(devicesInfo, []).map(item => item.deviceId)
  14403 + const id = node.getAttribute(UUID)
  14404 + const element = document.getElementById(id)
  14405 + if (element) {
  14406 + const [err, data] = await to(ConfigurationNodeApi.getAlarmList({ page: 1, pageSize: 30, startTime: Number(startTime), endTime: Number(endTime), deviceIds }))
  14407 + if (err) return
  14408 + if (data?.items && data?.items?.length) {
  14409 + const template = AlarmListComponent.createAlarmItem(data.items)
  14410 + $(`#${id}`).find('.list-wrapper').html(template)
  14411 + } else {
  14412 + $(`#${id}`).find('.list-wrapper').html(`<div>暂无数据</div>`)
  14413 + }
  14414 + if (autoPlay) {
  14415 + const wrapperHeight = $(`#${id}`).height()
  14416 + const listWrapper = $(`#${id}`).find('.list-wrapper')
  14417 + const allHeight = listWrapper.height()
  14418 + const itemHeight = allHeight / listWrapper.children().length
  14419 + let scrollDistance = 0
  14420 + const cancel = RAFSetInterval(() => {
  14421 + try {
  14422 + scrollDistance = itemHeight + scrollDistance
  14423 + if (scrollDistance + wrapperHeight > allHeight) scrollDistance = 0
  14424 + document.getElementById(id).scrollTo({ top: scrollDistance, behavior: 'smooth' })
  14425 + } catch (error) {
  14426 + cancel?.()
  14427 + }
  14428 +
  14429 + }, Number(interval) * 1000)
  14430 + }
  14431 + }
  14432 + }
  14433 + }
  14434 +
13856 sendSubscribeMessage() { 14435 sendSubscribeMessage() {
13857 const message = this.generateSubscribeMessage() 14436 const message = this.generateSubscribeMessage()
13858 this.socket.send(JSON.stringify(message)) 14437 this.socket.send(JSON.stringify(message))
@@ -13890,7 +14469,7 @@ class DispatchCenter { @@ -13890,7 +14469,7 @@ class DispatchCenter {
13890 * orgName?: string, 14469 * orgName?: string,
13891 * slaveDeviceName?: string 14470 * slaveDeviceName?: string
13892 * } 14471 * }
13893 - * }} record 14472 + * }} record
13894 */ 14473 */
13895 const setDeviceMapping = (record) => { 14474 const setDeviceMapping = (record) => {
13896 const { deviceId, slaveDeviceId } = record 14475 const { deviceId, slaveDeviceId } = record
@@ -13906,12 +14485,12 @@ class DispatchCenter { @@ -13906,12 +14485,12 @@ class DispatchCenter {
13906 /** 14485 /**
13907 * @type {{ 14486 * @type {{
13908 * id: string, 14487 * id: string,
13909 - * nodeId: string, 14488 + * nodeId: string,
13910 * deviceId: string, 14489 * deviceId: string,
13911 - * slaveDeviceId: string,  
13912 - * attr: string,  
13913 - * enabled: boolean,  
13914 - * additional: object, 14490 + * slaveDeviceId: string,
  14491 + * attr: string,
  14492 + * enabled: boolean,
  14493 + * additional: object,
13915 * condition: object 14494 * condition: object
13916 * }[]} 14495 * }[]}
13917 */ 14496 */
@@ -13931,10 +14510,10 @@ class DispatchCenter { @@ -13931,10 +14510,10 @@ class DispatchCenter {
13931 }) 14510 })
13932 14511
13933 /** 14512 /**
13934 - * @param {{  
13935 - * entityId: string,  
13936 - * cmdId: number,  
13937 - * keys: string, 14513 + * @param {{
  14514 + * entityId: string,
  14515 + * cmdId: number,
  14516 + * keys: string,
13938 * agg?: string, 14517 * agg?: string,
13939 * interval?: number, 14518 * interval?: number,
13940 * startTs?: number, 14519 * startTs?: number,
@@ -14296,10 +14875,9 @@ class HandleDataSource { @@ -14296,10 +14875,9 @@ class HandleDataSource {
14296 14875
14297 /** 14876 /**
14298 * @description 更新变量值 14877 * @description 更新变量值
14299 - * @param {} message 14878 + * @param {} message
14300 */ 14879 */
14301 updateCommonDataSource(message, record) { 14880 updateCommonDataSource(message, record) {
14302 - console.log('enter')  
14303 const { nodeId, attr } = record 14881 const { nodeId, attr } = record
14304 const node = this.getNodeByNodeId(nodeId) 14882 const node = this.getNodeByNodeId(nodeId)
14305 const { data } = message 14883 const { data } = message
@@ -14337,13 +14915,14 @@ class HandleDataSource { @@ -14337,13 +14915,14 @@ class HandleDataSource {
14337 14915
14338 /** 14916 /**
14339 * @description 处理switch 组件 14917 * @description 处理switch 组件
14340 - * @param {} message 14918 + * @param {} message
14341 */ 14919 */
14342 handleSwitchComponent(message, record) { 14920 handleSwitchComponent(message, record) {
14343 const { data = {} } = message 14921 const { data = {} } = message
14344 const { nodeId, attr } = record 14922 const { nodeId, attr } = record
14345 const node = this.getNodeByNodeId(nodeId) 14923 const node = this.getNodeByNodeId(nodeId)
14346 const [[_timespan, receiveValue] = []] = data[attr] || [] 14924 const [[_timespan, receiveValue] = []] = data[attr] || []
  14925 + if (receiveValue === null || receiveValue === undefined) return
14347 const switchConfig = this.DispatchInstance.contentData.act.find(item => item.id === nodeId && item.type === 'SWITCH') 14926 const switchConfig = this.DispatchInstance.contentData.act.find(item => item.id === nodeId && item.type === 'SWITCH')
14348 const { condition = [] } = switchConfig || {} 14927 const { condition = [] } = switchConfig || {}
14349 let reg = /image=[^;]+/g 14928 let reg = /image=[^;]+/g
@@ -14363,7 +14942,7 @@ class HandleDataSource { @@ -14363,7 +14942,7 @@ class HandleDataSource {
14363 if ((style || '').includes(imagePath)) return 14942 if ((style || '').includes(imagePath)) return
14364 const sendValue = getSendValue(type) 14943 const sendValue = getSendValue(type)
14365 node.setStyle(style.replace(reg, `image=${imagePath}`)) 14944 node.setStyle(style.replace(reg, `image=${imagePath}`))
14366 - node.setAttribute('label', '') 14945 + // node.setAttribute('label', '')
14367 node.setAttribute(SWITCH_VALUE, receiveValue) 14946 node.setAttribute(SWITCH_VALUE, receiveValue)
14368 node.setAttribute(SWITCH_SEND_VALUE, sendValue) 14947 node.setAttribute(SWITCH_SEND_VALUE, sendValue)
14369 node.setAttribute(SWITCH_STATE, type) 14948 node.setAttribute(SWITCH_STATE, type)
@@ -14400,7 +14979,6 @@ class HandleDataSource { @@ -14400,7 +14979,6 @@ class HandleDataSource {
14400 const { maxValue, minValue } = additional || {} 14979 const { maxValue, minValue } = additional || {}
14401 14980
14402 receiveValue = isNaN(receiveValue) ? 0 : Number(receiveValue) 14981 receiveValue = isNaN(receiveValue) ? 0 : Number(receiveValue)
14403 - console.log('enter')  
14404 if (element) { 14982 if (element) {
14405 if (type === flowmeterType.CIRCLE || type === flowmeterType.RECT) { 14983 if (type === flowmeterType.CIRCLE || type === flowmeterType.RECT) {
14406 const element = document.getElementById(id).querySelector('svg') 14984 const element = document.getElementById(id).querySelector('svg')
@@ -14424,8 +15002,9 @@ class HandleDataSource { @@ -14424,8 +15002,9 @@ class HandleDataSource {
14424 const { nodeId, attr } = record 15002 const { nodeId, attr } = record
14425 const node = this.getNodeByNodeId(nodeId) 15003 const node = this.getNodeByNodeId(nodeId)
14426 const [[_timespan, receiveValue] = []] = data[attr] || [] 15004 const [[_timespan, receiveValue] = []] = data[attr] || []
  15005 + if (receiveValue === null || receiveValue === undefined) return
14427 this.updatePage(() => { 15006 this.updatePage(() => {
14428 - node.setAttribute('label', `<button class="param-setting-button">${receiveValue}</button>`) 15007 + node.setAttribute('label', receiveValue)
14429 }, node) 15008 }, node)
14430 } 15009 }
14431 15010
@@ -14441,7 +15020,7 @@ class HandleDataSource { @@ -14441,7 +15020,7 @@ class HandleDataSource {
14441 15020
14442 /** 15021 /**
14443 * @description 更新实时数据 15022 * @description 更新实时数据
14444 - * @param {} message 15023 + * @param {} message
14445 * @param {} record 聚合方式 15024 * @param {} record 聚合方式
14446 */ 15025 */
14447 updateRealTimeDataSource(message, record) { 15026 updateRealTimeDataSource(message, record) {
@@ -14556,9 +15135,9 @@ class HandleDataSource { @@ -14556,9 +15135,9 @@ class HandleDataSource {
14556 } 15135 }
14557 15136
14558 /** 15137 /**
14559 - *  
14560 - * @param {@} params  
14561 - * @returns 15138 + *
  15139 + * @param {@} params
  15140 + * @returns
14562 */ 15141 */
14563 getBasicChartOption(params = { dataList: [], attr: '', chartType: 'bar', action, additional }) { 15142 getBasicChartOption(params = { dataList: [], attr: '', chartType: 'bar', action, additional }) {
14564 const { dataList = [], attr = '', chartType = 'bar', action, additional = {} } = params 15143 const { dataList = [], attr = '', chartType = 'bar', action, additional = {} } = params
@@ -14826,8 +15405,8 @@ class HandleDataSource { @@ -14826,8 +15405,8 @@ class HandleDataSource {
14826 15405
14827 /** 15406 /**
14828 * @description 获取cmdId 15407 * @description 获取cmdId
14829 - * @param {string} nodeId  
14830 - * @returns 15408 + * @param {string} nodeId
  15409 + * @returns
14831 */ 15410 */
14832 getCmdId(nodeId) { 15411 getCmdId(nodeId) {
14833 return this.DispatchInstance.getCmdId(nodeId) 15412 return this.DispatchInstance.getCmdId(nodeId)
@@ -14859,8 +15438,8 @@ class HandleDataSource { @@ -14859,8 +15438,8 @@ class HandleDataSource {
14859 15438
14860 /** 15439 /**
14861 * @description 发送socket 消息 15440 * @description 发送socket 消息
14862 - * @param {any} msg  
14863 - * @returns 15441 + * @param {any} msg
  15442 + * @returns
14864 */ 15443 */
14865 sendMsg(msg) { 15444 sendMsg(msg) {
14866 return this.DispatchInstance.sendMessageToGetRealTimeData(msg) 15445 return this.DispatchInstance.sendMessageToGetRealTimeData(msg)
@@ -15130,7 +15709,6 @@ class HandleDataInteraction { @@ -15130,7 +15709,6 @@ class HandleDataInteraction {
15130 const { COMPONENT_TYPE } = Sidebar.prototype.enumCellBasicAttribute 15709 const { COMPONENT_TYPE } = Sidebar.prototype.enumCellBasicAttribute
15131 const contentData = this.contentData 15710 const contentData = this.contentData
15132 const currentNode = this.contentAllCell.find(item => item.id === nodeId) 15711 const currentNode = this.contentAllCell.find(item => item.id === nodeId)
15133 -  
15134 const enumConst = { 15712 const enumConst = {
15135 VALUE: 'value', 15713 VALUE: 'value',
15136 ISSUED_WAY: 'way', 15714 ISSUED_WAY: 'way',
@@ -15311,7 +15889,7 @@ class HandleDataInteraction { @@ -15311,7 +15889,7 @@ class HandleDataInteraction {
15311 } else { 15889 } else {
15312 const replaceValue = currentNode.getAttribute(SWITCH_SEND_VALUE) 15890 const replaceValue = currentNode.getAttribute(SWITCH_SEND_VALUE)
15313 value = jsonParse(content.jsonCommand) 15891 value = jsonParse(content.jsonCommand)
15314 - value = replaceAttrPlaceholder(value, attr, replaceValue) 15892 + value = replaceAttrPlaceholder(value, attr, isNaN(replaceValue) ? 0 : Number(replaceValue))
15315 if (value) flag = true 15893 if (value) flag = true
15316 } 15894 }
15317 } else { 15895 } else {
@@ -15485,7 +16063,7 @@ class HandleDataInteraction { @@ -15485,7 +16063,7 @@ class HandleDataInteraction {
15485 } 16063 }
15486 16064
15487 try { 16065 try {
15488 - handle[componentType]() 16066 + handle[componentType]?.()
15489 } catch (error) { 16067 } catch (error) {
15490 throw error 16068 throw error
15491 } 16069 }
@@ -15646,7 +16224,7 @@ class HandleDynamicEffect { @@ -15646,7 +16224,7 @@ class HandleDynamicEffect {
15646 } 16224 }
15647 16225
15648 get contentAllCell() { 16226 get contentAllCell() {
15649 - // return this.graph.getDefaultParent().children || [] 16227 + // return this.graph.getDefaultParent().children || []
15650 return Object.entries(this.graph?.getModel()?.cells || {}).map(([_, item]) => item) || [] 16228 return Object.entries(this.graph?.getModel()?.cells || {}).map(([_, item]) => item) || []
15651 } 16229 }
15652 16230
@@ -16048,8 +16626,8 @@ class HandleDynamicEffect { @@ -16048,8 +16626,8 @@ class HandleDynamicEffect {
16048 16626
16049 /** 16627 /**
16050 * @description 验证数据动效优先级 显示隐藏优先级最高 16628 * @description 验证数据动效优先级 显示隐藏优先级最高
16051 - * @param {string} nodeId  
16052 - * @returns 16629 + * @param {string} nodeId
  16630 + * @returns
16053 */ 16631 */
16054 validatePriority(nodeId) { 16632 validatePriority(nodeId) {
16055 return this.actNodeMapping.get(nodeId).display 16633 return this.actNodeMapping.get(nodeId).display
@@ -16083,7 +16661,7 @@ class UpdateQueue { @@ -16083,7 +16661,7 @@ class UpdateQueue {
16083 16661
16084 /** 16662 /**
16085 * @description 创建更新队列 16663 * @description 创建更新队列
16086 - * @param {number} time 16664 + * @param {number} time
16087 */ 16665 */
16088 createUpdateQueue(time) { 16666 createUpdateQueue(time) {
16089 const callback = () => { 16667 const callback = () => {
@@ -16237,13 +16815,13 @@ function RAFSetInterval(callback, time) { @@ -16237,13 +16815,13 @@ function RAFSetInterval(callback, time) {
16237 class Validate { 16815 class Validate {
16238 /** 16816 /**
16239 * @description 16817 * @description
16240 - * @type {{value: any, message: string, required?: boolean, validator?: any}[]} list 16818 + * @type {{value: any, message: string, required?: boolean, validator?: any}[]} list
16241 */ 16819 */
16242 list = [] 16820 list = []
16243 16821
16244 /** 16822 /**
16245 * @description 16823 * @description
16246 - * @param {{value: any, message: string, required?: boolean, validator?: any}[]} ruleList 16824 + * @param {{value: any, message: string, required?: boolean, validator?: any}[]} ruleList
16247 */ 16825 */
16248 constructor(ruleList = []) { 16826 constructor(ruleList = []) {
16249 this.list = ruleList 16827 this.list = ruleList
@@ -16255,7 +16833,7 @@ class Validate { @@ -16255,7 +16833,7 @@ class Validate {
16255 16833
16256 /** 16834 /**
16257 * @description 设置规则 16835 * @description 设置规则
16258 - * @param {{value: any, message: string, required?: boolean, validator?: any}} rule 16836 + * @param {{value: any, message: string, required?: boolean, validator?: any}} rule
16259 */ 16837 */
16260 set(rule) { 16838 set(rule) {
16261 this.list.push(rule) 16839 this.list.push(rule)
@@ -167,6 +167,10 @@ @@ -167,6 +167,10 @@
167 table-layout: fixed; 167 table-layout: fixed;
168 } 168 }
169 169
  170 +.override__table .org-tree .layui-input-block {
  171 + margin-left: 0;
  172 +}
  173 +
170 /**/ 174 /**/
171 .override__radio-default { 175 .override__radio-default {
172 margin-right: 16px; 176 margin-right: 16px;
@@ -503,36 +507,6 @@ @@ -503,36 +507,6 @@
503 margin-left: 0; 507 margin-left: 0;
504 } 508 }
505 509
506 -/* 参数设置按钮 */  
507 -.param-setting-button {  
508 - color: #fff;  
509 - border-color: #1890ff;  
510 - background: #1890ff;  
511 - text-shadow: 0 -1px 0 rgb(0 0 0 / 12%);  
512 - box-shadow: 0 2px #0000000b;  
513 -  
514 - line-height: 1.5715;  
515 - position: relative;  
516 - display: inline-block;  
517 - font-weight: 400;  
518 - white-space: nowrap;  
519 - text-align: center;  
520 - background-image: none;  
521 - border: 1px solid transparent;  
522 - box-shadow: 0 2px #00000004;  
523 - cursor: pointer;  
524 - transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);  
525 - -webkit-user-select: none;  
526 - -moz-user-select: none;  
527 - -ms-user-select: none;  
528 - user-select: none;  
529 - touch-action: manipulation;  
530 - height: 32px;  
531 - padding: 4px 15px;  
532 - font-size: 14px;  
533 - border-radius: 2px;  
534 -}  
535 -  
536 /* ========== help message ========== */ 510 /* ========== help message ========== */
537 .thingskit-help-message { 511 .thingskit-help-message {
538 cursor: pointer; 512 cursor: pointer;