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 0a49d30b..a43e3361 100644 --- a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java +++ b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java @@ -64,12 +64,14 @@ public class SecurityConfig { // .requestMatchers("/eng/**").permitAll() // .requestMatchers("/eq/**").permitAll() // .requestMatchers("/env/**").permitAll() +// .requestMatchers("/warn/**").permitAll() // .requestMatchers("/wt/**").permitAll() // .requestMatchers("/fb/**").permitAll() // .requestMatchers("/zq/**").permitAll() // .requestMatchers("/wq/**").permitAll() // .requestMatchers("/vd/**").permitAll() // .requestMatchers("/fp/**").permitAll() +// .requestMatchers("/fpr/**").permitAll() // .requestMatchers("/fh/**").permitAll() // .requestMatchers("/data/**").permitAll() .requestMatchers("/sms/**").permitAll() 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 3eb42938..2b33fea4 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,21 @@ 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(); + } + + + @@ -150,7 +160,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/qgc_base/controller/SdEngInfoBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdEngInfoBHController.java index 866b074c..1faa114d 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 @@ -5,6 +5,7 @@ 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; @@ -91,16 +92,16 @@ public class SdEngInfoBHController { @Log(module = "电站管理", value = "新增电站") @PostMapping("/add") @Operation(summary = "新增电站") - public ResponseResult add(@RequestBody SdEngInfoBH engInfo) { - boolean result = engInfoBHService.addEngInfo(engInfo); + public ResponseResult add(@RequestBody SdEngInfoBHOperateRequest request) { + boolean result = engInfoBHService.addEngInfo(request.getEngInfo(), 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) { + boolean result = engInfoBHService.updateEngInfo(request.getEngInfo(), request.getSource()); return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败"); } @@ -111,4 +112,5 @@ public class SdEngInfoBHController { boolean result = engInfoBHService.deleteEngInfo(stcd); 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..2b4a003b 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,6 +27,12 @@ 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) { 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..277171ac --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/MsOperationLog.java @@ -0,0 +1,32 @@ +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; +} 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/SdEngInfoBHOperateRequest.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHOperateRequest.java new file mode 100644 index 00000000..bbe53d73 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBHOperateRequest.java @@ -0,0 +1,11 @@ +package com.yfd.platform.qgc_base.domain; + +import lombok.Data; + +@Data +public class SdEngInfoBHOperateRequest { + + private SdEngInfoBH engInfo; + + 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/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/EngVmsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngVmsstbprptVo.java index ba6b5723..c234fe73 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,7 @@ public class EngVmsstbprptVo implements Serializable { private String ennm; private String baseId; private String baseName; + private String reachcdName; private String hbrvcd; private String hbrvcdName; private String rvcd; @@ -33,6 +34,7 @@ public class EngVmsstbprptVo implements Serializable { private Date aiodt; private String bldstt; private Integer bldsttCcode; + private String bldsttCcodeName; private Double nrupar; private Double dstcrvr; private Double avyrp; @@ -79,6 +81,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 +105,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/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/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..51debb1d --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/IMsOperationLogService.java @@ -0,0 +1,10 @@ +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); +} 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..174f151d 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,6 +8,7 @@ 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.EngStInfoResultVo; import com.yfd.platform.qgc_base.domain.vo.EngVmsstbprptVo; import java.util.List; @@ -52,11 +53,15 @@ 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); + /** * 删除电站 */ @@ -66,6 +71,8 @@ public interface ISdEngInfoBHService extends IService { EngBaseInfoVo getStInfoByStcd(String stcd); + EngStInfoResultVo getStcdInfo(String stcd); + DataSourceResult getEiaapprovalKendoList(DataSourceRequest dataSourceRequest); DataSourceResult getVmsstbprptKendoList(DataSourceRequest dataSourceRequest); 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..0e2ec828 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/MsOperationLogServiceImpl.java @@ -0,0 +1,213 @@ +package com.yfd.platform.qgc_base.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.bean.copier.CopyOptions; +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.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@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("ENNM", "电站名称"); + ENG_FIELD_MEANING_MAP.put("BASE_ID", "所属基地编码"); + ENG_FIELD_MEANING_MAP.put("HBRVCD", "所属基地流域编码"); + ENG_FIELD_MEANING_MAP.put("RVCD", "所属流域编码"); + ENG_FIELD_MEANING_MAP.put("ADDVCD", "所属行政区编码"); + ENG_FIELD_MEANING_MAP.put("HYCD", "所属公司编码"); + ENG_FIELD_MEANING_MAP.put("BLPRD", "所属建设阶段"); + ENG_FIELD_MEANING_MAP.put("BLDSTT", "建设状态"); + ENG_FIELD_MEANING_MAP.put("BLDSTT_CODE", "建设状态分类"); + ENG_FIELD_MEANING_MAP.put("DVTP", "开发方式"); + ENG_FIELD_MEANING_MAP.put("DTIN", "数据是否接入"); + ENG_FIELD_MEANING_MAP.put("RGCP", "调节性能"); + ENG_FIELD_MEANING_MAP.put("LGTD", "经度"); + ENG_FIELD_MEANING_MAP.put("LTTD", "纬度"); + ENG_FIELD_MEANING_MAP.put("STLC", "站址"); + ENG_FIELD_MEANING_MAP.put("ORDER_INDEX", "排序"); + } + + @Resource + private MsOperationLogMapper msOperationLogMapper; + + @Resource + private MsOperationLogDetailMapper msOperationLogDetailMapper; + + @Override + public void recordEngAddLog(SdEngInfoBH engInfo, String source) { + if (engInfo == null) { + return; + } + MsOperationLog mainLog = buildMainLog("新增电站", source); + msOperationLogMapper.insert(mainLog); + + List details = new ArrayList<>(); + for (Field field : SdEngInfoBH.class.getDeclaredFields()) { + if (shouldSkipField(field)) { + continue; + } + field.setAccessible(true); + Object newValue = getFieldValue(field, engInfo); + if (newValue == null) { + continue; + } + details.add(buildDetail(mainLog.getId(), engInfo.getStcd(), resolveColumnName(field), + null, newValue, "新增字段值")); + } + batchInsertDetails(details); + } + + @Override + public void recordEngUpdateLog(SdEngInfoBH before, SdEngInfoBH changeSet, String source) { + if (before == null || changeSet == null) { + return; + } + SdEngInfoBH after = BeanUtil.copyProperties(before, SdEngInfoBH.class); + BeanUtil.copyProperties(changeSet, after, CopyOptions.create().ignoreNullValue()); + + MsOperationLog mainLog = buildMainLog("修改电站", source); + msOperationLogMapper.insert(mainLog); + + List details = new ArrayList<>(); + for (Field field : SdEngInfoBH.class.getDeclaredFields()) { + if (shouldSkipField(field)) { + continue; + } + field.setAccessible(true); + Object oldValue = getFieldValue(field, before); + Object newValue = getFieldValue(field, after); + if (equalsValue(oldValue, newValue)) { + continue; + } + details.add(buildDetail(mainLog.getId(), after.getStcd(), resolveColumnName(field), + oldValue, newValue, "修改字段值")); + } + batchInsertDetails(details); + } + + private MsOperationLog buildMainLog(String remark, String source) { + MsOperationLog log = new MsOperationLog(); + log.setOperator(resolveOperator()); + log.setOperateTime(new Date()); + log.setSource(StrUtil.trimToNull(source)); + log.setRemark(remark); + return log; + } + + private MsOperationLogDetail buildDetail(String mainId, + String stationCode, + String fieldCode, + Object oldValue, + Object newValue, + 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(oldValue)); + detail.setOldValueName(formatValue(oldValue)); + detail.setNewValueCode(formatValue(newValue)); + detail.setNewValueName(formatValue(newValue)); + 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 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/SdEngInfoBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdEngInfoBHServiceImpl.java index 0ee131b5..da85cba8 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 @@ -5,6 +5,7 @@ import cn.hutool.core.bean.copier.CopyOptions; 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.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.common.DataSourceLoadOptionsBase; @@ -19,13 +20,17 @@ 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.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.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; @@ -55,6 +60,9 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl queryPageList(Page page, String ennm, String rvcd, String baseId, String hycd) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); @@ -94,17 +102,20 @@ 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())){ return this.list(wrapper); @@ -186,17 +197,39 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl().eq(SdEngInfoBH::getStcd, stcd).set(SdEngInfoBH::getIsDeleted, 1)); +// return this.removeById(stcd); } @Override @@ -369,12 +402,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 +496,34 @@ public class SdEngInfoBHServiceImpl 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..5a7a0cfc 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; 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/service/impl/FpBuildServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpBuildServiceImpl.java index 88b8a6f9..a5b7963a 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( 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/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..549b34fa 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 + "}"; @@ -839,11 +1201,41 @@ public class VdMonitorServiceImpl implements VdMonitorService { return values; } + 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) { if (StrUtil.isBlank(field)) { return null; } return switch (field) { + case "sttp" -> "t.sttp"; case "sttpCode" -> "t.sttpCode"; case "sttpName" -> "t.sttpName"; case "sttpFullPath" -> "t.sttpFullPath"; @@ -878,11 +1270,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 +1367,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..91edb18c --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/entity/vo/StcdWarnStateVo.java @@ -0,0 +1,59 @@ +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 rstcdStepSort; + + @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..d6b57df6 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/warn/service/impl/WarnDataServiceImpl.java @@ -0,0 +1,2028 @@ +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.rstcdStepSort AS rstcdStepSort, ") + .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 nonEngWarnStateExpr = "CASE state.STD_SSTATE " + + "WHEN 2 THEN 0 " + + "WHEN 3 THEN 2 " + + "ELSE state.STD_SSTATE END"; + + List parts = new ArrayList<>(); + if ("QEC".equalsIgnoreCase(warnType)) { + parts.add(buildWarnStcdEngSql(normalizedWarnStateExpr, warnType)); + } else { + parts.add(buildWarnStcdEngSql(normalizedWarnStateExpr, warnType)); + parts.add(buildWarnStcdWqSql(nonEngWarnStateExpr)); + parts.add(buildWarnStcdWtSql(nonEngWarnStateExpr)); + } + 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("eng.ORDER_INDEX AS rstcdStepSort, ") + .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("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, " + + "eng.ORDER_INDEX AS rstcdStepSort, " + + "wq.DTIN_TYPE AS dtinType " + + "FROM SD_WQ_B_H wq " + + "LEFT JOIN (" + buildWarnStcdLatestStateSql() + ") state ON state.STCD = wq.STCD AND state.STTP_CODE = wq.STTP " + + "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 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, " + + "eng.ORDER_INDEX AS rstcdStepSort, " + + "wt.DTIN_TYPE AS dtinType " + + "FROM SD_WT_B_H wt " + + "LEFT JOIN (" + buildWarnStcdLatestStateSql() + ") state ON state.STCD = wt.STCD AND state.STTP_CODE = wt.STTP " + + "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_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 buildWarnStcdLatestStateSql() { + return "SELECT s.STCD, s.STTP_CODE, s.STD_SSTATE " + + "FROM MS_STSTATE_T s " + + "INNER JOIN (" + + "SELECT STCD, MAX(YR) AS MAX_YR " + + "FROM MS_STSTATE_T " + + "WHERE NVL(IS_DELETED, 0) = 0 " + + "GROUP BY STCD" + + ") mx ON mx.STCD = s.STCD AND mx.MAX_YR = s.YR " + + "WHERE NVL(s.IS_DELETED, 0) = 0"; + } + + 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 "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/service/impl/EnvWqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/wq/service/impl/EnvWqDataServiceImpl.java index 6910a908..32f2c970 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 @@ -3,15 +3,7 @@ package com.yfd.platform.qgc_env.wq.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.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.entity.vo.BatchDeleteAo; import com.yfd.platform.qgc_base.entity.vo.DataParam; @@ -694,6 +686,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 +724,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 +3176,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 +3206,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 +3222,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(); } 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..1bd2c665 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 @@ -66,11 +66,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' "); } @@ -1844,7 +1844,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/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/.env.development b/frontend/.env.development index aa2de5a5..4aa7a0cd 100644 --- a/frontend/.env.development +++ b/frontend/.env.development @@ -7,14 +7,26 @@ VITE_APP_TITLE = '水电水利建设项目全过程环境管理信息平台' VITE_APP_PORT = 3000 VITE_APP_BASE_API = '/dev-api' # 本地环境 -VITE_APP_BASE_URL = 'http://10.84.121.127:8093' +VITE_APP_BASE_URL = 'http://localhost:8093' # 测试环境 # VITE_APP_BASE_URL = 'http://172.16.21.142:8093' # VITE_APP_BASE_URL = 'http://172.16.21.142:8096' # 汤伟 +<<<<<<< Updated upstream +<<<<<<< HEAD # VITE_APP_BASE_URL = 'http://10.84.121.21:8093' # 李林 VITE_APP_BASE_URL = 'http://10.84.121.43:8093' +======= +VITE_APP_BASE_URL = 'http://10.84.121.127:8093' +# VITE_APP_BASE_URL = 'http://192.168.1.162:8093' +>>>>>>> fa4e1bc194446adb8adfd7f6404be1fbb50b31c3 +======= +# VITE_APP_BASE_URL = 'http://10.84.121.127:8093' +VITE_APP_BASE_URL = 'http://192.168.1.168:8093' +# 李林 +# VITE_APP_BASE_URL = 'http://10.84.121.43:8093' +>>>>>>> Stashed changes # 测试环境线上10.84.121.122: VITE_APP_TEST_ONLINE_URL = 'https://211.99.26.225:12122' diff --git a/frontend/.eslintrc.js b/frontend/.eslintrc.js index d7878cc2..7819e1fc 100644 --- a/frontend/.eslintrc.js +++ b/frontend/.eslintrc.js @@ -8,6 +8,7 @@ module.exports = { defineProps: 'readonly', defineEmits: 'readonly', defineExpose: 'readonly', + withDefaults: 'readonly', DialogType: "readonly", OptionType: "readonly", }, diff --git a/frontend/package.json b/frontend/package.json index 23b41752..4dd47f2c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -26,6 +26,7 @@ "echarts": "^5.2.2", "element-plus": "^2.2.27", "esri-leaflet": "^3.0.19", + "exceljs": "^4.4.0", "js-base64": "^3.7.5", "js-cookie": "^3.0.1", "jsencrypt": "^3.3.2", @@ -49,7 +50,8 @@ "vuedraggable": "^2.24.3", "wujie": "^1.0.24", "wujie-vue3": "^1.0.24", - "xlsx": "^0.18.5" + "xlsx": "^0.18.5", + "xlsx-js-style": "^1.2.0" }, "devDependencies": { "@commitlint/cli": "^16.2.3", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 8a571085..b67320b8 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -56,6 +56,9 @@ importers: esri-leaflet: specifier: ^3.0.19 version: 3.0.19(leaflet@1.9.4) + exceljs: + specifier: ^4.4.0 + version: 4.4.0 js-base64: specifier: ^3.7.5 version: 3.7.8 @@ -128,6 +131,9 @@ importers: xlsx: specifier: ^0.18.5 version: 0.18.5 + xlsx-js-style: + specifier: ^1.2.0 + version: 1.2.0 devDependencies: '@commitlint/cli': specifier: ^16.2.3 @@ -548,6 +554,12 @@ packages: resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@fast-csv/format@4.3.5': + resolution: {integrity: sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A==} + + '@fast-csv/parse@4.3.6': + resolution: {integrity: sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA==} + '@floating-ui/core@1.7.5': resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==} @@ -838,6 +850,9 @@ packages: '@types/minimist@1.2.5': resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} + '@types/node@14.18.63': + resolution: {integrity: sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==} + '@types/node@16.18.126': resolution: {integrity: sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==} @@ -1147,6 +1162,11 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + adler-32@1.2.0: + resolution: {integrity: sha512-/vUqU/UY4MVeFsg+SsK6c+/05RZXIHZMGJA+PX5JyWI0ZRcBpupnRuPLU/NXXoFwMYCPCoxIfElM2eS+DUXCqQ==} + engines: {node: '>=0.8'} + hasBin: true + adler-32@1.3.1: resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==} engines: {node: '>=0.8'} @@ -1192,6 +1212,18 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + archiver-utils@2.1.0: + resolution: {integrity: sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==} + engines: {node: '>= 6'} + + archiver-utils@3.0.4: + resolution: {integrity: sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==} + engines: {node: '>= 10'} + + archiver@5.3.2: + resolution: {integrity: sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==} + engines: {node: '>= 10'} + arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} @@ -1250,6 +1282,9 @@ packages: async-validator@4.2.5: resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -1286,6 +1321,9 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + base@0.11.2: resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} engines: {node: '>=0.10.0'} @@ -1298,6 +1336,10 @@ packages: better-scroll@2.5.1: resolution: {integrity: sha512-OiF3cQroRfTzf+CRQH2z1G52ZAlNHINI6lCAvDmyFu0o0nRuTaV9F+fmBGIU2BL5p5IplUQ4E7sYa1TLfZarzQ==} + big-integer@1.6.52: + resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} + engines: {node: '>=0.6'} + big.js@5.2.2: resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} @@ -1305,9 +1347,18 @@ packages: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} + binary@0.3.0: + resolution: {integrity: sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==} + bitmap-sdf@1.0.4: resolution: {integrity: sha512-1G3U4n5JE6RAiALMxu0p1XmeZkTeCwGKykzsLTCqVzfSDaN6S7fKnkIkfejogz+iwqBWc0UYAIKnKHNN7pSfDg==} + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + bluebird@3.4.7: + resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==} + bluebird@3.7.2: resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} @@ -1317,6 +1368,9 @@ packages: brace-expansion@1.1.14: resolution: {integrity: sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==} + brace-expansion@2.1.1: + resolution: {integrity: sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==} + braces@2.3.2: resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} engines: {node: '>=0.10.0'} @@ -1330,6 +1384,20 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + buffer-indexof-polyfill@1.0.2: + resolution: {integrity: sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==} + engines: {node: '>=0.10'} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + buffers@0.1.1: + resolution: {integrity: sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==} + engines: {node: '>=0.2.0'} + cache-base@1.0.1: resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} engines: {node: '>=0.10.0'} @@ -1373,6 +1441,9 @@ packages: resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==} engines: {node: '>=0.8'} + chainsaw@0.1.0: + resolution: {integrity: sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==} + chalk@1.1.3: resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} engines: {node: '>=0.10.0'} @@ -1401,6 +1472,11 @@ packages: resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} engines: {node: '>=0.8'} + codepage@1.14.0: + resolution: {integrity: sha512-iz3zJLhlrg37/gYRWgEPkaFTtzmnEv1h+r7NgZum2lFElYQPi0/5bnmuDfODHxfp0INEfnRqyfyeIJDbb7ahRw==} + engines: {node: '>=0.8'} + hasBin: true + codepage@1.15.0: resolution: {integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==} engines: {node: '>=0.8'} @@ -1420,6 +1496,12 @@ packages: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} + commander@2.14.1: + resolution: {integrity: sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==} + + commander@2.17.1: + resolution: {integrity: sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==} + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -1437,6 +1519,10 @@ packages: component-emitter@1.3.1: resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} + compress-commons@4.1.2: + resolution: {integrity: sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==} + engines: {node: '>= 10'} + compute-scroll-into-view@1.0.20: resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==} @@ -1491,6 +1577,10 @@ packages: engines: {node: '>=0.8'} hasBin: true + crc32-stream@4.0.3: + resolution: {integrity: sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==} + engines: {node: '>= 10'} + create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} @@ -1687,6 +1777,9 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + duplexer2@0.1.4: + resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==} + earcut@3.0.2: resolution: {integrity: sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==} @@ -1715,6 +1808,9 @@ packages: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + entities@1.1.2: resolution: {integrity: sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==} @@ -1881,10 +1977,18 @@ packages: event-emitter@0.3.5: resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} + exceljs@4.4.0: + resolution: {integrity: sha512-XctvKaEMaj1Ii9oDOqbW/6e1gXknSY4g/aLCDicOXqBE4M0nRWkUu0PTp++UPNzoFY12BNHMfs/VadKIS6llvg==} + engines: {node: '>=8.3.0'} + execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} + exit-on-epipe@1.0.1: + resolution: {integrity: sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==} + engines: {node: '>=0.8'} + expand-brackets@2.1.4: resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} engines: {node: '>=0.10.0'} @@ -1904,6 +2008,10 @@ packages: resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} engines: {node: '>=0.10.0'} + fast-csv@4.3.6: + resolution: {integrity: sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw==} + engines: {node: '>=10.0.0'} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -1932,6 +2040,9 @@ packages: picomatch: optional: true + fflate@0.3.11: + resolution: {integrity: sha512-Rr5QlUeGN1mbOHlaqcSYMKVpPbgLy0AWT/W0EHxA6NGI12yO1jpoui2zBBvU2G824ltM6Ut8BFgfHSBGfkmS0A==} + fflate@0.8.2: resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} @@ -1998,6 +2109,9 @@ packages: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} @@ -2014,6 +2128,11 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + fstream@1.0.12: + resolution: {integrity: sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==} + engines: {node: '>=0.6'} + deprecated: This package is no longer supported. + function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} @@ -2196,6 +2315,9 @@ packages: i18next@20.6.1: resolution: {integrity: sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==} + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -2529,6 +2651,10 @@ packages: ktx-parse@1.1.0: resolution: {integrity: sha512-mKp3y+FaYgR7mXWAbyyzpa/r1zDWeaunH+INJO4fou3hb45XuNSwar+7llrRyvpMWafxSIi99RNFJ05MHedaJQ==} + lazystream@1.0.1: + resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} + engines: {node: '>= 0.6.3'} + leaflet@1.9.4: resolution: {integrity: sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==} @@ -2552,6 +2678,9 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + listenercount@1.0.1: + resolution: {integrity: sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==} + loader-utils@1.4.2: resolution: {integrity: sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==} engines: {node: '>=4.0.0'} @@ -2583,13 +2712,43 @@ packages: lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + lodash.defaults@4.2.0: + resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + + lodash.difference@4.5.0: + resolution: {integrity: sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==} + + lodash.escaperegexp@4.1.2: + resolution: {integrity: sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==} + + lodash.flatten@4.4.0: + resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} + lodash.foreach@4.5.0: resolution: {integrity: sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==} + lodash.groupby@4.6.0: + resolution: {integrity: sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==} + + lodash.isboolean@3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + lodash.isequal@4.5.0: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. + lodash.isfunction@3.0.9: + resolution: {integrity: sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==} + + lodash.isnil@4.0.0: + resolution: {integrity: sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.isundefined@3.0.1: + resolution: {integrity: sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==} + lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} @@ -2599,6 +2758,12 @@ packages: lodash.toarray@4.4.0: resolution: {integrity: sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw==} + lodash.union@4.6.0: + resolution: {integrity: sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==} + + lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + lodash@4.18.1: resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} @@ -2713,6 +2878,10 @@ packages: minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + minimatch@5.1.9: + resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==} + engines: {node: '>=10'} + minimist-options@4.1.0: resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} engines: {node: '>= 6'} @@ -2724,6 +2893,10 @@ packages: resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} engines: {node: '>=0.10.0'} + mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + moment@2.30.1: resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} @@ -3080,6 +3253,11 @@ packages: engines: {node: '>=10.13.0'} hasBin: true + printj@1.1.2: + resolution: {integrity: sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==} + engines: {node: '>=0.8'} + hasBin: true + prismjs@1.30.0: resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} engines: {node: '>=6'} @@ -3161,6 +3339,9 @@ packages: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} + readdir-glob@1.1.3: + resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} + readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -3238,6 +3419,11 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rimraf@2.7.1: + resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} deprecated: Rimraf versions prior to v4 are no longer supported @@ -3292,6 +3478,10 @@ packages: resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} engines: {node: '>=11.0.0'} + saxes@5.0.1: + resolution: {integrity: sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==} + engines: {node: '>=10'} + screenfull@6.0.2: resolution: {integrity: sha512-AQdy8s4WhNvUZ6P8F6PB21tSPIYKniic+Ogx0AacBMjKP1GUHN2E9URxQHtCusiwxudnCKkdy4GrHXPPJSkCCw==} engines: {node: ^14.13.1 || >=16.0.0} @@ -3556,6 +3746,10 @@ packages: engines: {node: '>=14.0.0'} hasBin: true + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + text-extensions@1.9.0: resolution: {integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==} engines: {node: '>=0.10'} @@ -3590,6 +3784,10 @@ packages: resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} engines: {node: '>=12.0.0'} + tmp@0.2.7: + resolution: {integrity: sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==} + engines: {node: '>=14.14'} + to-object-path@0.3.0: resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} engines: {node: '>=0.10.0'} @@ -3614,6 +3812,9 @@ packages: resolution: {integrity: sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==} hasBin: true + traverse@0.3.9: + resolution: {integrity: sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==} + traverse@0.6.11: resolution: {integrity: sha512-vxXDZg8/+p3gblxB6BhhG5yWVn1kGRlaL8O78UDXc3wRnPizB5g83dcvWV1jpDMIPnjZjOFuxlMmE82XJ4407w==} engines: {node: '>= 0.4'} @@ -3731,6 +3932,9 @@ packages: resolution: {integrity: sha512-DVeVIWUZCAQPNzm5sB0hpsG1GygTTdBnzNtYYEpInkttx5evkyqRgZi6rTczoySqp8hO5jHVKzrH0f23X8FZLg==} engines: {node: '>=18'} + unzipper@0.10.14: + resolution: {integrity: sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==} + update-browserslist-db@1.2.3: resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} hasBin: true @@ -3757,6 +3961,10 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} @@ -3961,6 +4169,11 @@ packages: xhr@2.4.0: resolution: {integrity: sha512-TUbBsdAuJbX8olk9hsDwGK8P1ri1XlV+PdEWkYw+HQQbpkiBR8PLgD1F3kQDPBs9l4Px34hP9rCYAZOCCAENbw==} + xlsx-js-style@1.2.0: + resolution: {integrity: sha512-DDT4FXFSWfT4DXMSok/m3TvmP1gvO3dn0Eu/c+eXHW5Kzmp7IczNkxg/iEPnImbG9X0Vb8QhROda5eatSR/97Q==} + engines: {node: '>=0.8'} + hasBin: true + xlsx@0.18.5: resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==} engines: {node: '>=0.8'} @@ -3969,6 +4182,9 @@ packages: xml-utils@1.10.2: resolution: {integrity: sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA==} + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -4007,6 +4223,10 @@ packages: zarrita@0.7.1: resolution: {integrity: sha512-Nu4liRKJES1kkIjWALXSryglJf2+WJURUxgndklfX+mTBCd0lk4MV797p00lt4NzmU3Bbdbs10uxeN8LWwPyWA==} + zip-stream@4.1.1: + resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==} + engines: {node: '>= 10'} + zrender@5.6.1: resolution: {integrity: sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==} @@ -4351,6 +4571,25 @@ snapshots: '@eslint/js@8.57.1': {} + '@fast-csv/format@4.3.5': + dependencies: + '@types/node': 14.18.63 + lodash.escaperegexp: 4.1.2 + lodash.isboolean: 3.0.3 + lodash.isequal: 4.5.0 + lodash.isfunction: 3.0.9 + lodash.isnil: 4.0.0 + + '@fast-csv/parse@4.3.6': + dependencies: + '@types/node': 14.18.63 + lodash.escaperegexp: 4.1.2 + lodash.groupby: 4.6.0 + lodash.isfunction: 3.0.9 + lodash.isnil: 4.0.0 + lodash.isundefined: 3.0.1 + lodash.uniq: 4.5.0 + '@floating-ui/core@1.7.5': dependencies: '@floating-ui/utils': 0.2.11 @@ -4578,6 +4817,8 @@ snapshots: '@types/minimist@1.2.5': {} + '@types/node@14.18.63': {} + '@types/node@16.18.126': {} '@types/normalize-package-data@2.4.4': {} @@ -4991,6 +5232,11 @@ snapshots: acorn@8.16.0: {} + adler-32@1.2.0: + dependencies: + exit-on-epipe: 1.0.1 + printj: 1.1.2 + adler-32@1.3.1: {} aes-decrypter@1.0.3: @@ -5056,6 +5302,42 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.2 + archiver-utils@2.1.0: + dependencies: + glob: 7.2.3 + graceful-fs: 4.2.11 + lazystream: 1.0.1 + lodash.defaults: 4.2.0 + lodash.difference: 4.5.0 + lodash.flatten: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.union: 4.6.0 + normalize-path: 3.0.0 + readable-stream: 2.3.8 + + archiver-utils@3.0.4: + dependencies: + glob: 7.2.3 + graceful-fs: 4.2.11 + lazystream: 1.0.1 + lodash.defaults: 4.2.0 + lodash.difference: 4.5.0 + lodash.flatten: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.union: 4.6.0 + normalize-path: 3.0.0 + readable-stream: 3.6.2 + + archiver@5.3.2: + dependencies: + archiver-utils: 2.1.0 + async: 3.2.6 + buffer-crc32: 0.2.13 + readable-stream: 3.6.2 + readdir-glob: 1.1.3 + tar-stream: 2.2.0 + zip-stream: 4.1.1 + arg@4.1.3: {} arg@5.0.2: {} @@ -5099,6 +5381,8 @@ snapshots: async-validator@4.2.5: {} + async@3.2.6: {} + asynckit@0.4.0: {} at-least-node@1.0.0: {} @@ -5137,6 +5421,8 @@ snapshots: balanced-match@1.0.2: {} + base64-js@1.5.1: {} + base@0.11.2: dependencies: cache-base: 1.0.1 @@ -5166,12 +5452,27 @@ snapshots: '@better-scroll/wheel': 2.5.1 '@better-scroll/zoom': 2.5.1 + big-integer@1.6.52: {} + big.js@5.2.2: {} binary-extensions@2.3.0: {} + binary@0.3.0: + dependencies: + buffers: 0.1.1 + chainsaw: 0.1.0 + bitmap-sdf@1.0.4: {} + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + + bluebird@3.4.7: {} + bluebird@3.7.2: {} boolbase@1.0.0: {} @@ -5181,6 +5482,10 @@ snapshots: balanced-match: 1.0.2 concat-map: 0.0.1 + brace-expansion@2.1.1: + dependencies: + balanced-match: 1.0.2 + braces@2.3.2: dependencies: arr-flatten: 1.1.0 @@ -5208,6 +5513,17 @@ snapshots: node-releases: 2.0.38 update-browserslist-db: 1.2.3(browserslist@4.28.2) + buffer-crc32@0.2.13: {} + + buffer-indexof-polyfill@1.0.2: {} + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + buffers@0.1.1: {} + cache-base@1.0.1: dependencies: collection-visit: 1.0.0 @@ -5261,6 +5577,10 @@ snapshots: adler-32: 1.3.1 crc-32: 1.2.2 + chainsaw@0.1.0: + dependencies: + traverse: 0.3.9 + chalk@1.1.3: dependencies: ansi-styles: 2.2.1 @@ -5305,6 +5625,11 @@ snapshots: clone@2.1.2: {} + codepage@1.14.0: + dependencies: + commander: 2.14.1 + exit-on-epipe: 1.0.1 + codepage@1.15.0: {} collection-visit@1.0.0: @@ -5322,6 +5647,10 @@ snapshots: dependencies: delayed-stream: 1.0.0 + commander@2.14.1: {} + + commander@2.17.1: {} + commander@2.20.3: {} commander@4.1.1: {} @@ -5335,6 +5664,13 @@ snapshots: component-emitter@1.3.1: {} + compress-commons@4.1.2: + dependencies: + buffer-crc32: 0.2.13 + crc32-stream: 4.0.3 + normalize-path: 3.0.0 + readable-stream: 3.6.2 + compute-scroll-into-view@1.0.20: {} concat-map@0.0.1: {} @@ -5392,6 +5728,11 @@ snapshots: crc-32@1.2.2: {} + crc32-stream@4.0.3: + dependencies: + crc-32: 1.2.2 + readable-stream: 3.6.2 + create-require@1.1.1: {} cross-spawn@7.0.6: @@ -5581,6 +5922,10 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + duplexer2@0.1.4: + dependencies: + readable-stream: 2.3.8 + earcut@3.0.2: {} echarts@5.6.0: @@ -5619,6 +5964,10 @@ snapshots: encodeurl@2.0.0: {} + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + entities@1.1.2: {} entities@2.2.0: {} @@ -5888,6 +6237,18 @@ snapshots: d: 1.0.2 es5-ext: 0.10.64 + exceljs@4.4.0: + dependencies: + archiver: 5.3.2 + dayjs: 1.11.20 + fast-csv: 4.3.6 + jszip: 3.10.1 + readable-stream: 3.6.2 + saxes: 5.0.1 + tmp: 0.2.7 + unzipper: 0.10.14 + uuid: 8.3.2 + execa@5.1.1: dependencies: cross-spawn: 7.0.6 @@ -5900,6 +6261,8 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 + exit-on-epipe@1.0.1: {} + expand-brackets@2.1.4: dependencies: debug: 2.6.9 @@ -5938,6 +6301,11 @@ snapshots: transitivePeerDependencies: - supports-color + fast-csv@4.3.6: + dependencies: + '@fast-csv/format': 4.3.5 + '@fast-csv/parse': 4.3.6 + fast-deep-equal@3.1.3: {} fast-diff@1.3.0: {} @@ -5962,6 +6330,8 @@ snapshots: optionalDependencies: picomatch: 4.0.4 + fflate@0.3.11: {} + fflate@0.8.2: {} file-entry-cache@6.0.1: @@ -6023,6 +6393,8 @@ snapshots: fresh@0.5.2: {} + fs-constants@1.0.0: {} + fs-extra@10.1.0: dependencies: graceful-fs: 4.2.11 @@ -6041,6 +6413,13 @@ snapshots: fsevents@2.3.3: optional: true + fstream@1.0.12: + dependencies: + graceful-fs: 4.2.11 + inherits: 2.0.4 + mkdirp: 0.5.6 + rimraf: 2.7.1 + function-bind@1.1.2: {} function.prototype.name@1.1.8: @@ -6246,6 +6625,8 @@ snapshots: dependencies: '@babel/runtime': 7.29.2 + ieee754@1.2.1: {} + ignore@5.3.2: {} image-size@0.5.5: {} @@ -6537,6 +6918,10 @@ snapshots: ktx-parse@1.1.0: {} + lazystream@1.0.1: + dependencies: + readable-stream: 2.3.8 + leaflet@1.9.4: {} lerc@2.0.0: {} @@ -6556,6 +6941,8 @@ snapshots: lines-and-columns@1.2.4: {} + listenercount@1.0.1: {} + loader-utils@1.4.2: dependencies: big.js: 5.2.2 @@ -6584,16 +6971,40 @@ snapshots: lodash.debounce@4.0.8: {} + lodash.defaults@4.2.0: {} + + lodash.difference@4.5.0: {} + + lodash.escaperegexp@4.1.2: {} + + lodash.flatten@4.4.0: {} + lodash.foreach@4.5.0: {} + lodash.groupby@4.6.0: {} + + lodash.isboolean@3.0.3: {} + lodash.isequal@4.5.0: {} + lodash.isfunction@3.0.9: {} + + lodash.isnil@4.0.0: {} + + lodash.isplainobject@4.0.6: {} + + lodash.isundefined@3.0.1: {} + lodash.merge@4.6.2: {} lodash.throttle@4.1.1: {} lodash.toarray@4.4.0: {} + lodash.union@4.6.0: {} + + lodash.uniq@4.5.0: {} + lodash@4.18.1: {} long@5.3.2: {} @@ -6713,6 +7124,10 @@ snapshots: dependencies: brace-expansion: 1.1.14 + minimatch@5.1.9: + dependencies: + brace-expansion: 2.1.1 + minimist-options@4.1.0: dependencies: arrify: 1.0.1 @@ -6726,6 +7141,10 @@ snapshots: for-in: 1.0.2 is-extendable: 1.0.1 + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 + moment@2.30.1: {} mpd-parser@1.3.1: @@ -7062,6 +7481,8 @@ snapshots: prettier@2.8.8: {} + printj@1.1.2: {} + prismjs@1.30.0: {} process-nextick-args@2.0.1: {} @@ -7134,6 +7555,10 @@ snapshots: string_decoder: 1.3.0 util-deprecate: 1.0.2 + readdir-glob@1.1.3: + dependencies: + minimatch: 5.1.9 + readdirp@3.6.0: dependencies: picomatch: 2.3.2 @@ -7207,6 +7632,10 @@ snapshots: reusify@1.1.0: {} + rimraf@2.7.1: + dependencies: + glob: 7.2.3 + rimraf@3.0.2: dependencies: glob: 7.2.3 @@ -7272,6 +7701,10 @@ snapshots: sax@1.6.0: {} + saxes@5.0.1: + dependencies: + xmlchars: 2.2.0 + screenfull@6.0.2: {} scroll-into-view-if-needed@2.2.31: @@ -7621,6 +8054,14 @@ snapshots: - tsx - yaml + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.5 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + text-extensions@1.9.0: {} text-table@0.2.0: {} @@ -7650,6 +8091,8 @@ snapshots: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 + tmp@0.2.7: {} + to-object-path@0.3.0: dependencies: kind-of: 3.2.2 @@ -7676,6 +8119,8 @@ snapshots: dependencies: commander: 2.20.3 + traverse@0.3.9: {} + traverse@0.6.11: dependencies: gopd: 1.2.0 @@ -7802,6 +8247,19 @@ snapshots: unzipit@2.0.0: {} + unzipper@0.10.14: + dependencies: + big-integer: 1.6.52 + binary: 0.3.0 + bluebird: 3.4.7 + buffer-indexof-polyfill: 1.0.2 + duplexer2: 0.1.4 + fstream: 1.0.12 + graceful-fs: 4.2.11 + listenercount: 1.0.1 + readable-stream: 2.3.8 + setimmediate: 1.0.5 + update-browserslist-db@1.2.3(browserslist@4.28.2): dependencies: browserslist: 4.28.2 @@ -7822,6 +8280,8 @@ snapshots: util-deprecate@1.0.2: {} + uuid@8.3.2: {} + v8-compile-cache-lib@3.0.1: {} validate-npm-package-license@3.0.4: @@ -8074,6 +8534,19 @@ snapshots: parse-headers: 2.0.6 xtend: 4.0.2 + xlsx-js-style@1.2.0: + dependencies: + adler-32: 1.2.0 + cfb: 1.2.2 + codepage: 1.14.0 + commander: 2.17.1 + crc-32: 1.2.2 + exit-on-epipe: 1.0.1 + fflate: 0.3.11 + ssf: 0.11.2 + wmf: 1.0.2 + word: 0.3.0 + xlsx@0.18.5: dependencies: adler-32: 1.3.1 @@ -8086,6 +8559,8 @@ snapshots: xml-utils@1.10.2: {} + xmlchars@2.2.0: {} + xtend@4.0.2: {} y18n@5.0.8: {} @@ -8117,6 +8592,12 @@ snapshots: '@zarrita/storage': 0.2.0 numcodecs: 0.3.2 + zip-stream@4.1.1: + dependencies: + archiver-utils: 3.0.4 + compress-commons: 4.1.2 + readable-stream: 3.6.2 + zrender@5.6.1: dependencies: tslib: 2.3.0 diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 61733d78..45aee3ea 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -1,12 +1,13 @@