From b49bab1cccd71480e73c2246b488963e30693658 Mon Sep 17 00:00:00 2001 From: yufengshuo Date: Thu, 26 Mar 2026 16:15:43 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E5=A4=9A=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E5=B9=B6=E8=A1=8C=E5=A4=84=E7=90=86=E5=B9=B6=E5=A2=9E?= =?UTF-8?q?=E5=BC=BA=E5=81=9C=E7=94=B5=E7=94=A8=E6=88=B7=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在DnerDailyPowerOutageEventSync实体和同步记录中新增eventId字段,支持多事件并行处理 - 为DataExcelEntity和DnerHourlyPowerOutageEvent添加故障停电和计划停电用户数统计字段 - 修改所有相关查询、同步和数据处理方法,增加eventId参数以支持按事件隔离数据 - 优化日K线数据生成逻辑,分别统计故障停电和计划停电的用户数(总数、最大、最小、起始、结束值) - 修复文件上传时同步记录清理不完整的问题,确保删除旧的K线图同步记录 --- .../power/grid/controller/DnerController.java | 6 +- .../dao/DnerHourlyPowerOutageEventMapper.java | 2 +- .../power/grid/entity/DataExcelEntity.java | 14 +++- .../entity/DnerDailyPowerOutageEventSync.java | 5 ++ ...IDnerDailyPowerOutageEventSyncService.java | 6 +- ...DnerDailyPowerOutageEventBatchService.java | 75 ++++++++++++------- ...rDailyPowerOutageEventSyncServiceImpl.java | 22 +++--- .../grid/service/impl/FileServiceImpl.java | 12 ++- .../impl/HourlyOutageExcelProcessService.java | 6 ++ .../DnerHourlyPowerOutageEventMapper.xml | 13 +++- 10 files changed, 111 insertions(+), 50 deletions(-) diff --git a/src/main/java/com/southern/power/grid/controller/DnerController.java b/src/main/java/com/southern/power/grid/controller/DnerController.java index 9a41f7e..161d892 100644 --- a/src/main/java/com/southern/power/grid/controller/DnerController.java +++ b/src/main/java/com/southern/power/grid/controller/DnerController.java @@ -92,7 +92,7 @@ public class DnerController { */ @PostMapping("/excel/import") public Result importExcel(@RequestParam("file") MultipartFile file, - @RequestParam Long eventId) { + @RequestParam("eventId") Long eventId) { return Result.success(importTaskService.importExcel(file, eventId)); } @@ -136,7 +136,7 @@ public class DnerController { * @return 结果 <布尔> */ @GetMapping("/sync/dailyPowerOutageEvent") - public Result syncDailyPowerOutageEvent(@RequestParam String startDate, @RequestParam String endDate, @RequestParam String setDate) { - return Result.success(dnerDailyPowerOutageEventSyncService.processingData(startDate, endDate, setDate)); + public Result syncDailyPowerOutageEvent(@RequestParam String startDate, @RequestParam String endDate, @RequestParam String setDate,@RequestParam Long eventId) { + return Result.success(dnerDailyPowerOutageEventSyncService.processingData(startDate, endDate, setDate,eventId)); } } diff --git a/src/main/java/com/southern/power/grid/dao/DnerHourlyPowerOutageEventMapper.java b/src/main/java/com/southern/power/grid/dao/DnerHourlyPowerOutageEventMapper.java index 611730d..0da215e 100644 --- a/src/main/java/com/southern/power/grid/dao/DnerHourlyPowerOutageEventMapper.java +++ b/src/main/java/com/southern/power/grid/dao/DnerHourlyPowerOutageEventMapper.java @@ -36,7 +36,7 @@ public interface DnerHourlyPowerOutageEventMapper extends BaseMapper selectByOrgCodesAndDataTime(@Param("orgCodes") List orgCodes, @Param("startDate") String startDate, - @Param("endDate") String endDate); + @Param("endDate") String endDate, @Param("eventId") Long eventId); /** * 查询 outageState=2 且按 orgCode+日期分组后最小 dataTime 早于指定时间的分组列表 diff --git a/src/main/java/com/southern/power/grid/entity/DataExcelEntity.java b/src/main/java/com/southern/power/grid/entity/DataExcelEntity.java index ad69a97..d3f1999 100644 --- a/src/main/java/com/southern/power/grid/entity/DataExcelEntity.java +++ b/src/main/java/com/southern/power/grid/entity/DataExcelEntity.java @@ -37,7 +37,7 @@ public class DataExcelEntity { private LocalDateTime endTime; @ExcelProperty(value = "停电时长(mins)") - private Float lengthOutage ; + private Float lengthOutage; @ExcelProperty(value = "停电影响用户数") private Integer userCount; @@ -45,4 +45,16 @@ public class DataExcelEntity { @DateTimeFormat("yyyy-MM-dd HH:mm:ss") @ExcelProperty(value = "数据创建时间") private LocalDateTime createTime; + + /** + * 故障停电影响用户总数(导入的excel不存在,用于后续数据处理) + */ + @ExcelProperty(value = "故障停电影响用户总数") + private Integer faultUserCount; + + /** + * 计划停电影响用户数(导入的excel不存在,用于后续数据处理) + */ + @ExcelProperty(value = "计划停电影响用户数") + private Integer scheduledUserCount; } diff --git a/src/main/java/com/southern/power/grid/entity/DnerDailyPowerOutageEventSync.java b/src/main/java/com/southern/power/grid/entity/DnerDailyPowerOutageEventSync.java index 82778d7..64c743d 100644 --- a/src/main/java/com/southern/power/grid/entity/DnerDailyPowerOutageEventSync.java +++ b/src/main/java/com/southern/power/grid/entity/DnerDailyPowerOutageEventSync.java @@ -22,6 +22,11 @@ public class DnerDailyPowerOutageEventSync { */ private String dateTime; + /** + * 事件ID + */ + private Long eventId; + /** * 同步状态 1 非当日调用 2 当日调用 */ diff --git a/src/main/java/com/southern/power/grid/service/IDnerDailyPowerOutageEventSyncService.java b/src/main/java/com/southern/power/grid/service/IDnerDailyPowerOutageEventSyncService.java index 9a33d23..51f7928 100644 --- a/src/main/java/com/southern/power/grid/service/IDnerDailyPowerOutageEventSyncService.java +++ b/src/main/java/com/southern/power/grid/service/IDnerDailyPowerOutageEventSyncService.java @@ -5,9 +5,10 @@ public interface IDnerDailyPowerOutageEventSyncService { /** * 日K线停电事件同步 * + * @param eventId 事件id * @return 布尔型 */ - Boolean syncDnerDailyPowerOutageEvent(); + Boolean syncDnerDailyPowerOutageEvent(Long eventId); /** * 处理数据 @@ -15,7 +16,8 @@ public interface IDnerDailyPowerOutageEventSyncService { * @param startDate 开始日期 * @param endDate 结束日期 * @param setDate 设置哪个日期的同步记录状态为2 部分同步 为null则不设置 + * @param eventId 事件id * @return 布尔型 */ - Boolean processingData(String startDate, String endDate, String setDate); + Boolean processingData(String startDate, String endDate, String setDate, Long eventId); } diff --git a/src/main/java/com/southern/power/grid/service/impl/DnerDailyPowerOutageEventBatchService.java b/src/main/java/com/southern/power/grid/service/impl/DnerDailyPowerOutageEventBatchService.java index 07a0199..a36fcec 100644 --- a/src/main/java/com/southern/power/grid/service/impl/DnerDailyPowerOutageEventBatchService.java +++ b/src/main/java/com/southern/power/grid/service/impl/DnerDailyPowerOutageEventBatchService.java @@ -40,22 +40,25 @@ public class DnerDailyPowerOutageEventBatchService { * 删除指定日期的存量数据 * 删除dner_daily_power_outage_event(对应data_time字段)和dner_daily_power_outage_event_sync(对应date_time字段)中的对应数据 * - * @param date 日期 + * @param date 日期 + * @param eventId 事件id */ - public void deleteDateData(String date) { + public void deleteDateData(String date, Long eventId) { try { log.info("开始删除日期 {} 的存量数据", date); - + // 1. 删除dner_daily_power_outage_event表中对应日期的数据 int deleteDailyCount = dailyPowerOutageEventMapper.delete( new LambdaQueryWrapper() - .eq(DnerDailyPowerOutageEvent::getDataTime,date) + .eq(DnerDailyPowerOutageEvent::getEventId, eventId) + .eq(DnerDailyPowerOutageEvent::getDataTime, date) ); log.info("日期 {} 删除日表 {} 条存量数据", date, deleteDailyCount); // 2. 删除dner_daily_power_outage_event_sync表中对应日期的同步记录 int deleteSyncCount = syncMapper.delete( new LambdaQueryWrapper() + .eq(DnerDailyPowerOutageEventSync::getEventId, eventId) .eq(DnerDailyPowerOutageEventSync::getDateTime, date) ); log.info("日期 {} 删除同步记录表 {} 条存量数据", date, deleteSyncCount); @@ -69,16 +72,17 @@ public class DnerDailyPowerOutageEventBatchService { /** * 同步指定日期的一批区域数据(带事务) * - * @param date 日期 - * @param orgCodeList 区域编码列表(批次) - * @param batchIndex 批次索引 + * @param date 日期 + * @param orgCodeList 区域编码列表(批次) + * @param batchIndex 批次索引 + * @param eventId 事件id */ - public void syncDateDataForBatch(String date, List orgCodeList, int batchIndex) { + public void syncDateDataForBatch(String date, List orgCodeList, int batchIndex, Long eventId) { log.info("开始同步日期 {} 批次 {},区域数量: {}", date, batchIndex, orgCodeList.size()); List allData = new ArrayList<>(); - List allHourlyEvents = queryHourlyDataByDateAndOrgCodes(orgCodeList, date); + List allHourlyEvents = queryHourlyDataByDateAndOrgCodes(orgCodeList, date, eventId); if (CollectionUtils.isEmpty(allHourlyEvents)) { log.info("日期 {} 批次 {} 无小时数据需要处理", date, batchIndex); return; @@ -100,14 +104,7 @@ public class DnerDailyPowerOutageEventBatchService { log.warn("转换日K线数据失败:日期:{}, 区域编号:{}", date, orgCode); continue; } - - // 3. 保存两条停电状态不同的数据(停电中=2,已复电=3) - DnerDailyPowerOutageEvent copyEvent = deepCopyByJackson(dailyPowerOutageEvent, DnerDailyPowerOutageEvent.class); - dailyPowerOutageEvent.setOutageState(2); - copyEvent.setOutageState(3); - allData.add(dailyPowerOutageEvent); - allData.add(copyEvent); } catch (Exception e) { log.error("处理区域 {} 日期 {} 时发生异常: {}", orgCode, date, e.getMessage(), e); @@ -122,14 +119,14 @@ public class DnerDailyPowerOutageEventBatchService { for (int i = 0; i < allData.size(); i += BATCH_SIZE) { int end = Math.min(i + BATCH_SIZE, allData.size()); List subList = allData.subList(i, end); - + for (DnerDailyPowerOutageEvent event : subList) { dailyPowerOutageEventMapper.insert(event); } totalInserted += subList.size(); log.debug("日期 {} 批次 {} 已插入 {}/{} 条记录", date, batchIndex, totalInserted, allData.size()); } - + log.info("日期 {} 批次 {} 保存完成,共 {} 条记录", date, batchIndex, totalInserted); } catch (Exception e) { log.error("日期 {} 批次 {} 保存数据时发生异常:{}", date, batchIndex, e.getMessage(), e); @@ -144,15 +141,16 @@ public class DnerDailyPowerOutageEventBatchService { * 保存每日同步记录 * 一个日期的所有数据同步完成后,保存一条同步记录 * - * @param date 同步日期 - * @param errors 错误信息列表 + * @param date 同步日期 + * @param errors 错误信息列表 * @param setDate 设置哪个日期的同步记录状态为2 部分同步 为null则不设置 + * @param eventId 事件id */ - public void saveDailySyncRecord(String date, List errors,String setDate) { + public void saveDailySyncRecord(String date, List errors, String setDate, Long eventId) { try { DnerDailyPowerOutageEventSync record = new DnerDailyPowerOutageEventSync(); record.setDateTime(date); - + record.setEventId(eventId); // 判断同步状态 int syncStatus = setDate != null && setDate.equals(date) ? 2 : 1; @@ -195,14 +193,14 @@ public class DnerDailyPowerOutageEventBatchService { } } - private List queryHourlyDataByDateAndOrgCodes(List orgCodes, String date) { + private List queryHourlyDataByDateAndOrgCodes(List orgCodes, String date, Long eventId) { if (CollectionUtils.isEmpty(orgCodes)) { return new ArrayList<>(); } try { String start = date + " 00:00:00"; String end = date + " 23:59:59"; - return hourlyPowerOutageEventMapper.selectByOrgCodesAndDataTime(orgCodes,start,end); + return hourlyPowerOutageEventMapper.selectByOrgCodesAndDataTime(orgCodes, start, end, eventId); } catch (Exception e) { log.error("批量查询小时数据失败 - 日期: {}, 区域数: {}, 错误: {}", date, orgCodes.size(), e.getMessage(), e); throw new RuntimeException("批量查询小时数据失败: " + e.getMessage(), e); @@ -221,16 +219,39 @@ public class DnerDailyPowerOutageEventBatchService { DnerDailyPowerOutageEvent daily = new DnerDailyPowerOutageEvent(); daily.setOrgCode(orgCode); daily.setDataTime(date); + daily.setEventId(list.get(0).getEventId()); - // 用户数统计 + //故障停电影响用户总数 + IntSummaryStatistics faultStats = list.stream() + .mapToInt(e -> e.getFaultUserCount() == null ? 0 : e.getFaultUserCount()) + .summaryStatistics(); + daily.setFaultUserCount((int) faultStats.getSum()); + daily.setFaultMaxUserCount(faultStats.getMax()); + daily.setFaultMinUserCount(faultStats.getMin()); + daily.setFaultStarUserCount(list.stream().min(Comparator.comparing(DnerHourlyPowerOutageEvent::getDataTime)) + .map(DnerHourlyPowerOutageEvent::getFaultUserCount).orElse(0)); + daily.setFaultEndUserCount(list.stream().max(Comparator.comparing(DnerHourlyPowerOutageEvent::getDataTime)) + .map(DnerHourlyPowerOutageEvent::getFaultUserCount).orElse(0)); + + //计划停电影响用户数 + IntSummaryStatistics scheduledStats = list.stream() + .mapToInt(e -> e.getScheduledUserCount() == null ? 0 : e.getScheduledUserCount()) + .summaryStatistics(); + daily.setScheduledUserCount((int) scheduledStats.getSum()); + daily.setScheduledMaxUserCount(scheduledStats.getMax()); + daily.setScheduledMinUserCount(scheduledStats.getMin()); + daily.setScheduledStarUserCount(list.stream().min(Comparator.comparing(DnerHourlyPowerOutageEvent::getDataTime)) + .map(DnerHourlyPowerOutageEvent::getScheduledUserCount).orElse(0)); + daily.setScheduledEndUserCount(list.stream().max(Comparator.comparing(DnerHourlyPowerOutageEvent::getDataTime)) + .map(DnerHourlyPowerOutageEvent::getScheduledUserCount).orElse(0)); + + // 停电影响用户总数 IntSummaryStatistics userStats = list.stream() .mapToInt(e -> e.getUserCount() == null ? 0 : e.getUserCount()) .summaryStatistics(); daily.setUserCount((int) userStats.getSum()); daily.setMaxUserCount(userStats.getMax()); daily.setMinUserCount(userStats.getMin()); - - // 起始和结束用户数 daily.setStarUserCount(list.stream().min(Comparator.comparing(DnerHourlyPowerOutageEvent::getDataTime)) .map(DnerHourlyPowerOutageEvent::getUserCount).orElse(0)); daily.setEndUserCount(list.stream().max(Comparator.comparing(DnerHourlyPowerOutageEvent::getDataTime)) diff --git a/src/main/java/com/southern/power/grid/service/impl/DnerDailyPowerOutageEventSyncServiceImpl.java b/src/main/java/com/southern/power/grid/service/impl/DnerDailyPowerOutageEventSyncServiceImpl.java index c46ce27..442d25e 100644 --- a/src/main/java/com/southern/power/grid/service/impl/DnerDailyPowerOutageEventSyncServiceImpl.java +++ b/src/main/java/com/southern/power/grid/service/impl/DnerDailyPowerOutageEventSyncServiceImpl.java @@ -48,10 +48,10 @@ public class DnerDailyPowerOutageEventSyncServiceImpl extends ServiceImpl orgCodeList, String setDate) { + private boolean processDateData(ThreadPoolTaskExecutor executor, String date, List orgCodeList, String setDate, Long eventId) { List> orgCodeBatches = partitionList(orgCodeList, ORG_BATCH_SIZE); log.info("日期 {} 共分 {} 批进行处理", date, orgCodeBatches.size()); log.info("日期 {} 线程池状态: {}", date, ThreadPoolUtil.getThreadPoolMonitorInfo(executor)); @@ -160,7 +161,7 @@ public class DnerDailyPowerOutageEventSyncServiceImpl extends ServiceImpl future = executor.submit(() -> { try { log.info("日期 {} 批次 {} 开始执行,区域数量: {}", date, batchIndex, batchOrgCodes.size()); - batchService.syncDateDataForBatch(date, batchOrgCodes, batchIndex); + batchService.syncDateDataForBatch(date, batchOrgCodes, batchIndex, eventId); return null; } catch (Exception e) { log.error("日期 {} 批次 {} 处理失败: {}", date, batchIndex, e.getMessage(), e); @@ -216,7 +217,7 @@ public class DnerDailyPowerOutageEventSyncServiceImpl extends ServiceImpl() .eq(DnerHourlyPowerOutageEvent::getEventId, eventId)); - dnerDailyPowerOutageEventMapper.delete(new LambdaQueryWrapper() - .eq(DnerDailyPowerOutageEvent::getEventId, eventId)); + dnerDailyPowerOutageEventMapper.delete(new LambdaQueryWrapper().eq(DnerDailyPowerOutageEvent::getEventId,eventId)); + //删除旧的K线图数据的同步记录 + dnerDailyPowerOutageEventSyncMapper.delete( + new LambdaQueryWrapper().eq(DnerDailyPowerOutageEventSync::getEventId, eventId)); + return record.getId(); } } diff --git a/src/main/java/com/southern/power/grid/service/impl/HourlyOutageExcelProcessService.java b/src/main/java/com/southern/power/grid/service/impl/HourlyOutageExcelProcessService.java index 42a98de..d146840 100644 --- a/src/main/java/com/southern/power/grid/service/impl/HourlyOutageExcelProcessService.java +++ b/src/main/java/com/southern/power/grid/service/impl/HourlyOutageExcelProcessService.java @@ -146,6 +146,8 @@ public class HourlyOutageExcelProcessService { */ private void accumulateEvent(DnerHourlyPowerOutageEvent existing, DataExcelEntity row) { existing.setUserCount(row.getUserCount() + existing.getUserCount()); + existing.setScheduledUserCount(row.getScheduledUserCount() + existing.getScheduledUserCount()); + existing.setFaultUserCount(row.getFaultUserCount() + existing.getFaultUserCount()); } /** @@ -203,6 +205,8 @@ public class HourlyOutageExcelProcessService { RegionalWeatherData regionalWeatherData) { DnerHourlyPowerOutageEvent event = new DnerHourlyPowerOutageEvent(); event.setOrgCode(districtCode); + event.setFaultUserCount(0); + event.setScheduledUserCount(0); // 时间转成字符串,入库到 data_time if (row.getStartTime() != null) { @@ -228,8 +232,10 @@ public class HourlyOutageExcelProcessService { String outageTypeStr = row.getOutageType(); if ("故障类".equals(outageTypeStr)) { event.setOutageType("1"); + event.setFaultUserCount(event.getUserCount()); } else if ("计划类".equals(outageTypeStr)) { event.setOutageType("2"); + event.setScheduledUserCount(event.getUserCount()); } else { event.setOutageType(outageTypeStr); // 保留原值或根据需要设置默认值 } diff --git a/src/main/resources/mapper/DnerHourlyPowerOutageEventMapper.xml b/src/main/resources/mapper/DnerHourlyPowerOutageEventMapper.xml index 7475afb..5cf55ae 100644 --- a/src/main/resources/mapper/DnerHourlyPowerOutageEventMapper.xml +++ b/src/main/resources/mapper/DnerHourlyPowerOutageEventMapper.xml @@ -19,14 +19,15 @@ INSERT INTO dner_hourly_power_outage_event ( - org_code, data_time, hourly_precipitation, daily_precipitation, + org_code,event_id, data_time, hourly_precipitation, daily_precipitation, temperature, hourly_max_temperature, hourly_min_temperature, - extreme_wind_speed_hourly, user_count, outage_state, outage_type, + extreme_wind_speed_hourly, user_count,fault_user_count,scheduled_user_count, outage_state, outage_type, create_by, create_time, update_by, update_time ) VALUES ( #{item.orgCode}, + #{item.eventId}, #{item.dataTime}, #{item.hourlyPrecipitation}, #{item.dailyPrecipitation}, @@ -35,6 +36,8 @@ #{item.hourlyMinTemperature}, #{item.extremeWindSpeedHourly}, #{item.userCount}, + #{item.faultUserCount}, + #{item.scheduledUserCount}, #{item.outageState}, #{item.outageType}, #{item.createBy}, @@ -54,13 +57,15 @@