From b6f6c6e8d30a3fa92c6a23bfd8a253546bbae626 Mon Sep 17 00:00:00 2001 From: tangwei Date: Wed, 27 May 2026 11:02:23 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9F=A5=E8=AF=A2=E6=B0=B4=E6=B8=A9?= =?UTF-8?q?=E6=8C=87=E5=AE=9A=E6=97=B6=E9=97=B4=E6=9C=89=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E7=9A=84=E7=AB=99=E7=82=B9-=E6=A0=91=E5=BD=A2=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wt/controller/SdWTMonitorController.java | 6 + .../env/wt/entity/vo/RstcdTreeInfoVo.java | 24 ++ .../env/wt/entity/vo/WtTreeStcdVo.java | 58 ++++ .../env/wt/service/SdWtMonitorService.java | 3 + .../service/impl/SdWtMonitorServiceImpl.java | 288 +++++++++++++++++- 5 files changed, 377 insertions(+), 2 deletions(-) create mode 100644 backend/src/main/java/com/yfd/platform/env/wt/entity/vo/RstcdTreeInfoVo.java create mode 100644 backend/src/main/java/com/yfd/platform/env/wt/entity/vo/WtTreeStcdVo.java diff --git a/backend/src/main/java/com/yfd/platform/env/wt/controller/SdWTMonitorController.java b/backend/src/main/java/com/yfd/platform/env/wt/controller/SdWTMonitorController.java index b2c0c22..6398dbc 100644 --- a/backend/src/main/java/com/yfd/platform/env/wt/controller/SdWTMonitorController.java +++ b/backend/src/main/java/com/yfd/platform/env/wt/controller/SdWTMonitorController.java @@ -185,6 +185,12 @@ public class SdWTMonitorController { return ResponseResult.successData(sdWtvtRService.getWtrvDefaultYear(dataSourceRequest)); } + @PostMapping("/sdrvwts/default/treeStcd") + @Operation(summary = "查询水温指定时间有数据的站点-树形结构") + public ResponseResult getWtvtDefaultTreeStcd(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(sdWtMonitorService.getWtvtDefaultTreeStcd(dataSourceRequest)); + } + @PostMapping("/wtrv/fish/GetKendoListCust") @Operation(summary = "鱼类繁殖适宜性分析") public ResponseResult getWtFishAnalysis(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/env/wt/entity/vo/RstcdTreeInfoVo.java b/backend/src/main/java/com/yfd/platform/env/wt/entity/vo/RstcdTreeInfoVo.java new file mode 100644 index 0000000..d62cab4 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/wt/entity/vo/RstcdTreeInfoVo.java @@ -0,0 +1,24 @@ +package com.yfd.platform.env.wt.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +@Data +@Schema(description = "电站-站点树形结构") +public class RstcdTreeInfoVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "电站编码") + private String rstcd; + + @Schema(description = "电站名称") + private String ennm; + + @Schema(description = "测站数据") + private List stcdVo = new ArrayList<>(); +} diff --git a/backend/src/main/java/com/yfd/platform/env/wt/entity/vo/WtTreeStcdVo.java b/backend/src/main/java/com/yfd/platform/env/wt/entity/vo/WtTreeStcdVo.java new file mode 100644 index 0000000..541514b --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/wt/entity/vo/WtTreeStcdVo.java @@ -0,0 +1,58 @@ +package com.yfd.platform.env.wt.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +@Schema(description = "垂向水温树形站点") +public class WtTreeStcdVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "站码") + private String stcd; + + @Schema(description = "站名") + private String stnm; + + @Schema(description = "电站排序") + private Integer rstcdStepSort; + + @Schema(description = "所属电站编码") + private String rstcd; + + @Schema(description = "所属电站名称") + private String ennm; + + @Schema(description = "经度") + private String lgtd; + + @Schema(description = "纬度") + private String lttd; + + @Schema(description = "监测方式") + private Integer mway; + + @Schema(description = "垂向水温类型:1=浮动式 2=固定式") + private Integer wtDeviceType; + + @Schema(description = "所属流域") + private String hbrvcd; + + @Schema(description = "站点排序") + private Integer orderIndex; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "基地排序") + private Integer baseStepSort; + + @Schema(description = "站点排序") + private Integer siteStepSort; + + @Schema(description = "范围内是否有日数据") + private Integer sort; +} diff --git a/backend/src/main/java/com/yfd/platform/env/wt/service/SdWtMonitorService.java b/backend/src/main/java/com/yfd/platform/env/wt/service/SdWtMonitorService.java index 8f3dbc5..f4b2059 100644 --- a/backend/src/main/java/com/yfd/platform/env/wt/service/SdWtMonitorService.java +++ b/backend/src/main/java/com/yfd/platform/env/wt/service/SdWtMonitorService.java @@ -2,6 +2,7 @@ package com.yfd.platform.env.wt.service; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.env.wt.entity.vo.RstcdTreeInfoVo; import com.yfd.platform.env.wt.entity.vo.WbsbVo; import com.yfd.platform.env.wt.entity.vo.WtrvVo; @@ -20,4 +21,6 @@ public interface SdWtMonitorService { WtrvVo getFlagByStcd(String stcd); DataSourceResult getWbsbList(DataSourceRequest dataSourceRequest); + + List getWtvtDefaultTreeStcd(DataSourceRequest dataSourceRequest); } diff --git a/backend/src/main/java/com/yfd/platform/env/wt/service/impl/SdWtMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/env/wt/service/impl/SdWtMonitorServiceImpl.java index 6223eef..2588eeb 100644 --- a/backend/src/main/java/com/yfd/platform/env/wt/service/impl/SdWtMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/env/wt/service/impl/SdWtMonitorServiceImpl.java @@ -4,11 +4,13 @@ import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.yfd.platform.common.*; import com.yfd.platform.env.wt.entity.vo.FishSpawnVo; -import com.yfd.platform.env.wt.entity.vo.SdWtMonitorCountVO; +import com.yfd.platform.env.wt.entity.vo.RstcdTreeInfoVo; import com.yfd.platform.env.wt.entity.vo.SdWtBaseInfoVO; +import com.yfd.platform.env.wt.entity.vo.SdWtMonitorCountVO; import com.yfd.platform.env.wt.entity.vo.WbsbVo; -import com.yfd.platform.env.wt.entity.vo.WtrvVo; import com.yfd.platform.env.wt.entity.vo.WtFishVo; +import com.yfd.platform.env.wt.entity.vo.WtTreeStcdVo; +import com.yfd.platform.env.wt.entity.vo.WtrvVo; import com.yfd.platform.env.wt.mapper.SdWtMonitorMapper; import com.yfd.platform.env.wt.service.SdWtMonitorService; import com.yfd.platform.utils.QgcQueryWrapperUtil; @@ -593,6 +595,282 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService { return result; } + @Override + public List getWtvtDefaultTreeStcd(DataSourceRequest dataSourceRequest) { + List stationList = queryWtvtDefaultStations(dataSourceRequest); + return buildWtvtRstcdTree(stationList); + } + + private List queryWtvtDefaultStations(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String tm = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "tm"); + String mway = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "mway"); + String baseId = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId"); + String rstcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); + String year = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "year"); + + Map paramMap = new HashMap<>(); + String sql; + if (StrUtil.isNotBlank(year)) { + paramMap.put("year", year); + if (StrUtil.isNotBlank(mway)) { + paramMap.put("mway", mway); + } + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("baseId", baseId); + } + if (StrUtil.isNotBlank(rstcd)) { + paramMap.put("rstcd", rstcd); + } + sql = buildWtvtDefaultYearSql(paramMap); + } else { + List tmRange = parseTmRange(tm); + if (tmRange.size() == 2) { + paramMap.put("startTime", tmRange.get(0)); + paramMap.put("endTime", tmRange.get(1)); + } + if (StrUtil.isNotBlank(mway)) { + paramMap.put("mway", mway); + } + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("baseId", baseId); + } + sql = buildWtvtDefaultRangeSql(paramMap); + } + return microservicDynamicSQLMapper.getAllListWithResultType(sql, paramMap, WtTreeStcdVo.class); + } + + private String buildWtvtDefaultYearSql(Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT DISTINCT ") + .append("wt.STCD AS stcd, ") + .append("wt.STNM AS stnm, ") + .append("NVL(rstSort.SORT, eng.ORDER_INDEX) AS rstcdStepSort, ") + .append("wt.RSTCD AS rstcd, ") + .append("eng.ENNM AS ennm, ") + .append("TO_CHAR(wt.LGTD) AS lgtd, ") + .append("TO_CHAR(wt.LTTD) AS lttd, ") + .append("wt.MWAY AS mway, ") + .append("wt.WT_DEVICE_TYPE AS wtDeviceType, ") + .append("eng.HBRVCD AS hbrvcd, ") + .append("wt.ORDER_INDEX AS orderIndex, ") + .append("eng.BASE_ID AS baseId, ") + .append("hb.ORDER_INDEX AS baseStepSort, ") + .append("NVL(siteSort.SORT, wt.ORDER_INDEX) AS siteStepSort, ") + .append("1 AS sort ") + .append("FROM SD_WT_B_H wt ") + .append("INNER JOIN SD_WTVTDRTP_S drtp ON drtp.STCD = wt.STCD ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.RSTCD ") + .append("LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN (") + .append(" SELECT det.STCD, det.SORT, along.RVCD ") + .append(" FROM MS_ALONGDET_B det ") + .append(" INNER JOIN MS_ALONG_B along ON along.ID = det.ALONG_ID ") + .append(" WHERE NVL(det.IS_DELETED, 0) = 0 ") + .append(" AND NVL(along.IS_DELETED, 0) = 0 ") + .append(" AND along.CODE = 'common'") + .append(") rstSort ON rstSort.STCD = wt.RSTCD AND rstSort.RVCD = eng.HBRVCD ") + .append("LEFT JOIN (") + .append(" SELECT det.STCD, det.SORT, along.RVCD ") + .append(" FROM MS_ALONGDET_B det ") + .append(" INNER JOIN MS_ALONG_B along ON along.ID = det.ALONG_ID ") + .append(" WHERE NVL(det.IS_DELETED, 0) = 0 ") + .append(" AND NVL(along.IS_DELETED, 0) = 0 ") + .append(" AND along.CODE = 'common'") + .append(") siteSort ON siteSort.STCD = wt.STCD AND siteSort.RVCD = eng.HBRVCD ") + .append("WHERE NVL(wt.IS_DELETED, 0) = 0 ") + .append(" AND wt.STTP = 'WTVT' ") + .append(" AND NVL(wt.USFL, 0) = 1 ") + .append(" AND NVL(drtp.IS_DELETED, 0) = 0 ") + .append(" AND drtp.DRTP = 'YEAR' ") + .append(" AND drtp.YEAR = #{map.year} ") + .append(" AND drtp.WTHG IS NOT NULL ") + .append(" AND drtp.VWT IS NOT NULL "); + if (paramMap.containsKey("mway")) { + sql.append(" AND wt.MWAY = #{map.mway} "); + } + if (paramMap.containsKey("baseId")) { + sql.append(" AND eng.BASE_ID = #{map.baseId} "); + } + if (paramMap.containsKey("rstcd")) { + sql.append(" AND wt.RSTCD = #{map.rstcd} "); + } + sql.append("ORDER BY NVL(hb.ORDER_INDEX, 999999) ASC, ") + .append("NVL(NVL(rstSort.SORT, eng.ORDER_INDEX), 999999) ASC, ") + .append("NVL(NVL(siteSort.SORT, wt.ORDER_INDEX), 999999) ASC"); + return sql.toString(); + } + + private String buildWtvtDefaultRangeSql(Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT * FROM (") + .append("SELECT ") + .append("wt.STCD AS stcd, ") + .append("wt.STNM AS stnm, ") + .append("NVL(rstSort.SORT, eng.ORDER_INDEX) AS rstcdStepSort, ") + .append("wt.RSTCD AS rstcd, ") + .append("eng.ENNM AS ennm, ") + .append("TO_CHAR(wt.LGTD) AS lgtd, ") + .append("TO_CHAR(wt.LTTD) AS lttd, ") + .append("wt.MWAY AS mway, ") + .append("wt.WT_DEVICE_TYPE AS wtDeviceType, ") + .append("eng.HBRVCD AS hbrvcd, ") + .append("wt.ORDER_INDEX AS orderIndex, ") + .append("eng.BASE_ID AS baseId, ") + .append("hb.ORDER_INDEX AS baseStepSort, ") + .append("NVL(siteSort.SORT, wt.ORDER_INDEX) AS siteStepSort, ") + .append("CASE WHEN "); + if (paramMap.containsKey("startTime") && paramMap.containsKey("endTime")) { + sql.append("EXISTS (") + .append("SELECT 1 FROM SD_WTVTDAY_S dayData ") + .append("WHERE dayData.STCD = wt.STCD ") + .append(" AND NVL(dayData.IS_DELETED, 0) = 0 ") + .append(" AND dayData.DT >= TO_DATE(#{map.startTime}, 'YYYY-MM-DD HH24:MI:SS') ") + .append(" AND dayData.DT <= TO_DATE(#{map.endTime}, 'YYYY-MM-DD HH24:MI:SS') ") + .append(" AND dayData.WTHG IS NOT NULL ") + .append(" AND dayData.VWT IS NOT NULL") + .append(") "); + } else { + sql.append("1 = 0 "); + } + sql.append("THEN 1 ELSE -1 END AS sort ") + .append("FROM SD_WT_B_H wt ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.RSTCD ") + .append("LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN (") + .append(" SELECT det.STCD, det.SORT, along.RVCD ") + .append(" FROM MS_ALONGDET_B det ") + .append(" INNER JOIN MS_ALONG_B along ON along.ID = det.ALONG_ID ") + .append(" WHERE NVL(det.IS_DELETED, 0) = 0 ") + .append(" AND NVL(along.IS_DELETED, 0) = 0 ") + .append(" AND along.CODE = 'common'") + .append(") rstSort ON rstSort.STCD = wt.RSTCD AND rstSort.RVCD = eng.HBRVCD ") + .append("LEFT JOIN (") + .append(" SELECT det.STCD, det.SORT, along.RVCD ") + .append(" FROM MS_ALONGDET_B det ") + .append(" INNER JOIN MS_ALONG_B along ON along.ID = det.ALONG_ID ") + .append(" WHERE NVL(det.IS_DELETED, 0) = 0 ") + .append(" AND NVL(along.IS_DELETED, 0) = 0 ") + .append(" AND along.CODE = 'common'") + .append(") siteSort ON siteSort.STCD = wt.STCD AND siteSort.RVCD = eng.HBRVCD ") + .append("WHERE NVL(wt.IS_DELETED, 0) = 0 ") + .append(" AND wt.STTP = 'WTVT' ") + .append(" AND NVL(wt.USFL, 0) = 1 ") + .append(" AND EXISTS (") + .append(" SELECT 1 FROM SD_WTVTDRTP_S yearData ") + .append(" WHERE yearData.STCD = wt.STCD ") + .append(" AND NVL(yearData.IS_DELETED, 0) = 0 ") + .append(" AND yearData.DRTP = 'YEAR' ") + .append(" AND yearData.WTHG IS NOT NULL ") + .append(" AND yearData.VWT IS NOT NULL") + .append(" ) "); + if (paramMap.containsKey("mway")) { + sql.append(" AND wt.MWAY = #{map.mway} "); + } + if (paramMap.containsKey("baseId")) { + sql.append(" AND eng.BASE_ID = #{map.baseId} "); + } + sql.append(") ") + .append("ORDER BY NVL(baseStepSort, 999999) ASC, ") + .append("NVL(rstcdStepSort, 999999) ASC, ") + .append("NVL(siteStepSort, 999999) ASC, ") + .append("sort DESC"); + return sql.toString(); + } + + private List parseTmRange(String tm) { + if (StrUtil.isBlank(tm)) { + return Collections.emptyList(); + } + String[] split = tm.split(","); + List result = new ArrayList<>(); + for (String item : split) { + if (StrUtil.isNotBlank(item)) { + result.add(item.trim()); + } + } + return result; + } + + private List buildWtvtRstcdTree(List stationList) { + if (stationList == null || stationList.isEmpty()) { + return new ArrayList<>(); + } + LinkedHashMap treeMap = new LinkedHashMap<>(); + List otherStations = new ArrayList<>(); + for (WtTreeStcdVo station : stationList) { + List rstcdCodes = splitRstcdCodes(station.getRstcd()); + if (rstcdCodes.isEmpty()) { + otherStations.add(station); + continue; + } + for (String rstcdCode : rstcdCodes) { + RstcdTreeInfoVo treeInfo = treeMap.computeIfAbsent(rstcdCode, key -> { + RstcdTreeInfoVo vo = new RstcdTreeInfoVo(); + vo.setRstcd(key); + vo.setEnnm(station.getEnnm()); + return vo; + }); + if (StrUtil.isBlank(treeInfo.getEnnm()) && StrUtil.isNotBlank(station.getEnnm())) { + treeInfo.setEnnm(station.getEnnm()); + } + boolean exists = treeInfo.getStcdVo().stream() + .anyMatch(item -> StrUtil.equals(item.getStcd(), station.getStcd())); + if (!exists) { + treeInfo.getStcdVo().add(station); + } + } + } + fillMissingTreeEnnm(treeMap); + List result = new ArrayList<>(treeMap.values()); + if (!otherStations.isEmpty()) { + RstcdTreeInfoVo other = new RstcdTreeInfoVo(); + other.setRstcd("other"); + other.setEnnm("其它"); + other.setStcdVo(otherStations); + result.add(other); + } + return result; + } + + private List splitRstcdCodes(String rstcd) { + if (StrUtil.isBlank(rstcd)) { + return Collections.emptyList(); + } + List result = new ArrayList<>(); + for (String item : rstcd.split(",")) { + if (StrUtil.isNotBlank(item)) { + result.add(item.trim()); + } + } + return result; + } + + private void fillMissingTreeEnnm(LinkedHashMap treeMap) { + List missingCodes = treeMap.values().stream() + .filter(item -> StrUtil.isNotBlank(item.getRstcd()) && StrUtil.isBlank(item.getEnnm())) + .map(RstcdTreeInfoVo::getRstcd) + .distinct() + .collect(Collectors.toList()); + if (missingCodes.isEmpty()) { + return; + } + String inSql = missingCodes.stream() + .map(code -> "'" + code.replace("'", "''") + "'") + .collect(Collectors.joining(",")); + String sql = "SELECT STCD AS stcd, ENNM AS ennm FROM SD_ENGINFO_B_H " + + "WHERE NVL(IS_DELETED, 0) = 0 AND STCD IN (" + inSql + ")"; + List rowList = microservicDynamicSQLMapper.getAllListWithResultType(sql, new HashMap<>(), WtTreeNodeEnnmRow.class); + Map ennmMap = rowList.stream() + .filter(item -> StrUtil.isNotBlank(item.getStcd())) + .collect(Collectors.toMap(WtTreeNodeEnnmRow::getStcd, WtTreeNodeEnnmRow::getEnnm, (left, right) -> left)); + for (Map.Entry entry : treeMap.entrySet()) { + if (StrUtil.isBlank(entry.getValue().getEnnm())) { + entry.getValue().setEnnm(ennmMap.get(entry.getKey())); + } + } + } + private Page buildPage(DataSourceLoadOptionsBase loadOptions) { PageInfo pageInfo = QgcQueryWrapperUtil.getPageInfo(loadOptions); if (Boolean.TRUE.equals(pageInfo.getHasPageInfo())) { @@ -846,4 +1124,10 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService { private String vwt; } + @Data + private static class WtTreeNodeEnnmRow { + private String stcd; + private String ennm; + } + }