Browse Source

用能报表重构

learshaw 1 week ago
parent
commit
9a92b743f9
21 changed files with 2514 additions and 925 deletions
  1. 223 136
      ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/EnergyConsumptionController.java
  2. 66 0
      ems/ems-core/src/main/java/com/ruoyi/ems/mapper/ElecConsumptionMapper.java
  3. 0 137
      ems/ems-core/src/main/java/com/ruoyi/ems/mapper/EnergyConsumptionMapper.java
  4. 3 0
      ems/ems-core/src/main/java/com/ruoyi/ems/mapper/MeterBoundaryRelMapper.java
  5. 76 0
      ems/ems-core/src/main/java/com/ruoyi/ems/mapper/WaterConsumptionMapper.java
  6. 122 0
      ems/ems-core/src/main/java/com/ruoyi/ems/model/ElecConsumptionExportVO.java
  7. 231 0
      ems/ems-core/src/main/java/com/ruoyi/ems/model/ElecConsumptionVO.java
  8. 69 0
      ems/ems-core/src/main/java/com/ruoyi/ems/model/WaterConsumptionExportVO.java
  9. 27 76
      ems/ems-core/src/main/java/com/ruoyi/ems/model/WaterConsumptionVO.java
  10. 48 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/IElecConsumptionService.java
  11. 0 63
      ems/ems-core/src/main/java/com/ruoyi/ems/service/IEnergyConsumptionService.java
  12. 10 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/IMeterBoundaryRelService.java
  13. 58 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/IWaterConsumptionService.java
  14. 544 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/ElecConsumptionServiceImpl.java
  15. 0 142
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/EnergyConsumptionServiceImpl.java
  16. 6 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/MeterBoundaryRelServiceImpl.java
  17. 403 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/WaterConsumptionServiceImpl.java
  18. 327 0
      ems/ems-core/src/main/resources/mapper/ems/ElecConsumptionMapper.xml
  19. 0 371
      ems/ems-core/src/main/resources/mapper/ems/EnergyConsumptionMapper.xml
  20. 10 0
      ems/ems-core/src/main/resources/mapper/ems/MeterBoundaryRelMapper.xml
  21. 291 0
      ems/ems-core/src/main/resources/mapper/ems/WaterConsumptionMapper.xml

+ 223 - 136
ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/EnergyConsumptionController.java

@@ -1,25 +1,20 @@
-/*
- * 文 件 名:  EnergyConsumptionController
- * 版    权:  华设设计集团股份有限公司
- * 描    述:  <描述>
- * 修 改 人:  lvwenbin
- * 修改时间:  2025/8/26
- * 跟踪单号:  <跟踪单号>
- * 修改单号:  <修改单号>
- * 修改内容:  <修改内容>
- */
 package com.ruoyi.ems.controller;
 
 import com.huashe.common.domain.AjaxResult;
+import com.huashe.common.utils.ListUtils;
 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.model.EnergyConsumptionVO;
+import com.ruoyi.ems.model.ElecConsumptionVO;
+import com.ruoyi.ems.model.ElecConsumptionExportVO;
+import com.ruoyi.ems.model.WaterConsumptionVO;
+import com.ruoyi.ems.model.WaterConsumptionExportVO;
 import com.ruoyi.ems.model.QueryMeter;
-import com.ruoyi.ems.service.IEnergyConsumptionService;
+import com.ruoyi.ems.service.IElecConsumptionService;
+import com.ruoyi.ems.service.IWaterConsumptionService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
@@ -34,7 +29,7 @@ import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
- * 用能统计分析Controller
+ * 用能统计分析Controller - 重构版本
  *
  * @author ruoyi
  * @date 2024-12-20
@@ -45,204 +40,296 @@ import java.util.List;
 public class EnergyConsumptionController extends BaseController {
 
     @Autowired
-    private IEnergyConsumptionService energyConsumptionService;
+    private IElecConsumptionService elecConsumptionService;
+
+    @Autowired
+    private IWaterConsumptionService waterConsumptionService;
 
-    // ==================== 区域用能统计 ====================
+    // ==================== 区域用统计 ====================
 
     /**
-     * 查询区域用统计列表
+     * 查询区域用统计列表
      */
     @RequiresPermissions("ems:consumption:list")
-    @GetMapping("/area/list")
-    @ApiOperation("查询区域用能统计列表")
-    public TableDataInfo getAreaConsumptionList(@ApiParam("查询参数") QueryMeter queryMeter) {
-        // 参数校验和默认值设置
-        if (queryMeter == null) {
-            queryMeter = new QueryMeter();
-        }
+    @GetMapping("/area/elec/list")
+    @ApiOperation("查询区域用电统计列表")
+    public TableDataInfo getAreaElecConsumptionList(@ApiParam("查询参数") QueryMeter queryMeter) {
+        validateAndSetDefaults(queryMeter);
+        queryMeter.setObjType(1);
 
-        // 设置默认时间维度
-        if (StringUtils.isBlank(queryMeter.getTimeDimension())) {
-            queryMeter.setTimeDimension("month");
-        }
+        List<ElecConsumptionVO> list = elecConsumptionService.selectAreaElecConsumptionList(queryMeter);
+        int total = list.size();
+        list = ListUtils.subList(list, (queryMeter.getPageNum() - 1) * queryMeter.getPageSize(),
+            queryMeter.getPageNum() * queryMeter.getPageSize() - 1);
 
-        // 设置对象类型
-        queryMeter.setObjType(1);
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(200);
+        rspData.setRows(list);
+        rspData.setMsg("查询成功");
+        rspData.setTotal(total);
 
-        startPage();
-        List<EnergyConsumptionVO> list = energyConsumptionService.selectAreaConsumptionList(queryMeter);
-        return getDataTable(list);
+        return rspData;
     }
 
     /**
-     * 查询区域用统计汇总
+     * 查询区域用统计汇总
      */
     @RequiresPermissions("ems:consumption:list")
-    @GetMapping("/area/summary")
-    @ApiOperation("查询区域用能统计汇总")
-    public AjaxResult getAreaConsumptionSummary(@ApiParam("查询参数") QueryMeter queryMeter) {
-        if (queryMeter == null) {
-            queryMeter = new QueryMeter();
-        }
-
+    @GetMapping("/area/elec/summary")
+    @ApiOperation("查询区域用电统计汇总")
+    public AjaxResult getAreaElecConsumptionSummary(@ApiParam("查询参数") QueryMeter queryMeter) {
+        validateAndSetDefaults(queryMeter);
         queryMeter.setObjType(1);
-        EnergyConsumptionVO summary = energyConsumptionService.selectAreaConsumptionSummary(queryMeter);
+
+        ElecConsumptionVO summary = elecConsumptionService.selectAreaElecConsumptionSummary(queryMeter);
         return success(summary);
     }
 
     /**
-     * 导出区域用统计数据
+     * 导出区域用统计数据
      */
     @RequiresPermissions("ems:consumption:export")
-    @Log(title = "区域用能统计", businessType = BusinessType.EXPORT)
-    @PostMapping("/area/export")
-    @ApiOperation("导出区域用能统计数据")
-    public void exportAreaConsumption(HttpServletResponse response, @ApiParam("查询参数") QueryMeter queryMeter) {
-        if (queryMeter == null) {
-            queryMeter = new QueryMeter();
-        }
-
-        if (StringUtils.isBlank(queryMeter.getTimeDimension())) {
-            queryMeter.setTimeDimension("month");
-        }
-
+    @Log(title = "区域用电统计", businessType = BusinessType.EXPORT)
+    @PostMapping("/area/elec/export")
+    @ApiOperation("导出区域用电统计数据")
+    public void exportAreaElecConsumption(HttpServletResponse response, @ApiParam("查询参数") QueryMeter queryMeter) {
+        validateAndSetDefaults(queryMeter);
         queryMeter.setObjType(1);
-        List<EnergyConsumptionVO> list = energyConsumptionService.exportAreaConsumptionList(queryMeter);
 
-        ExcelUtil<EnergyConsumptionVO> util = new ExcelUtil<>(EnergyConsumptionVO.class);
-        String fileName = String.format("区域用能统计_%s_%s.xlsx",
-            queryMeter.getTimeDimension(),
+        List<ElecConsumptionVO> list = elecConsumptionService.exportAreaElecConsumptionList(queryMeter);
+        // 转换为导出VO
+        List<ElecConsumptionExportVO> exportList = elecConsumptionService.convertToElecExportVOList(list,
+            queryMeter.getTimeDimension());
+
+        ExcelUtil<ElecConsumptionExportVO> util = new ExcelUtil<>(ElecConsumptionExportVO.class);
+        String fileName = String.format("区域用电统计_%s_%s.xlsx", queryMeter.getTimeDimension(),
             System.currentTimeMillis());
-        util.exportExcel(response, list, fileName);
+        util.exportExcel(response, exportList, fileName);
     }
 
-    // ==================== 设施用统计 ====================
+    // ==================== 设施用统计 ====================
 
     /**
-     * 查询设施用统计列表
+     * 查询设施用统计列表
      */
     @RequiresPermissions("ems:consumption:list")
-    @GetMapping("/facs/list")
-    @ApiOperation("查询设施用能统计列表")
-    public TableDataInfo getFacsConsumptionList(@ApiParam("查询参数") QueryMeter queryMeter) {
-        // 参数校验和默认值设置
-        if (queryMeter == null) {
-            queryMeter = new QueryMeter();
-        }
-
-        // 设置默认时间维度
-        if (StringUtils.isBlank(queryMeter.getTimeDimension())) {
-            queryMeter.setTimeDimension("month");
-        }
-
-        // 设置默认设施分类
+    @GetMapping("/facs/elec/list")
+    @ApiOperation("查询设施用电统计列表")
+    public TableDataInfo getFacsElecConsumptionList(@ApiParam("查询参数") QueryMeter queryMeter) {
+        validateAndSetDefaults(queryMeter);
+        queryMeter.setObjType(2);
         if (StringUtils.isBlank(queryMeter.getFacsCategory())) {
             queryMeter.setFacsCategory("Z");
         }
 
-        // 设置对象类型
-        queryMeter.setObjType(2);
+        List<ElecConsumptionVO> list = elecConsumptionService.selectFacsElecConsumptionList(queryMeter);
+        int total = list.size();
+        list = ListUtils.subList(list, (queryMeter.getPageNum() - 1) * queryMeter.getPageSize(),
+            queryMeter.getPageNum() * queryMeter.getPageSize() - 1);
+
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(200);
+        rspData.setRows(list);
+        rspData.setMsg("查询成功");
+        rspData.setTotal(total);
 
-        startPage();
-        List<EnergyConsumptionVO> list = energyConsumptionService.selectFacsConsumptionList(queryMeter);
-        return getDataTable(list);
+        return rspData;
     }
 
     /**
-     * 查询设施用能统计汇总
+     * 查询设施用统计汇总
      */
     @RequiresPermissions("ems:consumption:list")
-    @GetMapping("/facs/summary")
-    @ApiOperation("查询设施用能统计汇总")
-    public AjaxResult getFacsConsumptionSummary(@ApiParam("查询参数") QueryMeter queryMeter) {
-        if (queryMeter == null) {
-            queryMeter = new QueryMeter();
-        }
-
+    @GetMapping("/facs/elec/summary")
+    @ApiOperation("查询设施用电统计汇总")
+    public AjaxResult getFacsElecConsumptionSummary(@ApiParam("查询参数") QueryMeter queryMeter) {
+        validateAndSetDefaults(queryMeter);
+        queryMeter.setObjType(2);
         if (StringUtils.isBlank(queryMeter.getFacsCategory())) {
             queryMeter.setFacsCategory("Z");
         }
 
-        queryMeter.setObjType(2);
-        EnergyConsumptionVO summary = energyConsumptionService.selectFacsConsumptionSummary(queryMeter);
+        ElecConsumptionVO summary = elecConsumptionService.selectFacsElecConsumptionSummary(queryMeter);
         return success(summary);
     }
 
     /**
-     * 导出设施用统计数据
+     * 导出设施用统计数据
      */
     @RequiresPermissions("ems:consumption:export")
-    @Log(title = "设施用能统计", businessType = BusinessType.EXPORT)
-    @PostMapping("/facs/export")
-    @ApiOperation("导出设施用能统计数据")
-    public void exportFacsConsumption(HttpServletResponse response, @ApiParam("查询参数") QueryMeter queryMeter) {
-        if (queryMeter == null) {
-            queryMeter = new QueryMeter();
-        }
-
-        if (StringUtils.isBlank(queryMeter.getTimeDimension())) {
-            queryMeter.setTimeDimension("month");
-        }
-
+    @Log(title = "设施用电统计", businessType = BusinessType.EXPORT)
+    @PostMapping("/facs/elec/export")
+    @ApiOperation("导出设施用电统计数据")
+    public void exportFacsElecConsumption(HttpServletResponse response, @ApiParam("查询参数") QueryMeter queryMeter) {
+        validateAndSetDefaults(queryMeter);
+        queryMeter.setObjType(2);
         if (StringUtils.isBlank(queryMeter.getFacsCategory())) {
             queryMeter.setFacsCategory("Z");
         }
 
-        queryMeter.setObjType(2);
-        List<EnergyConsumptionVO> list = energyConsumptionService.exportFacsConsumptionList(queryMeter);
+        List<ElecConsumptionVO> list = elecConsumptionService.exportFacsElecConsumptionList(queryMeter);
+        // 转换为导出VO
+        List<ElecConsumptionExportVO> exportList = elecConsumptionService.convertToElecExportVOList(list,
+            queryMeter.getTimeDimension());
 
-        ExcelUtil<EnergyConsumptionVO> util = new ExcelUtil<>(EnergyConsumptionVO.class);
-        String fileName = String.format("设施用能统计_%s_%s.xlsx",
-            queryMeter.getTimeDimension(),
+        ExcelUtil<ElecConsumptionExportVO> util = new ExcelUtil<>(ElecConsumptionExportVO.class);
+        String fileName = String.format("设施用电统计_%s_%s.xlsx", queryMeter.getTimeDimension(),
             System.currentTimeMillis());
-        util.exportExcel(response, list, fileName);
+        util.exportExcel(response, exportList, fileName);
     }
 
-    // ==================== 兼容性接口 ====================
+    // ==================== 区域用水统计 ====================
 
     /**
-     * 查询区域用能数据 (兼容旧接口)
+     * 查询区域用水统计列表
      */
     @RequiresPermissions("ems:consumption:list")
-    @GetMapping("/hour/listAreaMeter")
-    @ApiOperation("查询区域用能数据(兼容接口)")
-    @Deprecated
-    public TableDataInfo listAreaMeter(@ApiParam("查询参数") QueryMeter queryMeter) {
-        return getAreaConsumptionList(queryMeter);
+    @GetMapping("/area/water/list")
+    @ApiOperation("查询区域用水统计列表")
+    public TableDataInfo getAreaWaterConsumptionList(@ApiParam("查询参数") QueryMeter queryMeter) {
+        validateAndSetDefaults(queryMeter);
+        queryMeter.setObjType(1);
+
+        List<WaterConsumptionVO> list = waterConsumptionService.selectAreaWaterConsumptionList(queryMeter);
+        int total = list.size();
+        list = ListUtils.subList(list, (queryMeter.getPageNum() - 1) * queryMeter.getPageSize(),
+            queryMeter.getPageNum() * queryMeter.getPageSize() - 1);
+
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(200);
+        rspData.setRows(list);
+        rspData.setMsg("查询成功");
+        rspData.setTotal(total);
+
+        return rspData;
     }
 
     /**
-     * 查询设施用能数据 (兼容旧接口)
+     * 查询区域用水统计汇总
      */
     @RequiresPermissions("ems:consumption:list")
-    @GetMapping("/hour/listFacsMeter")
-    @ApiOperation("查询设施用能数据(兼容接口)")
-    @Deprecated
-    public TableDataInfo listFacsMeter(@ApiParam("查询参数") QueryMeter queryMeter) {
-        return getFacsConsumptionList(queryMeter);
+    @GetMapping("/area/water/summary")
+    @ApiOperation("查询区域用水统计汇总")
+    public AjaxResult getAreaWaterConsumptionSummary(@ApiParam("查询参数") QueryMeter queryMeter) {
+        validateAndSetDefaults(queryMeter);
+        queryMeter.setObjType(1);
+
+        WaterConsumptionVO summary = waterConsumptionService.selectAreaWaterConsumptionSummary(queryMeter);
+        return success(summary);
     }
 
     /**
-     * 导出区域用能数据 (兼容旧接口)
+     * 导出区域用水统计数据
      */
     @RequiresPermissions("ems:consumption:export")
-    @Log(title = "区域用能统计", businessType = BusinessType.EXPORT)
-    @PostMapping("/exportAreaMeter")
-    @ApiOperation("导出区域用能数据(兼容接口)")
-    @Deprecated
-    public void exportAreaMeter(HttpServletResponse response, @ApiParam("查询参数") QueryMeter queryMeter) {
-        exportAreaConsumption(response, queryMeter);
+    @Log(title = "区域用水统计", businessType = BusinessType.EXPORT)
+    @PostMapping("/area/water/export")
+    @ApiOperation("导出区域用水统计数据")
+    public void exportAreaWaterConsumption(HttpServletResponse response, @ApiParam("查询参数") QueryMeter queryMeter) {
+        validateAndSetDefaults(queryMeter);
+        queryMeter.setObjType(1);
+
+        List<WaterConsumptionVO> list = waterConsumptionService.exportAreaWaterConsumptionList(queryMeter);
+        // 转换为导出VO
+        List<WaterConsumptionExportVO> exportList = waterConsumptionService.convertToWaterExportVOList(list,
+            queryMeter.getTimeDimension());
+
+        ExcelUtil<WaterConsumptionExportVO> util = new ExcelUtil<>(WaterConsumptionExportVO.class);
+        String fileName = String.format("区域用水统计_%s_%s.xlsx", queryMeter.getTimeDimension(),
+            System.currentTimeMillis());
+        util.exportExcel(response, exportList, fileName);
+    }
+
+    // ==================== 设施用水统计 ====================
+
+    /**
+     * 查询设施用水统计列表
+     */
+    @RequiresPermissions("ems:consumption:list")
+    @GetMapping("/facs/water/list")
+    @ApiOperation("查询设施用水统计列表")
+    public TableDataInfo getFacsWaterConsumptionList(@ApiParam("查询参数") QueryMeter queryMeter) {
+        validateAndSetDefaults(queryMeter);
+        queryMeter.setObjType(2);
+        if (StringUtils.isBlank(queryMeter.getFacsCategory())) {
+            queryMeter.setFacsCategory("Z");
+        }
+
+        List<WaterConsumptionVO> list = waterConsumptionService.selectFacsWaterConsumptionList(queryMeter);
+
+        int total = list.size();
+        list = ListUtils.subList(list, (queryMeter.getPageNum() - 1) * queryMeter.getPageSize(),
+            queryMeter.getPageNum() * queryMeter.getPageSize() - 1);
+
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(200);
+        rspData.setRows(list);
+        rspData.setMsg("查询成功");
+        rspData.setTotal(total);
+
+        return rspData;
+    }
+
+    /**
+     * 查询设施用水统计汇总
+     */
+    @RequiresPermissions("ems:consumption:list")
+    @GetMapping("/facs/water/summary")
+    @ApiOperation("查询设施用水统计汇总")
+    public AjaxResult getFacsWaterConsumptionSummary(@ApiParam("查询参数") QueryMeter queryMeter) {
+        validateAndSetDefaults(queryMeter);
+        queryMeter.setObjType(2);
+        if (StringUtils.isBlank(queryMeter.getFacsCategory())) {
+            queryMeter.setFacsCategory("Z");
+        }
+
+        WaterConsumptionVO summary = waterConsumptionService.selectFacsWaterConsumptionSummary(queryMeter);
+        return success(summary);
     }
 
     /**
-     * 导出设施用能数据 (兼容旧接口)
+     * 导出设施用水统计数据
      */
     @RequiresPermissions("ems:consumption:export")
-    @Log(title = "设施用能统计", businessType = BusinessType.EXPORT)
-    @PostMapping("/exportFacsMeter")
-    @ApiOperation("导出设施用能数据(兼容接口)")
-    @Deprecated
-    public void exportFacsMeter(HttpServletResponse response, @ApiParam("查询参数") QueryMeter queryMeter) {
-        exportFacsConsumption(response, queryMeter);
+    @Log(title = "设施用水统计", businessType = BusinessType.EXPORT)
+    @PostMapping("/facs/water/export")
+    @ApiOperation("导出设施用水统计数据")
+    public void exportFacsWaterConsumption(HttpServletResponse response, @ApiParam("查询参数") QueryMeter queryMeter) {
+        validateAndSetDefaults(queryMeter);
+        queryMeter.setObjType(2);
+        if (StringUtils.isBlank(queryMeter.getFacsCategory())) {
+            queryMeter.setFacsCategory("Z");
+        }
+
+        List<WaterConsumptionVO> list = waterConsumptionService.exportFacsWaterConsumptionList(queryMeter);
+        // 转换为导出VO
+        List<WaterConsumptionExportVO> exportList = waterConsumptionService.convertToWaterExportVOList(list,
+            queryMeter.getTimeDimension());
+
+        ExcelUtil<WaterConsumptionExportVO> util = new ExcelUtil<>(WaterConsumptionExportVO.class);
+        String fileName = String.format("设施用水统计_%s_%s.xlsx", queryMeter.getTimeDimension(),
+            System.currentTimeMillis());
+        util.exportExcel(response, exportList, fileName);
+    }
+
+    // ==================== 参数校验方法 ====================
+
+    /**
+     * 校验并设置默认参数
+     */
+    private void validateAndSetDefaults(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            throw new IllegalArgumentException("查询参数不能为空");
+        }
+
+        // 设置默认时间维度
+        if (StringUtils.isBlank(queryMeter.getTimeDimension())) {
+            queryMeter.setTimeDimension("month");
+        }
+
+        // 设置默认排序
+        if (StringUtils.isBlank(queryMeter.getOrderFlag())) {
+            queryMeter.setOrderFlag("desc");
+        }
     }
 }

+ 66 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/mapper/ElecConsumptionMapper.java

@@ -0,0 +1,66 @@
+package com.ruoyi.ems.mapper;
+
+import com.ruoyi.ems.model.ElecConsumptionVO;
+import com.ruoyi.ems.model.QueryMeter;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 用电统计Mapper接口
+ */
+public interface ElecConsumptionMapper {
+
+    // ==================== 区域用电统计方法 ====================
+
+    /**
+     * 根据设备代码列表查询区域日用电统计
+     */
+    List<ElecConsumptionVO> selectAreaDailyElecConsumptionByDevices(
+        @Param("queryMeter") QueryMeter queryMeter,
+        @Param("meterDevices") Set<String> meterDevices);
+
+    /**
+     * 根据设备代码列表查询区域月用电统计
+     */
+    List<ElecConsumptionVO> selectAreaMonthlyElecConsumptionByDevices(
+        @Param("queryMeter") QueryMeter queryMeter,
+        @Param("meterDevices") Set<String> meterDevices);
+
+    /**
+     * 根据设备代码列表查询区域年用电统计
+     */
+    List<ElecConsumptionVO> selectAreaYearlyElecConsumptionByDevices(
+        @Param("queryMeter") QueryMeter queryMeter,
+        @Param("meterDevices") Set<String> meterDevices);
+
+    /**
+     * 根据设备代码列表查询区域用电汇总
+     */
+    ElecConsumptionVO selectAreaElecConsumptionSummaryByDevices(
+        @Param("queryMeter") QueryMeter queryMeter,
+        @Param("meterDevices") Set<String> meterDevices);
+
+    // ==================== 设施用电统计方法 ====================
+
+    /**
+     * 查询设施日用电统计
+     */
+    List<ElecConsumptionVO> selectFacsDailyElecConsumption(QueryMeter queryMeter);
+
+    /**
+     * 查询设施月用电统计
+     */
+    List<ElecConsumptionVO> selectFacsMonthlyElecConsumption(QueryMeter queryMeter);
+
+    /**
+     * 查询设施年用电统计
+     */
+    List<ElecConsumptionVO> selectFacsYearlyElecConsumption(QueryMeter queryMeter);
+
+    /**
+     * 查询设施用电统计汇总
+     */
+    ElecConsumptionVO selectFacsElecConsumptionSummary(QueryMeter queryMeter);
+}

+ 0 - 137
ems/ems-core/src/main/java/com/ruoyi/ems/mapper/EnergyConsumptionMapper.java

@@ -1,137 +0,0 @@
-/*
- * 文 件 名:  EnergyConsumptionMapper
- * 版    权:  华设设计集团股份有限公司
- * 描    述:  <描述>
- * 修 改 人:  lvwenbin
- * 修改时间:  2025/8/26
- * 跟踪单号:  <跟踪单号>
- * 修改单号:  <修改单号>
- * 修改内容:  <修改内容>
- */
-package com.ruoyi.ems.mapper;
-
-/**
- * <一句话功能简述>
- * <功能详细描述>
- *
- * @author lvwenbin
- * @version [版本号, 2025/8/26]
- * @see [相关类/方法]
- * @since [产品/模块版本]
- */
-import com.ruoyi.ems.model.EnergyConsumptionVO;
-import com.ruoyi.ems.model.QueryMeter;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-/**
- * 用能统计Mapper接口
- *
- * @author ruoyi
- * @date 2024-12-20
- */
-public interface EnergyConsumptionMapper {
-
-    // ==================== 区域用能统计 ====================
-
-    /**
-     * 查询区域日用能统计
-     *
-     * @param queryMeter 查询参数
-     * @return 区域日用能统计列表
-     */
-    List<EnergyConsumptionVO> selectAreaDailyConsumption(QueryMeter queryMeter);
-
-    /**
-     * 查询区域月用能统计
-     *
-     * @param queryMeter 查询参数
-     * @return 区域月用能统计列表
-     */
-    List<EnergyConsumptionVO> selectAreaMonthlyConsumption(QueryMeter queryMeter);
-
-    /**
-     * 查询区域年用能统计
-     *
-     * @param queryMeter 查询参数
-     * @return 区域年用能统计列表
-     */
-    List<EnergyConsumptionVO> selectAreaYearlyConsumption(QueryMeter queryMeter);
-
-    /**
-     * 查询区域用能统计汇总
-     *
-     * @param queryMeter 查询参数
-     * @return 区域用能统计汇总
-     */
-    EnergyConsumptionVO selectAreaConsumptionSummary(QueryMeter queryMeter);
-
-    // ==================== 设施用能统计 ====================
-
-    /**
-     * 查询设施日用能统计
-     *
-     * @param queryMeter 查询参数
-     * @return 设施日用能统计列表
-     */
-    List<EnergyConsumptionVO> selectFacsDailyConsumption(QueryMeter queryMeter);
-
-    /**
-     * 查询设施月用能统计
-     *
-     * @param queryMeter 查询参数
-     * @return 设施月用能统计列表
-     */
-    List<EnergyConsumptionVO> selectFacsMonthlyConsumption(QueryMeter queryMeter);
-
-    /**
-     * 查询设施年用能统计
-     *
-     * @param queryMeter 查询参数
-     * @return 设施年用能统计列表
-     */
-    List<EnergyConsumptionVO> selectFacsYearlyConsumption(QueryMeter queryMeter);
-
-    /**
-     * 查询设施用能统计汇总
-     *
-     * @param queryMeter 查询参数
-     * @return 设施用能统计汇总
-     */
-    EnergyConsumptionVO selectFacsConsumptionSummary(QueryMeter queryMeter);
-
-    // ==================== 辅助查询 ====================
-
-    /**
-     * 根据区域获取绑定的计量设备
-     *
-     * @param areaCode 区域代码
-     * @param meterCls 计量类别
-     * @return 设备代码列表
-     */
-    List<String> selectMeterDevicesByArea(@Param("areaCode") String areaCode,
-        @Param("meterCls") Integer meterCls);
-
-    /**
-     * 根据设施获取绑定的计量设备
-     *
-     * @param facsCode 设施代码
-     * @param meterCls 计量类别
-     * @return 设备代码列表
-     */
-    List<String> selectMeterDevicesByFacs(@Param("facsCode") String facsCode,
-        @Param("meterCls") Integer meterCls);
-
-    /**
-     * 根据设施分类获取绑定的计量设备
-     *
-     * @param facsCategory 设施分类
-     * @param areaCode 区域代码(可选)
-     * @param meterCls 计量类别
-     * @return 设备代码列表
-     */
-    List<String> selectMeterDevicesByFacsCategory(@Param("facsCategory") String facsCategory,
-        @Param("areaCode") String areaCode,
-        @Param("meterCls") Integer meterCls);
-}

+ 3 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/mapper/MeterBoundaryRelMapper.java

@@ -12,6 +12,9 @@ import java.util.List;
  * @date 2024-12-09
  */
 public interface MeterBoundaryRelMapper {
+    List<String> selectMeterDevices(@Param("boundaryObj") String boundaryObj, @Param("objType") Integer objType,
+        @Param("meterCls") Integer meterCls);
+
     /**
      * 查询计量设备绑定边界对象关系列表
      *

+ 76 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/mapper/WaterConsumptionMapper.java

@@ -0,0 +1,76 @@
+/*
+ * 文 件 名:  WaterConsumptionMapper
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/8/27
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.mapper;
+
+import com.ruoyi.ems.model.QueryMeter;
+import com.ruoyi.ems.model.WaterConsumptionVO;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 用水统计Mapper接口
+ */
+public interface WaterConsumptionMapper {
+
+    // ==================== 区域用水统计方法 ====================
+
+    /**
+     * 根据设备代码列表查询区域日用水统计
+     */
+    List<WaterConsumptionVO> selectAreaDailyWaterConsumptionByDevices(
+        @Param("queryMeter") QueryMeter queryMeter,
+        @Param("meterDevices") Set<String> meterDevices);
+
+    /**
+     * 根据设备代码列表查询区域月用水统计
+     */
+    List<WaterConsumptionVO> selectAreaMonthlyWaterConsumptionByDevices(
+        @Param("queryMeter") QueryMeter queryMeter,
+        @Param("meterDevices") Set<String> meterDevices);
+
+    /**
+     * 根据设备代码列表查询区域年用水统计
+     */
+    List<WaterConsumptionVO> selectAreaYearlyWaterConsumptionByDevices(
+        @Param("queryMeter") QueryMeter queryMeter,
+        @Param("meterDevices") Set<String> meterDevices);
+
+    /**
+     * 根据设备代码列表查询区域用水汇总
+     */
+    WaterConsumptionVO selectAreaWaterConsumptionSummaryByDevices(
+        @Param("queryMeter") QueryMeter queryMeter,
+        @Param("meterDevices") Set<String> meterDevices);
+
+    // ==================== 设施用水统计方法 ====================
+
+    /**
+     * 查询设施日用水统计
+     */
+    List<WaterConsumptionVO> selectFacsDailyWaterConsumption(QueryMeter queryMeter);
+
+    /**
+     * 查询设施月用水统计
+     */
+    List<WaterConsumptionVO> selectFacsMonthlyWaterConsumption(QueryMeter queryMeter);
+
+    /**
+     * 查询设施年用水统计
+     */
+    List<WaterConsumptionVO> selectFacsYearlyWaterConsumption(QueryMeter queryMeter);
+
+    /**
+     * 查询设施用水统计汇总
+     */
+    WaterConsumptionVO selectFacsWaterConsumptionSummary(QueryMeter queryMeter);
+}

+ 122 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/model/ElecConsumptionExportVO.java

@@ -0,0 +1,122 @@
+package com.ruoyi.ems.model;
+
+import com.huashe.common.annotation.Excel;
+
+/**
+ * 用电导出VO
+ */
+public class ElecConsumptionExportVO {
+
+    /** 对象名称 */
+    @Excel(name = "对象名称")
+    private String objName;
+
+    /** 统计时间 */
+    @Excel(name = "统计时间")
+    private String statisticTime;
+
+    /** 总用电量 */
+    @Excel(name = "总用电量(kWh)")
+    private String totalElecQuantity;
+
+    /** 尖峰电量 */
+    @Excel(name = "尖峰电量(kWh)")
+    private String sharpPeakQuantity;
+
+    /** 高峰电量 */
+    @Excel(name = "高峰电量(kWh)")
+    private String peakQuantity;
+
+    /** 平峰电量 */
+    @Excel(name = "平峰电量(kWh)")
+    private String normalQuantity;
+
+    /** 低谷电量 */
+    @Excel(name = "低谷电量(kWh)")
+    private String valleyQuantity;
+
+    /** 总用电费用 */
+    @Excel(name = "总用电费用(元)")
+    private String totalElecCost;
+
+    // 构造函数
+    public ElecConsumptionExportVO() {}
+
+    public ElecConsumptionExportVO(String objName, String statisticTime,
+        String totalElecQuantity, String sharpPeakQuantity, String peakQuantity,
+        String normalQuantity, String valleyQuantity, String totalElecCost) {
+        this.objName = objName;
+        this.statisticTime = statisticTime;
+        this.totalElecQuantity = totalElecQuantity;
+        this.sharpPeakQuantity = sharpPeakQuantity;
+        this.peakQuantity = peakQuantity;
+        this.normalQuantity = normalQuantity;
+        this.valleyQuantity = valleyQuantity;
+        this.totalElecCost = totalElecCost;
+    }
+
+    // Getter and Setter methods
+    public String getObjName() {
+        return objName;
+    }
+
+    public void setObjName(String objName) {
+        this.objName = objName;
+    }
+
+    public String getStatisticTime() {
+        return statisticTime;
+    }
+
+    public void setStatisticTime(String statisticTime) {
+        this.statisticTime = statisticTime;
+    }
+
+    public String getTotalElecQuantity() {
+        return totalElecQuantity;
+    }
+
+    public void setTotalElecQuantity(String totalElecQuantity) {
+        this.totalElecQuantity = totalElecQuantity;
+    }
+
+    public String getSharpPeakQuantity() {
+        return sharpPeakQuantity;
+    }
+
+    public void setSharpPeakQuantity(String sharpPeakQuantity) {
+        this.sharpPeakQuantity = sharpPeakQuantity;
+    }
+
+    public String getPeakQuantity() {
+        return peakQuantity;
+    }
+
+    public void setPeakQuantity(String peakQuantity) {
+        this.peakQuantity = peakQuantity;
+    }
+
+    public String getNormalQuantity() {
+        return normalQuantity;
+    }
+
+    public void setNormalQuantity(String normalQuantity) {
+        this.normalQuantity = normalQuantity;
+    }
+
+    public String getValleyQuantity() {
+        return valleyQuantity;
+    }
+
+    public void setValleyQuantity(String valleyQuantity) {
+        this.valleyQuantity = valleyQuantity;
+    }
+
+    public String getTotalElecCost() {
+        return totalElecCost;
+    }
+
+    public void setTotalElecCost(String totalElecCost) {
+        this.totalElecCost = totalElecCost;
+    }
+}

+ 231 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/model/ElecConsumptionVO.java

@@ -0,0 +1,231 @@
+package com.ruoyi.ems.model;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.huashe.common.annotation.Excel;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 用电统计视图对象
+ */
+@ApiModel("用电统计响应模型")
+public class ElecConsumptionVO {
+
+    @ApiModelProperty("区域代码")
+    private String areaCode;
+
+    @ApiModelProperty("区域名称")
+    private String areaName;
+
+    @ApiModelProperty("对象代码")
+    private String objCode;
+
+    @ApiModelProperty("对象名称")
+    @Excel(name = "对象名称")
+    private String objName;
+
+    @ApiModelProperty("对象类型 1-区域 2-设施")
+    private Integer objType;
+
+    @ApiModelProperty("统计日期")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @Excel(name = "统计日期", dateFormat = "yyyy-MM-dd")
+    private Date statisticDate;
+
+    @ApiModelProperty("统计年份")
+    @Excel(name = "统计年份")
+    private String statisticYear;
+
+    @ApiModelProperty("统计月份")
+    @Excel(name = "统计月份")
+    private String statisticMonth;
+
+    @ApiModelProperty("统计时间维度 DAY-日 MONTH-月 YEAR-年")
+    private String timeDimension;
+
+    // 峰谷电统计字段
+    @ApiModelProperty("总用电量(kWh)")
+    @Excel(name = "总用电量(kWh)")
+    private BigDecimal totalElecQuantity;
+
+    @ApiModelProperty("尖峰电量(kWh)")
+    @Excel(name = "尖峰电量(kWh)")
+    private BigDecimal sharpPeakQuantity;
+
+    @ApiModelProperty("高峰电量(kWh)")
+    @Excel(name = "高峰电量(kWh)")
+    private BigDecimal peakQuantity;
+
+    @ApiModelProperty("平峰电量(kWh)")
+    @Excel(name = "平峰电量(kWh)")
+    private BigDecimal normalQuantity;
+
+    @ApiModelProperty("低谷电量(kWh)")
+    @Excel(name = "低谷电量(kWh)")
+    private BigDecimal valleyQuantity;
+
+    @ApiModelProperty("总用电费用(元)")
+    @Excel(name = "总用电费用(元)")
+    private BigDecimal totalElecCost;
+
+    @ApiModelProperty("创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+
+    // 构造方法
+    public ElecConsumptionVO() {}
+
+    // Getters and Setters
+    public String getAreaCode() {
+        return areaCode;
+    }
+
+    public void setAreaCode(String areaCode) {
+        this.areaCode = areaCode;
+    }
+
+    public String getAreaName() {
+        return areaName;
+    }
+
+    public void setAreaName(String areaName) {
+        this.areaName = areaName;
+    }
+
+    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 Integer getObjType() {
+        return objType;
+    }
+
+    public void setObjType(Integer objType) {
+        this.objType = objType;
+    }
+
+    public Date getStatisticDate() {
+        return statisticDate;
+    }
+
+    public void setStatisticDate(Date statisticDate) {
+        this.statisticDate = statisticDate;
+    }
+
+    public String getStatisticYear() {
+        return statisticYear;
+    }
+
+    public void setStatisticYear(String statisticYear) {
+        this.statisticYear = statisticYear;
+    }
+
+    public String getStatisticMonth() {
+        return statisticMonth;
+    }
+
+    public void setStatisticMonth(String statisticMonth) {
+        this.statisticMonth = statisticMonth;
+    }
+
+    public String getTimeDimension() {
+        return timeDimension;
+    }
+
+    public void setTimeDimension(String timeDimension) {
+        this.timeDimension = timeDimension;
+    }
+
+    public BigDecimal getTotalElecQuantity() {
+        return totalElecQuantity;
+    }
+
+    public void setTotalElecQuantity(BigDecimal totalElecQuantity) {
+        this.totalElecQuantity = totalElecQuantity;
+    }
+
+    public BigDecimal getSharpPeakQuantity() {
+        return sharpPeakQuantity;
+    }
+
+    public void setSharpPeakQuantity(BigDecimal sharpPeakQuantity) {
+        this.sharpPeakQuantity = sharpPeakQuantity;
+    }
+
+    public BigDecimal getPeakQuantity() {
+        return peakQuantity;
+    }
+
+    public void setPeakQuantity(BigDecimal peakQuantity) {
+        this.peakQuantity = peakQuantity;
+    }
+
+    public BigDecimal getNormalQuantity() {
+        return normalQuantity;
+    }
+
+    public void setNormalQuantity(BigDecimal normalQuantity) {
+        this.normalQuantity = normalQuantity;
+    }
+
+    public BigDecimal getValleyQuantity() {
+        return valleyQuantity;
+    }
+
+    public void setValleyQuantity(BigDecimal valleyQuantity) {
+        this.valleyQuantity = valleyQuantity;
+    }
+
+    public BigDecimal getTotalElecCost() {
+        return totalElecCost;
+    }
+
+    public void setTotalElecCost(BigDecimal totalElecCost) {
+        this.totalElecCost = totalElecCost;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    @Override
+    public String toString() {
+        return "ElecConsumptionVO{" +
+            "areaCode='" + areaCode + '\'' +
+            ", areaName='" + areaName + '\'' +
+            ", objCode='" + objCode + '\'' +
+            ", objName='" + objName + '\'' +
+            ", objType=" + objType +
+            ", statisticDate=" + statisticDate +
+            ", statisticYear='" + statisticYear + '\'' +
+            ", statisticMonth='" + statisticMonth + '\'' +
+            ", timeDimension='" + timeDimension + '\'' +
+            ", totalElecQuantity=" + totalElecQuantity +
+            ", sharpPeakQuantity=" + sharpPeakQuantity +
+            ", peakQuantity=" + peakQuantity +
+            ", normalQuantity=" + normalQuantity +
+            ", valleyQuantity=" + valleyQuantity +
+            ", totalElecCost=" + totalElecCost +
+            ", createTime=" + createTime +
+            '}';
+    }
+}

+ 69 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/model/WaterConsumptionExportVO.java

@@ -0,0 +1,69 @@
+package com.ruoyi.ems.model;
+
+import com.huashe.common.annotation.Excel;
+
+/**
+ * 用水导出VO
+ */
+public class WaterConsumptionExportVO {
+
+    /** 对象名称 */
+    @Excel(name = "对象名称")
+    private String objName;
+
+    /** 统计时间 */
+    @Excel(name = "统计时间")
+    private String statisticTime;
+
+    /** 总用水量 */
+    @Excel(name = "总用水量(m³)")
+    private String totalWaterQuantity;
+
+    /** 总用水费用 */
+    @Excel(name = "总用水费用(元)")
+    private String totalWaterCost;
+
+    // 构造函数
+    public WaterConsumptionExportVO() {}
+
+    public WaterConsumptionExportVO(String objName, String statisticTime,
+        String totalWaterQuantity, String totalWaterCost) {
+        this.objName = objName;
+        this.statisticTime = statisticTime;
+        this.totalWaterQuantity = totalWaterQuantity;
+        this.totalWaterCost = totalWaterCost;
+    }
+
+    // Getter and Setter methods
+    public String getObjName() {
+        return objName;
+    }
+
+    public void setObjName(String objName) {
+        this.objName = objName;
+    }
+
+    public String getStatisticTime() {
+        return statisticTime;
+    }
+
+    public void setStatisticTime(String statisticTime) {
+        this.statisticTime = statisticTime;
+    }
+
+    public String getTotalWaterQuantity() {
+        return totalWaterQuantity;
+    }
+
+    public void setTotalWaterQuantity(String totalWaterQuantity) {
+        this.totalWaterQuantity = totalWaterQuantity;
+    }
+
+    public String getTotalWaterCost() {
+        return totalWaterCost;
+    }
+
+    public void setTotalWaterCost(String totalWaterCost) {
+        this.totalWaterCost = totalWaterCost;
+    }
+}

+ 27 - 76
ems/ems-core/src/main/java/com/ruoyi/ems/model/EnergyConsumptionVO.java → ems/ems-core/src/main/java/com/ruoyi/ems/model/WaterConsumptionVO.java

@@ -1,24 +1,15 @@
 /*
- * 文 件 名:  EnergyConsumptionVO
+ * 文 件 名:  WaterConsumptionVO
  * 版    权:  华设设计集团股份有限公司
  * 描    述:  <描述>
  * 修 改 人:  lvwenbin
- * 修改时间:  2025/8/26
+ * 修改时间:  2025/8/27
  * 跟踪单号:  <跟踪单号>
  * 修改单号:  <修改单号>
  * 修改内容:  <修改内容>
  */
-package com.ruoyi.ems.model;
 
-/**
- * <一句话功能简述>
- * <功能详细描述>
- *
- * @author lvwenbin
- * @version [版本号, 2025/8/26]
- * @see [相关类/方法]
- * @since [产品/模块版本]
- */
+package com.ruoyi.ems.model;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.huashe.common.annotation.Excel;
@@ -29,19 +20,18 @@ import java.math.BigDecimal;
 import java.util.Date;
 
 /**
- * 用能统计视图对象
- *
- * @author ruoyi
- * @date 2024-12-20
+ * 用水统计响应模型
+ */
+/**
+ * 用水统计视图对象
  */
-@ApiModel("用统计响应模型")
-public class EnergyConsumptionVO {
+@ApiModel("用统计响应模型")
+public class WaterConsumptionVO {
 
     @ApiModelProperty("区域代码")
     private String areaCode;
 
     @ApiModelProperty("区域名称")
-    @Excel(name = "区域名称")
     private String areaName;
 
     @ApiModelProperty("对象代码")
@@ -56,52 +46,31 @@ public class EnergyConsumptionVO {
 
     @ApiModelProperty("统计日期")
     @JsonFormat(pattern = "yyyy-MM-dd")
-    @Excel(name = "统计日期", dateFormat = "yyyy-MM-dd")
     private Date statisticDate;
 
     @ApiModelProperty("统计年份")
-    @Excel(name = "统计年份")
     private String statisticYear;
 
     @ApiModelProperty("统计月份")
-    @Excel(name = "统计月份")
     private String statisticMonth;
 
     @ApiModelProperty("统计时间维度 DAY-日 MONTH-月 YEAR-年")
     private String timeDimension;
 
-    @ApiModelProperty("用电量(kWh)")
-    @Excel(name = "用电量(kWh)")
-    private BigDecimal elecQuantity;
+    @ApiModelProperty("总用水量(m³)")
+    @Excel(name = "总用水量(m³)")
+    private BigDecimal totalWaterQuantity;
 
-    @ApiModelProperty("用电费用(元)")
-    @Excel(name = "用电费用(元)")
-    private BigDecimal elecCost;
-
-    @ApiModelProperty("用水量(m³)")
-    @Excel(name = "用水量(m³)")
-    private BigDecimal waterQuantity;
-
-    @ApiModelProperty("用水费用(元)")
-    @Excel(name = "用水费用(元)")
-    private BigDecimal waterCost;
+    @ApiModelProperty("总用水费用(元)")
+    @Excel(name = "总用水费用(元)")
+    private BigDecimal totalWaterCost;
 
     @ApiModelProperty("创建时间")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date createTime;
 
     // 构造方法
-    public EnergyConsumptionVO() {}
-
-    public EnergyConsumptionVO(String objCode, String objName, Integer objType,
-        String timeDimension, BigDecimal elecQuantity, BigDecimal elecCost) {
-        this.objCode = objCode;
-        this.objName = objName;
-        this.objType = objType;
-        this.timeDimension = timeDimension;
-        this.elecQuantity = elecQuantity;
-        this.elecCost = elecCost;
-    }
+    public WaterConsumptionVO() {}
 
     // Getters and Setters
     public String getAreaCode() {
@@ -176,36 +145,20 @@ public class EnergyConsumptionVO {
         this.timeDimension = timeDimension;
     }
 
-    public BigDecimal getElecQuantity() {
-        return elecQuantity;
-    }
-
-    public void setElecQuantity(BigDecimal elecQuantity) {
-        this.elecQuantity = elecQuantity;
-    }
-
-    public BigDecimal getElecCost() {
-        return elecCost;
-    }
-
-    public void setElecCost(BigDecimal elecCost) {
-        this.elecCost = elecCost;
-    }
-
-    public BigDecimal getWaterQuantity() {
-        return waterQuantity;
+    public BigDecimal getTotalWaterQuantity() {
+        return totalWaterQuantity;
     }
 
-    public void setWaterQuantity(BigDecimal waterQuantity) {
-        this.waterQuantity = waterQuantity;
+    public void setTotalWaterQuantity(BigDecimal totalWaterQuantity) {
+        this.totalWaterQuantity = totalWaterQuantity;
     }
 
-    public BigDecimal getWaterCost() {
-        return waterCost;
+    public BigDecimal getTotalWaterCost() {
+        return totalWaterCost;
     }
 
-    public void setWaterCost(BigDecimal waterCost) {
-        this.waterCost = waterCost;
+    public void setTotalWaterCost(BigDecimal totalWaterCost) {
+        this.totalWaterCost = totalWaterCost;
     }
 
     public Date getCreateTime() {
@@ -218,7 +171,7 @@ public class EnergyConsumptionVO {
 
     @Override
     public String toString() {
-        return "EnergyConsumptionVO{" +
+        return "WaterConsumptionVO{" +
             "areaCode='" + areaCode + '\'' +
             ", areaName='" + areaName + '\'' +
             ", objCode='" + objCode + '\'' +
@@ -228,10 +181,8 @@ public class EnergyConsumptionVO {
             ", statisticYear='" + statisticYear + '\'' +
             ", statisticMonth='" + statisticMonth + '\'' +
             ", timeDimension='" + timeDimension + '\'' +
-            ", elecQuantity=" + elecQuantity +
-            ", elecCost=" + elecCost +
-            ", waterQuantity=" + waterQuantity +
-            ", waterCost=" + waterCost +
+            ", totalWaterQuantity=" + totalWaterQuantity +
+            ", totalWaterCost=" + totalWaterCost +
             ", createTime=" + createTime +
             '}';
     }

+ 48 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/service/IElecConsumptionService.java

@@ -0,0 +1,48 @@
+package com.ruoyi.ems.service;
+
+import com.ruoyi.ems.model.ElecConsumptionExportVO;
+import com.ruoyi.ems.model.ElecConsumptionVO;
+import com.ruoyi.ems.model.QueryMeter;
+
+import java.util.List;
+
+/**
+ * 用电统计服务接口
+ */
+public interface IElecConsumptionService {
+
+    /**
+     * 查询区域用电统计列表
+     */
+    List<ElecConsumptionVO> selectAreaElecConsumptionList(QueryMeter queryMeter);
+
+    /**
+     * 查询设施用电统计列表
+     */
+    List<ElecConsumptionVO> selectFacsElecConsumptionList(QueryMeter queryMeter);
+
+    /**
+     * 查询区域用电统计汇总
+     */
+    ElecConsumptionVO selectAreaElecConsumptionSummary(QueryMeter queryMeter);
+
+    /**
+     * 查询设施用电统计汇总
+     */
+    ElecConsumptionVO selectFacsElecConsumptionSummary(QueryMeter queryMeter);
+
+    /**
+     * 导出区域用电统计列表
+     */
+    List<ElecConsumptionVO> exportAreaElecConsumptionList(QueryMeter queryMeter);
+
+    /**
+     * 导出设施用电统计列表
+     */
+    List<ElecConsumptionVO> exportFacsElecConsumptionList(QueryMeter queryMeter);
+
+    /**
+     * 转换为用电导出VO列表
+     */
+    List<ElecConsumptionExportVO> convertToElecExportVOList(List<ElecConsumptionVO> originalList, String timeDimension);
+}

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

@@ -1,63 +0,0 @@
-package com.ruoyi.ems.service;
-
-import com.ruoyi.ems.model.EnergyConsumptionVO;
-import com.ruoyi.ems.model.QueryMeter;
-
-import java.util.List;
-
-/**
- * 用能统计服务接口
- *
- * @author ruoyi
- * @date 2024-12-20
- */
-public interface IEnergyConsumptionService {
-
-    /**
-     * 查询区域用能统计列表
-     *
-     * @param queryMeter 查询参数
-     * @return 区域用能统计列表
-     */
-    List<EnergyConsumptionVO> selectAreaConsumptionList(QueryMeter queryMeter);
-
-    /**
-     * 查询设施用能统计列表
-     *
-     * @param queryMeter 查询参数
-     * @return 设施用能统计列表
-     */
-    List<EnergyConsumptionVO> selectFacsConsumptionList(QueryMeter queryMeter);
-
-    /**
-     * 查询区域用能统计汇总
-     *
-     * @param queryMeter 查询参数
-     * @return 用能统计汇总
-     */
-    EnergyConsumptionVO selectAreaConsumptionSummary(QueryMeter queryMeter);
-
-    /**
-     * 查询设施用能统计汇总
-     *
-     * @param queryMeter 查询参数
-     * @return 用能统计汇总
-     */
-    EnergyConsumptionVO selectFacsConsumptionSummary(QueryMeter queryMeter);
-
-    /**
-     * 导出区域用能统计数据
-     *
-     * @param queryMeter 查询参数
-     * @return 导出数据列表
-     */
-    List<EnergyConsumptionVO> exportAreaConsumptionList(QueryMeter queryMeter);
-
-    /**
-     * 导出设施用能统计数据
-     *
-     * @param queryMeter 查询参数
-     * @return 导出数据列表
-     */
-    List<EnergyConsumptionVO> exportFacsConsumptionList(QueryMeter queryMeter);
-}

+ 10 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/service/IMeterBoundaryRelService.java

@@ -12,6 +12,16 @@ import java.util.List;
  */
 public interface IMeterBoundaryRelService {
     /**
+     * 查询对象绑定的计量设备
+     *
+     * @param objType     计量对象类型
+     * @param boundaryObj 计量对象编号
+     * @param meterCls    计量介质
+     * @return 计量设备绑定边界对象关系集合
+     */
+    List<String> selectMeterDevices(String boundaryObj, Integer objType, Integer meterCls);
+
+    /**
      * 查询计量设备绑定边界对象关系列表
      *
      * @param objType     计量对象类型

+ 58 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/service/IWaterConsumptionService.java

@@ -0,0 +1,58 @@
+/*
+ * 文 件 名:  IWaterConsumptionService
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/8/27
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.service;
+
+import com.ruoyi.ems.model.QueryMeter;
+import com.ruoyi.ems.model.WaterConsumptionExportVO;
+import com.ruoyi.ems.model.WaterConsumptionVO;
+
+import java.util.List;
+
+/**
+ * 用水统计服务接口
+ */
+public interface IWaterConsumptionService {
+
+    /**
+     * 查询区域用水统计列表
+     */
+    List<WaterConsumptionVO> selectAreaWaterConsumptionList(QueryMeter queryMeter);
+
+    /**
+     * 查询设施用水统计列表
+     */
+    List<WaterConsumptionVO> selectFacsWaterConsumptionList(QueryMeter queryMeter);
+
+    /**
+     * 查询区域用水统计汇总
+     */
+    WaterConsumptionVO selectAreaWaterConsumptionSummary(QueryMeter queryMeter);
+
+    /**
+     * 查询设施用水统计汇总
+     */
+    WaterConsumptionVO selectFacsWaterConsumptionSummary(QueryMeter queryMeter);
+
+    /**
+     * 导出区域用水统计列表
+     */
+    List<WaterConsumptionVO> exportAreaWaterConsumptionList(QueryMeter queryMeter);
+
+    /**
+     * 导出设施用水统计列表
+     */
+    List<WaterConsumptionVO> exportFacsWaterConsumptionList(QueryMeter queryMeter);
+
+    /**
+     * 转换为用水导出VO列表
+     */
+    List<WaterConsumptionExportVO> convertToWaterExportVOList(List<WaterConsumptionVO> originalList, String timeDimension);
+}

+ 544 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/ElecConsumptionServiceImpl.java

@@ -0,0 +1,544 @@
+package com.ruoyi.ems.service.impl;
+
+import com.ruoyi.ems.domain.Area;
+import com.ruoyi.ems.mapper.ElecConsumptionMapper;
+import com.ruoyi.ems.model.ElecConsumptionExportVO;
+import com.ruoyi.ems.model.ElecConsumptionVO;
+import com.ruoyi.ems.model.QueryMeter;
+import com.ruoyi.ems.service.IAreaService;
+import com.ruoyi.ems.service.IElecConsumptionService;
+import com.ruoyi.ems.service.IMeterBoundaryRelService;
+import com.ruoyi.ems.util.AreaUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * 用电统计服务实现
+ */
+@Service
+public class ElecConsumptionServiceImpl implements IElecConsumptionService {
+
+    private static final Logger logger = LoggerFactory.getLogger(ElecConsumptionServiceImpl.class);
+
+    @Autowired
+    private ElecConsumptionMapper elecConsumptionMapper;
+
+    @Autowired
+    private IMeterBoundaryRelService meterBoundaryRelService;
+
+    @Autowired
+    private IAreaService areaService;
+
+    /**
+     * 电表计量类型常量
+     */
+    private static final int ELEC_METER_CLS = 45;
+
+    @Override
+    public List<ElecConsumptionVO> selectAreaElecConsumptionList(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            logger.warn("查询参数为空,返回空列表");
+            return Collections.emptyList();
+        }
+
+        try {
+            // 1. 获取所有相关测点设备
+            Set<String> meterDevices = getMeterDevicesByArea(queryMeter.getObjCode());
+            if (meterDevices.isEmpty()) {
+                logger.info("未找到相关电表设备,查询条件: areaCode={}, objCode={}", queryMeter.getAreaCode(),
+                    queryMeter.getObjCode());
+                return Collections.emptyList();
+            }
+
+            logger.info("查询区域用电统计,时间维度: {}, 设备数量: {}", queryMeter.getTimeDimension(),
+                meterDevices.size());
+
+            // 2. 根据时间维度调用相应的查询方法
+            List<ElecConsumptionVO> result;
+            // 根据时间维度调用相应的查询方法
+            switch (queryMeter.getTimeDimension().toLowerCase()) {
+                case "day":
+                    result = elecConsumptionMapper.selectAreaDailyElecConsumptionByDevices(queryMeter, meterDevices);
+                    break;
+                case "month":
+                    result = elecConsumptionMapper.selectAreaMonthlyElecConsumptionByDevices(queryMeter, meterDevices);
+                    break;
+                case "year":
+                    result = elecConsumptionMapper.selectAreaYearlyElecConsumptionByDevices(queryMeter, meterDevices);
+                    break;
+                default:
+                    logger.warn("未识别的时间维度: {},使用月统计", queryMeter.getTimeDimension());
+                    result = elecConsumptionMapper.selectAreaMonthlyElecConsumptionByDevices(queryMeter, meterDevices);
+                    break;
+            }
+
+            // 填充区域名称路径
+            fillAreaNameForElecConsumption(result);
+
+            return result;
+        }
+        catch (Exception e) {
+            logger.error("查询区域用电统计列表异常", e);
+            return Collections.emptyList();
+        }
+    }
+
+    @Override
+    public ElecConsumptionVO selectAreaElecConsumptionSummary(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            logger.warn("查询参数为空,返回空对象");
+            return new ElecConsumptionVO();
+        }
+
+        try {
+            // 1. 获取所有相关测点设备
+            Set<String> meterDevices = getMeterDevicesByArea(queryMeter.getObjCode());
+            if (meterDevices.isEmpty()) {
+                logger.info("未找到相关电表设备,返回空汇总");
+                return new ElecConsumptionVO();
+            }
+
+            logger.info("查询区域用电汇总,设备数量: {}", meterDevices.size());
+
+            // 2. 查询汇总数据
+            ElecConsumptionVO summary = elecConsumptionMapper.selectAreaElecConsumptionSummaryByDevices(queryMeter,
+                meterDevices);
+            return summary != null ? summary : new ElecConsumptionVO();
+        }
+        catch (Exception e) {
+            logger.error("查询区域用电统计汇总异常", e);
+            return new ElecConsumptionVO();
+        }
+    }
+
+    /**
+     * 根据区域获取所有相关的测点设备
+     */
+    private Set<String> getMeterDevicesByArea(String objCode) {
+        Set<String> meterDevices = new HashSet<>();
+
+        try {
+            // 确定查询的区域范围
+            Set<String> targetAreaCodes = new HashSet<>();
+
+            if (StringUtils.isNotBlank(objCode) && !"-1".equals(objCode)) {
+                // 指定了区域代码,需要查询该区域及其所有子区域(树节点点击传入的是objCode)
+                targetAreaCodes.addAll(getAllChildAreaCodes(objCode));
+                logger.debug("根据objCode查询区域设备,区域代码: {}, 找到子区域数量: {}", objCode,
+                    targetAreaCodes.size());
+            }
+
+            // 如果没有指定任何区域,查询所有区域的所有测点
+            if (targetAreaCodes.isEmpty()) {
+                logger.debug("未指定区域,查询所有电表设备");
+
+                // 方法1:直接获取所有绑定了电表的区域测点
+                List<String> allDevices = meterBoundaryRelService.selectMeterDevices(null, 1, ELEC_METER_CLS);
+                if (!CollectionUtils.isEmpty(allDevices)) {
+                    meterDevices.addAll(allDevices);
+                    logger.debug("查询到所有区域电表设备数量: {}", allDevices.size());
+                }
+                else {
+                    // 方法2:如果上面的方法没有数据,尝试获取所有区域,然后查询每个区域的设备
+                    List<Area> allAreas = areaService.selectArea(new Area());
+                    if (!CollectionUtils.isEmpty(allAreas)) {
+                        for (Area area : allAreas) {
+                            List<String> areaDevices = meterBoundaryRelService.selectMeterDevices(area.getAreaCode(), 1,
+                                ELEC_METER_CLS);
+                            if (!CollectionUtils.isEmpty(areaDevices)) {
+                                meterDevices.addAll(areaDevices);
+                                logger.debug("区域 {} 找到电表设备数量: {}", area.getAreaCode(), areaDevices.size());
+                            }
+                        }
+                    }
+                }
+            }
+            else {
+                // 根据区域代码获取绑定的测点设备
+                for (String areaCode : targetAreaCodes) {
+                    List<String> devices = meterBoundaryRelService.selectMeterDevices(areaCode, 1, ELEC_METER_CLS);
+                    if (!CollectionUtils.isEmpty(devices)) {
+                        meterDevices.addAll(devices);
+                        logger.debug("区域 {} 找到电表设备数量: {}", areaCode, devices.size());
+                    }
+                }
+            }
+
+            logger.info("最终获取到的电表设备总数: {}", meterDevices.size());
+            if (logger.isDebugEnabled()) {
+                logger.debug("设备列表: {}", meterDevices);
+            }
+
+        }
+        catch (Exception e) {
+            logger.error("获取区域测点设备异常", e);
+        }
+
+        return meterDevices;
+    }
+
+    /**
+     * 获取指定区域及其所有子区域的代码
+     */
+    private Set<String> getAllChildAreaCodes(String areaCode) {
+        Set<String> areaCodes = new HashSet<>();
+
+        if (StringUtils.isBlank(areaCode)) {
+            return areaCodes;
+        }
+
+        try {
+            // 1. 添加当前区域本身
+            Area currentArea = areaService.selectAreaByCode(areaCode);
+            if (currentArea != null) {
+                areaCodes.add(currentArea.getAreaCode());
+                logger.debug("添加当前区域: {}", currentArea.getAreaCode());
+            }
+
+            // 2. 获取当前区域的子区域树(递归获取)
+            List<Area> childAreas = areaService.selectAreaTree(areaCode, true);
+
+            // 3. 递归遍历子区域树,收集所有区域代码
+            collectAreaCodes(childAreas, areaCodes);
+
+            logger.debug("区域 {} 及其子区域总数: {}", areaCode, areaCodes.size());
+        }
+        catch (Exception e) {
+            logger.error("获取子区域代码异常,区域代码: {}", areaCode, e);
+        }
+
+        return areaCodes;
+    }
+
+    /**
+     * 递归收集区域树中的所有区域代码
+     */
+    private void collectAreaCodes(List<?> areas, Set<String> areaCodes) {
+        if (CollectionUtils.isEmpty(areas)) {
+            return;
+        }
+
+        for (Object obj : areas) {
+            if (obj instanceof Area) {
+                Area area = (Area) obj;
+                areaCodes.add(area.getAreaCode());
+
+                // 递归处理子区域
+                if (!CollectionUtils.isEmpty(area.getChildren())) {
+                    collectAreaCodes(area.getChildren(), areaCodes);
+                }
+            }
+        }
+    }
+
+    @Override
+    public List<ElecConsumptionVO> selectFacsElecConsumptionList(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            logger.warn("查询参数为空,返回空列表");
+            return Collections.emptyList();
+        }
+
+        try {
+            logger.info("查询设施用电统计,时间维度: {}, 设施分类: {}, 区域: {}, 设施: {}",
+                queryMeter.getTimeDimension(), queryMeter.getFacsCategory(), queryMeter.getAreaCode(),
+                queryMeter.getObjCode());
+
+            // 根据时间维度调用相应的查询方法
+            switch (queryMeter.getTimeDimension().toLowerCase()) {
+                case "day":
+                    return elecConsumptionMapper.selectFacsDailyElecConsumption(queryMeter);
+                case "month":
+                    return elecConsumptionMapper.selectFacsMonthlyElecConsumption(queryMeter);
+                case "year":
+                    return elecConsumptionMapper.selectFacsYearlyElecConsumption(queryMeter);
+                default:
+                    logger.warn("未识别的时间维度: {},使用月统计", queryMeter.getTimeDimension());
+                    return elecConsumptionMapper.selectFacsMonthlyElecConsumption(queryMeter);
+            }
+        }
+        catch (Exception e) {
+            logger.error("查询设施用电统计列表异常", e);
+            return Collections.emptyList();
+        }
+    }
+
+    @Override
+    public ElecConsumptionVO selectFacsElecConsumptionSummary(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            logger.warn("查询参数为空,返回空对象");
+            return new ElecConsumptionVO();
+        }
+
+        try {
+            logger.info("查询设施用电汇总,设施分类: {}, 区域: {}, 设施: {}", queryMeter.getFacsCategory(),
+                queryMeter.getAreaCode(), queryMeter.getObjCode());
+
+            ElecConsumptionVO summary = elecConsumptionMapper.selectFacsElecConsumptionSummary(queryMeter);
+            return summary != null ? summary : new ElecConsumptionVO();
+        }
+        catch (Exception e) {
+            logger.error("查询设施用电统计汇总异常", e);
+            return new ElecConsumptionVO();
+        }
+    }
+
+    @Override
+    public List<ElecConsumptionVO> exportAreaElecConsumptionList(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            logger.warn("导出参数为空,返回空列表");
+            return Collections.emptyList();
+        }
+
+        try {
+            // 导出时不分页,清除分页参数
+            QueryMeter exportQuery = cloneQueryMeter(queryMeter);
+            exportQuery.setPageNum(null);
+            exportQuery.setPageSize(null);
+
+            logger.info("导出区域用电统计,时间维度: {}", exportQuery.getTimeDimension());
+
+            List<ElecConsumptionVO> result = selectAreaElecConsumptionList(exportQuery);
+            logger.info("导出区域用电统计完成,记录数: {}", result.size());
+
+            return result;
+        }
+        catch (Exception e) {
+            logger.error("导出区域用电统计异常", e);
+            return Collections.emptyList();
+        }
+    }
+
+    @Override
+    public List<ElecConsumptionVO> exportFacsElecConsumptionList(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            logger.warn("导出参数为空,返回空列表");
+            return Collections.emptyList();
+        }
+
+        try {
+            // 导出时不分页,清除分页参数
+            QueryMeter exportQuery = cloneQueryMeter(queryMeter);
+            exportQuery.setPageNum(null);
+            exportQuery.setPageSize(null);
+
+            logger.info("导出设施用电统计,时间维度: {}, 设施分类: {}", exportQuery.getTimeDimension(),
+                exportQuery.getFacsCategory());
+
+            List<ElecConsumptionVO> result = selectFacsElecConsumptionList(exportQuery);
+            logger.info("导出设施用电统计完成,记录数: {}", result.size());
+
+            return result;
+        }
+        catch (Exception e) {
+            logger.error("导出设施用电统计异常", e);
+            return Collections.emptyList();
+        }
+    }
+
+    /**
+     * 转换为用电导出VO列表
+     */
+    public List<ElecConsumptionExportVO> convertToElecExportVOList(List<ElecConsumptionVO> originalList,
+        String timeDimension) {
+        if (CollectionUtils.isEmpty(originalList)) {
+            return Collections.emptyList();
+        }
+
+        return originalList.stream().map(vo -> convertToElecExportVO(vo, timeDimension))
+            .collect(java.util.stream.Collectors.toList());
+    }
+
+    /**
+     * 转换单个用电VO为导出VO
+     */
+    private ElecConsumptionExportVO convertToElecExportVO(ElecConsumptionVO vo, String timeDimension) {
+        ElecConsumptionExportVO exportVO = new ElecConsumptionExportVO();
+
+        // 对象名称
+        exportVO.setObjName(vo.getObjName());
+
+        // 统计时间 - 根据时间维度格式化
+        exportVO.setStatisticTime(formatStatisticTime(vo, timeDimension));
+
+        // 用电量数据 - 格式化为2位小数
+        exportVO.setTotalElecQuantity(formatNumber(vo.getTotalElecQuantity(), 2));
+        exportVO.setSharpPeakQuantity(formatNumber(vo.getSharpPeakQuantity(), 2));
+        exportVO.setPeakQuantity(formatNumber(vo.getPeakQuantity(), 2));
+        exportVO.setNormalQuantity(formatNumber(vo.getNormalQuantity(), 2));
+        exportVO.setValleyQuantity(formatNumber(vo.getValleyQuantity(), 2));
+
+        // 用电费用 - 格式化为2位小数
+        exportVO.setTotalElecCost(formatNumber(vo.getTotalElecCost(), 2));
+
+        return exportVO;
+    }
+
+    /**
+     * 格式化统计时间
+     */
+    private String formatStatisticTime(ElecConsumptionVO vo, String timeDimension) {
+        if (timeDimension == null) {
+            timeDimension = "month";
+        }
+
+        switch (timeDimension.toLowerCase()) {
+            case "day":
+                return formatDateForDisplay(vo.getStatisticDate());
+            case "month":
+                return StringUtils.isNotBlank(vo.getStatisticMonth()) ? vo.getStatisticMonth() : "";
+            case "year":
+                return vo.getStatisticYear() != null ? vo.getStatisticYear().toString() : "";
+            default:
+                return StringUtils.isNotBlank(vo.getStatisticMonth()) ? vo.getStatisticMonth() : "";
+        }
+    }
+
+    /**
+     * 数字格式化
+     */
+    private String formatNumber(java.math.BigDecimal num, int decimals) {
+        if (num == null) {
+            StringBuilder sb = new StringBuilder("0.");
+            for (int i = 0; i < decimals; i++) {
+                sb.append("0");
+            }
+            return sb.toString();
+        }
+        return String.format("%." + decimals + "f", num.doubleValue());
+    }
+
+    /**
+     * 日期格式化用于显示
+     */
+    private String formatDateForDisplay(Object dateObj) {
+        if (dateObj == null) {
+            return "";
+        }
+
+        String dateStr = dateObj.toString();
+
+        // 如果是完整的日期时间字符串,提取日期部分
+        if (dateStr.contains(" ")) {
+            return dateStr.split(" ")[0];
+        }
+
+        // 如果已经是日期格式,直接返回
+        if (dateStr.matches("\\d{4}-\\d{2}-\\d{2}")) {
+            return dateStr;
+        }
+
+        return dateStr;
+    }
+
+    /**
+     * 克隆查询参数对象
+     */
+    private QueryMeter cloneQueryMeter(QueryMeter source) {
+        if (source == null) {
+            return null;
+        }
+
+        QueryMeter target = new QueryMeter();
+        target.setAreaCode(source.getAreaCode());
+        target.setObjCode(source.getObjCode());
+        target.setObjType(source.getObjType());
+        target.setFacsCategory(source.getFacsCategory());
+        target.setTimeDimension(source.getTimeDimension());
+        target.setStartRecTime(source.getStartRecTime());
+        target.setEndRecTime(source.getEndRecTime());
+        target.setOrderFlag(source.getOrderFlag());
+        // 不复制分页参数
+        target.setPageNum(null);
+        target.setPageSize(null);
+
+        return target;
+    }
+
+    /**
+     * 验证查询参数
+     */
+    private boolean validateQueryMeter(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            return false;
+        }
+
+        // 验证时间维度
+        if (StringUtils.isBlank(queryMeter.getTimeDimension())) {
+            queryMeter.setTimeDimension("month");
+        }
+
+        String timeDimension = queryMeter.getTimeDimension().toLowerCase();
+        if (!"day".equals(timeDimension) && !"month".equals(timeDimension) && !"year".equals(timeDimension)) {
+            logger.warn("无效的时间维度: {}, 使用默认值 month", queryMeter.getTimeDimension());
+            queryMeter.setTimeDimension("month");
+        }
+
+        // 验证排序标志
+        if (StringUtils.isBlank(queryMeter.getOrderFlag())) {
+            queryMeter.setOrderFlag("desc");
+        }
+
+        String orderFlag = queryMeter.getOrderFlag().toLowerCase();
+        if (!"asc".equals(orderFlag) && !"desc".equals(orderFlag)) {
+            logger.warn("无效的排序标志: {}, 使用默认值 desc", queryMeter.getOrderFlag());
+            queryMeter.setOrderFlag("desc");
+        }
+
+        return true;
+    }
+
+    /**
+     * 填充区域用电统计的区域名称路径
+     */
+    private void fillAreaNameForElecConsumption(List<ElecConsumptionVO> consumptionList) {
+        if (CollectionUtils.isEmpty(consumptionList)) {
+            return;
+        }
+
+        try {
+            // 获取所有区域信息
+            List<Area> areas = areaService.selectArea(new Area());
+            Map<String, Area> areaMap = areas.stream()
+                .collect(Collectors.toMap(Area::getAreaCode, Function.identity()));
+
+            // 为每个统计记录填充区域路径名称
+            for (ElecConsumptionVO vo : consumptionList) {
+                fillAreaNameForSingleRecord(vo, areaMap);
+            }
+
+            logger.debug("完成用电统计区域名称填充,记录数: {}", consumptionList.size());
+        } catch (Exception e) {
+            logger.error("填充用电统计区域名称异常", e);
+        }
+    }
+
+    /**
+     * 为单条记录填充区域名称
+     */
+    private void fillAreaNameForSingleRecord(ElecConsumptionVO vo, Map<String, Area> areaMap) {
+        if (vo == null || StringUtils.isBlank(vo.getObjCode())) {
+            return;
+        }
+
+        // 获取区域完整路径名称
+        String areaNamePath = AreaUtils.getAreaNamePath(vo.getObjCode(), areaMap);
+
+        // 如果原名称是简单的名称(如"二楼"),用路径名称替换
+        if (StringUtils.isNotBlank(areaNamePath)) {
+            vo.setObjName(areaNamePath);
+            logger.debug("区域名称已替换: {} -> {}", vo.getObjCode(), areaNamePath);
+        }
+    }
+}

+ 0 - 142
ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/EnergyConsumptionServiceImpl.java

@@ -1,142 +0,0 @@
-package com.ruoyi.ems.service.impl;
-
-import com.ruoyi.ems.mapper.EnergyConsumptionMapper;
-import com.ruoyi.ems.model.EnergyConsumptionVO;
-import com.ruoyi.ems.model.QueryMeter;
-import com.ruoyi.ems.service.IEnergyConsumptionService;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.math.BigDecimal;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * 用能统计服务实现
- *
- * @author ruoyi
- * @date 2024-12-20
- */
-@Service
-public class EnergyConsumptionServiceImpl implements IEnergyConsumptionService {
-
-    @Autowired
-    private EnergyConsumptionMapper energyConsumptionMapper;
-
-    @Override
-    public List<EnergyConsumptionVO> selectAreaConsumptionList(QueryMeter queryMeter) {
-        // 参数校验
-        if (queryMeter == null) {
-            return Collections.emptyList();
-        }
-
-        // 设置默认时间维度
-        if (StringUtils.isBlank(queryMeter.getTimeDimension())) {
-            queryMeter.setTimeDimension("day");
-        }
-
-        // 根据时间维度调用不同的查询方法
-        switch (queryMeter.getTimeDimension().toLowerCase()) {
-            case "day":
-                return energyConsumptionMapper.selectAreaDailyConsumption(queryMeter);
-            case "month":
-                return energyConsumptionMapper.selectAreaMonthlyConsumption(queryMeter);
-            case "year":
-                return energyConsumptionMapper.selectAreaYearlyConsumption(queryMeter);
-            default:
-                return energyConsumptionMapper.selectAreaDailyConsumption(queryMeter);
-        }
-    }
-
-    @Override
-    public List<EnergyConsumptionVO> selectFacsConsumptionList(QueryMeter queryMeter) {
-        // 参数校验
-        if (queryMeter == null) {
-            return Collections.emptyList();
-        }
-
-        // 设置默认时间维度
-        if (StringUtils.isBlank(queryMeter.getTimeDimension())) {
-            queryMeter.setTimeDimension("day");
-        }
-
-        // 根据时间维度调用不同的查询方法
-        switch (queryMeter.getTimeDimension().toLowerCase()) {
-            case "day":
-                return energyConsumptionMapper.selectFacsDailyConsumption(queryMeter);
-            case "month":
-                return energyConsumptionMapper.selectFacsMonthlyConsumption(queryMeter);
-            case "year":
-                return energyConsumptionMapper.selectFacsYearlyConsumption(queryMeter);
-            default:
-                return energyConsumptionMapper.selectFacsDailyConsumption(queryMeter);
-        }
-    }
-
-    @Override
-    public EnergyConsumptionVO selectAreaConsumptionSummary(QueryMeter queryMeter) {
-        if (queryMeter == null) {
-            return new EnergyConsumptionVO();
-        }
-
-        EnergyConsumptionVO summary = energyConsumptionMapper.selectAreaConsumptionSummary(queryMeter);
-        return summary != null ? summary : new EnergyConsumptionVO();
-    }
-
-    @Override
-    public EnergyConsumptionVO selectFacsConsumptionSummary(QueryMeter queryMeter) {
-        if (queryMeter == null) {
-            return new EnergyConsumptionVO();
-        }
-
-        EnergyConsumptionVO summary = energyConsumptionMapper.selectFacsConsumptionSummary(queryMeter);
-        return summary != null ? summary : new EnergyConsumptionVO();
-    }
-
-    @Override
-    public List<EnergyConsumptionVO> exportAreaConsumptionList(QueryMeter queryMeter) {
-        if (queryMeter == null) {
-            return Collections.emptyList();
-        }
-
-        // 导出时不分页,设置大数据量限制
-        queryMeter.setPageNum(null);
-        queryMeter.setPageSize(null);
-
-        return selectAreaConsumptionList(queryMeter);
-    }
-
-    @Override
-    public List<EnergyConsumptionVO> exportFacsConsumptionList(QueryMeter queryMeter) {
-        if (queryMeter == null) {
-            return Collections.emptyList();
-        }
-
-        // 导出时不分页,设置大数据量限制
-        queryMeter.setPageNum(null);
-        queryMeter.setPageSize(null);
-
-        return selectFacsConsumptionList(queryMeter);
-    }
-
-    /**
-     * 计算统计数据的平均值
-     */
-    private BigDecimal calculateAverage(BigDecimal total, int count) {
-        if (total == null || count == 0) {
-            return BigDecimal.ZERO;
-        }
-        return total.divide(BigDecimal.valueOf(count), 2, BigDecimal.ROUND_HALF_UP);
-    }
-
-    /**
-     * 格式化统计时间
-     */
-    private String formatStatisticTime(QueryMeter queryMeter) {
-        if (StringUtils.isNotBlank(queryMeter.getStartRecTime())) {
-            return queryMeter.getStartRecTime().substring(0, 10);
-        }
-        return "";
-    }
-}

+ 6 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/MeterBoundaryRelServiceImpl.java

@@ -6,6 +6,7 @@ import com.ruoyi.ems.service.IMeterBoundaryRelService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -20,6 +21,11 @@ public class MeterBoundaryRelServiceImpl implements IMeterBoundaryRelService {
     private MeterBoundaryRelMapper relMapper;
 
     @Override
+    public List<String> selectMeterDevices(String boundaryObj, Integer objType, Integer meterCls) {
+        return relMapper.selectMeterDevices(boundaryObj, objType, meterCls);
+    }
+
+    @Override
     public List<MeterBoundaryRel> selectRelByObj(String boundaryObj, Integer objType, Integer meterCls) {
         return relMapper.selectByObj(boundaryObj, objType, meterCls);
     }

+ 403 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/WaterConsumptionServiceImpl.java

@@ -0,0 +1,403 @@
+package com.ruoyi.ems.service.impl;
+
+import com.ruoyi.ems.domain.Area;
+import com.ruoyi.ems.mapper.WaterConsumptionMapper;
+import com.ruoyi.ems.model.QueryMeter;
+import com.ruoyi.ems.model.WaterConsumptionExportVO;
+import com.ruoyi.ems.model.WaterConsumptionVO;
+import com.ruoyi.ems.service.IAreaService;
+import com.ruoyi.ems.service.IMeterBoundaryRelService;
+import com.ruoyi.ems.service.IWaterConsumptionService;
+import com.ruoyi.ems.util.AreaUtils;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * 用水统计服务实现
+ */
+@Service
+public class WaterConsumptionServiceImpl implements IWaterConsumptionService {
+    private static final Logger logger = LoggerFactory.getLogger(WaterConsumptionServiceImpl.class);
+
+    @Autowired
+    private WaterConsumptionMapper waterConsumptionMapper;
+
+    @Autowired
+    private IMeterBoundaryRelService meterBoundaryRelService;
+
+    @Autowired
+    private IAreaService areaService;
+
+    /**
+     * 水表计量类型常量
+     */
+    private static final int WATER_METER_CLS = 70;
+
+    @Override
+    public List<WaterConsumptionVO> selectAreaWaterConsumptionList(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            return Collections.emptyList();
+        }
+
+        // 1. 获取所有相关测点设备
+        Set<String> meterDevices = getMeterDevicesByArea(queryMeter);
+        if (meterDevices.isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        // 2. 根据时间维度调用相应的查询方法
+        List<WaterConsumptionVO> result;
+        switch (queryMeter.getTimeDimension().toLowerCase()) {
+            case "day":
+                result = waterConsumptionMapper.selectAreaDailyWaterConsumptionByDevices(queryMeter, meterDevices);
+            case "month":
+                result = waterConsumptionMapper.selectAreaMonthlyWaterConsumptionByDevices(queryMeter, meterDevices);
+            case "year":
+                result = waterConsumptionMapper.selectAreaYearlyWaterConsumptionByDevices(queryMeter, meterDevices);
+            default:
+                result = waterConsumptionMapper.selectAreaMonthlyWaterConsumptionByDevices(queryMeter, meterDevices);
+        }
+
+        // 填充区域名称路径
+        fillAreaNameForElecConsumption(result);
+
+        return result;
+    }
+
+    @Override
+    public WaterConsumptionVO selectAreaWaterConsumptionSummary(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            return new WaterConsumptionVO();
+        }
+
+        // 1. 获取所有相关测点设备
+        Set<String> meterDevices = getMeterDevicesByArea(queryMeter);
+        if (meterDevices.isEmpty()) {
+            return new WaterConsumptionVO();
+        }
+
+        // 2. 查询汇总数据
+        WaterConsumptionVO summary = waterConsumptionMapper.selectAreaWaterConsumptionSummaryByDevices(queryMeter,
+            meterDevices);
+        return summary != null ? summary : new WaterConsumptionVO();
+    }
+
+    /**
+     * 根据区域获取所有相关的水表设备(修复版本 - 参照用电实现)
+     */
+    private Set<String> getMeterDevicesByArea(QueryMeter queryMeter) {
+        Set<String> meterDevices = new HashSet<>();
+
+        try {
+            // 确定查询的区域范围
+            Set<String> targetAreaCodes = new HashSet<>();
+
+            if (StringUtils.isNotBlank(queryMeter.getObjCode()) && !"-1".equals(queryMeter.getObjCode())) {
+                // 指定了区域代码,需要查询该区域及其所有子区域(树节点点击传入的是objCode)
+                targetAreaCodes.addAll(getAllChildAreaCodes(queryMeter.getObjCode()));
+                logger.debug("根据objCode查询区域设备,区域代码: {}, 找到子区域数量: {}", queryMeter.getObjCode(),
+                    targetAreaCodes.size());
+            }
+
+            // 如果没有指定任何区域,查询所有区域的所有水表
+            if (targetAreaCodes.isEmpty()) {
+                logger.debug("未指定区域,查询所有水表设备");
+
+                // 关键修复:清除分页参数,避免影响测点设备查询
+                com.github.pagehelper.PageHelper.clearPage();
+
+                // 修复:objType应该是1(区域),不是2(设施)
+                List<String> allDevices = meterBoundaryRelService.selectMeterDevices(null, 1, WATER_METER_CLS);
+                if (!CollectionUtils.isEmpty(allDevices)) {
+                    meterDevices.addAll(allDevices);
+                    logger.debug("查询到所有区域水表设备数量: {}", allDevices.size());
+                }
+                else {
+                    // 方法2:如果上面的方法没有数据,尝试获取所有区域,然后查询每个区域的设备
+                    List<Area> allAreas = areaService.selectArea(new Area());
+                    if (!CollectionUtils.isEmpty(allAreas)) {
+                        for (Area area : allAreas) {
+                            // 每次查询前清除分页参数
+                            com.github.pagehelper.PageHelper.clearPage();
+
+                            List<String> areaDevices = meterBoundaryRelService.selectMeterDevices(area.getAreaCode(), 1,
+                                WATER_METER_CLS);
+                            if (!CollectionUtils.isEmpty(areaDevices)) {
+                                meterDevices.addAll(areaDevices);
+                                logger.debug("区域 {} 找到水表设备数量: {}", area.getAreaCode(), areaDevices.size());
+                            }
+                        }
+                    }
+                }
+            }
+            else {
+                // 根据区域代码获取绑定的测点设备
+                for (String areaCode : targetAreaCodes) {
+                    // 每次查询前清除分页参数
+                    com.github.pagehelper.PageHelper.clearPage();
+
+                    // 修复:objType应该是1(区域),不是2(设施)
+                    List<String> devices = meterBoundaryRelService.selectMeterDevices(areaCode, 1, WATER_METER_CLS);
+                    if (!CollectionUtils.isEmpty(devices)) {
+                        meterDevices.addAll(devices);
+                        logger.debug("区域 {} 找到水表设备数量: {}", areaCode, devices.size());
+                    }
+                }
+            }
+
+            logger.info("最终获取到的水表设备总数: {}", meterDevices.size());
+            if (logger.isDebugEnabled()) {
+                logger.debug("设备列表: {}", meterDevices);
+            }
+
+        }
+        catch (Exception e) {
+            logger.error("获取区域水表设备异常", e);
+        }
+        finally {
+            // 确保分页参数被清理
+            com.github.pagehelper.PageHelper.clearPage();
+        }
+
+        return meterDevices;
+    }
+
+    /**
+     * 获取指定区域及其所有子区域的代码
+     */
+    private Set<String> getAllChildAreaCodes(String areaCode) {
+        Set<String> areaCodes = new HashSet<>();
+
+        // 1. 添加当前区域本身
+        Area currentArea = areaService.selectAreaByCode(areaCode);
+        if (currentArea != null) {
+            areaCodes.add(currentArea.getAreaCode());
+        }
+
+        // 2. 获取当前区域的子区域树(递归获取)
+        List<Area> childAreas = areaService.selectAreaTree(areaCode, true);
+
+        // 3. 递归遍历子区域树,收集所有区域代码
+        collectAreaCodes(childAreas, areaCodes);
+
+        return areaCodes;
+    }
+
+    /**
+     * 递归收集区域树中的所有区域代码
+     */
+    private void collectAreaCodes(List<?> areas, Set<String> areaCodes) {
+        if (areas == null || areas.isEmpty()) {
+            return;
+        }
+
+        for (Object obj : areas) {
+            Area area = (Area) obj;
+            areaCodes.add(area.getAreaCode());
+
+            // 递归处理子区域
+            if (area.getChildren() != null && !area.getChildren().isEmpty()) {
+                collectAreaCodes(area.getChildren(), areaCodes);
+            }
+        }
+    }
+
+    @Override
+    public List<WaterConsumptionVO> selectFacsWaterConsumptionList(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            return Collections.emptyList();
+        }
+
+        switch (queryMeter.getTimeDimension().toLowerCase()) {
+            case "day":
+                return waterConsumptionMapper.selectFacsDailyWaterConsumption(queryMeter);
+            case "month":
+                return waterConsumptionMapper.selectFacsMonthlyWaterConsumption(queryMeter);
+            case "year":
+                return waterConsumptionMapper.selectFacsYearlyWaterConsumption(queryMeter);
+            default:
+                return waterConsumptionMapper.selectFacsMonthlyWaterConsumption(queryMeter);
+        }
+    }
+
+    @Override
+    public WaterConsumptionVO selectFacsWaterConsumptionSummary(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            return new WaterConsumptionVO();
+        }
+
+        WaterConsumptionVO summary = waterConsumptionMapper.selectFacsWaterConsumptionSummary(queryMeter);
+        return summary != null ? summary : new WaterConsumptionVO();
+    }
+
+    @Override
+    public List<WaterConsumptionVO> exportAreaWaterConsumptionList(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            return Collections.emptyList();
+        }
+
+        // 导出时不分页
+        queryMeter.setPageNum(null);
+        queryMeter.setPageSize(null);
+
+        return selectAreaWaterConsumptionList(queryMeter);
+    }
+
+    @Override
+    public List<WaterConsumptionVO> exportFacsWaterConsumptionList(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            return Collections.emptyList();
+        }
+
+        // 导出时不分页
+        queryMeter.setPageNum(null);
+        queryMeter.setPageSize(null);
+
+        return selectFacsWaterConsumptionList(queryMeter);
+    }
+
+    /**
+     * 转换为用水导出VO列表
+     */
+    public List<WaterConsumptionExportVO> convertToWaterExportVOList(List<WaterConsumptionVO> originalList,
+        String timeDimension) {
+        if (originalList == null || originalList.isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        return originalList.stream().map(vo -> convertToWaterExportVO(vo, timeDimension))
+            .collect(java.util.stream.Collectors.toList());
+    }
+
+    /**
+     * 转换单个用水VO为导出VO
+     */
+    private WaterConsumptionExportVO convertToWaterExportVO(WaterConsumptionVO vo, String timeDimension) {
+        WaterConsumptionExportVO exportVO = new WaterConsumptionExportVO();
+
+        // 对象名称
+        exportVO.setObjName(vo.getObjName());
+
+        // 统计时间 - 根据时间维度格式化
+        exportVO.setStatisticTime(formatStatisticTime(vo, timeDimension));
+
+        // 用水量和费用 - 格式化为2位小数
+        exportVO.setTotalWaterQuantity(formatNumber(vo.getTotalWaterQuantity(), 2));
+        exportVO.setTotalWaterCost(formatNumber(vo.getTotalWaterCost(), 2));
+
+        return exportVO;
+    }
+
+    /**
+     * 格式化统计时间
+     */
+    private String formatStatisticTime(WaterConsumptionVO vo, String timeDimension) {
+        if (timeDimension == null) {
+            timeDimension = "month";
+        }
+
+        switch (timeDimension.toLowerCase()) {
+            case "day":
+                return formatDateForDisplay(vo.getStatisticDate());
+            case "month":
+                return StringUtils.isNotBlank(vo.getStatisticMonth()) ? vo.getStatisticMonth() : "";
+            case "year":
+                return vo.getStatisticYear() != null ? vo.getStatisticYear().toString() : "";
+            default:
+                return StringUtils.isNotBlank(vo.getStatisticMonth()) ? vo.getStatisticMonth() : "";
+        }
+    }
+
+    /**
+     * 数字格式化
+     */
+    private String formatNumber(java.math.BigDecimal num, int decimals) {
+        if (num == null) {
+            StringBuilder sb = new StringBuilder("0.");
+            for (int i = 0; i < decimals; i++) {
+                sb.append("0");
+            }
+            return sb.toString();
+        }
+        return String.format("%." + decimals + "f", num.doubleValue());
+    }
+
+    /**
+     * 日期格式化用于显示
+     */
+    private String formatDateForDisplay(Object dateObj) {
+        if (dateObj == null) {
+            return "";
+        }
+
+        String dateStr = dateObj.toString();
+
+        // 如果是完整的日期时间字符串,提取日期部分
+        if (dateStr.contains(" ")) {
+            return dateStr.split(" ")[0];
+        }
+
+        // 如果已经是日期格式,直接返回
+        if (dateStr.matches("\\d{4}-\\d{2}-\\d{2}")) {
+            return dateStr;
+        }
+
+        return dateStr;
+    }
+
+    /**
+     * 填充区域用电统计的区域名称路径
+     */
+    private void fillAreaNameForElecConsumption(List<WaterConsumptionVO> consumptionList) {
+        if (org.springframework.util.CollectionUtils.isEmpty(consumptionList)) {
+            return;
+        }
+
+        try {
+            // 获取所有区域信息
+            List<Area> areas = areaService.selectArea(new Area());
+            Map<String, Area> areaMap = areas.stream()
+                .collect(Collectors.toMap(Area::getAreaCode, Function.identity()));
+
+            // 为每个统计记录填充区域路径名称
+            for (WaterConsumptionVO vo : consumptionList) {
+                fillAreaNameForSingleRecord(vo, areaMap);
+            }
+
+            logger.debug("完成用电统计区域名称填充,记录数: {}", consumptionList.size());
+        }
+        catch (Exception e) {
+            logger.error("填充用电统计区域名称异常", e);
+        }
+    }
+
+    /**
+     * 为单条记录填充区域名称
+     */
+    private void fillAreaNameForSingleRecord(WaterConsumptionVO vo, Map<String, Area> areaMap) {
+        if (vo == null || StringUtils.isBlank(vo.getObjCode())) {
+            return;
+        }
+
+        // 获取区域完整路径名称
+        String areaNamePath = AreaUtils.getAreaNamePath(vo.getObjCode(), areaMap);
+
+        // 如果原名称是简单的名称(如"二楼"),用路径名称替换
+        if (StringUtils.isNotBlank(areaNamePath)) {
+            vo.setObjName(areaNamePath);
+            logger.debug("区域名称已替换: {} -> {}", vo.getObjCode(), areaNamePath);
+        }
+    }
+}

+ 327 - 0
ems/ems-core/src/main/resources/mapper/ems/ElecConsumptionMapper.xml

@@ -0,0 +1,327 @@
+<?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.ElecConsumptionMapper">
+
+    <resultMap type="com.ruoyi.ems.model.ElecConsumptionVO" id="ElecConsumptionResult">
+        <result property="areaCode" column="area_code"/>
+        <result property="areaName" column="area_name"/>
+        <result property="objCode" column="obj_code"/>
+        <result property="objName" column="obj_name"/>
+        <result property="objType" column="obj_type"/>
+        <result property="statisticDate" column="statistic_date"/>
+        <result property="statisticYear" column="statistic_year"/>
+        <result property="statisticMonth" column="statistic_month"/>
+        <result property="timeDimension" column="time_dimension"/>
+        <result property="totalElecQuantity" column="total_elec_quantity"/>
+        <result property="sharpPeakQuantity" column="sharp_peak_quantity"/>
+        <result property="peakQuantity" column="peak_quantity"/>
+        <result property="normalQuantity" column="normal_quantity"/>
+        <result property="valleyQuantity" column="valley_quantity"/>
+        <result property="totalElecCost" column="total_elec_cost"/>
+        <result property="createTime" column="create_time"/>
+    </resultMap>
+
+    <!-- ==================== 区域用电统计查询(基于设备codes汇总,支持峰谷电) ==================== -->
+
+    <!-- 根据设备代码列表查询区域日用电统计 -->
+    <select id="selectAreaDailyElecConsumptionByDevices" resultMap="ElecConsumptionResult">
+        SELECT
+        a.area_code,
+        a.area_name as obj_name,
+        a.area_code as obj_code,
+        1 as obj_type,
+        h.date as statistic_date,
+        'DAY' as time_dimension,
+        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) as total_elec_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 2 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as sharp_peak_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 1 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as peak_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 0 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as normal_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = -1 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as valley_quantity,
+        ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as total_elec_cost,
+        NOW() as create_time
+        FROM adm_elec_meter_h h
+        INNER JOIN adm_meter_boundary_rel rel ON rel.meter_device = h.device_code AND rel.meter_cls = 45 AND rel.obj_type = 1
+        INNER JOIN adm_area a ON a.area_code = rel.boundary_obj
+        WHERE h.device_code IN
+        <foreach collection="meterDevices" item="device" open="(" close=")" separator=",">
+            #{device}
+        </foreach>
+        <if test="queryMeter.startRecTime != null and queryMeter.startRecTime != ''">
+            AND h.date &gt;= DATE(#{queryMeter.startRecTime})
+        </if>
+        <if test="queryMeter.endRecTime != null and queryMeter.endRecTime != ''">
+            AND h.date &lt;= DATE(#{queryMeter.endRecTime})
+        </if>
+        AND h.date IS NOT NULL
+        GROUP BY a.area_code, a.area_name, h.date
+        ORDER BY h.date ${queryMeter.orderFlag}, a.area_code
+    </select>
+
+    <!-- 根据设备代码列表查询区域月用电统计 -->
+    <select id="selectAreaMonthlyElecConsumptionByDevices" resultMap="ElecConsumptionResult">
+        SELECT
+        a.area_code,
+        a.area_name as obj_name,
+        a.area_code as obj_code,
+        1 as obj_type,
+        DATE(CONCAT(DATE_FORMAT(h.date, '%Y-%m'), '-01')) as statistic_date,
+        DATE_FORMAT(h.date, '%Y-%m') as statistic_month,
+        'MONTH' as time_dimension,
+        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) as total_elec_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 2 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as sharp_peak_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 1 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as peak_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 0 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as normal_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = -1 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as valley_quantity,
+        ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as total_elec_cost,
+        NOW() as create_time
+        FROM adm_elec_meter_h h
+        INNER JOIN adm_meter_boundary_rel rel ON rel.meter_device = h.device_code AND rel.meter_cls = 45 AND rel.obj_type = 1
+        INNER JOIN adm_area a ON a.area_code = rel.boundary_obj
+        WHERE h.device_code IN
+        <foreach collection="meterDevices" item="device" open="(" close=")" separator=",">
+            #{device}
+        </foreach>
+        <if test="queryMeter.startRecTime != null and queryMeter.startRecTime != ''">
+            AND h.date &gt;= DATE(#{queryMeter.startRecTime})
+        </if>
+        <if test="queryMeter.endRecTime != null and queryMeter.endRecTime != ''">
+            AND h.date &lt;= DATE(#{queryMeter.endRecTime})
+        </if>
+        AND h.date IS NOT NULL
+        GROUP BY a.area_code, a.area_name, DATE_FORMAT(h.date, '%Y-%m')
+        ORDER BY DATE_FORMAT(h.date, '%Y-%m') ${queryMeter.orderFlag}, a.area_code
+    </select>
+
+    <!-- 根据设备代码列表查询区域年用电统计 -->
+    <select id="selectAreaYearlyElecConsumptionByDevices" resultMap="ElecConsumptionResult">
+        SELECT
+        a.area_code,
+        a.area_name as obj_name,
+        a.area_code as obj_code,
+        1 as obj_type,
+        DATE(CONCAT(YEAR(h.date), '-01-01')) as statistic_date,
+        YEAR(h.date) as statistic_year,
+        'YEAR' as time_dimension,
+        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) as total_elec_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 2 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as sharp_peak_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 1 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as peak_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 0 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as normal_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = -1 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as valley_quantity,
+        ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as total_elec_cost,
+        NOW() as create_time
+        FROM adm_elec_meter_h h
+        INNER JOIN adm_meter_boundary_rel rel ON rel.meter_device = h.device_code AND rel.meter_cls = 45 AND rel.obj_type = 1
+        INNER JOIN adm_area a ON a.area_code = rel.boundary_obj
+        WHERE h.device_code IN
+        <foreach collection="meterDevices" item="device" open="(" close=")" separator=",">
+            #{device}
+        </foreach>
+        <if test="queryMeter.startRecTime != null and queryMeter.startRecTime != ''">
+            AND h.date &gt;= DATE(#{queryMeter.startRecTime})
+        </if>
+        <if test="queryMeter.endRecTime != null and queryMeter.endRecTime != ''">
+            AND h.date &lt;= DATE(#{queryMeter.endRecTime})
+        </if>
+        AND h.date IS NOT NULL
+        GROUP BY a.area_code, a.area_name, YEAR(h.date)
+        ORDER BY YEAR(h.date) ${queryMeter.orderFlag}, a.area_code
+    </select>
+
+    <!-- 根据设备代码列表查询区域用电汇总 -->
+    <select id="selectAreaElecConsumptionSummaryByDevices" resultMap="ElecConsumptionResult">
+        SELECT
+        'TOTAL' as area_code,
+        '总计' as obj_name,
+        'TOTAL' as obj_code,
+        1 as obj_type,
+        'SUMMARY' as time_dimension,
+        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) as total_elec_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 2 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as sharp_peak_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 1 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as peak_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 0 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as normal_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = -1 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as valley_quantity,
+        ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as total_elec_cost
+        FROM adm_elec_meter_h h
+        WHERE h.device_code IN
+        <foreach collection="meterDevices" item="device" open="(" close=")" separator=",">
+            #{device}
+        </foreach>
+        <if test="queryMeter.startRecTime != null and queryMeter.startRecTime != ''">
+            AND h.date &gt;= DATE(#{queryMeter.startRecTime})
+        </if>
+        <if test="queryMeter.endRecTime != null and queryMeter.endRecTime != ''">
+            AND h.date &lt;= DATE(#{queryMeter.endRecTime})
+        </if>
+        AND h.date IS NOT NULL
+    </select>
+
+    <!-- ==================== 设施用电统计查询 ==================== -->
+
+    <!-- 查询设施日用电统计 -->
+    <select id="selectFacsDailyElecConsumption" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="ElecConsumptionResult">
+        SELECT
+        f.ref_area as area_code,
+        f.facs_name as obj_name,
+        f.facs_code as obj_code,
+        2 as obj_type,
+        h.date as statistic_date,
+        'DAY' as time_dimension,
+        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) as total_elec_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 2 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as sharp_peak_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 1 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as peak_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 0 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as normal_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = -1 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as valley_quantity,
+        ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as total_elec_cost,
+        NOW() as create_time
+        FROM adm_ems_facs f
+        LEFT JOIN adm_meter_boundary_rel rel ON rel.obj_type = 2 AND rel.boundary_obj = f.facs_code
+        LEFT JOIN adm_elec_meter_h h ON h.device_code = rel.meter_device AND rel.meter_cls = 45
+        <where>
+            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
+                AND f.ref_area = #{areaCode}
+            </if>
+            <if test="objCode != null and objCode != '' and objCode != '-1'">
+                AND f.facs_code = #{objCode}
+            </if>
+            <if test="facsCategory != null and facsCategory != ''">
+                AND f.facs_category = #{facsCategory}
+            </if>
+            <if test="startRecTime != null and startRecTime != ''">
+                AND h.date &gt;= DATE(#{startRecTime})
+            </if>
+            <if test="endRecTime != null and endRecTime != ''">
+                AND h.date &lt;= DATE(#{endRecTime})
+            </if>
+            AND h.date IS NOT NULL
+            AND f.enable = 1
+        </where>
+        GROUP BY f.facs_code, f.facs_name, f.ref_area, h.date
+        ORDER BY h.date ${orderFlag}, f.facs_code
+    </select>
+
+    <!-- 查询设施月用电统计 -->
+    <select id="selectFacsMonthlyElecConsumption" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="ElecConsumptionResult">
+        SELECT
+        f.ref_area as area_code,
+        f.facs_name as obj_name,
+        f.facs_code as obj_code,
+        2 as obj_type,
+        DATE(CONCAT(DATE_FORMAT(h.date, '%Y-%m'), '-01')) as statistic_date,
+        DATE_FORMAT(h.date, '%Y-%m') as statistic_month,
+        'MONTH' as time_dimension,
+        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) as total_elec_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 2 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as sharp_peak_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 1 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as peak_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 0 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as normal_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = -1 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as valley_quantity,
+        ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as total_elec_cost,
+        NOW() as create_time
+        FROM adm_ems_facs f
+        LEFT JOIN adm_meter_boundary_rel rel ON rel.obj_type = 2 AND rel.boundary_obj = f.facs_code
+        LEFT JOIN adm_elec_meter_h h ON h.device_code = rel.meter_device AND rel.meter_cls = 45
+        <where>
+            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
+                AND f.ref_area = #{areaCode}
+            </if>
+            <if test="objCode != null and objCode != '' and objCode != '-1'">
+                AND f.facs_code = #{objCode}
+            </if>
+            <if test="facsCategory != null and facsCategory != ''">
+                AND f.facs_category = #{facsCategory}
+            </if>
+            <if test="startRecTime != null and startRecTime != ''">
+                AND h.date &gt;= DATE(#{startRecTime})
+            </if>
+            <if test="endRecTime != null and endRecTime != ''">
+                AND h.date &lt;= DATE(#{endRecTime})
+            </if>
+            AND h.date IS NOT NULL
+            AND f.enable = 1
+        </where>
+        GROUP BY f.facs_code, f.facs_name, f.ref_area, DATE_FORMAT(h.date, '%Y-%m')
+        ORDER BY DATE_FORMAT(h.date, '%Y-%m') ${orderFlag}, f.facs_code
+    </select>
+
+    <!-- 查询设施年用电统计 -->
+    <select id="selectFacsYearlyElecConsumption" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="ElecConsumptionResult">
+        SELECT
+        f.ref_area as area_code,
+        f.facs_name as obj_name,
+        f.facs_code as obj_code,
+        2 as obj_type,
+        DATE(CONCAT(YEAR(h.date), '-01-01')) as statistic_date,
+        YEAR(h.date) as statistic_year,
+        'YEAR' as time_dimension,
+        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) as total_elec_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 2 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as sharp_peak_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 1 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as peak_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 0 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as normal_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = -1 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as valley_quantity,
+        ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as total_elec_cost,
+        NOW() as create_time
+        FROM adm_ems_facs f
+        LEFT JOIN adm_meter_boundary_rel rel ON rel.obj_type = 2 AND rel.boundary_obj = f.facs_code
+        LEFT JOIN adm_elec_meter_h h ON h.device_code = rel.meter_device AND rel.meter_cls = 45
+        <where>
+            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
+                AND f.ref_area = #{areaCode}
+            </if>
+            <if test="objCode != null and objCode != '' and objCode != '-1'">
+                AND f.facs_code = #{objCode}
+            </if>
+            <if test="facsCategory != null and facsCategory != ''">
+                AND f.facs_category = #{facsCategory}
+            </if>
+            <if test="startRecTime != null and startRecTime != ''">
+                AND h.date &gt;= DATE(#{startRecTime})
+            </if>
+            <if test="endRecTime != null and endRecTime != ''">
+                AND h.date &lt;= DATE(#{endRecTime})
+            </if>
+            AND h.date IS NOT NULL
+            AND f.enable = 1
+        </where>
+        GROUP BY f.facs_code, f.facs_name, f.ref_area, YEAR(h.date)
+        ORDER BY YEAR(h.date) ${orderFlag}, f.facs_code
+    </select>
+
+    <!-- 查询设施用电统计汇总 -->
+    <select id="selectFacsElecConsumptionSummary" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="ElecConsumptionResult">
+        SELECT
+        COALESCE(#{areaCode}, '0') as area_code,
+        '总计' as obj_name,
+        'TOTAL' as obj_code,
+        2 as obj_type,
+        'SUMMARY' as time_dimension,
+        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) as total_elec_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 2 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as sharp_peak_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 1 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as peak_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = 0 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as normal_quantity,
+        ROUND(SUM(CASE WHEN h.meter_type = -1 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as valley_quantity,
+        ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as total_elec_cost
+        FROM adm_ems_facs f
+        LEFT JOIN adm_meter_boundary_rel rel ON rel.obj_type = 2 AND rel.boundary_obj = f.facs_code
+        LEFT JOIN adm_elec_meter_h h ON h.device_code = rel.meter_device AND rel.meter_cls = 45
+        <where>
+            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
+                AND f.ref_area = #{areaCode}
+            </if>
+            <if test="facsCategory != null and facsCategory != ''">
+                AND f.facs_category = #{facsCategory}
+            </if>
+            <if test="objCode != null and objCode != '' and objCode != '-1'">
+                AND f.facs_code = #{objCode}
+            </if>
+            <if test="startRecTime != null and startRecTime != ''">
+                AND h.date &gt;= DATE(#{startRecTime})
+            </if>
+            <if test="endRecTime != null and endRecTime != ''">
+                AND h.date &lt;= DATE(#{endRecTime})
+            </if>
+            AND h.date IS NOT NULL
+            AND f.enable = 1
+        </where>
+    </select>
+</mapper>

+ 0 - 371
ems/ems-core/src/main/resources/mapper/ems/EnergyConsumptionMapper.xml

@@ -1,371 +0,0 @@
-<?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.EnergyConsumptionMapper">
-
-    <resultMap type="com.ruoyi.ems.model.EnergyConsumptionVO" id="EnergyConsumptionResult">
-        <result property="areaCode" column="area_code"/>
-        <result property="areaName" column="area_name"/>
-        <result property="objCode" column="obj_code"/>
-        <result property="objName" column="obj_name"/>
-        <result property="objType" column="obj_type"/>
-        <result property="statisticDate" column="statistic_date"/>
-        <result property="statisticYear" column="statistic_year"/>
-        <result property="statisticMonth" column="statistic_month"/>
-        <result property="timeDimension" column="time_dimension"/>
-        <result property="elecQuantity" column="elec_quantity"/>
-        <result property="elecCost" column="elec_cost"/>
-        <result property="waterQuantity" column="water_quantity"/>
-        <result property="waterCost" column="water_cost"/>
-        <result property="createTime" column="create_time"/>
-    </resultMap>
-
-    <!-- ==================== 区域用能统计查询 ==================== -->
-
-    <!-- 查询区域日用能统计 -->
-    <select id="selectAreaDailyConsumption" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="EnergyConsumptionResult">
-        SELECT
-        a.area_code,
-        a.area_name as obj_name,
-        a.area_code as obj_code,
-        1 as obj_type,
-        h.date as statistic_date,
-        'DAY' as time_dimension,
-        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) as elec_quantity,
-        ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as elec_cost,
-        NOW() as create_time
-        FROM adm_area a
-        LEFT JOIN adm_meter_boundary_rel rel ON (
-        (rel.obj_type = 1 AND rel.boundary_obj = a.area_code) OR
-        (rel.obj_type = 1 AND EXISTS (
-        SELECT 1 FROM adm_area child
-        WHERE child.parent_code = a.area_code
-        AND rel.boundary_obj = child.area_code
-        ))
-        )
-        LEFT JOIN adm_elec_meter_h h ON h.device_code = rel.meter_device AND rel.meter_cls = 45
-        <where>
-            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
-                AND (a.area_code = #{areaCode} OR a.parent_code = #{areaCode} OR a.ancestors LIKE CONCAT('%,', #{areaCode}, ',%'))
-            </if>
-            <if test="objCode != null and objCode != '' and objCode != '-1'">
-                AND a.area_code = #{objCode}
-            </if>
-            <if test="startRecTime != null and startRecTime != ''">
-                AND h.date &gt;= DATE(#{startRecTime})
-            </if>
-            <if test="endRecTime != null and endRecTime != ''">
-                AND h.date &lt;= DATE(#{endRecTime})
-            </if>
-            AND h.date IS NOT NULL
-        </where>
-        GROUP BY a.area_code, a.area_name, h.date
-        ORDER BY h.date ${orderFlag}, a.area_code
-    </select>
-
-    <!-- 查询区域月用能统计 -->
-    <select id="selectAreaMonthlyConsumption" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="EnergyConsumptionResult">
-        SELECT
-        a.area_code,
-        a.area_name as obj_name,
-        a.area_code as obj_code,
-        1 as obj_type,
-        DATE(CONCAT(DATE_FORMAT(h.date, '%Y-%m'), '-01')) as statistic_date,
-        DATE_FORMAT(h.date, '%Y-%m') as statistic_month,
-        'MONTH' as time_dimension,
-        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) as elec_quantity,
-        ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as elec_cost,
-        NOW() as create_time
-        FROM adm_area a
-        LEFT JOIN adm_meter_boundary_rel rel ON (
-        (rel.obj_type = 1 AND rel.boundary_obj = a.area_code) OR
-        (rel.obj_type = 1 AND EXISTS (
-        SELECT 1 FROM adm_area child
-        WHERE child.parent_code = a.area_code
-        AND rel.boundary_obj = child.area_code
-        ))
-        )
-        LEFT JOIN adm_elec_meter_h h ON h.device_code = rel.meter_device AND rel.meter_cls = 45
-        <where>
-            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
-                AND (a.area_code = #{areaCode} OR a.parent_code = #{areaCode} OR a.ancestors LIKE CONCAT('%,', #{areaCode}, ',%'))
-            </if>
-            <if test="objCode != null and objCode != '' and objCode != '-1'">
-                AND a.area_code = #{objCode}
-            </if>
-            <if test="startRecTime != null and startRecTime != ''">
-                AND h.date &gt;= DATE(#{startRecTime})
-            </if>
-            <if test="endRecTime != null and endRecTime != ''">
-                AND h.date &lt;= DATE(#{endRecTime})
-            </if>
-            AND h.date IS NOT NULL
-        </where>
-        GROUP BY a.area_code, a.area_name, DATE_FORMAT(h.date, '%Y-%m')
-        ORDER BY DATE_FORMAT(h.date, '%Y-%m') ${orderFlag}, a.area_code
-    </select>
-
-    <!-- 查询区域年用能统计 -->
-    <select id="selectAreaYearlyConsumption" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="EnergyConsumptionResult">
-        SELECT
-        a.area_code,
-        a.area_name as obj_name,
-        a.area_code as obj_code,
-        1 as obj_type,
-        DATE(CONCAT(YEAR(h.date), '-01-01')) as statistic_date,
-        YEAR(h.date) as statistic_year,
-        'YEAR' as time_dimension,
-        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) as elec_quantity,
-        ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as elec_cost,
-        NOW() as create_time
-        FROM adm_area a
-        LEFT JOIN adm_meter_boundary_rel rel ON (
-        (rel.obj_type = 1 AND rel.boundary_obj = a.area_code) OR
-        (rel.obj_type = 1 AND EXISTS (
-        SELECT 1 FROM adm_area child
-        WHERE child.parent_code = a.area_code
-        AND rel.boundary_obj = child.area_code
-        ))
-        )
-        LEFT JOIN adm_elec_meter_h h ON h.device_code = rel.meter_device AND rel.meter_cls = 45
-        <where>
-            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
-                AND (a.area_code = #{areaCode} OR a.parent_code = #{areaCode} OR a.ancestors LIKE CONCAT('%,', #{areaCode}, ',%'))
-            </if>
-            <if test="objCode != null and objCode != '' and objCode != '-1'">
-                AND a.area_code = #{objCode}
-            </if>
-            <if test="startRecTime != null and startRecTime != ''">
-                AND h.date &gt;= DATE(#{startRecTime})
-            </if>
-            <if test="endRecTime != null and endRecTime != ''">
-                AND h.date &lt;= DATE(#{endRecTime})
-            </if>
-            AND h.date IS NOT NULL
-        </where>
-        GROUP BY a.area_code, a.area_name, YEAR(h.date)
-        ORDER BY YEAR(h.date) ${orderFlag}, a.area_code
-    </select>
-
-    <!-- 查询区域用能统计汇总 -->
-    <select id="selectAreaConsumptionSummary" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="EnergyConsumptionResult">
-        SELECT
-        COALESCE(#{areaCode}, '0') as area_code,
-        '总计' as obj_name,
-        'TOTAL' as obj_code,
-        1 as obj_type,
-        'SUMMARY' as time_dimension,
-        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) as elec_quantity,
-        ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as elec_cost
-        FROM adm_area a
-        LEFT JOIN adm_meter_boundary_rel rel ON (
-        (rel.obj_type = 1 AND rel.boundary_obj = a.area_code) OR
-        (rel.obj_type = 1 AND EXISTS (
-        SELECT 1 FROM adm_area child
-        WHERE child.parent_code = a.area_code
-        AND rel.boundary_obj = child.area_code
-        ))
-        )
-        LEFT JOIN adm_elec_meter_h h ON h.device_code = rel.meter_device AND rel.meter_cls = 45
-        <where>
-            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
-                AND (a.area_code = #{areaCode} OR a.parent_code = #{areaCode} OR a.ancestors LIKE CONCAT('%,', #{areaCode}, ',%'))
-            </if>
-            <if test="startRecTime != null and startRecTime != ''">
-                AND h.date &gt;= DATE(#{startRecTime})
-            </if>
-            <if test="endRecTime != null and endRecTime != ''">
-                AND h.date &lt;= DATE(#{endRecTime})
-            </if>
-            AND h.date IS NOT NULL
-        </where>
-    </select>
-
-    <!-- ==================== 设施用能统计查询 ==================== -->
-
-    <!-- 查询设施日用能统计 -->
-    <select id="selectFacsDailyConsumption" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="EnergyConsumptionResult">
-        SELECT
-        f.ref_area as area_code,
-        f.facs_name as obj_name,
-        f.facs_code as obj_code,
-        2 as obj_type,
-        h.date as statistic_date,
-        'DAY' as time_dimension,
-        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) as elec_quantity,
-        ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as elec_cost,
-        NOW() as create_time
-        FROM adm_ems_facs f
-        LEFT JOIN adm_meter_boundary_rel rel ON rel.obj_type = 2 AND rel.boundary_obj = f.facs_code
-        LEFT JOIN adm_elec_meter_h h ON h.device_code = rel.meter_device AND rel.meter_cls = 45
-        <where>
-            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
-                AND f.ref_area = #{areaCode}
-            </if>
-            <if test="objCode != null and objCode != '' and objCode != '-1'">
-                AND f.facs_code = #{objCode}
-            </if>
-            <if test="facsCategory != null and facsCategory != ''">
-                AND f.facs_category = #{facsCategory}
-            </if>
-            <if test="startRecTime != null and startRecTime != ''">
-                AND h.date &gt;= DATE(#{startRecTime})
-            </if>
-            <if test="endRecTime != null and endRecTime != ''">
-                AND h.date &lt;= DATE(#{endRecTime})
-            </if>
-            AND h.date IS NOT NULL
-            AND f.enable = 1
-        </where>
-        GROUP BY f.facs_code, f.facs_name, f.ref_area, h.date
-        ORDER BY h.date ${orderFlag}, f.facs_code
-    </select>
-
-    <!-- 查询设施月用能统计 -->
-    <select id="selectFacsMonthlyConsumption" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="EnergyConsumptionResult">
-        SELECT
-        f.ref_area as area_code,
-        f.facs_name as obj_name,
-        f.facs_code as obj_code,
-        2 as obj_type,
-        DATE(CONCAT(DATE_FORMAT(h.date, '%Y-%m'), '-01')) as statistic_date,
-        DATE_FORMAT(h.date, '%Y-%m') as statistic_month,
-        'MONTH' as time_dimension,
-        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) as elec_quantity,
-        ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as elec_cost,
-        NOW() as create_time
-        FROM adm_ems_facs f
-        LEFT JOIN adm_meter_boundary_rel rel ON rel.obj_type = 2 AND rel.boundary_obj = f.facs_code
-        LEFT JOIN adm_elec_meter_h h ON h.device_code = rel.meter_device AND rel.meter_cls = 45
-        <where>
-            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
-                AND f.ref_area = #{areaCode}
-            </if>
-            <if test="objCode != null and objCode != '' and objCode != '-1'">
-                AND f.facs_code = #{objCode}
-            </if>
-            <if test="facsCategory != null and facsCategory != ''">
-                AND f.facs_category = #{facsCategory}
-            </if>
-            <if test="startRecTime != null and startRecTime != ''">
-                AND h.date &gt;= DATE(#{startRecTime})
-            </if>
-            <if test="endRecTime != null and endRecTime != ''">
-                AND h.date &lt;= DATE(#{endRecTime})
-            </if>
-            AND h.date IS NOT NULL
-            AND f.enable = 1
-        </where>
-        GROUP BY f.facs_code, f.facs_name, f.ref_area, DATE_FORMAT(h.date, '%Y-%m')
-        ORDER BY DATE_FORMAT(h.date, '%Y-%m') ${orderFlag}, f.facs_code
-    </select>
-
-    <!-- 查询设施年用能统计 -->
-    <select id="selectFacsYearlyConsumption" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="EnergyConsumptionResult">
-        SELECT
-        f.ref_area as area_code,
-        f.facs_name as obj_name,
-        f.facs_code as obj_code,
-        2 as obj_type,
-        DATE(CONCAT(YEAR(h.date), '-01-01')) as statistic_date,
-        YEAR(h.date) as statistic_year,
-        'YEAR' as time_dimension,
-        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) as elec_quantity,
-        ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as elec_cost,
-        NOW() as create_time
-        FROM adm_ems_facs f
-        LEFT JOIN adm_meter_boundary_rel rel ON rel.obj_type = 2 AND rel.boundary_obj = f.facs_code
-        LEFT JOIN adm_elec_meter_h h ON h.device_code = rel.meter_device AND rel.meter_cls = 45
-        <where>
-            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
-                AND f.ref_area = #{areaCode}
-            </if>
-            <if test="objCode != null and objCode != '' and objCode != '-1'">
-                AND f.facs_code = #{objCode}
-            </if>
-            <if test="facsCategory != null and facsCategory != ''">
-                AND f.facs_category = #{facsCategory}
-            </if>
-            <if test="startRecTime != null and startRecTime != ''">
-                AND h.date &gt;= DATE(#{startRecTime})
-            </if>
-            <if test="endRecTime != null and endRecTime != ''">
-                AND h.date &lt;= DATE(#{endRecTime})
-            </if>
-            AND h.date IS NOT NULL
-            AND f.enable = 1
-        </where>
-        GROUP BY f.facs_code, f.facs_name, f.ref_area, YEAR(h.date)
-        ORDER BY YEAR(h.date) ${orderFlag}, f.facs_code
-    </select>
-
-    <!-- 查询设施用能统计汇总 -->
-    <select id="selectFacsConsumptionSummary" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="EnergyConsumptionResult">
-        SELECT
-        COALESCE(#{areaCode}, '0') as area_code,
-        '总计' as obj_name,
-        'TOTAL' as obj_code,
-        2 as obj_type,
-        'SUMMARY' as time_dimension,
-        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) as elec_quantity,
-        ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as elec_cost
-        FROM adm_ems_facs f
-        LEFT JOIN adm_meter_boundary_rel rel ON rel.obj_type = 2 AND rel.boundary_obj = f.facs_code
-        LEFT JOIN adm_elec_meter_h h ON h.device_code = rel.meter_device AND rel.meter_cls = 45
-        <where>
-            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
-                AND f.ref_area = #{areaCode}
-            </if>
-            <if test="facsCategory != null and facsCategory != ''">
-                AND f.facs_category = #{facsCategory}
-            </if>
-            <if test="objCode != null and objCode != '' and objCode != '-1'">
-                AND f.facs_code = #{objCode}
-            </if>
-            <if test="startRecTime != null and startRecTime != ''">
-                AND h.date &gt;= DATE(#{startRecTime})
-            </if>
-            <if test="endRecTime != null and endRecTime != ''">
-                AND h.date &lt;= DATE(#{endRecTime})
-            </if>
-            AND h.date IS NOT NULL
-            AND f.enable = 1
-        </where>
-    </select>
-
-    <!-- ==================== 辅助查询 ==================== -->
-
-    <!-- 根据区域获取绑定的计量设备 -->
-    <select id="selectMeterDevicesByArea" resultType="java.lang.String">
-        SELECT DISTINCT rel.meter_device
-        FROM adm_meter_boundary_rel rel
-        WHERE rel.obj_type = 1
-          AND rel.boundary_obj = #{areaCode}
-          AND rel.meter_cls = #{meterCls}
-    </select>
-
-    <!-- 根据设施获取绑定的计量设备 -->
-    <select id="selectMeterDevicesByFacs" resultType="java.lang.String">
-        SELECT DISTINCT rel.meter_device
-        FROM adm_meter_boundary_rel rel
-        WHERE rel.obj_type = 2
-          AND rel.boundary_obj = #{facsCode}
-          AND rel.meter_cls = #{meterCls}
-    </select>
-
-    <!-- 根据设施分类获取绑定的计量设备 -->
-    <select id="selectMeterDevicesByFacsCategory" resultType="java.lang.String">
-        SELECT DISTINCT rel.meter_device
-        FROM adm_meter_boundary_rel rel
-        INNER JOIN adm_ems_facs f ON f.facs_code = rel.boundary_obj
-        WHERE rel.obj_type = 2
-        AND f.facs_category = #{facsCategory}
-        <if test="areaCode != null and areaCode != ''">
-            AND f.ref_area = #{areaCode}
-        </if>
-        AND rel.meter_cls = #{meterCls}
-        AND f.enable = 1
-    </select>
-
-</mapper>

+ 10 - 0
ems/ems-core/src/main/resources/mapper/ems/MeterBoundaryRelMapper.xml

@@ -19,6 +19,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         from adm_meter_boundary_rel r
     </sql>
 
+    <select id="selectMeterDevices" resultType="java.lang.String">
+        SELECT DISTINCT r.meter_device
+        FROM adm_meter_boundary_rel r
+        <where>
+            <if test="boundaryObj != null  and boundaryObj != ''"> and r.boundary_obj = #{boundaryObj}</if>
+            <if test="objType != null "> and r.obj_type = #{objType}</if>
+            <if test="meterCls != null "> and r.meter_cls = #{meterCls}</if>
+        </where>
+    </select>
+
     <select id="selectByObj"  resultMap="relResult">
         <include refid="selectMeterBoundaryRelVo"/>
         left join adm_meter_device m on r.meter_device = m.device_code

+ 291 - 0
ems/ems-core/src/main/resources/mapper/ems/WaterConsumptionMapper.xml

@@ -0,0 +1,291 @@
+<?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.WaterConsumptionMapper">
+
+    <resultMap type="com.ruoyi.ems.model.WaterConsumptionVO" id="WaterConsumptionResult">
+        <result property="areaCode" column="area_code"/>
+        <result property="areaName" column="area_name"/>
+        <result property="objCode" column="obj_code"/>
+        <result property="objName" column="obj_name"/>
+        <result property="objType" column="obj_type"/>
+        <result property="statisticDate" column="statistic_date"/>
+        <result property="statisticYear" column="statistic_year"/>
+        <result property="statisticMonth" column="statistic_month"/>
+        <result property="timeDimension" column="time_dimension"/>
+        <result property="totalWaterQuantity" column="total_water_quantity"/>
+        <result property="totalWaterCost" column="total_water_cost"/>
+        <result property="createTime" column="create_time"/>
+    </resultMap>
+
+    <!-- ==================== 区域用水统计查询(基于设备codes汇总) ==================== -->
+
+    <!-- 根据设备代码列表查询区域日用水统计 -->
+    <select id="selectAreaDailyWaterConsumptionByDevices" resultMap="WaterConsumptionResult">
+        SELECT
+        a.area_code,
+        a.area_name as obj_name,
+        a.area_code as obj_code,
+        1 as obj_type,
+        h.date as statistic_date,
+        'DAY' as time_dimension,
+        ROUND(SUM(COALESCE(h.water_quantity, 0)), 2) as total_water_quantity,
+        ROUND(SUM(COALESCE(h.use_water_cost, 0)), 2) as total_water_cost,
+        NOW() as create_time
+        FROM adm_water_meter_h h
+        INNER JOIN adm_meter_boundary_rel rel ON rel.meter_device = h.device_code AND rel.meter_cls = 70 AND rel.obj_type = 1
+        INNER JOIN adm_area a ON a.area_code = rel.boundary_obj
+        WHERE h.device_code IN
+        <foreach collection="meterDevices" item="device" open="(" close=")" separator=",">
+            #{device}
+        </foreach>
+        <if test="queryMeter.startRecTime != null and queryMeter.startRecTime != ''">
+            AND h.date &gt;= DATE(#{queryMeter.startRecTime})
+        </if>
+        <if test="queryMeter.endRecTime != null and queryMeter.endRecTime != ''">
+            AND h.date &lt;= DATE(#{queryMeter.endRecTime})
+        </if>
+        AND h.date IS NOT NULL
+        GROUP BY a.area_code, a.area_name, h.date
+        ORDER BY h.date ${queryMeter.orderFlag}, a.area_code
+    </select>
+
+    <!-- 根据设备代码列表查询区域月用水统计 -->
+    <select id="selectAreaMonthlyWaterConsumptionByDevices" resultMap="WaterConsumptionResult">
+        SELECT
+        a.area_code,
+        a.area_name as obj_name,
+        a.area_code as obj_code,
+        1 as obj_type,
+        DATE(CONCAT(DATE_FORMAT(h.date, '%Y-%m'), '-01')) as statistic_date,
+        DATE_FORMAT(h.date, '%Y-%m') as statistic_month,
+        'MONTH' as time_dimension,
+        ROUND(SUM(COALESCE(h.water_quantity, 0)), 2) as total_water_quantity,
+        ROUND(SUM(COALESCE(h.use_water_cost, 0)), 2) as total_water_cost,
+        NOW() as create_time
+        FROM adm_water_meter_h h
+        INNER JOIN adm_meter_boundary_rel rel ON rel.meter_device = h.device_code AND rel.meter_cls = 70 AND rel.obj_type = 1
+        INNER JOIN adm_area a ON a.area_code = rel.boundary_obj
+        WHERE h.device_code IN
+        <foreach collection="meterDevices" item="device" open="(" close=")" separator=",">
+            #{device}
+        </foreach>
+        <if test="queryMeter.startRecTime != null and queryMeter.startRecTime != ''">
+            AND h.date &gt;= DATE(#{queryMeter.startRecTime})
+        </if>
+        <if test="queryMeter.endRecTime != null and queryMeter.endRecTime != ''">
+            AND h.date &lt;= DATE(#{queryMeter.endRecTime})
+        </if>
+        AND h.date IS NOT NULL
+        GROUP BY a.area_code, a.area_name, DATE_FORMAT(h.date, '%Y-%m')
+        ORDER BY DATE_FORMAT(h.date, '%Y-%m') ${queryMeter.orderFlag}, a.area_code
+    </select>
+
+    <!-- 根据设备代码列表查询区域年用水统计 -->
+    <select id="selectAreaYearlyWaterConsumptionByDevices" resultMap="WaterConsumptionResult">
+        SELECT
+        a.area_code,
+        a.area_name as obj_name,
+        a.area_code as obj_code,
+        1 as obj_type,
+        DATE(CONCAT(YEAR(h.date), '-01-01')) as statistic_date,
+        YEAR(h.date) as statistic_year,
+        'YEAR' as time_dimension,
+        ROUND(SUM(COALESCE(h.water_quantity, 0)), 2) as total_water_quantity,
+        ROUND(SUM(COALESCE(h.use_water_cost, 0)), 2) as total_water_cost,
+        NOW() as create_time
+        FROM adm_water_meter_h h
+        INNER JOIN adm_meter_boundary_rel rel ON rel.meter_device = h.device_code AND rel.meter_cls = 70 AND rel.obj_type = 1
+        INNER JOIN adm_area a ON a.area_code = rel.boundary_obj
+        WHERE h.device_code IN
+        <foreach collection="meterDevices" item="device" open="(" close=")" separator=",">
+            #{device}
+        </foreach>
+        <if test="queryMeter.startRecTime != null and queryMeter.startRecTime != ''">
+            AND h.date &gt;= DATE(#{queryMeter.startRecTime})
+        </if>
+        <if test="queryMeter.endRecTime != null and queryMeter.endRecTime != ''">
+            AND h.date &lt;= DATE(#{queryMeter.endRecTime})
+        </if>
+        AND h.date IS NOT NULL
+        GROUP BY a.area_code, a.area_name, YEAR(h.date)
+        ORDER BY YEAR(h.date) ${queryMeter.orderFlag}, a.area_code
+    </select>
+
+    <!-- 根据设备代码列表查询区域用水汇总 -->
+    <select id="selectAreaWaterConsumptionSummaryByDevices" resultMap="WaterConsumptionResult">
+        SELECT
+        'TOTAL' as area_code,
+        '总计' as obj_name,
+        'TOTAL' as obj_code,
+        1 as obj_type,
+        'SUMMARY' as time_dimension,
+        ROUND(SUM(COALESCE(h.water_quantity, 0)), 2) as total_water_quantity,
+        ROUND(SUM(COALESCE(h.use_water_cost, 0)), 2) as total_water_cost
+        FROM adm_water_meter_h h
+        WHERE h.device_code IN
+        <foreach collection="meterDevices" item="device" open="(" close=")" separator=",">
+            #{device}
+        </foreach>
+        <if test="queryMeter.startRecTime != null and queryMeter.startRecTime != ''">
+            AND h.date &gt;= DATE(#{queryMeter.startRecTime})
+        </if>
+        <if test="queryMeter.endRecTime != null and queryMeter.endRecTime != ''">
+            AND h.date &lt;= DATE(#{queryMeter.endRecTime})
+        </if>
+        AND h.date IS NOT NULL
+    </select>
+
+    <!-- ==================== 设施用水统计查询 ==================== -->
+
+    <!-- 查询设施日用水统计 -->
+    <select id="selectFacsDailyWaterConsumption" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="WaterConsumptionResult">
+        SELECT
+        f.ref_area as area_code,
+        f.facs_name as obj_name,
+        f.facs_code as obj_code,
+        2 as obj_type,
+        h.date as statistic_date,
+        'DAY' as time_dimension,
+        ROUND(SUM(COALESCE(h.water_quantity, 0)), 2) as total_water_quantity,
+        ROUND(SUM(COALESCE(h.use_water_cost, 0)), 2) as total_water_cost,
+        NOW() as create_time
+        FROM adm_ems_facs f
+        LEFT JOIN adm_meter_boundary_rel rel ON rel.obj_type = 2 AND rel.boundary_obj = f.facs_code
+        LEFT JOIN adm_water_meter_h h ON h.device_code = rel.meter_device AND rel.meter_cls = 70
+        <where>
+            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
+                AND f.ref_area = #{areaCode}
+            </if>
+            <if test="objCode != null and objCode != '' and objCode != '-1'">
+                AND f.facs_code = #{objCode}
+            </if>
+            <if test="facsCategory != null and facsCategory != ''">
+                AND f.facs_category = #{facsCategory}
+            </if>
+            <if test="startRecTime != null and startRecTime != ''">
+                AND h.date &gt;= DATE(#{startRecTime})
+            </if>
+            <if test="endRecTime != null and endRecTime != ''">
+                AND h.date &lt;= DATE(#{endRecTime})
+            </if>
+            AND h.date IS NOT NULL
+            AND f.enable = 1
+        </where>
+        GROUP BY f.facs_code, f.facs_name, f.ref_area, h.date
+        ORDER BY h.date ${orderFlag}, f.facs_code
+    </select>
+
+    <!-- 查询设施月用水统计 -->
+    <select id="selectFacsMonthlyWaterConsumption" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="WaterConsumptionResult">
+        SELECT
+        f.ref_area as area_code,
+        f.facs_name as obj_name,
+        f.facs_code as obj_code,
+        2 as obj_type,
+        DATE(CONCAT(DATE_FORMAT(h.date, '%Y-%m'), '-01')) as statistic_date,
+        DATE_FORMAT(h.date, '%Y-%m') as statistic_month,
+        'MONTH' as time_dimension,
+        ROUND(SUM(COALESCE(h.water_quantity, 0)), 2) as total_water_quantity,
+        ROUND(SUM(COALESCE(h.use_water_cost, 0)), 2) as total_water_cost,
+        NOW() as create_time
+        FROM adm_ems_facs f
+        LEFT JOIN adm_meter_boundary_rel rel ON rel.obj_type = 2 AND rel.boundary_obj = f.facs_code
+        LEFT JOIN adm_water_meter_h h ON h.device_code = rel.meter_device AND rel.meter_cls = 70
+        <where>
+            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
+                AND f.ref_area = #{areaCode}
+            </if>
+            <if test="objCode != null and objCode != '' and objCode != '-1'">
+                AND f.facs_code = #{objCode}
+            </if>
+            <if test="facsCategory != null and facsCategory != ''">
+                AND f.facs_category = #{facsCategory}
+            </if>
+            <if test="startRecTime != null and startRecTime != ''">
+                AND h.date &gt;= DATE(#{startRecTime})
+            </if>
+            <if test="endRecTime != null and endRecTime != ''">
+                AND h.date &lt;= DATE(#{endRecTime})
+            </if>
+            AND h.date IS NOT NULL
+            AND f.enable = 1
+        </where>
+        GROUP BY f.facs_code, f.facs_name, f.ref_area, DATE_FORMAT(h.date, '%Y-%m')
+        ORDER BY DATE_FORMAT(h.date, '%Y-%m') ${orderFlag}, f.facs_code
+    </select>
+
+    <!-- 查询设施年用水统计 -->
+    <select id="selectFacsYearlyWaterConsumption" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="WaterConsumptionResult">
+        SELECT
+        f.ref_area as area_code,
+        f.facs_name as obj_name,
+        f.facs_code as obj_code,
+        2 as obj_type,
+        DATE(CONCAT(YEAR(h.date), '-01-01')) as statistic_date,
+        YEAR(h.date) as statistic_year,
+        'YEAR' as time_dimension,
+        ROUND(SUM(COALESCE(h.water_quantity, 0)), 2) as total_water_quantity,
+        ROUND(SUM(COALESCE(h.use_water_cost, 0)), 2) as total_water_cost,
+        NOW() as create_time
+        FROM adm_ems_facs f
+        LEFT JOIN adm_meter_boundary_rel rel ON rel.obj_type = 2 AND rel.boundary_obj = f.facs_code
+        LEFT JOIN adm_water_meter_h h ON h.device_code = rel.meter_device AND rel.meter_cls = 70
+        <where>
+            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
+                AND f.ref_area = #{areaCode}
+            </if>
+            <if test="objCode != null and objCode != '' and objCode != '-1'">
+                AND f.facs_code = #{objCode}
+            </if>
+            <if test="facsCategory != null and facsCategory != ''">
+                AND f.facs_category = #{facsCategory}
+            </if>
+            <if test="startRecTime != null and startRecTime != ''">
+                AND h.date &gt;= DATE(#{startRecTime})
+            </if>
+            <if test="endRecTime != null and endRecTime != ''">
+                AND h.date &lt;= DATE(#{endRecTime})
+            </if>
+            AND h.date IS NOT NULL
+            AND f.enable = 1
+        </where>
+        GROUP BY f.facs_code, f.facs_name, f.ref_area, YEAR(h.date)
+        ORDER BY YEAR(h.date) ${orderFlag}, f.facs_code
+    </select>
+
+    <!-- 查询设施用水统计汇总 -->
+    <select id="selectFacsWaterConsumptionSummary" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="WaterConsumptionResult">
+        SELECT
+        COALESCE(#{areaCode}, '0') as area_code,
+        '总计' as obj_name,
+        'TOTAL' as obj_code,
+        2 as obj_type,
+        'SUMMARY' as time_dimension,
+        ROUND(SUM(COALESCE(h.water_quantity, 0)), 2) as total_water_quantity,
+        ROUND(SUM(COALESCE(h.use_water_cost, 0)), 2) as total_water_cost
+        FROM adm_ems_facs f
+        LEFT JOIN adm_meter_boundary_rel rel ON rel.obj_type = 2 AND rel.boundary_obj = f.facs_code
+        LEFT JOIN adm_water_meter_h h ON h.device_code = rel.meter_device AND rel.meter_cls = 70
+        <where>
+            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
+                AND f.ref_area = #{areaCode}
+            </if>
+            <if test="facsCategory != null and facsCategory != ''">
+                AND f.facs_category = #{facsCategory}
+            </if>
+            <if test="objCode != null and objCode != '' and objCode != '-1'">
+                AND f.facs_code = #{objCode}
+            </if>
+            <if test="startRecTime != null and startRecTime != ''">
+                AND h.date &gt;= DATE(#{startRecTime})
+            </if>
+            <if test="endRecTime != null and endRecTime != ''">
+                AND h.date &lt;= DATE(#{endRecTime})
+            </if>
+            AND h.date IS NOT NULL
+            AND f.enable = 1
+        </where>
+    </select>
+</mapper>