diff --git a/backend/src/main/java/com/yfd/platform/common/MicroservicDynamicSQLMapper.java b/backend/src/main/java/com/yfd/platform/common/MicroservicDynamicSQLMapper.java index 56b60176..59e435bd 100644 --- a/backend/src/main/java/com/yfd/platform/common/MicroservicDynamicSQLMapper.java +++ b/backend/src/main/java/com/yfd/platform/common/MicroservicDynamicSQLMapper.java @@ -45,7 +45,8 @@ public interface MicroservicDynamicSQLMapper { default List getAllListWithResultType(String sql, Map map, Class resultType) { - return convertList(getAllList(sql, map), resultType); + List> allList = getAllList(sql, map); + return convertList(allList, resultType); } @Select({"select count(1) count from ${sql} and ${ew.sqlSegment}"}) diff --git a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java index bedbb152..10ae42bf 100644 --- a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java +++ b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java @@ -61,20 +61,25 @@ public class SecurityConfig { .requestMatchers("/tempFile/**").permitAll() .requestMatchers("/system/user/auditUser").permitAll() .requestMatchers("/register/accessToken").permitAll() -// .requestMatchers("/eng/**").permitAll() -// .requestMatchers("/eq/**").permitAll() -// .requestMatchers("/env/**").permitAll() -// .requestMatchers("/wt/**").permitAll() -// .requestMatchers("/fb/**").permitAll() -// .requestMatchers("/zq/**").permitAll() -// .requestMatchers("/wq/**").permitAll() -// .requestMatchers("/vd/**").permitAll() -// .requestMatchers("/fp/**").permitAll() -// .requestMatchers("/fh/**").permitAll() -// .requestMatchers("/data/**").permitAll() - .requestMatchers("/mapLayer/**").permitAll() - .requestMatchers("/mapmodule/**").permitAll() - .requestMatchers("/mapLegend/**").permitAll() + .requestMatchers("/eng/**").permitAll() + .requestMatchers("/eq/**").permitAll() + .requestMatchers("/env/**").permitAll() + .requestMatchers("/warn/**").permitAll() + .requestMatchers("/overview/**").permitAll() + .requestMatchers("/wt/**").permitAll() + .requestMatchers("/fb/**").permitAll() + .requestMatchers("/zq/**").permitAll() + .requestMatchers("/wq/**").permitAll() + .requestMatchers("/wte/**").permitAll() + .requestMatchers("/vd/**").permitAll() + .requestMatchers("/vap/**").permitAll() + .requestMatchers("/fp/**").permitAll() + .requestMatchers("/fpr/**").permitAll() + .requestMatchers("/fh/**").permitAll() + .requestMatchers("/data/**").permitAll() + .requestMatchers("/mapLayer/**").permitAll() + .requestMatchers("/mapmodule/**").permitAll() + .requestMatchers("/mapLegend/**").permitAll() .requestMatchers("/sms/**").permitAll() .requestMatchers(HttpMethod.GET, "/").permitAll() .requestMatchers(HttpMethod.GET, diff --git a/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java b/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java index fd4d2841..85db8810 100644 --- a/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java +++ b/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java @@ -64,14 +64,14 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEnvWTApi() { return GroupedOpenApi.builder() - .group("3.1 全过程-生态环保数据服务-水温监测") + .group("3.1 全过程-生态环保数据服务-水温监测(wt)") .packagesToScan("com.yfd.platform.qgc_env.wt.controller") .build(); } @Bean public GroupedOpenApi groupEnvWQApi() { return GroupedOpenApi.builder() - .group("3.2 全过程-生态环保数据服务-水质监测") + .group("3.2 全过程-生态环保数据服务-水质监测(wq)") .packagesToScan("com.yfd.platform.qgc_env.wq.controller") .build(); } @@ -79,7 +79,7 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEnvFPApi() { return GroupedOpenApi.builder() - .group("3.3 全过程-生态环保数据服务-过鱼设施") + .group("3.3 全过程-生态环保数据服务-过鱼设施(fp)") .packagesToScan("com.yfd.platform.qgc_env.fp.controller") .build(); } @@ -87,7 +87,7 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEnvVDApi() { return GroupedOpenApi.builder() - .group("3.3.1 全过程-生态环保数据服务-过鱼设施-过鱼监测(VD视频模块)") + .group("3.3.1 全过程-生态环保数据服务-过鱼设施-过鱼监测(vd视频模块)") .packagesToScan("com.yfd.platform.qgc_env.vd.controller") .build(); } @@ -97,7 +97,7 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEnvFHApi() { return GroupedOpenApi.builder() - .group("3.4 全过程-生态环保数据服务-栖息地") + .group("3.4 全过程-生态环保数据服务-栖息地(fh)") .packagesToScan("com.yfd.platform.qgc_env.fh.controller") .build(); } @@ -105,7 +105,7 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEnvZQApi() { return GroupedOpenApi.builder() - .group("3.4.1 全过程-生态环保数据服务-栖息地-水文模块") + .group("3.4.1 全过程-生态环保数据服务-栖息地-水文模块(zq)") .packagesToScan("com.yfd.platform.qgc_env.zq.controller") .build(); } @@ -114,7 +114,7 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEnvVapApi() { return GroupedOpenApi.builder() - .group("3.5 全过程-生态环保数据服务-珍稀动植物") + .group("3.5 全过程-生态环保数据服务-珍稀动植物(vap)") .packagesToScan("com.yfd.platform.qgc_env.vap.controller") .build(); } @@ -122,7 +122,7 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEnvFprApi() { return GroupedOpenApi.builder() - .group("3.6 全过程-生态环保数据服务-鱼类调查") + .group("3.6 全过程-生态环保数据服务-鱼类调查(fpr)") .packagesToScan("com.yfd.platform.qgc_env.fpr.controller") .build(); } @@ -130,11 +130,38 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEnvFbApi() { return GroupedOpenApi.builder() - .group("3.7 全过程-生态环保数据服务-增殖放流") + .group("3.7 全过程-生态环保数据服务-增殖放流(fb)") .packagesToScan("com.yfd.platform.qgc_env.fb.controller") .build(); } + @Bean + public GroupedOpenApi groupEnvWarnApi() { + return GroupedOpenApi.builder() + .group("3.8 全过程-生态环保数据服务-智能告警(warn)") + .packagesToScan("com.yfd.platform.qgc_env.warn.controller") + .build(); + } + + @Bean + public GroupedOpenApi groupEnvWteApi() { + return GroupedOpenApi.builder() + .group("3.9 全过程-生态环保数据服务-生态调查(wte)") + .packagesToScan("com.yfd.platform.qgc_env.wte.controller") + .build(); + } + + @Bean + public GroupedOpenApi groupEnvOverviewApi() { + return GroupedOpenApi.builder() + .group("3.10 全过程-生态环保数据服务-首页(overview)") + .packagesToScan("com.yfd.platform.qgc_env.overview.controller") + .build(); + } + + + + @@ -150,7 +177,7 @@ public class SwaggerConfig { @Bean public GroupedOpenApi groupEngEqApi() { return GroupedOpenApi.builder() - .group("4.1. 全过程-常规水电数据服务-生态流量") + .group("4.1. 全过程-常规水电数据服务-生态流量(eq)") .packagesToScan("com.yfd.platform.qgc_eng.eq.controller") .build(); } diff --git a/backend/src/main/java/com/yfd/platform/constant/Constant.java b/backend/src/main/java/com/yfd/platform/constant/Constant.java index c460999e..32eab6e9 100644 --- a/backend/src/main/java/com/yfd/platform/constant/Constant.java +++ b/backend/src/main/java/com/yfd/platform/constant/Constant.java @@ -13,7 +13,7 @@ public class Constant { public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; public static final String CODE_KEY = "code-key-"; - public static final long CODE_EXPIRATION_TIME = 1000 * 60; + public static final long CODE_EXPIRATION_TIME = 1000 * 60 * 2; /** * 用于IP定位转换 */ diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdAddvcdDicController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdAddvcdDicController.java new file mode 100644 index 00000000..ff404809 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdAddvcdDicController.java @@ -0,0 +1,27 @@ +package com.yfd.platform.qgc_base.controller; + +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.qgc_base.domain.SdAddvcdDicDropdownRequest; +import com.yfd.platform.qgc_base.service.ISdAddvcdDicService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +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("/env/addvcd") +@Tag(name = "行政区管理") +public class SdAddvcdDicController { + + @Resource + private ISdAddvcdDicService addvcdDicService; + + @PostMapping("/selectForDropdown") + @Operation(summary = "根据级别和父级行政区编码查询行政区下拉") + public ResponseResult selectForDropdown(@RequestBody SdAddvcdDicDropdownRequest request) { + return ResponseResult.successData(addvcdDicService.selectForDropdown(request.getGrd(), request.getPaddvcd())); + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngInfoBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngInfoBHController.java index 866b074c..798ab6d7 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngInfoBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngInfoBHController.java @@ -1,10 +1,12 @@ package com.yfd.platform.qgc_base.controller; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.fasterxml.jackson.databind.ObjectMapper; import com.yfd.platform.annotation.Log; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.qgc_base.domain.SdEngInfoBH; +import com.yfd.platform.qgc_base.domain.SdEngInfoBHOperateRequest; import com.yfd.platform.qgc_base.domain.SdEngInfoBHRequest; import com.yfd.platform.qgc_base.service.ISdEngInfoBHService; import io.swagger.v3.oas.annotations.Operation; @@ -23,6 +25,9 @@ import jakarta.annotation.Resource; @Tag(name = "电站管理") public class SdEngInfoBHController { + @Resource + private ObjectMapper objectMapper; + @Resource private ISdEngInfoBHService engInfoBHService; @@ -88,27 +93,38 @@ public class SdEngInfoBHController { return ResponseResult.successData(engInfoBHService.getVmsstbprptKendoList(dataSourceRequest)); } + @PostMapping("/stbprpData/GetKendoListCust") + @Operation(summary = "电站通用实时监测数据查询") + public ResponseResult getStbprpDataKendoListCust(@RequestBody DataSourceRequest dataSourceRequest, + @RequestParam("tbCode") String tbCode, + @RequestParam(value = "ignorePageLimit", required = false) Boolean ignorePageLimit) { + return ResponseResult.successData(engInfoBHService.getStbprpDataKendoListCust(dataSourceRequest, tbCode, ignorePageLimit)); + } + @Log(module = "电站管理", value = "新增电站") @PostMapping("/add") @Operation(summary = "新增电站") - public ResponseResult add(@RequestBody SdEngInfoBH engInfo) { - boolean result = engInfoBHService.addEngInfo(engInfo); + public ResponseResult add(@RequestBody SdEngInfoBHOperateRequest request) { + SdEngInfoBH engInfo = request == null || request.getEngInfo() == null ? null : objectMapper.convertValue(request.getEngInfo(), SdEngInfoBH.class); + boolean result = engInfoBHService.addEngInfo(engInfo, request.getSource()); return result ? ResponseResult.success("新增成功") : ResponseResult.error("新增失败"); } @Log(module = "电站管理", value = "修改电站") @PostMapping("/update") @Operation(summary = "修改电站") - public ResponseResult update(@RequestBody SdEngInfoBH engInfo) { - boolean result = engInfoBHService.updateEngInfo(engInfo); + public ResponseResult update(@RequestBody SdEngInfoBHOperateRequest request) throws Exception { + boolean result = engInfoBHService.updateEngInfo(request.getEngInfo(), request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } @Log(module = "电站管理", value = "删除电站") @PostMapping("/delete") @Operation(summary = "删除电站") - public ResponseResult delete(@RequestParam String stcd) { - boolean result = engInfoBHService.deleteEngInfo(stcd); + public ResponseResult delete(@RequestBody SdEngInfoBHOperateRequest request) { + boolean result = engInfoBHService.deleteEngInfo(request == null ? null : request.getIds(), + request == null ? null : request.getSource()); return result ? ResponseResult.success("删除成功") : ResponseResult.error("删除失败"); } + } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngMonitorController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngMonitorController.java index 1524a5a9..b0bf0bcf 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngMonitorController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngMonitorController.java @@ -27,9 +27,21 @@ public class SdEngMonitorController { return ResponseResult.successData(engInfoBHService.getStInfoByStcd(stcd)); } + @GetMapping("/msstbprpt/getStcdInfo") + @Operation(summary = "根据站码查询电站详情兼容结构") + public ResponseResult getStcdInfo(@RequestParam String stcd) { + return ResponseResult.successData(engInfoBHService.getStcdInfo(stcd)); + } + @PostMapping("/eiaapproval/GetKendoList") @Operation(summary = "查询生态环保批复文件列表") public ResponseResult getEiaapprovalKendoList(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(engInfoBHService.getEiaapprovalKendoList(dataSourceRequest)); } + + @PostMapping("/operat/GetKendoListCust") + @Operation(summary = "首页-环保设施运行状况") + public ResponseResult getOperatKendoList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(engInfoBHService.getOperatKendoList(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdRvcdDicController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdRvcdDicController.java index 4ee42f4c..f49830ed 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdRvcdDicController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdRvcdDicController.java @@ -111,6 +111,15 @@ public class SdRvcdDicController { return ResponseResult.successData(rvcdDicService.selectForDropdown(rvnm, rvcd)); } + @GetMapping("/selectRvcdDropdown") + @Operation(summary = "流域下拉框列表查询") + public ResponseResult selectRvcdDropdown( + @RequestParam(required = false) String rvnm, + @RequestParam(required = false) String baseId + ) { + return ResponseResult.successData(rvcdDicService.selectRvcdDropdown(rvnm,baseId)); + } + @GetMapping("/regDropdown") @Operation(summary = "下拉框列表查询(注册)") public ResponseResult regDropdown( diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java new file mode 100644 index 00000000..04d9e34a --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java @@ -0,0 +1,39 @@ +package com.yfd.platform.qgc_base.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@Data +@TableName("MS_OPERATION_LOG") +public class MsOperationLog implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + @TableField("OPERATOR") + private String operator; + + @TableField("OPERATE_TIME") + private Date operateTime; + + @TableField("SOURCE") + private String source; + + @TableField("REMARK") + private String remark; + + @TableField("TABLE_NAME") + private String tableName; + + @TableField("RECORD_ID") + private String recordId; + +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLogDetail.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLogDetail.java new file mode 100644 index 00000000..27e06282 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLogDetail.java @@ -0,0 +1,49 @@ +package com.yfd.platform.qgc_base.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; + +@Data +@TableName("MS_OPERATION_LOG_DETAIL") +public class MsOperationLogDetail implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.ASSIGN_UUID) + private String id; + + @TableField("MAIN_ID") + private String mainId; + + @TableField("FIELD_CODE") + private String fieldCode; + + @TableField("TABLE_NAME") + private String tableName; + + @TableField("FIELD_MEANING") + private String fieldMeaning; + + @TableField("STATION_CODE") + private String stationCode; + + @TableField("OLD_VALUE_CODE") + private String oldValueCode; + + @TableField("OLD_VALUE_NAME") + private String oldValueName; + + @TableField("NEW_VALUE_CODE") + private String newValueCode; + + @TableField("NEW_VALUE_NAME") + private String newValueName; + + @TableField("REMARK") + private String remark; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdAddvcdDic.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdAddvcdDic.java new file mode 100644 index 00000000..69223c3e --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdAddvcdDic.java @@ -0,0 +1,93 @@ +package com.yfd.platform.qgc_base.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +/** + *

+ * 行政区字典表 + *

+ */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("SD_ADDVCD_DIC") +public class SdAddvcdDic implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 行政区编码 + */ + @TableId(type = IdType.INPUT) + private String addvcd; + + /** + * 行政区划名称 + */ + private String addvnm; + + /** + * 所属行政编码,根节点为空 + */ + private String paddvcd; + + /** + * 树级别,从1开始 1=省 2=市 3=县 + */ + private Integer grd; + + /** + * 树全路径 + */ + private String path; + + /** + * 排序 + */ + private Integer orderIndex; + + /** + * 中心经度 + */ + private Double lgtd; + + /** + * 中心纬度 + */ + private Double lttd; + + /** + * 面积 + */ + private Double area; + + /** + * 周长 + */ + private Double perimeter; + + /** + * 所属国家 + */ + private String country; + + /** + * 简介 + */ + private String introduce; + + /** + * 介绍图片 + */ + private String inffile; + + /** + * 简称 + */ + private String shortname; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdAddvcdDicDropdownRequest.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdAddvcdDicDropdownRequest.java new file mode 100644 index 00000000..27409592 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdAddvcdDicDropdownRequest.java @@ -0,0 +1,17 @@ +package com.yfd.platform.qgc_base.domain; + +import lombok.Data; + +@Data +public class SdAddvcdDicDropdownRequest { + + /** + * 树级别,从1开始 1=省 2=市 3=县 + */ + private Integer grd; + + /** + * 所属行政编码,根节点为空 + */ + private String paddvcd; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHOperateRequest.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHOperateRequest.java new file mode 100644 index 00000000..8087d328 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHOperateRequest.java @@ -0,0 +1,16 @@ +package com.yfd.platform.qgc_base.domain; + +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Data +public class SdEngInfoBHOperateRequest { + + private Map engInfo; + + private List ids; + + private String source; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHRequest.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHRequest.java index 402b3bda..4a7f7127 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHRequest.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHRequest.java @@ -13,8 +13,10 @@ public class SdEngInfoBHRequest { private String baseId; private String hbrvcd; private String rvcd; + private String reachcd; private List basIds; private List hbrvcds; private List rvcds; +// private List rvcds; private String ennm; } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssBH.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssBH.java index a20947e9..66d4e2e9 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssBH.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdFpssBH.java @@ -228,7 +228,7 @@ public class SdFpssBH implements Serializable { /** * 鱼道或仿自然通道-流速,单位:m/s */ - private String v; + private String flow; /** * 仿自然通道断面形状 @@ -308,7 +308,7 @@ public class SdFpssBH implements Serializable { /** * 设计过鱼规模,单位:尾 */ - private Long sjgycnt; + private String sjgycnt; /** * 主要过鱼对象{[code:鱼编码1,name:鱼名称1,数量],[code:鱼编码2,name:鱼名称2]...} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngOperatVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngOperatVo.java new file mode 100644 index 00000000..7e2ba7f2 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngOperatVo.java @@ -0,0 +1,32 @@ +package com.yfd.platform.qgc_base.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +@Schema(description = "环保设施运行状况") +public class EngOperatVo implements Serializable { + + private static final long serialVersionUID = 1L; + + private String repCode; + private String sttpCode; + private String pcode; + private String pname; + private String stcd; + private String ennm; + private String stnm; + private String addvcdName; + private String rvcdName; + private String sttpName; + private String baseId; + private Integer dtin; + private Integer runState; + private Integer stdState; + private Integer runSstate; + private Integer bldsttCcode; + private Integer yr; + private Integer count; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStBaseInfoVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStBaseInfoVo.java new file mode 100644 index 00000000..b4a0f370 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStBaseInfoVo.java @@ -0,0 +1,51 @@ +package com.yfd.platform.qgc_base.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "电站单站基础信息") +public class EngStBaseInfoVo { + + @Schema(description = "站点编码") + private String stcd; + + @Schema(description = "站点名称") + private String stnm; + + @Schema(description = "站类编码") + private String sttpCode; + + @Schema(description = "站类名称") + private String sttpName; + + @Schema(description = "站类全路径") + private String sttpFullPath; + + @Schema(description = "站类层级") + private Integer sttpTreeLevel; + + @Schema(description = "关联站点编码") + private String stCode; + + @Schema(description = "关联站点名称") + private String stName; + + @Schema(description = "所属基地编码") + private String baseId; + + @Schema(description = "所属基地名称") + private String baseName; + + @Schema(description = "所属基地流域编码") + private String hbrvcd; + + @Schema(description = "所属基地流域名称") + private String hbrvcdName; + + @Schema(description = "所属流域编码") + private String rvcd; + + @Schema(description = "所属流域名称") + private String rvcdName; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStInfoResultVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStInfoResultVo.java new file mode 100644 index 00000000..27e6ca72 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStInfoResultVo.java @@ -0,0 +1,26 @@ +package com.yfd.platform.qgc_base.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@Data +@Schema(description = "电站详情返回") +public class EngStInfoResultVo { + + @Schema(description = "主信息兼容对象") + private Map msStbprpT = new LinkedHashMap<>(); + + @Schema(description = "测值列表") + private List stcdValVoList = new ArrayList<>(); + + @Schema(description = "关联列表") + private List relList = new ArrayList<>(); + + @Schema(description = "站点基础信息") + private EngStBaseInfoVo stBaseInfo; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStbprpDataVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStbprpDataVo.java new file mode 100644 index 00000000..afd9546c --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngStbprpDataVo.java @@ -0,0 +1,24 @@ +package com.yfd.platform.qgc_base.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +@Schema(description = "电站通用监测数据动态行") +public class EngStbprpDataVo extends LinkedHashMap implements Serializable { + + private static final long serialVersionUID = 1L; + + public EngStbprpDataVo() { + super(); + } + + public EngStbprpDataVo(Map source) { + super(); + if (source != null && !source.isEmpty()) { + putAll(source); + } + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java index ba6b5723..28c657ee 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java @@ -20,6 +20,8 @@ public class EngVmsstbprptVo implements Serializable { private String ennm; private String baseId; private String baseName; + private String reachcdName; + private String reachcd; private String hbrvcd; private String hbrvcdName; private String rvcd; @@ -27,12 +29,17 @@ public class EngVmsstbprptVo implements Serializable { private String addvcdName; private String hynm; private String topHynm; + private String hycd; + private String topHycd; private String stlc; + private Double lgtd; + private Double lttd; private Date jcdt; private Date piodt; private Date aiodt; private String bldstt; private Integer bldsttCcode; + private String bldsttCcodeName; private Double nrupar; private Double dstcrvr; private Double avyrp; @@ -79,6 +86,7 @@ public class EngVmsstbprptVo implements Serializable { private Double ddcp; private Double cpsc; private String rgcp; + private String rgcpName; private Double dsflzmxq; private Double dsflzxyz; private Double ckflzmxq; @@ -102,7 +110,9 @@ public class EngVmsstbprptVo implements Serializable { private Double unyge; private Double gap; private String dvtp; + private String dvtpName; private Integer dtin; + private String dtinName; private Integer baseStepSort; private Integer rvcdStepSort; private Integer rstcdStepSort; diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/entity/vo/BatchDeleteAo.java b/backend/src/main/java/com/yfd/platform/qgc_base/entity/vo/BatchDeleteAo.java index 2fbb7069..f9bab6ca 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/entity/vo/BatchDeleteAo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/entity/vo/BatchDeleteAo.java @@ -12,6 +12,9 @@ public class BatchDeleteAo implements Serializable { private static final long serialVersionUID = 1L; + @Schema(description = "数据来源") + private String source; + @Schema(description = "数据类型") private String dataType; diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogDetailMapper.java b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogDetailMapper.java new file mode 100644 index 00000000..2f28291b --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogDetailMapper.java @@ -0,0 +1,7 @@ +package com.yfd.platform.qgc_base.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.qgc_base.domain.MsOperationLogDetail; + +public interface MsOperationLogDetailMapper extends BaseMapper { +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogMapper.java b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogMapper.java new file mode 100644 index 00000000..1049d713 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/MsOperationLogMapper.java @@ -0,0 +1,7 @@ +package com.yfd.platform.qgc_base.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.qgc_base.domain.MsOperationLog; + +public interface MsOperationLogMapper extends BaseMapper { +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdAddvcdDicMapper.java b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdAddvcdDicMapper.java new file mode 100644 index 00000000..9016fb28 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdAddvcdDicMapper.java @@ -0,0 +1,12 @@ +package com.yfd.platform.qgc_base.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.qgc_base.domain.SdAddvcdDic; + +/** + *

+ * 行政区字典表 Mapper 接口 + *

+ */ +public interface SdAddvcdDicMapper extends BaseMapper { +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdRvcdDicMapper.java b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdRvcdDicMapper.java index 537d2e5f..f54fece4 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdRvcdDicMapper.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdRvcdDicMapper.java @@ -32,4 +32,6 @@ public interface SdRvcdDicMapper extends BaseMapper { * 注册场景下拉框查询,仅返回能被电站表 RVCD 命中的流域 */ List selectRegDropdownWithEng(@Param("rvnm") String rvnm, @Param("rvcd") String rvcd); + + List selectRvcdDropdown(@Param("rvnm") String rvnm,@Param("baseId") String baseId); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/IMsOperationLogService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/IMsOperationLogService.java new file mode 100644 index 00000000..f9edde52 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/IMsOperationLogService.java @@ -0,0 +1,12 @@ +package com.yfd.platform.qgc_base.service; + +import com.yfd.platform.qgc_base.domain.SdEngInfoBH; + +public interface IMsOperationLogService { + + void recordEngAddLog(SdEngInfoBH engInfo, String source); + + void recordEngUpdateLog(SdEngInfoBH before, SdEngInfoBH changeSet, String source); + + void recordEngDeleteLog(SdEngInfoBH engInfo, String source); +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdAddvcdDicService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdAddvcdDicService.java new file mode 100644 index 00000000..f02313c4 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdAddvcdDicService.java @@ -0,0 +1,19 @@ +package com.yfd.platform.qgc_base.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.yfd.platform.qgc_base.domain.SdAddvcdDic; + +import java.util.List; + +/** + *

+ * 行政区字典表 服务类 + *

+ */ +public interface ISdAddvcdDicService extends IService { + + /** + * 根据级别和父级行政区编码查询下拉数据 + */ + List selectForDropdown(Integer grd, String paddvcd); +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java index bedb9d35..7d034512 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdEngInfoBHService.java @@ -8,9 +8,12 @@ import com.yfd.platform.qgc_base.domain.SdEngInfoBH; import com.yfd.platform.qgc_base.domain.SdEngInfoBHRequest; import com.yfd.platform.qgc_base.domain.vo.EngBaseInfoVo; import com.yfd.platform.qgc_base.domain.vo.EngEiaapprovalVo; +import com.yfd.platform.qgc_base.domain.vo.EngOperatVo; +import com.yfd.platform.qgc_base.domain.vo.EngStInfoResultVo; import com.yfd.platform.qgc_base.domain.vo.EngVmsstbprptVo; import java.util.List; +import java.util.Map; import java.util.Set; /** @@ -52,21 +55,35 @@ public interface ISdEngInfoBHService extends IService { */ boolean addEngInfo(SdEngInfoBH engInfo); + boolean addEngInfo(SdEngInfoBH engInfo, String source); + /** * 修改电站 */ boolean updateEngInfo(SdEngInfoBH engInfo); + boolean updateEngInfo(SdEngInfoBH engInfo, String source); + + boolean updateEngInfo(Map engInfoPatch, String source) throws Exception; + /** * 删除电站 */ boolean deleteEngInfo(String stcd); + boolean deleteEngInfo(List ids, String source); + List selectRegDropdown(SdEngInfoBHRequest sdEngInfoBHRequest); EngBaseInfoVo getStInfoByStcd(String stcd); + EngStInfoResultVo getStcdInfo(String stcd); + DataSourceResult getEiaapprovalKendoList(DataSourceRequest dataSourceRequest); DataSourceResult getVmsstbprptKendoList(DataSourceRequest dataSourceRequest); + + DataSourceResult getOperatKendoList(DataSourceRequest dataSourceRequest); + + DataSourceResult getStbprpDataKendoListCust(DataSourceRequest dataSourceRequest, String tbCode, Boolean ignorePageLimit); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdRvcdDicService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdRvcdDicService.java index 8eee4131..027d4b5c 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdRvcdDicService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdRvcdDicService.java @@ -55,5 +55,7 @@ public interface ISdRvcdDicService extends IService { List selectForDropdown(String rvnm, String rvcd); + List selectRvcdDropdown(String rvnm,String baseId); + List regDropdown(String rvnm, String rvcd); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java new file mode 100644 index 00000000..a915ff1d --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java @@ -0,0 +1,544 @@ +package com.yfd.platform.qgc_base.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.yfd.platform.qgc_base.domain.MsOperationLog; +import com.yfd.platform.qgc_base.domain.MsOperationLogDetail; +import com.yfd.platform.qgc_base.domain.SdEngInfoBH; +import com.yfd.platform.qgc_base.mapper.MsOperationLogDetailMapper; +import com.yfd.platform.qgc_base.mapper.MsOperationLogMapper; +import com.yfd.platform.qgc_base.service.IMsOperationLogService; +import com.yfd.platform.utils.SecurityUtils; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +@Service +public class MsOperationLogServiceImpl implements IMsOperationLogService { + + private static final String ENG_TABLE_NAME = "SD_ENGINFO_B_H"; + + private static final Map ENG_FIELD_MEANING_MAP = new LinkedHashMap<>(); + + static { + ENG_FIELD_MEANING_MAP.put("STCD", "电站编码"); + ENG_FIELD_MEANING_MAP.put("TM", "数据时间"); + ENG_FIELD_MEANING_MAP.put("ENNM", "电站名称"); + ENG_FIELD_MEANING_MAP.put("BASE_ID", "所属基地编码"); +// ENG_FIELD_MEANING_MAP.put("BASE_NAME", "所属基地名称"); + ENG_FIELD_MEANING_MAP.put("HBRVCD", "所属基地流域编码"); +// ENG_FIELD_MEANING_MAP.put("HBRVCD_NAME", "所属基地流域名称"); + ENG_FIELD_MEANING_MAP.put("RVCD", "所属流域编码"); +// ENG_FIELD_MEANING_MAP.put("RVCD_NAME", "所属流域名称"); + ENG_FIELD_MEANING_MAP.put("ADDVCD", "所属行政区编码"); +// ENG_FIELD_MEANING_MAP.put("ADDVCD_NAME", "所属行政区名称"); + ENG_FIELD_MEANING_MAP.put("COUNTRY", "所属国家编码"); +// ENG_FIELD_MEANING_MAP.put("COUNTRY_NAME", "所属国家名称"); + ENG_FIELD_MEANING_MAP.put("REACHCD", "所属河段编码"); +// ENG_FIELD_MEANING_MAP.put("REACHCD_NAME", "所属河段名称"); + ENG_FIELD_MEANING_MAP.put("HYCD", "所属公司编码"); +// ENG_FIELD_MEANING_MAP.put("HYNM", "所属公司名称"); + ENG_FIELD_MEANING_MAP.put("TOP_HYCD", "所属集团编码"); +// ENG_FIELD_MEANING_MAP.put("TOP_HYNM", "所属集团名称"); + ENG_FIELD_MEANING_MAP.put("BLPRD", "所属建设阶段"); + ENG_FIELD_MEANING_MAP.put("BLDSTT", "建设状态"); + ENG_FIELD_MEANING_MAP.put("BLDSTT_CODE", "建设状态分类"); + ENG_FIELD_MEANING_MAP.put("ENGTP", "工程类别"); + ENG_FIELD_MEANING_MAP.put("PRSC", "工程规模"); + ENG_FIELD_MEANING_MAP.put("SCRSC", "工程规模(水库库容)"); + ENG_FIELD_MEANING_MAP.put("PRGR", "工程等别"); + ENG_FIELD_MEANING_MAP.put("FN", "主要功能"); + ENG_FIELD_MEANING_MAP.put("BSSSIN", "地震基本烈度"); + ENG_FIELD_MEANING_MAP.put("FRSSIN", "设防地震烈度"); + ENG_FIELD_MEANING_MAP.put("ADJUST_ENG", "是否调节水库"); + ENG_FIELD_MEANING_MAP.put("ISHVBRRG", "有无拦河坝"); + ENG_FIELD_MEANING_MAP.put("DVTP", "开发方式"); + ENG_FIELD_MEANING_MAP.put("CNTP", "建设类型"); + ENG_FIELD_MEANING_MAP.put("DTIN", "数据是否接入"); + ENG_FIELD_MEANING_MAP.put("DTIN_TM", "数据接入时间"); + ENG_FIELD_MEANING_MAP.put("USFL", "是否启用"); + ENG_FIELD_MEANING_MAP.put("MONTH_REPORT", "是否发布月报"); + ENG_FIELD_MEANING_MAP.put("TB_WAY", "填报方式"); + ENG_FIELD_MEANING_MAP.put("TB_FREQUENCY", "填报频率"); + ENG_FIELD_MEANING_MAP.put("RGCP", "调节性能"); + ENG_FIELD_MEANING_MAP.put("LGTD", "经度"); + ENG_FIELD_MEANING_MAP.put("LTTD", "纬度"); + ENG_FIELD_MEANING_MAP.put("ELEV", "高程"); + ENG_FIELD_MEANING_MAP.put("STLC", "站址"); + ENG_FIELD_MEANING_MAP.put("ORDER_INDEX", "排序"); + ENG_FIELD_MEANING_MAP.put("STDSDT", "规划设计日期"); + ENG_FIELD_MEANING_MAP.put("PSTSTDT", "计划开工日期"); + ENG_FIELD_MEANING_MAP.put("PESSTDT", "计划完工日期"); + ENG_FIELD_MEANING_MAP.put("SWDT", "开工日期"); + ENG_FIELD_MEANING_MAP.put("JCDT", "建成日期"); + ENG_FIELD_MEANING_MAP.put("WDDT", "退役/拆除日期"); + ENG_FIELD_MEANING_MAP.put("JLDT", "截流日期"); + ENG_FIELD_MEANING_MAP.put("INTRODUCE", "电站简介"); + ENG_FIELD_MEANING_MAP.put("LOGO", "电站LOGO"); + ENG_FIELD_MEANING_MAP.put("INFFILE", "介绍弹窗图片"); + ENG_FIELD_MEANING_MAP.put("DMAT", "坝体材质"); + ENG_FIELD_MEANING_MAP.put("DMTP", "坝体类型"); + ENG_FIELD_MEANING_MAP.put("MNUN", "管理单位"); + ENG_FIELD_MEANING_MAP.put("CMUN", "主管单位"); + ENG_FIELD_MEANING_MAP.put("BLSYS", "归属部门"); + ENG_FIELD_MEANING_MAP.put("ROLL", "绕经度方向旋转矩阵值"); + ENG_FIELD_MEANING_MAP.put("PITCH", "绕纬度方向旋转矩阵值"); + ENG_FIELD_MEANING_MAP.put("HEADING", "绕高程方向旋转矩阵值"); + ENG_FIELD_MEANING_MAP.put("SCALE", "模型缩放比例"); + ENG_FIELD_MEANING_MAP.put("IMPDSTRZ", "是否受下游顶托"); + ENG_FIELD_MEANING_MAP.put("PROV", "工程概况"); + ENG_FIELD_MEANING_MAP.put("ESTRYDIS", "河口距离"); + ENG_FIELD_MEANING_MAP.put("THRSMDAYS", "三同时评价允许误差天数"); + ENG_FIELD_MEANING_MAP.put("ZJXYDZ", "直接下游电站"); + ENG_FIELD_MEANING_MAP.put("EDTUN", "编制单位"); + ENG_FIELD_MEANING_MAP.put("EDTTM", "编制时间"); + ENG_FIELD_MEANING_MAP.put("DSNSTT", "勘测设计情况"); + ENG_FIELD_MEANING_MAP.put("YSDLEN", "引水道长"); + ENG_FIELD_MEANING_MAP.put("DMRKTP", "坝基岩性"); + ENG_FIELD_MEANING_MAP.put("HNTJZL", "混凝土浇筑量"); + ENG_FIELD_MEANING_MAP.put("GNTP", "容量构成"); + ENG_FIELD_MEANING_MAP.put("CNTRAR", "控制流域面积"); + ENG_FIELD_MEANING_MAP.put("CNTRSC", "控制面积占全流域比例"); + ENG_FIELD_MEANING_MAP.put("AVYRP", "多年平均降水量"); + ENG_FIELD_MEANING_MAP.put("AVQ", "多年平均流量"); + ENG_FIELD_MEANING_MAP.put("DSAVQ", "电站未建枯水期平均流量"); + ENG_FIELD_MEANING_MAP.put("DSMXQ", "设计洪峰流量"); + ENG_FIELD_MEANING_MAP.put("CHMXQ", "校核洪峰流量"); + ENG_FIELD_MEANING_MAP.put("RVLEN", "河道长度"); + ENG_FIELD_MEANING_MAP.put("RVGR", "河道比降"); + ENG_FIELD_MEANING_MAP.put("AVW", "多年平均径流量"); + ENG_FIELD_MEANING_MAP.put("AVYRQ", "多年平均年径流量"); + ENG_FIELD_MEANING_MAP.put("AVSD", "多年平均输沙量"); + ENG_FIELD_MEANING_MAP.put("AVS", "多年平均含沙量"); + ENG_FIELD_MEANING_MAP.put("MYAVMNAT", "多年平均最低气温"); + ENG_FIELD_MEANING_MAP.put("DSW1", "设计一日洪量"); + ENG_FIELD_MEANING_MAP.put("DSW3", "设计三日洪量"); + ENG_FIELD_MEANING_MAP.put("CHFLDR", "校核洪水历时"); + ENG_FIELD_MEANING_MAP.put("CHFLW", "校核洪水总量"); + ENG_FIELD_MEANING_MAP.put("CPSC", "库容系数"); + ENG_FIELD_MEANING_MAP.put("NRZAR", "正常蓄水位时水库面积"); + ENG_FIELD_MEANING_MAP.put("BCKLEN", "水库回水长度"); + ENG_FIELD_MEANING_MAP.put("NRAVWT", "天然河流平均水温"); + ENG_FIELD_MEANING_MAP.put("NRMXAVWT", "天然河流最高温月份多年平均水温"); + ENG_FIELD_MEANING_MAP.put("NRMNAVWT", "天然河流最低温月份多年平均水温"); + ENG_FIELD_MEANING_MAP.put("DNAVWT", "建成后坝下平均水温"); + ENG_FIELD_MEANING_MAP.put("DNMXAVWT", "建成后坝下最高温月份多年平均水温"); + ENG_FIELD_MEANING_MAP.put("DNMNAVWT", "建成后坝下最低温月份多年平均水温"); + ENG_FIELD_MEANING_MAP.put("NRUPAR", "坝址以上流域面积"); + ENG_FIELD_MEANING_MAP.put("NRAVZ", "坝址天然河流平均水位"); + ENG_FIELD_MEANING_MAP.put("NRAVH", "坝址天然河流平均水深"); + ENG_FIELD_MEANING_MAP.put("DSNFQFRQ", "设计入库洪水流量"); + ENG_FIELD_MEANING_MAP.put("CKFQFQR", "校核入库洪水流量"); + ENG_FIELD_MEANING_MAP.put("OBMXW3", "实测最大洪量(三天)"); + ENG_FIELD_MEANING_MAP.put("FDCZ", "水库淹没城镇"); + ENG_FIELD_MEANING_MAP.put("FDQT", "淹没其它设施"); + ENG_FIELD_MEANING_MAP.put("DSTCRVR", "距河源距离"); + ENG_FIELD_MEANING_MAP.put("CKW3", "校核洪量(三天)"); + ENG_FIELD_MEANING_MAP.put("FSLTDZ", "防洪限制水位"); + ENG_FIELD_MEANING_MAP.put("RSTP", "资源类别"); + ENG_FIELD_MEANING_MAP.put("ADJCPS", "调节库容单独"); + ENG_FIELD_MEANING_MAP.put("ADJCPM", "调节库容联合"); + ENG_FIELD_MEANING_MAP.put("YRGEB", "已正建规模装机容量"); + ENG_FIELD_MEANING_MAP.put("TTPWRB", "已正建规模年发电量"); + ENG_FIELD_MEANING_MAP.put("DMCREL", "坝顶高程"); + ENG_FIELD_MEANING_MAP.put("WSC", "水量利用系数"); + ENG_FIELD_MEANING_MAP.put("MXDMHG", "最大坝高"); + ENG_FIELD_MEANING_MAP.put("MXDMHGL", "最大坝高(左)"); + ENG_FIELD_MEANING_MAP.put("MXDMHGR", "最大坝高(右)"); + ENG_FIELD_MEANING_MAP.put("WVTPEL", "防浪墙顶高程"); + } + + private static final Map ENG_CODE_NAME_FIELD_MAP = new LinkedHashMap<>(); + + private static final Set ENG_NAME_COLUMNS = new HashSet<>(); + + private static final Map> ENG_DICT_VALUE_NAME_MAP = new LinkedHashMap<>(); + + static { + ENG_CODE_NAME_FIELD_MAP.put("BASE_ID", "BASE_NAME"); + ENG_CODE_NAME_FIELD_MAP.put("HBRVCD", "HBRVCD_NAME"); + ENG_CODE_NAME_FIELD_MAP.put("RVCD", "RVCD_NAME"); + ENG_CODE_NAME_FIELD_MAP.put("ADDVCD", "ADDVCD_NAME"); + ENG_CODE_NAME_FIELD_MAP.put("COUNTRY", "COUNTRY_NAME"); + ENG_CODE_NAME_FIELD_MAP.put("HYCD", "HYNM"); + ENG_CODE_NAME_FIELD_MAP.put("TOP_HYCD", "TOP_HYNM"); + ENG_CODE_NAME_FIELD_MAP.put("REACHCD", "REACHCD_NAME"); + ENG_NAME_COLUMNS.addAll(ENG_CODE_NAME_FIELD_MAP.values()); + + ENG_DICT_VALUE_NAME_MAP.put("USFL", buildValueNameMap("0", "禁用", "1", "启用")); + ENG_DICT_VALUE_NAME_MAP.put("DTIN", buildValueNameMap("0", "否", "1", "是")); + ENG_DICT_VALUE_NAME_MAP.put("MONTH_REPORT", buildValueNameMap("0", "否", "1", "是")); + ENG_DICT_VALUE_NAME_MAP.put("BLPRD", buildValueNameMap( + "1001000", "规划", + "1002000", "预可研", + "1003000", "环评", + "1004000", "可研", + "1005000", "在建", + "1006000", "招标设计", + "1007000", "施工详图", + "1009000", "建设", + "1010000", "蓄水阶段环保验收", + "1011000", "竣工", + "1012000", "竣工环保验收", + "1013000", "环境影响后评价" + )); + ENG_DICT_VALUE_NAME_MAP.put("BLDSTT", buildValueNameMap( + "1", "已建成未验收", + "2", "在建", + "3", "可研", + "4", "规划", + "5", "预可研", + "6", "已核准", + "7", "招标设计", + "8", "施工详图", + "9", "其他", + "10", "已建成已验收", + "11", "已开展后评价", + "31", "项目建议书", + "32", "可研", + "33", "已审批", + "34", "初步设计", + "35", "技施设计", + "36", "在建", + "37", "已建成未验收", + "38", "已建成已验收", + "39", "已开展后评价", + "40", "其他", + "61", "规划", + "62", "项目建议书", + "63", "预可研", + "64", "可研", + "65", "已核准", + "66", "初步设计", + "67", "招标设计", + "68", "技施设计", + "69", "施工详图", + "70", "在建", + "71", "已建成未验收", + "72", "已建成已验收", + "73", "已开展后评价", + "74", "其他", + "91", "拆除" + )); + ENG_DICT_VALUE_NAME_MAP.put("BLDSTT_CODE", buildValueNameMap( + "0", "未建/规划", + "1", "在建", + "2", "已建" + )); + ENG_DICT_VALUE_NAME_MAP.put("ENGTP", buildValueNameMap("1", "水电站", "2", "水利工程", "3", "航电枢纽")); + ENG_DICT_VALUE_NAME_MAP.put("PRSC", buildValueNameMap("1", "大型1", "2", "大型2", "3", "中型", "4", "小型")); + ENG_DICT_VALUE_NAME_MAP.put("SCRSC", buildValueNameMap("1", "大型1", "2", "大型2", "3", "中型", "4", "小型1", "5", "小型2")); + ENG_DICT_VALUE_NAME_MAP.put("PRGR", buildValueNameMap("1", "Ⅰ", "2", "Ⅱ", "3", "Ⅲ", "4", "Ⅳ", "5", "Ⅴ")); + ENG_DICT_VALUE_NAME_MAP.put("FN", buildValueNameMap( + "1", "发电", "2", "防洪", "3", "灌溉", "4", "供水", "5", "航运", + "6", "旅游", "7", "环境", "8", "养殖", "9", "其他" + )); + ENG_DICT_VALUE_NAME_MAP.put("BSSSIN", buildValueNameMap("5", "<Ⅵ", "6", "Ⅵ", "7", "Ⅶ", "8", "Ⅷ", "9", "≥Ⅸ")); + ENG_DICT_VALUE_NAME_MAP.put("FRSSIN", buildValueNameMap("0", "未设防", "6", "Ⅵ", "7", "Ⅶ", "8", "Ⅷ", "9", "≥Ⅸ")); + ENG_DICT_VALUE_NAME_MAP.put("ADJUST_ENG", buildValueNameMap("0", "否", "1", "是")); + ENG_DICT_VALUE_NAME_MAP.put("ISHVBRRG", buildValueNameMap("0", "无", "1", "有")); + ENG_DICT_VALUE_NAME_MAP.put("RGCP", buildValueNameMap( + "1", "多年调节", "2", "年调节", "3", "不完全年调节", "4", "径流式(无调节)", + "5", "季调节", "6", "月调节", "7", "周调节", "8", "日调节", "9", "其他" + )); + ENG_DICT_VALUE_NAME_MAP.put("DMAT", buildValueNameMap("0", "混凝土坝", "1", "土坝")); + ENG_DICT_VALUE_NAME_MAP.put("DMTP", buildValueNameMap( + "0", "混合型", "1", "重力坝", "2", "拱坝", "3", "土石坝", "4", "支墩坝", + "5", "混凝土闸坝", "6", "混凝土面板堆石坝", "7", "预应力坝", + "8", "复合土工膜面板堆石坝", "9", "碾压混凝土重力坝", "10", "混凝土重力坝" + )); + ENG_DICT_VALUE_NAME_MAP.put("DVTP", buildValueNameMap("1", "堤坝式", "2", "引水式", "3", "混合式")); + ENG_DICT_VALUE_NAME_MAP.put("CNTP", buildValueNameMap("1", "新建", "2", "改建", "3", "扩建", "4", "加固")); + ENG_DICT_VALUE_NAME_MAP.put("BLSYS", buildValueNameMap("1", "水利", "2", "能源", "3", "交通", "4", "农业", "5", "建设", "9", "其他")); + ENG_DICT_VALUE_NAME_MAP.put("IMPDSTRZ", buildValueNameMap("0", "否", "1", "是")); + } + + @Resource + private MsOperationLogMapper msOperationLogMapper; + + @Resource + private MsOperationLogDetailMapper msOperationLogDetailMapper; + + @Override + public void recordEngAddLog(SdEngInfoBH engInfo, String source) { + if (engInfo == null) { + return; + } + MsOperationLog mainLog = buildMainLog(null,"新增电站", source); + msOperationLogMapper.insert(mainLog); + + List details = new ArrayList<>(); + Set processedColumns = new HashSet<>(); + for (Field field : SdEngInfoBH.class.getDeclaredFields()) { + if (shouldSkipField(field)) { + continue; + } + field.setAccessible(true); + String columnName = resolveColumnName(field); + if (ENG_NAME_COLUMNS.contains(columnName) || processedColumns.contains(columnName)) { + continue; + } + Object newValue = getFieldValue(field, engInfo); + if (newValue == null) { + continue; + } + String nameColumn = ENG_CODE_NAME_FIELD_MAP.get(columnName); + Object newNameValue = StrUtil.isBlank(nameColumn) ? newValue : getColumnValue(engInfo, nameColumn); + details.add(buildDetail(mainLog.getId(), engInfo.getStcd(), columnName, + null, null, newValue, newNameValue, "新增字段值")); + processedColumns.add(columnName); + if (StrUtil.isNotBlank(nameColumn)) { + processedColumns.add(nameColumn); + } + } + batchInsertDetails(details); + } + + @Override + public void recordEngUpdateLog(SdEngInfoBH before, SdEngInfoBH after, String source) { + if (before == null || after == null) { + return; + } + + MsOperationLog mainLog = buildMainLog(before.getStcd(),"修改电站", source); + msOperationLogMapper.insert(mainLog); + + List details = new ArrayList<>(); + Set processedColumns = new HashSet<>(); + for (Field field : SdEngInfoBH.class.getDeclaredFields()) { + if (shouldSkipField(field)) { + continue; + } + field.setAccessible(true); + String columnName = resolveColumnName(field); + if (ENG_NAME_COLUMNS.contains(columnName) || processedColumns.contains(columnName)) { + continue; + } + Object oldValue = getFieldValue(field, before); + Object newValue = getFieldValue(field, after); + String nameColumn = ENG_CODE_NAME_FIELD_MAP.get(columnName); + Object oldNameValue = resolveNameValue(columnName, nameColumn, oldValue, before); + Object newNameValue = resolveNameValue(columnName, nameColumn, newValue, after); + if (equalsValue(oldValue, newValue) && equalsValue(oldNameValue, newNameValue)) { + continue; + } + details.add(buildDetail(mainLog.getId(), after.getStcd(), columnName, + oldValue, oldNameValue, newValue, newNameValue, "修改字段值")); + processedColumns.add(columnName); + if (StrUtil.isNotBlank(nameColumn)) { + processedColumns.add(nameColumn); + } + } + batchInsertDetails(details); + } + + @Override + public void recordEngDeleteLog(SdEngInfoBH engInfo, String source) { + if (engInfo == null) { + return; + } + MsOperationLog mainLog = buildMainLog(engInfo.getStcd(),"删除电站", source); + msOperationLogMapper.insert(mainLog); + + List details = new ArrayList<>(); + Set processedColumns = new HashSet<>(); + for (Field field : SdEngInfoBH.class.getDeclaredFields()) { + if (shouldSkipField(field)) { + continue; + } + field.setAccessible(true); + String columnName = resolveColumnName(field); + if (ENG_NAME_COLUMNS.contains(columnName) || processedColumns.contains(columnName)) { + continue; + } + Object oldValue = getFieldValue(field, engInfo); + if (oldValue == null) { + continue; + } + String nameColumn = ENG_CODE_NAME_FIELD_MAP.get(columnName); + Object oldNameValue = resolveNameValue(columnName, nameColumn, oldValue, engInfo); + details.add(buildDetail(mainLog.getId(), engInfo.getStcd(), columnName, + oldValue, oldNameValue, null, null, "删除字段值")); + processedColumns.add(columnName); + if (StrUtil.isNotBlank(nameColumn)) { + processedColumns.add(nameColumn); + } + } + batchInsertDetails(details); + } + + private MsOperationLog buildMainLog(String recordId,String remark, String source) { + MsOperationLog log = new MsOperationLog(); + log.setOperator(resolveOperator()); + log.setOperateTime(new Date()); + log.setTableName(ENG_TABLE_NAME); + log.setRecordId(recordId); + log.setSource(StrUtil.trimToNull(source)); + log.setRemark(remark); + return log; + } + + private MsOperationLogDetail buildDetail(String mainId, + String stationCode, + String fieldCode, + Object oldValueCode, + Object oldValueName, + Object newValueCode, + Object newValueName, + String remark) { + MsOperationLogDetail detail = new MsOperationLogDetail(); + detail.setMainId(mainId); + detail.setTableName(ENG_TABLE_NAME); + detail.setStationCode(stationCode); + detail.setFieldCode(fieldCode); + detail.setFieldMeaning(ENG_FIELD_MEANING_MAP.getOrDefault(fieldCode, fieldCode)); + detail.setOldValueCode(formatValue(oldValueCode)); + detail.setOldValueName(formatValue(oldValueName)); + detail.setNewValueCode(formatValue(newValueCode)); + detail.setNewValueName(formatValue(newValueName)); + detail.setRemark(remark); + return detail; + } + + private void batchInsertDetails(List details) { + msOperationLogDetailMapper.insert(details); + } + + private boolean shouldSkipField(Field field) { + if (Modifier.isStatic(field.getModifiers())) { + return true; + } + TableField tableField = field.getAnnotation(TableField.class); + if (tableField != null && !tableField.exist()) { + return true; + } + return false; + } + + private String resolveColumnName(Field field) { + TableId tableId = field.getAnnotation(TableId.class); + if (tableId != null) { + return camelToUpperUnderline(field.getName()); + } + TableField tableField = field.getAnnotation(TableField.class); + if (tableField != null && StrUtil.isNotBlank(tableField.value())) { + return tableField.value(); + } + return camelToUpperUnderline(field.getName()); + } + + private Object getFieldValue(Field field, Object target) { + try { + return field.get(target); + } catch (IllegalAccessException e) { + return null; + } + } + + private Object getColumnValue(Object target, String columnName) { + if (target == null || StrUtil.isBlank(columnName)) { + return null; + } + for (Field field : SdEngInfoBH.class.getDeclaredFields()) { + if (shouldSkipField(field)) { + continue; + } + field.setAccessible(true); + if (StrUtil.equals(resolveColumnName(field), columnName)) { + return getFieldValue(field, target); + } + } + return null; + } + + private Object resolveNameValue(String fieldCode, String nameColumn, Object rawValue, SdEngInfoBH target) { + if (StrUtil.isNotBlank(nameColumn)) { + return getColumnValue(target, nameColumn); + } + return resolveDictName(fieldCode, rawValue); + } + + private Object resolveDictName(String fieldCode, Object rawValue) { + String text = formatValue(rawValue); + if (StrUtil.isBlank(text)) { + return rawValue; + } + Map dictMap = ENG_DICT_VALUE_NAME_MAP.get(fieldCode); + if (dictMap == null || dictMap.isEmpty()) { + return rawValue; + } + if (!text.contains(",") && !text.contains(";")) { + return dictMap.getOrDefault(text, rawValue == null ? null : text); + } + String[] parts = text.split("[,;]"); + List names = new ArrayList<>(); + for (String part : parts) { + String code = StrUtil.trim(part); + if (StrUtil.isBlank(code)) { + continue; + } + names.add(dictMap.getOrDefault(code, code)); + } + return names.isEmpty() ? rawValue : String.join(",", names); + } + + private static Map buildValueNameMap(String... keyValues) { + Map valueMap = new LinkedHashMap<>(); + if (keyValues == null) { + return valueMap; + } + for (int i = 0; i + 1 < keyValues.length; i += 2) { + valueMap.put(keyValues[i], keyValues[i + 1]); + } + return valueMap; + } + + private boolean equalsValue(Object oldValue, Object newValue) { + return StrUtil.equals(formatValue(oldValue), formatValue(newValue)); + } + + private String formatValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof Date date) { + return DateUtil.formatDateTime(date); + } + return String.valueOf(value); + } + + private String resolveOperator() { + try { + return SecurityUtils.getCurrentUsername(); + } catch (Exception ignored) { + try { + return SecurityUtils.getUserId(); + } catch (Exception ex) { + return null; + } + } + } + + private String camelToUpperUnderline(String text) { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < text.length(); i++) { + char ch = text.charAt(i); + if (Character.isUpperCase(ch) && i > 0) { + builder.append('_'); + } + builder.append(Character.toUpperCase(ch)); + } + return builder.toString(); + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdAddvcdDicServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdAddvcdDicServiceImpl.java new file mode 100644 index 00000000..05f5a959 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdAddvcdDicServiceImpl.java @@ -0,0 +1,28 @@ +package com.yfd.platform.qgc_base.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.qgc_base.domain.SdAddvcdDic; +import com.yfd.platform.qgc_base.mapper.SdAddvcdDicMapper; +import com.yfd.platform.qgc_base.service.ISdAddvcdDicService; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import java.util.List; + +/** + *

+ * 行政区字典表 服务实现类 + *

+ */ +@Service +public class SdAddvcdDicServiceImpl extends ServiceImpl implements ISdAddvcdDicService { + + @Override + public List selectForDropdown(Integer grd, String paddvcd) { + return this.lambdaQuery() + .eq(grd != null, SdAddvcdDic::getGrd, grd) + .eq(StringUtils.hasText(paddvcd), SdAddvcdDic::getPaddvcd, paddvcd) + .orderByAsc(SdAddvcdDic::getOrderIndex) + .list(); + } +} 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 0ee131b5..520e3752 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 @@ -4,8 +4,15 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +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.common.DataSourceLoadOptionsBase; import com.yfd.platform.common.DataSourceRequest; @@ -19,23 +26,24 @@ import com.yfd.platform.qgc_base.domain.SdEngInfoBH; import com.yfd.platform.qgc_base.domain.SdEngInfoBHRequest; import com.yfd.platform.qgc_base.domain.vo.EngBaseInfoVo; import com.yfd.platform.qgc_base.domain.vo.EngEiaapprovalVo; +import com.yfd.platform.qgc_base.domain.vo.EngOperatVo; +import com.yfd.platform.qgc_base.domain.vo.EngStbprpDataVo; +import com.yfd.platform.qgc_base.domain.vo.EngStBaseInfoVo; +import com.yfd.platform.qgc_base.domain.vo.EngStInfoResultVo; import com.yfd.platform.qgc_base.domain.vo.EngVmsstbprptVo; import com.yfd.platform.qgc_base.mapper.SdEngInfoBHMapper; +import com.yfd.platform.qgc_base.service.IMsOperationLogService; import com.yfd.platform.qgc_base.service.ISdEngInfoBHService; +import com.yfd.platform.system.service.IAdminAuthService; import com.yfd.platform.utils.QgcQueryWrapperUtil; import com.yfd.platform.utils.SecurityUtils; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.lang.reflect.Field; +import java.util.*; import java.util.stream.Collectors; /** @@ -46,6 +54,19 @@ import java.util.stream.Collectors; @Service public class SdEngInfoBHServiceImpl extends ServiceImpl implements ISdEngInfoBHService { + private static final Map ENG_CODE_NAME_FIELD_MAP = new LinkedHashMap<>(); + + static { + ENG_CODE_NAME_FIELD_MAP.put("baseId", "baseName"); + ENG_CODE_NAME_FIELD_MAP.put("hbrvcd", "hbrvcdName"); + ENG_CODE_NAME_FIELD_MAP.put("rvcd", "rvcdName"); + ENG_CODE_NAME_FIELD_MAP.put("addvcd", "addvcdName"); + ENG_CODE_NAME_FIELD_MAP.put("country", "countryName"); + ENG_CODE_NAME_FIELD_MAP.put("hycd", "hynm"); + ENG_CODE_NAME_FIELD_MAP.put("topHycd", "topHynm"); + ENG_CODE_NAME_FIELD_MAP.put("reachcd", "reachcdName"); + } + @Resource private SdEngInfoBHMapper engInfoBHMapper; @@ -55,6 +76,15 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl queryPageList(Page page, String ennm, String rvcd, String baseId, String hycd) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); @@ -67,7 +97,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl authorizedStations = getUserAuthorizedStationCodes(); if (authorizedStations != null && !authorizedStations.isEmpty()) { wrapper.in(SdEngInfoBH::getStcd, authorizedStations); - }else if (!"admin".equals(SecurityUtils.getCurrentUsername())){ + }else if (!adminAuthService.isCurrentManagedAdmin()){ return page; } return this.page(page, wrapper); @@ -94,19 +124,22 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl rvcds = sdEngInfoBHRequest.getRvcds(); List hbrvcds = sdEngInfoBHRequest.getHbrvcds(); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(StringUtils.hasText(baseId), SdEngInfoBH::getBaseId, baseId) .eq(StringUtils.hasText(hbrvcd), SdEngInfoBH::getHbrvcd, hbrvcd) + .eq(StrUtil.isNotBlank(reachcd), SdEngInfoBH::getRvcd, reachcd) + .eq(StrUtil.isNotBlank(rvcd), SdEngInfoBH::getReachcd, rvcd) .eq(StrUtil.isNotBlank(rvcd), SdEngInfoBH::getReachcd, rvcd) .in(rvcds != null && !rvcds.isEmpty(), SdEngInfoBH::getReachcd, rvcds) .in(hbrvcds != null && !hbrvcds.isEmpty(), SdEngInfoBH::getHbrvcd, hbrvcds) .like(StringUtils.hasText(ennm), SdEngInfoBH::getEnnm, ennm) - .select(SdEngInfoBH::getStcd, SdEngInfoBH::getEnnm, SdEngInfoBH::getBaseId) - .orderByAsc(SdEngInfoBH::getOrderIndex); + .select(SdEngInfoBH::getStcd, SdEngInfoBH::getEnnm, SdEngInfoBH::getReachcdName, SdEngInfoBH::getYrgeb, SdEngInfoBH::getBaseId) + .orderByAsc(SdEngInfoBH::getBaseId,SdEngInfoBH::getOrderIndex); - if("admin".equals(SecurityUtils.getCurrentUsername())){ + if(adminAuthService.isCurrentManagedAdmin()){ return this.list(wrapper); } Set authorizedStations = getUserAuthorizedStationCodes(); @@ -186,17 +219,324 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl engInfoPatch, String source) throws JsonMappingException { + Map filteredPatch = filterEngInfoPatchFields(engInfoPatch); + if (filteredPatch.isEmpty()) { + return false; + } + String stcd = toTextValue(filteredPatch.get("stcd")); + if (!StringUtils.hasText(stcd)) { + return false; + } + SdEngInfoBH before = this.getById(stcd); + if (before == null) { + return false; + } + SdEngInfoBH after = BeanUtil.copyProperties(before, SdEngInfoBH.class); + objectMapper.updateValue(after, filteredPatch); + fillRelatedNameFields(after); + boolean result = updateEngInfoByPatch(stcd, after, filteredPatch); + if (result) { + msOperationLogService.recordEngUpdateLog(before, after, source); + } + return result; + } + + private boolean updateEngInfoByPatch(String stcd, SdEngInfoBH after, Map engInfoPatch) { + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.eq("STCD", stcd); + boolean hasUpdateField = false; + for (Field field : SdEngInfoBH.class.getDeclaredFields()) { + field.setAccessible(true); + String fieldName = field.getName(); + if ("serialVersionUID".equals(fieldName) || "stcd".equals(fieldName)) { + continue; + } + boolean explicitPatched = engInfoPatch.containsKey(fieldName); + boolean linkedNamePatched = isLinkedNameFieldPatched(fieldName, engInfoPatch); + if (!explicitPatched && !linkedNamePatched) { + continue; + } + String resolveColumnName = resolveColumnName(field); + Object fieldValue = getFieldValue(field, after); + if (fieldValue == null) { + updateWrapper.setSql(resolveColumnName + " = NULL"); + } else { + updateWrapper.set(resolveColumnName, fieldValue); + } + hasUpdateField = true; + } + if (!hasUpdateField) { + return true; + } + return this.update(null, updateWrapper); + } + + private void fillRelatedNameFields(SdEngInfoBH engInfo) { + if (engInfo == null) { + return; + } + Map paramMap = new HashMap<>(); + paramMap.put("baseId", engInfo.getBaseId()); + paramMap.put("hbrvcd", engInfo.getHbrvcd()); + paramMap.put("rvcd", engInfo.getRvcd()); + paramMap.put("addvcd", engInfo.getAddvcd()); + paramMap.put("country", engInfo.getCountry()); + paramMap.put("hycd", engInfo.getHycd()); + paramMap.put("topHycd", engInfo.getTopHycd()); + paramMap.put("reachcd", engInfo.getReachcd()); + + Map row = microservicDynamicSQLMapper.getOneBySql(buildEngRelatedNameSql(paramMap), paramMap); + engInfo.setBaseName(resolveRelatedName(engInfo.getBaseId(), row, "BASENAME")); + engInfo.setHbrvcdName(resolveRelatedName(engInfo.getHbrvcd(), row, "HBRVNM")); + engInfo.setRvcdName(resolveRelatedName(engInfo.getRvcd(), row, "RVNM")); + engInfo.setAddvcdName(resolveRelatedName(engInfo.getAddvcd(), row, "ADDVNM")); + engInfo.setCountryName(resolveRelatedName(engInfo.getCountry(), row, "COUNTRY_NAME")); + engInfo.setHynm(resolveRelatedName(engInfo.getHycd(), row, "HYNM")); + engInfo.setTopHynm(resolveRelatedName(engInfo.getTopHycd(), row, "TOP_HYNM")); + engInfo.setReachcdName(resolveRelatedName(engInfo.getReachcd(), row, "REACHCD_NAME")); + } + + private String buildEngRelatedNameSql(Map paramMap) { + StringBuilder sql = new StringBuilder("SELECT "); + sql.append(buildScalarNameSelect( + StringUtils.hasText((String) paramMap.get("baseId")), + "(SELECT hb.BASENAME FROM SD_HYDROBASE hb WHERE hb.BASEID = #{map.baseId} AND NVL(hb.IS_DELETED, 0) = 0 AND ROWNUM = 1)", + "BASENAME" + )); + sql.append(", "); + sql.append(buildHbrvNameSelect(paramMap)); + sql.append(", "); + sql.append(buildScalarNameSelect( + StringUtils.hasText((String) paramMap.get("rvcd")), + "(SELECT rv.RVNM FROM SD_RVCD_DIC rv WHERE rv.RVCD = #{map.rvcd} AND ROWNUM = 1)", + "RVNM" + )); + sql.append(", "); + sql.append(buildScalarNameSelect( + StringUtils.hasText((String) paramMap.get("addvcd")), + "(SELECT addv.ADDVNM FROM SD_ADDVCD_DIC addv WHERE addv.ADDVCD = #{map.addvcd} AND ROWNUM = 1)", + "ADDVNM" + )); + sql.append(", "); + sql.append(buildScalarNameSelect( + StringUtils.hasText((String) paramMap.get("country")), + "(SELECT country.COUNTRY_NAME FROM SD_COUNTRY_B country WHERE country.COUNTRY_ID = #{map.country} " + + "AND NVL(country.ENABLED, 1) = 1 AND ROWNUM = 1)", + "COUNTRY_NAME" + )); + sql.append(", "); + sql.append(buildScalarNameSelect( + StringUtils.hasText((String) paramMap.get("hycd")), + "(SELECT hy.HYNM FROM SD_HYCD_DIC hy WHERE hy.HYCD = #{map.hycd} " + + "AND NVL(hy.IS_DELETED, 0) = 0 AND NVL(hy.ENABLED, 1) = 1 AND ROWNUM = 1)", + "HYNM" + )); + sql.append(", "); + sql.append(buildScalarNameSelect( + StringUtils.hasText((String) paramMap.get("topHycd")), + "(SELECT hy.HYNM FROM SD_HYCD_DIC hy WHERE hy.HYCD = #{map.topHycd} " + + "AND NVL(hy.IS_DELETED, 0) = 0 AND NVL(hy.ENABLED, 1) = 1 AND ROWNUM = 1)", + "TOP_HYNM" + )); + sql.append(", "); + sql.append(buildReachcdNameSelect(paramMap)); + sql.append(" FROM DUAL"); + return sql.toString(); + } + + private String buildHbrvNameSelect(Map paramMap) { + if (!StringUtils.hasText((String) paramMap.get("hbrvcd"))) { + return "NULL AS HBRVNM"; + } + StringBuilder sql = new StringBuilder("(SELECT hbrv.HBRVNM FROM SD_HBRV_DIC hbrv WHERE hbrv.HBRVCD = #{map.hbrvcd} "); + if (StringUtils.hasText((String) paramMap.get("baseId"))) { + sql.append("AND hbrv.BASEID = #{map.baseId} "); + } + sql.append("AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 AND ROWNUM = 1) AS HBRVNM"); + return sql.toString(); + } + + private String buildScalarNameSelect(boolean hasText, String querySql, String alias) { + if (!hasText) { + return "NULL AS " + alias; + } + return querySql + " AS " + alias; + } + + private String buildReachcdNameSelect(Map paramMap) { + if (!StringUtils.hasText((String) paramMap.get("reachcd"))) { + return "NULL AS REACHCD_NAME"; + } + return "(SELECT LISTAGG(pathNode.RVNM, '-') WITHIN GROUP (ORDER BY pathNode.LVL DESC) " + + "FROM ( " + + " SELECT rv.RVNM, LEVEL AS LVL " + + " FROM SD_RVCD_DIC rv " + + " START WITH rv.RVCD = #{map.reachcd} " + + " CONNECT BY PRIOR rv.PRVCD = rv.RVCD " + + ") pathNode) AS REACHCD_NAME"; + } + + private String resolveRelatedName(String code, Map row, String column) { + if (code == null) { + return null; + } + if (code.isBlank()) { + return ""; + } + if (row == null) { + return null; + } + Object value = row.get(column); + if (value == null) { + value = row.get(column.toLowerCase()); + } + return value == null ? null : String.valueOf(value); + } + + private Map filterEngInfoPatchFields(Map engInfoPatch) { + Map filteredPatch = new LinkedHashMap<>(); + if (engInfoPatch == null || engInfoPatch.isEmpty()) { + return filteredPatch; + } + Set validFieldNames = new HashSet<>(); + for (Field field : SdEngInfoBH.class.getDeclaredFields()) { + if ("serialVersionUID".equals(field.getName())) { + continue; + } + validFieldNames.add(field.getName()); + } + for (Map.Entry entry : engInfoPatch.entrySet()) { + if (validFieldNames.contains(entry.getKey())) { + filteredPatch.put(entry.getKey(), entry.getValue()); + } + } + return filteredPatch; + } + + private boolean isLinkedNameFieldPatched(String fieldName, Map engInfoPatch) { + for (Map.Entry entry : ENG_CODE_NAME_FIELD_MAP.entrySet()) { + if (entry.getValue().equals(fieldName) && engInfoPatch.containsKey(entry.getKey())) { + return true; + } + } + return false; + } + + private String resolveColumnName(Field field) { + TableId tableId = field.getAnnotation(TableId.class); + if (tableId != null) { + return camelToUpperUnderline(field.getName()); + } + TableField tableField = field.getAnnotation(TableField.class); + if (tableField != null && StrUtil.isNotBlank(tableField.value())) { + return tableField.value(); + } + return camelToUpperUnderline(field.getName()); + } + + private Object getFieldValue(Field field, Object target) { + try { + return field.get(target); + } catch (IllegalAccessException e) { + return null; + } + } + + private String toTextValue(Object value) { + if (value == null) { + return null; + } + String text = String.valueOf(value); + return text.isBlank() ? null : text; + } + + private String camelToUpperUnderline(String text) { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < text.length(); i++) { + char ch = text.charAt(i); + if (Character.isUpperCase(ch) && i > 0) { + builder.append('_'); + } + builder.append(Character.toUpperCase(ch)); + } + return builder.toString(); } @Override public boolean deleteEngInfo(String stcd) { - return this.removeById(stcd); + if (StrUtil.isBlank(stcd)) { + return false; + } + return deleteEngInfo(java.util.Collections.singletonList(stcd), null); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean deleteEngInfo(List ids, String source) { + List stcdList = ids == null ? new ArrayList<>() : ids.stream() + .filter(StrUtil::isNotBlank) + .distinct() + .collect(Collectors.toList()); + if (CollUtil.isEmpty(stcdList)) { + return false; + } + List beforeList = this.lambdaQuery() + .in(SdEngInfoBH::getStcd, stcdList) + .eq(SdEngInfoBH::getIsDeleted, 0) + .list(); + if (CollUtil.isEmpty(beforeList)) { + return false; + } + boolean result = this.update(new LambdaUpdateWrapper() + .in(SdEngInfoBH::getStcd, stcdList) + .eq(SdEngInfoBH::getIsDeleted, 0) + .set(SdEngInfoBH::getIsDeleted, 1) + .set(SdEngInfoBH::getDeleteUser, SecurityUtils.getCurrentUsername()) + .set(SdEngInfoBH::getDeleteTime, new Date())); + if (result) { + for (SdEngInfoBH before : beforeList) { + msOperationLogService.recordEngDeleteLog(before, source); + } + } + return result; } @Override @@ -349,6 +689,185 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl getOperatKendoList(DataSourceRequest dataSourceRequest) { + DataSourceResult result = new DataSourceResult<>(); + result.setAggregates(new HashMap<>()); + if (dataSourceRequest == null) { + result.setData(new ArrayList<>()); + result.setTotal(0L); + return result; + } + + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + if (CollUtil.isEmpty(dataSourceRequest.getGroup())) { + return queryOperatSummaryList(dataSourceRequest, loadOptions); + } + return queryOperatGroupList(dataSourceRequest, loadOptions); + } + + @Override + public DataSourceResult getStbprpDataKendoListCust(DataSourceRequest dataSourceRequest, String tbCode, Boolean ignorePageLimit) { + DataSourceResult result = new DataSourceResult<>(); + result.setAggregates(new HashMap<>()); + if (StrUtil.isBlank(tbCode)) { + result.setData(new ArrayList<>()); + result.setTotal(0L); + return result; + } + DataSourceRequest request = dataSourceRequest == null ? new DataSourceRequest() : dataSourceRequest; + if (!Boolean.TRUE.equals(ignorePageLimit) && request.getTake() == 0) { + request.setTake(2000); + } + + DataSourceLoadOptionsBase loadOptions = request.toDevRequest(); + List tableMetaList = queryStbprpTableMeta(tbCode); + if (CollUtil.isEmpty(tableMetaList)) { + return result; + } + + String firstTableName = tableMetaList.getFirst().tableName(); + String detailSql = buildStbprpDataDetailSql(request, tableMetaList); + Map paramMap = new HashMap<>(); + String filterSql = buildStbprpDataFilterCondition(request.getFilter(), paramMap, new int[]{0}, tableMetaList); + if (StrUtil.isNotBlank(filterSql)) { + detailSql = detailSql + " AND " + filterSql; + } + + if (CollUtil.isEmpty(request.getGroup())) { + String sql = detailSql + buildStbprpDataOrderBySql(request.getSort(), tableMetaList); + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List> rows = microservicDynamicSQLMapper.pageAllList(page, sql, paramMap); + List list = new ArrayList<>(); + for (Map row : rows) { + list.add(new EngStbprpDataVo(row)); + } + result.setData(list); + result.setTotal(page == null ? list.size() : page.getTotal()); + return result; + } + + GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup(); + String groupSql = buildStbprpDataGroupSql(detailSql, request.getGroup(), tableMetaList); + List> rows = microservicDynamicSQLMapper.pageAllList(null, groupSql, paramMap); + if (Boolean.TRUE.equals(request.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal((long) rows.size()); + return result; + } + + private DataSourceResult queryOperatSummaryList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildOperatSummarySelectSql(dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildOperatCategorySql()) + .append(") cat ") + .append("LEFT JOIN (SELECT * FROM (") + .append(buildOperatBaseViewSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = buildOperatBaseFilterCondition(dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StringUtils.hasText(filterSql)) { + sql.append(" AND ").append(filterSql); + } + sql.append(") src ON cat.repCode = src.repCode ") + .append("GROUP BY cat.repCode, cat.sttpName, cat.orderIndex ") + .append(buildOperatSummaryOrderBySql(dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, sql.toString(), paramMap, EngOperatVo.class); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page == null ? list.size() : page.getTotal()); + result.setAggregates(new HashMap<>()); + return result; + } + + private DataSourceResult queryOperatGroupList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + List groups = dataSourceRequest.getGroup(); + GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup(); + List selectItems = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || !StringUtils.hasText(descriptor.getField())) { + continue; + } + String column = mapOperatGroupColumn(descriptor.getField()); + if (!StringUtils.hasText(column)) { + continue; + } + selectItems.add(column + " AS " + descriptor.getField().toUpperCase()); + selectItems.add("COUNT(*) AS COUNT_" + descriptor.getField().toUpperCase()); + if (CollUtil.isNotEmpty(descriptor.getAggregates())) { + for (DataSourceRequest.AggregateDescriptor aggregate : descriptor.getAggregates()) { + String aggregateColumn = mapOperatGroupColumn(aggregate.getField()); + if (!StringUtils.hasText(aggregateColumn) || !StringUtils.hasText(aggregate.getAggregate())) { + continue; + } + String aggregateSql = buildAggregateSql(aggregate.getAggregate(), aggregateColumn, aggregate.getField()); + if (StringUtils.hasText(aggregateSql)) { + selectItems.add(aggregateSql); + } + } + } + } + if (selectItems.isEmpty()) { + selectItems.add("t.STCD AS STCD"); + selectItems.add("COUNT(*) AS COUNT_STCD"); + } + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(String.join(", ", selectItems)) + .append(" FROM (") + .append(buildOperatStateViewSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + if (!containsOperatYearFilter(dataSourceRequest.getFilter())) { + sql.append(" AND t.yr = ").append(new Date().getYear() + 1900); + } + String filterSql = buildOperatGroupFilterCondition(dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StringUtils.hasText(filterSql)) { + sql.append(" AND ").append(filterSql); + } + + List groupByColumns = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || !StringUtils.hasText(descriptor.getField())) { + continue; + } + String column = mapOperatGroupColumn(descriptor.getField()); + if (StringUtils.hasText(column)) { + groupByColumns.add(column); + } + } + if (!groupByColumns.isEmpty()) { + sql.append(" GROUP BY ").append(String.join(", ", groupByColumns)); + } + sql.append(buildOperatGroupOrderBySql(groups)); + + List> rows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap); + DataSourceResult result = new DataSourceResult<>(); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + @Override public DataSourceResult getEiaapprovalKendoList(DataSourceRequest dataSourceRequest) { DataSourceResult result = new DataSourceResult<>(); @@ -369,12 +888,13 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl page = null; - if (dataSourceRequest.getTake() > 0) { - page = new Page<>(dataSourceRequest.getSkip() / dataSourceRequest.getTake() + 1, - dataSourceRequest.getTake()); - } - +// Page page = null; +// if (dataSourceRequest.getTake() > 0) { +// page = new Page<>(dataSourceRequest.getSkip() / dataSourceRequest.getTake() + 1, +// dataSourceRequest.getTake()); +// } + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); Map paramMap = new HashMap<>(); StringBuilder sql = new StringBuilder(buildEiaapprovalBaseSql()); @@ -462,6 +982,34 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl 0 THEN SUBSTR(" + sttpExpr + ", 1, INSTR(" + sttpExpr + ", '_') - 1) ELSE " + sttpExpr + " END AS repCode, " + + dtinExpr + " AS dtin, " + + bldsttExpr + " AS bldsttCcode, " + + baseIdExpr + " AS baseId, " + + hbrvcdExpr + " AS hbrvcd, " + + rvcdExpr + " AS rvcd, " + + rvcdNameExpr + " AS rvcdName, " + + addvcdNameExpr + " AS addvcdName, " + + rstcdExpr + " AS rstcd, " + + ennmExpr + " AS ennm " + + "FROM " + fromSql + " " + + joinSql + " WHERE " + whereSql; + } + + private String buildOperatStateViewSql() { + return "SELECT " + + "src.repCode AS repCode, " + + "src.sttpCode AS sttpCode, " + + "src.repCode AS pcode, " + + "parent.STTP_NAME AS pname, " + + "child.STTP_NAME AS sttpName, " + + "src.stcd AS stcd, " + + "src.ennm AS ennm, " + + "src.stnm AS stnm, " + + "src.addvcdName AS addvcdName, " + + "src.rvcdName AS rvcdName, " + + "src.baseId AS baseId, " + + "src.dtin AS dtin, " + + "src.bldsttCcode AS bldsttCcode, " + + "state.RUN_STATE AS runState, " + + "state.STD_STATE AS stdState, " + + "state.STD_SSTATE AS runSstate, " + + "state.YR AS yr " + + "FROM (" + buildOperatBaseViewSql() + ") src " + + "LEFT JOIN SD_STTP_B child ON child.STTP_CODE = src.sttpCode AND NVL(child.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_STTP_B parent ON parent.STTP_CODE = src.repCode AND NVL(parent.IS_DELETED, 0) = 0 " + + "INNER JOIN MS_STSTATE_T state ON state.STCD = src.stcd AND NVL(state.IS_DELETED, 0) = 0"; + } + + private String buildOperatSummarySelectSql(List selectFields) { + Map columnMap = new LinkedHashMap<>(); + columnMap.put("repCode", "cat.repCode AS repCode"); + columnMap.put("sttpName", "cat.sttpName AS sttpName"); + columnMap.put("count", "COUNT(src.repCode) AS count"); + List items = new ArrayList<>(); + if (CollUtil.isNotEmpty(selectFields)) { + for (String field : selectFields) { + String column = columnMap.get(field); + if (StringUtils.hasText(column)) { + items.add(column); + } + } + } + if (items.isEmpty()) { + items.addAll(columnMap.values()); + } + return String.join(", ", items); + } + + private String buildOperatSummaryOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY cat.orderIndex ASC NULLS LAST, cat.repCode ASC"; + } + List orderItems = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sortDescriptor : sortList) { + if (sortDescriptor == null || !StringUtils.hasText(sortDescriptor.getField())) { + continue; + } + String column = mapOperatSummaryColumn(sortDescriptor.getField()); + if (!StringUtils.hasText(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sortDescriptor.getDir()) || "des".equalsIgnoreCase(sortDescriptor.getDir()) ? "DESC" : "ASC"; + orderItems.add(column + " " + dir); + } + if (orderItems.isEmpty()) { + return " ORDER BY cat.orderIndex ASC NULLS LAST, cat.repCode ASC"; + } + return " ORDER BY " + String.join(", ", orderItems); + } + + private String buildOperatBaseFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StringUtils.hasText(filter.getField())) { + String column = mapOperatBaseColumn(filter.getField()); + return buildOperatCondition(column, filter, paramMap, indexHolder, false, "operatBase"); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List childConditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildOperatBaseFilterCondition(child, paramMap, indexHolder); + if (StringUtils.hasText(childSql)) { + childConditions.add("(" + childSql + ")"); + } + } + if (childConditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, childConditions); + } + + private String buildOperatGroupFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StringUtils.hasText(filter.getField())) { + String field = filter.getField(); + String column = mapOperatGroupColumn(field); + boolean dateField = false; + return buildOperatCondition(column, filter, paramMap, indexHolder, dateField, "operatGroup"); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List childConditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildOperatGroupFilterCondition(child, paramMap, indexHolder); + if (StringUtils.hasText(childSql)) { + childConditions.add("(" + childSql + ")"); + } + } + if (childConditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, childConditions); + } + + private String buildOperatCondition(String column, + DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder, + boolean dateField, + String keyPrefix) { + if (!StringUtils.hasText(column) || filter == null) { + return ""; + } + String operator = filter.getOperator() == null ? "eq" : filter.getOperator().toLowerCase(); + Object value = filter.getValue(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("isempty".equals(operator)) { + return "(" + column + " IS NULL OR " + column + " = '')"; + } + if ("isnotempty".equals(operator)) { + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + } + if ("in".equals(operator) || "ni".equals(operator)) { + List values = normalizeFilterValues(value); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String key = keyPrefix + indexHolder[0]++; + paramMap.put(key, item); + placeholders.add("#{map." + key + "}"); + } + return column + ("ni".equals(operator) ? " NOT IN (" : " IN (") + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + String key = keyPrefix + indexHolder[0]++; + String expr = buildOperatValueExpr(key, dateField, value); + return switch (operator) { + case "eq" -> { + paramMap.put(key, value); + yield column + " = " + expr; + } + case "neq" -> { + paramMap.put(key, value); + yield column + " <> " + expr; + } + case "contains" -> { + paramMap.put(key, "%" + value + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "doesnotcontain" -> { + paramMap.put(key, "%" + value + "%"); + yield column + " NOT LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, value + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + value); + yield column + " LIKE #{map." + key + "}"; + } + case "gt" -> { + paramMap.put(key, value); + yield column + " > " + expr; + } + case "gte" -> { + paramMap.put(key, value); + yield column + " >= " + expr; + } + case "lt" -> { + paramMap.put(key, value); + yield column + " < " + expr; + } + case "lte" -> { + paramMap.put(key, value); + yield column + " <= " + expr; + } + default -> ""; + }; + } + + private String buildOperatValueExpr(String paramKey, boolean dateField, Object value) { + if (!dateField || value == null) { + return "#{map." + paramKey + "}"; + } + String text = String.valueOf(value).trim(); + if (text.length() <= 10) { + return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD')"; + } + return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD HH24:MI:SS')"; + } + + private String mapOperatSummaryColumn(String field) { + if (!StringUtils.hasText(field)) { + return null; + } + return switch (field) { + case "repCode" -> "cat.repCode"; + case "sttpName" -> "cat.sttpName"; + case "count" -> "COUNT(src.repCode)"; + default -> null; + }; + } + + private String mapOperatBaseColumn(String field) { + if (!StringUtils.hasText(field)) { + return null; + } + return switch (field) { + case "repCode" -> "t.repCode"; + case "sttpCode" -> "t.sttpCode"; + case "stcd" -> "t.stcd"; + case "stnm" -> "t.stnm"; + case "rstcd" -> "t.rstcd"; + case "ennm" -> "t.ennm"; + case "baseId", "baseid" -> "t.baseId"; + case "hbrvcd" -> "t.hbrvcd"; + case "rvcdName" -> "t.rvcdName"; + case "addvcdName" -> "t.addvcdName"; + case "dtin" -> "t.dtin"; + case "bldsttCcode" -> "t.bldsttCcode"; + default -> null; + }; + } + + private String mapOperatGroupColumn(String field) { + if (!StringUtils.hasText(field)) { + return null; + } + return switch (field) { + case "repCode" -> "t.repCode"; + case "sttpCode" -> "t.sttpCode"; + case "pcode" -> "t.pcode"; + case "pname" -> "t.pname"; + case "sttpName" -> "t.sttpName"; + case "stcd" -> "t.stcd"; + case "ennm" -> "t.ennm"; + case "stnm" -> "t.stnm"; + case "addvcdName" -> "t.addvcdName"; + case "rvcdName" -> "t.rvcdName"; + case "baseId", "baseid" -> "t.baseId"; + case "dtin" -> "t.dtin"; + case "runState" -> "t.runState"; + case "stdState" -> "t.stdState"; + case "runSstate" -> "t.runSstate"; + case "bldsttCcode" -> "t.bldsttCcode"; + case "yr" -> "t.yr"; + default -> null; + }; + } + + private String buildOperatGroupOrderBySql(List groups) { + if (CollUtil.isEmpty(groups)) { + return ""; + } + List orderItems = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || !StringUtils.hasText(descriptor.getField())) { + continue; + } + String column = mapOperatGroupColumn(descriptor.getField()); + if (!StringUtils.hasText(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(descriptor.getDir()) || "des".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC"; + orderItems.add(column + " " + dir); + } + if (orderItems.isEmpty()) { + return ""; + } + return " ORDER BY " + String.join(", ", orderItems); + } + + private boolean containsOperatYearFilter(DataSourceRequest.FilterDescriptor filter) { + if (filter == null) { + return false; + } + if ("yr".equalsIgnoreCase(filter.getField())) { + return true; + } + if (CollUtil.isEmpty(filter.getFilters())) { + return false; + } + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + if (containsOperatYearFilter(child)) { + return true; + } + } + return false; + } + private String buildAggregateSql(String aggregate, String column, String field) { String upperField = field == null ? "" : field.toUpperCase(); return switch (aggregate.toLowerCase()) { @@ -894,15 +1891,19 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl "t.id"; + case "sttp" -> "t.sttp"; case "sttpCode" -> "t.sttpCode"; + case "runState" -> "t.runState"; case "sttpName" -> "t.sttpName"; case "stcd" -> "t.stcd"; case "stnm", "ennm" -> "t.stnm"; + case "dtinEnv" -> "t.dtinEnv"; case "baseId" -> "t.baseId"; case "baseName" -> "t.baseName"; case "hbrvcd" -> "t.hbrvcd"; case "hbrvcdName" -> "t.hbrvcdName"; case "rvcd" -> "t.rvcd"; + case "prsc" -> "t.prsc"; case "rvcdName" -> "t.rvcdName"; case "addvcdName" -> "t.addvcdName"; case "hynm" -> "t.hynm"; @@ -1356,4 +2357,311 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl null; }; } + + private List queryStbprpTableMeta(String tbCode) { + // 1. 解析参数 + List tbCodes = StrUtil.split(tbCode, ',') + .stream() + .map(StrUtil::trim) + .filter(StrUtil::isNotBlank) + .distinct() + .toList(); + + if (tbCodes.isEmpty()) { + return Collections.emptyList(); + } + + // 2. 构建 SQL 和参数 + Map paramMap = new HashMap<>(); + List placeholders = new ArrayList<>(); + for (int i = 0; i < tbCodes.size(); i++) { + String key = "tbCode" + i; + paramMap.put(key, tbCodes.get(i)); + placeholders.add("#{map." + key + "}"); + } + + String sql = "SELECT ID, TB, TB_CODE, STCD_MAPPING, TM_MAPPING " + + "FROM ST_TB_B " + + "WHERE NVL(IS_DELETED, 0) = 0 " + + "AND TB_CODE IN (" + StrUtil.join(", ", placeholders) + ") " + + "ORDER BY TB_CODE"; + + // 3. 执行查询 + List> rows = microservicDynamicSQLMapper.pageAllList(null, sql, paramMap); + + // 4. 转换结果 + List result = new ArrayList<>(); + for (Map row : rows) { + result.add(new StbprpTableMeta( + asString(row.get("ID")), + asString(row.get("TB")), + asString(row.get("TB_CODE")), + StrUtil.blankToDefault(asString(row.get("STCD_MAPPING")), "STCD"), + StrUtil.blankToDefault(asString(row.get("TM_MAPPING")), "TM") + )); + } + return result; + } + + /** + * 安全转为字符串 + */ + private String asString(Object obj) { + return obj == null ? null : obj.toString(); + } + + private String buildStbprpDataDetailSql(DataSourceRequest request, List tableMetaList) { + List selectItems = resolveStbprpSelectItems(request == null ? null : request.getSelect(), tableMetaList); + StringBuilder sql = new StringBuilder("SELECT "); + sql.append(String.join(", ", selectItems)).append(" FROM "); + for (int i = 0; i < tableMetaList.size(); i++) { + StbprpTableMeta meta = tableMetaList.get(i); + String alias = "t" + (i + 1); + if (i == 0) { + sql.append(meta.tableName()).append(" ").append(alias).append(" "); + } else { + StbprpTableMeta first = tableMetaList.getFirst(); + sql.append(" LEFT JOIN ").append(meta.tableName()).append(" ").append(alias) + .append(" ON t1.").append(first.stcdMapping()).append(" = ").append(alias).append(".").append(meta.stcdMapping()) + .append(" AND t1.").append(first.tmMapping()).append(" = ").append(alias).append(".").append(meta.tmMapping()).append(" "); + } + } + sql.append(" WHERE 1 = 1"); + return sql.toString(); + } + + private List resolveStbprpSelectItems(List selectFields, List tableMetaList) { + if (CollUtil.isEmpty(selectFields)) { + return List.of("t1.*"); + } + List items = new ArrayList<>(); + for (String field : selectFields) { + if (StrUtil.isBlank(field)) { + continue; + } + String mapped = mapStbprpField(field, tableMetaList); + if (StrUtil.isNotBlank(mapped)) { + items.add(mapped + " AS \"" + field.trim() + "\""); + } + } + if (items.isEmpty()) { + items.add("t1.*"); + } + return items; + } + + private String buildStbprpDataFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder, + List tableMetaList) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildStbprpDataLeafCondition(filter, paramMap, indexHolder, tableMetaList); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List childConditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildStbprpDataFilterCondition(child, paramMap, indexHolder, tableMetaList); + if (StrUtil.isNotBlank(childSql)) { + childConditions.add("(" + childSql + ")"); + } + } + if (childConditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, childConditions); + } + + private String buildStbprpDataLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder, + List tableMetaList) { + String column = mapStbprpField(filter.getField(), tableMetaList); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + Object value = filter.getValue(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("isempty".equals(operator)) { + return "(" + column + " IS NULL OR " + column + " = '')"; + } + if ("isnotempty".equals(operator)) { + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + } + boolean dateField = isStbprpDateField(filter); + if ("in".equals(operator) || "ni".equals(operator)) { + List values = normalizeFilterValues(value); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String key = "stbprpParam" + indexHolder[0]++; + paramMap.put(key, item); + placeholders.add(buildStbprpDataValueExpr(key, dateField, item)); + } + return column + ("ni".equals(operator) ? " NOT IN (" : " IN (") + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + String key = "stbprpParam" + indexHolder[0]++; + String expr = buildStbprpDataValueExpr(key, dateField, value); + return switch (operator) { + case "eq" -> { + paramMap.put(key, value); + yield column + " = " + expr; + } + case "neq" -> { + paramMap.put(key, value); + yield column + " <> " + expr; + } + case "contains" -> { + paramMap.put(key, "%" + value + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "doesnotcontain" -> { + paramMap.put(key, "%" + value + "%"); + yield column + " NOT LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, value + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + value); + yield column + " LIKE #{map." + key + "}"; + } + case "gt" -> { + paramMap.put(key, value); + yield column + " > " + expr; + } + case "gte" -> { + paramMap.put(key, value); + yield column + " >= " + expr; + } + case "lt" -> { + paramMap.put(key, value); + yield column + " < " + expr; + } + case "lte" -> { + paramMap.put(key, value); + yield column + " <= " + expr; + } + default -> ""; + }; + } + + private String buildStbprpDataValueExpr(String paramKey, boolean dateField, Object value) { + if (!dateField || value == null) { + return "#{map." + paramKey + "}"; + } + String text = String.valueOf(value).trim(); + if (text.length() <= 10) { + return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD')"; + } + return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD HH24:MI:SS')"; + } + + private boolean isStbprpDateField(DataSourceRequest.FilterDescriptor filter) { + if (filter == null) { + return false; + } + if ("date".equalsIgnoreCase(filter.getDataType())) { + return true; + } + String field = StrUtil.blankToDefault(filter.getField(), "").trim().toLowerCase(); + if (field.contains(".")) { + field = field.substring(field.lastIndexOf('.') + 1); + } + return "tm".equals(field) || "dt".equals(field); + } + + private String buildStbprpDataOrderBySql(List sortList, List tableMetaList) { + if (CollUtil.isEmpty(sortList)) { + return ""; + } + List orderItems = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sortList) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapStbprpField(sort.getField(), tableMetaList); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sort.getDir()) || "des".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderItems.add(column + " " + dir); + } + if (orderItems.isEmpty()) { + return ""; + } + return " ORDER BY " + String.join(", ", orderItems); + } + + private String buildStbprpDataGroupSql(String detailSql, + List groups, + List tableMetaList) { + List selectItems = new ArrayList<>(); + List groupItems = new ArrayList<>(); + List orderItems = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapStbprpField(descriptor.getField(), tableMetaList); + if (StrUtil.isBlank(column)) { + continue; + } + String upperField = descriptor.getField().trim().toUpperCase(); + selectItems.add(column + " AS " + upperField); + selectItems.add("COUNT(*) AS COUNT_" + upperField); + groupItems.add(column); + String dir = "desc".equalsIgnoreCase(descriptor.getDir()) || "des".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC"; + orderItems.add(column + " " + dir); + } + if (selectItems.isEmpty()) { + selectItems.add("t1.STCD AS STCD"); + selectItems.add("COUNT(*) AS COUNT_STCD"); + groupItems.add("t1.STCD"); + orderItems.add("t1.STCD ASC"); + } + return "SELECT " + String.join(", ", selectItems) + + " FROM (" + detailSql + ") t1 GROUP BY " + String.join(", ", groupItems) + + " ORDER BY " + String.join(", ", orderItems); + } + + private String mapStbprpField(String field, List tableMetaList) { + if (StrUtil.isBlank(field) || CollUtil.isEmpty(tableMetaList)) { + return null; + } + String normalized = field.trim(); + if (!normalized.contains(".")) { + return "t1." + normalized.toUpperCase(); + } + String[] parts = normalized.split("\\.", 2); + if (parts.length != 2) { + return null; + } + for (int i = 0; i < tableMetaList.size(); i++) { + if (StrUtil.equalsIgnoreCase(tableMetaList.get(i).tbCode(), parts[0])) { + return "t" + (i + 1) + "." + parts[1].toUpperCase(); + } + } + return null; + } + + private record StbprpTableMeta(String id, String tableName, String tbCode, String stcdMapping, String tmMapping) { + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssBHServiceImpl.java index ea8b2378..c85ffa59 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssBHServiceImpl.java @@ -10,6 +10,7 @@ import com.yfd.platform.qgc_base.domain.SdFpssBH; import com.yfd.platform.qgc_base.mapper.SdEngInfoBHMapper; import com.yfd.platform.qgc_base.mapper.SdFpssBHMapper; import com.yfd.platform.qgc_base.service.ISdFpssBHService; +import com.yfd.platform.system.service.IAdminAuthService; import com.yfd.platform.utils.SecurityUtils; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; @@ -29,6 +30,9 @@ public class SdFpssBHServiceImpl extends ServiceImpl i @Resource private SdEngInfoBHMapper sdEngInfoBHMapper; + @Resource + private IAdminAuthService adminAuthService; + @Override public Page selectPage(String stcd, String sttp, String rstcd, Integer usfl, Page page) { @@ -50,7 +54,7 @@ public class SdFpssBHServiceImpl extends ServiceImpl i Set authorizedStations = getUserAuthorizedStationCodes(); if (authorizedStations != null && !authorizedStations.isEmpty()) { wrapper.in(SdFpssBH::getRstcd, authorizedStations); - }else if (!"admin".equals(SecurityUtils.getCurrentUsername())){ + }else if (!adminAuthService.isCurrentManagedAdmin()){ return page; } @@ -68,7 +72,7 @@ public class SdFpssBHServiceImpl extends ServiceImpl i @Override public List selectForDropdown(String rstcd, String stnm, String baseId,String rvcd,String reachcd) { // 管理员直接查询,无需权限过滤 - if ("admin".equals(SecurityUtils.getCurrentUsername())) { + if (adminAuthService.isCurrentManagedAdmin()) { return queryFpssList(rstcd, stnm, baseId,rvcd,reachcd); } @@ -196,4 +200,4 @@ public class SdFpssBHServiceImpl extends ServiceImpl i .eq(SdFpssBH::getSttp, sttp); return getOne(wrapper); } -} \ No newline at end of file +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdHbrvDicServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdHbrvDicServiceImpl.java index b897970b..5d58e2fe 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdHbrvDicServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdHbrvDicServiceImpl.java @@ -15,6 +15,9 @@ import com.yfd.platform.qgc_base.mapper.SdEngInfoBHMapper; import com.yfd.platform.qgc_base.mapper.SdHbrvDicMapper; import com.yfd.platform.qgc_base.mapper.SdHydrobaseMapper; import com.yfd.platform.qgc_base.service.ISdHbrvDicService; +import com.yfd.platform.system.service.IAdminAuthService; +import com.yfd.platform.utils.CodeToNameMetadataBo; +import com.yfd.platform.utils.DictCodeToNameConverter; import com.yfd.platform.utils.QgcQueryWrapperUtil; import com.yfd.platform.utils.SecurityUtils; import jakarta.annotation.Resource; @@ -46,7 +49,39 @@ public class SdHbrvDicServiceImpl extends ServiceImpl + * 每个模块的 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("grd").modifyProperty("grdName").dictType("STATIC").dictSource("TEST").build()); +// CODE_TO_NAME_META_LIST.add(CodeToNameMetadataBo.builder().codeProperty("baseid").modifyProperty("basename").dictType("DYNAMIC").dictSource("SD_HYDROBASE").codeColumn("BASEID").nameColumn("BASENAME").filter("NVL(IS_DELETED, 0) = 0 ").build()); +// } + + @Override public Page queryPageList(Page page, String hbrvnm, String baseid) { return this.page(page, this.lambdaQuery() @@ -110,7 +145,7 @@ public class SdHbrvDicServiceImpl extends ServiceImpl authorizedStations = getUserAuthorizedStationCodes(); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdHydrobaseServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdHydrobaseServiceImpl.java index 652d5d4d..9669eba8 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdHydrobaseServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdHydrobaseServiceImpl.java @@ -13,6 +13,7 @@ import com.yfd.platform.qgc_base.entity.vo.HydrobaseWbsVo; import com.yfd.platform.qgc_base.mapper.SdEngInfoBHMapper; import com.yfd.platform.qgc_base.mapper.SdHydrobaseMapper; import com.yfd.platform.qgc_base.service.ISdHydrobaseService; +import com.yfd.platform.system.service.IAdminAuthService; import com.yfd.platform.utils.SecurityUtils; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; @@ -39,6 +40,9 @@ public class SdHydrobaseServiceImpl extends ServiceImpl queryPageList(Page page, String basename, String pbaseid) { return this.page(page, this.lambdaQuery() @@ -91,7 +95,7 @@ public class SdHydrobaseServiceImpl extends ServiceImpl(); } - }else if (!"admin".equals(SecurityUtils.getCurrentUsername())){ + }else if (!adminAuthService.isCurrentManagedAdmin()){ return new ArrayList<>(); } // else { diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdRvcdDicServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdRvcdDicServiceImpl.java index ed0b961b..ff89fa82 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdRvcdDicServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdRvcdDicServiceImpl.java @@ -11,6 +11,7 @@ import com.yfd.platform.qgc_base.mapper.SdRvcdDicMapper; import com.yfd.platform.qgc_base.service.ISdRvcdDicService; import com.yfd.platform.qgc_data.domain.SysUserDataScope; import com.yfd.platform.qgc_data.mapper.SysUserDataScopeMapper; +import com.yfd.platform.system.service.IAdminAuthService; import com.yfd.platform.utils.SecurityUtils; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; @@ -33,6 +34,9 @@ public class SdRvcdDicServiceImpl extends ServiceImpl queryPageList(Page page, String rvnm, String prvcd) { return this.page(page, this.lambdaQuery() @@ -120,7 +124,7 @@ public class SdRvcdDicServiceImpl extends ServiceImpl selectForDropdown(String rvnm, String rvcd) { List dropdownList = this.baseMapper.selectRegDropdown(rvnm, rvcd); - if("admin".equals(SecurityUtils.getCurrentUsername())){ + if(adminAuthService.isCurrentManagedAdmin()){ return dropdownList; } Set authorizedStations = getUserAuthorizedStationCodes(); @@ -149,6 +153,12 @@ public class SdRvcdDicServiceImpl extends ServiceImpl selectRvcdDropdown(String rvnm,String baseId) { + List dropdownList = this.baseMapper.selectRvcdDropdown(rvnm,baseId); + return dropdownList; + } + @Override public Set getUserAuthorizedStationCodes() { diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java index 9421dcd7..66190642 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java @@ -4,8 +4,12 @@ import com.yfd.platform.common.DataSourceLoadOptionsBase; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseMsstbprptVo; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseVmsstbprptVo; 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.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.EngEqRuleVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqVmsstbprptVo; @@ -22,6 +26,8 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.List; + @RestController @RequestMapping("/eq") @Tag(name = "电站实时数据查询") @@ -56,6 +62,12 @@ public class EngEqDataController { return ResponseResult.successData(engEqDataService.getIntervalKendoListCust(dataSourceRequest)); } + @PostMapping("/to/eq/GetKendoListCust") + @Operation(summary = "电站生态流量统计查询(电站左连接)") + public ResponseResult getToEqKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(engEqDataService.getIntervalKendoListCust(dataSourceRequest)); + } + @PostMapping("/msstbprpt/GetKendoList") @Operation(summary = "电站基础信息查询") public ResponseResult getMsstbprptList(@RequestBody DataSourceRequest dataSourceRequest) { @@ -63,6 +75,20 @@ public class EngEqDataController { return ResponseResult.successData(result); } + @PostMapping("/base/msstbprpt/GetKendoList") + @Operation(summary = "生态流量泄放设施基础信息查询") + public ResponseResult getBaseMsstbprptList(@RequestBody DataSourceRequest dataSourceRequest) { + DataSourceResult result = engEqDataService.getBaseMsstbprptList(dataSourceRequest); + return ResponseResult.successData(result); + } + + @PostMapping("/base/vmsstbprpt/GetKendoList") + @Operation(summary = "生态流量泄放设施统计查询") + public ResponseResult getBaseVmsstbprptList(@RequestBody DataSourceRequest dataSourceRequest) { + DataSourceResult result = engEqDataService.getBaseVmsstbprptList(dataSourceRequest); + return ResponseResult.successData(result); + } + @PostMapping("/interval/qgc/hour/GetKendoListCust") @Operation(summary = "生态流量达标率小时统计(二级页面)") public ResponseResult getQgcHourKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { @@ -81,6 +107,13 @@ public class EngEqDataController { return ResponseResult.successData(engEqDataService.getQgcHourVAlongKendoListCust(dataSourceRequest)); } + @PostMapping("/engalong/statistics/qgc/getEngLimit") + @Operation(summary = "沿程生态流量限值变化曲线") + public ResponseResult getQgcEngLimit(@RequestBody EngEqLimitQueryVo queryVo) { + List result = engEqDataService.getQgcEngLimit(queryVo); + return ResponseResult.successData(result); + } + @PostMapping("/fid/GetKendoListCust") @Operation(summary = "查询电站相关鱼类附件编码") public ResponseResult getFidKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseMsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseMsstbprptVo.java new file mode 100644 index 00000000..e90510ac --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseMsstbprptVo.java @@ -0,0 +1,77 @@ +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.util.Date; + +@Data +@Schema(description = "生态流量泄放设施基础信息查询") +public class EngEqBaseMsstbprptVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "设施编码") + private String stcd; + + @Schema(description = "设施名称") + private String stnm; + + @Schema(description = "设施类型编码") + private String sttpCode; + + @Schema(description = "设施类型名称") + private String sttpName; + + @Schema(description = "所属电站编码") + private String rstcd; + + @Schema(description = "所属电站名称") + private String rstcdName; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "基地名称") + private String baseName; + + @Schema(description = "基地流域编码") + private String hbrvcd; + + @Schema(description = "基地流域名称") + private String hbrvcdName; + + @Schema(description = "设施位置") + private String stlc; + + @Schema(description = "经度") + private Double lgtd; + + @Schema(description = "纬度") + private Double lttd; + + @Schema(description = "高程") + private Double elev; + + @Schema(description = "建设状态分类编码") + private Integer bldsttCode; + + @Schema(description = "建设状态分类名称") + private String bldsttCodeName; + + @Schema(description = "数据接入状态") + private Integer dtin; + + @Schema(description = "数据接入状态中文") + private String dtinName; + + @Schema(description = "数据接入时间") + private Date dtinTm; + + @Schema(description = "数据时间") + private Date tm; + + @Schema(description = "排序") + private Integer orderIndex; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseVmsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseVmsstbprptVo.java new file mode 100644 index 00000000..588c7d77 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqBaseVmsstbprptVo.java @@ -0,0 +1,64 @@ +package com.yfd.platform.qgc_eng.eq.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@Schema(description = "生态流量泄放设施统计查询") +public class EngEqBaseVmsstbprptVo extends EngEqMsstbprptVo { + + private static final long serialVersionUID = 1L; + + @Schema(description = "所属电站编码") + private String rstcd; + + @Schema(description = "所属电站名称") + private String rstcdName; + + @Schema(description = "基地排序") + private Integer baseStepSort; + + @Schema(description = "流域排序") + private Integer rvcdStepSort; + + @Schema(description = "所属电站排序") + private Integer rstcdStepSort; + + @Schema(description = "设施排序") + private Integer siteStepSort; + + @Schema(description = "死水位时保证流量") + private Double ddzgq; + + @Schema(description = "最大泄放流量") + private String flkq; + + @Schema(description = "孔口尺寸") + private String flksz; + + @Schema(description = "结构形式") + private String frntwlltyp; + + @Schema(description = "进水口底版高程") + private Double jskgc; + + @Schema(description = "出水口底版高程") + private Double outflrelev; + + @Schema(description = "基荷发电工况") + private Double jhfdgk; + + @Schema(description = "发电流量") + private Double fdll; + + @Schema(description = "生态机组额定流量") + private Double stjzysq; + + @Schema(description = "装机容量") + private Double ttpwr; + + @Schema(description = "所属建设阶段名称") + private String blprdName; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqLimitQueryVo.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqLimitQueryVo.java new file mode 100644 index 00000000..f9985176 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqLimitQueryVo.java @@ -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; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqLimitVo.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqLimitVo.java new file mode 100644 index 00000000..f0083108 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqLimitVo.java @@ -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; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqVmsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqVmsstbprptVo.java index 04a7d016..e3a444c1 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqVmsstbprptVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqVmsstbprptVo.java @@ -56,6 +56,9 @@ public class EngEqVmsstbprptVo implements Serializable { @Schema(description = "环保数据接入状态") private Integer dtinEnv; + @Schema(description = "接入状态") + private Integer dtin; + @Schema(description = "基地排序") private Integer baseStepSort; diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java index e68b0699..7f0a0bf8 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java @@ -2,11 +2,15 @@ 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.EngEqBaseMsstbprptVo; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseVmsstbprptVo; 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.EngEqDayIntervalVo; 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.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.EngEqRuleVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngQecAlongVo; @@ -16,6 +20,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.WbsbVo; +import java.util.List; + public interface EngEqDataService { DataSourceResult getKendoListCust(DataSourceRequest dataSourceRequest); @@ -28,12 +34,18 @@ public interface EngEqDataService { DataSourceResult getMsstbprptList(DataSourceRequest dataSourceRequest); + DataSourceResult getBaseMsstbprptList(DataSourceRequest dataSourceRequest); + + DataSourceResult getBaseVmsstbprptList(DataSourceRequest dataSourceRequest); + DataSourceResult getQgcHourKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getQgcDayKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getQgcHourVAlongKendoListCust(DataSourceRequest dataSourceRequest); + List getQgcEngLimit(EngEqLimitQueryVo queryVo); + DataSourceResult getFidKendoListCust(DataSourceRequest dataSourceRequest); EngEqRuleVo getEngLimit(DataSourceRequest dataSourceRequest); diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java index 4b3fb30a..d470ba6e 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java @@ -12,10 +12,14 @@ import com.yfd.platform.common.GroupingInfo; 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.EngEqBaseMsstbprptVo; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqBaseVmsstbprptVo; 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.EngEqDrtpDataVo; 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.EngEqHourIntervalVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqIntervalVo; @@ -46,6 +50,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.format.DateTimeFormatter; @Service @@ -99,6 +104,498 @@ public class EngEqDataServiceImpl implements EngEqDataService { return queryMsstbprptGroupList(dataSourceRequest, loadOptions); } + @Override + public DataSourceResult getBaseMsstbprptList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + if (CollUtil.isEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + return queryBaseMsstbprptDetailList(dataSourceRequest, loadOptions); + } + return queryBaseMsstbprptGroupList(dataSourceRequest, loadOptions); + } + + @Override + public DataSourceResult getBaseVmsstbprptList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + if (CollUtil.isEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + return queryBaseVmsstbprptDetailList(dataSourceRequest, loadOptions); + } + return queryBaseVmsstbprptGroupList(dataSourceRequest, loadOptions); + } + + private DataSourceResult queryBaseMsstbprptDetailList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildBaseMsstbprptDetailSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildBaseMsstbprptViewSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = buildBaseMsstbprptFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildBaseMsstbprptDetailOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, EngEqBaseMsstbprptVo.class); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private DataSourceResult queryBaseMsstbprptGroupList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + List groups = dataSourceRequest.getGroup(); + GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup(); + List selectItems = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapBaseMsstbprptColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + selectItems.add(column + " AS " + descriptor.getField().toUpperCase()); + selectItems.add("COUNT(*) AS COUNT_" + descriptor.getField().toUpperCase()); + if (CollUtil.isNotEmpty(descriptor.getAggregates())) { + for (DataSourceRequest.AggregateDescriptor aggregate : descriptor.getAggregates()) { + String aggregateColumn = mapBaseMsstbprptColumn(aggregate.getField()); + if (StrUtil.isBlank(aggregateColumn) || StrUtil.isBlank(aggregate.getAggregate())) { + continue; + } + selectItems.add(buildAggregateSql(aggregate.getAggregate(), aggregateColumn, aggregate.getField())); + } + } + } + if (selectItems.isEmpty()) { + selectItems.add("t.STCD AS STCD"); + selectItems.add("COUNT(*) AS COUNT_STCD"); + } + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(String.join(", ", selectItems)) + .append(" FROM (") + .append(buildBaseMsstbprptViewSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = buildBaseMsstbprptFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + + List groupByColumns = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapBaseMsstbprptColumn(descriptor.getField()); + if (StrUtil.isNotBlank(column)) { + groupByColumns.add(column); + } + } + if (!groupByColumns.isEmpty()) { + sql.append(" GROUP BY ").append(String.join(", ", groupByColumns)).append(" "); + } + sql.append(buildBaseMsstbprptGroupOrderBySql(groups)); + + List> rows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap); + DataSourceResult result = new DataSourceResult<>(); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + if (CollUtil.isNotEmpty((List) result.getData()) && ((List) result.getData()).get(0) instanceof Group) { + populateBaseMsstbprptGroupKeyNames((List) (List) result.getData()); + } + result.setTotal((long) rows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private String buildBaseMsstbprptViewSql() { + return "SELECT " + + "eq.STCD AS stcd, " + + "eq.STNM AS stnm, " + + "eq.STTP AS sttpCode, " + + "NVL(sttp.STTP_NAME, eq.STTP) AS sttpName, " + + "eq.RSTCD AS rstcd, " + + "eng.ENNM AS rstcdName, " + + "eq.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName, " + + "eq.HBRVCD AS hbrvcd, " + + "hbrv.HBRVNM AS hbrvcdName, " + + "eq.STLC AS stlc, " + + "eq.LGTD AS lgtd, " + + "eq.LTTD AS lttd, " + + "eq.ELEV AS elev, " + + "eq.BLDSTT_CODE AS bldsttCode, " + + "CASE eq.BLDSTT_CODE WHEN 0 THEN '未建/规划' WHEN 1 THEN '在建' WHEN 2 THEN '已建' ELSE NULL END AS bldsttCodeName, " + + "eq.DTIN AS dtin, " + + "CASE NVL(eq.DTIN, 0) WHEN 1 THEN '是' WHEN 0 THEN '否' ELSE NULL END AS dtinName, " + + "eq.DTIN_TM AS dtinTm, " + + "eq.TM AS tm, " + + "eq.ORDER_INDEX AS orderIndex " + + "FROM SD_EQ_B_H eq " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = eq.STTP " + + " AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = eq.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eq.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eq.HBRVCD AND hbrv.BASEID = eq.BASE_ID " + + " AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 " + + "WHERE NVL(eq.IS_DELETED, 0) = 0"; + } + + private String buildBaseMsstbprptDetailSelectSql(List selectFields) { + Map columns = baseMsstbprptFieldColumns(); + List selected = new ArrayList<>(); + if (CollUtil.isEmpty(selectFields)) { + selected.addAll(columns.values()); + } else { + for (String field : selectFields) { + String column = columns.get(field); + if (StrUtil.isNotBlank(column)) { + selected.add(column); + } + } + if (selected.isEmpty()) { + selected.addAll(columns.values()); + } + } + return String.join(", ", selected); + } + + private Map baseMsstbprptFieldColumns() { + Map columns = new LinkedHashMap<>(); + columns.put("stcd", "t.stcd AS stcd"); + columns.put("stnm", "t.stnm AS stnm"); + columns.put("sttp", "t.sttpCode AS sttp"); + columns.put("sttpCode", "t.sttpCode AS sttpCode"); + columns.put("sttpName", "t.sttpName AS sttpName"); + columns.put("rstcd", "t.rstcd AS rstcd"); + columns.put("rstcdName", "t.rstcdName AS rstcdName"); + columns.put("baseId", "t.baseId AS baseId"); + columns.put("baseName", "t.baseName AS baseName"); + columns.put("hbrvcd", "t.hbrvcd AS hbrvcd"); + columns.put("hbrvcdName", "t.hbrvcdName AS hbrvcdName"); + columns.put("stlc", "t.stlc AS stlc"); + columns.put("lgtd", "t.lgtd AS lgtd"); + columns.put("lttd", "t.lttd AS lttd"); + columns.put("elev", "t.elev AS elev"); + columns.put("bldsttCode", "t.bldsttCode AS bldsttCode"); + columns.put("bldsttCodeName", "t.bldsttCodeName AS bldsttCodeName"); + columns.put("dtin", "t.dtin AS dtin"); + columns.put("dtinName", "t.dtinName AS dtinName"); + columns.put("dtinTm", "t.dtinTm AS dtinTm"); + columns.put("tm", "t.tm AS tm"); + columns.put("orderIndex", "t.orderIndex AS orderIndex"); + return columns; + } + + private DataSourceResult queryBaseVmsstbprptDetailList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildBaseVmsstbprptDetailSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildBaseVmsstbprptViewSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = buildBaseVmsstbprptFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildBaseVmsstbprptDetailOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, EngEqBaseVmsstbprptVo.class); + fillBaseVmsstbprptDetailFields(list); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private DataSourceResult queryBaseVmsstbprptGroupList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + List groups = dataSourceRequest.getGroup(); + GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup(); + List selectItems = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapBaseVmsstbprptColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + selectItems.add(column + " AS " + descriptor.getField().toUpperCase()); + selectItems.add("COUNT(*) AS COUNT_" + descriptor.getField().toUpperCase()); + if (CollUtil.isNotEmpty(descriptor.getAggregates())) { + for (DataSourceRequest.AggregateDescriptor aggregate : descriptor.getAggregates()) { + String aggregateColumn = mapBaseVmsstbprptColumn(aggregate.getField()); + if (StrUtil.isBlank(aggregateColumn) || StrUtil.isBlank(aggregate.getAggregate())) { + continue; + } + selectItems.add(buildAggregateSql(aggregate.getAggregate(), aggregateColumn, aggregate.getField())); + } + } + } + if (selectItems.isEmpty()) { + selectItems.add("t.STCD AS STCD"); + selectItems.add("COUNT(*) AS COUNT_STCD"); + } + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(String.join(", ", selectItems)) + .append(" FROM (") + .append(buildBaseVmsstbprptViewSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = buildBaseVmsstbprptFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + + List groupByColumns = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapBaseVmsstbprptColumn(descriptor.getField()); + if (StrUtil.isNotBlank(column)) { + groupByColumns.add(column); + } + } + if (!groupByColumns.isEmpty()) { + sql.append(" GROUP BY ").append(String.join(", ", groupByColumns)).append(" "); + } + sql.append(buildBaseVmsstbprptGroupOrderBySql(groups)); + + List> rows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap); + DataSourceResult result = new DataSourceResult<>(); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal((long) rows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private String buildBaseVmsstbprptViewSql() { + return "SELECT " + + "eq.STCD AS id, " + + "eq.RECORD_USER AS recordUser, " + + "eq.RECORD_TIME AS recordTime, " + + "eq.MODIFY_TIME AS modifyTime, " + + "eq.STTP AS sttpCode, " + + "NVL(sttp.STTP_NAME, eq.STTP) AS sttpName, " + + "sttp.ID AS sttp, " + + "sttp.FULL_PATH AS sttpFullPath, " + + "sttp.TREE_LEVEL AS sttpTreeLevel, " + + "eq.STCD AS stcd, " + + "eq.STNM AS stnm, " + + "eng.ENNM AS ennm, " + + "eq.RSTCD AS rstcd, " + + "eng.ENNM AS rstcdName, " + + "eq.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName, " + + "eq.HBRVCD AS hbrvcd, " + + "hbrv.HBRVNM AS hbrvcdName, " + + "eng.RVCD AS rvcd, " + + "rv.RVNM AS rvcdName, " + + "eng.ADDVCD AS addvcd, " + + "addv.ADDVNM AS addvcdName, " + + "eng.COUNTRY AS country, " + + "eng.COUNTRY_NAME AS countryName, " + + "eng.HYCD AS hycd, " + + "eng.HYNM AS hynm, " + + "eng.TOP_HYCD AS topHycd, " + + "eng.TOP_HYNM AS topHynm, " + + "eq.BLPRD AS blprd, " + + "CASE eq.BLPRD " + + " WHEN 1001000 THEN '规划' " + + " WHEN 1002000 THEN '预可研' " + + " WHEN 1003000 THEN '环评' " + + " WHEN 1004000 THEN '可研' " + + " WHEN 1005000 THEN '在建' " + + " WHEN 1006000 THEN '招标设计' " + + " WHEN 1007000 THEN '施工详图' " + + " WHEN 1009000 THEN '建设' " + + " WHEN 1010000 THEN '蓄水阶段环保验收' " + + " WHEN 1011000 THEN '竣工' " + + " WHEN 1012000 THEN '竣工环保验收' " + + " WHEN 1013000 THEN '环境影响后评价' " + + " ELSE NULL END AS blprdName, " + + "eq.LGTD AS lgtd, " + + "eq.LTTD AS lttd, " + + "eq.ELEV AS elev, " + + "eq.ELEV AS dtmel, " + + "eq.STLC AS stlc, " + + "eq.USFL AS usfl, " + + "eq.DTIN AS dtin, " + + "CASE NVL(eq.DTIN, 0) WHEN 1 THEN '已接入' WHEN 0 THEN '未接入' ELSE NULL END AS dtinName, " + + "eq.DTIN_TM AS dtinTm, " + + "eq.INTRODUCE AS introduce, " + + "eq.LOGO AS logo, " + + "eq.INFFILE AS inffile, " + + "eng.PRSC AS prsc, " + + "eng.RUN_STATE AS runState, " + + "eng.BLDSTT AS bldstt, " + + "eng.BLDSTT_CODE AS bldsttCode, " + + "TO_CHAR(eng.BLDSTT_CODE) AS bldsttCcode, " + + "CASE NVL(eng.BLDSTT_CODE, -1) WHEN 0 THEN '未建/规划' WHEN 1 THEN '在建' WHEN 2 THEN '已建' ELSE NULL END AS bldsttCcodeName, " + + "eq.DDZGQ AS ddzgq, " + + "eq.FLKQ AS flkq, " + + "eq.FLKSZ AS flksz, " + + "eq.FLKJG AS frntwlltyp, " + + "eq.JSKDBGC AS jskgc, " + + "eq.CSKDBGC AS outflrelev, " + + "eq.JHFDGK AS jhfdgk, " + + "eq.FDLL AS fdll, " + + "eq.STJZYSQ AS stjzysq, " + + "eq.STJZZJRL AS ttpwr, " + + "NVL(hb.ORDER_INDEX, 999999) AS baseStepSort, " + + "NVL(along.ORDER_INDEX, 999999) AS rvcdStepSort, " + + "NVL(eng.ORDER_INDEX, 999999) AS rstcdStepSort, " + + "NVL(eq.ORDER_INDEX, 999999) AS siteStepSort, " + + "eq.ORDER_INDEX AS orderIndex, " + + "eq.TM AS tm " + + "FROM SD_EQ_B_H eq " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = eq.STTP " + + " AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = eq.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eq.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eq.HBRVCD AND hbrv.BASEID = eq.BASE_ID " + + " AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 " + + "LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = eng.RVCD " + + "LEFT JOIN SD_ADDVCD_DIC addv ON addv.ADDVCD = eng.ADDVCD " + + "LEFT JOIN MS_ALONG_B along ON along.RVCD = eq.HBRVCD AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 " + + "WHERE NVL(eq.IS_DELETED, 0) = 0"; + } + + private String buildBaseVmsstbprptDetailSelectSql(List selectFields) { + Map columns = baseVmsstbprptFieldColumns(); + List selected = new ArrayList<>(); + if (CollUtil.isEmpty(selectFields)) { + selected.addAll(columns.values()); + } else { + for (String field : selectFields) { + String column = columns.get(field); + if (StrUtil.isNotBlank(column)) { + selected.add(column); + } + } + if (selected.isEmpty()) { + selected.addAll(columns.values()); + } + } + return String.join(", ", selected); + } + + private Map baseVmsstbprptFieldColumns() { + Map columns = new LinkedHashMap<>(); + columns.put("id", "t.id AS id"); + columns.put("recordUser", "t.recordUser AS recordUser"); + columns.put("recordTime", "t.recordTime AS recordTime"); + columns.put("modifyTime", "t.modifyTime AS modifyTime"); + columns.put("sttp", "t.sttp AS sttp"); + columns.put("sttpCode", "t.sttpCode AS sttpCode"); + columns.put("sttpName", "t.sttpName AS sttpName"); + columns.put("sttpFullPath", "t.sttpFullPath AS sttpFullPath"); + columns.put("sttpTreeLevel", "t.sttpTreeLevel AS sttpTreeLevel"); + columns.put("stcd", "t.stcd AS stcd"); + columns.put("stnm", "t.stnm AS stnm"); + columns.put("ennm", "t.ennm AS ennm"); + columns.put("rstcd", "t.rstcd AS rstcd"); + columns.put("rstcdName", "t.rstcdName AS rstcdName"); + columns.put("baseId", "t.baseId AS baseId"); + columns.put("baseName", "t.baseName AS baseName"); + columns.put("hbrvcd", "t.hbrvcd AS hbrvcd"); + columns.put("hbrvcdName", "t.hbrvcdName AS hbrvcdName"); + columns.put("rvcd", "t.rvcd AS rvcd"); + columns.put("rvcdName", "t.rvcdName AS rvcdName"); + columns.put("addvcd", "t.addvcd AS addvcd"); + columns.put("addvcdName", "t.addvcdName AS addvcdName"); + columns.put("country", "t.country AS country"); + columns.put("countryName", "t.countryName AS countryName"); + columns.put("hycd", "t.hycd AS hycd"); + columns.put("hynm", "t.hynm AS hynm"); + columns.put("topHycd", "t.topHycd AS topHycd"); + columns.put("topHynm", "t.topHynm AS topHynm"); + columns.put("blprd", "t.blprd AS blprd"); + columns.put("blprdName", "t.blprdName AS blprdName"); + columns.put("lgtd", "t.lgtd AS lgtd"); + columns.put("lttd", "t.lttd AS lttd"); + columns.put("elev", "t.elev AS elev"); + columns.put("dtmel", "t.dtmel AS dtmel"); + columns.put("stlc", "t.stlc AS stlc"); + columns.put("usfl", "t.usfl AS usfl"); + columns.put("dtin", "t.dtin AS dtin"); + columns.put("dtinName", "t.dtinName AS dtinName"); + columns.put("dtinTm", "t.dtinTm AS dtinTm"); + columns.put("introduce", "t.introduce AS introduce"); + columns.put("logo", "t.logo AS logo"); + columns.put("inffile", "t.inffile AS inffile"); + columns.put("prsc", "t.prsc AS prsc"); + columns.put("runState", "t.runState AS runState"); + columns.put("bldstt", "t.bldstt AS bldstt"); + columns.put("bldsttCcode", "t.bldsttCcode AS bldsttCcode"); + columns.put("bldsttCcodeName", "t.bldsttCcodeName AS bldsttCcodeName"); + columns.put("ddzgq", "t.ddzgq AS ddzgq"); + columns.put("flkq", "t.flkq AS flkq"); + columns.put("flksz", "t.flksz AS flksz"); + columns.put("frntwlltyp", "t.frntwlltyp AS frntwlltyp"); + columns.put("jskgc", "t.jskgc AS jskgc"); + columns.put("outflrelev", "t.outflrelev AS outflrelev"); + columns.put("jhfdgk", "t.jhfdgk AS jhfdgk"); + columns.put("fdll", "t.fdll AS fdll"); + columns.put("stjzysq", "t.stjzysq AS stjzysq"); + columns.put("ttpwr", "t.ttpwr AS ttpwr"); + columns.put("orderIndex", "t.orderIndex AS orderIndex"); + columns.put("tm", "t.tm AS tm"); + columns.put("bldsttCode", "t.bldsttCode AS bldsttCode"); + columns.put("baseStepSort", "t.baseStepSort AS baseStepSort"); + columns.put("rvcdStepSort", "t.rvcdStepSort AS rvcdStepSort"); + columns.put("rstcdStepSort", "t.rstcdStepSort AS rstcdStepSort"); + columns.put("siteStepSort", "t.siteStepSort AS siteStepSort"); + return columns; + } + + private void fillBaseVmsstbprptDetailFields(List list) { + if (CollUtil.isEmpty(list)) { + return; + } + Map sttpNameCache = new HashMap<>(); + for (EngEqBaseVmsstbprptVo item : list) { + if (item == null) { + continue; + } + if (StrUtil.isBlank(item.getSttpName())) { + item.setSttpName(resolveSttpName(item.getSttpCode(), sttpNameCache)); + } + if (StrUtil.isBlank(item.getDtinName()) && item.getDtin() != null) { + item.setDtinName(resolveEqDtinName(String.valueOf(item.getDtin()))); + } + if (StrUtil.isBlank(item.getBldsttCcodeName()) && StrUtil.isNotBlank(item.getBldsttCcode())) { + item.setBldsttCcodeName(resolveBldsttName(item.getBldsttCcode())); + } + } + } + private DataSourceResult queryMsstbprptDetailList(DataSourceRequest dataSourceRequest, DataSourceLoadOptionsBase loadOptions) { StringBuilder sql = new StringBuilder(); @@ -380,6 +877,56 @@ public class EngEqDataServiceImpl implements EngEqDataService { return result; } + @Override + public List 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 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 stationList = microservicDynamicSQLMapper.getAllListWithResultType( + buildQgcEngLimitStationSql(baseId, rvcd), + paramMap, + EngEqLimitVo.class + ); + if (CollUtil.isEmpty(stationList)) { + return new ArrayList<>(); + } + + List> ruleRows = microservicDynamicSQLMapper.pageAllList( + null, + buildQgcEngLimitRuleSql(baseId, rvcd), + paramMap + ); + Map>> stationRuleMap = new HashMap<>(); + for (Map 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 public EngEqRuleVo getEngLimit(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -975,6 +1522,58 @@ public class EngEqDataServiceImpl implements EngEqDataService { populateHourDayGroupKeyNames(groups, baseNameCache, hbrvNameCache); } + private void populateBaseMsstbprptGroupKeyNames(List groups) { + if (CollUtil.isEmpty(groups)) { + return; + } + Map sttpNameCache = new HashMap<>(); + Map baseNameCache = new HashMap<>(); + Map hbrvNameCache = new HashMap<>(); + populateBaseMsstbprptGroupKeyNames(groups, sttpNameCache, baseNameCache, hbrvNameCache); + } + + private void populateBaseMsstbprptGroupKeyNames(List groups, + Map sttpNameCache, + Map baseNameCache, + Map hbrvNameCache) { + for (Group group : groups) { + if (group == null) { + continue; + } + if (StrUtil.isBlank(group.getKeyName())) { + group.setKeyName(resolveBaseMsstbprptGroupKeyName(group.getField(), group.getKey(), + sttpNameCache, baseNameCache, hbrvNameCache)); + } + if (CollUtil.isNotEmpty(group.getItems()) && group.getItems().get(0) instanceof Group) { + populateBaseMsstbprptGroupKeyNames((List) group.getItems(), sttpNameCache, baseNameCache, hbrvNameCache); + } + } + } + + private String resolveBaseMsstbprptGroupKeyName(Object field, + Object key, + Map sttpNameCache, + Map baseNameCache, + Map hbrvNameCache) { + if (field == null || key == null) { + return null; + } + String fieldName = String.valueOf(field); + String keyValue = String.valueOf(key); + if (StrUtil.isBlank(keyValue)) { + return null; + } + return switch (fieldName) { + case "sttpName", "stnm", "rstcdName", "baseName", "hbrvcdName", "bldsttCodeName", "dtinName" -> keyValue; + case "sttp", "sttpCode" -> StrUtil.blankToDefault(resolveSttpName(keyValue, sttpNameCache), keyValue); + case "baseId" -> StrUtil.blankToDefault(resolveBaseName(keyValue, baseNameCache), keyValue); + case "hbrvcd" -> StrUtil.blankToDefault(resolveHbrvName(keyValue, hbrvNameCache), keyValue); + case "dtin" -> resolveDtinName(keyValue); + case "bldsttCode" -> resolveBldsttName(keyValue); + default -> keyValue; + }; + } + private void populateHourDayGroupKeyNames(List groups, Map baseNameCache, Map hbrvNameCache) { @@ -1065,6 +1664,38 @@ public class EngEqDataServiceImpl implements EngEqDataService { return name == null ? null : String.valueOf(name); } + private String resolveSttpName(String sttpCode, Map cache) { + if (StrUtil.isBlank(sttpCode)) { + return null; + } + if (cache.containsKey(sttpCode)) { + return cache.get(sttpCode); + } + Map paramMap = new HashMap<>(); + paramMap.put("code", sttpCode); + List> rows = microservicDynamicSQLMapper.pageAllList(null, + "SELECT sttp.STTP_NAME AS name FROM SD_STTP_B sttp " + + "WHERE sttp.STTP_CODE = #{map.code} " + + "AND NVL(sttp.IS_DELETED, 0) = 0 " + + "AND NVL(sttp.ENABLE, 1) = 1 " + + "AND ROWNUM = 1", + paramMap); + String name = extractName(rows); + if (StrUtil.isBlank(name)) { + name = switch (sttpCode) { + case "EQ_1" -> "生态放流孔"; + case "EQ_2" -> "生态放流闸"; + case "EQ_3" -> "生态放流洞"; + case "EQ_4" -> "生态放流管"; + case "EQ_5" -> "基荷发电"; + case "EQ_6" -> "生态机组"; + default -> null; + }; + } + cache.put(sttpCode, name); + return name; + } + private String resolveDtinName(String keyValue) { return switch (keyValue) { case "1" -> "是"; @@ -1073,6 +1704,14 @@ public class EngEqDataServiceImpl implements EngEqDataService { }; } + private String resolveEqDtinName(String keyValue) { + return switch (keyValue) { + case "1" -> "已接入"; + case "0" -> "未接入"; + default -> keyValue; + }; + } + private String resolveDtinEnvName(String keyValue) { return switch (keyValue) { case "2" -> "已全部接入"; @@ -1278,6 +1917,55 @@ public class EngEqDataServiceImpl implements EngEqDataService { 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> queryEngLimitRuleDetails(String stcd, String startTime, String endTime, @@ -1338,6 +2026,100 @@ public class EngEqDataServiceImpl implements EngEqDataService { return prefix + String.join(";", parts); } + private BigDecimal resolveQgcEngLimitValue(Date queryDate, List> ruleRows) { + if (queryDate == null || CollUtil.isEmpty(ruleRows)) { + return null; + } + Date currentTm = null; + List> currentRows = new ArrayList<>(); + String monthDay = DateTimeFormatter.ofPattern("MMdd").format( + queryDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate() + ); + for (Map 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> ruleRows) { + BigDecimal defaultValue = null; + for (Map 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, Map paramMap, int[] indexHolder) { @@ -1964,7 +2746,9 @@ public class EngEqDataServiceImpl implements EngEqDataService { if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); } else { - result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + List grouped = new GroupHelper().group(rows, Arrays.asList(groupInfos)); + populateHourDayGroupKeyNames(grouped); + result.setData((List) (List) grouped); } result.setTotal(0L); result.setAggregates(new HashMap<>()); @@ -2024,6 +2808,7 @@ public class EngEqDataServiceImpl implements EngEqDataService { return "SELECT " + "eng.STCD AS stcd, " + + "eng.RGCP AS rgcp, " + "eng.ENNM AS stnm, " + "eng.ENNM AS ennm, " + "'ENG' AS sttp, " + @@ -2237,6 +3022,7 @@ public class EngEqDataServiceImpl implements EngEqDataService { columns.put("dtmel", "t.dtmel AS dtmel"); columns.put("dtin", "t.dtin AS dtin"); columns.put("dtinEnv", "t.dtinEnv AS dtinEnv"); + columns.put("rgcp", "t.rgcp AS rgcp"); columns.put("prsc", "t.prsc AS prsc"); columns.put("bldsttCcode", "t.bldsttCcode AS bldsttCcode"); columns.put("qi", "t.qi AS qi"); @@ -2438,6 +3224,79 @@ public class EngEqDataServiceImpl implements EngEqDataService { return result; } + private String buildBaseVmsstbprptFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + String column = mapBaseVmsstbprptColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + return buildGenericCondition(column, filter, paramMap, indexHolder, false); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildBaseVmsstbprptFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildBaseVmsstbprptDetailOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY NVL(t.baseStepSort, 999999) ASC, NVL(t.rvcdStepSort, 999999) ASC, " + + "NVL(t.rstcdStepSort, 999999) ASC, NVL(t.siteStepSort, 999999) ASC, t.stcd ASC"; + } + List orders = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sortList) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapBaseVmsstbprptColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sort.getDir()) || "des".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orders.add(column + " " + dir); + } + if (orders.isEmpty()) { + return " ORDER BY NVL(t.baseStepSort, 999999) ASC, NVL(t.rvcdStepSort, 999999) ASC, " + + "NVL(t.rstcdStepSort, 999999) ASC, NVL(t.siteStepSort, 999999) ASC, t.stcd ASC"; + } + return " ORDER BY " + String.join(", ", orders); + } + + private String buildBaseVmsstbprptGroupOrderBySql(List groups) { + if (CollUtil.isEmpty(groups)) { + return ""; + } + List orders = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapBaseVmsstbprptColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(descriptor.getDir()) || "des".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC"; + orders.add(column + " " + dir); + } + return orders.isEmpty() ? "" : " ORDER BY " + String.join(", ", orders); + } + private DataSourceResult queryWbsbDetailList(DataSourceRequest dataSourceRequest, DataSourceLoadOptionsBase loadOptions) { StringBuilder sql = new StringBuilder(); @@ -2477,9 +3336,11 @@ public class EngEqDataServiceImpl implements EngEqDataService { "eng.RVCD AS rvcd, " + "rv.RVNM AS rvcdName, " + "eng.PRSC AS prsc, " + + "eng.RUN_STATE AS runState, " + "eng.BLDSTT AS bldstt, " + "eng.BLDSTT_CODE AS bldsttCcode, " + "eng.DTIN_ENV AS dtinEnv, " + + "eng.DTIN AS dtin, " + "NVL(hb.ORDER_INDEX, 999999) AS baseStepSort, " + "NVL(along.ORDER_INDEX, 999999) AS rvcdStepSort, " + "NVL(eng.ORDER_INDEX, 999999) AS rstcdStepSort, " + @@ -2528,6 +3389,8 @@ public class EngEqDataServiceImpl implements EngEqDataService { columns.put("prsc", "t.prsc AS prsc"); columns.put("bldstt", "t.bldstt AS bldstt"); columns.put("bldsttCcode", "t.bldsttCcode AS bldsttCcode"); + columns.put("dtin", "t.dtin AS dtin"); + columns.put("runState", "t.runState AS runState"); columns.put("dtinEnv", "t.dtinEnv AS dtinEnv"); columns.put("baseStepSort", "t.baseStepSort AS baseStepSort"); columns.put("rvcdStepSort", "t.rvcdStepSort AS rvcdStepSort"); @@ -2604,6 +3467,74 @@ public class EngEqDataServiceImpl implements EngEqDataService { return orders.isEmpty() ? "" : " ORDER BY " + String.join(", ", orders); } + private String buildBaseMsstbprptFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + String column = mapBaseMsstbprptColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + return buildGenericCondition(column, filter, paramMap, indexHolder, isBaseMsstbprptDateField(filter.getField())); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildBaseMsstbprptFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildBaseMsstbprptDetailOrderBySql(List sortList) { + List orders = new ArrayList<>(); + if (CollUtil.isNotEmpty(sortList)) { + for (DataSourceRequest.SortDescriptor sort : sortList) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapBaseMsstbprptColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + orders.add(column + ("desc".equalsIgnoreCase(sort.getDir()) ? " DESC" : " ASC")); + } + } + if (orders.isEmpty()) { + orders.add("NVL(t.orderIndex, 999999) ASC"); + orders.add("t.stnm ASC"); + } + return " ORDER BY " + String.join(", ", orders); + } + + private String buildBaseMsstbprptGroupOrderBySql(List groups) { + List orders = new ArrayList<>(); + if (CollUtil.isNotEmpty(groups)) { + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapBaseMsstbprptColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + orders.add(column + ("desc".equalsIgnoreCase(descriptor.getDir()) ? " DESC" : " ASC")); + } + } + return orders.isEmpty() ? "" : " ORDER BY " + String.join(", ", orders); + } + private String buildVmsstbprptFilterCondition(DataSourceRequest.FilterDescriptor filter, Map paramMap, int[] indexHolder) { @@ -3996,6 +4927,10 @@ public class EngEqDataServiceImpl implements EngEqDataService { return "tm".equalsIgnoreCase(field); } + private boolean isBaseMsstbprptDateField(String field) { + return "tm".equalsIgnoreCase(field) || "dtinTm".equalsIgnoreCase(field); + } + private boolean isEqDayDateField(String field) { return "dt".equalsIgnoreCase(field) || "tm".equalsIgnoreCase(field); } @@ -4298,6 +5233,20 @@ public class EngEqDataServiceImpl implements EngEqDataService { 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) { if (value == null) { return null; @@ -4443,6 +5392,7 @@ public class EngEqDataServiceImpl implements EngEqDataService { } return switch (field) { case "stcd" -> "t.stcd"; + case "rgcpCode" -> "t.rgcp"; case "stnm", "ennm" -> "t.ennm"; case "sttp", "sttpCode" -> "t.sttpCode"; case "baseId" -> "t.baseId"; @@ -4502,6 +5452,8 @@ public class EngEqDataServiceImpl implements EngEqDataService { case "bldstt" -> "t.bldstt"; case "bldsttCcode" -> "t.bldsttCcode"; case "dtinEnv" -> "t.dtinEnv"; + case "DTIN" -> "t.dtin"; + case "runState" -> "t.runState"; case "baseStepSort" -> "NVL(t.baseStepSort, 999999)"; case "rvcdStepSort" -> "NVL(t.rvcdStepSort, 999999)"; case "rstcdStepSort" -> "NVL(t.rstcdStepSort, 999999)"; @@ -4562,6 +5514,61 @@ public class EngEqDataServiceImpl implements EngEqDataService { }; } + private String mapBaseMsstbprptColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd" -> "t.stcd"; + case "stnm" -> "t.stnm"; + case "sttp", "sttpCode" -> "t.sttpCode"; + case "sttpName" -> "t.sttpName"; + case "rstcd" -> "t.rstcd"; + case "rstcdName" -> "t.rstcdName"; + case "baseId" -> "t.baseId"; + case "baseName" -> "t.baseName"; + case "hbrvcd" -> "t.hbrvcd"; + case "hbrvcdName" -> "t.hbrvcdName"; + case "stlc" -> "t.stlc"; + case "lgtd" -> "t.lgtd"; + case "lttd" -> "t.lttd"; + case "elev" -> "t.elev"; + case "bldsttCode" -> "t.bldsttCode"; + case "bldsttCodeName" -> "t.bldsttCodeName"; + case "dtin" -> "t.dtin"; + case "dtinName" -> "t.dtinName"; + case "dtinTm" -> "t.dtinTm"; + case "tm" -> "t.tm"; + case "orderIndex" -> "NVL(t.orderIndex, 999999)"; + default -> null; + }; + } + + private String mapBaseVmsstbprptColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "sttpCode" -> "t.sttpCode"; + case "sttpName" -> "t.sttpName"; + case "stcd" -> "t.stcd"; + case "stnm" -> "t.stnm"; + case "rstcd" -> "t.rstcd"; + case "rstcdName" -> "t.rstcdName"; + case "baseId" -> "t.baseId"; + case "baseName" -> "t.baseName"; + case "hbrvcd" -> "t.hbrvcd"; + case "hbrvcdName" -> "t.hbrvcdName"; + case "dtin" -> "t.dtin"; + case "bldsttCode" -> "t.bldsttCode"; + case "baseStepSort" -> "NVL(t.baseStepSort, 999999)"; + case "rvcdStepSort" -> "NVL(t.rvcdStepSort, 999999)"; + case "rstcdStepSort" -> "NVL(t.rstcdStepSort, 999999)"; + case "siteStepSort" -> "NVL(t.siteStepSort, 999999)"; + default -> null; + }; + } + private String mapWbsbColumn(String field) { if (StrUtil.isBlank(field)) { return null; @@ -4739,7 +5746,8 @@ public class EngEqDataServiceImpl implements EngEqDataService { } return switch (field) { case "id" -> "t.id"; - case "stcd" -> "t.stcd"; + case "rstcd" -> "t.stcd"; +// case "rstcd" -> "t.rstcd"; case "stnm", "ennm" -> "t.ennm"; case "baseId" -> "t.baseId"; case "baseName" -> "t.baseName"; diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbBsmfrController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbBsmfrController.java deleted file mode 100644 index 4eb347f0..00000000 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbBsmfrController.java +++ /dev/null @@ -1,35 +0,0 @@ -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/bsmfr") -@Tag(name = "亲鱼选配与培育-亲鱼信息") -@Validated -public class FbBsmfrController { - - @Resource - private FbStationService fbStationService; - - @PostMapping("/qgc/GetKendoListCust") - @Operation(summary = "(全过程)增殖站二级页面: 亲鱼选配与培育->亲鱼信息") - public ResponseResult getQgcKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { - return ResponseResult.successData(fbStationService.getQgcBsmfRKendoListCust(dataSourceRequest)); - } - - @PostMapping("/fish/GetKendoListCust") - @Operation(summary = "(全过程)增殖站二级页面: 过程图-亲鱼") - public ResponseResult getFishKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { - return ResponseResult.successData(fbStationService.getBsmfRFishKendoListCust(dataSourceRequest)); - } -} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbFbrdmrController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbFbrdmrController.java deleted file mode 100644 index ea102a41..00000000 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbFbrdmrController.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.yfd.platform.qgc_env.fb.controller; - -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.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/fb/fbrdmr") -@Tag(name = "鱼类增殖站年度鱼类标记数据") -@Validated -public class FbFbrdmrController { - - @Resource - private FbStationService fbStationService; - - @GetMapping("/getFbRelatedYrByStcd") - @Operation(summary = "根据增殖站编码查询相关业务年份") - public ResponseResult getFbRelatedYrByStcd(@Parameter(description = "增殖站编码") - @RequestParam("stcd") String stcd) { - return ResponseResult.successData(fbStationService.getFbRelatedYrByStcd(stcd)); - } -} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbMsfbrdmController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbMsfbrdmController.java deleted file mode 100644 index 0606b62e..00000000 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbMsfbrdmController.java +++ /dev/null @@ -1,29 +0,0 @@ -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/msfbrdm") -@Tag(name = "鱼类增殖站增殖情况") -@Validated -public class FbMsfbrdmController { - - @Resource - private FbStationService fbStationService; - - @PostMapping("/fbFlData/GetKendoListCust") - @Operation(summary = "增殖站增殖情况(app)") - public ResponseResult getFbFlData(@RequestBody DataSourceRequest dataSourceRequest) { - return ResponseResult.successData(fbStationService.getFbFlDataKendoListCust(dataSourceRequest)); - } -} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java index 169d8762..9d05bd9f 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/controller/FbStationController.java @@ -16,47 +16,120 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController -@RequestMapping("/fb/station") -@Tag(name = "鱼类增殖站概况") +@RequestMapping("/fb") +@Tag(name = "鱼类增殖站模块") @Validated public class FbStationController { @Resource private FbStationService fbStationService; - @PostMapping("/qgcoverview/getOverviewSecond") + @PostMapping("/station/qgcoverview/getOverviewSecond") @Operation(summary = "全流域增殖站概况二级页面") public ResponseResult getQgcOverviewSecond(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(fbStationService.getQgcOverviewSecond(dataSourceRequest)); } - @PostMapping("/overview/getOverviewSecond") + @PostMapping("/station/overview/getOverviewSecond") @Operation(summary = "增殖站概况二级页面") public ResponseResult getOverviewSecond(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(fbStationService.getOverviewSecond(dataSourceRequest)); } - @PostMapping("/overview/GetKendoListCust") + @PostMapping("/station/overview/GetKendoListCust") @Operation(summary = "全流域增殖站概况") public ResponseResult getOverviewKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(fbStationService.getOverviewKendoListCust(dataSourceRequest)); } - @PostMapping("/qgc/getFbStaticsData") + @PostMapping("/station/qgc/getFbStaticsData") @Operation(summary = "增殖站放流数据统计") public ResponseResult getQgcFbStaticsData(@RequestBody DataSourceRequest dataSourceRequest) { return ResponseResult.successData(fbStationService.getQgcFbStaticsData(dataSourceRequest)); } - @GetMapping("/msstbprpt/getStInfoByStcd") + @GetMapping("/station/msstbprpt/getStInfoByStcd") @Operation(summary = "增殖站单站基础信息") public ResponseResult getStInfoByStcd(@Parameter(description = "站点编码") @RequestParam("stcd") String stcd) { return ResponseResult.successData(fbStationService.getStInfoByStcd(stcd)); } - @GetMapping("/rpimnr/qgc/year/GetYearRpStatistics") + @GetMapping("/station/rpimnr/qgc/year/GetYearRpStatistics") @Operation(summary = "全过程放流统计总数,根据基地流域分组") public ResponseResult getYearRpStatistics(@Parameter(description = "年份") @RequestParam("year") String year) { return ResponseResult.successData(fbStationService.getYearRpStatistics(year)); } + + @PostMapping("/bsmfr/qgc/GetKendoListCust") + @Operation(summary = "(全过程)增殖站二级页面: 亲鱼选配与培育->亲鱼信息") + public ResponseResult getBsmfrQgcKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getQgcBsmfRKendoListCust(dataSourceRequest)); + } + + @PostMapping("/bsmfr/fish/GetKendoListCust") + @Operation(summary = "(全过程)增殖站二级页面: 过程图-亲鱼") + public ResponseResult getBsmfrFishKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getBsmfRFishKendoListCust(dataSourceRequest)); + } + + @GetMapping("/fbrdmr/getFbRelatedYrByStcd") + @Operation(summary = "根据增殖站编码查询相关业务年份") + public ResponseResult getFbRelatedYrByStcd(@Parameter(description = "增殖站编码") + @RequestParam("stcd") String stcd) { + return ResponseResult.successData(fbStationService.getFbRelatedYrByStcd(stcd)); + } + + @PostMapping("/msfbrdm/fbFlData/GetKendoListCust") + @Operation(summary = "增殖站增殖情况(app)") + public ResponseResult getFbFlData(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getFbFlDataKendoListCust(dataSourceRequest)); + } + + @PostMapping("/fishCount/GetKendoListCust") + @Operation(summary = "增殖站鱼数量完成情况统计") + public ResponseResult getFishCountKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getFishCountKendoListCust(dataSourceRequest)); + } + + @PostMapping("/fishrun/qgc/GetKendoListCust") + @Operation(summary = "全过程鱼类放鱼数据") + public ResponseResult getFishRunQgcKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getFishRunQgcKendoListCust(dataSourceRequest)); + } + + @PostMapping("/fishType/GetKendoListCust") + @Operation(summary = "增殖站鱼种完成情况统计") + public ResponseResult getFishTypeKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getFishTypeKendoListCust(dataSourceRequest)); + } + + @PostMapping("/fishType/getStcdList") + @Operation(summary = "增殖放流完成情况获取有数据的测站下拉") + public ResponseResult getFishTypeStcdList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getFishTypeStcdList(dataSourceRequest)); + } + + @PostMapping("/msfbrdm/GetKendoListCust") + @Operation(summary = "鱼类增殖站运行情况统计列表") + public ResponseResult getMsfbrdmKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getMsfbrdmKendoListCust(dataSourceRequest)); + } + + @PostMapping("/msfbrdm/qgc/GetKendoListCust") + @Operation(summary = "(全过程)增殖站二级页面: 增殖放流情况") + public ResponseResult getMsfbrdmQgcKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getQgcMsfbrdmKendoListCust(dataSourceRequest)); + } + + @PostMapping("/msstbprpt/GetKendoList") + @Operation(summary = "鱼类增殖站基础信息列表") + public ResponseResult getMsstbprptKendoList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getMsstbprptList(dataSourceRequest)); + } + + @PostMapping("/base/researchb/GetKendoList") + @Operation(summary = "鱼类增殖站科研情况列表") + public ResponseResult getResearchKendoList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fbStationService.getResearchKendoList(dataSourceRequest)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishCountFinishVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishCountFinishVo.java new file mode 100644 index 00000000..4a7a4419 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishCountFinishVo.java @@ -0,0 +1,15 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class FbFishCountFinishVo { + + private String stcd; + + private BigDecimal finished; + + private BigDecimal unfinished; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishRunQgcVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishRunQgcVo.java new file mode 100644 index 00000000..8c844de7 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishRunQgcVo.java @@ -0,0 +1,37 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import lombok.Data; + +@Data +public class FbFishRunQgcVo { + + private String stcd; + + private String stnm; + + private String ftp; + + private String ftpName; + + private String baseId; + + private String baseName; + + private String flyr; + + private Long fcnt; + + private Long totalFcnt; + + private String fid; + + private String release; + + private Integer baseStepSort; + + private Integer siteStepSort; + + private Integer rvcdStepSort; + + private Integer rstcdStepSort; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishTypeFinishVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishTypeFinishVo.java new file mode 100644 index 00000000..d930219e --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishTypeFinishVo.java @@ -0,0 +1,13 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import lombok.Data; + +@Data +public class FbFishTypeFinishVo { + + private String stcd; + + private Integer finished; + + private Integer unfinished; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishTypeStcdVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishTypeStcdVo.java new file mode 100644 index 00000000..4ecc11f1 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbFishTypeStcdVo.java @@ -0,0 +1,19 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class FbFishTypeStcdVo { + + private String stcd; + + private String stnm; + + private BigDecimal lgtd; + + private BigDecimal lttd; + + private String baseId; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbMsfbrdmQgcVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbMsfbrdmQgcVo.java new file mode 100644 index 00000000..e93d3e87 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbMsfbrdmQgcVo.java @@ -0,0 +1,47 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import lombok.Data; + +import java.util.List; + +@Data +public class FbMsfbrdmQgcVo { + + private String stcd; + + private String stnm; + + private String baseId; + + private String baseName; + + private String rstcd; + + private String ennm; + + private Integer bldstt; + + private Integer hydrodtin; + + private Integer runState; + + private String runStateName; + + private String ftp; + + private String ftpName; + + private Long fcntjh; + + private Long fcntjc; + + private String flyr; + + private String fsz; + + private String fwet; + + private String fid; + + private List directionVoList; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbReleaseDirectionVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbReleaseDirectionVo.java new file mode 100644 index 00000000..c8137b2c --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbReleaseDirectionVo.java @@ -0,0 +1,21 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import lombok.Data; +import lombok.experimental.Accessors; + +@Data +@Accessors(chain = true) +public class FbReleaseDirectionVo { + + private String flstcd; + + private String flstnm; + + private Long flfnct; + + private String flyr; + + private String ftp; + + private String stcd; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbResearchVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbResearchVo.java new file mode 100644 index 00000000..6af5dbcd --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fb/entity/vo/FbResearchVo.java @@ -0,0 +1,49 @@ +package com.yfd.platform.qgc_env.fb.entity.vo; + +import lombok.Data; + +import java.util.Date; + +@Data +public class FbResearchVo { + + private String id; + + private String stcd; + + private Date dt; + + private String ftp; + + private String ftpName; + + private String wco; + + private String jd; + + private String fid; + + private String recordUser; + + private Date recordTime; + + private String modifyUser; + + private Date modifyTime; + + private Integer isDeleted; + + private String deleteUser; + + private Date deleteTime; + + private String rstcd; + + private String ennm; + + private String baseId; + + private String baseName; + + private String hbrvcd; +} 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 a768fd7e..1bada486 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 @@ -5,13 +5,20 @@ import com.yfd.platform.common.DataSourceResult; 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.FbFlDataVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbFishCountFinishVo; +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.FbRelatedYrVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbMsfbrdmQgcVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbResearchVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbStInfoResultVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbStationStaticsDataVo; import com.yfd.platform.qgc_env.fb.entity.vo.YearRpStatisticsVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbStationOverviewSecondVo; import java.util.List; +import java.util.Map; public interface FbStationService { @@ -19,12 +26,28 @@ public interface FbStationService { DataSourceResult getOverviewKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult> getMsstbprptList(DataSourceRequest dataSourceRequest); + DataSourceResult getFbFlDataKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getFishCountKendoListCust(DataSourceRequest dataSourceRequest); + + DataSourceResult getFishRunQgcKendoListCust(DataSourceRequest dataSourceRequest); + + DataSourceResult getFishTypeKendoListCust(DataSourceRequest dataSourceRequest); + + DataSourceResult getFishTypeStcdList(DataSourceRequest dataSourceRequest); + + DataSourceResult getMsfbrdmKendoListCust(DataSourceRequest dataSourceRequest); + + DataSourceResult getQgcMsfbrdmKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getQgcBsmfRKendoListCust(DataSourceRequest dataSourceRequest); DataSourceResult getBsmfRFishKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getResearchKendoList(DataSourceRequest dataSourceRequest); + DataSourceResult getFbRelatedYrByStcd(String stcd); FbStInfoResultVo getStInfoByStcd(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 6a3965a9..a3e50842 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 @@ -15,9 +15,16 @@ 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; import com.yfd.platform.qgc_env.fb.entity.vo.FbBsmfRFishTableVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbFishCountFinishVo; +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.FbFlDataVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbMsfbrdmQgcVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbRelatedYrVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbReleaseDirectionVo; +import com.yfd.platform.qgc_env.fb.entity.vo.FbResearchVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbStBaseInfoVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbStInfoResultVo; import com.yfd.platform.qgc_env.fb.entity.vo.FbStationOverviewSecondVo; @@ -80,6 +87,226 @@ public class FbStationServiceImpl implements FbStationService { return queryFbFlDataDetailList(dataSourceRequest, loadOptions); } + @Override + public DataSourceResult getFishCountKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String rstcdFilter = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); + String stcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd"); + String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + + Map paramMap = new HashMap<>(); + String sql = buildFishCountFinishSql( + stcd, + parseFishTypeFilterValues(rstcdFilter), + parseFishTypeDate(startTime), + parseFishTypeDate(endTime), + paramMap + ) + buildFishCountOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort()); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql, + paramMap, + FbFishCountFinishVo.class + ); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getFishRunQgcKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String flyrFilter = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "flyr"); + String rstcdFilter = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); + Date[] flyrRange = parseFishRunFlyrRange(flyrFilter); + + Map paramMap = new HashMap<>(); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT r.stcd AS stcd, ") + .append("r.stnm AS stnm, ") + .append("r.baseId AS baseId, ") + .append("r.baseName AS baseName, ") + .append("r.baseStepSort AS baseStepSort, ") + .append("r.siteStepSort AS siteStepSort, ") + .append("r.rvcdStepSort AS rvcdStepSort, ") +// .append("r.rstcdStepSort AS rstcdStepSort, ") + .append("r.flyr AS flyr, ") + .append("r.ftp AS ftp, ") + .append("r.ftpName AS ftpName, ") + .append("r.fcnt AS fcnt, ") + .append("r.totalFcnt AS totalFcnt, ") + .append("r.fid AS fid, ") + .append("r.release AS release ") + .append("FROM (") + .append(buildFishRunQgcBaseSql( + parseFishTypeFilterValues(rstcdFilter), + flyrRange[0], + flyrRange[1], + paramMap + )) + .append(") r WHERE 1 = 1 "); + + String filterSql = buildFishRunQgcFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildFishRunQgcOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + FbFishRunQgcVo.class + ); + normalizeFishRunQgcRows(list); + appendFishRunMissingYears(list, flyrRange[0], flyrRange[1], page); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getFishTypeKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String rstcdFilter = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); + String stcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd"); + String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + + Map paramMap = new HashMap<>(); + String sql = buildFishTypeFinishSql( + stcd, + parseFishTypeFilterValues(rstcdFilter), + parseFishTypeDate(startTime), + parseFishTypeDate(endTime), + paramMap + ) + buildFishTypeOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort()); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql, + paramMap, + FbFishTypeFinishVo.class + ); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getFishTypeStcdList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String baseId = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId"); + String sttpCode = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "sttpCode"); + + Map paramMap = new HashMap<>(); + String sql = buildFishTypeStcdListSql(baseId, sttpCode, paramMap); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + null, + sql, + paramMap, + FbFishTypeStcdVo.class + ); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult> getMsstbprptList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Map paramMap = new HashMap<>(); + String filterSql = buildFbMsstbprptFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + + if (CollUtil.isNotEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + StringBuilder groupedBaseSql = new StringBuilder("SELECT * FROM (") + .append(buildFbMsstbprptBaseSql()) + .append(") t WHERE 1 = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + groupedBaseSql.append(" AND ").append(filterSql).append(" "); + } + String groupedSql = buildFbMsstbprptGroupSql(groupedBaseSql.toString(), dataSourceRequest.getGroup()); + List> rows = microservicDynamicSQLMapper.pageAllList(null, groupedSql, paramMap); + + DataSourceResult> result = new DataSourceResult<>(); + GroupingInfo[] groupInfos = loadOptions == null ? null : loadOptions.getGroup(); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List>) (List) new GroupHelper().faltGroup( + rows, + groupInfos == null ? Collections.emptyList() : Arrays.asList(groupInfos) + )); + } else { + result.setData((List>) (List) new GroupHelper().group( + rows, + groupInfos == null ? Collections.emptyList() : Arrays.asList(groupInfos) + )); + } + result.setTotal(rows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + List selectedFields = resolveFbMsstbprptSelectFields(dataSourceRequest == null ? null : dataSourceRequest.getSelect()); + StringBuilder sql = new StringBuilder("SELECT ") + .append(buildFbMsstbprptDetailSelectSql(selectedFields)) + .append(" FROM (") + .append(buildFbMsstbprptBaseSql()) + .append(") t WHERE 1 = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildFbMsstbprptOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List> rows = microservicDynamicSQLMapper.pageAllList(page, sql.toString(), paramMap); + + DataSourceResult> result = new DataSourceResult<>(); + result.setData(normalizeFbMsstbprptRows(rows, selectedFields)); + result.setTotal(page != null ? page.getTotal() : rows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getMsfbrdmKendoListCust(DataSourceRequest dataSourceRequest) { + return getQgcMsfbrdmKendoListCust(dataSourceRequest); + } + + @Override + public DataSourceResult getQgcMsfbrdmKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + GroupingInfo[] groups = loadOptions == null ? null : loadOptions.getGroup(); + if (groups != null && groups.length > 0) { + return queryQgcMsfbrdmGroupList(dataSourceRequest, loadOptions, groups); + } + return queryQgcMsfbrdmDetailList(dataSourceRequest, loadOptions); + } + @Override public DataSourceResult getQgcBsmfRKendoListCust(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -118,6 +345,16 @@ public class FbStationServiceImpl implements FbStationService { return result; } + @Override + public DataSourceResult getResearchKendoList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + GroupingInfo[] groups = loadOptions == null ? null : loadOptions.getGroup(); + if (groups != null && groups.length > 0) { + return queryResearchGroupList(dataSourceRequest, groups); + } + return queryResearchDetailList(dataSourceRequest, loadOptions); + } + @Override public DataSourceResult getFbRelatedYrByStcd(String stcd) { DataSourceResult result = new DataSourceResult<>(); @@ -321,6 +558,949 @@ public class FbStationServiceImpl implements FbStationService { return result; } + private String buildFbMsstbprptBaseSql() { + return "SELECT " + + "fb.STCD AS stcd, " + + "fb.STCD AS id, " + + "fb.STNM AS stnm, " + + "fb.STTP AS sttp, " + + "fb.STTP AS sttpCode, " + + "sttp.STTP_NAME AS sttpName, " + + "sttp.FULL_PATH AS sttpFullPath, " + + "sttp.TREE_LEVEL AS sttpTreeLevel, " + + "fb.LGTD AS lgtd, " + + "fb.LTTD AS lttd, " + + "fb.ELEV AS dtmel, " + + "fb.STLC AS stlc, " + + "fb.USFL AS usfl, " + + "fb.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "fb.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName, " + + "fb.HBRVCD AS hbrvcd, " + + "hbrv.HBRVNM AS hbrvcdName, " + + "eng.RVCD AS rvcd, " + + "rv.RVNM AS rvcdName, " + + "eng.ADDVCD AS addvcd, " + + "addv.ADDVNM AS addvcdName, " + + "eng.COUNTRY AS country, " + + "country.COUNTRY_NAME AS countryName, " + + "eng.HYCD AS hycd, " + + "CAST(NULL AS VARCHAR2(200)) AS hynm, " + + "fb.STDSDT AS stdsdt, " + + "fb.PSTSTDT AS pststdt, " + + "fb.PESSTDT AS pesstdt, " + + "fb.SWDT AS ststdt, " + + "fb.JCDT AS jcdt, " + + "fb.WDDT AS stwddt, " + + "fb.INTRODUCE AS introduce, " + + "fb.INTRODUCE AS precis, " + + "fb.LOGO AS logo, " + + "fb.INFFILE AS inffile, " + + "fb.DTIN AS dtin, " + + "CASE NVL(fb.DTIN, 0) WHEN 1 THEN '是' WHEN 0 THEN '否' ELSE NULL END AS dtinName, " + + "fb.DTIN_TM AS dtinTm, " + + "fb.BLDSTT_CODE AS bldsttCode, " + + "CASE fb.BLDSTT_CODE WHEN 0 THEN '0' WHEN 1 THEN '1' WHEN 2 THEN '2' ELSE NULL END AS bldsttCcode, " + + "CASE fb.BLDSTT_CODE WHEN 0 THEN '未建/规划' WHEN 1 THEN '在建' WHEN 2 THEN '已建' ELSE NULL END AS bldsttCcodeName, " + + "fb.INV AS inv, " + + "fb.INVINMN AS invinmn, " + + "fb.ZZFLAR AS zzflar, " + + "fb.ZZFLGY AS zzflgy, " + + "fb.ZZFLYZMS AS zzflyzms, " + + "fb.ZZFLBJFS AS zzflbjfs, " + + "fb.ZZFLDX AS zzfldx, " + + "fb.ZZFLCNT AS zzflcnt, " + + "fb.ZZFLFLLC AS zzflfllc, " + + "fb.ZZFLTM AS zzfltm, " + + "fb.ZZFLRW AS zzflrw, " + + "fb.DSUN AS dsun, " + + "fb.JBTXCS AS jbtxcs, " + + "fb.DTFRQCY AS dtfrqcy, " + + "fb.REMARK AS remark, " + + "fb.VLSR AS vlsr, " + + "fb.VLSR_TM AS vlsrTm, " + + "fb.ORDER_INDEX AS orderIndex " + + "FROM SD_FBRD_B_H fb " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = fb.STTP AND NVL(sttp.ENABLE, 1) = 1 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fb.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = fb.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = fb.HBRVCD AND hbrv.BASEID = fb.BASE_ID " + + " AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 " + + "LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = eng.RVCD " + + "LEFT JOIN SD_ADDVCD_DIC addv ON addv.ADDVCD = eng.ADDVCD " + + "LEFT JOIN SD_COUNTRY_B country ON country.COUNTRY_ID = eng.COUNTRY AND NVL(country.ENABLED, 1) = 1 "; + } + + private List resolveFbMsstbprptSelectFields(List select) { + List fields = CollUtil.isEmpty(select) + ? new ArrayList<>(List.of( + "stcd", "stnm", "sttpCode", "sttpName", "lgtd", "lttd", "stlc", "rstcd", "ennm", + "baseId", "baseName", "hbrvcd", "hbrvcdName", "introduce", "logo", "precis", + "dtin", "dtinName", "dtinTm", "bldsttCcode", "bldsttCcodeName", "inv", + "zzflar", "zzflgy", "zzflyzms", "zzflbjfs", "zzfldx", "zzflcnt", "zzflfllc", + "zzfltm", "zzflrw", "dsun", "jbtxcs", "dtfrqcy", "remark", "vlsr", "vlsrTm" + )) + : new ArrayList<>(select); + LinkedHashSet uniqueFields = new LinkedHashSet<>(); + for (String field : fields) { + if (StrUtil.isNotBlank(field)) { + uniqueFields.add(field.trim()); + } + } + if (uniqueFields.isEmpty()) { + uniqueFields.add("stcd"); + } + return new ArrayList<>(uniqueFields); + } + + private String buildFbMsstbprptDetailSelectSql(List selectFields) { + List selectParts = new ArrayList<>(); + for (String field : selectFields) { + String column = mapFbMsstbprptColumn(field); + if (StrUtil.isNotBlank(column)) { + selectParts.add(column + " AS \"" + field + "\""); + } else { + selectParts.add("NULL AS \"" + field + "\""); + } + } + if (selectParts.isEmpty()) { + selectParts.add("t.stcd AS \"stcd\""); + } + return String.join(", ", selectParts); + } + + private String buildFbMsstbprptFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildFbMsstbprptLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildFbMsstbprptFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildFbMsstbprptLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapFbMsstbprptColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + Object value = filter.getValue(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("in".equals(operator)) { + List values = normalizeFbMsstbprptValues(value); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String key = "fbMsstbprptP" + indexHolder[0]++; + paramMap.put(key, item); + placeholders.add("#{map." + key + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + + String key = "fbMsstbprptP" + indexHolder[0]++; + return switch (operator) { + case "eq" -> { + paramMap.put(key, value); + yield column + " = #{map." + key + "}"; + } + case "neq" -> { + paramMap.put(key, value); + yield column + " <> #{map." + key + "}"; + } + case "contains" -> { + paramMap.put(key, "%" + value + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, value + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + value); + yield column + " LIKE #{map." + key + "}"; + } + case "gt" -> { + paramMap.put(key, value); + yield column + " > #{map." + key + "}"; + } + case "gte" -> { + paramMap.put(key, value); + yield column + " >= #{map." + key + "}"; + } + case "lt" -> { + paramMap.put(key, value); + yield column + " < #{map." + key + "}"; + } + case "lte" -> { + paramMap.put(key, value); + yield column + " <= #{map." + key + "}"; + } + default -> ""; + }; + } + + private String buildFbMsstbprptOrderBySql(List sortDescriptors) { + if (CollUtil.isEmpty(sortDescriptors)) { + return " ORDER BY t.baseId ASC, t.orderIndex ASC, t.stcd ASC"; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor descriptor : sortDescriptors) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapFbMsstbprptColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction); + } + if (orderByParts.isEmpty()) { + return " ORDER BY t.baseId ASC, t.orderIndex ASC, t.stcd ASC"; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + private String buildFbMsstbprptGroupSql(String baseSql, List groups) { + if (CollUtil.isEmpty(groups)) { + return baseSql; + } + List validGroups = groups.stream() + .filter(Objects::nonNull) + .filter(group -> StrUtil.isNotBlank(group.getField())) + .filter(group -> StrUtil.isNotBlank(mapFbMsstbprptColumn(group.getField()))) + .toList(); + if (validGroups.isEmpty()) { + return baseSql; + } + List selectParts = new ArrayList<>(); + List groupByParts = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : validGroups) { + String column = mapFbMsstbprptColumn(descriptor.getField()); + selectParts.add(column + " AS " + descriptor.getField().toUpperCase()); + selectParts.add("COUNT(*) AS COUNT_" + descriptor.getField().toUpperCase()); + groupByParts.add(column); + } + return "SELECT " + String.join(", ", selectParts) + + " FROM (" + baseSql + ") t GROUP BY " + String.join(", ", groupByParts) + + buildFbMsstbprptGroupOrderBySql(validGroups); + } + + private String buildFbMsstbprptGroupOrderBySql(List groups) { + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + String column = mapFbMsstbprptColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction); + } + if (orderByParts.isEmpty()) { + return ""; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + private String mapFbMsstbprptColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "id" -> "t.id"; + case "stcd" -> "t.stcd"; + case "stnm" -> "t.stnm"; + case "sttp" -> "t.sttp"; + case "sttpCode" -> "t.sttpCode"; + case "sttpName" -> "t.sttpName"; + case "sttpFullPath" -> "t.sttpFullPath"; + case "sttpTreeLevel" -> "t.sttpTreeLevel"; + case "lgtd" -> "t.lgtd"; + case "lttd" -> "t.lttd"; + case "dtmel" -> "t.dtmel"; + case "stlc" -> "t.stlc"; + case "usfl" -> "t.usfl"; + case "rstcd" -> "t.rstcd"; + case "ennm" -> "t.ennm"; + case "baseId" -> "t.baseId"; + case "baseName" -> "t.baseName"; + case "hbrvcd" -> "t.hbrvcd"; + case "hbrvcdName" -> "t.hbrvcdName"; + case "rvcd" -> "t.rvcd"; + case "rvcdName" -> "t.rvcdName"; + case "addvcd" -> "t.addvcd"; + case "addvcdName" -> "t.addvcdName"; + case "country" -> "t.country"; + case "countryName" -> "t.countryName"; + case "hycd" -> "t.hycd"; + case "hynm" -> "t.hynm"; + case "stdsdt" -> "t.stdsdt"; + case "pststdt" -> "t.pststdt"; + case "pesstdt" -> "t.pesstdt"; + case "ststdt" -> "t.ststdt"; + case "jcdt" -> "t.jcdt"; + case "stwddt" -> "t.stwddt"; + case "introduce" -> "t.introduce"; + case "precis" -> "t.precis"; + case "logo" -> "t.logo"; + case "inffile" -> "t.inffile"; + case "dtin" -> "t.dtin"; + case "dtinName" -> "t.dtinName"; + case "dtinTm" -> "t.dtinTm"; + case "bldsttCode" -> "t.bldsttCode"; + case "bldsttCcode" -> "t.bldsttCcode"; + case "bldsttCcodeName" -> "t.bldsttCcodeName"; + case "inv" -> "t.inv"; + case "invinmn" -> "t.invinmn"; + case "zzflar" -> "t.zzflar"; + case "zzflgy" -> "t.zzflgy"; + case "zzflyzms" -> "t.zzflyzms"; + case "zzflbjfs" -> "t.zzflbjfs"; + case "zzfldx" -> "t.zzfldx"; + case "zzflcnt" -> "t.zzflcnt"; + case "zzflfllc" -> "t.zzflfllc"; + case "zzfltm" -> "t.zzfltm"; + case "zzflrw" -> "t.zzflrw"; + case "dsun" -> "t.dsun"; + case "jbtxcs" -> "t.jbtxcs"; + case "dtfrqcy" -> "t.dtfrqcy"; + case "remark" -> "t.remark"; + case "vlsr" -> "t.vlsr"; + case "vlsrTm" -> "t.vlsrTm"; + case "orderIndex" -> "t.orderIndex"; + default -> null; + }; + } + + private List normalizeFbMsstbprptValues(Object value) { + List values = new ArrayList<>(); + if (value instanceof List list) { + for (Object item : list) { + if (item != null) { + values.add(item); + } + } + return values; + } + if (value instanceof Object[] array) { + for (Object item : array) { + if (item != null) { + values.add(item); + } + } + return values; + } + if (value != null) { + values.add(value); + } + return values; + } + + private List> normalizeFbMsstbprptRows(List> rows, List fields) { + if (CollUtil.isEmpty(rows)) { + return Collections.emptyList(); + } + List> result = new ArrayList<>(); + for (Map row : rows) { + Map normalizedRow = new LinkedHashMap<>(); + for (String field : fields) { + normalizedRow.put(field, getIgnoreCaseValue(row, field)); + } + result.add(normalizedRow); + } + return result; + } + + private Object getIgnoreCaseValue(Map row, String field) { + if (row == null || StrUtil.isBlank(field)) { + return null; + } + if (row.containsKey(field)) { + return row.get(field); + } + for (Map.Entry entry : row.entrySet()) { + if (entry.getKey() != null && entry.getKey().equalsIgnoreCase(field)) { + return entry.getValue(); + } + } + return null; + } + + private String buildFishCountFinishSql(String stcd, + List rstcdList, + Date startTime, + Date endTime, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT jh.RSTCD AS stcd, ") + .append("CASE WHEN imn.FCNT IS NULL THEN 0 ELSE imn.FCNT END AS finished, ") + .append("CASE WHEN imn.FCNT IS NULL THEN jh.FCNT ") + .append("WHEN jh.FCNT - imn.FCNT < 0 THEN 0 ") + .append("ELSE (jh.FCNT - imn.FCNT) END AS unfinished ") + .append("FROM ( ") + .append("SELECT jhr.RSTCD, SUM(jhrs.FCNT) AS FCNT ") + .append("FROM SD_ENGFRPLAN_B jhr ") + .append("JOIN SD_ENGFRPLANDET_B jhrs ON jhr.ID = jhrs.RPJH_ID ") + .append("WHERE NVL(jhr.IS_DELETED, 0) = 0 AND NVL(jhrs.IS_DELETED, 0) = 0 "); + appendFishTypeFilterSql(sql, "jhr", stcd, rstcdList, startTime, endTime, true, paramMap); + sql.append("GROUP BY jhr.RSTCD ") + .append(") jh ") + .append("LEFT JOIN ( ") + .append("SELECT imnr.RSTCD, SUM(imnrs.FCNT) AS FCNT ") + .append("FROM SD_ENGFR_R imnr ") + .append("JOIN SD_RPIMNFISH_R imnrs ON imnr.ID = imnrs.RPIMN_ID ") + .append("WHERE NVL(imnr.IS_DELETED, 0) = 0 AND NVL(imnrs.IS_DELETED, 0) = 0 "); + appendFishTypeFilterSql(sql, "imnr", stcd, rstcdList, startTime, endTime, false, paramMap); + sql.append("GROUP BY imnr.RSTCD ") + .append(") imn ON jh.RSTCD = imn.RSTCD"); + return sql.toString(); + } + + private String buildFishCountOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return " ORDER BY stcd ASC"; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = switch (sort.getField()) { + case "stcd" -> "stcd"; + case "finished" -> "finished"; + case "unfinished" -> "unfinished"; + default -> null; + }; + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction); + } + if (orderByParts.isEmpty()) { + return " ORDER BY stcd ASC"; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + private String buildFishRunQgcBaseSql(List stcdList, + Date startTime, + Date endTime, + Map paramMap) { + String ftpNameExpr = buildFishNameExpr("agg.FTP"); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT agg.STCD AS stcd, ") + .append("eng.ENNM AS stnm, ") + .append("eng.BASE_ID AS baseId, ") + .append("NVL(hb.BASENAME, eng.BASE_NAME) AS baseName, ") + .append("hb.ORDER_INDEX AS baseStepSort, ") + .append("siteAlong.SORT AS siteStepSort, ") + .append("along.ORDER_INDEX AS rvcdStepSort, ") +// .append("rstAlong.SORT AS rstcdStepSort, ") + .append("TO_CHAR(agg.FLYR) AS flyr, ") + .append("COALESCE(TO_CHAR(NVL(relRv.ZY_FISH_ID, relRv.FISH_ID)), ") + .append("TO_CHAR(NVL(relZy.ZY_FISH_ID, relZy.FISH_ID)), TO_CHAR(agg.FTP)) AS ftp, ") + .append(ftpNameExpr).append(" AS ftpName, ") + .append("agg.FCNT AS fcnt, ") + .append("totalAgg.TOTALFCNT AS totalFcnt, ") + .append("agg.FID AS fid, ") + .append("agg.RELEASE AS release ") + .append("FROM (") + .append(" SELECT run.STCD AS STCD, ") + .append(" TO_NUMBER(TO_CHAR(run.TM, 'YYYY')) AS FLYR, ") + .append(" det.FTP AS FTP, ") + .append(" SUM(det.FCNT) AS FCNT, ") + .append(" MAX(run.FPRFID) || ',' || MAX(run.FLRFID) || ',' || MAX(run.BRRFID) || ',' || MAX(run.BRFFID) AS FID, ") + .append(" REGEXP_REPLACE(LISTAGG(fb.STNM, ',') WITHIN GROUP (ORDER BY fb.STCD), '([^,]+)(,\\1)+', '\\1') AS RELEASE ") + .append(" FROM SD_RPIMNFISH_R det ") + .append(" INNER JOIN SD_ENGFR_R run ON det.RPIMN_ID = run.ID ") + .append(" AND NVL(run.IS_DELETED, 0) = 0 ") + .append(" LEFT JOIN SD_FBRD_B_H fb ON fb.STCD = run.RSTCD ") +// .append(" AND NVL(fb.IS_DELETED, 0) = 0 ") + .append(" WHERE NVL(det.IS_DELETED, 0) = 0 ") + .append(" AND det.FTP IS NOT NULL "); + appendFishRunQgcTimeFilter(sql, paramMap, "run", startTime, endTime, "fishRunDetail"); + appendInCondition(sql, paramMap, "run.STCD", stcdList, "fishRunDetailStcd"); + sql.append(" GROUP BY run.STCD, det.FTP, TO_NUMBER(TO_CHAR(run.TM, 'YYYY')) ") + .append(") agg ") + .append("LEFT JOIN (") + .append(" SELECT run.STCD AS STCD, ") + .append(" TO_NUMBER(TO_CHAR(run.TM, 'YYYY')) AS FLYR, ") + .append(" SUM(det.FCNT) AS TOTALFCNT ") + .append(" FROM SD_RPIMNFISH_R det ") + .append(" INNER JOIN SD_ENGFR_R run ON det.RPIMN_ID = run.ID ") + .append(" AND NVL(run.IS_DELETED, 0) = 0 ") + .append(" WHERE NVL(det.IS_DELETED, 0) = 0 ") + .append(" AND det.FTP IS NOT NULL "); + appendFishRunQgcTimeFilter(sql, paramMap, "run", startTime, endTime, "fishRunTotal"); + appendInCondition(sql, paramMap, "run.STCD", stcdList, "fishRunTotalStcd"); + sql.append(" GROUP BY run.STCD, TO_NUMBER(TO_CHAR(run.TM, 'YYYY')) ") + .append(") totalAgg ON totalAgg.STCD = agg.STCD AND totalAgg.FLYR = agg.FLYR ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = agg.STCD ") + .append(" AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID ") + .append(" AND NVL(hb.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN MS_ALONG_B along ON along.RVCD = eng.HBRVCD ") + .append(" AND along.CODE = 'common' ") + .append(" AND NVL(along.IS_DELETED, 0) = 0 ") +// .append("LEFT JOIN MS_ALONGDET_B rstAlong ON rstAlong.ALONG_ID = along.ID ") +// .append(" AND rstAlong.STCD = eng.RSTCD ") +// .append(" AND NVL(rstAlong.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN MS_ALONGDET_B siteAlong ON siteAlong.ALONG_ID = along.ID ") + .append(" AND siteAlong.STCD = eng.STCD ") + .append(" AND NVL(siteAlong.IS_DELETED, 0) = 0 ") + .append(buildFishJoinSql("agg.FTP", "eng.HBRVCD")) + .append("WHERE NVL(eng.IS_DELETED, 0) = 0 "); + return sql.toString(); + } + + private void appendFishRunQgcTimeFilter(StringBuilder sql, + Map paramMap, + String alias, + Date startTime, + Date endTime, + String keyPrefix) { + if (startTime != null) { + String startKey = keyPrefix + "Start"; + paramMap.put(startKey, startTime); + sql.append(" AND ").append(alias).append(".TM >= #{map.").append(startKey).append("} "); + } + if (endTime != null) { + String endKey = keyPrefix + "End"; + paramMap.put(endKey, endTime); + sql.append(" AND ").append(alias).append(".TM <= #{map.").append(endKey).append("} "); + } + } + + private String buildFishRunQgcFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildFishRunQgcLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildFishRunQgcFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildFishRunQgcLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if ("flyr".equalsIgnoreCase(filter.getField()) || "rstcd".equalsIgnoreCase(filter.getField())) { + return ""; + } + String column = mapFishRunQgcColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("isempty".equals(operator)) { + return "(" + column + " IS NULL OR " + column + " = '')"; + } + if ("isnotempty".equals(operator)) { + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + } + if ("in".equals(operator)) { + List values = normalizeQgcBsmfRValues(filter.getValue()); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object value : values) { + String key = "fishRunQgcP" + indexHolder[0]++; + paramMap.put(key, normalizeFishRunQgcValue(filter.getField(), value)); + placeholders.add("#{map." + key + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + Object value = filter.getValue(); + if (value == null) { + return ""; + } + String key = "fishRunQgcP" + indexHolder[0]++; + Object normalizedValue = normalizeFishRunQgcValue(filter.getField(), value); + return switch (operator) { + case "eq" -> { + paramMap.put(key, normalizedValue); + yield column + " = #{map." + key + "}"; + } + case "neq" -> { + paramMap.put(key, normalizedValue); + yield column + " <> #{map." + key + "}"; + } + case "gt" -> { + paramMap.put(key, normalizedValue); + yield column + " > #{map." + key + "}"; + } + case "gte" -> { + paramMap.put(key, normalizedValue); + yield column + " >= #{map." + key + "}"; + } + case "lt" -> { + paramMap.put(key, normalizedValue); + yield column + " < #{map." + key + "}"; + } + case "lte" -> { + paramMap.put(key, normalizedValue); + yield column + " <= #{map." + key + "}"; + } + case "contains" -> { + paramMap.put(key, "%" + String.valueOf(normalizedValue).trim() + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "doesnotcontain" -> { + paramMap.put(key, "%" + String.valueOf(normalizedValue).trim() + "%"); + yield column + " NOT LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, String.valueOf(normalizedValue).trim() + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + String.valueOf(normalizedValue).trim()); + yield column + " LIKE #{map." + key + "}"; + } + default -> ""; + }; + } + + private String mapFishRunQgcColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd" -> "r.stcd"; + case "stnm" -> "r.stnm"; + case "baseId" -> "r.baseId"; + case "baseName" -> "r.baseName"; + case "flyr" -> "r.flyr"; + case "ftp" -> "r.ftp"; + case "ftpName" -> "r.ftpName"; + case "fcnt" -> "r.fcnt"; + case "totalFcnt" -> "r.totalFcnt"; + case "release" -> "r.release"; + case "baseStepSort" -> "r.baseStepSort"; + case "siteStepSort" -> "r.siteStepSort"; + case "rvcdStepSort" -> "r.rvcdStepSort"; + case "rstcdStepSort" -> "r.rstcdStepSort"; + default -> null; + }; + } + + private Object normalizeFishRunQgcValue(String field, Object value) { + if (value == null) { + return null; + } + if ("fcnt".equals(field) || "totalFcnt".equals(field) || "baseStepSort".equals(field) + || "siteStepSort".equals(field) || "rvcdStepSort".equals(field) + || "rstcdStepSort".equals(field)) { + try { + return Long.parseLong(String.valueOf(value).trim()); + } catch (Exception ex) { + return null; + } + } + return value; + } + + private String buildFishRunQgcOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return " ORDER BY r.baseStepSort ASC NULLS LAST, r.rvcdStepSort ASC NULLS LAST, " + + "r.rstcdStepSort ASC NULLS LAST, r.siteStepSort ASC NULLS LAST, r.flyr ASC, r.ftpName ASC"; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapFishRunQgcColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction); + } + if (orderByParts.isEmpty()) { + return " ORDER BY r.baseStepSort ASC NULLS LAST, r.rvcdStepSort ASC NULLS LAST, " + + "r.rstcdStepSort ASC NULLS LAST, r.siteStepSort ASC NULLS LAST, r.flyr ASC, r.ftpName ASC"; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + private Date[] parseFishRunFlyrRange(String flyrFilter) { + if (StrUtil.isBlank(flyrFilter)) { + return new Date[]{null, null}; + } + String value = flyrFilter.trim(); + if (value.matches("\\d{4}")) { + Date start = parseDateTimeSafely(value + "-01-01 00:00:00"); + Date end = parseDateTimeSafely(value + "-12-31 23:59:59"); + return new Date[]{start, end}; + } + if (!value.contains(",")) { + Date point = parseDateTimeSafely(value); + return new Date[]{point, point}; + } + String[] parts = value.split(","); + if (parts.length < 2) { + return new Date[]{null, null}; + } + Date first = parseDateTimeSafely(parts[0].trim()); + Date second = parseDateTimeSafely(parts[1].trim()); + if (first == null || second == null) { + return new Date[]{null, null}; + } + return first.after(second) ? new Date[]{second, first} : new Date[]{first, second}; + } + + private void normalizeFishRunQgcRows(List list) { + if (CollUtil.isEmpty(list)) { + return; + } + for (FbFishRunQgcVo item : list) { + if (item == null) { + continue; + } + if (item.getFid() != null) { + LinkedHashSet fidSet = Arrays.stream(item.getFid().split(",")) + .map(StrUtil::trim) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toCollection(LinkedHashSet::new)); + item.setFid(fidSet.isEmpty() ? null : String.join(",", fidSet)); + } + if (item.getRelease() != null) { + LinkedHashSet releaseSet = Arrays.stream(item.getRelease().split(",")) + .map(StrUtil::trim) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toCollection(LinkedHashSet::new)); + item.setRelease(releaseSet.isEmpty() ? null : String.join(",", releaseSet)); + } + if (item.getFcnt() == null) { + item.setFcnt(0L); + } + if (item.getTotalFcnt() == null) { + item.setTotalFcnt(0L); + } + } + } + + private void appendFishRunMissingYears(List list, Date startTime, Date endTime, Page page) { + if (page != null || startTime == null || endTime == null) { + return; + } + int startYear = Integer.parseInt(DateUtil.format(startTime, "yyyy")); + int endYear = Integer.parseInt(DateUtil.format(endTime, "yyyy")); + Set existingYears = list.stream() + .filter(Objects::nonNull) + .map(FbFishRunQgcVo::getFlyr) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toCollection(LinkedHashSet::new)); + for (int year = startYear; year <= endYear; year++) { + String yearText = String.valueOf(year); + if (existingYears.contains(yearText)) { + continue; + } + FbFishRunQgcVo vo = new FbFishRunQgcVo(); + vo.setFlyr(yearText); + vo.setFcnt(0L); + vo.setTotalFcnt(0L); + list.add(vo); + } + list.sort(Comparator.comparing(FbFishRunQgcVo::getFlyr, Comparator.nullsLast(String::compareTo))); + } + + private String buildFishTypeStcdListSql(String baseId, String sttpCode, Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT fb.STCD AS stcd, fb.STNM AS stnm, fb.LGTD AS lgtd, fb.LTTD AS lttd, fb.BASE_ID AS baseId ") + .append("FROM SD_FBRD_B_H fb ") + .append("INNER JOIN SD_ENGFRPLAN_B plan ON fb.STCD = plan.RSTCD AND NVL(plan.IS_DELETED, 0) = 0 ") + .append("INNER JOIN SD_ENGFRPLANDET_B det ON plan.ID = det.RPJH_ID AND NVL(det.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(fb.USFL, 0) = 1 "); + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("fishTypeBaseId", baseId.trim()); + sql.append(" AND fb.BASE_ID = #{map.fishTypeBaseId} "); + } + if (StrUtil.isNotBlank(sttpCode)) { + paramMap.put("fishTypeSttpCode", sttpCode.trim()); + sql.append(" AND fb.STTP = #{map.fishTypeSttpCode} "); + } + sql.append("GROUP BY fb.STCD, fb.STNM, fb.LGTD, fb.LTTD, fb.BASE_ID, fb.ORDER_INDEX ") + .append("ORDER BY fb.ORDER_INDEX ASC, fb.STCD ASC"); + return sql.toString(); + } + + private String buildFishTypeFinishSql(String stcd, + List rstcdList, + Date startTime, + Date endTime, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT temp.stcd AS stcd, ") + .append("SUM(CASE WHEN temp.bftp IS NOT NULL THEN 1 ELSE 0 END) AS finished, ") + .append("SUM(CASE WHEN temp.aftp IS NOT NULL THEN 1 ELSE 0 END) AS unfinished ") + .append("FROM ( ") + .append("SELECT a.RSTCD AS stcd, a.FTP AS aftp, b.FTP AS bftp ") + .append("FROM ( ") + .append("SELECT jhr.RSTCD, jhrs.FTP ") + .append("FROM SD_ENGFRPLAN_B jhr ") + .append("JOIN SD_ENGFRPLANDET_B jhrs ON jhr.ID = jhrs.RPJH_ID ") + .append("WHERE NVL(jhr.IS_DELETED, 0) = 0 AND NVL(jhrs.IS_DELETED, 0) = 0 "); + appendFishTypeFilterSql(sql, "jhr", stcd, rstcdList, startTime, endTime, true, paramMap); + sql.append("GROUP BY jhr.RSTCD, jhrs.FTP ") + .append(") a ") + .append("LEFT JOIN ( ") + .append("SELECT imnr.RSTCD, imnrs.FTP ") + .append("FROM SD_ENGFR_R imnr ") + .append("JOIN SD_RPIMNFISH_R imnrs ON imnr.ID = imnrs.RPIMN_ID ") + .append("WHERE NVL(imnr.IS_DELETED, 0) = 0 AND NVL(imnrs.IS_DELETED, 0) = 0 "); + appendFishTypeFilterSql(sql, "imnr", stcd, rstcdList, startTime, endTime, false, paramMap); + sql.append("GROUP BY imnr.RSTCD, imnrs.FTP ") + .append(") b ON a.RSTCD = b.RSTCD AND a.FTP = b.FTP ") + .append(") temp ") + .append("GROUP BY temp.stcd"); + return sql.toString(); + } + + private void appendFishTypeFilterSql(StringBuilder sql, + String alias, + String stcd, + List rstcdList, + Date startTime, + Date endTime, + boolean planSide, + Map paramMap) { + if (StrUtil.isNotBlank(stcd)) { + String key = "fishType" + alias + "Stcd"; + paramMap.put(key, stcd.trim()); + sql.append(" AND ").append(alias).append(".RSTCD = #{map.").append(key).append("} "); + } + if (CollUtil.isNotEmpty(rstcdList)) { + List placeholders = new ArrayList<>(); + for (int i = 0; i < rstcdList.size(); i++) { + String key = "fishType" + alias + "Rstcd" + i; + paramMap.put(key, rstcdList.get(i)); + placeholders.add("#{map." + key + "}"); + } + sql.append(" AND ").append(alias).append(".STCD IN (").append(String.join(", ", placeholders)).append(") "); + } + if (startTime != null) { + String key = "fishType" + alias + "StartTime"; + paramMap.put(key, startTime); + sql.append(" AND ").append(alias).append(planSide ? ".PLANSD" : ".TM") + .append(" >= #{map.").append(key).append("} "); + } + if (endTime != null) { + String key = "fishType" + alias + "EndTime"; + paramMap.put(key, endTime); + sql.append(" AND ").append(alias).append(planSide ? ".PLANED" : ".TM") + .append(" <= #{map.").append(key).append("} "); + } + } + + private String buildFishTypeOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return " ORDER BY stcd ASC"; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = switch (sort.getField()) { + case "stcd" -> "stcd"; + case "finished" -> "finished"; + case "unfinished" -> "unfinished"; + default -> null; + }; + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction); + } + if (orderByParts.isEmpty()) { + return " ORDER BY stcd ASC"; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + private List parseFishTypeFilterValues(String rawValue) { + if (StrUtil.isBlank(rawValue)) { + return Collections.emptyList(); + } + return Arrays.stream(rawValue.replace("[", "") + .replace("]", "") + .replace("\"", "") + .split(",")) + .map(String::trim) + .filter(StrUtil::isNotBlank) + .distinct() + .toList(); + } + + private Date parseFishTypeDate(String value) { + if (StrUtil.isBlank(value)) { + return null; + } + try { + return DateUtil.parse(value.trim()); + } catch (Exception ex) { + return null; + } + } + private String buildOverviewStationListSql(String baseId, List stcdList, Map paramMap) { @@ -721,6 +1901,505 @@ public class FbStationServiceImpl implements FbStationService { return sql.toString(); } + private DataSourceResult queryQgcMsfbrdmDetailList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + Map paramMap = new HashMap<>(); + String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildQgcMsfbrdmDetailSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildQgcMsfbrdmCoreSql(parseDateTimeSafely(startTime), parseDateTimeSafely(endTime), paramMap)) + .append(") t WHERE 1 = 1 "); + + String filterSql = buildQgcMsfbrdmFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildQgcMsfbrdmOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, sql.toString(), paramMap, FbMsfbrdmQgcVo.class + ); + enrichQgcMsfbrdmDirections(list, parseDateTimeSafely(startTime), parseDateTimeSafely(endTime)); + deduplicateQgcMsfbrdmFids(list); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + private DataSourceResult queryQgcMsfbrdmGroupList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions, + GroupingInfo[] groupInfos) { + Map paramMap = new HashMap<>(); + String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT * FROM (") + .append(buildQgcMsfbrdmCoreSql(parseDateTimeSafely(startTime), parseDateTimeSafely(endTime), paramMap)) + .append(") t WHERE 1 = 1 "); + + String filterSql = buildQgcMsfbrdmFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + + String groupSql = buildQgcMsfbrdmGroupSql(sql.toString(), dataSourceRequest == null ? null : dataSourceRequest.getGroup()); + List> rows = microservicDynamicSQLMapper.pageAllList(null, groupSql, paramMap); + DataSourceResult result = new DataSourceResult<>(); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + List grouped = new GroupHelper().group(rows, Arrays.asList(groupInfos)); + populateQgcMsfbrdmGroupKeyNames(grouped); + result.setData((List) (List) grouped); + } + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + + private String buildQgcMsfbrdmCoreSql(Date startTime, Date endTime, Map paramMap) { + Integer year = startTime == null ? null : Integer.parseInt(DateUtil.format(startTime, "yyyy")); + String ftpCodeExpr = "COALESCE(TO_CHAR(NVL(relRv.ZY_FISH_ID, relRv.FISH_ID)), " + + "TO_CHAR(NVL(relZy.ZY_FISH_ID, relZy.FISH_ID)), TO_CHAR(stat.FTP))"; + String ftpNameExpr = buildFishNameExpr("stat.FTP"); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT fb.STCD AS stcd, ") + .append("fb.STNM AS stnm, ") + .append("fb.RSTCD AS rstcd, ") + .append("eng.ENNM AS ennm, ") + .append("fb.BASE_ID AS baseId, ") + .append("hb.BASENAME AS baseName, ") + .append("TO_CHAR(mt.YR) AS flyr, ") + .append(ftpCodeExpr).append(" AS ftp, ") + .append(ftpNameExpr).append(" AS ftpName, ") + .append("stat.FCNTJH AS fcntjh, ") + .append("stat.FCNTJC AS fcntjc, ") + .append("stat.FSZ AS fsz, ") + .append("stat.FWET AS fwet, ") + .append("fb.DTIN AS hydrodtin, ") + .append("fb.BLDSTT_CODE AS bldstt, ") + .append("mt.STD_SSTATE AS runState, ") + .append("CASE mt.STD_SSTATE ") + .append(" WHEN 0 THEN '数据未接入' ") + .append(" WHEN 1 THEN '正常运行' ") + .append(" WHEN 2 THEN '未正常报送数据' ") + .append(" WHEN 3 THEN '未正常运行' ") + .append(" ELSE NULL END AS runStateName, ") + .append("stat.FID AS fid ") + .append("FROM MS_STSTATE_T mt ") + .append("INNER JOIN SD_FBRD_B_H fb ON fb.STCD = mt.STCD ") +// .append(" AND NVL(fb.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fb.RSTCD ") + .append(" AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = fb.BASE_ID ") + .append(" AND NVL(hb.IS_DELETED, 0) = 0 ") + .append(" AND NVL(hb.ENABLED, 1) = 1 ") + .append("LEFT JOIN (") + .append(" SELECT COALESCE(planAgg.STCD, actualAgg.STCD) AS STCD, ") + .append(" COALESCE(planAgg.FTP, actualAgg.FTP) AS FTP, ") + .append(" COALESCE(planAgg.FLYR, actualAgg.FLYR) AS FLYR, ") + .append(" planAgg.FCNTJH AS FCNTJH, ") + .append(" actualAgg.FCNTJC AS FCNTJC, ") + .append(" actualAgg.FID AS FID, ") + .append(" actualAgg.FSZ AS FSZ, ") + .append(" actualAgg.FWET AS FWET ") + .append(" FROM (") + .append(" SELECT plan.RSTCD AS STCD, ") + .append(" planDet.FTP AS FTP, ") + .append(" TO_NUMBER(TO_CHAR(plan.PLANSD, 'YYYY')) AS FLYR, ") + .append(" SUM(planDet.FCNT) AS FCNTJH ") + .append(" FROM SD_ENGFRPLAN_B plan ") + .append(" INNER JOIN SD_ENGFRPLANDET_B planDet ON plan.ID = planDet.RPJH_ID ") + .append(" AND NVL(planDet.IS_DELETED, 0) = 0 ") + .append(" AND planDet.FTP IS NOT NULL ") + .append(" WHERE NVL(plan.IS_DELETED, 0) = 0 "); + if (startTime != null) { + paramMap.put("qgcMsfbrdmPlanStart", startTime); + sql.append(" AND plan.PLANSD >= #{map.qgcMsfbrdmPlanStart} "); + } + if (endTime != null) { + paramMap.put("qgcMsfbrdmPlanEnd", endTime); + sql.append(" AND plan.PLANED <= #{map.qgcMsfbrdmPlanEnd} "); + } + sql.append(" GROUP BY plan.RSTCD, planDet.FTP, TO_NUMBER(TO_CHAR(plan.PLANSD, 'YYYY')) ") + .append(" ) planAgg ") + .append(" FULL OUTER JOIN (") + .append(" SELECT run.RSTCD AS STCD, ") + .append(" actualDet.FTP AS FTP, ") + .append(" TO_NUMBER(TO_CHAR(run.TM, 'YYYY')) AS FLYR, ") + .append(" SUM(actualDet.FCNT) AS FCNTJC, ") + .append(" LISTAGG(run.FPRFID || ',' || run.FLRFID || ',' || run.BRRFID || ',' || run.BRFFID, ',') ") + .append(" WITHIN GROUP (ORDER BY run.ID) AS FID, ") + .append(" MAX(actualDet.FSZ) AS FSZ, ") + .append(" MAX(actualDet.FWET) AS FWET ") + .append(" FROM SD_ENGFR_R run ") + .append(" INNER JOIN SD_RPIMNFISH_R actualDet ON run.ID = actualDet.RPIMN_ID ") + .append(" AND NVL(actualDet.IS_DELETED, 0) = 0 ") + .append(" AND actualDet.FTP IS NOT NULL ") + .append(" WHERE NVL(run.IS_DELETED, 0) = 0 "); + if (startTime != null) { + paramMap.put("qgcMsfbrdmRunStart", startTime); + sql.append(" AND run.TM >= #{map.qgcMsfbrdmRunStart} "); + } + if (endTime != null) { + paramMap.put("qgcMsfbrdmRunEnd", endTime); + sql.append(" AND run.TM <= #{map.qgcMsfbrdmRunEnd} "); + } + sql.append(" GROUP BY run.RSTCD, actualDet.FTP, TO_NUMBER(TO_CHAR(run.TM, 'YYYY')) ") + .append(" ) actualAgg ") + .append(" ON planAgg.STCD = actualAgg.STCD ") + .append(" AND NVL(planAgg.FTP, '~') = NVL(actualAgg.FTP, '~') ") + .append(" AND NVL(planAgg.FLYR, -1) = NVL(actualAgg.FLYR, -1) ") + .append(") stat ON stat.STCD = mt.STCD AND stat.FLYR = mt.YR ") + .append(buildFishJoinSql("stat.FTP", "fb.HBRVCD")) + .append("WHERE NVL(mt.IS_DELETED, 0) = 0 ") + .append(" AND mt.STTP_CODE = 'FB' "); + if (year != null) { + paramMap.put("qgcMsfbrdmYear", year); + sql.append(" AND mt.YR = #{map.qgcMsfbrdmYear} "); + } + return sql.toString(); + } + + private void enrichQgcMsfbrdmDirections(List list, Date startTime, Date endTime) { + if (CollUtil.isEmpty(list)) { + return; + } + Map paramMap = new HashMap<>(); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT run.STCD AS flstcd, ") + .append(" eng.ENNM AS flstnm, ") + .append(" SUM(det.FCNT) AS flfnct, ") + .append(" TO_CHAR(run.TM, 'YYYY') AS flyr, ") + .append(" COALESCE(TO_CHAR(NVL(relRv.ZY_FISH_ID, relRv.FISH_ID)), ") + .append(" TO_CHAR(NVL(relZy.ZY_FISH_ID, relZy.FISH_ID)), TO_CHAR(det.FTP)) AS ftp, ") + .append(" run.RSTCD AS stcd ") + .append("FROM SD_ENGFR_R run ") + .append("INNER JOIN SD_RPIMNFISH_R det ON det.RPIMN_ID = run.ID ") + .append(" AND NVL(det.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_FBRD_B_H fb ON fb.STCD = run.RSTCD ") +// .append(" AND NVL(fb.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = run.STCD ") + .append(" AND NVL(eng.IS_DELETED, 0) = 0 ") + .append(buildFishJoinSql("det.FTP", "fb.HBRVCD")) + .append("WHERE NVL(run.IS_DELETED, 0) = 0 "); + if (startTime != null) { + paramMap.put("qgcMsfbrdmDirStart", startTime); + sql.append(" AND run.TM >= #{map.qgcMsfbrdmDirStart} "); + } + if (endTime != null) { + paramMap.put("qgcMsfbrdmDirEnd", endTime); + sql.append(" AND run.TM <= #{map.qgcMsfbrdmDirEnd} "); + } + sql.append("GROUP BY run.STCD, eng.ENNM, TO_CHAR(run.TM, 'YYYY'), ") + .append(" COALESCE(TO_CHAR(NVL(relRv.ZY_FISH_ID, relRv.FISH_ID)), ") + .append(" TO_CHAR(NVL(relZy.ZY_FISH_ID, relZy.FISH_ID)), TO_CHAR(det.FTP)), ") + .append(" run.RSTCD "); + + List directions = microservicDynamicSQLMapper.pageAllListWithResultType( + null, sql.toString(), paramMap, FbReleaseDirectionVo.class + ); + if (CollUtil.isEmpty(directions)) { + return; + } + Map> directionMap = directions.stream() + .collect(Collectors.groupingBy( + item -> StrUtil.blankToDefault(item.getStcd(), "") + "|" + + StrUtil.blankToDefault(item.getFtp(), "") + "|" + + StrUtil.blankToDefault(item.getFlyr(), ""), + LinkedHashMap::new, + Collectors.toList() + )); + for (FbMsfbrdmQgcVo item : list) { + String key = StrUtil.blankToDefault(item.getStcd(), "") + "|" + + StrUtil.blankToDefault(item.getFtp(), "") + "|" + + StrUtil.blankToDefault(item.getFlyr(), ""); + item.setDirectionVoList(directionMap.getOrDefault(key, Collections.emptyList())); + } + } + + private void deduplicateQgcMsfbrdmFids(List list) { + if (CollUtil.isEmpty(list)) { + return; + } + for (FbMsfbrdmQgcVo item : list) { + if (item == null || StrUtil.isBlank(item.getFid())) { + continue; + } + Set fidSet = Arrays.stream(item.getFid().split(",")) + .map(StrUtil::trim) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toCollection(LinkedHashSet::new)); + item.setFid(fidSet.isEmpty() ? null : String.join(",", fidSet)); + } + } + + private String buildQgcMsfbrdmDetailSelectSql(List select) { + List fields = CollUtil.isEmpty(select) + ? List.of("stcd", "stnm", "baseId", "baseName", "rstcd", "ennm", "bldstt", + "hydrodtin", "runState", "runStateName", "ftp", "ftpName", "fcntjh", "fcntjc", + "flyr", "fsz", "fwet", "fid") + : select; + List selectParts = new ArrayList<>(); + for (String field : fields) { + String column = mapQgcMsfbrdmColumn(field); + if (StrUtil.isNotBlank(column)) { + selectParts.add(column + " AS " + field); + } + } + if (selectParts.isEmpty()) { + selectParts.add("t.stcd AS stcd"); + } + return String.join(", ", selectParts); + } + + private String buildQgcMsfbrdmFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildQgcMsfbrdmLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildQgcMsfbrdmFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildQgcMsfbrdmLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapQgcMsfbrdmColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + Object value = filter.getValue(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("in".equals(operator)) { + List values = normalizeQgcBsmfRValues(value); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String key = "qgcMsfbrdmP" + indexHolder[0]++; + paramMap.put(key, normalizeQgcMsfbrdmValue(filter.getField(), item)); + placeholders.add("#{map." + key + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + String key = "qgcMsfbrdmP" + indexHolder[0]++; + Object normalizedValue = normalizeQgcMsfbrdmValue(filter.getField(), value); + return switch (operator) { + case "eq" -> { + paramMap.put(key, normalizedValue); + yield column + " = #{map." + key + "}"; + } + case "neq" -> { + paramMap.put(key, normalizedValue); + yield column + " <> #{map." + key + "}"; + } + case "gt" -> { + paramMap.put(key, normalizedValue); + yield column + " > #{map." + key + "}"; + } + case "gte" -> { + paramMap.put(key, normalizedValue); + yield column + " >= #{map." + key + "}"; + } + case "lt" -> { + paramMap.put(key, normalizedValue); + yield column + " < #{map." + key + "}"; + } + case "lte" -> { + paramMap.put(key, normalizedValue); + yield column + " <= #{map." + key + "}"; + } + case "contains" -> { + paramMap.put(key, "%" + normalizedValue + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "doesnotcontain" -> { + paramMap.put(key, "%" + normalizedValue + "%"); + yield column + " NOT LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, normalizedValue + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + normalizedValue); + yield column + " LIKE #{map." + key + "}"; + } + default -> ""; + }; + } + + private String buildQgcMsfbrdmOrderBySql(List sortDescriptors) { + if (CollUtil.isEmpty(sortDescriptors)) { + return " ORDER BY t.flyr DESC, t.stnm ASC, t.ftpName ASC"; + } + List parts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor descriptor : sortDescriptors) { + String column = mapQgcMsfbrdmColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC"; + parts.add(column + " " + direction); + } + if (parts.isEmpty()) { + return " ORDER BY t.flyr DESC, t.stnm ASC, t.ftpName ASC"; + } + return " ORDER BY " + String.join(", ", parts); + } + + private String buildQgcMsfbrdmGroupSql(String baseSql, List groups) { + if (CollUtil.isEmpty(groups)) { + return baseSql; + } + List validGroups = groups.stream() + .filter(group -> StrUtil.isNotBlank(mapQgcMsfbrdmColumn(group.getField()))) + .toList(); + if (validGroups.isEmpty()) { + return baseSql; + } + List fields = validGroups.stream().map(DataSourceRequest.GroupDescriptor::getField).toList(); + StringBuilder sql = new StringBuilder("SELECT "); + for (int i = 0; i < fields.size(); i++) { + if (i > 0) { + sql.append(", "); + } + sql.append(fields.get(i)); + } + for (String field : fields) { + sql.append(", COUNT(*) AS count_").append(field); + } + sql.append(" FROM (").append(baseSql).append(") t GROUP BY "); + for (int i = 0; i < fields.size(); i++) { + if (i > 0) { + sql.append(", "); + } + sql.append(fields.get(i)); + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : validGroups) { + if (Boolean.FALSE.equals(descriptor.getNeedSortFlag())) { + continue; + } + String direction = "desc".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC"; + orderByParts.add(descriptor.getField() + " " + direction); + } + if (!orderByParts.isEmpty()) { + sql.append(" ORDER BY ").append(String.join(", ", orderByParts)); + } + return sql.toString(); + } + + private String mapQgcMsfbrdmColumn(String field) { + return switch (field) { + case "stcd" -> "t.stcd"; + case "stnm" -> "t.stnm"; + case "baseId" -> "t.baseId"; + case "baseName" -> "t.baseName"; + case "rstcd" -> "t.rstcd"; + case "ennm" -> "t.ennm"; + case "bldstt" -> "t.bldstt"; + case "hydrodtin" -> "t.hydrodtin"; + case "runState" -> "t.runState"; + case "runStateName" -> "t.runStateName"; + case "ftp" -> "t.ftp"; + case "ftpName" -> "t.ftpName"; + case "fcntjh" -> "t.fcntjh"; + case "fcntjc" -> "t.fcntjc"; + case "flyr" -> "t.flyr"; + case "fsz" -> "t.fsz"; + case "fwet" -> "t.fwet"; + case "fid" -> "t.fid"; + default -> ""; + }; + } + + private Object normalizeQgcMsfbrdmValue(String field, Object value) { + if (value == null) { + return null; + } + return switch (field) { + case "fcntjh", "fcntjc", "bldstt", "hydrodtin", "runState" -> Integer.valueOf(String.valueOf(value)); + case "flyr" -> String.valueOf(value); + default -> value; + }; + } + + @SuppressWarnings("unchecked") + private void populateQgcMsfbrdmGroupKeyNames(List groups) { + if (CollUtil.isEmpty(groups)) { + return; + } + for (Group group : groups) { + if (group == null) { + continue; + } + if ("runState".equals(group.getField()) || "runStateName".equals(group.getField())) { + group.setKeyName(resolveQgcMsfbrdmRunStateName(group.getKey())); + } + if (CollUtil.isNotEmpty(group.getItems()) && group.getItems().get(0) instanceof Group) { + populateQgcMsfbrdmGroupKeyNames((List) group.getItems()); + } + } + } + + private String resolveQgcMsfbrdmRunStateName(Object value) { + if (value == null) { + return null; + } + String text = String.valueOf(value); + return switch (text) { + case "0" -> "数据未接入"; + case "1" -> "正常运行"; + case "2" -> "未正常报送数据"; + case "3" -> "未正常运行"; + default -> text; + }; + } + private DataSourceResult queryQgcBsmfRDetailList(DataSourceRequest dataSourceRequest, DataSourceLoadOptionsBase loadOptions) { Map paramMap = new HashMap<>(); @@ -755,6 +2434,68 @@ public class FbStationServiceImpl implements FbStationService { return result; } + private DataSourceResult queryResearchDetailList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + Map paramMap = new HashMap<>(); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildResearchDetailSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildResearchCoreSql()) + .append(") t WHERE 1 = 1 "); + + String filterSql = buildResearchFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildResearchOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, sql.toString(), paramMap, FbResearchVo.class + ); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + private DataSourceResult queryResearchGroupList(DataSourceRequest dataSourceRequest, + GroupingInfo[] groupInfos) { + Map paramMap = new HashMap<>(); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT * FROM (") + .append(buildResearchCoreSql()) + .append(") t WHERE 1 = 1 "); + + String filterSql = buildResearchFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + + String groupSql = buildResearchGroupSql(sql.toString(), dataSourceRequest == null ? null : dataSourceRequest.getGroup()); + List> rows = microservicDynamicSQLMapper.pageAllList(null, groupSql, paramMap); + DataSourceResult result = new DataSourceResult<>(); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + @SuppressWarnings({"rawtypes", "unchecked"}) private DataSourceResult queryQgcBsmfRGroupList(DataSourceRequest dataSourceRequest, DataSourceLoadOptionsBase loadOptions, @@ -808,6 +2549,264 @@ public class FbStationServiceImpl implements FbStationService { } } + private String buildResearchCoreSql() { + String fishNameExpr = buildFishNameExpr("res.FTP"); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT res.ID AS id, ") + .append("res.STCD AS stcd, ") + .append("res.DT AS dt, ") + .append("res.FTP AS ftp, ") + .append(fishNameExpr).append(" AS ftpName, ") + .append("res.WCO AS wco, ") + .append("res.JD AS jd, ") + .append("res.FID AS fid, ") + .append("res.RECORD_USER AS recordUser, ") + .append("res.RECORD_TIME AS recordTime, ") + .append("res.MODIFY_USER AS modifyUser, ") + .append("res.MODIFY_TIME AS modifyTime, ") + .append("res.IS_DELETED AS isDeleted, ") + .append("res.DELETE_USER AS deleteUser, ") + .append("res.DELETE_TIME AS deleteTime, ") + .append("fb.RSTCD AS rstcd, ") + .append("eng.ENNM AS ennm, ") + .append("fb.BASE_ID AS baseId, ") + .append("hb.BASENAME AS baseName, ") + .append("fb.HBRVCD AS hbrvcd ") + .append("FROM SD_FBRESEARCH_B res ") + .append("LEFT JOIN SD_FBRD_B_H fb ON fb.STCD = res.STCD ") +// .append(" AND NVL(fb.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fb.RSTCD ") + .append(" AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = fb.BASE_ID ") + .append(" AND NVL(hb.IS_DELETED, 0) = 0 ") + .append(" AND NVL(hb.ENABLED, 1) = 1 ") + .append(buildFishJoinSql("res.FTP", "fb.HBRVCD")) + .append("WHERE NVL(res.IS_DELETED, 0) = 0 "); + return sql.toString(); + } + + private String buildResearchDetailSelectSql(List select) { + List fields = CollUtil.isEmpty(select) + ? List.of("id", "stcd", "dt", "ftp", "ftpName", "wco", "jd", "fid", + "recordUser", "recordTime", "modifyUser", "modifyTime", "isDeleted", + "deleteUser", "deleteTime", "rstcd", "ennm", "baseId", "baseName", "hbrvcd") + : select; + List selectParts = new ArrayList<>(); + for (String field : fields) { + String column = mapResearchColumn(field); + if (StrUtil.isNotBlank(column)) { + selectParts.add(column + " AS " + field); + } + } + if (selectParts.isEmpty()) { + selectParts.add("t.id AS id"); + } + return String.join(", ", selectParts); + } + + private String buildResearchFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildResearchLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildResearchFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildResearchLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String field = filter.getField(); + String column = mapResearchColumn(field); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + Object value = filter.getValue(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("in".equals(operator)) { + List values = normalizeQgcBsmfRValues(value); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String key = "researchP" + indexHolder[0]++; + paramMap.put(key, normalizeResearchValue(field, item)); + placeholders.add("#{map." + key + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + String key = "researchP" + indexHolder[0]++; + Object normalizedValue = normalizeResearchValue(field, value); + return switch (operator) { + case "eq" -> { + paramMap.put(key, normalizedValue); + yield column + " = #{map." + key + "}"; + } + case "neq" -> { + paramMap.put(key, normalizedValue); + yield column + " <> #{map." + key + "}"; + } + case "gt" -> { + paramMap.put(key, normalizedValue); + yield column + " > #{map." + key + "}"; + } + case "gte" -> { + paramMap.put(key, normalizedValue); + yield column + " >= #{map." + key + "}"; + } + case "lt" -> { + paramMap.put(key, normalizedValue); + yield column + " < #{map." + key + "}"; + } + case "lte" -> { + paramMap.put(key, normalizedValue); + yield column + " <= #{map." + key + "}"; + } + case "contains" -> { + paramMap.put(key, "%" + normalizedValue + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "doesnotcontain" -> { + paramMap.put(key, "%" + normalizedValue + "%"); + yield column + " NOT LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, normalizedValue + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + normalizedValue); + yield column + " LIKE #{map." + key + "}"; + } + default -> ""; + }; + } + + private String buildResearchOrderBySql(List sortDescriptors) { + if (CollUtil.isEmpty(sortDescriptors)) { + return " ORDER BY t.dt DESC, t.recordTime DESC"; + } + List parts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor descriptor : sortDescriptors) { + String column = mapResearchColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC"; + parts.add(column + " " + direction); + } + if (parts.isEmpty()) { + return " ORDER BY t.dt DESC, t.recordTime DESC"; + } + return " ORDER BY " + String.join(", ", parts); + } + + private String buildResearchGroupSql(String baseSql, List groups) { + if (CollUtil.isEmpty(groups)) { + return baseSql; + } + List validGroups = groups.stream() + .filter(group -> StrUtil.isNotBlank(mapResearchColumn(group.getField()))) + .toList(); + if (validGroups.isEmpty()) { + return baseSql; + } + List fields = validGroups.stream().map(DataSourceRequest.GroupDescriptor::getField).toList(); + StringBuilder sql = new StringBuilder("SELECT "); + for (int i = 0; i < fields.size(); i++) { + if (i > 0) { + sql.append(", "); + } + sql.append(fields.get(i)); + } + for (String field : fields) { + sql.append(", COUNT(*) AS count_").append(field); + } + sql.append(" FROM (").append(baseSql).append(") t GROUP BY "); + for (int i = 0; i < fields.size(); i++) { + if (i > 0) { + sql.append(", "); + } + sql.append(fields.get(i)); + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : validGroups) { + if (Boolean.FALSE.equals(descriptor.getNeedSortFlag())) { + continue; + } + String direction = "desc".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC"; + orderByParts.add(descriptor.getField() + " " + direction); + } + if (!orderByParts.isEmpty()) { + sql.append(" ORDER BY ").append(String.join(", ", orderByParts)); + } + return sql.toString(); + } + + private String mapResearchColumn(String field) { + return switch (field) { + case "id" -> "t.id"; + case "stcd" -> "t.stcd"; + case "dt" -> "t.dt"; + case "ftp" -> "t.ftp"; + case "ftpName" -> "t.ftpName"; + case "wco" -> "t.wco"; + case "jd" -> "t.jd"; + case "fid" -> "t.fid"; + case "recordUser" -> "t.recordUser"; + case "recordTime" -> "t.recordTime"; + case "modifyUser" -> "t.modifyUser"; + case "modifyTime" -> "t.modifyTime"; + case "isDeleted" -> "t.isDeleted"; + case "deleteUser" -> "t.deleteUser"; + case "deleteTime" -> "t.deleteTime"; + case "rstcd" -> "t.rstcd"; + case "ennm" -> "t.ennm"; + case "baseId" -> "t.baseId"; + case "baseName" -> "t.baseName"; + case "hbrvcd" -> "t.hbrvcd"; + default -> ""; + }; + } + + private Object normalizeResearchValue(String field, Object value) { + if (value == null) { + return null; + } + if (Set.of("dt", "recordTime", "modifyTime", "deleteTime").contains(field) + && value instanceof String text) { + return parseDateTimeSafely(text); + } + return value; + } + private String buildBsmfRFishInnerSql(DataSourceRequest dataSourceRequest, DataSourceLoadOptionsBase loadOptions, Map paramMap) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fh/service/impl/FhHabitatServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fh/service/impl/FhHabitatServiceImpl.java index 1f7a1337..cef364cf 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fh/service/impl/FhHabitatServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fh/service/impl/FhHabitatServiceImpl.java @@ -96,10 +96,14 @@ public class FhHabitatServiceImpl implements FhHabitatService { } sql.append(buildOrderBySql(dataSourceRequest.getSort())); - Page page = null; - if (QgcQueryWrapperUtil.getPageInfo(loadOptions).getHasPageInfo()) { - page = QgcQueryWrapperUtil.getPageInfo(loadOptions).getPage(); - } +// Page page = null; +// if (QgcQueryWrapperUtil.getPageInfo(loadOptions).getHasPageInfo()) { +// page = QgcQueryWrapperUtil.getPageInfo(loadOptions).getPage(); +// } + +// DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, HabitatVo.class); DataSourceResult result = new DataSourceResult<>(); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpFpssrlQueryVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpFpssrlQueryVo.java index 5094b292..56bbf631 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpFpssrlQueryVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpFpssrlQueryVo.java @@ -72,6 +72,9 @@ public class FpFpssrlQueryVo { @Schema(description = "游向") private String direction; + @Schema(description = "游向中文") + private String directionName; + @Schema(description = "水温") private String temperature; diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpVmsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpVmsstbprptVo.java index 83915608..a657d6a9 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpVmsstbprptVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpVmsstbprptVo.java @@ -199,8 +199,11 @@ public class FpVmsstbprptVo implements Serializable { @Schema(description = "升鱼机集鱼槽水深") private String syjwdp; +// @Schema(description = "设计过鱼规模") +// private Integer sjgycnt; + @Schema(description = "设计过鱼规模") - private Integer sjgycnt; + private String sjgycnt; @Schema(description = "主要过鱼对象描述") private String zygydxms; diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpBuildServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpBuildServiceImpl.java index 88b8a6f9..4e504346 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpBuildServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpBuildServiceImpl.java @@ -136,15 +136,15 @@ public class FpBuildServiceImpl implements FpBuildService { String sql = "SELECT DISTINCT " + " fish.ID AS id, " + " fish.NAME AS name " + - "FROM SD_FPSS_B_H fp " + - "INNER JOIN SD_ENGINFO_B_H eng ON eng.STCD = fp.RSTCD " + - " AND NVL(eng.IS_DELETED, 0) = 0 " + - "INNER JOIN SD_FISHDICTORY_RLTN_B rel ON rel.RVCD = eng.HBRVCD " + + "FROM SD_FBRD_B_H fb " + +// "INNER JOIN SD_ENGINFO_B_H eng ON eng.STCD = fb.RSTCD " + +// " AND NVL(eng.IS_DELETED, 0) = 0 " + + "INNER JOIN SD_FISHDICTORY_RLTN_B rel ON rel.BASE_ID = fb.BASE_ID " + " AND NVL(rel.IS_DELETED, 0) = 0 " + "INNER JOIN SD_FISHDICTORY_B fish ON fish.ID = NVL(rel.ZY_FISH_ID, rel.FISH_ID) " + " AND NVL(fish.IS_DELETED, 0) = 0 " + " AND NVL(fish.ENABLE, 1) = 1 " + - "WHERE fp.STCD = #{map.stcd} " + + "WHERE fb.STCD = #{map.stcd} " + "ORDER BY fish.NAME"; List list = microservicDynamicSQLMapper.getAllListWithResultType( @@ -337,7 +337,7 @@ public class FpBuildServiceImpl implements FpBuildService { .append("fp.YDCSPD AS ydcspd, ") .append("fp.YDCSCNT AS ydcscnt, ") .append("fp.YDXXCCNT AS ydxxccnt, ") - .append("fp.V AS v, ") + .append("fp.FLOW AS flow, ") .append("fp.FZRDMXZ AS fzrdmxz, ") .append("fp.FZRTDSZ AS fzrtdsz, ") .append("fp.FZRYXWDP AS fzryxwdp, ") @@ -858,7 +858,7 @@ public class FpBuildServiceImpl implements FpBuildService { columnMap.put("ydcspd", "fp.YDCSPD"); columnMap.put("ydcscnt", "fp.YDCSCNT"); columnMap.put("ydxxccnt", "fp.YDXXCCNT"); - columnMap.put("v", "fp.V"); + columnMap.put("flow", "fp.flow"); columnMap.put("fzrdmxz", "fp.FZRDMXZ"); columnMap.put("fzrtdsz", "fp.FZRTDSZ"); columnMap.put("fzryxwdp", "fp.FZRYXWDP"); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java index f94e7cfd..c81bf512 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java @@ -1635,6 +1635,7 @@ public class FpRunServiceImpl implements FpRunService { selectMap.put("width", "t.width AS width"); selectMap.put("fishspeed", "t.fishspeed AS fishspeed"); selectMap.put("direction", "t.direction AS direction"); + selectMap.put("directionName", "CASE t.direction WHEN '0' THEN '上行' WHEN '1' THEN '下行' WHEN '2' THEN '上行折返' WHEN '3' THEN '下行折返' END AS directionName"); selectMap.put("temperature", "t.temperature AS temperature"); selectMap.put("speed", "t.speed AS speed"); selectMap.put("channelno", "t.channelno AS channelno"); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/controller/FprMonitorController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/controller/FprMonitorController.java index a5f31b87..61cbb809 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/controller/FprMonitorController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/controller/FprMonitorController.java @@ -1,8 +1,10 @@ package com.yfd.platform.qgc_env.fpr.controller; import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.qgc_env.fpr.entity.ao.FprdRunDataAo; +import com.yfd.platform.qgc_env.fpr.entity.vo.FprdDetailVo; import com.yfd.platform.qgc_eng.eq.service.EngEqDataService; import com.yfd.platform.qgc_env.fpr.entity.vo.FprFtpChangeInfoVo; import com.yfd.platform.qgc_env.fpr.entity.vo.FprdRunDataInfoVo; @@ -38,6 +40,12 @@ public class FprMonitorController { return ResponseResult.successData(fprMonitorService.getMsstbprptList(dataSourceRequest)); } + @PostMapping("/vmsstbprpt/GetKendoList") + @Operation(summary = "鱼类调查装置统计查询") + public ResponseResult getVmsstbprptList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fprMonitorService.getVmsstbprptList(dataSourceRequest)); + } + @PostMapping("/fishDic/GetKendoList") @Operation(summary = "鱼类字典列表") public ResponseResult getFishDicList(@RequestBody DataSourceRequest dataSourceRequest) { @@ -64,6 +72,20 @@ public class FprMonitorController { return ResponseResult.successData(result); } + @PostMapping("/sdFprdR/GetKendoListCust") + @Operation(summary = "鱼类调查装置详情数据") + public ResponseResult getFprdDetailList(@RequestBody DataSourceRequest dataSourceRequest) { + DataSourceResult result = fprMonitorService.getFprdDetailList(dataSourceRequest); + return ResponseResult.successData(result); + } + + @PostMapping("/sdFprdR/getFishInfo") + @Operation(summary = "获取鱼种类信息") + public ResponseResult getFishInfo() { + List result = fprMonitorService.getFishInfo(); + return ResponseResult.successData(result); + } + @PostMapping("/wbsb/GetKendoList") @Operation(summary = "查询基地/基地流域树数据") public ResponseResult getWbsbList(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/entity/vo/FprZyFishDicVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/entity/vo/FprZyFishDicVo.java index 2fb1bf67..7dad88bf 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/entity/vo/FprZyFishDicVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/entity/vo/FprZyFishDicVo.java @@ -45,4 +45,5 @@ public class FprZyFishDicVo { private String spawnMonth; private String orders; private String vlsr; + private java.util.Date vlsrTm; } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/entity/vo/FprdDetailVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/entity/vo/FprdDetailVo.java new file mode 100644 index 00000000..d3c200f1 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/entity/vo/FprdDetailVo.java @@ -0,0 +1,36 @@ +package com.yfd.platform.qgc_env.fpr.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +@Data +@Schema(description = "鱼类调查装置详情数据") +public class FprdDetailVo { + + @Schema(description = "调查鱼类装置编码") + private String stcd; + + @Schema(description = "调查鱼类装置名称") + private String stnm; + + @Schema(description = "监测时间") + private Date tm; + + @Schema(description = "监测视频文件ID") + private String fid; + + @Schema(description = "鱼类名称") + private String name; + + @Schema(description = "鱼类数量") + private Long num; + + @Schema(description = "鱼尺寸") + private BigDecimal fsz; + + @Schema(description = "鱼重量") + private BigDecimal weight; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/FprMonitorService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/FprMonitorService.java index c0c49dd4..8681b405 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/FprMonitorService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/FprMonitorService.java @@ -6,6 +6,7 @@ import com.yfd.platform.qgc_env.fpr.entity.vo.FprFtpChangeInfoVo; import com.yfd.platform.qgc_env.fpr.entity.ao.FprdRunDataAo; import com.yfd.platform.qgc_env.fpr.entity.vo.FprFishDicVo; import com.yfd.platform.qgc_env.fpr.entity.vo.FprMsstbprptVo; +import com.yfd.platform.qgc_env.fpr.entity.vo.FprdDetailVo; import com.yfd.platform.qgc_env.fpr.entity.vo.FprdRunDataInfoVo; import com.yfd.platform.qgc_env.fpr.entity.vo.FprZyFishDicVo; @@ -15,6 +16,8 @@ public interface FprMonitorService { DataSourceResult getMsstbprptList(DataSourceRequest dataSourceRequest); + DataSourceResult getVmsstbprptList(DataSourceRequest dataSourceRequest); + DataSourceResult getFishDicList(DataSourceRequest dataSourceRequest); DataSourceResult getZyFishDicList(DataSourceRequest dataSourceRequest); @@ -22,4 +25,8 @@ public interface FprMonitorService { FprdRunDataInfoVo getFprdRunDataInfo(FprdRunDataAo ao); List getFtpChangeInfo(FprdRunDataAo ao); + + DataSourceResult getFprdDetailList(DataSourceRequest dataSourceRequest); + + List getFishInfo(); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java index 2ab792b0..09b35d14 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fpr/service/impl/FprMonitorServiceImpl.java @@ -3,6 +3,7 @@ package com.yfd.platform.qgc_env.fpr.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.yfd.platform.common.DataSourceLoadOptionsBase; @@ -16,6 +17,7 @@ import com.yfd.platform.qgc_env.fpr.entity.ao.FprdRunDataAo; import com.yfd.platform.qgc_env.fpr.entity.vo.FprFishDicVo; import com.yfd.platform.qgc_env.fpr.entity.vo.FprFtpChangeInfoVo; import com.yfd.platform.qgc_env.fpr.entity.vo.FprMsstbprptVo; +import com.yfd.platform.qgc_env.fpr.entity.vo.FprdDetailVo; import com.yfd.platform.qgc_env.fpr.entity.vo.FprdRunDataInfoVo; import com.yfd.platform.qgc_env.fpr.entity.vo.FprZyFishDicVo; import com.yfd.platform.qgc_env.fpr.service.FprMonitorService; @@ -25,6 +27,7 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -76,6 +79,53 @@ public class FprMonitorServiceImpl implements FprMonitorService { ); } + @Override + public DataSourceResult getFprdDetailList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Map paramMap = new HashMap<>(); + String filterSql = buildFprdDetailFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + + StringBuilder sql = new StringBuilder("SELECT ") + .append(buildFprdDetailSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildFprdDetailBaseSql()) + .append(") t WHERE 1 = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildFprdDetailOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, sql.toString(), paramMap, FprdDetailVo.class + ); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public List getFishInfo() { + List> rows = microservicDynamicSQLMapper.getAllList( + "SELECT DISTINCT NAME AS name FROM SD_FPRDFISH_R " + + "WHERE NVL(IS_DELETED, 0) = 0 AND NAME IS NOT NULL " + + "ORDER BY NAME", + null + ); + return rows.stream() + .map(row -> row.get("NAME")) + .filter(java.util.Objects::nonNull) + .map(String::valueOf) + .toList(); + } + @Override public DataSourceResult getMsstbprptList(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -130,6 +180,11 @@ public class FprMonitorServiceImpl implements FprMonitorService { return result; } + @Override + public DataSourceResult getVmsstbprptList(DataSourceRequest dataSourceRequest) { + return getMsstbprptList(dataSourceRequest); + } + @Override public DataSourceResult getFishDicList(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -195,87 +250,33 @@ public class FprMonitorServiceImpl implements FprMonitorService { new int[]{0} ); + String baseSql = StrUtil.isBlank(rvcd) ? buildZyFishDicSummarySql() : buildZyFishDicBaseSql(); StringBuilder sql = new StringBuilder("SELECT * FROM (") - .append(buildZyFishDicBaseSql()) + .append(baseSql) .append(") t WHERE 1 = 1 "); if (StrUtil.isNotBlank(filterSql)) { sql.append(" AND ").append(filterSql).append(" "); } - // 增加排序 - if(dataSourceRequest.getSort() !=null && !dataSourceRequest.getSort().isEmpty()){ - List sortDescriptors = dataSourceRequest.getSort(); - StringBuilder orderSql = new StringBuilder(); - orderSql.append(" order by "); - for (DataSourceRequest.SortDescriptor sort:sortDescriptors){ - orderSql.append(sort.getField()).append(" ").append(sort.getDir()).append(","); - } - sql.append(orderSql, 0, orderSql.length()-1); -// String[] beans = SpringContextHolder.getApplicationContext().getBeanDefinitionNames(); - sql.append(" nulls last "); - }else{ - sql.append(" order by rvcd nulls last "); - } - List list = microservicDynamicSQLMapper.getAllListWithResultType( + sql.append(buildZyFishDicOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List resultList = microservicDynamicSQLMapper.pageAllListWithResultType( + page, sql.toString(), paramMap, FprZyFishDicVo.class ); - List> rvcdRows = microservicDynamicSQLMapper.getAllList( - "SELECT RVCD AS rvcd, RVNM AS rvcdName FROM SD_RVCD_DIC", - null - ); - Map rvcdNameMap = new HashMap<>(); - for (Map row : rvcdRows) { - Object rvcdKey = row.get("RVCD"); - Object rvcdName = row.get("RVCDNAME"); - if (rvcdKey != null && rvcdName != null) { - rvcdNameMap.put(String.valueOf(rvcdKey), String.valueOf(rvcdName)); - } - } - - List resultList; - Map> rvcdMap = new HashMap<>(); - if (StrUtil.isBlank(rvcd)) { - rvcdMap = list.stream() - .collect(Collectors.groupingBy( - item -> StrUtil.blankToDefault(item.getZyFishId(), item.getId()), - LinkedHashMap::new, - Collectors.mapping(FprZyFishDicVo::getRvcd, Collectors.toList()) - )); - LinkedHashMap distinctMap = new LinkedHashMap<>(); - for (FprZyFishDicVo item : list) { - distinctMap.putIfAbsent(StrUtil.blankToDefault(item.getZyFishId(), item.getId()), item); - } - resultList = new ArrayList<>(distinctMap.values()); - } else { - resultList = new ArrayList<>(list); - } + int startIndex = loadOptions == null || loadOptions.getSkip() == null ? 0 : Math.max(loadOptions.getSkip(), 0); + fillZyFishRvcdNames(resultList, rvcd); for (int i = 0; i < resultList.size(); i++) { FprZyFishDicVo item = resultList.get(i); - item.setIndex(i + 1); + item.setIndex(startIndex + i + 1); item.setSpawnMonth(formatSpawnMonth(item.getSpawnMonth())); - if (StrUtil.isBlank(rvcd)) { - List rvcdList = rvcdMap.getOrDefault( - StrUtil.blankToDefault(item.getZyFishId(), item.getId()), - new ArrayList<>() - ).stream().filter(StrUtil::isNotBlank).distinct().toList(); - List rvcdNames = new ArrayList<>(); - for (String rvcdItem : rvcdList) { - String rvcdName = rvcdNameMap.get(rvcdItem); - if (StrUtil.isNotBlank(rvcdName)) { - rvcdNames.add(rvcdName); - } - } - item.setRvcdName(String.join(",", rvcdNames)); - } else { - item.setRvcdName(rvcdNameMap.get(item.getRvcd())); - } } DataSourceResult result = new DataSourceResult<>(); - result.setTotal((long) resultList.size()); - result.setData(paginateZyFishDicList(resultList, loadOptions)); + result.setTotal(page != null ? page.getTotal() : resultList.size()); + result.setData(resultList); result.setAggregates(new HashMap<>()); return result; } @@ -335,7 +336,7 @@ public class FprMonitorServiceImpl implements FprMonitorService { "NVL(alongBase.ORDER_INDEX, 999999) AS rvcdStepSort, " + "NVL(engSort.SORT, 999999) AS rstcdStepSort, " + "NVL(siteSort.SORT, NVL(src.ORDER_INDEX, 999999)) AS siteStepSort " + - "FROM SD_FPRD_B_H src " + + "FROM SD_AIMONITOR_B_H src " + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = src.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = src.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = src.HBRVCD " + @@ -371,13 +372,13 @@ public class FprMonitorServiceImpl implements FprMonitorService { private String buildFprdRunDataInfoSql(FprdRunDataAo ao) { StringBuilder sql = new StringBuilder("SELECT ") .append("NVL((SELECT COUNT(1) ") - .append(" FROM SD_FPRD_B_H baseCnt ") + .append(" FROM SD_AIMONITOR_B_H baseCnt ") .append(" WHERE NVL(baseCnt.IS_DELETED, 0) = 0 ") .append(" AND baseCnt.STTP = 'FPRD' ") .append(" AND baseCnt.BASE_ID = #{map.baseId}), 0) AS fprdCount, ") .append("NVL((SELECT COUNT(DISTINCT fish.NAME) ") .append(" FROM SD_FPRD_R run ") - .append(" INNER JOIN SD_FPRD_B_H base ON base.STCD = run.STCD ") + .append(" INNER JOIN SD_AIMONITOR_B_H base ON base.STCD = run.STCD ") .append(" AND NVL(base.IS_DELETED, 0) = 0 ") .append(" AND base.STTP = 'FPRD' ") .append(" INNER JOIN SD_FPRDFISH_R fish ON fish.FPRDR_ID = run.ID ") @@ -391,7 +392,7 @@ public class FprMonitorServiceImpl implements FprMonitorService { sql.append("), 0) AS ftpCount, ") .append("NVL((SELECT COUNT(1) ") .append(" FROM SD_FPRD_R run ") - .append(" INNER JOIN SD_FPRD_B_H base ON base.STCD = run.STCD ") + .append(" INNER JOIN SD_AIMONITOR_B_H base ON base.STCD = run.STCD ") .append(" AND NVL(base.IS_DELETED, 0) = 0 ") .append(" AND base.STTP = 'FPRD' ") .append(" INNER JOIN SD_FPRDFISH_R fish ON fish.FPRDR_ID = run.ID ") @@ -414,7 +415,7 @@ public class FprMonitorServiceImpl implements FprMonitorService { .append("TO_NUMBER(TO_CHAR(run.TM, 'MM')) AS month, ") .append("TO_NUMBER(TO_CHAR(run.TM, 'YYYY')) AS year ") .append("FROM SD_FPRD_R run ") - .append("INNER JOIN SD_FPRD_B_H base ON base.STCD = run.STCD ") + .append("INNER JOIN SD_AIMONITOR_B_H base ON base.STCD = run.STCD ") .append(" AND NVL(base.IS_DELETED, 0) = 0 ") .append(" AND base.STTP = 'FPRD' ") .append("INNER JOIN SD_FPRDFISH_R fish ON fish.FPRDR_ID = run.ID ") @@ -430,6 +431,171 @@ public class FprMonitorServiceImpl implements FprMonitorService { return sql.toString(); } + private String buildFprdDetailBaseSql() { + return "SELECT " + + "run.STCD AS stcd, " + + "base.STNM AS stnm, " + + "run.TM AS tm, " + + "run.FLPTH AS fid, " + + "fish.NAME AS name, " + + "fish.NUM AS num, " + + "fish.FSZ AS fsz, " + + "fish.WEIGHT AS weight " + + "FROM SD_FPRD_R run " + + "INNER JOIN SD_AIMONITOR_B_H base ON run.STCD = base.STCD " + + " AND base.STTP = 'FPRD' " + + " AND NVL(base.IS_DELETED, 0) = 0 " + + "INNER JOIN SD_FPRDFISH_R fish ON run.ID = fish.FPRDR_ID " + + " AND NVL(fish.IS_DELETED, 0) = 0 " + + "WHERE NVL(run.IS_DELETED, 0) = 0 "; + } + + private String buildFprdDetailSelectSql(List selectFields) { + LinkedHashMap columnMap = new LinkedHashMap<>(); + columnMap.put("stcd", "t.stcd AS stcd"); + columnMap.put("stnm", "t.stnm AS stnm"); + columnMap.put("tm", "t.tm AS tm"); + columnMap.put("fid", "t.fid AS fid"); + columnMap.put("name", "t.name AS name"); + columnMap.put("num", "t.num AS num"); + columnMap.put("fsz", "t.fsz AS fsz"); + columnMap.put("weight", "t.weight AS weight"); + if (CollUtil.isEmpty(selectFields)) { + return String.join(", ", columnMap.values()); + } + List columns = new ArrayList<>(); + for (String field : selectFields) { + String column = columnMap.get(field); + if (StrUtil.isNotBlank(column)) { + columns.add(column); + } + } + return columns.isEmpty() ? String.join(", ", columnMap.values()) : String.join(", ", columns); + } + + private String buildFprdDetailFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildFprdDetailLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildFprdDetailFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildFprdDetailLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String field = filter.getField(); + Object value = filter.getValue(); + if (value == null) { + return ""; + } + String key = "fprdDetailP" + indexHolder[0]++; + return switch (field) { + case "stcd" -> { + paramMap.put(key, String.valueOf(value)); + yield "t.stcd = #{map." + key + "}"; + } + case "name" -> { + paramMap.put(key, "%" + value + "%"); + yield "t.name LIKE #{map." + key + "}"; + } + case "startTime" -> { + Date date = parseFprdDate(value); + if (date == null) { + yield ""; + } + paramMap.put(key, date); + yield "t.tm >= #{map." + key + "}"; + } + case "endTime" -> { + Date date = parseFprdDate(value); + if (date == null) { + yield ""; + } + paramMap.put(key, date); + yield "t.tm <= #{map." + key + "}"; + } + case "tm" -> { + Date date = parseFprdDate(value); + if (date == null) { + yield ""; + } + paramMap.put(key, date); + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + yield switch (operator) { + case "gte" -> "t.tm >= #{map." + key + "}"; + case "lte" -> "t.tm <= #{map." + key + "}"; + case "gt" -> "t.tm > #{map." + key + "}"; + case "lt" -> "t.tm < #{map." + key + "}"; + default -> "t.tm = #{map." + key + "}"; + }; + } + default -> ""; + }; + } + + private String buildFprdDetailOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return " ORDER BY t.tm DESC"; + } + List orderParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + String column = switch (sort.getField()) { + case "stcd" -> "t.stcd"; + case "stnm" -> "t.stnm"; + case "tm" -> "t.tm"; + case "name" -> "t.name"; + case "num" -> "t.num"; + case "fsz" -> "t.fsz"; + case "weight" -> "t.weight"; + default -> ""; + }; + if (StrUtil.isBlank(column)) { + continue; + } + orderParts.add(column + ("desc".equalsIgnoreCase(sort.getDir()) ? " DESC" : " ASC")); + } + return orderParts.isEmpty() ? " ORDER BY t.tm DESC" : " ORDER BY " + String.join(", ", orderParts); + } + + private Date parseFprdDate(Object value) { + if (value == null) { + return null; + } + if (value instanceof Date date) { + return date; + } + String text = String.valueOf(value); + if (StrUtil.isBlank(text)) { + return null; + } + if (text.length() == 10) { + return DateUtil.parse(text, "yyyy-MM-dd"); + } + if (text.length() == 16) { + return DateUtil.parse(text, "yyyy-MM-dd HH:mm"); + } + return DateUtil.parse(text, "yyyy-MM-dd HH:mm:ss"); + } + private void validateFprdRunDataAo(FprdRunDataAo ao) { if (ao == null) { throw new BizException("请求参数不能为空."); @@ -519,6 +685,7 @@ public class FprMonitorServiceImpl implements FprMonitorService { "NVL(src.IS_DELETED, 0) AS isDeleted, " + "CASE WHEN rel.ZY_FISH_ID IS NULL THEN src.ID ELSE rel.ZY_FISH_ID END AS zyFishId, " + "CASE WHEN rel.RVCD IS NULL THEN 'null' ELSE rel.RVCD END AS rvcd, " + + "rv.RVNM AS rvcdName, " + "src.NAME AS name, " + "src.TYPE AS type, " + "src.FAMILY AS family, " + @@ -549,15 +716,108 @@ public class FprMonitorServiceImpl implements FprMonitorService { "src.LOGO AS logo, " + "src.INFFILE AS inffile, " + "src.ORDERS, \n" + - "src.VLSR, \n"+ + "src.VLSR AS vlsr, \n" + + "src.VLSR_TM AS vlsrTm, \n" + "src.SPAWN_MONTH AS spawnMonth " + "FROM SD_FISHDICTORY_B src " + "LEFT JOIN SD_FISHDICTORY_RLTN_B rel ON src.ID = rel.ZY_FISH_ID " + " AND rel.RVCD <> 'ZY' " + " AND NVL(rel.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = rel.RVCD " + "WHERE NVL(src.IS_DELETED, 0) = 0 "; } + private String buildZyFishDicSummarySql() { + return "SELECT " + + "src.ID AS id, " + + "NVL(src.IS_DELETED, 0) AS isDeleted, " + + "src.ID AS zyFishId, " + + "NVL(relAgg.rvcd, 'null') AS rvcd, " + + "NVL(relAgg.rvcdName, '') AS rvcdName, " + + "src.NAME AS name, " + + "src.TYPE AS type, " + + "src.FAMILY AS family, " + + "src.GENUS AS genus, " + + "src.SPECIES AS species, " + + "src.NAME_EN AS nameEn, " + + "src.ALIAS AS alias, " + + "src.FSZ AS fsz, " + + "src.SHAPEDESC AS shapedesc, " + + "src.HABITATION AS habitation, " + + "src.HABIT_MIGRAT AS habitMigrat, " + + "src.FEEDING_HABIT AS feedingHabit, " + + "src.FOOD AS food, " + + "src.TIME_FEED AS timeFeed, " + + "src.ORIGN_DATE AS orignDate, " + + "CAST(NULL AS VARCHAR2(255)) AS filterContent, " + + "src.PRETEMP AS pretemp, " + + "src.FLOW_RATE AS flowRate, " + + "src.DEPTH AS depth, " + + "src.WQTQ AS wqtq, " + + "src.SPAWN_CHARACT AS spawnCharact, " + + "src.BOTM_MATER AS botmMater, " + + "src.PTYPE AS ptype, " + + "CASE src.PTYPE WHEN 1 THEN '濒危' WHEN 2 THEN '极危' WHEN 3 THEN '近危' WHEN 4 THEN '易危' WHEN 5 THEN '重点保护' WHEN 6 THEN '无危' WHEN 7 THEN '国家二级' WHEN 8 THEN '市二级保护' ELSE '未知' END AS ptypeName, " + + "src.SPEC_ORIGIN AS specOrigin, " + + "CASE WHEN src.SPEC_ORIGIN = 1 THEN '本土物种' WHEN src.SPEC_ORIGIN = 2 THEN '外来物种' ELSE NULL END AS specOriginName, " + + "src.DESCRIPTION AS description, " + + "src.LOGO AS logo, " + + "src.INFFILE AS inffile, " + + "src.ORDERS, " + + "src.VLSR AS vlsr, " + + "src.VLSR_TM AS vlsrTm, " + + "src.SPAWN_MONTH AS spawnMonth " + + "FROM SD_FISHDICTORY_B src " + + "LEFT JOIN ( " + + " SELECT relBase.ZY_FISH_ID AS zyFishId, " + + " MIN(relBase.RVCD) AS rvcd, " + + " LISTAGG(relBase.RVNM, ',') WITHIN GROUP (ORDER BY relBase.RVNM) AS rvcdName " + + " FROM ( " + + " SELECT DISTINCT rel.ZY_FISH_ID, rel.RVCD, rv.RVNM " + + " FROM SD_FISHDICTORY_RLTN_B rel " + + " LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = rel.RVCD " + + " WHERE rel.RVCD <> 'ZY' " + + " AND NVL(rel.IS_DELETED, 0) = 0 " + + " AND rv.RVNM IS NOT NULL " + + " ) relBase " + + " GROUP BY relBase.ZY_FISH_ID " + + ") relAgg ON relAgg.zyFishId = src.ID " + + "WHERE NVL(src.IS_DELETED, 0) = 0 "; + } + + private void fillZyFishRvcdNames(List list, String rvcdFilter) { + if (CollUtil.isEmpty(list)) { + return; + } + if (StrUtil.isNotBlank(rvcdFilter)) { + for (FprZyFishDicVo item : list) { + if (item != null && StrUtil.isBlank(item.getRvcdName()) && StrUtil.isNotBlank(item.getRvcd()) && !"null".equalsIgnoreCase(item.getRvcd())) { + item.setRvcdName(querySingleRvcdName(item.getRvcd())); + } + } + return; + } + for (FprZyFishDicVo item : list) { + if (item != null && item.getRvcdName() == null) { + item.setRvcdName(""); + } + } + } + + private String querySingleRvcdName(String rvcd) { + Map paramMap = new HashMap<>(); + paramMap.put("rvcd", rvcd); + List> rows = microservicDynamicSQLMapper.getAllList( + "SELECT RVNM AS rvcdName FROM SD_RVCD_DIC WHERE RVCD = #{map.rvcd} AND ROWNUM = 1", + paramMap + ); + if (CollUtil.isEmpty(rows)) { + return null; + } + Object value = rows.get(0).get("RVCDNAME"); + return value == null ? null : String.valueOf(value); + } + private String buildMsstbprptDetailSelectSql(List selectFields) { LinkedHashMap columnMap = buildMsstbprptSelectColumnMap(); if (CollUtil.isEmpty(selectFields)) { @@ -1164,6 +1424,7 @@ public class FprMonitorServiceImpl implements FprMonitorService { case "isDeleted" -> "t.isDeleted"; case "zyFishId" -> "t.zyFishId"; case "rvcd" -> "t.rvcd"; + case "rvcdName" -> "t.rvcdName"; case "name" -> "t.name"; case "type" -> "t.type"; case "family" -> "t.family"; @@ -1192,26 +1453,33 @@ public class FprMonitorServiceImpl implements FprMonitorService { case "logo" -> "t.logo"; case "inffile" -> "t.inffile"; case "spawnMonth" -> "t.spawnMonth"; + case "orders" -> "t.orders"; + case "vlsr" -> "t.vlsr"; + case "vlsrTm" -> "t.vlsrTm"; default -> null; }; } - private List paginateZyFishDicList(List resultList, DataSourceLoadOptionsBase loadOptions) { - if (CollUtil.isEmpty(resultList) || loadOptions == null || loadOptions.getTake() == null || loadOptions.getTake() <= 0) { - return resultList; + private String buildZyFishDicOrderBySql(List sorts) { + List orderItems = new ArrayList<>(); + if (CollUtil.isNotEmpty(sorts)) { + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapZyFishDicColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) || "des".equalsIgnoreCase(sort.getDir()) + ? "DESC" : "ASC"; + orderItems.add(column + " " + direction + " NULLS LAST"); + } } - int page = loadOptions.getSkip() == null ? 1 : loadOptions.getSkip(); // 页码从1开始,缺省为1 - // 如果页码 ≤ 0,强制设为1(避免负值) - if (page < 1) { - page = 1; + if (orderItems.isEmpty()) { + return " ORDER BY t.rvcd ASC NULLS LAST, t.name ASC"; } - int size = loadOptions.getTake(); - int start = (page - 1) * size; - int end = Math.min(start + size, resultList.size()); - if (start >= resultList.size()) { - return new ArrayList<>(); - } - return new ArrayList<>(resultList.subList(start, end)); + return " ORDER BY " + String.join(", ", orderItems); } private String formatSpawnMonth(String input) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/overview/controller/OverviewController.java b/backend/src/main/java/com/yfd/platform/qgc_env/overview/controller/OverviewController.java new file mode 100644 index 00000000..a3ed0a61 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/overview/controller/OverviewController.java @@ -0,0 +1,35 @@ +package com.yfd.platform.qgc_env.overview.controller; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.qgc_env.overview.service.OverviewService; +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("/overview") +@Tag(name = "首页概览") +@Validated +public class OverviewController { + + @Resource + private OverviewService overviewService; + + @PostMapping("/msstbprpt/GetKendoList") + @Operation(summary = "首页基础设施概览列表") + public ResponseResult getMsstbprptList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(overviewService.getMsstbprptList(dataSourceRequest)); + } + + @PostMapping("/oped/GetKendoListCust") + @Operation(summary = "首页环保设施运行状况明细") + public ResponseResult getOpedList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(overviewService.getOpedList(dataSourceRequest)); + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/overview/entity/vo/OverviewMsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/overview/entity/vo/OverviewMsstbprptVo.java new file mode 100644 index 00000000..effa1e33 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/overview/entity/vo/OverviewMsstbprptVo.java @@ -0,0 +1,72 @@ +package com.yfd.platform.qgc_env.overview.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@Data +@Schema(description = "首页基础设施概览列表") +public class OverviewMsstbprptVo implements Serializable { + + private static final long serialVersionUID = 1L; + + private String id; + private String stcd; + private String stnm; + private String sttp; + private String sttpCode; + private String sttpName; + private String sttpFullPath; + private Integer sttpTreeLevel; + private String blprdId; + private Double lgtd; + private Double lttd; + private Double dtmel; + private String stlc; + private Integer usfl; + private String rstcd; + private String ennm; + private String baseId; + private String baseName; + private String hbrvcd; + private String hbrvcdName; + private String rvcd; + private String rvcdName; + private String addvcd; + private String addvcdName; + private String country; + private String countryName; + private String stCode; + private String stName; + private Date stdsdt; + private Date pststdt; + private Date pesstdt; + private Date ststdt; + private Date jcdt; + private Date stwddt; + private String introduce; + private String precis; + private String logo; + private String inffile; + private Integer dtin; + private String dtinName; + private Date dtinTm; + private Integer bldsttCode; + private String bldsttCcode; + private String bldsttCcodeName; + private Double inv; + private Integer invinmn; + private String dsun; + private String jbtxcs; + private Integer dtfrqcy; + private String remark; + private String vlsr; + private Date vlsrTm; + private Integer orderIndex; + private Integer baseStepSort; + private Integer rvcdStepSort; + private Integer rstcdStepSort; + private Integer siteStepSort; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/overview/entity/vo/OverviewOpedVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/overview/entity/vo/OverviewOpedVo.java new file mode 100644 index 00000000..67a71e8a --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/overview/entity/vo/OverviewOpedVo.java @@ -0,0 +1,65 @@ +package com.yfd.platform.qgc_env.overview.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +@Data +@Schema(description = "首页环保设施运行状况明细") +public class OverviewOpedVo implements Serializable { + + private static final long serialVersionUID = 1L; + + private Map _tls = new HashMap<>(); + + private String id; + private String recordUser; + private Date recordTime; + private Date modifyTime; + private String displayRecordUser; + private String repCode; + private String pcode; + private String pname; + private String psttpName; + private String sttpName; + private String baseId; + private String stcd; + private String stnm; + private String sttpCode; + private String baseName; + private String rstcd; + private String ennm; + private String bldsttCcode; + private String bldsttCcodeName; + private Date dtinTm; + private Integer dtin; + private String dtinName; + private Integer runState; + private String runStateName; + private Integer stdState; + private String stdStateName; + private Integer stdSstate; + private String stdSstateName; + private Integer runSstate; + private String runSstateName; + private Integer mway; + private String mwayName; + private String hbrvcd; + private String hbrvcdName; + private String addvcdName; + private String rvcdName; + private Integer baseStepSort; + private Integer baseStepsort; + private Integer rvcdStepSort; + private Integer rstcdStepSort; + private Integer rstcdStepsort; + private Integer siteStepSort; + private Integer count; + private Date jcdt; + private String departmentId; + private String displayDepartment; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/overview/service/OverviewService.java b/backend/src/main/java/com/yfd/platform/qgc_env/overview/service/OverviewService.java new file mode 100644 index 00000000..481e665f --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/overview/service/OverviewService.java @@ -0,0 +1,13 @@ +package com.yfd.platform.qgc_env.overview.service; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.qgc_env.overview.entity.vo.OverviewMsstbprptVo; +import com.yfd.platform.qgc_env.overview.entity.vo.OverviewOpedVo; + +public interface OverviewService { + + DataSourceResult getMsstbprptList(DataSourceRequest dataSourceRequest); + + DataSourceResult getOpedList(DataSourceRequest dataSourceRequest); +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/overview/service/impl/OverviewServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/overview/service/impl/OverviewServiceImpl.java new file mode 100644 index 00000000..79ec09ab --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/overview/service/impl/OverviewServiceImpl.java @@ -0,0 +1,1343 @@ +package com.yfd.platform.qgc_env.overview.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.common.DataSourceLoadOptionsBase; +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.common.GroupHelper; +import com.yfd.platform.common.GroupingInfo; +import com.yfd.platform.common.MicroservicDynamicSQLMapper; +import com.yfd.platform.qgc_env.overview.entity.vo.OverviewMsstbprptVo; +import com.yfd.platform.qgc_env.overview.entity.vo.OverviewOpedVo; +import com.yfd.platform.qgc_env.overview.service.OverviewService; +import com.yfd.platform.utils.QgcQueryWrapperUtil; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.time.Year; + +@Service +public class OverviewServiceImpl implements OverviewService { + + @Resource + private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; + + @Override + public DataSourceResult getMsstbprptList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + List selectFields = resolveSelectFields(dataSourceRequest == null ? null : dataSourceRequest.getSelect()); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildSelectSql(selectFields)) + .append(" FROM (") + .append(buildBaseSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = buildFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql); + } + sql.append(buildOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, sql.toString(), paramMap, OverviewMsstbprptVo.class + ); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page == null ? list.size() : page.getTotal()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + @SuppressWarnings("unchecked") + public DataSourceResult getOpedList(DataSourceRequest dataSourceRequest) { + DataSourceResult result = new DataSourceResult<>(); + result.setAggregates(new HashMap<>()); + if (dataSourceRequest == null) { + result.setData(new ArrayList<>()); + result.setTotal(0L); + return result; + } + + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + Map paramMap = new HashMap<>(); + paramMap.put("stateYear", resolveOpedStateYear()); + if (shouldQueryOpedSummary(dataSourceRequest)) { + return queryOpedSummaryList(dataSourceRequest, loadOptions, paramMap); + } + + String filterSql = buildOpedFilterCondition(dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (CollUtil.isNotEmpty(dataSourceRequest.getGroup())) { + GroupingInfo[] groupInfos = loadOptions == null ? null : loadOptions.getGroup(); + String groupSql = buildOpedGroupSql(buildOpedDetailSql(null, filterSql), groupInfos); + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List> rows = microservicDynamicSQLMapper.pageAllList(page, groupSql, paramMap); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal(0L); + return result; + } + + String sql = buildOpedDetailSql(dataSourceRequest.getSelect(), filterSql) + + buildOpedOrderBySql(dataSourceRequest.getSort()); + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, sql, paramMap, OverviewOpedVo.class + ); + result.setData(list); + result.setTotal(page == null ? list.size() : page.getTotal()); + return result; + } + + private DataSourceResult queryOpedSummaryList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions, + Map paramMap) { + String effectiveFilterSql = buildOpedEffectiveFilterCondition(dataSourceRequest.getFilter(), paramMap, new int[]{0}); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildOpedSummarySelectSql(dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildOpedCategorySql()) + .append(") cat ") + .append("LEFT JOIN (SELECT * FROM (") + .append(buildOpedBaseSql()) + .append(") t WHERE 1 = 1 "); + if (StrUtil.isNotBlank(effectiveFilterSql)) { + sql.append(" AND ").append(effectiveFilterSql); + } + sql.append(") src ON cat.repCode = src.repCode ") + .append("GROUP BY cat.repCode, cat.sttpName, cat.orderIndex ") + .append(buildOpedSummaryOrderBySql(dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, sql.toString(), paramMap, OverviewOpedVo.class + ); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page == null ? list.size() : page.getTotal()); + result.setAggregates(new HashMap<>()); + return result; + } + + private String buildBaseSql() { + return buildFbSql() + " UNION ALL " + buildDwSql() + " UNION ALL " + buildFpSql(); + } + + private String buildFbSql() { + return "SELECT " + + "fb.STCD AS id, " + + "fb.STCD AS stcd, " + + "fb.STNM AS stnm, " + + "fb.STTP AS sttp, " + + "fb.STTP AS sttpCode, " + + "sttp.STTP_NAME AS sttpName, " + + "sttp.FULL_PATH AS sttpFullPath, " + + "sttp.TREE_LEVEL AS sttpTreeLevel, " + + "CAST(fb.BLPRD AS VARCHAR2(64)) AS blprdId, " + + "fb.LGTD AS lgtd, " + + "fb.LTTD AS lttd, " + + "fb.ELEV AS dtmel, " + + "fb.STLC AS stlc, " + + "fb.USFL AS usfl, " + + "fb.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "NVL(fb.BASE_ID, eng.BASE_ID) AS baseId, " + + "hb.BASENAME AS baseName, " + + "NVL(fb.HBRVCD, eng.HBRVCD) AS hbrvcd, " + + "hbrv.HBRVNM AS hbrvcdName, " + + "eng.RVCD AS rvcd, " + + "rv.RVNM AS rvcdName, " + + "eng.ADDVCD AS addvcd, " + + "addv.ADDVNM AS addvcdName, " + + "eng.COUNTRY AS country, " + + "country.COUNTRY_NAME AS countryName, " + + "CAST(NULL AS VARCHAR2(64)) AS stCode, " + + "CAST(NULL AS VARCHAR2(200)) AS stName, " + + "fb.STDSDT AS stdsdt, " + + "fb.PSTSTDT AS pststdt, " + + "fb.PESSTDT AS pesstdt, " + + "fb.SWDT AS ststdt, " + + "fb.JCDT AS jcdt, " + + "fb.WDDT AS stwddt, " + + "fb.INTRODUCE AS introduce, " + + "fb.INTRODUCE AS precis, " + + "fb.LOGO AS logo, " + + "fb.INFFILE AS inffile, " + + "fb.DTIN AS dtin, " + + "CASE WHEN NVL(fb.DTIN, 0) = 1 THEN '已接入' ELSE '未接入' END AS dtinName, " + + "fb.DTIN_TM AS dtinTm, " + + "fb.BLDSTT_CODE AS bldsttCode, " + + "CASE fb.BLDSTT_CODE WHEN 0 THEN '0' WHEN 1 THEN '1' WHEN 2 THEN '2' ELSE NULL END AS bldsttCcode, " + + "CASE fb.BLDSTT_CODE WHEN 0 THEN '未建/规划' WHEN 1 THEN '在建' WHEN 2 THEN '已建' ELSE NULL END AS bldsttCcodeName, " + + "fb.INV AS inv, " + + "fb.INVINMN AS invinmn, " + + "fb.DSUN AS dsun, " + + "fb.JBTXCS AS jbtxcs, " + + "fb.DTFRQCY AS dtfrqcy, " + + "fb.REMARK AS remark, " + + "fb.VLSR AS vlsr, " + + "fb.VLSR_TM AS vlsrTm, " + + "fb.ORDER_INDEX AS orderIndex, " + + "NVL(hb.ORDER_INDEX, 999999) AS baseStepSort, " + + "NVL(hbrv.ORDER_INDEX, 999999) AS rvcdStepSort, " + + "NVL(eng.ORDER_INDEX, 999999) AS rstcdStepSort, " + + "NVL(fb.ORDER_INDEX, 999999) AS siteStepSort " + + "FROM SD_FBRD_B_H fb " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = fb.STTP AND NVL(sttp.ENABLE, 1) = 1 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fb.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = NVL(fb.BASE_ID, eng.BASE_ID) AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = NVL(fb.HBRVCD, eng.HBRVCD) AND hbrv.BASEID = NVL(fb.BASE_ID, eng.BASE_ID) " + + " AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 " + + "LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = eng.RVCD " + + "LEFT JOIN SD_ADDVCD_DIC addv ON addv.ADDVCD = eng.ADDVCD " + + "LEFT JOIN SD_COUNTRY_B country ON country.COUNTRY_ID = eng.COUNTRY AND NVL(country.ENABLED, 1) = 1 "; + } + + private String buildDwSql() { + return "SELECT " + + "dw.STCD AS id, " + + "dw.STCD AS stcd, " + + "dw.STNM AS stnm, " + + "dw.STTP AS sttp, " + + "dw.STTP AS sttpCode, " + + "sttp.STTP_NAME AS sttpName, " + + "sttp.FULL_PATH AS sttpFullPath, " + + "sttp.TREE_LEVEL AS sttpTreeLevel, " + + "CAST(NULL AS VARCHAR2(64)) AS blprdId, " + + "dw.LGTD AS lgtd, " + + "dw.LTTD AS lttd, " + + "dw.ELEV AS dtmel, " + + "dw.STLC AS stlc, " + + "dw.USFL AS usfl, " + + "dw.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "NVL(dw.BASE_ID, eng.BASE_ID) AS baseId, " + + "hb.BASENAME AS baseName, " + + "NVL(dw.HBRVCD, eng.HBRVCD) AS hbrvcd, " + + "hbrv.HBRVNM AS hbrvcdName, " + + "eng.RVCD AS rvcd, " + + "rv.RVNM AS rvcdName, " + + "eng.ADDVCD AS addvcd, " + + "addv.ADDVNM AS addvcdName, " + + "eng.COUNTRY AS country, " + + "country.COUNTRY_NAME AS countryName, " + + "CAST(NULL AS VARCHAR2(64)) AS stCode, " + + "CAST(NULL AS VARCHAR2(200)) AS stName, " + + "dw.STDSDT AS stdsdt, " + + "dw.PSTSTDT AS pststdt, " + + "dw.PESSTDT AS pesstdt, " + + "dw.SWDT AS ststdt, " + + "dw.JCDT AS jcdt, " + + "dw.WDDT AS stwddt, " + + "dw.INTRODUCE AS introduce, " + + "dw.INTRODUCE AS precis, " + + "dw.LOGO AS logo, " + + "dw.INFFILE AS inffile, " + + "dw.DTIN AS dtin, " + + "CASE WHEN NVL(dw.DTIN, 0) = 1 THEN '已接入' ELSE '未接入' END AS dtinName, " + + "dw.DTIN_TM AS dtinTm, " + + "dw.BLDSTT_CODE AS bldsttCode, " + + "CASE dw.BLDSTT_CODE WHEN 0 THEN '0' WHEN 1 THEN '1' WHEN 2 THEN '2' ELSE NULL END AS bldsttCcode, " + + "CASE dw.BLDSTT_CODE WHEN 0 THEN '未建/规划' WHEN 1 THEN '在建' WHEN 2 THEN '已建' ELSE NULL END AS bldsttCcodeName, " + + "dw.INV AS inv, " + + "dw.INVINMN AS invinmn, " + + "CAST(NULL AS VARCHAR2(500)) AS dsun, " + + "dw.QTSSJBTX AS jbtxcs, " + + "dw.DTFRQCY AS dtfrqcy, " + + "dw.REMARK AS remark, " + + "dw.VLSR AS vlsr, " + + "dw.VLSR_TM AS vlsrTm, " + + "dw.ORDER_INDEX AS orderIndex, " + + "NVL(hb.ORDER_INDEX, 999999) AS baseStepSort, " + + "NVL(hbrv.ORDER_INDEX, 999999) AS rvcdStepSort, " + + "NVL(eng.ORDER_INDEX, 999999) AS rstcdStepSort, " + + "NVL(dw.ORDER_INDEX, 999999) AS siteStepSort " + + "FROM SD_DW_B_H dw " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = dw.STTP AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = dw.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = NVL(dw.BASE_ID, eng.BASE_ID) AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = NVL(dw.HBRVCD, eng.HBRVCD) AND hbrv.BASEID = NVL(dw.BASE_ID, eng.BASE_ID) " + + " AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 " + + "LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = eng.RVCD " + + "LEFT JOIN SD_ADDVCD_DIC addv ON addv.ADDVCD = eng.ADDVCD " + + "LEFT JOIN SD_COUNTRY_B country ON country.COUNTRY_ID = eng.COUNTRY AND NVL(country.ENABLED, 1) = 1 " + + "WHERE NVL(dw.IS_DELETED, 0) = 0 "; + } + + private String buildFpSql() { + return "SELECT " + + "fp.STCD AS id, " + + "fp.STCD AS stcd, " + + "fp.STNM AS stnm, " + + "fp.STTP AS sttp, " + + "fp.STTP AS sttpCode, " + + "sttp.STTP_NAME AS sttpName, " + + "sttp.FULL_PATH AS sttpFullPath, " + + "sttp.TREE_LEVEL AS sttpTreeLevel, " + + "CAST(fp.BLPRD AS VARCHAR2(64)) AS blprdId, " + + "fp.LGTD AS lgtd, " + + "fp.LTTD AS lttd, " + + "fp.ELEV AS dtmel, " + + "fp.STLC AS stlc, " + + "fp.USFL AS usfl, " + + "fp.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "eng.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName, " + + "eng.HBRVCD AS hbrvcd, " + + "hbrv.HBRVNM AS hbrvcdName, " + + "eng.RVCD AS rvcd, " + + "rv.RVNM AS rvcdName, " + + "eng.ADDVCD AS addvcd, " + + "addv.ADDVNM AS addvcdName, " + + "eng.COUNTRY AS country, " + + "country.COUNTRY_NAME AS countryName, " + + "CAST(NULL AS VARCHAR2(64)) AS stCode, " + + "CAST(NULL AS VARCHAR2(200)) AS stName, " + + "fp.STDSDT AS stdsdt, " + + "fp.PSTSTDT AS pststdt, " + + "fp.PESSTDT AS pesstdt, " + + "fp.SWDT AS ststdt, " + + "fp.JCDT AS jcdt, " + + "fp.WDDT AS stwddt, " + + "fp.INTRODUCE AS introduce, " + + "fp.INTRODUCE AS precis, " + + "fp.LOGO AS logo, " + + "fp.INFFILE AS inffile, " + + "fp.DTIN AS dtin, " + + "CASE WHEN NVL(fp.DTIN, 0) = 1 THEN '已接入' ELSE '未接入' END AS dtinName, " + + "fp.DTIN_TM AS dtinTm, " + + "fp.BLDSTT_CODE AS bldsttCode, " + + "CASE fp.BLDSTT_CODE WHEN 0 THEN '0' WHEN 1 THEN '1' WHEN 2 THEN '2' ELSE NULL END AS bldsttCcode, " + + "CASE fp.BLDSTT_CODE WHEN 0 THEN '未建/规划' WHEN 1 THEN '在建' WHEN 2 THEN '已建' ELSE NULL END AS bldsttCcodeName, " + + "fp.INV AS inv, " + + "fp.INVINMN AS invinmn, " + + "CAST(NULL AS VARCHAR2(500)) AS dsun, " + + "fp.JBTXCS AS jbtxcs, " + + "fp.DTFRQCY AS dtfrqcy, " + + "fp.REMARK AS remark, " + + "fp.VLSR AS vlsr, " + + "fp.VLSR_TM AS vlsrTm, " + + "fp.ORDER_INDEX AS orderIndex, " + + "NVL(hb.ORDER_INDEX, 999999) AS baseStepSort, " + + "NVL(hbrv.ORDER_INDEX, 999999) AS rvcdStepSort, " + + "NVL(eng.ORDER_INDEX, 999999) AS rstcdStepSort, " + + "NVL(fp.ORDER_INDEX, 999999) AS siteStepSort " + + "FROM SD_FPSS_B_H fp " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fp.RSTCD " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eng.HBRVCD AND hbrv.BASEID = eng.BASE_ID " + + " AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = fp.STTP AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 " + + "LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = eng.RVCD " + + "LEFT JOIN SD_ADDVCD_DIC addv ON addv.ADDVCD = eng.ADDVCD " + + "LEFT JOIN SD_COUNTRY_B country ON country.COUNTRY_ID = eng.COUNTRY AND NVL(country.ENABLED, 1) = 1 "; + } + + private List resolveSelectFields(List select) { + List fields = CollUtil.isEmpty(select) + ? new ArrayList<>(buildSelectMap().keySet()) + : new ArrayList<>(select); + LinkedHashSet uniqueFields = new LinkedHashSet<>(); + for (String field : fields) { + if (StrUtil.isNotBlank(field)) { + uniqueFields.add(field.trim()); + } + } + if (uniqueFields.isEmpty()) { + uniqueFields.add("stcd"); + } + return new ArrayList<>(uniqueFields); + } + + private String buildSelectSql(List selectFields) { + Map columnMap = buildSelectMap(); + List selectParts = new ArrayList<>(); + for (String field : selectFields) { + String column = columnMap.get(field); + if (StrUtil.isNotBlank(column)) { + selectParts.add(column); + } else { + selectParts.add("NULL AS \"" + field + "\""); + } + } + if (selectParts.isEmpty()) { + selectParts.add("t.stcd AS \"stcd\""); + } + return String.join(", ", selectParts); + } + + private Map buildSelectMap() { + Map columnMap = new LinkedHashMap<>(); + columnMap.put("id", "t.id AS \"id\""); + columnMap.put("stcd", "t.stcd AS \"stcd\""); + columnMap.put("stnm", "t.stnm AS \"stnm\""); + columnMap.put("sttp", "t.sttp AS \"sttp\""); + columnMap.put("sttpCode", "t.sttpCode AS \"sttpCode\""); + columnMap.put("sttpName", "t.sttpName AS \"sttpName\""); + columnMap.put("sttpFullPath", "t.sttpFullPath AS \"sttpFullPath\""); + columnMap.put("sttpTreeLevel", "t.sttpTreeLevel AS \"sttpTreeLevel\""); + columnMap.put("blprdId", "t.blprdId AS \"blprdId\""); + columnMap.put("lgtd", "t.lgtd AS \"lgtd\""); + columnMap.put("lttd", "t.lttd AS \"lttd\""); + columnMap.put("dtmel", "t.dtmel AS \"dtmel\""); + columnMap.put("stlc", "t.stlc AS \"stlc\""); + columnMap.put("usfl", "t.usfl AS \"usfl\""); + columnMap.put("rstcd", "t.rstcd AS \"rstcd\""); + columnMap.put("ennm", "t.ennm AS \"ennm\""); + columnMap.put("baseId", "t.baseId AS \"baseId\""); + columnMap.put("baseName", "t.baseName AS \"baseName\""); + columnMap.put("hbrvcd", "t.hbrvcd AS \"hbrvcd\""); + columnMap.put("hbrvcdName", "t.hbrvcdName AS \"hbrvcdName\""); + columnMap.put("rvcd", "t.rvcd AS \"rvcd\""); + columnMap.put("rvcdName", "t.rvcdName AS \"rvcdName\""); + columnMap.put("addvcd", "t.addvcd AS \"addvcd\""); + columnMap.put("addvcdName", "t.addvcdName AS \"addvcdName\""); + columnMap.put("country", "t.country AS \"country\""); + columnMap.put("countryName", "t.countryName AS \"countryName\""); + columnMap.put("stCode", "t.stCode AS \"stCode\""); + columnMap.put("stName", "t.stName AS \"stName\""); + columnMap.put("stdsdt", "t.stdsdt AS \"stdsdt\""); + columnMap.put("pststdt", "t.pststdt AS \"pststdt\""); + columnMap.put("pesstdt", "t.pesstdt AS \"pesstdt\""); + columnMap.put("ststdt", "t.ststdt AS \"ststdt\""); + columnMap.put("jcdt", "t.jcdt AS \"jcdt\""); + columnMap.put("stwddt", "t.stwddt AS \"stwddt\""); + columnMap.put("introduce", "t.introduce AS \"introduce\""); + columnMap.put("precis", "t.precis AS \"precis\""); + columnMap.put("logo", "t.logo AS \"logo\""); + columnMap.put("inffile", "t.inffile AS \"inffile\""); + columnMap.put("dtin", "t.dtin AS \"dtin\""); + columnMap.put("dtinName", "t.dtinName AS \"dtinName\""); + columnMap.put("dtinTm", "t.dtinTm AS \"dtinTm\""); + columnMap.put("bldsttCode", "t.bldsttCode AS \"bldsttCode\""); + columnMap.put("bldsttCcode", "t.bldsttCcode AS \"bldsttCcode\""); + columnMap.put("bldsttCcodeName", "t.bldsttCcodeName AS \"bldsttCcodeName\""); + columnMap.put("inv", "t.inv AS \"inv\""); + columnMap.put("invinmn", "t.invinmn AS \"invinmn\""); + columnMap.put("dsun", "t.dsun AS \"dsun\""); + columnMap.put("jbtxcs", "t.jbtxcs AS \"jbtxcs\""); + columnMap.put("dtfrqcy", "t.dtfrqcy AS \"dtfrqcy\""); + columnMap.put("remark", "t.remark AS \"remark\""); + columnMap.put("vlsr", "t.vlsr AS \"vlsr\""); + columnMap.put("vlsrTm", "t.vlsrTm AS \"vlsrTm\""); + columnMap.put("orderIndex", "t.orderIndex AS \"orderIndex\""); + columnMap.put("baseStepSort", "t.baseStepSort AS \"baseStepSort\""); + columnMap.put("rvcdStepSort", "t.rvcdStepSort AS \"rvcdStepSort\""); + columnMap.put("rstcdStepSort", "t.rstcdStepSort AS \"rstcdStepSort\""); + columnMap.put("siteStepSort", "t.siteStepSort AS \"siteStepSort\""); + return columnMap; + } + + private String buildFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String field = filter.getField(); + if (StrUtil.isBlank(field)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + String column = mapFilterColumn(field); + if (StrUtil.isBlank(column)) { + return ""; + } + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("isempty".equals(operator)) { + return "(" + column + " IS NULL OR " + column + " = '')"; + } + if ("isnotempty".equals(operator)) { + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + } + if ("in".equals(operator) || "ni".equals(operator)) { + List values = normalizeValues(filter.getValue()); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String key = "overviewP" + indexHolder[0]++; + paramMap.put(key, item); + placeholders.add("#{map." + key + "}"); + } + if (placeholders.isEmpty()) { + return ""; + } + return column + ("ni".equals(operator) ? " NOT IN (" : " IN (") + String.join(", ", placeholders) + ")"; + } + Object value = filter.getValue(); + if (value == null) { + return ""; + } + String key = "overviewP" + indexHolder[0]++; + return switch (operator) { + case "eq" -> { + paramMap.put(key, value); + yield column + " = #{map." + key + "}"; + } + case "neq" -> { + paramMap.put(key, value); + yield column + " <> #{map." + key + "}"; + } + case "contains" -> { + paramMap.put(key, "%" + value + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "doesnotcontain" -> { + paramMap.put(key, "%" + value + "%"); + yield column + " NOT LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, value + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + value); + yield column + " LIKE #{map." + key + "}"; + } + case "gt" -> { + paramMap.put(key, value); + yield column + " > #{map." + key + "}"; + } + case "gte" -> { + paramMap.put(key, value); + yield column + " >= #{map." + key + "}"; + } + case "lt" -> { + paramMap.put(key, value); + yield column + " < #{map." + key + "}"; + } + case "lte" -> { + paramMap.put(key, value); + yield column + " <= #{map." + key + "}"; + } + default -> ""; + }; + } + + private String mapFilterColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "id" -> "t.id"; + case "stcd" -> "t.stcd"; + case "stnm" -> "t.stnm"; + case "sttp" -> "t.sttp"; + case "sttpCode" -> "t.sttpCode"; + case "sttpName" -> "t.sttpName"; + case "sttpFullPath" -> "t.sttpFullPath"; + case "sttpTreeLevel" -> "t.sttpTreeLevel"; + case "blprdId" -> "t.blprdId"; + case "lgtd" -> "t.lgtd"; + case "lttd" -> "t.lttd"; + case "dtmel" -> "t.dtmel"; + case "stlc" -> "t.stlc"; + case "usfl" -> "t.usfl"; + case "rstcd" -> "t.rstcd"; + case "ennm" -> "t.ennm"; + case "baseId" -> "t.baseId"; + case "baseName" -> "t.baseName"; + case "hbrvcd" -> "t.hbrvcd"; + case "hbrvcdName" -> "t.hbrvcdName"; + case "rvcd" -> "t.rvcd"; + case "rvcdName" -> "t.rvcdName"; + case "addvcd" -> "t.addvcd"; + case "addvcdName" -> "t.addvcdName"; + case "country" -> "t.country"; + case "countryName" -> "t.countryName"; + case "stCode" -> "t.stCode"; + case "stName" -> "t.stName"; + case "introduce" -> "t.introduce"; + case "precis" -> "t.precis"; + case "logo" -> "t.logo"; + case "inffile" -> "t.inffile"; + case "dtin" -> "t.dtin"; + case "dtinName" -> "t.dtinName"; + case "dtinTm" -> "t.dtinTm"; + case "bldsttCode" -> "t.bldsttCode"; + case "bldsttCcode" -> "t.bldsttCcode"; + case "bldsttCcodeName" -> "t.bldsttCcodeName"; + case "inv" -> "t.inv"; + case "invinmn" -> "t.invinmn"; + case "dsun" -> "t.dsun"; + case "jbtxcs" -> "t.jbtxcs"; + case "dtfrqcy" -> "t.dtfrqcy"; + case "remark" -> "t.remark"; + case "vlsr" -> "t.vlsr"; + case "vlsrTm" -> "t.vlsrTm"; + case "orderIndex" -> "t.orderIndex"; + case "baseStepSort" -> "t.baseStepSort"; + case "rvcdStepSort" -> "t.rvcdStepSort"; + case "rstcdStepSort" -> "t.rstcdStepSort"; + case "siteStepSort" -> "t.siteStepSort"; + case "stdsdt" -> "t.stdsdt"; + case "pststdt" -> "t.pststdt"; + case "pesstdt" -> "t.pesstdt"; + case "ststdt" -> "t.ststdt"; + case "jcdt" -> "t.jcdt"; + case "stwddt" -> "t.stwddt"; + default -> null; + }; + } + + private String buildOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY t.baseStepSort ASC, t.rvcdStepSort ASC, t.rstcdStepSort ASC, t.siteStepSort ASC, t.stnm ASC"; + } + List orderItems = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sortList) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapFilterColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sort.getDir()) || "des".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderItems.add(column + " " + dir + " NULLS LAST"); + } + if (orderItems.isEmpty()) { + return " ORDER BY t.baseStepSort ASC, t.rvcdStepSort ASC, t.rstcdStepSort ASC, t.siteStepSort ASC, t.stnm ASC"; + } + return " ORDER BY " + String.join(", ", orderItems); + } + + private Integer resolveOpedStateYear() { + return Year.now().getValue(); + } + + private String buildOpedDetailSql(List selectFields, String filterSql) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildOpedSelectSql(selectFields)) + .append(" FROM (") + .append(buildOpedBaseSql()) + .append(") t WHERE 1 = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql); + } + return sql.toString(); + } + + private String buildOpedBaseSql() { + return "SELECT " + + "src.sttpCode AS repCode, " + + "src.sttpName AS sttpName, " + + "src.baseId AS baseId, " + + "src.stcd AS stcd, " + + "src.stnm AS stnm, " + + "src.sttpCode AS sttpCode, " + + "src.baseName AS baseName, " + + "src.rstcd AS rstcd, " + + "src.ennm AS ennm, " + + "CAST(NULL AS VARCHAR2(255)) AS addvcdName, " + + "CAST(NULL AS VARCHAR2(255)) AS rvcdName, " + + "src.bldsttCcode AS bldsttCcode, " + + "src.bldsttCcodeName AS bldsttCcodeName, " + + "src.dtinTm AS dtinTm, " + + "src.dtin AS dtin, " + + "src.dtinName AS dtinName, " + + "state.RUN_STATE AS runState, " + + "CASE WHEN state.RUN_STATE = 1 THEN '运行中' " + + "WHEN state.RUN_STATE IN (0, 2) THEN '未运行' ELSE NULL END AS runStateName, " + + "state.STD_STATE AS stdState, " + + "CASE WHEN state.STD_STATE = 1 THEN '达标' " + + "WHEN state.STD_STATE = 2 THEN '无数据' " + + "WHEN state.STD_STATE IN (0, 3) THEN '未达标' ELSE NULL END AS stdStateName, " + + "state.STD_SSTATE AS stdSstate, " + + "CASE WHEN state.STD_SSTATE = 1 THEN '正常运行' " + + "WHEN state.STD_SSTATE IN (0, 2) THEN '暂无数据' " + + "WHEN state.STD_SSTATE = 3 THEN '未正常运行' ELSE NULL END AS stdSstateName, " + + "state.STD_SSTATE AS runSstate, " + + "CASE WHEN state.STD_SSTATE = 1 THEN '正常运行' " + + "WHEN state.STD_SSTATE IN (0, 2) THEN '暂无数据' " + + "WHEN state.STD_SSTATE = 3 THEN '未正常运行' ELSE NULL END AS runSstateName, " + + "CAST(NULL AS NUMBER(10)) AS mway, " + + "CAST(NULL AS VARCHAR2(32)) AS mwayName, " + + "src.hbrvcd AS hbrvcd, " + + "src.hbrvcdName AS hbrvcdName, " + + "src.baseStepSort AS baseStepSort, " + +// "src.baseStepSort AS baseStepsort, " + + "src.rvcdStepSort AS rvcdStepSort, " + + "src.rstcdStepSort AS rstcdStepSort, " + +// "src.rstcdStepSort AS rstcdStepsort, " + + "src.siteStepSort AS siteStepSort " + +// "#{map.stateYear} AS yr " + + "FROM (" + buildOpedUnionSql() + ") src " + + "LEFT JOIN MS_STSTATE_T state ON state.STCD = src.stcd " + + "AND NVL(state.IS_DELETED, 0) = 0 " + + "AND state.YR = #{map.stateYear}"; + } + + private String buildOpedUnionSql() { + return buildOpedBranchSql( + "fb.STCD", "fb.STNM", "'FB'", "child.STTP_NAME", "NVL(fb.BASE_ID, eng.BASE_ID)", + "hb.BASENAME", "fb.RSTCD", "eng.ENNM", "NVL(fb.HBRVCD, eng.HBRVCD)", "hbrv.HBRVNM", + "CAST(fb.BLDSTT_CODE AS VARCHAR2(10))", buildBldsttNameExpr("fb.BLDSTT_CODE"), "fb.DTIN_TM", "fb.DTIN", + "CASE WHEN NVL(fb.DTIN, 0) = 1 THEN '已接入' ELSE '未接入' END", + "NVL(hb.ORDER_INDEX, 999999)", "NVL(hbrv.ORDER_INDEX, 999999)", "NVL(eng.ORDER_INDEX, 999999)", "NVL(fb.ORDER_INDEX, 999999)", + "SD_FBRD_B_H fb", + "LEFT JOIN SD_STTP_B child ON child.STTP_CODE = fb.STTP AND NVL(child.IS_DELETED, 0) = 0 AND NVL(child.ENABLE, 1) = 1 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fb.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = NVL(fb.BASE_ID, eng.BASE_ID) AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = NVL(fb.HBRVCD, eng.HBRVCD) AND hbrv.BASEID = NVL(fb.BASE_ID, eng.BASE_ID) " + + "AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1", + "1 = 1" + ) + " UNION ALL " + + buildOpedBranchSql( + "vp.STCD", "vp.STNM", "'VP'", "child.STTP_NAME", "NVL(vp.BASE_ID, eng.BASE_ID)", + "hb.BASENAME", "vp.RSTCD", "eng.ENNM", "NVL(vp.HBRVCD, eng.HBRVCD)", "hbrv.HBRVNM", + "CAST(vp.BLDSTT_CODE AS VARCHAR2(10))", buildBldsttNameExpr("vp.BLDSTT_CODE"), "vp.DTIN_TM", "vp.DTIN", + "CASE WHEN NVL(vp.DTIN, 0) = 1 THEN '已接入' ELSE '未接入' END", + "NVL(hb.ORDER_INDEX, 999999)", "NVL(hbrv.ORDER_INDEX, 999999)", "NVL(eng.ORDER_INDEX, 999999)", "NVL(vp.ORDER_INDEX, 999999)", + "SD_VP_B_H vp", + "LEFT JOIN SD_STTP_B child ON child.STTP_CODE = vp.STTP AND NVL(child.IS_DELETED, 0) = 0 AND NVL(child.ENABLE, 1) = 1 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = vp.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = NVL(vp.BASE_ID, eng.BASE_ID) AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = NVL(vp.HBRVCD, eng.HBRVCD) AND hbrv.BASEID = NVL(vp.BASE_ID, eng.BASE_ID) " + + "AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1", + "NVL(vp.IS_DELETED, 0) = 0" + ) + " UNION ALL " + + buildOpedBranchSql( + "va.STCD", "va.STNM", "'VA'", "child.STTP_NAME", "NVL(va.BASE_ID, eng.BASE_ID)", + "hb.BASENAME", "va.RSTCD", "eng.ENNM", "NVL(va.HBRVCD, eng.HBRVCD)", "hbrv.HBRVNM", + "CAST(va.BLDSTT_CODE AS VARCHAR2(10))", buildBldsttNameExpr("va.BLDSTT_CODE"), "va.DTIN_TM", "va.DTIN", + "CASE WHEN NVL(va.DTIN, 0) = 1 THEN '已接入' ELSE '未接入' END", + "NVL(hb.ORDER_INDEX, 999999)", "NVL(hbrv.ORDER_INDEX, 999999)", "NVL(eng.ORDER_INDEX, 999999)", "NVL(va.ORDER_INDEX, 999999)", + "SD_VA_B_H va", + "LEFT JOIN SD_STTP_B child ON child.STTP_CODE = va.STTP AND NVL(child.IS_DELETED, 0) = 0 AND NVL(child.ENABLE, 1) = 1 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = va.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = NVL(va.BASE_ID, eng.BASE_ID) AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = NVL(va.HBRVCD, eng.HBRVCD) AND hbrv.BASEID = NVL(va.BASE_ID, eng.BASE_ID) " + + "AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1", + "NVL(va.IS_DELETED, 0) = 0" + ) + " UNION ALL " + + buildOpedBranchSql( + "fh.STCD", "fh.STNM", "'FH'", "child.STTP_NAME", "NVL(fh.BASE_ID, eng.BASE_ID)", + "hb.BASENAME", "fh.RSTCD", "eng.ENNM", "NVL(fh.HBRVCD, eng.HBRVCD)", "hbrv.HBRVNM", + "CAST(NULL AS VARCHAR2(10))", "CAST(NULL AS VARCHAR2(32))", "fh.DTIN_TM", "fh.DTIN", + "CASE WHEN NVL(fh.DTIN, 0) = 1 THEN '已接入' ELSE '未接入' END", + "NVL(hb.ORDER_INDEX, 999999)", "NVL(hbrv.ORDER_INDEX, 999999)", "NVL(eng.ORDER_INDEX, 999999)", "NVL(fh.ORDER_INDEX, 999999)", + "SD_FHBT_B_H fh", + "LEFT JOIN SD_STTP_B child ON child.STTP_CODE = 'FH' AND NVL(child.IS_DELETED, 0) = 0 AND NVL(child.ENABLE, 1) = 1 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fh.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = NVL(fh.BASE_ID, eng.BASE_ID) AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = NVL(fh.HBRVCD, eng.HBRVCD) AND hbrv.BASEID = NVL(fh.BASE_ID, eng.BASE_ID) " + + "AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1", + "NVL(fh.IS_DELETED, 0) = 0" + ) + " UNION ALL " + + buildOpedBranchSql( + "dw.STCD", "dw.STNM", "'DW'", "child.STTP_NAME", "NVL(dw.BASE_ID, eng.BASE_ID)", + "hb.BASENAME", "dw.RSTCD", "eng.ENNM", "NVL(dw.HBRVCD, eng.HBRVCD)", "hbrv.HBRVNM", + "CAST(dw.BLDSTT_CODE AS VARCHAR2(10))", buildBldsttNameExpr("dw.BLDSTT_CODE"), "dw.DTIN_TM", "dw.DTIN", + "CASE WHEN NVL(dw.DTIN, 0) = 1 THEN '已接入' ELSE '未接入' END", + "NVL(hb.ORDER_INDEX, 999999)", "NVL(hbrv.ORDER_INDEX, 999999)", "NVL(eng.ORDER_INDEX, 999999)", "NVL(dw.ORDER_INDEX, 999999)", + "SD_DW_B_H dw", + "LEFT JOIN SD_STTP_B child ON child.STTP_CODE = dw.STTP AND NVL(child.IS_DELETED, 0) = 0 AND NVL(child.ENABLE, 1) = 1 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = dw.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = NVL(dw.BASE_ID, eng.BASE_ID) AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = NVL(dw.HBRVCD, eng.HBRVCD) AND hbrv.BASEID = NVL(dw.BASE_ID, eng.BASE_ID) " + + "AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1", + "NVL(dw.IS_DELETED, 0) = 0" + ) + " UNION ALL " + + buildOpedBranchSql( + "fp.STCD", "fp.STNM", "'FP'", "child.STTP_NAME", "eng.BASE_ID", + "hb.BASENAME", "fp.RSTCD", "eng.ENNM", "eng.HBRVCD", "hbrv.HBRVNM", + "CAST(fp.BLDSTT_CODE AS VARCHAR2(10))", buildBldsttNameExpr("fp.BLDSTT_CODE"), "fp.DTIN_TM", "fp.DTIN", + "CASE WHEN NVL(fp.DTIN, 0) = 1 THEN '已接入' ELSE '未接入' END", + "NVL(hb.ORDER_INDEX, 999999)", "NVL(hbrv.ORDER_INDEX, 999999)", "NVL(eng.ORDER_INDEX, 999999)", "NVL(fp.ORDER_INDEX, 999999)", + "SD_FPSS_B_H fp", + "LEFT JOIN SD_STTP_B child ON child.STTP_CODE = fp.STTP AND NVL(child.IS_DELETED, 0) = 0 AND NVL(child.ENABLE, 1) = 1 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fp.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eng.HBRVCD AND hbrv.BASEID = eng.BASE_ID " + + "AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1", + "1 = 1 AND fp.STTP LIKE 'FP\\_%' ESCAPE '\\' " + ) + " UNION ALL " + + buildOpedBranchSql( + "eq.STCD", "eq.STNM", "'EQ'", "child.STTP_NAME", "NVL(eq.BASE_ID, eng.BASE_ID)", + "hb.BASENAME", "eq.RSTCD", "eng.ENNM", "NVL(eq.HBRVCD, eng.HBRVCD)", "hbrv.HBRVNM", + "CAST(eq.BLDSTT_CODE AS VARCHAR2(10))", buildBldsttNameExpr("eq.BLDSTT_CODE"), "eq.DTIN_TM", "eq.DTIN", + "CASE WHEN NVL(eq.DTIN, 0) = 1 THEN '已接入' ELSE '未接入' END", + "NVL(hb.ORDER_INDEX, 999999)", "NVL(hbrv.ORDER_INDEX, 999999)", "NVL(eng.ORDER_INDEX, 999999)", "NVL(eq.ORDER_INDEX, 999999)", + "SD_EQ_B_H eq", + "LEFT JOIN SD_STTP_B child ON child.STTP_CODE = eq.STTP AND NVL(child.IS_DELETED, 0) = 0 AND NVL(child.ENABLE, 1) = 1 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = eq.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = NVL(eq.BASE_ID, eng.BASE_ID) AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = NVL(eq.HBRVCD, eng.HBRVCD) AND hbrv.BASEID = NVL(eq.BASE_ID, eng.BASE_ID) " + + "AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1", + "NVL(eq.IS_DELETED, 0) = 0" + ); + } + + private String buildOpedBranchSql(String stcdExpr, + String stnmExpr, + String sttpCodeExpr, + String sttpNameExpr, + String baseIdExpr, + String baseNameExpr, + String rstcdExpr, + String ennmExpr, + String hbrvcdExpr, + String hbrvcdNameExpr, + String bldsttExpr, + String bldsttNameExpr, + String dtinTmExpr, + String dtinExpr, + String dtinNameExpr, + String baseStepSortExpr, + String rvcdStepSortExpr, + String rstcdStepSortExpr, + String siteStepSortExpr, + String fromSql, + String joinSql, + String whereSql) { + return "SELECT " + + sttpNameExpr + " AS sttpName, " + + baseIdExpr + " AS baseId, " + + stcdExpr + " AS stcd, " + + stnmExpr + " AS stnm, " + + sttpCodeExpr + " AS sttpCode, " + + baseNameExpr + " AS baseName, " + + rstcdExpr + " AS rstcd, " + + ennmExpr + " AS ennm, " + + bldsttExpr + " AS bldsttCcode, " + + bldsttNameExpr + " AS bldsttCcodeName, " + + dtinTmExpr + " AS dtinTm, " + + dtinExpr + " AS dtin, " + + dtinNameExpr + " AS dtinName, " + + hbrvcdExpr + " AS hbrvcd, " + + hbrvcdNameExpr + " AS hbrvcdName, " + + baseStepSortExpr + " AS baseStepSort, " + + rvcdStepSortExpr + " AS rvcdStepSort, " + + rstcdStepSortExpr + " AS rstcdStepSort, " + + siteStepSortExpr + " AS siteStepSort " + + "FROM " + fromSql + " " + joinSql + " WHERE " + whereSql; + } + + private String buildBldsttNameExpr(String column) { + return "CASE " + column + " WHEN 0 THEN '未建/规划' WHEN 1 THEN '在建' WHEN 2 THEN '已建' ELSE NULL END"; + } + + private List resolveOpedSelectFields(List select) { + List fields = CollUtil.isEmpty(select) + ? new ArrayList<>(buildOpedSelectMap().keySet()) + : new ArrayList<>(select); + LinkedHashSet uniqueFields = new LinkedHashSet<>(); + for (String field : fields) { + if (StrUtil.isNotBlank(field)) { + uniqueFields.add(field.trim()); + } + } + if (uniqueFields.isEmpty()) { + uniqueFields.add("stcd"); + } + return new ArrayList<>(uniqueFields); + } + + private String buildOpedSelectSql(List selectFields) { + Map columnMap = buildOpedSelectMap(); + List selectParts = new ArrayList<>(); + for (String field : resolveOpedSelectFields(selectFields)) { + String column = columnMap.get(field); + if (StrUtil.isNotBlank(column)) { + selectParts.add(column); + } else { + selectParts.add("NULL AS \"" + field + "\""); + } + } + return String.join(", ", selectParts); + } + + private Map buildOpedSelectMap() { + Map columnMap = new LinkedHashMap<>(); + columnMap.put("repCode", "t.repCode AS \"repCode\""); + columnMap.put("sttpName", "t.sttpName AS \"sttpName\""); + columnMap.put("baseId", "t.baseId AS \"baseId\""); + columnMap.put("stcd", "t.stcd AS \"stcd\""); + columnMap.put("stnm", "t.stnm AS \"stnm\""); + columnMap.put("sttpCode", "t.sttpCode AS \"sttpCode\""); + columnMap.put("baseName", "t.baseName AS \"baseName\""); + columnMap.put("rstcd", "t.rstcd AS \"rstcd\""); + columnMap.put("ennm", "t.ennm AS \"ennm\""); + columnMap.put("addvcdName", "t.addvcdName AS \"addvcdName\""); + columnMap.put("rvcdName", "t.rvcdName AS \"rvcdName\""); + columnMap.put("bldsttCcode", "t.bldsttCcode AS \"bldsttCcode\""); + columnMap.put("bldsttCcodeName", "t.bldsttCcodeName AS \"bldsttCcodeName\""); + columnMap.put("dtinTm", "t.dtinTm AS \"dtinTm\""); + columnMap.put("dtin", "t.dtin AS \"dtin\""); + columnMap.put("dtinName", "t.dtinName AS \"dtinName\""); + columnMap.put("runState", "t.runState AS \"runState\""); + columnMap.put("runStateName", "t.runStateName AS \"runStateName\""); + columnMap.put("stdState", "t.stdState AS \"stdState\""); + columnMap.put("stdStateName", "t.stdStateName AS \"stdStateName\""); + columnMap.put("stdSstate", "t.stdSstate AS \"stdSstate\""); + columnMap.put("stdSstateName", "t.stdSstateName AS \"stdSstateName\""); + columnMap.put("runSstate", "t.runSstate AS \"runSstate\""); + columnMap.put("runSstateName", "t.runSstateName AS \"runSstateName\""); + columnMap.put("mway", "t.mway AS \"mway\""); + columnMap.put("mwayName", "t.mwayName AS \"mwayName\""); + columnMap.put("hbrvcd", "t.hbrvcd AS \"hbrvcd\""); + columnMap.put("hbrvcdName", "t.hbrvcdName AS \"hbrvcdName\""); + columnMap.put("baseStepSort", "t.baseStepSort AS \"baseStepSort\""); +// columnMap.put("baseStepsort", "t.baseStepsort AS \"baseStepsort\""); + columnMap.put("rvcdStepSort", "t.rvcdStepSort AS \"rvcdStepSort\""); + columnMap.put("rstcdStepSort", "t.rstcdStepSort AS \"rstcdStepSort\""); +// columnMap.put("rstcdStepsort", "t.rstcdStepsort AS \"rstcdStepsort\""); + columnMap.put("siteStepSort", "t.siteStepSort AS \"siteStepSort\""); +// columnMap.put("yr", "t.yr AS \"yr\""); + return columnMap; + } + + private String buildOpedFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildOpedLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildOpedFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildOpedEffectiveFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + if ("1".equals(StrUtil.trim(filter.getField()))) { + return ""; + } + return buildOpedLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildOpedEffectiveFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildOpedLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String field = filter.getField(); + if (StrUtil.isBlank(field) || "yr".equals(field)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + String column = mapOpedColumn(field); + if (StrUtil.isBlank(column)) { + return ""; + } + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("isempty".equals(operator)) { + return "(" + column + " IS NULL OR " + column + " = '')"; + } + if ("isnotempty".equals(operator)) { + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + } + if ("in".equals(operator) || "ni".equals(operator)) { + List values = normalizeValues(filter.getValue()); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String key = "opedP" + indexHolder[0]++; + paramMap.put(key, item); + placeholders.add("#{map." + key + "}"); + } + return column + ("ni".equals(operator) ? " NOT IN (" : " IN (") + String.join(", ", placeholders) + ")"; + } + + Object value = filter.getValue(); + if (value == null) { + return ""; + } + String key = "opedP" + indexHolder[0]++; + boolean dateField = isOpedDateField(field); + String placeholder = dateField + ? "TO_DATE(#{map." + key + "}, 'YYYY-MM-DD HH24:MI:SS')" + : "#{map." + key + "}"; + paramMap.put(key, value); + return switch (operator) { + case "eq" -> column + " = " + placeholder; + case "neq" -> column + " <> " + placeholder; + case "contains" -> { + paramMap.put(key, "%" + value + "%"); + yield dateField + ? "TO_CHAR(" + column + ", 'YYYY-MM-DD HH24:MI:SS') LIKE #{map." + key + "}" + : column + " LIKE #{map." + key + "}"; + } + case "doesnotcontain" -> { + paramMap.put(key, "%" + value + "%"); + yield dateField + ? "TO_CHAR(" + column + ", 'YYYY-MM-DD HH24:MI:SS') NOT LIKE #{map." + key + "}" + : column + " NOT LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, value + "%"); + yield dateField + ? "TO_CHAR(" + column + ", 'YYYY-MM-DD HH24:MI:SS') LIKE #{map." + key + "}" + : column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + value); + yield dateField + ? "TO_CHAR(" + column + ", 'YYYY-MM-DD HH24:MI:SS') LIKE #{map." + key + "}" + : column + " LIKE #{map." + key + "}"; + } + case "gt" -> column + " > " + placeholder; + case "gte" -> column + " >= " + placeholder; + case "lt" -> column + " < " + placeholder; + case "lte" -> column + " <= " + placeholder; + default -> ""; + }; + } + + private boolean isOpedDateField(String field) { + return "dtinTm".equals(field); + } + + private String mapOpedColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "sttpName" -> "t.sttpName"; + case "baseId" -> "t.baseId"; + case "stcd" -> "t.stcd"; + case "stnm" -> "t.stnm"; + case "sttpCode" -> "t.sttpCode"; + case "baseName" -> "t.baseName"; + case "rstcd" -> "t.rstcd"; + case "ennm" -> "t.ennm"; + case "bldsttCcode" -> "t.bldsttCcode"; + case "bldsttCcodeName" -> "t.bldsttCcodeName"; + case "dtinTm" -> "t.dtinTm"; + case "dtin" -> "t.dtin"; + case "dtinName" -> "t.dtinName"; + case "runState" -> "t.runState"; + case "runStateName" -> "t.runStateName"; + case "stdState" -> "t.stdState"; + case "stdStateName" -> "t.stdStateName"; + case "stdSstate" -> "t.stdSstate"; + case "stdSstateName" -> "t.stdSstateName"; + case "mway" -> "t.mway"; + case "mwayName" -> "t.mwayName"; + case "hbrvcd" -> "t.hbrvcd"; + case "hbrvcdName" -> "t.hbrvcdName"; + case "baseStepSort", "baseStepsort" -> "t.baseStepSort"; + case "rvcdStepSort" -> "t.rvcdStepSort"; + case "rstcdStepSort", "rstcdStepsort" -> "t.rstcdStepSort"; + case "siteStepSort" -> "t.siteStepSort"; + case "yr" -> "t.yr"; + default -> null; + }; + } + + private String buildOpedOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY t.baseStepSort ASC NULLS LAST, t.rvcdStepSort ASC NULLS LAST, " + + "t.rstcdStepSort ASC NULLS LAST, t.siteStepSort ASC NULLS LAST, t.stnm ASC"; + } + List orderItems = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sortList) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapOpedColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sort.getDir()) || "des".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderItems.add(column + " " + dir + " NULLS LAST"); + } + if (orderItems.isEmpty()) { + return " ORDER BY t.baseStepSort ASC NULLS LAST, t.rvcdStepSort ASC NULLS LAST, " + + "t.rstcdStepSort ASC NULLS LAST, t.siteStepSort ASC NULLS LAST, t.stnm ASC"; + } + return " ORDER BY " + String.join(", ", orderItems); + } + + private String buildOpedGroupSql(String detailSql, GroupingInfo[] groupInfos) { + if (groupInfos == null || groupInfos.length == 0) { + return detailSql; + } + List groupFields = new ArrayList<>(); + List selectItems = new ArrayList<>(); + List orderItems = new ArrayList<>(); + for (GroupingInfo item : groupInfos) { + if (item == null || StrUtil.isBlank(item.getSelector())) { + continue; + } + String selector = item.getSelector(); + String column = mapOpedColumn(selector); + if (StrUtil.isBlank(column)) { + continue; + } + groupFields.add(column); + selectItems.add(column + " AS " + selector); + selectItems.add("COUNT(*) AS count_" + selector); + orderItems.add(column + (item.getDesc() ? " DESC" : " ASC")); + } + if (groupFields.isEmpty()) { + return "SELECT * FROM (" + detailSql + ") t WHERE 1 = 0"; + } + return "SELECT " + String.join(", ", selectItems) + + " FROM (" + detailSql + ") t GROUP BY " + String.join(", ", groupFields) + + " ORDER BY " + String.join(", ", orderItems); + } + + private boolean shouldQueryOpedSummary(DataSourceRequest dataSourceRequest) { + return dataSourceRequest != null + && CollUtil.isEmpty(dataSourceRequest.getGroup()) + && hasOnlyDummyFilter(dataSourceRequest.getFilter()); + } + + private boolean hasOnlyDummyFilter(DataSourceRequest.FilterDescriptor filter) { + return hasDummyField(filter) && !hasRealField(filter); + } + + private boolean hasDummyField(DataSourceRequest.FilterDescriptor filter) { + if (filter == null) { + return false; + } + if ("1".equals(StrUtil.trim(filter.getField()))) { + return true; + } + if (CollUtil.isEmpty(filter.getFilters())) { + return false; + } + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + if (hasDummyField(child)) { + return true; + } + } + return false; + } + + private boolean hasRealField(DataSourceRequest.FilterDescriptor filter) { + if (filter == null) { + return false; + } + String field = StrUtil.trim(filter.getField()); + if (StrUtil.isNotBlank(field) && !"1".equals(field)) { + return true; + } + if (CollUtil.isEmpty(filter.getFilters())) { + return false; + } + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + if (hasRealField(child)) { + return true; + } + } + return false; + } + + private String buildOpedCategorySql() { + return "SELECT 'VA' AS repCode, '动物救助站' AS sttpName, 1 AS orderIndex FROM dual " + + "UNION ALL SELECT 'FP' AS repCode, '过鱼设施' AS sttpName, 2 AS orderIndex FROM dual " + + "UNION ALL SELECT 'FB' AS repCode, '鱼类增殖站' AS sttpName, 3 AS orderIndex FROM dual " + + "UNION ALL SELECT 'DW' AS repCode, '低温水减缓设施' AS sttpName, 4 AS orderIndex FROM dual " + + "UNION ALL SELECT 'VP' AS repCode, '珍稀植物园' AS sttpName, 5 AS orderIndex FROM dual " + + "UNION ALL SELECT 'FH' AS repCode, '鱼类栖息地' AS sttpName, 6 AS orderIndex FROM dual " + + "UNION ALL SELECT 'EQ' AS repCode, '生态流量泄放设施' AS sttpName, 7 AS orderIndex FROM dual"; + } + + private String buildOpedSummarySelectSql(List selectFields) { + Map columnMap = buildOpedSummarySelectMap(); + List fields = CollUtil.isEmpty(selectFields) + ? new ArrayList<>(columnMap.keySet()) + : new ArrayList<>(selectFields); + List selectItems = new ArrayList<>(); + for (String field : fields) { + if (StrUtil.isBlank(field)) { + continue; + } + String column = columnMap.get(field.trim()); + if (StrUtil.isNotBlank(column)) { + selectItems.add(column); + } + } + if (selectItems.isEmpty()) { + selectItems.addAll(columnMap.values()); + } + return String.join(", ", selectItems); + } + + private Map buildOpedSummarySelectMap() { + Map columnMap = new LinkedHashMap<>(); + columnMap.put("id", "CAST(NULL AS VARCHAR2(64)) AS \"id\""); + columnMap.put("recordUser", "CAST(NULL AS VARCHAR2(64)) AS \"recordUser\""); + columnMap.put("recordTime", "CAST(NULL AS DATE) AS \"recordTime\""); + columnMap.put("modifyTime", "CAST(NULL AS DATE) AS \"modifyTime\""); + columnMap.put("displayRecordUser", "CAST(NULL AS VARCHAR2(128)) AS \"displayRecordUser\""); + columnMap.put("repCode", "cat.repCode AS \"repCode\""); + columnMap.put("sttpCode", "CAST(NULL AS VARCHAR2(64)) AS \"sttpCode\""); + columnMap.put("pcode", "CAST(NULL AS VARCHAR2(64)) AS \"pcode\""); + columnMap.put("pname", "CAST(NULL AS VARCHAR2(128)) AS \"pname\""); + columnMap.put("psttpName", "CAST(NULL AS VARCHAR2(128)) AS \"psttpName\""); + columnMap.put("stcd", "CAST(NULL AS VARCHAR2(64)) AS \"stcd\""); + columnMap.put("ennm", "CAST(NULL AS VARCHAR2(255)) AS \"ennm\""); + columnMap.put("stnm", "CAST(NULL AS VARCHAR2(255)) AS \"stnm\""); + columnMap.put("addvcdName", "CAST(NULL AS VARCHAR2(255)) AS \"addvcdName\""); + columnMap.put("rvcdName", "CAST(NULL AS VARCHAR2(255)) AS \"rvcdName\""); + columnMap.put("sttpName", "cat.sttpName AS \"sttpName\""); + columnMap.put("baseId", "CAST(NULL AS VARCHAR2(64)) AS \"baseId\""); + columnMap.put("dtin", "CAST(NULL AS NUMBER(10)) AS \"dtin\""); + columnMap.put("dtinName", "CAST(NULL AS VARCHAR2(32)) AS \"dtinName\""); + columnMap.put("runState", "CAST(NULL AS NUMBER(10)) AS \"runState\""); + columnMap.put("runStateName", "CAST(NULL AS VARCHAR2(32)) AS \"runStateName\""); + columnMap.put("stdState", "CAST(NULL AS NUMBER(10)) AS \"stdState\""); + columnMap.put("stdStateName", "CAST(NULL AS VARCHAR2(32)) AS \"stdStateName\""); + columnMap.put("bldsttCcode", "CAST(NULL AS VARCHAR2(10)) AS \"bldsttCcode\""); + columnMap.put("bldsttCcodeName", "CAST(NULL AS VARCHAR2(32)) AS \"bldsttCcodeName\""); + columnMap.put("count", "COUNT(src.repCode) AS \"count\""); + columnMap.put("jcdt", "CAST(NULL AS DATE) AS \"jcdt\""); + columnMap.put("runSstate", "CAST(NULL AS NUMBER(10)) AS \"runSstate\""); + columnMap.put("runSstateName", "CAST(NULL AS VARCHAR2(32)) AS \"runSstateName\""); + columnMap.put("departmentId", "CAST(NULL AS VARCHAR2(64)) AS \"departmentId\""); + columnMap.put("displayDepartment", "CAST(NULL AS VARCHAR2(255)) AS \"displayDepartment\""); + return columnMap; + } + + private String buildOpedSummaryOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY cat.orderIndex ASC, cat.repCode ASC"; + } + List orderItems = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sortList) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = switch (sort.getField()) { + case "repCode" -> "cat.repCode"; + case "sttpName" -> "cat.sttpName"; + case "count" -> "COUNT(src.repCode)"; + default -> null; + }; + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sort.getDir()) || "des".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderItems.add(column + " " + dir); + } + if (orderItems.isEmpty()) { + return " ORDER BY cat.orderIndex ASC, cat.repCode ASC"; + } + return " ORDER BY " + String.join(", ", orderItems); + } + + private List normalizeValues(Object value) { + List values = new ArrayList<>(); + collectValues(value, values); + return values; + } + + private void collectValues(Object value, List values) { + if (value == null) { + return; + } + if (value instanceof List list) { + for (Object item : list) { + collectValues(item, values); + } + return; + } + if (value instanceof Object[] array) { + for (Object item : array) { + collectValues(item, values); + } + return; + } + values.add(value); + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/impl/VpConstructionServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/impl/VpConstructionServiceImpl.java index 9a2ad153..fe46774a 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/impl/VpConstructionServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/impl/VpConstructionServiceImpl.java @@ -1738,7 +1738,7 @@ public class VpConstructionServiceImpl implements VpConstructionService { columnMap.put("runState", "vp.RUN_STATE"); columnMap.put("runStateName", "CASE NVL(vp.RUN_STATE, -1) WHEN 1 THEN '运行' WHEN 0 THEN '未运行' ELSE NULL END"); columnMap.put("baseStepSort", "hb.ORDER_INDEX"); - columnMap.put("rvcdStepSort", "hbrv.ORDER_INDEX"); +// columnMap.put("rvcdStepSort", "hbrv.ORDER_INDEX"); columnMap.put("rstcdStepSort", "eng.ORDER_INDEX"); columnMap.put("siteStepSort", "vp.ORDER_INDEX"); return columnMap.get(field); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/controller/VdMonitorController.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/controller/VdMonitorController.java index a341cb51..1c37e616 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vd/controller/VdMonitorController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/controller/VdMonitorController.java @@ -47,6 +47,24 @@ public class VdMonitorController { return ResponseResult.successData(vdMonitorService.getKendoListCust(dataSourceRequest)); } + @PostMapping("/tree/GetKendoListCust") + @Operation(summary = "视频站树级结构查询") + public ResponseResult getVdTreeKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(vdMonitorService.getVdTreeKendoListCust(dataSourceRequest)); + } + + @PostMapping("/tree/GetKendoListCustSt") + @Operation(summary = "视频站树级结构查询-站点维度") + public ResponseResult getVdTreeKendoListCustSt(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(vdMonitorService.getVdTreeKendoListCustSt(dataSourceRequest)); + } + + @PostMapping("/vdpoint/GetKendoListCust") + @Operation(summary = "视频站锚点接口") + public ResponseResult getVdPointKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(vdMonitorService.getVdPointKendoListCust(dataSourceRequest)); + } + @PostMapping("/runData/GetKendoListCust") @Operation(summary = "查询视频监控运行数据") public ResponseResult getRunDataKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdPointVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdPointVo.java new file mode 100644 index 00000000..84f26352 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdPointVo.java @@ -0,0 +1,86 @@ +package com.yfd.platform.qgc_env.vd.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 VdPointVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "视频站子站类") + private String sttp; + + @Schema(description = "视频站编码") + private String stcd; + + @Schema(description = "经度") + private BigDecimal lgtd; + + @Schema(description = "纬度") + private BigDecimal lttd; + + @Schema(description = "高程") + private BigDecimal dtmel; + + @Schema(description = "锚点状态") + private String anchoPointState; + + @Schema(description = "站类地图标识") + private String sttpMap; + + @Schema(description = "标题") + private String titleName; + + @Schema(description = "默认距离") + private Integer distance; + + @Schema(description = "流域编码") + private String rvcd; + + @Schema(description = "行政区编码") + private String addvcd; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "所属电站编码") + private String rstcds; + + @Schema(description = "站类编码") + private String sttpCode; + + @Schema(description = "视频站名称") + private String stnm; + + @Schema(description = "流域名称") + private String rvnm; + + @Schema(description = "电站名称") + private String ennm; + + @Schema(description = "栖息地编码") + private String fhstcd; + + @Schema(description = "栖息地名称") + private String fhstnm; + + @Schema(description = "站类名称") + private String sttpName; + + @Schema(description = "站址") + private String stlc; + + @Schema(description = "播放方式") + private String playWay; + + @Schema(description = "站点排序") + private Integer siteStepSort; + + @Schema(description = "基地流域编码") + private String hbrvcd; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdTreeNodeVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdTreeNodeVo.java new file mode 100644 index 00000000..8b31efb7 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdTreeNodeVo.java @@ -0,0 +1,71 @@ +package com.yfd.platform.qgc_env.vd.entity.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +@Data +@Schema(description = "视频站树节点") +public class VdTreeNodeVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "节点ID") + private String id; + + @Schema(description = "节点名称") + private String name; + + @Schema(description = "节点类型") + private String type; + + @Schema(description = "节点类型名称") + private String typeName; + + @Schema(description = "排序值") + private Integer sort; + + @Schema(description = "父节点ID") + private String parentId; + + @Schema(description = "父节点名称") + private String parentName; + + @Schema(description = "是否有子节点") + private Integer hasChildren; + + @Schema(description = "播放地址") + private String url; + + @Schema(description = "播放方式") + private String playWay; + + @Schema(description = "设备序列号") + private String deviceSerial; + + @Schema(description = "接入方式") + private String accessWay; + + @Schema(description = "流协议") + private String protocol; + + @Schema(description = "清晰度") + private String quality; + + @Schema(description = "控制方式") + private String controlMode; + + @Schema(description = "设备状态") + private Integer status; + + @Schema(description = "状态时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date statusTm; + + @Schema(description = "子节点") + private List children; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdTreeRowVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdTreeRowVo.java new file mode 100644 index 00000000..eeea11bb --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/entity/vo/VdTreeRowVo.java @@ -0,0 +1,39 @@ +package com.yfd.platform.qgc_env.vd.entity.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@Data +public class VdTreeRowVo implements Serializable { + + private static final long serialVersionUID = 1L; + + private String stcd; + private String stCode; + private String stName; + private String stnm; + private String sttpCode; + private String sttpName; + private String sttpFullPath; + private String rstcd; + private String ennm; + private String baseId; + private String baseName; + private String url; + private String playWay; + private Integer baseSort; + private Integer rstcdStepSort; + private Integer siteStepSort; + private String deviceSerial; + private String accessWay; + private String protocol; + private String quality; + private String controlMode; + private Integer status; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date statusTm; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java index 4fa8d933..490bd6b7 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/VdMonitorService.java @@ -2,6 +2,7 @@ package com.yfd.platform.qgc_env.vd.service; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.qgc_env.vd.entity.vo.VdTreeNodeVo; import com.yfd.platform.qgc_env.vd.entity.vo.VdRunDataVo; import com.yfd.platform.qgc_env.vd.entity.vo.VdVmsstbprptVo; @@ -13,5 +14,11 @@ public interface VdMonitorService { DataSourceResult getKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getVdTreeKendoListCust(DataSourceRequest dataSourceRequest); + + DataSourceResult getVdTreeKendoListCustSt(DataSourceRequest dataSourceRequest); + + DataSourceResult getVdPointKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getRunDataKendoListCust(DataSourceRequest dataSourceRequest); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java index 3c4cc27f..0a674c47 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vd/service/impl/VdMonitorServiceImpl.java @@ -9,7 +9,10 @@ import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.common.GroupHelper; import com.yfd.platform.common.GroupingInfo; import com.yfd.platform.common.MicroservicDynamicSQLMapper; +import com.yfd.platform.qgc_env.vd.entity.vo.VdPointVo; import com.yfd.platform.qgc_env.vd.entity.vo.VdRunDataVo; +import com.yfd.platform.qgc_env.vd.entity.vo.VdTreeNodeVo; +import com.yfd.platform.qgc_env.vd.entity.vo.VdTreeRowVo; import com.yfd.platform.qgc_env.vd.entity.vo.VdVmsstbprptVo; import com.yfd.platform.qgc_env.vd.service.VdMonitorService; import com.yfd.platform.utils.QgcQueryWrapperUtil; @@ -18,6 +21,7 @@ import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -118,6 +122,113 @@ public class VdMonitorServiceImpl implements VdMonitorService { return queryLatestRunDataGroupList(dataSourceRequest, loadOptions); } + @Override + public DataSourceResult getVdTreeKendoListCust(DataSourceRequest dataSourceRequest) { + Map paramMap = new HashMap<>(); + String filterSql = buildVdTreeFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("t.stcd AS stcd, ") + .append("t.stCode AS stCode, ") + .append("t.stName AS stName, ") + .append("t.stnm AS stnm, ") + .append("t.sttpCode AS sttpCode, ") + .append("t.sttpName AS sttpName, ") + .append("t.sttpFullPath AS sttpFullPath, ") + .append("t.rstcd AS rstcd, ") + .append("t.ennm AS ennm, ") + .append("t.baseId AS baseId, ") + .append("t.baseName AS baseName, ") + .append("t.url AS url, ") + .append("t.playWay AS playWay, ") + .append("t.baseSort AS baseSort, ") + .append("t.rstcdStepSort AS rstcdStepSort, ") + .append("t.siteStepSort AS siteStepSort, ") + .append("t.deviceSerial AS deviceSerial, ") + .append("t.accessWay AS accessWay, ") + .append("t.protocol AS protocol, ") + .append("t.quality AS quality, ") + .append("t.controlMode AS controlMode, ") + .append("t.status AS status, ") + .append("t.statusTm AS statusTm ") + .append("FROM (") + .append(buildVdTreeCoreSql()) + .append(") t WHERE 1 = 1 AND t.sttpCode != 'VD_FPRD'"); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(" ORDER BY t.baseSort ASC NULLS LAST, t.rstcdStepSort ASC NULLS LAST, t.siteStepSort ASC NULLS LAST, t.stcd ASC"); + + List rows = microservicDynamicSQLMapper.getAllListWithResultType(sql.toString(), paramMap, VdTreeRowVo.class); + boolean baseScoped = containsNonBlankFilterValue(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), "baseId"); + + DataSourceResult result = new DataSourceResult<>(); + List treeData = buildVdTreeNodes(rows, baseScoped); + result.setData(treeData); + result.setTotal((long) treeData.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getVdTreeKendoListCustSt(DataSourceRequest dataSourceRequest) { + Map paramMap = new HashMap<>(); + String filterSql = buildVdTreeFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("t.stcd AS stcd, ") + .append("t.stCode AS stCode, ") + .append("t.stName AS stName, ") + .append("t.stnm AS stnm, ") + .append("t.sttpCode AS sttpCode, ") + .append("t.sttpName AS sttpName, ") + .append("t.sttpFullPath AS sttpFullPath, ") + .append("t.rstcd AS rstcd, ") + .append("t.ennm AS ennm, ") + .append("t.baseId AS baseId, ") + .append("t.baseName AS baseName, ") + .append("t.url AS url, ") + .append("t.playWay AS playWay, ") + .append("t.baseSort AS baseSort, ") + .append("t.rstcdStepSort AS rstcdStepSort, ") + .append("t.siteStepSort AS siteStepSort, ") + .append("t.deviceSerial AS deviceSerial, ") + .append("t.accessWay AS accessWay, ") + .append("t.protocol AS protocol, ") + .append("t.quality AS quality, ") + .append("t.controlMode AS controlMode, ") + .append("t.status AS status, ") + .append("t.statusTm AS statusTm ") + .append("FROM (") + .append(buildVdTreeCoreSql()) + .append(") t WHERE 1 = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(" ORDER BY t.baseSort ASC NULLS LAST, t.rstcdStepSort ASC NULLS LAST, t.siteStepSort ASC NULLS LAST, t.stcd ASC"); + + List rows = microservicDynamicSQLMapper.getAllListWithResultType(sql.toString(), paramMap, VdTreeRowVo.class); + boolean baseScoped = containsNonBlankFilterValue(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), "baseId"); + + DataSourceResult result = new DataSourceResult<>(); + List treeData = buildVdTreeNodesByStation(rows, baseScoped); + result.setData(treeData); + result.setTotal((long) treeData.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getVdPointKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + if (CollUtil.isNotEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + return getKendoListCust(dataSourceRequest); + } + return queryVdPointDetailList(dataSourceRequest, loadOptions); + } + @Override public DataSourceResult getRunDataKendoListCust(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -131,9 +242,30 @@ public class VdMonitorServiceImpl implements VdMonitorService { GroupingInfo[] groups, String filterSql, Map paramMap) { + List groupDescriptors = dataSourceRequest == null ? null : dataSourceRequest.getGroup(); + List selectItems = new ArrayList<>(); + if (CollUtil.isNotEmpty(groupDescriptors)) { + for (DataSourceRequest.GroupDescriptor descriptor : groupDescriptors) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + selectItems.add(column + " AS " + descriptor.getField()); + selectItems.add("COUNT(1) AS count_" + descriptor.getField()); + } + } + if (selectItems.isEmpty()) { + selectItems.add("t.sttpCode AS sttpCode"); + selectItems.add("COUNT(1) AS count_sttpCode"); + } + StringBuilder sql = new StringBuilder(); - sql.append("SELECT t.sttpCode AS sttpCode, COUNT(1) AS count_sttpCode ") - .append("FROM (") + sql.append("SELECT ") + .append(String.join(", ", selectItems)) + .append(" FROM (") .append(buildVmsstbprptViewSql()) .append(") t ") .append("WHERE 1 = 1 "); @@ -141,8 +273,24 @@ public class VdMonitorServiceImpl implements VdMonitorService { sql.append(" AND ").append(filterSql).append(" "); } - sql.append(" GROUP BY t.sttpCode "); - sql.append(buildOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getGroup())); + List groupByColumns = new ArrayList<>(); + if (CollUtil.isNotEmpty(groupDescriptors)) { + for (DataSourceRequest.GroupDescriptor descriptor : groupDescriptors) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapColumn(descriptor.getField()); + if (StrUtil.isNotBlank(column)) { + groupByColumns.add(column); + } + } + } + if (!groupByColumns.isEmpty()) { + sql.append(" GROUP BY ").append(String.join(", ", groupByColumns)); + } else { + sql.append(" GROUP BY t.sttpCode "); + } + sql.append(buildOrderBySql(groupDescriptors)); List> rows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap); DataSourceResult result = new DataSourceResult<>(); @@ -294,6 +442,32 @@ public class VdMonitorServiceImpl implements VdMonitorService { return queryRunDataGroupList(dataSourceRequest, loadOptions, buildLatestRunDataCoreSql()); } + private DataSourceResult queryVdPointDetailList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildVdPointSelectSql()) + .append("FROM (") + .append(buildVdPointCoreSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = buildFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildVdPointOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, sql.toString(), paramMap, VdPointVo.class); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + private DataSourceResult queryRunDataGroupList(DataSourceRequest dataSourceRequest, DataSourceLoadOptionsBase loadOptions, String coreSql) { @@ -418,12 +592,57 @@ public class VdMonitorServiceImpl implements VdMonitorService { " AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 "; } + private String buildVdTreeCoreSql() { + return "SELECT " + + "base.STCD AS stcd, " + + "base.STNM AS stnm, " + + "base.CSTCD AS stCode, " + + "cst.STNM AS stName, " + + "base.STTP AS sttpCode, " + + "sttp.STTP_NAME AS sttpName, " + + "sttp.FULL_PATH AS sttpFullPath, " + + "base.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "NVL(eng.BASE_ID, base.BASE_ID) AS baseId, " + + "hb.BASENAME AS baseName, " + + "base.URL AS url, " + + "CASE WHEN base.URL IS NULL THEN NULL WHEN INSTR(base.URL, 'm3u8') > 0 THEN '1' ELSE '0' END AS playWay, " + + "NVL(hb.ORDER_INDEX, 999999) AS baseSort, " + + "NVL(eng.ORDER_INDEX, 999999) AS rstcdStepSort, " + + "NVL(base.ORDER_INDEX, 999999) AS siteStepSort, " + + "base.DEVICE_SERIAL AS deviceSerial, " + + "base.ACCESS_WAY AS accessWay, " + + "base.PROTOCOL AS protocol, " + + "base.QUALITY AS quality, " + + "base.CONTROL_MODE AS controlMode, " + + "status.STATUS AS status, " + + "status.TM AS statusTm " + + "FROM (" + buildVdDeviceBaseSql() + ") base " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = base.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = NVL(eng.BASE_ID, base.BASE_ID) " + + " AND NVL(hb.IS_DELETED, 0) = 0 AND NVL(hb.ENABLED, 1) = 1 " + + "LEFT JOIN (" + buildStationBaseSql() + ") cst ON cst.STCD = base.CSTCD " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = base.STTP " + + " AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 " + + "LEFT JOIN ( " + + "SELECT detail.STCD, detail.TM, detail.STATUS " + + "FROM MS_SBGZSTAT_B detail " + + "INNER JOIN ( " + + "SELECT STCD, MAX(TM) AS MAX_TM FROM MS_SBGZSTAT_B " + + "WHERE NVL(IS_DELETED, 0) = 0 GROUP BY STCD " + + ") latest ON detail.STCD = latest.STCD AND detail.TM = latest.MAX_TM " + + "WHERE NVL(detail.IS_DELETED, 0) = 0 " + + ") status ON status.STCD = base.STCD " + + "WHERE base.STTP LIKE 'VD_%' "; + } + private String buildVdDeviceBaseSql() { return "SELECT vd.STCD, vd.STNM, vd.MNTP, vd.STTP, vd.LGTD, vd.LTTD, vd.ELEV, vd.STLC, " + " vd.JCDT, vd.WDDT, vd.BLDSTT_CODE, vd.USFL, vd.DTIN, vd.STINDX, vd.RSTCD, vd.BASE_ID, " + " vd.HBRVCD, vd.RVCD, vd.ADDVCD, vd.CSTCD, vd.FHSTCD, CAST(NULL AS VARCHAR2(3000)) AS INTRODUCE, " + " CAST(NULL AS VARCHAR2(255)) AS LOGO, CAST(NULL AS VARCHAR2(1000)) AS INFFILE, " + - " vd.DTFRQCY, vd.REMARK, vd.VLSR, vd.VLSR_TM, vd.URL AS URL, CAST(NULL AS NUMBER(8,0)) AS ORDER_INDEX, " + + " vd.DTFRQCY, vd.REMARK, vd.VLSR, vd.VLSR_TM, vd.URL AS URL, vd.DEVICE_SERIAL, vd.ACCESS_WAY, " + + " vd.PROTOCOL, vd.QUALITY, vd.CONTROL_MODE, CAST(NULL AS NUMBER(8,0)) AS ORDER_INDEX, " + " 'SD_VDINFO_B' AS SOURCE_TABLE " + "FROM SD_VDINFO_B vd WHERE 1=1 " + // " AND vd.STTP = 'VD_FP' "+ @@ -431,11 +650,59 @@ public class VdMonitorServiceImpl implements VdMonitorService { "SELECT sonar.STCD, sonar.STNM, sonar.MNTP, sonar.STTP, sonar.LGTD, sonar.LTTD, sonar.ELEV, sonar.STLC, " + " sonar.JCDT, sonar.WDDT, sonar.BLDSTT_CODE, sonar.USFL, sonar.DTIN, sonar.STINDX, sonar.RSTCD, sonar.BASE_ID, " + " sonar.HBRVCD, sonar.RVCD, sonar.ADDVCD, CAST(NULL AS VARCHAR2(36)) AS CSTCD, CAST(NULL AS VARCHAR2(36)) AS FHSTCD, " + - " sonar.INTRODUCE, sonar.LOGO, sonar.INFFILE, sonar.DTFRQCY, sonar.REMARK, sonar.VLSR, sonar.VLSR_TM, CAST(NULL AS VARCHAR2(512)) AS URL, sonar.ORDER_INDEX, " + + " sonar.INTRODUCE, sonar.LOGO, sonar.INFFILE, sonar.DTFRQCY, sonar.REMARK, sonar.VLSR, sonar.VLSR_TM, CAST(NULL AS VARCHAR2(512)) AS URL, " + + " CAST(NULL AS VARCHAR2(255)) AS DEVICE_SERIAL, CAST(NULL AS VARCHAR2(10)) AS ACCESS_WAY, " + + " CAST(NULL AS VARCHAR2(50)) AS PROTOCOL, CAST(NULL AS VARCHAR2(50)) AS QUALITY, CAST(NULL AS VARCHAR2(2048)) AS CONTROL_MODE, sonar.ORDER_INDEX, " + " 'SD_SONAR_B_H' AS SOURCE_TABLE " + "FROM SD_SONAR_B_H sonar WHERE NVL(sonar.IS_DELETED, 0) = 0 AND sonar.STTP IN ('VD_WVD', 'VD_SN') "; } + private String buildVdPointCoreSql() { + return "SELECT " + + "src.STTP AS sttp, " + + "src.STCD AS stcd, " + + "src.LGTD AS lgtd, " + + "src.LTTD AS lttd, " + + "CAST(NULL AS NUMBER(10, 6)) AS dtmel, " + + "CASE " + + " WHEN NVL(eng.HBRVCD, src.HBRVCD) = 'SJLY126' THEN CASE src.STTP " + + " WHEN 'VD_FBFM' THEN 'fbfm_spjk' " + + " WHEN 'VD_EQS' THEN 'eqs_spjk' " + + " WHEN 'VD_FB' THEN 'fb_spjk' " + + " WHEN 'VD_FP' THEN 'fp_spjk' " + + " WHEN 'VD_FH' THEN 'fh_spjk' " + + " WHEN 'VD_VA' THEN 'va_spjk' " + + " WHEN 'VD_VP' THEN 'vp_spjk' " + + " WHEN 'VD_DW' THEN 'dw_spjk' " + + " WHEN 'VD_WQ' THEN 'wq_spjk' " + + " ELSE 'spjk' END " + + " ELSE 'spjk' END AS anchoPointState, " + + "'VD' AS sttpMap, " + + "src.STNM AS titleName, " + + "400000 AS distance, " + + "NVL(eng.RVCD, src.RVCD) AS rvcd, " + + "NVL(eng.ADDVCD, src.ADDVCD) AS addvcd, " + + "NVL(eng.BASE_ID, src.BASE_ID) AS baseId, " + + "src.RSTCD AS rstcds, " + + "'VD' AS sttpCode, " + + "src.STNM AS stnm, " + + "rv.RVNM AS rvnm, " + + "eng.ENNM AS ennm, " + + "src.FHSTCD AS fhstcd, " + + "fh.STNM AS fhstnm, " + + "sttp.STTP_NAME AS sttpName, " + + "src.STLC AS stlc, " + + "CASE WHEN src.URL IS NULL THEN NULL WHEN INSTR(src.URL, 'm3u8') > 0 THEN '1' ELSE '0' END AS playWay, " + + "src.ORDER_INDEX AS siteStepSort, " + + "NVL(eng.HBRVCD, src.HBRVCD) AS hbrvcd " + + "FROM (" + buildVdDeviceBaseSql() + ") src " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = src.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_FHBT_B_H fh ON fh.STCD = src.FHSTCD AND NVL(fh.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = NVL(eng.RVCD, src.RVCD) " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = src.STTP " + + " AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 "; + } + private String buildRunDataCoreSql() { return "SELECT " + "run.ID AS id, " + @@ -591,6 +858,33 @@ public class VdMonitorServiceImpl implements VdMonitorService { return String.join(", ", actualColumns); } + private String buildVdPointSelectSql() { + return "t.sttp AS sttp, " + + "t.stcd AS stcd, " + + "t.lgtd AS lgtd, " + + "t.lttd AS lttd, " + + "t.dtmel AS dtmel, " + + "t.anchoPointState AS anchoPointState, " + + "t.sttpMap AS sttpMap, " + + "t.titleName AS titleName, " + + "t.distance AS distance, " + + "t.rvcd AS rvcd, " + + "t.addvcd AS addvcd, " + + "t.baseId AS baseId, " + + "t.rstcds AS rstcds, " + + "t.sttpCode AS sttpCode, " + + "t.stnm AS stnm, " + + "t.rvnm AS rvnm, " + + "t.ennm AS ennm, " + + "t.fhstcd AS fhstcd, " + + "t.fhstnm AS fhstnm, " + + "t.sttpName AS sttpName, " + + "t.stlc AS stlc, " + + "t.playWay AS playWay, " + + "t.siteStepSort AS siteStepSort, " + + "t.hbrvcd AS hbrvcd "; + } + private String buildRunDataOrderBySql(List sortList) { if (CollUtil.isEmpty(sortList)) { return " ORDER BY t.baseStepSort ASC, t.rvcdStepSort ASC, t.rstcdStepSort ASC, t.siteStepSort ASC, t.stcd ASC, t.tm DESC"; @@ -613,6 +907,28 @@ public class VdMonitorServiceImpl implements VdMonitorService { return " ORDER BY " + String.join(", ", orderItems); } + private String buildVdPointOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY t.siteStepSort ASC NULLS LAST, t.stcd ASC"; + } + List orderItems = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sortList) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) || "des".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderItems.add(column + " " + direction + " NULLS LAST"); + } + if (orderItems.isEmpty()) { + return " ORDER BY t.siteStepSort ASC NULLS LAST, t.stcd ASC"; + } + return " ORDER BY " + String.join(", ", orderItems); + } + private String buildRunDataGroupOrderBySql(List groups) { if (CollUtil.isEmpty(groups)) { return ""; @@ -641,6 +957,42 @@ public class VdMonitorServiceImpl implements VdMonitorService { }; } + private String buildVdTreeFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildVdTreeLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildVdTreeFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildVdTreeLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapVdTreeColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + return buildSimpleCondition(column, "vdTreeParam", filter, paramMap, indexHolder, isVdTreeDateField(filter)); + } + private String buildFilterCondition(DataSourceRequest.FilterDescriptor filter, Map paramMap, int[] indexHolder) { @@ -804,6 +1156,16 @@ public class VdMonitorServiceImpl implements VdMonitorService { return "date".equalsIgnoreCase(filter.getDataType()); } + private boolean isVdTreeDateField(DataSourceRequest.FilterDescriptor filter) { + if (filter == null || StrUtil.isBlank(filter.getField())) { + return false; + } + if ("statusTm".equalsIgnoreCase(filter.getField())) { + return true; + } + return "date".equalsIgnoreCase(filter.getDataType()); + } + private String buildValueExpr(String paramKey, boolean dateField, Object value) { if (!dateField || value == null) { return "#{map." + paramKey + "}"; @@ -817,26 +1179,62 @@ public class VdMonitorServiceImpl implements VdMonitorService { private List normalizeValues(Object value) { List values = new ArrayList<>(); + appendNormalizedValues(values, value); + return values; + } + + private void appendNormalizedValues(List values, Object value) { + if (value == null) { + return; + } if (value instanceof List list) { for (Object item : list) { - if (item != null) { - values.add(item); - } + appendNormalizedValues(values, item); } - return values; + return; } if (value instanceof Object[] array) { for (Object item : array) { - if (item != null) { - values.add(item); - } + appendNormalizedValues(values, item); } - return values; + return; } - if (value != null) { - values.add(value); + if (value instanceof String text) { + if (StrUtil.isNotBlank(text)) { + values.add(text); + } + return; } - return values; + values.add(value); + } + + private String mapVdTreeColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd" -> "t.stcd"; + case "stCode" -> "t.stCode"; + case "stName" -> "t.stName"; + case "stnm" -> "t.stnm"; + case "sttpCode" -> "t.sttpCode"; + case "sttpName" -> "t.sttpName"; + case "sttpFullPath" -> "t.sttpFullPath"; + case "rstcd" -> "t.rstcd"; + case "ennm" -> "t.ennm"; + case "baseId" -> "t.baseId"; + case "baseName" -> "t.baseName"; + case "url" -> "t.url"; + case "playWay" -> "t.playWay"; + case "deviceSerial" -> "t.deviceSerial"; + case "accessWay" -> "t.accessWay"; + case "protocol" -> "t.protocol"; + case "quality" -> "t.quality"; + case "controlMode" -> "t.controlMode"; + case "status" -> "NVL(t.status, 0)"; + case "statusTm" -> "t.statusTm"; + default -> null; + }; } private String mapColumn(String field) { @@ -844,6 +1242,7 @@ public class VdMonitorServiceImpl implements VdMonitorService { return null; } return switch (field) { + case "sttp" -> "t.sttp"; case "sttpCode" -> "t.sttpCode"; case "sttpName" -> "t.sttpName"; case "sttpFullPath" -> "t.sttpFullPath"; @@ -878,11 +1277,15 @@ public class VdMonitorServiceImpl implements VdMonitorService { case "vlsr" -> "t.vlsr"; case "vlsrTm" -> "t.vlsrTm"; case "rvcd" -> "t.rvcd"; + case "rvnm" -> "t.rvnm"; case "addvcd" -> "t.addvcd"; case "dtin" -> "t.dtin"; case "usfl" -> "t.usfl"; case "url" -> "t.url"; case "playWay" -> "t.playWay"; + case "titleName" -> "t.titleName"; + case "rstcds" -> "t.rstcds"; + case "anchoPointState" -> "t.anchoPointState"; case "sourceTable" -> "t.sourceTable"; case "baseStepSort" -> "t.baseStepSort"; case "rstcdStepSort" -> "t.rstcdStepSort"; @@ -971,4 +1374,265 @@ public class VdMonitorServiceImpl implements VdMonitorService { } return " ORDER BY " + String.join(", ", orderItems); } + + private boolean containsNonBlankFilterValue(DataSourceRequest.FilterDescriptor filter, String fieldName) { + if (filter == null || StrUtil.isBlank(fieldName)) { + return false; + } + if (fieldName.equalsIgnoreCase(filter.getField())) { + if (filter.getValue() instanceof List list) { + return CollUtil.isNotEmpty(list); + } + return StrUtil.isNotBlank(filter.getValue() == null ? null : String.valueOf(filter.getValue())); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return false; + } + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + if (containsNonBlankFilterValue(child, fieldName)) { + return true; + } + } + return false; + } + + private List buildVdTreeNodes(List rows, boolean baseScoped) { + List stationNodes = buildStationTreeNodes(rows, baseScoped); + if (baseScoped) { + return sortTreeNodes(stationNodes); + } + + LinkedHashMap baseNodeMap = new LinkedHashMap<>(); + List topLevelWithoutBase = new ArrayList<>(); + for (VdTreeRowVo row : rows) { + if (row == null) { + continue; + } + if (StrUtil.isBlank(row.getBaseId())) { + continue; + } + baseNodeMap.computeIfAbsent(row.getBaseId(), key -> { + VdTreeNodeVo node = new VdTreeNodeVo(); + node.setId(key); + node.setName(StrUtil.blankToDefault(row.getBaseName(), key)); + node.setType("PSB"); + node.setTypeName("基地"); + node.setSort(defaultSort(row.getBaseSort())); + node.setHasChildren(1); + node.setParentId(null); + node.setParentName(null); + return node; + }); + } + + Map> stationByBase = new LinkedHashMap<>(); + for (VdTreeNodeVo stationNode : stationNodes) { + if (StrUtil.isBlank(stationNode.getParentId())) { + topLevelWithoutBase.add(stationNode); + continue; + } + stationByBase.computeIfAbsent(stationNode.getParentId(), key -> new ArrayList<>()).add(stationNode); + } + + List result = new ArrayList<>(); + for (Map.Entry entry : baseNodeMap.entrySet()) { + VdTreeNodeVo baseNode = entry.getValue(); + baseNode.setChildren(sortTreeNodes(stationByBase.get(entry.getKey()))); + result.add(baseNode); + } + result.addAll(topLevelWithoutBase); + return sortTreeNodes(result); + } + + private List buildVdTreeNodesByStation(List rows, boolean baseScoped) { + List stationNodes = buildStationCodeTreeNodes(rows, baseScoped); + if (baseScoped) { + return sortTreeNodes(stationNodes); + } + + LinkedHashMap baseNodeMap = new LinkedHashMap<>(); + List topLevelWithoutBase = new ArrayList<>(); + for (VdTreeRowVo row : rows) { + if (row == null || StrUtil.isBlank(row.getBaseId())) { + continue; + } + baseNodeMap.computeIfAbsent(row.getBaseId(), key -> { + VdTreeNodeVo node = new VdTreeNodeVo(); + node.setId(key); + node.setName(StrUtil.blankToDefault(row.getBaseName(), key)); + node.setType("PSB"); + node.setTypeName("基地"); + node.setSort(defaultSort(row.getBaseSort())); + node.setHasChildren(1); + node.setParentId(null); + node.setParentName(null); + return node; + }); + } + + Map> stationByBase = new LinkedHashMap<>(); + for (VdTreeNodeVo stationNode : stationNodes) { + if (StrUtil.isBlank(stationNode.getParentId())) { + topLevelWithoutBase.add(stationNode); + continue; + } + stationByBase.computeIfAbsent(stationNode.getParentId(), key -> new ArrayList<>()).add(stationNode); + } + + List result = new ArrayList<>(); + for (Map.Entry entry : baseNodeMap.entrySet()) { + VdTreeNodeVo baseNode = entry.getValue(); + baseNode.setChildren(sortTreeNodes(stationByBase.get(entry.getKey()))); + result.add(baseNode); + } + result.addAll(topLevelWithoutBase); + return sortTreeNodes(result); + } + + private List buildStationTreeNodes(List rows, boolean baseScoped) { + LinkedHashMap> stationRowMap = new LinkedHashMap<>(); + for (VdTreeRowVo row : rows) { + if (row == null || StrUtil.isBlank(row.getRstcd())) { + continue; + } + stationRowMap.computeIfAbsent(row.getRstcd(), key -> new ArrayList<>()).add(row); + } + + List stationNodes = new ArrayList<>(); + for (Map.Entry> entry : stationRowMap.entrySet()) { + List stationRows = entry.getValue(); + if (CollUtil.isEmpty(stationRows)) { + continue; + } + VdTreeRowVo sample = stationRows.get(0); + VdTreeNodeVo stationNode = new VdTreeNodeVo(); + stationNode.setId(entry.getKey()); + stationNode.setName(StrUtil.blankToDefault(sample.getEnnm(), entry.getKey())); + stationNode.setType("ENG"); + stationNode.setTypeName("电站"); + stationNode.setSort(defaultSort(sample.getRstcdStepSort())); + stationNode.setHasChildren(1); + if (baseScoped) { + stationNode.setParentId(null); + stationNode.setParentName(null); + } else { + stationNode.setParentId(sample.getBaseId()); + stationNode.setParentName(sample.getBaseName()); + } + stationNode.setChildren(buildSiteTreeNodes(stationRows)); + stationNodes.add(stationNode); + } + return sortTreeNodes(stationNodes); + } + + private List buildSiteTreeNodes(List rows) { + LinkedHashMap siteNodeMap = new LinkedHashMap<>(); + for (VdTreeRowVo row : rows) { + if (row == null || StrUtil.isBlank(row.getStcd()) || siteNodeMap.containsKey(row.getStcd())) { + continue; + } + VdTreeNodeVo node = new VdTreeNodeVo(); + node.setId(row.getStcd()); + node.setName(StrUtil.blankToDefault(row.getStnm(), row.getStcd())); + node.setType(row.getSttpCode()); + node.setTypeName(row.getSttpName()); + node.setSort(defaultSort(row.getSiteStepSort())); + node.setHasChildren(0); + node.setParentId(row.getRstcd()); + node.setParentName(row.getEnnm()); + node.setUrl(row.getUrl()); + node.setPlayWay(row.getPlayWay()); + node.setDeviceSerial(row.getDeviceSerial()); + node.setAccessWay(row.getAccessWay()); + node.setProtocol(row.getProtocol()); + node.setQuality(row.getQuality()); + node.setControlMode(row.getControlMode()); + node.setStatus(row.getStatus()); + node.setStatusTm(row.getStatusTm()); + siteNodeMap.put(row.getStcd(), node); + } + return sortTreeNodes(new ArrayList<>(siteNodeMap.values())); + } + + private List buildStationCodeTreeNodes(List rows, boolean baseScoped) { + LinkedHashMap> stationRowMap = new LinkedHashMap<>(); + for (VdTreeRowVo row : rows) { + if (row == null || StrUtil.isBlank(row.getStCode())) { + continue; + } + stationRowMap.computeIfAbsent(row.getStCode(), key -> new ArrayList<>()).add(row); + } + + List stationNodes = new ArrayList<>(); + for (Map.Entry> entry : stationRowMap.entrySet()) { + List stationRows = entry.getValue(); + if (CollUtil.isEmpty(stationRows)) { + continue; + } + VdTreeRowVo sample = stationRows.get(0); + VdTreeNodeVo stationNode = new VdTreeNodeVo(); + stationNode.setId(entry.getKey()); + stationNode.setName(StrUtil.blankToDefault(sample.getStName(), entry.getKey())); + stationNode.setType("VD_FB"); + stationNode.setTypeName("鱼类增殖站"); + stationNode.setSort(defaultSort(sample.getRstcdStepSort())); + stationNode.setHasChildren(1); + if (baseScoped) { + stationNode.setParentId(null); + stationNode.setParentName(null); + } else { + stationNode.setParentId(sample.getBaseId()); + stationNode.setParentName(sample.getBaseName()); + } + stationNode.setChildren(buildSiteTreeNodesByStation(stationRows)); + stationNodes.add(stationNode); + } + return sortTreeNodes(stationNodes); + } + + private List buildSiteTreeNodesByStation(List rows) { + LinkedHashMap siteNodeMap = new LinkedHashMap<>(); + for (VdTreeRowVo row : rows) { + if (row == null || StrUtil.isBlank(row.getStcd()) || siteNodeMap.containsKey(row.getStcd())) { + continue; + } + VdTreeNodeVo node = new VdTreeNodeVo(); + node.setId(row.getStcd()); + node.setName(StrUtil.blankToDefault(row.getStnm(), row.getStcd())); + node.setType(row.getSttpCode()); + node.setTypeName(row.getSttpName()); + node.setSort(defaultSort(row.getSiteStepSort())); + node.setHasChildren(0); + node.setParentId(row.getStCode()); + node.setParentName(row.getStName()); + node.setUrl(row.getUrl()); + node.setPlayWay(row.getPlayWay()); + node.setDeviceSerial(row.getDeviceSerial()); + node.setAccessWay(row.getAccessWay()); + node.setProtocol(row.getProtocol()); + node.setQuality(row.getQuality()); + node.setControlMode(row.getControlMode()); + node.setStatus(row.getStatus()); + node.setStatusTm(row.getStatusTm()); + siteNodeMap.put(row.getStcd(), node); + } + return sortTreeNodes(new ArrayList<>(siteNodeMap.values())); + } + + private List sortTreeNodes(List nodes) { + if (CollUtil.isEmpty(nodes)) { + return new ArrayList<>(); + } + nodes.sort(Comparator.comparing(VdMonitorServiceImpl::sortValue) + .thenComparing(node -> StrUtil.blankToDefault(node.getId(), ""))); + return nodes; + } + + private static Integer sortValue(VdTreeNodeVo node) { + return node == null ? 999999 : defaultSort(node.getSort()); + } + + private static Integer defaultSort(Integer sort) { + return sort == null ? 999999 : sort; + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/controller/WarnDataController.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/controller/WarnDataController.java new file mode 100644 index 00000000..00421006 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/controller/WarnDataController.java @@ -0,0 +1,77 @@ +package com.yfd.platform.qgc_env.warn.controller; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.qgc_env.warn.service.WarnDataService; +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("/warn") +@Tag(name = "告警状态模块") +@Validated +public class WarnDataController { + + @Resource + private WarnDataService warnDataService; + + @PostMapping("/stcd/eng/GetKendoListCust") + @Operation(summary = "电站水位、生态流量告警状态统计") + public ResponseResult getEngWarnCount(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getEngWarnCount(dataSourceRequest)); + } + + @PostMapping("/ai/com/qgcDmRun/GetKendoListCust") + @Operation(summary = "全过程AI识别大坝运行") + public ResponseResult getAiDmRunCount(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getAiDmRunCount(dataSourceRequest)); + } + + @PostMapping("/ai/com/qgcProtect/GetKendoListCust") + @Operation(summary = "全过程AI识别动植物保护") + public ResponseResult getAiProtectCount(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getAiProtectCount(dataSourceRequest)); + } + + @PostMapping("/ai/com/GetKendoListCust") + @Operation(summary = "AI常规业务列表") + public ResponseResult getAiComKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getAiComKendoListCust(dataSourceRequest)); + } + + @PostMapping("/ai/com/qgc/aiRstcd/GetKendoListCust") + @Operation(summary = "全过程AI识别有数据的电站下拉") + public ResponseResult getAiRstcdListKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getAiRstcdListKendoListCust(dataSourceRequest)); + } + + @PostMapping("/ai/com/qgc/aiPfwRecord/GetKendoListCust") + @Operation(summary = "全过程AI识别监测日历表(漂浮物+清漂合并)") + public ResponseResult getAiPfwRecordKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getAiPfwRecordKendoListCust(dataSourceRequest)); + } + + @PostMapping("/ai/com/qgc/aiRecord/GetKendoListCust") + @Operation(summary = "全过程AI识别监测日历表") + public ResponseResult getAiRecordKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getAiRecordKendoListCust(dataSourceRequest)); + } + + @PostMapping("/alarmPoint/GetKendoListCust") + @Operation(summary = "电站告警描点列表") + public ResponseResult getAlarmPointKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getAlarmPointKendoListCust(dataSourceRequest)); + } + + @PostMapping("/stcd/GetKendoListCust") + @Operation(summary = "监测设备告警情况列表") + public ResponseResult getWarnStcdKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(warnDataService.getWarnStcdKendoListCust(dataSourceRequest)); + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiComListVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiComListVo.java new file mode 100644 index 00000000..5b7445e1 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiComListVo.java @@ -0,0 +1,71 @@ +package com.yfd.platform.qgc_env.warn.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Date; + +@Data +@Schema(description = "AI常规业务列表") +public class AiComListVo { + + @Schema(description = "主键") + private String id; + + @Schema(description = "类型编码") + private String type; + + @Schema(description = "类型名称") + private String typeName; + + @Schema(description = "AI测站编码") + private String stcd; + + @Schema(description = "AI测站名称") + private String stnm; + + @Schema(description = "所属电站编码") + private String rstcd; + + @Schema(description = "所属电站名称") + private String ennm; + + @Schema(description = "所属基地编码") + private String baseId; + + @Schema(description = "所属基地流域编码") + private String hbrvcd; + + @Schema(description = "所属流域编码") + private String rvcd; + + @Schema(description = "数据时间") + private Date tm; + + @Schema(description = "结束时间") + private Date endTm; + + @Schema(description = "AI识别值") + private String aiVal; + + @Schema(description = "附件ID") + private String fid; + + @Schema(description = "是否填报") + private Integer isFsf; + + @Schema(description = "是否大面积漂浮物") + private Integer isBigDebrisArea; + + @Schema(description = "是否已清漂") + private Integer isClearDrift; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + private Date recordTime; + + @Schema(description = "更新时间") + private Date modifyTime; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiDmRunVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiDmRunVo.java new file mode 100644 index 00000000..ac5671e7 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiDmRunVo.java @@ -0,0 +1,18 @@ +package com.yfd.platform.qgc_env.warn.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "全过程AI识别大坝运行") +public class AiDmRunVo { + + @Schema(description = "漂浮物监测次数") + private Integer pfwCnt; + + @Schema(description = "漂浮物清理次数") + private Integer pfwqlCnt; + + @Schema(description = "叠梁门运行次数") + private Integer dlmCnt; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiProtectVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiProtectVo.java new file mode 100644 index 00000000..3a81096e --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiProtectVo.java @@ -0,0 +1,30 @@ +package com.yfd.platform.qgc_env.warn.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "全过程AI识别动植物保护") +public class AiProtectVo { + + @Schema(description = "运鱼船进出港次数") + private Integer fpYycCnt; + + @Schema(description = "赶鱼栅运行次数") + private Integer fpGysCnt; + + @Schema(description = "升鱼机运行次数") + private Integer fpSyjCnt; + + @Schema(description = "AGV小车次数") + private Integer fpAgvCnt; + + @Schema(description = "运鱼车运行次数") + private Integer fpYychCnt; + + @Schema(description = "鱼道放流次数") + private Integer fpYdhCnt; + + @Schema(description = "植物园养护次数") + private Integer vpYhCnt; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiRecordVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiRecordVo.java new file mode 100644 index 00000000..dfe4d0e3 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiRecordVo.java @@ -0,0 +1,44 @@ +package com.yfd.platform.qgc_env.warn.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +@Data +@Accessors(chain = true) +@Schema(description = "全过程AI识别监测日历记录") +public class AiRecordVo { + + @Schema(description = "AI类型") + private String type; + + @Schema(description = "日期") + private String dt; + + @Schema(description = "是否大面积漂浮物") + private Integer isBigDebrisArea; + + @Schema(description = "AI数据数") + private Integer aiCnt; + + @Schema(description = "统计数") + private Integer cnt; + + @Schema(description = "是否已清漂") + private Integer isClearDrift; + + @Schema(description = "漂浮物状态") + private Integer status; + + @Schema(description = "漂浮物状态名称") + private String statusName; + + @Schema(description = "清漂状态") + private Integer qpStatus; + + @Schema(description = "清漂状态名称") + private String qpStatusName; + + @Schema(description = "附件ID") + private String fid; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiRstcdVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiRstcdVo.java new file mode 100644 index 00000000..46c0ca88 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AiRstcdVo.java @@ -0,0 +1,15 @@ +package com.yfd.platform.qgc_env.warn.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "全过程AI识别电站下拉") +public class AiRstcdVo { + + @Schema(description = "电站编码") + private String stcd; + + @Schema(description = "电站名称") + private String stnm; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AlarmPointVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AlarmPointVo.java new file mode 100644 index 00000000..69cbfaa2 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/AlarmPointVo.java @@ -0,0 +1,103 @@ +package com.yfd.platform.qgc_env.warn.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; + +@Data +@Accessors(chain = true) +@Schema(description = "电站告警描点") +public class AlarmPointVo { + + @Schema(description = "站点类型") + private String sttp; + + @Schema(description = "站点编码") + private String stcd; + + @Schema(description = "经度") + private BigDecimal lgtd; + + @Schema(description = "纬度") + private BigDecimal lttd; + + @Schema(description = "高程") + private BigDecimal dtmel; + + @Schema(description = "描点状态") + private String anchoPointState; + + @Schema(description = "锚点类型") + private String sttpMap; + + @Schema(description = "弹框站点名称") + private String titleName; + + @Schema(description = "地图避让") + private Integer distance; + + @Schema(description = "流域编码") + private String rvcd; + + @Schema(description = "行政编码") + private String addvcd; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "关联电站编码") + private String rstcds; + + @Schema(description = "设施类型") + private String sttpCode; + + @Schema(description = "电站名称") + private String ennm; + + @Schema(description = "流域名称") + private String rvnm; + + @Schema(description = "电站装机类型") + private Integer endInstalledType; + + @Schema(description = "生态流量告警数") + private Integer stqCount; + + @Schema(description = "水质告警数") + private Integer wqCount; + + @Schema(description = "水位告警数") + private Integer zCount; + + @Schema(description = "水温告警数") + private Integer wtCount; + + @Schema(description = "年份") + private String yyyy; + + @Schema(description = "告警区间范围") + private String range; + + @Schema(description = "装机容量") + private BigDecimal ttpwr; + + @Schema(description = "基地名称") + private String baseName; + + @Schema(description = "电站编码") + private String rstcd; + + @Schema(description = "流域沿程") + private Integer rvcdStepSort; + + @Schema(description = "电站沿程") + private Integer rstcdStepSort; + + @Schema(description = "站点沿程") + private Integer siteStepSort; + + @Schema(description = "电站图片") + private String logo; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/EngWarnCountVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/EngWarnCountVo.java new file mode 100644 index 00000000..b0cfb180 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/EngWarnCountVo.java @@ -0,0 +1,28 @@ +package com.yfd.platform.qgc_env.warn.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +@Schema(description = "电站告警状态统计") +public class EngWarnCountVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "告警状态") + private Integer warnState; + + @Schema(description = "告警状态名称") + private String warnStateName; + + @Schema(description = "数量") + private Integer num; + + @Schema(description = "告警类型") + private String warnType; + + @Schema(description = "告警类型名称") + private String warnTypeName; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/StcdWarnStateVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/StcdWarnStateVo.java new file mode 100644 index 00000000..9843ffc3 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/StcdWarnStateVo.java @@ -0,0 +1,65 @@ +package com.yfd.platform.qgc_env.warn.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Date; + +@Data +@Schema(description = "监测设备告警情况") +public class StcdWarnStateVo { + + @Schema(description = "测站编码") + private String stcd; + + @Schema(description = "测站名称") + private String stnm; + + @Schema(description = "电站编码") + private String rstcd; + + @Schema(description = "电站名称") + private String ennm; + + @Schema(description = "监测方式") + private Integer mway; + + @Schema(description = "测站类型编码") + private String sttpCode; + + @Schema(description = "测站类型名称") + private String sttpName; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "基地名称") + private String baseName; + + @Schema(description = "流域编码") + private String rvcd; + + @Schema(description = "告警状态") + private Integer warnState; + + @Schema(description = "告警状态名称") + private String warnstateName; + + @Schema(description = "告警时间") + private Date warnTm; + + @Schema(description = "基础排序") + private Integer baseStepSort; + + @Schema(description = "流域排序") + private Integer rvcdStepSort; + + @Schema(description = "电站排序") + private Integer rstcdStepSort; + + @Schema(description = "站点排序") + private Integer siteStepSort; + + @Schema(description = "数据接入类型") + private Integer dtinType; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/WarnDataService.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/WarnDataService.java new file mode 100644 index 00000000..eccdcb72 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/WarnDataService.java @@ -0,0 +1,35 @@ +package com.yfd.platform.qgc_env.warn.service; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.qgc_env.warn.entity.vo.AlarmPointVo; +import com.yfd.platform.qgc_env.warn.entity.vo.AiRecordVo; +import com.yfd.platform.qgc_env.warn.entity.vo.AiProtectVo; +import com.yfd.platform.qgc_env.warn.entity.vo.AiDmRunVo; +import com.yfd.platform.qgc_env.warn.entity.vo.AiComListVo; +import com.yfd.platform.qgc_env.warn.entity.vo.AiRstcdVo; +import com.yfd.platform.qgc_env.warn.entity.vo.EngWarnCountVo; +import com.yfd.platform.qgc_env.warn.entity.vo.StcdWarnStateVo; + +import java.util.List; + +public interface WarnDataService { + + DataSourceResult getEngWarnCount(DataSourceRequest dataSourceRequest); + + AiDmRunVo getAiDmRunCount(DataSourceRequest dataSourceRequest); + + AiProtectVo getAiProtectCount(DataSourceRequest dataSourceRequest); + + DataSourceResult getAiComKendoListCust(DataSourceRequest dataSourceRequest); + + DataSourceResult getAiRstcdListKendoListCust(DataSourceRequest dataSourceRequest); + + List getAiPfwRecordKendoListCust(DataSourceRequest dataSourceRequest); + + List getAiRecordKendoListCust(DataSourceRequest dataSourceRequest); + + DataSourceResult getAlarmPointKendoListCust(DataSourceRequest dataSourceRequest); + + DataSourceResult getWarnStcdKendoListCust(DataSourceRequest dataSourceRequest); +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/impl/WarnDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/impl/WarnDataServiceImpl.java new file mode 100644 index 00000000..efd22964 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/impl/WarnDataServiceImpl.java @@ -0,0 +1,2029 @@ +package com.yfd.platform.qgc_env.warn.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.common.DataSourceLoadOptionsBase; +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.common.GroupHelper; +import com.yfd.platform.common.GroupingInfo; +import com.yfd.platform.common.MicroservicDynamicSQLMapper; +import com.yfd.platform.qgc_env.warn.entity.vo.AlarmPointVo; +import com.yfd.platform.qgc_env.warn.entity.vo.AiComListVo; +import com.yfd.platform.qgc_env.warn.entity.vo.AiDmRunVo; +import com.yfd.platform.qgc_env.warn.entity.vo.AiProtectVo; +import com.yfd.platform.qgc_env.warn.entity.vo.AiRecordVo; +import com.yfd.platform.qgc_env.warn.entity.vo.AiRstcdVo; +import com.yfd.platform.qgc_env.warn.entity.vo.EngWarnCountVo; +import com.yfd.platform.qgc_env.warn.entity.vo.StcdWarnStateVo; +import com.yfd.platform.qgc_env.warn.service.WarnDataService; +import com.yfd.platform.utils.QgcQueryWrapperUtil; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class WarnDataServiceImpl implements WarnDataService { + + @Resource + private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; + + @Override + public DataSourceResult getEngWarnCount(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Map paramMap = new HashMap<>(); + String filterSql = buildSourceFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("r.warnState AS warnState, ") + .append("r.num AS num, ") + .append("r.warnType AS warnType ") + .append("FROM (") + .append(buildEngWarnCountSql(filterSql)) + .append(") r "); + sql.append(buildOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + EngWarnCountVo.class + ); + fillWarnNames(list); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public AiDmRunVo getAiDmRunCount(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String baseId = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId"); + String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + String rstcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); + String stnm = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stnm"); + + Map paramMap = new HashMap<>(); + String sql = buildAiDmRunSql(baseId, parseAiTime(startTime), parseAiTime(endTime), parseAiCodes(rstcd), stnm, paramMap); + Map row = microservicDynamicSQLMapper.getOneBySql(sql, paramMap); + AiDmRunVo vo = buildAiDmRunVo(row); + if (vo == null) { + vo = new AiDmRunVo(); + } + if (vo.getPfwCnt() == null) { + vo.setPfwCnt(0); + } + if (vo.getPfwqlCnt() == null) { + vo.setPfwqlCnt(0); + } + if (vo.getDlmCnt() == null) { + vo.setDlmCnt(0); + } + return vo; + } + + @Override + public AiProtectVo getAiProtectCount(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String baseId = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId"); + String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + String rstcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); + String stnm = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stnm"); + + Map paramMap = new HashMap<>(); + String sql = buildAiProtectSql(baseId, parseAiTime(startTime), parseAiTime(endTime), parseAiCodes(rstcd), stnm, paramMap); + Map row = microservicDynamicSQLMapper.getOneBySql(sql, paramMap); + AiProtectVo vo = buildAiProtectVo(row); + if (vo == null) { + vo = new AiProtectVo(); + } + if (vo.getFpYycCnt() == null) { + vo.setFpYycCnt(0); + } + if (vo.getFpGysCnt() == null) { + vo.setFpGysCnt(0); + } + if (vo.getFpSyjCnt() == null) { + vo.setFpSyjCnt(0); + } + if (vo.getFpAgvCnt() == null) { + vo.setFpAgvCnt(0); + } + if (vo.getFpYychCnt() == null) { + vo.setFpYychCnt(0); + } + if (vo.getFpYdhCnt() == null) { + vo.setFpYdhCnt(0); + } + if (vo.getVpYhCnt() == null) { + vo.setVpYhCnt(0); + } + return vo; + } + + @Override + public DataSourceResult getAiComKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + GroupingInfo[] groupInfos = loadOptions == null ? null : loadOptions.getGroup(); + Map paramMap = new HashMap<>(); + + StringBuilder detailSql = new StringBuilder(); + detailSql.append("SELECT ") + .append("rec.ID AS id, ") + .append("rec.TYPE AS type, ") + .append(buildAiTypeNameExpr("rec.TYPE")).append(" AS typeName, ") + .append("rec.STCD AS stcd, ") + .append("ai.STNM AS stnm, ") + .append("ai.RSTCD AS rstcd, ") + .append("eng.ENNM AS ennm, ") + .append("ai.BASE_ID AS baseId, ") + .append("ai.HBRVCD AS hbrvcd, ") + .append("ai.RVCD AS rvcd, ") + .append("rec.TM AS tm, ") + .append("rec.END_TM AS endTm, ") + .append("rec.AI_VAL AS aiVal, ") + .append("rec.FID AS fid, ") + .append("rec.IS_FSF AS isFsf, ") + .append("rec.IS_BIG_DEBRIS_AREA AS isBigDebrisArea, ") + .append("rec.IS_CLEAR_DRIFT AS isClearDrift, ") + .append("rec.REMARK AS remark, ") + .append("rec.RECORD_TIME AS recordTime, ") + .append("rec.MODIFY_TIME AS modifyTime ") + .append("FROM SD_AICOM_R rec ") + .append("LEFT JOIN SD_AIMONITOR_B_H ai ON ai.STCD = rec.STCD AND NVL(ai.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = ai.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(rec.IS_DELETED, 0) = 0 "); + + String filterSql = buildAiComFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + detailSql.append(" AND ").append(filterSql).append(" "); + } + + DataSourceResult result = new DataSourceResult<>(); + if (CollUtil.isNotEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + String groupedSql = buildAiComGroupSql(detailSql.toString(), groupInfos); + List> rows = microservicDynamicSQLMapper.getAllList(groupedSql, paramMap); + result.setTotal(rows.size()); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setAggregates(new HashMap<>()); + return result; + } + + StringBuilder finalSql = new StringBuilder(); + finalSql.append("SELECT r.* FROM (").append(detailSql).append(") r "); + finalSql.append(buildAiComOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType(page, finalSql.toString(), paramMap, AiComListVo.class); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getAiRstcdListKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String baseId = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId"); + String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + String type = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "type"); + + Map paramMap = new HashMap<>(); + String sql = buildAiRstcdListSql(baseId, parseAiTime(startTime), parseAiTime(endTime), type, paramMap); + List list = microservicDynamicSQLMapper.getAllListWithResultType(sql, paramMap, AiRstcdVo.class); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public List getAiPfwRecordKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String baseId = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId"); + String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + String rstcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); + + Map paramMap = new HashMap<>(); + String sql = buildAiPfwRecordSql(baseId, parseAiTime(startTime), parseAiTime(endTime), parseAiCodes(rstcd), paramMap); + List list = microservicDynamicSQLMapper.getAllListWithResultType(sql, paramMap, AiRecordVo.class); + fillAiPfwStatus(list); + return list; + } + + @Override + public List getAiRecordKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String baseId = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId"); + String startTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTime = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + String rstcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); + String stcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd"); + String type = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "type"); + + Map paramMap = new HashMap<>(); + String sql = buildAiRecordSql(baseId, parseAiTime(startTime), parseAiTime(endTime), parseAiCodes(rstcd), stcd, type, paramMap); + List list = microservicDynamicSQLMapper.getAllListWithResultType(sql, paramMap, AiRecordVo.class); + fillAiRecordStatus(list); + return list; + } + + @Override + public DataSourceResult getAlarmPointKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String startTimeText = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTimeText = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + + Date startTime = null; + Date endTime = null; + String yyyy = null; + if (StrUtil.isNotBlank(startTimeText) && StrUtil.isNotBlank(endTimeText)) { + startTime = parseAiTime(startTimeText); + endTime = parseAiTime(endTimeText); + } else { + yyyy = String.valueOf(DateUtil.year(new Date())); + Map yearRange = buildAlarmPointYearRange(yyyy); + startTime = yearRange.get("startTime"); + endTime = yearRange.get("endTime"); + } + + List points = microservicDynamicSQLMapper.getAllListWithResultType( + buildAlarmPointBaseSql(), + new HashMap<>(), + AlarmPointVo.class + ); + + Map countParamMap = new HashMap<>(); + countParamMap.put("alarmPointStartTime", startTime); + countParamMap.put("alarmPointEndTime", endTime); + List> countRows = microservicDynamicSQLMapper.getAllList(buildAlarmPointCountSql(), countParamMap); + Map qecCountMap = buildAlarmPointQecCountMap(countRows); + Map wqCountMap = buildAlarmPointWqCountMap(countRows); + + List> expressionRows = microservicDynamicSQLMapper.getAllList(buildAlarmPointLegendSql(), new HashMap<>()); + List resultList = mergeAlarmPointData(points, qecCountMap, wqCountMap, expressionRows, yyyy); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(resultList); + result.setTotal(resultList.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getWarnStcdKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String warnType = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "warnType"); + String rvcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rvcd"); + + Map paramMap = new HashMap<>(); + String filterSql = buildWarnStcdFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("r.stcd AS stcd, ") + .append("r.stnm AS stnm, ") + .append("r.rstcd AS rstcd, ") + .append("r.ennm AS ennm, ") + .append("r.mway AS mway, ") + .append("r.sttpCode AS sttpCode, ") + .append("r.sttpName AS sttpName, ") + .append("r.baseId AS baseId, ") + .append("r.baseName AS baseName, ") + .append("r.rvcd AS rvcd, ") + .append("r.warnState AS warnState, ") + .append("r.baseStepSort AS baseStepSort, ") + .append("r.rvcdStepSort AS rvcdStepSort, ") + .append("r.rstcdStepSort AS rstcdStepSort, ") + .append("r.siteStepSort AS siteStepSort, ") + .append("r.dtinType AS dtinType ") + .append("FROM (") + .append(buildWarnStcdDetailSql(warnType)) + .append(") r WHERE 1 = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildWarnStcdOrderBySql( + dataSourceRequest == null ? null : dataSourceRequest.getSort(), + rvcd + )); + + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + StcdWarnStateVo.class + ); + fillWarnStcdData(list, warnType); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page == null ? list.size() : page.getTotal()); + result.setAggregates(new HashMap<>()); + return result; + } + + private AiDmRunVo buildAiDmRunVo(Map row) { + if (row == null || row.isEmpty()) { + return null; + } + AiDmRunVo vo = new AiDmRunVo(); + vo.setPfwCnt(toIntegerValue(firstPresentValue(row, "PFWCNT", "pfwCnt"))); + vo.setPfwqlCnt(toIntegerValue(firstPresentValue(row, "PFWQLCNT", "pfwqlCnt"))); + vo.setDlmCnt(toIntegerValue(firstPresentValue(row, "DLMCNT", "dlmCnt"))); + return vo; + } + + private String buildWarnStcdDetailSql(String warnType) { + String normalizedWarnStateExpr = "CASE " + + "WHEN eng.WARN_STATE = '0' OR eng.WARN_STATE IS NULL OR eng.WARN_STATE = '' THEN '00' " + + "ELSE eng.WARN_STATE END"; + String wqWarnStateExpr = "TO_NUMBER(NULLIF(wq.WARN_STATE, ''))"; + String wtWarnStateExpr = "TO_NUMBER(NULLIF(wt.WARN_STATE, ''))"; + + List parts = new ArrayList<>(); + if ("QEC".equalsIgnoreCase(warnType)) { + parts.add(buildWarnStcdEngSql(normalizedWarnStateExpr, warnType)); + } else { + parts.add(buildWarnStcdEngSql(normalizedWarnStateExpr, warnType)); + parts.add(buildWarnStcdWqSql(wqWarnStateExpr)); + parts.add(buildWarnStcdWtSql(wtWarnStateExpr)); + } + return String.join(" UNION ALL ", parts); + } + + private String buildWarnStcdEngSql(String normalizedWarnStateExpr, String warnType) { + String warnStateExpr; + if ("RZ".equalsIgnoreCase(warnType)) { + warnStateExpr = "TO_NUMBER(SUBSTR(" + normalizedWarnStateExpr + ", 1, 1))"; + } else if ("QEC".equalsIgnoreCase(warnType)) { + warnStateExpr = "NVL(TO_NUMBER(SUBSTR(" + normalizedWarnStateExpr + ", 2, 1)), 0)"; + } else { + warnStateExpr = "TO_NUMBER(NULLIF(eng.WARN_STATE, ''))"; + } + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("eng.STCD AS stcd, ") + .append("eng.ENNM AS stnm, ") + .append("CAST(NULL AS VARCHAR2(32)) AS rstcd, ") + .append("eng.ENNM AS ennm, ") + .append("CAST(NULL AS NUMBER) AS mway, ") + .append("'ENG' AS sttpCode, ") + .append("sttp.STTP_NAME AS sttpName, ") + .append("eng.BASE_ID AS baseId, ") + .append("NVL(hb.BASENAME, eng.BASE_NAME) AS baseName, ") + .append("eng.HBRVCD AS rvcd, ") + .append(warnStateExpr).append(" AS warnState, ") + .append("hb.ORDER_INDEX AS baseStepSort, ") + .append("along.ORDER_INDEX AS rvcdStepSort, ") + .append("eng.ORDER_INDEX AS rstcdStepSort, ") + .append("eng.ORDER_INDEX AS siteStepSort, ") + .append("CAST(NULL AS NUMBER) AS dtinType ") + .append("FROM SD_ENGINFO_B_H eng ") + .append("LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = 'ENG' AND NVL(sttp.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN MS_ALONG_B along ON along.RVCD = eng.HBRVCD AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(eng.IS_DELETED, 0) = 0 "); + if ("QEC".equalsIgnoreCase(warnType)) { + sql.append("AND NVL(eng.BLDSTT_CODE, -1) = 2 ") + .append("AND NVL(eng.DTIN, 0) = 1 ") + .append("AND NVL(eng.RUN_STATE, 2) = 4 "); + } else { + sql.append("AND NVL(eng.USFL, 0) = 1 "); + } + return sql.toString(); + } + + private String buildWarnStcdWqSql(String warnStateExpr) { + return "SELECT " + + "wq.STCD AS stcd, " + + "wq.STNM AS stnm, " + + "wq.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "wq.MWAY AS mway, " + + "wq.STTP AS sttpCode, " + + "sttp.STTP_NAME AS sttpName, " + + "eng.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName, " + + "eng.HBRVCD AS rvcd, " + + warnStateExpr + " AS warnState, " + + "hb.ORDER_INDEX AS baseStepSort, " + + "along.ORDER_INDEX AS rvcdStepSort, " + + "eng.ORDER_INDEX AS rstcdStepSort, " + + "siteAlong.SORT AS siteStepSort, " + + "wq.DTIN_TYPE AS dtinType " + + "FROM SD_WQ_B_H wq " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wq.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN MS_ALONG_B along ON along.RVCD = eng.HBRVCD AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 " + + "LEFT JOIN MS_ALONGDET_B siteAlong ON siteAlong.ALONG_ID = along.ID AND siteAlong.STCD = wq.STCD AND NVL(siteAlong.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = wq.STTP AND NVL(sttp.IS_DELETED, 0) = 0 " + + "WHERE NVL(wq.IS_DELETED, 0) = 0 " + + "AND NVL(wq.USFL, 0) = 1 " + + "AND wq.STTP IN ('WQ', 'WQFB') "; + } + + private String buildWarnStcdWtSql(String warnStateExpr) { + return "SELECT " + + "wt.STCD AS stcd, " + + "wt.STNM AS stnm, " + + "wt.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "wt.MWAY AS mway, " + + "wt.STTP AS sttpCode, " + + "sttp.STTP_NAME AS sttpName, " + + "eng.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName, " + + "eng.HBRVCD AS rvcd, " + + warnStateExpr + " AS warnState, " + + "hb.ORDER_INDEX AS baseStepSort, " + + "along.ORDER_INDEX AS rvcdStepSort, " + + "eng.ORDER_INDEX AS rstcdStepSort, " + + "siteAlong.SORT AS siteStepSort, " + + "wt.DTIN_TYPE AS dtinType " + + "FROM SD_WT_B_H wt " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN MS_ALONG_B along ON along.RVCD = eng.HBRVCD AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 " + + "LEFT JOIN MS_ALONGDET_B siteAlong ON siteAlong.ALONG_ID = along.ID AND siteAlong.STCD = wt.STCD AND NVL(siteAlong.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = wt.STTP AND NVL(sttp.IS_DELETED, 0) = 0 " + + "WHERE NVL(wt.IS_DELETED, 0) = 0 " + + "AND NVL(wt.USFL, 0) = 1 " + + "AND wt.STTP = 'WTRV' "; + } + + private String buildWarnStcdFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + List parts = new ArrayList<>(); + if (CollUtil.isNotEmpty(filter.getFilters())) { + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildWarnStcdFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + parts.add(childSql); + } + } + if (parts.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return "(" + String.join(logic, parts) + ")"; + } + if ("warnType".equalsIgnoreCase(filter.getField())) { + return ""; + } + String column = mapWarnStcdColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String paramKey = "warnStcdParam" + indexHolder[0]++; + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + Object value = filter.getValue(); + switch (operator) { + case "eq": + paramMap.put(paramKey, normalizeWarnStcdValue(filter.getField(), value)); + return column + " = #{map." + paramKey + "}"; + case "neq": + paramMap.put(paramKey, normalizeWarnStcdValue(filter.getField(), value)); + return column + " <> #{map." + paramKey + "}"; + case "contains": + paramMap.put(paramKey, "%" + safeString(value) + "%"); + return column + " LIKE #{map." + paramKey + "}"; + case "doesnotcontain": + paramMap.put(paramKey, "%" + safeString(value) + "%"); + return column + " NOT LIKE #{map." + paramKey + "}"; + case "startswith": + paramMap.put(paramKey, safeString(value) + "%"); + return column + " LIKE #{map." + paramKey + "}"; + case "endswith": + paramMap.put(paramKey, "%" + safeString(value)); + return column + " LIKE #{map." + paramKey + "}"; + case "gt": + paramMap.put(paramKey, normalizeWarnStcdValue(filter.getField(), value)); + return column + " > #{map." + paramKey + "}"; + case "gte": + paramMap.put(paramKey, normalizeWarnStcdValue(filter.getField(), value)); + return column + " >= #{map." + paramKey + "}"; + case "lt": + paramMap.put(paramKey, normalizeWarnStcdValue(filter.getField(), value)); + return column + " < #{map." + paramKey + "}"; + case "lte": + paramMap.put(paramKey, normalizeWarnStcdValue(filter.getField(), value)); + return column + " <= #{map." + paramKey + "}"; + case "isnull": + return column + " IS NULL"; + case "isnotnull": + return column + " IS NOT NULL"; + case "isempty": + return "(" + column + " IS NULL OR " + column + " = '')"; + case "isnotempty": + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + case "in": + return buildWarnStcdInSql(column, value, paramKey, paramMap); + default: + return ""; + } + } + + private String buildWarnStcdInSql(String column, Object value, String paramKey, Map paramMap) { + List values = parseAiCodes(value == null ? null : String.valueOf(value)); + if (CollUtil.isEmpty(values)) { + return ""; + } + List placeholders = new ArrayList<>(); + for (int i = 0; i < values.size(); i++) { + String key = paramKey + "_" + i; + paramMap.put(key, values.get(i)); + placeholders.add("#{map." + key + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + + private String mapWarnStcdColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd" -> "r.stcd"; + case "stnm" -> "r.stnm"; + case "rstcd" -> "r.rstcd"; + case "ennm" -> "r.ennm"; + case "mway" -> "r.mway"; + case "sttpCode" -> "r.sttpCode"; + case "sttpName" -> "r.sttpName"; + case "baseId" -> "r.baseId"; + case "baseName" -> "r.baseName"; + case "rvcd" -> "r.rvcd"; + case "warnState" -> "r.warnState"; + case "baseStepSort" -> "r.baseStepSort"; + case "rvcdStepSort" -> "r.rvcdStepSort"; + case "rstcdStepSort" -> "r.rstcdStepSort"; + case "siteStepSort" -> "r.siteStepSort"; + case "dtinType" -> "r.dtinType"; + default -> null; + }; + } + + private Object normalizeWarnStcdValue(String field, Object value) { + if ("warnState".equals(field) || "mway".equals(field) || "dtinType".equals(field)) { + return toIntegerValue(value); + } + return value; + } + + private String buildWarnStcdOrderBySql(List sortList, String rvcd) { + if (CollUtil.isEmpty(sortList)) { + if (StrUtil.isNotBlank(rvcd)) { + return " ORDER BY r.rstcdStepSort ASC NULLS LAST "; + } + return ""; + } + List orderItems = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor item : sortList) { + if (item == null || StrUtil.isBlank(item.getField())) { + continue; + } + String column = mapWarnStcdColumn(item.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(item.getDir()) ? "DESC" : "ASC"; + orderItems.add(column + " " + dir); + } + if (orderItems.isEmpty()) { + if (StrUtil.isNotBlank(rvcd)) { + return " ORDER BY r.rstcdStepSort ASC NULLS LAST "; + } + return ""; + } + return " ORDER BY " + String.join(", ", orderItems); + } + + private void fillWarnStcdData(List list, String warnType) { + if (CollUtil.isEmpty(list)) { + return; + } + Map engRzWarnTmMap = new HashMap<>(); + Map engQecWarnTmMap = new HashMap<>(); + Map wqWarnTmMap = new HashMap<>(); + Map wtWarnTmMap = new HashMap<>(); + + if ("RZ".equalsIgnoreCase(warnType)) { + engRzWarnTmMap = getWarnRecordTimeMap(collectWarnStcds(list, "ENG"), "HYDROPW_R"); + } else if ("QEC".equalsIgnoreCase(warnType)) { + engQecWarnTmMap = getWarnRecordTimeMap(collectWarnStcds(list, "ENG"), "QEC_R"); + } + wqWarnTmMap = getWarnRecordTimeMap(collectWarnStcds(list, "WQ", "WQFB"), "WQ_R"); + wtWarnTmMap = getWarnRecordTimeMap(collectWarnStcds(list, "WTRV"), "WTRV_R"); + + for (StcdWarnStateVo item : list) { + if (item == null) { + continue; + } + item.setWarnstateName(resolveWarnStateName(item.getWarnState())); + if (!Integer.valueOf(2).equals(item.getWarnState())) { + continue; + } + if ("ENG".equalsIgnoreCase(item.getSttpCode()) && "RZ".equalsIgnoreCase(warnType)) { + item.setWarnTm(defaultWarnTm(engRzWarnTmMap.get(item.getStcd()))); + } else if ("ENG".equalsIgnoreCase(item.getSttpCode()) && "QEC".equalsIgnoreCase(warnType)) { + item.setWarnTm(defaultWarnTm(engQecWarnTmMap.get(item.getStcd()))); + } else if ("WTRV".equalsIgnoreCase(item.getSttpCode())) { + item.setWarnTm(defaultWarnTm(wtWarnTmMap.get(item.getStcd()))); + } else if ("WQ".equalsIgnoreCase(item.getSttpCode()) || "WQFB".equalsIgnoreCase(item.getSttpCode())) { + item.setWarnTm(defaultWarnTm(wqWarnTmMap.get(item.getStcd()))); + } else { + item.setWarnTm(new Date()); + } + } + } + + private List collectWarnStcds(List list, String... sttpCodes) { + List result = new ArrayList<>(); + if (CollUtil.isEmpty(list) || sttpCodes == null || sttpCodes.length == 0) { + return result; + } + List sttpCodeList = Arrays.asList(sttpCodes); + for (StcdWarnStateVo item : list) { + if (item == null || !Integer.valueOf(2).equals(item.getWarnState())) { + continue; + } + if (!sttpCodeList.contains(item.getSttpCode())) { + continue; + } + if (StrUtil.isNotBlank(item.getStcd()) && !result.contains(item.getStcd())) { + result.add(item.getStcd()); + } + } + return result; + } + + private Map getWarnRecordTimeMap(List stcdList, String tbCode) { + Map result = new HashMap<>(); + if (CollUtil.isEmpty(stcdList) || StrUtil.isBlank(tbCode)) { + return result; + } + Map paramMap = new HashMap<>(); + List placeholders = new ArrayList<>(); + for (int i = 0; i < stcdList.size(); i++) { + String key = "warnRecordStcd" + i; + paramMap.put(key, stcdList.get(i)); + placeholders.add("#{map." + key + "}"); + } + paramMap.put("warnRecordTbCode", tbCode); + String sql = "SELECT rec.STCD AS stcd, MAX(rec.BTM) AS warnTm " + + "FROM MS_WARN_RECORD_W rec " + + "INNER JOIN ST_TB_B tb ON tb.ID = rec.TB_ID AND NVL(tb.IS_DELETED, 0) = 0 " + + "WHERE NVL(rec.IS_DELETED, 0) = 0 " + + "AND NVL(rec.SFGB, 'N') = 'N' " + + "AND tb.TB_CODE = #{map.warnRecordTbCode} " + + "AND rec.STCD IN (" + String.join(", ", placeholders) + ") " + + "GROUP BY rec.STCD"; + List> rows = microservicDynamicSQLMapper.getAllList(sql, paramMap); + for (Map row : rows) { + String stcd = safeString(firstPresentValue(row, "STCD", "stcd")); + Date warnTm = toDateValue(firstPresentValue(row, "WARNTM", "warnTm")); + if (StrUtil.isNotBlank(stcd) && warnTm != null) { + result.put(stcd, warnTm); + } + } + return result; + } + + private Date defaultWarnTm(Date warnTm) { + return warnTm == null ? new Date() : warnTm; + } + + private String buildAiRstcdListSql(String baseId, + Date startTime, + Date endTime, + String type, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT DISTINCT t.stcd AS stcd, t.stnm AS stnm FROM ("); + sql.append("SELECT ai.RSTCD AS stcd, eng.ENNM AS stnm ") + .append("FROM SD_AIMONITOR_B_H ai ") + .append("INNER JOIN SD_AICOM_R rec ON ai.STCD = rec.STCD ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = ai.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND NVL(rec.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP LIKE 'AI_%' ") + .append("AND ai.RSTCD IS NOT NULL "); + appendAiRstcdCommonFilterSql(sql, "aiRstcdAicom", "ai", "rec", baseId, startTime, endTime, paramMap); + appendAiRstcdTypeFilterSql(sql, "aiRstcdType", "rec.TYPE", type, paramMap); + sql.append(" UNION "); + sql.append("SELECT ai.RSTCD AS stcd, eng.ENNM AS stnm ") + .append("FROM SD_AIMONITOR_B_H ai ") + .append("INNER JOIN SD_AIHEARTBEAT_R hb ON ai.STCD = hb.STCD ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = ai.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND NVL(hb.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP LIKE 'AI_%' ") + .append("AND ai.RSTCD IS NOT NULL "); + appendAiRstcdCommonFilterSql(sql, "aiRstcdHeartbeat", "ai", "hb", baseId, startTime, endTime, paramMap); + appendAiRstcdHeartbeatTypeFilterSql(sql, type, paramMap); + sql.append(") t ORDER BY t.stnm, t.stcd"); + return sql.toString(); + } + + private String buildAiPfwRecordSql(String baseId, + Date startTime, + Date endTime, + List rstcdList, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT a.dt AS dt, b.isClearDrift AS isClearDrift, b.isBigDebrisArea AS isBigDebrisArea, b.fid AS fid ") + .append("FROM (") + .append("SELECT TO_CHAR(hb.TM, 'yyyy-MM-dd') AS dt ") + .append("FROM SD_AIHEARTBEAT_R hb ") + .append("INNER JOIN SD_AIMONITOR_B_H ai ON ai.STCD = hb.STCD ") + .append("WHERE NVL(hb.IS_DELETED, 0) = 0 ") + .append("AND NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP = 'AI_5001' "); + appendAiPfwFacilityFilterSql(sql, "aiPfwHeartbeat", "ai", "hb", baseId, startTime, endTime, rstcdList, paramMap); + sql.append("GROUP BY TO_CHAR(hb.TM, 'yyyy-MM-dd') ") + .append("UNION ") + .append("SELECT TO_CHAR(rec.TM, 'yyyy-MM-dd') AS dt ") + .append("FROM SD_AICOM_R rec ") + .append("INNER JOIN SD_AIMONITOR_B_H ai ON ai.STCD = rec.STCD ") + .append("WHERE NVL(rec.IS_DELETED, 0) = 0 ") + .append("AND NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP = 'AI_5001' "); + appendAiPfwFacilityFilterSql(sql, "aiPfwAicom", "ai", "rec", baseId, startTime, endTime, rstcdList, paramMap); + sql.append("GROUP BY TO_CHAR(rec.TM, 'yyyy-MM-dd') ") + .append(") a ") + .append("LEFT JOIN (") + .append("SELECT TO_CHAR(rec.TM, 'yyyy-MM-dd') AS dt, ") + .append("MAX(CASE ") + .append("WHEN rec.TYPE = 'AI_5001' AND rec.IS_BIG_DEBRIS_AREA IS NULL THEN 0 ") + .append("WHEN rec.TYPE = 'AI_5001' AND rec.IS_BIG_DEBRIS_AREA IS NOT NULL THEN rec.IS_BIG_DEBRIS_AREA ") + .append("END) AS isBigDebrisArea, ") + .append("MAX(CASE WHEN rec.TYPE = 'AI_5011' THEN 1 END) AS isClearDrift, ") + .append("LISTAGG(rec.FID, ',') WITHIN GROUP (ORDER BY rec.FID) AS fid ") + .append("FROM SD_AICOM_R rec ") + .append("INNER JOIN SD_AIMONITOR_B_H ai ON ai.STCD = rec.STCD ") + .append("WHERE NVL(rec.IS_DELETED, 0) = 0 ") + .append("AND NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP = 'AI_5001' ") + .append("AND rec.TYPE IN ('AI_5001', 'AI_5011') "); + appendAiPfwFacilityFilterSql(sql, "aiPfwStatus", "ai", "rec", baseId, startTime, endTime, rstcdList, paramMap); + sql.append("GROUP BY TO_CHAR(rec.TM, 'yyyy-MM-dd') ") + .append(") b ON a.dt = b.dt ") + .append("ORDER BY a.dt"); + return sql.toString(); + } + + private String buildAiRecordSql(String baseId, + Date startTime, + Date endTime, + List rstcdList, + String stcd, + String type, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT a.dt AS dt, b.cnt AS cnt ") + .append("FROM (") + .append("SELECT TO_CHAR(hb.TM, 'yyyy-MM-dd') AS dt ") + .append("FROM SD_AIHEARTBEAT_R hb ") + .append("INNER JOIN SD_AIMONITOR_B_H ai ON ai.STCD = hb.STCD ") + .append("WHERE NVL(hb.IS_DELETED, 0) = 0 ") + .append("AND NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP LIKE 'AI_%' "); + appendAiRecordFilterSql(sql, "aiRecordHeartbeat", "ai", "hb", baseId, startTime, endTime, rstcdList, stcd, type, paramMap); + sql.append("GROUP BY TO_CHAR(hb.TM, 'yyyy-MM-dd') ") + .append("UNION ") + .append("SELECT TO_CHAR(rec.TM, 'yyyy-MM-dd') AS dt ") + .append("FROM SD_AICOM_R rec ") + .append("INNER JOIN SD_AIMONITOR_B_H ai ON ai.STCD = rec.STCD ") + .append("WHERE NVL(rec.IS_DELETED, 0) = 0 ") + .append("AND NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP LIKE 'AI_%' "); + appendAiRecordFilterSql(sql, "aiRecordAicomDate", "ai", "rec", baseId, startTime, endTime, rstcdList, stcd, type, paramMap); + sql.append("GROUP BY TO_CHAR(rec.TM, 'yyyy-MM-dd') ") + .append(") a ") + .append("LEFT JOIN (") + .append("SELECT TO_CHAR(rec.TM, 'yyyy-MM-dd') AS dt, COUNT(1) AS cnt ") + .append("FROM SD_AICOM_R rec ") + .append("INNER JOIN SD_AIMONITOR_B_H ai ON ai.STCD = rec.STCD ") + .append("WHERE NVL(rec.IS_DELETED, 0) = 0 ") + .append("AND NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP LIKE 'AI_%' "); + appendAiRecordFilterSql(sql, "aiRecordAicomCnt", "ai", "rec", baseId, startTime, endTime, rstcdList, stcd, type, paramMap); + sql.append("GROUP BY TO_CHAR(rec.TM, 'yyyy-MM-dd') ") + .append(") b ON a.dt = b.dt ") + .append("ORDER BY a.dt"); + return sql.toString(); + } + + private String buildAlarmPointBaseSql() { + return "SELECT " + + "eng.STCD AS stcd, " + + "'ENG' AS sttp, " + + "eng.ENNM AS ennm, " + + "eng.ENNM AS titleName, " + + "eng.LOGO AS logo, " + + "eng.RVCD AS rvcd, " + + "eng.RVCD_NAME AS rvnm, " + + "eng.ADDVCD AS addvcd, " + + "eng.BASE_ID AS baseId, " + + "NVL(eng.BASE_NAME, hb.BASENAME) AS baseName, " + + "eng.LGTD AS lgtd, " + + "eng.LTTD AS lttd, " + + "eng.ELEV AS dtmel, " + + "eng.YRGEB AS ttpwr, " + + "'ENG' AS sttpMap, " + + "CASE WHEN eng.PRSC IN (1, 2) THEN 1 WHEN eng.PRSC = 3 THEN 2 END AS endInstalledType, " + + "CASE " + + " WHEN eng.PRSC IN (1, 2) AND NVL(eng.BLDSTT_CODE, 0) = 2 THEN 'large_eng_built' " + + " WHEN eng.PRSC IN (1, 2) AND NVL(eng.BLDSTT_CODE, 0) = 1 THEN 'large_eng_ubuilt' " + + " WHEN eng.PRSC IN (1, 2) THEN 'large_eng_nbuilt' " + + " WHEN eng.PRSC = 3 AND NVL(eng.BLDSTT_CODE, 0) = 2 THEN 'mid_eng_built' " + + " WHEN eng.PRSC = 3 AND NVL(eng.BLDSTT_CODE, 0) = 1 THEN 'mid_eng_ubuilt' " + + " WHEN eng.PRSC = 3 THEN 'mid_eng_nbuilt' " + + " ELSE NULL END AS anchoPointState, " + + "NVL(along.ORDER_INDEX, 999999) AS rvcdStepSort, " + + "NVL(rstSort.SORT, 999999) AS rstcdStepSort, " + + "NVL(siteSort.SORT, 999999) AS siteStepSort " + + "FROM SD_ENGINFO_B_H eng " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN MS_ALONG_B along ON along.RVCD = eng.HBRVCD AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 " + + "LEFT JOIN ( " + + " SELECT det.SORT, cfg.RVCD, det.STCD " + + " FROM MS_ALONGDET_B det " + + " INNER JOIN MS_ALONG_B cfg ON det.ALONG_ID = cfg.ID " + + " WHERE NVL(det.IS_DELETED, 0) = 0 AND NVL(cfg.IS_DELETED, 0) = 0 AND cfg.CODE = 'common' " + + ") rstSort ON rstSort.RVCD = eng.HBRVCD AND rstSort.STCD = eng.STCD " + + "LEFT JOIN ( " + + " SELECT det.SORT, cfg.RVCD, det.STCD " + + " FROM MS_ALONGDET_B det " + + " INNER JOIN MS_ALONG_B cfg ON det.ALONG_ID = cfg.ID " + + " WHERE NVL(det.IS_DELETED, 0) = 0 AND NVL(cfg.IS_DELETED, 0) = 0 AND cfg.CODE = 'common' " + + ") siteSort ON siteSort.RVCD = eng.HBRVCD AND siteSort.STCD = eng.STCD " + + "WHERE NVL(eng.IS_DELETED, 0) = 0 " + + "AND NVL(eng.USFL, 0) = 1 " + + "AND eng.LGTD IS NOT NULL " + + "AND eng.LTTD IS NOT NULL " + + "ORDER BY NVL(hb.ORDER_INDEX, 999999), NVL(along.ORDER_INDEX, 999999), NVL(siteSort.SORT, 999999), eng.ENNM"; + } + + private String buildAlarmPointCountSql() { + return "SELECT wr.STCD AS stcd, wr.STCD AS rstcd, COUNT(wr.STCD) AS count, 'QEC' AS ys " + + "FROM MS_WARN_RECORD_W wr " + + "WHERE NVL(wr.IS_DELETED, 0) = 0 " + + "AND wr.TB_ID IN (SELECT tb.ID FROM ST_TB_B tb WHERE tb.TB_CODE = 'QEC_R' AND NVL(tb.IS_DELETED, 0) = 0) " + + "AND wr.YS = 'QEC' " + + "AND wr.SFGB = 'N' " + + "AND wr.BTM BETWEEN #{map.alarmPointStartTime} AND #{map.alarmPointEndTime} " + + "GROUP BY wr.STCD " + + "UNION ALL " + + "SELECT wr.STCD AS stcd, wq.RSTCD AS rstcd, COUNT(wr.STCD) AS count, 'WQ' AS ys " + + "FROM MS_WARN_RECORD_W wr " + + "LEFT JOIN SD_WQ_B_H wq ON wr.STCD = wq.STCD AND NVL(wq.IS_DELETED, 0) = 0 " + + "WHERE NVL(wr.IS_DELETED, 0) = 0 " + + "AND wr.TB_ID IN (SELECT tb.ID FROM ST_TB_B tb WHERE tb.TB_CODE = 'WQ_R' AND NVL(tb.IS_DELETED, 0) = 0) " + + "AND wr.SFGB = 'N' " + + "AND wr.BTM BETWEEN #{map.alarmPointStartTime} AND #{map.alarmPointEndTime} " + + "AND wq.RSTCD IS NOT NULL " + + "GROUP BY wr.STCD, wq.RSTCD"; + } + + private String buildAlarmPointLegendSql() { + return "SELECT EXPRESSION AS expression, NAME_EN AS nameEn " + + "FROM MS_MAPLEGEND_B " + + "WHERE LAYER_CODE = 'eng_alarm_point' " + + "AND IF_SHOW = 1 " + + "AND NVL(IS_DELETED, 0) = 0 " + + "AND EXPRESSION IS NOT NULL " + + "ORDER BY NVL(ORDER_INDEX, 999999), ID"; + } + + private void appendAiRstcdCommonFilterSql(StringBuilder sql, + String keyPrefix, + String aiAlias, + String recordAlias, + String baseId, + Date startTime, + Date endTime, + Map paramMap) { + if (StrUtil.isNotBlank(baseId)) { + paramMap.put(keyPrefix + "BaseId", baseId.trim()); + sql.append("AND ").append(aiAlias).append(".BASE_ID = #{map.").append(keyPrefix).append("BaseId} "); + } + if (startTime != null) { + paramMap.put(keyPrefix + "StartTime", startTime); + sql.append("AND ").append(recordAlias).append(".TM >= #{map.").append(keyPrefix).append("StartTime} "); + } + if (endTime != null) { + paramMap.put(keyPrefix + "EndTime", endTime); + sql.append("AND ").append(recordAlias).append(".TM <= #{map.").append(keyPrefix).append("EndTime} "); + } + } + + private void appendAiRstcdTypeFilterSql(StringBuilder sql, + String keyPrefix, + String typeColumn, + String type, + Map paramMap) { + if (StrUtil.isBlank(type)) { + return; + } + paramMap.put(keyPrefix, type.trim()); + sql.append("AND ").append(typeColumn).append(" = #{map.").append(keyPrefix).append("} "); + } + + private void appendAiRstcdHeartbeatTypeFilterSql(StringBuilder sql, + String type, + Map paramMap) { + if (StrUtil.isBlank(type)) { + return; + } + String normalizedType = type.trim(); + if ("AI_5011".equalsIgnoreCase(normalizedType)) { + paramMap.put("aiRstcdHeartbeatType", "AI_5001"); + } else { + paramMap.put("aiRstcdHeartbeatType", normalizedType); + } + sql.append("AND ai.STTP = #{map.aiRstcdHeartbeatType} "); + } + + private void appendAiPfwFacilityFilterSql(StringBuilder sql, + String keyPrefix, + String aiAlias, + String recordAlias, + String baseId, + Date startTime, + Date endTime, + List rstcdList, + Map paramMap) { + if (StrUtil.isNotBlank(baseId)) { + paramMap.put(keyPrefix + "BaseId", baseId.trim()); + sql.append("AND ").append(aiAlias).append(".BASE_ID = #{map.").append(keyPrefix).append("BaseId} "); + } + if (CollUtil.isNotEmpty(rstcdList)) { + List placeholders = new ArrayList<>(); + for (int i = 0; i < rstcdList.size(); i++) { + String key = keyPrefix + "Rstcd" + i; + paramMap.put(key, rstcdList.get(i)); + placeholders.add("#{map." + key + "}"); + } + sql.append("AND ").append(aiAlias).append(".RSTCD IN (").append(String.join(", ", placeholders)).append(") "); + } + if (startTime != null) { + paramMap.put(keyPrefix + "StartTime", startTime); + sql.append("AND ").append(recordAlias).append(".TM >= #{map.").append(keyPrefix).append("StartTime} "); + } + if (endTime != null) { + paramMap.put(keyPrefix + "EndTime", endTime); + sql.append("AND ").append(recordAlias).append(".TM <= #{map.").append(keyPrefix).append("EndTime} "); + } + } + + private void appendAiRecordFilterSql(StringBuilder sql, + String keyPrefix, + String aiAlias, + String recordAlias, + String baseId, + Date startTime, + Date endTime, + List rstcdList, + String stcd, + String type, + Map paramMap) { + if (StrUtil.isNotBlank(baseId)) { + paramMap.put(keyPrefix + "BaseId", baseId.trim()); + sql.append("AND ").append(aiAlias).append(".BASE_ID = #{map.").append(keyPrefix).append("BaseId} "); + } + if (StrUtil.isNotBlank(stcd)) { + paramMap.put(keyPrefix + "Stcd", stcd.trim()); + sql.append("AND ").append(aiAlias).append(".STCD = #{map.").append(keyPrefix).append("Stcd} "); + } + if (StrUtil.isNotBlank(type)) { + paramMap.put(keyPrefix + "Type", type.trim()); + sql.append("AND ").append(aiAlias).append(".STTP = #{map.").append(keyPrefix).append("Type} "); + } + if (CollUtil.isNotEmpty(rstcdList)) { + List placeholders = new ArrayList<>(); + for (int i = 0; i < rstcdList.size(); i++) { + String key = keyPrefix + "Rstcd" + i; + paramMap.put(key, rstcdList.get(i)); + placeholders.add("#{map." + key + "}"); + } + sql.append("AND ").append(aiAlias).append(".RSTCD IN (").append(String.join(", ", placeholders)).append(") "); + } + if (startTime != null) { + paramMap.put(keyPrefix + "StartTime", startTime); + sql.append("AND ").append(recordAlias).append(".TM >= #{map.").append(keyPrefix).append("StartTime} "); + } + if (endTime != null) { + paramMap.put(keyPrefix + "EndTime", endTime); + sql.append("AND ").append(recordAlias).append(".TM <= #{map.").append(keyPrefix).append("EndTime} "); + } + } + + private Map buildAlarmPointYearRange(String yearText) { + Date endTime = new Date(); + String currentYear = String.valueOf(DateUtil.year(endTime)); + Date startTime = DateUtil.parse(currentYear + "-01-01"); + if (StrUtil.isNotBlank(yearText) && !currentYear.equals(yearText)) { + startTime = DateUtil.parse(yearText + "-01-01"); + endTime = DateUtil.parse(yearText + "-12-31"); + } + Map result = new HashMap<>(); + result.put("startTime", startTime); + result.put("endTime", endTime); + return result; + } + + private Map buildAlarmPointQecCountMap(List> countRows) { + Map result = new HashMap<>(); + if (CollUtil.isEmpty(countRows)) { + return result; + } + for (Map row : countRows) { + if (!"QEC".equalsIgnoreCase(safeString(firstPresentValue(row, "YS", "ys")))) { + continue; + } + String stcd = safeString(firstPresentValue(row, "RSTCD", "rstcd", "STCD", "stcd")); + if (StrUtil.isBlank(stcd)) { + continue; + } + result.put(stcd, toIntegerValue(firstPresentValue(row, "COUNT", "count"))); + } + return result; + } + + private Map buildAlarmPointWqCountMap(List> countRows) { + Map result = new HashMap<>(); + if (CollUtil.isEmpty(countRows)) { + return result; + } + for (Map row : countRows) { + if (!"WQ".equalsIgnoreCase(safeString(firstPresentValue(row, "YS", "ys")))) { + continue; + } + Integer count = toIntegerValue(firstPresentValue(row, "COUNT", "count")); + if (count == null) { + count = 0; + } + String rstcdText = safeString(firstPresentValue(row, "RSTCD", "rstcd")); + if (StrUtil.isBlank(rstcdText)) { + continue; + } + for (String rstcd : rstcdText.split(",")) { + String trimmed = StrUtil.trim(rstcd); + if (StrUtil.isBlank(trimmed)) { + continue; + } + result.put(trimmed, result.getOrDefault(trimmed, 0) + count); + } + } + return result; + } + + private List mergeAlarmPointData(List points, + Map qecCountMap, + Map wqCountMap, + List> expressionRows, + String yyyy) { + List result = new ArrayList<>(); + if (CollUtil.isEmpty(points)) { + return result; + } + for (AlarmPointVo point : points) { + if (point == null || !isAlarmPointVisible(point.getAnchoPointState())) { + continue; + } + point.setAnchoPointState(normalizeAlarmPointState(point.getAnchoPointState()) + "_ALARM"); + point.setStqCount(qecCountMap.getOrDefault(point.getStcd(), 0)); + point.setWqCount(wqCountMap.getOrDefault(point.getStcd(), 0)); + point.setZCount(0); + point.setWtCount(0); + point.setYyyy(yyyy); + point.setSttpCode("ENG"); + int total = point.getStqCount() + point.getWqCount(); + applyAlarmPointRange(point, total, expressionRows); + result.add(point); + } + return result; + } + + private boolean isAlarmPointVisible(String state) { + return "large_eng_built".equals(state) + || "mid_eng_built".equals(state) + || "large_eng_ubuilt".equals(state) + || "mid_eng_ubuilt".equals(state); + } + + private String normalizeAlarmPointState(String state) { + if ("large_eng_ubuilt".equals(state)) { + return "large_eng_built"; + } + if ("mid_eng_ubuilt".equals(state)) { + return "mid_eng_built"; + } + return state; + } + + private void applyAlarmPointRange(AlarmPointVo point, int total, List> expressionRows) { + if (point == null || CollUtil.isEmpty(expressionRows)) { + return; + } + for (Map row : expressionRows) { + String expression = safeString(firstPresentValue(row, "EXPRESSION", "expression")); + if (!matchesAlarmExpression(expression, total)) { + continue; + } + String nameEn = safeString(firstPresentValue(row, "NAMEEN", "nameEn", "NAME_EN")); + if (StrUtil.isNotBlank(nameEn)) { + point.setAnchoPointState(point.getAnchoPointState() + "_" + nameEn); + point.setRange(nameEn); + } + return; + } + } + + private boolean matchesAlarmExpression(String range, int value) { + if (StrUtil.isBlank(range)) { + return false; + } + if (range.matches("x=\\d+")) { + return value == Integer.parseInt(range.substring(2)); + } + if (range.matches("x>\\d+")) { + return value > Integer.parseInt(range.substring(2)); + } + if (range.matches("x>=\\d+")) { + return value >= Integer.parseInt(range.substring(3)); + } + if (range.matches("x<\\d+")) { + return value < Integer.parseInt(range.substring(2)); + } + if (range.matches("x<=\\d+")) { + return value <= Integer.parseInt(range.substring(3)); + } + if (range.matches("\\d+ Integer.parseInt(split[0]) && value < Integer.parseInt(split[1]); + } + if (range.matches("\\d+<=x<=\\d+")) { + String[] split = range.split("<=x<="); + return value >= Integer.parseInt(split[0]) && value <= Integer.parseInt(split[1]); + } + if (range.matches("\\d+ Integer.parseInt(split[0]) && value <= Integer.parseInt(split[1]); + } + if (range.matches("\\d+<=x<\\d+")) { + String[] split = range.split("<=x<"); + return value >= Integer.parseInt(split[0]) && value < Integer.parseInt(split[1]); + } + return false; + } + + private void fillAiPfwStatus(List list) { + if (CollUtil.isEmpty(list)) { + return; + } + for (AiRecordVo item : list) { + if (item == null) { + continue; + } + if (item.getIsBigDebrisArea() != null) { + if (item.getIsBigDebrisArea() == 0) { + item.setStatus(1); + } else { + item.setStatus(2); + } + } else { + item.setStatus(0); + } + item.setStatusName(resolveAiStatusName(item.getStatus())); + if (item.getIsClearDrift() != null) { + item.setQpStatus(5); + } else { + item.setQpStatus(6); + } + item.setQpStatusName(resolveAiStatusName(item.getQpStatus())); + } + } + + private void fillAiRecordStatus(List list) { + if (CollUtil.isEmpty(list)) { + return; + } + for (AiRecordVo item : list) { + if (item == null) { + continue; + } + if (item.getCnt() != null) { + item.setStatus(3); + } else { + item.setStatus(4); + } + item.setStatusName(resolveAiStatusName(item.getStatus())); + } + } + + private String resolveAiStatusName(Integer status) { + if (status == null) { + return null; + } + return switch (status) { + case -1 -> "未监测"; + case 0 -> "无漂浮物"; + case 1 -> "小面积漂浮物"; + case 2 -> "大面积漂浮物"; + case 3 -> "运行"; + case 4 -> "未运行"; + case 5 -> "清漂"; + case 6 -> "未清漂"; + default -> null; + }; + } + + private AiProtectVo buildAiProtectVo(Map row) { + if (row == null || row.isEmpty()) { + return null; + } + AiProtectVo vo = new AiProtectVo(); + vo.setFpYycCnt(toIntegerValue(firstPresentValue(row, "FPYYCCNT", "fpYycCnt"))); + vo.setFpGysCnt(toIntegerValue(firstPresentValue(row, "FPGYSCNT", "fpGysCnt"))); + vo.setFpSyjCnt(toIntegerValue(firstPresentValue(row, "FPSYJCNT", "fpSyjCnt"))); + vo.setFpAgvCnt(toIntegerValue(firstPresentValue(row, "FPAGVCNT", "fpAgvCnt"))); + vo.setFpYychCnt(toIntegerValue(firstPresentValue(row, "FPYYCHCNT", "fpYychCnt"))); + vo.setFpYdhCnt(toIntegerValue(firstPresentValue(row, "FPYDHCNT", "fpYdhCnt"))); + vo.setVpYhCnt(toIntegerValue(firstPresentValue(row, "VPYHCNT", "vpYhCnt"))); + return vo; + } + + private String buildEngWarnCountSql(String filterSql) { + String normalizedWarnStateExpr = "CASE " + + "WHEN t.WARN_STATE = '0' OR t.WARN_STATE IS NULL OR t.WARN_STATE = '' THEN '00' " + + "ELSE t.WARN_STATE END"; + StringBuilder sql = new StringBuilder(); + sql.append("SELECT s.warnState, COUNT(s.STCD) AS num, s.warnType ") + .append("FROM ("); + sql.append("SELECT DISTINCT ") + .append("t.STCD AS STCD, ") + .append("TO_NUMBER(SUBSTR(").append(normalizedWarnStateExpr).append(", 1, 1)) AS warnState, ") + .append("'RZ' AS warnType ") + .append("FROM SD_ENGINFO_B_H t ") + .append("WHERE NVL(t.IS_DELETED, 0) = 0 ") + .append("AND NVL(t.USFL, 0) = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append("UNION ALL "); + sql.append("SELECT DISTINCT ") + .append("t.STCD AS STCD, ") + .append("NVL(TO_NUMBER(SUBSTR(").append(normalizedWarnStateExpr).append(", 2, 1)), 0) AS warnState, ") + .append("'QEC' AS warnType ") + .append("FROM SD_ENGINFO_B_H t ") + .append("WHERE NVL(t.IS_DELETED, 0) = 0 ") + .append("AND NVL(t.BLDSTT_CODE, -1) = 2 ") + .append("AND NVL(t.DTIN, 0) = 1 ") + .append("AND NVL(t.RUN_STATE, 2) = 4 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(") s GROUP BY s.warnType, s.warnState"); + return sql.toString(); + } + + private String buildAiDmRunSql(String baseId, + Date startTime, + Date endTime, + List rstcdList, + String stnm, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("NVL(SUM(CASE WHEN rec.TYPE = 'AI_5001' THEN 1 ELSE 0 END), 0) AS pfwCnt, ") + .append("NVL(SUM(CASE WHEN rec.TYPE = 'AI_5011' THEN 1 ELSE 0 END), 0) AS pfwqlCnt, ") + .append("NVL(SUM(CASE WHEN rec.TYPE = 'AI_5005' THEN 1 ELSE 0 END), 0) AS dlmCnt ") + .append("FROM SD_AIMONITOR_B_H ai ") + .append("INNER JOIN SD_AICOM_R rec ON ai.STCD = rec.STCD ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = ai.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND NVL(rec.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP LIKE 'AI_%' ") + .append("AND rec.TYPE IN ('AI_5001', 'AI_5011', 'AI_5005') "); + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("aiBaseId", baseId.trim()); + sql.append("AND ai.BASE_ID = #{map.aiBaseId} "); + } + if (startTime != null) { + paramMap.put("aiStartTime", startTime); + sql.append("AND rec.TM >= #{map.aiStartTime} "); + } + if (endTime != null) { + paramMap.put("aiEndTime", endTime); + sql.append("AND rec.TM <= #{map.aiEndTime} "); + } + if (CollUtil.isNotEmpty(rstcdList)) { + List placeholders = new ArrayList<>(); + for (int i = 0; i < rstcdList.size(); i++) { + String key = "aiRstcd" + i; + paramMap.put(key, rstcdList.get(i)); + placeholders.add("#{map." + key + "}"); + } + sql.append("AND ai.RSTCD IN (").append(String.join(", ", placeholders)).append(") "); + } + if (StrUtil.isNotBlank(stnm)) { + paramMap.put("aiEnnm", "%" + stnm.trim() + "%"); + sql.append("AND eng.ENNM LIKE #{map.aiEnnm} "); + } + return sql.toString(); + } + + private String buildAiProtectSql(String baseId, + Date startTime, + Date endTime, + List rstcdList, + String stnm, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("aiStat.fpYycCnt AS fpYycCnt, ") + .append("aiStat.fpGysCnt AS fpGysCnt, ") + .append("aiStat.fpSyjCnt AS fpSyjCnt, ") + .append("aiStat.fpAgvCnt AS fpAgvCnt, ") + .append("aiStat.fpYychCnt AS fpYychCnt, ") + .append("aiStat.fpYdhCnt AS fpYdhCnt, ") + .append("vpStat.vpYhCnt AS vpYhCnt ") + .append("FROM (") + .append("SELECT ") + .append("NVL(SUM(CASE WHEN rec.TYPE = 'AI_5003' THEN 1 ELSE 0 END), 0) AS fpYycCnt, ") + .append("NVL(SUM(CASE WHEN rec.TYPE = 'AI_5006' THEN 1 ELSE 0 END), 0) AS fpGysCnt, ") + .append("NVL(SUM(CASE WHEN rec.TYPE = 'AI_5007' THEN 1 ELSE 0 END), 0) AS fpSyjCnt, ") + .append("NVL(SUM(CASE WHEN rec.TYPE = 'AI_5008' THEN 1 ELSE 0 END), 0) AS fpAgvCnt, ") + .append("NVL(SUM(CASE WHEN rec.TYPE = 'AI_5002' THEN 1 ELSE 0 END), 0) AS fpYychCnt, ") + .append("NVL(SUM(CASE WHEN rec.TYPE = 'AI_5012' THEN 1 ELSE 0 END), 0) AS fpYdhCnt ") + .append("FROM SD_AIMONITOR_B_H ai ") + .append("INNER JOIN SD_AICOM_R rec ON ai.STCD = rec.STCD ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = ai.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND NVL(rec.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP LIKE 'AI_%' ") + .append("AND rec.TYPE IN ('AI_5003', 'AI_5006', 'AI_5007', 'AI_5008', 'AI_5002', 'AI_5012') "); + appendAiProtectCommonFilterSql(sql, baseId, startTime, endTime, rstcdList, stnm, paramMap); + sql.append(") aiStat, (") + .append("SELECT COUNT(1) AS vpYhCnt ") + .append("FROM SD_AIMONITOR_B_H vpAi ") + .append("INNER JOIN SD_AIVPWATER_R vpRec ON vpAi.STCD = vpRec.STCD ") + .append("WHERE NVL(vpAi.IS_DELETED, 0) = 0 ") + .append("AND NVL(vpRec.IS_DELETED, 0) = 0 ") + .append("AND vpAi.STTP = 'AI_VP_WATER' "); + appendAiProtectVpFilterSql(sql, baseId, startTime, endTime, rstcdList, paramMap); + sql.append(") vpStat"); + return sql.toString(); + } + + private void appendAiProtectCommonFilterSql(StringBuilder sql, + String baseId, + Date startTime, + Date endTime, + List rstcdList, + String stnm, + Map paramMap) { + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("aiProtectBaseId", baseId.trim()); + sql.append("AND ai.BASE_ID = #{map.aiProtectBaseId} "); + } + if (startTime != null) { + paramMap.put("aiProtectStartTime", startTime); + sql.append("AND rec.TM >= #{map.aiProtectStartTime} "); + } + if (endTime != null) { + paramMap.put("aiProtectEndTime", endTime); + sql.append("AND rec.TM <= #{map.aiProtectEndTime} "); + } + if (CollUtil.isNotEmpty(rstcdList)) { + List placeholders = new ArrayList<>(); + for (int i = 0; i < rstcdList.size(); i++) { + String key = "aiProtectRstcd" + i; + paramMap.put(key, rstcdList.get(i)); + placeholders.add("#{map." + key + "}"); + } + sql.append("AND ai.RSTCD IN (").append(String.join(", ", placeholders)).append(") "); + } + if (StrUtil.isNotBlank(stnm)) { + paramMap.put("aiProtectEnnm", "%" + stnm.trim() + "%"); + sql.append("AND eng.ENNM LIKE #{map.aiProtectEnnm} "); + } + } + + private void appendAiProtectVpFilterSql(StringBuilder sql, + String baseId, + Date startTime, + Date endTime, + List rstcdList, + Map paramMap) { + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("aiProtectVpBaseId", baseId.trim()); + sql.append("AND vpAi.BASE_ID = #{map.aiProtectVpBaseId} "); + } + if (startTime != null) { + paramMap.put("aiProtectVpStartTime", startTime); + sql.append("AND vpRec.TM >= #{map.aiProtectVpStartTime} "); + } + if (endTime != null) { + paramMap.put("aiProtectVpEndTime", endTime); + sql.append("AND vpRec.TM <= #{map.aiProtectVpEndTime} "); + } + if (CollUtil.isNotEmpty(rstcdList)) { + List placeholders = new ArrayList<>(); + for (int i = 0; i < rstcdList.size(); i++) { + String key = "aiProtectVpRstcd" + i; + paramMap.put(key, rstcdList.get(i)); + placeholders.add("#{map." + key + "}"); + } + sql.append("AND vpAi.RSTCD IN (").append(String.join(", ", placeholders)).append(") "); + } + } + + private String buildAiComGroupSql(String detailSql, GroupingInfo[] groupInfos) { + if (groupInfos == null || groupInfos.length == 0) { + return detailSql; + } + List selectColumns = new ArrayList<>(); + List groupColumns = new ArrayList<>(); + for (GroupingInfo item : groupInfos) { + String column = mapAiComResultColumn("t", item.getSelector()); + if (StrUtil.isBlank(column)) { + continue; + } + String alias = item.getSelector(); + selectColumns.add(column + " AS " + alias); + selectColumns.add("COUNT(1) AS count_" + alias); + groupColumns.add(column); + } + if (selectColumns.isEmpty()) { + return detailSql; + } + return "SELECT " + String.join(", ", selectColumns) + + " FROM (" + detailSql + ") t GROUP BY " + String.join(", ", groupColumns); + } + + private String buildAiComOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return " ORDER BY r.tm DESC, r.recordTime DESC "; + } + List orderItems = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor item : sorts) { + if (item == null || StrUtil.isBlank(item.getField())) { + continue; + } + String column = mapAiComResultColumn("r", item.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(item.getDir()) ? "DESC" : "ASC"; + orderItems.add(column + " " + dir); + } + if (orderItems.isEmpty()) { + return " ORDER BY r.tm DESC, r.recordTime DESC "; + } + return " ORDER BY " + String.join(", ", orderItems); + } + + private String buildAiComFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + List parts = new ArrayList<>(); + if (CollUtil.isNotEmpty(filter.getFilters())) { + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildAiComFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + parts.add(childSql); + } + } + if (parts.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return "(" + String.join(logic, parts) + ")"; + } + String column = mapAiComBaseColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String paramKey = "aiComParam" + indexHolder[0]++; + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + Object value = filter.getValue(); + switch (operator) { + case "eq": + paramMap.put(paramKey, value); + return column + " = #{map." + paramKey + "}"; + case "neq": + paramMap.put(paramKey, value); + return column + " <> #{map." + paramKey + "}"; + case "contains": + paramMap.put(paramKey, "%" + safeString(value) + "%"); + return column + " LIKE #{map." + paramKey + "}"; + case "doesnotcontain": + paramMap.put(paramKey, "%" + safeString(value) + "%"); + return column + " NOT LIKE #{map." + paramKey + "}"; + case "startswith": + paramMap.put(paramKey, safeString(value) + "%"); + return column + " LIKE #{map." + paramKey + "}"; + case "endswith": + paramMap.put(paramKey, "%" + safeString(value)); + return column + " LIKE #{map." + paramKey + "}"; + case "gt": + paramMap.put(paramKey, normalizeAiValue(filter.getField(), value)); + return column + " > #{map." + paramKey + "}"; + case "gte": + paramMap.put(paramKey, normalizeAiValue(filter.getField(), value)); + return column + " >= #{map." + paramKey + "}"; + case "lt": + paramMap.put(paramKey, normalizeAiValue(filter.getField(), value)); + return column + " < #{map." + paramKey + "}"; + case "lte": + paramMap.put(paramKey, normalizeAiValue(filter.getField(), value)); + return column + " <= #{map." + paramKey + "}"; + case "isnull": + return column + " IS NULL"; + case "isnotnull": + return column + " IS NOT NULL"; + case "isempty": + return "(" + column + " IS NULL OR " + column + " = '')"; + case "isnotempty": + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + case "in": + return buildAiComInSql(column, value, paramKey, paramMap); + default: + return ""; + } + } + + private String buildAiComInSql(String column, Object value, String paramKey, Map paramMap) { + List values = parseAiCodes(value == null ? null : String.valueOf(value)); + if (CollUtil.isEmpty(values)) { + return ""; + } + List placeholders = new ArrayList<>(); + for (int i = 0; i < values.size(); i++) { + String key = paramKey + "_" + i; + paramMap.put(key, values.get(i)); + placeholders.add("#{map." + key + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + + private String mapAiComBaseColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "id" -> "rec.ID"; + case "type" -> "rec.TYPE"; + case "typeName" -> buildAiTypeNameExpr("rec.TYPE"); + case "stcd" -> "rec.STCD"; + case "stnm" -> "ai.STNM"; + case "rstcd" -> "ai.RSTCD"; + case "ennm", "stnmEng" -> "eng.ENNM"; + case "baseId" -> "ai.BASE_ID"; + case "hbrvcd" -> "ai.HBRVCD"; + case "rvcd" -> "ai.RVCD"; + case "tm" -> "rec.TM"; + case "endTm" -> "rec.END_TM"; + case "aiVal" -> "rec.AI_VAL"; + case "fid" -> "rec.FID"; + case "isFsf" -> "rec.IS_FSF"; + case "isBigDebrisArea" -> "rec.IS_BIG_DEBRIS_AREA"; + case "isClearDrift" -> "rec.IS_CLEAR_DRIFT"; + case "remark" -> "rec.REMARK"; + case "recordTime" -> "rec.RECORD_TIME"; + case "modifyTime" -> "rec.MODIFY_TIME"; + default -> null; + }; + } + + private String mapAiComResultColumn(String alias, String field) { + if (StrUtil.isBlank(alias) || StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "id" -> alias + ".id"; + case "type" -> alias + ".type"; + case "typeName" -> alias + ".typeName"; + case "stcd" -> alias + ".stcd"; + case "stnm" -> alias + ".stnm"; + case "rstcd" -> alias + ".rstcd"; + case "ennm", "stnmEng" -> alias + ".ennm"; + case "baseId" -> alias + ".baseId"; + case "hbrvcd" -> alias + ".hbrvcd"; + case "rvcd" -> alias + ".rvcd"; + case "tm" -> alias + ".tm"; + case "endTm" -> alias + ".endTm"; + case "aiVal" -> alias + ".aiVal"; + case "fid" -> alias + ".fid"; + case "isFsf" -> alias + ".isFsf"; + case "isBigDebrisArea" -> alias + ".isBigDebrisArea"; + case "isClearDrift" -> alias + ".isClearDrift"; + case "remark" -> alias + ".remark"; + case "recordTime" -> alias + ".recordTime"; + case "modifyTime" -> alias + ".modifyTime"; + default -> null; + }; + } + + private String buildAiTypeNameExpr(String typeColumn) { + return "CASE " + typeColumn + + " WHEN 'AI_5001' THEN '漂浮物' " + + " WHEN 'AI_5002' THEN '运鱼车运行' " + + " WHEN 'AI_5003' THEN '运鱼船出港' " + + " WHEN 'AI_5004' THEN '集鱼船集鱼' " + + " WHEN 'AI_5005' THEN '叠梁门运行' " + + " WHEN 'AI_5006' THEN '赶鱼栅运行' " + + " WHEN 'AI_5007' THEN '升鱼机运行' " + + " WHEN 'AI_5008' THEN 'AGV小车' " + + " WHEN 'AI_5009' THEN '鱼类暂养' " + + " WHEN 'AI_5010' THEN '坝上升鱼机' " + + " WHEN 'AI_5011' THEN '漂浮物清理' " + + " WHEN 'AI_5012' THEN '鱼道放流' " + + " ELSE " + typeColumn + " END"; + } + + private void fillWarnNames(List list) { + if (CollUtil.isEmpty(list)) { + return; + } + for (EngWarnCountVo item : list) { + if (item == null) { + continue; + } + item.setWarnStateName(resolveWarnStateName(item.getWarnState())); + item.setWarnTypeName(resolveWarnTypeName(item.getWarnType())); + } + } + + private String resolveWarnStateName(Integer warnState) { + if (warnState == null) { + return null; + } + return switch (warnState) { + case 0 -> "无数据"; + case 1 -> "正常"; + case 2 -> "告警"; + default -> null; + }; + } + + private String resolveWarnTypeName(String warnType) { + if ("RZ".equalsIgnoreCase(warnType)) { + return "电站水位"; + } + if ("QEC".equalsIgnoreCase(warnType)) { + return "生态流量"; + } + return null; + } + + private Date parseAiTime(String timeText) { + if (StrUtil.isBlank(timeText)) { + return null; + } + String value = timeText.trim(); + if (value.length() <= 10) { + return DateUtil.parse(value, "yyyy-MM-dd"); + } + return DateUtil.parse(value, "yyyy-MM-dd HH:mm:ss"); + } + + private List parseAiCodes(String codeText) { + if (StrUtil.isBlank(codeText)) { + return new ArrayList<>(); + } + String normalized = codeText.replace("[", "") + .replace("]", "") + .replace("\"", "") + .trim(); + if (StrUtil.isBlank(normalized)) { + return new ArrayList<>(); + } + List result = new ArrayList<>(); + for (String item : normalized.split(",")) { + String code = StrUtil.trim(item); + if (StrUtil.isNotBlank(code)) { + result.add(code); + } + } + return result; + } + + private Object firstPresentValue(Map row, String... keys) { + if (row == null || keys == null) { + return null; + } + for (String key : keys) { + if (row.containsKey(key)) { + return row.get(key); + } + } + return null; + } + + private Integer toIntegerValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof Number number) { + return number.intValue(); + } + String text = String.valueOf(value).trim(); + if (StrUtil.isBlank(text)) { + return null; + } + try { + return Integer.parseInt(text); + } catch (NumberFormatException ex) { + try { + return Double.valueOf(text).intValue(); + } catch (NumberFormatException ignore) { + return null; + } + } + } + + private Date toDateValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof Date date) { + return date; + } + if (value instanceof Number number) { + return new Date(number.longValue()); + } + String text = String.valueOf(value).trim(); + if (StrUtil.isBlank(text)) { + return null; + } + try { + return DateUtil.parse(text).toJdkDate(); + } catch (Exception ex) { + return null; + } + } + + private BigDecimal toBigDecimalValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof BigDecimal bigDecimal) { + return bigDecimal; + } + if (value instanceof Number number) { + return BigDecimal.valueOf(number.doubleValue()); + } + String text = String.valueOf(value).trim(); + if (StrUtil.isBlank(text)) { + return null; + } + try { + return new BigDecimal(text); + } catch (NumberFormatException ex) { + return null; + } + } + + private Object normalizeAiValue(String field, Object value) { + if (value == null) { + return null; + } + if ("tm".equals(field) || "endTm".equals(field) || "recordTime".equals(field) || "modifyTime".equals(field)) { + return parseAiTime(String.valueOf(value)); + } + return value; + } + + private String safeString(Object value) { + return value == null ? "" : String.valueOf(value).trim(); + } + + private String buildSourceFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildSourceLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildSourceFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildSourceLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapSourceColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + return buildSimpleCondition(column, "warnParam", filter, paramMap, indexHolder); + } + + private String buildSimpleCondition(String column, + String paramPrefix, + DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + Object value = filter.getValue(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("in".equals(operator)) { + List values = normalizeValues(value); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String paramKey = paramPrefix + indexHolder[0]++; + paramMap.put(paramKey, item); + placeholders.add("#{map." + paramKey + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + String paramKey = paramPrefix + indexHolder[0]++; + return switch (operator) { + case "eq" -> { + paramMap.put(paramKey, value); + yield column + " = #{map." + paramKey + "}"; + } + case "neq" -> { + paramMap.put(paramKey, value); + yield column + " <> #{map." + paramKey + "}"; + } + case "contains" -> { + paramMap.put(paramKey, "%" + value + "%"); + yield column + " LIKE #{map." + paramKey + "}"; + } + case "startswith" -> { + paramMap.put(paramKey, value + "%"); + yield column + " LIKE #{map." + paramKey + "}"; + } + case "endswith" -> { + paramMap.put(paramKey, "%" + value); + yield column + " LIKE #{map." + paramKey + "}"; + } + case "gt" -> { + paramMap.put(paramKey, value); + yield column + " > #{map." + paramKey + "}"; + } + case "gte" -> { + paramMap.put(paramKey, value); + yield column + " >= #{map." + paramKey + "}"; + } + case "lt" -> { + paramMap.put(paramKey, value); + yield column + " < #{map." + paramKey + "}"; + } + case "lte" -> { + paramMap.put(paramKey, value); + yield column + " <= #{map." + paramKey + "}"; + } + default -> ""; + }; + } + + private List normalizeValues(Object value) { + List values = new ArrayList<>(); + if (value instanceof List list) { + for (Object item : list) { + if (item != null) { + values.add(item); + } + } + return values; + } + if (value instanceof Object[] array) { + for (Object item : array) { + if (item != null) { + values.add(item); + } + } + return values; + } + if (value != null) { + values.add(value); + } + return values; + } + + private String buildOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY CASE r.warnType WHEN 'RZ' THEN 1 WHEN 'QEC' THEN 2 ELSE 99 END, r.warnState"; + } + List orderItems = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sortList) { + String column = mapResultColumn(sort == null ? null : sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderItems.add(column + " " + direction); + } + if (orderItems.isEmpty()) { + return " ORDER BY CASE r.warnType WHEN 'RZ' THEN 1 WHEN 'QEC' THEN 2 ELSE 99 END, r.warnState"; + } + return " ORDER BY " + String.join(", ", orderItems); + } + + private String mapSourceColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd", "rstcd" -> "t.STCD"; + case "ennm", "stnm" -> "t.ENNM"; + case "baseId" -> "t.BASE_ID"; + case "hbrvcd" -> "t.HBRVCD"; + case "rvcd" -> "t.RVCD"; + case "addvcd" -> "t.ADDVCD"; + case "country" -> "t.COUNTRY"; + case "reachcd" -> "t.REACHCD"; + case "hycd" -> "t.HYCD"; + case "usfl" -> "NVL(t.USFL, 0)"; + case "dtin" -> "NVL(t.DTIN, 0)"; + case "runState" -> "NVL(t.RUN_STATE, 2)"; + case "bldsttCode", "bldsttCcode" -> "NVL(t.BLDSTT_CODE, -1)"; + default -> null; + }; + } + + private String mapResultColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "warnState" -> "r.warnState"; + case "num" -> "r.num"; + case "warnType" -> "r.warnType"; + default -> null; + }; + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wq/controller/EnvWqDataController.java b/backend/src/main/java/com/yfd/platform/qgc_env/wq/controller/EnvWqDataController.java index 6d0a35b7..9a6709aa 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wq/controller/EnvWqDataController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wq/controller/EnvWqDataController.java @@ -2,7 +2,9 @@ package com.yfd.platform.qgc_env.wq.controller; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.annotation.Log; import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo; +import com.yfd.platform.qgc_env.wq.entity.vo.WqOperateRequest; import com.yfd.platform.qgc_env.wq.service.EnvWqDataService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -57,13 +59,18 @@ public class EnvWqDataController { return ResponseResult.successData(envWqDataService.getDrtpKendoListCust(dataSourceRequest)); } + @Log(module = "水质统计分析", value = "修改水质小时数据") @PostMapping("/updateWqRsData") @Operation(summary = "修改水质小时数据") - public ResponseResult updateWqRsData(@RequestBody Map updateData) { - envWqDataService.updateWqRsData(updateData); + public ResponseResult updateWqRsData(@RequestBody WqOperateRequest wqOperateRequest) { + envWqDataService.updateWqRsData( + wqOperateRequest == null ? null : wqOperateRequest.getUpdateData(), + wqOperateRequest == null ? null : wqOperateRequest.getSource() + ); return ResponseResult.success(); } + @Log(module = "水质统计分析", value = "删除水质小时/日/月数据") @PostMapping("/removeKendoByIds") @Operation(summary = "删除水质小时/日/月数据") public ResponseResult removeKendoByIds(@RequestBody BatchDeleteAo batchDeleteAo) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wq/entity/vo/WqOperateRequest.java b/backend/src/main/java/com/yfd/platform/qgc_env/wq/entity/vo/WqOperateRequest.java new file mode 100644 index 00000000..4b7d5050 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wq/entity/vo/WqOperateRequest.java @@ -0,0 +1,13 @@ +package com.yfd.platform.qgc_env.wq.entity.vo; + +import lombok.Data; + +import java.util.Map; + +@Data +public class WqOperateRequest { + + private String source; + + private Map updateData; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/EnvWqDataService.java b/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/EnvWqDataService.java index f23a3931..6a55e1da 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/EnvWqDataService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/EnvWqDataService.java @@ -39,7 +39,7 @@ public interface EnvWqDataService { DataSourceResult getStTbYsBVoKendoListCust(DataSourceRequest dataSourceRequest); - boolean updateWqRsData(Map updateData); + boolean updateWqRsData(Map updateData, String source); boolean removeKendoByIds(BatchDeleteAo batchDeleteAo); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/impl/EnvWqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/impl/EnvWqDataServiceImpl.java index 6910a908..e041cf54 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/impl/EnvWqDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/impl/EnvWqDataServiceImpl.java @@ -1,20 +1,18 @@ package com.yfd.platform.qgc_env.wq.service.impl; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.yfd.platform.common.CommonConstant; -import com.yfd.platform.common.DataSourceLoadOptionsBase; -import com.yfd.platform.common.DataSourceRequest; -import com.yfd.platform.common.DataSourceResult; -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.common.PageInfo; +import com.yfd.platform.common.*; import com.yfd.platform.common.exception.BizException; +import com.yfd.platform.qgc_base.domain.MsOperationLog; +import com.yfd.platform.qgc_base.domain.MsOperationLogDetail; import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo; import com.yfd.platform.qgc_base.entity.vo.DataParam; +import com.yfd.platform.qgc_base.mapper.MsOperationLogDetailMapper; +import com.yfd.platform.qgc_base.mapper.MsOperationLogMapper; import com.yfd.platform.qgc_env.wq.entity.vo.*; import com.yfd.platform.qgc_env.wq.service.EnvWqDataService; import com.yfd.platform.qgc_env.wt.entity.vo.WbsbVo; @@ -44,12 +42,114 @@ import java.util.stream.Collectors; @Service public class EnvWqDataServiceImpl implements EnvWqDataService { + private static final String WQ_HOUR_TABLE_NAME = "SD_WQ_R"; + private static final String WQ_DAY_TABLE_NAME = "SD_WQDAY_S"; + private static final String WQ_MONTH_TABLE_NAME = "SD_WQDRTP_S"; + private static final String WQ_STATION_TABLE_NAME = "SD_WQ_B_H"; + + private static final LinkedHashMap WQ_UPDATE_COLUMN_MAP = new LinkedHashMap<>(); + private static final Map WQ_FIELD_MEANING_MAP = new LinkedHashMap<>(); + static { + WQ_UPDATE_COLUMN_MAP.put("wtmp", "WTMP"); + WQ_UPDATE_COLUMN_MAP.put("ph", "PH"); + WQ_UPDATE_COLUMN_MAP.put("dox", "DOX"); + WQ_UPDATE_COLUMN_MAP.put("codmn", "CODMN"); + WQ_UPDATE_COLUMN_MAP.put("codcr", "CODCR"); + WQ_UPDATE_COLUMN_MAP.put("bod5", "BOD5"); + WQ_UPDATE_COLUMN_MAP.put("nh3n", "NH3N"); + WQ_UPDATE_COLUMN_MAP.put("tp", "TP"); + WQ_UPDATE_COLUMN_MAP.put("tn", "TN"); + WQ_UPDATE_COLUMN_MAP.put("cu", "CU"); + WQ_UPDATE_COLUMN_MAP.put("zn", "ZN"); + WQ_UPDATE_COLUMN_MAP.put("f", "F"); + WQ_UPDATE_COLUMN_MAP.put("se", "SE"); + WQ_UPDATE_COLUMN_MAP.put("ars", "ARS"); + WQ_UPDATE_COLUMN_MAP.put("hg", "HG"); + WQ_UPDATE_COLUMN_MAP.put("cd", "CD"); + WQ_UPDATE_COLUMN_MAP.put("cr6", "CR6"); + WQ_UPDATE_COLUMN_MAP.put("pb", "PB"); + WQ_UPDATE_COLUMN_MAP.put("cn", "CN"); + WQ_UPDATE_COLUMN_MAP.put("vlph", "VLPH"); + WQ_UPDATE_COLUMN_MAP.put("oil", "OIL"); + WQ_UPDATE_COLUMN_MAP.put("las", "LAS"); + WQ_UPDATE_COLUMN_MAP.put("s2", "S2"); + WQ_UPDATE_COLUMN_MAP.put("fcg", "FCG"); + WQ_UPDATE_COLUMN_MAP.put("cl", "CL"); + WQ_UPDATE_COLUMN_MAP.put("so4", "SO4"); + WQ_UPDATE_COLUMN_MAP.put("no3", "NO3"); + WQ_UPDATE_COLUMN_MAP.put("thrd", "THRD"); + WQ_UPDATE_COLUMN_MAP.put("cond", "COND"); + WQ_UPDATE_COLUMN_MAP.put("fe", "FE"); + WQ_UPDATE_COLUMN_MAP.put("mn", "MN"); + WQ_UPDATE_COLUMN_MAP.put("al", "AL"); + WQ_UPDATE_COLUMN_MAP.put("chla", "CHLA"); + WQ_UPDATE_COLUMN_MAP.put("clarity", "CLARITY"); + WQ_UPDATE_COLUMN_MAP.put("tu", "TU"); + WQ_UPDATE_COLUMN_MAP.put("cyano", "CYANO"); + WQ_UPDATE_COLUMN_MAP.put("wqgrd", "WQGRD"); + WQ_UPDATE_COLUMN_MAP.put("sfdb", "SFDB"); + WQ_UPDATE_COLUMN_MAP.put("wqSfdbhnYs", "WQ_SFDBHN_YS"); + + WQ_FIELD_MEANING_MAP.put("STCD", "站点编码"); + WQ_FIELD_MEANING_MAP.put("TM", "监测时间"); + WQ_FIELD_MEANING_MAP.put("DT", "统计日期"); + WQ_FIELD_MEANING_MAP.put("DRTP", "统计类型"); + WQ_FIELD_MEANING_MAP.put("YEAR", "年份"); + WQ_FIELD_MEANING_MAP.put("MONTH", "月份"); + WQ_FIELD_MEANING_MAP.put("WTMP", "水温"); + WQ_FIELD_MEANING_MAP.put("PH", "酸碱度"); + WQ_FIELD_MEANING_MAP.put("DOX", "溶解氧"); + WQ_FIELD_MEANING_MAP.put("CODMN", "高锰酸盐指数"); + WQ_FIELD_MEANING_MAP.put("CODCR", "化学需氧量"); + WQ_FIELD_MEANING_MAP.put("BOD5", "五日生化需氧量"); + WQ_FIELD_MEANING_MAP.put("NH3N", "氨氮"); + WQ_FIELD_MEANING_MAP.put("TP", "总磷"); + WQ_FIELD_MEANING_MAP.put("TN", "总氮"); + WQ_FIELD_MEANING_MAP.put("CU", "铜"); + WQ_FIELD_MEANING_MAP.put("ZN", "锌"); + WQ_FIELD_MEANING_MAP.put("F", "氟化物"); + WQ_FIELD_MEANING_MAP.put("SE", "硒"); + WQ_FIELD_MEANING_MAP.put("ARS", "砷"); + WQ_FIELD_MEANING_MAP.put("HG", "汞"); + WQ_FIELD_MEANING_MAP.put("CD", "镉"); + WQ_FIELD_MEANING_MAP.put("CR6", "六价铬"); + WQ_FIELD_MEANING_MAP.put("PB", "铅"); + WQ_FIELD_MEANING_MAP.put("CN", "氰化物"); + WQ_FIELD_MEANING_MAP.put("VLPH", "挥发酚"); + WQ_FIELD_MEANING_MAP.put("OIL", "石油类"); + WQ_FIELD_MEANING_MAP.put("LAS", "阴离子表面活性剂"); + WQ_FIELD_MEANING_MAP.put("S2", "硫化物"); + WQ_FIELD_MEANING_MAP.put("FCG", "粪大肠菌群"); + WQ_FIELD_MEANING_MAP.put("CL", "氯化物"); + WQ_FIELD_MEANING_MAP.put("SO4", "硫酸盐"); + WQ_FIELD_MEANING_MAP.put("NO3", "硝酸盐"); + WQ_FIELD_MEANING_MAP.put("THRD", "总硬度"); + WQ_FIELD_MEANING_MAP.put("COND", "电导率"); + WQ_FIELD_MEANING_MAP.put("FE", "铁"); + WQ_FIELD_MEANING_MAP.put("MN", "锰"); + WQ_FIELD_MEANING_MAP.put("AL", "铝"); + WQ_FIELD_MEANING_MAP.put("CHLA", "叶绿素a"); + WQ_FIELD_MEANING_MAP.put("CLARITY", "透明度"); + WQ_FIELD_MEANING_MAP.put("TU", "浊度"); + WQ_FIELD_MEANING_MAP.put("CYANO", "蓝绿藻"); + WQ_FIELD_MEANING_MAP.put("WQGRD", "水质类别"); + WQ_FIELD_MEANING_MAP.put("WWQTG", "水功能区目标"); + WQ_FIELD_MEANING_MAP.put("SFDB", "是否达标"); + WQ_FIELD_MEANING_MAP.put("WQ_SFDBHN_YS", "是否达标湖内饮用水源"); + } + @Resource private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; @Resource private JdbcTemplate jdbcTemplate; + @Resource + private MsOperationLogMapper msOperationLogMapper; + + @Resource + private MsOperationLogDetailMapper msOperationLogDetailMapper; + @Override public DataSourceResult processKendoList(DataSourceRequest dataSourceRequest) { boolean calculated = CommonConstant.CALCULATE_SUCCESS.equals( @@ -694,6 +794,7 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { baseSql.append("SELECT ") .append("NVL(t.IS_DELETED, 0) AS isDeleted, ") .append("t.STTP AS sttpCode, ") + .append("t.WARN_STATE AS warnState, ") .append("t.MWAY AS mway, ") .append("t.DTIN_TYPE AS dtinType, ") .append("t.STCD AS stcd, ") @@ -731,6 +832,8 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { DataSourceResult result = new DataSourceResult(); if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { result.setData(new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else if (groupInfos != null && groupInfos.length == 1 && groupInfos[0] != null && StrUtil.isNotBlank(groupInfos[0].getSelector())) { + result.setData(toMsstbprptLegacyGroups(rows, groupInfos[0].getSelector())); } else { result.setData(toLegacyGroupResult(new GroupHelper().group(rows, Arrays.asList(groupInfos)), 0)); } @@ -3181,14 +3284,17 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { return result; } String upperField = groupField == null ? "DTINTYPE" : groupField.toUpperCase(); - String countField = "COUNT_" + upperField; - String aggregateKey = "count_" + groupField; for (Map row : rows) { Object key = row.get(upperField); if (key == null) { key = row.get(groupField); } + String countField = row.containsKey("COUNT_STCD") ? "COUNT_STCD" : "COUNT_" + upperField; + String aggregateKey = "COUNT_STCD".equals(countField) ? "count_stcd" : "count_" + groupField; Object countValue = row.get(countField); + if (countValue == null) { + countValue = row.get("count_stcd"); + } if (countValue == null) { countValue = row.get("count_" + upperField); } @@ -3208,7 +3314,7 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { detail.put(upperField, key); detail.put(countField, count); item.put("items", List.of(detail)); - item.put("count", count); + item.put("count", 0); item.put("summary", new Object[0]); Map aggregates = new LinkedHashMap<>(); @@ -3224,27 +3330,52 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { return baseSql; } List groupFields = new ArrayList<>(); + List selectItems = new ArrayList<>(); List orderByItems = new ArrayList<>(); for (GroupingInfo item : groupInfos) { if (item == null || StrUtil.isBlank(item.getSelector())) { continue; } - groupFields.add(item.getSelector()); + String selector = item.getSelector(); + groupFields.add(selector); + selectItems.add(selector + " AS " + selector.toUpperCase()); String dir = Boolean.TRUE.equals(item.getDesc()) ? "DESC" : "ASC"; - orderByItems.add(item.getSelector() + " " + dir); + orderByItems.add(selector + " " + dir); + boolean hasCountStcd = false; + if (CollUtil.isNotEmpty(item.getSummaryInfos())) { + for (SummaryInfo summaryInfo : item.getSummaryInfos()) { + if (summaryInfo == null || StrUtil.isBlank(summaryInfo.getSelector()) || StrUtil.isBlank(summaryInfo.getSummaryType())) { + continue; + } + String summaryType = summaryInfo.getSummaryType().toUpperCase(); + String summarySelector = summaryInfo.getSelector().toUpperCase(); + if ("count".equalsIgnoreCase(summaryInfo.getSummaryType()) && "stcd".equalsIgnoreCase(summaryInfo.getSelector())) { + hasCountStcd = true; + } + switch (summaryInfo.getSummaryType().toLowerCase()) { + case "count" -> selectItems.add("COUNT(" + summaryInfo.getSelector() + ") AS " + summaryType + "_" + summarySelector); + case "sum" -> selectItems.add("SUM(" + summaryInfo.getSelector() + ") AS " + summaryType + "_" + summarySelector); + case "avg", "average" -> selectItems.add("AVG(" + summaryInfo.getSelector() + ") AS AVG_" + summarySelector); + case "min" -> selectItems.add("MIN(" + summaryInfo.getSelector() + ") AS " + summaryType + "_" + summarySelector); + case "max" -> selectItems.add("MAX(" + summaryInfo.getSelector() + ") AS " + summaryType + "_" + summarySelector); + default -> { + } + } + } + } + if (!hasCountStcd) { + selectItems.add("COUNT(*) AS COUNT_STCD"); + } } if (groupFields.isEmpty()) { return baseSql; } StringBuilder sql = new StringBuilder("SELECT "); - sql.append(String.join(", ", groupFields)); - for (String groupField : groupFields) { - sql.append(", COUNT(*) AS count_").append(groupField).append(" "); - } - sql.append("FROM (").append(baseSql).append(") T ") - .append("GROUP BY ").append(String.join(", ", groupFields)).append(" "); + sql.append(String.join(", ", selectItems)); + sql.append(" FROM (").append(baseSql).append(") T ") + .append(" GROUP BY ").append(String.join(", ", groupFields)).append(" "); if (!orderByItems.isEmpty()) { - sql.append("ORDER BY ").append(String.join(", ", orderByItems)); + sql.append(" ORDER BY ").append(String.join(", ", orderByItems)); } return sql.toString(); } @@ -3648,15 +3779,18 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { @Override @Transactional(rollbackFor = Exception.class) - public boolean updateWqRsData(Map updateData) { + public boolean updateWqRsData(Map updateData, String source) { if (updateData == null || updateData.isEmpty()) { return true; } - updateWqHourData(updateData); - updateWqTargetIfNeeded(updateData); - String stcd = asString(updateData.get("stcd")); String tm = asString(updateData.get("tm")); + Map beforeHour = queryWqHourRow(stcd, tm); + Map beforeStation = queryWqStationRow(stcd); + updateWqHourData(updateData); + updateWqTargetIfNeeded(updateData); + recordWqUpdateLog(beforeHour, beforeStation, updateData, source); + if (StrUtil.isNotBlank(stcd) && StrUtil.isNotBlank(tm) && tm.length() >= 10) { String dateStr = tm.substring(0, 10); statisticsDayDataFromHour(stcd, dateStr, dateStr); @@ -3681,17 +3815,24 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { return true; } String dataType = StrUtil.blankToDefault(batchDeleteAo.getDataType(), "").toUpperCase(); + String source = batchDeleteAo == null ? null : batchDeleteAo.getSource(); int batchSize = 500; for (int i = 0; i < dataList.size(); i += batchSize) { List subList = dataList.subList(i, Math.min(i + batchSize, dataList.size())); if ("MON".equals(dataType)) { + List> beforeRows = queryWqMonthRows(subList); softDeleteWqMonthData(subList); + recordWqDeleteLog(beforeRows, WQ_MONTH_TABLE_NAME, "删除水质月数据", source); } if ("DATE".equals(dataType)) { + List> beforeRows = queryWqDayRows(subList); softDeleteWqDayData(subList); + recordWqDeleteLog(beforeRows, WQ_DAY_TABLE_NAME, "删除水质日数据", source); } if ("TIME".equals(dataType)) { + List> beforeRows = queryWqHourRows(subList); deleteWqHourData(subList); + recordWqDeleteLog(beforeRows, WQ_HOUR_TABLE_NAME, "删除水质小时数据", source); Map dateRangeMap = new HashMap<>(); Map monthRangeMap = new HashMap<>(); @@ -3742,50 +3883,9 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { } private void updateWqHourData(Map updateData) { - LinkedHashMap columnMap = new LinkedHashMap<>(); - columnMap.put("wtmp", "WTMP"); - columnMap.put("ph", "PH"); - columnMap.put("dox", "DOX"); - columnMap.put("codmn", "CODMN"); - columnMap.put("codcr", "CODCR"); - columnMap.put("bod5", "BOD5"); - columnMap.put("nh3n", "NH3N"); - columnMap.put("tp", "TP"); - columnMap.put("tn", "TN"); - columnMap.put("cu", "CU"); - columnMap.put("zn", "ZN"); - columnMap.put("f", "F"); - columnMap.put("se", "SE"); - columnMap.put("ars", "ARS"); - columnMap.put("hg", "HG"); - columnMap.put("cd", "CD"); - columnMap.put("cr6", "CR6"); - columnMap.put("pb", "PB"); - columnMap.put("cn", "CN"); - columnMap.put("vlph", "VLPH"); - columnMap.put("oil", "OIL"); - columnMap.put("las", "LAS"); - columnMap.put("s2", "S2"); - columnMap.put("fcg", "FCG"); - columnMap.put("cl", "CL"); - columnMap.put("so4", "SO4"); - columnMap.put("no3", "NO3"); - columnMap.put("thrd", "THRD"); - columnMap.put("cond", "COND"); - columnMap.put("fe", "FE"); - columnMap.put("mn", "MN"); - columnMap.put("al", "AL"); - columnMap.put("chla", "CHLA"); - columnMap.put("clarity", "CLARITY"); - columnMap.put("tu", "TU"); - columnMap.put("cyano", "CYANO"); - columnMap.put("wqgrd", "WQGRD"); - columnMap.put("sfdb", "SFDB"); - columnMap.put("wqSfdbhnYs", "WQ_SFDBHN_YS"); - List setClauses = new ArrayList<>(); List params = new ArrayList<>(); - for (Map.Entry entry : columnMap.entrySet()) { + for (Map.Entry entry : WQ_UPDATE_COLUMN_MAP.entrySet()) { if (updateData.containsKey(entry.getKey())) { setClauses.add(entry.getValue() + " = ?"); params.add(updateData.get(entry.getKey())); @@ -3886,6 +3986,286 @@ public class EnvWqDataServiceImpl implements EnvWqDataService { jdbcTemplate.update(sql.toString(), params.toArray()); } + private Map queryWqHourRow(String stcd, String tm) { + if (StrUtil.isBlank(stcd) || StrUtil.isBlank(tm)) { + return new HashMap<>(); + } + String sql = "SELECT " + buildWqHourLogSelectColumns() + + " FROM SD_WQ_R WHERE STCD = ? AND TM = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS')"; + List> rows = jdbcTemplate.queryForList(sql, stcd, tm); + return rows.isEmpty() ? new HashMap<>() : normalizeLogRow(rows.getFirst()); + } + + private Map queryWqStationRow(String stcd) { + if (StrUtil.isBlank(stcd)) { + return new HashMap<>(); + } + String sql = "SELECT STCD, WWQTG FROM SD_WQ_B_H WHERE STCD = ? AND NVL(IS_DELETED, 0) = 0"; + List> rows = jdbcTemplate.queryForList(sql, stcd); + return rows.isEmpty() ? new HashMap<>() : normalizeLogRow(rows.getFirst()); + } + + private List> queryWqHourRows(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return new ArrayList<>(); + } + StringBuilder sql = new StringBuilder("SELECT ") + .append(buildWqHourLogSelectColumns()) + .append(" FROM SD_WQ_R WHERE "); + List params = new ArrayList<>(); + appendHourRowConditions(sql, params, dataParamList); + return normalizeLogRows(jdbcTemplate.queryForList(sql.toString(), params.toArray())); + } + + private List> queryWqDayRows(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return new ArrayList<>(); + } + StringBuilder sql = new StringBuilder("SELECT ") + .append(buildWqDayLogSelectColumns()) + .append(" FROM SD_WQDAY_S WHERE "); + List params = new ArrayList<>(); + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" OR "); + } + sql.append("(STCD = ? AND DT = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS'))"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getDt()); + } + return normalizeLogRows(jdbcTemplate.queryForList(sql.toString(), params.toArray())); + } + + private List> queryWqMonthRows(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return new ArrayList<>(); + } + StringBuilder sql = new StringBuilder("SELECT ") + .append(buildWqMonthLogSelectColumns()) + .append(" FROM SD_WQDRTP_S WHERE "); + List params = new ArrayList<>(); + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" OR "); + } + sql.append("(STCD = ? AND DRTP = ? AND YEAR = ? AND MONTH = ?)"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getDrtp()); + params.add(item == null ? null : item.getYear()); + params.add(item == null ? null : item.getMonth()); + } + return normalizeLogRows(jdbcTemplate.queryForList(sql.toString(), params.toArray())); + } + + private void appendHourRowConditions(StringBuilder sql, List params, List dataParamList) { + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" OR "); + } + sql.append("(STCD = ? AND TM = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS'))"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getTm()); + } + } + + private String buildWqHourLogSelectColumns() { + return "ID,STCD, TO_CHAR(TM, 'YYYY-MM-DD HH24:MI:SS') AS TM, " + + "WTMP, PH, DOX, CODMN, CODCR, BOD5, NH3N, TP, TN, CU, ZN, F, SE, ARS, HG, CD, CR6, PB, CN, " + + "VLPH, OIL, LAS, S2, FCG, CL, SO4, NO3, THRD, COND, FE, MN, AL, CHLA, CLARITY, TU, CYANO, " + + "WQGRD, SFDB, WQ_SFDBHN_YS"; + } + + private String buildWqDayLogSelectColumns() { + return "STCD, TO_CHAR(DT, 'YYYY-MM-DD HH24:MI:SS') AS DT, " + + "WTMP, PH, DOX, CODMN, CODCR, BOD5, NH3N, TP, TN, CU, ZN, F, SE, ARS, HG, CD, CR6, PB, CN, " + + "VLPH, OIL, LAS, S2, FCG, CL, SO4, NO3, THRD, COND, FE, MN, AL, CHLA, CLARITY, TU, CYANO, " + + "WQGRD, SFDB, IS_DELETED"; + } + + private String buildWqMonthLogSelectColumns() { + return "STCD, DRTP, YEAR, MONTH, " + + "WTMP, PH, DOX, CODMN, CODCR, BOD5, NH3N, TP, TN, CU, ZN, F, SE, ARS, HG, CD, CR6, PB, CN, " + + "VLPH, OIL, LAS, S2, FCG, CL, SO4, NO3, THRD, COND, FE, MN, AL, CHLA, CLARITY, TU, CYANO, " + + "WQGRD, SFDB, IS_DELETED"; + } + + private List> normalizeLogRows(List> rows) { + List> result = new ArrayList<>(); + if (CollUtil.isEmpty(rows)) { + return result; + } + for (Map row : rows) { + result.add(normalizeLogRow(row)); + } + return result; + } + + private Map normalizeLogRow(Map row) { + Map normalized = new LinkedHashMap<>(); + if (row == null || row.isEmpty()) { + return normalized; + } + for (Map.Entry entry : row.entrySet()) { + normalized.put(entry.getKey() == null ? null : entry.getKey().toUpperCase(), entry.getValue()); + } + return normalized; + } + + private void recordWqUpdateLog(Map beforeHour, + Map beforeStation, + Map updateData, + String source) { + if (updateData == null || updateData.isEmpty()) { + return; + } + String stcd = asString(updateData.get("stcd")); + List details = new ArrayList<>(); + for (Map.Entry entry : WQ_UPDATE_COLUMN_MAP.entrySet()) { + if (!updateData.containsKey(entry.getKey())) { + continue; + } + String column = entry.getValue(); + Object oldValue = beforeHour == null ? null : beforeHour.get(column); + Object newValue = updateData.get(entry.getKey()); + if (StrUtil.equals(formatLogValue(oldValue), formatLogValue(newValue))) { + continue; + } + details.add(buildWqDetail(null, WQ_HOUR_TABLE_NAME, stcd, column, + oldValue, resolveWqDisplayValue(column, oldValue), + newValue, resolveWqDisplayValue(column, newValue), "修改字段值")); + } + if (updateData.containsKey("wwqtg")) { + Object oldValue = beforeStation == null ? null : beforeStation.get("WWQTG"); + Object newValue = updateData.get("wwqtg"); + if (!StrUtil.equals(formatLogValue(oldValue), formatLogValue(newValue))) { + details.add(buildWqDetail(null, WQ_STATION_TABLE_NAME, stcd, "WWQTG", + oldValue, resolveWqDisplayValue("WWQTG", oldValue), + newValue, resolveWqDisplayValue("WWQTG", newValue), "修改字段值")); + } + } + if (details.isEmpty()) { + return; + } + String recordId = ObjectUtil.isNotEmpty(beforeHour) && ObjectUtil.isNotEmpty(beforeHour.get("ID")) + ? beforeHour.get("ID").toString() + : null; MsOperationLog mainLog = buildWqMainLog(recordId,"修改水质小时数据", source); + msOperationLogMapper.insert(mainLog); + for (MsOperationLogDetail detail : details) { + detail.setMainId(mainLog.getId()); + } + batchInsertWqLogDetails(details); + } + + private void recordWqDeleteLog(List> rows, String tableName, String remark, String source) { + if (CollUtil.isEmpty(rows)) { + return; + } + List details = new ArrayList<>(); + for (Map row : rows) { + String stcd = asString(row.get("STCD")); + String recordId = asString(row.get("ID")); + MsOperationLog mainLog = buildWqMainLog(recordId,remark, source); + msOperationLogMapper.insert(mainLog); + for (Map.Entry entry : row.entrySet()) { + String fieldCode = entry.getKey(); + if (StrUtil.isBlank(fieldCode)) { + continue; + } + Object oldValue = entry.getValue(); + if (oldValue == null) { + continue; + } + details.add(buildWqDetail(mainLog.getId(), tableName, stcd, fieldCode, + oldValue, resolveWqDisplayValue(fieldCode, oldValue), + null, null, "删除字段值")); + } + } + batchInsertWqLogDetails(details); + } + + private MsOperationLog buildWqMainLog(String recordId,String remark, String source) { + MsOperationLog log = new MsOperationLog(); + log.setOperator(resolveLogOperator()); + log.setRecordId(recordId); + log.setOperateTime(new Date()); + log.setTableName(WQ_HOUR_TABLE_NAME); + log.setSource(StrUtil.trimToNull(source)); + log.setRemark(remark); + return log; + } + + private MsOperationLogDetail buildWqDetail(String mainId, + String tableName, + String stationCode, + String fieldCode, + Object oldValueCode, + Object oldValueName, + Object newValueCode, + Object newValueName, + String remark) { + MsOperationLogDetail detail = new MsOperationLogDetail(); + detail.setMainId(mainId); + detail.setTableName(tableName); + detail.setStationCode(stationCode); + detail.setFieldCode(fieldCode); + detail.setFieldMeaning(WQ_FIELD_MEANING_MAP.getOrDefault(fieldCode, fieldCode)); + detail.setOldValueCode(formatLogValue(oldValueCode)); + detail.setOldValueName(formatLogValue(oldValueName)); + detail.setNewValueCode(formatLogValue(newValueCode)); + detail.setNewValueName(formatLogValue(newValueName)); + detail.setRemark(remark); + return detail; + } + + private void batchInsertWqLogDetails(List details) { + if (CollUtil.isEmpty(details)) { + return; + } + for (MsOperationLogDetail detail : details) { + if (detail == null) { + continue; + } + msOperationLogDetailMapper.insert(detail); + } + } + + private Object resolveWqDisplayValue(String fieldCode, Object rawValue) { + String text = formatLogValue(rawValue); + if (StrUtil.isBlank(text)) { + return rawValue; + } + return switch (fieldCode) { + case "WQGRD", "WWQTG" -> getWqLevelName(text); + case "SFDB" -> parseInteger(text) == null ? text : getSfdbName(parseInteger(text)); + default -> text; + }; + } + + private String resolveLogOperator() { + try { + return SecurityUtils.getCurrentUsername(); + } catch (Exception ignored) { + try { + return SecurityUtils.getUserId(); + } catch (Exception ex) { + return null; + } + } + } + + private String formatLogValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof Date date) { + return DateUtil.formatDateTime(date); + } + return String.valueOf(value); + } + private String getMonthEndDate(Integer year, Integer month) { Calendar calendar = Calendar.getInstance(); calendar.set(year, month - 1, 1); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/controller/SdWTMonitorController.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/controller/SdWTMonitorController.java index e1bc5b59..8212bef8 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/controller/SdWTMonitorController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/controller/SdWTMonitorController.java @@ -2,13 +2,16 @@ package com.yfd.platform.qgc_env.wt.controller; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.annotation.Log; import com.yfd.platform.common.DataSourceLoadOptionsBase; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; import com.yfd.platform.common.exception.BizException; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo; +import com.yfd.platform.qgc_env.wt.entity.vo.WtOperateRequest; import com.yfd.platform.qgc_env.wt.entity.vo.WtrvInfo; +import com.yfd.platform.qgc_env.wt.entity.vo.WtrvAmendSaveVo; import com.yfd.platform.qgc_env.wt.service.*; import com.yfd.platform.utils.QgcQueryWrapperUtil; import io.swagger.v3.oas.annotations.Operation; @@ -17,6 +20,7 @@ import jakarta.annotation.Resource; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.List; import java.util.Map; @RestController @@ -52,10 +56,14 @@ public class SdWTMonitorController { return ResponseResult.successData(result); } + @Log(module = "水温监测", value = "修改表层水温日数据") @PostMapping("/alongDetail/updateWtrvRData") @Operation(summary = "修改表层水温日数据") - public ResponseResult updateWtrvRData(@RequestBody Map updateData) { - alongDetailService.updateWtrvRData(updateData); + public ResponseResult updateWtrvRData(@RequestBody WtOperateRequest wtOperateRequest) { + alongDetailService.updateWtrvRData( + wtOperateRequest == null ? null : wtOperateRequest.getUpdateData(), + wtOperateRequest == null ? null : wtOperateRequest.getSource() + ); return ResponseResult.success(); } @@ -73,6 +81,7 @@ public class SdWTMonitorController { return ResponseResult.successData(result); } + @Log(module = "水温监测", value = "删除出库水温周旬月季年数据") @PostMapping("/alongDetail/drtp/removeKendoByIds") @Operation(summary = "删除出库水温周旬月季年数据") public ResponseResult removeKendoByIds(@RequestBody BatchDeleteAo batchDeleteAo) { @@ -197,6 +206,25 @@ public class SdWTMonitorController { return ResponseResult.successData(sdWtMonitorService.getMsstbprptList(dataSourceRequest)); } + @PostMapping("/msstbprpt/eng/GetKendoList") + @Operation(summary = "根据条件查询电站页水温基础站点列表") + public ResponseResult getMsstbprptEngList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(sdWtMonitorService.getMsstbprptEngList(dataSourceRequest)); + } + + @PostMapping("/wtrvAmend/dayAmend/GetKendoListCust") + @Operation(summary = "水温日数据统计修正结果数据") + public ResponseResult getWtrvAmendDayList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(sdWtMonitorService.getWtrvAmendDayList(dataSourceRequest)); + } + + @PostMapping("/wtrvAmend/dayAmend/saveAmendData") + @Operation(summary = "保存修正后的河道水温日数据") + public ResponseResult saveWtrvAmendData(@RequestBody List amendDataList) { + sdWtMonitorService.saveWtrvAmendData(amendDataList); + return ResponseResult.success(); + } + @GetMapping("/msstbprpt/getStcdInfo") @Operation(summary = "根据站码查询单条水温基础数据") public ResponseResult getStcdInfo(@RequestParam String stcd) { @@ -215,6 +243,7 @@ public class SdWTMonitorController { return ResponseResult.successData(sdWtMonitorService.getCxDetailList(dataSourceRequest)); } + @Log(module = "水温监测", value = "删除垂向水温数据") @PostMapping("/cxDetail/removeKendoByIds") @Operation(summary = "删除垂向水温数据") public ResponseResult removeCxDetailByIds(@RequestBody BatchDeleteAo batchDeleteAo) { @@ -222,10 +251,14 @@ public class SdWTMonitorController { return ResponseResult.success(); } + @Log(module = "水温监测", value = "修改垂向水温数据") @PostMapping("/cxDetail/updateWtvtRData") @Operation(summary = "修改垂向水温数据") - public ResponseResult updateWtvtRData(@RequestBody Map updateData) { - sdWtvtRService.updateWtvtRData(updateData); + public ResponseResult updateWtvtRData(@RequestBody WtOperateRequest wtOperateRequest) { + sdWtvtRService.updateWtvtRData( + wtOperateRequest == null ? null : wtOperateRequest.getUpdateData(), + wtOperateRequest == null ? null : wtOperateRequest.getSource() + ); return ResponseResult.success(); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/SdWtBaseInfoVO.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/SdWtBaseInfoVO.java index 034e0633..f88daf2f 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/SdWtBaseInfoVO.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/SdWtBaseInfoVO.java @@ -74,6 +74,15 @@ public class SdWtBaseInfoVO implements Serializable { @Schema(description = "所属电站编码") private String rstcd; + @Schema(description = "设备类型") + private Integer wtDeviceType; + + @Schema(description = "接入类型") + private Integer dtinType; + + @Schema(description = "监测方式") + private Integer mway; + @Schema(description = "所属测站编码") private String stCode; diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtOperateRequest.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtOperateRequest.java new file mode 100644 index 00000000..cdddcf9b --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtOperateRequest.java @@ -0,0 +1,13 @@ +package com.yfd.platform.qgc_env.wt.entity.vo; + +import lombok.Data; + +import java.util.Map; + +@Data +public class WtOperateRequest { + + private String source; + + private Map updateData; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtrvAmendResultVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtrvAmendResultVo.java new file mode 100644 index 00000000..330d668c --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtrvAmendResultVo.java @@ -0,0 +1,38 @@ +package com.yfd.platform.qgc_env.wt.entity.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +@Data +@Schema(description = "水温日数据统计修正结果数据") +public class WtrvAmendResultVo { + + @Schema(description = "站点编码") + private String stcd; + + @Schema(description = "日期") + @JsonFormat(pattern = "yyyy-MM-dd") + private Date dt; + + @Schema(description = "温度") + private BigDecimal wt; + + @Schema(description = "站点名称") + private String stnm; + + @Schema(description = "电站编码") + private String rstcd; + + @Schema(description = "电站名称") + private String ennm; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "基地名称") + private String baseName; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtrvAmendSaveVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtrvAmendSaveVo.java new file mode 100644 index 00000000..29482d0c --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtrvAmendSaveVo.java @@ -0,0 +1,20 @@ +package com.yfd.platform.qgc_env.wt.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +@Data +@Schema(description = "河道水温日修正保存入参") +public class WtrvAmendSaveVo { + + @Schema(description = "站点编码") + private String stcd; + + @Schema(description = "日期,支持 yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss") + private String dt; + + @Schema(description = "修正后水温") + private BigDecimal wt; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/AlongDetailService.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/AlongDetailService.java index 5465ec79..a4de4324 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/AlongDetailService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/AlongDetailService.java @@ -43,6 +43,6 @@ public interface AlongDetailService extends IService { boolean removeKendoByIds(BatchDeleteAo batchDeleteAo); - void updateWtrvRData(Map updateData); + void updateWtrvRData(Map updateData, String source); -} \ No newline at end of file +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/SdWtMonitorService.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/SdWtMonitorService.java index e8aab7ec..c6d44008 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/SdWtMonitorService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/SdWtMonitorService.java @@ -10,7 +10,9 @@ import com.yfd.platform.qgc_env.wt.entity.vo.SdYearDetailVO; import com.yfd.platform.qgc_env.wt.entity.vo.SttpInfoVo; import com.yfd.platform.qgc_env.wt.entity.vo.WbsbVo; import com.yfd.platform.qgc_env.wt.entity.vo.WtBaseInfoVo; +import com.yfd.platform.qgc_env.wt.entity.vo.WtrvAmendSaveVo; import com.yfd.platform.qgc_env.wt.entity.vo.WtrvVo; +import com.yfd.platform.qgc_env.wt.entity.vo.WtrvAmendResultVo; import java.util.List; @@ -22,6 +24,12 @@ public interface SdWtMonitorService { DataSourceResult getMsstbprptList(DataSourceRequest dataSourceRequest); + DataSourceResult getMsstbprptEngList(DataSourceRequest dataSourceRequest); + + DataSourceResult getWtrvAmendDayList(DataSourceRequest dataSourceRequest); + + void saveWtrvAmendData(List amendDataList); + WtBaseInfoVo getStcdInfo(String stcd); DataSourceResult getCxDetailList(DataSourceRequest dataSourceRequest); diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/SdWtvtRService.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/SdWtvtRService.java index 2b62f2b3..43c165a0 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/SdWtvtRService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/SdWtvtRService.java @@ -24,5 +24,5 @@ public interface SdWtvtRService { boolean removeKendoByIds(BatchDeleteAo batchDeleteAo); - void updateWtvtRData(Map updateData); + void updateWtvtRData(Map updateData, String source); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/AlongDetailServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/AlongDetailServiceImpl.java index 009f7cf6..13596442 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/AlongDetailServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/AlongDetailServiceImpl.java @@ -8,6 +8,8 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.common.*; import com.yfd.platform.common.exception.BizException; +import com.yfd.platform.qgc_base.domain.MsOperationLog; +import com.yfd.platform.qgc_base.domain.MsOperationLogDetail; import com.yfd.platform.qgc_env.wt.mapper.AlongDetailMapper; import com.yfd.platform.qgc_env.wt.mapper.SdWtrvdrtpSMapper; import com.yfd.platform.qgc_env.wt.service.AlongDetailService; @@ -17,6 +19,8 @@ import com.yfd.platform.qgc_env.wt.entity.vo.SdAlongDrtpDetailVO; import com.yfd.platform.qgc_env.wt.entity.vo.WtrvInfo; import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo; import com.yfd.platform.qgc_base.entity.vo.DataParam; +import com.yfd.platform.qgc_base.mapper.MsOperationLogDetailMapper; +import com.yfd.platform.qgc_base.mapper.MsOperationLogMapper; import com.yfd.platform.utils.CollectionExtUtils; import com.yfd.platform.utils.QgcQueryWrapperUtil; import com.yfd.platform.utils.SecurityUtils; @@ -37,6 +41,29 @@ import java.util.stream.Collectors; */ @Service public class AlongDetailServiceImpl extends ServiceImpl implements AlongDetailService { + private static final String WT_HOUR_TABLE_NAME = "SD_WTRV_R"; + private static final Map WT_UPDATE_COLUMN_MAP = new LinkedHashMap<>(); + private static final Map WT_FIELD_MEANING_MAP = new LinkedHashMap<>(); + + static { + WT_UPDATE_COLUMN_MAP.put("wt", "WT"); + + WT_FIELD_MEANING_MAP.put("ID", "主键ID"); + WT_FIELD_MEANING_MAP.put("STCD", "水温站编码"); + WT_FIELD_MEANING_MAP.put("TM", "数据时间"); + WT_FIELD_MEANING_MAP.put("WT", "水温"); + WT_FIELD_MEANING_MAP.put("REMARK", "备注"); + WT_FIELD_MEANING_MAP.put("FID", "附件ID"); + WT_FIELD_MEANING_MAP.put("WER_ID", "所属水生生态调查数据表ID"); + WT_FIELD_MEANING_MAP.put("RECORD_USER", "创建人"); + WT_FIELD_MEANING_MAP.put("RECORD_TIME", "创建时间"); + WT_FIELD_MEANING_MAP.put("MODIFY_USER", "更新人"); + WT_FIELD_MEANING_MAP.put("MODIFY_TIME", "更新时间"); + WT_FIELD_MEANING_MAP.put("IS_DELETED", "是否已删除"); + WT_FIELD_MEANING_MAP.put("DELETE_USER", "删除人"); + WT_FIELD_MEANING_MAP.put("DELETE_TIME", "删除时间"); + } + @Resource private DynamicSQLMapper dynamicSQLMapper; @Resource @@ -50,6 +77,12 @@ public class AlongDetailServiceImpl extends ServiceImpl filterResult, Page page) { DataSourceResult dataSourceResult = new DataSourceResult(); @@ -799,6 +832,7 @@ public class AlongDetailServiceImpl extends ServiceImpl dataList = batchDeleteAo.getDataList(); + String source = batchDeleteAo == null ? null : batchDeleteAo.getSource(); if(CollUtil.isEmpty(dataList)){ return true; } @@ -816,7 +850,9 @@ public class AlongDetailServiceImpl extends ServiceImpl> beforeRows = queryWtHourRows(subList); sdWtrvdrtpSMapper.deleteWtrvRData(subList, DateUtil.now(), SecurityUtils.getCurrentUsername()); + recordWtDeleteLog(beforeRows, "删除表层水温日数据", source); // 删除小时数据后,需要重新统计对应的日数据和月数据 Map dateRangeMap = new HashMap<>(); Map monthRangeMap = new HashMap<>(); @@ -1048,13 +1084,14 @@ public class AlongDetailServiceImpl extends ServiceImpl updateData) { + public void updateWtrvRData(Map updateData, String source) { + String stcd = asString(getValueIgnoreCase(updateData, "stcd")); + String tm = asString(getValueIgnoreCase(updateData, "dt")); + Map beforeRow = queryWtHourRow(stcd, tm); sdWtrvdrtpSMapper.updateWtrvRData(updateData); + recordWtUpdateLog(beforeRow, updateData, source); // 获取测站编码和时间 - String stcd = (String) updateData.get("stcd"); - String tm = (String) updateData.get("dt"); - if (StrUtil.isNotBlank(stcd) && StrUtil.isNotBlank(tm)) { // 提取日期部分(yyyy-MM-dd) String dateStr = tm.substring(0, 10); @@ -1074,4 +1111,204 @@ public class AlongDetailServiceImpl extends ServiceImpl queryWtHourRow(String stcd, String tm) { + if (StrUtil.isBlank(stcd) || StrUtil.isBlank(tm)) { + return new HashMap<>(); + } + String sql = "SELECT ID, STCD, TO_CHAR(TM, 'YYYY-MM-DD HH24:MI:SS') AS TM, WT, REMARK, FID, WER_ID, " + + "RECORD_USER, RECORD_TIME, MODIFY_USER, MODIFY_TIME, IS_DELETED, DELETE_USER, DELETE_TIME " + + "FROM SD_WTRV_R WHERE STCD = ? AND TM = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS')"; + List> rows = jdbcTemplate.queryForList(sql, stcd, tm); + return rows.isEmpty() ? new HashMap<>() : normalizeWtLogRow(rows.getFirst()); + } + + private List> queryWtHourRows(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return new ArrayList<>(); + } + StringBuilder sql = new StringBuilder("SELECT ID, STCD, TO_CHAR(TM, 'YYYY-MM-DD HH24:MI:SS') AS TM, WT, REMARK, FID, WER_ID, ") + .append("RECORD_USER, RECORD_TIME, MODIFY_USER, MODIFY_TIME, IS_DELETED, DELETE_USER, DELETE_TIME ") + .append("FROM SD_WTRV_R WHERE "); + List params = new ArrayList<>(); + for (int i = 0; i < dataParamList.size(); i++) { + if (i > 0) { + sql.append(" OR "); + } + sql.append("(STCD = ? AND TM = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS'))"); + DataParam item = dataParamList.get(i); + params.add(item == null ? null : item.getId()); + params.add(item == null ? null : item.getDt()); + } + return normalizeWtLogRows(jdbcTemplate.queryForList(sql.toString(), params.toArray())); + } + + private List> normalizeWtLogRows(List> rows) { + List> result = new ArrayList<>(); + if (CollUtil.isEmpty(rows)) { + return result; + } + for (Map row : rows) { + result.add(normalizeWtLogRow(row)); + } + return result; + } + + private Map normalizeWtLogRow(Map row) { + Map normalized = new LinkedHashMap<>(); + if (row == null || row.isEmpty()) { + return normalized; + } + for (Map.Entry entry : row.entrySet()) { + normalized.put(entry.getKey() == null ? null : entry.getKey().toUpperCase(), entry.getValue()); + } + return normalized; + } + + private void recordWtUpdateLog(Map beforeRow, Map updateData, String source) { + if (updateData == null || updateData.isEmpty()) { + return; + } + String stcd = asString(getValueIgnoreCase(updateData, "stcd")); + String recordId = asString(getValueIgnoreCase(beforeRow, "id")); + List details = new ArrayList<>(); + for (Map.Entry entry : WT_UPDATE_COLUMN_MAP.entrySet()) { + if (!containsKeyIgnoreCase(updateData, entry.getKey())) { + continue; + } + String column = entry.getValue(); + Object oldValue = beforeRow == null ? null : beforeRow.get(column); + Object newValue = getValueIgnoreCase(updateData, entry.getKey()); + if (StrUtil.equals(formatWtLogValue(oldValue), formatWtLogValue(newValue))) { + continue; + } + details.add(buildWtDetail(null, stcd, column, + oldValue, resolveWtDisplayValue(column, oldValue), + newValue, resolveWtDisplayValue(column, newValue), "修改字段值")); + } + if (details.isEmpty()) { + return; + } + MsOperationLog mainLog = buildWtMainLog(recordId,"修改表层水温日数据", source); + msOperationLogMapper.insert(mainLog); + for (MsOperationLogDetail detail : details) { + detail.setMainId(mainLog.getId()); + } + batchInsertWtLogDetails(details); + } + + private void recordWtDeleteLog(List> rows, String remark, String source) { + if (CollUtil.isEmpty(rows)) { + return; + } + + List details = new ArrayList<>(); + for (Map row : rows) { + String stcd = asString(row.get("STCD")); + String recordId = asString(row.get("ID")); + MsOperationLog mainLog = buildWtMainLog(recordId,remark, source); + msOperationLogMapper.insert(mainLog); + for (Map.Entry entry : row.entrySet()) { + String fieldCode = entry.getKey(); + Object oldValue = entry.getValue(); + if (StrUtil.isBlank(fieldCode) || oldValue == null) { + continue; + } + details.add(buildWtDetail(mainLog.getId(), stcd, fieldCode, + oldValue, resolveWtDisplayValue(fieldCode, oldValue), + null, null, "删除字段值")); + } + } + batchInsertWtLogDetails(details); + } + + private MsOperationLog buildWtMainLog(String recordId,String remark, String source) { + MsOperationLog log = new MsOperationLog(); + log.setOperator(resolveWtLogOperator()); + log.setOperateTime(new Date()); + log.setRecordId(recordId); + log.setTableName(WT_HOUR_TABLE_NAME); + log.setSource(StrUtil.trimToNull(source)); + log.setRemark(remark); + return log; + } + + private MsOperationLogDetail buildWtDetail(String mainId, + String stationCode, + String fieldCode, + Object oldValueCode, + Object oldValueName, + Object newValueCode, + Object newValueName, + String remark) { + MsOperationLogDetail detail = new MsOperationLogDetail(); + detail.setMainId(mainId); + detail.setTableName(WT_HOUR_TABLE_NAME); + detail.setStationCode(stationCode); + detail.setFieldCode(fieldCode); + detail.setFieldMeaning(WT_FIELD_MEANING_MAP.getOrDefault(fieldCode, fieldCode)); + detail.setOldValueCode(formatWtLogValue(oldValueCode)); + detail.setOldValueName(formatWtLogValue(oldValueName)); + detail.setNewValueCode(formatWtLogValue(newValueCode)); + detail.setNewValueName(formatWtLogValue(newValueName)); + detail.setRemark(remark); + return detail; + } + + private void batchInsertWtLogDetails(List details) { + if (CollUtil.isEmpty(details)) { + return; + } + for (MsOperationLogDetail detail : details) { + if (detail == null) { + continue; + } + msOperationLogDetailMapper.insert(detail); + } + } + + private Object resolveWtDisplayValue(String fieldCode, Object rawValue) { + return formatWtLogValue(rawValue); + } + + private String resolveWtLogOperator() { + try { + return SecurityUtils.getCurrentUsername(); + } catch (Exception ignored) { + try { + return SecurityUtils.getUserId(); + } catch (Exception ex) { + return null; + } + } + } + + private String formatWtLogValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof Date date) { + return DateUtil.formatDateTime(date); + } + return String.valueOf(value); + } + + private String asString(Object value) { + return value == null ? null : String.valueOf(value); + } + + private boolean containsKeyIgnoreCase(Map data, String key) { + if (data == null || StrUtil.isBlank(key)) { + return false; + } + if (data.containsKey(key)) { + return true; + } + for (String mapKey : data.keySet()) { + if (StrUtil.equalsIgnoreCase(mapKey, key)) { + return true; + } + } + return false; + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java index c34f1641..fa485604 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java @@ -1,5 +1,6 @@ package com.yfd.platform.qgc_env.wt.service.impl; +import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.yfd.platform.common.*; @@ -16,13 +17,17 @@ import com.yfd.platform.qgc_env.wt.entity.vo.WbsbVo; import com.yfd.platform.qgc_env.wt.entity.vo.WtBaseInfoVo; import com.yfd.platform.qgc_env.wt.entity.vo.WtFishVo; import com.yfd.platform.qgc_env.wt.entity.vo.WtTreeStcdVo; +import com.yfd.platform.qgc_env.wt.entity.vo.WtrvAmendResultVo; +import com.yfd.platform.qgc_env.wt.entity.vo.WtrvAmendSaveVo; import com.yfd.platform.qgc_env.wt.entity.vo.WtrvVo; import com.yfd.platform.qgc_env.wt.mapper.SdWtMonitorMapper; import com.yfd.platform.qgc_env.wt.service.SdWtMonitorService; import com.yfd.platform.utils.QgcQueryWrapperUtil; import jakarta.annotation.Resource; import lombok.Data; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.util.ArrayList; @@ -46,6 +51,9 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService { @Resource private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; + @Resource + private JdbcTemplate jdbcTemplate; + @Override public DataSourceResult getEvnmAutoMonitorList(DataSourceRequest dataSourceRequest) { DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); @@ -856,14 +864,7 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService { StringBuilder sql = new StringBuilder(); sql.append("SELECT ").append(selectSql).append(" ") - .append("FROM SD_WT_B_H wt ") - .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") - .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 AND NVL(hbrv.IS_DELETED, 0) = 0 ") - .append("LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = wt.STTP AND NVL(sttp.IS_DELETED, 0) = 0 ") - .append("LEFT JOIN (SELECT DISTINCT STCD FROM SD_WTRV_R WHERE IS_DELETED = 0 AND TM >= SYSDATE - 1) rvRecent ON rvRecent.STCD = wt.STCD ") - .append("LEFT JOIN (SELECT DISTINCT STCD FROM SD_WTVT_R WHERE IS_DELETED = 0 AND TM >= SYSDATE - 1) vtRecent ON vtRecent.STCD = wt.STCD ") - .append("WHERE NVL(wt.IS_DELETED, 0) = 0 AND NVL(wt.DTIN_TYPE, 0) = 0 "); + .append(buildWtMsstbprptFromSql()); Map paramMap = new HashMap<>(); appendWtMsstbprptFilters(sql, paramMap, dataSourceRequest == null ? null : dataSourceRequest.getFilter()); @@ -880,6 +881,74 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService { return result; } + @Override + public DataSourceResult getMsstbprptEngList(DataSourceRequest dataSourceRequest) { + List selectFields = dataSourceRequest == null ? null : dataSourceRequest.getSelect(); + String selectSql = buildWtMsstbprptEngSelectSql(selectFields); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ").append(selectSql).append(" ") + .append(buildWtMsstbprptFromSql()); + + Map paramMap = new HashMap<>(); + appendWtMsstbprptFilters(sql, paramMap, dataSourceRequest == null ? null : dataSourceRequest.getFilter()); + sql.append(buildVmsstbprptOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + Page page = QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, SdWtBaseInfoVO.class); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getWtrvAmendDayList(DataSourceRequest dataSourceRequest) { + List selectFields = dataSourceRequest == null ? null : dataSourceRequest.getSelect(); + String selectSql = buildWtrvAmendSelectSql(selectFields); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ").append(selectSql).append(" FROM (") + .append(buildWtrvAmendMergedSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = buildWtrvAmendFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql); + } + sql.append(buildWtrvAmendOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType(page, + sql.toString(), paramMap, WtrvAmendResultVo.class); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void saveWtrvAmendData(List amendDataList) { + if (amendDataList == null || amendDataList.isEmpty()) { + throw new BizException("数据不能为空"); + } + int batchSize = 500; + for (int i = 0; i < amendDataList.size(); i += batchSize) { + List subList = amendDataList.subList(i, Math.min(i + batchSize, amendDataList.size())); + mergeWtrvAmendDataBatch(subList, i); + } + } + @Override public DataSourceResult getCxDetailList(DataSourceRequest dataSourceRequest) { List filters = new ArrayList<>(); @@ -1802,6 +1871,300 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService { return " ORDER BY " + String.join(", ", orderColumns); } + private String buildWtrvAmendMergedSql() { + return "SELECT " + + "dayData.STCD AS stcd, " + + "dayData.DT AS dt, " + + "NVL(amendData.WT, dayData.WT) AS wt, " + + "wt.STNM AS stnm, " + + "wt.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "eng.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName " + + "FROM SD_WTRVDAY_S dayData " + + "INNER JOIN SD_WT_B_H wt ON dayData.STCD = wt.STCD " + + " AND wt.STTP = 'WTRV' " + + " AND NVL(wt.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_WTRVAMEND_S amendData ON amendData.STCD = dayData.STCD " + + " AND amendData.DT = dayData.DT " + + " AND NVL(amendData.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.RSTCD " + + " AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID " + + " AND NVL(hb.IS_DELETED, 0) = 0 " + + "WHERE NVL(dayData.IS_DELETED, 0) = 0 " + + "UNION ALL " + + "SELECT " + + "amendData.STCD AS stcd, " + + "amendData.DT AS dt, " + + "amendData.WT AS wt, " + + "wt.STNM AS stnm, " + + "wt.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "eng.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName " + + "FROM SD_WTRVAMEND_S amendData " + + "INNER JOIN SD_WT_B_H wt ON amendData.STCD = wt.STCD " + + " AND wt.STTP = 'WTRV' " + + " AND NVL(wt.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.RSTCD " + + " AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID " + + " AND NVL(hb.IS_DELETED, 0) = 0 " + + "WHERE NVL(amendData.IS_DELETED, 0) = 0 " + + "AND NOT EXISTS ( " + + " SELECT 1 FROM SD_WTRVDAY_S dayData " + + " WHERE dayData.STCD = amendData.STCD " + + " AND dayData.DT = amendData.DT " + + " AND NVL(dayData.IS_DELETED, 0) = 0 " + + ")"; + } + + private String buildWtrvAmendSelectSql(List selectFields) { + Map columnMap = buildWtrvAmendColumnMap(); + List actualColumns = new ArrayList<>(); + if (selectFields != null && !selectFields.isEmpty()) { + for (String field : selectFields) { + String column = columnMap.get(field); + if (StrUtil.isNotBlank(column)) { + actualColumns.add(column); + } + } + } + if (actualColumns.isEmpty()) { + actualColumns.addAll(columnMap.values()); + } + return String.join(", ", actualColumns); + } + + private Map buildWtrvAmendColumnMap() { + Map columnMap = new LinkedHashMap<>(); + columnMap.put("stcd", "t.stcd AS stcd"); + columnMap.put("dt", "t.dt AS dt"); + columnMap.put("wt", "t.wt AS wt"); + columnMap.put("stnm", "t.stnm AS stnm"); + columnMap.put("rstcd", "t.rstcd AS rstcd"); + columnMap.put("ennm", "t.ennm AS ennm"); + columnMap.put("baseId", "t.baseId AS baseId"); + columnMap.put("baseName", "t.baseName AS baseName"); + return columnMap; + } + + private String buildWtrvAmendFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (filter.getFilters() != null && !filter.getFilters().isEmpty()) { + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String condition = buildWtrvAmendFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(condition)) { + conditions.add("(" + condition + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + return buildWtrvAmendLeafCondition(filter, paramMap, indexHolder); + } + + private String buildWtrvAmendLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapWtrvAmendColumn(filter == null ? null : filter.getField()); + if (StrUtil.isBlank(column) || StrUtil.isBlank(filter.getOperator())) { + return ""; + } + String operator = filter.getOperator().toLowerCase(); + Object rawValue = filter.getValue(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("isempty".equals(operator)) { + return "(" + column + " IS NULL OR " + column + " = '')"; + } + if ("isnotempty".equals(operator)) { + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + } + if (rawValue == null) { + return ""; + } + String paramKey = "wtrvAmendP" + indexHolder[0]++; + boolean dateField = isWtrvAmendDateField(filter); + if ("in".equals(operator) || "ni".equals(operator)) { + List values = normalizeToList(rawValue); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + int itemIndex = 0; + for (Object value : values) { + String itemKey = paramKey + "_" + itemIndex++; + paramMap.put(itemKey, String.valueOf(value).trim()); + placeholders.add(buildWtrvAmendValueExpr(itemKey, dateField, value)); + } + return column + ("ni".equals(operator) ? " NOT IN (" : " IN (") + String.join(", ", placeholders) + ")"; + } + String text = String.valueOf(rawValue).trim(); + paramMap.put(paramKey, text); + String valueExpr = buildWtrvAmendValueExpr(paramKey, dateField, rawValue); + return switch (operator) { + case "eq" -> column + " = " + valueExpr; + case "neq" -> column + " <> " + valueExpr; + case "gt" -> column + " > " + valueExpr; + case "gte" -> column + " >= " + valueExpr; + case "lt" -> column + " < " + valueExpr; + case "lte" -> column + " <= " + valueExpr; + case "contains" -> { + paramMap.put(paramKey, "%" + text + "%"); + yield column + " LIKE #{map." + paramKey + "}"; + } + case "doesnotcontain" -> { + paramMap.put(paramKey, "%" + text + "%"); + yield column + " NOT LIKE #{map." + paramKey + "}"; + } + case "startswith" -> { + paramMap.put(paramKey, text + "%"); + yield column + " LIKE #{map." + paramKey + "}"; + } + case "endswith" -> { + paramMap.put(paramKey, "%" + text); + yield column + " LIKE #{map." + paramKey + "}"; + } + default -> ""; + }; + } + + private String mapWtrvAmendColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd" -> "t.stcd"; + case "dt" -> "t.dt"; + case "wt" -> "t.wt"; + case "stnm" -> "t.stnm"; + case "rstcd" -> "t.rstcd"; + case "ennm" -> "t.ennm"; + case "baseId" -> "t.baseId"; + case "baseName" -> "t.baseName"; + default -> null; + }; + } + + private String buildWtrvAmendOrderBySql(List sortList) { + List orderColumns = new ArrayList<>(); + if (sortList != null) { + for (DataSourceRequest.SortDescriptor sortDescriptor : sortList) { + String column = mapWtrvAmendColumn(sortDescriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sortDescriptor.getDir()) || "des".equalsIgnoreCase(sortDescriptor.getDir()) ? "DESC" : "ASC"; + orderColumns.add(column + " " + dir + ("t.dt".equals(column) || "t.wt".equals(column) ? " NULLS LAST" : "")); + } + } + if (orderColumns.isEmpty()) { + return " ORDER BY t.dt DESC, t.stcd ASC"; + } + return " ORDER BY " + String.join(", ", orderColumns); + } + + private boolean isWtrvAmendDateField(DataSourceRequest.FilterDescriptor filter) { + if (filter == null || StrUtil.isBlank(filter.getField())) { + return false; + } + if ("dt".equalsIgnoreCase(filter.getField())) { + return true; + } + return "date".equalsIgnoreCase(filter.getDataType()); + } + + private String buildWtrvAmendValueExpr(String paramKey, boolean dateField, Object value) { + if (!dateField || value == null) { + return "#{map." + paramKey + "}"; + } + String text = String.valueOf(value).trim(); + if (text.length() <= 10) { + return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD')"; + } + return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD HH24:MI:SS')"; + } + + private List normalizeToList(Object value) { + if (value == null) { + return Collections.emptyList(); + } + if (value instanceof List list) { + return list.stream().filter(Objects::nonNull).collect(Collectors.toList()); + } + return Collections.singletonList(value); + } + + private void mergeWtrvAmendDataBatch(List amendDataList, int startIndex) { + StringBuilder sql = new StringBuilder("MERGE INTO SD_WTRVAMEND_S target USING ("); + List params = new ArrayList<>(); + for (int i = 0; i < amendDataList.size(); i++) { + WtrvAmendSaveVo item = amendDataList.get(i); + int rowNo = startIndex + i + 1; + String stcd = item == null ? null : StrUtil.trimToNull(item.getStcd()); + if (StrUtil.isBlank(stcd)) { + throw new BizException("第" + rowNo + "条数据站点编码不能为空"); + } + String dt = normalizeWtrvAmendDate(item.getDt()); + if (StrUtil.isBlank(dt)) { + throw new BizException("第" + rowNo + "条数据日期格式不正确"); + } + if (i > 0) { + sql.append(" UNION ALL "); + } + sql.append("SELECT ? AS STCD, TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS') AS DT, ? AS WT FROM DUAL"); + params.add(stcd); + params.add(dt); + params.add(item.getWt()); + } + sql.append(") source ON (target.STCD = source.STCD AND target.DT = source.DT) ") + .append("WHEN MATCHED THEN UPDATE SET ") + .append("target.WT = source.WT, ") + .append("target.IS_DELETED = 0, ") + .append("target.DELETE_USER = NULL, ") + .append("target.DELETE_TIME = NULL, ") + .append("target.MODIFY_TIME = SYSDATE ") + .append("WHEN NOT MATCHED THEN INSERT (ID, STCD, DT, WT, RECORD_TIME, IS_DELETED) ") + .append("VALUES (SYS_GUID(), source.STCD, source.DT, source.WT, SYSDATE, 0)"); + jdbcTemplate.update(sql.toString(), params.toArray()); + } + + private String normalizeWtrvAmendDate(String value) { + if (StrUtil.isBlank(value)) { + return null; + } + String text = value.trim().replace('T', ' '); + try { + if (text.length() <= 10) { + return DateUtil.formatDateTime(DateUtil.parse(text.substring(0, 10), "yyyy-MM-dd").toJdkDate()); + } + if (text.length() >= 19) { + return DateUtil.formatDateTime(DateUtil.parse(text.substring(0, 19), "yyyy-MM-dd HH:mm:ss").toJdkDate()); + } + return DateUtil.formatDateTime(DateUtil.parse(text, "yyyy-MM-dd HH:mm").toJdkDate()); + } catch (Exception ex) { + try { + return DateUtil.formatDateTime(DateUtil.parse(value.trim()).toJdkDate()); + } catch (Exception ignore) { + return null; + } + } + } + private String buildSttpInfoFilterCondition(DataSourceRequest.FilterDescriptor filter, Map paramMap, int[] indexHolder) { @@ -1980,6 +2343,16 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService { orderColumns.add("NVL(dtin, -1) " + dir + " NULLS LAST"); } else if ("dtinName".equals(field)) { orderColumns.add("CASE WHEN NVL(dtin, 0) = 1 THEN '已接入' ELSE '未接入' END " + dir + " NULLS LAST"); + } else if ("wtDeviceType".equals(field)) { + orderColumns.add("NVL(wtDeviceType, -1) " + dir + " NULLS LAST"); + } else if ("dtinType".equals(field)) { + orderColumns.add("NVL(dtinType, -1) " + dir + " NULLS LAST"); + } else if ("mway".equals(field)) { + orderColumns.add("NVL(mway, -1) " + dir + " NULLS LAST"); + } else if ("lgtd".equals(field)) { + orderColumns.add("lgtd " + dir + " NULLS LAST"); + } else if ("lttd".equals(field)) { + orderColumns.add("lttd " + dir + " NULLS LAST"); } } } @@ -1991,6 +2364,54 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService { } private String buildWtMsstbprptSelectSql(List selectFields) { + Map columnMap = buildWtMsstbprptColumnMap(); + + List actualColumns = new ArrayList<>(); + if (selectFields != null && !selectFields.isEmpty()) { + for (String field : selectFields) { + String column = columnMap.get(field); + if (StrUtil.isNotBlank(column)) { + actualColumns.add(column); + } + } + } + if (actualColumns.isEmpty()) { + actualColumns.addAll(columnMap.values()); + } + return String.join(", ", actualColumns); + } + + private String buildWtMsstbprptEngSelectSql(List selectFields) { + Map columnMap = buildWtMsstbprptColumnMap(); + List actualColumns = new ArrayList<>(); + if (selectFields == null || selectFields.isEmpty()) { + actualColumns.add(columnMap.get("stcd")); + actualColumns.add(columnMap.get("stnm")); + actualColumns.add(columnMap.get("wtDeviceType")); + actualColumns.add(columnMap.get("dtinType")); + actualColumns.add(columnMap.get("mway")); + actualColumns.add(columnMap.get("lgtd")); + actualColumns.add(columnMap.get("lttd")); + actualColumns.add(columnMap.get("baseId")); + actualColumns.add(columnMap.get("baseName")); + } else { + for (String field : selectFields) { + String column = columnMap.get(field); + if (StrUtil.isNotBlank(column)) { + actualColumns.add(column); + } + } + } + ensureWtMsstbprptColumn(actualColumns, columnMap, "stcd"); + ensureWtMsstbprptColumn(actualColumns, columnMap, "stnm"); + ensureWtMsstbprptColumn(actualColumns, columnMap, "lgtd"); + ensureWtMsstbprptColumn(actualColumns, columnMap, "lttd"); + ensureWtMsstbprptColumn(actualColumns, columnMap, "baseId"); + ensureWtMsstbprptColumn(actualColumns, columnMap, "baseName"); + return String.join(", ", actualColumns); + } + + private Map buildWtMsstbprptColumnMap() { Map columnMap = new LinkedHashMap<>(); columnMap.put("baseName", "hb.BASENAME AS baseName"); columnMap.put("baseId", "hb.BASEID AS baseId"); @@ -2009,31 +2430,43 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService { columnMap.put("stcd", "wt.STCD AS stcd"); columnMap.put("fhstcd", "wt.FHSTCD AS fhstcd"); columnMap.put("rstcd", "wt.RSTCD AS rstcd"); -// columnMap.put("bldsttCcodeName", "CASE WHEN wt.BLDSTT_CODE IN ('1', '10', '11') THEN '已建' WHEN wt.BLDSTT_CODE IN ('2', '7', '8') THEN '在建' ELSE '未建/规划' END AS bldsttCcodeName"); columnMap.put("bldsttCcodeName", "CASE WHEN wt.BLDSTT_CODE = 0 THEN '未建/规划' " + "WHEN wt.BLDSTT_CODE = 1 THEN '在建' " + "WHEN wt.BLDSTT_CODE = 2 THEN '已建' " + - "ELSE '未知' END"); + "ELSE '未知' END AS bldsttCcodeName"); columnMap.put("bldsttCcode", "wt.BLDSTT_CODE AS bldsttCcode"); columnMap.put("stCode", "NULL AS stCode"); columnMap.put("stName", "NULL AS stName"); columnMap.put("dvtp", "eng.DVTP AS dvtp"); columnMap.put("hbrvcd", "eng.HBRVCD AS hbrvcd"); + columnMap.put("lgtd", "wt.LGTD AS lgtd"); + columnMap.put("lttd", "wt.LTTD AS lttd"); + columnMap.put("wtDeviceType", "wt.WT_DEVICE_TYPE AS wtDeviceType"); + columnMap.put("dtinType", "wt.DTIN_TYPE AS dtinType"); + columnMap.put("mway", "wt.MWAY AS mway"); + return columnMap; + } - List actualColumns = new ArrayList<>(); - if (selectFields != null && !selectFields.isEmpty()) { - for (String field : selectFields) { - String column = columnMap.get(field); - if (StrUtil.isNotBlank(column)) { - actualColumns.add(column); - } - } + private void ensureWtMsstbprptColumn(List actualColumns, Map columnMap, String field) { + String column = columnMap.get(field); + if (StrUtil.isBlank(column)) { + return; } - if (actualColumns.isEmpty()) { - actualColumns.addAll(columnMap.values()); + if (!actualColumns.contains(column)) { + actualColumns.add(column); } - return String.join(", ", actualColumns); + } + + private String buildWtMsstbprptFromSql() { + return "FROM SD_WT_B_H wt " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eng.HBRVCD AND hbrv.BASEID = eng.BASE_ID AND NVL(hbrv.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = wt.STTP AND NVL(sttp.IS_DELETED, 0) = 0 " + + "LEFT JOIN (SELECT DISTINCT STCD FROM SD_WTRV_R WHERE IS_DELETED = 0 AND TM >= SYSDATE - 1) rvRecent ON rvRecent.STCD = wt.STCD " + + "LEFT JOIN (SELECT DISTINCT STCD FROM SD_WTVT_R WHERE IS_DELETED = 0 AND TM >= SYSDATE - 1) vtRecent ON vtRecent.STCD = wt.STCD " + + "WHERE NVL(wt.IS_DELETED, 0) = 0 AND NVL(wt.DTIN_TYPE, 0) = 0 "; } private void appendWtMsstbprptFilters(StringBuilder sql, @@ -2061,6 +2494,8 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService { appendWtMsstbprptLeaf(sql, paramMap, paramKey, "wt.RSTCD", operator, value); } else if ("baseId".equals(field)) { appendWtMsstbprptLeaf(sql, paramMap, paramKey, "eng.BASE_ID", operator, value); + } else if ("sttpFullPath".equals(field)) { + appendWtMsstbprptLeaf(sql, paramMap, paramKey, "sttp.FULL_PATH", operator, value); } else if ("mway".equals(field)) { appendWtMsstbprptLeaf(sql, paramMap, paramKey, "wt.MWAY", operator, value); } else if ("dtin".equals(field)) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtvtRServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtvtRServiceImpl.java index c91fcda6..80a91b5a 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtvtRServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtvtRServiceImpl.java @@ -1,13 +1,18 @@ package com.yfd.platform.qgc_env.wt.service.impl; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateUtil; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 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_base.domain.MsOperationLog; +import com.yfd.platform.qgc_base.domain.MsOperationLogDetail; import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo; import com.yfd.platform.qgc_base.entity.vo.DataParam; +import com.yfd.platform.qgc_base.mapper.MsOperationLogDetailMapper; +import com.yfd.platform.qgc_base.mapper.MsOperationLogMapper; import com.yfd.platform.qgc_env.wt.entity.vo.SdWtvtYearVo; import com.yfd.platform.qgc_env.wt.mapper.SdWtvtRMapper; import com.yfd.platform.qgc_env.wt.service.SdWtvtRService; @@ -22,6 +27,7 @@ import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Calendar; +import java.util.Date; import java.util.HashSet; import java.util.HashMap; import java.util.List; @@ -37,6 +43,28 @@ import java.util.Set; */ @Service public class SdWtvtRServiceImpl extends ServiceImpl implements SdWtvtRService { + private static final String WT_CX_TABLE_NAME = "SD_WTVT_R"; + private static final Map WT_CX_FIELD_MEANING_MAP = new LinkedHashMap<>(); + + static { + WT_CX_FIELD_MEANING_MAP.put("ID", "主键ID"); + WT_CX_FIELD_MEANING_MAP.put("STCD", "垂向水温站编码"); + WT_CX_FIELD_MEANING_MAP.put("TM", "时间"); + WT_CX_FIELD_MEANING_MAP.put("WTHG", "水温深度"); + WT_CX_FIELD_MEANING_MAP.put("VWT", "水温"); + WT_CX_FIELD_MEANING_MAP.put("FID", "附件ID"); + WT_CX_FIELD_MEANING_MAP.put("RECORD_USER", "创建人"); + WT_CX_FIELD_MEANING_MAP.put("RECORD_TIME", "创建时间"); + WT_CX_FIELD_MEANING_MAP.put("MODIFY_USER", "更新人"); + WT_CX_FIELD_MEANING_MAP.put("MODIFY_TIME", "更新时间"); + WT_CX_FIELD_MEANING_MAP.put("IS_DELETED", "是否已删除"); + WT_CX_FIELD_MEANING_MAP.put("DELETE_USER", "删除人"); + WT_CX_FIELD_MEANING_MAP.put("DELETE_TIME", "删除时间"); + WT_CX_FIELD_MEANING_MAP.put("RZ", "坝前水位"); + WT_CX_FIELD_MEANING_MAP.put("HGT", "测点高程"); + WT_CX_FIELD_MEANING_MAP.put("REMARK", "备注"); + WT_CX_FIELD_MEANING_MAP.put("WER_ID", "所属水生生态调查数据表ID"); + } @Resource private SdWtvtRMapper sdWtvtRMapper; @@ -47,6 +75,12 @@ public class SdWtvtRServiceImpl extends ServiceImpl @Resource private JdbcTemplate jdbcTemplate; + @Resource + private MsOperationLogMapper msOperationLogMapper; + + @Resource + private MsOperationLogDetailMapper msOperationLogDetailMapper; + @Override public DataSourceResult getWtrvDefaultYear(DataSourceRequest dataSourceRequest) { DataSourceResult dataSourceResult = new DataSourceResult<>(); @@ -91,6 +125,7 @@ public class SdWtvtRServiceImpl extends ServiceImpl public boolean removeKendoByIds(BatchDeleteAo batchDeleteAo) { String dataType = batchDeleteAo == null ? null : batchDeleteAo.getDataType(); List dataList = batchDeleteAo == null ? null : batchDeleteAo.getDataList(); + String source = batchDeleteAo == null ? null : batchDeleteAo.getSource(); if (CollUtil.isEmpty(dataList)) { return true; } @@ -104,7 +139,9 @@ public class SdWtvtRServiceImpl extends ServiceImpl continue; } if ("TIME".equalsIgnoreCase(dataType)) { + List> beforeRows = queryWtvtRows(subList); deleteWtvtRData(subList); + recordWtvtDeleteLog(beforeRows, "删除垂向水温数据", source); Map dateRangeMap = new HashMap<>(); Map monthRangeMap = new HashMap<>(); for (DataParam param : subList) { @@ -160,7 +197,7 @@ public class SdWtvtRServiceImpl extends ServiceImpl @Override @Transactional(rollbackFor = Exception.class) - public void updateWtvtRData(Map updateData) { + public void updateWtvtRData(Map updateData, String source) { if (updateData == null || updateData.isEmpty()) { return; } @@ -171,7 +208,10 @@ public class SdWtvtRServiceImpl extends ServiceImpl return; } + Map> beforeRowMap = buildWtvtBeforeRowMap(stcd, dt); + List> dataList = new ArrayList<>(); + List logDetails = new ArrayList<>(); rawMap.forEach((wthgObj, vwtObj) -> { if (wthgObj == null) { return; @@ -192,12 +232,32 @@ public class SdWtvtRServiceImpl extends ServiceImpl // item.put("recordUser", "admin"); item.put("recordUser", SecurityUtils.getUserId()); dataList.add(item); + + String depthKey = buildWtvtDepthKey(item.get("wthg")); + Map beforeRow = beforeRowMap.get(depthKey); + Object oldValue = beforeRow == null ? null : beforeRow.get("VWT"); + Object newValue = item.get("vwt"); + if (StringUtils.equals(formatWtvtLogValue(oldValue), formatWtvtLogValue(newValue))) { + return; + } + logDetails.add(buildWtvtDetail(null, stcd, "VWT", + oldValue, resolveWtvtDisplayValue("VWT", oldValue), + newValue, resolveWtvtDisplayValue("VWT", newValue), + buildWtvtDepthRemark("修改字段值", item.get("wthg")))); }); if (dataList.isEmpty()) { return; } batchUpdateWtvtRData(dataList); + if (CollUtil.isNotEmpty(logDetails)) { + MsOperationLog mainLog = buildWtvtMainLog(null,"修改垂向水温数据", source); + msOperationLogMapper.insert(mainLog); + for (MsOperationLogDetail detail : logDetails) { + detail.setMainId(mainLog.getId()); + } + batchInsertWtvtLogDetails(logDetails); + } String dateStr = dt.substring(0, 10); statisticsDayDataFromHour(stcd, dateStr, dateStr); @@ -363,4 +423,163 @@ public class SdWtvtRServiceImpl extends ServiceImpl private String asString(Object value) { return value == null ? null : String.valueOf(value); } + + private List> queryWtvtRows(List dataParamList) { + if (CollUtil.isEmpty(dataParamList)) { + return new ArrayList<>(); + } + StringBuilder sql = new StringBuilder("SELECT ID, STCD, TO_CHAR(TM, 'YYYY-MM-DD HH24:MI:SS') AS TM, WTHG, VWT, FID, ") + .append("RECORD_USER, RECORD_TIME, MODIFY_USER, MODIFY_TIME, IS_DELETED, DELETE_USER, DELETE_TIME, RZ, HGT, REMARK, WER_ID ") + .append("FROM SD_WTVT_R WHERE "); + List params = new ArrayList<>(); + List conditions = new ArrayList<>(); + for (DataParam item : dataParamList) { + if (item == null || StringUtils.isBlank(item.getId()) || StringUtils.isBlank(item.getDt())) { + continue; + } + conditions.add("(STCD = ? AND TM = TO_DATE(SUBSTR(?, 1, 19), 'YYYY-MM-DD HH24:MI:SS'))"); + params.add(item.getId()); + params.add(item.getDt()); + } + if (conditions.isEmpty()) { + return new ArrayList<>(); + } + sql.append(String.join(" OR ", conditions)); + return normalizeWtvtRows(jdbcTemplate.queryForList(sql.toString(), params.toArray())); + } + + private Map> buildWtvtBeforeRowMap(String stcd, String dt) { + Map> result = new HashMap<>(); + if (StringUtils.isBlank(stcd) || StringUtils.isBlank(dt)) { + return result; + } + String sql = "SELECT ID, STCD, TO_CHAR(TM, 'YYYY-MM-DD HH24:MI:SS') AS TM, WTHG, VWT, FID, " + + "RECORD_USER, RECORD_TIME, MODIFY_USER, MODIFY_TIME, IS_DELETED, DELETE_USER, DELETE_TIME, RZ, HGT, REMARK, WER_ID " + + "FROM SD_WTVT_R WHERE WTHG IS NOT NULL AND VWT IS NOT NULL AND STCD = ? AND TM = TO_DATE(SUBSTR(?, 1, 19), 'YYYY-MM-DD HH24:MI:SS')"; + List> rows = normalizeWtvtRows(jdbcTemplate.queryForList(sql, stcd, dt)); + for (Map row : rows) { + + result.put(String.valueOf(Double.parseDouble(row.get("WTHG").toString())), row); + } + return result; + } + + private List> normalizeWtvtRows(List> rows) { + List> result = new ArrayList<>(); + if (CollUtil.isEmpty(rows)) { + return result; + } + for (Map row : rows) { + Map normalized = new LinkedHashMap<>(); + for (Map.Entry entry : row.entrySet()) { + normalized.put(entry.getKey() == null ? null : entry.getKey().toUpperCase(), entry.getValue()); + } + result.add(normalized); + } + return result; + } + + private void recordWtvtDeleteLog(List> rows, String remark, String source) { + if (CollUtil.isEmpty(rows)) { + return; + } + MsOperationLog mainLog = buildWtvtMainLog(null,remark, source); + msOperationLogMapper.insert(mainLog); + List details = new ArrayList<>(); + for (Map row : rows) { + String stcd = asString(row.get("STCD")); + Object depth = row.get("WTHG"); + for (Map.Entry entry : row.entrySet()) { + String fieldCode = entry.getKey(); + Object oldValue = entry.getValue(); + if (StringUtils.isBlank(fieldCode) || oldValue == null) { + continue; + } + details.add(buildWtvtDetail(mainLog.getId(), stcd, fieldCode, + oldValue, resolveWtvtDisplayValue(fieldCode, oldValue), + null, null, buildWtvtDepthRemark("删除字段值", depth))); + } + } + batchInsertWtvtLogDetails(details); + } + + private MsOperationLog buildWtvtMainLog(String recordId,String remark, String source) { + MsOperationLog log = new MsOperationLog(); + log.setOperator(resolveWtvtLogOperator()); + log.setOperateTime(new Date()); + log.setTableName(WT_CX_TABLE_NAME); + log.setRecordId(remark); + log.setSource(StringUtils.trimToNull(source)); + log.setRemark(remark); + return log; + } + + private MsOperationLogDetail buildWtvtDetail(String mainId, + String stationCode, + String fieldCode, + Object oldValueCode, + Object oldValueName, + Object newValueCode, + Object newValueName, + String remark) { + MsOperationLogDetail detail = new MsOperationLogDetail(); + detail.setMainId(mainId); + detail.setTableName(WT_CX_TABLE_NAME); + detail.setStationCode(stationCode); + detail.setFieldCode(fieldCode); + detail.setFieldMeaning(WT_CX_FIELD_MEANING_MAP.getOrDefault(fieldCode, fieldCode)); + detail.setOldValueCode(formatWtvtLogValue(oldValueCode)); + detail.setOldValueName(formatWtvtLogValue(oldValueName)); + detail.setNewValueCode(formatWtvtLogValue(newValueCode)); + detail.setNewValueName(formatWtvtLogValue(newValueName)); + detail.setRemark(remark); + return detail; + } + + private void batchInsertWtvtLogDetails(List details) { + if (CollUtil.isEmpty(details)) { + return; + } + for (MsOperationLogDetail detail : details) { + if (detail == null) { + continue; + } + msOperationLogDetailMapper.insert(detail); + } + } + + private Object resolveWtvtDisplayValue(String fieldCode, Object rawValue) { + return formatWtvtLogValue(rawValue); + } + + private String resolveWtvtLogOperator() { + try { + return SecurityUtils.getCurrentUsername(); + } catch (Exception ignored) { + try { + return SecurityUtils.getUserId(); + } catch (Exception ex) { + return null; + } + } + } + + private String formatWtvtLogValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof Date date) { + return DateUtil.formatDateTime(date); + } + return String.valueOf(value); + } + + private String buildWtvtDepthKey(Object depth) { + return formatWtvtLogValue(depth); + } + + private String buildWtvtDepthRemark(String action, Object depth) { + String depthText = formatWtvtLogValue(depth); + return depthText == null ? action : action + "(深度:" + depthText + ")"; + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/controller/WeFishController.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/controller/WeFishController.java new file mode 100644 index 00000000..b9a881bb --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/controller/WeFishController.java @@ -0,0 +1,161 @@ +package com.yfd.platform.qgc_env.wte.controller; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.qgc_env.wte.service.WeFishService; +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("/wte") +@Tag(name = "生态调查模块") +@Validated +public class WeFishController { + + @Resource + private WeFishService weFishService; + + @PostMapping("/we/fisht/GetKendoListCust") + @Operation(summary = "条件过滤数据列表定制") + public ResponseResult getWeFishTKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getWeFishTKendoListCust(dataSourceRequest)); + } + + @PostMapping("/we/fisht/qgc/GetKendoListCust") + @Operation(summary = "全过程沿程鱼类变化情况") + public ResponseResult getQgcWeFishTKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getQgcWeFishTKendoListCust(dataSourceRequest)); + } + + @PostMapping("/we/fishList/GetKendoListCust") + @Operation(summary = "环保部-水生生态调查-水生生态一级页面列表") + public ResponseResult getQgcWeFishList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getQgcWeFishList(dataSourceRequest)); + } + + @PostMapping("/msstbprpt/GetKendoList") + @Operation(summary = "水生生态AI监测装置基础信息查询") + public ResponseResult getMsstbprptList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getMsstbprptList(dataSourceRequest)); + } + + @PostMapping("/vmsstbprpt/GetKendoList") + @Operation(summary = "水生生态站点基础统计查询") + public ResponseResult getVmsstbprptList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getVmsstbprptList(dataSourceRequest)); + } + + @PostMapping("/wva/year/GetKendoListCust") + @Operation(summary = "野生动物监测默认有数据的年份和月份") + public ResponseResult getWvaDefaultYearList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getWvaDefaultYearList(dataSourceRequest)); + } + + @PostMapping("/wva/GetKendoListCust") + @Operation(summary = "野生动物监测情况") + public ResponseResult getWvaList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getWvaList(dataSourceRequest)); + } + + @PostMapping("/wva/default/GetKendoListCust") + @Operation(summary = "野生动物监测默认数据") + public ResponseResult getWvaDefaultList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getWvaDefaultList(dataSourceRequest)); + } + + @PostMapping("/we/compareBar/GetKendoListCust") + @Operation(summary = "水生生态调查对比(柱状图)") + public ResponseResult getWeCompareBarList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getWeCompareBarList(dataSourceRequest)); + } + + @PostMapping("/we/fishPage/qgc/GetKendoListCust") + @Operation(summary = "环保部-水生生态调查二级页面") + public ResponseResult getQgcWeFishPageList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getQgcWeFishPageList(dataSourceRequest)); + } + + @PostMapping("/base/evnmAutoMonitor/GetKendoListCust") + @Operation(summary = "环保自动监测开展情况") + public ResponseResult getEnvmAutoMonitorList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getEnvmAutoMonitorList(dataSourceRequest)); + } + + @PostMapping("/we/fisht/year/qgc/GetKendoListCust") + @Operation(summary = "全过程沿程鱼类变化情况有数据的流域和年份") + public ResponseResult getQgcFishStaticsYearList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getQgcFishStaticsYearList(dataSourceRequest)); + } + + @PostMapping("/we/fisht/statics/GetKendoListCust") + @Operation(summary = "水生生态调查概况") + public ResponseResult getQgcWeFishStatics(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getQgcWeFishStatics(dataSourceRequest)); + } + + @PostMapping("/we/fisht/statics/getWeStaticsSecond") + @Operation(summary = "水生生态调查概况二级页面") + public ResponseResult getWeStaticsSecond(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getWeStaticsSecond(dataSourceRequest)); + } + + @PostMapping("/we/fisht/stat/qgc/GetKendoListCust") + @Operation(summary = "环保部-沿程鱼类变化情况柱状图") + public ResponseResult getQgcWeFishStatList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getQgcWeFishStatList(dataSourceRequest)); + } + + @PostMapping("/we/fisht/stat/GetKendoListCust") + @Operation(summary = "沿程鱼类变化情况柱状图") + public ResponseResult getWeFishStatList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getWeFishStatList(dataSourceRequest)); + } + + @PostMapping("/we/fisht/qgcDetail/GetKendoListCust") + @Operation(summary = "沿程鱼类变化情况二级弹窗-按照新逻辑重写") + public ResponseResult getQgcWeFishDetailList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getQgcWeFishDetailList(dataSourceRequest)); + } + + @PostMapping("/we/fisht/qgcDetail/qgc/GetKendoListCust") + @Operation(summary = "环保部-沿程鱼类变化情况二级弹窗") + public ResponseResult getHbbQgcWeFishDetailList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getHbbQgcWeFishDetailList(dataSourceRequest)); + } + + @PostMapping("/we/fisht/detail/GetKendoListCust") + @Operation(summary = "沿程鱼类变化情况二级弹窗") + public ResponseResult getWeFishDetailList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getWeFishDetailList(dataSourceRequest)); + } + + @PostMapping("/we/fisht/statTab/GetKendoListCust") + @Operation(summary = "沿程鱼类变化情况二级页面tab页签数据") + public ResponseResult getWeFishStatTabList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getWeFishStatTabList(dataSourceRequest)); + } + + @PostMapping("/we/fishList/stat/qgc/GetKendoListCust") + @Operation(summary = "环保部-水生生态调查-水生生态面板") + public ResponseResult getQgcFishListStat(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getQgcFishListStat(dataSourceRequest)); + } + + @PostMapping("/we/fishPoint/qgc/GetKendoListCust") + @Operation(summary = "环保部-水生生态调查-鱼类分布锚点") + public ResponseResult getQgcWeFishPoint(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getQgcWeFishPoint(dataSourceRequest)); + } + + @PostMapping("/te/tet/spec/GetKendoListCust") + @Operation(summary = "重点陆生动物二级页面") + public ResponseResult getTeSpecialAnimalList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(weFishService.getTeSpecialAnimalList(dataSourceRequest)); + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeCompareBarHeadColumnVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeCompareBarHeadColumnVo.java new file mode 100644 index 00000000..7790311d --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeCompareBarHeadColumnVo.java @@ -0,0 +1,33 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +@Data +@Accessors(chain = true) +@AllArgsConstructor +@Schema(description = "水生生态调查对比柱状图表头") +public class WeCompareBarHeadColumnVo { + + @Schema(description = "字段名") + private String dataIndex; + + @Schema(description = "标题") + private String title; + + @Schema(description = "是否可见") + private Boolean visible; + + @Schema(description = "键") + private String key; + + @Schema(description = "单位") + private boolean merge; + + @Schema(description = "子列") + private List children; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeCompareBarTableVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeCompareBarTableVo.java new file mode 100644 index 00000000..573d0f9c --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeCompareBarTableVo.java @@ -0,0 +1,22 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +@Data +@Accessors(chain = true) +@Schema(description = "水生生态调查对比柱状图表格") +public class WeCompareBarTableVo { + + @Schema(description = "表头") + private List columns; + + @Schema(description = "表格数据") + private Object dataSource; + + @Schema(description = "总数") + private Long total; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeCompareBarVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeCompareBarVo.java new file mode 100644 index 00000000..2999824c --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeCompareBarVo.java @@ -0,0 +1,29 @@ +package com.yfd.platform.qgc_env.wte.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 WeCompareBarVo { + + @Schema(description = "鱼类名称") + private String ftp; + + @Schema(description = "科属") + private String genus; + + @Schema(description = "调查批次") + private String dcpc; + + @Schema(description = "对比批次") + private String dcpc2; + + @Schema(description = "鱼类数量") + private Integer fcnt; + + @Schema(description = "对比鱼类数量") + private Integer fcnt2; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeEnvmAutoMonitorVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeEnvmAutoMonitorVo.java new file mode 100644 index 00000000..e84210c8 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeEnvmAutoMonitorVo.java @@ -0,0 +1,27 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "环保自动监测开展情况") +public class WeEnvmAutoMonitorVo { + + @Schema(description = "数量") + private Integer cnt; + + @Schema(description = "功能序号") + private Integer orderInx; + + @Schema(description = "功能序号名称") + private String orderInxName; + + @Schema(description = "类型路径") + private String sttpFullPath; + + @Schema(description = "站点类型") + private String sttpCode; + + @Schema(description = "站点类型名称") + private String sttpName; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishDetailVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishDetailVo.java new file mode 100644 index 00000000..cae4f59b --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishDetailVo.java @@ -0,0 +1,36 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +@Data +@Accessors(chain = true) +@Schema(description = "沿程鱼类变化情况二级弹窗") +public class WeFishDetailVo { + + @Schema(description = "电站编码") + private String rsctd; + + @Schema(description = "电站名称") + private String rsctdName; + + @Schema(description = "鱼类列表") + private List fishList; + + @Schema(description = "断面列表") + private List stcdList; + + @Data + @Accessors(chain = true) + @Schema(description = "断面信息") + public static class StationItem { + @Schema(description = "断面编码") + private String stcd; + + @Schema(description = "断面名称") + private String stnm; + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishHbbQgcDetailVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishHbbQgcDetailVo.java new file mode 100644 index 00000000..fc73c31a --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishHbbQgcDetailVo.java @@ -0,0 +1,29 @@ +package com.yfd.platform.qgc_env.wte.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 WeFishHbbQgcDetailVo { + + @Schema(description = "电站编码") + private String rstcd; + + @Schema(description = "电站名称") + private String rstcdName; + + @Schema(description = "断面编码") + private String stcd; + + @Schema(description = "断面名称") + private String stnm; + + @Schema(description = "鱼类名称") + private String name; + + @Schema(description = "鱼类对应ID") + private String id; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishListQgcVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishListQgcVo.java new file mode 100644 index 00000000..5ee533c5 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishListQgcVo.java @@ -0,0 +1,50 @@ +package com.yfd.platform.qgc_env.wte.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 WeFishListQgcVo { + + @Schema(description = "鱼类编码") + private String id; + + @Schema(description = "鱼类名称") + private String name; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "基地名称") + private String baseName; + + @Schema(description = "河流编码") + private String rvcd; + + @Schema(description = "河流名称") + private String rvcdName; + + @Schema(description = "流域编码") + private String hbrvcd; + + @Schema(description = "流域名称") + private String hbrvcdName; + + @Schema(description = "电站编码") + private String rstcd; + + @Schema(description = "电站名称") + private String ennm; + + @Schema(description = "时间") + private String tm; + + @Schema(description = "年份") + private Integer yr; + + @Schema(description = "鱼类数量") + private Long fcnt; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishListStatQgcVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishListStatQgcVo.java new file mode 100644 index 00000000..a70632a1 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishListStatQgcVo.java @@ -0,0 +1,52 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.Date; + +@Data +@Accessors(chain = true) +@Schema(description = "环保部-水生生态调查-水生生态面板") +public class WeFishListStatQgcVo { + + @Schema(description = "鱼类编码") + private String id; + + @Schema(description = "鱼类名称") + private String name; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "基地名称") + private String baseName; + + @Schema(description = "河流编码") + private String rvcd; + + @Schema(description = "河流名称") + private String rvcdName; + + @Schema(description = "流域编码") + private String hbrvcd; + + @Schema(description = "流域名称") + private String hbrvcdName; + + @Schema(description = "电站编码") + private String rstcd; + + @Schema(description = "电站名称") + private String ennm; + + @Schema(description = "时间") + private Date tm; + + @Schema(description = "年份") + private Integer yr; + + @Schema(description = "鱼类数量") + private Long fcnt; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishPageQgcVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishPageQgcVo.java new file mode 100644 index 00000000..ad5c68b0 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishPageQgcVo.java @@ -0,0 +1,37 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; + +@Data +@Accessors(chain = true) +@Schema(description = "环保部-水生生态调查二级页面数据") +public class WeFishPageQgcVo { + + @Schema(description = "鱼类名称") + private String ftp; + + @Schema(description = "科属") + private String genus; + + @Schema(description = "开始年份鱼类总量") + private Integer startFtpCnt; + + @Schema(description = "开始年份总量") + private Integer startCnt; + + @Schema(description = "开始年份占比") + private BigDecimal startYear; + + @Schema(description = "结束年份鱼类总量") + private Integer endFtpCnt; + + @Schema(description = "结束年份总量") + private Integer endCnt; + + @Schema(description = "结束年份占比") + private BigDecimal endYear; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishPageTableVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishPageTableVo.java new file mode 100644 index 00000000..99298e48 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishPageTableVo.java @@ -0,0 +1,22 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +@Data +@Accessors(chain = true) +@Schema(description = "环保部-水生生态调查二级页面表格") +public class WeFishPageTableVo { + + @Schema(description = "表头") + private List columns; + + @Schema(description = "表格数据") + private Object dataSource; + + @Schema(description = "总数") + private Long total; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishPointQgcVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishPointQgcVo.java new file mode 100644 index 00000000..5de853ca --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishPointQgcVo.java @@ -0,0 +1,64 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; + +@Data +@Accessors(chain = true) +@Schema(description = "环保部-水生生态调查-鱼类分布锚点") +public class WeFishPointQgcVo { + + @Schema(description = "站点类型") + private String sttp; + + @Schema(description = "站点编码") + private String stcd; + + @Schema(description = "经度") + private BigDecimal lgtd; + + @Schema(description = "纬度") + private BigDecimal lttd; + + @Schema(description = "高程") + private BigDecimal dtmel; + + @Schema(description = "描点状态") + private String anchoPointState; + + @Schema(description = "锚点类型") + private String sttpMap; + + @Schema(description = "弹框站点名称") + private String titleName; + + @Schema(description = "地图避让") + private Integer distance; + + @Schema(description = "流域编码") + private String rvcd; + + @Schema(description = "行政编码") + private String addvcd; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "关联电站编码") + private String rstcds; + + @Schema(description = "设施类型") + private String sttpCode; + + @Schema(description = "断面名称") + private String stnm; + + @Schema(description = "电站名称") + private String ennm; + + @Schema(description = "调查鱼类列表") + private String ftp; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishStatQgcVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishStatQgcVo.java new file mode 100644 index 00000000..0ad18a62 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishStatQgcVo.java @@ -0,0 +1,26 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Map; + +@Data +@Schema(description = "全过程沿程鱼类变化情况柱状图") +public class WeFishStatQgcVo { + + @Schema(description = "电站编码") + private String stcd; + + @Schema(description = "电站名称") + private String stnm; + + @Schema(description = "鱼类类型总数") + private Long total; + + @Schema(description = "鱼类类型明细,key 为鱼类类型,value 为鱼种类数量") + private Map detail; + + @Schema(description = "排序") + private Integer sort; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishStatTabVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishStatTabVo.java new file mode 100644 index 00000000..e5961f0e --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishStatTabVo.java @@ -0,0 +1,20 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +@Data +@Accessors(chain = true) +@Schema(description = "沿程鱼类变化情况二级页面tab页签数据") +public class WeFishStatTabVo { + + @Schema(description = "鱼类类型") + private String ty; + + @Schema(description = "鱼类类型名称") + private String tyName; + + @Schema(description = "鱼类数量") + private Long num; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishTQgcVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishTQgcVo.java new file mode 100644 index 00000000..fa0fc4a4 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeFishTQgcVo.java @@ -0,0 +1,134 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +@Data +@Schema(description = "全过程沿程鱼类变化情况") +public class WeFishTQgcVo { + + @Schema(description = "断面编码") + private String stcd; + + @Schema(description = "断面名称") + private String stnm; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "基地名称") + private String baseName; + + @Schema(description = "流域编码") + private String rvcd; + + @Schema(description = "流域名称") + private String rvcdName; + + @Schema(description = "行政区编码") + private String addvcd; + + @Schema(description = "行政区名称") + private String addvcdName; + + @Schema(description = "河段编码") + private String hbrvcd; + + @Schema(description = "河段名称") + private String hbrvcdName; + + @Schema(description = "调查批次") + private String dcpc; + + @Schema(description = "调查时间") + @JsonFormat(pattern = "yyyy-MM-dd") + private Date tm; + + @Schema(description = "调查报告") + private String werFid; + + @Schema(description = "调查主表ID") + private String werId; + + @Schema(description = "渔获物种类编码") + private String ftp; + + @Schema(description = "鱼类规格(cm)") + private String fsz; + + @Schema(description = "渔获物数量(尾)") + private Long fcnt; + + @Schema(description = "渔获物重量(kg)") + private BigDecimal fwgh; + + @Schema(description = "性腺发育期") + private String st; + + @Schema(description = "早期资源量和种类") + private String ps; + + @Schema(description = "平均重量") + private BigDecimal avgFwgt; + + @Schema(description = "平均体长") + private BigDecimal avgFsz; + + @Schema(description = "附件ID") + private String fid; + + @Schema(description = "现场影像ID") + private String fileId; + + @Schema(description = "鱼类ID") + private String id; + + @Schema(description = "渔获物种类") + private String name; + + @Schema(description = "别名") + private String alias; + + @Schema(description = "属") + private String genus; + + @Schema(description = "科") + private String family; + + @Schema(description = "种") + private String species; + + @Schema(description = "鱼类分类") + private String type; + + @Schema(description = "鱼类分类名称") + private String typeName; + + @Schema(description = "稀有程度") + private String rare; + + @Schema(description = "鱼类来源") + private String specOrigin; + + @Schema(description = "鱼类来源名称") + private String specOriginName; + + @Schema(description = "保护类型") + private String ptype; + + @Schema(description = "保护类型名称") + private String ptypeName; + + @Schema(description = "年份") + private String yr; + + @Schema(description = "鱼类类型") + private Integer ty; + + @Schema(description = "鱼类类型名称") + private String tyName; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeMsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeMsstbprptVo.java new file mode 100644 index 00000000..999bd6f3 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeMsstbprptVo.java @@ -0,0 +1,38 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +@Data +@Schema(description = "水生生态AI监测装置基础信息查询") +public class WeMsstbprptVo { + + @Schema(description = "主键") + private String id; + + @Schema(description = "站点编码") + private String stcd; + + @Schema(description = "所属电站编码") + private String rstcd; + + @Schema(description = "电站名称") + private String ennm; + + @Schema(description = "站点名称") + private String stnm; + + @Schema(description = "站类编码") + private String sttpCode; + + @Schema(description = "排序") + private Integer orderIndex; + + @Schema(description = "经度") + private BigDecimal lgtd; + + @Schema(description = "纬度") + private BigDecimal lttd; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeRvcdYearVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeRvcdYearVo.java new file mode 100644 index 00000000..96ce4c52 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeRvcdYearVo.java @@ -0,0 +1,15 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "沿程鱼类有数据流域年份") +public class WeRvcdYearVo { + + @Schema(description = "河段编码") + private String hbrvcd; + + @Schema(description = "年份") + private String yr; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeStaticsVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeStaticsVo.java new file mode 100644 index 00000000..83a2e442 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeStaticsVo.java @@ -0,0 +1,49 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.Date; + +@Data +@Accessors(chain = true) +@Schema(description = "水生生态调查概况") +public class WeStaticsVo { + + @Schema(description = "断面编码") + private String stcd; + + @Schema(description = "断面名称") + private String stnm; + + @Schema(description = "调查批次") + private String dcpc; + + @Schema(description = "调查鱼类") + private String ftp; + + @Schema(description = "调查鱼类名称") + private String ftpName; + + @Schema(description = "鱼类数量") + private Long fcnt; + + @Schema(description = "附件ID") + private String fid; + + @Schema(description = "调查时间") + private Date tm; + + @Schema(description = "调查批次数量") + private Long dcpcCount; + + @Schema(description = "调查断面数量") + private Long stcdCount; + + @Schema(description = "调查鱼类数量") + private Long ftpCount; + + @Schema(description = "调查鱼类总数") + private Long fcntSum; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeTeSpecialAnimalVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeTeSpecialAnimalVo.java new file mode 100644 index 00000000..7622d501 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeTeSpecialAnimalVo.java @@ -0,0 +1,32 @@ +package com.yfd.platform.qgc_env.wte.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 WeTeSpecialAnimalVo { + + @Schema(description = "动物主键") + private String id; + + @Schema(description = "动物名称") + private String name; + + @Schema(description = "动物英文名称") + private String nameEn; + + @Schema(description = "保护级别编码") + private String protectlvl; + + @Schema(description = "保护级别名称") + private String protectlvlName; + + @Schema(description = "LOGO") + private String logo; + + @Schema(description = "介绍") + private String introduce; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeVmsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeVmsstbprptVo.java new file mode 100644 index 00000000..e65e99cf --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeVmsstbprptVo.java @@ -0,0 +1,47 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +@Data +@Schema(description = "水生生态站点基础统计查询") +public class WeVmsstbprptVo { + + @Schema(description = "主键") + private String id; + + @Schema(description = "站类编码") + private String sttpCode; + + @Schema(description = "站点编码") + private String stcd; + + @Schema(description = "站点名称") + private String stnm; + + @Schema(description = "所属电站编码") + private String rstcd; + + @Schema(description = "所属电站名称") + private String ennm; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "流域编码") + private String hbrvcd; + + @Schema(description = "河流编码") + private String rvcd; + + @Schema(description = "排序") + private Integer orderIndex; + + @Schema(description = "经度") + private BigDecimal lgtd; + + @Schema(description = "纬度") + private BigDecimal lttd; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeWvaDefaultVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeWvaDefaultVo.java new file mode 100644 index 00000000..d683b725 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeWvaDefaultVo.java @@ -0,0 +1,28 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Date; + +@Data +@Schema(description = "野生动物监测默认数据") +public class WeWvaDefaultVo { + + @Schema(description = "站点编码") + private String stcd; + + @Schema(description = "站点名称") + private String stnm; + + @Schema(description = "站类编码") + private String sttpCode; + + @Schema(description = "站类名称") + private String sttpName; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Schema(description = "最新时间") + private Date tm; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeWvaQgcVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeWvaQgcVo.java new file mode 100644 index 00000000..b0911f8d --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeWvaQgcVo.java @@ -0,0 +1,58 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Date; + +@Data +@Schema(description = "野生动物监测情况") +public class WeWvaQgcVo { + + @Schema(description = "主键") + private String id; + + @Schema(description = "野生动物监测站编码") + private String stcd; + + @Schema(description = "野生动物监测站名称") + private String stnm; + + @Schema(description = "站类编码") + private String sttpCode; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Schema(description = "时间") + private Date tm; + + @Schema(description = "显示名称") + private String flnm; + + @Schema(description = "图片路径") + private String imgPath; + + @Schema(description = "视频路径") + private String flpth; + + @Schema(description = "附件ID") + private String fid; + + @Schema(description = "备注") + private String description; + + @Schema(description = "所属电站编码") + private String rstcd; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "流域编码") + private String hbrvcd; + + @Schema(description = "河流编码") + private String rvcd; + + @Schema(description = "排序") + private Integer orderIndex; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeWvaYearQgcVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeWvaYearQgcVo.java new file mode 100644 index 00000000..ef90a362 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/entity/vo/WeWvaYearQgcVo.java @@ -0,0 +1,12 @@ +package com.yfd.platform.qgc_env.wte.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "野生动物监测默认有数据的年月") +public class WeWvaYearQgcVo { + + @Schema(description = "年月,格式yyyy-MM") + private String ym; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/service/WeFishService.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/service/WeFishService.java new file mode 100644 index 00000000..fe6da23e --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/service/WeFishService.java @@ -0,0 +1,74 @@ +package com.yfd.platform.qgc_env.wte.service; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishListQgcVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishListStatQgcVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeCompareBarTableVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeEnvmAutoMonitorVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishDetailVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishHbbQgcDetailVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeMsstbprptVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishPageTableVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishPointQgcVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishStatQgcVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishStatTabVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishTQgcVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeStaticsVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeTeSpecialAnimalVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeVmsstbprptVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeWvaDefaultVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeWvaQgcVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeWvaYearQgcVo; + +import java.util.List; +import java.util.Map; + +public interface WeFishService { + + DataSourceResult getWeFishTKendoListCust(DataSourceRequest dataSourceRequest); + + DataSourceResult getQgcWeFishTKendoListCust(DataSourceRequest dataSourceRequest); + + DataSourceResult getQgcWeFishList(DataSourceRequest dataSourceRequest); + + DataSourceResult getMsstbprptList(DataSourceRequest dataSourceRequest); + + DataSourceResult getVmsstbprptList(DataSourceRequest dataSourceRequest); + + DataSourceResult getWvaList(DataSourceRequest dataSourceRequest); + + DataSourceResult getWvaDefaultList(DataSourceRequest dataSourceRequest); + + DataSourceResult getWvaDefaultYearList(DataSourceRequest dataSourceRequest); + + DataSourceResult getWeCompareBarList(DataSourceRequest dataSourceRequest); + + DataSourceResult getQgcWeFishPageList(DataSourceRequest dataSourceRequest); + + DataSourceResult getEnvmAutoMonitorList(DataSourceRequest dataSourceRequest); + + DataSourceResult>> getQgcFishStaticsYearList(DataSourceRequest dataSourceRequest); + + DataSourceResult getQgcWeFishStatics(DataSourceRequest dataSourceRequest); + + DataSourceResult getWeStaticsSecond(DataSourceRequest dataSourceRequest); + + DataSourceResult getQgcWeFishStatList(DataSourceRequest dataSourceRequest); + + DataSourceResult getWeFishStatList(DataSourceRequest dataSourceRequest); + + DataSourceResult getQgcWeFishDetailList(DataSourceRequest dataSourceRequest); + + DataSourceResult getHbbQgcWeFishDetailList(DataSourceRequest dataSourceRequest); + + DataSourceResult getWeFishDetailList(DataSourceRequest dataSourceRequest); + + DataSourceResult getWeFishStatTabList(DataSourceRequest dataSourceRequest); + + DataSourceResult getQgcFishListStat(DataSourceRequest dataSourceRequest); + + DataSourceResult getQgcWeFishPoint(DataSourceRequest dataSourceRequest); + + DataSourceResult getTeSpecialAnimalList(DataSourceRequest dataSourceRequest); +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wte/service/impl/WeFishServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/wte/service/impl/WeFishServiceImpl.java new file mode 100644 index 00000000..d6fa20be --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wte/service/impl/WeFishServiceImpl.java @@ -0,0 +1,4630 @@ +package com.yfd.platform.qgc_env.wte.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.common.DataSourceLoadOptionsBase; +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.common.GroupHelper; +import com.yfd.platform.common.GroupingInfo; +import com.yfd.platform.common.MicroservicDynamicSQLMapper; +import com.yfd.platform.qgc_env.wte.entity.vo.WeCompareBarHeadColumnVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeCompareBarTableVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeCompareBarVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeEnvmAutoMonitorVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishListQgcVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishListStatQgcVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishDetailVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishHbbQgcDetailVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishPageQgcVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishPageTableVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeMsstbprptVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishPointQgcVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishStatQgcVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishStatTabVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeFishTQgcVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeRvcdYearVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeStaticsVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeTeSpecialAnimalVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeVmsstbprptVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeWvaDefaultVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeWvaQgcVo; +import com.yfd.platform.qgc_env.wte.entity.vo.WeWvaYearQgcVo; +import com.yfd.platform.qgc_env.wte.service.WeFishService; +import com.yfd.platform.utils.QgcQueryWrapperUtil; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +@Service +public class WeFishServiceImpl implements WeFishService { + + @Resource + private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; + + @Override + public DataSourceResult getWeFishTKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + GroupingInfo[] groupInfos = loadOptions == null ? null : loadOptions.getGroup(); + Map paramMap = new HashMap<>(); + + String filterSql = buildWeFishQgcFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT r.* FROM (") + .append(buildWeFishTDetailSql()) + .append(") r WHERE 1 = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + + DataSourceResult result = new DataSourceResult<>(); + if (CollUtil.isNotEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + String groupedSql = buildWeFishQgcGroupSql(sql.toString(), groupInfos); + List> rows = microservicDynamicSQLMapper.getAllList(groupedSql, paramMap); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal((long) rows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + sql.append(buildWeFishQgcOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + WeFishTQgcVo.class + ); + fillWeFishDerivedFields(list); + + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getQgcWeFishTKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + GroupingInfo[] groupInfos = loadOptions == null ? null : loadOptions.getGroup(); + Map paramMap = new HashMap<>(); + + String filterSql = buildWeFishQgcFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT r.* FROM (") + .append(buildWeFishQgcDetailSql()) + .append(") r WHERE 1 = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + + DataSourceResult result = new DataSourceResult<>(); + if (CollUtil.isNotEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + String groupedSql = buildWeFishQgcGroupSql(sql.toString(), groupInfos); + List> rows = microservicDynamicSQLMapper.getAllList(groupedSql, paramMap); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal((long) rows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + sql.append(buildWeFishQgcOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + WeFishTQgcVo.class + ); + fillWeFishDerivedFields(list); + + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getQgcWeFishList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + GroupingInfo[] groupInfos = loadOptions == null ? null : loadOptions.getGroup(); + Map paramMap = new HashMap<>(); + + String filterSql = buildWeFishListStatFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT r.id AS id, r.name AS name, r.rvcd AS rvcd, r.rvcdName AS rvcdName, ") + .append("r.hbrvcd AS hbrvcd, r.hbrvcdName AS hbrvcdName, r.rstcd AS rstcd, r.ennm AS ennm, ") + .append("r.baseId AS baseId, r.baseName AS baseName, r.tm AS tm, r.yr AS yr, r.fcnt AS fcnt, r.code AS code ") + .append("FROM (") + .append(buildWeFishListStatQgcDetailSql()) + .append(") r WHERE 1 = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append("AND ").append(filterSql).append(" "); + } + + DataSourceResult result = new DataSourceResult<>(); + if (CollUtil.isNotEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + String groupedSql = buildWeFishListQgcGroupSql(sql.toString(), groupInfos); + List> rows = microservicDynamicSQLMapper.getAllList(groupedSql, paramMap); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + + sql.append(buildWeFishListQgcOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List> rows = microservicDynamicSQLMapper.pageAllList(page, sql.toString(), paramMap); + List list = new ArrayList<>(); + for (Map row : rows) { + WeFishListQgcVo vo = buildWeFishListQgcVo(row); + if (vo != null) { + list.add(vo); + } + } + + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getMsstbprptList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Map paramMap = new HashMap<>(); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildWeMsstbprptSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildWeMsstbprptViewSql()) + .append(") t WHERE 1 = 1 "); + + String filterSql = buildWeMsstbprptFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append("AND ").append(filterSql).append(" "); + } + sql.append(buildWeMsstbprptOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + WeMsstbprptVo.class + ); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getVmsstbprptList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Map paramMap = new HashMap<>(); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildWeVmsstbprptSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildWeVmsstbprptViewSql()) + .append(") t WHERE 1 = 1 "); + + String filterSql = buildWeVmsstbprptFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append("AND ").append(filterSql).append(" "); + } + sql.append(buildWeVmsstbprptOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + WeVmsstbprptVo.class + ); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getWvaDefaultYearList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Map paramMap = new HashMap<>(); + + String filterSql = buildWeWvaYearFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT TO_CHAR(a.TM, 'yyyy') || '-' || TO_CHAR(a.TM, 'MM') AS ym ") + .append("FROM SD_WVA_R a ") + .append("INNER JOIN SD_AIMONITOR_B_H b ON a.STCD = b.STCD ") + .append("WHERE NVL(a.IS_DELETED, 0) = 0 ") + .append("AND NVL(b.IS_DELETED, 0) = 0 ") + .append("AND b.STTP = 'WVA' "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append("AND ").append(filterSql).append(" "); + } + sql.append("GROUP BY TO_CHAR(a.TM, 'yyyy'), TO_CHAR(a.TM, 'MM') ") + .append("ORDER BY TO_CHAR(a.TM, 'yyyy') DESC, TO_CHAR(a.TM, 'MM') DESC"); + + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + WeWvaYearQgcVo.class + ); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal((long) list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getWvaDefaultList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Map innerParamMap = new HashMap<>(); + Map outerParamMap = new HashMap<>(); + + String innerFilterSql = buildWeWvaDefaultInnerFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + innerParamMap, + new int[]{0} + ); + String outerFilterSql = buildWeWvaDefaultOuterFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + outerParamMap, + new int[]{0} + ); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT t.stcd AS stcd, t.stnm AS stnm, t.tm AS tm, t.sttpCode AS sttpCode, t.sttpName AS sttpName ") + .append("FROM (") + .append("SELECT latest.stcd AS stcd, ai.STNM AS stnm, latest.tm AS tm, ai.STTP AS sttpCode, sttp.STTP_NAME AS sttpName, ") + .append("ai.RSTCD AS rstcd, ai.BASE_ID AS baseId, ai.HBRVCD AS hbrvcd ") + .append("FROM (SELECT src.STCD AS stcd, MAX(src.TM) AS tm FROM SD_WVA_R src WHERE NVL(src.IS_DELETED, 0) = 0 "); + if (StrUtil.isNotBlank(innerFilterSql)) { + sql.append("AND ").append(innerFilterSql).append(" "); + } + sql.append("GROUP BY src.STCD) latest ") + .append("INNER JOIN SD_AIMONITOR_B_H ai ON latest.stcd = ai.STCD ") + .append("AND NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP = 'WVA' ") + .append("LEFT JOIN SD_STTP_B sttp ON ai.STTP = sttp.STTP_CODE ") + .append("AND NVL(sttp.IS_DELETED, 0) = 0 ") + .append(") t WHERE 1 = 1 "); + if (StrUtil.isNotBlank(outerFilterSql)) { + sql.append("AND ").append(outerFilterSql).append(" "); + } + sql.append(buildWeWvaDefaultOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Map paramMap = new HashMap<>(); + paramMap.putAll(innerParamMap); + paramMap.putAll(outerParamMap); + + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + WeWvaDefaultVo.class + ); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : (long) list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getWvaList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Map paramMap = new HashMap<>(); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildWeWvaSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildWeWvaViewSql()) + .append(") t WHERE 1 = 1 "); + + String filterSql = buildWeWvaFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append("AND ").append(filterSql).append(" "); + } + sql.append(buildWeWvaOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + WeWvaQgcVo.class + ); + for (WeWvaQgcVo vo : list) { + if (vo == null || vo.getTm() == null || StrUtil.isBlank(vo.getStnm())) { + continue; + } + vo.setFlnm(vo.getStnm() + " " + DateUtil.format(vo.getTm(), "yyyy-MM-dd HH")); + } + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getWeCompareBarList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + DataSourceRequest.FilterDescriptor filter = dataSourceRequest == null ? null : dataSourceRequest.getFilter(); + + String stcd = getFirstWeFishFilterText(filter, "stcd"); + String dcpc = getFirstWeFishFilterText(filter, "dcpc"); + String dcpc2 = getFirstWeFishFilterText(filter, "dcpc2"); + + List list = new ArrayList<>(); + long total = 0L; + if (StrUtil.isNotBlank(stcd) && StrUtil.isNotBlank(dcpc) && StrUtil.isNotBlank(dcpc2)) { + Map paramMap = new HashMap<>(); + paramMap.put("stcd", stcd); + paramMap.put("dcpc", dcpc); + paramMap.put("dcpc2", dcpc2); + + String sql = "SELECT dict.NAME AS ftp, " + + "MAX(NVL(dict.FAMILY, '') || NVL(dict.GENUS, '')) AS genus, " + + "#{map.dcpc} AS dcpc, " + + "#{map.dcpc2} AS dcpc2, " + + "SUM(CASE WHEN we.DCPC = #{map.dcpc} THEN NVL(fish.FCNT, 0) ELSE 0 END) AS fcnt, " + + "SUM(CASE WHEN we.DCPC = #{map.dcpc2} THEN NVL(fish.FCNT, 0) ELSE 0 END) AS fcnt2 " + + "FROM SD_WE_R we " + + "INNER JOIN SD_WEFISH_R fish ON we.ID = fish.WER_ID AND NVL(fish.IS_DELETED, 0) = 0 " + + "INNER JOIN SD_WE_B_H section ON section.STCD = we.STCD AND NVL(section.USFL, 0) = 1 " + + "INNER JOIN SD_FISHDICTORY_B dict ON dict.ID = fish.FTP AND NVL(dict.IS_DELETED, 0) = 0 " + + "WHERE NVL(we.IS_DELETED, 0) = 0 " + + "AND NVL(we.STATUS, 1) = 1 " + + "AND we.STCD = #{map.stcd} " + + "AND we.DCPC IN (#{map.dcpc}, #{map.dcpc2}) " + + "GROUP BY dict.NAME " + + "ORDER BY dict.NAME"; + + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + list = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql, paramMap, WeCompareBarVo.class); + total = page != null ? page.getTotal() : list.size(); + } + + WeCompareBarTableVo tableVo = new WeCompareBarTableVo() + .setColumns(buildWeCompareBarColumns(dcpc, dcpc2)) + .setDataSource(list) + .setTotal(total); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(Collections.singletonList(tableVo)); + result.setTotal(total); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getQgcWeFishPageList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + DataSourceRequest.FilterDescriptor filter = dataSourceRequest == null ? null : dataSourceRequest.getFilter(); + + String startYear = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "startYear"); + String endYear = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "endYear"); + if (StrUtil.isBlank(startYear)) { + throw new IllegalArgumentException("开始年份不能为空!"); + } + if (StrUtil.isBlank(endYear)) { + throw new IllegalArgumentException("结束年份(endYear)不能为空!"); + } + + String baseId = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "baseId"); + String hbrvcd = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "hbrvcd"); + String rstcd = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "rstcd"); + String ftp = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "ftp"); + + Map paramMap = new HashMap<>(); + paramMap.put("startYear", startYear); + paramMap.put("endYear", endYear); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ftp, genus, startFtpCnt, startCnt, startYear, endFtpCnt, endCnt, endYear ") + .append("FROM (") + .append("SELECT dict.NAME AS ftp, ") + .append("CONCAT(CONCAT(dict.FAMILY,'-'),dict.GENUS) as genus, ") + .append("agg.startYear AS startYear, agg.endYear AS endYear, ") + .append("agg.startCnt AS startCnt, agg.startFtpCnt AS startFtpCnt, ") + .append("agg.endCnt AS endCnt, agg.endFtpCnt AS endFtpCnt ") + .append("FROM (") + .append("SELECT ftp, hbrvcd, ") + .append("ROUND(MAX(startYear), 2) AS startYear, ") + .append("ROUND(MAX(endYear), 2) AS endYear, ") + .append("MAX(startCnt) AS startCnt, ") + .append("MAX(startFtpCnt) AS startFtpCnt, ") + .append("MAX(endCnt) AS endCnt, ") + .append("MAX(endFtpCnt) AS endFtpCnt ") + .append("FROM (") + .append("SELECT fishAgg.ftp AS ftp, fishAgg.hbrvcd AS hbrvcd, fishAgg.fcnt AS fcnt, ") + .append("CASE WHEN fishAgg.yr = #{map.startYear} ") + .append("THEN CASE WHEN NVL(totalAgg.fcnt, 0) = 0 THEN 0 ELSE 100 * fishAgg.fcnt / totalAgg.fcnt END END AS startYear, ") + .append("CASE WHEN fishAgg.yr = #{map.endYear} ") + .append("THEN CASE WHEN NVL(totalAgg.fcnt, 0) = 0 THEN 0 ELSE 100 * fishAgg.fcnt / totalAgg.fcnt END END AS endYear, ") + .append("CASE WHEN fishAgg.yr = #{map.startYear} THEN fishAgg.fcnt END AS startFtpCnt, ") + .append("CASE WHEN fishAgg.yr = #{map.startYear} THEN totalAgg.fcnt END AS startCnt, ") + .append("CASE WHEN fishAgg.yr = #{map.endYear} THEN fishAgg.fcnt END AS endFtpCnt, ") + .append("CASE WHEN fishAgg.yr = #{map.endYear} THEN totalAgg.fcnt END AS endCnt ") + .append("FROM (") + .append("SELECT fish.FTP AS ftp, section.HBRVCD AS hbrvcd, SUM(NVL(fish.FCNT, 0)) AS fcnt, TO_CHAR(we.TM, 'YYYY') AS yr ") + .append("FROM SD_WE_R we ") + .append("INNER JOIN SD_WEFISH_R fish ON we.ID = fish.WER_ID ") + .append(" AND NVL(fish.IS_DELETED, 0) = 0 ") + .append("INNER JOIN SD_WE_B_H section ON section.STCD = we.STCD ") + .append("INNER JOIN V_SD_FISHDICTORY_B dictFilter ON dictFilter.FISH_ID = fish.FTP ") + .append(" AND (section.HBRVCD = dictFilter.RVCD OR dictFilter.RVCD = 'ZY') ") + .append("WHERE NVL(we.STATUS, 1) = 1 ") + .append("AND NVL(we.IS_DELETED, 0) = 0 ") + .append("AND TO_CHAR(we.TM, 'YYYY') IN (#{map.startYear}, #{map.endYear}) "); + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("fishPageBaseId", baseId); + sql.append("AND section.BASE_ID = #{map.fishPageBaseId} "); + } + if (StrUtil.isNotBlank(hbrvcd)) { + paramMap.put("fishPageHbrvcd", hbrvcd); + sql.append("AND section.HBRVCD = #{map.fishPageHbrvcd} "); + } + if (StrUtil.isNotBlank(rstcd)) { + paramMap.put("fishPageRstcd", rstcd); + sql.append("AND section.RSTCD = #{map.fishPageRstcd} "); + } + sql.append("GROUP BY fish.FTP, section.HBRVCD, TO_CHAR(we.TM, 'YYYY') ") + .append(") fishAgg ") + .append("LEFT JOIN (") + .append("SELECT SUM(NVL(fish.FCNT, 0)) AS fcnt, TO_CHAR(we.TM, 'YYYY') AS yr ") + .append("FROM SD_WE_R we ") + .append("INNER JOIN SD_WEFISH_R fish ON we.ID = fish.WER_ID ") + .append(" AND NVL(fish.IS_DELETED, 0) = 0 ") + .append("INNER JOIN SD_WE_B_H section ON section.STCD = we.STCD ") + .append("INNER JOIN V_SD_FISHDICTORY_B dictFilter ON dictFilter.FISH_ID = fish.FTP ") + .append(" AND (section.HBRVCD = dictFilter.RVCD OR dictFilter.RVCD = 'ZY') ") + .append("WHERE NVL(we.STATUS, 1) = 1 ") + .append("AND NVL(we.IS_DELETED, 0) = 0 ") + .append("AND TO_CHAR(we.TM, 'YYYY') IN (#{map.startYear}, #{map.endYear}) "); + if (StrUtil.isNotBlank(baseId)) { + sql.append("AND section.BASE_ID = #{map.fishPageBaseId} "); + } + if (StrUtil.isNotBlank(hbrvcd)) { + sql.append("AND section.HBRVCD = #{map.fishPageHbrvcd} "); + } + if (StrUtil.isNotBlank(rstcd)) { + sql.append("AND section.RSTCD = #{map.fishPageRstcd} "); + } + sql.append("GROUP BY TO_CHAR(we.TM, 'YYYY') ") + .append(") totalAgg ON totalAgg.yr = fishAgg.yr ") + .append(") temp ") + .append("GROUP BY ftp, hbrvcd ") + .append(") agg ") + .append("INNER JOIN V_SD_FISHDICTORY_B dict ON dict.FISH_ID = agg.ftp ") + .append(" AND (agg.HBRVCD = dict.RVCD OR dict.RVCD = 'ZY')") + .append(") r WHERE 1 = 1 "); + if (StrUtil.isNotBlank(ftp)) { + paramMap.put("fishPageFtp", "%" + ftp.trim() + "%"); + sql.append("AND r.ftp LIKE #{map.fishPageFtp} "); + } + sql.append(buildWeFishPageOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + WeFishPageQgcVo.class + ); + long total = page != null ? page.getTotal() : list.size(); + + WeFishPageTableVo tableVo = new WeFishPageTableVo() + .setColumns(buildWeFishPageColumns(startYear, endYear)) + .setDataSource(list) + .setTotal(total); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(Collections.singletonList(tableVo)); + result.setTotal(total); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getEnvmAutoMonitorList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + DataSourceRequest.FilterDescriptor filter = dataSourceRequest == null ? null : dataSourceRequest.getFilter(); + + String baseId = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "baseId"); + Date startTime = toDateValue(resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "startTime")); + Date endTime = toDateValue(resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "endTime")); + if (startTime == null || endTime == null) { + startTime = null; + endTime = null; + } + + List rstcds = getWeFishFilterTexts(filter, "rstcd"); + List hbrvcds = getWeFishFilterTexts(filter, "hbrvcd"); + List rvcds = getWeFishFilterTexts(filter, "rvcd"); + List showIds = getWeFishFilterTexts(filter, "showIds"); + boolean ignoreFhRstcd = shouldIgnoreWeEnvmFhRstcd(rstcds); + + List rows = new ArrayList<>(); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmWtSql(baseId, rstcds)), + 1, null, "ENV,ENVM,WT,", "水温监测" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmGjWqSql(baseId, hbrvcds, rvcds)), + 2, "WQ", "ENV,ENVM,WQ,", "国家水质站" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmZjWqSql(baseId, rstcds)), + 3, "WQ", "ENV,ENVM,WQ,", "水质监测" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmStGjSql(baseId)), + 5, null, "ST,ZQ-ST,ZZ", "国家水文站" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmStZjSql(baseId, rstcds)), + 6, null, "ST,ZQ-ST,ZZ", "水文监测" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmEngQecSql(baseId, rstcds)), + 7, "ENG", "ENG", "生态流量" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmVdSql(baseId, rstcds)), + 8, null, "VD,VD", "视频监控" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmRiverWqSql(baseId, rstcds)), + 9, "WQ", "ENV,ENVM,WQ,", "河道水质监测" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmFbWqSql(baseId, rstcds)), + 10, "WQFB", "ENV,ENVM,WQFB,", "增殖站水质站" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmFhSql(baseId, rstcds, ignoreFhRstcd)), + 11, "FH", "ENV,ENVP,FH,", "栖息地" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmFhWqSql(baseId, rstcds, ignoreFhRstcd)), + 12, "WQ", "ENV,ENVM,WQ,", "栖息地水质监测" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmFhWtSql(baseId, rstcds, ignoreFhRstcd)), + 13, "WTRV", "ENV,ENVM,WT,WTRV,", "栖息地水温监测" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmFhStSql(baseId, rstcds, ignoreFhRstcd)), + 14, null, "ST,ZQ-ST,ZZ", "水文监测" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmWeSql(baseId, rstcds)), + 15, "WE", "ENV,ENVM,WE,", "水生态调查断面" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmWvaSql(baseId, rstcds, hbrvcds)), + 16, "WVA", "ENV,ENVM,WVA,", "野生动物监测" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmVdEqsSql(baseId, rstcds)), + 17, "VD_EQS", "VD,VD_EQS,", "生态流量视频站" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmRareFishSql(baseId, rstcds, startTime, endTime)), + 18, null, "WE_FISH", "土著珍稀鱼类" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmTeAnimalsSql()), + 20, "TE_ANIMALS", "TE_ANIMALS", "重点陆生动物" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmRgWqSql(baseId, rstcds)), + 21, "WQ", "ENV,ENVM,WQ,", "人工水质监测" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmWeFishStaticsSql(baseId, rstcds, startTime, endTime)), + 22, "WE", "WE_FISH_ST", "调查鱼类统计" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmFpStaticsSql(baseId, rstcds)), + 23, "FP", "ENV,ENVP,FP,", "过鱼设施" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmVdYljSql(baseId, rstcds)), + 24, null, "VD,VD", "视频监控" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmAiSql(baseId, rstcds, hbrvcds)), + 25, "AI", "AI,AI_", "AI盒子" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmWtrvSql(baseId, rstcds)), + 26, null, "ENV,ENVM,WT,", "表层水温监测" + )); + rows.add(buildWeEnvmAutoMonitorVo( + queryWeEnvmAutoMonitorCount(buildWeEnvmWtvtSql(baseId, rstcds)), + 27, null, "ENV,ENVM,WT,", "垂向水温监测" + )); + + List finalRows = reorderWeEnvmAutoMonitorRows(rows, showIds); + DataSourceResult result = new DataSourceResult<>(); + result.setData(finalRows); + result.setTotal((long) finalRows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult>> getQgcFishStaticsYearList(DataSourceRequest dataSourceRequest) { + Map paramMap = new HashMap<>(); + DataSourceRequest.FilterDescriptor filter = dataSourceRequest == null ? null : dataSourceRequest.getFilter(); + + String baseId = getFirstWeFishFilterText(filter, "baseId"); + String hbrvcd = getFirstWeFishFilterText(filter, "hbrvcd"); + String yr = getFirstWeFishFilterText(filter, "yr"); + List rstcdList = getWeFishFilterTexts(filter, "rstcd"); + + String sql = buildWeFishYearSql(baseId, hbrvcd, yr, rstcdList, paramMap); + List rows = microservicDynamicSQLMapper.getAllListWithResultType(sql, paramMap, WeRvcdYearVo.class); + + LinkedHashMap> yrMap = new LinkedHashMap<>(); + for (WeRvcdYearVo row : rows) { + if (row == null || StrUtil.isBlank(row.getHbrvcd()) || StrUtil.isBlank(row.getYr())) { + continue; + } + yrMap.computeIfAbsent(row.getHbrvcd(), key -> new ArrayList<>()).add(row.getYr()); + } + + DataSourceResult>> result = new DataSourceResult<>(); + if (yrMap.isEmpty()) { + result.setData(null); + result.setTotal(0L); + } else { + result.setData(java.util.Collections.singletonList(yrMap)); + result.setTotal(1L); + } + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getQgcWeFishStatics(DataSourceRequest dataSourceRequest) { + Map paramMap = new HashMap<>(); + DataSourceRequest.FilterDescriptor filter = dataSourceRequest == null ? null : dataSourceRequest.getFilter(); + + String baseId = getFirstWeFishFilterText(filter, "baseId"); + String hbrvcd = getFirstWeFishFilterText(filter, "hbrvcd"); + String yr = getFirstWeFishFilterText(filter, "yr"); + List rstcdList = getWeFishFilterTexts(filter, "rstcd"); + + String sql = buildWeFishStaticsSql(baseId, hbrvcd, yr, rstcdList, paramMap); + Map row = microservicDynamicSQLMapper.getOneBySql(sql, paramMap); + WeStaticsVo vo = buildWeFishStaticsVo(row); + if (vo == null) { + vo = new WeStaticsVo(); + } + vo.setDcpcCount(vo.getDcpcCount() == null ? 0L : vo.getDcpcCount()); + vo.setStcdCount(vo.getStcdCount() == null ? 0L : vo.getStcdCount()); + vo.setFtpCount(vo.getFtpCount() == null ? 0L : vo.getFtpCount()); + vo.setFcntSum(vo.getFcntSum() == null ? 0L : vo.getFcntSum()); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(Collections.singletonList(vo)); + result.setTotal(1L); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getWeStaticsSecond(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + GroupingInfo[] groupInfos = loadOptions == null ? null : loadOptions.getGroup(); + Map paramMap = new HashMap<>(); + + String filterSql = buildWeFishQgcFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildWeStaticsSecondSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildWeFishQgcDetailSql()) + .append(") r WHERE 1 = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + + DataSourceResult result = new DataSourceResult<>(); + if (CollUtil.isNotEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + String groupedSql = buildWeFishQgcGroupSql(sql.toString(), groupInfos); + List> rows = microservicDynamicSQLMapper.getAllList(groupedSql, paramMap); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal((long) rows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + sql.append(buildWeFishQgcOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + WeStaticsVo.class + ); + + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getWeFishStatList(DataSourceRequest dataSourceRequest) { + Map paramMap = new HashMap<>(); + DataSourceRequest.FilterDescriptor filter = dataSourceRequest == null ? null : dataSourceRequest.getFilter(); + + String baseId = getFirstWeFishFilterText(filter, "baseId"); + String hbrvcd = getFirstWeFishFilterText(filter, "hbrvcd"); + String yr = getFirstWeFishFilterText(filter, "yr"); + List rstcdList = getWeFishFilterTexts(filter, "rstcd"); + + String sql = buildWeFishStatSql(baseId, hbrvcd, yr, rstcdList, paramMap); + List> rows = microservicDynamicSQLMapper.getAllList(sql, paramMap); + return buildWeFishStatResult(rows); + } + + @Override + public DataSourceResult getQgcWeFishDetailList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + Map paramMap = new HashMap<>(); + DataSourceRequest.FilterDescriptor filter = dataSourceRequest == null ? null : dataSourceRequest.getFilter(); + + String baseId = firstNonBlankWeFishFilter(filter, "baseId", "base_id"); + String rstcd = getFirstWeFishFilterText(filter, "stcd"); + String rvcd = firstNonBlankWeFishFilter(filter, "rvcd", "hbrvcd"); + String yr = getFirstWeFishFilterText(filter, "yr"); + String ty = getFirstWeFishFilterText(filter, "ty"); + + String sql = buildQgcWeFishDetailSql(baseId, rstcd, rvcd, yr, ty, paramMap); + List> rows = microservicDynamicSQLMapper.pageAllList(page, sql, paramMap); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(buildQgcWeFishDetailResult(rows)); + result.setTotal(page != null ? page.getTotal() : (long) rows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getHbbQgcWeFishDetailList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + Map paramMap = new HashMap<>(); + DataSourceRequest.FilterDescriptor filter = dataSourceRequest == null ? null : dataSourceRequest.getFilter(); + + String baseId = firstNonBlankWeFishFilter(filter, "baseId", "base_id"); + String rstcd = getFirstWeFishFilterText(filter, "stcd"); + String rvcd = firstNonBlankWeFishFilter(filter, "rvcd", "hbrvcd"); + String yr = getFirstWeFishFilterText(filter, "yr"); + String ty = getFirstWeFishFilterText(filter, "ty"); + + String sql = buildHbbQgcWeFishDetailSql(baseId, rstcd, rvcd, yr, ty, paramMap); + List> rows = microservicDynamicSQLMapper.pageAllList(page, sql, paramMap); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(buildHbbQgcWeFishDetailResult(rows)); + result.setTotal(page != null ? page.getTotal() : (long) rows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getWeFishDetailList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + Map paramMap = new HashMap<>(); + DataSourceRequest.FilterDescriptor filter = dataSourceRequest == null ? null : dataSourceRequest.getFilter(); + + String baseId = firstNonBlankWeFishFilter(filter, "baseId", "base_id"); + String rstcd = getFirstWeFishFilterText(filter, "stcd"); + String rvcd = firstNonBlankWeFishFilter(filter, "rvcd", "hbrvcd"); + String yr = getFirstWeFishFilterText(filter, "yr"); + String ty = getFirstWeFishFilterText(filter, "ty"); + + String sql = buildWeFishDetailSql(baseId, rstcd, rvcd, yr, ty, paramMap); + List> rows = microservicDynamicSQLMapper.pageAllList(page, sql, paramMap); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(buildWeFishDetailResult(rows)); + result.setTotal(page != null ? page.getTotal() : (long) rows.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getWeFishStatTabList(DataSourceRequest dataSourceRequest) { + Map paramMap = new HashMap<>(); + DataSourceRequest.FilterDescriptor filter = dataSourceRequest == null ? null : dataSourceRequest.getFilter(); + + String baseId = firstNonBlankWeFishFilter(filter, "baseId", "base_id"); + String rstcd = getFirstWeFishFilterText(filter, "stcd"); + String rvcd = firstNonBlankWeFishFilter(filter, "rvcd", "hbrvcd"); + String yr = getFirstWeFishFilterText(filter, "yr"); + + String sql = buildWeFishStatTabSql(baseId, rstcd, rvcd, yr, paramMap); + List list = microservicDynamicSQLMapper.getAllListWithResultType( + sql, + paramMap, + WeFishStatTabVo.class + ); + if (CollUtil.isNotEmpty(list)) { + for (WeFishStatTabVo item : list) { + item.setTyName(resolveTyName(toWeFishIntegerValue(item.getTy()))); + } + } + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(list == null ? 0L : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getQgcWeFishStatList(DataSourceRequest dataSourceRequest) { + Map paramMap = new HashMap<>(); + DataSourceRequest.FilterDescriptor filter = dataSourceRequest == null ? null : dataSourceRequest.getFilter(); + + String baseId = getFirstWeFishFilterText(filter, "baseId"); + String hbrvcd = getFirstWeFishFilterText(filter, "hbrvcd"); + String yr = getFirstWeFishFilterText(filter, "yr"); + List rstcdList = getWeFishFilterTexts(filter, "rstcd"); + + String sql = buildWeFishStatQgcSql(baseId, hbrvcd, yr, rstcdList, paramMap); + List> rows = microservicDynamicSQLMapper.getAllList(sql, paramMap); + + LinkedHashMap resultMap = new LinkedHashMap<>(); + for (Map row : rows) { + String stcd = safeWeFishString(firstPresentWeFishValue(row, "STCD", "stcd")); + if (StrUtil.isBlank(stcd)) { + continue; + } + WeFishStatQgcVo vo = resultMap.computeIfAbsent(stcd, key -> { + WeFishStatQgcVo item = new WeFishStatQgcVo(); + item.setStcd(key); + item.setStnm(safeWeFishString(firstPresentWeFishValue(row, "STNM", "stnm"))); + item.setSort(toWeFishIntegerValue(firstPresentWeFishValue(row, "SORT", "sort"))); + item.setTotal(0L); + item.setDetail(new LinkedHashMap<>()); + return item; + }); + Long num = toWeFishLongValue(firstPresentWeFishValue(row, "NUM", "num")); + if (num == null) { + num = 0L; + } + String ty = safeWeFishString(firstPresentWeFishValue(row, "TY", "ty")); + if (StrUtil.isNotBlank(ty)) { + vo.getDetail().put(ty, num); + } + vo.setTotal((vo.getTotal() == null ? 0L : vo.getTotal()) + num); + } + + DataSourceResult result = new DataSourceResult<>(); + result.setData(new ArrayList<>(resultMap.values())); + result.setTotal((long) resultMap.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getQgcFishListStat(DataSourceRequest dataSourceRequest) { + Map paramMap = new HashMap<>(); + String filterSql = buildWeFishListStatFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT r.yr AS yr, r.id AS id, r.name AS name, r.hbrvcd AS hbrvcd, r.hbrvcdName AS hbrvcdName, ") + .append("SUM(NVL(r.fcnt, 0)) AS fcnt ") + .append("FROM (") + .append(buildWeFishListStatQgcDetailSql()) + .append(") r WHERE 1 = 1 "); + if (StrUtil.isNotBlank(filterSql)) { + sql.append("AND ").append(filterSql).append(" "); + } + sql.append("GROUP BY r.yr, r.id, r.name, r.hbrvcd, r.hbrvcdName ") + .append("ORDER BY r.yr ASC"); + + List> rows = microservicDynamicSQLMapper.getAllList(sql.toString(), paramMap); + List list = new ArrayList<>(); + for (Map row : rows) { + WeFishListStatQgcVo vo = buildWeFishListStatQgcVo(row); + if (vo != null) { + list.add(vo); + } + } + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal((long) list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getQgcWeFishPoint(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String stcd = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "stcd"); + String baseId = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "baseId"); + String startTime = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "startTime"); + String endTime = resolveWeFishStringFilterValue(dataSourceRequest, loadOptions, "endTime"); + List fishList = getWeFishFilterTexts(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), "fishList"); + + Map paramMap = new HashMap<>(); + String sql = buildWeFishPointQgcSql(stcd, baseId, startTime, endTime, fishList, paramMap); + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List> rows = microservicDynamicSQLMapper.pageAllList(page, sql, paramMap); + + Map fishNameMap = loadWeFishNameMap(); + List list = new ArrayList<>(); + for (Map row : rows) { + WeFishPointQgcVo vo = buildWeFishPointQgcVo(row, fishNameMap); + if (vo != null) { + list.add(vo); + } + } + applyWeFishPointMapDistance(list); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getTeSpecialAnimalList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + Map paramMap = new HashMap<>(); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildTeSpecialAnimalSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildTeSpecialAnimalDetailSql()) + .append(") t WHERE 1 = 1 "); + + String filterSql = buildTeSpecialAnimalFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append("AND ").append(filterSql).append(" "); + } + sql.append(buildTeSpecialAnimalOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + + Page page = loadOptions == null ? null + : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + WeTeSpecialAnimalVo.class + ); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private String buildWeFishQgcGroupSql(String baseSql, GroupingInfo[] groupInfos) { + if (groupInfos == null || groupInfos.length == 0) { + return baseSql; + } + List groupFields = new ArrayList<>(); + List selectItems = new ArrayList<>(); + List orderByItems = new ArrayList<>(); + for (GroupingInfo item : groupInfos) { + if (item == null || StrUtil.isBlank(item.getSelector())) { + continue; + } + String selector = item.getSelector(); + String groupColumn = mapWeFishQgcGroupColumn(selector); + if (StrUtil.isBlank(groupColumn)) { + continue; + } + groupFields.add(groupColumn); + selectItems.add(groupColumn + " AS " + selector.toUpperCase()); + boolean hasCountAlias = false; + if (CollUtil.isNotEmpty(item.getSummaryInfos())) { + for (com.yfd.platform.common.SummaryInfo summaryInfo : item.getSummaryInfos()) { + if (summaryInfo == null || StrUtil.isBlank(summaryInfo.getSelector()) || StrUtil.isBlank(summaryInfo.getSummaryType())) { + continue; + } + String summaryColumn = mapWeFishQgcGroupColumn(summaryInfo.getSelector()); + if (StrUtil.isBlank(summaryColumn)) { + continue; + } + String summaryType = summaryInfo.getSummaryType().toUpperCase(); + String summarySelector = summaryInfo.getSelector().toUpperCase(); + switch (summaryInfo.getSummaryType().toLowerCase()) { + case "count" -> { + selectItems.add("COUNT(" + summaryColumn + ") AS " + summaryType + "_" + summarySelector); + if (selector.equalsIgnoreCase(summaryInfo.getSelector())) { + hasCountAlias = true; + } + } + case "sum" -> selectItems.add("SUM(" + summaryColumn + ") AS " + summaryType + "_" + summarySelector); + case "avg", "average" -> selectItems.add("AVG(" + summaryColumn + ") AS AVG_" + summarySelector); + case "min" -> selectItems.add("MIN(" + summaryColumn + ") AS " + summaryType + "_" + summarySelector); + case "max" -> selectItems.add("MAX(" + summaryColumn + ") AS " + summaryType + "_" + summarySelector); + default -> { + } + } + } + } + if (!hasCountAlias) { + selectItems.add("COUNT(*) AS COUNT_" + selector.toUpperCase()); + } + String dir = Boolean.TRUE.equals(item.getDesc()) ? "DESC" : "ASC"; + orderByItems.add(groupColumn + " " + dir); + } + if (groupFields.isEmpty()) { + return baseSql; + } + StringBuilder sql = new StringBuilder("SELECT "); + sql.append(String.join(", ", selectItems)) + .append(" FROM (") + .append(baseSql) + .append(") T GROUP BY ") + .append(String.join(", ", groupFields)); + if (!orderByItems.isEmpty()) { + sql.append(" ORDER BY ").append(String.join(", ", orderByItems)); + } + return sql.toString(); + } + + private String buildWeFishYearSql(String baseId, + String hbrvcd, + String yr, + List rstcdList, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT t.HBRVCD AS hbrvcd, t.YR AS yr ") + .append("FROM (") + .append("SELECT section.HBRVCD, section.RSTCD, section.BASE_ID, TO_CHAR(we.TM, 'yyyy') AS yr ") + .append("FROM SD_WE_B_H section ") + .append("INNER JOIN SD_WE_R we ON section.STCD = we.STCD ") + .append(" AND NVL(we.IS_DELETED, 0) = 0 ") + .append(" AND NVL(we.STATUS, 1) = 1 ") + .append("INNER JOIN SD_WEFISH_R fish ON we.ID = fish.WER_ID ") + .append(" AND NVL(fish.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN V_SD_FISHDICTORY_B dict ON fish.FTP = dict.FISH_ID ") + .append(" AND (section.HBRVCD = dict.RVCD OR dict.RVCD = 'ZY') ") + .append("WHERE NVL(section.USFL, 0) = 1 ") + .append("AND CASE ") + .append("WHEN dict.SPEC_ORIGIN = 2 THEN 1 ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND NVL(dict.PTYPE, -1) <> 6 THEN 2 ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND dict.PTYPE = 6 THEN 3 ") + .append("END IS NOT NULL "); + + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("weYearBaseId", baseId); + sql.append("AND section.BASE_ID = #{map.weYearBaseId} "); + } + if (StrUtil.isNotBlank(hbrvcd)) { + paramMap.put("weYearHbrvcd", hbrvcd); + sql.append("AND section.HBRVCD = #{map.weYearHbrvcd} "); + } + if (StrUtil.isNotBlank(yr)) { + paramMap.put("weYearYr", yr); + sql.append("AND TO_CHAR(we.TM, 'yyyy') = #{map.weYearYr} "); + } + if (CollUtil.isNotEmpty(rstcdList)) { + List placeholders = new ArrayList<>(); + int index = 0; + for (String rstcd : rstcdList) { + if (StrUtil.isBlank(rstcd)) { + continue; + } + String key = "weYearRstcd" + index++; + paramMap.put(key, rstcd); + placeholders.add("#{map." + key + "}"); + } + if (CollUtil.isNotEmpty(placeholders)) { + sql.append("AND section.RSTCD IN (").append(String.join(", ", placeholders)).append(") "); + } + } + + sql.append("GROUP BY section.BASE_ID, section.HBRVCD, section.RSTCD, TO_CHAR(we.TM, 'yyyy')") + .append(") t ") + .append("INNER JOIN (") + .append("SELECT det.STCD, det.SORT, cfg.RVCD ") + .append("FROM MS_ALONG_B cfg ") + .append("INNER JOIN MS_ALONGDET_B det ON cfg.ID = det.ALONG_ID ") + .append("WHERE det.STTP = 'ENG' ") + .append(" AND cfg.CODE = 'common' ") + .append(" AND NVL(det.IS_DELETED, 0) = 0 ") + .append(" AND NVL(cfg.IS_DELETED, 0) = 0") + .append(") t2 ON t.RSTCD = t2.STCD ") + .append("GROUP BY t.BASE_ID, t.HBRVCD, t.YR ") + .append("ORDER BY t.BASE_ID ASC NULLS LAST, t.HBRVCD ASC NULLS LAST, t.YR DESC"); + return sql.toString(); + } + + private String buildWeFishStatQgcSql(String baseId, + String hbrvcd, + String yr, + List rstcdList, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT t.STCD AS stcd, t.STNM AS stnm, t.NUM AS num, t.TY AS ty, t2.SORT AS sort ") + .append("FROM (") + .append("SELECT section.RSTCD AS STCD, ") + .append("eng.ENNM AS STNM, ") + .append("COUNT(DISTINCT fish.FTP) AS NUM, ") + .append("CASE ") + .append("WHEN dict.SPEC_ORIGIN = 2 THEN '1' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND NVL(dict.PTYPE, -1) <> 6 THEN '2' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND dict.PTYPE = 6 THEN '3' ") + .append("END AS TY ") + .append("FROM SD_WE_B_H section ") + .append("INNER JOIN SD_WE_R we ON section.STCD = we.STCD ") + .append(" AND NVL(we.IS_DELETED, 0) = 0 ") +// .append(" AND NVL(we.STATUS, 1) = 1 ") + .append("INNER JOIN SD_WEFISH_R fish ON we.ID = fish.WER_ID ") + .append(" AND NVL(fish.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = section.RSTCD ") + .append(" AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN V_SD_FISHDICTORY_B dict ON fish.FTP = dict.FISH_ID ") + .append(" AND (section.HBRVCD = dict.RVCD OR dict.RVCD = 'ZY') ") + .append("WHERE 1 = 1 "); +// .append("WHERE NVL(section.USFL, 0) = 1 "); + + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("weFishStatBaseId", baseId); + sql.append("AND section.BASE_ID = #{map.weFishStatBaseId} "); + } + if (StrUtil.isNotBlank(hbrvcd)) { + paramMap.put("weFishStatHbrvcd", hbrvcd); + sql.append("AND section.HBRVCD = #{map.weFishStatHbrvcd} "); + } + if (StrUtil.isNotBlank(yr)) { + paramMap.put("weFishStatYr", yr); + sql.append("AND TO_CHAR(we.TM, 'yyyy') = #{map.weFishStatYr} "); + } + if (CollUtil.isNotEmpty(rstcdList)) { + List placeholders = new ArrayList<>(); + int index = 0; + for (String rstcd : rstcdList) { + if (StrUtil.isBlank(rstcd)) { + continue; + } + String key = "weFishStatRstcd" + index++; + paramMap.put(key, rstcd); + placeholders.add("#{map." + key + "}"); + } + if (CollUtil.isNotEmpty(placeholders)) { + sql.append("AND section.RSTCD IN (").append(String.join(", ", placeholders)).append(") "); + } + } + + sql.append("AND CASE ") + .append("WHEN dict.SPEC_ORIGIN = 2 THEN 1 ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND NVL(dict.PTYPE, -1) <> 6 THEN 2 ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND dict.PTYPE = 6 THEN 3 ") + .append("END IS NOT NULL ") + .append("GROUP BY section.RSTCD, eng.ENNM, CASE ") + .append("WHEN dict.SPEC_ORIGIN = 2 THEN '1' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND NVL(dict.PTYPE, -1) <> 6 THEN '2' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND dict.PTYPE = 6 THEN '3' ") + .append("END") + .append(") t ") + .append("INNER JOIN (") + .append("SELECT det.STCD, det.SORT, cfg.RVCD ") + .append("FROM MS_ALONG_B cfg ") + .append("INNER JOIN MS_ALONGDET_B det ON cfg.ID = det.ALONG_ID ") + .append("WHERE det.STTP = 'ENG' ") + .append(" AND cfg.CODE = 'common' ") + .append(" AND NVL(det.IS_DELETED, 0) = 0 ") + .append(" AND NVL(cfg.IS_DELETED, 0) = 0") + .append(") t2 ON t.STCD = t2.STCD ") + .append("ORDER BY t2.SORT ASC NULLS LAST, t.STCD ASC, t.TY ASC"); + return sql.toString(); + } + + private String buildWeFishStatSql(String baseId, + String hbrvcd, + String yr, + List rstcdList, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT t.STCD AS stcd, t.STNM AS stnm, t.NUM AS num, t.TY AS ty, t2.SORT AS sort ") + .append("FROM (") + .append("SELECT section.RSTCD AS STCD, ") + .append("eng.ENNM AS STNM, ") + .append("COUNT(DISTINCT fish.FTP) AS NUM, ") + .append("CASE ") + .append("WHEN dict.SPEC_ORIGIN = 2 THEN '1' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND NVL(dict.PTYPE, -1) <> 6 THEN '2' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND dict.PTYPE = 6 THEN '3' ") + .append("END AS TY, ") + .append("TO_CHAR(we.TM, 'yyyy') AS YR ") + .append("FROM SD_WE_B_H section ") + .append("INNER JOIN SD_WE_R we ON section.STCD = we.STCD ") + .append(" AND NVL(we.IS_DELETED, 0) = 0 ") + .append(" AND NVL(we.STATUS, 1) = 1 ") + .append("INNER JOIN SD_WEFISH_R fish ON we.ID = fish.WER_ID ") + .append(" AND NVL(fish.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = section.RSTCD ") + .append(" AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_FISHDICTORY_B dict ON fish.FTP = dict.ID ") + .append(" AND NVL(dict.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(section.USFL, 0) = 1 "); + + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("weFishStatBaseId", baseId); + sql.append("AND section.BASE_ID = #{map.weFishStatBaseId} "); + } + if (StrUtil.isNotBlank(hbrvcd)) { + paramMap.put("weFishStatHbrvcd", hbrvcd); + sql.append("AND section.HBRVCD = #{map.weFishStatHbrvcd} "); + } + sql.append("AND section.RSTCD IS NOT NULL ") + .append("AND dict.SPEC_ORIGIN IS NOT NULL ") + .append("GROUP BY section.RSTCD, eng.ENNM, ") + .append("CASE ") + .append("WHEN dict.SPEC_ORIGIN = 2 THEN '1' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND NVL(dict.PTYPE, -1) <> 6 THEN '2' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND dict.PTYPE = 6 THEN '3' ") + .append("END, ") + .append("TO_CHAR(we.TM, 'yyyy') ") + .append(") t ") + .append("INNER JOIN (") + .append("SELECT det.STCD, det.SORT ") + .append("FROM MS_ALONG_B cfg ") + .append("INNER JOIN MS_ALONGDET_B det ON cfg.ID = det.ALONG_ID ") + .append("WHERE det.STTP = 'ENG' ") + .append(" AND cfg.CODE = 'common' ") + .append(" AND NVL(det.IS_DELETED, 0) = 0 ") + .append(" AND NVL(cfg.IS_DELETED, 0) = 0") + .append(") t2 ON t.STCD = t2.STCD ") + .append("WHERE t.TY IS NOT NULL "); + + if (StrUtil.isNotBlank(yr)) { + paramMap.put("weFishStatYr", yr); + sql.append("AND t.YR = #{map.weFishStatYr} "); + } + if (CollUtil.isNotEmpty(rstcdList)) { + List placeholders = new ArrayList<>(); + int index = 0; + for (String rstcd : rstcdList) { + if (StrUtil.isBlank(rstcd)) { + continue; + } + String key = "weFishStatRstcd" + index++; + paramMap.put(key, rstcd); + placeholders.add("#{map." + key + "}"); + } + if (CollUtil.isNotEmpty(placeholders)) { + sql.append("AND t.STCD IN (").append(String.join(", ", placeholders)).append(") "); + } + } + sql.append("ORDER BY t2.SORT ASC NULLS LAST"); + return sql.toString(); + } + + private DataSourceResult buildWeFishStatResult(List> rows) { + LinkedHashMap resultMap = new LinkedHashMap<>(); + for (Map row : rows) { + String stcd = safeWeFishString(firstPresentWeFishValue(row, "STCD", "stcd")); + if (StrUtil.isBlank(stcd)) { + continue; + } + WeFishStatQgcVo vo = resultMap.computeIfAbsent(stcd, key -> { + WeFishStatQgcVo item = new WeFishStatQgcVo(); + item.setStcd(key); + item.setStnm(safeWeFishString(firstPresentWeFishValue(row, "STNM", "stnm"))); + item.setSort(toWeFishIntegerValue(firstPresentWeFishValue(row, "SORT", "sort"))); + item.setTotal(0L); + item.setDetail(new LinkedHashMap<>()); + return item; + }); + Long num = toWeFishLongValue(firstPresentWeFishValue(row, "NUM", "num")); + if (num == null) { + num = 0L; + } + String ty = safeWeFishString(firstPresentWeFishValue(row, "TY", "ty")); + if (StrUtil.isNotBlank(ty)) { + vo.getDetail().put(ty, num); + } + vo.setTotal((vo.getTotal() == null ? 0L : vo.getTotal()) + num); + } + + DataSourceResult result = new DataSourceResult<>(); + result.setData(new ArrayList<>(resultMap.values())); + result.setTotal((long) resultMap.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private String buildQgcWeFishDetailSql(String baseId, + String rstcd, + String rvcd, + String yr, + String ty, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("section.RSTCD AS rstcd, ") + .append("eng.ENNM AS rstcdName, ") + .append("TO_CHAR(WM_CONCAT(DISTINCT section.STCD)) AS stcd, ") + .append("TO_CHAR(WM_CONCAT(DISTINCT section.STNM)) AS stnm, ") + .append("TO_CHAR(WM_CONCAT(DISTINCT dict.ZY_FISH_ID)) AS id ") + .append("FROM SD_WE_B_H section ") + .append("INNER JOIN SD_WE_R we ON section.STCD = we.STCD ") + .append(" AND NVL(we.IS_DELETED, 0) = 0 ") + .append(" AND NVL(we.STATUS, 1) = 1 ") + .append("INNER JOIN SD_WEFISH_R fish ON we.ID = fish.WER_ID ") + .append(" AND NVL(fish.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON section.RSTCD = eng.STCD ") + .append(" AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN V_SD_FISHDICTORY_B dict ON fish.FTP = dict.FISH_ID ") + .append(" AND (section.HBRVCD = dict.RVCD OR dict.RVCD = 'ZY') ") + .append("WHERE NVL(section.USFL, 0) = 1 ") + .append("AND section.RSTCD IS NOT NULL ") + .append("AND dict.ZY_FISH_ID IS NOT NULL "); + + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("qgcWeFishDetailBaseId", baseId); + sql.append("AND section.BASE_ID = #{map.qgcWeFishDetailBaseId} "); + } + if (StrUtil.isNotBlank(rstcd)) { + paramMap.put("qgcWeFishDetailRstcd", rstcd); + sql.append("AND section.RSTCD = #{map.qgcWeFishDetailRstcd} "); + } + if (StrUtil.isNotBlank(rvcd)) { + paramMap.put("qgcWeFishDetailRvcd", rvcd); + sql.append("AND section.HBRVCD = #{map.qgcWeFishDetailRvcd} "); + } + if (StrUtil.isNotBlank(yr)) { + paramMap.put("qgcWeFishDetailYr", yr); + sql.append("AND TO_CHAR(we.TM, 'yyyy') = #{map.qgcWeFishDetailYr} "); + } + if (StrUtil.isNotBlank(ty)) { + paramMap.put("qgcWeFishDetailTy", ty); + sql.append("AND CASE ") + .append("WHEN dict.SPEC_ORIGIN = 2 THEN '1' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND NVL(dict.PTYPE, -1) <> 6 THEN '2' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND dict.PTYPE = 6 THEN '3' ") + .append("END = #{map.qgcWeFishDetailTy} "); + } + + sql.append("GROUP BY section.RSTCD, eng.ENNM ") + .append("ORDER BY eng.ENNM ASC NULLS LAST"); + return sql.toString(); + } + + private String buildWeFishDetailSql(String baseId, + String rstcd, + String rvcd, + String yr, + String ty, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("section.RSTCD AS rstcd, ") + .append("eng.ENNM AS rstcdName, ") + .append("TO_CHAR(WM_CONCAT(DISTINCT section.STCD)) AS stcd, ") + .append("TO_CHAR(WM_CONCAT(DISTINCT section.STNM)) AS stnm, ") + .append("TO_CHAR(WM_CONCAT(DISTINCT dict.NAME)) AS name ") + .append("FROM SD_WE_B_H section ") + .append("INNER JOIN SD_WE_R we ON section.STCD = we.STCD ") + .append(" AND NVL(we.IS_DELETED, 0) = 0 ") + .append(" AND NVL(we.STATUS, 1) = 1 ") + .append("INNER JOIN SD_WEFISH_R fish ON we.ID = fish.WER_ID ") + .append(" AND NVL(fish.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON section.RSTCD = eng.STCD ") + .append(" AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_FISHDICTORY_B dict ON fish.FTP = dict.ID ") + .append(" AND NVL(dict.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(section.USFL, 0) = 1 ") + .append("AND section.RSTCD IS NOT NULL ") + .append("AND dict.NAME IS NOT NULL "); + + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("weFishDetailBaseId", baseId); + sql.append("AND section.BASE_ID = #{map.weFishDetailBaseId} "); + } + if (StrUtil.isNotBlank(rstcd)) { + paramMap.put("weFishDetailRstcd", rstcd); + sql.append("AND section.RSTCD = #{map.weFishDetailRstcd} "); + } + if (StrUtil.isNotBlank(rvcd)) { + paramMap.put("weFishDetailRvcd", rvcd); + sql.append("AND section.HBRVCD = #{map.weFishDetailRvcd} "); + } + if (StrUtil.isNotBlank(yr)) { + paramMap.put("weFishDetailYr", yr); + sql.append("AND TO_CHAR(we.TM, 'yyyy') = #{map.weFishDetailYr} "); + } + if (StrUtil.isNotBlank(ty)) { + paramMap.put("weFishDetailTy", ty); + sql.append("AND CASE ") + .append("WHEN dict.SPEC_ORIGIN = 2 THEN '1' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND NVL(dict.PTYPE, -1) <> 6 THEN '2' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND dict.PTYPE = 6 THEN '3' ") + .append("END = #{map.weFishDetailTy} "); + } + + sql.append("GROUP BY section.RSTCD, eng.ENNM ") + .append("ORDER BY eng.ENNM ASC NULLS LAST"); + return sql.toString(); + } + + private String buildHbbQgcWeFishDetailSql(String baseId, + String rstcd, + String rvcd, + String yr, + String ty, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("section.RSTCD AS rstcd, ") + .append("eng.ENNM AS rstcdName, ") + .append("section.STCD AS stcd, ") + .append("section.STNM AS stnm, ") + .append("dict.ZY_FISH_ID AS id ") + .append("FROM SD_WE_B_H section ") + .append("INNER JOIN SD_WE_R we ON section.STCD = we.STCD ") + .append(" AND NVL(we.IS_DELETED, 0) = 0 ") + .append(" AND NVL(we.STATUS, 1) = 1 ") + .append("INNER JOIN SD_WEFISH_R fish ON we.ID = fish.WER_ID ") + .append(" AND NVL(fish.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON section.RSTCD = eng.STCD ") + .append(" AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN V_SD_FISHDICTORY_B dict ON fish.FTP = dict.FISH_ID ") + .append(" AND (section.HBRVCD = dict.RVCD OR dict.RVCD = 'ZY') ") + .append("WHERE NVL(section.USFL, 0) = 1 ") + .append("AND section.RSTCD IS NOT NULL ") + .append("AND dict.ZY_FISH_ID IS NOT NULL "); + + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("hbbQgcWeFishDetailBaseId", baseId); + sql.append("AND section.BASE_ID = #{map.hbbQgcWeFishDetailBaseId} "); + } + if (StrUtil.isNotBlank(rstcd)) { + paramMap.put("hbbQgcWeFishDetailRstcd", rstcd); + sql.append("AND section.RSTCD = #{map.hbbQgcWeFishDetailRstcd} "); + } + if (StrUtil.isNotBlank(rvcd)) { + paramMap.put("hbbQgcWeFishDetailRvcd", rvcd); + sql.append("AND section.HBRVCD = #{map.hbbQgcWeFishDetailRvcd} "); + } + if (StrUtil.isNotBlank(yr)) { + paramMap.put("hbbQgcWeFishDetailYr", yr); + sql.append("AND TO_CHAR(we.TM, 'yyyy') = #{map.hbbQgcWeFishDetailYr} "); + } + if (StrUtil.isNotBlank(ty)) { + paramMap.put("hbbQgcWeFishDetailTy", ty); + sql.append("AND CASE ") + .append("WHEN dict.SPEC_ORIGIN = 2 THEN '1' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND NVL(dict.PTYPE, -1) <> 6 THEN '2' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND dict.PTYPE = 6 THEN '3' ") + .append("END = #{map.hbbQgcWeFishDetailTy} "); + } + + sql.append("GROUP BY section.RSTCD, eng.ENNM, section.STCD, section.STNM,dict.ZY_FISH_ID ") + .append("ORDER BY eng.ENNM ASC NULLS LAST, section.STNM ASC NULLS LAST"); + return sql.toString(); + } + + private String buildWeFishStatTabSql(String baseId, + String rstcd, + String rvcd, + String yr, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT COUNT(DISTINCT fish.FTP) AS num, ") + .append("CASE ") + .append("WHEN dict.SPEC_ORIGIN = 2 THEN '1' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND NVL(dict.PTYPE, -1) <> 6 THEN '2' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND dict.PTYPE = 6 THEN '3' ") + .append("END AS ty ") + .append("FROM SD_WE_B_H section ") + .append("INNER JOIN SD_WE_R we ON section.STCD = we.STCD ") + .append(" AND NVL(we.IS_DELETED, 0) = 0 ") + .append(" AND NVL(we.STATUS, 1) = 1 ") + .append("INNER JOIN SD_WEFISH_R fish ON we.ID = fish.WER_ID ") + .append(" AND NVL(fish.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_FISHDICTORY_B dict ON fish.FTP = dict.ID ") + .append(" AND NVL(dict.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(section.USFL, 0) = 1 "); + + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("weFishStatTabBaseId", baseId); + sql.append("AND section.BASE_ID = #{map.weFishStatTabBaseId} "); + } + if (StrUtil.isNotBlank(rvcd)) { + paramMap.put("weFishStatTabRvcd", rvcd); + sql.append("AND section.HBRVCD = #{map.weFishStatTabRvcd} "); + } + if (StrUtil.isNotBlank(rstcd)) { + paramMap.put("weFishStatTabRstcd", rstcd); + sql.append("AND section.RSTCD = #{map.weFishStatTabRstcd} "); + } + if (StrUtil.isNotBlank(yr)) { + paramMap.put("weFishStatTabYr", yr); + sql.append("AND TO_CHAR(we.TM, 'yyyy') = #{map.weFishStatTabYr} "); + } + + sql.append("AND CASE ") + .append("WHEN dict.SPEC_ORIGIN = 2 THEN '1' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND NVL(dict.PTYPE, -1) <> 6 THEN '2' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND dict.PTYPE = 6 THEN '3' ") + .append("END IS NOT NULL ") + .append("GROUP BY CASE ") + .append("WHEN dict.SPEC_ORIGIN = 2 THEN '1' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND NVL(dict.PTYPE, -1) <> 6 THEN '2' ") + .append("WHEN dict.SPEC_ORIGIN = 1 AND dict.PTYPE = 6 THEN '3' ") + .append("END ") + .append("ORDER BY ty ASC"); + return sql.toString(); + } + + private List buildWeFishDetailResult(List> rows) { + List result = new ArrayList<>(); + if (CollUtil.isEmpty(rows)) { + return result; + } + for (Map row : rows) { + String stcd = safeWeFishString(firstPresentWeFishValue(row, "STCD", "stcd")); + String stnm = safeWeFishString(firstPresentWeFishValue(row, "STNM", "stnm")); + String fishNames = safeWeFishString(firstPresentWeFishValue(row, "NAME", "name")); + + WeFishDetailVo vo = new WeFishDetailVo() + .setRsctd(safeWeFishString(firstPresentWeFishValue(row, "RSTCD", "rstcd"))) + .setRsctdName(safeWeFishString(firstPresentWeFishValue(row, "RSTCDNAME", "rstcdName"))) + .setFishList(splitWeFishText(fishNames)) + .setStcdList(buildWeFishStationItems(stcd, stnm)); + result.add(vo); + } + return result; + } + + private List buildQgcWeFishDetailResult(List> rows) { + List result = new ArrayList<>(); + if (CollUtil.isEmpty(rows)) { + return result; + } + Map fishNameMap = loadWeFishNameMap(); + for (Map row : rows) { + String stcd = safeWeFishString(firstPresentWeFishValue(row, "STCD", "stcd")); + String stnm = safeWeFishString(firstPresentWeFishValue(row, "STNM", "stnm")); + String fishIds = safeWeFishString(firstPresentWeFishValue(row, "ID", "id")); + + WeFishDetailVo vo = new WeFishDetailVo() + .setRsctd(safeWeFishString(firstPresentWeFishValue(row, "RSTCD", "rstcd"))) + .setRsctdName(safeWeFishString(firstPresentWeFishValue(row, "RSTCDNAME", "rstcdName"))) + .setFishList(resolveWeFishNameList(fishIds, fishNameMap)) + .setStcdList(buildWeFishStationItems(stcd, stnm)); + result.add(vo); + } + return result; + } + + private List buildHbbQgcWeFishDetailResult(List> rows) { + List result = new ArrayList<>(); + if (CollUtil.isEmpty(rows)) { + return result; + } + Map fishNameMap = loadWeFishNameMap(); + for (Map row : rows) { + String fishIds = safeWeFishString(firstPresentWeFishValue(row, "ID", "id")); + result.add(new WeFishHbbQgcDetailVo() + .setRstcd(safeWeFishString(firstPresentWeFishValue(row, "RSTCD", "rstcd"))) + .setRstcdName(safeWeFishString(firstPresentWeFishValue(row, "RSTCDNAME", "rstcdName"))) + .setStcd(safeWeFishString(firstPresentWeFishValue(row, "STCD", "stcd"))) + .setStnm(safeWeFishString(firstPresentWeFishValue(row, "STNM", "stnm"))) + .setId(fishIds) + .setName(resolveWeFishNames(fishIds, fishNameMap))); + } + return result; + } + + private List buildWeFishStationItems(String stcdText, String stnmText) { + List result = new ArrayList<>(); + if (StrUtil.isBlank(stcdText) || StrUtil.isBlank(stnmText)) { + return result; + } + List stcdList = splitWeFishText(stcdText); + List stnmList = splitWeFishText(stnmText); + int size = Math.min(stcdList.size(), stnmList.size()); + for (int i = 0; i < size; i++) { + result.add(new WeFishDetailVo.StationItem() + .setStcd(stcdList.get(i)) + .setStnm(stnmList.get(i))); + } + return result; + } + + private List splitWeFishText(String text) { + if (StrUtil.isBlank(text)) { + return new ArrayList<>(); + } + String[] parts = text.split(","); + List result = new ArrayList<>(); + Set seen = new HashSet<>(); + for (String part : parts) { + String value = StrUtil.trim(part); + if (StrUtil.isBlank(value) || !seen.add(value)) { + continue; + } + result.add(value); + } + return result; + } + + private List resolveWeFishNameList(String idsText, Map fishNameMap) { + String names = resolveWeFishNames(idsText, fishNameMap); + return splitWeFishText(names); + } + + private List buildWeCompareBarColumns(String dcpc, String dcpc2) { + List columns = new ArrayList<>(); + columns.add(new WeCompareBarHeadColumnVo("ftp", "鱼种类", true, "ftp", false, new ArrayList<>())); + columns.add(new WeCompareBarHeadColumnVo("genus", "科属", true, "genus", false, new ArrayList<>())); + columns.add(new WeCompareBarHeadColumnVo("dcpc", StrUtil.isBlank(dcpc) ? "调查批次" : dcpc, true, "dcpc", false, new ArrayList<>())); + columns.add(new WeCompareBarHeadColumnVo("dcpc2", StrUtil.isBlank(dcpc2) ? "对比批次" : dcpc2, true, "dcpc2", false, new ArrayList<>())); + columns.add(new WeCompareBarHeadColumnVo("fcnt", "鱼类数量(尾)", true, "fnct", false, new ArrayList<>())); + columns.add(new WeCompareBarHeadColumnVo("fcnt2", "对比鱼类数量(尾)", true, "fcnt2", false, new ArrayList<>())); + return columns; + } + + private List buildWeFishPageColumns(String startYear, String endYear) { + List columns = new ArrayList<>(); + columns.add(new WeCompareBarHeadColumnVo("genus", "科属", true, "genus", true, new ArrayList<>())); + columns.add(new WeCompareBarHeadColumnVo("ftp", "鱼类名称", true, "ftp", false, new ArrayList<>())); + columns.add(new WeCompareBarHeadColumnVo("startFtpCnt", startYear + "鱼类总量(尾)", true, "startFtpCnt", false, new ArrayList<>())); + columns.add(new WeCompareBarHeadColumnVo("startYear", startYear + "占比(%)", true, "startYear", false, new ArrayList<>())); + columns.add(new WeCompareBarHeadColumnVo("endFtpCnt", endYear + "鱼类总量(尾)", true, "endFtpCnt", false, new ArrayList<>())); + columns.add(new WeCompareBarHeadColumnVo("endYear", endYear + "占比(%)", true, "endYear", false, new ArrayList<>())); + return columns; + } + + private String firstNonBlankWeFishFilter(DataSourceRequest.FilterDescriptor filter, String... fields) { + if (fields == null) { + return null; + } + for (String field : fields) { + String value = getFirstWeFishFilterText(filter, field); + if (StrUtil.isNotBlank(value)) { + return value; + } + } + return null; + } + + private String buildWeFishListStatQgcDetailSql() { + return "SELECT " + + "dict.FISH_ID AS id, " + + "dict.NAME AS name, " + + "dict.CODE AS code, " + + "eng.RVCD AS rvcd, " + + "eng.RVCD_NAME AS rvcdName, " + + "eng.HBRVCD AS hbrvcd, " + + "eng.HBRVCD_NAME AS hbrvcdName, " + + "section.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "eng.BASE_ID AS baseId, " + + "eng.BASE_NAME AS baseName, " + + "we.TM AS tm, " + + "TO_CHAR(we.TM, 'yyyy') AS yr, " + + "fish.FCNT AS fcnt " + + "FROM SD_WE_R we " + + "INNER JOIN SD_WEFISH_R fish ON we.ID = fish.WER_ID " + + " AND NVL(fish.IS_DELETED, 0) = 0 " + + "INNER JOIN SD_WE_B_H section ON we.STCD = section.STCD " + + " AND NVL(section.USFL, 0) = 1 " + + "INNER JOIN SD_ENGINFO_B_H eng ON eng.STCD = section.RSTCD " + + " AND NVL(eng.IS_DELETED, 0) = 0 " + + "INNER JOIN V_SD_FISHDICTORY_B dict ON dict.FISH_ID = fish.FTP " + + " AND (eng.HBRVCD = dict.RVCD OR dict.RVCD = 'ZY') " + + "WHERE NVL(we.IS_DELETED, 0) = 0 " + + "AND NVL(we.STATUS, 1) = 1 "; + } + + private String buildWeFishPointQgcSql(String stcd, + String baseId, + String startTime, + String endTime, + List fishList, + Map paramMap) { + Date start = null; + Date end = null; + if (StrUtil.isNotBlank(startTime) && StrUtil.isNotBlank(endTime)) { + start = parseDateTimeSafely(startTime); + end = parseDateTimeSafely(endTime); + } + StringBuilder sql = new StringBuilder(); + sql.append("SELECT agg.ftp AS ftp, section.STCD AS stcd, section.RSTCD AS rstcds, ") + .append("section.STNM AS stnm, eng.ENNM AS ennm, ") + .append("section.LGTD AS lgtd, section.LTTD AS lttd, ") + .append("'ylfb' AS sttp, 'ylfb' AS sttpMap, ") + .append("section.RVCD AS rvcd, section.ADDVCD AS addvcd, section.BASE_ID AS baseId, ") + .append("'WE' AS sttpCode, 'ylfb' AS anchoPointState, '鱼类分布' AS titleName, ") + .append("eng.ELEV AS dtmel ") + .append("FROM (") + .append("SELECT LISTAGG(TO_CHAR(t.ID), ',') WITHIN GROUP (ORDER BY t.ID) AS ftp, t.stcd ") + .append("FROM (") + .append("SELECT dict.ZY_FISH_ID AS ID, we.STCD AS stcd ") + .append("FROM SD_WE_R we ") + .append("INNER JOIN SD_WE_B_H section ON we.STCD = section.STCD ") + .append(" AND NVL(section.USFL, 0) = 1 ") + .append("INNER JOIN SD_WEFISH_R fish ON we.ID = fish.WER_ID ") + .append(" AND NVL(fish.IS_DELETED, 0) = 0 ") + .append("INNER JOIN V_SD_FISHDICTORY_B dict ON dict.FISH_ID = fish.FTP ") + .append(" AND (section.HBRVCD = dict.RVCD OR dict.RVCD = 'ZY') ") + .append("WHERE NVL(we.IS_DELETED, 0) = 0 ") + .append("AND NVL(we.STATUS, 1) = 1 "); + + if (StrUtil.isNotBlank(stcd)) { + paramMap.put("weFishPointStcd", stcd); + sql.append("AND we.STCD = #{map.weFishPointStcd} "); + } + if (start != null && end != null) { + paramMap.put("weFishPointStartTime", start); + paramMap.put("weFishPointEndTime", end); + sql.append("AND we.TM BETWEEN #{map.weFishPointStartTime} AND #{map.weFishPointEndTime} "); + } + if (CollUtil.isNotEmpty(fishList)) { + List placeholders = new ArrayList<>(); + int index = 0; + for (String fishId : fishList) { + if (StrUtil.isBlank(fishId)) { + continue; + } + String key = "weFishPointFish" + index++; + paramMap.put(key, fishId); + placeholders.add("#{map." + key + "}"); + } + if (CollUtil.isNotEmpty(placeholders)) { + sql.append("AND we.STCD IN (") + .append("SELECT a.STCD ") + .append("FROM SD_WE_R a ") + .append("INNER JOIN SD_WE_B_H section2 ON a.STCD = section2.STCD ") + .append(" AND NVL(section2.USFL, 0) = 1 ") + .append("INNER JOIN SD_WEFISH_R b ON a.ID = b.WER_ID ") + .append(" AND NVL(b.IS_DELETED, 0) = 0 ") + .append("INNER JOIN V_SD_FISHDICTORY_B c ON c.FISH_ID = b.FTP ") + .append(" AND (section2.HBRVCD = c.RVCD OR c.RVCD = 'ZY') ") + .append("WHERE NVL(a.IS_DELETED, 0) = 0 ") + .append("AND NVL(a.STATUS, 1) = 1 "); + if (start != null && end != null) { + sql.append("AND a.TM BETWEEN #{map.weFishPointStartTime} AND #{map.weFishPointEndTime} "); + } + sql.append("AND c.FISH_ID IN (").append(String.join(", ", placeholders)).append(")") + .append(") "); + } + } + + sql.append("GROUP BY we.STCD, dict.ZY_FISH_ID") + .append(") t GROUP BY t.stcd") + .append(") agg ") + .append("INNER JOIN SD_WE_B_H section ON agg.stcd = section.STCD ") + .append(" AND NVL(section.USFL, 0) = 1 ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = section.RSTCD ") + .append(" AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE 1 = 1 "); + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("weFishPointBaseId", baseId); + sql.append("AND section.BASE_ID = #{map.weFishPointBaseId} "); + } + sql.append("ORDER BY section.STCD ASC"); + return sql.toString(); + } + + private String buildTeSpecialAnimalDetailSql() { + return "SELECT DISTINCT " + + "b.ID AS id, " + + "b.NAME AS name, " + + "b.NAME_EN AS nameEn, " + + "b.PROTECTLVL AS protectlvl, " + + "b.PROTECTLVL AS protectlvlName, " + + "b.LOGO AS logo, " + + "b.INTRODUCE AS introduce " + + "FROM MS_SPECANIMALS_B a " + + "INNER JOIN SD_VABASIC_B b ON a.ANIMAL_ID = b.ID " + + "WHERE NVL(a.IS_DELETED, 0) = 0 " + + "AND NVL(b.IS_DELETED, 0) = 0 " + + "AND NVL(b.ENABLE, 1) = 1 "; + } + + private String buildTeSpecialAnimalSelectSql(List selectFields) { + Map columnMap = buildTeSpecialAnimalColumnMap(); + List columns = new ArrayList<>(); + if (CollUtil.isNotEmpty(selectFields)) { + for (String field : selectFields) { + String column = columnMap.get(field); + if (StrUtil.isNotBlank(column)) { + columns.add(column); + } + } + } + if (columns.isEmpty()) { + columns.addAll(columnMap.values()); + } + return String.join(", ", columns); + } + + private Map buildTeSpecialAnimalColumnMap() { + Map columnMap = new LinkedHashMap<>(); + columnMap.put("id", "t.id AS id"); + columnMap.put("name", "t.name AS name"); + columnMap.put("nameEn", "t.nameEn AS nameEn"); + columnMap.put("protectlvl", "t.protectlvl AS protectlvl"); + columnMap.put("protectlvlName", "t.protectlvlName AS protectlvlName"); + columnMap.put("logo", "t.logo AS logo"); + columnMap.put("introduce", "t.introduce AS introduce"); + return columnMap; + } + + private String buildTeSpecialAnimalFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildTeSpecialAnimalLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildTeSpecialAnimalFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildTeSpecialAnimalLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapTeSpecialAnimalColumn(filter == null ? null : filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("isempty".equals(operator)) { + return "(" + column + " IS NULL OR " + column + " = '')"; + } + if ("isnotempty".equals(operator)) { + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + } + if ("in".equals(operator) || "ni".equals(operator)) { + List values = normalizeWeFishQgcValues(filter.getValue()); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object value : values) { + String text = safeWeFishString(value); + if (StrUtil.isBlank(text)) { + continue; + } + String key = "teSpecP" + indexHolder[0]++; + paramMap.put(key, text); + placeholders.add("#{map." + key + "}"); + } + if (placeholders.isEmpty()) { + return ""; + } + return column + ("ni".equals(operator) ? " NOT IN (" : " IN (") + String.join(", ", placeholders) + ")"; + } + String text = safeWeFishString(filter.getValue()); + if (StrUtil.isBlank(text)) { + return ""; + } + String key = "teSpecP" + indexHolder[0]++; + return switch (operator) { + case "eq" -> { + paramMap.put(key, text); + yield column + " = #{map." + key + "}"; + } + case "neq" -> { + paramMap.put(key, text); + yield column + " <> #{map." + key + "}"; + } + case "contains" -> { + paramMap.put(key, "%" + text + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "doesnotcontain" -> { + paramMap.put(key, "%" + text + "%"); + yield column + " NOT LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, text + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + text); + yield column + " LIKE #{map." + key + "}"; + } + default -> ""; + }; + } + + private String mapTeSpecialAnimalColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "id" -> "t.id"; + case "name" -> "t.name"; + case "nameEn" -> "t.nameEn"; + case "protectlvl" -> "t.protectlvl"; + case "protectlvlName" -> "t.protectlvlName"; + case "logo" -> "t.logo"; + case "introduce" -> "t.introduce"; + default -> null; + }; + } + + private String buildTeSpecialAnimalOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return " ORDER BY t.name ASC NULLS LAST, t.id ASC"; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapTeSpecialAnimalColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) || "des".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction + " NULLS LAST"); + } + if (orderByParts.isEmpty()) { + return " ORDER BY t.name ASC NULLS LAST, t.id ASC"; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + private String buildWeWvaYearFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildWeWvaYearLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildWeWvaYearFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildWeWvaYearLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapWeWvaYearColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("isempty".equals(operator)) { + return "(" + column + " IS NULL OR " + column + " = '')"; + } + if ("isnotempty".equals(operator)) { + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + } + if ("in".equals(operator) || "ni".equals(operator)) { + List values = normalizeWeFishQgcValues(filter.getValue()); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object value : values) { + if (value == null || StrUtil.isBlank(String.valueOf(value).trim())) { + continue; + } + String key = "weWvaYearP" + indexHolder[0]++; + paramMap.put(key, String.valueOf(value).trim()); + placeholders.add("#{map." + key + "}"); + } + if (placeholders.isEmpty()) { + return ""; + } + return column + ("ni".equals(operator) ? " NOT IN (" : " IN (") + String.join(", ", placeholders) + ")"; + } + + Object rawValue = filter.getValue(); + if (rawValue == null || StrUtil.isBlank(String.valueOf(rawValue).trim())) { + return ""; + } + String text = String.valueOf(rawValue).trim(); + String key = "weWvaYearP" + indexHolder[0]++; + return switch (operator) { + case "eq" -> { + paramMap.put(key, text); + yield column + " = #{map." + key + "}"; + } + case "neq" -> { + paramMap.put(key, text); + yield column + " <> #{map." + key + "}"; + } + case "gt" -> { + paramMap.put(key, text); + yield column + " > #{map." + key + "}"; + } + case "gte" -> { + paramMap.put(key, text); + yield column + " >= #{map." + key + "}"; + } + case "lt" -> { + paramMap.put(key, text); + yield column + " < #{map." + key + "}"; + } + case "lte" -> { + paramMap.put(key, text); + yield column + " <= #{map." + key + "}"; + } + case "contains" -> { + paramMap.put(key, "%" + text + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "doesnotcontain" -> { + paramMap.put(key, "%" + text + "%"); + yield column + " NOT LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, text + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + text); + yield column + " LIKE #{map." + key + "}"; + } + default -> ""; + }; + } + + private String mapWeWvaYearColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd" -> "a.STCD"; + case "tm" -> "a.TM"; + case "fid" -> "a.FID"; + case "stnm" -> "b.STNM"; + case "sttpCode" -> "b.STTP"; + case "rstcd" -> "b.RSTCD"; + case "baseId" -> "b.BASE_ID"; + case "hbrvcd" -> "b.HBRVCD"; + case "ym" -> "TO_CHAR(a.TM, 'yyyy') || '-' || TO_CHAR(a.TM, 'MM')"; + default -> null; + }; + } + + private String buildWeWvaDefaultInnerFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildWeWvaDefaultLeafCondition(filter, paramMap, indexHolder, true); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildWeWvaDefaultInnerFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildWeWvaDefaultOuterFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildWeWvaDefaultLeafCondition(filter, paramMap, indexHolder, false); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildWeWvaDefaultOuterFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildWeWvaDefaultLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder, + boolean inner) { + String column = inner ? mapWeWvaDefaultInnerColumn(filter.getField()) : mapWeWvaDefaultOuterColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("isempty".equals(operator)) { + return "(" + column + " IS NULL OR " + column + " = '')"; + } + if ("isnotempty".equals(operator)) { + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + } + if ("in".equals(operator) || "ni".equals(operator)) { + List values = normalizeWeWvaValues(filter.getValue()); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object value : values) { + Object normalizedValue = normalizeWeWvaDefaultValue(filter.getField(), value); + if (normalizedValue == null) { + continue; + } + String key = (inner ? "weWvaDefaultInnerP" : "weWvaDefaultOuterP") + indexHolder[0]++; + paramMap.put(key, normalizedValue); + placeholders.add(buildWeWvaDefaultValueExpr(key, "tm".equals(filter.getField()), normalizedValue)); + } + if (placeholders.isEmpty()) { + return ""; + } + return column + ("ni".equals(operator) ? " NOT IN (" : " IN (") + String.join(", ", placeholders) + ")"; + } + + Object normalizedValue = normalizeWeWvaDefaultValue(filter.getField(), filter.getValue()); + if (normalizedValue == null) { + return ""; + } + String key = (inner ? "weWvaDefaultInnerP" : "weWvaDefaultOuterP") + indexHolder[0]++; + paramMap.put(key, normalizedValue); + String valueExpr = buildWeWvaDefaultValueExpr(key, "tm".equals(filter.getField()), normalizedValue); + return switch (operator) { + case "eq" -> column + " = " + valueExpr; + case "neq" -> column + " <> " + valueExpr; + case "gt" -> column + " > " + valueExpr; + case "gte" -> column + " >= " + valueExpr; + case "lt" -> column + " < " + valueExpr; + case "lte" -> column + " <= " + valueExpr; + case "contains" -> { + paramMap.put(key, "%" + String.valueOf(normalizedValue).trim() + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "doesnotcontain" -> { + paramMap.put(key, "%" + String.valueOf(normalizedValue).trim() + "%"); + yield column + " NOT LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, String.valueOf(normalizedValue).trim() + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + String.valueOf(normalizedValue).trim()); + yield column + " LIKE #{map." + key + "}"; + } + default -> ""; + }; + } + + private String mapWeWvaDefaultInnerColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd" -> "src.STCD"; + case "tm" -> "src.TM"; + case "fid" -> "src.FID"; + default -> null; + }; + } + + private String mapWeWvaDefaultOuterColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd" -> "t.stcd"; + case "stnm" -> "t.stnm"; + case "tm" -> "t.tm"; + case "sttpCode" -> "t.sttpCode"; + case "sttpName" -> "t.sttpName"; + case "rstcd" -> "t.rstcd"; + case "baseId" -> "t.baseId"; + case "hbrvcd" -> "t.hbrvcd"; + default -> null; + }; + } + + private Object normalizeWeWvaDefaultValue(String field, Object value) { + if (value == null) { + return null; + } + if ("tm".equals(field)) { + String text = String.valueOf(value).trim(); + return StrUtil.isBlank(text) ? null : text; + } + return value; + } + + private String buildWeWvaDefaultValueExpr(String paramKey, boolean dateField, Object value) { + if (!dateField || value == null) { + return "#{map." + paramKey + "}"; + } + String text = String.valueOf(value).trim(); + if (text.length() <= 10) { + return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD')"; + } + return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD HH24:MI:SS')"; + } + + private String buildWeWvaDefaultOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return ""; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapWeWvaDefaultOuterColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction + " NULLS LAST"); + } + if (orderByParts.isEmpty()) { + return ""; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + private String buildWeMsstbprptViewSql() { + return "SELECT " + + "ai.STCD AS id, " + + "ai.STCD AS stcd, " + + "ai.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "ai.STNM AS stnm, " + + "ai.STTP AS sttpCode, " + + "ai.ORDER_INDEX AS orderIndex, " + + "ai.LGTD AS lgtd, " + + "ai.LTTD AS lttd " + + "FROM SD_AIMONITOR_B_H ai " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = ai.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "WHERE NVL(ai.IS_DELETED, 0) = 0"; + } + + private String buildWeVmsstbprptViewSql() { + return "SELECT " + + "ai.STCD AS id, " + + "ai.STTP AS sttpCode, " + + "ai.STCD AS stcd, " + + "ai.STNM AS stnm, " + + "ai.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "ai.BASE_ID AS baseId, " + + "ai.HBRVCD AS hbrvcd, " + + "ai.RVCD AS rvcd, " + + "ai.ORDER_INDEX AS orderIndex, " + + "ai.LGTD AS lgtd, " + + "ai.LTTD AS lttd " + + "FROM SD_AIMONITOR_B_H ai " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = ai.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "WHERE NVL(ai.IS_DELETED, 0) = 0"; + } + + private String buildWeWvaViewSql() { + return "SELECT " + + "a.ID AS id, " + + "a.STCD AS stcd, " + + "b.STNM AS stnm, " + + "b.STTP AS sttpCode, " + + "a.TM AS tm, " + + "a.FLNM AS flnm, " + + "a.IMG_PATH AS imgPath, " + + "a.FLPTH AS flpth, " + + "a.FID AS fid, " + + "a.DESCRIPTION AS description, " + + "b.RSTCD AS rstcd, " + + "b.BASE_ID AS baseId, " + + "b.HBRVCD AS hbrvcd, " + + "b.RVCD AS rvcd, " + + "b.ORDER_INDEX AS orderIndex " + + "FROM SD_WVA_R a " + + "INNER JOIN SD_AIMONITOR_B_H b ON a.STCD = b.STCD " + + "WHERE NVL(a.IS_DELETED, 0) = 0 " + + "AND NVL(b.IS_DELETED, 0) = 0"; + } + + private String buildWeMsstbprptSelectSql(List selectFields) { + Map columns = weMsstbprptFieldColumns(); + List selected = new ArrayList<>(); + if (CollUtil.isEmpty(selectFields)) { + selected.addAll(columns.values()); + } else { + for (String field : selectFields) { + String column = columns.get(field); + if (StrUtil.isNotBlank(column)) { + selected.add(column); + } + } + } + if (selected.isEmpty()) { + selected.addAll(columns.values()); + } + return String.join(", ", selected); + } + + private String buildWeVmsstbprptSelectSql(List selectFields) { + Map columns = weVmsstbprptFieldColumns(); + List selected = new ArrayList<>(); + if (CollUtil.isEmpty(selectFields)) { + selected.add("t.sttpCode AS sttpCode"); + selected.add("t.stnm AS stnm"); + selected.add("t.stcd AS stcd"); + } else { + for (String field : selectFields) { + String column = columns.get(field); + if (StrUtil.isNotBlank(column)) { + selected.add(column); + } + } + } + if (selected.isEmpty()) { + selected.add("t.sttpCode AS sttpCode"); + selected.add("t.stnm AS stnm"); + selected.add("t.stcd AS stcd"); + } + return String.join(", ", selected); + } + + private String buildWeWvaSelectSql(List selectFields) { + Map columns = weWvaFieldColumns(); + List selected = new ArrayList<>(); + if (CollUtil.isEmpty(selectFields)) { + selected.add("t.id AS id"); + selected.add("t.stcd AS stcd"); + selected.add("t.stnm AS stnm"); + selected.add("t.tm AS tm"); + selected.add("t.flnm AS flnm"); + selected.add("t.imgPath AS imgPath"); + selected.add("t.flpth AS flpth"); + selected.add("t.fid AS fid"); + selected.add("t.description AS description"); + } else { + for (String field : selectFields) { + String column = columns.get(field); + if (StrUtil.isNotBlank(column)) { + selected.add(column); + } + } + } + if (!selected.stream().anyMatch(item -> item.contains(" AS stnm"))) { + selected.add("t.stnm AS stnm"); + } + if (!selected.stream().anyMatch(item -> item.contains(" AS tm"))) { + selected.add("t.tm AS tm"); + } + if (!selected.stream().anyMatch(item -> item.contains(" AS flnm"))) { + selected.add("t.flnm AS flnm"); + } + return String.join(", ", selected); + } + + private Map weMsstbprptFieldColumns() { + Map columns = new LinkedHashMap<>(); + columns.put("id", "t.id AS id"); + columns.put("stcd", "t.stcd AS stcd"); + columns.put("rstcd", "t.rstcd AS rstcd"); + columns.put("ennm", "t.ennm AS ennm"); + columns.put("stnm", "t.stnm AS stnm"); + columns.put("sttpCode", "t.sttpCode AS sttpCode"); + columns.put("orderIndex", "t.orderIndex AS orderIndex"); + columns.put("lgtd", "t.lgtd AS lgtd"); + columns.put("lttd", "t.lttd AS lttd"); + return columns; + } + + private Map weVmsstbprptFieldColumns() { + Map columns = new LinkedHashMap<>(); + columns.put("id", "t.id AS id"); + columns.put("sttpCode", "t.sttpCode AS sttpCode"); + columns.put("stcd", "t.stcd AS stcd"); + columns.put("stnm", "t.stnm AS stnm"); + columns.put("rstcd", "t.rstcd AS rstcd"); + columns.put("ennm", "t.ennm AS ennm"); + columns.put("baseId", "t.baseId AS baseId"); + columns.put("hbrvcd", "t.hbrvcd AS hbrvcd"); + columns.put("rvcd", "t.rvcd AS rvcd"); + columns.put("orderIndex", "t.orderIndex AS orderIndex"); + columns.put("lgtd", "t.lgtd AS lgtd"); + columns.put("lttd", "t.lttd AS lttd"); + return columns; + } + + private Map weWvaFieldColumns() { + Map columns = new LinkedHashMap<>(); + columns.put("id", "t.id AS id"); + columns.put("stcd", "t.stcd AS stcd"); + columns.put("stnm", "t.stnm AS stnm"); + columns.put("sttpCode", "t.sttpCode AS sttpCode"); + columns.put("tm", "t.tm AS tm"); + columns.put("flnm", "t.flnm AS flnm"); + columns.put("imgPath", "t.imgPath AS imgPath"); + columns.put("flpth", "t.flpth AS flpth"); + columns.put("fid", "t.fid AS fid"); + columns.put("description", "t.description AS description"); + columns.put("rstcd", "t.rstcd AS rstcd"); + columns.put("baseId", "t.baseId AS baseId"); + columns.put("hbrvcd", "t.hbrvcd AS hbrvcd"); + columns.put("rvcd", "t.rvcd AS rvcd"); + columns.put("orderIndex", "t.orderIndex AS orderIndex"); + return columns; + } + + private String buildWeMsstbprptFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildWeMsstbprptLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildWeMsstbprptFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildWeMsstbprptLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapWeMsstbprptColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + if ("in".equals(operator) || "ni".equals(operator)) { + List values = normalizeWeFishQgcValues(filter.getValue()); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object value : values) { + if (value == null || StrUtil.isBlank(String.valueOf(value).trim())) { + continue; + } + String key = "weMsstbprptP" + indexHolder[0]++; + paramMap.put(key, String.valueOf(value).trim()); + placeholders.add("#{map." + key + "}"); + } + if (placeholders.isEmpty()) { + return ""; + } + return column + ("ni".equals(operator) ? " NOT IN (" : " IN (") + String.join(", ", placeholders) + ")"; + } + Object rawValue = filter.getValue(); + if (rawValue == null || StrUtil.isBlank(String.valueOf(rawValue).trim())) { + return ""; + } + String key = "weMsstbprptP" + indexHolder[0]++; + paramMap.put(key, String.valueOf(rawValue).trim()); + return switch (operator) { + case "eq" -> column + " = #{map." + key + "}"; + case "neq" -> column + " <> #{map." + key + "}"; + case "contains" -> { + paramMap.put(key, "%" + String.valueOf(rawValue).trim() + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "doesnotcontain" -> { + paramMap.put(key, "%" + String.valueOf(rawValue).trim() + "%"); + yield column + " NOT LIKE #{map." + key + "}"; + } + default -> ""; + }; + } + + private String buildWeVmsstbprptFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildWeVmsstbprptLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildWeVmsstbprptFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildWeVmsstbprptLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapWeVmsstbprptColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("isempty".equals(operator)) { + return "(" + column + " IS NULL OR " + column + " = '')"; + } + if ("isnotempty".equals(operator)) { + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + } + if ("in".equals(operator) || "ni".equals(operator)) { + List values = normalizeWeFishQgcValues(filter.getValue()); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object value : values) { + if (value == null || StrUtil.isBlank(String.valueOf(value).trim())) { + continue; + } + String key = "weVmsstbprptP" + indexHolder[0]++; + paramMap.put(key, String.valueOf(value).trim()); + placeholders.add("#{map." + key + "}"); + } + if (placeholders.isEmpty()) { + return ""; + } + return column + ("ni".equals(operator) ? " NOT IN (" : " IN (") + String.join(", ", placeholders) + ")"; + } + Object rawValue = filter.getValue(); + if (rawValue == null || StrUtil.isBlank(String.valueOf(rawValue).trim())) { + return ""; + } + String key = "weVmsstbprptP" + indexHolder[0]++; + String text = String.valueOf(rawValue).trim(); + return switch (operator) { + case "eq" -> { + paramMap.put(key, text); + yield column + " = #{map." + key + "}"; + } + case "neq" -> { + paramMap.put(key, text); + yield column + " <> #{map." + key + "}"; + } + case "gt" -> { + paramMap.put(key, text); + yield column + " > #{map." + key + "}"; + } + case "gte" -> { + paramMap.put(key, text); + yield column + " >= #{map." + key + "}"; + } + case "lt" -> { + paramMap.put(key, text); + yield column + " < #{map." + key + "}"; + } + case "lte" -> { + paramMap.put(key, text); + yield column + " <= #{map." + key + "}"; + } + case "contains" -> { + paramMap.put(key, "%" + text + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "doesnotcontain" -> { + paramMap.put(key, "%" + text + "%"); + yield column + " NOT LIKE #{map." + key + "}"; + } + default -> ""; + }; + } + + private String buildWeWvaFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildWeWvaLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildWeWvaFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildWeWvaLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapWeWvaColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("isempty".equals(operator)) { + return "(" + column + " IS NULL OR " + column + " = '')"; + } + if ("isnotempty".equals(operator)) { + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + } + if ("in".equals(operator) || "ni".equals(operator)) { + List values = normalizeWeFishQgcValues(filter.getValue()); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object value : values) { + if (value == null || StrUtil.isBlank(String.valueOf(value).trim())) { + continue; + } + String key = "weWvaP" + indexHolder[0]++; + paramMap.put(key, String.valueOf(value).trim()); + placeholders.add("#{map." + key + "}"); + } + if (placeholders.isEmpty()) { + return ""; + } + return column + ("ni".equals(operator) ? " NOT IN (" : " IN (") + String.join(", ", placeholders) + ")"; + } + Object rawValue = filter.getValue(); + if (rawValue == null || StrUtil.isBlank(String.valueOf(rawValue).trim())) { + return ""; + } + String key = "weWvaP" + indexHolder[0]++; + String text = String.valueOf(rawValue).trim(); + boolean dateField = isWeWvaDateField(filter); + String valueExpr = buildWeWvaValueExpr(key, dateField, rawValue); + return switch (operator) { + case "eq" -> { + paramMap.put(key, text); + yield column + " = " + valueExpr; + } + case "neq" -> { + paramMap.put(key, text); + yield column + " <> " + valueExpr; + } + case "gt" -> { + paramMap.put(key, text); + yield column + " > " + valueExpr; + } + case "gte" -> { + paramMap.put(key, text); + yield column + " >= " + valueExpr; + } + case "lt" -> { + paramMap.put(key, text); + yield column + " < " + valueExpr; + } + case "lte" -> { + paramMap.put(key, text); + yield column + " <= " + valueExpr; + } + case "contains" -> { + paramMap.put(key, "%" + text + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "doesnotcontain" -> { + paramMap.put(key, "%" + text + "%"); + yield column + " NOT LIKE #{map." + key + "}"; + } + default -> ""; + }; + } + + private boolean isWeWvaDateField(DataSourceRequest.FilterDescriptor filter) { + if (filter == null || StrUtil.isBlank(filter.getField())) { + return false; + } + if ("tm".equalsIgnoreCase(filter.getField())) { + return true; + } + return "date".equalsIgnoreCase(filter.getDataType()); + } + + private String buildWeWvaValueExpr(String paramKey, boolean dateField, Object value) { + if (!dateField || value == null) { + return "#{map." + paramKey + "}"; + } + String text = String.valueOf(value).trim(); + if (text.length() <= 10) { + return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD')"; + } + return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD HH24:MI:SS')"; + } + + private String mapWeMsstbprptColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "id" -> "t.id"; + case "stcd" -> "t.stcd"; + case "rstcd" -> "t.rstcd"; + case "ennm" -> "t.ennm"; + case "stnm" -> "t.stnm"; + case "sttpCode" -> "t.sttpCode"; + case "orderIndex" -> "t.orderIndex"; + case "lgtd" -> "t.lgtd"; + case "lttd" -> "t.lttd"; + default -> null; + }; + } + + private String mapWeVmsstbprptColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "id" -> "t.id"; + case "sttpCode" -> "t.sttpCode"; + case "stcd" -> "t.stcd"; + case "stnm" -> "t.stnm"; + case "rstcd" -> "t.rstcd"; + case "ennm" -> "t.ennm"; + case "baseId" -> "t.baseId"; + case "hbrvcd" -> "t.hbrvcd"; + case "rvcd" -> "t.rvcd"; + case "orderIndex" -> "t.orderIndex"; + case "lgtd" -> "t.lgtd"; + case "lttd" -> "t.lttd"; + default -> null; + }; + } + + private String mapWeWvaColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "id" -> "t.id"; + case "stcd" -> "t.stcd"; + case "stnm" -> "t.stnm"; + case "sttpCode" -> "t.sttpCode"; + case "tm" -> "t.tm"; + case "flnm" -> "t.flnm"; + case "imgPath" -> "t.imgPath"; + case "flpth" -> "t.flpth"; + case "fid" -> "t.fid"; + case "description" -> "t.description"; + case "rstcd" -> "t.rstcd"; + case "baseId" -> "t.baseId"; + case "hbrvcd" -> "t.hbrvcd"; + case "rvcd" -> "t.rvcd"; + case "orderIndex" -> "t.orderIndex"; + default -> null; + }; + } + + private String buildWeMsstbprptOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return ""; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapWeMsstbprptColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction + " NULLS LAST"); + } + if (orderByParts.isEmpty()) { + return ""; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + private String buildWeVmsstbprptOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return ""; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapWeVmsstbprptColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction + " NULLS LAST"); + } + if (orderByParts.isEmpty()) { + return ""; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + private String buildWeWvaOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return " ORDER BY t.tm DESC NULLS LAST"; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapWeWvaColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction + " NULLS LAST"); + } + if (orderByParts.isEmpty()) { + return " ORDER BY t.tm DESC NULLS LAST"; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + private String buildWeFishListQgcGroupSql(String baseSql, GroupingInfo[] groupInfos) { + if (groupInfos == null || groupInfos.length == 0) { + return baseSql; + } + List groupFields = new ArrayList<>(); + List selectItems = new ArrayList<>(); + for (GroupingInfo item : groupInfos) { + if (item == null || StrUtil.isBlank(item.getSelector())) { + continue; + } + String groupColumn = mapWeFishListQgcGroupColumn(item.getSelector()); + if (StrUtil.isBlank(groupColumn)) { + continue; + } + groupFields.add(groupColumn); + selectItems.add(groupColumn + " AS " + item.getSelector().toUpperCase()); + selectItems.add("COUNT(*) AS COUNT_" + item.getSelector().toUpperCase()); + } + if (groupFields.isEmpty()) { + return baseSql; + } + StringBuilder sql = new StringBuilder("SELECT "); + sql.append(String.join(", ", selectItems)) + .append(" FROM (") + .append(baseSql) + .append(") T GROUP BY ") + .append(String.join(", ", groupFields)); + return sql.toString(); + } + + private String buildWeFishStaticsSql(String baseId, + String hbrvcd, + String yr, + List rstcdList, + Map paramMap) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("COUNT(DISTINCT we.DCPC) AS dcpcCount, ") + .append("COUNT(DISTINCT we.STCD) AS stcdCount, ") + .append("COUNT(DISTINCT fish.FTP) AS ftpCount, ") + .append("NVL(SUM(NVL(fish.FCNT, 0)), 0) AS fcntSum ") + .append("FROM SD_WE_B_H section ") + .append("INNER JOIN SD_WE_R we ON section.STCD = we.STCD ") + .append(" AND NVL(we.IS_DELETED, 0) = 0 ") + .append(" AND NVL(we.STATUS, 1) = 1 ") + .append("LEFT JOIN SD_WEFISH_R fish ON fish.WER_ID = we.ID ") + .append(" AND NVL(fish.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(section.USFL, 0) = 1 "); + + if (StrUtil.isNotBlank(baseId)) { + paramMap.put("weStaticsBaseId", baseId); + sql.append("AND section.BASE_ID = #{map.weStaticsBaseId} "); + } + if (StrUtil.isNotBlank(hbrvcd)) { + paramMap.put("weStaticsHbrvcd", hbrvcd); + sql.append("AND section.HBRVCD = #{map.weStaticsHbrvcd} "); + } + if (StrUtil.isNotBlank(yr)) { + paramMap.put("weStaticsYr", yr); + sql.append("AND TO_CHAR(we.TM, 'yyyy') = #{map.weStaticsYr} "); + } + if (CollUtil.isNotEmpty(rstcdList)) { + List placeholders = new ArrayList<>(); + int index = 0; + for (String rstcd : rstcdList) { + if (StrUtil.isBlank(rstcd)) { + continue; + } + String key = "weStaticsRstcd" + index++; + paramMap.put(key, rstcd); + placeholders.add("#{map." + key + "}"); + } + if (CollUtil.isNotEmpty(placeholders)) { + sql.append("AND section.RSTCD IN (").append(String.join(", ", placeholders)).append(") "); + } + } + return sql.toString(); + } + + private WeStaticsVo buildWeFishStaticsVo(Map row) { + if (row == null || row.isEmpty()) { + return null; + } + WeStaticsVo vo = new WeStaticsVo(); + vo.setDcpcCount(toWeFishLongValue(firstPresentWeFishValue(row, "DCPCCOUNT", "dcpcCount"))); + vo.setStcdCount(toWeFishLongValue(firstPresentWeFishValue(row, "STCDCOUNT", "stcdCount"))); + vo.setFtpCount(toWeFishLongValue(firstPresentWeFishValue(row, "FTPCOUNT", "ftpCount"))); + vo.setFcntSum(toWeFishLongValue(firstPresentWeFishValue(row, "FCNTSUM", "fcntSum"))); + return vo; + } + + private String buildWeFishTDetailSql() { + return "SELECT " + + "section.STCD AS stcd, " + + "section.STNM AS stnm, " + + "eng.BASE_ID AS baseId, " + + "eng.BASE_NAME AS baseName, " + + "eng.RVCD AS rvcd, " + + "eng.RVCD_NAME AS rvcdName, " + + "eng.ADDVCD AS addvcd, " + + "eng.ADDVCD_NAME AS addvcdName, " + + "eng.HBRVCD AS hbrvcd, " + + "eng.HBRVCD_NAME AS hbrvcdName, " + + "we.DCPC AS dcpc, " + + "we.TM AS tm, " + + "we.FID AS werFid, " + + "fish.WER_ID AS werId, " + + "fish.FTP AS ftp, " + + "fish.FSZ AS fsz, " + + "fish.FCNT AS fcnt, " + + "fish.FWGH AS fwgh, " + + "fish.ST AS st, " + + "fish.PS AS ps, " + + "fish.AVG_FWGT AS avgFwgt, " + + "fish.AVG_FSZ AS avgFsz, " + + "fish.FID AS fid, " + + "fish.FILE_ID AS fileId, " + + "dict.ID AS id, " + + "dict.NAME AS name, " + + "dict.ALIAS AS alias, " + + "dict.GENUS AS genus, " + + "dict.FAMILY AS family, " + + "dict.SPECIES AS species, " + + "dict.TYPE AS type, " + + "dict.RARE AS rare, " + + "dict.SPEC_ORIGIN AS specOrigin, " + + "dict.PTYPE AS ptype, " + + "TO_CHAR(we.TM, 'yyyy') AS yr, " + + "CASE " + + "WHEN dict.SPEC_ORIGIN = 2 THEN 1 " + + "WHEN dict.SPEC_ORIGIN = 1 AND NVL(dict.PTYPE, -1) <> 6 THEN 2 " + + "WHEN dict.SPEC_ORIGIN = 1 AND dict.PTYPE = 6 THEN 3 " + + "END AS ty " + + "FROM SD_WE_R we " + + "INNER JOIN SD_WEFISH_R fish ON fish.WER_ID = we.ID " + + " AND NVL(fish.IS_DELETED, 0) = 0 " + + "INNER JOIN SD_WE_B_H section ON section.STCD = we.STCD " + + " AND NVL(section.USFL, 0) = 1 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = section.RSTCD " + + " AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_FISHDICTORY_B dict ON dict.ID = fish.FTP " + + " AND NVL(dict.IS_DELETED, 0) = 0 " + + "WHERE NVL(we.IS_DELETED, 0) = 0 " + + "AND NVL(we.STATUS, 1) = 1 "; + } + + private String buildWeFishQgcDetailSql() { + return "SELECT " + + "section.STCD AS stcd, " + + "section.STNM AS stnm, " + + "eng.BASE_ID AS baseId, " + + "eng.BASE_NAME AS baseName, " + + "eng.RVCD AS rvcd, " + + "eng.RVCD_NAME AS rvcdName, " + + "eng.ADDVCD AS addvcd, " + + "eng.ADDVCD_NAME AS addvcdName, " + + "eng.HBRVCD AS hbrvcd, " + + "eng.HBRVCD_NAME AS hbrvcdName, " + + "we.DCPC AS dcpc, " + + "we.TM AS tm, " + + "we.FID AS werFid, " + + "fish.WER_ID AS werId, " + + "fish.FTP AS ftp, " + + "fish.FSZ AS fsz, " + + "fish.FCNT AS fcnt, " + + "fish.FWGH AS fwgh, " + + "fish.ST AS st, " + + "fish.PS AS ps, " + + "fish.AVG_FWGT AS avgFwgt, " + + "fish.AVG_FSZ AS avgFsz, " + + "fish.FID AS fid, " + + "fish.FILE_ID AS fileId, " + + "dict.ID AS id, " + + "dict.NAME AS name, " + + "dict.ALIAS AS alias, " + + "dict.GENUS AS genus, " + + "dict.FAMILY AS family, " + + "dict.SPECIES AS species, " + + "dict.TYPE AS type, " + + "dict.RARE AS rare, " + + "dict.SPEC_ORIGIN AS specOrigin, " + + "dict.PTYPE AS ptype, " + + "TO_CHAR(we.TM, 'yyyy') AS yr, " + + "CASE " + + "WHEN dict.SPEC_ORIGIN = 2 THEN 1 " + + "WHEN dict.SPEC_ORIGIN = 1 AND NVL(dict.PTYPE, -1) <> 6 THEN 2 " + + "WHEN dict.SPEC_ORIGIN = 1 AND dict.PTYPE = 6 THEN 3 " + + "END AS ty " + + "FROM SD_WE_R we " + + "INNER JOIN SD_WEFISH_R fish ON fish.WER_ID = we.ID " + + " AND NVL(fish.IS_DELETED, 0) = 0 " + + "INNER JOIN SD_WE_B_H section ON section.STCD = we.STCD " + +// " AND NVL(section.USFL, 0) = 1 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = section.RSTCD " + + " AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_FISHDICTORY_B dict ON dict.ID = fish.FTP " + +// " AND (dict.RVCD = 'ZY' OR dict.RVCD = eng.HBRVCD) " + + "WHERE NVL(we.IS_DELETED, 0) = 0 " + + // 旧库按 TASK_STATUS=Approved/null 过滤,新库改用 STATUS=1(完成) 承接审批通过口径 + "AND dict.IS_DELETED =0 "; + } + + private String buildWeFishQgcFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildWeFishQgcLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildWeFishQgcFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildWeFishQgcLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapWeFishQgcColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("isempty".equals(operator)) { + return "(" + column + " IS NULL OR " + column + " = '')"; + } + if ("isnotempty".equals(operator)) { + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + } + if ("in".equals(operator) || "ni".equals(operator)) { + List values = normalizeWeFishQgcValues(filter.getValue()); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object value : values) { + Object normalizedValue = normalizeWeFishQgcValue(filter.getField(), value); + if (normalizedValue == null) { + continue; + } + String key = "weFishQgcP" + indexHolder[0]++; + paramMap.put(key, normalizedValue); + placeholders.add("#{map." + key + "}"); + } + if (placeholders.isEmpty()) { + return ""; + } + return column + ("ni".equals(operator) ? " NOT IN (" : " IN (") + String.join(", ", placeholders) + ")"; + } + + Object normalizedValue = normalizeWeFishQgcValue(filter.getField(), filter.getValue()); + if (normalizedValue == null) { + return ""; + } + String key = "weFishQgcP" + indexHolder[0]++; + return switch (operator) { + case "eq" -> { + paramMap.put(key, normalizedValue); + yield column + " = #{map." + key + "}"; + } + case "neq" -> { + paramMap.put(key, normalizedValue); + yield column + " <> #{map." + key + "}"; + } + case "gt" -> { + paramMap.put(key, normalizedValue); + yield column + " > #{map." + key + "}"; + } + case "gte" -> { + paramMap.put(key, normalizedValue); + yield column + " >= #{map." + key + "}"; + } + case "lt" -> { + paramMap.put(key, normalizedValue); + yield column + " < #{map." + key + "}"; + } + case "lte" -> { + paramMap.put(key, normalizedValue); + yield column + " <= #{map." + key + "}"; + } + case "contains" -> { + paramMap.put(key, "%" + String.valueOf(normalizedValue).trim() + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "doesnotcontain" -> { + paramMap.put(key, "%" + String.valueOf(normalizedValue).trim() + "%"); + yield column + " NOT LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, String.valueOf(normalizedValue).trim() + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + String.valueOf(normalizedValue).trim()); + yield column + " LIKE #{map." + key + "}"; + } + default -> ""; + }; + } + + private String mapWeFishQgcColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd" -> "r.stcd"; + case "stnm" -> "r.stnm"; + case "baseId" -> "r.baseId"; + case "baseName" -> "r.baseName"; + case "rvcd" -> "r.rvcd"; + case "rvcdName" -> "r.rvcdName"; + case "addvcd" -> "r.addvcd"; + case "addvcdName" -> "r.addvcdName"; + case "hbrvcd" -> "r.hbrvcd"; + case "hbrvcdName" -> "r.hbrvcdName"; + case "dcpc" -> "r.dcpc"; + case "tm" -> "r.tm"; + case "year" -> "r.yr"; + case "werFid" -> "r.werFid"; + case "werId" -> "r.werId"; + case "ftp" -> "r.ftp"; + case "ftpName" -> "r.name"; + case "fsz" -> "r.fsz"; + case "fcnt" -> "r.fcnt"; + case "fwgh" -> "r.fwgh"; + case "st" -> "r.st"; + case "ps" -> "r.ps"; + case "avgFwgt" -> "r.avgFwgt"; + case "avgFsz" -> "r.avgFsz"; + case "fid" -> "r.fid"; + case "fileId" -> "r.fileId"; + case "id" -> "r.id"; + case "name" -> "r.name"; + case "alias" -> "r.alias"; + case "genus" -> "r.genus"; + case "family" -> "r.family"; + case "species" -> "r.species"; + case "type" -> "r.type"; + case "rare" -> "r.rare"; + case "specOrigin" -> "r.specOrigin"; + case "ptype" -> "r.ptype"; + case "yr" -> "r.yr"; + case "ty" -> "r.ty"; + default -> null; + }; + } + + private String mapWeFishQgcGroupColumn(String field) { + String column = mapWeFishQgcColumn(field); + if (StrUtil.isBlank(column)) { + return null; + } + return column.startsWith("r.") ? column.substring(2) : column; + } + + private String buildWeFishQgcOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return " ORDER BY r.tm DESC NULLS LAST, r.stcd ASC, r.name ASC"; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapWeFishQgcColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction + " NULLS LAST"); + } + if (orderByParts.isEmpty()) { + return " ORDER BY r.tm DESC NULLS LAST, r.stcd ASC, r.name ASC"; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + private String buildWeFishPageOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return " ORDER BY r.ftp ASC"; + } + Map columnMap = new LinkedHashMap<>(); + columnMap.put("ftp", "r.ftp"); + columnMap.put("genus", "r.genus"); + columnMap.put("startFtpCnt", "r.startFtpCnt"); + columnMap.put("startCnt", "r.startCnt"); + columnMap.put("startYear", "r.startYear"); + columnMap.put("endFtpCnt", "r.endFtpCnt"); + columnMap.put("endCnt", "r.endCnt"); + columnMap.put("endYear", "r.endYear"); + + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = columnMap.get(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction + " NULLS LAST"); + } + if (orderByParts.isEmpty()) { + return " ORDER BY r.ftp ASC"; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + private String buildWeStaticsSecondSelectSql(List selectFields) { + Map columns = new LinkedHashMap<>(); + columns.put("stcd", "r.stcd AS stcd"); + columns.put("stnm", "r.stnm AS stnm"); + columns.put("ftp", "r.ftp AS ftp"); + columns.put("ftpName", "r.name AS ftpName"); + columns.put("dcpc", "r.dcpc AS dcpc"); + columns.put("tm", "r.tm AS tm"); + columns.put("fcnt", "r.fcnt AS fcnt"); + columns.put("fid", "r.werFid AS fid"); + + List selected = new ArrayList<>(); + if (CollUtil.isEmpty(selectFields)) { + selected.addAll(columns.values()); + } else { + for (String field : selectFields) { + String column = columns.get(field); + if (StrUtil.isNotBlank(column)) { + selected.add(column); + } + } + } + if (selected.isEmpty()) { + selected.addAll(columns.values()); + } + return String.join(", ", selected); + } + + private Object normalizeWeFishQgcValue(String field, Object value) { + if (value == null) { + return null; + } + if (isWeFishIntegerField(field)) { + try { + return Integer.parseInt(String.valueOf(value).trim()); + } catch (Exception ex) { + return null; + } + } + if (isWeFishDecimalField(field)) { + try { + return new java.math.BigDecimal(String.valueOf(value).trim()); + } catch (Exception ex) { + return null; + } + } + if ("tm".equals(field)) { + return parseDateTimeSafely(value); + } + return value; + } + + private List normalizeWeFishQgcValues(Object value) { + List values = new ArrayList<>(); + appendWeFishQgcValues(values, value); + return values; + } + + private List normalizeWeWvaValues(Object value) { + List values = new ArrayList<>(); + appendWeFishQgcValues(values, value); + return values; + } + + private String buildWeFishListStatFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildWeFishListStatLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildWeFishListStatFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildWeFishListStatLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapWeFishListStatColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + if ("isempty".equals(operator)) { + return "(" + column + " IS NULL OR " + column + " = '')"; + } + if ("isnotempty".equals(operator)) { + return "(" + column + " IS NOT NULL AND " + column + " <> '')"; + } + if ("in".equals(operator) || "ni".equals(operator)) { + List values = normalizeWeFishQgcValues(filter.getValue()); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object value : values) { + Object normalizedValue = normalizeWeFishListStatValue(filter.getField(), value); + if (normalizedValue == null) { + continue; + } + String key = "weFishListStatP" + indexHolder[0]++; + paramMap.put(key, normalizedValue); + placeholders.add("#{map." + key + "}"); + } + if (placeholders.isEmpty()) { + return ""; + } + return column + ("ni".equals(operator) ? " NOT IN (" : " IN (") + String.join(", ", placeholders) + ")"; + } + + Object normalizedValue = normalizeWeFishListStatValue(filter.getField(), filter.getValue()); + if (normalizedValue == null) { + return ""; + } + String key = "weFishListStatP" + indexHolder[0]++; + return switch (operator) { + case "eq" -> { + paramMap.put(key, normalizedValue); + yield column + " = #{map." + key + "}"; + } + case "neq" -> { + paramMap.put(key, normalizedValue); + yield column + " <> #{map." + key + "}"; + } + case "gt" -> { + paramMap.put(key, normalizedValue); + yield column + " > #{map." + key + "}"; + } + case "gte" -> { + paramMap.put(key, normalizedValue); + yield column + " >= #{map." + key + "}"; + } + case "lt" -> { + paramMap.put(key, normalizedValue); + yield column + " < #{map." + key + "}"; + } + case "lte" -> { + paramMap.put(key, normalizedValue); + yield column + " <= #{map." + key + "}"; + } + case "contains" -> { + paramMap.put(key, "%" + String.valueOf(normalizedValue).trim() + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "doesnotcontain" -> { + paramMap.put(key, "%" + String.valueOf(normalizedValue).trim() + "%"); + yield column + " NOT LIKE #{map." + key + "}"; + } + case "startswith" -> { + paramMap.put(key, String.valueOf(normalizedValue).trim() + "%"); + yield column + " LIKE #{map." + key + "}"; + } + case "endswith" -> { + paramMap.put(key, "%" + String.valueOf(normalizedValue).trim()); + yield column + " LIKE #{map." + key + "}"; + } + default -> ""; + }; + } + + private String mapWeFishListStatColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "id" -> "r.id"; + case "name" -> "r.name"; + case "baseId" -> "r.baseId"; + case "baseName" -> "r.baseName"; + case "rvcd" -> "r.rvcd"; + case "rvcdName" -> "r.rvcdName"; + case "hbrvcd" -> "r.hbrvcd"; + case "hbrvcdName" -> "r.hbrvcdName"; + case "rstcd" -> "r.rstcd"; + case "ennm" -> "r.ennm"; + case "tm" -> "r.tm"; + case "yr" -> "r.yr"; + case "fcnt" -> "r.fcnt"; + case "code" -> "r.code"; + default -> null; + }; + } + + private String mapWeFishListQgcGroupColumn(String field) { + String column = mapWeFishListStatColumn(field); + if (StrUtil.isBlank(column)) { + return null; + } + return column.startsWith("r.") ? column.substring(2) : column; + } + + private String buildWeFishListQgcOrderBySql(List sorts) { + if (CollUtil.isEmpty(sorts)) { + return ""; + } + List orderByParts = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapWeFishListStatColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String direction = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderByParts.add(column + " " + direction + " NULLS LAST"); + } + if (orderByParts.isEmpty()) { + return ""; + } + return " ORDER BY " + String.join(", ", orderByParts); + } + + private Object normalizeWeFishListStatValue(String field, Object value) { + if (value == null) { + return null; + } + if ("yr".equals(field)) { + try { + return Integer.parseInt(String.valueOf(value).trim()); + } catch (Exception ex) { + return null; + } + } + if ("fcnt".equals(field)) { + try { + return new java.math.BigDecimal(String.valueOf(value).trim()); + } catch (Exception ex) { + return null; + } + } + if ("tm".equals(field)) { + return parseDateTimeSafely(value); + } + return value; + } + + private WeFishListStatQgcVo buildWeFishListStatQgcVo(Map row) { + if (row == null || row.isEmpty()) { + return null; + } + return new WeFishListStatQgcVo() + .setId(safeWeFishString(firstPresentWeFishValue(row, "ID", "id"))) + .setName(safeWeFishString(firstPresentWeFishValue(row, "NAME", "name"))) + .setBaseId(safeWeFishString(firstPresentWeFishValue(row, "BASEID", "baseId"))) + .setBaseName(safeWeFishString(firstPresentWeFishValue(row, "BASENAME", "baseName"))) + .setRvcd(safeWeFishString(firstPresentWeFishValue(row, "RVCD", "rvcd"))) + .setRvcdName(safeWeFishString(firstPresentWeFishValue(row, "RVCDNAME", "rvcdName"))) + .setHbrvcd(safeWeFishString(firstPresentWeFishValue(row, "HBRVCD", "hbrvcd"))) + .setHbrvcdName(safeWeFishString(firstPresentWeFishValue(row, "HBRVCDNAME", "hbrvcdName"))) + .setRstcd(safeWeFishString(firstPresentWeFishValue(row, "RSTCD", "rstcd"))) + .setEnnm(safeWeFishString(firstPresentWeFishValue(row, "ENNM", "ennm"))) + .setTm(toDateValue(firstPresentWeFishValue(row, "TM", "tm"))) + .setYr(toWeFishIntegerValue(firstPresentWeFishValue(row, "YR", "yr"))) + .setFcnt(toWeFishLongValue(firstPresentWeFishValue(row, "FCNT", "fcnt"))); + } + + private WeFishListQgcVo buildWeFishListQgcVo(Map row) { + if (row == null || row.isEmpty()) { + return null; + } + return new WeFishListQgcVo() + .setId(safeWeFishString(firstPresentWeFishValue(row, "ID", "id"))) + .setName(safeWeFishString(firstPresentWeFishValue(row, "NAME", "name"))) + .setBaseId(safeWeFishString(firstPresentWeFishValue(row, "BASEID", "baseId"))) + .setBaseName(safeWeFishString(firstPresentWeFishValue(row, "BASENAME", "baseName"))) + .setRvcd(safeWeFishString(firstPresentWeFishValue(row, "RVCD", "rvcd"))) + .setRvcdName(safeWeFishString(firstPresentWeFishValue(row, "RVCDNAME", "rvcdName"))) + .setHbrvcd(safeWeFishString(firstPresentWeFishValue(row, "HBRVCD", "hbrvcd"))) + .setHbrvcdName(safeWeFishString(firstPresentWeFishValue(row, "HBRVCDNAME", "hbrvcdName"))) + .setRstcd(safeWeFishString(firstPresentWeFishValue(row, "RSTCD", "rstcd"))) + .setEnnm(safeWeFishString(firstPresentWeFishValue(row, "ENNM", "ennm"))) + .setTm(toWeFishDateTimeTextValue(firstPresentWeFishValue(row, "TM", "tm"))) + .setYr(toWeFishIntegerValue(firstPresentWeFishValue(row, "YR", "yr"))) + .setFcnt(toWeFishLongValue(firstPresentWeFishValue(row, "FCNT", "fcnt"))); + } + + private WeFishPointQgcVo buildWeFishPointQgcVo(Map row, Map fishNameMap) { + if (row == null || row.isEmpty()) { + return null; + } + return new WeFishPointQgcVo() + .setFtp(resolveWeFishNames(firstPresentWeFishValue(row, "FTP", "ftp"), fishNameMap)) + .setStcd(safeWeFishString(firstPresentWeFishValue(row, "STCD", "stcd"))) + .setRstcds(safeWeFishString(firstPresentWeFishValue(row, "RSTCDS", "rstcds"))) + .setStnm(safeWeFishString(firstPresentWeFishValue(row, "STNM", "stnm"))) + .setEnnm(safeWeFishString(firstPresentWeFishValue(row, "ENNM", "ennm"))) + .setLgtd(toWeFishBigDecimalValue(firstPresentWeFishValue(row, "LGTD", "lgtd"))) + .setLttd(toWeFishBigDecimalValue(firstPresentWeFishValue(row, "LTTD", "lttd"))) + .setSttp(safeWeFishString(firstPresentWeFishValue(row, "STTP", "sttp"))) + .setSttpMap(safeWeFishString(firstPresentWeFishValue(row, "STTPMAP", "sttpMap"))) + .setRvcd(safeWeFishString(firstPresentWeFishValue(row, "RVCD", "rvcd"))) + .setAddvcd(safeWeFishString(firstPresentWeFishValue(row, "ADDVCD", "addvcd"))) + .setBaseId(safeWeFishString(firstPresentWeFishValue(row, "BASEID", "baseId"))) + .setSttpCode(safeWeFishString(firstPresentWeFishValue(row, "STTPCODE", "sttpCode"))) + .setAnchoPointState(safeWeFishString(firstPresentWeFishValue(row, "ANCHOPOINTSTATE", "anchoPointState"))) + .setTitleName(safeWeFishString(firstPresentWeFishValue(row, "TITLENAME", "titleName"))) + .setDtmel(toWeFishBigDecimalValue(firstPresentWeFishValue(row, "DTMEL", "dtmel"))); + } + + private Map loadWeFishNameMap() { + List> rows = microservicDynamicSQLMapper.getAllList( + "SELECT ID AS id, NAME AS name FROM SD_FISHDICTORY_B WHERE NVL(IS_DELETED, 0) = 0", + new HashMap<>() + ); + Map fishNameMap = new LinkedHashMap<>(); + for (Map row : rows) { + String id = safeWeFishString(firstPresentWeFishValue(row, "ID", "id")); + String name = safeWeFishString(firstPresentWeFishValue(row, "NAME", "name")); + if (StrUtil.isNotBlank(id) && StrUtil.isNotBlank(name)) { + fishNameMap.put(id, name); + } + } + return fishNameMap; + } + + private String resolveWeFishNames(Object ftpValue, Map fishNameMap) { + String ftp = safeWeFishString(ftpValue); + if (StrUtil.isBlank(ftp)) { + return ""; + } + String[] ids = ftp.split(","); + List names = new ArrayList<>(); + for (String id : ids) { + String trimId = StrUtil.trim(id); + if (StrUtil.isBlank(trimId)) { + continue; + } + String name = fishNameMap.get(trimId); + if (StrUtil.isNotBlank(name)) { + names.add(name); + } + } + return names.isEmpty() ? "" : String.join(",", names); + } + + private void applyWeFishPointMapDistance(List points) { + if (CollUtil.isEmpty(points)) { + return; + } + int defaultLevel = 50000000; + int level1 = 1500000; + double level1Distance = 1.2D; + int level2 = 800000; + double level2Distance = 0.8D; + int level3 = 400000; + double level3Distance = 0.4D; + int level4 = 50000; + double level4Distance = 0.1D; + + Set marked = new HashSet<>(); + for (int i = 0; i < points.size(); i++) { + WeFishPointQgcVo current = points.get(i); + String category = current.getAnchoPointState(); + String currentKey = StrUtil.nullToEmpty(current.getStcd()) + StrUtil.nullToEmpty(category); + if (marked.contains(currentKey)) { + continue; + } + current.setDistance(defaultLevel); + BigDecimal x1 = current.getLgtd(); + BigDecimal y1 = current.getLttd(); + if (x1 == null || y1 == null) { + continue; + } + for (int j = i + 1; j < points.size(); j++) { + WeFishPointQgcVo target = points.get(j); + String targetCategory = target.getAnchoPointState(); + String targetKey = StrUtil.nullToEmpty(target.getStcd()) + StrUtil.nullToEmpty(targetCategory); + if (marked.contains(targetKey)) { + continue; + } + BigDecimal x2 = target.getLgtd(); + BigDecimal y2 = target.getLttd(); + if (x2 == null || y2 == null || currentKey.equals(targetKey)) { + continue; + } + double dx = Math.abs(x1.doubleValue() - x2.doubleValue()); + double dy = Math.abs(y1.doubleValue() - y2.doubleValue()); + double distance = Math.sqrt(dx * dx + dy * dy); + if (distance < level4Distance) { + target.setDistance(level4); + marked.add(targetKey); + } else if (distance < level3Distance) { + target.setDistance(level3); + marked.add(targetKey); + } else if (distance < level2Distance) { + target.setDistance(level2); + marked.add(targetKey); + } else if (distance < level1Distance) { + target.setDistance(level1); + marked.add(targetKey); + } + } + } + } + + private java.math.BigDecimal toWeFishBigDecimalValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof java.math.BigDecimal decimal) { + return decimal; + } + if (value instanceof Number number) { + return java.math.BigDecimal.valueOf(number.doubleValue()); + } + try { + return new java.math.BigDecimal(String.valueOf(value).trim()); + } catch (Exception ex) { + return null; + } + } + + private String resolveWeFishStringFilterValue(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions, + String field) { + String value = getFirstWeFishFilterText(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), field); + if (StrUtil.isBlank(value) && loadOptions != null) { + value = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, field); + } + return StrUtil.trim(value); + } + + private Date toDateValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof Date date) { + return date; + } + if (value instanceof Number number) { + return new Date(number.longValue()); + } + String text = String.valueOf(value).trim(); + if (StrUtil.isBlank(text)) { + return null; + } + try { + return DateUtil.parse(text).toJdkDate(); + } catch (Exception ex) { + return null; + } + } + + private String toWeFishDateTimeTextValue(Object value) { + Date date = toDateValue(value); + if (date != null) { + return DateUtil.formatDateTime(date); + } + String text = safeWeFishString(value); + return StrUtil.isBlank(text) ? null : text; + } + + + private void appendWeFishQgcValues(List values, Object value) { + if (value == null) { + return; + } + if (value instanceof Iterable iterable) { + for (Object item : iterable) { + appendWeFishQgcValues(values, item); + } + return; + } + if (value.getClass().isArray()) { + Object[] array = (Object[]) value; + for (Object item : array) { + appendWeFishQgcValues(values, item); + } + return; + } + values.add(value); + } + + private boolean isWeFishIntegerField(String field) { + return "fcnt".equals(field) || "ty".equals(field); + } + + private boolean isWeFishDecimalField(String field) { + return "fwgh".equals(field) || "avgFwgt".equals(field) || "avgFsz".equals(field); + } + + private Date parseDateTimeSafely(Object value) { + if (value == null) { + return null; + } + if (value instanceof Date date) { + return date; + } + try { + return DateUtil.parse(String.valueOf(value).trim()).toJdkDate(); + } catch (Exception ex) { + return null; + } + } + + private Object firstPresentWeFishValue(Map row, String... keys) { + if (row == null || keys == null) { + return null; + } + for (String key : keys) { + if (key != null && row.containsKey(key)) { + return row.get(key); + } + } + return null; + } + + private Long toWeFishLongValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof Number number) { + return number.longValue(); + } + try { + return Long.parseLong(String.valueOf(value).trim()); + } catch (Exception ex) { + return null; + } + } + + private Integer toWeFishIntegerValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof Number number) { + return number.intValue(); + } + try { + return Integer.parseInt(String.valueOf(value).trim()); + } catch (Exception ex) { + return null; + } + } + + private String safeWeFishString(Object value) { + if (value == null) { + return null; + } + String text = String.valueOf(value).trim(); + return StrUtil.isBlank(text) ? null : text; + } + + private String getFirstWeFishFilterText(DataSourceRequest.FilterDescriptor filter, String fieldName) { + List values = getWeFishFilterTexts(filter, fieldName); + return CollUtil.isEmpty(values) ? null : values.get(0); + } + + private List getWeFishFilterTexts(DataSourceRequest.FilterDescriptor filter, String fieldName) { + List values = new ArrayList<>(); + collectWeFishFilterTexts(filter, fieldName, values); + return values; + } + + private void collectWeFishFilterTexts(DataSourceRequest.FilterDescriptor filter, String fieldName, List values) { + if (filter == null || StrUtil.isBlank(fieldName)) { + return; + } + if (fieldName.equalsIgnoreCase(filter.getField())) { + for (Object item : normalizeWeFishQgcValues(filter.getValue())) { + if (item == null) { + continue; + } + String text = String.valueOf(item).trim(); + if (StrUtil.isNotBlank(text)) { + values.add(text); + } + } + } + if (CollUtil.isEmpty(filter.getFilters())) { + return; + } + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + collectWeFishFilterTexts(child, fieldName, values); + } + } + + private WeEnvmAutoMonitorVo buildWeEnvmAutoMonitorVo(Integer cnt, + Integer orderInx, + String sttpCode, + String sttpFullPath, + String sttpName) { + WeEnvmAutoMonitorVo vo = new WeEnvmAutoMonitorVo(); + vo.setCnt(cnt == null ? 0 : cnt); + vo.setOrderInx(orderInx); + vo.setOrderInxName(sttpName); + vo.setSttpCode(sttpCode); + vo.setSttpFullPath(sttpFullPath); + vo.setSttpName(sttpName); + return vo; + } + + private List reorderWeEnvmAutoMonitorRows(List rows, List showIds) { + if (CollUtil.isEmpty(rows)) { + return new ArrayList<>(); + } + LinkedHashMap rowMap = new LinkedHashMap<>(); + for (WeEnvmAutoMonitorVo row : rows) { + if (row != null && row.getOrderInx() != null) { + rowMap.put(String.valueOf(row.getOrderInx()), row); + } + } + List result = new ArrayList<>(); + if (CollUtil.isNotEmpty(showIds)) { + for (String showId : showIds) { + WeEnvmAutoMonitorVo row = rowMap.get(showId); + if (row != null) { + result.add(row); + } + } + return result; + } + result.addAll(rowMap.values()); + result.sort((a, b) -> Integer.compare( + a == null || a.getOrderInx() == null ? Integer.MAX_VALUE : a.getOrderInx(), + b == null || b.getOrderInx() == null ? Integer.MAX_VALUE : b.getOrderInx() + )); + return result; + } + + private Integer queryWeEnvmAutoMonitorCount(SqlAndParams sqlAndParams) { + if (sqlAndParams == null || StrUtil.isBlank(sqlAndParams.sql())) { + return 0; + } + Map row = microservicDynamicSQLMapper.getOneBySql(sqlAndParams.sql(), sqlAndParams.params()); + return toWeFishIntegerValue(firstPresentWeFishValue(row, "CNT", "cnt")); + } + + private boolean shouldIgnoreWeEnvmFhRstcd(List rstcds) { + if (CollUtil.isEmpty(rstcds)) { + return false; + } + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(DISTINCT eng.STCD) AS cnt ") + .append("FROM SD_ENGINFO_B_H eng ") + .append("WHERE NVL(eng.IS_DELETED, 0) = 0 ") + .append("AND eng.HYCD = '10304' ") + .append("AND NVL(eng.BLDSTT_CODE, 0) IN (1, 2) "); + appendWeEnvmExactInCondition(sql, paramMap, "eng.STCD", "rstcd", rstcds); + Integer cnt = queryWeEnvmAutoMonitorCount(new SqlAndParams(sql.toString(), paramMap)); + return cnt != null && cnt == rstcds.size(); + } + + private SqlAndParams buildWeEnvmWtSql(String baseId, List rstcds) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt ") + .append("FROM SD_WT_B_H wt ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(wt.IS_DELETED, 0) = 0 ") + .append("AND wt.STTP IN ('WTRV', 'WTVT') ") + .append("AND NVL(wt.MWAY, 0) = 2 "); + appendWeEnvmBaseIdCondition(sql, paramMap, "eng.BASE_ID", baseId); + appendWeEnvmLikeCondition(sql, paramMap, "wt.RSTCD", "rstcd", rstcds); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmGjWqSql(String baseId, List hbrvcds, List rvcds) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt ") + .append("FROM SD_WQ_B_H wq ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wq.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(wq.IS_DELETED, 0) = 0 ") + .append("AND wq.STTP = 'WQ' ") + .append("AND NVL(wq.MWAY, 0) = 2 ") + .append("AND NVL(wq.DTIN_TYPE, 0) = 1 "); + appendWeEnvmBaseIdCondition(sql, paramMap, "eng.BASE_ID", baseId); + appendWeEnvmExactInCondition(sql, paramMap, "eng.HBRVCD", "hbrvcd", hbrvcds); + appendWeEnvmExactInCondition(sql, paramMap, "eng.RVCD", "rvcd", rvcds); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmZjWqSql(String baseId, List rstcds) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_WQ_B_H wq ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wq.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(wq.IS_DELETED, 0) = 0 ") + .append("AND wq.STTP IN ('WQ', 'WQFB') ") + .append("AND NVL(wq.MWAY, 0) = 2 ") + .append("AND NVL(wq.DTIN_TYPE, 0) = 0 "); + appendWeEnvmBaseIdCondition(sql, paramMap, "eng.BASE_ID", baseId); + appendWeEnvmLikeCondition(sql, paramMap, "wq.RSTCD", "rstcd", rstcds); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmStGjSql(String baseId) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_RIVER_B_H river ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = river.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(river.IS_DELETED, 0) = 0 ") + .append("AND river.STTP IN ('ZQ', 'ZZ') ") + .append("AND NVL(river.MWAY, 0) = 2 ") + .append("AND NVL(river.DTIN_TYPE, 0) = 1 "); + appendWeEnvmBaseIdCondition(sql, paramMap, "eng.BASE_ID", baseId); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmStZjSql(String baseId, List rstcds) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_RIVER_B_H river ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = river.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(river.IS_DELETED, 0) = 0 ") + .append("AND river.STTP IN ('ZQ', 'ZZ') ") + .append("AND NVL(river.MWAY, 0) = 2 ") + .append("AND NVL(river.DTIN_TYPE, 0) = 0 "); + appendWeEnvmBaseIdCondition(sql, paramMap, "eng.BASE_ID", baseId); + appendWeEnvmLikeCondition(sql, paramMap, "river.RSTCD", "rstcd", rstcds); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmEngQecSql(String baseId, List rstcds) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_ENGINFO_B_H eng ") + .append("WHERE NVL(eng.IS_DELETED, 0) = 0 ") + .append("AND NVL(eng.DTIN, 0) = 1 ") + .append("AND NVL(eng.BLDSTT_CODE, 0) = 2 "); + if (CollUtil.isEmpty(rstcds)) { + sql.append("AND NVL(eng.RUN_STATE, 0) = 4 "); + } else { + sql.append("AND NVL(eng.PRSC, 0) IN (1, 2, 3) ") + .append("AND NVL(eng.COENVW_STATE, 0) = 1 "); + } + appendWeEnvmBaseIdCondition(sql, paramMap, "eng.BASE_ID", baseId); + appendWeEnvmExactInCondition(sql, paramMap, "eng.STCD", "rstcd", rstcds); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmVdSql(String baseId, List rstcds) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_VDINFO_B vd ") + .append("WHERE 1=1 ") + .append("AND vd.STTP LIKE 'VD%' ") + .append("AND NVL(vd.DTIN, 0) = 1 "); + appendWeEnvmBaseIdCondition(sql, paramMap, "vd.BASE_ID", baseId); + appendWeEnvmLikeCondition(sql, paramMap, "vd.RSTCD", "rstcd", rstcds); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmRiverWqSql(String baseId, List rstcds) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_WQ_B_H wq ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wq.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(wq.IS_DELETED, 0) = 0 ") + .append("AND wq.STTP = 'WQ' ") + .append("AND NVL(wq.MWAY, 0) = 2 ") + .append("AND NVL(wq.DTIN_TYPE, 0) = 0 "); + appendWeEnvmBaseIdCondition(sql, paramMap, "eng.BASE_ID", baseId); + appendWeEnvmLikeCondition(sql, paramMap, "wq.RSTCD", "rstcd", rstcds); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmFbWqSql(String baseId, List rstcds) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_WQ_B_H wq ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wq.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(wq.IS_DELETED, 0) = 0 ") + .append("AND wq.STTP = 'WQFB' ") + .append("AND NVL(wq.MWAY, 0) = 2 ") + .append("AND NVL(wq.DTIN_TYPE, 0) = 0 "); + appendWeEnvmBaseIdCondition(sql, paramMap, "eng.BASE_ID", baseId); + appendWeEnvmLikeCondition(sql, paramMap, "wq.RSTCD", "rstcd", rstcds); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmFhSql(String baseId, List rstcds, boolean ignoreRstcd) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_FHBT_B_H fh ") + .append("WHERE NVL(fh.IS_DELETED, 0) = 0 "); + appendWeEnvmBaseIdCondition(sql, paramMap, "fh.BASE_ID", baseId); + if (!ignoreRstcd) { + appendWeEnvmLikeCondition(sql, paramMap, "fh.RSTCD", "rstcd", rstcds); + } + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmFhWqSql(String baseId, List rstcds, boolean ignoreRstcd) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_WQ_B_H wq ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wq.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(wq.IS_DELETED, 0) = 0 ") + .append("AND wq.STTP = 'WQ' "); + appendWeEnvmBaseIdCondition(sql, paramMap, "eng.BASE_ID", baseId); + if (!ignoreRstcd) { + appendWeEnvmLikeCondition(sql, paramMap, "wq.RSTCD", "rstcd", rstcds); + appendWeEnvmFhByRstcdCondition(sql, paramMap, "wq.FHSTCD", "fh_rstcd", rstcds); + } + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmFhWtSql(String baseId, List rstcds, boolean ignoreRstcd) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_WT_B_H wt ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(wt.IS_DELETED, 0) = 0 ") + .append("AND wt.STTP = 'WTRV' ") + .append("AND NVL(wt.DTIN_TYPE, 0) = 0 "); + appendWeEnvmBaseIdCondition(sql, paramMap, "eng.BASE_ID", baseId); + if (!ignoreRstcd) { + appendWeEnvmLikeCondition(sql, paramMap, "wt.RSTCD", "rstcd", rstcds); + appendWeEnvmFhByRstcdCondition(sql, paramMap, "wt.FHSTCD", "fh_rstcd", rstcds); + } + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmFhStSql(String baseId, List rstcds, boolean ignoreRstcd) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_RIVER_B_H river ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = river.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(river.IS_DELETED, 0) = 0 ") + .append("AND river.STTP IN ('ZQ', 'ZZ') ") + .append("AND NVL(river.DTIN_TYPE, 0) = 0 "); + appendWeEnvmBaseIdCondition(sql, paramMap, "eng.BASE_ID", baseId); + if (!ignoreRstcd) { + appendWeEnvmLikeCondition(sql, paramMap, "river.RSTCD", "rstcd", rstcds); + appendWeEnvmFhByRstcdCondition(sql, paramMap, "river.FHSTCD", "fh_rstcd", rstcds); + } + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmWeSql(String baseId, List rstcds) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_WE_B_H weB ") + .append("WHERE 1=1 ") + .append("AND EXISTS (SELECT 1 FROM SD_WE_R we ") + .append("WHERE we.STCD = weB.STCD AND NVL(we.IS_DELETED, 0) = 0 AND NVL(we.STATUS, 1) = 1) "); + appendWeEnvmBaseIdCondition(sql, paramMap, "weB.BASE_ID", baseId); + appendWeEnvmLikeCondition(sql, paramMap, "weB.RSTCD", "rstcd", rstcds); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmWvaSql(String baseId, List rstcds, List hbrvcds) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_AIMONITOR_B_H ai ") + .append("WHERE NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP = 'WVA' "); + appendWeEnvmBaseIdCondition(sql, paramMap, "ai.BASE_ID", baseId); + appendWeEnvmLikeCondition(sql, paramMap, "ai.RSTCD", "rstcd", rstcds); + appendWeEnvmExactInCondition(sql, paramMap, "ai.HBRVCD", "hbrvcd", hbrvcds); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmVdEqsSql(String baseId, List rstcds) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_VDINFO_B vd ") + .append("WHERE 1=1 ") + .append("AND vd.STTP = 'VD_EQS' "); + appendWeEnvmBaseIdCondition(sql, paramMap, "vd.BASE_ID", baseId); + appendWeEnvmLikeCondition(sql, paramMap, "vd.RSTCD", "rstcd", rstcds); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmRareFishSql(String baseId, List rstcds, Date startTime, Date endTime) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(DISTINCT fish.FTP) AS cnt ") + .append("FROM SD_WE_R we ") + .append("INNER JOIN SD_WEFISH_R fish ON we.ID = fish.WER_ID AND NVL(fish.IS_DELETED, 0) = 0 ") + .append("INNER JOIN SD_FISHDICTORY_B dict ON dict.ID = fish.FTP AND NVL(dict.IS_DELETED, 0) = 0 ") + .append("INNER JOIN SD_WE_B_H weB ON weB.STCD = we.STCD ") + .append("WHERE NVL(we.IS_DELETED, 0) = 0 ") + .append("AND NVL(we.STATUS, 1) = 1 ") + .append("AND NVL(dict.RARE, 0) = 1 ") + .append("AND NVL(dict.SPEC_ORIGIN, 0) = 1 "); + appendWeEnvmBaseIdCondition(sql, paramMap, "weB.BASE_ID", baseId); + appendWeEnvmLikeCondition(sql, paramMap, "weB.RSTCD", "rstcd", rstcds); + appendWeEnvmDateRangeCondition(sql, paramMap, "we.TM", startTime, endTime); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmTeAnimalsSql() { + String sql = "SELECT COUNT(1) AS cnt FROM (" + + "SELECT b.ID FROM MS_SPECANIMALS_B a " + + "INNER JOIN SD_VABASIC_B b ON a.ANIMAL_ID = b.ID " + + "WHERE NVL(a.IS_DELETED, 0) = 0 AND NVL(b.IS_DELETED, 0) = 0 AND NVL(b.ENABLE, 1) = 1 " + + "GROUP BY b.ID" + + ")"; + return new SqlAndParams(sql, new HashMap<>()); + } + + private SqlAndParams buildWeEnvmRgWqSql(String baseId, List rstcds) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_WQ_B_H wq ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wq.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(wq.IS_DELETED, 0) = 0 ") + .append("AND wq.STTP = 'WQ' ") + .append("AND NVL(wq.MWAY, 0) = 1 ") + .append("AND NVL(wq.DTIN_TYPE, 0) = 2 "); + appendWeEnvmBaseIdCondition(sql, paramMap, "eng.BASE_ID", baseId); + appendWeEnvmLikeCondition(sql, paramMap, "wq.RSTCD", "rstcd", rstcds); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmWeFishStaticsSql(String baseId, List rstcds, Date startTime, Date endTime) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(DISTINCT fish.FTP) AS cnt ") + .append("FROM SD_WE_R we ") + .append("INNER JOIN SD_WEFISH_R fish ON we.ID = fish.WER_ID AND NVL(fish.IS_DELETED, 0) = 0 ") + .append("INNER JOIN SD_WE_B_H weB ON weB.STCD = we.STCD ") + .append("WHERE NVL(we.IS_DELETED, 0) = 0 ") + .append("AND NVL(we.STATUS, 1) = 1 "); + appendWeEnvmBaseIdCondition(sql, paramMap, "weB.BASE_ID", baseId); + appendWeEnvmLikeCondition(sql, paramMap, "weB.RSTCD", "rstcd", rstcds); + appendWeEnvmDateRangeCondition(sql, paramMap, "we.TM", startTime, endTime); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmFpStaticsSql(String baseId, List rstcds) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_FPSS_B_H fp ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fp.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(fp.IS_DELETED, 0) = 0 ") + .append("AND fp.LGTD IS NOT NULL "); + appendWeEnvmBaseIdCondition(sql, paramMap, "eng.BASE_ID", baseId); + appendWeEnvmExactInCondition(sql, paramMap, "fp.RSTCD", "rstcd", rstcds); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmVdYljSql(String baseId, List rstcds) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_VDINFO_B vd ") + .append("WHERE 1=1 ") + .append("AND vd.STTP LIKE 'VD%' ") + .append("AND vd.STTP <> 'VD_FH' ") + .append("AND NVL(vd.DTIN, 0) = 1 "); + appendWeEnvmBaseIdCondition(sql, paramMap, "vd.BASE_ID", baseId); + appendWeEnvmLikeCondition(sql, paramMap, "vd.RSTCD", "rstcd", rstcds); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmAiSql(String baseId, List rstcds, List hbrvcds) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_AIMONITOR_B_H ai ") + .append("WHERE NVL(ai.IS_DELETED, 0) = 0 ") + .append("AND ai.STTP LIKE 'AI%' "); +// .append("AND ai.STCD = ai.DTIN_SRC "); + appendWeEnvmBaseIdCondition(sql, paramMap, "ai.BASE_ID", baseId); + appendWeEnvmLikeCondition(sql, paramMap, "ai.RSTCD", "rstcd", rstcds); + appendWeEnvmExactInCondition(sql, paramMap, "ai.HBRVCD", "hbrvcd", hbrvcds); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmWtrvSql(String baseId, List rstcds) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_WT_B_H wt ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(wt.IS_DELETED, 0) = 0 ") + .append("AND wt.STTP = 'WTRV' ") + .append("AND NVL(wt.MWAY, 0) = 2 "); + appendWeEnvmBaseIdCondition(sql, paramMap, "eng.BASE_ID", baseId); + appendWeEnvmLikeCondition(sql, paramMap, "wt.RSTCD", "rstcd", rstcds); + return new SqlAndParams(sql.toString(), paramMap); + } + + private SqlAndParams buildWeEnvmWtvtSql(String baseId, List rstcds) { + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + sql.append("SELECT COUNT(1) AS cnt FROM SD_WT_B_H wt ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("WHERE NVL(wt.IS_DELETED, 0) = 0 ") + .append("AND wt.STTP = 'WTVT' ") + .append("AND NVL(wt.MWAY, 0) = 2 "); + appendWeEnvmBaseIdCondition(sql, paramMap, "eng.BASE_ID", baseId); + appendWeEnvmLikeCondition(sql, paramMap, "wt.RSTCD", "rstcd", rstcds); + return new SqlAndParams(sql.toString(), paramMap); + } + + private void appendWeEnvmBaseIdCondition(StringBuilder sql, Map paramMap, String column, String baseId) { + if (StrUtil.isBlank(baseId)) { + return; + } + sql.append("AND ").append(column).append(" = #{map.baseId} "); + paramMap.put("baseId", baseId); + } + + private void appendWeEnvmExactInCondition(StringBuilder sql, + Map paramMap, + String column, + String prefix, + List values) { + if (CollUtil.isEmpty(values)) { + return; + } + sql.append("AND ").append(column).append(" IN ("); + for (int i = 0; i < values.size(); i++) { + String key = prefix + i; + if (i > 0) { + sql.append(", "); + } + sql.append("#{map.").append(key).append("}"); + paramMap.put(key, values.get(i)); + } + sql.append(") "); + } + + private void appendWeEnvmLikeCondition(StringBuilder sql, + Map paramMap, + String column, + String prefix, + List values) { + if (CollUtil.isEmpty(values)) { + return; + } + sql.append("AND ("); + for (int i = 0; i < values.size(); i++) { + String key = prefix + i; + if (i > 0) { + sql.append(" OR "); + } + sql.append(column).append(" LIKE '%' || #{map.").append(key).append("} || '%'"); + paramMap.put(key, values.get(i)); + } + sql.append(") "); + } + + private void appendWeEnvmDateRangeCondition(StringBuilder sql, + Map paramMap, + String column, + Date startTime, + Date endTime) { + if (startTime == null || endTime == null) { + return; + } + sql.append("AND ").append(column).append(" BETWEEN #{map.startTime} AND #{map.endTime} "); + paramMap.put("startTime", startTime); + paramMap.put("endTime", endTime); + } + + private void appendWeEnvmFhByRstcdCondition(StringBuilder sql, + Map paramMap, + String column, + String prefix, + List rstcds) { + if (CollUtil.isEmpty(rstcds)) { + return; + } + sql.append("AND ").append(column).append(" IN (") + .append("SELECT fh.STCD FROM SD_FHBT_B_H fh ") + .append("WHERE NVL(fh.IS_DELETED, 0) = 0 "); + appendWeEnvmLikeCondition(sql, paramMap, "fh.RSTCD", prefix, rstcds); + sql.append(") "); + } + + private record SqlAndParams(String sql, Map params) { + } + + private void fillWeFishDerivedFields(List list) { + if (CollUtil.isEmpty(list)) { + return; + } + for (WeFishTQgcVo item : list) { + if (item == null) { + continue; + } + item.setTyName(resolveTyName(item.getTy())); + item.setSpecOriginName(resolveSpecOriginName(item.getSpecOrigin())); + } + } + + private String resolveTyName(Integer ty) { + if (ty == null) { + return null; + } + return switch (ty) { + case 1 -> "外来鱼类"; + case 2 -> "本土受威胁鱼类"; + case 3 -> "本土无危鱼类"; + default -> null; + }; + } + + private String resolveSpecOriginName(String specOrigin) { + if (StrUtil.isBlank(specOrigin)) { + return null; + } + return switch (specOrigin) { + case "1" -> "本土"; + case "2" -> "外来鱼类"; + default -> null; + }; + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/zq/controller/ZqMonitorController.java b/backend/src/main/java/com/yfd/platform/qgc_env/zq/controller/ZqMonitorController.java index 91cd4c78..7629326f 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/zq/controller/ZqMonitorController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/zq/controller/ZqMonitorController.java @@ -1,8 +1,10 @@ package com.yfd.platform.qgc_env.zq.controller; +import com.yfd.platform.annotation.Log; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo; +import com.yfd.platform.qgc_env.zq.entity.vo.ZqOperateRequest; import com.yfd.platform.qgc_env.zq.service.ZqMonitorService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -56,6 +58,7 @@ public class ZqMonitorController { return ResponseResult.successData(zqMonitorService.getRiverDrtpKendoListCust(dataSourceRequest)); } + @Log(module = "水文流量站监测", value = "删除流量站小时/日/月数据") @PostMapping("/river/removeKendoByIds") @Operation(summary = "删除流量站小时/日/月数据") public ResponseResult removeKendoByIds(@RequestBody BatchDeleteAo batchDeleteAo) { @@ -63,10 +66,14 @@ public class ZqMonitorController { return ResponseResult.success(); } + @Log(module = "水文流量站监测", value = "修改流量站小时数据") @PostMapping("/river/updateRiverRData") @Operation(summary = "修改流量站小时数据") - public ResponseResult updateRiverRData(@RequestBody Map updateData) { - zqMonitorService.updateRiverRData(updateData); + public ResponseResult updateRiverRData(@RequestBody ZqOperateRequest zqOperateRequest) { + zqMonitorService.updateRiverRData( + zqOperateRequest == null ? null : zqOperateRequest.getUpdateData(), + zqOperateRequest == null ? null : zqOperateRequest.getSource() + ); return ResponseResult.success(); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/zq/entity/vo/ZqOperateRequest.java b/backend/src/main/java/com/yfd/platform/qgc_env/zq/entity/vo/ZqOperateRequest.java new file mode 100644 index 00000000..5073c1e7 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/zq/entity/vo/ZqOperateRequest.java @@ -0,0 +1,13 @@ +package com.yfd.platform.qgc_env.zq.entity.vo; + +import lombok.Data; + +import java.util.Map; + +@Data +public class ZqOperateRequest { + + private String source; + + private Map updateData; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/zq/service/ZqMonitorService.java b/backend/src/main/java/com/yfd/platform/qgc_env/zq/service/ZqMonitorService.java index 8dcdd5c7..f2468d65 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/zq/service/ZqMonitorService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/zq/service/ZqMonitorService.java @@ -22,7 +22,7 @@ public interface ZqMonitorService { boolean removeKendoByIds(BatchDeleteAo batchDeleteAo); - boolean updateRiverRData(java.util.Map updateData); + boolean updateRiverRData(java.util.Map updateData, String source); ZqBaseInfoVo getStcdInfo(String stcd); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/zq/service/impl/ZqMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/zq/service/impl/ZqMonitorServiceImpl.java index ee6173d7..923af1cd 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/zq/service/impl/ZqMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/zq/service/impl/ZqMonitorServiceImpl.java @@ -10,8 +10,12 @@ import com.yfd.platform.common.GroupHelper; import com.yfd.platform.common.GroupingInfo; import com.yfd.platform.common.MicroservicDynamicSQLMapper; import com.yfd.platform.common.exception.BizException; +import com.yfd.platform.qgc_base.domain.MsOperationLog; +import com.yfd.platform.qgc_base.domain.MsOperationLogDetail; import com.yfd.platform.qgc_base.entity.vo.BatchDeleteAo; import com.yfd.platform.qgc_base.entity.vo.DataParam; +import com.yfd.platform.qgc_base.mapper.MsOperationLogDetailMapper; +import com.yfd.platform.qgc_base.mapper.MsOperationLogMapper; import com.yfd.platform.qgc_env.fh.entity.vo.HabitatVo; import com.yfd.platform.qgc_env.zq.entity.vo.ZqBaseInfoVo; import com.yfd.platform.qgc_env.zq.entity.vo.ZqRiverDayDataVo; @@ -19,23 +23,58 @@ import com.yfd.platform.qgc_env.zq.entity.vo.ZqRiverDrtpDataVo; import com.yfd.platform.qgc_env.zq.entity.vo.ZqRiverDataVo; import com.yfd.platform.qgc_env.zq.service.ZqMonitorService; import com.yfd.platform.utils.QgcQueryWrapperUtil; +import com.yfd.platform.utils.SecurityUtils; import jakarta.annotation.Resource; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.jdbc.core.JdbcTemplate; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; +import java.util.Date; import java.util.HashSet; -import java.util.LinkedHashMap; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @Service public class ZqMonitorServiceImpl implements ZqMonitorService { + private static final String ZQ_HOUR_TABLE_NAME = "SD_RIVER_R"; + private static final String ZQ_DAY_TABLE_NAME = "SD_RIVERDAY_S"; + private static final String ZQ_MONTH_TABLE_NAME = "SD_RIVERDRTP_S"; + private static final Map ZQ_UPDATE_COLUMN_MAP = new LinkedHashMap<>(); + private static final Map ZQ_FIELD_MEANING_MAP = new LinkedHashMap<>(); + + static { + ZQ_UPDATE_COLUMN_MAP.put("z", "Z"); + ZQ_UPDATE_COLUMN_MAP.put("q", "Q"); + ZQ_UPDATE_COLUMN_MAP.put("v", "V"); + + ZQ_FIELD_MEANING_MAP.put("ID", "主键ID"); + ZQ_FIELD_MEANING_MAP.put("STCD", "站码"); + ZQ_FIELD_MEANING_MAP.put("TM", "时间"); + ZQ_FIELD_MEANING_MAP.put("DT", "时间"); + ZQ_FIELD_MEANING_MAP.put("DRTP", "维度类型"); + ZQ_FIELD_MEANING_MAP.put("YEAR", "年"); + ZQ_FIELD_MEANING_MAP.put("MONTH", "月"); + ZQ_FIELD_MEANING_MAP.put("DR", "时段类型"); + ZQ_FIELD_MEANING_MAP.put("Z", "水位"); + ZQ_FIELD_MEANING_MAP.put("Q", "流量"); + ZQ_FIELD_MEANING_MAP.put("V", "流速"); + ZQ_FIELD_MEANING_MAP.put("MSQMT", "测流方法"); + ZQ_FIELD_MEANING_MAP.put("RECORD_USER", "创建人"); + ZQ_FIELD_MEANING_MAP.put("RECORD_TIME", "创建时间"); + ZQ_FIELD_MEANING_MAP.put("MODIFY_USER", "更新人"); + ZQ_FIELD_MEANING_MAP.put("MODIFY_TIME", "更新时间"); + ZQ_FIELD_MEANING_MAP.put("IS_DELETED", "是否已删除"); + ZQ_FIELD_MEANING_MAP.put("DELETE_USER", "删除人"); + ZQ_FIELD_MEANING_MAP.put("DELETE_TIME", "删除时间"); + ZQ_FIELD_MEANING_MAP.put("FID", "附件ID"); + ZQ_FIELD_MEANING_MAP.put("REMARK", "备注"); + } @Resource private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; @@ -43,6 +82,12 @@ public class ZqMonitorServiceImpl implements ZqMonitorService { @Resource private JdbcTemplate jdbcTemplate; + @Resource + private MsOperationLogMapper msOperationLogMapper; + + @Resource + private MsOperationLogDetailMapper msOperationLogDetailMapper; + @Override public DataSourceResult getMsstbprptList(DataSourceRequest dataSourceRequest) { return getMsstbprptListInternal(dataSourceRequest, false); @@ -66,11 +111,11 @@ public class ZqMonitorServiceImpl implements ZqMonitorService { .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 ") .append(" AND hbrv.BASEID = eng.BASE_ID ") - .append(" AND NVL(hbrv.IS_DELETED, 0) = 0 ") - .append(" AND NVL(hbrv.ENABLED, 1) = 1 ") + .append(" AND hbrv.IS_DELETED = 0 ") + .append(" AND hbrv.ENABLED = 1 ") .append("LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = eng.RVCD ") .append("LEFT JOIN SD_ADDVCD_DIC addv ON addv.ADDVCD = eng.ADDVCD ") - .append("WHERE NVL(t.IS_DELETED, 0) = 0 "); + .append("WHERE t.IS_DELETED = 0 "); if (onlyZq) { sql.append("AND t.STTP = 'ZQ' "); } @@ -170,11 +215,14 @@ public class ZqMonitorServiceImpl implements ZqMonitorService { } String dataType = batchDeleteAo.getDataType(); List dataList = batchDeleteAo.getDataList(); + String source = batchDeleteAo.getSource(); int batchSize = 500; for (int i = 0; i < dataList.size(); i += batchSize) { List subList = dataList.subList(i, Math.min(i + batchSize, dataList.size())); if ("TIME".equals(dataType)) { + List> beforeRows = queryRiverHourRows(subList); deleteRiverRData(subList); + recordRiverDeleteLog(beforeRows, ZQ_HOUR_TABLE_NAME, "删除流量站小时数据", source); Map dateRangeMap = new HashMap<>(); Map monthRangeMap = new HashMap<>(); for (DataParam param : subList) { @@ -209,10 +257,14 @@ public class ZqMonitorServiceImpl implements ZqMonitorService { } } if ("DATE".equals(dataType)) { + List> beforeRows = queryRiverDayRows(subList); deleteRiverDayData(subList); + recordRiverDeleteLog(beforeRows, ZQ_DAY_TABLE_NAME, "删除流量站日数据", source); } if ("MON".equals(dataType)) { + List> beforeRows = queryRiverMonthRows(subList); deleteRiverMonthData(subList); + recordRiverDeleteLog(beforeRows, ZQ_MONTH_TABLE_NAME, "删除流量站月数据", source); } } return true; @@ -220,10 +272,12 @@ public class ZqMonitorServiceImpl implements ZqMonitorService { @Override @Transactional(rollbackFor = Exception.class) - public boolean updateRiverRData(Map updateData) { - updateRiverHourData(updateData); + public boolean updateRiverRData(Map updateData, String source) { String stcd = updateData == null ? null : asString(updateData.get("stcd")); String tm = updateData == null ? null : asString(updateData.get("tm")); + Map beforeRow = queryRiverHourRow(stcd, tm); + updateRiverHourData(updateData); + recordRiverUpdateLog(beforeRow, updateData, source); if (StrUtil.isNotBlank(stcd) && StrUtil.isNotBlank(tm) && tm.length() >= 10) { String dateStr = tm.substring(0, 10); statisticsDayDataFromHour(stcd, dateStr, dateStr); @@ -1612,6 +1666,273 @@ public class ZqMonitorServiceImpl implements ZqMonitorService { return value == null ? null : String.valueOf(value); } + private Map queryRiverHourRow(String stcd, String tm) { + if (StrUtil.isBlank(stcd) || StrUtil.isBlank(tm)) { + return new HashMap<>(); + } + String sql = "SELECT ID, STCD, TO_CHAR(TM, 'YYYY-MM-DD HH24:MI:SS') AS TM, Z, Q, V, MSQMT, RECORD_USER, " + + "RECORD_TIME, MODIFY_USER, MODIFY_TIME, IS_DELETED, DELETE_USER, DELETE_TIME, FID, REMARK " + + "FROM SD_RIVER_R WHERE STCD = ? AND TM = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS')"; + List> rows = jdbcTemplate.queryForList(sql, stcd, tm); + return rows.isEmpty() ? new HashMap<>() : normalizeRiverLogRow(rows.getFirst()); + } + + private List> queryRiverHourRows(List dataList) { + if (CollUtil.isEmpty(dataList)) { + return new ArrayList<>(); + } + StringBuilder sql = new StringBuilder("SELECT ID, STCD, TO_CHAR(TM, 'YYYY-MM-DD HH24:MI:SS') AS TM, Z, Q, V, MSQMT, RECORD_USER, ") + .append("RECORD_TIME, MODIFY_USER, MODIFY_TIME, IS_DELETED, DELETE_USER, DELETE_TIME, FID, REMARK ") + .append("FROM SD_RIVER_R WHERE "); + List args = new ArrayList<>(); + List conditions = new ArrayList<>(); + for (DataParam item : dataList) { + if (item == null || StrUtil.isBlank(item.getId()) || StrUtil.isBlank(item.getTm())) { + continue; + } + conditions.add("(STCD = ? AND TM = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS'))"); + args.add(item.getId()); + args.add(item.getTm()); + } + if (conditions.isEmpty()) { + return new ArrayList<>(); + } + sql.append(String.join(" OR ", conditions)); + return normalizeRiverLogRows(jdbcTemplate.queryForList(sql.toString(), args.toArray())); + } + + private List> queryRiverDayRows(List dataList) { + if (CollUtil.isEmpty(dataList)) { + return new ArrayList<>(); + } + StringBuilder sql = new StringBuilder("SELECT ID, STCD, TO_CHAR(DT, 'YYYY-MM-DD HH24:MI:SS') AS DT, Z, Q, V, MSQMT, RECORD_USER, ") + .append("RECORD_TIME, MODIFY_USER, MODIFY_TIME, IS_DELETED, DELETE_USER, DELETE_TIME ") + .append("FROM SD_RIVERDAY_S WHERE "); + List args = new ArrayList<>(); + List conditions = new ArrayList<>(); + for (DataParam item : dataList) { + if (item == null || StrUtil.isBlank(item.getId()) || StrUtil.isBlank(item.getDt())) { + continue; + } + conditions.add("(STCD = ? AND DT = TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS'))"); + args.add(item.getId()); + args.add(item.getDt()); + } + if (conditions.isEmpty()) { + return new ArrayList<>(); + } + sql.append(String.join(" OR ", conditions)); + return normalizeRiverLogRows(jdbcTemplate.queryForList(sql.toString(), args.toArray())); + } + + private List> queryRiverMonthRows(List dataList) { + if (CollUtil.isEmpty(dataList)) { + return new ArrayList<>(); + } + StringBuilder sql = new StringBuilder("SELECT ID, STCD, TO_CHAR(TM, 'YYYY-MM-DD HH24:MI:SS') AS TM, DRTP, YEAR, MONTH, DR, Z, Q, V, MSQMT, ") + .append("RECORD_USER, RECORD_TIME, MODIFY_USER, MODIFY_TIME, IS_DELETED, DELETE_USER, DELETE_TIME ") + .append("FROM SD_RIVERDRTP_S WHERE "); + List args = new ArrayList<>(); + List conditions = new ArrayList<>(); + for (DataParam item : dataList) { + if (item == null || StrUtil.isBlank(item.getId()) || StrUtil.isBlank(item.getDrtp()) + || StrUtil.isBlank(item.getYear()) || StrUtil.isBlank(item.getMonth())) { + continue; + } + conditions.add("(STCD = ? AND DRTP = ? AND YEAR = ? AND MONTH = ?)"); + args.add(item.getId()); + args.add(item.getDrtp()); + args.add(Integer.parseInt(item.getYear())); + args.add(Integer.parseInt(item.getMonth())); + } + if (conditions.isEmpty()) { + return new ArrayList<>(); + } + sql.append(String.join(" OR ", conditions)); + return normalizeRiverLogRows(jdbcTemplate.queryForList(sql.toString(), args.toArray())); + } + + private List> normalizeRiverLogRows(List> rows) { + List> result = new ArrayList<>(); + if (CollUtil.isEmpty(rows)) { + return result; + } + for (Map row : rows) { + result.add(normalizeRiverLogRow(row)); + } + return result; + } + + private Map normalizeRiverLogRow(Map row) { + Map normalized = new LinkedHashMap<>(); + if (row == null || row.isEmpty()) { + return normalized; + } + for (Map.Entry entry : row.entrySet()) { + normalized.put(entry.getKey() == null ? null : entry.getKey().toUpperCase(), entry.getValue()); + } + return normalized; + } + + private void recordRiverUpdateLog(Map beforeRow, Map updateData, String source) { + if (updateData == null || updateData.isEmpty()) { + return; + } + String stcd = asString(updateData.get("stcd")); + String recordId = asString(beforeRow.get("ID")); + List details = new ArrayList<>(); + for (Map.Entry entry : ZQ_UPDATE_COLUMN_MAP.entrySet()) { + if (!containsKeyIgnoreCase(updateData, entry.getKey())) { + continue; + } + String column = entry.getValue(); + Object oldValue = beforeRow == null ? null : beforeRow.get(column); + Object newValue = getValueIgnoreCase(updateData, entry.getKey()); + if (StrUtil.equals(formatRiverLogValue(oldValue), formatRiverLogValue(newValue))) { + continue; + } + details.add(buildRiverLogDetail(null, ZQ_HOUR_TABLE_NAME, stcd, column, + oldValue, resolveRiverDisplayValue(column, oldValue), + newValue, resolveRiverDisplayValue(column, newValue), "修改字段值")); + } + if (details.isEmpty()) { + return; + } + MsOperationLog mainLog = buildRiverMainLog(recordId,"修改流量站小时数据", source); + msOperationLogMapper.insert(mainLog); + for (MsOperationLogDetail detail : details) { + detail.setMainId(mainLog.getId()); + } + batchInsertRiverLogDetails(details); + } + + private void recordRiverDeleteLog(List> rows, String tableName, String remark, String source) { + if (CollUtil.isEmpty(rows)) { + return; + } + + List details = new ArrayList<>(); + for (Map row : rows) { + String stcd = asString(row.get("STCD")); + String recordId = asString(row.get("ID")); + MsOperationLog mainLog = buildRiverMainLog(recordId,remark, source); + msOperationLogMapper.insert(mainLog); + for (Map.Entry entry : row.entrySet()) { + String fieldCode = entry.getKey(); + Object oldValue = entry.getValue(); + if (StrUtil.isBlank(fieldCode) || oldValue == null) { + continue; + } + details.add(buildRiverLogDetail(mainLog.getId(), tableName, stcd, fieldCode, + oldValue, resolveRiverDisplayValue(fieldCode, oldValue), + null, null, "删除字段值")); + } + } + batchInsertRiverLogDetails(details); + } + + private MsOperationLog buildRiverMainLog(String recordId,String remark, String source) { + MsOperationLog log = new MsOperationLog(); + log.setOperator(resolveRiverLogOperator()); + log.setOperateTime(new Date()); + log.setRecordId(recordId); + log.setTableName(ZQ_HOUR_TABLE_NAME); + log.setSource(StrUtil.trimToNull(source)); + log.setRemark(remark); + return log; + } + + private MsOperationLogDetail buildRiverLogDetail(String mainId, + String tableName, + String stationCode, + String fieldCode, + Object oldValueCode, + Object oldValueName, + Object newValueCode, + Object newValueName, + String remark) { + MsOperationLogDetail detail = new MsOperationLogDetail(); + detail.setMainId(mainId); + detail.setTableName(tableName); + detail.setStationCode(stationCode); + detail.setFieldCode(fieldCode); + detail.setFieldMeaning(ZQ_FIELD_MEANING_MAP.getOrDefault(fieldCode, fieldCode)); + detail.setOldValueCode(formatRiverLogValue(oldValueCode)); + detail.setOldValueName(formatRiverLogValue(oldValueName)); + detail.setNewValueCode(formatRiverLogValue(newValueCode)); + detail.setNewValueName(formatRiverLogValue(newValueName)); + detail.setRemark(remark); + return detail; + } + + private void batchInsertRiverLogDetails(List details) { + if (CollUtil.isEmpty(details)) { + return; + } + for (MsOperationLogDetail detail : details) { + if (detail == null) { + continue; + } + msOperationLogDetailMapper.insert(detail); + } + } + + private Object resolveRiverDisplayValue(String fieldCode, Object rawValue) { + return formatRiverLogValue(rawValue); + } + + private Object getValueIgnoreCase(Map data, String key) { + if (data == null || StrUtil.isBlank(key)) { + return null; + } + if (data.containsKey(key)) { + return data.get(key); + } + for (Map.Entry entry : data.entrySet()) { + if (StrUtil.equalsIgnoreCase(entry.getKey(), key)) { + return entry.getValue(); + } + } + return null; + } + + private boolean containsKeyIgnoreCase(Map data, String key) { + if (data == null || StrUtil.isBlank(key)) { + return false; + } + if (data.containsKey(key)) { + return true; + } + for (String mapKey : data.keySet()) { + if (StrUtil.equalsIgnoreCase(mapKey, key)) { + return true; + } + } + return false; + } + + private String resolveRiverLogOperator() { + try { + return SecurityUtils.getCurrentUsername(); + } catch (Exception ignored) { + try { + return SecurityUtils.getUserId(); + } catch (Exception ex) { + return null; + } + } + } + + private String formatRiverLogValue(Object value) { + if (value == null) { + return null; + } + if (value instanceof Date date) { + return cn.hutool.core.date.DateUtil.formatDateTime(date); + } + return String.valueOf(value); + } + private void statisticsDayDataFromHour(String stcd, String startDate, String endDate) { String deleteSql = "DELETE FROM SD_RIVERDAY_S T " + "WHERE T.STCD = ? " + @@ -1844,7 +2165,7 @@ public class ZqMonitorServiceImpl implements ZqMonitorService { } return switch (field) { case "isDeleted" -> "NVL(t.IS_DELETED, 0)"; - case "sttpFullPath" -> null; + case "sttpFullPath" -> "t.STTP"; case "sttpCode" -> "t.STTP"; case "mway" -> "t.MWAY"; case "dtinType" -> "t.DTIN_TYPE"; diff --git a/backend/src/main/java/com/yfd/platform/system/controller/LoginController.java b/backend/src/main/java/com/yfd/platform/system/controller/LoginController.java index 0a51347e..82ed2e6f 100644 --- a/backend/src/main/java/com/yfd/platform/system/controller/LoginController.java +++ b/backend/src/main/java/com/yfd/platform/system/controller/LoginController.java @@ -68,7 +68,7 @@ public class LoginController { @PostMapping("/login") @Operation(summary = "登录用户") @ResponseBody - public ResponseResult login(SysUser user) throws Exception { + public ResponseResult login(SysUser user, @RequestHeader(value = "Tenant_id", required = false) String tenantId) throws Exception { // 密码解密 String password = RsaUtils.decryptByPrivateKey(privateKey, user.getPassword()); @@ -100,6 +100,10 @@ public class LoginController { Integer status = loginUser.getUser().getStatus(); String regStatus = loginUser.getUser().getRegStatus(); + if (StrUtil.isNotBlank(tenantId)&&!tenantId.equals(loginUser.getUser().getTenantId())) { + return ResponseResult.error("账号不存在或密码错误"); + } + if (StrUtil.isNotBlank(regStatus)&&"REJECTED".equals(regStatus)) { return ResponseResult.error("账号审核未通过"); } diff --git a/backend/src/main/java/com/yfd/platform/system/service/IAdminAuthService.java b/backend/src/main/java/com/yfd/platform/system/service/IAdminAuthService.java new file mode 100644 index 00000000..ea25071d --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/system/service/IAdminAuthService.java @@ -0,0 +1,39 @@ +package com.yfd.platform.system.service; + +import java.util.List; +import java.util.Set; + +/** + * 超级管理员判断服务 + */ +public interface IAdminAuthService { + + /** + * 查询超级管理员用户名列表(SYS_USER.USERTYPE = 0) + * + * @return 超级管理员用户名列表 + */ + List getSuperAdminUsernames(); + + /** + * 查询统一管理的管理员用户名集合 + * + * @return 管理员用户名集合 + */ + Set getManagedAdminUsernames(); + + /** + * 判断指定用户名是否为超级管理员 + * + * @param username 用户名 + * @return 是否为超级管理员 + */ + boolean isManagedAdminUsername(String username); + + /** + * 判断当前登录用户是否为超级管理员 + * + * @return 是否为超级管理员 + */ + boolean isCurrentManagedAdmin(); +} diff --git a/backend/src/main/java/com/yfd/platform/system/service/IUserService.java b/backend/src/main/java/com/yfd/platform/system/service/IUserService.java index e5d970ac..4e9cdd62 100644 --- a/backend/src/main/java/com/yfd/platform/system/service/IUserService.java +++ b/backend/src/main/java/com/yfd/platform/system/service/IUserService.java @@ -103,6 +103,13 @@ public interface IUserService extends IService { ************************************/ ResponseResult resetPassword(String id) throws Exception; + /** + * 查询超级管理员用户名列表(SYS_USER.USERTYPE = 0) + * + * @return 超级管理员用户名列表 + */ + List getSuperAdminUsernames(); + /*********************************** * 用途说明:设置账号状态(管理员) * 参数说明 diff --git a/backend/src/main/java/com/yfd/platform/system/service/impl/AdminAuthServiceImpl.java b/backend/src/main/java/com/yfd/platform/system/service/impl/AdminAuthServiceImpl.java new file mode 100644 index 00000000..046de510 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/system/service/impl/AdminAuthServiceImpl.java @@ -0,0 +1,79 @@ +package com.yfd.platform.system.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.yfd.platform.system.domain.SysUser; +import com.yfd.platform.system.mapper.SysUserMapper; +import com.yfd.platform.system.service.IAdminAuthService; +import com.yfd.platform.system.service.IUserService; +import com.yfd.platform.utils.SecurityUtils; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.stereotype.Service; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * 超级管理员判断服务实现 + */ +@Service +public class AdminAuthServiceImpl implements IAdminAuthService { + + private static final Set BUILT_IN_ADMIN_USERNAMES = + new LinkedHashSet<>(Collections.singletonList("admin")); + + @Resource + private SysUserMapper userMapper; + + @Override + public List getSuperAdminUsernames() { + + // 获取当前请求 + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(SysUser::getUsertype, 0).select(SysUser::getUsername); + //根据用户名称或手机号查询用户信息 + if (attributes != null) { + HttpServletRequest request = attributes.getRequest(); + String tenantId = request.getHeader("Tenant_Id"); + if(StrUtil.isNotBlank(tenantId)){ + queryWrapper.eq(SysUser::getTenantId, tenantId); + } + } + List userList = userMapper.selectList(queryWrapper); + if (CollUtil.isEmpty(userList)) { + return new ArrayList<>(); + } + return userList.stream() + .map(SysUser::getUsername) + .filter(StrUtil::isNotBlank) + .distinct() + .collect(Collectors.toList()); + } + + @Override + public Set getManagedAdminUsernames() { + LinkedHashSet usernames = new LinkedHashSet<>(BUILT_IN_ADMIN_USERNAMES); + usernames.addAll(getSuperAdminUsernames()); + return usernames; + } + + @Override + public boolean isManagedAdminUsername(String username) { + return StrUtil.isNotBlank(username) && getManagedAdminUsernames().contains(username); + } + + @Override + public boolean isCurrentManagedAdmin() { + return isManagedAdminUsername(SecurityUtils.getCurrentUsername()); + } +} diff --git a/backend/src/main/java/com/yfd/platform/system/service/impl/SysOrganizationServiceImpl.java b/backend/src/main/java/com/yfd/platform/system/service/impl/SysOrganizationServiceImpl.java index 6e20d9dc..dcf3e8b6 100644 --- a/backend/src/main/java/com/yfd/platform/system/service/impl/SysOrganizationServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/system/service/impl/SysOrganizationServiceImpl.java @@ -11,6 +11,7 @@ import com.yfd.platform.system.domain.SysRole; import com.yfd.platform.system.domain.SysUser; import com.yfd.platform.system.mapper.SysOrganizationMapper; import com.yfd.platform.system.mapper.SysRoleMapper; +import com.yfd.platform.system.service.IAdminAuthService; import com.yfd.platform.system.service.ISysOrganizationService; import com.yfd.platform.system.service.IUserService; import com.yfd.platform.utils.ObjectConverterUtil; @@ -38,6 +39,9 @@ public class SysOrganizationServiceImpl extends ServiceImpl> getOrgScopeTree(String roleId, String tenantId) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - if(!"admin".equals(SecurityUtils.getCurrentUsername())){ + if(!adminAuthService.isCurrentManagedAdmin()){ String userId = SecurityUtils.getUserId(); List roles = sysRoleMapper.getRoleByUserId(userId); List ids = new ArrayList<>(); diff --git a/backend/src/main/java/com/yfd/platform/system/service/impl/UserDetailsServiceImpl.java b/backend/src/main/java/com/yfd/platform/system/service/impl/UserDetailsServiceImpl.java index 6042beea..77506150 100644 --- a/backend/src/main/java/com/yfd/platform/system/service/impl/UserDetailsServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/system/service/impl/UserDetailsServiceImpl.java @@ -1,18 +1,23 @@ package com.yfd.platform.system.service.impl; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.yfd.platform.datasource.DataSource; import com.yfd.platform.system.domain.LoginUser; import com.yfd.platform.system.domain.SysUser; import com.yfd.platform.system.mapper.SysMenuMapper; import com.yfd.platform.system.service.IUserService; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import jakarta.annotation.Resource; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + import java.util.List; /** @@ -35,9 +40,19 @@ public class UserDetailsServiceImpl implements UserDetailsService { @Override @DataSource(name = "master") public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + // 获取当前请求 + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); //根据用户名称或手机号查询用户信息 QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.and(wrapper -> wrapper.eq("username", username).or().eq("phone", username)); + if (attributes != null) { + HttpServletRequest request = attributes.getRequest(); + String tenantId = request.getHeader("Tenant_Id"); + if(StrUtil.isNotBlank(tenantId)){ + queryWrapper.eq("TENANT_ID", tenantId); + } + } + SysUser user = userService.getOne(queryWrapper); if (ObjectUtil.isEmpty(user)) { throw new RuntimeException("用户账号不存在!"); diff --git a/backend/src/main/java/com/yfd/platform/system/service/impl/UserServiceImpl.java b/backend/src/main/java/com/yfd/platform/system/service/impl/UserServiceImpl.java index 0e157cd4..5f11a266 100644 --- a/backend/src/main/java/com/yfd/platform/system/service/impl/UserServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/system/service/impl/UserServiceImpl.java @@ -22,6 +22,7 @@ import com.yfd.platform.system.domain.SysRole; import com.yfd.platform.system.domain.SysUser; import com.yfd.platform.system.mapper.SysRoleMapper; import com.yfd.platform.system.mapper.SysUserMapper; +import com.yfd.platform.system.service.IAdminAuthService; import com.yfd.platform.system.service.IUserService; import com.yfd.platform.utils.FileUtil; import com.yfd.platform.utils.PasswordGenerator; @@ -80,6 +81,9 @@ public class UserServiceImpl extends ServiceImpl impleme @Resource private SysUserDataScopeMapper sysUserDataScopeMapper; + @Resource + private IAdminAuthService adminAuthService; + /********************************** * 用途说明:获取当前用户账号及名称 * 参数说明 @@ -162,7 +166,7 @@ public class UserServiceImpl extends ServiceImpl impleme //账号有效 sysUser.setStatus(1); //判断注册的登录账号是否存在 - if (isExistAccount(sysUser.getUsername())) { + if (isExistAccount(sysUser.getUsername(),sysUser.getTenantId() )) { //新增用户 boolean ok = this.save(sysUser); //新增用户分配权限 @@ -419,7 +423,7 @@ public class UserServiceImpl extends ServiceImpl impleme //账号头像存储地址 String imgName = fileSpaceProperties.getSystem() + File.separator + "user" + File.separator + sysUser.getAvatar(); - if ("admin".equals(sysUser.getUsername())) { + if (adminAuthService.isManagedAdminUsername(sysUser.getUsername())) { return false; } else { boolean isOk = this.removeById(id); @@ -446,31 +450,30 @@ public class UserServiceImpl extends ServiceImpl impleme ************************************/ @Override public ResponseResult resetPassword(String id) throws Exception { - //根据当前用户id 查询角色表的级别 currentUser.getUser() 获取当前用户id - String level = sysUserMapper.getMaxLevel(id); - //判断是否获取级别 - if ("admin".equals(SecurityUtils.getCurrentUsername()) || StrUtil.isNotEmpty(level)) { - //判断当前用户级别 管理员及以上权限 - if ("admin".equals(SecurityUtils.getCurrentUsername()) || Integer.parseInt(level) <= 2) { - SysUser sysUser = sysUserMapper.selectById(id); - UpdateWrapper updateWrapper = new UpdateWrapper<>(); - String password = PasswordGenerator.generateRandomPassword(sysUser.getUsername()); - //根据id 修改密码,密码修改时间,最近修改者,最近修改日期 将密码修改为 123456 - String cryptPassword = passwordEncoder.encode(password); - updateWrapper.eq("id", id).set("password", cryptPassword).set( - "pwdresettime", - new Timestamp(System.currentTimeMillis())).set( - "lastmodifydate", - new Timestamp(System.currentTimeMillis())).set( - "lastmodifier", getUsername()); - //是否修改成功 - this.update(updateWrapper); - return ResponseResult.successData(password); - } + if (hasAdminOperationPermission()) { + SysUser sysUser = sysUserMapper.selectById(id); + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + String password = PasswordGenerator.generateRandomPassword(sysUser.getUsername()); + //根据id 修改密码,密码修改时间,最近修改者,最近修改日期 + String cryptPassword = passwordEncoder.encode(password); + updateWrapper.eq("id", id).set("password", cryptPassword).set( + "pwdresettime", + new Timestamp(System.currentTimeMillis())).set( + "lastmodifydate", + new Timestamp(System.currentTimeMillis())).set( + "lastmodifier", getUsername()); + //是否修改成功 + this.update(updateWrapper); + return ResponseResult.successData(password); } return ResponseResult.error(); } + @Override + public List getSuperAdminUsernames() { + return adminAuthService.getSuperAdminUsernames(); + } + /*********************************** * 用途说明:设置账号状态(管理员) * 参数说明 @@ -481,10 +484,8 @@ public class UserServiceImpl extends ServiceImpl impleme @Override public boolean setStatus(String id, String status) { boolean isOk = false; - //根据当前用户id 查询角色表的级别 currentUser.getUser() 获取当前用户id - String level = sysUserMapper.getMaxLevel(id); //判断当前用户级别 管理员及以上权限 - if ("admin".equals(SecurityUtils.getCurrentUsername()) || Integer.parseInt(level) <= 2) { + if (hasAdminOperationPermission()) { UpdateWrapper updateWrapper = new UpdateWrapper<>(); //根据id修改用户状态,最近修改人,最近修改时间 updateWrapper.eq("id", id).set("status", status).set( @@ -497,6 +498,35 @@ public class UserServiceImpl extends ServiceImpl impleme return isOk; } + private boolean hasAdminOperationPermission() { + if (adminAuthService.isCurrentManagedAdmin()) { + return true; + } + String currentUserId = SecurityUtils.getUserId(); + String level = sysUserMapper.getMaxLevel(currentUserId); + Integer roleLevel = parseRoleLevel(level); + return roleLevel != null && roleLevel <= 2; + } + + private boolean isCurrentManagedAdmin() { + return adminAuthService.isCurrentManagedAdmin(); + } + + private boolean isManagedAdminUsername(String username) { + return adminAuthService.isManagedAdminUsername(username); + } + + private Set getManagedAdminUsernames() { + return adminAuthService.getManagedAdminUsernames(); + } + + private Integer parseRoleLevel(String level) { + if (StrUtil.isBlank(level) || !StrUtil.isNumeric(level)) { + return null; + } + return Integer.parseInt(level); + } + /*********************************** * 用途说明:上传用户头像 * 参数说明 @@ -864,9 +894,9 @@ public class UserServiceImpl extends ServiceImpl impleme * account 登录名称 * 返回值说明: 重复返回 false 否则返回 true ************************************/ - private boolean isExistAccount(String username) { + private boolean isExistAccount(String username,String tenantId) { QueryWrapper queryWrapper = new QueryWrapper<>(); - if (this.list(queryWrapper.eq("username", username)).size() > 0) { + if (this.list(queryWrapper.eq("username", username).eq("TENANT_ID", tenantId)).size() > 0) { //判断 查询登录账号 结果集是否为null 重复返回 false 否则返回 tree return false; } else { diff --git a/backend/src/main/java/com/yfd/platform/utils/CodeToNameMetadataBo.java b/backend/src/main/java/com/yfd/platform/utils/CodeToNameMetadataBo.java new file mode 100644 index 00000000..5f8ba742 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/utils/CodeToNameMetadataBo.java @@ -0,0 +1,94 @@ +package com.yfd.platform.utils; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 代码转名称元数据配置 + *

+ * 用于配置 VO 中某个 code 字段如何转换为对应的 name 字段, + * 支持静态字典(SYS_DICTIONARY / SYS_DICTIONARY_ITEMS)和动态字典(业务表)。 + *

+ * + *
+ * 使用示例:
+ * // 静态字典:将 vo.typeCode 转为 vo.typeName,字典编码为 "PROJECT_TYPE"
+ * CodeToNameMetadataBo.builder()
+ *     .codeProperty("typeCode")
+ *     .modifyProperty("typeName")
+ *     .dictType("STATIC")
+ *     .dictSource("PROJECT_TYPE")
+ *     .build();
+ *
+ * // 动态字典:将 vo.engCode 转为 vo.engName,查 SD_ENGINFO_B_H 表
+ * CodeToNameMetadataBo.builder()
+ *     .codeProperty("engCode")
+ *     .modifyProperty("engName")
+ *     .dictType("DYNAMIC")
+ *     .dictSource("SD_ENGINFO_B_H")
+ *     .codeColumn("STCD")
+ *     .nameColumn("ENNM")
+ *     .filter("NVL(IS_DELETED, 0) = 0")
+ *     .build();
+ * 
+ * + * @author Generated + * @since 2025-05-18 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CodeToNameMetadataBo implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 编码属性名(VO 中存放 code 的字段名) + */ + private String codeProperty; + + /** + * 名称属性名(VO 中需要设置 name 的字段名) + */ + private String modifyProperty; + + /** + * 字典类型:STATIC(静态字典)或 DYNAMIC(动态字典) + */ + private String dictType; + + /** + * 字典来源: + * - 静态字典:SYS_DICTIONARY 表中的 DICTCODE + * - 动态字典:业务表名 + */ + private String dictSource; + + /** + * 动态字典:表中编码列名(静态字典不需要) + */ + private String codeColumn; + + /** + * 动态字典:表中名称列名(静态字典不需要) + */ + private String nameColumn; + + /** + * 额外过滤条件(可选) + * - 静态字典:SYS_DICTIONARY_ITEMS 的额外 WHERE 条件 + * - 动态字典:业务表的额外 WHERE 条件 + */ + private String filter; + + /** + * 是否多选(code 值为逗号分隔的多个编码) + */ + @Builder.Default + private boolean isMulti = false; +} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/utils/DictCodeToNameConverter.java b/backend/src/main/java/com/yfd/platform/utils/DictCodeToNameConverter.java new file mode 100644 index 00000000..363d4f92 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/utils/DictCodeToNameConverter.java @@ -0,0 +1,391 @@ +package com.yfd.platform.utils; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.common.MicroservicDynamicSQLMapper; +import com.yfd.platform.system.domain.SysDictionary; +import com.yfd.platform.system.domain.SysDictionaryItems; +import com.yfd.platform.system.mapper.SysDictionaryItemsMapper; +import com.yfd.platform.system.mapper.SysDictionaryMapper; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Field; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * 字典代码转名称转换器 + *

+ * 支持静态字典(SYS_DICTIONARY / SYS_DICTIONARY_ITEMS)和动态字典(业务表查询), + * 将 VO 中的 code 字段值转换为对应的 name 字段值。 + *

+ * + *

使用方式

+ *
+ * // 1. 在 ServiceImpl 中注入
+ * @Resource
+ * private DictCodeToNameConverter dictCodeToNameConverter;
+ *
+ * // 2. 定义元数据列表(通常放在 static 静态代码块中)
+ * private static final List<CodeToNameMetadataBo> CODE_TO_NAME_META_LIST = List.of(
+ *     CodeToNameMetadataBo.builder()
+ *         .codeProperty("stationType")
+ *         .modifyProperty("stationTypeName")
+ *         .dictType("STATIC")
+ *         .dictSource("STATION_TYPE")
+ *         .build(),
+ *     CodeToNameMetadataBo.builder()
+ *         .codeProperty("engCode")
+ *         .modifyProperty("engName")
+ *         .dictType("DYNAMIC")
+ *         .dictSource("SD_ENGINFO_B_H")
+ *         .codeColumn("STCD")
+ *         .nameColumn("ENNM")
+ *         .filter("NVL(IS_DELETED, 0) = 0")
+ *         .build()
+ * );
+ *
+ * // 3. 在查询方法中调用转换
+ * public DataSourceResult<MyVo> queryList(DataSourceRequest request) {
+ *     // ... 查询数据得到 voList ...
+ *     dictCodeToNameConverter.convertCodeToName(voList, CODE_TO_NAME_META_LIST);
+ *     // ... 返回结果 ...
+ * }
+ * 
+ * + * @author Generated + * @since 2025-05-18 + */ +@Slf4j +@Component +public class DictCodeToNameConverter { + + @Resource + private SysDictionaryMapper sysDictionaryMapper; + + @Resource + private SysDictionaryItemsMapper sysDictionaryItemsMapper; + + @Resource + private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; + + /** + * 静态字典缓存:dictCode -> Map + */ + private final Map> staticDictCache = new ConcurrentHashMap<>(); + + /** + * 动态字典缓存:缓存key -> Map + */ + private final Map> dynamicDictCache = new ConcurrentHashMap<>(); + + /** + * 批量转换:根据元数据配置,将 VO 列表中的 code 字段转换为对应的 name 字段 + * + * @param voList VO 对象列表 + * @param metadataList 元数据配置列表 + * @param VO 类型 + */ + public void convertCodeToName(List voList, List metadataList) { + if (voList == null || voList.isEmpty() || metadataList == null || metadataList.isEmpty()) { + return; + } + + for (CodeToNameMetadataBo metadata : metadataList) { + try { + Map codeNameMap = loadCodeNameMap(metadata); + if (codeNameMap.isEmpty()) { + continue; + } + applyCodeToName(voList, metadata, codeNameMap); + } catch (Exception e) { + log.error("字典转换失败: codeProperty={}, dictSource={}", metadata.getCodeProperty(), metadata.getDictSource(), e); + } + } + } + + /** + * 分页结果转换:将 Page 中所有记录的 code 字段转换为对应的 name 字段 + * + *
+     * 使用示例:
+     * Page<SdHbrvDic> page = hbrvDicService.queryPageList(...);
+     * dictCodeToNameConverter.convertCodeToName(page, CODE_TO_NAME_META_LIST);
+     * 
+ * + * @param page 分页对象 + * @param metadataList 元数据配置列表 + * @param VO 类型 + */ + public void convertCodeToName(Page page, List metadataList) { + if (page == null || page.getRecords() == null || page.getRecords().isEmpty()) { + return; + } + convertCodeToName(page.getRecords(), metadataList); + } + + /** + * 单个对象转换:将单个对象的 code 字段转换为对应的 name 字段 + * + *
+     * 使用示例:
+     * SdHbrvDic hbrvDic = hbrvDicService.getById(hbrvcd);
+     * dictCodeToNameConverter.convertCodeToName(hbrvDic, CODE_TO_NAME_META_LIST);
+     * 
+ * + * @param obj 单个对象 + * @param metadataList 元数据配置列表 + * @param VO 类型 + */ + public void convertCodeToName(T obj, List metadataList) { + if (obj == null || metadataList == null || metadataList.isEmpty()) { + return; + } + convertCodeToName(Collections.singletonList(obj), metadataList); + } + + /** + * 加载静态字典映射 + * + * @param dictCode 字典编码 + * @return Map + */ + public Map loadStaticDictMap(String dictCode) { + return staticDictCache.computeIfAbsent(dictCode, key -> { + Map map = new LinkedHashMap<>(); + try { + SysDictionary dict = sysDictionaryMapper.selectOne( + new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() + .eq(SysDictionary::getDictCode, key) + ); + if (dict == null) { + log.warn("静态字典未找到: dictCode={}", key); + return map; + } + List items = sysDictionaryItemsMapper.selectList( + new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper() + .eq(SysDictionaryItems::getDictId, dict.getId()) + .orderByAsc(SysDictionaryItems::getOrderNo) + ); + for (SysDictionaryItems item : items) { + if (StrUtil.isNotBlank(item.getItemCode())) { + map.put(item.getItemCode(), StrUtil.nullToDefault(item.getDictName(), item.getItemCode())); + } + } + } catch (Exception e) { + log.error("加载静态字典失败: dictCode={}", key, e); + } + return map; + }); + } + + /** + * 加载动态字典映射(从业务表查询) + * + * @param tableName 表名 + * @param codeColumn 编码列名 + * @param nameColumn 名称列名 + * @param filter 额外过滤条件 + * @return Map + */ + public Map loadDynamicDictMap(String tableName, String codeColumn, String nameColumn, String filter) { + String cacheKey = tableName + "|" + codeColumn + "|" + nameColumn + "|" + StrUtil.nullToDefault(filter, ""); + return dynamicDictCache.computeIfAbsent(cacheKey, key -> { + Map map = new LinkedHashMap<>(); + try { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ").append(codeColumn).append(" AS code, ") + .append(nameColumn).append(" AS name ") + .append("FROM ").append(tableName) + .append(" WHERE 1=1 "); + if (StrUtil.isNotBlank(filter)) { + sql.append("AND ").append(filter).append(" "); + } + Map params = new HashMap<>(); + List> rows = microservicDynamicSQLMapper.getAllList(sql.toString(), params); + for (Map row : rows) { + String code = Objects.toString(row.get("CODE"), null); + String name = Objects.toString(row.get("NAME"), null); + if (StrUtil.isNotBlank(code)) { + map.put(code, StrUtil.nullToDefault(name, code)); + } + } + } catch (Exception e) { + log.error("加载动态字典失败: tableName={}", tableName, e); + } + return map; + }); + } + + /** + * 根据元数据加载 code->name 映射 + */ + private Map loadCodeNameMap(CodeToNameMetadataBo metadata) { + if ("STATIC".equalsIgnoreCase(metadata.getDictType())) { + return loadStaticDictMap(metadata.getDictSource()); + } else if ("DYNAMIC".equalsIgnoreCase(metadata.getDictType())) { + return loadDynamicDictMap( + metadata.getDictSource(), + metadata.getCodeColumn(), + metadata.getNameColumn(), + metadata.getFilter() + ); + } + log.warn("未知字典类型: dictType={}", metadata.getDictType()); + return Collections.emptyMap(); + } + + /** + * 将 code->name 映射应用到 VO 列表 + */ + private void applyCodeToName(List voList, CodeToNameMetadataBo metadata, Map codeNameMap) { + for (T vo : voList) { + try { + String codeValue = getFieldValue(vo, metadata.getCodeProperty()); + if (StrUtil.isBlank(codeValue)) { + continue; + } + + String nameValue; + if (metadata.isMulti()) { + // 多选:逗号分隔的多个code + nameValue = Arrays.stream(codeValue.split(",")) + .map(String::trim) + .filter(StrUtil::isNotBlank) + .map(c -> codeNameMap.getOrDefault(c, c)) + .collect(Collectors.joining(",")); + } else { + nameValue = codeNameMap.getOrDefault(codeValue.trim(), codeValue); + } + setFieldValue(vo, metadata.getModifyProperty(), nameValue); + } catch (Exception e) { + log.debug("字段转换跳过: vo={}, codeProperty={}", vo.getClass().getSimpleName(), metadata.getCodeProperty(), e); + } + } + } + + /** + * 清除所有缓存 + */ + public void clearCache() { + staticDictCache.clear(); + dynamicDictCache.clear(); + } + + /** + * 清除指定静态字典缓存 + */ + public void clearStaticDictCache(String dictCode) { + staticDictCache.remove(dictCode); + } + + /** + * 清除指定动态字典缓存 + */ + public void clearDynamicDictCache(String tableName, String codeColumn, String nameColumn, String filter) { + String cacheKey = tableName + "|" + codeColumn + "|" + nameColumn + "|" + StrUtil.nullToDefault(filter, ""); + dynamicDictCache.remove(cacheKey); + } + + // ==================== 反射工具方法 ==================== + + /** + * 通过反射获取对象的字段值(转为字符串),支持驼峰命名 + */ + private String getFieldValue(T obj, String fieldName) { + try { + Field field = findField(obj.getClass(), fieldName); + if (field == null) { + return null; + } + field.setAccessible(true); + Object value = field.get(obj); + return value != null ? value.toString() : null; + } catch (Exception e) { + return null; + } + } + + /** + * 通过反射设置对象的字段值,支持驼峰命名 + */ + private void setFieldValue(T obj, String fieldName, String value) { + try { + Field field = findField(obj.getClass(), fieldName); + if (field == null) { + return; + } + field.setAccessible(true); + field.set(obj, value); + } catch (Exception ignored) { + // 忽略设置失败 + } + } + + /** + * 查找字段(忽略大小写,支持驼峰和下划线变体),递归查找父类 + */ + private Field findField(Class clazz, String fieldName) { + if (clazz == null || clazz == Object.class) { + return null; + } + // 先精确匹配 + for (Field field : clazz.getDeclaredFields()) { + if (field.getName().equals(fieldName)) { + return field; + } + } + // 忽略大小写匹配 + for (Field field : clazz.getDeclaredFields()) { + if (field.getName().equalsIgnoreCase(fieldName)) { + return field; + } + } + // 驼峰-下划线互转匹配 + String camelName = underlineToCamel(fieldName); + String underlineName = camelToUnderline(fieldName); + for (Field field : clazz.getDeclaredFields()) { + String fName = field.getName(); + if (fName.equalsIgnoreCase(camelName) || fName.equalsIgnoreCase(underlineName)) { + return field; + } + } + return findField(clazz.getSuperclass(), fieldName); + } + + private String underlineToCamel(String str) { + if (StrUtil.isBlank(str) || !str.contains("_")) { + return str; + } + StringBuilder sb = new StringBuilder(); + boolean upper = false; + for (char c : str.toCharArray()) { + if (c == '_') { + upper = true; + } else { + sb.append(upper ? Character.toUpperCase(c) : c); + upper = false; + } + } + return sb.toString(); + } + + private String camelToUnderline(String str) { + if (StrUtil.isBlank(str)) { + return str; + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (Character.isUpperCase(c)) { + sb.append('_').append(Character.toLowerCase(c)); + } else { + sb.append(c); + } + } + return sb.toString(); + } +} \ No newline at end of file diff --git a/backend/src/main/resources/mapper/data/FishStatisticsMapper.xml b/backend/src/main/resources/mapper/data/FishStatisticsMapper.xml index 61f193c2..6099458b 100644 --- a/backend/src/main/resources/mapper/data/FishStatisticsMapper.xml +++ b/backend/src/main/resources/mapper/data/FishStatisticsMapper.xml @@ -76,7 +76,7 @@ ON sud.ORG_ID = rr.ROOT_RVCD JOIN SD_ENGINFO_B_H e ON e.REACHCD = rr.DESC_RVCD - AND e.USFL = 1 +-- AND e.USFL = 1 JOIN river_display r ON e.REACHCD = r.RVCD WHERE su.STATUS = 1 @@ -98,7 +98,7 @@ AND sud.ORG_TYPE = 'STATION' JOIN SD_ENGINFO_B_H e ON sud.ORG_ID = e.STCD - AND e.USFL = 1 +-- AND e.USFL = 1 JOIN river_display r ON e.REACHCD = r.RVCD WHERE su.STATUS = 1 diff --git a/backend/src/main/resources/mapper/qgc_base/SdRvcdDicMapper.xml b/backend/src/main/resources/mapper/qgc_base/SdRvcdDicMapper.xml index 504dcc0b..3d40173f 100644 --- a/backend/src/main/resources/mapper/qgc_base/SdRvcdDicMapper.xml +++ b/backend/src/main/resources/mapper/qgc_base/SdRvcdDicMapper.xml @@ -212,5 +212,30 @@ ORDER BY t.ORDER_PATH ASC, t.RVCD ASC + diff --git a/frontend-sjtb/.eslintrc.js b/frontend-sjtb/.eslintrc.js index d7878cc2..061b63d5 100644 --- a/frontend-sjtb/.eslintrc.js +++ b/frontend-sjtb/.eslintrc.js @@ -24,6 +24,7 @@ module.exports = { }, plugins: ['vue', '@typescript-eslint'], rules: { + "no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], 'vue/multi-word-component-names': 'off', '@typescript-eslint/no-empty-function': 'off', // 关闭空方法检查 '@typescript-eslint/no-explicit-any': 'off', // 关闭any类型的警告 diff --git a/frontend-sjtb/public/file/过鱼设施数据填报操作手册.docx b/frontend-sjtb/public/file/过鱼设施数据填报操作手册.docx index f3d2e60d..536eb442 100644 Binary files a/frontend-sjtb/public/file/过鱼设施数据填报操作手册.docx and b/frontend-sjtb/public/file/过鱼设施数据填报操作手册.docx differ diff --git a/frontend-sjtb/src/api/changePassWord/index.ts b/frontend-sjtb/src/api/changePassWord/index.ts new file mode 100644 index 00000000..727c442f --- /dev/null +++ b/frontend-sjtb/src/api/changePassWord/index.ts @@ -0,0 +1,9 @@ +import request from '@/utils/request'; +//修改密码 +export function updatePassword(params:any) { + return request({ + url: '/user/updatePassword', + method: 'post', + data: params + }); +} \ No newline at end of file diff --git a/frontend-sjtb/src/api/shuidiankaifa/index.ts b/frontend-sjtb/src/api/shuidiankaifa/index.ts deleted file mode 100644 index c46f8d25..00000000 --- a/frontend-sjtb/src/api/shuidiankaifa/index.ts +++ /dev/null @@ -1,62 +0,0 @@ -import request from '@/utils/request'; - -/** - * 获取 Kendo 列表数据(支持聚合和分组) - * @param params 过滤条件 - * @param sortConfig 排序配置 - */ -export function getKendoList(params: any, sortConfig?: any[]) { - return request({ - url: '/dec-lygk-base-server/base/vmsstbprpt/GetKendoList', - method: 'post', - data: { - filters: params, - sorts: sortConfig || [] - } - }); -} - -/** - * 获取自定义 Kendo 列表数据(用于全基地模式) - * @param params 过滤条件 - * @param sortConfig 排序配置 - */ -export function getKendoListCust(params: any, sortConfig?: any[]) { - return request({ - url: '/dec-lygk-base-server/base/vmsstbprpt/GetKendoListCust', - method: 'post', - data: { - filters: params, - sorts: sortConfig || [] - } - }); -} - -/** - * 获取介绍信息(用于 other 类型排序) - * @param filters 过滤条件 - * @param sorts 排序配置 - * @param needTotal 是否需要总数 - * @param fields 返回字段 - * @param defaultSort 默认排序 - */ -export function getIntroduce( - filters: any[], - sorts?: any[], - needTotal?: boolean, - fields?: string[], - defaultSort?: any -) { - return request({ - url: '/dec-lygk-base-server/base/introduce/getIntroduce', - method: 'post', - data: { - logic: 'and', - filters: filters, - sorts: sorts || [], - needTotal: needTotal || false, - fields: fields || [], - defaultSort: defaultSort - } - }); -} diff --git a/frontend-sjtb/src/api/system/map/ConfigManagement/index.ts b/frontend-sjtb/src/api/system/map/ConfigManagement/index.ts deleted file mode 100644 index d9549aed..00000000 --- a/frontend-sjtb/src/api/system/map/ConfigManagement/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -import request from '@/utils/request'; - -// 获取所有沿程配置数据 -export function getAllConfigTree(data: any) { - return request({ - url: '/api/dec-lygk-base-server/base/msalongb/GetKendoList', - method: 'post', - data: data - }); -} -// 保存沿程配置 -export function saveBaseWbsb(data: any) { - return request({ - url: '/api/dec-lygk-base-server/base/wbsb/addOrUpdate', - method: 'post', - data: data - }); -} -// 删除沿程配置 -export function deleteBaseWbsb(data: any) { - return request({ - url: '/api/dec-lygk-base-server/base/wbsb/delete', - method: 'get', - params: data - }); -} diff --git a/frontend-sjtb/src/api/system/map/LayerManagement/index.ts b/frontend-sjtb/src/api/system/map/LayerManagement/index.ts deleted file mode 100644 index b24fe72d..00000000 --- a/frontend-sjtb/src/api/system/map/LayerManagement/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -import request from '@/utils/request'; - -// 获取所有地图 图层树 -export function getAllMapLayerTree(data: any) { - return request({ - url: '/api/wmp-sys-server/mapLayer/getAllMapLayerTree', - method: 'post', - data: data - }); -} -// 保存地图 图层 -export function saveMapLayer(data: any) { - return request({ - url: '/api/wmp-sys-server/mapLayer/save', - method: 'post', - data: data - }); -} -// 删除地图 图层 -export function deleteMapLayer(data: any) { - return request({ - url: '/api/wmp-sys-server/mapLayer/delete', - method: 'post', - data: data - }); -} -// 获取所有地图 图层树 -export function getAllMapLayerParentIdTree(data: any) { - return request({ - url: '/api/wmp-sys-server/mapLayer/getAllMapLayerTree', - method: 'post', - data: data - }); -} diff --git a/frontend-sjtb/src/api/system/map/LegendStructure/index.ts b/frontend-sjtb/src/api/system/map/LegendStructure/index.ts deleted file mode 100644 index 0ba70188..00000000 --- a/frontend-sjtb/src/api/system/map/LegendStructure/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -import request from '@/utils/request'; - -// 获取所有地图 图例树 -export function getAllMapLegendTree(data: any) { - return request({ - url: '/api/wmp-sys-server/mapLegend/GetKendoList', - method: 'post', - data: data - }); -} -// 保存地图 图例 -export function saveMapLegend(data: any) { - return request({ - url: '/api/wmp-sys-server/mapLegend/save', - method: 'post', - data: data - }); -} -// 删除地图 图例 -export function deleteMapLegend(data: any) { - return request({ - url: '/api/wmp-sys-server/mapLegend/delete', - method: 'post', - data: data - }); -} - -// 获取所有地图 图例树 -export function getAllMapLegendParentIdTree(data: any) { - return request({ - url: '/api/wmp-sys-server/mapLegend/getAllMapLegendTree', - method: 'get', - params: data - }); -} diff --git a/frontend-sjtb/src/api/system/map/TiltPhotoManagement/index.ts b/frontend-sjtb/src/api/system/map/TiltPhotoManagement/index.ts deleted file mode 100644 index b6ee61fc..00000000 --- a/frontend-sjtb/src/api/system/map/TiltPhotoManagement/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -import request from '@/utils/request'; - -// 获取所有倾斜摄影 -export function getAllTiltPhotoTree(data: any) { - return request({ - url: '/api/wmp-sys-server/sys/oblique/GetKendoListCust', - method: 'post', - data: data - }); -} -// 保存倾斜摄影 -export function saveTiltPhoto(data: any) { - return request({ - url: '/api/wmp-sys-server/sys/oblique/addOrUpdate', - method: 'post', - data: data - }); -} -// 删除倾斜摄影 -export function deleteTiltPhoto(data: any) { - return request({ - url: '/api/wmp-sys-server/sys/oblique/delete', - method: 'get', - params: data - }); -} diff --git a/frontend-sjtb/src/assets/401_images/401.gif b/frontend-sjtb/src/assets/401_images/401.gif deleted file mode 100644 index cd6e0d94..00000000 Binary files a/frontend-sjtb/src/assets/401_images/401.gif and /dev/null differ diff --git a/frontend-sjtb/src/assets/404_images/404.png b/frontend-sjtb/src/assets/404_images/404.png deleted file mode 100644 index 3d8e2305..00000000 Binary files a/frontend-sjtb/src/assets/404_images/404.png and /dev/null differ diff --git a/frontend-sjtb/src/assets/404_images/404_cloud.png b/frontend-sjtb/src/assets/404_images/404_cloud.png deleted file mode 100644 index c6281d09..00000000 Binary files a/frontend-sjtb/src/assets/404_images/404_cloud.png and /dev/null differ diff --git a/frontend-sjtb/src/assets/components/审批通过.png b/frontend-sjtb/src/assets/components/审批通过.png deleted file mode 100644 index 53cecf20..00000000 Binary files a/frontend-sjtb/src/assets/components/审批通过.png and /dev/null differ diff --git a/frontend-sjtb/src/layout/components/Navbar.vue b/frontend-sjtb/src/layout/components/Navbar.vue index 60febd65..0e72ea71 100644 --- a/frontend-sjtb/src/layout/components/Navbar.vue +++ b/frontend-sjtb/src/layout/components/Navbar.vue @@ -1,18 +1,17 @@ + diff --git a/frontend-sjtb/src/main.ts b/frontend-sjtb/src/main.ts index 48e4d1a4..66b5af4b 100644 --- a/frontend-sjtb/src/main.ts +++ b/frontend-sjtb/src/main.ts @@ -14,17 +14,11 @@ import dayjs from 'dayjs'; // ant 中文语言 import 'dayjs/locale/zh-cn'; // @ts-ignore import 'virtual:svg-icons-register'; -// 3d地图 -import * as Cesium from 'cesium'; -import 'cesium/Build/Cesium/Widgets/widgets.css'; - // 国际化 import i18n from '@/lang/index'; import '@/styles/index.scss'; import 'element-plus/theme-chalk/index.css'; -//import 'element-plus/theme-chalk/dark/css-vars.css'; -import WujieVue from 'wujie-vue3'; const app = createApp(App); // 自定义指令 @@ -48,7 +42,5 @@ app .use(router) .use(ElementPlus) .use(Antd) - .use(Antd) - .use(WujieVue) .use(i18n) .mount('#app'); diff --git a/frontend-sjtb/src/permission.ts b/frontend-sjtb/src/permission.ts index 7e9fa5df..8a26aa43 100644 --- a/frontend-sjtb/src/permission.ts +++ b/frontend-sjtb/src/permission.ts @@ -52,7 +52,6 @@ function findFirstAvailableRoute(routes: any[]): string | undefined { router.beforeEach(async (to, from, next) => { NProgress.start(); const userStore = useUserStoreHook(); - if (userStore.Token) { // 登录成功,跳转到首页 if (to.path === '/login') { @@ -60,6 +59,15 @@ router.beforeEach(async (to, from, next) => { next({ path: '/' }); NProgress.done(); return; + } else if ( + (to.path === '/401' || to.path === '/404') && + from.matched.length === 0 && + !from.name + ) { + // 拦截直接 URL 访问错误页面,仅允许内部重定向触发 + next({ path: '/' }); + NProgress.done(); + return; } else { const hasGetUserInfo = userStore.roles.length > 0; if (hasGetUserInfo) { diff --git a/frontend-sjtb/src/router/index.ts b/frontend-sjtb/src/router/index.ts index 84eaef81..75cf3d8f 100644 --- a/frontend-sjtb/src/router/index.ts +++ b/frontend-sjtb/src/router/index.ts @@ -35,12 +35,7 @@ export const constantRoutes: RouteRecordRaw[] = [ path: '/401', component: () => import('@/views/error-page/401.vue'), meta: { hidden: true } - }, - { - path: '/changePassword', - component: () => import('@/views/changePassword/index.vue'), - meta: { hidden: true } - }, + } ]; // 创建路由 diff --git a/frontend-sjtb/src/utils/request.ts b/frontend-sjtb/src/utils/request.ts index 85febfcf..f7c65b69 100644 --- a/frontend-sjtb/src/utils/request.ts +++ b/frontend-sjtb/src/utils/request.ts @@ -19,27 +19,10 @@ service.interceptors.request.use( `Expected 'config' and 'config.headers' not to be undefined` ); } - config.headers.tenant_id = '4'; - if ( - config.url.includes('/dec-lygk-base-server') || - config.url.includes('/wmp-env-server') || - config.url.includes('/wmp-sys-server') || - config.url.includes('/wmp-eng-server') || - config.url.includes('/dec-modules-usm-springcloud-starter') || - config.url.includes('/wmp-swqx-server') - ) { - config.headers._appid = '974975A6-47FD-4C04-9ACD-68938D2992BD'; - config.headers._isolateid = '5b34aecb-adfb-4dfc-ad95-21505a9eb388'; - config.headers._platformid = '31e6d13f-c359-4a19-8e67-b6f868f2401b'; - config.headers._sysid = '10EC2E0B-AEA9-4757-83A2-201BA1BC54E9'; - config.headers.authorization = - 'bearer aa5be16b-d1a3-4b93-9886-b2490025c7d6'; - config.baseURL = '/'; - } else { - const user = useUserStoreHook(); - if (user.Token) { - config.headers.token = getToken(); - } + config.headers.tenant_id = '4'; + const user = useUserStoreHook(); + if (user.Token) { + config.headers.token = getToken(); } return config; }, diff --git a/frontend-sjtb/src/views/error-page/401.vue b/frontend-sjtb/src/views/error-page/401.vue index 61c6ae60..2e393696 100644 --- a/frontend-sjtb/src/views/error-page/401.vue +++ b/frontend-sjtb/src/views/error-page/401.vue @@ -1,114 +1,48 @@ - - - - - - diff --git a/frontend-sjtb/src/views/error-page/404.vue b/frontend-sjtb/src/views/error-page/404.vue index 85594047..567066a4 100644 --- a/frontend-sjtb/src/views/error-page/404.vue +++ b/frontend-sjtb/src/views/error-page/404.vue @@ -1,280 +1,47 @@ - - - - - - diff --git a/frontend-sjtb/src/views/login/index.vue b/frontend-sjtb/src/views/login/index.vue index 642e1f5c..68f0f0f5 100644 --- a/frontend-sjtb/src/views/login/index.vue +++ b/frontend-sjtb/src/views/login/index.vue @@ -10,7 +10,7 @@
-

{{ $t('login.titleSjtb') }}

+

{{ $t("login.titleSjtb") }}

@@ -49,6 +49,7 @@ v-model:value="forgotPasswordForm.captcha" placeholder="请输入验证码" size="large" + autocomplete="current-captcha" class="captcha-input" > @@ -76,6 +75,7 @@ @@ -88,6 +88,7 @@ @@ -130,6 +131,7 @@ type="text" placeholder="请输入用户账号/手机号" size="large" + autocomplete="current-username" > diff --git a/frontend-sjtb/src/views/register/index.vue b/frontend-sjtb/src/views/register/index.vue index 6a1cf445..a5b10809 100644 --- a/frontend-sjtb/src/views/register/index.vue +++ b/frontend-sjtb/src/views/register/index.vue @@ -29,6 +29,7 @@ @@ -41,6 +42,7 @@ > @@ -49,6 +51,7 @@ diff --git a/frontend-sjtb/src/views/shuJuTianBao/guoYuDaoShuTongJi/guoYuDaoShuTongJiSearch.vue b/frontend-sjtb/src/views/shuJuTianBao/guoYuDaoShuTongJi/guoYuDaoShuTongJiSearch.vue index f32f79f9..00daca1e 100644 --- a/frontend-sjtb/src/views/shuJuTianBao/guoYuDaoShuTongJi/guoYuDaoShuTongJiSearch.vue +++ b/frontend-sjtb/src/views/shuJuTianBao/guoYuDaoShuTongJi/guoYuDaoShuTongJiSearch.vue @@ -25,8 +25,7 @@ diff --git a/frontend/src/main.ts b/frontend/src/main.ts index 48e4d1a4..8b4cee37 100644 --- a/frontend/src/main.ts +++ b/frontend/src/main.ts @@ -23,8 +23,6 @@ import i18n from '@/lang/index'; import '@/styles/index.scss'; import 'element-plus/theme-chalk/index.css'; -//import 'element-plus/theme-chalk/dark/css-vars.css'; -import WujieVue from 'wujie-vue3'; const app = createApp(App); // 自定义指令 @@ -48,7 +46,5 @@ app .use(router) .use(ElementPlus) .use(Antd) - .use(Antd) - .use(WujieVue) .use(i18n) .mount('#app'); diff --git a/frontend/src/modules/DongWuJiuZhuZhan/JiuZhuZhanQingKuangJieShao.vue b/frontend/src/modules/DongWuJiuZhuZhan/JiuZhuZhanQingKuangJieShao.vue index e1ac0ce1..d65599df 100644 --- a/frontend/src/modules/DongWuJiuZhuZhan/JiuZhuZhanQingKuangJieShao.vue +++ b/frontend/src/modules/DongWuJiuZhuZhan/JiuZhuZhanQingKuangJieShao.vue @@ -1,76 +1,94 @@ \ No newline at end of file + diff --git a/frontend/src/modules/EnvironmentalQuality/TwoLayers/EnvironmentalQualityTwoLayers.vue b/frontend/src/modules/EnvironmentalQuality/TwoLayers/EnvironmentalQualityTwoLayers.vue index ac7acf40..e871f270 100644 --- a/frontend/src/modules/EnvironmentalQuality/TwoLayers/EnvironmentalQualityTwoLayers.vue +++ b/frontend/src/modules/EnvironmentalQuality/TwoLayers/EnvironmentalQualityTwoLayers.vue @@ -596,7 +596,7 @@ const handleSearch = () => { // console.log( typeOne.value ) // console.log( formState.dtinType ) // console.log(typeOne.value == 'all' && formState.dtinType !='') - // debugger + // const filters: any[] = [ formState.dataDimensionVal != 'all' ? { field: 'baseId', @@ -660,7 +660,7 @@ const handleSearch = () => { // 刷新表格 tableRef.value?.getList(filter) if (kong.value) { - // debugger + // fetchPieData() } kong.value = true @@ -781,7 +781,7 @@ watch( () => props.typeOne, (newVal) => { typeOne.value = newVal - // debugger + // } ) @@ -798,7 +798,7 @@ watch( () => formState.types, (newType, oldType) => { if (!formState.dateValues || newType === oldType) return - // debugger + // const currentValue: any = formState.dateValues if (newType === 'year') { diff --git a/frontend/src/modules/EnvironmentalQuality/TwoLayers/HJMZDTwoLays.vue b/frontend/src/modules/EnvironmentalQuality/TwoLayers/HJMZDTwoLays.vue index 250a3217..d89fd1b2 100644 --- a/frontend/src/modules/EnvironmentalQuality/TwoLayers/HJMZDTwoLays.vue +++ b/frontend/src/modules/EnvironmentalQuality/TwoLayers/HJMZDTwoLays.vue @@ -564,7 +564,7 @@ watch( if (!stcd) { return; } - // debugger + // tableRef.value.tableData = []; getCol({ stcd, startTime, endTime }); }, diff --git a/frontend/src/modules/EnvironmentalQuality/index.vue b/frontend/src/modules/EnvironmentalQuality/index.vue index 2d3c4279..d2c9a511 100644 --- a/frontend/src/modules/EnvironmentalQuality/index.vue +++ b/frontend/src/modules/EnvironmentalQuality/index.vue @@ -319,7 +319,7 @@ const initChart = (): Promise => { const getEchartsData = async () => { // 1. 格式验证 const currentValue = datetimePicker.value.value; - // debugger + // if (select.value.value === 'year') { // 年度模式:验证是否为 YYYY 格式(4位数字) if (!/^\d{4}$/.test(currentValue)) { @@ -361,7 +361,7 @@ const getEchartsData = async () => { if( ! baseid.value){ return } - // debugger + // let params = { "filter": { "logic": "and", @@ -439,7 +439,7 @@ const getEchartsData = async () => { ] }; console.log('请求参数:', params); - // debugger + // // 4. 调用API并处理数据 loading.value = true; try { @@ -687,7 +687,7 @@ const updateChartData = (currentLabel: string, lastYearLabel: string) => { if (barData) { // 新增:获取对应的 baseid 或 rstcd const selectedId = chartDataIdMap.value[dataIndex] || ''; - // debugger + // clickedBarData.value = { name: barData.name.replace('\n', ''), // 去除换行符 current: barData.current, diff --git a/frontend/src/modules/GYZLLB/index.vue b/frontend/src/modules/GYZLLB/index.vue index fbc8e841..91f70884 100644 --- a/frontend/src/modules/GYZLLB/index.vue +++ b/frontend/src/modules/GYZLLB/index.vue @@ -714,7 +714,7 @@ const getechartsdata = async (yearOne: string) => { stopAutoPlay(); return; } - // debugger + // // 缓存全量数据 cachedApiData.value = responseData; currentYear.value = yearOne; diff --git a/frontend/src/modules/Ysdwjc/index.vue b/frontend/src/modules/Ysdwjc/index.vue index 63451fcc..76ad8bfa 100644 --- a/frontend/src/modules/Ysdwjc/index.vue +++ b/frontend/src/modules/Ysdwjc/index.vue @@ -1,320 +1,541 @@ - + \ No newline at end of file + diff --git a/frontend/src/modules/ZhenXiZhiWuYuanMod/Dwjzqk/index.vue b/frontend/src/modules/ZhenXiZhiWuYuanMod/Dwjzqk/index.vue index a04d568a..e23d04fc 100644 --- a/frontend/src/modules/ZhenXiZhiWuYuanMod/Dwjzqk/index.vue +++ b/frontend/src/modules/ZhenXiZhiWuYuanMod/Dwjzqk/index.vue @@ -1,56 +1,64 @@ \ No newline at end of file +:deep(.ant-empty-description){ + text-indent:0em !important; +} + diff --git a/frontend/src/modules/ZhenXiZhiWuYuanMod/ZhiWuYuanJianSheJiJieRuQingKuangBar/ZhiWuYuanDetailTable.vue b/frontend/src/modules/ZhenXiZhiWuYuanMod/ZhiWuYuanJianSheJiJieRuQingKuangBar/ZhiWuYuanDetailTable.vue new file mode 100644 index 00000000..5926aaf0 --- /dev/null +++ b/frontend/src/modules/ZhenXiZhiWuYuanMod/ZhiWuYuanJianSheJiJieRuQingKuangBar/ZhiWuYuanDetailTable.vue @@ -0,0 +1,293 @@ + + + + + diff --git a/frontend/src/modules/ZhenXiZhiWuYuanMod/ZhiWuYuanJianSheJiJieRuQingKuangBar/index.vue b/frontend/src/modules/ZhenXiZhiWuYuanMod/ZhiWuYuanJianSheJiJieRuQingKuangBar/index.vue index 0dc3fd67..2ace8474 100644 --- a/frontend/src/modules/ZhenXiZhiWuYuanMod/ZhiWuYuanJianSheJiJieRuQingKuangBar/index.vue +++ b/frontend/src/modules/ZhenXiZhiWuYuanMod/ZhiWuYuanJianSheJiJieRuQingKuangBar/index.vue @@ -1,135 +1,275 @@ \ No newline at end of file + +.chart-container { + width: 100%; + height: 100%; + display: block; + box-sizing: border-box; +} + diff --git a/frontend/src/modules/alongFishMod/TwoLayers/Yanchengyulei.vue b/frontend/src/modules/alongFishMod/TwoLayers/Yanchengyulei.vue new file mode 100644 index 00000000..8d7f6e9f --- /dev/null +++ b/frontend/src/modules/alongFishMod/TwoLayers/Yanchengyulei.vue @@ -0,0 +1,615 @@ + + + + + + diff --git a/frontend/src/modules/alongFishMod/index.vue b/frontend/src/modules/alongFishMod/index.vue index 91763f43..937433fa 100644 --- a/frontend/src/modules/alongFishMod/index.vue +++ b/frontend/src/modules/alongFishMod/index.vue @@ -1,209 +1,631 @@ - + \ No newline at end of file + +.empty-placeholder { + width: 100%; + min-height: 231px; + display: flex; + background: #fff; + flex-direction: column; + justify-content: center; + align-items: center; +} + +:deep(.ant-empty-description) { + text-indent: 0em !important; +} + diff --git a/frontend/src/modules/chuixiangshuiwenChangeMod/index.vue b/frontend/src/modules/chuixiangshuiwenChangeMod/index.vue index 0f04e34d..fb8619e4 100644 --- a/frontend/src/modules/chuixiangshuiwenChangeMod/index.vue +++ b/frontend/src/modules/chuixiangshuiwenChangeMod/index.vue @@ -37,7 +37,7 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue'; import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent'; import { getChuiXiangShuiWenTreeStcd, getCxswList } from '@/api/sw'; import { useModelStore } from '@/store/modules/model'; -import { useMapModalStore } from '@/store/modules/mapModal'; +// import { useMapModalStore } from '@/store/modules/mapModal'; import { MapClass } from '@/components/gis/map.class'; const modelStore = useModelStore(); @@ -356,7 +356,6 @@ const selectOptions = async () => { const data = { filter, sort }; const res = await getChuiXiangShuiWenTreeStcd(data); let dataOne = res?.data?.data || res.data; - if (dataOne.length > 0) { const treeData = dataOne.map(item => { return { @@ -547,7 +546,7 @@ const initChart = () => { )}-${lastDay} 23:59:59`; console.log(endTime); modelStore.modalVisible = true; - modelStore.params.sttp = 'WT'; + modelStore.params.sttp = 'WTRV'; modelStore.params.enfc = '1'; modelStore.title = stnm; // modelStore.isBasicEdit = true; @@ -663,53 +662,53 @@ const updateChart = () => { chartInstance.setOption(option, { notMerge: true }); }; -const handleChartClick = (params: any) => { - if (!params || !params.seriesName) return; +// const handleChartClick = (params: any) => { +// if (!params || !params.seriesName) return; - const matchMonth = params.seriesName.match(/\d+/); - const monthNum = matchMonth ? parseInt(matchMonth[0]) : 1; +// const matchMonth = params.seriesName.match(/\d+/); +// const monthNum = matchMonth ? parseInt(matchMonth[0]) : 1; - const year = - typeof datetimePicker.value.value === 'string' - ? parseInt(datetimePicker.value.value) - : datetimePicker.value.value; +// const year = +// typeof datetimePicker.value.value === 'string' +// ? parseInt(datetimePicker.value.value) +// : datetimePicker.value.value; - const startTime = `${year}-${String(monthNum).padStart(2, '0')}-01 00:00:00`; - const lastDay = new Date(year, monthNum, 0).getDate(); - const endTime = `${year}-${String(monthNum).padStart( - 2, - '0' - )}-${lastDay} 23:59:59`; +// const startTime = `${year}-${String(monthNum).padStart(2, '0')}-01 00:00:00`; +// const lastDay = new Date(year, monthNum, 0).getDate(); +// const endTime = `${year}-${String(monthNum).padStart( +// 2, +// '0' +// )}-${lastDay} 23:59:59`; - const currentStcd = select.value.value; - let currentStnm = ''; +// const currentStcd = select.value.value; +// let currentStnm = ''; - select.value.options.forEach((station: any) => { - station.children?.forEach((child: any) => { - if (child.value === currentStcd) { - currentStnm = child.title; - } - }); - }); +// select.value.options.forEach((station: any) => { +// station.children?.forEach((child: any) => { +// if (child.value === currentStcd) { +// currentStnm = child.title; +// } +// }); +// }); - import('@/store/modules/model').then(({ useModelStore }) => { - import('@/components/MapModal/setting.config').then(({ handleTabs }) => { - const modelStore = useModelStore(); +// import('@/store/modules/model').then(({ useModelStore }) => { +// import('@/components/MapModal/setting.config').then(({ handleTabs }) => { +// const modelStore = useModelStore(); - modelStore.params = { - sttp: 'WT', - stcd: currentStcd, - titleName: currentStnm, - enfc: '1', - timeRange: [startTime, endTime] - } as any; +// modelStore.params = { +// sttp: 'WT', +// stcd: currentStcd, +// titleName: currentStnm, +// enfc: '1', +// timeRange: [startTime, endTime] +// } as any; - modelStore.title = currentStnm ? `${currentStnm} ` : ''; - modelStore.tabList = handleTabs(modelStore.params); - modelStore.modalVisible = true; - }); - }); -}; +// modelStore.title = currentStnm ? `${currentStnm} ` : ''; +// modelStore.tabList = handleTabs(modelStore.params); +// modelStore.modalVisible = true; +// }); +// }); +// }; // ==================== 生命周期和监听 ==================== @@ -750,19 +749,9 @@ watch( // }, // { deep: true } // ); -const handlePanelChange1 = (data: any, type: string) => { +const handlePanelChange1 = (data: any) => { console.log('当前所有控件状态:', data); if (data.moreSelect && data.datetime) { - if (type == 'click') { - const mapClass = MapClass.getInstance(); - mapClass.flyTopanto( - [ - Number(data.selectedNodeExtra.lgtd), - Number(data.selectedNodeExtra.lttd) - ], - 15 - ); - } year.value = data.datetime; fetchChartData(data.moreSelect, data.datetime); } else { @@ -772,6 +761,16 @@ const handlePanelChange1 = (data: any, type: string) => { selected.value = {}; showemit.value = false; } + if (data?.selectedNodeExtra?.lttd && data?.selectedNodeExtra?.lgtd) { + const mapClass = MapClass.getInstance(); + mapClass.flyTopanto( + [ + Number(data.selectedNodeExtra.lgtd), + Number(data.selectedNodeExtra.lttd) + ], + 15 + ); + } }; diff --git a/frontend/src/modules/churukushuiwenMod/index.vue b/frontend/src/modules/churukushuiwenMod/index.vue index 71ff0fb7..388895b7 100644 --- a/frontend/src/modules/churukushuiwenMod/index.vue +++ b/frontend/src/modules/churukushuiwenMod/index.vue @@ -52,6 +52,7 @@ import SidePanelItem from '@/components/SidePanelItem/index.vue'; import { getVmsstbprpt, inOutOneGetKendoListCust } from '@/api/sw'; import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent'; import churukushuiwen from './churukushuiwen.vue'; +import { MapClass } from '@/components/gis/map.class'; // ==================== 组件基础配置 ==================== // 定义组件名(便于调试和递归) defineOptions({ @@ -608,10 +609,12 @@ const handleModalClose = () => { */ const handlePanelChange1 = (data: any, type: string) => { // TODO: 后续可扩展联动逻辑 - if (data.moreSelect) { + if (data.moreSelect && data.scopeDate) { paramsOne.value.value = data.moreSelect; - } - if (type == 'click') { + paramsOne.value.tm = data.scopeDate; + fetchChartData(); + } + if (data?.selectedNodeExtra?.lttd && data?.selectedNodeExtra?.lgtd) { const mapClass = MapClass.getInstance(); mapClass.flyTopanto( [ @@ -621,8 +624,6 @@ const handlePanelChange1 = (data: any, type: string) => { 13 ); } - paramsOne.value.tm = data.scopeDate; - fetchChartData(); }; /** @@ -695,7 +696,6 @@ const getselsectData = async () => { console.log('res', res); const data = res?.data?.data || res?.data; const obj: any = {}; - if (data) { // 将扁平数据转换为树形结构(按基地分组) data.map(e => { @@ -733,7 +733,6 @@ const getselsectData = async () => { return indexA - indexB; }); console.log('treeData', treeData); - // 更新下拉框选项 select.value.options = treeData; diff --git a/frontend/src/modules/fishSurvey/FishChangeTu/index.vue b/frontend/src/modules/fishSurvey/FishChangeTu/index.vue new file mode 100644 index 00000000..2a5cceec --- /dev/null +++ b/frontend/src/modules/fishSurvey/FishChangeTu/index.vue @@ -0,0 +1,303 @@ + + + + + diff --git a/frontend/src/modules/fishSurvey/FishIntroduce/index.vue b/frontend/src/modules/fishSurvey/FishIntroduce/index.vue index 220c21f7..e910b751 100644 --- a/frontend/src/modules/fishSurvey/FishIntroduce/index.vue +++ b/frontend/src/modules/fishSurvey/FishIntroduce/index.vue @@ -1,76 +1,98 @@ \ No newline at end of file + diff --git a/frontend/src/modules/fishSurvey/FishVideo/index.vue b/frontend/src/modules/fishSurvey/FishVideo/index.vue index 324687dd..7c4a9546 100644 --- a/frontend/src/modules/fishSurvey/FishVideo/index.vue +++ b/frontend/src/modules/fishSurvey/FishVideo/index.vue @@ -1,76 +1,144 @@ \ No newline at end of file + diff --git a/frontend/src/modules/fishSurvey/SurveyQingKuang/DeviceTableModal.vue b/frontend/src/modules/fishSurvey/SurveyQingKuang/DeviceTableModal.vue new file mode 100644 index 00000000..b9fb5571 --- /dev/null +++ b/frontend/src/modules/fishSurvey/SurveyQingKuang/DeviceTableModal.vue @@ -0,0 +1,376 @@ + + + + + diff --git a/frontend/src/modules/fishSurvey/SurveyQingKuang/index.vue b/frontend/src/modules/fishSurvey/SurveyQingKuang/index.vue new file mode 100644 index 00000000..a823e004 --- /dev/null +++ b/frontend/src/modules/fishSurvey/SurveyQingKuang/index.vue @@ -0,0 +1,177 @@ + + + + + diff --git a/frontend/src/modules/fishSurvey/ZhuanZhiIntroduce/index.vue b/frontend/src/modules/fishSurvey/ZhuanZhiIntroduce/index.vue index 24c07ee7..d2bca5f2 100644 --- a/frontend/src/modules/fishSurvey/ZhuanZhiIntroduce/index.vue +++ b/frontend/src/modules/fishSurvey/ZhuanZhiIntroduce/index.vue @@ -1,75 +1,111 @@ \ No newline at end of file + diff --git a/frontend/src/modules/guoyusheshijiansheqingkuang/ModalPage/index.vue b/frontend/src/modules/guoyusheshijiansheqingkuang/ModalPage/index.vue index 3806a835..e623f9ad 100644 --- a/frontend/src/modules/guoyusheshijiansheqingkuang/ModalPage/index.vue +++ b/frontend/src/modules/guoyusheshijiansheqingkuang/ModalPage/index.vue @@ -58,10 +58,8 @@ :scroll-y="400" :columns="columns" :list-url="fpVmsstbprptGetKendoList" - :enable-sort="true" :search-params="searchParams" :transform-data="customTransform" - @sort-change="handleSortChange" >