feat: 生态流量达标率计算优化

This commit is contained in:
tangwei 2026-06-01 19:26:17 +08:00
parent aea22ebf02
commit d3d41cb3b6
4 changed files with 297 additions and 0 deletions

View File

@ -3,6 +3,7 @@ package com.yfd.platform.qgc_eng.eq.controller;
import com.yfd.platform.common.DataSourceLoadOptionsBase;
import com.yfd.platform.common.DataSourceRequest;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqRateCountVo;
import com.yfd.platform.qgc_eng.eq.service.EngEqDataService;
import com.yfd.platform.qgc_eng.eq.entity.vo.QgcQecStaticVo;
import com.yfd.platform.utils.QgcQueryWrapperUtil;
@ -53,4 +54,10 @@ public class EngEqDataController {
public ResponseResult getEvnmAutoMonitorList(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(engEqDataService.getEvnmAutoMonitorList(dataSourceRequest));
}
@PostMapping("/qecRateCount")
@Operation(summary = "生态流量达标率计算(基地维度、不达标原因维度)")
public ResponseResult getQecRateCount(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(engEqDataService.qecRateCount(dataSourceRequest));
}
}

View File

@ -0,0 +1,50 @@
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.math.BigDecimal;
@Data
@Schema(description = "生态流量达标率统计")
public class EngEqRateCountVo implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "基地编码")
private String baseId;
@Schema(description = "基地名称")
private String baseName;
@Schema(description = "基地流域编码")
private String hbrvcd;
@Schema(description = "基地流域名称")
private String hbrvcdName;
@Schema(description = "行政区编码")
private String addvcd;
@Schema(description = "行政区名称")
private String addvcdName;
@Schema(description = "电站编码")
private String stcd;
@Schema(description = "电站名称")
private String stnm;
@Schema(description = "工程名称")
private String ennm;
@Schema(description = "调节性能编码")
private String qecPerformance;
@Schema(description = "调节性能名称")
private String qecPerformanceName;
@Schema(description = "生态流量达标率")
private BigDecimal qecRate;
}

View File

@ -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.EngEqRateCountVo;
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;
@ -15,4 +16,6 @@ public interface EngEqDataService {
DataSourceResult<WbsbVo> getWbsbList(DataSourceRequest dataSourceRequest);
DataSourceResult<SdEqMonitorCountVo> getEvnmAutoMonitorList(DataSourceRequest dataSourceRequest);
DataSourceResult<EngEqRateCountVo> qecRateCount(DataSourceRequest dataSourceRequest);
}

View File

@ -12,6 +12,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.EngEqDataVo;
import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqRateCountVo;
import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqStaticIntervalVo;
import com.yfd.platform.qgc_eng.eq.entity.vo.QgcQecStaticVo;
import com.yfd.platform.qgc_eng.eq.entity.vo.QgcQecVo;
@ -29,6 +30,9 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Service
public class EngEqDataServiceImpl implements EngEqDataService {
@ -155,6 +159,74 @@ public class EngEqDataServiceImpl implements EngEqDataService {
return result;
}
@Override
public DataSourceResult<EngEqRateCountVo> qecRateCount(DataSourceRequest dataSourceRequest) {
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
String baseId = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId");
String tm = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "tm");
String[] tmRange = resolveQecRateTimeRange(tm);
List<DataSourceRequest.GroupDescriptor> groups = dataSourceRequest == null ? null : dataSourceRequest.getGroup();
List<String> selectItems = new ArrayList<>();
List<String> groupItems = new ArrayList<>();
if (CollUtil.isNotEmpty(groups)) {
for (DataSourceRequest.GroupDescriptor group : groups) {
if (group == null || StrUtil.isBlank(group.getField())) {
continue;
}
String selectSql = mapQecRateSelect(group.getField());
String groupSql = mapQecRateGroup(group.getField());
if (StrUtil.isNotBlank(selectSql) && StrUtil.isNotBlank(groupSql)) {
selectItems.add(selectSql);
groupItems.add(groupSql);
}
}
}
StringBuilder sql = new StringBuilder();
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("startTime", tmRange[0]);
paramMap.put("endTime", tmRange[1]);
if (StrUtil.isNotBlank(baseId)) {
paramMap.put("baseId", baseId);
}
sql.append("SELECT ");
if (!selectItems.isEmpty()) {
sql.append(String.join(", ", selectItems)).append(", ");
}
sql.append(buildQecRateSql()).append(" AS qecRate ")
.append("FROM SD_ENGINFO_B_H eng ")
.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 AND hbrv.BASEID = eng.BASE_ID ")
.append(" AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 ")
.append("LEFT JOIN SD_ADDVCD_DIC addv ON addv.ADDVCD = eng.ADDVCD ")
.append("LEFT JOIN (")
.append(buildQecRateMetricSourceSql())
.append(") met ON met.STCD = eng.STCD ")
.append("WHERE NVL(eng.IS_DELETED, 0) = 0 ")
.append(" AND NVL(eng.DTIN_ENV, 0) IN (1, 2) ")
.append(" AND NVL(eng.BLDSTT_CODE, 0) = 2 ");
if (StrUtil.isNotBlank(baseId)) {
sql.append(" AND eng.BASE_ID = #{map.baseId} ");
}
if (!groupItems.isEmpty()) {
sql.append(" GROUP BY ").append(String.join(", ", groupItems)).append(" ");
sql.append(buildQecRateOrderBy(groups));
}
List<EngEqRateCountVo> list = microservicDynamicSQLMapper.getAllListWithResultType(
sql.toString(), paramMap, EngEqRateCountVo.class);
fillQecRateCountNames(list);
list = completeQecPerformanceGroups(list, groups);
DataSourceResult<EngEqRateCountVo> result = new DataSourceResult<>();
result.setData(list);
result.setTotal(list == null ? 0 : list.size());
result.setAggregates(new HashMap<>());
return result;
}
private DataSourceResult<EngEqDataVo> queryDetailList(DataSourceRequest dataSourceRequest,
DataSourceLoadOptionsBase loadOptions) {
StringBuilder sql = new StringBuilder();
@ -697,6 +769,171 @@ public class EngEqDataServiceImpl implements EngEqDataService {
"FROM SD_HBRV_DIC t WHERE NVL(t.IS_DELETED, 0) = 0 AND t.ORDER_INDEX IS NOT NULL";
}
private String buildQecRateMetricSourceSql() {
// 方案一当前没有新框架业务结果表时直接使用日统计表 SD_QECDAY_S 参与达标率计算
// 方案二后续如果补齐新框架业务结果表可仅替换此处为SELECT * FROM 新业务结果表 WHERE TYPE='DAY' ...
return "SELECT met.STCD, met.QEC, met.QEC_LIMIT, met.MWR_LIMIT, met.AVQ_LIMIT, " +
"met.SFDB, met.MWR_SFDB, met.AVQ_SFDB " +
"FROM SD_QECDAY_S met " +
"WHERE NVL(met.IS_DELETED, 0) = 0 " +
" AND met.DT BETWEEN TO_DATE(#{map.startTime}, 'YYYY-MM-DD HH24:MI:SS') " +
" AND TO_DATE(#{map.endTime}, 'YYYY-MM-DD HH24:MI:SS')";
}
private String buildQecRateSql() {
return "CASE " +
"WHEN COUNT(*) = 0 THEN NULL " +
"WHEN SUM(CASE WHEN met.QEC_LIMIT IS NULL AND met.MWR_LIMIT IS NULL AND met.AVQ_LIMIT IS NULL THEN 0 ELSE 1 END) = 0 THEN NULL " +
"WHEN SUM(CASE WHEN (met.QEC_LIMIT IS NOT NULL OR met.MWR_LIMIT IS NOT NULL OR met.AVQ_LIMIT IS NOT NULL) AND met.QEC IS NULL THEN 0 ELSE 1 END) = 0 THEN NULL " +
"WHEN SUM(CASE " +
"WHEN met.SFDB = 1 OR met.SFDB = 0 THEN 1 " +
"WHEN met.SFDB = 2 AND (met.MWR_SFDB = 1 OR met.MWR_SFDB = 0) THEN 1 " +
"WHEN met.MWR_SFDB = 2 AND (met.AVQ_SFDB = 1 OR met.AVQ_SFDB = 0) THEN 1 " +
"ELSE 0 END) = 0 THEN NULL " +
"ELSE ((SUM(CASE " +
"WHEN met.SFDB = 1 THEN 1 " +
"WHEN met.SFDB = 0 THEN 0 " +
"WHEN met.SFDB = 2 AND met.MWR_SFDB = 1 THEN 1 " +
"WHEN met.SFDB = 2 AND met.MWR_SFDB = 0 THEN 0 " +
"WHEN met.MWR_SFDB = 2 AND met.AVQ_SFDB = 1 THEN 1 " +
"WHEN met.MWR_SFDB = 2 AND met.AVQ_SFDB = 0 THEN 0 " +
"ELSE 0 END) / NULLIF(SUM(CASE " +
"WHEN met.SFDB = 1 OR met.SFDB = 0 THEN 1 " +
"WHEN met.SFDB = 2 AND (met.MWR_SFDB = 1 OR met.MWR_SFDB = 0) THEN 1 " +
"WHEN met.MWR_SFDB = 2 AND (met.AVQ_SFDB = 1 OR met.AVQ_SFDB = 0) THEN 1 " +
"ELSE 0 END), 0)) * 100) END";
}
private String[] resolveQecRateTimeRange(String tm) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
if (StrUtil.isNotBlank(tm)) {
String[] arr = StrUtil.splitToArray(tm, ',');
if (arr != null && arr.length >= 2) {
return new String[]{arr[0].trim(), arr[1].trim()};
}
}
LocalDateTime end = LocalDateTime.now().withHour(23).withMinute(59).withSecond(59).withNano(0);
LocalDateTime start = end.minusMonths(3).withHour(0).withMinute(0).withSecond(0).withNano(0);
return new String[]{start.format(formatter), end.format(formatter)};
}
private String mapQecRateSelect(String field) {
if (StrUtil.isBlank(field)) {
return null;
}
return switch (field) {
case "baseId" -> "eng.BASE_ID AS baseId";
case "baseName" -> "hb.BASENAME AS baseName";
case "hbrvcd" -> "eng.HBRVCD AS hbrvcd";
case "hbrvcdName" -> "hbrv.HBRVNM AS hbrvcdName";
case "addvcd" -> "eng.ADDVCD AS addvcd";
case "addvcdName" -> "addv.ADDVNM AS addvcdName";
case "stcd" -> "eng.STCD AS stcd";
case "stnm" -> "eng.ENNM AS stnm";
case "ennm" -> "eng.ENNM AS ennm";
case "qecPerformance" -> buildQecPerformanceCaseSql() + " AS qecPerformance";
default -> null;
};
}
private String mapQecRateGroup(String field) {
if (StrUtil.isBlank(field)) {
return null;
}
return switch (field) {
case "baseId" -> "eng.BASE_ID";
case "baseName" -> "hb.BASENAME";
case "hbrvcd" -> "eng.HBRVCD";
case "hbrvcdName" -> "hbrv.HBRVNM";
case "addvcd" -> "eng.ADDVCD";
case "addvcdName" -> "addv.ADDVNM";
case "stcd" -> "eng.STCD";
case "stnm", "ennm" -> "eng.ENNM";
case "qecPerformance" -> buildQecPerformanceCaseSql();
default -> null;
};
}
private String buildQecPerformanceCaseSql() {
return "CASE " +
"WHEN eng.RGCP = '1' THEN '1' " +
"WHEN eng.RGCP = '2' THEN '2' " +
"WHEN eng.RGCP = '5' THEN '5' " +
"WHEN eng.RGCP = '7' THEN '7' " +
"ELSE '9' END";
}
private String buildQecRateOrderBy(List<DataSourceRequest.GroupDescriptor> groups) {
if (CollUtil.isEmpty(groups)) {
return "";
}
List<String> orders = new ArrayList<>();
for (DataSourceRequest.GroupDescriptor group : groups) {
if (group == null || StrUtil.isBlank(group.getField())) {
continue;
}
String column = mapQecRateGroup(group.getField());
if (StrUtil.isBlank(column)) {
continue;
}
String dir = "desc".equalsIgnoreCase(group.getDir()) || "des".equalsIgnoreCase(group.getDir()) ? "DESC" : "ASC";
orders.add(column + " " + dir);
}
return orders.isEmpty() ? "" : " ORDER BY " + String.join(", ", orders);
}
private void fillQecRateCountNames(List<EngEqRateCountVo> list) {
if (CollUtil.isEmpty(list)) {
return;
}
for (EngEqRateCountVo item : list) {
item.setQecPerformanceName(getQecPerformanceName(item.getQecPerformance()));
if (item.getQecRate() != null) {
item.setQecRate(item.getQecRate().setScale(2, RoundingMode.HALF_UP));
}
}
}
private List<EngEqRateCountVo> completeQecPerformanceGroups(List<EngEqRateCountVo> list,
List<DataSourceRequest.GroupDescriptor> groups) {
if (CollUtil.isEmpty(groups) || groups.get(0) == null || !"qecPerformance".equals(groups.get(0).getField())) {
return list;
}
Map<String, EngEqRateCountVo> exists = new LinkedHashMap<>();
if (CollUtil.isNotEmpty(list)) {
for (EngEqRateCountVo item : list) {
if (item != null && StrUtil.isNotBlank(item.getQecPerformance())) {
exists.put(item.getQecPerformance(), item);
}
}
}
List<EngEqRateCountVo> result = new ArrayList<>();
for (String code : Arrays.asList("1", "2", "5", "7", "9")) {
EngEqRateCountVo item = exists.get(code);
if (item == null) {
item = new EngEqRateCountVo();
item.setQecPerformance(code);
item.setQecPerformanceName(getQecPerformanceName(code));
}
result.add(item);
}
return result;
}
private String getQecPerformanceName(String code) {
if (StrUtil.isBlank(code)) {
return null;
}
return switch (code) {
case "1" -> "多年调节";
case "2" -> "年调节";
case "5" -> "季调节";
case "7" -> "周调节";
case "9" -> "其他";
default -> null;
};
}
private String buildWbsbDetailSelectSql(List<String> selectFields) {
Map<String, String> columns = wbsbFieldColumns();
List<String> selected = new ArrayList<>();