Bladeren bron

节能分析

learshaw 1 maand geleden
bovenliggende
commit
346fe7f0fb
29 gewijzigde bestanden met toevoegingen van 1258 en 173 verwijderingen
  1. 1 6
      ems/ems-application/ems-admin/src/main/java/com/ruoyi/web/controller/ems/EmsObjAttrController.java
  2. 1 7
      ems/ems-application/ems-admin/src/main/java/com/ruoyi/web/controller/ems/EmsObjAttrValueController.java
  3. 55 0
      ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/config/AnalysisConfig.java
  4. 33 18
      ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/ElecMeterHController.java
  5. 103 0
      ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/EmsEcoDController.java
  6. 13 0
      ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/WaterMeterHController.java
  7. 55 7
      ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/task/TaskService.java
  8. 5 2
      ems/ems-cloud/ems-server/src/main/resources/application-local.yml
  9. 5 2
      ems/ems-cloud/ems-server/src/main/resources/application-prod-ct.yml
  10. 82 0
      ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsEcoD.java
  11. 98 0
      ems/ems-core/src/main/java/com/ruoyi/ems/domain/EnergyMeter.java
  12. 12 4
      ems/ems-core/src/main/java/com/ruoyi/ems/mapper/ElecMeterHMapper.java
  13. 73 0
      ems/ems-core/src/main/java/com/ruoyi/ems/mapper/EmsEcoDMapper.java
  14. 3 1
      ems/ems-core/src/main/java/com/ruoyi/ems/mapper/WaterMeterHMapper.java
  15. 3 3
      ems/ems-core/src/main/java/com/ruoyi/ems/service/IBoundaryObjService.java
  16. 12 5
      ems/ems-core/src/main/java/com/ruoyi/ems/service/IElecMeterHService.java
  17. 63 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/IEmsEcoDService.java
  18. 4 2
      ems/ems-core/src/main/java/com/ruoyi/ems/service/IWaterMeterHService.java
  19. 242 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/analysis/ElecProdForecastService.java
  20. 109 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/analysis/EmsEcoAnalysisService.java
  21. 0 98
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/AdmEmsEcoDServiceImpl.java
  22. 8 8
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/BoundaryObjServiceImpl.java
  23. 9 4
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/ElecMeterHServiceImpl.java
  24. 98 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/EmsEcoDServiceImpl.java
  25. 6 2
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/WaterMeterHServiceImpl.java
  26. 26 2
      ems/ems-core/src/main/resources/mapper/ems/ElecMeterHMapper.xml
  27. 104 0
      ems/ems-core/src/main/resources/mapper/ems/EmsEcoDMapper.xml
  28. 34 2
      ems/ems-core/src/main/resources/mapper/ems/WaterMeterHMapper.xml
  29. 1 0
      ems/sql/ems_server.sql

+ 1 - 6
ems/ems-application/ems-admin/src/main/java/com/ruoyi/web/controller/ems/EmsObjAttrController.java

@@ -83,12 +83,7 @@ public class EmsObjAttrController extends BaseController {
         try {
             String modeCode = null;
 
-            if (objType == DevObjType.FACS.getCode()) {
-                EmsFacs facs = facsService.selectEmsFacsByCode(objCode);
-                Assert.notNull(facs, -1, "能源设施不存在");
-                modeCode = facs.getFacsModel();
-            }
-            else if (objType == DevObjType.DEVC.getCode()) {
+            if (objType == DevObjType.DEVC.getCode()) {
                 EmsDevice device = deviceService.selectByCode(objCode);
                 Assert.notNull(device, -1, "能源设备不存在");
                 modeCode = device.getDeviceModel();

+ 1 - 7
ems/ems-application/ems-admin/src/main/java/com/ruoyi/web/controller/ems/EmsObjAttrValueController.java

@@ -100,13 +100,7 @@ public class EmsObjAttrValueController extends BaseController {
         String modeCode = null;
         int cnt = 0;
 
-        if (objType == DevObjType.FACS.getCode()) {
-            EmsFacs facs = facsService.selectEmsFacsByCode(objCode);
-            Assert.notNull(facs, -1, "能源设施不存在");
-            modeCode = facs.getFacsModel();
-            cnt = objAttrValueService.deleteByObjCode(modeCode, objCode);
-        }
-        else if (objType == DevObjType.DEVC.getCode()) {
+       if (objType == DevObjType.DEVC.getCode()) {
             EmsDevice device = deviceService.selectByCode(objCode);
             Assert.notNull(device, -1, "能源设备不存在");
             modeCode = device.getDeviceModel();

+ 55 - 0
ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/config/AnalysisConfig.java

@@ -0,0 +1,55 @@
+/*
+ * 文 件 名:  ForecastConfig
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/6/19
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.config;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 预测配置
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/6/19]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+@Configuration
+public class AnalysisConfig {
+    @Value("${general-data.weather.adcode}")
+    private String adcode;
+
+    @Value("${analysis-task.eco-analysis.area-codes}")
+    private String ecoAnalysisArea;
+
+    @Value("${analysis-task.pv-forecast.area-codes}")
+    private String pvForecastArea;
+
+    @Value("${analysis-task.pv-forecast.forecastDays}")
+    private int prodForecastDays;
+
+    public String[] getEcoAnalysisAreas() {
+        return StringUtils.split(ecoAnalysisArea, ",");
+    }
+
+    public String[] getPvForecastAreas() {
+        return StringUtils.split(pvForecastArea, ",");
+    }
+
+    public int getProdForecastDays() {
+        return prodForecastDays;
+    }
+
+    public String getAdcode() {
+        return adcode;
+    }
+}

+ 33 - 18
ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/ElecMeterHController.java

@@ -8,7 +8,7 @@ import com.ruoyi.common.core.web.page.TableDataInfo;
 import com.ruoyi.common.log.annotation.Log;
 import com.ruoyi.common.log.enums.BusinessType;
 import com.ruoyi.common.security.annotation.RequiresPermissions;
-import com.ruoyi.ems.domain.ElecMeter;
+import com.ruoyi.ems.domain.EnergyMeter;
 import com.ruoyi.ems.domain.ElecMeterH;
 import com.ruoyi.ems.model.QueryMeter;
 import com.ruoyi.ems.service.IBoundaryObjService;
@@ -68,19 +68,19 @@ public class ElecMeterHController extends BaseController {
      */
     @GetMapping("/staByTime")
     public AjaxResult staByTime(QueryMeter queryMeter) {
-        List<ElecMeter> list = elecMeterHService.staByTime(queryMeter);
+        List<EnergyMeter> list = elecMeterHService.staByTime(queryMeter);
         JSONObject jsonObject = new JSONObject();
 
         if (CollectionUtils.isNotEmpty(list)) {
-            Map<String, ElecMeter> map = list.stream()
-                    .collect(Collectors.toMap(ElecMeter::getObjName, Function.identity()));
+            Map<String, EnergyMeter> map = list.stream()
+                .collect(Collectors.toMap(EnergyMeter::getObjName, Function.identity()));
             BigDecimal quantity = BigDecimal.ZERO;
             BigDecimal useCost = BigDecimal.ZERO;
 
-            ElecMeter lowElec = map.computeIfAbsent("lowElec", k -> new ElecMeter("-1", "lowElec", 0.0, 0.0));
-            ElecMeter normalElec = map.computeIfAbsent("normalElec", k -> new ElecMeter("0", "normalElec", 0.0, 0.0));
-            ElecMeter highElec = map.computeIfAbsent("highElec", k -> new ElecMeter("1", "highElec", 0.0, 0.0));
-            ElecMeter peakElec = map.computeIfAbsent("peakElec", k -> new ElecMeter("-1", "peakElec", 0.0, 0.0));
+            EnergyMeter lowElec = map.computeIfAbsent("lowElec", k -> new EnergyMeter("-1", "lowElec", 0.0, 0.0));
+            EnergyMeter normalElec = map.computeIfAbsent("normalElec", k -> new EnergyMeter("0", "normalElec", 0.0, 0.0));
+            EnergyMeter highElec = map.computeIfAbsent("highElec", k -> new EnergyMeter("1", "highElec", 0.0, 0.0));
+            EnergyMeter peakElec = map.computeIfAbsent("peakElec", k -> new EnergyMeter("-1", "peakElec", 0.0, 0.0));
 
             quantity = quantity.add(new BigDecimal(String.valueOf(lowElec.getQuantity())));
             useCost = useCost.add(new BigDecimal(String.valueOf(lowElec.getUseCost())));
@@ -91,17 +91,18 @@ public class ElecMeterHController extends BaseController {
             quantity = quantity.add(new BigDecimal(String.valueOf(peakElec.getQuantity())));
             useCost = useCost.add(new BigDecimal(String.valueOf(peakElec.getUseCost())));
 
-            jsonObject.put("total", new ElecMeter("total", "total", quantity.doubleValue(), useCost.doubleValue()));
+            jsonObject.put("total", new EnergyMeter("total", "total", quantity.doubleValue(), useCost.doubleValue()));
             jsonObject.put("lowElec", lowElec);
             jsonObject.put("normalElec", normalElec);
             jsonObject.put("highElec", highElec);
             jsonObject.put("peakElec", peakElec);
-        } else {
-            jsonObject.put("total", new ElecMeter("total", "total", 0.0, 0.0));
-            jsonObject.put("lowElec", new ElecMeter("-1", "lowElec", 0.0, 0.0));
-            jsonObject.put("normalElec", new ElecMeter("0", "normalElec", 0.0, 0.0));
-            jsonObject.put("highElec", new ElecMeter("1", "highElec", 0.0, 0.0));
-            jsonObject.put("peakElec", new ElecMeter("2", "peakElec", 0.0, 0.0));
+        }
+        else {
+            jsonObject.put("total", new EnergyMeter("total", "total", 0.0, 0.0));
+            jsonObject.put("lowElec", new EnergyMeter("-1", "lowElec", 0.0, 0.0));
+            jsonObject.put("normalElec", new EnergyMeter("0", "normalElec", 0.0, 0.0));
+            jsonObject.put("highElec", new EnergyMeter("1", "highElec", 0.0, 0.0));
+            jsonObject.put("peakElec", new EnergyMeter("2", "peakElec", 0.0, 0.0));
         }
 
         return success(jsonObject);
@@ -115,7 +116,7 @@ public class ElecMeterHController extends BaseController {
      */
     @GetMapping("/hour/listFacsMeterTotal")
     public AjaxResult listFacsMeterTotal(QueryMeter queryMeter) {
-        List<ElecMeter> list = boundaryObjService.getMeterStaByFacsCategory(queryMeter);
+        List<EnergyMeter> list = boundaryObjService.getMeterStaByFacsCategory(queryMeter);
         return success(list);
     }
 
@@ -133,6 +134,18 @@ public class ElecMeterHController extends BaseController {
     }
 
     /**
+     * 计算时间范围内日平均
+     *
+     * @param queryMeter 支持areaCode、deviceCode、date范围筛选
+     * @return ElecMeter
+     */
+    @GetMapping("/day/avg")
+    public AjaxResult selectElecDayAvg(QueryMeter queryMeter) {
+        EnergyMeter ElecMeter = elecMeterHService.selectElecDayAvg(queryMeter);
+        return success(ElecMeter);
+    }
+
+    /**
      * 导出用电计量-小时列表
      */
     @RequiresPermissions("ems:elecMeterH:export")
@@ -175,12 +188,14 @@ public class ElecMeterHController extends BaseController {
     }
 
     @GetMapping("/sum/byDate/{date}")
-    public AjaxResult qryElecMeterByDate(@PathVariable("date") String date, @RequestParam(name = "areaCode", required = false) String areaCode) {
+    public AjaxResult qryElecMeterByDate(@PathVariable("date") String date,
+        @RequestParam(name = "areaCode", required = false) String areaCode) {
         return success(elecMeterHService.qryElecMeterByDate(date, areaCode));
     }
 
     @GetMapping("/sum/timeIndex/byDate/{date}/{timeIndex}")
-    public AjaxResult qryTimeIndexElecMeterByDay(@PathVariable("date") String date, @PathVariable("timeIndex") Integer timeIndex) {
+    public AjaxResult qryTimeIndexElecMeterByDay(@PathVariable("date") String date,
+        @PathVariable("timeIndex") Integer timeIndex) {
         return success(elecMeterHService.qryTimeIndexElecMeterByDay(date, timeIndex));
     }
 

+ 103 - 0
ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/EmsEcoDController.java

@@ -0,0 +1,103 @@
+package com.ruoyi.ems.controller;
+
+import com.huashe.common.domain.AjaxResult;
+import com.ruoyi.common.core.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.core.web.page.TableDataInfo;
+import com.ruoyi.common.log.annotation.Log;
+import com.ruoyi.common.log.enums.BusinessType;
+import com.ruoyi.common.security.annotation.RequiresPermissions;
+import com.ruoyi.ems.domain.EmsEcoD;
+import com.ruoyi.ems.service.IEmsEcoDService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 节能计量日Controller
+ *
+ * @author ruoyi
+ * @date 2025-04-22
+ */
+@RestController
+@RequestMapping("/EmsEcoD")
+public class EmsEcoDController extends BaseController {
+    @Autowired
+    private IEmsEcoDService emsEcoDService;
+
+    /**
+     * 查询节能计量日列表
+     */
+    @RequiresPermissions("ems:EmsEcoD:list")
+    @GetMapping("/list")
+    public TableDataInfo list(EmsEcoD admEmsEcoD) {
+        startPage();
+        List<EmsEcoD> list = emsEcoDService.selectEmsEcoDList(admEmsEcoD);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出节能计量日列表
+     */
+    @RequiresPermissions("ems:EmsEcoD:export")
+    @Log(title = "节能计量日", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, EmsEcoD admEmsEcoD) {
+        List<EmsEcoD> list = emsEcoDService.selectEmsEcoDList(admEmsEcoD);
+        ExcelUtil<EmsEcoD> util = new ExcelUtil<EmsEcoD>(EmsEcoD.class);
+        util.exportExcel(response, list, "节能计量日数据");
+    }
+
+    /**
+     * 获取节能计量日详细信息
+     */
+    @RequiresPermissions("ems:EmsEcoD:query")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id) {
+        return success(emsEcoDService.selectEmsEcoDById(id));
+    }
+
+    /**
+     * 新增节能计量日
+     */
+    @RequiresPermissions("ems:EmsEcoD:add")
+    @Log(title = "节能计量日", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody EmsEcoD admEmsEcoD) {
+        return toAjax(emsEcoDService.insertEmsEcoD(admEmsEcoD));
+    }
+
+    /**
+     * 修改节能计量日
+     */
+    @RequiresPermissions("ems:EmsEcoD:edit")
+    @Log(title = "节能计量日", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody EmsEcoD admEmsEcoD) {
+        return toAjax(emsEcoDService.updateEmsEcoD(admEmsEcoD));
+    }
+
+    /**
+     * 删除节能计量日
+     */
+    @RequiresPermissions("ems:EmsEcoD:remove")
+    @Log(title = "节能计量日", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids) {
+        return toAjax(emsEcoDService.deleteEmsEcoDByIds(ids));
+    }
+
+    @GetMapping(value = "/date/range")
+    public AjaxResult calcAdmEmsEcoDateRange(EmsEcoD admEmsEcoD) {
+        return success(emsEcoDService.calcEmsEcoDateRange(admEmsEcoD));
+    }
+}

+ 13 - 0
ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/WaterMeterHController.java

@@ -7,6 +7,7 @@ import com.ruoyi.common.core.web.page.TableDataInfo;
 import com.ruoyi.common.log.annotation.Log;
 import com.ruoyi.common.log.enums.BusinessType;
 import com.ruoyi.common.security.annotation.RequiresPermissions;
+import com.ruoyi.ems.domain.EnergyMeter;
 import com.ruoyi.ems.domain.WaterMeterH;
 import com.ruoyi.ems.model.QueryMeter;
 import com.ruoyi.ems.service.IWaterMeterHService;
@@ -112,4 +113,16 @@ public class WaterMeterHController extends BaseController {
     public AjaxResult qryDateWaterMeterByYear(@PathVariable(name = "date") String date) {
         return success(waterMeterHService.qryDateWaterMeterByYear(date));
     }
+
+    /**
+     * 计算时间范围内日平均
+     *
+     * @param queryMeter 支持areaCode、deviceCode、date范围筛选
+     * @return ElecMeter
+     */
+    @GetMapping("/day/avg")
+    public AjaxResult selectElecDayAvg(QueryMeter queryMeter) {
+        EnergyMeter waterMeter = waterMeterHService.selectWaterDayAvg(queryMeter);
+        return success(waterMeter);
+    }
 }

+ 55 - 7
ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/task/TaskService.java

@@ -18,14 +18,16 @@ import com.huashe.common.domain.model.WeatherForecast;
 import com.huashe.common.domain.model.WeatherRt;
 import com.huashe.common.exception.Assert;
 import com.huashe.common.utils.HttpUtils;
+import com.ruoyi.ems.config.AnalysisConfig;
 import com.ruoyi.ems.config.DateAttrConfig;
-import com.ruoyi.ems.config.ForecastConfig;
 import com.ruoyi.ems.config.WeatherConfig;
 import com.ruoyi.ems.domain.EmsFacs;
+import com.ruoyi.ems.model.QueryMeter;
 import com.ruoyi.ems.service.IDateService;
 import com.ruoyi.ems.service.IEmsFacsService;
 import com.ruoyi.ems.service.IWeatherService;
-import com.ruoyi.ems.service.forecast.ElecProdForecastService;
+import com.ruoyi.ems.service.analysis.ElecProdForecastService;
+import com.ruoyi.ems.service.analysis.EmsEcoAnalysisService;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -41,6 +43,7 @@ import javax.annotation.Resource;
 import java.time.LocalDate;
 import java.time.Year;
 import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAdjusters;
 import java.util.List;
 
 /**
@@ -73,10 +76,13 @@ public class TaskService {
     private IDateService dateService;
 
     @Resource
+    private EmsEcoAnalysisService ecoAnalysisService;
+
+    @Resource
     private ElecProdForecastService elecProdForecastService;
 
     @Resource
-    private ForecastConfig forecastConfig;
+    private AnalysisConfig analysisConfig;
 
     /**
      * 天气实况采集
@@ -197,21 +203,63 @@ public class TaskService {
     }
 
     /**
+     * 节能分析
+     */
+    @Async
+    @Scheduled(cron = "${analysis-task.eco-analysis.cron}")
+    public void triggerEcoAnalysis() {
+        log.debug("start eco analysis task.");
+        DateTimeFormatter dateForm = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+        try {
+            // 获取今天的日期
+            LocalDate today = LocalDate.now();
+            LocalDate yesterday = today.minusDays(1);
+            String date = yesterday.format(dateForm);
+
+            String[] areaCodes = analysisConfig.getEcoAnalysisAreas();
+
+            if (ArrayUtils.isNotEmpty(areaCodes)) {
+                // 获取上个月的日期
+                LocalDate lastMonth = today.minusMonths(1);
+
+                // 获取上个月的第一天
+                LocalDate firstDayOfLastMonth = lastMonth.withDayOfMonth(1);
+
+                // 获取上个月的最后一天
+                LocalDate lastDayOfLastMonth = lastMonth.with(TemporalAdjusters.lastDayOfMonth());
+
+                for (String areaCode : areaCodes) {
+                    QueryMeter queryMeter = new QueryMeter();
+                    queryMeter.setAreaCode(areaCode);
+                    queryMeter.setStartRecTime(firstDayOfLastMonth.format(dateForm));
+                    queryMeter.setEndRecTime(lastDayOfLastMonth.format(dateForm));
+
+                    ecoAnalysisService.executePvForecast(areaCode, date, queryMeter);
+                }
+            }
+        }
+        catch (Exception e) {
+            log.error("eco analysis fail!", e);
+        }
+    }
+
+    /**
      * 光伏发电预测
      */
     @Async
-    @Scheduled(cron = "${forecast-task.pv-forecast.cron}")
+    @Scheduled(cron = "${analysis-task.pv-forecast.cron}")
     public void pvForecastTask() {
         log.debug("start pv forecast task.");
 
         try {
             // 获取今天的日期
             LocalDate today = LocalDate.now();
-            String[] areaCodes = forecastConfig.getAreaCodes();
+            String[] areaCodes = analysisConfig.getPvForecastAreas();
 
             if (ArrayUtils.isNotEmpty(areaCodes)) {
-                String adcode = forecastConfig.getAdcode();
-                int prodForecastDays = forecastConfig.getProdForecastDays();
+                String adcode = analysisConfig.getAdcode();
+                int prodForecastDays = analysisConfig.getProdForecastDays();
 
                 for (String areaCode : areaCodes) {
                     EmsFacs param = new EmsFacs();

+ 5 - 2
ems/ems-cloud/ems-server/src/main/resources/application-local.yml

@@ -58,9 +58,12 @@ general-data:
     cron: 0 0 12 1 * ?
     api-addr: http://${general-data.server}/general-data/date/getAttrs
 
-forecast-task:
-  area-codes: 321283124S3001,321283124S3002,321283124S3003
+analysis-task:
+  eco-analysis:
+    area-codes: 321283124S3001,321283124S3002
+    cron: 0 0 3 * * ?
   pv-forecast:
+    area-codes: 321283124S3001,321283124S3002,321283124S3003
     forecastDays: 5
     cron: 0 30 8 * * ?
 

+ 5 - 2
ems/ems-cloud/ems-server/src/main/resources/application-prod-ct.yml

@@ -58,9 +58,12 @@ general-data:
     cron: 0 0 12 1 * ?
     api-addr: http://${general-data.server}/general-data/date/getAttrs
 
-forecast-task:
-  area-codes: 321283124S3001,321283124S3002,321283124S3003
+analysis-task:
+  eco-analysis:
+    area-codes: 321283124S3001,321283124S3002
+    cron: 0 0 3 * * ?
   pv-forecast:
+    area-codes: 321283124S3001,321283124S3002,321283124S3003
     forecastDays: 5
     cron: 0 30 8 * * ?
 

+ 82 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsEcoD.java

@@ -0,0 +1,82 @@
+package com.ruoyi.ems.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.huashe.common.annotation.Excel;
+import com.huashe.common.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import java.util.Date;
+
+/**
+ * 节能计量日对象 adm_ems_eco_d
+ *
+ * @author ruoyi
+ * @date 2025-04-22
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class EmsEcoD extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 序号
+     */
+    private Long id;
+
+    /**
+     * 园区代码
+     */
+    @Excel(name = "园区代码")
+    private String areaCode;
+
+    @Excel(name = "园区名称")
+    private String areaName;
+
+    /**
+     * 日期
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "日期", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date date;
+
+    /**
+     * 节(千瓦时)
+     */
+    @Excel(name = "节", readConverterExp = "千=瓦时")
+    private Double elecEcoQuantity;
+
+    /**
+     * 节电金额(元)
+     */
+    @Excel(name = "节电金额", readConverterExp = "元=")
+    private Double elecEcoCost;
+
+    /**
+     * 节水量 (吨)
+     */
+    @Excel(name = "节水量 ", readConverterExp = "吨=")
+    private Double waterEcoQuantity;
+
+    /**
+     * 节水金额(元)
+     */
+    @Excel(name = "节水金额", readConverterExp = "元=")
+    private Double waterEcoCost;
+
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+                .append("id", getId())
+                .append("areaCode", getAreaCode())
+                .append("date", getDate())
+                .append("elecEcoQuantity", getElecEcoQuantity())
+                .append("elecEcoCost", getElecEcoCost())
+                .append("waterEcoQuantity", getWaterEcoQuantity())
+                .append("waterEcoCost", getWaterEcoCost())
+                .toString();
+    }
+}

+ 98 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/domain/EnergyMeter.java

@@ -0,0 +1,98 @@
+/*
+ * 文 件 名:  ElecMeter
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/2/12
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.domain;
+
+/**
+ * 电计量
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/2/12]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+public class EnergyMeter {
+    // 区域编码
+    private String areaCode;
+
+    // 边界对象类型
+    private Integer objType;
+
+    // 边界对象代码
+    private String objCode;
+
+    // 边界对象名称
+    private String objName;
+
+    // 用电量
+    private Double quantity;
+
+    // 用电成本
+    private Double useCost;
+
+    public EnergyMeter() {
+    }
+
+    public EnergyMeter(String objCode, String objName, Double quantity, Double useCost) {
+        this.objCode = objCode;
+        this.objName = objName;
+        this.quantity = quantity;
+        this.useCost = useCost;
+    }
+
+    public String getAreaCode() {
+        return areaCode;
+    }
+
+    public void setAreaCode(String areaCode) {
+        this.areaCode = areaCode;
+    }
+
+    public Integer getObjType() {
+        return objType;
+    }
+
+    public void setObjType(Integer objType) {
+        this.objType = objType;
+    }
+
+    public String getObjCode() {
+        return objCode;
+    }
+
+    public void setObjCode(String objCode) {
+        this.objCode = objCode;
+    }
+
+    public String getObjName() {
+        return objName;
+    }
+
+    public void setObjName(String objName) {
+        this.objName = objName;
+    }
+
+    public Double getQuantity() {
+        return quantity;
+    }
+
+    public void setQuantity(Double quantity) {
+        this.quantity = quantity;
+    }
+
+    public Double getUseCost() {
+        return useCost;
+    }
+
+    public void setUseCost(Double useCost) {
+        this.useCost = useCost;
+    }
+}

+ 12 - 4
ems/ems-core/src/main/java/com/ruoyi/ems/mapper/ElecMeterHMapper.java

@@ -1,6 +1,6 @@
 package com.ruoyi.ems.mapper;
 
-import com.ruoyi.ems.domain.ElecMeter;
+import com.ruoyi.ems.domain.EnergyMeter;
 import com.ruoyi.ems.domain.ElecMeterH;
 import com.ruoyi.ems.model.QueryMeter;
 import org.apache.ibatis.annotations.Param;
@@ -44,7 +44,15 @@ public interface ElecMeterHMapper {
      * @param queryMeter 查询计量条件
      * @return 用电计量-小时集合
      */
-    ElecMeter selectElecMeterSumByDev(QueryMeter queryMeter);
+    EnergyMeter selectElecMeterSumByDev(QueryMeter queryMeter);
+
+    /**
+     * 查询日用电平均
+     *
+     * @param queryMeter 查询计量条件
+     * @return 用电计量-小时集合
+     */
+    EnergyMeter selectElecDayAvg(QueryMeter queryMeter);
 
     /**
      * 根据时间统计
@@ -52,7 +60,7 @@ public interface ElecMeterHMapper {
      * @param queryMeter 查询条件
      * @return 统计
      */
-    List<ElecMeter> selectStaByTime(QueryMeter queryMeter);
+    List<EnergyMeter> selectStaByTime(QueryMeter queryMeter);
 
     /**
      * 新增用电计量-小时
@@ -87,7 +95,7 @@ public interface ElecMeterHMapper {
     int deleteElecMeterHByDate(@Param("date") String date);
 
 
-    ElecMeterH qryElecMeterByDate(ElecMeterH dataRange);
+    EnergyMeter qryElecMeterByDate(ElecMeterH dataRange);
 
     List<ElecMeterH> qryTimeIndexElecMeterByDay(@Param("dataRange") String dataRange);
 

+ 73 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/mapper/EmsEcoDMapper.java

@@ -0,0 +1,73 @@
+package com.ruoyi.ems.mapper;
+
+import com.ruoyi.ems.domain.EmsEcoD;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 节能计量日Mapper接口
+ *
+ * @author ruoyi
+ * @date 2025-04-22
+ */
+public interface EmsEcoDMapper {
+    /**
+     * 查询节能计量日
+     *
+     * @param id 节能计量日主键
+     * @return 节能计量日
+     */
+    EmsEcoD selectEmsEcoDById(Long id);
+
+    /**
+     * 查询节能计量日列表
+     *
+     * @param emsEcoD 节能计量日
+     * @return 节能计量日集合
+     */
+    List<EmsEcoD> selectEmsEcoDList(EmsEcoD emsEcoD);
+
+    /**
+     * 新增节能计量日
+     *
+     * @param emsEcoD 节能计量日
+     * @return 结果
+     */
+    int insertEmsEcoD(EmsEcoD emsEcoD);
+
+    /**
+     * 修改节能计量日
+     *
+     * @param emsEcoD 节能计量日
+     * @return 结果
+     */
+    int updateEmsEcoD(EmsEcoD emsEcoD);
+
+    /**
+     * 删除节能计量日
+     *
+     * @param id 节能计量日主键
+     * @return 结果
+     */
+    int deleteEmsEcoDById(Long id);
+
+    /**
+     * 批量删除节能计量日
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    int deleteEmsEcoDByIds(Long[] ids);
+
+    /**
+     * 删除节能计量日
+     *
+     * @param date     日期
+     * @param areaCode 区域
+     * @return 结果
+     */
+    int deleteEmsEcoD(@Param("date") String date, @Param("areaCode") String areaCode);
+
+    EmsEcoD calcEmsEcoDateRange(EmsEcoD emsEcoD);
+}

+ 3 - 1
ems/ems-core/src/main/java/com/ruoyi/ems/mapper/WaterMeterHMapper.java

@@ -1,5 +1,6 @@
 package com.ruoyi.ems.mapper;
 
+import com.ruoyi.ems.domain.EnergyMeter;
 import com.ruoyi.ems.domain.WaterMeterH;
 import com.ruoyi.ems.model.QueryMeter;
 import org.apache.ibatis.annotations.Param;
@@ -54,7 +55,7 @@ public interface WaterMeterHMapper {
     int deleteWaterMeterHByDate(@Param("date") String date);
 
 
-    WaterMeterH qryWaterMeterByDate(WaterMeterH waterMeterH);
+    EnergyMeter qryWaterMeterByDate(WaterMeterH waterMeterH);
 
     List<WaterMeterH> qryTimeIndexWaterMeterByDay(@Param("dataRange") String dataRange);
 
@@ -62,4 +63,5 @@ public interface WaterMeterHMapper {
 
     List<WaterMeterH> qryDateWaterMeterByYear(String dataRange);
 
+    EnergyMeter selectWaterDayAvg(QueryMeter queryMeter);
 }

+ 3 - 3
ems/ems-core/src/main/java/com/ruoyi/ems/service/IBoundaryObjService.java

@@ -12,7 +12,7 @@ package com.ruoyi.ems.service;
 
 import com.ruoyi.ems.domain.ElecMeterH;
 import com.ruoyi.ems.model.BoundaryObj;
-import com.ruoyi.ems.domain.ElecMeter;
+import com.ruoyi.ems.domain.EnergyMeter;
 import com.ruoyi.ems.model.QueryMeter;
 
 import java.util.List;
@@ -41,7 +41,7 @@ public interface IBoundaryObjService {
      * @param queryMeter 查询条件
      * @return 用电计量统计结果
      */
-    List<ElecMeter> getMeterStaByFacsCategory(QueryMeter queryMeter);
+    List<EnergyMeter> getMeterStaByFacsCategory(QueryMeter queryMeter);
 
     /**
      * 查询用电计量列表-根据设施分类
@@ -57,7 +57,7 @@ public interface IBoundaryObjService {
      * @param queryMeter 查询条件
      * @return 用电计量统计结果
      */
-    List<ElecMeter> getMeterStaByBoundaryObj(QueryMeter queryMeter);
+    List<EnergyMeter> getMeterStaByBoundaryObj(QueryMeter queryMeter);
 
     /**
      * 查询用电计量-根据边界对象

+ 12 - 5
ems/ems-core/src/main/java/com/ruoyi/ems/service/IElecMeterHService.java

@@ -1,6 +1,6 @@
 package com.ruoyi.ems.service;
 
-import com.ruoyi.ems.domain.ElecMeter;
+import com.ruoyi.ems.domain.EnergyMeter;
 import com.ruoyi.ems.domain.ElecMeterH;
 import com.ruoyi.ems.model.QueryMeter;
 
@@ -35,7 +35,7 @@ public interface IElecMeterHService {
      * @param queryMeter 查询条件
      * @return 用电统计
      */
-    List<ElecMeter> staByTime(QueryMeter queryMeter);
+    List<EnergyMeter> staByTime(QueryMeter queryMeter);
 
     /**
      * 统计用电计量-根据边界对象
@@ -43,7 +43,14 @@ public interface IElecMeterHService {
      * @param queryMeter 查询条件
      * @return
      */
-    ElecMeter staByMeterDev(QueryMeter queryMeter);
+    EnergyMeter staByMeterDev(QueryMeter queryMeter);
+
+    /**
+     * 计算时间范围内日平均
+     * @param queryMeter 支持areaCode、deviceCode、date范围筛选
+     * @return ElecMeter
+     */
+    EnergyMeter selectElecDayAvg(QueryMeter queryMeter);
 
     /**
      * 查询最近的一条记录
@@ -85,13 +92,13 @@ public interface IElecMeterHService {
      */
     int deleteElecMeterHByDate(String date);
 
-    ElecMeterH qryElecMeterByDate(String dateRange, String areaCode);
+    EnergyMeter qryElecMeterByDate(String dateRange, String areaCode);
 
     List<ElecMeterH> qryTimeIndexElecMeterByDay(String dateRange, Integer timeIndex);
 
     List<ElecMeterH> qryDateElecMeterByDate(String dateRange);
 
-    public List<ElecMeterH> qryDateElecMeterByYear(String dataRange);
+    List<ElecMeterH> qryDateElecMeterByYear(String dataRange);
 
     List<ElecMeterH> qryDeviceTypeElecMeterByDay(ElecMeterH elecMeterH);
 }

+ 63 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/service/IEmsEcoDService.java

@@ -0,0 +1,63 @@
+package com.ruoyi.ems.service;
+
+import java.util.List;
+
+import com.ruoyi.ems.domain.EmsEcoD;
+
+/**
+ * 节能计量日Service接口
+ *
+ * @author ruoyi
+ * @date 2025-04-22
+ */
+public interface IEmsEcoDService {
+    /**
+     * 查询节能计量日
+     *
+     * @param id 节能计量日主键
+     * @return 节能计量日
+     */
+    EmsEcoD selectEmsEcoDById(Long id);
+
+    /**
+     * 查询节能计量日列表
+     *
+     * @param emsEcoD 节能计量日
+     * @return 节能计量日集合
+     */
+    List<EmsEcoD> selectEmsEcoDList(EmsEcoD emsEcoD);
+
+    /**
+     * 新增节能计量日
+     *
+     * @param emsEcoD 节能计量日
+     * @return 结果
+     */
+    int insertEmsEcoD(EmsEcoD emsEcoD);
+
+    /**
+     * 修改节能计量日
+     *
+     * @param emsEcoD 节能计量日
+     * @return 结果
+     */
+    int updateEmsEcoD(EmsEcoD emsEcoD);
+
+    /**
+     * 批量删除节能计量日
+     *
+     * @param ids 需要删除的节能计量日主键集合
+     * @return 结果
+     */
+    int deleteEmsEcoDByIds(Long[] ids);
+
+    /**
+     * 删除节能计量日信息
+     *
+     * @param id 节能计量日主键
+     * @return 结果
+     */
+    int deleteEmsEcoDById(Long id);
+
+    EmsEcoD calcEmsEcoDateRange(EmsEcoD emsEcoD);
+}

+ 4 - 2
ems/ems-core/src/main/java/com/ruoyi/ems/service/IWaterMeterHService.java

@@ -1,5 +1,6 @@
 package com.ruoyi.ems.service;
 
+import com.ruoyi.ems.domain.EnergyMeter;
 import com.ruoyi.ems.domain.WaterMeterH;
 import com.ruoyi.ems.model.QueryMeter;
 
@@ -45,12 +46,13 @@ public interface IWaterMeterHService {
      */
     int deleteWaterMeterHByDate(String date);
 
-
-    WaterMeterH qryWaterMeterByDate(String dataRange, String areaCode);
+    EnergyMeter qryWaterMeterByDate(String dataRange, String areaCode);
 
     List<WaterMeterH> qryTimeIndexWaterMeterByDay(String dataRange,Integer timeIndex);
 
     List<WaterMeterH> qryDateWaterMeterByDay(String dataRange);
 
     List<WaterMeterH> qryDateWaterMeterByYear(String dataRange);
+
+    EnergyMeter selectWaterDayAvg(QueryMeter queryMeter);
 }

+ 242 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/service/analysis/ElecProdForecastService.java

@@ -0,0 +1,242 @@
+/*
+ * 文 件 名:  ElecProdForecastService
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/6/19
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.service.analysis;
+
+import com.huashe.common.domain.model.WeatherForecast;
+import com.huashe.common.utils.DateUtils;
+import com.ruoyi.ems.domain.ElecProdForecast;
+import com.ruoyi.ems.domain.ElecPvSupplyH;
+import com.ruoyi.ems.mapper.ElecProdForecastMapper;
+import com.ruoyi.ems.model.QueryMeter;
+import com.ruoyi.ems.service.IElecPvSupplyHService;
+import com.ruoyi.ems.service.IWeatherService;
+import org.apache.commons.collections4.CollectionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 产能预测
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/6/19]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+@Service
+public class ElecProdForecastService {
+    private static final Logger log = LoggerFactory.getLogger(ElecProdForecastService.class);
+
+    // 天气影响因子
+    private final static Map<String, Double> weatherFactorMap = new HashMap<>();
+
+    private final DateTimeFormatter dateForm = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+    /**
+     * 光伏产能预测数据服务
+     */
+    @Resource
+    private IElecPvSupplyHService pvSupplyHService;
+
+    /**
+     * 天气服务
+     */
+    @Resource
+    private IWeatherService weatherService;
+
+    @Resource
+    private ElecProdForecastMapper forecastMapper;
+
+    static {
+        // 初始化默认影响因子
+        weatherFactorMap.put("1101", 1.0);   // 晴
+        weatherFactorMap.put("1103", 0.8);   // 多云
+        weatherFactorMap.put("1106", 0.4);   // 阴天
+        weatherFactorMap.put("2100", 0.5);   // 雨
+        weatherFactorMap.put("2101", 0.6);   // 小雨
+        weatherFactorMap.put("2102", 0.5);   // 中雨
+        weatherFactorMap.put("2103", 0.4);   // 大雨
+        weatherFactorMap.put("2104", 0.3);   // 暴雨
+        weatherFactorMap.put("2111", 0.7);   // 阵雨
+        weatherFactorMap.put("2121", 0.7);   // 雷阵雨
+        weatherFactorMap.put("2200", 0.3);   // 雪
+        weatherFactorMap.put("2201", 0.3);   // 小雪
+        weatherFactorMap.put("2202", 0.3);   // 中雪
+        weatherFactorMap.put("2203", 0.2);   // 大雪
+        weatherFactorMap.put("2204", 0.1);   // 暴雪
+        weatherFactorMap.put("2211", 0.4);   // 雨夹雪
+        weatherFactorMap.put("4101", 0.8);   // 轻雾
+        weatherFactorMap.put("4102", 0.7);   // 大雾
+        weatherFactorMap.put("4103", 0.6);   // 浓雾
+        weatherFactorMap.put("4200", 0.5);   // 霾
+        weatherFactorMap.put("4301", 0.5);   // 浮尘
+        weatherFactorMap.put("4302", 0.4);   // 扬沙
+        weatherFactorMap.put("4303", 0.3);   // 沙尘暴
+    }
+
+    /**
+     * 执行光伏产能预测
+     *
+     * @param areaCode    园区代码
+     * @param facsCode    设施编码
+     * @param today       当前日期
+     * @param forecastDay 预测天数
+     */
+    public void executePvForecast(String adcode, String areaCode, String facsCode, LocalDate today, int forecastDay) {
+
+        try {
+            // 1. 读取历史数据 (使用过去30天的数据作为训练集)
+            LocalDate historyStart = today.minusDays(30);
+            LocalDate historyEnd = today.minusDays(1);
+            QueryMeter queryMeter = new QueryMeter(areaCode, facsCode, historyStart.format(dateForm),
+                historyEnd.format(dateForm));
+            List<ElecPvSupplyH> historicalData = pvSupplyHService.selectPvSupplyDayList(queryMeter);
+
+            if (historicalData.isEmpty()) {
+                // 没有历史数据,无法进行预测
+                return;
+            }
+
+            // 2. 读取天气预报
+            LocalDate forecastStart = today;
+            LocalDate forecastEnd = today.plusDays(forecastDay - 1);
+            List<WeatherForecast> weatherForecasts = weatherService.getWeatherForecast(adcode,
+                forecastStart.format(dateForm), forecastEnd.format(dateForm));
+            Map<String, WeatherForecast> weatherMap = convertToWeatherMap(weatherForecasts);
+            List<ElecProdForecast> result = new ArrayList<>();
+
+            while (forecastStart.isBefore(forecastEnd) || forecastStart.isEqual(forecastEnd)) {
+                WeatherForecast weatherForecast = weatherMap.get(forecastStart.format(dateForm));
+                ElecProdForecast elecProdForecast = predictDailyProduction(areaCode, facsCode, forecastStart,
+                    historicalData, weatherForecast);
+                result.add(elecProdForecast);
+                forecastStart = forecastStart.plusDays(1);
+            }
+
+            // 保存数据到数据库
+            forecastMapper.deleteByCondition(areaCode, facsCode, today.format(dateForm), forecastEnd.format(dateForm));
+
+            if (CollectionUtils.isNotEmpty(result)) {
+                forecastMapper.insertBatch(result);
+            }
+        }
+        catch (Exception e) {
+            log.error("execute Pv forecast fail! areaCode:{}, facsCode:{}", areaCode, facsCode, e);
+        }
+    }
+
+    private ElecProdForecast predictDailyProduction(String areaCode, String facsCode, LocalDate date,
+        List<ElecPvSupplyH> trainingData, WeatherForecast weatherForecast) {
+        // 计算历史平均日发电量(保留两位小数)
+        double totalGenElec = trainingData.stream().mapToDouble(ElecPvSupplyH::getGenElecQuantity).sum();
+        double historicalAvgDailyProduction = divideAndRound(totalGenElec, trainingData.size(), 2);
+
+        // 计算历史平均上网电量(保留两位小数)
+        double totalUpElec = trainingData.stream().mapToDouble(ElecPvSupplyH::getUpElecQuantity).sum();
+        double upElecQuantity = divideAndRound(totalUpElec, trainingData.size(), 2);
+
+        // 获取天气影响因子
+        double weatherFactor = getWeatherFactor(weatherForecast);
+
+        // 计算预测值 = 历史平均值 * 天气影响因子
+        double forecastProduction = multiplyAndRound(historicalAvgDailyProduction, weatherFactor, 2);
+
+        // 计算平均功率 (kW)
+        double avgPower = divideAndRound(forecastProduction, 24.0, 2);
+
+        ElecProdForecast forecast = new ElecProdForecast();
+        forecast.setAreaCode(areaCode);
+        forecast.setFacsCode(facsCode);
+        forecast.setDate(Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant()));
+        forecast.setElecProdQuantity(forecastProduction);
+        forecast.setAvgPower(avgPower);
+        forecast.setUpElecQuantity(upElecQuantity);
+        return forecast;
+    }
+
+    private double getWeatherFactor(WeatherForecast forecast) {
+        Double factor = null;
+
+        if (null != forecast) {
+            // 优先使用日间天气
+            String weatherCode = forecast.getDayWeatherType();
+            factor = weatherFactorMap.get(weatherCode);
+
+            // 如果日间天气没有影响因子,使用夜间天气
+            if (factor == null) {
+                weatherCode = forecast.getNightWeatherType();
+                factor = weatherFactorMap.get(weatherCode);
+            }
+
+            // 如果仍然没有,使用默认值
+            factor = factor != null ? factor : 0.8;
+        }
+        else {
+            factor = 0.8;
+        }
+
+        return factor;
+    }
+
+    private Map<String, WeatherForecast> convertToWeatherMap(List<WeatherForecast> weatherForecasts) {
+        Map<String, WeatherForecast> weatherMap = new HashMap<>();
+
+        for (WeatherForecast weatherForecast : weatherForecasts) {
+            String date = DateUtils.dateToString(weatherForecast.getDate(), "yyyy-MM-dd");
+            weatherMap.put(date, weatherForecast);
+        }
+
+        return weatherMap;
+    }
+
+    /**
+     * 除法运算并保留指定小数位数
+     * @param dividend 被除数
+     * @param divisor 除数
+     * @param scale 保留小数位数
+     * @return 四舍五入后的结果
+     */
+    private double divideAndRound(double dividend, double divisor, int scale) {
+        if (divisor == 0) {
+            return 0.0;
+        }
+
+        return BigDecimal.valueOf(dividend / divisor)
+            .setScale(scale, RoundingMode.HALF_UP)
+            .doubleValue();
+    }
+
+    /**
+     * 乘法运算并保留指定小数位数
+     * @param a 乘数1
+     * @param b 乘数2
+     * @param scale 保留小数位数
+     * @return 四舍五入后的结果
+     */
+    private double multiplyAndRound(double a, double b, int scale) {
+        return BigDecimal.valueOf(a * b)
+            .setScale(scale, RoundingMode.HALF_UP)
+            .doubleValue();
+    }
+}

+ 109 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/service/analysis/EmsEcoAnalysisService.java

@@ -0,0 +1,109 @@
+/*
+ * 文 件 名:  EmsEcoAnalysis
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/6/21
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.service.analysis;
+
+import com.huashe.common.utils.DateUtils;
+import com.ruoyi.ems.domain.EmsEcoD;
+import com.ruoyi.ems.domain.EnergyMeter;
+import com.ruoyi.ems.mapper.EmsEcoDMapper;
+import com.ruoyi.ems.model.QueryMeter;
+import com.ruoyi.ems.service.IElecMeterHService;
+import com.ruoyi.ems.service.IWaterMeterHService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * 节能分析
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/6/21]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+@Service
+public class EmsEcoAnalysisService {
+    private static final Logger log = LoggerFactory.getLogger(EmsEcoAnalysisService.class);
+
+    private final DateTimeFormatter dateForm = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+    @Resource
+    private EmsEcoDMapper emsEcoDMapper;
+
+    @Resource
+    private IElecMeterHService elecMeterHService;
+
+    @Resource
+    private IWaterMeterHService waterMeterHService;
+
+    public void executePvForecast(String adcode, String date, QueryMeter reference) {
+        try {
+            EmsEcoD emsEcoD = new EmsEcoD();
+            emsEcoD.setAreaCode(adcode);
+            emsEcoD.setDate(DateUtils.stringToDate(date, "yyyy-MM-dd"));
+
+            // 节电计算
+            EnergyMeter yestElecMeter = elecMeterHService.qryElecMeterByDate(date, adcode);
+
+            if (null != yestElecMeter) {
+                // 参照对比数据提取
+                EnergyMeter referenceMeter = elecMeterHService.selectElecDayAvg(reference);
+                referenceMeter = referenceMeter != null ? referenceMeter : yestElecMeter;
+
+                double quantity = subtractAndRound(referenceMeter.getQuantity(), yestElecMeter.getQuantity(), 2);
+                double cost = subtractAndRound(referenceMeter.getUseCost(), yestElecMeter.getUseCost(), 2);
+                emsEcoD.setElecEcoQuantity(quantity);
+                emsEcoD.setElecEcoCost(cost);
+            }
+
+            EnergyMeter yestWaterMeter = waterMeterHService.qryWaterMeterByDate(date, adcode);
+
+            if (null != yestWaterMeter) {
+                // 参照对比数据提取
+                EnergyMeter referenceMeter = waterMeterHService.selectWaterDayAvg(reference);
+                referenceMeter = referenceMeter != null ? referenceMeter : yestWaterMeter;
+
+                double quantity = subtractAndRound(referenceMeter.getQuantity(), yestWaterMeter.getQuantity(), 2);
+                double cost = subtractAndRound(referenceMeter.getUseCost(), yestWaterMeter.getUseCost(), 2);
+                emsEcoD.setWaterEcoQuantity(quantity);
+                emsEcoD.setWaterEcoCost(cost);
+            }
+
+            emsEcoDMapper.deleteEmsEcoD(date, adcode);
+            emsEcoDMapper.insertEmsEcoD(emsEcoD);
+        }
+        catch (Exception e) {
+            log.error("executePvForecast fail! adcode:{}, date:{}", adcode, date, e);
+        }
+
+    }
+
+    /**
+     * 减法运算并保留指定小数位数
+     *
+     * @param a     乘数
+     * @param b     乘数
+     * @param scale 保留小数位数
+     * @return 四舍五入后的结果
+     */
+    private double subtractAndRound(double a, double b, int scale) {
+        BigDecimal bd1 = new BigDecimal(Double.toString(a));
+        BigDecimal bd2 = new BigDecimal(Double.toString(b));
+
+        return bd1.subtract(bd2).setScale(scale, RoundingMode.HALF_UP).doubleValue();
+    }
+}

+ 0 - 98
ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/AdmEmsEcoDServiceImpl.java

@@ -1,98 +0,0 @@
-package com.ruoyi.ems.service.impl;
-
-import java.util.List;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import com.ruoyi.ems.mapper.AdmEmsEcoDMapper;
-import com.ruoyi.ems.domain.AdmEmsEcoD;
-import com.ruoyi.ems.service.IAdmEmsEcoDService;
-
-/**
- * 节能计量日Service业务层处理
- * 
- * @author ruoyi
- * @date 2025-04-22
- */
-@Service
-public class AdmEmsEcoDServiceImpl implements IAdmEmsEcoDService 
-{
-    @Autowired
-    private AdmEmsEcoDMapper admEmsEcoDMapper;
-
-    /**
-     * 查询节能计量日
-     * 
-     * @param id 节能计量日主键
-     * @return 节能计量日
-     */
-    @Override
-    public AdmEmsEcoD selectAdmEmsEcoDById(Long id)
-    {
-        return admEmsEcoDMapper.selectAdmEmsEcoDById(id);
-    }
-
-    /**
-     * 查询节能计量日列表
-     * 
-     * @param admEmsEcoD 节能计量日
-     * @return 节能计量日
-     */
-    @Override
-    public List<AdmEmsEcoD> selectAdmEmsEcoDList(AdmEmsEcoD admEmsEcoD)
-    {
-        return admEmsEcoDMapper.selectAdmEmsEcoDList(admEmsEcoD);
-    }
-
-    /**
-     * 新增节能计量日
-     * 
-     * @param admEmsEcoD 节能计量日
-     * @return 结果
-     */
-    @Override
-    public int insertAdmEmsEcoD(AdmEmsEcoD admEmsEcoD)
-    {
-        return admEmsEcoDMapper.insertAdmEmsEcoD(admEmsEcoD);
-    }
-
-    /**
-     * 修改节能计量日
-     * 
-     * @param admEmsEcoD 节能计量日
-     * @return 结果
-     */
-    @Override
-    public int updateAdmEmsEcoD(AdmEmsEcoD admEmsEcoD)
-    {
-        return admEmsEcoDMapper.updateAdmEmsEcoD(admEmsEcoD);
-    }
-
-    /**
-     * 批量删除节能计量日
-     * 
-     * @param ids 需要删除的节能计量日主键
-     * @return 结果
-     */
-    @Override
-    public int deleteAdmEmsEcoDByIds(Long[] ids)
-    {
-        return admEmsEcoDMapper.deleteAdmEmsEcoDByIds(ids);
-    }
-
-    /**
-     * 删除节能计量日信息
-     * 
-     * @param id 节能计量日主键
-     * @return 结果
-     */
-    @Override
-    public int deleteAdmEmsEcoDById(Long id)
-    {
-        return admEmsEcoDMapper.deleteAdmEmsEcoDById(id);
-    }
-
-    @Override
-    public AdmEmsEcoD calcAdmEmsEcoDateRange(AdmEmsEcoD admEmsEcoD){
-        return admEmsEcoDMapper.calcAdmEmsEcoDateRange(admEmsEcoD);
-    }
-}

+ 8 - 8
ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/BoundaryObjServiceImpl.java

@@ -14,7 +14,7 @@ import com.huashe.common.exception.Assert;
 import com.huashe.common.exception.BusinessException;
 import com.ruoyi.ems.core.BaseCache;
 import com.ruoyi.ems.domain.Area;
-import com.ruoyi.ems.domain.ElecMeter;
+import com.ruoyi.ems.domain.EnergyMeter;
 import com.ruoyi.ems.domain.ElecMeterH;
 import com.ruoyi.ems.domain.FacsCategory;
 import com.ruoyi.ems.domain.FacsSubCategory;
@@ -116,21 +116,21 @@ public class BoundaryObjServiceImpl implements IBoundaryObjService {
      * @return 返回电表信息列表,如果未找到符合条件的数据,则返回空列表
      */
     @Override
-    public List<ElecMeter> getMeterStaByFacsCategory(QueryMeter queryMeter) {
-        List<ElecMeter> result = new ArrayList<>();
+    public List<EnergyMeter> getMeterStaByFacsCategory(QueryMeter queryMeter) {
+        List<EnergyMeter> result = new ArrayList<>();
         List<BoundaryObj> bObjs = emsFacsService.getFacsWithMeterDev(queryMeter.getAreaCode(),
             queryMeter.getFacsCategory(), queryMeter.getFacsSubCategory());
 
         if (CollectionUtils.isNotEmpty(bObjs)) {
             for (BoundaryObj bObj : bObjs) {
-                ElecMeter meter = new ElecMeter();
+                EnergyMeter meter = new EnergyMeter();
                 meter.setAreaCode(queryMeter.getAreaCode());
                 meter.setObjType(bObj.getObjType());
                 meter.setObjCode(bObj.getObjCode());
                 meter.setObjName(bObj.getObjName());
 
                 if (CollectionUtils.isNotEmpty(bObj.getBindElecMeterDevs())) {
-                    ElecMeter staObj = getElecMeter(queryMeter, bObj);
+                    EnergyMeter staObj = getElecMeter(queryMeter, bObj);
 
                     if (null != staObj) {
                         meter.setQuantity(staObj.getQuantity());
@@ -190,7 +190,7 @@ public class BoundaryObjServiceImpl implements IBoundaryObjService {
     }
 
     @Override
-    public List<ElecMeter> getMeterStaByBoundaryObj(QueryMeter queryMeter) {
+    public List<EnergyMeter> getMeterStaByBoundaryObj(QueryMeter queryMeter) {
         return Collections.emptyList();
     }
 
@@ -199,7 +199,7 @@ public class BoundaryObjServiceImpl implements IBoundaryObjService {
         return Collections.emptyList();
     }
 
-    private ElecMeter getElecMeter(QueryMeter queryMeter, BoundaryObj bObj) {
+    private EnergyMeter getElecMeter(QueryMeter queryMeter, BoundaryObj bObj) {
         QueryMeter condition = new QueryMeter();
         condition.setAreaCode(queryMeter.getAreaCode());
         condition.setObjType(MeterObjType.METER_FACS.getType());
@@ -209,7 +209,7 @@ public class BoundaryObjServiceImpl implements IBoundaryObjService {
         condition.setEndRecTime(queryMeter.getEndRecTime());
         condition.setDeviceCodes(bObj.getBindElecMeterDevs());
 
-        ElecMeter meterRes = elecMeterHService.staByMeterDev(condition);
+        EnergyMeter meterRes = elecMeterHService.staByMeterDev(condition);
         return meterRes;
     }
 

+ 9 - 4
ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/ElecMeterHServiceImpl.java

@@ -1,6 +1,6 @@
 package com.ruoyi.ems.service.impl;
 
-import com.ruoyi.ems.domain.ElecMeter;
+import com.ruoyi.ems.domain.EnergyMeter;
 import com.ruoyi.ems.domain.ElecMeterH;
 import com.ruoyi.ems.mapper.ElecMeterHMapper;
 import com.ruoyi.ems.model.QueryMeter;
@@ -44,7 +44,7 @@ public class ElecMeterHServiceImpl implements IElecMeterHService {
     }
 
     @Override
-    public List<ElecMeter> staByTime(QueryMeter queryMeter) {
+    public List<EnergyMeter> staByTime(QueryMeter queryMeter) {
         return elecMeterHMapper.selectStaByTime(queryMeter);
     }
 
@@ -55,11 +55,16 @@ public class ElecMeterHServiceImpl implements IElecMeterHService {
      * @return 统计电量信息
      */
     @Override
-    public ElecMeter staByMeterDev(QueryMeter queryMeter) {
+    public EnergyMeter staByMeterDev(QueryMeter queryMeter) {
         return elecMeterHMapper.selectElecMeterSumByDev(queryMeter);
     }
 
     @Override
+    public EnergyMeter selectElecDayAvg(QueryMeter queryMeter) {
+        return elecMeterHMapper.selectElecDayAvg(queryMeter);
+    }
+
+    @Override
     public ElecMeterH selectLatelyItem(String deviceCode) {
         return elecMeterHMapper.selectLatelyItem(deviceCode);
     }
@@ -103,7 +108,7 @@ public class ElecMeterHServiceImpl implements IElecMeterHService {
     }
 
     @Override
-    public ElecMeterH qryElecMeterByDate(String dateRange, String areaCode) {
+    public EnergyMeter qryElecMeterByDate(String dateRange, String areaCode) {
         return elecMeterHMapper.qryElecMeterByDate(new ElecMeterH() {{
             setStartRecTime(dateRange);
             setAreaCode(areaCode);

+ 98 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/EmsEcoDServiceImpl.java

@@ -0,0 +1,98 @@
+package com.ruoyi.ems.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.ems.mapper.EmsEcoDMapper;
+import com.ruoyi.ems.domain.EmsEcoD;
+import com.ruoyi.ems.service.IEmsEcoDService;
+
+/**
+ * 节能计量日Service业务层处理
+ * 
+ * @author ruoyi
+ * @date 2025-04-22
+ */
+@Service
+public class EmsEcoDServiceImpl implements IEmsEcoDService
+{
+    @Autowired
+    private EmsEcoDMapper emsEcoDMapper;
+
+    /**
+     * 查询节能计量日
+     * 
+     * @param id 节能计量日主键
+     * @return 节能计量日
+     */
+    @Override
+    public EmsEcoD selectEmsEcoDById(Long id)
+    {
+        return emsEcoDMapper.selectEmsEcoDById(id);
+    }
+
+    /**
+     * 查询节能计量日列表
+     * 
+     * @param emsEcoD 节能计量日
+     * @return 节能计量日
+     */
+    @Override
+    public List<EmsEcoD> selectEmsEcoDList(EmsEcoD emsEcoD)
+    {
+        return emsEcoDMapper.selectEmsEcoDList(emsEcoD);
+    }
+
+    /**
+     * 新增节能计量日
+     * 
+     * @param emsEcoD 节能计量日
+     * @return 结果
+     */
+    @Override
+    public int insertEmsEcoD(EmsEcoD emsEcoD)
+    {
+        return emsEcoDMapper.insertEmsEcoD(emsEcoD);
+    }
+
+    /**
+     * 修改节能计量日
+     * 
+     * @param emsEcoD 节能计量日
+     * @return 结果
+     */
+    @Override
+    public int updateEmsEcoD(EmsEcoD emsEcoD)
+    {
+        return emsEcoDMapper.updateEmsEcoD(emsEcoD);
+    }
+
+    /**
+     * 批量删除节能计量日
+     * 
+     * @param ids 需要删除的节能计量日主键
+     * @return 结果
+     */
+    @Override
+    public int deleteEmsEcoDByIds(Long[] ids)
+    {
+        return emsEcoDMapper.deleteEmsEcoDByIds(ids);
+    }
+
+    /**
+     * 删除节能计量日信息
+     * 
+     * @param id 节能计量日主键
+     * @return 结果
+     */
+    @Override
+    public int deleteEmsEcoDById(Long id)
+    {
+        return emsEcoDMapper.deleteEmsEcoDById(id);
+    }
+
+    @Override
+    public EmsEcoD calcEmsEcoDateRange(EmsEcoD emsEcoD){
+        return emsEcoDMapper.calcEmsEcoDateRange(emsEcoD);
+    }
+}

+ 6 - 2
ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/WaterMeterHServiceImpl.java

@@ -1,6 +1,7 @@
 package com.ruoyi.ems.service.impl;
 
 import com.huashe.common.utils.DateUtils;
+import com.ruoyi.ems.domain.EnergyMeter;
 import com.ruoyi.ems.domain.WaterMeterH;
 import com.ruoyi.ems.mapper.WaterMeterHMapper;
 import com.ruoyi.ems.model.QueryMeter;
@@ -68,7 +69,7 @@ public class WaterMeterHServiceImpl implements IWaterMeterHService {
 
 
     @Override
-    public WaterMeterH qryWaterMeterByDate(String dataRange, String areaCode) {
+    public EnergyMeter qryWaterMeterByDate(String dataRange, String areaCode) {
         return waterMeterHMapper.qryWaterMeterByDate(new WaterMeterH(){{
             setStartRecTime(dataRange);
             setAreaCode(areaCode);
@@ -90,5 +91,8 @@ public class WaterMeterHServiceImpl implements IWaterMeterHService {
         return waterMeterHMapper.qryDateWaterMeterByYear(dataRange);
     }
 
-
+    @Override
+    public EnergyMeter selectWaterDayAvg(QueryMeter queryMeter) {
+        return waterMeterHMapper.selectWaterDayAvg(queryMeter);
+    }
 }

+ 26 - 2
ems/ems-core/src/main/resources/mapper/ems/ElecMeterHMapper.xml

@@ -21,7 +21,7 @@
         <result property="createTime" column="create_time"/>
     </resultMap>
 
-    <resultMap type="com.ruoyi.ems.domain.ElecMeter" id="ElecMeterResult">
+    <resultMap type="com.ruoyi.ems.domain.EnergyMeter" id="ElecMeterResult">
         <result property="areaCode" column="area_code"/>
         <result property="objType" column="obj_type"/>
         <result property="objCode" column="obj_code"/>
@@ -116,6 +116,30 @@
         </where>
     </select>
 
+    <select id="selectElecDayAvg" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="ElecMeterResult">
+        select
+        <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
+            area_code,
+        </if>
+        <if test="deviceCode != null and deviceCode != ''">
+            device_code,
+        </if>
+        SUM(elec_quantity) / COUNT(DISTINCT date) AS elec_quantity,
+        SUM(use_elec_cost) / COUNT(DISTINCT date) AS use_elec_cost
+        from adm_elec_meter_h h
+        <where>
+            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
+                and h.area_code = #{areaCode}
+            </if>
+            <if test="deviceCode != null and deviceCode != ''">
+                and h.device_code = #{deviceCode}
+            </if>
+            <if test="startRecTime != null and startRecTime != '' and endRecTime != null and endRecTime != ''">
+                and h.`date` &gt;= #{startRecTime} and h.`date` &lt;= #{endRecTime}
+            </if>
+        </where>
+    </select>
+
     <select id="selectStaByTime" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="ElecMeterResult">
         SELECT
         meter_type as obj_code,
@@ -214,7 +238,7 @@
     </delete>
 
 
-    <select id="qryElecMeterByDate" parameterType="ElecMeterH" resultMap="ElecMeterHResult">
+    <select id="qryElecMeterByDate" parameterType="com.ruoyi.ems.domain.ElecMeterH" resultMap="ElecMeterResult">
         SELECT sum(elec_quantity) elec_quantity,
         SUM(use_elec_cost) use_elec_cost
         from adm_elec_meter_h aemh

+ 104 - 0
ems/ems-core/src/main/resources/mapper/ems/EmsEcoDMapper.xml

@@ -0,0 +1,104 @@
+<?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.ruoyi.ems.mapper.EmsEcoDMapper">
+    
+    <resultMap type="EmsEcoD" id="AdmEmsEcoDResult">
+        <result property="id"    column="id"    />
+        <result property="areaCode"    column="area_code"    />
+        <result property="date"    column="date"    />
+        <result property="elecEcoQuantity"    column="elec_eco_quantity"    />
+        <result property="elecEcoCost"    column="elec_eco_cost"    />
+        <result property="waterEcoQuantity"    column="water_eco_quantity"    />
+        <result property="waterEcoCost"    column="water_eco_cost"    />
+    </resultMap>
+
+    <sql id="selectEmsEcoDVo">
+        select id, area_code, date, elec_eco_quantity, elec_eco_cost, water_eco_quantity, water_eco_cost from adm_ems_eco_d
+    </sql>
+
+    <select id="selectEmsEcoDList" parameterType="EmsEcoD" resultMap="AdmEmsEcoDResult">
+        select d.id, area.area_code, area.area_name, d.`date`, d.elec_eco_quantity, d.elec_eco_cost, d.water_eco_quantity,
+        water_eco_cost from adm_ems_eco_d d
+        inner join adm_area area on area.area_code = d.area_code and area.parent_code = '0'
+        <where>
+            <if test="areaCode != null  and areaCode != '' and areaCode != '-1'">and d.area_code = #{areaCode}</if>
+            <if test="startRecTime != null  and startRecTime != '' and endRecTime != null and endRecTime !=''">
+                and d.`date` &gt;= #{startRecTime} and d.`date` &lt;= #{endRecTime}
+            </if>
+        </where>
+        order by date desc
+    </select>
+    
+    <select id="selectEmsEcoDById" parameterType="Long" resultMap="AdmEmsEcoDResult">
+        <include refid="selectEmsEcoDVo"/>
+        where id = #{id}
+    </select>
+        
+    <insert id="insertEmsEcoD" parameterType="EmsEcoD" useGeneratedKeys="true" keyProperty="id">
+        insert into adm_ems_eco_d
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="areaCode != null and areaCode != ''">area_code,</if>
+            <if test="date != null">date,</if>
+            <if test="elecEcoQuantity != null">elec_eco_quantity,</if>
+            <if test="elecEcoCost != null">elec_eco_cost,</if>
+            <if test="waterEcoQuantity != null">water_eco_quantity,</if>
+            <if test="waterEcoCost != null">water_eco_cost,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="areaCode != null and areaCode != ''">#{areaCode},</if>
+            <if test="date != null">#{date},</if>
+            <if test="elecEcoQuantity != null">#{elecEcoQuantity},</if>
+            <if test="elecEcoCost != null">#{elecEcoCost},</if>
+            <if test="waterEcoQuantity != null">#{waterEcoQuantity},</if>
+            <if test="waterEcoCost != null">#{waterEcoCost},</if>
+         </trim>
+    </insert>
+
+    <update id="updateEmsEcoD" parameterType="EmsEcoD">
+        update adm_ems_eco_d
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="areaCode != null and areaCode != ''">area_code = #{areaCode},</if>
+            <if test="date != null">date = #{date},</if>
+            <if test="elecEcoQuantity != null">elec_eco_quantity = #{elecEcoQuantity},</if>
+            <if test="elecEcoCost != null">elec_eco_cost = #{elecEcoCost},</if>
+            <if test="waterEcoQuantity != null">water_eco_quantity = #{waterEcoQuantity},</if>
+            <if test="waterEcoCost != null">water_eco_cost = #{waterEcoCost},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteEmsEcoDById" parameterType="Long">
+        delete from adm_ems_eco_d where id = #{id}
+    </delete>
+
+    <delete id="deleteEmsEcoDByIds" parameterType="String">
+        delete from adm_ems_eco_d where id in 
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+    <delete id="deleteEmsEcoD" parameterType="String">
+        delete from adm_ems_eco_d where `date` = #{date} and area_code = #{areaCode}
+    </delete>
+
+    <select id="calcEmsEcoDateRange" parameterType="EmsEcoD" resultMap="AdmEmsEcoDResult">
+        select sum(
+        COALESCE(CAST(elec_eco_quantity AS DECIMAL(10, 2)), 0)) elec_eco_quantity,
+        sum(
+        COALESCE(CAST(elec_eco_cost AS DECIMAL(10, 2)), 0)) elec_eco_cost,
+        sum(
+        COALESCE(CAST(water_eco_quantity AS DECIMAL(10, 2)), 0)) water_eco_quantity,
+        sum(
+        COALESCE(CAST(water_eco_cost AS DECIMAL(10, 2)), 0)) water_eco_cost
+        from adm_ems_eco_d d
+        <where>
+            <if test="date != null and date != ''">DATE like concat(#{date}, '%')</if>
+            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
+                and area_code = #{areaCode}
+            </if>
+        </where>
+    </select>
+</mapper>

+ 34 - 2
ems/ems-core/src/main/resources/mapper/ems/WaterMeterHMapper.xml

@@ -19,6 +19,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="useWaterCost"    column="use_water_cost"    />
     </resultMap>
 
+    <resultMap type="com.ruoyi.ems.domain.EnergyMeter" id="WaterMeterResult">
+        <result property="areaCode" column="area_code"/>
+        <result property="objType" column="obj_type"/>
+        <result property="objCode" column="obj_code"/>
+        <result property="objName" column="obj_name"/>
+        <result property="quantity" column="water_quantity"/>
+        <result property="useCost" column="use_water_cost"/>
+    </resultMap>
+
     <sql id="selectWaterMeterHVo">
         select id, area_code, device_code, record_time, `date`, `time`, time_index, water_quantity, meter_unit_price, use_water_cost, create_time from adm_water_meter_h
     </sql>
@@ -114,13 +123,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         delete from adm_water_meter_h where `date` = #{date}
     </delete>
 
-    <select id="qryWaterMeterByDate" parameterType="WaterMeterH" resultMap="WaterMeterHResult">
+    <select id="qryWaterMeterByDate" parameterType="WaterMeterH" resultMap="WaterMeterResult">
         SELECT sum(water_quantity) water_quantity,
                SUM(use_water_cost) use_water_cost
         from adm_water_meter_h aemh
         where `date` like concat(#{startRecTime}, '%')
         <if test="areaCode != null and areaCode != ''">and aemh.area_code = #{areaCode}</if>
-
     </select>
 
     <select id="qryTimeIndexWaterMeterByDay" resultMap="WaterMeterHResult">
@@ -155,4 +163,28 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         order by
             startRecTime asc
     </select>
+
+    <select id="selectWaterDayAvg" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="WaterMeterResult">
+        select
+        <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
+            area_code,
+        </if>
+        <if test="deviceCode != null and deviceCode != ''">
+            device_code,
+        </if>
+        SUM(water_quantity) / COUNT(DISTINCT date) AS water_quantity,
+        SUM(use_water_cost) / COUNT(DISTINCT date) AS use_water_cost
+        from adm_water_meter_h h
+        <where>
+            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
+                and h.area_code = #{areaCode}
+            </if>
+            <if test="deviceCode != null and deviceCode != ''">
+                and h.device_code = #{deviceCode}
+            </if>
+            <if test="startRecTime != null and startRecTime != '' and endRecTime != null and endRecTime != ''">
+                and h.`date` &gt;= #{startRecTime} and h.`date` &lt;= #{endRecTime}
+            </if>
+        </where>
+    </select>
 </mapper>

+ 1 - 0
ems/sql/ems_server.sql

@@ -1143,6 +1143,7 @@ create table adm_pv_elecprice_config (
   unique key ux_pv_elecprice_config(`cfg_code`)
 ) engine=innodb auto_increment=1 comment = '光伏电价配置表';
 
+INSERT INTO `adm_pv_elecprice_config` (`cfg_code`, `price_name`, `obj_price`, `state_subsidy`, `local_subsidy`) VALUES ('0000', '默认价格', 0.88, 0.42, 0.3);
 
 -- ----------------------------
 -- 电价策略表