浏览代码

Merge branch 'fu-dev' of hanzhengyi/usky-power into master

fuyuchuan 1 天之前
父节点
当前提交
7001675585
共有 34 个文件被更改,包括 1471 次插入388 次删除
  1. 19 2
      fiveep-controller/src/main/java/com/bizmatics/controller/web/DeviceController.java
  2. 32 8
      fiveep-controller/src/main/java/com/bizmatics/controller/web/HtAnalogDataController.java
  3. 6 6
      fiveep-controller/src/main/java/com/bizmatics/controller/web/SiteController.java
  4. 25 0
      fiveep-controller/src/main/java/com/bizmatics/controller/web/StarMarkingEquipmentController.java
  5. 2 2
      fiveep-controller/src/main/resources/application-dev.properties
  6. 5 2
      fiveep-controller/src/main/resources/application-prod.properties
  7. 1 1
      fiveep-controller/src/main/resources/application.properties
  8. 3 0
      fiveep-model/src/main/java/com/bizmatics/model/DeviceList.java
  9. 4 3
      fiveep-model/src/main/java/com/bizmatics/model/RtAnalogData.java
  10. 9 2
      fiveep-model/src/main/java/com/bizmatics/model/Site.java
  11. 30 1
      fiveep-model/src/main/java/com/bizmatics/model/SiteElectricityRecord.java
  12. 4 1
      fiveep-persistence/src/main/java/com/bizmatics/persistence/mapper/DeviceMapper.java
  13. 3 1
      fiveep-persistence/src/main/java/com/bizmatics/persistence/mapper/HtAnalogDataMapper.java
  14. 2 0
      fiveep-persistence/src/main/java/com/bizmatics/persistence/mapper/RtAnalogDataMapper.java
  15. 41 10
      fiveep-persistence/src/main/resources/mapper/mysql/DeviceMapper.xml
  16. 6 3
      fiveep-persistence/src/main/resources/mapper/mysql/HtAnalogDataMapper.xml
  17. 92 80
      fiveep-persistence/src/main/resources/mapper/mysql/RtAnalogDataMapper.xml
  18. 16 0
      fiveep-service/pom.xml
  19. 4 2
      fiveep-service/src/main/java/com/bizmatics/service/DeviceService.java
  20. 28 5
      fiveep-service/src/main/java/com/bizmatics/service/HtAnalogDataService.java
  21. 8 4
      fiveep-service/src/main/java/com/bizmatics/service/RtAnalogDataService.java
  22. 3 1
      fiveep-service/src/main/java/com/bizmatics/service/SiteService.java
  23. 40 39
      fiveep-service/src/main/java/com/bizmatics/service/impl/DeviceServiceImpl.java
  24. 598 5
      fiveep-service/src/main/java/com/bizmatics/service/impl/HtAnalogDataServiceImpl.java
  25. 52 50
      fiveep-service/src/main/java/com/bizmatics/service/impl/RtAnalogDataServiceImpl.java
  26. 144 139
      fiveep-service/src/main/java/com/bizmatics/service/impl/SiteServiceImpl.java
  27. 46 20
      fiveep-service/src/main/java/com/bizmatics/service/job/SiteDailyElectricityCostTask.java
  28. 44 0
      fiveep-service/src/main/java/com/bizmatics/service/vo/ElectricityTrendRequestVO.java
  29. 27 0
      fiveep-service/src/main/java/com/bizmatics/service/vo/ElectricityTrendResponseVO.java
  30. 41 0
      fiveep-service/src/main/java/com/bizmatics/service/vo/ElectricityTrendVO.java
  31. 6 0
      fiveep-service/src/main/java/com/bizmatics/service/vo/SiteLoadAnalysisVO.java
  32. 53 0
      fiveep-service/src/main/java/com/bizmatics/service/vo/TimeSharingElectricityRequestVO.java
  33. 76 0
      fiveep-service/src/main/java/com/bizmatics/service/vo/TimeSharingElectricityResponseVO.java
  34. 1 1
      pom.xml

+ 19 - 2
fiveep-controller/src/main/java/com/bizmatics/controller/web/DeviceController.java

@@ -68,6 +68,23 @@ public class DeviceController {
         return ApiResult.success(deviceService.deviceList(siteId));
         return ApiResult.success(deviceService.deviceList(siteId));
     }
     }
 
 
+    /**
+     * 分时用电-设备分页列表查询
+     *
+     * @param siteId     站点ID
+     * @param deviceType 设备类型 默认1、支路设备(183 用电设备), 2、分路设备(171、173用电设备)
+     * @param pageNum    页数
+     * @param pageSize   条数
+     * @return
+     */
+    @GetMapping("list")
+    public ApiResult<List<DeviceList>> branch(@RequestParam(value = "siteId") int siteId,
+                                              @RequestParam(value = "deviceType", required = false, defaultValue = "1") int deviceType,
+                                              @RequestParam(value = "pageNum", required = false, defaultValue = "1") int pageNum,
+                                              @RequestParam(value = "pageSize", required = false, defaultValue = "20") int pageSize) {
+        return ApiResult.success(deviceService.deviceBranch(siteId, deviceType, pageNum, pageSize));
+    }
+
 
 
     /**
     /**
      * 数据管理-同比分析报表-右侧设备查询
      * 数据管理-同比分析报表-右侧设备查询
@@ -242,7 +259,7 @@ public class DeviceController {
      */
      */
     @Log(title = "设备管理-通信设备", businessType = BusinessType.IMPORT)
     @Log(title = "设备管理-通信设备", businessType = BusinessType.IMPORT)
     @PostMapping("/deviceImport")
     @PostMapping("/deviceImport")
-    public ApiResult<Void> deviceImport(@RequestParam("file") MultipartFile file){
+    public ApiResult<Void> deviceImport(@RequestParam("file") MultipartFile file) {
         deviceService.deviceImport(file);
         deviceService.deviceImport(file);
         return ApiResult.success();
         return ApiResult.success();
     }
     }
@@ -253,7 +270,7 @@ public class DeviceController {
      * @return
      * @return
      */
      */
     @GetMapping("deviceBoxList")
     @GetMapping("deviceBoxList")
-    public ApiResult<List<DeviceOneVo>> deviceBoxList(@RequestParam (required = false) Integer siteId) {
+    public ApiResult<List<DeviceOneVo>> deviceBoxList(@RequestParam(required = false) Integer siteId) {
         return ApiResult.success(deviceService.deviceBoxList(siteId));
         return ApiResult.success(deviceService.deviceBoxList(siteId));
     }
     }
 
 

+ 32 - 8
fiveep-controller/src/main/java/com/bizmatics/controller/web/HtAnalogDataController.java

@@ -1,7 +1,7 @@
 package com.bizmatics.controller.web;
 package com.bizmatics.controller.web;
 
 
-
 import com.bizmatics.common.core.bean.ApiResult;
 import com.bizmatics.common.core.bean.ApiResult;
+import com.bizmatics.common.core.bean.CommonPage;
 import com.bizmatics.model.vo.DataManagementOneVO;
 import com.bizmatics.model.vo.DataManagementOneVO;
 import com.bizmatics.model.vo.HtAnalogEnergyConsumptionVo;
 import com.bizmatics.model.vo.HtAnalogEnergyConsumptionVo;
 import com.bizmatics.model.vo.HtAnalogEnergySegmentedVo;
 import com.bizmatics.model.vo.HtAnalogEnergySegmentedVo;
@@ -9,19 +9,16 @@ import com.bizmatics.model.vo.SingleLoopReportOneVo;
 import com.bizmatics.service.HtAnalogDataService;
 import com.bizmatics.service.HtAnalogDataService;
 import com.bizmatics.service.aop.BusinessType;
 import com.bizmatics.service.aop.BusinessType;
 import com.bizmatics.service.aop.Log;
 import com.bizmatics.service.aop.Log;
-import com.bizmatics.service.vo.CommonIcoVO;
-import com.bizmatics.service.vo.HadCountVO;
-import com.bizmatics.service.vo.RealScoreVO;
-import com.bizmatics.service.vo.TimeShareVO;
+import com.bizmatics.service.vo.*;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.format.annotation.DateTimeFormat;
 import org.springframework.format.annotation.DateTimeFormat;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 
 
-import java.time.LocalDate;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.URLEncoder;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.time.temporal.ChronoUnit;
 import java.util.Date;
 import java.util.Date;
 import java.util.List;
 import java.util.List;
 
 
@@ -259,5 +256,32 @@ public class HtAnalogDataController {
         }
         }
         return ApiResult.success(htAnalogDataService.getSegmentedData(siteId, queryPeriod, queryTime, queryType));
         return ApiResult.success(htAnalogDataService.getSegmentedData(siteId, queryPeriod, queryTime, queryType));
     }
     }
+
+    /**
+     * 时间分时电量、电费-表格统计
+     * @param request 请求参数
+     * @return 响应
+     */
+    @PostMapping("page")
+    public ApiResult<CommonPage<TimeSharingElectricityResponseVO>> timeSharingElectricity(@RequestBody TimeSharingElectricityRequestVO request) {
+        return ApiResult.success(htAnalogDataService.timeSharingElectricity(request));
+    }
+
+    /**
+     * 分时用电-电量趋势
+     * @param trendVO 请求参数
+     * @return 响应
+     */
+    @PostMapping("trend")
+    public ApiResult<List<ElectricityTrendResponseVO>> trend(@RequestBody ElectricityTrendRequestVO trendVO) {
+        return ApiResult.success(htAnalogDataService.trend(trendVO));
+    }
+
+    @PostMapping("export")
+    public void export(@RequestBody TimeSharingElectricityRequestVO request, HttpServletResponse response) throws IOException {
+        htAnalogDataService.export(request, response);
+
+    }
+
 }
 }
 
 

+ 6 - 6
fiveep-controller/src/main/java/com/bizmatics/controller/web/SiteController.java

@@ -174,15 +174,15 @@ public class SiteController {
     /**
     /**
      * 站点管理-基础信息-站点负载分析
      * 站点管理-基础信息-站点负载分析
      * @param siteId 站点ID
      * @param siteId 站点ID
-     * @param pageNum 页码
-     * @param pageSize 每页数量
+     * @param startTime 开始时间
+     * @param endTime 结束时间
      * @return 负载分析数据
      * @return 负载分析数据
      */
      */
     @GetMapping("siteLoadAnalysis")
     @GetMapping("siteLoadAnalysis")
-    public ApiResult<CommonPage<SiteLoadAnalysisVO>> siteLoadAnalysis(@RequestParam(value = "siteId") Integer siteId,
-                                                                      @RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
-                                                                      @RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize) {
-        return ApiResult.success(siteService.siteLoadAnalysis(siteId, pageNum, pageSize));
+    public ApiResult<List<SiteLoadAnalysisVO>> siteLoadAnalysis(@RequestParam(value = "siteId") Integer siteId,
+                                                                    @RequestParam(value = "startTime", required = false) String startTime,
+                                                                    @RequestParam(value = "endTime", required = false) String endTime) {
+        return ApiResult.success(siteService.siteLoadAnalysis(siteId, startTime, endTime));
     }
     }
 }
 }
 
 

+ 25 - 0
fiveep-controller/src/main/java/com/bizmatics/controller/web/StarMarkingEquipmentController.java

@@ -0,0 +1,25 @@
+package com.bizmatics.controller.web;
+
+import com.bizmatics.persistence.mapper.HtAnalogDataMapper;
+import com.bizmatics.service.HtAnalogDataService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ *
+ * @author fyc
+ * @email yuchuan.fu@chinausky.com
+ * @date 2025/9/4
+ */
+@RestController
+@RequestMapping("/starMarkingEquipment")
+public class StarMarkingEquipmentController {
+    @Autowired
+    private HtAnalogDataService htAnalogDataService;
+    @Autowired
+    private HtAnalogDataMapper htAnalogDataMapper;
+
+    // @RequestMapping("/powerLevel")
+    // public
+}

+ 2 - 2
fiveep-controller/src/main/resources/application-dev.properties

@@ -19,10 +19,10 @@ spring.autoconfigure.exclude=com.alibaba.druid.spring.boot.autoconfigure.DruidDa
 spring.datasource.dynamic.primary=usky-power
 spring.datasource.dynamic.primary=usky-power
 #spring.datasource.dynamic.datasource.usky-power.url=jdbc:mysql://usky-cloud-mysql:3306/usky-electricity?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8
 #spring.datasource.dynamic.datasource.usky-power.url=jdbc:mysql://usky-cloud-mysql:3306/usky-electricity?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8
 #spring.datasource.dynamic.datasource.usky-power.url=jdbc:mysql://dianli.usky.cn:3306/usky-electricity?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8
 #spring.datasource.dynamic.datasource.usky-power.url=jdbc:mysql://dianli.usky.cn:3306/usky-electricity?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8
-#spring.datasource.dynamic.datasource.usky-power.url=jdbc:mysql://101.133.214.75:3306/usky-electricity?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8
+spring.datasource.dynamic.datasource.usky-power.url=jdbc:mysql://101.133.214.75:3306/usky-electricity?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8
 spring.datasource.dynamic.datasource.usky-power.username=usky
 spring.datasource.dynamic.datasource.usky-power.username=usky
 spring.datasource.dynamic.datasource.usky-power.password=Yt#75Usky
 spring.datasource.dynamic.datasource.usky-power.password=Yt#75Usky
-spring.datasource.dynamic.druid.initial-size=5                                                                       
+spring.datasource.dynamic.druid.initial-size=5
 spring.datasource.dynamic.druid.min-idle=5
 spring.datasource.dynamic.druid.min-idle=5
 spring.datasource.dynamic.druid.max-active=30
 spring.datasource.dynamic.druid.max-active=30
 spring.datasource.dynamic.druid.max-wait=60000
 spring.datasource.dynamic.druid.max-wait=60000

+ 5 - 2
fiveep-controller/src/main/resources/application-prod.properties

@@ -14,11 +14,14 @@ mybatis-plus.configuration.defaultStatementTimeout=3
 mybatis.refresh.enabled=true
 mybatis.refresh.enabled=true
 mybatis.refresh.delay-seconds=10
 mybatis.refresh.delay-seconds=10
 mybatis.refresh.sleep-seconds=20
 mybatis.refresh.sleep-seconds=20
+# SQL日志打印
+mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
 # datasource
 # datasource
 spring.autoconfigure.exclude=com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
 spring.autoconfigure.exclude=com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
 spring.datasource.dynamic.primary=usky-power
 spring.datasource.dynamic.primary=usky-power
-spring.datasource.dynamic.datasource.usky-power.url=jdbc:mysql://usky-cloud-mysql:3306/usky-electricity?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8
+#spring.datasource.dynamic.datasource.usky-power.url=jdbc:mysql://usky-cloud-mysql:3306/usky-electricity?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8
 #spring.datasource.dynamic.datasource.usky-power.url=jdbc:mysql://101.133.214.75:3306/usky-electricity?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8
 #spring.datasource.dynamic.datasource.usky-power.url=jdbc:mysql://101.133.214.75:3306/usky-electricity?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8
+spring.datasource.dynamic.datasource.usky-power.url=jdbc:mysql://101.133.214.75:3306/usky-electricity?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
 spring.datasource.dynamic.datasource.usky-power.username=usky
 spring.datasource.dynamic.datasource.usky-power.username=usky
 spring.datasource.dynamic.datasource.usky-power.password=Yt#75Usky
 spring.datasource.dynamic.datasource.usky-power.password=Yt#75Usky
 spring.datasource.dynamic.druid.initial-size=5
 spring.datasource.dynamic.druid.initial-size=5
@@ -73,7 +76,7 @@ spring.cache.ehcache.config=classpath:ehcache.xml
 # redis
 # redis
 spring.cache.redis.enabled=true
 spring.cache.redis.enabled=true
 spring.redis.database=0
 spring.redis.database=0
-spring.redis.host=usky-cloud-redist 
+spring.redis.host=usky-cloud-redis
 spring.redis.port=6379
 spring.redis.port=6379
 spring.redis.password=123456
 spring.redis.password=123456
 spring.redis.timeout=10000
 spring.redis.timeout=10000

+ 1 - 1
fiveep-controller/src/main/resources/application.properties

@@ -1,5 +1,5 @@
 # common
 # common
-spring.profiles.active=test
+spring.profiles.active=prod
 spring.application.name=usky-power
 spring.application.name=usky-power
 spring.main.banner-mode=off
 spring.main.banner-mode=off
 mybatis-plus.global-config.banner=false
 mybatis-plus.global-config.banner=false

+ 3 - 0
fiveep-model/src/main/java/com/bizmatics/model/DeviceList.java

@@ -72,6 +72,9 @@ public class DeviceList implements Serializable {
      */
      */
     private Integer enable;
     private Integer enable;
 
 
+    /**
+     * 设备状态(0 正常,1 离线,77 告警,4 故障)
+     **/
     @TableField(exist = false)
     @TableField(exist = false)
     private Integer deviceStatus;
     private Integer deviceStatus;
 
 

+ 4 - 3
fiveep-model/src/main/java/com/bizmatics/model/RtAnalogData.java

@@ -8,11 +8,12 @@ import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 import lombok.experimental.Accessors;
 
 
 import java.io.Serializable;
 import java.io.Serializable;
+import java.time.LocalDateTime;
 import java.util.Date;
 import java.util.Date;
 
 
 /**
 /**
  * <p>
  * <p>
- * 
+ *
  * </p>
  * </p>
  *
  *
  * @author ya
  * @author ya
@@ -23,7 +24,7 @@ import java.util.Date;
 @Accessors(chain = true)
 @Accessors(chain = true)
 public class RtAnalogData implements Serializable {
 public class RtAnalogData implements Serializable {
 
 
-    private static final long serialVersionUID=1L;
+    private static final long serialVersionUID = 1L;
 
 
     /**
     /**
      * 伍继电力test_183消费组模拟量数据表ID
      * 伍继电力test_183消费组模拟量数据表ID
@@ -407,7 +408,7 @@ public class RtAnalogData implements Serializable {
      * 上报时间
      * 上报时间
      */
      */
     @TableField("dataTime")
     @TableField("dataTime")
-    private Date dataTime;
+    private LocalDateTime dataTime;
 
 
 
 
 }
 }

+ 9 - 2
fiveep-model/src/main/java/com/bizmatics/model/Site.java

@@ -3,12 +3,13 @@ package com.bizmatics.model;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 import lombok.experimental.Accessors;
 
 
 import java.io.Serializable;
 import java.io.Serializable;
-import java.util.Date;
+import java.time.LocalDateTime;
 
 
 /**
 /**
  * <p>
  * <p>
@@ -104,7 +105,8 @@ public class Site implements Serializable {
     /**
     /**
      * 创建时间
      * 创建时间
      */
      */
-    private Date createTime;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime createTime;
 
 
     /**
     /**
      * 创建人
      * 创建人
@@ -126,4 +128,9 @@ public class Site implements Serializable {
      */
      */
     private Integer tenantId;
     private Integer tenantId;
 
 
+    /**
+     * 站点费用状态:ture-正常,false-异常(没有费用配置)
+     */
+    @TableField(exist = false)
+    private boolean costTypeStatus;
 }
 }

+ 30 - 1
fiveep-model/src/main/java/com/bizmatics/model/SiteElectricityRecord.java

@@ -1,10 +1,15 @@
 package com.bizmatics.model;
 package com.bizmatics.model;
 
 
 import java.math.BigDecimal;
 import java.math.BigDecimal;
+
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.IdType;
+
 import java.time.LocalDate;
 import java.time.LocalDate;
+
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableId;
+
 import java.io.Serializable;
 import java.io.Serializable;
+
 import lombok.Data;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 import lombok.experimental.Accessors;
@@ -22,7 +27,7 @@ import lombok.experimental.Accessors;
 @Accessors(chain = true)
 @Accessors(chain = true)
 public class SiteElectricityRecord implements Serializable {
 public class SiteElectricityRecord implements Serializable {
 
 
-    private static final long serialVersionUID=1L;
+    private static final long serialVersionUID = 1L;
 
 
     /**
     /**
      * 站点日电费记录表ID
      * 站点日电费记录表ID
@@ -70,5 +75,29 @@ public class SiteElectricityRecord implements Serializable {
      */
      */
     private BigDecimal totalCost;
     private BigDecimal totalCost;
 
 
+    /**
+     * 尖 用量(Kwh)
+     */
+    private BigDecimal sharpPeak;
+
+    /**
+     * 峰 用量(Kwh)
+     */
+    private BigDecimal peak;
+
+    /**
+     * 平 用量(Kwh)
+     */
+    private BigDecimal flat;
+
+    /**
+     * 谷 用量(Kwh)
+     */
+    private BigDecimal valley;
+
+    /**
+     * 总电量(Kwh)
+     */
+    private BigDecimal totalElectricity;
 
 
 }
 }

+ 4 - 1
fiveep-persistence/src/main/java/com/bizmatics/persistence/mapper/DeviceMapper.java

@@ -59,5 +59,8 @@ public interface DeviceMapper extends CrudMapper<Device> {
 
 
     List<DeviceOneVo> deviceBoxList(@Param("siteId") Integer siteId);
     List<DeviceOneVo> deviceBoxList(@Param("siteId") Integer siteId);
 
 
-
+    List<DeviceList> deviceBranch(@Param("siteId") int siteId,
+                                  @Param("deviceType") int deviceType,
+                                  @Param("pageNum") int pageNum,
+                                  @Param("pageSize") int pageSize);
 }
 }

+ 3 - 1
fiveep-persistence/src/main/java/com/bizmatics/persistence/mapper/HtAnalogDataMapper.java

@@ -181,7 +181,9 @@ public interface HtAnalogDataMapper extends CrudMapper<HtAnalogData> {
                                            @Param("endTime") String endTime,
                                            @Param("endTime") String endTime,
                                            @Param("table") String table);
                                            @Param("table") String table);
 
 
-    List<HtAnalogData> getP(@Param("deviceCodes") List<String> deviceCodes);
+    List<HtAnalogData> getP(@Param("deviceCodes") List<String> deviceCodes,
+                            @Param("startTime") LocalDateTime startTime,
+                            @Param("endTime") LocalDateTime endTime);
 
 
     List<Map<String, Object>> aggregateAll(TimeRangeParams params);
     List<Map<String, Object>> aggregateAll(TimeRangeParams params);
 }
 }

+ 2 - 0
fiveep-persistence/src/main/java/com/bizmatics/persistence/mapper/RtAnalogDataMapper.java

@@ -69,4 +69,6 @@ public interface RtAnalogDataMapper extends CrudMapper<RtAnalogData> {
     List<RtAnalogData> getRtAnalogDataList(@Param("deviceCode") String deviceCode,
     List<RtAnalogData> getRtAnalogDataList(@Param("deviceCode") String deviceCode,
                                            @Param("table") String table);
                                            @Param("table") String table);
 
 
+    List<RtAnalogData> getP(@Param("deviceCodes") List<String> deviceCodes);
+
 }
 }

+ 41 - 10
fiveep-persistence/src/main/resources/mapper/mysql/DeviceMapper.xml

@@ -4,15 +4,15 @@
 
 
     <!-- 通用查询映射结果 -->
     <!-- 通用查询映射结果 -->
     <resultMap id="BaseResultMap" type="com.bizmatics.model.Device">
     <resultMap id="BaseResultMap" type="com.bizmatics.model.Device">
-        <id column="id" property="id" />
-        <result column="device_code" property="deviceCode" />
-        <result column="device_name" property="deviceName" />
-        <result column="site_id" property="siteId" />
-        <result column="device_address" property="deviceAddress" />
-        <result column="device_type" property="deviceType" />
-        <result column="install_time" property="installTime" />
-        <result column="creator" property="creator" />
-        <result column="enable" property="enable" />
+        <id column="id" property="id"/>
+        <result column="device_code" property="deviceCode"/>
+        <result column="device_name" property="deviceName"/>
+        <result column="site_id" property="siteId"/>
+        <result column="device_address" property="deviceAddress"/>
+        <result column="device_type" property="deviceType"/>
+        <result column="install_time" property="installTime"/>
+        <result column="creator" property="creator"/>
+        <result column="enable" property="enable"/>
     </resultMap>
     </resultMap>
     <select id="selectCount" resultType="java.lang.Integer">
     <select id="selectCount" resultType="java.lang.Integer">
         select count(1)
         select count(1)
@@ -44,7 +44,8 @@
         </where>
         </where>
     </select>
     </select>
     <select id="list" resultType="com.bizmatics.model.Device">
     <select id="list" resultType="com.bizmatics.model.Device">
-        select d.id,d.device_code,d.device_name,d.site_id,d.device_address,d.device_type,d.install_time,ds.device_status as deviceStatus,
+        select d.id,d.device_code,d.device_name,d.site_id,d.device_address,d.device_type,d.install_time,ds.device_status
+        as deviceStatus,
         s.installed_capacity as installedCapacity
         s.installed_capacity as installedCapacity
         from user_site as us
         from user_site as us
         inner join device_status as ds
         inner join device_status as ds
@@ -90,6 +91,36 @@
         </where>
         </where>
     </select>
     </select>
 
 
+    <select id="deviceBranch" resultType="com.bizmatics.model.DeviceList">
+        SELECT
+        a.*, c.rated_voltage, c.rated_current
+        FROM
+        device AS a
+        JOIN device_attribute AS c ON a.device_code = c.monitor_device_code
+        <where>
+            a.enable = 1
+            <if test="siteId != null and siteId != 0">
+                AND a.site_id = #{siteId}
+            </if>
+
+            <choose>
+                <!-- deviceType == 1 -->
+                <when test="deviceType == 1">
+                    AND a.device_type = 1
+                </when>
+                <!-- deviceType == 2 -->
+                <when test="deviceType == 2">
+                    AND a.device_type IN (3,4)
+                </when>
+            </choose>
+        </where>
+
+        <!-- 分页参数 -->
+        <if test="pageNum != null and pageSize != null">
+            LIMIT #{pageSize} OFFSET ${(pageNum - 1) * pageSize}
+        </if>
+    </select>
+
     <select id="CorrespondDeviceList" resultType="com.bizmatics.model.vo.CorrespondDeviceVO">
     <select id="CorrespondDeviceList" resultType="com.bizmatics.model.vo.CorrespondDeviceVO">
         SELECT
         SELECT
         a.id,
         a.id,

+ 6 - 3
fiveep-persistence/src/main/resources/mapper/mysql/HtAnalogDataMapper.xml

@@ -1554,11 +1554,14 @@
         SELECT deviceName, MAX(id) AS max_id
         SELECT deviceName, MAX(id) AS max_id
         FROM ht_analog_data
         FROM ht_analog_data
         WHERE deviceName IN
         WHERE deviceName IN
-        <foreach item="item" collection="deviceCodes" open="(" separator="," close=")">
-            #{item}
+        <foreach collection="deviceCodes" item="code" open="(" separator="," close=")">
+            #{code}
         </foreach>
         </foreach>
+        AND dataTime BETWEEN #{startTime} AND #{endTime}
         GROUP BY deviceName
         GROUP BY deviceName
-        ) latest ON t.deviceName = latest.deviceName AND t.id = latest.max_id
+        ) latest
+        ON t.deviceName = latest.deviceName
+        AND t.id = latest.max_id
     </select>
     </select>
 
 
     <select id="aggregateAll" resultType="map">
     <select id="aggregateAll" resultType="map">

+ 92 - 80
fiveep-persistence/src/main/resources/mapper/mysql/RtAnalogDataMapper.xml

@@ -20,68 +20,68 @@
     </select>
     </select>
     <select id="getOneMap" resultType="java.util.Map">
     <select id="getOneMap" resultType="java.util.Map">
         select
         select
-          `Busot` as '母线停电次数',
-          `COS` as '三相功率因数',
-          `COSa` as 'A相功率因数',
-          `COSb` as 'B相功率因数',
-          `COSc` as 'C相功率因数',
-          `Demand` as '实时有功需量',
-          `DevResetTimes` as '设备复位次数',
-          `DeviceTemp` as '设备温度',
-          `Epn` as '三相反向有功电度',
-          `Epn1` as '尖段反向有功电度',
-          `Epn2` as '峰段反向有功电度',
-          `Epn3` as '平段反向有功电度',
-          `Epn4` as '谷段反向有功电度',
-          `Epp` as '三相正向有功电度',
-          `Epp1` as '尖段正向有功电度',
-          `Epp2` as '峰段正向有功电度',
-          `Epp3` as '平段正向有功电度',
-          `Epp4` as '谷段正向有功电度',
-          `Eqn` as '三相反向无功电度',
-          `Eqp` as '三相正向无功电度',
-          `F` as '频率',
-          `I0` as '零序电流',
-          `I2` as '负序电流',
-          `IHa` as 'A相总谐波电流',
-          `IHb` as 'B相总谐波电流',
-          `IHc` as 'C相总谐波电流',
-          `Ia` as 'A相电流',
-          `Ib` as 'B相电流',
-          `Ic` as 'C相电流',
-          `Ir` as '剩余电流',
-          `LastDayMD` as '昨日有功最大需量',
-          `LastDayMDt` as '昨日有功最大需量发生时间',
-          `P` as '三相总有功功率',
-          `Pa` as 'A相有功功率',
-          `Pb` as 'B相有功功率',
-          `Pc` as 'C相有功功率',
-          `Q` as '三相总无功功率',
-          `Qa` as 'A相无功功率',
-          `Qb` as 'B相无功功率',
-          `Qc` as 'C相无功功率',
-          `SignalIntensity` as '信号强度',
-          `T1` as '第1路温度',
-          `T2` as '第2路温度',
-          `T3` as '第3路温度',
-          `T4` as '第4路温度',
-          `THDUa` as 'A相电压THD',
-          `THDUb` as 'B相电压THD',
-          `THDUc` as 'C相电压THD',
-          `Ua` as 'A相电压',
-          `Uab` as 'AB线电压',
-          `Ub` as 'B相电压',
-          `Ubc` as 'BC线电压',
-          `UblU0` as '零序电压不平衡度',
-          `UblU2` as '负序电压不平衡度',
-          `Uc` as 'C相电压',
-          `Uca` as 'CA线电压',
-          `Udt` as '电压暂降次数',
-          `Ul` as '线路侧电压',
-          `Upt` as '电压暂升次数',
-          `Ust` as '电压短时中断次数',
-          `freezingTime` as '冻结时间',
-          `dataTime` as '上报时间'
+        `Busot` as '母线停电次数',
+        `COS` as '三相功率因数',
+        `COSa` as 'A相功率因数',
+        `COSb` as 'B相功率因数',
+        `COSc` as 'C相功率因数',
+        `Demand` as '实时有功需量',
+        `DevResetTimes` as '设备复位次数',
+        `DeviceTemp` as '设备温度',
+        `Epn` as '三相反向有功电度',
+        `Epn1` as '尖段反向有功电度',
+        `Epn2` as '峰段反向有功电度',
+        `Epn3` as '平段反向有功电度',
+        `Epn4` as '谷段反向有功电度',
+        `Epp` as '三相正向有功电度',
+        `Epp1` as '尖段正向有功电度',
+        `Epp2` as '峰段正向有功电度',
+        `Epp3` as '平段正向有功电度',
+        `Epp4` as '谷段正向有功电度',
+        `Eqn` as '三相反向无功电度',
+        `Eqp` as '三相正向无功电度',
+        `F` as '频率',
+        `I0` as '零序电流',
+        `I2` as '负序电流',
+        `IHa` as 'A相总谐波电流',
+        `IHb` as 'B相总谐波电流',
+        `IHc` as 'C相总谐波电流',
+        `Ia` as 'A相电流',
+        `Ib` as 'B相电流',
+        `Ic` as 'C相电流',
+        `Ir` as '剩余电流',
+        `LastDayMD` as '昨日有功最大需量',
+        `LastDayMDt` as '昨日有功最大需量发生时间',
+        `P` as '三相总有功功率',
+        `Pa` as 'A相有功功率',
+        `Pb` as 'B相有功功率',
+        `Pc` as 'C相有功功率',
+        `Q` as '三相总无功功率',
+        `Qa` as 'A相无功功率',
+        `Qb` as 'B相无功功率',
+        `Qc` as 'C相无功功率',
+        `SignalIntensity` as '信号强度',
+        `T1` as '第1路温度',
+        `T2` as '第2路温度',
+        `T3` as '第3路温度',
+        `T4` as '第4路温度',
+        `THDUa` as 'A相电压THD',
+        `THDUb` as 'B相电压THD',
+        `THDUc` as 'C相电压THD',
+        `Ua` as 'A相电压',
+        `Uab` as 'AB线电压',
+        `Ub` as 'B相电压',
+        `Ubc` as 'BC线电压',
+        `UblU0` as '零序电压不平衡度',
+        `UblU2` as '负序电压不平衡度',
+        `Uc` as 'C相电压',
+        `Uca` as 'CA线电压',
+        `Udt` as '电压暂降次数',
+        `Ul` as '线路侧电压',
+        `Upt` as '电压暂升次数',
+        `Ust` as '电压短时中断次数',
+        `freezingTime` as '冻结时间',
+        `dataTime` as '上报时间'
         from user_site as us
         from user_site as us
         inner join device as d
         inner join device as d
         on us.site_id = d.site_id
         on us.site_id = d.site_id
@@ -89,10 +89,10 @@
         on d.device_code = rad.deviceName
         on d.device_code = rad.deviceName
         <where>
         <where>
             <if test="siteId != null and siteId != 0">
             <if test="siteId != null and siteId != 0">
-              us.site_id = #{siteId}
+                us.site_id = #{siteId}
             </if>
             </if>
             <if test="userId != null and userId != 0">
             <if test="userId != null and userId != 0">
-              and  us.user_id = #{userId}
+                and us.user_id = #{userId}
             </if>
             </if>
         </where>
         </where>
     </select>
     </select>
@@ -121,7 +121,7 @@
         inner join device as d
         inner join device as d
         on us.site_id = d.site_id
         on us.site_id = d.site_id
         <where>
         <where>
-                and d.enable=1
+            and d.enable=1
             <if test="siteId != null and siteId != 0">
             <if test="siteId != null and siteId != 0">
                 and d.site_id = #{siteId}
                 and d.site_id = #{siteId}
             </if>
             </if>
@@ -262,12 +262,12 @@
         FROM
         FROM
         ht_analog_data
         ht_analog_data
         <where>
         <where>
-                and deviceName in
-            <foreach item="item"  collection="deviceCode" open="(" separator="," close=")">
+            and deviceName in
+            <foreach item="item" collection="deviceCode" open="(" separator="," close=")">
                 #{item.deviceCode}
                 #{item.deviceCode}
             </foreach>
             </foreach>
             <if test="endTime != null and startTime != null">
             <if test="endTime != null and startTime != null">
-                and dataTime BETWEEN   #{startTime} and #{endTime}
+                and dataTime BETWEEN #{startTime} and #{endTime}
             </if>
             </if>
         </where>
         </where>
         ) t
         ) t
@@ -412,11 +412,11 @@
         ht_analog_data
         ht_analog_data
         <where>
         <where>
             and deviceName in
             and deviceName in
-            <foreach item="item"  collection="deviceCode" open="(" separator="," close=")">
+            <foreach item="item" collection="deviceCode" open="(" separator="," close=")">
                 #{item.deviceCode}
                 #{item.deviceCode}
             </foreach>
             </foreach>
             <if test="endTime != null and startTime != null">
             <if test="endTime != null and startTime != null">
-                and dataTime BETWEEN   #{startTime} and #{endTime}
+                and dataTime BETWEEN #{startTime} and #{endTime}
             </if>
             </if>
         </where>
         </where>
         ) t
         ) t
@@ -580,11 +580,11 @@
         ht_analog_data
         ht_analog_data
         <where>
         <where>
             and deviceName in
             and deviceName in
-            <foreach item="item"  collection="deviceCode" open="(" separator="," close=")">
+            <foreach item="item" collection="deviceCode" open="(" separator="," close=")">
                 #{item.deviceCode}
                 #{item.deviceCode}
             </foreach>
             </foreach>
             <if test="endTime != null and startTime != null">
             <if test="endTime != null and startTime != null">
-                and dataTime BETWEEN   #{startTime} and #{endTime}
+                and dataTime BETWEEN #{startTime} and #{endTime}
             </if>
             </if>
         </where>
         </where>
         ) t
         ) t
@@ -731,11 +731,11 @@
         ht_analog_data
         ht_analog_data
         <where>
         <where>
             and deviceName in
             and deviceName in
-            <foreach item="item"  collection="deviceCode" open="(" separator="," close=")">
+            <foreach item="item" collection="deviceCode" open="(" separator="," close=")">
                 #{item.deviceCode}
                 #{item.deviceCode}
             </foreach>
             </foreach>
             <if test="endTime != null and startTime != null">
             <if test="endTime != null and startTime != null">
-                and dataTime BETWEEN   #{startTime} and #{endTime}
+                and dataTime BETWEEN #{startTime} and #{endTime}
             </if>
             </if>
         </where>
         </where>
         ) t
         ) t
@@ -827,11 +827,23 @@
 
 
 
 
     <select id="getRtAnalogDataList" resultType="com.bizmatics.model.RtAnalogData">
     <select id="getRtAnalogDataList" resultType="com.bizmatics.model.RtAnalogData">
-        SELECT
-            *
-        FROM
-            ${table}
-        WHERE
-            deviceName = #{deviceCode}
+        SELECT *
+        FROM ${table}
+        WHERE deviceName = #{deviceCode}
     </select>
     </select>
+
+    <select id="getP" resultType="com.bizmatics.model.RtAnalogData">
+        SELECT t.deviceName, t.p, t.dataTime
+        FROM rt_analog_data t
+        INNER JOIN (
+        SELECT deviceName, MAX(id) AS max_id
+        FROM rt_analog_data
+        WHERE deviceName IN
+        <foreach item="item" collection="deviceCodes" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+        GROUP BY deviceName
+        ) latest ON t.deviceName = latest.deviceName AND t.id = latest.max_id
+    </select>
+
 </mapper>
 </mapper>

+ 16 - 0
fiveep-service/pom.xml

@@ -112,6 +112,22 @@
             <groupId>com.google.protobuf</groupId>
             <groupId>com.google.protobuf</groupId>
             <artifactId>protobuf-java</artifactId>
             <artifactId>protobuf-java</artifactId>
         </dependency>
         </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
+
+        <!-- Apache POI -->
+<!--        <dependency>-->
+<!--            <groupId>org.apache.poi</groupId>-->
+<!--            <artifactId>poi</artifactId>-->
+<!--            <version>5.2.2</version>-->
+<!--        </dependency>-->
+<!--        <dependency>-->
+<!--            <groupId>org.apache.poi</groupId>-->
+<!--            <artifactId>poi-ooxml</artifactId>-->
+<!--            <version>5.4.0</version>-->
+<!--        </dependency>-->
     </dependencies>
     </dependencies>
 
 
 
 

+ 4 - 2
fiveep-service/src/main/java/com/bizmatics/service/DeviceService.java

@@ -37,7 +37,7 @@ public interface DeviceService extends CrudService<Device> {
      */
      */
     DeviceCountVO selectDeviceCountByType(Integer site);
     DeviceCountVO selectDeviceCountByType(Integer site);
 
 
-    List<Device> list(Integer userId,Integer siteId,Integer deviceStatus,Date startTime,Date endTime,String type);
+    List<Device> list(Integer userId, Integer siteId, Integer deviceStatus, Date startTime, Date endTime, String type);
 
 
     List<DeviceList> deviceList(String siteId);
     List<DeviceList> deviceList(String siteId);
 
 
@@ -57,7 +57,7 @@ public interface DeviceService extends CrudService<Device> {
 
 
     void variableCloning(Integer type, String newDeviceCode, String oldDeviceCode, String deviceName);
     void variableCloning(Integer type, String newDeviceCode, String oldDeviceCode, String deviceName);
 
 
-    List<Device> deviceListOne(Integer siteId,Integer deviceType);
+    List<Device> deviceListOne(Integer siteId, Integer deviceType);
 
 
     String deviceExport(String deviceName, Integer deviceType, Integer siteId);
     String deviceExport(String deviceName, Integer deviceType, Integer siteId);
 
 
@@ -67,4 +67,6 @@ public interface DeviceService extends CrudService<Device> {
 
 
 
 
     List<DeviceOneVo> deviceBoxList(Integer siteId);
     List<DeviceOneVo> deviceBoxList(Integer siteId);
+
+    List<DeviceList> deviceBranch(int siteId, int deviceType, int pageNum, int pageSize);
 }
 }

+ 28 - 5
fiveep-service/src/main/java/com/bizmatics/service/HtAnalogDataService.java

@@ -1,14 +1,14 @@
 package com.bizmatics.service;
 package com.bizmatics.service;
 
 
 import com.bizmatics.common.core.bean.ApiResult;
 import com.bizmatics.common.core.bean.ApiResult;
+import com.bizmatics.common.core.bean.CommonPage;
 import com.bizmatics.common.mvc.base.CrudService;
 import com.bizmatics.common.mvc.base.CrudService;
 import com.bizmatics.model.HtAnalogData;
 import com.bizmatics.model.HtAnalogData;
 import com.bizmatics.model.vo.*;
 import com.bizmatics.model.vo.*;
-import com.bizmatics.service.vo.CommonIcoVO;
-import com.bizmatics.service.vo.HadCountVO;
-import com.bizmatics.service.vo.RealScoreVO;
-import com.bizmatics.service.vo.TimeShareVO;
+import com.bizmatics.service.vo.*;
 
 
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
 import java.time.LocalDate;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 import java.util.Date;
 import java.util.Date;
@@ -108,7 +108,7 @@ public interface HtAnalogDataService extends CrudService<HtAnalogData> {
     SingleLoopReportOneVo SingleLoopReportData(String deviceCode, Date time, int type);
     SingleLoopReportOneVo SingleLoopReportData(String deviceCode, Date time, int type);
 
 
     // 获取设备三相总有功功率值
     // 获取设备三相总有功功率值
-    List<HtAnalogData> getP(List<String> deviceCode);
+    List<HtAnalogData> getP(List<String> deviceCode, LocalDateTime startTime, LocalDateTime endTime);
 
 
     /**
     /**
      * 获取设备三相有功功率值
      * 获取设备三相有功功率值
@@ -131,4 +131,27 @@ public interface HtAnalogDataService extends CrudService<HtAnalogData> {
      * @return HtAnalogEnergySegmentedVo
      * @return HtAnalogEnergySegmentedVo
      */
      */
     HtAnalogEnergySegmentedVo getSegmentedData(Integer siteId, String queryPeriod, LocalDateTime queryTime, String queryType);
     HtAnalogEnergySegmentedVo getSegmentedData(Integer siteId, String queryPeriod, LocalDateTime queryTime, String queryType);
+
+    /**
+     * 分时电量-表格统计
+     *
+     * @param request
+     * @return
+     */
+    CommonPage<TimeSharingElectricityResponseVO> timeSharingElectricity(TimeSharingElectricityRequestVO request);
+
+    /**
+     * 分时电量-趋势统计
+     *
+     * @param trendVO
+     * @return
+     */
+    List<ElectricityTrendResponseVO> trend(ElectricityTrendRequestVO trendVO);
+
+    /**
+     * 分时电量-导出
+     *
+     * @param request
+     */
+    void export(TimeSharingElectricityRequestVO request, HttpServletResponse response) throws IOException;
 }
 }

+ 8 - 4
fiveep-service/src/main/java/com/bizmatics/service/RtAnalogDataService.java

@@ -2,6 +2,7 @@ package com.bizmatics.service;
 
 
 import com.bizmatics.common.mvc.base.CrudService;
 import com.bizmatics.common.mvc.base.CrudService;
 import com.bizmatics.model.DeviceAttribute;
 import com.bizmatics.model.DeviceAttribute;
+import com.bizmatics.model.HtAnalogData;
 import com.bizmatics.model.RtAnalogData;
 import com.bizmatics.model.RtAnalogData;
 import com.bizmatics.model.SiteDynamicProperties;
 import com.bizmatics.model.SiteDynamicProperties;
 import com.bizmatics.model.vo.EvaluationReporVo;
 import com.bizmatics.model.vo.EvaluationReporVo;
@@ -35,7 +36,7 @@ public interface RtAnalogDataService extends CrudService<RtAnalogData> {
      * @param siteId 站点id
      * @param siteId 站点id
      * @return
      * @return
      */
      */
-    List<Map<String,Object>> getOne(Integer siteId);
+    List<Map<String, Object>> getOne(Integer siteId);
 
 
     /**
     /**
      * 实时负荷
      * 实时负荷
@@ -77,7 +78,7 @@ public interface RtAnalogDataService extends CrudService<RtAnalogData> {
      * @param queryType
      * @param queryType
      * @return
      * @return
      */
      */
-    List<Map<String,Object>> getDataReport(Integer siteId,Date startTime, Date endTime,String queryType);
+    List<Map<String, Object>> getDataReport(Integer siteId, Date startTime, Date endTime, String queryType);
 
 
     /**
     /**
      *
      *
@@ -87,7 +88,7 @@ public interface RtAnalogDataService extends CrudService<RtAnalogData> {
      * @param queryType
      * @param queryType
      * @return
      * @return
      */
      */
-    List<Map<String,Object>> getHistoricalCurve(Integer siteId,Date startTime, Date endTime,String queryType);
+    List<Map<String, Object>> getHistoricalCurve(Integer siteId, Date startTime, Date endTime, String queryType);
 
 
     /**
     /**
      *
      *
@@ -97,11 +98,14 @@ public interface RtAnalogDataService extends CrudService<RtAnalogData> {
      * @param queryType
      * @param queryType
      * @return
      * @return
      */
      */
-    String DataReportExport(Integer siteId,Date startTime, Date endTime,String queryType);
+    String DataReportExport(Integer siteId, Date startTime, Date endTime, String queryType);
 
 
 
 
     List<RealScoreVO> fillRealScoreDataTwo(List<EvaluationReporVo> evaluationReporVo);
     List<RealScoreVO> fillRealScoreDataTwo(List<EvaluationReporVo> evaluationReporVo);
 
 
     List<RealScoreVO> evaluationReport(int siteId, Date time, int type);
     List<RealScoreVO> evaluationReport(int siteId, Date time, int type);
 
 
+    // 获取三项总有功功率
+    List<RtAnalogData> getP(List<String> deviceCode);
+
 }
 }

+ 3 - 1
fiveep-service/src/main/java/com/bizmatics/service/SiteService.java

@@ -96,8 +96,10 @@ public interface SiteService extends CrudService<Site> {
     /**
     /**
      * 站点负载分析
      * 站点负载分析
      * @param siteId 站点id
      * @param siteId 站点id
+     * @param startTime 开始时间
+     * @param endTime 结束时间
      * @return 站点负载分析
      * @return 站点负载分析
      */
      */
-    CommonPage<SiteLoadAnalysisVO> siteLoadAnalysis(Integer siteId, Integer pageNum, Integer pageSize);
+    List<SiteLoadAnalysisVO> siteLoadAnalysis(Integer siteId, String startTime, String endTime);
 }
 }
 
 

+ 40 - 39
fiveep-service/src/main/java/com/bizmatics/service/impl/DeviceServiceImpl.java

@@ -43,10 +43,7 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.IOException;
 import java.text.DateFormat;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
 
 
 /**
 /**
  * 设备
  * 设备
@@ -143,7 +140,7 @@ public class DeviceServiceImpl extends AbstractCrudService<DeviceMapper, Device>
                     for (int j = 0; j < deviceAnalogVariableList.size(); j++) {
                     for (int j = 0; j < deviceAnalogVariableList.size(); j++) {
                         if (deviceList.get(i).getId().equals(deviceAnalogVariableList.get(j).getMonitoringEquipment())) {
                         if (deviceList.get(i).getId().equals(deviceAnalogVariableList.get(j).getMonitoringEquipment())) {
                             DeviceAnalogVariableList deviceAnalogVariableListThree = new DeviceAnalogVariableList();
                             DeviceAnalogVariableList deviceAnalogVariableListThree = new DeviceAnalogVariableList();
-                            deviceAnalogVariableListThree.setVariableCoding(deviceAnalogVariableList.get(j).getVariableCoding()+"_"+deviceList.get(i).getId());
+                            deviceAnalogVariableListThree.setVariableCoding(deviceAnalogVariableList.get(j).getVariableCoding() + "_" + deviceList.get(i).getId());
                             deviceAnalogVariableListThree.setVariableName(deviceAnalogVariableList.get(j).getVariableName());
                             deviceAnalogVariableListThree.setVariableName(deviceAnalogVariableList.get(j).getVariableName());
                             deviceAnalogVariableListThree.setId(deviceAnalogVariableList.get(j).getId());
                             deviceAnalogVariableListThree.setId(deviceAnalogVariableList.get(j).getId());
                             deviceAnalogVariableListTwo.add(deviceAnalogVariableListThree);
                             deviceAnalogVariableListTwo.add(deviceAnalogVariableListThree);
@@ -159,7 +156,7 @@ public class DeviceServiceImpl extends AbstractCrudService<DeviceMapper, Device>
     }
     }
 
 
     @Override
     @Override
-    public List<DeviceOneVo> deviceBoxList(Integer siteId){
+    public List<DeviceOneVo> deviceBoxList(Integer siteId) {
         List<DeviceOneVo> deviceOneVo = baseMapper.deviceBoxList(siteId);
         List<DeviceOneVo> deviceOneVo = baseMapper.deviceBoxList(siteId);
         return deviceOneVo;
         return deviceOneVo;
     }
     }
@@ -198,16 +195,16 @@ public class DeviceServiceImpl extends AbstractCrudService<DeviceMapper, Device>
     @Override
     @Override
     public CommonPage<CorrespondDeviceVO> correspondDeviceList(String deviceName, int size, int current) {
     public CommonPage<CorrespondDeviceVO> correspondDeviceList(String deviceName, int size, int current) {
         List<SysUser> tenantDaya = userMapper.getTenantId(SecurityUtils.getLoginUser().getUser().getUserId());
         List<SysUser> tenantDaya = userMapper.getTenantId(SecurityUtils.getLoginUser().getUser().getUserId());
-        if (tenantDaya.size()<0) {
+        if (tenantDaya.size() < 0) {
             throw new BusinessException("无此租户,请联系管理员");
             throw new BusinessException("无此租户,请联系管理员");
         }
         }
-        List<CorrespondDeviceVO> correspondDeviceListOne = baseMapper.CorrespondDeviceList(deviceName, null, null,tenantDaya.get(0).getTenantId());
+        List<CorrespondDeviceVO> correspondDeviceListOne = baseMapper.CorrespondDeviceList(deviceName, null, null, tenantDaya.get(0).getTenantId());
         int total = 0;
         int total = 0;
         if (correspondDeviceListOne.size() > 0) {
         if (correspondDeviceListOne.size() > 0) {
             total = correspondDeviceListOne.size();
             total = correspondDeviceListOne.size();
         }
         }
         int startCurrent = (current - 1) * size;
         int startCurrent = (current - 1) * size;
-        List<CorrespondDeviceVO> correspondDeviceList = baseMapper.CorrespondDeviceList(deviceName, startCurrent, size,tenantDaya.get(0).getTenantId());
+        List<CorrespondDeviceVO> correspondDeviceList = baseMapper.CorrespondDeviceList(deviceName, startCurrent, size, tenantDaya.get(0).getTenantId());
         return new CommonPage<>(correspondDeviceList, total, size, current);
         return new CommonPage<>(correspondDeviceList, total, size, current);
     }
     }
 
 
@@ -231,7 +228,7 @@ public class DeviceServiceImpl extends AbstractCrudService<DeviceMapper, Device>
 
 
     @Override
     @Override
     public CommonPage<Device> videoMonitoringDeviceList(String deviceName, Integer deviceType, Integer siteId, Integer size, Integer current) {
     public CommonPage<Device> videoMonitoringDeviceList(String deviceName, Integer deviceType, Integer siteId, Integer size, Integer current) {
-        IPage<Device> page = new Page<Device>(current,size);
+        IPage<Device> page = new Page<Device>(current, size);
         LambdaQueryWrapper<Device> queryWrapper = Wrappers.lambdaQuery();
         LambdaQueryWrapper<Device> queryWrapper = Wrappers.lambdaQuery();
         queryWrapper.eq(Device::getSiteId, siteId).eq(Device::getEnable, 1);
         queryWrapper.eq(Device::getSiteId, siteId).eq(Device::getEnable, 1);
         if (deviceType != null && deviceType != 0) {
         if (deviceType != null && deviceType != 0) {
@@ -243,13 +240,13 @@ public class DeviceServiceImpl extends AbstractCrudService<DeviceMapper, Device>
 
 
         page = this.page(page, queryWrapper);
         page = this.page(page, queryWrapper);
         this.ToCommonPage(page);
         this.ToCommonPage(page);
-        return new CommonPage<>(page.getRecords(), page.getTotal(), page.getSize(),page.getCurrent() );
+        return new CommonPage<>(page.getRecords(), page.getTotal(), page.getSize(), page.getCurrent());
     }
     }
 
 
     @Override
     @Override
     public void variableCloning(Integer type, String newDeviceCode, String oldDeviceCode, String deviceName) {
     public void variableCloning(Integer type, String newDeviceCode, String oldDeviceCode, String deviceName) {
         SysUser user = SecurityUtils.getLoginUser().getUser();
         SysUser user = SecurityUtils.getLoginUser().getUser();
-        //查询出旧设备配置
+        // 查询出旧设备配置
         LambdaQueryWrapper<Device> queryWrapper = Wrappers.lambdaQuery();
         LambdaQueryWrapper<Device> queryWrapper = Wrappers.lambdaQuery();
         queryWrapper.eq(Device::getEnable, 1).eq(Device::getDeviceCode, oldDeviceCode);
         queryWrapper.eq(Device::getEnable, 1).eq(Device::getDeviceCode, oldDeviceCode);
         List<Device> deviceList = this.list(queryWrapper);
         List<Device> deviceList = this.list(queryWrapper);
@@ -258,10 +255,10 @@ public class DeviceServiceImpl extends AbstractCrudService<DeviceMapper, Device>
             LambdaQueryWrapper<Device> queryWrapperFour = Wrappers.lambdaQuery();
             LambdaQueryWrapper<Device> queryWrapperFour = Wrappers.lambdaQuery();
             queryWrapperFour.eq(Device::getEnable, 1).eq(Device::getDeviceCode, newDeviceCode);
             queryWrapperFour.eq(Device::getEnable, 1).eq(Device::getDeviceCode, newDeviceCode);
             List<Device> deviceListrFour = this.list(queryWrapperFour);
             List<Device> deviceListrFour = this.list(queryWrapperFour);
-            if (deviceListrFour.size()>0){
-                throw new BusinessException(newDeviceCode+"设备编号重复");
-            }else {
-                //设备表新增
+            if (deviceListrFour.size() > 0) {
+                throw new BusinessException(newDeviceCode + "设备编号重复");
+            } else {
+                // 设备表新增
                 Device device = new Device();
                 Device device = new Device();
                 device.setEnable(1);
                 device.setEnable(1);
                 device.setInstallTime(new Date());
                 device.setInstallTime(new Date());
@@ -277,14 +274,14 @@ public class DeviceServiceImpl extends AbstractCrudService<DeviceMapper, Device>
                 Integer deviceId = device.getId();
                 Integer deviceId = device.getId();
                 String deviceCode = device.getDeviceCode();
                 String deviceCode = device.getDeviceCode();
                 Integer siteId = device.getSiteId();
                 Integer siteId = device.getSiteId();
-                //设备状态表新增
+                // 设备状态表新增
                 DeviceStatus deviceStatus = new DeviceStatus();
                 DeviceStatus deviceStatus = new DeviceStatus();
                 deviceStatus.setDeviceStatus(1);
                 deviceStatus.setDeviceStatus(1);
                 deviceStatus.setDeviceCode(deviceCode);
                 deviceStatus.setDeviceCode(deviceCode);
                 deviceStatus.setStatusTime(new Date());
                 deviceStatus.setStatusTime(new Date());
                 deviceStatus.setSiteId(siteId);
                 deviceStatus.setSiteId(siteId);
                 deviceStatusService.save(deviceStatus);
                 deviceStatusService.save(deviceStatus);
-                //变量配置查询
+                // 变量配置查询
                 LambdaQueryWrapper<DeviceAnalogVariableList> queryWrapperOne = Wrappers.lambdaQuery();
                 LambdaQueryWrapper<DeviceAnalogVariableList> queryWrapperOne = Wrappers.lambdaQuery();
                 queryWrapperOne.eq(DeviceAnalogVariableList::getStatus, 1).eq(DeviceAnalogVariableList::getCommunicationEquipment, deviceList.get(0).getId());
                 queryWrapperOne.eq(DeviceAnalogVariableList::getStatus, 1).eq(DeviceAnalogVariableList::getCommunicationEquipment, deviceList.get(0).getId());
                 List<DeviceAnalogVariableList> deviceAnalogVariableList = deviceAnalogVariableListService.list(queryWrapperOne);
                 List<DeviceAnalogVariableList> deviceAnalogVariableList = deviceAnalogVariableListService.list(queryWrapperOne);
@@ -293,7 +290,7 @@ public class DeviceServiceImpl extends AbstractCrudService<DeviceMapper, Device>
                         DeviceAnalogVariableList deviceAnalogVariableListOne = new DeviceAnalogVariableList();
                         DeviceAnalogVariableList deviceAnalogVariableListOne = new DeviceAnalogVariableList();
                         deviceAnalogVariableListOne.setDeviceCode(newDeviceCode);
                         deviceAnalogVariableListOne.setDeviceCode(newDeviceCode);
                         deviceAnalogVariableListOne.setVariableName(deviceAnalogVariableList.get(i).getVariableName());
                         deviceAnalogVariableListOne.setVariableName(deviceAnalogVariableList.get(i).getVariableName());
-                        deviceAnalogVariableListOne.setVariableCoding(newDeviceCode+"_"+deviceAnalogVariableList.get(i).getVariableCoding().split("_")[1]);
+                        deviceAnalogVariableListOne.setVariableCoding(newDeviceCode + "_" + deviceAnalogVariableList.get(i).getVariableCoding().split("_")[1]);
                         deviceAnalogVariableListOne.setMonitoringEquipment(0);
                         deviceAnalogVariableListOne.setMonitoringEquipment(0);
                         deviceAnalogVariableListOne.setCommunicationEquipment(deviceId);
                         deviceAnalogVariableListOne.setCommunicationEquipment(deviceId);
                         deviceAnalogVariableListOne.setDataAddress(deviceAnalogVariableList.get(i).getDataAddress());
                         deviceAnalogVariableListOne.setDataAddress(deviceAnalogVariableList.get(i).getDataAddress());
@@ -313,7 +310,7 @@ public class DeviceServiceImpl extends AbstractCrudService<DeviceMapper, Device>
             queryWrapperOneA.eq(DeviceAnalogVariableList::getStatus, 1).eq(DeviceAnalogVariableList::getCommunicationEquipment, deviceList.get(0).getId());
             queryWrapperOneA.eq(DeviceAnalogVariableList::getStatus, 1).eq(DeviceAnalogVariableList::getCommunicationEquipment, deviceList.get(0).getId());
             List<DeviceAnalogVariableList> deviceAnalogVariableListOne = deviceAnalogVariableListService.list(queryWrapperOneA);
             List<DeviceAnalogVariableList> deviceAnalogVariableListOne = deviceAnalogVariableListService.list(queryWrapperOneA);
 
 
-            //克隆设备查询是否存在
+            // 克隆设备查询是否存在
             LambdaQueryWrapper<Device> queryWrapperTwo = Wrappers.lambdaQuery();
             LambdaQueryWrapper<Device> queryWrapperTwo = Wrappers.lambdaQuery();
             queryWrapperTwo.eq(Device::getEnable, 1).eq(Device::getDeviceCode, newDeviceCode);
             queryWrapperTwo.eq(Device::getEnable, 1).eq(Device::getDeviceCode, newDeviceCode);
             List<Device> deviceListTwo = this.list(queryWrapperTwo);
             List<Device> deviceListTwo = this.list(queryWrapperTwo);
@@ -335,7 +332,7 @@ public class DeviceServiceImpl extends AbstractCrudService<DeviceMapper, Device>
                     DeviceAnalogVariableList deviceAnalogVariableList = new DeviceAnalogVariableList();
                     DeviceAnalogVariableList deviceAnalogVariableList = new DeviceAnalogVariableList();
                     deviceAnalogVariableList.setDeviceCode(newDeviceCode);
                     deviceAnalogVariableList.setDeviceCode(newDeviceCode);
                     deviceAnalogVariableList.setVariableName(deviceAnalogVariableListOne.get(i).getVariableName());
                     deviceAnalogVariableList.setVariableName(deviceAnalogVariableListOne.get(i).getVariableName());
-                    deviceAnalogVariableList.setVariableCoding(newDeviceCode+"_"+deviceAnalogVariableListOne.get(i).getVariableCoding().split("_")[1]);
+                    deviceAnalogVariableList.setVariableCoding(newDeviceCode + "_" + deviceAnalogVariableListOne.get(i).getVariableCoding().split("_")[1]);
                     deviceAnalogVariableList.setMonitoringEquipment(0);
                     deviceAnalogVariableList.setMonitoringEquipment(0);
                     deviceAnalogVariableList.setCommunicationEquipment(deviceListTwo.get(0).getId());
                     deviceAnalogVariableList.setCommunicationEquipment(deviceListTwo.get(0).getId());
                     deviceAnalogVariableList.setDataType(deviceAnalogVariableListOne.get(i).getDataType());
                     deviceAnalogVariableList.setDataType(deviceAnalogVariableListOne.get(i).getDataType());
@@ -375,7 +372,7 @@ public class DeviceServiceImpl extends AbstractCrudService<DeviceMapper, Device>
                         Page<Device> page = new Page<>(i, 30);
                         Page<Device> page = new Page<>(i, 30);
                         LambdaQueryWrapper<Device> queryWrapper = Wrappers.lambdaQuery();
                         LambdaQueryWrapper<Device> queryWrapper = Wrappers.lambdaQuery();
                         queryWrapper.eq(Device::getEnable, 1);
                         queryWrapper.eq(Device::getEnable, 1);
-                        if (siteId!=0){
+                        if (siteId != 0) {
                             queryWrapper.eq(Device::getSiteId, siteId);
                             queryWrapper.eq(Device::getSiteId, siteId);
                         }
                         }
 
 
@@ -388,7 +385,7 @@ public class DeviceServiceImpl extends AbstractCrudService<DeviceMapper, Device>
 
 
                         page = this.page(page, queryWrapper);
                         page = this.page(page, queryWrapper);
 
 
-                        for (int j = 0; j < page.getRecords().size(); j++){
+                        for (int j = 0; j < page.getRecords().size(); j++) {
                             DeviceOne deviceOne = new DeviceOne();
                             DeviceOne deviceOne = new DeviceOne();
                             deviceOne.setDeviceCode(page.getRecords().get(j).getDeviceCode());
                             deviceOne.setDeviceCode(page.getRecords().get(j).getDeviceCode());
                             deviceOne.setDeviceName(page.getRecords().get(j).getDeviceName());
                             deviceOne.setDeviceName(page.getRecords().get(j).getDeviceName());
@@ -438,7 +435,7 @@ public class DeviceServiceImpl extends AbstractCrudService<DeviceMapper, Device>
         Workbook workbook = null;
         Workbook workbook = null;
         File file = null;
         File file = null;
         List<SysUser> tenantDaya = userMapper.getTenantId(SecurityUtils.getLoginUser().getUser().getUserId());
         List<SysUser> tenantDaya = userMapper.getTenantId(SecurityUtils.getLoginUser().getUser().getUserId());
-        if (tenantDaya.size()<0) {
+        if (tenantDaya.size() < 0) {
             throw new BusinessException("无此租户,请联系管理员");
             throw new BusinessException("无此租户,请联系管理员");
         }
         }
         try {
         try {
@@ -447,8 +444,8 @@ public class DeviceServiceImpl extends AbstractCrudService<DeviceMapper, Device>
                     (o, i) -> {
                     (o, i) -> {
                         List<CorrespondDeviceTwoVO> Active = new ArrayList<CorrespondDeviceTwoVO>();
                         List<CorrespondDeviceTwoVO> Active = new ArrayList<CorrespondDeviceTwoVO>();
                         int startCurrent = (i - 1) * 30;
                         int startCurrent = (i - 1) * 30;
-                        List<CorrespondDeviceVO> correspondDeviceList = baseMapper.CorrespondDeviceList(deviceName, startCurrent, 30,tenantDaya.get(0).getTenantId());
-                        for (int j = 0; j <correspondDeviceList.size(); j++){
+                        List<CorrespondDeviceVO> correspondDeviceList = baseMapper.CorrespondDeviceList(deviceName, startCurrent, 30, tenantDaya.get(0).getTenantId());
+                        for (int j = 0; j < correspondDeviceList.size(); j++) {
                             CorrespondDeviceTwoVO correspondDeviceTwoVO = new CorrespondDeviceTwoVO();
                             CorrespondDeviceTwoVO correspondDeviceTwoVO = new CorrespondDeviceTwoVO();
                             correspondDeviceTwoVO.setDeviceCode(correspondDeviceList.get(j).getDeviceCode());
                             correspondDeviceTwoVO.setDeviceCode(correspondDeviceList.get(j).getDeviceCode());
                             correspondDeviceTwoVO.setDeviceName(correspondDeviceList.get(j).getDeviceName());
                             correspondDeviceTwoVO.setDeviceName(correspondDeviceList.get(j).getDeviceName());
@@ -497,19 +494,19 @@ public class DeviceServiceImpl extends AbstractCrudService<DeviceMapper, Device>
         SysUser user = SecurityUtils.getLoginUser().getUser();
         SysUser user = SecurityUtils.getLoginUser().getUser();
         ImportParams params = new ImportParams();
         ImportParams params = new ImportParams();
         params.setHeadRows(1);
         params.setHeadRows(1);
-        String err="文件导入失败";
+        String err = "文件导入失败";
         try {
         try {
             List<DeviceImportVo> deviceImportVos = ExcelImportUtil.importExcel(multipartFile.getInputStream(),
             List<DeviceImportVo> deviceImportVos = ExcelImportUtil.importExcel(multipartFile.getInputStream(),
                     DeviceImportVo.class, params);
                     DeviceImportVo.class, params);
-            if (CollectionUtils.isNotEmpty(deviceImportVos)){
-                int rot=0;
-                for (DeviceImportVo deviceImportVo:deviceImportVos) {
+            if (CollectionUtils.isNotEmpty(deviceImportVos)) {
+                int rot = 0;
+                for (DeviceImportVo deviceImportVo : deviceImportVos) {
                     DeviceStatus deviceStatus = new DeviceStatus();
                     DeviceStatus deviceStatus = new DeviceStatus();
                     Device device = BeanMapperUtils.map(deviceImportVo, Device.class);
                     Device device = BeanMapperUtils.map(deviceImportVo, Device.class);
                     device.setEnable(1);
                     device.setEnable(1);
                     device.setCreator(user.getUserName());
                     device.setCreator(user.getUserName());
                     device.setInstallTime(new Date());
                     device.setInstallTime(new Date());
-                    try{
+                    try {
                         this.save(device);
                         this.save(device);
                         String deviceCode = device.getDeviceCode();
                         String deviceCode = device.getDeviceCode();
                         Integer siteId = device.getSiteId();
                         Integer siteId = device.getSiteId();
@@ -518,21 +515,25 @@ public class DeviceServiceImpl extends AbstractCrudService<DeviceMapper, Device>
                         deviceStatus.setStatusTime(new Date());
                         deviceStatus.setStatusTime(new Date());
                         deviceStatus.setSiteId(siteId);
                         deviceStatus.setSiteId(siteId);
                         deviceStatusService.save(deviceStatus);
                         deviceStatusService.save(deviceStatus);
-                    }catch (Exception e){
-                        int h=rot+2;
-                        err="文件导入失败,第"+h+"行数据导入失败";
-                        throw  new BusinessException(err);
+                    } catch (Exception e) {
+                        int h = rot + 2;
+                        err = "文件导入失败,第" + h + "行数据导入失败";
+                        throw new BusinessException(err);
                     }
                     }
                     rot++;
                     rot++;
                 }
                 }
-            }else {
-                err="文件不能为空";
+            } else {
+                err = "文件不能为空";
                 throw new BusinessException(err);
                 throw new BusinessException(err);
             }
             }
-        }catch (Exception e){
+        } catch (Exception e) {
             TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
             TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
-            throw  new BusinessException(err);
+            throw new BusinessException(err);
         }
         }
     }
     }
 
 
+    @Override
+    public List<DeviceList> deviceBranch(int siteId, int deviceType, int pageNum, int pageSize) {
+        return baseMapper.deviceBranch(siteId, deviceType, pageNum, pageSize);
+    }
 }
 }

+ 598 - 5
fiveep-service/src/main/java/com/bizmatics/service/impl/HtAnalogDataServiceImpl.java

@@ -5,13 +5,13 @@ import cn.afterturn.easypoi.excel.entity.ExportParams;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.bizmatics.common.core.bean.CommonPage;
 import com.bizmatics.common.core.exception.BusinessException;
 import com.bizmatics.common.core.exception.BusinessException;
 import com.bizmatics.common.core.util.*;
 import com.bizmatics.common.core.util.*;
 import com.bizmatics.common.mvc.base.AbstractCrudService;
 import com.bizmatics.common.mvc.base.AbstractCrudService;
 import com.bizmatics.common.spring.util.GlobalUtils;
 import com.bizmatics.common.spring.util.GlobalUtils;
 import com.bizmatics.common.spring.util.JsonUtils;
 import com.bizmatics.common.spring.util.JsonUtils;
 import com.bizmatics.model.*;
 import com.bizmatics.model.*;
-import com.bizmatics.model.utils.TimeRangeParams;
 import com.bizmatics.model.utils.TimeRangeUtils;
 import com.bizmatics.model.utils.TimeRangeUtils;
 import com.bizmatics.model.vo.*;
 import com.bizmatics.model.vo.*;
 import com.bizmatics.persistence.mapper.*;
 import com.bizmatics.persistence.mapper.*;
@@ -22,25 +22,34 @@ import com.bizmatics.service.util.SecurityUtils;
 import com.bizmatics.service.util.SiteFeeCacheService;
 import com.bizmatics.service.util.SiteFeeCacheService;
 import com.bizmatics.service.vo.*;
 import com.bizmatics.service.vo.*;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.core.type.TypeReference;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.checkerframework.checker.units.qual.A;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
+import javax.servlet.http.HttpServletResponse;
 import java.io.File;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.IOException;
+import java.io.OutputStream;
 import java.math.BigDecimal;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.math.RoundingMode;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 import java.text.DateFormat;
 import java.text.DateFormat;
 import java.text.DecimalFormat;
 import java.text.DecimalFormat;
 import java.text.SimpleDateFormat;
 import java.text.SimpleDateFormat;
 import java.time.*;
 import java.time.*;
+import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoUnit;
 import java.time.temporal.ChronoUnit;
 import java.time.temporal.TemporalAdjusters;
 import java.time.temporal.TemporalAdjusters;
 import java.util.*;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import java.util.stream.Stream;
 
 
@@ -88,6 +97,8 @@ public class HtAnalogDataServiceImpl extends AbstractCrudService<HtAnalogDataMap
 
 
     private static final BigDecimal ZERO = BigDecimal.ZERO;
     private static final BigDecimal ZERO = BigDecimal.ZERO;
 
 
+    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
     @Override
     @Override
     public HadCountVO selectCount() {
     public HadCountVO selectCount() {
         HadCountVO hadCountVO = new HadCountVO();
         HadCountVO hadCountVO = new HadCountVO();
@@ -1501,8 +1512,8 @@ public class HtAnalogDataServiceImpl extends AbstractCrudService<HtAnalogDataMap
 
 
     // 获取设备三相总有功功率值
     // 获取设备三相总有功功率值
     @Override
     @Override
-    public List<HtAnalogData> getP(List<String> deviceCodes) {
-        return htAnalogDataMapper.getP(deviceCodes);
+    public List<HtAnalogData> getP(List<String> deviceCodes, LocalDateTime startTime, LocalDateTime endTime) {
+        return htAnalogDataMapper.getP(deviceCodes, startTime, endTime);
     }
     }
 
 
     /**
     /**
@@ -3028,5 +3039,587 @@ public class HtAnalogDataServiceImpl extends AbstractCrudService<HtAnalogDataMap
                 .reduce(ZERO, BigDecimal::add);
                 .reduce(ZERO, BigDecimal::add);
     }
     }
 
 
+    @Override
+    public CommonPage<TimeSharingElectricityResponseVO> timeSharingElectricity(TimeSharingElectricityRequestVO request) {
+        /* ---------- 1. 参数兜底 ---------- */
+        Integer pageNum = request.getPageNum() == null ? 1 : request.getPageNum();
+        Integer pageSize = request.getPageSize() == null ? 20 : request.getPageSize();
+        if (request.getSiteId() == null) {
+            throw new BusinessException("站点ID不能为空");
+        }
+        if (CollectionUtils.isEmpty(request.getDeviceCodes())) {
+            throw new BusinessException("设备代码列表不能为空");
+        }
+        if (request.getStartTime() == null || request.getEndTime() == null) {
+            throw new BusinessException("起止时间不能为空");
+        }
+
+        /* ---------- 2. 分页查询 ---------- */
+        PageHelper.startPage(pageNum, pageSize);
+        LambdaQueryWrapper<SiteElectricityRecord> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(SiteElectricityRecord::getSiteId, request.getSiteId())
+                .in(SiteElectricityRecord::getDeviceCode, request.getDeviceCodes())
+                .between(SiteElectricityRecord::getDate, request.getStartTime(), request.getEndTime())
+                .orderByAsc(SiteElectricityRecord::getDate, SiteElectricityRecord::getDeviceCode);
+
+        List<SiteElectricityRecord> records = siteElectricityRecordMapper.selectList(wrapper);
+
+        // 3. 按 deviceCode 分组汇总
+        List<TimeSharingElectricityResponseVO> list = records.stream()
+                .collect(Collectors.groupingBy(
+                        SiteElectricityRecord::getDeviceCode,
+                        LinkedHashMap::new,
+                        Collectors.reducing((a, b) -> {
+                            // 累加电量
+                            a.setSharpPeak(a.getSharpPeak().add(b.getSharpPeak()));
+                            a.setPeak(a.getPeak().add(b.getPeak()));
+                            a.setFlat(a.getFlat().add(b.getFlat()));
+                            a.setValley(a.getValley().add(b.getValley()));
+                            a.setTotalElectricity(a.getTotalElectricity().add(b.getTotalElectricity()));
+
+                            // 累加电费
+                            a.setSharpPeakCost(a.getSharpPeakCost().add(b.getSharpPeakCost()));
+                            a.setPeakCost(a.getPeakCost().add(b.getPeakCost()));
+                            a.setFlatCost(a.getFlatCost().add(b.getFlatCost()));
+                            a.setValleyCost(a.getValleyCost().add(b.getValleyCost()));
+                            a.setTotalCost(a.getTotalCost().add(b.getTotalCost()));
+                            return a;
+                        })
+                ))
+                .values().stream()
+                .map(opt -> opt.orElseThrow(() -> new RuntimeException("汇总数据不能为空")))
+                .map(r -> {
+                    TimeSharingElectricityResponseVO vo = new TimeSharingElectricityResponseVO();
+                    vo.setDeviceName(r.getDeviceCode());
+                    vo.setSharpNum(r.getSharpPeak());
+                    vo.setPeakNum(r.getPeak());
+                    vo.setFlatNum(r.getFlat());
+                    vo.setValleyNum(r.getValley());
+                    vo.setTotalNum(r.getTotalElectricity());
+                    vo.setSharpPrice(r.getSharpPeakCost());
+                    vo.setPeakPrice(r.getPeakCost());
+                    vo.setFlatPrice(r.getFlatCost());
+                    vo.setValleyPrice(r.getValleyCost());
+                    vo.setTotalPrice(r.getTotalCost());
+                    vo.setTime(request.getStartTime().toString() +
+                            " - " + request.getEndTime().toString());
+                    return vo;
+                })
+                .collect(Collectors.toList());
+
+        /* ---------- 4. 封装分页结果 ---------- */
+        PageInfo<TimeSharingElectricityResponseVO> pageInfo = new PageInfo<>(list);
+        return new CommonPage<>(list, pageInfo.getTotal(), pageNum, pageSize);
+    }
+
+    @Override
+    public List<ElectricityTrendResponseVO> trend(ElectricityTrendRequestVO request) {
+        // 1. 参数校验
+        if (request.getSiteId() == null) {
+            throw new BusinessException("站点ID不能为空");
+        }
+        if (CollectionUtils.isEmpty(request.getDeviceCodes())) {
+            throw new BusinessException("设备代码列表不能为空");
+        }
+        if (request.getStartTime() == null || request.getEndTime() == null || request.getStartTime().isAfter(request.getEndTime())) {
+            throw new BusinessException("起止时间异常");
+        }
+        if (request.getType() == null || !Arrays.asList(1, 2).contains(request.getType())) {
+            throw new BusinessException("查询类型必须为1(电量)或2(电费)");
+        }
+
+        LocalDate startDate = request.getStartTime();
+        LocalDate endDate = request.getEndTime();
+
+        // 2. 查询数据
+        LambdaQueryWrapper<SiteElectricityRecord> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(SiteElectricityRecord::getSiteId, request.getSiteId())
+                .in(SiteElectricityRecord::getDeviceCode, request.getDeviceCodes())
+                .between(SiteElectricityRecord::getDate, startDate, endDate)
+                .orderByAsc(SiteElectricityRecord::getDeviceCode, SiteElectricityRecord::getDate);
+
+        List<SiteElectricityRecord> records = siteElectricityRecordMapper.selectList(wrapper);
+
+        // 3. 判断维度
+        long days = ChronoUnit.DAYS.between(startDate, endDate) + 1;
+        boolean monthMode = days > 31;
+
+        // 4. 选择字段函数(电量 or 电费)
+        boolean isElectricity = request.getType() == 1;
+        Function<SiteElectricityRecord, BigDecimal> sharpFn = isElectricity ?
+                SiteElectricityRecord::getSharpPeak : SiteElectricityRecord::getSharpPeakCost;
+        Function<SiteElectricityRecord, BigDecimal> peakFn = isElectricity ?
+                SiteElectricityRecord::getPeak : SiteElectricityRecord::getPeakCost;
+        Function<SiteElectricityRecord, BigDecimal> flatFn = isElectricity ?
+                SiteElectricityRecord::getFlat : SiteElectricityRecord::getFlatCost;
+        Function<SiteElectricityRecord, BigDecimal> valleyFn = isElectricity ?
+                SiteElectricityRecord::getValley : SiteElectricityRecord::getValleyCost;
+
+        records.forEach(r -> log.info("id={}, date={}, toString={}", r.getId(), r.getDate(), r.getDate().toString()));
+
+        // 5. 分组汇总
+        Map<String, Map<String, List<SiteElectricityRecord>>> group =
+                records.stream()
+                        .collect(Collectors.groupingBy(
+                                SiteElectricityRecord::getDeviceCode,
+                                LinkedHashMap::new,
+                                Collectors.groupingBy(r -> monthMode ?
+                                                YearMonth.from(r.getDate()).toString() : r.getDate().toString(),
+                                        LinkedHashMap::new,
+                                        Collectors.toList())
+                        ));
+
+
+        // 6. 转 VO
+        List<ElectricityTrendResponseVO> result = new ArrayList<>();
+        group.forEach((deviceCode, timeMap) -> {
+            ElectricityTrendResponseVO dev = new ElectricityTrendResponseVO();
+            dev.setDeviceCode(deviceCode);
+
+            List<ElectricityTrendVO> trendList = new ArrayList<>();
+            timeMap.forEach((timeKey, list) -> {
+
+                if (timeKey.contains("031") || timeKey.contains("-0031")) {
+                    throw new IllegalArgumentException("脏 timeKey 出现:" + timeKey);
+                }
+
+                BigDecimal sharp = list.stream().map(sharpFn).reduce(ZERO, BigDecimal::add);
+                BigDecimal peak = list.stream().map(peakFn).reduce(ZERO, BigDecimal::add);
+                BigDecimal flat = list.stream().map(flatFn).reduce(ZERO, BigDecimal::add);
+                BigDecimal valley = list.stream().map(valleyFn).reduce(ZERO, BigDecimal::add);
+
+                ElectricityTrendVO vo = new ElectricityTrendVO();
+                vo.setTime(timeKey);
+                vo.setSharp(sharp);
+                vo.setPeak(peak);
+                vo.setFlat(flat);
+                vo.setValley(valley);
+                trendList.add(vo);
+            });
+            dev.setData(trendList);
+            result.add(dev);
+        });
+
+        return result;
+    }
+
+    @Override
+    public void export(TimeSharingElectricityRequestVO request, HttpServletResponse response) throws IOException {
+        // 参数校验
+        if (request.getSiteId() == null) {
+            throw new BusinessException("站点ID不能为空");
+        }
+        if (CollectionUtils.isEmpty(request.getDeviceCodes())) {
+            throw new BusinessException("设备代码列表不能为空");
+        }
+        if (request.getStartTime() == null || request.getEndTime() == null) {
+            throw new BusinessException("起止时间不能为空");
+        }
+
+        // 格式化时间(解决之前的时间格式问题)
+        String start = formatter.format(request.getStartTime());
+        String end = formatter.format(request.getEndTime());
+
+        // 查询数据
+        LambdaQueryWrapper<SiteElectricityRecord> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(SiteElectricityRecord::getSiteId, request.getSiteId())
+                .in(SiteElectricityRecord::getDeviceCode, request.getDeviceCodes())
+                .between(SiteElectricityRecord::getDate, request.getStartTime(), request.getEndTime())
+                .orderByAsc(SiteElectricityRecord::getDate, SiteElectricityRecord::getDeviceCode);
+
+        List<SiteElectricityRecord> records = siteElectricityRecordMapper.selectList(wrapper);
+        log.info("查询到的记录数: {}", records.size());
+        if (records.isEmpty()) {
+            throw new BusinessException("没有找到符合条件的数据");
+        }
+
+        // 按设备分组汇总数据
+        List<TimeSharingElectricityResponseVO> dataList = aggregateData(records, start, end);
+
+        // 处理分页
+        List<TimeSharingElectricityResponseVO> pageList = handlePagination(dataList, request);
+
+        // 准备导出信息
+        String deviceTypePrefix = request.getDeviceType() == 1 ? "支路" : "分项";
+        String sheetName = deviceTypePrefix + "分时用电";
+        String fileName = String.format("%s分时用电(%s-%s).xlsx", deviceTypePrefix, start, end);
+        String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());
+
+        // 导出Excel
+        try (Workbook workbook = new XSSFWorkbook()) {
+            Sheet sheet = workbook.createSheet(sheetName);
+
+            // 创建样式
+            CellStyle titleStyle = createTitleStyle(workbook);    // 新增标题样式
+            CellStyle headerStyle = createHeaderStyle(workbook);
+            CellStyle dataStyle = createDataStyle(workbook);
+            CellStyle percentageStyle = createPercentageStyle(workbook);
+
+            // 构建表格结构
+            int currentRow = 0;
+            currentRow = createTitleRow(sheet, titleStyle, sheetName, currentRow);  // 使用标题样式
+            currentRow = createHeaderRows(sheet, headerStyle, currentRow, deviceTypePrefix);
+
+            // 设置列宽
+            setColumnWidths(sheet);
+
+            // 插入数据
+            currentRow = insertDataIntoSheet(sheet, pageList, dataStyle, percentageStyle, currentRow);
+
+            // 响应处理
+            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+            response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFileName);
+
+            try (OutputStream outputStream = response.getOutputStream()) {
+                workbook.write(outputStream);
+            }
+        } catch (Exception e) {
+            log.error("导出文件失败", e);
+            throw new BusinessException("导出文件失败: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 创建标题行
+     */
+    private int createTitleRow(Sheet sheet, CellStyle titleStyle, String title, int rowIndex) {
+        Row titleRow = sheet.createRow(rowIndex++);
+        Cell titleCell = titleRow.createCell(0);
+        titleCell.setCellValue(title);
+        titleCell.setCellStyle(titleStyle);
+        // 合并标题行(0行0列到0行11列)
+        sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), 0, 11));
+        return rowIndex;
+    }
+
+    /**
+     * 创建表头行(包含单元格合并逻辑)
+     */
+    /**
+     * 创建表头行(包含单元格合并逻辑,确保所有单元格应用带边框的样式)
+     */
+    private int createHeaderRows(Sheet sheet, CellStyle headerStyle, int rowIndex, String deviceTypePrefix) {
+        // 第一级表头(rowIndex行)
+        Row headerRow = sheet.createRow(rowIndex);
+
+        // 1. 支路名称 - 合并两行(rowIndex和rowIndex+1行,0列)
+        sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex + 1, 0, 0));
+        // 为合并区域的两个行(rowIndex 和 rowIndex+1)的第0列单元格设置样式
+        for (int r = rowIndex; r <= rowIndex + 1; r++) {
+            Row row = sheet.getRow(r);
+            if (row == null) {
+                row = sheet.createRow(r);
+            }
+            Cell cell = row.getCell(0);
+            if (cell == null) {
+                cell = row.createCell(0);
+            }
+            cell.setCellValue(deviceTypePrefix + "名称");
+            cell.setCellStyle(headerStyle);
+        }
+
+        // 2. 尖峰 - 合并两列(rowIndex行,1-2列)
+        sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 1, 2));
+        // 为合并区域的两个列(1 和 2)的单元格设置样式
+        for (int c = 1; c <= 2; c++) {
+            Cell cell = headerRow.getCell(c);
+            if (cell == null) {
+                cell = headerRow.createCell(c);
+            }
+            cell.setCellValue("尖峰");
+            cell.setCellStyle(headerStyle);
+        }
+
+        // 3. 峰 - 合并两列(rowIndex行,3-4列)
+        sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 3, 4));
+        for (int c = 3; c <= 4; c++) {
+            Cell cell = headerRow.getCell(c);
+            if (cell == null) {
+                cell = headerRow.createCell(c);
+            }
+            cell.setCellValue("峰");
+            cell.setCellStyle(headerStyle);
+        }
+
+        // 4. 平 - 合并两列(rowIndex行,5-6列)
+        sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 5, 6));
+        for (int c = 5; c <= 6; c++) {
+            Cell cell = headerRow.getCell(c);
+            if (cell == null) {
+                cell = headerRow.createCell(c);
+            }
+            cell.setCellValue("平");
+            cell.setCellStyle(headerStyle);
+        }
+
+        // 5. 谷 - 合并两列(rowIndex行,7-8列)
+        sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 7, 8));
+        for (int c = 7; c <= 8; c++) {
+            Cell cell = headerRow.getCell(c);
+            if (cell == null) {
+                cell = headerRow.createCell(c);
+            }
+            cell.setCellValue("谷");
+            cell.setCellStyle(headerStyle);
+        }
+
+        // 6. 总 - 合并两列(rowIndex行,9-10列)
+        sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 9, 10));
+        for (int c = 9; c <= 10; c++) {
+            Cell cell = headerRow.getCell(c);
+            if (cell == null) {
+                cell = headerRow.createCell(c);
+            }
+            cell.setCellValue("总");
+            cell.setCellStyle(headerStyle);
+        }
+
+        // 7. 谷电量占比 - 合并两行(rowIndex和rowIndex+1行,11列)
+        sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex + 1, 11, 11));
+        for (int r = rowIndex; r <= rowIndex + 1; r++) {
+            Row row = sheet.getRow(r);
+            if (row == null) {
+                row = sheet.createRow(r);
+            }
+            Cell cell = row.getCell(11);
+            if (cell == null) {
+                cell = row.createCell(11);
+            }
+            cell.setCellValue("谷电量占比");
+            cell.setCellStyle(headerStyle);
+        }
+
+        // 第二级表头(rowIndex+1行)
+        rowIndex++;
+        Row subHeaderRow = sheet.createRow(rowIndex);
+        String[] subHeaders = {"", "电量(kWh)", "电费(元)", "电量(kWh)", "电费(元)",
+                "电量(kWh)", "电费(元)", "电量(kWh)", "电费(元)",
+                "电量(kWh)", "电费(元)", ""};
+        for (int i = 0; i < subHeaders.length; i++) {
+            Cell cell = subHeaderRow.createCell(i);
+            cell.setCellValue(subHeaders[i]);
+            cell.setCellStyle(headerStyle);
+        }
+
+        return rowIndex + 1;
+    }
+
+    /**
+     * 设置列宽(增加标题行宽度)
+     */
+    private void setColumnWidths(Sheet sheet) {
+        // 为不同列设置更合理的宽度,第0列(支路名称)宽度增加
+        int[] columnWidths = {25, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 18};
+        for (int i = 0; i < columnWidths.length; i++) {
+            sheet.setColumnWidth(i, columnWidths[i] * 256);
+        }
+    }
+
+    // 创建标题样式(带边框、宋体,24号)
+    private CellStyle createTitleStyle(Workbook workbook) {
+        CellStyle style = workbook.createCellStyle();
+        // 设置边框
+        style.setBorderTop(BorderStyle.THIN);
+        style.setBorderBottom(BorderStyle.THIN);
+        style.setBorderLeft(BorderStyle.THIN);
+        style.setBorderRight(BorderStyle.THIN);
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+
+        Font font = workbook.createFont();
+        font.setFontName("宋体");
+        font.setFontHeightInPoints((short) 24);
+        font.setBold(true);
+        style.setFont(font);
+        return style;
+    }
+
+    // 创建表头样式(带边框、宋体,12号,加粗)
+    private CellStyle createHeaderStyle(Workbook workbook) {
+        CellStyle style = workbook.createCellStyle();
+        // 设置边框
+        style.setBorderTop(BorderStyle.THIN);
+        style.setBorderBottom(BorderStyle.THIN);
+        style.setBorderLeft(BorderStyle.THIN);
+        style.setBorderRight(BorderStyle.THIN);
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+
+        Font font = workbook.createFont();
+        font.setFontName("宋体");
+        font.setFontHeightInPoints((short) 12);
+        font.setBold(true);
+        style.setFont(font);
+        return style;
+    }
+
+    // 创建数据行样式(带边框、宋体,12号)
+    private CellStyle createDataStyle(Workbook workbook) {
+        CellStyle style = workbook.createCellStyle();
+        // 设置边框
+        style.setBorderTop(BorderStyle.THIN);
+        style.setBorderBottom(BorderStyle.THIN);
+        style.setBorderLeft(BorderStyle.THIN);
+        style.setBorderRight(BorderStyle.THIN);
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+
+        Font font = workbook.createFont();
+        font.setFontName("宋体");
+        font.setFontHeightInPoints((short) 12);
+        style.setFont(font);
+        return style;
+    }
+
+    // 创建百分比样式(带边框、宋体,12号,百分比格式)
+    private CellStyle createPercentageStyle(Workbook workbook) {
+        CellStyle style = createDataStyle(workbook);
+        DataFormat format = workbook.createDataFormat();
+        style.setDataFormat(format.getFormat("0.00%"));
+        return style;
+    }
+
+    /**
+     * 汇总数据
+     */
+    private List<TimeSharingElectricityResponseVO> aggregateData(List<SiteElectricityRecord> records, String start, String end) {
+        return records.stream()
+                .collect(Collectors.groupingBy(
+                        SiteElectricityRecord::getDeviceCode,
+                        LinkedHashMap::new,
+                        Collectors.reducing((a, b) -> {
+                            // 累加电量
+                            a.setSharpPeak(a.getSharpPeak().add(b.getSharpPeak()));
+                            a.setPeak(a.getPeak().add(b.getPeak()));
+                            a.setFlat(a.getFlat().add(b.getFlat()));
+                            a.setValley(a.getValley().add(b.getValley()));
+                            a.setTotalElectricity(a.getTotalElectricity().add(b.getTotalElectricity()));
+
+                            // 累加电费
+                            a.setSharpPeakCost(a.getSharpPeakCost().add(b.getSharpPeakCost()));
+                            a.setPeakCost(a.getPeakCost().add(b.getPeakCost()));
+                            a.setFlatCost(a.getFlatCost().add(b.getFlatCost()));
+                            a.setValleyCost(a.getValleyCost().add(b.getValleyCost()));
+                            a.setTotalCost(a.getTotalCost().add(b.getTotalCost()));
+                            return a;
+                        })
+                ))
+                .values().stream()
+                .map(opt -> opt.orElseThrow(() -> new RuntimeException("汇总数据不能为空")))
+                .map(r -> {
+                    TimeSharingElectricityResponseVO vo = new TimeSharingElectricityResponseVO();
+                    vo.setDeviceName(r.getDeviceCode());
+                    vo.setSharpNum(r.getSharpPeak());
+                    vo.setPeakNum(r.getPeak());
+                    vo.setFlatNum(r.getFlat());
+                    vo.setValleyNum(r.getValley());
+                    vo.setTotalNum(r.getTotalElectricity());
+                    vo.setSharpPrice(r.getSharpPeakCost());
+                    vo.setPeakPrice(r.getPeakCost());
+                    vo.setFlatPrice(r.getFlatCost());
+                    vo.setValleyPrice(r.getValleyCost());
+                    vo.setTotalPrice(r.getTotalCost());
+                    vo.setTime(start + " - " + end);
+                    return vo;
+                })
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 处理分页
+     */
+    private List<TimeSharingElectricityResponseVO> handlePagination(List<TimeSharingElectricityResponseVO> dataList,
+                                                                    TimeSharingElectricityRequestVO request) {
+        int total = dataList.size();
+        int startIndex = (request.getPageNum() - 1) * request.getPageSize();
+        int endIndex = Math.min(startIndex + request.getPageSize(), total);
+
+        log.info("总记录数: {}, 起始索引: {}, 结束索引: {}", total, startIndex, endIndex);
+
+        if (startIndex > total) {
+            throw new BusinessException("起始索引无效");
+        }
+
+        return dataList.subList(startIndex, endIndex);
+    }
+
+    /**
+     * 插入数据到工作表
+     */
+    private int insertDataIntoSheet(Sheet sheet, List<TimeSharingElectricityResponseVO> dataList,
+                                    CellStyle dataStyle, CellStyle percentageStyle, int startRow) {
+        int currentRow = startRow;
+
+        for (TimeSharingElectricityResponseVO vo : dataList) {
+            Row row = sheet.createRow(currentRow++);
+            int cellIndex = 0;
+
+            // 支路名称
+            createCell(row, cellIndex++, vo.getDeviceName(), dataStyle);
+
+            // 尖峰数据
+            createCell(row, cellIndex++, vo.getSharpNum(), dataStyle);
+            createCell(row, cellIndex++, vo.getSharpPrice(), dataStyle);
+
+            // 峰数据
+            createCell(row, cellIndex++, vo.getPeakNum(), dataStyle);
+            createCell(row, cellIndex++, vo.getPeakPrice(), dataStyle);
+
+            // 平数据
+            createCell(row, cellIndex++, vo.getFlatNum(), dataStyle);
+            createCell(row, cellIndex++, vo.getFlatPrice(), dataStyle);
+
+            // 谷数据
+            createCell(row, cellIndex++, vo.getValleyNum(), dataStyle);
+            createCell(row, cellIndex++, vo.getValleyPrice(), dataStyle);
+
+            // 总数据
+            createCell(row, cellIndex++, vo.getTotalNum(), dataStyle);
+            createCell(row, cellIndex++, vo.getTotalPrice(), dataStyle);
+
+            // 谷电量占比(处理除零情况)
+            BigDecimal valleyRatio = calculateValleyRatio(vo);
+            createCell(row, cellIndex++, valleyRatio, percentageStyle);
+        }
+
+        return currentRow;
+    }
+
+    /**
+     * 创建单元格并设置值和样式
+     */
+    private void createCell(Row row, int cellIndex, Object value, CellStyle style) {
+        Cell cell = row.createCell(cellIndex);
+        cell.setCellStyle(style);
+
+        if (value == null) {
+            cell.setCellValue("");
+            return;
+        }
+
+        // 根据值类型设置单元格内容
+        if (value instanceof BigDecimal) {
+            cell.setCellValue(((BigDecimal) value).doubleValue());
+        } else if (value instanceof Number) {
+            cell.setCellValue(((Number) value).doubleValue());
+        } else {
+            cell.setCellValue(value.toString());
+        }
+    }
+
+    /**
+     * 计算谷电量占比(处理除零情况)
+     */
+    private BigDecimal calculateValleyRatio(TimeSharingElectricityResponseVO vo) {
+        try {
+            if (vo.getTotalNum() == null || vo.getTotalNum().compareTo(BigDecimal.ZERO) == 0) {
+                return BigDecimal.ZERO;
+            }
+            return vo.getValleyNum().divide(vo.getTotalNum(), 4, RoundingMode.HALF_UP);
+        } catch (Exception e) {
+            log.warn("计算谷电量占比失败", e);
+            return BigDecimal.ZERO;
+        }
+    }
 
 
 }
 }

+ 52 - 50
fiveep-service/src/main/java/com/bizmatics/service/impl/RtAnalogDataServiceImpl.java

@@ -131,7 +131,7 @@ public class RtAnalogDataServiceImpl extends AbstractCrudService<RtAnalogDataMap
     public List<Map<String, Object>> getOne(Integer siteId) {
     public List<Map<String, Object>> getOne(Integer siteId) {
         Integer userId = SecurityUtils.getLoginUser().getUser().getUserId().intValue();
         Integer userId = SecurityUtils.getLoginUser().getUser().getUserId().intValue();
         List<Map<String, Object>> list = new ArrayList<>();
         List<Map<String, Object>> list = new ArrayList<>();
-        Map<String, Object> radMap = baseMapper.getOneMap(userId,siteId);
+        Map<String, Object> radMap = baseMapper.getOneMap(userId, siteId);
         Optional.ofNullable(radMap).ifPresent(rad -> {
         Optional.ofNullable(radMap).ifPresent(rad -> {
             for (String name : rad.keySet()) {
             for (String name : rad.keySet()) {
                 Map<String, Object> map = new HashMap<>();
                 Map<String, Object> map = new HashMap<>();
@@ -151,27 +151,27 @@ public class RtAnalogDataServiceImpl extends AbstractCrudService<RtAnalogDataMap
 
 
     @Override
     @Override
     public RealScoreVO realScore(String deviceCode) {
     public RealScoreVO realScore(String deviceCode) {
-        //查询设备
+        // 查询设备
         LambdaQueryWrapper<Device> deviceQuery = Wrappers.lambdaQuery();
         LambdaQueryWrapper<Device> deviceQuery = Wrappers.lambdaQuery();
         deviceQuery.eq(Device::getDeviceCode, deviceCode);
         deviceQuery.eq(Device::getDeviceCode, deviceCode);
         Device device = deviceService.getOne(deviceQuery);
         Device device = deviceService.getOne(deviceQuery);
         Optional.ofNullable(device).orElseThrow(() -> new BusinessException("设备不存在"));
         Optional.ofNullable(device).orElseThrow(() -> new BusinessException("设备不存在"));
 
 
         String table = "rt_analog_data";
         String table = "rt_analog_data";
-        if (device.getDeviceType().equals("1")){
+        if (device.getDeviceType().equals("1")) {
             table = "rt_analog_data";
             table = "rt_analog_data";
-        }else if (device.getDeviceType().equals("4")){
+        } else if (device.getDeviceType().equals("4")) {
             table = "rt_analog_173_data";
             table = "rt_analog_173_data";
         }
         }
 
 
-        List<RtAnalogData> rtAnalogDataList = baseMapper.getRtAnalogDataList(deviceCode,table);
+        List<RtAnalogData> rtAnalogDataList = baseMapper.getRtAnalogDataList(deviceCode, table);
         RtAnalogData rtAnalogData = new RtAnalogData();
         RtAnalogData rtAnalogData = new RtAnalogData();
-        if (rtAnalogDataList.size()>0){
+        if (rtAnalogDataList.size() > 0) {
             rtAnalogData = rtAnalogDataList.get(0);
             rtAnalogData = rtAnalogDataList.get(0);
-        }else {
+        } else {
             new BusinessException("设备实时信息不存在");
             new BusinessException("设备实时信息不存在");
         }
         }
-        //查询sd
+        // 查询sd
         LambdaQueryWrapper<SiteDynamicProperties> sdQuery = Wrappers.lambdaQuery();
         LambdaQueryWrapper<SiteDynamicProperties> sdQuery = Wrappers.lambdaQuery();
         sdQuery.eq(SiteDynamicProperties::getSiteId, device.getSiteId());
         sdQuery.eq(SiteDynamicProperties::getSiteId, device.getSiteId());
         SiteDynamicProperties siteDynamicProperties = siteDynamicPropertiesService.getOne(sdQuery);
         SiteDynamicProperties siteDynamicProperties = siteDynamicPropertiesService.getOne(sdQuery);
@@ -212,7 +212,7 @@ public class RtAnalogDataServiceImpl extends AbstractCrudService<RtAnalogDataMap
 
 
     @Override
     @Override
     public RealScoreOneVO realScoreOne(String deviceCode) {
     public RealScoreOneVO realScoreOne(String deviceCode) {
-        //查询设备
+        // 查询设备
         LambdaQueryWrapper<Device> deviceQuery = Wrappers.lambdaQuery();
         LambdaQueryWrapper<Device> deviceQuery = Wrappers.lambdaQuery();
         deviceQuery.eq(Device::getDeviceCode, deviceCode);
         deviceQuery.eq(Device::getDeviceCode, deviceCode);
         Device device = deviceService.getOne(deviceQuery);
         Device device = deviceService.getOne(deviceQuery);
@@ -220,21 +220,21 @@ public class RtAnalogDataServiceImpl extends AbstractCrudService<RtAnalogDataMap
 
 
 
 
         String table = "rt_analog_data";
         String table = "rt_analog_data";
-        if (device.getDeviceType().equals("1")){
+        if (device.getDeviceType().equals("1")) {
             table = "rt_analog_data";
             table = "rt_analog_data";
-        }else if (device.getDeviceType().equals("4")){
+        } else if (device.getDeviceType().equals("4")) {
             table = "rt_analog_173_data";
             table = "rt_analog_173_data";
         }
         }
 
 
-        List<RtAnalogData> rtAnalogDataList = baseMapper.getRtAnalogDataList(deviceCode,table);
+        List<RtAnalogData> rtAnalogDataList = baseMapper.getRtAnalogDataList(deviceCode, table);
         RtAnalogData rtAnalogData = new RtAnalogData();
         RtAnalogData rtAnalogData = new RtAnalogData();
-        if (rtAnalogDataList.size()>0){
+        if (rtAnalogDataList.size() > 0) {
             rtAnalogData = rtAnalogDataList.get(0);
             rtAnalogData = rtAnalogDataList.get(0);
-        }else {
+        } else {
             new BusinessException("设备实时信息不存在");
             new BusinessException("设备实时信息不存在");
         }
         }
 
 
-        //查询sd
+        // 查询sd
         LambdaQueryWrapper<SiteDynamicProperties> sdQuery = Wrappers.lambdaQuery();
         LambdaQueryWrapper<SiteDynamicProperties> sdQuery = Wrappers.lambdaQuery();
         sdQuery.eq(SiteDynamicProperties::getSiteId, device.getSiteId());
         sdQuery.eq(SiteDynamicProperties::getSiteId, device.getSiteId());
         SiteDynamicProperties siteDynamicProperties = siteDynamicPropertiesService.getOne(sdQuery);
         SiteDynamicProperties siteDynamicProperties = siteDynamicPropertiesService.getOne(sdQuery);
@@ -269,14 +269,14 @@ public class RtAnalogDataServiceImpl extends AbstractCrudService<RtAnalogDataMap
         checkList.add(realScoreVo.getIb());
         checkList.add(realScoreVo.getIb());
         checkList.add(realScoreVo.getIc());
         checkList.add(realScoreVo.getIc());
 
 
-        //电流不平衡
+        // 电流不平衡
         realScoreVo.setElBalun(checkBalun(checkList));
         realScoreVo.setElBalun(checkBalun(checkList));
 
 
         checkList.clear();
         checkList.clear();
         checkList.add(realScoreVo.getUa());
         checkList.add(realScoreVo.getUa());
         checkList.add(realScoreVo.getUb());
         checkList.add(realScoreVo.getUb());
         checkList.add(realScoreVo.getUc());
         checkList.add(realScoreVo.getUc());
-        //ABC三相电压占比
+        // ABC三相电压占比
         Double max = checkList.stream().max(Double::compareTo).get();
         Double max = checkList.stream().max(Double::compareTo).get();
         if (max == 0.00) {
         if (max == 0.00) {
             realScoreVo.setUaPercentage(0.00);
             realScoreVo.setUaPercentage(0.00);
@@ -289,11 +289,11 @@ public class RtAnalogDataServiceImpl extends AbstractCrudService<RtAnalogDataMap
         }
         }
 
 
 
 
-        //电压不平衡
+        // 电压不平衡
         realScoreVo.setVtBalun(checkBalun(checkList));
         realScoreVo.setVtBalun(checkBalun(checkList));
-        //当前频率
+        // 当前频率
         realScoreVo.setF(realScoreVo.getF());
         realScoreVo.setF(realScoreVo.getF());
-        //频率偏差
+        // 频率偏差
         if (realScoreVo.getF() == 0.00) {
         if (realScoreVo.getF() == 0.00) {
             realScoreVo.setFdeviation(0.00);
             realScoreVo.setFdeviation(0.00);
         } else {
         } else {
@@ -333,26 +333,26 @@ public class RtAnalogDataServiceImpl extends AbstractCrudService<RtAnalogDataMap
         checkList.add(realScoreVo.getIa());
         checkList.add(realScoreVo.getIa());
         checkList.add(realScoreVo.getIb());
         checkList.add(realScoreVo.getIb());
         checkList.add(realScoreVo.getIc());
         checkList.add(realScoreVo.getIc());
-        //电流不平衡
+        // 电流不平衡
         realScoreVo.setElBalun(checkBalun(checkList));
         realScoreVo.setElBalun(checkBalun(checkList));
         checkList.clear();
         checkList.clear();
         checkList.add(realScoreVo.getUa());
         checkList.add(realScoreVo.getUa());
         checkList.add(realScoreVo.getUb());
         checkList.add(realScoreVo.getUb());
         checkList.add(realScoreVo.getUc());
         checkList.add(realScoreVo.getUc());
-        //电压不平衡
+        // 电压不平衡
         realScoreVo.setVtBalun(checkBalun(checkList));
         realScoreVo.setVtBalun(checkBalun(checkList));
-        //电压合格率
+        // 电压合格率
         double voltageLevel = Double.parseDouble(siteDynamicProperties.getVoltageLevel());
         double voltageLevel = Double.parseDouble(siteDynamicProperties.getVoltageLevel());
         realScoreVo.setUaQualified(Arith.sub(rtAnalogData.getUa(), voltageLevel));
         realScoreVo.setUaQualified(Arith.sub(rtAnalogData.getUa(), voltageLevel));
         realScoreVo.setUbQualified(Arith.sub(rtAnalogData.getUb(), voltageLevel));
         realScoreVo.setUbQualified(Arith.sub(rtAnalogData.getUb(), voltageLevel));
         realScoreVo.setUcQualified(Arith.sub(rtAnalogData.getUc(), voltageLevel));
         realScoreVo.setUcQualified(Arith.sub(rtAnalogData.getUc(), voltageLevel));
-        //电流负载率
+        // 电流负载率
         Double ratedCurrent = deviceAttribute.getRatedCurrent();
         Double ratedCurrent = deviceAttribute.getRatedCurrent();
         realScoreVo.setIaLoad(Arith.div(realScoreVo.getIa(), ratedCurrent));
         realScoreVo.setIaLoad(Arith.div(realScoreVo.getIa(), ratedCurrent));
         realScoreVo.setIbLoad(Arith.div(realScoreVo.getIb(), ratedCurrent));
         realScoreVo.setIbLoad(Arith.div(realScoreVo.getIb(), ratedCurrent));
         realScoreVo.setIcLoad(Arith.div(realScoreVo.getIc(), ratedCurrent));
         realScoreVo.setIcLoad(Arith.div(realScoreVo.getIc(), ratedCurrent));
-        //计算分数
-        //电压分数
+        // 计算分数
+        // 电压分数
         realScoreVo.setUaQ(computeUScore(realScoreVo.getUaQualified(), voltageLevel));
         realScoreVo.setUaQ(computeUScore(realScoreVo.getUaQualified(), voltageLevel));
         realScoreVo.setUbQ(computeUScore(realScoreVo.getUbQualified(), voltageLevel));
         realScoreVo.setUbQ(computeUScore(realScoreVo.getUbQualified(), voltageLevel));
         realScoreVo.setUcQ(computeUScore(realScoreVo.getUcQualified(), voltageLevel));
         realScoreVo.setUcQ(computeUScore(realScoreVo.getUcQualified(), voltageLevel));
@@ -362,7 +362,7 @@ public class RtAnalogDataServiceImpl extends AbstractCrudService<RtAnalogDataMap
         } else {
         } else {
             realScoreVo.setUQ(false);
             realScoreVo.setUQ(false);
         }
         }
-        //电流分数
+        // 电流分数
         realScoreVo.setIaLoadQ(realScoreVo.getIaLoad() <= 0.8);
         realScoreVo.setIaLoadQ(realScoreVo.getIaLoad() <= 0.8);
         realScoreVo.setIbLoadQ(realScoreVo.getIbLoad() <= 0.8);
         realScoreVo.setIbLoadQ(realScoreVo.getIbLoad() <= 0.8);
         realScoreVo.setIcLoadQ(realScoreVo.getIcLoad() <= 0.8);
         realScoreVo.setIcLoadQ(realScoreVo.getIcLoad() <= 0.8);
@@ -372,17 +372,17 @@ public class RtAnalogDataServiceImpl extends AbstractCrudService<RtAnalogDataMap
         } else {
         } else {
             realScoreVo.setILoadQ(false);
             realScoreVo.setILoadQ(false);
         }
         }
-        //电压平衡分数
+        // 电压平衡分数
         realScoreVo.setElBalunQ(realScoreVo.getElBalun() <= 0.15);
         realScoreVo.setElBalunQ(realScoreVo.getElBalun() <= 0.15);
         if (realScoreVo.getElBalunQ()) {
         if (realScoreVo.getElBalunQ()) {
             score += 20;
             score += 20;
         }
         }
-        //电流平衡分数
+        // 电流平衡分数
         realScoreVo.setVtBalunQ(realScoreVo.getVtBalun() <= 0.15);
         realScoreVo.setVtBalunQ(realScoreVo.getVtBalun() <= 0.15);
         if (realScoreVo.getVtBalunQ()) {
         if (realScoreVo.getVtBalunQ()) {
             score += 20;
             score += 20;
         }
         }
-        //功率
+        // 功率
         realScoreVo.setCosQ(realScoreVo.getCos() >= 0.9);
         realScoreVo.setCosQ(realScoreVo.getCos() >= 0.9);
         if (realScoreVo.getCosQ()) {
         if (realScoreVo.getCosQ()) {
             score += 20;
             score += 20;
@@ -1181,8 +1181,6 @@ public class RtAnalogDataServiceImpl extends AbstractCrudService<RtAnalogDataMap
     }
     }
 
 
 
 
-
-
     @Override
     @Override
     public List<RealScoreVO> evaluationReport(int siteId, Date time, int type) {
     public List<RealScoreVO> evaluationReport(int siteId, Date time, int type) {
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
@@ -1203,13 +1201,13 @@ public class RtAnalogDataServiceImpl extends AbstractCrudService<RtAnalogDataMap
             }
             }
         }
         }
         LambdaQueryWrapper<Device> queryWrapper1 = Wrappers.lambdaQuery();
         LambdaQueryWrapper<Device> queryWrapper1 = Wrappers.lambdaQuery();
-        queryWrapper1.eq(Device::getSiteId,siteId);
+        queryWrapper1.eq(Device::getSiteId, siteId);
         List<Device> deviceList = deviceService.list(queryWrapper1);
         List<Device> deviceList = deviceService.list(queryWrapper1);
         List<String> fieldDisplayOne183 = new ArrayList();
         List<String> fieldDisplayOne183 = new ArrayList();
         List<String> fieldDisplayOne171 = new ArrayList();
         List<String> fieldDisplayOne171 = new ArrayList();
         List<String> fieldDisplayOne173 = new ArrayList();
         List<String> fieldDisplayOne173 = new ArrayList();
         if (deviceList.size() > 0) {
         if (deviceList.size() > 0) {
-            for(int j = 0; j < deviceList.size(); j++){
+            for (int j = 0; j < deviceList.size(); j++) {
                 if (deviceList.get(j).getDeviceType().equals("1")) {
                 if (deviceList.get(j).getDeviceType().equals("1")) {
                     fieldDisplayOne183.add(deviceList.get(j).getDeviceCode());
                     fieldDisplayOne183.add(deviceList.get(j).getDeviceCode());
                 } else if (deviceList.get(j).getDeviceType().equals("3")) {
                 } else if (deviceList.get(j).getDeviceType().equals("3")) {
@@ -1221,11 +1219,11 @@ public class RtAnalogDataServiceImpl extends AbstractCrudService<RtAnalogDataMap
         }
         }
         List<EvaluationReporVo> evaluationReporVo1 = new ArrayList<>();
         List<EvaluationReporVo> evaluationReporVo1 = new ArrayList<>();
         List<EvaluationReporVo> evaluationReporVo2 = new ArrayList<>();
         List<EvaluationReporVo> evaluationReporVo2 = new ArrayList<>();
-        if (fieldDisplayOne183.size()>0){
-            evaluationReporVo1 = baseMapper.getEvaluationReportList(siteId, startTime, endtime,"ht_analog_data",fieldDisplayOne183);
+        if (fieldDisplayOne183.size() > 0) {
+            evaluationReporVo1 = baseMapper.getEvaluationReportList(siteId, startTime, endtime, "ht_analog_data", fieldDisplayOne183);
         }
         }
-        if (fieldDisplayOne173.size()>0){
-            evaluationReporVo2 = baseMapper.getEvaluationReportList(siteId, startTime, endtime,"ht_analog_173_data",fieldDisplayOne173);
+        if (fieldDisplayOne173.size() > 0) {
+            evaluationReporVo2 = baseMapper.getEvaluationReportList(siteId, startTime, endtime, "ht_analog_173_data", fieldDisplayOne173);
         }
         }
 
 
         List<EvaluationReporVo> evaluationReporVo = Stream.of(evaluationReporVo1, evaluationReporVo2).flatMap(Collection::stream).distinct().collect(Collectors.toList());
         List<EvaluationReporVo> evaluationReporVo = Stream.of(evaluationReporVo1, evaluationReporVo2).flatMap(Collection::stream).distinct().collect(Collectors.toList());
@@ -1262,8 +1260,8 @@ public class RtAnalogDataServiceImpl extends AbstractCrudService<RtAnalogDataMap
      */
      */
     public Boolean computeUScoreOne(Double qualified, Double voltageLevel) {
     public Boolean computeUScoreOne(Double qualified, Double voltageLevel) {
 //        double mul = Arith.mul(qualified, voltageLevel);
 //        double mul = Arith.mul(qualified, voltageLevel);
-        Double voltageLevels = voltageLevel+(voltageLevel / 100 * 7);
-        Double voltageLevelx = voltageLevel-(voltageLevel / 100 * 7);
+        Double voltageLevels = voltageLevel + (voltageLevel / 100 * 7);
+        Double voltageLevelx = voltageLevel - (voltageLevel / 100 * 7);
         if (voltageLevelx <= qualified && voltageLevels >= qualified) {
         if (voltageLevelx <= qualified && voltageLevels >= qualified) {
             return true;
             return true;
         }
         }
@@ -1285,26 +1283,26 @@ public class RtAnalogDataServiceImpl extends AbstractCrudService<RtAnalogDataMap
                 checkList.add(realScoreVo.getIa());
                 checkList.add(realScoreVo.getIa());
                 checkList.add(realScoreVo.getIb());
                 checkList.add(realScoreVo.getIb());
                 checkList.add(realScoreVo.getIc());
                 checkList.add(realScoreVo.getIc());
-                //电流不平衡
+                // 电流不平衡
                 realScoreVo.setElBalun(checkBalun(checkList));
                 realScoreVo.setElBalun(checkBalun(checkList));
                 checkList.clear();
                 checkList.clear();
                 checkList.add(realScoreVo.getUa());
                 checkList.add(realScoreVo.getUa());
                 checkList.add(realScoreVo.getUb());
                 checkList.add(realScoreVo.getUb());
                 checkList.add(realScoreVo.getUc());
                 checkList.add(realScoreVo.getUc());
-                //电压不平衡
+                // 电压不平衡
                 realScoreVo.setVtBalun(checkBalun(checkList));
                 realScoreVo.setVtBalun(checkBalun(checkList));
-                //电压合格率
+                // 电压合格率
                 double voltageLevel = Double.parseDouble(evaluationReporVo.get(i).getVoltageLevel());
                 double voltageLevel = Double.parseDouble(evaluationReporVo.get(i).getVoltageLevel());
                 realScoreVo.setUaQualified(Arith.sub(evaluationReporVo.get(i).getUa(), voltageLevel));
                 realScoreVo.setUaQualified(Arith.sub(evaluationReporVo.get(i).getUa(), voltageLevel));
                 realScoreVo.setUbQualified(Arith.sub(evaluationReporVo.get(i).getUb(), voltageLevel));
                 realScoreVo.setUbQualified(Arith.sub(evaluationReporVo.get(i).getUb(), voltageLevel));
                 realScoreVo.setUcQualified(Arith.sub(evaluationReporVo.get(i).getUc(), voltageLevel));
                 realScoreVo.setUcQualified(Arith.sub(evaluationReporVo.get(i).getUc(), voltageLevel));
-                //电流负载率
+                // 电流负载率
                 Double ratedCurrent = evaluationReporVo.get(i).getRatedCurrent();
                 Double ratedCurrent = evaluationReporVo.get(i).getRatedCurrent();
                 realScoreVo.setIaLoad(Arith.div(realScoreVo.getIa(), ratedCurrent));
                 realScoreVo.setIaLoad(Arith.div(realScoreVo.getIa(), ratedCurrent));
                 realScoreVo.setIbLoad(Arith.div(realScoreVo.getIb(), ratedCurrent));
                 realScoreVo.setIbLoad(Arith.div(realScoreVo.getIb(), ratedCurrent));
                 realScoreVo.setIcLoad(Arith.div(realScoreVo.getIc(), ratedCurrent));
                 realScoreVo.setIcLoad(Arith.div(realScoreVo.getIc(), ratedCurrent));
-                //计算分数
-                //电压分数
+                // 计算分数
+                // 电压分数
                 realScoreVo.setUaQ(computeUScoreOne(realScoreVo.getUa(), voltageLevel));
                 realScoreVo.setUaQ(computeUScoreOne(realScoreVo.getUa(), voltageLevel));
                 realScoreVo.setUbQ(computeUScoreOne(realScoreVo.getUb(), voltageLevel));
                 realScoreVo.setUbQ(computeUScoreOne(realScoreVo.getUb(), voltageLevel));
                 realScoreVo.setUcQ(computeUScoreOne(realScoreVo.getUc(), voltageLevel));
                 realScoreVo.setUcQ(computeUScoreOne(realScoreVo.getUc(), voltageLevel));
@@ -1314,7 +1312,7 @@ public class RtAnalogDataServiceImpl extends AbstractCrudService<RtAnalogDataMap
                 } else {
                 } else {
                     realScoreVo.setUQ(false);
                     realScoreVo.setUQ(false);
                 }
                 }
-                //电流分数
+                // 电流分数
                 realScoreVo.setIaLoadQ(realScoreVo.getIaLoad() <= 0.8);
                 realScoreVo.setIaLoadQ(realScoreVo.getIaLoad() <= 0.8);
                 realScoreVo.setIbLoadQ(realScoreVo.getIbLoad() <= 0.8);
                 realScoreVo.setIbLoadQ(realScoreVo.getIbLoad() <= 0.8);
                 realScoreVo.setIcLoadQ(realScoreVo.getIcLoad() <= 0.8);
                 realScoreVo.setIcLoadQ(realScoreVo.getIcLoad() <= 0.8);
@@ -1324,17 +1322,17 @@ public class RtAnalogDataServiceImpl extends AbstractCrudService<RtAnalogDataMap
                 } else {
                 } else {
                     realScoreVo.setILoadQ(false);
                     realScoreVo.setILoadQ(false);
                 }
                 }
-                //电压平衡分数
+                // 电压平衡分数
                 realScoreVo.setElBalunQ(realScoreVo.getElBalun() <= 0.15);
                 realScoreVo.setElBalunQ(realScoreVo.getElBalun() <= 0.15);
                 if (realScoreVo.getElBalunQ()) {
                 if (realScoreVo.getElBalunQ()) {
                     score += 20;
                     score += 20;
                 }
                 }
-                //电流平衡分数
+                // 电流平衡分数
                 realScoreVo.setVtBalunQ(realScoreVo.getVtBalun() <= 0.15);
                 realScoreVo.setVtBalunQ(realScoreVo.getVtBalun() <= 0.15);
                 if (realScoreVo.getVtBalunQ()) {
                 if (realScoreVo.getVtBalunQ()) {
                     score += 20;
                     score += 20;
                 }
                 }
-                //功率
+                // 功率
                 realScoreVo.setCosQ(realScoreVo.getCos() <= 0.15);
                 realScoreVo.setCosQ(realScoreVo.getCos() <= 0.15);
                 if (realScoreVo.getCosQ()) {
                 if (realScoreVo.getCosQ()) {
                     score += 20;
                     score += 20;
@@ -1394,4 +1392,8 @@ public class RtAnalogDataServiceImpl extends AbstractCrudService<RtAnalogDataMap
 //    }
 //    }
 
 
 
 
+    @Override
+    public List<RtAnalogData> getP(List<String> deviceCodes) {
+        return baseMapper.getP(deviceCodes);
+    }
 }
 }

+ 144 - 139
fiveep-service/src/main/java/com/bizmatics/service/impl/SiteServiceImpl.java

@@ -11,10 +11,7 @@ import com.bizmatics.common.mvc.base.AbstractCrudService;
 import com.bizmatics.model.*;
 import com.bizmatics.model.*;
 import com.bizmatics.model.system.SysUser;
 import com.bizmatics.model.system.SysUser;
 import com.bizmatics.model.vo.PlatformAreaVo;
 import com.bizmatics.model.vo.PlatformAreaVo;
-import com.bizmatics.persistence.mapper.AlarmPowerMapper;
-import com.bizmatics.persistence.mapper.DeviceMapper;
-import com.bizmatics.persistence.mapper.PlatformAreaMapper;
-import com.bizmatics.persistence.mapper.SiteMapper;
+import com.bizmatics.persistence.mapper.*;
 import com.bizmatics.persistence.mapper.system.SysUserMapper;
 import com.bizmatics.persistence.mapper.system.SysUserMapper;
 import com.bizmatics.service.*;
 import com.bizmatics.service.*;
 import com.bizmatics.service.enums.DeviceStatusCode;
 import com.bizmatics.service.enums.DeviceStatusCode;
@@ -30,6 +27,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
 import java.util.*;
 import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import java.util.stream.Stream;
@@ -65,6 +64,10 @@ public class SiteServiceImpl extends AbstractCrudService<SiteMapper, Site> imple
     private SysUserMapper userMapper;
     private SysUserMapper userMapper;
     @Autowired
     @Autowired
     private HtAnalogDataService htAnalogDataService;
     private HtAnalogDataService htAnalogDataService;
+    @Autowired
+    private ElectricityRateConfigMapper electricityRateConfigMapper;
+    @Autowired
+    private RtAnalogDataService rtAnalogDataService;
 
 
     @Override
     @Override
     public DeviceCountVO selectCount() {
     public DeviceCountVO selectCount() {
@@ -84,15 +87,28 @@ public class SiteServiceImpl extends AbstractCrudService<SiteMapper, Site> imple
     public List<Site> list(String name) {
     public List<Site> list(String name) {
         Integer userId = SecurityUtils.getLoginUser().getUser().getUserId().intValue();
         Integer userId = SecurityUtils.getLoginUser().getUser().getUserId().intValue();
         List<SysUser> tenantDaya = userMapper.getTenantId(SecurityUtils.getLoginUser().getUser().getUserId());
         List<SysUser> tenantDaya = userMapper.getTenantId(SecurityUtils.getLoginUser().getUser().getUserId());
-        if (tenantDaya.size() < 0) {
+        if (tenantDaya.isEmpty()) {
             throw new BusinessException("无此租户,请联系管理员");
             throw new BusinessException("无此租户,请联系管理员");
         }
         }
         List<Site> siteList = new ArrayList<>();
         List<Site> siteList = new ArrayList<>();
-        if (tenantDaya.get(0).getUserType().equals("01")) {
+        if ("01".equals(tenantDaya.get(0).getUserType())) {
             siteList = baseMapper.listOne(name, tenantDaya.get(0).getTenantId());
             siteList = baseMapper.listOne(name, tenantDaya.get(0).getTenantId());
-        } else if (tenantDaya.get(0).getUserType().equals("00")) {
+        } else if ("00".equals(tenantDaya.get(0).getUserType())) {
             siteList = baseMapper.list(userId, name, tenantDaya.get(0).getTenantId());
             siteList = baseMapper.list(userId, name, tenantDaya.get(0).getTenantId());
         }
         }
+
+        // 查询是否存在费用
+        List<Integer> siteIds = siteList.stream()
+                .map(Site::getId)
+                .collect(Collectors.toList());
+
+        Set<Integer> exists = electricityRateConfigMapper.selectBatchIds(siteIds)
+                .stream()
+                .map(ElectricityRateConfig::getSiteId)
+                .collect(Collectors.toSet());
+
+        siteList.forEach(site -> site.setCostTypeStatus(exists.contains(site.getId())));
+
         return siteList;
         return siteList;
     }
     }
 
 
@@ -194,7 +210,7 @@ public class SiteServiceImpl extends AbstractCrudService<SiteMapper, Site> imple
         }
         }
         SysUser user = SecurityUtils.getLoginUser().getUser();
         SysUser user = SecurityUtils.getLoginUser().getUser();
         Site site1 = siteVOT.getSite();
         Site site1 = siteVOT.getSite();
-        site1.setCreateTime(new Date());
+        site1.setCreateTime(LocalDateTime.now());
         site1.setCreator(user.getUserName());
         site1.setCreator(user.getUserName());
         site1.setCompanyCode(11111);
         site1.setCompanyCode(11111);
         site1.setEnable(1);
         site1.setEnable(1);
@@ -363,149 +379,138 @@ public class SiteServiceImpl extends AbstractCrudService<SiteMapper, Site> imple
     }
     }
 
 
     @Override
     @Override
-    public CommonPage<SiteLoadAnalysisVO> siteLoadAnalysis(Integer siteId, Integer pageNum, Integer pageSize) {
-        List<SiteLoadAnalysisVO> records = new ArrayList<>();
-        LambdaQueryWrapper<Site> siteQuery = Wrappers.lambdaQuery();
-        siteQuery.eq(Site::getId, siteId);
-        Site site = baseMapper.selectOne(siteQuery);
-        log.info("站点信息:{}", site);
+    public List<SiteLoadAnalysisVO> siteLoadAnalysis(Integer siteId,
+                                                     String startTime,
+                                                     String endTime) {
+
+        SiteLoadAnalysisVO siteRow = new SiteLoadAnalysisVO();
+
+        /* ---------- 1. 站点&动态属性 ---------- */
+        Site site = Optional.ofNullable(
+                        baseMapper.selectById(siteId))
+                .orElseGet(() -> {
+                    log.warn("站点 {} 不存在", siteId);
+                    return null;
+                });
         if (site == null) {
         if (site == null) {
-            return new CommonPage<>();
+            return Collections.singletonList(siteRow);
         }
         }
 
 
-        // 站点动态属性查询
-        LambdaQueryWrapper<SiteDynamicProperties> siteDynamicPropertiesQuery = Wrappers.lambdaQuery();
-        siteDynamicPropertiesQuery.eq(SiteDynamicProperties::getSiteId, siteId);
-        SiteDynamicProperties siteDynamicProperties = siteDynamicPropertiesService.getOne(siteDynamicPropertiesQuery);
-        log.info("站点动态属性信息:{}", siteDynamicProperties);
-        if (siteDynamicProperties == null) {
-            log.error("站点{}动态属性不存在", siteId);
+        SiteDynamicProperties sdp = siteDynamicPropertiesService.lambdaQuery()
+                .eq(SiteDynamicProperties::getSiteId, siteId)
+                .one();
+        if (sdp == null) {
+            log.warn("站点 {} 动态属性缺失", siteId);
         }
         }
 
 
-        // 存入接口返回
-        SiteLoadAnalysisVO siteLoadAnalysisVO = new SiteLoadAnalysisVO();
-        siteLoadAnalysisVO.setId(site.getId());
-        siteLoadAnalysisVO.setName(site.getSiteName());
-        // 额定容量=装机容量
-        siteLoadAnalysisVO.setRatedCapacity(Double.valueOf(site.getInstalledCapacity()));
-        // 额定电压
-        try {
-            siteLoadAnalysisVO.setRatedVoltage(StringUtils.isBlank(siteDynamicProperties.getVoltageLevel()) ? 0.0 : Double.parseDouble(siteDynamicProperties.getVoltageLevel()) / 1000.0);
-        } catch (NumberFormatException e) {
-            log.error("站点{}  电压等级(单位:V)格式转换错误{} ,已重置为0.0", siteDynamicProperties.getSiteId(), e);
-            siteLoadAnalysisVO.setRatedVoltage(0.0);
-        }
-        // 先插入部分站点信息
-        records.add(0, siteLoadAnalysisVO);
-
-        List<DeviceList> deviceList = deviceService.deviceList(String.valueOf(siteId));
-        log.info("设备信息list:{}", deviceList);
-
-        // 类型为1的设备为站点的有功功率(总和)
-        List<DeviceList> typeOneDevices = new ArrayList<>();
-        List<DeviceList> typeOtherDevices = new ArrayList<>();
-        List<String> deviceCodeList = new ArrayList<>();
-        // Map<String, Double> pMap = new HashMap<>();
-        Double p = 0.0;
-
-        if (!deviceList.isEmpty()) {
-            for (DeviceList device : deviceList) {
-                String deviceType = device.getDeviceType();
-                if ("1".equals(deviceType)) {
-                    typeOneDevices.add(device);
-                } else if (!"2".equals(deviceType)) {
-                    typeOtherDevices.add(device);
-                }
-                deviceCodeList.add(device.getDeviceCode());
-            }
-        } else {
-            log.error("站点{}无设备", siteId);
-            return new CommonPage<>(records, records.size(), pageSize, pageNum);
+        /* ---------- 2. 设备 ---------- */
+        List<DeviceList> devices = deviceService.deviceList(String.valueOf(siteId));
+        if (CollectionUtils.isEmpty(devices)) {
+            log.warn("站点 {} 无设备", siteId);
+            return Collections.singletonList(siteRow);
         }
         }
 
 
-        // pMap = (htAnalogDataService.getP(deviceCodeList)).stream().collect(Collectors.toMap(HtAnalogData::getDeviceName, HtAnalogData::getP));
-        List<HtAnalogData> pList = htAnalogDataService.getP(deviceCodeList);
-        if (pList.isEmpty()) {
-            log.error("站点{},设备编号{} 无有功功率数据", siteId, deviceCodeList);
-            for (DeviceList device : deviceList) {
-                SiteLoadAnalysisVO deviceLoadAnalysis = new SiteLoadAnalysisVO();
-                deviceLoadAnalysis.setName(device.getDeviceName());
-                deviceLoadAnalysis.setId(null);
-                deviceLoadAnalysis.setCode(device.getDeviceCode());
-                deviceLoadAnalysis.setRatedCapacity(0.0);
-                deviceLoadAnalysis.setRatedVoltage(0.0);
-                deviceLoadAnalysis.setP(0.0);
-                deviceLoadAnalysis.setLoadRate(0.0);
-                deviceLoadAnalysis.setDataTime(null);
-                records.add(deviceLoadAnalysis);
-            }
-            return new CommonPage<>(records, records.size(), pageSize, pageNum);
-        }
-        for (DeviceList device : deviceList) {
-            log.info("设备信息:{}", device);
-            SiteLoadAnalysisVO deviceLoadAnalysis = new SiteLoadAnalysisVO();
-            deviceLoadAnalysis.setId(device.getId());
-            deviceLoadAnalysis.setName(device.getDeviceName());
-            deviceLoadAnalysis.setCode(device.getDeviceCode());
-            double ratedCapacity = device.getRatedCurrent() * device.getRatedVoltage();
-            log.info("额定容量:{}", ratedCapacity);
-            deviceLoadAnalysis.setRatedCapacity(ratedCapacity);
-            deviceLoadAnalysis.setRatedVoltage(device.getRatedVoltage());
-
-            LocalDateTime dateTime = pList.stream()
-                    .filter(ht -> ht.getDeviceName().equals(device.getDeviceCode()))
-                    .findFirst()
-                    .map(HtAnalogData::getDataTime)
-                    .orElse(null);
-            deviceLoadAnalysis.setDataTime(dateTime);
-
-            // deviceLoadAnalysis.setP(pMap.get(device.getDeviceCode()));
-
-            Double m = pList.stream()
-                    .filter(ht -> ht.getDeviceName().equals(device.getDeviceCode()))
-                    .findFirst()
-                    .map(HtAnalogData::getP)
-                    .orElse(0.0);
-            deviceLoadAnalysis.setP(m);
-
-            if (ratedCapacity != 0.0) {
-                deviceLoadAnalysis.setLoadRate(Arith.div(m, ratedCapacity, 3));
-            } else {
-                deviceLoadAnalysis.setLoadRate(0.0);
+        // 提前过滤并分组
+        Map<Boolean, List<DeviceList>> group = devices.stream()
+                .collect(Collectors.partitioningBy(d -> "1".equals(d.getDeviceType())));
+        List<DeviceList> typeOneDevices = group.get(true);
+        List<DeviceList> typeOtherDevices = group.get(false).stream()
+                .filter(d -> !"2".equals(d.getDeviceType()))
+                .collect(Collectors.toList());
+
+        List<String> deviceCodes = devices.stream()
+                .map(DeviceList::getDeviceCode)
+                .collect(Collectors.toList());
+
+        /* ---------- 3. 有功功率数据 ---------- */
+        // 解析时间
+        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        LocalDateTime start = null, end = null;
+        if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
+            try {
+                start = LocalDateTime.parse(startTime, fmt);
+                end = LocalDateTime.parse(endTime, fmt);
+            } catch (DateTimeParseException ex) {
+                throw new BusinessException("时间格式错误: " + ex.getMessage());
             }
             }
-            records.add(deviceLoadAnalysis);
         }
         }
 
 
-        // 没有的话则是其他类型的总和(类型2 视频监控除外)
-        if (!typeOneDevices.isEmpty()) {
-            for (DeviceList device : typeOneDevices) {
-                Double m = pList.stream()
-                        .filter(ht -> ht.getDeviceName().equals(device.getDeviceCode()))
-                        .findFirst()
-                        .map(HtAnalogData::getP)
-                        .orElse(0.0);
-                p += m;
-            }
-        } else {
-            for (DeviceList device : typeOtherDevices) {
-                Double m = pList.stream()
-                        .filter(ht -> ht.getDeviceName().equals(device.getDeviceCode()))
-                        .findFirst()
-                        .map(HtAnalogData::getP)
-                        .orElse(0.0);
-                p += m;
-            }
-        }
-        records.get(0).setP(p);
+        // 统一获取数据并转 Map
+        Map<String, ? extends Number> pMap = start != null
+                ? htAnalogDataService.getP(deviceCodes, start, end)
+                .stream()
+                .collect(Collectors.toMap(HtAnalogData::getDeviceName,
+                        HtAnalogData::getP,
+                        (v1, v2) -> v1))
+                : rtAnalogDataService.getP(deviceCodes)
+                .stream()
+                .collect(Collectors.toMap(RtAnalogData::getDeviceName,
+                        RtAnalogData::getP,
+                        (v1, v2) -> v1));
+
+        /* ---------- 4. 组装结果 ---------- */
+        // 站点根节点
+        siteRow.setId(site.getId());
+        siteRow.setName(site.getSiteName());
+        siteRow.setRatedCapacity(Optional.ofNullable(site.getInstalledCapacity()).map(Double::valueOf).orElse(0.0));
+        siteRow.setRatedVoltage(
+                Optional.ofNullable(sdp)
+                        .map(SiteDynamicProperties::getVoltageLevel)
+                        .filter(StringUtils::isNotBlank)
+                        .map(v -> Double.parseDouble(v) / 1000.0)
+                        .orElse(0.0));
+        siteRow.setDataTime(site.getCreateTime());
+
+        // 汇总功率、负载率用
+        double totalP = (typeOneDevices.isEmpty() ? typeOtherDevices : typeOneDevices)
+                .stream()
+                .mapToDouble(d -> Optional.ofNullable(pMap.get(d.getDeviceCode()))
+                        .map(Number::doubleValue)
+                        .orElse(0.0))
+                .sum();
+        siteRow.setP(totalP);
+        siteRow.setLoadRate(siteRow.getRatedCapacity() == 0
+                ? 0.0
+                : Arith.div(totalP, siteRow.getRatedCapacity(), 3));
+
+        /* --- 构造 children --- */
+        LocalDateTime finalStart = start, finalEnd = end;
+        List<SiteLoadAnalysisVO> children = devices.stream()
+                .map(d -> {
+                    SiteLoadAnalysisVO dev = new SiteLoadAnalysisVO();
+                    dev.setId(d.getId());
+                    dev.setName(d.getDeviceName());
+                    dev.setCode(d.getDeviceCode());
+
+                    double ratedCap = d.getRatedCurrent() * d.getRatedVoltage();
+                    dev.setRatedCapacity(ratedCap);
+                    dev.setRatedVoltage(d.getRatedVoltage());
+
+                    double p = Optional.ofNullable(pMap.get(d.getDeviceCode()))
+                            .map(Number::doubleValue)
+                            .orElse(0.0);
+                    dev.setP(p);
+                    dev.setLoadRate(ratedCap == 0 ? 0.0 : Arith.div(p, ratedCap, 3));
+
+                    // 数据时间
+                    if (finalStart != null) {
+                        htAnalogDataService.getP(deviceCodes, finalStart, finalEnd).stream()
+                                .filter(h -> h.getDeviceName().equals(d.getDeviceCode()))
+                                .findFirst()
+                                .ifPresent(h -> dev.setDataTime(h.getDataTime()));
+                    } else {
+                        rtAnalogDataService.getP(deviceCodes).stream()
+                                .filter(h -> h.getDeviceName().equals(d.getDeviceCode()))
+                                .findFirst()
+                                .ifPresent(h -> dev.setDataTime(h.getDataTime()));
+                    }
+                    return dev;
+                })
+                .collect(Collectors.toList());
 
 
-        // 负载率
-        if (records.get(0).getRatedCapacity() != 0.0) {
-            records.get(0).setLoadRate(Arith.div(p, records.get(0).getRatedCapacity(), 3));
-        } else {
-            records.get(0).setLoadRate(0.0);
-        }
+        siteRow.setChildren(children);
 
 
-        return new CommonPage<>(records, records.size(), pageNum, pageSize);
+        return Collections.singletonList(siteRow);
     }
     }
 
 
 }
 }

+ 46 - 20
fiveep-service/src/main/java/com/bizmatics/service/job/SiteDailyElectricityCostTask.java

@@ -34,17 +34,20 @@ public class SiteDailyElectricityCostTask implements ApplicationRunner {
     /** 应用启动后立即执行一次 */
     /** 应用启动后立即执行一次 */
     @Override
     @Override
     public void run(ApplicationArguments args) {
     public void run(ApplicationArguments args) {
-        log.info("立即执行一次日电费记录");
+        log.info("立即执行一次日电量电费记录");
         // calculateDailyElectricityCost();
         // calculateDailyElectricityCost();
     }
     }
 
 
     // 每天凌晨0点过5分执行,计算前一天的用电费用
     // 每天凌晨0点过5分执行,计算前一天的用电费用
-    @Scheduled(cron = "0 5 0 * * ?")
+    //@Scheduled(cron = "0 5 0 * * ?")
+
+    // 每小时第5分钟执行一次
+    @Scheduled(cron = "0 5 * * * ?")
     public void calculateDailyElectricityCost() {
     public void calculateDailyElectricityCost() {
-        LocalDate yesterday = LocalDate.now().minusDays(1);
-        // LocalDate yesterday = LocalDate.now();
+        // LocalDate yesterday = LocalDate.now().minusDays(1);
+        LocalDate yesterday = LocalDate.now();
         // LocalDate yesterday = LocalDate.parse("2025-07-19");
         // LocalDate yesterday = LocalDate.parse("2025-07-19");
-        log.info("开始计算{}的用电费用", yesterday);
+        // log.info("开始计算{}的用电费用", yesterday);
 
 
         try {
         try {
             calculateElectricityCostForDate(yesterday);
             calculateElectricityCostForDate(yesterday);
@@ -80,7 +83,7 @@ public class SiteDailyElectricityCostTask implements ApplicationRunner {
     private Map<Integer, List<String>> getSiteDevicesMap() {
     private Map<Integer, List<String>> getSiteDevicesMap() {
         Map<Integer, List<String>> siteDevicesMap = new HashMap<>();
         Map<Integer, List<String>> siteDevicesMap = new HashMap<>();
 
 
-        String sql = "SELECT site_id, device_code FROM device WHERE device_type = '1' AND enable = 1";
+        String sql = "SELECT site_id, device_code FROM device WHERE device_type IN ('1','3','4') AND enable = 1";
 
 
         jdbcTemplate.query(sql, rs -> {
         jdbcTemplate.query(sql, rs -> {
             Integer siteId = rs.getInt("site_id");
             Integer siteId = rs.getInt("site_id");
@@ -121,6 +124,13 @@ public class SiteDailyElectricityCostTask implements ApplicationRunner {
         BigDecimal valleyCost = BigDecimal.ZERO;
         BigDecimal valleyCost = BigDecimal.ZERO;
         BigDecimal totalCost = BigDecimal.ZERO;
         BigDecimal totalCost = BigDecimal.ZERO;
 
 
+        // 初始化用电量
+        BigDecimal sharpPeak = BigDecimal.ZERO;
+        BigDecimal peak = BigDecimal.ZERO;
+        BigDecimal flat = BigDecimal.ZERO;
+        BigDecimal valley = BigDecimal.ZERO;
+        BigDecimal totalElectricity = BigDecimal.ZERO;
+
         // 计算每个时间段的电费
         // 计算每个时间段的电费
         for (int i = 1; i < electricityDataList.size(); i++) {
         for (int i = 1; i < electricityDataList.size(); i++) {
             ElectricityData prev = electricityDataList.get(i - 1);
             ElectricityData prev = electricityDataList.get(i - 1);
@@ -154,19 +164,24 @@ public class SiteDailyElectricityCostTask implements ApplicationRunner {
             // 计算电费:用电量 × 电价
             // 计算电费:用电量 × 电价
             BigDecimal cost = electricityUsage.multiply(config.getElectricityPrice());
             BigDecimal cost = electricityUsage.multiply(config.getElectricityPrice());
             totalCost = totalCost.add(cost).setScale(2, RoundingMode.HALF_UP);
             totalCost = totalCost.add(cost).setScale(2, RoundingMode.HALF_UP);
+            totalElectricity = totalElectricity.add(electricityUsage);
 
 
             switch (config.getPeakValleyAttribute()) {
             switch (config.getPeakValleyAttribute()) {
                 case 1: // 尖
                 case 1: // 尖
                     sharpPeakCost = sharpPeakCost.add(cost).setScale(2, RoundingMode.HALF_UP);
                     sharpPeakCost = sharpPeakCost.add(cost).setScale(2, RoundingMode.HALF_UP);
+                    sharpPeak = sharpPeak.add(electricityUsage);
                     break;
                     break;
                 case 2: // 峰
                 case 2: // 峰
                     peakCost = peakCost.add(cost).setScale(2, RoundingMode.HALF_UP);
                     peakCost = peakCost.add(cost).setScale(2, RoundingMode.HALF_UP);
+                    peak = peak.add(electricityUsage);
                     break;
                     break;
                 case 3: // 平
                 case 3: // 平
                     flatCost = flatCost.add(cost).setScale(2, RoundingMode.HALF_UP);
                     flatCost = flatCost.add(cost).setScale(2, RoundingMode.HALF_UP);
+                    flat = flat.add(electricityUsage);
                     break;
                     break;
                 case 4: // 谷
                 case 4: // 谷
                     valleyCost = valleyCost.add(cost).setScale(2, RoundingMode.HALF_UP);
                     valleyCost = valleyCost.add(cost).setScale(2, RoundingMode.HALF_UP);
+                    valley = valley.add(electricityUsage);
                     break;
                     break;
                 default:
                 default:
                     log.warn("未知的峰谷属性: {}", config.getPeakValleyAttribute());
                     log.warn("未知的峰谷属性: {}", config.getPeakValleyAttribute());
@@ -175,10 +190,15 @@ public class SiteDailyElectricityCostTask implements ApplicationRunner {
 
 
         // 保存计算结果
         // 保存计算结果
         saveElectricityRecord(siteId, deviceCode, date, sharpPeakCost, peakCost,
         saveElectricityRecord(siteId, deviceCode, date, sharpPeakCost, peakCost,
-                flatCost, valleyCost, totalCost);
-
-        log.info("站点{}设备{}在{}的电费计算完成:尖峰{}元,峰{}元,平{}元,谷{}元,总计{}元",
-                siteId, deviceCode, date, sharpPeakCost, peakCost, flatCost, valleyCost, totalCost);
+                flatCost, valleyCost, totalCost, sharpPeak, peak, flat, valley, totalElectricity);
+
+        log.info("站点{}设备{}在{}的电费计算完成:尖峰{}元({}kWh),峰{}元({}kWh),平{}元({}kWh),谷{}元({}kWh),总计{}元({}kwh)",
+                siteId, deviceCode, date,
+                sharpPeakCost, sharpPeak,
+                peakCost, peak,
+                flatCost, flat,
+                valleyCost, valley,
+                totalCost, totalElectricity);
     }
     }
 
 
     private List<TimePriceConfig> getTimePriceConfigs(Integer siteId, int month) {
     private List<TimePriceConfig> getTimePriceConfigs(Integer siteId, int month) {
@@ -250,17 +270,18 @@ public class SiteDailyElectricityCostTask implements ApplicationRunner {
     private void saveElectricityRecord(Integer siteId, String deviceCode, LocalDate date,
     private void saveElectricityRecord(Integer siteId, String deviceCode, LocalDate date,
                                        BigDecimal sharpPeakCost, BigDecimal peakCost,
                                        BigDecimal sharpPeakCost, BigDecimal peakCost,
                                        BigDecimal flatCost, BigDecimal valleyCost,
                                        BigDecimal flatCost, BigDecimal valleyCost,
-                                       BigDecimal totalCost) {
+                                       BigDecimal totalCost, BigDecimal sharpPeak,
+                                       BigDecimal peak, BigDecimal flat, BigDecimal valley,
+                                       BigDecimal totalElectricity) {
         String sql = "INSERT INTO site_electricity_record " +
         String sql = "INSERT INTO site_electricity_record " +
-                "(site_id, device_code, date, peak_cost, flat_cost, " +
-                "valley_cost, sharp_peak_cost, total_cost) " +
-                "VALUES (?, ?, ?, ?, ?, ?, ?, ?) " +
+                "(site_id, device_code, date, peak_cost, flat_cost, valley_cost, sharp_peak_cost, total_cost, " +
+                "sharp_peak, peak, flat, valley, total_electricity) " +
+                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) " +
                 "ON DUPLICATE KEY UPDATE " +
                 "ON DUPLICATE KEY UPDATE " +
-                "peak_cost = VALUES(peak_cost), " +
-                "flat_cost = VALUES(flat_cost), " +
-                "valley_cost = VALUES(valley_cost), " +
-                "sharp_peak_cost = VALUES(sharp_peak_cost), " +
-                "total_cost = VALUES(total_cost)";
+                "peak_cost = VALUES(peak_cost), flat_cost = VALUES(flat_cost), valley_cost = VALUES(valley_cost), " +
+                "sharp_peak_cost = VALUES(sharp_peak_cost), total_cost = VALUES(total_cost), " +
+                "sharp_peak = VALUES(sharp_peak), peak = VALUES(peak), " +
+                "flat = VALUES(flat), valley = VALUES(valley), total_electricity = VALUES(total_electricity)";
 
 
         try {
         try {
             jdbcTemplate.update(sql,
             jdbcTemplate.update(sql,
@@ -271,7 +292,12 @@ public class SiteDailyElectricityCostTask implements ApplicationRunner {
                     flatCost,
                     flatCost,
                     valleyCost,
                     valleyCost,
                     sharpPeakCost,
                     sharpPeakCost,
-                    totalCost
+                    totalCost,
+                    sharpPeak,
+                    peak,
+                    flat,
+                    valley,
+                    totalElectricity
             );
             );
             log.debug("成功保存站点{}设备{}的电费记录", siteId, deviceCode);
             log.debug("成功保存站点{}设备{}的电费记录", siteId, deviceCode);
         } catch (Exception e) {
         } catch (Exception e) {

+ 44 - 0
fiveep-service/src/main/java/com/bizmatics/service/vo/ElectricityTrendRequestVO.java

@@ -0,0 +1,44 @@
+package com.bizmatics.service.vo;
+
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+import java.util.List;
+
+/**
+ *
+ * @author fyc
+ * @email yuchuan.fu@chinausky.com
+ * @date 2025/9/5
+ */
+@Data
+public class ElectricityTrendRequestVO {
+
+    /**
+     * 站点id
+     */
+    private Integer siteId;
+
+    /**
+     * 查询类型 1:电量,2:费用
+     */
+    private Integer type;
+
+    /**
+     * 开始时间
+     */
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate startTime;
+
+    /**
+     * 结束时间
+     */
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate endTime;
+
+    /**
+     * 设备编码列表
+     */
+    private List<String> deviceCodes;
+}

+ 27 - 0
fiveep-service/src/main/java/com/bizmatics/service/vo/ElectricityTrendResponseVO.java

@@ -0,0 +1,27 @@
+package com.bizmatics.service.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ *
+ * @author fyc
+ * @email yuchuan.fu@chinausky.com
+ * @date 2025/9/5
+ */
+@Data
+public class ElectricityTrendResponseVO {
+
+    /**
+     * 设备名称
+     */
+    private String deviceCode;
+
+    /**
+     * 设备数据
+     */
+    private List<ElectricityTrendVO> data;
+}

+ 41 - 0
fiveep-service/src/main/java/com/bizmatics/service/vo/ElectricityTrendVO.java

@@ -0,0 +1,41 @@
+package com.bizmatics.service.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ *
+ * @author fyc
+ * @email yuchuan.fu@chinausky.com
+ * @date 2025/9/5
+ */
+@Data
+public class ElectricityTrendVO {
+
+    /**
+     * 时间
+     */
+    private String time;
+
+    /**
+     * 尖
+     */
+    private BigDecimal sharp;
+
+    /**
+     * 峰
+     */
+    private BigDecimal peak;
+
+    /**
+     * 平
+     */
+    private BigDecimal flat;
+
+    /**
+     * 谷
+     */
+    private BigDecimal valley;
+
+}

+ 6 - 0
fiveep-service/src/main/java/com/bizmatics/service/vo/SiteLoadAnalysisVO.java

@@ -1,11 +1,14 @@
 package com.bizmatics.service.vo;
 package com.bizmatics.service.vo;
 
 
 import com.bizmatics.service.config.CustomerDoubleSerialize;
 import com.bizmatics.service.config.CustomerDoubleSerialize;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import lombok.Data;
 import lombok.Data;
 
 
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.Date;
+import java.util.List;
 
 
 /**
 /**
  *
  *
@@ -60,4 +63,7 @@ public class SiteLoadAnalysisVO {
      * 上报时间
      * 上报时间
      */
      */
     private LocalDateTime dataTime;
     private LocalDateTime dataTime;
+
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    private List<SiteLoadAnalysisVO> children = new ArrayList<>();
 }
 }

+ 53 - 0
fiveep-service/src/main/java/com/bizmatics/service/vo/TimeSharingElectricityRequestVO.java

@@ -0,0 +1,53 @@
+package com.bizmatics.service.vo;
+
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+import java.util.List;
+
+/**
+ *
+ * @author fyc
+ * @email yuchuan.fu@chinausky.com
+ * @date 2025/9/4
+ */
+@Data
+public class TimeSharingElectricityRequestVO {
+    /**
+     * 站点id
+     */
+    private Integer siteId;
+
+    /**
+     * 设备类型 1:支路 2:分项
+     */
+    private Integer deviceType;
+
+    /**
+     * 开始时间
+     */
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate startTime;
+
+    /**
+     * 结束时间
+     */
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate endTime;
+
+    /**
+     * 页数
+     */
+    private Integer pageNum;
+
+    /**
+     * 每页数量
+     */
+    private Integer pageSize;
+
+    /**
+     * 设备编码
+     */
+    private List<String> deviceCodes;
+}

+ 76 - 0
fiveep-service/src/main/java/com/bizmatics/service/vo/TimeSharingElectricityResponseVO.java

@@ -0,0 +1,76 @@
+package com.bizmatics.service.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ *
+ * @author fyc
+ * @email yuchuan.fu@chinausky.com
+ * @date 2025/9/4
+ */
+@Data
+public class TimeSharingElectricityResponseVO {
+
+    /**
+     * 设备名称
+     */
+    private String deviceName;
+
+    /**
+     * 尖 电量
+     */
+    private BigDecimal sharpNum;
+
+    /**
+     * 峰 电量
+     */
+    private BigDecimal peakNum;
+
+    /**
+     * 平 电量
+     */
+    private BigDecimal flatNum;
+
+    /**
+     * 谷 电量
+     */
+    private BigDecimal valleyNum;
+
+    /**
+     * 总 电量
+     */
+    private BigDecimal totalNum;
+
+    /**
+     * 尖 电费
+     */
+    private BigDecimal sharpPrice;
+
+    /**
+     * 峰 电费
+     */
+    private BigDecimal peakPrice;
+
+    /**
+     * 平 电费
+     */
+    private BigDecimal flatPrice;
+
+    /**
+     * 谷 电费
+     */
+    private BigDecimal valleyPrice;
+
+    /**
+     * 总 电费
+     */
+    private BigDecimal totalPrice;
+
+    /**
+     * 数据时间区间
+     * 也用于导出文件名
+     */
+    private String time;
+}

+ 1 - 1
pom.xml

@@ -50,7 +50,7 @@
         <!--apache-->
         <!--apache-->
         <commons-lang3.version>3.11</commons-lang3.version>
         <commons-lang3.version>3.11</commons-lang3.version>
         <commons-beanutils.version>1.9.4</commons-beanutils.version>
         <commons-beanutils.version>1.9.4</commons-beanutils.version>
-        <commons-io.version>2.6</commons-io.version>
+        <commons-io.version>2.11.0</commons-io.version>
         <okhttp3.version>4.8.1</okhttp3.version>
         <okhttp3.version>4.8.1</okhttp3.version>
         <openCsv.version>4.6</openCsv.version>
         <openCsv.version>4.6</openCsv.version>