瀏覽代碼

运行部分修正

lisonglin 2 周之前
父節點
當前提交
8d6dfc44d5

+ 1 - 1
services/load-transfer-bf/src/main/java/com/hdkj/lt/bf/entity/dto/SeVoltageAlarmListReq.java

@@ -32,7 +32,7 @@ public class SeVoltageAlarmListReq {
     @ApiModelProperty(value = "时间排序 asc/desc")
     private String orderByTime;
 
-    @ApiModelProperty(value = "告警级别 feeder/mvtrans")
+    @ApiModelProperty(value = "告警级别 feeder/mvtrans", required = true)
     private String alarmLevel;
 
     @ApiModelProperty(value = "页码")

+ 31 - 14
services/load-transfer-bf/src/main/java/com/hdkj/lt/bf/service/impl/SeAlarmServiceImpl.java

@@ -1,6 +1,7 @@
 package com.hdkj.lt.bf.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
 import com.hdkj.lt.bf.entity.FhzgSeCurrentEvent;
 import com.hdkj.lt.bf.entity.FhzgSeMonitorCurrent;
@@ -28,8 +29,7 @@ import java.time.Duration;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
-import java.util.Arrays;
-import java.util.List;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -137,24 +137,41 @@ public class SeAlarmServiceImpl implements SeAlarmService {
         applyOrderBy(wrapper, req.getOrderByTime(), FhzgSeVoltageEvent::getFirstOverTime);
 
         Page<FhzgSeVoltageEvent> result = voltageEventMapper.selectPage(mpPage, wrapper);
-        List<SeAlarmListVO> voList = result.getRecords().stream().map(this::toVoltageVO).collect(Collectors.toList());
+
+        // 批查本页所有配变下的用户事件数,代替 N+1
+        Map<String, Integer> consumerCountMap = new HashMap<>();
+        List<FhzgSeVoltageEvent> mvtransList = result.getRecords().stream()
+                .filter(e -> "mvtrans".equals(e.getAlarmLevel()) && e.getMvtransId() != null)
+                .collect(Collectors.toList());
+        if (!mvtransList.isEmpty()) {
+            List<String> mvtransIds = mvtransList.stream()
+                    .map(FhzgSeVoltageEvent::getMvtransId).distinct().collect(Collectors.toList());
+            QueryWrapper<FhzgSeVoltageEvent> qw = new QueryWrapper<>();
+            qw.select("mvtrans_id", "COUNT(DISTINCT device_id) AS consumer_count")
+                    .eq("alarm_level", "consumer")
+                    .in("mvtrans_id", mvtransIds)
+                    .ge("first_over_time", rangeStart)
+                    .lt("first_over_time", rangeEnd)
+                    .groupBy("mvtrans_id");
+            List<Map<String, Object>> rows = voltageEventMapper.selectMaps(qw);
+            for (Map<String, Object> row : rows) {
+                String mvId = (String) row.get("mvtrans_id");
+                int cnt = ((Number) row.getOrDefault("consumer_count", 0)).intValue();
+                consumerCountMap.put(mvId, cnt);
+            }
+        }
+
+        List<SeAlarmListVO> voList = result.getRecords().stream()
+                .map(e -> toVoltageVO(e, consumerCountMap))
+                .collect(Collectors.toList());
         return PageResult.of(result, voList);
     }
 
-    private SeAlarmListVO toVoltageVO(FhzgSeVoltageEvent e) {
+    private SeAlarmListVO toVoltageVO(FhzgSeVoltageEvent e, Map<String, Integer> consumerCountMap) {
         String displayValue = resolveVoltageDirection(e.getAlarmType());
-        // 台区事件:查窗口内该配变下用户越限事件数(嵌套在配变窗口内的,不去重)
         Integer consumerCount = null;
         if ("mvtrans".equals(e.getAlarmLevel()) && e.getMvtransId() != null) {
-            LocalDateTime windowEnd = (e.getStatus() != null && e.getStatus() == 2 && e.getRecoverTime() != null)
-                    ? e.getRecoverTime() : LocalDateTime.now();
-            Long cnt = voltageEventMapper.selectCount(
-                    new LambdaQueryWrapper<FhzgSeVoltageEvent>()
-                            .eq(FhzgSeVoltageEvent::getAlarmLevel, "consumer")
-                            .eq(FhzgSeVoltageEvent::getMvtransId, e.getMvtransId())
-                            .ge(FhzgSeVoltageEvent::getFirstOverTime, e.getFirstOverTime())
-                            .lt(FhzgSeVoltageEvent::getFirstOverTime, windowEnd));
-            consumerCount = cnt != null ? cnt.intValue() : 0;
+            consumerCount = consumerCountMap.getOrDefault(e.getMvtransId(), 0);
         }
         return SeAlarmListVO.builder()
                 .alarmEventId(e.getId())

+ 92 - 43
services/load-transfer-bf/src/main/java/com/hdkj/lt/bf/service/impl/SeIndicatorServiceImpl.java

@@ -132,31 +132,32 @@ public class SeIndicatorServiceImpl implements SeIndicatorService {
      */
     private int[] countVoltageByAlarmLevel(String id, Integer type, String alarmLevel,
                                             LocalDateTime start, LocalDateTime end) {
-        LambdaQueryWrapper<FhzgSeVoltageEvent> wrapper = new LambdaQueryWrapper<FhzgSeVoltageEvent>()
-                .eq(FhzgSeVoltageEvent::getAlarmLevel, alarmLevel)
-                .ge(FhzgSeVoltageEvent::getFirstOverTime, start)
-                .lt(FhzgSeVoltageEvent::getFirstOverTime, end);
-        applyNodeFilter(wrapper, id, type);
-
-        List<FhzgSeVoltageEvent> events = voltageEventMapper.selectList(wrapper);
-
-        Set<String> overDeviceIds = new HashSet<>();
-        Set<String> underDeviceIds = new HashSet<>();
-        int overTimes = 0, underTimes = 0;
-
-        for (FhzgSeVoltageEvent e : events) {
-            String t = e.getAlarmType();
-            if (t == null) continue;
-            if (t.contains("over")) {
-                if (e.getDeviceId() != null) overDeviceIds.add(e.getDeviceId());
-                overTimes++;
-            } else if (t.contains("under")) {
-                if (e.getDeviceId() != null) underDeviceIds.add(e.getDeviceId());
-                underTimes++;
-            }
+        QueryWrapper<FhzgSeVoltageEvent> qw = new QueryWrapper<>();
+        qw.select(
+                "COUNT(DISTINCT CASE WHEN alarm_type LIKE '%over%' THEN device_id END) AS over_cnt",
+                "COUNT(DISTINCT CASE WHEN alarm_type LIKE '%under%' THEN device_id END) AS under_cnt",
+                "COUNT(CASE WHEN alarm_type LIKE '%over%' THEN 1 END) AS over_times",
+                "COUNT(CASE WHEN alarm_type LIKE '%under%' THEN 1 END) AS under_times")
+                .eq("alarm_level", alarmLevel)
+                .ge("first_over_time", start)
+                .lt("first_over_time", end);
+        if (type == 2) {
+            qw.eq("county_id", id);
+        } else if (type == 3) {
+            qw.eq("subs_id", id);
+        } else if (type == 4) {
+            qw.eq("feeder_id", id);
         }
 
-        return new int[]{overDeviceIds.size(), underDeviceIds.size(), overTimes, underTimes};
+        List<Map<String, Object>> rows = voltageEventMapper.selectMaps(qw);
+        if (rows.isEmpty()) return new int[]{0, 0, 0, 0};
+        Map<String, Object> row = rows.get(0);
+        return new int[]{
+                ((Number) row.getOrDefault("over_cnt", 0)).intValue(),
+                ((Number) row.getOrDefault("under_cnt", 0)).intValue(),
+                ((Number) row.getOrDefault("over_times", 0)).intValue(),
+                ((Number) row.getOrDefault("under_times", 0)).intValue()
+        };
     }
 
     /**
@@ -202,12 +203,17 @@ public class SeIndicatorServiceImpl implements SeIndicatorService {
             startDate = LocalDate.of(today.getYear(), 1, 1);
         }
 
-        // 17:00前:中台到前天 + 我们昨天;17:00后:中台到昨天
-        int hour = LocalDateTime.now().getHour();
-        if (hour < 17) {
-            endDate = today.minusDays(2);
+        String dimLevel = resolveDimLevel(type);
+
+        // 查中台日汇总表最新日期,判断是否需要补昨日
+        String maxOverDate = queryDailyMaxOverDate(dimLevel, id, type);
+        String yesterdayStr = today.minusDays(1).format(DATE_FMT);
+        boolean needFillYesterday = (maxOverDate == null || maxOverDate.compareTo(yesterdayStr) < 0);
+
+        if (needFillYesterday) {
+            endDate = today.minusDays(2); // 中台只到T-2,补昨日T-1
         } else {
-            endDate = today.minusDays(1);
+            endDate = today.minusDays(1); // 中台已有昨天
         }
 
         // 如果 endDate < startDate,返回空
@@ -215,8 +221,6 @@ public class SeIndicatorServiceImpl implements SeIndicatorService {
             return SeVoltageDashboardVO.builder().build();
         }
 
-        String dimLevel = resolveDimLevel(type);
-
         // 一条 SQL 聚合 16个count字段 + total_over_limit_hours
         QueryWrapper<FhzgDwmVoltageOverLimitDaily> qw = new QueryWrapper<>();
         qw.select(
@@ -272,22 +276,48 @@ public class SeIndicatorServiceImpl implements SeIndicatorService {
         BigDecimal totalHours = r != null && r.getTotalOverLimitHours() != null
                 ? r.getTotalOverLimitHours() : BigDecimal.ZERO;
 
-        // 17:00前补昨日数据(从我们alarm_event查昨天)
-        if (hour < 17) {
+        // 补昨日:中台无昨日数据时,从事件表SQL聚合,按 alarm_level 分流
+        if (needFillYesterday) {
             LocalDateTime yesterdayStart = today.minusDays(1).atStartOfDay();
             LocalDateTime yesterdayEnd = today.minusDays(1).atTime(23, 59, 59);
-            LambdaQueryWrapper<FhzgSeVoltageEvent> yesterdayWrapper = new LambdaQueryWrapper<FhzgSeVoltageEvent>()
-                    .ge(FhzgSeVoltageEvent::getTriggerTime, yesterdayStart)
-                    .le(FhzgSeVoltageEvent::getTriggerTime, yesterdayEnd)
-                    .eq(FhzgSeVoltageEvent::getStatus, 2);
-            applyNodeFilter(yesterdayWrapper, id, type);
-            List<FhzgSeVoltageEvent> yesterdayEvents = voltageEventMapper.selectList(yesterdayWrapper);
-            for (FhzgSeVoltageEvent e : yesterdayEvents) {
-                if ("voltage_over".equals(e.getAlarmType()) || e.getAlarmType() != null && e.getAlarmType().contains("over")) {
-                    overUpperMildTg++;
-                } else if (e.getAlarmType() != null && e.getAlarmType().contains("under")) {
-                    overLowerMildTg++;
+
+            QueryWrapper<FhzgSeVoltageEvent> agg = new QueryWrapper<>();
+            agg.select("alarm_level", "alarm_type", "COUNT(*) AS cnt")
+                    .ge("trigger_time", yesterdayStart)
+                    .le("trigger_time", yesterdayEnd)
+                    .eq("status", 2)
+                    .groupBy("alarm_level", "alarm_type");
+            if (type == 2) agg.eq("county_id", id);
+            else if (type == 3) agg.eq("subs_id", id);
+            else if (type == 4) agg.eq("feeder_id", id);
+
+            List<Map<String, Object>> aggRows = voltageEventMapper.selectMaps(agg);
+            for (Map<String, Object> row : aggRows) {
+                String alarmLevel = (String) row.get("alarm_level");
+                String alarmType = (String) row.get("alarm_type");
+                int cnt = ((Number) row.getOrDefault("cnt", 0)).intValue();
+                if (alarmType == null) continue;
+                boolean isOver = alarmType.contains("over");
+                boolean isUnder = alarmType.contains("under");
+                if (!isOver && !isUnder) continue;
+                boolean isSevere = alarmType.contains("severe");
+
+                if ("consumer".equals(alarmLevel)) {
+                    if (isOver) {
+                        if (isSevere) overUpperSevereCust += cnt;
+                        else overUpperMildCust += cnt;
+                    } else {
+                        if (isSevere) overLowerSevereCust += cnt;
+                        else overLowerMildCust += cnt;
+                    }
+                } else if ("mvtrans".equals(alarmLevel)) {
+                    if (isOver) overUpperMildTg += cnt;
+                    else overLowerMildTg += cnt;
+                } else if ("feeder".equals(alarmLevel)) {
+                    if (isOver) overUpperMildFeeder += cnt;
+                    else overLowerMildFeeder += cnt;
                 }
+                // generatrix → 跳过
             }
         }
 
@@ -531,4 +561,23 @@ public class SeIndicatorServiceImpl implements SeIndicatorService {
     private int safeInt(Integer v) {
         return v == null ? 0 : v;
     }
+
+    /**
+     * 查中台日汇总表该维度的最新 over_date
+     */
+    private String queryDailyMaxOverDate(String dimLevel, String id, Integer type) {
+        QueryWrapper<FhzgDwmVoltageOverLimitDaily> qw = new QueryWrapper<>();
+        qw.select("MAX(over_date) AS max_over_date")
+                .eq("dim_level", dimLevel);
+        if (type == 2) qw.eq("maintainer_id", id);
+        else if (type == 3) qw.eq("substation_id", id);
+        else if (type == 4) qw.eq("feeder_id", id);
+        qw.last("LIMIT 1");
+        List<Map<String, Object>> records = voltageDailyMapper.selectMaps(qw);
+        if (records != null && !records.isEmpty()) {
+            Object val = records.get(0).get("max_over_date");
+            return val != null ? val.toString() : null;
+        }
+        return null;
+    }
 }