feat: 沿程生态流量限值变化曲线

This commit is contained in:
tangwei 2026-06-18 09:45:06 +08:00
parent 13831737eb
commit d42040b133
5 changed files with 275 additions and 0 deletions

View File

@ -6,6 +6,8 @@ import com.yfd.platform.common.DataSourceResult;
import com.yfd.platform.config.ResponseResult; 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.EngEqDrtpDataVo;
import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqIntervalVo; 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.EngEqMsstbprptVo;
import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqRuleVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqRuleVo;
import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqVmsstbprptVo; 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.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController @RestController
@RequestMapping("/eq") @RequestMapping("/eq")
@Tag(name = "电站实时数据查询") @Tag(name = "电站实时数据查询")
@ -87,6 +91,13 @@ public class EngEqDataController {
return ResponseResult.successData(engEqDataService.getQgcHourVAlongKendoListCust(dataSourceRequest)); return ResponseResult.successData(engEqDataService.getQgcHourVAlongKendoListCust(dataSourceRequest));
} }
@PostMapping("/engalong/statistics/qgc/getEngLimit")
@Operation(summary = "沿程生态流量限值变化曲线")
public ResponseResult getQgcEngLimit(@RequestBody EngEqLimitQueryVo queryVo) {
List<EngEqLimitVo> result = engEqDataService.getQgcEngLimit(queryVo);
return ResponseResult.successData(result);
}
@PostMapping("/fid/GetKendoListCust") @PostMapping("/fid/GetKendoListCust")
@Operation(summary = "查询电站相关鱼类附件编码") @Operation(summary = "查询电站相关鱼类附件编码")
public ResponseResult getFidKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { public ResponseResult getFidKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) {

View File

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

View File

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

View File

@ -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.EngEqDayIntervalVo;
import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqHourIntervalVo; 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.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.EngEqMsstbprptVo;
import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqRuleVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqRuleVo;
import com.yfd.platform.qgc_eng.eq.entity.vo.EngQecAlongVo; 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.SdEqMonitorCountVo;
import com.yfd.platform.qgc_eng.eq.entity.vo.WbsbVo; import com.yfd.platform.qgc_eng.eq.entity.vo.WbsbVo;
import java.util.List;
public interface EngEqDataService { public interface EngEqDataService {
DataSourceResult getKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getKendoListCust(DataSourceRequest dataSourceRequest);
@ -34,6 +38,8 @@ public interface EngEqDataService {
DataSourceResult<EngQecAlongVo> getQgcHourVAlongKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult<EngQecAlongVo> getQgcHourVAlongKendoListCust(DataSourceRequest dataSourceRequest);
List<EngEqLimitVo> getQgcEngLimit(EngEqLimitQueryVo queryVo);
DataSourceResult<String> getFidKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult<String> getFidKendoListCust(DataSourceRequest dataSourceRequest);
EngEqRuleVo getEngLimit(DataSourceRequest dataSourceRequest); EngEqRuleVo getEngLimit(DataSourceRequest dataSourceRequest);

View File

@ -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.EngEqDayDataVo;
import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDrtpDataVo; 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.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.EngFidVo;
import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqHourIntervalVo; 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.EngEqIntervalVo;
@ -46,6 +48,7 @@ import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@Service @Service
@ -380,6 +383,56 @@ public class EngEqDataServiceImpl implements EngEqDataService {
return result; return result;
} }
@Override
public List<EngEqLimitVo> 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<String, Object> 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<EngEqLimitVo> stationList = microservicDynamicSQLMapper.getAllListWithResultType(
buildQgcEngLimitStationSql(baseId, rvcd),
paramMap,
EngEqLimitVo.class
);
if (CollUtil.isEmpty(stationList)) {
return new ArrayList<>();
}
List<Map<String, Object>> ruleRows = microservicDynamicSQLMapper.pageAllList(
null,
buildQgcEngLimitRuleSql(baseId, rvcd),
paramMap
);
Map<String, List<Map<String, Object>>> stationRuleMap = new HashMap<>();
for (Map<String, Object> 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 @Override
public EngEqRuleVo getEngLimit(DataSourceRequest dataSourceRequest) { public EngEqRuleVo getEngLimit(DataSourceRequest dataSourceRequest) {
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
@ -1278,6 +1331,55 @@ public class EngEqDataServiceImpl implements EngEqDataService {
return sql.toString(); 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<Map<String, Object>> queryEngLimitRuleDetails(String stcd, private List<Map<String, Object>> queryEngLimitRuleDetails(String stcd,
String startTime, String startTime,
String endTime, String endTime,
@ -1338,6 +1440,100 @@ public class EngEqDataServiceImpl implements EngEqDataService {
return prefix + String.join(";", parts); return prefix + String.join(";", parts);
} }
private BigDecimal resolveQgcEngLimitValue(Date queryDate, List<Map<String, Object>> ruleRows) {
if (queryDate == null || CollUtil.isEmpty(ruleRows)) {
return null;
}
Date currentTm = null;
List<Map<String, Object>> currentRows = new ArrayList<>();
String monthDay = DateTimeFormatter.ofPattern("MMdd").format(
queryDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()
);
for (Map<String, Object> 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<Map<String, Object>> ruleRows) {
BigDecimal defaultValue = null;
for (Map<String, Object> 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, private String buildHourIntervalViewSql(DataSourceRequest.FilterDescriptor filter,
Map<String, Object> paramMap, Map<String, Object> paramMap,
int[] indexHolder) { int[] indexHolder) {
@ -4306,6 +4502,20 @@ public class EngEqDataServiceImpl implements EngEqDataService {
return new BigDecimal(String.valueOf(value)); 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) { private String stripTrailingZeros(BigDecimal value) {
if (value == null) { if (value == null) {
return null; return null;