feat: 全流域增殖站概况二级页面

This commit is contained in:
tangwei 2026-06-15 17:13:58 +08:00
parent 5632e00f0b
commit 229a987dfa
6 changed files with 393 additions and 5 deletions

View File

@ -122,11 +122,19 @@ public class SwaggerConfig {
@Bean @Bean
public GroupedOpenApi groupEnvFprApi() { public GroupedOpenApi groupEnvFprApi() {
return GroupedOpenApi.builder() return GroupedOpenApi.builder()
.group("3.5 全过程-生态环保数据服务-鱼类调查") .group("3.6 全过程-生态环保数据服务-鱼类调查")
.packagesToScan("com.yfd.platform.qgc_env.fpr.controller") .packagesToScan("com.yfd.platform.qgc_env.fpr.controller")
.build(); .build();
} }
@Bean
public GroupedOpenApi groupEnvFbApi() {
return GroupedOpenApi.builder()
.group("3.7 全过程-生态环保数据服务-鱼类调查")
.packagesToScan("com.yfd.platform.qgc_env.fb.controller")
.build();
}

View File

@ -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/station")
@Tag(name = "鱼类增殖站概况")
@Validated
public class FbStationController {
@Resource
private FbStationService fbStationService;
@PostMapping("/qgcoverview/getOverviewSecond")
@Operation(summary = "全流域增殖站概况二级页面")
public ResponseResult getQgcOverviewSecond(@RequestBody DataSourceRequest dataSourceRequest) {
return ResponseResult.successData(fbStationService.getQgcOverviewSecond(dataSourceRequest));
}
}

View File

@ -0,0 +1,53 @@
package com.yfd.platform.qgc_env.fb.entity.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Data
@Schema(description = "全流域增殖站概况二级页面")
public class FbStationOverviewSecondVo {
@Schema(description = "增殖站编码")
private String stcd;
@Schema(description = "增殖站名称")
private String stnm;
@Schema(description = "服务电站")
private String ennm;
@Schema(description = "增殖站总数")
private Integer count;
@Schema(description = "鱼种类数")
private Integer ftpCount;
@Schema(description = "总投资")
private BigDecimal totalInv;
@Schema(description = "计划放流鱼种类")
private String planFtp;
@Schema(description = "计划放流尾数")
private BigDecimal fcntjh;
@Schema(description = "实际鱼种类数")
private Integer realftpCount;
@Schema(description = "实际鱼种类")
private String realftp;
@Schema(description = "实际放流尾数")
private BigDecimal realfcnt;
@Schema(description = "实际放流尾数字符串")
private String realfcntStr;
@Schema(description = "年份")
private String year;
@Schema(description = "累计放鱼数量")
private Long totalFtpCount;
}

View File

@ -0,0 +1,10 @@
package com.yfd.platform.qgc_env.fb.service;
import com.yfd.platform.common.DataSourceRequest;
import com.yfd.platform.common.DataSourceResult;
import com.yfd.platform.qgc_env.fb.entity.vo.FbStationOverviewSecondVo;
public interface FbStationService {
DataSourceResult<FbStationOverviewSecondVo> getQgcOverviewSecond(DataSourceRequest dataSourceRequest);
}

View File

@ -0,0 +1,284 @@
package com.yfd.platform.qgc_env.fb.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
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.fb.entity.vo.FbStationOverviewSecondVo;
import com.yfd.platform.qgc_env.fb.service.FbStationService;
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.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Service
public class FbStationServiceImpl implements FbStationService {
@Resource
private MicroservicDynamicSQLMapper microservicDynamicSQLMapper;
@Override
public DataSourceResult<FbStationOverviewSecondVo> getQgcOverviewSecond(DataSourceRequest dataSourceRequest) {
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
String year = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "year");
String baseId = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId");
String hbrvcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "hbrvcd");
String stnm = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stnm");
List<String> stcdList = resolveStcdList(dataSourceRequest, loadOptions);
Map<String, Object> paramMap = new HashMap<>();
String sql = buildQgcOverviewSecondSql(year, baseId, hbrvcd, stnm, stcdList, paramMap);
List<FbStationOverviewSecondVo> list = microservicDynamicSQLMapper.pageAllListWithResultType(
null, sql, paramMap, FbStationOverviewSecondVo.class
);
DataSourceResult<FbStationOverviewSecondVo> result = new DataSourceResult<>();
result.setData(list);
result.setTotal(list.size());
result.setAggregates(new HashMap<>());
return result;
}
private String buildQgcOverviewSecondSql(String year,
String baseId,
String hbrvcd,
String stnm,
List<String> stcdList,
Map<String, Object> paramMap) {
StringBuilder sql = new StringBuilder();
sql.append("SELECT fb.STCD AS stcd, ")
.append("fb.STNM AS stnm, ")
.append("eng.ENNM AS ennm, ")
.append("fb.INV AS totalInv, ")
.append("t.YEAR AS year, ")
.append("MAX(t.planFtp) AS planFtp, ")
.append("SUM(t.fcntjh) AS fcntjh, ")
.append("MAX(t.realftp) AS realftp, ")
.append("MAX(t.realfcnt) AS realfcntStr ")
.append("FROM SD_FBRD_B_H fb ")
.append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fb.RSTCD ")
.append(" AND NVL(eng.IS_DELETED, 0) = 0 ")
.append("LEFT JOIN (")
.append(buildPlanUnionActualSql(year, stcdList, paramMap))
.append(") t ON fb.STCD = t.rstcd ")
.append("WHERE 1 = 1 ");
if (StrUtil.isNotBlank(stnm)) {
paramMap.put("stnm", "%" + stnm.trim() + "%");
sql.append("AND fb.STNM LIKE #{map.stnm} ");
}
if (StrUtil.isNotBlank(baseId)) {
paramMap.put("baseId", baseId.trim());
sql.append("AND fb.BASE_ID = #{map.baseId} ");
}
if (StrUtil.isNotBlank(hbrvcd)) {
paramMap.put("hbrvcd", hbrvcd.trim());
sql.append("AND fb.HBRVCD = #{map.hbrvcd} ");
}
appendLikeAnyCondition(sql, paramMap, "NVL(fb.RENGCD, fb.RSTCD)", stcdList, "stationFilter");
sql.append("GROUP BY fb.STCD, fb.STNM, eng.ENNM, t.YEAR, fb.INV ")
.append("ORDER BY fb.STCD ASC");
return sql.toString();
}
private String buildPlanUnionActualSql(String year, List<String> stcdList, Map<String, Object> paramMap) {
return buildPlanSql(year, stcdList, paramMap) + " UNION ALL " + buildActualSql(year, stcdList, paramMap);
}
private String buildPlanSql(String year, List<String> stcdList, Map<String, Object> paramMap) {
String fishNameExpr = buildFishNameExpr("det.FTP");
StringBuilder sql = new StringBuilder();
sql.append("SELECT plan.RSTCD AS rstcd, ")
.append("fishAgg.NAME AS planFtp, ")
.append("SUM(fishAgg.FCNT) AS fcntjh, ")
.append("CAST(NULL AS VARCHAR2(4000)) AS realftp, ")
.append("CAST(NULL AS VARCHAR2(4000)) AS realfcnt, ")
.append("TO_CHAR(plan.PLANSD, 'YYYY') AS year ")
.append("FROM SD_ENGFRPLAN_B plan ")
.append("LEFT JOIN ( ")
.append(" SELECT det.RPJH_ID, ")
.append(" SUM(det.FCNT) AS FCNT, ")
.append(" LISTAGG(TO_CHAR(").append(fishNameExpr).append("), ', ') ")
.append(" WITHIN GROUP (ORDER BY ").append(fishNameExpr).append(") AS NAME ")
.append(" FROM SD_ENGFRPLANDET_B det ")
.append(" INNER JOIN SD_ENGFRPLAN_B planInner ON det.RPJH_ID = planInner.ID ")
.append(" INNER JOIN SD_FBRD_B_H fbPlan ON fbPlan.STCD = planInner.RSTCD ")
.append(buildFishJoinSql("det.FTP", "fbPlan.HBRVCD"))
.append(" WHERE NVL(det.IS_DELETED, 0) = 0 ")
.append(" AND det.FTP IS NOT NULL ")
.append(" GROUP BY det.RPJH_ID ")
.append(") fishAgg ON plan.ID = fishAgg.RPJH_ID ")
.append("WHERE NVL(plan.IS_DELETED, 0) = 0 ");
if (StrUtil.isNotBlank(year)) {
paramMap.put("planYear", year.trim());
sql.append("AND TO_CHAR(plan.PLANSD, 'YYYY') = #{map.planYear} ");
}
appendInCondition(sql, paramMap, "plan.STCD", stcdList, "planStcd");
sql.append("GROUP BY plan.RSTCD, fishAgg.NAME, TO_CHAR(plan.PLANSD, 'YYYY') ");
return sql.toString();
}
private String buildActualSql(String year, List<String> stcdList, Map<String, Object> paramMap) {
String fishNameExpr = buildFishNameExpr("det.FTP");
StringBuilder sql = new StringBuilder();
sql.append("SELECT actualFish.RSTCD AS rstcd, ")
.append("CAST(NULL AS VARCHAR2(4000)) AS planFtp, ")
.append("CAST(NULL AS NUMBER(18, 2)) AS fcntjh, ")
.append("LISTAGG(TO_CHAR(actualFish.NAME), ', ') WITHIN GROUP (ORDER BY actualFish.NAME) AS realftp, ")
.append("LISTAGG(TO_CHAR(actualFish.FCNT), ', ') WITHIN GROUP (ORDER BY actualFish.NAME) AS realfcnt, ")
.append("actualFish.YR AS year ")
.append("FROM ( ")
.append(" SELECT run.RSTCD AS RSTCD, ")
.append(" TO_CHAR(run.TM, 'YYYY') AS YR, ")
.append(" ").append(fishNameExpr).append(" AS NAME, ")
.append(" SUM(det.FCNT) AS FCNT ")
.append(" FROM SD_ENGFR_R run ")
.append(" LEFT JOIN SD_RPIMNFISH_R det ON run.ID = det.RPIMN_ID ")
.append(" AND NVL(det.IS_DELETED, 0) = 0 ")
.append(" AND det.FTP IS NOT NULL ")
.append(" INNER JOIN SD_FBRD_B_H fbRun ON fbRun.STCD = run.RSTCD ")
.append(buildFishJoinSql("det.FTP", "fbRun.HBRVCD"))
.append(" WHERE NVL(run.IS_DELETED, 0) = 0 ");
if (StrUtil.isNotBlank(year)) {
paramMap.put("actualYear", year.trim());
sql.append("AND TO_CHAR(run.TM, 'YYYY') = #{map.actualYear} ");
}
appendInCondition(sql, paramMap, "run.STCD", stcdList, "actualStcd");
sql.append(" GROUP BY run.RSTCD, TO_CHAR(run.TM, 'YYYY'), ").append(fishNameExpr).append(" ")
.append(") actualFish ")
.append("GROUP BY actualFish.RSTCD, actualFish.YR ");
return sql.toString();
}
private String buildFishJoinSql(String fishFieldExpr, String hbrvcdFieldExpr) {
return " LEFT JOIN SD_FISHDICTORY_RLTN_B relRv ON relRv.FISH_ID = " + fishFieldExpr +
" AND relRv.RVCD = " + hbrvcdFieldExpr +
" AND NVL(relRv.IS_DELETED, 0) = 0 " +
" LEFT JOIN SD_FISHDICTORY_B fishRv ON fishRv.ID = NVL(relRv.ZY_FISH_ID, relRv.FISH_ID) " +
" AND NVL(fishRv.IS_DELETED, 0) = 0 " +
" AND NVL(fishRv.ENABLE, 1) = 1 " +
" LEFT JOIN SD_FISHDICTORY_RLTN_B relZy ON relZy.FISH_ID = " + fishFieldExpr +
" AND relZy.RVCD = 'ZY' " +
" AND NVL(relZy.IS_DELETED, 0) = 0 " +
" LEFT JOIN SD_FISHDICTORY_B fishZy ON fishZy.ID = NVL(relZy.ZY_FISH_ID, relZy.FISH_ID) " +
" AND NVL(fishZy.IS_DELETED, 0) = 0 " +
" AND NVL(fishZy.ENABLE, 1) = 1 " +
" LEFT JOIN SD_FISHDICTORY_B fishDirect ON fishDirect.ID = " + fishFieldExpr +
" AND NVL(fishDirect.IS_DELETED, 0) = 0 " +
" AND NVL(fishDirect.ENABLE, 1) = 1 ";
}
private String buildFishNameExpr(String fishFieldExpr) {
return "COALESCE(fishRv.NAME, relRv.FISH_NAME, fishZy.NAME, relZy.FISH_NAME, fishDirect.NAME, " + fishFieldExpr + ")";
}
private void appendInCondition(StringBuilder sql,
Map<String, Object> paramMap,
String column,
List<String> values,
String keyPrefix) {
if (CollUtil.isEmpty(values)) {
return;
}
List<String> placeholders = new ArrayList<>();
for (int i = 0; i < values.size(); i++) {
String key = keyPrefix + i;
paramMap.put(key, values.get(i));
placeholders.add("#{map." + key + "}");
}
sql.append("AND ").append(column).append(" IN (").append(String.join(", ", placeholders)).append(") ");
}
private void appendLikeAnyCondition(StringBuilder sql,
Map<String, Object> paramMap,
String column,
List<String> values,
String keyPrefix) {
if (CollUtil.isEmpty(values)) {
return;
}
List<String> conditions = new ArrayList<>();
for (int i = 0; i < values.size(); i++) {
String key = keyPrefix + i;
paramMap.put(key, "%" + values.get(i) + "%");
conditions.add(column + " LIKE #{map." + key + "}");
}
if (!conditions.isEmpty()) {
sql.append("AND (").append(String.join(" OR ", conditions)).append(") ");
}
}
private List<String> resolveStcdList(DataSourceRequest dataSourceRequest, DataSourceLoadOptionsBase loadOptions) {
Set<String> values = new LinkedHashSet<>();
String stcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd");
addFilterValue(values, stcd);
collectFilterValues(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), "stcd", values);
return new ArrayList<>(values);
}
private void collectFilterValues(DataSourceRequest.FilterDescriptor filter, String field, Set<String> values) {
if (filter == null) {
return;
}
if (StrUtil.isNotBlank(filter.getField())) {
if (field.equalsIgnoreCase(filter.getField())) {
addFilterValue(values, filter.getValue());
}
return;
}
if (CollUtil.isEmpty(filter.getFilters())) {
return;
}
for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) {
collectFilterValues(child, field, values);
}
}
private void addFilterValue(Set<String> values, Object value) {
if (value == null) {
return;
}
if (value instanceof List<?> list) {
for (Object item : list) {
addFilterValue(values, item);
}
return;
}
if (value instanceof Object[] array) {
for (Object item : array) {
addFilterValue(values, item);
}
return;
}
String text = String.valueOf(value).trim()
.replace("[", "")
.replace("]", "")
.replace("\"", "");
if (StrUtil.isBlank(text)) {
return;
}
if (text.contains(",")) {
for (String item : text.split(",")) {
String trimmed = StrUtil.trim(item);
if (StrUtil.isNotBlank(trimmed)) {
values.add(trimmed);
}
}
return;
}
values.add(text);
}
}

View File

@ -700,8 +700,10 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService {
.append("eng.DVTP AS dvtp, ") .append("eng.DVTP AS dvtp, ")
.append("CASE WHEN NVL(dw.DTIN, 0) = 1 THEN '已接入' ELSE '未接入' END AS dtinName, ") .append("CASE WHEN NVL(dw.DTIN, 0) = 1 THEN '已接入' ELSE '未接入' END AS dtinName, ")
.append("CASE ") .append("CASE ")
.append("WHEN dw.BLDSTT_CODE IN ('1', '10', '11') THEN '已建' ") .append("WHEN dw.BLDSTT_CODE = 2 THEN '已建' ")
.append("WHEN dw.BLDSTT_CODE IN ('2', '7', '8') THEN '在建' ") .append("WHEN dw.BLDSTT_CODE = 1 THEN '在建' ")
// .append("WHEN dw.BLDSTT_CODE IN ('1', '10', '11') THEN '已建' ")
// .append("WHEN dw.BLDSTT_CODE IN ('2', '7', '8') THEN '在建' ")
.append("ELSE '未建/规划' END AS bldsttCcodeName, ") .append("ELSE '未建/规划' END AS bldsttCcodeName, ")
.append("dw.BLDSTT_CODE AS bldsttCcode, ") .append("dw.BLDSTT_CODE AS bldsttCcode, ")
.append("eng.HBRVCD AS hbrvcd ") .append("eng.HBRVCD AS hbrvcd ")
@ -733,8 +735,10 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService {
.append("wt.STCD AS stcd, ") .append("wt.STCD AS stcd, ")
.append("wt.RSTCD AS rstcd, ") .append("wt.RSTCD AS rstcd, ")
.append("CASE ") .append("CASE ")
.append("WHEN wt.BLDSTT_CODE IN ('1', '10', '11') THEN '已建' ") .append("WHEN wt.BLDSTT_CODE = 2 THEN '已建' ")
.append("WHEN wt.BLDSTT_CODE IN ('2', '7', '8') THEN '在建' ") .append("WHEN wt.BLDSTT_CODE = 1 THEN '在建' ")
// .append("WHEN wt.BLDSTT_CODE IN ('1', '10', '11') THEN '已建' ")
// .append("WHEN wt.BLDSTT_CODE IN ('2', '7', '8') THEN '在建' ")
.append("ELSE '未建/规划' END AS bldsttCcodeName, ") .append("ELSE '未建/规划' END AS bldsttCcodeName, ")
.append("wt.BLDSTT_CODE AS bldsttCcode, ") .append("wt.BLDSTT_CODE AS bldsttCcode, ")
.append("NULL AS stCode, ") .append("NULL AS stCode, ")