diff --git a/hzims-service-api/hzims-operational-api/src/main/java/com/hnac/hzims/operational/main/vo/WindAreaDutyVo.java b/hzims-service-api/hzims-operational-api/src/main/java/com/hnac/hzims/operational/main/vo/WindAreaDutyVo.java new file mode 100644 index 0000000..89f5c9d --- /dev/null +++ b/hzims-service-api/hzims-operational-api/src/main/java/com/hnac/hzims/operational/main/vo/WindAreaDutyVo.java @@ -0,0 +1,146 @@ +package com.hnac.hzims.operational.main.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.NullSerializer; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author ysj + */ +@Data +@ApiModel(value = "风电站点app指标数据") +public class WindAreaDutyVo { + + @ApiModelProperty(value = "机构Id") + private Long deptId; + + @ApiModelProperty(value = "开始时间") + private String start; + + @ApiModelProperty(value = "结束时间") + private String end; + + @ApiModelProperty("班次") + private String shift; + + @ApiModelProperty("班组") + private String team; + + @ApiModelProperty("班组长") + private String teamLeader; + + @ApiModelProperty("班成员") + private String classMember; + + @ApiModelProperty("下一班次") + private String nextShift; + + @ApiModelProperty("下一班组") + private String nextTeam; + + @ApiModelProperty("下一班组长") + private String nextTeamLeader; + + @ApiModelProperty("下一班成员") + private String nextClassMember; + + @ApiModelProperty("缺陷总数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer defectSum; + + @ApiModelProperty("缺陷未解决数量") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer unsolvedCount; + + @ApiModelProperty("缺陷已解决数量") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer solvedCount; + + @ApiModelProperty("缺陷严重数量") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer seriousCount; + + @ApiModelProperty("消缺率") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Double defectRate; + + @ApiModelProperty("巡检任务总数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer inspectionTaskCount; + + @ApiModelProperty("巡检完成数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer inspectionTaskFinishCount; + + @ApiModelProperty("未执行巡检任务数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer notInspectionTaskCount; + + @ApiModelProperty("日常维护任务总数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer maintenanceTaskCount; + + @ApiModelProperty("日常维护执行任务完成数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer maintenanceTaskFinishCount; + + @ApiModelProperty("日常维护未执行任务数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer notMaintenanceTaskCount; + + @ApiModelProperty("检修任务总数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer overhaulTaskCount; + + @ApiModelProperty("检修任务执行完成总数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer overhaulTaskFinishCount; + + @ApiModelProperty("检修任务未执行总数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer notOverhaulTaskCount; + + @ApiModelProperty("任务完成率") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Double taskRate; + + /**=============================================风电指标数据=============================================**/ + + @ApiModelProperty("计划发电量") + private Double plan; + + @ApiModelProperty(value = "年实际发电量") + private Double generate; + + @ApiModelProperty(value = "年发电量完成率") + private Double generateComplete; + + @ApiModelProperty("平均风速: m/s") + private Double speed; + + @ApiModelProperty("上网电量") + private Double surfPower; + + @ApiModelProperty("下网电量") + private Double belowPower; + + @ApiModelProperty("可用时长") + private Double available; + + @ApiModelProperty("综合用电量") + private Double comprehensivePower; + + @ApiModelProperty("峰值功率") + private Double peakPower; + + @ApiModelProperty("故障时长: 单位-小时") + private Double faultHours; + + @ApiModelProperty("短期预测准确率") + private Double accuracy; + + @ApiModelProperty("超短准确率") + private Double ultraShortAccuracy; +} diff --git a/hzims-service-api/hzims-operational-api/src/main/java/com/hnac/hzims/operational/main/vo/WindAreaVo.java b/hzims-service-api/hzims-operational-api/src/main/java/com/hnac/hzims/operational/main/vo/WindAreaVo.java new file mode 100644 index 0000000..80117ab --- /dev/null +++ b/hzims-service-api/hzims-operational-api/src/main/java/com/hnac/hzims/operational/main/vo/WindAreaVo.java @@ -0,0 +1,41 @@ +package com.hnac.hzims.operational.main.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.NullSerializer; +import com.hnac.hzims.hzimsweather.response.weather.Now; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author ysj + */ +@Data +@ApiModel(value = "风电站点区域数据") +public class WindAreaVo { + + @ApiModelProperty(value = "机构Id") + private Long deptId; + + @ApiModelProperty(value = "机构名称") + private String deptName; + + @ApiModelProperty(value = "天气") + private Now now; + + @ApiModelProperty(value = "最大温度") + private String maxTemp; + + @ApiModelProperty(value = "最低温度") + private String minTemp; + + + @ApiModelProperty(value = "年计划发电量") + private Double plan; + + @ApiModelProperty(value = "年实际发电量") + private Double generate; + + @ApiModelProperty(value = "年发电量完成率") + private Double generateComplete; +} diff --git a/hzims-service-api/hzims-operational-api/src/main/java/com/hnac/hzims/operational/main/vo/WindKpiAppVo.java b/hzims-service-api/hzims-operational-api/src/main/java/com/hnac/hzims/operational/main/vo/WindKpiAppVo.java new file mode 100644 index 0000000..bc36b91 --- /dev/null +++ b/hzims-service-api/hzims-operational-api/src/main/java/com/hnac/hzims/operational/main/vo/WindKpiAppVo.java @@ -0,0 +1,38 @@ +package com.hnac.hzims.operational.main.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.NullSerializer; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author ysj + */ +@Data +@ApiModel(value = "风电站点app指标数据") +public class WindKpiAppVo { + + @ApiModelProperty(value = "风电站数量") + private Integer count; + + @ApiModelProperty(value = "年计划发电量") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Double plan; + + @ApiModelProperty(value = "年实际发电量") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Double generate; + + @ApiModelProperty(value = "年发电量完成率") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Double generateComplete; + + @ApiModelProperty(value = "装机容量") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Double capacity; + + @ApiModelProperty(value = "峰值功率") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Double peak; +} diff --git a/hzims-service-api/hzims-operational-api/src/main/java/com/hnac/hzims/operational/main/vo/WindStationGenerateVo.java b/hzims-service-api/hzims-operational-api/src/main/java/com/hnac/hzims/operational/main/vo/WindStationGenerateVo.java new file mode 100644 index 0000000..7c68b05 --- /dev/null +++ b/hzims-service-api/hzims-operational-api/src/main/java/com/hnac/hzims/operational/main/vo/WindStationGenerateVo.java @@ -0,0 +1,36 @@ +package com.hnac.hzims.operational.main.vo; + +import com.hnac.hzims.hzimsweather.response.weather.Now; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.models.auth.In; +import lombok.Data; + +/** + * @author ysj + */ +@Data +@ApiModel(value = "风电站点区域数据") +public class WindStationGenerateVo { + + @ApiModelProperty(value = "机构Id") + private Long deptId; + + @ApiModelProperty(value = "机构名称") + private String deptName; + + @ApiModelProperty(value = "年计划发电量") + private Double plan; + + @ApiModelProperty(value = "年实际发电量") + private Double generate; + + @ApiModelProperty(value = "年发电量完成率") + private Double generateComplete; + + @ApiModelProperty(value = "设备数量") + private Long deviceCount; + + @ApiModelProperty(value = "峰值功率") + private Double peak; +} diff --git a/hzims-service-api/hzims-operational-api/src/main/java/com/hnac/hzims/operational/main/vo/WindSubordinateAppVo.java b/hzims-service-api/hzims-operational-api/src/main/java/com/hnac/hzims/operational/main/vo/WindSubordinateAppVo.java new file mode 100644 index 0000000..56901b5 --- /dev/null +++ b/hzims-service-api/hzims-operational-api/src/main/java/com/hnac/hzims/operational/main/vo/WindSubordinateAppVo.java @@ -0,0 +1,70 @@ +package com.hnac.hzims.operational.main.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.NullSerializer; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author ysj + */ +@Data +@ApiModel(value = "风电站点app指标数据") +public class WindSubordinateAppVo { + + @ApiModelProperty(value = "机构Id") + private Long deptId; + + @ApiModelProperty(value = "开始时间") + private String start; + + @ApiModelProperty(value = "结束时间") + private String end; + + @ApiModelProperty(value = "日常维护总数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer maintain; + + @ApiModelProperty(value = "日常维护完成数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer maintainFinish; + + @ApiModelProperty(value = "缺陷总数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer defect; + + @ApiModelProperty(value = "缺陷完成数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer defectFinish; + + @ApiModelProperty(value = "检修总数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer overhaul; + + @ApiModelProperty(value = "检修完成数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer overhaulFinish; + + @ApiModelProperty(value = "操作票总数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer operate; + + @ApiModelProperty(value = "操作票完成数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer operateFinish; + + @ApiModelProperty(value = "工作票总数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer work; + + @ApiModelProperty(value = "工作票完成数") + @JsonSerialize(nullsUsing = NullSerializer.class) + private Integer workFinish; + + @ApiModelProperty(value = "站点统计数据") + private List stations; + +} diff --git a/hzims-service/operational/src/main/java/com/hnac/hzims/operational/main/controller/WindHomeController.java b/hzims-service/operational/src/main/java/com/hnac/hzims/operational/main/controller/WindHomeController.java index afaee0e..6d2781a 100644 --- a/hzims-service/operational/src/main/java/com/hnac/hzims/operational/main/controller/WindHomeController.java +++ b/hzims-service/operational/src/main/java/com/hnac/hzims/operational/main/controller/WindHomeController.java @@ -67,4 +67,36 @@ public class WindHomeController extends BladeController { return R.data(service.target_curve(deptId)); } + @ApiLog + @ApiOperation("风电站点App指标数据") + @GetMapping("/app_kpi") + @ApiOperationSupport(order = 3) + public R app_kpi() { + return R.data(service.app_kpi()); + } + + @ApiLog + @ApiOperation("风电站区域数据") + @GetMapping("/app_area") + @ApiOperationSupport(order = 3) + public R> app_area(@ApiParam(value = "站点机构ID") Long deptId) { + return R.data(service.app_area(deptId)); + } + + @ApiLog + @ApiOperation("风电站区域统计数据") + @GetMapping("/app_subordinate") + @ApiOperationSupport(order = 3) + public R app_subordinate(@ApiParam(value = "站点机构ID") Long deptId) { + return R.data(service.app_subordinate(deptId)); + } + + @ApiLog + @ApiOperation("风电站区域指标/值班数据") + @GetMapping("/app_area_duty") + @ApiOperationSupport(order = 3) + public R app_area_duty(@ApiParam(value = "站点机构ID") Long deptId) { + return R.data(service.app_area_duty(deptId)); + } + } \ No newline at end of file diff --git a/hzims-service/operational/src/main/java/com/hnac/hzims/operational/main/service/WindHomeService.java b/hzims-service/operational/src/main/java/com/hnac/hzims/operational/main/service/WindHomeService.java index cc73703..8b56f4d 100644 --- a/hzims-service/operational/src/main/java/com/hnac/hzims/operational/main/service/WindHomeService.java +++ b/hzims-service/operational/src/main/java/com/hnac/hzims/operational/main/service/WindHomeService.java @@ -19,4 +19,12 @@ public interface WindHomeService { List target_curve(Long deptId); List subordinate(Long deptId); + + WindKpiAppVo app_kpi(); + + List app_area(Long deptId); + + WindSubordinateAppVo app_subordinate(Long deptId); + + WindAreaDutyVo app_area_duty(Long deptId); } diff --git a/hzims-service/operational/src/main/java/com/hnac/hzims/operational/main/service/impl/WindHomeServiceImpl.java b/hzims-service/operational/src/main/java/com/hnac/hzims/operational/main/service/impl/WindHomeServiceImpl.java index ee49639..f27bbbb 100644 --- a/hzims-service/operational/src/main/java/com/hnac/hzims/operational/main/service/impl/WindHomeServiceImpl.java +++ b/hzims-service/operational/src/main/java/com/hnac/hzims/operational/main/service/impl/WindHomeServiceImpl.java @@ -4,19 +4,37 @@ import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.TypeReference; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.hnac.hzims.equipment.vo.EminfoAndEmParamVo; import com.hnac.hzims.hzimsweather.response.weather.Daily; import com.hnac.hzims.hzimsweather.response.weather.HeWeatherWeatherDailyResponse; import com.hnac.hzims.hzimsweather.response.weather.HeWeatherWeatherNowResponse; +import com.hnac.hzims.operational.access.constants.AccessConstants; +import com.hnac.hzims.operational.access.entity.OperAccessTaskEntity; +import com.hnac.hzims.operational.access.service.IOperAccessTaskService; +import com.hnac.hzims.operational.defect.constants.TreatMethodConstant; +import com.hnac.hzims.operational.defect.entity.OperPhenomenonEntity; +import com.hnac.hzims.operational.defect.service.IOperPhenomenonService; +import com.hnac.hzims.operational.duty.service.IImsDutyMainService; +import com.hnac.hzims.operational.duty.vo.DutyMainInfoVo; import com.hnac.hzims.operational.fill.entity.WindEntity; import com.hnac.hzims.operational.fill.service.WindService; import com.hnac.hzims.operational.main.constant.HomePageConstant; import com.hnac.hzims.operational.main.service.AreaService; +import com.hnac.hzims.operational.main.service.IMainTaskStatisticService; import com.hnac.hzims.operational.main.service.IWeatherService; import com.hnac.hzims.operational.main.service.WindHomeService; import com.hnac.hzims.operational.main.vo.*; +import com.hnac.hzims.operational.maintenance.constants.MaintenanceConstant; +import com.hnac.hzims.operational.maintenance.entity.OperMaintenanceTaskEntity; +import com.hnac.hzims.operational.maintenance.service.IOperMaintenanceTaskService; import com.hnac.hzims.operational.station.entity.StationEntity; import com.hnac.hzims.operational.station.service.IStationService; +import com.hnac.hzims.ticket.workTicket.feign.ITicketInfoClient; +import com.hnac.hzims.ticket.workTicket.vo.TicketMonthVO; +import com.hnac.hzinfo.inspect.task.feign.IInspectTaskReportClient; +import com.hnac.hzinfo.inspect.task.vo.DutyInspectTaskVO; +import io.swagger.annotations.ApiModelProperty; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.MapUtils; @@ -28,15 +46,20 @@ import org.springblade.core.tool.utils.StringUtil; import org.springblade.system.entity.Dept; import org.springblade.system.entity.Region; import org.springblade.system.feign.ISysClient; +import org.springblade.system.user.cache.UserCache; +import org.springblade.system.user.entity.User; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import java.math.BigDecimal; +import java.math.RoundingMode; import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.concurrent.*; import java.util.stream.Collectors; /** @@ -55,10 +78,28 @@ public class WindHomeServiceImpl implements WindHomeService { private final IStationService stationService; + private final IImsDutyMainService dutyMainService; + + private final IOperPhenomenonService phenomenonService; + + private final IOperAccessTaskService operAccessTaskService; + + private final IOperMaintenanceTaskService maintenanceTaskService; + + private final IMainTaskStatisticService mainTaskStatisticService; + private final RedisTemplate redisTemplate; private final ISysClient sysClient; + private final ITicketInfoClient ticketInfoClient; + + + private final IInspectTaskReportClient inspectTaskReportClient; + + // 线程数量 + private final static int POOL_QUANTITY = 4; + public final static String device_cache_final = "hzims:equipment:emInfo:deviceCode.emInfoList"; /** @@ -211,6 +252,11 @@ public class WindHomeServiceImpl implements WindHomeService { if(CollectionUtil.isNotEmpty(winds)){ List piece = winds.stream().filter(o->entry.getValue().stream().map(StationEntity::getCode).collect(Collectors.toList()).contains(o.getStationCode())).collect(Collectors.toList()); if(CollectionUtil.isEmpty(piece)){ + subordinate.setGeneration(0.0); + subordinate.setGenerationRate(0.0); + subordinate.setGenerationComplete(0.0); + subordinate.setFanUse(0.0); + subordinate.setFactoryUse(0.0); return subordinate; } // 发电量 @@ -242,6 +288,525 @@ public class WindHomeServiceImpl implements WindHomeService { } /** + * 风电站点APP指标数据 + * @return + */ + @Override + public WindKpiAppVo app_kpi() { + // 查询站点 + List stations = stationService.list(new LambdaQueryWrapper() {{ + eq(StationEntity::getServeType, HomePageConstant.HYDROPOWER_SERVETYPE); + eq(StationEntity::getType,HomePageConstant.WIND_POWER); + }}); + if(CollectionUtil.isEmpty(stations)){ + return new WindKpiAppVo(); + } + // 设备查询 + List devices = JSONObject.parseObject(redisTemplate.opsForValue().get(device_cache_final).toString(), new TypeReference>() {}); + WindKpiAppVo kpi = new WindKpiAppVo(); + // 站点数量 + kpi.setCount(stations.size()); + // 风电数据 + List winds = windService.list(new LambdaQueryWrapper() {{ + in(WindEntity::getStationCode,stations.stream().map(StationEntity::getCode).collect(Collectors.toList())) + .like(WindEntity::getFillDate,DateUtil.format(new Date(),"yyyy")); + }}); + if(CollectionUtil.isEmpty(winds)){ + return kpi; + } + // 装机容量 + kpi.setCapacity(devices.stream().filter(o->stations.stream().map(StationEntity::getRefDept).collect(Collectors.toList()).contains(o.getCreateDept())).mapToDouble(EminfoAndEmParamVo::getInstalledCapacity).sum()); + + // 计划发电量 + kpi.setPlan(winds.stream().mapToDouble(WindEntity::getPlan).sum()); + // 实际发电量 + kpi.setGenerate(winds.stream().mapToDouble(WindEntity::getPower).sum()); + // 发电量完成率 + if(Math.abs(kpi.getPlan()) > 0 && Math.abs(kpi.getGenerate()) > 0){ + kpi.setGenerateComplete(BigDecimal.valueOf(kpi.getGenerate() / kpi.getPlan() * 100).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()); + } + // 峰值功率 + kpi.setPeak(winds.stream().filter(o->o.getFillDate().contains(DateUtil.format(new Date(),DateUtil.PATTERN_DATE))).mapToDouble(WindEntity::getPeakPower).sum()); + return kpi; + } + + /** + * 风电app区域数据 + * @param deptId + * @return + */ + @Override + public List app_area(Long deptId) { + // 区域数据查询 + Map> areas = areaService.areaOrStaion(deptId, Collections.singletonList(HomePageConstant.WIND_POWER)); + if (MapUtils.isEmpty(areas)) { + return new ArrayList<>(); + } + List codes = new ArrayList<>(); + areas.forEach((key,value)-> codes.addAll(value.stream().map(StationEntity::getCode).collect(Collectors.toList()))); + // 获取站点实时天气 + Map nowWeather = this.weatherService.getNowWeather(codes); + // 获取站点7日天气 + Map weekWeather = this.weatherService.getWeekWeather(codes); + // 风电填报数据 + List winds = windService.list(new LambdaQueryWrapper() {{ + in(WindEntity::getStationCode,codes) + .like(WindEntity::getFillDate,DateUtil.format(new Date(),"yyyy")); + }}); + return areas.entrySet().stream().map(entry -> { + WindAreaVo area = new WindAreaVo(); + area.setDeptId(entry.getKey().getId()); + area.setDeptName(entry.getKey().getDeptName()); + List stationCodes = entry.getValue().stream().map(StationEntity::getCode).collect(Collectors.toList()); + area.setPlan(winds.stream().filter(o-> stationCodes.contains(o.getStationCode())).mapToDouble(WindEntity::getPlan).sum()); + area.setGenerate(winds.stream().filter(o-> stationCodes.contains(o.getStationCode())).mapToDouble(WindEntity::getPower).sum()); + if(Math.abs(area.getPlan()) > 0 && Math.abs(area.getGenerate()) > 0){ + area.setGenerateComplete(BigDecimal.valueOf(area.getGenerate() / area.getPlan() * 100).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()); + } + if(MapUtils.isNotEmpty(nowWeather) && nowWeather.containsKey(entry.getValue().get(0).getCode())){ + HeWeatherWeatherNowResponse nowData = nowWeather.get(entry.getValue().get(0).getCode()); + if(ObjectUtil.isNotEmpty(nowData.getNow())){ + area.setNow(nowData.getNow()); + } + } + // 天气区间 + area.setMaxTemp(this.intervalTemp(weekWeather,entry.getValue().get(0).getCode(),true)); + area.setMinTemp(this.intervalTemp(weekWeather,entry.getValue().get(0).getCode(),false)); + return area; + }).collect(Collectors.toList()); + } + + /** + * 区域数据统计 + * @param deptId + * @return + */ + @Override + public WindSubordinateAppVo app_subordinate(Long deptId) { + WindSubordinateAppVo subordinate = new WindSubordinateAppVo(); + subordinate.setDeptId(deptId); + // 当月任务执行数据 + this.complteTask(subordinate); + // 站点数据 + this.stations(subordinate); + return subordinate; + } + + /** + * 风电app区域值班数据 + * @param deptId + * @return + */ + @Override + public WindAreaDutyVo app_area_duty(Long deptId) { + WindAreaDutyVo areaDuty = new WindAreaDutyVo(); + areaDuty.setDeptId(deptId); + // 风电统计数据 + this.windFill(areaDuty,deptId); + + // 获取当班、下一班组列表数据 + List dutys = this.dutyMainService.getDutyDataV2(deptId); + if(CollectionUtil.isEmpty(dutys)){ + return areaDuty; + } + this.settingBase(dutys.get(0),areaDuty); + this.nextDuty(dutys.get(0).getId(),areaDuty); + // 开始时间、结束时间 + LocalDateTime localDateTime = LocalDateTime.ofInstant(dutys.get(0).getDutyDate().toInstant(), ZoneId.systemDefault()); + LocalDateTime startDate = localDateTime.withHour(dutys.get(0).getStartTime().getHours()).withMinute(dutys.get(0).getStartTime().getMinutes()).withSecond(0); + String start = DateUtil.format(startDate,DateUtil.PATTERN_DATETIME); + String end = DateUtil.format(LocalDateTime.now(),DateUtil.PATTERN_DATETIME); + List deptList = Collections.singletonList(dutys.get(0).getCreateDept()); + areaDuty.setStart(start); + areaDuty.setEnd(end); + + // 使用多线程处理数据 + ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("duty_data-pool-%d").build(); + ExecutorService pool = new ThreadPoolExecutor(4, 4, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()); + CountDownLatch countDownLatch = new CountDownLatch(4); + // 缺陷 + pool.execute(()-> { + this.dutyDefect(areaDuty,startDate); + countDownLatch.countDown(); + }); + // 巡检 + pool.execute(()-> { + this.inspectionTask(areaDuty,start,end,deptList); + countDownLatch.countDown(); + }); + // 维护 + pool.execute(()-> { + this.maintenanceTask(areaDuty,start,end,deptList); + countDownLatch.countDown(); + }); + // 检修 + pool.execute(()-> { + this.overhaulTask(areaDuty,start,end,deptList); + countDownLatch.countDown(); + }); + // 等待所有线程执行完成 + try { + countDownLatch.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + Thread.currentThread().interrupt(); + } + // 任务完成率 + int taskSum = areaDuty.getDefectSum() + areaDuty.getInspectionTaskCount() + areaDuty.getMaintenanceTaskCount() + areaDuty.getOverhaulTaskCount(); + int finishSum = areaDuty.getSolvedCount() + areaDuty.getInspectionTaskFinishCount() + areaDuty.getMaintenanceTaskFinishCount() + areaDuty.getOverhaulTaskFinishCount(); + if(Math.abs(taskSum) <= 0){ + areaDuty.setTaskRate(0.0); + }else{ + double taskRate = BigDecimal.valueOf((double)finishSum / (double)taskSum * 100).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); + areaDuty.setTaskRate(taskRate); + } + return areaDuty; + } + + private void windFill(WindAreaDutyVo areaDuty,Long deptId) { + // 查询站点 + List stations = stationService.getHomeStationList(deptId,Collections.singletonList(HomePageConstant.WIND_POWER),HomePageConstant.HYDROPOWER_SERVETYPE); + if(CollectionUtil.isEmpty(stations)){ + return; + } + // 查询站点填报数据 + List winds = windService.list(new LambdaQueryWrapper() {{ + in(WindEntity::getStationCode,stations.stream().map(StationEntity::getCode).collect(Collectors.toList())) + .like(WindEntity::getFillDate,DateUtil.format(new Date(),DateUtil.PATTERN_DATE)); + }}); + if(CollectionUtil.isEmpty(winds)){ + return; + } + areaDuty.setPlan(winds.stream().mapToDouble(WindEntity::getPlan).sum()); + areaDuty.setGenerate(winds.stream().mapToDouble(WindEntity::getPower).sum()); + // 发电量完成率 + if(Math.abs(areaDuty.getPlan()) > 0 && Math.abs(areaDuty.getGenerate()) > 0){ + areaDuty.setGenerateComplete(BigDecimal.valueOf(areaDuty.getGenerate() / areaDuty.getPlan() * 100).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()); + } + areaDuty.setSpeed(winds.stream().mapToDouble(WindEntity::getPower).average().orElse(0.0)); + areaDuty.setSurfPower(winds.stream().mapToDouble(WindEntity::getSurfPower).sum()); + areaDuty.setBelowPower(winds.stream().mapToDouble(WindEntity::getBelowPower).sum()); + areaDuty.setAvailable(winds.stream().mapToDouble(WindEntity::getAvailable).average().orElse(0.0)); + areaDuty.setComprehensivePower(winds.stream().mapToDouble(WindEntity::getComprehensivePower).sum()); + areaDuty.setPeakPower(winds.stream().mapToDouble(WindEntity::getPeakPower).average().orElse(0.0)); + areaDuty.setFaultHours(winds.stream().mapToDouble(WindEntity::getPeakPower).average().orElse(0.0)); + areaDuty.setAccuracy(winds.stream().mapToDouble(WindEntity::getAccuracy).average().orElse(0.0)); + areaDuty.setUltraShortAccuracy(winds.stream().mapToDouble(WindEntity::getUltraShortAccuracy).average().orElse(0.0)); + } + + /** + * 获取当班缺陷数据 + * + * @param item + * @param startTime + */ + private void dutyDefect(WindAreaDutyVo item, LocalDateTime startTime) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.ge(OperPhenomenonEntity::getCreateTime,startTime); + wrapper.le(OperPhenomenonEntity::getCreateTime,LocalDateTime.now()); + wrapper.eq(OperPhenomenonEntity::getIsDefect, TreatMethodConstant.IS_DEFECT); + wrapper.eq(OperPhenomenonEntity::getDiscriminateStatus,TreatMethodConstant.AUTO_SCREENED); + // 查询现象 + List list = phenomenonService.list(wrapper); + if(CollectionUtil.isEmpty(list)){ + item.setUnsolvedCount(0); + item.setSolvedCount(0); + item.setDefectSum(0); + item.setSeriousCount(0); + item.setDefectRate(0.0); + return; + } + // 缺陷总数 + int defectSum = list.size(); + item.setDefectSum(defectSum); + // 缺陷已解决数量 + int solvedCount = (int) list.stream().filter(o->TreatMethodConstant.CONCLUSION_COMPLETED.equals(o.getConclusionStatus())).count(); + item.setSolvedCount(solvedCount); + // 缺陷未解决数量 + int unsolvedCount = list.size() - solvedCount; + item.setUnsolvedCount(unsolvedCount); + // 缺陷严重数量 + int seriousCount = (int) list.stream().filter(o-> TreatMethodConstant.CLASS_I_DEFECT.toString().equals(o.getDefectLevel())).count(); + item.setSeriousCount(seriousCount); + // 消缺率 + double defectRate = BigDecimal.valueOf((double) solvedCount / (double)list.size() * 100).setScale(2, RoundingMode.HALF_UP).doubleValue(); + item.setDefectRate(defectRate); + } + + /** + * 获取巡检任务数量 + * @param item + * @param startDate + * @param endDate + */ + private void inspectionTask(WindAreaDutyVo item, String startDate, String endDate, List deptList) { + item.setInspectionTaskCount(0); + item.setInspectionTaskFinishCount(0); + item.setNotInspectionTaskCount(0); + // 查询当班巡检任务 + Map params = new HashMap<>(); + params.put("startDate",startDate); + params.put("endDate",endDate); + params.put("deptList",deptList); + R response = inspectTaskReportClient.getDutyInspectTask(params); + if(!response.isSuccess() || ObjectUtil.isEmpty(response.getData())){ + return; + } + // 赋值 + item.setInspectionTaskCount(response.getData().getInspectTaskSum()); + item.setInspectionTaskFinishCount(response.getData().getInspectTaskFinish()); + item.setNotInspectionTaskCount(response.getData().getNotExecuteTaskCount()); + } + + /** + * 获取当班日常维护数据 + * @param item + * @param start + * @param end + * @param deptList + */ + private void maintenanceTask(WindAreaDutyVo item, String start, String end, List deptList) { + item.setMaintenanceTaskCount(0); + item.setMaintenanceTaskFinishCount(0); + item.setNotMaintenanceTaskCount(0); + // 查询当班日常维护任务 + List list = maintenanceTaskService.getMaintenanceTask(start, end, deptList); + if(CollectionUtil.isEmpty(list)){ + return; + } + // 总数 + item.setMaintenanceTaskCount(list.size()); + // 完成数 + int maintenanceTaskFinishCount = (int) list.stream().filter(o-> MaintenanceConstant.TASK_STATUS_5 == o.getStatus()).count(); + item.setMaintenanceTaskFinishCount(maintenanceTaskFinishCount); + // 未完成数 + int notMaintenanceTaskCount = list.size() - maintenanceTaskFinishCount; + item.setNotMaintenanceTaskCount(notMaintenanceTaskCount); + } + + /** + * 获取检修任务数量 + * @param item + * @param start + * @param end + * @param deptList + */ + private void overhaulTask(WindAreaDutyVo item, String start, String end, List deptList) { + item.setOverhaulTaskCount(0); + item.setNotOverhaulTaskCount(0); + item.setOverhaulTaskFinishCount(0); + // 查询当班检修任务 + List list = operAccessTaskService.getAccessTask(start, end, deptList); + if(CollectionUtil.isEmpty(list)){ + return; + } + // 总数 + item.setOverhaulTaskCount(list.size()); + // 完成数 + int overhaulTaskFinishCount = (int) list.stream().filter(o-> AccessConstants.ACCESS_TASK_STATUS_4 == o.getStatus()).count(); + item.setOverhaulTaskFinishCount(overhaulTaskFinishCount); + // 未开始数 + int notOverhaulTaskCount = (int) list.stream().filter(o-> AccessConstants.ACCESS_TASK_STATUS_0 == o.getStatus()).count(); + item.setNotOverhaulTaskCount(notOverhaulTaskCount); + } + + /** + * 班组基础数据设置 + * @param duty + * @param item + */ + private void settingBase(DutyMainInfoVo duty, WindAreaDutyVo item) { + if(ObjectUtil.isEmpty(duty)){ + return; + } + item.setShift(duty.getClassName()); + item.setTeam(Optional.ofNullable(duty.getGroupName()).orElse("灵活排班")); + // 班组负责人 + String managerName = this.getManagerName(duty.getManagerId()); + item.setTeamLeader(managerName); + // 班组成员 + String classMember = this.getClassMemberName(duty.getDutyPersonIds(),duty.getManagerId()); + item.setClassMember(classMember); + } + + /** + * 获取下一班组数据 + * @param id + * @param item + */ + private void nextDuty(Long id,WindAreaDutyVo item) { + DutyMainInfoVo nextDuty = this.dutyMainService.getNextDutyDataV2(id); + if(ObjectUtil.isEmpty(nextDuty) || ObjectUtil.isEmpty(nextDuty.getId())){ + return; + } + item.setNextShift(nextDuty.getClassName()); + item.setNextTeam(Optional.ofNullable(nextDuty.getGroupName()).orElse("灵活排班")); + // 下一班组负责人 + String managerName = this.getManagerName(nextDuty.getManagerId()); + item.setNextTeamLeader(managerName); + // 下一班组成员 + String classMember = this.getClassMemberName(nextDuty.getDutyPersonIds(),nextDuty.getManagerId()); + item.setNextClassMember(classMember); + } + + /** + * 获取班组负责人 + * @param managerId + * @return + */ + private String getManagerName(String managerId) { + if(StringUtil.isBlank(managerId)){ + return ""; + } + User user = UserCache.getUser(Long.valueOf(managerId)); + if (ObjectUtil.isEmpty(user)) { + return ""; + } + return user.getName(); + } + + /** + * 获取班组成员 + * @param personIds + * @param managerId + * @return + */ + private String getClassMemberName(String personIds,String managerId) { + if(StringUtil.isBlank(personIds)){ + return ""; + } + StringBuilder builder = new StringBuilder(); + // 遍历成员 + for (String item : personIds.split("\\^")) { + if (item.equals(managerId)) { + continue; + } + User user = UserCache.getUser(Long.valueOf(item)); + if (ObjectUtil.isEmpty(user)) { + continue; + } + builder.append(user.getName()).append(","); + } + if(builder.length() <= 0){ + return ""; + } + return builder.substring(0,builder.toString().length() - 1); + } + + /** + * 当月任务执行情况 + * @param area + */ + private void complteTask(WindSubordinateAppVo area) { + String start = DateUtil.format(new Date(),"yyyy-MM") + "-01 00:00:00"; + area.setStart(start); + String end = DateUtil.format(new Date(),DateUtil.PATTERN_DATETIME); + area.setEnd(end); + // 线程 + ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("app-area-taget-pool-%d").build(); + ScheduledExecutorService exe = new ScheduledThreadPoolExecutor(POOL_QUANTITY, namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()); + CountDownLatch countDownLatch = new CountDownLatch(POOL_QUANTITY); + // 日常维护 + exe.execute(()->{ + MaintainVo maintainVo = mainTaskStatisticService.getMaintain(start,end,Collections.singletonList(area.getDeptId())); + area.setMaintain(maintainVo.getMaintain()); + area.setMaintainFinish(maintainVo.getMaintainFinish()); + countDownLatch.countDown(); + }); + + // 消缺 + exe.execute(()->{ + ShortagesVo shortagesVo = mainTaskStatisticService.getShortage(start,end,Collections.singletonList(area.getDeptId())); + area.setDefect(shortagesVo.getShortagesSum()); + area.setDefectFinish(shortagesVo.getShortages()); + countDownLatch.countDown(); + }); + // 检修 + exe.execute(()->{ + OverhaulVo overhaulVo = mainTaskStatisticService.getOverhaul(start,end,Collections.singletonList(area.getDeptId())); + area.setOverhaul(overhaulVo.getOverhaul()); + area.setOverhaulFinish(overhaulVo.getOverhaulFinish()); + countDownLatch.countDown(); + }); + // 操作票&工作票 + exe.execute(()->{ + Map map = new HashMap<>(); + map.put("startDate",start); + map.put("endDate",end); + map.put("deptList",Collections.singletonList(area.getDeptId())); + R result = ticketInfoClient.getOperateWorkStatistic(map); + if (result.isSuccess() && ObjectUtil.isNotEmpty(result.getData())) { + // 操作票 + TicketMonthVO tiket = result.getData(); + area.setOperate(tiket.getOperate()); + area.setOperateFinish(tiket.getOperateQualify()); + // 工作票 + area.setWork(tiket.getWork()); + area.setWorkFinish(tiket.getWorkQualify()); + } + countDownLatch.countDown(); + }); + // 等待所有线程执行完成 + try { + countDownLatch.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + Thread.currentThread().interrupt(); + } + exe.shutdown(); + } + + /** + * 区域站点数据统计 + * @param subordinate + */ + private void stations(WindSubordinateAppVo subordinate) { + List stations = stationService.getHomeStationList(subordinate.getDeptId(),Collections.singletonList(HomePageConstant.WIND_POWER),HomePageConstant.HYDROPOWER_SERVETYPE); + if(CollectionUtil.isEmpty(stations)){ + return; + } + // 查询风电填报数据 + List winds = windService.list(new LambdaQueryWrapper() {{ + in(WindEntity::getStationCode,stations.stream().map(StationEntity::getCode).collect(Collectors.toList())) + .like(WindEntity::getFillDate,DateUtil.format(new Date(),"yyyy")); + }}); + // 设备 + List devices = JSONObject.parseObject(redisTemplate.opsForValue().get(device_cache_final).toString(), new TypeReference>() {}); + subordinate.setStations(stations.stream().map(station -> { + WindStationGenerateVo generate = new WindStationGenerateVo(); + generate.setDeptId(station.getRefDept()); + generate.setDeptName(station.getName()); + generate.setPlan(winds.stream().filter(o-> o.getStationCode().equals(station.getCode())).mapToDouble(WindEntity::getPlan).sum()); + generate.setGenerate(winds.stream().filter(o-> o.getStationCode().equals(station.getCode())).mapToDouble(WindEntity::getPower).sum()); + // 发电量完成率 + if(Math.abs(generate.getPlan()) > 0 && Math.abs(generate.getGenerate()) > 0){ + generate.setGenerateComplete(BigDecimal.valueOf(generate.getGenerate() / generate.getPlan() * 100).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()); + } + // 设备数量 + generate.setDeviceCount(devices.stream().filter(o->o.getCreateDept().equals(station.getRefDept())).count()); + // 峰值功率 + generate.setPeak(winds.stream().filter(o->o.getStationCode().equals(station.getCode()) && o.getFillDate().contains(DateUtil.format(new Date(),DateUtil.PATTERN_DATE))).mapToDouble(WindEntity::getPeakPower).sum()); + return generate; + }).collect(Collectors.toList())); + } + + /** + * 天气区间 + * @param week + * @param flag + * @return + */ + private String intervalTemp(Map week, String code,boolean flag) { + if(MapUtils.isEmpty(week) || !week.containsKey(code)){ + return "21"; + } + if(flag){ + return week.get(code).getDaily().get(0).getTempMax(); + } + return week.get(code).getDaily().get(0).getTempMin(); + } + + /** * 区域天气 * @param scale * @param nowWeather