From 75f043dfa6660716364e66ee0b3cf99f44255686 Mon Sep 17 00:00:00 2001
From: DYL0109 <dn18191638832@163.com>
Date: 星期三, 16 四月 2025 19:20:36 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/develop1.0' into dyl_dev

---
 zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/service/impl/EnergyConsumeDataServiceImpl.java |  498 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 498 insertions(+), 0 deletions(-)

diff --git a/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/service/impl/EnergyConsumeDataServiceImpl.java b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/service/impl/EnergyConsumeDataServiceImpl.java
new file mode 100644
index 0000000..94fcfe6
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/service/impl/EnergyConsumeDataServiceImpl.java
@@ -0,0 +1,498 @@
+package com.zhitan.statisticalAnalysis.service.impl;
+
+import cn.hutool.core.date.DateField;
+import cn.hutool.core.date.DateUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.zhitan.basicdata.domain.SysEnergy;
+import com.zhitan.basicdata.mapper.SysEnergyMapper;
+import com.zhitan.carbonemission.domain.CarbonEmission;
+import com.zhitan.common.constant.CommonConst;
+import com.zhitan.common.constant.TimeTypeConst;
+import com.zhitan.common.utils.StringUtils;
+import com.zhitan.dataitem.mapper.DataItemMapper;
+import com.zhitan.model.domain.ModelNode;
+import com.zhitan.model.domain.NodeIndex;
+import com.zhitan.model.mapper.ModelNodeMapper;
+import com.zhitan.model.mapper.NodeIndexMapper;
+import com.zhitan.peakvalley.domain.ElectricityDataItem;
+import com.zhitan.peakvalley.mapper.PeakValleyMapper;
+import com.zhitan.statisticalAnalysis.common.DateTimeUtil;
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang3.ObjectUtils;
+import com.zhitan.statisticalAnalysis.domain.vo.*;
+import com.zhitan.statisticalAnalysis.service.IEnergyConsumeDataService;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @Description: TODO
+ * @author: yxw
+ * @date: 2022骞�04鏈�12鏃� 14:15
+ */
+@Service
+@AllArgsConstructor
+public class EnergyConsumeDataServiceImpl implements IEnergyConsumeDataService {
+
+    private DataItemMapper dataItemMapper;
+    private ModelNodeMapper modelNodeMapper;
+    private NodeIndexMapper nodeIndexMapper;
+    private PeakValleyMapper peakValleyMapper;
+    private SysEnergyMapper sysEnergyMapper;
+
+    /**
+     * 鎴愭湰瓒嬪娍鍒嗘瀽锛堣兘婧愭秷鑰楁垚鏈級- 鑾峰彇琛ㄦ牸鍒楄〃鏁版嵁
+     *
+     * @param pageNo     椤电爜鏁�
+     * @param pageSize   姣忛〉鏁版嵁澶氬皯
+     * @param timeCode   鏃堕棿鍊�   涓庢椂闂寸被鍨嬪搴旓細2022-03-21/2022-03/2022
+     * @param timeType   鏃堕棿绫诲瀷 DAY/MONTH/YEAR
+     * @param energyType 鑳芥簮绫诲瀷
+     * @param modelCode  妯″瀷Code
+     * @return
+     */
+    @Override
+    public EnergyCostTrendPage listEnergyCostTrend(int pageNo, int pageSize, String timeCode, String timeType, String energyType,
+                                                   String modelCode) {
+        //鑳芥簮绫诲瀷淇℃伅
+        SysEnergy sysEnergy = new SysEnergy();
+        if (StringUtils.isNotEmpty(energyType)) {
+            sysEnergy.setEnersno(energyType);
+        }
+        List<SysEnergy> sysEnergies = sysEnergyMapper.selectSysEnergyList(sysEnergy);
+        if (sysEnergies.isEmpty()) {
+            throw new RuntimeException("鏈煡璇㈠埌鑳芥簮淇℃伅");
+        }
+        //鑺傜偣淇℃伅
+        List<ModelNode> modelNodes = modelNodeMapper.selectList(Wrappers.<ModelNode>lambdaQuery().eq(ModelNode::getModelCode, modelCode)
+                .isNull(ModelNode::getParentId));
+        if (ObjectUtils.isEmpty(modelNodes)) {
+            throw new RuntimeException("鏈煡璇㈠埌鑺傜偣淇℃伅");
+        }
+        ModelNode modelNodeInfo = modelNodes.stream().findFirst().get();
+        //鐐逛綅淇℃伅
+        List<NodeIndex> nodeIndices = nodeIndexMapper.selectList(Wrappers.<NodeIndex>lambdaQuery()
+                .eq(NodeIndex::getNodeId, modelNodeInfo.getNodeId()));
+        if (nodeIndices.isEmpty()) {
+            throw new RuntimeException("鏈煡璇㈠埌鐐逛綅淇℃伅");
+        }
+
+        // 鎬昏垂鐢�
+        BigDecimal totalCost = BigDecimal.ZERO;
+        // 閬嶅巻鑳芥簮绫诲瀷
+        List<CostTrendEnergyTypeItem> itemList = new ArrayList<>();
+        for (SysEnergy sysEnergyInfo : sysEnergies) {
+            CostTrendEnergyTypeItem item = new CostTrendEnergyTypeItem();
+            item.setEnergyType(sysEnergyInfo.getEnersno());
+            item.setEnergyName(sysEnergyInfo.getEnername());
+            // 澶勭悊鏃堕棿
+            Date bsTime = DateTimeUtil.getTime(timeType, timeCode);
+            Date endTime = DateTimeUtil.getEndTimeByType(timeType, bsTime);
+            totalCost = getEnergyUnitCostTrendAnalysisValueInfo(timeType, bsTime, endTime, totalCost, nodeIndices, modelNodeInfo.getNodeId(), sysEnergyInfo, item);
+            itemList.add(item);
+        }
+        // 閬嶅巻鐢ㄨ兘鍗曞厓鑾峰彇琛ㄦ牸涓殑鏁版嵁
+        List<EnergyCostTrendItem> trendItemList = new ArrayList<>();
+        EnergyCostTrendItem energyCostTrendItem = new EnergyCostTrendItem();
+        energyCostTrendItem.setDateCode(timeCode);
+        energyCostTrendItem.setTotal(totalCost.setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP));
+        energyCostTrendItem.setItemList(itemList);
+        trendItemList.add(energyCostTrendItem);
+
+        EnergyCostTrendPage energyCostTrendPage = new EnergyCostTrendPage();
+        energyCostTrendPage.setTotal(1);
+        energyCostTrendPage.setItemList(trendItemList);
+        return energyCostTrendPage;
+    }
+
+    /**
+     * 鑾峰彇鐢ㄨ兘鍗曞厓鎴愭湰瓒嬪娍鍒嗘瀽绱Н閲忋�佽垂鐢ㄤ俊鎭�
+     *
+     * @param timeType      鏃堕棿绫诲瀷
+     * @param bsTime        寮�濮嬫椂闂�
+     * @param endTime       缁撴潫鏃堕棿
+     * @param totalCost     鎬昏垂鐢�
+     * @param nodeIndices   鑺傜偣鐐逛綅闆嗗悎
+     * @param nodeId        鑺傜偣id
+     * @param sysEnergyInfo 鑳芥簮绫诲瀷淇℃伅
+     * @param item          杩斿洖瀵硅薄
+     * @return
+     */
+    private BigDecimal getEnergyUnitCostTrendAnalysisValueInfo(String timeType, Date bsTime, Date endTime, BigDecimal totalCost,
+                                                               List<NodeIndex> nodeIndices, String nodeId, SysEnergy sysEnergyInfo,
+                                                               CostTrendEnergyTypeItem item) {
+        BigDecimal costValue = BigDecimal.ZERO;
+        BigDecimal accumulationValue = BigDecimal.ZERO;
+        //鐢碉細鍙湁HOUR鏁版嵁鏈夋晥锛涘叾浠栬兘婧愮被鍨嬶細HOUR銆丏AY鏈夋暟鎹�
+        switch (sysEnergyInfo.getEnersno()) {
+            case "electric":
+                List<ElectricityDataItem> electricityDataItems = peakValleyMapper.getDataStatistics(nodeIndices.stream().map(NodeIndex::getIndexId).collect(Collectors.toSet()), bsTime, endTime, TimeTypeConst.TIME_TYPE_HOUR);
+                costValue = electricityDataItems.stream().map(ElectricityDataItem::getCost).reduce(BigDecimal.ZERO, BigDecimal::add);
+                accumulationValue = electricityDataItems.stream().map(ElectricityDataItem::getElectricity).reduce(BigDecimal.ZERO, BigDecimal::add);
+                break;
+            default:
+                accumulationValue = dataItemMapper.getDataItemTimeRangeValueByNodeId(bsTime, endTime, TimeTypeConst.TIME_TYPE_DAY, nodeId, sysEnergyInfo.getEnersno());
+                costValue = accumulationValue.multiply(sysEnergyInfo.getPrice());
+                break;
+        }
+        costValue = costValue.setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP);
+        totalCost = totalCost.add(costValue);
+        item.setCost(costValue);
+        item.setAccumulation(accumulationValue.setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP));
+        return totalCost;
+    }
+
+    /**
+     * 鎴愭湰瓒嬪娍鍒嗘瀽锛堣兘婧愭秷鑰楁垚鏈級
+     *
+     * @param timeCode   鏃堕棿鍊�   涓庢椂闂寸被鍨嬪搴旓細2022-03-21/2022-03/2022
+     * @param timeType   鏃堕棿绫诲瀷 DAY/MONTH/YEAR
+     * @param modelCode  妯″瀷Code
+     * @param energyType 鑳芥簮绫诲瀷
+     * @return
+     */
+    @Override
+    public List<EnergyConsumeTrendDetailItem> listEnergyCostTrendDetail(String timeCode, String timeType, String modelCode, String energyType) {
+        //鑳芥簮绫诲瀷淇℃伅
+        SysEnergy sysEnergy = new SysEnergy();
+        if (StringUtils.isNotEmpty(energyType)) {
+            sysEnergy.setEnersno(energyType);
+        }
+        List<SysEnergy> sysEnergies = sysEnergyMapper.selectSysEnergyList(sysEnergy);
+        if (sysEnergies.isEmpty()) {
+            throw new RuntimeException("鏈煡璇㈠埌鑳芥簮淇℃伅");
+        }
+
+        //鑺傜偣淇℃伅
+        List<ModelNode> modelNodes = modelNodeMapper.selectList(Wrappers.<ModelNode>lambdaQuery().eq(ModelNode::getModelCode, modelCode)
+                .isNull(ModelNode::getParentId));
+        if (modelNodes.isEmpty()) {
+            throw new RuntimeException("鏈煡璇㈠埌鑺傜偣淇℃伅");
+        }
+        String nodeId = modelNodes.stream().findFirst().get().getNodeId();
+
+        // 鑳借�椾俊鎭�
+        List<EnergyConsumeTrendDetailItem> itemList = new ArrayList<>();
+        Date startTime = DateTimeUtil.getTime(timeType, timeCode);
+        Date endTime = DateTimeUtil.getEndTimeByType(timeType, startTime);
+        //鐢碉細鍙湁HOUR鏁版嵁鏈夋晥锛涘叾浠栬兘婧愮被鍨嬶細HOUR銆丏AY鏈夋暟鎹�
+        String queryTimeType = TimeTypeConst.TIME_TYPE_HOUR;
+        for (SysEnergy sysEnergyInfo : sysEnergies) {
+            List<EnergyConsumeVO> energyConsumeVOList = new ArrayList<>();
+            switch (sysEnergyInfo.getEnersno()) {
+                case "electric":
+                    List<ElectricityDataItem> electricityDataItems = peakValleyMapper.getCostTrends(startTime, endTime, queryTimeType, nodeId, sysEnergyInfo.getEnersno());
+                    if (!electricityDataItems.isEmpty()) {
+                        electricityDataItems.forEach(electricityDataItem -> {
+                            EnergyConsumeVO temp = new EnergyConsumeVO();
+                            temp.setDataTime(electricityDataItem.getDataTime());
+                            temp.setCostValue(electricityDataItem.getCost());
+                            temp.setAccumulationValue(electricityDataItem.getElectricity());
+                            energyConsumeVOList.add(temp);
+                        });
+                    }
+                    break;
+                default:
+                    if (timeType.equals(TimeTypeConst.TIME_TYPE_MONTH) || timeType.equals(TimeTypeConst.TIME_TYPE_YEAR)) {
+                        queryTimeType = TimeTypeConst.TIME_TYPE_DAY;
+                    }
+                    List<CarbonEmission> dataItems = dataItemMapper.getMiddleCarbonEmission(startTime, endTime, queryTimeType, nodeId, sysEnergyInfo.getEnersno());
+                    if (!dataItems.isEmpty()) {
+                        dataItems.forEach(electricityDataItem -> {
+                            EnergyConsumeVO temp = new EnergyConsumeVO();
+                            temp.setDataTime(electricityDataItem.getDataTime());
+                            temp.setCostValue(new BigDecimal(electricityDataItem.getValue()));
+                            temp.setAccumulationValue(new BigDecimal(electricityDataItem.getValue()).multiply(sysEnergyInfo.getPrice()));
+                            energyConsumeVOList.add(temp);
+                        });
+                    }
+                    break;
+            }
+            BigDecimal cost = energyConsumeVOList.stream().map(EnergyConsumeVO::getCostValue)
+                    .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP);
+            BigDecimal accumulation = energyConsumeVOList.stream().map(EnergyConsumeVO::getAccumulationValue)
+                    .reduce(BigDecimal.ZERO, BigDecimal::add).setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP);
+            // 缁勮缁熻鍥句俊鎭�
+            EnergyConsumeTrendDetailItem item = new EnergyConsumeTrendDetailItem();
+            item.setEnergyType(sysEnergyInfo.getEnersno());
+            item.setEnergyUnit(sysEnergyInfo.getMuid());
+            item.setCostLabel(sysEnergyInfo.getEnername() + "璐�");
+            item.setAccumulationLabel(sysEnergyInfo.getEnername() + "鐢ㄩ噺");
+            item.setCost(cost);
+            item.setAccumulation(accumulation);
+            // 缁勮鍥捐〃淇℃伅
+            getTrendAnalysisCharInfoByEnergyType(startTime, timeType, energyConsumeVOList, item);
+            itemList.add(item);
+        }
+        return itemList;
+    }
+
+    /**
+     * 缁勮鎴愭湰瓒嬪娍鍒嗘瀽-缁熻鍥句俊鎭�
+     *
+     * @param bsTime    鏃堕棿
+     * @param timeType  鏃堕棿绫诲瀷
+     * @param dataItems 鑳借��
+     * @param item      杩斿洖瀵硅薄
+     */
+    private void getTrendAnalysisCharInfoByEnergyType(Date bsTime, String timeType,
+                                                      List<EnergyConsumeVO> dataItems, EnergyConsumeTrendDetailItem item) {
+        List<String> costKeyList = new ArrayList<>();
+        List<String> accumulationKeyList = new ArrayList<>();
+        List<BigDecimal> costValueList = new ArrayList<>();
+        List<BigDecimal> accumulationValueList = new ArrayList<>();
+        Map<String, List<EnergyConsumeVO>> energyConsumeVOMap;
+        //鎸夋椂闂寸被鍨嬬粍缁囪繑鍥炴暟鎹�
+        switch (timeType) {
+            case TimeTypeConst.TIME_TYPE_DAY:
+                energyConsumeVOMap = dataItems.stream().collect(Collectors.groupingBy(li -> DateUtil.formatDateTime(li.getDataTime())));
+                for (int i = 0; i < CommonConst.DIGIT_24; i++) {
+                    String formatDate = i + CommonConst.TIME_UNIT_SHOW_HOUR;
+                    costKeyList.add(formatDate);
+                    accumulationKeyList.add(formatDate);
+                    String key = DateUtil.formatDateTime(DateUtil.offsetHour(bsTime, i));
+                    calculateCostAndAccumulation(energyConsumeVOMap, key, costValueList, accumulationValueList);
+                }
+                break;
+            case TimeTypeConst.TIME_TYPE_MONTH:
+                energyConsumeVOMap = dataItems.stream().collect(Collectors.groupingBy(li -> DateUtil.formatDate(li.getDataTime())));
+                Date endTime = DateTimeUtil.getEndTimeByType(timeType, bsTime);
+                while (bsTime.before(endTime)) {
+                    String formatDate = DateUtil.formatDate(bsTime);
+                    costKeyList.add(formatDate);
+                    accumulationKeyList.add(formatDate);
+                    calculateCostAndAccumulation(energyConsumeVOMap, formatDate, costValueList, accumulationValueList);
+                    bsTime = DateUtil.offsetDay(bsTime, CommonConst.DIGIT_1);
+                }
+                break;
+            case TimeTypeConst.TIME_TYPE_YEAR:
+                SimpleDateFormat formatter = new SimpleDateFormat(DateTimeUtil.COMMON_PATTERN_TO_MONTH_ZH);
+                energyConsumeVOMap = dataItems.stream().collect(Collectors.groupingBy(li -> formatter.format(li.getDataTime())));
+                for (int i = 0; i < CommonConst.DIGIT_12; i++) {
+                    Date newDate = DateUtil.offsetMonth(bsTime, i);
+                    String formatDate = DateUtil.format(newDate, DateTimeUtil.COMMON_PATTERN_TO_MONTH_ZH);
+                    costKeyList.add(formatDate);
+                    accumulationKeyList.add(formatDate);
+                    calculateCostAndAccumulation(energyConsumeVOMap, formatDate, costValueList, accumulationValueList);
+                }
+                break;
+            default:
+                break;
+        }
+
+        item.setCostKeyList(costKeyList);
+        item.setCostValueList(costValueList);
+        item.setAccumulationKeyList(accumulationKeyList);
+        item.setAccumulationValueList(accumulationValueList);
+    }
+
+    /**
+     * 璁$畻璐圭敤鍜岀敤閲�
+     *
+     * @param energyConsumeVOMap
+     * @param formatDate
+     * @param costValueList
+     * @param accumulationValueList
+     */
+    private static void calculateCostAndAccumulation(Map<String, List<EnergyConsumeVO>> energyConsumeVOMap, String formatDate, List<BigDecimal> costValueList, List<BigDecimal> accumulationValueList) {
+        List<EnergyConsumeVO> energyConsumeList = Optional.ofNullable(energyConsumeVOMap.get(formatDate))
+                .orElse(Collections.emptyList());
+        BigDecimal totalCost = energyConsumeList.stream()
+                .map(EnergyConsumeVO::getCostValue)
+                .reduce(BigDecimal.ZERO, BigDecimal::add)
+                .setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP);
+
+        BigDecimal totalAccumulation = energyConsumeList.stream()
+                .map(EnergyConsumeVO::getAccumulationValue)
+                .reduce(BigDecimal.ZERO, BigDecimal::add)
+                .setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP);
+        costValueList.add(totalCost);
+        accumulationValueList.add(totalAccumulation);
+    }
+
+    /**
+     * 鍚屾鐜瘮鍒嗘瀽
+     *
+     * @param req            璇锋眰鍙傛暟
+     * @param comparisonType 瀵规瘮绫诲瀷
+     * @return
+     */
+    @Override
+    public List<EnergyTypeValueContrastedVO> listEnergyTypeYoyInfo(QueryCompareRequest req, String comparisonType) {
+        String energyType = req.getEnergyType();
+        String timeType = req.getTimeType();
+        String timeCode = req.getTimeCode();
+        String nodeId = req.getNodeId();
+        //鑳芥簮绫诲瀷淇℃伅
+        SysEnergy sysEnergy = new SysEnergy();
+        sysEnergy.setEnersno(energyType);
+        List<SysEnergy> sysEnergies = sysEnergyMapper.selectSysEnergyList(sysEnergy);
+        if (sysEnergies.isEmpty()) {
+            throw new RuntimeException("鏈煡璇㈠埌鑳芥簮淇℃伅");
+        }
+        SysEnergy sysEnergyInfo = sysEnergies.get(0);
+
+        // 鑳借�椾俊鎭�
+        Date startTime = DateTimeUtil.getTime(timeType, timeCode);
+        Date endTime = DateTimeUtil.getEndTimeByType(timeType, startTime);
+        //鏄惁鍚屾瘮
+        boolean isYoy = comparisonType.equals(CommonConst.ENERGY_COMPARISON_YOY);
+        // 璁$畻涓婁竴骞寸殑鍚屾湡鏃堕棿
+        Date lastBeginTime = DateUtil.offset(startTime, DateField.YEAR, CommonConst.DIGIT_MINUS_1);
+        Date lastEndTime = DateUtil.offset(endTime, DateField.YEAR, CommonConst.DIGIT_MINUS_1);
+        if (!isYoy) {
+            switch (timeType) {
+                case TimeTypeConst.TIME_TYPE_DAY:
+                    lastBeginTime = DateUtil.offsetDay(startTime, CommonConst.DIGIT_MINUS_1);
+                    lastEndTime = DateUtil.offsetDay(endTime, CommonConst.DIGIT_MINUS_1);
+                    break;
+                case TimeTypeConst.TIME_TYPE_MONTH:
+                    lastBeginTime = DateUtil.offsetMonth(startTime, CommonConst.DIGIT_MINUS_1);
+                    lastEndTime = DateUtil.offsetMonth(endTime, CommonConst.DIGIT_MINUS_1);
+                    break;
+            }
+        }
+
+        //鐢碉細鍙湁HOUR鏁版嵁鏈夋晥锛涘叾浠栬兘婧愮被鍨嬶細HOUR銆丏AY鏈夋暟鎹�
+        String queryTimeType = TimeTypeConst.TIME_TYPE_HOUR;
+        List<EnergyConsumeVO> energyConsumeVOList = new ArrayList<>();
+        switch (sysEnergyInfo.getEnersno()) {
+            case "electric":
+                List<ElectricityDataItem> electricityDataItems = peakValleyMapper.getCostTrends(startTime, endTime, queryTimeType, nodeId, sysEnergyInfo.getEnersno());
+                List<ElectricityDataItem> lastDataItemList = peakValleyMapper.getCostTrends(lastBeginTime, lastEndTime, queryTimeType, nodeId, sysEnergyInfo.getEnersno());
+                if (!lastDataItemList.isEmpty()) {
+                    electricityDataItems.addAll(lastDataItemList);
+                }
+                if (!electricityDataItems.isEmpty()) {
+                    electricityDataItems.forEach(electricityDataItem -> {
+                        EnergyConsumeVO temp = new EnergyConsumeVO();
+                        temp.setDataTime(electricityDataItem.getDataTime());
+                        temp.setAccumulationValue(electricityDataItem.getElectricity());
+                        energyConsumeVOList.add(temp);
+                    });
+                }
+                break;
+            default:
+                if (timeType.equals(TimeTypeConst.TIME_TYPE_MONTH) || timeType.equals(TimeTypeConst.TIME_TYPE_YEAR)) {
+                    queryTimeType = TimeTypeConst.TIME_TYPE_DAY;
+                }
+                List<CarbonEmission> dataItems = dataItemMapper.getMiddleCarbonEmission(startTime, endTime, queryTimeType, nodeId, sysEnergyInfo.getEnersno());
+                List<CarbonEmission> lastDataItems = dataItemMapper.getMiddleCarbonEmission(lastBeginTime, lastEndTime, queryTimeType, nodeId, sysEnergyInfo.getEnersno());
+                if (!lastDataItems.isEmpty()) {
+                    dataItems.addAll(lastDataItems);
+                }
+                dataItems.addAll(lastDataItems);
+                if (!dataItems.isEmpty()) {
+                    dataItems.forEach(dataItem -> {
+                        EnergyConsumeVO temp = new EnergyConsumeVO();
+                        temp.setDataTime(dataItem.getDataTime());
+                        temp.setAccumulationValue(new BigDecimal(dataItem.getValue()));
+                        energyConsumeVOList.add(temp);
+                    });
+                }
+                break;
+        }
+        // 缁勮缁熻鍥句俊鎭�
+        return getEnergyTypeValueContrastedVOList(startTime, timeType, energyConsumeVOList, sysEnergyInfo.getEnersno(), isYoy);
+    }
+
+    /**
+     * 缁勮鎴愭湰瓒嬪娍鍒嗘瀽-缁熻鍥句俊鎭�
+     *
+     * @param bsTime     鏃堕棿
+     * @param timeType   鏃堕棿绫诲瀷
+     * @param dataItems  鑳借��
+     * @param energyType 鑳芥簮绫诲瀷
+     * @param isYoy      鏄惁鍚屾瘮
+     */
+    private List<EnergyTypeValueContrastedVO> getEnergyTypeValueContrastedVOList(Date bsTime, String timeType,
+                                                                                 List<EnergyConsumeVO> dataItems, String energyType, boolean isYoy) {
+        Map<String, List<EnergyConsumeVO>> energyConsumeVOMap;
+        Map<String, List<EnergyConsumeVO>> lastEnergyConsumeVOMap;
+        List<EnergyTypeValueContrastedVO> itemList = new ArrayList<>();
+        //鎸夋椂闂寸被鍨嬬粍缁囪繑鍥炴暟鎹�
+        switch (timeType) {
+            case TimeTypeConst.TIME_TYPE_DAY:
+                energyConsumeVOMap = dataItems.stream().collect(Collectors.groupingBy(li -> DateUtil.formatDateTime(li.getDataTime())));
+                for (int i = 0; i < CommonConst.DIGIT_24; i++) {
+                    Date currentTime = DateUtil.offsetHour(bsTime, i);
+                    Date compareTime = isYoy ? DateUtil.offset(currentTime, DateField.YEAR, CommonConst.DIGIT_MINUS_1) : DateUtil.offsetDay(currentTime, CommonConst.DIGIT_MINUS_1);
+                    String keyCurrentTime = DateUtil.formatDateTime(currentTime);
+                    String keyCompareTime = DateUtil.formatDateTime(compareTime);
+                    EnergyTypeValueContrastedVO item = getEnergyTypeValueContrastedVO(energyType, energyConsumeVOMap, keyCurrentTime, keyCompareTime, currentTime, compareTime);
+                    itemList.add(item);
+                }
+                break;
+            case TimeTypeConst.TIME_TYPE_MONTH:
+                energyConsumeVOMap = dataItems.stream().collect(Collectors.groupingBy(li -> DateUtil.formatDate(li.getDataTime())));
+                Date endTime = DateTimeUtil.getEndTimeByType(timeType, bsTime);
+                while (bsTime.before(endTime)) {
+                    Date currentTime = bsTime;
+                    Date compareTime = isYoy ? DateUtil.offset(currentTime, DateField.YEAR, CommonConst.DIGIT_MINUS_1) : DateUtil.offsetMonth(currentTime, CommonConst.DIGIT_MINUS_1);
+                    String keyCurrentTime = DateUtil.formatDate(currentTime);
+                    String keyCompareTime = DateUtil.formatDate(compareTime);
+                    EnergyTypeValueContrastedVO item = getEnergyTypeValueContrastedVO(energyType, energyConsumeVOMap, keyCurrentTime, keyCompareTime, currentTime, compareTime);
+                    itemList.add(item);
+                    bsTime = DateUtil.offsetDay(bsTime, CommonConst.DIGIT_1);
+                }
+                break;
+            case TimeTypeConst.TIME_TYPE_YEAR:
+                SimpleDateFormat formatter = new SimpleDateFormat(DateTimeUtil.COMMON_PATTERN_TO_MONTH_ZH);
+                energyConsumeVOMap = dataItems.stream().collect(Collectors.groupingBy(li -> formatter.format(li.getDataTime())));
+                for (int i = 0; i < CommonConst.DIGIT_12; i++) {
+                    Date currentTime = DateUtil.offsetMonth(bsTime, i);
+                    Date compareTime = DateUtil.offset(currentTime, DateField.YEAR, CommonConst.DIGIT_MINUS_1);
+                    String keyCurrentTime = formatter.format(currentTime);
+                    String keyCompareTime = formatter.format(compareTime);
+                    EnergyTypeValueContrastedVO item = getEnergyTypeValueContrastedVO(energyType, energyConsumeVOMap, keyCurrentTime, keyCompareTime, currentTime, compareTime);
+                    itemList.add(item);
+                }
+                break;
+            default:
+                break;
+        }
+        return itemList;
+    }
+
+    private @NotNull EnergyTypeValueContrastedVO getEnergyTypeValueContrastedVO(String energyType, Map<String, List<EnergyConsumeVO>> energyConsumeVOMap,
+                                                                                String keyCurrentTime, String keyCompareTime, Date currentTime, Date compareTime) {
+        List<EnergyConsumeVO> energyConsumeList = Optional.ofNullable(energyConsumeVOMap.get(keyCurrentTime))
+                .orElse(Collections.emptyList());
+        BigDecimal currentValue = calculateSum(energyConsumeList);
+        List<EnergyConsumeVO> lastEnergyConsumeList = Optional.ofNullable(energyConsumeVOMap.get(keyCompareTime))
+                .orElse(Collections.emptyList());
+        BigDecimal contrastValues = calculateSum(lastEnergyConsumeList);
+        BigDecimal multiple = BigDecimal.valueOf(CommonConst.DIGIT_100);
+        BigDecimal ratio = calculateRatio(currentValue, contrastValues, multiple);
+        EnergyTypeValueContrastedVO item = new EnergyTypeValueContrastedVO();
+        item.setEnergyType(energyType);
+        item.setCurrentTime(DateUtil.formatDateTime(currentTime));
+        item.setCompareTime(DateUtil.formatDateTime(compareTime));
+        item.setCurrentValue(currentValue);
+        item.setContrastValues(contrastValues);
+        item.setRatio(ratio);
+        return item;
+    }
+
+    private BigDecimal calculateSum(List<EnergyConsumeVO> dataItemList) {
+        return dataItemList.stream()
+                .map(EnergyConsumeVO::getAccumulationValue)
+                .reduce(BigDecimal.ZERO, BigDecimal::add)
+                .setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP);
+    }
+
+    private BigDecimal calculateRatio(BigDecimal currentSum, BigDecimal lastSum, BigDecimal multiple) {
+        if (lastSum.compareTo(BigDecimal.ZERO) == 0) {
+            return BigDecimal.ZERO;
+        }
+        return currentSum.subtract(lastSum)
+                .divide(lastSum, CommonConst.DIGIT_2, RoundingMode.HALF_UP)
+                .multiply(multiple)
+                .setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP);
+    }
+}

--
Gitblit v1.9.3