From d42040b13385261ad1242af93985d7cc5b11c942 Mon Sep 17 00:00:00 2001 From: tangwei Date: Thu, 18 Jun 2026 09:45:06 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B2=BF=E7=A8=8B=E7=94=9F=E6=80=81?= =?UTF-8?q?=E6=B5=81=E9=87=8F=E9=99=90=E5=80=BC=E5=8F=98=E5=8C=96=E6=9B=B2?= =?UTF-8?q?=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;