| src/main/java/com/ruoyi/http/controller/StatisticEleController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/http/service/StatisticEleService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/http/service/impl/StatisticEleServiceImpl.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/http/util/StatisticEleAggregateUtil.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/http/util/StatisticEleAnalyticsUtil.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/http/vo/StatisticEleAnalyticsVo.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/http/vo/StatisticEleComparisonVo.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/http/vo/StatisticEleSplitItemVo.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/main/java/com/ruoyi/http/controller/StatisticEleController.java
@@ -44,6 +44,16 @@ return AjaxResult.success(statisticEleService.getSummary(dimension, startTime, endTime)); } @GetMapping("/analytics") @Operation(summary = "è½èæ°æ®-综ååæ") public AjaxResult analytics( @RequestParam(defaultValue = "day") String dimension, @RequestParam String startTime, @RequestParam String endTime, @RequestParam(required = false) String trendGranularity) { return AjaxResult.success(statisticEleService.getAnalytics(dimension, startTime, endTime, trendGranularity)); } @GetMapping("/yesterday") @Operation(summary = "æ¨æ¥ç¨çµéæ±æ»") public AjaxResult yesterday() { src/main/java/com/ruoyi/http/service/StatisticEleService.java
@@ -1,5 +1,6 @@ package com.ruoyi.http.service; import com.ruoyi.http.vo.StatisticEleAnalyticsVo; import com.ruoyi.http.vo.StatisticEleRecordVo; import com.ruoyi.http.vo.StatisticEleSummaryVo; import com.ruoyi.http.vo.StatisticEleSyncStatusVo; @@ -18,6 +19,8 @@ StatisticEleSummaryVo getSummary(String dimension, String startTime, String endTime); StatisticEleAnalyticsVo getAnalytics(String dimension, String startTime, String endTime, String trendGranularity); StatisticEleSummaryVo getYesterdaySummary(); void exportRecords(String dimension, String startTime, String endTime, HttpServletResponse response); 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; @@ -31,16 +34,17 @@ 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; @@ -76,22 +80,91 @@ 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; } /** @@ -108,13 +181,15 @@ ? StatisticEleAggregateUtil.aggregateHourToBuckets(hourRecords, StatisticEleAggregateUtil.HOUR_TO_HOUR) : StatisticEleAggregateUtil.aggregateHourToBuckets(hourRecords, StatisticEleAggregateUtil.HOUR_TO_DAY); return buildSummary(detailRecords, chartRecords); 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); src/main/java/com/ruoyi/http/util/StatisticEleAggregateUtil.java
@@ -34,6 +34,7 @@ String monthKey = HOUR_TO_MONTH.apply(tk); return monthKey != null ? toQuarterKey(monthKey) : null; }; public static final Function<String, String> HOUR_TO_WEEK = StatisticEleAnalyticsUtil.HOUR_TO_WEEK; /** * ææ¶é´æ¡¶æ±æ»ï¼å¤çµè¡¨åå¹¶ï¼ç¨äºå¾è¡¨ï¼ @@ -178,6 +179,7 @@ return switch (dimension) { case "hour" -> new HourRange(startTime, endTime); case "day" -> new HourRange(startTime + "00", endTime + "23"); case "week" -> new HourRange(startTime + "00", endTime + "23"); case "month" -> new HourRange(startTime + "0100", endTime + lastDayOfMonth(endTime) + "23"); case "year" -> new HourRange(startTime + "010100", endTime + "123123"); case "quarter" -> new HourRange( @@ -234,6 +236,7 @@ return switch (dimension) { case "hour" -> HOUR_TO_HOUR; case "day" -> HOUR_TO_DAY; case "week" -> HOUR_TO_WEEK; case "month" -> HOUR_TO_MONTH; case "quarter" -> HOUR_TO_QUARTER; case "year" -> HOUR_TO_YEAR; src/main/java/com/ruoyi/http/util/StatisticEleAnalyticsUtil.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,288 @@ package com.ruoyi.http.util; import com.ruoyi.http.vo.StatisticEleComparisonVo; import com.ruoyi.http.vo.StatisticEleRecordVo; import com.ruoyi.http.vo.StatisticEleSplitItemVo; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.DayOfWeek; import java.time.LocalDate; import java.time.YearMonth; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.time.temporal.WeekFields; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.function.Function; /** * è½è综ååæè®¡ç® */ public final class StatisticEleAnalyticsUtil { private static final DateTimeFormatter DAY_FMT = DateTimeFormatter.ofPattern("yyyyMMdd"); private static final int SUMMARY_SCALE = 2; /** ç½ç 08:00-19:59 */ private static final int DAY_SHIFT_START = 8; private static final int DAY_SHIFT_END = 19; private StatisticEleAnalyticsUtil() { } public static final Function<String, String> HOUR_TO_WEEK = tk -> { if (tk == null || tk.length() < 8) { return null; } LocalDate date = LocalDate.parse(tk.substring(0, 8), DAY_FMT); WeekFields wf = WeekFields.of(Locale.CHINA); int week = date.get(wf.weekOfWeekBasedYear()); int year = date.get(wf.weekBasedYear()); return String.format("%04dW%02d", year, week); }; public static Function<String, String> trendBucketFn(String granularity) { return switch (granularity) { case "hour" -> StatisticEleAggregateUtil.HOUR_TO_HOUR; case "week" -> HOUR_TO_WEEK; case "month" -> StatisticEleAggregateUtil.HOUR_TO_MONTH; case "year" -> StatisticEleAggregateUtil.HOUR_TO_YEAR; default -> StatisticEleAggregateUtil.HOUR_TO_DAY; }; } /** * å¨æç´¯è®¡æ¥èªæ±æ»æ¡¶ï¼æå¼/åå¼å§ç»æ¥èªå°æ¶æ¡¶ã */ public static StatisticEleAggregateUtil.StatisticEleSummaryMetrics calcCombinedMetrics( List<StatisticEleRecordVo> hourRecords, List<StatisticEleRecordVo> periodChartRecords) { List<StatisticEleRecordVo> hourlyBuckets = StatisticEleAggregateUtil.aggregateHourToBuckets( hourRecords, StatisticEleAggregateUtil.HOUR_TO_HOUR); StatisticEleAggregateUtil.StatisticEleSummaryMetrics hourMetrics = StatisticEleAggregateUtil.calcMetrics(hourlyBuckets); StatisticEleAggregateUtil.StatisticEleSummaryMetrics periodMetrics = StatisticEleAggregateUtil.calcMetrics(periodChartRecords); StatisticEleAggregateUtil.StatisticEleSummaryMetrics result = new StatisticEleAggregateUtil.StatisticEleSummaryMetrics(); result.setRecordCount(periodMetrics.getRecordCount()); result.setTotalConsumption(hourMetrics.getTotalConsumption()); result.setAvgConsumption(hourMetrics.getAvgConsumption()); result.setMaxConsumption(hourMetrics.getMaxConsumption()); result.setMinConsumption(hourMetrics.getMinConsumption()); return result; } public static double calcLoadRate(Double avgHourly, Double maxHourly) { if (avgHourly == null || maxHourly == null || maxHourly <= 0) { return 0.0; } return roundSummary(BigDecimal.valueOf(avgHourly) .divide(BigDecimal.valueOf(maxHourly), SUMMARY_SCALE + 2, RoundingMode.HALF_UP) .multiply(BigDecimal.valueOf(100))); } public static List<StatisticEleSplitItemVo> calcPeriodSplits(List<StatisticEleRecordVo> hourRecords) { double sharp = sumField(hourRecords, StatisticEleRecordVo::getSharpConsumption); double peak = sumField(hourRecords, StatisticEleRecordVo::getPeakConsumption); double flat = sumField(hourRecords, StatisticEleRecordVo::getFlatConsumption); double valley = sumField(hourRecords, StatisticEleRecordVo::getValleyConsumption); double total = sharp + peak + flat + valley; if (total <= 0) { total = sumField(hourRecords, StatisticEleRecordVo::getTotalConsumption); } List<StatisticEleSplitItemVo> items = new ArrayList<>(); addSplitItem(items, "å°", sharp, total); addSplitItem(items, "å³°", peak, total); addSplitItem(items, "å¹³", flat, total); addSplitItem(items, "è°·", valley, total); return items.stream().filter(i -> i.getConsumption() != null && i.getConsumption() > 0).toList(); } public static List<StatisticEleSplitItemVo> calcShiftSplits(List<StatisticEleRecordVo> hourRecords) { Map<String, Double> map = new LinkedHashMap<>(); map.put("ç½ç", 0.0); map.put("å¤ç", 0.0); for (StatisticEleRecordVo record : hourRecords) { int hour = parseHour(record.getTimeKey()); if (hour < 0) { continue; } double val = safe(record.getTotalConsumption()); if (hour >= DAY_SHIFT_START && hour <= DAY_SHIFT_END) { map.merge("ç½ç", val, Double::sum); } else { map.merge("å¤ç", val, Double::sum); } } return toSplitItems(map); } public static List<StatisticEleSplitItemVo> calcDayTypeSplits(List<StatisticEleRecordVo> hourRecords) { Map<String, Double> map = new LinkedHashMap<>(); map.put("工使¥", 0.0); map.put("伿¯æ¥", 0.0); for (StatisticEleRecordVo record : hourRecords) { LocalDate date = parseDate(record.getTimeKey()); if (date == null) { continue; } double val = safe(record.getTotalConsumption()); DayOfWeek dow = date.getDayOfWeek(); if (dow == DayOfWeek.SATURDAY || dow == DayOfWeek.SUNDAY) { map.merge("伿¯æ¥", val, Double::sum); } else { map.merge("工使¥", val, Double::sum); } } return toSplitItems(map); } public static StatisticEleComparisonVo buildComparison( String type, String label, Double currentTotal, Double compareTotal) { StatisticEleComparisonVo vo = new StatisticEleComparisonVo(); vo.setType(type); vo.setLabel(label); vo.setCurrentTotal(round(currentTotal)); vo.setCompareTotal(round(compareTotal)); double delta = round(safe(currentTotal) - safe(compareTotal)); vo.setDelta(delta); if (compareTotal != null && compareTotal > 0) { vo.setChangeRate(roundSummary(BigDecimal.valueOf(delta) .divide(BigDecimal.valueOf(compareTotal), SUMMARY_SCALE + 2, RoundingMode.HALF_UP) .multiply(BigDecimal.valueOf(100)))); } else { vo.setChangeRate(currentTotal != null && currentTotal > 0 ? 100.0 : 0.0); } return vo; } public record DateBounds(LocalDate start, LocalDate end) {} public static DateBounds resolveBounds(String dimension, String startTime, String endTime) { LocalDate start = resolveStartDate(dimension, startTime); LocalDate end = resolveEndDate(dimension, endTime); if (start.isAfter(end)) { LocalDate tmp = start; start = end; end = tmp; } return new DateBounds(start, end); } public static DateBounds shiftChain(DateBounds bounds) { long days = ChronoUnit.DAYS.between(bounds.start(), bounds.end()) + 1; return new DateBounds(bounds.start().minusDays(days), bounds.start().minusDays(1)); } public static DateBounds shiftYoy(DateBounds bounds) { return new DateBounds(bounds.start().minusYears(1), bounds.end().minusYears(1)); } public static String defaultTrendGranularity(String dimension, boolean singleDay) { if (singleDay) { return "hour"; } return switch (dimension) { case "week", "day" -> "day"; case "month", "quarter" -> "week"; case "year" -> "month"; default -> "day"; }; } private static LocalDate resolveStartDate(String dimension, String startTime) { return switch (dimension) { case "year" -> LocalDate.of(Integer.parseInt(startTime), 1, 1); case "month" -> YearMonth.parse(startTime, DateTimeFormatter.ofPattern("yyyyMM")).atDay(1); default -> LocalDate.parse(normalizeDayKey(startTime), DAY_FMT); }; } private static LocalDate resolveEndDate(String dimension, String endTime) { return switch (dimension) { case "year" -> LocalDate.of(Integer.parseInt(endTime), 12, 31); case "month" -> YearMonth.parse(endTime, DateTimeFormatter.ofPattern("yyyyMM")).atEndOfMonth(); default -> LocalDate.parse(normalizeDayKey(endTime), DAY_FMT); }; } private static String normalizeDayKey(String timeKey) { if (timeKey == null) { return LocalDate.now().format(DAY_FMT); } if (timeKey.length() == 4) { return timeKey + "0101"; } if (timeKey.length() == 6) { return timeKey + "01"; } return timeKey.length() >= 8 ? timeKey.substring(0, 8) : timeKey; } private static List<StatisticEleSplitItemVo> toSplitItems(Map<String, Double> map) { double total = map.values().stream().mapToDouble(v -> v).sum(); List<StatisticEleSplitItemVo> items = new ArrayList<>(); map.forEach((name, val) -> addSplitItem(items, name, val, total)); return items; } private static void addSplitItem(List<StatisticEleSplitItemVo> items, String name, double val, double total) { if (val <= 0) { return; } StatisticEleSplitItemVo item = new StatisticEleSplitItemVo(); item.setName(name); item.setConsumption(round(val)); item.setRatio(total > 0 ? roundSummary(BigDecimal.valueOf(val) .divide(BigDecimal.valueOf(total), SUMMARY_SCALE + 2, RoundingMode.HALF_UP) .multiply(BigDecimal.valueOf(100))) : 0.0); items.add(item); } private static double sumField(List<StatisticEleRecordVo> records, Function<StatisticEleRecordVo, Double> getter) { return records.stream().map(getter).mapToDouble(StatisticEleAnalyticsUtil::safe).sum(); } private static int parseHour(String timeKey) { if (timeKey == null || timeKey.length() < 10) { return -1; } try { return Integer.parseInt(timeKey.substring(8, 10)); } catch (NumberFormatException e) { return -1; } } private static LocalDate parseDate(String timeKey) { if (timeKey == null || timeKey.length() < 8) { return null; } try { return LocalDate.parse(timeKey.substring(0, 8), DAY_FMT); } catch (Exception e) { return null; } } private static double safe(Double v) { return v == null ? 0.0 : v; } private static double round(Double v) { if (v == null) { return 0.0; } return roundSummary(BigDecimal.valueOf(v)); } private static double roundSummary(BigDecimal value) { return value.setScale(SUMMARY_SCALE, RoundingMode.HALF_UP).doubleValue(); } } src/main/java/com/ruoyi/http/vo/StatisticEleAnalyticsVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,38 @@ package com.ruoyi.http.vo; import lombok.Data; import lombok.EqualsAndHashCode; import java.util.List; /** * è½è综ååæç»æ */ @Data @EqualsAndHashCode(callSuper = true) public class StatisticEleAnalyticsVo extends StatisticEleSummaryVo { /** è´è·ç = å°æ¶å¹³å ÷ å°æ¶æå¤§ */ private Double loadRate; /** å³°å¹³è°·å°æå */ private List<StatisticEleSplitItemVo> periodSplits; /** ç½ç/å¤çæå */ private List<StatisticEleSplitItemVo> shiftSplits; /** 工使¥/伿¯æ¥æå */ private List<StatisticEleSplitItemVo> dayTypeSplits; /** ç¯æ¯ */ private StatisticEleComparisonVo chainComparison; /** 忝 */ private StatisticEleComparisonVo yoyComparison; /** è¶å¿å¾ç²åº¦ */ private String trendGranularity; /** è¶å¿å¾æ°æ®ï¼æ trendGranularity èåï¼ */ private List<StatisticEleRecordVo> trendRecords; } src/main/java/com/ruoyi/http/vo/StatisticEleComparisonVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,28 @@ package com.ruoyi.http.vo; import lombok.Data; /** * 忝/ç¯æ¯å¯¹æ¯ */ @Data public class StatisticEleComparisonVo { /** 对æ¯ç±»åï¼chain-ç¯æ¯, yoy-忝 */ private String type; /** å¯¹æ¯ææ ç¾ï¼å¦ã䏿ããå»å¹´åæã */ private String label; /** å¯¹æ¯ææ»ç¨çµé(kWh) */ private Double compareTotal; /** æ¬ææ»ç¨çµé(kWh) */ private Double currentTotal; /** å·®å¼(kWh)ï¼æ¬æ-å¯¹æ¯æ */ private Double delta; /** ååç(%) */ private Double changeRate; } src/main/java/com/ruoyi/http/vo/StatisticEleSplitItemVo.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,18 @@ package com.ruoyi.http.vo; import lombok.Data; /** * ç¨çµéæåé¡¹ï¼æ¶æ®µ/çæ¬¡/æ¥ç±»åçï¼ */ @Data public class StatisticEleSplitItemVo { private String name; /** ç¨çµé(kWh) */ private Double consumption; /** å æ¯(%) */ private Double ratio; }