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

diff --git a/src/main/java/com/ruoyi/http/service/impl/TqdianbiaoEleRecordManageServiceImpl.java b/src/main/java/com/ruoyi/http/service/impl/TqdianbiaoEleRecordManageServiceImpl.java
new file mode 100644
index 0000000..43ec32c
--- /dev/null
+++ b/src/main/java/com/ruoyi/http/service/impl/TqdianbiaoEleRecordManageServiceImpl.java
@@ -0,0 +1,140 @@
+package com.ruoyi.http.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+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.TqdianbiaoEleRecordManageService;
+import com.ruoyi.http.util.StatisticEleReadingUtil;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Set;
+
+@Service
+public class TqdianbiaoEleRecordManageServiceImpl
+        extends ServiceImpl<TqdianbiaoEleRecordMapper, TqdianbiaoEleRecord>
+        implements TqdianbiaoEleRecordManageService {
+
+    private static final Set<String> MANUAL_DIMENSIONS = Set.of("manual");
+
+    private final TqdianbiaoMeterMapper meterMapper;
+
+    public TqdianbiaoEleRecordManageServiceImpl(TqdianbiaoMeterMapper meterMapper) {
+        this.meterMapper = meterMapper;
+    }
+
+    @Override
+    public IPage<TqdianbiaoEleRecord> listPage(Page page, TqdianbiaoEleRecord query) {
+        return page(page, Wrappers.<TqdianbiaoEleRecord>lambdaQuery()
+                .eq(StringUtils.isNotEmpty(query.getDimension()), TqdianbiaoEleRecord::getDimension, query.getDimension())
+                .eq(query.getMeterId() != null, TqdianbiaoEleRecord::getMeterId, query.getMeterId())
+                .ge(StringUtils.isNotEmpty(query.getStartTimeKey()), TqdianbiaoEleRecord::getTimeKey, query.getStartTimeKey())
+                .le(StringUtils.isNotEmpty(query.getEndTimeKey()), TqdianbiaoEleRecord::getTimeKey, query.getEndTimeKey())
+                .orderByDesc(TqdianbiaoEleRecord::getTimeKey));
+    }
+
+    @Override
+    public boolean addRecord(TqdianbiaoEleRecord record) {
+        validateRecord(record);
+        enrichFromMeter(record);
+        if (existsUnique(record, null)) {
+            throw new ServiceException("璇ョ數琛ㄥ湪璇ユ椂闂寸偣宸插瓨鍦ㄨ褰�");
+        }
+        record.setSyncTime(LocalDateTime.now());
+        return save(record);
+    }
+
+    @Override
+    public boolean updateRecord(TqdianbiaoEleRecord record) {
+        if (record.getId() == null) {
+            throw new ServiceException("ID涓嶈兘涓虹┖");
+        }
+        validateRecord(record);
+        enrichFromMeter(record);
+        if (existsUnique(record, record.getId())) {
+            throw new ServiceException("璇ョ數琛ㄥ湪璇ユ椂闂寸偣宸插瓨鍦ㄨ褰�");
+        }
+        record.setSyncTime(LocalDateTime.now());
+        return updateById(record);
+    }
+
+    @Override
+    public boolean deleteByIds(List<Long> ids) {
+        if (CollectionUtils.isEmpty(ids)) {
+            throw new ServiceException("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+        }
+        return removeBatchByIds(ids);
+    }
+
+    @Override
+    public BigDecimal getPrevReading(Long meterId, String timeKey) {
+        if (meterId == null || StringUtils.isEmpty(timeKey)) {
+            return null;
+        }
+        TqdianbiaoEleRecord prev = baseMapper.selectPrevReading(meterId, timeKey);
+        if (prev == null) {
+            return null;
+        }
+        if (prev.getCurrReading() != null) {
+            return prev.getCurrReading();
+        }
+        return StatisticEleReadingUtil.parseFirstReading(prev.getEndReading());
+    }
+
+    private void enrichFromMeter(TqdianbiaoEleRecord record) {
+        TqdianbiaoMeter meter = meterMapper.selectOne(
+                Wrappers.<TqdianbiaoMeter>lambdaQuery()
+                        .eq(TqdianbiaoMeter::getMeterId, record.getMeterId())
+                        .last("LIMIT 1"));
+        if (meter != null) {
+            record.setMeterName(meter.getMeterName());
+            if (record.getRatio() == null && meter.getRate() != null) {
+                record.setRatio(meter.getRate());
+            }
+        }
+        if (record.getPrevReading() != null && record.getCurrReading() != null) {
+            record.setTotalConsumption(
+                    StatisticEleReadingUtil.calcConsumption(record.getPrevReading(), record.getCurrReading(), record.getRatio()));
+        }
+    }
+
+    private void validateRecord(TqdianbiaoEleRecord record) {
+        if (record.getMeterId() == null) {
+            throw new ServiceException("鐢佃〃涓嶈兘涓虹┖");
+        }
+        if (StringUtils.isEmpty(record.getDimension()) || !MANUAL_DIMENSIONS.contains(record.getDimension())) {
+            throw new ServiceException("浠呮敮鎸佹墜鍔ㄥ綍鍏�(manual)缁村害鏁版嵁");
+        }
+        if (StringUtils.isEmpty(record.getTimeKey())) {
+            throw new ServiceException("鏃堕棿鏍囪瘑涓嶈兘涓虹┖");
+        }
+        if (record.getTimeKey().length() != 12) {
+            throw new ServiceException("鎵嬪姩褰曞叆鏃堕棿鏍囪瘑鏍煎紡搴斾负 YYYYMMDDHHmm");
+        }
+        if (record.getCurrReading() == null) {
+            throw new ServiceException("鏈鐢甸噺涓嶈兘涓虹┖");
+        }
+        if (record.getPrevReading() == null) {
+            throw new ServiceException("涓婃鐢甸噺涓嶈兘涓虹┖");
+        }
+        record.setReadingMethod("manual");
+    }
+
+    private boolean existsUnique(TqdianbiaoEleRecord record, Long excludeId) {
+        return count(Wrappers.<TqdianbiaoEleRecord>lambdaQuery()
+                .eq(TqdianbiaoEleRecord::getMeterId, record.getMeterId())
+                .eq(TqdianbiaoEleRecord::getDimension, record.getDimension())
+                .eq(TqdianbiaoEleRecord::getTimeKey, record.getTimeKey())
+                .ne(excludeId != null, TqdianbiaoEleRecord::getId, excludeId)) > 0;
+    }
+}

--
Gitblit v1.9.3