From 9ecc36c0694f6f0495f51b1c32cb3d22c9371208 Mon Sep 17 00:00:00 2001
From: letsgocoding <sdxt_0802@163.com>
Date: 星期五, 14 二月 2025 15:46:56 +0800
Subject: [PATCH] !77 !76 修改swagger信息 Merge pull request !77 from letsgocoding/develop1.0

---
 zhitan-system/src/main/java/com/zhitan/model/service/impl/EnergyIndexServiceImpl.java                               |    5 
 zhitan-vue/src/views/powerquality/threephase/index.vue                                                              |  503 +++++
 zhitan-vue/src/views/costAnalysis/cost-trend-analysis.vue                                                           |  316 +++
 zhitan-admin/src/main/java/com/zhitan/web/controller/statisticalAnalysis/StatisticalAnalysisController.java         |    2 
 zhitan-vue/src/api/powerquality/electricThreePhase/api.js                                                           |   10 
 zhitan-vue/src/views/energyefficiency/benchmarkmanage/benchmarkmanage.vue                                           |  198 +-
 zhitan-vue/src/views/powerquality/load/index.vue                                                                    |  402 ++++
 zhitan-admin/src/main/java/com/zhitan/web/controller/comprehensivestatistics/ComprehensiveStatisticsController.java |    1 
 zhitan-admin/src/main/java/com/zhitan/web/controller/meter/MeterController.java                                     |    3 
 zhitan-system/src/main/java/com/zhitan/energyMonitor/service/impl/ElectricThreePhaseServiceImpl.java                |   26 
 zhitan-system/src/main/java/com/zhitan/peakvalley/mapper/PeakValleyMapper.java                                      |   12 
 zhitan-vue/src/api/powerquality/electric-power-factor/api.js                                                        |    9 
 zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyCostTrendPage.java                       |   22 
 zhitan-admin/src/main/java/com/zhitan/web/controller/energyMonitor/ElectricThreePhaseController.java                |    1 
 zhitan-admin/src/main/java/com/zhitan/web/controller/statisticalAnalysis/EnergyConsumeDataController.java           |   69 
 zhitan-system/src/main/resources/mapper/dataitem/DataItemMapper.xml                                                 |   18 
 zhitan-vue/src/views/dataMonitoring/historyDataTrend/index.vue                                                      |  337 +++
 zhitan-admin/src/main/java/com/zhitan/web/controller/saving/EnergySavingProgramController.java                      |    6 
 zhitan-vue/src/assets/styles/ruoyi.scss                                                                             |   13 
 zhitan-system/src/main/java/com/zhitan/realtimedata/service/impl/RealtimeDatabaseServiceImpl.java                   |    1 
 zhitan-vue/src/views/comprehensive/monthlyComprehensive/index.vue                                                   |    3 
 zhitan-system/src/main/java/com/zhitan/dataitem/mapper/DataItemMapper.java                                          |   12 
 zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyConsumeVO.java                           |   43 
 zhitan-admin/src/main/java/com/zhitan/web/core/config/SwaggerConfig.java                                            |    6 
 zhitan-common/src/main/java/com/zhitan/common/constant/CommonConst.java                                             |    6 
 zhitan-system/src/main/resources/mapper/peakvalley/ElectricityDataItemMapper.xml                                    |   26 
 zhitan-vue/src/components/Echarts/LineChart.vue                                                                     |  182 ++
 zhitan-vue/src/views/index.vue                                                                                      |   14 
 zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/CostTrendEnergyTypeItem.java                   |   47 
 zhitan-vue/src/views/costAnalysis/energy-trend-analysis.vue                                                         |  295 +++
 zhitan-vue/src/api/realTimeMonitor/historyDataTrend.js                                                              |   16 
 zhitan-vue/src/api/cost/api.js                                                                                      |   16 
 zhitan-vue/src/views/modelconfiguration/indexwarehouse/indexWarehouse.vue                                           |  161 +
 zhitan-vue/src/views/businessconfiguration/gatewayledger/gatewayLedger.vue                                          |  199 +-
 zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/common/DateTimeUtil.java                                 |  750 ++++++++
 .gitignore                                                                                                          |    1 
 zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyTypeValueContrastedVO.java               |   62 
 zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/service/impl/EnergyConsumeDataServiceImpl.java           |  498 +++++
 zhitan-admin/src/main/java/com/zhitan/web/controller/model/ModelInfoController.java                                 |    2 
 zhitan-admin/src/main/java/com/zhitan/web/controller/consumptionanalysis/ConsumptionAnalysisController.java         |    2 
 zhitan-common/src/main/java/com/zhitan/common/utils/ChartUtils.java                                                 |   14 
 zhitan-vue/src/views/realtimemonitor/realtimemonitor/realtimemonitor.vue                                            |  126 
 zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/QueryCompareRequest.java                       |   49 
 zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyCostTrendItem.java                       |   51 
 zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/service/IEnergyConsumeDataService.java                   |   44 
 zhitan-vue/src/views/comprehensive/yearComprehensive/index.vue                                                      |    2 
 zhitan-vue/src/views/powerquality/power/index.vue                                                                   |  331 +++
 zhitan-admin/src/main/java/com/zhitan/web/controller/history/HistoryDataTrendController.java                        |   97 
 zhitan-common/src/main/java/com/zhitan/common/enums/RetrievalModes.java                                             |    5 
 zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyConsumeTrendDetailItem.java              |   83 
 zhitan-vue/src/views/peakvalley/period/period.vue                                                                   |    9 
 zhitan-vue/src/api/powerquality/load-analysis/api.js                                                                |   28 
 zhitan-vue/src/views/comprehensive/comps/LineChart.vue                                                              |    4 
 zhitan-admin/src/main/java/com/zhitan/web/controller/statisticalAnalysis/EnergyDataItemController.java              |   30 
 54 files changed, 4,756 insertions(+), 412 deletions(-)

diff --git a/.gitignore b/.gitignore
index 5f073e0..7dc579c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,7 @@
 
 ######################################################################
 # IDE
+.DS_Store
 
 ### STS ###
 .apt_generated
diff --git a/zhitan-admin/src/main/java/com/zhitan/web/controller/comprehensivestatistics/ComprehensiveStatisticsController.java b/zhitan-admin/src/main/java/com/zhitan/web/controller/comprehensivestatistics/ComprehensiveStatisticsController.java
index 4beb942..d5c6788 100644
--- a/zhitan-admin/src/main/java/com/zhitan/web/controller/comprehensivestatistics/ComprehensiveStatisticsController.java
+++ b/zhitan-admin/src/main/java/com/zhitan/web/controller/comprehensivestatistics/ComprehensiveStatisticsController.java
@@ -9,6 +9,7 @@
 import com.zhitan.keyequipment.service.IDailyKeyEquipmentService;
 import com.zhitan.model.domain.EnergyIndex;
 import com.zhitan.model.service.IModelNodeService;
+import io.swagger.annotations.Api;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
diff --git a/zhitan-admin/src/main/java/com/zhitan/web/controller/consumptionanalysis/ConsumptionAnalysisController.java b/zhitan-admin/src/main/java/com/zhitan/web/controller/consumptionanalysis/ConsumptionAnalysisController.java
index af9dc6d..9c22a8d 100644
--- a/zhitan-admin/src/main/java/com/zhitan/web/controller/consumptionanalysis/ConsumptionAnalysisController.java
+++ b/zhitan-admin/src/main/java/com/zhitan/web/controller/consumptionanalysis/ConsumptionAnalysisController.java
@@ -10,6 +10,7 @@
 import com.zhitan.consumptionanalysis.domain.vo.RankingDataVO;
 import com.zhitan.consumptionanalysis.domain.vo.RankingEnergyData;
 import com.zhitan.consumptionanalysis.service.IConsumptionAnalysisService;
+import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.apache.poi.ss.usermodel.Cell;
 import org.apache.poi.ss.usermodel.Row;
@@ -35,6 +36,7 @@
  * @Author: Zhujw
  * @Date: 2023/3/1
  */
+@Api(tags = "缁煎悎鑳借�楀垎鏋�")
 @RestController
 @RequestMapping("/consumptionanalysis")
 public class ConsumptionAnalysisController extends BaseController {
diff --git a/zhitan-admin/src/main/java/com/zhitan/web/controller/energyMonitor/ElectricThreePhaseController.java b/zhitan-admin/src/main/java/com/zhitan/web/controller/energyMonitor/ElectricThreePhaseController.java
index fca2c2d..3a10efa 100644
--- a/zhitan-admin/src/main/java/com/zhitan/web/controller/energyMonitor/ElectricThreePhaseController.java
+++ b/zhitan-admin/src/main/java/com/zhitan/web/controller/energyMonitor/ElectricThreePhaseController.java
@@ -56,6 +56,7 @@
         if (ObjectUtils.isEmpty(meterId)){
             return AjaxResult.error("鐢佃〃id涓嶈兘涓虹┖");
         }
+
         List<EnergyIndex> energyIndexList = energyIndexService.listDeviceIndex(nodeId, meterId);
 
         return AjaxResult.success(electricThreePhaseService.list(timeType, timeCode, energyIndexList, requestType, meterId));
diff --git a/zhitan-admin/src/main/java/com/zhitan/web/controller/history/HistoryDataTrendController.java b/zhitan-admin/src/main/java/com/zhitan/web/controller/history/HistoryDataTrendController.java
index e1f067b..5b5bd17 100644
--- a/zhitan-admin/src/main/java/com/zhitan/web/controller/history/HistoryDataTrendController.java
+++ b/zhitan-admin/src/main/java/com/zhitan/web/controller/history/HistoryDataTrendController.java
@@ -4,10 +4,15 @@
 import com.zhitan.basicdata.domain.MeterImplement;
 import com.zhitan.basicdata.services.IMeterImplementService;
 import com.zhitan.common.annotation.Log;
+import com.zhitan.common.constant.CommonConst;
+import com.zhitan.common.constant.TimeTypeConst;
 import com.zhitan.common.core.controller.BaseController;
 import com.zhitan.common.core.domain.AjaxResult;
 import com.zhitan.common.enums.BusinessType;
 import com.zhitan.common.enums.RetrievalModes;
+import com.zhitan.common.enums.TimeType;
+import com.zhitan.common.utils.ChartUtils;
+import com.zhitan.common.utils.DateTimeUtil;
 import com.zhitan.common.utils.poi.ExcelUtil;
 import com.zhitan.history.domain.dto.HistoricalDataDTO;
 import com.zhitan.history.domain.vo.HistoricalDataExcel;
@@ -16,7 +21,9 @@
 import com.zhitan.model.service.IEnergyIndexService;
 import com.zhitan.realtimedata.domain.TagValue;
 import com.zhitan.realtimedata.service.RealtimeDatabaseService;
+import io.swagger.annotations.Api;
 import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -29,11 +36,12 @@
 import java.util.List;
 
 /**
- * 璁惧鍚仠瀹炴椂鐩戞祴Controller
+ * 鍘嗗彶鏁版嵁瓒嬪娍Controller
  *
  * @author sys
  * @date 2020-03-30
  */
+@Api(tags = "鍘嗗彶鏁版嵁瓒嬪娍")
 @RestController
 @RequestMapping("/dataMonitoring/historyDataTrend")
 public class HistoryDataTrendController extends BaseController {
@@ -61,9 +69,6 @@
     public AjaxResult getSettingIndex(EnergyIndex energyIndex) {
         try {
             List<EnergyIndex> infoList = energyIndexService.selectEnergyIndexList(energyIndex);
-//            List<String> codeList= infoList.stream().map(EnergyIndex::getCode).collect(Collectors.toList());
-//            List<TagValue> valList = realtimeDatabaseService.retrieve(codeList);
-//            List resultList = new ArrayList();
             return AjaxResult.success(infoList);
         } catch (Exception ex) {
             logger.error("鑾峰彇鍏宠仈閲囬泦鎸囨爣鍑洪敊锛�", ex);
@@ -80,68 +85,44 @@
             if (ObjectUtils.isEmpty(energyIndex)) {
                 return AjaxResult.error("鏈壘鍒扮偣浣嶄俊鎭�");
             }
-            Date beginTime = dto.getDataTime();
-            Date endTime;
-            // 鏌ヨ鏉℃暟
-            int count = 1440;
-            if ("DAY".equals(dto.getTimeType())) {
-                endTime = DateUtil.endOfDay(beginTime);
+            List<Date> dateList = new ArrayList<>();
+            if (TimeType.DAY.name().equals(dto.getTimeType())) {
+                String timeCode = DateTimeUtil.getDateTime(dto.getDataTime(), DateTimeUtil.COMMON_PATTERN_TO_DAY);
+                ChartUtils.generateDateList(TimeTypeConst.TIME_TYPE_DAY, timeCode, dateList);
+            } else if (TimeType.HOUR.name().equals(dto.getTimeType())) {
+                String timeCode = DateTimeUtil.getDateTime(dto.getDataTime(), DateTimeUtil.COMMON_PATTERN_TO_HOUR);
+                ChartUtils.generateDateList(TimeTypeConst.TIME_TYPE_HOUR, timeCode, dateList);
             } else {
-                count = 3600;
-                endTime = DateUtil.offsetSecond(DateUtil.offsetHour(beginTime, 1), -1);
+                return AjaxResult.error("鏃堕棿闂撮殧绫诲瀷涓嶆纭�");
             }
             // 鏌ヨ璁¢噺鍣ㄥ叿
-            MeterImplement info = meterImplementService.selectMeterImplementById(energyIndex.getMeterId());
-            List<TagValue> tagValueList = realtimeDatabaseService.retrieve(energyIndex.getCode(), beginTime, endTime,
-                    RetrievalModes.BestFit, count);
+            MeterImplement meterInfo = meterImplementService.selectMeterImplementById(energyIndex.getMeterId());
+            if (ObjectUtils.isEmpty(meterInfo)) {
+                return AjaxResult.error("鏈壘鍒拌閲忓櫒鍏蜂俊鎭�");
+            }
             List<HistoricalDataVO> voList = new ArrayList<>();
-            Date date = DateUtil.date();
-            for (int i = 0; i < count + 1; i++) {
+            for (Date date : dateList) {
+                List<TagValue> tagValues = new ArrayList<>();
+                if(TimeType.DAY.name().equals(dto.getTimeType())){
+                    Date beginTime = date;
+                    Date endTime = DateUtil.offsetHour(DateUtil.offsetMinute(date, CommonConst.DIGIT_MINUS_1), CommonConst.DIGIT_1);
+                    tagValues = realtimeDatabaseService.retrieve(energyIndex.getCode(), beginTime,endTime,CommonConst.DIGIT_1);
+                }
+                if(TimeType.HOUR.name().equals(dto.getTimeType())){
+                    Date beginTime = date;
+                    Date endTime = DateUtil.offsetMinute(DateUtil.offsetSecond(date, CommonConst.DIGIT_MINUS_1), CommonConst.DIGIT_1);
+                    tagValues = realtimeDatabaseService.retrieve(energyIndex.getCode(), beginTime,endTime,CommonConst.DIGIT_1);
+                }
+
                 HistoricalDataVO vo = new HistoricalDataVO();
+                vo.setDataTime(DateUtil.formatDateTime(date));
                 vo.setIndexId(energyIndex.getIndexId());
-                String indexName = energyIndex.getName();
-                if (ObjectUtils.isNotEmpty(info)) {
-                    indexName = info.getInstallactionLocation() + "_" + info.getMeterName() + "_" + indexName;
+                vo.setIndexName(meterInfo.getInstallactionLocation() + "_" + meterInfo.getMeterName() + "_" + energyIndex.getName());
+                vo.setValue(CommonConst.DOUBLE_MINUS_SIGN);
+                if(ObjectUtils.isNotEmpty(tagValues)){
+                    vo.setValue(tagValues.get(0).getValue().toString());
                 }
-                vo.setIndexName(indexName);
-                // 鍙栧��
-                String value = "--";
-                String usedValue = "--";
-                if (beginTime.getTime() <= date.getTime()) {
-                    try {
-                        TagValue tagValue = tagValueList.get(i);
-                        BigDecimal cumulative = BigDecimal.valueOf(tagValue.getValue());
 
-                        if ("SWWSDJ_SD".equals(energyIndex.getCode()) || "SWWSDJ_WD".equals(energyIndex.getCode())) {
-                            cumulative = cumulative.multiply(BigDecimal.valueOf(0.1));
-                        }
-                        if (i > 0) {
-                            TagValue previousTagValue = tagValueList.get(i - 1);
-                            BigDecimal previousValue = BigDecimal.ZERO;
-                            if (ObjectUtils.isNotEmpty(previousTagValue.getValue())) {
-                                previousValue = BigDecimal.valueOf(previousTagValue.getValue());
-                            }
-                            if ("SWWSDJ_SD".equals(energyIndex.getCode()) || "SWWSDJ_WD".equals(energyIndex.getCode())) {
-                                previousValue = previousValue.multiply(BigDecimal.valueOf(0.1));
-
-                            }
-                            usedValue = String.valueOf(cumulative.subtract(previousValue).setScale(2, RoundingMode.HALF_UP));
-                        }
-
-                        value = String.valueOf(cumulative.setScale(2, RoundingMode.HALF_UP));
-                    } catch (Exception ignored) {
-                    }
-                }
-                // 鏃堕棿
-                String timeName = DateUtil.formatDateTime(beginTime);
-                vo.setDataTime(timeName);
-                if ("DAY".equals(dto.getTimeType())) {
-                    beginTime = DateUtil.offsetMinute(beginTime, 1);
-                } else {
-                    beginTime = DateUtil.offsetSecond(beginTime, 1);
-                }
-                vo.setUsedValue(String.valueOf(usedValue));
-                vo.setValue(String.valueOf(value));
                 voList.add(vo);
             }
             return AjaxResult.success(voList);
diff --git a/zhitan-admin/src/main/java/com/zhitan/web/controller/meter/MeterController.java b/zhitan-admin/src/main/java/com/zhitan/web/controller/meter/MeterController.java
index 7f933f4..7bf5cc1 100644
--- a/zhitan-admin/src/main/java/com/zhitan/web/controller/meter/MeterController.java
+++ b/zhitan-admin/src/main/java/com/zhitan/web/controller/meter/MeterController.java
@@ -26,9 +26,8 @@
  * @Version: 1.0
  * @Since: JDK1.8
  */
-
-@Slf4j
 @Api("閲囬泦璁¢噺琛ㄦ暟鎹鐞�")
+@Slf4j
 @RestController
 @RequestMapping("/meters")
 public class MeterController extends BaseController {
diff --git a/zhitan-admin/src/main/java/com/zhitan/web/controller/model/ModelInfoController.java b/zhitan-admin/src/main/java/com/zhitan/web/controller/model/ModelInfoController.java
index 73dcb3a..9a7f65b 100644
--- a/zhitan-admin/src/main/java/com/zhitan/web/controller/model/ModelInfoController.java
+++ b/zhitan-admin/src/main/java/com/zhitan/web/controller/model/ModelInfoController.java
@@ -10,6 +10,7 @@
 import com.zhitan.model.domain.vo.PointDataVO;
 import com.zhitan.model.service.IEnergyIndexService;
 import com.zhitan.model.service.IModelInfoService;
+import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -23,6 +24,7 @@
  * @author fanxinfu
  * @date 2020-02-17
  */
+@Api(tags = "妯″瀷鐩稿叧")
 @RestController
 @RequestMapping("/basicsetting/model")
 public class ModelInfoController extends BaseController {
diff --git a/zhitan-admin/src/main/java/com/zhitan/web/controller/saving/EnergySavingProgramController.java b/zhitan-admin/src/main/java/com/zhitan/web/controller/saving/EnergySavingProgramController.java
index 69c3440..a26fef2 100644
--- a/zhitan-admin/src/main/java/com/zhitan/web/controller/saving/EnergySavingProgramController.java
+++ b/zhitan-admin/src/main/java/com/zhitan/web/controller/saving/EnergySavingProgramController.java
@@ -36,7 +36,7 @@
      * 鍒楄〃
      */
     @GetMapping("/page")
-    @PreAuthorize("@ss.hasPermi('energySavingProject:list')")
+    @PreAuthorize("@ss.hasPermi('energySavingProject:Project:list')")
     @ApiOperation(value = "鍒嗛〉鍒楄〃")
     public TableDataInfo list(EnergySavingProgram energySavingProgram) {
         Page<EnergySavingProgramVO> list = energySavingProgramService.selectEnergySavingProgramList(energySavingProgram);
@@ -50,7 +50,6 @@
      * 璇︾粏淇℃伅
      */
     @ApiOperation(value = "鏌ヨ璇︽儏")
-    @PreAuthorize("@ss.hasPermi('energySavingProject')")
     @GetMapping(value = "getById")
     public AjaxResult getInfo(@RequestParam("id") Long id) {
         return success(energySavingProgramService.selectEnergySavingProgramById(id));
@@ -61,6 +60,7 @@
      * 鑺傝兘椤圭洰绠$悊
      */
     @ApiOperation(value = "鏂板")
+    @PreAuthorize("@ss.hasPermi('energySavingProject:Project:add')")
     @PostMapping("add")
     public AjaxResult add(  @RequestBody EnergySavingProgramDTO dto) {
         return energySavingProgramService.insertEnergySavingProgram(dto);
@@ -71,6 +71,7 @@
      * 鑺傝兘椤圭洰绠$悊
      */
     @ApiOperation(value = "鏇存柊")
+    @PreAuthorize("@ss.hasPermi('energySavingProject:Project:edit')")
     @PostMapping("edit")
     public AjaxResult edit(@RequestBody EnergySavingProgramDTO dto) {
         return energySavingProgramService.updateEnergySavingProgram(dto);
@@ -81,6 +82,7 @@
      * 鑺傝兘椤圭洰绠$悊
      */
     @DeleteMapping("del/{id}")
+    @PreAuthorize("@ss.hasPermi('energySavingProject:Project:del')")
     @ApiOperation(value = "鍒犻櫎")
     public AjaxResult remove(@PathVariable  Long id) {
         return energySavingProgramService.deleteEnergySavingProgramById(id);
diff --git a/zhitan-admin/src/main/java/com/zhitan/web/controller/statisticalAnalysis/EnergyConsumeDataController.java b/zhitan-admin/src/main/java/com/zhitan/web/controller/statisticalAnalysis/EnergyConsumeDataController.java
new file mode 100644
index 0000000..e91dc45
--- /dev/null
+++ b/zhitan-admin/src/main/java/com/zhitan/web/controller/statisticalAnalysis/EnergyConsumeDataController.java
@@ -0,0 +1,69 @@
+package com.zhitan.web.controller.statisticalAnalysis;
+
+import com.zhitan.common.annotation.Log;
+import com.zhitan.common.core.domain.AjaxResult;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import com.zhitan.statisticalAnalysis.service.IEnergyConsumeDataService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+
+/**
+ * @Description: 鑳芥簮娑堣�楃粺璁″垎鏋�
+ * @author: yxw
+ * @date: 2022骞�04鏈�12鏃� 14:11
+ */
+@Api(tags = "鑳借�楃粺璁″垎鏋�")
+@RestController
+@RequestMapping("/energyTypeAnalysis")
+@Slf4j
+public class EnergyConsumeDataController {
+    @Autowired
+    private IEnergyConsumeDataService energyConsumeDataService;
+
+    /**
+     * 鎴愭湰瓒嬪娍鍒嗘瀽锛堣兘婧愭秷鑰楁垚鏈級- 鑾峰彇琛ㄦ牸鍒楄〃鏁版嵁
+     *
+     * @param pageNo   椤电爜鏁�
+     * @param pageSize 姣忛〉鏁版嵁澶氬皯
+     * @param timeCode 鏃堕棿鍊�   涓庢椂闂寸被鍨嬪搴旓細2022-03-21/2022-03/2022
+     * @param timeType 鏃堕棿绫诲瀷 DAY/MONTH/YEAR
+     * @param energyType 鑳芥簮绫诲瀷
+     * @param modelCode 妯″瀷Code
+     * @return
+     */
+    @Log(title = "鑳借�楃粺璁″垎鏋�-鎴愭湰瓒嬪娍鍒嗘瀽锛堣兘婧愭秷鑰楁垚鏈級- 鑾峰彇琛ㄦ牸鍒楄〃鏁版嵁")
+    @ApiOperation(value = "鑳借�楃粺璁″垎鏋�-鎴愭湰瓒嬪娍鍒嗘瀽锛堣兘婧愭秷鑰楁垚鏈級- 鑾峰彇琛ㄦ牸鍒楄〃鏁版嵁", notes = "鑳借�楃粺璁″垎鏋�-鎴愭湰瓒嬪娍鍒嗘瀽锛堣兘婧愭秷鑰楁垚鏈級- 鑾峰彇琛ㄦ牸鍒楄〃鏁版嵁")
+    @GetMapping(value = "/listEnergyCostTrend")
+    public AjaxResult listEnergyCostTrend(@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
+                                          @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
+                                          @RequestParam(name = "timeCode") String timeCode,
+                                          @RequestParam(name = "timeType") String timeType,
+                                          @RequestParam(name = "energyType",required = false) String energyType,
+                                          @RequestParam(name = "modelCode") String modelCode) {
+        return AjaxResult.success(energyConsumeDataService.listEnergyCostTrend(pageNo, pageSize, timeCode, timeType,energyType,
+                modelCode));
+    }
+
+    /**
+     * 鎴愭湰瓒嬪娍鍒嗘瀽锛堣兘婧愭秷鑰楁垚鏈級
+     *
+     * @param timeCode 鏃堕棿鍊�   涓庢椂闂寸被鍨嬪搴旓細2022-03-21/2022-03/2022
+     * @param timeType 鏃堕棿绫诲瀷 DAY/MONTH/YEAR
+     * @param modelCode   妯″瀷Code
+     * @param energyType 鑳芥簮绫诲瀷
+     * @return
+     */
+    @Log(title = "鑳借�楃粺璁″垎鏋�-鎴愭湰瓒嬪娍鍒嗘瀽锛堣兘婧愭秷鑰楁垚鏈級")
+    @ApiOperation(value = "鑳借�楃粺璁″垎鏋�-鎴愭湰瓒嬪娍鍒嗘瀽锛堣兘婧愭秷鑰楁垚鏈級", notes = "鑳借�楃粺璁″垎鏋�-鎴愭湰瓒嬪娍鍒嗘瀽锛堣兘婧愭秷鑰楁垚鏈級")
+    @GetMapping(value = "/listEnergyCostTrendDetail")
+    public AjaxResult listEnergyCostTrendDetail(@RequestParam(name = "timeCode") String timeCode,
+                                                                                @RequestParam(name = "timeType") String timeType,
+                                                                                @RequestParam(name = "modelCode") String modelCode,
+                                                                                @RequestParam(name = "energyType",required = false) String energyType) {
+        return AjaxResult.success(energyConsumeDataService.listEnergyCostTrendDetail(timeCode, timeType, modelCode, energyType));
+    }
+
+}
diff --git a/zhitan-admin/src/main/java/com/zhitan/web/controller/statisticalAnalysis/EnergyDataItemController.java b/zhitan-admin/src/main/java/com/zhitan/web/controller/statisticalAnalysis/EnergyDataItemController.java
index af79e0b..b3028e2 100644
--- a/zhitan-admin/src/main/java/com/zhitan/web/controller/statisticalAnalysis/EnergyDataItemController.java
+++ b/zhitan-admin/src/main/java/com/zhitan/web/controller/statisticalAnalysis/EnergyDataItemController.java
@@ -1,9 +1,12 @@
 package com.zhitan.web.controller.statisticalAnalysis;
 
 import com.zhitan.common.annotation.Log;
+import com.zhitan.common.constant.CommonConst;
 import com.zhitan.common.core.domain.AjaxResult;
 import com.zhitan.dataitem.service.IDataItemService;
 import com.zhitan.statisticalAnalysis.domain.dto.FlowChartsDTO;
+import com.zhitan.statisticalAnalysis.domain.vo.QueryCompareRequest;
+import com.zhitan.statisticalAnalysis.service.IEnergyConsumeDataService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -24,6 +27,9 @@
     @Autowired
     private IDataItemService dataItemService;
 
+    @Autowired
+    private IEnergyConsumeDataService energyConsumeDataService;
+
     /**
      * 鑾峰彇鑳芥祦鍥惧舰鍒嗘瀽
      *
@@ -36,4 +42,28 @@
     public AjaxResult getFlowCharts(@Validated FlowChartsDTO dto) {
         return AjaxResult.success(dataItemService.getFlowCharts(dto));
     }
+
+    @Log(title = "鑳借�楃粺璁″垎鏋�-鑾峰彇鍚屾瘮鍒嗘瀽鍒楄〃鏁版嵁")
+    @ApiOperation(value = "鑳借�楃粺璁″垎鏋�-鑾峰彇鍚屾瘮鍒嗘瀽鍒楄〃鏁版嵁", notes = "鑳借�楃粺璁″垎鏋�-鑾峰彇鍚屾瘮鍒嗘瀽鍒楄〃鏁版嵁")
+    @GetMapping(value = "/querySameCompareList")
+    public AjaxResult querySameCompareList(@Validated QueryCompareRequest queryCompareRequest) {
+        return AjaxResult.success(energyConsumeDataService.listEnergyTypeYoyInfo(queryCompareRequest, CommonConst.ENERGY_COMPARISON_YOY));
+    }
+
+    /**
+     * 鑾峰彇鐜瘮鍒嗘瀽鏁版嵁
+     * <p>
+     * 閫氳繃鑷繁鐨勬湇鍔¤闂湴鍧�锛歨ttp://localhost:7005/fengniao/energyDataItem/queryLoopCompare?timeType=1
+     * 閫氳繃缃戝叧璁块棶鍦板潃锛歨ttp://localhost:9999/jeecg-fengniao/fengniao/energyDataItem/queryLoopCompare?timeType=1
+     *
+     * @param queryCompareRequest
+     * @return
+     */
+    @Log(title = "鑳借�楃粺璁″垎鏋�-鑾峰彇鐜瘮鍒嗘瀽鍒楄〃鏁版嵁")
+    @ApiOperation(value = "鑳借�楃粺璁″垎鏋�-鑾峰彇鐜瘮鍒嗘瀽鍒楄〃鏁版嵁", notes = "鑳借�楃粺璁″垎鏋�-鑾峰彇鐜瘮鍒嗘瀽鍒楄〃鏁版嵁")
+    @GetMapping(value = "/queryLoopCompareList")
+    public AjaxResult queryLoopCompareList(@Validated QueryCompareRequest queryCompareRequest) {
+
+        return AjaxResult.success(energyConsumeDataService.listEnergyTypeYoyInfo(queryCompareRequest, CommonConst.ENERGY_COMPARISON_MOM));
+    }
 }
diff --git a/zhitan-admin/src/main/java/com/zhitan/web/controller/statisticalAnalysis/StatisticalAnalysisController.java b/zhitan-admin/src/main/java/com/zhitan/web/controller/statisticalAnalysis/StatisticalAnalysisController.java
index b93f9c7..6503583 100644
--- a/zhitan-admin/src/main/java/com/zhitan/web/controller/statisticalAnalysis/StatisticalAnalysisController.java
+++ b/zhitan-admin/src/main/java/com/zhitan/web/controller/statisticalAnalysis/StatisticalAnalysisController.java
@@ -9,6 +9,7 @@
 import com.zhitan.statisticalAnalysis.domain.vo.DataAnalysisYoYExcel;
 import com.zhitan.statisticalAnalysis.domain.vo.DataAnalysisYoYVO;
 import com.zhitan.statisticalAnalysis.service.IStatisticalAnalysisService;
+import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.beans.BeanUtils;
@@ -26,6 +27,7 @@
 /**
  * 缁熻鍒嗘瀽 鎺у埗灞�
  */
+@Api(tags = "缁熻鍒嗘瀽")
 @RestController
 @RequestMapping("/statisticalAnalysis")
 public class StatisticalAnalysisController extends BaseController {
diff --git a/zhitan-admin/src/main/java/com/zhitan/web/core/config/SwaggerConfig.java b/zhitan-admin/src/main/java/com/zhitan/web/core/config/SwaggerConfig.java
index 540acc0..aba5d1d 100644
--- a/zhitan-admin/src/main/java/com/zhitan/web/core/config/SwaggerConfig.java
+++ b/zhitan-admin/src/main/java/com/zhitan/web/core/config/SwaggerConfig.java
@@ -115,11 +115,11 @@
         // 鐢ˋpiInfoBuilder杩涜瀹氬埗
         return new ApiInfoBuilder()
                 // 璁剧疆鏍囬
-                .title("鏍囬:鍚庡彴绠$悊绯荤粺_鎺ュ彛鏂囨。")
+                .title("鏅虹⒊_鑳芥簮绠$悊绯荤粺_鎺ュ彛鏂囨。")
                 // 鎻忚堪
-                .description("鎻忚堪:鎺ュ彛鏂囨。")
+                .description("閲囬泦浼佷笟姘淬�佺數銆佹皵銆佺儹绛夎兘鑰楁暟鎹紱甯姪浼佷笟寤虹珛鑳芥簮绠$悊浣撶郴锛屾壘鍒拌窇鍐掓淮婕忥紝涓轰紒涓氳妭鑳芥彁渚涙暟鎹敮鎾戯紱涓轰紒涓氬疄鐜扮⒊璺熻釜銆佺⒊鐩樻煡銆佺⒊浜ゆ槗銆佺⒊姹囨姤鐨勫叏鐢熷懡杩囩▼锛涗负涓浗纰宠揪宄�-纰充腑鍜屽仛鍑鸿础鐚紒")
                 // 浣滆�呬俊鎭�
-                .contact(new Contact(baseConfig.getName(), null, null))
+                .contact(new Contact(baseConfig.getName(), "https://www.zhitancloud.com", "yin.cun@qq.com"))
                 // 鐗堟湰
                 .version("鐗堟湰鍙�:" + baseConfig.getVersion())
                 .build();
diff --git a/zhitan-common/src/main/java/com/zhitan/common/constant/CommonConst.java b/zhitan-common/src/main/java/com/zhitan/common/constant/CommonConst.java
index 73fea42..7a5bb48 100644
--- a/zhitan-common/src/main/java/com/zhitan/common/constant/CommonConst.java
+++ b/zhitan-common/src/main/java/com/zhitan/common/constant/CommonConst.java
@@ -891,15 +891,15 @@
     /**
      * 鐢垫祦
      */
-    public static final String TAG_CODE_CURRENT = "Current_";
+    public static final String TAG_CODE_CURRENT = "Current";
     /**
      * 鐢靛帇
      */
-    public static final String TAG_CODE_VOLTAGE = "Voltage_";
+    public static final String TAG_CODE_VOLTAGE = "Voltage";
     /**
      * 鍔熺巼鍥犳暟
      */
-    public static final String TAG_CODE_FACTOR = "PowerFactor_";
+    public static final String TAG_CODE_FACTOR = "PowerFactor";
     /**
      * 鍔熺巼鍥犳暟
      */
diff --git a/zhitan-common/src/main/java/com/zhitan/common/enums/RetrievalModes.java b/zhitan-common/src/main/java/com/zhitan/common/enums/RetrievalModes.java
index 24c77fa..0ad5f32 100644
--- a/zhitan-common/src/main/java/com/zhitan/common/enums/RetrievalModes.java
+++ b/zhitan-common/src/main/java/com/zhitan/common/enums/RetrievalModes.java
@@ -6,5 +6,8 @@
  *     鑾峰彇瀹炴椂鏁版嵁鏂瑰紡.
  */
 public enum RetrievalModes {
-  Full, BestFit
+
+  Full,
+
+  BestFit
 }
diff --git a/zhitan-common/src/main/java/com/zhitan/common/utils/ChartUtils.java b/zhitan-common/src/main/java/com/zhitan/common/utils/ChartUtils.java
index a099168..50ef51b 100644
--- a/zhitan-common/src/main/java/com/zhitan/common/utils/ChartUtils.java
+++ b/zhitan-common/src/main/java/com/zhitan/common/utils/ChartUtils.java
@@ -24,6 +24,20 @@
     public static void generateDateList(String timeType, String timeCode, List<Date> dateList) {
         Date now = new Date();
         switch (timeType) {
+            case TimeTypeConst.TIME_TYPE_HOUR:
+                if (!timeCode.contains(CommonConst.SINGLE_MINUS_SIGN)) {
+                    timeCode = DateTimeUtil.toDateTimeStr(timeCode, DateTimeUtil.COMMON_PATTERN_HOUR, DateTimeUtil.COMMON_PATTERN_TO_HOUR);
+                }
+                int minute = 59;
+                for (int i =  CommonConst.DIGIT_0; i <= minute; i++) {
+                    String tempCode = timeCode + ":0" + i;
+                    if(i>9){
+                        tempCode = timeCode + ":" + i;
+                    }
+                    Date tempD = DateTimeUtil.toDateTime(tempCode, DateTimeUtil.COMMON_PATTERN_END_WITH_MINUTE);
+                    dateList.add(tempD);
+                }
+                break;
             case TimeTypeConst.TIME_TYPE_DAY:
                 if (!timeCode.contains(CommonConst.SINGLE_MINUS_SIGN)) {
                     timeCode = DateTimeUtil.toDateTimeStr(timeCode, DateTimeUtil.COMMON_PATTERN_DAY, DateTimeUtil.COMMON_PATTERN_TO_DAY);
diff --git a/zhitan-system/src/main/java/com/zhitan/dataitem/mapper/DataItemMapper.java b/zhitan-system/src/main/java/com/zhitan/dataitem/mapper/DataItemMapper.java
index 94f00fe..99d5317 100644
--- a/zhitan-system/src/main/java/com/zhitan/dataitem/mapper/DataItemMapper.java
+++ b/zhitan-system/src/main/java/com/zhitan/dataitem/mapper/DataItemMapper.java
@@ -123,4 +123,16 @@
      */
     List<DataItem> getDataItemHourInforByIndexIds(@Param("beginTime") Date beginTime, @Param("endTime") Date endTime,
                                                   @Param("timeType") String timeType, @Param("indexIds") List<String> indexIds);
+
+    /**
+     * 鏌ヨ鑳芥簮绫诲瀷闈炵數鐨勭敤閲�
+     * @param beginTime
+     * @param endTime
+     * @param timeType 鏃堕棿绫诲瀷
+     * @param nodeId 鑺傜偣Id
+     * @param energyType 鑳芥簮绫诲瀷
+     * @return
+     */
+    BigDecimal getDataItemTimeRangeValueByNodeId(@Param("beginTime") Date beginTime, @Param("endTime") Date endTime,
+                                            @Param("timeType") String timeType, @Param("nodeId") String nodeId, @Param("energyType") String energyType);
 }
diff --git a/zhitan-system/src/main/java/com/zhitan/energyMonitor/service/impl/ElectricThreePhaseServiceImpl.java b/zhitan-system/src/main/java/com/zhitan/energyMonitor/service/impl/ElectricThreePhaseServiceImpl.java
index 5a21836..f855043 100644
--- a/zhitan-system/src/main/java/com/zhitan/energyMonitor/service/impl/ElectricThreePhaseServiceImpl.java
+++ b/zhitan-system/src/main/java/com/zhitan/energyMonitor/service/impl/ElectricThreePhaseServiceImpl.java
@@ -54,9 +54,7 @@
     @Override
     public ElectricThreePhaseVO list(String timeType, String timeCode, List<EnergyIndex> energyIndexList, String requestType, String meterId) {
         ElectricThreePhaseVO vo = new ElectricThreePhaseVO();
-        if (ObjectUtil.isEmpty(energyIndexList)) {
-            return vo;
-        }
+
         // 鑾峰彇鐢靛帇涓嶅钩琛℃暟鎹�
         if (CommonConst.STR_NUMBER_0.equals(requestType)) {
             energyIndexList = energyIndexList.stream()
@@ -70,9 +68,13 @@
                             || StringUtil.ifEmptyOrNullReturnValue(x.getCode()).trim().endsWith(CommonConst.TAG_CODE_CURRENT_C))
                     .collect(Collectors.toList());
         }
+        if (ObjectUtil.isEmpty(energyIndexList)) {
+            return vo;
+        }
         List<String> tagCodeList = energyIndexList.stream().map(EnergyIndex::getCode).collect(Collectors.toList());
-        tagCodeList.add(CommonConst.STR_NUMBER_MINUS_ONE);
-        String tagCodes = String.join(StrUtil.COMMA, tagCodeList);
+        if(ObjectUtil.isEmpty(tagCodeList)){
+            tagCodeList.add(CommonConst.STR_NUMBER_MINUS_ONE);
+        }
 
         Date start = ChartUtils.getDateTime(timeType, timeCode);
         Date end = getEndTime(timeType, start);
@@ -82,7 +84,7 @@
         long millis = new Duration(begin, finish).getMillis();
         int pointCount = IntegerUtil.toInt(millis / CommonConst.DIGIT_3600 / CommonConst.DIGIT_1000);
 
-        List<TagValue> tagValueList = realtimeDatabaseService.retrieve(tagCodes, start, end, pointCount);
+        List<TagValue> tagValueList = realtimeDatabaseService.retrieve(tagCodeList, start, end, pointCount);
         List<ElectricThreePhaseItem> itemList = new ArrayList<>();
         List<Date> dateList = new ArrayList<>();
         ChartUtils.generateDateList(timeType, timeCode, dateList);
@@ -281,10 +283,14 @@
      */
     private void listDayData(Date date, List<TagValue> tagValueList, ElectricThreePhaseItem temp, ElectricThreePhaseTempModel tempModel) {
         Date endTime = DateTimeUtil.addHours(date, CommonConst.DIGIT_1);
-        List<TagValue> currentTagValueList = tagValueList.stream().filter(x -> DateTimeUtil.compareDateDiff(date, x.getDataTime()) <= 0 && DateTimeUtil.compareDateDiff(endTime, x.getDataTime()) > 0).collect(Collectors.toList());
-        List<TagValue> currentATagValueList = currentTagValueList.stream().filter(x -> StringUtil.ifEmptyOrNullReturnValue(x.getTagCode()).trim().endsWith("_A")).collect(Collectors.toList());
-        List<TagValue> currentBTagValueList = currentTagValueList.stream().filter(x -> StringUtil.ifEmptyOrNullReturnValue(x.getTagCode()).trim().endsWith("_B")).collect(Collectors.toList());
-        List<TagValue> currentCTagValueList = currentTagValueList.stream().filter(x -> StringUtil.ifEmptyOrNullReturnValue(x.getTagCode()).trim().endsWith("_C")).collect(Collectors.toList());
+        List<TagValue> currentTagValueList = tagValueList.stream()
+                .filter(x -> DateTimeUtil.compareDateDiff(date, x.getDataTime()) <= 0 && DateTimeUtil.compareDateDiff(endTime, x.getDataTime()) > 0).collect(Collectors.toList());
+        List<TagValue> currentATagValueList = currentTagValueList.stream()
+                .filter(x -> StringUtil.ifEmptyOrNullReturnValue(x.getTagCode()).trim().endsWith(CommonConst.A_PHASE)).collect(Collectors.toList());
+        List<TagValue> currentBTagValueList = currentTagValueList.stream()
+                .filter(x -> StringUtil.ifEmptyOrNullReturnValue(x.getTagCode()).trim().endsWith(CommonConst.B_PHASE)).collect(Collectors.toList());
+        List<TagValue> currentCTagValueList = currentTagValueList.stream()
+                .filter(x -> StringUtil.ifEmptyOrNullReturnValue(x.getTagCode()).trim().endsWith(CommonConst.C_PHASE)).collect(Collectors.toList());
         TagValue tagValueA = currentATagValueList.stream().filter(x -> DateTimeUtil.compareDateDiff(date, x.getDataTime()) == 0).findAny().orElse(null);
         TagValue tagValueB = currentBTagValueList.stream().filter(x -> DateTimeUtil.compareDateDiff(date, x.getDataTime()) == 0).findAny().orElse(null);
         TagValue tagValueC = currentCTagValueList.stream().filter(x -> DateTimeUtil.compareDateDiff(date, x.getDataTime()) == 0).findAny().orElse(null);
diff --git a/zhitan-system/src/main/java/com/zhitan/model/service/impl/EnergyIndexServiceImpl.java b/zhitan-system/src/main/java/com/zhitan/model/service/impl/EnergyIndexServiceImpl.java
index 16d8a62..c519c97 100644
--- a/zhitan-system/src/main/java/com/zhitan/model/service/impl/EnergyIndexServiceImpl.java
+++ b/zhitan-system/src/main/java/com/zhitan/model/service/impl/EnergyIndexServiceImpl.java
@@ -358,8 +358,7 @@
      */
     @Override
     public List<EnergyIndex> listDeviceIndex(String nodeId, String meterId) {
-        return energyIndexMapper.selectList(Wrappers.<EnergyIndex>lambdaQuery()
-                .eq(EnergyIndex::getNodeId, nodeId)
-                .eq(EnergyIndex::getMeterId, meterId));
+        List<EnergyIndex> energyIndexList = energyIndexMapper.getIndexByMeterIdIndexCode(meterId,null,nodeId);
+        return energyIndexList;
     }
 }
diff --git a/zhitan-system/src/main/java/com/zhitan/peakvalley/mapper/PeakValleyMapper.java b/zhitan-system/src/main/java/com/zhitan/peakvalley/mapper/PeakValleyMapper.java
index b11d097..98b4e01 100644
--- a/zhitan-system/src/main/java/com/zhitan/peakvalley/mapper/PeakValleyMapper.java
+++ b/zhitan-system/src/main/java/com/zhitan/peakvalley/mapper/PeakValleyMapper.java
@@ -38,4 +38,16 @@
     List<ElectricityDataItem> getDataStatisticsDeviationAnalysis(@Param("indexIdSet") Set<String> indexIdSet,
                                                  @Param("timeType") String timeType);
 
+    /**
+     * 鏌ヨ鎴愭湰瓒嬪娍
+     * @param beginTime
+     * @param endTime
+     * @param timeType 鏃堕棿绫诲瀷
+     * @param nodeId 鑺傜偣Id
+     * @param energyType 鑳芥簮绫诲瀷
+     * @return
+     */
+    List<ElectricityDataItem> getCostTrends(@Param("beginTime") Date beginTime, @Param("endTime") Date endTime,
+                                                 @Param("timeType") String timeType, @Param("nodeId") String nodeId,@Param("energyType") String energyType);
+
 }
diff --git a/zhitan-system/src/main/java/com/zhitan/realtimedata/service/impl/RealtimeDatabaseServiceImpl.java b/zhitan-system/src/main/java/com/zhitan/realtimedata/service/impl/RealtimeDatabaseServiceImpl.java
index 796fa5f..a06574d 100644
--- a/zhitan-system/src/main/java/com/zhitan/realtimedata/service/impl/RealtimeDatabaseServiceImpl.java
+++ b/zhitan-system/src/main/java/com/zhitan/realtimedata/service/impl/RealtimeDatabaseServiceImpl.java
@@ -178,6 +178,5 @@
         tagCodes.add(tagCode);
         List<TagValue> historyData = repository.getHistoryData(tagCodes, beginTime, endTime, interval);
         return historyData;
-//        return realtimeDatabaseManager.retrieve(tagCode, beginTime, endTime, retrievalModes, pointCount);
     }
 }
diff --git a/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/common/DateTimeUtil.java b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/common/DateTimeUtil.java
new file mode 100644
index 0000000..d38bfce
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/common/DateTimeUtil.java
@@ -0,0 +1,750 @@
+package com.zhitan.statisticalAnalysis.common;
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.zhitan.common.constant.CommonConst;
+import com.zhitan.common.constant.TimeTypeConst;
+import com.zhitan.common.utils.IntegerUtil;
+import com.zhitan.common.utils.StringUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.time.DateUtils;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+/**
+ * @Description: 鏃堕棿宸ュ叿绫�
+ * @author: yxw
+ * @date: 2022骞�02鏈�02鏃� 12:23
+ */
+@Slf4j
+public class DateTimeUtil {
+    /**
+     * 鏃ユ湡甯哥敤鏍煎紡
+     */
+    public static final String COMMON_PATTERN = "yyyy-MM-dd HH:mm:ss";
+    /**
+     * 鏍煎紡鍖栨棩鏈熷埌鍒嗛挓
+     */
+    public static final String COMMON_PATTERN_END_WITH_MINUTE = "yyyy-MM-dd HH:mm";
+    /**
+     * 鏃ユ湡鏍煎紡 - 灏忔椂:鍒嗛挓
+     */
+    public static final String COMMON_PATTERN_HOUR_MINUTE = "HH:mm";
+    /**
+     * 鏃ユ湡甯哥敤鏍煎紡 - 骞翠唤
+     */
+    public static final String COMMON_PATTERN_YEAR = "yyyy";
+    /**
+     * 鏃ユ湡甯哥敤鏍煎紡 - 鏌愪竴骞�,
+     */
+    public static final String COMMON_PATTERN_CERTAIN_YEAR = "yy";
+
+    /**
+     * 鏃ユ湡甯哥敤鏍煎紡 - 鏈堜唤
+     */
+    public static final String COMMON_PATTERN_MONTH = "yyyyMM";
+    /**
+     * 鏃ユ湡甯哥敤鏍煎紡 - 鏈堜唤
+     */
+    public static final String COMMON_PATTERN_TO_MONTH = "yyyy-MM";
+    /**
+     * 鏃ユ湡甯哥敤鏍煎紡 - 鏈堜唤
+     */
+    public static final String COMMON_PATTERN_TO_MONTH_WORD = "yyyy-MM鏈�";
+    /**
+     * 鏃ユ湡甯哥敤鏍煎紡 - 鏈堜唤
+     */
+    public static final String COMMON_PATTERN_TO_MONTH_ZH = "yyyy骞碝M鏈�";
+    /**
+     * 鏃ユ湡甯哥敤鏍煎紡 - 澶�
+     */
+    public static final String COMMON_PATTERN_DAY = "yyyyMMdd";
+    /**
+     * 鏃ユ湡甯哥敤鏍煎紡 - 澶�
+     */
+    public static final String COMMON_PATTERN_TO_DAY = "yyyy-MM-dd";
+    /**
+     * 鏃ユ湡甯哥敤鏍煎紡 - 澶�
+     */
+    public static final String COMMON_PATTERN_TO_DAY_WORD = "yyyy-MM-dd鏃�";
+    /**
+     * 鏃ユ湡甯哥敤鏍煎紡 - 鏈堟棩
+     */
+    public static final String COMMON_PATTERN_MONTH_DAY = "MM-dd";
+    /**
+     * 鏃ユ湡甯哥敤鏍煎紡 - 澶╂煇涓�澶�,
+     */
+    public static final String COMMON_PATTERN_DAY_OF_MONTH = "dd";
+    /**
+     * 鏃ユ湡甯哥敤鏍煎紡 - 灏忔椂
+     */
+    public static final String COMMON_PATTERN_HOUR = "yyyyMMddHH";
+    /**
+     * 鏃ユ湡甯哥敤鏍煎紡 - 灏忔椂
+     */
+    public static final String COMMON_PATTERN_TO_HOUR = "yyyy-MM-dd HH";
+    /**
+     * 鏃ユ湡甯哥敤鏍煎紡 - 灏忔椂
+     */
+    public static final String COMMON_PATTERN_TO_HOUR_WORD = "yyyy-MM-dd HH鏃�";
+    /**
+     * 鏃ユ湡甯哥敤鏍煎紡 - 灏忔椂
+     */
+    public static final String COMMON_PATTERN_TO_HOUR_TEXT = "yyyy骞碝M鏈坉d鏃� HH鏃�";
+
+    /**
+     * 鑾峰彇褰撳墠鏃堕棿,鏃堕棿鏍煎紡锛歽yyy-MM-dd HH:mm:ss
+     *
+     * @return
+     */
+    public static String getNowDateTime() {
+        return getNowDateTime(COMMON_PATTERN);
+    }
+
+    /**
+     * 鑾峰彇褰撳墠鏃堕棿
+     *
+     * @param pattern 鏃堕棿鏍煎紡
+     * @return
+     */
+    public static String getNowDateTime(String pattern) {
+        //璁剧疆鏃ユ湡鏍煎紡
+        SimpleDateFormat df = new SimpleDateFormat(pattern);
+        String dateTime = df.format(new Date());
+        return dateTime;
+    }
+
+    /**
+     * 鑾峰彇浠婂勾鐨勫勾浠藉��
+     *
+     * @return
+     */
+    public static String getNowYear() {
+        return getNowDateTime(COMMON_PATTERN_YEAR);
+    }
+
+    /**
+     * 鑾峰彇浠婂勾鐨勬湀浠藉��
+     *
+     * @return
+     */
+    public static String getNowMonth() {
+        return getNowDateTime(COMMON_PATTERN_MONTH);
+    }
+
+    /**
+     * 瀛楃涓茶浆鎴愭椂闂寸被鍨�,榛樿鏍煎紡锛歽yyy-MM-dd HH:mm:ss
+     *
+     * @param dateTimeStr
+     * @return
+     */
+    public static Date toDateTime(String dateTimeStr) {
+        DateTime dt = null;
+        try {
+            dt = DateTime.of(dateTimeStr, COMMON_PATTERN);
+        } catch (Exception e) {
+
+        }
+        return dt;
+    }
+
+    /**
+     * 瀛楃涓茶浆鎴愭椂闂寸被鍨�
+     *
+     * @param dateTimeStr
+     * @return
+     */
+    public static Date toDateTime(String dateTimeStr, String pattern) {
+        DateTime dt = null;
+        try {
+            dt = DateTime.of(dateTimeStr, pattern);
+        } catch (Exception e) {
+
+        }
+        return dt;
+    }
+
+    /**
+     * 瀛楃涓茶浆鎴愮壒瀹氭牸寮忕殑鏃堕棿瀛楃涓茬被鍨�
+     *
+     * @param dateTimeStr   鏃堕棿瀛楃涓�
+     * @param sourcePattern 瀛楃涓叉椂闂存牸寮�
+     * @param toPattern     瑕佽浆鎴愪粈涔堟牸寮忕殑鏃堕棿
+     * @return
+     */
+    public static String toDateTimeStr(String dateTimeStr, String sourcePattern, String toPattern) {
+        String str = CommonConst.EMPTY;
+        try {
+            DateTime dt = DateTime.of(dateTimeStr, sourcePattern);
+            str = getDateTime(dt, toPattern);
+        } catch (Exception e) {
+
+        }
+        return str;
+    }
+
+    /**
+     * 鏃堕棿杞垚鎸囧畾鐨勬牸寮�
+     *
+     * @param pattern 鏃堕棿鏍煎紡
+     * @return
+     */
+    public static String getDateTime(Date dt, String pattern) {
+        //璁剧疆鏃ユ湡鏍煎紡
+        SimpleDateFormat df = new SimpleDateFormat(pattern);
+        return df.format(dt);
+    }
+
+    /**
+     * 鏃堕棿杞垚yyyy-MM-dd HH:mm:ss鏍煎紡
+     *
+     * @return
+     */
+    public static String getDateTime(Date dt) {
+        if (ObjectUtil.isEmpty(dt)) {
+            return CommonConst.EMPTY;
+        }
+        return getDateTime(dt, COMMON_PATTERN);
+    }
+
+    /**
+     * 鑾峰彇褰撳墠鏃堕棿鎵�灞炴湀浠界殑鏈�鍚庝竴澶�
+     *
+     * @return
+     */
+    public static int getDateTimeLastDay(Date dt) {
+        String month = getMonth(dt);
+        String firstDate = month + "01";
+        Date nextMonthFirstDate = addMonths(toDateTime(firstDate, COMMON_PATTERN_DAY), CommonConst.DIGIT_1);
+        Date currentMonthLastDate = addDays(nextMonthFirstDate, CommonConst.DIGIT_MINUS_1);
+        int day = IntegerUtil.toInt(getDateTime(currentMonthLastDate, COMMON_PATTERN_DAY_OF_MONTH));
+        return day;
+    }
+
+    /**
+     * 鑾峰彇骞翠唤鍊�
+     *
+     * @return
+     */
+    public static String getYear(Date dt) {
+        return getDateTime(dt, COMMON_PATTERN_YEAR);
+    }
+
+    /**
+     * 鑾峰彇鏈堜唤鍊� 202202
+     *
+     * @return
+     */
+    public static String getMonth(Date dt) {
+        return getDateTime(dt, COMMON_PATTERN_MONTH);
+    }
+
+    /**
+     * 鑾峰彇澶�,鏍煎紡锛歽yyyMMdd
+     *
+     * @return
+     */
+    public static String toDay(Date dt) {
+        return getDateTime(dt, COMMON_PATTERN_DAY);
+    }
+
+    /**
+     * 鑾峰彇灏忔椂:yyyyMMddHH
+     *
+     * @return
+     */
+    public static String toHour(Date dt) {
+        return getDateTime(dt, COMMON_PATTERN_HOUR);
+    }
+
+    /**
+     * 杞垚瀛楃涓茬被鍨嬪��
+     *
+     * @return
+     */
+    public static String toString(Date dt) {
+        return getDateTime(dt, COMMON_PATTERN);
+    }
+
+    /**
+     * 鏃堕棿澧炲姞瀵瑰簲鐨勫勾鏁�
+     *
+     * @param dateTime
+     * @param years
+     * @return
+     */
+    public static Date addYears(Date dateTime, int years) {
+        return calcDate(dateTime, years, Calendar.YEAR);
+    }
+
+    /**
+     * 鏃堕棿澧炲姞瀵瑰簲鐨勬湀鏁�
+     *
+     * @param dateTime
+     * @param months
+     * @return
+     */
+    public static Date addMonths(Date dateTime, int months) {
+        return calcDate(dateTime, months, Calendar.MONTH);
+    }
+
+    /**
+     * 鏃堕棿澧炲姞瀵瑰簲鐨勫ぉ鏁�
+     *
+     * @param dateTime
+     * @param days
+     * @return
+     */
+    public static Date addDays(Date dateTime, int days) {
+        return calcDate(dateTime, days, Calendar.DATE);
+    }
+
+    /**
+     * 鏃堕棿澧炲姞瀵瑰簲鐨勫皬鏃舵暟
+     *
+     * @param dateTime
+     * @param hours
+     * @return
+     */
+    public static Date addHours(Date dateTime, int hours) {
+        return calcDate(dateTime, hours, Calendar.HOUR);
+    }
+
+    /**
+     * 鏃堕棿澧炲姞瀵瑰簲鐨勫垎閽熸暟
+     *
+     * @param dateTime
+     * @param minutes
+     * @return
+     */
+    public static Date addMinutes(Date dateTime, int minutes) {
+        return calcDate(dateTime, minutes, Calendar.MINUTE);
+    }
+
+    /**
+     * 鏃堕棿澧炲姞瀵瑰簲鐨勫皬鏃舵暟
+     *
+     * @param dateTime
+     * @param seconds
+     * @return
+     */
+    public static Date addSeconds(Date dateTime, int seconds) {
+        return calcDate(dateTime, seconds, Calendar.SECOND);
+    }
+
+    /**
+     * 璁$畻鏃ユ湡閫氱敤鏂规硶
+     *
+     * @param dateTime
+     * @param addValue
+     * @param calendarType 璁$畻绫诲瀷锛欳alendar.YEAR锛孋alendar.MONTH,Calendar.DAY
+     * @return
+     */
+    private static Date calcDate(Date dateTime, int addValue, int calendarType) {
+        Date dt = null;
+        try {
+            Calendar calendar = new GregorianCalendar();
+            calendar.setTime(dateTime);
+            //鎶婃棩鏈熷線鍚庡鍔犱竴骞达紝鏁存暟寰�鍚庢帹锛岃礋鏁板線鍓嶇Щ
+            calendar.add(calendarType, addValue);
+            // 鑾峰彇鐩稿姞鎴栬�呯浉鍑忎箣鍚庣殑鏃堕棿鍊�
+            Date tempDt = calendar.getTime();
+            // 鎶婃椂闂磋浆鎴愭墍闇�瑕佺殑鏍煎紡
+            String temp = getDateTime(tempDt, COMMON_PATTERN);
+            dt = toDateTime(temp);
+        } catch (Exception e) {
+
+        }
+        return dt;
+    }
+
+    /**
+     * 鑾峰彇璇ユ椂闂村睘浜庡綋澶╃殑绗嚑涓皬鏃�
+     *
+     * @param dateTime
+     * @return
+     */
+    public static int getHourOfDay(Date dateTime) {
+        return getDateValue(dateTime, Calendar.HOUR_OF_DAY);
+    }
+
+    /**
+     * 鑾峰彇璇ユ椂闂村睘浜庡綋鏈堢殑绗嚑澶�
+     *
+     * @param dateTime
+     * @return
+     */
+    public static int getDayOfMonth(Date dateTime) {
+        return getDateValue(dateTime, Calendar.DAY_OF_MONTH);
+    }
+
+    /**
+     * 鑾峰彇璇ユ椂闂村睘浜庡綋鍛ㄧ殑绗嚑澶�
+     * 涓�鍛ㄧ殑绗竴澶╂槸鍛ㄦ棩
+     *
+     * @param dateTime
+     * @return
+     */
+    public static int getDayOfWeek(Date dateTime) {
+        return getDateValue(dateTime, Calendar.DAY_OF_WEEK);
+    }
+
+    /**
+     * 鑾峰彇璇ユ椂闂村睘浜庡勾鐨勭鍑犱釜鏈�
+     * 鏈堜唤鍊�+1鏄湡瀹炵殑褰撳墠鏈�
+     *
+     * @param dateTime
+     * @return 宸茬粡鍦ㄧ郴缁熶腑鑾峰彇鍊肩殑鍩虹涓婂姞1浜嗭紝鐜板湪鏄湡瀹炵殑褰撳墠鏈堜唤鍊�
+     */
+    public static int getMonthOfYear(Date dateTime) {
+        return getDateValue(dateTime, Calendar.MONTH) + 1;
+    }
+
+    /**
+     * 鑾峰彇褰撳ぉ鐨勭鍑犱釜灏忔椂/褰撴湀鐨勭鍑犲ぉ/褰撳勾鐨勭鍑犱釜鏈�
+     *
+     * @param dateTime     濡傛灉鏃堕棿鍊间负绌猴紝榛樿褰撳墠鏃堕棿
+     * @param calendarType
+     * @return
+     */
+    private static int getDateValue(Date dateTime, int calendarType) {
+        int value = 0;
+        try {
+            if (ObjectUtil.isEmpty(dateTime)) {
+                dateTime = new Date();
+            }
+            Calendar calendar = new GregorianCalendar();
+            calendar.setTime(dateTime);
+            value = calendar.get(calendarType);
+        } catch (Exception e) {
+
+        }
+        return value;
+    }
+
+    /**
+     * 瀵规瘮time1 鍜� time2 鐨勫ぇ灏�
+     *
+     * @param time1
+     * @param time2
+     * @return -1:time1灏忎簬time2;0:time1绛変簬time2;1:time1澶т簬time2;
+     */
+    public static int compareDateDiff(Date time1, Date time2) {
+        long diff = time1.getTime() - time2.getTime();
+        int res = 0;
+        if (diff > 0) {
+            res = 1;
+        } else if (diff < 0) {
+            res = -1;
+        }
+        return res;
+    }
+
+    /**
+     * 鑾峰彇鏌ヨdata_item鎵�闇�瑕佺殑timecode鍊�
+     *
+     * @param timeType 鏃ユ湡绫诲瀷
+     * @param date     鏃堕棿
+     * @return
+     */
+    public static String getTimeCode(String timeType, Date date) {
+        String timeCode = CommonConst.EMPTY;
+        if (ObjectUtil.isEmpty(date)) {
+            date = new Date();
+        }
+        timeType = StringUtil.ifEmptyOrNullReturnValue(timeType).toUpperCase();
+        switch (timeType) {
+            case TimeTypeConst.TIME_TYPE_HOUR:
+                timeCode = CommonConst.WORD_H + getDateTime(date, COMMON_PATTERN_HOUR);
+                break;
+            case TimeTypeConst.TIME_TYPE_DAY:
+                timeCode = CommonConst.WORD_D + getDateTime(date, COMMON_PATTERN_DAY);
+                break;
+            case TimeTypeConst.TIME_TYPE_MONTH:
+                timeCode = CommonConst.WORD_M + getDateTime(date, COMMON_PATTERN_MONTH);
+                break;
+            case TimeTypeConst.TIME_TYPE_YEAR:
+                timeCode = CommonConst.WORD_Y + getDateTime(date, COMMON_PATTERN_YEAR);
+                break;
+            default:
+                break;
+        }
+        return timeCode;
+    }
+
+    /**
+     * 鑾峰彇鏌ヨ鏃ユ湀骞存姤琛ㄦ墍闇�瑕佺殑timecode鍊�
+     *
+     * @param timeType 鏃ユ湡绫诲瀷
+     * @param date     鏃堕棿
+     * @return
+     */
+    public static String getReportTimeCode(String timeType, Date date) {
+        String timeCode = CommonConst.EMPTY;
+        if (ObjectUtil.isEmpty(date)) {
+            date = new Date();
+        }
+        timeType = StringUtil.ifEmptyOrNullReturnValue(timeType).toUpperCase();
+        switch (timeType) {
+            case TimeTypeConst.TIME_TYPE_HOUR:
+                timeCode = getDateTime(date, COMMON_PATTERN_TO_HOUR);
+                break;
+            case TimeTypeConst.TIME_TYPE_DAY:
+                timeCode = getDateTime(date, COMMON_PATTERN_TO_DAY);
+                break;
+            case TimeTypeConst.TIME_TYPE_MONTH:
+                timeCode = getDateTime(date, COMMON_PATTERN_TO_MONTH);
+                break;
+            case TimeTypeConst.TIME_TYPE_YEAR:
+                timeCode = getDateTime(date, COMMON_PATTERN_YEAR);
+                break;
+            default:
+                break;
+        }
+        return timeCode;
+    }
+
+    /**
+     * 鑾峰彇鏃堕棿瀵瑰簲鐨勭幆姣旀椂闂�
+     *
+     * @param timeType HOUR/DAY/MONTH/YEAR
+     * @param date     鏃堕棿鍊�
+     * @return
+     */
+    public static Date getLoopTime(String timeType, Date date) {
+        Date dt = null;
+        if (ObjectUtil.isEmpty(date)) {
+            date = new Date();
+        }
+        timeType = StringUtil.ifEmptyOrNullReturnValue(timeType).toUpperCase();
+        switch (timeType) {
+            case TimeTypeConst.TIME_TYPE_HOUR:
+                dt = addHours(date, CommonConst.DIGIT_MINUS_1);
+                break;
+            case TimeTypeConst.TIME_TYPE_DAY:
+                dt = addDays(date, CommonConst.DIGIT_MINUS_1);
+                break;
+            case TimeTypeConst.TIME_TYPE_MONTH:
+                dt = addMonths(date, CommonConst.DIGIT_MINUS_1);
+                break;
+            case TimeTypeConst.TIME_TYPE_YEAR:
+                dt = addYears(date, CommonConst.DIGIT_MINUS_1);
+                break;
+            default:
+                break;
+        }
+        return dt;
+    }
+
+    /**
+     * 鑾峰彇鏁寸偣鏃堕棿
+     *
+     * @param timeType HOUR/DAY/MONTH/YEAR
+     * @param date     鏃堕棿鍊�
+     * @return
+     */
+    public static Date getHourTime(String timeType, Date date) {
+        Date dt = null;
+        if (ObjectUtil.isEmpty(date)) {
+            date = new Date();
+        }
+        String tempStr = null;
+        timeType = StringUtil.ifEmptyOrNullReturnValue(timeType).toUpperCase();
+        switch (timeType) {
+            case TimeTypeConst.TIME_TYPE_HOUR:
+                tempStr = getDateTime(date, COMMON_PATTERN_TO_HOUR);
+                dt = toDateTime(tempStr, COMMON_PATTERN_TO_HOUR);
+                break;
+            case TimeTypeConst.TIME_TYPE_DAY:
+                tempStr = getDateTime(date, COMMON_PATTERN_TO_DAY);
+                dt = toDateTime(tempStr, COMMON_PATTERN_TO_DAY);
+                break;
+            case TimeTypeConst.TIME_TYPE_MONTH:
+                tempStr = getDateTime(date, COMMON_PATTERN_TO_MONTH);
+                dt = toDateTime(tempStr, COMMON_PATTERN_TO_MONTH);
+                break;
+            case TimeTypeConst.TIME_TYPE_YEAR:
+                tempStr = getDateTime(date, COMMON_PATTERN_YEAR);
+                dt = toDateTime(tempStr, COMMON_PATTERN_YEAR);
+                break;
+            default:
+                break;
+        }
+        return dt;
+    }
+
+    /**
+     * 璁$畻涓や釜鏃堕棿闂撮殧澶╂暟锛堟棩鏈熸牸寮忔瘮杈冿級
+     *
+     * @param beginTime
+     * @param endTime
+     * @return
+     */
+    public static int daysBetween(Date beginTime, Date endTime) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(beginTime);
+        long beginStamp = calendar.getTimeInMillis();
+        calendar.setTime(endTime);
+        long endStamp = calendar.getTimeInMillis();
+        long betweenDays = (endStamp - beginStamp) / (1000 * 3600 * 24);
+        return Integer.parseInt(String.valueOf(betweenDays));
+    }
+
+    /**
+     * 璁$畻涓や釜鏃堕棿闂撮殧澶╂暟锛堝瓧绗︿覆鏍煎紡姣旇緝锛�
+     *
+     * @param beginTime
+     * @param endTime
+     * @return
+     */
+    public static int daysBetween(String beginTime, String endTime) {
+        try {
+            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+            Date begin = format.parse(beginTime);
+            Date end = format.parse(endTime);
+            return daysBetween(begin, end);
+        } catch (ParseException exception) {
+            log.error("璁$畻涓や釜鏃堕棿闂撮殧澶╂暟" + exception.getMessage());
+            return 0;
+        }
+    }
+
+    /**
+     * 鏍规嵁鏃堕棿绫诲瀷鎶婂瓧绗︿覆杞垚瀵瑰簲鐨勬椂闂�
+     *
+     * @param timeType 鏃堕棿绫诲瀷
+     * @param time     鏃堕棿瀛楃涓�
+     * @return
+     */
+    public static Date getTime(String timeType, String time) {
+        Date dt = null;
+        timeType = StringUtil.ifEmptyOrNullReturnValue(timeType).toUpperCase();
+        switch (timeType) {
+            case TimeTypeConst.TIME_TYPE_HOUR:
+                dt = toDateTime(time, COMMON_PATTERN_TO_HOUR);
+                break;
+            case TimeTypeConst.TIME_TYPE_DAY:
+                dt = toDateTime(time, COMMON_PATTERN_TO_DAY);
+                break;
+            case TimeTypeConst.TIME_TYPE_MONTH:
+                dt = toDateTime(time, COMMON_PATTERN_TO_MONTH);
+                break;
+            case TimeTypeConst.TIME_TYPE_YEAR:
+                dt = toDateTime(time, COMMON_PATTERN_YEAR);
+                break;
+            default:
+                break;
+        }
+        return dt;
+    }
+
+    /**
+     * 鏍规嵁鏃堕棿绫诲瀷鎶婅繛缁殑鏃ユ湡瀛楃涓茶浆鎴愬搴旂殑鏃堕棿 锛�202303銆�20230303銆�2023030301銆�202303030101锛�
+     *
+     * @param timeType 鏃堕棿绫诲瀷
+     * @param time     鏃堕棿瀛楃涓�
+     * @return
+     */
+    public static Date getTimeByContinuousTimeCode(String timeType, String time) {
+        Date dt = null;
+        timeType = StringUtil.ifEmptyOrNullReturnValue(timeType).toUpperCase();
+        switch (timeType) {
+            case TimeTypeConst.TIME_TYPE_HOUR:
+                dt = toDateTime(time, COMMON_PATTERN_HOUR);
+                break;
+            case TimeTypeConst.TIME_TYPE_DAY:
+                dt = toDateTime(time, COMMON_PATTERN_DAY);
+                break;
+            case TimeTypeConst.TIME_TYPE_MONTH:
+                dt = toDateTime(time, COMMON_PATTERN_MONTH);
+                break;
+            case TimeTypeConst.TIME_TYPE_YEAR:
+                dt = toDateTime(time, COMMON_PATTERN_YEAR);
+                break;
+            default:
+                break;
+        }
+        return dt;
+    }
+
+    /**
+     * 鏍规嵁鏃堕棿绫诲瀷杩斿洖澶┿�佹湀銆佸勾鏈�鍚庣殑鏃堕棿
+     *
+     * @param timeType 鏃堕棿绫诲瀷
+     * @param time     鏃堕棿
+     * @return
+     */
+    public static Date getEndTimeByType(String timeType, Date time) {
+        Date dt = null;
+        switch (timeType) {
+            case TimeTypeConst.TIME_TYPE_DAY:
+                dt = DateUtil.endOfDay(time);
+                break;
+            case TimeTypeConst.TIME_TYPE_MONTH:
+                dt = DateUtil.endOfMonth(time);
+                break;
+            case TimeTypeConst.TIME_TYPE_YEAR:
+                dt = DateUtil.endOfYear(time);
+                break;
+            default:
+                break;
+        }
+        return dt;
+    }
+
+    /**
+     * 鏍规嵁鍛ㄦ湡绫诲瀷瀵圭敓浜у懆鏈熻繘琛屽姞鍑忚绠�
+     * 濉姤鍛ㄦ湡绫诲瀷锛圚OUR灏忔椂銆丏AY澶┿�丮ONTH鏈堛�乊EAR骞达級
+     *
+     * @param date      鐢熶骇鍛ㄦ湡
+     * @param cycleType 鐢熶骇鍛ㄦ湡绫诲瀷
+     * @param cycleType 鐢熶骇鍛ㄦ湡绫诲瀷
+     * @param val 璁$畻鍊�
+     * @return
+     */
+    public static Date productionCycleCal(Date date, String cycleType,int val) {
+        Date momDate = date;
+        switch (cycleType) {
+            case TimeTypeConst.TIME_TYPE_HOUR:
+                momDate = DateUtils.addHours(date, val);
+                break;
+            case TimeTypeConst.TIME_TYPE_DAY:
+                momDate = DateUtils.addDays(date, val);
+                break;
+            case TimeTypeConst.TIME_TYPE_MONTH:
+                momDate = DateUtils.addMonths(date, val);
+                break;
+        }
+        return momDate;
+    }
+
+    /**
+     * 鏍规嵁鍛ㄦ湡绫诲瀷瀵圭敓浜у懆鏈熻繘琛屽姞鍑忚绠� 骞朵笖杩涗綅  渚嬪锛� HOUR +1杩涗綅灏辨槸 鍔犱竴澶�
+     * 濉姤鍛ㄦ湡绫诲瀷锛圚OUR灏忔椂銆丏AY澶┿�丮ONTH鏈堛�乊EAR骞达級
+     *
+     * @param date      鐢熶骇鍛ㄦ湡
+     * @param cycleType 鐢熶骇鍛ㄦ湡绫诲瀷
+     * @param val 璁$畻鍊�
+     * @return
+     */
+    public static Date productionCycleCalCarry(Date date, String cycleType,int val) {
+        Date momDate = date;
+        switch (cycleType) {
+            case TimeTypeConst.TIME_TYPE_HOUR:
+                momDate = DateUtils.addDays(date, val);
+                break;
+            case TimeTypeConst.TIME_TYPE_DAY:
+                momDate = DateUtils.addMonths(date, val);
+                break;
+            case TimeTypeConst.TIME_TYPE_MONTH:
+                momDate = DateUtils.addYears(date, val);
+                break;
+        }
+        return momDate;
+    }
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/CostTrendEnergyTypeItem.java b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/CostTrendEnergyTypeItem.java
new file mode 100644
index 0000000..6ccf9a9
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/CostTrendEnergyTypeItem.java
@@ -0,0 +1,47 @@
+package com.zhitan.statisticalAnalysis.domain.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+
+/**
+ * 鎴愭湰瓒嬪娍-鑳芥簮绫诲瀷
+ *
+ * @Author: Zhujw
+ * @Date: 2023/2/14
+ */
+@Data
+@ApiModel(value = "鎴愭湰瓒嬪娍-鑳芥簮绫诲瀷", description = "鎴愭湰瓒嬪娍-鑳芥簮绫诲瀷")
+public class CostTrendEnergyTypeItem implements Serializable {
+
+    /**
+     * 鑳芥簮绫诲瀷
+     */
+    @ApiModelProperty(value = "鑳芥簮绫诲瀷")
+    private String energyType;
+
+    /**
+     * 鑳芥簮鍚嶇О
+     */
+    @ApiModelProperty(value = "鑳芥簮鍚嶇О")
+    private String energyName;
+
+    /**
+     * 绱Н閲�
+     */
+    @ApiModelProperty(value = "绱Н閲�")
+    @JsonFormat(shape = JsonFormat.Shape.STRING)
+    private BigDecimal accumulation;
+
+    /**
+     * 璐圭敤
+     */
+    @ApiModelProperty(value = "璐圭敤")
+    @JsonFormat(shape = JsonFormat.Shape.STRING)
+    private BigDecimal cost;
+}
\ No newline at end of file
diff --git a/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyConsumeTrendDetailItem.java b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyConsumeTrendDetailItem.java
new file mode 100644
index 0000000..ccc4a25
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyConsumeTrendDetailItem.java
@@ -0,0 +1,83 @@
+package com.zhitan.statisticalAnalysis.domain.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+
+/**
+ * 璐圭敤鍒嗘瀽-鎴愭湰瓒嬪娍鍒嗘瀽缁熻鍥捐繑鍥炲�间俊鎭�
+ *
+ * @Author: Zhujw
+ * @Date: 2023/2/14
+*/
+@Data
+@ApiModel(value = "璐圭敤鍒嗘瀽-鎴愭湰瓒嬪娍鍒嗘瀽缁熻鍥捐繑鍥炲�间俊鎭�", description = "璐圭敤鍒嗘瀽-鎴愭湰瓒嬪娍鍒嗘瀽缁熻鍥捐繑鍥炲�间俊鎭�")
+public class EnergyConsumeTrendDetailItem {
+
+    /**
+     *  鑳芥簮绫诲瀷
+     */
+    @ApiModelProperty(value = "鑳芥簮绫诲瀷")
+    private String energyType;
+
+    /**
+     *  鑳芥簮鍗曚綅
+     */
+    @ApiModelProperty(value = "鑳芥簮鍗曚綅")
+    private String energyUnit;
+
+    /**
+     *  绱Н閲忔爣绛�
+     */
+    @ApiModelProperty(value = "绱Н閲忔爣绛�")
+    private String accumulationLabel;
+
+    /**
+     *  璐圭敤鏍囩
+     */
+    @ApiModelProperty(value = "璐圭敤鏍囩")
+    private String costLabel;
+
+    /**
+     * 绱Н閲�
+     */
+    @ApiModelProperty(value = "绱Н閲�")
+    @JsonFormat(shape = JsonFormat.Shape.STRING)
+    private BigDecimal accumulation;
+
+    /**
+     * 璐圭敤
+     */
+    @ApiModelProperty(value = "璐圭敤")
+    @JsonFormat(shape = JsonFormat.Shape.STRING)
+    private BigDecimal cost;
+
+    /**
+     * 绱Н閲弅ey闆嗗悎
+     */
+    @ApiModelProperty(value = "绱Н閲弅ey闆嗗悎")
+    private List<String> accumulationKeyList;
+
+    /**
+     * 绱Н閲弙alue闆嗗悎
+     */
+    @ApiModelProperty(value = "绱Н閲弙alue闆嗗悎")
+    private List<BigDecimal> accumulationValueList;
+
+    /**
+     * 璐圭敤key闆嗗悎
+     */
+    @ApiModelProperty(value = "璐圭敤key闆嗗悎")
+    private List<String> costKeyList;
+
+    /**
+     * 璐圭敤value闆嗗悎
+     */
+    @ApiModelProperty(value = "璐圭敤value闆嗗悎")
+    private List<BigDecimal> costValueList;
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyConsumeVO.java b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyConsumeVO.java
new file mode 100644
index 0000000..c38a70e
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyConsumeVO.java
@@ -0,0 +1,43 @@
+package com.zhitan.statisticalAnalysis.domain.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+
+/**
+ * 鑳借�楀疄浣撶被
+ *
+ * @Author: Zhujw
+ * @Date: 2023/1/28
+ */
+@Data
+public class EnergyConsumeVO implements Serializable {
+
+    /**
+     * 璁¢噺鍣ㄥ叿id
+     */
+    private String deviceId;
+
+    /**
+     * 鑳芥簮绫诲瀷
+     */
+    private String energyType;
+
+    /**
+     * 鏃堕棿缂栫爜
+     */
+    private Date dataTime;
+
+    /**
+     * 璐圭敤
+     */
+    private BigDecimal costValue;
+
+    /**
+     * 绱閲�
+     */
+    private BigDecimal accumulationValue;
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyCostTrendItem.java b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyCostTrendItem.java
new file mode 100644
index 0000000..2d5b8d4
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyCostTrendItem.java
@@ -0,0 +1,51 @@
+package com.zhitan.statisticalAnalysis.domain.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 鎴愭湰瓒嬪娍鍒嗘瀽-琛ㄦ牸淇℃伅
+ *
+ * @Author: Zhujw
+ * @Date: 2023/2/14
+ */
+@Data
+@ApiModel(value = "鎴愭湰瓒嬪娍鍒嗘瀽-琛ㄦ牸淇℃伅", description = "鎴愭湰瓒嬪娍鍒嗘瀽-琛ㄦ牸淇℃伅")
+public class EnergyCostTrendItem {
+
+    /**
+     * 鐢ㄨ兘鍗曞厓id
+     */
+    @ApiModelProperty(value = "鐢ㄨ兘鍗曞厓id")
+    private String energyUnitId;
+
+    /**
+     * 鐢ㄨ兘鍗曞厓鍚嶇О
+     */
+    @ApiModelProperty(value = "鐢ㄨ兘鍗曞厓鍚嶇О")
+    private String energyUnitName;
+
+    /**
+     * 鎬昏垂鐢�
+     */
+    @ApiModelProperty(value = "鎬昏垂鐢�")
+    @JsonFormat(shape = JsonFormat.Shape.STRING)
+    private BigDecimal total;
+
+    /**
+     * 鏃堕棿
+     */
+    @ApiModelProperty(value = "鏃堕棿")
+    private String dateCode;
+
+    /**
+     * 鑳芥簮绫诲瀷
+     */
+    @ApiModelProperty(value = "鑳芥簮绫诲瀷")
+    private List<CostTrendEnergyTypeItem> itemList;
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyCostTrendPage.java b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyCostTrendPage.java
new file mode 100644
index 0000000..a865034
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyCostTrendPage.java
@@ -0,0 +1,22 @@
+package com.zhitan.statisticalAnalysis.domain.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @Description: TODO
+ * @author: yxw
+ * @date: 2022骞�04鏈�15鏃� 10:07
+ */
+@Data
+public class EnergyCostTrendPage {
+    /**
+     * 鏁版嵁鍒楄〃
+     */
+    private List<EnergyCostTrendItem> itemList;
+    /**
+     * 璁板綍鎬绘暟閲�
+     */
+    private long total;
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyTypeValueContrastedVO.java b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyTypeValueContrastedVO.java
new file mode 100644
index 0000000..e598661
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/EnergyTypeValueContrastedVO.java
@@ -0,0 +1,62 @@
+package com.zhitan.statisticalAnalysis.domain.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 鍚勮兘婧愮被鍨嬪�煎悓姣斻�佺幆姣擵O
+ *
+ * @Author: Zhujw
+ * @Date: 2023/2/8
+ */
+@Data
+public class EnergyTypeValueContrastedVO {
+
+    /**
+     * 鐢ㄨ兘鍗曞厓鍚嶇О
+     */
+    @ApiModelProperty(value = "鐢ㄨ兘鍗曞厓鍚嶇О")
+    private String energyUnitName;
+
+    /**
+     * 鑳芥簮绫诲瀷
+     */
+    @ApiModelProperty(value = "鑳芥簮绫诲瀷")
+    private String energyType;
+
+    /**
+     * 鏈湡鏃堕棿
+     */
+    @ApiModelProperty(value = "鏈湡鏃堕棿")
+    private String currentTime;
+
+    /**
+     * 鏈湡鍊�
+     */
+    @ApiModelProperty(value = "鏈湡鍊�")
+    private BigDecimal currentValue;
+
+    /**
+     * 瀵规瘮鏃堕棿
+     */
+    @ApiModelProperty(value = "瀵规瘮鏃堕棿")
+    private String compareTime;
+
+    /**
+     * 瀵规瘮鍊�
+     */
+    @ApiModelProperty(value = "瀵规瘮鍊�")
+    private BigDecimal contrastValues;
+
+    /**
+     * 鍚屾瘮鍊�
+     * 鍚屾瘮澧為暱鐜�=锛堟湰鏈熷��-鍘诲勾鍚屾湡鍊硷級/鍘诲勾鍚屾湡鍊济�100%
+     * 鐜瘮鍊�
+     * 鐜瘮澧為暱鐜�=锛堟湰鏈熷��-涓婃湡鍊硷級/涓婃湡鍊济�100%
+     */
+    @ApiModelProperty(value = "鍚屾瘮澧為暱鐜�/鐜瘮澧為暱鐜�")
+    private BigDecimal ratio;
+
+}
\ No newline at end of file
diff --git a/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/QueryCompareRequest.java b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/QueryCompareRequest.java
new file mode 100644
index 0000000..71998cb
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/QueryCompareRequest.java
@@ -0,0 +1,49 @@
+package com.zhitan.statisticalAnalysis.domain.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotBlank;
+
+/**
+ * @Description: 鏁版嵁鏌ヨ鏉′欢瀹炰綋
+ * @author: yxw
+ * @date: 2022骞�01鏈�28鏃� 14:49
+ */
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value="QueryCompareRequest", description="鑾峰彇鏁版嵁鐨勫弬鏁板疄浣�")
+public class QueryCompareRequest {
+
+    /**
+     * 鏌ヨ鏃堕棿绫诲瀷,瀵瑰簲甯搁噺绫伙細TimeTypeConst
+     */
+    @NotBlank(message = "鏃堕棿绫诲瀷涓嶈兘涓虹┖")
+    @ApiModelProperty(value = "鏌ヨ鏃堕棿绫诲瀷,瀵瑰簲甯搁噺锛欴AY/MONTH/SEASON/YEAR锛岄粯璁ONTH")
+    private String timeType;
+
+    /**
+     * 鏃ユ湡鍊硷紝鏈堜唤(202201-202212)銆佸勾浠�(2022-~)
+     */
+    @NotBlank(message = "鏃堕棿缂栫爜涓嶈兘涓虹┖")
+    @ApiModelProperty(value = "鏃ユ湡鍊硷紝鏈堜唤(202201-202212)銆佸勾浠�(2022-~)")
+    private String timeCode;
+
+    /**
+     * 鑺傜偣Id
+     */
+    @NotBlank(message = "鑺傜偣Id")
+    @ApiModelProperty(value = "鑺傜偣Id")
+    private String nodeId;
+
+    /**
+     * 鑳芥簮绫诲瀷锛岄�氳繃/闅斿紑,water/gas
+     */
+    @ApiModelProperty(value = "鑳芥簮绫诲瀷锛岄�氳繃/闅斿紑,water/gas")
+    private String energyType;
+
+}
\ No newline at end of file
diff --git a/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/service/IEnergyConsumeDataService.java b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/service/IEnergyConsumeDataService.java
new file mode 100644
index 0000000..382d099
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/service/IEnergyConsumeDataService.java
@@ -0,0 +1,44 @@
+package com.zhitan.statisticalAnalysis.service;
+
+import com.zhitan.statisticalAnalysis.domain.vo.*;
+
+import java.util.List;
+
+/**
+ * 鑳芥簮娑堣�楃粺璁$浉鍏虫煡璇�
+ */
+public interface IEnergyConsumeDataService {
+
+    /**
+     * 鎴愭湰瓒嬪娍鍒嗘瀽锛堣兘婧愭秷鑰楁垚鏈級- 鑾峰彇琛ㄦ牸鍒楄〃鏁版嵁
+     *
+     * @param pageNo   椤电爜鏁�
+     * @param pageSize 姣忛〉鏁版嵁澶氬皯
+     * @param timeCode 鏃堕棿鍊�   涓庢椂闂寸被鍨嬪搴旓細2022-03-21/2022-03/2022
+     * @param timeType 鏃堕棿绫诲瀷 DAY/MONTH/YEAR
+     * @param energyType 鑳芥簮绫诲瀷
+     * @param modelCode 妯″瀷Code
+     * @return
+     */
+    EnergyCostTrendPage listEnergyCostTrend(int pageNo, int pageSize, String timeCode, String timeType,String energyType, String modelCode);
+
+    /**
+     * 鎴愭湰瓒嬪娍鍒嗘瀽锛堣兘婧愭秷鑰楁垚鏈級
+     *
+     * @param timeCode 鏃堕棿鍊�   涓庢椂闂寸被鍨嬪搴旓細2022-03-21/2022-03/2022
+     * @param timeType 鏃堕棿绫诲瀷 DAY/MONTH/YEAR
+     * @param modelCode   妯″瀷Code
+     * @param energyType 鑳芥簮绫诲瀷
+     * @return
+     */
+    List<EnergyConsumeTrendDetailItem> listEnergyCostTrendDetail(String timeCode, String timeType, String modelCode, String energyType);
+
+    /**
+     * 鍚屾瘮鐜瘮鍒嗘瀽
+     *
+     * @param req            璇锋眰鍙傛暟
+     * @param comparisonType 瀵规瘮绫诲瀷
+     * @return
+     */
+    public List<EnergyTypeValueContrastedVO> listEnergyTypeYoyInfo(QueryCompareRequest req, String comparisonType);
+}
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);
+    }
+}
diff --git a/zhitan-system/src/main/resources/mapper/dataitem/DataItemMapper.xml b/zhitan-system/src/main/resources/mapper/dataitem/DataItemMapper.xml
index 37b928f..e06ddbe 100644
--- a/zhitan-system/src/main/resources/mapper/dataitem/DataItemMapper.xml
+++ b/zhitan-system/src/main/resources/mapper/dataitem/DataItemMapper.xml
@@ -215,4 +215,22 @@
         AND ( begin_time BETWEEN #{beginTime} AND #{endTime} )
         AND time_type = #{timeType}
     </select>
+
+    <select id="getDataItemTimeRangeValueByNodeId" resultType="java.math.BigDecimal">
+        SELECT
+        COALESCE (SUM ( "value" ), 0)
+        FROM
+        "data_item" di
+        JOIN energy_index ei  ON di.index_id = ei.index_id
+        WHERE
+        di.index_id IN ( SELECT index_id FROM node_index WHERE node_id = #{nodeId})
+        <if test="energyType !='' and energyType !=null  and energyType =='allType'">
+            AND ei.energy_id != ''
+        </if>
+        <if test="energyType !='' and energyType !=null  and energyType !='allType'">
+            AND  ei.energy_id = #{energyType}
+        </if>
+        AND (di.data_time BETWEEN #{beginTime} AND #{endTime})
+        AND di.time_type = #{timeType}
+    </select>
 </mapper>
\ No newline at end of file
diff --git a/zhitan-system/src/main/resources/mapper/peakvalley/ElectricityDataItemMapper.xml b/zhitan-system/src/main/resources/mapper/peakvalley/ElectricityDataItemMapper.xml
index 2676c7d..d478107 100644
--- a/zhitan-system/src/main/resources/mapper/peakvalley/ElectricityDataItemMapper.xml
+++ b/zhitan-system/src/main/resources/mapper/peakvalley/ElectricityDataItemMapper.xml
@@ -49,4 +49,30 @@
 
         AND time_type = #{timeType}
     </select>
+    <select id="getCostTrends"
+            resultType="com.zhitan.peakvalley.domain.ElectricityDataItem">
+        SELECT
+        di.index_code,
+        di.time_code,
+        di.electricity_type,
+        di.data_time,
+        di.electricity,
+        di.cost,
+        di.time_type,
+        di.price,
+        di.remark
+        FROM
+        "electricity_data_item" di
+        JOIN energy_index ei  ON di.index_id = ei.index_id
+        WHERE
+        di.index_id IN ( SELECT index_id FROM node_index WHERE node_id = #{nodeId})
+        <if test="energyType !='' and energyType !=null  and energyType =='allType'">
+            AND ei.energy_id != ''
+        </if>
+        <if test="energyType !='' and energyType !=null  and energyType !='allType'">
+            AND  ei.energy_id = #{energyType}
+        </if>
+        AND (di.data_time BETWEEN #{beginTime} AND #{endTime})
+        AND di.time_type = #{timeType}
+    </select>
 </mapper>
\ No newline at end of file
diff --git a/zhitan-vue/src/api/cost/api.js b/zhitan-vue/src/api/cost/api.js
new file mode 100644
index 0000000..c0e5595
--- /dev/null
+++ b/zhitan-vue/src/api/cost/api.js
@@ -0,0 +1,16 @@
+import request from "@/utils/request"
+
+export function listEnergyCostTrend(query) {
+  return request({
+    url: "/energyTypeAnalysis/listEnergyCostTrend",
+    method: "get",
+    params: query,
+  })
+}
+export function listEnergyCostTrendDetail(query) {
+  return request({
+    url: "/energyTypeAnalysis/listEnergyCostTrendDetail",
+    method: "get",
+    params: query,
+  })
+}
diff --git a/zhitan-vue/src/api/powerquality/electric-power-factor/api.js b/zhitan-vue/src/api/powerquality/electric-power-factor/api.js
new file mode 100644
index 0000000..1b9a7c3
--- /dev/null
+++ b/zhitan-vue/src/api/powerquality/electric-power-factor/api.js
@@ -0,0 +1,9 @@
+import request from "@/utils/request"
+// 鑾峰彇鐢ㄨ兘鍗曞厓涓嬬殑鏌愪釜鐢佃〃鐨勫姛鐜囧洜鏁版暟鎹�
+export function powerFactorAnalysisDetail(params) {
+  return request({
+    url: "/powerFactorAnalysis/detail",
+    method: "get",
+    params,
+  })
+}
diff --git a/zhitan-vue/src/api/powerquality/electricThreePhase/api.js b/zhitan-vue/src/api/powerquality/electricThreePhase/api.js
new file mode 100644
index 0000000..cf8072c
--- /dev/null
+++ b/zhitan-vue/src/api/powerquality/electricThreePhase/api.js
@@ -0,0 +1,10 @@
+import request from "@/utils/request"
+
+// 鑾峰彇涓夌浉涓嶅钩琛″垎鏋愭暟鎹�
+export function threePhaseUnbalanceAnalysisDetail(params) {
+  return request({
+    url: "/threePhaseUnbalanceAnalysis/detail",
+    method: "get",
+    params,
+  })
+}
diff --git a/zhitan-vue/src/api/powerquality/load-analysis/api.js b/zhitan-vue/src/api/powerquality/load-analysis/api.js
new file mode 100644
index 0000000..b6859f4
--- /dev/null
+++ b/zhitan-vue/src/api/powerquality/load-analysis/api.js
@@ -0,0 +1,28 @@
+import request from "@/utils/request"
+
+// 鑾峰彇鐢ㄨ兘鍗曞厓涓嬬殑鐢佃〃鍒楄〃
+export function listElectricityMeter(params) {
+  return request({
+    url: "/meter/listElectricityMeter",
+    method: "get",
+    params,
+  })
+}
+
+// 鑾峰彇鐢ㄨ兘鍗曞厓涓嬬殑鏌愪釜鐢佃〃鐨勮礋鑽峰垎鏋愭暟鎹�
+export function loadAnalysisDetail(params) {
+  return request({
+    url: "/loadAnalysis/detail",
+    method: "get",
+    params,
+  })
+}
+
+// 鑾峰彇鐢ㄨ兘鍗曞厓涓嬬殑鐢佃〃鍒楄〃-瀹炰綋琛�
+export function listElectricityDeviceMeter(params) {
+  return request({
+    url: "/loadAnalysis/listElectricMeter",
+    method: "get",
+    params,
+  })
+}
diff --git a/zhitan-vue/src/api/realTimeMonitor/historyDataTrend.js b/zhitan-vue/src/api/realTimeMonitor/historyDataTrend.js
new file mode 100644
index 0000000..3201d12
--- /dev/null
+++ b/zhitan-vue/src/api/realTimeMonitor/historyDataTrend.js
@@ -0,0 +1,16 @@
+import request from "@/utils/request"
+
+export function getHistoricalDataByIndexId(query) {
+  return request({
+    url: "/dataMonitoring/historyDataTrend/getHistoricalDataByIndexId",
+    method: "get",
+    params: query,
+  })
+}
+export function getEnergyIndexByModelId(query) {
+  return request({
+    url: "/basicsetting/model/getEnergyIndexByModelId",
+    method: "get",
+    params: query,
+  })
+}
diff --git a/zhitan-vue/src/assets/styles/ruoyi.scss b/zhitan-vue/src/assets/styles/ruoyi.scss
index 505048c..cd8f03c 100644
--- a/zhitan-vue/src/assets/styles/ruoyi.scss
+++ b/zhitan-vue/src/assets/styles/ruoyi.scss
@@ -569,6 +569,19 @@
   .el-tabs__item.is-active {
     color: #409EFF;
   }
+
+  .el-descriptions__cell {
+    background: transparent;
+    color: #fff !important;
+  }
+  .el-descriptions__body {
+    background-color: transparent;
+    color: #fff;
+  }
+  .el-descriptions__label {
+    color: #fff !important;
+    background-color: #1a235d !important;
+  }
 }
 
 
diff --git a/zhitan-vue/src/components/Echarts/LineChart.vue b/zhitan-vue/src/components/Echarts/LineChart.vue
new file mode 100644
index 0000000..8703363
--- /dev/null
+++ b/zhitan-vue/src/components/Echarts/LineChart.vue
@@ -0,0 +1,182 @@
+<template>
+  <div class="chart-item">
+    <div :id="domId" style="width: 100%; height: 100%"></div>
+  </div>
+</template>
+
+<script setup>
+import * as echarts from "echarts"
+const { proxy } = getCurrentInstance()
+import useSettingsStore from "@/store/modules/settings"
+const settingsStore = useSettingsStore()
+const emit = defineEmits()
+const props = defineProps({
+  chartData: {
+    type: Object,
+    default: () => {},
+  },
+  chartType: {
+    type: String,
+    default: "line", // bar
+  },
+  domId: {
+    type: String,
+    default: "ChartDom",
+  },
+})
+
+watch(
+  () => props.chartData,
+  (val) => {
+    console.log("watch", val)
+    initChart()
+  }
+)
+watch(
+  () => settingsStore.sideTheme,
+  (val) => {
+    initChart()
+  }
+)
+
+onMounted(() => {
+  initChart()
+})
+
+function initChart(value) {
+  console.log("initChart", props.chartData)
+  if (!props.chartData.xAxis) {
+    return
+  }
+  const chartDom = document.getElementById(props.domId)
+  if (echarts.getInstanceByDom(chartDom)) {
+    echarts.dispose(chartDom)
+  }
+  const myChart = echarts.init(chartDom)
+  // 澶勭悊澶氱郴鍒楁暟鎹�
+  const series = props.chartData.series.map((item) => ({
+    ...item,
+    name: item.name,
+    type: props.chartType, // 鏍规嵁浼犲叆绫诲瀷娓叉煋
+    data: item.data,
+    barWidth: "16",
+    itemStyle: {
+      borderRadius: [15, 15, 0, 0],
+    },
+    smooth: true, // 鍚敤骞虫粦鏇茬嚎
+  }))
+  console.log("initChart", series)
+  let option = {
+    title: {
+      // text: props.chartData.title,
+      left: "40",
+      textStyle: {
+        color: "#2979ff",
+      },
+    },
+    color: ["#2979ff", "#19be6b", "#ff9900", "#fa3534"],
+    tooltip: {
+      trigger: "axis",
+      axisPointer: {
+        type: "shadow",
+      },
+    },
+    legend: {
+      data: props.chartData.series.map((item) => item.name), // 鍥句緥鏁版嵁
+      icon: "rect",
+      right: 40,
+      itemWidth: 14,
+      itemHeight: 10,
+      textStyle: {
+        color: settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222",
+      },
+    },
+    grid: {
+      top: "40",
+      left: "40",
+      right: "40",
+      bottom: "20",
+      containLabel: true,
+    },
+    xAxis: {
+      type: "category",
+      axisPointer: {
+        type: "shadow",
+      },
+      axisLine: {
+        show: true,
+        lineStyle: {
+          color: settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222",
+        },
+      },
+      axisTick: {
+        show: false,
+      },
+      splitArea: {
+        show: false,
+      },
+      splitLine: {
+        show: false,
+      },
+      axisLabel: {
+        color: settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222",
+        fontSize: 14,
+        padding: [5, 0, 0, 0],
+        //   formatter: '{value} ml'
+      },
+      data: props.chartData.xAxis,
+    },
+    yAxis: [
+      {
+        type: "value",
+        nameTextStyle: {
+          color: settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222",
+          fontSize: 14,
+          padding: [0, 0, 5, 0],
+        },
+        axisLine: {
+          show: false,
+        },
+        splitLine: {
+          show: true,
+          lineStyle: {
+            type: "dashed",
+            color: settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222",
+          },
+        },
+        axisTick: {
+          show: false,
+        },
+        splitArea: {
+          show: false,
+        },
+        axisLabel: {
+          color: settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222",
+          fontSize: 14,
+        },
+      },
+    ],
+    series: series,
+  }
+  setTimeout(() => {
+    myChart.setOption(option)
+  }, 200)
+
+  window.addEventListener(
+    "resize",
+    () => {
+      myChart.resize()
+    },
+    { passive: true }
+  )
+}
+</script>
+
+<style lang="scss" scoped>
+.chart-item {
+  width: 100%;
+  height: 360px !important;
+  margin-top: 0px;
+  padding-top: 20px;
+}
+</style>
diff --git a/zhitan-vue/src/views/businessconfiguration/gatewayledger/gatewayLedger.vue b/zhitan-vue/src/views/businessconfiguration/gatewayledger/gatewayLedger.vue
index 1cdeb7f..a7f3304 100644
--- a/zhitan-vue/src/views/businessconfiguration/gatewayledger/gatewayLedger.vue
+++ b/zhitan-vue/src/views/businessconfiguration/gatewayledger/gatewayLedger.vue
@@ -1,131 +1,140 @@
 <template>
-    <div class="page">
-        <div class="form-card">
-            <el-form :inline="true">
-                <el-form-item label="缃戝叧鏁伴噺:" class="header-box">
-                    {{ total }}
-                </el-form-item>
-                <el-form-item label="璁¢噺鍣ㄥ叿鏁伴噺:" class="header-box">
-                    {{ statistics.deviceNum }}
-                </el-form-item>
-                <el-form-item label="娴嬬偣鏁伴噺:" class="header-box">
-                    {{ statistics.ptNum }}
-                </el-form-item>
-            </el-form>
-        </div>
-        <div class="table-box">
-            <div class="mt20 mb20">
-                <el-button type="primary" icon="plus" @click="handleAdd">鏂板</el-button>
-                <el-button type="primary" icon="Download" @click="handleExport">瀵煎嚭</el-button>
-            </div>
-            <el-table :data="tableData" v-loading="loading">
-                <el-table-column prop="gatewayNum" label="缃戝叧缂栧彿" show-overflow-tooltip align="center" />
-                <el-table-column prop="gatewayName" label="缃戝叧鍚嶇О" show-overflow-tooltip align="center" />
-                <el-table-column prop="specsModel" label="瑙勬牸鍨嬪彿" show-overflow-tooltip align="center" />
-                <el-table-column prop="installLocation" label="瀹夎浣嶇疆" show-overflow-tooltip align="center" />
-                <el-table-column prop="ipAdd" label="IP鍦板潃" show-overflow-tooltip align="center" />
-                <el-table-column prop="runStatus" label="杩愯鐘舵��" show-overflow-tooltip align="center" />
-                <el-table-column prop="deviceNum" label="璁¢噺鍣ㄥ叿鏁伴噺" show-overflow-tooltip align="center" />
-                <el-table-column prop="ptNum" label="閲囬泦娴嬬偣鏁伴噺" show-overflow-tooltip align="center" />
-                <el-table-column label="鎿嶄綔" width="300" align="center">
-                    <template #default="scope">
-                        <el-button link type="primary" icon="Edit" @click="handleAdd(scope.row)">
-                            淇敼
-                        </el-button>
-                        <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)">
-                            鍒犻櫎
-                        </el-button>
-                    </template>
-                </el-table-column>
-            </el-table>
-            <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
-                v-model:limit="queryParams.pageSize" @pagination="getList" />
-        </div>
-        <edit-modal ref="EditModalRef" @getList="getList(1)" />
+  <div class="page">
+    <div class="form-card">
+      <el-form :inline="true">
+        <el-form-item label="缃戝叧鏁伴噺:" class="header-box">
+          <span class="count">{{ total || 0 }}</span>
+        </el-form-item>
+        <el-form-item label="璁¢噺鍣ㄥ叿鏁伴噺:" class="header-box">
+          <span class="count">{{ deviceNum || 0 }}</span>
+        </el-form-item>
+        <el-form-item label="娴嬬偣鏁伴噺:" class="header-box">
+          <span class="count">{{ ptNum || 0 }}</span>
+        </el-form-item>
+      </el-form>
     </div>
+    <div class="table-bg-style">
+      <div class="theme-dark-mt20 mb20 ml20">
+        <el-button type="primary" icon="plus" @click="handleAdd">鏂板</el-button>
+        <el-button type="primary" icon="Download" @click="handleExport">瀵煎嚭</el-button>
+      </div>
+
+      <div class="table-box">
+        <el-table :data="tableData" v-loading="loading">
+          <el-table-column prop="gatewayNum" label="缃戝叧缂栧彿" show-overflow-tooltip align="center" />
+          <el-table-column prop="gatewayName" label="缃戝叧鍚嶇О" show-overflow-tooltip align="center" />
+          <el-table-column prop="specsModel" label="瑙勬牸鍨嬪彿" show-overflow-tooltip align="center" />
+          <el-table-column prop="installLocation" label="瀹夎浣嶇疆" show-overflow-tooltip align="center" />
+          <el-table-column prop="ipAdd" label="IP鍦板潃" show-overflow-tooltip align="center" />
+          <el-table-column prop="runStatus" label="杩愯鐘舵��" show-overflow-tooltip align="center" />
+          <el-table-column prop="deviceNum" label="璁¢噺鍣ㄥ叿鏁伴噺" show-overflow-tooltip align="center" />
+          <el-table-column prop="ptNum" label="閲囬泦娴嬬偣鏁伴噺" show-overflow-tooltip align="center" />
+          <el-table-column label="鎿嶄綔" width="300" align="center">
+            <template #default="scope">
+              <el-button link type="primary" icon="Edit" @click="handleAdd(scope.row)"> 淇敼 </el-button>
+              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"> 鍒犻櫎 </el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+        <pagination
+          v-show="total > 0"
+          :total="total"
+          v-model:page="queryParams.pageNum"
+          v-model:limit="queryParams.pageSize"
+          @pagination="getList"
+        />
+      </div>
+    </div>
+
+    <edit-modal ref="EditModalRef" @getList="getList(1)" />
+  </div>
 </template>
 
 <script setup>
-import EditModal from './components/EditModal.vue'
-import { gatewayStatistics, gatewayList, gatewayDel } from "@/api/businessConfiguration/gatewayLedger";
+import EditModal from "./components/EditModal.vue"
+import { gatewayStatistics, gatewayList, gatewayDel } from "@/api/businessConfiguration/gatewayLedger"
 let { proxy } = getCurrentInstance()
 
 let statistics = ref({
-    deviceNum: 0,
-    ptNum: 0
+  deviceNum: 0,
+  ptNum: 0,
 })
 function getGatewayStatisticsFun() {
-    gatewayStatistics().then(res => {
-        if (res.code == 200) {
-            if (res.data) {
-                statistics.value = res.data
-            }
-        }
-    })
+  gatewayStatistics().then((res) => {
+    if (res.code == 200) {
+      if (res.data) {
+        statistics.value = res.data
+      }
+    }
+  })
 }
 getGatewayStatisticsFun()
 
-
-let loading = ref(false);
-let total = ref(0);
+let loading = ref(false)
+let total = ref(0)
 let tableData = ref([])
 let queryParams = ref({
-    pageNum: 1,
-    pageSize: 10,
+  pageNum: 1,
+  pageSize: 10,
 })
 
 function getList(arg) {
-    if (arg == 1) {
-        queryParams.value.pageNum = 1
-    }
-    loading.value = true
-    gatewayList(queryParams.value).then(res => {
-        tableData.value = res.rows
-        total.value = res.total
-        loading.value = false
-    })
+  if (arg == 1) {
+    queryParams.value.pageNum = 1
+  }
+  loading.value = true
+  gatewayList(queryParams.value).then((res) => {
+    tableData.value = res.rows
+    total.value = res.total
+    loading.value = false
+  })
 }
 getList()
 
 function handleExport() {
-    proxy.download(
-        "gatewaySetting/export",
-        queryParams.value,
-        `缃戝叧鍙拌处${new Date().getTime()}.xlsx`
-    );
+  proxy.download("gatewaySetting/export", queryParams.value, `缃戝叧鍙拌处${new Date().getTime()}.xlsx`)
 }
 
-let EditModalRef = ref('')
+let EditModalRef = ref("")
 function handleAdd(row) {
-    if (EditModalRef.value) {
-        EditModalRef.value.handleOpen(row)
-    }
-
+  if (EditModalRef.value) {
+    EditModalRef.value.handleOpen(row)
+  }
 }
 
 function handleDelete(row) {
-    proxy.$modal
-        .confirm('鏄惁纭鍒犻櫎缃戝叧涓�"' + row.gatewayName + '"鐨勬暟鎹」锛�')
-        .then(function () {
-            return gatewayDel(row.id);
-        })
-        .then(() => {
-            getList(1);
-            proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
-        })
-        .catch(() => { });
+  proxy.$modal
+    .confirm('鏄惁纭鍒犻櫎缃戝叧涓�"' + row.gatewayName + '"鐨勬暟鎹」锛�')
+    .then(function () {
+      return gatewayDel(row.id)
+    })
+    .then(() => {
+      getList(1)
+      proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛")
+    })
+    .catch(() => {})
 }
 </script>
 
 <style lang="scss" scoped>
 @import "@/assets/styles/page.scss";
 
-
 .header-box {
-    :deep .el-form-item__content {
-        color: #fff;
-        font-size: 16px;
-    }
-
+  :deep .el-form-item__content {
+    color: #fff;
+    font-size: 16px;
+  }
 }
-</style>
\ No newline at end of file
+
+.themeDark {
+  .count {
+    color: #fff;
+  }
+}
+
+.themeLight {
+  .count {
+    color: #333;
+  }
+}
+</style>
diff --git a/zhitan-vue/src/views/comprehensive/comps/LineChart.vue b/zhitan-vue/src/views/comprehensive/comps/LineChart.vue
index e9cc744..891d8e5 100644
--- a/zhitan-vue/src/views/comprehensive/comps/LineChart.vue
+++ b/zhitan-vue/src/views/comprehensive/comps/LineChart.vue
@@ -31,6 +31,10 @@
   }
 )
 
+onMounted(() => {
+  initChart()
+})
+
 function initChart(value) {
   const chartDom = document.getElementById("ChartDom")
   if (echarts.getInstanceByDom(chartDom)) {
diff --git a/zhitan-vue/src/views/comprehensive/monthlyComprehensive/index.vue b/zhitan-vue/src/views/comprehensive/monthlyComprehensive/index.vue
index c63c0fe..588b94d 100644
--- a/zhitan-vue/src/views/comprehensive/monthlyComprehensive/index.vue
+++ b/zhitan-vue/src/views/comprehensive/monthlyComprehensive/index.vue
@@ -69,10 +69,9 @@
             </template>
           </el-table-column>
           <el-table-column v-for="index in 31" :key="index" :label="index + '鏃�'" align="center" min-width="100">
-            <template #default="scope">{{ numFilter(scope.row[`value${index - 1}`]) }}</template>
+            <template #default="scope">{{ numFilter(scope.row[`value${index}`]) }}</template>
           </el-table-column>
         </el-table>
-
         <div>
           <line-chart ref="LineChartRef" :chartData="lineChartData" />
         </div>
diff --git a/zhitan-vue/src/views/comprehensive/yearComprehensive/index.vue b/zhitan-vue/src/views/comprehensive/yearComprehensive/index.vue
index 494e37a..1b4eb04 100644
--- a/zhitan-vue/src/views/comprehensive/yearComprehensive/index.vue
+++ b/zhitan-vue/src/views/comprehensive/yearComprehensive/index.vue
@@ -69,7 +69,7 @@
             </template>
           </el-table-column>
           <el-table-column v-for="index in 12" :key="index" :label="index + '鏈�'" align="center" min-width="100">
-            <template #default="scope">{{ numFilter(scope.row[`value${index - 1}`]) }}</template>
+            <template #default="scope">{{ numFilter(scope.row[`value${index}`]) }}</template>
           </el-table-column>
         </el-table>
 
diff --git a/zhitan-vue/src/views/costAnalysis/cost-trend-analysis.vue b/zhitan-vue/src/views/costAnalysis/cost-trend-analysis.vue
new file mode 100644
index 0000000..d3dc582
--- /dev/null
+++ b/zhitan-vue/src/views/costAnalysis/cost-trend-analysis.vue
@@ -0,0 +1,316 @@
+<template>
+  <div class="page">
+    <div>
+      <div class="form-card">
+        <el-form :model="queryParams" ref="queryRef" :inline="true">
+          <el-form-item label="鏈熼棿" prop="timeType">
+            <el-select
+              v-model="queryParams.timeType"
+              placeholder="鏈熼棿"
+              clearable
+              style="width: 120px"
+              @change="handleTimeType"
+            >
+              <el-option v-for="dict in period" :key="dict.value" :label="dict.label" :value="dict.value" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="鏃堕棿" prop="dataTime">
+            <el-date-picker
+              v-model="queryParams.dataTime"
+              :type="queryParams.timeType == 'YEAR' ? 'year' : queryParams.timeType == 'MONTH' ? 'month' : 'date'"
+              :format="
+                queryParams.timeType == 'YEAR' ? 'YYYY' : queryParams.timeType == 'MONTH' ? 'YYYY-MM' : 'YYYY-MM-DD'
+              "
+              value-format="YYYY-MM-DD"
+              placeholder="鏃堕棿"
+              style="width: 100%"
+            />
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" icon="Search" @click="handleQuery"> 鎼滅储 </el-button>
+          </el-form-item>
+          <!-- <el-form-item>
+              <el-button type="primary" icon="Download" @click="handleExport"> 瀵煎嚭 </el-button>
+            </el-form-item> -->
+        </el-form>
+      </div>
+      <div class="table-bg-style">
+        <div class="table-box theme-dark-mt20" style="">
+          <el-table :data="tableData" v-loading="loading">
+            <el-table-column label="鏃堕棿" prop="dateCode" align="center" width="160" />
+            <el-table-column label="鎬昏垂鐢�(鍏�)" prop="total" align="center" width="120" />
+            <el-table-column :label="col.energyName" v-for="(col, index) in columns" :key="index" align="center">
+              <el-table-column :prop="'energyTotal' + col.energyType" label="娑堣�楅噺" min-width="120" align="center" />
+              <el-table-column :prop="'costTotal' + col.energyType" label="璐圭敤锛堝厓锛�" min-width="120" align="center" />
+            </el-table-column>
+          </el-table>
+        </div>
+      </div>
+      <div class="charts-view" v-loading="loading">
+        <el-row :gutter="2" class="" v-for="item in chartDataList" :key="item.energyType">
+          <el-col :span="12">
+            <BaseCard :title="item.costLabel + '(鍏�)'">
+              <div class="">
+                <LineChart
+                  :ref="'LineChartCostRef' + item.energyType"
+                  :domId="'costDom_' + item.energyType"
+                  :chartData="{
+                    title: item.costLabel,
+                    chartType: 'line',
+                    xAxis: item.costKeyList,
+                    series: [
+                      {
+                        name: item.costLabel,
+                        data: item.costValueList,
+                        markPoint: {
+                          data: [
+                            { type: 'max', name: 'Max' },
+                            { type: 'min', name: 'Min' },
+                          ],
+                        },
+                      },
+                    ],
+                  }"
+                />
+              </div>
+            </BaseCard>
+          </el-col>
+          <el-col :span="12">
+            <BaseCard :title="item.accumulationLabel + '(' + item.energyUnit + ')'">
+              <div class="">
+                <LineChart
+                  :ref="'LineChartaccumulationRef' + item.energyType"
+                  :domId="'accumulationDom_' + item.energyType"
+                  :chartType="'bar'"
+                  :chartData="{
+                    title: item.accumulationLabel,
+                    chartType: 'bar',
+                    xAxis: item.accumulationKeyList,
+                    series: [
+                      {
+                        name: item.accumulationLabel,
+                        color: '#19be6b',
+                        data: item.accumulationValueList,
+                        markPoint: {
+                          data: [
+                            { type: 'max', name: 'Max' },
+                            { type: 'min', name: 'Min' },
+                          ],
+                        },
+                      },
+                    ],
+                  }"
+                />
+              </div>
+            </BaseCard>
+          </el-col>
+        </el-row>
+      </div>
+    </div>
+  </div>
+</template>
+<script setup name="loadAnalysis">
+import { listEnergyCostTrend, listEnergyCostTrendDetail } from "@/api/cost/api.js"
+import LineChart from "@/components/Echarts/LineChart.vue"
+import { deepClone } from "@/utils/index.js"
+const { proxy } = getCurrentInstance()
+import { useRoute } from "vue-router"
+const { period } = proxy.useDict("period")
+import useSettingsStore from "@/store/modules/settings"
+const settingsStore = useSettingsStore()
+watch(
+  () => settingsStore.sideTheme,
+  (val) => {
+    getList()
+  }
+)
+const activeKey = ref(1)
+const loading = ref(false)
+const tableData = ref([])
+const columns = ref([])
+const detailData = ref({})
+const lineChartData = ref({})
+const chartDataList = ref([])
+const data = reactive({
+  queryParams: {
+    nodeId: null,
+    nodeName: null,
+    timeType: null,
+    dataTime: null,
+    meterId: "",
+    modelCode: useRoute().query.modelCode,
+  },
+  query: { ...useRoute().query },
+})
+const { queryParams, query } = toRefs(data)
+
+function handleTimeType(e) {
+  queryParams.value.timeType = e
+  queryParams.value.dataTime = proxy.dayjs(new Date()).format("YYYY-MM-DD")
+  getTableData()
+  getList()
+}
+
+function getTableData() {
+  let params = {
+    ...queryParams.value,
+    nodeId: queryParams.value.nodeId,
+    timeType: queryParams.value.timeType,
+    timeCode: queryParams.value.dataTime,
+    meterId: queryParams.value.meterId,
+  }
+  if (queryParams.value.timeType == "DAY") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY-MM-DD")
+  } else if (queryParams.value.timeType == "MONTH") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY-MM")
+  } else if (queryParams.value.timeType == "YEAR") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY")
+  }
+  listEnergyCostTrend(params).then((res) => {
+    if (res.code === 200) {
+      let data = deepClone(res.data.itemList || [])
+      // 琛ㄥご鐨勬暟鎹�
+      if (data.length > 0 && data[0].itemList.length > 0) {
+        let energyList = data[0].itemList
+        columns.value = energyList.map((item) => {
+          return {
+            energyName: item.energyName,
+            energyType: item.energyType,
+          }
+        })
+      }
+      tableData.value = data.map((item) => {
+        let tempObj = {}
+        item.itemList.forEach((element) => {
+          tempObj["energyTotal" + element.energyType] = element.accumulation
+          tempObj["costTotal" + element.energyType] = element.cost
+        })
+        return {
+          ...item,
+          ...tempObj,
+        }
+      })
+    }
+  })
+}
+const LineChartRef = ref()
+function getList() {
+  loading.value = true
+  let params = {
+    ...queryParams.value,
+    nodeId: queryParams.value.nodeId,
+    timeType: queryParams.value.timeType,
+    timeCode: queryParams.value.dataTime,
+    meterId: queryParams.value.meterId,
+  }
+  if (queryParams.value.timeType == "DAY") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY-MM-DD")
+  } else if (queryParams.value.timeType == "MONTH") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY-MM")
+  } else if (queryParams.value.timeType == "YEAR") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY")
+  }
+  listEnergyCostTrendDetail(params)
+    .then((res) => {
+      if (res.code == 200) {
+        loading.value = false
+        chartDataList.value = res.data
+      }
+    })
+    .catch(() => {
+      loading.value = false
+    })
+}
+// 纰虫帓鏀剧鐞�-纰虫帓鏀鹃噺鏍哥畻-鎼滅储
+function handleQuery() {
+  getTableData()
+  getList()
+}
+// 纰虫帓鏀剧鐞�-纰虫帓鏀鹃噺鏍哥畻-閲嶇疆
+function resetQuery() {
+  proxy.resetForm("queryRef")
+  queryParams.value.timeType = null
+  queryParams.value.dataTime = null
+  handleTimeType(period.value[0].value)
+  handleQuery()
+}
+// 纰虫帓鏀剧鐞�-纰虫帓鏀鹃噺鏍哥畻-瀵煎嚭
+function handleExport() {
+  proxy.download(
+    "carbonEmission/export",
+    {
+      emissionType: "allType",
+      ...queryParams.value,
+      ...query.value,
+    },
+    `${queryParams.value.nodeName}-纰虫帓鏀鹃噺鏍哥畻_${new Date().getTime()}.xlsx`
+  )
+}
+
+onMounted(() => {
+  setTimeout(() => {
+    handleTimeType(period.value[0].value)
+  }, 200)
+})
+</script>
+<style scoped lang="scss">
+@import "@/assets/styles/page.scss";
+
+.table-box {
+  margin-top: 0;
+  :deep .el-table--border .el-table__inner-wrapper:after {
+    height: 0;
+  }
+
+  :deep .el-table--border:after {
+    width: 0;
+  }
+
+  :deep .el-table--border:before {
+    width: 0;
+  }
+
+  :deep .el-table__border-left-patch {
+    background: transparent;
+  }
+
+  :deep .el-table--border .el-table__cell {
+    border-right: none;
+  }
+}
+
+.charts-view {
+  width: 100%;
+  margin-top: 20px;
+  // padding: 0 30px;
+}
+.display-buttons {
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  margin-top: 16px;
+  margin-right: 16px;
+  .display-btn,
+  .active-display-btn {
+    width: 78px;
+    height: 34px;
+    background: #fff;
+    color: #409eff;
+    border: 2px solid #409eff;
+    border-radius: 4px;
+    margin-left: 10px;
+    text-align: center;
+    line-height: 31px;
+    font-size: 14px;
+    font-weight: 400;
+    cursor: pointer;
+    &:hover {
+      opacity: 0.9;
+    }
+  }
+  .active-display-btn {
+    background: #409eff;
+    color: #fff;
+  }
+}
+</style>
diff --git a/zhitan-vue/src/views/costAnalysis/energy-trend-analysis.vue b/zhitan-vue/src/views/costAnalysis/energy-trend-analysis.vue
new file mode 100644
index 0000000..1c82358
--- /dev/null
+++ b/zhitan-vue/src/views/costAnalysis/energy-trend-analysis.vue
@@ -0,0 +1,295 @@
+<template>
+  <div class="page"></div>
+</template>
+<script setup name="loadAnalysis">
+import { loadAnalysisDetail, listElectricityDeviceMeter } from "@/api/powerquality/load-analysis/api.js"
+import LineChart from "@/components/Echarts/LineChart.vue"
+const { proxy } = getCurrentInstance()
+import { useRoute } from "vue-router"
+const { period } = proxy.useDict("period")
+import useSettingsStore from "@/store/modules/settings"
+const settingsStore = useSettingsStore()
+watch(
+  () => settingsStore.sideTheme,
+  (val) => {
+    getList()
+  }
+)
+const activeKey = ref(1)
+const loading = ref(false)
+const tableData = ref([])
+const detailData = ref({})
+const lineChartData = ref({})
+const electricityMeter = ref([])
+const data = reactive({
+  queryParams: {
+    nodeId: null,
+    nodeName: null,
+    timeType: null,
+    dataTime: null,
+    meterId: "",
+    modelCode: useRoute().query.modelCode,
+  },
+  query: { ...useRoute().query },
+})
+const { queryParams, query } = toRefs(data)
+function getElectricityMeter(params) {
+  listElectricityDeviceMeter(params).then((res) => {
+    if (res.code === 200) {
+      electricityMeter.value = res.data.map((item) => {
+        return {
+          ...item,
+          value: item.code,
+        }
+      })
+      queryParams.value.meterId = res.data.length > 0 ? res.data[0].code : ""
+      getList()
+    }
+  })
+}
+/** 鑺傜偣鍗曞嚮浜嬩欢 */
+function handleNodeClick(data) {
+  queryParams.value.nodeId = data.id
+  queryParams.value.nodeName = data.label
+  setTimeout(() => {
+    handleTimeType(period.value[0].value)
+  }, 200)
+}
+function handleTimeType(e) {
+  queryParams.value.timeType = e
+  queryParams.value.dataTime = proxy.dayjs(new Date()).format("YYYY-MM-DD")
+  getElectricityMeter({ nodeId: queryParams.value.nodeId })
+}
+const LineChartRef = ref()
+function getList() {
+  return
+  loading.value = true
+  let params = {
+    nodeId: queryParams.value.nodeId,
+    timeType: queryParams.value.timeType,
+    timeCode: queryParams.value.dataTime,
+    meterId: queryParams.value.meterId,
+  }
+  if (queryParams.value.timeType == "DAY") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY-MM-DD")
+  } else if (queryParams.value.timeType == "MONTH") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY-MM")
+  } else if (queryParams.value.timeType == "YEAR") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY")
+  }
+  loadAnalysisDetail(params)
+    .then((res) => {
+      if (res.code == 200) {
+        loading.value = false
+        tableData.value = res.data.itemList
+        detailData.value = res.data.detail
+        let itemList = res.data.itemList
+        if (queryParams.value.timeType == "DAY") {
+          lineChartData.value = {
+            title: "璐熻嵎鍒嗘瀽",
+            xAxis: itemList.map((item) => {
+              return item.timeCode.slice(item.timeCode.length - 2, item.timeCode.length) + "鏃�"
+            }),
+            series: [
+              {
+                name: "璐熻嵎鍊�",
+                data: itemList.map((item) => {
+                  return item.value
+                }),
+              },
+            ],
+          }
+        } else {
+          lineChartData.value = {
+            title: "璐熻嵎鍒嗘瀽",
+            xAxis: itemList.map((item) => {
+              return item.timeCodeChart
+            }),
+            series: [
+              {
+                name: "骞冲潎璐熻嵎",
+                data: itemList.map((item) => {
+                  return item.avg
+                }),
+              },
+              {
+                name: "鏈�澶ц礋鑽�",
+                data: itemList.map((item) => {
+                  return item.max
+                }),
+              },
+              {
+                name: "鏈�灏忚礋鑽�",
+                data: itemList.map((item) => {
+                  return item.min
+                }),
+              },
+            ],
+          }
+        }
+      }
+    })
+    .catch(() => {
+      loading.value = false
+    })
+}
+// 纰虫帓鏀剧鐞�-纰虫帓鏀鹃噺鏍哥畻-鎼滅储
+function handleQuery() {
+  getList()
+}
+// 纰虫帓鏀剧鐞�-纰虫帓鏀鹃噺鏍哥畻-閲嶇疆
+function resetQuery() {
+  proxy.resetForm("queryRef")
+  queryParams.value.timeType = null
+  queryParams.value.dataTime = null
+  handleTimeType(period.value[0].value)
+  handleQuery()
+}
+// 纰虫帓鏀剧鐞�-纰虫帓鏀鹃噺鏍哥畻-瀵煎嚭
+function handleExport() {
+  proxy.download(
+    "carbonEmission/export",
+    {
+      emissionType: "allType",
+      ...queryParams.value,
+      ...query.value,
+    },
+    `${queryParams.value.nodeName}-纰虫帓鏀鹃噺鏍哥畻_${new Date().getTime()}.xlsx`
+  )
+}
+</script>
+<style scoped lang="scss">
+@import "@/assets/styles/page.scss";
+
+.themeDark {
+  .card-list {
+    width: 100%;
+    display: flex;
+    flex-wrap: wrap;
+    padding: 18px;
+    color: #fff;
+
+    .card-list-item {
+      width: 19%;
+      margin-right: 1%;
+      height: 157px;
+      background: #223386;
+      border-radius: 5px 5px 5px 5px;
+      border: 1px solid #4868b7;
+      background-size: 100% 100%;
+      box-sizing: border-box;
+      padding: 25px 18px 12px 16px;
+
+      .item-top {
+        display: flex;
+        align-items: center;
+
+        .top-icon {
+          width: 40px;
+          height: 40px;
+          background-size: 100% 100%;
+        }
+
+        .top-right {
+          margin-left: 16px;
+          font-weight: bold;
+          font-size: 16px;
+          font-family: OPPOSans-Bold;
+        }
+      }
+
+      .item-bottom {
+        display: flex;
+        justify-content: space-between;
+        margin-top: 18px;
+        font-family: OPPOSans, OPPOSans;
+        font-weight: bold;
+        font-size: 14px;
+      }
+    }
+  }
+}
+
+.themeLight {
+  .card-list {
+    width: 100%;
+    display: flex;
+    flex-wrap: wrap;
+    padding: 18px;
+
+    .card-list-item {
+      width: 19%;
+      margin-right: 1%;
+      height: 157px;
+      background: #fff;
+      border-radius: 5px 5px 5px 5px;
+      border: 1px solid #e8e8e8;
+      background-size: 100% 100%;
+      box-sizing: border-box;
+      padding: 25px 18px 12px 16px;
+
+      .item-top {
+        display: flex;
+        align-items: center;
+
+        .top-icon {
+          width: 40px;
+          height: 40px;
+          background-size: 100% 100%;
+        }
+
+        .top-right {
+          margin-left: 16px;
+          font-weight: bold;
+          font-size: 16px;
+          color: #000;
+          font-family: OPPOSans-Bold;
+        }
+      }
+
+      .item-bottom {
+        display: flex;
+        justify-content: space-between;
+        margin-top: 18px;
+        font-family: OPPOSans, OPPOSans;
+        font-weight: bold;
+        font-size: 14px;
+      }
+    }
+  }
+}
+
+.chart-box {
+  width: 100%;
+  height: 100% !important;
+}
+.display-buttons {
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  margin-top: 16px;
+  margin-right: 16px;
+  .display-btn,
+  .active-display-btn {
+    width: 78px;
+    height: 34px;
+    background: #fff;
+    color: #409eff;
+    border: 2px solid #409eff;
+    border-radius: 4px;
+    margin-left: 10px;
+    text-align: center;
+    line-height: 31px;
+    font-size: 14px;
+    font-weight: 400;
+    cursor: pointer;
+    &:hover {
+      opacity: 0.9;
+    }
+  }
+  .active-display-btn {
+    background: #409eff;
+    color: #fff;
+  }
+}
+</style>
diff --git a/zhitan-vue/src/views/dataMonitoring/historyDataTrend/index.vue b/zhitan-vue/src/views/dataMonitoring/historyDataTrend/index.vue
new file mode 100644
index 0000000..1f64bec
--- /dev/null
+++ b/zhitan-vue/src/views/dataMonitoring/historyDataTrend/index.vue
@@ -0,0 +1,337 @@
+<template>
+  <div class="page">
+    <div class="page-container">
+      <div class="page-container-left">
+        <LeftTree ref="leftTreeRef" @handleNodeClick="handleNodeClick" />
+      </div>
+      <div class="page-container-right">
+        <div>
+          <BaseCard :title="queryParams.nodeName">
+            <div class="form-card">
+              <el-form :model="queryParams" ref="queryRef" :inline="true" label-width="40px">
+                <el-form-item label=" " prop="timeType" label-width="0">
+                  <el-radio-group v-model="queryParams.timeType" @change="changeTimeType">
+                    <el-radio-button label="DAY">鏃�</el-radio-button>
+                    <el-radio-button label="HOUR">灏忔椂</el-radio-button>
+                  </el-radio-group>
+                </el-form-item>
+                <el-form-item label="鏃堕棿" prop="dataTime">
+                  <el-date-picker
+                    v-model="queryParams.dataTime"
+                    :type="queryParams.timeType == 'DAY' ? 'date' : 'datetime'"
+                    :format="queryParams.timeType == 'DAY' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:00:00'"
+                    :value-format="queryParams.timeType == 'DAY' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:00:00'"
+                    placeholder="鏃堕棿"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+                <el-form-item label="鐐逛綅" prop="meterId">
+                  <el-select v-model="queryParams.meterId" placeholder="閫夋嫨鐐逛綅" clearable style="width: 220px">
+                    <el-option
+                      v-for="dict in electricityMeter"
+                      :key="dict.value"
+                      :label="dict.label"
+                      :value="dict.value"
+                    />
+                  </el-select>
+                </el-form-item>
+                <el-form-item>
+                  <el-button type="primary" icon="Search" @click="handleQuery"> 鎼滅储 </el-button>
+                </el-form-item>
+                <!-- <el-form-item>
+              <el-button type="primary" icon="Download" @click="handleExport"> 瀵煎嚭 </el-button>
+            </el-form-item> -->
+              </el-form>
+            </div>
+            <div class="display-buttons">
+              <div class="display-btn" @click="activeKey = 1" :class="{ 'active-display-btn': activeKey === 1 }">
+                鍥惧舰
+              </div>
+              <div class="display-btn" @click="activeKey = 2" :class="{ 'active-display-btn': activeKey === 2 }">
+                鏁版嵁
+              </div>
+            </div>
+            <div class="chart-box" v-loading="loading" v-show="activeKey === 1">
+              <LineChart ref="LineChartRef" :chartData="lineChartData" />
+            </div>
+            <div style="margin-top: 16px" v-show="activeKey === 2">
+              <div class="" style="padding: 0 16px">
+                <el-table :data="tableData" v-loading="loading" height="calc(100vh - 350px)">
+                  <el-table-column label="鐐逛綅鍚嶇О" prop="indexName" align="center" />
+                  <el-table-column label="鐐逛綅鍊�" prop="value" align="center" />
+                  <el-table-column label="鏃堕棿" prop="dataTime" align="center" />
+                </el-table>
+              </div>
+            </div>
+          </BaseCard>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script setup name="loadAnalysis">
+import { getHistoricalDataByIndexId, getEnergyIndexByModelId } from "@/api/realTimeMonitor/historyDataTrend.js"
+import LineChart from "@/components/Echarts/LineChart.vue"
+const { proxy } = getCurrentInstance()
+import { useRoute } from "vue-router"
+import useSettingsStore from "@/store/modules/settings"
+const settingsStore = useSettingsStore()
+watch(
+  () => settingsStore.sideTheme,
+  (val) => {
+    getList()
+  }
+)
+const activeKey = ref(1)
+const loading = ref(false)
+const tableData = ref([])
+const lineChartData = ref({})
+const electricityMeter = ref([])
+const data = reactive({
+  queryParams: {
+    nodeId: null,
+    nodeName: null,
+    timeType: "DAY",
+    dataTime: null,
+    meterId: "",
+  },
+  query: { ...useRoute().query },
+})
+const { queryParams, query } = toRefs(data)
+function getElectricityMeter(params) {
+  getEnergyIndexByModelId(params).then((res) => {
+    if (res.code === 200) {
+      electricityMeter.value = res.data.map((item) => {
+        return {
+          ...item,
+          label: item.indexName,
+          value: item.indexId,
+        }
+      })
+      queryParams.value.meterId = res.data.length > 0 ? res.data[0].indexId : ""
+      getList()
+    }
+  })
+}
+/** 鑺傜偣鍗曞嚮浜嬩欢 */
+function handleNodeClick(data) {
+  queryParams.value.nodeId = data.id
+  queryParams.value.nodeName = data.label
+  setTimeout(() => {
+    handleTimeType(queryParams.value.timeType)
+  }, 200)
+}
+function handleTimeType(e) {
+  queryParams.value.timeType = e
+  queryParams.value.dataTime = proxy.dayjs(new Date()).format("YYYY-MM-DD HH:00:00")
+  getElectricityMeter({ modelId: queryParams.value.nodeId })
+}
+
+function changeTimeType(e) {
+  console.log(e)
+  queryParams.value.dataTime = proxy.dayjs(new Date()).format("YYYY-MM-DD HH:00:00")
+  getElectricityMeter({ modelId: queryParams.value.nodeId })
+}
+const LineChartRef = ref()
+function getList() {
+  loading.value = true
+  let params = {
+    nodeId: queryParams.value.nodeId,
+    timeType: queryParams.value.timeType,
+    dataTime: queryParams.value.dataTime,
+    indexId: queryParams.value.meterId,
+  }
+  if (queryParams.value.timeType == "DAY") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY-MM-DD")
+  } else if (queryParams.value.timeType == "MONTH") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY-MM")
+  } else if (queryParams.value.timeType == "YEAR") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY")
+  }
+  getHistoricalDataByIndexId(params)
+    .then((res) => {
+      if (res.code == 200) {
+        loading.value = false
+        tableData.value = res.data
+        let itemList = res.data
+        lineChartData.value = {
+          title: "",
+          xAxis: itemList.map((item) => {
+            return queryParams.value.timeType == "DAY"
+              ? item.dataTime.slice(11, 13) + "鏃�"
+              : item.dataTime.slice(11, 16)
+          }),
+          series: [
+            {
+              name: "鐐逛綅鍊�",
+              data: itemList.map((item) => {
+                return item.value
+              }),
+            },
+          ],
+        }
+      }
+    })
+    .catch(() => {
+      loading.value = false
+    })
+}
+// 纰虫帓鏀剧鐞�-纰虫帓鏀鹃噺鏍哥畻-鎼滅储
+function handleQuery() {
+  getList()
+}
+// 纰虫帓鏀剧鐞�-纰虫帓鏀鹃噺鏍哥畻-閲嶇疆
+function resetQuery() {
+  proxy.resetForm("queryRef")
+  queryParams.value.timeType = null
+  queryParams.value.dataTime = null
+  handleQuery()
+}
+// 纰虫帓鏀剧鐞�-纰虫帓鏀鹃噺鏍哥畻-瀵煎嚭
+function handleExport() {
+  proxy.download(
+    "carbonEmission/export",
+    {
+      emissionType: "allType",
+      ...queryParams.value,
+      ...query.value,
+    },
+    `${queryParams.value.nodeName}-纰虫帓鏀鹃噺鏍哥畻_${new Date().getTime()}.xlsx`
+  )
+}
+</script>
+<style scoped lang="scss">
+@import "@/assets/styles/page.scss";
+
+.themeDark {
+  .card-list {
+    width: 100%;
+    display: flex;
+    flex-wrap: wrap;
+    padding: 18px;
+    color: #fff;
+
+    .card-list-item {
+      width: 19%;
+      margin-right: 1%;
+      height: 157px;
+      background: #223386;
+      border-radius: 5px 5px 5px 5px;
+      border: 1px solid #4868b7;
+      background-size: 100% 100%;
+      box-sizing: border-box;
+      padding: 25px 18px 12px 16px;
+
+      .item-top {
+        display: flex;
+        align-items: center;
+
+        .top-icon {
+          width: 40px;
+          height: 40px;
+          background-size: 100% 100%;
+        }
+
+        .top-right {
+          margin-left: 16px;
+          font-weight: bold;
+          font-size: 16px;
+          font-family: OPPOSans-Bold;
+        }
+      }
+
+      .item-bottom {
+        display: flex;
+        justify-content: space-between;
+        margin-top: 18px;
+        font-family: OPPOSans, OPPOSans;
+        font-weight: bold;
+        font-size: 14px;
+      }
+    }
+  }
+}
+
+.themeLight {
+  .card-list {
+    width: 100%;
+    display: flex;
+    flex-wrap: wrap;
+    padding: 18px;
+
+    .card-list-item {
+      width: 19%;
+      margin-right: 1%;
+      height: 157px;
+      background: #fff;
+      border-radius: 5px 5px 5px 5px;
+      border: 1px solid #e8e8e8;
+      background-size: 100% 100%;
+      box-sizing: border-box;
+      padding: 25px 18px 12px 16px;
+
+      .item-top {
+        display: flex;
+        align-items: center;
+
+        .top-icon {
+          width: 40px;
+          height: 40px;
+          background-size: 100% 100%;
+        }
+
+        .top-right {
+          margin-left: 16px;
+          font-weight: bold;
+          font-size: 16px;
+          color: #000;
+          font-family: OPPOSans-Bold;
+        }
+      }
+
+      .item-bottom {
+        display: flex;
+        justify-content: space-between;
+        margin-top: 18px;
+        font-family: OPPOSans, OPPOSans;
+        font-weight: bold;
+        font-size: 14px;
+      }
+    }
+  }
+}
+
+.chart-box {
+  width: 100%;
+  height: 100% !important;
+}
+.display-buttons {
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  margin-top: 16px;
+  margin-right: 16px;
+  .display-btn,
+  .active-display-btn {
+    width: 78px;
+    height: 34px;
+    background: #fff;
+    color: #409eff;
+    border: 2px solid #409eff;
+    border-radius: 4px;
+    margin-left: 10px;
+    text-align: center;
+    line-height: 31px;
+    font-size: 14px;
+    font-weight: 400;
+    cursor: pointer;
+    &:hover {
+      opacity: 0.9;
+    }
+  }
+  .active-display-btn {
+    background: #409eff;
+    color: #fff;
+  }
+}
+</style>
diff --git a/zhitan-vue/src/views/energyefficiency/benchmarkmanage/benchmarkmanage.vue b/zhitan-vue/src/views/energyefficiency/benchmarkmanage/benchmarkmanage.vue
index aee4ffb..1e43c29 100644
--- a/zhitan-vue/src/views/energyefficiency/benchmarkmanage/benchmarkmanage.vue
+++ b/zhitan-vue/src/views/energyefficiency/benchmarkmanage/benchmarkmanage.vue
@@ -1,122 +1,136 @@
 <template>
-    <div class="page">
-        <div class="form-card">
-            <el-form :model="form" ref="queryRef" :inline="true" label-width="85px">
-                <el-form-item label="鏍囨潌缂栧彿" prop="code">
-                    <el-input v-model="form.code" placeholder="璇疯緭鍏ユ爣鏉嗙紪鍙�" />
-                </el-form-item>
-                <el-form-item label="鏍囨潌绫诲瀷" prop="type">
-                    <el-select v-model="form.type" clearable>
-                        <el-option v-for="dict in benchmark_type" :key="dict.value" :label="dict.label"
-                            :value="dict.value" />
-                    </el-select>
-                </el-form-item>
-                <el-form-item label="鏍囨潌绛夌骇" prop="grade">
-                    <el-select v-model="form.grade" clearable>
-                        <el-option v-for="dict in benchmark_grade" :key="dict.value" :label="dict.label"
-                            :value="dict.value" />
-                    </el-select>
-                </el-form-item>
-                <el-form-item>
-                    <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button>
-                    <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button>
-                </el-form-item>
-            </el-form>
-        </div>
-        <div class="table-box">
-            <div class=" mt20 mb20">
-                <el-button type="primary" icon="Plus" @click="handleAdd">鏂板</el-button>
-            </div>
-            <el-table :data="tableData" v-loading="loading">
-                <el-table-column prop="code" label="鏍囨潌缂栧彿" show-overflow-tooltip align="center" />
-                <el-table-column prop="type" label="鏍囨潌绫诲瀷" show-overflow-tooltip align="center"
-                    :formatter="(row, c) => proxy.selectDictLabel(benchmark_type, row.type)" />
-                <el-table-column prop="grade" label="鏍囨潌绛夌骇" show-overflow-tooltip align="center"
-                    :formatter="(row, c) => proxy.selectDictLabel(benchmark_grade, row.grade)" />
-                <el-table-column prop="value" label="鏍囨潌鍊�" show-overflow-tooltip align="center" />
-                <el-table-column prop="nationalNum" label="鍥芥爣缂栧彿" show-overflow-tooltip align="center" />
-                <el-table-column prop="createBy" label="褰曞叆浜�" show-overflow-tooltip align="center" />
-                <el-table-column prop="createTime" label="褰曞叆鏃堕棿" show-overflow-tooltip align="center" />
-                <el-table-column prop="remark" label="澶囨敞" show-overflow-tooltip align="center" />
-                <el-table-column prop="active" label="鎿嶄綔" width="150" align="center">
-                    <template #default="scope">
-                        <el-button link type="primary" icon="Edit" @click="handleAdd(scope.row)">
-                            淇敼
-                        </el-button>
-                        <el-button link type="primary" icon="Delete" @click="handleDel(scope.row)">
-                            鍒犻櫎
-                        </el-button>
-                    </template>
-                </el-table-column>
-            </el-table>
-            <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
-                v-model:limit="queryParams.pageSize" @pagination="getList" />
-        </div>
-        <EditModal ref="EditModalRef" :benchmark_grade="benchmark_grade" :benchmark_type="benchmark_type"
-            @getList="getList" />
-
+  <div class="page">
+    <div class="form-card">
+      <el-form :model="form" ref="queryRef" :inline="true" label-width="85px">
+        <el-form-item label="鏍囨潌缂栧彿" prop="code">
+          <el-input v-model="form.code" placeholder="璇疯緭鍏ユ爣鏉嗙紪鍙�" />
+        </el-form-item>
+        <el-form-item label="鏍囨潌绫诲瀷" prop="type">
+          <el-select v-model="form.type" clearable>
+            <el-option v-for="dict in benchmark_type" :key="dict.value" :label="dict.label" :value="dict.value" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鏍囨潌绛夌骇" prop="grade">
+          <el-select v-model="form.grade" clearable>
+            <el-option v-for="dict in benchmark_grade" :key="dict.value" :label="dict.label" :value="dict.value" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button>
+          <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button>
+        </el-form-item>
+      </el-form>
     </div>
+    <div class="table-bg-style">
+      <div class="theme-dark-mt20 mb20 ml20">
+        <el-button type="primary" icon="Plus" @click="handleAdd">鏂板</el-button>
+      </div>
+      <div class="table-box">
+        <el-table :data="tableData" v-loading="loading">
+          <el-table-column prop="code" label="鏍囨潌缂栧彿" show-overflow-tooltip align="center" />
+          <el-table-column
+            prop="type"
+            label="鏍囨潌绫诲瀷"
+            show-overflow-tooltip
+            align="center"
+            :formatter="(row, c) => proxy.selectDictLabel(benchmark_type, row.type)"
+          />
+          <el-table-column
+            prop="grade"
+            label="鏍囨潌绛夌骇"
+            show-overflow-tooltip
+            align="center"
+            :formatter="(row, c) => proxy.selectDictLabel(benchmark_grade, row.grade)"
+          />
+          <el-table-column prop="value" label="鏍囨潌鍊�" show-overflow-tooltip align="center" />
+          <el-table-column prop="nationalNum" label="鍥芥爣缂栧彿" show-overflow-tooltip align="center" />
+          <el-table-column prop="createBy" label="褰曞叆浜�" show-overflow-tooltip align="center" />
+          <el-table-column prop="createTime" label="褰曞叆鏃堕棿" show-overflow-tooltip align="center" />
+          <el-table-column prop="remark" label="澶囨敞" show-overflow-tooltip align="center" />
+          <el-table-column prop="active" label="鎿嶄綔" width="150" align="center">
+            <template #default="scope">
+              <el-button link type="primary" icon="Edit" @click="handleAdd(scope.row)"> 淇敼 </el-button>
+              <el-button link type="primary" icon="Delete" @click="handleDel(scope.row)"> 鍒犻櫎 </el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+        <pagination
+          v-show="total > 0"
+          :total="total"
+          v-model:page="queryParams.pageNum"
+          v-model:limit="queryParams.pageSize"
+          @pagination="getList"
+        />
+      </div>
+    </div>
+
+    <EditModal
+      ref="EditModalRef"
+      :benchmark_grade="benchmark_grade"
+      :benchmark_type="benchmark_type"
+      @getList="getList"
+    />
+  </div>
 </template>
 <script setup>
-import EditModal from './components/EditModal.vue'
-import { valueManageList, valueManageDel } from '@/api/benchmarkManage'
+import EditModal from "./components/EditModal.vue"
+import { valueManageList, valueManageDel } from "@/api/benchmarkManage"
 let proxy = getCurrentInstance().proxy
 
-let { benchmark_grade, benchmark_type } = proxy.useDict("benchmark_grade", 'benchmark_type')
+let { benchmark_grade, benchmark_type } = proxy.useDict("benchmark_grade", "benchmark_type")
 let form = ref({
-    code: null,
-    type: null,
-    grade: null,
+  code: null,
+  type: null,
+  grade: null,
 })
 function handleQuery() {
-    queryParams.value.pageNum = 1
-    getList()
+  queryParams.value.pageNum = 1
+  getList()
 }
 
 function resetQuery() {
-    queryParams.value.pageNum = 1
-    form.value = {}
-    handleQuery();
+  queryParams.value.pageNum = 1
+  form.value = {}
+  handleQuery()
 }
 
-
-let loading = ref(false);
-let total = ref(0);
+let loading = ref(false)
+let total = ref(0)
 let tableData = ref([])
 let queryParams = ref({
-    pageNum: 1,
-    pageSize: 10,
+  pageNum: 1,
+  pageSize: 10,
 })
 function getList(flag) {
-    loading.value = true
-    valueManageList({ ...queryParams.value, ...form.value }).then(res => {
-        tableData.value = res.rows
-        total.value = res.total
-        loading.value = false
-    })
-
+  loading.value = true
+  valueManageList({ ...queryParams.value, ...form.value }).then((res) => {
+    tableData.value = res.rows
+    total.value = res.total
+    loading.value = false
+  })
 }
 
 getList()
-let EditModalRef = ref('')
+let EditModalRef = ref("")
 function handleAdd(row) {
-    if (EditModalRef.value) {
-        EditModalRef.value.handleOpen(row)
-    }
-
+  if (EditModalRef.value) {
+    EditModalRef.value.handleOpen(row)
+  }
 }
 
 function handleDel(row) {
-    proxy.$modal.confirm('鏄惁纭鍒犻櫎鏁版嵁椤�?').then(function () {
-        return valueManageDel(row.id);
-    }).then(() => {
-        getList();
-        proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
-    }).catch(() => { });
+  proxy.$modal
+    .confirm("鏄惁纭鍒犻櫎鏁版嵁椤�?")
+    .then(function () {
+      return valueManageDel(row.id)
+    })
+    .then(() => {
+      getList()
+      proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛")
+    })
+    .catch(() => {})
 }
-
 </script>
-
 
 <style lang="scss" scoped>
 @import "@/assets/styles/page.scss";
diff --git a/zhitan-vue/src/views/index.vue b/zhitan-vue/src/views/index.vue
index 2474cd7..168b68f 100644
--- a/zhitan-vue/src/views/index.vue
+++ b/zhitan-vue/src/views/index.vue
@@ -20,10 +20,11 @@
               <div class="top-right">
                 <div class="right-name">
                   {{ item.energyName }}
+                  <span v-if="item.energyUnit" class="unit">({{ item.energyUnit }})</span>
                 </div>
                 <div class="right-value">
                   <span> {{ item.count }}</span>
-                  <span class="unit">{{ item.energyUnit }}</span>
+                  <!-- <span class="unit">{{ item.energyUnit }}</span> -->
                 </div>
               </div>
             </div>
@@ -889,18 +890,23 @@
           display: flex;
 
           .top-icon {
-            width: 69px;
-            height: 69px;
+            width: 50px;
+            height: 50px;
             background-size: 100% 100%;
           }
 
           .top-right {
-            margin-left: 16px;
+            margin-left: 12px;
 
             .right-name {
               font-weight: bold;
               font-size: 16px;
               font-family: OPPOSans-Bold;
+              .unit {
+                margin-left: 2px;
+                font-size: 16px;
+                font-weight: normal;
+              }
             }
 
             .right-value {
diff --git a/zhitan-vue/src/views/modelconfiguration/indexwarehouse/indexWarehouse.vue b/zhitan-vue/src/views/modelconfiguration/indexwarehouse/indexWarehouse.vue
index a42b60d..82f3ef3 100644
--- a/zhitan-vue/src/views/modelconfiguration/indexwarehouse/indexWarehouse.vue
+++ b/zhitan-vue/src/views/modelconfiguration/indexwarehouse/indexWarehouse.vue
@@ -5,38 +5,44 @@
         <div class="tree page-box">
           <!-- <CardHeader class="mb20">鐢ㄨ兘鍗曞厓缁撴瀯</CardHeader> -->
           <!-- <el-input v-model="filterText" style="width: 240px" placeholder="杈撳叆鍏抽敭瀛楄繘琛岃繃婊�" class="mb10" /> -->
-          <el-tree ref="treeRef" :props="defaultProps" :data="treeData" node-key="id" highlight-current
-            :filter-node-method="filterNode" :default-expanded-keys="treeExpandData" :expand-on-click-node="false"
-            @node-click="changeNode" accordion>
+          <el-tree
+            ref="treeRef"
+            :props="defaultProps"
+            :data="treeData"
+            node-key="id"
+            highlight-current
+            :filter-node-method="filterNode"
+            :default-expanded-keys="treeExpandData"
+            :expand-on-click-node="false"
+            @node-click="changeNode"
+            accordion
+          >
             <template #default="{ node, data }">
               <span>
-                <el-tooltip v-if="node.label.length > 6" class="item" effect="dark" :content="node.label"
-                  placement="top-end">
+                <el-tooltip
+                  v-if="node.label.length > 6"
+                  class="item"
+                  effect="dark"
+                  :content="node.label"
+                  placement="top-end"
+                >
                   <span>{{ node.label.slice(0, 6) + "..." }}</span>
                 </el-tooltip>
                 <span v-else id="b">{{ node.label }}</span>
               </span>
               <span class="node-opt">
-                <el-link title="鏂板涓嬬骇鑺傜偣" icon="Plus" @click="() => addNode(node, data)">
-                </el-link>
-                <el-link title="淇敼鑺傜偣" icon="EditPen" @click="() => editNode(node, data)">
-                </el-link>
-                <el-link title="鍒犻櫎鑺傜偣" icon="Delete" @click="() => delNode(node, data)">
-                </el-link>
+                <el-link title="鏂板涓嬬骇鑺傜偣" icon="Plus" @click="() => addNode(node, data)"> </el-link>
+                <el-link title="淇敼鑺傜偣" icon="EditPen" @click="() => editNode(node, data)"> </el-link>
+                <el-link title="鍒犻櫎鑺傜偣" icon="Delete" @click="() => delNode(node, data)"> </el-link>
               </span>
             </template>
           </el-tree>
         </div>
       </div>
       <div class="page-container-right">
-
         <div class="mb20 mt20 ml20 tab-box">
-          <div class="tab-li" :class="tab == 1 ? 'is-tab' : ''" @click="handleTab('1')">
-            璁¢噺鍣ㄥ叿閰嶇疆淇℃伅
-          </div>
-          <div class="tab-li" :class="tab == 2 ? 'is-tab' : ''" @click="handleTab('2')">
-            缁熻鎸囨爣
-          </div>
+          <div class="tab-li" :class="tab == 1 ? 'is-tab' : ''" @click="handleTab('1')">璁¢噺鍣ㄥ叿閰嶇疆淇℃伅</div>
+          <div class="tab-li" :class="tab == 2 ? 'is-tab' : ''" @click="handleTab('2')">缁熻鎸囨爣</div>
           <!-- <el-radio-group v-model="tab">
                                 <el-radio-button label="1" @click="handleTab('1')"> 璁惧閰嶇疆</el-radio-button>
                                 <el-radio-button label="2" @click="handleTab('2')"> 閲囬泦鎸囨爣</el-radio-button>
@@ -45,10 +51,10 @@
         <BaseCard :title="currentNode ? currentNode.label + '--鑺傜偣閰嶇疆' : '鏆傛棤鑺傜偣閰嶇疆'">
           <div>
             <div class="content-box" v-if="tab == '1'">
-              <deviceConfig ref='deviceConfigRef' />
+              <deviceConfig ref="deviceConfigRef" />
             </div>
             <div class="content-box1" v-if="tab == '2'">
-              <statisticalIndicatorManagement ref='statisticalIndicatorManagementRef' :indexType='"STATISTIC"' />
+              <statisticalIndicatorManagement ref="statisticalIndicatorManagementRef" :indexType="'STATISTIC'" />
             </div>
           </div>
         </BaseCard>
@@ -56,18 +62,22 @@
         <!-- <statisticalIndicatorManagement ref="statisticalIndicatorManagementRef" :indexType='"STATISTIC"' /> -->
       </div>
     </div>
-    <treeNodeModal ref="treeNodeModalRef" @getList="getTreeList" modelCode="JCZBK_CODE" @addTreeList="addTreeList"
-      @addTreeSelectList="addTreeSelectList" />
+    <treeNodeModal
+      ref="treeNodeModalRef"
+      @getList="getTreeList"
+      modelCode="JCZBK_CODE"
+      @addTreeList="addTreeList"
+      @addTreeSelectList="addTreeSelectList"
+    />
   </div>
-
 </template>
 
 <script setup>
-import treeNodeModal from './components/TreeNodeModal.vue'
-import deviceConfig from './components/deviceConfig/DeviceConfig.vue'
-import statisticalIndicatorManagement from './components/statisticalIndicatorManagement/statisticalIndicatorManagement.vue';
-import { treeList, delModelNode, hasEnergyIndex, } from '@/api/modelConfiguration/indexWarehouse'
-const { proxy } = getCurrentInstance();
+import treeNodeModal from "./components/TreeNodeModal.vue"
+import deviceConfig from "./components/deviceConfig/DeviceConfig.vue"
+import statisticalIndicatorManagement from "./components/statisticalIndicatorManagement/statisticalIndicatorManagement.vue"
+import { treeList, delModelNode, hasEnergyIndex } from "@/api/modelConfiguration/indexWarehouse"
+const { proxy } = getCurrentInstance()
 
 let currentNode = ref()
 let treeRef = ref()
@@ -75,12 +85,12 @@
 let treeData = ref([])
 
 const defaultProps = ref({
-  children: 'children',
-  label: 'label',
+  children: "children",
+  label: "label",
 })
 
 //妫�绱㈡爲
-let filterText = ref('')
+let filterText = ref("")
 
 const filterNode = (value, data) => {
   if (!value) return true
@@ -88,14 +98,14 @@
 }
 watch(filterText, (val) => {
   // 妫�鏌reeRef.value鏄惁鏄竴涓湁鏁堢殑ElTree瀹炰緥
-  if (treeRef.value && typeof treeRef.value.filter === 'function') {
+  if (treeRef.value && typeof treeRef.value.filter === "function") {
     // 璋冪敤filter鏂规硶
-    treeRef.value.filter(val);
+    treeRef.value.filter(val)
   } else {
     // treeRef.value鏃犳晥锛屽鐞嗛敊璇�
-    console.error('error');
+    console.error("error")
   }
-});
+})
 
 let treeExpandData = ref([])
 let isFirstLeafNode = ref(false)
@@ -103,32 +113,31 @@
 let statisticalIndicatorManagementRef = ref(null)
 //鑾峰彇鏍戝垪琛�
 function getTreeList() {
-  treeList({ modelCode: 'JCZBK_CODE' }).then(res => {
+  treeList({ modelCode: "JCZBK_CODE" }).then((res) => {
     let { data } = res
-    treeData.value = data;
-    let chooseNode = null;
+    treeData.value = data
+    let chooseNode = null
     if (data.length > 0) {
       if (data[0].children && data[0].children.length !== 0 && isFirstLeafNode.value) {
         if (data[0].children[0].children && data[0].children[0].children.length !== 0) {
-          chooseNode = data[0].children[0].children[0];
+          chooseNode = data[0].children[0].children[0]
         } else {
-          chooseNode = data[0].children[0];
+          chooseNode = data[0].children[0]
         }
       } else {
-        chooseNode = data[0];
+        chooseNode = data[0]
       }
-      currentNode.value = chooseNode;
-      treeExpandData.value.push(chooseNode.id);
+      currentNode.value = chooseNode
+      treeExpandData.value.push(chooseNode.id)
       nextTick(() => {
-        treeRef.value.setCurrentKey(chooseNode.id);
+        treeRef.value.setCurrentKey(chooseNode.id)
         if (tab.value == 1 && deviceConfigRef.value) {
           deviceConfigRef.value.getList(chooseNode)
         }
         if (tab.value == 2 && statisticalIndicatorManagementRef.value) {
           statisticalIndicatorManagementRef.value.getList(chooseNode)
         }
-
-      });
+      })
     }
   })
 }
@@ -143,7 +152,7 @@
   treeExpandData.value.push(addedNode.nodeId)
   nextTick(() => {
     treeRef.value.setCurrentNode(newChild)
-    currentNode.value = newChild;
+    currentNode.value = newChild
     if (tab.value == 1) {
       if (deviceConfigRef.value) {
         deviceConfigRef.value.getList(newChild)
@@ -155,11 +164,10 @@
       }
     }
   })
-
 }
 //鏍戠偣鍑�
 function changeNode(data, node, ev) {
-  currentNode.value = data;
+  currentNode.value = data
   if (tab.value == 1) {
     if (deviceConfigRef.value) {
       deviceConfigRef.value.getList(data)
@@ -171,7 +179,6 @@
     }
   }
 }
-
 
 let treeNodeModalRef = ref(null)
 
@@ -188,26 +195,27 @@
 
 function delNode(node, data) {
   if (data.children && data.children.length > 0) {
-    proxy.$modal.msgWarning('鍖呭惈瀛愯妭鐐癸紝涓嶈兘杩涜鍒犻櫎锛�')
+    proxy.$modal.msgWarning("鍖呭惈瀛愯妭鐐癸紝涓嶈兘杩涜鍒犻櫎锛�")
     return
   }
 
-  hasEnergyIndex(data.id).then(response => {
+  hasEnergyIndex(data.id).then((response) => {
     if (response.data) {
-      proxy.$modal.msgWarning('褰撳墠鑺傜偣涓嬪瓨鍦ㄦ寚鏍囷紝涓嶈兘杩涜鍒犻櫎锛�')
+      proxy.$modal.msgWarning("褰撳墠鑺傜偣涓嬪瓨鍦ㄦ寚鏍囷紝涓嶈兘杩涜鍒犻櫎锛�")
     } else {
-      proxy.$modal.confirm('鏄惁纭鍒犻櫎鍚嶄负"' + data.label + '"鐨勮妭鐐�?', '璀﹀憡', {
-        confirmButtonText: '纭畾',
-        cancelButtonText: '鍙栨秷',
-        type: 'warning'
-      })
+      proxy.$modal
+        .confirm('鏄惁纭鍒犻櫎鍚嶄负"' + data.label + '"鐨勮妭鐐�?', "璀﹀憡", {
+          confirmButtonText: "纭畾",
+          cancelButtonText: "鍙栨秷",
+          type: "warning",
+        })
         .then(function () {
           return delModelNode(data.id)
         })
         .then(() => {
           let parent = node.parent
           let children = parent.data.children || parent.data
-          let index = children.findIndex(d => d.id === data.id)
+          let index = children.findIndex((d) => d.id === data.id)
           children.splice(index, 1)
 
           nextTick(() => {
@@ -217,10 +225,9 @@
               changeNode(null)
             }
           })
-          proxy.$modal.msgSuccess('鍒犻櫎鎴愬姛')
+          proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛")
         })
-        .catch(function () {
-        })
+        .catch(function () {})
     }
   })
 }
@@ -234,15 +241,12 @@
     if (value == 2 && statisticalIndicatorManagementRef.value) {
       statisticalIndicatorManagementRef.value.getList(currentNode.value)
     }
-
-  });
-
+  })
 }
 </script>
 
 <style lang="scss" scoped>
 @import "@/assets/styles/page.scss";
-
 
 .page-box {
   height: calc(100vh - 145px);
@@ -276,8 +280,6 @@
       margin-right: 5px;
     }
   }
-
-
 }
 
 :deep .el-tabs__nav-wrap:after {
@@ -298,29 +300,40 @@
 .tab-box {
   display: flex;
   align-items: center;
-  color: #fff;
-  border-bottom: 1px solid #3371EB;
+  color: #333;
+  border-bottom: 1px solid #3371eb;
   margin-right: 20px;
 
   .tab-li {
     cursor: pointer;
-    border: 1px solid #3371EB;
+    border: 1px solid #3371eb;
     padding: 10px 25px;
     border-radius: 5px 5px 0 0;
   }
 
   .is-tab {
-    background: #3371EB;
+    background: #3371eb;
+    color: #fff;
+  }
+}
+
+.themeDark {
+  .tab-box {
+    color: #fff;
+  }
+}
+
+.themeLight {
+  .tab-box {
+    color: #333;
   }
 }
 
 .content-box {
   height: calc(100vh - 310px) !important;
-
 }
 
 .content-box1 {
   height: calc(100vh - 290px) !important;
-
 }
 </style>
diff --git a/zhitan-vue/src/views/peakvalley/period/period.vue b/zhitan-vue/src/views/peakvalley/period/period.vue
index 749fa2e..a9551c6 100644
--- a/zhitan-vue/src/views/peakvalley/period/period.vue
+++ b/zhitan-vue/src/views/peakvalley/period/period.vue
@@ -555,16 +555,21 @@
     display: flex;
     justify-content: space-between;
     padding: 18px;
+    width: 100%;
+    overflow: hidden;
+    overflow-x: auto;
 
     .card-list-item {
-      width: 19%;
-      height: 187px;
+      flex-shrink: 0;
+      width: 230px;
+      height: 188px;
       background: #223386;
       border-radius: 5px 5px 5px 5px;
       border: 1px solid #4868b7;
       background-size: 100% 100%;
       box-sizing: border-box;
       padding: 10px 18px 13px 16px;
+      margin-right: 12px;
 
       .item-top {
         display: flex;
diff --git a/zhitan-vue/src/views/powerquality/load/index.vue b/zhitan-vue/src/views/powerquality/load/index.vue
new file mode 100644
index 0000000..a386abe
--- /dev/null
+++ b/zhitan-vue/src/views/powerquality/load/index.vue
@@ -0,0 +1,402 @@
+<template>
+  <div class="page">
+    <div class="page-container">
+      <div class="page-container-left">
+        <LeftTree ref="leftTreeRef" @handleNodeClick="handleNodeClick" />
+      </div>
+      <div class="page-container-right">
+        <div
+          style="height: calc(100vh - 150px) !important; max-height: calc(100vh - 150px) !important; overflow-y: auto"
+        >
+          <BaseCard :title="queryParams.nodeName + '-璐熻嵎鍒嗘瀽'">
+            <div class="form-card">
+              <el-form :model="queryParams" ref="queryRef" :inline="true">
+                <el-form-item label="鏈熼棿" prop="timeType">
+                  <el-select
+                    v-model="queryParams.timeType"
+                    placeholder="鏈熼棿"
+                    clearable
+                    style="width: 120px"
+                    @change="handleTimeType"
+                  >
+                    <el-option v-for="dict in period" :key="dict.value" :label="dict.label" :value="dict.value" />
+                  </el-select>
+                </el-form-item>
+                <el-form-item label="鏃堕棿" prop="dataTime">
+                  <el-date-picker
+                    v-model="queryParams.dataTime"
+                    :type="queryParams.timeType == 'YEAR' ? 'year' : queryParams.timeType == 'MONTH' ? 'month' : 'date'"
+                    :format="
+                      queryParams.timeType == 'YEAR'
+                        ? 'YYYY'
+                        : queryParams.timeType == 'MONTH'
+                        ? 'YYYY-MM'
+                        : 'YYYY-MM-DD'
+                    "
+                    value-format="YYYY-MM-DD"
+                    placeholder="鏃堕棿"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+                <el-form-item label="閫夋嫨鐢佃〃" prop="meterId">
+                  <el-select v-model="queryParams.meterId" placeholder="閫夋嫨鐢佃〃" clearable style="width: 200px">
+                    <el-option
+                      v-for="dict in electricityMeter"
+                      :key="dict.value"
+                      :label="dict.label"
+                      :value="dict.value"
+                    />
+                  </el-select>
+                </el-form-item>
+                <el-form-item>
+                  <el-button type="primary" icon="Search" @click="handleQuery"> 鎼滅储 </el-button>
+                </el-form-item>
+                <!-- <el-form-item>
+              <el-button type="primary" icon="Download" @click="handleExport"> 瀵煎嚭 </el-button>
+            </el-form-item> -->
+              </el-form>
+            </div>
+            <div class="display-buttons">
+              <div class="display-btn" @click="activeKey = 1" :class="{ 'active-display-btn': activeKey === 1 }">
+                鍥惧舰
+              </div>
+              <div class="display-btn" @click="activeKey = 2" :class="{ 'active-display-btn': activeKey === 2 }">
+                鏁版嵁
+              </div>
+            </div>
+            <div class="chart-box" v-loading="loading" v-show="activeKey === 1">
+              <LineChart ref="LineChartRef" :chartData="lineChartData" />
+              <div style="padding: 16px">
+                <el-descriptions title="" size="large" border :column="2">
+                  <el-descriptions-item label="鏈�澶ц礋鑽�">
+                    {{ detailData.max || "--" }}
+                  </el-descriptions-item>
+                  <el-descriptions-item label="鍙戠敓鏃堕棿">
+                    {{ detailData.maxTime || "" }}
+                  </el-descriptions-item>
+
+                  <el-descriptions-item label="鏈�灏忚礋鑽�">
+                    {{ detailData.min || "--" }}
+                  </el-descriptions-item>
+                  <el-descriptions-item label="鍙戠敓鏃堕棿">
+                    {{ detailData.minTime || "--" }}
+                  </el-descriptions-item>
+
+                  <el-descriptions-item label="骞冲潎璐熻嵎">
+                    {{ detailData.avg || "--" }}
+                  </el-descriptions-item>
+                  <el-descriptions-item label="璐熻嵎鐜�">
+                    {{ detailData.rate || "" }}
+                  </el-descriptions-item>
+                </el-descriptions>
+              </div>
+            </div>
+            <div style="margin-top: 16px" v-show="activeKey === 2">
+              <div class="" style="padding: 0 16px">
+                <el-table :data="tableData" v-loading="loading" height="calc(100vh - 400px)">
+                  <el-table-column label="鏃堕棿" prop="timeCode" align="center" />
+                  <el-table-column label="鐢佃〃鍚嶇О" prop="name" align="center" />
+                  <el-table-column v-if="queryParams.timeType == 'DAY'" label="璐熻嵎" prop="value" align="center" />
+                  <el-table-column v-if="queryParams.timeType != 'DAY'" label="鏈�澶ц礋鑽�" prop="max" align="center" />
+                  <el-table-column v-if="queryParams.timeType != 'DAY'" label="鏈�灏忚礋鑽�" prop="min" align="center" />
+                  <el-table-column v-if="queryParams.timeType != 'DAY'" label="骞冲潎璐熻嵎" prop="avg" align="center" />
+                  <el-table-column v-if="queryParams.timeType != 'DAY'" label="璐熻嵎鐜�(%)" prop="rate" align="center" />
+                </el-table>
+              </div>
+            </div>
+          </BaseCard>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script setup name="loadAnalysis">
+import { loadAnalysisDetail, listElectricityDeviceMeter } from "@/api/powerquality/load-analysis/api.js"
+import LineChart from "@/components/Echarts/LineChart.vue"
+const { proxy } = getCurrentInstance()
+import { useRoute } from "vue-router"
+const { period } = proxy.useDict("period")
+import useSettingsStore from "@/store/modules/settings"
+const settingsStore = useSettingsStore()
+watch(
+  () => settingsStore.sideTheme,
+  (val) => {
+    getList()
+  }
+)
+const activeKey = ref(1)
+const loading = ref(false)
+const tableData = ref([])
+const detailData = ref({})
+const lineChartData = ref({})
+const electricityMeter = ref([])
+const data = reactive({
+  queryParams: {
+    nodeId: null,
+    nodeName: null,
+    timeType: null,
+    dataTime: null,
+    meterId: "",
+  },
+  query: { ...useRoute().query },
+})
+const { queryParams, query } = toRefs(data)
+function getElectricityMeter(params) {
+  listElectricityDeviceMeter(params).then((res) => {
+    if (res.code === 200) {
+      electricityMeter.value = res.data.map((item) => {
+        return {
+          ...item,
+          value: item.code,
+        }
+      })
+      queryParams.value.meterId = res.data.length > 0 ? res.data[0].code : ""
+      getList()
+    }
+  })
+}
+/** 鑺傜偣鍗曞嚮浜嬩欢 */
+function handleNodeClick(data) {
+  queryParams.value.nodeId = data.id
+  queryParams.value.nodeName = data.label
+  setTimeout(() => {
+    handleTimeType(period.value[0].value)
+  }, 200)
+}
+function handleTimeType(e) {
+  queryParams.value.timeType = e
+  queryParams.value.dataTime = proxy.dayjs(new Date()).format("YYYY-MM-DD")
+  getElectricityMeter({ nodeId: queryParams.value.nodeId })
+}
+const LineChartRef = ref()
+function getList() {
+  loading.value = true
+  let params = {
+    nodeId: queryParams.value.nodeId,
+    timeType: queryParams.value.timeType,
+    timeCode: queryParams.value.dataTime,
+    meterId: queryParams.value.meterId,
+  }
+  if (queryParams.value.timeType == "DAY") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY-MM-DD")
+  } else if (queryParams.value.timeType == "MONTH") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY-MM")
+  } else if (queryParams.value.timeType == "YEAR") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY")
+  }
+  loadAnalysisDetail(params)
+    .then((res) => {
+      if (res.code == 200) {
+        loading.value = false
+        tableData.value = res.data.itemList
+        detailData.value = res.data.detail
+        let itemList = res.data.itemList
+        if (queryParams.value.timeType == "DAY") {
+          lineChartData.value = {
+            title: "璐熻嵎鍒嗘瀽",
+            xAxis: itemList.map((item) => {
+              return item.timeCode.slice(item.timeCode.length - 2, item.timeCode.length) + "鏃�"
+            }),
+            series: [
+              {
+                name: "璐熻嵎鍊�",
+                data: itemList.map((item) => {
+                  return item.value
+                }),
+              },
+            ],
+          }
+        } else {
+          lineChartData.value = {
+            title: "璐熻嵎鍒嗘瀽",
+            xAxis: itemList.map((item) => {
+              return item.timeCodeChart
+            }),
+            series: [
+              {
+                name: "骞冲潎璐熻嵎",
+                data: itemList.map((item) => {
+                  return item.avg
+                }),
+              },
+              {
+                name: "鏈�澶ц礋鑽�",
+                data: itemList.map((item) => {
+                  return item.max
+                }),
+              },
+              {
+                name: "鏈�灏忚礋鑽�",
+                data: itemList.map((item) => {
+                  return item.min
+                }),
+              },
+            ],
+          }
+        }
+      }
+    })
+    .catch(() => {
+      loading.value = false
+    })
+}
+// 纰虫帓鏀剧鐞�-纰虫帓鏀鹃噺鏍哥畻-鎼滅储
+function handleQuery() {
+  getList()
+}
+// 纰虫帓鏀剧鐞�-纰虫帓鏀鹃噺鏍哥畻-閲嶇疆
+function resetQuery() {
+  proxy.resetForm("queryRef")
+  queryParams.value.timeType = null
+  queryParams.value.dataTime = null
+  handleTimeType(period.value[0].value)
+  handleQuery()
+}
+// 纰虫帓鏀剧鐞�-纰虫帓鏀鹃噺鏍哥畻-瀵煎嚭
+function handleExport() {
+  proxy.download(
+    "carbonEmission/export",
+    {
+      emissionType: "allType",
+      ...queryParams.value,
+      ...query.value,
+    },
+    `${queryParams.value.nodeName}-纰虫帓鏀鹃噺鏍哥畻_${new Date().getTime()}.xlsx`
+  )
+}
+</script>
+<style scoped lang="scss">
+@import "@/assets/styles/page.scss";
+
+.themeDark {
+  .card-list {
+    width: 100%;
+    display: flex;
+    flex-wrap: wrap;
+    padding: 18px;
+    color: #fff;
+
+    .card-list-item {
+      width: 19%;
+      margin-right: 1%;
+      height: 157px;
+      background: #223386;
+      border-radius: 5px 5px 5px 5px;
+      border: 1px solid #4868b7;
+      background-size: 100% 100%;
+      box-sizing: border-box;
+      padding: 25px 18px 12px 16px;
+
+      .item-top {
+        display: flex;
+        align-items: center;
+
+        .top-icon {
+          width: 40px;
+          height: 40px;
+          background-size: 100% 100%;
+        }
+
+        .top-right {
+          margin-left: 16px;
+          font-weight: bold;
+          font-size: 16px;
+          font-family: OPPOSans-Bold;
+        }
+      }
+
+      .item-bottom {
+        display: flex;
+        justify-content: space-between;
+        margin-top: 18px;
+        font-family: OPPOSans, OPPOSans;
+        font-weight: bold;
+        font-size: 14px;
+      }
+    }
+  }
+}
+
+.themeLight {
+  .card-list {
+    width: 100%;
+    display: flex;
+    flex-wrap: wrap;
+    padding: 18px;
+
+    .card-list-item {
+      width: 19%;
+      margin-right: 1%;
+      height: 157px;
+      background: #fff;
+      border-radius: 5px 5px 5px 5px;
+      border: 1px solid #e8e8e8;
+      background-size: 100% 100%;
+      box-sizing: border-box;
+      padding: 25px 18px 12px 16px;
+
+      .item-top {
+        display: flex;
+        align-items: center;
+
+        .top-icon {
+          width: 40px;
+          height: 40px;
+          background-size: 100% 100%;
+        }
+
+        .top-right {
+          margin-left: 16px;
+          font-weight: bold;
+          font-size: 16px;
+          color: #000;
+          font-family: OPPOSans-Bold;
+        }
+      }
+
+      .item-bottom {
+        display: flex;
+        justify-content: space-between;
+        margin-top: 18px;
+        font-family: OPPOSans, OPPOSans;
+        font-weight: bold;
+        font-size: 14px;
+      }
+    }
+  }
+}
+
+.chart-box {
+  width: 100%;
+  height: 100% !important;
+}
+.display-buttons {
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  margin-top: 16px;
+  margin-right: 16px;
+  .display-btn,
+  .active-display-btn {
+    width: 78px;
+    height: 34px;
+    background: #fff;
+    color: #409eff;
+    border: 2px solid #409eff;
+    border-radius: 4px;
+    margin-left: 10px;
+    text-align: center;
+    line-height: 31px;
+    font-size: 14px;
+    font-weight: 400;
+    cursor: pointer;
+    &:hover {
+      opacity: 0.9;
+    }
+  }
+  .active-display-btn {
+    background: #409eff;
+    color: #fff;
+  }
+}
+</style>
diff --git a/zhitan-vue/src/views/powerquality/power/index.vue b/zhitan-vue/src/views/powerquality/power/index.vue
new file mode 100644
index 0000000..37d5bba
--- /dev/null
+++ b/zhitan-vue/src/views/powerquality/power/index.vue
@@ -0,0 +1,331 @@
+<template>
+  <div class="page">
+    <div class="page-container">
+      <div class="page-container-left">
+        <LeftTree ref="leftTreeRef" @handleNodeClick="handleNodeClick" />
+      </div>
+      <div class="page-container-right">
+        <div
+          style="height: calc(100vh - 150px) !important; max-height: calc(100vh - 150px) !important; overflow-y: auto"
+        >
+          <BaseCard :title="queryParams.nodeName + '-鍔熺巼鍥犳暟鍒嗘瀽'">
+            <div class="form-card">
+              <el-form :model="queryParams" ref="queryRef" :inline="true">
+                <el-form-item label="鏃堕棿" prop="dataTime">
+                  <el-date-picker
+                    v-model="queryParams.dataTime"
+                    :type="queryParams.timeType == 'YEAR' ? 'year' : queryParams.timeType == 'MONTH' ? 'month' : 'date'"
+                    :format="
+                      queryParams.timeType == 'YEAR'
+                        ? 'YYYY'
+                        : queryParams.timeType == 'MONTH'
+                        ? 'YYYY-MM'
+                        : 'YYYY-MM-DD'
+                    "
+                    value-format="YYYY-MM-DD"
+                    placeholder="鏃堕棿"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+                <el-form-item label="閫夋嫨鐢佃〃" prop="meterId">
+                  <el-select v-model="queryParams.meterId" placeholder="閫夋嫨鐢佃〃" clearable style="width: 200px">
+                    <el-option
+                      v-for="dict in electricityMeter"
+                      :key="dict.value"
+                      :label="dict.label"
+                      :value="dict.value"
+                    />
+                  </el-select>
+                </el-form-item>
+                <el-form-item>
+                  <el-button type="primary" icon="Search" @click="handleQuery"> 鎼滅储 </el-button>
+                </el-form-item>
+                <!-- <el-form-item>
+              <el-button type="primary" icon="Download" @click="handleExport"> 瀵煎嚭 </el-button>
+            </el-form-item> -->
+              </el-form>
+            </div>
+
+            <div class="chart-box" v-loading="loading">
+              <LineChart ref="LineChartRef" :chartData="lineChartData" />
+              <div style="padding: 16px">
+                <el-table :data="tableData" v-loading="loading">
+                  <el-table-column label="鍔熺巼鍥犳暟" prop="title" align="center" />
+                  <el-table-column label="鏈�澶у��" prop="max" align="center" />
+                  <el-table-column label="鏈�灏忓��" prop="min" align="center" />
+                  <el-table-column label="骞冲潎鍊�" prop="avg" align="center" />
+                </el-table>
+              </div>
+            </div>
+          </BaseCard>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script setup name="loadAnalysis">
+import { powerFactorAnalysisDetail } from "@/api/powerquality/electric-power-factor/api.js"
+import { listElectricityDeviceMeter } from "@/api/powerquality/load-analysis/api.js"
+import LineChart from "@/components/Echarts/LineChart.vue"
+const { proxy } = getCurrentInstance()
+import { useRoute } from "vue-router"
+import useSettingsStore from "@/store/modules/settings"
+const settingsStore = useSettingsStore()
+watch(
+  () => settingsStore.sideTheme,
+  (val) => {
+    getList()
+  }
+)
+const loading = ref(false)
+const tableData = ref([])
+const lineChartData = ref({})
+const electricityMeter = ref([])
+const data = reactive({
+  queryParams: {
+    nodeId: null,
+    nodeName: null,
+    timeType: "DAY",
+    dataTime: proxy.dayjs(new Date()).format("YYYY-MM-DD"),
+    meterId: "",
+  },
+  query: { ...useRoute().query },
+})
+const { queryParams, query } = toRefs(data)
+function getElectricityMeter(params) {
+  listElectricityDeviceMeter(params).then((res) => {
+    if (res.code === 200) {
+      electricityMeter.value = res.data.map((item) => {
+        return {
+          ...item,
+          value: item.code,
+        }
+      })
+      queryParams.value.meterId = res.data.length > 0 ? res.data[0].code : ""
+      getList()
+    }
+  })
+}
+/** 鑺傜偣鍗曞嚮浜嬩欢 */
+function handleNodeClick(data) {
+  queryParams.value.nodeId = data.id
+  queryParams.value.nodeName = data.label
+  getElectricityMeter({ nodeId: queryParams.value.nodeId })
+}
+
+const LineChartRef = ref()
+function getList() {
+  loading.value = true
+  let params = {
+    nodeId: queryParams.value.nodeId,
+    timeType: queryParams.value.timeType,
+    timeCode: queryParams.value.dataTime,
+    meterId: queryParams.value.meterId,
+  }
+  if (queryParams.value.timeType == "DAY") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY-MM-DD")
+  } else if (queryParams.value.timeType == "MONTH") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY-MM")
+  } else if (queryParams.value.timeType == "YEAR") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY")
+  }
+  powerFactorAnalysisDetail(params)
+    .then((res) => {
+      if (res.code == 200) {
+        loading.value = false
+        let detailData = res.data.detail
+        tableData.value = [
+          {
+            title: "鍙戠敓鍊�",
+            max: detailData.max,
+            min: detailData.min,
+            avg: detailData.avg,
+          },
+          {
+            title: "鍙戠敓鏃堕棿",
+            max: detailData.maxTime,
+            min: detailData.minTime,
+            avg: "--",
+          },
+        ]
+        detailData.value = res.data.detail
+        let itemList = res.data.itemList
+        lineChartData.value = {
+          title: "鍔熺巼鍥犳暟鍒嗘瀽",
+          xAxis: itemList.map((item) => {
+            return item.timeCode.slice(0, 2) + "鏃�"
+          }),
+          series: [
+            {
+              name: "鍔熺巼鍥犳暟",
+              data: itemList.map((item) => {
+                return item.value
+              }),
+            },
+          ],
+        }
+      }
+    })
+    .catch(() => {
+      loading.value = false
+    })
+}
+// 纰虫帓鏀剧鐞�-纰虫帓鏀鹃噺鏍哥畻-鎼滅储
+function handleQuery() {
+  getList()
+}
+// 纰虫帓鏀剧鐞�-纰虫帓鏀鹃噺鏍哥畻-閲嶇疆
+function resetQuery() {
+  proxy.resetForm("queryRef")
+  queryParams.value.timeType = null
+  queryParams.value.dataTime = null
+  handleQuery()
+}
+// 纰虫帓鏀剧鐞�-纰虫帓鏀鹃噺鏍哥畻-瀵煎嚭
+function handleExport() {
+  proxy.download(
+    "carbonEmission/export",
+    {
+      emissionType: "allType",
+      ...queryParams.value,
+      ...query.value,
+    },
+    `${queryParams.value.nodeName}-纰虫帓鏀鹃噺鏍哥畻_${new Date().getTime()}.xlsx`
+  )
+}
+</script>
+<style scoped lang="scss">
+@import "@/assets/styles/page.scss";
+
+.themeDark {
+  .card-list {
+    width: 100%;
+    display: flex;
+    flex-wrap: wrap;
+    padding: 18px;
+    color: #fff;
+
+    .card-list-item {
+      width: 19%;
+      margin-right: 1%;
+      height: 157px;
+      background: #223386;
+      border-radius: 5px 5px 5px 5px;
+      border: 1px solid #4868b7;
+      background-size: 100% 100%;
+      box-sizing: border-box;
+      padding: 25px 18px 12px 16px;
+
+      .item-top {
+        display: flex;
+        align-items: center;
+
+        .top-icon {
+          width: 40px;
+          height: 40px;
+          background-size: 100% 100%;
+        }
+
+        .top-right {
+          margin-left: 16px;
+          font-weight: bold;
+          font-size: 16px;
+          font-family: OPPOSans-Bold;
+        }
+      }
+
+      .item-bottom {
+        display: flex;
+        justify-content: space-between;
+        margin-top: 18px;
+        font-family: OPPOSans, OPPOSans;
+        font-weight: bold;
+        font-size: 14px;
+      }
+    }
+  }
+}
+
+.themeLight {
+  .card-list {
+    width: 100%;
+    display: flex;
+    flex-wrap: wrap;
+    padding: 18px;
+
+    .card-list-item {
+      width: 19%;
+      margin-right: 1%;
+      height: 157px;
+      background: #fff;
+      border-radius: 5px 5px 5px 5px;
+      border: 1px solid #e8e8e8;
+      background-size: 100% 100%;
+      box-sizing: border-box;
+      padding: 25px 18px 12px 16px;
+
+      .item-top {
+        display: flex;
+        align-items: center;
+
+        .top-icon {
+          width: 40px;
+          height: 40px;
+          background-size: 100% 100%;
+        }
+
+        .top-right {
+          margin-left: 16px;
+          font-weight: bold;
+          font-size: 16px;
+          color: #000;
+          font-family: OPPOSans-Bold;
+        }
+      }
+
+      .item-bottom {
+        display: flex;
+        justify-content: space-between;
+        margin-top: 18px;
+        font-family: OPPOSans, OPPOSans;
+        font-weight: bold;
+        font-size: 14px;
+      }
+    }
+  }
+}
+
+.chart-box {
+  width: 100%;
+  height: 100% !important;
+}
+.display-buttons {
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  margin-top: 16px;
+  margin-right: 16px;
+  .display-btn,
+  .active-display-btn {
+    width: 78px;
+    height: 34px;
+    background: #fff;
+    color: #409eff;
+    border: 2px solid #409eff;
+    border-radius: 4px;
+    margin-left: 10px;
+    text-align: center;
+    line-height: 31px;
+    font-size: 14px;
+    font-weight: 400;
+    cursor: pointer;
+    &:hover {
+      opacity: 0.9;
+    }
+  }
+  .active-display-btn {
+    background: #409eff;
+    color: #fff;
+  }
+}
+</style>
diff --git a/zhitan-vue/src/views/powerquality/threephase/index.vue b/zhitan-vue/src/views/powerquality/threephase/index.vue
new file mode 100644
index 0000000..496c460
--- /dev/null
+++ b/zhitan-vue/src/views/powerquality/threephase/index.vue
@@ -0,0 +1,503 @@
+<template>
+  <div class="page">
+    <div class="page-container">
+      <div class="page-container-left">
+        <LeftTree ref="leftTreeRef" @handleNodeClick="handleNodeClick" />
+      </div>
+      <div class="page-container-right">
+        <div
+          style="height: calc(100vh - 150px) !important; max-height: calc(100vh - 150px) !important; overflow-y: auto"
+        >
+          <BaseCard :title="queryParams.nodeName + '-涓夌浉涓嶅钩琛″垎鏋�'">
+            <div class="form-card">
+              <el-form :model="queryParams" ref="queryRef" :inline="true">
+                <el-form-item label="鏈熼棿" prop="timeType">
+                  <el-select
+                    v-model="queryParams.timeType"
+                    placeholder="鏈熼棿"
+                    clearable
+                    style="width: 120px"
+                    @change="handleTimeType"
+                  >
+                    <el-option v-for="dict in period" :key="dict.value" :label="dict.label" :value="dict.value" />
+                  </el-select>
+                </el-form-item>
+                <el-form-item label="鏃堕棿">
+                  <el-date-picker
+                    v-model="queryParams.dataTime"
+                    :type="queryParams.timeType == 'YEAR' ? 'year' : queryParams.timeType == 'MONTH' ? 'month' : 'date'"
+                    :format="
+                      queryParams.timeType == 'YEAR'
+                        ? 'YYYY'
+                        : queryParams.timeType == 'MONTH'
+                        ? 'YYYY-MM'
+                        : 'YYYY-MM-DD'
+                    "
+                    value-format="YYYY-MM-DD"
+                    placeholder="鏃堕棿"
+                    style="width: 100%"
+                  />
+                </el-form-item>
+                <el-form-item label="閫夋嫨鐢佃〃" prop="meterId">
+                  <el-select
+                    v-model="queryParams.meterId"
+                    placeholder="閫夋嫨鐢佃〃"
+                    clearable
+                    style="width: 200px"
+                    @change="handleTimeType"
+                  >
+                    <el-option
+                      v-for="dict in electricityMeter"
+                      :key="dict.value"
+                      :label="dict.label"
+                      :value="dict.value"
+                    />
+                  </el-select>
+                </el-form-item>
+                <el-form-item>
+                  <el-button type="primary" icon="Search" @click="handleQuery"> 鎼滅储 </el-button>
+                </el-form-item>
+                <!-- <el-form-item>
+              <el-button type="primary" icon="Download" @click="handleExport"> 瀵煎嚭 </el-button>
+            </el-form-item> -->
+              </el-form>
+            </div>
+
+            <div style="padding: 0 16px">
+              <el-tabs v-model="activeTabKey" type="card">
+                <el-tab-pane label="鐢靛帇涓嶅钩琛�" name="1"> </el-tab-pane>
+                <el-tab-pane label="鐢垫祦涓嶅钩琛�" name="2"> </el-tab-pane>
+              </el-tabs>
+              <div class="display-buttons">
+                <div class="display-btn" @click="switchBtnType(1)" :class="{ 'active-display-btn': activeKey === 1 }">
+                  鍥惧舰
+                </div>
+                <div class="display-btn" @click="switchBtnType(2)" :class="{ 'active-display-btn': activeKey === 2 }">
+                  鏁版嵁
+                </div>
+              </div>
+            </div>
+
+            <div class="chart-box" v-loading="loading" v-show="activeKey === 1">
+              <LineChart ref="LineChartRef" :chartData="lineChartData" />
+              <el-table :data="tableData1" v-loading="loading">
+                <el-table-column label="绫诲瀷" prop="type" align="center" />
+                <el-table-column label="涓夐」涓嶅钩琛℃瀬鍊�" prop="value" align="center" />
+                <el-table-column label="鍙戠敓鏃堕棿" prop="time" align="center" />
+                <el-table-column v-if="activeTabKey == 1" label="A椤圭數鍘�(V)" prop="valueA" align="center" />
+                <el-table-column v-if="activeTabKey == 1" label="B椤圭數鍘�(V)" prop="valueB" align="center" />
+                <el-table-column v-if="activeTabKey == 1" label="C椤圭數鍘�(V)" prop="valueC" align="center" />
+                <el-table-column v-if="activeTabKey == 2" label="A椤圭數娴�(A)" prop="valueA" align="center" />
+                <el-table-column v-if="activeTabKey == 2" label="B椤圭數娴�(A)" prop="valueB" align="center" />
+                <el-table-column v-if="activeTabKey == 2" label="C椤圭數娴�(A)" prop="valueC" align="center" />
+              </el-table>
+            </div>
+            <div style="margin-top: 16px" v-show="activeKey === 2">
+              <div class="" style="padding: 0 16px">
+                <el-table :data="tableData2" v-loading="loading" height="calc(100vh - 400px)">
+                  <el-table-column label="鏃堕棿" prop="timeCode" align="center" />
+                  <el-table-column label="鐢佃〃鍚嶇О" prop="name" align="center" />
+                  <el-table-column
+                    v-if="activeTabKey == 1 && queryParams.timeType == 'DAY'"
+                    label="A椤圭數鍘�(V)"
+                    prop="valueA"
+                    align="center"
+                  />
+                  <el-table-column
+                    v-if="activeTabKey == 1 && queryParams.timeType == 'DAY'"
+                    label="B椤圭數鍘�(V)"
+                    prop="valueB"
+                    align="center"
+                  />
+                  <el-table-column
+                    v-if="activeTabKey == 1 && queryParams.timeType == 'DAY'"
+                    label="C椤圭數鍘�(V)"
+                    prop="valueC"
+                    align="center"
+                  />
+                  <el-table-column
+                    v-if="activeTabKey == 2 && queryParams.timeType == 'DAY'"
+                    label="A椤圭數娴�(A)"
+                    prop="valueA"
+                    align="center"
+                  />
+                  <el-table-column
+                    v-if="activeTabKey == 2 && queryParams.timeType == 'DAY'"
+                    label="B椤圭數娴�(A)"
+                    prop="valueB"
+                    align="center"
+                  />
+                  <el-table-column
+                    v-if="activeTabKey == 2 && queryParams.timeType == 'DAY'"
+                    label="C椤圭數娴�(A)"
+                    prop="valueC"
+                    align="center"
+                  />
+                  <el-table-column
+                    v-if="activeTabKey == 1 && queryParams.timeType !== 'DAY'"
+                    label="鏈�澶у��(V)"
+                    prop="max"
+                    align="center"
+                  />
+                  <el-table-column
+                    v-if="activeTabKey == 1 && queryParams.timeType !== 'DAY'"
+                    label="鏈�灏忓��(V)"
+                    prop="min"
+                    align="center"
+                  />
+                  <el-table-column
+                    v-if="activeTabKey == 2 && queryParams.timeType !== 'DAY'"
+                    label="鏈�澶у��(A)"
+                    prop="max"
+                    align="center"
+                  />
+                  <el-table-column
+                    v-if="activeTabKey == 2 && queryParams.timeType !== 'DAY'"
+                    label="鏈�灏忓��(A)"
+                    prop="min"
+                    align="center"
+                  />
+                </el-table>
+              </div>
+            </div>
+          </BaseCard>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script setup name="loadAnalysis">
+import { threePhaseUnbalanceAnalysisDetail } from "@/api/powerquality/electricThreePhase/api.js"
+import { listElectricityDeviceMeter } from "@/api/powerquality/load-analysis/api.js"
+import LineChart from "@/components/Echarts/LineChart.vue"
+const { proxy } = getCurrentInstance()
+import { useRoute } from "vue-router"
+const { period } = proxy.useDict("period")
+import useSettingsStore from "@/store/modules/settings"
+const settingsStore = useSettingsStore()
+watch(
+  () => settingsStore.sideTheme,
+  (val) => {
+    getList()
+  }
+)
+const activeTabKey = ref("1")
+const activeKey = ref(1)
+const activeKeyA = ref(1)
+const loading = ref(false)
+const tableData1 = ref([])
+const tableData2 = ref([])
+const detailData = ref({})
+const lineChartData = ref({})
+const electricityMeter = ref([])
+const data = reactive({
+  queryParams: {
+    nodeId: null,
+    nodeName: null,
+    timeType: null,
+    dataTime: null,
+    meterId: "",
+  },
+  query: { ...useRoute().query },
+})
+const { queryParams, query } = toRefs(data)
+function getElectricityMeter(params) {
+  listElectricityDeviceMeter(params).then((res) => {
+    if (res.code === 200) {
+      electricityMeter.value = res.data.map((item) => {
+        return {
+          ...item,
+          value: item.code,
+        }
+      })
+      queryParams.value.meterId = res.data.length > 0 ? res.data[0].code : ""
+      getList()
+    }
+  })
+}
+/** 鑺傜偣鍗曞嚮浜嬩欢 */
+function handleNodeClick(data) {
+  queryParams.value.nodeId = data.id
+  queryParams.value.nodeName = data.label
+  handleTimeType(period.value[0].value)
+  getElectricityMeter({ nodeId: queryParams.value.nodeId })
+}
+function handleTimeType(e) {
+  queryParams.value.timeType = e
+  queryParams.value.dataTime = proxy.dayjs(new Date()).format("YYYY-MM-DD")
+}
+
+function switchBtnType(e) {
+  activeKey.value = e
+  if (e === 1) {
+    getList()
+  }
+}
+// 鍒楄〃
+function getList() {
+  loading.value = true
+  let params = {
+    nodeId: queryParams.value.nodeId,
+    timeType: queryParams.value.timeType,
+    timeCode: queryParams.value.dataTime,
+    meterId: queryParams.value.meterId,
+    requestType: activeTabKey.value == 1 ? 0 : 1,
+  }
+  if (queryParams.value.timeType == "DAY") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY-MM-DD")
+  } else if (queryParams.value.timeType == "MONTH") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY-MM")
+  } else if (queryParams.value.timeType == "YEAR") {
+    params.timeCode = proxy.dayjs(new Date(queryParams.value.dataTime)).format("YYYY")
+  }
+  threePhaseUnbalanceAnalysisDetail(params)
+    .then((res) => {
+      if (!!res.code && res.code == 200) {
+        // detailData.value = res.data.detail
+        loading.value = false
+        let itemList = res.data.itemList || []
+        let detail = res.data.detail || {}
+        if (detail) {
+          tableData1.value = [
+            {
+              type: "鏈�澶у��",
+              value: detail.max || "--",
+              time: detail.maxTime,
+              valueA: detail.valueMaxA,
+              valueB: detail.valueMaxB,
+              valueC: detail.valueMaxC,
+            },
+            {
+              type: "鏈�灏忓��",
+              value: detail.min,
+              time: detail.minTime,
+              valueA: detail.valueMinA,
+              valueB: detail.valueMinB,
+              valueC: detail.valueMinC,
+            },
+          ]
+        }
+
+        let tableDataWithMeterList = itemList
+        tableData2.value =
+          tableDataWithMeterList.map((item) => {
+            // item.timeCode = this.formatTime(item.timeCode)
+            return item
+          }) || []
+
+        // chart
+        let chartData = {}
+        if (queryParams.value.timeType !== "DAY") {
+          chartData = {
+            title: "涓夌浉涓嶅钩琛″垎鏋�",
+            xAxis: itemList.map((item) => {
+              return item.timeCodeChart
+            }),
+            series: [
+              {
+                name: "鏈�灏忓��",
+                data: itemList.map((item) => {
+                  return item.min === "--" || !item.min ? null : Number(item.min)
+                }),
+              },
+              {
+                name: "鏈�澶у��",
+                data: itemList.map((item) => {
+                  return item.max === "--" || !item.max ? null : Number(item.max)
+                }),
+              },
+            ],
+          }
+        } else {
+          chartData = {
+            title: "涓夌浉涓嶅钩琛″垎鏋�",
+            xAxis: itemList.map((item) => {
+              return item.timeCode.slice(item.timeCode.length - 2, item.timeCode.length) + "鏃�"
+            }),
+            series: [
+              {
+                name: "A鐩�" + (activeTabKey.value == 1 ? "鐢靛帇" : "鐢垫祦"),
+                data: itemList.map((item) => {
+                  return item.valueA === "--" || !item.valueA ? null : Number(item.valueA)
+                }),
+              },
+              {
+                name: "B鐩�" + (activeTabKey.value == 1 ? "鐢靛帇" : "鐢垫祦"),
+                data: itemList.map((item) => {
+                  return item.valueB === "--" || !item.valueB ? null : Number(item.valueB)
+                }),
+              },
+              {
+                name: "C鐩�" + (activeTabKey.value == 1 ? "鐢靛帇" : "鐢垫祦"),
+                data: itemList.map((item) => {
+                  return item.valueC === "--" || !item.valueC ? null : Number(item.valueC)
+                }),
+              },
+            ],
+          }
+        }
+        lineChartData.value = chartData
+      }
+    })
+    .catch(() => {
+      loading.value = false
+    })
+}
+// 纰虫帓鏀剧鐞�-纰虫帓鏀鹃噺鏍哥畻-鎼滅储
+function handleQuery() {
+  getList()
+}
+// 纰虫帓鏀剧鐞�-纰虫帓鏀鹃噺鏍哥畻-閲嶇疆
+function resetQuery() {
+  proxy.resetForm("queryRef")
+  queryParams.value.timeType = null
+  queryParams.value.dataTime = null
+  handleTimeType(period.value[0].value)
+  handleQuery()
+}
+// 纰虫帓鏀剧鐞�-纰虫帓鏀鹃噺鏍哥畻-瀵煎嚭
+function handleExport() {
+  proxy.download(
+    "carbonEmission/export",
+    {
+      emissionType: "allType",
+      ...queryParams.value,
+      ...query.value,
+    },
+    `${queryParams.value.nodeName}-纰虫帓鏀鹃噺鏍哥畻_${new Date().getTime()}.xlsx`
+  )
+}
+</script>
+<style scoped lang="scss">
+@import "@/assets/styles/page.scss";
+
+.themeDark {
+  .card-list {
+    width: 100%;
+    display: flex;
+    flex-wrap: wrap;
+    padding: 18px;
+    color: #fff;
+
+    .card-list-item {
+      width: 19%;
+      margin-right: 1%;
+      height: 157px;
+      background: #223386;
+      border-radius: 5px 5px 5px 5px;
+      border: 1px solid #4868b7;
+      background-size: 100% 100%;
+      box-sizing: border-box;
+      padding: 25px 18px 12px 16px;
+
+      .item-top {
+        display: flex;
+        align-items: center;
+
+        .top-icon {
+          width: 40px;
+          height: 40px;
+          background-size: 100% 100%;
+        }
+
+        .top-right {
+          margin-left: 16px;
+          font-weight: bold;
+          font-size: 16px;
+          font-family: OPPOSans-Bold;
+        }
+      }
+
+      .item-bottom {
+        display: flex;
+        justify-content: space-between;
+        margin-top: 18px;
+        font-family: OPPOSans, OPPOSans;
+        font-weight: bold;
+        font-size: 14px;
+      }
+    }
+  }
+}
+
+.themeLight {
+  .card-list {
+    width: 100%;
+    display: flex;
+    flex-wrap: wrap;
+    padding: 18px;
+
+    .card-list-item {
+      width: 19%;
+      margin-right: 1%;
+      height: 157px;
+      background: #fff;
+      border-radius: 5px 5px 5px 5px;
+      border: 1px solid #e8e8e8;
+      background-size: 100% 100%;
+      box-sizing: border-box;
+      padding: 25px 18px 12px 16px;
+
+      .item-top {
+        display: flex;
+        align-items: center;
+
+        .top-icon {
+          width: 40px;
+          height: 40px;
+          background-size: 100% 100%;
+        }
+
+        .top-right {
+          margin-left: 16px;
+          font-weight: bold;
+          font-size: 16px;
+          color: #000;
+          font-family: OPPOSans-Bold;
+        }
+      }
+
+      .item-bottom {
+        display: flex;
+        justify-content: space-between;
+        margin-top: 18px;
+        font-family: OPPOSans, OPPOSans;
+        font-weight: bold;
+        font-size: 14px;
+      }
+    }
+  }
+}
+
+.chart-box {
+  width: 100%;
+  height: 100% !important;
+}
+.display-buttons {
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  .display-btn,
+  .active-display-btn {
+    width: 78px;
+    height: 34px;
+    background: #fff;
+    color: #409eff;
+    border: 2px solid #409eff;
+    border-radius: 4px;
+    margin-left: 10px;
+    text-align: center;
+    line-height: 31px;
+    font-size: 14px;
+    font-weight: 400;
+    cursor: pointer;
+    &:hover {
+      opacity: 0.9;
+    }
+  }
+  .active-display-btn {
+    background: #409eff;
+    color: #fff;
+  }
+}
+</style>
diff --git a/zhitan-vue/src/views/realtimemonitor/realtimemonitor/realtimemonitor.vue b/zhitan-vue/src/views/realtimemonitor/realtimemonitor/realtimemonitor.vue
index bab0dc2..23b7d46 100644
--- a/zhitan-vue/src/views/realtimemonitor/realtimemonitor/realtimemonitor.vue
+++ b/zhitan-vue/src/views/realtimemonitor/realtimemonitor/realtimemonitor.vue
@@ -9,13 +9,16 @@
           <el-form :model="queryParams" ref="queryRef" :inline="true">
             <el-form-item label="鑳芥簮绫诲瀷" prop="energyType">
               <el-select v-model="queryParams.energyType" placeholder="鑳芥簮绫诲瀷" @change="handleQuery">
-                <el-option :label="item.enername" :value="item.enersno" v-for="item in energyTypeList" :key="item.enersno" />
+                <el-option
+                  :label="item.enername"
+                  :value="item.enersno"
+                  v-for="item in energyTypeList"
+                  :key="item.enersno"
+                />
               </el-select>
             </el-form-item>
             <el-form-item>
-              <el-button type="primary" icon="Search" @click="handleQuery">
-                鎼滅储
-              </el-button>
+              <el-button type="primary" icon="Search" @click="handleQuery"> 鎼滅储 </el-button>
               <el-button icon="Refresh" @click="resetQuery"> 閲嶇疆 </el-button>
             </el-form-item>
             <el-form-item>
@@ -23,20 +26,24 @@
             </el-form-item>
           </el-form>
         </div>
-        <div style="
-            height: calc(100vh - 220px) !important;
-            max-height: calc(100vh - 220px) !important;
-            overflow-y: auto;
-          " v-loading="loading">
+        <div
+          style="height: calc(100vh - 220px) !important; max-height: calc(100vh - 220px) !important; overflow-y: auto"
+          v-loading="loading"
+        >
           <div v-for="(item, index) in energyRealTimeMonitorList" :key="index" v-show="!!item.deviceArray">
             <BaseCard :title="queryParams.nodeName + '-' + item.energyTypeName" v-if="item.deviceArray.length > 0">
               <el-scrollbar>
                 <div class="scrollbar-flex-content">
                   <p></p>
-                  <div class="scrollbar-demo-item item-tag" @click="handleClick(item, index1)" v-for="item1,index1 in item.deviceArray" :key="index1" :style="{
-                    backgroundColor:
-                      index1 == item.activeIndex ? '#5EC894' : '#9841FC',
-                  }">
+                  <div
+                    class="scrollbar-demo-item item-tag"
+                    @click="handleClick(item, index1)"
+                    v-for="(item1, index1) in item.deviceArray"
+                    :key="index1"
+                    :style="{
+                      backgroundColor: index1 == item.activeIndex ? '#5EC894' : '#9841FC',
+                    }"
+                  >
                     {{ item1.deviceName }}
                   </div>
                 </div>
@@ -71,18 +78,18 @@
                   {{ item.deviceArray[item.activeIndex].energyTypeName }}
                 </div>
                 <div class="card-box-ul">
-                  <div class="card-box-li" v-for="(item2, index2) in item.deviceArray[item.activeIndex]
-                    .energyIndexArray">
+                  <div
+                    class="card-box-li"
+                    v-for="(item2, index2) in item.deviceArray[item.activeIndex].energyIndexArray"
+                  >
                     <el-tooltip class="box-item" effect="dark" content="鏌ョ湅鍘嗗彶鏁版嵁" placement="top">
                       <dl @click="handleChartModal(item2)">
                         <dd class="title">
                           {{ item2.name }}
-                          <template v-if="!!item2.unit">
-                            ({{ item2.unit }})
-                          </template>
+                          <template v-if="!!item2.unit"> ({{ item2.unit }}) </template>
                         </dd>
                         <dd class="num">
-                          {{ item2.value!=null ? item2.value.toFixed(2) : '--' }}
+                          {{ item2.value != null ? item2.value.toFixed(2) : "--" }}
                         </dd>
                         <dd class="time">
                           <el-icon>
@@ -105,22 +112,22 @@
   </div>
 </template>
 <script setup name="energy-real-time-monitor">
-import chartModal from "./components/chart-modal.vue";
-import { listEnergyRealTimeMonitor } from "@/api/realTimeMonitor/realTimeMonitor";
-import { listEnergyTypeList } from "@/api/modelConfiguration/energyType";
-const { proxy } = getCurrentInstance();
-import { useRoute } from "vue-router";
-import useSettingsStore from "@/store/modules/settings";
-const settingsStore = useSettingsStore();
+import chartModal from "./components/chart-modal.vue"
+import { listEnergyRealTimeMonitor } from "@/api/realTimeMonitor/realTimeMonitor"
+import { listEnergyTypeList } from "@/api/modelConfiguration/energyType"
+const { proxy } = getCurrentInstance()
+import { useRoute } from "vue-router"
+import useSettingsStore from "@/store/modules/settings"
+const settingsStore = useSettingsStore()
 watch(
   () => settingsStore.sideTheme,
   (val) => {
-    getList();
+    getList()
   }
-);
-const energyTypeList = ref(undefined);
-let energyRealTimeMonitorList = ref([]);
-const loading = ref(false);
+)
+const energyTypeList = ref(undefined)
+let energyRealTimeMonitorList = ref([])
+const loading = ref(false)
 const data = reactive({
   queryParams: {
     nodeId: null,
@@ -128,24 +135,24 @@
     energyType: null,
   },
   query: { ...useRoute().query },
-});
-const { queryParams, query } = toRefs(data);
+})
+const { queryParams, query } = toRefs(data)
 /** 鑺傜偣鍗曞嚮浜嬩欢 */
 function handleNodeClick(data) {
-  queryParams.value.nodeId = data.id;
-  queryParams.value.nodeName = data.label;
+  queryParams.value.nodeId = data.id
+  queryParams.value.nodeName = data.label
   listEnergyTypeList().then((res) => {
-    energyTypeList.value = res.data;
-    queryParams.value.energyType = energyTypeList.value[0].enersno;
-    handleQuery();
-  });
+    energyTypeList.value = res.data
+    queryParams.value.energyType = energyTypeList.value[0].enersno
+    handleQuery()
+  })
 }
 function handleClick(item, index) {
-  item.activeIndex = index;
+  item.activeIndex = index
 }
 // 鑳芥簮瀹炴椂鐩戞帶-鑳芥簮瀹炴椂鐩戞帶-鍒楄〃
 function getList() {
-  loading.value = true;
+  loading.value = true
   listEnergyRealTimeMonitor(
     proxy.addDateRange({
       ...queryParams.value,
@@ -154,31 +161,31 @@
   ).then((res) => {
     if (!!res.code && res.code == 200) {
       res.data.map((item) => {
-        item.activeIndex = 0;
-      });
-      loading.value = false;
-      energyRealTimeMonitorList.value = res.data;
+        item.activeIndex = 0
+      })
+      loading.value = false
+      energyRealTimeMonitorList.value = res.data
     }
-  });
+  })
 }
 // 鑳芥簮瀹炴椂鐩戞帶-鑳芥簮瀹炴椂鐩戞帶-鎼滅储
 function handleQuery() {
-  energyRealTimeMonitorList.value = [];
-  getList();
+  energyRealTimeMonitorList.value = []
+  getList()
 }
 // 鑳芥簮瀹炴椂鐩戞帶-鑳芥簮瀹炴椂鐩戞帶-閲嶇疆
 function resetQuery() {
-  proxy.resetForm("queryRef");
-  queryParams.value.energyType = null;
-  energyRealTimeMonitorList.value = [];
-  handleQuery();
+  proxy.resetForm("queryRef")
+  queryParams.value.energyType = null
+  energyRealTimeMonitorList.value = []
+  handleQuery()
 }
-let chartRef = ref();
+let chartRef = ref()
 
 function handleChartModal(row) {
   if (chartRef.value) {
     row.nodeName = queryParams.value.nodeName
-    chartRef.value.handleOpen(row);
+    chartRef.value.handleOpen(row)
   }
 }
 </script>
@@ -213,6 +220,7 @@
 
     &-li {
       width: 18%;
+      min-width: 190px;
       margin: 1%;
       border-radius: 5px;
       border: 1px solid #22408c;
@@ -235,11 +243,10 @@
       }
 
       .num {
-        font-size: 22px;
+        font-size: 24px;
         color: #36d3ff;
         font-family: OPPOSans, OPPOSans;
         font-weight: 800;
-        font-size: 32px;
         text-align: left;
         font-style: normal;
         text-transform: none;
@@ -252,6 +259,7 @@
         text-align: left;
         font-style: normal;
         text-transform: none;
+        font-size: 14px;
       }
     }
 
@@ -423,12 +431,12 @@
 .item-tag {
   // width: 13%;
   text-align: center;
-  margin: 5px 8px;
+  margin: 2px 6px;
   border-radius: 8px;
-  padding: 7px 10px;
+  padding: 5px 10px;
   font-family: OPPOSans, OPPOSans;
   font-weight: 500;
-  font-size: 16px;
+  font-size: 14px;
   color: #ffffff;
   cursor: pointer;
 }

--
Gitblit v1.9.3