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/TqdianbiaoEleSyncServiceImpl.java |  155 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 155 insertions(+), 0 deletions(-)

diff --git a/src/main/java/com/ruoyi/http/service/impl/TqdianbiaoEleSyncServiceImpl.java b/src/main/java/com/ruoyi/http/service/impl/TqdianbiaoEleSyncServiceImpl.java
new file mode 100644
index 0000000..406e027
--- /dev/null
+++ b/src/main/java/com/ruoyi/http/service/impl/TqdianbiaoEleSyncServiceImpl.java
@@ -0,0 +1,155 @@
+package com.ruoyi.http.service.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ruoyi.common.utils.http.HttpUtils;
+import com.ruoyi.http.config.TqdianbiaoConfig;
+import com.ruoyi.http.mapper.TqdianbiaoEleRecordMapper;
+import com.ruoyi.http.mapper.TqdianbiaoMeterMapper;
+import com.ruoyi.http.pojo.TqdianbiaoEleRecord;
+import com.ruoyi.http.pojo.TqdianbiaoMeter;
+import com.ruoyi.http.service.TqdianbiaoEleSyncService;
+import com.ruoyi.http.service.TqdianbiaoSyncLogService;
+import com.ruoyi.http.util.StatisticEleParseUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class TqdianbiaoEleSyncServiceImpl implements TqdianbiaoEleSyncService {
+
+    private static final DateTimeFormatter HOUR_FMT = DateTimeFormatter.ofPattern("yyyyMMddHH");
+    private static final DateTimeFormatter DAY_FMT = DateTimeFormatter.ofPattern("yyyyMMdd");
+    private static final DateTimeFormatter MONTH_FMT = DateTimeFormatter.ofPattern("yyyyMM");
+    private static final DateTimeFormatter YEAR_FMT = DateTimeFormatter.ofPattern("yyyy");
+
+    private final TqdianbiaoConfig config;
+    private final TqdianbiaoEleRecordMapper eleRecordMapper;
+    private final TqdianbiaoMeterMapper meterMapper;
+    private final TqdianbiaoSyncLogService syncLogService;
+
+    @Override
+    public int syncHourData() {
+        int window = config.getSync().getHourWindow() != null ? config.getSync().getHourWindow() : 1;
+        if (window < 1) {
+            window = 1;
+        }
+        // 缁撴潫浜庝笂涓�瀹屾暣灏忔椂锛屼笉鍖呭惈褰撳墠鏈粨鏉熺殑灏忔椂
+        LocalDateTime currentHourStart = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0);
+        LocalDateTime end = currentHourStart.minusHours(1);
+        LocalDateTime start = end.minusHours(window - 1L);
+        String startTime = start.format(HOUR_FMT);
+        String endTime = end.format(HOUR_FMT);
+        return syncDimension("hour", startTime, endTime);
+    }
+
+    @Override
+    public int syncLast3DaysHourData() {
+        LocalDateTime start = LocalDate.now().minusDays(3).atStartOfDay();
+        LocalDateTime end = LocalDateTime.now().withMinute(0).withSecond(0).withNano(0);
+        return syncHourRangeInChunks(start, end);
+    }
+
+    /** 鎸夋渶澶� 24 灏忔椂涓�娈靛垎鎵规媺鍙栵紙骞冲彴鎺ュ彛闄愬埗锛� */
+    private int syncHourRangeInChunks(LocalDateTime start, LocalDateTime end) {
+        int total = 0;
+        LocalDateTime windowStart = start;
+        while (!windowStart.isAfter(end)) {
+            LocalDateTime windowEnd = windowStart.plusHours(23);
+            if (windowEnd.isAfter(end)) {
+                windowEnd = end;
+            }
+            total += syncDimension("hour", windowStart.format(HOUR_FMT), windowEnd.format(HOUR_FMT));
+            windowStart = windowEnd.plusHours(1);
+        }
+        return total;
+    }
+
+    @Override
+    public int syncDayData() {
+        LocalDate yesterday = LocalDate.now().minusDays(1);
+        String day = yesterday.format(DAY_FMT);
+        return syncDimension("day", day, day);
+    }
+
+    @Override
+    public int syncMonthData() {
+        LocalDate now = LocalDate.now();
+        String month = now.format(MONTH_FMT);
+        return syncDimension("month", month, month);
+    }
+
+    @Override
+    public int syncYearData() {
+        LocalDate now = LocalDate.now();
+        String year = now.format(YEAR_FMT);
+        return syncDimension("year", year, year);
+    }
+
+    private int syncDimension(String dimension, String startTime, String endTime) {
+        return syncDimension(dimension, startTime, endTime, config.getIgnoreRadio());
+    }
+
+    private int syncDimension(String dimension, String startTime, String endTime, int ignoreRadio) {
+        try {
+            String url = config.getBaseUrl() + "/Api/StatisticEle/" + dimension;
+            String param = String.format(
+                    "auth=%s&start_time=%s&end_time=%s&ignore_radio=%d",
+                    config.getAuth(), startTime, endTime, ignoreRadio
+            );
+            log.info("鍚屾鐢甸噺鏁版嵁: {} {}-{} ignore_radio={}", dimension, startTime, endTime, ignoreRadio);
+            String raw = HttpUtils.sendGet(url, param);
+            List<TqdianbiaoEleRecord> records = StatisticEleParseUtil.parseToEntities(raw, dimension);
+            enrichMeterInfo(records);
+            int count = upsertRecords(records);
+            syncLogService.logSuccess(dimension, startTime, endTime, count);
+            return count;
+        } catch (Exception e) {
+            log.error("鐢甸噺鍚屾澶辫触 dimension={} {}-{}", dimension, startTime, endTime, e);
+            syncLogService.logFailure(dimension, startTime, endTime, e.getMessage());
+            throw e;
+        }
+    }
+
+    private void enrichMeterInfo(List<TqdianbiaoEleRecord> records) {
+        for (TqdianbiaoEleRecord record : records) {
+            if (record.getMeterId() == null) {
+                continue;
+            }
+            TqdianbiaoMeter meter = meterMapper.selectOne(
+                    Wrappers.<TqdianbiaoMeter>lambdaQuery()
+                            .eq(TqdianbiaoMeter::getMeterId, record.getMeterId())
+                            .last("LIMIT 1"));
+            if (meter != null && StringUtils.hasText(meter.getMeterName())) {
+                record.setMeterName(meter.getMeterName());
+            }
+        }
+    }
+
+    private int upsertRecords(List<TqdianbiaoEleRecord> records) {
+        int count = 0;
+        for (TqdianbiaoEleRecord record : records) {
+            TqdianbiaoEleRecord existing = eleRecordMapper.selectOne(
+                    Wrappers.<TqdianbiaoEleRecord>lambdaQuery()
+                            .eq(TqdianbiaoEleRecord::getMeterId, record.getMeterId())
+                            .eq(TqdianbiaoEleRecord::getDimension, record.getDimension())
+                            .eq(TqdianbiaoEleRecord::getTimeKey, record.getTimeKey())
+                            .last("LIMIT 1"));
+            if (existing == null) {
+                eleRecordMapper.insert(record);
+            } else {
+                record.setId(existing.getId());
+                eleRecordMapper.updateById(record);
+            }
+            count++;
+        }
+        return count;
+    }
+}

--
Gitblit v1.9.3