| src/main/java/com/ruoyi/http/controller/TqdianbiaoEleRecordController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/http/service/impl/StatisticEleServiceImpl.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/http/task/TqdianbiaoSyncTask.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/http/util/StatisticEleAggregateUtil.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/http/util/StatisticEleParseUtil.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/ruoyi/http/util/StatisticEleReadingUtil.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/resources/application-zqsy.yml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/main/java/com/ruoyi/http/controller/TqdianbiaoEleRecordController.java
@@ -7,6 +7,7 @@ import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.http.pojo.TqdianbiaoEleRecord; import com.ruoyi.http.service.TqdianbiaoEleRecordManageService; import com.ruoyi.http.service.TqdianbiaoEleSyncService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -17,7 +18,12 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.HashMap; import java.util.List; import java.util.Map; @RestController @Tag(name = "电量记录管理") @@ -25,7 +31,10 @@ @RequiredArgsConstructor public class TqdianbiaoEleRecordController extends BaseController { private static final DateTimeFormatter HOUR_FMT = DateTimeFormatter.ofPattern("yyyyMMddHH"); private final TqdianbiaoEleRecordManageService eleRecordManageService; private final TqdianbiaoEleSyncService eleSyncService; @GetMapping("/listPage") @Operation(summary = "电量记录-分页查询") @@ -56,4 +65,18 @@ public AjaxResult prevReading(Long meterId, String timeKey) { return AjaxResult.success(eleRecordManageService.getPrevReading(meterId, timeKey)); } @PostMapping("/syncRecentOnce") @Log(title = "电量记录-近三天补数", businessType = BusinessType.OTHER) @Operation(summary = "同步前三天至当前小时电量(一次性补数)") public AjaxResult syncRecentOnce() { LocalDateTime start = LocalDate.now().minusDays(3).atStartOfDay(); LocalDateTime end = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0); int count = eleSyncService.syncLast3DaysHourData(); Map<String, Object> data = new HashMap<>(); data.put("count", count); data.put("startTime", start.format(HOUR_FMT)); data.put("endTime", end.format(HOUR_FMT)); return AjaxResult.success("同步完成:" + data.get("startTime") + " ~ " + data.get("endTime") + " 共 " + count + " 条", data); } } src/main/java/com/ruoyi/http/service/impl/StatisticEleServiceImpl.java
@@ -163,7 +163,9 @@ private List<StatisticEleRecordVo> queryHourRecords(String startTime, String endTime) { String normalizedStart = StatisticEleAggregateUtil.normalizeQueryStartTimeKey(startTime); String normalizedEnd = StatisticEleAggregateUtil.normalizeQueryEndTimeKey(endTime); return eleRecordMapper.selectRecordList(DATA_DIMENSIONS, normalizedStart, normalizedEnd); List<StatisticEleRecordVo> records = eleRecordMapper.selectRecordList(DATA_DIMENSIONS, normalizedStart, normalizedEnd); StatisticEleAggregateUtil.normalizeConsumptions(records); return records; } private List<StatisticEleRecordVo> aggregateFromHour( src/main/java/com/ruoyi/http/task/TqdianbiaoSyncTask.java
@@ -22,7 +22,7 @@ private final TqdianbiaoMeterSyncService meterSyncService; private final TqdianbiaoEleSyncService eleSyncService; @Scheduled(cron = "30 5 * * * ?") //@Scheduled(cron = "30 5 * * * ?") public void syncCollectors() { if (!isEnabled()) return; try { 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() { } @@ -144,11 +148,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 +184,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 +219,7 @@ private static List<StatisticEleRecordVo> sorted(Map<String, StatisticEleRecordVo> map) { return map.values().stream() .peek(vo -> normalizeConsumptions(vo)) .sorted(Comparator.comparing(StatisticEleRecordVo::getTimeKey)) .collect(Collectors.toList()); } @@ -222,11 +230,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) {} src/main/java/com/ruoyi/http/util/StatisticEleParseUtil.java
@@ -8,6 +8,7 @@ import com.ruoyi.http.vo.StatisticEleRecordVo; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Comparator; @@ -99,24 +100,33 @@ private static void fillConsumption(TqdianbiaoEleRecord entity, JSONArray d, Integer ratio, JSONArray sArr, JSONArray eArr) { BigDecimal rawTotal = null; if (d != null && !d.isEmpty()) { rawTotal = d.getBigDecimal(0); entity.setSharpConsumption(d.size() >= 2 ? d.getBigDecimal(1) : null); entity.setPeakConsumption(d.size() >= 3 ? d.getBigDecimal(2) : null); entity.setFlatConsumption(d.size() >= 4 ? d.getBigDecimal(3) : null); entity.setValleyConsumption(d.size() >= 5 ? d.getBigDecimal(4) : null); entity.setDeepValleyConsumption(d.size() >= 6 ? d.getBigDecimal(5) : null); entity.setTotalConsumption(StatisticEleReadingUtil.calcConsumptionFromRaw(d.getBigDecimal(0), ratio)); entity.setSharpConsumption(consumptionAt(d, 1, ratio)); entity.setPeakConsumption(consumptionAt(d, 2, ratio)); entity.setFlatConsumption(consumptionAt(d, 3, ratio)); entity.setValleyConsumption(consumptionAt(d, 4, ratio)); entity.setDeepValleyConsumption(consumptionAt(d, 5, ratio)); } else { rawTotal = StatisticEleReadingUtil.calcConsumption( BigDecimal rawTotal = StatisticEleReadingUtil.calcConsumption( StatisticEleReadingUtil.firstReading(sArr), StatisticEleReadingUtil.firstReading(eArr), 1); entity.setTotalConsumption(StatisticEleReadingUtil.calcConsumptionFromRaw(rawTotal, ratio)); } entity.setTotalConsumption(StatisticEleReadingUtil.calcConsumptionFromRaw(rawTotal, ratio)); } private static BigDecimal consumptionAt(JSONArray d, int index, Integer ratio) { if (d.size() <= index) { return null; } return StatisticEleReadingUtil.calcConsumptionFromRaw(d.getBigDecimal(index), ratio); } private static Double toDouble(BigDecimal value) { return value == null ? null : value.doubleValue(); if (value == null) { return null; } return value.setScale(StatisticEleReadingUtil.CONSUMPTION_SCALE, RoundingMode.HALF_UP).doubleValue(); } } src/main/java/com/ruoyi/http/util/StatisticEleReadingUtil.java
@@ -10,6 +10,8 @@ */ public final class StatisticEleReadingUtil { public static final int CONSUMPTION_SCALE = 4; private StatisticEleReadingUtil() { } @@ -40,7 +42,7 @@ return null; } int r = ratio == null || ratio <= 0 ? 1 : ratio; return value.multiply(BigDecimal.valueOf(r)).setScale(4, RoundingMode.HALF_UP); return value.multiply(BigDecimal.valueOf(r)).setScale(CONSUMPTION_SCALE, RoundingMode.HALF_UP); } public static String formatReadingArray(JSONArray arr) { src/main/resources/application-zqsy.yml
@@ -267,3 +267,11 @@ compressQuality: 0.5 # 压缩质量(0.0-1.0) knowledge: one: D:\新疆大罗素企业产品体系说明文档.md tqdianbiao: base-url: https://168.tqdianbiao.com auth: b6229401590539d5def7f2bf897b33de ignore-radio: 1 sync: enabled: true hour-window: 2