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

fix(cockpit): 对齐行业预警和工单时间线

Kazerin 3 недель назад
Родитель
Сommit
11e5d9a7b9
11 измененных файлов с 86 добавлено и 8 удалено
  1. 3 0
      pipe-network-service/zksy-admin/src/test/java/com/zksy/web/controller/cockpit/BusinessCockpitDeviceFactResolverTest.java
  2. 16 0
      pipe-network-service/zksy-admin/src/test/java/com/zksy/web/controller/cockpit/BusinessCockpitMapSnapshotAdapterTest.java
  3. 16 1
      pipe-network-service/zksy-admin/src/test/java/com/zksy/web/controller/cockpit/BusinessCockpitMonitoringDistributionAdapterTest.java
  4. 2 2
      pipe-network-service/zksy-admin/src/test/java/com/zksy/web/controller/cockpit/CockpitOverviewInfrastructureControllerTest.java
  5. 17 0
      pipe-network-service/zksy-admin/src/test/java/com/zksy/web/controller/cockpit/CockpitWorkOrderStateDictionaryTest.java
  6. 1 1
      pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/map/BusinessCockpitMapSnapshotAdapter.java
  7. 1 1
      pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/monitoring/BusinessCockpitMonitoringDistributionAdapter.java
  8. 6 1
      pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/overview/CockpitOverviewInfrastructureService.java
  9. 1 1
      pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/point/BusinessCockpitDeviceFactResolver.java
  10. 2 1
      pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/BusinessCockpitWorkOrderReadAdapter.java
  11. 21 0
      pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/CockpitWorkOrderStateDictionary.java

+ 3 - 0
pipe-network-service/zksy-admin/src/test/java/com/zksy/web/controller/cockpit/BusinessCockpitDeviceFactResolverTest.java

@@ -124,6 +124,9 @@ class BusinessCockpitDeviceFactResolverTest {
 
 
         assertTrue(resolver.resolve(device("DEV-5"), null).isWarning(), "小写 processing 也视为预警中");
         assertTrue(resolver.resolve(device("DEV-5"), null).isWarning(), "小写 processing 也视为预警中");
 
 
+        when(earlyWarningService.list(any(Wrapper.class))).thenReturn(Collections.singletonList(warning("released")));
+        assertTrue(resolver.resolve(device("DEV-5"), null).isWarning(), "RELEASED 已发布预警仍为当前预警");
+
         when(earlyWarningService.list(any(Wrapper.class))).thenReturn(Collections.singletonList(warning("CLOSED")));
         when(earlyWarningService.list(any(Wrapper.class))).thenReturn(Collections.singletonList(warning("CLOSED")));
         assertFalse(resolver.resolve(device("DEV-5"), null).isWarning(), "CLOSED 预警不算预警中");
         assertFalse(resolver.resolve(device("DEV-5"), null).isWarning(), "CLOSED 预警不算预警中");
     }
     }

+ 16 - 0
pipe-network-service/zksy-admin/src/test/java/com/zksy/web/controller/cockpit/BusinessCockpitMapSnapshotAdapterTest.java

@@ -160,6 +160,22 @@ class BusinessCockpitMapSnapshotAdapterTest {
                 "窨井根映射为 MANHOLE 传值,交由服务层判非正式行业,而非在适配器吞掉");
                 "窨井根映射为 MANHOLE 传值,交由服务层判非正式行业,而非在适配器吞掉");
     }
     }
 
 
+    @Test
+    void nestedEquipmentTypeResolvesIndustryFromRoot() {
+        stubPoints(Collections.emptyList());
+        stubTypes(Arrays.asList(
+                type(4, "manhole_root", "窨井设备", "0"),
+                type(40, "manhole_family", "窨井监测族", "4"),
+                type(41, "manhole_sensor", "窨井传感器", "40")));
+        stubDevices(Collections.emptyList(), Collections.emptyList());
+
+        CockpitMapSnapshot snapshot = adapter.load("2026-09-02T10:00:00+08:00");
+
+        assertEquals("MANHOLE", snapshot.getTypes().stream()
+                .filter(item -> "41".equals(item.getCode()))
+                .findFirst().orElseThrow(AssertionError::new).getIndustry());
+    }
+
     @Test
     @Test
     void sameSnapshotAtReusesTheFirstSourceSnapshotAfterRelationsChange() {
     void sameSnapshotAtReusesTheFirstSourceSnapshotAfterRelationsChange() {
         String snapshotAt = "2026-09-02T10:00:00+08:00";
         String snapshotAt = "2026-09-02T10:00:00+08:00";

+ 16 - 1
pipe-network-service/zksy-admin/src/test/java/com/zksy/web/controller/cockpit/BusinessCockpitMonitoringDistributionAdapterTest.java

@@ -112,7 +112,22 @@ class BusinessCockpitMonitoringDistributionAdapterTest {
                 .findFirst().orElseThrow().getIndustry());
                 .findFirst().orElseThrow().getIndustry());
     }
     }
 
 
-    // ---- stubbing helpers ----
+    @Test
+    void nestedEquipmentTypeResolvesIndustryFromRoot() {
+        stubPoints(Collections.emptyList());
+        stubTypes(Arrays.asList(
+                type(4, "4", "窨井设备", "0"),
+                type(40, "40", "窨井监测族", "4"),
+                type(41, "41", "窨井传感器", "40")));
+        stubDevices(Collections.emptyList(), Collections.emptyList());
+
+        CockpitMonitoringDistributionSnapshot snapshot = adapter.load(null);
+
+        assertEquals("MANHOLE", snapshot.getTypes().stream()
+                .filter(item -> "41".equals(item.getCode()))
+                .findFirst().orElseThrow(AssertionError::new).getIndustry());
+    }
+
 
 
     private void stubPoints(List<MonitorPoint> points) {
     private void stubPoints(List<MonitorPoint> points) {
         when(monitorPointService.list()).thenReturn(points);
         when(monitorPointService.list()).thenReturn(points);

+ 2 - 2
pipe-network-service/zksy-admin/src/test/java/com/zksy/web/controller/cockpit/CockpitOverviewInfrastructureControllerTest.java

@@ -52,7 +52,7 @@ class CockpitOverviewInfrastructureControllerTest {
         mockMvc.perform(get("/api/cockpit/v1/overview/infrastructure"))
         mockMvc.perform(get("/api/cockpit/v1/overview/infrastructure"))
                 .andExpect(status().isOk())
                 .andExpect(status().isOk())
                 .andExpect(jsonPath("$.data.totals.facilityCount").value(3))
                 .andExpect(jsonPath("$.data.totals.facilityCount").value(3))
-                .andExpect(jsonPath("$.data.totals.smartDeviceCount").value(14))
+                .andExpect(jsonPath("$.data.totals.smartDeviceCount").value(12))
                 .andExpect(jsonPath("$.data.industries", hasSize(4)))
                 .andExpect(jsonPath("$.data.industries", hasSize(4)))
                 .andExpect(jsonPath("$.data.industries[0].code").value("GAS"))
                 .andExpect(jsonPath("$.data.industries[0].code").value("GAS"))
                 .andExpect(jsonPath("$.data.industries[0].facilityCount").value(0))
                 .andExpect(jsonPath("$.data.industries[0].facilityCount").value(0))
@@ -67,7 +67,7 @@ class CockpitOverviewInfrastructureControllerTest {
                 .andExpect(jsonPath("$.data.industries[2].deviceTypes[0].count").value(4))
                 .andExpect(jsonPath("$.data.industries[2].deviceTypes[0].count").value(4))
                 .andExpect(jsonPath("$.data.industries[2].deviceTypes[1].code").value("SEWAGE_ENVIRONMENT_SENSOR"))
                 .andExpect(jsonPath("$.data.industries[2].deviceTypes[1].code").value("SEWAGE_ENVIRONMENT_SENSOR"))
                 .andExpect(jsonPath("$.data.industries[2].deviceTypes[1].count").value(5))
                 .andExpect(jsonPath("$.data.industries[2].deviceTypes[1].count").value(5))
-                .andExpect(jsonPath("$.data.excluded.unknownTypeCount").value(8))
+                .andExpect(jsonPath("$.data.excluded.unknownTypeCount").value(10))
                 .andExpect(jsonPath("$.data.excluded.typeKindMismatchCount").value(5));
                 .andExpect(jsonPath("$.data.excluded.typeKindMismatchCount").value(5));
     }
     }
 
 

+ 17 - 0
pipe-network-service/zksy-admin/src/test/java/com/zksy/web/controller/cockpit/CockpitWorkOrderStateDictionaryTest.java

@@ -0,0 +1,17 @@
+package com.zksy.web.controller.cockpit;
+
+import com.zksy.cockpit.workorder.CockpitWorkOrderStateDictionary;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class CockpitWorkOrderStateDictionaryTest {
+
+    @Test
+    void mapsOperationLogsToCurrentRuntimeStates() {
+        assertEquals(0, CockpitWorkOrderStateDictionary.byOperationCode(0, 0).getCode());
+        assertEquals(3, CockpitWorkOrderStateDictionary.byOperationCode(6, 3).getCode());
+        assertEquals(6, CockpitWorkOrderStateDictionary.byOperationCode(9, 6).getCode());
+        assertEquals(3, CockpitWorkOrderStateDictionary.byOperationCode(10, 3).getCode());
+    }
+}

+ 1 - 1
pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/map/BusinessCockpitMapSnapshotAdapter.java

@@ -256,7 +256,7 @@ public class BusinessCockpitMapSnapshotAdapter implements CockpitMapSnapshotAdap
                 .map(type -> new CockpitMapSnapshot.SourceType(
                 .map(type -> new CockpitMapSnapshot.SourceType(
                         String.valueOf(type.getId()),
                         String.valueOf(type.getId()),
                         type.getTypeName(),
                         type.getTypeName(),
-                        CockpitTypeIndustry.industryOf(type),
+                        CockpitTypeIndustry.industryOf(type, types),
                         "SMART_DEVICE"))
                         "SMART_DEVICE"))
                 .collect(Collectors.toList());
                 .collect(Collectors.toList());
 
 

+ 1 - 1
pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/monitoring/BusinessCockpitMonitoringDistributionAdapter.java

@@ -139,7 +139,7 @@ public class BusinessCockpitMonitoringDistributionAdapter implements CockpitMoni
                 .map(type -> new CockpitMonitoringDistributionSnapshot.SourceType(
                 .map(type -> new CockpitMonitoringDistributionSnapshot.SourceType(
                         String.valueOf(type.getId()),
                         String.valueOf(type.getId()),
                         type.getTypeName(),
                         type.getTypeName(),
-                        CockpitTypeIndustry.industryOf(type),
+                        CockpitTypeIndustry.industryOf(type, types),
                         "SMART_DEVICE"))
                         "SMART_DEVICE"))
                 .collect(Collectors.toList());
                 .collect(Collectors.toList());
 
 

+ 6 - 1
pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/overview/CockpitOverviewInfrastructureService.java

@@ -62,7 +62,12 @@ public class CockpitOverviewInfrastructureService {
                         unknownTypeCount += count.getCount();
                         unknownTypeCount += count.getCount();
                     }
                     }
                 } else {
                 } else {
-                    addResolvedCount(count, type, industryBuilders, totals);
+                    if (industryBuilders.stream().noneMatch(candidate ->
+                            candidate.getCode().equals(type.getIndustry()))) {
+                        unknownTypeCount += count.getCount();
+                    } else {
+                        addResolvedCount(count, type, industryBuilders, totals);
+                    }
                 }
                 }
             }
             }
         }
         }

+ 1 - 1
pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/point/BusinessCockpitDeviceFactResolver.java

@@ -34,7 +34,7 @@ public class BusinessCockpitDeviceFactResolver {
 
 
     /** 未关闭的预警状态:现网取值含 PENDING/PROCESSING 等。 */
     /** 未关闭的预警状态:现网取值含 PENDING/PROCESSING 等。 */
     private static final Set<String> OPEN_WARNING_STATUS = new LinkedHashSet<>(
     private static final Set<String> OPEN_WARNING_STATUS = new LinkedHashSet<>(
-            Arrays.asList("PENDING", "PROCESSING", "HANDLING"));
+            Arrays.asList("PENDING", "PROCESSING", "HANDLING", "RELEASED"));
 
 
     private final EquipmentStatusService equipmentStatusService;
     private final EquipmentStatusService equipmentStatusService;
     private final EarlyWarningService earlyWarningService;
     private final EarlyWarningService earlyWarningService;

+ 2 - 1
pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/BusinessCockpitWorkOrderReadAdapter.java

@@ -149,7 +149,8 @@ public class BusinessCockpitWorkOrderReadAdapter implements CockpitWorkOrderRead
     }
     }
 
 
     private CockpitWorkOrderTimelineEntry toTimelineEntry(WorkOrder order, WorkOrderLogVO log) {
     private CockpitWorkOrderTimelineEntry toTimelineEntry(WorkOrder order, WorkOrderLogVO log) {
-        CockpitWorkOrderState state = CockpitWorkOrderStateDictionary.byLegacyCode(log.getOperType());
+        CockpitWorkOrderState state = CockpitWorkOrderStateDictionary.byOperationCode(
+                log.getOperType(), order.getOrderStatus());
         return new CockpitWorkOrderTimelineEntry(
         return new CockpitWorkOrderTimelineEntry(
                 log.getLogId(),
                 log.getLogId(),
                 order.getOrderNo(),
                 order.getOrderNo(),

+ 21 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/cockpit/workorder/CockpitWorkOrderStateDictionary.java

@@ -44,6 +44,27 @@ public final class CockpitWorkOrderStateDictionary {
         return code == null ? null : BY_CODE.get(code);
         return code == null ? null : BY_CODE.get(code);
     }
     }
 
 
+    /** 将工单操作日志操作码映射为操作完成后的当前运行时状态。 */
+    public static CockpitWorkOrderState byOperationCode(Integer operationCode, Integer currentStateCode) {
+        if (operationCode == null) {
+            return byCode(currentStateCode);
+        }
+        switch (operationCode) {
+            case 0: return byCode(0); // 创建:待派单
+            case 1: return byCode(1); // 派单:待接单
+            case 2: return byCode(2); // 接单:已接单
+            case 3: return byCode(3); // 处置:处理中
+            case 4: return byCode(4); // 提交验收:待验收
+            case 5: return byCode(5); // 验收通过:已结案
+            case 6: return byCode(3); // 验收驳回:回到处理中
+            case 7: return byCode(7); // 取消:已取消
+            case 8: return byCode(3); // 申请延期:仍在处理中
+            case 9: return byCode(6); // 延期通过:延期中
+            case 10: return byCode(3); // 延期驳回:回到处理中
+            default: return byCode(currentStateCode);
+        }
+    }
+
     /**
     /**
      * 迁移期兼容:把旧编码(1 待派单 … 6 已结案、7 已取消)转换到运行时 0–7 编码。
      * 迁移期兼容:把旧编码(1 待派单 … 6 已结案、7 已取消)转换到运行时 0–7 编码。
      * 旧 1–6 映射到新 0–5(旧 6 已结案 → 新 5 已结案);旧 7 已取消 → 新 7 已取消;
      * 旧 1–6 映射到新 0–5(旧 6 已结案 → 新 5 已结案);旧 7 已取消 → 新 7 已取消;