diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBH.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBH.java index aaf8da45..cec92071 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBH.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBH.java @@ -60,6 +60,10 @@ public class SdEngInfoBH implements Serializable { @FieldChinese("是否启用") private Integer usfl; + /** 是否启用名称 */ + @TableField(exist = false) + private String usflName; + /** 水能利用数据是否接入 */ @FieldChinese("水能利用数据是否接入") private Integer dtin; @@ -219,15 +223,31 @@ public class SdEngInfoBH implements Serializable { @FieldChinese("建设状态") private String bldstt; + /** 站类 */ + @FieldChinese("站类") + private String sttp; + + /** 站类名称 */ + @TableField(exist = false) + private String sttpName; + /** 建设状态分类 */ @TableField("BLDSTT_CODE") @FieldChinese("建设状态分类") private Integer bldsttCode; + /** 建设状态分类名称 */ + @TableField(exist = false) + private String bldsttCodeName; + /** 工程类别 */ @FieldChinese("工程类别") private Integer engtp; + /** 工程类别名称 */ + @TableField(exist = false) + private String engtpName; + /** 工程规模 */ @FieldChinese("工程规模") private Integer prsc; @@ -236,14 +256,26 @@ public class SdEngInfoBH implements Serializable { @FieldChinese("工程规模(水库库容)") private Integer scrsc; + /** 工程规模(水库库容)名称 */ + @TableField(exist = false) + private String scrscName; + /** 工程等别 */ @FieldChinese("工程等别") private String prgr; + /** 工程等别名称 */ + @TableField(exist = false) + private String prgrName; + /** 电站-主要功能 */ @FieldChinese("电站-主要功能") private String fn; + /** 电站-主要功能名称 */ + @TableField(exist = false) + private String fnName; + /** 地震基本烈度 */ @FieldChinese("地震基本烈度") private String bsssin; @@ -256,31 +288,58 @@ public class SdEngInfoBH implements Serializable { @FieldChinese("是否调节水库") private Integer adjustEng; + /** 是否调节水库名称 */ + @TableField(exist = false) + private String adjustEngName; + /** 有无拦河坝 */ @TableField("ISHVBRRG") @FieldChinese("有无拦河坝") private String ishvrgrg; + /** 有无拦河坝名称 */ + @TableField(exist = false) + private String ishvrgrgName; + /** 水库调节性能 */ @FieldChinese("水库调节性能") private String rgcp; + @TableField(exist = false) + private String rgcpName; + /** 坝体材质 */ @FieldChinese("坝体材质") private Integer dmat; + /** 坝体材质名称 */ + @TableField(exist = false) + private String dmatName; + /** 坝体类型 */ @FieldChinese("坝体类型") private String dmtp; + /** 坝体类型名称 */ + @TableField(exist = false) + private String dmtpName; + /** 开发方式 */ @FieldChinese("开发方式") private String dvtp; + /** 开发方式名称 */ + @TableField(exist = false) + private String dvtpName; + /** 建设类型 */ @FieldChinese("建设类型") private String cntp; + /** 建设类型名称 */ + @TableField(exist = false) + private String cntpName; + /** 管理单位 */ @FieldChinese("管理单位") private String mnun; @@ -293,6 +352,10 @@ public class SdEngInfoBH implements Serializable { @FieldChinese("归属部门") private String blsys; + /** 归属部门名称 */ + @TableField(exist = false) + private String blsysName; + /** 绕经度方向旋转矩阵值 */ @FieldChinese("绕经度方向旋转矩阵值") private Double roll; @@ -313,6 +376,10 @@ public class SdEngInfoBH implements Serializable { @FieldChinese("是否受下游顶托") private String impdstrz; + /** 是否受下游顶托名称 */ + @TableField(exist = false) + private String impdstrzName; + /** 工程概况 */ @FieldChinese("工程概况") private String prov; @@ -831,6 +898,10 @@ public class SdEngInfoBH implements Serializable { @FieldChinese("航道级别") private String chngrd; + /** 渠道级别名称 */ + @TableField(exist = false) + private String chngrdName; + /** 渠化航道里程 */ @FieldChinese("渠化航道里程") private Double chnlnth; @@ -968,6 +1039,10 @@ public class SdEngInfoBH implements Serializable { @FieldChinese("是否主要流域电站") private Integer chiefbasineng; + /** 是否主要流域电站名称 */ + @TableField(exist = false) + private String chiefbasinengName; + /** 蓄水开始时间 */ @FieldChinese("蓄水开始时间") private String swsdt; @@ -1037,18 +1112,34 @@ public class SdEngInfoBH implements Serializable { @FieldChinese("环境监测数据接入情况") private Integer dtinEnv; + /** 环境监测数据接入情况描述 */ + @TableField(exist = false) + private String dtinEnvName; + /** 最新运行状态:1=运行中 2=未运行 */ @FieldChinese("最新运行状态") private Integer runState; + /** 最新运行状态描述 */ + @TableField(exist = false) + private String runStateName; + /** 告警状态 */ @FieldChinese("告警状态") private String warnState; + /** 告警状态描述 */ + @TableField(exist = false) + private String warnStateName; + /** 开展环保自动检测工作状态:0=暂无数据 1=正常 */ @FieldChinese("开展环保自动检测工作状态") private Integer coenvwState; + /** 开展环保自动检测工作状态描述 */ + @TableField(exist = false) + private String coenvwStateName; + /** 在线地址 */ @FieldChinese("在线地址") private String url; diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 1db399ec..1b275306 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java @@ -16,6 +16,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.annotation.FieldChinese; import com.yfd.platform.common.DataSourceLoadOptionsBase; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; @@ -45,9 +46,7 @@ import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdEngInfoBHService; import com.yfd.platform.qgc_eng.eq.entity.vo.LastTmEngEqDataVo; import com.yfd.platform.system.service.IAdminAuthService; -import com.yfd.platform.utils.QgcQueryWrapperUtil; -import com.yfd.platform.utils.RedisCacheUtil; -import com.yfd.platform.utils.SecurityUtils; +import com.yfd.platform.utils.*; import jakarta.annotation.Resource; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; @@ -66,13 +65,61 @@ import java.util.stream.Collectors; */ @Service public class SdEngInfoBHServiceImpl extends ServiceImpl implements ISdEngInfoBHService { - + private static final String TABLE_NAME = "SD_FISHDICTORY_B"; private static final Map ENG_CODE_NAME_FIELD_MAP = new LinkedHashMap<>(); @Resource private RedisCacheUtil redisCacheUtil; @Resource private IDataScopeFilterService dataScopeFilterService; + @Resource + private DictCodeToNameConverter dictCodeToNameConverter; + + /** + * 代码转名称元数据配置列表(静态初始化) + *

+ * 每个模块的 ServiceImpl 中可按需定义自己的 codeToNameMetadataBoList, + * 在查询方法返回前调用 dictCodeToNameConverter.convertCodeToName(voList, codeToNameMetadataBoList) + * 即可自动将 code 字段转为对应的 name 字段。 + *

+ * + *
+     * 使用示例:
+     * // 在查询方法末尾调用:
+     * dictCodeToNameConverter.convertCodeToName(voList, CODE_TO_NAME_META_LIST);
+     * 
+ */ + private static final List CODE_TO_NAME_META_LIST = new ArrayList<>(); + + static { + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("dtin").modifyProperty("dtinName").dictType("STATIC").dictSource("DTIN").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("mway").modifyProperty("mwayName").dictType("STATIC").dictSource("MWAY").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("bldsttCode").modifyProperty("bldsttCodeName").dictType("STATIC").dictSource("BLDSTT_CODE").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("dtinEnv").modifyProperty("dtinEnvName").dictType("STATIC").dictSource("DTIN_ENV").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("sttp").modifyProperty("sttpName").dictType("DYNAMIC").dictSource("SD_STTP_B").codeColumn("STTP_CODE").nameColumn("STTP_NAME").filter("NVL(IS_DELETED, 0) = 0 ").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("usfl").modifyProperty("usflName").dictType("STATIC").dictSource("USFL").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("runState").modifyProperty("runStateName").dictType("STATIC").dictSource("RUN_STATE").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("warnState").modifyProperty("warnStateName").dictType("STATIC").dictSource("WARN_STATE").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("coenvwState").modifyProperty("coenvwStateName").dictType("STATIC").dictSource("COENVW_STATE").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("scrsc").modifyProperty("scrscStateName").dictType("STATIC").dictSource("SCRSC").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("adjustEng").modifyProperty("adjustEngName").dictType("STATIC").dictSource("TY_SF").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("chiefbasineng").modifyProperty("chiefbasinengName").dictType("STATIC").dictSource("TY_SF").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("impdstrz").modifyProperty("impdstrzName").dictType("STATIC").dictSource("TY_SF").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("ishvbrrg").modifyProperty("ishvbrrgName").dictType("STATIC").dictSource("YW_TY").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("dvtp").modifyProperty("dvtpName").dictType("STATIC").dictSource("DVTP").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("blsys").modifyProperty("blsysName").dictType("STATIC").dictSource("BLSYS").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("chngrd").modifyProperty("chngrdName").dictType("STATIC").dictSource("CHNGRD").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("cntp").modifyProperty("cntpName").dictType("STATIC").dictSource("CNTP").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("dmat").modifyProperty("dmatName").dictType("STATIC").dictSource("DMAT").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("dmtp").modifyProperty("dmtpName").dictType("STATIC").dictSource("DMTP").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("engtp").modifyProperty("engtpName").dictType("STATIC").dictSource("ENGTP").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("fn").modifyProperty("fnName").dictType("STATIC").dictSource("ENG_FN").build()); + CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("prgr").modifyProperty("prgrName").dictType("STATIC").dictSource("PRGR").build()); + + + } + + static { ENG_CODE_NAME_FIELD_MAP.put("baseId", "baseName"); ENG_CODE_NAME_FIELD_MAP.put("hbrvcd", "hbrvcdName"); @@ -252,10 +299,11 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl filters = dataSourceRequest.getFilter().getFilters(); + for (DataSourceRequest.FilterDescriptor filter : filters) { + if ("stcd".equals(filter.getField())) { + stcd = (String) filter.getValue(); + } + } + if (StrUtil.isEmpty(stcd)) { + return ResponseResult.error("增殖站stcd不能为空!"); + } + List breedStageList = fbStationService.getBreedStageList(stcd); + DataSourceResult dataSourceResult = new DataSourceResult<>(); + dataSourceResult.setData(breedStageList); + dataSourceResult.setTotal(breedStageList.size()); + return ResponseResult.successData(dataSourceResult); + } + @PostMapping("/msfbrdm/fbFlData/GetKendoListCust") @Operation(summary = "增殖站增殖情况(app)") public ResponseResult getFbFlData(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/BreedStageVO.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/BreedStageVO.java new file mode 100644 index 00000000..96e50ad1 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/BreedStageVO.java @@ -0,0 +1,30 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 鱼类增殖阶段 + */ +@Data +@Accessors(chain = true) +public class BreedStageVO { + + /** 增殖站编码 */ + private String stcd; + + /** 阶段名称 */ + private String key; + + /** 阶段状态:1=有数据 2=无数据 */ + private String value; + + /** 是否为最新数据 */ + private Boolean newest; + + /** 最新表 */ + private String newSurface; + + /** 主菜单 */ + private String firstGrade; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbEngFishVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbEngFishVo.java new file mode 100644 index 00000000..581f109b --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbEngFishVo.java @@ -0,0 +1,22 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 电站放流统计-有数据的年份 + */ +@Data +public class FbEngFishVo { + /** 电站编码 */ + private String stcd; + /** 电站名称 */ + private String ennm; + /** 计划放流尾数 */ + private BigDecimal fcntjh; + /** 实际放流尾数 */ + private BigDecimal fcntjc; + /** 计划放流日期(年份) */ + private String plansd; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java index 66578ed0..5e94e2de 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/FbStationService.java @@ -2,8 +2,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.BreedStageVO; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRQgcVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishTableVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbEngFishVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFlDataVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFishCountFinishVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFishRunQgcVo; @@ -67,4 +69,19 @@ public interface FbStationService { DataSourceResult getFbPointKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getFbBuiltPointKendoListCust(DataSourceRequest dataSourceRequest); + + /** + * 电站放流统计-返回有数据的年份 + */ + DataSourceResult getAggregateData(DataSourceRequest dataSourceRequest); + + /** + * 电站放流统计列表 + */ + DataSourceResult getEngKendoListCust(DataSourceRequest dataSourceRequest); + + /** + * 获取增殖站各阶段数据状态(选配/繁殖/培育/防治) + */ + List getBreedStageList(String stcd); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java index ee2f4b67..635edcef 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/service/impl/FbStationServiceImpl.java @@ -11,6 +11,7 @@ import com.yfd.platform.common.Group; import com.yfd.platform.common.GroupHelper; import com.yfd.platform.common.GroupingInfo; import com.yfd.platform.common.MicroservicDynamicSQLMapper; +import com.yfd.platform.qgc_env.fb.entity.vo.BreedStageVO; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRQgcVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishHeadColumnVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishSummaryVo; @@ -20,6 +21,7 @@ import com.yfd.platform.qgc_env.fb.entity.vo.FbFishRunQgcVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFishTypeStcdVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFishTypeFinishVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFtpStatisticsVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbEngFishVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbFlDataVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbMsfbrdmQgcVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbRelatedYrVo; @@ -4809,6 +4811,285 @@ public class FbStationServiceImpl implements FbStationService { return voList; } + @Override + public DataSourceResult getAggregateData(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + List stcdList = resolveStcdList(dataSourceRequest, loadOptions); + + Map paramMap = new HashMap<>(); + String sql = buildAggregateDataSql(stcdList, paramMap); + + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + null, sql, paramMap, FbEngFishVo.class + ); + + if (CollUtil.isNotEmpty(list)) { + FbEngFishVo first = list.get(0); + if (StrUtil.isNotBlank(first.getPlansd()) && first.getPlansd().length() >= 4) { + first.setPlansd(first.getPlansd().substring(0, 4)); + } + } + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list.stream() + .filter(it -> StrUtil.isNotBlank(it.getStcd())) + .sorted(Comparator.comparing(FbEngFishVo::getStcd)) + .collect(Collectors.toList())); + result.setTotal(list.size()); + return result; + } + + /** + * 构建电站放流统计-年份聚合数据 SQL + *

+ * 查询指定电站有放流数据(计划或实际)的最新一条年份记录。 + * 上半部分以计划表为主 LEFT JOIN 实际表,下半部分以实际表为主 LEFT JOIN 计划表, + * UNION 去重合并后按日期降序取第一条。 + *

+ */ + private String buildAggregateDataSql(List stcdList, Map paramMap) { + String planTable = "SD_ENGFRPLAN_B"; + String planDetTable = "SD_ENGFRPLANDET_B"; + String actualTable = "SD_ENGFR_R"; + String actualDetTable = "SD_RPIMNFISH_R"; + String engInfoTable = "SD_ENGINFO_B_H"; + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT STCD, ennm, fcntjh, fcntjc, PLANSD FROM ( "); + sql.append("SELECT s.STCD, e.ENNM AS ennm, s.fcntjh, s.fcntjc, s.PLANSD "); + sql.append("FROM ( "); + + // 上半部分:计划表为主 LEFT JOIN 实际表 + sql.append("SELECT jh.STCD, jh.PLANSD, jh.fcntjh, jc.fcntjc FROM ( "); + sql.append("SELECT a.STCD, a.PLANSD, SUM(NVL(b.FCNT, 0)) AS fcntjh "); + sql.append("FROM ").append(planTable).append(" a "); + sql.append("LEFT JOIN ").append(planDetTable).append(" b ON a.ID = b.RPJH_ID AND NVL(b.IS_DELETED, 0) = 0 "); + sql.append("WHERE NVL(a.IS_DELETED, 0) = 0 "); + appendInCondition(sql, paramMap, "a.STCD", stcdList, "aggPlanStcd"); + sql.append("GROUP BY a.STCD, a.PLANSD "); + sql.append(") jh "); + sql.append("LEFT JOIN ( "); + sql.append("SELECT a.STCD, SUM(NVL(b.FCNT, 0)) AS fcntjc "); + sql.append("FROM ").append(actualTable).append(" a "); + sql.append("LEFT JOIN ").append(actualDetTable).append(" b ON a.ID = b.RPIMN_ID AND NVL(b.IS_DELETED, 0) = 0 "); + sql.append("WHERE NVL(a.IS_DELETED, 0) = 0 "); + appendInCondition(sql, paramMap, "a.STCD", stcdList, "aggActStcd1"); + sql.append("GROUP BY a.STCD "); + sql.append(") jc ON jh.STCD = jc.STCD "); + sql.append("WHERE (jh.fcntjh IS NOT NULL OR jc.fcntjc IS NOT NULL) "); + + sql.append("UNION "); + + // 下半部分:实际表为主 LEFT JOIN 计划表 + sql.append("SELECT jc.STCD, jc.PLANSD, jh.fcntjh, jc.fcntjc FROM ( "); + sql.append("SELECT a.STCD, a.TM AS PLANSD, SUM(NVL(b.FCNT, 0)) AS fcntjc "); + sql.append("FROM ").append(actualTable).append(" a "); + sql.append("LEFT JOIN ").append(actualDetTable).append(" b ON a.ID = b.RPIMN_ID AND NVL(b.IS_DELETED, 0) = 0 "); + sql.append("WHERE NVL(a.IS_DELETED, 0) = 0 "); + appendInCondition(sql, paramMap, "a.STCD", stcdList, "aggActStcd2"); + sql.append("GROUP BY a.STCD, a.TM "); + sql.append(") jc "); + sql.append("LEFT JOIN ( "); + sql.append("SELECT a.STCD, SUM(NVL(b.FCNT, 0)) AS fcntjh "); + sql.append("FROM ").append(planTable).append(" a "); + sql.append("LEFT JOIN ").append(planDetTable).append(" b ON a.ID = b.RPJH_ID AND NVL(b.IS_DELETED, 0) = 0 "); + sql.append("WHERE NVL(a.IS_DELETED, 0) = 0 "); + appendInCondition(sql, paramMap, "a.STCD", stcdList, "aggPlanStcd2"); + sql.append("GROUP BY a.STCD "); + sql.append(") jh ON jc.STCD = jh.STCD "); + sql.append("WHERE (jh.fcntjh IS NOT NULL OR jc.fcntjc IS NOT NULL) "); + + sql.append(") s "); + sql.append("LEFT JOIN ").append(engInfoTable).append(" e ON s.STCD = e.STCD AND NVL(e.IS_DELETED, 0) = 0 "); + sql.append("WHERE (s.fcntjh IS NOT NULL OR s.fcntjc IS NOT NULL) "); + sql.append("ORDER BY s.PLANSD DESC "); + sql.append(") WHERE ROWNUM = 1"); + + return sql.toString(); + } + + @Override + public DataSourceResult getEngKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + List stcdList = resolveStcdList(dataSourceRequest, loadOptions); + + Map paramMap = new HashMap<>(); + String sql = buildEngKendoListCustSql(startTime, endTime, stcdList, paramMap); + + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + null, sql, paramMap, FbEngFishVo.class + ); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list.stream() + .filter(it -> StrUtil.isNotBlank(it.getStcd())) + .collect(Collectors.toList())); + result.setTotal(list.size()); + return result; + } + + /** + * 构建电站放流统计列表 SQL + *

+ * UNION 合并计划放流和实际放流数据,确保同时有两类数据的电站不遗漏。 + * 上半部分以计划表为主 LEFT JOIN 实际表,下半部分以实际表为主 LEFT JOIN 计划表。 + *

+ */ + private String buildEngKendoListCustSql(String startTime, String endTime, + List stcdList, Map paramMap) { + String planTable = "SD_ENGFRPLAN_B"; + String planDetTable = "SD_ENGFRPLANDET_B"; + String actualTable = "SD_ENGFR_R"; + String actualDetTable = "SD_RPIMNFISH_R"; + String viewTable = "V_MS_STBPRP_T"; + + StringBuilder sql = new StringBuilder(); + + sql.append("SELECT s.STCD, t.STNM AS ennm, s.fcntjh, s.fcntjc "); + sql.append("FROM ( "); + + // 上半部分:计划表为主 LEFT JOIN 实际表 + sql.append("SELECT jh.STCD, jh.fcntjh, jc.fcntjc FROM ( "); + sql.append("SELECT a.STCD, SUM(NVL(b.FCNT, 0)) AS fcntjh "); + sql.append("FROM ").append(planTable).append(" a "); + sql.append("LEFT JOIN ").append(planDetTable).append(" b ON a.ID = b.RPJH_ID "); + sql.append("WHERE NVL(a.IS_DELETED, 0) = 0 "); + if (StrUtil.isNotBlank(startTime)) { + paramMap.put("planStartTime1", DateUtil.parse(startTime)); + sql.append("AND a.PLANSD >= #{map.planStartTime1} "); + } + if (StrUtil.isNotBlank(endTime)) { + paramMap.put("planEndTime1", DateUtil.parse(endTime)); + sql.append("AND a.PLANED <= #{map.planEndTime1} "); + } + sql.append("GROUP BY a.STCD "); + sql.append(") jh "); + sql.append("LEFT JOIN ( "); + sql.append("SELECT a.STCD, SUM(NVL(b.FCNT, 0)) AS fcntjc "); + sql.append("FROM ").append(actualTable).append(" a "); + sql.append("LEFT JOIN ").append(actualDetTable).append(" b ON a.ID = b.RPIMN_ID AND NVL(b.IS_DELETED, 0) = 0 "); + sql.append("WHERE NVL(a.IS_DELETED, 0) = 0 "); +// sql.append("AND (a.TASK_STATUS = 'Approved' OR a.TASK_STATUS IS NULL) "); + if (StrUtil.isNotBlank(startTime)) { + paramMap.put("actStartTime1", DateUtil.parse(startTime)); + sql.append("AND a.TM >= #{map.actStartTime1} "); + } + if (StrUtil.isNotBlank(endTime)) { + paramMap.put("actEndTime1", DateUtil.parse(endTime)); + sql.append("AND a.TM <= #{map.actEndTime1} "); + } + sql.append("GROUP BY a.STCD "); + sql.append(") jc ON jh.STCD = jc.STCD "); + + sql.append("UNION "); + + // 下半部分:实际表为主 LEFT JOIN 计划表 + sql.append("SELECT jc.STCD, jh.fcntjh, jc.fcntjc FROM ( "); + sql.append("SELECT a.STCD, SUM(NVL(b.FCNT, 0)) AS fcntjc "); + sql.append("FROM ").append(actualTable).append(" a "); + sql.append("LEFT JOIN ").append(actualDetTable).append(" b ON a.ID = b.RPIMN_ID AND NVL(b.IS_DELETED, 0) = 0 "); + sql.append("WHERE NVL(a.IS_DELETED, 0) = 0 "); +// sql.append("AND (a.TASK_STATUS = 'Approved' OR a.TASK_STATUS IS NULL) "); + if (StrUtil.isNotBlank(startTime)) { + paramMap.put("actStartTime2", DateUtil.parse(startTime)); + sql.append("AND a.TM >= #{map.actStartTime2} "); + } + if (StrUtil.isNotBlank(endTime)) { + paramMap.put("actEndTime2", DateUtil.parse(endTime)); + sql.append("AND a.TM <= #{map.actEndTime2} "); + } + sql.append("GROUP BY a.STCD "); + sql.append(") jc "); + sql.append("LEFT JOIN ( "); + sql.append("SELECT a.STCD, SUM(NVL(b.FCNT, 0)) AS fcntjh "); + sql.append("FROM ").append(planTable).append(" a "); + sql.append("LEFT JOIN ").append(planDetTable).append(" b ON a.ID = b.RPJH_ID "); + sql.append("WHERE NVL(a.IS_DELETED, 0) = 0 "); + if (StrUtil.isNotBlank(startTime)) { + paramMap.put("planStartTime2", DateUtil.parse(startTime)); + sql.append("AND a.PLANSD >= #{map.planStartTime2} "); + } + if (StrUtil.isNotBlank(endTime)) { + paramMap.put("planEndTime2", DateUtil.parse(endTime)); + sql.append("AND a.PLANED <= #{map.planEndTime2} "); + } + sql.append("GROUP BY a.STCD "); + sql.append(") jh ON jc.STCD = jh.STCD "); + + sql.append(") s "); + sql.append("LEFT JOIN ").append(viewTable).append(" t ON s.STCD = t.STCD "); + sql.append("WHERE 1 = 1 "); + appendInCondition(sql, paramMap, "s.STCD", stcdList, "engStcd"); + sql.append("ORDER BY t.SITESTEPSORT "); + + return sql.toString(); + } + + @Override + public List getBreedStageList(String stcd) { + List stageVOList = new ArrayList<>(); + + // 阶段1:选配 --- SD_FBBSMF_R(亲鱼档案管理记录表)+ SD_FBBSDEATH_R(亲鱼死亡记录表) + boolean bsmfExists = existsDataInTable("SD_FBBSMF_R", stcd); + boolean bsdeathExists = existsDataInTable("SD_FBBSDEATH_R", stcd); + BreedStageVO stage1 = new BreedStageVO(); + stage1.setKey("选配"); + stage1.setValue((bsmfExists || bsdeathExists) ? "1" : "2"); + stageVOList.add(stage1); + + // 阶段2:繁殖 --- SD_FBFISHARTINL_R(鱼类人工催产记录) + boolean fishArtinlExists = existsDataInTable("SD_FBFISHARTINL_R", stcd); + BreedStageVO stage2 = new BreedStageVO(); + stage2.setKey("繁殖"); + stage2.setValue(fishArtinlExists ? "1" : "2"); + stageVOList.add(stage2); + + // 阶段3:培育 --- SD_FBFISHBREED_R(鱼苗和鱼种培育记录)+ SD_FBSCWEM_R(苗种培育水环境监测记录表) + boolean fishbreedExists = existsDataInTable("SD_FBFISHBREED_R", stcd); + boolean scwemExists = existsDataInTable("SD_FBSCWEM_R", stcd); + BreedStageVO stage3 = new BreedStageVO(); + stage3.setKey("培育"); + stage3.setValue((fishbreedExists || scwemExists) ? "1" : "2"); + stageVOList.add(stage3); + + // 阶段4:防治 --- SD_FBFISHDPAC_R(鱼病防治记录表) + boolean fishDpacExists = existsDataInTable("SD_FBFISHDPAC_R", stcd); + BreedStageVO stage4 = new BreedStageVO(); + stage4.setKey("防治"); + stage4.setValue(fishDpacExists ? "1" : "2"); + stageVOList.add(stage4); + + return stageVOList; + } + + /** + * 检查指定表在指定 stcd 下是否存在未删除的数据 + */ + private boolean existsDataInTable(String tableName, String stcd) { + Map paramMap = new HashMap<>(); + paramMap.put("stcd", stcd); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT 1 AS existFlag FROM ").append(tableName); + sql.append(" WHERE STCD = #{map.stcd} AND NVL(IS_DELETED, 0) = 0 AND ROWNUM = 1"); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + null, sql.toString(), paramMap, DataExistsVo.class); + return CollUtil.isNotEmpty(list); + } + + private static class DataExistsVo { + private Integer existFlag; + + public Integer getExistFlag() { + return existFlag; + } + + public void setExistFlag(Integer existFlag) { + this.existFlag = existFlag; + } + } + private static class FbPointCountVo { private String stcd; private Long fcnt;