From 7fc5bc0c6f92d65099397690128cbf218935972d Mon Sep 17 00:00:00 2001
From: yuan <123@>
Date: 星期二, 16 六月 2026 13:33:41 +0800
Subject: [PATCH] feat: 修改小时同步回看窗口为1小时,并添加天维度汇总功能

---
 src/main/java/com/ruoyi/http/util/StatisticEleAggregateUtil.java |  148 ++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 134 insertions(+), 14 deletions(-)

diff --git a/src/main/java/com/ruoyi/http/util/StatisticEleAggregateUtil.java b/src/main/java/com/ruoyi/http/util/StatisticEleAggregateUtil.java
index c57f8bd..dc3b133 100644
--- a/src/main/java/com/ruoyi/http/util/StatisticEleAggregateUtil.java
+++ b/src/main/java/com/ruoyi/http/util/StatisticEleAggregateUtil.java
@@ -2,6 +2,8 @@
 
 import com.ruoyi.http.vo.StatisticEleRecordVo;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.YearMonth;
 import java.time.format.DateTimeFormatter;
@@ -18,6 +20,8 @@
 public final class StatisticEleAggregateUtil {
 
     private static final DateTimeFormatter DAY_FMT = DateTimeFormatter.ofPattern("yyyyMMdd");
+    private static final int CONSUMPTION_SCALE = StatisticEleReadingUtil.CONSUMPTION_SCALE;
+    private static final int SUMMARY_SCALE = 2;
 
     private StatisticEleAggregateUtil() {
     }
@@ -62,10 +66,84 @@
             mergeInto(map, key, bucket, record);
             StatisticEleRecordVo agg = map.get(key);
             agg.setMeterId(record.getMeterId());
-            agg.setAddress(record.getAddress());
-            agg.setCollectorNo(record.getCollectorNo());
+            mergeMeterInfo(agg, record);
         }
         return sorted(map);
+    }
+
+    private static void mergeMeterInfo(StatisticEleRecordVo agg, StatisticEleRecordVo record) {
+        if (hasText(record.getMeterName())) {
+            agg.setMeterName(record.getMeterName());
+        }
+        if (hasText(record.getAddress())) {
+            agg.setAddress(record.getAddress());
+        }
+        mergeTimeRange(agg, record);
+    }
+
+    private static void mergeTimeRange(StatisticEleRecordVo agg, StatisticEleRecordVo record) {
+        if (hasText(record.getStartTime())) {
+            if (!hasText(agg.getStartTime()) || record.getStartTime().compareTo(agg.getStartTime()) < 0) {
+                agg.setStartTime(record.getStartTime());
+            }
+        }
+        if (hasText(record.getEndTime())) {
+            if (!hasText(agg.getEndTime()) || record.getEndTime().compareTo(agg.getEndTime()) > 0) {
+                agg.setEndTime(record.getEndTime());
+            }
+        }
+    }
+
+    /** 姹囨�诲悗鑻ヨ捣姝㈡椂闂翠负绌猴紝鎸� timeKey 鎺ㄥ */
+    private static void fillTimeRangeIfEmpty(StatisticEleRecordVo vo) {
+        if (hasText(vo.getStartTime()) && hasText(vo.getEndTime())) {
+            return;
+        }
+        String timeKey = vo.getTimeKey();
+        if (!hasText(timeKey)) {
+            return;
+        }
+        if (timeKey.contains("Q")) {
+            String[] parts = timeKey.split("Q");
+            if (parts.length != 2) {
+                return;
+            }
+            int year = Integer.parseInt(parts[0]);
+            int quarter = Integer.parseInt(parts[1]);
+            int startMonth = (quarter - 1) * 3 + 1;
+            int endMonth = startMonth + 2;
+            YearMonth endYm = YearMonth.of(year, endMonth);
+            vo.setStartTime(String.format("%04d-%02d-01 00:00:00", year, startMonth));
+            vo.setEndTime(String.format("%04d-%02d-%02d 23:59:59", year, endMonth, endYm.lengthOfMonth()));
+            return;
+        }
+        if (timeKey.length() == 4) {
+            vo.setStartTime(timeKey + "-01-01 00:00:00");
+            vo.setEndTime(timeKey + "-12-31 23:59:59");
+            return;
+        }
+        if (timeKey.length() == 6) {
+            YearMonth ym = YearMonth.parse(timeKey, DateTimeFormatter.ofPattern("yyyyMM"));
+            vo.setStartTime(String.format("%04d-%02d-01 00:00:00", ym.getYear(), ym.getMonthValue()));
+            vo.setEndTime(String.format("%04d-%02d-%02d 23:59:59",
+                    ym.getYear(), ym.getMonthValue(), ym.lengthOfMonth()));
+            return;
+        }
+        if (timeKey.length() >= 8) {
+            String day = timeKey.substring(0, 8);
+            vo.setStartTime(toDateTime(day, "00:00:00"));
+            vo.setEndTime(toDateTime(day, "23:59:59"));
+        }
+    }
+
+    private static String toDateTime(String yyyyMMdd, String time) {
+        return yyyyMMdd.substring(0, 4) + "-"
+                + yyyyMMdd.substring(4, 6) + "-"
+                + yyyyMMdd.substring(6, 8) + " " + time;
+    }
+
+    private static boolean hasText(String value) {
+        return value != null && !value.isBlank();
     }
 
     /**
@@ -144,11 +222,12 @@
 
     /** 鏄庣粏璁板綍鎬荤敤鐢甸噺锛堜笌鏁版嵁閲囬泦椤垫眰鍜屾柟寮忎竴鑷达級 */
     public static double sumRecordsTotal(List<StatisticEleRecordVo> records) {
-        return records.stream()
+        BigDecimal total = records.stream()
                 .map(StatisticEleRecordVo::getTotalConsumption)
                 .filter(v -> v != null)
-                .mapToDouble(Double::doubleValue)
-                .sum();
+                .map(BigDecimal::valueOf)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        return roundSummary(total);
     }
 
     public static Function<String, String> bucketFn(String dimension) {
@@ -179,15 +258,17 @@
             metrics.setMinConsumption(0.0);
             return metrics;
         }
-        List<Double> values = buckets.stream()
+        List<BigDecimal> values = buckets.stream()
                 .map(StatisticEleRecordVo::getTotalConsumption)
                 .filter(v -> v != null)
+                .map(BigDecimal::valueOf)
                 .collect(Collectors.toList());
-        double total = values.stream().mapToDouble(Double::doubleValue).sum();
-        metrics.setTotalConsumption(round(total));
-        metrics.setAvgConsumption(round(total / values.size()));
-        metrics.setMaxConsumption(round(values.stream().mapToDouble(Double::doubleValue).max().orElse(0)));
-        metrics.setMinConsumption(round(values.stream().mapToDouble(Double::doubleValue).min().orElse(0)));
+        BigDecimal total = values.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
+        metrics.setTotalConsumption(roundSummary(total));
+        metrics.setAvgConsumption(roundSummary(total.divide(
+                BigDecimal.valueOf(values.size()), CONSUMPTION_SCALE, RoundingMode.HALF_UP)));
+        metrics.setMaxConsumption(roundSummary(values.stream().max(BigDecimal::compareTo).orElse(BigDecimal.ZERO)));
+        metrics.setMinConsumption(roundSummary(values.stream().min(BigDecimal::compareTo).orElse(BigDecimal.ZERO)));
         return metrics;
     }
 
@@ -212,6 +293,10 @@
 
     private static List<StatisticEleRecordVo> sorted(Map<String, StatisticEleRecordVo> map) {
         return map.values().stream()
+                .peek(vo -> {
+                    normalizeConsumptions(vo);
+                    fillTimeRangeIfEmpty(vo);
+                })
                 .sorted(Comparator.comparing(StatisticEleRecordVo::getTimeKey))
                 .collect(Collectors.toList());
     }
@@ -222,11 +307,46 @@
     }
 
     private static Double add(Double a, Double b) {
-        return (a == null ? 0.0 : a) + (b == null ? 0.0 : b);
+        BigDecimal sum = BigDecimal.valueOf(a == null ? 0.0 : a)
+                .add(BigDecimal.valueOf(b == null ? 0.0 : b));
+        return roundConsumption(sum);
     }
 
-    private static double round(double value) {
-        return Math.round(value * 100.0) / 100.0;
+    /** 缁熶竴鐢甸噺瀛楁绮惧害锛堟槑缁嗗睍绀猴級 */
+    public static void normalizeConsumptions(StatisticEleRecordVo vo) {
+        if (vo == null) {
+            return;
+        }
+        vo.setTotalConsumption(roundConsumption(vo.getTotalConsumption()));
+        vo.setSharpConsumption(roundConsumption(vo.getSharpConsumption()));
+        vo.setPeakConsumption(roundConsumption(vo.getPeakConsumption()));
+        vo.setFlatConsumption(roundConsumption(vo.getFlatConsumption()));
+        vo.setValleyConsumption(roundConsumption(vo.getValleyConsumption()));
+    }
+
+    public static void normalizeConsumptions(List<StatisticEleRecordVo> records) {
+        if (records == null) {
+            return;
+        }
+        records.forEach(vo -> normalizeConsumptions(vo));
+    }
+
+    private static Double roundConsumption(Double value) {
+        if (value == null) {
+            return null;
+        }
+        return roundConsumption(BigDecimal.valueOf(value));
+    }
+
+    private static Double roundConsumption(BigDecimal value) {
+        if (value == null) {
+            return null;
+        }
+        return value.setScale(CONSUMPTION_SCALE, RoundingMode.HALF_UP).doubleValue();
+    }
+
+    private static double roundSummary(BigDecimal value) {
+        return value.setScale(SUMMARY_SCALE, RoundingMode.HALF_UP).doubleValue();
     }
 
     public record HourRange(String startTime, String endTime) {}

--
Gitblit v1.9.3