From 2e7dbd705fc82e8db74b073e55af938d67d8c19f Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期二, 17 三月 2026 09:05:49 +0800
Subject: [PATCH] #

---
 src/main/java/com/zy/system/controller/DashboardController.java |  169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 169 insertions(+), 0 deletions(-)

diff --git a/src/main/java/com/zy/system/controller/DashboardController.java b/src/main/java/com/zy/system/controller/DashboardController.java
index fa97e4d..de5cdc9 100644
--- a/src/main/java/com/zy/system/controller/DashboardController.java
+++ b/src/main/java/com/zy/system/controller/DashboardController.java
@@ -25,6 +25,7 @@
 import com.zy.core.thread.StationThread;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
@@ -59,12 +60,24 @@
     private LlmCallLogService llmCallLogService;
     @Autowired
     private AiChatSessionMapper aiChatSessionMapper;
+    @Autowired
+    private DevicePingFileStorageService devicePingFileStorageService;
+
+    @Value("${devicePingStorage.intervalMs:1000}")
+    private int devicePingIntervalMs;
+    @Value("${devicePingStorage.timeoutMs:800}")
+    private int devicePingTimeoutMs;
+    @Value("${devicePingStorage.probeCount:3}")
+    private int devicePingProbeCount;
+    @Value("${devicePingStorage.packetSize:-1}")
+    private int devicePingPacketSize;
 
     @GetMapping("/summary/auth")
     @ManagerAuth(memo = "绯荤粺浠〃鐩樼粺璁�")
     public R summary() {
         Map<String, Object> tasks = buildTaskStats();
         Map<String, Object> devices = buildDeviceStats();
+        Map<String, Object> network = buildNetworkStats();
         Map<String, Object> ai = buildAiStats();
 
         Map<String, Object> overview = new LinkedHashMap<>();
@@ -82,6 +95,7 @@
         result.put("overview", overview);
         result.put("tasks", tasks);
         result.put("devices", devices);
+        result.put("network", network);
         result.put("ai", ai);
         return R.ok(result);
     }
@@ -424,6 +438,74 @@
         return result;
     }
 
+    @SuppressWarnings("unchecked")
+    private Map<String, Object> buildNetworkStats() {
+        Map<String, Object> result = new LinkedHashMap<>();
+        Map<String, Object> overview = new LinkedHashMap<>();
+        overview.put("totalDevices", 0L);
+        overview.put("okDevices", 0L);
+        overview.put("unstableDevices", 0L);
+        overview.put("offlineDevices", 0L);
+        overview.put("noDataDevices", 0L);
+        overview.put("attentionDevices", 0L);
+        overview.put("avgLatencyMs", null);
+        overview.put("maxLatencyMs", null);
+
+        Map<String, Object> samplingConfig = new LinkedHashMap<>();
+        samplingConfig.put("intervalMs", devicePingIntervalMs);
+        samplingConfig.put("timeoutMs", devicePingTimeoutMs);
+        samplingConfig.put("probeCount", devicePingProbeCount);
+        samplingConfig.put("packetSize", Math.max(devicePingPacketSize, -1));
+
+        List<Map<String, Object>> statusStats = new ArrayList<>();
+        statusStats.add(metric("姝e父", 0L));
+        statusStats.add(metric("娉㈠姩", 0L));
+        statusStats.add(metric("瓒呮椂/寮傚父", 0L));
+        statusStats.add(metric("鏆傛棤鏁版嵁", 0L));
+
+        List<Map<String, Object>> focusDevices = new ArrayList<>();
+
+        try {
+            Map<String, Object> overviewResult = devicePingFileStorageService.queryOverview(listPingConfigs());
+            Map<String, Object> summary = overviewResult.get("summary") instanceof Map
+                    ? (Map<String, Object>) overviewResult.get("summary")
+                    : Collections.emptyMap();
+            List<Map<String, Object>> devices = overviewResult.get("devices") instanceof List
+                    ? (List<Map<String, Object>>) overviewResult.get("devices")
+                    : Collections.emptyList();
+
+            long okDevices = toLong(summary.get("okDevices"));
+            long unstableDevices = toLong(summary.get("unstableDevices"));
+            long offlineDevices = toLong(summary.get("offlineDevices"));
+            long noDataDevices = toLong(summary.get("noDataDevices"));
+
+            overview.put("totalDevices", toLong(summary.get("totalDevices")));
+            overview.put("okDevices", okDevices);
+            overview.put("unstableDevices", unstableDevices);
+            overview.put("offlineDevices", offlineDevices);
+            overview.put("noDataDevices", noDataDevices);
+            overview.put("attentionDevices", unstableDevices + offlineDevices + noDataDevices);
+            overview.put("avgLatencyMs", summary.get("avgLatencyMs"));
+            overview.put("maxLatencyMs", summary.get("maxLatencyMs"));
+
+            statusStats = new ArrayList<>();
+            statusStats.add(metric("姝e父", okDevices));
+            statusStats.add(metric("娉㈠姩", unstableDevices));
+            statusStats.add(metric("瓒呮椂/寮傚父", offlineDevices));
+            statusStats.add(metric("鏆傛棤鏁版嵁", noDataDevices));
+
+            focusDevices = buildNetworkFocusDevices(devices);
+        } catch (Exception e) {
+            log.warn("dashboard network stats load failed: {}", safeMessage(e));
+        }
+
+        result.put("overview", overview);
+        result.put("samplingConfig", samplingConfig);
+        result.put("statusStats", statusStats);
+        result.put("focusDevices", focusDevices);
+        return result;
+    }
+
     private List<DeviceConfig> listDeviceConfig(SlaveType type) {
         try {
             return deviceConfigService.list(new QueryWrapper<DeviceConfig>()
@@ -434,6 +516,93 @@
         }
     }
 
+    private List<DeviceConfig> listPingConfigs() {
+        try {
+            return deviceConfigService.list(new QueryWrapper<DeviceConfig>()
+                    .isNotNull("ip")
+                    .ne("ip", "")
+                    .orderBy(true, true, "device_type", "device_no"));
+        } catch (Exception e) {
+            log.warn("dashboard ping device config load failed: {}", safeMessage(e));
+            return Collections.emptyList();
+        }
+    }
+
+    private List<Map<String, Object>> buildNetworkFocusDevices(List<Map<String, Object>> devices) {
+        if (devices == null || devices.isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        List<Map<String, Object>> candidates = new ArrayList<>();
+        for (Map<String, Object> row : devices) {
+            if (resolveNetworkFocusRank(row) < 3) {
+                candidates.add(row);
+            }
+        }
+        if (candidates.isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        candidates.sort((left, right) -> {
+            int rankDiff = Integer.compare(resolveNetworkFocusRank(left), resolveNetworkFocusRank(right));
+            if (rankDiff != 0) {
+                return rankDiff;
+            }
+            int latencyDiff = Long.compare(toLong(right.get("avgLatencyMs")), toLong(left.get("avgLatencyMs")));
+            if (latencyDiff != 0) {
+                return latencyDiff;
+            }
+            return Long.compare(toLong(right.get("latestTime")), toLong(left.get("latestTime")));
+        });
+
+        List<Map<String, Object>> result = new ArrayList<>();
+        for (Map<String, Object> item : candidates) {
+            if (item == null) {
+                continue;
+            }
+            Map<String, Object> focus = new LinkedHashMap<>();
+            focus.put("name", toText(item.get("deviceType")) + "-" + toText(item.get("deviceNo")));
+            focus.put("ip", toText(item.get("ip")));
+            focus.put("statusText", defaultText(toText(item.get("statusText")), "鏈煡"));
+            focus.put("statusType", resolveNetworkStatusTagType(toText(item.get("status"))));
+            focus.put("avgLatencyMs", item.get("avgLatencyMs"));
+            focus.put("latestTimeLabel", defaultText(toText(item.get("latestTimeLabel")), "--"));
+            focus.put("message", defaultText(toText(item.get("message")), "鏆傛棤棰濆璇存槑"));
+            result.add(focus);
+            if (result.size() >= 4) {
+                break;
+            }
+        }
+        return result;
+    }
+
+    private int resolveNetworkFocusRank(Map<String, Object> row) {
+        String status = row == null ? "" : toText(row.get("status"));
+        if ("TIMEOUT".equalsIgnoreCase(status) || "ERROR".equalsIgnoreCase(status)) {
+            return 0;
+        }
+        if ("UNSTABLE".equalsIgnoreCase(status)) {
+            return 1;
+        }
+        if ("NO_DATA".equalsIgnoreCase(status)) {
+            return 2;
+        }
+        return 3;
+    }
+
+    private String resolveNetworkStatusTagType(String status) {
+        if ("TIMEOUT".equalsIgnoreCase(status) || "ERROR".equalsIgnoreCase(status)) {
+            return "danger";
+        }
+        if ("UNSTABLE".equalsIgnoreCase(status)) {
+            return "warning";
+        }
+        if ("OK".equalsIgnoreCase(status)) {
+            return "success";
+        }
+        return "info";
+    }
+
     private boolean isInboundTask(Long wrkSts) {
         return wrkSts != null && wrkSts > 0 && wrkSts < 100;
     }

--
Gitblit v1.9.1