From 76cd5948e95ddbde9dd4411b466ee75ba20b562e Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期四, 03 九月 2026 17:28:29 +0800
Subject: [PATCH] 实现测试预警异常管理

---
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTestLiveServiceImpl.java |   37 +++++++++++++++++++++++--------------
 1 files changed, 23 insertions(+), 14 deletions(-)

diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTestLiveServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTestLiveServiceImpl.java
index 7ae32ac..1869330 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTestLiveServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTestLiveServiceImpl.java
@@ -11,10 +11,9 @@
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 import jakarta.annotation.PreDestroy;
 import org.springframework.stereotype.Service;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
 import com.ruoyi.device.bts.BtsDevelopmentSimulator;
 import com.ruoyi.device.bts.BtsDevelopmentSimulator.CollectorSnapshot;
@@ -28,6 +27,7 @@
 import com.ruoyi.system.service.ITestLiveService.TestPlanRow;
 import com.ruoyi.system.service.ITestLiveService.TestPlanSnapshot;
 import com.ruoyi.system.service.ITTestService;
+import com.ruoyi.system.mapper.TTestMapper;
 
 /** 将设备最新快照转换为测试视角,并托管 SSE 连接生命周期。 */
 @Service
@@ -36,12 +36,17 @@
     private final ITTestService tests;
     private final DeviceDiscoveryCandidateStore candidates;
     private final BtsDevelopmentSimulator simulator;
+    private final TTestMapper mapper;
     private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
-    private final ConcurrentMap<String, LiveSource> lastSources = new ConcurrentHashMap<>();
+
+    @Autowired
+    public TTestLiveServiceImpl(ITTestService tests, DeviceDiscoveryCandidateStore candidates,
+            BtsDevelopmentSimulator simulator, TTestMapper mapper)
+    { this.tests = tests; this.candidates = candidates; this.simulator = simulator; this.mapper = mapper; }
 
     public TTestLiveServiceImpl(ITTestService tests, DeviceDiscoveryCandidateStore candidates,
             BtsDevelopmentSimulator simulator)
-    { this.tests = tests; this.candidates = candidates; this.simulator = simulator; }
+    { this(tests, candidates, simulator, null); }
 
     @Override public LiveState current(Long testId)
     {
@@ -49,14 +54,12 @@
         List<CabinetCandidate> cabinets = candidates.snapshot(Instant.now()).cabinets();
         List<LiveSource> sources = new ArrayList<>();
         boolean receiving = "RECEIVING".equals(test.getReceptionStatus());
-        boolean freezeSnapshots = "PAUSED".equals(test.getReceptionStatus())
-                || "ENDED".equals(test.getReceptionStatus());
         for (TTestBattery battery : test.getBatteries() == null ? List.<TTestBattery>of() : test.getBatteries())
         {
             if (battery.getBinding() != null)
-                sources.add(snapshotFor(testId, cabinetSource(battery, cabinets), receiving, freezeSnapshots));
+                sources.add(snapshotFor(cabinetSource(battery, cabinets), receiving));
             if (battery.getCollectorId() != null)
-                sources.add(snapshotFor(testId, collectorSource(battery), receiving, freezeSnapshots));
+                sources.add(snapshotFor(collectorSource(battery), receiving));
         }
         List<Map<String, Object>> exceptions = new ArrayList<>();
         exceptions.addAll(sources.stream().filter(source -> !"COLLECTOR".equals(source.sourceType())
@@ -65,6 +68,12 @@
                 .map(source -> Map.<String, Object>of("sourceType", source.sourceType(), "sourceId", source.sourceId(),
                         "batteryNo", source.batteryNo(), "status", source.deviceStatus(), "message", "数据来源当前不可观测"))
                 .toList());
+        if (mapper != null) {
+            mapper.selectWarningExceptions(testId, "OPEN").forEach(item -> exceptions.add(Map.of(
+                    "exceptionId", item.getExceptionId(), "sourceType", item.getSourceType(),
+                    "metricCode", item.getMetricCode(), "value", item.getAbnormalValue(), "unit", item.getUnit(),
+                    "status", item.getExceptionStatus(), "message", "测试预警异常")));
+        }
         String testStatus = test.getTestStatus();
         TestPlanSnapshot testPlan = detectorTestPlan(test);
         return new LiveState(testId, testStatus, test.getReceptionStatus(), Instant.now(), sources, exceptions, testPlan);
@@ -94,12 +103,11 @@
         return null;
     }
 
-    private LiveSource snapshotFor(Long testId, LiveSource fresh, boolean receiving, boolean freeze)
+    private LiveSource snapshotFor(LiveSource fresh, boolean receiving)
     {
-        String key = testId + ":" + fresh.sourceType() + ":" + fresh.sourceId() + ":" + fresh.batteryNo();
+        // 暂停或停止只停止数据请求;设备状态仍以本次查询的最新事实为准,采集快照不继续展示。
         if (!receiving)
-            return freeze ? lastSources.getOrDefault(key, withoutSnapshot(fresh)) : withoutSnapshot(fresh);
-        lastSources.put(key, fresh);
+            return withoutSnapshot(fresh);
         return fresh;
     }
 
@@ -160,7 +168,8 @@
                     && Objects.equals(channel.identity().subdevid(), binding.getSubdevid())
                     && Objects.equals(channel.identity().chlid(), binding.getChlid()))
                 return new LiveSource("CABINET_CHANNEL", binding.getChannelId(), battery.getBatteryNo(),
-                        channel.online() ? channel.workStatus().name() : "OFFLINE", snapshot(channel));
+                        channel.online() ? channel.workStatus().name() : "OFFLINE",
+                        channel.online() ? snapshot(channel) : Map.of());
         return new LiveSource("CABINET_CHANNEL", binding.getChannelId(), battery.getBatteryNo(), "UNKNOWN", Map.of());
     }
 
@@ -205,7 +214,7 @@
             collector.latestMeasurements().stream().map(item -> item.serverReceivedAt()).max(Instant::compareTo)
                     .ifPresent(observedAt -> value.put("observedAt", observedAt));
             return new LiveSource("COLLECTOR", (long) collector.collectorId(), battery.getBatteryNo(),
-                    collector.online() ? "ONLINE" : "OFFLINE", value);
+                    collector.online() ? "ONLINE" : "OFFLINE", collector.online() ? value : Map.of());
         }
         return new LiveSource("COLLECTOR", battery.getCollectorId(), battery.getBatteryNo(), "UNKNOWN", Map.of());
     }

--
Gitblit v1.7.1