Browse Source

feat(configuration):m1,m2组态页面数据获取

HMY 10 months ago
parent
commit
4dff668070

+ 3 - 1
admin/src/main/java/com/dcs/equipment/task/ModbusTcpTask.java

@@ -7,8 +7,10 @@ import com.dcs.equipment.server.EquipmentListWebSocketServer;
 import com.dcs.equipment.server.EquipmentTreeWebSocketServer;
 import com.dcs.equipment.service.InfluxDBService;
 import com.dcs.equipment.service.ModbusTcpService;
+import com.dcs.hnyz.cache.CacheCenter;
 import com.dcs.hnyz.domain.EquipmentParam;
 import com.dcs.hnyz.domain.vo.EquipmentParamFormVo;
+import com.dcs.hnyz.utils.EquipmentParamUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
@@ -138,6 +140,7 @@ public class ModbusTcpTask {
             }
         }
         broadCastEquipmentParamFormVOList = Collections.unmodifiableList(deepCopyEquipmentParamFormVOList);
+        CacheCenter.registerNowDataMap= EquipmentParamUtils.paramListToMap(broadCastEquipmentParamFormVOList);
         saveDataToInfluxdb(deepCopyEquipmentParamFormVOList);
     }
 
@@ -156,5 +159,4 @@ public class ModbusTcpTask {
 //        }
     }
 
-
 }

+ 39 - 0
admin/src/main/java/com/dcs/hnyz/controller/ConfigurationPageController.java

@@ -0,0 +1,39 @@
+package com.dcs.hnyz.controller;
+
+import com.dcs.common.core.controller.BaseController;
+import com.dcs.common.core.domain.AjaxResult;
+import com.dcs.hnyz.cache.CacheCenter;
+import com.dcs.hnyz.domain.vo.EquipmentParamFormVo;
+import com.dcs.hnyz.service.IConfigurationPageService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * ConfigurationPageController
+ * 组态页面相关接口
+ * @author: hmy
+ * @date: 2025/5/29 17:25
+ */
+@RestController
+@RequestMapping("/hnyz/configuration")
+public class ConfigurationPageController extends BaseController {
+    @Resource
+    private IConfigurationPageService configurationPageService;
+
+    /**
+     * 更新组态页面配置
+     * @param pageCode 页面编码
+     * @param configMap 配置结构
+     * @return
+     */
+    @PostMapping("/config/{pageCode}")
+    public AjaxResult updateZTPageConfig(@PathVariable String pageCode, @RequestBody Map<String, List<String>> configMap) {
+        configurationPageService.updateZTPageDeviceConfig(pageCode, configMap);
+        return success();
+    }
+
+}

+ 22 - 0
admin/src/main/java/com/dcs/hnyz/domain/dto/PageDeviceSubscribeDTO.java

@@ -0,0 +1,22 @@
+package com.dcs.hnyz.domain.dto;
+
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * PageDeviceSubscribeDTO
+ * 客户端订阅消息格式(数据传输对象)
+ * @author: hmy
+ * @date: 2025/5/30 16:00
+ */
+@Data
+public class PageDeviceSubscribeDTO {
+    //页面编码
+    private String pageCode;
+    //设备组
+    private Map<String, List<String>> deviceGroupMap;
+}
+

+ 22 - 0
admin/src/main/java/com/dcs/hnyz/service/IConfigurationPageService.java

@@ -0,0 +1,22 @@
+package com.dcs.hnyz.service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * IConfigurationPageService
+ *
+ * @author: hmy
+ * @date: 2025/5/30 10:09
+ */
+public interface IConfigurationPageService {
+
+    /**
+     * 更新页面设备配置
+     * @param pageCode
+     * @param configMap
+     */
+    void updateZTPageDeviceConfig(String pageCode, Map<String, List<String>> configMap);
+
+    Map<String, List<Map<String, Object>>> getZTPageDeviceRealtimeData(String pageCode);
+}

+ 16 - 0
admin/src/main/java/com/dcs/hnyz/service/IDeviceDataService.java

@@ -0,0 +1,16 @@
+package com.dcs.hnyz.service;
+
+import com.dcs.hnyz.domain.vo.PageDeviceRealtimeVO;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * IDeviceDataService
+ *
+ * @author: hmy
+ * @date: 2025/5/30 16:15
+ */
+public interface IDeviceDataService {
+    Map<String, List<PageDeviceRealtimeVO>> buildRealtimeData(Map<String, List<String>> deviceGroupMap);
+}

+ 64 - 0
admin/src/main/java/com/dcs/hnyz/service/impl/ConfigurationPageServiceImpl.java

@@ -0,0 +1,64 @@
+package com.dcs.hnyz.service.impl;
+
+import com.dcs.hnyz.cache.CacheCenter;
+import com.dcs.hnyz.domain.vo.EquipmentParamFormVo;
+import com.dcs.hnyz.service.IConfigurationPageService;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * ConfigurationPageServiceImpl
+ *
+ * @author: hmy
+ * @date: 2025/5/30 10:10
+ */
+@Service
+public class ConfigurationPageServiceImpl implements IConfigurationPageService {
+
+    @Override
+    public void updateZTPageDeviceConfig(String pageCode, Map<String, List<String>> configMap) {
+        CacheCenter.pageDeviceGroupMap.put(pageCode,configMap);
+    }
+
+    @Override
+    public Map<String, List<Map<String, Object>>> getZTPageDeviceRealtimeData(String pageCode) {
+        Map<String, List<Map<String, Object>>> result = new HashMap<>();
+
+        Map<String, List<String>> groupMap = CacheCenter.pageDeviceGroupMap.get(pageCode);
+        if (groupMap == null) {
+            return result; // 页面未注册
+        }
+
+        for (Map.Entry<String, List<String>> groupEntry : groupMap.entrySet()) {
+            String groupKey = groupEntry.getKey(); // M1(大设备code)
+            List<String> deviceCodes = groupEntry.getValue(); // [N1, N2, ...](对应小设备code数组)
+
+            List<Map<String, Object>> deviceList = new ArrayList<>();
+
+            for (String deviceCode : deviceCodes) {
+                List<String> registerCodes = CacheCenter.deviceToRegistersMap.get(deviceCode);
+                if (registerCodes == null) continue;
+
+                List<Object> values = new ArrayList<>();
+                for (String registerCode : registerCodes) {
+                    EquipmentParamFormVo param = CacheCenter.registerNowDataMap.get(registerCode);
+                    values.add(param != null ? param.getValue() : null);
+                }
+
+                Map<String, Object> deviceData = new HashMap<>();
+                deviceData.put("code", deviceCode);
+                deviceData.put("value", values);
+
+                deviceList.add(deviceData);
+            }
+
+            result.put(groupKey, deviceList);
+        }
+
+        return result;
+    }
+}

+ 40 - 0
admin/src/main/java/com/dcs/hnyz/service/impl/DeviceDataServiceImpl.java

@@ -0,0 +1,40 @@
+package com.dcs.hnyz.service.impl;
+
+import com.dcs.hnyz.cache.CacheCenter;
+import com.dcs.hnyz.domain.vo.EquipmentParamFormVo;
+import com.dcs.hnyz.domain.vo.PageDeviceRealtimeVO;
+import com.dcs.hnyz.service.IDeviceDataService;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * DeviceDataServiceImpl
+ *
+ * @author: hmy
+ * @date: 2025/5/30 16:16
+ */
+@Service
+public class DeviceDataServiceImpl implements IDeviceDataService {
+
+    @Override
+    public Map<String, List<PageDeviceRealtimeVO>> buildRealtimeData(Map<String, List<String>> deviceGroupMap) {
+        Map<String, List<PageDeviceRealtimeVO>> result = new HashMap<>();
+
+        for (Map.Entry<String, List<String>> entry : deviceGroupMap.entrySet()) {
+            String group = entry.getKey();
+            List<PageDeviceRealtimeVO> voList = new ArrayList<>();
+            for (String deviceCode : entry.getValue()) {
+                List<String> registerCodes = CacheCenter.deviceToRegistersMap.get(deviceCode);
+                List<Object> values = Optional.ofNullable(registerCodes).orElse(Collections.emptyList()).stream()
+                        .map(code -> Optional.ofNullable(CacheCenter.registerNowDataMap.get(code)).map(EquipmentParamFormVo::getValue).orElse(null))
+                        .collect(Collectors.toList());
+                voList.add(new PageDeviceRealtimeVO(deviceCode, values));
+            }
+            result.put(group, voList);
+        }
+
+        return result;
+    }
+}

+ 96 - 0
admin/src/main/java/com/dcs/hnyz/task/WebSocketPushTask.java

@@ -0,0 +1,96 @@
+package com.dcs.hnyz.task;
+
+import com.alibaba.fastjson2.JSON;
+import com.dcs.equipment.server.EquipmentListWebSocketServer;
+import com.dcs.hnyz.cache.CacheCenter;
+import com.dcs.hnyz.domain.AlarmEvent;
+import com.dcs.hnyz.domain.dto.AlarmBroadcastPayload;
+import com.dcs.hnyz.domain.vo.EquipmentParamFormVo;
+import com.dcs.hnyz.domain.vo.PageDeviceRealtimeVO;
+import com.dcs.hnyz.service.IDeviceDataService;
+import com.dcs.hnyz.service.impl.AlarmConfigServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.messaging.simp.SimpMessagingTemplate;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * WebSocketPushTask
+ * 定时推送任务
+ * @author: hmy
+ * @date: 2025/5/30 16:06
+ */
+@Component
+public class WebSocketPushTask {
+    //TODO 改成若依的定时器
+    @Autowired
+    private SimpMessagingTemplate messagingTemplate;
+
+    @Resource
+    private EquipmentListWebSocketServer equipmentListWebSocketServer;
+
+    @Autowired
+    private IDeviceDataService deviceDataService;
+
+    @Autowired
+    private AlarmConfigServiceImpl alarmConfigService;
+
+    /**
+     * 每3秒推送一次组态页面所需实时数据
+     */
+    // @Scheduled(fixedRate = 3000)
+    public void pushData() {
+        //模拟数据
+        CacheCenter.registerNowDataMap.put("N1fm", create("N1fm", true));
+        CacheCenter.registerNowDataMap.put("N2fm", create("N2fm", true));
+        CacheCenter.registerNowDataMap.put("D5kxh", create("D5kxh", true));
+        CacheCenter.registerNowDataMap.put("D5gxh", create("D5gxh", false));
+        CacheCenter.registerNowDataMap.put("D5k", create("D5k", true));
+        CacheCenter.registerNowDataMap.put("S1wdsj", create("S1wdsj", 130));
+
+        CacheCenter.pageDeviceGroupMap.forEach((pageCode, deviceGroupMap) -> {
+            Map<String, List<PageDeviceRealtimeVO>> data = deviceDataService.buildRealtimeData(deviceGroupMap);
+            messagingTemplate.convertAndSend("/topic/page/" + pageCode, data);
+        });
+    }
+
+    //仅用来测试
+    private EquipmentParamFormVo create(String code, boolean value) {
+        EquipmentParamFormVo ep = new EquipmentParamFormVo();
+        ep.setCode(code);
+        ep.setValue(value);
+        return ep;
+    }
+
+    private EquipmentParamFormVo create(String code,int value) {
+        EquipmentParamFormVo ep = new EquipmentParamFormVo();
+        ep.setCode(code);
+        ep.setValue(value);
+        return ep;
+    }
+
+    /**
+     * 告警信息信息检测推送
+     */
+//    @Scheduled(fixedRate = 1000)
+    public void pushAlarmInfo(){
+        //测试数据
+        CacheCenter.registerNowDataMap.put("S1wdsj", create("S1wdsj", 130));
+
+//        System.out.println("告警检测");
+        List<AlarmEvent> alarms = alarmConfigService.checkAlarms();
+        if (!alarms.isEmpty()) {
+//            System.out.println("有告警信息");
+            AlarmBroadcastPayload payload = new AlarmBroadcastPayload();
+            payload.setAlarms(alarms);
+            String json = JSON.toJSONString(payload);
+            equipmentListWebSocketServer.broadCastInfo(json);
+        }
+    }
+}
+

+ 3 - 0
ui/package.json

@@ -14,6 +14,7 @@
   "dependencies": {
     "@element-plus/icons-vue": "2.3.1",
     "@kjgl77/datav-vue3": "^1.7.4",
+    "@stomp/stompjs": "^7.1.1",
     "@vueup/vue-quill": "1.2.0",
     "@vueuse/core": "10.11.0",
     "axios": "0.28.1",
@@ -29,6 +30,7 @@
     "nprogress": "0.2.0",
     "pinia": "2.1.7",
     "pinia-plugin-persistedstate": "^2.4.0",
+    "sockjs-client": "^1.6.1",
     "splitpanes": "3.1.5",
     "vue": "3.4.31",
     "vue-cropper": "1.1.1",
@@ -36,6 +38,7 @@
     "vuedraggable": "4.1.0"
   },
   "devDependencies": {
+    "@esbuild-plugins/node-globals-polyfill": "^0.2.3",
     "@vitejs/plugin-vue": "5.0.5",
     "sass": "1.77.5",
     "unplugin-auto-import": "0.17.6",

+ 11 - 0
ui/src/api/dcs/configurePage.js

@@ -0,0 +1,11 @@
+//组态页面相关的接口
+import request from '@/utils/request'
+
+// 更新组态页面设备配置
+export function updateZTPageConfig(pageCode, configMap) {
+  return request({
+    url: `/hnyz/configuration/config/${pageCode}`,
+    method: 'post',
+    data: configMap
+  })
+}

+ 6 - 4
ui/src/components/DCS/M1TankComponent.vue

@@ -2,7 +2,7 @@
 
     <div class="tank" :style="{ width: `${iconSize}px`, height: `${iconSize}px` }">
         <!-- m1罐体 -->
-        <WaterTank :temperatureValue="temperatureValue" tankType="1" :title="title" :waterLevelValue="waterLevelValue"
+        <WaterTank :temperatureValue="temperatureValue" :tankType="1" :title="title" :waterLevelValue="waterLevelValue"
             :iconSize="iconSize" class="m1_tank" :pressureValue="pressureValue" :weightValue="weightValue">
         </WaterTank>
         <!-- n4/n14 -->
@@ -74,7 +74,7 @@
 
         <!-- N2 /n13-->
         <div :style="valveProgressStyle" class="valve_progress_2" v-if="hasValve(valveNames[7])">
-            <ValveProgress :iconSize="valveIconSize" :title="valveNames[7]" pipeReverse="true"
+            <ValveProgress :iconSize="valveIconSize" :title="valveNames[7]" :pipeReverse="true"
                 :progressType="title === 'M1' ? 'heat_exchange_fluid' : 'red'"
                 :valveStatusArr="getValveStatusArr(valveNames[7])" :pipeStatus="getValveAndStatus(valveNames[7])" />
         </div>
@@ -105,7 +105,7 @@
 <script setup>
 import WaterTank from '@/components/DCS/WaterTankComponent';
 import ValveProgress from '@/components/DCS/ValveProgressComponent.vue';
-import { defineProps, computed } from 'vue'
+import { defineProps, computed, onMounted } from 'vue'
 import { useValveHelper } from '@/hooks/useValveHelper'
 
 const props = defineProps({
@@ -142,7 +142,9 @@ const props = defineProps({
     },
 })
 
-const { hasValve, getValveStatusArr, getValveAndStatus } = useValveHelper(props.valveArr)
+//props.valveArr 是响应式的“只读属性”,但不是 ref,直接传给工具函数内部会失去响应性
+const valveArrRef = computed(() => props.valveArr || []);
+const { hasValve, getValveStatusArr, getValveAndStatus } = useValveHelper(valveArrRef)
 
 //进度条配置
 const progressConfig = {

+ 26 - 13
ui/src/components/DCS/PumpComponent.vue

@@ -6,7 +6,7 @@
         <div class="pump_title" :style="getPumpTitleStyle">
             {{ props.title }}
         </div>
-        <div class="pump_status" :style="{ fontSize: `${props.iconSize / 6}px` }"> {{ props.pumpStatus }} </div>
+        <div class="pump_status" :style="{ fontSize: `${props.iconSize / 6}px` }"> {{ getStartStatus }} </div>
         <div class="pump_hz" :style="{ fontSize: `${props.iconSize / 5}px` }"> {{ hzValue }} Hz</div>
     </div>
 </template>
@@ -32,17 +32,30 @@ const props = defineProps({
         type: String,
         default: 'L'
     },
-    pumpStatus: {
-        type: String,
-        default: '正转'
-    },
-    hz: {
-        type: Number,
-        default: 0
-    },
+    pumpDataArr:{
+        type:Array,
+        default:[0,3]
+    }
+})
+
+const hzValue = computed(() => `${props.pumpDataArr[0]}` * 0.01);
+
+//状态启动字
+const getStartStatus = computed(() => {
+    switch (props.pumpDataArr[1]) {
+        case 1:
+            return '正转'
+        case 2:
+            return '反转'
+        case 3:
+            return '停机'
+        case 4:
+            return '故障'
+        default:
+            return '未知'
+    }
 })
 
-const hzValue = computed(() => `${props.hz}` * 0.01);
 // 泵图标类名
 const getPumpClass = computed(() => {
     return `icon-beng${props.pumpType}_${props.pumpDirection}`
@@ -50,9 +63,9 @@ const getPumpClass = computed(() => {
 
 // 泵标题样式
 const getPumpTitleStyle = computed(() => {
-    return props.pumpDirection === 'R'? {
-        left:'auto',
-        right:'0%'
+    return props.pumpDirection === 'R' ? {
+        left: 'auto',
+        right: '0%'
     } : {}
 })
 

+ 3 - 2
ui/src/components/DCS/S1TankComponent.vue

@@ -1,7 +1,7 @@
 <template>
     <div class="tank" :style="{ width: `${iconSize}px`, height: `${iconSize}px` }">
         <!-- s1罐体 拓展s2,s3罐体 -->
-        <WaterTank :temperatureValue="temperatureValue" tankType="3" :waterLevelValue="waterLevelValue"
+        <WaterTank :temperatureValue="temperatureValue" :tankType="3" :waterLevelValue="waterLevelValue"
             :iconSize="iconSize" :pressureValue="pressureValue" :weightValue="weightValue" :title="title"
             class="s1_tank" />
         <!-- d11阀门/d12/d13 -->
@@ -75,7 +75,8 @@ const props = defineProps({
     },
 })
 // 将 props.valveArr 转换为响应式引用传入
-const { hasValve, getValveStatusArr, getValveAndStatus } = useValveHelper(props.valveArr)
+const valveArrRef = computed(() => props.valveArr);
+const { hasValve, getValveStatusArr, getValveAndStatus } = useValveHelper(valveArrRef)
 // s1,s2,s3罐对应阀门数组
 const valveNames1 = ['D11', 'D5', 'D16', 'D8', 'N22']
 const valveNames2 = ['D12', 'D6', 'D17', 'D9', 'N23']

+ 2 - 2
ui/src/components/DCS/WaterTankComponent.vue

@@ -11,7 +11,7 @@
                 <dv-water-level-pond :config="waterLevelConfig" class="water_level" :class="waterLevelPosClass" />
             </div>
             <!-- 温度计 -->
-            <div class="slider-demo-block" v-if="temperatureValue >= 0" :class="tempPosClass">
+            <div class="slider-demo-block" v-if="temperatureValue" :class="tempPosClass">
                 <el-slider v-model="temperatureValue" vertical disabled max="140" min="-10" :marks="marks"
                     class="temperature_slider" :class="getTempClass" />
             </div>
@@ -56,7 +56,7 @@ onMounted(() => {
 const props = defineProps({
     temperatureValue: {//温度
         type: Number,
-        default: -1
+        default: null
     },
     waterLevelValue: {// 水位值
         type: Number,

+ 2 - 1
ui/src/config.js

@@ -4,5 +4,6 @@ export const BASE_URL = "127.0.0.1:38080";
 // ws 配置中使用
 export const wsConfig = {
   equipmentList: `ws://${BASE_URL}/webSocket/equipment/list`,
-  equipmentTree: `ws://${BASE_URL}/webSocket/equipment/tree`
+  equipmentTree: `ws://${BASE_URL}/webSocket/equipment/tree`,
+  stompEndpoint: `http://${BASE_URL}/ws/configurationPage`, 
 };

+ 15 - 1
ui/src/hooks/useValveHelper.js

@@ -57,11 +57,25 @@ export function useValveHelper(valveArrRef) {
     }
   };
 
+  // 获取某个 设备 的数据数组
+  const getDataArrByCode = (code) => {
+    // 检查 code 是否有效
+    if (!code || typeof code !== 'string') return [];
+
+    const valve = getArr().find(v => {
+      const vCode = v?.code;
+      return typeof vCode === 'string' && vCode.toUpperCase() === code.toUpperCase();
+    });
+
+    return valve?.value || [];
+  }
+
 
   return {
     hasValve,
     getValveStatusArr,
     getValveAndStatus,
-    getValveOrStatus
+    getValveOrStatus,
+    getDataArrByCode
   }
 }

+ 123 - 16
ui/src/views/configuratePage/m1Hydrolyze/index.vue

@@ -2,21 +2,25 @@
     <div class="page">
         <HeaderComponent title="M1水解"></HeaderComponent>
         <div class="content_page">
-            <M1Tank title="M1" :valveArr="valveArr_M1" :waterLevelValue="30" :pressureValue="0.444"
-                :temperatureValue="110" :iconSize="400" :weightValue="100" class="m1Flow_m1Tank"></M1Tank>
-            <S1Tank title="S1" :fanStatus="fanStatus" :valveArr="valveArr_S1" :pressureValue="0.444"
-                :waterLevelValue="30" :temperatureValue="20" :iconSize="300" :weightValue="100" class="m1Flow_s1Tank">
+            <M1Tank title="M1" :valveArr="valveMap.M1" :iconSize="400" :waterLevelValue="30"
+                :pressureValue="sensorHelper.getDataArrByCode('M1yl')[0]" :temperatureValue="30" :weightValue="300"
+                class="m1Flow_m1Tank">
+            </M1Tank>
+            <S1Tank title="S1" :fanStatus="fanStatus" :valveArr="valveMap.S1" :iconSize="300"
+                :pressureValue="sensorHelper.getDataArrByCode('S1yl')[0]" :waterLevelValue="30"
+                :temperatureValue="sensorHelper.getDataArrByCode('S1wd')[0]" :weightValue="100" class="m1Flow_s1Tank">
             </S1Tank>
-            <S1Tank title="S2" :fanStatus="fanStatus" :valveArr="valveArr_S2" :pressureValue="0.444"
-                :waterLevelValue="30" :temperatureValue="20" :iconSize="300" :weightValue="100" class="m1Flow_s2Tank">
+            <S1Tank title="S2" :fanStatus="fanStatus" :valveArr="valveMap.S2" :iconSize="300"
+                :pressureValue="sensorHelper.getDataArrByCode('S2yl')[0]" :waterLevelValue="30"
+                :temperatureValue="sensorHelper.getDataArrByCode('S2wd')[0]" :weightValue="100" class="m1Flow_s2Tank">
             </S1Tank>
-            <S1Tank title="S3" :fanStatus="fanStatus" :valveArr="valveArr_S3" :pressureValue="0.444"
+            <S1Tank title="S3" :fanStatus="fanStatus" :valveArr="valveMap.S3" :pressureValue="0.444"
                 :waterLevelValue="30" :temperatureValue="20" :iconSize="300" :weightValue="100" class="m1Flow_s3Tank">
             </S1Tank>
             <div class="pumps">
                 <!-- lb9 -->
                 <div class="lb9_pos">
-                    <Pump title="进料泵" :hz="5000" :pumpStatus="正转" :iconSize="100"></Pump>
+                    <Pump title="进料泵" :pumpDataArr="pumpHelper.getDataArrByCode('LB9')" :iconSize="100"></Pump>
                 </div>
             </div>
             <div class="icon_others">
@@ -157,8 +161,21 @@ import S1Tank from '@/components/DCS/S1TankComponent.vue';
 import Pump from '@/components/DCS/PumpComponent.vue';
 import { useValveHelper } from '@/hooks/useValveHelper'
 import { useRouter } from 'vue-router'
-
+import { stompClient } from '@/utils/ws/stompClient';
+import { onMounted, onBeforeUnmount, reactive } from 'vue';
+import { updateZTPageConfig } from '@/api/dcs/configurePage';
+import { computed } from 'vue';
 const router = useRouter()
+
+const pageCode = 'm1Hydrolyze';
+const pageParams = {
+    "M1": ['N1', 'N3', 'N4', 'N5', 'N6', 'N7', 'N8', 'N9', 'N10', 'N11'],
+    "S1": ['N10', 'D5', 'D11', 'N22', 'D16', 'D8'],
+    "S2": ['D6', 'D9', 'D17', 'D12', 'N23', 'N10'],
+    "S3": ['D7', 'D10', 'D13', 'N24', 'N10'],
+    "PUMP": ['LB9'],
+    "SENSORS": ['M1yl', 'M1cz', 'M1wd', 'S1yl', 'S1cz', 'S1wd', 'S2yl', 'S2cz', 'S2wd', 'S3yl', 'S3cz', 'S3wd'],
+}
 //M1罐阀门状态
 const valveArr_M1 = [
     {
@@ -206,7 +223,6 @@ const valveArr_M1 = [
         value: [true],
     },
 ]
-
 //S1罐阀门状态
 const valveArr_S1 = [
     {
@@ -286,15 +302,106 @@ const valveArr_S3 = [
         value: [true],
     },
 ]
+//传感器状态
+const sensorArr = [
+    {
+        code: 'M1yl',
+        value: [0.5],
+    },
+    {
+        code: 'M1cz',
+        value: [100],
+    },
+    {
+        code: 'M1wd',
+        value: [30],
+    },
+    {
+        code: 'S1yl',
+        value: [0.6],
+    },
+    {
+        code: 'S1cz',
+        value: [100],
+    },
+    {
+        code: 'S1wd',
+        value: [30],
+    },
+    {
+        code: 'S2yl',
+        value: [0.3],
+    },
+    {
+        code: 'S2cz',
+        value: [100],
+    },
+    {
+        code: 'S2wd',
+        value: [30],
+    },
+    {
+        code: 'S3yl',
+        value: [0.5],
+    },
+    {
+        code: 'S3cz',
+        value: [100],
+    },
+    {
+        code: 'S3wd',
+        value: [30],
+    },
+]
+const pumpArr = [
+    {
+        code: 'LB9',
+        value: [0, 3],
+    },
+]
+
+const valveMap = reactive({
+    M1: valveArr_M1,
+    S1: valveArr_S1,
+    S2: valveArr_S2,
+    S3: valveArr_S3,
+    PUMP: pumpArr,
+    SENSORS: sensorArr,
+})
+onMounted(() => {
+    updateZTPageConfig(pageCode, pageParams).then(res => {
+        // console.log('页面配置成功:', res);
+    }).catch(err => {
+        console.log('页面配置失败:', err);
+    });
+    stompClient.subscribeToPage(pageCode, (data) => {
+        valveMap.M1 = Object.values(data.M1)
+        valveMap.S1 = Object.values(data.S1)
+        valveMap.S2 = Object.values(data.S2)
+        valveMap.S3 = Object.values(data.S3)
+        valveMap.PUMP = Object.values(data.PUMP)
+        valveMap.SENSORS = Object.values(data.SENSORS)
+        // console.log('页面数据更新:', data.SENSORS);
+    });
+});
+
+onBeforeUnmount(() => {
+    // 页面销毁时取消订阅
+    stompClient.unsubscribeFromPage(pageCode);
+});
+
 //所有阀门状态
-const valveArr = [...new Set([
-    ...valveArr_M1,
-    ...valveArr_S1,
-    ...valveArr_S2,
-    ...valveArr_S3
-])];
+const valveArr = computed(() => [...new Set([
+    ...valveMap.M1,
+    ...valveMap.S1,
+    ...valveMap.S2,
+    ...valveMap.S3,
+])]);
 
 const { getValveAndStatus, getValveOrStatus } = useValveHelper(valveArr)
+const pumpHelper = useValveHelper(computed(() => valveMap.PUMP))
+const sensorHelper = useValveHelper(computed(() => valveMap.SENSORS))
+
 
 //搅拌电机运行状态
 const fanStatus = true;

+ 136 - 93
ui/src/views/configuratePage/m2OutMaterial/index.vue

@@ -2,28 +2,27 @@
     <div class="page">
         <HeaderComponent title="M2出料"></HeaderComponent>
         <div class="content_page">
-            <M1Tank title="M2" :valveArr="valveArr_M2" :waterLevelValue="30" :pressureValue="0.444"
-                :temperatureValue="110" :iconSize="400" :weightValue="100" class="m2Flow_m1Tank"></M1Tank>
-            <S1Tank title="S1" :fanStatus="fanStatus" :valveArr="valveArr_S1" :pressureValue="0.444"
-                :waterLevelValue="30" :temperatureValue="20" :iconSize="300" :weightValue="100" class="m2Flow_s1Tank">
+            <M1Tank title="M2" :valveArr="valveMap.M2" :waterLevelValue="30"
+                :pressureValue="sensorHelper.getDataArrByCode('M2yl')[0]" :temperatureValue="110" :iconSize="400"
+                :weightValue="100" class="m2Flow_m1Tank"></M1Tank>
+            <S1Tank title="S1" :fanStatus="fanStatus" :valveArr="valveMap.S1" :iconSize="300"
+                :pressureValue="sensorHelper.getDataArrByCode('S1yl')[0]" :waterLevelValue="30"
+                :temperatureValue="sensorHelper.getDataArrByCode('S1wd')[0]" class="m2Flow_s1Tank">
             </S1Tank>
-            <S1Tank title="S2" :fanStatus="fanStatus" :valveArr="valveArr_S2" :pressureValue="0.444"
-                :waterLevelValue="30" :temperatureValue="20" :iconSize="300" :weightValue="100" class="m2Flow_s2Tank">
+            <S1Tank title="S2" :fanStatus="fanStatus" :valveArr="valveMap.S2" :iconSize="300"
+                :pressureValue="sensorHelper.getDataArrByCode('S2yl')[0]" :waterLevelValue="30"
+                :temperatureValue="sensorHelper.getDataArrByCode('S2wd')[0]" class="m2Flow_s2Tank">
             </S1Tank>
             <S1Tank title="S3" :fanStatus="fanStatus" :valveArr="valveArr_S3" :pressureValue="0.444"
                 :waterLevelValue="30" :temperatureValue="20" :iconSize="300" :weightValue="100" class="m2Flow_s3Tank">
             </S1Tank>
             <WaterTank title="P1" :tankType="3" class="m2Flow_p1Tank" :iconSize="300"></WaterTank>
 
-            <!-- <J1Tank title="J2" :valveArr="valveArr_J2" :iconSize="300" class="m2Flow_j1Tank"></J1Tank> -->
             <div class="pumps">
-                <!-- lb9 -->
+                <!-- lb6 -->
                 <div class="lb6_pos">
-                    <Pump title="出料泵" :hz="5000" :pumpStatus="正转" :iconSize="100"></Pump>
+                    <Pump title="出料泵" :pumpDataArr="pumpHelper.getDataArrByCode('LB6')" :iconSize="100"></Pump>
                 </div>
-                <!-- <div class="lb7_pos">
-                    <Pump title="换热进液泵" :hz="5000" :pumpStatus="正转" :iconSize="100"></Pump>
-                </div> -->
             </div>
             <div class="icon_others">
                 <div class="other1">
@@ -62,24 +61,6 @@
                     :striped-flow="getValveAndStatus('N12') && getValveOrStatus('N22', 'N23', 'N24')"
                     :duration="progressConfig.duration" class="progress_materials progress_pos2_2" />
 
-                <!-- m2-换热进液泵-j2 -->
-                <!-- <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
-                     :striped="getValveAndStatus('N15') && getValveOrStatus('N16', 'N17')"
-                    :striped-flow="getValveAndStatus('N15') && getValveOrStatus('N16', 'N17')"
-                    :duration="progressConfig.duration" class="progress_red progress_pos3" />
-                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
-                     :striped="getValveAndStatus('N15', 'D4') && getValveOrStatus('N16', 'N17')"
-                    :striped-flow="getValveAndStatus('N15', 'D4') && getValveOrStatus('N16', 'N17')"
-                    :duration="progressConfig.duration" class="progress_red progress_pos4 rotate_270" />
-                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
-                     :striped="getValveAndStatus('N15', 'D4') && getValveOrStatus('N16', 'N17')"
-                    :striped-flow="getValveAndStatus('N15', 'D4') && getValveOrStatus('N16', 'N17')" :duration="20"
-                    class="progress_red progress_pos5" />
-                <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
-                     :striped="getValveAndStatus('N15', 'D4') && getValveOrStatus('N16', 'N17')"
-                    :striped-flow="getValveAndStatus('N15', 'D4') && getValveOrStatus('N16', 'N17')" :duration="30"
-                    class="progress_red progress_pos6 rotate_90" /> -->
-
                 <!-- 喷淋塔相关管道 -->
                 <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
                     :striped="getValveOrStatus('D16')" :striped-flow="getValveOrStatus('D16')" :duration="20"
@@ -138,13 +119,16 @@
 
                 <!-- 通向m1流程页面的管道 -->
                 <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
-                    :striped="getValveOrStatus('D6', 'D7')" :striped-flow="getValveOrStatus('D6', 'D7')"
+                    :striped="getValveOrStatus('D6', 'D7') && getValveAndStatus('N10')"
+                    :striped-flow="getValveOrStatus('D6', 'D7') && getValveAndStatus('N10')"
                     :duration="progressConfig.duration" class="progress_materials progress_pos15_1" />
                 <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
-                    :striped="getValveAndStatus('D7')" :striped-flow="getValveAndStatus('D7')"
+                    :striped="getValveAndStatus('D7') && getValveAndStatus('N10')"
+                    :striped-flow="getValveAndStatus('D7') && getValveAndStatus('N10')"
                     :duration="progressConfig.duration" class="progress_materials progress_pos15_2" />
                 <el-progress :percentage="100" :stroke-width="progressConfig.strokeWidth" :show-text="false"
-                    :striped="getValveOrStatus('D5', 'D6', 'D7')" :striped-flow="getValveOrStatus('D5', 'D6', 'D7')"
+                    :striped="getValveOrStatus('D5', 'D6', 'D7') && getValveAndStatus('N10')"
+                    :striped-flow="getValveOrStatus('D5', 'D6', 'D7') && getValveAndStatus('N10')"
                     :duration="progressConfig.duration" class="progress_materials progress_pos16 rotate_90" />
 
                 <!-- 通向换热流程的管道 -->
@@ -177,13 +161,25 @@
 import M1Tank from '@/components/DCS/M1TankComponent.vue';
 import S1Tank from '@/components/DCS/S1TankComponent.vue';
 import WaterTank from '@/components/DCS/WaterTankComponent.vue';
-import J1Tank from '@/components/DCS/J1TankComponent.vue';
 import Pump from '@/components/DCS/PumpComponent.vue';
 import { useValveHelper } from '@/hooks/useValveHelper'
 import { useRouter } from 'vue-router'
-import { computed } from 'vue';
+import { computed, onMounted, onBeforeUnmount } from 'vue';
 
+import { stompClient } from '@/utils/ws/stompClient';
+import { updateZTPageConfig } from '@/api/dcs/configurePage';
 const router = useRouter()
+
+const pageCode = 'm2OutMaterial';
+const pageParams = {
+    "M2": ['N12', 'N13', 'N14', 'N15', 'N16', 'N17', 'N18', 'N20'],
+    "S1": ['N10', 'D5', 'D11', 'N22', 'D16', 'D8'],
+    "S2": ['D6', 'D9', 'D17', 'D12', 'N23', 'N10'],
+    "S3": ['D7', 'D10', 'D13', 'N24', 'N10'],
+    "PUMP": ['LB6'],
+    "SENSORS": ['M2yl', 'M2cz', 'M2wd', 'S1yl', 'S1cz', 'S1wd', 'S2yl', 'S2cz', 'S2wd', 'S3yl', 'S3cz', 'S3wd'],
+}
+
 //M1罐阀门状态
 const valveArr_M2 = [
     {
@@ -223,7 +219,6 @@ const valveArr_M2 = [
     //     value: [true],
     // },
 ]
-
 //S1罐阀门状态
 const valveArr_S1 = [
     {
@@ -254,6 +249,10 @@ const valveArr_S1 = [
 ]
 //S2罐阀门状态
 const valveArr_S2 = [
+    {
+        code: 'N10',
+        value: [true],
+    },
     {
         code: 'D6',
         value: [true, false, false],
@@ -278,46 +277,126 @@ const valveArr_S2 = [
 ]
 //S3罐阀门状态
 const valveArr_S3 = [
+    {
+        code: 'N10',
+        value: [true],
+    },
     {
         code: 'D7',
         value: [false, true, false],
     },
     {
         code: 'D10',
-        value: [true, false, false],
+        value: [false, true, false],
     },
     {
         code: 'D13',
-        value: [true, false, false],
+        value: [false, true, false],
     },
     {
         code: 'N24',
-        value: [true],
+        value: [false],
     },
 
 ]
-
-const valveArr_J2 = [
-    // {
-    //     code: 'D3',
-    //     value: [true, false, true],
-    // },
+//传感器状态
+const sensorArr = [
     {
-        code: 'D4',
-        value: [true, false, true],
-    }
+        code: 'M2yl',
+        value: [0.5],
+    },
+    {
+        code: 'M2cz',
+        value: [100],
+    },
+    {
+        code: 'M2wd',
+        value: [30],
+    },
+    {
+        code: 'S1yl',
+        value: [0.6],
+    },
+    {
+        code: 'S1cz',
+        value: [100],
+    },
+    {
+        code: 'S1wd',
+        value: [30],
+    },
+    {
+        code: 'S2yl',
+        value: [0.3],
+    },
+    {
+        code: 'S2cz',
+        value: [100],
+    },
+    {
+        code: 'S2wd',
+        value: [30],
+    },
+    {
+        code: 'S3yl',
+        value: [0.5],
+    },
+    {
+        code: 'S3cz',
+        value: [100],
+    },
+    {
+        code: 'S3wd',
+        value: [30],
+    },
+]
+const pumpArr = [
+    {
+        code: 'LB9',
+        value: [0, 3],
+    },
 ]
+
+const valveMap = reactive({
+    M2: valveArr_M2,
+    S1: valveArr_S1,
+    S2: valveArr_S2,
+    S3: valveArr_S3,
+    PUMP: pumpArr,
+    SENSORS: sensorArr,
+})
+onMounted(() => {
+    updateZTPageConfig(pageCode, pageParams).then(res => {
+        // console.log('页面配置成功:', res);
+    }).catch(err => {
+        console.log('页面配置失败:', err);
+    });
+    stompClient.subscribeToPage(pageCode, (data) => {
+        valveMap.M2 = Object.values(data.M2)
+        valveMap.S1 = Object.values(data.S1)
+        valveMap.S2 = Object.values(data.S2)
+        valveMap.S3 = Object.values(data.S3)
+        valveMap.PUMP = Object.values(data.PUMP)
+        valveMap.SENSORS = Object.values(data.SENSORS)
+    });
+});
+
+onBeforeUnmount(() => {
+    // 页面销毁时取消订阅
+    stompClient.unsubscribeFromPage(pageCode);
+});
+
 //所有阀门状态
-const valveArr = [...new Set([
-    ...valveArr_M2,
-    ...valveArr_S1,
-    ...valveArr_S2,
-    ...valveArr_S3,
-    ...valveArr_J2
-])];
+const valveArr = computed(() => [...new Set([
+    ...valveMap.M2,
+    ...valveMap.S1,
+    ...valveMap.S2,
+    ...valveMap.S3,
+])]);
 
 const { getValveAndStatus, getValveOrStatus } = useValveHelper(valveArr)
-
+const pumpHelper = useValveHelper(computed(() => valveMap.PUMP))
+const sensorHelper = useValveHelper(computed(() => valveMap.SENSORS))
 //搅拌电机运行状态
 const fanStatus = true;
 
@@ -387,8 +466,7 @@ const pumpStatus_N18 = computed(() => {
 
         .pumps {
 
-            .lb6_pos,
-            .lb7_pos {
+            .lb6_pos {
                 z-index: 15;
             }
 
@@ -399,13 +477,6 @@ const pumpStatus_N18 = computed(() => {
                 transform: translate(-50%, -50%);
             }
 
-            .lb7_pos {
-                position: absolute;
-                top: 23%;
-                left: 69.6%;
-                transform: translate(-50%, -50%);
-            }
-
         }
 
         //其他图标
@@ -520,34 +591,6 @@ const pumpStatus_N18 = computed(() => {
                 width: 7.3%;
             }
 
-            .progress_pos3 {
-                position: absolute;
-                top: 23.1%;
-                left: 58%;
-                width: 11.3%;
-            }
-
-            .progress_pos4 {
-                position: absolute;
-                top: 18.1%;
-                left: 66.5%;
-                width: 5.3%;
-            }
-
-            .progress_pos5 {
-                position: absolute;
-                top: 13.1%;
-                left: 69%;
-                width: 18.9%;
-            }
-
-            .progress_pos6 {
-                position: absolute;
-                top: 40%;
-                left: 73.6%;
-                width: 28.3%;
-            }
-
             //喷淋塔相关管道
             .progress_pos7_1 {
                 position: absolute;

+ 14 - 0
ui/vite.config.js

@@ -2,6 +2,7 @@ import { defineConfig, loadEnv } from 'vite'
 import path from 'path'
 import createVitePlugins from './vite/plugins'
 import {BASE_URL} from './src/config'
+import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill';
 
 // https://vitejs.dev/config/
 export default defineConfig(({ mode, command }) => {
@@ -65,6 +66,19 @@ export default defineConfig(({ mode, command }) => {
           }
         ]
       }
+    },
+    optimizeDeps: {
+      esbuildOptions: {
+        define: {
+          global: 'globalThis'
+        },
+        plugins: [
+          NodeGlobalsPolyfillPlugin({
+            process: true,
+            buffer: true,
+          })
+        ]
+      }
     }
   }
 })