From 23f3a73cf986db7f1642e89fcfb447f0645556e7 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 23 Jun 2026 13:51:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=94=B5=E7=AB=99=E6=B0=B4=E4=BD=8D?= =?UTF-8?q?=E3=80=81=E7=94=9F=E6=80=81=E6=B5=81=E9=87=8F=E5=91=8A=E8=AD=A6?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yfd/platform/config/SwaggerConfig.java | 10 + .../warn/controller/WarnDataController.java | 29 ++ .../warn/entity/vo/EngWarnCountVo.java | 28 ++ .../qgc_env/warn/service/WarnDataService.java | 10 + .../service/impl/WarnDataServiceImpl.java | 315 ++++++++++++++++++ 5 files changed, 392 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/warn/controller/WarnDataController.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/EngWarnCountVo.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/warn/service/WarnDataService.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/warn/service/impl/WarnDataServiceImpl.java diff --git a/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java b/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java index 3eb42938..73f92660 100644 --- a/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java +++ b/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java @@ -135,6 +135,16 @@ public class SwaggerConfig { .build(); } + @Bean + public GroupedOpenApi groupEnvWarnApi() { + return GroupedOpenApi.builder() + .group("3.8 全过程-生态环保数据服务-智能告警") + .packagesToScan("com.yfd.platform.qgc_env.warn.controller") + .build(); + } + + + diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/controller/WarnDataController.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/controller/WarnDataController.java new file mode 100644 index 00000000..5fce9628 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/controller/WarnDataController.java @@ -0,0 +1,29 @@ +package com.yfd.platform.qgc_env.warn.controller; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.qgc_env.warn.service.WarnDataService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/warn/stcd") +@Tag(name = "告警状态模块") +@Validated +public class WarnDataController { + + @Resource + private WarnDataService warnDataService; + + @PostMapping("/eng/GetKendoListCust") + @Operation(summary = "电站水位、生态流量告警状态统计") + public ResponseResult getEngWarnCount(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getEngWarnCount(dataSourceRequest)); + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/EngWarnCountVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/EngWarnCountVo.java new file mode 100644 index 00000000..b0cfb180 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/EngWarnCountVo.java @@ -0,0 +1,28 @@ +package com.yfd.platform.qgc_env.warn.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +@Schema(description = "电站告警状态统计") +public class EngWarnCountVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "告警状态") + private Integer warnState; + + @Schema(description = "告警状态名称") + private String warnStateName; + + @Schema(description = "数量") + private Integer num; + + @Schema(description = "告警类型") + private String warnType; + + @Schema(description = "告警类型名称") + private String warnTypeName; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/WarnDataService.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/WarnDataService.java new file mode 100644 index 00000000..b809eaf6 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/WarnDataService.java @@ -0,0 +1,10 @@ +package com.yfd.platform.qgc_env.warn.service; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.qgc_env.warn.entity.vo.EngWarnCountVo; + +public interface WarnDataService { + + DataSourceResult getEngWarnCount(DataSourceRequest dataSourceRequest); +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/impl/WarnDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/impl/WarnDataServiceImpl.java new file mode 100644 index 00000000..e5f94b32 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/impl/WarnDataServiceImpl.java @@ -0,0 +1,315 @@ +package com.yfd.platform.qgc_env.warn.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.common.DataSourceLoadOptionsBase; +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.common.MicroservicDynamicSQLMapper; +import com.yfd.platform.qgc_env.warn.entity.vo.EngWarnCountVo; +import com.yfd.platform.qgc_env.warn.service.WarnDataService; +import com.yfd.platform.utils.QgcQueryWrapperUtil; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class WarnDataServiceImpl implements WarnDataService { + + @Resource + private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; + + @Override + public DataSourceResult getEngWarnCount(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Map paramMap = new HashMap<>(); + String filterSql = buildSourceFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("r.warnState AS warnState, ") + .append("r.num AS num, ") + .append("r.warnType AS warnType ") + .append("FROM (") + .append(buildEngWarnCountSql(filterSql)) + .append(") r "); + sql.append(buildOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + EngWarnCountVo.class + ); + fillWarnNames(list); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private String buildEngWarnCountSql(String filterSql) { + String normalizedWarnStateExpr = "CASE " + + "WHEN t.WARN_STATE = '0' OR t.WARN_STATE IS NULL OR t.WARN_STATE = '' THEN '00' " + + "ELSE t.WARN_STATE END"; + StringBuilder sql = new StringBuilder(); + sql.append("SELECT s.warnState, COUNT(s.STCD) AS num, s.warnType ") + .append("FROM ("); + sql.append("SELECT DISTINCT ") + .append("t.STCD AS STCD, ") + .append("TO_NUMBER(SUBSTR(").append(normalizedWarnStateExpr).append(", 1, 1)) AS warnState, ") + .append("'RZ' AS warnType ") + .append("FROM SD_ENGINFO_B_H t ") + .append("WHERE NVL(t.IS_DELETED, 0) = 0 ") + .append("AND NVL(t.USFL, 0) = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append("UNION ALL "); + sql.append("SELECT DISTINCT ") + .append("t.STCD AS STCD, ") + .append("NVL(TO_NUMBER(SUBSTR(").append(normalizedWarnStateExpr).append(", 2, 1)), 0) AS warnState, ") + .append("'QEC' AS warnType ") + .append("FROM SD_ENGINFO_B_H t ") + .append("WHERE NVL(t.IS_DELETED, 0) = 0 ") + .append("AND NVL(t.BLDSTT_CODE, -1) = 2 ") + .append("AND NVL(t.DTIN, 0) = 1 ") + .append("AND NVL(t.RUN_STATE, 2) = 4 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(") s GROUP BY s.warnType, s.warnState"); + return sql.toString(); + } + + private void fillWarnNames(List list) { + if (CollUtil.isEmpty(list)) { + return; + } + for (EngWarnCountVo item : list) { + if (item == null) { + continue; + } + item.setWarnStateName(resolveWarnStateName(item.getWarnState())); + item.setWarnTypeName(resolveWarnTypeName(item.getWarnType())); + } + } + + private String resolveWarnStateName(Integer warnState) { + if (warnState == null) { + return null; + } + return switch (warnState) { + case 0 -> "无数据"; + case 1 -> "正常"; + case 2 -> "告警"; + default -> null; + }; + } + + private String resolveWarnTypeName(String warnType) { + if ("RZ".equalsIgnoreCase(warnType)) { + return "电站水位"; + } + if ("QEC".equalsIgnoreCase(warnType)) { + return "生态流量"; + } + return null; + } + + private String buildSourceFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildSourceLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildSourceFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildSourceLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapSourceColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + return buildSimpleCondition(column, "warnParam", filter, paramMap, indexHolder); + } + + private String buildSimpleCondition(String column, + String paramPrefix, + DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + Object value = filter.getValue(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("in".equals(operator)) { + List values = normalizeValues(value); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String paramKey = paramPrefix + indexHolder[0]++; + paramMap.put(paramKey, item); + placeholders.add("#{map." + paramKey + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + String paramKey = paramPrefix + indexHolder[0]++; + return switch (operator) { + case "eq" -> { + paramMap.put(paramKey, value); + yield column + " = #{map." + paramKey + "}"; + } + case "neq" -> { + paramMap.put(paramKey, value); + yield column + " <> #{map." + paramKey + "}"; + } + case "contains" -> { + paramMap.put(paramKey, "%" + value + "%"); + yield column + " LIKE #{map." + paramKey + "}"; + } + case "startswith" -> { + paramMap.put(paramKey, value + "%"); + yield column + " LIKE #{map." + paramKey + "}"; + } + case "endswith" -> { + paramMap.put(paramKey, "%" + value); + yield column + " LIKE #{map." + paramKey + "}"; + } + case "gt" -> { + paramMap.put(paramKey, value); + yield column + " > #{map." + paramKey + "}"; + } + case "gte" -> { + paramMap.put(paramKey, value); + yield column + " >= #{map." + paramKey + "}"; + } + case "lt" -> { + paramMap.put(paramKey, value); + yield column + " < #{map." + paramKey + "}"; + } + case "lte" -> { + paramMap.put(paramKey, value); + yield column + " <= #{map." + paramKey + "}"; + } + default -> ""; + }; + } + + private List normalizeValues(Object value) { + List values = new ArrayList<>(); + if (value instanceof List list) { + for (Object item : list) { + if (item != null) { + values.add(item); + } + } + return values; + } + if (value instanceof Object[] array) { + for (Object item : array) { + if (item != null) { + values.add(item); + } + } + return values; + } + if (value != null) { + values.add(value); + } + return values; + } + + private String buildOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY CASE r.warnType WHEN 'RZ' THEN 1 WHEN 'QEC' THEN 2 ELSE 99 END, r.warnState"; + } + List orderItems = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sortList) { + String column = mapResultColumn(sort == null ? null : sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderItems.add(column + " " + direction); + } + if (orderItems.isEmpty()) { + return " ORDER BY CASE r.warnType WHEN 'RZ' THEN 1 WHEN 'QEC' THEN 2 ELSE 99 END, r.warnState"; + } + return " ORDER BY " + String.join(", ", orderItems); + } + + private String mapSourceColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd", "rstcd" -> "t.STCD"; + case "ennm", "stnm" -> "t.ENNM"; + case "baseId" -> "t.BASE_ID"; + case "hbrvcd" -> "t.HBRVCD"; + case "rvcd" -> "t.RVCD"; + case "addvcd" -> "t.ADDVCD"; + case "country" -> "t.COUNTRY"; + case "reachcd" -> "t.REACHCD"; + case "hycd" -> "t.HYCD"; + case "usfl" -> "NVL(t.USFL, 0)"; + case "dtin" -> "NVL(t.DTIN, 0)"; + case "runState" -> "NVL(t.RUN_STATE, 2)"; + case "bldsttCode", "bldsttCcode" -> "NVL(t.BLDSTT_CODE, -1)"; + default -> null; + }; + } + + private String mapResultColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "warnState" -> "r.warnState"; + case "num" -> "r.num"; + case "warnType" -> "r.warnType"; + default -> null; + }; + } +}