From 6c5150dfdd69a9c1d5db9c9780f721759b0e0e9c Mon Sep 17 00:00:00 2001
From: VVT789 <sdxt_0802@163.com>
Date: 星期一, 10 二月 2025 17:26:56 +0800
Subject: [PATCH] Merge branch 'develop1.0' into wt_from_develop1.0

---
 zhitan-system/src/main/java/com/zhitan/history/domain/dto/HistoricalDataDTO.java                     |   63 +
 zhitan-vue/src/api/svg/equipmentfile.js                                                              |   40 
 zhitan-vue/src/assets/images/login-background.jpg                                                    |    0 
 zhitan-vue/src/views/login.vue                                                                       |   38 
 zhitan-vue/src/views/svg/components/configureView.vue                                                |  124 ++
 zhitan-system/src/main/java/com/zhitan/basicSetup/service/impl/SysEquipmentfileServiceImpl.java      |   59 +
 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/energyMonitor/service/IEnergyUnitToDeviceService.java         |  100 +
 zhitan-vue/public/logo.png                                                                           |    0 
 zhitan-admin/src/main/java/com/zhitan/web/controller/basicSetup/SysEquipmentfileController.java      |   91 +
 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-vue/src/components/FileUpload/index.vue                                                       |   12 
 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-vue/index.html                                                                                |  385 +++---
 zhitan-admin/src/main/java/com/zhitan/web/controller/history/HistoryDataTrendController.java         |  224 ++++
 zhitan-system/src/main/java/com/zhitan/energyMonitor/mapper/EnergyUnitToDeviceMapper.java            |   38 
 zhitan-vue/src/views/svg/equipmentfile/index.vue                                                     |  243 ++++
 zhitan-vue/src/views/index.vue                                                                       |    4 
 zhitan-common/src/main/java/com/zhitan/common/config/BaseConfig.java                                 |    4 
 /dev/null                                                                                            |  293 -----
 zhitan-vue/src/views/svg/components/configure.vue                                                    |  204 +++
 zhitan-system/src/main/java/com/zhitan/realtimedata/service/RealtimeDatabaseService.java             |   14 
 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-vue/src/views/svg/equipmentfile/chartView.vue                                                 |  314 +++++
 zhitan-vue/package.json                                                                              |    2 
 zhitan-system/src/main/java/com/zhitan/energyMonitor/domain/vo/ListElectricityMeterVO.java           |   20 
 zhitan-system/src/main/java/com/zhitan/realtimedata/data/RealtimeDatabaseManager.java                |  163 +++
 35 files changed, 2,628 insertions(+), 510 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-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-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/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/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/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/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-vue/index.html b/zhitan-vue/index.html
index 3b22332..756ed87 100644
--- a/zhitan-vue/index.html
+++ b/zhitan-vue/index.html
@@ -1,215 +1,214 @@
 <!DOCTYPE html>
 <html>
-
-<head>
-  <meta charset="utf-8">
-  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
-  <meta name="renderer" content="webkit">
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
-  <link rel="icon" href="/favicon.ico">
-  <title>绠$悊绯荤粺</title>
-  <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
-  <style>
-    html,
-    body,
-    #app {
-      height: 100%;
-      margin: 0px;
-      padding: 0px;
-    }
-
-    .chromeframe {
-      margin: 0.2em 0;
-      background: #ccc;
-      color: #000;
-      padding: 0.2em 0;
-    }
-
-    #loader-wrapper {
-      position: fixed;
-      top: 0;
-      left: 0;
-      width: 100%;
-      height: 100%;
-      z-index: 999999;
-    }
-
-    #loader {
-      display: block;
-      position: relative;
-      left: 50%;
-      top: 50%;
-      width: 150px;
-      height: 150px;
-      margin: -75px 0 0 -75px;
-      border-radius: 50%;
-      border: 3px solid transparent;
-      border-top-color: #FFF;
-      -webkit-animation: spin 2s linear infinite;
-      -ms-animation: spin 2s linear infinite;
-      -moz-animation: spin 2s linear infinite;
-      -o-animation: spin 2s linear infinite;
-      animation: spin 2s linear infinite;
-      z-index: 1001;
-    }
-
-    #loader:before {
-      content: "";
-      position: absolute;
-      top: 5px;
-      left: 5px;
-      right: 5px;
-      bottom: 5px;
-      border-radius: 50%;
-      border: 3px solid transparent;
-      border-top-color: #FFF;
-      -webkit-animation: spin 3s linear infinite;
-      -moz-animation: spin 3s linear infinite;
-      -o-animation: spin 3s linear infinite;
-      -ms-animation: spin 3s linear infinite;
-      animation: spin 3s linear infinite;
-    }
-
-    #loader:after {
-      content: "";
-      position: absolute;
-      top: 15px;
-      left: 15px;
-      right: 15px;
-      bottom: 15px;
-      border-radius: 50%;
-      border: 3px solid transparent;
-      border-top-color: #FFF;
-      -moz-animation: spin 1.5s linear infinite;
-      -o-animation: spin 1.5s linear infinite;
-      -ms-animation: spin 1.5s linear infinite;
-      -webkit-animation: spin 1.5s linear infinite;
-      animation: spin 1.5s linear infinite;
-    }
-
-
-    @-webkit-keyframes spin {
-      0% {
-        -webkit-transform: rotate(0deg);
-        -ms-transform: rotate(0deg);
-        transform: rotate(0deg);
+  <head>
+    <meta charset="utf-8" />
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+    <meta name="renderer" content="webkit" />
+    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
+    <link rel="icon" href="/logo.png" />
+    <title>绠$悊绯荤粺</title>
+    <!--[if lt IE 11
+      ]><script>
+        window.location.href = "/html/ie.html"
+      </script><!
+    [endif]-->
+    <style>
+      html,
+      body,
+      #app {
+        height: 100%;
+        margin: 0px;
+        padding: 0px;
       }
 
-      100% {
-        -webkit-transform: rotate(360deg);
-        -ms-transform: rotate(360deg);
-        transform: rotate(360deg);
-      }
-    }
-
-    @keyframes spin {
-      0% {
-        -webkit-transform: rotate(0deg);
-        -ms-transform: rotate(0deg);
-        transform: rotate(0deg);
+      .chromeframe {
+        margin: 0.2em 0;
+        background: #ccc;
+        color: #000;
+        padding: 0.2em 0;
       }
 
-      100% {
-        -webkit-transform: rotate(360deg);
-        -ms-transform: rotate(360deg);
-        transform: rotate(360deg);
+      #loader-wrapper {
+        position: fixed;
+        top: 0;
+        left: 0;
+        width: 100%;
+        height: 100%;
+        z-index: 999999;
       }
-    }
 
+      #loader {
+        display: block;
+        position: relative;
+        left: 50%;
+        top: 50%;
+        width: 150px;
+        height: 150px;
+        margin: -75px 0 0 -75px;
+        border-radius: 50%;
+        border: 3px solid transparent;
+        border-top-color: #fff;
+        -webkit-animation: spin 2s linear infinite;
+        -ms-animation: spin 2s linear infinite;
+        -moz-animation: spin 2s linear infinite;
+        -o-animation: spin 2s linear infinite;
+        animation: spin 2s linear infinite;
+        z-index: 1001;
+      }
 
-    #loader-wrapper .loader-section {
-      position: fixed;
-      top: 0;
-      width: 51%;
-      height: 100%;
-      background: #7171C6;
-      z-index: 1000;
-      -webkit-transform: translateX(0);
-      -ms-transform: translateX(0);
-      transform: translateX(0);
-    }
+      #loader:before {
+        content: "";
+        position: absolute;
+        top: 5px;
+        left: 5px;
+        right: 5px;
+        bottom: 5px;
+        border-radius: 50%;
+        border: 3px solid transparent;
+        border-top-color: #fff;
+        -webkit-animation: spin 3s linear infinite;
+        -moz-animation: spin 3s linear infinite;
+        -o-animation: spin 3s linear infinite;
+        -ms-animation: spin 3s linear infinite;
+        animation: spin 3s linear infinite;
+      }
 
-    #loader-wrapper .loader-section.section-left {
-      left: 0;
-    }
+      #loader:after {
+        content: "";
+        position: absolute;
+        top: 15px;
+        left: 15px;
+        right: 15px;
+        bottom: 15px;
+        border-radius: 50%;
+        border: 3px solid transparent;
+        border-top-color: #fff;
+        -moz-animation: spin 1.5s linear infinite;
+        -o-animation: spin 1.5s linear infinite;
+        -ms-animation: spin 1.5s linear infinite;
+        -webkit-animation: spin 1.5s linear infinite;
+        animation: spin 1.5s linear infinite;
+      }
 
-    #loader-wrapper .loader-section.section-right {
-      right: 0;
-    }
+      @-webkit-keyframes spin {
+        0% {
+          -webkit-transform: rotate(0deg);
+          -ms-transform: rotate(0deg);
+          transform: rotate(0deg);
+        }
 
+        100% {
+          -webkit-transform: rotate(360deg);
+          -ms-transform: rotate(360deg);
+          transform: rotate(360deg);
+        }
+      }
 
-    .loaded #loader-wrapper .loader-section.section-left {
-      -webkit-transform: translateX(-100%);
-      -ms-transform: translateX(-100%);
-      transform: translateX(-100%);
-      -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
-      transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
-    }
+      @keyframes spin {
+        0% {
+          -webkit-transform: rotate(0deg);
+          -ms-transform: rotate(0deg);
+          transform: rotate(0deg);
+        }
 
-    .loaded #loader-wrapper .loader-section.section-right {
-      -webkit-transform: translateX(100%);
-      -ms-transform: translateX(100%);
-      transform: translateX(100%);
-      -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
-      transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
-    }
+        100% {
+          -webkit-transform: rotate(360deg);
+          -ms-transform: rotate(360deg);
+          transform: rotate(360deg);
+        }
+      }
 
-    .loaded #loader {
-      opacity: 0;
-      -webkit-transition: all 0.3s ease-out;
-      transition: all 0.3s ease-out;
-    }
+      #loader-wrapper .loader-section {
+        position: fixed;
+        top: 0;
+        width: 51%;
+        height: 100%;
+        background: #7171c6;
+        z-index: 1000;
+        -webkit-transform: translateX(0);
+        -ms-transform: translateX(0);
+        transform: translateX(0);
+      }
 
-    .loaded #loader-wrapper {
-      visibility: hidden;
-      -webkit-transform: translateY(-100%);
-      -ms-transform: translateY(-100%);
-      transform: translateY(-100%);
-      -webkit-transition: all 0.3s 1s ease-out;
-      transition: all 0.3s 1s ease-out;
-    }
+      #loader-wrapper .loader-section.section-left {
+        left: 0;
+      }
 
-    .no-js #loader-wrapper {
-      display: none;
-    }
+      #loader-wrapper .loader-section.section-right {
+        right: 0;
+      }
 
-    .no-js h1 {
-      color: #222222;
-    }
+      .loaded #loader-wrapper .loader-section.section-left {
+        -webkit-transform: translateX(-100%);
+        -ms-transform: translateX(-100%);
+        transform: translateX(-100%);
+        -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
+        transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
+      }
 
-    #loader-wrapper .load_title {
-      font-family: 'Open Sans';
-      color: #FFF;
-      font-size: 19px;
-      width: 100%;
-      text-align: center;
-      z-index: 9999999999999;
-      position: absolute;
-      top: 60%;
-      opacity: 1;
-      line-height: 30px;
-    }
+      .loaded #loader-wrapper .loader-section.section-right {
+        -webkit-transform: translateX(100%);
+        -ms-transform: translateX(100%);
+        transform: translateX(100%);
+        -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
+        transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
+      }
 
-    #loader-wrapper .load_title span {
-      font-weight: normal;
-      font-style: italic;
-      font-size: 13px;
-      color: #FFF;
-      opacity: 0.5;
-    }
-  </style>
-</head>
+      .loaded #loader {
+        opacity: 0;
+        -webkit-transition: all 0.3s ease-out;
+        transition: all 0.3s ease-out;
+      }
 
-<body>
-  <div id="app">
-    <div id="loader-wrapper">
-      <div id="loader"></div>
-      <div class="loader-section section-left"></div>
-      <div class="loader-section section-right"></div>
-      <div class="load_title">姝e湪鍔犺浇,璇疯�愬績绛夊緟</div>
+      .loaded #loader-wrapper {
+        visibility: hidden;
+        -webkit-transform: translateY(-100%);
+        -ms-transform: translateY(-100%);
+        transform: translateY(-100%);
+        -webkit-transition: all 0.3s 1s ease-out;
+        transition: all 0.3s 1s ease-out;
+      }
+
+      .no-js #loader-wrapper {
+        display: none;
+      }
+
+      .no-js h1 {
+        color: #222222;
+      }
+
+      #loader-wrapper .load_title {
+        font-family: "Open Sans";
+        color: #fff;
+        font-size: 19px;
+        width: 100%;
+        text-align: center;
+        z-index: 9999999999999;
+        position: absolute;
+        top: 60%;
+        opacity: 1;
+        line-height: 30px;
+      }
+
+      #loader-wrapper .load_title span {
+        font-weight: normal;
+        font-style: italic;
+        font-size: 13px;
+        color: #fff;
+        opacity: 0.5;
+      }
+    </style>
+  </head>
+
+  <body>
+    <div id="app">
+      <div id="loader-wrapper">
+        <div id="loader"></div>
+        <div class="loader-section section-left"></div>
+        <div class="loader-section section-right"></div>
+        <div class="load_title">姝e湪鍔犺浇,璇疯�愬績绛夊緟</div>
+      </div>
     </div>
-  </div>
-  <script type="module" src="/src/main.js"></script>
-</body>
-
-</html>
\ No newline at end of file
+    <script type="module" src="/src/main.js"></script>
+  </body>
+</html>
diff --git a/zhitan-vue/package.json b/zhitan-vue/package.json
index c9e26a4..1f3c3cb 100644
--- a/zhitan-vue/package.json
+++ b/zhitan-vue/package.json
@@ -7,7 +7,7 @@
   "type": "module",
   "scripts": {
     "dev": "vite",
-    "build:prod": "vite build",
+    "build": "vite build",
     "build:stage": "vite build --mode staging",
     "preview": "vite preview"
   },
diff --git a/zhitan-vue/public/logo.png b/zhitan-vue/public/logo.png
new file mode 100644
index 0000000..2e6aab6
--- /dev/null
+++ b/zhitan-vue/public/logo.png
Binary files differ
diff --git a/zhitan-vue/src/api/svg/equipmentfile.js b/zhitan-vue/src/api/svg/equipmentfile.js
new file mode 100644
index 0000000..ecdeb36
--- /dev/null
+++ b/zhitan-vue/src/api/svg/equipmentfile.js
@@ -0,0 +1,40 @@
+import request from "@/utils/request"
+
+// 淇敼缁勬�佸浘
+export function updateEquipmentfile(data) {
+  return request({
+    url: "/basicSetup/equipmentfile",
+    method: "put",
+    data: data,
+  })
+}
+
+export function getAllCollectTag(data) {
+  return request({
+    url: "/basicsetting/energyindex/filter",
+    method: "get",
+    params: data,
+  })
+}
+
+export function saveSettingApi(nodeId, data) {
+  return request({
+    url: "/basicSetup/equipmentfile/setting/" + nodeId,
+    method: "put",
+    data: data,
+  })
+}
+
+export function getConfigure(nodeId) {
+  return request({
+    url: "/basicSetup/equipmentfile/configure/" + nodeId,
+    method: "get",
+  })
+}
+
+export function getLiveData(tagCodes) {
+  return request({
+    url: "/rtdb/retrieve/" + tagCodes,
+    method: "get",
+  })
+}
diff --git a/zhitan-vue/src/assets/images/login-background.jpg b/zhitan-vue/src/assets/images/login-background.jpg
new file mode 100644
index 0000000..9194e14
--- /dev/null
+++ b/zhitan-vue/src/assets/images/login-background.jpg
Binary files differ
diff --git a/zhitan-vue/src/components/FileUpload/index.vue b/zhitan-vue/src/components/FileUpload/index.vue
index 044aeda..a1746dd 100644
--- a/zhitan-vue/src/components/FileUpload/index.vue
+++ b/zhitan-vue/src/components/FileUpload/index.vue
@@ -13,9 +13,14 @@
       :headers="headers"
       class="upload-file-uploader"
       ref="fileUpload"
+      :drag="draggable"
     >
       <!-- 涓婁紶鎸夐挳 -->
-      <el-button type="primary">閫夊彇鏂囦欢</el-button>
+      <el-button v-if="!draggable" type="primary">閫夊彇鏂囦欢</el-button>
+      <div v-else>
+        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
+        <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
+      </div>
     </el-upload>
     <!-- 涓婁紶鎻愮ず -->
     <div class="el-upload__tip" v-if="showTip">
@@ -66,6 +71,11 @@
     type: Boolean,
     default: true,
   },
+  // 鏄惁鎷栨嫿涓婁紶
+  draggable: {
+    type: Boolean,
+    default: false,
+  },
 })
 
 const { proxy } = getCurrentInstance()
diff --git a/zhitan-vue/src/views/index.vue b/zhitan-vue/src/views/index.vue
index 8c988a0..2474cd7 100644
--- a/zhitan-vue/src/views/index.vue
+++ b/zhitan-vue/src/views/index.vue
@@ -379,7 +379,7 @@
             right: "5%",
             itemWidth: 14,
             itemHeight: 14,
-            itemGap: 60,
+            itemGap: 16,
             textStyle: {
               align: "left",
               verticalAlign: "middle",
@@ -777,7 +777,7 @@
             right: "10%",
             itemWidth: 14,
             itemHeight: 14,
-            itemGap: 50,
+            itemGap: 16,
             textStyle: {
               align: "left",
               verticalAlign: "middle",
diff --git a/zhitan-vue/src/views/login copy.vue b/zhitan-vue/src/views/login copy.vue
deleted file mode 100644
index d9b0c13..0000000
--- a/zhitan-vue/src/views/login copy.vue
+++ /dev/null
@@ -1,293 +0,0 @@
-<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 3e8b868..2fe18dd 100644
--- a/zhitan-vue/src/views/login.vue
+++ b/zhitan-vue/src/views/login.vue
@@ -11,8 +11,8 @@
     <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" />
+        <img src="@/assets/images/font01.png" alt="" style="width: 380px" />
+        <img src="@/assets/images/img_logo.png" alt="" style="width: 180px; margin-top: 20px" />
       </div>
       <div class="right-wrapper">
         <div class="header">
@@ -44,7 +44,7 @@
               size="large"
               auto-complete="off"
               placeholder="楠岃瘉鐮�"
-              style="width: 266px"
+              style="width: 230px"
               @keyup.enter="handleLogin"
             >
               <!-- <template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template> -->
@@ -202,7 +202,7 @@
   display: flex;
   align-items: center;
   height: 100%;
-  background-image: url("@/assets/images/login-background.png");
+  background-image: url("@/assets/images/login-background.jpg");
   background-repeat: no-repeat;
   background-size: cover;
   flex-direction: column;
@@ -223,31 +223,31 @@
     flex-direction: column;
   }
   .login-font {
-    font-size: 34px;
+    font-size: 32px;
     font-weight: 700;
     color: #d5f8ff;
-    margin-bottom: 12px;
+    margin-bottom: 10px;
   }
 }
 
 .right-wrapper {
   border-radius: 23px;
   background: #ffffff;
-  width: 480px;
+  width: 410px;
   position: relative;
   .header {
-    height: 70px;
-    line-height: 70px;
+    height: 56px;
+    line-height: 56px;
     border-bottom: 1px solid #f1f1f1;
     color: #3b3b3b;
-    font-size: 22px;
+    font-size: 18px;
     margin-bottom: 22px;
     span {
       display: inline-block;
-      height: 70px;
-      line-height: 70px;
-      border-bottom: 6px solid #3a83fc;
-      margin-left: 50px;
+      height: 56px;
+      line-height: 62px;
+      border-bottom: 4px solid #3a83fc;
+      margin-left: 32px;
     }
   }
 }
@@ -277,14 +277,14 @@
 }
 
 .login-form {
-  padding: 0 50px 30px;
+  padding: 0 32px 20px;
 
   .submit-btn {
-    width: 382px;
-    height: 54px;
+    width: 360px;
+    height: 44px;
     background: #3a83fc;
     border-radius: 3px;
-    font-size: 20px;
+    font-size: 18px;
     box-shadow: 1px 2px 5px #3a83fc;
     border: none;
     border-radius: 6px;
@@ -342,7 +342,7 @@
   text-align: center;
   color: #fff;
   font-family: Arial;
-  font-size: 16px;
+  font-size: 14px;
   letter-spacing: 1px;
 }
 </style>
diff --git a/zhitan-vue/src/views/svg/components/configure.vue b/zhitan-vue/src/views/svg/components/configure.vue
new file mode 100644
index 0000000..7137b94
--- /dev/null
+++ b/zhitan-vue/src/views/svg/components/configure.vue
@@ -0,0 +1,204 @@
+<template>
+  <div>
+    <div slot="header" class="clearfix">
+      <el-button
+        style="float: right; padding: 8px; margin-left: 8px"
+        type="text"
+        icon="el-icon-setting"
+        @click="saveSetting"
+      >
+        淇濆瓨閰嶇疆
+      </el-button>
+      <el-button
+        style="float: right; padding: 8px; margin-left: 8px"
+        type="text"
+        icon="el-icon-setting"
+        @click="reset()"
+      >
+        閲嶆柊閫夋嫨搴曞浘
+      </el-button>
+    </div>
+    <el-row>
+      <el-col :span="18">
+        <!-- v-if="filePath === '绌鸿妭鐐�'" -->
+        <div style="text-align: center; margin-left: 12px" v-if="filePath === '绌鸿妭鐐�'">
+          <FileUpload
+            :modelValue="fileList"
+            @update:modelValue="fileUploadChange"
+            :isShowTip="false"
+            :limit="1"
+            :fileSize="20"
+            :fileType="[]"
+            :draggable="true"
+          />
+        </div>
+
+        <div id="svgHtml" v-if="filePath !== '绌鸿妭鐐�'">
+          <div v-html="svgHtml" />
+        </div>
+      </el-col>
+      <el-col :span="6" style="height: calc(100vh - 165px); overflow: auto">
+        <el-table :data="tags" border>
+          <el-table-column label="鍙傛暟" align="center" prop="param" />
+          <el-table-column label="閲囬泦鐐�" align="center" prop="tag">
+            <template #default="scope">
+              <el-autocomplete
+                popper-class="my-autocomplete"
+                v-model="scope.row['tag']"
+                :fetch-suggestions="querySearch"
+                placeholder="璇疯緭鍏ユ寚鏍囩紪鐮�"
+                placement="bottom-end"
+              >
+                <template #default="{ item }">
+                  <div class="">{{ item.value }}</div>
+                  <span class="" style="color: #409eff; display: block">{{ item.name }}</span>
+                </template>
+              </el-autocomplete>
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script setup>
+import { getAllCollectTag, getConfigure, saveSettingApi, updateEquipmentfile } from "@/api/svg/equipmentfile"
+const { proxy } = getCurrentInstance()
+let props = defineProps(["types"])
+const emit = defineEmits(["getList"])
+const currentNode = ref({})
+const filePath = ref("绌鸿妭鐐�")
+const svgHtml = ref("")
+const form = ref({
+  nodeId: "",
+  fileName: "",
+  svgType: "",
+})
+const tags = ref([])
+const fileList = ref([])
+
+function changeModelNode(modelNode) {
+  currentNode.value = modelNode
+  filePath.value = "绌鸿妭鐐�"
+  getConfigure(modelNode.id).then((response) => {
+    tags.value = []
+    svgHtml.value = ""
+    if (response.code === 200) {
+      if (response.data) {
+        filePath.value = response.data.filePath
+        tags.value = response.data.infoList
+        getSvg()
+      }
+    } else {
+      proxy.$modal.msgError(response.msg)
+    }
+  })
+}
+// 鍒濆鍖杝vg
+function getSvg() {
+  /* 鍒涘缓xhr瀵硅薄 */
+  const xhr = new XMLHttpRequest()
+  xhr.open("GET", filePath.value, true)
+  xhr.send()
+  /* 鐩戝惉xhr瀵硅薄 */
+  xhr.addEventListener("load", () => {
+    svgHtml.value = xhr.responseText
+    let values = xhr.responseXML.getElementsByTagName("text")
+    let tagTemps = []
+    for (let i = 0; i < values.length; i++) {
+      if (values[i].getAttribute("id") != undefined)
+        tagTemps.push({
+          param: values[i].textContent,
+          tag: "",
+          tagType: "COLLECT",
+        })
+    }
+    console.log(tags.value.length, tagTemps.length)
+    if (tags.value.length === 0 || tags.value.length != tagTemps.length) {
+      tags.value = []
+      tags.value = tagTemps
+      console.log("222", tags.value.length, tagTemps.length)
+    }
+  })
+}
+//涓婁紶鎴愬姛鍚�
+function fileUploadChange(val) {
+  if (val.length) {
+    // this.$refs.upload.clearFiles()
+    form.value.nodeId = currentNode.value.id
+    form.value.filePath = val[0].fullUrl
+    form.value.svgType = "COLLECT"
+    updateEquipmentfile(form.value).then((result) => {
+      if (result.code === 200) {
+        filePath.value = response.msg
+        tags.value = []
+        getSvg()
+      } else {
+        proxy.$modal.msgError(result.msg)
+      }
+    })
+  } else {
+    proxy.$modal.msgError(response.msg)
+  }
+}
+
+function querySearch(queryString, cb) {
+  if (queryString) {
+    getAllCollectTag({
+      codeOrName: queryString,
+      indexType: "COLLECT",
+    }).then((response) => {
+      // 璋冪敤 callback 杩斿洖寤鸿鍒楄〃鐨勬暟鎹�
+      let result = response.data
+      let values = []
+      result.forEach((item) => {
+        values.push({
+          value: item.code,
+          name: item.name,
+        })
+      })
+      cb(values)
+    })
+  }
+}
+function saveSetting() {
+  saveSettingApi(currentNode.value.id, tags.value).then((response) => {
+    if (response.code === 200) {
+      proxy.$modal.msgSuccess(response.msg)
+    } else {
+      proxy.$modal.msgError(response.msg)
+    }
+  })
+}
+function reset() {
+  filePath.value = "绌鸿妭鐐�"
+}
+
+defineExpose({ changeModelNode })
+</script>
+
+<style lang="scss" scoped>
+.el-autocomplete {
+  width: 100%;
+}
+
+.my-autocomplete li {
+  line-height: normal;
+  padding: 7px;
+}
+
+.my-autocomplete li .name {
+  text-overflow: ellipsis;
+  overflow: hidden;
+}
+
+.my-autocomplete li .addr {
+  font-size: 12px;
+  color: #b4b4b4;
+}
+
+.my-autocomplete li .highlighted .addr {
+  color: #ddd;
+}
+</style>
diff --git a/zhitan-vue/src/views/svg/components/configureView.vue b/zhitan-vue/src/views/svg/components/configureView.vue
new file mode 100644
index 0000000..46eed3f
--- /dev/null
+++ b/zhitan-vue/src/views/svg/components/configureView.vue
@@ -0,0 +1,124 @@
+<template>
+  <div>
+    <div v-if="filePath" v-html="svgHtml" />
+    <div v-else>鏆傛湭涓婁紶</div>
+  </div>
+</template>
+
+<script setup>
+import { getConfigure, getLiveData } from "@/api/svg/equipmentfile"
+import { onMounted } from "vue"
+const { proxy } = getCurrentInstance()
+let props = defineProps(["nodeId"])
+const emit = defineEmits(["getList"])
+const currentNode = ref({})
+const filePath = ref("")
+const svgHtml = ref("")
+const form = ref({
+  nodeId: "",
+  fileName: "",
+  svgType: "",
+})
+const tags = ref([])
+const tagCodes = ref([])
+const valueItems = ref(null)
+const timer = ref(null)
+
+function show(nodeId) {
+  console.log(nodeId)
+  tagCodes.value = []
+  filePath.value = ""
+  getConfigure(nodeId).then((response) => {
+    tags.value = []
+    svgHtml.value = ""
+    if (response.code === 200) {
+      if (response.data) {
+        filePath.value = response.data.filePath
+        tags.value = response.data.infoList
+        getSvg()
+        refresh()
+      }
+    } else {
+      proxy.$modal.msgError(response.msg)
+    }
+  })
+}
+
+function refresh() {
+  if (tagCodes.value.length === 0) {
+    return
+  }
+  getLiveData(tagCodes.value).then((response) => {
+    if (response.code === 200) {
+      if (response.data) {
+        response.data.forEach((tagValue) => {
+          let value = ""
+          if (tagValue.value) {
+            value = parseFloat(tagValue.value).toFixed(2)
+          } else {
+            value = "0"
+          }
+
+          let el = document.getElementById(tagValue.tagCode)
+          if (el) {
+            el.textContent = value
+          }
+        })
+        //杩欏潡鏄崟鐙姞鐨� 鐢ㄦ潵澶勭悊 娌℃湁鎸囨爣鎴栬�呮寚鏍囨病鏈夌粨鏋滅殑 閮借缃�0
+        let allText = document.getElementsByTagName("text")
+        for (let i = 0; i < allText.length; i++) {
+          // console.log(i + "textContent=" + allText[i].textContent);
+          if (allText[i].textContent == null || allText[i].textContent == "") {
+            allText[i].textContent = "0"
+          }
+        }
+      }
+    }
+  })
+}
+
+function refreshData() {
+  timer.value = setInterval(() => {
+    refresh()
+  }, 3000)
+}
+
+onMounted(() => {
+  refreshData()
+})
+
+onBeforeUnmount(() => {
+  clearInterval(timer.value)
+})
+
+// 鍒濆鍖杝vg
+function getSvg() {
+  /* 鍒涘缓xhr瀵硅薄 */
+  const xhr = new XMLHttpRequest()
+  xhr.open("GET", filePath.value, true)
+  xhr.send()
+  /* 鐩戝惉xhr瀵硅薄 */
+  xhr.addEventListener("load", () => {
+    const resXML = xhr.responseXML
+    let svgDom = resXML.documentElement.cloneNode(true)
+    let values = svgDom.getElementsByTagName("text")
+    for (let i = 0; i < values.length; i++) {
+      let tag = tags.value.filter((f) => f.param === values[i].textContent)
+      if (tag && tag.length > 0) {
+        let tagCode = tag[0].tag
+        values[i].textContent = ""
+        if (tagCode) {
+          values[i].setAttribute("id", tagCode)
+          tagCodes.value.push(tagCode)
+        }
+      }
+    }
+    let oSerializer = new XMLSerializer()
+    svgHtml.value = oSerializer.serializeToString(svgDom)
+  })
+}
+
+defineExpose({ show })
+</script>
+
+<style lang="scss" scoped></style>
diff --git a/zhitan-vue/src/views/svg/equipmentfile/chartView.vue b/zhitan-vue/src/views/svg/equipmentfile/chartView.vue
new file mode 100644
index 0000000..44c9b44
--- /dev/null
+++ b/zhitan-vue/src/views/svg/equipmentfile/chartView.vue
@@ -0,0 +1,314 @@
+<template>
+  <div class="page">
+    <div class="page-container">
+      <div class="page-container-left">
+        <LeftTree ref="leftTreeRef" @handleNodeClick="handleNodeClick" />
+      </div>
+      <div class="page-container-right">
+        <BaseCard :title="queryParams.nodeName">
+          <ConfigureChartView ref="ConfigureChartViewRef" />
+        </BaseCard>
+      </div>
+    </div>
+  </div>
+</template>
+<script setup name="energy-real-time-monitor">
+import ConfigureChartView from "../components/configureView.vue"
+import { listEnergyRealTimeMonitor } from "@/api/realTimeMonitor/realTimeMonitor"
+import { getConfigure } from "@/api/svg/equipmentfile"
+const { proxy } = getCurrentInstance()
+import { useRoute } from "vue-router"
+import useSettingsStore from "@/store/modules/settings"
+const settingsStore = useSettingsStore()
+watch(
+  () => settingsStore.sideTheme,
+  (val) => {
+    // getList()
+  }
+)
+const loading = ref(false)
+const data = reactive({
+  queryParams: {
+    nodeId: null,
+    nodeName: null,
+    energyType: null,
+  },
+  query: { ...useRoute().query },
+})
+const { queryParams, query } = toRefs(data)
+const ConfigureChartViewRef = ref()
+/** 鑺傜偣鍗曞嚮浜嬩欢 */
+function handleNodeClick(data) {
+  queryParams.value.nodeId = data.id
+  queryParams.value.nodeName = data.label
+  if (!data.id) {
+    return
+  }
+  getConfigure(data.id).then((response) => {
+    if (response.code === 200) {
+      let tagCodes = []
+      if (response.data) {
+        response.data.infoList.forEach((tag) => {
+          tagCodes.push(tag.tag)
+        })
+      } else {
+        tagCodes = []
+      }
+      ConfigureChartViewRef.value.show(data.id)
+    } else {
+      proxy.$modal.msgError(response.msg)
+    }
+  })
+}
+</script>
+<style scoped lang="scss">
+@import "@/assets/styles/page.scss";
+
+.themeDark {
+  .card-box {
+    margin: 0 18px;
+    padding: 10px 18px;
+    box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.12);
+    border-radius: 8px 8px 8px 8px;
+    border: 1px solid #22408c;
+    margin-bottom: 20px;
+
+    &-title {
+      // margin: 10px 0 10px;
+      color: rgba(255, 255, 255, 0.8);
+      text-align: left;
+      font-weight: bold;
+      font-family: OPPOSans, OPPOSans;
+      font-weight: 500;
+      font-size: 16px;
+      font-style: normal;
+      text-transform: none;
+    }
+
+    &-ul {
+      display: flex;
+      flex-wrap: wrap;
+    }
+
+    &-li {
+      width: 18%;
+      margin: 1%;
+      border-radius: 5px;
+      border: 1px solid #22408c;
+      margin-bottom: 5px;
+      background: #1a235d;
+      box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.12);
+      border-radius: 8px 8px 8px 8px;
+      padding: 0 10px;
+
+      .title {
+        font-size: 14px;
+        color: rgba(255, 255, 255, 0.8);
+        font-family: OPPOSans, OPPOSans;
+        font-weight: 500;
+        font-size: 16px;
+        line-height: 19px;
+        text-align: left;
+        font-style: normal;
+        text-transform: none;
+      }
+
+      .num {
+        font-size: 22px;
+        color: #36d3ff;
+        font-family: OPPOSans, OPPOSans;
+        font-weight: 800;
+        font-size: 32px;
+        text-align: left;
+        font-style: normal;
+        text-transform: none;
+      }
+
+      .time {
+        color: rgba(255, 253, 253, 0.7);
+        font-family: Poppins, Poppins;
+        font-weight: 400;
+        text-align: left;
+        font-style: normal;
+        text-transform: none;
+      }
+    }
+
+    dd {
+      padding: 0;
+      margin-left: 5px;
+      margin-bottom: 10px;
+    }
+  }
+
+  .hamburger {
+    display: inline-block;
+    vertical-align: middle;
+    width: 20px;
+    height: 20px;
+  }
+
+  .hamburger.is-active {
+    transform: rotate(180deg);
+  }
+
+  .item-box {
+    display: flex;
+    justify-items: center;
+    align-items: center;
+    flex-wrap: wrap;
+    margin: 10px 18px;
+
+    .item-tag {
+      // width: 13%;
+      text-align: center;
+      margin: 5px 8px;
+      border-radius: 8px;
+      padding: 7px 10px;
+      font-family: OPPOSans, OPPOSans;
+      font-weight: 500;
+      font-size: 16px;
+      color: #ffffff;
+    }
+  }
+}
+
+.themeLight {
+  .card-box {
+    margin: 0 18px;
+    padding: 10px 18px;
+    box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.12);
+    border-radius: 8px 8px 8px 8px;
+    margin-bottom: 20px;
+
+    &-title {
+      // margin: 10px 0 10px;
+      text-align: left;
+      font-weight: bold;
+      font-family: OPPOSans, OPPOSans;
+      font-weight: 500;
+      font-size: 16px;
+      font-style: normal;
+      text-transform: none;
+    }
+
+    &-ul {
+      display: flex;
+      flex-wrap: wrap;
+    }
+
+    &-li {
+      width: 240px;
+      margin-right: 10px;
+      margin-top: 16px;
+      border-radius: 5px;
+      border: 1px solid #ebebeb;
+      margin-bottom: 5px;
+      background: #fff;
+      // box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.12);
+      border-radius: 8px 8px 8px 8px;
+      padding: 0 10px;
+
+      .title {
+        font-size: 14px;
+        color: #676767;
+        font-family: OPPOSans, OPPOSans;
+        font-weight: 500;
+        font-size: 16px;
+        line-height: 19px;
+        text-align: left;
+        font-style: normal;
+        text-transform: none;
+      }
+
+      .num {
+        font-size: 22px;
+        color: #3271eb;
+        font-family: OPPOSans, OPPOSans;
+        font-weight: 800;
+        font-size: 32px;
+        text-align: left;
+        font-style: normal;
+        text-transform: none;
+      }
+
+      .time {
+        color: #676767;
+        font-family: Poppins, Poppins;
+        font-weight: 400;
+        text-align: left;
+        font-style: normal;
+        text-transform: none;
+      }
+    }
+
+    dd {
+      padding: 0;
+      margin-left: 5px;
+      margin-bottom: 10px;
+    }
+  }
+
+  .hamburger {
+    display: inline-block;
+    vertical-align: middle;
+    width: 20px;
+    height: 20px;
+  }
+
+  .hamburger.is-active {
+    transform: rotate(180deg);
+  }
+
+  .item-box {
+    display: flex;
+    justify-items: center;
+    align-items: center;
+    flex-wrap: wrap;
+    margin: 10px 18px;
+
+    .item-tag {
+      // width: 13%;
+      text-align: center;
+      margin: 5px 8px;
+      border-radius: 8px;
+      padding: 7px 3px;
+      font-family: OPPOSans, OPPOSans;
+      font-weight: 500;
+      font-size: 16px;
+      color: #ffffff;
+    }
+  }
+}
+
+.scrollbar-flex-content {
+  display: flex;
+  margin: 10px 18px;
+}
+.scrollbar-demo-item {
+  flex-shrink: 0;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  // width: 100px;
+  // height: 50px;
+  // margin: 10px;
+  text-align: center;
+  border-radius: 4px;
+  background: var(--el-color-danger-light-9);
+  color: var(--el-color-danger);
+}
+
+.item-tag {
+  // width: 13%;
+  text-align: center;
+  margin: 5px 8px;
+  border-radius: 8px;
+  padding: 7px 10px;
+  font-family: OPPOSans, OPPOSans;
+  font-weight: 500;
+  font-size: 16px;
+  color: #ffffff;
+  cursor: pointer;
+}
+</style>
diff --git a/zhitan-vue/src/views/svg/equipmentfile/index.vue b/zhitan-vue/src/views/svg/equipmentfile/index.vue
new file mode 100644
index 0000000..b689a8d
--- /dev/null
+++ b/zhitan-vue/src/views/svg/equipmentfile/index.vue
@@ -0,0 +1,243 @@
+<template>
+  <div class="page">
+    <div class="page-container">
+      <div class="page-container-left">
+        <div class="tree page-box">
+          <div class="select-box mb20">
+            鏁版嵁妯″瀷锛�
+            <el-select
+              style="width: 180px"
+              v-model="modelData"
+              placeholder="璇烽�夋嫨妯″瀷"
+              filterable
+              @change="changeModel"
+            >
+              <el-option
+                v-for="model in modelInfoOptions"
+                :key="model.modelCode"
+                :label="model.modelName"
+                :value="model.modelCode"
+              />
+            </el-select>
+          </div>
+          <div class="tree-box" v-loading="treeLoading">
+            <el-tree
+              ref="treeRef"
+              :props="defaultProps"
+              :data="treeData"
+              node-key="id"
+              highlight-current
+              :filter-node-method="filterNode"
+              :default-expanded-keys="treeExpandData"
+              :expand-on-click-node="false"
+              @node-click="changeNode"
+              accordion
+            >
+              <template #default="{ node, data }">
+                <span>
+                  <el-tooltip
+                    v-if="node.label.length > 16"
+                    class="item"
+                    effect="dark"
+                    :content="node.label"
+                    placement="top-end"
+                  >
+                    <span>{{ node.label.slice(0, 16) + "..." }}</span>
+                  </el-tooltip>
+                  <span v-else id="b">{{ node.label }}</span>
+                </span>
+              </template>
+            </el-tree>
+          </div>
+        </div>
+      </div>
+      <div class="page-container-right">
+        <BaseCard :title="currentNode ? currentNode.label + '--鑺傜偣閰嶇疆' : '鏆傛棤鑺傜偣閰嶇疆'">
+          <div class="content-box">
+            <ConfigureView ref="configureViewRef" />
+          </div>
+        </BaseCard>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { listModel } from "@/api/modelConfiguration/businessModel"
+import { treeList } from "@/api/modelConfiguration/indexWarehouse"
+import ConfigureView from "../components/configure.vue"
+import { nextTick } from "vue"
+import { useRoute } from "vue-router"
+let { proxy } = getCurrentInstance()
+let treeLoading = ref(true)
+let modelData = ref(null)
+let modelInfoOptions = ref([]) //涓嬫媺鍒楄〃
+const configureViewRef = ref()
+//鑾峰彇涓嬫媺鍒楄〃
+function searchList(flag) {
+  listModel({ isShow: 1 }).then((response) => {
+    modelInfoOptions.value = response.data
+    if (flag) {
+      if (modelInfoOptions.value.length > 0) {
+        if (proxy.$route.query.modelCode) {
+          modelData.value = proxy.$route.query.modelCode
+        } else {
+          modelData.value = modelInfoOptions.value[0].modelCode
+        }
+        getTreeList(modelData.value)
+      }
+    }
+  })
+}
+
+searchList(true)
+
+//涓嬫媺閫変腑瑙﹀彂鏍戝垪琛�
+function changeModel(item) {
+  // console.log('changeModel', item)
+  getTreeList(item)
+}
+
+let treeRef = ref(null)
+let treeData = ref([])
+
+const defaultProps = ref({
+  children: "children",
+  label: "label",
+})
+
+//妫�绱㈡爲
+let filterText = ref("")
+
+const filterNode = (value, data) => {
+  if (!value) return true
+  return data.label.includes(value)
+}
+watch(filterText, (val) => {
+  // 妫�鏌reeRef.value鏄惁鏄竴涓湁鏁堢殑ElTree瀹炰緥
+  if (treeRef.value && typeof treeRef.value.filter === "function") {
+    // 璋冪敤filter鏂规硶
+    treeRef.value.filter(val)
+  } else {
+    // treeRef.value鏃犳晥锛屽鐞嗛敊璇�
+    console.error("error")
+  }
+})
+
+let currentNode = ref(null)
+let treeExpandData = ref([])
+let isFirstLeafNode = ref(false)
+let deviceConfigRef = ref(null)
+let collectIndicatorsRef = ref(null)
+let statisticalIndicatorsRef = ref(null)
+
+//鑾峰彇鏍戝垪琛�
+function getTreeList(modelCode) {
+  treeLoading.value = true
+  treeList({ modelCode }).then((res) => {
+    treeLoading.value = false
+    let { data } = res
+    treeData.value = data
+    let chooseNode = null
+    if (data.length > 0) {
+      if (data[0].children && data[0].children.length !== 0 && isFirstLeafNode.value) {
+        if (data[0].children[0].children && data[0].children[0].children.length !== 0) {
+          chooseNode = data[0].children[0].children[0]
+        } else {
+          chooseNode = data[0].children[0]
+        }
+      } else {
+        chooseNode = data[0]
+      }
+      currentNode.value = chooseNode
+      changeNode(currentNode.value)
+      treeExpandData.value.push(chooseNode.id)
+      nextTick(() => {
+        treeRef.value.setCurrentKey(chooseNode.id)
+      })
+    }
+  })
+}
+//鏍戠偣鍑�
+function changeNode(data, node, ev) {
+  console.log("鏍戠偣鍑�", data)
+  currentNode.value = data
+  configureViewRef.value.changeModelNode(data)
+}
+</script>
+
+<style lang="scss" scoped>
+@import "@/assets/styles/page.scss";
+
+.page-box {
+  height: calc(100vh - 145px);
+  padding-top: 12px;
+
+  .tree-box {
+    height: calc(100% - 70px);
+    overflow-y: auto !important;
+  }
+
+  .select-box {
+    display: flex;
+    align-items: center;
+    color: #3371eb;
+    margin-left: 10px;
+
+    :deep .el-icon {
+      color: #fff;
+      margin: 0 10px 0 15px;
+      font-size: 14px;
+    }
+  }
+
+  .node-opt {
+    flex: 1;
+    text-align: right;
+    margin-right: 5px;
+
+    :deep .el-icon {
+      color: #fff;
+      margin-right: 5px;
+    }
+  }
+}
+
+:deep .el-tabs__nav-wrap:after {
+  background: transparent;
+}
+
+:deep .el-tabs__item {
+  color: #fff;
+  font-size: 20px;
+  padding: 0 20px;
+
+  &.is-active,
+  &:hover {
+    color: #999 !important;
+  }
+}
+
+.tab-box {
+  display: flex;
+  align-items: center;
+  color: #fff;
+  border-bottom: 1px solid #3371eb;
+  margin-right: 20px;
+
+  .tab-li {
+    cursor: pointer;
+    border: 1px solid #3371eb;
+    padding: 10px 25px;
+    border-radius: 5px 5px 0 0;
+  }
+
+  .is-tab {
+    background: #3371eb;
+  }
+}
+
+.content-box {
+  height: calc(100vh - 206px) !important;
+}
+</style>

--
Gitblit v1.9.3