learshaw 3 месяцев назад
Родитель
Сommit
346fc3f80a
23 измененных файлов с 1282 добавлено и 1703 удалено
  1. 0 93
      ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/ElecLoadIndexController.java
  2. 0 90
      ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/ElecMeterHController.java
  3. 196 0
      ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/EnergyConsumptionController.java
  4. 0 373
      ems/ems-core/src/main/java/com/ruoyi/ems/domain/ElecLoadIndex.java
  5. 43 3
      ems/ems-core/src/main/java/com/ruoyi/ems/mapper/ElecConsumptionMapper.java
  6. 0 93
      ems/ems-core/src/main/java/com/ruoyi/ems/mapper/ElecLoadIndex15minMapper.java
  7. 0 16
      ems/ems-core/src/main/java/com/ruoyi/ems/mapper/ElecMeterHMapper.java
  8. 17 0
      ems/ems-core/src/main/java/com/ruoyi/ems/mapper/WaterConsumptionMapper.java
  9. 1 23
      ems/ems-core/src/main/java/com/ruoyi/ems/service/IBoundaryObjService.java
  10. 55 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/IElecConsumptionService.java
  11. 0 56
      ems/ems-core/src/main/java/com/ruoyi/ems/service/IElecLoadIndexService.java
  12. 0 16
      ems/ems-core/src/main/java/com/ruoyi/ems/service/IElecMeterHService.java
  13. 24 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/IWaterConsumptionService.java
  14. 0 174
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/BoundaryObjServiceImpl.java
  15. 420 229
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/ElecConsumptionServiceImpl.java
  16. 0 93
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/ElecLoadIndexServiceImpl.java
  17. 0 23
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/ElecMeterHServiceImpl.java
  18. 197 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/WaterConsumptionServiceImpl.java
  19. 198 4
      ems/ems-core/src/main/resources/mapper/ems/ElecConsumptionMapper.xml
  20. 0 336
      ems/ems-core/src/main/resources/mapper/ems/ElecLoadIndex15minMapper.xml
  21. 0 47
      ems/ems-core/src/main/resources/mapper/ems/ElecMeterHMapper.xml
  22. 131 0
      ems/ems-core/src/main/resources/mapper/ems/WaterConsumptionMapper.xml
  23. 0 34
      ems/sql/ems_server.sql

+ 0 - 93
ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/ElecLoadIndexController.java

@@ -1,93 +0,0 @@
-package com.ruoyi.ems.controller;
-
-import com.huashe.common.domain.AjaxResult;
-import com.ruoyi.common.core.utils.poi.ExcelUtil;
-import com.ruoyi.common.core.web.controller.BaseController;
-import com.ruoyi.common.core.web.page.TableDataInfo;
-import com.ruoyi.common.log.annotation.Log;
-import com.ruoyi.common.log.enums.BusinessType;
-import com.ruoyi.ems.domain.ElecLoadIndex;
-import com.ruoyi.ems.model.QueryMeter;
-import com.ruoyi.ems.service.IElecLoadIndexService;
-import io.swagger.annotations.Api;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.servlet.http.HttpServletResponse;
-import java.util.List;
-
-/**
- * 电力负荷设施指标Controller
- *
- * @author ruoyi
- * @date 2024-08-09
- */
-@RestController
-@RequestMapping("/object/loadIndex")
-@Api(value = "ElecLoadIndexController", description = "电力负荷指标数据接口")
-public class ElecLoadIndexController extends BaseController {
-    @Autowired
-    private IElecLoadIndexService indexService;
-
-    /**
-     * 查询电力负荷设施指标列表
-     */
-    @GetMapping("/min/15/list")
-    public TableDataInfo min15List(QueryMeter param) {
-        startPage();
-        List<ElecLoadIndex> list = indexService.selectMin15IndexList(param);
-        return getDataTable(list);
-    }
-
-    @GetMapping("/min/15/getMaxLoad")
-    public AjaxResult getMin15MaxLoad(QueryMeter param) {
-        ElecLoadIndex maxLoad = indexService.selectMin15IndexMaxLoad(param);
-        return success(maxLoad);
-    }
-
-    @GetMapping("/day/getMaxLoad")
-    public TableDataInfo getMaxLoad(QueryMeter param) {
-        startPage();
-        List<ElecLoadIndex> list = indexService.selectDayIndexMaxLoad(param);
-        return getDataTable(list);
-    }
-
-    /**
-     * 查询最新电力负荷设施指标
-     *
-     * @param areaCode 区域代码
-     * @param objType  对象类型
-     * @param objCode  对象代码
-     * @return 电力负荷设施指标
-     */
-    @GetMapping("/getNewIndex")
-    public AjaxResult getNewIndex(@RequestParam(name = "areaCode") String areaCode,
-        @RequestParam(name = "objType") String objType, @RequestParam(name = "objCode") String objCode) {
-        return success(indexService.selectNewIndex(areaCode, objType, objCode));
-    }
-
-    /**
-     * 导出电力负荷设施指标列表
-     */
-    @Log(title = "电力负荷设施指标", businessType = BusinessType.EXPORT)
-    @PostMapping("/export")
-    public void export(HttpServletResponse response, QueryMeter param) {
-        List<ElecLoadIndex> list = indexService.selectMin15IndexList(param);
-        ExcelUtil<ElecLoadIndex> util = new ExcelUtil<ElecLoadIndex>(ElecLoadIndex.class);
-        util.exportExcel(response, list, "电力负荷设施指标数据");
-    }
-
-    /**
-     * 新增电力负荷设施指标
-     */
-    @Log(title = "电力负荷设施指标", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody ElecLoadIndex index) {
-        return toAjax(indexService.insertMin15Index(index));
-    }
-}

+ 0 - 90
ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/ElecMeterHController.java

@@ -1,19 +1,13 @@
 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.PageDomain;
-import com.ruoyi.common.core.web.page.TableDataInfo;
-import com.ruoyi.common.core.web.page.TableSupport;
 import com.ruoyi.common.log.annotation.Log;
 import com.ruoyi.common.log.enums.BusinessType;
 import com.ruoyi.common.security.annotation.RequiresPermissions;
 import com.ruoyi.ems.domain.ElecMeterH;
 import com.ruoyi.ems.domain.EnergyMeter;
 import com.ruoyi.ems.model.QueryMeter;
-import com.ruoyi.ems.service.IBoundaryObjService;
 import com.ruoyi.ems.service.IElecMeterHService;
 import io.swagger.annotations.Api;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -27,9 +21,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
-import javax.servlet.http.HttpServletResponse;
-import java.util.List;
-
 /**
  * 用电计量-小时Controller
  *
@@ -43,87 +34,6 @@ public class ElecMeterHController extends BaseController {
     @Autowired
     private IElecMeterHService elecMeterHService;
 
-    @Autowired
-    private IBoundaryObjService boundaryObjService;
-
-    /**
-     * 查询设施用能统计数据
-     *
-     * @param queryMeter 查询条件
-     * @return
-     */
-    @GetMapping("/hour/listFacsMeterTotal")
-    public AjaxResult listFacsMeterTotal(QueryMeter queryMeter) {
-        queryMeter.setMeterCls(45);
-        List<EnergyMeter> list = boundaryObjService.getMeterStaByFacsCategory(queryMeter);
-        return success(list);
-    }
-
-    /**
-     * 查询设施用能统计数据
-     *
-     * @param queryMeter 查询条件
-     * @return
-     */
-    @GetMapping("/hour/listFacsMeter")
-    public TableDataInfo listFacsMeter(QueryMeter queryMeter) {
-        PageDomain pageDomain = TableSupport.buildPageRequest();
-        Integer pageNum = pageDomain.getPageNum();
-        Integer pageSize = pageDomain.getPageSize();
-        queryMeter.setMeterCls(45);
-        List<ElecMeterH> list = boundaryObjService.getMeterByFacsCategory(queryMeter);
-        int total = list.size();
-        list = ListUtils.subList(list, (pageNum - 1) * pageSize, pageNum * pageSize -1);
-
-        TableDataInfo rspData = new TableDataInfo();
-        rspData.setCode(200);
-        rspData.setRows(list);
-        rspData.setMsg("查询成功");
-        rspData.setTotal(total);
-
-        return rspData;
-    }
-
-    @Log(title = "设施用能-小时", businessType = BusinessType.EXPORT)
-    @PostMapping("/exportFacsMeter")
-    public void exportFacsMeter(HttpServletResponse response, QueryMeter queryMeter) {
-        List<ElecMeterH> list = boundaryObjService.getMeterByFacsCategory(queryMeter);
-        ExcelUtil<ElecMeterH> util = new ExcelUtil<>(ElecMeterH.class);
-        util.exportExcel(response, list, "设施用能-小时数据");
-    }
-
-    /**
-     * 查询区域用能统计数据
-     *
-     * @param queryMeter 查询条件
-     * @return
-     */
-    @GetMapping("/hour/listAreaMeter")
-    public TableDataInfo listAreaMeter(QueryMeter queryMeter) {
-        PageDomain pageDomain = TableSupport.buildPageRequest();
-        Integer pageNum = pageDomain.getPageNum();
-        Integer pageSize = pageDomain.getPageSize();
-        List<ElecMeterH> list = boundaryObjService.getMeterByArea(queryMeter);
-        int total = list.size();
-        list = ListUtils.subList(list, (pageNum - 1) * pageSize, pageNum * pageSize -1);
-
-        TableDataInfo rspData = new TableDataInfo();
-        rspData.setCode(200);
-        rspData.setRows(list);
-        rspData.setMsg("查询成功");
-        rspData.setTotal(total);
-
-        return rspData;
-    }
-
-    @Log(title = "区域用能-小时", businessType = BusinessType.EXPORT)
-    @PostMapping("/exportAreaMeter")
-    public void exportAreaMeter(HttpServletResponse response, QueryMeter queryMeter) {
-        List<ElecMeterH> list = boundaryObjService.getMeterByArea(queryMeter);
-        ExcelUtil<ElecMeterH> util = new ExcelUtil<>(ElecMeterH.class);
-        util.exportExcel(response, list, "区域用能-小时数据");
-    }
-
     /**
      * 计算时间范围内日平均
      *

+ 196 - 0
ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/EnergyConsumptionController.java

@@ -4,11 +4,14 @@ 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.PageDomain;
 import com.ruoyi.common.core.web.page.TableDataInfo;
+import com.ruoyi.common.core.web.page.TableSupport;
 import com.ruoyi.common.log.annotation.Log;
 import com.ruoyi.common.log.enums.BusinessType;
 import com.ruoyi.common.security.annotation.RequiresPermissions;
 import com.ruoyi.ems.domain.ElecMeterH;
+import com.ruoyi.ems.domain.EnergyMeter;
 import com.ruoyi.ems.domain.WaterMeterH;
 import com.ruoyi.ems.model.ElecConsumptionExportVO;
 import com.ruoyi.ems.model.ElecConsumptionVO;
@@ -26,6 +29,7 @@ import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.servlet.http.HttpServletResponse;
@@ -161,6 +165,69 @@ public class EnergyConsumptionController extends BaseController {
         util.exportExcel(response, exportList, fileName);
     }
 
+    /**
+     * 查询区域用能统计数据
+     *
+     * @param queryMeter 查询条件
+     * @return
+     */
+    @GetMapping("/area/elec/hour/list")
+    public TableDataInfo getAreaElecHourMeter(QueryMeter queryMeter) {
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Integer pageNum = pageDomain.getPageNum();
+        Integer pageSize = pageDomain.getPageSize();
+        List<ElecMeterH> list = elecConsumptionService.getAreaElecHourMeter(queryMeter);
+        int total = list.size();
+        list = ListUtils.subList(list, (pageNum - 1) * pageSize, pageNum * pageSize - 1);
+
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(200);
+        rspData.setRows(list);
+        rspData.setMsg("查询成功");
+        rspData.setTotal(total);
+
+        return rspData;
+    }
+
+    /**
+     * 查询区域小时用电明细(按时间序列)
+     */
+    @GetMapping("/area/elec/hour/byTimeIndex")
+    @ApiOperation("查询按时间序列的区域用电统计")
+    public AjaxResult getAreaElecByTimeIndex(QueryMeter queryMeter) {
+        if (StringUtils.isBlank(queryMeter.getOrderFlag())) {
+            queryMeter.setOrderFlag("asc");
+        }
+        List<ElecMeterH> list = elecConsumptionService.getAreaElecHourMeter(queryMeter);
+        return success(list);
+    }
+
+    /**
+     * 计算时间范围内日平均用电
+     *
+     * @param queryMeter 支持areaCode、deviceCode、date范围筛选
+     * @return EnergyMeter
+     */
+    @GetMapping("/elec/day/avg")
+    @ApiOperation("计算时间范围内日平均用电")
+    public AjaxResult getElecDayAvg(@ApiParam("查询参数") QueryMeter queryMeter) {
+        EnergyMeter result = elecConsumptionService.selectElecDayAvg(queryMeter);
+        return success(result);
+    }
+
+    /**
+     * 按设备类型查询日用电
+     *
+     * @param queryMeter 查询条件(startRecTime、areaCode)
+     * @return 设备用电列表
+     */
+    @GetMapping("/elec/sum/device/day")
+    @ApiOperation("按设备类型查询日用电")
+    public AjaxResult qryDeviceElecByDay(QueryMeter queryMeter) {
+        List<EnergyMeter> result = elecConsumptionService.qryDeviceElecByDay(queryMeter);
+        return success(result);
+    }
+
     // ==================== 设施用电统计 ====================
 
     /**
@@ -232,6 +299,44 @@ public class EnergyConsumptionController extends BaseController {
         util.exportExcel(response, exportList, fileName);
     }
 
+    /**
+     * 查询设施用能统计数据
+     *
+     * @param queryMeter 查询条件
+     * @return
+     */
+    @GetMapping("/facs/elec/listFacsMeterHourSta")
+    public AjaxResult listFacsMeterHourSta(QueryMeter queryMeter) {
+        queryMeter.setMeterCls(45);
+        List<ElecConsumptionVO> list = elecConsumptionService.getFacsMeterHourSta(queryMeter);
+        return success(list);
+    }
+
+    /**
+     * 查询设施用能统计数据
+     *
+     * @param queryMeter 查询条件
+     * @return
+     */
+    @GetMapping("/facs/elec/hour/list")
+    public TableDataInfo getFacsElecHourMeter(QueryMeter queryMeter) {
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Integer pageNum = pageDomain.getPageNum();
+        Integer pageSize = pageDomain.getPageSize();
+        queryMeter.setMeterCls(45);
+        List<ElecMeterH> list = elecConsumptionService.getFacsElecHourMeter(queryMeter);
+        int total = list.size();
+        list = ListUtils.subList(list, (pageNum - 1) * pageSize, pageNum * pageSize - 1);
+
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(200);
+        rspData.setRows(list);
+        rspData.setMsg("查询成功");
+        rspData.setTotal(total);
+
+        return rspData;
+    }
+
     // ==================== 水表计抄表查询 ====================
 
     /**
@@ -275,6 +380,77 @@ public class EnergyConsumptionController extends BaseController {
     // ==================== 区域用水统计 ====================
 
     /**
+     * 查询区域小时用水明细
+     */
+    @GetMapping("/area/water/hour/list")
+    @ApiOperation("查询区域小时用水明细")
+    public TableDataInfo getAreaWaterHourMeter(QueryMeter queryMeter) {
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Integer pageNum = pageDomain.getPageNum();
+        Integer pageSize = pageDomain.getPageSize();
+
+        List<WaterMeterH> list = waterConsumptionService.getAreaWaterHourMeter(queryMeter);
+        int total = list.size();
+        list = ListUtils.subList(list, (pageNum - 1) * pageSize, pageNum * pageSize - 1);
+
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(200);
+        rspData.setRows(list);
+        rspData.setMsg("查询成功");
+        rspData.setTotal(total);
+
+        return rspData;
+    }
+
+    /**
+     * 查询区域小时用水明细(按时间序列)
+     */
+    @GetMapping("/area/water/hour/byTimeIndex")
+    @ApiOperation("查询按时间序列的区域用水统计")
+    public AjaxResult getAreaWaterByTimeIndex(QueryMeter queryMeter) {
+        if (StringUtils.isBlank(queryMeter.getOrderFlag())) {
+            queryMeter.setOrderFlag("asc");
+        }
+        List<WaterMeterH> list = waterConsumptionService.getAreaWaterHourMeter(queryMeter);
+        return success(list);
+    }
+
+    /**
+     * 查询设施小时用水明细
+     */
+    @GetMapping("/facs/water/hour/list")
+    @ApiOperation("查询设施小时用水明细")
+    public TableDataInfo getFacsWaterHourMeter(QueryMeter queryMeter) {
+        PageDomain pageDomain = TableSupport.buildPageRequest();
+        Integer pageNum = pageDomain.getPageNum();
+        Integer pageSize = pageDomain.getPageSize();
+
+        queryMeter.setMeterCls(70);
+        List<WaterMeterH> list = waterConsumptionService.getFacsWaterHourMeter(queryMeter);
+        int total = list.size();
+        list = ListUtils.subList(list, (pageNum - 1) * pageSize, pageNum * pageSize - 1);
+
+        TableDataInfo rspData = new TableDataInfo();
+        rspData.setCode(200);
+        rspData.setRows(list);
+        rspData.setMsg("查询成功");
+        rspData.setTotal(total);
+
+        return rspData;
+    }
+
+    /**
+     * 查询设施小时用水汇总统计
+     */
+    @GetMapping("/facs/water/listFacsMeterHourSta")
+    @ApiOperation("查询设施小时用水汇总")
+    public AjaxResult listFacsWaterMeterHourSta(QueryMeter queryMeter) {
+        queryMeter.setMeterCls(70);
+        List<WaterConsumptionVO> list = waterConsumptionService.getFacsWaterHourSta(queryMeter);
+        return success(list);
+    }
+
+    /**
      * 查询区域用水统计列表
      */
     @RequiresPermissions("ems:consumption:list")
@@ -334,6 +510,26 @@ public class EnergyConsumptionController extends BaseController {
         util.exportExcel(response, exportList, fileName);
     }
 
+    /**
+     * 查询按时间序列(小时)的用水统计
+     */
+    @GetMapping("/area/water/hour/byTimeIndex")
+    @ApiOperation("查询按时间序列的用水统计")
+    public AjaxResult getAreaWaterByTimeIndex(
+        @RequestParam(name = "startRecTime") String startRecTime,
+        @RequestParam(name = "endRecTime", required = false) String endRecTime,
+        @RequestParam(name = "areaCode", required = false) String areaCode) {
+
+        QueryMeter queryMeter = new QueryMeter();
+        queryMeter.setStartRecTime(startRecTime);
+        queryMeter.setEndRecTime(endRecTime != null ? endRecTime : startRecTime + " 23:59:59");
+        queryMeter.setAreaCode(areaCode);
+        queryMeter.setObjCode(areaCode);
+
+        List<WaterMeterH> list = waterConsumptionService.getAreaWaterHourMeter(queryMeter);
+        return success(list);
+    }
+
     // ==================== 设施用水统计 ====================
 
     /**

+ 0 - 373
ems/ems-core/src/main/java/com/ruoyi/ems/domain/ElecLoadIndex.java

@@ -1,373 +0,0 @@
-package com.ruoyi.ems.domain;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.huashe.common.annotation.Excel;
-import com.huashe.common.domain.BaseEntity;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-
-import java.sql.Time;
-import java.util.Date;
-
-/**
- * 电力负荷设施指标对象 adm_ems_elec_load_index
- * 
- * @author ruoyi
- * @date 2024-09-27
- */
-public class ElecLoadIndex extends BaseEntity
-{
-    private static final long serialVersionUID = 1L;
-
-    /** 序号 */
-    private Long id;
-
-    /** 园区代码 */
-    private String areaCode;
-
-    /** 园区名称 */
-    @Excel(name = "园区名称")
-    private String areaName;
-
-    /** 园区简称 */
-    private String areaShortName;
-
-    /** 对象类型 */
-    @Excel(name = "对象类型")
-    private Long objType;
-
-    /** 对象编码 */
-    private String objCode;
-
-    @Excel(name = "对象名称")
-    private String objName;
-
-    /** 记录时间 */
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    @Excel(name = "记录时间", width = 30, dateFormat = "yyyy-MM-dd")
-    private Date recordTime;
-
-    /** 日期 yyyy-MM-dd */
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    @Excel(name = "日期", width = 30, dateFormat = "yyyy-MM-dd")
-    private Date date;
-
-    /** 时间 HH:mm:ss */
-    @JsonFormat(pattern = "HH:mm:ss")
-    @Excel(name = "时间", width = 30, dateFormat = "yyyy-MM-dd")
-    private Time time;
-
-    /** 事件序列 */
-    @Excel(name = "事件序列")
-    private Integer timeIndex;
-
-    /** 电压 单位:V(伏) */
-    @Excel(name = "A相电压")
-    private Double ua;
-
-    /** 电压 单位:V(伏) */
-    @Excel(name = "B相电压")
-    private Double ub;
-
-    /** 电压 单位:V(伏) */
-    @Excel(name = "C相电压")
-    private Double uc;
-
-    /** 电流 单位:A(伏) */
-    @Excel(name = "A相电流")
-    private Double la;
-
-    /** 电流 单位:A(伏) */
-    @Excel(name = "B相电流")
-    private Double lb;
-
-    /** 电流 单位:A(伏) */
-    @Excel(name = "C相电流")
-    private Double lc;
-
-    /** 有功总功率 */
-    @Excel(name = "有功总功率")
-    private Double p;
-
-    /** A相有功功率 */
-    @Excel(name = "A相有功功率")
-    private Double pa;
-
-    /** B相有功功率 */
-    @Excel(name = "B相有功功率")
-    private Double pb;
-
-    /** C相有功功率 */
-    @Excel(name = "C相有功功率")
-    private Double pc;
-
-    /** 无功总功率 */
-    @Excel(name = "无功总功率")
-    private Double q;
-
-    /** A相无功总功率 */
-    @Excel(name = "A相无功总功率")
-    private Double qa;
-
-    /** B相无功总功率 */
-    @Excel(name = "B相无功总功率")
-    private Double qb;
-
-    /** C相无功总功率 */
-    @Excel(name = "C相无功总功率")
-    private Double qc;
-
-    /** 视在功率 */
-    @Excel(name = "视在功率")
-    private Double s;
-
-    /** 功率因素 */
-    @Excel(name = "功率因素")
-    private Double pf;
-
-    public Long getId() {
-        return id;
-    }
-
-    public void setId(Long id) {
-        this.id = id;
-    }
-
-    public String getAreaCode() {
-        return areaCode;
-    }
-
-    public void setAreaCode(String areaCode) {
-        this.areaCode = areaCode;
-    }
-
-    public Long getObjType() {
-        return objType;
-    }
-
-    public void setObjType(Long objType) {
-        this.objType = objType;
-    }
-
-    public String getObjCode() {
-        return objCode;
-    }
-
-    public void setObjCode(String objCode) {
-        this.objCode = objCode;
-    }
-
-    public Date getRecordTime() {
-        return recordTime;
-    }
-
-    public void setRecordTime(Date recordTime) {
-        this.recordTime = recordTime;
-    }
-
-    public Date getDate() {
-        return date;
-    }
-
-    public void setDate(Date date) {
-        this.date = date;
-    }
-
-    public Time getTime() {
-        return time;
-    }
-
-    public void setTime(Time time) {
-        this.time = time;
-    }
-
-    public Integer getTimeIndex() {
-        return timeIndex;
-    }
-
-    public void setTimeIndex(Integer timeIndex) {
-        this.timeIndex = timeIndex;
-    }
-
-    public Double getUa() {
-        return ua;
-    }
-
-    public void setUa(Double ua) {
-        this.ua = ua;
-    }
-
-    public Double getUb() {
-        return ub;
-    }
-
-    public void setUb(Double ub) {
-        this.ub = ub;
-    }
-
-    public Double getUc() {
-        return uc;
-    }
-
-    public void setUc(Double uc) {
-        this.uc = uc;
-    }
-
-    public Double getLa() {
-        return la;
-    }
-
-    public void setLa(Double la) {
-        this.la = la;
-    }
-
-    public Double getLb() {
-        return lb;
-    }
-
-    public void setLb(Double lb) {
-        this.lb = lb;
-    }
-
-    public Double getLc() {
-        return lc;
-    }
-
-    public void setLc(Double lc) {
-        this.lc = lc;
-    }
-
-    public Double getP() {
-        return p;
-    }
-
-    public void setP(Double p) {
-        this.p = p;
-    }
-
-    public Double getPa() {
-        return pa;
-    }
-
-    public void setPa(Double pa) {
-        this.pa = pa;
-    }
-
-    public Double getPb() {
-        return pb;
-    }
-
-    public void setPb(Double pb) {
-        this.pb = pb;
-    }
-
-    public Double getPc() {
-        return pc;
-    }
-
-    public void setPc(Double pc) {
-        this.pc = pc;
-    }
-
-    public Double getQ() {
-        return q;
-    }
-
-    public void setQ(Double q) {
-        this.q = q;
-    }
-
-    public Double getQa() {
-        return qa;
-    }
-
-    public void setQa(Double qa) {
-        this.qa = qa;
-    }
-
-    public Double getQb() {
-        return qb;
-    }
-
-    public void setQb(Double qb) {
-        this.qb = qb;
-    }
-
-    public Double getQc() {
-        return qc;
-    }
-
-    public void setQc(Double qc) {
-        this.qc = qc;
-    }
-
-    public Double getS() {
-        return s;
-    }
-
-    public void setS(Double s) {
-        this.s = s;
-    }
-
-    public Double getPf() {
-        return pf;
-    }
-
-    public void setPf(Double pf) {
-        this.pf = pf;
-    }
-
-    public String getAreaName() {
-        return areaName;
-    }
-
-    public void setAreaName(String areaName) {
-        this.areaName = areaName;
-    }
-
-    public String getAreaShortName() {
-        return areaShortName;
-    }
-
-    public void setAreaShortName(String areaShortName) {
-        this.areaShortName = areaShortName;
-    }
-
-    public String getObjName() {
-        return objName;
-    }
-
-    public void setObjName(String objName) {
-        this.objName = objName;
-    }
-
-    @Override
-    public String toString() {
-        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
-            .append("id", getId())
-            .append("areaCode", getAreaCode())
-            .append("objType", getObjType())
-            .append("objCode", getObjCode())
-            .append("recordTime", getRecordTime())
-            .append("date", getDate())
-            .append("time", getTime())
-            .append("timeIndex", getTimeIndex())
-            .append("ua", getUa())
-            .append("ub", getUb())
-            .append("uc", getUc())
-            .append("la", getLa())
-            .append("lb", getLb())
-            .append("lc", getLc())
-            .append("p", getP())
-            .append("pa", getPa())
-            .append("pb", getPb())
-            .append("pc", getPc())
-            .append("q", getQ())
-            .append("qa", getQa())
-            .append("qb", getQb())
-            .append("qc", getQc())
-            .append("s", getS())
-            .append("pf", getPf())
-            .toString();
-    }
-}

+ 43 - 3
ems/ems-core/src/main/java/com/ruoyi/ems/mapper/ElecConsumptionMapper.java

@@ -1,6 +1,7 @@
 package com.ruoyi.ems.mapper;
 
 import com.ruoyi.ems.domain.ElecMeterH;
+import com.ruoyi.ems.domain.EnergyMeter;
 import com.ruoyi.ems.model.ElecConsumptionVO;
 import com.ruoyi.ems.model.QueryMeter;
 import org.apache.ibatis.annotations.Param;
@@ -10,10 +11,17 @@ import java.util.Set;
 
 /**
  * 用电统计Mapper接口
+ *
+ * 重构说明:
+ * 1. 新增小时粒度查询方法
+ * 2. 统一使用 ElecConsumptionVO 和 ElecMeterH,不依赖 EnergyMeter
  */
 public interface ElecConsumptionMapper {
+
+    // ==================== 查询分时类型 ====================
+
     /**
-     * 根据设备代码列表查询区域日用电统计
+     * 查询支持的分时电价类型
      */
     List<String> selectElecHourSupportTypes(@Param("queryMeter") QueryMeter queryMeter,
         @Param("meterDevices") Set<String> meterDevices);
@@ -27,8 +35,6 @@ public interface ElecConsumptionMapper {
 
     /**
      * 计量设备抄表数据统计
-     * @param queryMeter 查询条件
-     * @return 统计电量信息
      */
     ElecConsumptionVO selectMDevElecConsumptionSummary(QueryMeter queryMeter);
 
@@ -79,4 +85,38 @@ public interface ElecConsumptionMapper {
      * 查询设施用电统计汇总
      */
     ElecConsumptionVO selectFacsElecConsumptionSummary(QueryMeter queryMeter);
+
+    // ==================== 小时粒度查询方法 ====================
+
+    /**
+     * 根据设备代码列表查询区域小时用电明细
+     * 替代原: IElecMeterHService.selectByMeterDevs (区域场景)
+     */
+    List<ElecMeterH> selectAreaHourlyElecConsumptionByDevices(@Param("queryMeter") QueryMeter queryMeter,
+        @Param("meterDevices") Set<String> meterDevices);
+
+    /**
+     * 查询设施小时用电明细
+     * 替代原: IElecMeterHService.selectByMeterDevs (设施场景)
+     */
+    List<ElecMeterH> selectFacsHourlyElecConsumption(QueryMeter queryMeter);
+
+    /**
+     * 查询设施小时用电汇总统计
+     * 替代原: IElecMeterHService.staByMeterDev
+     * 返回 ElecConsumptionVO 统一对象
+     */
+    List<ElecConsumptionVO> selectFacsHourlyElecSummary(QueryMeter queryMeter);
+
+    /**
+     * 查询日平均用电
+     * 兼容老接口: selectElecDayAvg
+     */
+    EnergyMeter selectElecDayAvg(QueryMeter queryMeter);
+
+    /**
+     * 按设备类型查询日用电
+     * 兼容老接口: qryDeviceDay
+     */
+    List<EnergyMeter> selectDeviceElecByDay(QueryMeter queryMeter);
 }

+ 0 - 93
ems/ems-core/src/main/java/com/ruoyi/ems/mapper/ElecLoadIndex15minMapper.java

@@ -1,93 +0,0 @@
-package com.ruoyi.ems.mapper;
-
-import com.ruoyi.ems.domain.ElecLoadIndex;
-import com.ruoyi.ems.model.QueryMeter;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-/**
- * 电力负荷设施指标Mapper接口
- *
- * @author ruoyi
- * @date 2024-09-27
- */
-public interface ElecLoadIndex15minMapper {
-    /**
-     * 查询电力负荷设施指标
-     *
-     * @param id 电力负荷设施指标主键
-     * @return 电力负荷设施指标
-     */
-    ElecLoadIndex selectIndexById(Long id);
-
-    /**
-     * 查询最新电力负荷设施指标
-     *
-     * @param areaCode 区域代码
-     * @param objType  对象类型
-     * @param objCode  对象代码
-     * @return 电力负荷设施指标
-     */
-    ElecLoadIndex selectNewIndex(@Param("areaCode") String areaCode, @Param("objType") String objType,
-                                 @Param("objCode") String objCode);
-
-    /**
-     * 查询电力负荷设施指标列表
-     *
-     * @param queryMeter 查询条件
-     * @return 电力负荷设施指标集合
-     */
-    List<ElecLoadIndex> selectIndexList(QueryMeter queryMeter);
-
-
-    List<ElecLoadIndex> selectIndexDetailList(QueryMeter queryMeter);
-
-    /**
-     * 查询电力负荷设施指标(最大负荷)
-     *
-     * @param queryMeter 查询条件
-     * @return 电力负荷设施指标集合
-     */
-    ElecLoadIndex selectIndexMaxLoad(QueryMeter queryMeter);
-
-    /**
-     * 查询每日电力负荷设施指标(最大负荷)
-     *
-     * @param queryMeter 查询条件
-     * @return 电力负荷设施指标集合
-     */
-    List<ElecLoadIndex> selectDayIndexMaxLoad(QueryMeter queryMeter);
-
-    /**
-     * 新增电力负荷设施指标
-     *
-     * @param loadIndex 电力负荷设施指标
-     * @return 结果
-     */
-    int insertIndex(ElecLoadIndex loadIndex);
-
-    /**
-     * 修改电力负荷设施指标
-     *
-     * @param loadIndex 电力负荷设施指标
-     * @return 结果
-     */
-    int updateIndex(ElecLoadIndex loadIndex);
-
-    /**
-     * 删除电力负荷设施指标
-     *
-     * @param id 电力负荷设施指标主键
-     * @return 结果
-     */
-    int deleteIndexById(Long id);
-
-    /**
-     * 批量删除电力负荷设施指标
-     *
-     * @param ids 需要删除的数据主键集合
-     * @return 结果
-     */
-    int deleteIndexByIds(Long[] ids);
-}

+ 0 - 16
ems/ems-core/src/main/java/com/ruoyi/ems/mapper/ElecMeterHMapper.java

@@ -17,14 +17,6 @@ import java.util.List;
 public interface ElecMeterHMapper {
 
     /**
-     * 查询用电计量-小时列表
-     *
-     * @param queryMeter 查询计量条件
-     * @return 用电计量-小时集合
-     */
-    List<ElecMeterH> selectElecMeterByDevs(QueryMeter queryMeter);
-
-    /**
      * 查询用电计量-日汇总列表
      *
      * @param queryMeter 查询计量条件
@@ -41,14 +33,6 @@ public interface ElecMeterHMapper {
     ElecMeterH selectLatelyItem(@Param("deviceCode") String deviceCode);
 
     /**
-     * 查询用电计量-小时列表
-     *
-     * @param queryMeter 查询计量条件
-     * @return 用电计量-小时集合
-     */
-    EnergyMeter selectElecMeterSumByDev(QueryMeter queryMeter);
-
-    /**
      * 查询日用电平均
      *
      * @param queryMeter 查询计量条件

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

@@ -88,4 +88,21 @@ public interface WaterConsumptionMapper {
      * 查询设施用水统计汇总
      */
     WaterConsumptionVO selectFacsWaterConsumptionSummary(QueryMeter queryMeter);
+
+    /**
+     * 根据设备代码列表查询区域小时用水明细
+     */
+    List<WaterMeterH> selectAreaHourlyWaterConsumptionByDevices(
+        @Param("queryMeter") QueryMeter queryMeter,
+        @Param("meterDevices") Set<String> meterDevices);
+
+    /**
+     * 查询设施小时用水明细
+     */
+    List<WaterMeterH> selectFacsHourlyWaterConsumption(QueryMeter queryMeter);
+
+    /**
+     * 查询设施小时用水汇总统计
+     */
+    List<WaterConsumptionVO> selectFacsHourlyWaterSummary(QueryMeter queryMeter);
 }

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

@@ -36,22 +36,6 @@ public interface IBoundaryObjService {
     BoundaryObj getBoundaryByArea(String areaCode, Integer meterCls);
 
     /**
-     * 查询用电计量统计-根据边界设施分类
-     *
-     * @param queryMeter 查询条件
-     * @return 用电计量统计结果
-     */
-    List<EnergyMeter> getMeterStaByFacsCategory(QueryMeter queryMeter);
-
-    /**
-     * 查询用电计量列表-根据设施分类
-     *
-     * @param queryMeter 查询条件
-     * @return 用电计量结果
-     */
-    List<ElecMeterH> getMeterByFacsCategory(QueryMeter queryMeter);
-
-    /**
      * 查询用电计量-根据边界设施分类
      *
      * @param queryMeter 查询条件
@@ -59,11 +43,5 @@ public interface IBoundaryObjService {
      */
     List<ElecMeterH> getMeterStaByArea(QueryMeter queryMeter);
 
-    /**
-     * 查询用电计量-根据边界对象
-     *
-     * @param queryMeter 查询条件
-     * @return 用电计量结果
-     */
-    List<ElecMeterH> getMeterByArea(QueryMeter queryMeter);
+
 }

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

@@ -1,6 +1,7 @@
 package com.ruoyi.ems.service;
 
 import com.ruoyi.ems.domain.ElecMeterH;
+import com.ruoyi.ems.domain.EnergyMeter;
 import com.ruoyi.ems.model.ElecConsumptionExportVO;
 import com.ruoyi.ems.model.ElecConsumptionVO;
 import com.ruoyi.ems.model.QueryMeter;
@@ -9,8 +10,16 @@ import java.util.List;
 
 /**
  * 用电统计服务接口
+ *
+ * 重构说明:
+ * 1. 移除对 EnergyMeter 的依赖,统一使用 ElecConsumptionVO
+ * 2. 支持 hour/day/month/year 四种时间粒度
  */
 public interface IElecConsumptionService {
+
+    /**
+     * 查询用电小时计量类型列表
+     */
     List<String> getElecHourTypes(QueryMeter queryMeter);
 
     /**
@@ -57,4 +66,50 @@ public interface IElecConsumptionService {
      * 转换为用电导出VO列表
      */
     List<ElecConsumptionExportVO> convertToElecExportVOList(List<ElecConsumptionVO> originalList, String timeDimension);
+
+    // ==================== 小时粒度查询方法 ====================
+
+    /**
+     * 查询设施小时用电汇总统计
+     *
+     * 重构说明:返回类型从 EnergyMeter 改为 ElecConsumptionVO
+     *
+     * @param queryMeter 查询条件
+     * @return 设施用电汇总列表
+     */
+    List<ElecConsumptionVO> getFacsMeterHourSta(QueryMeter queryMeter);
+
+    /**
+     * 查询设施小时用电明细
+     *
+     * @param queryMeter 查询条件
+     * @return 小时用电明细列表
+     */
+    List<ElecMeterH> getFacsElecHourMeter(QueryMeter queryMeter);
+
+    /**
+     * 查询区域小时用电明细
+     *
+     * @param queryMeter 查询条件
+     * @return 小时用电明细列表
+     */
+    List<ElecMeterH> getAreaElecHourMeter(QueryMeter queryMeter);
+
+    /**
+     * 计算时间范围内日平均用电
+     * 兼容老接口: getElecDayAvg
+     *
+     * @param queryMeter 支持areaCode、deviceCode、date范围筛选
+     * @return EnergyMeter
+     */
+    EnergyMeter selectElecDayAvg(QueryMeter queryMeter);
+
+    /**
+     * 按设备类型查询日用电
+     * 兼容老接口: qryDeviceDay
+     *
+     * @param queryMeter 查询条件
+     * @return 设备用电列表
+     */
+    List<EnergyMeter> qryDeviceElecByDay(QueryMeter queryMeter);
 }

+ 0 - 56
ems/ems-core/src/main/java/com/ruoyi/ems/service/IElecLoadIndexService.java

@@ -1,56 +0,0 @@
-package com.ruoyi.ems.service;
-
-import com.ruoyi.ems.domain.ElecLoadIndex;
-import com.ruoyi.ems.model.QueryMeter;
-
-import java.util.List;
-
-/**
- * 电力负荷设施指标Service接口
- *
- * @author ruoyi
- * @date 2024-08-09
- */
-public interface IElecLoadIndexService {
-    /**
-     * 查询最新电力负荷设施指标
-     *
-     * @param areaCode 区域代码
-     * @param objType  对象类型
-     * @param objCode  对象代码
-     * @return 电力负荷设施指标
-     */
-    ElecLoadIndex selectNewIndex(String areaCode, String objType, String objCode);
-
-    /**
-     * 查询电力负荷设施指标列表
-     *
-     * @param queryMeter 电力负荷设施指标
-     * @return 电力负荷设施指标集合
-     */
-    List<ElecLoadIndex> selectMin15IndexList(QueryMeter queryMeter);
-
-    /**
-     * 查询最大功率负荷
-     *
-     * @param queryMeter 条件
-     * @return 结果
-     */
-    ElecLoadIndex selectMin15IndexMaxLoad(QueryMeter queryMeter);
-
-    /**
-     * 查询日最大功率负荷
-     *
-     * @param queryMeter 条件
-     * @return 结果
-     */
-    List<ElecLoadIndex> selectDayIndexMaxLoad(QueryMeter queryMeter);
-
-    /**
-     * 新增电力负荷设施指标
-     *
-     * @param index 电力负荷设施指标
-     * @return 结果
-     */
-    int insertMin15Index(ElecLoadIndex index);
-}

+ 0 - 16
ems/ems-core/src/main/java/com/ruoyi/ems/service/IElecMeterHService.java

@@ -14,14 +14,6 @@ import java.util.List;
  */
 public interface IElecMeterHService {
     /**
-     * 统计用电计量-根据边界对象
-     *
-     * @param queryMeter 查询条件
-     * @return 用电计量-小时集合
-     */
-    List<ElecMeterH> selectByMeterDevs(QueryMeter queryMeter);
-
-    /**
      * 统计日用电
      * @param queryMeter 查询条件
      * @return
@@ -29,14 +21,6 @@ public interface IElecMeterHService {
     List<ElecMeterH> staMeterDayList(QueryMeter queryMeter);
 
     /**
-     * 统计用电计量-根据边界对象
-     *
-     * @param queryMeter 查询条件
-     * @return
-     */
-    EnergyMeter staByMeterDev(QueryMeter queryMeter);
-
-    /**
      * 计算时间范围内日平均
      * @param queryMeter 支持areaCode、deviceCode、date范围筛选
      * @return ElecMeter

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

@@ -67,4 +67,28 @@ public interface IWaterConsumptionService {
      */
     List<WaterConsumptionExportVO> convertToWaterExportVOList(List<WaterConsumptionVO> originalList,
         String timeDimension);
+
+    /**
+     * 查询区域小时用水明细
+     *
+     * @param queryMeter 查询条件
+     * @return 小时用水明细列表
+     */
+    List<WaterMeterH> getAreaWaterHourMeter(QueryMeter queryMeter);
+
+    /**
+     * 查询设施小时用水明细
+     *
+     * @param queryMeter 查询条件
+     * @return 小时用水明细列表
+     */
+    List<WaterMeterH> getFacsWaterHourMeter(QueryMeter queryMeter);
+
+    /**
+     * 查询设施小时用水汇总统计
+     *
+     * @param queryMeter 查询条件
+     * @return 设施用水汇总列表
+     */
+    List<WaterConsumptionVO> getFacsWaterHourSta(QueryMeter queryMeter);
 }

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

@@ -103,187 +103,13 @@ public class BoundaryObjServiceImpl implements IBoundaryObjService {
         return boundaryObj;
     }
 
-    /**
-     * 查询设施用电统计
-     *
-     * @param queryMeter 查询条件对象,用于指定查询条件
-     * @return 返回电表信息列表,如果未找到符合条件的数据,则返回空列表
-     */
-    @Override
-    public List<EnergyMeter> getMeterStaByFacsCategory(QueryMeter queryMeter) {
-        List<EnergyMeter> result = new ArrayList<>();
-        List<BoundaryObj> bObjs = facsService.getFacsWithMeterDev(queryMeter.getAreaCode(),
-            queryMeter.getFacsCategory(), queryMeter.getFacsSubCategory(), queryMeter.getMeterCls());
-
-        if (CollectionUtils.isNotEmpty(bObjs)) {
-            for (BoundaryObj bObj : bObjs) {
-                EnergyMeter meter = new EnergyMeter();
-                meter.setAreaCode(queryMeter.getAreaCode());
-                meter.setObjType(bObj.getObjType());
-                meter.setObjCode(bObj.getObjCode());
-                meter.setObjName(bObj.getObjName());
-
-                if (CollectionUtils.isNotEmpty(bObj.getBindMeterDevs())) {
-                    EnergyMeter staObj = getElecMeter(queryMeter, bObj);
-
-                    if (null != staObj) {
-                        meter.setQuantity(staObj.getQuantity());
-                        meter.setUseCost(staObj.getUseCost());
-                    }
-                }
-
-                result.add(meter);
-            }
-        }
-
-        return result;
-    }
-
-    @Override
-    public List<ElecMeterH> getMeterByFacsCategory(QueryMeter queryMeter) {
-        List<ElecMeterH> result = new ArrayList<>();
-        List<BoundaryObj> bObjs = null;
-        String objCode = null;
-        String objName = null;
-        Set<String> devCodes = new HashSet<>();
-
-        if (!StringUtils.equals(queryMeter.getObjCode(), queryMeter.getAreaCode()) && StringUtils.isNotEmpty(
-            queryMeter.getObjCode())) {
-            objCode = queryMeter.getObjCode();
-            EmsFacs emsFacs = facsService.selectEmsFacsByCode(objCode);
-            objName = emsFacs.getFacsName();
-
-            List<MeterBoundaryRel> relList = boundaryRelService.selectRelByObj(queryMeter.getObjCode(),
-                MeterObjType.METER_FACS.getType(), 45);
-
-            if (CollectionUtils.isNotEmpty(relList)) {
-                for (MeterBoundaryRel bObj : relList) {
-                    devCodes.add(bObj.getMeterDevice());
-                }
-            }
-        }
-        else {
-            if (StringUtils.equals("-1", queryMeter.getAreaCode())) {
-                objCode = "-1";
-                objName = "全部设施";
-            }
-            else {
-                Area area = areaService.selectAreaByCode(queryMeter.getAreaCode());
-                objCode = queryMeter.getAreaCode();
-                objName = area.getAreaName();
-            }
-
-            bObjs = facsService.getFacsWithMeterDev(queryMeter.getAreaCode(), queryMeter.getFacsCategory(),
-                queryMeter.getFacsSubCategory(), queryMeter.getMeterCls());
-
-            for (BoundaryObj bObj : bObjs) {
-                if (CollectionUtils.isNotEmpty(bObj.getBindMeterDevs())) {
-                    devCodes.addAll(bObj.getBindMeterDevs());
-                }
-            }
-        }
-
-        if (CollectionUtils.isNotEmpty(devCodes)) {
-            QueryMeter condition = new QueryMeter();
-            condition.setAreaCode(queryMeter.getAreaCode());
-            condition.setObjType(MeterObjType.METER_FACS.getType());
-            condition.setObjCode(objCode);
-            condition.setObjName(objName);
-            condition.setStartRecTime(queryMeter.getStartRecTime());
-            condition.setEndRecTime(queryMeter.getEndRecTime());
-            condition.setDeviceCodes(devCodes);
-
-            result = elecMeterHService.selectByMeterDevs(condition);
-        }
-
-        return result;
-    }
-
     @Override
     public List<ElecMeterH> getMeterStaByArea(QueryMeter queryMeter) {
         return Collections.emptyList();
     }
 
-    @Override
-    public List<ElecMeterH> getMeterByArea(QueryMeter queryMeter) {
-
-        List<ElecMeterH> result = new ArrayList<>();
-
-        if (StringUtils.equals("-1", queryMeter.getAreaCode())) {
-            // 查询区域树
-            List<Area> areaTree = areaService.selectAreaTree("0", false);
-
-            // 查询设施列表
-            EmsFacs facsParam = new EmsFacs();
-            facsParam.setFacsCategory(queryMeter.getFacsCategory());
-            List<EmsFacs> facsList = facsService.selectEmsFacsList(facsParam);
-            Set<String> facsAreaCodes = facsList.stream().map(EmsFacs::getRefArea).collect(Collectors.toSet());
-
-            // 过滤树节点
-            areaTree = AreaUtils.filterTree(areaTree, facsAreaCodes);
-            List<String> areaCodes = areaTree.stream().map(Area::getAreaCode).collect(Collectors.toList());
-
-            List<MeterBoundaryRel> relList = new ArrayList<>();
-
-            for (String areaCode : areaCodes) {
-                List<MeterBoundaryRel> rels = boundaryRelService.selectRelByObj(areaCode,
-                    MeterObjType.METER_AREA.getType(), 45);
-                relList.addAll(rels);
-            }
-
-            if (CollectionUtils.isNotEmpty(relList)) {
-                Area rootArea = new Area();
-                rootArea.setAreaCode(queryMeter.getAreaCode());
-                rootArea.setAreaName("全部区域");
 
-                Set<String> bdDevs = relList.stream().map(MeterBoundaryRel::getMeterDevice).collect(Collectors.toSet());
 
-                result = getAreaMeterQuery(queryMeter, rootArea, bdDevs, queryMeter.getStartRecTime(),
-                    queryMeter.getEndRecTime());
-            }
-        }
-        else {
-            Area area = areaService.selectAreaByCode(queryMeter.getObjCode());
-            List<MeterBoundaryRel> relList = boundaryRelService.selectRelByObj(queryMeter.getAreaCode(),
-                MeterObjType.METER_AREA.getType(), 45);
-
-            if (null != area && CollectionUtils.isNotEmpty(relList)) {
-                Set<String> bdDevs = relList.stream().map(MeterBoundaryRel::getMeterDevice).collect(Collectors.toSet());
-
-                result = getAreaMeterQuery(queryMeter, area, bdDevs, queryMeter.getStartRecTime(),
-                    queryMeter.getEndRecTime());
-            }
-        }
-
-        return result;
-    }
-
-    private List<ElecMeterH> getAreaMeterQuery(QueryMeter queryMeter, Area area, Set<String> bdDevs, String startTime,
-        String endTime) {
-        QueryMeter condition = new QueryMeter();
-        condition.setAreaCode(queryMeter.getAreaCode());
-        condition.setObjCode(queryMeter.getObjCode());
-        condition.setObjName(area.getAreaName());
-        condition.setStartRecTime(startTime);
-        condition.setEndRecTime(endTime);
-        condition.setDeviceCodes(bdDevs);
-
-        return elecMeterHService.selectByMeterDevs(condition);
-    }
-
-    private EnergyMeter getElecMeter(QueryMeter queryMeter, BoundaryObj bObj) {
-        QueryMeter condition = new QueryMeter();
-        condition.setAreaCode(queryMeter.getAreaCode());
-        condition.setObjType(MeterObjType.METER_FACS.getType());
-        condition.setObjCode(bObj.getObjCode());
-        condition.setObjName(bObj.getObjName());
-        condition.setStartRecTime(queryMeter.getStartRecTime());
-        condition.setEndRecTime(queryMeter.getEndRecTime());
-        condition.setDeviceCodes(bObj.getBindMeterDevs());
-
-        EnergyMeter meterRes = elecMeterHService.staByMeterDev(condition);
-        return meterRes;
-    }
 
     /**
      * 递归构造边界-绑定电表 的树结构

+ 420 - 229
ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/ElecConsumptionServiceImpl.java

@@ -3,20 +3,25 @@ package com.ruoyi.ems.service.impl;
 import com.huashe.common.utils.DateUtils;
 import com.ruoyi.ems.domain.Area;
 import com.ruoyi.ems.domain.ElecMeterH;
+import com.ruoyi.ems.domain.EmsFacs;
+import com.ruoyi.ems.domain.EnergyMeter;
+import com.ruoyi.ems.domain.MeterBoundaryRel;
+import com.ruoyi.ems.enums.MeterObjType;
 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.IEmsFacsService;
 import com.ruoyi.ems.service.IMeterBoundaryRelService;
 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 org.springframework.util.CollectionUtils;
 
 import java.util.Collections;
 import java.util.Date;
@@ -39,7 +44,10 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
     private ElecConsumptionMapper elecConsumptionMapper;
 
     @Autowired
-    private IMeterBoundaryRelService meterBoundaryRelService;
+    private IMeterBoundaryRelService boundaryRelService;
+
+    @Autowired
+    private IEmsFacsService facsService;
 
     @Autowired
     private IAreaService areaService;
@@ -49,6 +57,8 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
      */
     private static final int ELEC_METER_CLS = 45;
 
+    // ==================== 用电类型查询 ====================
+
     @Override
     public List<String> getElecHourTypes(QueryMeter queryMeter) {
         if (queryMeter == null) {
@@ -57,34 +67,35 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
         }
 
         try {
-            // 1. 获取所有相关测点设备
             Set<String> meterDevices = getMeterDevicesByArea(queryMeter.getObjCode());
             if (meterDevices.isEmpty()) {
-                logger.info("未找到相关电表设备,查询条件: areaCode={}, objCode={}", queryMeter.getAreaCode(),
-                    queryMeter.getObjCode());
+                logger.info("未找到相关电表设备,查询条件: areaCode={}, objCode={}",
+                    queryMeter.getAreaCode(), queryMeter.getObjCode());
                 return Collections.emptyList();
             }
 
             return elecConsumptionMapper.selectElecHourSupportTypes(queryMeter, meterDevices);
-        }
-        catch (Exception e) {
+        } catch (Exception e) {
             logger.error("查询区域用电统计列表异常", e);
             return Collections.emptyList();
         }
     }
 
-    /**
-     * 查询用电计量-小时列表
-     *
-     * @param queryMeter 用电计量-小时
-     * @return 用电计量-小时集合
-     */
+    // ==================== 电表原始数据查询 ====================
+
     @Override
     public List<ElecMeterH> selectMDevElecConsumptionList(QueryMeter queryMeter) {
         return elecConsumptionMapper.selectMDevElecConsumptionList(queryMeter);
     }
 
     @Override
+    public ElecConsumptionVO selectMDevElecConsumptionSummary(QueryMeter queryMeter) {
+        return elecConsumptionMapper.selectMDevElecConsumptionSummary(queryMeter);
+    }
+
+    // ==================== 区域用电统计(day/month/year) ====================
+
+    @Override
     public List<ElecConsumptionVO> selectAreaElecConsumptionList(QueryMeter queryMeter) {
         if (queryMeter == null) {
             logger.warn("查询参数为空,返回空列表");
@@ -92,20 +103,17 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
         }
 
         try {
-            // 1. 获取所有相关测点设备
             Set<String> meterDevices = getMeterDevicesByArea(queryMeter.getObjCode());
             if (meterDevices.isEmpty()) {
-                logger.info("未找到相关电表设备,查询条件: areaCode={}, objCode={}", queryMeter.getAreaCode(),
-                    queryMeter.getObjCode());
+                logger.info("未找到相关电表设备,查询条件: areaCode={}, objCode={}",
+                    queryMeter.getAreaCode(), queryMeter.getObjCode());
                 return Collections.emptyList();
             }
 
-            logger.info("查询区域用电统计,时间维度: {}, 设备数量: {}", queryMeter.getTimeDimension(),
-                meterDevices.size());
+            logger.info("查询区域用电统计,时间维度: {}, 设备数量: {}",
+                queryMeter.getTimeDimension(), meterDevices.size());
 
-            // 2. 根据时间维度调用相应的查询方法
             List<ElecConsumptionVO> result;
-            // 根据时间维度调用相应的查询方法
             switch (queryMeter.getTimeDimension().toLowerCase()) {
                 case "day":
                     result = elecConsumptionMapper.selectAreaDailyElecConsumptionByDevices(queryMeter, meterDevices);
@@ -122,12 +130,9 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
                     break;
             }
 
-            // 填充区域名称路径
             fillAreaNameForElecConsumption(result);
-
             return result;
-        }
-        catch (Exception e) {
+        } catch (Exception e) {
             logger.error("查询区域用电统计列表异常", e);
             return Collections.emptyList();
         }
@@ -141,7 +146,6 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
         }
 
         try {
-            // 1. 获取所有相关测点设备
             Set<String> meterDevices = getMeterDevicesByArea(queryMeter.getObjCode());
             if (meterDevices.isEmpty()) {
                 logger.info("未找到相关电表设备,返回空汇总");
@@ -150,136 +154,16 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
 
             logger.info("查询区域用电汇总,设备数量: {}", meterDevices.size());
 
-            // 2. 查询汇总数据
-            ElecConsumptionVO summary = elecConsumptionMapper.selectAreaElecConsumptionSummaryByDevices(queryMeter,
-                meterDevices);
+            ElecConsumptionVO summary = elecConsumptionMapper.selectAreaElecConsumptionSummaryByDevices(
+                queryMeter, meterDevices);
             return summary != null ? summary : new ElecConsumptionVO();
-        }
-        catch (Exception e) {
+        } 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);
-                }
-            }
-        }
-    }
+    // ==================== 设施用电统计(day/month/year) ====================
 
     @Override
     public List<ElecConsumptionVO> selectFacsElecConsumptionList(QueryMeter queryMeter) {
@@ -290,10 +174,9 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
 
         try {
             logger.info("查询设施用电统计,时间维度: {}, 设施分类: {}, 区域: {}, 设施: {}",
-                queryMeter.getTimeDimension(), queryMeter.getFacsCategory(), queryMeter.getAreaCode(),
-                queryMeter.getObjCode());
+                queryMeter.getTimeDimension(), queryMeter.getFacsCategory(),
+                queryMeter.getAreaCode(), queryMeter.getObjCode());
 
-            // 根据时间维度调用相应的查询方法
             switch (queryMeter.getTimeDimension().toLowerCase()) {
                 case "day":
                     return elecConsumptionMapper.selectFacsDailyElecConsumption(queryMeter);
@@ -305,19 +188,13 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
                     logger.warn("未识别的时间维度: {},使用月统计", queryMeter.getTimeDimension());
                     return elecConsumptionMapper.selectFacsMonthlyElecConsumption(queryMeter);
             }
-        }
-        catch (Exception e) {
+        } catch (Exception e) {
             logger.error("查询设施用电统计列表异常", e);
             return Collections.emptyList();
         }
     }
 
     @Override
-    public ElecConsumptionVO selectMDevElecConsumptionSummary(QueryMeter queryMeter) {
-        return elecConsumptionMapper.selectMDevElecConsumptionSummary(queryMeter);
-    }
-
-    @Override
     public ElecConsumptionVO selectFacsElecConsumptionSummary(QueryMeter queryMeter) {
         if (queryMeter == null) {
             logger.warn("查询参数为空,返回空对象");
@@ -325,18 +202,19 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
         }
 
         try {
-            logger.info("查询设施用电汇总,设施分类: {}, 区域: {}, 设施: {}", queryMeter.getFacsCategory(),
-                queryMeter.getAreaCode(), queryMeter.getObjCode());
+            logger.info("查询设施用电汇总,设施分类: {}, 区域: {}, 设施: {}",
+                queryMeter.getFacsCategory(), queryMeter.getAreaCode(), queryMeter.getObjCode());
 
             ElecConsumptionVO summary = elecConsumptionMapper.selectFacsElecConsumptionSummary(queryMeter);
             return summary != null ? summary : new ElecConsumptionVO();
-        }
-        catch (Exception e) {
+        } catch (Exception e) {
             logger.error("查询设施用电统计汇总异常", e);
             return new ElecConsumptionVO();
         }
     }
 
+    // ==================== 导出功能 ====================
+
     @Override
     public List<ElecConsumptionVO> exportAreaElecConsumptionList(QueryMeter queryMeter) {
         if (queryMeter == null) {
@@ -345,7 +223,6 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
         }
 
         try {
-            // 导出时不分页,清除分页参数
             QueryMeter exportQuery = cloneQueryMeter(queryMeter);
             exportQuery.setPageNum(null);
             exportQuery.setPageSize(null);
@@ -356,8 +233,7 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
             logger.info("导出区域用电统计完成,记录数: {}", result.size());
 
             return result;
-        }
-        catch (Exception e) {
+        } catch (Exception e) {
             logger.error("导出区域用电统计异常", e);
             return Collections.emptyList();
         }
@@ -371,36 +247,399 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
         }
 
         try {
-            // 导出时不分页,清除分页参数
             QueryMeter exportQuery = cloneQueryMeter(queryMeter);
             exportQuery.setPageNum(null);
             exportQuery.setPageSize(null);
 
-            logger.info("导出设施用电统计,时间维度: {}, 设施分类: {}", exportQuery.getTimeDimension(),
-                exportQuery.getFacsCategory());
+            logger.info("导出设施用电统计,时间维度: {}, 设施分类: {}",
+                exportQuery.getTimeDimension(), exportQuery.getFacsCategory());
 
             List<ElecConsumptionVO> result = selectFacsElecConsumptionList(exportQuery);
             logger.info("导出设施用电统计完成,记录数: {}", result.size());
 
             return result;
-        }
-        catch (Exception e) {
+        } catch (Exception e) {
             logger.error("导出设施用电统计异常", e);
             return Collections.emptyList();
         }
     }
 
-    /**
-     * 转换为用电导出VO列表
-     */
+    @Override
     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());
+        return originalList.stream()
+            .map(vo -> convertToElecExportVO(vo, timeDimension))
+            .collect(Collectors.toList());
+    }
+
+    // ==================== 小时粒度查询方法(重构后) ====================
+
+    /**
+     * 查询设施小时用电汇总统计
+     *
+     * 重构说明:
+     * - 返回类型从 EnergyMeter 改为 ElecConsumptionVO(统一对象)
+     * - 原方法调用 facsService + elecMeterHService 循环查询
+     * - 重构后直接通过SQL一次完成,性能大幅提升
+     *
+     * @param queryMeter 查询条件
+     * @return 设施用电汇总列表
+     */
+    @Override
+    public List<ElecConsumptionVO> getFacsMeterHourSta(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            logger.warn("查询参数为空,返回空列表");
+            return Collections.emptyList();
+        }
+
+        try {
+            // 设置默认计量类型为电表
+            if (queryMeter.getMeterCls() == null) {
+                queryMeter.setMeterCls(ELEC_METER_CLS);
+            }
+
+            logger.info("查询设施小时用电汇总,区域: {}, 设施分类: {}, 子类: {}",
+                queryMeter.getAreaCode(), queryMeter.getFacsCategory(), queryMeter.getFacsSubCategory());
+
+            // 直接通过Mapper一次查询完成,替代原来的循环调用
+            List<ElecConsumptionVO> result = elecConsumptionMapper.selectFacsHourlyElecSummary(queryMeter);
+
+            return result != null ? result : Collections.emptyList();
+        } catch (Exception e) {
+            logger.error("查询设施小时用电汇总异常", e);
+            return Collections.emptyList();
+        }
+    }
+
+    /**
+     * 查询设施小时用电明细
+     *
+     * @param queryMeter 查询条件
+     * @return 小时用电明细列表
+     */
+    @Override
+    public List<ElecMeterH> getFacsElecHourMeter(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            logger.warn("查询参数为空,返回空列表");
+            return Collections.emptyList();
+        }
+
+        try {
+            // 设置默认计量类型
+            if (queryMeter.getMeterCls() == null) {
+                queryMeter.setMeterCls(ELEC_METER_CLS);
+            }
+
+            // 设置默认排序
+            if (StringUtils.isBlank(queryMeter.getOrderFlag())) {
+                queryMeter.setOrderFlag("desc");
+            }
+
+            // 处理对象名称(用于结果展示)
+            enrichFacsQueryMeter(queryMeter);
+
+            logger.info("查询设施小时用电明细,区域: {}, 设施: {}, 设施分类: {}",
+                queryMeter.getAreaCode(), queryMeter.getObjCode(), queryMeter.getFacsCategory());
+
+            // 直接通过Mapper查询
+            List<ElecMeterH> result = elecConsumptionMapper.selectFacsHourlyElecConsumption(queryMeter);
+
+            return result != null ? result : Collections.emptyList();
+        } catch (Exception e) {
+            logger.error("查询设施小时用电明细异常", e);
+            return Collections.emptyList();
+        }
+    }
+
+    /**
+     * 查询区域小时用电明细
+     *
+     * @param queryMeter 查询条件
+     * @return 小时用电明细列表
+     */
+    @Override
+    public List<ElecMeterH> getAreaElecHourMeter(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            logger.warn("查询参数为空,返回空列表");
+            return Collections.emptyList();
+        }
+
+        try {
+            // 设置默认排序
+            if (StringUtils.isBlank(queryMeter.getOrderFlag())) {
+                queryMeter.setOrderFlag("desc");
+            }
+
+            // 处理对象名称
+            enrichAreaQueryMeter(queryMeter);
+
+            // 获取区域绑定的所有电表设备
+            Set<String> meterDevices = getAreaMeterDevicesForHourly(queryMeter);
+
+            if (CollectionUtils.isEmpty(meterDevices)) {
+                logger.info("未找到区域绑定的电表设备,区域: {}", queryMeter.getAreaCode());
+                return Collections.emptyList();
+            }
+
+            logger.info("查询区域小时用电明细,区域: {}, 对象: {}, 设备数量: {}",
+                queryMeter.getAreaCode(), queryMeter.getObjCode(), meterDevices.size());
+
+            // 通过Mapper查询
+            List<ElecMeterH> result = elecConsumptionMapper.selectAreaHourlyElecConsumptionByDevices(
+                queryMeter, meterDevices);
+
+            return result != null ? result : Collections.emptyList();
+        } catch (Exception e) {
+            logger.error("查询区域小时用电明细异常", e);
+            return Collections.emptyList();
+        }
+    }
+
+    @Override
+    public EnergyMeter selectElecDayAvg(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            logger.warn("查询参数为空,返回空对象");
+            return new EnergyMeter();
+        }
+
+        try {
+            logger.info("查询日平均用电,区域: {}, 设备: {}, 时间范围: {} ~ {}",
+                queryMeter.getAreaCode(), queryMeter.getDeviceCode(),
+                queryMeter.getStartRecTime(), queryMeter.getEndRecTime());
+
+            EnergyMeter result = elecConsumptionMapper.selectElecDayAvg(queryMeter);
+            return result != null ? result : new EnergyMeter();
+        } catch (Exception e) {
+            logger.error("查询日平均用电异常", e);
+            return new EnergyMeter();
+        }
+    }
+
+    @Override
+    public List<EnergyMeter> qryDeviceElecByDay(QueryMeter queryMeter) {
+        if (queryMeter == null || StringUtils.isBlank(queryMeter.getStartRecTime())) {
+            logger.warn("查询参数为空,返回空列表");
+            return Collections.emptyList();
+        }
+
+        try {
+            logger.info("按设备类型查询日用电,区域: {}, 起始日期: {}",
+                queryMeter.getAreaCode(), queryMeter.getStartRecTime());
+
+            List<EnergyMeter> result = elecConsumptionMapper.selectDeviceElecByDay(queryMeter);
+            return result != null ? result : Collections.emptyList();
+        } catch (Exception e) {
+            logger.error("按设备类型查询日用电异常", e);
+            return Collections.emptyList();
+        }
+    }
+
+    // ==================== 私有辅助方法 ====================
+
+    /**
+     * 为设施查询条件补充名称信息
+     */
+    private void enrichFacsQueryMeter(QueryMeter queryMeter) {
+        String objCode = queryMeter.getObjCode();
+        String areaCode = queryMeter.getAreaCode();
+
+        if (StringUtils.isNotBlank(objCode) && !StringUtils.equals(objCode, areaCode)
+            && !StringUtils.equals("-1", objCode)) {
+            // 查询指定设施
+            EmsFacs emsFacs = facsService.selectEmsFacsByCode(objCode);
+            if (emsFacs != null) {
+                queryMeter.setObjName(emsFacs.getFacsName());
+            }
+        } else if (StringUtils.equals("-1", areaCode)) {
+            // 全部设施
+            queryMeter.setObjCode("-1");
+            queryMeter.setObjName("全部设施");
+        } else if (StringUtils.isNotBlank(areaCode)) {
+            // 指定区域下的设施
+            Area area = areaService.selectAreaByCode(areaCode);
+            if (area != null) {
+                queryMeter.setObjCode(areaCode);
+                queryMeter.setObjName(area.getAreaName());
+            }
+        }
+    }
+
+    /**
+     * 为区域查询条件补充名称信息
+     */
+    private void enrichAreaQueryMeter(QueryMeter queryMeter) {
+        String areaCode = queryMeter.getAreaCode();
+
+        if (StringUtils.equals("-1", areaCode)) {
+            queryMeter.setObjCode("-1");
+            queryMeter.setObjName("全部区域");
+        } else if (StringUtils.isNotBlank(queryMeter.getObjCode())) {
+            Area area = areaService.selectAreaByCode(queryMeter.getObjCode());
+            if (area != null) {
+                queryMeter.setObjName(area.getAreaName());
+            }
+        }
+    }
+
+    /**
+     * 获取区域绑定的电表设备(用于小时粒度查询)
+     *
+     * 复用并简化原 getAreaElecHourMeter 中的设备获取逻辑
+     */
+    private Set<String> getAreaMeterDevicesForHourly(QueryMeter queryMeter) {
+        Set<String> meterDevices = new HashSet<>();
+        String areaCode = queryMeter.getAreaCode();
+
+        try {
+            if (StringUtils.equals("-1", areaCode)) {
+                // 全部区域:获取所有顶级区域的设备
+                List<Area> areaTree = areaService.selectAreaTree("0", false);
+
+                // 如果有设施分类过滤,先过滤区域
+                if (StringUtils.isNotBlank(queryMeter.getFacsCategory())) {
+                    EmsFacs facsParam = new EmsFacs();
+                    facsParam.setFacsCategory(queryMeter.getFacsCategory());
+                    List<EmsFacs> facsList = facsService.selectEmsFacsList(facsParam);
+                    Set<String> facsAreaCodes = facsList.stream()
+                        .map(EmsFacs::getRefArea)
+                        .collect(Collectors.toSet());
+                    areaTree = AreaUtils.filterTree(areaTree, facsAreaCodes);
+                }
+
+                // 获取过滤后区域的所有电表设备
+                for (Area area : areaTree) {
+                    List<MeterBoundaryRel> rels = boundaryRelService.selectRelByObj(
+                        area.getAreaCode(), MeterObjType.METER_AREA.getType(), ELEC_METER_CLS);
+                    if (CollectionUtils.isNotEmpty(rels)) {
+                        rels.forEach(rel -> meterDevices.add(rel.getMeterDevice()));
+                    }
+                }
+            } else {
+                // 指定区域:使用objCode或areaCode
+                String targetCode = StringUtils.isNotBlank(queryMeter.getObjCode())
+                    ? queryMeter.getObjCode() : areaCode;
+
+                List<MeterBoundaryRel> relList = boundaryRelService.selectRelByObj(
+                    targetCode, MeterObjType.METER_AREA.getType(), ELEC_METER_CLS);
+                if (CollectionUtils.isNotEmpty(relList)) {
+                    relList.forEach(rel -> meterDevices.add(rel.getMeterDevice()));
+                }
+            }
+        } catch (Exception e) {
+            logger.error("获取区域电表设备异常,区域: {}", areaCode, e);
+        }
+
+        return meterDevices;
+    }
+
+    /**
+     * 根据区域获取所有相关的测点设备
+     */
+    private Set<String> getMeterDevicesByArea(String objCode) {
+        Set<String> meterDevices = new HashSet<>();
+
+        try {
+            Set<String> targetAreaCodes = new HashSet<>();
+
+            if (StringUtils.isNotBlank(objCode) && !"-1".equals(objCode)) {
+                targetAreaCodes.addAll(getAllChildAreaCodes(objCode));
+                logger.debug("根据objCode查询区域设备,区域代码: {}, 找到子区域数量: {}",
+                    objCode, targetAreaCodes.size());
+            }
+
+            if (targetAreaCodes.isEmpty()) {
+                logger.debug("未指定区域,查询所有电表设备");
+
+                List<String> allDevices = boundaryRelService.selectMeterDevices(null, 1, ELEC_METER_CLS);
+                if (CollectionUtils.isNotEmpty(allDevices)) {
+                    meterDevices.addAll(allDevices);
+                    logger.debug("查询到所有区域电表设备数量: {}", allDevices.size());
+                } else {
+                    List<Area> allAreas = areaService.selectArea(new Area());
+                    if (CollectionUtils.isNotEmpty(allAreas)) {
+                        for (Area area : allAreas) {
+                            List<String> areaDevices = boundaryRelService.selectMeterDevices(
+                                area.getAreaCode(), 1, ELEC_METER_CLS);
+                            if (CollectionUtils.isNotEmpty(areaDevices)) {
+                                meterDevices.addAll(areaDevices);
+                                logger.debug("区域 {} 找到电表设备数量: {}",
+                                    area.getAreaCode(), areaDevices.size());
+                            }
+                        }
+                    }
+                }
+            } else {
+                for (String areaCode : targetAreaCodes) {
+                    List<String> devices = boundaryRelService.selectMeterDevices(areaCode, 1, ELEC_METER_CLS);
+                    if (CollectionUtils.isNotEmpty(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 {
+            Area currentArea = areaService.selectAreaByCode(areaCode);
+            if (currentArea != null) {
+                areaCodes.add(currentArea.getAreaCode());
+                logger.debug("添加当前区域: {}", currentArea.getAreaCode());
+            }
+
+            List<Area> childAreas = areaService.selectAreaTree(areaCode, true);
+            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.isNotEmpty(area.getChildren())) {
+                    collectAreaCodes(area.getChildren(), areaCodes);
+                }
+            }
+        }
     }
 
     /**
@@ -409,20 +648,13 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
     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;
@@ -442,7 +674,7 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
             case "month":
                 return StringUtils.isNotBlank(vo.getStatisticMonth()) ? vo.getStatisticMonth() : "";
             case "year":
-                return vo.getStatisticYear() != null ? vo.getStatisticYear().toString() : "";
+                return vo.getStatisticYear() != null ? vo.getStatisticYear() : "";
             default:
                 return StringUtils.isNotBlank(vo.getStatisticMonth()) ? vo.getStatisticMonth() : "";
         }
@@ -453,11 +685,7 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
      */
     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", 0.0);
         }
         return String.format("%." + decimals + "f", num.doubleValue());
     }
@@ -482,11 +710,12 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
         target.setObjCode(source.getObjCode());
         target.setObjType(source.getObjType());
         target.setFacsCategory(source.getFacsCategory());
+        target.setFacsSubCategory(source.getFacsSubCategory());
         target.setTimeDimension(source.getTimeDimension());
         target.setStartRecTime(source.getStartRecTime());
         target.setEndRecTime(source.getEndRecTime());
         target.setOrderFlag(source.getOrderFlag());
-        // 不复制分页参数
+        target.setMeterCls(source.getMeterCls());
         target.setPageNum(null);
         target.setPageSize(null);
 
@@ -494,39 +723,6 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
     }
 
     /**
-     * 验证查询参数
-     */
-    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) {
@@ -535,19 +731,16 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
         }
 
         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) {
+        } catch (Exception e) {
             logger.error("填充用电统计区域名称异常", e);
         }
     }
@@ -560,10 +753,8 @@ public class ElecConsumptionServiceImpl implements IElecConsumptionService {
             return;
         }
 
-        // 获取区域完整路径名称
         String areaNamePath = AreaUtils.getAreaNamePath(vo.getObjCode(), areaMap);
 
-        // 如果原名称是简单的名称(如"二楼"),用路径名称替换
         if (StringUtils.isNotBlank(areaNamePath)) {
             vo.setObjName(areaNamePath);
             logger.debug("区域名称已替换: {} -> {}", vo.getObjCode(), areaNamePath);

+ 0 - 93
ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/ElecLoadIndexServiceImpl.java

@@ -1,93 +0,0 @@
-package com.ruoyi.ems.service.impl;
-
-import com.ruoyi.ems.domain.ElecLoadIndex;
-import com.ruoyi.ems.mapper.ElecLoadIndex15minMapper;
-import com.ruoyi.ems.model.QueryMeter;
-import com.ruoyi.ems.service.IElecLoadIndexService;
-import com.ruoyi.ems.util.PowerUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-/**
- * 电力负荷设施指标Service业务层处理
- *
- * @author ruoyi
- * @date 2024-08-09
- */
-@Service
-public class ElecLoadIndexServiceImpl implements IElecLoadIndexService {
-    @Autowired
-    private ElecLoadIndex15minMapper index15minMapper;
-
-    @Override
-    public ElecLoadIndex selectNewIndex(String areaCode, String objType, String objCode) {
-        return index15minMapper.selectNewIndex(areaCode, objType, objCode);
-    }
-
-    /**
-     * 查询电力负荷设施指标列表
-     *
-     * @param queryMeter 查询参数
-     * @return 电力负荷设施指标
-     */
-    @Override
-    public List<ElecLoadIndex> selectMin15IndexList(QueryMeter queryMeter) {
-        List<ElecLoadIndex> indexList = index15minMapper.selectIndexList(queryMeter);
-
-        for (ElecLoadIndex index : indexList) {
-            index.setS(PowerUtils.getSPower(index.getP(), index.getQ()));
-            index.setPf(PowerUtils.getPF(index.getP(), index.getS()));
-        }
-
-        return indexList;
-    }
-
-//    @Override
-//    public List<ElecLoadIndex> selectMin15IndexDetailList(QueryMeter queryMeter) {
-//        List<ElecLoadIndex> indexList = index15minMapper.selectIndexList(queryMeter);
-//
-//        for (ElecLoadIndex index : indexList) {
-//            index.setS(PowerUtils.getSPower(index.getP(), index.getQ()));
-//            index.setPf(PowerUtils.getPF(index.getP(), index.getS()));
-//        }
-//
-//        return indexList;
-//    }
-
-    @Override
-    public ElecLoadIndex selectMin15IndexMaxLoad(QueryMeter queryMeter) {
-        ElecLoadIndex index = index15minMapper.selectIndexMaxLoad(queryMeter);
-
-        if (null != index) {
-            index.setS(PowerUtils.getSPower(index.getP(), index.getQ()));
-            index.setPf(PowerUtils.getPF(index.getP(), index.getS()));
-        }
-
-        return index;
-    }
-
-    @Override
-    public List<ElecLoadIndex> selectDayIndexMaxLoad(QueryMeter queryMeter) {
-        List<ElecLoadIndex> indexList = index15minMapper.selectDayIndexMaxLoad(queryMeter);
-
-        for (ElecLoadIndex index : indexList) {
-            index.setS(PowerUtils.getSPower(index.getP(), index.getQ()));
-            index.setPf(PowerUtils.getPF(index.getP(), index.getS()));
-        }
-
-        return indexList;
-    }
-
-    /**
-     * 新增电力负荷设施指标
-     *
-     * @param loadIndex 电力负荷设施指标
-     * @return 结果
-     */
-    @Override
-    public int insertMin15Index(ElecLoadIndex loadIndex) {
-        return index15minMapper.insertIndex(loadIndex);
-    }
-}

+ 0 - 23
ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/ElecMeterHServiceImpl.java

@@ -1,6 +1,5 @@
 package com.ruoyi.ems.service.impl;
 
-import com.huashe.common.utils.DateUtils;
 import com.ruoyi.ems.domain.ElecMeterH;
 import com.ruoyi.ems.domain.EnergyMeter;
 import com.ruoyi.ems.mapper.ElecMeterHMapper;
@@ -22,33 +21,11 @@ public class ElecMeterHServiceImpl implements IElecMeterHService {
     @Autowired
     private ElecMeterHMapper elecMeterHMapper;
 
-    /**
-     * 根据多个电表/断路器合并查询用电计量-小时列表
-     *
-     * @param queryMeter 用电计量-小时
-     * @return 用电计量-小时
-     */
-    @Override
-    public List<ElecMeterH> selectByMeterDevs(QueryMeter queryMeter) {
-        return elecMeterHMapper.selectElecMeterByDevs(queryMeter);
-    }
-
     @Override
     public List<ElecMeterH> staMeterDayList(QueryMeter queryMeter) {
         return elecMeterHMapper.selectElecMeterDayList(queryMeter);
     }
 
-    /**
-     * 统计用电计量-根据边界对象
-     *
-     * @param queryMeter 查询条件
-     * @return 统计电量信息
-     */
-    @Override
-    public EnergyMeter staByMeterDev(QueryMeter queryMeter) {
-        return elecMeterHMapper.selectElecMeterSumByDev(queryMeter);
-    }
-
     @Override
     public EnergyMeter selectElecDayAvg(QueryMeter queryMeter) {
         return elecMeterHMapper.selectElecDayAvg(queryMeter);

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

@@ -2,12 +2,14 @@ package com.ruoyi.ems.service.impl;
 
 import com.huashe.common.utils.DateUtils;
 import com.ruoyi.ems.domain.Area;
+import com.ruoyi.ems.domain.EmsFacs;
 import com.ruoyi.ems.domain.WaterMeterH;
 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.IEmsFacsService;
 import com.ruoyi.ems.service.IMeterBoundaryRelService;
 import com.ruoyi.ems.service.IWaterConsumptionService;
 import com.ruoyi.ems.util.AreaUtils;
@@ -41,6 +43,9 @@ public class WaterConsumptionServiceImpl implements IWaterConsumptionService {
     private IMeterBoundaryRelService meterBoundaryRelService;
 
     @Autowired
+    private IEmsFacsService facsService;
+
+    @Autowired
     private IAreaService areaService;
 
     /**
@@ -284,6 +289,198 @@ public class WaterConsumptionServiceImpl implements IWaterConsumptionService {
         return selectFacsWaterConsumptionList(queryMeter);
     }
 
+    @Override
+    public List<WaterMeterH> getAreaWaterHourMeter(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            logger.warn("查询参数为空,返回空列表");
+            return Collections.emptyList();
+        }
+
+        try {
+            // 设置默认排序
+            if (StringUtils.isBlank(queryMeter.getOrderFlag())) {
+                queryMeter.setOrderFlag("desc");
+            }
+
+            // 处理对象名称
+            enrichAreaQueryMeter(queryMeter);
+
+            // 获取区域绑定的所有水表设备
+            Set<String> meterDevices = getAreaMeterDevicesForHourly(queryMeter);
+
+            if (CollectionUtils.isEmpty(meterDevices)) {
+                logger.info("未找到区域绑定的水表设备,区域: {}", queryMeter.getAreaCode());
+                return Collections.emptyList();
+            }
+
+            logger.info("查询区域小时用水明细,区域: {}, 对象: {}, 设备数量: {}",
+                queryMeter.getAreaCode(), queryMeter.getObjCode(), meterDevices.size());
+
+            // 通过Mapper查询
+            List<WaterMeterH> result = waterConsumptionMapper.selectAreaHourlyWaterConsumptionByDevices(
+                queryMeter, meterDevices);
+
+            return result != null ? result : Collections.emptyList();
+        } catch (Exception e) {
+            logger.error("查询区域小时用水明细异常", e);
+            return Collections.emptyList();
+        }
+    }
+
+    @Override
+    public List<WaterMeterH> getFacsWaterHourMeter(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            logger.warn("查询参数为空,返回空列表");
+            return Collections.emptyList();
+        }
+
+        try {
+            // 设置默认计量类型
+            if (queryMeter.getMeterCls() == null) {
+                queryMeter.setMeterCls(WATER_METER_CLS);
+            }
+
+            // 设置默认排序
+            if (StringUtils.isBlank(queryMeter.getOrderFlag())) {
+                queryMeter.setOrderFlag("desc");
+            }
+
+            // 处理对象名称(用于结果展示)
+            enrichFacsQueryMeter(queryMeter);
+
+            logger.info("查询设施小时用水明细,区域: {}, 设施: {}, 设施分类: {}",
+                queryMeter.getAreaCode(), queryMeter.getObjCode(), queryMeter.getFacsCategory());
+
+            // 直接通过Mapper查询
+            List<WaterMeterH> result = waterConsumptionMapper.selectFacsHourlyWaterConsumption(queryMeter);
+
+            return result != null ? result : Collections.emptyList();
+        } catch (Exception e) {
+            logger.error("查询设施小时用水明细异常", e);
+            return Collections.emptyList();
+        }
+    }
+
+    @Override
+    public List<WaterConsumptionVO> getFacsWaterHourSta(QueryMeter queryMeter) {
+        if (queryMeter == null) {
+            logger.warn("查询参数为空,返回空列表");
+            return Collections.emptyList();
+        }
+
+        try {
+            // 设置默认计量类型为水表
+            if (queryMeter.getMeterCls() == null) {
+                queryMeter.setMeterCls(WATER_METER_CLS);
+            }
+
+            logger.info("查询设施小时用水汇总,区域: {}, 设施分类: {}, 子类: {}",
+                queryMeter.getAreaCode(), queryMeter.getFacsCategory(), queryMeter.getFacsSubCategory());
+
+            // 直接通过Mapper一次查询完成
+            List<WaterConsumptionVO> result = waterConsumptionMapper.selectFacsHourlyWaterSummary(queryMeter);
+
+            return result != null ? result : Collections.emptyList();
+        } catch (Exception e) {
+            logger.error("查询设施小时用水汇总异常", e);
+            return Collections.emptyList();
+        }
+    }
+
+    /**
+     * 为设施查询条件补充名称信息
+     */
+    private void enrichFacsQueryMeter(QueryMeter queryMeter) {
+        String objCode = queryMeter.getObjCode();
+        String areaCode = queryMeter.getAreaCode();
+
+        if (StringUtils.isNotBlank(objCode) && !StringUtils.equals(objCode, areaCode)
+            && !StringUtils.equals("-1", objCode)) {
+            // 查询指定设施
+            EmsFacs emsFacs = facsService.selectEmsFacsByCode(objCode);
+            if (emsFacs != null) {
+                queryMeter.setObjName(emsFacs.getFacsName());
+            }
+        } else if (StringUtils.equals("-1", areaCode)) {
+            // 全部设施
+            queryMeter.setObjCode("-1");
+            queryMeter.setObjName("全部设施");
+        } else if (StringUtils.isNotBlank(areaCode)) {
+            // 指定区域下的设施
+            Area area = areaService.selectAreaByCode(areaCode);
+            if (area != null) {
+                queryMeter.setObjCode(areaCode);
+                queryMeter.setObjName(area.getAreaName());
+            }
+        }
+    }
+
+    /**
+     * 为区域查询条件补充名称信息
+     */
+    private void enrichAreaQueryMeter(QueryMeter queryMeter) {
+        String areaCode = queryMeter.getAreaCode();
+
+        if (StringUtils.equals("-1", areaCode)) {
+            queryMeter.setObjCode("-1");
+            queryMeter.setObjName("全部区域");
+        } else if (StringUtils.isNotBlank(queryMeter.getObjCode())) {
+            Area area = areaService.selectAreaByCode(queryMeter.getObjCode());
+            if (area != null) {
+                queryMeter.setObjName(area.getAreaName());
+            }
+        }
+    }
+
+    /**
+     * 获取区域绑定的水表设备(用于小时粒度查询)
+     */
+    private Set<String> getAreaMeterDevicesForHourly(QueryMeter queryMeter) {
+        Set<String> meterDevices = new HashSet<>();
+        String areaCode = queryMeter.getAreaCode();
+
+        try {
+            // 清除分页参数
+            com.github.pagehelper.PageHelper.clearPage();
+
+            if (StringUtils.equals("-1", areaCode)) {
+                // 全部区域:获取所有区域的水表设备
+                List<String> allDevices = meterBoundaryRelService.selectMeterDevices(null, 1, WATER_METER_CLS);
+                if (CollectionUtils.isNotEmpty(allDevices)) {
+                    meterDevices.addAll(allDevices);
+                } else {
+                    // 备选方案:遍历所有区域获取设备
+                    List<Area> allAreas = areaService.selectArea(new Area());
+                    if (CollectionUtils.isNotEmpty(allAreas)) {
+                        for (Area area : allAreas) {
+                            com.github.pagehelper.PageHelper.clearPage();
+                            List<String> areaDevices = meterBoundaryRelService.selectMeterDevices(
+                                area.getAreaCode(), 1, WATER_METER_CLS);
+                            if (CollectionUtils.isNotEmpty(areaDevices)) {
+                                meterDevices.addAll(areaDevices);
+                            }
+                        }
+                    }
+                }
+            } else {
+                // 指定区域:使用objCode或areaCode
+                String targetCode = StringUtils.isNotBlank(queryMeter.getObjCode())
+                    ? queryMeter.getObjCode() : areaCode;
+
+                List<String> devices = meterBoundaryRelService.selectMeterDevices(targetCode, 1, WATER_METER_CLS);
+                if (CollectionUtils.isNotEmpty(devices)) {
+                    meterDevices.addAll(devices);
+                }
+            }
+        } catch (Exception e) {
+            logger.error("获取区域水表设备异常,区域: {}", areaCode, e);
+        } finally {
+            com.github.pagehelper.PageHelper.clearPage();
+        }
+
+        return meterDevices;
+    }
+
     /**
      * 转换为用水导出VO列表
      */

+ 198 - 4
ems/ems-core/src/main/resources/mapper/ems/ElecConsumptionMapper.xml

@@ -41,6 +41,15 @@
         <result property="createTime" column="create_time"/>
     </resultMap>
 
+    <resultMap type="com.ruoyi.ems.domain.EnergyMeter" id="EnergyMeterResult">
+        <result property="areaCode" column="area_code"/>
+        <result property="objType" column="obj_type"/>
+        <result property="objCode" column="obj_code"/>
+        <result property="objName" column="obj_name"/>
+        <result property="quantity" column="elec_quantity"/>
+        <result property="useCost" column="use_elec_cost"/>
+    </resultMap>
+
     <!-- ==================== 查询分时类型 ==================== -->
     <select id="selectElecHourSupportTypes" resultType="java.lang.String">
         SELECT
@@ -81,9 +90,9 @@
 
     <select id="selectMDevElecConsumptionSummary" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="ElecConsumptionResult">
         SELECT
-         h.area_code,
-         d.device_name as obj_name,
-         d.device_code as obj_code,
+        h.area_code,
+        d.device_name as obj_name,
+        d.device_code as obj_code,
         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,
@@ -92,7 +101,7 @@
         ROUND(SUM(CASE WHEN h.meter_type = -2 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as deep_valley_quantity,
         ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as total_elec_cost
         FROM adm_elec_meter_h h
-            LEFT JOIN adm_meter_device d ON h.device_code = d.device_code
+        LEFT JOIN adm_meter_device d ON h.device_code = d.device_code
         <where>
             <if test="deviceCode != null  and deviceCode != ''">and h.device_code = #{deviceCode}</if>
             <if test="startRecTime != null and startRecTime != ''">
@@ -413,4 +422,189 @@
             AND f.enable = 1
         </where>
     </select>
+
+    <!-- ==================== 新增:小时粒度查询SQL ==================== -->
+
+    <!--
+        区域小时用电明细查询
+    -->
+    <select id="selectAreaHourlyElecConsumptionByDevices" resultMap="ElecMeterHResult">
+        SELECT
+        #{queryMeter.objCode} as device_code,
+        #{queryMeter.objName} as device_name,
+        h.area_code,
+        h.record_time,
+        h.date,
+        h.time,
+        h.time_index,
+        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) as elec_quantity,
+        ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as use_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.areaCode != null and queryMeter.areaCode != '' and queryMeter.areaCode != '-1'">
+            AND h.area_code = #{queryMeter.areaCode}
+        </if>
+        <if test="queryMeter.startRecTime != null and queryMeter.startRecTime != ''">
+            AND h.record_time &gt;= #{queryMeter.startRecTime}
+        </if>
+        <if test="queryMeter.endRecTime != null and queryMeter.endRecTime != ''">
+            AND h.record_time &lt;= #{queryMeter.endRecTime}
+        </if>
+        GROUP BY h.date, h.time_index, h.area_code, h.record_time, h.time
+        ORDER BY h.record_time ${queryMeter.orderFlag}
+    </select>
+
+    <!--
+        设施小时用电明细查询
+    -->
+    <select id="selectFacsHourlyElecConsumption" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="ElecMeterHResult">
+        SELECT
+        <choose>
+            <when test="objCode != null and objCode != '' and objCode != areaCode and objCode != '-1'">
+                f.facs_code as device_code,
+                f.facs_name as device_name,
+            </when>
+            <otherwise>
+                #{objCode} as device_code,
+                #{objName} as device_name,
+            </otherwise>
+        </choose>
+        f.ref_area as area_code,
+        h.record_time,
+        h.date,
+        h.time,
+        h.time_index,
+        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) as elec_quantity,
+        ROUND(SUM(COALESCE(h.use_elec_cost, 0)), 2) as use_elec_cost
+        FROM adm_ems_facs f
+        INNER JOIN adm_meter_boundary_rel rel ON rel.obj_type = 2
+        AND rel.boundary_obj = f.facs_code
+        AND rel.meter_cls = 45
+        INNER JOIN adm_elec_meter_h h ON h.device_code = rel.meter_device
+        <where>
+            f.enable = 1
+            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
+                AND f.ref_area = #{areaCode}
+            </if>
+            <if test="objCode != null and objCode != '' and objCode != areaCode and objCode != '-1'">
+                AND f.facs_code = #{objCode}
+            </if>
+            <if test="facsCategory != null and facsCategory != ''">
+                AND f.facs_category = #{facsCategory}
+            </if>
+            <if test="facsSubCategory != null and facsSubCategory != ''">
+                AND f.facs_subcategory = #{facsSubCategory}
+            </if>
+            <if test="startRecTime != null and startRecTime != ''">
+                AND h.record_time &gt;= #{startRecTime}
+            </if>
+            <if test="endRecTime != null and endRecTime != ''">
+                AND h.record_time &lt;= #{endRecTime}
+            </if>
+        </where>
+        GROUP BY
+        <choose>
+            <when test="objCode != null and objCode != '' and objCode != areaCode and objCode != '-1'">
+                f.facs_code, f.facs_name, f.ref_area, h.date, h.time_index, h.record_time, h.time
+            </when>
+            <otherwise>
+                f.ref_area, h.date, h.time_index, h.record_time, h.time
+            </otherwise>
+        </choose>
+        ORDER BY h.record_time ${orderFlag}
+    </select>
+
+    <!--
+        设施小时用电汇总统计
+    -->
+    <select id="selectFacsHourlyElecSummary" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="ElecConsumptionResult">
+        SELECT
+        f.ref_area as area_code,
+        2 as obj_type,
+        f.facs_code as obj_code,
+        f.facs_name as obj_name,
+        'HOUR' 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(CASE WHEN h.meter_type = -2 THEN COALESCE(h.elec_quantity, 0) ELSE 0 END), 2) as deep_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
+        AND rel.meter_cls = #{meterCls}
+        LEFT JOIN adm_elec_meter_h h ON h.device_code = rel.meter_device
+        <where>
+            f.enable = 1
+            <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="facsSubCategory != null and facsSubCategory != ''">
+                AND f.facs_subcategory = #{facsSubCategory}
+            </if>
+            <if test="startRecTime != null and startRecTime != ''">
+                AND h.record_time &gt;= #{startRecTime}
+            </if>
+            <if test="endRecTime != null and endRecTime != ''">
+                AND h.record_time &lt;= #{endRecTime}
+            </if>
+        </where>
+        GROUP BY f.facs_code, f.facs_name, f.ref_area
+        ORDER BY f.facs_code
+    </select>
+
+    <!--
+    查询日平均用电
+    -->
+    <select id="selectElecDayAvg" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="EnergyMeterResult">
+        SELECT
+        <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
+            h.area_code,
+        </if>
+        <if test="deviceCode != null and deviceCode != ''">
+            h.device_code as obj_code,
+        </if>
+        ROUND(SUM(COALESCE(h.elec_quantity, 0)) / NULLIF(COUNT(DISTINCT h.date), 0), 2) AS elec_quantity,
+        ROUND(SUM(COALESCE(h.use_elec_cost, 0)) / NULLIF(COUNT(DISTINCT h.date), 0), 2) AS use_elec_cost
+        FROM adm_elec_meter_h h
+        <where>
+            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
+                AND h.area_code = #{areaCode}
+            </if>
+            <if test="deviceCode != null and deviceCode != ''">
+                AND h.device_code = #{deviceCode}
+            </if>
+            <if test="startRecTime != null and startRecTime != '' and endRecTime != null and endRecTime != ''">
+                AND h.date &gt;= #{startRecTime} AND h.date &lt;= #{endRecTime}
+            </if>
+        </where>
+    </select>
+
+    <!-- ==================== 按设备类型查询日用电 ==================== -->
+    <!--
+        按设备类型查询日用电
+    -->
+    <select id="selectDeviceElecByDay" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="EnergyMeterResult">
+        SELECT
+        d.device_name AS obj_name,
+        ROUND(SUM(COALESCE(h.elec_quantity, 0)), 2) AS elec_quantity
+        FROM adm_ems_device d
+        INNER JOIN adm_elec_meter_h h ON d.device_code = h.device_code
+        <where>
+            h.date &gt;= #{startRecTime}
+            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
+                AND h.area_code = #{areaCode}
+            </if>
+        </where>
+        GROUP BY d.device_name
+        ORDER BY elec_quantity DESC
+    </select>
 </mapper>

+ 0 - 336
ems/ems-core/src/main/resources/mapper/ems/ElecLoadIndex15minMapper.xml

@@ -1,336 +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.ElecLoadIndex15minMapper">
-    
-    <resultMap type="com.ruoyi.ems.domain.ElecLoadIndex" id="indexResult">
-        <result property="id"    column="id"    />
-        <result property="areaCode"    column="area_code"    />
-        <result property="areaName"    column="area_name"    />
-        <result property="areaShortName"    column="area_short_name"    />
-        <result property="objType"    column="obj_type"    />
-        <result property="objCode"    column="obj_code"    />
-        <result property="objName"    column="obj_name"    />
-        <result property="recordTime"    column="record_time"    />
-        <result property="date"    column="date"    />
-        <result property="time"    column="time"    />
-        <result property="timeIndex"    column="time_index"    />
-        <result property="ua"    column="ua"    />
-        <result property="ub"    column="ub"    />
-        <result property="uc"    column="uc"    />
-        <result property="la"    column="la"    />
-        <result property="lb"    column="lb"    />
-        <result property="lc"    column="lc"    />
-        <result property="p"    column="p"    />
-        <result property="pa"    column="pa"    />
-        <result property="pb"    column="pb"    />
-        <result property="pc"    column="pc"    />
-        <result property="q"    column="q"    />
-        <result property="qa"    column="qa"    />
-        <result property="qb"    column="qb"    />
-        <result property="qc"    column="qc"    />
-        <result property="pf"    column="pf"    />
-    </resultMap>
-
-    <sql id="selectIndexVo">
-        select id, area_code, obj_type, obj_code, record_time, `date`, `time`, time_index, ua, ub, uc, la, lb, lc, p, pa, pb, pc, q, qa, qb, qc, pf from adm_ems_elec_load_index_15min
-    </sql>
-
-    <select id="selectIndexList" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="indexResult">
-        select
-        i.obj_code,
-        i.obj_type,
-        COALESCE(a2.area_name,
-        f.facs_name,
-        d.device_name) AS obj_name,
-        f.facs_category,
-        f.facs_subcategory,
-        <if test="(facsCategory != null and facsCategory != '') or (facsSubCategory != null and facsSubCategory != '')">
-            <if test="objCode == null or objCode == ''">
-                fs.name as sub_obj_name,
-            </if>
-        </if>
-        i.record_time,
-        i.`date`,
-        i.`time`,
-        i.`time_index`,
-        sum(i.ua) as ua,
-        sum(i.ub) as ub,
-        sum(i.uc) as uc,
-        sum(i.la) as la,
-        sum(i.lb) as lb,
-        sum(i.lc) as lc,
-        sum(i.p) as p,
-        sum(i.pa) as pa,
-        sum(i.pb) as pb,
-        sum(i.pc) as pc,
-        sum(i.q) as q,
-        sum(i.qa) as qa,
-        sum(i.qb) as qb,
-        sum(i.qc) as qc,
-        sum(i.pf) as pf
-        from adm_ems_elec_load_index_15min i
-        LEFT JOIN adm_ems_facs f ON i.`obj_code` = f.`facs_code`
-        LEFT JOIN dim_ems_facs_subcategory fs ON f.`facs_subcategory` = fs.`code`
-        LEFT JOIN adm_ems_device d ON i.`obj_code` = d.`device_code`
-        LEFT JOIN adm_area a2 ON i.`obj_code` = a2.`area_code`
-        <where>
-            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">and i.area_code = #{areaCode}</if>
-            <if test="objType != null">and i.obj_type = #{objType}</if>
-            <if test="objCode != null  and objCode != ''">and i.obj_code = #{objCode}</if>
-            <if test="facsCategory != null and facsCategory != ''">and f.facs_category = #{facsCategory}</if>
-            <if test="facsSubCategory != null and facsSubCategory != ''">and f.facs_subcategory = #{facsSubCategory}
-            </if>
-            <if test="startRecTime != null and startRecTime != '' and endRecTime != null and endRecTime !=''">
-                and i.`record_time` &gt;= #{startRecTime} and i.`record_time` &lt;= #{endRecTime}
-            </if>
-            <if test="date != null">
-                and i.`date` &gt;= #{date}
-            </if>
-        </where>
-        GROUP BY i.`record_time`
-        ORDER BY i.`record_time` desc
-    </select>
-    <select id="selectIndexDetailList" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="indexResult">
-        select
-        <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
-            i.area_code,
-            a.area_name,
-            a.short_name as area_short_name,
-        </if>
-        <if test="objCode != null and objCode != ''">
-            i.obj_code,
-            CASE
-            WHEN i.obj_type = 1 THEN a2.area_name
-            WHEN i.obj_type = 2 THEN f.facs_name
-            WHEN i.obj_type = 3 THEN d.device_name
-            END as obj_name,
-        </if>
-        <if test="(facsCategory != null and facsCategory != '') or (facsSubCategory != null and facsSubCategory != '')">
-            fa.facs_category,
-            fa.facs_subcategory,
-            <if test="objCode == null or objCode == ''">
-                fs.name as obj_name,
-            </if>
-        </if>
-        i.record_time,
-        i.`date`,
-        i.`time`,
-        i.`time_index`,
-        sum(i.ua) as ua,
-        sum(i.ub) as ub,
-        sum(i.uc) as uc,
-        sum(i.la) as la,
-        sum(i.lb) as lb,
-        sum(i.lc) as lc,
-        sum(i.p) as p,
-        sum(i.pa) as pa,
-        sum(i.pb) as pb,
-        sum(i.pc) as pc,
-        sum(i.q) as q,
-        sum(i.qa) as qa,
-        sum(i.qb) as qb,
-        sum(i.qc) as qc,
-        sum(i.pf) as pf
-        from adm_ems_elec_load_index_15min i
-        <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
-            LEFT JOIN adm_area a ON i.`area_code` = a.`area_code`
-        </if>
-        <if test="objCode != null and objCode != ''">
-            LEFT JOIN adm_ems_facs f ON i.`obj_code` = f.`facs_code`
-            LEFT JOIN adm_ems_device d ON i.`obj_code` = d.`device_code`
-            LEFT JOIN adm_ems_area a2 ON i.`obj_code` = a2.`area_code`
-        </if>
-        <if test="(facsCategory != null  and facsCategory != '') or (facsSubCategory != null  and facsSubCategory != '')">
-            LEFT JOIN adm_ems_facs fa ON i.`obj_code` = fa.`facs_code`
-            <if test="objCode == null or objCode == ''">
-                LEFT JOIN dim_ems_facs_subcategory fs ON fa.`facs_subcategory` = fs.`code`
-            </if>
-        </if>
-        <where>
-            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">and i.area_code = #{areaCode}</if>
-            <if test="objType != null">and i.obj_type = #{objType}</if>
-            <if test="objCode != null  and objCode != ''">and i.obj_code = #{objCode}</if>
-            <if test="facsCategory != null and facsCategory != ''">and fa.facs_category = #{facsCategory}</if>
-            <if test="facsSubCategory != null and facsSubCategory != ''">and fa.facs_subcategory = #{facsSubCategory}</if>
-            <if test="startRecTime != null and startRecTime != '' and endRecTime != null and endRecTime !=''">
-                and i.`record_time` &gt;= #{startRecTime} and i.`record_time` &lt;= #{endRecTime}
-            </if>
-        </where>
-    </select>
-    <select id="selectIndexMaxLoad" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="indexResult">
-        SELECT
-            MAX(t.total_p) AS p,
-            MAX(t.total_q) AS q
-        FROM (
-            SELECT
-             i.`date` as date_part,
-             i.`time` as time_part,
-             SUM(p) AS total_p,
-             SUM(q) AS total_q
-            FROM
-        adm_ems_elec_load_index_15min i
-        <if test="(facsCategory != null  and facsCategory != '') or (facsSubCategory != null  and facsSubCategory != '')">
-            LEFT JOIN adm_ems_facs fa ON i.`obj_code` = fa.`facs_code`
-            <if test="objCode == null or objCode == ''">
-                LEFT JOIN dim_ems_facs_subcategory fs ON fa.`facs_subcategory` = fs.`code`
-            </if>
-        </if>
-        <where>
-            <if test="areaCode != null  and areaCode != '' and areaCode != '-1'">and i.area_code = #{areaCode}</if>
-            <if test="objType != null">and i.obj_type = #{objType}</if>
-            <if test="objCode != null  and objCode != ''">and i.obj_code = #{objCode}</if>
-            <if test="facsCategory != null and facsCategory != ''">and fa.facs_category = #{facsCategory}</if>
-            <if test="facsSubCategory != null and facsSubCategory != ''">and fa.facs_subcategory = #{facsSubCategory}</if>
-            <if test="startRecTime != null and startRecTime != '' and endRecTime != null and endRecTime !=''">
-                and i.`record_time` BETWEEN  #{startRecTime} and #{endRecTime}
-            </if>
-        </where>
-        GROUP BY
-            i.`date`,
-            i.`time`) t
-    </select>
-
-    <select id="selectDayIndexMaxLoad" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="indexResult">
-        SELECT
-            t.date_part as `date`,
-            MAX(t.total_p) AS p,
-            MAX(t.total_q) AS q
-        FROM (
-             SELECT
-               DATE(record_time) AS date_part,
-               SUM(p) AS total_p,
-               SUM(q) AS total_q
-            FROM
-        adm_ems_elec_load_index_15min i
-        <if test="(facsCategory != null  and facsCategory != '') or (facsSubCategory != null  and facsSubCategory != '')">
-            LEFT JOIN adm_ems_facs fa ON i.`obj_code` = fa.`facs_code`
-            <if test="objCode == null or objCode == ''">
-                LEFT JOIN dim_ems_facs_subcategory fs ON fa.`facs_subcategory` = fs.`code`
-            </if>
-        </if>
-        <where>
-            <if test="areaCode != null  and areaCode != '' and areaCode != '-1'">and i.area_code = #{areaCode}</if>
-            <if test="objType != null">and i.obj_type = #{objType}</if>
-            <if test="objCode != null  and objCode != ''">and i.obj_code = #{objCode}</if>
-            <if test="facsCategory != null and facsCategory != ''">and fa.facs_category = #{facsCategory}</if>
-            <if test="facsSubCategory != null and facsSubCategory != ''">and fa.facs_subcategory = #{facsSubCategory}</if>
-            <if test="startRecTime != null and startRecTime != '' and endRecTime != null and endRecTime !=''">
-                and i.`date` between #{startRecTime} and #{endRecTime}
-            </if>
-        </where>
-        GROUP BY
-            i.`date`,
-            i.`time`
-            ) AS t
-        GROUP BY
-            date_part
-        ORDER BY
-            date_part
-    </select>
-
-    <select id="selectIndexById" parameterType="Long" resultMap="indexResult">
-        <include refid="selectIndexVo"/>
-        where id = #{id}
-    </select>
-
-    <select id="selectNewIndex" resultMap="indexResult">
-        <include refid="selectIndexVo"/>
-        where area_code = #{areaCode} and obj_type = #{objType} and obj_code = #{objCode}
-        order by record_time
-        desc limit 1
-    </select>
-        
-    <insert id="insertIndex" parameterType="com.ruoyi.ems.domain.ElecLoadIndex" useGeneratedKeys="true" keyProperty="id">
-        insert into adm_ems_elec_load_index_15min
-        <trim prefix="(" suffix=")" suffixOverrides=",">
-            <if test="areaCode != null and areaCode != ''">area_code,</if>
-            <if test="objType != null">obj_type,</if>
-            <if test="objCode != null and objCode != ''">obj_code,</if>
-            <if test="recordTime != null">record_time,</if>
-            <if test="date != null">`date`,</if>
-            <if test="time != null">`time`,</if>
-            <if test="timeIndex != null">time_index,</if>
-            <if test="ua != null">ua,</if>
-            <if test="ub != null">ub,</if>
-            <if test="uc != null">uc,</if>
-            <if test="la != null">la,</if>
-            <if test="lb != null">lb,</if>
-            <if test="lc != null">lc,</if>
-            <if test="p != null">p,</if>
-            <if test="pa != null">pa,</if>
-            <if test="pb != null">pb,</if>
-            <if test="pc != null">pc,</if>
-            <if test="q != null">q,</if>
-            <if test="qa != null">qa,</if>
-            <if test="qb != null">qb,</if>
-            <if test="qc != null">qc,</if>
-            <if test="pf != null">pf,</if>
-         </trim>
-        <trim prefix="values (" suffix=")" suffixOverrides=",">
-            <if test="areaCode != null and areaCode != ''">#{areaCode},</if>
-            <if test="objType != null">#{objType},</if>
-            <if test="objCode != null and objCode != ''">#{objCode},</if>
-            <if test="recordTime != null">#{recordTime},</if>
-            <if test="date != null">#{date},</if>
-            <if test="time != null">#{time},</if>
-            <if test="timeIndex != null">#{timeIndex},</if>
-            <if test="ua != null">#{ua},</if>
-            <if test="ub != null">#{ub},</if>
-            <if test="uc != null">#{uc},</if>
-            <if test="la != null">#{la},</if>
-            <if test="lb != null">#{lb},</if>
-            <if test="lc != null">#{lc},</if>
-            <if test="p != null">#{p},</if>
-            <if test="pa != null">#{pa},</if>
-            <if test="pb != null">#{pb},</if>
-            <if test="pc != null">#{pc},</if>
-            <if test="q != null">#{q},</if>
-            <if test="qa != null">#{qa},</if>
-            <if test="qb != null">#{qb},</if>
-            <if test="qc != null">#{qc},</if>
-            <if test="pf != null">#{pf},</if>
-         </trim>
-    </insert>
-
-    <update id="updateIndex" parameterType="com.ruoyi.ems.domain.ElecLoadIndex">
-        update adm_ems_elec_load_index_15min
-        <trim prefix="SET" suffixOverrides=",">
-            <if test="areaCode != null and areaCode != ''">area_code = #{areaCode},</if>
-            <if test="objType != null">obj_type = #{objType},</if>
-            <if test="objCode != null and objCode != ''">obj_code = #{objCode},</if>
-            <if test="recordTime != null">record_time = #{recordTime},</if>
-            <if test="date != null">`date` = #{date},</if>
-            <if test="time != null">`time` = #{time},</if>
-            <if test="timeIndex != null">time_index = #{timeIndex},</if>
-            <if test="ua != null">ua = #{ua},</if>
-            <if test="ub != null">ub = #{ub},</if>
-            <if test="uc != null">uc = #{uc},</if>
-            <if test="la != null">la = #{la},</if>
-            <if test="lb != null">lb = #{lb},</if>
-            <if test="lc != null">lc = #{lc},</if>
-            <if test="p != null">p = #{p},</if>
-            <if test="pa != null">pa = #{pa},</if>
-            <if test="pb != null">pb = #{pb},</if>
-            <if test="pc != null">pc = #{pc},</if>
-            <if test="q != null">q = #{q},</if>
-            <if test="qa != null">qa = #{qa},</if>
-            <if test="qb != null">qb = #{qb},</if>
-            <if test="qc != null">qc = #{qc},</if>
-            <if test="pf != null">pf = #{pf},</if>
-        </trim>
-        where id = #{id}
-    </update>
-
-    <delete id="deleteIndexById" parameterType="Long">
-        delete from adm_ems_elec_load_index_15min where id = #{id}
-    </delete>
-
-    <delete id="deleteIndexByIds" parameterType="String">
-        delete from adm_ems_elec_load_index_15min where id in
-        <foreach item="id" collection="array" open="(" separator="," close=")">
-            #{id}
-        </foreach>
-    </delete>
-</mapper>

+ 0 - 47
ems/ems-core/src/main/resources/mapper/ems/ElecMeterHMapper.xml

@@ -47,30 +47,6 @@
         from adm_elec_meter_h
     </sql>
 
-    <select id="selectElecMeterByDevs" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="ElecMeterHResult">
-        select
-        '${objCode}' as device_code,
-        '${objName}' as device_name,
-        m.area_code, m.record_time, m.`date`, m.`time`, m.time_index,
-        round(sum(m.elec_quantity),2) as elec_quantity,
-        round(sum(m.use_elec_cost),2) as use_elec_cost
-        from adm_elec_meter_h m
-        <where>
-            <if test="areaCode != null and areaCode != '-1'">
-                and m.area_code = #{areaCode}
-            </if>
-            <if test="startRecTime != null and startRecTime != '' and endRecTime != null and endRecTime != ''">
-                and m.record_time between #{startRecTime} and #{endRecTime}
-            </if>
-            and m.device_code in
-            <foreach item="item" index="index" collection="deviceCodes" open="(" separator=", " close=")">
-                #{item}
-            </foreach>
-        </where>
-        GROUP BY m.`date`, m.time_index
-        ORDER BY m.record_time ${orderFlag}
-    </select>
-
     <select id="selectElecMeterDayList" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="ElecMeterHResult">
         SELECT
         <if test="areaCode != null and areaCode !='' and areaCode !='-1'">
@@ -103,29 +79,6 @@
         ORDER BY record_time desc limit 1
     </select>
 
-    <select id="selectElecMeterSumByDev" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="ElecMeterResult">
-        select
-        area_code,
-        '${objType}' as obj_type,
-        '${objCode}' as obj_code,
-        '${objName}' as obj_name,
-        ROUND(SUM(m.elec_quantity),1) as elec_quantity,
-        ROUND(SUM(m.use_elec_cost),2) as use_elec_cost
-        from adm_elec_meter_h m
-        <where>
-            <if test="areaCode != null and areaCode != '-1'">
-                and m.area_code = #{areaCode}
-            </if>
-            <if test="startRecTime != null and startRecTime != '' and endRecTime != null and endRecTime != ''">
-                and m.record_time between #{startRecTime} and #{endRecTime}
-            </if>
-            and m.device_code in
-            <foreach item="item" index="index" collection="deviceCodes" open="(" separator=", " close=")">
-                #{item}
-            </foreach>
-        </where>
-    </select>
-
     <select id="selectElecDayAvg" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="ElecMeterResult">
         select
         <if test="areaCode != null and areaCode != '' and areaCode != '-1'">

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

@@ -345,4 +345,135 @@
             AND f.enable = 1
         </where>
     </select>
+
+    <!--
+       区域小时用水明细查询
+   -->
+    <select id="selectAreaHourlyWaterConsumptionByDevices" resultMap="WaterMeterHResult">
+        SELECT
+        #{queryMeter.objCode} as device_code,
+        #{queryMeter.objName} as device_name,
+        h.area_code,
+        h.record_time,
+        h.date,
+        h.time,
+        h.time_index,
+        ROUND(SUM(COALESCE(h.water_quantity, 0)), 2) as water_quantity,
+        ROUND(SUM(COALESCE(h.use_water_cost, 0)), 2) as use_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.areaCode != null and queryMeter.areaCode != '' and queryMeter.areaCode != '-1'">
+            AND h.area_code = #{queryMeter.areaCode}
+        </if>
+        <if test="queryMeter.startRecTime != null and queryMeter.startRecTime != ''">
+            AND h.record_time &gt;= #{queryMeter.startRecTime}
+        </if>
+        <if test="queryMeter.endRecTime != null and queryMeter.endRecTime != ''">
+            AND h.record_time &lt;= #{queryMeter.endRecTime}
+        </if>
+        GROUP BY h.date, h.time_index, h.area_code, h.record_time, h.time
+        ORDER BY h.record_time ${queryMeter.orderFlag}
+    </select>
+
+    <!--
+        设施小时用水明细查询
+    -->
+    <select id="selectFacsHourlyWaterConsumption" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="WaterMeterHResult">
+        SELECT
+        <choose>
+            <when test="objCode != null and objCode != '' and objCode != areaCode and objCode != '-1'">
+                f.facs_code as device_code,
+                f.facs_name as device_name,
+            </when>
+            <otherwise>
+                #{objCode} as device_code,
+                #{objName} as device_name,
+            </otherwise>
+        </choose>
+        f.ref_area as area_code,
+        h.record_time,
+        h.date,
+        h.time,
+        h.time_index,
+        ROUND(SUM(COALESCE(h.water_quantity, 0)), 2) as water_quantity,
+        ROUND(SUM(COALESCE(h.use_water_cost, 0)), 2) as use_water_cost
+        FROM adm_ems_facs f
+        INNER JOIN adm_meter_boundary_rel rel ON rel.obj_type = 2
+        AND rel.boundary_obj = f.facs_code
+        AND rel.meter_cls = 70
+        INNER JOIN adm_water_meter_h h ON h.device_code = rel.meter_device
+        <where>
+            f.enable = 1
+            <if test="areaCode != null and areaCode != '' and areaCode != '-1'">
+                AND f.ref_area = #{areaCode}
+            </if>
+            <if test="objCode != null and objCode != '' and objCode != areaCode and objCode != '-1'">
+                AND f.facs_code = #{objCode}
+            </if>
+            <if test="facsCategory != null and facsCategory != ''">
+                AND f.facs_category = #{facsCategory}
+            </if>
+            <if test="facsSubCategory != null and facsSubCategory != ''">
+                AND f.facs_subcategory = #{facsSubCategory}
+            </if>
+            <if test="startRecTime != null and startRecTime != ''">
+                AND h.record_time &gt;= #{startRecTime}
+            </if>
+            <if test="endRecTime != null and endRecTime != ''">
+                AND h.record_time &lt;= #{endRecTime}
+            </if>
+        </where>
+        GROUP BY
+        <choose>
+            <when test="objCode != null and objCode != '' and objCode != areaCode and objCode != '-1'">
+                f.facs_code, f.facs_name, f.ref_area, h.date, h.time_index, h.record_time, h.time
+            </when>
+            <otherwise>
+                f.ref_area, h.date, h.time_index, h.record_time, h.time
+            </otherwise>
+        </choose>
+        ORDER BY h.record_time ${orderFlag}
+    </select>
+
+    <!--
+        设施小时用水汇总统计
+    -->
+    <select id="selectFacsHourlyWaterSummary" parameterType="com.ruoyi.ems.model.QueryMeter" resultMap="WaterConsumptionResult">
+        SELECT
+        f.ref_area as area_code,
+        2 as obj_type,
+        f.facs_code as obj_code,
+        f.facs_name as obj_name,
+        'HOUR' 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
+        AND rel.meter_cls = #{meterCls}
+        LEFT JOIN adm_water_meter_h h ON h.device_code = rel.meter_device
+        <where>
+            f.enable = 1
+            <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="facsSubCategory != null and facsSubCategory != ''">
+                AND f.facs_subcategory = #{facsSubCategory}
+            </if>
+            <if test="startRecTime != null and startRecTime != ''">
+                AND h.record_time &gt;= #{startRecTime}
+            </if>
+            <if test="endRecTime != null and endRecTime != ''">
+                AND h.record_time &lt;= #{endRecTime}
+            </if>
+        </where>
+        GROUP BY f.facs_code, f.facs_name, f.ref_area
+        ORDER BY f.facs_code
+    </select>
 </mapper>

+ 0 - 34
ems/sql/ems_server.sql

@@ -1781,40 +1781,6 @@ CREATE TABLE adm_charging_meter_h (
 ) ENGINE=InnoDB AUTO_INCREMENT=1 COMMENT='充电计量表-分时';
 
 -- ----------------------------
--- 电力负荷设施指标表
--- ----------------------------
-drop table if exists adm_ems_elec_load_index_15min;
-create table adm_ems_elec_load_index_15min (
-  `id`                        bigint(20)      not null auto_increment      comment '序号',
-  `area_code`                 varchar(32)     not null                     comment '园区代码',
-  `obj_type`                  int             not null                     comment '对象类型',
-  `obj_code`                  varchar(64)     not null                     comment '对象编码',
-  `record_time`               timestamp       not null                     comment '记录时间',
-  `date`                      date            not null                     comment '日期 yyyy-MM-dd',
-  `time`                      time            not null                     comment '时间 HH:mm:ss',
-  `time_index`                int             not null                     comment '事件序列',
-  `ua`                        double          default null                 comment '电压 单位:V(伏)',
-  `ub`                        double          default null                 comment '电压 单位:V(伏)',
-  `uc`                        double          default null                 comment '电压 单位:V(伏)',
-  `la`                        double          default null                 comment '电流 单位:A(伏)',
-  `lb`                        double          default null                 comment '电流 单位:A(伏)',
-  `lc`                        double          default null                 comment '电流 单位:A(伏)',
-  `p`                         double          default null                 comment '有功总功率',
-  `pa`                        double          default null                 comment 'A相有功功率',
-  `pb`                        double          default null                 comment 'B相有功功率',
-  `pc`                        double          default null                 comment 'C相有功功率',
-  `q`                         double          default null                 comment '无功总功率',
-  `qa`                        double          default null                 comment 'A相无功总功率',
-  `qb`                        double          default null                 comment 'B相无功总功率',
-  `qc`                        double          default null                 comment 'C相无功总功率',
-  `pf`                        double          default null                 comment '功率因素',
-  primary key (`id`),
-  unique key ux_ems_elec_load_index(`area_code`, `obj_type`, `obj_code`, `record_time`),
-  key ux_ems_elec_load_index_date(`date`)
-) engine=innodb auto_increment=1 comment = '电力负荷设施15分钟指标表';
-
-
--- ----------------------------
 -- 电力产能预测表
 -- ----------------------------
 drop table if exists adm_ems_elec_prod_forecast;