浏览代码

1.大屏优化

wangxiaofei 2 月之前
父节点
当前提交
2e7406ab3f

+ 325 - 319
taphole-iron/src/main/java/com/sckj/iron/service/impl/TIronVisualScreenServiceImpl.java

@@ -1,6 +1,5 @@
 package com.sckj.iron.service.impl;
 
-import com.sckj.common.exception.OperateException;
 import com.sckj.common.util.TimeUtils;
 import com.sckj.iron.dto.IronTrendL1DTO;
 import com.sckj.iron.dto.IronTrendL2DTO;
@@ -18,7 +17,6 @@ import javax.annotation.Resource;
 import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
 import java.util.stream.Collectors;
 
 @Slf4j
@@ -40,28 +38,37 @@ public class TIronVisualScreenServiceImpl {
      * @param result
      * @return
      */
-    public Map<String, Object> getIronLegend(Map<String, Object> result) {
+    public synchronized Map<String, Object> getIronLegend(Map<String, Object> result) {
 
-        // L2类
-        CompletableFuture<TL2Data> preL2Future = CompletableFuture.supplyAsync(() ->
+        //最新L2数据
+        CompletableFuture<TL2Data> latestL2Future = CompletableFuture.supplyAsync(() ->
                 tl2DataService.lambdaQuery()
-                        .le(TL2Data::getIronStarttime, new SimpleDateFormat("yyyyMMddHHmmss").format(new java.util.Date()))
+                        //.le(TL2Data::getIronStarttime, new SimpleDateFormat("yyyyMMddHHmmss").format(new java.util.Date()))
                         .eq(TL2Data::getTapholeId, "1")
                         .orderByDesc(TL2Data::getIronStarttime)
                         .last("limit 1").one()
         );
 
         // 1. 计算起止时间
-        // 临时调试用,固定时间范围
-        final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-        final java.util.Date startTime;
-        final java.util.Date endTime;
-        try {
-            startTime = sdf.parse("2025-07-13 02:15:00");
-            endTime = sdf.parse("2025-07-14 00:20:00");
-        } catch (Exception e) {
-            throw new RuntimeException("时间解析失败", e);
-        }
+        int hours = 24;
+        //给固定时间,24小时之内
+        java.util.Date endTime = new java.util.Date();
+        java.util.Calendar cal = java.util.Calendar.getInstance();
+        cal.setTime(endTime);
+        cal.add(java.util.Calendar.HOUR_OF_DAY, -hours);
+        java.util.Date startTime = cal.getTime();
+
+//        // 1. 计算起止时间
+//        // 临时调试用,固定时间范围
+//        final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+//        final java.util.Date startTime;
+//        final java.util.Date endTime;
+//        try {
+//            startTime = sdf.parse("2025-07-13 02:15:00");
+//            endTime = sdf.parse("2025-07-14 00:20:00");
+//        } catch (Exception e) {
+//            throw new RuntimeException("时间解析失败", e);
+//        }
 
 
         // 1. 生成完整的每一分钟时间点
@@ -77,9 +84,12 @@ public class TIronVisualScreenServiceImpl {
         CompletableFuture<List<OPCData>> opcDataFuture = CompletableFuture.supplyAsync(() ->
                 opcDataService.lambdaQuery()
                         .in(OPCData::getPointName, Arrays.asList(
+                                "BF4_1_IRONNOTCH_MIR_TEMP",                 // 温度
+                                "BF4_1_IRONNOTCH_RAILLINE_ACPIRON_SPEED1",  // 1车流速
+                                "BF4_1_IRONNOTCH_RAILLINE_ACPIRON_SPEED2",  // 2车流速
                                 "BF4_1TH_1_MIR_NWT",                        // 四高炉1TH-1号车铁水净重
-                                "BF4_1TH_2_MIR_NWT",                     // 四高炉1TH-2号车铁水净重
-                                "BF4_1_IRONNOTCH_TAPPING",                      // 四高炉1TH-2号车铁水净重
+                                "BF4_1TH_2_MIR_NWT",                        // 四高炉1TH-2号车铁水净重
+                                "BF4_1_IRONNOTCH_TAPPING",                  // 四高炉1号铁口出铁状态
                                 "BF4_1TH_2_TPC_CARNO",                      // 1TH-2号车混铁车车号
                                 "BF4_1TH_1_TPC_CARNO"                       // 1TH-1号车混铁车车号
                         ))
@@ -112,13 +122,17 @@ public class TIronVisualScreenServiceImpl {
 
         Integer preTappingVal = null;
 
-
         try {
-            CompletableFuture.allOf(preTappingFuture, preL2Future, opcDataFuture).join();
+            CompletableFuture.allOf(preTappingFuture, latestL2Future, opcDataFuture).join();
             Map<String, List<OPCData>> opcDataMap = opcDataFuture.get().stream()
                     .collect(Collectors.groupingBy(OPCData::getPointName));
 
-            TL2Data preL2 = preL2Future.get();
+            TL2Data latestL2 = latestL2Future.get();
+            result.put("elementS", RealtimeData.builder().desc("铁水成分-硫").value(latestL2.getElementS()).build());
+            result.put("elementSi", RealtimeData.builder().desc("铁水成分-硅").value(latestL2.getElementSi()).build());
+            result.put("mudWeight", RealtimeData.builder().desc("泥炮量").value(latestL2.getMudWeight()).unit("L").build());
+            result.put("pollMm", RealtimeData.builder().desc("钻杆直径").value(latestL2.getPollMm()).unit("mm").build());
+            result.put("openDepth", RealtimeData.builder().desc("开口深度").value(latestL2.getOpenDepth()).unit("mm").build());
 
 
             //如果开始时间点没有值就从最近的获取
@@ -138,11 +152,6 @@ public class TIronVisualScreenServiceImpl {
                 }
             }
 
-            result.put("elementS", RealtimeData.builder().desc("铁水成分-硫").value(preL2.getElementS()).build());
-            result.put("elementSi", RealtimeData.builder().desc("铁水成分-硅").value(preL2.getElementSi()).build());
-            result.put("mudWeight", RealtimeData.builder().desc("泥炮量").value(preL2.getMudWeight()).unit("L").build());
-            result.put("pollMm", RealtimeData.builder().desc("钻杆直径").value(preL2.getPollMm()).unit("mm").build());
-            result.put("openDepth", RealtimeData.builder().desc("开口深度").value(preL2.getOpenDepth()).unit("mm").build());
 
             //BF4_1TH_1_MIR_NWT 1号车净重
             CompletableFuture<List<IronTrendL1DTO>> weight1ListFuture = CompletableFuture.supplyAsync(() ->
@@ -166,7 +175,7 @@ public class TIronVisualScreenServiceImpl {
                             }).collect(Collectors.toList())
             );
 
-            //BF4_1TH_1_TPC_CARNO 2号车净重
+            //BF4_1TH_1_TPC_CARNO 2号车
             CompletableFuture<List<IronTrendL1DTO>> car1ListFuture = CompletableFuture.supplyAsync(() ->
                     opcDataMap.getOrDefault("BF4_1TH_1_TPC_CARNO", new ArrayList<>())
                             .stream().map(item -> {
@@ -177,7 +186,7 @@ public class TIronVisualScreenServiceImpl {
                             }).collect(Collectors.toList())
             );
 
-            //BF4_1TH_2_TPC_CARNO 2号车净重
+            //BF4_1TH_2_TPC_CARNO 2号车
             CompletableFuture<List<IronTrendL1DTO>> car2ListFuture = CompletableFuture.supplyAsync(() ->
                     opcDataMap.getOrDefault("BF4_1TH_2_TPC_CARNO", new ArrayList<>())
                             .stream().map(item -> {
@@ -187,7 +196,8 @@ public class TIronVisualScreenServiceImpl {
                                 return dto;
                             }).collect(Collectors.toList())
             );
-            //BF4_1TH_2_TPC_CARNO 2号车净重
+
+            //1号铁口状态
             CompletableFuture<List<IronTrendL1DTO>> tapping1ListFuture = CompletableFuture.supplyAsync(() ->
                     opcDataMap.getOrDefault("BF4_1_IRONNOTCH_TAPPING", new ArrayList<>())
                             .stream().map(item -> {
@@ -242,11 +252,11 @@ public class TIronVisualScreenServiceImpl {
             List<IronTrendL1DTO> car2List = car2ListFuture.get();
 
             int ironWeightScale = 2; // 可调整为0、1、2等
-            List<List<Object>> ironFlowArr = buildIronWeightMinuteArray(xAxis, tappingMap, weight1List, weight2List, ironWeightScale);
+            List<List<Object>> ironWeightArr = buildIronWeightMinuteArray(xAxis, tappingMap, weight1List, weight2List, ironWeightScale);
 
-            if (ObjectUtils.isNotEmpty(ironFlowArr)) {
+            if (ObjectUtils.isNotEmpty(ironWeightArr)) {
                 List<Map<String, Object>> mapList = new ArrayList<>();
-                for (List<Object> objects : ironFlowArr) {
+                for (List<Object> objects : ironWeightArr) {
                     String string = objects.get(0).toString();
                     String data = objects.get(1).toString();
                     for (IronTrendL1DTO ironTrendL1DTO : car1List) {
@@ -268,9 +278,10 @@ public class TIronVisualScreenServiceImpl {
                         }
                     }
                 }
+
                 RealtimeData ironWeight = (RealtimeData) result.getOrDefault("ironWeight", RealtimeData.builder().desc("铁水流量").unit("t").value(0).build());
                 Map<String, Object> extraMap = new HashMap<>();
-                extraMap.put("mark", mapList);
+                extraMap.put("mark",  new ArrayList<>());
                 ironWeight.setExtra(extraMap);
 
                 result.put("ironWeight", ironWeight);
@@ -300,12 +311,10 @@ public class TIronVisualScreenServiceImpl {
                 result.put("ironCosttime", ironCosttime);
             }
 
-
         } catch (Exception e) {
-            throw new RuntimeException(e);
+             e.printStackTrace();
         }
 
-
         return result;
     }
 
@@ -317,17 +326,30 @@ public class TIronVisualScreenServiceImpl {
      * @param queryDateType
      * @return
      */
-    public Map<String, Object> getIronChart(TrendRequest queryDateType) {
+    public synchronized Map<String, Object> getIronChart(TrendRequest queryDateType) {
+        // 1. 计算起止时间
+        int hours = Objects.isNull(queryDateType.getQueryHourBefore()) ? 24 : queryDateType.getQueryHourBefore();
+        //给固定时间,24小时之内
+        java.util.Date endTime = new java.util.Date();
+        java.util.Calendar cal = java.util.Calendar.getInstance();
+        cal.setTime(endTime);
+        cal.add(java.util.Calendar.HOUR_OF_DAY, -hours);
+        java.util.Date startTime = cal.getTime();
+//        // ====== 日志定位时间区间开始 ======
+//        System.out.println("[DEBUG] hours: " + hours);
+//        System.out.println("[DEBUG] startTime: " + sdfMinute.format(startTime));
+//        System.out.println("[DEBUG] endTime: " + sdfMinute.format(endTime));
+        // ====== 日志定位时间区间结束 ======
         // 临时调试用,固定时间范围
-        final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-        final java.util.Date startTime;
-        final java.util.Date endTime;
-        try {
-            startTime = sdf.parse("2025-07-13 02:15:00");
-            endTime = sdf.parse("2025-07-14 00:20:00");
-        } catch (Exception e) {
-            throw new RuntimeException("时间解析失败", e);
-        }
+//        final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+//        final java.util.Date startTime;
+//        final java.util.Date endTime;
+//        try {
+//            startTime = sdf.parse("2025-07-13 02:15:00");
+//            endTime = sdf.parse("2025-07-14 00:20:00");
+//        } catch (Exception e) {
+//            throw new RuntimeException("时间解析失败", e);
+//        }
 
         // 2. 异步查询所有数据
         CompletableFuture<List<OPCData>> opcDataFuture = CompletableFuture.supplyAsync(() ->
@@ -362,284 +384,271 @@ public class TIronVisualScreenServiceImpl {
             CompletableFuture.allOf(opcDataFuture, l2DataFuture).join();
 
             // 4. 按pointName分类OPC数据并转换为DTO
-            try {
-                Map<String, List<OPCData>> opcDataMap = opcDataFuture.get().stream()
-                        .collect(Collectors.groupingBy(OPCData::getPointName));
-
-                List<TL2Data> l2DataList = l2DataFuture.get();
-
-                // 并行转换所有数据
-                //铁水温度
-                CompletableFuture<List<IronTrendL1DTO>> tempListFuture = CompletableFuture.supplyAsync(() ->
-                        opcDataMap.getOrDefault("BF4_1_IRONNOTCH_MIR_TEMP", new ArrayList<>())
-                                .stream().map(item -> {
-                                    IronTrendL1DTO dto = new IronTrendL1DTO();
-                                    dto.setData(item.getData());
-                                    dto.setCreateTime(item.getSourceTime());
-                                    return dto;
-                                }).collect(Collectors.toList())
-                );
-
-                //1TH-1号车受铁速度
-                CompletableFuture<List<IronTrendL1DTO>> speed1ListFuture = CompletableFuture.supplyAsync(() ->
-                        opcDataMap.getOrDefault("BF4_1_IRONNOTCH_RAILLINE_ACPIRON_SPEED1", new ArrayList<>())
-                                .stream().map(item -> {
-                                    IronTrendL1DTO dto = new IronTrendL1DTO();
-                                    dto.setData(item.getData());
-                                    dto.setCreateTime(item.getSourceTime());
-                                    return dto;
-                                }).collect(Collectors.toList())
-                );
-
-                //1TH-2号车受铁速度
-                CompletableFuture<List<IronTrendL1DTO>> speed2ListFuture = CompletableFuture.supplyAsync(() ->
-                        opcDataMap.getOrDefault("BF4_1_IRONNOTCH_RAILLINE_ACPIRON_SPEED2", new ArrayList<>())
-                                .stream().map(item -> {
-                                    IronTrendL1DTO dto = new IronTrendL1DTO();
-                                    dto.setData(item.getData());
-                                    dto.setCreateTime(item.getSourceTime());
-                                    return dto;
-                                }).collect(Collectors.toList())
-                );
-
-                //BF4_1TH_1_MIR_NWT 1号车净重
-                CompletableFuture<List<IronTrendL1DTO>> weight1ListFuture = CompletableFuture.supplyAsync(() ->
-                        opcDataMap.getOrDefault("BF4_1TH_1_MIR_NWT", new ArrayList<>())
-                                .stream().map(item -> {
-                                    IronTrendL1DTO dto = new IronTrendL1DTO();
-                                    dto.setData(item.getData());
-                                    dto.setCreateTime(item.getSourceTime());
-                                    return dto;
-                                }).collect(Collectors.toList())
-                );
-
-                //BF4_1TH_2_MIR_NWT 2号车净重
-                CompletableFuture<List<IronTrendL1DTO>> weight2ListFuture = CompletableFuture.supplyAsync(() ->
-                        opcDataMap.getOrDefault("BF4_1TH_2_MIR_NWT", new ArrayList<>())
-                                .stream().map(item -> {
-                                    IronTrendL1DTO dto = new IronTrendL1DTO();
-                                    dto.setData(item.getData());
-                                    dto.setCreateTime(item.getSourceTime());
-                                    return dto;
-                                }).collect(Collectors.toList())
-                );
-
-                //L2
-                CompletableFuture<List<IronTrendL2DTO>> elemenListFuture = CompletableFuture.supplyAsync(() ->
-                        l2DataList.stream().map(item -> {
-                            IronTrendL2DTO dto = new IronTrendL2DTO();
-                            try {
-                                dto.setElementS(item.getElementS() != null ? Double.parseDouble(item.getElementS()) : null);
-                            } catch (NumberFormatException e) {
-                                dto.setElementS(null);
-                            }
-                            try {
-                                dto.setElementSi(item.getElementSi() != null ? Double.parseDouble(item.getElementSi()) : null);
-                            } catch (NumberFormatException e) {
-                                dto.setElementSi(null);
-                            }
-                            dto.setIronStarttime(item.getIronStarttime());
-                            dto.setIronEndtime(item.getIronEndtime());
-                            dto.setPollMm(item.getPollMm());
-                            dto.setOpenDepth(item.getOpenDepth());
-                            dto.setMudWeight(item.getMudWeight());
-                            dto.setIronCosttime(item.getIronCosttime());
-                            return dto;
-                        }).collect(Collectors.toList())
-                );
-
-                // 等待所有转换完成
-                CompletableFuture.allOf(
-                        tempListFuture,
-                        speed1ListFuture,
-                        speed2ListFuture,
-                        weight1ListFuture,
-                        weight2ListFuture,
-                        elemenListFuture
-                ).join();
-
-                // 5. 封装返回
-                try {
-                    List<IronTrendL1DTO> tempList = tempListFuture.get();
-                    List<IronTrendL1DTO> speed1List = speed1ListFuture.get();
-                    List<IronTrendL1DTO> speed2List = speed2ListFuture.get();
-                    List<IronTrendL1DTO> weight1List = weight1ListFuture.get();
-                    List<IronTrendL1DTO> weight2List = weight2ListFuture.get();
-                    List<IronTrendL2DTO> elemenList = elemenListFuture.get();
-
-                    // 1. 生成完整的每一分钟时间点
-                    java.util.List<String> xAxis = new java.util.ArrayList<>();
-                    java.util.Calendar cursor = java.util.Calendar.getInstance();
-                    cursor.setTime(startTime);
-                    while (!cursor.getTime().after(endTime)) {
-                        xAxis.add(sdfMinute.format(cursor.getTime()));
-                        cursor.add(java.util.Calendar.MINUTE, 1);
-                    }
+            Map<String, List<OPCData>> opcDataMap = opcDataFuture.get().stream()
+                    .collect(Collectors.groupingBy(OPCData::getPointName));
 
-                    // 查询区间前的最近一条历史数据(前置值)
-                    // OPC类
-                    OPCData preTemp = opcDataService.lambdaQuery()
-                            .eq(OPCData::getPointName, "BF4_1_IRONNOTCH_MIR_TEMP")
-                            .isNotNull(OPCData::getData)
-                            .lt(OPCData::getServerTime, startTime)
-                            .orderByDesc(OPCData::getServerTime)
-                            .last("limit 1").one();
-                    OPCData preSpeed1 = opcDataService.lambdaQuery()
-                            .eq(OPCData::getPointName, "BF4_1_IRONNOTCH_RAILLINE_ACPIRON_SPEED1")
-                            .isNotNull(OPCData::getData)
-                            .lt(OPCData::getServerTime, startTime)
-                            .orderByDesc(OPCData::getServerTime)
-                            .last("limit 1").one();
-                    OPCData preSpeed2 = opcDataService.lambdaQuery()
-                            .eq(OPCData::getPointName, "BF4_1_IRONNOTCH_RAILLINE_ACPIRON_SPEED2")
-                            .isNotNull(OPCData::getData)
-                            .lt(OPCData::getServerTime, startTime)
-                            .orderByDesc(OPCData::getServerTime)
-                            .last("limit 1").one();
-                    OPCData preWeight1 = opcDataService.lambdaQuery()
-                            .eq(OPCData::getPointName, "BF4_1TH_1_MIR_NWT")
-                            .isNotNull(OPCData::getData)
-                            .lt(OPCData::getServerTime, startTime)
-                            .orderByDesc(OPCData::getServerTime)
-                            .last("limit 1").one();
-                    OPCData preWeight2 = opcDataService.lambdaQuery()
-                            .eq(OPCData::getPointName, "BF4_1TH_2_MIR_NWT")
-                            .isNotNull(OPCData::getData)
-                            .lt(OPCData::getServerTime, startTime)
-                            .orderByDesc(OPCData::getServerTime)
-                            .last("limit 1").one();
-
-                    // tappingMap补齐每一分钟,前面无数据用前置值补齐
-                    // 先查区间前最近一条tapping
-                    Integer preTappingVal = 0;
-
-                    OPCData preTapping = opcDataService.lambdaQuery()
-                            .eq(OPCData::getPointName, "BF4_1_IRONNOTCH_TAPPING")
-                            .isNotNull(OPCData::getData)
-                            .lt(OPCData::getServerTime, startTime)
-                            .orderByDesc(OPCData::getServerTime)
-                            .last("limit 1").one();
-
-                    // L2类
-                    TL2Data preL2 = tl2DataService.lambdaQuery()
-                            .lt(TL2Data::getIronStarttime, new SimpleDateFormat("yyyyMMddHHmmss").format(startTime))
-                            .eq(TL2Data::getTapholeId, "1")
-                            .orderByDesc(TL2Data::getIronStarttime)
-                            .last("limit 1").one();
-
-                    // 2. 构建每分钟补全的二维数组
-                    java.util.Map<String, Object> result = new java.util.LinkedHashMap<>();
-                    result.put("ironTemp", buildMinuteArray(tempList, xAxis, preTemp != null ? preTemp.getData() : null));
-                    result.put("elementS", buildMinuteArray(elemenList, xAxis, "elementS", preL2 != null ? preL2.getElementS() : null));
-                    result.put("elementSi", buildMinuteArray(elemenList, xAxis, "elementSi", preL2 != null ? preL2.getElementSi() : null));
-                    result.put("mudWeight", buildMinuteArray(elemenList, xAxis, "mudWeight", preL2 != null ? preL2.getMudWeight() : null));
-                    result.put("pollMm", buildMinuteArray(elemenList, xAxis, "pollMm", preL2 != null ? preL2.getPollMm() : null));
-                    result.put("openDepth", buildMinuteArray(elemenList, xAxis, "openDepth", preL2 != null ? preL2.getOpenDepth() : null));
-
-
-                    //
-                    if (preTapping != null && preTapping.getData() != null) {
-                        Object v = preTapping.getData();
-                        if (v instanceof Number) preTappingVal = ((Number) v).intValue();
-                        else if (v instanceof String) {
-                            String str = ((String) v).trim();
-                            if (!str.isEmpty()) {
-                                try {
-                                    preTappingVal = Integer.parseInt(str);
-                                } catch (Exception ignore) {
-                                }
-                            }
+            List<TL2Data> l2DataList = l2DataFuture.get();
+
+            // 并行转换所有数据
+            //铁水温度
+            CompletableFuture<List<IronTrendL1DTO>> tempListFuture = CompletableFuture.supplyAsync(() ->
+                    opcDataMap.getOrDefault("BF4_1_IRONNOTCH_MIR_TEMP", new ArrayList<>())
+                            .stream().map(item -> {
+                                IronTrendL1DTO dto = new IronTrendL1DTO();
+                                dto.setData(item.getData());
+                                dto.setCreateTime(item.getSourceTime());
+                                return dto;
+                            }).collect(Collectors.toList())
+            );
+
+            //1TH-1号车受铁速度
+            CompletableFuture<List<IronTrendL1DTO>> speed1ListFuture = CompletableFuture.supplyAsync(() ->
+                    opcDataMap.getOrDefault("BF4_1_IRONNOTCH_RAILLINE_ACPIRON_SPEED1", new ArrayList<>())
+                            .stream().map(item -> {
+                                IronTrendL1DTO dto = new IronTrendL1DTO();
+                                dto.setData(item.getData());
+                                dto.setCreateTime(item.getSourceTime());
+                                return dto;
+                            }).collect(Collectors.toList())
+            );
+
+            //1TH-2号车受铁速度
+            CompletableFuture<List<IronTrendL1DTO>> speed2ListFuture = CompletableFuture.supplyAsync(() ->
+                    opcDataMap.getOrDefault("BF4_1_IRONNOTCH_RAILLINE_ACPIRON_SPEED2", new ArrayList<>())
+                            .stream().map(item -> {
+                                IronTrendL1DTO dto = new IronTrendL1DTO();
+                                dto.setData(item.getData());
+                                dto.setCreateTime(item.getSourceTime());
+                                return dto;
+                            }).collect(Collectors.toList())
+            );
+
+            //BF4_1TH_1_MIR_NWT 1号车净重
+            CompletableFuture<List<IronTrendL1DTO>> weight1ListFuture = CompletableFuture.supplyAsync(() ->
+                    opcDataMap.getOrDefault("BF4_1TH_1_MIR_NWT", new ArrayList<>())
+                            .stream().map(item -> {
+                                IronTrendL1DTO dto = new IronTrendL1DTO();
+                                dto.setData(item.getData());
+                                dto.setCreateTime(item.getSourceTime());
+                                return dto;
+                            }).collect(Collectors.toList())
+            );
+
+            //BF4_1TH_2_MIR_NWT 2号车净重
+            CompletableFuture<List<IronTrendL1DTO>> weight2ListFuture = CompletableFuture.supplyAsync(() ->
+                    opcDataMap.getOrDefault("BF4_1TH_2_MIR_NWT", new ArrayList<>())
+                            .stream().map(item -> {
+                                IronTrendL1DTO dto = new IronTrendL1DTO();
+                                dto.setData(item.getData());
+                                dto.setCreateTime(item.getSourceTime());
+                                return dto;
+                            }).collect(Collectors.toList())
+            );
+
+            //L2
+            CompletableFuture<List<IronTrendL2DTO>> elemenListFuture = CompletableFuture.supplyAsync(() ->
+                    l2DataList.stream().map(item -> {
+                        IronTrendL2DTO dto = new IronTrendL2DTO();
+                        try {
+                            dto.setElementS(item.getElementS() != null ? Double.parseDouble(item.getElementS()) : null);
+                        } catch (NumberFormatException e) {
+                            dto.setElementS(null);
                         }
-                    }
-                    // 构建每分钟tappingMap
-                    Map<String, Integer> tappingMap = new LinkedHashMap<>();
-                    List<OPCData> tappingList = opcDataMap.getOrDefault("BF4_1_IRONNOTCH_TAPPING", new ArrayList<>());
-                    Map<String, Integer> rawTappingMap = new LinkedHashMap<>();
-                    for (OPCData item : tappingList) {
-                        if (item.getServerTime() != null && item.getData() != null) {
-                            String min = sdfMinute.format(item.getServerTime());
-                            Integer val = null;
-                            Object v = item.getData();
-                            if (v instanceof Number) val = ((Number) v).intValue();
-                            else if (v instanceof String) {
-                                String str = ((String) v).trim();
-                                if (!str.isEmpty()) {
-                                    try {
-                                        val = Integer.parseInt(str);
-                                    } catch (Exception ignore) {
-                                    }
-                                }
-                            }
-                            if (val != null) rawTappingMap.put(min, val);
+                        try {
+                            dto.setElementSi(item.getElementSi() != null ? Double.parseDouble(item.getElementSi()) : null);
+                        } catch (NumberFormatException e) {
+                            dto.setElementSi(null);
                         }
-                    }
-                    Integer last = preTappingVal;
-                    for (String t : xAxis) {
-                        Integer v = rawTappingMap.getOrDefault(t, last);
-                        tappingMap.put(t, v);
-                        if (v != null) last = v;
-                    }
+                        dto.setIronStarttime(item.getIronStarttime());
+                        dto.setIronEndtime(item.getIronEndtime());
+                        dto.setPollMm(item.getPollMm());
+                        dto.setOpenDepth(item.getOpenDepth());
+                        dto.setMudWeight(item.getMudWeight());
+                        dto.setIronCosttime(item.getIronCosttime());
+                        return dto;
+                    }).collect(Collectors.toList())
+            );
 
+            // 等待所有转换完成
+            CompletableFuture.allOf(
+                    tempListFuture,
+                    speed1ListFuture,
+                    speed2ListFuture,
+                    weight1ListFuture,
+                    weight2ListFuture,
+                    elemenListFuture
+            ).join();
 
-                    int ironWeightScale = 2; // 可调整为0、1、2等
-                    List<List<Object>> ironFlowArr = buildIronWeightMinuteArray(xAxis, tappingMap, weight1List, weight2List, ironWeightScale);
-                    result.put("ironWeight", ironFlowArr);
+            // 5. 封装返回
+            List<IronTrendL1DTO> tempList = tempListFuture.get();
+            List<IronTrendL1DTO> speed1List = speed1ListFuture.get();
+            List<IronTrendL1DTO> speed2List = speed2ListFuture.get();
+            List<IronTrendL1DTO> weight1List = weight1ListFuture.get();
+            List<IronTrendL1DTO> weight2List = weight2ListFuture.get();
+            List<IronTrendL2DTO> elemenList = elemenListFuture.get();
+
+            // 1. 生成完整的每一分钟时间点
+            java.util.List<String> xAxis = new java.util.ArrayList<>();
+            java.util.Calendar cursor = java.util.Calendar.getInstance();
+            cursor.setTime(startTime);
+            while (!cursor.getTime().after(endTime)) {
+                xAxis.add(sdfMinute.format(cursor.getTime()));
+                cursor.add(java.util.Calendar.MINUTE, 1);
+            }
 
-                    // 处理铁水流速,出铁中按原逻辑,出铁结束后为0
-                    List<List<Object>> ironSpeedArr = buildMinuteArrayForSpeed(xAxis, speed1List, speed2List, preSpeed1 != null ? preSpeed1.getData() : null, preSpeed2 != null ? preSpeed2.getData() : null);
-                    for (int i = 0; i < xAxis.size(); i++) {
-                        String t = xAxis.get(i);
-                        Integer tapping = tappingMap.getOrDefault(t, 0);
-                        if (tapping == 0 && ironSpeedArr.get(i).size() > 1) {
-                            ironSpeedArr.get(i).set(1, 0);
+            // 查询区间前的最近一条历史数据(前置值)
+            // OPC类
+            OPCData preTemp = opcDataService.lambdaQuery()
+                    .eq(OPCData::getPointName, "BF4_1_IRONNOTCH_MIR_TEMP")
+                    .isNotNull(OPCData::getData)
+                    .lt(OPCData::getServerTime, startTime)
+                    .orderByDesc(OPCData::getServerTime)
+                    .last("limit 1").one();
+            OPCData preSpeed1 = opcDataService.lambdaQuery()
+                    .eq(OPCData::getPointName, "BF4_1_IRONNOTCH_RAILLINE_ACPIRON_SPEED1")
+                    .isNotNull(OPCData::getData)
+                    .lt(OPCData::getServerTime, startTime)
+                    .orderByDesc(OPCData::getServerTime)
+                    .last("limit 1").one();
+            OPCData preSpeed2 = opcDataService.lambdaQuery()
+                    .eq(OPCData::getPointName, "BF4_1_IRONNOTCH_RAILLINE_ACPIRON_SPEED2")
+                    .isNotNull(OPCData::getData)
+                    .lt(OPCData::getServerTime, startTime)
+                    .orderByDesc(OPCData::getServerTime)
+                    .last("limit 1").one();
+            OPCData preWeight1 = opcDataService.lambdaQuery()
+                    .eq(OPCData::getPointName, "BF4_1TH_1_MIR_NWT")
+                    .isNotNull(OPCData::getData)
+                    .lt(OPCData::getServerTime, startTime)
+                    .orderByDesc(OPCData::getServerTime)
+                    .last("limit 1").one();
+            OPCData preWeight2 = opcDataService.lambdaQuery()
+                    .eq(OPCData::getPointName, "BF4_1TH_2_MIR_NWT")
+                    .isNotNull(OPCData::getData)
+                    .lt(OPCData::getServerTime, startTime)
+                    .orderByDesc(OPCData::getServerTime)
+                    .last("limit 1").one();
+
+            // tappingMap补齐每一分钟,前面无数据用前置值补齐
+            // 先查区间前最近一条tapping
+            Integer preTappingVal = 0;
+
+            OPCData preTapping = opcDataService.lambdaQuery()
+                    .eq(OPCData::getPointName, "BF4_1_IRONNOTCH_TAPPING")
+                    .isNotNull(OPCData::getData)
+                    .lt(OPCData::getServerTime, startTime)
+                    .orderByDesc(OPCData::getServerTime)
+                    .last("limit 1").one();
+
+            // L2类
+            TL2Data preL2 = tl2DataService.lambdaQuery()
+                    .lt(TL2Data::getIronStarttime, new SimpleDateFormat("yyyyMMddHHmmss").format(startTime))
+                    .eq(TL2Data::getTapholeId, "1")
+                    .orderByDesc(TL2Data::getIronStarttime)
+                    .last("limit 1").one();
+
+            // 2. 构建每分钟补全的二维数组
+            java.util.Map<String, Object> result = new java.util.LinkedHashMap<>();
+
+
+            //
+            if (preTapping != null && preTapping.getData() != null) {
+                Object v = preTapping.getData();
+                if (v instanceof Number) preTappingVal = ((Number) v).intValue();
+                else if (v instanceof String) {
+                    String str = ((String) v).trim();
+                    if (!str.isEmpty()) {
+                        try {
+                            preTappingVal = Integer.parseInt(str);
+                        } catch (Exception ignore) {
                         }
                     }
-                    result.put("ironSpeed", ironSpeedArr);
-
-
-                    // 处理L2类数据,tapping=0时设为0
-                    List<List<Object>> elementSArr = buildMinuteArray(elemenList, xAxis, "elementS", preL2 != null ? preL2.getElementS() : null);
-                    List<List<Object>> elementSiArr = buildMinuteArray(elemenList, xAxis, "elementSi", preL2 != null ? preL2.getElementSi() : null);
-                    List<List<Object>> mudWeightArr = buildMinuteArray(elemenList, xAxis, "mudWeight", preL2 != null ? preL2.getMudWeight() : null);
-                    List<List<Object>> pollMmArr = buildMinuteArray(elemenList, xAxis, "pollMm", preL2 != null ? preL2.getPollMm() : null);
-                    List<List<Object>> openDepthArr = buildMinuteArray(elemenList, xAxis, "openDepth", preL2 != null ? preL2.getOpenDepth() : null);
-                    List<List<Object>> ironCosttimeArr = buildMinuteArray(elemenList, xAxis, "ironCosttime", preL2 != null ? preL2.getIronCosttime() : null);
-                    for (int i = 0; i < xAxis.size(); i++) {
-                        String t = xAxis.get(i);
-                        Integer tapping = tappingMap.getOrDefault(t, 0);
-                        if (tapping == 0) {
-                            if (elementSArr.get(i).size() > 1) elementSArr.get(i).set(1, 0);
-                            if (elementSiArr.get(i).size() > 1) elementSiArr.get(i).set(1, 0);
-                            if (mudWeightArr.get(i).size() > 1) mudWeightArr.get(i).set(1, 0);
-                            if (pollMmArr.get(i).size() > 1) pollMmArr.get(i).set(1, 0);
-                            if (openDepthArr.get(i).size() > 1) openDepthArr.get(i).set(1, 0);
-                            if (ironCosttimeArr.get(i).size() > 1) ironCosttimeArr.get(i).set(1, 0);
+                }
+            }
+            // 构建每分钟tappingMap
+            Map<String, Integer> tappingMap = new LinkedHashMap<>();
+            List<OPCData> tappingList = opcDataMap.getOrDefault("BF4_1_IRONNOTCH_TAPPING", new ArrayList<>());
+            Map<String, Integer> rawTappingMap = new LinkedHashMap<>();
+            for (OPCData item : tappingList) {
+                if (item.getServerTime() != null && item.getData() != null) {
+                    String min = sdfMinute.format(item.getServerTime());
+                    Integer val = null;
+                    Object v = item.getData();
+                    if (v instanceof Number) val = ((Number) v).intValue();
+                    else if (v instanceof String) {
+                        String str = ((String) v).trim();
+                        if (!str.isEmpty()) {
+                            try {
+                                val = Integer.parseInt(str);
+                            } catch (Exception ignore) {
+                            }
                         }
                     }
-                    result.put("elementS", elementSArr);
-                    result.put("elementSi", elementSiArr);
-                    result.put("mudWeight", mudWeightArr);
-                    result.put("pollMm", pollMmArr);
-                    result.put("openDepth", openDepthArr);
-                    result.put("ironCosttime", ironCosttimeArr);
-
-                    return result;
-                } catch (InterruptedException | ExecutionException e) {
-                    e.printStackTrace();
-                    throw new OperateException("获取或转换趋势数据异常: " + e.getMessage());
+                    if (val != null) rawTappingMap.put(min, val);
                 }
+            }
+            Integer last = preTappingVal;
+            for (String t : xAxis) {
+                Integer v = rawTappingMap.getOrDefault(t, last);
+                tappingMap.put(t, v);
+                if (v != null) last = v;
+            }
+
 
-            } catch (InterruptedException | ExecutionException e) {
-                e.printStackTrace();
-                throw new OperateException("获取或转换趋势数据异常: " + e.getMessage());
+            int ironWeightScale = 2; // 可调整为0、1、2等
+            List<List<Object>> ironFlowArr = buildIronWeightMinuteArray(xAxis, tappingMap, weight1List, weight2List, ironWeightScale);
+            result.put("ironWeight", ironFlowArr);
+
+            // 处理铁水流速,出铁中按原逻辑,出铁结束后为0
+            List<List<Object>> ironSpeedArr = buildMinuteArrayForSpeed(xAxis, speed1List, speed2List, preSpeed1 != null ? preSpeed1.getData() : null, preSpeed2 != null ? preSpeed2.getData() : null);
+            List<List<Object>> ironTempArr = buildMinuteArray(tempList, xAxis, preTemp != null ? preTemp.getData() : null);
+
+            for (int i = 0; i < xAxis.size(); i++) {
+                String t = xAxis.get(i);
+                Integer tapping = tappingMap.getOrDefault(t, 0);
+                if (tapping == 0 && ironSpeedArr.get(i).size() > 1) {
+                    ironSpeedArr.get(i).set(1, 0);
+                    ironTempArr.get(i).set(1, 0);
+                }
             }
+            result.put("ironSpeed", ironSpeedArr);
+            result.put("ironTemp", ironTempArr);
+
+
+            // 处理L2类数据,tapping=0时设为0
+            List<List<Object>> elementSArr = buildL2MinuteArray(elemenList, xAxis, "elementS", preL2 != null ? preL2.getElementS() : null);
+            List<List<Object>> elementSiArr = buildL2MinuteArray(elemenList, xAxis, "elementSi", preL2 != null ? preL2.getElementSi() : null);
+            List<List<Object>> mudWeightArr = buildL2MinuteArray(elemenList, xAxis, "mudWeight", preL2 != null ? preL2.getMudWeight() : null);
+            List<List<Object>> pollMmArr = buildL2MinuteArray(elemenList, xAxis, "pollMm", preL2 != null ? preL2.getPollMm() : null);
+            List<List<Object>> openDepthArr = buildL2MinuteArray(elemenList, xAxis, "openDepth", preL2 != null ? preL2.getOpenDepth() : null);
+            List<List<Object>> ironCosttimeArr = buildL2MinuteArray(elemenList, xAxis, "ironCosttime", preL2 != null ? preL2.getIronCosttime() : null);
+            for (int i = 0; i < xAxis.size(); i++) {
+                String t = xAxis.get(i);
+                Integer tapping = tappingMap.getOrDefault(t, 0);
+                if (tapping == 0) {
+                    if (elementSArr.get(i).size() > 1) elementSArr.get(i).set(1, 0);
+                    if (elementSiArr.get(i).size() > 1) elementSiArr.get(i).set(1, 0);
+                    if (mudWeightArr.get(i).size() > 1) mudWeightArr.get(i).set(1, 0);
+                    if (pollMmArr.get(i).size() > 1) pollMmArr.get(i).set(1, 0);
+                    if (openDepthArr.get(i).size() > 1) openDepthArr.get(i).set(1, 0);
+                    if (ironCosttimeArr.get(i).size() > 1) ironCosttimeArr.get(i).set(1, 0);
+                }
+            }
+            result.put("elementS", elementSArr);
+            result.put("elementSi", elementSiArr);
+            result.put("mudWeight", mudWeightArr);
+            result.put("pollMm", pollMmArr);
+            result.put("openDepth", openDepthArr);
+            result.put("ironCosttime", ironCosttimeArr);
+
+            return result;
+
         } catch (Exception e) {
             e.printStackTrace();
-            throw new OperateException("获取趋势数据异常: " + e.getMessage());
         }
+        return null;
     }
 
-
     // 新增工具方法:L1类型
     private java.util.List<java.util.List<Object>> buildMinuteArray(java.util.List<IronTrendL1DTO> list, java.util.List<String> xAxis, Object preValue) {
         java.util.Map<String, Object> timeValueMap = new java.util.LinkedHashMap<>();
@@ -659,7 +668,6 @@ public class TIronVisualScreenServiceImpl {
         return arr;
     }
 
-
     // 铁水流速
     private java.util.List<java.util.List<Object>> buildMinuteArrayForSpeed(java.util.List<String> xAxis, java.util.List<IronTrendL1DTO> speed1List, java.util.List<IronTrendL1DTO> speed2List, Object pre1, Object pre2) {
         java.util.Map<String, Double> speed1Map = new java.util.LinkedHashMap<>();
@@ -735,13 +743,11 @@ public class TIronVisualScreenServiceImpl {
             arr.add(java.util.Arrays.asList(t, sum));
             if (sum != null) last = sum;
         }
-
-
         return arr;
     }
 
-    // L2类型,增加preValue参数
-    private java.util.List<java.util.List<Object>> buildMinuteArray(java.util.List<IronTrendL2DTO> list, java.util.List<String> xAxis, String field, Object preValue) {
+    //L2
+    private java.util.List<java.util.List<Object>> buildL2MinuteArray(java.util.List<IronTrendL2DTO> list, java.util.List<String> xAxis, String field, Object preValue) {
         java.util.Map<String, Object> timeValueMap = new java.util.LinkedHashMap<>();
         for (IronTrendL2DTO e : list) {
             String min = e.getIronStarttime();
@@ -781,7 +787,7 @@ public class TIronVisualScreenServiceImpl {
     }
 
 
-    //
+    //铁水重量
     private List<List<Object>> buildIronWeightMinuteArray(List<String> xAxis, Map<String, Integer> tappingMap, List<IronTrendL1DTO> weight1List, List<IronTrendL1DTO> weight2List, int scale) {
         Map<String, Double> weight1Map = new LinkedHashMap<>();
         for (IronTrendL1DTO e : weight1List) {
@@ -849,11 +855,11 @@ public class TIronVisualScreenServiceImpl {
             if (tapping == 1) {
                 if (!inTappingCycle) {
                     inTappingCycle = true;
-                    System.out.println("[出铁周期结束] 开始于: " + time);
+                    //System.out.println("[出铁周期结束] 开始于: " + time);
                 }
                 if (w.compareTo(java.math.BigDecimal.ZERO) == 0) {
                     w = lastW;
-                    weightMap.put(time,w.doubleValue());
+                    weightMap.put(time, w.doubleValue());
                 } else {
                     lastW = w;
                 }
@@ -861,7 +867,7 @@ public class TIronVisualScreenServiceImpl {
                     java.math.BigDecimal prevW = new java.math.BigDecimal(weightMap.getOrDefault(xAxis.get(i - 1), 0d).toString());
                     //上一个减去当前的
                     if (prevW.subtract(w).compareTo(new java.math.BigDecimal("130")) > 0) {
-                        System.out.println("[出铁周期满载情况] 时间: " + xAxis.get(i - 1) + ", 铁水满载值: " + prevW);
+                        //System.out.println("[出铁周期满载情况] 时间: " + xAxis.get(i - 1) + ", 铁水满载值: " + prevW);
                         cycleTotal = cycleTotal.add(prevW);
                     }
                 }
@@ -869,13 +875,13 @@ public class TIronVisualScreenServiceImpl {
             } else {
                 if (inTappingCycle) {
                     double value = cycleTotal.setScale(scale, java.math.RoundingMode.HALF_UP).doubleValue();
-                    System.out.println("[出铁周期结束] 结束于: " + time + ", 本周期铁水总净重: " + value);
+                    //System.out.println("[出铁周期结束] 结束于: " + time + ", 本周期铁水总净重: " + value);
                     arr.add(java.util.Arrays.asList(time, value));
                     inTappingCycle = false;
                     cycleTotal = java.math.BigDecimal.ZERO;
-                    for (List<Object> objects : arr) {
-                        System.out.println(objects.get(0)+" >>> "+objects.get(1));
-                    }
+//                    for (List<Object> objects : arr) {
+//                        System.out.println(objects.get(0)+" >>> "+objects.get(1));
+//                    }
                 } else {
                     arr.add(java.util.Arrays.asList(time, 0));
                 }

+ 15 - 11
taphole-iron/src/main/java/com/sckj/iron/socketio/DeviceEventListener.java

@@ -325,13 +325,13 @@ public class DeviceEventListener extends AbstractEventListener { //
         List<TAudio> list = audioService.lambdaQuery().eq(TAudio::getStatus, "1").eq(TAudio::getDelFlag, "1").list();
         if (ObjectUtils.isNotEmpty(list)) {
             for (TAudio tAudio : list) {
-                if (Objects.equals(tAudio.getExceptionType(), "100")) {
+                if (ExceptionTypeEnum.JI_XU_DU_KOU.equals(ExceptionTypeEnum.fromCode(tAudio.getExceptionType()))) {
                     closureAlarmUrl = SERVER_URL + "/" + GlobalConfig.publicPrefix + File.separator + tAudio.getPath();
-                } else if (Objects.equals(tAudio.getExceptionType(), "200")) {
+                } else  if (ExceptionTypeEnum.JI_XU_CHU_TIE.equals(ExceptionTypeEnum.fromCode(tAudio.getExceptionType()))) {
                     tappingAlramUrl = SERVER_URL + "/" + GlobalConfig.publicPrefix + File.separator + tAudio.getPath();
-                } else if (Objects.equals(tAudio.getExceptionType(), "300")) {
+                } else  if (ExceptionTypeEnum.CHU_TIE_SHI_JIAN_TAI_CHANG.equals(ExceptionTypeEnum.fromCode(tAudio.getExceptionType()))) {
                     tappingTimeoutAlramUrl = SERVER_URL + "/" + GlobalConfig.publicPrefix + File.separator + tAudio.getPath();
-                } else if (Objects.equals(tAudio.getExceptionType(), "300")) {
+                } else  if (ExceptionTypeEnum.KAI_KOU_CHAO_SHI.equals(ExceptionTypeEnum.fromCode(tAudio.getExceptionType()))) {
                     openAlarmUrl = SERVER_URL + "/" + GlobalConfig.publicPrefix + File.separator + tAudio.getPath();
                 }
             }
@@ -1161,7 +1161,7 @@ public class DeviceEventListener extends AbstractEventListener { //
                     ironWeight12Max = BigDecimal.ZERO;
                     ironWeight12Current = BigDecimal.ZERO;
                 }
-            } else if (opcData.getPointName().contains(SubscribeTagConstants.TAG_CHUZ_STATUS(opcData.getServerType()))) {
+            } else if (opcData.getPointName().contains(SubscribeTagConstants.TAG_NSZSW(opcData.getServerType()))) {
                 double temp = Double.parseDouble(opcData.getData().toString());
                 if (lastChuzTemps.size() >= 3) {
                     lastChuzTemps.removeFirst();
@@ -1187,12 +1187,16 @@ public class DeviceEventListener extends AbstractEventListener { //
             } else if (opcData.getPointName().contains(SubscribeTagConstants.TAG_SZB_STATUS(opcData.getServerType()))
                     || opcData.getPointName().contains(SubscribeTagConstants.TAG_CZF_STATUS(opcData.getServerType()))
             ) {
-                RealtimeData realtimeData = new RealtimeData();
-                Boolean value = mParser.parseExpression("#subszb41 > 0 and #subczf41 > 0").getValue(mContext, Boolean.class);
-                realtimeData.setValue(Boolean.TRUE.equals(value) ? 1 : 0);
-                realtimeData.setDesc("冲渣状态");
-                realtimeData.setExtra(opcData.getData());
-                mRealtimeStatus.put(CHONGZ_STATUS, realtimeData);
+                try {
+                    RealtimeData realtimeData = new RealtimeData();
+                    Boolean value = mParser.parseExpression("#subszb41 > 0 and #subczf41 > 0").getValue(mContext, Boolean.class);
+                    realtimeData.setValue(Boolean.TRUE.equals(value) ? 1 : 0);
+                    realtimeData.setDesc("冲渣状态");
+                    realtimeData.setExtra(opcData.getData());
+                    mRealtimeStatus.put(CHONGZ_STATUS, realtimeData);
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
             } else if (opcData.getPointName().contains(SubscribeTagConstants.TAG_KKJ_STATUS(opcData.getServerType()))) {
                 //开口机状态
                 RealtimeData realtimeData = new RealtimeData();