From d2ab6f7153e604bac7bc4ad58f27f368b65d8a1e Mon Sep 17 00:00:00 2001
From: yuan <123@>
Date: 星期二, 16 六月 2026 13:54:58 +0800
Subject: [PATCH] feat: 添加能耗数据综合分析功能,支持按天和周维度的趋势分析
---
src/main/java/com/ruoyi/http/service/impl/StatisticEleServiceImpl.java | 128 ++++++++++++++++++++++++++++++++++++------
1 files changed, 108 insertions(+), 20 deletions(-)
diff --git a/src/main/java/com/ruoyi/http/service/impl/StatisticEleServiceImpl.java b/src/main/java/com/ruoyi/http/service/impl/StatisticEleServiceImpl.java
index 357fdcd..1d624d2 100644
--- a/src/main/java/com/ruoyi/http/service/impl/StatisticEleServiceImpl.java
+++ b/src/main/java/com/ruoyi/http/service/impl/StatisticEleServiceImpl.java
@@ -15,6 +15,9 @@
import com.ruoyi.http.service.StatisticEleService;
import com.ruoyi.http.util.StatisticEleAggregateUtil;
import com.ruoyi.http.util.StatisticEleAggregateUtil.HourRange;
+import com.ruoyi.http.util.StatisticEleAnalyticsUtil;
+import com.ruoyi.http.util.StatisticEleAnalyticsUtil.DateBounds;
+import com.ruoyi.http.vo.StatisticEleAnalyticsVo;
import com.ruoyi.http.vo.StatisticEleRecordVo;
import com.ruoyi.http.vo.StatisticEleSummaryVo;
import com.ruoyi.http.vo.StatisticEleSyncStatusVo;
@@ -24,22 +27,24 @@
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
+import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
-import java.util.stream.Collectors;
@Service
@Slf4j
@RequiredArgsConstructor
public class StatisticEleServiceImpl implements StatisticEleService {
- private static final Set<String> STAT_DIMENSIONS = Set.of("day", "month", "quarter", "year");
+ private static final Set<String> STAT_DIMENSIONS = Set.of("day", "week", "month", "quarter", "year");
private static final List<String> DATA_DIMENSIONS = List.of("hour", "manual");
private static final DateTimeFormatter LOG_TIME_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+ private static final DateTimeFormatter DAY_FMT = DateTimeFormatter.ofPattern("yyyyMMdd");
private final TqdianbiaoConfig config;
private final TqdianbiaoEleRecordMapper eleRecordMapper;
@@ -75,24 +80,116 @@
throw new ServiceException("寮�濮嬫椂闂村拰缁撴潫鏃堕棿涓嶈兘涓虹┖");
}
if ("hour".equals(dimension)) {
- List<StatisticEleRecordVo> detailRecords = queryHourRecords(startTime, endTime);
+ List<StatisticEleRecordVo> hourRecords = queryHourRecords(startTime, endTime);
List<StatisticEleRecordVo> chartRecords = StatisticEleAggregateUtil.aggregateHourToBuckets(
- detailRecords, StatisticEleAggregateUtil.HOUR_TO_HOUR);
- return buildSummary(detailRecords, chartRecords);
+ hourRecords, StatisticEleAggregateUtil.HOUR_TO_HOUR);
+ return buildSummary(hourRecords, chartRecords, hourRecords);
}
if (!STAT_DIMENSIONS.contains(dimension)) {
- throw new ServiceException("缁熻缁村害鏃犳晥锛屾敮鎸� hour/day/month/quarter/year");
+ throw new ServiceException("缁熻缁村害鏃犳晥锛屾敮鎸� hour/day/week/month/quarter/year");
}
+ if ("day".equals(dimension)) {
+ return getDayDimensionSummary(startTime, endTime);
+ }
+
+ HourRange range = StatisticEleAggregateUtil.toHourQueryRange(dimension, startTime, endTime);
+ List<StatisticEleRecordVo> hourRecords = queryHourRecords(range.startTime(), range.endTime());
List<StatisticEleRecordVo> detailRecords = aggregateFromHour(dimension, startTime, endTime, true);
List<StatisticEleRecordVo> chartRecords = aggregateFromHour(dimension, startTime, endTime, false);
- return buildSummary(detailRecords, chartRecords);
+ return buildSummary(detailRecords, chartRecords, hourRecords);
+ }
+
+ @Override
+ public StatisticEleAnalyticsVo getAnalytics(String dimension, String startTime, String endTime, String trendGranularity) {
+ if (!StringUtils.hasText(startTime) || !StringUtils.hasText(endTime)) {
+ throw new ServiceException("寮�濮嬫椂闂村拰缁撴潫鏃堕棿涓嶈兘涓虹┖");
+ }
+ StatisticEleSummaryVo summary = getSummary(dimension, startTime, endTime);
+ HourRange range = StatisticEleAggregateUtil.toHourQueryRange(
+ normalizeAnalyticsDimension(dimension), startTime, endTime);
+ List<StatisticEleRecordVo> hourRecords = queryHourRecords(range.startTime(), range.endTime());
+ List<StatisticEleRecordVo> hourlyMerged = StatisticEleAggregateUtil.aggregateHourToBuckets(
+ hourRecords, StatisticEleAggregateUtil.HOUR_TO_HOUR);
+
+ boolean singleDay = "day".equals(dimension) && startTime.equals(endTime);
+ String trend = StringUtils.hasText(trendGranularity)
+ ? trendGranularity
+ : StatisticEleAnalyticsUtil.defaultTrendGranularity(dimension, singleDay);
+
+ StatisticEleAnalyticsVo analytics = copyToAnalytics(summary);
+ analytics.setLoadRate(StatisticEleAnalyticsUtil.calcLoadRate(
+ summary.getAvgConsumption(), summary.getMaxConsumption()));
+ analytics.setPeriodSplits(StatisticEleAnalyticsUtil.calcPeriodSplits(hourlyMerged));
+ analytics.setShiftSplits(StatisticEleAnalyticsUtil.calcShiftSplits(hourlyMerged));
+ analytics.setDayTypeSplits(StatisticEleAnalyticsUtil.calcDayTypeSplits(hourlyMerged));
+ analytics.setTrendGranularity(trend);
+ analytics.setTrendRecords(StatisticEleAggregateUtil.aggregateHourToBuckets(
+ hourRecords, StatisticEleAnalyticsUtil.trendBucketFn(trend)));
+
+ DateBounds bounds = StatisticEleAnalyticsUtil.resolveBounds(dimension, startTime, endTime);
+ Double chainTotal = queryTotalByDayBounds(StatisticEleAnalyticsUtil.shiftChain(bounds));
+ Double yoyTotal = queryTotalByDayBounds(StatisticEleAnalyticsUtil.shiftYoy(bounds));
+ analytics.setChainComparison(StatisticEleAnalyticsUtil.buildComparison(
+ "chain", "鐜瘮涓婃湡", summary.getTotalConsumption(), chainTotal));
+ analytics.setYoyComparison(StatisticEleAnalyticsUtil.buildComparison(
+ "yoy", "鍚屾瘮鍘诲勾鍚屾湡", summary.getTotalConsumption(), yoyTotal));
+ return analytics;
+ }
+
+ private String normalizeAnalyticsDimension(String dimension) {
+ return STAT_DIMENSIONS.contains(dimension) ? dimension : "day";
+ }
+
+ private Double queryTotalByDayBounds(DateBounds bounds) {
+ String start = bounds.start().format(DAY_FMT);
+ String end = bounds.end().format(DAY_FMT);
+ HourRange range = StatisticEleAggregateUtil.toHourQueryRange("day", start, end);
+ List<StatisticEleRecordVo> hourRecords = queryHourRecords(range.startTime(), range.endTime());
+ if (hourRecords.isEmpty()) {
+ return 0.0;
+ }
+ return StatisticEleAnalyticsUtil.calcCombinedMetrics(
+ hourRecords,
+ StatisticEleAggregateUtil.aggregateHourToBuckets(hourRecords, StatisticEleAggregateUtil.HOUR_TO_DAY)
+ ).getTotalConsumption();
+ }
+
+ private StatisticEleAnalyticsVo copyToAnalytics(StatisticEleSummaryVo summary) {
+ StatisticEleAnalyticsVo analytics = new StatisticEleAnalyticsVo();
+ analytics.setTotalConsumption(summary.getTotalConsumption());
+ analytics.setAvgConsumption(summary.getAvgConsumption());
+ analytics.setMaxConsumption(summary.getMaxConsumption());
+ analytics.setMinConsumption(summary.getMinConsumption());
+ analytics.setRecordCount(summary.getRecordCount());
+ analytics.setChartRecords(summary.getChartRecords());
+ analytics.setRecords(summary.getRecords());
+ return analytics;
+ }
+
+ /**
+ * 澶╃淮搴︽眹鎬伙細鍗曟棩鐢ㄥ皬鏃剁骇鏁版嵁璁$畻鍧囧��/鏋佸�煎苟灞曠ず 24 灏忔椂瓒嬪娍锛涘鏃ユ寜鏃ユ《瀵规瘮銆�
+ */
+ private StatisticEleSummaryVo getDayDimensionSummary(String startTime, String endTime) {
+ HourRange range = StatisticEleAggregateUtil.toHourQueryRange("day", startTime, endTime);
+ List<StatisticEleRecordVo> hourRecords = queryHourRecords(range.startTime(), range.endTime());
+ List<StatisticEleRecordVo> detailRecords = StatisticEleAggregateUtil.aggregateHourPerMeter(
+ hourRecords, StatisticEleAggregateUtil.HOUR_TO_DAY);
+
+ boolean singleDay = startTime.equals(endTime);
+ List<StatisticEleRecordVo> chartRecords = singleDay
+ ? StatisticEleAggregateUtil.aggregateHourToBuckets(hourRecords, StatisticEleAggregateUtil.HOUR_TO_HOUR)
+ : StatisticEleAggregateUtil.aggregateHourToBuckets(hourRecords, StatisticEleAggregateUtil.HOUR_TO_DAY);
+
+ return buildSummary(detailRecords, chartRecords, hourRecords);
}
private StatisticEleSummaryVo buildSummary(
- List<StatisticEleRecordVo> detailRecords, List<StatisticEleRecordVo> chartRecords) {
+ List<StatisticEleRecordVo> detailRecords,
+ List<StatisticEleRecordVo> chartRecords,
+ List<StatisticEleRecordVo> hourRecords) {
StatisticEleAggregateUtil.StatisticEleSummaryMetrics metrics =
- StatisticEleAggregateUtil.calcMetrics(chartRecords);
+ StatisticEleAnalyticsUtil.calcCombinedMetrics(hourRecords, chartRecords);
StatisticEleSummaryVo summary = new StatisticEleSummaryVo();
summary.setRecords(detailRecords);
summary.setChartRecords(chartRecords);
@@ -106,17 +203,8 @@
@Override
public StatisticEleSummaryVo getYesterdaySummary() {
- HourRange range = StatisticEleAggregateUtil.yesterdayHourRange();
- List<StatisticEleRecordVo> records = queryHourRecords(range.startTime(), range.endTime());
- List<StatisticEleRecordVo> chartRecords = StatisticEleAggregateUtil.aggregateHourToBuckets(
- records, StatisticEleAggregateUtil.HOUR_TO_HOUR);
- StatisticEleSummaryVo summary = buildSummary(records, chartRecords);
- summary.setTotalConsumption(round(StatisticEleAggregateUtil.sumRecordsTotal(records)));
- return summary;
- }
-
- private static double round(double value) {
- return Math.round(value * 100.0) / 100.0;
+ String day = LocalDate.now().minusDays(1).format(DateTimeFormatter.ofPattern("yyyyMMdd"));
+ return getDayDimensionSummary(day, day);
}
@Override
--
Gitblit v1.9.3