From d42040b13385261ad1242af93985d7cc5b11c942 Mon Sep 17 00:00:00 2001 From: tangwei Date: Thu, 18 Jun 2026 09:45:06 +0800 Subject: [PATCH 01/38] =?UTF-8?q?feat:=20=E6=B2=BF=E7=A8=8B=E7=94=9F?= =?UTF-8?q?=E6=80=81=E6=B5=81=E9=87=8F=E9=99=90=E5=80=BC=E5=8F=98=E5=8C=96?= =?UTF-8?q?=E6=9B=B2=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eq/controller/EngEqDataController.java | 11 + .../eq/entity/vo/EngEqLimitQueryVo.java | 20 ++ .../qgc_eng/eq/entity/vo/EngEqLimitVo.java | 28 +++ .../qgc_eng/eq/service/EngEqDataService.java | 6 + .../eq/service/impl/EngEqDataServiceImpl.java | 210 ++++++++++++++++++ 5 files changed, 275 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqLimitQueryVo.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqLimitVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java index 64e9c879..db724237 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java @@ -6,6 +6,8 @@ import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDrtpDataVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqIntervalVo; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqLimitQueryVo; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqLimitVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqMsstbprptVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqRuleVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqVmsstbprptVo; @@ -22,6 +24,8 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.List; + @RestController @RequestMapping("/eq") @Tag(name = "电站实时数据查询") @@ -87,6 +91,13 @@ public class EngEqDataController { return ResponseResult.successData(engEqDataService.getQgcHourVAlongKendoListCust(dataSourceRequest)); } + @PostMapping("/engalong/statistics/qgc/getEngLimit") + @Operation(summary = "沿程生态流量限值变化曲线") + public ResponseResult getQgcEngLimit(@RequestBody EngEqLimitQueryVo queryVo) { + List result = engEqDataService.getQgcEngLimit(queryVo); + return ResponseResult.successData(result); + } + @PostMapping("/fid/GetKendoListCust") @Operation(summary = "查询电站相关鱼类附件编码") public ResponseResult getFidKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqLimitQueryVo.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqLimitQueryVo.java new file mode 100644 index 00000000..f9985176 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqLimitQueryVo.java @@ -0,0 +1,20 @@ +package com.yfd.platform.qgc_eng.eq.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +@Data +@Accessors(chain = true) +@Schema(description = "沿程生态流量限值查询参数") +public class EngEqLimitQueryVo { + + @Schema(description = "查询日期,支持 yyyy-MM-dd、yyyy-MM-dd HH:mm、yyyy-MM-dd HH:mm:ss") + private String date; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "流域编码") + private String rvcd; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqLimitVo.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqLimitVo.java new file mode 100644 index 00000000..f0083108 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqLimitVo.java @@ -0,0 +1,28 @@ +package com.yfd.platform.qgc_eng.eq.entity.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; +import java.util.Date; + +@Data +@Accessors(chain = true) +@Schema(description = "沿程生态流量限值") +public class EngEqLimitVo { + + @Schema(description = "电站编码") + private String stcd; + + @Schema(description = "电站名称") + private String stnm; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Schema(description = "查询日期") + private Date date; + + @Schema(description = "生态流量限值") + private BigDecimal qecLimit; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java index e68b0699..729bf403 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java @@ -7,6 +7,8 @@ import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDrtpDataVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDayIntervalVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqHourIntervalVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqIntervalVo; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqLimitQueryVo; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqLimitVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqMsstbprptVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqRuleVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngQecAlongVo; @@ -16,6 +18,8 @@ import com.yfd.platform.qgc_eng.eq.entity.vo.QgcQecStaticVo; import com.yfd.platform.qgc_eng.eq.entity.vo.SdEqMonitorCountVo; import com.yfd.platform.qgc_eng.eq.entity.vo.WbsbVo; +import java.util.List; + public interface EngEqDataService { DataSourceResult getKendoListCust(DataSourceRequest dataSourceRequest); @@ -34,6 +38,8 @@ public interface EngEqDataService { DataSourceResult getQgcHourVAlongKendoListCust(DataSourceRequest dataSourceRequest); + List getQgcEngLimit(EngEqLimitQueryVo queryVo); + DataSourceResult getFidKendoListCust(DataSourceRequest dataSourceRequest); EngEqRuleVo getEngLimit(DataSourceRequest dataSourceRequest); diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java index 5f898876..ce289df7 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java @@ -16,6 +16,8 @@ import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDataVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDayDataVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDrtpDataVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDayIntervalVo; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqLimitQueryVo; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqLimitVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngFidVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqHourIntervalVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqIntervalVo; @@ -46,6 +48,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.format.DateTimeFormatter; @Service @@ -380,6 +383,56 @@ public class EngEqDataServiceImpl implements EngEqDataService { return result; } + @Override + public List getQgcEngLimit(EngEqLimitQueryVo queryVo) { + if (queryVo == null || StrUtil.isBlank(queryVo.getDate())) { + throw new IllegalArgumentException("查询日期不能为空."); + } + Date queryDate = parseEngLimitQueryDate(queryVo.getDate()); + if (queryDate == null) { + throw new IllegalArgumentException("查询日期格式不正确."); + } + + String baseId = StrUtil.trimToNull(queryVo.getBaseId()); + String rvcd = StrUtil.trimToNull(queryVo.getRvcd()); + Map paramMap = new HashMap<>(); + paramMap.put("queryDate", formatDateTime(queryDate)); + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("baseId", baseId); + } + if (StrUtil.isNotBlank(rvcd)) { + paramMap.put("rvcd", rvcd); + } + + List stationList = microservicDynamicSQLMapper.getAllListWithResultType( + buildQgcEngLimitStationSql(baseId, rvcd), + paramMap, + EngEqLimitVo.class + ); + if (CollUtil.isEmpty(stationList)) { + return new ArrayList<>(); + } + + List> ruleRows = microservicDynamicSQLMapper.pageAllList( + null, + buildQgcEngLimitRuleSql(baseId, rvcd), + paramMap + ); + Map>> stationRuleMap = new HashMap<>(); + for (Map row : ruleRows) { + String stcd = asString(row.get("STCD")); + if (StrUtil.isBlank(stcd)) { + continue; + } + stationRuleMap.computeIfAbsent(stcd, key -> new ArrayList<>()).add(row); + } + for (EngEqLimitVo station : stationList) { + station.setDate(queryDate); + station.setQecLimit(resolveQgcEngLimitValue(queryDate, stationRuleMap.get(station.getStcd()))); + } + return stationList; + } + @Override public EngEqRuleVo getEngLimit(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -1278,6 +1331,55 @@ public class EngEqDataServiceImpl implements EngEqDataService { return sql.toString(); } + private String buildQgcEngLimitStationScopeSql(String baseId, String rvcd) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT det.STCD AS stcd, eng.ENNM AS stnm, along.ORDER_INDEX AS rvcdSort, det.SORT AS stcdSort ") + .append("FROM MS_ALONG_B along ") + .append("INNER JOIN MS_ALONGDET_B det ON along.ID = det.ALONG_ID ") + .append("INNER JOIN SD_ENGINFO_B_H eng ON eng.STCD = det.STCD ") + .append("WHERE det.STTP = 'ENG' ") + .append(" AND NVL(eng.IS_DELETED, 0) = 0 ") + .append(" AND NVL(eng.BLDSTT_CODE, 0) = 2 ") + .append(" AND along.CODE = 'common' ") + .append(" AND NVL(along.IS_DELETED, 0) = 0 ") + .append(" AND NVL(det.IS_DELETED, 0) = 0 "); + if (StrUtil.isNotBlank(baseId)) { + sql.append(" AND along.RVCD IN (") + .append("SELECT dic.HBRVCD FROM SD_HBRV_DIC dic ") + .append("WHERE dic.BASEID = #{map.baseId} ") + .append(" AND NVL(dic.IS_DELETED, 0) = 0 ") + .append(" AND NVL(dic.ENABLED, 1) = 1") + .append(") "); + } + if (StrUtil.isNotBlank(rvcd)) { + sql.append(" AND along.RVCD = #{map.rvcd} "); + } + return sql.toString(); + } + + private String buildQgcEngLimitStationSql(String baseId, String rvcd) { + return "SELECT scope.STCD AS stcd, scope.STNM AS stnm " + + "FROM (" + buildQgcEngLimitStationScopeSql(baseId, rvcd) + ") scope " + + "ORDER BY scope.RVCDSORT, scope.STCDSORT"; + } + + private String buildQgcEngLimitRuleSql(String baseId, String rvcd) { + return "SELECT scope.STCD AS stcd, det.TM AS tm, det.MIN_VAL AS minVal, " + + "det.BEGIN_TIME AS beginTime, det.END_TIME AS endTime " + + "FROM (" + buildQgcEngLimitStationScopeSql(baseId, rvcd) + ") scope " + + "INNER JOIN MS_WARN_RULE_STBPRP_B rel ON rel.STCD = scope.STCD " + + " AND NVL(rel.IS_DELETED, 0) = 0 " + + "INNER JOIN MS_WARN_RULE_B rule ON rule.ID = rel.RULE_ID " + + " AND rule.RULE_TYPE = 'EQMN' " + + " AND NVL(rule.IS_DELETED, 0) = 0 " + + "INNER JOIN MS_WARN_RULE_DETAIL_B det ON det.RULE_ID = rule.ID " + + " AND NVL(det.IS_DELETED, 0) = 0 " + + "WHERE det.TM <= TO_DATE(#{map.queryDate}, 'YYYY-MM-DD HH24:MI:SS') " + + " AND det.MIN_VAL IS NOT NULL " + + "ORDER BY scope.STCD, det.TM DESC, LPAD(det.BEGIN_TIME, 4, '0') DESC NULLS LAST, " + + " LPAD(det.END_TIME, 4, '0') DESC NULLS LAST"; + } + private List> queryEngLimitRuleDetails(String stcd, String startTime, String endTime, @@ -1338,6 +1440,100 @@ public class EngEqDataServiceImpl implements EngEqDataService { return prefix + String.join(";", parts); } + private BigDecimal resolveQgcEngLimitValue(Date queryDate, List> ruleRows) { + if (queryDate == null || CollUtil.isEmpty(ruleRows)) { + return null; + } + Date currentTm = null; + List> currentRows = new ArrayList<>(); + String monthDay = DateTimeFormatter.ofPattern("MMdd").format( + queryDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate() + ); + for (Map row : ruleRows) { + Date tm = toDate(row.get("TM")); + if (tm == null || queryDate.compareTo(tm) < 0) { + continue; + } + if (currentTm != null && !currentTm.equals(tm)) { + return matchQgcEngLimitValue(monthDay, currentRows); + } + currentTm = tm; + currentRows.add(row); + } + if (currentTm == null) { + return null; + } + return matchQgcEngLimitValue(monthDay, currentRows); + } + + private BigDecimal matchQgcEngLimitValue(String monthDay, List> ruleRows) { + BigDecimal defaultValue = null; + for (Map row : ruleRows) { + BigDecimal minVal = toBigDecimal(row.get("MINVAL")); + if (minVal == null) { + continue; + } + String beginTime = normalizeMonthDay(asString(row.get("BEGINTIME"))); + String endTime = normalizeMonthDay(asString(row.get("ENDTIME"))); + if (StrUtil.isNotBlank(beginTime) && StrUtil.isNotBlank(endTime)) { + if (isMonthDayInRange(monthDay, beginTime, endTime)) { + return minVal; + } + continue; + } + if (StrUtil.isBlank(beginTime) && StrUtil.isBlank(endTime)) { + defaultValue = minVal; + } + } + return defaultValue; + } + + private boolean isMonthDayInRange(String monthDay, String beginTime, String endTime) { + if (StrUtil.hasBlank(monthDay, beginTime, endTime)) { + return false; + } + return monthDay.compareTo(beginTime) >= 0 && monthDay.compareTo(endTime) <= 0; + } + + private String normalizeMonthDay(String value) { + String text = StrUtil.trimToNull(value); + if (text == null) { + return null; + } + return StrUtil.padPre(text, 4, '0'); + } + + private Date parseEngLimitQueryDate(String text) { + String value = StrUtil.trimToNull(text); + if (value == null) { + return null; + } + value = value.replace('T', ' '); + try { + if (value.length() == 10) { + LocalDate localDate = LocalDate.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd")); + return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); + } + if (value.length() == 16) { + LocalDateTime localDateTime = LocalDateTime.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")); + return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); + } + LocalDateTime localDateTime = LocalDateTime.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); + } catch (Exception ex) { + return null; + } + } + + private String formatDateTime(Date date) { + if (date == null) { + return null; + } + return DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format( + date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime() + ); + } + private String buildHourIntervalViewSql(DataSourceRequest.FilterDescriptor filter, Map paramMap, int[] indexHolder) { @@ -4306,6 +4502,20 @@ public class EngEqDataServiceImpl implements EngEqDataService { return new BigDecimal(String.valueOf(value)); } + private Date toDate(Object value) { + if (value == null) { + return null; + } + if (value instanceof Date date) { + return date; + } + String text = StrUtil.trimToNull(String.valueOf(value)); + if (text == null) { + return null; + } + return parseEngLimitQueryDate(text); + } + private String stripTrailingZeros(BigDecimal value) { if (value == null) { return null; From eea7aa8213d6a23c3b5d24c7c91ed4b92f9f4e55 Mon Sep 17 00:00:00 2001 From: tangwei Date: Thu, 18 Jun 2026 14:21:28 +0800 Subject: [PATCH 02/38] =?UTF-8?q?feat:=20=E7=94=9F=E6=80=81=E6=B5=81?= =?UTF-8?q?=E9=87=8F=E6=B3=84=E6=94=BE=E8=AE=BE=E6=96=BD=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eq/controller/EngEqDataController.java | 8 + .../eq/entity/vo/EngEqBaseMsstbprptVo.java | 77 +++++ .../qgc_eng/eq/service/EngEqDataService.java | 3 + .../eq/service/impl/EngEqDataServiceImpl.java | 291 ++++++++++++++++++ 4 files changed, 379 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseMsstbprptVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java index db724237..abff7d48 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java @@ -4,6 +4,7 @@ import com.yfd.platform.common.DataSourceLoadOptionsBase; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseMsstbprptVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDrtpDataVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqIntervalVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqLimitQueryVo; @@ -73,6 +74,13 @@ public class EngEqDataController { return ResponseResult.successData(result); } + @PostMapping("/base/msstbprpt/GetKendoList") + @Operation(summary = "生态流量泄放设施基础信息查询") + public ResponseResult getBaseMsstbprptList(@RequestBody DataSourceRequest dataSourceRequest) { + DataSourceResult result = engEqDataService.getBaseMsstbprptList(dataSourceRequest); + return ResponseResult.successData(result); + } + @PostMapping("/interval/qgc/hour/GetKendoListCust") @Operation(summary = "生态流量达标率小时统计(二级页面)") public ResponseResult getQgcHourKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseMsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseMsstbprptVo.java new file mode 100644 index 00000000..e90510ac --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseMsstbprptVo.java @@ -0,0 +1,77 @@ +package com.yfd.platform.qgc_eng.eq.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@Data +@Schema(description = "生态流量泄放设施基础信息查询") +public class EngEqBaseMsstbprptVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "设施编码") + private String stcd; + + @Schema(description = "设施名称") + private String stnm; + + @Schema(description = "设施类型编码") + private String sttpCode; + + @Schema(description = "设施类型名称") + private String sttpName; + + @Schema(description = "所属电站编码") + private String rstcd; + + @Schema(description = "所属电站名称") + private String rstcdName; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "基地名称") + private String baseName; + + @Schema(description = "基地流域编码") + private String hbrvcd; + + @Schema(description = "基地流域名称") + private String hbrvcdName; + + @Schema(description = "设施位置") + private String stlc; + + @Schema(description = "经度") + private Double lgtd; + + @Schema(description = "纬度") + private Double lttd; + + @Schema(description = "高程") + private Double elev; + + @Schema(description = "建设状态分类编码") + private Integer bldsttCode; + + @Schema(description = "建设状态分类名称") + private String bldsttCodeName; + + @Schema(description = "数据接入状态") + private Integer dtin; + + @Schema(description = "数据接入状态中文") + private String dtinName; + + @Schema(description = "数据接入时间") + private Date dtinTm; + + @Schema(description = "数据时间") + private Date tm; + + @Schema(description = "排序") + private Integer orderIndex; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java index 729bf403..e1541b32 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java @@ -2,6 +2,7 @@ package com.yfd.platform.qgc_eng.eq.service; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseMsstbprptVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDayDataVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDrtpDataVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDayIntervalVo; @@ -32,6 +33,8 @@ public interface EngEqDataService { DataSourceResult getMsstbprptList(DataSourceRequest dataSourceRequest); + DataSourceResult getBaseMsstbprptList(DataSourceRequest dataSourceRequest); + DataSourceResult getQgcHourKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getQgcDayKendoListCust(DataSourceRequest dataSourceRequest); diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java index ce289df7..bb83777e 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java @@ -12,6 +12,7 @@ import com.yfd.platform.common.GroupingInfo; import com.yfd.platform.common.MicroservicDynamicSQLMapper; import com.yfd.platform.common.enums.QecIntervalEnum; import com.yfd.platform.common.enums.ShowEnum; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseMsstbprptVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDataVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDayDataVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDrtpDataVo; @@ -102,6 +103,194 @@ public class EngEqDataServiceImpl implements EngEqDataService { return queryMsstbprptGroupList(dataSourceRequest, loadOptions); } + @Override + public DataSourceResult getBaseMsstbprptList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + if (CollUtil.isEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + return queryBaseMsstbprptDetailList(dataSourceRequest, loadOptions); + } + return queryBaseMsstbprptGroupList(dataSourceRequest, loadOptions); + } + + private DataSourceResult queryBaseMsstbprptDetailList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildBaseMsstbprptDetailSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildBaseMsstbprptViewSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = buildBaseMsstbprptFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildBaseMsstbprptDetailOrderBySql(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, EngEqBaseMsstbprptVo.class); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private DataSourceResult queryBaseMsstbprptGroupList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + List groups = dataSourceRequest.getGroup(); + GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup(); + List selectItems = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapBaseMsstbprptColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + selectItems.add(column + " AS " + descriptor.getField().toUpperCase()); + selectItems.add("COUNT(*) AS COUNT_" + descriptor.getField().toUpperCase()); + if (CollUtil.isNotEmpty(descriptor.getAggregates())) { + for (DataSourceRequest.AggregateDescriptor aggregate : descriptor.getAggregates()) { + String aggregateColumn = mapBaseMsstbprptColumn(aggregate.getField()); + if (StrUtil.isBlank(aggregateColumn) || StrUtil.isBlank(aggregate.getAggregate())) { + continue; + } + selectItems.add(buildAggregateSql(aggregate.getAggregate(), aggregateColumn, aggregate.getField())); + } + } + } + if (selectItems.isEmpty()) { + selectItems.add("t.STCD AS STCD"); + selectItems.add("COUNT(*) AS COUNT_STCD"); + } + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(String.join(", ", selectItems)) + .append(" FROM (") + .append(buildBaseMsstbprptViewSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = buildBaseMsstbprptFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + + List groupByColumns = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapBaseMsstbprptColumn(descriptor.getField()); + if (StrUtil.isNotBlank(column)) { + groupByColumns.add(column); + } + } + if (!groupByColumns.isEmpty()) { + sql.append(" GROUP BY ").append(String.join(", ", groupByColumns)).append(" "); + } + sql.append(buildBaseMsstbprptGroupOrderBySql(groups)); + + List> rows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap); + DataSourceResult result = new DataSourceResult<>(); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal((long) rows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private String buildBaseMsstbprptViewSql() { + return "SELECT " + + "eq.STCD AS stcd, " + + "eq.STNM AS stnm, " + + "eq.STTP AS sttpCode, " + + "CASE eq.STTP " + + " WHEN 'EQ_1' THEN '生态放流孔' " + + " WHEN 'EQ_2' THEN '生态放流闸' " + + " WHEN 'EQ_3' THEN '生态放流洞' " + + " WHEN 'EQ_4' THEN '生态放流管' " + + " WHEN 'EQ_5' THEN '基荷发电' " + + " WHEN 'EQ_6' THEN '生态机组' " + + " ELSE eq.STTP END AS sttpName, " + + "eq.RSTCD AS rstcd, " + + "eng.ENNM AS rstcdName, " + + "eq.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName, " + + "eq.HBRVCD AS hbrvcd, " + + "hbrv.HBRVNM AS hbrvcdName, " + + "eq.STLC AS stlc, " + + "eq.LGTD AS lgtd, " + + "eq.LTTD AS lttd, " + + "eq.ELEV AS elev, " + + "eq.BLDSTT_CODE AS bldsttCode, " + + "CASE eq.BLDSTT_CODE WHEN 0 THEN '未建/规划' WHEN 1 THEN '在建' WHEN 2 THEN '已建' ELSE NULL END AS bldsttCodeName, " + + "eq.DTIN AS dtin, " + + "CASE NVL(eq.DTIN, 0) WHEN 1 THEN '是' WHEN 0 THEN '否' ELSE NULL END AS dtinName, " + + "eq.DTIN_TM AS dtinTm, " + + "eq.TM AS tm, " + + "eq.ORDER_INDEX AS orderIndex " + + "FROM SD_EQ_B_H eq " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = eq.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eq.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eq.HBRVCD AND hbrv.BASEID = eq.BASE_ID " + + " AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 " + + "WHERE NVL(eq.IS_DELETED, 0) = 0"; + } + + private String buildBaseMsstbprptDetailSelectSql(List selectFields) { + Map columns = baseMsstbprptFieldColumns(); + List selected = new ArrayList<>(); + if (CollUtil.isEmpty(selectFields)) { + selected.addAll(columns.values()); + } else { + for (String field : selectFields) { + String column = columns.get(field); + if (StrUtil.isNotBlank(column)) { + selected.add(column); + } + } + if (selected.isEmpty()) { + selected.addAll(columns.values()); + } + } + return String.join(", ", selected); + } + + private Map baseMsstbprptFieldColumns() { + Map columns = new LinkedHashMap<>(); + columns.put("stcd", "t.stcd AS stcd"); + columns.put("stnm", "t.stnm AS stnm"); + columns.put("sttp", "t.sttpCode AS sttp"); + columns.put("sttpCode", "t.sttpCode AS sttpCode"); + columns.put("sttpName", "t.sttpName AS sttpName"); + columns.put("rstcd", "t.rstcd AS rstcd"); + columns.put("rstcdName", "t.rstcdName AS rstcdName"); + columns.put("baseId", "t.baseId AS baseId"); + columns.put("baseName", "t.baseName AS baseName"); + columns.put("hbrvcd", "t.hbrvcd AS hbrvcd"); + columns.put("hbrvcdName", "t.hbrvcdName AS hbrvcdName"); + columns.put("stlc", "t.stlc AS stlc"); + columns.put("lgtd", "t.lgtd AS lgtd"); + columns.put("lttd", "t.lttd AS lttd"); + columns.put("elev", "t.elev AS elev"); + columns.put("bldsttCode", "t.bldsttCode AS bldsttCode"); + columns.put("bldsttCodeName", "t.bldsttCodeName AS bldsttCodeName"); + columns.put("dtin", "t.dtin AS dtin"); + columns.put("dtinName", "t.dtinName AS dtinName"); + columns.put("dtinTm", "t.dtinTm AS dtinTm"); + columns.put("tm", "t.tm AS tm"); + columns.put("orderIndex", "t.orderIndex AS orderIndex"); + return columns; + } + private DataSourceResult queryMsstbprptDetailList(DataSourceRequest dataSourceRequest, DataSourceLoadOptionsBase loadOptions) { StringBuilder sql = new StringBuilder(); @@ -2808,6 +2997,74 @@ public class EngEqDataServiceImpl implements EngEqDataService { return orders.isEmpty() ? "" : " ORDER BY " + String.join(", ", orders); } + private String buildBaseMsstbprptFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + String column = mapBaseMsstbprptColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + return buildGenericCondition(column, filter, paramMap, indexHolder, isBaseMsstbprptDateField(filter.getField())); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildBaseMsstbprptFilterCondition(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 buildBaseMsstbprptDetailOrderBySql(List sortList) { + List orders = new ArrayList<>(); + if (CollUtil.isNotEmpty(sortList)) { + for (DataSourceRequest.SortDescriptor sort : sortList) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapBaseMsstbprptColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + orders.add(column + ("desc".equalsIgnoreCase(sort.getDir()) ? " DESC" : " ASC")); + } + } + if (orders.isEmpty()) { + orders.add("NVL(t.orderIndex, 999999) ASC"); + orders.add("t.stnm ASC"); + } + return " ORDER BY " + String.join(", ", orders); + } + + private String buildBaseMsstbprptGroupOrderBySql(List groups) { + List orders = new ArrayList<>(); + if (CollUtil.isNotEmpty(groups)) { + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapBaseMsstbprptColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + orders.add(column + ("desc".equalsIgnoreCase(descriptor.getDir()) ? " DESC" : " ASC")); + } + } + return orders.isEmpty() ? "" : " ORDER BY " + String.join(", ", orders); + } + private String buildVmsstbprptFilterCondition(DataSourceRequest.FilterDescriptor filter, Map paramMap, int[] indexHolder) { @@ -4200,6 +4457,10 @@ public class EngEqDataServiceImpl implements EngEqDataService { return "tm".equalsIgnoreCase(field); } + private boolean isBaseMsstbprptDateField(String field) { + return "tm".equalsIgnoreCase(field) || "dtinTm".equalsIgnoreCase(field); + } + private boolean isEqDayDateField(String field) { return "dt".equalsIgnoreCase(field) || "tm".equalsIgnoreCase(field); } @@ -4783,6 +5044,36 @@ public class EngEqDataServiceImpl implements EngEqDataService { }; } + private String mapBaseMsstbprptColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd" -> "t.stcd"; + case "stnm" -> "t.stnm"; + case "sttp", "sttpCode" -> "t.sttpCode"; + case "sttpName" -> "t.sttpName"; + case "rstcd" -> "t.rstcd"; + case "rstcdName" -> "t.rstcdName"; + case "baseId" -> "t.baseId"; + case "baseName" -> "t.baseName"; + case "hbrvcd" -> "t.hbrvcd"; + case "hbrvcdName" -> "t.hbrvcdName"; + case "stlc" -> "t.stlc"; + case "lgtd" -> "t.lgtd"; + case "lttd" -> "t.lttd"; + case "elev" -> "t.elev"; + case "bldsttCode" -> "t.bldsttCode"; + case "bldsttCodeName" -> "t.bldsttCodeName"; + case "dtin" -> "t.dtin"; + case "dtinName" -> "t.dtinName"; + case "dtinTm" -> "t.dtinTm"; + case "tm" -> "t.tm"; + case "orderIndex" -> "NVL(t.orderIndex, 999999)"; + default -> null; + }; + } + private String mapWbsbColumn(String field) { if (StrUtil.isBlank(field)) { return null; From c44c8d2229670d623a6719da1ea6ae015dc26424 Mon Sep 17 00:00:00 2001 From: tangwei Date: Thu, 18 Jun 2026 14:43:05 +0800 Subject: [PATCH 03/38] =?UTF-8?q?feat:=20=E7=94=9F=E6=80=81=E6=B5=81?= =?UTF-8?q?=E9=87=8F=E6=B3=84=E6=94=BE=E8=AE=BE=E6=96=BD=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eq/controller/EngEqDataController.java | 8 + .../eq/entity/vo/EngEqBaseVmsstbprptVo.java | 61 +++ .../qgc_eng/eq/service/EngEqDataService.java | 3 + .../eq/service/impl/EngEqDataServiceImpl.java | 370 +++++++++++++++++- 4 files changed, 434 insertions(+), 8 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseVmsstbprptVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java index abff7d48..66190642 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java @@ -5,6 +5,7 @@ import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseMsstbprptVo; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseVmsstbprptVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDrtpDataVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqIntervalVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqLimitQueryVo; @@ -81,6 +82,13 @@ public class EngEqDataController { return ResponseResult.successData(result); } + @PostMapping("/base/vmsstbprpt/GetKendoList") + @Operation(summary = "生态流量泄放设施统计查询") + public ResponseResult getBaseVmsstbprptList(@RequestBody DataSourceRequest dataSourceRequest) { + DataSourceResult result = engEqDataService.getBaseVmsstbprptList(dataSourceRequest); + return ResponseResult.successData(result); + } + @PostMapping("/interval/qgc/hour/GetKendoListCust") @Operation(summary = "生态流量达标率小时统计(二级页面)") public ResponseResult getQgcHourKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseVmsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseVmsstbprptVo.java new file mode 100644 index 00000000..4b14d507 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseVmsstbprptVo.java @@ -0,0 +1,61 @@ +package com.yfd.platform.qgc_eng.eq.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +@Schema(description = "生态流量泄放设施统计查询") +public class EngEqBaseVmsstbprptVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "设施类型编码") + private String sttpCode; + + @Schema(description = "设施类型名称") + private String sttpName; + + @Schema(description = "设施编码") + private String stcd; + + @Schema(description = "设施名称") + private String stnm; + + @Schema(description = "所属电站编码") + private String rstcd; + + @Schema(description = "所属电站名称") + private String rstcdName; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "基地名称") + private String baseName; + + @Schema(description = "基地流域编码") + private String hbrvcd; + + @Schema(description = "基地流域名称") + private String hbrvcdName; + + @Schema(description = "数据接入状态") + private Integer dtin; + + @Schema(description = "建设状态分类") + private Integer bldsttCode; + + @Schema(description = "基地排序") + private Integer baseStepSort; + + @Schema(description = "流域排序") + private Integer rvcdStepSort; + + @Schema(description = "所属电站排序") + private Integer rstcdStepSort; + + @Schema(description = "设施排序") + private Integer siteStepSort; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java index e1541b32..7f0a0bf8 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java @@ -3,6 +3,7 @@ package com.yfd.platform.qgc_eng.eq.service; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseMsstbprptVo; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseVmsstbprptVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDayDataVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDrtpDataVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDayIntervalVo; @@ -35,6 +36,8 @@ public interface EngEqDataService { DataSourceResult getBaseMsstbprptList(DataSourceRequest dataSourceRequest); + DataSourceResult getBaseVmsstbprptList(DataSourceRequest dataSourceRequest); + DataSourceResult getQgcHourKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getQgcDayKendoListCust(DataSourceRequest dataSourceRequest); diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java index bb83777e..701cec27 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java @@ -13,6 +13,7 @@ import com.yfd.platform.common.MicroservicDynamicSQLMapper; import com.yfd.platform.common.enums.QecIntervalEnum; import com.yfd.platform.common.enums.ShowEnum; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseMsstbprptVo; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseVmsstbprptVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDataVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDayDataVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDrtpDataVo; @@ -112,6 +113,15 @@ public class EngEqDataServiceImpl implements EngEqDataService { return queryBaseMsstbprptGroupList(dataSourceRequest, loadOptions); } + @Override + public DataSourceResult getBaseVmsstbprptList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + if (CollUtil.isEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + return queryBaseVmsstbprptDetailList(dataSourceRequest, loadOptions); + } + return queryBaseVmsstbprptGroupList(dataSourceRequest, loadOptions); + } + private DataSourceResult queryBaseMsstbprptDetailList(DataSourceRequest dataSourceRequest, DataSourceLoadOptionsBase loadOptions) { StringBuilder sql = new StringBuilder(); @@ -202,6 +212,9 @@ public class EngEqDataServiceImpl implements EngEqDataService { } else { result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); } + if (CollUtil.isNotEmpty((List) result.getData()) && ((List) result.getData()).get(0) instanceof Group) { + populateBaseMsstbprptGroupKeyNames((List) (List) result.getData()); + } result.setTotal((long) rows.size()); result.setAggregates(new HashMap<>()); return result; @@ -212,14 +225,7 @@ public class EngEqDataServiceImpl implements EngEqDataService { "eq.STCD AS stcd, " + "eq.STNM AS stnm, " + "eq.STTP AS sttpCode, " + - "CASE eq.STTP " + - " WHEN 'EQ_1' THEN '生态放流孔' " + - " WHEN 'EQ_2' THEN '生态放流闸' " + - " WHEN 'EQ_3' THEN '生态放流洞' " + - " WHEN 'EQ_4' THEN '生态放流管' " + - " WHEN 'EQ_5' THEN '基荷发电' " + - " WHEN 'EQ_6' THEN '生态机组' " + - " ELSE eq.STTP END AS sttpName, " + + "NVL(sttp.STTP_NAME, eq.STTP) AS sttpName, " + "eq.RSTCD AS rstcd, " + "eng.ENNM AS rstcdName, " + "eq.BASE_ID AS baseId, " + @@ -238,6 +244,8 @@ public class EngEqDataServiceImpl implements EngEqDataService { "eq.TM AS tm, " + "eq.ORDER_INDEX AS orderIndex " + "FROM SD_EQ_B_H eq " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = eq.STTP " + + " AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 " + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = eq.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eq.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eq.HBRVCD AND hbrv.BASEID = eq.BASE_ID " + @@ -291,6 +299,170 @@ public class EngEqDataServiceImpl implements EngEqDataService { return columns; } + private DataSourceResult queryBaseVmsstbprptDetailList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildBaseVmsstbprptDetailSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildBaseVmsstbprptViewSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = buildBaseVmsstbprptFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildBaseVmsstbprptDetailOrderBySql(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, EngEqBaseVmsstbprptVo.class); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private DataSourceResult queryBaseVmsstbprptGroupList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + List groups = dataSourceRequest.getGroup(); + GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup(); + List selectItems = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapBaseVmsstbprptColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + selectItems.add(column + " AS " + descriptor.getField().toUpperCase()); + selectItems.add("COUNT(*) AS COUNT_" + descriptor.getField().toUpperCase()); + if (CollUtil.isNotEmpty(descriptor.getAggregates())) { + for (DataSourceRequest.AggregateDescriptor aggregate : descriptor.getAggregates()) { + String aggregateColumn = mapBaseVmsstbprptColumn(aggregate.getField()); + if (StrUtil.isBlank(aggregateColumn) || StrUtil.isBlank(aggregate.getAggregate())) { + continue; + } + selectItems.add(buildAggregateSql(aggregate.getAggregate(), aggregateColumn, aggregate.getField())); + } + } + } + if (selectItems.isEmpty()) { + selectItems.add("t.STCD AS STCD"); + selectItems.add("COUNT(*) AS COUNT_STCD"); + } + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(String.join(", ", selectItems)) + .append(" FROM (") + .append(buildBaseVmsstbprptViewSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = buildBaseVmsstbprptFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + + List groupByColumns = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapBaseVmsstbprptColumn(descriptor.getField()); + if (StrUtil.isNotBlank(column)) { + groupByColumns.add(column); + } + } + if (!groupByColumns.isEmpty()) { + sql.append(" GROUP BY ").append(String.join(", ", groupByColumns)).append(" "); + } + sql.append(buildBaseVmsstbprptGroupOrderBySql(groups)); + + List> rows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap); + DataSourceResult result = new DataSourceResult<>(); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal((long) rows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private String buildBaseVmsstbprptViewSql() { + return "SELECT " + + "eq.STTP AS sttpCode, " + + "NVL(sttp.STTP_NAME, eq.STTP) AS sttpName, " + + "eq.STCD AS stcd, " + + "eq.STNM AS stnm, " + + "eq.RSTCD AS rstcd, " + + "eng.ENNM AS rstcdName, " + + "eq.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName, " + + "eq.HBRVCD AS hbrvcd, " + + "hbrv.HBRVNM AS hbrvcdName, " + + "eq.DTIN AS dtin, " + + "eq.BLDSTT_CODE AS bldsttCode, " + + "NVL(hb.ORDER_INDEX, 999999) AS baseStepSort, " + + "NVL(along.ORDER_INDEX, 999999) AS rvcdStepSort, " + + "NVL(eng.ORDER_INDEX, 999999) AS rstcdStepSort, " + + "NVL(eq.ORDER_INDEX, 999999) AS siteStepSort " + + "FROM SD_EQ_B_H eq " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = eq.STTP " + + " AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLED, 1) = 1 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = eq.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eq.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eq.HBRVCD AND hbrv.BASEID = eq.BASE_ID " + + " AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 " + + "LEFT JOIN MS_ALONG_B along ON along.RVCD = eq.HBRVCD AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 " + + "WHERE NVL(eq.IS_DELETED, 0) = 0"; + } + + private String buildBaseVmsstbprptDetailSelectSql(List selectFields) { + Map columns = baseVmsstbprptFieldColumns(); + List selected = new ArrayList<>(); + if (CollUtil.isEmpty(selectFields)) { + selected.addAll(columns.values()); + } else { + for (String field : selectFields) { + String column = columns.get(field); + if (StrUtil.isNotBlank(column)) { + selected.add(column); + } + } + if (selected.isEmpty()) { + selected.addAll(columns.values()); + } + } + return String.join(", ", selected); + } + + private Map baseVmsstbprptFieldColumns() { + Map columns = new LinkedHashMap<>(); + columns.put("sttpCode", "t.sttpCode AS sttpCode"); + columns.put("sttpName", "t.sttpName AS sttpName"); + columns.put("stcd", "t.stcd AS stcd"); + columns.put("stnm", "t.stnm AS stnm"); + columns.put("rstcd", "t.rstcd AS rstcd"); + columns.put("rstcdName", "t.rstcdName AS rstcdName"); + columns.put("baseId", "t.baseId AS baseId"); + columns.put("baseName", "t.baseName AS baseName"); + columns.put("hbrvcd", "t.hbrvcd AS hbrvcd"); + columns.put("hbrvcdName", "t.hbrvcdName AS hbrvcdName"); + columns.put("dtin", "t.dtin AS dtin"); + columns.put("bldsttCode", "t.bldsttCode AS bldsttCode"); + columns.put("baseStepSort", "t.baseStepSort AS baseStepSort"); + columns.put("rvcdStepSort", "t.rvcdStepSort AS rvcdStepSort"); + columns.put("rstcdStepSort", "t.rstcdStepSort AS rstcdStepSort"); + columns.put("siteStepSort", "t.siteStepSort AS siteStepSort"); + return columns; + } + private DataSourceResult queryMsstbprptDetailList(DataSourceRequest dataSourceRequest, DataSourceLoadOptionsBase loadOptions) { StringBuilder sql = new StringBuilder(); @@ -1217,6 +1389,58 @@ public class EngEqDataServiceImpl implements EngEqDataService { populateHourDayGroupKeyNames(groups, baseNameCache, hbrvNameCache); } + private void populateBaseMsstbprptGroupKeyNames(List groups) { + if (CollUtil.isEmpty(groups)) { + return; + } + Map sttpNameCache = new HashMap<>(); + Map baseNameCache = new HashMap<>(); + Map hbrvNameCache = new HashMap<>(); + populateBaseMsstbprptGroupKeyNames(groups, sttpNameCache, baseNameCache, hbrvNameCache); + } + + private void populateBaseMsstbprptGroupKeyNames(List groups, + Map sttpNameCache, + Map baseNameCache, + Map hbrvNameCache) { + for (Group group : groups) { + if (group == null) { + continue; + } + if (StrUtil.isBlank(group.getKeyName())) { + group.setKeyName(resolveBaseMsstbprptGroupKeyName(group.getField(), group.getKey(), + sttpNameCache, baseNameCache, hbrvNameCache)); + } + if (CollUtil.isNotEmpty(group.getItems()) && group.getItems().get(0) instanceof Group) { + populateBaseMsstbprptGroupKeyNames((List) group.getItems(), sttpNameCache, baseNameCache, hbrvNameCache); + } + } + } + + private String resolveBaseMsstbprptGroupKeyName(Object field, + Object key, + Map sttpNameCache, + Map baseNameCache, + Map hbrvNameCache) { + if (field == null || key == null) { + return null; + } + String fieldName = String.valueOf(field); + String keyValue = String.valueOf(key); + if (StrUtil.isBlank(keyValue)) { + return null; + } + return switch (fieldName) { + case "sttpName", "stnm", "rstcdName", "baseName", "hbrvcdName", "bldsttCodeName", "dtinName" -> keyValue; + case "sttp", "sttpCode" -> StrUtil.blankToDefault(resolveSttpName(keyValue, sttpNameCache), keyValue); + case "baseId" -> StrUtil.blankToDefault(resolveBaseName(keyValue, baseNameCache), keyValue); + case "hbrvcd" -> StrUtil.blankToDefault(resolveHbrvName(keyValue, hbrvNameCache), keyValue); + case "dtin" -> resolveDtinName(keyValue); + case "bldsttCode" -> resolveBldsttName(keyValue); + default -> keyValue; + }; + } + private void populateHourDayGroupKeyNames(List groups, Map baseNameCache, Map hbrvNameCache) { @@ -1307,6 +1531,38 @@ public class EngEqDataServiceImpl implements EngEqDataService { return name == null ? null : String.valueOf(name); } + private String resolveSttpName(String sttpCode, Map cache) { + if (StrUtil.isBlank(sttpCode)) { + return null; + } + if (cache.containsKey(sttpCode)) { + return cache.get(sttpCode); + } + Map paramMap = new HashMap<>(); + paramMap.put("code", sttpCode); + List> rows = microservicDynamicSQLMapper.pageAllList(null, + "SELECT sttp.STTP_NAME AS name FROM SD_STTP_B sttp " + + "WHERE sttp.STTP_CODE = #{map.code} " + + "AND NVL(sttp.IS_DELETED, 0) = 0 " + + "AND NVL(sttp.ENABLE, 1) = 1 " + + "AND ROWNUM = 1", + paramMap); + String name = extractName(rows); + if (StrUtil.isBlank(name)) { + name = switch (sttpCode) { + case "EQ_1" -> "生态放流孔"; + case "EQ_2" -> "生态放流闸"; + case "EQ_3" -> "生态放流洞"; + case "EQ_4" -> "生态放流管"; + case "EQ_5" -> "基荷发电"; + case "EQ_6" -> "生态机组"; + default -> null; + }; + } + cache.put(sttpCode, name); + return name; + } + private String resolveDtinName(String keyValue) { return switch (keyValue) { case "1" -> "是"; @@ -2827,6 +3083,79 @@ public class EngEqDataServiceImpl implements EngEqDataService { return result; } + private String buildBaseVmsstbprptFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + String column = mapBaseVmsstbprptColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + return buildGenericCondition(column, filter, paramMap, indexHolder, false); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildBaseVmsstbprptFilterCondition(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 buildBaseVmsstbprptDetailOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY NVL(t.baseStepSort, 999999) ASC, NVL(t.rvcdStepSort, 999999) ASC, " + + "NVL(t.rstcdStepSort, 999999) ASC, NVL(t.siteStepSort, 999999) ASC, t.stcd ASC"; + } + List orders = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sortList) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapBaseVmsstbprptColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sort.getDir()) || "des".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orders.add(column + " " + dir); + } + if (orders.isEmpty()) { + return " ORDER BY NVL(t.baseStepSort, 999999) ASC, NVL(t.rvcdStepSort, 999999) ASC, " + + "NVL(t.rstcdStepSort, 999999) ASC, NVL(t.siteStepSort, 999999) ASC, t.stcd ASC"; + } + return " ORDER BY " + String.join(", ", orders); + } + + private String buildBaseVmsstbprptGroupOrderBySql(List groups) { + if (CollUtil.isEmpty(groups)) { + return ""; + } + List orders = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapBaseVmsstbprptColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(descriptor.getDir()) || "des".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC"; + orders.add(column + " " + dir); + } + return orders.isEmpty() ? "" : " ORDER BY " + String.join(", ", orders); + } + private DataSourceResult queryWbsbDetailList(DataSourceRequest dataSourceRequest, DataSourceLoadOptionsBase loadOptions) { StringBuilder sql = new StringBuilder(); @@ -5074,6 +5403,31 @@ public class EngEqDataServiceImpl implements EngEqDataService { }; } + private String mapBaseVmsstbprptColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "sttpCode" -> "t.sttpCode"; + case "sttpName" -> "t.sttpName"; + case "stcd" -> "t.stcd"; + case "stnm" -> "t.stnm"; + case "rstcd" -> "t.rstcd"; + case "rstcdName" -> "t.rstcdName"; + case "baseId" -> "t.baseId"; + case "baseName" -> "t.baseName"; + case "hbrvcd" -> "t.hbrvcd"; + case "hbrvcdName" -> "t.hbrvcdName"; + case "dtin" -> "t.dtin"; + case "bldsttCode" -> "t.bldsttCode"; + case "baseStepSort" -> "NVL(t.baseStepSort, 999999)"; + case "rvcdStepSort" -> "NVL(t.rvcdStepSort, 999999)"; + case "rstcdStepSort" -> "NVL(t.rstcdStepSort, 999999)"; + case "siteStepSort" -> "NVL(t.siteStepSort, 999999)"; + default -> null; + }; + } + private String mapWbsbColumn(String field) { if (StrUtil.isBlank(field)) { return null; From 675d6a19273de780be3a493d9e481f57b6b28e30 Mon Sep 17 00:00:00 2001 From: tangwei Date: Thu, 18 Jun 2026 15:45:35 +0800 Subject: [PATCH 04/38] =?UTF-8?q?feat:=20=E7=94=9F=E6=80=81=E6=B5=81?= =?UTF-8?q?=E9=87=8F=E6=B3=84=E6=94=BE=E8=AE=BE=E6=96=BD=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eq/entity/vo/EngEqBaseVmsstbprptVo.java | 36 +----- .../eq/service/impl/EngEqDataServiceImpl.java | 112 +++++++++++++++++- 2 files changed, 112 insertions(+), 36 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseVmsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseVmsstbprptVo.java index 4b14d507..84f485a0 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseVmsstbprptVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseVmsstbprptVo.java @@ -2,51 +2,21 @@ package com.yfd.platform.qgc_eng.eq.entity.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; - -import java.io.Serializable; +import lombok.EqualsAndHashCode; @Data +@EqualsAndHashCode(callSuper = true) @Schema(description = "生态流量泄放设施统计查询") -public class EngEqBaseVmsstbprptVo implements Serializable { +public class EngEqBaseVmsstbprptVo extends EngEqMsstbprptVo { private static final long serialVersionUID = 1L; - @Schema(description = "设施类型编码") - private String sttpCode; - - @Schema(description = "设施类型名称") - private String sttpName; - - @Schema(description = "设施编码") - private String stcd; - - @Schema(description = "设施名称") - private String stnm; - @Schema(description = "所属电站编码") private String rstcd; @Schema(description = "所属电站名称") private String rstcdName; - @Schema(description = "基地编码") - private String baseId; - - @Schema(description = "基地名称") - private String baseName; - - @Schema(description = "基地流域编码") - private String hbrvcd; - - @Schema(description = "基地流域名称") - private String hbrvcdName; - - @Schema(description = "数据接入状态") - private Integer dtin; - - @Schema(description = "建设状态分类") - private Integer bldsttCode; - @Schema(description = "基地排序") private Integer baseStepSort; diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java index 701cec27..cc8cff1f 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java @@ -317,6 +317,7 @@ public class EngEqDataServiceImpl implements EngEqDataService { Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); List list = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, EngEqBaseVmsstbprptVo.class); + fillBaseVmsstbprptDetailFields(list); DataSourceResult result = new DataSourceResult<>(); result.setData(list); result.setTotal(page != null ? page.getTotal() : list.size()); @@ -396,29 +397,68 @@ public class EngEqDataServiceImpl implements EngEqDataService { private String buildBaseVmsstbprptViewSql() { return "SELECT " + + "eq.STCD AS id, " + + "eq.RECORD_USER AS recordUser, " + + "eq.RECORD_TIME AS recordTime, " + + "eq.MODIFY_TIME AS modifyTime, " + "eq.STTP AS sttpCode, " + "NVL(sttp.STTP_NAME, eq.STTP) AS sttpName, " + + "sttp.ID AS sttp, " + + "sttp.FULL_PATH AS sttpFullPath, " + + "sttp.TREE_LEVEL AS sttpTreeLevel, " + "eq.STCD AS stcd, " + "eq.STNM AS stnm, " + + "eng.ENNM AS ennm, " + "eq.RSTCD AS rstcd, " + "eng.ENNM AS rstcdName, " + "eq.BASE_ID AS baseId, " + "hb.BASENAME AS baseName, " + "eq.HBRVCD AS hbrvcd, " + "hbrv.HBRVNM AS hbrvcdName, " + + "eng.RVCD AS rvcd, " + + "rv.RVNM AS rvcdName, " + + "eng.ADDVCD AS addvcd, " + + "addv.ADDVNM AS addvcdName, " + + "eng.COUNTRY AS country, " + + "eng.COUNTRY_NAME AS countryName, " + + "eng.HYCD AS hycd, " + + "eng.HYNM AS hynm, " + + "eng.TOP_HYCD AS topHycd, " + + "eng.TOP_HYNM AS topHynm, " + + "eq.BLPRD AS blprd, " + + "eq.LGTD AS lgtd, " + + "eq.LTTD AS lttd, " + + "eq.ELEV AS elev, " + + "eq.ELEV AS dtmel, " + + "eq.STLC AS stlc, " + + "eq.USFL AS usfl, " + "eq.DTIN AS dtin, " + - "eq.BLDSTT_CODE AS bldsttCode, " + + "CASE NVL(eq.DTIN, 0) WHEN 1 THEN '已接入' WHEN 0 THEN '未接入' ELSE NULL END AS dtinName, " + + "eq.DTIN_TM AS dtinTm, " + + "eq.INTRODUCE AS introduce, " + + "eq.LOGO AS logo, " + + "eq.INFFILE AS inffile, " + + "eng.PRSC AS prsc, " + + "eng.RUN_STATE AS runState, " + + "eng.BLDSTT AS bldstt, " + + "eng.BLDSTT_CODE AS bldsttCode, " + + "TO_CHAR(eng.BLDSTT_CODE) AS bldsttCcode, " + + "CASE NVL(eng.BLDSTT_CODE, -1) WHEN 0 THEN '未建/规划' WHEN 1 THEN '在建' WHEN 2 THEN '已建' ELSE NULL END AS bldsttCcodeName, " + "NVL(hb.ORDER_INDEX, 999999) AS baseStepSort, " + "NVL(along.ORDER_INDEX, 999999) AS rvcdStepSort, " + "NVL(eng.ORDER_INDEX, 999999) AS rstcdStepSort, " + - "NVL(eq.ORDER_INDEX, 999999) AS siteStepSort " + + "NVL(eq.ORDER_INDEX, 999999) AS siteStepSort, " + + "eq.ORDER_INDEX AS orderIndex, " + + "eq.TM AS tm " + "FROM SD_EQ_B_H eq " + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = eq.STTP " + - " AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLED, 1) = 1 " + + " AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 " + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = eq.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eq.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eq.HBRVCD AND hbrv.BASEID = eq.BASE_ID " + " AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 " + + "LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = eng.RVCD " + + "LEFT JOIN SD_ADDVCD_DIC addv ON addv.ADDVCD = eng.ADDVCD " + "LEFT JOIN MS_ALONG_B along ON along.RVCD = eq.HBRVCD AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 " + "WHERE NVL(eq.IS_DELETED, 0) = 0"; } @@ -444,17 +484,54 @@ public class EngEqDataServiceImpl implements EngEqDataService { private Map baseVmsstbprptFieldColumns() { Map columns = new LinkedHashMap<>(); + columns.put("id", "t.id AS id"); + columns.put("recordUser", "t.recordUser AS recordUser"); + columns.put("recordTime", "t.recordTime AS recordTime"); + columns.put("modifyTime", "t.modifyTime AS modifyTime"); + columns.put("sttp", "t.sttp AS sttp"); columns.put("sttpCode", "t.sttpCode AS sttpCode"); columns.put("sttpName", "t.sttpName AS sttpName"); + columns.put("sttpFullPath", "t.sttpFullPath AS sttpFullPath"); + columns.put("sttpTreeLevel", "t.sttpTreeLevel AS sttpTreeLevel"); columns.put("stcd", "t.stcd AS stcd"); columns.put("stnm", "t.stnm AS stnm"); + columns.put("ennm", "t.ennm AS ennm"); columns.put("rstcd", "t.rstcd AS rstcd"); columns.put("rstcdName", "t.rstcdName AS rstcdName"); columns.put("baseId", "t.baseId AS baseId"); columns.put("baseName", "t.baseName AS baseName"); columns.put("hbrvcd", "t.hbrvcd AS hbrvcd"); columns.put("hbrvcdName", "t.hbrvcdName AS hbrvcdName"); + columns.put("rvcd", "t.rvcd AS rvcd"); + columns.put("rvcdName", "t.rvcdName AS rvcdName"); + columns.put("addvcd", "t.addvcd AS addvcd"); + columns.put("addvcdName", "t.addvcdName AS addvcdName"); + columns.put("country", "t.country AS country"); + columns.put("countryName", "t.countryName AS countryName"); + columns.put("hycd", "t.hycd AS hycd"); + columns.put("hynm", "t.hynm AS hynm"); + columns.put("topHycd", "t.topHycd AS topHycd"); + columns.put("topHynm", "t.topHynm AS topHynm"); + columns.put("blprd", "t.blprd AS blprd"); + columns.put("lgtd", "t.lgtd AS lgtd"); + columns.put("lttd", "t.lttd AS lttd"); + columns.put("elev", "t.elev AS elev"); + columns.put("dtmel", "t.dtmel AS dtmel"); + columns.put("stlc", "t.stlc AS stlc"); + columns.put("usfl", "t.usfl AS usfl"); columns.put("dtin", "t.dtin AS dtin"); + columns.put("dtinName", "t.dtinName AS dtinName"); + columns.put("dtinTm", "t.dtinTm AS dtinTm"); + columns.put("introduce", "t.introduce AS introduce"); + columns.put("logo", "t.logo AS logo"); + columns.put("inffile", "t.inffile AS inffile"); + columns.put("prsc", "t.prsc AS prsc"); + columns.put("runState", "t.runState AS runState"); + columns.put("bldstt", "t.bldstt AS bldstt"); + columns.put("bldsttCcode", "t.bldsttCcode AS bldsttCcode"); + columns.put("bldsttCcodeName", "t.bldsttCcodeName AS bldsttCcodeName"); + columns.put("orderIndex", "t.orderIndex AS orderIndex"); + columns.put("tm", "t.tm AS tm"); columns.put("bldsttCode", "t.bldsttCode AS bldsttCode"); columns.put("baseStepSort", "t.baseStepSort AS baseStepSort"); columns.put("rvcdStepSort", "t.rvcdStepSort AS rvcdStepSort"); @@ -463,6 +540,27 @@ public class EngEqDataServiceImpl implements EngEqDataService { return columns; } + private void fillBaseVmsstbprptDetailFields(List list) { + if (CollUtil.isEmpty(list)) { + return; + } + Map sttpNameCache = new HashMap<>(); + for (EngEqBaseVmsstbprptVo item : list) { + if (item == null) { + continue; + } + if (StrUtil.isBlank(item.getSttpName())) { + item.setSttpName(resolveSttpName(item.getSttpCode(), sttpNameCache)); + } + if (StrUtil.isBlank(item.getDtinName()) && item.getDtin() != null) { + item.setDtinName(resolveEqDtinName(String.valueOf(item.getDtin()))); + } + if (StrUtil.isBlank(item.getBldsttCcodeName()) && StrUtil.isNotBlank(item.getBldsttCcode())) { + item.setBldsttCcodeName(resolveBldsttName(item.getBldsttCcode())); + } + } + } + private DataSourceResult queryMsstbprptDetailList(DataSourceRequest dataSourceRequest, DataSourceLoadOptionsBase loadOptions) { StringBuilder sql = new StringBuilder(); @@ -1571,6 +1669,14 @@ public class EngEqDataServiceImpl implements EngEqDataService { }; } + private String resolveEqDtinName(String keyValue) { + return switch (keyValue) { + case "1" -> "已接入"; + case "0" -> "未接入"; + default -> keyValue; + }; + } + private String resolveDtinEnvName(String keyValue) { return switch (keyValue) { case "2" -> "已全部接入"; From 970de330168fb4c3e2f74ab82f3aa650a2b1fdd0 Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 22 Jun 2026 10:33:08 +0800 Subject: [PATCH 05/38] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qgc_env/fpr/entity/vo/FprZyFishDicVo.java | 1 + .../service/impl/FprMonitorServiceImpl.java | 237 ++++++++++++------ 2 files changed, 158 insertions(+), 80 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/entity/vo/FprZyFishDicVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/entity/vo/FprZyFishDicVo.java index 2fb1bf67..7dad88bf 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/entity/vo/FprZyFishDicVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/entity/vo/FprZyFishDicVo.java @@ -45,4 +45,5 @@ public class FprZyFishDicVo { private String spawnMonth; private String orders; private String vlsr; + private java.util.Date vlsrTm; } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java index ab2cfaca..a1503c2e 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java @@ -250,87 +250,33 @@ public class FprMonitorServiceImpl implements FprMonitorService { new int[]{0} ); + String baseSql = StrUtil.isBlank(rvcd) ? buildZyFishDicSummarySql() : buildZyFishDicBaseSql(); StringBuilder sql = new StringBuilder("SELECT * FROM (") - .append(buildZyFishDicBaseSql()) + .append(baseSql) .append(") t WHERE 1 = 1 "); if (StrUtil.isNotBlank(filterSql)) { sql.append(" AND ").append(filterSql).append(" "); } - // 增加排序 - if(dataSourceRequest.getSort() !=null && !dataSourceRequest.getSort().isEmpty()){ - List sortDescriptors = dataSourceRequest.getSort(); - StringBuilder orderSql = new StringBuilder(); - orderSql.append(" order by "); - for (DataSourceRequest.SortDescriptor sort:sortDescriptors){ - orderSql.append(sort.getField()).append(" ").append(sort.getDir()).append(","); - } - sql.append(orderSql, 0, orderSql.length()-1); -// String[] beans = SpringContextHolder.getApplicationContext().getBeanDefinitionNames(); - sql.append(" nulls last "); - }else{ - sql.append(" order by rvcd nulls last "); - } - List list = microservicDynamicSQLMapper.getAllListWithResultType( + sql.append(buildZyFishDicOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List resultList = microservicDynamicSQLMapper.pageAllListWithResultType( + page, sql.toString(), paramMap, FprZyFishDicVo.class ); - List> rvcdRows = microservicDynamicSQLMapper.getAllList( - "SELECT RVCD AS rvcd, RVNM AS rvcdName FROM SD_RVCD_DIC", - null - ); - Map rvcdNameMap = new HashMap<>(); - for (Map row : rvcdRows) { - Object rvcdKey = row.get("RVCD"); - Object rvcdName = row.get("RVCDNAME"); - if (rvcdKey != null && rvcdName != null) { - rvcdNameMap.put(String.valueOf(rvcdKey), String.valueOf(rvcdName)); - } - } - - List resultList; - Map> rvcdMap = new HashMap<>(); - if (StrUtil.isBlank(rvcd)) { - rvcdMap = list.stream() - .collect(Collectors.groupingBy( - item -> StrUtil.blankToDefault(item.getZyFishId(), item.getId()), - LinkedHashMap::new, - Collectors.mapping(FprZyFishDicVo::getRvcd, Collectors.toList()) - )); - LinkedHashMap distinctMap = new LinkedHashMap<>(); - for (FprZyFishDicVo item : list) { - distinctMap.putIfAbsent(StrUtil.blankToDefault(item.getZyFishId(), item.getId()), item); - } - resultList = new ArrayList<>(distinctMap.values()); - } else { - resultList = new ArrayList<>(list); - } + int startIndex = loadOptions == null || loadOptions.getSkip() == null ? 0 : Math.max(loadOptions.getSkip(), 0); + fillZyFishRvcdNames(resultList, rvcd); for (int i = 0; i < resultList.size(); i++) { FprZyFishDicVo item = resultList.get(i); - item.setIndex(i + 1); + item.setIndex(startIndex + i + 1); item.setSpawnMonth(formatSpawnMonth(item.getSpawnMonth())); - if (StrUtil.isBlank(rvcd)) { - List rvcdList = rvcdMap.getOrDefault( - StrUtil.blankToDefault(item.getZyFishId(), item.getId()), - new ArrayList<>() - ).stream().filter(StrUtil::isNotBlank).distinct().toList(); - List rvcdNames = new ArrayList<>(); - for (String rvcdItem : rvcdList) { - String rvcdName = rvcdNameMap.get(rvcdItem); - if (StrUtil.isNotBlank(rvcdName)) { - rvcdNames.add(rvcdName); - } - } - item.setRvcdName(String.join(",", rvcdNames)); - } else { - item.setRvcdName(rvcdNameMap.get(item.getRvcd())); - } } DataSourceResult result = new DataSourceResult<>(); - result.setTotal((long) resultList.size()); - result.setData(paginateZyFishDicList(resultList, loadOptions)); + result.setTotal(page != null ? page.getTotal() : resultList.size()); + result.setData(resultList); result.setAggregates(new HashMap<>()); return result; } @@ -739,6 +685,7 @@ public class FprMonitorServiceImpl implements FprMonitorService { "NVL(src.IS_DELETED, 0) AS isDeleted, " + "CASE WHEN rel.ZY_FISH_ID IS NULL THEN src.ID ELSE rel.ZY_FISH_ID END AS zyFishId, " + "CASE WHEN rel.RVCD IS NULL THEN 'null' ELSE rel.RVCD END AS rvcd, " + + "rv.RVNM AS rvcdName, " + "src.NAME AS name, " + "src.TYPE AS type, " + "src.FAMILY AS family, " + @@ -769,15 +716,137 @@ public class FprMonitorServiceImpl implements FprMonitorService { "src.LOGO AS logo, " + "src.INFFILE AS inffile, " + "src.ORDERS, \n" + - "src.VLSR, \n"+ + "src.VLSR AS vlsr, \n" + + "src.VLSR_TM AS vlsrTm, \n" + "src.SPAWN_MONTH AS spawnMonth " + "FROM SD_FISHDICTORY_B src " + "LEFT JOIN SD_FISHDICTORY_RLTN_B rel ON src.ID = rel.ZY_FISH_ID " + " AND rel.RVCD <> 'ZY' " + " AND NVL(rel.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = rel.RVCD " + "WHERE NVL(src.IS_DELETED, 0) = 0 "; } + private String buildZyFishDicSummarySql() { + return "SELECT " + + "src.ID AS id, " + + "NVL(src.IS_DELETED, 0) AS isDeleted, " + + "src.ID AS zyFishId, " + + "NVL((SELECT MIN(rel2.RVCD) " + + " FROM SD_FISHDICTORY_RLTN_B rel2 " + + " WHERE rel2.ZY_FISH_ID = src.ID " + + " AND rel2.RVCD <> 'ZY' " + + " AND NVL(rel2.IS_DELETED, 0) = 0), 'null') AS rvcd, " + + "CAST(NULL AS VARCHAR2(1000)) AS rvcdName, " + + "src.NAME AS name, " + + "src.TYPE AS type, " + + "src.FAMILY AS family, " + + "src.GENUS AS genus, " + + "src.SPECIES AS species, " + + "src.NAME_EN AS nameEn, " + + "src.ALIAS AS alias, " + + "src.FSZ AS fsz, " + + "src.SHAPEDESC AS shapedesc, " + + "src.HABITATION AS habitation, " + + "src.HABIT_MIGRAT AS habitMigrat, " + + "src.FEEDING_HABIT AS feedingHabit, " + + "src.FOOD AS food, " + + "src.TIME_FEED AS timeFeed, " + + "src.ORIGN_DATE AS orignDate, " + + "CAST(NULL AS VARCHAR2(255)) AS filterContent, " + + "src.PRETEMP AS pretemp, " + + "src.FLOW_RATE AS flowRate, " + + "src.DEPTH AS depth, " + + "src.WQTQ AS wqtq, " + + "src.SPAWN_CHARACT AS spawnCharact, " + + "src.BOTM_MATER AS botmMater, " + + "src.PTYPE AS ptype, " + + "CASE src.PTYPE WHEN 1 THEN '濒危' WHEN 2 THEN '极危' WHEN 3 THEN '近危' WHEN 4 THEN '易危' WHEN 5 THEN '重点保护' WHEN 6 THEN '无危' WHEN 7 THEN '国家二级' WHEN 8 THEN '市二级保护' ELSE '未知' END AS ptypeName, " + + "src.SPEC_ORIGIN AS specOrigin, " + + "CASE WHEN src.SPEC_ORIGIN = 1 THEN '本土物种' WHEN src.SPEC_ORIGIN = 2 THEN '外来物种' ELSE NULL END AS specOriginName, " + + "src.DESCRIPTION AS description, " + + "src.LOGO AS logo, " + + "src.INFFILE AS inffile, " + + "src.ORDERS, " + + "src.VLSR AS vlsr, " + + "src.VLSR_TM AS vlsrTm, " + + "src.SPAWN_MONTH AS spawnMonth " + + "FROM SD_FISHDICTORY_B src " + + "WHERE NVL(src.IS_DELETED, 0) = 0 "; + } + + private void fillZyFishRvcdNames(List list, String rvcdFilter) { + if (CollUtil.isEmpty(list)) { + return; + } + if (StrUtil.isNotBlank(rvcdFilter)) { + for (FprZyFishDicVo item : list) { + if (item != null && StrUtil.isBlank(item.getRvcdName()) && StrUtil.isNotBlank(item.getRvcd()) && !"null".equalsIgnoreCase(item.getRvcd())) { + item.setRvcdName(querySingleRvcdName(item.getRvcd())); + } + } + return; + } + List fishIds = list.stream() + .map(item -> StrUtil.blankToDefault(item.getZyFishId(), item.getId())) + .filter(StrUtil::isNotBlank) + .distinct() + .toList(); + if (CollUtil.isEmpty(fishIds)) { + return; + } + Map paramMap = new HashMap<>(); + List placeholders = new ArrayList<>(); + for (int i = 0; i < fishIds.size(); i++) { + String key = "zyFishId" + i; + paramMap.put(key, fishIds.get(i)); + placeholders.add("#{map." + key + "}"); + } + String sql = "SELECT rel.ZY_FISH_ID AS zyFishId, rv.RVNM AS rvcdName " + + "FROM SD_FISHDICTORY_RLTN_B rel " + + "LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = rel.RVCD " + + "WHERE rel.ZY_FISH_ID IN (" + String.join(", ", placeholders) + ") " + + "AND rel.RVCD <> 'ZY' " + + "AND NVL(rel.IS_DELETED, 0) = 0 " + + "AND rv.RVNM IS NOT NULL"; + List> rows = microservicDynamicSQLMapper.getAllList(sql, paramMap); + Map> rvcdNameMap = new HashMap<>(); + for (Map row : rows) { + Object fishId = row.get("ZYFISHID"); + Object rvcdName = row.get("RVCDNAME"); + if (fishId == null || rvcdName == null) { + continue; + } + rvcdNameMap.computeIfAbsent(String.valueOf(fishId), key -> new ArrayList<>()) + .add(String.valueOf(rvcdName)); + } + for (FprZyFishDicVo item : list) { + if (item == null) { + continue; + } + String fishKey = StrUtil.blankToDefault(item.getZyFishId(), item.getId()); + List names = rvcdNameMap.getOrDefault(fishKey, new ArrayList<>()).stream() + .filter(StrUtil::isNotBlank) + .distinct() + .toList(); + item.setRvcdName(String.join(",", names)); + } + } + + private String querySingleRvcdName(String rvcd) { + Map paramMap = new HashMap<>(); + paramMap.put("rvcd", rvcd); + List> rows = microservicDynamicSQLMapper.getAllList( + "SELECT RVNM AS rvcdName FROM SD_RVCD_DIC WHERE RVCD = #{map.rvcd} AND ROWNUM = 1", + paramMap + ); + if (CollUtil.isEmpty(rows)) { + return null; + } + Object value = rows.get(0).get("RVCDNAME"); + return value == null ? null : String.valueOf(value); + } + private String buildMsstbprptDetailSelectSql(List selectFields) { LinkedHashMap columnMap = buildMsstbprptSelectColumnMap(); if (CollUtil.isEmpty(selectFields)) { @@ -1384,6 +1453,7 @@ public class FprMonitorServiceImpl implements FprMonitorService { case "isDeleted" -> "t.isDeleted"; case "zyFishId" -> "t.zyFishId"; case "rvcd" -> "t.rvcd"; + case "rvcdName" -> "t.rvcdName"; case "name" -> "t.name"; case "type" -> "t.type"; case "family" -> "t.family"; @@ -1412,26 +1482,33 @@ public class FprMonitorServiceImpl implements FprMonitorService { case "logo" -> "t.logo"; case "inffile" -> "t.inffile"; case "spawnMonth" -> "t.spawnMonth"; + case "orders" -> "t.orders"; + case "vlsr" -> "t.vlsr"; + case "vlsrTm" -> "t.vlsrTm"; default -> null; }; } - private List paginateZyFishDicList(List resultList, DataSourceLoadOptionsBase loadOptions) { - if (CollUtil.isEmpty(resultList) || loadOptions == null || loadOptions.getTake() == null || loadOptions.getTake() <= 0) { - return resultList; + private String buildZyFishDicOrderBySql(List sorts) { + List orderItems = new ArrayList<>(); + if (CollUtil.isNotEmpty(sorts)) { + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapZyFishDicColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) || "des".equalsIgnoreCase(sort.getDir()) + ? "DESC" : "ASC"; + orderItems.add(column + " " + direction + " NULLS LAST"); + } } - int page = loadOptions.getSkip() == null ? 1 : loadOptions.getSkip(); // 页码从1开始,缺省为1 - // 如果页码 ≤ 0,强制设为1(避免负值) - if (page < 1) { - page = 1; + if (orderItems.isEmpty()) { + return " ORDER BY t.rvcd ASC NULLS LAST, t.name ASC"; } - int size = loadOptions.getTake(); - int start = (page - 1) * size; - int end = Math.min(start + size, resultList.size()); - if (start >= resultList.size()) { - return new ArrayList<>(); - } - return new ArrayList<>(resultList.subList(start, end)); + return " ORDER BY " + String.join(", ", orderItems); } private String formatSpawnMonth(String input) { From ed0e6ed372d5f7d8eef2c0fad4ed768d2be5a223 Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 22 Jun 2026 13:52:54 +0800 Subject: [PATCH 06/38] =?UTF-8?q?feat:=20=E6=B5=81=E5=9F=9F=E4=B8=8B?= =?UTF-8?q?=E6=8B=89=E6=A1=86=E5=88=97=E8=A1=A8=E6=9F=A5=E8=AF=A2&?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SdRvcdDicController.java | 9 ++++ .../qgc_base/mapper/SdRvcdDicMapper.java | 2 + .../qgc_base/service/ISdRvcdDicService.java | 2 + .../service/impl/SdRvcdDicServiceImpl.java | 6 +++ .../vd/service/impl/VdMonitorServiceImpl.java | 45 +++++++++++++++++-- .../mapper/qgc_base/SdRvcdDicMapper.xml | 25 +++++++++++ 6 files changed, 85 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdRvcdDicController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdRvcdDicController.java index 4ee42f4c..f49830ed 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdRvcdDicController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdRvcdDicController.java @@ -111,6 +111,15 @@ public class SdRvcdDicController { return ResponseResult.successData(rvcdDicService.selectForDropdown(rvnm, rvcd)); } + @GetMapping("/selectRvcdDropdown") + @Operation(summary = "流域下拉框列表查询") + public ResponseResult selectRvcdDropdown( + @RequestParam(required = false) String rvnm, + @RequestParam(required = false) String baseId + ) { + return ResponseResult.successData(rvcdDicService.selectRvcdDropdown(rvnm,baseId)); + } + @GetMapping("/regDropdown") @Operation(summary = "下拉框列表查询(注册)") public ResponseResult regDropdown( diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdRvcdDicMapper.java b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdRvcdDicMapper.java index 537d2e5f..f54fece4 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdRvcdDicMapper.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdRvcdDicMapper.java @@ -32,4 +32,6 @@ public interface SdRvcdDicMapper extends BaseMapper { * 注册场景下拉框查询,仅返回能被电站表 RVCD 命中的流域 */ List selectRegDropdownWithEng(@Param("rvnm") String rvnm, @Param("rvcd") String rvcd); + + List selectRvcdDropdown(@Param("rvnm") String rvnm,@Param("baseId") String baseId); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdRvcdDicService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdRvcdDicService.java index 8eee4131..027d4b5c 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdRvcdDicService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdRvcdDicService.java @@ -55,5 +55,7 @@ public interface ISdRvcdDicService extends IService { List selectForDropdown(String rvnm, String rvcd); + List selectRvcdDropdown(String rvnm,String baseId); + List regDropdown(String rvnm, String rvcd); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdRvcdDicServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdRvcdDicServiceImpl.java index ed0b961b..60446e27 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdRvcdDicServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdRvcdDicServiceImpl.java @@ -149,6 +149,12 @@ public class SdRvcdDicServiceImpl extends ServiceImpl selectRvcdDropdown(String rvnm,String baseId) { + List dropdownList = this.baseMapper.selectRvcdDropdown(rvnm,baseId); + return dropdownList; + } + @Override public Set getUserAuthorizedStationCodes() { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java index 3c4cc27f..b0d6d265 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java @@ -131,9 +131,30 @@ public class VdMonitorServiceImpl implements VdMonitorService { GroupingInfo[] groups, String filterSql, Map paramMap) { + List groupDescriptors = dataSourceRequest == null ? null : dataSourceRequest.getGroup(); + List selectItems = new ArrayList<>(); + if (CollUtil.isNotEmpty(groupDescriptors)) { + for (DataSourceRequest.GroupDescriptor descriptor : groupDescriptors) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + selectItems.add(column + " AS " + descriptor.getField()); + selectItems.add("COUNT(1) AS count_" + descriptor.getField()); + } + } + if (selectItems.isEmpty()) { + selectItems.add("t.sttpCode AS sttpCode"); + selectItems.add("COUNT(1) AS count_sttpCode"); + } + StringBuilder sql = new StringBuilder(); - sql.append("SELECT t.sttpCode AS sttpCode, COUNT(1) AS count_sttpCode ") - .append("FROM (") + sql.append("SELECT ") + .append(String.join(", ", selectItems)) + .append(" FROM (") .append(buildVmsstbprptViewSql()) .append(") t ") .append("WHERE 1 = 1 "); @@ -141,8 +162,24 @@ public class VdMonitorServiceImpl implements VdMonitorService { sql.append(" AND ").append(filterSql).append(" "); } - sql.append(" GROUP BY t.sttpCode "); - sql.append(buildOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getGroup())); + List groupByColumns = new ArrayList<>(); + if (CollUtil.isNotEmpty(groupDescriptors)) { + for (DataSourceRequest.GroupDescriptor descriptor : groupDescriptors) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapColumn(descriptor.getField()); + if (StrUtil.isNotBlank(column)) { + groupByColumns.add(column); + } + } + } + if (!groupByColumns.isEmpty()) { + sql.append(" GROUP BY ").append(String.join(", ", groupByColumns)); + } else { + sql.append(" GROUP BY t.sttpCode "); + } + sql.append(buildOrderBySql(groupDescriptors)); List> rows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap); DataSourceResult result = new DataSourceResult<>(); diff --git a/backend/src/main/resources/mapper/qgc_base/SdRvcdDicMapper.xml b/backend/src/main/resources/mapper/qgc_base/SdRvcdDicMapper.xml index 504dcc0b..3d40173f 100644 --- a/backend/src/main/resources/mapper/qgc_base/SdRvcdDicMapper.xml +++ b/backend/src/main/resources/mapper/qgc_base/SdRvcdDicMapper.xml @@ -212,5 +212,30 @@ ORDER BY t.ORDER_PATH ASC, t.RVCD ASC + From d6be29b0fa849bf2edb3a88660acee86332ecad5 Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 22 Jun 2026 14:16:06 +0800 Subject: [PATCH 07/38] =?UTF-8?q?feat:=20=E8=A7=86=E9=A2=91=E7=AB=99?= =?UTF-8?q?=E9=94=9A=E7=82=B9=E6=8E=A5=E5=8F=A3=E5=88=86=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../platform/qgc_env/vd/controller/VdMonitorController.java | 6 ++++++ .../yfd/platform/qgc_env/vd/service/VdMonitorService.java | 2 ++ .../qgc_env/vd/service/impl/VdMonitorServiceImpl.java | 5 +++++ 3 files changed, 13 insertions(+) diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/controller/VdMonitorController.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/controller/VdMonitorController.java index a341cb51..1e670bfe 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vd/controller/VdMonitorController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/controller/VdMonitorController.java @@ -47,6 +47,12 @@ public class VdMonitorController { return ResponseResult.successData(vdMonitorService.getKendoListCust(dataSourceRequest)); } + @PostMapping("/vdpoint/GetKendoListCust") + @Operation(summary = "视频站锚点接口") + public ResponseResult getVdPointKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(vdMonitorService.getVdPointKendoListCust(dataSourceRequest)); + } + @PostMapping("/runData/GetKendoListCust") @Operation(summary = "查询视频监控运行数据") public ResponseResult getRunDataKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java index 4fa8d933..e3ca7d7c 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java @@ -13,5 +13,7 @@ public interface VdMonitorService { DataSourceResult getKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getVdPointKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getRunDataKendoListCust(DataSourceRequest dataSourceRequest); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java index b0d6d265..e72e5249 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java @@ -118,6 +118,11 @@ public class VdMonitorServiceImpl implements VdMonitorService { return queryLatestRunDataGroupList(dataSourceRequest, loadOptions); } + @Override + public DataSourceResult getVdPointKendoListCust(DataSourceRequest dataSourceRequest) { + return getKendoListCust(dataSourceRequest); + } + @Override public DataSourceResult getRunDataKendoListCust(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); From 332bde605bba87420860cae19f2124ddb3cb4600 Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 22 Jun 2026 14:30:00 +0800 Subject: [PATCH 08/38] =?UTF-8?q?feat:=20=E8=A7=86=E9=A2=91=E7=AB=99?= =?UTF-8?q?=E9=94=9A=E7=82=B9=E6=8E=A5=E5=8F=A3=E8=AF=A6=E6=83=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qgc_env/vd/entity/vo/VdPointVo.java | 86 +++++++++++ .../qgc_env/vd/service/VdMonitorService.java | 2 +- .../vd/service/impl/VdMonitorServiceImpl.java | 135 +++++++++++++++++- 3 files changed, 220 insertions(+), 3 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdPointVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdPointVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdPointVo.java new file mode 100644 index 00000000..84f26352 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdPointVo.java @@ -0,0 +1,86 @@ +package com.yfd.platform.qgc_env.vd.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; + +@Data +@Schema(description = "视频站锚点信息") +public class VdPointVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "视频站子站类") + private String sttp; + + @Schema(description = "视频站编码") + private String stcd; + + @Schema(description = "经度") + private BigDecimal lgtd; + + @Schema(description = "纬度") + private BigDecimal lttd; + + @Schema(description = "高程") + private BigDecimal dtmel; + + @Schema(description = "锚点状态") + private String anchoPointState; + + @Schema(description = "站类地图标识") + private String sttpMap; + + @Schema(description = "标题") + private String titleName; + + @Schema(description = "默认距离") + private Integer distance; + + @Schema(description = "流域编码") + private String rvcd; + + @Schema(description = "行政区编码") + private String addvcd; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "所属电站编码") + private String rstcds; + + @Schema(description = "站类编码") + private String sttpCode; + + @Schema(description = "视频站名称") + private String stnm; + + @Schema(description = "流域名称") + private String rvnm; + + @Schema(description = "电站名称") + private String ennm; + + @Schema(description = "栖息地编码") + private String fhstcd; + + @Schema(description = "栖息地名称") + private String fhstnm; + + @Schema(description = "站类名称") + private String sttpName; + + @Schema(description = "站址") + private String stlc; + + @Schema(description = "播放方式") + private String playWay; + + @Schema(description = "站点排序") + private Integer siteStepSort; + + @Schema(description = "基地流域编码") + private String hbrvcd; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java index e3ca7d7c..3b21de15 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java @@ -13,7 +13,7 @@ public interface VdMonitorService { DataSourceResult getKendoListCust(DataSourceRequest dataSourceRequest); - DataSourceResult getVdPointKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getVdPointKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getRunDataKendoListCust(DataSourceRequest dataSourceRequest); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java index e72e5249..d1931ea5 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java @@ -9,6 +9,7 @@ import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.common.GroupHelper; import com.yfd.platform.common.GroupingInfo; import com.yfd.platform.common.MicroservicDynamicSQLMapper; +import com.yfd.platform.qgc_env.vd.entity.vo.VdPointVo; import com.yfd.platform.qgc_env.vd.entity.vo.VdRunDataVo; import com.yfd.platform.qgc_env.vd.entity.vo.VdVmsstbprptVo; import com.yfd.platform.qgc_env.vd.service.VdMonitorService; @@ -119,8 +120,12 @@ public class VdMonitorServiceImpl implements VdMonitorService { } @Override - public DataSourceResult getVdPointKendoListCust(DataSourceRequest dataSourceRequest) { - return getKendoListCust(dataSourceRequest); + public DataSourceResult getVdPointKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + if (CollUtil.isNotEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + return getKendoListCust(dataSourceRequest); + } + return queryVdPointDetailList(dataSourceRequest, loadOptions); } @Override @@ -336,6 +341,32 @@ public class VdMonitorServiceImpl implements VdMonitorService { return queryRunDataGroupList(dataSourceRequest, loadOptions, buildLatestRunDataCoreSql()); } + private DataSourceResult queryVdPointDetailList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildVdPointSelectSql()) + .append("FROM (") + .append(buildVdPointCoreSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = buildFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildVdPointOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, sql.toString(), paramMap, VdPointVo.class); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + private DataSourceResult queryRunDataGroupList(DataSourceRequest dataSourceRequest, DataSourceLoadOptionsBase loadOptions, String coreSql) { @@ -478,6 +509,52 @@ public class VdMonitorServiceImpl implements VdMonitorService { "FROM SD_SONAR_B_H sonar WHERE NVL(sonar.IS_DELETED, 0) = 0 AND sonar.STTP IN ('VD_WVD', 'VD_SN') "; } + private String buildVdPointCoreSql() { + return "SELECT " + + "src.STTP AS sttp, " + + "src.STCD AS stcd, " + + "src.LGTD AS lgtd, " + + "src.LTTD AS lttd, " + + "CAST(NULL AS NUMBER(10, 6)) AS dtmel, " + + "CASE " + + " WHEN NVL(eng.HBRVCD, src.HBRVCD) = 'SJLY126' THEN CASE src.STTP " + + " WHEN 'VD_FBFM' THEN 'fbfm_spjk' " + + " WHEN 'VD_EQS' THEN 'eqs_spjk' " + + " WHEN 'VD_FB' THEN 'fb_spjk' " + + " WHEN 'VD_FP' THEN 'fp_spjk' " + + " WHEN 'VD_FH' THEN 'fh_spjk' " + + " WHEN 'VD_VA' THEN 'va_spjk' " + + " WHEN 'VD_VP' THEN 'vp_spjk' " + + " WHEN 'VD_DW' THEN 'dw_spjk' " + + " WHEN 'VD_WQ' THEN 'wq_spjk' " + + " ELSE 'spjk' END " + + " ELSE 'spjk' END AS anchoPointState, " + + "'VD' AS sttpMap, " + + "src.STNM AS titleName, " + + "400000 AS distance, " + + "NVL(eng.RVCD, src.RVCD) AS rvcd, " + + "NVL(eng.ADDVCD, src.ADDVCD) AS addvcd, " + + "NVL(eng.BASE_ID, src.BASE_ID) AS baseId, " + + "src.RSTCD AS rstcds, " + + "'VD' AS sttpCode, " + + "src.STNM AS stnm, " + + "rv.RVNM AS rvnm, " + + "eng.ENNM AS ennm, " + + "src.FHSTCD AS fhstcd, " + + "fh.STNM AS fhstnm, " + + "sttp.STTP_NAME AS sttpName, " + + "src.STLC AS stlc, " + + "CASE WHEN src.URL IS NULL THEN NULL WHEN INSTR(src.URL, 'm3u8') > 0 THEN '1' ELSE '0' END AS playWay, " + + "src.ORDER_INDEX AS siteStepSort, " + + "NVL(eng.HBRVCD, src.HBRVCD) AS hbrvcd " + + "FROM (" + buildVdDeviceBaseSql() + ") src " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = src.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_FHBT_B_H fh ON fh.STCD = src.FHSTCD AND NVL(fh.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = NVL(eng.RVCD, src.RVCD) " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = src.STTP " + + " AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 "; + } + private String buildRunDataCoreSql() { return "SELECT " + "run.ID AS id, " + @@ -633,6 +710,33 @@ public class VdMonitorServiceImpl implements VdMonitorService { return String.join(", ", actualColumns); } + private String buildVdPointSelectSql() { + return "t.sttp AS sttp, " + + "t.stcd AS stcd, " + + "t.lgtd AS lgtd, " + + "t.lttd AS lttd, " + + "t.dtmel AS dtmel, " + + "t.anchoPointState AS anchoPointState, " + + "t.sttpMap AS sttpMap, " + + "t.titleName AS titleName, " + + "t.distance AS distance, " + + "t.rvcd AS rvcd, " + + "t.addvcd AS addvcd, " + + "t.baseId AS baseId, " + + "t.rstcds AS rstcds, " + + "t.sttpCode AS sttpCode, " + + "t.stnm AS stnm, " + + "t.rvnm AS rvnm, " + + "t.ennm AS ennm, " + + "t.fhstcd AS fhstcd, " + + "t.fhstnm AS fhstnm, " + + "t.sttpName AS sttpName, " + + "t.stlc AS stlc, " + + "t.playWay AS playWay, " + + "t.siteStepSort AS siteStepSort, " + + "t.hbrvcd AS hbrvcd "; + } + private String buildRunDataOrderBySql(List sortList) { if (CollUtil.isEmpty(sortList)) { return " ORDER BY t.baseStepSort ASC, t.rvcdStepSort ASC, t.rstcdStepSort ASC, t.siteStepSort ASC, t.stcd ASC, t.tm DESC"; @@ -655,6 +759,28 @@ public class VdMonitorServiceImpl implements VdMonitorService { return " ORDER BY " + String.join(", ", orderItems); } + private String buildVdPointOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY t.siteStepSort ASC NULLS LAST, t.stcd ASC"; + } + List orderItems = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sortList) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) || "des".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderItems.add(column + " " + direction + " NULLS LAST"); + } + if (orderItems.isEmpty()) { + return " ORDER BY t.siteStepSort ASC NULLS LAST, t.stcd ASC"; + } + return " ORDER BY " + String.join(", ", orderItems); + } + private String buildRunDataGroupOrderBySql(List groups) { if (CollUtil.isEmpty(groups)) { return ""; @@ -886,6 +1012,7 @@ public class VdMonitorServiceImpl implements VdMonitorService { return null; } return switch (field) { + case "sttp" -> "t.sttp"; case "sttpCode" -> "t.sttpCode"; case "sttpName" -> "t.sttpName"; case "sttpFullPath" -> "t.sttpFullPath"; @@ -920,11 +1047,15 @@ public class VdMonitorServiceImpl implements VdMonitorService { case "vlsr" -> "t.vlsr"; case "vlsrTm" -> "t.vlsrTm"; case "rvcd" -> "t.rvcd"; + case "rvnm" -> "t.rvnm"; case "addvcd" -> "t.addvcd"; case "dtin" -> "t.dtin"; case "usfl" -> "t.usfl"; case "url" -> "t.url"; case "playWay" -> "t.playWay"; + case "titleName" -> "t.titleName"; + case "rstcds" -> "t.rstcds"; + case "anchoPointState" -> "t.anchoPointState"; case "sourceTable" -> "t.sourceTable"; case "baseStepSort" -> "t.baseStepSort"; case "rstcdStepSort" -> "t.rstcdStepSort"; From d23d1b3dc00a1b6d14684e36fbe2d8d4d226446c Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 22 Jun 2026 14:48:35 +0800 Subject: [PATCH 09/38] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eq/entity/vo/EngEqBaseVmsstbprptVo.java | 33 +++++++++++++++++ .../eq/service/impl/EngEqDataServiceImpl.java | 35 +++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseVmsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseVmsstbprptVo.java index 84f485a0..588c7d77 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseVmsstbprptVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseVmsstbprptVo.java @@ -28,4 +28,37 @@ public class EngEqBaseVmsstbprptVo extends EngEqMsstbprptVo { @Schema(description = "设施排序") private Integer siteStepSort; + + @Schema(description = "死水位时保证流量") + private Double ddzgq; + + @Schema(description = "最大泄放流量") + private String flkq; + + @Schema(description = "孔口尺寸") + private String flksz; + + @Schema(description = "结构形式") + private String frntwlltyp; + + @Schema(description = "进水口底版高程") + private Double jskgc; + + @Schema(description = "出水口底版高程") + private Double outflrelev; + + @Schema(description = "基荷发电工况") + private Double jhfdgk; + + @Schema(description = "发电流量") + private Double fdll; + + @Schema(description = "生态机组额定流量") + private Double stjzysq; + + @Schema(description = "装机容量") + private Double ttpwr; + + @Schema(description = "所属建设阶段名称") + private String blprdName; } diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java index cc8cff1f..5a7a0cfc 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java @@ -426,6 +426,20 @@ public class EngEqDataServiceImpl implements EngEqDataService { "eng.TOP_HYCD AS topHycd, " + "eng.TOP_HYNM AS topHynm, " + "eq.BLPRD AS blprd, " + + "CASE eq.BLPRD " + + " WHEN 1001000 THEN '规划' " + + " WHEN 1002000 THEN '预可研' " + + " WHEN 1003000 THEN '环评' " + + " WHEN 1004000 THEN '可研' " + + " WHEN 1005000 THEN '在建' " + + " WHEN 1006000 THEN '招标设计' " + + " WHEN 1007000 THEN '施工详图' " + + " WHEN 1009000 THEN '建设' " + + " WHEN 1010000 THEN '蓄水阶段环保验收' " + + " WHEN 1011000 THEN '竣工' " + + " WHEN 1012000 THEN '竣工环保验收' " + + " WHEN 1013000 THEN '环境影响后评价' " + + " ELSE NULL END AS blprdName, " + "eq.LGTD AS lgtd, " + "eq.LTTD AS lttd, " + "eq.ELEV AS elev, " + @@ -444,6 +458,16 @@ public class EngEqDataServiceImpl implements EngEqDataService { "eng.BLDSTT_CODE AS bldsttCode, " + "TO_CHAR(eng.BLDSTT_CODE) AS bldsttCcode, " + "CASE NVL(eng.BLDSTT_CODE, -1) WHEN 0 THEN '未建/规划' WHEN 1 THEN '在建' WHEN 2 THEN '已建' ELSE NULL END AS bldsttCcodeName, " + + "eq.DDZGQ AS ddzgq, " + + "eq.FLKQ AS flkq, " + + "eq.FLKSZ AS flksz, " + + "eq.FLKJG AS frntwlltyp, " + + "eq.JSKDBGC AS jskgc, " + + "eq.CSKDBGC AS outflrelev, " + + "eq.JHFDGK AS jhfdgk, " + + "eq.FDLL AS fdll, " + + "eq.STJZYSQ AS stjzysq, " + + "eq.STJZZJRL AS ttpwr, " + "NVL(hb.ORDER_INDEX, 999999) AS baseStepSort, " + "NVL(along.ORDER_INDEX, 999999) AS rvcdStepSort, " + "NVL(eng.ORDER_INDEX, 999999) AS rstcdStepSort, " + @@ -513,6 +537,7 @@ public class EngEqDataServiceImpl implements EngEqDataService { columns.put("topHycd", "t.topHycd AS topHycd"); columns.put("topHynm", "t.topHynm AS topHynm"); columns.put("blprd", "t.blprd AS blprd"); + columns.put("blprdName", "t.blprdName AS blprdName"); columns.put("lgtd", "t.lgtd AS lgtd"); columns.put("lttd", "t.lttd AS lttd"); columns.put("elev", "t.elev AS elev"); @@ -530,6 +555,16 @@ public class EngEqDataServiceImpl implements EngEqDataService { columns.put("bldstt", "t.bldstt AS bldstt"); columns.put("bldsttCcode", "t.bldsttCcode AS bldsttCcode"); columns.put("bldsttCcodeName", "t.bldsttCcodeName AS bldsttCcodeName"); + columns.put("ddzgq", "t.ddzgq AS ddzgq"); + columns.put("flkq", "t.flkq AS flkq"); + columns.put("flksz", "t.flksz AS flksz"); + columns.put("frntwlltyp", "t.frntwlltyp AS frntwlltyp"); + columns.put("jskgc", "t.jskgc AS jskgc"); + columns.put("outflrelev", "t.outflrelev AS outflrelev"); + columns.put("jhfdgk", "t.jhfdgk AS jhfdgk"); + columns.put("fdll", "t.fdll AS fdll"); + columns.put("stjzysq", "t.stjzysq AS stjzysq"); + columns.put("ttpwr", "t.ttpwr AS ttpwr"); columns.put("orderIndex", "t.orderIndex AS orderIndex"); columns.put("tm", "t.tm AS tm"); columns.put("bldsttCode", "t.bldsttCode AS bldsttCode"); From aa2993a1e29ac8e76f71154c3e00afd884a86370 Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 22 Jun 2026 15:25:59 +0800 Subject: [PATCH 10/38] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yfd/platform/qgc_base/domain/SdEngInfoBHRequest.java | 2 ++ .../qgc_base/service/impl/SdEngInfoBHServiceImpl.java | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHRequest.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHRequest.java index 402b3bda..4a7f7127 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHRequest.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHRequest.java @@ -13,8 +13,10 @@ public class SdEngInfoBHRequest { private String baseId; private String hbrvcd; private String rvcd; + private String reachcd; private List basIds; private List hbrvcds; private List rvcds; +// private List rvcds; private String ennm; } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 0ee131b5..44ad3ca1 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -94,17 +94,20 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl rvcds = sdEngInfoBHRequest.getRvcds(); List hbrvcds = sdEngInfoBHRequest.getHbrvcds(); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(StringUtils.hasText(baseId), SdEngInfoBH::getBaseId, baseId) .eq(StringUtils.hasText(hbrvcd), SdEngInfoBH::getHbrvcd, hbrvcd) + .eq(StrUtil.isNotBlank(reachcd), SdEngInfoBH::getRvcd, reachcd) + .eq(StrUtil.isNotBlank(rvcd), SdEngInfoBH::getReachcd, rvcd) .eq(StrUtil.isNotBlank(rvcd), SdEngInfoBH::getReachcd, rvcd) .in(rvcds != null && !rvcds.isEmpty(), SdEngInfoBH::getReachcd, rvcds) .in(hbrvcds != null && !hbrvcds.isEmpty(), SdEngInfoBH::getHbrvcd, hbrvcds) .like(StringUtils.hasText(ennm), SdEngInfoBH::getEnnm, ennm) - .select(SdEngInfoBH::getStcd, SdEngInfoBH::getEnnm, SdEngInfoBH::getBaseId) - .orderByAsc(SdEngInfoBH::getOrderIndex); + .select(SdEngInfoBH::getStcd, SdEngInfoBH::getEnnm, SdEngInfoBH::getReachcdName, SdEngInfoBH::getYrgeb, SdEngInfoBH::getBaseId) + .orderByAsc(SdEngInfoBH::getBaseId,SdEngInfoBH::getOrderIndex); if("admin".equals(SecurityUtils.getCurrentUsername())){ return this.list(wrapper); From c07a73e20112888201bf7f00cbbeb51bc2a3fe04 Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 22 Jun 2026 15:32:46 +0800 Subject: [PATCH 11/38] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java | 1 + .../platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java | 2 ++ 2 files changed, 3 insertions(+) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java index ba6b5723..c01fd42e 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java @@ -20,6 +20,7 @@ public class EngVmsstbprptVo implements Serializable { private String ennm; private String baseId; private String baseName; + private String reachcdName; private String hbrvcd; private String hbrvcdName; private String rvcd; diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 44ad3ca1..5b90ab7f 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -472,6 +472,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl Date: Mon, 22 Jun 2026 15:45:55 +0800 Subject: [PATCH 12/38] =?UTF-8?q?fix:=20=E7=94=B5=E7=AB=99=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E4=B8=AD=E6=96=87=E8=BF=94=E5=9B=9E&=E7=94=B5?= =?UTF-8?q?=E7=AB=99=E9=80=BB=E8=BE=91=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qgc_base/domain/vo/EngVmsstbprptVo.java | 4 +++ .../service/impl/SdEngInfoBHServiceImpl.java | 33 ++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java index c01fd42e..c234fe73 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java @@ -34,6 +34,7 @@ public class EngVmsstbprptVo implements Serializable { private Date aiodt; private String bldstt; private Integer bldsttCcode; + private String bldsttCcodeName; private Double nrupar; private Double dstcrvr; private Double avyrp; @@ -80,6 +81,7 @@ public class EngVmsstbprptVo implements Serializable { private Double ddcp; private Double cpsc; private String rgcp; + private String rgcpName; private Double dsflzmxq; private Double dsflzxyz; private Double ckflzmxq; @@ -103,7 +105,9 @@ public class EngVmsstbprptVo implements Serializable { private Double unyge; private Double gap; private String dvtp; + private String dvtpName; private Integer dtin; + private String dtinName; private Integer baseStepSort; private Integer rvcdStepSort; private Integer rstcdStepSort; diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 5b90ab7f..848a7c49 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -5,6 +5,7 @@ import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.common.DataSourceLoadOptionsBase; @@ -199,7 +200,8 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl().eq(SdEngInfoBH::getStcd, stcd).set(SdEngInfoBH::getIsDeleted, 1)); +// return this.removeById(stcd); } @Override @@ -489,6 +491,11 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl Date: Mon, 22 Jun 2026 16:32:53 +0800 Subject: [PATCH 13/38] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E7=94=B5?= =?UTF-8?q?=E7=AB=99=E5=9F=BA=E6=9C=AC=E4=BF=A1=E6=81=AF=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SdEngInfoBHController.java | 10 +- .../qgc_base/domain/MsOperationLog.java | 32 +++ .../qgc_base/domain/MsOperationLogDetail.java | 49 ++++ .../domain/SdEngInfoBHOperateRequest.java | 11 + .../mapper/MsOperationLogDetailMapper.java | 7 + .../qgc_base/mapper/MsOperationLogMapper.java | 7 + .../service/IMsOperationLogService.java | 10 + .../qgc_base/service/ISdEngInfoBHService.java | 4 + .../impl/MsOperationLogServiceImpl.java | 213 ++++++++++++++++++ .../service/impl/SdEngInfoBHServiceImpl.java | 30 ++- 10 files changed, 367 insertions(+), 6 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLogDetail.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHOperateRequest.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogDetailMapper.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogMapper.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/service/IMsOperationLogService.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngInfoBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngInfoBHController.java index 866b074c..1faa114d 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngInfoBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngInfoBHController.java @@ -5,6 +5,7 @@ import com.yfd.platform.annotation.Log; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.qgc_base.domain.SdEngInfoBH; +import com.yfd.platform.qgc_base.domain.SdEngInfoBHOperateRequest; import com.yfd.platform.qgc_base.domain.SdEngInfoBHRequest; import com.yfd.platform.qgc_base.service.ISdEngInfoBHService; import io.swagger.v3.oas.annotations.Operation; @@ -91,16 +92,16 @@ public class SdEngInfoBHController { @Log(module = "电站管理", value = "新增电站") @PostMapping("/add") @Operation(summary = "新增电站") - public ResponseResult add(@RequestBody SdEngInfoBH engInfo) { - boolean result = engInfoBHService.addEngInfo(engInfo); + public ResponseResult add(@RequestBody SdEngInfoBHOperateRequest request) { + boolean result = engInfoBHService.addEngInfo(request.getEngInfo(), request.getSource()); return result ? ResponseResult.success("新增成功") : ResponseResult.error("新增失败"); } @Log(module = "电站管理", value = "修改电站") @PostMapping("/update") @Operation(summary = "修改电站") - public ResponseResult update(@RequestBody SdEngInfoBH engInfo) { - boolean result = engInfoBHService.updateEngInfo(engInfo); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) { + boolean result = engInfoBHService.updateEngInfo(request.getEngInfo(), request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } @@ -111,4 +112,5 @@ public class SdEngInfoBHController { boolean result = engInfoBHService.deleteEngInfo(stcd); return result ? ResponseResult.success("删除成功") : ResponseResult.error("删除失败"); } + } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java new file mode 100644 index 00000000..277171ac --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java @@ -0,0 +1,32 @@ +package com.yfd.platform.qgc_base.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@Data +@TableName("MS_OPERATION_LOG") +public class MsOperationLog implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + @TableField("OPERATOR") + private String operator; + + @TableField("OPERATE_TIME") + private Date operateTime; + + @TableField("SOURCE") + private String source; + + @TableField("REMARK") + private String remark; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLogDetail.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLogDetail.java new file mode 100644 index 00000000..27e06282 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLogDetail.java @@ -0,0 +1,49 @@ +package com.yfd.platform.qgc_base.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; + +@Data +@TableName("MS_OPERATION_LOG_DETAIL") +public class MsOperationLogDetail implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + @TableField("MAIN_ID") + private String mainId; + + @TableField("FIELD_CODE") + private String fieldCode; + + @TableField("TABLE_NAME") + private String tableName; + + @TableField("FIELD_MEANING") + private String fieldMeaning; + + @TableField("STATION_CODE") + private String stationCode; + + @TableField("OLD_VALUE_CODE") + private String oldValueCode; + + @TableField("OLD_VALUE_NAME") + private String oldValueName; + + @TableField("NEW_VALUE_CODE") + private String newValueCode; + + @TableField("NEW_VALUE_NAME") + private String newValueName; + + @TableField("REMARK") + private String remark; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHOperateRequest.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHOperateRequest.java new file mode 100644 index 00000000..bbe53d73 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHOperateRequest.java @@ -0,0 +1,11 @@ +package com.yfd.platform.qgc_base.domain; + +import lombok.Data; + +@Data +public class SdEngInfoBHOperateRequest { + + private SdEngInfoBH engInfo; + + private String source; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogDetailMapper.java b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogDetailMapper.java new file mode 100644 index 00000000..2f28291b --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogDetailMapper.java @@ -0,0 +1,7 @@ +package com.yfd.platform.qgc_base.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.qgc_base.domain.MsOperationLogDetail; + +public interface MsOperationLogDetailMapper extends BaseMapper { +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogMapper.java b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogMapper.java new file mode 100644 index 00000000..1049d713 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogMapper.java @@ -0,0 +1,7 @@ +package com.yfd.platform.qgc_base.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.qgc_base.domain.MsOperationLog; + +public interface MsOperationLogMapper extends BaseMapper { +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/IMsOperationLogService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/IMsOperationLogService.java new file mode 100644 index 00000000..51debb1d --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/IMsOperationLogService.java @@ -0,0 +1,10 @@ +package com.yfd.platform.qgc_base.service; + +import com.yfd.platform.qgc_base.domain.SdEngInfoBH; + +public interface IMsOperationLogService { + + void recordEngAddLog(SdEngInfoBH engInfo, String source); + + void recordEngUpdateLog(SdEngInfoBH before, SdEngInfoBH changeSet, String source); +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java index bedb9d35..0c3a521c 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java @@ -52,11 +52,15 @@ public interface ISdEngInfoBHService extends IService { */ boolean addEngInfo(SdEngInfoBH engInfo); + boolean addEngInfo(SdEngInfoBH engInfo, String source); + /** * 修改电站 */ boolean updateEngInfo(SdEngInfoBH engInfo); + boolean updateEngInfo(SdEngInfoBH engInfo, String source); + /** * 删除电站 */ diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java new file mode 100644 index 00000000..0e2ec828 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java @@ -0,0 +1,213 @@ +package com.yfd.platform.qgc_base.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.bean.copier.CopyOptions; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.yfd.platform.qgc_base.domain.MsOperationLog; +import com.yfd.platform.qgc_base.domain.MsOperationLogDetail; +import com.yfd.platform.qgc_base.domain.SdEngInfoBH; +import com.yfd.platform.qgc_base.mapper.MsOperationLogDetailMapper; +import com.yfd.platform.qgc_base.mapper.MsOperationLogMapper; +import com.yfd.platform.qgc_base.service.IMsOperationLogService; +import com.yfd.platform.utils.SecurityUtils; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@Service +public class MsOperationLogServiceImpl implements IMsOperationLogService { + + private static final String ENG_TABLE_NAME = "SD_ENGINFO_B_H"; + + private static final Map ENG_FIELD_MEANING_MAP = new LinkedHashMap<>(); + + static { + ENG_FIELD_MEANING_MAP.put("STCD", "电站编码"); + ENG_FIELD_MEANING_MAP.put("ENNM", "电站名称"); + ENG_FIELD_MEANING_MAP.put("BASE_ID", "所属基地编码"); + ENG_FIELD_MEANING_MAP.put("HBRVCD", "所属基地流域编码"); + ENG_FIELD_MEANING_MAP.put("RVCD", "所属流域编码"); + ENG_FIELD_MEANING_MAP.put("ADDVCD", "所属行政区编码"); + ENG_FIELD_MEANING_MAP.put("HYCD", "所属公司编码"); + ENG_FIELD_MEANING_MAP.put("BLPRD", "所属建设阶段"); + ENG_FIELD_MEANING_MAP.put("BLDSTT", "建设状态"); + ENG_FIELD_MEANING_MAP.put("BLDSTT_CODE", "建设状态分类"); + ENG_FIELD_MEANING_MAP.put("DVTP", "开发方式"); + ENG_FIELD_MEANING_MAP.put("DTIN", "数据是否接入"); + ENG_FIELD_MEANING_MAP.put("RGCP", "调节性能"); + ENG_FIELD_MEANING_MAP.put("LGTD", "经度"); + ENG_FIELD_MEANING_MAP.put("LTTD", "纬度"); + ENG_FIELD_MEANING_MAP.put("STLC", "站址"); + ENG_FIELD_MEANING_MAP.put("ORDER_INDEX", "排序"); + } + + @Resource + private MsOperationLogMapper msOperationLogMapper; + + @Resource + private MsOperationLogDetailMapper msOperationLogDetailMapper; + + @Override + public void recordEngAddLog(SdEngInfoBH engInfo, String source) { + if (engInfo == null) { + return; + } + MsOperationLog mainLog = buildMainLog("新增电站", source); + msOperationLogMapper.insert(mainLog); + + List details = new ArrayList<>(); + for (Field field : SdEngInfoBH.class.getDeclaredFields()) { + if (shouldSkipField(field)) { + continue; + } + field.setAccessible(true); + Object newValue = getFieldValue(field, engInfo); + if (newValue == null) { + continue; + } + details.add(buildDetail(mainLog.getId(), engInfo.getStcd(), resolveColumnName(field), + null, newValue, "新增字段值")); + } + batchInsertDetails(details); + } + + @Override + public void recordEngUpdateLog(SdEngInfoBH before, SdEngInfoBH changeSet, String source) { + if (before == null || changeSet == null) { + return; + } + SdEngInfoBH after = BeanUtil.copyProperties(before, SdEngInfoBH.class); + BeanUtil.copyProperties(changeSet, after, CopyOptions.create().ignoreNullValue()); + + MsOperationLog mainLog = buildMainLog("修改电站", source); + msOperationLogMapper.insert(mainLog); + + List details = new ArrayList<>(); + for (Field field : SdEngInfoBH.class.getDeclaredFields()) { + if (shouldSkipField(field)) { + continue; + } + field.setAccessible(true); + Object oldValue = getFieldValue(field, before); + Object newValue = getFieldValue(field, after); + if (equalsValue(oldValue, newValue)) { + continue; + } + details.add(buildDetail(mainLog.getId(), after.getStcd(), resolveColumnName(field), + oldValue, newValue, "修改字段值")); + } + batchInsertDetails(details); + } + + private MsOperationLog buildMainLog(String remark, String source) { + MsOperationLog log = new MsOperationLog(); + log.setOperator(resolveOperator()); + log.setOperateTime(new Date()); + log.setSource(StrUtil.trimToNull(source)); + log.setRemark(remark); + return log; + } + + private MsOperationLogDetail buildDetail(String mainId, + String stationCode, + String fieldCode, + Object oldValue, + Object newValue, + String remark) { + MsOperationLogDetail detail = new MsOperationLogDetail(); + detail.setMainId(mainId); + detail.setTableName(ENG_TABLE_NAME); + detail.setStationCode(stationCode); + detail.setFieldCode(fieldCode); + detail.setFieldMeaning(ENG_FIELD_MEANING_MAP.getOrDefault(fieldCode, fieldCode)); + detail.setOldValueCode(formatValue(oldValue)); + detail.setOldValueName(formatValue(oldValue)); + detail.setNewValueCode(formatValue(newValue)); + detail.setNewValueName(formatValue(newValue)); + detail.setRemark(remark); + return detail; + } + + private void batchInsertDetails(List details) { + msOperationLogDetailMapper.insert(details); + } + + private boolean shouldSkipField(Field field) { + if (Modifier.isStatic(field.getModifiers())) { + return true; + } + TableField tableField = field.getAnnotation(TableField.class); + if (tableField != null && !tableField.exist()) { + return true; + } + return false; + } + + private String resolveColumnName(Field field) { + TableId tableId = field.getAnnotation(TableId.class); + if (tableId != null) { + return camelToUpperUnderline(field.getName()); + } + TableField tableField = field.getAnnotation(TableField.class); + if (tableField != null && StrUtil.isNotBlank(tableField.value())) { + return tableField.value(); + } + return camelToUpperUnderline(field.getName()); + } + + private Object getFieldValue(Field field, Object target) { + try { + return field.get(target); + } catch (IllegalAccessException e) { + return null; + } + } + + private boolean equalsValue(Object oldValue, Object newValue) { + return StrUtil.equals(formatValue(oldValue), formatValue(newValue)); + } + + private String formatValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof Date date) { + return DateUtil.formatDateTime(date); + } + return String.valueOf(value); + } + + private String resolveOperator() { + try { + return SecurityUtils.getCurrentUsername(); + } catch (Exception ignored) { + try { + return SecurityUtils.getUserId(); + } catch (Exception ex) { + return null; + } + } + } + + private String camelToUpperUnderline(String text) { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < text.length(); i++) { + char ch = text.charAt(i); + if (Character.isUpperCase(ch) && i > 0) { + builder.append('_'); + } + builder.append(Character.toUpperCase(ch)); + } + return builder.toString(); + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 848a7c49..90f2cf64 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -22,11 +22,13 @@ import com.yfd.platform.qgc_base.domain.vo.EngBaseInfoVo; import com.yfd.platform.qgc_base.domain.vo.EngEiaapprovalVo; import com.yfd.platform.qgc_base.domain.vo.EngVmsstbprptVo; import com.yfd.platform.qgc_base.mapper.SdEngInfoBHMapper; +import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdEngInfoBHService; import com.yfd.platform.utils.QgcQueryWrapperUtil; import com.yfd.platform.utils.SecurityUtils; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import java.util.ArrayList; @@ -56,6 +58,9 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl queryPageList(Page page, String ennm, String rvcd, String baseId, String hycd) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); @@ -190,12 +195,33 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl Date: Mon, 22 Jun 2026 17:12:03 +0800 Subject: [PATCH 14/38] =?UTF-8?q?feat:=20=E8=A7=86=E9=A2=91=E7=AB=99?= =?UTF-8?q?=E6=A0=91=E7=BA=A7=E7=BB=93=E6=9E=84=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vd/controller/VdMonitorController.java | 6 + .../qgc_env/vd/entity/vo/VdTreeNodeVo.java | 71 ++++ .../qgc_env/vd/entity/vo/VdTreeRowVo.java | 39 +++ .../qgc_env/vd/service/VdMonitorService.java | 3 + .../vd/service/impl/VdMonitorServiceImpl.java | 329 +++++++++++++++++- 5 files changed, 446 insertions(+), 2 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdTreeNodeVo.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdTreeRowVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/controller/VdMonitorController.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/controller/VdMonitorController.java index 1e670bfe..3bd3f3f0 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vd/controller/VdMonitorController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/controller/VdMonitorController.java @@ -47,6 +47,12 @@ public class VdMonitorController { return ResponseResult.successData(vdMonitorService.getKendoListCust(dataSourceRequest)); } + @PostMapping("/tree/GetKendoListCust") + @Operation(summary = "视频站树级结构查询") + public ResponseResult getVdTreeKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(vdMonitorService.getVdTreeKendoListCust(dataSourceRequest)); + } + @PostMapping("/vdpoint/GetKendoListCust") @Operation(summary = "视频站锚点接口") public ResponseResult getVdPointKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdTreeNodeVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdTreeNodeVo.java new file mode 100644 index 00000000..8b31efb7 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdTreeNodeVo.java @@ -0,0 +1,71 @@ +package com.yfd.platform.qgc_env.vd.entity.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +@Data +@Schema(description = "视频站树节点") +public class VdTreeNodeVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "节点ID") + private String id; + + @Schema(description = "节点名称") + private String name; + + @Schema(description = "节点类型") + private String type; + + @Schema(description = "节点类型名称") + private String typeName; + + @Schema(description = "排序值") + private Integer sort; + + @Schema(description = "父节点ID") + private String parentId; + + @Schema(description = "父节点名称") + private String parentName; + + @Schema(description = "是否有子节点") + private Integer hasChildren; + + @Schema(description = "播放地址") + private String url; + + @Schema(description = "播放方式") + private String playWay; + + @Schema(description = "设备序列号") + private String deviceSerial; + + @Schema(description = "接入方式") + private String accessWay; + + @Schema(description = "流协议") + private String protocol; + + @Schema(description = "清晰度") + private String quality; + + @Schema(description = "控制方式") + private String controlMode; + + @Schema(description = "设备状态") + private Integer status; + + @Schema(description = "状态时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date statusTm; + + @Schema(description = "子节点") + private List children; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdTreeRowVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdTreeRowVo.java new file mode 100644 index 00000000..eeea11bb --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdTreeRowVo.java @@ -0,0 +1,39 @@ +package com.yfd.platform.qgc_env.vd.entity.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@Data +public class VdTreeRowVo implements Serializable { + + private static final long serialVersionUID = 1L; + + private String stcd; + private String stCode; + private String stName; + private String stnm; + private String sttpCode; + private String sttpName; + private String sttpFullPath; + private String rstcd; + private String ennm; + private String baseId; + private String baseName; + private String url; + private String playWay; + private Integer baseSort; + private Integer rstcdStepSort; + private Integer siteStepSort; + private String deviceSerial; + private String accessWay; + private String protocol; + private String quality; + private String controlMode; + private Integer status; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date statusTm; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java index 3b21de15..58d6e69a 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java @@ -2,6 +2,7 @@ package com.yfd.platform.qgc_env.vd.service; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.qgc_env.vd.entity.vo.VdTreeNodeVo; import com.yfd.platform.qgc_env.vd.entity.vo.VdRunDataVo; import com.yfd.platform.qgc_env.vd.entity.vo.VdVmsstbprptVo; @@ -13,6 +14,8 @@ public interface VdMonitorService { DataSourceResult getKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getVdTreeKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getVdPointKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getRunDataKendoListCust(DataSourceRequest dataSourceRequest); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java index d1931ea5..f13f0ed0 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java @@ -11,6 +11,8 @@ import com.yfd.platform.common.GroupingInfo; import com.yfd.platform.common.MicroservicDynamicSQLMapper; import com.yfd.platform.qgc_env.vd.entity.vo.VdPointVo; import com.yfd.platform.qgc_env.vd.entity.vo.VdRunDataVo; +import com.yfd.platform.qgc_env.vd.entity.vo.VdTreeNodeVo; +import com.yfd.platform.qgc_env.vd.entity.vo.VdTreeRowVo; import com.yfd.platform.qgc_env.vd.entity.vo.VdVmsstbprptVo; import com.yfd.platform.qgc_env.vd.service.VdMonitorService; import com.yfd.platform.utils.QgcQueryWrapperUtil; @@ -19,6 +21,7 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -119,6 +122,55 @@ public class VdMonitorServiceImpl implements VdMonitorService { return queryLatestRunDataGroupList(dataSourceRequest, loadOptions); } + @Override + public DataSourceResult getVdTreeKendoListCust(DataSourceRequest dataSourceRequest) { + Map paramMap = new HashMap<>(); + String filterSql = buildVdTreeFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("t.stcd AS stcd, ") + .append("t.stCode AS stCode, ") + .append("t.stName AS stName, ") + .append("t.stnm AS stnm, ") + .append("t.sttpCode AS sttpCode, ") + .append("t.sttpName AS sttpName, ") + .append("t.sttpFullPath AS sttpFullPath, ") + .append("t.rstcd AS rstcd, ") + .append("t.ennm AS ennm, ") + .append("t.baseId AS baseId, ") + .append("t.baseName AS baseName, ") + .append("t.url AS url, ") + .append("t.playWay AS playWay, ") + .append("t.baseSort AS baseSort, ") + .append("t.rstcdStepSort AS rstcdStepSort, ") + .append("t.siteStepSort AS siteStepSort, ") + .append("t.deviceSerial AS deviceSerial, ") + .append("t.accessWay AS accessWay, ") + .append("t.protocol AS protocol, ") + .append("t.quality AS quality, ") + .append("t.controlMode AS controlMode, ") + .append("t.status AS status, ") + .append("t.statusTm AS statusTm ") + .append("FROM (") + .append(buildVdTreeCoreSql()) + .append(") t WHERE 1 = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(" ORDER BY t.baseSort ASC NULLS LAST, t.rstcdStepSort ASC NULLS LAST, t.siteStepSort ASC NULLS LAST, t.stcd ASC"); + + List rows = microservicDynamicSQLMapper.getAllListWithResultType(sql.toString(), paramMap, VdTreeRowVo.class); + boolean baseScoped = containsNonBlankFilterValue(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), "baseId"); + + DataSourceResult result = new DataSourceResult<>(); + List treeData = buildVdTreeNodes(rows, baseScoped); + result.setData(treeData); + result.setTotal((long) treeData.size()); + result.setAggregates(new HashMap<>()); + return result; + } + @Override public DataSourceResult getVdPointKendoListCust(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -491,12 +543,57 @@ public class VdMonitorServiceImpl implements VdMonitorService { " AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 "; } + private String buildVdTreeCoreSql() { + return "SELECT " + + "base.STCD AS stcd, " + + "base.STNM AS stnm, " + + "base.CSTCD AS stCode, " + + "cst.STNM AS stName, " + + "base.STTP AS sttpCode, " + + "sttp.STTP_NAME AS sttpName, " + + "sttp.FULL_PATH AS sttpFullPath, " + + "base.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "NVL(eng.BASE_ID, base.BASE_ID) AS baseId, " + + "hb.BASENAME AS baseName, " + + "base.URL AS url, " + + "CASE WHEN base.URL IS NULL THEN NULL WHEN INSTR(base.URL, 'm3u8') > 0 THEN '1' ELSE '0' END AS playWay, " + + "NVL(hb.ORDER_INDEX, 999999) AS baseSort, " + + "NVL(eng.ORDER_INDEX, 999999) AS rstcdStepSort, " + + "NVL(base.ORDER_INDEX, 999999) AS siteStepSort, " + + "base.DEVICE_SERIAL AS deviceSerial, " + + "base.ACCESS_WAY AS accessWay, " + + "base.PROTOCOL AS protocol, " + + "base.QUALITY AS quality, " + + "base.CONTROL_MODE AS controlMode, " + + "status.STATUS AS status, " + + "status.TM AS statusTm " + + "FROM (" + buildVdDeviceBaseSql() + ") base " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = base.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = NVL(eng.BASE_ID, base.BASE_ID) " + + " AND NVL(hb.IS_DELETED, 0) = 0 AND NVL(hb.ENABLED, 1) = 1 " + + "LEFT JOIN (" + buildStationBaseSql() + ") cst ON cst.STCD = base.CSTCD " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = base.STTP " + + " AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 " + + "LEFT JOIN ( " + + "SELECT detail.STCD, detail.TM, detail.STATUS " + + "FROM MS_SBGZSTAT_B detail " + + "INNER JOIN ( " + + "SELECT STCD, MAX(TM) AS MAX_TM FROM MS_SBGZSTAT_B " + + "WHERE NVL(IS_DELETED, 0) = 0 GROUP BY STCD " + + ") latest ON detail.STCD = latest.STCD AND detail.TM = latest.MAX_TM " + + "WHERE NVL(detail.IS_DELETED, 0) = 0 " + + ") status ON status.STCD = base.STCD " + + "WHERE base.STTP LIKE 'VD_%' "; + } + private String buildVdDeviceBaseSql() { return "SELECT vd.STCD, vd.STNM, vd.MNTP, vd.STTP, vd.LGTD, vd.LTTD, vd.ELEV, vd.STLC, " + " vd.JCDT, vd.WDDT, vd.BLDSTT_CODE, vd.USFL, vd.DTIN, vd.STINDX, vd.RSTCD, vd.BASE_ID, " + " vd.HBRVCD, vd.RVCD, vd.ADDVCD, vd.CSTCD, vd.FHSTCD, CAST(NULL AS VARCHAR2(3000)) AS INTRODUCE, " + " CAST(NULL AS VARCHAR2(255)) AS LOGO, CAST(NULL AS VARCHAR2(1000)) AS INFFILE, " + - " vd.DTFRQCY, vd.REMARK, vd.VLSR, vd.VLSR_TM, vd.URL AS URL, CAST(NULL AS NUMBER(8,0)) AS ORDER_INDEX, " + + " vd.DTFRQCY, vd.REMARK, vd.VLSR, vd.VLSR_TM, vd.URL AS URL, vd.DEVICE_SERIAL, vd.ACCESS_WAY, " + + " vd.PROTOCOL, vd.QUALITY, vd.CONTROL_MODE, CAST(NULL AS NUMBER(8,0)) AS ORDER_INDEX, " + " 'SD_VDINFO_B' AS SOURCE_TABLE " + "FROM SD_VDINFO_B vd WHERE 1=1 " + // " AND vd.STTP = 'VD_FP' "+ @@ -504,7 +601,9 @@ public class VdMonitorServiceImpl implements VdMonitorService { "SELECT sonar.STCD, sonar.STNM, sonar.MNTP, sonar.STTP, sonar.LGTD, sonar.LTTD, sonar.ELEV, sonar.STLC, " + " sonar.JCDT, sonar.WDDT, sonar.BLDSTT_CODE, sonar.USFL, sonar.DTIN, sonar.STINDX, sonar.RSTCD, sonar.BASE_ID, " + " sonar.HBRVCD, sonar.RVCD, sonar.ADDVCD, CAST(NULL AS VARCHAR2(36)) AS CSTCD, CAST(NULL AS VARCHAR2(36)) AS FHSTCD, " + - " sonar.INTRODUCE, sonar.LOGO, sonar.INFFILE, sonar.DTFRQCY, sonar.REMARK, sonar.VLSR, sonar.VLSR_TM, CAST(NULL AS VARCHAR2(512)) AS URL, sonar.ORDER_INDEX, " + + " sonar.INTRODUCE, sonar.LOGO, sonar.INFFILE, sonar.DTFRQCY, sonar.REMARK, sonar.VLSR, sonar.VLSR_TM, CAST(NULL AS VARCHAR2(512)) AS URL, " + + " CAST(NULL AS VARCHAR2(255)) AS DEVICE_SERIAL, CAST(NULL AS VARCHAR2(10)) AS ACCESS_WAY, " + + " CAST(NULL AS VARCHAR2(50)) AS PROTOCOL, CAST(NULL AS VARCHAR2(50)) AS QUALITY, CAST(NULL AS VARCHAR2(2048)) AS CONTROL_MODE, sonar.ORDER_INDEX, " + " 'SD_SONAR_B_H' AS SOURCE_TABLE " + "FROM SD_SONAR_B_H sonar WHERE NVL(sonar.IS_DELETED, 0) = 0 AND sonar.STTP IN ('VD_WVD', 'VD_SN') "; } @@ -809,6 +908,42 @@ public class VdMonitorServiceImpl implements VdMonitorService { }; } + private String buildVdTreeFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildVdTreeLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildVdTreeFilterCondition(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 buildVdTreeLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapVdTreeColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + return buildSimpleCondition(column, "vdTreeParam", filter, paramMap, indexHolder, isVdTreeDateField(filter)); + } + private String buildFilterCondition(DataSourceRequest.FilterDescriptor filter, Map paramMap, int[] indexHolder) { @@ -972,6 +1107,16 @@ public class VdMonitorServiceImpl implements VdMonitorService { return "date".equalsIgnoreCase(filter.getDataType()); } + private boolean isVdTreeDateField(DataSourceRequest.FilterDescriptor filter) { + if (filter == null || StrUtil.isBlank(filter.getField())) { + return false; + } + if ("statusTm".equalsIgnoreCase(filter.getField())) { + return true; + } + return "date".equalsIgnoreCase(filter.getDataType()); + } + private String buildValueExpr(String paramKey, boolean dateField, Object value) { if (!dateField || value == null) { return "#{map." + paramKey + "}"; @@ -1007,6 +1152,35 @@ public class VdMonitorServiceImpl implements VdMonitorService { return values; } + private String mapVdTreeColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd" -> "t.stcd"; + case "stCode" -> "t.stCode"; + case "stName" -> "t.stName"; + case "stnm" -> "t.stnm"; + case "sttpCode" -> "t.sttpCode"; + case "sttpName" -> "t.sttpName"; + case "sttpFullPath" -> "t.sttpFullPath"; + case "rstcd" -> "t.rstcd"; + case "ennm" -> "t.ennm"; + case "baseId" -> "t.baseId"; + case "baseName" -> "t.baseName"; + case "url" -> "t.url"; + case "playWay" -> "t.playWay"; + case "deviceSerial" -> "t.deviceSerial"; + case "accessWay" -> "t.accessWay"; + case "protocol" -> "t.protocol"; + case "quality" -> "t.quality"; + case "controlMode" -> "t.controlMode"; + case "status" -> "NVL(t.status, 0)"; + case "statusTm" -> "t.statusTm"; + default -> null; + }; + } + private String mapColumn(String field) { if (StrUtil.isBlank(field)) { return null; @@ -1144,4 +1318,155 @@ public class VdMonitorServiceImpl implements VdMonitorService { } return " ORDER BY " + String.join(", ", orderItems); } + + private boolean containsNonBlankFilterValue(DataSourceRequest.FilterDescriptor filter, String fieldName) { + if (filter == null || StrUtil.isBlank(fieldName)) { + return false; + } + if (fieldName.equalsIgnoreCase(filter.getField())) { + if (filter.getValue() instanceof List list) { + return CollUtil.isNotEmpty(list); + } + return StrUtil.isNotBlank(filter.getValue() == null ? null : String.valueOf(filter.getValue())); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return false; + } + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + if (containsNonBlankFilterValue(child, fieldName)) { + return true; + } + } + return false; + } + + private List buildVdTreeNodes(List rows, boolean baseScoped) { + List stationNodes = buildStationTreeNodes(rows, baseScoped); + if (baseScoped) { + return sortTreeNodes(stationNodes); + } + + LinkedHashMap baseNodeMap = new LinkedHashMap<>(); + List topLevelWithoutBase = new ArrayList<>(); + for (VdTreeRowVo row : rows) { + if (row == null) { + continue; + } + if (StrUtil.isBlank(row.getBaseId())) { + continue; + } + baseNodeMap.computeIfAbsent(row.getBaseId(), key -> { + VdTreeNodeVo node = new VdTreeNodeVo(); + node.setId(key); + node.setName(StrUtil.blankToDefault(row.getBaseName(), key)); + node.setType("PSB"); + node.setTypeName("基地"); + node.setSort(defaultSort(row.getBaseSort())); + node.setHasChildren(1); + node.setParentId(null); + node.setParentName(null); + return node; + }); + } + + Map> stationByBase = new LinkedHashMap<>(); + for (VdTreeNodeVo stationNode : stationNodes) { + if (StrUtil.isBlank(stationNode.getParentId())) { + topLevelWithoutBase.add(stationNode); + continue; + } + stationByBase.computeIfAbsent(stationNode.getParentId(), key -> new ArrayList<>()).add(stationNode); + } + + List result = new ArrayList<>(); + for (Map.Entry entry : baseNodeMap.entrySet()) { + VdTreeNodeVo baseNode = entry.getValue(); + baseNode.setChildren(sortTreeNodes(stationByBase.get(entry.getKey()))); + result.add(baseNode); + } + result.addAll(topLevelWithoutBase); + return sortTreeNodes(result); + } + + private List buildStationTreeNodes(List rows, boolean baseScoped) { + LinkedHashMap> stationRowMap = new LinkedHashMap<>(); + for (VdTreeRowVo row : rows) { + if (row == null || StrUtil.isBlank(row.getRstcd())) { + continue; + } + stationRowMap.computeIfAbsent(row.getRstcd(), key -> new ArrayList<>()).add(row); + } + + List stationNodes = new ArrayList<>(); + for (Map.Entry> entry : stationRowMap.entrySet()) { + List stationRows = entry.getValue(); + if (CollUtil.isEmpty(stationRows)) { + continue; + } + VdTreeRowVo sample = stationRows.get(0); + VdTreeNodeVo stationNode = new VdTreeNodeVo(); + stationNode.setId(entry.getKey()); + stationNode.setName(StrUtil.blankToDefault(sample.getEnnm(), entry.getKey())); + stationNode.setType("ENG"); + stationNode.setTypeName("电站"); + stationNode.setSort(defaultSort(sample.getRstcdStepSort())); + stationNode.setHasChildren(1); + if (baseScoped) { + stationNode.setParentId(null); + stationNode.setParentName(null); + } else { + stationNode.setParentId(sample.getBaseId()); + stationNode.setParentName(sample.getBaseName()); + } + stationNode.setChildren(buildSiteTreeNodes(stationRows)); + stationNodes.add(stationNode); + } + return sortTreeNodes(stationNodes); + } + + private List buildSiteTreeNodes(List rows) { + LinkedHashMap siteNodeMap = new LinkedHashMap<>(); + for (VdTreeRowVo row : rows) { + if (row == null || StrUtil.isBlank(row.getStcd()) || siteNodeMap.containsKey(row.getStcd())) { + continue; + } + VdTreeNodeVo node = new VdTreeNodeVo(); + node.setId(row.getStcd()); + node.setName(StrUtil.blankToDefault(row.getStnm(), row.getStcd())); + node.setType(row.getSttpCode()); + node.setTypeName(row.getSttpName()); + node.setSort(defaultSort(row.getSiteStepSort())); + node.setHasChildren(0); + node.setParentId(row.getRstcd()); + node.setParentName(row.getEnnm()); + node.setUrl(row.getUrl()); + node.setPlayWay(row.getPlayWay()); + node.setDeviceSerial(row.getDeviceSerial()); + node.setAccessWay(row.getAccessWay()); + node.setProtocol(row.getProtocol()); + node.setQuality(row.getQuality()); + node.setControlMode(row.getControlMode()); + node.setStatus(row.getStatus()); + node.setStatusTm(row.getStatusTm()); + siteNodeMap.put(row.getStcd(), node); + } + return sortTreeNodes(new ArrayList<>(siteNodeMap.values())); + } + + private List sortTreeNodes(List nodes) { + if (CollUtil.isEmpty(nodes)) { + return new ArrayList<>(); + } + nodes.sort(Comparator.comparing(VdMonitorServiceImpl::sortValue) + .thenComparing(node -> StrUtil.blankToDefault(node.getId(), ""))); + return nodes; + } + + private static Integer sortValue(VdTreeNodeVo node) { + return node == null ? 999999 : defaultSort(node.getSort()); + } + + private static Integer defaultSort(Integer sort) { + return sort == null ? 999999 : sort; + } } From 26837f30c5a2e319d4208175a5fd02a0edcab55e Mon Sep 17 00:00:00 2001 From: tangwei Date: Mon, 22 Jun 2026 17:17:28 +0800 Subject: [PATCH 15/38] =?UTF-8?q?feat:=20=E8=A7=86=E9=A2=91=E7=AB=99?= =?UTF-8?q?=E6=A0=91=E7=BA=A7=E7=BB=93=E6=9E=84=E6=9F=A5=E8=AF=A2-?= =?UTF-8?q?=E7=AB=99=E7=82=B9=E7=BB=B4=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vd/controller/VdMonitorController.java | 6 + .../qgc_env/vd/service/VdMonitorService.java | 2 + .../vd/service/impl/VdMonitorServiceImpl.java | 159 ++++++++++++++++++ 3 files changed, 167 insertions(+) diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/controller/VdMonitorController.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/controller/VdMonitorController.java index 3bd3f3f0..1c37e616 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vd/controller/VdMonitorController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/controller/VdMonitorController.java @@ -53,6 +53,12 @@ public class VdMonitorController { return ResponseResult.successData(vdMonitorService.getVdTreeKendoListCust(dataSourceRequest)); } + @PostMapping("/tree/GetKendoListCustSt") + @Operation(summary = "视频站树级结构查询-站点维度") + public ResponseResult getVdTreeKendoListCustSt(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(vdMonitorService.getVdTreeKendoListCustSt(dataSourceRequest)); + } + @PostMapping("/vdpoint/GetKendoListCust") @Operation(summary = "视频站锚点接口") public ResponseResult getVdPointKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java index 58d6e69a..490bd6b7 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java @@ -16,6 +16,8 @@ public interface VdMonitorService { DataSourceResult getVdTreeKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getVdTreeKendoListCustSt(DataSourceRequest dataSourceRequest); + DataSourceResult getVdPointKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getRunDataKendoListCust(DataSourceRequest dataSourceRequest); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java index f13f0ed0..e4b17aca 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java @@ -171,6 +171,55 @@ public class VdMonitorServiceImpl implements VdMonitorService { return result; } + @Override + public DataSourceResult getVdTreeKendoListCustSt(DataSourceRequest dataSourceRequest) { + Map paramMap = new HashMap<>(); + String filterSql = buildVdTreeFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("t.stcd AS stcd, ") + .append("t.stCode AS stCode, ") + .append("t.stName AS stName, ") + .append("t.stnm AS stnm, ") + .append("t.sttpCode AS sttpCode, ") + .append("t.sttpName AS sttpName, ") + .append("t.sttpFullPath AS sttpFullPath, ") + .append("t.rstcd AS rstcd, ") + .append("t.ennm AS ennm, ") + .append("t.baseId AS baseId, ") + .append("t.baseName AS baseName, ") + .append("t.url AS url, ") + .append("t.playWay AS playWay, ") + .append("t.baseSort AS baseSort, ") + .append("t.rstcdStepSort AS rstcdStepSort, ") + .append("t.siteStepSort AS siteStepSort, ") + .append("t.deviceSerial AS deviceSerial, ") + .append("t.accessWay AS accessWay, ") + .append("t.protocol AS protocol, ") + .append("t.quality AS quality, ") + .append("t.controlMode AS controlMode, ") + .append("t.status AS status, ") + .append("t.statusTm AS statusTm ") + .append("FROM (") + .append(buildVdTreeCoreSql()) + .append(") t WHERE 1 = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(" ORDER BY t.baseSort ASC NULLS LAST, t.rstcdStepSort ASC NULLS LAST, t.siteStepSort ASC NULLS LAST, t.stcd ASC"); + + List rows = microservicDynamicSQLMapper.getAllListWithResultType(sql.toString(), paramMap, VdTreeRowVo.class); + boolean baseScoped = containsNonBlankFilterValue(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), "baseId"); + + DataSourceResult result = new DataSourceResult<>(); + List treeData = buildVdTreeNodesByStation(rows, baseScoped); + result.setData(treeData); + result.setTotal((long) treeData.size()); + result.setAggregates(new HashMap<>()); + return result; + } + @Override public DataSourceResult getVdPointKendoListCust(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -1388,6 +1437,51 @@ public class VdMonitorServiceImpl implements VdMonitorService { return sortTreeNodes(result); } + private List buildVdTreeNodesByStation(List rows, boolean baseScoped) { + List stationNodes = buildStationCodeTreeNodes(rows, baseScoped); + if (baseScoped) { + return sortTreeNodes(stationNodes); + } + + LinkedHashMap baseNodeMap = new LinkedHashMap<>(); + List topLevelWithoutBase = new ArrayList<>(); + for (VdTreeRowVo row : rows) { + if (row == null || StrUtil.isBlank(row.getBaseId())) { + continue; + } + baseNodeMap.computeIfAbsent(row.getBaseId(), key -> { + VdTreeNodeVo node = new VdTreeNodeVo(); + node.setId(key); + node.setName(StrUtil.blankToDefault(row.getBaseName(), key)); + node.setType("PSB"); + node.setTypeName("基地"); + node.setSort(defaultSort(row.getBaseSort())); + node.setHasChildren(1); + node.setParentId(null); + node.setParentName(null); + return node; + }); + } + + Map> stationByBase = new LinkedHashMap<>(); + for (VdTreeNodeVo stationNode : stationNodes) { + if (StrUtil.isBlank(stationNode.getParentId())) { + topLevelWithoutBase.add(stationNode); + continue; + } + stationByBase.computeIfAbsent(stationNode.getParentId(), key -> new ArrayList<>()).add(stationNode); + } + + List result = new ArrayList<>(); + for (Map.Entry entry : baseNodeMap.entrySet()) { + VdTreeNodeVo baseNode = entry.getValue(); + baseNode.setChildren(sortTreeNodes(stationByBase.get(entry.getKey()))); + result.add(baseNode); + } + result.addAll(topLevelWithoutBase); + return sortTreeNodes(result); + } + private List buildStationTreeNodes(List rows, boolean baseScoped) { LinkedHashMap> stationRowMap = new LinkedHashMap<>(); for (VdTreeRowVo row : rows) { @@ -1453,6 +1547,71 @@ public class VdMonitorServiceImpl implements VdMonitorService { return sortTreeNodes(new ArrayList<>(siteNodeMap.values())); } + private List buildStationCodeTreeNodes(List rows, boolean baseScoped) { + LinkedHashMap> stationRowMap = new LinkedHashMap<>(); + for (VdTreeRowVo row : rows) { + if (row == null || StrUtil.isBlank(row.getStCode())) { + continue; + } + stationRowMap.computeIfAbsent(row.getStCode(), key -> new ArrayList<>()).add(row); + } + + List stationNodes = new ArrayList<>(); + for (Map.Entry> entry : stationRowMap.entrySet()) { + List stationRows = entry.getValue(); + if (CollUtil.isEmpty(stationRows)) { + continue; + } + VdTreeRowVo sample = stationRows.get(0); + VdTreeNodeVo stationNode = new VdTreeNodeVo(); + stationNode.setId(entry.getKey()); + stationNode.setName(StrUtil.blankToDefault(sample.getStName(), entry.getKey())); + stationNode.setType("VD_FB"); + stationNode.setTypeName("鱼类增殖站"); + stationNode.setSort(defaultSort(sample.getRstcdStepSort())); + stationNode.setHasChildren(1); + if (baseScoped) { + stationNode.setParentId(null); + stationNode.setParentName(null); + } else { + stationNode.setParentId(sample.getBaseId()); + stationNode.setParentName(sample.getBaseName()); + } + stationNode.setChildren(buildSiteTreeNodesByStation(stationRows)); + stationNodes.add(stationNode); + } + return sortTreeNodes(stationNodes); + } + + private List buildSiteTreeNodesByStation(List rows) { + LinkedHashMap siteNodeMap = new LinkedHashMap<>(); + for (VdTreeRowVo row : rows) { + if (row == null || StrUtil.isBlank(row.getStcd()) || siteNodeMap.containsKey(row.getStcd())) { + continue; + } + VdTreeNodeVo node = new VdTreeNodeVo(); + node.setId(row.getStcd()); + node.setName(StrUtil.blankToDefault(row.getStnm(), row.getStcd())); + node.setType(row.getSttpCode()); + node.setTypeName(row.getSttpName()); + node.setSort(defaultSort(row.getSiteStepSort())); + node.setHasChildren(0); + node.setParentId(row.getStCode()); + node.setParentName(row.getStName()); + node.setUrl(row.getUrl()); + node.setPlayWay(row.getPlayWay()); + node.setDeviceSerial(row.getDeviceSerial()); + node.setAccessWay(row.getAccessWay()); + node.setProtocol(row.getProtocol()); + node.setQuality(row.getQuality()); + node.setControlMode(row.getControlMode()); + node.setStatus(row.getStatus()); + node.setStatusTm(row.getStatusTm()); + siteNodeMap.put(row.getStcd(), node); + } + return sortTreeNodes(new ArrayList<>(siteNodeMap.values())); + } + private List sortTreeNodes(List nodes) { if (CollUtil.isEmpty(nodes)) { return new ArrayList<>(); From 808953dc76fcb16320cc2dae8540f83a2fc38373 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 23 Jun 2026 09:00:10 +0800 Subject: [PATCH 16/38] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/FprMonitorServiceImpl.java | 65 +++++-------------- 1 file changed, 18 insertions(+), 47 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java index a1503c2e..8bef55ff 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java @@ -732,12 +732,8 @@ public class FprMonitorServiceImpl implements FprMonitorService { "src.ID AS id, " + "NVL(src.IS_DELETED, 0) AS isDeleted, " + "src.ID AS zyFishId, " + - "NVL((SELECT MIN(rel2.RVCD) " + - " FROM SD_FISHDICTORY_RLTN_B rel2 " + - " WHERE rel2.ZY_FISH_ID = src.ID " + - " AND rel2.RVCD <> 'ZY' " + - " AND NVL(rel2.IS_DELETED, 0) = 0), 'null') AS rvcd, " + - "CAST(NULL AS VARCHAR2(1000)) AS rvcdName, " + + "NVL(relAgg.rvcd, 'null') AS rvcd, " + + "NVL(relAgg.rvcdName, '') AS rvcdName, " + "src.NAME AS name, " + "src.TYPE AS type, " + "src.FAMILY AS family, " + @@ -772,6 +768,20 @@ public class FprMonitorServiceImpl implements FprMonitorService { "src.VLSR_TM AS vlsrTm, " + "src.SPAWN_MONTH AS spawnMonth " + "FROM SD_FISHDICTORY_B src " + + "LEFT JOIN ( " + + " SELECT relBase.ZY_FISH_ID AS zyFishId, " + + " MIN(relBase.RVCD) AS rvcd, " + + " LISTAGG(relBase.RVNM, ',') WITHIN GROUP (ORDER BY relBase.RVNM) AS rvcdName " + + " FROM ( " + + " SELECT DISTINCT rel.ZY_FISH_ID, rel.RVCD, rv.RVNM " + + " FROM SD_FISHDICTORY_RLTN_B rel " + + " LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = rel.RVCD " + + " WHERE rel.RVCD <> 'ZY' " + + " AND NVL(rel.IS_DELETED, 0) = 0 " + + " AND rv.RVNM IS NOT NULL " + + " ) relBase " + + " GROUP BY relBase.ZY_FISH_ID " + + ") relAgg ON relAgg.zyFishId = src.ID " + "WHERE NVL(src.IS_DELETED, 0) = 0 "; } @@ -787,49 +797,10 @@ public class FprMonitorServiceImpl implements FprMonitorService { } return; } - List fishIds = list.stream() - .map(item -> StrUtil.blankToDefault(item.getZyFishId(), item.getId())) - .filter(StrUtil::isNotBlank) - .distinct() - .toList(); - if (CollUtil.isEmpty(fishIds)) { - return; - } - Map paramMap = new HashMap<>(); - List placeholders = new ArrayList<>(); - for (int i = 0; i < fishIds.size(); i++) { - String key = "zyFishId" + i; - paramMap.put(key, fishIds.get(i)); - placeholders.add("#{map." + key + "}"); - } - String sql = "SELECT rel.ZY_FISH_ID AS zyFishId, rv.RVNM AS rvcdName " + - "FROM SD_FISHDICTORY_RLTN_B rel " + - "LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = rel.RVCD " + - "WHERE rel.ZY_FISH_ID IN (" + String.join(", ", placeholders) + ") " + - "AND rel.RVCD <> 'ZY' " + - "AND NVL(rel.IS_DELETED, 0) = 0 " + - "AND rv.RVNM IS NOT NULL"; - List> rows = microservicDynamicSQLMapper.getAllList(sql, paramMap); - Map> rvcdNameMap = new HashMap<>(); - for (Map row : rows) { - Object fishId = row.get("ZYFISHID"); - Object rvcdName = row.get("RVCDNAME"); - if (fishId == null || rvcdName == null) { - continue; - } - rvcdNameMap.computeIfAbsent(String.valueOf(fishId), key -> new ArrayList<>()) - .add(String.valueOf(rvcdName)); - } for (FprZyFishDicVo item : list) { - if (item == null) { - continue; + if (item != null && item.getRvcdName() == null) { + item.setRvcdName(""); } - String fishKey = StrUtil.blankToDefault(item.getZyFishId(), item.getId()); - List names = rvcdNameMap.getOrDefault(fishKey, new ArrayList<>()).stream() - .filter(StrUtil::isNotBlank) - .distinct() - .toList(); - item.setRvcdName(String.join(",", names)); } } From 75adb3836b6e4c7b548f055d20126288e3c9af62 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 23 Jun 2026 10:01:50 +0800 Subject: [PATCH 17/38] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java index e4b17aca..549b34fa 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java @@ -154,7 +154,7 @@ public class VdMonitorServiceImpl implements VdMonitorService { .append("t.statusTm AS statusTm ") .append("FROM (") .append(buildVdTreeCoreSql()) - .append(") t WHERE 1 = 1 "); + .append(") t WHERE 1 = 1 AND t.sttpCode != 'VD_FPRD'"); if (StrUtil.isNotBlank(filterSql)) { sql.append(" AND ").append(filterSql).append(" "); } From 6b30e5552861c305de3a80fd1f968bc440c1ef13 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 23 Jun 2026 10:10:24 +0800 Subject: [PATCH 18/38] =?UTF-8?q?fix:=20=E9=B1=BC=E7=B1=BB=E8=B0=83?= =?UTF-8?q?=E6=9F=A5=E8=A3=85=E7=BD=AE=E6=95=B0=E6=8D=AE=E5=BA=93=E8=A1=A8?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fpr/service/impl/FprMonitorServiceImpl.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java index 8bef55ff..09b35d14 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java @@ -336,7 +336,7 @@ public class FprMonitorServiceImpl implements FprMonitorService { "NVL(alongBase.ORDER_INDEX, 999999) AS rvcdStepSort, " + "NVL(engSort.SORT, 999999) AS rstcdStepSort, " + "NVL(siteSort.SORT, NVL(src.ORDER_INDEX, 999999)) AS siteStepSort " + - "FROM SD_FPRD_B_H src " + + "FROM SD_AIMONITOR_B_H src " + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = src.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = src.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = src.HBRVCD " + @@ -372,13 +372,13 @@ public class FprMonitorServiceImpl implements FprMonitorService { private String buildFprdRunDataInfoSql(FprdRunDataAo ao) { StringBuilder sql = new StringBuilder("SELECT ") .append("NVL((SELECT COUNT(1) ") - .append(" FROM SD_FPRD_B_H baseCnt ") + .append(" FROM SD_AIMONITOR_B_H baseCnt ") .append(" WHERE NVL(baseCnt.IS_DELETED, 0) = 0 ") .append(" AND baseCnt.STTP = 'FPRD' ") .append(" AND baseCnt.BASE_ID = #{map.baseId}), 0) AS fprdCount, ") .append("NVL((SELECT COUNT(DISTINCT fish.NAME) ") .append(" FROM SD_FPRD_R run ") - .append(" INNER JOIN SD_FPRD_B_H base ON base.STCD = run.STCD ") + .append(" INNER JOIN SD_AIMONITOR_B_H base ON base.STCD = run.STCD ") .append(" AND NVL(base.IS_DELETED, 0) = 0 ") .append(" AND base.STTP = 'FPRD' ") .append(" INNER JOIN SD_FPRDFISH_R fish ON fish.FPRDR_ID = run.ID ") @@ -392,7 +392,7 @@ public class FprMonitorServiceImpl implements FprMonitorService { sql.append("), 0) AS ftpCount, ") .append("NVL((SELECT COUNT(1) ") .append(" FROM SD_FPRD_R run ") - .append(" INNER JOIN SD_FPRD_B_H base ON base.STCD = run.STCD ") + .append(" INNER JOIN SD_AIMONITOR_B_H base ON base.STCD = run.STCD ") .append(" AND NVL(base.IS_DELETED, 0) = 0 ") .append(" AND base.STTP = 'FPRD' ") .append(" INNER JOIN SD_FPRDFISH_R fish ON fish.FPRDR_ID = run.ID ") @@ -415,7 +415,7 @@ public class FprMonitorServiceImpl implements FprMonitorService { .append("TO_NUMBER(TO_CHAR(run.TM, 'MM')) AS month, ") .append("TO_NUMBER(TO_CHAR(run.TM, 'YYYY')) AS year ") .append("FROM SD_FPRD_R run ") - .append("INNER JOIN SD_FPRD_B_H base ON base.STCD = run.STCD ") + .append("INNER JOIN SD_AIMONITOR_B_H base ON base.STCD = run.STCD ") .append(" AND NVL(base.IS_DELETED, 0) = 0 ") .append(" AND base.STTP = 'FPRD' ") .append("INNER JOIN SD_FPRDFISH_R fish ON fish.FPRDR_ID = run.ID ") @@ -442,7 +442,7 @@ public class FprMonitorServiceImpl implements FprMonitorService { "fish.FSZ AS fsz, " + "fish.WEIGHT AS weight " + "FROM SD_FPRD_R run " + - "INNER JOIN SD_FPRD_B_H base ON run.STCD = base.STCD " + + "INNER JOIN SD_AIMONITOR_B_H base ON run.STCD = base.STCD " + " AND base.STTP = 'FPRD' " + " AND NVL(base.IS_DELETED, 0) = 0 " + "INNER JOIN SD_FPRDFISH_R fish ON run.ID = fish.FPRDR_ID " + From 23f3a73cf986db7f1642e89fcfb447f0645556e7 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 23 Jun 2026 13:51:25 +0800 Subject: [PATCH 19/38] =?UTF-8?q?feat:=20=E7=94=B5=E7=AB=99=E6=B0=B4?= =?UTF-8?q?=E4=BD=8D=E3=80=81=E7=94=9F=E6=80=81=E6=B5=81=E9=87=8F=E5=91=8A?= =?UTF-8?q?=E8=AD=A6=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; + }; + } +} From 1942b6c1934a67aff0a2d84702f4a8998b43b969 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 23 Jun 2026 14:11:59 +0800 Subject: [PATCH 20/38] =?UTF-8?q?feat:=20=E9=B1=BC=E7=B1=BB=E5=A2=9E?= =?UTF-8?q?=E6=AE=96=E7=AB=99=E5=9F=BA=E7=A1=80=E4=BF=A1=E6=81=AF=E5=88=97?= =?UTF-8?q?=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fb/controller/FbMsstbprptController.java | 29 ++ .../qgc_env/fb/service/FbStationService.java | 3 + .../fb/service/impl/FbStationServiceImpl.java | 458 ++++++++++++++++++ 3 files changed, 490 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbMsstbprptController.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbMsstbprptController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbMsstbprptController.java new file mode 100644 index 00000000..7f05ee42 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbMsstbprptController.java @@ -0,0 +1,29 @@ +package com.yfd.platform.qgc_env.fb.controller; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.qgc_env.fb.service.FbStationService; +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("/fb/msstbprpt") +@Tag(name = "鱼类增殖站基础信息") +@Validated +public class FbMsstbprptController { + + @Resource + private FbStationService fbStationService; + + @PostMapping("/GetKendoList") + @Operation(summary = "鱼类增殖站基础信息列表") + public ResponseResult getKendoList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getMsstbprptList(dataSourceRequest)); + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java index 66d93a2b..34383566 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java @@ -14,6 +14,7 @@ import com.yfd.platform.qgc_env.fb.entity.vo.YearRpStatisticsVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbStationOverviewSecondVo; import java.util.List; +import java.util.Map; public interface FbStationService { @@ -21,6 +22,8 @@ public interface FbStationService { DataSourceResult getOverviewKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult> getMsstbprptList(DataSourceRequest dataSourceRequest); + DataSourceResult getFbFlDataKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getQgcMsfbrdmKendoListCust(DataSourceRequest dataSourceRequest); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java index ec88961c..05dcfbcb 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java @@ -83,6 +83,65 @@ public class FbStationServiceImpl implements FbStationService { return queryFbFlDataDetailList(dataSourceRequest, loadOptions); } + @Override + public DataSourceResult> getMsstbprptList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Map paramMap = new HashMap<>(); + String filterSql = buildFbMsstbprptFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + + if (CollUtil.isNotEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + StringBuilder groupedBaseSql = new StringBuilder("SELECT * FROM (") + .append(buildFbMsstbprptBaseSql()) + .append(") t WHERE 1 = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + groupedBaseSql.append(" AND ").append(filterSql).append(" "); + } + String groupedSql = buildFbMsstbprptGroupSql(groupedBaseSql.toString(), dataSourceRequest.getGroup()); + List> rows = microservicDynamicSQLMapper.pageAllList(null, groupedSql, paramMap); + + DataSourceResult> result = new DataSourceResult<>(); + GroupingInfo[] groupInfos = loadOptions == null ? null : loadOptions.getGroup(); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List>) (List) new GroupHelper().faltGroup( + rows, + groupInfos == null ? Collections.emptyList() : Arrays.asList(groupInfos) + )); + } else { + result.setData((List>) (List) new GroupHelper().group( + rows, + groupInfos == null ? Collections.emptyList() : Arrays.asList(groupInfos) + )); + } + result.setTotal(rows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + List selectedFields = resolveFbMsstbprptSelectFields(dataSourceRequest == null ? null : dataSourceRequest.getSelect()); + StringBuilder sql = new StringBuilder("SELECT ") + .append(buildFbMsstbprptDetailSelectSql(selectedFields)) + .append(" FROM (") + .append(buildFbMsstbprptBaseSql()) + .append(") t WHERE 1 = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildFbMsstbprptOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List> rows = microservicDynamicSQLMapper.pageAllList(page, sql.toString(), paramMap); + + DataSourceResult> result = new DataSourceResult<>(); + result.setData(normalizeFbMsstbprptRows(rows, selectedFields)); + result.setTotal(page != null ? page.getTotal() : rows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + @Override public DataSourceResult getQgcMsfbrdmKendoListCust(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -344,6 +403,405 @@ public class FbStationServiceImpl implements FbStationService { return result; } + private String buildFbMsstbprptBaseSql() { + return "SELECT " + + "fb.STCD AS stcd, " + + "fb.STCD AS id, " + + "fb.STNM AS stnm, " + + "fb.STTP AS sttp, " + + "fb.STTP AS sttpCode, " + + "sttp.STTP_NAME AS sttpName, " + + "sttp.FULL_PATH AS sttpFullPath, " + + "sttp.TREE_LEVEL AS sttpTreeLevel, " + + "fb.LGTD AS lgtd, " + + "fb.LTTD AS lttd, " + + "fb.ELEV AS dtmel, " + + "fb.STLC AS stlc, " + + "fb.USFL AS usfl, " + + "fb.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "fb.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName, " + + "fb.HBRVCD AS hbrvcd, " + + "hbrv.HBRVNM AS hbrvcdName, " + + "eng.RVCD AS rvcd, " + + "rv.RVNM AS rvcdName, " + + "eng.ADDVCD AS addvcd, " + + "addv.ADDVNM AS addvcdName, " + + "eng.COUNTRY AS country, " + + "country.COUNTRY_NAME AS countryName, " + + "eng.HYCD AS hycd, " + + "CAST(NULL AS VARCHAR2(200)) AS hynm, " + + "fb.STDSDT AS stdsdt, " + + "fb.PSTSTDT AS pststdt, " + + "fb.PESSTDT AS pesstdt, " + + "fb.SWDT AS ststdt, " + + "fb.JCDT AS jcdt, " + + "fb.WDDT AS stwddt, " + + "fb.INTRODUCE AS introduce, " + + "fb.INTRODUCE AS precis, " + + "fb.LOGO AS logo, " + + "fb.INFFILE AS inffile, " + + "fb.DTIN AS dtin, " + + "CASE NVL(fb.DTIN, 0) WHEN 1 THEN '是' WHEN 0 THEN '否' ELSE NULL END AS dtinName, " + + "fb.DTIN_TM AS dtinTm, " + + "fb.BLDSTT_CODE AS bldsttCode, " + + "CASE fb.BLDSTT_CODE WHEN 0 THEN '0' WHEN 1 THEN '1' WHEN 2 THEN '2' ELSE NULL END AS bldsttCcode, " + + "CASE fb.BLDSTT_CODE WHEN 0 THEN '未建/规划' WHEN 1 THEN '在建' WHEN 2 THEN '已建' ELSE NULL END AS bldsttCcodeName, " + + "fb.INV AS inv, " + + "fb.INVINMN AS invinmn, " + + "fb.ZZFLAR AS zzflar, " + + "fb.ZZFLGY AS zzflgy, " + + "fb.ZZFLYZMS AS zzflyzms, " + + "fb.ZZFLBJFS AS zzflbjfs, " + + "fb.ZZFLDX AS zzfldx, " + + "fb.ZZFLCNT AS zzflcnt, " + + "fb.ZZFLFLLC AS zzflfllc, " + + "fb.ZZFLTM AS zzfltm, " + + "fb.ZZFLRW AS zzflrw, " + + "fb.DSUN AS dsun, " + + "fb.JBTXCS AS jbtxcs, " + + "fb.DTFRQCY AS dtfrqcy, " + + "fb.REMARK AS remark, " + + "fb.VLSR AS vlsr, " + + "fb.VLSR_TM AS vlsrTm, " + + "fb.ORDER_INDEX AS orderIndex " + + "FROM SD_FBRD_B_H fb " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = fb.STTP AND NVL(sttp.ENABLE, 1) = 1 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fb.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = fb.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = fb.HBRVCD AND hbrv.BASEID = fb.BASE_ID " + + " AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 " + + "LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = eng.RVCD " + + "LEFT JOIN SD_ADDVCD_DIC addv ON addv.ADDVCD = eng.ADDVCD " + + "LEFT JOIN SD_COUNTRY_B country ON country.COUNTRY_ID = eng.COUNTRY AND NVL(country.ENABLED, 1) = 1 "; + } + + private List resolveFbMsstbprptSelectFields(List select) { + List fields = CollUtil.isEmpty(select) + ? new ArrayList<>(List.of( + "stcd", "stnm", "sttpCode", "sttpName", "lgtd", "lttd", "stlc", "rstcd", "ennm", + "baseId", "baseName", "hbrvcd", "hbrvcdName", "introduce", "logo", "precis", + "dtin", "dtinName", "dtinTm", "bldsttCcode", "bldsttCcodeName", "inv", + "zzflar", "zzflgy", "zzflyzms", "zzflbjfs", "zzfldx", "zzflcnt", "zzflfllc", + "zzfltm", "zzflrw", "dsun", "jbtxcs", "dtfrqcy", "remark", "vlsr", "vlsrTm" + )) + : new ArrayList<>(select); + LinkedHashSet uniqueFields = new LinkedHashSet<>(); + for (String field : fields) { + if (StrUtil.isNotBlank(field)) { + uniqueFields.add(field.trim()); + } + } + if (uniqueFields.isEmpty()) { + uniqueFields.add("stcd"); + } + return new ArrayList<>(uniqueFields); + } + + private String buildFbMsstbprptDetailSelectSql(List selectFields) { + List selectParts = new ArrayList<>(); + for (String field : selectFields) { + String column = mapFbMsstbprptColumn(field); + if (StrUtil.isNotBlank(column)) { + selectParts.add(column + " AS \"" + field + "\""); + } else { + selectParts.add("NULL AS \"" + field + "\""); + } + } + if (selectParts.isEmpty()) { + selectParts.add("t.stcd AS \"stcd\""); + } + return String.join(", ", selectParts); + } + + private String buildFbMsstbprptFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildFbMsstbprptLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildFbMsstbprptFilterCondition(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 buildFbMsstbprptLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapFbMsstbprptColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + 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 = normalizeFbMsstbprptValues(value); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String key = "fbMsstbprptP" + indexHolder[0]++; + paramMap.put(key, item); + placeholders.add("#{map." + key + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + + String key = "fbMsstbprptP" + indexHolder[0]++; + return switch (operator) { + case "eq" -> { + paramMap.put(key, value); + yield column + " = #{map." + key + "}"; + } + case "neq" -> { + paramMap.put(key, value); + yield column + " <> #{map." + key + "}"; + } + case "contains" -> { + paramMap.put(key, "%" + value + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, value + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + value); + yield column + " LIKE #{map." + key + "}"; + } + case "gt" -> { + paramMap.put(key, value); + yield column + " > #{map." + key + "}"; + } + case "gte" -> { + paramMap.put(key, value); + yield column + " >= #{map." + key + "}"; + } + case "lt" -> { + paramMap.put(key, value); + yield column + " < #{map." + key + "}"; + } + case "lte" -> { + paramMap.put(key, value); + yield column + " <= #{map." + key + "}"; + } + default -> ""; + }; + } + + private String buildFbMsstbprptOrderBySql(List sortDescriptors) { + if (CollUtil.isEmpty(sortDescriptors)) { + return " ORDER BY t.baseId ASC, t.orderIndex ASC, t.stcd ASC"; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor descriptor : sortDescriptors) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapFbMsstbprptColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction); + } + if (orderByParts.isEmpty()) { + return " ORDER BY t.baseId ASC, t.orderIndex ASC, t.stcd ASC"; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + private String buildFbMsstbprptGroupSql(String baseSql, List groups) { + if (CollUtil.isEmpty(groups)) { + return baseSql; + } + List validGroups = groups.stream() + .filter(Objects::nonNull) + .filter(group -> StrUtil.isNotBlank(group.getField())) + .filter(group -> StrUtil.isNotBlank(mapFbMsstbprptColumn(group.getField()))) + .toList(); + if (validGroups.isEmpty()) { + return baseSql; + } + List selectParts = new ArrayList<>(); + List groupByParts = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : validGroups) { + String column = mapFbMsstbprptColumn(descriptor.getField()); + selectParts.add(column + " AS " + descriptor.getField().toUpperCase()); + selectParts.add("COUNT(*) AS COUNT_" + descriptor.getField().toUpperCase()); + groupByParts.add(column); + } + return "SELECT " + String.join(", ", selectParts) + + " FROM (" + baseSql + ") t GROUP BY " + String.join(", ", groupByParts) + + buildFbMsstbprptGroupOrderBySql(validGroups); + } + + private String buildFbMsstbprptGroupOrderBySql(List groups) { + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + String column = mapFbMsstbprptColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction); + } + if (orderByParts.isEmpty()) { + return ""; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + private String mapFbMsstbprptColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "id" -> "t.id"; + case "stcd" -> "t.stcd"; + case "stnm" -> "t.stnm"; + case "sttp" -> "t.sttp"; + case "sttpCode" -> "t.sttpCode"; + case "sttpName" -> "t.sttpName"; + case "sttpFullPath" -> "t.sttpFullPath"; + case "sttpTreeLevel" -> "t.sttpTreeLevel"; + case "lgtd" -> "t.lgtd"; + case "lttd" -> "t.lttd"; + case "dtmel" -> "t.dtmel"; + case "stlc" -> "t.stlc"; + case "usfl" -> "t.usfl"; + case "rstcd" -> "t.rstcd"; + case "ennm" -> "t.ennm"; + case "baseId" -> "t.baseId"; + case "baseName" -> "t.baseName"; + case "hbrvcd" -> "t.hbrvcd"; + case "hbrvcdName" -> "t.hbrvcdName"; + case "rvcd" -> "t.rvcd"; + case "rvcdName" -> "t.rvcdName"; + case "addvcd" -> "t.addvcd"; + case "addvcdName" -> "t.addvcdName"; + case "country" -> "t.country"; + case "countryName" -> "t.countryName"; + case "hycd" -> "t.hycd"; + case "hynm" -> "t.hynm"; + case "stdsdt" -> "t.stdsdt"; + case "pststdt" -> "t.pststdt"; + case "pesstdt" -> "t.pesstdt"; + case "ststdt" -> "t.ststdt"; + case "jcdt" -> "t.jcdt"; + case "stwddt" -> "t.stwddt"; + case "introduce" -> "t.introduce"; + case "precis" -> "t.precis"; + case "logo" -> "t.logo"; + case "inffile" -> "t.inffile"; + case "dtin" -> "t.dtin"; + case "dtinName" -> "t.dtinName"; + case "dtinTm" -> "t.dtinTm"; + case "bldsttCode" -> "t.bldsttCode"; + case "bldsttCcode" -> "t.bldsttCcode"; + case "bldsttCcodeName" -> "t.bldsttCcodeName"; + case "inv" -> "t.inv"; + case "invinmn" -> "t.invinmn"; + case "zzflar" -> "t.zzflar"; + case "zzflgy" -> "t.zzflgy"; + case "zzflyzms" -> "t.zzflyzms"; + case "zzflbjfs" -> "t.zzflbjfs"; + case "zzfldx" -> "t.zzfldx"; + case "zzflcnt" -> "t.zzflcnt"; + case "zzflfllc" -> "t.zzflfllc"; + case "zzfltm" -> "t.zzfltm"; + case "zzflrw" -> "t.zzflrw"; + case "dsun" -> "t.dsun"; + case "jbtxcs" -> "t.jbtxcs"; + case "dtfrqcy" -> "t.dtfrqcy"; + case "remark" -> "t.remark"; + case "vlsr" -> "t.vlsr"; + case "vlsrTm" -> "t.vlsrTm"; + case "orderIndex" -> "t.orderIndex"; + default -> null; + }; + } + + private List normalizeFbMsstbprptValues(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 List> normalizeFbMsstbprptRows(List> rows, List fields) { + if (CollUtil.isEmpty(rows)) { + return Collections.emptyList(); + } + List> result = new ArrayList<>(); + for (Map row : rows) { + Map normalizedRow = new LinkedHashMap<>(); + for (String field : fields) { + normalizedRow.put(field, getIgnoreCaseValue(row, field)); + } + result.add(normalizedRow); + } + return result; + } + + private Object getIgnoreCaseValue(Map row, String field) { + if (row == null || StrUtil.isBlank(field)) { + return null; + } + if (row.containsKey(field)) { + return row.get(field); + } + for (Map.Entry entry : row.entrySet()) { + if (entry.getKey() != null && entry.getKey().equalsIgnoreCase(field)) { + return entry.getValue(); + } + } + return null; + } + private String buildOverviewStationListSql(String baseId, List stcdList, Map paramMap) { From 9b811cb1c9a6b1465e19aca2253c57ef439dae02 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 23 Jun 2026 14:15:46 +0800 Subject: [PATCH 21/38] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fb/controller/FbBsmfrController.java | 35 ----------- .../fb/controller/FbFbrdmrController.java | 30 ---------- .../fb/controller/FbMsfbrdmController.java | 35 ----------- .../fb/controller/FbMsstbprptController.java | 29 --------- .../fb/controller/FbResearchbController.java | 29 --------- .../fb/controller/FbStationController.java | 59 ++++++++++++++++--- 6 files changed, 51 insertions(+), 166 deletions(-) delete mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbBsmfrController.java delete mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbFbrdmrController.java delete mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbMsfbrdmController.java delete mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbMsstbprptController.java delete mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbResearchbController.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbBsmfrController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbBsmfrController.java deleted file mode 100644 index 4eb347f0..00000000 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbBsmfrController.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.yfd.platform.qgc_env.fb.controller; - -import com.yfd.platform.common.DataSourceRequest; -import com.yfd.platform.config.ResponseResult; -import com.yfd.platform.qgc_env.fb.service.FbStationService; -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("/fb/bsmfr") -@Tag(name = "亲鱼选配与培育-亲鱼信息") -@Validated -public class FbBsmfrController { - - @Resource - private FbStationService fbStationService; - - @PostMapping("/qgc/GetKendoListCust") - @Operation(summary = "(全过程)增殖站二级页面: 亲鱼选配与培育->亲鱼信息") - public ResponseResult getQgcKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { - return ResponseResult.successData(fbStationService.getQgcBsmfRKendoListCust(dataSourceRequest)); - } - - @PostMapping("/fish/GetKendoListCust") - @Operation(summary = "(全过程)增殖站二级页面: 过程图-亲鱼") - public ResponseResult getFishKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { - return ResponseResult.successData(fbStationService.getBsmfRFishKendoListCust(dataSourceRequest)); - } -} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbFbrdmrController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbFbrdmrController.java deleted file mode 100644 index ea102a41..00000000 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbFbrdmrController.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.yfd.platform.qgc_env.fb.controller; - -import com.yfd.platform.config.ResponseResult; -import com.yfd.platform.qgc_env.fb.service.FbStationService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/fb/fbrdmr") -@Tag(name = "鱼类增殖站年度鱼类标记数据") -@Validated -public class FbFbrdmrController { - - @Resource - private FbStationService fbStationService; - - @GetMapping("/getFbRelatedYrByStcd") - @Operation(summary = "根据增殖站编码查询相关业务年份") - public ResponseResult getFbRelatedYrByStcd(@Parameter(description = "增殖站编码") - @RequestParam("stcd") String stcd) { - return ResponseResult.successData(fbStationService.getFbRelatedYrByStcd(stcd)); - } -} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbMsfbrdmController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbMsfbrdmController.java deleted file mode 100644 index 3a70e79a..00000000 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbMsfbrdmController.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.yfd.platform.qgc_env.fb.controller; - -import com.yfd.platform.common.DataSourceRequest; -import com.yfd.platform.config.ResponseResult; -import com.yfd.platform.qgc_env.fb.service.FbStationService; -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("/fb/msfbrdm") -@Tag(name = "鱼类增殖站增殖情况") -@Validated -public class FbMsfbrdmController { - - @Resource - private FbStationService fbStationService; - - @PostMapping("/fbFlData/GetKendoListCust") - @Operation(summary = "增殖站增殖情况(app)") - public ResponseResult getFbFlData(@RequestBody DataSourceRequest dataSourceRequest) { - return ResponseResult.successData(fbStationService.getFbFlDataKendoListCust(dataSourceRequest)); - } - - @PostMapping("/qgc/GetKendoListCust") - @Operation(summary = "(全过程)增殖站二级页面: 增殖放流情况") - public ResponseResult getQgcKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { - return ResponseResult.successData(fbStationService.getQgcMsfbrdmKendoListCust(dataSourceRequest)); - } -} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbMsstbprptController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbMsstbprptController.java deleted file mode 100644 index 7f05ee42..00000000 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbMsstbprptController.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.yfd.platform.qgc_env.fb.controller; - -import com.yfd.platform.common.DataSourceRequest; -import com.yfd.platform.config.ResponseResult; -import com.yfd.platform.qgc_env.fb.service.FbStationService; -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("/fb/msstbprpt") -@Tag(name = "鱼类增殖站基础信息") -@Validated -public class FbMsstbprptController { - - @Resource - private FbStationService fbStationService; - - @PostMapping("/GetKendoList") - @Operation(summary = "鱼类增殖站基础信息列表") - public ResponseResult getKendoList(@RequestBody DataSourceRequest dataSourceRequest) { - return ResponseResult.successData(fbStationService.getMsstbprptList(dataSourceRequest)); - } -} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbResearchbController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbResearchbController.java deleted file mode 100644 index 4861d4c1..00000000 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbResearchbController.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.yfd.platform.qgc_env.fb.controller; - -import com.yfd.platform.common.DataSourceRequest; -import com.yfd.platform.config.ResponseResult; -import com.yfd.platform.qgc_env.fb.service.FbStationService; -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("/fb/base/researchb") -@Tag(name = "鱼类增殖站科研情况") -@Validated -public class FbResearchbController { - - @Resource - private FbStationService fbStationService; - - @PostMapping("/GetKendoList") - @Operation(summary = "鱼类增殖站科研情况列表") - public ResponseResult getKendoList(@RequestBody DataSourceRequest dataSourceRequest) { - return ResponseResult.successData(fbStationService.getResearchKendoList(dataSourceRequest)); - } -} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java index 169d8762..fbb233d6 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java @@ -16,47 +16,90 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController -@RequestMapping("/fb/station") -@Tag(name = "鱼类增殖站概况") +@RequestMapping("/fb") +@Tag(name = "鱼类增殖站模块") @Validated public class FbStationController { @Resource private FbStationService fbStationService; - @PostMapping("/qgcoverview/getOverviewSecond") + @PostMapping("/station/qgcoverview/getOverviewSecond") @Operation(summary = "全流域增殖站概况二级页面") public ResponseResult getQgcOverviewSecond(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(fbStationService.getQgcOverviewSecond(dataSourceRequest)); } - @PostMapping("/overview/getOverviewSecond") + @PostMapping("/station/overview/getOverviewSecond") @Operation(summary = "增殖站概况二级页面") public ResponseResult getOverviewSecond(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(fbStationService.getOverviewSecond(dataSourceRequest)); } - @PostMapping("/overview/GetKendoListCust") + @PostMapping("/station/overview/GetKendoListCust") @Operation(summary = "全流域增殖站概况") public ResponseResult getOverviewKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(fbStationService.getOverviewKendoListCust(dataSourceRequest)); } - @PostMapping("/qgc/getFbStaticsData") + @PostMapping("/station/qgc/getFbStaticsData") @Operation(summary = "增殖站放流数据统计") public ResponseResult getQgcFbStaticsData(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(fbStationService.getQgcFbStaticsData(dataSourceRequest)); } - @GetMapping("/msstbprpt/getStInfoByStcd") + @GetMapping("/station/msstbprpt/getStInfoByStcd") @Operation(summary = "增殖站单站基础信息") public ResponseResult getStInfoByStcd(@Parameter(description = "站点编码") @RequestParam("stcd") String stcd) { return ResponseResult.successData(fbStationService.getStInfoByStcd(stcd)); } - @GetMapping("/rpimnr/qgc/year/GetYearRpStatistics") + @GetMapping("/station/rpimnr/qgc/year/GetYearRpStatistics") @Operation(summary = "全过程放流统计总数,根据基地流域分组") public ResponseResult getYearRpStatistics(@Parameter(description = "年份") @RequestParam("year") String year) { return ResponseResult.successData(fbStationService.getYearRpStatistics(year)); } + + @PostMapping("/bsmfr/qgc/GetKendoListCust") + @Operation(summary = "(全过程)增殖站二级页面: 亲鱼选配与培育->亲鱼信息") + public ResponseResult getBsmfrQgcKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getQgcBsmfRKendoListCust(dataSourceRequest)); + } + + @PostMapping("/bsmfr/fish/GetKendoListCust") + @Operation(summary = "(全过程)增殖站二级页面: 过程图-亲鱼") + public ResponseResult getBsmfrFishKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getBsmfRFishKendoListCust(dataSourceRequest)); + } + + @GetMapping("/fbrdmr/getFbRelatedYrByStcd") + @Operation(summary = "根据增殖站编码查询相关业务年份") + public ResponseResult getFbRelatedYrByStcd(@Parameter(description = "增殖站编码") + @RequestParam("stcd") String stcd) { + return ResponseResult.successData(fbStationService.getFbRelatedYrByStcd(stcd)); + } + + @PostMapping("/msfbrdm/fbFlData/GetKendoListCust") + @Operation(summary = "增殖站增殖情况(app)") + public ResponseResult getFbFlData(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getFbFlDataKendoListCust(dataSourceRequest)); + } + + @PostMapping("/msfbrdm/qgc/GetKendoListCust") + @Operation(summary = "(全过程)增殖站二级页面: 增殖放流情况") + public ResponseResult getMsfbrdmQgcKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getQgcMsfbrdmKendoListCust(dataSourceRequest)); + } + + @PostMapping("/msstbprpt/GetKendoList") + @Operation(summary = "鱼类增殖站基础信息列表") + public ResponseResult getMsstbprptKendoList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getMsstbprptList(dataSourceRequest)); + } + + @PostMapping("/base/researchb/GetKendoList") + @Operation(summary = "鱼类增殖站科研情况列表") + public ResponseResult getResearchKendoList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getResearchKendoList(dataSourceRequest)); + } } From 72677ee0e572d5be51d9e7d65a0a4931e7ad70ec Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 23 Jun 2026 14:28:12 +0800 Subject: [PATCH 22/38] =?UTF-8?q?feat:=20=E9=B1=BC=E7=B1=BB=E5=A2=9E?= =?UTF-8?q?=E6=AE=96=E7=AB=99=E8=BF=90=E8=A1=8C=E6=83=85=E5=86=B5=E7=BB=9F?= =?UTF-8?q?=E8=AE=A1=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../platform/qgc_env/fb/controller/FbStationController.java | 6 ++++++ .../yfd/platform/qgc_env/fb/service/FbStationService.java | 2 ++ .../qgc_env/fb/service/impl/FbStationServiceImpl.java | 5 +++++ 3 files changed, 13 insertions(+) diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java index fbb233d6..365c2b13 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java @@ -85,6 +85,12 @@ public class FbStationController { return ResponseResult.successData(fbStationService.getFbFlDataKendoListCust(dataSourceRequest)); } + @PostMapping("/msfbrdm/GetKendoListCust") + @Operation(summary = "鱼类增殖站运行情况统计列表") + public ResponseResult getMsfbrdmKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getMsfbrdmKendoListCust(dataSourceRequest)); + } + @PostMapping("/msfbrdm/qgc/GetKendoListCust") @Operation(summary = "(全过程)增殖站二级页面: 增殖放流情况") public ResponseResult getMsfbrdmQgcKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java index 34383566..5b5976c0 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java @@ -26,6 +26,8 @@ public interface FbStationService { DataSourceResult getFbFlDataKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getMsfbrdmKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getQgcMsfbrdmKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getQgcBsmfRKendoListCust(DataSourceRequest dataSourceRequest); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java index 05dcfbcb..d9291274 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java @@ -142,6 +142,11 @@ public class FbStationServiceImpl implements FbStationService { return result; } + @Override + public DataSourceResult getMsfbrdmKendoListCust(DataSourceRequest dataSourceRequest) { + return getQgcMsfbrdmKendoListCust(dataSourceRequest); + } + @Override public DataSourceResult getQgcMsfbrdmKendoListCust(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); From 64ef59380df0ad30cdd31709b4e4fa91ec036a29 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 23 Jun 2026 14:47:17 +0800 Subject: [PATCH 23/38] =?UTF-8?q?feat:=20=E5=A2=9E=E6=AE=96=E7=AB=99?= =?UTF-8?q?=E9=B1=BC=E7=A7=8D=E5=AE=8C=E6=88=90=E6=83=85=E5=86=B5=E7=BB=9F?= =?UTF-8?q?=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fb/controller/FbStationController.java | 6 + .../fb/entity/vo/FbFishTypeFinishVo.java | 13 ++ .../qgc_env/fb/service/FbStationService.java | 3 + .../fb/service/impl/FbStationServiceImpl.java | 153 ++++++++++++++++++ 4 files changed, 175 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishTypeFinishVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java index 365c2b13..ff227fa1 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java @@ -85,6 +85,12 @@ public class FbStationController { return ResponseResult.successData(fbStationService.getFbFlDataKendoListCust(dataSourceRequest)); } + @PostMapping("/fishType/GetKendoListCust") + @Operation(summary = "增殖站鱼种完成情况统计") + public ResponseResult getFishTypeKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getFishTypeKendoListCust(dataSourceRequest)); + } + @PostMapping("/msfbrdm/GetKendoListCust") @Operation(summary = "鱼类增殖站运行情况统计列表") public ResponseResult getMsfbrdmKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishTypeFinishVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishTypeFinishVo.java new file mode 100644 index 00000000..d930219e --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishTypeFinishVo.java @@ -0,0 +1,13 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import lombok.Data; + +@Data +public class FbFishTypeFinishVo { + + private String stcd; + + private Integer finished; + + private Integer unfinished; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java index 5b5976c0..1737b5fe 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java @@ -5,6 +5,7 @@ import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRQgcVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishTableVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFlDataVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbFishTypeFinishVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbRelatedYrVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbMsfbrdmQgcVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbResearchVo; @@ -26,6 +27,8 @@ public interface FbStationService { DataSourceResult getFbFlDataKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getFishTypeKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getMsfbrdmKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getQgcMsfbrdmKendoListCust(DataSourceRequest dataSourceRequest); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java index d9291274..e4404592 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java @@ -15,6 +15,7 @@ import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRQgcVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishHeadColumnVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishSummaryVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishTableVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbFishTypeFinishVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFtpStatisticsVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFlDataVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbMsfbrdmQgcVo; @@ -83,6 +84,38 @@ public class FbStationServiceImpl implements FbStationService { return queryFbFlDataDetailList(dataSourceRequest, loadOptions); } + @Override + public DataSourceResult getFishTypeKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String rstcdFilter = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); + String stcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd"); + String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + + Map paramMap = new HashMap<>(); + String sql = buildFishTypeFinishSql( + stcd, + parseFishTypeFilterValues(rstcdFilter), + parseFishTypeDate(startTime), + parseFishTypeDate(endTime), + paramMap + ) + buildFishTypeOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort()); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql, + paramMap, + FbFishTypeFinishVo.class + ); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + @Override public DataSourceResult> getMsstbprptList(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -807,6 +840,126 @@ public class FbStationServiceImpl implements FbStationService { return null; } + private String buildFishTypeFinishSql(String stcd, + List rstcdList, + Date startTime, + Date endTime, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT temp.stcd AS stcd, ") + .append("SUM(CASE WHEN temp.bftp IS NOT NULL THEN 1 ELSE 0 END) AS finished, ") + .append("SUM(CASE WHEN temp.aftp IS NOT NULL THEN 1 ELSE 0 END) AS unfinished ") + .append("FROM ( ") + .append("SELECT a.RSTCD AS stcd, a.FTP AS aftp, b.FTP AS bftp ") + .append("FROM ( ") + .append("SELECT jhr.RSTCD, jhrs.FTP ") + .append("FROM SD_ENGFRPLAN_B jhr ") + .append("JOIN SD_ENGFRPLANDET_B jhrs ON jhr.ID = jhrs.RPJH_ID ") + .append("WHERE NVL(jhr.IS_DELETED, 0) = 0 AND NVL(jhrs.IS_DELETED, 0) = 0 "); + appendFishTypeFilterSql(sql, "jhr", stcd, rstcdList, startTime, endTime, true, paramMap); + sql.append("GROUP BY jhr.RSTCD, jhrs.FTP ") + .append(") a ") + .append("LEFT JOIN ( ") + .append("SELECT imnr.RSTCD, imnrs.FTP ") + .append("FROM SD_ENGFR_R imnr ") + .append("JOIN SD_RPIMNFISH_R imnrs ON imnr.ID = imnrs.RPIMN_ID ") + .append("WHERE NVL(imnr.IS_DELETED, 0) = 0 AND NVL(imnrs.IS_DELETED, 0) = 0 "); + appendFishTypeFilterSql(sql, "imnr", stcd, rstcdList, startTime, endTime, false, paramMap); + sql.append("GROUP BY imnr.RSTCD, imnrs.FTP ") + .append(") b ON a.RSTCD = b.RSTCD AND a.FTP = b.FTP ") + .append(") temp ") + .append("GROUP BY temp.stcd"); + return sql.toString(); + } + + private void appendFishTypeFilterSql(StringBuilder sql, + String alias, + String stcd, + List rstcdList, + Date startTime, + Date endTime, + boolean planSide, + Map paramMap) { + if (StrUtil.isNotBlank(stcd)) { + String key = "fishType" + alias + "Stcd"; + paramMap.put(key, stcd.trim()); + sql.append(" AND ").append(alias).append(".RSTCD = #{map.").append(key).append("} "); + } + if (CollUtil.isNotEmpty(rstcdList)) { + List placeholders = new ArrayList<>(); + for (int i = 0; i < rstcdList.size(); i++) { + String key = "fishType" + alias + "Rstcd" + i; + paramMap.put(key, rstcdList.get(i)); + placeholders.add("#{map." + key + "}"); + } + sql.append(" AND ").append(alias).append(".STCD IN (").append(String.join(", ", placeholders)).append(") "); + } + if (startTime != null) { + String key = "fishType" + alias + "StartTime"; + paramMap.put(key, startTime); + sql.append(" AND ").append(alias).append(planSide ? ".PLANSD" : ".TM") + .append(" >= #{map.").append(key).append("} "); + } + if (endTime != null) { + String key = "fishType" + alias + "EndTime"; + paramMap.put(key, endTime); + sql.append(" AND ").append(alias).append(planSide ? ".PLANED" : ".TM") + .append(" <= #{map.").append(key).append("} "); + } + } + + private String buildFishTypeOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return " ORDER BY stcd ASC"; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = switch (sort.getField()) { + case "stcd" -> "stcd"; + case "finished" -> "finished"; + case "unfinished" -> "unfinished"; + default -> null; + }; + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction); + } + if (orderByParts.isEmpty()) { + return " ORDER BY stcd ASC"; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + private List parseFishTypeFilterValues(String rawValue) { + if (StrUtil.isBlank(rawValue)) { + return Collections.emptyList(); + } + return Arrays.stream(rawValue.replace("[", "") + .replace("]", "") + .replace("\"", "") + .split(",")) + .map(String::trim) + .filter(StrUtil::isNotBlank) + .distinct() + .toList(); + } + + private Date parseFishTypeDate(String value) { + if (StrUtil.isBlank(value)) { + return null; + } + try { + return DateUtil.parse(value.trim()); + } catch (Exception ex) { + return null; + } + } + private String buildOverviewStationListSql(String baseId, List stcdList, Map paramMap) { From 101c60e8c0b4857829bd568a8fa5c1cff8dcd30a Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 23 Jun 2026 15:07:26 +0800 Subject: [PATCH 24/38] =?UTF-8?q?feat:=20=E5=A2=9E=E6=AE=96=E7=AB=99?= =?UTF-8?q?=E9=B1=BC=E6=95=B0=E9=87=8F=E5=AE=8C=E6=88=90=E6=83=85=E5=86=B5?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fb/controller/FbStationController.java | 6 ++ .../fb/entity/vo/FbFishCountFinishVo.java | 15 ++++ .../qgc_env/fb/service/FbStationService.java | 3 + .../fb/service/impl/FbStationServiceImpl.java | 90 +++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishCountFinishVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java index ff227fa1..68489d04 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java @@ -85,6 +85,12 @@ public class FbStationController { return ResponseResult.successData(fbStationService.getFbFlDataKendoListCust(dataSourceRequest)); } + @PostMapping("/fishCount/GetKendoListCust") + @Operation(summary = "增殖站鱼数量完成情况统计") + public ResponseResult getFishCountKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getFishCountKendoListCust(dataSourceRequest)); + } + @PostMapping("/fishType/GetKendoListCust") @Operation(summary = "增殖站鱼种完成情况统计") public ResponseResult getFishTypeKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishCountFinishVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishCountFinishVo.java new file mode 100644 index 00000000..4a7a4419 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishCountFinishVo.java @@ -0,0 +1,15 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class FbFishCountFinishVo { + + private String stcd; + + private BigDecimal finished; + + private BigDecimal unfinished; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java index 1737b5fe..c55257ea 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java @@ -5,6 +5,7 @@ import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRQgcVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishTableVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFlDataVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbFishCountFinishVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFishTypeFinishVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbRelatedYrVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbMsfbrdmQgcVo; @@ -27,6 +28,8 @@ public interface FbStationService { DataSourceResult getFbFlDataKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getFishCountKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getFishTypeKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getMsfbrdmKendoListCust(DataSourceRequest dataSourceRequest); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java index e4404592..de23128f 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java @@ -15,6 +15,7 @@ import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRQgcVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishHeadColumnVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishSummaryVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishTableVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbFishCountFinishVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFishTypeFinishVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFtpStatisticsVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFlDataVo; @@ -84,6 +85,38 @@ public class FbStationServiceImpl implements FbStationService { return queryFbFlDataDetailList(dataSourceRequest, loadOptions); } + @Override + public DataSourceResult getFishCountKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String rstcdFilter = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); + String stcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd"); + String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + + Map paramMap = new HashMap<>(); + String sql = buildFishCountFinishSql( + stcd, + parseFishTypeFilterValues(rstcdFilter), + parseFishTypeDate(startTime), + parseFishTypeDate(endTime), + paramMap + ) + buildFishCountOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort()); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql, + paramMap, + FbFishCountFinishVo.class + ); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + @Override public DataSourceResult getFishTypeKendoListCust(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -840,6 +873,63 @@ public class FbStationServiceImpl implements FbStationService { return null; } + private String buildFishCountFinishSql(String stcd, + List rstcdList, + Date startTime, + Date endTime, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT jh.RSTCD AS stcd, ") + .append("CASE WHEN imn.FCNT IS NULL THEN 0 ELSE imn.FCNT END AS finished, ") + .append("CASE WHEN imn.FCNT IS NULL THEN jh.FCNT ") + .append("WHEN jh.FCNT - imn.FCNT < 0 THEN 0 ") + .append("ELSE (jh.FCNT - imn.FCNT) END AS unfinished ") + .append("FROM ( ") + .append("SELECT jhr.RSTCD, SUM(jhrs.FCNT) AS FCNT ") + .append("FROM SD_ENGFRPLAN_B jhr ") + .append("JOIN SD_ENGFRPLANDET_B jhrs ON jhr.ID = jhrs.RPJH_ID ") + .append("WHERE NVL(jhr.IS_DELETED, 0) = 0 AND NVL(jhrs.IS_DELETED, 0) = 0 "); + appendFishTypeFilterSql(sql, "jhr", stcd, rstcdList, startTime, endTime, true, paramMap); + sql.append("GROUP BY jhr.RSTCD ") + .append(") jh ") + .append("LEFT JOIN ( ") + .append("SELECT imnr.RSTCD, SUM(imnrs.FCNT) AS FCNT ") + .append("FROM SD_ENGFR_R imnr ") + .append("JOIN SD_RPIMNFISH_R imnrs ON imnr.ID = imnrs.RPIMN_ID ") + .append("WHERE NVL(imnr.IS_DELETED, 0) = 0 AND NVL(imnrs.IS_DELETED, 0) = 0 "); + appendFishTypeFilterSql(sql, "imnr", stcd, rstcdList, startTime, endTime, false, paramMap); + sql.append("GROUP BY imnr.RSTCD ") + .append(") imn ON jh.RSTCD = imn.RSTCD"); + return sql.toString(); + } + + private String buildFishCountOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return " ORDER BY stcd ASC"; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = switch (sort.getField()) { + case "stcd" -> "stcd"; + case "finished" -> "finished"; + case "unfinished" -> "unfinished"; + default -> null; + }; + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction); + } + if (orderByParts.isEmpty()) { + return " ORDER BY stcd ASC"; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + private String buildFishTypeFinishSql(String stcd, List rstcdList, Date startTime, From 0cc208edb48ed0b525dfddbed0b52f204f5a67c1 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 23 Jun 2026 15:12:06 +0800 Subject: [PATCH 25/38] =?UTF-8?q?feat:=20=E5=A2=9E=E6=AE=96=E6=94=BE?= =?UTF-8?q?=E6=B5=81=E5=AE=8C=E6=88=90=E6=83=85=E5=86=B5=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E6=9C=89=E6=95=B0=E6=8D=AE=E7=9A=84=E6=B5=8B=E7=AB=99=E4=B8=8B?= =?UTF-8?q?=E6=8B=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fb/controller/FbStationController.java | 6 +++ .../fb/entity/vo/FbFishTypeStcdVo.java | 19 ++++++++ .../qgc_env/fb/service/FbStationService.java | 3 ++ .../fb/service/impl/FbStationServiceImpl.java | 43 +++++++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishTypeStcdVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java index 68489d04..de45344c 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java @@ -97,6 +97,12 @@ public class FbStationController { return ResponseResult.successData(fbStationService.getFishTypeKendoListCust(dataSourceRequest)); } + @PostMapping("/fishType/getStcdList") + @Operation(summary = "增殖放流完成情况获取有数据的测站下拉") + public ResponseResult getFishTypeStcdList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getFishTypeStcdList(dataSourceRequest)); + } + @PostMapping("/msfbrdm/GetKendoListCust") @Operation(summary = "鱼类增殖站运行情况统计列表") public ResponseResult getMsfbrdmKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishTypeStcdVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishTypeStcdVo.java new file mode 100644 index 00000000..4ecc11f1 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishTypeStcdVo.java @@ -0,0 +1,19 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class FbFishTypeStcdVo { + + private String stcd; + + private String stnm; + + private BigDecimal lgtd; + + private BigDecimal lttd; + + private String baseId; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java index c55257ea..31513088 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java @@ -6,6 +6,7 @@ import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRQgcVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishTableVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFlDataVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFishCountFinishVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbFishTypeStcdVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFishTypeFinishVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbRelatedYrVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbMsfbrdmQgcVo; @@ -32,6 +33,8 @@ public interface FbStationService { DataSourceResult getFishTypeKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getFishTypeStcdList(DataSourceRequest dataSourceRequest); + DataSourceResult getMsfbrdmKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getQgcMsfbrdmKendoListCust(DataSourceRequest dataSourceRequest); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java index de23128f..0f3d8830 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java @@ -16,6 +16,7 @@ import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishHeadColumnVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishSummaryVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishTableVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFishCountFinishVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbFishTypeStcdVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFishTypeFinishVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFtpStatisticsVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFlDataVo; @@ -149,6 +150,28 @@ public class FbStationServiceImpl implements FbStationService { return result; } + @Override + public DataSourceResult getFishTypeStcdList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String baseId = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId"); + String sttpCode = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "sttpCode"); + + Map paramMap = new HashMap<>(); + String sql = buildFishTypeStcdListSql(baseId, sttpCode, paramMap); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + null, + sql, + paramMap, + FbFishTypeStcdVo.class + ); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + @Override public DataSourceResult> getMsstbprptList(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -930,6 +953,26 @@ public class FbStationServiceImpl implements FbStationService { return " ORDER BY " + String.join(", ", orderByParts); } + private String buildFishTypeStcdListSql(String baseId, String sttpCode, Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT fb.STCD AS stcd, fb.STNM AS stnm, fb.LGTD AS lgtd, fb.LTTD AS lttd, fb.BASE_ID AS baseId ") + .append("FROM SD_FBRD_B_H fb ") + .append("INNER JOIN SD_ENGFRPLAN_B plan ON fb.STCD = plan.RSTCD AND NVL(plan.IS_DELETED, 0) = 0 ") + .append("INNER JOIN SD_ENGFRPLANDET_B det ON plan.ID = det.RPJH_ID AND NVL(det.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(fb.USFL, 0) = 1 "); + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("fishTypeBaseId", baseId.trim()); + sql.append(" AND fb.BASE_ID = #{map.fishTypeBaseId} "); + } + if (StrUtil.isNotBlank(sttpCode)) { + paramMap.put("fishTypeSttpCode", sttpCode.trim()); + sql.append(" AND fb.STTP = #{map.fishTypeSttpCode} "); + } + sql.append("GROUP BY fb.STCD, fb.STNM, fb.LGTD, fb.LTTD, fb.BASE_ID, fb.ORDER_INDEX ") + .append("ORDER BY fb.ORDER_INDEX ASC, fb.STCD ASC"); + return sql.toString(); + } + private String buildFishTypeFinishSql(String stcd, List rstcdList, Date startTime, From 144e04e3b6cd41938b1f8da15924e1bae9d01b14 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 23 Jun 2026 15:54:23 +0800 Subject: [PATCH 26/38] =?UTF-8?q?feat:=20=E6=A0=B9=E6=8D=AE=E7=AB=99?= =?UTF-8?q?=E7=A0=81=E6=9F=A5=E8=AF=A2=E7=94=B5=E7=AB=99=E8=AF=A6=E6=83=85?= =?UTF-8?q?=E5=85=BC=E5=AE=B9=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SdEngMonitorController.java | 6 +++ .../qgc_base/domain/vo/EngStBaseInfoVo.java | 51 +++++++++++++++++++ .../qgc_base/domain/vo/EngStInfoResultVo.java | 26 ++++++++++ .../qgc_base/service/ISdEngInfoBHService.java | 3 ++ .../service/impl/SdEngInfoBHServiceImpl.java | 30 +++++++++++ 5 files changed, 116 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStBaseInfoVo.java create mode 100644 backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStInfoResultVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngMonitorController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngMonitorController.java index 1524a5a9..2b4a003b 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngMonitorController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngMonitorController.java @@ -27,6 +27,12 @@ public class SdEngMonitorController { return ResponseResult.successData(engInfoBHService.getStInfoByStcd(stcd)); } + @GetMapping("/msstbprpt/getStcdInfo") + @Operation(summary = "根据站码查询电站详情兼容结构") + public ResponseResult getStcdInfo(@RequestParam String stcd) { + return ResponseResult.successData(engInfoBHService.getStcdInfo(stcd)); + } + @PostMapping("/eiaapproval/GetKendoList") @Operation(summary = "查询生态环保批复文件列表") public ResponseResult getEiaapprovalKendoList(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStBaseInfoVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStBaseInfoVo.java new file mode 100644 index 00000000..b4a0f370 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStBaseInfoVo.java @@ -0,0 +1,51 @@ +package com.yfd.platform.qgc_base.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "电站单站基础信息") +public class EngStBaseInfoVo { + + @Schema(description = "站点编码") + private String stcd; + + @Schema(description = "站点名称") + private String stnm; + + @Schema(description = "站类编码") + private String sttpCode; + + @Schema(description = "站类名称") + private String sttpName; + + @Schema(description = "站类全路径") + private String sttpFullPath; + + @Schema(description = "站类层级") + private Integer sttpTreeLevel; + + @Schema(description = "关联站点编码") + private String stCode; + + @Schema(description = "关联站点名称") + private String stName; + + @Schema(description = "所属基地编码") + private String baseId; + + @Schema(description = "所属基地名称") + private String baseName; + + @Schema(description = "所属基地流域编码") + private String hbrvcd; + + @Schema(description = "所属基地流域名称") + private String hbrvcdName; + + @Schema(description = "所属流域编码") + private String rvcd; + + @Schema(description = "所属流域名称") + private String rvcdName; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStInfoResultVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStInfoResultVo.java new file mode 100644 index 00000000..27e6ca72 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStInfoResultVo.java @@ -0,0 +1,26 @@ +package com.yfd.platform.qgc_base.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@Data +@Schema(description = "电站详情返回") +public class EngStInfoResultVo { + + @Schema(description = "主信息兼容对象") + private Map msStbprpT = new LinkedHashMap<>(); + + @Schema(description = "测值列表") + private List stcdValVoList = new ArrayList<>(); + + @Schema(description = "关联列表") + private List relList = new ArrayList<>(); + + @Schema(description = "站点基础信息") + private EngStBaseInfoVo stBaseInfo; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java index 0c3a521c..174f151d 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java @@ -8,6 +8,7 @@ import com.yfd.platform.qgc_base.domain.SdEngInfoBH; import com.yfd.platform.qgc_base.domain.SdEngInfoBHRequest; import com.yfd.platform.qgc_base.domain.vo.EngBaseInfoVo; import com.yfd.platform.qgc_base.domain.vo.EngEiaapprovalVo; +import com.yfd.platform.qgc_base.domain.vo.EngStInfoResultVo; import com.yfd.platform.qgc_base.domain.vo.EngVmsstbprptVo; import java.util.List; @@ -70,6 +71,8 @@ public interface ISdEngInfoBHService extends IService { EngBaseInfoVo getStInfoByStcd(String stcd); + EngStInfoResultVo getStcdInfo(String stcd); + DataSourceResult getEiaapprovalKendoList(DataSourceRequest dataSourceRequest); DataSourceResult getVmsstbprptKendoList(DataSourceRequest dataSourceRequest); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 90f2cf64..64fa1084 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -20,6 +20,8 @@ import com.yfd.platform.qgc_base.domain.SdEngInfoBH; import com.yfd.platform.qgc_base.domain.SdEngInfoBHRequest; import com.yfd.platform.qgc_base.domain.vo.EngBaseInfoVo; import com.yfd.platform.qgc_base.domain.vo.EngEiaapprovalVo; +import com.yfd.platform.qgc_base.domain.vo.EngStBaseInfoVo; +import com.yfd.platform.qgc_base.domain.vo.EngStInfoResultVo; import com.yfd.platform.qgc_base.domain.vo.EngVmsstbprptVo; import com.yfd.platform.qgc_base.mapper.SdEngInfoBHMapper; import com.yfd.platform.qgc_base.service.IMsOperationLogService; @@ -493,6 +495,34 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl Date: Tue, 23 Jun 2026 16:18:21 +0800 Subject: [PATCH 27/38] =?UTF-8?q?feat:=20=E5=85=A8=E8=BF=87=E7=A8=8BAI?= =?UTF-8?q?=E8=AF=86=E5=88=AB=E5=A4=A7=E5=9D=9D=E8=BF=90=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../warn/controller/WarnDataController.java | 10 +- .../qgc_env/warn/entity/vo/AiDmRunVo.java | 18 ++ .../qgc_env/warn/service/WarnDataService.java | 3 + .../service/impl/WarnDataServiceImpl.java | 154 ++++++++++++++++++ 4 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiDmRunVo.java 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 index 5fce9628..bb9adeb2 100644 --- 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 @@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController -@RequestMapping("/warn/stcd") +@RequestMapping("/warn") @Tag(name = "告警状态模块") @Validated public class WarnDataController { @@ -21,9 +21,15 @@ public class WarnDataController { @Resource private WarnDataService warnDataService; - @PostMapping("/eng/GetKendoListCust") + @PostMapping("/stcd/eng/GetKendoListCust") @Operation(summary = "电站水位、生态流量告警状态统计") public ResponseResult getEngWarnCount(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(warnDataService.getEngWarnCount(dataSourceRequest)); } + + @PostMapping("/ai/com/qgcDmRun/GetKendoListCust") + @Operation(summary = "全过程AI识别大坝运行") + public ResponseResult getAiDmRunCount(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getAiDmRunCount(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiDmRunVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiDmRunVo.java new file mode 100644 index 00000000..ac5671e7 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiDmRunVo.java @@ -0,0 +1,18 @@ +package com.yfd.platform.qgc_env.warn.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "全过程AI识别大坝运行") +public class AiDmRunVo { + + @Schema(description = "漂浮物监测次数") + private Integer pfwCnt; + + @Schema(description = "漂浮物清理次数") + private Integer pfwqlCnt; + + @Schema(description = "叠梁门运行次数") + private Integer dlmCnt; +} 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 index b809eaf6..3c1a3a10 100644 --- 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 @@ -2,9 +2,12 @@ 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.AiDmRunVo; import com.yfd.platform.qgc_env.warn.entity.vo.EngWarnCountVo; public interface WarnDataService { DataSourceResult getEngWarnCount(DataSourceRequest dataSourceRequest); + + AiDmRunVo getAiDmRunCount(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 index e5f94b32..30227e9d 100644 --- 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 @@ -1,12 +1,14 @@ package com.yfd.platform.qgc_env.warn.service.impl; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateUtil; 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.AiDmRunVo; 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; @@ -14,6 +16,7 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -60,6 +63,45 @@ public class WarnDataServiceImpl implements WarnDataService { return result; } + @Override + public AiDmRunVo getAiDmRunCount(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String baseId = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId"); + String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + String rstcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); + String stnm = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stnm"); + + Map paramMap = new HashMap<>(); + String sql = buildAiDmRunSql(baseId, parseAiTime(startTime), parseAiTime(endTime), parseAiCodes(rstcd), stnm, paramMap); + Map row = microservicDynamicSQLMapper.getOneBySql(sql, paramMap); + AiDmRunVo vo = buildAiDmRunVo(row); + if (vo == null) { + vo = new AiDmRunVo(); + } + if (vo.getPfwCnt() == null) { + vo.setPfwCnt(0); + } + if (vo.getPfwqlCnt() == null) { + vo.setPfwqlCnt(0); + } + if (vo.getDlmCnt() == null) { + vo.setDlmCnt(0); + } + return vo; + } + + private AiDmRunVo buildAiDmRunVo(Map row) { + if (row == null || row.isEmpty()) { + return null; + } + AiDmRunVo vo = new AiDmRunVo(); + vo.setPfwCnt(toIntegerValue(firstPresentValue(row, "PFWCNT", "pfwCnt"))); + vo.setPfwqlCnt(toIntegerValue(firstPresentValue(row, "PFWQLCNT", "pfwqlCnt"))); + vo.setDlmCnt(toIntegerValue(firstPresentValue(row, "DLMCNT", "dlmCnt"))); + return vo; + } + 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' " + @@ -94,6 +136,52 @@ public class WarnDataServiceImpl implements WarnDataService { return sql.toString(); } + private String buildAiDmRunSql(String baseId, + Date startTime, + Date endTime, + List rstcdList, + String stnm, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("NVL(SUM(CASE WHEN rec.TYPE = 'AI_5001' THEN 1 ELSE 0 END), 0) AS pfwCnt, ") + .append("NVL(SUM(CASE WHEN rec.TYPE = 'AI_5011' THEN 1 ELSE 0 END), 0) AS pfwqlCnt, ") + .append("NVL(SUM(CASE WHEN rec.TYPE = 'AI_5005' THEN 1 ELSE 0 END), 0) AS dlmCnt ") + .append("FROM SD_AIMONITOR_B_H ai ") + .append("INNER JOIN SD_AICOM_R rec ON ai.STCD = rec.STCD ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = ai.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND NVL(rec.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP LIKE 'AI_%' ") + .append("AND rec.TYPE IN ('AI_5001', 'AI_5011', 'AI_5005') "); + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("aiBaseId", baseId.trim()); + sql.append("AND ai.BASE_ID = #{map.aiBaseId} "); + } + if (startTime != null) { + paramMap.put("aiStartTime", startTime); + sql.append("AND rec.TM >= #{map.aiStartTime} "); + } + if (endTime != null) { + paramMap.put("aiEndTime", endTime); + sql.append("AND rec.TM <= #{map.aiEndTime} "); + } + if (CollUtil.isNotEmpty(rstcdList)) { + List placeholders = new ArrayList<>(); + for (int i = 0; i < rstcdList.size(); i++) { + String key = "aiRstcd" + i; + paramMap.put(key, rstcdList.get(i)); + placeholders.add("#{map." + key + "}"); + } + sql.append("AND ai.RSTCD IN (").append(String.join(", ", placeholders)).append(") "); + } + if (StrUtil.isNotBlank(stnm)) { + paramMap.put("aiEnnm", "%" + stnm.trim() + "%"); + sql.append("AND eng.ENNM LIKE #{map.aiEnnm} "); + } + return sql.toString(); + } + private void fillWarnNames(List list) { if (CollUtil.isEmpty(list)) { return; @@ -129,6 +217,72 @@ public class WarnDataServiceImpl implements WarnDataService { return null; } + private Date parseAiTime(String timeText) { + if (StrUtil.isBlank(timeText)) { + return null; + } + String value = timeText.trim(); + if (value.length() <= 10) { + return DateUtil.parse(value, "yyyy-MM-dd"); + } + return DateUtil.parse(value, "yyyy-MM-dd HH:mm:ss"); + } + + private List parseAiCodes(String codeText) { + if (StrUtil.isBlank(codeText)) { + return new ArrayList<>(); + } + String normalized = codeText.replace("[", "") + .replace("]", "") + .replace("\"", "") + .trim(); + if (StrUtil.isBlank(normalized)) { + return new ArrayList<>(); + } + List result = new ArrayList<>(); + for (String item : normalized.split(",")) { + String code = StrUtil.trim(item); + if (StrUtil.isNotBlank(code)) { + result.add(code); + } + } + return result; + } + + private Object firstPresentValue(Map row, String... keys) { + if (row == null || keys == null) { + return null; + } + for (String key : keys) { + if (row.containsKey(key)) { + return row.get(key); + } + } + return null; + } + + private Integer toIntegerValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof Number number) { + return number.intValue(); + } + String text = String.valueOf(value).trim(); + if (StrUtil.isBlank(text)) { + return null; + } + try { + return Integer.parseInt(text); + } catch (NumberFormatException ex) { + try { + return Double.valueOf(text).intValue(); + } catch (NumberFormatException ignore) { + return null; + } + } + } + private String buildSourceFilterCondition(DataSourceRequest.FilterDescriptor filter, Map paramMap, int[] indexHolder) { From 99dbc6502f157e4a76a598b2f11ed8da2182d267 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 23 Jun 2026 16:31:46 +0800 Subject: [PATCH 28/38] =?UTF-8?q?feat:=20AI=E5=B8=B8=E8=A7=84=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/SdEngInfoBHServiceImpl.java | 13 +- .../fh/service/impl/FhHabitatServiceImpl.java | 12 +- .../warn/controller/WarnDataController.java | 6 + .../qgc_env/warn/entity/vo/AiComListVo.java | 71 +++++ .../qgc_env/warn/service/WarnDataService.java | 3 + .../service/impl/WarnDataServiceImpl.java | 289 ++++++++++++++++++ 6 files changed, 384 insertions(+), 10 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiComListVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 64fa1084..da85cba8 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -402,12 +402,13 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl page = null; - if (dataSourceRequest.getTake() > 0) { - page = new Page<>(dataSourceRequest.getSkip() / dataSourceRequest.getTake() + 1, - dataSourceRequest.getTake()); - } - +// Page page = null; +// if (dataSourceRequest.getTake() > 0) { +// page = new Page<>(dataSourceRequest.getSkip() / dataSourceRequest.getTake() + 1, +// dataSourceRequest.getTake()); +// } + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); Map paramMap = new HashMap<>(); StringBuilder sql = new StringBuilder(buildEiaapprovalBaseSql()); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fh/service/impl/FhHabitatServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fh/service/impl/FhHabitatServiceImpl.java index 1f7a1337..cef364cf 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fh/service/impl/FhHabitatServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fh/service/impl/FhHabitatServiceImpl.java @@ -96,10 +96,14 @@ public class FhHabitatServiceImpl implements FhHabitatService { } sql.append(buildOrderBySql(dataSourceRequest.getSort())); - Page page = null; - if (QgcQueryWrapperUtil.getPageInfo(loadOptions).getHasPageInfo()) { - page = QgcQueryWrapperUtil.getPageInfo(loadOptions).getPage(); - } +// Page page = null; +// if (QgcQueryWrapperUtil.getPageInfo(loadOptions).getHasPageInfo()) { +// page = QgcQueryWrapperUtil.getPageInfo(loadOptions).getPage(); +// } + +// DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, HabitatVo.class); DataSourceResult result = new DataSourceResult<>(); 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 index bb9adeb2..493d28d1 100644 --- 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 @@ -32,4 +32,10 @@ public class WarnDataController { public ResponseResult getAiDmRunCount(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(warnDataService.getAiDmRunCount(dataSourceRequest)); } + + @PostMapping("/ai/com/GetKendoListCust") + @Operation(summary = "AI常规业务列表") + public ResponseResult getAiComKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getAiComKendoListCust(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiComListVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiComListVo.java new file mode 100644 index 00000000..5b7445e1 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiComListVo.java @@ -0,0 +1,71 @@ +package com.yfd.platform.qgc_env.warn.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Date; + +@Data +@Schema(description = "AI常规业务列表") +public class AiComListVo { + + @Schema(description = "主键") + private String id; + + @Schema(description = "类型编码") + private String type; + + @Schema(description = "类型名称") + private String typeName; + + @Schema(description = "AI测站编码") + private String stcd; + + @Schema(description = "AI测站名称") + private String stnm; + + @Schema(description = "所属电站编码") + private String rstcd; + + @Schema(description = "所属电站名称") + private String ennm; + + @Schema(description = "所属基地编码") + private String baseId; + + @Schema(description = "所属基地流域编码") + private String hbrvcd; + + @Schema(description = "所属流域编码") + private String rvcd; + + @Schema(description = "数据时间") + private Date tm; + + @Schema(description = "结束时间") + private Date endTm; + + @Schema(description = "AI识别值") + private String aiVal; + + @Schema(description = "附件ID") + private String fid; + + @Schema(description = "是否填报") + private Integer isFsf; + + @Schema(description = "是否大面积漂浮物") + private Integer isBigDebrisArea; + + @Schema(description = "是否已清漂") + private Integer isClearDrift; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + private Date recordTime; + + @Schema(description = "更新时间") + private Date modifyTime; +} 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 index 3c1a3a10..f371d4bb 100644 --- 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 @@ -3,6 +3,7 @@ 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.AiDmRunVo; +import com.yfd.platform.qgc_env.warn.entity.vo.AiComListVo; import com.yfd.platform.qgc_env.warn.entity.vo.EngWarnCountVo; public interface WarnDataService { @@ -10,4 +11,6 @@ public interface WarnDataService { DataSourceResult getEngWarnCount(DataSourceRequest dataSourceRequest); AiDmRunVo getAiDmRunCount(DataSourceRequest dataSourceRequest); + + DataSourceResult getAiComKendoListCust(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 index 30227e9d..7616b699 100644 --- 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 @@ -7,7 +7,10 @@ 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.GroupHelper; +import com.yfd.platform.common.GroupingInfo; import com.yfd.platform.common.MicroservicDynamicSQLMapper; +import com.yfd.platform.qgc_env.warn.entity.vo.AiComListVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiDmRunVo; import com.yfd.platform.qgc_env.warn.entity.vo.EngWarnCountVo; import com.yfd.platform.qgc_env.warn.service.WarnDataService; @@ -16,6 +19,7 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -91,6 +95,70 @@ public class WarnDataServiceImpl implements WarnDataService { return vo; } + @Override + public DataSourceResult getAiComKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + GroupingInfo[] groupInfos = loadOptions == null ? null : loadOptions.getGroup(); + Map paramMap = new HashMap<>(); + + StringBuilder detailSql = new StringBuilder(); + detailSql.append("SELECT ") + .append("rec.ID AS id, ") + .append("rec.TYPE AS type, ") + .append(buildAiTypeNameExpr("rec.TYPE")).append(" AS typeName, ") + .append("rec.STCD AS stcd, ") + .append("ai.STNM AS stnm, ") + .append("ai.RSTCD AS rstcd, ") + .append("eng.ENNM AS ennm, ") + .append("ai.BASE_ID AS baseId, ") + .append("ai.HBRVCD AS hbrvcd, ") + .append("ai.RVCD AS rvcd, ") + .append("rec.TM AS tm, ") + .append("rec.END_TM AS endTm, ") + .append("rec.AI_VAL AS aiVal, ") + .append("rec.FID AS fid, ") + .append("rec.IS_FSF AS isFsf, ") + .append("rec.IS_BIG_DEBRIS_AREA AS isBigDebrisArea, ") + .append("rec.IS_CLEAR_DRIFT AS isClearDrift, ") + .append("rec.REMARK AS remark, ") + .append("rec.RECORD_TIME AS recordTime, ") + .append("rec.MODIFY_TIME AS modifyTime ") + .append("FROM SD_AICOM_R rec ") + .append("LEFT JOIN SD_AIMONITOR_B_H ai ON ai.STCD = rec.STCD AND NVL(ai.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = ai.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(rec.IS_DELETED, 0) = 0 "); + + String filterSql = buildAiComFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + detailSql.append(" AND ").append(filterSql).append(" "); + } + + DataSourceResult result = new DataSourceResult<>(); + if (CollUtil.isNotEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + String groupedSql = buildAiComGroupSql(detailSql.toString(), groupInfos); + List> rows = microservicDynamicSQLMapper.getAllList(groupedSql, paramMap); + result.setTotal(rows.size()); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setAggregates(new HashMap<>()); + return result; + } + + StringBuilder finalSql = new StringBuilder(); + finalSql.append("SELECT r.* FROM (").append(detailSql).append(") r "); + finalSql.append(buildAiComOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType(page, finalSql.toString(), paramMap, AiComListVo.class); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + private AiDmRunVo buildAiDmRunVo(Map row) { if (row == null || row.isEmpty()) { return null; @@ -182,6 +250,213 @@ public class WarnDataServiceImpl implements WarnDataService { return sql.toString(); } + private String buildAiComGroupSql(String detailSql, GroupingInfo[] groupInfos) { + if (groupInfos == null || groupInfos.length == 0) { + return detailSql; + } + List selectColumns = new ArrayList<>(); + List groupColumns = new ArrayList<>(); + for (GroupingInfo item : groupInfos) { + String column = mapAiComResultColumn("t", item.getSelector()); + if (StrUtil.isBlank(column)) { + continue; + } + String alias = item.getSelector(); + selectColumns.add(column + " AS " + alias); + selectColumns.add("COUNT(1) AS count_" + alias); + groupColumns.add(column); + } + if (selectColumns.isEmpty()) { + return detailSql; + } + return "SELECT " + String.join(", ", selectColumns) + + " FROM (" + detailSql + ") t GROUP BY " + String.join(", ", groupColumns); + } + + private String buildAiComOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return " ORDER BY r.tm DESC, r.recordTime DESC "; + } + List orderItems = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor item : sorts) { + if (item == null || StrUtil.isBlank(item.getField())) { + continue; + } + String column = mapAiComResultColumn("r", item.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(item.getDir()) ? "DESC" : "ASC"; + orderItems.add(column + " " + dir); + } + if (orderItems.isEmpty()) { + return " ORDER BY r.tm DESC, r.recordTime DESC "; + } + return " ORDER BY " + String.join(", ", orderItems); + } + + private String buildAiComFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + List parts = new ArrayList<>(); + if (CollUtil.isNotEmpty(filter.getFilters())) { + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildAiComFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + parts.add(childSql); + } + } + if (parts.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return "(" + String.join(logic, parts) + ")"; + } + String column = mapAiComBaseColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String paramKey = "aiComParam" + indexHolder[0]++; + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + Object value = filter.getValue(); + switch (operator) { + case "eq": + paramMap.put(paramKey, value); + return column + " = #{map." + paramKey + "}"; + case "neq": + paramMap.put(paramKey, value); + return column + " <> #{map." + paramKey + "}"; + case "contains": + paramMap.put(paramKey, "%" + safeString(value) + "%"); + return column + " LIKE #{map." + paramKey + "}"; + case "doesnotcontain": + paramMap.put(paramKey, "%" + safeString(value) + "%"); + return column + " NOT LIKE #{map." + paramKey + "}"; + case "startswith": + paramMap.put(paramKey, safeString(value) + "%"); + return column + " LIKE #{map." + paramKey + "}"; + case "endswith": + paramMap.put(paramKey, "%" + safeString(value)); + return column + " LIKE #{map." + paramKey + "}"; + case "gt": + paramMap.put(paramKey, normalizeAiValue(filter.getField(), value)); + return column + " > #{map." + paramKey + "}"; + case "gte": + paramMap.put(paramKey, normalizeAiValue(filter.getField(), value)); + return column + " >= #{map." + paramKey + "}"; + case "lt": + paramMap.put(paramKey, normalizeAiValue(filter.getField(), value)); + return column + " < #{map." + paramKey + "}"; + case "lte": + paramMap.put(paramKey, normalizeAiValue(filter.getField(), value)); + return column + " <= #{map." + paramKey + "}"; + case "isnull": + return column + " IS NULL"; + case "isnotnull": + return column + " IS NOT NULL"; + case "isempty": + return "(" + column + " IS NULL OR " + column + " = '')"; + case "isnotempty": + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + case "in": + return buildAiComInSql(column, value, paramKey, paramMap); + default: + return ""; + } + } + + private String buildAiComInSql(String column, Object value, String paramKey, Map paramMap) { + List values = parseAiCodes(value == null ? null : String.valueOf(value)); + if (CollUtil.isEmpty(values)) { + return ""; + } + List placeholders = new ArrayList<>(); + for (int i = 0; i < values.size(); i++) { + String key = paramKey + "_" + i; + paramMap.put(key, values.get(i)); + placeholders.add("#{map." + key + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + + private String mapAiComBaseColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "id" -> "rec.ID"; + case "type" -> "rec.TYPE"; + case "typeName" -> buildAiTypeNameExpr("rec.TYPE"); + case "stcd" -> "rec.STCD"; + case "stnm" -> "ai.STNM"; + case "rstcd" -> "ai.RSTCD"; + case "ennm", "stnmEng" -> "eng.ENNM"; + case "baseId" -> "ai.BASE_ID"; + case "hbrvcd" -> "ai.HBRVCD"; + case "rvcd" -> "ai.RVCD"; + case "tm" -> "rec.TM"; + case "endTm" -> "rec.END_TM"; + case "aiVal" -> "rec.AI_VAL"; + case "fid" -> "rec.FID"; + case "isFsf" -> "rec.IS_FSF"; + case "isBigDebrisArea" -> "rec.IS_BIG_DEBRIS_AREA"; + case "isClearDrift" -> "rec.IS_CLEAR_DRIFT"; + case "remark" -> "rec.REMARK"; + case "recordTime" -> "rec.RECORD_TIME"; + case "modifyTime" -> "rec.MODIFY_TIME"; + default -> null; + }; + } + + private String mapAiComResultColumn(String alias, String field) { + if (StrUtil.isBlank(alias) || StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "id" -> alias + ".id"; + case "type" -> alias + ".type"; + case "typeName" -> alias + ".typeName"; + case "stcd" -> alias + ".stcd"; + case "stnm" -> alias + ".stnm"; + case "rstcd" -> alias + ".rstcd"; + case "ennm", "stnmEng" -> alias + ".ennm"; + case "baseId" -> alias + ".baseId"; + case "hbrvcd" -> alias + ".hbrvcd"; + case "rvcd" -> alias + ".rvcd"; + case "tm" -> alias + ".tm"; + case "endTm" -> alias + ".endTm"; + case "aiVal" -> alias + ".aiVal"; + case "fid" -> alias + ".fid"; + case "isFsf" -> alias + ".isFsf"; + case "isBigDebrisArea" -> alias + ".isBigDebrisArea"; + case "isClearDrift" -> alias + ".isClearDrift"; + case "remark" -> alias + ".remark"; + case "recordTime" -> alias + ".recordTime"; + case "modifyTime" -> alias + ".modifyTime"; + default -> null; + }; + } + + private String buildAiTypeNameExpr(String typeColumn) { + return "CASE " + typeColumn + + " WHEN 'AI_5001' THEN '漂浮物' " + + " WHEN 'AI_5002' THEN '运鱼车运行' " + + " WHEN 'AI_5003' THEN '运鱼船出港' " + + " WHEN 'AI_5004' THEN '集鱼船集鱼' " + + " WHEN 'AI_5005' THEN '叠梁门运行' " + + " WHEN 'AI_5006' THEN '赶鱼栅运行' " + + " WHEN 'AI_5007' THEN '升鱼机运行' " + + " WHEN 'AI_5008' THEN 'AGV小车' " + + " WHEN 'AI_5009' THEN '鱼类暂养' " + + " WHEN 'AI_5010' THEN '坝上升鱼机' " + + " WHEN 'AI_5011' THEN '漂浮物清理' " + + " WHEN 'AI_5012' THEN '鱼道放流' " + + " ELSE " + typeColumn + " END"; + } + private void fillWarnNames(List list) { if (CollUtil.isEmpty(list)) { return; @@ -283,6 +558,20 @@ public class WarnDataServiceImpl implements WarnDataService { } } + private Object normalizeAiValue(String field, Object value) { + if (value == null) { + return null; + } + if ("tm".equals(field) || "endTm".equals(field) || "recordTime".equals(field) || "modifyTime".equals(field)) { + return parseAiTime(String.valueOf(value)); + } + return value; + } + + private String safeString(Object value) { + return value == null ? "" : String.valueOf(value).trim(); + } + private String buildSourceFilterCondition(DataSourceRequest.FilterDescriptor filter, Map paramMap, int[] indexHolder) { From 5f6038db51a0cde928888ac276f8566879389fb3 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 23 Jun 2026 16:59:50 +0800 Subject: [PATCH 29/38] =?UTF-8?q?feat:=20=E5=85=A8=E8=BF=87=E7=A8=8BAI?= =?UTF-8?q?=E8=AF=86=E5=88=AB=E5=8A=A8=E6=A4=8D=E7=89=A9=E4=BF=9D=E6=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yfd/platform/config/SwaggerConfig.java | 22 +-- .../warn/controller/WarnDataController.java | 6 + .../qgc_env/warn/entity/vo/AiProtectVo.java | 30 ++++ .../qgc_env/warn/service/WarnDataService.java | 3 + .../service/impl/WarnDataServiceImpl.java | 162 ++++++++++++++++++ 5 files changed, 212 insertions(+), 11 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiProtectVo.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 73f92660..2b33fea4 100644 --- a/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java +++ b/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java @@ -64,14 +64,14 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEnvWTApi() { return GroupedOpenApi.builder() - .group("3.1 全过程-生态环保数据服务-水温监测") + .group("3.1 全过程-生态环保数据服务-水温监测(wt)") .packagesToScan("com.yfd.platform.qgc_env.wt.controller") .build(); } @Bean public GroupedOpenApi groupEnvWQApi() { return GroupedOpenApi.builder() - .group("3.2 全过程-生态环保数据服务-水质监测") + .group("3.2 全过程-生态环保数据服务-水质监测(wq)") .packagesToScan("com.yfd.platform.qgc_env.wq.controller") .build(); } @@ -79,7 +79,7 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEnvFPApi() { return GroupedOpenApi.builder() - .group("3.3 全过程-生态环保数据服务-过鱼设施") + .group("3.3 全过程-生态环保数据服务-过鱼设施(fp)") .packagesToScan("com.yfd.platform.qgc_env.fp.controller") .build(); } @@ -87,7 +87,7 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEnvVDApi() { return GroupedOpenApi.builder() - .group("3.3.1 全过程-生态环保数据服务-过鱼设施-过鱼监测(VD视频模块)") + .group("3.3.1 全过程-生态环保数据服务-过鱼设施-过鱼监测(vd视频模块)") .packagesToScan("com.yfd.platform.qgc_env.vd.controller") .build(); } @@ -97,7 +97,7 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEnvFHApi() { return GroupedOpenApi.builder() - .group("3.4 全过程-生态环保数据服务-栖息地") + .group("3.4 全过程-生态环保数据服务-栖息地(fh)") .packagesToScan("com.yfd.platform.qgc_env.fh.controller") .build(); } @@ -105,7 +105,7 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEnvZQApi() { return GroupedOpenApi.builder() - .group("3.4.1 全过程-生态环保数据服务-栖息地-水文模块") + .group("3.4.1 全过程-生态环保数据服务-栖息地-水文模块(zq)") .packagesToScan("com.yfd.platform.qgc_env.zq.controller") .build(); } @@ -114,7 +114,7 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEnvVapApi() { return GroupedOpenApi.builder() - .group("3.5 全过程-生态环保数据服务-珍稀动植物") + .group("3.5 全过程-生态环保数据服务-珍稀动植物(vap)") .packagesToScan("com.yfd.platform.qgc_env.vap.controller") .build(); } @@ -122,7 +122,7 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEnvFprApi() { return GroupedOpenApi.builder() - .group("3.6 全过程-生态环保数据服务-鱼类调查") + .group("3.6 全过程-生态环保数据服务-鱼类调查(fpr)") .packagesToScan("com.yfd.platform.qgc_env.fpr.controller") .build(); } @@ -130,7 +130,7 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEnvFbApi() { return GroupedOpenApi.builder() - .group("3.7 全过程-生态环保数据服务-增殖放流") + .group("3.7 全过程-生态环保数据服务-增殖放流(fb)") .packagesToScan("com.yfd.platform.qgc_env.fb.controller") .build(); } @@ -138,7 +138,7 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEnvWarnApi() { return GroupedOpenApi.builder() - .group("3.8 全过程-生态环保数据服务-智能告警") + .group("3.8 全过程-生态环保数据服务-智能告警(warn)") .packagesToScan("com.yfd.platform.qgc_env.warn.controller") .build(); } @@ -160,7 +160,7 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEngEqApi() { return GroupedOpenApi.builder() - .group("4.1. 全过程-常规水电数据服务-生态流量") + .group("4.1. 全过程-常规水电数据服务-生态流量(eq)") .packagesToScan("com.yfd.platform.qgc_eng.eq.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 index 493d28d1..b1f22d02 100644 --- 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 @@ -33,6 +33,12 @@ public class WarnDataController { return ResponseResult.successData(warnDataService.getAiDmRunCount(dataSourceRequest)); } + @PostMapping("/ai/com/qgcProtect/GetKendoListCust") + @Operation(summary = "全过程AI识别动植物保护") + public ResponseResult getAiProtectCount(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getAiProtectCount(dataSourceRequest)); + } + @PostMapping("/ai/com/GetKendoListCust") @Operation(summary = "AI常规业务列表") public ResponseResult getAiComKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiProtectVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiProtectVo.java new file mode 100644 index 00000000..3a81096e --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiProtectVo.java @@ -0,0 +1,30 @@ +package com.yfd.platform.qgc_env.warn.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "全过程AI识别动植物保护") +public class AiProtectVo { + + @Schema(description = "运鱼船进出港次数") + private Integer fpYycCnt; + + @Schema(description = "赶鱼栅运行次数") + private Integer fpGysCnt; + + @Schema(description = "升鱼机运行次数") + private Integer fpSyjCnt; + + @Schema(description = "AGV小车次数") + private Integer fpAgvCnt; + + @Schema(description = "运鱼车运行次数") + private Integer fpYychCnt; + + @Schema(description = "鱼道放流次数") + private Integer fpYdhCnt; + + @Schema(description = "植物园养护次数") + private Integer vpYhCnt; +} 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 index f371d4bb..e6a5e4b7 100644 --- 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 @@ -2,6 +2,7 @@ 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.AiProtectVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiDmRunVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiComListVo; import com.yfd.platform.qgc_env.warn.entity.vo.EngWarnCountVo; @@ -12,5 +13,7 @@ public interface WarnDataService { AiDmRunVo getAiDmRunCount(DataSourceRequest dataSourceRequest); + AiProtectVo getAiProtectCount(DataSourceRequest dataSourceRequest); + DataSourceResult getAiComKendoListCust(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 index 7616b699..47ecb5be 100644 --- 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 @@ -12,6 +12,7 @@ import com.yfd.platform.common.GroupingInfo; import com.yfd.platform.common.MicroservicDynamicSQLMapper; import com.yfd.platform.qgc_env.warn.entity.vo.AiComListVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiDmRunVo; +import com.yfd.platform.qgc_env.warn.entity.vo.AiProtectVo; 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; @@ -95,6 +96,46 @@ public class WarnDataServiceImpl implements WarnDataService { return vo; } + @Override + public AiProtectVo getAiProtectCount(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String baseId = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId"); + String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + String rstcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); + String stnm = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stnm"); + + Map paramMap = new HashMap<>(); + String sql = buildAiProtectSql(baseId, parseAiTime(startTime), parseAiTime(endTime), parseAiCodes(rstcd), stnm, paramMap); + Map row = microservicDynamicSQLMapper.getOneBySql(sql, paramMap); + AiProtectVo vo = buildAiProtectVo(row); + if (vo == null) { + vo = new AiProtectVo(); + } + if (vo.getFpYycCnt() == null) { + vo.setFpYycCnt(0); + } + if (vo.getFpGysCnt() == null) { + vo.setFpGysCnt(0); + } + if (vo.getFpSyjCnt() == null) { + vo.setFpSyjCnt(0); + } + if (vo.getFpAgvCnt() == null) { + vo.setFpAgvCnt(0); + } + if (vo.getFpYychCnt() == null) { + vo.setFpYychCnt(0); + } + if (vo.getFpYdhCnt() == null) { + vo.setFpYdhCnt(0); + } + if (vo.getVpYhCnt() == null) { + vo.setVpYhCnt(0); + } + return vo; + } + @Override public DataSourceResult getAiComKendoListCust(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -170,6 +211,21 @@ public class WarnDataServiceImpl implements WarnDataService { return vo; } + private AiProtectVo buildAiProtectVo(Map row) { + if (row == null || row.isEmpty()) { + return null; + } + AiProtectVo vo = new AiProtectVo(); + vo.setFpYycCnt(toIntegerValue(firstPresentValue(row, "FPYYCCNT", "fpYycCnt"))); + vo.setFpGysCnt(toIntegerValue(firstPresentValue(row, "FPGYSCNT", "fpGysCnt"))); + vo.setFpSyjCnt(toIntegerValue(firstPresentValue(row, "FPSYJCNT", "fpSyjCnt"))); + vo.setFpAgvCnt(toIntegerValue(firstPresentValue(row, "FPAGVCNT", "fpAgvCnt"))); + vo.setFpYychCnt(toIntegerValue(firstPresentValue(row, "FPYYCHCNT", "fpYychCnt"))); + vo.setFpYdhCnt(toIntegerValue(firstPresentValue(row, "FPYDHCNT", "fpYdhCnt"))); + vo.setVpYhCnt(toIntegerValue(firstPresentValue(row, "VPYHCNT", "vpYhCnt"))); + return vo; + } + 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' " + @@ -250,6 +306,112 @@ public class WarnDataServiceImpl implements WarnDataService { return sql.toString(); } + private String buildAiProtectSql(String baseId, + Date startTime, + Date endTime, + List rstcdList, + String stnm, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("aiStat.fpYycCnt AS fpYycCnt, ") + .append("aiStat.fpGysCnt AS fpGysCnt, ") + .append("aiStat.fpSyjCnt AS fpSyjCnt, ") + .append("aiStat.fpAgvCnt AS fpAgvCnt, ") + .append("aiStat.fpYychCnt AS fpYychCnt, ") + .append("aiStat.fpYdhCnt AS fpYdhCnt, ") + .append("vpStat.vpYhCnt AS vpYhCnt ") + .append("FROM (") + .append("SELECT ") + .append("NVL(SUM(CASE WHEN rec.TYPE = 'AI_5003' THEN 1 ELSE 0 END), 0) AS fpYycCnt, ") + .append("NVL(SUM(CASE WHEN rec.TYPE = 'AI_5006' THEN 1 ELSE 0 END), 0) AS fpGysCnt, ") + .append("NVL(SUM(CASE WHEN rec.TYPE = 'AI_5007' THEN 1 ELSE 0 END), 0) AS fpSyjCnt, ") + .append("NVL(SUM(CASE WHEN rec.TYPE = 'AI_5008' THEN 1 ELSE 0 END), 0) AS fpAgvCnt, ") + .append("NVL(SUM(CASE WHEN rec.TYPE = 'AI_5002' THEN 1 ELSE 0 END), 0) AS fpYychCnt, ") + .append("NVL(SUM(CASE WHEN rec.TYPE = 'AI_5012' THEN 1 ELSE 0 END), 0) AS fpYdhCnt ") + .append("FROM SD_AIMONITOR_B_H ai ") + .append("INNER JOIN SD_AICOM_R rec ON ai.STCD = rec.STCD ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = ai.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND NVL(rec.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP LIKE 'AI_%' ") + .append("AND rec.TYPE IN ('AI_5003', 'AI_5006', 'AI_5007', 'AI_5008', 'AI_5002', 'AI_5012') "); + appendAiProtectCommonFilterSql(sql, baseId, startTime, endTime, rstcdList, stnm, paramMap); + sql.append(") aiStat, (") + .append("SELECT COUNT(1) AS vpYhCnt ") + .append("FROM SD_AIMONITOR_B_H vpAi ") + .append("INNER JOIN SD_AIVPWATER_R vpRec ON vpAi.STCD = vpRec.STCD ") + .append("WHERE NVL(vpAi.IS_DELETED, 0) = 0 ") + .append("AND NVL(vpRec.IS_DELETED, 0) = 0 ") + .append("AND vpAi.STTP = 'AI_VP_WATER' "); + appendAiProtectVpFilterSql(sql, baseId, startTime, endTime, rstcdList, paramMap); + sql.append(") vpStat"); + return sql.toString(); + } + + private void appendAiProtectCommonFilterSql(StringBuilder sql, + String baseId, + Date startTime, + Date endTime, + List rstcdList, + String stnm, + Map paramMap) { + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("aiProtectBaseId", baseId.trim()); + sql.append("AND ai.BASE_ID = #{map.aiProtectBaseId} "); + } + if (startTime != null) { + paramMap.put("aiProtectStartTime", startTime); + sql.append("AND rec.TM >= #{map.aiProtectStartTime} "); + } + if (endTime != null) { + paramMap.put("aiProtectEndTime", endTime); + sql.append("AND rec.TM <= #{map.aiProtectEndTime} "); + } + if (CollUtil.isNotEmpty(rstcdList)) { + List placeholders = new ArrayList<>(); + for (int i = 0; i < rstcdList.size(); i++) { + String key = "aiProtectRstcd" + i; + paramMap.put(key, rstcdList.get(i)); + placeholders.add("#{map." + key + "}"); + } + sql.append("AND ai.RSTCD IN (").append(String.join(", ", placeholders)).append(") "); + } + if (StrUtil.isNotBlank(stnm)) { + paramMap.put("aiProtectEnnm", "%" + stnm.trim() + "%"); + sql.append("AND eng.ENNM LIKE #{map.aiProtectEnnm} "); + } + } + + private void appendAiProtectVpFilterSql(StringBuilder sql, + String baseId, + Date startTime, + Date endTime, + List rstcdList, + Map paramMap) { + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("aiProtectVpBaseId", baseId.trim()); + sql.append("AND vpAi.BASE_ID = #{map.aiProtectVpBaseId} "); + } + if (startTime != null) { + paramMap.put("aiProtectVpStartTime", startTime); + sql.append("AND vpRec.TM >= #{map.aiProtectVpStartTime} "); + } + if (endTime != null) { + paramMap.put("aiProtectVpEndTime", endTime); + sql.append("AND vpRec.TM <= #{map.aiProtectVpEndTime} "); + } + if (CollUtil.isNotEmpty(rstcdList)) { + List placeholders = new ArrayList<>(); + for (int i = 0; i < rstcdList.size(); i++) { + String key = "aiProtectVpRstcd" + i; + paramMap.put(key, rstcdList.get(i)); + placeholders.add("#{map." + key + "}"); + } + sql.append("AND vpAi.RSTCD IN (").append(String.join(", ", placeholders)).append(") "); + } + } + private String buildAiComGroupSql(String detailSql, GroupingInfo[] groupInfos) { if (groupInfos == null || groupInfos.length == 0) { return detailSql; From e8489a4f56460d338077875932e732ee86663a96 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 23 Jun 2026 17:46:42 +0800 Subject: [PATCH 30/38] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qgc_env/zq/service/impl/ZqMonitorServiceImpl.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/zq/service/impl/ZqMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/zq/service/impl/ZqMonitorServiceImpl.java index ee6173d7..1bd2c665 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/zq/service/impl/ZqMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/zq/service/impl/ZqMonitorServiceImpl.java @@ -66,11 +66,11 @@ public class ZqMonitorServiceImpl implements ZqMonitorService { .append("LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 ") .append("LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eng.HBRVCD ") .append(" AND hbrv.BASEID = eng.BASE_ID ") - .append(" AND NVL(hbrv.IS_DELETED, 0) = 0 ") - .append(" AND NVL(hbrv.ENABLED, 1) = 1 ") + .append(" AND hbrv.IS_DELETED = 0 ") + .append(" AND hbrv.ENABLED = 1 ") .append("LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = eng.RVCD ") .append("LEFT JOIN SD_ADDVCD_DIC addv ON addv.ADDVCD = eng.ADDVCD ") - .append("WHERE NVL(t.IS_DELETED, 0) = 0 "); + .append("WHERE t.IS_DELETED = 0 "); if (onlyZq) { sql.append("AND t.STTP = 'ZQ' "); } @@ -1844,7 +1844,7 @@ public class ZqMonitorServiceImpl implements ZqMonitorService { } return switch (field) { case "isDeleted" -> "NVL(t.IS_DELETED, 0)"; - case "sttpFullPath" -> null; + case "sttpFullPath" -> "t.STTP"; case "sttpCode" -> "t.STTP"; case "mway" -> "t.MWAY"; case "dtinType" -> "t.DTIN_TYPE"; From 2fbdb0cdef90fe1f93d5f4852dce87d145674f6d Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 23 Jun 2026 17:54:30 +0800 Subject: [PATCH 31/38] =?UTF-8?q?feat:=20=E5=85=A8=E8=BF=87=E7=A8=8BAI?= =?UTF-8?q?=E8=AF=86=E5=88=AB=E6=9C=89=E6=95=B0=E6=8D=AE=E7=9A=84=E7=94=B5?= =?UTF-8?q?=E7=AB=99=E4=B8=8B=E6=8B=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../warn/controller/WarnDataController.java | 6 ++ .../qgc_env/warn/entity/vo/AiRstcdVo.java | 15 +++ .../qgc_env/warn/service/WarnDataService.java | 3 + .../service/impl/WarnDataServiceImpl.java | 102 ++++++++++++++++++ 4 files changed, 126 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiRstcdVo.java 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 index b1f22d02..223aa53d 100644 --- 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 @@ -44,4 +44,10 @@ public class WarnDataController { public ResponseResult getAiComKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(warnDataService.getAiComKendoListCust(dataSourceRequest)); } + + @PostMapping("/ai/com/qgc/aiRstcd/GetKendoListCust") + @Operation(summary = "全过程AI识别有数据的电站下拉") + public ResponseResult getAiRstcdListKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getAiRstcdListKendoListCust(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiRstcdVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiRstcdVo.java new file mode 100644 index 00000000..46c0ca88 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiRstcdVo.java @@ -0,0 +1,15 @@ +package com.yfd.platform.qgc_env.warn.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "全过程AI识别电站下拉") +public class AiRstcdVo { + + @Schema(description = "电站编码") + private String stcd; + + @Schema(description = "电站名称") + private String stnm; +} 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 index e6a5e4b7..fd640f6f 100644 --- 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 @@ -5,6 +5,7 @@ import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.qgc_env.warn.entity.vo.AiProtectVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiDmRunVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiComListVo; +import com.yfd.platform.qgc_env.warn.entity.vo.AiRstcdVo; import com.yfd.platform.qgc_env.warn.entity.vo.EngWarnCountVo; public interface WarnDataService { @@ -16,4 +17,6 @@ public interface WarnDataService { AiProtectVo getAiProtectCount(DataSourceRequest dataSourceRequest); DataSourceResult getAiComKendoListCust(DataSourceRequest dataSourceRequest); + + DataSourceResult getAiRstcdListKendoListCust(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 index 47ecb5be..d454814d 100644 --- 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 @@ -13,6 +13,8 @@ import com.yfd.platform.common.MicroservicDynamicSQLMapper; import com.yfd.platform.qgc_env.warn.entity.vo.AiComListVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiDmRunVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiProtectVo; +import com.yfd.platform.qgc_env.warn.entity.vo.AiProtectVo; +import com.yfd.platform.qgc_env.warn.entity.vo.AiRstcdVo; 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; @@ -200,6 +202,25 @@ public class WarnDataServiceImpl implements WarnDataService { return result; } + @Override + public DataSourceResult getAiRstcdListKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String baseId = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId"); + String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + String type = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "type"); + + Map paramMap = new HashMap<>(); + String sql = buildAiRstcdListSql(baseId, parseAiTime(startTime), parseAiTime(endTime), type, paramMap); + List list = microservicDynamicSQLMapper.getAllListWithResultType(sql, paramMap, AiRstcdVo.class); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + private AiDmRunVo buildAiDmRunVo(Map row) { if (row == null || row.isEmpty()) { return null; @@ -211,6 +232,87 @@ public class WarnDataServiceImpl implements WarnDataService { return vo; } + private String buildAiRstcdListSql(String baseId, + Date startTime, + Date endTime, + String type, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT DISTINCT t.stcd AS stcd, t.stnm AS stnm FROM ("); + sql.append("SELECT ai.RSTCD AS stcd, eng.ENNM AS stnm ") + .append("FROM SD_AIMONITOR_B_H ai ") + .append("INNER JOIN SD_AICOM_R rec ON ai.STCD = rec.STCD ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = ai.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND NVL(rec.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP LIKE 'AI_%' ") + .append("AND ai.RSTCD IS NOT NULL "); + appendAiRstcdCommonFilterSql(sql, "aiRstcdAicom", "ai", "rec", baseId, startTime, endTime, paramMap); + appendAiRstcdTypeFilterSql(sql, "aiRstcdType", "rec.TYPE", type, paramMap); + sql.append(" UNION "); + sql.append("SELECT ai.RSTCD AS stcd, eng.ENNM AS stnm ") + .append("FROM SD_AIMONITOR_B_H ai ") + .append("INNER JOIN SD_AIHEARTBEAT_R hb ON ai.STCD = hb.STCD ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = ai.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND NVL(hb.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP LIKE 'AI_%' ") + .append("AND ai.RSTCD IS NOT NULL "); + appendAiRstcdCommonFilterSql(sql, "aiRstcdHeartbeat", "ai", "hb", baseId, startTime, endTime, paramMap); + appendAiRstcdHeartbeatTypeFilterSql(sql, type, paramMap); + sql.append(") t ORDER BY t.stnm, t.stcd"); + return sql.toString(); + } + + private void appendAiRstcdCommonFilterSql(StringBuilder sql, + String keyPrefix, + String aiAlias, + String recordAlias, + String baseId, + Date startTime, + Date endTime, + Map paramMap) { + if (StrUtil.isNotBlank(baseId)) { + paramMap.put(keyPrefix + "BaseId", baseId.trim()); + sql.append("AND ").append(aiAlias).append(".BASE_ID = #{map.").append(keyPrefix).append("BaseId} "); + } + if (startTime != null) { + paramMap.put(keyPrefix + "StartTime", startTime); + sql.append("AND ").append(recordAlias).append(".TM >= #{map.").append(keyPrefix).append("StartTime} "); + } + if (endTime != null) { + paramMap.put(keyPrefix + "EndTime", endTime); + sql.append("AND ").append(recordAlias).append(".TM <= #{map.").append(keyPrefix).append("EndTime} "); + } + } + + private void appendAiRstcdTypeFilterSql(StringBuilder sql, + String keyPrefix, + String typeColumn, + String type, + Map paramMap) { + if (StrUtil.isBlank(type)) { + return; + } + paramMap.put(keyPrefix, type.trim()); + sql.append("AND ").append(typeColumn).append(" = #{map.").append(keyPrefix).append("} "); + } + + private void appendAiRstcdHeartbeatTypeFilterSql(StringBuilder sql, + String type, + Map paramMap) { + if (StrUtil.isBlank(type)) { + return; + } + String normalizedType = type.trim(); + if ("AI_5011".equalsIgnoreCase(normalizedType)) { + paramMap.put("aiRstcdHeartbeatType", "AI_5001"); + } else { + paramMap.put("aiRstcdHeartbeatType", normalizedType); + } + sql.append("AND ai.STTP = #{map.aiRstcdHeartbeatType} "); + } + private AiProtectVo buildAiProtectVo(Map row) { if (row == null || row.isEmpty()) { return null; From 158f33177744abd9d15eb3aee7d0785693d821c7 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 23 Jun 2026 18:01:36 +0800 Subject: [PATCH 32/38] =?UTF-8?q?feat:=20=E5=85=A8=E8=BF=87=E7=A8=8BAI?= =?UTF-8?q?=E8=AF=86=E5=88=AB=E7=9B=91=E6=B5=8B=E6=97=A5=E5=8E=86=E8=A1=A8?= =?UTF-8?q?(=E6=BC=82=E6=B5=AE=E7=89=A9+=E6=B8=85=E6=BC=82=E5=90=88?= =?UTF-8?q?=E5=B9=B6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../warn/controller/WarnDataController.java | 6 + .../qgc_env/warn/entity/vo/AiRecordVo.java | 44 ++++++ .../qgc_env/warn/service/WarnDataService.java | 5 + .../service/impl/WarnDataServiceImpl.java | 140 +++++++++++++++++- 4 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiRecordVo.java 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 index 223aa53d..7b3bf630 100644 --- 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 @@ -50,4 +50,10 @@ public class WarnDataController { public ResponseResult getAiRstcdListKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(warnDataService.getAiRstcdListKendoListCust(dataSourceRequest)); } + + @PostMapping("/ai/com/qgc/aiPfwRecord/GetKendoListCust") + @Operation(summary = "全过程AI识别监测日历表(漂浮物+清漂合并)") + public ResponseResult getAiPfwRecordKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getAiPfwRecordKendoListCust(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiRecordVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiRecordVo.java new file mode 100644 index 00000000..dfe4d0e3 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiRecordVo.java @@ -0,0 +1,44 @@ +package com.yfd.platform.qgc_env.warn.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +@Data +@Accessors(chain = true) +@Schema(description = "全过程AI识别监测日历记录") +public class AiRecordVo { + + @Schema(description = "AI类型") + private String type; + + @Schema(description = "日期") + private String dt; + + @Schema(description = "是否大面积漂浮物") + private Integer isBigDebrisArea; + + @Schema(description = "AI数据数") + private Integer aiCnt; + + @Schema(description = "统计数") + private Integer cnt; + + @Schema(description = "是否已清漂") + private Integer isClearDrift; + + @Schema(description = "漂浮物状态") + private Integer status; + + @Schema(description = "漂浮物状态名称") + private String statusName; + + @Schema(description = "清漂状态") + private Integer qpStatus; + + @Schema(description = "清漂状态名称") + private String qpStatusName; + + @Schema(description = "附件ID") + private String fid; +} 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 index fd640f6f..99706afa 100644 --- 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 @@ -2,12 +2,15 @@ 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.AiRecordVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiProtectVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiDmRunVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiComListVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiRstcdVo; import com.yfd.platform.qgc_env.warn.entity.vo.EngWarnCountVo; +import java.util.List; + public interface WarnDataService { DataSourceResult getEngWarnCount(DataSourceRequest dataSourceRequest); @@ -19,4 +22,6 @@ public interface WarnDataService { DataSourceResult getAiComKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getAiRstcdListKendoListCust(DataSourceRequest dataSourceRequest); + + List getAiPfwRecordKendoListCust(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 index d454814d..98b1eebf 100644 --- 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 @@ -13,7 +13,7 @@ import com.yfd.platform.common.MicroservicDynamicSQLMapper; import com.yfd.platform.qgc_env.warn.entity.vo.AiComListVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiDmRunVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiProtectVo; -import com.yfd.platform.qgc_env.warn.entity.vo.AiProtectVo; +import com.yfd.platform.qgc_env.warn.entity.vo.AiRecordVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiRstcdVo; import com.yfd.platform.qgc_env.warn.entity.vo.EngWarnCountVo; import com.yfd.platform.qgc_env.warn.service.WarnDataService; @@ -221,6 +221,21 @@ public class WarnDataServiceImpl implements WarnDataService { return result; } + @Override + public List getAiPfwRecordKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String baseId = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId"); + String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + String rstcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); + + Map paramMap = new HashMap<>(); + String sql = buildAiPfwRecordSql(baseId, parseAiTime(startTime), parseAiTime(endTime), parseAiCodes(rstcd), paramMap); + List list = microservicDynamicSQLMapper.getAllListWithResultType(sql, paramMap, AiRecordVo.class); + fillAiPfwStatus(list); + return list; + } + private AiDmRunVo buildAiDmRunVo(Map row) { if (row == null || row.isEmpty()) { return null; @@ -264,6 +279,53 @@ public class WarnDataServiceImpl implements WarnDataService { return sql.toString(); } + private String buildAiPfwRecordSql(String baseId, + Date startTime, + Date endTime, + List rstcdList, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT a.dt AS dt, b.isClearDrift AS isClearDrift, b.isBigDebrisArea AS isBigDebrisArea, b.fid AS fid ") + .append("FROM (") + .append("SELECT TO_CHAR(hb.TM, 'yyyy-MM-dd') AS dt ") + .append("FROM SD_AIHEARTBEAT_R hb ") + .append("INNER JOIN SD_AIMONITOR_B_H ai ON ai.STCD = hb.STCD ") + .append("WHERE NVL(hb.IS_DELETED, 0) = 0 ") + .append("AND NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP = 'AI_5001' "); + appendAiPfwFacilityFilterSql(sql, "aiPfwHeartbeat", "ai", "hb", baseId, startTime, endTime, rstcdList, paramMap); + sql.append("GROUP BY TO_CHAR(hb.TM, 'yyyy-MM-dd') ") + .append("UNION ") + .append("SELECT TO_CHAR(rec.TM, 'yyyy-MM-dd') AS dt ") + .append("FROM SD_AICOM_R rec ") + .append("INNER JOIN SD_AIMONITOR_B_H ai ON ai.STCD = rec.STCD ") + .append("WHERE NVL(rec.IS_DELETED, 0) = 0 ") + .append("AND NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP = 'AI_5001' "); + appendAiPfwFacilityFilterSql(sql, "aiPfwAicom", "ai", "rec", baseId, startTime, endTime, rstcdList, paramMap); + sql.append("GROUP BY TO_CHAR(rec.TM, 'yyyy-MM-dd') ") + .append(") a ") + .append("LEFT JOIN (") + .append("SELECT TO_CHAR(rec.TM, 'yyyy-MM-dd') AS dt, ") + .append("MAX(CASE ") + .append("WHEN rec.TYPE = 'AI_5001' AND rec.IS_BIG_DEBRIS_AREA IS NULL THEN 0 ") + .append("WHEN rec.TYPE = 'AI_5001' AND rec.IS_BIG_DEBRIS_AREA IS NOT NULL THEN rec.IS_BIG_DEBRIS_AREA ") + .append("END) AS isBigDebrisArea, ") + .append("MAX(CASE WHEN rec.TYPE = 'AI_5011' THEN 1 END) AS isClearDrift, ") + .append("LISTAGG(rec.FID, ',') WITHIN GROUP (ORDER BY rec.FID) AS fid ") + .append("FROM SD_AICOM_R rec ") + .append("INNER JOIN SD_AIMONITOR_B_H ai ON ai.STCD = rec.STCD ") + .append("WHERE NVL(rec.IS_DELETED, 0) = 0 ") + .append("AND NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP = 'AI_5001' ") + .append("AND rec.TYPE IN ('AI_5001', 'AI_5011') "); + appendAiPfwFacilityFilterSql(sql, "aiPfwStatus", "ai", "rec", baseId, startTime, endTime, rstcdList, paramMap); + sql.append("GROUP BY TO_CHAR(rec.TM, 'yyyy-MM-dd') ") + .append(") b ON a.dt = b.dt ") + .append("ORDER BY a.dt"); + return sql.toString(); + } + private void appendAiRstcdCommonFilterSql(StringBuilder sql, String keyPrefix, String aiAlias, @@ -313,6 +375,82 @@ public class WarnDataServiceImpl implements WarnDataService { sql.append("AND ai.STTP = #{map.aiRstcdHeartbeatType} "); } + private void appendAiPfwFacilityFilterSql(StringBuilder sql, + String keyPrefix, + String aiAlias, + String recordAlias, + String baseId, + Date startTime, + Date endTime, + List rstcdList, + Map paramMap) { + if (StrUtil.isNotBlank(baseId)) { + paramMap.put(keyPrefix + "BaseId", baseId.trim()); + sql.append("AND ").append(aiAlias).append(".BASE_ID = #{map.").append(keyPrefix).append("BaseId} "); + } + if (CollUtil.isNotEmpty(rstcdList)) { + List placeholders = new ArrayList<>(); + for (int i = 0; i < rstcdList.size(); i++) { + String key = keyPrefix + "Rstcd" + i; + paramMap.put(key, rstcdList.get(i)); + placeholders.add("#{map." + key + "}"); + } + sql.append("AND ").append(aiAlias).append(".RSTCD IN (").append(String.join(", ", placeholders)).append(") "); + } + if (startTime != null) { + paramMap.put(keyPrefix + "StartTime", startTime); + sql.append("AND ").append(recordAlias).append(".TM >= #{map.").append(keyPrefix).append("StartTime} "); + } + if (endTime != null) { + paramMap.put(keyPrefix + "EndTime", endTime); + sql.append("AND ").append(recordAlias).append(".TM <= #{map.").append(keyPrefix).append("EndTime} "); + } + } + + private void fillAiPfwStatus(List list) { + if (CollUtil.isEmpty(list)) { + return; + } + for (AiRecordVo item : list) { + if (item == null) { + continue; + } + if (item.getIsBigDebrisArea() != null) { + if (item.getIsBigDebrisArea() == 0) { + item.setStatus(1); + } else { + item.setStatus(2); + } + } else { + item.setStatus(0); + } + item.setStatusName(resolveAiStatusName(item.getStatus())); + if (item.getIsClearDrift() != null) { + item.setQpStatus(5); + } else { + item.setQpStatus(6); + } + item.setQpStatusName(resolveAiStatusName(item.getQpStatus())); + } + } + + private String resolveAiStatusName(Integer status) { + if (status == null) { + return null; + } + return switch (status) { + case -1 -> "未监测"; + case 0 -> "无漂浮物"; + case 1 -> "小面积漂浮物"; + case 2 -> "大面积漂浮物"; + case 3 -> "运行"; + case 4 -> "未运行"; + case 5 -> "清漂"; + case 6 -> "未清漂"; + default -> null; + }; + } + private AiProtectVo buildAiProtectVo(Map row) { if (row == null || row.isEmpty()) { return null; From 939ddd11e03c0c78e05b6c47e85055104afac453 Mon Sep 17 00:00:00 2001 From: tangwei Date: Tue, 23 Jun 2026 18:08:12 +0800 Subject: [PATCH 33/38] =?UTF-8?q?feat:=20=E7=94=B5=E7=AB=99=E5=91=8A?= =?UTF-8?q?=E8=AD=A6=E6=8F=8F=E7=82=B9=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../warn/controller/WarnDataController.java | 6 + .../qgc_env/warn/entity/vo/AlarmPointVo.java | 103 ++++++ .../qgc_env/warn/service/WarnDataService.java | 3 + .../service/impl/WarnDataServiceImpl.java | 307 ++++++++++++++++++ 4 files changed, 419 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AlarmPointVo.java 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 index 7b3bf630..ce2ebc7d 100644 --- 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 @@ -56,4 +56,10 @@ public class WarnDataController { public ResponseResult getAiPfwRecordKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(warnDataService.getAiPfwRecordKendoListCust(dataSourceRequest)); } + + @PostMapping("/alarmPoint/GetKendoListCust") + @Operation(summary = "电站告警描点列表") + public ResponseResult getAlarmPointKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getAlarmPointKendoListCust(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AlarmPointVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AlarmPointVo.java new file mode 100644 index 00000000..69cbfaa2 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AlarmPointVo.java @@ -0,0 +1,103 @@ +package com.yfd.platform.qgc_env.warn.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; + +@Data +@Accessors(chain = true) +@Schema(description = "电站告警描点") +public class AlarmPointVo { + + @Schema(description = "站点类型") + private String sttp; + + @Schema(description = "站点编码") + private String stcd; + + @Schema(description = "经度") + private BigDecimal lgtd; + + @Schema(description = "纬度") + private BigDecimal lttd; + + @Schema(description = "高程") + private BigDecimal dtmel; + + @Schema(description = "描点状态") + private String anchoPointState; + + @Schema(description = "锚点类型") + private String sttpMap; + + @Schema(description = "弹框站点名称") + private String titleName; + + @Schema(description = "地图避让") + private Integer distance; + + @Schema(description = "流域编码") + private String rvcd; + + @Schema(description = "行政编码") + private String addvcd; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "关联电站编码") + private String rstcds; + + @Schema(description = "设施类型") + private String sttpCode; + + @Schema(description = "电站名称") + private String ennm; + + @Schema(description = "流域名称") + private String rvnm; + + @Schema(description = "电站装机类型") + private Integer endInstalledType; + + @Schema(description = "生态流量告警数") + private Integer stqCount; + + @Schema(description = "水质告警数") + private Integer wqCount; + + @Schema(description = "水位告警数") + private Integer zCount; + + @Schema(description = "水温告警数") + private Integer wtCount; + + @Schema(description = "年份") + private String yyyy; + + @Schema(description = "告警区间范围") + private String range; + + @Schema(description = "装机容量") + private BigDecimal ttpwr; + + @Schema(description = "基地名称") + private String baseName; + + @Schema(description = "电站编码") + private String rstcd; + + @Schema(description = "流域沿程") + private Integer rvcdStepSort; + + @Schema(description = "电站沿程") + private Integer rstcdStepSort; + + @Schema(description = "站点沿程") + private Integer siteStepSort; + + @Schema(description = "电站图片") + private String logo; +} 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 index 99706afa..4572615c 100644 --- 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 @@ -2,6 +2,7 @@ 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.AlarmPointVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiRecordVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiProtectVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiDmRunVo; @@ -24,4 +25,6 @@ public interface WarnDataService { DataSourceResult getAiRstcdListKendoListCust(DataSourceRequest dataSourceRequest); List getAiPfwRecordKendoListCust(DataSourceRequest dataSourceRequest); + + DataSourceResult getAlarmPointKendoListCust(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 index 98b1eebf..75e9c8aa 100644 --- 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 @@ -10,6 +10,7 @@ import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.common.GroupHelper; import com.yfd.platform.common.GroupingInfo; import com.yfd.platform.common.MicroservicDynamicSQLMapper; +import com.yfd.platform.qgc_env.warn.entity.vo.AlarmPointVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiComListVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiDmRunVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiProtectVo; @@ -21,6 +22,7 @@ import com.yfd.platform.utils.QgcQueryWrapperUtil; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; @@ -236,6 +238,48 @@ public class WarnDataServiceImpl implements WarnDataService { return list; } + @Override + public DataSourceResult getAlarmPointKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String startTimeText = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTimeText = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + + Date startTime = null; + Date endTime = null; + String yyyy = null; + if (StrUtil.isNotBlank(startTimeText) && StrUtil.isNotBlank(endTimeText)) { + startTime = parseAiTime(startTimeText); + endTime = parseAiTime(endTimeText); + } else { + yyyy = String.valueOf(DateUtil.year(new Date())); + Map yearRange = buildAlarmPointYearRange(yyyy); + startTime = yearRange.get("startTime"); + endTime = yearRange.get("endTime"); + } + + List points = microservicDynamicSQLMapper.getAllListWithResultType( + buildAlarmPointBaseSql(), + new HashMap<>(), + AlarmPointVo.class + ); + + Map countParamMap = new HashMap<>(); + countParamMap.put("alarmPointStartTime", startTime); + countParamMap.put("alarmPointEndTime", endTime); + List> countRows = microservicDynamicSQLMapper.getAllList(buildAlarmPointCountSql(), countParamMap); + Map qecCountMap = buildAlarmPointQecCountMap(countRows); + Map wqCountMap = buildAlarmPointWqCountMap(countRows); + + List> expressionRows = microservicDynamicSQLMapper.getAllList(buildAlarmPointLegendSql(), new HashMap<>()); + List resultList = mergeAlarmPointData(points, qecCountMap, wqCountMap, expressionRows, yyyy); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(resultList); + result.setTotal(resultList.size()); + result.setAggregates(new HashMap<>()); + return result; + } + private AiDmRunVo buildAiDmRunVo(Map row) { if (row == null || row.isEmpty()) { return null; @@ -326,6 +370,88 @@ public class WarnDataServiceImpl implements WarnDataService { return sql.toString(); } + private String buildAlarmPointBaseSql() { + return "SELECT " + + "eng.STCD AS stcd, " + + "'ENG' AS sttp, " + + "eng.ENNM AS ennm, " + + "eng.ENNM AS titleName, " + + "eng.LOGO AS logo, " + + "eng.RVCD AS rvcd, " + + "eng.RVCD_NAME AS rvnm, " + + "eng.ADDVCD AS addvcd, " + + "eng.BASE_ID AS baseId, " + + "NVL(eng.BASE_NAME, hb.BASENAME) AS baseName, " + + "eng.LGTD AS lgtd, " + + "eng.LTTD AS lttd, " + + "eng.ELEV AS dtmel, " + + "eng.YRGEB AS ttpwr, " + + "'ENG' AS sttpMap, " + + "CASE WHEN eng.PRSC IN (1, 2) THEN 1 WHEN eng.PRSC = 3 THEN 2 END AS endInstalledType, " + + "CASE " + + " WHEN eng.PRSC IN (1, 2) AND NVL(eng.BLDSTT_CODE, 0) = 2 THEN 'large_eng_built' " + + " WHEN eng.PRSC IN (1, 2) AND NVL(eng.BLDSTT_CODE, 0) = 1 THEN 'large_eng_ubuilt' " + + " WHEN eng.PRSC IN (1, 2) THEN 'large_eng_nbuilt' " + + " WHEN eng.PRSC = 3 AND NVL(eng.BLDSTT_CODE, 0) = 2 THEN 'mid_eng_built' " + + " WHEN eng.PRSC = 3 AND NVL(eng.BLDSTT_CODE, 0) = 1 THEN 'mid_eng_ubuilt' " + + " WHEN eng.PRSC = 3 THEN 'mid_eng_nbuilt' " + + " ELSE NULL END AS anchoPointState, " + + "NVL(along.ORDER_INDEX, 999999) AS rvcdStepSort, " + + "NVL(rstSort.SORT, 999999) AS rstcdStepSort, " + + "NVL(siteSort.SORT, 999999) AS siteStepSort " + + "FROM SD_ENGINFO_B_H eng " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN MS_ALONG_B along ON along.RVCD = eng.HBRVCD AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 " + + "LEFT JOIN ( " + + " SELECT det.SORT, cfg.RVCD, det.STCD " + + " FROM MS_ALONGDET_B det " + + " INNER JOIN MS_ALONG_B cfg ON det.ALONG_ID = cfg.ID " + + " WHERE NVL(det.IS_DELETED, 0) = 0 AND NVL(cfg.IS_DELETED, 0) = 0 AND cfg.CODE = 'common' " + + ") rstSort ON rstSort.RVCD = eng.HBRVCD AND rstSort.STCD = eng.STCD " + + "LEFT JOIN ( " + + " SELECT det.SORT, cfg.RVCD, det.STCD " + + " FROM MS_ALONGDET_B det " + + " INNER JOIN MS_ALONG_B cfg ON det.ALONG_ID = cfg.ID " + + " WHERE NVL(det.IS_DELETED, 0) = 0 AND NVL(cfg.IS_DELETED, 0) = 0 AND cfg.CODE = 'common' " + + ") siteSort ON siteSort.RVCD = eng.HBRVCD AND siteSort.STCD = eng.STCD " + + "WHERE NVL(eng.IS_DELETED, 0) = 0 " + + "AND NVL(eng.USFL, 0) = 1 " + + "AND eng.LGTD IS NOT NULL " + + "AND eng.LTTD IS NOT NULL " + + "ORDER BY NVL(hb.ORDER_INDEX, 999999), NVL(along.ORDER_INDEX, 999999), NVL(siteSort.SORT, 999999), eng.ENNM"; + } + + private String buildAlarmPointCountSql() { + return "SELECT wr.STCD AS stcd, wr.STCD AS rstcd, COUNT(wr.STCD) AS count, 'QEC' AS ys " + + "FROM MS_WARN_RECORD_W wr " + + "WHERE NVL(wr.IS_DELETED, 0) = 0 " + + "AND wr.TB_ID IN (SELECT tb.ID FROM ST_TB_B tb WHERE tb.TB_CODE = 'QEC_R' AND NVL(tb.IS_DELETED, 0) = 0) " + + "AND wr.YS = 'QEC' " + + "AND wr.SFGB = 'N' " + + "AND wr.BTM BETWEEN #{map.alarmPointStartTime} AND #{map.alarmPointEndTime} " + + "GROUP BY wr.STCD " + + "UNION ALL " + + "SELECT wr.STCD AS stcd, wq.RSTCD AS rstcd, COUNT(wr.STCD) AS count, 'WQ' AS ys " + + "FROM MS_WARN_RECORD_W wr " + + "LEFT JOIN SD_WQ_B_H wq ON wr.STCD = wq.STCD AND NVL(wq.IS_DELETED, 0) = 0 " + + "WHERE NVL(wr.IS_DELETED, 0) = 0 " + + "AND wr.TB_ID IN (SELECT tb.ID FROM ST_TB_B tb WHERE tb.TB_CODE = 'WQ_R' AND NVL(tb.IS_DELETED, 0) = 0) " + + "AND wr.SFGB = 'N' " + + "AND wr.BTM BETWEEN #{map.alarmPointStartTime} AND #{map.alarmPointEndTime} " + + "AND wq.RSTCD IS NOT NULL " + + "GROUP BY wr.STCD, wq.RSTCD"; + } + + private String buildAlarmPointLegendSql() { + return "SELECT EXPRESSION AS expression, NAME_EN AS nameEn " + + "FROM MS_MAPLEGEND_B " + + "WHERE LAYER_CODE = 'eng_alarm_point' " + + "AND IF_SHOW = 1 " + + "AND NVL(IS_DELETED, 0) = 0 " + + "AND EXPRESSION IS NOT NULL " + + "ORDER BY NVL(ORDER_INDEX, 999999), ID"; + } + private void appendAiRstcdCommonFilterSql(StringBuilder sql, String keyPrefix, String aiAlias, @@ -407,6 +533,166 @@ public class WarnDataServiceImpl implements WarnDataService { } } + private Map buildAlarmPointYearRange(String yearText) { + Date endTime = new Date(); + String currentYear = String.valueOf(DateUtil.year(endTime)); + Date startTime = DateUtil.parse(currentYear + "-01-01"); + if (StrUtil.isNotBlank(yearText) && !currentYear.equals(yearText)) { + startTime = DateUtil.parse(yearText + "-01-01"); + endTime = DateUtil.parse(yearText + "-12-31"); + } + Map result = new HashMap<>(); + result.put("startTime", startTime); + result.put("endTime", endTime); + return result; + } + + private Map buildAlarmPointQecCountMap(List> countRows) { + Map result = new HashMap<>(); + if (CollUtil.isEmpty(countRows)) { + return result; + } + for (Map row : countRows) { + if (!"QEC".equalsIgnoreCase(safeString(firstPresentValue(row, "YS", "ys")))) { + continue; + } + String stcd = safeString(firstPresentValue(row, "RSTCD", "rstcd", "STCD", "stcd")); + if (StrUtil.isBlank(stcd)) { + continue; + } + result.put(stcd, toIntegerValue(firstPresentValue(row, "COUNT", "count"))); + } + return result; + } + + private Map buildAlarmPointWqCountMap(List> countRows) { + Map result = new HashMap<>(); + if (CollUtil.isEmpty(countRows)) { + return result; + } + for (Map row : countRows) { + if (!"WQ".equalsIgnoreCase(safeString(firstPresentValue(row, "YS", "ys")))) { + continue; + } + Integer count = toIntegerValue(firstPresentValue(row, "COUNT", "count")); + if (count == null) { + count = 0; + } + String rstcdText = safeString(firstPresentValue(row, "RSTCD", "rstcd")); + if (StrUtil.isBlank(rstcdText)) { + continue; + } + for (String rstcd : rstcdText.split(",")) { + String trimmed = StrUtil.trim(rstcd); + if (StrUtil.isBlank(trimmed)) { + continue; + } + result.put(trimmed, result.getOrDefault(trimmed, 0) + count); + } + } + return result; + } + + private List mergeAlarmPointData(List points, + Map qecCountMap, + Map wqCountMap, + List> expressionRows, + String yyyy) { + List result = new ArrayList<>(); + if (CollUtil.isEmpty(points)) { + return result; + } + for (AlarmPointVo point : points) { + if (point == null || !isAlarmPointVisible(point.getAnchoPointState())) { + continue; + } + point.setAnchoPointState(normalizeAlarmPointState(point.getAnchoPointState()) + "_ALARM"); + point.setStqCount(qecCountMap.getOrDefault(point.getStcd(), 0)); + point.setWqCount(wqCountMap.getOrDefault(point.getStcd(), 0)); + point.setZCount(0); + point.setWtCount(0); + point.setYyyy(yyyy); + point.setSttpCode("ENG"); + int total = point.getStqCount() + point.getWqCount(); + applyAlarmPointRange(point, total, expressionRows); + result.add(point); + } + return result; + } + + private boolean isAlarmPointVisible(String state) { + return "large_eng_built".equals(state) + || "mid_eng_built".equals(state) + || "large_eng_ubuilt".equals(state) + || "mid_eng_ubuilt".equals(state); + } + + private String normalizeAlarmPointState(String state) { + if ("large_eng_ubuilt".equals(state)) { + return "large_eng_built"; + } + if ("mid_eng_ubuilt".equals(state)) { + return "mid_eng_built"; + } + return state; + } + + private void applyAlarmPointRange(AlarmPointVo point, int total, List> expressionRows) { + if (point == null || CollUtil.isEmpty(expressionRows)) { + return; + } + for (Map row : expressionRows) { + String expression = safeString(firstPresentValue(row, "EXPRESSION", "expression")); + if (!matchesAlarmExpression(expression, total)) { + continue; + } + String nameEn = safeString(firstPresentValue(row, "NAMEEN", "nameEn", "NAME_EN")); + if (StrUtil.isNotBlank(nameEn)) { + point.setAnchoPointState(point.getAnchoPointState() + "_" + nameEn); + point.setRange(nameEn); + } + return; + } + } + + private boolean matchesAlarmExpression(String range, int value) { + if (StrUtil.isBlank(range)) { + return false; + } + if (range.matches("x=\\d+")) { + return value == Integer.parseInt(range.substring(2)); + } + if (range.matches("x>\\d+")) { + return value > Integer.parseInt(range.substring(2)); + } + if (range.matches("x>=\\d+")) { + return value >= Integer.parseInt(range.substring(3)); + } + if (range.matches("x<\\d+")) { + return value < Integer.parseInt(range.substring(2)); + } + if (range.matches("x<=\\d+")) { + return value <= Integer.parseInt(range.substring(3)); + } + if (range.matches("\\d+ Integer.parseInt(split[0]) && value < Integer.parseInt(split[1]); + } + if (range.matches("\\d+<=x<=\\d+")) { + String[] split = range.split("<=x<="); + return value >= Integer.parseInt(split[0]) && value <= Integer.parseInt(split[1]); + } + if (range.matches("\\d+ Integer.parseInt(split[0]) && value <= Integer.parseInt(split[1]); + } + if (range.matches("\\d+<=x<\\d+")) { + String[] split = range.split("<=x<"); + return value >= Integer.parseInt(split[0]) && value < Integer.parseInt(split[1]); + } + return false; + } + private void fillAiPfwStatus(List list) { if (CollUtil.isEmpty(list)) { return; @@ -960,6 +1246,27 @@ public class WarnDataServiceImpl implements WarnDataService { } } + private BigDecimal toBigDecimalValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof BigDecimal bigDecimal) { + return bigDecimal; + } + if (value instanceof Number number) { + return BigDecimal.valueOf(number.doubleValue()); + } + String text = String.valueOf(value).trim(); + if (StrUtil.isBlank(text)) { + return null; + } + try { + return new BigDecimal(text); + } catch (NumberFormatException ex) { + return null; + } + } + private Object normalizeAiValue(String field, Object value) { if (value == null) { return null; From 2e69b3e73cf3a76dc31bc4e90872d12a5308ee4b Mon Sep 17 00:00:00 2001 From: tangwei Date: Wed, 24 Jun 2026 08:51:54 +0800 Subject: [PATCH 34/38] =?UTF-8?q?feat:=20=E5=85=A8=E8=BF=87=E7=A8=8BAI?= =?UTF-8?q?=E8=AF=86=E5=88=AB=E7=9B=91=E6=B5=8B=E6=97=A5=E5=8E=86=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../warn/controller/WarnDataController.java | 6 + .../qgc_env/warn/service/WarnDataService.java | 2 + .../service/impl/WarnDataServiceImpl.java | 118 ++++++++++++++++++ 3 files changed, 126 insertions(+) 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 index ce2ebc7d..9d29dd2e 100644 --- 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 @@ -57,6 +57,12 @@ public class WarnDataController { return ResponseResult.successData(warnDataService.getAiPfwRecordKendoListCust(dataSourceRequest)); } + @PostMapping("/ai/com/qgc/aiRecord/GetKendoListCust") + @Operation(summary = "全过程AI识别监测日历表") + public ResponseResult getAiRecordKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getAiRecordKendoListCust(dataSourceRequest)); + } + @PostMapping("/alarmPoint/GetKendoListCust") @Operation(summary = "电站告警描点列表") public ResponseResult getAlarmPointKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { 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 index 4572615c..acc3b40b 100644 --- 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 @@ -26,5 +26,7 @@ public interface WarnDataService { List getAiPfwRecordKendoListCust(DataSourceRequest dataSourceRequest); + List getAiRecordKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getAlarmPointKendoListCust(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 index 75e9c8aa..8f5e190f 100644 --- 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 @@ -238,6 +238,23 @@ public class WarnDataServiceImpl implements WarnDataService { return list; } + @Override + public List getAiRecordKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String baseId = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId"); + String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + String rstcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); + String stcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd"); + String type = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "type"); + + Map paramMap = new HashMap<>(); + String sql = buildAiRecordSql(baseId, parseAiTime(startTime), parseAiTime(endTime), parseAiCodes(rstcd), stcd, type, paramMap); + List list = microservicDynamicSQLMapper.getAllListWithResultType(sql, paramMap, AiRecordVo.class); + fillAiRecordStatus(list); + return list; + } + @Override public DataSourceResult getAlarmPointKendoListCust(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -370,6 +387,48 @@ public class WarnDataServiceImpl implements WarnDataService { return sql.toString(); } + private String buildAiRecordSql(String baseId, + Date startTime, + Date endTime, + List rstcdList, + String stcd, + String type, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT a.dt AS dt, b.cnt AS cnt ") + .append("FROM (") + .append("SELECT TO_CHAR(hb.TM, 'yyyy-MM-dd') AS dt ") + .append("FROM SD_AIHEARTBEAT_R hb ") + .append("INNER JOIN SD_AIMONITOR_B_H ai ON ai.STCD = hb.STCD ") + .append("WHERE NVL(hb.IS_DELETED, 0) = 0 ") + .append("AND NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP LIKE 'AI_%' "); + appendAiRecordFilterSql(sql, "aiRecordHeartbeat", "ai", "hb", baseId, startTime, endTime, rstcdList, stcd, type, paramMap); + sql.append("GROUP BY TO_CHAR(hb.TM, 'yyyy-MM-dd') ") + .append("UNION ") + .append("SELECT TO_CHAR(rec.TM, 'yyyy-MM-dd') AS dt ") + .append("FROM SD_AICOM_R rec ") + .append("INNER JOIN SD_AIMONITOR_B_H ai ON ai.STCD = rec.STCD ") + .append("WHERE NVL(rec.IS_DELETED, 0) = 0 ") + .append("AND NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP LIKE 'AI_%' "); + appendAiRecordFilterSql(sql, "aiRecordAicomDate", "ai", "rec", baseId, startTime, endTime, rstcdList, stcd, type, paramMap); + sql.append("GROUP BY TO_CHAR(rec.TM, 'yyyy-MM-dd') ") + .append(") a ") + .append("LEFT JOIN (") + .append("SELECT TO_CHAR(rec.TM, 'yyyy-MM-dd') AS dt, COUNT(1) AS cnt ") + .append("FROM SD_AICOM_R rec ") + .append("INNER JOIN SD_AIMONITOR_B_H ai ON ai.STCD = rec.STCD ") + .append("WHERE NVL(rec.IS_DELETED, 0) = 0 ") + .append("AND NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP LIKE 'AI_%' "); + appendAiRecordFilterSql(sql, "aiRecordAicomCnt", "ai", "rec", baseId, startTime, endTime, rstcdList, stcd, type, paramMap); + sql.append("GROUP BY TO_CHAR(rec.TM, 'yyyy-MM-dd') ") + .append(") b ON a.dt = b.dt ") + .append("ORDER BY a.dt"); + return sql.toString(); + } + private String buildAlarmPointBaseSql() { return "SELECT " + "eng.STCD AS stcd, " + @@ -533,6 +592,48 @@ public class WarnDataServiceImpl implements WarnDataService { } } + private void appendAiRecordFilterSql(StringBuilder sql, + String keyPrefix, + String aiAlias, + String recordAlias, + String baseId, + Date startTime, + Date endTime, + List rstcdList, + String stcd, + String type, + Map paramMap) { + if (StrUtil.isNotBlank(baseId)) { + paramMap.put(keyPrefix + "BaseId", baseId.trim()); + sql.append("AND ").append(aiAlias).append(".BASE_ID = #{map.").append(keyPrefix).append("BaseId} "); + } + if (StrUtil.isNotBlank(stcd)) { + paramMap.put(keyPrefix + "Stcd", stcd.trim()); + sql.append("AND ").append(aiAlias).append(".STCD = #{map.").append(keyPrefix).append("Stcd} "); + } + if (StrUtil.isNotBlank(type)) { + paramMap.put(keyPrefix + "Type", type.trim()); + sql.append("AND ").append(aiAlias).append(".STTP = #{map.").append(keyPrefix).append("Type} "); + } + if (CollUtil.isNotEmpty(rstcdList)) { + List placeholders = new ArrayList<>(); + for (int i = 0; i < rstcdList.size(); i++) { + String key = keyPrefix + "Rstcd" + i; + paramMap.put(key, rstcdList.get(i)); + placeholders.add("#{map." + key + "}"); + } + sql.append("AND ").append(aiAlias).append(".RSTCD IN (").append(String.join(", ", placeholders)).append(") "); + } + if (startTime != null) { + paramMap.put(keyPrefix + "StartTime", startTime); + sql.append("AND ").append(recordAlias).append(".TM >= #{map.").append(keyPrefix).append("StartTime} "); + } + if (endTime != null) { + paramMap.put(keyPrefix + "EndTime", endTime); + sql.append("AND ").append(recordAlias).append(".TM <= #{map.").append(keyPrefix).append("EndTime} "); + } + } + private Map buildAlarmPointYearRange(String yearText) { Date endTime = new Date(); String currentYear = String.valueOf(DateUtil.year(endTime)); @@ -720,6 +821,23 @@ public class WarnDataServiceImpl implements WarnDataService { } } + private void fillAiRecordStatus(List list) { + if (CollUtil.isEmpty(list)) { + return; + } + for (AiRecordVo item : list) { + if (item == null) { + continue; + } + if (item.getCnt() != null) { + item.setStatus(3); + } else { + item.setStatus(4); + } + item.setStatusName(resolveAiStatusName(item.getStatus())); + } + } + private String resolveAiStatusName(Integer status) { if (status == null) { return null; From d2199e47b8ce266e00ee4a01c9a42f1e29c5318e Mon Sep 17 00:00:00 2001 From: tangwei Date: Wed, 24 Jun 2026 10:02:29 +0800 Subject: [PATCH 35/38] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wq/service/impl/EnvWqDataServiceImpl.java | 65 +++++++++++++------ 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/impl/EnvWqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/impl/EnvWqDataServiceImpl.java index 6910a908..32f2c970 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/impl/EnvWqDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/impl/EnvWqDataServiceImpl.java @@ -3,15 +3,7 @@ package com.yfd.platform.qgc_env.wq.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.CommonConstant; -import com.yfd.platform.common.DataSourceLoadOptionsBase; -import com.yfd.platform.common.DataSourceRequest; -import com.yfd.platform.common.DataSourceResult; -import com.yfd.platform.common.Group; -import com.yfd.platform.common.GroupHelper; -import com.yfd.platform.common.GroupingInfo; -import com.yfd.platform.common.MicroservicDynamicSQLMapper; -import com.yfd.platform.common.PageInfo; +import com.yfd.platform.common.*; import com.yfd.platform.common.exception.BizException; import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo; import com.yfd.platform.qgc_base.entity.vo.DataParam; @@ -694,6 +686,7 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { baseSql.append("SELECT ") .append("NVL(t.IS_DELETED, 0) AS isDeleted, ") .append("t.STTP AS sttpCode, ") + .append("t.WARN_STATE AS warnState, ") .append("t.MWAY AS mway, ") .append("t.DTIN_TYPE AS dtinType, ") .append("t.STCD AS stcd, ") @@ -731,6 +724,8 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { DataSourceResult result = new DataSourceResult(); if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { result.setData(new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else if (groupInfos != null && groupInfos.length == 1 && groupInfos[0] != null && StrUtil.isNotBlank(groupInfos[0].getSelector())) { + result.setData(toMsstbprptLegacyGroups(rows, groupInfos[0].getSelector())); } else { result.setData(toLegacyGroupResult(new GroupHelper().group(rows, Arrays.asList(groupInfos)), 0)); } @@ -3181,14 +3176,17 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { return result; } String upperField = groupField == null ? "DTINTYPE" : groupField.toUpperCase(); - String countField = "COUNT_" + upperField; - String aggregateKey = "count_" + groupField; for (Map row : rows) { Object key = row.get(upperField); if (key == null) { key = row.get(groupField); } + String countField = row.containsKey("COUNT_STCD") ? "COUNT_STCD" : "COUNT_" + upperField; + String aggregateKey = "COUNT_STCD".equals(countField) ? "count_stcd" : "count_" + groupField; Object countValue = row.get(countField); + if (countValue == null) { + countValue = row.get("count_stcd"); + } if (countValue == null) { countValue = row.get("count_" + upperField); } @@ -3208,7 +3206,7 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { detail.put(upperField, key); detail.put(countField, count); item.put("items", List.of(detail)); - item.put("count", count); + item.put("count", 0); item.put("summary", new Object[0]); Map aggregates = new LinkedHashMap<>(); @@ -3224,27 +3222,52 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { return baseSql; } List groupFields = new ArrayList<>(); + List selectItems = new ArrayList<>(); List orderByItems = new ArrayList<>(); for (GroupingInfo item : groupInfos) { if (item == null || StrUtil.isBlank(item.getSelector())) { continue; } - groupFields.add(item.getSelector()); + String selector = item.getSelector(); + groupFields.add(selector); + selectItems.add(selector + " AS " + selector.toUpperCase()); String dir = Boolean.TRUE.equals(item.getDesc()) ? "DESC" : "ASC"; - orderByItems.add(item.getSelector() + " " + dir); + orderByItems.add(selector + " " + dir); + boolean hasCountStcd = false; + if (CollUtil.isNotEmpty(item.getSummaryInfos())) { + for (SummaryInfo summaryInfo : item.getSummaryInfos()) { + if (summaryInfo == null || StrUtil.isBlank(summaryInfo.getSelector()) || StrUtil.isBlank(summaryInfo.getSummaryType())) { + continue; + } + String summaryType = summaryInfo.getSummaryType().toUpperCase(); + String summarySelector = summaryInfo.getSelector().toUpperCase(); + if ("count".equalsIgnoreCase(summaryInfo.getSummaryType()) && "stcd".equalsIgnoreCase(summaryInfo.getSelector())) { + hasCountStcd = true; + } + switch (summaryInfo.getSummaryType().toLowerCase()) { + case "count" -> selectItems.add("COUNT(" + summaryInfo.getSelector() + ") AS " + summaryType + "_" + summarySelector); + case "sum" -> selectItems.add("SUM(" + summaryInfo.getSelector() + ") AS " + summaryType + "_" + summarySelector); + case "avg", "average" -> selectItems.add("AVG(" + summaryInfo.getSelector() + ") AS AVG_" + summarySelector); + case "min" -> selectItems.add("MIN(" + summaryInfo.getSelector() + ") AS " + summaryType + "_" + summarySelector); + case "max" -> selectItems.add("MAX(" + summaryInfo.getSelector() + ") AS " + summaryType + "_" + summarySelector); + default -> { + } + } + } + } + if (!hasCountStcd) { + selectItems.add("COUNT(*) AS COUNT_STCD"); + } } if (groupFields.isEmpty()) { return baseSql; } StringBuilder sql = new StringBuilder("SELECT "); - sql.append(String.join(", ", groupFields)); - for (String groupField : groupFields) { - sql.append(", COUNT(*) AS count_").append(groupField).append(" "); - } - sql.append("FROM (").append(baseSql).append(") T ") - .append("GROUP BY ").append(String.join(", ", groupFields)).append(" "); + sql.append(String.join(", ", selectItems)); + sql.append(" FROM (").append(baseSql).append(") T ") + .append(" GROUP BY ").append(String.join(", ", groupFields)).append(" "); if (!orderByItems.isEmpty()) { - sql.append("ORDER BY ").append(String.join(", ", orderByItems)); + sql.append(" ORDER BY ").append(String.join(", ", orderByItems)); } return sql.toString(); } From 201c36e3b68c75e6b46b2a92f58d0aa479f7f909 Mon Sep 17 00:00:00 2001 From: tangwei Date: Wed, 24 Jun 2026 10:19:38 +0800 Subject: [PATCH 36/38] =?UTF-8?q?feat:=20=E7=9B=91=E6=B5=8B=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E5=91=8A=E8=AD=A6=E6=83=85=E5=86=B5=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../warn/controller/WarnDataController.java | 6 + .../warn/entity/vo/StcdWarnStateVo.java | 59 +++ .../qgc_env/warn/service/WarnDataService.java | 3 + .../service/impl/WarnDataServiceImpl.java | 443 ++++++++++++++++++ 4 files changed, 511 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/StcdWarnStateVo.java 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 index 9d29dd2e..00421006 100644 --- 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 @@ -68,4 +68,10 @@ public class WarnDataController { public ResponseResult getAlarmPointKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(warnDataService.getAlarmPointKendoListCust(dataSourceRequest)); } + + @PostMapping("/stcd/GetKendoListCust") + @Operation(summary = "监测设备告警情况列表") + public ResponseResult getWarnStcdKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getWarnStcdKendoListCust(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/StcdWarnStateVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/StcdWarnStateVo.java new file mode 100644 index 00000000..91edb18c --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/StcdWarnStateVo.java @@ -0,0 +1,59 @@ +package com.yfd.platform.qgc_env.warn.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Date; + +@Data +@Schema(description = "监测设备告警情况") +public class StcdWarnStateVo { + + @Schema(description = "测站编码") + private String stcd; + + @Schema(description = "测站名称") + private String stnm; + + @Schema(description = "电站编码") + private String rstcd; + + @Schema(description = "电站名称") + private String ennm; + + @Schema(description = "监测方式") + private Integer mway; + + @Schema(description = "测站类型编码") + private String sttpCode; + + @Schema(description = "测站类型名称") + private String sttpName; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "基地名称") + private String baseName; + + @Schema(description = "流域编码") + private String rvcd; + + @Schema(description = "告警状态") + private Integer warnState; + + @Schema(description = "告警状态名称") + private String warnstateName; + + @Schema(description = "告警时间") + private Date warnTm; + + @Schema(description = "基础排序") + private Integer baseStepSort; + + @Schema(description = "电站排序") + private Integer rstcdStepSort; + + @Schema(description = "数据接入类型") + private Integer dtinType; +} 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 index acc3b40b..eccdcb72 100644 --- 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 @@ -9,6 +9,7 @@ import com.yfd.platform.qgc_env.warn.entity.vo.AiDmRunVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiComListVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiRstcdVo; import com.yfd.platform.qgc_env.warn.entity.vo.EngWarnCountVo; +import com.yfd.platform.qgc_env.warn.entity.vo.StcdWarnStateVo; import java.util.List; @@ -29,4 +30,6 @@ public interface WarnDataService { List getAiRecordKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getAlarmPointKendoListCust(DataSourceRequest dataSourceRequest); + + DataSourceResult getWarnStcdKendoListCust(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 index 8f5e190f..d6b57df6 100644 --- 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 @@ -17,6 +17,7 @@ import com.yfd.platform.qgc_env.warn.entity.vo.AiProtectVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiRecordVo; import com.yfd.platform.qgc_env.warn.entity.vo.AiRstcdVo; import com.yfd.platform.qgc_env.warn.entity.vo.EngWarnCountVo; +import com.yfd.platform.qgc_env.warn.entity.vo.StcdWarnStateVo; import com.yfd.platform.qgc_env.warn.service.WarnDataService; import com.yfd.platform.utils.QgcQueryWrapperUtil; import jakarta.annotation.Resource; @@ -297,6 +298,62 @@ public class WarnDataServiceImpl implements WarnDataService { return result; } + @Override + public DataSourceResult getWarnStcdKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String warnType = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "warnType"); + String rvcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rvcd"); + + Map paramMap = new HashMap<>(); + String filterSql = buildWarnStcdFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("r.stcd AS stcd, ") + .append("r.stnm AS stnm, ") + .append("r.rstcd AS rstcd, ") + .append("r.ennm AS ennm, ") + .append("r.mway AS mway, ") + .append("r.sttpCode AS sttpCode, ") + .append("r.sttpName AS sttpName, ") + .append("r.baseId AS baseId, ") + .append("r.baseName AS baseName, ") + .append("r.rvcd AS rvcd, ") + .append("r.warnState AS warnState, ") + .append("r.baseStepSort AS baseStepSort, ") + .append("r.rstcdStepSort AS rstcdStepSort, ") + .append("r.dtinType AS dtinType ") + .append("FROM (") + .append(buildWarnStcdDetailSql(warnType)) + .append(") r WHERE 1 = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildWarnStcdOrderBySql( + dataSourceRequest == null ? null : dataSourceRequest.getSort(), + rvcd + )); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + StcdWarnStateVo.class + ); + fillWarnStcdData(list, warnType); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page == null ? list.size() : page.getTotal()); + result.setAggregates(new HashMap<>()); + return result; + } + private AiDmRunVo buildAiDmRunVo(Map row) { if (row == null || row.isEmpty()) { return null; @@ -308,6 +365,371 @@ public class WarnDataServiceImpl implements WarnDataService { return vo; } + private String buildWarnStcdDetailSql(String warnType) { + String normalizedWarnStateExpr = "CASE " + + "WHEN eng.WARN_STATE = '0' OR eng.WARN_STATE IS NULL OR eng.WARN_STATE = '' THEN '00' " + + "ELSE eng.WARN_STATE END"; + String nonEngWarnStateExpr = "CASE state.STD_SSTATE " + + "WHEN 2 THEN 0 " + + "WHEN 3 THEN 2 " + + "ELSE state.STD_SSTATE END"; + + List parts = new ArrayList<>(); + if ("QEC".equalsIgnoreCase(warnType)) { + parts.add(buildWarnStcdEngSql(normalizedWarnStateExpr, warnType)); + } else { + parts.add(buildWarnStcdEngSql(normalizedWarnStateExpr, warnType)); + parts.add(buildWarnStcdWqSql(nonEngWarnStateExpr)); + parts.add(buildWarnStcdWtSql(nonEngWarnStateExpr)); + } + return String.join(" UNION ALL ", parts); + } + + private String buildWarnStcdEngSql(String normalizedWarnStateExpr, String warnType) { + String warnStateExpr; + if ("RZ".equalsIgnoreCase(warnType)) { + warnStateExpr = "TO_NUMBER(SUBSTR(" + normalizedWarnStateExpr + ", 1, 1))"; + } else if ("QEC".equalsIgnoreCase(warnType)) { + warnStateExpr = "NVL(TO_NUMBER(SUBSTR(" + normalizedWarnStateExpr + ", 2, 1)), 0)"; + } else { + warnStateExpr = "TO_NUMBER(NULLIF(eng.WARN_STATE, ''))"; + } + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("eng.STCD AS stcd, ") + .append("eng.ENNM AS stnm, ") + .append("CAST(NULL AS VARCHAR2(32)) AS rstcd, ") + .append("eng.ENNM AS ennm, ") + .append("CAST(NULL AS NUMBER) AS mway, ") + .append("'ENG' AS sttpCode, ") + .append("sttp.STTP_NAME AS sttpName, ") + .append("eng.BASE_ID AS baseId, ") + .append("NVL(hb.BASENAME, eng.BASE_NAME) AS baseName, ") + .append("eng.HBRVCD AS rvcd, ") + .append(warnStateExpr).append(" AS warnState, ") + .append("hb.ORDER_INDEX AS baseStepSort, ") + .append("eng.ORDER_INDEX AS rstcdStepSort, ") + .append("CAST(NULL AS NUMBER) AS dtinType ") + .append("FROM SD_ENGINFO_B_H eng ") + .append("LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = 'ENG' AND NVL(sttp.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(eng.IS_DELETED, 0) = 0 "); + if ("QEC".equalsIgnoreCase(warnType)) { + sql.append("AND NVL(eng.BLDSTT_CODE, -1) = 2 ") + .append("AND NVL(eng.DTIN, 0) = 1 ") + .append("AND NVL(eng.RUN_STATE, 2) = 4 "); + } else { + sql.append("AND NVL(eng.USFL, 0) = 1 "); + } + return sql.toString(); + } + + private String buildWarnStcdWqSql(String warnStateExpr) { + return "SELECT " + + "wq.STCD AS stcd, " + + "wq.STNM AS stnm, " + + "wq.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "wq.MWAY AS mway, " + + "wq.STTP AS sttpCode, " + + "sttp.STTP_NAME AS sttpName, " + + "eng.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName, " + + "eng.HBRVCD AS rvcd, " + + warnStateExpr + " AS warnState, " + + "hb.ORDER_INDEX AS baseStepSort, " + + "eng.ORDER_INDEX AS rstcdStepSort, " + + "wq.DTIN_TYPE AS dtinType " + + "FROM SD_WQ_B_H wq " + + "LEFT JOIN (" + buildWarnStcdLatestStateSql() + ") state ON state.STCD = wq.STCD AND state.STTP_CODE = wq.STTP " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wq.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = wq.STTP AND NVL(sttp.IS_DELETED, 0) = 0 " + + "WHERE NVL(wq.IS_DELETED, 0) = 0 " + + "AND NVL(wq.USFL, 0) = 1 " + + "AND wq.STTP IN ('WQ', 'WQFB') "; + } + + private String buildWarnStcdWtSql(String warnStateExpr) { + return "SELECT " + + "wt.STCD AS stcd, " + + "wt.STNM AS stnm, " + + "wt.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "wt.MWAY AS mway, " + + "wt.STTP AS sttpCode, " + + "sttp.STTP_NAME AS sttpName, " + + "eng.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName, " + + "eng.HBRVCD AS rvcd, " + + warnStateExpr + " AS warnState, " + + "hb.ORDER_INDEX AS baseStepSort, " + + "eng.ORDER_INDEX AS rstcdStepSort, " + + "wt.DTIN_TYPE AS dtinType " + + "FROM SD_WT_B_H wt " + + "LEFT JOIN (" + buildWarnStcdLatestStateSql() + ") state ON state.STCD = wt.STCD AND state.STTP_CODE = wt.STTP " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = wt.STTP AND NVL(sttp.IS_DELETED, 0) = 0 " + + "WHERE NVL(wt.IS_DELETED, 0) = 0 " + + "AND NVL(wt.USFL, 0) = 1 " + + "AND wt.STTP = 'WTRV' "; + } + + private String buildWarnStcdLatestStateSql() { + return "SELECT s.STCD, s.STTP_CODE, s.STD_SSTATE " + + "FROM MS_STSTATE_T s " + + "INNER JOIN (" + + "SELECT STCD, MAX(YR) AS MAX_YR " + + "FROM MS_STSTATE_T " + + "WHERE NVL(IS_DELETED, 0) = 0 " + + "GROUP BY STCD" + + ") mx ON mx.STCD = s.STCD AND mx.MAX_YR = s.YR " + + "WHERE NVL(s.IS_DELETED, 0) = 0"; + } + + private String buildWarnStcdFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + List parts = new ArrayList<>(); + if (CollUtil.isNotEmpty(filter.getFilters())) { + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildWarnStcdFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + parts.add(childSql); + } + } + if (parts.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return "(" + String.join(logic, parts) + ")"; + } + if ("warnType".equalsIgnoreCase(filter.getField())) { + return ""; + } + String column = mapWarnStcdColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String paramKey = "warnStcdParam" + indexHolder[0]++; + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + Object value = filter.getValue(); + switch (operator) { + case "eq": + paramMap.put(paramKey, normalizeWarnStcdValue(filter.getField(), value)); + return column + " = #{map." + paramKey + "}"; + case "neq": + paramMap.put(paramKey, normalizeWarnStcdValue(filter.getField(), value)); + return column + " <> #{map." + paramKey + "}"; + case "contains": + paramMap.put(paramKey, "%" + safeString(value) + "%"); + return column + " LIKE #{map." + paramKey + "}"; + case "doesnotcontain": + paramMap.put(paramKey, "%" + safeString(value) + "%"); + return column + " NOT LIKE #{map." + paramKey + "}"; + case "startswith": + paramMap.put(paramKey, safeString(value) + "%"); + return column + " LIKE #{map." + paramKey + "}"; + case "endswith": + paramMap.put(paramKey, "%" + safeString(value)); + return column + " LIKE #{map." + paramKey + "}"; + case "gt": + paramMap.put(paramKey, normalizeWarnStcdValue(filter.getField(), value)); + return column + " > #{map." + paramKey + "}"; + case "gte": + paramMap.put(paramKey, normalizeWarnStcdValue(filter.getField(), value)); + return column + " >= #{map." + paramKey + "}"; + case "lt": + paramMap.put(paramKey, normalizeWarnStcdValue(filter.getField(), value)); + return column + " < #{map." + paramKey + "}"; + case "lte": + paramMap.put(paramKey, normalizeWarnStcdValue(filter.getField(), value)); + return column + " <= #{map." + paramKey + "}"; + case "isnull": + return column + " IS NULL"; + case "isnotnull": + return column + " IS NOT NULL"; + case "isempty": + return "(" + column + " IS NULL OR " + column + " = '')"; + case "isnotempty": + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + case "in": + return buildWarnStcdInSql(column, value, paramKey, paramMap); + default: + return ""; + } + } + + private String buildWarnStcdInSql(String column, Object value, String paramKey, Map paramMap) { + List values = parseAiCodes(value == null ? null : String.valueOf(value)); + if (CollUtil.isEmpty(values)) { + return ""; + } + List placeholders = new ArrayList<>(); + for (int i = 0; i < values.size(); i++) { + String key = paramKey + "_" + i; + paramMap.put(key, values.get(i)); + placeholders.add("#{map." + key + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + + private String mapWarnStcdColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd" -> "r.stcd"; + case "stnm" -> "r.stnm"; + case "rstcd" -> "r.rstcd"; + case "ennm" -> "r.ennm"; + case "mway" -> "r.mway"; + case "sttpCode" -> "r.sttpCode"; + case "sttpName" -> "r.sttpName"; + case "baseId" -> "r.baseId"; + case "baseName" -> "r.baseName"; + case "rvcd" -> "r.rvcd"; + case "warnState" -> "r.warnState"; + case "dtinType" -> "r.dtinType"; + default -> null; + }; + } + + private Object normalizeWarnStcdValue(String field, Object value) { + if ("warnState".equals(field) || "mway".equals(field) || "dtinType".equals(field)) { + return toIntegerValue(value); + } + return value; + } + + private String buildWarnStcdOrderBySql(List sortList, String rvcd) { + if (CollUtil.isEmpty(sortList)) { + if (StrUtil.isNotBlank(rvcd)) { + return " ORDER BY r.rstcdStepSort ASC NULLS LAST "; + } + return ""; + } + List orderItems = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor item : sortList) { + if (item == null || StrUtil.isBlank(item.getField())) { + continue; + } + String column = mapWarnStcdColumn(item.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(item.getDir()) ? "DESC" : "ASC"; + orderItems.add(column + " " + dir); + } + if (orderItems.isEmpty()) { + if (StrUtil.isNotBlank(rvcd)) { + return " ORDER BY r.rstcdStepSort ASC NULLS LAST "; + } + return ""; + } + return " ORDER BY " + String.join(", ", orderItems); + } + + private void fillWarnStcdData(List list, String warnType) { + if (CollUtil.isEmpty(list)) { + return; + } + Map engRzWarnTmMap = new HashMap<>(); + Map engQecWarnTmMap = new HashMap<>(); + Map wqWarnTmMap = new HashMap<>(); + Map wtWarnTmMap = new HashMap<>(); + + if ("RZ".equalsIgnoreCase(warnType)) { + engRzWarnTmMap = getWarnRecordTimeMap(collectWarnStcds(list, "ENG"), "HYDROPW_R"); + } else if ("QEC".equalsIgnoreCase(warnType)) { + engQecWarnTmMap = getWarnRecordTimeMap(collectWarnStcds(list, "ENG"), "QEC_R"); + } + wqWarnTmMap = getWarnRecordTimeMap(collectWarnStcds(list, "WQ", "WQFB"), "WQ_R"); + wtWarnTmMap = getWarnRecordTimeMap(collectWarnStcds(list, "WTRV"), "WTRV_R"); + + for (StcdWarnStateVo item : list) { + if (item == null) { + continue; + } + item.setWarnstateName(resolveWarnStateName(item.getWarnState())); + if (!Integer.valueOf(2).equals(item.getWarnState())) { + continue; + } + if ("ENG".equalsIgnoreCase(item.getSttpCode()) && "RZ".equalsIgnoreCase(warnType)) { + item.setWarnTm(defaultWarnTm(engRzWarnTmMap.get(item.getStcd()))); + } else if ("ENG".equalsIgnoreCase(item.getSttpCode()) && "QEC".equalsIgnoreCase(warnType)) { + item.setWarnTm(defaultWarnTm(engQecWarnTmMap.get(item.getStcd()))); + } else if ("WTRV".equalsIgnoreCase(item.getSttpCode())) { + item.setWarnTm(defaultWarnTm(wtWarnTmMap.get(item.getStcd()))); + } else if ("WQ".equalsIgnoreCase(item.getSttpCode()) || "WQFB".equalsIgnoreCase(item.getSttpCode())) { + item.setWarnTm(defaultWarnTm(wqWarnTmMap.get(item.getStcd()))); + } else { + item.setWarnTm(new Date()); + } + } + } + + private List collectWarnStcds(List list, String... sttpCodes) { + List result = new ArrayList<>(); + if (CollUtil.isEmpty(list) || sttpCodes == null || sttpCodes.length == 0) { + return result; + } + List sttpCodeList = Arrays.asList(sttpCodes); + for (StcdWarnStateVo item : list) { + if (item == null || !Integer.valueOf(2).equals(item.getWarnState())) { + continue; + } + if (!sttpCodeList.contains(item.getSttpCode())) { + continue; + } + if (StrUtil.isNotBlank(item.getStcd()) && !result.contains(item.getStcd())) { + result.add(item.getStcd()); + } + } + return result; + } + + private Map getWarnRecordTimeMap(List stcdList, String tbCode) { + Map result = new HashMap<>(); + if (CollUtil.isEmpty(stcdList) || StrUtil.isBlank(tbCode)) { + return result; + } + Map paramMap = new HashMap<>(); + List placeholders = new ArrayList<>(); + for (int i = 0; i < stcdList.size(); i++) { + String key = "warnRecordStcd" + i; + paramMap.put(key, stcdList.get(i)); + placeholders.add("#{map." + key + "}"); + } + paramMap.put("warnRecordTbCode", tbCode); + String sql = "SELECT rec.STCD AS stcd, MAX(rec.BTM) AS warnTm " + + "FROM MS_WARN_RECORD_W rec " + + "INNER JOIN ST_TB_B tb ON tb.ID = rec.TB_ID AND NVL(tb.IS_DELETED, 0) = 0 " + + "WHERE NVL(rec.IS_DELETED, 0) = 0 " + + "AND NVL(rec.SFGB, 'N') = 'N' " + + "AND tb.TB_CODE = #{map.warnRecordTbCode} " + + "AND rec.STCD IN (" + String.join(", ", placeholders) + ") " + + "GROUP BY rec.STCD"; + List> rows = microservicDynamicSQLMapper.getAllList(sql, paramMap); + for (Map row : rows) { + String stcd = safeString(firstPresentValue(row, "STCD", "stcd")); + Date warnTm = toDateValue(firstPresentValue(row, "WARNTM", "warnTm")); + if (StrUtil.isNotBlank(stcd) && warnTm != null) { + result.put(stcd, warnTm); + } + } + return result; + } + + private Date defaultWarnTm(Date warnTm) { + return warnTm == null ? new Date() : warnTm; + } + private String buildAiRstcdListSql(String baseId, Date startTime, Date endTime, @@ -1364,6 +1786,27 @@ public class WarnDataServiceImpl implements WarnDataService { } } + private Date toDateValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof Date date) { + return date; + } + if (value instanceof Number number) { + return new Date(number.longValue()); + } + String text = String.valueOf(value).trim(); + if (StrUtil.isBlank(text)) { + return null; + } + try { + return DateUtil.parse(text).toJdkDate(); + } catch (Exception ex) { + return null; + } + } + private BigDecimal toBigDecimalValue(Object value) { if (value == null) { return null; From 8567930f94f585ac0d6ca792f8792f42951cb778 Mon Sep 17 00:00:00 2001 From: tangwei Date: Wed, 24 Jun 2026 10:38:39 +0800 Subject: [PATCH 37/38] =?UTF-8?q?feat:=20=E5=85=A8=E8=BF=87=E7=A8=8B?= =?UTF-8?q?=E9=B1=BC=E7=B1=BB=E6=94=BE=E9=B1=BC=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fb/controller/FbStationController.java | 6 + .../qgc_env/fb/entity/vo/FbFishRunQgcVo.java | 37 ++ .../qgc_env/fb/service/FbStationService.java | 3 + .../fb/service/impl/FbStationServiceImpl.java | 408 ++++++++++++++++++ 4 files changed, 454 insertions(+) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishRunQgcVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java index de45344c..9d05bd9f 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java @@ -91,6 +91,12 @@ public class FbStationController { return ResponseResult.successData(fbStationService.getFishCountKendoListCust(dataSourceRequest)); } + @PostMapping("/fishrun/qgc/GetKendoListCust") + @Operation(summary = "全过程鱼类放鱼数据") + public ResponseResult getFishRunQgcKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getFishRunQgcKendoListCust(dataSourceRequest)); + } + @PostMapping("/fishType/GetKendoListCust") @Operation(summary = "增殖站鱼种完成情况统计") public ResponseResult getFishTypeKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishRunQgcVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishRunQgcVo.java new file mode 100644 index 00000000..8c844de7 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishRunQgcVo.java @@ -0,0 +1,37 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import lombok.Data; + +@Data +public class FbFishRunQgcVo { + + private String stcd; + + private String stnm; + + private String ftp; + + private String ftpName; + + private String baseId; + + private String baseName; + + private String flyr; + + private Long fcnt; + + private Long totalFcnt; + + private String fid; + + private String release; + + private Integer baseStepSort; + + private Integer siteStepSort; + + private Integer rvcdStepSort; + + private Integer rstcdStepSort; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java index 31513088..1bada486 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java @@ -6,6 +6,7 @@ import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRQgcVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishTableVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFlDataVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFishCountFinishVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbFishRunQgcVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFishTypeStcdVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFishTypeFinishVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbRelatedYrVo; @@ -31,6 +32,8 @@ public interface FbStationService { DataSourceResult getFishCountKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getFishRunQgcKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getFishTypeKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getFishTypeStcdList(DataSourceRequest dataSourceRequest); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java index 0f3d8830..a3e50842 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java @@ -16,6 +16,7 @@ import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishHeadColumnVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishSummaryVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishTableVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFishCountFinishVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbFishRunQgcVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFishTypeStcdVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFishTypeFinishVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFtpStatisticsVo; @@ -118,6 +119,66 @@ public class FbStationServiceImpl implements FbStationService { return result; } + @Override + public DataSourceResult getFishRunQgcKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String flyrFilter = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "flyr"); + String rstcdFilter = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); + Date[] flyrRange = parseFishRunFlyrRange(flyrFilter); + + Map paramMap = new HashMap<>(); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT r.stcd AS stcd, ") + .append("r.stnm AS stnm, ") + .append("r.baseId AS baseId, ") + .append("r.baseName AS baseName, ") + .append("r.baseStepSort AS baseStepSort, ") + .append("r.siteStepSort AS siteStepSort, ") + .append("r.rvcdStepSort AS rvcdStepSort, ") +// .append("r.rstcdStepSort AS rstcdStepSort, ") + .append("r.flyr AS flyr, ") + .append("r.ftp AS ftp, ") + .append("r.ftpName AS ftpName, ") + .append("r.fcnt AS fcnt, ") + .append("r.totalFcnt AS totalFcnt, ") + .append("r.fid AS fid, ") + .append("r.release AS release ") + .append("FROM (") + .append(buildFishRunQgcBaseSql( + parseFishTypeFilterValues(rstcdFilter), + flyrRange[0], + flyrRange[1], + paramMap + )) + .append(") r WHERE 1 = 1 "); + + String filterSql = buildFishRunQgcFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildFishRunQgcOrderBySql(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, + FbFishRunQgcVo.class + ); + normalizeFishRunQgcRows(list); + appendFishRunMissingYears(list, flyrRange[0], flyrRange[1], page); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + @Override public DataSourceResult getFishTypeKendoListCust(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -953,6 +1014,353 @@ public class FbStationServiceImpl implements FbStationService { return " ORDER BY " + String.join(", ", orderByParts); } + private String buildFishRunQgcBaseSql(List stcdList, + Date startTime, + Date endTime, + Map paramMap) { + String ftpNameExpr = buildFishNameExpr("agg.FTP"); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT agg.STCD AS stcd, ") + .append("eng.ENNM AS stnm, ") + .append("eng.BASE_ID AS baseId, ") + .append("NVL(hb.BASENAME, eng.BASE_NAME) AS baseName, ") + .append("hb.ORDER_INDEX AS baseStepSort, ") + .append("siteAlong.SORT AS siteStepSort, ") + .append("along.ORDER_INDEX AS rvcdStepSort, ") +// .append("rstAlong.SORT AS rstcdStepSort, ") + .append("TO_CHAR(agg.FLYR) AS flyr, ") + .append("COALESCE(TO_CHAR(NVL(relRv.ZY_FISH_ID, relRv.FISH_ID)), ") + .append("TO_CHAR(NVL(relZy.ZY_FISH_ID, relZy.FISH_ID)), TO_CHAR(agg.FTP)) AS ftp, ") + .append(ftpNameExpr).append(" AS ftpName, ") + .append("agg.FCNT AS fcnt, ") + .append("totalAgg.TOTALFCNT AS totalFcnt, ") + .append("agg.FID AS fid, ") + .append("agg.RELEASE AS release ") + .append("FROM (") + .append(" SELECT run.STCD AS STCD, ") + .append(" TO_NUMBER(TO_CHAR(run.TM, 'YYYY')) AS FLYR, ") + .append(" det.FTP AS FTP, ") + .append(" SUM(det.FCNT) AS FCNT, ") + .append(" MAX(run.FPRFID) || ',' || MAX(run.FLRFID) || ',' || MAX(run.BRRFID) || ',' || MAX(run.BRFFID) AS FID, ") + .append(" REGEXP_REPLACE(LISTAGG(fb.STNM, ',') WITHIN GROUP (ORDER BY fb.STCD), '([^,]+)(,\\1)+', '\\1') AS RELEASE ") + .append(" FROM SD_RPIMNFISH_R det ") + .append(" INNER JOIN SD_ENGFR_R run ON det.RPIMN_ID = run.ID ") + .append(" AND NVL(run.IS_DELETED, 0) = 0 ") + .append(" LEFT JOIN SD_FBRD_B_H fb ON fb.STCD = run.RSTCD ") +// .append(" AND NVL(fb.IS_DELETED, 0) = 0 ") + .append(" WHERE NVL(det.IS_DELETED, 0) = 0 ") + .append(" AND det.FTP IS NOT NULL "); + appendFishRunQgcTimeFilter(sql, paramMap, "run", startTime, endTime, "fishRunDetail"); + appendInCondition(sql, paramMap, "run.STCD", stcdList, "fishRunDetailStcd"); + sql.append(" GROUP BY run.STCD, det.FTP, TO_NUMBER(TO_CHAR(run.TM, 'YYYY')) ") + .append(") agg ") + .append("LEFT JOIN (") + .append(" SELECT run.STCD AS STCD, ") + .append(" TO_NUMBER(TO_CHAR(run.TM, 'YYYY')) AS FLYR, ") + .append(" SUM(det.FCNT) AS TOTALFCNT ") + .append(" FROM SD_RPIMNFISH_R det ") + .append(" INNER JOIN SD_ENGFR_R run ON det.RPIMN_ID = run.ID ") + .append(" AND NVL(run.IS_DELETED, 0) = 0 ") + .append(" WHERE NVL(det.IS_DELETED, 0) = 0 ") + .append(" AND det.FTP IS NOT NULL "); + appendFishRunQgcTimeFilter(sql, paramMap, "run", startTime, endTime, "fishRunTotal"); + appendInCondition(sql, paramMap, "run.STCD", stcdList, "fishRunTotalStcd"); + sql.append(" GROUP BY run.STCD, TO_NUMBER(TO_CHAR(run.TM, 'YYYY')) ") + .append(") totalAgg ON totalAgg.STCD = agg.STCD AND totalAgg.FLYR = agg.FLYR ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = agg.STCD ") + .append(" AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID ") + .append(" AND NVL(hb.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN MS_ALONG_B along ON along.RVCD = eng.HBRVCD ") + .append(" AND along.CODE = 'common' ") + .append(" AND NVL(along.IS_DELETED, 0) = 0 ") +// .append("LEFT JOIN MS_ALONGDET_B rstAlong ON rstAlong.ALONG_ID = along.ID ") +// .append(" AND rstAlong.STCD = eng.RSTCD ") +// .append(" AND NVL(rstAlong.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN MS_ALONGDET_B siteAlong ON siteAlong.ALONG_ID = along.ID ") + .append(" AND siteAlong.STCD = eng.STCD ") + .append(" AND NVL(siteAlong.IS_DELETED, 0) = 0 ") + .append(buildFishJoinSql("agg.FTP", "eng.HBRVCD")) + .append("WHERE NVL(eng.IS_DELETED, 0) = 0 "); + return sql.toString(); + } + + private void appendFishRunQgcTimeFilter(StringBuilder sql, + Map paramMap, + String alias, + Date startTime, + Date endTime, + String keyPrefix) { + if (startTime != null) { + String startKey = keyPrefix + "Start"; + paramMap.put(startKey, startTime); + sql.append(" AND ").append(alias).append(".TM >= #{map.").append(startKey).append("} "); + } + if (endTime != null) { + String endKey = keyPrefix + "End"; + paramMap.put(endKey, endTime); + sql.append(" AND ").append(alias).append(".TM <= #{map.").append(endKey).append("} "); + } + } + + private String buildFishRunQgcFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildFishRunQgcLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildFishRunQgcFilterCondition(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 buildFishRunQgcLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if ("flyr".equalsIgnoreCase(filter.getField()) || "rstcd".equalsIgnoreCase(filter.getField())) { + return ""; + } + String column = mapFishRunQgcColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("isempty".equals(operator)) { + return "(" + column + " IS NULL OR " + column + " = '')"; + } + if ("isnotempty".equals(operator)) { + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + } + if ("in".equals(operator)) { + List values = normalizeQgcBsmfRValues(filter.getValue()); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object value : values) { + String key = "fishRunQgcP" + indexHolder[0]++; + paramMap.put(key, normalizeFishRunQgcValue(filter.getField(), value)); + placeholders.add("#{map." + key + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + Object value = filter.getValue(); + if (value == null) { + return ""; + } + String key = "fishRunQgcP" + indexHolder[0]++; + Object normalizedValue = normalizeFishRunQgcValue(filter.getField(), value); + return switch (operator) { + case "eq" -> { + paramMap.put(key, normalizedValue); + yield column + " = #{map." + key + "}"; + } + case "neq" -> { + paramMap.put(key, normalizedValue); + yield column + " <> #{map." + key + "}"; + } + case "gt" -> { + paramMap.put(key, normalizedValue); + yield column + " > #{map." + key + "}"; + } + case "gte" -> { + paramMap.put(key, normalizedValue); + yield column + " >= #{map." + key + "}"; + } + case "lt" -> { + paramMap.put(key, normalizedValue); + yield column + " < #{map." + key + "}"; + } + case "lte" -> { + paramMap.put(key, normalizedValue); + yield column + " <= #{map." + key + "}"; + } + case "contains" -> { + paramMap.put(key, "%" + String.valueOf(normalizedValue).trim() + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "doesnotcontain" -> { + paramMap.put(key, "%" + String.valueOf(normalizedValue).trim() + "%"); + yield column + " NOT LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, String.valueOf(normalizedValue).trim() + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + String.valueOf(normalizedValue).trim()); + yield column + " LIKE #{map." + key + "}"; + } + default -> ""; + }; + } + + private String mapFishRunQgcColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd" -> "r.stcd"; + case "stnm" -> "r.stnm"; + case "baseId" -> "r.baseId"; + case "baseName" -> "r.baseName"; + case "flyr" -> "r.flyr"; + case "ftp" -> "r.ftp"; + case "ftpName" -> "r.ftpName"; + case "fcnt" -> "r.fcnt"; + case "totalFcnt" -> "r.totalFcnt"; + case "release" -> "r.release"; + case "baseStepSort" -> "r.baseStepSort"; + case "siteStepSort" -> "r.siteStepSort"; + case "rvcdStepSort" -> "r.rvcdStepSort"; + case "rstcdStepSort" -> "r.rstcdStepSort"; + default -> null; + }; + } + + private Object normalizeFishRunQgcValue(String field, Object value) { + if (value == null) { + return null; + } + if ("fcnt".equals(field) || "totalFcnt".equals(field) || "baseStepSort".equals(field) + || "siteStepSort".equals(field) || "rvcdStepSort".equals(field) + || "rstcdStepSort".equals(field)) { + try { + return Long.parseLong(String.valueOf(value).trim()); + } catch (Exception ex) { + return null; + } + } + return value; + } + + private String buildFishRunQgcOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return " ORDER BY r.baseStepSort ASC NULLS LAST, r.rvcdStepSort ASC NULLS LAST, " + + "r.rstcdStepSort ASC NULLS LAST, r.siteStepSort ASC NULLS LAST, r.flyr ASC, r.ftpName ASC"; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapFishRunQgcColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction); + } + if (orderByParts.isEmpty()) { + return " ORDER BY r.baseStepSort ASC NULLS LAST, r.rvcdStepSort ASC NULLS LAST, " + + "r.rstcdStepSort ASC NULLS LAST, r.siteStepSort ASC NULLS LAST, r.flyr ASC, r.ftpName ASC"; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + private Date[] parseFishRunFlyrRange(String flyrFilter) { + if (StrUtil.isBlank(flyrFilter)) { + return new Date[]{null, null}; + } + String value = flyrFilter.trim(); + if (value.matches("\\d{4}")) { + Date start = parseDateTimeSafely(value + "-01-01 00:00:00"); + Date end = parseDateTimeSafely(value + "-12-31 23:59:59"); + return new Date[]{start, end}; + } + if (!value.contains(",")) { + Date point = parseDateTimeSafely(value); + return new Date[]{point, point}; + } + String[] parts = value.split(","); + if (parts.length < 2) { + return new Date[]{null, null}; + } + Date first = parseDateTimeSafely(parts[0].trim()); + Date second = parseDateTimeSafely(parts[1].trim()); + if (first == null || second == null) { + return new Date[]{null, null}; + } + return first.after(second) ? new Date[]{second, first} : new Date[]{first, second}; + } + + private void normalizeFishRunQgcRows(List list) { + if (CollUtil.isEmpty(list)) { + return; + } + for (FbFishRunQgcVo item : list) { + if (item == null) { + continue; + } + if (item.getFid() != null) { + LinkedHashSet fidSet = Arrays.stream(item.getFid().split(",")) + .map(StrUtil::trim) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toCollection(LinkedHashSet::new)); + item.setFid(fidSet.isEmpty() ? null : String.join(",", fidSet)); + } + if (item.getRelease() != null) { + LinkedHashSet releaseSet = Arrays.stream(item.getRelease().split(",")) + .map(StrUtil::trim) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toCollection(LinkedHashSet::new)); + item.setRelease(releaseSet.isEmpty() ? null : String.join(",", releaseSet)); + } + if (item.getFcnt() == null) { + item.setFcnt(0L); + } + if (item.getTotalFcnt() == null) { + item.setTotalFcnt(0L); + } + } + } + + private void appendFishRunMissingYears(List list, Date startTime, Date endTime, Page page) { + if (page != null || startTime == null || endTime == null) { + return; + } + int startYear = Integer.parseInt(DateUtil.format(startTime, "yyyy")); + int endYear = Integer.parseInt(DateUtil.format(endTime, "yyyy")); + Set existingYears = list.stream() + .filter(Objects::nonNull) + .map(FbFishRunQgcVo::getFlyr) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toCollection(LinkedHashSet::new)); + for (int year = startYear; year <= endYear; year++) { + String yearText = String.valueOf(year); + if (existingYears.contains(yearText)) { + continue; + } + FbFishRunQgcVo vo = new FbFishRunQgcVo(); + vo.setFlyr(yearText); + vo.setFcnt(0L); + vo.setTotalFcnt(0L); + list.add(vo); + } + list.sort(Comparator.comparing(FbFishRunQgcVo::getFlyr, Comparator.nullsLast(String::compareTo))); + } + private String buildFishTypeStcdListSql(String baseId, String sttpCode, Map paramMap) { StringBuilder sql = new StringBuilder(); sql.append("SELECT fb.STCD AS stcd, fb.STNM AS stnm, fb.LGTD AS lgtd, fb.LTTD AS lttd, fb.BASE_ID AS baseId ") From f44417be84ad46295e9d11996b455d472ee5d67d Mon Sep 17 00:00:00 2001 From: tangwei Date: Wed, 24 Jun 2026 10:39:30 +0800 Subject: [PATCH 38/38] =?UTF-8?q?fix:=20=E6=B3=A8=E9=87=8A=E5=89=8D?= =?UTF-8?q?=E7=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/yfd/platform/config/SecurityConfig.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java index 0a49d30b..a43e3361 100644 --- a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java +++ b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java @@ -64,12 +64,14 @@ public class SecurityConfig { // .requestMatchers("/eng/**").permitAll() // .requestMatchers("/eq/**").permitAll() // .requestMatchers("/env/**").permitAll() +// .requestMatchers("/warn/**").permitAll() // .requestMatchers("/wt/**").permitAll() // .requestMatchers("/fb/**").permitAll() // .requestMatchers("/zq/**").permitAll() // .requestMatchers("/wq/**").permitAll() // .requestMatchers("/vd/**").permitAll() // .requestMatchers("/fp/**").permitAll() +// .requestMatchers("/fpr/**").permitAll() // .requestMatchers("/fh/**").permitAll() // .requestMatchers("/data/**").permitAll() .requestMatchers("/sms/**").permitAll()