From 0164d6fadfd6590ab8d08b6ec3213a967cc6276f Mon Sep 17 00:00:00 2001
From: zhitan-cloud <394600+ustcyc@user.noreply.gitee.com>
Date: 星期六, 08 二月 2025 19:08:50 +0800
Subject: [PATCH] !54 !53 组态图更新 Merge pull request !54 from zhitan-cloud/develop1.0

---
 zhitan-system/src/main/java/com/zhitan/history/domain/dto/HistoricalDataDTO.java                            |   63 +
 zhitan-admin/src/main/java/com/zhitan/web/controller/statisticalAnalysis/StatisticalAnalysisController.java |  129 ++
 zhitan-system/src/main/java/com/zhitan/model/domain/vo/ModelNodeIndexInfor.java                             |   10 
 zhitan-system/src/main/java/com/zhitan/basicSetup/service/impl/SysEquipmentfileServiceImpl.java             |   59 +
 zhitan-admin/src/main/java/com/zhitan/web/controller/realtimedata/RealtimeTrendController.java              |   73 +
 zhitan-admin/src/main/java/com/zhitan/web/controller/energyMonitor/ElectricLoadController.java              |   58 +
 zhitan-system/src/main/java/com/zhitan/energyMonitor/domain/EnergyUnitToDevice.java                         |   71 +
 zhitan-system/src/main/resources/mapper/basicSetup/SysEquipmentfileMapper.xml                               |   48 
 zhitan-system/src/main/java/com/zhitan/energyMonitor/service/impl/EnergyUnitToDeviceServiceImpl.java        |  232 ++++
 zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/DataAnalysisMoMVO.java                 |   42 
 zhitan-vue/src/assets/images/img_logo.png                                                                   |    0 
 zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/DataAnalysisMoMExcel.java              |   47 
 zhitan-system/src/main/java/com/zhitan/realtimedata/mapper/SvgTrendMapper.java                              |   16 
 zhitan-system/src/main/resources/mapper/dataitem/DataItemMapper.xml                                         |   24 
 zhitan-system/src/main/java/com/zhitan/realtimedata/domain/SysEquipmentFile.java                            |   11 
 zhitan-system/src/main/java/com/zhitan/history/domain/vo/HistoricalDataExcel.java                           |   70 +
 zhitan-system/src/main/java/com/zhitan/realtimedata/service/impl/RealtimeDatabaseServiceImpl.java           |   12 
 zhitan-system/src/main/java/com/zhitan/dataitem/mapper/DataItemMapper.java                                  |   12 
 zhitan-system/src/main/java/com/zhitan/dataitem/service/impl/DataItemServiceImpl.java                       |   14 
 zhitan-system/src/main/java/com/zhitan/energyMonitor/domain/vo/EnergyCalculateCalcTV.java                   |   31 
 zhitan-system/src/main/java/com/zhitan/history/domain/vo/HistoricalDataVO.java                              |   77 +
 zhitan-system/src/main/java/com/zhitan/basicSetup/service/ISysEquipmentfileService.java                     |   33 
 zhitan-system/src/main/java/com/zhitan/realtimedata/service/impl/SvgTrendServicelmpl.java                   |   26 
 zhitan-system/src/main/java/com/zhitan/basicSetup/mapper/SysEquipmentfileMapper.java                        |   25 
 zhitan-system/src/main/java/com/zhitan/energyMonitor/domain/vo/UnitToDeviceRelationVO.java                  |   35 
 zhitan-system/src/main/java/com/zhitan/energyMonitor/domain/vo/ListElectricityMeterVO.java                  |   20 
 zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/service/IStatisticalAnalysisService.java         |   36 
 zhitan-vue/src/assets/images/font01.png                                                                     |    0 
 zhitan-vue/src/views/login.vue                                                                              |  295 +++--
 zhitan-system/src/main/resources/mapper/realtimedata/SvgTrendMapper.xml                                     |   37 
 zhitan-system/src/main/java/com/zhitan/realtimedata/service/ISvgTrendService.java                           |   15 
 zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/service/impl/StatisticalAnalysisServiceImpl.java |  293 +++++
 zhitan-system/src/main/java/com/zhitan/dataitem/service/IDataItemService.java                               |   11 
 zhitan-system/src/main/java/com/zhitan/energyMonitor/service/IEnergyUnitToDeviceService.java                |  100 +
 zhitan-system/src/main/java/com/zhitan/realtimedata/domain/vo/EquipmentMeasuringPointParameters.java        |   30 
 zhitan-admin/src/main/java/com/zhitan/web/controller/basicSetup/SysEquipmentfileController.java             |   91 +
 zhitan-vue/src/assets/images/login-background.png                                                           |    0 
 zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/DataAnalysisYoYExcel.java              |   47 
 zhitan-common/src/main/java/com/zhitan/common/constant/TimeTypeConst.java                                   |   25 
 zhitan-system/src/main/resources/mapper/model/ModelNodeMapper.xml                                           |    3 
 zhitan-system/src/main/java/com/zhitan/consumptionanalysis/service/impl/ConsumptionAnalysisServiceImpl.java |  369 +++---
 zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/DataAnalysisYoYVO.java                 |   42 
 zhitan-admin/src/main/java/com/zhitan/web/controller/history/HistoryDataTrendController.java                |  224 +++
 zhitan-vue/src/views/login copy.vue                                                                         |  293 +++++
 zhitan-system/src/main/java/com/zhitan/energyMonitor/mapper/EnergyUnitToDeviceMapper.java                   |   38 
 zhitan-vue/src/assets/images/logo.png                                                                       |    0 
 zhitan-common/src/main/java/com/zhitan/common/config/BaseConfig.java                                        |    4 
 /dev/null                                                                                                   |    0 
 zhitan-system/src/main/java/com/zhitan/realtimedata/service/RealtimeDatabaseService.java                    |   14 
 zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/dto/DataAnalysisMoMDTO.java               |   48 
 zhitan-system/src/main/java/com/zhitan/realtimedata/data/RealtimeDatabaseManager.java                       |  163 ++
 51 files changed, 3,100 insertions(+), 316 deletions(-)

diff --git a/zhitan-admin/src/main/java/com/zhitan/web/controller/basicSetup/SysEquipmentfileController.java b/zhitan-admin/src/main/java/com/zhitan/web/controller/basicSetup/SysEquipmentfileController.java
new file mode 100644
index 0000000..1fe189b
--- /dev/null
+++ b/zhitan-admin/src/main/java/com/zhitan/web/controller/basicSetup/SysEquipmentfileController.java
@@ -0,0 +1,91 @@
+package com.zhitan.web.controller.basicSetup;
+
+import com.zhitan.basicSetup.service.ISysEquipmentfileService;
+import com.zhitan.common.annotation.Log;
+import com.zhitan.common.config.BaseConfig;
+import com.zhitan.common.core.controller.BaseController;
+import com.zhitan.common.core.domain.AjaxResult;
+import com.zhitan.common.enums.BusinessType;
+import com.zhitan.common.utils.file.FileUploadUtils;
+import com.zhitan.common.utils.uuid.UUID;
+import com.zhitan.realtimedata.domain.SysEquipmentFile;
+import com.zhitan.realtimedata.domain.SysSvgInfo;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.List;
+
+
+/**
+ * 缁勬�佸浘Controller
+ *
+ * @author sys
+ * @date 2020-02-24
+ */
+@Slf4j
+@RestController
+@RequestMapping("/basicSetup/equipmentfile")
+public class SysEquipmentfileController extends BaseController {
+
+  private final ISysEquipmentfileService sysEquipmentfileService;
+
+  public SysEquipmentfileController(
+      ISysEquipmentfileService sysEquipmentfileService) {
+    this.sysEquipmentfileService = sysEquipmentfileService;
+  }
+
+  @PostMapping(value = "/upload")
+  @Log(title = "绯荤粺鍥�", businessType = BusinessType.IMPORT)
+  public AjaxResult upload(MultipartFile file) throws IOException {
+    if (!file.isEmpty()) {
+      String fileSuffix = FileUploadUtils.getExtension(file);
+      if (StringUtils.containsIgnoreCase(".svg,.jpg,.png,.gif", fileSuffix)) {
+        //鏂囦欢鏈�缁堜繚瀛樼殑缁濆璺緞
+        String filePath = FileUploadUtils.upload(BaseConfig.getConfigurePath(), file);
+        return AjaxResult.success(filePath);
+      }
+      return AjaxResult.error("鏂囦欢鏍煎紡閿欒");
+    }
+    return AjaxResult.error("绯荤粺鍥句笂浼犲け璐�");
+  }
+
+  /**
+   * 淇敼缁勬�佸浘
+   */
+  @Log(title = "绯荤粺鍥�", businessType = BusinessType.UPDATE)
+  @PutMapping
+  public AjaxResult edit(@RequestBody SysEquipmentFile sysEquipmentfile) {
+    try {
+      sysEquipmentfileService.saveEquipmentFile(sysEquipmentfile);
+      return AjaxResult.success();
+    } catch (Exception ex) {
+      log.error("缁勬�佸浘鏇存柊澶辫触", ex);
+      return AjaxResult.error();
+    }
+  }
+
+  @PutMapping("/setting/{nodeId}")
+  public AjaxResult saveSetting(@PathVariable("nodeId") String nodeId,
+      @RequestBody List<SysSvgInfo> svgInfo) {
+    try {
+      svgInfo.forEach(info -> info.setId(UUID.fastUUID().toString()));
+      sysEquipmentfileService.saveSettingInfo(nodeId, svgInfo);
+      return AjaxResult.success("淇濆瓨鎴愬姛锛�");
+    } catch (Exception ex) {
+      return AjaxResult.error("淇濆瓨澶辫触锛�");
+    }
+  }
+
+  @GetMapping("/configure/{nodeId}")
+  public AjaxResult getConfigure(@PathVariable("nodeId") String nodeId) {
+    try {
+      SysEquipmentFile sysEquipmentfile = sysEquipmentfileService.getConfigure(nodeId);
+      return AjaxResult.success(sysEquipmentfile);
+    } catch (Exception ex) {
+      return AjaxResult.error("鏌ヨ澶辫触锛�");
+    }
+  }
+}
diff --git a/zhitan-admin/src/main/java/com/zhitan/web/controller/energyMonitor/ElectricLoadController.java b/zhitan-admin/src/main/java/com/zhitan/web/controller/energyMonitor/ElectricLoadController.java
new file mode 100644
index 0000000..6434f20
--- /dev/null
+++ b/zhitan-admin/src/main/java/com/zhitan/web/controller/energyMonitor/ElectricLoadController.java
@@ -0,0 +1,58 @@
+package com.zhitan.web.controller.energyMonitor;
+
+import com.zhitan.common.annotation.Log;
+import com.zhitan.common.core.controller.BaseController;
+import com.zhitan.common.core.domain.AjaxResult;
+import com.zhitan.energyMonitor.service.IEnergyUnitToDeviceService;
+import com.zhitan.model.service.IEnergyIndexService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @Description: 璐熻嵎鍒嗘瀽
+ * @Author: yxw
+ * @Date: 2022-04-24
+ * @Version: V1.2
+ */
+@Api(tags = "璐熻嵎鍒嗘瀽")
+@RestController
+@RequestMapping("/loadAnalysis")
+@Slf4j
+public class ElectricLoadController extends BaseController {
+    @Autowired
+    private IEnergyUnitToDeviceService energyUnitToDeviceService;
+//    @Autowired
+//    private IElectricLoadService electricLoadService;
+    @Autowired
+    private IEnergyIndexService energyIndexService;
+
+    /**
+     * 鏍规嵁鐢佃〃id鑾峰彇璐熻嵎鍒嗘瀽鏁版嵁
+     *
+     * @param energyUnitId 鐢ㄨ兘鍗曞厓id
+     * @param meterId      鐢佃〃id
+     * @param timeType     鏃堕棿绫诲瀷 DAY/MONTH/YEAR
+     * @param timeCode     鏃堕棿鍊� 涓庢椂闂寸被鍨嬪搴旓細2022-03-21/2022-03/2022
+     * @return
+     */
+    @Log(title = "鏍规嵁鐢佃〃id鑾峰彇璐熻嵎鍒嗘瀽鏁版嵁")
+    @ApiOperation(value = "鏍规嵁鐢佃〃id鑾峰彇璐熻嵎鍒嗘瀽鏁版嵁", notes = "鏍规嵁鐢佃〃id鑾峰彇璐熻嵎鍒嗘瀽鏁版嵁")
+    @GetMapping(value = "/detail")
+    public AjaxResult list(@RequestParam(name = "energyUnitId") String energyUnitId,
+                           @RequestParam(name = "meterId") String meterId,
+                           @RequestParam(name = "timeType") String timeType,
+                           @RequestParam(name = "timeCode") String timeCode) {
+//        EnergyIndex energyIndex = energyIndexService.getDeviceIndexByCode(energyUnitId, meterId, CommonConst.TAG_CODE_ZYGGL);
+//
+//        EnergyUnitToDevice energyUnitToDevice = energyUnitToDeviceService.getEnergyUnitToDeviceById(energyUnitId, meterId);
+//        ListElectricLoadVO lsvo = electricLoadService.list(timeType, timeCode, energyIndex, energyUnitToDevice);
+        return AjaxResult.success(null);
+    }
+
+}
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
new file mode 100644
index 0000000..e1f067b
--- /dev/null
+++ b/zhitan-admin/src/main/java/com/zhitan/web/controller/history/HistoryDataTrendController.java
@@ -0,0 +1,224 @@
+package com.zhitan.web.controller.history;
+
+import cn.hutool.core.date.DateUtil;
+import com.zhitan.basicdata.domain.MeterImplement;
+import com.zhitan.basicdata.services.IMeterImplementService;
+import com.zhitan.common.annotation.Log;
+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.utils.poi.ExcelUtil;
+import com.zhitan.history.domain.dto.HistoricalDataDTO;
+import com.zhitan.history.domain.vo.HistoricalDataExcel;
+import com.zhitan.history.domain.vo.HistoricalDataVO;
+import com.zhitan.model.domain.EnergyIndex;
+import com.zhitan.model.service.IEnergyIndexService;
+import com.zhitan.realtimedata.domain.TagValue;
+import com.zhitan.realtimedata.service.RealtimeDatabaseService;
+import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 璁惧鍚仠瀹炴椂鐩戞祴Controller
+ *
+ * @author sys
+ * @date 2020-03-30
+ */
+@RestController
+@RequestMapping("/dataMonitoring/historyDataTrend")
+public class HistoryDataTrendController extends BaseController {
+    @Autowired
+    private final IEnergyIndexService energyIndexService;
+
+    @Autowired
+    private final IMeterImplementService meterImplementService;
+
+    @Autowired
+    private final RealtimeDatabaseService realtimeDatabaseService;
+
+
+    public HistoryDataTrendController(IEnergyIndexService energyIndexService,
+                                      IMeterImplementService meterImplementService,
+                                      RealtimeDatabaseService realtimeDatabaseService) {
+        this.energyIndexService = energyIndexService;
+        this.meterImplementService = meterImplementService;
+        this.realtimeDatabaseService = realtimeDatabaseService;
+    }
+
+
+    @Log(title = "鑾峰彇妯″瀷鑺傜偣鍏宠仈閲囬泦鎸囨爣", businessType = BusinessType.UPDATE)
+    @GetMapping("/energyIndex/list")
+    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);
+            return AjaxResult.error("鑾峰彇鍏宠仈鎸囨爣鍑洪敊!");
+        }
+    }
+
+    @Log(title = "鏍规嵁鏃堕棿涓庣偣浣嶆煡璇㈠巻鍙茬洃娴嬫暟鎹�", businessType = BusinessType.UPDATE)
+    @GetMapping("/getHistoricalDataByIndexId")
+    public AjaxResult getHistoricalDataByIndexId(HistoricalDataDTO dto) {
+        try {
+            // 鑾峰彇鐐逛綅淇℃伅
+            EnergyIndex energyIndex = energyIndexService.selectEnergyIndexById(dto.getIndexId());
+            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);
+            } else {
+                count = 3600;
+                endTime = DateUtil.offsetSecond(DateUtil.offsetHour(beginTime, 1), -1);
+            }
+            // 鏌ヨ璁¢噺鍣ㄥ叿
+            MeterImplement info = meterImplementService.selectMeterImplementById(energyIndex.getMeterId());
+            List<TagValue> tagValueList = realtimeDatabaseService.retrieve(energyIndex.getCode(), beginTime, endTime,
+                    RetrievalModes.BestFit, count);
+            List<HistoricalDataVO> voList = new ArrayList<>();
+            Date date = DateUtil.date();
+            for (int i = 0; i < count + 1; i++) {
+                HistoricalDataVO vo = new HistoricalDataVO();
+                vo.setIndexId(energyIndex.getIndexId());
+                String indexName = energyIndex.getName();
+                if (ObjectUtils.isNotEmpty(info)) {
+                    indexName = info.getInstallactionLocation() + "_" + info.getMeterName() + "_" + indexName;
+                }
+                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);
+        } catch (Exception ex) {
+            logger.error("鏌ヨ鍘嗗彶鐩戞祴鏁版嵁鍑洪敊锛�", ex);
+            return AjaxResult.error("鏌ヨ鍘嗗彶鐩戞祴鏁版嵁鍑洪敊!");
+        }
+    }
+
+    @Log(title = "瀵煎嚭Excel", businessType = BusinessType.UPDATE)
+    @GetMapping("/export")
+    public AjaxResult export(HistoricalDataDTO dto) {
+        try {
+            // 鑾峰彇鐐逛綅淇℃伅
+            EnergyIndex energyIndex = energyIndexService.selectEnergyIndexById(dto.getIndexId());
+            if (ObjectUtils.isEmpty(energyIndex)) {
+                return AjaxResult.success("鏈壘鍒扮偣浣嶄俊鎭�");
+            }
+            Date beginTime = dto.getDataTime();
+            Date endTime;
+            // 鏌ヨ鏉℃暟
+            int count = 23;
+            if ("DAY".equals(dto.getTimeType())) {
+                endTime = DateUtil.endOfDay(beginTime);
+            } else {
+                count = 19;
+                endTime = DateUtil.offsetSecond(DateUtil.offsetHour(beginTime, 1), -1);
+            }
+            // 鏌ヨ璁¢噺鍣ㄥ叿
+            MeterImplement infor = meterImplementService.selectMeterImplementById(energyIndex.getMeterId());
+            List<TagValue> tagValueList = realtimeDatabaseService.retrieve(energyIndex.getCode(), beginTime, endTime,
+                    RetrievalModes.BestFit, count);
+            List<HistoricalDataExcel> excelList = new ArrayList<>();
+            Date date = DateUtil.date();
+            for (int i = 0; i < count + 1; i++) {
+                HistoricalDataExcel vo = new HistoricalDataExcel();
+                String indexName = energyIndex.getName();
+                if (ObjectUtils.isNotEmpty(infor)) {
+                    indexName = infor.getInstallactionLocation() + "_" + infor.getMeterName() + "_" + indexName;
+                }
+                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 (i > 0) {
+                            TagValue previousTagValue = tagValueList.get(i - 1);
+                            BigDecimal previousValue = BigDecimal.valueOf(previousTagValue.getValue());
+                            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.offsetHour(beginTime, 1);
+                } else {
+                    beginTime = DateUtil.offsetMinute(beginTime, 3);
+                }
+                vo.setValue(String.valueOf(value));
+                vo.setUsedValue(String.valueOf(usedValue));
+                excelList.add(vo);
+            }
+            ExcelUtil<HistoricalDataExcel> util = new ExcelUtil<>(HistoricalDataExcel.class);
+            String sheetName = "鍘嗗彶鏁版嵁缁熻" + DateUtil.formatDate(dto.getDataTime());
+//            return util.exportRealTimeDataExcel(excelList, sheetName);
+            return util.exportExcel(excelList, sheetName);
+        } catch (Exception ex) {
+            logger.error("瀵煎嚭Excel鏁版嵁鍑洪敊锛�", ex);
+            return AjaxResult.error("瀵煎嚭Excel鏁版嵁鍑洪敊!");
+        }
+    }
+
+}
diff --git a/zhitan-admin/src/main/java/com/zhitan/web/controller/realtimedata/RealtimeTrendController.java b/zhitan-admin/src/main/java/com/zhitan/web/controller/realtimedata/RealtimeTrendController.java
index 9acf65f..43cb400 100644
--- a/zhitan-admin/src/main/java/com/zhitan/web/controller/realtimedata/RealtimeTrendController.java
+++ b/zhitan-admin/src/main/java/com/zhitan/web/controller/realtimedata/RealtimeTrendController.java
@@ -5,9 +5,14 @@
 import com.zhitan.common.core.domain.AjaxResult;
 import com.zhitan.common.enums.BusinessType;
 import com.zhitan.common.utils.poi.ExcelUtil;
+import com.zhitan.model.domain.EnergyIndex;
+import com.zhitan.realtimedata.domain.TagValue;
 import com.zhitan.realtimedata.domain.dto.EnergyIndexMonitorDTO;
+import com.zhitan.realtimedata.domain.vo.EquipmentMeasuringPointParameters;
 import com.zhitan.realtimedata.domain.vo.EquipmentPointParametersExcel;
 import com.zhitan.realtimedata.domain.vo.ExportrealtimeTrendVO;
+import com.zhitan.realtimedata.service.ISvgTrendService;
+import com.zhitan.realtimedata.service.RealtimeDatabaseService;
 import com.zhitan.realtimedata.service.RealtimeTrendService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -15,14 +20,18 @@
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
 
 /**
- * @Description 瀹炴椂鐩戞祴鎺у埗绫�
- *
- * @Author zhoubg
- * @date 2024-10-15
+ * 瀹炴椂鐩戞祴鎺у埗绫�
  **/
 @RestController
 @RequestMapping("rtdb/realtimeTrend")
@@ -31,11 +40,13 @@
 
     @Autowired
     private RealtimeTrendService realtimeTrendService;
+    @Resource
+    private ISvgTrendService svgTrendService;
+    @Resource
+    private RealtimeDatabaseService realtimeDatabaseService;
 
     /**
      * 鑾峰彇妯″瀷鑺傜偣鍏宠仈閲囬泦鎸囨爣
-     *
-     * @return
      */
     @GetMapping("/list")
     @ApiOperation(value = "鑾峰彇妯″瀷鑺傜偣鍏宠仈閲囬泦鎸囨爣")
@@ -45,9 +56,6 @@
 
     /**
      * 鑾峰彇鍘嗗彶妯″瀷鑺傜偣鍏宠仈閲囬泦鎸囨爣鏁版嵁
-     * @param tagCode
-     * @param dataTime
-     * @return
      */
     @Log(title = "鑾峰彇鍘嗗彶妯″瀷鑺傜偣鍏宠仈閲囬泦鎸囨爣鏁版嵁", businessType = BusinessType.UPDATE)
     @GetMapping("/chartByDay")
@@ -58,7 +66,6 @@
 
     /**
      * 瀵煎嚭瀹炴椂鐩戞祴Excel淇℃伅
-     * @return
      */
     @Log(title = "瀵煎嚭瀹炴椂鐩戞祴Excel淇℃伅", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
@@ -69,4 +76,50 @@
         util.exportExcel(response,list, "瀹炴椂鐩戞祴");
     }
 
+    /**
+     * 鑾峰彇妯″瀷鑺傜偣鍏宠仈閲囬泦鎸囨爣
+     */
+    @Log(title = "鑾峰彇妯″瀷鑺傜偣鍏宠仈閲囬泦鎸囨爣", businessType = BusinessType.UPDATE)
+    @GetMapping("/svgTrendView/energyIndex/list")
+    @ApiOperation(value = "鑾峰彇妯″瀷鑺傜偣鍏宠仈閲囬泦鎸囨爣")
+    public AjaxResult getSvgTrendViewSettingIndex(EnergyIndex energyIndex) {
+        try {
+            List<EnergyIndex> infoList = svgTrendService.selectSvgList(energyIndex);
+            if (infoList == null || infoList.isEmpty()){
+                return AjaxResult.success(Collections.emptyList());
+            }
+            List<String> codeList = infoList.stream().map(EnergyIndex::getCode).collect(Collectors.toList());
+
+            List<TagValue> valList = realtimeDatabaseService.retrieve(codeList);
+            if (valList == null || valList.isEmpty()) {
+                return AjaxResult.success(Collections.emptyList());
+            }
+
+            Map<String, List<TagValue>> tagValueMap = valList.stream().collect(Collectors.groupingBy(TagValue::getTagCode));
+
+            List<EquipmentMeasuringPointParameters> resultList = infoList.stream().map(index -> {
+                EquipmentMeasuringPointParameters item = new EquipmentMeasuringPointParameters();
+                item.setCode(index.getCode());
+                item.setIndexName(index.getName());
+                item.setIndexUnit(index.getUnitId());
+                item.setMeteName(index.getMeterName());
+                item.setyValue("y0");
+
+                List<TagValue> tagValueList = tagValueMap.getOrDefault(index.getCode(), Collections.emptyList());
+                if (!tagValueList.isEmpty()){
+                    Optional<Double> sumOptional = tagValueList.stream()
+                            .map(TagValue::getValue)
+                            .reduce(Double::sum);
+                    sumOptional.ifPresent(sum -> item.setValue(BigDecimal.valueOf(sum)
+                            .setScale(2, RoundingMode.HALF_UP).doubleValue()));
+                }
+                return item;
+            }).collect(Collectors.toList());
+
+            return AjaxResult.success(resultList);
+        } catch (Exception ex) {
+            logger.error("鑾峰彇鍏宠仈閲囬泦鎸囨爣鍑洪敊锛�", ex);
+            return AjaxResult.error("鑾峰彇鍏宠仈鎸囨爣鍑洪敊!");
+        }
+    }
 }
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
new file mode 100644
index 0000000..b93f9c7
--- /dev/null
+++ b/zhitan-admin/src/main/java/com/zhitan/web/controller/statisticalAnalysis/StatisticalAnalysisController.java
@@ -0,0 +1,129 @@
+package com.zhitan.web.controller.statisticalAnalysis;
+
+import com.zhitan.common.core.controller.BaseController;
+import com.zhitan.common.core.domain.AjaxResult;
+import com.zhitan.common.utils.poi.ExcelUtil;
+import com.zhitan.statisticalAnalysis.domain.dto.DataAnalysisMoMDTO;
+import com.zhitan.statisticalAnalysis.domain.vo.DataAnalysisMoMExcel;
+import com.zhitan.statisticalAnalysis.domain.vo.DataAnalysisMoMVO;
+import com.zhitan.statisticalAnalysis.domain.vo.DataAnalysisYoYExcel;
+import com.zhitan.statisticalAnalysis.domain.vo.DataAnalysisYoYVO;
+import com.zhitan.statisticalAnalysis.service.IStatisticalAnalysisService;
+import io.swagger.annotations.ApiOperation;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * 缁熻鍒嗘瀽 鎺у埗灞�
+ */
+@RestController
+@RequestMapping("/statisticalAnalysis")
+public class StatisticalAnalysisController extends BaseController {
+
+    @Autowired
+    private IStatisticalAnalysisService analysisService;
+
+
+    @PostMapping("/getElectricDataComparisonYoY")
+    @ApiOperation(value = "鑾峰彇鐢佃兘鑰楀悓姣旀暟鎹�", notes = "鑾峰彇鐢佃兘鑰楀悓姣旀暟鎹�")
+    public AjaxResult listElectricDataComparisonYoY(@RequestBody @Validated DataAnalysisMoMDTO dto) {
+        List<DataAnalysisYoYVO> yoyList = analysisService.listElectricDataComparisonYoY(dto);
+        return AjaxResult.success(yoyList);
+    }
+
+    @PostMapping("/getElectricDataComparisonMoM")
+    @ApiOperation(value = "鑾峰彇鐢佃兘鑰楃幆姣旀暟鎹�", notes = "鑾峰彇鐢佃兘鑰楃幆姣旀暟鎹�")
+    public AjaxResult listElectricDataComparisonMoM(@RequestBody @Validated DataAnalysisMoMDTO dto) {
+        List<DataAnalysisMoMVO> momList = analysisService.listElectricDataComparisonMoM(dto);
+        return AjaxResult.success(momList);
+    }
+
+    @PostMapping("/getWaterDataComparisonYoY")
+    @ApiOperation(value = "鑾峰彇姘磋兘鑰楀悓姣旀暟鎹�", notes = "鑾峰彇姘磋兘鑰楀悓姣旀暟鎹�")
+    public AjaxResult listWaterDataComparisonYoY(@RequestBody @Validated DataAnalysisMoMDTO dto) {
+        List<DataAnalysisYoYVO> yoyList = analysisService.listWaterDataComparisonYoY(dto);
+        return AjaxResult.success(yoyList);
+    }
+
+    @PostMapping("/getWaterDataComparisonMoM")
+    @ApiOperation(value = "鑾峰彇姘磋兘鑰楃幆姣旀暟鎹�", notes = "鑾峰彇姘磋兘鑰楃幆姣旀暟鎹�")
+    public AjaxResult listWaterDataComparisonMoM(@RequestBody @Validated DataAnalysisMoMDTO dto) {
+        List<DataAnalysisMoMVO> momList = analysisService.listWaterDataComparisonMoM(dto);
+        return AjaxResult.success(momList);
+    }
+
+    @PostMapping("/exportElectricYoY")
+    @ApiOperation(value = "瀵煎嚭鐢佃兘鑰楀悓姣旀暟鎹�", notes = "瀵煎嚭鐢佃兘鑰楀悓姣旀暟鎹�")
+    public AjaxResult exportElectricComparisonYoY(@RequestBody @Validated DataAnalysisMoMDTO dto) {
+        List<DataAnalysisYoYExcel> yoYExcelsList = new ArrayList<>();
+        List<DataAnalysisYoYVO> yoYList = analysisService.listElectricDataComparisonYoY(dto);
+        if (CollectionUtils.isNotEmpty(yoYList)) {
+            for (DataAnalysisYoYVO vo : yoYList) {
+                DataAnalysisYoYExcel excel = new DataAnalysisYoYExcel();
+                BeanUtils.copyProperties(vo, excel);
+                yoYExcelsList.add(excel);
+            }
+        }
+        ExcelUtil<DataAnalysisYoYExcel> util = new ExcelUtil<>(DataAnalysisYoYExcel.class);
+        return util.exportExcel(yoYExcelsList, "鐢电患鍚堣兘鑰楀悓姣斾俊鎭�");
+    }
+
+//    @PostMapping("/exportElectricMoM")
+//    @ApiOperation(value = "瀵煎嚭鐢佃兘鑰楃幆姣旀暟鎹�", notes = "瀵煎嚭鐢佃兘鑰楃幆姣旀暟鎹�")
+//    public AjaxResult exportElectricComparisonMoM(@RequestBody @Validated DataAnalysisMoMDTO dto) {
+//        List<DataAnalysisMoMExcel> moMExcelsList = new ArrayList<>();
+//        List<DataAnalysisMoMVO> moMList = analysisService.listElectricDataComparisonMoM(dto);
+//        if (CollectionUtils.isNotEmpty(moMList)) {
+//            for (DataAnalysisMoMVO vo : moMList) {
+//                DataAnalysisMoMExcel excel = new DataAnalysisMoMExcel();
+//                BeanUtils.copyProperties(vo, excel);
+//                moMExcelsList.add(excel);
+//            }
+//        }
+//        ExcelUtil<DataAnalysisMoMExcel> util = new ExcelUtil<>(DataAnalysisMoMExcel.class);
+//        return util.exportRealTimeDataExcel(moMExcelsList, "鐢电患鍚堣兘鑰楃幆姣斾俊鎭�");
+//    }
+
+    @PostMapping("/exportWaterYoY")
+    @ApiOperation(value = "瀵煎嚭姘磋�楀悓姣旀暟鎹�", notes = "瀵煎嚭姘磋�楀悓姣旀暟鎹�")
+    public AjaxResult exportWaterComparisonYoY(@RequestBody @Validated DataAnalysisMoMDTO dto) {
+        List<DataAnalysisYoYExcel> yoYExcelsList = new ArrayList<>();
+        List<DataAnalysisYoYVO> yoYList = analysisService.listWaterDataComparisonYoY(dto);
+        if (CollectionUtils.isNotEmpty(yoYList)) {
+            for (DataAnalysisYoYVO vo : yoYList) {
+                DataAnalysisYoYExcel excel = new DataAnalysisYoYExcel();
+                BeanUtils.copyProperties(vo, excel);
+                yoYExcelsList.add(excel);
+            }
+        }
+        ExcelUtil<DataAnalysisYoYExcel> util = new ExcelUtil<>(DataAnalysisYoYExcel.class);
+        return util.exportExcel(yoYExcelsList, "姘寸患鍚堣兘鑰楄�楀悓姣斾俊鎭�");
+    }
+
+    @PostMapping("/exportWaterMoM")
+    @ApiOperation(value = "瀵煎嚭姘磋�楃幆姣旀暟鎹�", notes = "瀵煎嚭姘磋�楃幆姣旀暟鎹�")
+    public AjaxResult exportWaterComparisonMoM(@RequestBody @Validated DataAnalysisMoMDTO dto) {
+        List<DataAnalysisMoMExcel> moMExcelsList = new ArrayList<>();
+        List<DataAnalysisMoMVO> moMList = analysisService.listWaterDataComparisonMoM(dto);
+        if (CollectionUtils.isNotEmpty(moMList)) {
+            for (DataAnalysisMoMVO vo : moMList) {
+                DataAnalysisMoMExcel excel = new DataAnalysisMoMExcel();
+                BeanUtils.copyProperties(vo, excel);
+                moMExcelsList.add(excel);
+            }
+        }
+        ExcelUtil<DataAnalysisMoMExcel> util = new ExcelUtil<>(DataAnalysisMoMExcel.class);
+        return util.exportExcel(moMExcelsList, "姘寸患鍚堣兘鑰楄�楃幆姣斾俊鎭�");
+    }
+
+}
diff --git a/zhitan-common/src/main/java/com/zhitan/common/config/BaseConfig.java b/zhitan-common/src/main/java/com/zhitan/common/config/BaseConfig.java
index edd535b..c9096ba 100644
--- a/zhitan-common/src/main/java/com/zhitan/common/config/BaseConfig.java
+++ b/zhitan-common/src/main/java/com/zhitan/common/config/BaseConfig.java
@@ -119,4 +119,8 @@
     {
         return getProfile() + "/upload";
     }
+
+    public static String getConfigurePath() {
+        return getProfile() + "/configure";
+    }
 }
diff --git a/zhitan-common/src/main/java/com/zhitan/common/constant/TimeTypeConst.java b/zhitan-common/src/main/java/com/zhitan/common/constant/TimeTypeConst.java
new file mode 100644
index 0000000..0847ab2
--- /dev/null
+++ b/zhitan-common/src/main/java/com/zhitan/common/constant/TimeTypeConst.java
@@ -0,0 +1,25 @@
+package com.zhitan.common.constant;
+
+/**
+ * @Description: 鍛ㄦ湡绫诲瀷
+ * @author: yxw
+ * @date: 2022骞�03鏈�17鏃� 12:33
+ */
+public class TimeTypeConst {
+    /**
+     * 鍛ㄦ湡绫诲瀷 - 灏忔椂
+     */
+    public static final String TIME_TYPE_HOUR="HOUR";
+    /**
+     * 鍛ㄦ湡绫诲瀷 - 鏃�
+     */
+    public static final String TIME_TYPE_DAY="DAY";
+    /**
+     * 鍛ㄦ湡绫诲瀷 - 鏈�
+     */
+    public static final String TIME_TYPE_MONTH="MONTH";
+    /**
+     * 鍛ㄦ湡绫诲瀷 - 骞�
+     */
+    public static final String TIME_TYPE_YEAR="YEAR";
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/basicSetup/mapper/SysEquipmentfileMapper.java b/zhitan-system/src/main/java/com/zhitan/basicSetup/mapper/SysEquipmentfileMapper.java
new file mode 100644
index 0000000..17a7b14
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/basicSetup/mapper/SysEquipmentfileMapper.java
@@ -0,0 +1,25 @@
+package com.zhitan.basicSetup.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhitan.realtimedata.domain.SysEquipmentFile;
+import com.zhitan.realtimedata.domain.SysSvgInfo;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 缁勬�佸浘Mapper鎺ュ彛
+ *
+ * @author sys
+ * @date 2020-02-24
+ */
+public interface SysEquipmentfileMapper extends BaseMapper<SysEquipmentFile> {
+
+  void saveEquipmentFile(SysEquipmentFile sysEquipmentfile);
+
+  void saveSettingInfo(@Param("nodeId") String nodeId, @Param("svgInfo") List<SysSvgInfo> svgInfo);
+
+  SysEquipmentFile getConfigure(String nodeId);
+
+  List<SysSvgInfo> getConfigureTag(String nodeId);
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/basicSetup/service/ISysEquipmentfileService.java b/zhitan-system/src/main/java/com/zhitan/basicSetup/service/ISysEquipmentfileService.java
new file mode 100644
index 0000000..f62ca2a
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/basicSetup/service/ISysEquipmentfileService.java
@@ -0,0 +1,33 @@
+package com.zhitan.basicSetup.service;
+
+import com.zhitan.realtimedata.domain.SysEquipmentFile;
+import com.zhitan.realtimedata.domain.SysSvgInfo;
+
+import java.util.List;
+
+/**
+ * 缁勬�佸浘Service鎺ュ彛
+ *
+ * @author sys
+ * @date 2020-02-24
+ */
+public interface ISysEquipmentfileService {
+
+  void saveEquipmentFile(SysEquipmentFile sysEquipmentfile);
+
+  void saveSettingInfo(String nodeId, List<SysSvgInfo> svgInfo);
+
+  /**
+   * 鑾峰彇缁勬�佸浘閰嶇疆淇℃伅
+   * @param nodeId 妯″瀷鑺傜偣 id
+   * @return
+   */
+  SysEquipmentFile getConfigure(String nodeId);
+
+  /**
+   * 鑾峰彇缁勬�佸浘閰嶇疆鐨勭偣浣嶅彿
+   * @param nodeId 妯″瀷鑺傜偣 id
+   * @return
+   */
+  List<SysSvgInfo> getConfigureTag(String nodeId);
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/basicSetup/service/impl/SysEquipmentfileServiceImpl.java b/zhitan-system/src/main/java/com/zhitan/basicSetup/service/impl/SysEquipmentfileServiceImpl.java
new file mode 100644
index 0000000..2f4dd10
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/basicSetup/service/impl/SysEquipmentfileServiceImpl.java
@@ -0,0 +1,59 @@
+package com.zhitan.basicSetup.service.impl;
+
+import com.zhitan.basicSetup.mapper.SysEquipmentfileMapper;
+import com.zhitan.basicSetup.service.ISysEquipmentfileService;
+import com.zhitan.realtimedata.domain.SysEquipmentFile;
+import com.zhitan.realtimedata.domain.SysSvgInfo;
+import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 缁勬�佸浘Service涓氬姟灞傚鐞�
+ *
+ * @author sys
+ * @date 2020-02-24
+ */
+@Service
+public class SysEquipmentfileServiceImpl implements ISysEquipmentfileService {
+
+  @Autowired
+  private SysEquipmentfileMapper equipmentfileMapper;
+
+  @Override
+  public void saveEquipmentFile(SysEquipmentFile sysEquipmentfile) {
+    SysEquipmentFile sysEquipmentFile = equipmentfileMapper.selectById(sysEquipmentfile.getNodeId());
+    if (ObjectUtils.isNotEmpty(sysEquipmentFile)){
+      sysEquipmentFile.setFilePath(sysEquipmentfile.getFilePath());
+      equipmentfileMapper.updateById(sysEquipmentFile);
+    }else {
+      SysEquipmentFile equipmentFile = new SysEquipmentFile();
+      equipmentFile.setFilePath(sysEquipmentfile.getFilePath());
+      equipmentFile.setNodeId(sysEquipmentfile.getNodeId());
+      equipmentfileMapper.insert(equipmentFile);
+    }
+  }
+
+  @Override
+  public void saveSettingInfo(String nodeId, List<SysSvgInfo> svgInfo) {
+    equipmentfileMapper.saveSettingInfo(nodeId, svgInfo);
+  }
+
+  @Override
+  public SysEquipmentFile getConfigure(String nodeId) {
+    SysEquipmentFile sysEquipmentfile = equipmentfileMapper.getConfigure(nodeId);
+    List<SysSvgInfo> infos = getConfigureTag(nodeId);
+    if (sysEquipmentfile != null) {
+      sysEquipmentfile.setInfoList(infos);
+    }
+
+    return sysEquipmentfile;
+  }
+
+  @Override
+  public List<SysSvgInfo> getConfigureTag(String nodeId) {
+    return equipmentfileMapper.getConfigureTag(nodeId);
+  }
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/consumptionanalysis/service/impl/ConsumptionAnalysisServiceImpl.java b/zhitan-system/src/main/java/com/zhitan/consumptionanalysis/service/impl/ConsumptionAnalysisServiceImpl.java
index 4f48bc5..7d1db3e 100644
--- a/zhitan-system/src/main/java/com/zhitan/consumptionanalysis/service/impl/ConsumptionAnalysisServiceImpl.java
+++ b/zhitan-system/src/main/java/com/zhitan/consumptionanalysis/service/impl/ConsumptionAnalysisServiceImpl.java
@@ -44,20 +44,20 @@
     private final ModelNodeMapper modelNodeMapper;
 
     private final EnergyIndicatorsMapper energyIndicatorsMapper;
-    
+
     private final ProductOutputMapper productOutputMapper;
-    
+
     private final SysEnergyMapper sysEnergyMapper;
 
     private final IDataItemService dataItemService;
 
     private final IModelNodeService modelNodeService;
-    
+
     @Override
     public ConsumptionAnalysisVO getByArea(ConsumptionAnalysisDTO dto) {
         List<ConsumptionAnalysisData> dataList = new ArrayList<>();
         List<ChartData> chartDataList = new ArrayList<>();
-        
+
         ConsumptionAnalysisVO consumptionAnalysisVO = new ConsumptionAnalysisVO();
         final String analysisType = dto.getAnalysisType();
         final String nodeId = dto.getNodeId();
@@ -67,7 +67,7 @@
         /**
          * 鏌ヨ鐐逛綅涓庣敤鑳藉崟鍏冧俊鎭�
          */
-        List<ModelNodeIndexInfor> nodeIndexInforList = modelNodeMapper.getModelNodeIndexIdByNodeId(nodeId,energyType);
+        List<ModelNodeIndexInfor> nodeIndexInforList = modelNodeMapper.getModelNodeIndexIdByNodeId(nodeId, energyType);
 
 //        if (CollectionUtils.isEmpty(nodeIndexInforList)) {
 //            return consumptionAnalysisVO;
@@ -88,7 +88,7 @@
                 //鍚屾瘮鍒嗘瀽锛屾椂闂村彇鍘诲勾鐨�
                 lastTime = DateUtil.offsetMonth(beginTime, -12);
                 lastEndTime = DateUtil.offsetMonth(endTime, -12);
-            }else {
+            } else {
                 //鐜瘮鍒嗘瀽锛屾椂闂村彇 鏄ㄥぉ
                 lastTime = DateUtil.offsetDay(beginTime, -1);
                 lastEndTime = DateUtil.offsetDay(endTime, -1);
@@ -103,7 +103,7 @@
                 //鍚屾瘮鍒嗘瀽锛屾椂闂村彇鍘诲勾鐨�
                 lastTime = DateUtil.offsetMonth(beginTime, -12);
                 lastEndTime = DateUtil.offsetMonth(endTime, -12);
-            }else {
+            } else {
                 //鐜瘮鍒嗘瀽锛屾椂闂村彇 鏄ㄥぉ
                 lastTime = DateUtil.offsetMonth(beginTime, -1);
                 lastEndTime = DateUtil.offsetMonth(endTime, -1);
@@ -118,18 +118,18 @@
                 //鍚屾瘮鍒嗘瀽锛屾椂闂村彇鍘诲勾鐨�
                 lastTime = DateUtil.offsetMonth(beginTime, -12);
                 lastEndTime = DateUtil.offsetMonth(endTime, -12);
-            }else {
+            } else {
                 //鐜瘮鍒嗘瀽锛屾椂闂村彇 鏄ㄥぉ
-                lastTime = DateUtil.offsetMonth(beginTime,  -1);
-                lastEndTime = DateUtil.offsetMonth(endTime,  -1);
+                lastTime = DateUtil.offsetMonth(beginTime, -1);
+                lastEndTime = DateUtil.offsetMonth(endTime, -1);
             }
-            
+
             timeFormat = "yyyy-MM";
         }
         // 鏍规嵁indexId鏌ヨdataItem
         List<DataItem> dataItemList = new ArrayList<>();
         List<DataItem> lastDataItemList = new ArrayList<>();
-        if(CollectionUtils.isNotEmpty(indexIds)) {
+        if (CollectionUtils.isNotEmpty(indexIds)) {
             dataItemList = dataItemService.getDataItemTimeRangeInforByIndexIds(beginTime, endTime, shixuTimeType, indexIds);
             lastDataItemList = dataItemService.getDataItemTimeRangeInforByIndexIds(lastTime, lastEndTime, shixuTimeType, indexIds);
         }
@@ -144,11 +144,11 @@
             final String compareTime;
             DateTime dateTime;
             if (TimeType.DAY.name().equals(queryTimeType)) {
-               
+
                 if ("YOY".equals(analysisType)) {
                     //鍚屾瘮鍒嗘瀽锛屾椂闂村彇鍘诲勾鐨�
                     dateTime = DateUtil.offsetMonth(beginTime, -12);
-                }else {
+                } else {
                     //鐜瘮鍒嗘瀽锛屾椂闂村彇 鏄ㄥぉ
                     dateTime = DateUtil.offsetDay(beginTime, -1);
                 }
@@ -158,7 +158,7 @@
                 if ("YOY".equals(analysisType)) {
                     //鍚屾瘮鍒嗘瀽锛屾椂闂村彇鍘诲勾鐨�
                     dateTime = DateUtil.offsetMonth(beginTime, -12);
-                }else {
+                } else {
                     //鐜瘮鍒嗘瀽锛屾椂闂村彇 鏄ㄥぉ
                     dateTime = DateUtil.offsetMonth(beginTime, -1);
                 }
@@ -168,25 +168,25 @@
                 if ("YOY".equals(analysisType)) {
                     //鍚屾瘮鍒嗘瀽锛屾椂闂村彇鍘诲勾鐨�
                     dateTime = DateUtil.offsetMonth(beginTime, -12);
-                }else {
+                } else {
                     //鐜瘮鍒嗘瀽锛屾椂闂村彇 鏄ㄥぉ
-                    dateTime = DateUtil.offsetMonth(beginTime,  -1);
+                    dateTime = DateUtil.offsetMonth(beginTime, -1);
                 }
                 compareTime = DateUtil.format(dateTime, timeFormat);
             }
-            
-            
+
+
             final List<DataItem> dataItems = dataItemMap.get(currentTime);
             final List<DataItem> lastDataItems = lastDataItemMap.get(compareTime);
             BigDecimal sum = new BigDecimal(0);
             BigDecimal lastSum = new BigDecimal(0);
             if (CollectionUtils.isNotEmpty(dataItems)) {
-                 // 姹傚拰
-                 sum = BigDecimal.valueOf(dataItems.stream()
+                // 姹傚拰
+                sum = BigDecimal.valueOf(dataItems.stream()
                         .mapToDouble(DataItem::getValue).sum()).setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP);
             }
-            
-            if(CollectionUtils.isNotEmpty(lastDataItems)) {
+
+            if (CollectionUtils.isNotEmpty(lastDataItems)) {
                 lastSum = BigDecimal.valueOf(lastDataItems.stream()
                         .mapToDouble(DataItem::getValue).sum()).setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP);
             }
@@ -194,7 +194,7 @@
             data.setCompareValue(lastSum.doubleValue());
             data.setCurrentTime(currentTime);
             data.setCompareTime(compareTime);
-            
+
 
             if ("YOY".equals(analysisType)) {
                 //鍚屾瘮鍒嗘瀽
@@ -238,7 +238,7 @@
             chartDataList.add(chartData);
 
         });
-        
+
         consumptionAnalysisVO.setDataList(dataList);
         consumptionAnalysisVO.setChartDataList(chartDataList);
         return consumptionAnalysisVO;
@@ -252,32 +252,32 @@
         String queryTimeType = dto.getTimeType();
         // 鍒涘缓涓�涓狹ap鏉ュ瓨鍌ㄦ�诲拰
         Map<String, BigDecimal> result = new HashMap<>();
-        
-        
+
+
         //鏍规嵁妯″瀷鍚嶇О鏌ヨmodelCode
         final String parentId = dto.getNodeId();
-        
+
         //鏍规嵁鎬荤粨鐐规煡璇�
         final List<ModelNodeIndexInfor> nodeIndexInforList = modelNodeMapper.getModelNodeByParentId(parentId);
 
         final List<String> eneryIdList = nodeIndexInforList.stream().map(ModelNodeIndexInfor::getEnergyId).distinct().collect(Collectors.toList());
         final LambdaQueryWrapper<SysEnergy> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.in(CollectionUtils.isNotEmpty(eneryIdList),SysEnergy::getEnersno,eneryIdList);
+        queryWrapper.in(CollectionUtils.isNotEmpty(eneryIdList), SysEnergy::getEnersno, eneryIdList);
         final List<SysEnergy> sysEnergies = sysEnergyMapper.selectList(queryWrapper);
         final Map<String, String> energyNameMap = sysEnergies.stream().collect(Collectors.toMap(SysEnergy::getEnersno, SysEnergy::getEnername));
         final Map<String, String> nodeNameMap = new HashMap<>();
-        nodeIndexInforList.forEach(n->{
+        nodeIndexInforList.forEach(n -> {
             final String nodeId = n.getNodeId();
             final String name = n.getName();
-            if(!nodeNameMap.containsKey(nodeId)){
-                nodeNameMap.put(nodeId,name);
+            if (!nodeNameMap.containsKey(nodeId)) {
+                nodeNameMap.put(nodeId, name);
             }
         });
 
         // 鎸夌収鐐逛綅杩涜鍒嗙粍
         Map<String, List<ModelNodeIndexInfor>> nodeIndexMap = nodeIndexInforList.stream().collect(
                 Collectors.groupingBy(ModelNodeIndexInfor::getNodeId));
-        
+
         // 鏍规嵁nodeId鑾峰彇鑳芥簮绫诲瀷
         // 鎵�鏈夌偣浣嶄俊鎭�
         List<String> indexIds = nodeIndexInforList.stream().map(ModelNodeIndexInfor::getIndexId).distinct().collect(Collectors.toList());
@@ -300,27 +300,26 @@
             endTime = DateUtil.endOfYear(queryTime);
             shixuTimeType = TimeType.MONTH.name();
         }
-        
-        
+
+
         // 鏍规嵁indexId鏌ヨdataItem
         List<DataItem> dataItemList = new ArrayList<>();
-        if(CollectionUtils.isNotEmpty(indexIds)) {
+        if (CollectionUtils.isNotEmpty(indexIds)) {
             dataItemList = dataItemService.getDataItemTimeRangeInforByIndexIds(beginTime, endTime, shixuTimeType, indexIds);
         }
         final Map<String, List<DataItem>> dataItemMap = dataItemList.stream().collect(Collectors.groupingBy(DataItem::getIndexId));
-        
+
         // 鏍规嵁鐐逛綅鍒嗙粍锛屾眰鍜�
-        Map<String,BigDecimal> dataItemTotalMap = new HashMap<>();
-        dataItemMap.forEach((key,value)->{
+        Map<String, BigDecimal> dataItemTotalMap = new HashMap<>();
+        dataItemMap.forEach((key, value) -> {
             BigDecimal sum = BigDecimal.valueOf(value.stream()
                     .mapToDouble(DataItem::getValue).sum()).setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP);
-            dataItemTotalMap.put(key,sum);
+            dataItemTotalMap.put(key, sum);
         });
 
-        
-        
-        nodeIndexMap.forEach((nodeId,indexList)->{
-            indexList.forEach(index->{
+
+        nodeIndexMap.forEach((nodeId, indexList) -> {
+            indexList.forEach(index -> {
                 final String energyId = index.getEnergyId();
                 final String indexId = index.getIndexId();
                 final BigDecimal total = dataItemTotalMap.getOrDefault(indexId, BigDecimal.ZERO);
@@ -337,15 +336,15 @@
             String energyId = keys[1];
             BigDecimal totalEnergy = entry.getValue();
             chartData.setEnergyTypeNo(energyId);
-            chartData.setEnergyTypeName(energyNameMap.getOrDefault(energyId,""));
-            chartData.setNodeName(nodeNameMap.getOrDefault(nodeId,""));
+            chartData.setEnergyTypeName(energyNameMap.getOrDefault(energyId, ""));
+            chartData.setNodeName(nodeNameMap.getOrDefault(nodeId, ""));
             chartData.setEnergyConsumption(totalEnergy.doubleValue());
             chartData.setNodeId(nodeId);
             rankingEnergyData.add(chartData);
-            
+
         }
         final Map<String, List<RankingEnergyData>> collect = rankingEnergyData.stream().collect(Collectors.groupingBy(RankingEnergyData::getNodeId));
-        nodeNameMap.forEach((key,value)->{
+        nodeNameMap.forEach((key, value) -> {
             final List<RankingEnergyData> rankingEnergyData1 = collect.get(key);
             RankingDataVO rankingDataVO = new RankingDataVO();
             rankingDataVO.setNodeId(key);
@@ -353,7 +352,7 @@
             rankingDataVO.setData(rankingEnergyData1);
             rankingDataVOArrayList.add(rankingDataVO);
         });
-        
+
         return rankingDataVOArrayList;
     }
 
@@ -382,7 +381,7 @@
         List<EnergyProportion> energyProportionList = new ArrayList<>();
 
         ConsumptionAnalysisVO consumptionAnalysisVO = new ConsumptionAnalysisVO();
-        
+
         //todo hmj 缁煎悎鑳借�楀厛榛樿鍙栧悓姣�
         final String analysisType = "YOY";
         final String nodeId = dto.getNodeId();
@@ -392,24 +391,25 @@
         /**
          * 鏌ヨ鐐逛綅涓庣敤鑳藉崟鍏冧俊鎭�
          */
-        List<ModelNodeIndexInfor> nodeIndexInforList = modelNodeMapper.getModelNodeIndexIdByNodeId(nodeId,energyType);
+        List<ModelNodeIndexInfor> nodeIndexInforList = modelNodeMapper.getModelNodeIndexIdByNodeId(nodeId, energyType);
 
 //        if (CollectionUtils.isEmpty(nodeIndexInforList)) {
 //            return consumptionAnalysisVO;
 //        }
-
+        //淇敼杩囨护缁熻鐐逛綅
+        nodeIndexInforList = nodeIndexInforList.stream().filter(x -> "STATISTIC".equals(x.getIndexType())).collect(Collectors.toList());
         final List<String> eneryIdList = nodeIndexInforList.stream().map(ModelNodeIndexInfor::getEnergyId).distinct().collect(Collectors.toList());
         final LambdaQueryWrapper<SysEnergy> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.in(CollectionUtils.isNotEmpty(eneryIdList),SysEnergy::getEnersno,eneryIdList);
+        queryWrapper.in(CollectionUtils.isNotEmpty(eneryIdList), SysEnergy::getEnersno, eneryIdList);
         final List<SysEnergy> sysEnergies = sysEnergyMapper.selectList(queryWrapper);
         final Map<String, BigDecimal> energyCoefficientMap = sysEnergies.stream().collect(Collectors.toMap(SysEnergy::getEnersno, SysEnergy::getCoefficient));
-        final Map<String, String> energyNameMap = sysEnergies.stream().collect(Collectors.toMap(SysEnergy::getEnersno,SysEnergy::getEnername));
+        final Map<String, String> energyNameMap = sysEnergies.stream().collect(Collectors.toMap(SysEnergy::getEnersno, SysEnergy::getEnername));
         final Map<String, String> indexIdEnergyIdMap = new HashMap<>();
-        nodeIndexInforList.forEach(n->{
+        nodeIndexInforList.forEach(n -> {
             final String indexId = n.getIndexId();
             final String energyId = n.getEnergyId();
-            if(!indexIdEnergyIdMap.containsKey(indexId)){
-                indexIdEnergyIdMap.put(indexId,energyId);
+            if (!indexIdEnergyIdMap.containsKey(indexId)) {
+                indexIdEnergyIdMap.put(indexId, energyId);
             }
         });
         List<String> indexIds = nodeIndexInforList.stream().map(ModelNodeIndexInfor::getIndexId).collect(Collectors.toList());
@@ -428,7 +428,7 @@
                 //鍚屾瘮鍒嗘瀽锛屾椂闂村彇鍘诲勾鐨�
                 lastTime = DateUtil.offsetMonth(beginTime, -12);
                 lastEndTime = DateUtil.offsetMonth(endTime, -12);
-            }else {
+            } else {
                 //鐜瘮鍒嗘瀽锛屾椂闂村彇 鏄ㄥぉ
                 lastTime = DateUtil.offsetDay(beginTime, -1);
                 lastEndTime = DateUtil.offsetDay(endTime, -1);
@@ -443,7 +443,7 @@
                 //鍚屾瘮鍒嗘瀽锛屾椂闂村彇鍘诲勾鐨�
                 lastTime = DateUtil.offsetMonth(beginTime, -12);
                 lastEndTime = DateUtil.offsetMonth(endTime, -12);
-            }else {
+            } else {
                 //鐜瘮鍒嗘瀽锛屾椂闂村彇 鏄ㄥぉ
                 lastTime = DateUtil.offsetMonth(beginTime, -1);
                 lastEndTime = DateUtil.offsetMonth(endTime, -1);
@@ -458,10 +458,10 @@
                 //鍚屾瘮鍒嗘瀽锛屾椂闂村彇鍘诲勾鐨�
                 lastTime = DateUtil.offsetMonth(beginTime, -12);
                 lastEndTime = DateUtil.offsetMonth(endTime, -12);
-            }else {
+            } else {
                 //鐜瘮鍒嗘瀽锛屾椂闂村彇 鏄ㄥぉ
-                lastTime = DateUtil.offsetMonth(beginTime,  -1);
-                lastEndTime = DateUtil.offsetMonth(endTime,  -1);
+                lastTime = DateUtil.offsetMonth(beginTime, -1);
+                lastEndTime = DateUtil.offsetMonth(endTime, -1);
             }
 
             timeFormat = "yyyy-MM";
@@ -469,7 +469,7 @@
         // 鏍规嵁indexId鏌ヨdataItem
         List<DataItem> dataItemList = new ArrayList<>();
         List<DataItem> lastDataItemList = new ArrayList<>();
-        if(CollectionUtils.isNotEmpty(indexIds)) {
+        if (CollectionUtils.isNotEmpty(indexIds)) {
             dataItemList = dataItemService.getDataItemTimeRangeInforByIndexIds(beginTime, endTime, shixuTimeType, indexIds);
             lastDataItemList = dataItemService.getDataItemTimeRangeInforByIndexIds(lastTime, lastEndTime, shixuTimeType, indexIds);
         }
@@ -478,7 +478,7 @@
         //  鍊嶇巼
         BigDecimal multiple = BigDecimal.valueOf(CommonConst.DIGIT_100);
 
-        Map<String,Double> energyProportionMap = new HashMap<>();
+        Map<String, Double> energyProportionMap = new HashMap<>();
         while (!beginTime.after(endTime)) {
             ConsumptionAnalysisData data = new ConsumptionAnalysisData();
             final String currentTime = DateUtil.format(beginTime, timeFormat);
@@ -489,7 +489,7 @@
                 if ("YOY".equals(analysisType)) {
                     //鍚屾瘮鍒嗘瀽锛屾椂闂村彇鍘诲勾鐨�
                     dateTime = DateUtil.offsetMonth(beginTime, -12);
-                }else {
+                } else {
                     //鐜瘮鍒嗘瀽锛屾椂闂村彇 鏄ㄥぉ
                     dateTime = DateUtil.offsetDay(beginTime, -1);
                 }
@@ -499,7 +499,7 @@
                 if ("YOY".equals(analysisType)) {
                     //鍚屾瘮鍒嗘瀽锛屾椂闂村彇鍘诲勾鐨�
                     dateTime = DateUtil.offsetMonth(beginTime, -12);
-                }else {
+                } else {
                     //鐜瘮鍒嗘瀽锛屾椂闂村彇 鏄ㄥぉ
                     dateTime = DateUtil.offsetMonth(beginTime, -1);
                 }
@@ -509,9 +509,9 @@
                 if ("YOY".equals(analysisType)) {
                     //鍚屾瘮鍒嗘瀽锛屾椂闂村彇鍘诲勾鐨�
                     dateTime = DateUtil.offsetMonth(beginTime, -12);
-                }else {
+                } else {
                     //鐜瘮鍒嗘瀽锛屾椂闂村彇 鏄ㄥぉ
-                    dateTime = DateUtil.offsetMonth(beginTime,  -1);
+                    dateTime = DateUtil.offsetMonth(beginTime, -1);
                 }
                 compareTime = DateUtil.format(dateTime, timeFormat);
             }
@@ -523,38 +523,40 @@
             BigDecimal lastSum = new BigDecimal(0);
             if (CollectionUtils.isNotEmpty(dataItems)) {
                 // 姹傚拰
-                for (int i=0;i<dataItems.size(); i++){
+                for (int i = 0; i < dataItems.size(); i++) {
                     final DataItem dataItem = dataItems.get(i);
                     final String indexId = dataItem.getIndexId();
                     final String energyId = indexIdEnergyIdMap.get(indexId);
-                    
+
                     final BigDecimal coefficient = energyCoefficientMap.get(energyId);
-                    if(coefficient == null){
+                    if (coefficient == null) {
                         throw new RuntimeException("鑳芥簮绫诲瀷" + energyId + "娌℃湁閰嶇疆鎶樻爣绯绘暟锛屾棤娉曡绠�");
                     }
-                    
-                    sum = sum.add(new BigDecimal(dataItem.getValue()).multiply(coefficient)).setScale(2, RoundingMode.HALF_UP);;
+
+                    sum = sum.add(new BigDecimal(dataItem.getValue()).multiply(coefficient)).setScale(2, RoundingMode.HALF_UP);
+                    ;
 //                    if(energyProportionMap.containsKey(energyId)) {
 //                        energyProportionMap.put(energyId,energyProportionMap.get(energyId) + sum.doubleValue());
 //                    }else {
 //                        energyProportionMap.put(energyId, sum.doubleValue());
 //                    }
                 }
-                
+
             }
 
-            if(CollectionUtils.isNotEmpty(lastDataItems)) {
-                for (int i=0;i<lastDataItems.size(); i++){
+            if (CollectionUtils.isNotEmpty(lastDataItems)) {
+                for (int i = 0; i < lastDataItems.size(); i++) {
                     final DataItem dataItem = lastDataItems.get(i);
                     final String indexId = dataItem.getIndexId();
                     final String energyId = indexIdEnergyIdMap.get(indexId);
 
                     final BigDecimal coefficient = energyCoefficientMap.get(energyId);
-                    if(coefficient == null){
+                    if (coefficient == null) {
                         throw new RuntimeException("鑳芥簮绫诲瀷" + energyId + "娌℃湁閰嶇疆鎶樻爣绯绘暟锛屾棤娉曡绠�");
                     }
 
-                    lastSum = lastSum.add(new BigDecimal(dataItem.getValue()).multiply(coefficient)).setScale(2, RoundingMode.HALF_UP);;
+                    lastSum = lastSum.add(new BigDecimal(dataItem.getValue()).multiply(coefficient)).setScale(2, RoundingMode.HALF_UP);
+                    ;
                 }
             }
             data.setCurrentValue(sum.doubleValue());
@@ -605,34 +607,34 @@
             chartDataList.add(chartData);
 
         });
-        
-        Double eneryTotal =  energyProportionMap.values().stream().mapToDouble(Double::doubleValue).sum();
+
+        Double eneryTotal = energyProportionMap.values().stream().mapToDouble(Double::doubleValue).sum();
 
         Map<String, List<DataItem>> indexDataItemMap = dataItemList.stream().collect(Collectors.groupingBy(DataItem::getIndexId));
-        
-        indexDataItemMap.forEach((indexId,value)->{
+
+        indexDataItemMap.forEach((indexId, value) -> {
             final String energyId = indexIdEnergyIdMap.get(indexId);
 
             final BigDecimal coefficient = energyCoefficientMap.get(energyId);
-            if(coefficient == null){
+            if (coefficient == null) {
                 throw new RuntimeException("鑳芥簮绫诲瀷" + energyId + "娌℃湁閰嶇疆鎶樻爣绯绘暟锛屾棤娉曡绠�");
             }
 
             final double sum = value.stream().map(DataItem::getValue).mapToDouble(Double::doubleValue).sum();
-            if(energyProportionMap.containsKey(energyId)) {
-                energyProportionMap.put(energyId,energyProportionMap.get(energyId) + sum * coefficient.doubleValue());
-            }else {
+            if (energyProportionMap.containsKey(energyId)) {
+                energyProportionMap.put(energyId, energyProportionMap.get(energyId) + sum * coefficient.doubleValue());
+            } else {
                 energyProportionMap.put(energyId, sum * coefficient.doubleValue());
             }
         });
-       
-        energyProportionMap.forEach((key,value)->{
+
+        energyProportionMap.forEach((key, value) -> {
             EnergyProportion energyProportion = new EnergyProportion();
             energyProportion.setEnergyNo(key);
-            energyProportion.setEnergyName(energyNameMap.getOrDefault(key,""));
+            energyProportion.setEnergyName(energyNameMap.getOrDefault(key, ""));
             energyProportion.setCount(value);
-            energyProportion.setPercentage(value/eneryTotal * 100);
-            
+            energyProportion.setPercentage(value / eneryTotal * 100);
+
             energyProportionList.add(energyProportion);
         });
 
@@ -660,50 +662,50 @@
         } else {
             timeFormat = "yyyy";
         }
-        
+
         final Double currTotalEnergy = getTotalEnergy(dto);
 
         DateTime tongbiTime = DateUtil.offsetMonth(queryTime, -12);
         dto.setDataTime(tongbiTime);
         final Double tongbiTotalEnergy = getTotalEnergy(dto);
-        
+
         DateTime huanbiTime = DateUtil.offsetMonth(queryTime, -1);
         dto.setDataTime(huanbiTime);
         final Double huanbiTotalEnergy = getTotalEnergy(dto);
 
-        
-        tongbi.setCurrentTime(DateUtil.format(queryTime,timeFormat));
-        tongbi.setCompareTime(DateUtil.format(tongbiTime,timeFormat));
+
+        tongbi.setCurrentTime(DateUtil.format(queryTime, timeFormat));
+        tongbi.setCompareTime(DateUtil.format(tongbiTime, timeFormat));
         tongbi.setCurrentValue(currTotalEnergy);
         tongbi.setCompareValue(tongbiTotalEnergy);
-        if(tongbiTotalEnergy != 0) {
+        if (tongbiTotalEnergy != 0) {
             final double tongbiRatio = (currTotalEnergy - tongbiTotalEnergy) / tongbiTotalEnergy * 100;
             BigDecimal bd = new BigDecimal(tongbiRatio);
             bd = bd.setScale(2, RoundingMode.HALF_UP);
             tongbi.setRatio(bd.doubleValue());
-        }else {
+        } else {
             tongbi.setRatio(0);
         }
-        
-        huanbi.setCurrentTime(DateUtil.format(queryTime,timeFormat));
-        huanbi.setCompareTime(DateUtil.format(huanbiTime,timeFormat));
+
+        huanbi.setCurrentTime(DateUtil.format(queryTime, timeFormat));
+        huanbi.setCompareTime(DateUtil.format(huanbiTime, timeFormat));
         huanbi.setCompareValue(huanbiTotalEnergy);
         huanbi.setCurrentValue(currTotalEnergy);
-     
-        if(huanbiTotalEnergy != 0) {
+
+        if (huanbiTotalEnergy != 0) {
             final double huanbiRatio = (currTotalEnergy - huanbiTotalEnergy) / huanbiTotalEnergy * 100;
             BigDecimal bd = new BigDecimal(huanbiRatio);
             bd = bd.setScale(2, RoundingMode.HALF_UP);
             huanbi.setRatio(bd.doubleValue());
-        }else {
+        } else {
             huanbi.setRatio(0);
         }
         consumptionAnalysisVO.setTongbi(tongbi);
         consumptionAnalysisVO.setHuanbi(huanbi);
         return consumptionAnalysisVO;
     }
-    
-    public Double getTotalEnergy(ConsumptionAnalysisDTO dto){
+
+    public Double getTotalEnergy(ConsumptionAnalysisDTO dto) {
         //todo hmj 缁煎悎鑳借�楀厛榛樿鍙栧悓姣�
         final String nodeId = dto.getNodeId();
         final String energyType = dto.getEnergyType();
@@ -712,23 +714,23 @@
         /**
          * 鏌ヨ鐐逛綅涓庣敤鑳藉崟鍏冧俊鎭�
          */
-        List<ModelNodeIndexInfor> nodeIndexInforList = modelNodeMapper.getModelNodeIndexIdByNodeId(nodeId,energyType);
+        List<ModelNodeIndexInfor> nodeIndexInforList = modelNodeMapper.getModelNodeIndexIdByNodeId(nodeId, energyType);
 
 //        if (CollectionUtils.isEmpty(nodeIndexInforList)) {
 //            return consumptionAnalysisVO;
 //        }
-
+        nodeIndexInforList = nodeIndexInforList.stream().filter(x -> "STATISTIC".equals(x.getIndexType())).collect(Collectors.toList());
         final List<String> eneryIdList = nodeIndexInforList.stream().map(ModelNodeIndexInfor::getEnergyId).distinct().collect(Collectors.toList());
         final LambdaQueryWrapper<SysEnergy> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.in(CollectionUtils.isNotEmpty(eneryIdList),SysEnergy::getEnersno,eneryIdList);
+        queryWrapper.in(CollectionUtils.isNotEmpty(eneryIdList), SysEnergy::getEnersno, eneryIdList);
         final List<SysEnergy> sysEnergies = sysEnergyMapper.selectList(queryWrapper);
         final Map<String, BigDecimal> energyCoefficientMap = sysEnergies.stream().collect(Collectors.toMap(SysEnergy::getEnersno, SysEnergy::getCoefficient));
         final Map<String, String> indexIdEnergyIdMap = new HashMap<>();
-        nodeIndexInforList.forEach(n->{
+        nodeIndexInforList.forEach(n -> {
             final String indexId = n.getIndexId();
             final String energyId = n.getEnergyId();
-            if(!indexIdEnergyIdMap.containsKey(indexId)){
-                indexIdEnergyIdMap.put(indexId,energyId);
+            if (!indexIdEnergyIdMap.containsKey(indexId)) {
+                indexIdEnergyIdMap.put(indexId, energyId);
             }
         });
         List<String> indexIds = nodeIndexInforList.stream().map(ModelNodeIndexInfor::getIndexId).collect(Collectors.toList());
@@ -757,12 +759,12 @@
         }
         // 鏍规嵁indexId鏌ヨdataItem
         List<DataItem> dataItemList = new ArrayList<>();
-        if(CollectionUtils.isNotEmpty(indexIds)) {
+        if (CollectionUtils.isNotEmpty(indexIds)) {
             dataItemList = dataItemService.getDataItemTimeRangeInforByIndexIds(beginTime, endTime, shixuTimeType, indexIds);
         }
         Map<String, List<DataItem>> dataItemMap = dataItemList.stream().collect(Collectors.groupingBy(li -> DateUtil.format(li.getDataTime(), timeFormat)));
 
-        Map<String,Double> energyProportionMap = new HashMap<>();
+        Map<String, Double> energyProportionMap = new HashMap<>();
         while (!beginTime.after(endTime)) {
             final String currentTime = DateUtil.format(beginTime, timeFormat);
 
@@ -770,17 +772,18 @@
             BigDecimal sum = new BigDecimal(0);
             if (CollectionUtils.isNotEmpty(dataItems)) {
                 // 姹傚拰
-                for (int i=0;i<dataItems.size(); i++){
+                for (int i = 0; i < dataItems.size(); i++) {
                     final DataItem dataItem = dataItems.get(i);
                     final String indexId = dataItem.getIndexId();
                     final String energyId = indexIdEnergyIdMap.get(indexId);
 
                     final BigDecimal coefficient = energyCoefficientMap.get(energyId);
-                    if(coefficient == null){
+                    if (coefficient == null) {
                         throw new RuntimeException("鑳芥簮绫诲瀷" + energyId + "娌℃湁閰嶇疆鎶樻爣绯绘暟锛屾棤娉曡绠�");
                     }
 
-                    sum = sum.add(new BigDecimal(dataItem.getValue()).multiply(coefficient)).setScale(2, RoundingMode.HALF_UP);;
+                    sum = sum.add(new BigDecimal(dataItem.getValue()).multiply(coefficient)).setScale(2, RoundingMode.HALF_UP);
+                    ;
 //                    if(energyProportionMap.containsKey(energyId)) {
 //                        energyProportionMap.put(energyId,energyProportionMap.get(energyId) + sum.doubleValue());
 //                    }else {
@@ -804,26 +807,24 @@
         }
 
 
-
-        
         Map<String, List<DataItem>> indexDataItemMap = dataItemList.stream().collect(Collectors.groupingBy(DataItem::getIndexId));
 
-        indexDataItemMap.forEach((indexId,value)->{
+        indexDataItemMap.forEach((indexId, value) -> {
             final String energyId = indexIdEnergyIdMap.get(indexId);
 
             final BigDecimal coefficient = energyCoefficientMap.get(energyId);
-            if(coefficient == null){
+            if (coefficient == null) {
                 throw new RuntimeException("鑳芥簮绫诲瀷" + energyId + "娌℃湁閰嶇疆鎶樻爣绯绘暟锛屾棤娉曡绠�");
             }
 
             final double sum = value.stream().map(DataItem::getValue).mapToDouble(Double::doubleValue).sum();
-            if(energyProportionMap.containsKey(energyId)) {
-                energyProportionMap.put(energyId,energyProportionMap.get(energyId) + sum * coefficient.doubleValue());
-            }else {
+            if (energyProportionMap.containsKey(energyId)) {
+                energyProportionMap.put(energyId, energyProportionMap.get(energyId) + sum * coefficient.doubleValue());
+            } else {
                 energyProportionMap.put(energyId, sum * coefficient.doubleValue());
             }
         });
-        Double eneryTotal =  energyProportionMap.values().stream().mapToDouble(Double::doubleValue).sum();
+        Double eneryTotal = energyProportionMap.values().stream().mapToDouble(Double::doubleValue).sum();
         return eneryTotal.doubleValue();
     }
 
@@ -839,11 +840,11 @@
          */
         List<ModelNodeIndexInfor> nodeIndexInforList = modelNodeMapper.getModelNodeByParentId(nodeId);
         final Map<String, String> nodeNameMap = new HashMap<>();
-        nodeIndexInforList.forEach(n->{
+        nodeIndexInforList.forEach(n -> {
             final String id = n.getNodeId();
             final String name = n.getName();
-            if(!nodeNameMap.containsKey(id)){
-                nodeNameMap.put(id,name);
+            if (!nodeNameMap.containsKey(id)) {
+                nodeNameMap.put(id, name);
             }
         });
         // 鎸夌収鐐逛綅杩涜鍒嗙粍
@@ -851,17 +852,17 @@
                 Collectors.groupingBy(ModelNodeIndexInfor::getNodeId));
         final List<String> eneryIdList = nodeIndexInforList.stream().map(ModelNodeIndexInfor::getEnergyId).distinct().collect(Collectors.toList());
         final LambdaQueryWrapper<SysEnergy> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.in(CollectionUtils.isNotEmpty(eneryIdList),SysEnergy::getEnersno,eneryIdList);
+        queryWrapper.in(CollectionUtils.isNotEmpty(eneryIdList), SysEnergy::getEnersno, eneryIdList);
         final List<SysEnergy> sysEnergies = sysEnergyMapper.selectList(queryWrapper);
         //鑳芥簮缂栧彿鍜岃兘婧愭姌鏍囩郴鏁�
         final Map<String, BigDecimal> energyCoefficientMap = sysEnergies.stream().collect(Collectors.toMap(SysEnergy::getEnersno, SysEnergy::getCoefficient));
         //index鍜岃兘婧�
         final Map<String, String> indexIdEnergyIdMap = new HashMap<>();
-        nodeIndexInforList.forEach(n->{
+        nodeIndexInforList.forEach(n -> {
             final String indexId = n.getIndexId();
             final String energyId = n.getEnergyId();
-            if(!indexIdEnergyIdMap.containsKey(indexId)){
-                indexIdEnergyIdMap.put(indexId,energyId);
+            if (!indexIdEnergyIdMap.containsKey(indexId)) {
+                indexIdEnergyIdMap.put(indexId, energyId);
             }
         });
         List<String> indexIds = nodeIndexInforList.stream().map(ModelNodeIndexInfor::getIndexId).collect(Collectors.toList());
@@ -886,22 +887,22 @@
         }
         // 鏍规嵁indexId鏌ヨdataItem
         List<DataItem> dataItemList = new ArrayList<>();
-        if(CollectionUtils.isNotEmpty(indexIds)) {
+        if (CollectionUtils.isNotEmpty(indexIds)) {
             dataItemList = dataItemService.getDataItemTimeRangeInforByIndexIds(beginTime, endTime, shixuTimeType, indexIds);
         }
         Map<String, List<DataItem>> dataItemMap = dataItemList.stream().collect(Collectors.groupingBy(DataItem::getIndexId));
 
-        Map<String,BigDecimal> resultMap = new HashMap<>();
+        Map<String, BigDecimal> resultMap = new HashMap<>();
         nodeIndexMap.forEach((key, value) -> {
             // 鎵惧嚭indexIds
             List<String> indexIdList = value.stream().map(ModelNodeIndexInfor::getIndexId).collect(Collectors.toList());
-            
-            indexIdList.forEach(indexId->{
+
+            indexIdList.forEach(indexId -> {
                 final List<DataItem> dataItems = dataItemMap.get(indexId);
                 final String energyId = indexIdEnergyIdMap.get(indexId);
                 final BigDecimal coefficient = energyCoefficientMap.get(energyId);
-                
-                if(CollectionUtils.isNotEmpty(dataItems) ){
+
+                if (CollectionUtils.isNotEmpty(dataItems)) {
                     BigDecimal sum = BigDecimal.valueOf(dataItems.stream()
                             .mapToDouble(DataItem::getValue).sum()).setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP).multiply(coefficient);
 
@@ -914,7 +915,7 @@
             });
         });
 
-        resultMap.forEach((key,value)->{
+        resultMap.forEach((key, value) -> {
             RankingEnergyData rankingEnergyData = new RankingEnergyData();
             rankingEnergyData.setNodeId(key);
             rankingEnergyData.setNodeName(nodeNameMap.get(key));
@@ -950,30 +951,30 @@
         }
 
         LambdaQueryWrapper<EnergyIndicators> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.eq(EnergyIndicators::getTimeType,queryTimeType);
-        queryWrapper.eq(EnergyIndicators::getDataTime,DateUtil.format(dto.getDataTime(),timeFormat));
-        queryWrapper.eq(EnergyIndicators::getNodeId,dto.getNodeId());
-        queryWrapper.eq(EnergyIndicators::getEnergyType,dto.getEnergyType());
+        queryWrapper.eq(EnergyIndicators::getTimeType, queryTimeType);
+        queryWrapper.eq(EnergyIndicators::getDataTime, DateUtil.format(dto.getDataTime(), timeFormat));
+        queryWrapper.eq(EnergyIndicators::getNodeId, dto.getNodeId());
+        queryWrapper.eq(EnergyIndicators::getEnergyType, dto.getEnergyType());
         // 0 鏄鍒掗噺
-        queryWrapper.eq(EnergyIndicators::getIndicatorsType,"0");
+        queryWrapper.eq(EnergyIndicators::getIndicatorsType, "0");
         final EnergyIndicators plan = energyIndicatorsMapper.selectOne(queryWrapper);
-        if(null != plan && null!= plan.getNumber()) {
+        if (null != plan && null != plan.getNumber()) {
             consumptionAnalysisVO.setPlanCount(plan.getNumber().divide(new BigDecimal(between), CommonConst.DIGIT_2, RoundingMode.HALF_UP).doubleValue());
-        }else {
+        } else {
             consumptionAnalysisVO.setPlanCount(0D);
         }
         queryWrapper.clear();
 
 
-        queryWrapper.eq(EnergyIndicators::getTimeType,queryTimeType);
-        queryWrapper.eq(EnergyIndicators::getDataTime,DateUtil.format(dto.getDataTime(),timeFormat));
-        queryWrapper.eq(EnergyIndicators::getNodeId,dto.getNodeId());
-        queryWrapper.eq(EnergyIndicators::getEnergyType,dto.getEnergyType());
-        queryWrapper.eq(EnergyIndicators::getIndicatorsType,"1");
+        queryWrapper.eq(EnergyIndicators::getTimeType, queryTimeType);
+        queryWrapper.eq(EnergyIndicators::getDataTime, DateUtil.format(dto.getDataTime(), timeFormat));
+        queryWrapper.eq(EnergyIndicators::getNodeId, dto.getNodeId());
+        queryWrapper.eq(EnergyIndicators::getEnergyType, dto.getEnergyType());
+        queryWrapper.eq(EnergyIndicators::getIndicatorsType, "1");
         final EnergyIndicators prod = energyIndicatorsMapper.selectOne(queryWrapper);
-        if(null != prod && null!= prod.getNumber()) {
+        if (null != prod && null != prod.getNumber()) {
             consumptionAnalysisVO.setPlanCount(prod.getNumber().divide(new BigDecimal(between), CommonConst.DIGIT_2, RoundingMode.HALF_UP).doubleValue());
-        }else {
+        } else {
             consumptionAnalysisVO.setProdCount(0D);
         }
         return consumptionAnalysisVO;
@@ -993,19 +994,19 @@
         /**
          * 鏌ヨ鐐逛綅涓庣敤鑳藉崟鍏冧俊鎭�
          */
-        List<ModelNodeIndexInfor> nodeIndexInforList = modelNodeMapper.getModelNodeIndexIdByNodeId(nodeId,energyType);
+        List<ModelNodeIndexInfor> nodeIndexInforList = modelNodeMapper.getModelNodeIndexIdByNodeId(nodeId, energyType);
 
         final List<String> eneryIdList = nodeIndexInforList.stream().map(ModelNodeIndexInfor::getEnergyId).distinct().collect(Collectors.toList());
         final LambdaQueryWrapper<SysEnergy> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.in(CollectionUtils.isNotEmpty(eneryIdList),SysEnergy::getEnersno,eneryIdList);
+        queryWrapper.in(CollectionUtils.isNotEmpty(eneryIdList), SysEnergy::getEnersno, eneryIdList);
         final List<SysEnergy> sysEnergies = sysEnergyMapper.selectList(queryWrapper);
         final Map<String, BigDecimal> energyCoefficientMap = sysEnergies.stream().collect(Collectors.toMap(SysEnergy::getEnersno, SysEnergy::getCoefficient));
         final Map<String, String> indexIdEnergyIdMap = new HashMap<>();
-        nodeIndexInforList.forEach(n->{
+        nodeIndexInforList.forEach(n -> {
             final String indexId = n.getIndexId();
             final String energyId = n.getEnergyId();
-            if(!indexIdEnergyIdMap.containsKey(indexId)){
-                indexIdEnergyIdMap.put(indexId,energyId);
+            if (!indexIdEnergyIdMap.containsKey(indexId)) {
+                indexIdEnergyIdMap.put(indexId, energyId);
             }
         });
         List<String> indexIds = nodeIndexInforList.stream().map(ModelNodeIndexInfor::getIndexId).collect(Collectors.toList());
@@ -1032,12 +1033,11 @@
             shixuTimeType = TimeType.MONTH.name();
             timeFormat = "yyyy-MM";
         }
-        
-        
+
 
         // 鏍规嵁indexId鏌ヨdataItem
         List<DataItem> dataItemList = new ArrayList<>();
-        if(CollectionUtils.isNotEmpty(indexIds)) {
+        if (CollectionUtils.isNotEmpty(indexIds)) {
             dataItemList = dataItemService.getDataItemTimeRangeInforByIndexIds(beginTime, endTime, shixuTimeType, indexIds);
         }
         Map<String, List<DataItem>> dataItemMap = dataItemList.stream().collect(Collectors.groupingBy(li -> DateUtil.format(li.getDataTime(), timeFormat)));
@@ -1045,12 +1045,12 @@
         while (!beginTime.after(endTime)) {
             //鏌ヨ寮�濮嬫椂闂村拰缁撴潫鏃堕棿涔嬮棿鐨勪骇閲�
             LambdaQueryWrapper<ProductOutput> indicatorsWrapper = new LambdaQueryWrapper<>();
-            indicatorsWrapper.eq(ProductOutput::getTimeType,shixuTimeType);
-            indicatorsWrapper.eq(ProductOutput::getNodeId,dto.getNodeId());
-            indicatorsWrapper.eq(ProductOutput::getDataTime,DateUtil.format(beginTime,timeFormat));
+            indicatorsWrapper.eq(ProductOutput::getTimeType, shixuTimeType);
+            indicatorsWrapper.eq(ProductOutput::getNodeId, dto.getNodeId());
+            indicatorsWrapper.eq(ProductOutput::getDataTime, DateUtil.format(beginTime, timeFormat));
             List<ProductOutput> energyIndicators = productOutputMapper.selectList(indicatorsWrapper);
-            prodCountMap.put(DateUtil.format(beginTime,timeFormat),energyIndicators);
-            
+            prodCountMap.put(DateUtil.format(beginTime, timeFormat), energyIndicators);
+
             ConsumptionAnalysisData data = new ConsumptionAnalysisData();
             final String currentTime = DateUtil.format(beginTime, timeFormat);
 
@@ -1058,17 +1058,18 @@
             BigDecimal sum = new BigDecimal(0);
             if (CollectionUtils.isNotEmpty(dataItems)) {
                 // 姹傚拰
-                for (int i=0;i<dataItems.size(); i++){
+                for (int i = 0; i < dataItems.size(); i++) {
                     final DataItem dataItem = dataItems.get(i);
                     final String indexId = dataItem.getIndexId();
                     final String energyId = indexIdEnergyIdMap.get(indexId);
 
                     final BigDecimal coefficient = energyCoefficientMap.get(energyId);
-                    if(coefficient == null){
+                    if (coefficient == null) {
                         throw new RuntimeException("鑳芥簮绫诲瀷" + energyId + "娌℃湁閰嶇疆鎶樻爣绯绘暟锛屾棤娉曡绠�");
                     }
 
-                    sum = sum.add(new BigDecimal(dataItem.getValue()).multiply(coefficient)).setScale(2, RoundingMode.HALF_UP);;
+                    sum = sum.add(new BigDecimal(dataItem.getValue()).multiply(coefficient)).setScale(2, RoundingMode.HALF_UP);
+                    ;
                 }
 
             }
@@ -1090,18 +1091,18 @@
                     break;
             }
         }
-        dataList.forEach(d->{
+        dataList.forEach(d -> {
             ProductEnergyAnalysisData productEnergyAnalysisData = new ProductEnergyAnalysisData();
             final String currentTime = d.getCurrentTime();
-            
+
             productEnergyAnalysisData.setDateTime(currentTime);
-            
+
             final List<ProductOutput> productOutputs = prodCountMap.get(currentTime);
-            if(StringUtils.isEmpty(dto.getProdType())){
+            if (StringUtils.isEmpty(dto.getProdType())) {
                 productEnergyAnalysisData.setEnergyCount(format2Double(d.getCurrentValue()));
                 final double sum = productOutputs.stream().map(ProductOutput::getNumber).mapToDouble(BigDecimal::doubleValue).sum();
                 productEnergyAnalysisData.setProductCount(format2Double(sum));
-                if(sum != 0) {
+                if (sum != 0) {
                     final double averageEnergy = productEnergyAnalysisData.getEnergyCount() / productEnergyAnalysisData.getProductCount();
                     // 鍒涘缓DecimalFormat瀵硅薄锛岃缃繚鐣欎袱浣嶅皬鏁�
                     DecimalFormat df = new DecimalFormat("#.00");
@@ -1109,15 +1110,15 @@
                     // 鏍煎紡鍖栫粨鏋�
                     String formattedResult = df.format(averageEnergy);
                     productEnergyAnalysisData.setAverage(Double.valueOf(formattedResult));
-                }else {
+                } else {
                     productEnergyAnalysisData.setAverage(0);
                 }
-            }else {
-                if(CollectionUtils.isNotEmpty(productOutputs)) {
+            } else {
+                if (CollectionUtils.isNotEmpty(productOutputs)) {
                     final Map<String, List<ProductOutput>> productTypeMap = productOutputs.stream().collect(Collectors.groupingBy(ProductOutput::getProductType));
                     final double sum = productOutputs.stream().map(ProductOutput::getNumber).mapToDouble(BigDecimal::doubleValue).sum();
                     final List<ProductOutput> outputList = productTypeMap.get(dto.getProdType());
-                    if(CollectionUtils.isNotEmpty(outputList)) {
+                    if (CollectionUtils.isNotEmpty(outputList)) {
                         final double enengyProd = outputList.stream().map(ProductOutput::getNumber).mapToDouble(BigDecimal::doubleValue).sum();
                         productEnergyAnalysisData.setProductCount(format2Double(enengyProd));
                         productEnergyAnalysisData.setEnergyCount(format2Double(d.getCurrentValue() * enengyProd / sum));
@@ -1128,19 +1129,19 @@
                         } else {
                             productEnergyAnalysisData.setAverage(0);
                         }
-                    }else {
+                    } else {
                         productEnergyAnalysisData.setProductCount(0);
                         productEnergyAnalysisData.setEnergyCount(d.getCurrentValue());
                         productEnergyAnalysisData.setAverage(0);
                     }
-                }else {
+                } else {
                     productEnergyAnalysisData.setProductCount(0);
                     productEnergyAnalysisData.setEnergyCount(d.getCurrentValue());
                     productEnergyAnalysisData.setAverage(0);
                 }
             }
-            
-           
+
+
             chart.add(productEnergyAnalysisData);
         });
 
@@ -1149,9 +1150,9 @@
         final double totalProd = chart.stream().map(ProductEnergyAnalysisData::getProductCount).mapToDouble(Double::doubleValue).sum();
         productEnergyAnalysisVO.setTotalEnergy(format2Double(totalEnergy));
         productEnergyAnalysisVO.setTotalProduct(format2Double(totalProd));
-        if(totalProd != 0) {
+        if (totalProd != 0) {
             productEnergyAnalysisVO.setAverageEnergy(format2Double(totalEnergy / totalProd));
-        }else {
+        } else {
             productEnergyAnalysisVO.setAverageEnergy(0D);
         }
         return productEnergyAnalysisVO;
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 d33b810..2f6d9ab 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
@@ -110,4 +110,16 @@
      */
     List<CarbonEmission> getDownCarbonEmission(@Param("beginTime") Date beginTime, @Param("endTime") Date endTime,
                                              @Param("timeType") String timeType, @Param("indexId") String indexId);
+
+    /**
+     * 鏍规嵁indexId涓庢椂闂磋寖鍥存煡璇㈠皬鏃剁殑dataitem淇℃伅
+     *
+     * @param beginTime 寮�濮嬫椂闂�
+     * @param endTime   鎴鏃堕棿
+     * @param timeType  鏃堕棿绫诲瀷
+     * @param indexIds  鐐逛綅闆嗗悎
+     * @return
+     */
+    List<DataItem> getDataItemHourInforByIndexIds(@Param("beginTime") Date beginTime, @Param("endTime") Date endTime,
+                                                  @Param("timeType") String timeType, @Param("indexIds") List<String> indexIds);
 }
diff --git a/zhitan-system/src/main/java/com/zhitan/dataitem/service/IDataItemService.java b/zhitan-system/src/main/java/com/zhitan/dataitem/service/IDataItemService.java
index 6266f72..993beb7 100644
--- a/zhitan-system/src/main/java/com/zhitan/dataitem/service/IDataItemService.java
+++ b/zhitan-system/src/main/java/com/zhitan/dataitem/service/IDataItemService.java
@@ -77,4 +77,15 @@
      * @return
      */
     BigDecimal getDataItemValueByIndexIds(String timeCode, List<String> indexIds);
+
+    /**
+     * 鏍规嵁indexId涓庢椂闂磋寖鍥存煡璇㈠皬鏃剁殑dataitem淇℃伅
+     *
+     * @param beginTime 寮�濮嬫椂闂�
+     * @param endTime   鎴鏃堕棿
+     * @param timeType  鏃堕棿绫诲瀷
+     * @param indexIds  鐐逛綅闆嗗悎
+     * @return
+     */
+    List<DataItem> getDataItemHourInforByIndexIds(Date beginTime, Date endTime, String timeType, List<String> indexIds);
 }
diff --git a/zhitan-system/src/main/java/com/zhitan/dataitem/service/impl/DataItemServiceImpl.java b/zhitan-system/src/main/java/com/zhitan/dataitem/service/impl/DataItemServiceImpl.java
index 0b82a1d..1e29b7f 100644
--- a/zhitan-system/src/main/java/com/zhitan/dataitem/service/impl/DataItemServiceImpl.java
+++ b/zhitan-system/src/main/java/com/zhitan/dataitem/service/impl/DataItemServiceImpl.java
@@ -103,4 +103,18 @@
     public BigDecimal getDataItemValueByIndexIds(String timeCode, List<String> indexIds) {
         return dataItemMapper.getDataItemValueByIndexIds(timeCode, indexIds);
     }
+
+    /**
+     * 鏍规嵁indexId涓庢椂闂磋寖鍥存煡璇㈠皬鏃剁殑dataitem淇℃伅
+     *
+     * @param beginTime 寮�濮嬫椂闂�
+     * @param endTime   鎴鏃堕棿
+     * @param timeType  鏃堕棿绫诲瀷
+     * @param indexIds  鐐逛綅闆嗗悎
+     * @return
+     */
+    @Override
+    public List<DataItem> getDataItemHourInforByIndexIds(Date beginTime, Date endTime, String timeType, List<String> indexIds) {
+        return dataItemMapper.getDataItemHourInforByIndexIds(beginTime, endTime, timeType, indexIds);
+    }
 }
diff --git a/zhitan-system/src/main/java/com/zhitan/energyMonitor/domain/EnergyUnitToDevice.java b/zhitan-system/src/main/java/com/zhitan/energyMonitor/domain/EnergyUnitToDevice.java
new file mode 100644
index 0000000..bf35d02
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/energyMonitor/domain/EnergyUnitToDevice.java
@@ -0,0 +1,71 @@
+package com.zhitan.energyMonitor.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.zhitan.common.annotation.Excel;
+import com.zhitan.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.math.BigDecimal;
+
+/**
+ * @Description: 鐢ㄨ兘鍗曞厓鍏宠仈鐨勫钩鍙版ā鏉夸腑浠〃鐨勭晫闈㈤�昏緫鍏崇郴 涓嶅惈鏈� 閲囬泦銆佽绠椾俊鎭�
+ * @Author: jeecg-boot
+ * @Date:   2022-01-26
+ * @Version: V1.0
+ */
+@Data
+@TableName("energy_unit_to_device")
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value="energy_unit_to_device瀵硅薄", description="鐢ㄨ兘鍗曞厓鍏宠仈鐨勫钩鍙版ā鏉夸腑浠〃鐨勭晫闈㈤�昏緫鍏崇郴 涓嶅惈鏈� 閲囬泦銆佽绠椾俊鎭�")
+public class EnergyUnitToDevice extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "鏂颁富閿�")
+    @TableId(type = IdType.ASSIGN_ID)
+    private String newId;
+
+	/**涓婚敭*/
+    @ApiModelProperty(value = "涓婚敭")
+    private String id;
+
+	/**鍏宠仈浠〃鍚嶇О*/
+	@Excel(name = "鍏宠仈浠〃鍚嶇О", width = 15)
+    @ApiModelProperty(value = "鍏宠仈浠〃鍚嶇О")
+    private String name;
+
+	/**鍏宠仈浠〃缂栫爜*/
+	@Excel(name = "鍏宠仈浠〃缂栫爜", width = 15)
+    @ApiModelProperty(value = "鍏宠仈浠〃缂栫爜")
+    private String code;
+
+	/**鑳芥簮绫诲瀷锛堟按琛ㄣ�佺數琛ㄣ�佹皵琛ㄧ瓑锛�*/
+	@Excel(name = "鑳芥簮绫诲瀷锛堟按琛ㄣ�佺數琛ㄣ�佹皵琛ㄧ瓑锛�", width = 15)
+    @ApiModelProperty(value = "鑳芥簮绫诲瀷锛堟按琛ㄣ�佺數琛ㄣ�佹皵琛ㄧ瓑锛�")
+    private String deviceType;
+
+	/**鐢ㄨ兘鍗曞厓涓婚敭*/
+	@Excel(name = "鐢ㄨ兘鍗曞厓涓婚敭", width = 15)
+    @ApiModelProperty(value = "鐢ㄨ兘鍗曞厓涓婚敭")
+    private String energyUnitId;
+
+	/**绉熸埛涓婚敭*/
+	@Excel(name = "绉熸埛涓婚敭", width = 15)
+    @ApiModelProperty(value = "绉熸埛涓婚敭")
+    private Integer tenantId;
+
+    @ApiModelProperty(value = "鍙備笌璁¢噺")
+    private String partMeasurement;
+
+    @ApiModelProperty(value = "瀹夎浣嶇疆")
+    private String installPosition;
+
+    @ApiModelProperty(value = "鍒嗘憡姣斾緥")
+    private BigDecimal shareRatio;
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/energyMonitor/domain/vo/EnergyCalculateCalcTV.java b/zhitan-system/src/main/java/com/zhitan/energyMonitor/domain/vo/EnergyCalculateCalcTV.java
new file mode 100644
index 0000000..0c46301
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/energyMonitor/domain/vo/EnergyCalculateCalcTV.java
@@ -0,0 +1,31 @@
+package com.zhitan.energyMonitor.domain.vo;
+
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 璁$畻鐐逛綅瀵瑰簲鐨勮绠楀叕寮�
+ * @author  zhw
+ */
+@Data
+@ApiModel(value="璁$畻鐐逛綅瀵瑰簲鐨勮绠楀叕寮�", description="璁$畻鐐逛綅瀵瑰簲鐨勮绠楀叕寮�")
+public class EnergyCalculateCalcTV {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "璁$畻鐐逛綅涓婚敭")
+    private String  calculateIndexId;
+
+    @ApiModelProperty(value = "浠〃璁惧涓婚敭")
+    private String deviceId;
+
+    @ApiModelProperty(value = "浠〃鍚嶇О")
+    private String name;
+
+    @ApiModelProperty(value = "璁$畻鐐逛綅鍖呭惈鐨勯噰闆嗙偣浣嶄富閿�")
+    private String collectIndexId;
+
+    @ApiModelProperty(value = "閲囬泦鐐逛綅瀵瑰簲鎿嶄綔绗﹀彿")
+    private String operator;
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/energyMonitor/domain/vo/ListElectricityMeterVO.java b/zhitan-system/src/main/java/com/zhitan/energyMonitor/domain/vo/ListElectricityMeterVO.java
new file mode 100644
index 0000000..36c19ed
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/energyMonitor/domain/vo/ListElectricityMeterVO.java
@@ -0,0 +1,20 @@
+package com.zhitan.energyMonitor.domain.vo;
+
+import lombok.Data;
+
+/**
+ * @Description: TODO
+ * @author: yxw
+ * @date: 2022骞�04鏈�24鏃� 16:07
+ */
+@Data
+public class ListElectricityMeterVO {
+    /**
+     * 鐢佃〃鍚嶇О
+     */
+    private String label;
+    /**
+     * 鐢佃〃id
+     */
+    private String code;
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/energyMonitor/domain/vo/UnitToDeviceRelationVO.java b/zhitan-system/src/main/java/com/zhitan/energyMonitor/domain/vo/UnitToDeviceRelationVO.java
new file mode 100644
index 0000000..6be45ff
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/energyMonitor/domain/vo/UnitToDeviceRelationVO.java
@@ -0,0 +1,35 @@
+package com.zhitan.energyMonitor.domain.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+
+/**
+ * 鐢ㄨ兘鍗曞厓涓庤閲忓櫒鍏峰叧绯籿o
+ *
+ * @Author: Zhujw
+ * @Date: 2023/4/4
+ */
+@Data
+@ApiModel(value = "鐢ㄨ兘鍗曞厓涓庤閲忓櫒鍏峰叧绯籿o-杩斿洖vo", description = "鐢ㄨ兘鍗曞厓涓庤閲忓櫒鍏峰叧绯籿o-杩斿洖vo")
+public class UnitToDeviceRelationVO {
+
+    /**
+     * 鐢ㄨ兘鍗曞厓id
+     */
+    @ApiModelProperty(value = "鐢ㄨ兘鍗曞厓id")
+    private String unitId;
+
+    /**
+     * 璁¢噺鍣ㄥ叿id
+     */
+    @ApiModelProperty(value = "璁¢噺鍣ㄥ叿id")
+    private String deviceId;
+
+    /**
+     * 璁¢噺鍣ㄥ叿鍚嶇О
+     */
+    @ApiModelProperty(value = "璁¢噺鍣ㄥ叿鍚嶇О")
+    private String deviceName;
+}
\ No newline at end of file
diff --git a/zhitan-system/src/main/java/com/zhitan/energyMonitor/mapper/EnergyUnitToDeviceMapper.java b/zhitan-system/src/main/java/com/zhitan/energyMonitor/mapper/EnergyUnitToDeviceMapper.java
new file mode 100644
index 0000000..32edd1e
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/energyMonitor/mapper/EnergyUnitToDeviceMapper.java
@@ -0,0 +1,38 @@
+package com.zhitan.energyMonitor.mapper;
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhitan.energyMonitor.domain.EnergyUnitToDevice;
+import com.zhitan.energyMonitor.domain.vo.EnergyCalculateCalcTV;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * @Description: 鐢ㄨ兘鍗曞厓鍏宠仈鐨勫钩鍙版ā鏉夸腑浠〃鐨勭晫闈㈤�昏緫鍏崇郴 涓嶅惈鏈� 閲囬泦銆佽绠椾俊鎭�
+ * @Author: jeecg-boot
+ * @Date: 2022-01-26
+ * @Version: V1.0
+ */
+public interface EnergyUnitToDeviceMapper extends BaseMapper<EnergyUnitToDevice> {
+
+    /**
+     * 鏍规嵁璁$畻鐐逛綅涓婚敭鍜岀敤鑳藉崟鍏冧富閿� 鏌ヨ 浣跨敤鐨� 閲囬泦鐐瑰強浠〃淇℃伅
+     *
+     * @param calculateIndexId
+     * @param energyUnitId
+     * @return
+     */
+    public List<EnergyCalculateCalcTV> getCalculateDevices(@Param("calculateIndexId") String calculateIndexId,
+                                                           @Param("energyUnitId") String energyUnitId,
+                                                           @Param("tenantId") String tenantId);
+
+    /**
+     * 涓-鏍规嵁绉熸埛id闆嗗悎鏌ヨ璁¢噺鍣ㄥ叿id
+     *
+     * @param unitIds
+     * @return
+     */
+    @InterceptorIgnore(tenantLine = "true")
+    List<String> listDeviceByTenantIds(@Param("unitIds") List<String> unitIds);
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/energyMonitor/service/IEnergyUnitToDeviceService.java b/zhitan-system/src/main/java/com/zhitan/energyMonitor/service/IEnergyUnitToDeviceService.java
new file mode 100644
index 0000000..30bb563
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/energyMonitor/service/IEnergyUnitToDeviceService.java
@@ -0,0 +1,100 @@
+package com.zhitan.energyMonitor.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhitan.energyMonitor.domain.EnergyUnitToDevice;
+import com.zhitan.energyMonitor.domain.vo.ListElectricityMeterVO;
+import com.zhitan.energyMonitor.domain.vo.UnitToDeviceRelationVO;
+
+import java.util.List;
+
+/**
+ * @Description: 鐢ㄨ兘鍗曞厓鍏宠仈鐨勫钩鍙版ā鏉夸腑浠〃鐨勭晫闈㈤�昏緫鍏崇郴 涓嶅惈鏈� 閲囬泦銆佽绠椾俊鎭�
+ * @Author: jeecg-boot
+ * @Date:   2022-01-26
+ * @Version: V1.0
+ */
+public interface IEnergyUnitToDeviceService extends IService<EnergyUnitToDevice> {
+
+    /**
+     * 鏍规嵁鐢ㄨ兘鍗曞厓ID鑾峰彇绉熸埛涓嬫湁鏁堢殑浠〃闆嗗悎
+     * @param unitId
+     * @return
+     */
+    List<EnergyUnitToDevice> queryTenantUnitDeviceByUnitId(String unitId);
+
+    /**
+     * 鏍规嵁鐢ㄨ兘鍗曞厓ID鑾峰彇绉熸埛涓嬫墍鏈夋湁鏁堢殑瀹炰綋琛ㄩ泦鍚�
+     * @param unitId
+     * @return
+     */
+    List<EnergyUnitToDevice> queryTenantEntityMeterByUnitId(String unitId);
+
+    /**
+     * 鏍规嵁鐢ㄨ兘鍗曞厓id鑾峰彇绉熸埛涓嬫湁鏁堢殑浠〃id闆嗗悎
+     *
+     * @param unitId 鐢ㄨ兘鍗曞厓id
+     * @return 浠〃id闆嗗悎
+     */
+    List<String> getEnergyUnitDeviceIdByUnitId(String unitId);
+
+    /**
+     * 鏍规嵁鐢ㄨ兘鍗曞厓id闆嗗悎鑾峰彇绉熸埛涓嬫湁鏁堢殑浠〃id闆嗗悎
+     *
+     * @param unitIds 鐢ㄨ兘鍗曞厓id
+     */
+    List<String> getEnergyUnitDeviceIdByUnitIds(List<String> unitIds);
+
+    /**
+     * 鏍规嵁鐢ㄨ兘鍗曞厓id闆嗗悎+鑳芥簮绫诲瀷鑾峰彇绉熸埛涓嬫湁鏁堢殑浠〃id闆嗗悎
+     *
+     * @param unitIds    鐢ㄨ兘鍗曞厓id闆嗗悎
+     * @return
+     */
+    List<String> getDeviceIdByUnitIds(List<String> unitIds);
+
+    /**
+     * 鏇存柊鑳藉崟鍏僫d鑾峰彇绉熸埛涓嬫湁鏁堢殑浠〃id闆嗗悎
+     *
+     * @param unitId 鐢ㄨ兘鍗曞厓id
+     * @return 浠〃id闆嗗悎
+     */
+    List<String> updateEnergyUnitDeviceIdByUnitId(String unitId);
+
+    /**
+     * 鍒犻櫎鑳藉崟鍏僫d鑾峰彇绉熸埛涓嬫湁鏁堢殑浠〃id闆嗗悎
+     * @param unitId    鐢ㄨ兘鍗曞厓id
+     * @return  浠〃id闆嗗悎
+     */
+    void deleteEnergyUnitDeviceIdByUnitId(String unitId);
+
+    /**
+     * 鏍规嵁鐢ㄨ兘鍗曞厓ID鑾峰彇绉熸埛涓嬫湁鏁堢殑鐢佃〃闆嗗悎
+     * @param unitId
+     * @return
+     */
+    List<ListElectricityMeterVO> listElectricityMeter(String unitId);
+
+    /**
+     * 鑾峰彇绉熸埛涓嬫湁鏁堢殑琛ㄩ泦鍚�
+     * @return
+     */
+    List<EnergyUnitToDevice> listAllMeter();
+
+    /**
+     * 鏍规嵁璁¢噺鍣ㄥ叿id鍜岀敤鑳藉崟鍏僫d鏌ヨ琛ㄥ叧绯�
+     *
+     * @param unitId 鐢ㄨ兘鍗曞厓id
+     * @param id     id
+     * @return EnergyUnitToDevice瀹炰綋
+     */
+    EnergyUnitToDevice getEnergyUnitToDeviceById(String unitId, String id);
+
+    /**
+     * 鏍规嵁璁¢噺鍣ㄥ叿id闆嗗悎鏌ヨ涓庣敤鑳界殑鍏崇郴
+     *
+     * @param unitIds
+     * @return
+     */
+    List<UnitToDeviceRelationVO> listDeviceByUnitIds(List<String> unitIds);
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/energyMonitor/service/impl/EnergyUnitToDeviceServiceImpl.java b/zhitan-system/src/main/java/com/zhitan/energyMonitor/service/impl/EnergyUnitToDeviceServiceImpl.java
new file mode 100644
index 0000000..5df3d47
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/energyMonitor/service/impl/EnergyUnitToDeviceServiceImpl.java
@@ -0,0 +1,232 @@
+package com.zhitan.energyMonitor.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhitan.common.constant.CommonConst;
+import com.zhitan.energyMonitor.domain.EnergyUnitToDevice;
+import com.zhitan.energyMonitor.domain.vo.ListElectricityMeterVO;
+import com.zhitan.energyMonitor.domain.vo.UnitToDeviceRelationVO;
+import com.zhitan.energyMonitor.mapper.EnergyUnitToDeviceMapper;
+import com.zhitan.energyMonitor.service.IEnergyUnitToDeviceService;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @Description: 鐢ㄨ兘鍗曞厓鍏宠仈鐨勫钩鍙版ā鏉夸腑浠〃鐨勭晫闈㈤�昏緫鍏崇郴 涓嶅惈鏈� 閲囬泦銆佽绠椾俊鎭�
+ * @Author: jeecg-boot
+ * @Date: 2022-01-26
+ * @Version: V1.0
+ */
+@Service
+public class EnergyUnitToDeviceServiceImpl extends ServiceImpl<EnergyUnitToDeviceMapper, EnergyUnitToDevice>
+        implements IEnergyUnitToDeviceService {
+
+
+//    @Autowired
+//    private IMeasuringInstrumentsService meterService;
+
+
+    /**
+     * 鏍规嵁鐢ㄨ兘鍗曞厓id鑾峰彇绉熸埛涓嬬殑鍏朵笅鐨勪华琛ㄥ垪琛�
+     *
+     * @param unitId
+     * @return
+     */
+    @Override
+    public List<EnergyUnitToDevice> queryTenantUnitDeviceByUnitId(String unitId) {
+
+        QueryWrapper<EnergyUnitToDevice> queryWrapper = new QueryWrapper<EnergyUnitToDevice>();
+//                .eq(TableColumnConst.TABLE_COLUMN_ENERGY_UNIT_ID, unitId);
+        return baseMapper.selectList(queryWrapper);
+    }
+
+    /**
+     * 鏍规嵁鐢ㄨ兘鍗曞厓ID鑾峰彇绉熸埛涓嬫墍鏈夋湁鏁堢殑瀹炰綋琛ㄩ泦鍚�
+     *
+     * @param unitId
+     * @return
+     */
+    @Override
+    public List<EnergyUnitToDevice> queryTenantEntityMeterByUnitId(String unitId) {
+
+        List<EnergyUnitToDevice> unitToDeviceList = baseMapper.selectList(Wrappers.<EnergyUnitToDevice>lambdaQuery()
+                .eq(EnergyUnitToDevice::getEnergyUnitId, unitId)
+        );
+//        if (CollectionUtils.isNotEmpty(unitToDeviceList)) {
+//            List<String> meterIds = unitToDeviceList.stream().map(EnergyUnitToDevice::getId).collect(Collectors.toList());
+//            // 杩囨护鍑哄疄浣撹〃
+//            Integer applianceType = EquipmentInformationEnum.MEASURING_INSTRUMENT_TYPE.ENTITY.getValue();
+//            List<Meter> meterList = meterService.list(Wrappers.<Meter>lambdaQuery()
+//                    .select(Meter::getId).in(Meter::getId, meterIds)
+//                    .eq(Meter::getApplianceType, applianceType)
+//            );
+//            List<String> newMeterIds = meterList.stream().map(Meter::getId).collect(Collectors.toList());
+//            unitToDeviceList = unitToDeviceList.stream().filter(li -> newMeterIds.contains(li.getId())).collect(Collectors.toList());
+//        }
+        return unitToDeviceList;
+    }
+
+    /**
+     * 鏍规嵁鐢ㄨ兘鍗曞厓id鑾峰彇绉熸埛涓嬫湁鏁堢殑浠〃id闆嗗悎
+     *
+     * @param unitId 鐢ㄨ兘鍗曞厓id
+     * @return 浠〃id闆嗗悎
+     */
+    @Override
+//    @Cacheable(value = CacheConstant.ENERGY_UNIT_DEVICE_ID_CACHE, key = "#unitId", unless = "#result == null")
+    public List<String> getEnergyUnitDeviceIdByUnitId(String unitId) {
+
+        if (StringUtils.isEmpty(unitId)) {
+            return Collections.emptyList();
+        }
+        List<EnergyUnitToDevice> energyUnitToDevices = baseMapper.selectList(Wrappers.<EnergyUnitToDevice>lambdaQuery()
+                .select(EnergyUnitToDevice::getId).eq(EnergyUnitToDevice::getEnergyUnitId, unitId)
+        );
+        if (CollectionUtils.isEmpty(energyUnitToDevices)) {
+            return Collections.emptyList();
+        }
+        return energyUnitToDevices.stream().map(EnergyUnitToDevice::getId).collect(Collectors.toList());
+    }
+
+    /**
+     * 鏍规嵁鐢ㄨ兘鍗曞厓id闆嗗悎鑾峰彇绉熸埛涓嬫湁鏁堢殑浠〃id闆嗗悎
+     *
+     * @param unitIds 鐢ㄨ兘鍗曞厓id
+     */
+    @Override
+    public List<String> getEnergyUnitDeviceIdByUnitIds(List<String> unitIds) {
+        if (CollectionUtils.isEmpty(unitIds)) {
+            return Collections.emptyList();
+        }
+        List<String> deviceIdList = new ArrayList<>();
+        for (String unitId : unitIds) {
+            List<String> unitDeviceIdByUnitId = this.getEnergyUnitDeviceIdByUnitId(unitId);
+            if (CollectionUtils.isNotEmpty(unitDeviceIdByUnitId)) {
+                deviceIdList.addAll(unitDeviceIdByUnitId);
+            }
+        }
+        return deviceIdList;
+    }
+
+    /**
+     * 鏍规嵁鐢ㄨ兘鍗曞厓id闆嗗悎+鑳芥簮绫诲瀷鑾峰彇绉熸埛涓嬫湁鏁堢殑浠〃id闆嗗悎
+     *
+     * @param unitIds 鐢ㄨ兘鍗曞厓id闆嗗悎
+     * @return
+     */
+    @Override
+    public List<String> getDeviceIdByUnitIds(List<String> unitIds) {
+        if (CollectionUtils.isEmpty(unitIds)) {
+            return Collections.emptyList();
+        }
+
+        return baseMapper.listDeviceByTenantIds(unitIds);
+    }
+
+    /**
+     * 鏇存柊鑳藉崟鍏僫d鑾峰彇绉熸埛涓嬫湁鏁堢殑浠〃id闆嗗悎
+     *
+     * @param unitId 鐢ㄨ兘鍗曞厓id
+     * @return 浠〃id闆嗗悎
+     */
+    @Override
+//    @CachePut(value = CacheConstant.ENERGY_UNIT_DEVICE_ID_CACHE, key = "#unitId", unless = "#result == null")
+    public List<String> updateEnergyUnitDeviceIdByUnitId(String unitId) {
+
+        if (StringUtils.isEmpty(unitId)) {
+            return Collections.emptyList();
+        }
+        List<EnergyUnitToDevice> energyUnitToDevices = baseMapper.selectList(Wrappers.<EnergyUnitToDevice>lambdaQuery()
+                .select(EnergyUnitToDevice::getId).eq(EnergyUnitToDevice::getEnergyUnitId, unitId)
+        );
+        if (CollectionUtils.isEmpty(energyUnitToDevices)) {
+            return Collections.emptyList();
+        }
+        return energyUnitToDevices.stream().map(EnergyUnitToDevice::getId).collect(Collectors.toList());
+    }
+
+    /**
+     * 鍒犻櫎鑳藉崟鍏僫d鑾峰彇绉熸埛涓嬫湁鏁堢殑浠〃id闆嗗悎
+     *
+     * @param unitId 鐢ㄨ兘鍗曞厓id
+     */
+    @Override
+//    @CacheEvict(value = CacheConstant.ENERGY_UNIT_DEVICE_ID_CACHE, key = "#unitId")
+    public void deleteEnergyUnitDeviceIdByUnitId(String unitId) {
+    }
+
+    @Override
+    public List<ListElectricityMeterVO> listElectricityMeter(String unitId) {
+
+        LambdaQueryWrapper<EnergyUnitToDevice> queryWrapper = new LambdaQueryWrapper<EnergyUnitToDevice>()
+                .eq(EnergyUnitToDevice::getEnergyUnitId, unitId);
+//                .eq(EnergyUnitToDevice::getDeviceType, EnergyTypeConst.ELECTRICITY);
+        List<EnergyUnitToDevice> models = baseMapper.selectList(queryWrapper);
+
+        List<ListElectricityMeterVO> resultList = new ArrayList<>();
+        for (EnergyUnitToDevice model : models) {
+            ListElectricityMeterVO temp = new ListElectricityMeterVO();
+            temp.setCode(model.getId());
+            temp.setLabel(model.getName());
+            resultList.add(temp);
+        }
+        return resultList;
+    }
+
+    @Override
+    public List<EnergyUnitToDevice> listAllMeter() {
+        QueryWrapper<EnergyUnitToDevice> queryWrapper = new QueryWrapper<EnergyUnitToDevice>();
+        return baseMapper.selectList(queryWrapper);
+    }
+
+    @Override
+    public EnergyUnitToDevice getEnergyUnitToDeviceById(String unitId, String id) {
+        if (StringUtils.isEmpty(id)) {
+            return null;
+        }
+        LambdaQueryWrapper<EnergyUnitToDevice> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+        lambdaQueryWrapper.eq(EnergyUnitToDevice::getEnergyUnitId, unitId);
+        lambdaQueryWrapper.eq(EnergyUnitToDevice::getId, id);
+        List<EnergyUnitToDevice> energyUnitToDevices = baseMapper.selectList(lambdaQueryWrapper);
+        if (CollectionUtils.isNotEmpty(energyUnitToDevices)) {
+            return energyUnitToDevices.get(CommonConst.DIGIT_0);
+        }
+        return null;
+    }
+
+    /**
+     * 鏍规嵁璁¢噺鍣ㄥ叿id闆嗗悎鏌ヨ涓庣敤鑳界殑鍏崇郴
+     *
+     * @param unitIds
+     * @return
+     */
+    @Override
+    public List<UnitToDeviceRelationVO> listDeviceByUnitIds(List<String> unitIds) {
+        List<UnitToDeviceRelationVO> relationList = new ArrayList<>();
+        if (CollectionUtils.isEmpty(unitIds)) {
+            return relationList;
+        }
+        List<EnergyUnitToDevice> unitToDeviceList = baseMapper.selectList(Wrappers.<EnergyUnitToDevice>lambdaQuery()
+                .select(EnergyUnitToDevice::getId, EnergyUnitToDevice::getEnergyUnitId, EnergyUnitToDevice::getName)
+                .in(EnergyUnitToDevice::getEnergyUnitId, unitIds)
+        );
+        if (CollectionUtils.isNotEmpty(unitToDeviceList)) {
+            unitToDeviceList.forEach(li -> {
+                UnitToDeviceRelationVO vo = new UnitToDeviceRelationVO();
+                vo.setDeviceId(li.getId());
+                vo.setUnitId(li.getEnergyUnitId());
+                vo.setDeviceName(li.getName());
+                relationList.add(vo);
+            });
+        }
+        return relationList;
+    }
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/history/domain/dto/HistoricalDataDTO.java b/zhitan-system/src/main/java/com/zhitan/history/domain/dto/HistoricalDataDTO.java
new file mode 100644
index 0000000..347976b
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/history/domain/dto/HistoricalDataDTO.java
@@ -0,0 +1,63 @@
+package com.zhitan.history.domain.dto;
+
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.util.Date;
+
+/**
+ * 鍘嗗彶鐩戞祴鏁版嵁璇锋眰 DTO
+ *
+ * @Author: Zhujw
+ * @Date: 2023/3/7
+ */
+public class HistoricalDataDTO {
+
+    /**
+     * 鐐逛綅id
+     */
+    @NotBlank(message = "鏈壘鍒扮偣浣嶄俊鎭�")
+    private String indexId;
+
+    /**
+     * 鏃堕棿绫诲瀷
+     */
+    @NotBlank(message = "鏈壘鍒版椂闂寸被鍨�")
+    private String timeType;
+
+    /**
+     * 鏌ヨ鏃堕棿
+     */
+    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    @NotNull(message = "鏈壘鍒版椂闂翠俊鎭�")
+    private Date dataTime;
+
+    public String getIndexId() {
+        return indexId;
+    }
+
+    public void setIndexId(String indexId) {
+        this.indexId = indexId;
+    }
+
+    public String getTimeType() {
+        return timeType;
+    }
+
+    public void setTimeType(String timeType) {
+        this.timeType = timeType;
+    }
+
+    public Date getDataTime() {
+        return dataTime;
+    }
+
+    public void setDataTime(Date dataTime) {
+        this.dataTime = dataTime;
+    }
+
+}
\ No newline at end of file
diff --git a/zhitan-system/src/main/java/com/zhitan/history/domain/vo/HistoricalDataExcel.java b/zhitan-system/src/main/java/com/zhitan/history/domain/vo/HistoricalDataExcel.java
new file mode 100644
index 0000000..ca0b653
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/history/domain/vo/HistoricalDataExcel.java
@@ -0,0 +1,70 @@
+package com.zhitan.history.domain.vo;
+
+
+import com.zhitan.common.annotation.Excel;
+
+/**
+ * 鍘嗗彶鐩戞祴鏁版嵁杩斿洖 Excel
+ *
+ * @Author: Zhujw
+ * @Date: 2023/3/7
+ */
+public class HistoricalDataExcel {
+
+    /**
+     * 鐐逛綅鍚嶇О
+     */
+    @Excel(name = "鐐逛綅鍚嶇О")
+    private String indexName;
+
+    /**
+     * 鍊�
+     */
+    @Excel(name = "鍊�")
+    private String value;
+
+    /**
+     * 浣跨敤閲�
+     */
+    @Excel(name = "浣跨敤閲�")
+    private String usedValue;
+
+    /**
+     * 鏃堕棿
+     */
+    @Excel(name = "鏃堕棿")
+    private String dataTime;
+
+
+    public String getIndexName() {
+        return indexName;
+    }
+
+    public void setIndexName(String indexName) {
+        this.indexName = indexName;
+    }
+
+    public String getDataTime() {
+        return dataTime;
+    }
+
+    public void setDataTime(String dataTime) {
+        this.dataTime = dataTime;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public String getUsedValue() {
+        return usedValue;
+    }
+
+    public void setUsedValue(String usedValue) {
+        this.usedValue = usedValue;
+    }
+}
\ No newline at end of file
diff --git a/zhitan-system/src/main/java/com/zhitan/history/domain/vo/HistoricalDataVO.java b/zhitan-system/src/main/java/com/zhitan/history/domain/vo/HistoricalDataVO.java
new file mode 100644
index 0000000..b03f10b
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/history/domain/vo/HistoricalDataVO.java
@@ -0,0 +1,77 @@
+package com.zhitan.history.domain.vo;
+
+
+/**
+ * 鍘嗗彶鐩戞祴鏁版嵁杩斿洖 VO
+ *
+ * @Author: Zhujw
+ * @Date: 2023/3/7
+ */
+public class HistoricalDataVO {
+
+    /**
+     * 鐐逛綅id
+     */
+    private String indexId;
+
+    /**
+     * 鐐逛綅鍚嶇О
+     */
+    private String indexName;
+
+    /**
+     * 鏃堕棿
+     */
+    private String dataTime;
+
+    /**
+     * 鍊�
+     */
+    private String value;
+
+    /**
+     * 浣跨敤閲�
+     */
+    private String usedValue;
+
+
+    public String getIndexId() {
+        return indexId;
+    }
+
+    public void setIndexId(String indexId) {
+        this.indexId = indexId;
+    }
+
+    public String getIndexName() {
+        return indexName;
+    }
+
+    public void setIndexName(String indexName) {
+        this.indexName = indexName;
+    }
+
+    public String getDataTime() {
+        return dataTime;
+    }
+
+    public void setDataTime(String dataTime) {
+        this.dataTime = dataTime;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public String getUsedValue() {
+        return usedValue;
+    }
+
+    public void setUsedValue(String usedValue) {
+        this.usedValue = usedValue;
+    }
+}
\ No newline at end of file
diff --git a/zhitan-system/src/main/java/com/zhitan/model/domain/vo/ModelNodeIndexInfor.java b/zhitan-system/src/main/java/com/zhitan/model/domain/vo/ModelNodeIndexInfor.java
index e7446e3..e52a163 100644
--- a/zhitan-system/src/main/java/com/zhitan/model/domain/vo/ModelNodeIndexInfor.java
+++ b/zhitan-system/src/main/java/com/zhitan/model/domain/vo/ModelNodeIndexInfor.java
@@ -32,6 +32,8 @@
    */
   private String energyId;
 
+  private String indexType;
+
   public String getNodeId() {
     return nodeId;
   }
@@ -63,4 +65,12 @@
   public void setEnergyId(String energyId) {
     this.energyId = energyId;
   }
+
+  public String getIndexType() {
+    return indexType;
+  }
+
+  public void setIndexType(String indexType) {
+    this.indexType = indexType;
+  }
 }
diff --git a/zhitan-system/src/main/java/com/zhitan/realtimedata/data/RealtimeDatabaseManager.java b/zhitan-system/src/main/java/com/zhitan/realtimedata/data/RealtimeDatabaseManager.java
new file mode 100644
index 0000000..f3914ff
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/realtimedata/data/RealtimeDatabaseManager.java
@@ -0,0 +1,163 @@
+package com.zhitan.realtimedata.data;
+
+import com.influxdb.client.InfluxDBClient;
+import com.influxdb.client.InfluxDBClientFactory;
+import com.influxdb.client.domain.HealthCheck;
+import com.zhitan.common.enums.CollectionModes;
+import com.zhitan.common.enums.RetrievalModes;
+import com.zhitan.realtimedata.config.RtdbConfig;
+import com.zhitan.realtimedata.domain.TagValue;
+import com.zhitan.realtimedata.service.RealtimeDatabase;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @author 鑼冩柊瀵� 瀹炴椂鏁版嵁搴撹闂鐞�.
+ */
+@Component
+public class RealtimeDatabaseManager {
+
+    private final RealtimeDatabase connection;
+
+    private final Logger logger = LogManager.getLogger(RealtimeDatabaseManager.class);
+
+    public RealtimeDatabaseManager(RtdbConfig config) {
+    connection = new VirtualRtdb();
+        try {
+            InfluxDBClient influxDBClient = InfluxDBClientFactory.create(config.getHost(),
+                    config.getToken().toCharArray(), config.getOrg(), config.getBucket());
+
+            logger.error("--------------------瀹炴椂搴撹繛鎺ユ垚鍔�--------------------");
+            HealthCheck health = influxDBClient.health();
+            if (health.getStatus() == HealthCheck.StatusEnum.FAIL) {
+                influxDBClient.close();
+            }
+        } catch (Exception e) {
+            logger.error(e);
+        }
+    }
+
+    public TagValue retrieve(String tagCode) {
+        List<String> tagCodes = new ArrayList<>();
+        tagCodes.add(tagCode);
+        List<TagValue> tagValues = retrieve(tagCodes);
+        if (!tagValues.isEmpty()) {
+            return tagValues.get(0);
+        }
+
+        return null;
+    }
+
+    public List<TagValue> retrieve(List<String> tagCodes) {
+        List<TagValue> tagValues = new ArrayList<>();
+        try {
+            tagValues = connection.retrieve(tagCodes);
+        } catch (Exception e) {
+            logger.error(e);
+        }
+
+        return tagValues;
+    }
+
+    public TagValue retrieve(String tagCode, Date dataTime, String timeCode) {
+        List<String> tagCodes = new ArrayList<>();
+        tagCodes.add(tagCode);
+        List<TagValue> tagValues = retrieve(tagCodes, dataTime, timeCode);
+        if (!tagValues.isEmpty()) {
+            return tagValues.get(0);
+        }
+
+        return null;
+    }
+
+    public List<TagValue> retrieve(List<String> tagCodes, Date dataTime, String timeCode) {
+        List<TagValue> tagValues = new ArrayList<>();
+        try {
+            List<TagValue> tmp = connection.retrieve(tagCodes, dataTime, timeCode);
+            for (String tagCode : tagCodes) {
+                Optional<TagValue> tagValue = tmp.stream()
+                        .filter(f -> StringUtils.equalsIgnoreCase(f.getTagCode(), tagCode)).findAny();
+                TagValue value;
+                if (!tagValue.isPresent()) {
+                    value = new TagValue();
+                    value.setTagCode(tagCode);
+                    value.setDataTime(dataTime);
+                } else {
+                    value = tagValue.get();
+                }
+
+                tagValues.add(value);
+            }
+        } catch (Exception e1) {
+            logger.error(e1);
+        }
+
+        return tagValues;
+    }
+
+    public List<TagValue> retrieve(String tagCode, Date beginTime, Date endTime,
+                                   RetrievalModes retrievalModes, int pointCount) {
+        List<String> tagCodes = new ArrayList<>();
+        tagCodes.add(tagCode);
+        return retrieve(tagCodes, beginTime, endTime, retrievalModes, pointCount);
+    }
+
+    public List<TagValue> retrieve(List<String> tagCodes, Date beginTime, Date endTime,
+                                   RetrievalModes retrievalModes, int pointCount) {
+        List<TagValue> tagValues = new ArrayList<>();
+        try {
+            tagValues = connection.retrieve(tagCodes, beginTime, endTime, retrievalModes, pointCount);
+        } catch (Exception e1) {
+            logger.error(e1);
+        }
+
+        return tagValues;
+    }
+
+    public TagValue statistics(String tagCode, Date beginTime, Date endTime,
+                               CollectionModes collectionModes) {
+        List<String> tagCodes = new ArrayList<>();
+        tagCodes.add(tagCode);
+        List<TagValue> tagValues = statistics(tagCodes, beginTime, endTime, collectionModes);
+        if (!tagValues.isEmpty()) {
+            return tagValues.get(0);
+        }
+
+        return null;
+    }
+
+    public List<TagValue> statistics(List<String> tagCodes, Date beginTime, Date endTime,
+                                     CollectionModes collectionModes) {
+        List<TagValue> tagValues = new ArrayList<>();
+        try {
+            tagValues = connection.statistics(tagCodes, beginTime, endTime, collectionModes);
+        } catch (Exception e1) {
+            logger.error(e1);
+        }
+
+        return tagValues;
+    }
+
+    public void storeData(List<TagValue> tagValues) {
+        try {
+            connection.storeData(tagValues);
+        } catch (Exception e1) {
+            logger.error(e1);
+        }
+    }
+
+    public void insertData(List<TagValue> tagValues) {
+        try {
+            connection.insertData(tagValues);
+        } catch (Exception e1) {
+            logger.error(e1);
+        }
+    }
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/realtimedata/domain/SysEquipmentFile.java b/zhitan-system/src/main/java/com/zhitan/realtimedata/domain/SysEquipmentFile.java
index 5ced53d..a84a983 100644
--- a/zhitan-system/src/main/java/com/zhitan/realtimedata/domain/SysEquipmentFile.java
+++ b/zhitan-system/src/main/java/com/zhitan/realtimedata/domain/SysEquipmentFile.java
@@ -1,5 +1,8 @@
 package com.zhitan.realtimedata.domain;
 
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.util.List;
@@ -9,10 +12,18 @@
  *
  */
 @Data
+@TableName("sys_equipmentfile")
 public class SysEquipmentFile {
 
+  @TableId
   private String nodeId;
+
+  @TableField(value = "filepath")
   private String filePath;
+
+  @TableField(exist = false)
   private String svgType;
+
+  @TableField(exist = false)
   private List<SysSvgInfo> infoList;
 }
diff --git a/zhitan-system/src/main/java/com/zhitan/realtimedata/domain/vo/EquipmentMeasuringPointParameters.java b/zhitan-system/src/main/java/com/zhitan/realtimedata/domain/vo/EquipmentMeasuringPointParameters.java
new file mode 100644
index 0000000..c899288
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/realtimedata/domain/vo/EquipmentMeasuringPointParameters.java
@@ -0,0 +1,30 @@
+package com.zhitan.realtimedata.domain.vo;
+
+import lombok.Data;
+
+/**
+ * 璁惧鐩戞祴鍙傛暟鍒楄〃瀵硅薄
+ */
+@Data
+public class EquipmentMeasuringPointParameters {
+
+    private String code;
+
+    private String indexName;
+
+    private String indexUnit;
+
+    private Double value;
+
+    private String yValue;
+
+    private String meteName;
+
+    public String getyValue() {
+        return yValue;
+    }
+
+    public void setyValue(String yValue) {
+        this.yValue = yValue;
+    }
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/realtimedata/mapper/SvgTrendMapper.java b/zhitan-system/src/main/java/com/zhitan/realtimedata/mapper/SvgTrendMapper.java
new file mode 100644
index 0000000..e3fc7b8
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/realtimedata/mapper/SvgTrendMapper.java
@@ -0,0 +1,16 @@
+package com.zhitan.realtimedata.mapper;
+
+
+import com.zhitan.model.domain.EnergyIndex;
+
+import java.util.List;
+
+public interface SvgTrendMapper {
+    /**
+     * 瀹炴椂妫�娴� 鍔熻兘 鐨勫 sheet椤�  灞曠ず 缁勬�佸浘  娴嬬偣 鎶ヨ淇℃伅
+     *
+     * @param energyIndex
+     * @return
+     */
+    List<EnergyIndex> selectSvgTrendList(EnergyIndex energyIndex);
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/realtimedata/service/ISvgTrendService.java b/zhitan-system/src/main/java/com/zhitan/realtimedata/service/ISvgTrendService.java
new file mode 100644
index 0000000..cb34eda
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/realtimedata/service/ISvgTrendService.java
@@ -0,0 +1,15 @@
+package com.zhitan.realtimedata.service;
+
+import com.zhitan.model.domain.EnergyIndex;
+
+import java.util.List;
+
+public interface ISvgTrendService {
+
+    /**
+     * 瀹炴椂妫�娴� 鍔熻兘 鐨勫 sheet椤�  灞曠ず瓒嬪娍鍥�
+     * @param energyIndex
+     * @return
+     */
+    List<EnergyIndex> selectSvgList(EnergyIndex energyIndex);
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/realtimedata/service/RealtimeDatabaseService.java b/zhitan-system/src/main/java/com/zhitan/realtimedata/service/RealtimeDatabaseService.java
index 956a5cd..dc45bc7 100644
--- a/zhitan-system/src/main/java/com/zhitan/realtimedata/service/RealtimeDatabaseService.java
+++ b/zhitan-system/src/main/java/com/zhitan/realtimedata/service/RealtimeDatabaseService.java
@@ -2,6 +2,7 @@
 
 
 import com.zhitan.common.enums.CollectionModes;
+import com.zhitan.common.enums.RetrievalModes;
 import com.zhitan.realtimedata.domain.TagValue;
 
 import java.util.Date;
@@ -105,4 +106,17 @@
      * @param tagValues 娴嬬偣鍘嗗彶鏃跺埢鏁版嵁
      */
     void insertData(List<TagValue> tagValues);
+
+    /**
+     * 鑾峰彇涓�娈垫椂闂村唴娴嬬偣鐨勫巻鍙叉暟鎹�.
+     *
+     * @param tagCode        娴嬬偣缂栧彿
+     * @param beginTime      寮�濮嬫椂闂�
+     * @param endTime        缁撴潫鏃堕棿
+     * @param retrievalModes 鏌ヨ鏁版嵁鏂瑰紡
+     * @param pointCount     娴嬬偣寰楀埌鐨勬暟鎹釜鏁�
+     * @return 娴嬬偣鍘嗗彶鏁版嵁
+     */
+    List<TagValue> retrieve(String tagCode, Date beginTime, Date endTime,
+                            RetrievalModes retrievalModes, int pointCount);
 }
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 bb8b97b..7128652 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
@@ -2,6 +2,8 @@
 
 import com.google.common.collect.Lists;
 import com.zhitan.common.enums.CollectionModes;
+import com.zhitan.common.enums.RetrievalModes;
+import com.zhitan.realtimedata.data.RealtimeDatabaseManager;
 import com.zhitan.realtimedata.data.influxdb.InfluxDBRepository;
 import com.zhitan.realtimedata.domain.TagValue;
 import com.zhitan.realtimedata.service.RealtimeDatabaseService;
@@ -20,8 +22,11 @@
 
     private final InfluxDBRepository repository;
 
-    public RealtimeDatabaseServiceImpl(InfluxDBRepository repository) {
+    private final RealtimeDatabaseManager realtimeDatabaseManager;
+
+    public RealtimeDatabaseServiceImpl(InfluxDBRepository repository, RealtimeDatabaseManager realtimeDatabaseManager) {
         this.repository = repository;
+        this.realtimeDatabaseManager = realtimeDatabaseManager;
     }
 
     /**
@@ -146,4 +151,9 @@
         repository.store(tagValues);
     }
 
+    @Override
+    public List<TagValue> retrieve(String tagCode, Date beginTime, Date endTime,
+                                   RetrievalModes retrievalModes, int pointCount) {
+        return realtimeDatabaseManager.retrieve(tagCode, beginTime, endTime, retrievalModes, pointCount);
+    }
 }
diff --git a/zhitan-system/src/main/java/com/zhitan/realtimedata/service/impl/SvgTrendServicelmpl.java b/zhitan-system/src/main/java/com/zhitan/realtimedata/service/impl/SvgTrendServicelmpl.java
new file mode 100644
index 0000000..2c848ba
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/realtimedata/service/impl/SvgTrendServicelmpl.java
@@ -0,0 +1,26 @@
+package com.zhitan.realtimedata.service.impl;
+
+import com.zhitan.model.domain.EnergyIndex;
+import com.zhitan.realtimedata.mapper.SvgTrendMapper;
+import com.zhitan.realtimedata.service.ISvgTrendService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class SvgTrendServicelmpl implements ISvgTrendService {
+
+    @Autowired
+    private SvgTrendMapper svgTrendMapper;
+    /**
+     * 鏌ヨ鎸囨爣淇℃伅
+     *
+     * @param energyIndex 鎸囨爣淇℃伅ID
+     * @return 鎸囨爣淇℃伅
+     */
+    @Override
+    public List<EnergyIndex> selectSvgList(EnergyIndex energyIndex) {
+        return svgTrendMapper.selectSvgTrendList(energyIndex);
+    }
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/dto/DataAnalysisMoMDTO.java b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/dto/DataAnalysisMoMDTO.java
new file mode 100644
index 0000000..53ea2e2
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/dto/DataAnalysisMoMDTO.java
@@ -0,0 +1,48 @@
+package com.zhitan.statisticalAnalysis.domain.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.zhitan.common.annotation.Excel;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.util.Date;
+
+/**
+ * 鏁版嵁鍒嗘瀽鐜瘮 璇锋眰鍙傛暟
+ *
+ * @Author: Zhujw
+ * @Date: 2023/3/3
+ */
+@Data
+public class DataAnalysisMoMDTO {
+
+
+    /**
+     * 缁熻寮�濮嬫椂闂�
+     */
+    @NotNull(message = "璇风淮鎶ゆ煡璇㈡椂闂�")
+    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "鎶ヨ寮�濮嬫椂闂�", dateFormat = "yyyy-MM-dd HH:mm:ss")
+    private Date beginTime;
+
+    /**
+     * 缁熻寮�濮嬫椂闂�
+     */
+    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "鎶ヨ寮�濮嬫椂闂�", dateFormat = "yyyy-MM-dd HH:mm:ss")
+    @NotNull(message = "璇风淮鎶ゆ煡璇㈡椂闂�")
+    private Date endTime;
+
+    /**
+     * 鏃堕棿绫诲瀷
+     */
+    @NotBlank(message = "鏈壘鍒版椂闂寸被鍨�")
+    private String timeType;
+
+    /**
+     * 妯″瀷鑺傜偣id
+     */
+    @NotBlank(message = "鏈壘鍒版ā鍨嬭妭鐐逛俊鎭�")
+    private String nodeId;
+}
\ No newline at end of file
diff --git a/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/DataAnalysisMoMExcel.java b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/DataAnalysisMoMExcel.java
new file mode 100644
index 0000000..d2212da
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/DataAnalysisMoMExcel.java
@@ -0,0 +1,47 @@
+package com.zhitan.statisticalAnalysis.domain.vo;
+
+import com.zhitan.common.annotation.Excel;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 鏁版嵁鍒嗘瀽鐜瘮 瀵煎嚭Excel
+ *
+ * @Author: Zhujw
+ * @Date: 2023/3/3
+ */
+@Data
+public class DataAnalysisMoMExcel {
+
+
+    /**
+     * 鐢ㄨ兘鍗曞厓鍚嶇О
+     */
+    @Excel(name = "鐢ㄨ兘鍗曞厓")
+    private String energyUnitName;
+
+    /**
+     * 鏈湡鍊�
+     */
+    @Excel(name = "鏈湡鍊�")
+    private BigDecimal currentValue;
+
+    /**
+     * 鍚屾湡鍊�
+     */
+    @Excel(name = "鍚屾湡鍊�")
+    private BigDecimal oldValue;
+
+    /**
+     * 鍚屾瘮鍊�
+     */
+    @Excel(name = "鍚屾瘮鍊�")
+    private BigDecimal ratio;
+
+    /**
+     * 鍗曚綅
+     */
+    @Excel(name = "鍗曚綅")
+    private String unit;
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/DataAnalysisMoMVO.java b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/DataAnalysisMoMVO.java
new file mode 100644
index 0000000..f675130
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/DataAnalysisMoMVO.java
@@ -0,0 +1,42 @@
+package com.zhitan.statisticalAnalysis.domain.vo;
+
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 鏁版嵁鍒嗘瀽鐜瘮 杩斿洖vo
+ *
+ * @Author: Zhujw
+ * @Date: 2023/3/3
+ */
+@Data
+public class DataAnalysisMoMVO {
+
+
+    /**
+     * 鍗曚綅
+     */
+    private String unit;
+
+    /**
+     * 鐢ㄨ兘鍗曞厓鍚嶇О
+     */
+    private String energyUnitName;
+
+    /**
+     * 鏈湡鍊�
+     */
+    private BigDecimal currentValue;
+
+    /**
+     * 鍚屾湡鍊�
+     */
+    private BigDecimal oldValue;
+
+    /**
+     * 鍚屾瘮鍊�
+     */
+    private BigDecimal ratio;
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/DataAnalysisYoYExcel.java b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/DataAnalysisYoYExcel.java
new file mode 100644
index 0000000..e2516e4
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/DataAnalysisYoYExcel.java
@@ -0,0 +1,47 @@
+package com.zhitan.statisticalAnalysis.domain.vo;
+
+import com.zhitan.common.annotation.Excel;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 鏁版嵁鍒嗘瀽鍚屾瘮 瀵煎嚭Excel
+ *
+ * @Author: Zhujw
+ * @Date: 2023/3/3
+ */
+@Data
+public class DataAnalysisYoYExcel {
+
+
+    /**
+     * 鐢ㄨ兘鍗曞厓鍚嶇О
+     */
+    @Excel(name = "鐢ㄨ兘鍗曞厓鍚嶇О")
+    private String energyUnitName;
+
+    /**
+     * 鏈湡鍊�
+     */
+    @Excel(name = "鏈湡鍊�")
+    private BigDecimal currentValue;
+
+    /**
+     * 鍚屾湡鍊�
+     */
+    @Excel(name = "鍚屾湡鍊�")
+    private BigDecimal oldValue;
+
+    /**
+     * 鍚屾瘮鍊�
+     */
+    @Excel(name = "鍚屾瘮鍊�")
+    private BigDecimal ratio;
+
+    /**
+     * 鍗曚綅
+     */
+    @Excel(name = "鍗曚綅")
+    private String unit;
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/DataAnalysisYoYVO.java b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/DataAnalysisYoYVO.java
new file mode 100644
index 0000000..49e0223
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/domain/vo/DataAnalysisYoYVO.java
@@ -0,0 +1,42 @@
+package com.zhitan.statisticalAnalysis.domain.vo;
+
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 鏁版嵁鍒嗘瀽鍚屾瘮 杩斿洖vo
+ *
+ * @Author: Zhujw
+ * @Date: 2023/3/3
+ */
+@Data
+public class DataAnalysisYoYVO {
+
+
+    /**
+     * 鍗曚綅
+     */
+    private String unit;
+
+    /**
+     * 鐢ㄨ兘鍗曞厓鍚嶇О
+     */
+    private String energyUnitName;
+
+    /**
+     * 鏈湡鍊�
+     */
+    private BigDecimal currentValue;
+
+    /**
+     * 鍚屾湡鍊�
+     */
+    private BigDecimal oldValue;
+
+    /**
+     * 鍚屾瘮鍊�
+     */
+    private BigDecimal ratio;
+}
diff --git a/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/service/IStatisticalAnalysisService.java b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/service/IStatisticalAnalysisService.java
new file mode 100644
index 0000000..4add9e7
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/service/IStatisticalAnalysisService.java
@@ -0,0 +1,36 @@
+package com.zhitan.statisticalAnalysis.service;
+
+import com.zhitan.statisticalAnalysis.domain.dto.DataAnalysisMoMDTO;
+import com.zhitan.statisticalAnalysis.domain.vo.DataAnalysisMoMVO;
+import com.zhitan.statisticalAnalysis.domain.vo.DataAnalysisYoYVO;
+
+import java.util.List;
+
+/**
+ * 缁熻鍒嗘瀽  鎺ュ彛灞�
+ *
+ * @Author: Zhujw
+ * @Date: 2023/3/1
+ */
+public interface IStatisticalAnalysisService {
+
+    /**
+     * 鑾峰彇鐢佃兘鑰楀悓姣旀暟鎹�
+     */
+    List<DataAnalysisYoYVO> listElectricDataComparisonYoY(DataAnalysisMoMDTO dto);
+
+    /**
+     * 鑾峰彇鐢佃兘鑰楃幆姣旀暟鎹�
+     */
+    List<DataAnalysisMoMVO> listElectricDataComparisonMoM(DataAnalysisMoMDTO dto);
+
+    /**
+     * 鑾峰彇鑳借�楀悓姣旀暟鎹�
+     */
+    List<DataAnalysisYoYVO> listWaterDataComparisonYoY(DataAnalysisMoMDTO dto);
+
+    /**
+     * 鑾峰彇鑳借�楃幆姣旀暟鎹�
+     */
+    List<DataAnalysisMoMVO> listWaterDataComparisonMoM(DataAnalysisMoMDTO dto);
+}
\ No newline at end of file
diff --git a/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/service/impl/StatisticalAnalysisServiceImpl.java b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/service/impl/StatisticalAnalysisServiceImpl.java
new file mode 100644
index 0000000..257f890
--- /dev/null
+++ b/zhitan-system/src/main/java/com/zhitan/statisticalAnalysis/service/impl/StatisticalAnalysisServiceImpl.java
@@ -0,0 +1,293 @@
+package com.zhitan.statisticalAnalysis.service.impl;
+
+import cn.hutool.core.date.DateField;
+import cn.hutool.core.date.DateUtil;
+import com.zhitan.common.constant.CommonConst;
+import com.zhitan.common.constant.TimeTypeConst;
+import com.zhitan.common.enums.TimeType;
+import com.zhitan.dataitem.service.IDataItemService;
+import com.zhitan.model.domain.vo.ModelNodeIndexInfor;
+import com.zhitan.model.service.IModelNodeService;
+import com.zhitan.realtimedata.domain.DataItem;
+import com.zhitan.statisticalAnalysis.domain.dto.DataAnalysisMoMDTO;
+import com.zhitan.statisticalAnalysis.domain.vo.DataAnalysisMoMVO;
+import com.zhitan.statisticalAnalysis.domain.vo.DataAnalysisYoYVO;
+import com.zhitan.statisticalAnalysis.service.IStatisticalAnalysisService;
+import lombok.AllArgsConstructor;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 缁熻鍒嗘瀽  鎺ュ彛灞傚疄鐜板眰
+ */
+@Service
+@AllArgsConstructor
+public class StatisticalAnalysisServiceImpl implements IStatisticalAnalysisService {
+
+    private final IDataItemService dataItemService;
+
+    private final IModelNodeService modelNodeService;
+
+
+    /**
+     * 鑾峰彇鐢佃兘鑰楀悓姣旀暟鎹�
+     */
+    @Override
+    public List<DataAnalysisYoYVO> listElectricDataComparisonYoY(DataAnalysisMoMDTO dto) {
+        List<DataAnalysisYoYVO> yoyList = new ArrayList<>();
+        // 鏌ヨ鐐逛綅涓庣敤鑳藉崟鍏冧俊鎭�
+        List<ModelNodeIndexInfor> nodeInforList = listModelNodeIndexIdRelationInfor(dto.getNodeId());
+        if (CollectionUtils.isEmpty(nodeInforList)) {
+            return yoyList;
+        }
+        List<String> indexIds = nodeInforList.stream().map(ModelNodeIndexInfor::getIndexId).collect(Collectors.toList());
+        // 鎸夌収鐐逛綅杩涜鍒嗙粍
+        Map<String, List<ModelNodeIndexInfor>> nodeIndexMap = nodeInforList.stream().collect(
+                Collectors.groupingBy(ModelNodeIndexInfor::getNodeId));
+        // 鑾峰彇鏌ヨ鏃堕棿
+        Date beginTime = dto.getBeginTime();
+        Date endTime = dto.getEndTime();
+        // 鍚屾瘮鏃堕棿
+        Date lastTime = DateUtil.offset(beginTime, DateField.YEAR, CommonConst.DIGIT_MINUS_1);
+        Date lastEndTime = DateUtil.offset(endTime, DateField.YEAR, CommonConst.DIGIT_MINUS_1);
+        // 鏌ヨ瀵瑰簲indexIds锛屾壘鍒板搴攄ataItem淇℃伅
+        List<DataItem> dataItemList = dataItemService.getDataItemHourInforByIndexIds(beginTime, endTime, TimeType.HOUR.name(), indexIds);
+        List<DataItem> lastDataItemList = dataItemService.getDataItemHourInforByIndexIds(lastTime, lastEndTime, TimeType.HOUR.name(), indexIds);
+        //  鍊嶇巼
+        BigDecimal multiple = BigDecimal.valueOf(CommonConst.DIGIT_100);
+        nodeIndexMap.forEach((key, value) -> {
+            DataAnalysisYoYVO yoyVO = new DataAnalysisYoYVO();
+            Optional<ModelNodeIndexInfor> first = value.stream().findFirst();
+            first.ifPresent(modelNodeIndexInfor -> yoyVO.setEnergyUnitName(modelNodeIndexInfor.getName()));
+            // 璧嬪�煎崟浣�
+            yoyVO.setUnit("kWh");
+            // 鎵惧嚭indexIds
+            List<String> indexIdList = value.stream().map(ModelNodeIndexInfor::getIndexId).collect(Collectors.toList());
+            // 姹傚拰
+            BigDecimal sum = BigDecimal.valueOf(dataItemList.stream().filter(li -> indexIdList.contains(li.getIndexId()))
+                    .mapToDouble(DataItem::getValue).sum()).setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP);
+            BigDecimal lastSum = BigDecimal.valueOf(lastDataItemList.stream().filter(li -> indexIdList.contains(li.getIndexId()))
+                    .mapToDouble(DataItem::getValue).sum()).setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP);
+            yoyVO.setCurrentValue(sum);
+            yoyVO.setOldValue(lastSum);
+            //  鍚屾瘮鍊�
+            BigDecimal ratio = BigDecimal.ZERO;
+            if (lastSum.compareTo(BigDecimal.ZERO) != 0) {
+                ratio = sum.subtract(lastSum).divide(lastSum, CommonConst.DIGIT_2, RoundingMode.HALF_UP).multiply(multiple);
+            }
+            yoyVO.setRatio(ratio);
+            yoyList.add(yoyVO);
+        });
+        return yoyList;
+    }
+
+    /**
+     * 鑾峰彇鐢佃兘鑰楃幆姣旀暟鎹�
+     */
+    @Override
+    public List<DataAnalysisMoMVO> listElectricDataComparisonMoM(DataAnalysisMoMDTO dto) {
+        List<DataAnalysisMoMVO> momList = new ArrayList<>();
+        // 鏍规嵁id鏌ヨ鐐逛綅淇℃伅
+        List<ModelNodeIndexInfor> nodeIndexInforList = listModelNodeIndexIdRelationInfor(dto.getNodeId());
+        if (CollectionUtils.isEmpty(nodeIndexInforList)) {
+            return momList;
+        }
+        List<String> indexIds = nodeIndexInforList.stream().map(ModelNodeIndexInfor::getIndexId).collect(Collectors.toList());
+        Date beginTime = dto.getBeginTime();
+        Date endTime = dto.getEndTime();
+        Date lastTime;
+        Date lastEndTime;
+        String queryTimeType = dto.getTimeType();
+        // 灏忔椂
+        if (TimeTypeConst.TIME_TYPE_HOUR.equals(queryTimeType)) {
+            lastTime = DateUtil.offsetHour(beginTime, CommonConst.DIGIT_MINUS_1);
+            lastEndTime = DateUtil.offsetHour(endTime, CommonConst.DIGIT_MINUS_1);
+            // 澶�
+        } else if (TimeTypeConst.TIME_TYPE_DAY.equals(queryTimeType)) {
+            lastTime = DateUtil.offsetDay(beginTime, CommonConst.DIGIT_MINUS_1);
+            lastEndTime = DateUtil.offsetDay(endTime, CommonConst.DIGIT_MINUS_1);
+            // 鏈�
+        } else if (TimeTypeConst.TIME_TYPE_MONTH.equals(queryTimeType)) {
+            lastTime = DateUtil.offsetMonth(beginTime, CommonConst.DIGIT_MINUS_1);
+            lastEndTime = DateUtil.offsetMonth(endTime, CommonConst.DIGIT_MINUS_1);
+            // 骞�
+        } else {
+            lastTime = DateUtil.offset(beginTime, DateField.YEAR, CommonConst.DIGIT_MINUS_1);
+            lastEndTime = DateUtil.offset(endTime, DateField.YEAR, CommonConst.DIGIT_MINUS_1);
+        }
+        // 鎸夌収鐐逛綅杩涜鍒嗙粍
+        Map<String, List<ModelNodeIndexInfor>> nodeIndexMap = nodeIndexInforList.stream().collect(
+                Collectors.groupingBy(ModelNodeIndexInfor::getNodeId));
+        // 鏍规嵁indexId鏌ヨdataItem
+        List<DataItem> dataItemList = dataItemService.getDataItemHourInforByIndexIds(beginTime, endTime, TimeType.HOUR.name(), indexIds);
+        List<DataItem> lastDataItemList = dataItemService.getDataItemHourInforByIndexIds(lastTime, lastEndTime, TimeType.HOUR.name(), indexIds);
+        //  鍊嶇巼
+        BigDecimal multiple = BigDecimal.valueOf(CommonConst.DIGIT_100);
+        nodeIndexMap.forEach((key, value) -> {
+            DataAnalysisMoMVO momVO = new DataAnalysisMoMVO();
+            Optional<ModelNodeIndexInfor> first = value.stream().findFirst();
+            first.ifPresent(modelNodeIndexInfor -> momVO.setEnergyUnitName(modelNodeIndexInfor.getName()));
+            // 璧嬪�煎崟浣�
+            momVO.setUnit("kWh");
+            // 鎵惧嚭indexIds
+            List<String> indexIdList = value.stream().map(ModelNodeIndexInfor::getIndexId).collect(Collectors.toList());
+            // 姹傚拰
+            BigDecimal sum = BigDecimal.valueOf(dataItemList.stream().filter(li -> indexIdList.contains(li.getIndexId()))
+                    .mapToDouble(DataItem::getValue).sum()).setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP);
+            BigDecimal lastSum = BigDecimal.valueOf(lastDataItemList.stream().filter(li -> indexIdList.contains(li.getIndexId()))
+                    .mapToDouble(DataItem::getValue).sum()).setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP);
+            momVO.setCurrentValue(sum);
+            momVO.setOldValue(lastSum);
+            //  鍚屾瘮鍊�
+            BigDecimal ratio = BigDecimal.ZERO;
+            if (lastSum.compareTo(BigDecimal.ZERO) != 0) {
+                ratio = sum.subtract(lastSum).divide(lastSum, CommonConst.DIGIT_2, RoundingMode.HALF_UP).multiply(multiple);
+            }
+            momVO.setRatio(ratio);
+            momList.add(momVO);
+        });
+        return momList;
+    }
+
+    /**
+     * 鑾峰彇鑳借�楀悓姣旀暟鎹�
+     */
+    @Override
+    public List<DataAnalysisYoYVO> listWaterDataComparisonYoY(DataAnalysisMoMDTO dto) {
+        List<DataAnalysisYoYVO> yoyList = new ArrayList<>();
+        // 鏌ヨ鐐逛綅涓庣敤鑳藉崟鍏冧俊鎭�
+        List<ModelNodeIndexInfor> nodeInforList = listModelNodeIndexIdRelationInfor(dto.getNodeId());
+        if (CollectionUtils.isEmpty(nodeInforList)) {
+            return yoyList;
+        }
+        List<String> indexIds = nodeInforList.stream().map(ModelNodeIndexInfor::getIndexId).collect(Collectors.toList());
+        // 鎸夌収鐐逛綅杩涜鍒嗙粍
+        Map<String, List<ModelNodeIndexInfor>> nodeIndexMap = nodeInforList.stream().collect(
+                Collectors.groupingBy(ModelNodeIndexInfor::getNodeId));
+        // 鏃堕棿绫诲瀷
+        // 鑾峰彇鏌ヨ鏃堕棿
+        Date beginTime = dto.getBeginTime();
+        Date endTime = dto.getEndTime();
+        // 鍚屾瘮鏃堕棿
+        Date lastTime = DateUtil.offset(beginTime, DateField.YEAR, CommonConst.DIGIT_MINUS_1);
+        Date lastEndTime = DateUtil.offset(endTime, DateField.YEAR, CommonConst.DIGIT_MINUS_1);
+        // 鏌ヨ瀵瑰簲indexIds锛屾壘鍒板搴攄ataItem淇℃伅
+        List<DataItem> dataItemList = dataItemService.getDataItemHourInforByIndexIds(beginTime, endTime, TimeType.HOUR.name(), indexIds);
+        List<DataItem> lastDataItemList = dataItemService.getDataItemHourInforByIndexIds(lastTime, lastEndTime, TimeType.HOUR.name(), indexIds);
+        //  鍊嶇巼
+        BigDecimal multiple = BigDecimal.valueOf(CommonConst.DIGIT_100);
+        nodeIndexMap.forEach((key, value) -> {
+            DataAnalysisYoYVO yoyVO = new DataAnalysisYoYVO();
+            Optional<ModelNodeIndexInfor> first = value.stream().findFirst();
+            first.ifPresent(modelNodeIndexInfor -> yoyVO.setEnergyUnitName(modelNodeIndexInfor.getName()));
+            // 璧嬪�煎崟浣�
+            yoyVO.setUnit("m鲁");
+            // 鎵惧嚭indexIds
+            List<String> indexIdList = value.stream().map(ModelNodeIndexInfor::getIndexId).collect(Collectors.toList());
+            // 姹傚拰
+            BigDecimal sum = BigDecimal.valueOf(dataItemList.stream().filter(li -> indexIdList.contains(li.getIndexId()))
+                    .mapToDouble(DataItem::getValue).sum()).setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP);
+            BigDecimal lastSum = BigDecimal.valueOf(lastDataItemList.stream().filter(li -> indexIdList.contains(li.getIndexId()))
+                    .mapToDouble(DataItem::getValue).sum()).setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP);
+            yoyVO.setCurrentValue(sum);
+            yoyVO.setOldValue(lastSum);
+            //  鍚屾瘮鍊�
+            BigDecimal ratio = BigDecimal.ZERO;
+            if (lastSum.compareTo(BigDecimal.ZERO) != 0) {
+                ratio = sum.subtract(lastSum).divide(lastSum, CommonConst.DIGIT_2, RoundingMode.HALF_UP).multiply(multiple);
+            }
+            yoyVO.setRatio(ratio);
+            yoyList.add(yoyVO);
+        });
+        return yoyList;
+    }
+
+    /**
+     * 鑾峰彇鑳借�楃幆姣旀暟鎹�
+     */
+    @Override
+    public List<DataAnalysisMoMVO> listWaterDataComparisonMoM(DataAnalysisMoMDTO dto) {
+        List<DataAnalysisMoMVO> momList = new ArrayList<>();
+        // 鏍规嵁id鏌ヨ鐐逛綅淇℃伅
+        List<ModelNodeIndexInfor> nodeIndexInforList = listModelNodeIndexIdRelationInfor(dto.getNodeId());
+        if (CollectionUtils.isEmpty(nodeIndexInforList)) {
+            return momList;
+        }
+        List<String> indexIds = nodeIndexInforList.stream().map(ModelNodeIndexInfor::getIndexId).collect(Collectors.toList());
+        Date beginTime = dto.getBeginTime();
+        Date endTime = dto.getEndTime();
+        Date lastTime;
+        Date lastEndTime;
+        String queryTimeType = dto.getTimeType();
+        // 灏忔椂
+        if (TimeTypeConst.TIME_TYPE_HOUR.equals(queryTimeType)) {
+            lastTime = DateUtil.offsetHour(beginTime, CommonConst.DIGIT_MINUS_1);
+            lastEndTime = DateUtil.offsetHour(endTime, CommonConst.DIGIT_MINUS_1);
+            // 澶�
+        } else if (TimeTypeConst.TIME_TYPE_DAY.equals(queryTimeType)) {
+            lastTime = DateUtil.offsetDay(beginTime, CommonConst.DIGIT_MINUS_1);
+            lastEndTime = DateUtil.offsetDay(endTime, CommonConst.DIGIT_MINUS_1);
+            // 鏈�
+        } else if (TimeTypeConst.TIME_TYPE_MONTH.equals(queryTimeType)) {
+            lastTime = DateUtil.offsetMonth(beginTime, CommonConst.DIGIT_MINUS_1);
+            lastEndTime = DateUtil.offsetMonth(endTime, CommonConst.DIGIT_MINUS_1);
+            // 骞�
+        } else {
+            lastTime = DateUtil.offset(beginTime, DateField.YEAR, CommonConst.DIGIT_MINUS_1);
+            lastEndTime = DateUtil.offset(endTime, DateField.YEAR, CommonConst.DIGIT_MINUS_1);
+        }
+        // 鎸夌収鐐逛綅杩涜鍒嗙粍
+        Map<String, List<ModelNodeIndexInfor>> nodeIndexMap = nodeIndexInforList.stream().collect(
+                Collectors.groupingBy(ModelNodeIndexInfor::getNodeId));
+        // 鏌ヨ瀵瑰簲indexIds锛屾壘鍒板搴攄ataItem淇℃伅
+        List<DataItem> dataItemList = dataItemService.getDataItemHourInforByIndexIds(beginTime, endTime, TimeType.HOUR.name(), indexIds);
+        List<DataItem> lastDataItemList = dataItemService.getDataItemHourInforByIndexIds(lastTime, lastEndTime, TimeType.HOUR.name(), indexIds);
+        //  鍊嶇巼
+        BigDecimal multiple = BigDecimal.valueOf(CommonConst.DIGIT_100);
+        nodeIndexMap.forEach((key, value) -> {
+            DataAnalysisMoMVO momVO = new DataAnalysisMoMVO();
+            Optional<ModelNodeIndexInfor> first = value.stream().findFirst();
+            first.ifPresent(modelNodeIndexInfor -> momVO.setEnergyUnitName(modelNodeIndexInfor.getName()));
+            // 璧嬪�煎崟浣�
+            momVO.setUnit("m鲁");
+            // 鎵惧嚭indexIds
+            List<String> indexIdList = value.stream().map(ModelNodeIndexInfor::getIndexId).collect(Collectors.toList());
+            // 姹傚拰
+            BigDecimal sum = BigDecimal.valueOf(dataItemList.stream().filter(li -> indexIdList.contains(li.getIndexId()))
+                    .mapToDouble(DataItem::getValue).sum()).setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP);
+            BigDecimal lastSum = BigDecimal.valueOf(lastDataItemList.stream().filter(li -> indexIdList.contains(li.getIndexId()))
+                    .mapToDouble(DataItem::getValue).sum()).setScale(CommonConst.DIGIT_2, RoundingMode.HALF_UP);
+            momVO.setCurrentValue(sum);
+            momVO.setOldValue(lastSum);
+            //  鍚屾瘮鍊�
+            BigDecimal ratio = BigDecimal.ZERO;
+            if (lastSum.compareTo(BigDecimal.ZERO) != 0) {
+                ratio = sum.subtract(lastSum).divide(lastSum, CommonConst.DIGIT_2, RoundingMode.HALF_UP).multiply(multiple);
+            }
+            momVO.setRatio(ratio);
+            momList.add(momVO);
+        });
+        return momList;
+    }
+
+    /**
+     * 鏌ヨ鐐逛綅涓庣敤鑳藉崟鍏冧俊鎭�
+     */
+    private List<ModelNodeIndexInfor> listModelNodeIndexIdRelationInfor(String nodeId) {
+        List<ModelNodeIndexInfor> nodeInforList = modelNodeService.listModelNodeIndexIdRelationInforByParentId(nodeId);
+        // 濡傛灉鏄┖瀛樺湪涓ょ鎯呭喌锛�1锛歩d鏈夐棶棰橈紝2锛氭渶搴曞眰
+        if (CollectionUtils.isEmpty(nodeInforList)) {
+            List<ModelNodeIndexInfor> inforList = modelNodeService.getModelNodeIndexIdRelationInforByNodeId(nodeId);
+            if (CollectionUtils.isNotEmpty(inforList)) {
+                nodeInforList.addAll(inforList);
+            }
+        }
+        return nodeInforList;
+    }
+
+}
\ No newline at end of file
diff --git a/zhitan-system/src/main/resources/mapper/basicSetup/SysEquipmentfileMapper.xml b/zhitan-system/src/main/resources/mapper/basicSetup/SysEquipmentfileMapper.xml
new file mode 100644
index 0000000..396d884
--- /dev/null
+++ b/zhitan-system/src/main/resources/mapper/basicSetup/SysEquipmentfileMapper.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhitan.basicSetup.mapper.SysEquipmentfileMapper">
+    <resultMap id="SysEquipmentFile"
+               type="com.zhitan.realtimedata.domain.SysEquipmentFile">
+        <result property="nodeId" column="node_id"/>
+        <result property="filePath" column="filepath"/>
+    </resultMap>
+    <resultMap id="SysSvgInfo"
+               type="com.zhitan.realtimedata.domain.SysSvgInfo">
+        <result property="id" column="id"/>
+        <result property="param" column="param"/>
+        <result property="tag" column="tag"/>
+    </resultMap>
+
+    <insert id="saveSettingInfo">
+        delete
+        from sys_svg_info
+        where node_id = #{nodeId};
+
+        <foreach collection="svgInfo" item="info" separator=";">
+            insert into sys_svg_info (id, node_id, param, tag)
+            values (#{info.id}, #{nodeId}, #{info.param}, #{info.tag});
+        </foreach>
+    </insert>
+
+  <update id="saveEquipmentFile">
+    INSERT INTO sys_equipmentfile (node_id, filepath)
+    VALUES(#{nodeId}, #{filePath}) ON CONFLICT (node_id) DO
+    UPDATE
+    SET filepath = excluded.filepath
+  </update>
+
+    <select id="getConfigure" resultMap="SysEquipmentFile">
+        select node_id, filepath
+        from sys_equipmentfile
+        where node_id = #{nodeId};
+    </select>
+
+    <select id="getConfigureTag" resultMap="SysSvgInfo">
+        select id, param, tag
+        from sys_svg_info
+        where node_id = #{nodeId}
+    </select>
+
+</mapper>
diff --git a/zhitan-system/src/main/resources/mapper/dataitem/DataItemMapper.xml b/zhitan-system/src/main/resources/mapper/dataitem/DataItemMapper.xml
index d64ec15..37b928f 100644
--- a/zhitan-system/src/main/resources/mapper/dataitem/DataItemMapper.xml
+++ b/zhitan-system/src/main/resources/mapper/dataitem/DataItemMapper.xml
@@ -3,7 +3,7 @@
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.zhitan.dataitem.mapper.DataItemMapper">
-    <resultMap type="StagseDataEntry" id="stagseDataEntryResult">
+    <resultMap type="com.zhitan.dataitem.domain.StagseDataEntry" id="stagseDataEntryResult">
         <result property="code" column="code"/>
         <result property="name" column="name"/>
         <result property="indexId" column="index_id"/>
@@ -15,7 +15,7 @@
         <result property="dataTime" column="data_time"/>
     </resultMap>
 
-    <select id="getSettingIndex" parameterType="StagseDataEntry" resultMap="stagseDataEntryResult">
+    <select id="getSettingIndex" parameterType="com.zhitan.dataitem.domain.StagseDataEntry" resultMap="stagseDataEntryResult">
 
         SELECT
         ei.index_id,
@@ -33,7 +33,7 @@
         and si.time_type = #{timeType}
         AND si.calc_type = #{calcType}
    </select>
-    <select id="getSettingEdit" parameterType="StagseDataEntry" resultMap="stagseDataEntryResult">
+    <select id="getSettingEdit" parameterType="com.zhitan.dataitem.domain.StagseDataEntry" resultMap="stagseDataEntryResult">
         SELECT
             ei.index_id,
             code,
@@ -54,7 +54,7 @@
             AND data_time &gt;= #{beginTime}
             AND data_time &lt;= #{endTime}
     </select>
-    <select id="stagseDataByCode" parameterType="StagseDataEntry" resultMap="stagseDataEntryResult">
+    <select id="stagseDataByCode" parameterType="com.zhitan.dataitem.domain.StagseDataEntry" resultMap="stagseDataEntryResult">
         SELECT
             ei.index_id,
             code,
@@ -199,4 +199,20 @@
         AND di.data_time BETWEEN   #{beginTime}  AND  #{endTime}
         AND di.time_type =  #{timeType}
     </select>
+
+    <select id="getDataItemHourInforByIndexIds" resultType="com.zhitan.realtimedata.domain.DataItem">
+        SELECT
+        index_id indexId,
+        data_time dataTime,
+        "value"
+        FROM
+        "data_item"
+        WHERE
+        index_id IN
+        <foreach collection="indexIds" item="indexId" open="(" separator="," close=")">
+            #{indexId}
+        </foreach>
+        AND ( begin_time BETWEEN #{beginTime} AND #{endTime} )
+        AND time_type = #{timeType}
+    </select>
 </mapper>
\ No newline at end of file
diff --git a/zhitan-system/src/main/resources/mapper/model/ModelNodeMapper.xml b/zhitan-system/src/main/resources/mapper/model/ModelNodeMapper.xml
index c704454..01c8c59 100644
--- a/zhitan-system/src/main/resources/mapper/model/ModelNodeMapper.xml
+++ b/zhitan-system/src/main/resources/mapper/model/ModelNodeMapper.xml
@@ -382,7 +382,8 @@
         SELECT mn.node_id  nodeId,
                mn."name"   "name",
                ni.index_id indexId,
-               ei.energy_id energyId
+               ei.energy_id energyId,
+               ei.index_type indexType
         FROM "model_node" mn
         LEFT JOIN "node_index" ni ON mn.node_id = ni.node_id
         LEFT JOIN energy_index ei on ni.index_id = ei.index_id
diff --git a/zhitan-system/src/main/resources/mapper/realtimedata/SvgTrendMapper.xml b/zhitan-system/src/main/resources/mapper/realtimedata/SvgTrendMapper.xml
new file mode 100644
index 0000000..699f573
--- /dev/null
+++ b/zhitan-system/src/main/resources/mapper/realtimedata/SvgTrendMapper.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhitan.realtimedata.mapper.SvgTrendMapper">
+    <resultMap type="com.zhitan.model.domain.EnergyIndex" id="EnergyIndexResult">
+        <result property="indexId" column="index_id"/>
+        <result property="name" column="name"/>
+        <result property="code" column="code"/>
+        <result property="indexType" column="index_type"/>
+        <result property="indexCategory" column="index_category"/>
+        <result property="remark" column="remark"/>
+        <result property="unitId" column="unit_id"/>
+        <result property="meterId" column="meter_id"/>
+        <result property="meterName" column="meter_name"/>
+    </resultMap>
+
+    <select id="selectSvgTrendList" parameterType="com.zhitan.model.domain.EnergyIndex" resultMap="EnergyIndexResult">
+        select ei.index_id, name, ei.code, index_type, ei.remark, ei.unit_id, index_category,meter_name
+        from
+        energy_index ei,
+        sys_svg_info svg,
+        meter_implement as me
+        <where>
+            ei.code = svg.tag
+            and ei.meter_id = me.id
+            <if test="name != null  and name != ''">and name like concat('%', #{name}, '%')</if>
+            <if test="code != null  and code != ''">and ei.code like concat('%', #{code}, '%')</if>
+            <if test="indexType != null">and index_type = #{indexType}</if>
+            <if test="nodeId != null  and nodeId != ''">and svg.node_id = #{nodeId}</if>
+            <if test="indexCategory != null  and indexCategory != ''">and index_category =
+                #{indexCategory}
+            </if>
+        </where>
+    </select>
+
+</mapper>
diff --git a/zhitan-vue/src/assets/images/font01.png b/zhitan-vue/src/assets/images/font01.png
new file mode 100644
index 0000000..42bbca9
--- /dev/null
+++ b/zhitan-vue/src/assets/images/font01.png
Binary files differ
diff --git a/zhitan-vue/src/assets/images/img_logo.png b/zhitan-vue/src/assets/images/img_logo.png
new file mode 100644
index 0000000..593b9e6
--- /dev/null
+++ b/zhitan-vue/src/assets/images/img_logo.png
Binary files differ
diff --git a/zhitan-vue/src/assets/images/login-background.jpg b/zhitan-vue/src/assets/images/login-background.jpg
deleted file mode 100644
index 8a89eb8..0000000
--- a/zhitan-vue/src/assets/images/login-background.jpg
+++ /dev/null
Binary files differ
diff --git a/zhitan-vue/src/assets/images/login-background.png b/zhitan-vue/src/assets/images/login-background.png
new file mode 100644
index 0000000..b27391b
--- /dev/null
+++ b/zhitan-vue/src/assets/images/login-background.png
Binary files differ
diff --git a/zhitan-vue/src/assets/images/logo.png b/zhitan-vue/src/assets/images/logo.png
new file mode 100644
index 0000000..35f902b
--- /dev/null
+++ b/zhitan-vue/src/assets/images/logo.png
Binary files differ
diff --git a/zhitan-vue/src/views/login copy.vue b/zhitan-vue/src/views/login copy.vue
new file mode 100644
index 0000000..d9b0c13
--- /dev/null
+++ b/zhitan-vue/src/views/login copy.vue
@@ -0,0 +1,293 @@
+<template>
+  <div class="login">
+    <!-- <div
+      class="login-logo-bg"
+      v-if="systemInfo && systemInfo.homeLogo"
+      :style="{ backgroundImage: 'url(' + systemInfo.homeLogo + ')', backgroundSize: '100% 100%' }"
+    ></div> -->
+    <img v-if="systemInfo && systemInfo.homeLogo" :src="systemInfo.homeLogo" alt="" class="login-logo-img" />
+    <div class="login-font" v-else>{{ systemInfo.systemName || "鑳芥簮绠$悊绯荤粺" }}</div>
+    <el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
+      <!-- <h3 class="title">鍏呯數妗╁悗鍙扮鐞嗙郴缁�</h3> -->
+      <el-form-item prop="username">
+        <el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" placeholder="璐﹀彿">
+          <template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template>
+        </el-input>
+      </el-form-item>
+      <el-form-item prop="password">
+        <el-input
+          v-model="loginForm.password"
+          type="password"
+          size="large"
+          auto-complete="off"
+          placeholder="瀵嗙爜"
+          show-password
+          @keyup.enter="handleLogin"
+        >
+          <template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template>
+        </el-input>
+      </el-form-item>
+      <el-form-item prop="code" v-if="captchaEnabled">
+        <el-input
+          v-model="loginForm.code"
+          size="large"
+          auto-complete="off"
+          placeholder="楠岃瘉鐮�"
+          style="width: 63%"
+          @keyup.enter="handleLogin"
+        >
+          <template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template>
+        </el-input>
+        <div class="login-code">
+          <img :src="codeUrl" @click="getCode" class="login-code-img" />
+        </div>
+      </el-form-item>
+      <el-checkbox v-model="loginForm.rememberMe" style="margin: 0px 0px 25px 0px">璁颁綇瀵嗙爜</el-checkbox>
+      <el-form-item style="width: 100%">
+        <el-button
+          :loading="loading"
+          size="large"
+          type="primary"
+          style="width: 100%"
+          color="#626aef"
+          :dark="isDark"
+          @click.prevent="handleLogin"
+        >
+          <span v-if="!loading">鐧� 褰�</span>
+          <span v-else>鐧� 褰� 涓�...</span>
+        </el-button>
+      </el-form-item>
+    </el-form>
+    <!--  搴曢儴  -->
+    <div class="el-login-footer">
+      <!-- <span>Copyright 漏 2021-2024 ZhiTanCloud All Rights Reserved.</span> -->
+      <span>{{ systemInfo.copyRight || "Copyright 漏 2017-2024 ZhiTanCloud All Rights Reserved." }}</span>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { getCodeImg } from "@/api/login"
+import Cookies from "js-cookie"
+import { encrypt, decrypt } from "@/utils/jsencrypt"
+import useUserStore from "@/store/modules/user"
+
+const userStore = useUserStore()
+const route = useRoute()
+const router = useRouter()
+const { proxy } = getCurrentInstance()
+const systemInfo1 = JSON.parse(Cookies.get("SystemInfo") || "{}")
+const systemInfo = {
+  ...systemInfo1,
+  homeLogo: systemInfo1.homeLogo
+    ? systemInfo1.homeLogo.includes("http")
+      ? systemInfo1.homeLogo
+      : "https://demo-ems.zhitancloud.com" + systemInfo1.homeLogo
+    : "",
+}
+console.log(systemInfo)
+
+const loginForm = ref({
+  username: "admin",
+  password: "admin123",
+  rememberMe: false,
+  code: "",
+  uuid: "",
+})
+
+const loginRules = {
+  username: [{ required: true, trigger: "blur", message: "璇疯緭鍏ユ偍鐨勮处鍙�" }],
+  password: [{ required: true, trigger: "blur", message: "璇疯緭鍏ユ偍鐨勫瘑鐮�" }],
+  code: [{ required: true, trigger: "change", message: "璇疯緭鍏ラ獙璇佺爜" }],
+}
+
+const codeUrl = ref("")
+const loading = ref(false)
+// 楠岃瘉鐮佸紑鍏�
+const captchaEnabled = ref(true)
+// 娉ㄥ唽寮�鍏�
+const register = ref(false)
+const redirect = ref(undefined)
+
+watch(
+  route,
+  (newRoute) => {
+    redirect.value = newRoute.query && newRoute.query.redirect
+  },
+  { immediate: true }
+)
+
+function handleLogin() {
+  proxy.$refs.loginRef.validate((valid) => {
+    if (valid) {
+      loading.value = true
+      // 鍕鹃�変簡闇�瑕佽浣忓瘑鐮佽缃湪 cookie 涓缃浣忕敤鎴峰悕鍜屽瘑鐮�
+      if (loginForm.value.rememberMe) {
+        Cookies.set("username", loginForm.value.username, { expires: 30 })
+        Cookies.set("password", encrypt(loginForm.value.password), { expires: 30 })
+        Cookies.set("rememberMe", loginForm.value.rememberMe, { expires: 30 })
+      } else {
+        // 鍚﹀垯绉婚櫎
+        Cookies.remove("username")
+        Cookies.remove("password")
+        Cookies.remove("rememberMe")
+      }
+      // 璋冪敤action鐨勭櫥褰曟柟娉�
+      userStore
+        .login(loginForm.value)
+        .then(() => {
+          const query = route.query
+          const otherQueryParams = Object.keys(query).reduce((acc, cur) => {
+            if (cur !== "redirect") {
+              acc[cur] = query[cur]
+            }
+            return acc
+          }, {})
+          router.push({ path: redirect.value || "/", query: otherQueryParams })
+        })
+        .catch(() => {
+          loading.value = false
+          // 閲嶆柊鑾峰彇楠岃瘉鐮�
+          if (captchaEnabled.value) {
+            getCode()
+          }
+        })
+    }
+  })
+}
+
+function getCode() {
+  getCodeImg().then((res) => {
+    captchaEnabled.value = res.captchaEnabled === undefined ? true : res.captchaEnabled
+    if (captchaEnabled.value) {
+      codeUrl.value = "data:image/gif;base64," + res.img
+      loginForm.value.uuid = res.uuid
+    }
+  })
+}
+
+function getCookie() {
+  const username = Cookies.get("username")
+  const password = Cookies.get("password")
+  const rememberMe = Cookies.get("rememberMe")
+  loginForm.value = {
+    username: username === undefined ? loginForm.value.username : username,
+    password: password === undefined ? loginForm.value.password : decrypt(password),
+    rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
+  }
+}
+
+getCode()
+getCookie()
+</script>
+
+<style lang="scss" scoped>
+.login {
+  display: flex;
+  align-items: center;
+  height: 100%;
+  background-image: url("@/assets/images/login-bg.jpg");
+  background-size: 100% 100%;
+  flex-direction: column;
+  position: relative;
+  min-width: 700px;
+  min-height: 700px;
+}
+
+.title {
+  margin: 0px auto 30px auto;
+  text-align: center;
+  color: #707070;
+}
+
+.login-form {
+  position: absolute;
+  left: 50%;
+  top: 60%;
+  transform: translate(-50%, -50%);
+  border-radius: 6px;
+  // background: #ffffff;
+  width: 400px;
+  padding: 25px 25px 5px 25px;
+
+  .el-input {
+    height: 40px;
+
+    input {
+      height: 40px;
+    }
+  }
+
+  .input-icon {
+    height: 39px;
+    width: 14px;
+    margin-left: 0px;
+  }
+}
+
+.login-tip {
+  font-size: 13px;
+  text-align: center;
+  color: #bfbfbf;
+}
+
+.login-code {
+  width: 33%;
+  height: 40px;
+  float: right;
+
+  img {
+    cursor: pointer;
+    vertical-align: middle;
+  }
+}
+
+.el-login-footer {
+  height: 40px;
+  line-height: 40px;
+  position: fixed;
+  bottom: 0;
+  width: 100%;
+  text-align: center;
+  color: #fff;
+  font-family: Arial;
+  font-size: 12px;
+  letter-spacing: 1px;
+}
+
+.login-code-img {
+  height: 40px;
+  padding-left: 12px;
+}
+
+.login-logo-bg {
+  width: 514px;
+  height: 177px;
+  // background-image: url('@/assets/images/login-logo.png');
+  // background-size: 100% 100%;
+  position: absolute;
+  left: 50%;
+  top: 22%;
+  transform: translate(-50%, -50%);
+}
+.login-logo-img {
+  // width: 100%;
+  // height: 100%;
+  // transform: translate(-50%, -50%);
+  max-height: 200px;
+  margin: 0 auto;
+  position: absolute;
+  top: 17%;
+}
+
+.login-font {
+  font-size: 50px;
+  color: #fff;
+  top: 32%;
+  position: absolute;
+  left: 50%;
+  width: 514px;
+  text-align: center;
+  transform: translate(-50%, -50%);
+}
+</style>
diff --git a/zhitan-vue/src/views/login.vue b/zhitan-vue/src/views/login.vue
index 86d243f..3e8b868 100644
--- a/zhitan-vue/src/views/login.vue
+++ b/zhitan-vue/src/views/login.vue
@@ -1,67 +1,83 @@
 <template>
   <div class="login">
-    <!-- <div
-      class="login-logo-bg"
-      v-if="systemInfo && systemInfo.homeLogo"
-      :style="{ backgroundImage: 'url(' + systemInfo.homeLogo + ')', backgroundSize: '100% 100%' }"
-    ></div> -->
-    <img v-if="systemInfo && systemInfo.homeLogo" :src="systemInfo.homeLogo" alt="" class="login-logo-img" />
-    <div class="login-font" v-else>{{ systemInfo.systemName || "鑳芥簮绠$悊绯荤粺" }}</div>
-    <el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
-      <!-- <h3 class="title">鍏呯數妗╁悗鍙扮鐞嗙郴缁�</h3> -->
-      <el-form-item prop="username">
-        <el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" placeholder="璐﹀彿">
-          <template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template>
-        </el-input>
-      </el-form-item>
-      <el-form-item prop="password">
-        <el-input
-          v-model="loginForm.password"
-          type="password"
-          size="large"
-          auto-complete="off"
-          placeholder="瀵嗙爜"
-          show-password
-          @keyup.enter="handleLogin"
-        >
-          <template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template>
-        </el-input>
-      </el-form-item>
-      <el-form-item prop="code" v-if="captchaEnabled">
-        <el-input
-          v-model="loginForm.code"
-          size="large"
-          auto-complete="off"
-          placeholder="楠岃瘉鐮�"
-          style="width: 63%"
-          @keyup.enter="handleLogin"
-        >
-          <template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template>
-        </el-input>
-        <div class="login-code">
-          <img :src="codeUrl" @click="getCode" class="login-code-img" />
+    <!-- <img v-if="systemInfo && systemInfo.homeLogo" :src="systemInfo.homeLogo" alt="" class="login-logo-img" />
+    <div class="login-font" v-else>{{ systemInfo.systemName || "鑳芥簮绠$悊绯荤粺" }}</div> -->
+    <!-- 宸︿笂瑙抣ogo -->
+    <div>
+      <img v-if="systemInfo && systemInfo.homeLogo" :src="systemInfo.homeLogo" alt="" class="login-logo-img" />
+    </div>
+
+    <!-- 涓棿閮ㄥ垎form -->
+    <div class="middle-view">
+      <div class="left-wrapper">
+        <div class="login-font">{{ systemInfo.systemName || "" }}</div>
+        <img src="@/assets/images/font01.png" alt="" style="width: 406px" />
+        <img src="@/assets/images/img_logo.png" alt="" style="width: 200px; margin-top: 20px" />
+      </div>
+      <div class="right-wrapper">
+        <div class="header">
+          <span>璐﹀彿鐧诲綍</span>
         </div>
-      </el-form-item>
-      <el-checkbox v-model="loginForm.rememberMe" style="margin: 0px 0px 25px 0px">璁颁綇瀵嗙爜</el-checkbox>
-      <el-form-item style="width: 100%">
-        <el-button
-          :loading="loading"
-          size="large"
-          type="primary"
-          style="width: 100%"
-          color="#626aef"
-          :dark="isDark"
-          @click.prevent="handleLogin"
-        >
-          <span v-if="!loading">鐧� 褰�</span>
-          <span v-else>鐧� 褰� 涓�...</span>
-        </el-button>
-      </el-form-item>
-    </el-form>
+        <div class="bottom-block"></div>
+        <el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form" :label-position="'top'">
+          <el-form-item prop="username" label="璐﹀彿">
+            <el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" placeholder="璐﹀彿">
+              <!-- <template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template> -->
+            </el-input>
+          </el-form-item>
+          <el-form-item prop="password" label="瀵嗙爜">
+            <el-input
+              v-model="loginForm.password"
+              type="password"
+              size="large"
+              auto-complete="off"
+              placeholder="瀵嗙爜"
+              show-password
+              @keyup.enter="handleLogin"
+            >
+              <!-- <template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template> -->
+            </el-input>
+          </el-form-item>
+          <el-form-item prop="code" v-if="captchaEnabled" label="楠岃瘉鐮�">
+            <el-input
+              v-model="loginForm.code"
+              size="large"
+              auto-complete="off"
+              placeholder="楠岃瘉鐮�"
+              style="width: 266px"
+              @keyup.enter="handleLogin"
+            >
+              <!-- <template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template> -->
+            </el-input>
+            <div class="login-code">
+              <img :src="codeUrl" @click="getCode" class="login-code-img" />
+            </div>
+          </el-form-item>
+          <el-checkbox v-model="loginForm.rememberMe" style="margin: 0px 0px 25px 0px">璁颁綇瀵嗙爜</el-checkbox>
+          <el-form-item style="width: 100%">
+            <el-button
+              :loading="loading"
+              size="large"
+              type="primary"
+              style="width: 100%"
+              color="#626aef"
+              :dark="isDark"
+              @click.prevent="handleLogin"
+              class="submit-btn"
+            >
+              <span v-if="!loading">鐧� 褰�</span>
+              <span v-else>鐧� 褰� 涓�...</span>
+            </el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+    </div>
+
     <!--  搴曢儴  -->
     <div class="el-login-footer">
-      <!-- <span>Copyright 漏 2021-2024 ZhiTanCloud All Rights Reserved.</span> -->
-      <span>{{ systemInfo.copyRight || "Copyright 漏 2017-2024 ZhiTanCloud All Rights Reserved." }}</span>
+      <span>{{
+        systemInfo.copyRight || "Copyright 漏 2017-" + new Date().getFullYear() + " ZhiTanCloud All Rights Reserved."
+      }}</span>
     </div>
   </div>
 </template>
@@ -76,12 +92,20 @@
 const route = useRoute()
 const router = useRouter()
 const { proxy } = getCurrentInstance()
-const systemInfo = JSON.parse(Cookies.get("SystemInfo") || "{}")
+const systemInfo1 = JSON.parse(Cookies.get("SystemInfo") || "{}")
+const systemInfo = {
+  ...systemInfo1,
+  homeLogo: systemInfo1.homeLogo
+    ? systemInfo1.homeLogo.includes("http")
+      ? systemInfo1.homeLogo
+      : "https://demo-ems.zhitancloud.com" + systemInfo1.homeLogo
+    : "",
+}
 console.log(systemInfo)
 
 const loginForm = ref({
-  username: "admin",
-  password: "admin123",
+  username: "guestUser",
+  password: "guest@123456",
   rememberMe: false,
   code: "",
   uuid: "",
@@ -178,29 +202,93 @@
   display: flex;
   align-items: center;
   height: 100%;
-  background-image: url("@/assets/images/login-bg.jpg");
-  background-size: 100% 100%;
+  background-image: url("@/assets/images/login-background.png");
+  background-repeat: no-repeat;
+  background-size: cover;
   flex-direction: column;
   position: relative;
   min-width: 700px;
   min-height: 700px;
 }
 
-.title {
-  margin: 0px auto 30px auto;
-  text-align: center;
-  color: #707070;
+.middle-view {
+  display: flex;
+  align-items: center;
+  justify-content: space-around;
+  height: 100%;
+  width: 1200px;
+  .left-wrapper {
+    width: 420px;
+    display: flex;
+    flex-direction: column;
+  }
+  .login-font {
+    font-size: 34px;
+    font-weight: 700;
+    color: #d5f8ff;
+    margin-bottom: 12px;
+  }
+}
+
+.right-wrapper {
+  border-radius: 23px;
+  background: #ffffff;
+  width: 480px;
+  position: relative;
+  .header {
+    height: 70px;
+    line-height: 70px;
+    border-bottom: 1px solid #f1f1f1;
+    color: #3b3b3b;
+    font-size: 22px;
+    margin-bottom: 22px;
+    span {
+      display: inline-block;
+      height: 70px;
+      line-height: 70px;
+      border-bottom: 6px solid #3a83fc;
+      margin-left: 50px;
+    }
+  }
+}
+
+:deep(.el-input__wrapper) {
+  background-color: #f7f8fa !important;
+  border: none;
+}
+:deep(.el-input__inner) {
+  color: #3b3b3b;
+}
+:deep(.el-form-item__label) {
+  color: #3b3b3b !important;
+}
+:deep(.el-checkbox__label) {
+  color: #2e2e2e;
+}
+
+.bottom-block {
+  height: 140px;
+  width: 90%;
+  background-color: rgba(255, 255, 255, 0.3);
+  position: absolute;
+  left: 5%;
+  bottom: -20px;
+  border-radius: 20px;
 }
 
 .login-form {
-  position: absolute;
-  left: 50%;
-  top: 60%;
-  transform: translate(-50%, -50%);
-  border-radius: 6px;
-  // background: #ffffff;
-  width: 400px;
-  padding: 25px 25px 5px 25px;
+  padding: 0 50px 30px;
+
+  .submit-btn {
+    width: 382px;
+    height: 54px;
+    background: #3a83fc;
+    border-radius: 3px;
+    font-size: 20px;
+    box-shadow: 1px 2px 5px #3a83fc;
+    border: none;
+    border-radius: 6px;
+  }
 
   .el-input {
     height: 40px;
@@ -224,7 +312,7 @@
 }
 
 .login-code {
-  width: 33%;
+  // width: 120px;
   height: 40px;
   float: right;
 
@@ -232,54 +320,29 @@
     cursor: pointer;
     vertical-align: middle;
   }
+  .login-code-img {
+    height: 40px;
+    // padding-left: 12px;
+  }
 }
 
+.login-logo-img {
+  max-height: 100px;
+  margin: 0 auto;
+  position: absolute;
+  top: 35px;
+  left: 65px;
+}
 .el-login-footer {
-  height: 40px;
-  line-height: 40px;
+  height: 60px;
+  line-height: 60px;
   position: fixed;
   bottom: 0;
   width: 100%;
   text-align: center;
   color: #fff;
   font-family: Arial;
-  font-size: 12px;
+  font-size: 16px;
   letter-spacing: 1px;
-}
-
-.login-code-img {
-  height: 40px;
-  padding-left: 12px;
-}
-
-.login-logo-bg {
-  width: 514px;
-  height: 177px;
-  // background-image: url('@/assets/images/login-logo.png');
-  // background-size: 100% 100%;
-  position: absolute;
-  left: 50%;
-  top: 22%;
-  transform: translate(-50%, -50%);
-}
-.login-logo-img {
-  // width: 100%;
-  // height: 100%;
-  // transform: translate(-50%, -50%);
-  max-height: 200px;
-  margin: 0 auto;
-  position: absolute;
-  top: 17%;
-}
-
-.login-font {
-  font-size: 50px;
-  color: #fff;
-  top: 32%;
-  position: absolute;
-  left: 50%;
-  width: 514px;
-  text-align: center;
-  transform: translate(-50%, -50%);
 }
 </style>

--
Gitblit v1.9.3