Просмотр исходного кода

nor web增加告警显示等功能

liyi 1 год назад
Родитель
Сommit
6f3cda6514

+ 29 - 4
nor_web/api/channel_display.js

@@ -10,6 +10,7 @@ function channel_display(j_data, channel_power_infro) {
     length = channel_power_infro.length
     for (let j = 1; j < length; j++) {
         let alarm=channel_power_infro[j].alarm;
+        let thr=channel_power_infro[j].thr;
         num = channel_power_infro[j].info.type
             // 创建一个新的列表项元素
         const channelFormData1 = {
@@ -31,10 +32,31 @@ function channel_display(j_data, channel_power_infro) {
             const channelFormData = {
 
             };
-            if(alarm.c_upper!=0 || alarm.p_upper!=0 || alarm.v_lower!=0 || alarm.v_upper!=0 || alarm.w_upper!=0){
-                channelFormData.colorStyle='color: red;'
+
+            if(alarm.c_upper!=0){
+                channelFormData.colorStyledl='color: red;font-weight: bold;'
+            }else{
+                channelFormData.colorStyledl=''
+            }
+            if( alarm.p_upper!=0 ){
+                channelFormData.colorStylegl='color: red;font-weight: bold;'
+            }else{
+                channelFormData.colorStylegl=''
+            }
+            if( alarm.v_lower!=0){
+                channelFormData.colorStyledy2='color: #ff00ff;font-weight: bold;'
+            }else{
+                channelFormData.colorStyledy2=''
+            }
+            if( alarm.v_upper!=0){
+                channelFormData.colorStyledy='color: red;font-weight: bold;'
+            }else{
+                channelFormData.colorStyledy=''
+            }
+            if(alarm.w_upper!=0){
+                channelFormData.colorStylehdl='color: red;font-weight: bold;'
             }else{
-                channelFormData.colorStyle=''
+                channelFormData.colorStylehdl=''
             }
             //自动生成设备名称列
 
@@ -90,7 +112,10 @@ function channel_display(j_data, channel_power_infro) {
 
                 };
                 if(alarm.c_upper!=0 || alarm.p_upper!=0 || alarm.v_lower!=0 || alarm.v_upper!=0 || alarm.w_upper!=0){
-                    channelFormData.colorStyle='color: red;'
+                    channelFormData.colorStyledy='color: red;'
+                    channelFormData.colorStyledl='color: red;'
+                    channelFormData.colorStylegl='color: red;'
+                    channelFormData.colorStylehdl='color: red;'
                 }else{
                     channelFormData.colorStyle=''
                 }

+ 30 - 3
nor_web/api/data.js

@@ -1558,7 +1558,23 @@ function bin_to_sys(bin) {
 
 }
 
+function bin_to_his_alarm(bin) {
+    var tmp, length = 0;
+
+    tmp = new DataView(bin, length);
 
+    this.type = tmp.getUint8(0, true);
+    length += 1;
+
+    this.date = array_to_string(bin.slice(length, length + 32));
+    length += 32;
+
+    this.waning_context = array_to_string(bin.slice(length, length + 64));
+    length += 64;
+
+    this.len = length;
+
+}
 
 
 function bin_to_snmp(bin) {
@@ -1653,11 +1669,22 @@ function bin_parse(bin) {
                 break;
 
             case PKT_TYPE.PKT_TYPE_ALARM:
-                h.alarmd = new bin_to_alarm(data);
+                {
+                    var length = 0;
+                    var tmp = [];
+                    for (var i = 0;; i++) {
+                        tmp[i] = new bin_to_his_alarm(data.slice(length));
+                        length += tmp[i].len;
+                        if (length >= data.byteLength) {
+                            break;
+                        }
+                    }
+                    h.his_alarmd = tmp;
+                }
                 break;
 
             case PKT_TYPE.PKT_TYPE_SLAVE_LIST:
-                h.alarmd = new bin_to_slist(data);
+                //h.alarmd = new bin_to_slist(data);
                 break;
 
             case PKT_TYPE.PKT_TYPE_PARAS:
@@ -1779,7 +1806,7 @@ function WS(url, fn) {
     function loop_send() {
         console.log("PKT_TYPE_POWER_CH request");
         _send(mk_hdr(PKT_TYPE.PKT_TYPE_POWER_CH));
-        setTimeout(loop_send, 2000);
+        setTimeout(loop_send, 400);
     }
 
 

+ 32 - 30
nor_web/api/display_data.js

@@ -1,34 +1,35 @@
-function total_Infor(j, total_data, type) {
-    initialTotalFormList = [];
+function total_Infor(j, total_data,type) {
+    initialTotalFormList=[];
     len = total_data.length
         //显示总信息
-    for (let i = 0; i <= len - 1; i++) {
+    for (let i = 0; i <=len-1; i++) {
         num = i + 1
         voltage = total_data[i].voltage.toFixed(2)
         current = total_data[i].current.toFixed(2)
         power = total_data[i].power
+        power = power / 1000
         power = power.toFixed(3)
         consump = total_data[i].consump.toFixed(2)
-            // if (consump <= 0) {
-            //     consump = 0
-            // }
-            // consump = consump / 1000
-            // consump = consump.toFixed(3)
+        // if (consump <= 0) {
+        //     consump = 0
+        // }
+        // consump = consump / 1000
+        // consump = consump.toFixed(3)
         freq = total_data[i].freq.toFixed(2)
-        if (type == '0') {
-            initialFormData.totalVoltage = voltage; // 总电压
-            initialFormData.totalCurrent = current; // 总电流
-            initialFormData.totalPower = power; // 总功率
-            initialFormData.totalFrequency = freq; // 总频率
-            initialFormData.totalEnergy = consump; // 总耗电量
+        if(type=='0'){
+            initialFormData.totalVoltage=voltage ; // 总电压
+            initialFormData.totalCurrent=current ; // 总电流
+            initialFormData.totalPower=power;  // 总功率
+            initialFormData.totalFrequency=freq; // 总频率
+            initialFormData.totalEnergy=consump; // 总耗电量
             break
-        } else {
+        }else{
             const initialChFormData = {};
-            initialChFormData.totalVoltage = voltage; // 总电压
-            initialChFormData.totalCurrent = current; // 总电流
-            initialChFormData.totalPower = power; // 总功率
-            initialChFormData.totalFrequency = freq; // 总频率
-            initialChFormData.totalEnergy = consump; // 总耗电量
+            initialChFormData.totalVoltage=voltage ; // 总电压
+            initialChFormData.totalCurrent=current ; // 总电流
+            initialChFormData.totalPower=power;  // 总功率
+            initialChFormData.totalFrequency=freq; // 总频率
+            initialChFormData.totalEnergy=consump; // 总耗电量
             initialTotalFormList.push(initialChFormData);
         }
 
@@ -48,30 +49,30 @@ function threshold_mannage(orgin_data, channel_power_infro) {
     // const dataList = document.getElementById('threshold_mannage');
     // // 清空现有的列表项
     // dataList.innerHTML = '';
-    initialYzFormList = [];
+    initialYzFormList=[];
     channel_length = channel_power_infro.length
         //遍历数据数组
     for (let j = 1; j < channel_length; j++) {
         const initialChFormData = {};
         //自动生成名称列
-        initialChFormData.productChName = "CH" + j;
+        initialChFormData.productChName="CH" + j;
         //自动生成编号列
-        initialChFormData.productChId = j;
+        initialChFormData.productChId=j;
         //自动生成电流上限列
-        initialChFormData.currentUpperAction = channel_power_infro[j].thr.c_upper / 10.0;
+        initialChFormData.currentUpperAction= channel_power_infro[j].thr.c_upper / 10.0;
 
         // 自动生成电压上限列
-        initialChFormData.voltageUpperAction = channel_power_infro[j].thr.v_upper / 10.0;
+        initialChFormData.voltageUpperAction=channel_power_infro[j].thr.v_upper / 10.0;
 
         // 自动生成电压下限列
-        initialChFormData.voltageDownAction = channel_power_infro[j].thr.v_lower / 10.0;
+        initialChFormData.voltageDownAction=channel_power_infro[j].thr.v_lower / 10.0;
 
         // 自动生成功率上限列
-        initialChFormData.powerUpperAction = channel_power_infro[j].thr.p_upper / 1000.0;
+        initialChFormData.powerUpperAction=channel_power_infro[j].thr.p_upper / 1000.0;
 
         // 自动生成耗电量上限列
-        initialChFormData.alarmContentUpperAction = channel_power_infro[j].thr.w_upper / 1000.0;
-        initialChFormData.channel_power_infro = channel_power_infro[j]
+        initialChFormData.alarmContentUpperAction=channel_power_infro[j].thr.w_upper / 1000.0;
+        initialChFormData.channel_power_infro=channel_power_infro[j]
         initialYzFormList.push(initialChFormData);
     }
 }
@@ -103,4 +104,5 @@ let initialFormData = {
 let initialYzFormList = [];
 
 
-let channel_power_infro1 = [];
+let channel_power_infro1=[];
+

+ 1 - 0
nor_web/api/operation.js

@@ -98,6 +98,7 @@ function function1() {
     ws.send(mk_hdr_bin(0, PKT_TYPE.PKT_TYPE_POWER_CH, 0, 0, 0));
     ws.send(mk_hdr_bin(0, PKT_TYPE.PKT_TYPE_SENSOR, 0, 0, 0, 0));
     ws.send(mk_hdr_bin(0, PKT_TYPE.PKT_TYPE_PARAS, SUB_TYPE.SUB_TYPE_PARAS_SYS, 0, 0, 0));
+    ws.send(mk_hdr_bin(0, PKT_TYPE.PKT_TYPE_ALARM, 0, 0, 0, 0));
 }
 
 //获取网络配置信息

+ 10 - 3
nor_web/api/ws.js

@@ -13,6 +13,8 @@ let lang_data = {}
 
 let sensor_data = {}
 
+let his_alarm = []
+
 function on_ws_msg(js) {
     console.log("执行")
 
@@ -72,13 +74,18 @@ function on_ws_msg(js) {
         sensorc_list = [];
         // 传感器
         sensorc_list = js.sensorc
-        console.log(sensorc_list)
+            // console.log(sensorc_list)
     }
     if (js.sys != undefined) {
         lang_data = js.sys
             // console.log(lang_data)
     }
 
+    if (js.his_alarmd != undefined) {
+        his_alarm = js.his_alarmd;
+        console.log(his_alarm)
+    }
+
 }
 
 function alarm_process(alarmd_data) {
@@ -121,7 +128,7 @@ function setActivePage(pageFunction, intervalTime) {
     activePageIntervalId = setInterval(pageFunction, intervalTime);
 }
 
-ws = new WS('ws://' + window.location.host + '/ws', on_ws_msg);
+ws = new WS('ws://'+window.location.host+'/ws',on_ws_msg);
 
 // ws = new WS('ws://192.168.1.134/ws', on_ws_msg);
-// ws = new WS('ws://192.168.1.134/websocket/TMS-WebSocket', on_ws_msg);
+//ws = new WS('ws://192.168.1.134/websocket/TMS-WebSocket', on_ws_msg);

+ 156 - 2
nor_web/css/index.css

@@ -248,7 +248,7 @@ html, body {
     border-radius: 8px;
     max-width: 500px;
     width: 80%;
-    max-height: 80vh;
+    max-height: 95vh;
     overflow-y: auto;
 }
 
@@ -455,4 +455,158 @@ thead {
     border-radius: 8px;
     box-shadow: 0 2px 10px rgb(0 0 0 / 10%);
     overflow: hidden;
-}
+}
+
+
+
+/*-----------------*/
+header {
+    text-align: center;
+    margin-bottom: 30px;
+    padding: 20px;
+    background: white;
+    border-radius: 10px;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+}
+
+h1 {
+    color: #2c3e50;
+    margin-bottom: 10px;
+}
+
+.description {
+    color: #7f8c8d;
+    font-size: 1.1rem;
+    max-width: 600px;
+    margin: 0 auto;
+}
+
+.multi-select-container {
+    background: white;
+    border-radius: 10px;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+    padding: 20px;
+    margin-bottom: 30px;
+}
+
+.select-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 15px;
+    padding-bottom: 10px;
+    border-bottom: 1px solid #eee;
+}
+
+.select-title {
+    font-weight: 600;
+    color: #2c3e50;
+}
+
+.select-all {
+    background: none;
+    border: none;
+    color: #3498db;
+    cursor: pointer;
+    font-size: 0.9rem;
+    font-weight: 500;
+    padding: 5px 10px;
+    border-radius: 4px;
+}
+
+.select-all:hover {
+    background-color: #f1f8ff;
+}
+
+select[multiple] {
+    width: 100%;
+    padding: 10px;
+    border: 1px solid #ddd;
+    border-radius: 4px;
+    background-color: #f8f9fa;
+    height: 200px;
+    margin-bottom: 15px;
+}
+
+select[multiple] option {
+    padding: 8px;
+    margin: 4px 0;
+    border-radius: 4px;
+}
+
+select[multiple] option:hover {
+    background-color: #e3f2fd;
+}
+
+select[multiple] option:checked {
+    background-color: #3498db;
+    color: white;
+}
+
+.selected-count {
+    margin-top: 15px;
+    font-size: 0.9rem;
+    color: #7f8c8d;
+}
+
+.selected-items {
+    /*margin-top: 20px;*/
+    padding: 15px;
+    background-color: #f8f9fa;
+    border-radius: 6px;
+    border-left: 4px solid #3498db;
+}
+
+.selected-items h3 {
+    margin-bottom: 10px;
+    color: #2c3e50;
+    font-size: 1rem;
+}
+
+.selected-tags {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 8px;
+}
+
+.tag {
+    background-color: #3498db;
+    color: white;
+    padding: 5px 10px;
+    border-radius: 20px;
+    font-size: 0.85rem;
+    display: flex;
+    align-items: center;
+}
+
+.tag button {
+    background: none;
+    border: none;
+    color: white;
+    margin-left: 5px;
+    cursor: pointer;
+    font-weight: bold;
+}
+
+.no-selection {
+    color: #95a5a6;
+    font-style: italic;
+}
+
+.code-example {
+    background-color: #2d2d2d;
+    color: #f8f8f2;
+    padding: 15px;
+    border-radius: 5px;
+    margin-top: 20px;
+    overflow-x: auto;
+    font-family: 'Fira Code', monospace;
+}
+
+footer {
+    text-align: center;
+    margin-top: 40px;
+    color: #7f8c8d;
+    font-size: 0.9rem;
+}
+

+ 33 - 8
nor_web/h_html/channel_display.h

@@ -1,7 +1,7 @@
 /* 自动生成的文本数据头文件 */
 /* 源文件: channel_display.js */
-/* 文件大小: 5403 字节 */
-/* 生成时间: 2025-09-12 05:42:04 */
+/* 文件大小: 6362 字节 */
+/* 生成时间: 2025-09-16 05:47:15 */
 /* 编码: utf-8 */
 #ifndef P_CHANNEL_DISPLAY_H
 #define P_CHANNEL_DISPLAY_H
@@ -22,6 +22,7 @@ const char *p_channel_display =
     "    length = channel_power_infro.length\n"
     "    for (let j = 1; j < length; j++) {\n"
     "        let alarm=channel_power_infro[j].alarm;\n"
+    "        let thr=channel_power_infro[j].thr;\n"
     "        num = channel_power_infro[j].info.type\n"
     "            // 创建一个新的列表项元素\n"
     "        const channelFormData1 = {\n"
@@ -43,10 +44,31 @@ const char *p_channel_display =
     "            const channelFormData = {\n"
     
     "            };\n"
-    "            if(alarm.c_upper!=0 || alarm.p_upper!=0 || alarm.v_lower!=0 || alarm.v_upper!=0 || alarm.w_upper!=0){\n"
-    "                channelFormData.colorStyle='color: red;'\n"
+    
+    "            if(alarm.c_upper!=0){\n"
+    "                channelFormData.colorStyledl='color: red;font-weight: bold;'\n"
+    "            }else{\n"
+    "                channelFormData.colorStyledl=''\n"
+    "            }\n"
+    "            if( alarm.p_upper!=0 ){\n"
+    "                channelFormData.colorStylegl='color: red;font-weight: bold;'\n"
+    "            }else{\n"
+    "                channelFormData.colorStylegl=''\n"
+    "            }\n"
+    "            if( alarm.v_lower!=0){\n"
+    "                channelFormData.colorStyledy2='color: #ff00ff;font-weight: bold;'\n"
+    "            }else{\n"
+    "                channelFormData.colorStyledy2=''\n"
+    "            }\n"
+    "            if( alarm.v_upper!=0){\n"
+    "                channelFormData.colorStyledy='color: red;font-weight: bold;'\n"
+    "            }else{\n"
+    "                channelFormData.colorStyledy=''\n"
+    "            }\n"
+    "            if(alarm.w_upper!=0){\n"
+    "                channelFormData.colorStylehdl='color: red;font-weight: bold;'\n"
     "            }else{\n"
-    "                channelFormData.colorStyle=''\n"
+    "                channelFormData.colorStylehdl=''\n"
     "            }\n"
     "            //自动生成设备名称列\n"
     
@@ -102,7 +124,10 @@ const char *p_channel_display =
     
     "                };\n"
     "                if(alarm.c_upper!=0 || alarm.p_upper!=0 || alarm.v_lower!=0 || alarm.v_upper!=0 || alarm.w_upper!=0){\n"
-    "                    channelFormData.colorStyle='color: red;'\n"
+    "                    channelFormData.colorStyledy='color: red;'\n"
+    "                    channelFormData.colorStyledl='color: red;'\n"
+    "                    channelFormData.colorStylegl='color: red;'\n"
+    "                    channelFormData.colorStylehdl='color: red;'\n"
     "                }else{\n"
     "                    channelFormData.colorStyle=''\n"
     "                }\n"
@@ -165,9 +190,9 @@ const char *p_channel_display =
 ;
 
 // 文本数据大小(包括null终止符)
-const size_t p_channel_display_size = 5404;
+const size_t p_channel_display_size = 6363;
 
 // 文本长度(字符数)
-const size_t p_channel_display_length = 4969;
+const size_t p_channel_display_length = 5928;
 
 #endif /* P_CHANNEL_DISPLAY_H */

+ 34 - 7
nor_web/h_html/data_js.h

@@ -1,7 +1,7 @@
 /* 自动生成的文本数据头文件 */
 /* 源文件: data.js */
-/* 文件大小: 42870 字节 */
-/* 生成时间: 2025-09-12 05:42:05 */
+/* 文件大小: 43628 字节 */
+/* 生成时间: 2025-09-16 05:47:16 */
 /* 编码: utf-8 */
 #ifndef P_DATA_JS_H
 #define P_DATA_JS_H
@@ -1570,7 +1570,23 @@ const char *p_data_js =
     
     "}\n"
     
+    "function bin_to_his_alarm(bin) {\n"
+    "    var tmp, length = 0;\n"
+    
+    "    tmp = new DataView(bin, length);\n"
     
+    "    this.type = tmp.getUint8(0, true);\n"
+    "    length += 1;\n"
+    
+    "    this.date = array_to_string(bin.slice(length, length + 32));\n"
+    "    length += 32;\n"
+    
+    "    this.waning_context = array_to_string(bin.slice(length, length + 64));\n"
+    "    length += 64;\n"
+    
+    "    this.len = length;\n"
+    
+    "}\n"
     
     
     "function bin_to_snmp(bin) {\n"
@@ -1665,11 +1681,22 @@ const char *p_data_js =
     "                break;\n"
     
     "            case PKT_TYPE.PKT_TYPE_ALARM:\n"
-    "                h.alarmd = new bin_to_alarm(data);\n"
+    "                {\n"
+    "                    var length = 0;\n"
+    "                    var tmp = [];\n"
+    "                    for (var i = 0;; i++) {\n"
+    "                        tmp[i] = new bin_to_his_alarm(data.slice(length));\n"
+    "                        length += tmp[i].len;\n"
+    "                        if (length >= data.byteLength) {\n"
+    "                            break;\n"
+    "                        }\n"
+    "                    }\n"
+    "                    h.his_alarmd = tmp;\n"
+    "                }\n"
     "                break;\n"
     
     "            case PKT_TYPE.PKT_TYPE_SLAVE_LIST:\n"
-    "                h.alarmd = new bin_to_slist(data);\n"
+    "                //h.alarmd = new bin_to_slist(data);\n"
     "                break;\n"
     
     "            case PKT_TYPE.PKT_TYPE_PARAS:\n"
@@ -1791,7 +1818,7 @@ const char *p_data_js =
     "    function loop_send() {\n"
     "        console.log(\"PKT_TYPE_POWER_CH request\");\n"
     "        _send(mk_hdr(PKT_TYPE.PKT_TYPE_POWER_CH));\n"
-    "        setTimeout(loop_send, 2000);\n"
+    "        setTimeout(loop_send, 400);\n"
     "    }\n"
     
     
@@ -1832,9 +1859,9 @@ const char *p_data_js =
 ;
 
 // 文本数据大小(包括null终止符)
-const size_t p_data_js_size = 42871;
+const size_t p_data_js_size = 43629;
 
 // 文本长度(字符数)
-const size_t p_data_js_length = 42788;
+const size_t p_data_js_length = 43546;
 
 #endif /* P_DATA_JS_H */

+ 36 - 34
nor_web/h_html/display_data.h

@@ -1,7 +1,7 @@
 /* 自动生成的文本数据头文件 */
 /* 源文件: display_data.js */
-/* 文件大小: 3755 字节 */
-/* 生成时间: 2025-09-12 05:42:13 */
+/* 文件大小: 3721 字节 */
+/* 生成时间: 2025-09-16 05:47:24 */
 /* 编码: utf-8 */
 #ifndef P_DISPLAY_DATA_H
 #define P_DISPLAY_DATA_H
@@ -10,37 +10,38 @@
 
 // 文本数据(UTF-8编码)
 const char *p_display_data = 
-    "function total_Infor(j, total_data, type) {\n"
-    "    initialTotalFormList = [];\n"
+    "function total_Infor(j, total_data,type) {\n"
+    "    initialTotalFormList=[];\n"
     "    len = total_data.length\n"
     "        //显示总信息\n"
-    "    for (let i = 0; i <= len - 1; i++) {\n"
+    "    for (let i = 0; i <=len-1; i++) {\n"
     "        num = i + 1\n"
     "        voltage = total_data[i].voltage.toFixed(2)\n"
     "        current = total_data[i].current.toFixed(2)\n"
     "        power = total_data[i].power\n"
+    "        power = power / 1000\n"
     "        power = power.toFixed(3)\n"
     "        consump = total_data[i].consump.toFixed(2)\n"
-    "            // if (consump <= 0) {\n"
-    "            //     consump = 0\n"
-    "            // }\n"
-    "            // consump = consump / 1000\n"
-    "            // consump = consump.toFixed(3)\n"
+    "        // if (consump <= 0) {\n"
+    "        //     consump = 0\n"
+    "        // }\n"
+    "        // consump = consump / 1000\n"
+    "        // consump = consump.toFixed(3)\n"
     "        freq = total_data[i].freq.toFixed(2)\n"
-    "        if (type == '0') {\n"
-    "            initialFormData.totalVoltage = voltage; // 总电压\n"
-    "            initialFormData.totalCurrent = current; // 总电流\n"
-    "            initialFormData.totalPower = power; // 总功率\n"
-    "            initialFormData.totalFrequency = freq; // 总频率\n"
-    "            initialFormData.totalEnergy = consump; // 总耗电量\n"
+    "        if(type=='0'){\n"
+    "            initialFormData.totalVoltage=voltage ; // 总电压\n"
+    "            initialFormData.totalCurrent=current ; // 总电流\n"
+    "            initialFormData.totalPower=power;  // 总功率\n"
+    "            initialFormData.totalFrequency=freq; // 总频率\n"
+    "            initialFormData.totalEnergy=consump; // 总耗电量\n"
     "            break\n"
-    "        } else {\n"
+    "        }else{\n"
     "            const initialChFormData = {};\n"
-    "            initialChFormData.totalVoltage = voltage; // 总电压\n"
-    "            initialChFormData.totalCurrent = current; // 总电流\n"
-    "            initialChFormData.totalPower = power; // 总功率\n"
-    "            initialChFormData.totalFrequency = freq; // 总频率\n"
-    "            initialChFormData.totalEnergy = consump; // 总耗电量\n"
+    "            initialChFormData.totalVoltage=voltage ; // 总电压\n"
+    "            initialChFormData.totalCurrent=current ; // 总电流\n"
+    "            initialChFormData.totalPower=power;  // 总功率\n"
+    "            initialChFormData.totalFrequency=freq; // 总频率\n"
+    "            initialChFormData.totalEnergy=consump; // 总耗电量\n"
     "            initialTotalFormList.push(initialChFormData);\n"
     "        }\n"
     
@@ -60,30 +61,30 @@ const char *p_display_data =
     "    // const dataList = document.getElementById('threshold_mannage');\n"
     "    // // 清空现有的列表项\n"
     "    // dataList.innerHTML = '';\n"
-    "    initialYzFormList = [];\n"
+    "    initialYzFormList=[];\n"
     "    channel_length = channel_power_infro.length\n"
     "        //遍历数据数组\n"
     "    for (let j = 1; j < channel_length; j++) {\n"
     "        const initialChFormData = {};\n"
     "        //自动生成名称列\n"
-    "        initialChFormData.productChName = \"CH\" + j;\n"
+    "        initialChFormData.productChName=\"CH\" + j;\n"
     "        //自动生成编号列\n"
-    "        initialChFormData.productChId = j;\n"
+    "        initialChFormData.productChId=j;\n"
     "        //自动生成电流上限列\n"
-    "        initialChFormData.currentUpperAction = channel_power_infro[j].thr.c_upper / 10.0;\n"
+    "        initialChFormData.currentUpperAction= channel_power_infro[j].thr.c_upper / 10.0;\n"
     
     "        // 自动生成电压上限列\n"
-    "        initialChFormData.voltageUpperAction = channel_power_infro[j].thr.v_upper / 10.0;\n"
+    "        initialChFormData.voltageUpperAction=channel_power_infro[j].thr.v_upper / 10.0;\n"
     
     "        // 自动生成电压下限列\n"
-    "        initialChFormData.voltageDownAction = channel_power_infro[j].thr.v_lower / 10.0;\n"
+    "        initialChFormData.voltageDownAction=channel_power_infro[j].thr.v_lower / 10.0;\n"
     
     "        // 自动生成功率上限列\n"
-    "        initialChFormData.powerUpperAction = channel_power_infro[j].thr.p_upper / 1000.0;\n"
+    "        initialChFormData.powerUpperAction=channel_power_infro[j].thr.p_upper / 1000.0;\n"
     
     "        // 自动生成耗电量上限列\n"
-    "        initialChFormData.alarmContentUpperAction = channel_power_infro[j].thr.w_upper / 1000.0;\n"
-    "        initialChFormData.channel_power_infro = channel_power_infro[j]\n"
+    "        initialChFormData.alarmContentUpperAction=channel_power_infro[j].thr.w_upper / 1000.0;\n"
+    "        initialChFormData.channel_power_infro=channel_power_infro[j]\n"
     "        initialYzFormList.push(initialChFormData);\n"
     "    }\n"
     "}\n"
@@ -115,13 +116,14 @@ const char *p_display_data =
     "let initialYzFormList = [];\n"
     
     
-    "let channel_power_infro1 = [];"
+    "let channel_power_infro1=[];\n"
+    
 ;
 
 // 文本数据大小(包括null终止符)
-const size_t p_display_data_size = 3756;
+const size_t p_display_data_size = 3722;
 
 // 文本长度(字符数)
-const size_t p_display_data_length = 3439;
+const size_t p_display_data_length = 3405;
 
 #endif /* P_DISPLAY_DATA_H */

+ 160 - 6
nor_web/h_html/index_css.h

@@ -1,7 +1,7 @@
 /* 自动生成的文本数据头文件 */
 /* 源文件: index.css */
-/* 文件大小: 8112 字节 */
-/* 生成时间: 2025-09-12 05:42:15 */
+/* 文件大小: 10638 字节 */
+/* 生成时间: 2025-09-16 05:47:26 */
 /* 编码: utf-8 */
 #ifndef P_CSS_INDEX_H
 #define P_CSS_INDEX_H
@@ -260,7 +260,7 @@ const char *p_css_index =
     "    border-radius: 8px;\n"
     "    max-width: 500px;\n"
     "    width: 80%;\n"
-    "    max-height: 80vh;\n"
+    "    max-height: 95vh;\n"
     "    overflow-y: auto;\n"
     "}\n"
     
@@ -467,13 +467,167 @@ const char *p_css_index =
     "    border-radius: 8px;\n"
     "    box-shadow: 0 2px 10px rgb(0 0 0 / 10%);\n"
     "    overflow: hidden;\n"
-    "}"
+    "}\n"
+    
+    
+    
+    "/*-----------------*/\n"
+    "header {\n"
+    "    text-align: center;\n"
+    "    margin-bottom: 30px;\n"
+    "    padding: 20px;\n"
+    "    background: white;\n"
+    "    border-radius: 10px;\n"
+    "    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n"
+    "}\n"
+    
+    "h1 {\n"
+    "    color: #2c3e50;\n"
+    "    margin-bottom: 10px;\n"
+    "}\n"
+    
+    ".description {\n"
+    "    color: #7f8c8d;\n"
+    "    font-size: 1.1rem;\n"
+    "    max-width: 600px;\n"
+    "    margin: 0 auto;\n"
+    "}\n"
+    
+    ".multi-select-container {\n"
+    "    background: white;\n"
+    "    border-radius: 10px;\n"
+    "    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n"
+    "    padding: 20px;\n"
+    "    margin-bottom: 30px;\n"
+    "}\n"
+    
+    ".select-header {\n"
+    "    display: flex;\n"
+    "    justify-content: space-between;\n"
+    "    align-items: center;\n"
+    "    margin-bottom: 15px;\n"
+    "    padding-bottom: 10px;\n"
+    "    border-bottom: 1px solid #eee;\n"
+    "}\n"
+    
+    ".select-title {\n"
+    "    font-weight: 600;\n"
+    "    color: #2c3e50;\n"
+    "}\n"
+    
+    ".select-all {\n"
+    "    background: none;\n"
+    "    border: none;\n"
+    "    color: #3498db;\n"
+    "    cursor: pointer;\n"
+    "    font-size: 0.9rem;\n"
+    "    font-weight: 500;\n"
+    "    padding: 5px 10px;\n"
+    "    border-radius: 4px;\n"
+    "}\n"
+    
+    ".select-all:hover {\n"
+    "    background-color: #f1f8ff;\n"
+    "}\n"
+    
+    "select[multiple] {\n"
+    "    width: 100%;\n"
+    "    padding: 10px;\n"
+    "    border: 1px solid #ddd;\n"
+    "    border-radius: 4px;\n"
+    "    background-color: #f8f9fa;\n"
+    "    height: 200px;\n"
+    "    margin-bottom: 15px;\n"
+    "}\n"
+    
+    "select[multiple] option {\n"
+    "    padding: 8px;\n"
+    "    margin: 4px 0;\n"
+    "    border-radius: 4px;\n"
+    "}\n"
+    
+    "select[multiple] option:hover {\n"
+    "    background-color: #e3f2fd;\n"
+    "}\n"
+    
+    "select[multiple] option:checked {\n"
+    "    background-color: #3498db;\n"
+    "    color: white;\n"
+    "}\n"
+    
+    ".selected-count {\n"
+    "    margin-top: 15px;\n"
+    "    font-size: 0.9rem;\n"
+    "    color: #7f8c8d;\n"
+    "}\n"
+    
+    ".selected-items {\n"
+    "    /*margin-top: 20px;*/\n"
+    "    padding: 15px;\n"
+    "    background-color: #f8f9fa;\n"
+    "    border-radius: 6px;\n"
+    "    border-left: 4px solid #3498db;\n"
+    "}\n"
+    
+    ".selected-items h3 {\n"
+    "    margin-bottom: 10px;\n"
+    "    color: #2c3e50;\n"
+    "    font-size: 1rem;\n"
+    "}\n"
+    
+    ".selected-tags {\n"
+    "    display: flex;\n"
+    "    flex-wrap: wrap;\n"
+    "    gap: 8px;\n"
+    "}\n"
+    
+    ".tag {\n"
+    "    background-color: #3498db;\n"
+    "    color: white;\n"
+    "    padding: 5px 10px;\n"
+    "    border-radius: 20px;\n"
+    "    font-size: 0.85rem;\n"
+    "    display: flex;\n"
+    "    align-items: center;\n"
+    "}\n"
+    
+    ".tag button {\n"
+    "    background: none;\n"
+    "    border: none;\n"
+    "    color: white;\n"
+    "    margin-left: 5px;\n"
+    "    cursor: pointer;\n"
+    "    font-weight: bold;\n"
+    "}\n"
+    
+    ".no-selection {\n"
+    "    color: #95a5a6;\n"
+    "    font-style: italic;\n"
+    "}\n"
+    
+    ".code-example {\n"
+    "    background-color: #2d2d2d;\n"
+    "    color: #f8f8f2;\n"
+    "    padding: 15px;\n"
+    "    border-radius: 5px;\n"
+    "    margin-top: 20px;\n"
+    "    overflow-x: auto;\n"
+    "    font-family: 'Fira Code', monospace;\n"
+    "}\n"
+    
+    "footer {\n"
+    "    text-align: center;\n"
+    "    margin-top: 40px;\n"
+    "    color: #7f8c8d;\n"
+    "    font-size: 0.9rem;\n"
+    "}\n"
+    
 ;
 
 // 文本数据大小(包括null终止符)
-const size_t p_css_index_size = 8113;
+const size_t p_css_index_size = 10639;
 
 // 文本长度(字符数)
-const size_t p_css_index_length = 7864;
+const size_t p_css_index_length = 10390;
 
 #endif /* P_CSS_INDEX_H */

+ 281 - 50
nor_web/h_html/index_html.h

@@ -1,7 +1,7 @@
 /* 自动生成的文本数据头文件 */
 /* 源文件: index.html */
-/* 文件大小: 57177 字节 */
-/* 生成时间: 2025-09-12 05:41:57 */
+/* 文件大小: 68489 字节 */
+/* 生成时间: 2025-09-16 05:47:07 */
 /* 编码: utf-8 */
 #ifndef P_INDEX_HTML_H
 #define P_INDEX_HTML_H
@@ -60,7 +60,7 @@ const char *p_index_html =
     "            <div class=\"left-buttons\">\n"
     "              <button @click=\"showFzszModal = true;\" class=\"btn btn-threshold\">阈值设置</button>\n"
     "              <button @click=\"showysszModal=true\" class=\"btn btn-delay\">延时设置</button>\n"
-    "              <button @click=\"showFormModal = true\" class=\"btn btn-energy\">耗电量重置</button>\n"
+    "              <button @click=\" hdlsz()\" class=\"btn btn-energy\">耗电量重置</button>\n"
     "            </div>\n"
     "            <div  class=\"right-buttons\">\n"
     "              <button @click=\"toggleAllDevices(true)\" class=\" btn btn-energy\">总开</button>\n"
@@ -116,15 +116,16 @@ const char *p_index_html =
     "            </thead>\n"
     "            <tbody>\n"
     "            <tr v-for=\"device in channelList\">\n"
-    "              <td :style=\"device.colorStyle\">{{ device.productChName }}</td>\n"
-    "              <td :style=\"device.colorStyle\">{{ device.productPhOrder }}</td>\n"
-    "              <td :style=\"device.colorStyle\">{{ device.productChVoltage }}</td>\n"
-    "              <td :style=\"device.colorStyle\">{{ device.productChCurrent }}</td>\n"
-    "              <td :style=\"device.colorStyle\">{{ device.productChPower }}</td>\n"
-    "              <td :style=\"device.colorStyle\">{{ device.productChPowerFreq }}</td>\n"
-    "              <td :style=\"device.colorStyle\">{{ device.productChConsumption }}</td>\n"
-    "              <td :style=\"device.colorStyle\">{{ device.firingInterval }}</td>\n"
-    "              <td :style=\"device.colorStyle\">{{ device.closeInterval }}</td>\n"
+    "              <td >{{ device.productChName }}</td>\n"
+    "              <td >{{ device.productPhOrder }}</td>\n"
+    "              <td v-if=\"device.colorStyledy!=''\" :style=\"device.colorStyledy\">{{ device.productChVoltage }}</td>\n"
+    "              <td v-else  :style=\"device.colorStyledy2\">{{ device.productChVoltage }}</td>\n"
+    "              <td :style=\"device.colorStyledl\">{{ device.productChCurrent }}</td>\n"
+    "              <td  :style=\"device.colorStylegl\">{{ device.productChPower }}</td>\n"
+    "              <td>{{ device.productChPowerFreq }}</td>\n"
+    "              <td :style=\"device.colorStylehdl\">{{ device.productChConsumption }}</td>\n"
+    "              <td >{{ device.firingInterval }}</td>\n"
+    "              <td >{{ device.closeInterval }}</td>\n"
     "              <td :class=\"device.productChStatus ? 'status-active' : 'status-inactive'\">\n"
     "                {{ device.productChStatus==1 ? '接通' : '断开' }}\n"
     "              </td>\n"
@@ -147,12 +148,12 @@ const char *p_index_html =
     "          <div class=\"status-box\">\n"
     "            <h3>温度</h3>\n"
     "            <p v-if=\"statusData.temperatureStatus==0\" style=\"color: red\">{{ statusData.temperature }}</p>\n"
-    "            <p v-else>{{ statusData.temperature }} </p>\n"
+    "            <p v-else :style=\"statusData.tempcolorStyle\">{{ statusData.temperature }} </p>\n"
     "          </div>\n"
     "          <div class=\"status-box\">\n"
     "            <h3>湿度</h3>\n"
     "            <p v-if=\"statusData.temperatureStatus==0\" style=\"color: red\">{{ statusData.humidity }}</p>\n"
-    "            <p v-else>{{ statusData.humidity }} </p>\n"
+    "            <p v-else :style=\"statusData.humcolorStylesx\">{{ statusData.humidity }} </p>\n"
     
     "          </div>\n"
     "          <div class=\"status-box\">\n"
@@ -163,9 +164,9 @@ const char *p_index_html =
     "          <div class=\"status-box\">\n"
     "            <h3>CO2</h3>\n"
     "            <p v-if=\"statusData.smokeStatus==0\" style=\"color: red\">{{ statusData.smoke }}</p>\n"
-    "            <p v-else>{{ statusData.smoke }} </p>\n"
+    "            <p v-else :style=\"statusData.smokecolorStylesx\">{{ statusData.smoke }} </p>\n"
     "          </div>\n"
-    "          <div class=\"status-box\">\n"
+    "          <div class=\"status-box\"  @click=\"showFzszModalgj=true\" style=\" cursor: pointer;  position: relative;    \">\n"
     "            <h3>报警</h3>\n"
     "            <p>{{ statusData.alarm1 }}</p>\n"
     "          </div>\n"
@@ -178,10 +179,31 @@ const char *p_index_html =
     "          <!-- 下拉选择 -->\n"
     "          <div class=\"form-group\" >\n"
     "            <label>通道:</label>\n"
-    "            <select   v-model=\"formData.channel_power_infro\"  class=\"custom-select\">\n"
-    "              <option :value=\"null\" disabled selected hidden style=\"color: #aaa;\">请选择耗电量复位通道...</option>\n"
-    "              <option   v-for=\"option in  channelList1\" :value=\"option.channel_power_infro\">{{ option.productChName }}</option>\n"
+    "            <div class=\"select-header\">\n"
+    "              <p class=\"hint\">提示:使用Ctrl/Cmd键进行多选</p>\n"
+    "              <button class=\"select-all\" @click=\"toggleSelectAll2\">\n"
+    "                {{ formData.productChIds.length === Object.keys(channelList1).length  ? '取消全选' : '全选' }}\n"
+    "              </button>\n"
+    "            </div>\n"
+    "            <select v-model=\"formData.productChIds\" multiple  >\n"
+    "              <option    v-for=\"option in  channelList1\" :value=\"option.productChId\">{{ option.productChName }}</option>\n"
     "            </select>\n"
+    
+    "            <div class=\"selected-items\">\n"
+    "              <h3>已选通道:</h3>\n"
+    "              <div class=\"selected-tags\">\n"
+    "                <span v-if=\"formData.productChIds.length === 0\" class=\"no-selection\">暂无选择</span>\n"
+    "                <div v-for=\"id in formData.productChIds\" :key=\"id\" class=\"tag\">\n"
+    "                  {{ getOptionName2(id) }}\n"
+    "                  <button @click=\"removeOption2(id)\">×</button>\n"
+    "                </div>\n"
+    "              </div>\n"
+    "            </div>\n"
+    "            <!--<label>通道:</label>-->\n"
+    "            <!--<select   v-model=\"formData.channel_power_infro\"  class=\"custom-select\">-->\n"
+    "              <!--<option :value=\"null\" disabled selected hidden style=\"color: #aaa;\">请选择耗电量复位通道...</option>-->\n"
+    "              <!--<option   v-for=\"option in  channelList1\" :value=\"option.channel_power_infro\">{{ option.productChName }}</option>-->\n"
+    "            <!--</select>-->\n"
     "          </div>\n"
     "          <!-- 表单按钮 -->\n"
     "          <div class=\"form-actions\">\n"
@@ -195,6 +217,7 @@ const char *p_index_html =
     "      <div @vue:mounted=\"fzszData\"  v-if=\"showFzszModal\" class=\"modal-overlay\"  >\n"
     "        <div class=\"modal-content\" style=\"max-width: 100%;overflow-y: hidden\">\n"
     "          <h2>阈值设置</h2>\n"
+    "          <button @click=\"handleUpdateList()\" style=\"margin: 10px;\" :class=\"   'btn btn-on'\">批量设置 </button>\n"
     "          <div class=\"scrollable-table\" style=\"    max-height: 60vh; \">\n"
     "            <table class=\"device-table\">\n"
     "              <thead>\n"
@@ -211,7 +234,7 @@ const char *p_index_html =
     "              </thead>\n"
     "              <tbody>\n"
     "              <tr v-for=\"power in powerThresholdList\" :key=\"power.productChId\">\n"
-    "                <td :style=\"{{ power.colorStyle }}\">{{ power.productChName }}</td>\n"
+    "                <td>{{ power.productChName }}</td>\n"
     "                <td>{{ power.productChId }}</td>\n"
     "                <td>{{ power.currentUpperAction }}</td>\n"
     "                <td>{{ power.voltageUpperAction }}</td>\n"
@@ -237,7 +260,30 @@ const char *p_index_html =
     "      <!-- 阈值设置单设备弹窗内容 -->\n"
     "      <div v-if=\"showFzszModal2\" class=\"modal-overlay\"  >\n"
     "        <div class=\"modal-content\">\n"
-    "          <div class=\"form-group\" >\n"
+    "          <div class=\"form-group\" v-if=\"fzscData.list=='1'\" >\n"
+    "            <label>通道:</label>\n"
+    "            <div class=\"select-header\">\n"
+    "              <p class=\"hint\">提示:使用Ctrl/Cmd键进行多选</p>\n"
+    "              <button class=\"select-all\" @click=\"toggleSelectAll\">\n"
+    "                {{ fzscData.productChIds.length === Object.keys(channelList1).length  ? '取消全选' : '全选' }}\n"
+    "              </button>\n"
+    "            </div>\n"
+    "            <select v-model=\"fzscData.productChIds\" multiple  >\n"
+    "              <option    v-for=\"option in  channelList1\" :value=\"option.productChId\">{{ option.productChName }}</option>\n"
+    "            </select>\n"
+    
+    "            <div class=\"selected-items\">\n"
+    "              <h3>已选通道:</h3>\n"
+    "              <div class=\"selected-tags\">\n"
+    "                <span v-if=\"fzscData.productChIds.length === 0\" class=\"no-selection\">暂无选择</span>\n"
+    "                <div v-for=\"id in fzscData.productChIds\" :key=\"id\" class=\"tag\">\n"
+    "                  {{ getOptionName(id) }}\n"
+    "                  <button @click=\"removeOption(id)\">×</button>\n"
+    "                </div>\n"
+    "              </div>\n"
+    "            </div>\n"
+    "          </div>\n"
+    "          <div class=\"form-group\"  v-if=\"fzscData.list==''\">\n"
     "            <label>通道号:</label>\n"
     "            <input type=\"text\" v-model=\"fzscData.productChId\"  readonly >\n"
     "          </div>\n"
@@ -261,7 +307,6 @@ const char *p_index_html =
     "            <label>耗电量上限:</label>\n"
     "            <input type=\"text\" v-model=\"fzscData.alarmContentUpperAction\">\n"
     "          </div>\n"
-    
     "          <!-- 表单按钮 -->\n"
     "          <div class=\"form-actions\">\n"
     "            <button  class=\"btn  btn-energy\" @click=\"fzscClick()\"  >提交</button>\n"
@@ -330,6 +375,35 @@ const char *p_index_html =
     "        </div>\n"
     "      </div>\n"
     
+    "      <!--告警信息弹窗-->\n"
+    "      <div    v-if=\"showFzszModalgj\" class=\"modal-overlay\"  >\n"
+    "        <div class=\"modal-content\" style=\"max-width: 100%;overflow-y: hidden\">\n"
+    "          <div class=\"scrollable-table\" style=\"    max-height: 60vh; \">\n"
+    "            <table class=\"device-table\">\n"
+    "              <thead>\n"
+    "              <tr>\n"
+    "                <th>序号</th>\n"
+    "                <th>报警时间</th>\n"
+    "                <th>报警类型</th>\n"
+    "                <th>报警信息</th>\n"
+    "              </tr>\n"
+    "              </thead>\n"
+    "              <tbody>\n"
+    "              <tr  v-for=\"(item, index) in his_alarmd\" :key=\"index\">\n"
+    "                <td>{{  item.number   }}</td>\n"
+    "                <td>{{ item.date }}</td>\n"
+    "                <td>{{ item.type }}</td>\n"
+    "                <td>{{ item.waning_context }}</td>\n"
+    "              </tr>\n"
+    "              </tbody>\n"
+    "            </table>\n"
+    "          </div>\n"
+    "          <!-- 表单按钮 -->\n"
+    "          <div class=\"button-footer form-actions\">\n"
+    "            <button type=\"button\"  class=\"btn  btn-energy\" @click=\"fzscClickClosegj()\">取消</button>\n"
+    "          </div>\n"
+    "        </div>\n"
+    "      </div>\n"
     
     "    </div>\n"
     
@@ -738,10 +812,19 @@ const char *p_index_html =
     "                    delay_update(this.saveDataAll.channel_power_infro)\n"
     "                    this.ysszClickClose2()\n"
     "                }else if(this.popType=='hdlcz'){\n"
-    "                    power_reset(this.saveDataAll.channel_power_infro)\n"
+    "                    for(const ket in this.saveDataAll.channel_power_infros){\n"
+    "                        power_reset(this.saveDataAll.channel_power_infros[ket])\n"
+    "                    }\n"
     "                    this.hdlczClickClose()\n"
     "                }else if(this.popType=='fzsz'){\n"
-    "                    threshold_update(this.saveDataAll.channel_power_infro)\n"
+    "                    if(this.saveDataAll.list=='1'){\n"
+    "                        for(const ket in this.saveDataAll.channel_power_infros){\n"
+    "                            threshold_update(this.saveDataAll.channel_power_infros[ket])\n"
+    "                        }\n"
+    "                    }else{\n"
+    "                        threshold_update(this.saveDataAll.channel_power_infro)\n"
+    "                    }\n"
+    
     "                    this.fzscClickClose2()\n"
     "                }else if(this.popType=='tdkg'){\n"
     
@@ -792,12 +875,16 @@ const char *p_index_html =
     "            showFormModal:false,\n"
     "            // 阈值设置\n"
     "            showFzszModal:false,\n"
+    "            //告警\n"
+    "            showFzszModalgj:false,\n"
     "            showFzszModal2:false,\n"
     "            showysszModal:false,\n"
     "            showysszModal2:false,\n"
-    "            formData:{productChName:null,productChId:null,channel_power_infro:null},\n"
+    "            formData:{productChName:null,productChId:null,channel_power_infro:null,productChIds:[]},\n"
     "            powerThresholdList:[],\n"
-    "            fzscData:{},\n"
+    "            fzscData:{\n"
+    "                productChIds:[]\n"
+    "            },\n"
     "            items: [],\n"
     "            newItem: '',\n"
     "            loading: false,\n"
@@ -836,6 +923,7 @@ const char *p_index_html =
     "            channelList1:[],\n"
     "            ysszList:[],\n"
     "            totalFormList:[],\n"
+    "            his_alarmd:[],\n"
     "            ysszData2:{},\n"
     "            popMessage:'',\n"
     "            popType:'',\n"
@@ -889,6 +977,68 @@ const char *p_index_html =
     "            /** 阈值设置按钮操作 */\n"
     "            handleUpdate(row) {\n"
     "                this.fzscData = JSON.parse(JSON.stringify(row));\n"
+    "                this.fzscData.list='';\n"
+    "                this.showFzszModal2 = true;\n"
+    "                // this.title = this.$t('pz');\n"
+    "            },\n"
+    "            getOptionName(id) {\n"
+    "                for(const key in   this.channelList1){\n"
+    "                    if(this.channelList1[key].productChId===id){\n"
+    "                        return this.channelList1[key].productChName\n"
+    "                        break\n"
+    "                    }\n"
+    "                }\n"
+    "                ;\n"
+    "            },\n"
+    "            removeOption(id) {\n"
+    "                this.fzscData.productChIds = this.fzscData.productChIds.filter(optId => optId !== id);\n"
+    "            },\n"
+    "            toggleSelectAll() {\n"
+    
+    "                if (this.fzscData.productChIds.length === Object.keys(this.channelList1).length ) {\n"
+    "                    this.fzscData.productChIds = [];\n"
+    "                } else {\n"
+    "                    for(const key in   this.channelList1){\n"
+    "                        this.fzscData.productChIds.push(this.channelList1[key].productChId)\n"
+    "                    }\n"
+    
+    "                   // this.fzscData.productChIds = this.channelList1.map(option => option.productChId);\n"
+    "                }\n"
+    "            },\n"
+    
+    "            getOptionName2(id) {\n"
+    "                for(const key in   this.channelList1){\n"
+    "                    if(this.channelList1[key].productChId===id){\n"
+    "                        return this.channelList1[key].productChName\n"
+    "                        break\n"
+    "                    }\n"
+    "                }\n"
+    "                ;\n"
+    "            },\n"
+    "            removeOption2(id) {\n"
+    "                this.formData.productChIds = this.formData.productChIds.filter(optId => optId !== id);\n"
+    "            },\n"
+    "            toggleSelectAll2() {\n"
+    "                if (this.formData.productChIds.length === Object.keys(this.channelList1).length ) {\n"
+    "                    this.formData.productChIds = [];\n"
+    "                } else {\n"
+    "                    for(const key in   this.channelList1){\n"
+    "                        this.formData.productChIds.push(this.channelList1[key].productChId)\n"
+    "                    }\n"
+    
+    "                   // this.fzscData.productChIds = this.channelList1.map(option => option.productChId);\n"
+    "                }\n"
+    "            },\n"
+    "  /** 阈值设置按钮操作 */\n"
+    "            handleUpdateList() {\n"
+    "                this.fzscData.list='1';\n"
+    "                this.fzscData.productChIds=[];\n"
+    "                this.fzscData.currentUpperAction='';\n"
+    "                this.fzscData.voltageUpperAction='';\n"
+    "                this.fzscData.voltageDownAction='';\n"
+    "                this.fzscData.powerUpperAction='';\n"
+    "                this.fzscData.alarmContentUpperAction='';\n"
+    
     "                this.showFzszModal2 = true;\n"
     "                // this.title = this.$t('pz');\n"
     "            },\n"
@@ -916,6 +1066,9 @@ const char *p_index_html =
     "                this.powerThresholdList=[];\n"
     "                //    this.formData.productChId=null;\n"
     "            },\n"
+    "            fzscClickClosegj(){\n"
+    "                this.showFzszModalgj = false;\n"
+    "            },\n"
     
     "            fzscClickClose2(){\n"
     "                this.showFzszModal2 = false\n"
@@ -930,11 +1083,27 @@ const char *p_index_html =
     "                this.showysszModal2 = false;\n"
     "            },\n"
     
+    "            hdlsz(){\n"
+    "                this.formData.productChIds=[]\n"
+    "                this.showFormModal = true\n"
+    "            },\n"
+    
     "            // 耗电量重置\n"
     "            async hdlczClick(){\n"
     "                const params={};\n"
+    "                let lists=[]\n"
+    "                console.log( this.formData.productChIds)\n"
+    "                for( const id in  this.formData.productChIds){\n"
+    "                    for( const key in  this.powerThresholdList ){\n"
+    "                        if(this.formData.productChIds[id]== this.powerThresholdList[key].productChId){\n"
+    "                            lists.push(this.powerThresholdList[key].channel_power_infro);\n"
+    "                            break\n"
+    "                        }\n"
+    "                    }\n"
+    "                }\n"
+    "                params.channel_power_infros= lists;\n"
     
-    "                params.channel_power_infro=this.formData.channel_power_infro;\n"
+    "              //  params.channel_power_infro=this.formData.channel_power_infro;\n"
     "                this.popMessage=\"确认要重置此通道吗?\";\n"
     "                // const result = await confirmAction({\n"
     "                //     title: message\n"
@@ -949,12 +1118,46 @@ const char *p_index_html =
     "            // 阈值设置保存\n"
     "            async fzscClick(){\n"
     "                const params={};\n"
-    "                params.channel_power_infro=this.fzscData.channel_power_infro;\n"
-    "                params.channel_power_infro.thr.w_upper=this.fzscData.alarmContentUpperAction* 1000;\n"
-    "                params.channel_power_infro.thr.c_upper=this.fzscData.currentUpperAction* 10;\n"
-    "                params.channel_power_infro.thr.p_upper=this.fzscData.powerUpperAction* 1000;\n"
-    "                params.channel_power_infro.thr.v_lower=this.fzscData.voltageDownAction* 10;\n"
-    "                params.channel_power_infro.thr.v_upper=this.fzscData.voltageUpperAction* 10;\n"
+    "                params.list=this.fzscData.list;\n"
+    "                if(this.fzscData.list=='1'){\n"
+    "                    if(this.fzscData.productChIds.length==0){\n"
+    "                        alert(\"请选择通道\")\n"
+    "                        return\n"
+    "                    }\n"
+    "                    if(this.fzscData.alarmContentUpperAction=='' || this.fzscData.currentUpperAction=='' || this.fzscData.voltageDownAction==''  || this.fzscData.voltageUpperAction==''){\n"
+    "                        alert(\"存在未设置项,请重试\")\n"
+    "                        return\n"
+    "                    }\n"
+    "                    if(this.fzscData.voltageUpperAction!=0 && this.fzscData.voltageDownAction !=0 && this.fzscData.voltageUpperAction* 10<=this.fzscData.voltageDownAction* 10){\n"
+    "                        alert(\"电压上限需要大于下限\")\n"
+    "                        return\n"
+    "                    }\n"
+    "                    let lists=[]\n"
+    "                    for( const id in  this.fzscData.productChIds){\n"
+    "                        for( const key in  this.powerThresholdList ){\n"
+    "                               if(this.fzscData.productChIds[id]== this.powerThresholdList[key].productChId){\n"
+    "                                   let param=this.powerThresholdList[key].channel_power_infro;\n"
+    "                                   param.thr.w_upper=this.fzscData.alarmContentUpperAction* 1000;\n"
+    "                                   param.thr.c_upper=this.fzscData.currentUpperAction* 10;\n"
+    "                                   param.thr.p_upper=this.fzscData.powerUpperAction* 1000;\n"
+    "                                   param.thr.v_lower=this.fzscData.voltageDownAction* 10;\n"
+    "                                   param.thr.v_upper=this.fzscData.voltageUpperAction* 10;\n"
+    "                                   lists.push(param);\n"
+    "                                      break\n"
+    "                               }\n"
+    "                        }\n"
+    "                    }\n"
+    "                    params.channel_power_infros= lists;\n"
+    
+    "                }else{\n"
+    "                    params.channel_power_infro=this.fzscData.channel_power_infro;\n"
+    "                    params.channel_power_infro.thr.w_upper=this.fzscData.alarmContentUpperAction* 1000;\n"
+    "                    params.channel_power_infro.thr.c_upper=this.fzscData.currentUpperAction* 10;\n"
+    "                    params.channel_power_infro.thr.p_upper=this.fzscData.powerUpperAction* 1000;\n"
+    "                    params.channel_power_infro.thr.v_lower=this.fzscData.voltageDownAction* 10;\n"
+    "                    params.channel_power_infro.thr.v_upper=this.fzscData.voltageUpperAction* 10;\n"
+    
+    "                }\n"
     
     "                this.popMessage=\"确认要保存吗?\";\n"
     "                // const result = await confirmAction({\n"
@@ -1005,18 +1208,7 @@ const char *p_index_html =
     
     "            // 获取数据方法\n"
     "            async fetchData() {\n"
-    "                // var js={\n"
-    "                //     \"sys\":{\n"
-    "                //         \"lang\": 0,\n"
-    "                //         \"tzone\": 8,\n"
-    "                //         \"route\": 90,\n"
-    "                //         \"ver\": \"V1.0.0\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\",\n"
-    "                //         \"sys_time\": \"2025/09/09 01:00:06\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\",\n"
-    "                //         \"len\": 52\n"
-    "                //     }\n"
-    "                //\n"
-    "                // }\n"
-    "                // on_ws_msg(js)\n"
+    "         \n"
     "                function5();\n"
     "                this.queryTotalStatus5();\n"
     "                if (activePageIntervalId1 != null) {\n"
@@ -1024,7 +1216,7 @@ const char *p_index_html =
     "                };\n"
     "                activePageIntervalId1 = setInterval(() => {\n"
     "                    if(tabId=='tab1'){\n"
-    "                        function1();\n"
+    "                         function1();\n"
     "                        this.queryTotalStatus();\n"
     "                        if(this.wlszForm4.sys_time=='' || this.wlszForm4.sys_time==null){\n"
     "                            this.queryTotalStatus5();\n"
@@ -1063,8 +1255,23 @@ const char *p_index_html =
     "                this.channelList1 = {...channelAllList1};\n"
     "                this.powerThresholdList = {...initialYzFormList};\n"
     "                this.ysszList = {...channelAllList1};\n"
-    "                if({...data_alarm}!=null){\n"
-    "                    this.statusData.alarm1 =  Object.keys({...data_alarm}).length;\n"
+    "                if({...his_alarm}!=null){\n"
+    "                    this.statusData.alarm1 =  Object.keys({...his_alarm}).length;\n"
+    "                    var alarmds={...his_alarm};\n"
+    "                    this.his_alarmd=[]\n"
+    "                    for(var i=0;i<Object.keys({...his_alarm}).length ;i++){\n"
+    "                        var open=alarmds[i];\n"
+    "                            open.number=i+1;\n"
+    "                        open.date= (open.date.replace(/\\\\u0000/g, '\\u0000')).replace(/\\u0000/g, '');\n"
+    "                        open.waning_context= (open.waning_context.replace(/\\\\u0000/g, '\\u0000')).replace(/\\u0000/g, '');\n"
+    "                        if(open.type==0){\n"
+    "                            open.type='电量信息报警'\n"
+    "                        }else if(open.type==1){\n"
+    "                            open.type='传感器报警'\n"
+    "                        }\n"
+    "                        this.his_alarmd.push(open)\n"
+    "                    }\n"
+    
     "                }\n"
     "                if({...sensorc_list}!=null && Object.keys({...sensorc_list}).length>0){\n"
     "                   let sencorList={...sensorc_list};\n"
@@ -1074,7 +1281,24 @@ const char *p_index_html =
     "                               try{\n"
     "                                   let sensor_val =sencorList[key].sensor_val\n"
     "                                   this.statusData.temperature=sensor_val[1].val.toFixed(2)\n"
+    
+    "                                   if(sensor_val[1].s_alarm  & 0x1){ // 上限\n"
+    "                                       this.statusData.tempcolorStyle='color: red;font-weight: bold;'\n"
+    "                                   }else if(sensor_val[1].s_alarm & 0x2){ // 下限\n"
+    "                                       this.statusData.tempcolorStyle='color:  #ff00ff;font-weight: bold;'\n"
+    "                                   }else{\n"
+    "                                       this.statusData.tempcolorStyle=''\n"
+    "                                   }\n"
+    
     "                                   this.statusData.humidity=sensor_val[0].val.toFixed(2)\n"
+    
+    "                                   if(sensor_val[0].s_alarm  & 0x1){ // 上限\n"
+    "                                       this.statusData.humcolorStylesx='color: red;font-weight: bold;'\n"
+    "                                   }else if(sensor_val[0].s_alarm & 0x2){ // 下限\n"
+    "                                       this.statusData.humcolorStylesx='color:  #ff00ff;font-weight: bold;'\n"
+    "                                   }else{\n"
+    "                                       this.statusData.humcolorStylesx=''\n"
+    "                                   }\n"
     "                               }catch (e) {\n"
     "                                   console.log(\"温湿度传感器赋值失败\")\n"
     "                               }\n"
@@ -1104,6 +1328,13 @@ const char *p_index_html =
     "                               try{\n"
     "                                   let sensor_val =sencorList[key].sensor_val\n"
     "                                   this.statusData.smoke=sensor_val[0].val.toFixed(2)\n"
+    "                                   if(sensor_val[0] & 0x1 ){ // 上限\n"
+    "                                       this.statusData.smokecolorStylesx='color: red;font-weight: bold;'\n"
+    "                                   }else if(sensor_val[0] & 0x2){ // 下限\n"
+    "                                       this.statusData.smokecolorStylesx='color:  #ff00ff;font-weight: bold;'\n"
+    "                                   }else{\n"
+    "                                       this.statusData.smokecolorStylesx=''\n"
+    "                                   }\n"
     "                               }catch (e) {\n"
     "                                   console.log(\"CO2传感器赋值失败\")\n"
     "                               }\n"
@@ -1473,9 +1704,9 @@ const char *p_index_html =
 ;
 
 // 文本数据大小(包括null终止符)
-const size_t p_index_html_size = 57178;
+const size_t p_index_html_size = 68490;
 
 // 文本长度(字符数)
-const size_t p_index_html_length = 55265;
+const size_t p_index_html_length = 66291;
 
 #endif /* P_INDEX_HTML_H */

+ 1 - 1
nor_web/h_html/index_js.h

@@ -1,7 +1,7 @@
 /* 自动生成的文本数据头文件 */
 /* 源文件: index.js */
 /* 文件大小: 417 字节 */
-/* 生成时间: 2025-09-12 05:42:13 */
+/* 生成时间: 2025-09-16 05:47:25 */
 /* 编码: utf-8 */
 #ifndef P_INDEX_JS_H
 #define P_INDEX_JS_H

+ 5 - 4
nor_web/h_html/operation.h

@@ -1,7 +1,7 @@
 /* 自动生成的文本数据头文件 */
 /* 源文件: operation.js */
-/* 文件大小: 3700 字节 */
-/* 生成时间: 2025-09-12 05:42:14 */
+/* 文件大小: 3765 字节 */
+/* 生成时间: 2025-09-16 05:47:25 */
 /* 编码: utf-8 */
 #ifndef P_OPERATION_H
 #define P_OPERATION_H
@@ -110,6 +110,7 @@ const char *p_operation =
     "    ws.send(mk_hdr_bin(0, PKT_TYPE.PKT_TYPE_POWER_CH, 0, 0, 0));\n"
     "    ws.send(mk_hdr_bin(0, PKT_TYPE.PKT_TYPE_SENSOR, 0, 0, 0, 0));\n"
     "    ws.send(mk_hdr_bin(0, PKT_TYPE.PKT_TYPE_PARAS, SUB_TYPE.SUB_TYPE_PARAS_SYS, 0, 0, 0));\n"
+    "    ws.send(mk_hdr_bin(0, PKT_TYPE.PKT_TYPE_ALARM, 0, 0, 0, 0));\n"
     "}\n"
     
     "//获取网络配置信息\n"
@@ -139,9 +140,9 @@ const char *p_operation =
 ;
 
 // 文本数据大小(包括null终止符)
-const size_t p_operation_size = 3701;
+const size_t p_operation_size = 3766;
 
 // 文本长度(字符数)
-const size_t p_operation_length = 3532;
+const size_t p_operation_length = 3597;
 
 #endif /* P_OPERATION_H */

+ 1 - 1
nor_web/h_html/petite-vue.min.h

@@ -1,7 +1,7 @@
 /* 自动生成的文本数据头文件 */
 /* 源文件: petite-vue.min.js */
 /* 文件大小: 16901 字节 */
-/* 生成时间: 2025-09-12 05:42:14 */
+/* 生成时间: 2025-09-16 05:47:25 */
 /* 编码: us-ascii */
 #ifndef P_PETITE_VUE_H
 #define P_PETITE_VUE_H

+ 1 - 1
nor_web/h_html/sys_para.h

@@ -1,7 +1,7 @@
 /* 自动生成的文本数据头文件 */
 /* 源文件: sys_paras.js */
 /* 文件大小: 240 字节 */
-/* 生成时间: 2025-09-12 05:42:14 */
+/* 生成时间: 2025-09-16 05:47:25 */
 /* 编码: us-ascii */
 #ifndef P_SYS_PARA_H
 #define P_SYS_PARA_H

+ 14 - 7
nor_web/h_html/ws.h

@@ -1,7 +1,7 @@
 /* 自动生成的文本数据头文件 */
 /* 源文件: ws.js */
-/* 文件大小: 3174 字节 */
-/* 生成时间: 2025-09-12 05:42:14 */
+/* 文件大小: 3306 字节 */
+/* 生成时间: 2025-09-16 05:47:25 */
 /* 编码: utf-8 */
 #ifndef P_WS_H
 #define P_WS_H
@@ -25,6 +25,8 @@ const char *p_ws =
     
     "let sensor_data = {}\n"
     
+    "let his_alarm = []\n"
+    
     "function on_ws_msg(js) {\n"
     "    console.log(\"执行\")\n"
     
@@ -84,13 +86,18 @@ const char *p_ws =
     "        sensorc_list = [];\n"
     "        // 传感器\n"
     "        sensorc_list = js.sensorc\n"
-    "        console.log(sensorc_list)\n"
+    "            // console.log(sensorc_list)\n"
     "    }\n"
     "    if (js.sys != undefined) {\n"
     "        lang_data = js.sys\n"
     "            // console.log(lang_data)\n"
     "    }\n"
     
+    "    if (js.his_alarmd != undefined) {\n"
+    "        his_alarm = js.his_alarmd;\n"
+    "        console.log(his_alarm)\n"
+    "    }\n"
+    
     "}\n"
     
     "function alarm_process(alarmd_data) {\n"
@@ -133,16 +140,16 @@ const char *p_ws =
     "    activePageIntervalId = setInterval(pageFunction, intervalTime);\n"
     "}\n"
     
-    "ws = new WS('ws://' + window.location.host + '/ws', on_ws_msg);\n"
+    "ws = new WS('ws://'+window.location.host+'/ws',on_ws_msg);\n"
     
     "// ws = new WS('ws://192.168.1.134/ws', on_ws_msg);\n"
-    "// ws = new WS('ws://192.168.1.134/websocket/TMS-WebSocket', on_ws_msg);"
+    "//ws = new WS('ws://192.168.1.134/websocket/TMS-WebSocket', on_ws_msg);"
 ;
 
 // 文本数据大小(包括null终止符)
-const size_t p_ws_size = 3175;
+const size_t p_ws_size = 3307;
 
 // 文本长度(字符数)
-const size_t p_ws_length = 3016;
+const size_t p_ws_length = 3148;
 
 #endif /* P_WS_H */

+ 277 - 46
nor_web/index.html

@@ -48,7 +48,7 @@
             <div class="left-buttons">
               <button @click="showFzszModal = true;" class="btn btn-threshold">阈值设置</button>
               <button @click="showysszModal=true" class="btn btn-delay">延时设置</button>
-              <button @click="showFormModal = true" class="btn btn-energy">耗电量重置</button>
+              <button @click=" hdlsz()" class="btn btn-energy">耗电量重置</button>
             </div>
             <div  class="right-buttons">
               <button @click="toggleAllDevices(true)" class=" btn btn-energy">总开</button>
@@ -104,15 +104,16 @@
             </thead>
             <tbody>
             <tr v-for="device in channelList">
-              <td :style="device.colorStyle">{{ device.productChName }}</td>
-              <td :style="device.colorStyle">{{ device.productPhOrder }}</td>
-              <td :style="device.colorStyle">{{ device.productChVoltage }}</td>
-              <td :style="device.colorStyle">{{ device.productChCurrent }}</td>
-              <td :style="device.colorStyle">{{ device.productChPower }}</td>
-              <td :style="device.colorStyle">{{ device.productChPowerFreq }}</td>
-              <td :style="device.colorStyle">{{ device.productChConsumption }}</td>
-              <td :style="device.colorStyle">{{ device.firingInterval }}</td>
-              <td :style="device.colorStyle">{{ device.closeInterval }}</td>
+              <td >{{ device.productChName }}</td>
+              <td >{{ device.productPhOrder }}</td>
+              <td v-if="device.colorStyledy!=''" :style="device.colorStyledy">{{ device.productChVoltage }}</td>
+              <td v-else  :style="device.colorStyledy2">{{ device.productChVoltage }}</td>
+              <td :style="device.colorStyledl">{{ device.productChCurrent }}</td>
+              <td  :style="device.colorStylegl">{{ device.productChPower }}</td>
+              <td>{{ device.productChPowerFreq }}</td>
+              <td :style="device.colorStylehdl">{{ device.productChConsumption }}</td>
+              <td >{{ device.firingInterval }}</td>
+              <td >{{ device.closeInterval }}</td>
               <td :class="device.productChStatus ? 'status-active' : 'status-inactive'">
                 {{ device.productChStatus==1 ? '接通' : '断开' }}
               </td>
@@ -135,12 +136,12 @@
           <div class="status-box">
             <h3>温度</h3>
             <p v-if="statusData.temperatureStatus==0" style="color: red">{{ statusData.temperature }}</p>
-            <p v-else>{{ statusData.temperature }} </p>
+            <p v-else :style="statusData.tempcolorStyle">{{ statusData.temperature }} </p>
           </div>
           <div class="status-box">
             <h3>湿度</h3>
             <p v-if="statusData.temperatureStatus==0" style="color: red">{{ statusData.humidity }}</p>
-            <p v-else>{{ statusData.humidity }} </p>
+            <p v-else :style="statusData.humcolorStylesx">{{ statusData.humidity }} </p>
 
           </div>
           <div class="status-box">
@@ -151,9 +152,9 @@
           <div class="status-box">
             <h3>CO2</h3>
             <p v-if="statusData.smokeStatus==0" style="color: red">{{ statusData.smoke }}</p>
-            <p v-else>{{ statusData.smoke }} </p>
+            <p v-else :style="statusData.smokecolorStylesx">{{ statusData.smoke }} </p>
           </div>
-          <div class="status-box">
+          <div class="status-box"  @click="showFzszModalgj=true" style=" cursor: pointer;  position: relative;    ">
             <h3>报警</h3>
             <p>{{ statusData.alarm1 }}</p>
           </div>
@@ -166,10 +167,31 @@
           <!-- 下拉选择 -->
           <div class="form-group" >
             <label>通道:</label>
-            <select   v-model="formData.channel_power_infro"  class="custom-select">
-              <option :value="null" disabled selected hidden style="color: #aaa;">请选择耗电量复位通道...</option>
-              <option   v-for="option in  channelList1" :value="option.channel_power_infro">{{ option.productChName }}</option>
+            <div class="select-header">
+              <p class="hint">提示:使用Ctrl/Cmd键进行多选</p>
+              <button class="select-all" @click="toggleSelectAll2">
+                {{ formData.productChIds.length === Object.keys(channelList1).length  ? '取消全选' : '全选' }}
+              </button>
+            </div>
+            <select v-model="formData.productChIds" multiple  >
+              <option    v-for="option in  channelList1" :value="option.productChId">{{ option.productChName }}</option>
             </select>
+
+            <div class="selected-items">
+              <h3>已选通道:</h3>
+              <div class="selected-tags">
+                <span v-if="formData.productChIds.length === 0" class="no-selection">暂无选择</span>
+                <div v-for="id in formData.productChIds" :key="id" class="tag">
+                  {{ getOptionName2(id) }}
+                  <button @click="removeOption2(id)">×</button>
+                </div>
+              </div>
+            </div>
+            <!--<label>通道:</label>-->
+            <!--<select   v-model="formData.channel_power_infro"  class="custom-select">-->
+              <!--<option :value="null" disabled selected hidden style="color: #aaa;">请选择耗电量复位通道...</option>-->
+              <!--<option   v-for="option in  channelList1" :value="option.channel_power_infro">{{ option.productChName }}</option>-->
+            <!--</select>-->
           </div>
           <!-- 表单按钮 -->
           <div class="form-actions">
@@ -183,6 +205,7 @@
       <div @vue:mounted="fzszData"  v-if="showFzszModal" class="modal-overlay"  >
         <div class="modal-content" style="max-width: 100%;overflow-y: hidden">
           <h2>阈值设置</h2>
+          <button @click="handleUpdateList()" style="margin: 10px;" :class="   'btn btn-on'">批量设置 </button>
           <div class="scrollable-table" style="    max-height: 60vh; ">
             <table class="device-table">
               <thead>
@@ -199,7 +222,7 @@
               </thead>
               <tbody>
               <tr v-for="power in powerThresholdList" :key="power.productChId">
-                <td :style="{{ power.colorStyle }}">{{ power.productChName }}</td>
+                <td>{{ power.productChName }}</td>
                 <td>{{ power.productChId }}</td>
                 <td>{{ power.currentUpperAction }}</td>
                 <td>{{ power.voltageUpperAction }}</td>
@@ -225,7 +248,30 @@
       <!-- 阈值设置单设备弹窗内容 -->
       <div v-if="showFzszModal2" class="modal-overlay"  >
         <div class="modal-content">
-          <div class="form-group" >
+          <div class="form-group" v-if="fzscData.list=='1'" >
+            <label>通道:</label>
+            <div class="select-header">
+              <p class="hint">提示:使用Ctrl/Cmd键进行多选</p>
+              <button class="select-all" @click="toggleSelectAll">
+                {{ fzscData.productChIds.length === Object.keys(channelList1).length  ? '取消全选' : '全选' }}
+              </button>
+            </div>
+            <select v-model="fzscData.productChIds" multiple  >
+              <option    v-for="option in  channelList1" :value="option.productChId">{{ option.productChName }}</option>
+            </select>
+
+            <div class="selected-items">
+              <h3>已选通道:</h3>
+              <div class="selected-tags">
+                <span v-if="fzscData.productChIds.length === 0" class="no-selection">暂无选择</span>
+                <div v-for="id in fzscData.productChIds" :key="id" class="tag">
+                  {{ getOptionName(id) }}
+                  <button @click="removeOption(id)">×</button>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="form-group"  v-if="fzscData.list==''">
             <label>通道号:</label>
             <input type="text" v-model="fzscData.productChId"  readonly >
           </div>
@@ -249,7 +295,6 @@
             <label>耗电量上限:</label>
             <input type="text" v-model="fzscData.alarmContentUpperAction">
           </div>
-
           <!-- 表单按钮 -->
           <div class="form-actions">
             <button  class="btn  btn-energy" @click="fzscClick()"  >提交</button>
@@ -318,6 +363,35 @@
         </div>
       </div>
 
+      <!--告警信息弹窗-->
+      <div    v-if="showFzszModalgj" class="modal-overlay"  >
+        <div class="modal-content" style="max-width: 100%;overflow-y: hidden">
+          <div class="scrollable-table" style="    max-height: 60vh; ">
+            <table class="device-table">
+              <thead>
+              <tr>
+                <th>序号</th>
+                <th>报警时间</th>
+                <th>报警类型</th>
+                <th>报警信息</th>
+              </tr>
+              </thead>
+              <tbody>
+              <tr  v-for="(item, index) in his_alarmd" :key="index">
+                <td>{{  item.number   }}</td>
+                <td>{{ item.date }}</td>
+                <td>{{ item.type }}</td>
+                <td>{{ item.waning_context }}</td>
+              </tr>
+              </tbody>
+            </table>
+          </div>
+          <!-- 表单按钮 -->
+          <div class="button-footer form-actions">
+            <button type="button"  class="btn  btn-energy" @click="fzscClickClosegj()">取消</button>
+          </div>
+        </div>
+      </div>
 
     </div>
 
@@ -726,10 +800,19 @@
                     delay_update(this.saveDataAll.channel_power_infro)
                     this.ysszClickClose2()
                 }else if(this.popType=='hdlcz'){
-                    power_reset(this.saveDataAll.channel_power_infro)
+                    for(const ket in this.saveDataAll.channel_power_infros){
+                        power_reset(this.saveDataAll.channel_power_infros[ket])
+                    }
                     this.hdlczClickClose()
                 }else if(this.popType=='fzsz'){
-                    threshold_update(this.saveDataAll.channel_power_infro)
+                    if(this.saveDataAll.list=='1'){
+                        for(const ket in this.saveDataAll.channel_power_infros){
+                            threshold_update(this.saveDataAll.channel_power_infros[ket])
+                        }
+                    }else{
+                        threshold_update(this.saveDataAll.channel_power_infro)
+                    }
+
                     this.fzscClickClose2()
                 }else if(this.popType=='tdkg'){
 
@@ -780,12 +863,16 @@
             showFormModal:false,
             // 阈值设置
             showFzszModal:false,
+            //告警
+            showFzszModalgj:false,
             showFzszModal2:false,
             showysszModal:false,
             showysszModal2:false,
-            formData:{productChName:null,productChId:null,channel_power_infro:null},
+            formData:{productChName:null,productChId:null,channel_power_infro:null,productChIds:[]},
             powerThresholdList:[],
-            fzscData:{},
+            fzscData:{
+                productChIds:[]
+            },
             items: [],
             newItem: '',
             loading: false,
@@ -824,6 +911,7 @@
             channelList1:[],
             ysszList:[],
             totalFormList:[],
+            his_alarmd:[],
             ysszData2:{},
             popMessage:'',
             popType:'',
@@ -877,6 +965,68 @@
             /** 阈值设置按钮操作 */
             handleUpdate(row) {
                 this.fzscData = JSON.parse(JSON.stringify(row));
+                this.fzscData.list='';
+                this.showFzszModal2 = true;
+                // this.title = this.$t('pz');
+            },
+            getOptionName(id) {
+                for(const key in   this.channelList1){
+                    if(this.channelList1[key].productChId===id){
+                        return this.channelList1[key].productChName
+                        break
+                    }
+                }
+                ;
+            },
+            removeOption(id) {
+                this.fzscData.productChIds = this.fzscData.productChIds.filter(optId => optId !== id);
+            },
+            toggleSelectAll() {
+
+                if (this.fzscData.productChIds.length === Object.keys(this.channelList1).length ) {
+                    this.fzscData.productChIds = [];
+                } else {
+                    for(const key in   this.channelList1){
+                        this.fzscData.productChIds.push(this.channelList1[key].productChId)
+                    }
+
+                   // this.fzscData.productChIds = this.channelList1.map(option => option.productChId);
+                }
+            },
+
+            getOptionName2(id) {
+                for(const key in   this.channelList1){
+                    if(this.channelList1[key].productChId===id){
+                        return this.channelList1[key].productChName
+                        break
+                    }
+                }
+                ;
+            },
+            removeOption2(id) {
+                this.formData.productChIds = this.formData.productChIds.filter(optId => optId !== id);
+            },
+            toggleSelectAll2() {
+                if (this.formData.productChIds.length === Object.keys(this.channelList1).length ) {
+                    this.formData.productChIds = [];
+                } else {
+                    for(const key in   this.channelList1){
+                        this.formData.productChIds.push(this.channelList1[key].productChId)
+                    }
+
+                   // this.fzscData.productChIds = this.channelList1.map(option => option.productChId);
+                }
+            },
+  /** 阈值设置按钮操作 */
+            handleUpdateList() {
+                this.fzscData.list='1';
+                this.fzscData.productChIds=[];
+                this.fzscData.currentUpperAction='';
+                this.fzscData.voltageUpperAction='';
+                this.fzscData.voltageDownAction='';
+                this.fzscData.powerUpperAction='';
+                this.fzscData.alarmContentUpperAction='';
+
                 this.showFzszModal2 = true;
                 // this.title = this.$t('pz');
             },
@@ -904,6 +1054,9 @@
                 this.powerThresholdList=[];
                 //    this.formData.productChId=null;
             },
+            fzscClickClosegj(){
+                this.showFzszModalgj = false;
+            },
 
             fzscClickClose2(){
                 this.showFzszModal2 = false
@@ -918,11 +1071,27 @@
                 this.showysszModal2 = false;
             },
 
+            hdlsz(){
+                this.formData.productChIds=[]
+                this.showFormModal = true
+            },
+
             // 耗电量重置
             async hdlczClick(){
                 const params={};
+                let lists=[]
+                console.log( this.formData.productChIds)
+                for( const id in  this.formData.productChIds){
+                    for( const key in  this.powerThresholdList ){
+                        if(this.formData.productChIds[id]== this.powerThresholdList[key].productChId){
+                            lists.push(this.powerThresholdList[key].channel_power_infro);
+                            break
+                        }
+                    }
+                }
+                params.channel_power_infros= lists;
 
-                params.channel_power_infro=this.formData.channel_power_infro;
+              //  params.channel_power_infro=this.formData.channel_power_infro;
                 this.popMessage="确认要重置此通道吗?";
                 // const result = await confirmAction({
                 //     title: message
@@ -937,12 +1106,46 @@
             // 阈值设置保存
             async fzscClick(){
                 const params={};
-                params.channel_power_infro=this.fzscData.channel_power_infro;
-                params.channel_power_infro.thr.w_upper=this.fzscData.alarmContentUpperAction* 1000;
-                params.channel_power_infro.thr.c_upper=this.fzscData.currentUpperAction* 10;
-                params.channel_power_infro.thr.p_upper=this.fzscData.powerUpperAction* 1000;
-                params.channel_power_infro.thr.v_lower=this.fzscData.voltageDownAction* 10;
-                params.channel_power_infro.thr.v_upper=this.fzscData.voltageUpperAction* 10;
+                params.list=this.fzscData.list;
+                if(this.fzscData.list=='1'){
+                    if(this.fzscData.productChIds.length==0){
+                        alert("请选择通道")
+                        return
+                    }
+                    if(this.fzscData.alarmContentUpperAction=='' || this.fzscData.currentUpperAction=='' || this.fzscData.voltageDownAction==''  || this.fzscData.voltageUpperAction==''){
+                        alert("存在未设置项,请重试")
+                        return
+                    }
+                    if(this.fzscData.voltageUpperAction!=0 && this.fzscData.voltageDownAction !=0 && this.fzscData.voltageUpperAction* 10<=this.fzscData.voltageDownAction* 10){
+                        alert("电压上限需要大于下限")
+                        return
+                    }
+                    let lists=[]
+                    for( const id in  this.fzscData.productChIds){
+                        for( const key in  this.powerThresholdList ){
+                               if(this.fzscData.productChIds[id]== this.powerThresholdList[key].productChId){
+                                   let param=this.powerThresholdList[key].channel_power_infro;
+                                   param.thr.w_upper=this.fzscData.alarmContentUpperAction* 1000;
+                                   param.thr.c_upper=this.fzscData.currentUpperAction* 10;
+                                   param.thr.p_upper=this.fzscData.powerUpperAction* 1000;
+                                   param.thr.v_lower=this.fzscData.voltageDownAction* 10;
+                                   param.thr.v_upper=this.fzscData.voltageUpperAction* 10;
+                                   lists.push(param);
+                                      break
+                               }
+                        }
+                    }
+                    params.channel_power_infros= lists;
+
+                }else{
+                    params.channel_power_infro=this.fzscData.channel_power_infro;
+                    params.channel_power_infro.thr.w_upper=this.fzscData.alarmContentUpperAction* 1000;
+                    params.channel_power_infro.thr.c_upper=this.fzscData.currentUpperAction* 10;
+                    params.channel_power_infro.thr.p_upper=this.fzscData.powerUpperAction* 1000;
+                    params.channel_power_infro.thr.v_lower=this.fzscData.voltageDownAction* 10;
+                    params.channel_power_infro.thr.v_upper=this.fzscData.voltageUpperAction* 10;
+
+                }
 
                 this.popMessage="确认要保存吗?";
                 // const result = await confirmAction({
@@ -993,18 +1196,7 @@
 
             // 获取数据方法
             async fetchData() {
-                // var js={
-                //     "sys":{
-                //         "lang": 0,
-                //         "tzone": 8,
-                //         "route": 90,
-                //         "ver": "V1.0.0\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000",
-                //         "sys_time": "2025/09/09 01:00:06\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000",
-                //         "len": 52
-                //     }
-                //
-                // }
-                // on_ws_msg(js)
+         
                 function5();
                 this.queryTotalStatus5();
                 if (activePageIntervalId1 != null) {
@@ -1012,7 +1204,7 @@
                 };
                 activePageIntervalId1 = setInterval(() => {
                     if(tabId=='tab1'){
-                        function1();
+                         function1();
                         this.queryTotalStatus();
                         if(this.wlszForm4.sys_time=='' || this.wlszForm4.sys_time==null){
                             this.queryTotalStatus5();
@@ -1051,8 +1243,23 @@
                 this.channelList1 = {...channelAllList1};
                 this.powerThresholdList = {...initialYzFormList};
                 this.ysszList = {...channelAllList1};
-                if({...data_alarm}!=null){
-                    this.statusData.alarm1 =  Object.keys({...data_alarm}).length;
+                if({...his_alarm}!=null){
+                    this.statusData.alarm1 =  Object.keys({...his_alarm}).length;
+                    var alarmds={...his_alarm};
+                    this.his_alarmd=[]
+                    for(var i=0;i<Object.keys({...his_alarm}).length ;i++){
+                        var open=alarmds[i];
+                            open.number=i+1;
+                        open.date= (open.date.replace(/\\u0000/g, '\u0000')).replace(/\u0000/g, '');
+                        open.waning_context= (open.waning_context.replace(/\\u0000/g, '\u0000')).replace(/\u0000/g, '');
+                        if(open.type==0){
+                            open.type='电量信息报警'
+                        }else if(open.type==1){
+                            open.type='传感器报警'
+                        }
+                        this.his_alarmd.push(open)
+                    }
+
                 }
                 if({...sensorc_list}!=null && Object.keys({...sensorc_list}).length>0){
                    let sencorList={...sensorc_list};
@@ -1062,7 +1269,24 @@
                                try{
                                    let sensor_val =sencorList[key].sensor_val
                                    this.statusData.temperature=sensor_val[1].val.toFixed(2)
+
+                                   if(sensor_val[1].s_alarm  & 0x1){ // 上限
+                                       this.statusData.tempcolorStyle='color: red;font-weight: bold;'
+                                   }else if(sensor_val[1].s_alarm & 0x2){ // 下限
+                                       this.statusData.tempcolorStyle='color:  #ff00ff;font-weight: bold;'
+                                   }else{
+                                       this.statusData.tempcolorStyle=''
+                                   }
+
                                    this.statusData.humidity=sensor_val[0].val.toFixed(2)
+
+                                   if(sensor_val[0].s_alarm  & 0x1){ // 上限
+                                       this.statusData.humcolorStylesx='color: red;font-weight: bold;'
+                                   }else if(sensor_val[0].s_alarm & 0x2){ // 下限
+                                       this.statusData.humcolorStylesx='color:  #ff00ff;font-weight: bold;'
+                                   }else{
+                                       this.statusData.humcolorStylesx=''
+                                   }
                                }catch (e) {
                                    console.log("温湿度传感器赋值失败")
                                }
@@ -1092,6 +1316,13 @@
                                try{
                                    let sensor_val =sencorList[key].sensor_val
                                    this.statusData.smoke=sensor_val[0].val.toFixed(2)
+                                   if(sensor_val[0] & 0x1 ){ // 上限
+                                       this.statusData.smokecolorStylesx='color: red;font-weight: bold;'
+                                   }else if(sensor_val[0] & 0x2){ // 下限
+                                       this.statusData.smokecolorStylesx='color:  #ff00ff;font-weight: bold;'
+                                   }else{
+                                       this.statusData.smokecolorStylesx=''
+                                   }
                                }catch (e) {
                                    console.log("CO2传感器赋值失败")
                                }