|
|
@@ -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;
|
|
|
+ }
|
|
|
}
|