Ver código fonte

fix(waterSupply): 报警趋势按四级统计并补齐台账流水列 (#45)

- TrendItem 改为按日输出一至四级报警计数,移除报警数与高等级两个汇总口径

- 导出台账补偏差率列,与列表流水口径一致

- 同步调整 dashboard 服务测试与 ledger 控制器契约测试
Kazerin 1 mês atrás
pai
commit
a9078381ec

+ 7 - 3
pipe-network-service/zksy-admin/src/test/java/com/zksy/web/controller/WaterSupply/MonitorAlarm/WaterSupplyAlarmLedgerControllerTest.java

@@ -92,8 +92,10 @@ class WaterSupplyAlarmLedgerControllerTest {
         dashboard.setAlarmingDeviceCount(4);
         AlarmDashboardOutDTO.TrendItem trend = new AlarmDashboardOutDTO.TrendItem();
         trend.setDate("2026-09-14");
-        trend.setCount(4);
-        trend.setHighLevelCount(2);
+        trend.setLevel1Count(1);
+        trend.setLevel2Count(2);
+        trend.setLevel3Count(0);
+        trend.setLevel4Count(1);
         dashboard.setTrend(Collections.singletonList(trend));
         AlarmDashboardOutDTO.RatioItem ratio = new AlarmDashboardOutDTO.RatioItem();
         ratio.setName("压力预警");
@@ -109,7 +111,9 @@ class WaterSupplyAlarmLedgerControllerTest {
                     assertThat(json, "\"transferredCount\":3");
                     assertThat(json, "\"releasedCount\":1");
                     assertThat(json, "\"alarmingDeviceCount\":4");
-                    assertThat(json, "\"highLevelCount\":2");
+                    assertThat(json, "\"level1Count\":1");
+                    assertThat(json, "\"level2Count\":2");
+                    assertThat(json, "\"level4Count\":1");
                     assertThat(json, "\"name\":\"压力预警\"");
                 });
     }

+ 10 - 4
pipe-network-service/zksy-system/src/main/java/com/zksy/WaterSupply/MonitorAlarm/dto/out/AlarmDashboardOutDTO.java

@@ -53,11 +53,17 @@ public class AlarmDashboardOutDTO implements Serializable {
         @ApiModelProperty(value = "日期", example = "2026-09-14")
         private String date;
 
-        @ApiModelProperty(value = "当日报警数", example = "4")
-        private long count;
+        @ApiModelProperty(value = "当日一级报警数", example = "1")
+        private long level1Count;
+
+        @ApiModelProperty(value = "当日二级报警数", example = "2")
+        private long level2Count;
+
+        @ApiModelProperty(value = "当日三级报警数", example = "0")
+        private long level3Count;
 
-        @ApiModelProperty(value = "其中高等级(1-2 级)报警数", example = "2")
-        private long highLevelCount;
+        @ApiModelProperty(value = "当日四级报警数", example = "1")
+        private long level4Count;
     }
 
     @Data

+ 28 - 4
pipe-network-service/zksy-system/src/main/java/com/zksy/WaterSupply/MonitorAlarm/service/impl/WaterSupplyAlarmServiceImpl.java

@@ -488,6 +488,8 @@ public class WaterSupplyAlarmServiceImpl implements IWaterSupplyAlarmService {
 
     /**
      * 报警趋势:按自然日分桶,区间内无报警的日期补 0,保证图表横轴连续。
+     *
+     * <p>逐日报警按四个报警等级分别计数,供前端直接画四条趋势序列。</p>
      */
     private List<AlarmDashboardOutDTO.TrendItem> buildTrend(List<WaterAlarmOutDTO> rows, int days) {
         LocalDate today = LocalDate.now();
@@ -506,14 +508,36 @@ public class WaterSupplyAlarmServiceImpl implements IWaterSupplyAlarmService {
             if (item == null) {
                 continue;
             }
-            item.setCount(item.getCount() + 1);
-            if (row.getAlarmLevel() != null && row.getAlarmLevel() <= 2) {
-                item.setHighLevelCount(item.getHighLevelCount() + 1);
-            }
+            increaseTrendLevel(item, row.getAlarmLevel());
         }
         return new ArrayList<>(byDate.values());
     }
 
+    /**
+     * 按报警等级累加当日趋势计数;等级缺失或越界时不计入任何序列。
+     */
+    private void increaseTrendLevel(AlarmDashboardOutDTO.TrendItem item, Integer alarmLevel) {
+        if (alarmLevel == null) {
+            return;
+        }
+        switch (alarmLevel) {
+            case 1:
+                item.setLevel1Count(item.getLevel1Count() + 1);
+                break;
+            case 2:
+                item.setLevel2Count(item.getLevel2Count() + 1);
+                break;
+            case 3:
+                item.setLevel3Count(item.getLevel3Count() + 1);
+                break;
+            case 4:
+                item.setLevel4Count(item.getLevel4Count() + 1);
+                break;
+            default:
+                break;
+        }
+    }
+
     private List<AlarmDashboardOutDTO.TrendItem> emptyTrend(int days) {
         List<AlarmDashboardOutDTO.TrendItem> empty = new ArrayList<>();
         LocalDate from = LocalDate.now().minusDays(days - 1L);

+ 4 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/WaterSupply/export/WaterAlarmLedgerExportDTO.java

@@ -49,6 +49,9 @@ public class WaterAlarmLedgerExportDTO {
     @Excel(name = "阈值上限")
     private BigDecimal maxValue;
 
+    @Excel(name = "偏差率")
+    private BigDecimal deviationRatio;
+
     @Excel(name = "安装位置")
     private String equipmentLocation;
 
@@ -77,6 +80,7 @@ public class WaterAlarmLedgerExportDTO {
         dto.actualValue = value.getActualValue();
         dto.minValue = value.getMinValue();
         dto.maxValue = value.getMaxValue();
+        dto.deviationRatio = value.getDeviationRatio();
         dto.equipmentLocation = value.getEquipmentLocation();
         dto.alarmTime = value.getAlarmTime();
         dto.handleTime = value.getHandleTime();

+ 26 - 13
pipe-network-service/zksy-system/src/test/java/com/zksy/WaterSupply/MonitorAlarm/WaterSupplyAlarmDashboardServiceTest.java

@@ -159,12 +159,16 @@ class WaterSupplyAlarmDashboardServiceTest {
         assertEquals(1, dashboard.getReleasedCount());
         assertEquals(1, dashboard.getAlarmingDeviceCount());
 
-        // 趋势覆盖 7 天,含无报警日
+        // 趋势:按天覆盖 7 天(含无报警日),且只按四个报警等级分别给序列,
+        // 不再输出“报警数 / 高等级报警”两个汇总口径(#45 验收反馈)
         assertEquals(7, dashboard.getTrend().size());
-        assertEquals(2, countOn(dashboard, LocalDate.now().toString()));
-        assertEquals(1, countOn(dashboard, LocalDate.now().minusDays(1).toString()));
-        // 今日两条报警分别为 1 级与 2 级,均属于“高等级(1-2 级)”口径
-        assertEquals(2, highLevelCountOn(dashboard, LocalDate.now().toString()));
+        String todayLabel = LocalDate.now().toString();
+        String yesterdayLabel = LocalDate.now().minusDays(1).toString();
+        assertEquals(1, levelCountOn(dashboard, todayLabel, 1));
+        assertEquals(1, levelCountOn(dashboard, todayLabel, 2));
+        assertEquals(0, levelCountOn(dashboard, todayLabel, 3));
+        assertEquals(0, levelCountOn(dashboard, todayLabel, 4));
+        assertEquals(1, levelCountOn(dashboard, yesterdayLabel, 3));
 
         // 报警分类占比:压力预警 2 条,流量预警 1 条
         assertEquals(2, ratioOf(dashboard.getWarningTypeRatio(), "压力预警"));
@@ -190,14 +194,23 @@ class WaterSupplyAlarmDashboardServiceTest {
         return status;
     }
 
-    private static long countOn(AlarmDashboardOutDTO dashboard, String date) {
-        return dashboard.getTrend().stream().filter(item -> date.equals(item.getDate()))
-                .mapToLong(AlarmDashboardOutDTO.TrendItem::getCount).sum();
-    }
-
-    private static long highLevelCountOn(AlarmDashboardOutDTO dashboard, String date) {
-        return dashboard.getTrend().stream().filter(item -> date.equals(item.getDate()))
-                .mapToLong(AlarmDashboardOutDTO.TrendItem::getHighLevelCount).sum();
+    /** 读取指定日期、指定报警等级的趋势计数 */
+    private static long levelCountOn(AlarmDashboardOutDTO dashboard, String date, int level) {
+        return dashboard.getTrend().stream()
+                .filter(item -> date.equals(item.getDate()))
+                .mapToLong(item -> {
+                    switch (level) {
+                        case 1:
+                            return item.getLevel1Count();
+                        case 2:
+                            return item.getLevel2Count();
+                        case 3:
+                            return item.getLevel3Count();
+                        default:
+                            return item.getLevel4Count();
+                    }
+                })
+                .sum();
     }
 
     private static long ratioOf(List<AlarmDashboardOutDTO.RatioItem> items, String name) {