diff --git a/backend/src/main/java/com/yfd/platform/config/RegisterAccessTokenFilter.java b/backend/src/main/java/com/yfd/platform/config/RegisterAccessTokenFilter.java new file mode 100644 index 00000000..12b85648 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/config/RegisterAccessTokenFilter.java @@ -0,0 +1,70 @@ +package com.yfd.platform.config; + +import com.yfd.platform.system.service.RegisterAccessTokenService; +import jakarta.annotation.Resource; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; + +@Component +public class RegisterAccessTokenFilter extends OncePerRequestFilter { + + private static final String ENG_INFO_PATH = "/register/dropdown/engInfo"; + private static final String HBRV_PATH = "/register/dropdown/hbrv"; + private static final String HYCD_PATH = "/register/dropdown/hycd"; + private static final String RVCD_PATH = "/register/dropdown/rvcd"; + + @Resource + private RegisterAccessTokenService registerAccessTokenService; + + @Override + protected void doFilterInternal(HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + String requestPath = resolveRequestPath(request); + if (!needsRegisterAccessToken(requestPath)) { + filterChain.doFilter(request, response); + return; + } + + String token = registerAccessTokenService.resolveToken(request); + if (!registerAccessTokenService.validateToken(token, request)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "registerToken无效或已过期"); + return; + } + + UsernamePasswordAuthenticationToken authenticationToken = + new UsernamePasswordAuthenticationToken( + "register-access", + null, + AuthorityUtils.NO_AUTHORITIES + ); + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + filterChain.doFilter(request, response); + } + + private boolean needsRegisterAccessToken(String uri) { + return ENG_INFO_PATH.equals(uri) || HBRV_PATH.equals(uri) || HYCD_PATH.equals(uri)|| RVCD_PATH.equals(uri); + } + + private String resolveRequestPath(HttpServletRequest request) { + String servletPath = request.getServletPath(); + if (servletPath != null && !servletPath.isEmpty()) { + return servletPath; + } + String uri = request.getRequestURI(); + String contextPath = request.getContextPath(); + if (contextPath != null && !contextPath.isEmpty() && uri.startsWith(contextPath)) { + return uri.substring(contextPath.length()); + } + return uri; + } +} 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 b4323148..79a4e331 100644 --- a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java +++ b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java @@ -39,6 +39,9 @@ public class SecurityConfig { @Autowired private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; + @Autowired + private RegisterAccessTokenFilter registerAccessTokenFilter; + @Autowired private AuthenticationException authenticationException; @@ -57,16 +60,17 @@ public class SecurityConfig { .requestMatchers("/data/fishDraft/previewFile").permitAll() .requestMatchers("/tempFile/**").permitAll() .requestMatchers("/system/user/auditUser").permitAll() - .requestMatchers("/eng/**").permitAll() - .requestMatchers("/eq/**").permitAll() - .requestMatchers("/env/**").permitAll() - .requestMatchers("/wt/**").permitAll() - .requestMatchers("/zq/**").permitAll() - .requestMatchers("/wq/**").permitAll() - .requestMatchers("/vd/**").permitAll() - .requestMatchers("/fp/**").permitAll() - .requestMatchers("/fh/**").permitAll() - .requestMatchers("/data/**").permitAll() + .requestMatchers("/register/accessToken").permitAll() +// .requestMatchers("/eng/**").permitAll() +// .requestMatchers("/eq/**").permitAll() +// .requestMatchers("/env/**").permitAll() +// .requestMatchers("/wt/**").permitAll() +// .requestMatchers("/zq/**").permitAll() +// .requestMatchers("/wq/**").permitAll() +// .requestMatchers("/vd/**").permitAll() +// .requestMatchers("/fp/**").permitAll() +// .requestMatchers("/fh/**").permitAll() +// .requestMatchers("/data/**").permitAll() .requestMatchers("/sms/**").permitAll() .requestMatchers(HttpMethod.GET, "/").permitAll() .requestMatchers(HttpMethod.GET, @@ -93,6 +97,7 @@ public class SecurityConfig { ) .cors(cors -> {}); + http.addFilterBefore(registerAccessTokenFilter, UsernamePasswordAuthenticationFilter.class); http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); http.exceptionHandling(ex -> ex 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 9178996a..3cc06390 100644 --- a/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java +++ b/backend/src/main/java/com/yfd/platform/config/SwaggerConfig.java @@ -92,6 +92,8 @@ public class SwaggerConfig { .build(); } + + @Bean public GroupedOpenApi groupEnvFHApi() { return GroupedOpenApi.builder() @@ -109,6 +111,15 @@ public class SwaggerConfig { } + @Bean + public GroupedOpenApi groupEnvVapApi() { + return GroupedOpenApi.builder() + .group("3.5 全过程-生态环保数据服务-珍稀动植物") + .packagesToScan("com.yfd.platform.qgc_env.vap.controller") + .build(); + } + + @Bean diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/RegisterDropdownController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/RegisterDropdownController.java new file mode 100644 index 00000000..5c6155b0 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/RegisterDropdownController.java @@ -0,0 +1,65 @@ +package com.yfd.platform.qgc_base.controller; + +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.qgc_base.domain.SdEngInfoBHRequest; +import com.yfd.platform.qgc_base.service.ISdEngInfoBHService; +import com.yfd.platform.qgc_base.service.ISdHbrvDicService; +import com.yfd.platform.qgc_base.service.ISdHycdDicService; +import com.yfd.platform.qgc_base.service.ISdRvcdDicService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.GetMapping; +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.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/register/dropdown") +@Tag(name = "注册下拉数据") +public class RegisterDropdownController { + + @Resource + private ISdEngInfoBHService engInfoBHService; + + @Resource + private ISdHbrvDicService hbrvDicService; + + @Resource + private ISdHycdDicService hycdDicService; + + @Resource + private ISdRvcdDicService sdRvcdDicService; + + @PostMapping("/engInfo") + @Operation(summary = "注册场景电站下拉") + public ResponseResult engInfoDropdown(@RequestBody SdEngInfoBHRequest request) { + return ResponseResult.successData(engInfoBHService.selectRegDropdown(request)); + } + + @GetMapping("/hbrv") + @Operation(summary = "注册场景基地流域下拉") + public ResponseResult hbrvDropdown(@RequestParam(required = false) String hbrvnm, + @RequestParam(required = false) String baseid) { + return ResponseResult.successData(hbrvDicService.regDropdown(hbrvnm, baseid)); + } + + @GetMapping("/hycd") + @Operation(summary = "注册场景公司下拉") + public ResponseResult hycdDropdown(@RequestParam(required = false) String hynm, + @RequestParam(required = false) Integer grd, + @RequestParam(required = false) Integer lx, + @RequestParam(required = false) String phycd) { + return ResponseResult.successData(hycdDicService.regDropdown(hynm, grd, lx, phycd)); + } + + @GetMapping("/rvcd") + @Operation(summary = "流域下拉框列表查询(注册)") + public ResponseResult regDropdown( + @RequestParam(required = false) String rvnm, + @RequestParam(required = false) String rvcd) { + return ResponseResult.successData(sdRvcdDicService.regDropdown(rvnm, rvcd)); + } +} 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 4382224e..866b074c 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 @@ -66,8 +66,8 @@ public class SdEngInfoBHController { @GetMapping("/getByRvcd") @Operation(summary = "根据流域编码查询电站") - public ResponseResult getByRvcd(@RequestParam String rvcd) { - return ResponseResult.successData(engInfoBHService.getByRvcd(rvcd)); + public ResponseResult getByRvcd(@RequestParam String rvcd, @RequestParam String reachcd) { + return ResponseResult.successData(engInfoBHService.getByRvcd(rvcd,reachcd)); } @PostMapping("/dropdown") diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssBHController.java b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssBHController.java index 1f83d18c..9c38b5d1 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssBHController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/controller/SdFpssBHController.java @@ -59,8 +59,10 @@ public class SdFpssBHController { @Operation(summary = "设施下拉列表(根据电站编码筛选 + 支持名称模糊搜索 + 支持基地编码筛选)") public ResponseResult dropdown(@RequestParam(required = false) String rstcd, @RequestParam(required = false) String stnm, - @RequestParam(required = false) String baseId) { - return ResponseResult.successData(sdFpssBHService.selectForDropdown(rstcd, stnm, baseId)); + @RequestParam(required = false) String baseId, + @RequestParam(required = false) String rvcd, + @RequestParam(required = false) String reachcd) { + return ResponseResult.successData(sdFpssBHService.selectForDropdown(rstcd, stnm, baseId,rvcd,reachcd)); } @Log(module = "过鱼设施管理", value = "新增过鱼设施") 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 9a1c6bdc..4ee42f4c 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 @@ -102,4 +102,20 @@ public class SdRvcdDicController { boolean result = rvcdDicService.deleteRvcdDic(rvcd); return result ? ResponseResult.success("删除成功") : ResponseResult.error("删除失败"); } + + @GetMapping("/selectForDropdown") + @Operation(summary = "下拉框列表查询") + public ResponseResult selectForDropdown( + @RequestParam(required = false) String rvnm, + @RequestParam(required = false) String rvcd) { + return ResponseResult.successData(rvcdDicService.selectForDropdown(rvnm, rvcd)); + } + + @GetMapping("/regDropdown") + @Operation(summary = "下拉框列表查询(注册)") + public ResponseResult regDropdown( + @RequestParam(required = false) String rvnm, + @RequestParam(required = false) String rvcd) { + return ResponseResult.successData(rvcdDicService.regDropdown(rvnm, rvcd)); + } } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBH.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBH.java index f316193c..1770f06e 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBH.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdEngInfoBH.java @@ -96,26 +96,56 @@ public class SdEngInfoBH implements Serializable { @TableField("BASE_ID") private String baseId; + /** + * 所属基地名称 + */ + @TableField("BASE_NAME") + private String baseName; + /** * 所属基地流域编码 */ private String hbrvcd; /** - * 所属流域代码,关联SD_LYSXJGX_QGC.RVCD + * 所属基地河段名称 + */ + @TableField("HBRVCD_NAME") + private String hbrvcdName; + + /** + * 所属流域代码,关联SD_RVCD_DIC.RVCD */ private String rvcd; + /** + * 所属流域名称 + */ + @TableField("RVCD_NAME") + private String rvcdName; + /** * 所属行政区编码,关联SD_ADDVCD_DIC.ADDVCD */ private String addvcd; + /** + * 所属行政区名称 + */ + @TableField("ADDVCD_NAME") + private String addvcdName; + /** * 所属国家,关联SD_COUNTRY_B.COUNTRY_ID */ private String country; + /** + * 所属国家名称 + */ + @TableField("COUNTRY_NAME") + private String countryName; + /** * 所属河段编码 */ @@ -132,11 +162,22 @@ public class SdEngInfoBH implements Serializable { private String hycd; /** - * 所属集团名称,关联SD_HYDROCOCD_DIC.HYCD + * 所属公司名称 + */ + private String hynm; + + /** + * 所属集团编码,关联SD_HYDROCOCD_DIC.HYCD */ @TableField("TOP_HYCD") private String topHycd; + /** + * 所属集团名称 + */ + @TableField("TOP_HYNM") + private String topHynm; + /** * 规划设计日期 */ @@ -1178,4 +1219,65 @@ public class SdEngInfoBH implements Serializable { * 植被覆盖调查时间 */ private Date vlsrTm; -} \ No newline at end of file + + /** + * 创建人 + */ + private String recordUser; + + /** + * 创建时间 + */ + private Date recordTime; + + /** + * 更新人 + */ + private String modifyUser; + + /** + * 更新时间 + */ + private Date modifyTime; + + /** + * 是否已删除 + */ + private Integer isDeleted; + + /** + * 删除人 + */ + private String deleteUser; + + /** + * 删除时间 + */ + private Date deleteTime; + + /** + * 环境监测数据接入情况:2=已全部接入 1=部分接入 0=未接入 + */ + @TableField("DTIN_ENV") + private Integer dtinEnv; + + /** + * 最新运行状态:1=运行中 2=未运行 + */ + private Integer runState; + + /** + * 告警状态 + */ + private String warnState; + + /** + * 开展环保自动检测工作状态:0=暂无数据 1=正常 + */ + private Integer coenvwState; + + /** + * 在线地址 + */ + private String url; +} 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 5227bdb2..402b3bda 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 @@ -12,6 +12,7 @@ import java.util.List; public class SdEngInfoBHRequest { private String baseId; private String hbrvcd; + private String rvcd; private List basIds; private List hbrvcds; private List rvcds; diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdHbrvDic.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdHbrvDic.java index 94b45e33..6c355d33 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdHbrvDic.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdHbrvDic.java @@ -5,10 +5,11 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; +import java.util.Date; /** *

- * 水电基地流域表 + * 水电基地河段字典表 *

*/ @Data @@ -29,6 +30,11 @@ public class SdHbrvDic implements Serializable { */ private String hbrvnm; + /** + * 所属基地流域编码,根节点为空 + */ + private String phbrvcd; + /** * 水电基地编码 */ @@ -49,8 +55,48 @@ public class SdHbrvDic implements Serializable { */ private Integer orderIndex; + /** + * 备注 + */ + private String remark; + /** * 是否启用:0=禁用 1=启用 */ private Integer enabled; -} \ No newline at end of file + + /** + * 创建人 + */ + private String recordUser; + + /** + * 创建时间 + */ + private Date recordTime; + + /** + * 更新人 + */ + private String modifyUser; + + /** + * 更新时间 + */ + private Date modifyTime; + + /** + * 是否已删除:0=未删除 1=已删除 + */ + private Integer isDeleted; + + /** + * 删除人 + */ + private String deleteUser; + + /** + * 删除时间 + */ + private Date deleteTime; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdHycdDic.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdHycdDic.java index 4d8826ea..fe161975 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdHycdDic.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdHycdDic.java @@ -5,6 +5,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; +import java.util.Date; /** *

@@ -30,7 +31,7 @@ public class SdHycdDic implements Serializable { private String hynm; /** - * 所属公司编码,根节点为0 + * 所属公司编码,根节点为空 */ private String phycd; @@ -49,14 +50,18 @@ public class SdHycdDic implements Serializable { */ private Integer orderIndex; + /** + * 备注 + */ + private String remark; /** - * 所属国家,关联SD_COUNTRY_B.COUNTRY_ID + * 所属国家 */ private String country; /** - * 公司Logo + * 公司LOGO */ private String logo; @@ -80,4 +85,44 @@ public class SdHycdDic implements Serializable { */ private Integer lx; + /** + * 是否启用:0=禁用 1=启用 + */ + private Integer enabled; + + /** + * 创建人 + */ + private String recordUser; + + /** + * 创建时间 + */ + private Date recordTime; + + /** + * 更新人 + */ + private String modifyUser; + + /** + * 更新时间 + */ + private Date modifyTime; + + /** + * 是否已删除:0=未删除 1=已删除 + */ + private Integer isDeleted; + + /** + * 删除人 + */ + private String deleteUser; + + /** + * 删除时间 + */ + private Date deleteTime; + } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdHydrobase.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdHydrobase.java index 296090ae..acd0c913 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdHydrobase.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdHydrobase.java @@ -5,6 +5,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; +import java.util.Date; /** *

@@ -63,4 +64,44 @@ public class SdHydrobase implements Serializable { * 简称 */ private String shortname; + + /** + * 是否启用:0=禁用 1=启用 + */ + private Integer enabled; + + /** + * 创建人 + */ + private String recordUser; + + /** + * 创建时间 + */ + private Date recordTime; + + /** + * 更新人 + */ + private String modifyUser; + + /** + * 更新时间 + */ + private Date modifyTime; + + /** + * 是否已删除:0=未删除 1=已删除 + */ + private Integer isDeleted; + + /** + * 删除人 + */ + private String deleteUser; + + /** + * 删除时间 + */ + private Date deleteTime; } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdRvcdDic.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdRvcdDic.java index 2b92f18d..53178c88 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdRvcdDic.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/SdRvcdDic.java @@ -5,6 +5,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; +import java.util.Date; import java.util.List; /** @@ -71,10 +72,15 @@ public class SdRvcdDic implements Serializable { private Double perimeter; /** - * 所属国家,关联SD_COUNTRY_B.COUNTRY_ID + * 所属国家 */ private String country; + /** + * 流域LOGO + */ + private String logo; + /** * 简介 */ @@ -86,20 +92,10 @@ public class SdRvcdDic implements Serializable { private String inffile; /** - * 简称 + * 流域简称 */ private String shortname; - /** - * 气象预报 0=不支持 1=支持 - */ - private Integer weatherForecast; - - /** - * 气象反演 0=不支持 1=支持 - */ - private Integer weatherInversion; - /** * 范围 */ @@ -111,9 +107,44 @@ public class SdRvcdDic implements Serializable { private String baseid; /** - * 地图专题流域标识:1=是 0否 + * 是否启用:0=禁用 1=启用 */ - private Integer ismap; + private Integer enabled; + + /** + * 创建人 + */ + private String recordUser; + + /** + * 创建时间 + */ + private Date recordTime; + + /** + * 更新人 + */ + private String modifyUser; + + /** + * 更新时间 + */ + private Date modifyTime; + + /** + * 是否已删除:0=未删除 1=已删除 + */ + private Integer isDeleted; + + /** + * 删除人 + */ + private String deleteUser; + + /** + * 删除时间 + */ + private Date deleteTime; /** * 子节点(用于树形结构,不映射数据库字段) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/StationBasinInfo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/StationBasinInfo.java index ac1f326c..45712859 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/StationBasinInfo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/StationBasinInfo.java @@ -8,4 +8,7 @@ public class StationBasinInfo { private String ennm; // 电站名称 private String hbrvcd; // 流域编码 private String hbrvnm; // 流域名称 + private String rvcd; + private String rvnm; + private String reachcd; } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngEiaapprovalVo.java b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngEiaapprovalVo.java index 21648517..2095ceb5 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngEiaapprovalVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/domain/vo/EngEiaapprovalVo.java @@ -111,6 +111,9 @@ public class EngEiaapprovalVo { @Schema(description = "纬度") private String lttd; + @Schema(description = "纬度") + private String flid; + @Schema(description = "基地排序") private Integer baseStepSort; @@ -122,4 +125,5 @@ public class EngEiaapprovalVo { @Schema(description = "站点排序") private Integer siteStepSort; + } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdEngInfoBHMapper.java b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdEngInfoBHMapper.java index 2a4fa27c..2c886d73 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdEngInfoBHMapper.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdEngInfoBHMapper.java @@ -27,7 +27,7 @@ public interface SdEngInfoBHMapper extends BaseMapper { /** * 根据流域编码查询电站列表(通过关联关系) */ - List selectByRvcd(@Param("rvcd") String rvcd); + List selectByRvcd(@Param("rvcd") String rvcd,@Param("reachcd") String reachcd); /** * 根据基地流域编码查询电站列表 @@ -40,5 +40,14 @@ public interface SdEngInfoBHMapper extends BaseMapper { List selectByHbrvcdList(@Param("hbrvcdList") List hbrvcdList); + /** + * 根据基地流域编码列表批量查询电站 + */ + List selectByRvcdList(@Param("rvcdList") List rvcdList); + /** + * 根据基地流域编码列表批量查询电站 + */ + List selectByReachcdList(@Param("rvcdList") List rvcdList); + List selectStationBasinInfo(); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdFpssBHMapper.java b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdFpssBHMapper.java index 86ac6ee7..e12224c6 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdFpssBHMapper.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/mapper/SdFpssBHMapper.java @@ -17,10 +17,14 @@ public interface SdFpssBHMapper extends BaseMapper { "WHERE 1=1 " + " AND E.BASE_ID = #{baseId} " + " AND F.RSTCD = #{rstcd} " + + " AND E.REACHCD = #{rvcd} " + +// " AND F.RSTCD = #{rstcd} " + " AND F.STNM LIKE '%' || #{stnm} || '%' " + "ORDER BY F.ORDER_INDEX DESC" + "") List selectForDropdownWithBaseId(@Param("rstcd") String rstcd, @Param("stnm") String stnm, - @Param("baseId") String baseId); + @Param("baseId") String baseId, + @Param("rvcd") String rvcd, + @Param("reachcd") String reachcd); } \ No newline at end of file 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 00b83828..537d2e5f 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 @@ -22,4 +22,14 @@ public interface SdRvcdDicMapper extends BaseMapper { * 查询所有根流域 */ List selectRootList(); + + /** + * 注册场景下拉框查询 + */ + List selectRegDropdown(@Param("rvnm") String rvnm, @Param("rvcd") String rvcd); + + /** + * 注册场景下拉框查询,仅返回能被电站表 RVCD 命中的流域 + */ + List selectRegDropdownWithEng(@Param("rvnm") String rvnm, @Param("rvcd") String rvcd); } 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 c26255a1..bedb9d35 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 @@ -38,7 +38,7 @@ public interface ISdEngInfoBHService extends IService { /** * 根据流域编码查询电站 */ - List getByRvcd(String rvcd); + List getByRvcd(String rvcd,String reachcd); /** * 电站下拉列表(根据基地编码筛选 + 支持名称模糊搜索) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFpssBHService.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFpssBHService.java index 42d1fee2..f9960352 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFpssBHService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/ISdFpssBHService.java @@ -16,7 +16,7 @@ public interface ISdFpssBHService extends IService { /** * 设施下拉列表(根据电站编码筛选 + 支持名称模糊搜索 + 支持基地编码筛选) */ - List selectForDropdown(String rstcd, String stnm, String baseId); + List selectForDropdown(String rstcd, String stnm, String baseId,String rvcd,String reachcd); Set getUserAuthorizedStationCodes(); 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 38e299f0..8eee4131 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 @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService; import com.yfd.platform.qgc_base.domain.SdRvcdDic; import java.util.List; +import java.util.Set; /** *

@@ -43,10 +44,16 @@ public interface ISdRvcdDicService extends IService { */ boolean deleteRvcdDic(String rvcd); + Set getUserAuthorizedStationCodes(); + /** * 获取流域树形结构 * @param rvcd 流域编码(可选,为空则返回全部) * @param rvnm 流域名称(可选,用于模糊搜索) */ List getTree(String rvcd, String rvnm); + + List selectForDropdown(String rvnm, String rvcd); + + List regDropdown(String rvnm, String rvcd); } 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 56ac8a13..fea2bf6e 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 @@ -84,8 +84,8 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl getByRvcd(String rvcd) { - return engInfoBHMapper.selectByRvcd(rvcd); + public List getByRvcd(String rvcd,String reachcd) { + return engInfoBHMapper.selectByRvcd(rvcd,reachcd); } @Override @@ -93,12 +93,14 @@ 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) - .in(rvcds != null && !rvcds.isEmpty(), SdEngInfoBH::getRvcd, rvcds) + .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) @@ -141,23 +143,23 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl stationList = engInfoBHMapper.selectByHbrvcd(orgId); + } else if ("RVCD".equals(orgType)) { + List stationList = engInfoBHMapper.selectByRvcd(null,orgId); if (stationList != null) { for (SdEngInfoBH station : stationList) { if (station.getStcd() != null) { stationCodes.add(station.getStcd()); } if (station.getEnnm() != null) { - basinCodes.add(station.getHbrvcd()); + basinCodes.add(station.getReachcd()); } } } @@ -172,7 +174,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl engInfos = this.lambdaQuery() .select(SdEngInfoBH::getStcd) - .in(SdEngInfoBH::getHbrvcd, basinCodes) + .in(SdEngInfoBH::getReachcd, basinCodes) .list(); return engInfos.stream() .map(SdEngInfoBH::getStcd) @@ -207,7 +209,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl wrapper = new LambdaQueryWrapper<>(); wrapper.eq(StringUtils.hasText(baseId), SdEngInfoBH::getBaseId, baseId) .eq(StringUtils.hasText(hbrvcd), SdEngInfoBH::getHbrvcd, hbrvcd) - .in(rvcds != null && !rvcds.isEmpty(), SdEngInfoBH::getRvcd, rvcds) + .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) @@ -373,6 +375,7 @@ public class SdEngInfoBHServiceImpl extends ServiceImpl paramMap = new HashMap<>(); StringBuilder sql = new StringBuilder(buildEiaapprovalBaseSql()); diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssBHServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssBHServiceImpl.java index 101135f6..ea8b2378 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssBHServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdFpssBHServiceImpl.java @@ -66,10 +66,10 @@ public class SdFpssBHServiceImpl extends ServiceImpl i } @Override - public List selectForDropdown(String rstcd, String stnm, String baseId) { + public List selectForDropdown(String rstcd, String stnm, String baseId,String rvcd,String reachcd) { // 管理员直接查询,无需权限过滤 if ("admin".equals(SecurityUtils.getCurrentUsername())) { - return queryFpssList(rstcd, stnm, baseId); + return queryFpssList(rstcd, stnm, baseId,rvcd,reachcd); } // 获取用户有权限的工程编码 @@ -81,7 +81,7 @@ public class SdFpssBHServiceImpl extends ServiceImpl i } // 查询数据 - List result = queryFpssList(rstcd, stnm, baseId); + List result = queryFpssList(rstcd, stnm, baseId,rvcd,reachcd); // 权限过滤 return result.stream() @@ -92,9 +92,9 @@ public class SdFpssBHServiceImpl extends ServiceImpl i /** * 查询过鱼设施列表(公共方法) */ - private List queryFpssList(String rstcd, String stnm, String baseId) { - if (StringUtils.hasText(baseId)) { - return baseMapper.selectForDropdownWithBaseId(rstcd, stnm, baseId); + private List queryFpssList(String rstcd, String stnm, String baseId,String rvcd,String reachcd) { + if (StringUtils.hasText(baseId)||StringUtils.hasText(rvcd)||StringUtils.hasText(reachcd)) { + return baseMapper.selectForDropdownWithBaseId(rstcd, stnm, baseId,rvcd,reachcd); } else { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(StringUtils.hasText(rstcd), SdFpssBH::getRstcd, rstcd) @@ -127,23 +127,23 @@ public class SdFpssBHServiceImpl extends ServiceImpl i if ("STATION".equals(orgType)) { SdEngInfoBH station = sdEngInfoBHMapper.selectById(orgId); if (station != null) { - if (station.getHbrvcd() != null) { - basinCodes.add(station.getHbrvcd()); + if (station.getReachcd() != null) { + basinCodes.add(station.getReachcd()); } if (station.getStcd() != null) { stationCodes.add(station.getStcd()); } } - } else if ("HBRVCD".equals(orgType)) { - List stationList = sdEngInfoBHMapper.selectByHbrvcd(orgId); + } else if ("RVCD".equals(orgType)) { + List stationList = sdEngInfoBHMapper.selectByRvcd(null,orgId); if (stationList != null) { for (SdEngInfoBH station : stationList) { if (station.getStcd() != null) { stationCodes.add(station.getStcd()); } if (station.getEnnm() != null) { - basinCodes.add(station.getHbrvcd()); + basinCodes.add(station.getReachcd()); } } } @@ -158,7 +158,7 @@ public class SdFpssBHServiceImpl extends ServiceImpl i List engInfos = sdEngInfoBHMapper.selectList( new LambdaQueryWrapper() .select(SdEngInfoBH::getStcd) - .in(SdEngInfoBH::getHbrvcd, basinCodes) + .in(SdEngInfoBH::getReachcd, basinCodes) ); return engInfos.stream() .map(SdEngInfoBH::getStcd) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdHbrvDicServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdHbrvDicServiceImpl.java index dde43f59..c0653ad3 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdHbrvDicServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdHbrvDicServiceImpl.java @@ -96,7 +96,7 @@ public class SdHbrvDicServiceImpl extends ServiceImpl stationList = engInfoBHMapper.selectByHbrvcd(orgId); if (stationList != null) { for (SdEngInfoBH station : stationList) { @@ -165,7 +165,7 @@ public class SdHbrvDicServiceImpl extends ServiceImpl stationList = sdEngInfoBHMapper.selectByHbrvcd(orgId); + } else if ("RVCD".equals(orgType)) { + List stationList = sdEngInfoBHMapper.selectByRvcd(null,orgId); if (stationList != null) { for (SdEngInfoBH station : stationList) { if (station.getStcd() != null) { stationCodes.add(station.getStcd()); } if (station.getEnnm() != null) { - basinCodes.add(station.getHbrvcd()); + basinCodes.add(station.getReachcd()); } } } @@ -214,7 +214,7 @@ public class SdHydrobaseServiceImpl extends ServiceImpl engInfos = sdEngInfoBHMapper.selectList( new LambdaQueryWrapper() .select(SdEngInfoBH::getStcd) - .in(SdEngInfoBH::getHbrvcd, basinCodes) + .in(SdEngInfoBH::getReachcd, basinCodes) ); return engInfos.stream() .map(SdEngInfoBH::getStcd) diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdRvcdDicServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdRvcdDicServiceImpl.java index 1b5bdc36..ed0b961b 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdRvcdDicServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/SdRvcdDicServiceImpl.java @@ -1,10 +1,18 @@ package com.yfd.platform.qgc_base.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.qgc_base.domain.SdEngInfoBH; +import com.yfd.platform.qgc_base.domain.SdHbrvDic; import com.yfd.platform.qgc_base.domain.SdRvcdDic; +import com.yfd.platform.qgc_base.mapper.SdEngInfoBHMapper; import com.yfd.platform.qgc_base.mapper.SdRvcdDicMapper; import com.yfd.platform.qgc_base.service.ISdRvcdDicService; +import com.yfd.platform.qgc_data.domain.SysUserDataScope; +import com.yfd.platform.qgc_data.mapper.SysUserDataScopeMapper; +import com.yfd.platform.utils.SecurityUtils; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; @@ -19,6 +27,12 @@ import java.util.stream.Collectors; @Service public class SdRvcdDicServiceImpl extends ServiceImpl implements ISdRvcdDicService { + @Resource + private SdEngInfoBHMapper engInfoBHMapper; + + @Resource + private SysUserDataScopeMapper sysUserDataScopeMapper; + @Override public Page queryPageList(Page page, String rvnm, String prvcd) { return this.page(page, this.lambdaQuery() @@ -103,6 +117,110 @@ public class SdRvcdDicServiceImpl extends ServiceImpl selectForDropdown(String rvnm, String rvcd) { + List dropdownList = this.baseMapper.selectRegDropdown(rvnm, rvcd); + if("admin".equals(SecurityUtils.getCurrentUsername())){ + return dropdownList; + } + Set authorizedStations = getUserAuthorizedStationCodes(); + if (authorizedStations != null && !authorizedStations.isEmpty()) { + List engInfos = engInfoBHMapper.selectList( + new LambdaQueryWrapper() + .select(SdEngInfoBH::getReachcd) + .in(SdEngInfoBH::getStcd, authorizedStations) + ); + List rvcds = engInfos.stream() + .map(SdEngInfoBH::getReachcd) + .filter(id -> id != null && !id.isEmpty()) + .distinct() + .toList(); + + + if (!rvcds.isEmpty()) { + return dropdownList.stream() + .filter(rvDic -> rvcds.contains(rvDic.getRvcd())) + .collect(Collectors.toList()); + } else { + return new ArrayList<>(); + } + }else { + return new ArrayList<>(); + } + } + + + @Override + public Set getUserAuthorizedStationCodes() { + String userId = SecurityUtils.getUserId(); + List sysUserDataScopes = sysUserDataScopeMapper.selectList( + new LambdaQueryWrapper() + .eq(SysUserDataScope::getUserId, userId) + .select(SysUserDataScope::getOrgId, SysUserDataScope::getOrgType) + ); + + if (sysUserDataScopes == null || sysUserDataScopes.isEmpty()) { + return new HashSet<>(); + } + + + Set stationCodes = new HashSet<>(); + Set basinCodes = new HashSet<>(); + + for (SysUserDataScope scope : sysUserDataScopes) { + String orgType = scope.getOrgType(); + String orgId = scope.getOrgId(); + + if ("STATION".equals(orgType)) { + SdEngInfoBH station = engInfoBHMapper.selectById(orgId); + if (station != null) { + if (station.getReachcd() != null) { + basinCodes.add(station.getReachcd()); + } + if (station.getStcd() != null) { + stationCodes.add(station.getStcd()); + } + + } + } else if ("RVCD".equals(orgType)) { + List stationList = engInfoBHMapper.selectByRvcd(null,orgId); + if (stationList != null) { + for (SdEngInfoBH station : stationList) { + if (station.getStcd() != null) { + stationCodes.add(station.getStcd()); + } + if (station.getEnnm() != null) { + basinCodes.add(station.getReachcd()); + } + } + } + + } + } + if (!stationCodes.isEmpty()) { + return stationCodes; + } + + if (!basinCodes.isEmpty()) { + List engInfos = engInfoBHMapper.selectList( + new LambdaQueryWrapper() + .select(SdEngInfoBH::getStcd) + .in(SdEngInfoBH::getReachcd, basinCodes) + ); + return engInfos.stream() + .map(SdEngInfoBH::getStcd) + .collect(Collectors.toSet()); + } + + return stationCodes; + } + + + @Override + public List regDropdown(String rvnm, String rvcd) { + return this.baseMapper.selectRegDropdownWithEng(rvnm, rvcd); + } + private void buildTreeRecursive(SdRvcdDic parent, Map> childrenMap, Set rootRvcdSet) { List children = childrenMap.get(parent.getRvcd()); if (children != null && !children.isEmpty()) { @@ -114,4 +232,8 @@ public class SdRvcdDicServiceImpl extends ServiceImpl()); } } -} \ No newline at end of file + + private boolean isRootRvcd(SdRvcdDic item) { + return item == null || !StringUtils.hasText(item.getPrvcd()) || "0".equals(item.getPrvcd()); + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/TreeStructureServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/TreeStructureServiceImpl.java index 0f627d39..18a0ec2e 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/TreeStructureServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_base/service/impl/TreeStructureServiceImpl.java @@ -61,7 +61,7 @@ public class TreeStructureServiceImpl implements ITreeStructureService { Map> rvcdEngMap = new HashMap<>(); for (SdRvcdDic rvcdDic : rvcdList) { - List engList = engInfoBHMapper.selectByRvcd(rvcdDic.getRvcd()); + List engList = engInfoBHMapper.selectByRvcd(null,rvcdDic.getRvcd()); // 如果提供了电站名称参数,进行模糊匹配筛选 if (StringUtils.hasText(engName) && engList != null) { @@ -83,8 +83,8 @@ public class TreeStructureServiceImpl implements ITreeStructureService { rvcdNode.put("path", rvcdDic.getPath()); rvcdNode.put("orgLevel", 0); rvcdNode.put("grd", rvcdDic.getGrd()); - rvcdNode.put("lgtd", rvcdDic.getLgtd()); - rvcdNode.put("lttd", rvcdDic.getLttd()); +// rvcdNode.put("lgtd", rvcdDic.getLgtd()); +// rvcdNode.put("lttd", rvcdDic.getLttd()); rvcdNode.put("parentId", "0"); List> baseChildren = new ArrayList<>(); @@ -122,8 +122,8 @@ public class TreeStructureServiceImpl implements ITreeStructureService { engNode.put("type", "STATION"); engNode.put("code", eng.getStcd()); engNode.put("name", eng.getEnnm()); - engNode.put("lgtd", eng.getLgtd()); - engNode.put("lttd", eng.getLttd()); +// engNode.put("lgtd", eng.getLgtd()); +// engNode.put("lttd", eng.getLttd()); engNode.put("elev", eng.getElev()); engNode.put("usfl", eng.getUsfl()); engNode.put("bldstt", eng.getBldstt()); @@ -172,7 +172,7 @@ public class TreeStructureServiceImpl implements ITreeStructureService { // 2. 预加载所有流域下的电站(按流域分组) Map> rvcdEngMap = new HashMap<>(); for (SdRvcdDic rvcdDic : rvcdList) { - List engList = engInfoBHMapper.selectByRvcd(rvcdDic.getRvcd()); + List engList = engInfoBHMapper.selectByRvcd(null,rvcdDic.getRvcd()); // 如果提供了电站名称参数,进行模糊匹配筛选 if (StringUtils.hasText(engName) && engList != null) { @@ -195,8 +195,8 @@ public class TreeStructureServiceImpl implements ITreeStructureService { rvcdNode.put("path", rvcdDic.getPath()); rvcdNode.put("orgLevel", 0); rvcdNode.put("grd", rvcdDic.getGrd()); - rvcdNode.put("lgtd", rvcdDic.getLgtd()); - rvcdNode.put("lttd", rvcdDic.getLttd()); +// rvcdNode.put("lgtd", rvcdDic.getLgtd()); +// rvcdNode.put("lttd", rvcdDic.getLttd()); rvcdNode.put("parentId", "0"); List> companyChildren = new ArrayList<>(); @@ -239,8 +239,8 @@ public class TreeStructureServiceImpl implements ITreeStructureService { engNode.put("type", "STATION"); engNode.put("code", eng.getStcd()); engNode.put("name", eng.getEnnm()); - engNode.put("lgtd", eng.getLgtd()); - engNode.put("lttd", eng.getLttd()); +// engNode.put("lgtd", eng.getLgtd()); +// engNode.put("lttd", eng.getLttd()); engNode.put("elev", eng.getElev()); engNode.put("usfl", eng.getUsfl()); engNode.put("bldstt", eng.getBldstt()); @@ -353,23 +353,20 @@ public class TreeStructureServiceImpl implements ITreeStructureService { public List> getRvcdEngTree(String rvcd, String engName) { List> result = new ArrayList<>(); - // 1. 查询流域列表 - List rvcdList; + // 1. 查询流域列表,名称与排序口径对齐注册下拉 + List rvcdList = rvcdDicMapper.selectRegDropdown(null, null); if (StringUtils.hasText(rvcd)) { - rvcdList = rvcdDicMapper.selectByPrvcd(rvcd); - SdRvcdDic singleRvcd = rvcdDicMapper.selectById(rvcd); - if (singleRvcd != null && !rvcdList.contains(singleRvcd)) { - rvcdList = new ArrayList<>(); - rvcdList.add(singleRvcd); - } - } else { - rvcdList = rvcdDicMapper.selectRootList(); + Map rvcdMap = rvcdList.stream() + .collect(Collectors.toMap(SdRvcdDic::getRvcd, item -> item, (left, right) -> left)); + rvcdList = rvcdList.stream() + .filter(item -> isSameOrDescendantRvcd(item, rvcd, rvcdMap)) + .collect(Collectors.toList()); } // 2. 预加载所有流域下的电站(按流域分组) Map> rvcdEngMap = new HashMap<>(); for (SdRvcdDic rvcdDic : rvcdList) { - List engList = engInfoBHMapper.selectByRvcd(rvcdDic.getRvcd()); + List engList = engInfoBHMapper.selectByRvcd(null,rvcdDic.getRvcd()); // 如果提供了电站名称参数,进行模糊匹配筛选 if (StringUtils.hasText(engName) && engList != null) { @@ -392,8 +389,8 @@ public class TreeStructureServiceImpl implements ITreeStructureService { rvcdNode.put("path", rvcdDic.getPath()); rvcdNode.put("orgLevel", 0); rvcdNode.put("grd", rvcdDic.getGrd()); - rvcdNode.put("lgtd", rvcdDic.getLgtd()); - rvcdNode.put("lttd", rvcdDic.getLttd()); +// rvcdNode.put("lgtd", rvcdDic.getLgtd()); +// rvcdNode.put("lttd", rvcdDic.getLttd()); rvcdNode.put("parentId", "0"); // 获取该流域下的所有电站 @@ -406,8 +403,8 @@ public class TreeStructureServiceImpl implements ITreeStructureService { engNode.put("type", "STATION"); engNode.put("code", eng.getStcd()); engNode.put("name", eng.getEnnm()); - engNode.put("lgtd", eng.getLgtd()); - engNode.put("lttd", eng.getLttd()); +// engNode.put("lgtd", eng.getLgtd()); +// engNode.put("lttd", eng.getLttd()); engNode.put("elev", eng.getElev()); engNode.put("usfl", eng.getUsfl()); engNode.put("bldstt", eng.getBldstt()); @@ -428,6 +425,24 @@ public class TreeStructureServiceImpl implements ITreeStructureService { return result; } + private boolean isSameOrDescendantRvcd(SdRvcdDic current, String targetRvcd, Map rvcdMap) { + if (current == null || !StringUtils.hasText(targetRvcd)) { + return false; + } + if (targetRvcd.equals(current.getRvcd())) { + return true; + } + Set visited = new HashSet<>(); + SdRvcdDic cursor = current; + while (cursor != null && StringUtils.hasText(cursor.getPrvcd()) && visited.add(cursor.getRvcd())) { + if (targetRvcd.equals(cursor.getPrvcd())) { + return true; + } + cursor = rvcdMap.get(cursor.getPrvcd()); + } + return false; + } + @Override public List> getBaseEngTree(String baseId, String engName) { List> result = new ArrayList<>(); @@ -483,8 +498,8 @@ public class TreeStructureServiceImpl implements ITreeStructureService { engNode.put("type", "STATION"); engNode.put("code", eng.getStcd()); engNode.put("name", eng.getEnnm()); - engNode.put("lgtd", eng.getLgtd()); - engNode.put("lttd", eng.getLttd()); +// engNode.put("lgtd", eng.getLgtd()); +// engNode.put("lttd", eng.getLttd()); engNode.put("elev", eng.getElev()); engNode.put("usfl", eng.getUsfl()); engNode.put("bldstt", eng.getBldstt()); @@ -565,8 +580,8 @@ public class TreeStructureServiceImpl implements ITreeStructureService { engNode.put("type", "STATION"); engNode.put("code", eng.getStcd()); engNode.put("name", eng.getEnnm()); - engNode.put("lgtd", eng.getLgtd()); - engNode.put("lttd", eng.getLttd()); +// engNode.put("lgtd", eng.getLgtd()); +// engNode.put("lttd", eng.getLttd()); engNode.put("elev", eng.getElev()); engNode.put("usfl", eng.getUsfl()); engNode.put("bldstt", eng.getBldstt()); diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/controller/FishDraftDataController.java b/backend/src/main/java/com/yfd/platform/qgc_data/controller/FishDraftDataController.java index 6c3b3ce6..4399f5e5 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/controller/FishDraftDataController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/controller/FishDraftDataController.java @@ -834,7 +834,7 @@ public class FishDraftDataController { result.put("currentTask", null); return ResponseResult.successData(result); } - String statusText = getStatusText(currentTask.getStatus()); + String statusText = getStatusText(currentTask.getStatus(), currentTask.getSummary()); boolean canImport = isTaskComplete(currentTask.getStatus()); Map taskInfo = new HashMap<>(); @@ -848,13 +848,14 @@ public class FishDraftDataController { return ResponseResult.successData(result); } - private String getStatusText(String status) { + private String getStatusText(String status, String failureReason) { return switch (status) { case "UPLOADED" -> "已上传,等待解析"; case "PARSING" -> "解析中"; case "VALIDATING" -> "校验中"; - case "VALIDATED" -> "已校验,待确认导入"; - case "FAILED" -> "导入失败"; + case "FAILED" -> (failureReason != null && !failureReason.isBlank()) + ? failureReason + : "导入失败"; case "CONFIRMED" -> "已完成"; case "CANCELLED" -> "已取消"; default -> "未知状态"; @@ -886,7 +887,7 @@ public class FishDraftDataController { int failCount = lastTask.getFailCount() != null ? lastTask.getFailCount() : 0; int progressPercent = totalCount > 0 ? (int) ((successCount + failCount) * 100.0 / totalCount) : 0; - Map taskInfo = buildTaskInfoMap(lastTask, getStatusText(lastTask.getStatus()), + Map taskInfo = buildTaskInfoMap(lastTask, getStatusText(lastTask.getStatus(),lastTask.getSummary()), totalCount, successCount, failCount, progressPercent); Map resultInfo = buildResultInfoMap(importResult); @@ -1095,21 +1096,25 @@ public class FishDraftDataController { private void validateAndNormalizeData(FishDraftData data, FishImportResult.FishImportRow importRow, List warnings) { if (data.getStcd() == null || data.getStcd().isEmpty()) { - warnings.add("stcd"); + addWarning(warnings, "stcd"); } else { String stcd = fishImportService.resolveFpssCode(data.getStcd(), data.getStnm()); if (stcd == null) { - warnings.add("stcd"); + addWarning(warnings, "stcd"); + } else { + data.setStcd(stcd); } } if (data.getRstcd() != null && !data.getRstcd().isEmpty()) { String stationCode = fishImportService.resolveStationCode(data.getRstcd(), data.getEnnm()); if (stationCode == null) { - warnings.add("rstcd"); + addWarning(warnings, "rstcd"); + } else { + data.setRstcd(stationCode); } } else { - warnings.add("rstcd"); + addWarning(warnings, "rstcd"); } // if (data.getBaseId() != null && !data.getBaseId().isEmpty()) { @@ -1122,14 +1127,18 @@ public class FishDraftDataController { if (data.getHbrvcd() != null && !data.getHbrvcd().isEmpty()) { String baseId = fishImportService.resolveHbrvcdCode(data.getHbrvcd(), data.getHbrvnm()); if (baseId == null) { - warnings.add("hbrvcd"); + addWarning(warnings, "hbrvcd"); + } else { + data.setHbrvcd(baseId); } } if (data.getRvcd() != null && !data.getRvcd().isEmpty()) { - String rvcd = fishImportService.resolveRiverCode(data.getRvcd(), data.getRvcd()); + String rvcd = fishImportService.resolveRiverCode(data.getRvcd(), data.getRvnm()); if (rvcd == null) { - warnings.add("rvcd"); + addWarning(warnings, "rvcd"); + } else { + data.setRvcd(rvcd); } } @@ -1145,55 +1154,64 @@ public class FishDraftDataController { // } if (data.getFtp() == null || data.getFtp().isEmpty()) { - warnings.add("ftp"); + addWarning(warnings, "ftp"); } else { String ftpCode = fishImportService.resolveFishDictCode(data.getFtp(), data.getFtpName()); if (ftpCode == null) { - warnings.add("ftp"); + addWarning(warnings, "ftp"); + } else { + data.setFtp(ftpCode); } } if (data.getFcnt() == null) { - warnings.add("fcnt"); + addWarning(warnings, "fcnt"); } if (data.getStrdt() == null) { - warnings.add("strdt"); + addWarning(warnings, "strdt"); } if (data.getEnddt() != null && data.getStrdt() != null && data.getEnddt().before(data.getStrdt())) { - warnings.add("enddt"); + addWarning(warnings, "enddt"); } if (data.getDirection() == null || data.getDirection().isEmpty()) { - warnings.add("direction"); + addWarning(warnings, "direction"); } else { String direction = fishImportService.resolveDirection(data.getDirection().trim(), importRow); if (direction == null) { - warnings.add("direction"); + addWarning(warnings, "direction"); } } if (data.getIsfs() == null) { - warnings.add("isfs"); + addWarning(warnings, "isfs"); } else { String isfs = fishImportService.resolveIsfs(String.valueOf(data.getIsfs()), importRow); if (isfs == null) { - warnings.add("isfs"); + addWarning(warnings, "isfs"); } } if (StringUtils.hasText(data.getHbrvcd()) && StringUtils.hasText(data.getRstcd())) { if (!fishImportService.validateStationBelongsToBase(data.getRstcd(), data.getHbrvcd())) { - warnings.add("hbrvcd"); - warnings.add("rstcd"); + addWarning(warnings, "hbrvcd"); + addWarning(warnings, "rstcd"); + } + } + + if (StringUtils.hasText(data.getRvcd()) && StringUtils.hasText(data.getRstcd())) { + if (!fishImportService.validateStationBelongsToRiver(data.getRstcd(), data.getRvcd())) { + addWarning(warnings, "rvcd"); + addWarning(warnings, "rstcd"); } } if (StringUtils.hasText(data.getRstcd()) && StringUtils.hasText(data.getStcd())) { if (!fishImportService.validateFpssBelongsToStation(data.getStcd(), data.getRstcd())) { - warnings.add("stcd"); - warnings.add("rstcd"); + addWarning(warnings, "stcd"); + addWarning(warnings, "rstcd"); } } @@ -1202,6 +1220,12 @@ public class FishDraftDataController { // } } + private void addWarning(List warnings, String field) { + if (!warnings.contains(field)) { + warnings.add(field); + } + } + @PostMapping("/validateAndMatchRow") @Operation(summary = "校验数据并匹配到成功或失败列表") public ResponseResult validateAndMatchRow(@RequestBody FishImportRowRequest request) { @@ -1324,4 +1348,4 @@ public class FishDraftDataController { Thread.currentThread().interrupt(); } } -} \ No newline at end of file +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/domain/ApprovalMain.java b/backend/src/main/java/com/yfd/platform/qgc_data/domain/ApprovalMain.java index 495747fe..3c44aa81 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/domain/ApprovalMain.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/domain/ApprovalMain.java @@ -94,6 +94,16 @@ public class ApprovalMain implements Serializable { */ private String hbrvnm; + /** + * 流域 + */ + private String rvcd; + + /** + * 流域 + */ + private String rvnm; + /** * 电站 */ diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/domain/FishDraftData.java b/backend/src/main/java/com/yfd/platform/qgc_data/domain/FishDraftData.java index f3f02325..567d883d 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/domain/FishDraftData.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/domain/FishDraftData.java @@ -237,6 +237,12 @@ public class FishDraftData implements Serializable { @TableField(exist = false) private String rvcd; + /** + * 流域编码 + */ + @TableField(exist = false) + private String rvnm; + /** * 基地流域编码 */ diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/domain/ImportTaskRow.java b/backend/src/main/java/com/yfd/platform/qgc_data/domain/ImportTaskRow.java index 71527dc8..3112c103 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/domain/ImportTaskRow.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/domain/ImportTaskRow.java @@ -47,6 +47,8 @@ public class ImportTaskRow implements Serializable { private String rvcd; + private String rvnm; + private String baseId; private String baseName; diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/domain/vo/FishDraftDataVO.java b/backend/src/main/java/com/yfd/platform/qgc_data/domain/vo/FishDraftDataVO.java index 8f58d3ee..b87da039 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/domain/vo/FishDraftDataVO.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/domain/vo/FishDraftDataVO.java @@ -202,6 +202,11 @@ public class FishDraftDataVO implements Serializable { */ private String rvcd; + /** + * 流域名称(全路径) + */ + private String rvnm; + /** * 电站经度(电站表) */ @@ -241,4 +246,4 @@ public class FishDraftDataVO implements Serializable { * 基地流域编码 */ private String hbrvnm; -} \ No newline at end of file +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/mapper/FishDraftDataMapper.java b/backend/src/main/java/com/yfd/platform/qgc_data/mapper/FishDraftDataMapper.java index baa8d260..994d4e48 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/mapper/FishDraftDataMapper.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/mapper/FishDraftDataMapper.java @@ -23,6 +23,7 @@ public interface FishDraftDataMapper extends BaseMapper { @Param("stcd") String stcd, @Param("rstcd") String rstcd, @Param("baseId") String baseId, + @Param("rvcd") String rvcd, @Param("direction") String direction, @Param("status") String status, @Param("ftp") String ftp, @@ -38,6 +39,7 @@ public interface FishDraftDataMapper extends BaseMapper { List selectJoinList(@Param("stcd") String stcd, @Param("rstcd") String rstcd, @Param("baseId") String baseId, + @Param("rvcd") String rvcd, @Param("direction") String direction, @Param("status") String status, @Param("ftp") String ftp, @@ -79,4 +81,4 @@ public interface FishDraftDataMapper extends BaseMapper { */ @Select("SELECT COUNT(*) FROM FISH_DRAFT_DATA WHERE APPROVAL_ID = #{approvalId}") int countByApprovalId(@Param("approvalId") Long approvalId); -} \ No newline at end of file +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/mapper/FishStatisticsMapper.java b/backend/src/main/java/com/yfd/platform/qgc_data/mapper/FishStatisticsMapper.java index f0df6603..8bb8fdd8 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/mapper/FishStatisticsMapper.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/mapper/FishStatisticsMapper.java @@ -9,9 +9,11 @@ public interface FishStatisticsMapper { List queryStatistics(@Param("basinCode") String basinCode, @Param("stationCode") String stationCode, + @Param("reportMonth") String reportMonth, @Param("startRow") int startRow, @Param("endRow") int endRow); int countStatistics(@Param("basinCode") String basinCode, - @Param("stationCode") String stationCode); -} \ No newline at end of file + @Param("stationCode") String stationCode, + @Param("reportMonth") String reportMonth); +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/mapper/ImportTaskMapper.java b/backend/src/main/java/com/yfd/platform/qgc_data/mapper/ImportTaskMapper.java index d811e589..42cda28b 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/mapper/ImportTaskMapper.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/mapper/ImportTaskMapper.java @@ -40,7 +40,7 @@ public interface ImportTaskMapper extends BaseMapper { @Select("SELECT * FROM (" + "SELECT ID, IMPORT_NO, BIZ_TYPE, FILE_NAME, FILE_SIZE, FILE_PATH, TEMP_DIR, " + - "TOTAL_COUNT, SUCCESS_COUNT, FAIL_COUNT, STATUS, ERROR_MSG " + + "TOTAL_COUNT, SUCCESS_COUNT,SUMMARY, FAIL_COUNT, STATUS, ERROR_MSG " + "FROM IMPORT_TASK " + "WHERE UPLOAD_USER_ID = #{uploadUserId} " + "AND STATUS IN ('UPLOADED', 'PARSING', 'VALIDATED','FAILED') " + diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/service/IFishImportService.java b/backend/src/main/java/com/yfd/platform/qgc_data/service/IFishImportService.java index 1aafd8a1..44bfdb8d 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/service/IFishImportService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/service/IFishImportService.java @@ -50,10 +50,12 @@ public interface IFishImportService { boolean validateStationBelongsToBase(String stationCode, String baseId); + boolean validateStationBelongsToRiver(String stationCode, String rvcd); + boolean validateFpssBelongsToStation(String fpssCode, String stationCode); void processAttachments(FishImportResult result, ZipFileUtil.ZipContent zipContent); void processAttachmentsAsync(List dataList, String tempDir); -} \ No newline at end of file +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishDraftDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishDraftDataServiceImpl.java index 2d723be6..5a150f58 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishDraftDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishDraftDataServiceImpl.java @@ -7,6 +7,8 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.common.DataSourceLoadOptionsBase; import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.qgc_base.domain.SdRvcdDic; +import com.yfd.platform.qgc_base.mapper.SdRvcdDicMapper; import com.yfd.platform.qgc_data.domain.ApprovalMain; import com.yfd.platform.qgc_data.domain.FishDraftData; import com.yfd.platform.qgc_data.domain.SysUserDataScope; @@ -73,6 +75,10 @@ public class FishDraftDataServiceImpl extends ServiceImpl resultPage = fishDraftDataMapper.selectJoinPage(page, stcd, rstcd, baseId, direction, status, ftp, startTime, endTime,userId,hbrvcd,approvalId); + Page resultPage = fishDraftDataMapper.selectJoinPage(page, stcd, rstcd, baseId, rvcd, direction, status, ftp, startTime, endTime,userId,hbrvcd,approvalId); fillUserNames(resultPage.getRecords()); return resultPage; } @@ -117,13 +124,14 @@ public class FishDraftDataServiceImpl extends ServiceImpl list = fishDraftDataMapper.selectJoinList(stcd, rstcd, baseId, direction, status, ftp, startTime, endTime); + List list = fishDraftDataMapper.selectJoinList(stcd, rstcd, baseId, rvcd, direction, status, ftp, startTime, endTime); fillUserNames(list); return list; } @@ -342,15 +350,15 @@ public class FishDraftDataServiceImpl extends ServiceImpl stationList = engInfoBHMapper.selectByHbrvcd(orgId); + List stationList = engInfoBHMapper.selectByRvcd(null,orgId); if (stationList != null) { for (SdEngInfoBH station : stationList) { if (station.getStcd() != null) { @@ -359,14 +367,17 @@ public class FishDraftDataServiceImpl extends ServiceImpl columnIndexMap = new HashMap<>(EXCEL_COLUMN_INDEX_MAPPING); - Set allowedHbrvcdSet = new HashSet<>(); + Set allowedRvcdSet = new HashSet<>(); Set directStcdSet = new HashSet<>(); List sdFpssList=new ArrayList<>(); - List allowedHbrvcdList = new ArrayList<>(); + List allowedRvcdList = new ArrayList<>(); List directStcdList = new ArrayList<>(); if (uploadUserId != null) { List permissions = userDataScopeMapper.selectValidPermissions(uploadUserId); @@ -203,8 +204,8 @@ public class FishImportServiceImpl implements IFishImportService { continue; } - if ("HBRVCD".equals(orgType)) { - allowedHbrvcdSet.add(orgId); + if ("RVCD".equals(orgType)) { + allowedRvcdSet.add(orgId); } else if ("STATION".equals(orgType)) { directStcdSet.add(orgId); } @@ -213,9 +214,23 @@ public class FishImportServiceImpl implements IFishImportService { } - if (!allowedHbrvcdSet.isEmpty() || !directStcdSet.isEmpty()) { - if (!allowedHbrvcdSet.isEmpty()) { - List stationsFromHbrv = engInfoBHMapper.selectByHbrvcdList(new ArrayList<>(allowedHbrvcdSet)); + Map rvcdMap = new HashMap<>(); + if (!allowedRvcdSet.isEmpty() || !directStcdSet.isEmpty()) { + if (!allowedRvcdSet.isEmpty()) { + List activeRvcdList = rvcdDicMapper.selectList(new LambdaQueryWrapper() + .eq(SdRvcdDic::getEnabled, 1) + .eq(SdRvcdDic::getIsDeleted, 0) + .select(SdRvcdDic::getRvcd, SdRvcdDic::getRvnm, SdRvcdDic::getPrvcd, SdRvcdDic::getOrderIndex)); + if (activeRvcdList != null) { + for (SdRvcdDic rvcdDic : activeRvcdList) { + if (StrUtil.isNotBlank(rvcdDic.getRvcd())) { + rvcdMap.put(rvcdDic.getRvcd(), rvcdDic); + } + } + } + + Set expandedReachcdSet = expandReachcdScope(allowedRvcdSet, rvcdMap); + List stationsFromHbrv = engInfoBHMapper.selectByReachcdList(new ArrayList<>(expandedReachcdSet)); for (SdEngInfoBH station : stationsFromHbrv) { if (station.getStcd() != null) { directStcdSet.add(station.getStcd()); @@ -229,16 +244,42 @@ public class FishImportServiceImpl implements IFishImportService { if (station.getStcd() != null) { directStcdSet.add(station.getStcd()); } - if (station.getHbrvcd() != null) { - allowedHbrvcdSet.add(station.getHbrvcd()); + if (station.getReachcd() != null) { + allowedRvcdSet.add(station.getReachcd()); } } } } - if(!allowedHbrvcdSet.isEmpty()){ - List sdHbrvDics = sdHbrvDicMapper.selectList(new LambdaQueryWrapper().in(SdHbrvDic::getHbrvcd, allowedHbrvcdSet).select(SdHbrvDic::getHbrvcd, SdHbrvDic::getHbrvnm)); - allowedHbrvcdList.addAll(sdHbrvDics); + if(!allowedRvcdSet.isEmpty()){ + if (rvcdMap.isEmpty()) { + List activeRvcdList = rvcdDicMapper.selectList(new LambdaQueryWrapper() + .eq(SdRvcdDic::getEnabled, 1) + .eq(SdRvcdDic::getIsDeleted, 0) + .select(SdRvcdDic::getRvcd, SdRvcdDic::getRvnm, SdRvcdDic::getPrvcd, SdRvcdDic::getOrderIndex)); + if (activeRvcdList != null) { + for (SdRvcdDic rvcdDic : activeRvcdList) { + if (StrUtil.isNotBlank(rvcdDic.getRvcd())) { + rvcdMap.put(rvcdDic.getRvcd(), rvcdDic); + } + } + } + } + + Map rvcdDisplayNameMap = new HashMap<>(); + Map rvcdOrderPathMap = new HashMap<>(); + for (String rvcd : allowedRvcdSet) { + rvcdDisplayNameMap.put(rvcd, buildRvcdDisplayName(rvcd, rvcdMap, rvcdDisplayNameMap)); + rvcdOrderPathMap.put(rvcd, buildRvcdOrderPath(rvcd, rvcdMap, rvcdOrderPathMap)); + } + + allowedRvcdList.addAll(allowedRvcdSet.stream() + .map(rvcdMap::get) + .filter(Objects::nonNull) + .peek(item -> item.setRvnm(rvcdDisplayNameMap.getOrDefault(item.getRvcd(), item.getRvnm()))) + .sorted(Comparator.comparing((SdRvcdDic item) -> rvcdOrderPathMap.getOrDefault(item.getRvcd(), "~~~~~~~~~~")) + .thenComparing(SdRvcdDic::getRvcd, Comparator.nullsLast(String::compareTo))) + .toList()); } if (!directStcdSet.isEmpty()) { @@ -251,6 +292,20 @@ public class FishImportServiceImpl implements IFishImportService { } + Map allowedRvcdNameToCodeMap = allowedRvcdList.stream() + .filter(item -> StrUtil.isNotBlank(item.getRvnm()) && StrUtil.isNotBlank(item.getRvcd())) + .collect(Collectors.toMap(SdRvcdDic::getRvnm, SdRvcdDic::getRvcd, (left, right) -> left, LinkedHashMap::new)); + Map allowedRvcdLastNameToCodeMap = buildAllowedRvcdLastNameToCodeMap(allowedRvcdList); + Map allowedRvcdCodeToNameMap = allowedRvcdList.stream() + .filter(item -> StrUtil.isNotBlank(item.getRvcd()) && StrUtil.isNotBlank(item.getRvnm())) + .collect(Collectors.toMap(SdRvcdDic::getRvcd, SdRvcdDic::getRvnm, (left, right) -> left, LinkedHashMap::new)); + Map directStationNameToCodeMap = directStcdList.stream() + .filter(item -> StrUtil.isNotBlank(item.getEnnm()) && StrUtil.isNotBlank(item.getStcd())) + .collect(Collectors.toMap(SdEngInfoBH::getEnnm, SdEngInfoBH::getStcd, (left, right) -> left, LinkedHashMap::new)); + Map fpssNameToCodeMap = sdFpssList.stream() + .filter(item -> StrUtil.isNotBlank(item.getStnm()) && StrUtil.isNotBlank(item.getStcd())) + .collect(Collectors.toMap(SdFpssBH::getStnm, SdFpssBH::getStcd, (left, right) -> left, LinkedHashMap::new)); + int totalRows = sheet.getLastRowNum(); for (int i = 1; i <= totalRows; i++) { Row row = sheet.getRow(i); @@ -258,7 +313,9 @@ public class FishImportServiceImpl implements IFishImportService { continue; } - FishImportResult.FishImportRow importRow = parseRow(result, row, columnIndexMap, i, uploadUserId,allowedHbrvcdList,directStcdList,sdFpssList); + FishImportResult.FishImportRow importRow = parseRow(result, row, columnIndexMap, i, uploadUserId, + allowedRvcdNameToCodeMap, allowedRvcdLastNameToCodeMap, allowedRvcdCodeToNameMap, + directStationNameToCodeMap, fpssNameToCodeMap); result.setTotalCount(result.getTotalCount() + 1); if (importRow.getData() != null && importRow.getWarnings().isEmpty()) { result.addSuccessRow(importRow); @@ -274,7 +331,12 @@ public class FishImportServiceImpl implements IFishImportService { return result; } - private FishImportResult.FishImportRow parseRow(FishImportResult result, Row row, Map columnIndexMap, int rowIndex, String userId,List allowedHbrvcdList,List directStcdList,List sdFpssList) { + private FishImportResult.FishImportRow parseRow(FishImportResult result, Row row, Map columnIndexMap, + int rowIndex, String userId, Map allowRvcdNameToCodeMap, + Map allowRvcdLastNameToCodeMap, + Map allowRvcdCodeToNameMap, + Map directStationNameToCodeMap, + Map fpssNameToCodeMap) { FishImportResult.FishImportRow importRow = new FishImportResult.FishImportRow(rowIndex); @@ -294,7 +356,7 @@ public class FishImportServiceImpl implements IFishImportService { data.setEnnm(cellValue.trim()); data.setRstcd(cellValue); } else { - String stcd = directStcdList.stream().filter(sdEngInfoBH -> sdEngInfoBH.getEnnm().equals(cellValue.trim())).map(SdEngInfoBH::getStcd).findFirst().orElse( null); + String stcd = directStationNameToCodeMap.get(cellValue.trim()); if (StrUtil.isBlank(stcd)) { importRow.getWarnings().add("rstcd"); data.setEnnm(cellValue.trim()); @@ -323,13 +385,19 @@ public class FishImportServiceImpl implements IFishImportService { } break; case "rvcd": - if (StringUtils.hasText(cellValue)) { - String rvcd = resolveRiverCode(cellValue.trim()); - if (rvcd == null) { - importRow.getWarnings().add(fieldName); - data.setRvcd(cellValue); + if (!StringUtils.hasText(cellValue)) { + importRow.getWarnings().add("rvcd"); + data.setRvcd(cellValue); + data.setRvnm(cellValue); + } else { + String rvcdCode = resolveAllowedRvcdCode(cellValue.trim(), allowRvcdNameToCodeMap, allowRvcdLastNameToCodeMap); + if (StrUtil.isBlank(rvcdCode)) { + importRow.getWarnings().add("rvcd"); + data.setRvcd(cellValue.trim()); + data.setRvnm(cellValue.trim()); } else { - data.setRvcd(rvcd); + data.setRvcd(rvcdCode); + data.setRvnm(allowRvcdCodeToNameMap.getOrDefault(rvcdCode, cellValue.trim())); } } break; @@ -338,17 +406,18 @@ public class FishImportServiceImpl implements IFishImportService { importRow.getWarnings().add("hbrvcd"); data.setHbrvcd(cellValue); data.setHbrvnm(cellValue); - } else { - String hbrvcdCode = allowedHbrvcdList.stream().filter(sdHbrvDic -> sdHbrvDic.getHbrvnm().equals(cellValue.trim())).map(SdHbrvDic::getHbrvcd).findFirst().orElse( null); - if (StrUtil.isBlank(hbrvcdCode)) { - importRow.getWarnings().add("hbrvcd"); - data.setHbrvcd(cellValue.trim()); - data.setHbrvnm(cellValue.trim()); - } else { - data.setHbrvcd(hbrvcdCode); - data.setHbrvnm(cellValue.trim()); - } } +// else { +// String hbrvcdCode = allowedHbrvcdList.stream().filter(sdHbrvDic -> sdHbrvDic.getHbrvnm().equals(cellValue.trim())).map(SdHbrvDic::getHbrvcd).findFirst().orElse( null); +// if (StrUtil.isBlank(hbrvcdCode)) { +// importRow.getWarnings().add("hbrvcd"); +// data.setHbrvcd(cellValue.trim()); +// data.setHbrvnm(cellValue.trim()); +// } else { +// data.setHbrvcd(hbrvcdCode); +// data.setHbrvnm(cellValue.trim()); +// } +// } // break; case "tm": @@ -529,7 +598,7 @@ public class FishImportServiceImpl implements IFishImportService { importRow.getWarnings().add("stcd"); data.setStcd(cellValue); } else { - String stcd = sdFpssList.stream().filter(sdFpssBH -> sdFpssBH.getStnm().equals(cellValue.trim())).map(SdFpssBH::getStcd).findFirst().orElse( null); + String stcd = fpssNameToCodeMap.get(cellValue.trim()); if (StrUtil.isBlank(stcd)) { importRow.getWarnings().add("stcd"); data.setStcd(cellValue.trim()); @@ -554,6 +623,115 @@ public class FishImportServiceImpl implements IFishImportService { return importRow; } + private Map buildAllowedRvcdLastNameToCodeMap(List allowedRvcdList) { + Map uniqueMap = new LinkedHashMap<>(); + Set duplicateNames = new HashSet<>(); + for (SdRvcdDic item : allowedRvcdList) { + if (item == null || StrUtil.isBlank(item.getRvnm()) || StrUtil.isBlank(item.getRvcd())) { + continue; + } + String lastName = extractLastRvcdName(item.getRvnm()); + if (StrUtil.isBlank(lastName)) { + continue; + } + String existed = uniqueMap.putIfAbsent(lastName, item.getRvcd()); + if (existed != null && !Objects.equals(existed, item.getRvcd())) { + duplicateNames.add(lastName); + } + } + duplicateNames.forEach(uniqueMap::remove); + return uniqueMap; + } + + private String resolveAllowedRvcdCode(String inputName, Map allowRvcdNameToCodeMap, + Map allowRvcdLastNameToCodeMap) { + if (StrUtil.isBlank(inputName)) { + return null; + } + String exactCode = allowRvcdNameToCodeMap.get(inputName); + if (StrUtil.isNotBlank(exactCode)) { + return exactCode; + } + return allowRvcdLastNameToCodeMap.get(extractLastRvcdName(inputName)); + } + + private String extractLastRvcdName(String rvnm) { + if (StrUtil.isBlank(rvnm)) { + return null; + } + int separatorIndex = rvnm.lastIndexOf('-'); + return separatorIndex >= 0 ? StrUtil.trim(rvnm.substring(separatorIndex + 1)) : StrUtil.trim(rvnm); + } + + private Set expandReachcdScope(Set allowedRvcdSet, Map rvcdMap) { + if (allowedRvcdSet == null || allowedRvcdSet.isEmpty() || rvcdMap == null || rvcdMap.isEmpty()) { + return Collections.emptySet(); + } + Set result = new LinkedHashSet<>(); + for (String rvcd : rvcdMap.keySet()) { + if (isInRvcdScope(rvcd, allowedRvcdSet, rvcdMap)) { + result.add(rvcd); + } + } + return result; + } + + private boolean isInRvcdScope(String currentRvcd, Set allowedRvcdSet, Map rvcdMap) { + String code = currentRvcd; + Set visited = new HashSet<>(); + while (StrUtil.isNotBlank(code) && visited.add(code)) { + if (allowedRvcdSet.contains(code)) { + return true; + } + SdRvcdDic current = rvcdMap.get(code); + if (current == null || StrUtil.isBlank(current.getPrvcd()) || "0".equals(current.getPrvcd())) { + break; + } + code = current.getPrvcd(); + } + return false; + } + + private String buildRvcdDisplayName(String rvcd, Map rvcdMap, Map cache) { + if (StrUtil.isBlank(rvcd)) { + return null; + } + if (cache.containsKey(rvcd)) { + return cache.get(rvcd); + } + SdRvcdDic current = rvcdMap.get(rvcd); + if (current == null) { + return rvcd; + } + String currentName = StrUtil.blankToDefault(current.getRvnm(), rvcd); + String parentCode = current.getPrvcd(); + if (StrUtil.isBlank(parentCode) || "0".equals(parentCode)) { + return currentName; + } + String parentName = buildRvcdDisplayName(parentCode, rvcdMap, cache); + return StrUtil.isBlank(parentName) ? currentName : parentName + "-" + currentName; + } + + private String buildRvcdOrderPath(String rvcd, Map rvcdMap, Map cache) { + if (StrUtil.isBlank(rvcd)) { + return null; + } + if (cache.containsKey(rvcd)) { + return cache.get(rvcd); + } + SdRvcdDic current = rvcdMap.get(rvcd); + if (current == null) { + return "~~~~~~~~~~/" + rvcd; + } + String currentSegment = String.format("%010d", current.getOrderIndex() == null ? 999999999 : current.getOrderIndex()); + String parentCode = current.getPrvcd(); + if (StrUtil.isBlank(parentCode) || "0".equals(parentCode)) { + return currentSegment; + } + String parentPath = buildRvcdOrderPath(parentCode, rvcdMap, cache); + return StrUtil.isBlank(parentPath) ? currentSegment : parentPath + "/" + currentSegment; + } + /** * 解析鱼类体长范围 @@ -618,7 +796,7 @@ public class FishImportServiceImpl implements IFishImportService { private void validateStationFpssRelation(FishDraftData data, FishImportResult.FishImportRow importRow) { - if (importRow.getWarnings().contains("hbrvcd")) { + if (importRow.getWarnings().contains("rvcd")) { if (!importRow.getWarnings().contains("rstcd")) { importRow.getWarnings().add("rstcd"); } @@ -824,248 +1002,343 @@ public class FishImportServiceImpl implements IFishImportService { public String resolveStationCode(String stationName) { - if (stationName == null) { + String normalizedName = normalizeInput(stationName); + if (!StringUtils.hasText(normalizedName)) { return null; } - String lowerName = stationName.toLowerCase().trim(); - if (STATION_NAME_CACHE.containsKey(lowerName)) { - return STATION_NAME_CACHE.get(lowerName); + SdEngInfoBH exactMatch = findFirst(engInfoBHMapper.selectList(new LambdaQueryWrapper() + .select(SdEngInfoBH::getStcd, SdEngInfoBH::getEnnm) + .eq(SdEngInfoBH::getEnnm, normalizedName))); + if (exactMatch != null) { + return exactMatch.getStcd(); } - for (Map.Entry entry : STATION_NAME_CACHE.entrySet()) { - if (entry.getKey().contains(lowerName)) { - return entry.getValue(); - } - } - return null; + SdEngInfoBH fuzzyMatch = findFirst(engInfoBHMapper.selectList(new LambdaQueryWrapper() + .select(SdEngInfoBH::getStcd, SdEngInfoBH::getEnnm) + .like(SdEngInfoBH::getEnnm, normalizedName))); + return fuzzyMatch == null ? null : fuzzyMatch.getStcd(); } public String resolveFpssCode(String name) { - if (name == null) { + String normalizedName = normalizeInput(name); + if (!StringUtils.hasText(normalizedName)) { return null; } - String lowerName = name.toLowerCase().trim(); - if (FPSS_BH_CACHE.containsKey(lowerName)) { - return FPSS_BH_CACHE.get(lowerName); + SdFpssBH exactMatch = findFirst(fpssBHMapper.selectList(new LambdaQueryWrapper() + .select(SdFpssBH::getStcd, SdFpssBH::getStnm, SdFpssBH::getRstcd) + .eq(SdFpssBH::getStnm, normalizedName))); + if (exactMatch != null) { + return exactMatch.getStcd(); } - for (Map.Entry entry : FPSS_BH_CACHE.entrySet()) { - if (entry.getKey().contains(lowerName)) { - return entry.getValue(); - } - } - return null; + SdFpssBH fuzzyMatch = findFirst(fpssBHMapper.selectList(new LambdaQueryWrapper() + .select(SdFpssBH::getStcd, SdFpssBH::getStnm, SdFpssBH::getRstcd) + .like(SdFpssBH::getStnm, normalizedName))); + return fuzzyMatch == null ? null : fuzzyMatch.getStcd(); } @Override public String resolveStationCode(String code, String stationName) { - if (code == null && stationName == null) { + String normalizedCode = normalizeInput(code); +// String normalizedName = normalizeInput(stationName); + if (!StringUtils.hasText(normalizedCode)) { return null; } - loadStationAndBaseCache(); - String lowerCode = code != null ? code.trim().toLowerCase() : null; - String lowerName = stationName != null ? stationName.trim().toLowerCase() : null; - if (lowerCode != null && lowerName != null) { - String cachedName = STATION_CODE_TO_NAME_CACHE.get(lowerCode); - if (cachedName != null && cachedName.equals(lowerName)) { - return code.trim(); + if (StringUtils.hasText(normalizedCode)) { + SdEngInfoBH exact = findFirst(engInfoBHMapper.selectList(new LambdaQueryWrapper() + .select(SdEngInfoBH::getStcd, SdEngInfoBH::getEnnm) + .eq(SdEngInfoBH::getStcd, normalizedCode))); +// .eq(SdEngInfoBH::getEnnm, normalizedName))); + if (exact != null) { + return exact.getStcd(); } } - String resultByName = resolveStationCode(stationName); - if (resultByName != null && resultByName.equalsIgnoreCase(code)) { - return resultByName; - } +// if (StringUtils.hasText(normalizedCode)) { +// SdEngInfoBH byCode = engInfoBHMapper.selectById(normalizedCode); +// if (byCode != null && (!StringUtils.hasText(normalizedName) || normalizedName.equals(byCode.getEnnm()))) { +// return byCode.getStcd(); +// } +// } +// if (StringUtils.hasText(normalizedName)) { +// String resultByName = resolveStationCode(normalizedName); +// if (!StringUtils.hasText(normalizedCode) || normalizedCode.equalsIgnoreCase(resultByName)) { +// return resultByName; +// } +// } return null; } @Override public String resolveFpssCode(String code, String name) { - if (code == null && name == null) { + String normalizedCode = normalizeInput(code); +// String normalizedName = normalizeInput(name); + if (!StringUtils.hasText(normalizedCode)) { return null; } - loadStationAndBaseCache(); - String lowerCode = code != null ? code.trim().toLowerCase() : null; - String lowerName = name != null ? name.trim().toLowerCase() : null; - if (lowerCode != null && lowerName != null) { - String cachedName = FPSS_CODE_TO_NAME_CACHE.get(lowerCode); - if (cachedName != null && cachedName.equals(lowerName)) { - return code.trim(); + if (StringUtils.hasText(normalizedCode)) { + SdFpssBH exact = findFirst(fpssBHMapper.selectList(new LambdaQueryWrapper() + .select(SdFpssBH::getStcd, SdFpssBH::getStnm, SdFpssBH::getRstcd) + .eq(SdFpssBH::getStcd, normalizedCode))); +// .eq(SdFpssBH::getStnm, normalizedName))); + if (exact != null) { + return exact.getStcd(); } } - String resultByName = resolveFpssCode(name); - if (resultByName != null && resultByName.equalsIgnoreCase(code)) { - return resultByName; - } +// if (StringUtils.hasText(normalizedCode)) { +// SdFpssBH byCode = fpssBHMapper.selectById(normalizedCode); +// if (byCode != null && (!StringUtils.hasText(normalizedName) || normalizedName.equals(byCode.getStnm()))) { +// return byCode.getStcd(); +// } +// } +// if (StringUtils.hasText(normalizedName)) { +// String resultByName = resolveFpssCode(normalizedName); +// if (!StringUtils.hasText(normalizedCode) || normalizedCode.equalsIgnoreCase(resultByName)) { +// return resultByName; +// } +// } return null; } public String resolveFishDictCode(String name) { - if (name == null) { + String normalizedName = normalizeInput(name); + if (!StringUtils.hasText(normalizedName)) { return null; } - String lowerName = name.toLowerCase().trim(); - if (FISH_DICT_CACHE.containsKey(lowerName)) { - return FISH_DICT_CACHE.get(lowerName); + SdFishDictoryB exactMatch = findFirst(fishDictoryBMapper.selectList(new LambdaQueryWrapper() + .select(SdFishDictoryB::getCode, SdFishDictoryB::getName) + .eq(SdFishDictoryB::getName, normalizedName))); + if (exactMatch != null) { + return exactMatch.getCode(); } - for (Map.Entry entry : FISH_DICT_CACHE.entrySet()) { - if (entry.getKey().contains(lowerName) || lowerName.contains(entry.getKey())) { - return entry.getValue(); - } - } - return null; + SdFishDictoryB fuzzyMatch = findFirst(fishDictoryBMapper.selectList(new LambdaQueryWrapper() + .select(SdFishDictoryB::getCode, SdFishDictoryB::getName) + .and(wrapper -> wrapper.like(SdFishDictoryB::getName, normalizedName) + .or() + .like(SdFishDictoryB::getAlias, normalizedName)))); + return fuzzyMatch == null ? null : fuzzyMatch.getCode(); } @Override public String resolveFishDictCode(String code, String name) { - if (code == null && name == null) { + String normalizedCode = normalizeInput(code); +// String normalizedName = normalizeInput(name); + if (!StringUtils.hasText(normalizedCode)) { return null; } - loadStationAndBaseCache(); - String lowerCode = code != null ? code.trim().toLowerCase() : null; - String lowerName = name != null ? name.trim().toLowerCase() : null; - if (lowerCode != null && lowerName != null) { - String cachedName = FISH_CODE_TO_NAME_CACHE.get(lowerCode); - if (cachedName != null && cachedName.equals(lowerName)) { - return code.trim(); + if (StringUtils.hasText(normalizedCode)) { + SdFishDictoryB exact = findFirst(fishDictoryBMapper.selectList(new LambdaQueryWrapper() + .select(SdFishDictoryB::getCode, SdFishDictoryB::getName) + .eq(SdFishDictoryB::getCode, normalizedCode))); +// .eq(SdFishDictoryB::getName, normalizedName))); + if (exact != null) { + return exact.getCode(); } } - String resultByName = resolveFishDictCode(name); - if (resultByName != null && resultByName.equalsIgnoreCase(code)) { - return resultByName; - } +// if (StringUtils.hasText(normalizedCode)) { +// SdFishDictoryB byCode = findFirst(fishDictoryBMapper.selectList(new LambdaQueryWrapper() +// .select(SdFishDictoryB::getCode, SdFishDictoryB::getName) +// .eq(SdFishDictoryB::getCode, normalizedCode))); +// if (byCode != null && (!StringUtils.hasText(normalizedName) || normalizedName.equals(byCode.getName()))) { +// return byCode.getCode(); +// } +// } +// if (StringUtils.hasText(normalizedName)) { +// String resultByName = resolveFishDictCode(normalizedName); +// if (!StringUtils.hasText(normalizedCode) || normalizedCode.equalsIgnoreCase(resultByName)) { +// return resultByName; +// } +// } return null; } public String resolveBaseCode(String baseName) { - if (baseName == null) { + String normalizedName = normalizeInput(baseName); + if (!StringUtils.hasText(normalizedName)) { return null; } - String lowerName = baseName.toLowerCase().trim(); - if (BASE_NAME_CACHE.containsKey(lowerName)) { - return BASE_NAME_CACHE.get(lowerName); + SdHydrobase exactMatch = findFirst(hydrobaseMapper.selectList(new LambdaQueryWrapper() + .select(SdHydrobase::getBaseid, SdHydrobase::getBasename) + .eq(SdHydrobase::getBasename, normalizedName))); + if (exactMatch != null) { + return exactMatch.getBaseid(); } - for (Map.Entry entry : BASE_NAME_CACHE.entrySet()) { - if (entry.getKey().contains(lowerName)) { - return entry.getValue(); - } - } - return null; + SdHydrobase fuzzyMatch = findFirst(hydrobaseMapper.selectList(new LambdaQueryWrapper() + .select(SdHydrobase::getBaseid, SdHydrobase::getBasename) + .like(SdHydrobase::getBasename, normalizedName))); + return fuzzyMatch == null ? null : fuzzyMatch.getBaseid(); } @Override public String resolveBaseCode(String code, String baseName) { - if (code == null && baseName == null) { + String normalizedCode = normalizeInput(code); + String normalizedName = normalizeInput(baseName); + if (!StringUtils.hasText(normalizedCode) && !StringUtils.hasText(normalizedName)) { return null; } - loadStationAndBaseCache(); - String lowerCode = code != null ? code.trim().toLowerCase() : null; - String lowerName = baseName != null ? baseName.trim().toLowerCase() : null; - if (lowerCode != null && lowerName != null) { - String cachedName = BASE_CODE_TO_NAME_CACHE.get(lowerCode); - if (cachedName != null && cachedName.equals(lowerName)) { - return code.trim(); + if (StringUtils.hasText(normalizedCode) && StringUtils.hasText(normalizedName)) { + SdHydrobase exact = findFirst(hydrobaseMapper.selectList(new LambdaQueryWrapper() + .select(SdHydrobase::getBaseid, SdHydrobase::getBasename) + .eq(SdHydrobase::getBaseid, normalizedCode) + .eq(SdHydrobase::getBasename, normalizedName))); + if (exact != null) { + return exact.getBaseid(); } } - String resultByName = resolveBaseCode(baseName); - if (resultByName != null && resultByName.equalsIgnoreCase(code)) { - return resultByName; + if (StringUtils.hasText(normalizedCode)) { + SdHydrobase byCode = hydrobaseMapper.selectById(normalizedCode); + if (byCode != null && (!StringUtils.hasText(normalizedName) || normalizedName.equals(byCode.getBasename()))) { + return byCode.getBaseid(); + } + } + if (StringUtils.hasText(normalizedName)) { + String resultByName = resolveBaseCode(normalizedName); + if (!StringUtils.hasText(normalizedCode) || normalizedCode.equalsIgnoreCase(resultByName)) { + return resultByName; + } } return null; } public String resolveRiverCode(String riverName) { - if (riverName == null) { + String normalizedName = normalizeInput(riverName); + if (!StringUtils.hasText(normalizedName)) { return null; } - String lowerName = riverName.toLowerCase().trim(); - if (RIVER_NAME_CACHE.containsKey(lowerName)) { - return RIVER_NAME_CACHE.get(lowerName); + SdRvcdDic exactMatch = findFirst(rvcdDicMapper.selectList(new LambdaQueryWrapper() + .select(SdRvcdDic::getRvcd, SdRvcdDic::getRvnm) + .eq(SdRvcdDic::getRvnm, normalizedName))); + if (exactMatch != null) { + return exactMatch.getRvcd(); } - for (Map.Entry entry : RIVER_NAME_CACHE.entrySet()) { - if (entry.getKey().contains(lowerName)) { - return entry.getValue(); - } - } - return null; + SdRvcdDic fuzzyMatch = findFirst(rvcdDicMapper.selectList(new LambdaQueryWrapper() + .select(SdRvcdDic::getRvcd, SdRvcdDic::getRvnm) + .like(SdRvcdDic::getRvnm, normalizedName))); + return fuzzyMatch == null ? null : fuzzyMatch.getRvcd(); } public String resolveHbrvcdCode(String riverName) { - if (riverName == null) { + String normalizedName = normalizeInput(riverName); + if (!StringUtils.hasText(normalizedName)) { return null; } - String lowerName = riverName.toLowerCase().trim(); - if (HBRVCD_NAME_CACHE.containsKey(lowerName)) { - return HBRVCD_NAME_CACHE.get(lowerName); + SdHbrvDic exactMatch = findFirst(sdHbrvDicMapper.selectList(new LambdaQueryWrapper() + .select(SdHbrvDic::getHbrvcd, SdHbrvDic::getHbrvnm) + .eq(SdHbrvDic::getHbrvnm, normalizedName))); + if (exactMatch != null) { + return exactMatch.getHbrvcd(); } - for (Map.Entry entry : HBRVCD_NAME_CACHE.entrySet()) { - if (entry.getKey().contains(lowerName)) { - return entry.getValue(); - } - } - return null; + SdHbrvDic fuzzyMatch = findFirst(sdHbrvDicMapper.selectList(new LambdaQueryWrapper() + .select(SdHbrvDic::getHbrvcd, SdHbrvDic::getHbrvnm) + .like(SdHbrvDic::getHbrvnm, normalizedName))); + return fuzzyMatch == null ? null : fuzzyMatch.getHbrvcd(); } @Override public String resolveRiverCode(String code, String riverName) { - if (code == null && riverName == null) { + String normalizedCode = normalizeInput(code); +// String normalizedName = normalizeInput(riverName); + if (!StringUtils.hasText(normalizedCode)) { return null; } - loadStationAndBaseCache(); - String lowerCode = code != null ? code.trim().toLowerCase() : null; - String lowerName = riverName != null ? riverName.trim().toLowerCase() : null; - if (lowerCode != null && lowerName != null) { - String cachedName = RIVER_CODE_TO_NAME_CACHE.get(lowerCode); - if (cachedName != null && cachedName.equals(lowerName)) { - return code.trim(); + if (StringUtils.hasText(normalizedCode)) { + SdRvcdDic exact = findFirst(rvcdDicMapper.selectList(new LambdaQueryWrapper() + .select(SdRvcdDic::getRvcd, SdRvcdDic::getRvnm) + .eq(SdRvcdDic::getRvcd, normalizedCode))); +// .eq(SdRvcdDic::getRvnm, normalizedName))); + if (exact != null) { + return exact.getRvcd(); } } - String resultByName = resolveRiverCode(riverName); - if (resultByName != null && resultByName.equalsIgnoreCase(code)) { - return resultByName; - } +// if (StringUtils.hasText(normalizedCode)) { +// SdRvcdDic byCode = rvcdDicMapper.selectById(normalizedCode); +// if (byCode != null && (!StringUtils.hasText(normalizedName) || normalizedName.equals(byCode.getRvnm()))) { +// return byCode.getRvcd(); +// } +// } +// if (StringUtils.hasText(normalizedName)) { +// String resultByName = resolveRiverCode(normalizedName); +// if (!StringUtils.hasText(normalizedCode) || normalizedCode.equalsIgnoreCase(resultByName)) { +// return resultByName; +// } +// } return null; } @Override public String resolveHbrvcdCode(String code, String riverName) { - if (code == null && riverName == null) { + String normalizedCode = normalizeInput(code); +// String normalizedName = normalizeInput(riverName); + if (!StringUtils.hasText(normalizedCode)) { return null; } - loadStationAndBaseCache(); - String lowerCode = code != null ? code.trim().toLowerCase() : null; - String lowerName = riverName != null ? riverName.trim().toLowerCase() : null; - if (lowerCode != null && lowerName != null) { - String cachedName = HBRVCD_CODE_TO_NAME_CACHE.get(lowerCode); - if (cachedName != null && cachedName.equals(lowerName)) { - return code.trim(); + if (StringUtils.hasText(normalizedCode)) { + SdHbrvDic exact = findFirst(sdHbrvDicMapper.selectList(new LambdaQueryWrapper() + .select(SdHbrvDic::getHbrvcd, SdHbrvDic::getHbrvnm) + .eq(SdHbrvDic::getHbrvcd, normalizedCode))); +// .eq(SdHbrvDic::getHbrvnm, normalizedName))); + if (exact != null) { + return exact.getHbrvcd(); } } - String resultByName = resolveHbrvcdCode(riverName); - if (resultByName != null && resultByName.equalsIgnoreCase(code)) { - return resultByName; - } +// if (StringUtils.hasText(normalizedCode)) { +// SdHbrvDic byCode = sdHbrvDicMapper.selectById(normalizedCode); +// if (byCode != null && (!StringUtils.hasText(normalizedName) || normalizedName.equals(byCode.getHbrvnm()))) { +// return byCode.getHbrvcd(); +// } +// } +// if (StringUtils.hasText(normalizedName)) { +// String resultByName = resolveHbrvcdCode(normalizedName); +// if (!StringUtils.hasText(normalizedCode) || normalizedCode.equalsIgnoreCase(resultByName)) { +// return resultByName; +// } +// } return null; } @Override public boolean validateStationBelongsToBase(String stationCode, String baseId) { - if (stationCode == null || baseId == null) { + String normalizedStationCode = normalizeInput(stationCode); + String normalizedBaseId = normalizeInput(baseId); + if (!StringUtils.hasText(normalizedStationCode) || !StringUtils.hasText(normalizedBaseId)) { return false; } - loadStationAndBaseCache(); - String stationLower = stationCode.trim().toLowerCase(); - String cachedBaseId = STATION_TO_BASE_CACHE.get(stationLower); - return baseId.equalsIgnoreCase(cachedBaseId); + return findFirst(engInfoBHMapper.selectList(new LambdaQueryWrapper() + .select(SdEngInfoBH::getStcd) + .eq(SdEngInfoBH::getStcd, normalizedStationCode) + .eq(SdEngInfoBH::getHbrvcd, normalizedBaseId))) != null; + } + + @Override + public boolean validateStationBelongsToRiver(String stationCode, String rvcd) { + String normalizedStationCode = normalizeInput(stationCode); + String normalizedRvcd = normalizeInput(rvcd); + if (!StringUtils.hasText(normalizedStationCode) || !StringUtils.hasText(normalizedRvcd)) { + return false; + } + return findFirst(engInfoBHMapper.selectList(new LambdaQueryWrapper() + .select(SdEngInfoBH::getStcd) + .eq(SdEngInfoBH::getStcd, normalizedStationCode) + .eq(SdEngInfoBH::getReachcd, normalizedRvcd))) != null; } @Override public boolean validateFpssBelongsToStation(String fpssCode, String stationCode) { - if (fpssCode == null || stationCode == null) { + String normalizedFpssCode = normalizeInput(fpssCode); + String normalizedStationCode = normalizeInput(stationCode); + if (!StringUtils.hasText(normalizedFpssCode) || !StringUtils.hasText(normalizedStationCode)) { return false; } - loadStationAndBaseCache(); - String fpssLower = fpssCode.trim().toLowerCase(); - String cachedStationCode = FPSS_TO_STATION_CACHE.get(fpssLower); - return stationCode.equalsIgnoreCase(cachedStationCode); + return findFirst(fpssBHMapper.selectList(new LambdaQueryWrapper() + .select(SdFpssBH::getStcd) + .eq(SdFpssBH::getStcd, normalizedFpssCode) + .eq(SdFpssBH::getRstcd, normalizedStationCode))) != null; + } + + private String normalizeInput(String value) { + return StringUtils.hasText(value) ? value.trim() : null; + } + + private T findFirst(List list) { + return list == null || list.isEmpty() ? null : list.get(0); } private String validateFishType(String fishName, FishImportResult.FishImportRow importRow) { @@ -1755,4 +2028,4 @@ public class FishImportServiceImpl implements IFishImportService { Thread.currentThread().interrupt(); } } -} \ No newline at end of file +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishStatisticsServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishStatisticsServiceImpl.java index 87749f86..e9a688da 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishStatisticsServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/FishStatisticsServiceImpl.java @@ -12,6 +12,8 @@ import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -29,6 +31,10 @@ public class FishStatisticsServiceImpl implements IFishStatisticsService { String basinNamesStr = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "basinCode"); String stationNamesStr = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stationCode"); + String reportMonth = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "reportMonth"); + if (StrUtil.isBlank(reportMonth)) { + reportMonth = LocalDate.now().minusMonths(1).format(DateTimeFormatter.ofPattern("yyyy-MM")); + } // List basinNames = parseFilterList(basinNamesStr); // List stationNames = parseFilterList(stationNamesStr); @@ -47,9 +53,9 @@ public class FishStatisticsServiceImpl implements IFishStatisticsService { int endRow = startRow + pageSize; List records = fishStatisticsMapper.queryStatistics( - basinNamesStr, stationNamesStr, startRow, endRow); + basinNamesStr, stationNamesStr, reportMonth, startRow, endRow); - int total = fishStatisticsMapper.countStatistics(basinNamesStr, basinNamesStr); + int total = fishStatisticsMapper.countStatistics(basinNamesStr, stationNamesStr, reportMonth); Page page = new Page<>(); page.setRecords(records); @@ -66,4 +72,4 @@ public class FishStatisticsServiceImpl implements IFishStatisticsService { } return Arrays.asList(filterValue.split(",")); } -} \ No newline at end of file +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/ImportTaskServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/ImportTaskServiceImpl.java index db0b1550..c4c829d5 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/ImportTaskServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_data/service/impl/ImportTaskServiceImpl.java @@ -263,6 +263,7 @@ public class ImportTaskServiceImpl extends ServiceImpl orgNameMap = new HashMap<>(); + Map rvcdOrderMap = new HashMap<>(); // 3.1 查询流域名称 (BASIN) if (groupedByType.containsKey("RVCD")) { @@ -181,8 +182,30 @@ public class SysUserDataScopeServiceImpl extends ServiceImpl basins = rvcdDicMapper.selectBatchIds(rvcds); - basins.forEach(basin -> orgNameMap.put(basin.getRvcd(), basin.getRvnm())); + List dropdownBasins = rvcdDicMapper.selectRegDropdown(null, null); + Set handledRvcds = new HashSet<>(); + int dropdownOrder = 0; + + for (SdRvcdDic basin : dropdownBasins) { + dropdownOrder++; + if (rvcds.contains(basin.getRvcd())) { + orgNameMap.put(basin.getRvcd(), basin.getRvnm()); + rvcdOrderMap.put(basin.getRvcd(), String.format("%010d", dropdownOrder)); + handledRvcds.add(basin.getRvcd()); + } + } + + Set missingRvcds = rvcds.stream() + .filter(rvcd -> !handledRvcds.contains(rvcd)) + .collect(Collectors.toSet()); + + if (CollUtil.isNotEmpty(missingRvcds)) { + List basins = rvcdDicMapper.selectBatchIds(missingRvcds); + basins.forEach(basin -> { + orgNameMap.put(basin.getRvcd(), basin.getRvnm()); + rvcdOrderMap.put(basin.getRvcd(), String.format("ROOT-%010d", basin.getOrderIndex() == null ? Integer.MAX_VALUE : basin.getOrderIndex())); + }); + } } } @@ -251,6 +274,21 @@ public class SysUserDataScopeServiceImpl extends ServiceImpl { + boolean leftRvcd = "RVCD".equals(left.getOrgType()); + boolean rightRvcd = "RVCD".equals(right.getOrgType()); + if (leftRvcd && rightRvcd) { + String leftKey = rvcdOrderMap.getOrDefault(left.getOrgId(), "9999999999"); + String rightKey = rvcdOrderMap.getOrDefault(right.getOrgId(), "9999999999"); + int compare = leftKey.compareTo(rightKey); + if (compare != 0) { + return compare; + } + return StrUtil.nullToDefault(left.getOrgId(), "").compareTo(StrUtil.nullToDefault(right.getOrgId(), "")); + } + return 0; + }); + return voList; } diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/zq/controller/EngRiverController.java b/backend/src/main/java/com/yfd/platform/qgc_eng/zq/controller/EngRiverController.java new file mode 100644 index 00000000..59b14d48 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/zq/controller/EngRiverController.java @@ -0,0 +1,29 @@ +package com.yfd.platform.qgc_eng.zq.controller; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.qgc_eng.zq.service.EngRiverService; +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("/eng/river") +@Tag(name = "河道水情监测") +@Validated +public class EngRiverController { + + @Resource + private EngRiverService engRiverService; + + @PostMapping("/GetKendoListCust") + @Operation(summary = "查询河道水情实时数据") + public ResponseResult getKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(engRiverService.getKendoListCust(dataSourceRequest)); + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/zq/entity/vo/EngRiverDataVo.java b/backend/src/main/java/com/yfd/platform/qgc_eng/zq/entity/vo/EngRiverDataVo.java new file mode 100644 index 00000000..a36b845d --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/zq/entity/vo/EngRiverDataVo.java @@ -0,0 +1,87 @@ +package com.yfd.platform.qgc_eng.zq.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 EngRiverDataVo { + + @Schema(description = "流量") + private BigDecimal q; + + @Schema(description = "站码") + private String stcd; + + @Schema(description = "站名") + private String stnm; + + @Schema(description = "流速") + private BigDecimal v; + + @Schema(description = "所属电站名称") + private String ennm; + + @Schema(description = "时间") + private Date tm; + + @Schema(description = "水位") + private BigDecimal z; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "基地名称") + private String baseName; + + @Schema(description = "站址") + private String stlc; + + @Schema(description = "所属电站编码") + private String rstcd; + + @Schema(description = "流域编码") + private String rvcd; + + @Schema(description = "流域名称") + private String rvcdName; + + @Schema(description = "基地流域编码") + private String hbrvcd; + + @Schema(description = "基地流域名称") + private String hbrvcdName; + + @Schema(description = "建设状态分类") + private Integer bldsttCcode; + + @Schema(description = "视频站编码聚合") + private String vdid; + + @Schema(description = "水位视频名称") + private String rzVideo; + + @Schema(description = "流速视频名称") + private String speedVideo; + + @Schema(description = "水位视频路径") + private String rzVideoPath; + + @Schema(description = "流速视频路径") + private String speedVideoPath; + + @Schema(description = "基地排序") + private Integer baseStepSort; + + @Schema(description = "流域排序") + private Integer rvcdStepSort; + + @Schema(description = "电站排序") + private Integer rstcdStepSort; + + @Schema(description = "站点排序") + private Integer siteStepSort; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/zq/service/EngRiverService.java b/backend/src/main/java/com/yfd/platform/qgc_eng/zq/service/EngRiverService.java new file mode 100644 index 00000000..8ae27394 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/zq/service/EngRiverService.java @@ -0,0 +1,10 @@ +package com.yfd.platform.qgc_eng.zq.service; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.qgc_eng.zq.entity.vo.EngRiverDataVo; + +public interface EngRiverService { + + DataSourceResult getKendoListCust(DataSourceRequest dataSourceRequest); +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/zq/service/impl/EngRiverServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_eng/zq/service/impl/EngRiverServiceImpl.java new file mode 100644 index 00000000..ec537c0b --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/zq/service/impl/EngRiverServiceImpl.java @@ -0,0 +1,506 @@ +package com.yfd.platform.qgc_eng.zq.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.common.DataSourceLoadOptionsBase; +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.common.GroupHelper; +import com.yfd.platform.common.GroupingInfo; +import com.yfd.platform.common.MicroservicDynamicSQLMapper; +import com.yfd.platform.qgc_eng.zq.entity.vo.EngRiverDataVo; +import com.yfd.platform.qgc_eng.zq.service.EngRiverService; +import com.yfd.platform.utils.QgcQueryWrapperUtil; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@Service +public class EngRiverServiceImpl implements EngRiverService { + + @Resource + private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; + + @Override + public DataSourceResult getKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + if (CollUtil.isEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + return queryDetailList(dataSourceRequest, loadOptions); + } + return queryGroupList(dataSourceRequest, loadOptions); + } + + private DataSourceResult queryDetailList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildDetailSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildCoreSql()) + .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(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, EngRiverDataVo.class); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private DataSourceResult queryGroupList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + List groups = dataSourceRequest.getGroup(); + GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup(); + + StringBuilder sql = new StringBuilder("SELECT "); + List selectItems = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapColumn(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 = mapColumn(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"); + } + sql.append(String.join(", ", selectItems)) + .append(" FROM (") + .append(buildCoreSql()) + .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(" "); + } + + List groupByColumns = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + 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)).append(" "); + } + sql.append(buildGroupOrderBySql(groups)); + + List> rows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap); + DataSourceResult result = new DataSourceResult<>(); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + + private String buildCoreSql() { + return "SELECT " + + "rr.Q AS q, " + + "rr.STCD AS stcd, " + + "rb.STNM AS stnm, " + + "rr.V AS v, " + + "eng.ENNM AS ennm, " + + "rr.TM AS tm, " + + "rr.Z AS z, " + + "eng.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName, " + + "rb.STLC AS stlc, " + + "rb.RSTCD AS rstcd, " + + "eng.RVCD AS rvcd, " + + "rv.RVNM AS rvcdName, " + + "eng.HBRVCD AS hbrvcd, " + + "hbrv.HBRVNM AS hbrvcdName, " + + "rb.BLDSTT_CODE AS bldsttCcode, " + + "LISTAGG(vdb.STCD, ',') WITHIN GROUP(ORDER BY vdb.STCD) AS vdid, " + + "CASE " + + " WHEN INSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), ',') > 0 " + + " THEN CASE WHEN INSTR(SUBSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), INSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), ',') + 1), '水位') > 0 " + + " THEN SUBSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), INSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), ',') + 1) " + + " ELSE SUBSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), 1, INSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), ',') - 1) END " + + " ELSE CASE WHEN INSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), '水位') > 0 THEN LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD) END " + + "END AS rzVideo, " + + "CASE " + + " WHEN INSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), ',') > 0 " + + " THEN CASE WHEN INSTR(SUBSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), INSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), ',') + 1), '流速') > 0 " + + " THEN SUBSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), INSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), ',') + 1) " + + " ELSE SUBSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), 1, INSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), ',') - 1) END " + + " ELSE CASE WHEN INSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), '流速') > 0 THEN LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD) END " + + "END AS speedVideo, " + + "CASE " + + " WHEN INSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), ',') > 0 " + + " THEN CASE WHEN INSTR(SUBSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), INSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), ',') + 1), '水位') > 0 " + + " THEN SUBSTR(LISTAGG(vdr.FLPTH, ',') WITHIN GROUP(ORDER BY vdb.STCD), INSTR(LISTAGG(vdr.FLPTH, ',') WITHIN GROUP(ORDER BY vdb.STCD), ',') + 1) " + + " ELSE SUBSTR(LISTAGG(vdr.FLPTH, ',') WITHIN GROUP(ORDER BY vdb.STCD), 1, INSTR(LISTAGG(vdr.FLPTH, ',') WITHIN GROUP(ORDER BY vdb.STCD), ',') - 1) END " + + " ELSE CASE WHEN INSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), '水位') > 0 THEN LISTAGG(vdr.FLPTH, ',') WITHIN GROUP(ORDER BY vdb.STCD) END " + + "END AS rzVideoPath, " + + "CASE " + + " WHEN INSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), ',') > 0 " + + " THEN CASE WHEN INSTR(SUBSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), INSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), ',') + 1), '流速') > 0 " + + " THEN SUBSTR(LISTAGG(vdr.FLPTH, ',') WITHIN GROUP(ORDER BY vdb.STCD), INSTR(LISTAGG(vdr.FLPTH, ',') WITHIN GROUP(ORDER BY vdb.STCD), ',') + 1) " + + " ELSE SUBSTR(LISTAGG(vdr.FLPTH, ',') WITHIN GROUP(ORDER BY vdb.STCD), 1, INSTR(LISTAGG(vdr.FLPTH, ',') WITHIN GROUP(ORDER BY vdb.STCD), ',') - 1) END " + + " ELSE CASE WHEN INSTR(LISTAGG(vdr.FLNM, ',') WITHIN GROUP(ORDER BY vdb.STCD), '流速') > 0 THEN LISTAGG(vdr.FLPTH, ',') WITHIN GROUP(ORDER BY vdb.STCD) END " + + "END AS speedVideoPath, " + + "NVL(hb.ORDER_INDEX, 999999) AS baseStepSort, " + + "NVL(along.ORDER_INDEX, 999999) AS rvcdStepSort, " + + "NVL(rstSort.SORT, 999999) AS rstcdStepSort, " + + "NVL(siteSort.SORT, 999999) AS siteStepSort " + + "FROM SD_RIVER_R rr " + + "INNER JOIN SD_RIVER_B_H rb ON rb.STCD = rr.STCD AND rb.STTP = 'ZQ' AND NVL(rb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = rb.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eng.HBRVCD AND hbrv.BASEID = eng.BASE_ID " + + " AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 " + + "LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = eng.RVCD " + + "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 = rb.RSTCD " + + "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 = rb.STCD " + + "LEFT JOIN SD_VDINFO_B vdb ON vdb.CSTCD = rr.STCD AND NVL(vdb.USFL, 1) = 1 " + + "LEFT JOIN SD_VDINFO_R vdr ON vdr.STCD = vdb.STCD AND vdr.TM = rr.TM AND NVL(vdr.IS_DELETED, 0) = 0 " + + "WHERE NVL(rr.IS_DELETED, 0) = 0 " + + "GROUP BY rr.Q, rr.STCD, rb.STNM, rr.V, eng.ENNM, rr.TM, rr.Z, eng.BASE_ID, hb.BASENAME, rb.STLC, rb.RSTCD, " + + "eng.RVCD, rv.RVNM, eng.HBRVCD, hbrv.HBRVNM, rb.BLDSTT_CODE, hb.ORDER_INDEX, along.ORDER_INDEX, rstSort.SORT, siteSort.SORT"; + } + + private String buildFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String field = filter.getField(); + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + Object value = filter.getValue(); + if ("vdid".equalsIgnoreCase(field)) { + return buildVdidCondition(operator, value, paramMap, indexHolder); + } + + String column = mapColumn(field); + if (StrUtil.isBlank(column)) { + return ""; + } + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + boolean dateField = "tm".equalsIgnoreCase(field); + if ("in".equals(operator)) { + List values = normalizeValues(value); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String key = "engRiverP" + indexHolder[0]++; + paramMap.put(key, item); + placeholders.add(buildValueExpr(key, dateField, item)); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + + String key = "engRiverP" + indexHolder[0]++; + String valueExpr = buildValueExpr(key, dateField, value); + return switch (operator) { + case "eq" -> { + paramMap.put(key, value); + yield column + " = " + valueExpr; + } + case "neq" -> { + paramMap.put(key, value); + yield column + " <> " + valueExpr; + } + 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 + " > " + valueExpr; + } + case "gte" -> { + paramMap.put(key, value); + yield column + " >= " + valueExpr; + } + case "lt" -> { + paramMap.put(key, value); + yield column + " < " + valueExpr; + } + case "lte" -> { + paramMap.put(key, value); + yield column + " <= " + valueExpr; + } + default -> ""; + }; + } + + private String buildVdidCondition(String operator, + Object value, + Map paramMap, + int[] indexHolder) { + List values; + if ("in".equals(operator)) { + values = normalizeValues(value); + } else if (value == null) { + return ""; + } else { + values = List.of(value); + } + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String key = "engRiverP" + indexHolder[0]++; + paramMap.put(key, item); + placeholders.add("#{map." + key + "}"); + } + if ("neq".equals(operator)) { + return " NOT EXISTS (SELECT 1 FROM SD_VDINFO_B vdb WHERE vdb.CSTCD = t.STCD AND vdb.STCD IN (" + String.join(", ", placeholders) + "))"; + } + return " EXISTS (SELECT 1 FROM SD_VDINFO_B vdb WHERE vdb.CSTCD = t.STCD AND vdb.STCD IN (" + String.join(", ", placeholders) + "))"; + } + + private List normalizeValues(Object value) { + if (value == null) { + return new ArrayList<>(); + } + if (value instanceof List list) { + return new ArrayList<>(list); + } + String text = String.valueOf(value).trim(); + if (StrUtil.isBlank(text)) { + return new ArrayList<>(); + } + if (text.startsWith("[") && text.endsWith("]")) { + text = text.substring(1, text.length() - 1); + } + List values = new ArrayList<>(); + for (String item : text.split(",")) { + String trimmed = StrUtil.trim(item); + if (StrUtil.isNotBlank(trimmed)) { + values.add(StrUtil.removeAll(trimmed, "\"")); + } + } + return values; + } + + private String buildValueExpr(String paramKey, boolean dateField, Object value) { + if (!dateField || value == null) { + return "#{map." + paramKey + "}"; + } + String text = String.valueOf(value).trim(); + if (text.length() <= 10) { + return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD')"; + } + return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD HH24:MI:SS')"; + } + + private String mapColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "q" -> "t.Q"; + case "stcd" -> "t.STCD"; + case "stnm" -> "t.STNM"; + case "v" -> "t.V"; + case "ennm" -> "t.ENNM"; + case "tm" -> "t.TM"; + case "z" -> "t.Z"; + case "baseId" -> "t.BASEID"; + case "baseName" -> "t.BASENAME"; + case "stlc" -> "t.STLC"; + case "rstcd" -> "t.RSTCD"; + case "rvcd" -> "t.RVCD"; + case "rvcdName" -> "t.RVCDNAME"; + case "hbrvcd" -> "t.HBRVCD"; + case "hbrvcdName" -> "t.HBRVCDNAME"; + case "bldsttCcode" -> "t.BLDSTTCCODE"; + case "rzVideo" -> "t.RZVIDEO"; + case "speedVideo" -> "t.SPEEDVIDEO"; + case "baseStepSort" -> "t.BASESTEPSORT"; + case "rvcdStepSort" -> "t.RVCDSTEPSORT"; + case "rstcdStepSort" -> "t.RSTCDSTEPSORT"; + case "siteStepSort" -> "t.SITESTEPSORT"; + default -> null; + }; + } + + private String buildDetailSelectSql(List selectFields) { + Map selectMap = new LinkedHashMap<>(); + selectMap.put("q", "t.Q AS q"); + selectMap.put("stcd", "t.STCD AS stcd"); + selectMap.put("stnm", "t.STNM AS stnm"); + selectMap.put("v", "t.V AS v"); + selectMap.put("ennm", "t.ENNM AS ennm"); + selectMap.put("tm", "t.TM AS tm"); + selectMap.put("z", "t.Z AS z"); + selectMap.put("baseId", "t.BASEID AS baseId"); + selectMap.put("baseName", "t.BASENAME AS baseName"); + selectMap.put("stlc", "t.STLC AS stlc"); + selectMap.put("rstcd", "t.RSTCD AS rstcd"); + selectMap.put("rvcd", "t.RVCD AS rvcd"); + selectMap.put("rvcdName", "t.RVCDNAME AS rvcdName"); + selectMap.put("hbrvcd", "t.HBRVCD AS hbrvcd"); + selectMap.put("hbrvcdName", "t.HBRVCDNAME AS hbrvcdName"); + selectMap.put("bldsttCcode", "t.BLDSTTCCODE AS bldsttCcode"); + selectMap.put("vdid", "t.VDID AS vdid"); + selectMap.put("rzVideo", "t.RZVIDEO AS rzVideo"); + selectMap.put("speedVideo", "t.SPEEDVIDEO AS speedVideo"); + selectMap.put("rzVideoPath", "t.RZVIDEOPATH AS rzVideoPath"); + selectMap.put("speedVideoPath", "t.SPEEDVIDEOPATH AS speedVideoPath"); + selectMap.put("baseStepSort", "t.BASESTEPSORT AS baseStepSort"); + selectMap.put("rvcdStepSort", "t.RVCDSTEPSORT AS rvcdStepSort"); + selectMap.put("rstcdStepSort", "t.RSTCDSTEPSORT AS rstcdStepSort"); + selectMap.put("siteStepSort", "t.SITESTEPSORT AS siteStepSort"); + + if (CollUtil.isEmpty(selectFields)) { + return String.join(", ", selectMap.values()); + } + List actualColumns = new ArrayList<>(); + for (String selectField : selectFields) { + String column = selectMap.get(selectField); + if (StrUtil.isNotBlank(column)) { + actualColumns.add(column); + } + } + if (actualColumns.isEmpty()) { + actualColumns.addAll(selectMap.values()); + } + return String.join(", ", actualColumns); + } + + private String buildOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY t.BASESTEPSORT ASC, t.RVCDSTEPSORT ASC, t.RSTCDSTEPSORT ASC, t.SITESTEPSORT ASC, t.STCD ASC, t.TM DESC"; + } + List orderColumns = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sortDescriptor : sortList) { + if (sortDescriptor == null || StrUtil.isBlank(sortDescriptor.getField())) { + continue; + } + String column = mapColumn(sortDescriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sortDescriptor.getDir()) || "des".equalsIgnoreCase(sortDescriptor.getDir()) ? "DESC" : "ASC"; + orderColumns.add(column + " " + dir + " NULLS LAST"); + } + if (orderColumns.isEmpty()) { + return " ORDER BY t.BASESTEPSORT ASC, t.RVCDSTEPSORT ASC, t.RSTCDSTEPSORT ASC, t.SITESTEPSORT ASC, t.STCD ASC, t.TM DESC"; + } + return " ORDER BY " + String.join(", ", orderColumns); + } + + private String buildGroupOrderBySql(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 = mapColumn(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 String buildAggregateSql(String aggregate, String column, String field) { + String normalized = aggregate == null ? "" : aggregate.toLowerCase(); + return switch (normalized) { + case "sum", "min", "max", "avg", "count" -> + normalized.toUpperCase() + "(" + column + ") AS " + normalized + "_" + field; + default -> ""; + }; + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java index 104b5e69..30979d90 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/controller/FishPassageController.java @@ -34,6 +34,18 @@ public class FishPassageController { return ResponseResult.successData(fpRunService.processQgcSecondPlanKendoList(dataSourceRequest)); } + @PostMapping("/query/qgc/sdfpssr/GetKendoListCust") + @Operation(summary = "全过程过鱼人工监测数据查询") + public ResponseResult getQgcSdfpssrKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fpRunService.processQgcSdfpssrKendoList(dataSourceRequest)); + } + + @PostMapping("/fpssTable/qgc/GetKendoListCust") + @Operation(summary = "过鱼设施监测数据查询") + public ResponseResult getQgcFpssTableKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(fpRunService.processQgcFpssTableKendoList(dataSourceRequest)); + } + @PostMapping("/build/GetKendoListCust") @Operation(summary = "过鱼设施建设及接入情况统计") public ResponseResult getKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpSdfpssrVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpSdfpssrVo.java new file mode 100644 index 00000000..19e357fc --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpSdfpssrVo.java @@ -0,0 +1,83 @@ +package com.yfd.platform.qgc_env.fp.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Date; + +@Data +@Schema(description = "全过程过鱼人工监测数据") +public class FpSdfpssrVo { + + @Schema(description = "过鱼设施编码") + private String stcd; + + @Schema(description = "设施名称") + private String stnm; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "基地名称") + private String baseName; + + @Schema(description = "电站编码") + private String rstcd; + + @Schema(description = "电站名称") + private String ennm; + + @Schema(description = "基地流域编码") + private String hbrvcd; + + @Schema(description = "时间") + private Date tm; + + @Schema(description = "站点排序") + private Integer siteStepSort; + + @Schema(description = "基地排序") + private Integer baseStepSort; + + @Schema(description = "流域排序") + private Integer rvcdStepSort; + + @Schema(description = "电站排序") + private Integer rstcdStepSort; + + @Schema(description = "鱼类名称") + private String name; + + @Schema(description = "鱼类编码") + private String ftp; + + @Schema(description = "鱼类编码") + private String fishId; + + @Schema(description = "过鱼数量") + private Integer fcnt; + + @Schema(description = "大小") + private String fsz; + + @Schema(description = "附件ID") + private String fid; + + @Schema(description = "游向") + private Integer direction; + + @Schema(description = "监测方式") + private Integer mway; + + @Schema(description = "开始时间") + private Date strdt; + + @Schema(description = "结束时间") + private Date enddt; + + @Schema(description = "站点分类编码") + private String stCode; + + @Schema(description = "站点分类名称") + private String stName; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpTableVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpTableVo.java new file mode 100644 index 00000000..e336bf1b --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/entity/vo/FpTableVo.java @@ -0,0 +1,78 @@ +package com.yfd.platform.qgc_env.fp.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "过鱼设施监测数据") +public class FpTableVo { + + @Schema(description = "设施编码") + private String stcd; + + @Schema(description = "设施名称") + private String stnm; + + @Schema(description = "时间") + private String tm; + + @Schema(description = "鱼种类") + private String ftp; + + @Schema(description = "鱼类编码") + private String fishId; + + @Schema(description = "鱼尺寸") + private String fsz; + + @Schema(description = "鱼数量") + private String fcnt; + + @Schema(description = "鱼长度(cm)") + private String length; + + @Schema(description = "鱼宽度(cm)") + private String width; + + @Schema(description = "鱼速度(m/s)") + private String fishspeed; + + @Schema(description = "鱼游向") + private String direction; + + @Schema(description = "鱼游向名称") + private String directionName; + + @Schema(description = "水温(℃)") + private String temperature; + + @Schema(description = "流速(m/s)") + private String speed; + + @Schema(description = "轮廓图") + private String firstimgurl; + + @Schema(description = "短视频") + private String videourl; + + @Schema(description = "年份") + private String yr; + + @Schema(description = "鱼重量") + private String fwet; + + @Schema(description = "文件ID") + private String fid; + + @Schema(description = "上行过鱼数量(尾)") + private Long upFcnt; + + @Schema(description = "下行过鱼数量(尾)") + private Long downFcnt; + + @Schema(description = "数据来源") + private String dataSrc; + + @Schema(description = "监测方式:1=人工 2=自动(预留)") + private Integer mway; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java index 3088f708..48c3ce8b 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/FpRunService.java @@ -2,6 +2,8 @@ package com.yfd.platform.qgc_env.fp.service; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.qgc_env.fp.entity.vo.FpSdfpssrVo; +import com.yfd.platform.qgc_env.fp.entity.vo.FpTableVo; import com.yfd.platform.qgc_env.fp.entity.vo.YearFpStatisticsVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpRunPlanVo; @@ -11,5 +13,9 @@ public interface FpRunService { DataSourceResult processQgcSecondPlanKendoList(DataSourceRequest dataSourceRequest); + DataSourceResult processQgcSdfpssrKendoList(DataSourceRequest dataSourceRequest); + + DataSourceResult processQgcFpssTableKendoList(DataSourceRequest dataSourceRequest); + List getYearFpStatic(String year); } diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java index d0591911..00b1c6e1 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/fp/service/impl/FpRunServiceImpl.java @@ -2,15 +2,21 @@ package com.yfd.platform.qgc_env.fp.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.convert.Convert; 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.common.exception.BizException; import com.yfd.platform.qgc_env.fp.entity.vo.FpFtpStatisticsVo; import com.yfd.platform.qgc_env.fp.entity.vo.FpRunPlanVo; +import com.yfd.platform.qgc_env.fp.entity.vo.FpSdfpssrVo; +import com.yfd.platform.qgc_env.fp.entity.vo.FpTableVo; import com.yfd.platform.qgc_env.fp.entity.vo.YearFpStatisticsVo; import com.yfd.platform.qgc_env.fp.service.FpRunService; import com.yfd.platform.utils.QgcQueryWrapperUtil; @@ -20,6 +26,7 @@ import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; @@ -99,6 +106,28 @@ public class FpRunServiceImpl implements FpRunService { return result; } + @Override + public DataSourceResult processQgcSdfpssrKendoList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + if (CollUtil.isEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + return queryQgcSdfpssrDetailList(dataSourceRequest, loadOptions); + } + return queryQgcSdfpssrGroupList(dataSourceRequest, loadOptions); + } + + @Override + public DataSourceResult processQgcFpssTableKendoList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + String stcd = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd"); + if (StrUtil.isBlank(stcd)) { + throw new BizException("过鱼设施(stcd)编码不能为空."); + } + if (CollUtil.isEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + return queryQgcFpssTableDetailList(dataSourceRequest, loadOptions, stcd); + } + return queryQgcFpssTableGroupList(dataSourceRequest, loadOptions, stcd); + } + @Override public List getYearFpStatic(String year) { Map paramMap = new HashMap<>(); @@ -129,6 +158,892 @@ public class FpRunServiceImpl implements FpRunService { return new ArrayList<>(grouped.values()); } + private DataSourceResult queryQgcFpssTableDetailList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions, + String stcdFilter) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildQgcFpssTableDetailSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildQgcFpssTableCoreSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + appendQgcFpssTableRequiredConditions(sql, paramMap, stcdFilter, loadOptions); + String filterSql = buildQgcFpssTableFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildQgcFpssTableOrderBySql(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, FpTableVo.class); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private DataSourceResult queryQgcFpssTableGroupList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions, + String stcdFilter) { + List groups = dataSourceRequest.getGroup(); + GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup(); + + StringBuilder sql = new StringBuilder("SELECT "); + List selectItems = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapQgcFpssTableColumn(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 = mapQgcFpssTableColumn(aggregate.getField()); + if (StrUtil.isBlank(aggregateColumn) || StrUtil.isBlank(aggregate.getAggregate())) { + continue; + } + String aggregateSql = buildAggregateSql(aggregate.getAggregate(), aggregateColumn, aggregate.getField()); + if (StrUtil.isNotBlank(aggregateSql)) { + selectItems.add(aggregateSql); + } + } + } + } + if (selectItems.isEmpty()) { + selectItems.add("t.YR AS YR"); + selectItems.add("COUNT(*) AS COUNT_YR"); + } + + sql.append(String.join(", ", selectItems)) + .append(" FROM (") + .append(buildQgcFpssTableCoreSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + appendQgcFpssTableRequiredConditions(sql, paramMap, stcdFilter, loadOptions); + String filterSql = buildQgcFpssTableFilterCondition(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 = mapQgcFpssTableColumn(descriptor.getField()); + if (StrUtil.isNotBlank(column)) { + groupByColumns.add(column); + } + } + if (!groupByColumns.isEmpty()) { + sql.append(" GROUP BY ").append(String.join(", ", groupByColumns)).append(" "); + } + sql.append(buildQgcFpssTableGroupOrderBySql(groups)); + + List> rows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap); + DataSourceResult result = new DataSourceResult<>(); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + + private void appendQgcFpssTableRequiredConditions(StringBuilder sql, + Map paramMap, + String stcdFilter, + DataSourceLoadOptionsBase loadOptions) { + List stcdValues = normalizeValues(stcdFilter); + if (stcdValues.isEmpty() && StrUtil.isNotBlank(stcdFilter)) { + stcdValues.add(StrUtil.trim(stcdFilter)); + } + if (!stcdValues.isEmpty()) { + List placeholders = new ArrayList<>(); + for (int i = 0; i < stcdValues.size(); i++) { + String key = "fpssTableStcd" + i; + paramMap.put(key, stcdValues.get(i)); + placeholders.add("#{map." + key + "}"); + } + sql.append(" AND t.STCD IN (").append(String.join(", ", placeholders)).append(") "); + } + + String tm = loadOptions == null ? null : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "tm"); + if (StrUtil.isNotBlank(tm) && tm.contains(",")) { + String[] tmArr = tm.split(","); + if (tmArr.length > 1 && StrUtil.isNotBlank(tmArr[0]) && StrUtil.isNotBlank(tmArr[1])) { + paramMap.put("fpssTableTmStart", StrUtil.trim(tmArr[0])); + paramMap.put("fpssTableTmEnd", StrUtil.trim(tmArr[1])); + sql.append(" AND t.STRDT >= TO_DATE(#{map.fpssTableTmStart}, 'YYYY-MM-DD HH24:MI:SS') "); + sql.append(" AND t.ENDDT <= TO_DATE(#{map.fpssTableTmEnd}, 'YYYY-MM-DD HH24:MI:SS') "); + } + } + } + + private String buildQgcFpssTableCoreSql() { + return "SELECT " + + "manualData.STCD AS stcd, " + + "manualData.STNM AS stnm, " + + "manualData.TM AS tm, " + + "manualData.FTP AS ftp, " + + "manualData.FISHID AS fishId, " + + "manualData.FSZ AS fsz, " + + "manualData.YR AS yr, " + + "manualData.FCNT AS fcnt, " + + "manualData.LENGTH AS length, " + + "manualData.WIDTH AS width, " + + "manualData.FISHSPEED AS fishspeed, " + + "manualData.DIRECTION AS direction, " + + "manualData.DIRECTIONNAME AS directionName, " + + "manualData.UPFCNT AS upFcnt, " + + "manualData.DOWNFCNT AS downFcnt, " + + "manualData.TEMPERATURE AS temperature, " + + "manualData.SPEED AS speed, " + + "manualData.FIRSTIMGURL AS firstimgurl, " + + "manualData.VIDEOURL AS videourl, " + + "manualData.FWET AS fwet, " + + "manualData.FID AS fid, " + + "manualData.DATASRC AS dataSrc, " + + "manualData.MWAY AS mway, " + + "manualData.STRDT AS strdt, " + + "manualData.ENDDT AS enddt " + + "FROM ( " + + " SELECT t.STCD AS STCD, " + + " fp.STNM AS STNM, " + + " TO_CHAR(t.STRDT, 'YYYY-MM-DD HH24:MI:SS') AS TM, " + + " COALESCE(fishRv.NAME, relRv.FISH_NAME, fishZy.NAME, relZy.FISH_NAME, fishDirect.NAME, t.FTP) AS FTP, " + + " t.FTP AS FISHID, " + + " t.FSZ AS FSZ, " + + " TO_CHAR(t.STRDT, 'YYYY') AS YR, " + + " TO_CHAR(t.FCNT) AS FCNT, " + + " CAST(NULL AS VARCHAR2(50)) AS LENGTH, " + + " CAST(NULL AS VARCHAR2(50)) AS WIDTH, " + + " CAST(NULL AS VARCHAR2(50)) AS FISHSPEED, " + + " TO_CHAR(t.DIRECTION) AS DIRECTION, " + + " CASE t.DIRECTION WHEN 0 THEN '上行' WHEN 1 THEN '下行' WHEN 2 THEN '上行折返' WHEN 3 THEN '下行折返' END AS DIRECTIONNAME, " + + " CASE WHEN t.DIRECTION = 0 THEN t.FCNT END AS UPFCNT, " + + " CASE WHEN t.DIRECTION = 1 THEN t.FCNT END AS DOWNFCNT, " + + " CAST(NULL AS VARCHAR2(50)) AS TEMPERATURE, " + + " CAST(NULL AS VARCHAR2(50)) AS SPEED, " + + " CAST(NULL AS VARCHAR2(255)) AS FIRSTIMGURL, " + + " CAST(NULL AS VARCHAR2(255)) AS VIDEOURL, " + + " t.FWET AS FWET, " + + " t.FID AS FID, " + + " CASE WHEN t.AI_STCD IS NULL THEN '人工填报' ELSE aiFp.STNM END AS DATASRC, " + + " 1 AS MWAY, " + + " t.STRDT AS STRDT, " + + " t.ENDDT AS ENDDT " + + " FROM SD_FPSS_R t " + + " LEFT JOIN SD_FPSS_B_H fp ON fp.STCD = t.STCD " + + " LEFT JOIN SD_FPSS_B_H aiFp ON aiFp.STCD = t.AI_STCD " + + " LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fp.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + " LEFT JOIN SD_FISHDICTORY_RLTN_B relRv ON relRv.FISH_ID = t.FTP AND relRv.RVCD = eng.HBRVCD AND NVL(relRv.IS_DELETED, 0) = 0 " + + " LEFT JOIN SD_FISHDICTORY_B fishRv ON fishRv.ID = relRv.ZY_FISH_ID AND NVL(fishRv.IS_DELETED, 0) = 0 AND NVL(fishRv.ENABLE, 1) = 1 " + + " LEFT JOIN SD_FISHDICTORY_RLTN_B relZy ON relZy.FISH_ID = t.FTP AND relZy.RVCD = 'ZY' AND NVL(relZy.IS_DELETED, 0) = 0 " + + " LEFT JOIN SD_FISHDICTORY_B fishZy ON fishZy.ID = relZy.ZY_FISH_ID AND NVL(fishZy.IS_DELETED, 0) = 0 AND NVL(fishZy.ENABLE, 1) = 1 " + + " LEFT JOIN SD_FISHDICTORY_B fishDirect ON fishDirect.ID = t.FTP AND NVL(fishDirect.IS_DELETED, 0) = 0 AND NVL(fishDirect.ENABLE, 1) = 1 " + + " WHERE (t.TASK_STATUS = 'Approved' OR t.TASK_STATUS IS NULL) " + + " AND NVL(t.IS_DELETED, 0) = 0 " + + " UNION ALL " + + " SELECT CAST(NULL AS VARCHAR2(36)) AS STCD, " + + " CAST(NULL AS VARCHAR2(64)) AS STNM, " + + " CAST(NULL AS VARCHAR2(19)) AS TM, " + + " CAST(NULL AS VARCHAR2(255)) AS FTP, " + + " CAST(NULL AS VARCHAR2(200)) AS FISHID, " + + " CAST(NULL AS VARCHAR2(256)) AS FSZ, " + + " CAST(NULL AS VARCHAR2(4)) AS YR, " + + " CAST(NULL AS VARCHAR2(20)) AS FCNT, " + + " CAST(NULL AS VARCHAR2(50)) AS LENGTH, " + + " CAST(NULL AS VARCHAR2(50)) AS WIDTH, " + + " CAST(NULL AS VARCHAR2(50)) AS FISHSPEED, " + + " CAST(NULL AS VARCHAR2(10)) AS DIRECTION, " + + " CAST(NULL AS VARCHAR2(20)) AS DIRECTIONNAME, " + + " CAST(NULL AS NUMBER(18,0)) AS UPFCNT, " + + " CAST(NULL AS NUMBER(18,0)) AS DOWNFCNT, " + + " CAST(NULL AS VARCHAR2(50)) AS TEMPERATURE, " + + " CAST(NULL AS VARCHAR2(50)) AS SPEED, " + + " CAST(NULL AS VARCHAR2(255)) AS FIRSTIMGURL, " + + " CAST(NULL AS VARCHAR2(255)) AS VIDEOURL, " + + " CAST(NULL AS VARCHAR2(50)) AS FWET, " + + " CAST(NULL AS VARCHAR2(1000)) AS FID, " + + " CAST(NULL AS VARCHAR2(64)) AS DATASRC, " + + " 2 AS MWAY, " + + " CAST(NULL AS TIMESTAMP) AS STRDT, " + + " CAST(NULL AS TIMESTAMP) AS ENDDT " + + " FROM DUAL WHERE 1 = 0 " + + ") manualData"; + } + + private String buildQgcFpssTableDetailSelectSql(List selectFields) { + Map selectMap = new LinkedHashMap<>(); + selectMap.put("stcd", "t.stcd AS stcd"); + selectMap.put("stnm", "t.stnm AS stnm"); + selectMap.put("tm", "t.tm AS tm"); + selectMap.put("ftp", "t.ftp AS ftp"); + selectMap.put("fishId", "t.fishId AS fishId"); + selectMap.put("fsz", "t.fsz AS fsz"); + selectMap.put("yr", "t.yr AS yr"); + selectMap.put("fcnt", "t.fcnt AS fcnt"); + selectMap.put("length", "t.length AS length"); + selectMap.put("width", "t.width AS width"); + selectMap.put("fishspeed", "t.fishspeed AS fishspeed"); + selectMap.put("direction", "t.direction AS direction"); + selectMap.put("directionName", "t.directionName AS directionName"); + selectMap.put("temperature", "t.temperature AS temperature"); + selectMap.put("speed", "t.speed AS speed"); + selectMap.put("firstimgurl", "t.firstimgurl AS firstimgurl"); + selectMap.put("videourl", "t.videourl AS videourl"); + selectMap.put("fwet", "t.fwet AS fwet"); + selectMap.put("fid", "t.fid AS fid"); + selectMap.put("upFcnt", "t.upFcnt AS upFcnt"); + selectMap.put("downFcnt", "t.downFcnt AS downFcnt"); + selectMap.put("dataSrc", "t.dataSrc AS dataSrc"); + selectMap.put("mway", "t.mway AS mway"); + selectMap.put("strdt", "t.strdt AS strdt"); + selectMap.put("enddt", "t.enddt AS enddt"); + + if (CollUtil.isEmpty(selectFields)) { + return String.join(", ", selectMap.values()); + } + List actualColumns = new ArrayList<>(); + for (String field : selectFields) { + String column = selectMap.get(field); + if (StrUtil.isNotBlank(column)) { + actualColumns.add(column); + } + } + if (actualColumns.isEmpty()) { + actualColumns.addAll(selectMap.values()); + } + return String.join(", ", actualColumns); + } + + private String buildQgcFpssTableFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildQgcFpssTableLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildQgcFpssTableFilterCondition(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 buildQgcFpssTableLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String field = filter.getField(); + if ("stcd".equalsIgnoreCase(field) || "tm".equalsIgnoreCase(field)) { + return ""; + } + + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + Object value = filter.getValue(); + if ("keyword".equalsIgnoreCase(field)) { + if (value == null || StrUtil.isBlank(String.valueOf(value))) { + return ""; + } + String key = "fpTableP" + indexHolder[0]++; + paramMap.put(key, "%" + String.valueOf(value).trim() + "%"); + return "(t.STNM LIKE #{map." + key + "} OR t.FTP LIKE #{map." + key + "} OR t.DATASRC LIKE #{map." + key + "})"; + } + + String column = mapQgcFpssTableColumn(field); + if (StrUtil.isBlank(column)) { + return ""; + } + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + + boolean dateField = "strdt".equalsIgnoreCase(field) || "enddt".equalsIgnoreCase(field); + if ("in".equals(operator)) { + List values = normalizeValues(value); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String key = "fpTableP" + indexHolder[0]++; + paramMap.put(key, item); + placeholders.add(buildValueExpr(key, dateField, item)); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + + String key = "fpTableP" + indexHolder[0]++; + String valueExpr = buildValueExpr(key, dateField, value); + return switch (operator) { + case "eq" -> { + paramMap.put(key, value); + yield column + " = " + valueExpr; + } + case "neq" -> { + paramMap.put(key, value); + yield column + " <> " + valueExpr; + } + 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 + " > " + valueExpr; + } + case "gte" -> { + paramMap.put(key, value); + yield column + " >= " + valueExpr; + } + case "lt" -> { + paramMap.put(key, value); + yield column + " < " + valueExpr; + } + case "lte" -> { + paramMap.put(key, value); + yield column + " <= " + valueExpr; + } + default -> ""; + }; + } + + private String mapQgcFpssTableColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd" -> "t.STCD"; + case "stnm" -> "t.STNM"; + case "tm" -> "t.STRDT"; + case "ftp" -> "t.FTP"; + case "fishId" -> "t.FISHID"; + case "fsz" -> "t.FSZ"; + case "yr" -> "t.YR"; + case "fcnt" -> "t.FCNT"; + case "length" -> "t.LENGTH"; + case "width" -> "t.WIDTH"; + case "fishspeed" -> "t.FISHSPEED"; + case "direction" -> "t.DIRECTION"; + case "directionName" -> "t.DIRECTIONNAME"; + case "temperature" -> "t.TEMPERATURE"; + case "speed" -> "t.SPEED"; + case "firstimgurl" -> "t.FIRSTIMGURL"; + case "videourl" -> "t.VIDEOURL"; + case "fwet" -> "t.FWET"; + case "fid" -> "t.FID"; + case "upFcnt" -> "t.UPFCNT"; + case "downFcnt" -> "t.DOWNFCNT"; + case "dataSrc" -> "t.DATASRC"; + case "mway" -> "t.MWAY"; + case "strdt" -> "t.STRDT"; + case "enddt" -> "t.ENDDT"; + default -> null; + }; + } + + private String buildQgcFpssTableOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY t.STRDT DESC NULLS LAST"; + } + List orderColumns = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sortDescriptor : sortList) { + if (sortDescriptor == null || StrUtil.isBlank(sortDescriptor.getField())) { + continue; + } + String column = mapQgcFpssTableColumn(sortDescriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sortDescriptor.getDir()) || "des".equalsIgnoreCase(sortDescriptor.getDir()) ? "DESC" : "ASC"; + orderColumns.add(column + " " + dir + " NULLS LAST"); + } + if (orderColumns.isEmpty()) { + return " ORDER BY t.STRDT DESC NULLS LAST"; + } + return " ORDER BY " + String.join(", ", orderColumns); + } + + private String buildQgcFpssTableGroupOrderBySql(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 = mapQgcFpssTableColumn(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 queryQgcSdfpssrDetailList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildQgcSdfpssrDetailSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(buildQgcSdfpssrCoreSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = buildQgcSdfpssrFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + sql.append(buildQgcSdfpssrOrderBySql(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, FpSdfpssrVo.class); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private DataSourceResult queryQgcSdfpssrGroupList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + List groups = dataSourceRequest.getGroup(); + GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup(); + + StringBuilder sql = new StringBuilder("SELECT "); + List selectItems = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapQgcSdfpssrColumn(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 = mapQgcSdfpssrColumn(aggregate.getField()); + if (StrUtil.isBlank(aggregateColumn) || StrUtil.isBlank(aggregate.getAggregate())) { + continue; + } + String aggregateSql = buildAggregateSql(aggregate.getAggregate(), aggregateColumn, aggregate.getField()); + if (StrUtil.isNotBlank(aggregateSql)) { + selectItems.add(aggregateSql); + } + } + } + } + if (selectItems.isEmpty()) { + selectItems.add("t.STCD AS STCD"); + selectItems.add("COUNT(*) AS COUNT_STCD"); + } + + sql.append(String.join(", ", selectItems)) + .append(" FROM (") + .append(buildQgcSdfpssrCoreSql()) + .append(") t WHERE 1 = 1 "); + + Map paramMap = new HashMap<>(); + String filterSql = buildQgcSdfpssrFilterCondition(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 = mapQgcSdfpssrColumn(descriptor.getField()); + if (StrUtil.isNotBlank(column)) { + groupByColumns.add(column); + } + } + if (!groupByColumns.isEmpty()) { + sql.append(" GROUP BY ").append(String.join(", ", groupByColumns)).append(" "); + } + sql.append(buildQgcSdfpssrGroupOrderBySql(groups)); + + List> rows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap); + DataSourceResult result = new DataSourceResult<>(); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + + private String buildQgcSdfpssrCoreSql() { + return "SELECT " + + "t.STCD AS stcd, " + + "fp.STNM AS stnm, " + + "eng.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName, " + + "fp.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "eng.HBRVCD AS hbrvcd, " + + "t.TM AS tm, " + + "NVL(fp.ORDER_INDEX, 999999) AS siteStepSort, " + + "NVL(hb.ORDER_INDEX, 999999) AS baseStepSort, " + + "NVL(hbrv.ORDER_INDEX, 999999) AS rvcdStepSort, " + + "NVL(eng.ORDER_INDEX, 999999) AS rstcdStepSort, " + + "COALESCE(fishRv.NAME, relRv.FISH_NAME, fishZy.NAME, relZy.FISH_NAME, fishDirect.NAME, t.FTP) AS name, " + + "t.FTP AS ftp, " + + "t.FTP AS fishId, " + + "t.FCNT AS fcnt, " + + "t.FSZ AS fsz, " + + "t.FID AS fid, " + + "t.DIRECTION AS direction, " + + "1 AS mway, " + + "t.STRDT AS strdt, " + + "t.ENDDT AS enddt, " + + "CAST(NULL AS VARCHAR2(100)) AS stCode, " + + "CAST(NULL AS VARCHAR2(200)) AS stName " + + "FROM SD_FPSS_R t " + + "INNER JOIN SD_FPSS_B_H fp ON fp.STCD = t.STCD " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = fp.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eng.HBRVCD " + + " AND hbrv.BASEID = eng.BASE_ID " + + " AND NVL(hbrv.IS_DELETED, 0) = 0 " + + " AND NVL(hbrv.ENABLED, 1) = 1 " + + "LEFT JOIN SD_FISHDICTORY_RLTN_B relRv ON relRv.FISH_ID = t.FTP " + + " AND relRv.RVCD = eng.HBRVCD " + + " AND NVL(relRv.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_FISHDICTORY_B fishRv ON fishRv.ID = relRv.ZY_FISH_ID " + + " AND NVL(fishRv.IS_DELETED, 0) = 0 " + + " AND NVL(fishRv.ENABLE, 1) = 1 " + + "LEFT JOIN SD_FISHDICTORY_RLTN_B relZy ON relZy.FISH_ID = t.FTP " + + " AND relZy.RVCD = 'ZY' " + + " AND NVL(relZy.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_FISHDICTORY_B fishZy ON fishZy.ID = relZy.ZY_FISH_ID " + + " AND NVL(fishZy.IS_DELETED, 0) = 0 " + + " AND NVL(fishZy.ENABLE, 1) = 1 " + + "LEFT JOIN SD_FISHDICTORY_B fishDirect ON fishDirect.ID = t.FTP " + + " AND NVL(fishDirect.IS_DELETED, 0) = 0 " + + " AND NVL(fishDirect.ENABLE, 1) = 1 " + + "WHERE NVL(t.IS_DELETED, 0) = 0"; + } + + private String buildQgcSdfpssrDetailSelectSql(List selectFields) { + Map selectMap = new LinkedHashMap<>(); + selectMap.put("stcd", "t.stcd AS stcd"); + selectMap.put("stnm", "t.stnm AS stnm"); + selectMap.put("baseId", "t.baseId AS baseId"); + selectMap.put("baseName", "t.baseName AS baseName"); + selectMap.put("rstcd", "t.rstcd AS rstcd"); + selectMap.put("ennm", "t.ennm AS ennm"); + selectMap.put("hbrvcd", "t.hbrvcd AS hbrvcd"); + selectMap.put("tm", "t.tm AS tm"); + selectMap.put("siteStepSort", "t.siteStepSort AS siteStepSort"); + selectMap.put("baseStepSort", "t.baseStepSort AS baseStepSort"); + selectMap.put("rvcdStepSort", "t.rvcdStepSort AS rvcdStepSort"); + selectMap.put("rstcdStepSort", "t.rstcdStepSort AS rstcdStepSort"); + selectMap.put("name", "t.name AS name"); + selectMap.put("ftp", "t.ftp AS ftp"); + selectMap.put("fishId", "t.fishId AS fishId"); + selectMap.put("fcnt", "t.fcnt AS fcnt"); + selectMap.put("fsz", "t.fsz AS fsz"); + selectMap.put("fid", "t.fid AS fid"); + selectMap.put("direction", "t.direction AS direction"); + selectMap.put("mway", "t.mway AS mway"); + selectMap.put("strdt", "t.strdt AS strdt"); + selectMap.put("enddt", "t.enddt AS enddt"); + selectMap.put("stCode", "t.stCode AS stCode"); + selectMap.put("stName", "t.stName AS stName"); + + if (CollUtil.isEmpty(selectFields)) { + return String.join(", ", selectMap.values()); + } + List actualColumns = new ArrayList<>(); + for (String field : selectFields) { + String column = selectMap.get(field); + if (StrUtil.isNotBlank(column)) { + actualColumns.add(column); + } + } + if (actualColumns.isEmpty()) { + actualColumns.addAll(selectMap.values()); + } + return String.join(", ", actualColumns); + } + + private String buildQgcSdfpssrFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildQgcSdfpssrLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildQgcSdfpssrFilterCondition(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 buildQgcSdfpssrLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String field = filter.getField(); + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + Object value = filter.getValue(); + + if ("keyword".equalsIgnoreCase(field)) { + if (value == null || StrUtil.isBlank(String.valueOf(value))) { + return ""; + } + String key = "fpSdfpssrP" + indexHolder[0]++; + paramMap.put(key, "%" + String.valueOf(value).trim() + "%"); + return "(t.STNM LIKE #{map." + key + "} OR t.BASENAME LIKE #{map." + key + "} OR t.ENNM LIKE #{map." + key + "} OR t.NAME LIKE #{map." + key + "} OR t.FTP LIKE #{map." + key + "})"; + } + + String column = mapQgcSdfpssrColumn(field); + if (StrUtil.isBlank(column)) { + return ""; + } + if ("isnull".equals(operator)) { + return column + " IS NULL"; + } + if ("isnotnull".equals(operator)) { + return column + " IS NOT NULL"; + } + boolean dateField = "tm".equalsIgnoreCase(field) || "strdt".equalsIgnoreCase(field) || "enddt".equalsIgnoreCase(field); + if ("in".equals(operator)) { + List values = normalizeValues(value); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String key = "fpSdfpssrP" + indexHolder[0]++; + paramMap.put(key, item); + placeholders.add(buildValueExpr(key, dateField, item)); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + + String key = "fpSdfpssrP" + indexHolder[0]++; + String valueExpr = buildValueExpr(key, dateField, value); + return switch (operator) { + case "eq" -> { + paramMap.put(key, value); + yield column + " = " + valueExpr; + } + case "neq" -> { + paramMap.put(key, value); + yield column + " <> " + valueExpr; + } + 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 + " > " + valueExpr; + } + case "gte" -> { + paramMap.put(key, value); + yield column + " >= " + valueExpr; + } + case "lt" -> { + paramMap.put(key, value); + yield column + " < " + valueExpr; + } + case "lte" -> { + paramMap.put(key, value); + yield column + " <= " + valueExpr; + } + default -> ""; + }; + } + + private String mapQgcSdfpssrColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + 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 "hbrvcd" -> "t.HBRVCD"; + case "tm" -> "t.TM"; + case "siteStepSort" -> "t.SITESTEPSORT"; + case "baseStepSort" -> "t.BASESTEPSORT"; + case "rvcdStepSort" -> "t.RVCDSTEPSORT"; + case "rstcdStepSort" -> "t.RSTCDSTEPSORT"; + case "name" -> "t.NAME"; + case "ftp" -> "t.FTP"; + case "fishId" -> "t.FISHID"; + case "fcnt" -> "t.FCNT"; + case "fsz" -> "t.FSZ"; + case "fid" -> "t.FID"; + case "direction" -> "t.DIRECTION"; + case "mway" -> "t.MWAY"; + case "strdt" -> "t.STRDT"; + case "enddt" -> "t.ENDDT"; + case "stCode" -> "t.STCODE"; + case "stName" -> "t.STNAME"; + default -> null; + }; + } + + private String buildQgcSdfpssrOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY t.STRDT ASC, t.STCD ASC"; + } + List orderColumns = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sortDescriptor : sortList) { + if (sortDescriptor == null || StrUtil.isBlank(sortDescriptor.getField())) { + continue; + } + String column = mapQgcSdfpssrColumn(sortDescriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sortDescriptor.getDir()) || "des".equalsIgnoreCase(sortDescriptor.getDir()) ? "DESC" : "ASC"; + orderColumns.add(column + " " + dir + " NULLS LAST"); + } + if (orderColumns.isEmpty()) { + return " ORDER BY t.STRDT ASC, t.STCD ASC"; + } + return " ORDER BY " + String.join(", ", orderColumns); + } + + private String buildQgcSdfpssrGroupOrderBySql(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 = mapQgcSdfpssrColumn(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 String buildAggregateSql(String aggregate, String column, String field) { + String normalized = aggregate == null ? "" : aggregate.toLowerCase(); + return switch (normalized) { + case "sum", "min", "max", "avg", "count" -> + normalized.toUpperCase() + "(" + column + ") AS " + normalized + "_" + field; + default -> ""; + }; + } + + private List normalizeValues(Object value) { + if (value == null) { + return new ArrayList<>(); + } + if (value instanceof List list) { + return new ArrayList<>(list); + } + String text = String.valueOf(value).trim(); + if (StrUtil.isBlank(text)) { + return new ArrayList<>(); + } + if (text.startsWith("[") && text.endsWith("]")) { + text = text.substring(1, text.length() - 1); + } + List values = new ArrayList<>(); + for (String item : text.split(",")) { + String trimmed = StrUtil.trim(item); + if (StrUtil.isNotBlank(trimmed)) { + values.add(StrUtil.removeAll(trimmed, "\"")); + } + } + return values; + } + + private String buildValueExpr(String paramKey, boolean dateField, Object value) { + if (!dateField || value == null) { + return "#{map." + paramKey + "}"; + } + String text = String.valueOf(value).trim(); + if (text.length() <= 10) { + return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD')"; + } + return "TO_DATE(#{map." + paramKey + "}, 'YYYY-MM-DD HH24:MI:SS')"; + } + private String buildQgcSecondPlanSql() { return "SELECT t.STCD AS stcd, " + " t2.stm AS designStartDate, " + diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vap/controller/VpConstructionController.java b/backend/src/main/java/com/yfd/platform/qgc_env/vap/controller/VpConstructionController.java new file mode 100644 index 00000000..e9f4b4f3 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vap/controller/VpConstructionController.java @@ -0,0 +1,49 @@ +package com.yfd.platform.qgc_env.vap.controller; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.qgc_env.vap.service.VpConstructionService; +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.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/vap") +@Tag(name = "珍稀植物园建设及接入情况") +@Validated +public class VpConstructionController { + + @Resource + private VpConstructionService vpConstructionService; + + @PostMapping("/vpc/GetKendoListCust") + @Operation(summary = "植物园建设及接入情况") + public ResponseResult getKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(vpConstructionService.processKendoList(dataSourceRequest)); + } + + @PostMapping("/vmsstbprpt/GetKendoList") + @Operation(summary = "植物园统计查询") + public ResponseResult getVmsstbprptList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(vpConstructionService.processVmsstbprptList(dataSourceRequest)); + } + + @GetMapping("/msstbprpt/getStInfoByStcd") + @Operation(summary = "植物园单站基础信息") + public ResponseResult getStInfoByStcd(@RequestParam String stcd) { + return ResponseResult.successData(vpConstructionService.getStInfoByStcd(stcd)); + } + + @PostMapping("/vpr/basinVpIntDetail") + @Operation(summary = "珍稀植物园运行数据-弹窗") + public ResponseResult basinVpIntDetail(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(vpConstructionService.basinVpIntDetail(dataSourceRequest)); + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpBasinIntDetailVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpBasinIntDetailVo.java new file mode 100644 index 00000000..f1b2673f --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpBasinIntDetailVo.java @@ -0,0 +1,61 @@ +package com.yfd.platform.qgc_env.vap.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +@Schema(description = "植物园运行数据弹窗") +public class VpBasinIntDetailVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "植物园名称") + private String stnm; + + @Schema(description = "所属基地编码") + private String baseId; + + @Schema(description = "所属基地名称") + private String baseName; + + @Schema(description = "植物园编码") + private String stcd; + + @Schema(description = "分类") + private Integer type; + + @Schema(description = "单位") + private Integer unit; + + @Schema(description = "植物名称") + private String tetp; + + @Schema(description = "总数量") + private Integer tecnt; + + @Schema(description = "存活数量") + private Integer surnum; + + @Schema(description = "移栽规模") + private Integer transplant; + + @Schema(description = "种植要求") + private Integer plantask; + + @Schema(description = "树木统计") + private String treeNum; + + @Schema(description = "花草统计") + private String fgNum; + + @Schema(description = "成活率") + private String rate; + + @Schema(description = "年份") + private String tm; + + @Schema(description = "附件") + private String fid; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpConstructionSituationVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpConstructionSituationVo.java new file mode 100644 index 00000000..c9da5a4f --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpConstructionSituationVo.java @@ -0,0 +1,71 @@ +package com.yfd.platform.qgc_env.vap.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Date; + +@Data +@Schema(description = "植物园建设及接入情况") +public class VpConstructionSituationVo { + + @Schema(description = "植物园编码") + private String stcd; + + @Schema(description = "植物园名称") + private String stnm; + + @Schema(description = "站类编码") + private String sttpCode; + + @Schema(description = "站类名称") + private String sttpName; + + @Schema(description = "所属基地编码") + private String baseId; + + @Schema(description = "所属基地名称") + private String baseName; + + @Schema(description = "所属电站名称") + private String ennm; + + @Schema(description = "是否接入") + private String dtin; + + @Schema(description = "是否接入名称") + private String dtinName; + + @Schema(description = "建设状态") + private String bldstt; + + @Schema(description = "建设状态名称") + private String bldsttName; + + @Schema(description = "开工日期") + private Date ststdt; + + @Schema(description = "建成日期") + private Date esstdt; + + @Schema(description = "建成日期") + private Date jcdt; + + @Schema(description = "LOGO") + private String logo; + + @Schema(description = "简介") + private String introduce; + + @Schema(description = "介绍弹窗图片") + private String inffile; + + @Schema(description = "基地排序") + private Integer baseStepSort; + + @Schema(description = "电站排序") + private Integer rstcdStepSort; + + @Schema(description = "站点排序") + private Integer siteStepSort; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpStBaseInfoVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpStBaseInfoVo.java new file mode 100644 index 00000000..3b212f66 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpStBaseInfoVo.java @@ -0,0 +1,51 @@ +package com.yfd.platform.qgc_env.vap.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "植物园单站基础信息") +public class VpStBaseInfoVo { + + @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_env/vap/entity/vo/VpStInfoResultVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpStInfoResultVo.java new file mode 100644 index 00000000..b7e2a0f8 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpStInfoResultVo.java @@ -0,0 +1,26 @@ +package com.yfd.platform.qgc_env.vap.entity.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 VpStInfoResultVo { + + @Schema(description = "主信息兼容对象") + private Map msStbprpT = new LinkedHashMap<>(); + + @Schema(description = "测值列表") + private List stcdValVoList = new ArrayList<>(); + + @Schema(description = "关联列表") + private List relList = new ArrayList<>(); + + @Schema(description = "站点基础信息") + private VpStBaseInfoVo stBaseInfo; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpVmsstbprptVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpVmsstbprptVo.java new file mode 100644 index 00000000..12bbfcad --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vap/entity/vo/VpVmsstbprptVo.java @@ -0,0 +1,159 @@ +package com.yfd.platform.qgc_env.vap.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +@Data +@Schema(description = "植物园统计查询") +public class VpVmsstbprptVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "主键") + private String id; + + @Schema(description = "创建人") + private String recordUser; + + @Schema(description = "创建时间") + private Date recordTime; + + @Schema(description = "修改时间") + private Date modifyTime; + + @Schema(description = "创建人展示") + private String displayRecordUser; + + @Schema(description = "流域排序") + private Integer rvcdStepSort; + + @Schema(description = "电站排序") + private Integer rstcdStepSort; + + @Schema(description = "站点排序") + private Integer siteStepSort; + + @Schema(description = "基地排序") + private Integer baseStepSort; + + @Schema(description = "站点编码") + private String stcd; + + @Schema(description = "站点名称") + private String stnm; + + @Schema(description = "站类") + private String sttp; + + @Schema(description = "站类编码") + private String sttpCode; + + @Schema(description = "站类名称") + private String sttpName; + + @Schema(description = "站类全路径") + private String sttpFullPath; + + @Schema(description = "站类层级") + private Integer sttpTreeLevel; + + @Schema(description = "经度") + private Double lgtd; + + @Schema(description = "纬度") + private Double lttd; + + @Schema(description = "站址") + private String stlc; + + @Schema(description = "是否启用") + private Integer usfl; + + @Schema(description = "所属电站编码") + private String rstcd; + + @Schema(description = "所属电站名称") + private String ennm; + + @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; + + @Schema(description = "规划设计日期") + private Date stdsdt; + + @Schema(description = "计划开工日期") + private Date pststdt; + + @Schema(description = "计划完工日期") + private Date pesstdt; + + @Schema(description = "开工日期") + private Date ststdt; + + @Schema(description = "建成日期") + private Date jcdt; + + @Schema(description = "简介") + private String introduce; + + @Schema(description = "LOGO") + private String logo; + + @Schema(description = "介绍图") + private String inffile; + + @Schema(description = "是否接入") + private Integer dtin; + + @Schema(description = "是否接入名称") + private String dtinName; + + @Schema(description = "接入时间") + private Date dtinTm; + + @Schema(description = "建设状态") + private String bldstt; + + @Schema(description = "建设状态名称") + private String bldsttName; + + @Schema(description = "建设状态分类") + private String bldsttCcode; + + @Schema(description = "建设状态分类名称") + private String bldsttCcodeName; + + @Schema(description = "投资") + private BigDecimal inv; + + @Schema(description = "总工期") + private BigDecimal aptl; + + @Schema(description = "面积") + private BigDecimal area; + + @Schema(description = "运行状态") + private Integer runState; + + @Schema(description = "运行状态名称") + private String runStateName; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/VpConstructionService.java b/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/VpConstructionService.java new file mode 100644 index 00000000..2f073631 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/VpConstructionService.java @@ -0,0 +1,17 @@ +package com.yfd.platform.qgc_env.vap.service; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.qgc_env.vap.entity.vo.VpBasinIntDetailVo; +import com.yfd.platform.qgc_env.vap.entity.vo.VpStInfoResultVo; + +public interface VpConstructionService { + + DataSourceResult processKendoList(DataSourceRequest dataSourceRequest); + + DataSourceResult processVmsstbprptList(DataSourceRequest dataSourceRequest); + + VpStInfoResultVo getStInfoByStcd(String stcd); + + DataSourceResult basinVpIntDetail(DataSourceRequest dataSourceRequest); +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/impl/VpConstructionServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/impl/VpConstructionServiceImpl.java new file mode 100644 index 00000000..f3d3976f --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_env/vap/service/impl/VpConstructionServiceImpl.java @@ -0,0 +1,873 @@ +package com.yfd.platform.qgc_env.vap.service.impl; + +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.common.PageInfo; +import com.yfd.platform.qgc_env.vap.entity.vo.VpBasinIntDetailVo; +import com.yfd.platform.qgc_env.vap.entity.vo.VpConstructionSituationVo; +import com.yfd.platform.qgc_env.vap.entity.vo.VpStBaseInfoVo; +import com.yfd.platform.qgc_env.vap.entity.vo.VpStInfoResultVo; +import com.yfd.platform.qgc_env.vap.entity.vo.VpVmsstbprptVo; +import com.yfd.platform.qgc_env.vap.service.VpConstructionService; +import com.yfd.platform.utils.KendoUtil; +import com.yfd.platform.utils.QgcQueryWrapperUtil; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class VpConstructionServiceImpl implements VpConstructionService { + + @Resource + private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; + + @Override + public DataSourceResult processKendoList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + PageInfo pageInfo = loadOptions == null ? new PageInfo() : QgcQueryWrapperUtil.getPageInfo(loadOptions); + Page page = pageInfo.getHasPageInfo() ? pageInfo.getPage() : null; + + String isBotanicalGarden = loadOptions == null ? null + : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "isBotanicalGarden"); + String isNationwide = loadOptions == null ? null + : QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "isNationwide"); + + Map paramMap = new HashMap<>(); + StringBuilder sql = new StringBuilder(buildBaseSql("1".equals(isBotanicalGarden), "1".equals(isNationwide))); + + String filterSql = buildFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, + new int[]{0}); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql); + } + + String groupBy = dataSourceRequest == null ? null : KendoUtil.getGroupBy(dataSourceRequest); + GroupingInfo[] groupInfos = loadOptions == null ? null : loadOptions.getGroup(); + if (StrUtil.isNotBlank(groupBy) && groupInfos != null && groupInfos.length > 0) { + String groupedSql = buildGroupSql(sql.toString(), groupInfos); + List> rows = microservicDynamicSQLMapper.pageAllList(null, groupedSql, paramMap); + DataSourceResult result = new DataSourceResult(); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData(new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData(new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + + sql.append(buildOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + VpConstructionSituationVo.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 processVmsstbprptList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + PageInfo pageInfo = loadOptions == null ? new PageInfo() : QgcQueryWrapperUtil.getPageInfo(loadOptions); + Page page = pageInfo.getHasPageInfo() ? pageInfo.getPage() : null; + + Map paramMap = new HashMap<>(); + StringBuilder sql = new StringBuilder(buildVmsstbprptBaseSql()); + String filterSql = buildVmsstbprptFilterCondition( + dataSourceRequest == null ? null : dataSourceRequest.getFilter(), + paramMap, + new int[]{0} + ); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql); + } + + String groupBy = dataSourceRequest == null ? null : KendoUtil.getGroupBy(dataSourceRequest); + GroupingInfo[] groupInfos = loadOptions == null ? null : loadOptions.getGroup(); + if (StrUtil.isNotBlank(groupBy) && groupInfos != null && groupInfos.length > 0) { + String groupedSql = buildVmsstbprptGroupSql(sql.toString(), groupInfos); + List> rows = microservicDynamicSQLMapper.pageAllList(null, groupedSql, paramMap); + DataSourceResult result = new DataSourceResult(); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData(new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData(new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + + sql.append(buildVmsstbprptOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + VpVmsstbprptVo.class + ); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public VpStInfoResultVo getStInfoByStcd(String stcd) { + VpStInfoResultVo result = new VpStInfoResultVo(); + if (StrUtil.isBlank(stcd)) { + return result; + } + Map paramMap = new HashMap<>(); + paramMap.put("stcd", stcd); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + null, + buildStInfoByStcdSql(), + paramMap, + VpStBaseInfoVo.class + ); + if (!list.isEmpty()) { + result.setStBaseInfo(list.get(0)); + } + return result; + } + + @Override + public DataSourceResult basinVpIntDetail(DataSourceRequest dataSourceRequest) { + DataSourceResult result = new DataSourceResult<>(); + Page page = KendoUtil.getPage(dataSourceRequest); + Map paramMap = new HashMap<>(); + StringBuilder sql = new StringBuilder(buildBasinVpIntDetailSql(paramMap, + dataSourceRequest == null ? null : dataSourceRequest.getFilter())); + sql.append(buildBasinVpIntDetailOrderBy(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + List list = microservicDynamicSQLMapper.pageAllListWithResultType( + page, + sql.toString(), + paramMap, + VpBasinIntDetailVo.class + ); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private String buildBaseSql(boolean botanicalGarden, boolean nationwide) { + String baseIdExpr = botanicalGarden + ? "CASE WHEN vp.BASE_ID IS NULL THEN 'null' ELSE vp.BASE_ID END" + : "vp.BASE_ID"; + String dtinExpr = botanicalGarden + ? "CASE WHEN vp.DTIN IS NULL THEN '400' ELSE TO_CHAR(vp.DTIN) END" + : "TO_CHAR(vp.DTIN)"; + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("vp.STCD AS stcd, ") + .append("vp.STNM AS stnm, ") + .append("vp.STTP AS sttpCode, ") + .append("sttp.STTP_NAME AS sttpName, ") + .append(baseIdExpr).append(" AS baseId, ") + .append("hb.BASENAME AS baseName, ") + .append("eng.ENNM AS ennm, ") + .append(dtinExpr).append(" AS dtin, ") + .append("CASE WHEN NVL(vp.DTIN, 0) = 1 THEN '已接入' ELSE '未接入' END AS dtinName, ") + .append("TO_CHAR(vp.BLDSTT_CODE) AS bldstt, ") + .append("CASE WHEN NVL(vp.BLDSTT_CODE, 0) = 2 THEN '已建' ") + .append("WHEN NVL(vp.BLDSTT_CODE, 0) = 1 THEN '在建' ") + .append("ELSE '未建/规划' END AS bldsttName, ") + .append("vp.SWDT AS ststdt, ") + .append("vp.JCDT AS esstdt, ") + .append("vp.JCDT AS jcdt, ") + .append("vp.LOGO AS logo, ") + .append("vp.INTRODUCE AS introduce, ") + .append("vp.INFFILE AS inffile, ") + .append("NVL(hb.ORDER_INDEX, 999999) AS baseStepSort, ") + .append("NVL(eng.ORDER_INDEX, 999999) AS rstcdStepSort, ") + .append("NVL(vp.ORDER_INDEX, 999999) AS siteStepSort ") + .append("FROM SD_VP_B_H vp ") + .append("LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = vp.BASE_ID ") + .append(" AND NVL(hb.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = vp.RSTCD ") + .append(" AND NVL(eng.IS_DELETED, 0) = 0 ") + .append("LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = vp.STTP ") + .append(" AND NVL(sttp.IS_DELETED, 0) = 0 ") + .append(" AND NVL(sttp.ENABLE, 1) = 1 ") + .append("WHERE 1 = 1 "); + + if (botanicalGarden) { + sql.append(" AND NVL(vp.IS_DELETED, 0) = 0 "); + } + if (!nationwide) { + sql.append(" AND (vp.LOGO IS NOT NULL OR vp.INTRODUCE IS NOT NULL) "); + } + return sql.toString(); + } + + private String buildFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildLeafCondition(filter, paramMap, indexHolder); + } + if (CollectionUtils.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String field = filter.getField(); + if ("isBotanicalGarden".equals(field) || "isNationwide".equals(field)) { + return ""; + } + Object value = filter.getValue(); + String operator = StrUtil.blankToDefault(filter.getOperator(), "eq").toLowerCase(); + + if ("keyword".equals(field)) { + if (value == null || StrUtil.isBlank(String.valueOf(value))) { + return ""; + } + String paramKey = "vpParam" + indexHolder[0]++; + paramMap.put(paramKey, "%" + value + "%"); + return "(vp.STNM LIKE #{map." + paramKey + "} OR hb.BASENAME LIKE #{map." + paramKey + + "} OR eng.ENNM LIKE #{map." + paramKey + "})"; + } + + String column = mapColumn(field); + if (StrUtil.isBlank(column)) { + return ""; + } + 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 = "vpParam" + indexHolder[0]++; + paramMap.put(paramKey, item); + placeholders.add("#{map." + paramKey + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + + String paramKey = "vpParam" + indexHolder[0]++; + 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, "%" + value + "%"); + return column + " LIKE #{map." + paramKey + "}"; + case "startswith": + paramMap.put(paramKey, value + "%"); + return column + " LIKE #{map." + paramKey + "}"; + case "endswith": + paramMap.put(paramKey, "%" + value); + return column + " LIKE #{map." + paramKey + "}"; + case "gt": + paramMap.put(paramKey, value); + return column + " > #{map." + paramKey + "}"; + case "gte": + paramMap.put(paramKey, value); + return column + " >= #{map." + paramKey + "}"; + case "lt": + paramMap.put(paramKey, value); + return column + " < #{map." + paramKey + "}"; + case "lte": + paramMap.put(paramKey, value); + return column + " <= #{map." + paramKey + "}"; + default: + return ""; + } + } + + private String buildGroupSql(String detailSql, GroupingInfo[] groupInfos) { + List groupFields = new ArrayList<>(); + List orderItems = new ArrayList<>(); + StringBuilder sql = new StringBuilder("SELECT "); + boolean first = true; + for (GroupingInfo item : groupInfos) { + if (item == null || StrUtil.isBlank(item.getSelector())) { + continue; + } + String selector = item.getSelector(); + if (!isGroupSupported(selector)) { + continue; + } + if (!first) { + sql.append(", "); + } + sql.append("t.").append(selector).append(" AS ").append(selector); + sql.append(", COUNT(*) AS count_").append(selector); + groupFields.add("t." + selector); + orderItems.add("t." + selector + ("desc".equalsIgnoreCase(item.getDesc() ? "desc" : "asc") ? " DESC" : " ASC")); + first = false; + } + if (groupFields.isEmpty()) { + return "SELECT * FROM (" + detailSql + ") t WHERE 1 = 0"; + } + sql.append(" FROM (").append(detailSql).append(") t GROUP BY ") + .append(String.join(", ", groupFields)); + if (!orderItems.isEmpty()) { + sql.append(" ORDER BY ").append(String.join(", ", orderItems)); + } + return sql.toString(); + } + + private boolean isGroupSupported(String selector) { + return "stcd".equals(selector) + || "stnm".equals(selector) + || "sttpCode".equals(selector) + || "sttpName".equals(selector) + || "baseId".equals(selector) + || "baseName".equals(selector) + || "ennm".equals(selector) + || "dtin".equals(selector) + || "dtinName".equals(selector) + || "bldstt".equals(selector) + || "bldsttName".equals(selector); + } + + private String mapColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + Map columnMap = new HashMap<>(); + columnMap.put("stcd", "vp.STCD"); + columnMap.put("stnm", "vp.STNM"); + columnMap.put("sttpCode", "vp.STTP"); + columnMap.put("sttpName", "sttp.STTP_NAME"); + columnMap.put("baseId", "vp.BASE_ID"); + columnMap.put("baseName", "hb.BASENAME"); + columnMap.put("ennm", "eng.ENNM"); + columnMap.put("dtin", "vp.DTIN"); + columnMap.put("dtinName", "CASE WHEN NVL(vp.DTIN, 0) = 1 THEN '已接入' ELSE '未接入' END"); + columnMap.put("bldstt", "vp.BLDSTT_CODE"); + columnMap.put("bldsttName", "CASE WHEN NVL(vp.BLDSTT_CODE, 0) = 2 THEN '已建' WHEN NVL(vp.BLDSTT_CODE, 0) = 1 THEN '在建' ELSE '未建/规划' END"); + columnMap.put("ststdt", "vp.SWDT"); + columnMap.put("jcdt", "vp.JCDT"); + return columnMap.get(field); + } + + private String buildOrderBySql(List sorts) { + if (sorts == null || sorts.isEmpty()) { + return " ORDER BY NVL(hb.ORDER_INDEX, 999999) ASC, NVL(eng.ORDER_INDEX, 999999) ASC, " + + "NVL(vp.ORDER_INDEX, 999999) ASC, vp.STCD ASC"; + } + Map sortMap = new HashMap<>(); + sortMap.put("stcd", "vp.STCD"); + sortMap.put("stnm", "vp.STNM"); + sortMap.put("sttpCode", "vp.STTP"); + sortMap.put("sttpName", "sttp.STTP_NAME"); + sortMap.put("baseId", "vp.BASE_ID"); + sortMap.put("baseName", "hb.BASENAME"); + sortMap.put("ennm", "eng.ENNM"); + sortMap.put("dtin", "vp.DTIN"); + sortMap.put("dtinName", "CASE WHEN NVL(vp.DTIN, 0) = 1 THEN '已接入' ELSE '未接入' END"); + sortMap.put("bldstt", "vp.BLDSTT_CODE"); + sortMap.put("bldsttName", "CASE WHEN NVL(vp.BLDSTT_CODE, 0) = 2 THEN '已建' WHEN NVL(vp.BLDSTT_CODE, 0) = 1 THEN '在建' ELSE '未建/规划' END"); + sortMap.put("ststdt", "vp.SWDT"); + sortMap.put("jcdt", "vp.JCDT"); + sortMap.put("baseStepSort", "hb.ORDER_INDEX"); + sortMap.put("rstcdStepSort", "eng.ORDER_INDEX"); + sortMap.put("siteStepSort", "vp.ORDER_INDEX"); + + List orderItems = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = sortMap.get(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 NVL(hb.ORDER_INDEX, 999999) ASC, NVL(eng.ORDER_INDEX, 999999) ASC, " + + "NVL(vp.ORDER_INDEX, 999999) ASC, vp.STCD ASC"; + } + return " ORDER BY " + String.join(", ", orderItems); + } + + 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 buildVmsstbprptBaseSql() { + return "SELECT " + + "vp.STCD AS id, " + + "vp.RECORD_USER AS recordUser, " + + "vp.RECORD_TIME AS recordTime, " + + "vp.MODIFY_TIME AS modifyTime, " + + "CAST(NULL AS VARCHAR2(100)) AS displayRecordUser, " + + "NVL(eng.ORDER_INDEX, 999999) AS rvcdStepSort, " + + "NVL(eng.ORDER_INDEX, 999999) AS rstcdStepSort, " + + "NVL(vp.ORDER_INDEX, 999999) AS siteStepSort, " + + "NVL(hb.ORDER_INDEX, 999999) AS baseStepSort, " + + "vp.STCD AS stcd, " + + "vp.STNM AS stnm, " + + "vp.STTP AS sttp, " + + "vp.STTP AS sttpCode, " + + "sttp.STTP_NAME AS sttpName, " + + "sttp.FULL_PATH AS sttpFullPath, " + + "sttp.TREE_LEVEL AS sttpTreeLevel, " + + "vp.LGTD AS lgtd, " + + "vp.LTTD AS lttd, " + + "vp.STLC AS stlc, " + + "vp.USFL AS usfl, " + + "vp.RSTCD AS rstcd, " + + "eng.ENNM AS ennm, " + + "vp.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName, " + + "vp.HBRVCD AS hbrvcd, " + + "CAST(NULL AS VARCHAR2(100)) AS hbrvcdName, " + + "eng.REACHCD AS rvcd, " + + "eng.REACHCD_NAME AS rvcdName, " + + "vp.STDSDT AS stdsdt, " + + "vp.PSTSTDT AS pststdt, " + + "vp.PESSTDT AS pesstdt, " + + "vp.SWDT AS ststdt, " + + "vp.JCDT AS jcdt, " + + "vp.INTRODUCE AS introduce, " + + "vp.LOGO AS logo, " + + "vp.INFFILE AS inffile, " + + "vp.DTIN AS dtin, " + + "CASE WHEN NVL(vp.DTIN, 0) = 1 THEN '已接入' ELSE '未接入' END AS dtinName, " + + "vp.DTIN_TM AS dtinTm, " + + "TO_CHAR(vp.BLPRD) AS bldstt, " + + "CAST(NULL AS VARCHAR2(100)) AS bldsttName, " + + "TO_CHAR(vp.BLDSTT_CODE) AS bldsttCcode, " + + "CASE WHEN NVL(vp.BLDSTT_CODE, 0) = 2 THEN '已建' " + + "WHEN NVL(vp.BLDSTT_CODE, 0) = 1 THEN '在建' ELSE '未建/规划' END AS bldsttCcodeName, " + + "vp.INV AS inv, " + + "vp.APTL AS aptl, " + + "vp.AREA AS area, " + + "eng.RUN_STATE AS runState, " + + "CASE WHEN eng.RUN_STATE = 1 THEN '运行中' WHEN eng.RUN_STATE = 2 THEN '未运行' ELSE NULL END AS runStateName " + + "FROM SD_VP_B_H vp " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = vp.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = vp.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = vp.STTP " + + " AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 " + + "WHERE NVL(vp.IS_DELETED, 0) = 0"; + } + + private String buildStInfoByStcdSql() { + return "SELECT " + + "vp.STCD AS stcd, " + + "vp.STNM AS stnm, " + + "vp.STTP AS sttpCode, " + + "sttp.STTP_NAME AS sttpName, " + + "sttp.FULL_PATH AS sttpFullPath, " + + "sttp.TREE_LEVEL AS sttpTreeLevel, " + + "CAST(NULL AS VARCHAR2(100)) AS stCode, " + + "CAST(NULL AS VARCHAR2(200)) AS stName, " + + "vp.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName, " + + "vp.HBRVCD AS hbrvcd, " + + "hbrv.HBRVNM AS hbrvcdName, " + + "eng.REACHCD AS rvcd, " + + "rv.RVNM AS rvcdName " + + "FROM SD_VP_B_H vp " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = vp.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = vp.HBRVCD AND hbrv.BASEID = vp.BASE_ID " + + " AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = vp.RSTCD AND NVL(eng.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_RVCD_DIC rv ON rv.RVCD = eng.REACHCD " + + "LEFT JOIN SD_STTP_B sttp ON sttp.STTP_CODE = vp.STTP " + + " AND NVL(sttp.IS_DELETED, 0) = 0 AND NVL(sttp.ENABLE, 1) = 1 " + + "WHERE NVL(vp.IS_DELETED, 0) = 0 AND vp.STCD = #{map.stcd}"; + } + + private String buildBasinVpIntDetailSql(Map paramMap, DataSourceRequest.FilterDescriptor descriptor) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT * FROM (") + .append(" SELECT vp.STNM AS stnm, ") + .append(" vp.BASE_ID AS baseId, ") + .append(" hb.BASENAME AS baseName, ") + .append(" vp.STCD AS stcd, ") + .append(" r.TYPE AS type, ") + .append(" r.TEUNT AS unit, ") + .append(" basic.NAME AS tetp, ") + .append(" SUM(r.TECNT) AS tecnt, ") + .append(" SUM(r.SURNUM) AS surnum, ") + .append(" SUM(r.TRANSPLANT) AS transplant, ") + .append(" SUM(r.PLANTASK) AS plantask, ") + .append(" CASE WHEN r.TYPE = 3 THEN CEIL(SUM(r.SURNUM)) || '/' || SUM(r.TRANSPLANT) ELSE '-' END AS treeNum, ") + .append(" CASE WHEN r.TYPE <> 3 THEN CEIL(SUM(r.SURNUM)) || '/' || SUM(r.TRANSPLANT) ELSE '-' END AS fgNum, ") + .append(" CASE WHEN SUM(r.TRANSPLANT) != 0 ") + .append(" THEN TO_CHAR(ROUND(SUM(r.SURNUM) / SUM(r.TRANSPLANT) * 100, 2)) ") + .append(" ELSE '-' END AS rate, ") + .append(" TO_CHAR(r.TM, 'YYYY') AS tm, ") + .append(" r.FID AS fid ") + .append(" FROM SD_VP_R r ") + .append(" LEFT JOIN SD_VPBASIC_B basic ON basic.ID = r.PLANT_ID ") + .append(" AND NVL(basic.IS_DELETED, 0) = 0 ") + .append(" AND NVL(basic.ENABLE, 1) = 1 ") + .append(" LEFT JOIN SD_VP_B_H vp ON vp.STCD = r.STCD ") + .append(" AND NVL(vp.IS_DELETED, 0) = 0 ") + .append(" LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = vp.BASE_ID ") + .append(" AND NVL(hb.IS_DELETED, 0) = 0 ") + .append(" WHERE NVL(r.IS_DELETED, 0) = 0 "); + + appendBasinVpIntDetailFilters(sql, paramMap, descriptor); + + sql.append(" GROUP BY vp.STCD, vp.BASE_ID, TO_CHAR(r.TM, 'YYYY'), vp.STNM, hb.BASENAME, basic.NAME, r.TYPE, r.TEUNT, r.FID ") + .append(") t WHERE 1 = 1"); + return sql.toString(); + } + + private void appendBasinVpIntDetailFilters(StringBuilder sql, + Map paramMap, + DataSourceRequest.FilterDescriptor descriptor) { + if (descriptor == null || CollectionUtils.isEmpty(descriptor.getFilters())) { + return; + } + List stcdValues = new ArrayList<>(); + String tm = null; + for (DataSourceRequest.FilterDescriptor filter : descriptor.getFilters()) { + if (filter == null || StrUtil.isBlank(filter.getField())) { + continue; + } + if ("stcd".equals(filter.getField())) { + stcdValues.addAll(normalizeValues(filter.getValue())); + } + if ("tm".equals(filter.getField()) && filter.getValue() != null) { + tm = String.valueOf(filter.getValue()); + } + } + if (!stcdValues.isEmpty()) { + List placeholders = new ArrayList<>(); + for (int i = 0; i < stcdValues.size(); i++) { + String key = "vpRunStcd" + i; + paramMap.put(key, stcdValues.get(i)); + placeholders.add("#{map." + key + "}"); + } + sql.append(" AND (r.STCD IN (").append(String.join(", ", placeholders)).append(")") + .append(" OR r.RSTCD IN (").append(String.join(", ", placeholders)).append("))"); + } + if (StrUtil.isNotBlank(tm)) { + paramMap.put("vpRunYear", tm); + sql.append(" AND TO_CHAR(r.TM, 'YYYY') = #{map.vpRunYear}"); + } + } + + private String buildBasinVpIntDetailOrderBy(List sorts) { + if (sorts == null || sorts.isEmpty()) { + return " ORDER BY tetp ASC, tm ASC"; + } + Map sortMap = new HashMap<>(); + sortMap.put("stnm", "stnm"); + sortMap.put("baseId", "baseId"); + sortMap.put("baseName", "baseName"); + sortMap.put("stcd", "stcd"); + sortMap.put("type", "type"); + sortMap.put("unit", "unit"); + sortMap.put("tetp", "tetp"); + sortMap.put("tecnt", "tecnt"); + sortMap.put("surnum", "surnum"); + sortMap.put("transplant", "transplant"); + sortMap.put("plantask", "plantask"); + sortMap.put("treeNum", "treeNum"); + sortMap.put("fgNum", "fgNum"); + sortMap.put("rate", "rate"); + sortMap.put("tm", "tm"); + sortMap.put("fid", "fid"); + List orderItems = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = sortMap.get(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orderItems.add(column + " " + dir); + } + if (orderItems.isEmpty()) { + return " ORDER BY tetp ASC, tm ASC"; + } + return " ORDER BY " + String.join(", ", orderItems); + } + + private String buildVmsstbprptFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + return buildVmsstbprptLeafCondition(filter, paramMap, indexHolder); + } + if (CollectionUtils.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildVmsstbprptFilterCondition(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 buildVmsstbprptLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapVmsstbprptColumn(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 = normalizeValues(value); + if (values.isEmpty()) { + return ""; + } + List placeholders = new ArrayList<>(); + for (Object item : values) { + String key = "vpMsParam" + indexHolder[0]++; + paramMap.put(key, item); + placeholders.add("#{map." + key + "}"); + } + return column + " IN (" + String.join(", ", placeholders) + ")"; + } + if (value == null) { + return ""; + } + String key = "vpMsParam" + 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 mapVmsstbprptColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + Map columnMap = new HashMap<>(); + columnMap.put("stcd", "vp.STCD"); + columnMap.put("stnm", "vp.STNM"); + columnMap.put("sttp", "vp.STTP"); + columnMap.put("sttpCode", "vp.STTP"); + columnMap.put("sttpName", "sttp.STTP_NAME"); + columnMap.put("baseId", "vp.BASE_ID"); + columnMap.put("baseName", "hb.BASENAME"); + columnMap.put("rstcd", "vp.RSTCD"); + columnMap.put("ennm", "eng.ENNM"); + columnMap.put("hbrvcd", "vp.HBRVCD"); + columnMap.put("rvcd", "eng.REACHCD"); + columnMap.put("dtin", "vp.DTIN"); + columnMap.put("bldstt", "vp.BLPRD"); + columnMap.put("bldsttCcode", "vp.BLDSTT_CODE"); + return columnMap.get(field); + } + + private String buildVmsstbprptGroupSql(String detailSql, GroupingInfo[] groupInfos) { + List groupFields = new ArrayList<>(); + List orderItems = new ArrayList<>(); + StringBuilder sql = new StringBuilder("SELECT "); + boolean first = true; + for (GroupingInfo item : groupInfos) { + if (item == null || StrUtil.isBlank(item.getSelector())) { + continue; + } + String selector = item.getSelector(); + if (!isVmsstbprptGroupSupported(selector)) { + continue; + } + if (!first) { + sql.append(", "); + } + sql.append("t.").append(selector).append(" AS ").append(selector); + sql.append(", COUNT(*) AS count_").append(selector); + groupFields.add("t." + selector); + orderItems.add("t." + selector + ("desc".equalsIgnoreCase(item.getDesc() ? "desc" : "asc") ? " DESC" : " ASC")); + first = false; + } + if (groupFields.isEmpty()) { + return "SELECT * FROM (" + detailSql + ") t WHERE 1 = 0"; + } + sql.append(" FROM (").append(detailSql).append(") t GROUP BY ") + .append(String.join(", ", groupFields)); + if (!orderItems.isEmpty()) { + sql.append(" ORDER BY ").append(String.join(", ", orderItems)); + } + return sql.toString(); + } + + private boolean isVmsstbprptGroupSupported(String selector) { + return "stcd".equals(selector) + || "stnm".equals(selector) + || "sttpCode".equals(selector) + || "sttpName".equals(selector) + || "baseId".equals(selector) + || "baseName".equals(selector) + || "rstcd".equals(selector) + || "ennm".equals(selector) + || "dtin".equals(selector) + || "bldstt".equals(selector) + || "bldsttCcode".equals(selector); + } + + private String buildVmsstbprptOrderBySql(List sorts) { + if (sorts == null || sorts.isEmpty()) { + return " ORDER BY NVL(eng.ORDER_INDEX, 999999) ASC, NVL(eng.ORDER_INDEX, 999999) ASC, " + + "NVL(vp.ORDER_INDEX, 999999) ASC, vp.STCD ASC"; + } + Map sortMap = new HashMap<>(); + sortMap.put("stcd", "vp.STCD"); + sortMap.put("stnm", "vp.STNM"); + sortMap.put("sttp", "vp.STTP"); + sortMap.put("sttpCode", "vp.STTP"); + sortMap.put("sttpName", "sttp.STTP_NAME"); + sortMap.put("baseId", "vp.BASE_ID"); + sortMap.put("baseName", "hb.BASENAME"); + sortMap.put("rstcd", "vp.RSTCD"); + sortMap.put("ennm", "eng.ENNM"); + sortMap.put("dtin", "vp.DTIN"); + sortMap.put("bldstt", "vp.BLPRD"); + sortMap.put("bldsttCcode", "vp.BLDSTT_CODE"); + sortMap.put("rvcdStepSort", "eng.ORDER_INDEX"); + sortMap.put("rstcdStepSort", "eng.ORDER_INDEX"); + sortMap.put("siteStepSort", "vp.ORDER_INDEX"); + sortMap.put("baseStepSort", "hb.ORDER_INDEX"); + + List orderItems = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sorts) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = sortMap.get(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 NVL(eng.ORDER_INDEX, 999999) ASC, NVL(eng.ORDER_INDEX, 999999) ASC, " + + "NVL(vp.ORDER_INDEX, 999999) ASC, vp.STCD ASC"; + } + return " ORDER BY " + String.join(", ", orderItems); + } +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtrvVo.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtrvVo.java index ac9c0f7d..0324eb4c 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtrvVo.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/entity/vo/WtrvVo.java @@ -12,7 +12,9 @@ public class WtrvVo { private Date tm; - private Boolean isIoWtrv; +// private Boolean isIoWtrv; + + private Boolean ioWtrv; private Boolean hasRstcdWtvt; diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/AlongDetailServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/AlongDetailServiceImpl.java index d1bb3656..53be0477 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/AlongDetailServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/AlongDetailServiceImpl.java @@ -214,51 +214,56 @@ public class AlongDetailServiceImpl extends ServiceImpl> iwtDataVoList = new ArrayList<>(); List> dwtDataVoList = new ArrayList<>(); List> wtvtDataVoList = new ArrayList<>(); -// List> hydropwDataVoList = new ArrayList<>(); - List> pptnDataVoList = new ArrayList<>(); + List> hydropwDataVoList = new ArrayList<>(); +// List> pptnDataVoList = new ArrayList<>(); List> tmpDataVoList = new ArrayList<>(); List> wtnpDataVoList; if (wtrvInfo.getType() == 1) { - dwtDataVoList.addAll(this.alongDetailMapper.getDwtrvDataList(wtrvInfo.getStcd(), null, startTime, endTime)); + dwtDataVoList.addAll(normalizeMapKeyList(this.alongDetailMapper.getDwtrvDataList(wtrvInfo.getStcd(), null, startTime, endTime))); } Map>> wtvtDataVoMap; if (wtrvInfo.getType() == 2) { - iwtDataVoList.addAll(this.alongDetailMapper.getIwtrvDataList(wtrvInfo.getStcd(), null, startTime, endTime)); - wtvtDataVoList.addAll(this.alongDetailMapper.getWtvtDataList(null, wtrvInfo.getRstcd(), startTime, endTime)); + iwtDataVoList.addAll(normalizeMapKeyList(this.alongDetailMapper.getIwtrvDataList(wtrvInfo.getStcd(), null, startTime, endTime))); + wtvtDataVoList.addAll(normalizeMapKeyList(this.alongDetailMapper.getWtvtDataList(null, wtrvInfo.getRstcd(), startTime, endTime))); wtvtDataVoMap = wtvtDataVoList.stream() - .filter(it -> it.get("tm") != null) - .collect(Collectors.groupingBy(it -> (Date) it.get("tm"))); + .filter(it -> getDateValueIgnoreCase(it, "tm") != null) + .collect(Collectors.groupingBy(it -> getDateValueIgnoreCase(it, "tm"))); } else { wtvtDataVoMap = null; } Map> iwtDataMap = iwtDataVoList.stream() - .collect(Collectors.toMap(it -> (Date) it.get("tm"), Function.identity())); + .filter(it -> getDateValueIgnoreCase(it, "tm") != null) + .collect(Collectors.toMap(it -> getDateValueIgnoreCase(it, "tm"), Function.identity())); Map> dwtDataMap = dwtDataVoList.stream() - .collect(Collectors.toMap(it -> (Date) it.get("tm"), Function.identity())); + .filter(it -> getDateValueIgnoreCase(it, "tm") != null) + .collect(Collectors.toMap(it -> getDateValueIgnoreCase(it, "tm"), Function.identity())); -// hydropwDataVoList.addAll(this.alongDetailMapper.getHydropwDataList(wtrvInfo.getStcd(), startTime, endTime)); -// Map> hydropwDataMap = hydropwDataVoList.stream() -// .collect(Collectors.toMap(it -> (Date) it.get("tm"), Function.identity())); + hydropwDataVoList.addAll(normalizeMapKeyList(this.alongDetailMapper.getHydropwDataList(wtrvInfo.getStcd(), startTime, endTime))); + Map> hydropwDataMap = hydropwDataVoList.stream() + .filter(it -> getDateValueIgnoreCase(it, "tm") != null) + .collect(Collectors.toMap(it -> getDateValueIgnoreCase(it, "tm"), Function.identity())); -// pptnDataVoList.addAll(this.alongDetailMapper.getPptnDataList(wtrvInfo.getStcd(), startTime, endTime)); +// pptnDataVoList.addAll(normalizeMapKeyList(this.alongDetailMapper.getPptnDataList(wtrvInfo.getStcd(), startTime, endTime))); // Map> pptnDataMap = pptnDataVoList.stream() -// .collect(Collectors.toMap(it -> (Date) it.get("tm"), Function.identity())); +// .filter(it -> getDateValueIgnoreCase(it, "tm") != null) +// .collect(Collectors.toMap(it -> getDateValueIgnoreCase(it, "tm"), Function.identity())); -// tmpDataVoList.addAll(this.alongDetailMapper.getTmpDataList(wtrvInfo.getStcd(), startTime, endTime)); +// tmpDataVoList.addAll(normalizeMapKeyList(this.alongDetailMapper.getTmpDataList(wtrvInfo.getStcd(), startTime, endTime))); // Map> tmpDataMap = tmpDataVoList.stream() -// .collect(Collectors.toMap(it -> (Date) it.get("tm"), Function.identity())); +// .filter(it -> getDateValueIgnoreCase(it, "tm") != null) +// .collect(Collectors.toMap(it -> getDateValueIgnoreCase(it, "tm"), Function.identity())); Map wtnpDataMap = new HashMap<>(); if (StrUtil.isNotBlank(wtrvInfo.getRstcd())) { - wtnpDataVoList = this.alongDetailMapper.getNatureTmpDataList(wtrvInfo.getRstcd(), null); + wtnpDataVoList = normalizeMapKeyList(this.alongDetailMapper.getNatureTmpDataList(wtrvInfo.getRstcd(), null)); wtnpDataMap.putAll(wtnpDataVoList.stream() - .filter(it -> it.get("mnth") != null) + .filter(it -> getIntegerValueIgnoreCase(it, "mnth") != null) .collect(Collectors.toMap( - it -> (Integer) it.get("mnth"), - it -> (BigDecimal) it.get("wt") + it -> getIntegerValueIgnoreCase(it, "mnth"), + it -> getBigDecimalValueIgnoreCase(it, "wt") ))); } @@ -273,7 +278,7 @@ public class AlongDetailServiceImpl extends ServiceImpl> vtList = wtvtDataVoMap.get(it.getTm()); if (vtList != null) { Map>> vtMap = vtList.stream() - .filter(tt -> tt.get("vwt") != null) - .collect(Collectors.groupingBy(tt -> (BigDecimal) tt.get("vwt"))); + .filter(tt -> getBigDecimalValueIgnoreCase(tt, "vwt") != null) + .collect(Collectors.groupingBy(tt -> getBigDecimalValueIgnoreCase(tt, "vwt"))); if (vtMap.containsKey(it.getWt())) { vo.put("wtvtDataVo", vtMap.get(it.getWt()).get(0)); @@ -332,8 +337,10 @@ public class AlongDetailServiceImpl extends ServiceImpl> normalizeMapKeyList(List> dataList) { + if (CollUtil.isEmpty(dataList)) { + return Collections.emptyList(); + } + return dataList.stream() + .map(this::normalizeMapKeys) + .collect(Collectors.toList()); + } + + private Map normalizeMapKeys(Map source) { + if (source == null || source.isEmpty()) { + return Collections.emptyMap(); + } + Map normalized = new LinkedHashMap<>(); + source.forEach((key, value) -> normalized.put(toLowerCamelKey(key), value)); + return normalized; + } + + private String toLowerCamelKey(String key) { + if (StrUtil.isBlank(key)) { + return key; + } + String trimmedKey = key.trim(); + if (trimmedKey.contains("_")) { + return StrUtil.toCamelCase(trimmedKey.toLowerCase(Locale.ROOT)); + } + if (trimmedKey.equals(trimmedKey.toUpperCase(Locale.ROOT))) { + return trimmedKey.toLowerCase(Locale.ROOT); + } + return Character.toLowerCase(trimmedKey.charAt(0)) + trimmedKey.substring(1); + } + + private Object getValueIgnoreCase(Map data, String key) { + if (data == null || StrUtil.isBlank(key)) { + return null; + } + if (data.containsKey(key)) { + return data.get(key); + } + String upperKey = key.toUpperCase(Locale.ROOT); + if (data.containsKey(upperKey)) { + return data.get(upperKey); + } + String lowerKey = key.toLowerCase(Locale.ROOT); + if (data.containsKey(lowerKey)) { + return data.get(lowerKey); + } + for (Map.Entry entry : data.entrySet()) { + if (entry.getKey() != null && entry.getKey().equalsIgnoreCase(key)) { + return entry.getValue(); + } + } + return null; + } + + private Date getDateValueIgnoreCase(Map data, String key) { + return (Date) getValueIgnoreCase(data, key); + } + + private Integer getIntegerValueIgnoreCase(Map data, String key) { + Object value = getValueIgnoreCase(data, key); + if (value == null) { + return null; + } + if (value instanceof Integer integerValue) { + return integerValue; + } + if (value instanceof Number numberValue) { + return numberValue.intValue(); + } + return Integer.valueOf(String.valueOf(value)); + } + + private BigDecimal getBigDecimalValueIgnoreCase(Map data, String key) { + Object value = getValueIgnoreCase(data, key); + if (value == null) { + return null; + } + if (value instanceof BigDecimal decimalValue) { + return decimalValue; + } + if (value instanceof Number numberValue) { + return BigDecimal.valueOf(numberValue.doubleValue()); + } + return new BigDecimal(String.valueOf(value)); + } + @Override public WtrvInfo getWtrvInfoByStcd(String stcd) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java index aa9942ff..d3946de4 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_env/wt/service/impl/SdWtMonitorServiceImpl.java @@ -491,7 +491,7 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService { @Override public WtrvVo getFlagByStcd(String stcd) { String sql = "SELECT wt.STCD AS stcd, " + - "CASE WHEN rel.ENG_IWT_CODE IS NOT NULL OR rel.ENG_DWT_CODE IS NOT NULL THEN 1 ELSE 0 END AS isIoWtrv, " + + "CASE WHEN rel.ENG_IWT_CODE IS NOT NULL OR rel.ENG_DWT_CODE IS NOT NULL THEN 1 ELSE 0 END AS ioWtrv, " + "CASE WHEN EXISTS ( " + " SELECT 1 FROM SD_WT_B_H vt " + " WHERE vt.RSTCD = wt.RSTCD " + @@ -2305,7 +2305,7 @@ public class SdWtMonitorServiceImpl implements SdWtMonitorService { private WtrvVo buildDefaultWtrvVo(String stcd) { WtrvVo vo = new WtrvVo(); vo.setStcd(stcd); - vo.setIsIoWtrv(false); + vo.setIoWtrv(false); vo.setHasRstcdWtvt(false); return vo; } diff --git a/backend/src/main/java/com/yfd/platform/system/controller/LoginController.java b/backend/src/main/java/com/yfd/platform/system/controller/LoginController.java index 0ad501f4..0a51347e 100644 --- a/backend/src/main/java/com/yfd/platform/system/controller/LoginController.java +++ b/backend/src/main/java/com/yfd/platform/system/controller/LoginController.java @@ -99,17 +99,21 @@ public class LoginController { LoginUser loginUser = (LoginUser) authenticate.getPrincipal(); Integer status = loginUser.getUser().getStatus(); String regStatus = loginUser.getUser().getRegStatus(); + + if (StrUtil.isNotBlank(regStatus)&&"REJECTED".equals(regStatus)) { + return ResponseResult.error("账号审核未通过"); + } + + if (StrUtil.isNotBlank(regStatus)&&"PENDING".equals(regStatus)) { + return ResponseResult.error("账号待审核,请联系管理员"); + } + if ("0".equals(status.toString())) { return ResponseResult.error("账号已停用"); } - if ("PENDING".equals(regStatus)) { - return ResponseResult.error("账号待审核,请联系管理员"); - } - if ("REJECTED".equals(regStatus)) { - return ResponseResult.error("账号审核未通过"); - } + HttpServletRequest request = RequestHolder.getHttpServletRequest(); SysLog sysLog = new SysLog(); sysLog.setUsercode(user.getUsername()); diff --git a/backend/src/main/java/com/yfd/platform/system/controller/RegisterAccessController.java b/backend/src/main/java/com/yfd/platform/system/controller/RegisterAccessController.java new file mode 100644 index 00000000..83a01fcf --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/system/controller/RegisterAccessController.java @@ -0,0 +1,26 @@ +package com.yfd.platform.system.controller; + +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.system.service.RegisterAccessTokenService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/register") +@Tag(name = "注册访问控制") +public class RegisterAccessController { + + @Resource + private RegisterAccessTokenService registerAccessTokenService; + + @GetMapping("/accessToken") + @Operation(summary = "获取注册场景临时访问令牌") + public ResponseResult getRegisterAccessToken(HttpServletRequest request) { + return ResponseResult.successData(registerAccessTokenService.createToken(request)); + } +} diff --git a/backend/src/main/java/com/yfd/platform/system/controller/SmsVerifyCodeController.java b/backend/src/main/java/com/yfd/platform/system/controller/SmsVerifyCodeController.java index a0572066..d777842d 100644 --- a/backend/src/main/java/com/yfd/platform/system/controller/SmsVerifyCodeController.java +++ b/backend/src/main/java/com/yfd/platform/system/controller/SmsVerifyCodeController.java @@ -242,7 +242,7 @@ public class SmsVerifyCodeController { } String stationCode = smsVerifyCodeRequest.getStationCode(); - String hbrvcdCode = smsVerifyCodeRequest.getHbrvcdCode(); + String rvcdCode = smsVerifyCodeRequest.getRvcdCode(); Set selectedStationCodes = new HashSet<>(); if (StringUtils.isNotEmpty(stationCode)) { @@ -250,8 +250,8 @@ public class SmsVerifyCodeController { } Set selectedBasinCodes = new HashSet<>(); - if (StringUtils.isNotEmpty(hbrvcdCode)) { - selectedBasinCodes.addAll(Arrays.asList(hbrvcdCode.split(","))); + if (StringUtils.isNotEmpty(rvcdCode)) { + selectedBasinCodes.addAll(Arrays.asList(rvcdCode.split(","))); } // Set addedStationCodes = new HashSet<>(); @@ -262,13 +262,13 @@ public class SmsVerifyCodeController { } List allStationsInBasin = engInfoBHService.lambdaQuery() - .eq(SdEngInfoBH::getHbrvcd, basinCode) + .eq(SdEngInfoBH::getRvcd, basinCode) .list(); if (allStationsInBasin == null || allStationsInBasin.isEmpty()) { SysUserDataScope scope = new SysUserDataScope(); scope.setUserId(userId); - scope.setOrgType("HBRVCD"); + scope.setOrgType("RVCD"); scope.setOrgId(basinCode); scope.setStatus(1); scope.setPermissionType("READ"); @@ -286,7 +286,7 @@ public class SmsVerifyCodeController { if (allStationsSelected) { SysUserDataScope scope = new SysUserDataScope(); scope.setUserId(userId); - scope.setOrgType("HBRVCD"); + scope.setOrgType("RVCD"); scope.setOrgId(basinCode); scope.setStatus(1); scope.setPermissionType("READ"); diff --git a/backend/src/main/java/com/yfd/platform/system/service/RegisterAccessTokenService.java b/backend/src/main/java/com/yfd/platform/system/service/RegisterAccessTokenService.java new file mode 100644 index 00000000..eae95315 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/system/service/RegisterAccessTokenService.java @@ -0,0 +1,89 @@ +package com.yfd.platform.system.service; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.yfd.platform.config.WebConfig; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +@Service +public class RegisterAccessTokenService { + + public static final String TOKEN_HEADER = "register-token"; + public static final String TOKEN_PARAM = "registerToken"; + public static final long EXPIRE_MILLIS = 5 * 60 * 1000L; + private static final String CACHE_PREFIX = "register:access:"; + + @Resource + private WebConfig webConfig; + + public Map createToken(HttpServletRequest request) { + String token = UUID.randomUUID().toString().replace("-", ""); + long expireAt = System.currentTimeMillis() + EXPIRE_MILLIS; + + Map payload = new HashMap<>(); + payload.put("ip", getClientIp(request)); + payload.put("userAgent", getUserAgent(request)); + payload.put("expireAt", expireAt); + + webConfig.loginuserCache().put(CACHE_PREFIX + token, JSON.toJSONString(payload), EXPIRE_MILLIS); + + Map result = new HashMap<>(); + result.put("registerToken", token); + result.put("headerName", TOKEN_HEADER); + result.put("expireIn", EXPIRE_MILLIS / 1000); + result.put("expireAt", expireAt); + return result; + } + + public boolean validateToken(String token, HttpServletRequest request) { + if (StrUtil.isBlank(token)) { + return false; + } + String cacheValue = webConfig.loginuserCache().get(CACHE_PREFIX + token); + if (StrUtil.isBlank(cacheValue)) { + return false; + } + JSONObject payload = JSON.parseObject(cacheValue); + if (payload == null) { + return false; + } + Long expireAt = payload.getLong("expireAt"); + if (expireAt == null || expireAt < System.currentTimeMillis()) { + webConfig.loginuserCache().remove(CACHE_PREFIX + token); + return false; + } + String ip = payload.getString("ip"); + String userAgent = payload.getString("userAgent"); + String clientIp = getClientIp(request); + String userAgent1 = getUserAgent(request); + return StrUtil.equals(ip,clientIp ) + && StrUtil.equals(userAgent, userAgent1); + } + + public String resolveToken(HttpServletRequest request) { + String token = request.getHeader(TOKEN_HEADER); + if (StrUtil.isBlank(token)) { + token = request.getParameter(TOKEN_PARAM); + } + return token; + } + + private String getClientIp(HttpServletRequest request) { + String ip = request.getHeader("X-Forwarded-For"); + if (StrUtil.isNotBlank(ip)) { + return ip.split(",")[0].trim(); + } + return request.getRemoteAddr(); + } + + private String getUserAgent(HttpServletRequest request) { + return StrUtil.nullToDefault(request.getHeader("User-Agent"), ""); + } +} diff --git a/backend/src/main/java/com/yfd/platform/system/service/impl/UserServiceImpl.java b/backend/src/main/java/com/yfd/platform/system/service/impl/UserServiceImpl.java index bdc2fa5e..0b108700 100644 --- a/backend/src/main/java/com/yfd/platform/system/service/impl/UserServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/system/service/impl/UserServiceImpl.java @@ -12,9 +12,11 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.qgc_data.domain.SysUserDataScope; import com.yfd.platform.qgc_data.mapper.SysUserDataScopeMapper; +import com.yfd.platform.qgc_base.domain.SdRvcdDic; import com.yfd.platform.qgc_base.domain.StationBasinInfo; import com.yfd.platform.qgc_base.mapper.SdEngInfoBHMapper; import com.yfd.platform.qgc_base.mapper.SdHbrvDicMapper; +import com.yfd.platform.qgc_base.mapper.SdRvcdDicMapper; import com.yfd.platform.system.domain.LoginUser; import com.yfd.platform.system.domain.SysRole; import com.yfd.platform.system.domain.SysUser; @@ -66,6 +68,9 @@ public class UserServiceImpl extends ServiceImpl impleme @Resource private SdEngInfoBHMapper sdEngInfoBHMapper; + + @Resource + private SdRvcdDicMapper sdRvcdDicMapper; /** * 文件空间配置 */ @@ -693,7 +698,44 @@ public class UserServiceImpl extends ServiceImpl impleme userScopeMap.computeIfAbsent(scope.getUserId(), k -> new ArrayList<>()).add(scope); } } + List stationBasinInfos = sdEngInfoBHMapper.selectStationBasinInfo(); + List activeRvcdList = sdRvcdDicMapper.selectList(new LambdaQueryWrapper() + .eq(SdRvcdDic::getEnabled, 1) + .eq(SdRvcdDic::getIsDeleted, 0)); + Map rvcdMap = new HashMap<>(); + if (activeRvcdList != null) { + for (SdRvcdDic basin : activeRvcdList) { + if (StrUtil.isNotBlank(basin.getRvcd())) { + rvcdMap.put(basin.getRvcd(), basin); + } + } + } + Map rvcdDisplayNameMap = new HashMap<>(); + Map rvcdOrderPathMap = new HashMap<>(); + for (String rvcd : rvcdMap.keySet()) { + rvcdDisplayNameMap.put(rvcd, buildRvcdDisplayName(rvcd, rvcdMap, rvcdDisplayNameMap)); + rvcdOrderPathMap.put(rvcd, buildRvcdOrderPath(rvcd, rvcdMap, rvcdOrderPathMap)); + } + + Map stationNameMap = new HashMap<>(); + Map stationReachcdMap = new HashMap<>(); + Map> rvcdStationNamesMap = new HashMap<>(); + if (stationBasinInfos != null) { + for (StationBasinInfo info : stationBasinInfos) { + if (StrUtil.isNotBlank(info.getStcd()) && StrUtil.isNotBlank(info.getEnnm())) { + stationNameMap.put(info.getStcd(), info.getEnnm()); + } + if (StrUtil.isNotBlank(info.getStcd()) && StrUtil.isNotBlank(info.getReachcd())) { + stationReachcdMap.put(info.getStcd(), info.getReachcd()); + } + if (StrUtil.isBlank(info.getReachcd()) || StrUtil.isBlank(info.getEnnm())) { + continue; + } + addStationToRvcdIndex(rvcdStationNamesMap, info.getReachcd(), info.getEnnm(), rvcdMap); + } + } + for (SysUser record : records) { String userId = record.getId(); @@ -701,44 +743,119 @@ public class UserServiceImpl extends ServiceImpl impleme record.setRoles(roles); List scopes = userScopeMap.getOrDefault(userId, Collections.emptyList()); - Set basinNameSet = new LinkedHashSet<>(); + Set basinCodeSet = new LinkedHashSet<>(); Set stationNameSet = new LinkedHashSet<>(); for (SysUserDataScope scope : scopes) { String orgType = scope.getOrgType(); String orgId = scope.getOrgId(); - String orgName = scope.getOrgName(); - if ("HBRVCD".equals(orgType)) { - if (orgName != null) { - basinNameSet.add(orgName); - } - if (orgId != null) { - if (stationBasinInfos != null) { - List stcdList = stationBasinInfos.stream().filter(info -> info.getHbrvcd().equals(orgId)).map(StationBasinInfo::getEnnm).toList(); - stationNameSet.addAll(stcdList); + if ("RVCD".equals(orgType)) { + if (StrUtil.isNotBlank(orgId)) { + basinCodeSet.add(orgId); + Set stationNames = rvcdStationNamesMap.get(orgId); + if (stationNames != null && !stationNames.isEmpty()) { + stationNameSet.addAll(stationNames); } } } else if ("STATION".equals(orgType)) { - if (orgName != null) { - stationNameSet.add(orgName); - } - if (orgId != null) { - if (stationBasinInfos != null) { - String hbrbcd = stationBasinInfos.stream().filter(info -> info.getStcd().equals(orgId)).map(StationBasinInfo::getHbrvnm).findFirst().orElse(null); - basinNameSet.add(hbrbcd); + if (StrUtil.isNotBlank(orgId)) { + String stationName = stationNameMap.get(orgId); + if (StrUtil.isNotBlank(stationName)) { + stationNameSet.add(stationName); + } else if (StrUtil.isNotBlank(scope.getOrgName())) { + stationNameSet.add(scope.getOrgName()); + } + + String reachcd = stationReachcdMap.get(orgId); + if (StrUtil.isNotBlank(reachcd)) { + basinCodeSet.add(reachcd); } } } } - record.setBasinNames(basinNameSet.isEmpty() ? null : String.join(",", basinNameSet)); - record.setStationNames(stationNameSet.isEmpty() ? null : String.join(",", stationNameSet)); + List sortedBasinNames = basinCodeSet.stream() + .sorted(Comparator.comparing((String code) -> rvcdOrderPathMap.getOrDefault(code, "~~~~~~~~~~")) + .thenComparing((String code) -> rvcdDisplayNameMap.getOrDefault(code, code), + Comparator.nullsLast(Comparator.naturalOrder())) + .thenComparing(Comparator.naturalOrder())) + .map(code -> rvcdDisplayNameMap.getOrDefault(code, code)) + .filter(StrUtil::isNotBlank) + .distinct() + .toList(); + + List sortedStationNames = stationNameSet.stream() + .filter(StrUtil::isNotBlank) + .sorted() + .toList(); + + record.setBasinNames(sortedBasinNames.isEmpty() ? null : String.join(",", sortedBasinNames)); + record.setStationNames(sortedStationNames.isEmpty() ? null : String.join(",", sortedStationNames)); } return mapPage; } + private void addStationToRvcdIndex(Map> rvcdStationNamesMap, String reachcd, + String stationName, Map rvcdMap) { + if (StrUtil.isBlank(reachcd) || StrUtil.isBlank(stationName)) { + return; + } + String currentCode = reachcd; + while (StrUtil.isNotBlank(currentCode)) { + rvcdStationNamesMap.computeIfAbsent(currentCode, key -> new LinkedHashSet<>()).add(stationName); + SdRvcdDic current = rvcdMap.get(currentCode); + if (current == null || StrUtil.isBlank(current.getPrvcd()) || "0".equals(current.getPrvcd())) { + break; + } + if (Objects.equals(current.getPrvcd(), currentCode)) { + break; + } + currentCode = current.getPrvcd(); + } + } + + private String buildRvcdDisplayName(String rvcd, Map rvcdMap, Map cache) { + if (StrUtil.isBlank(rvcd)) { + return null; + } + if (cache.containsKey(rvcd)) { + return cache.get(rvcd); + } + SdRvcdDic current = rvcdMap.get(rvcd); + if (current == null) { + return rvcd; + } + String currentName = StrUtil.blankToDefault(current.getRvnm(), rvcd); + String parentCode = current.getPrvcd(); + if (StrUtil.isBlank(parentCode) || "0".equals(parentCode)) { + return currentName; + } + String parentName = buildRvcdDisplayName(parentCode, rvcdMap, cache); + return StrUtil.isBlank(parentName) ? currentName : parentName + "-" + currentName; + } + + private String buildRvcdOrderPath(String rvcd, Map rvcdMap, Map cache) { + if (StrUtil.isBlank(rvcd)) { + return null; + } + if (cache.containsKey(rvcd)) { + return cache.get(rvcd); + } + SdRvcdDic current = rvcdMap.get(rvcd); + if (current == null) { + return "~~~~~~~~~~/" + rvcd; + } + String currentSegment = String.format("%010d", current.getOrderIndex() == null ? 999999999 : current.getOrderIndex()); + String parentCode = current.getPrvcd(); + if (StrUtil.isBlank(parentCode) || "0".equals(parentCode)) { + return currentSegment; + } + String parentPath = buildRvcdOrderPath(parentCode, rvcdMap, cache); + return StrUtil.isBlank(parentPath) ? currentSegment : parentPath + "/" + currentSegment; + } + /*********************************** * 用途说明:比较登录名称是否有重复 * 参数说明 diff --git a/backend/src/main/resources/application-devtw.yml b/backend/src/main/resources/application-devtw.yml index e34ac55d..597cd003 100644 --- a/backend/src/main/resources/application-devtw.yml +++ b/backend/src/main/resources/application-devtw.yml @@ -13,7 +13,7 @@ spring: druid: master: driverClassName: oracle.jdbc.OracleDriver - url: "${DB_MASTER_URL:jdbc:oracle:thin:@172.16.31.190:1521/SDLYZ}" + url: "${DB_MASTER_URL:jdbc:oracle:thin:@172.16.21.134:1521/SDLYZ}" username: "${DB_MASTER_USERNAME:QGC_REFA}" password: "${DB_MASTER_PASSWORD:Y4M4K1oCkL8U}" initial-size: 5 diff --git a/backend/src/main/resources/mapper/data/FishDraftDataMapper.xml b/backend/src/main/resources/mapper/data/FishDraftDataMapper.xml index a2e54147..205a2796 100644 --- a/backend/src/main/resources/mapper/data/FishDraftDataMapper.xml +++ b/backend/src/main/resources/mapper/data/FishDraftDataMapper.xml @@ -1,7 +1,7 @@ - + @@ -76,6 +76,7 @@ + @@ -85,7 +86,7 @@ D.ID, D.STCD, E.HBRVCD, - G.HBRVNM, + NULL AS HBRVNM, D.TM, D.FTP, FB.NAME FTPNAME, @@ -120,13 +121,27 @@ E.ENNM, E.BASE_ID, H.BASENAME, - E.RVCD, + E.REACHCD AS RVCD, + R.RVNM, E.LGTD, E.LTTD, E.ORDER_INDEX, D.ROW_INDEX + + LEFT JOIN ( + SELECT + d.RVCD, + LTRIM(SYS_CONNECT_BY_PATH(d.RVNM, '-'), '-') AS RVNM + FROM SD_RVCD_DIC d + WHERE NVL(d.ENABLED, 1) = 1 + AND NVL(d.IS_DELETED, 0) = 0 + START WITH d.PRVCD IS NULL OR d.PRVCD = '' OR d.PRVCD = '0' + CONNECT BY PRIOR d.RVCD = d.PRVCD + ) R ON R.RVCD = E.REACHCD + + - \ No newline at end of file + diff --git a/backend/src/main/resources/mapper/data/ImportTaskRowMapper.xml b/backend/src/main/resources/mapper/data/ImportTaskRowMapper.xml index 78a617a6..5278483b 100644 --- a/backend/src/main/resources/mapper/data/ImportTaskRowMapper.xml +++ b/backend/src/main/resources/mapper/data/ImportTaskRowMapper.xml @@ -1,7 +1,7 @@ - + diff --git a/backend/src/main/resources/mapper/data/SysUserDataScopeMapper.xml b/backend/src/main/resources/mapper/data/SysUserDataScopeMapper.xml index b5d72bda..7f4f65d0 100644 --- a/backend/src/main/resources/mapper/data/SysUserDataScopeMapper.xml +++ b/backend/src/main/resources/mapper/data/SysUserDataScopeMapper.xml @@ -1,7 +1,7 @@ - + @@ -103,36 +103,69 @@ ORDER BY s.CREATED_AT DESC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/backend/src/main/resources/mapper/qgc_base/SdEngInfoBHMapper.xml b/backend/src/main/resources/mapper/qgc_base/SdEngInfoBHMapper.xml index 0e04883c..515f6b3f 100644 --- a/backend/src/main/resources/mapper/qgc_base/SdEngInfoBHMapper.xml +++ b/backend/src/main/resources/mapper/qgc_base/SdEngInfoBHMapper.xml @@ -14,19 +14,26 @@ - - - + + + + + + + + - + - - + + + + @@ -39,7 +46,7 @@ - + @@ -47,8 +54,8 @@ - - + + @@ -80,7 +87,7 @@ - + @@ -89,17 +96,17 @@ - + - + - + @@ -138,7 +145,7 @@ - + @@ -178,12 +185,13 @@ - + - + + @@ -193,9 +201,9 @@ - - - + + + @@ -215,11 +223,11 @@ - + - - + + @@ -228,7 +236,19 @@ - + + + + + + + + + + + + + @@ -236,17 +256,31 @@ + + + + + + + + + + + + + SELECT * FROM SD_ENGINFO_B_H - WHERE RVCD = #{rvcd} - ORDER BY ORDER_INDEX ASC + + + AND REACHCD = #{reachcd} + + + AND RVCD = #{rvcd} + + + ORDER BY RVCD, REACHCD + + + + + diff --git a/backend/src/main/resources/mapper/qgc_base/SdHbrvDicMapper.xml b/backend/src/main/resources/mapper/qgc_base/SdHbrvDicMapper.xml index 09f8a32d..8bdffbb7 100644 --- a/backend/src/main/resources/mapper/qgc_base/SdHbrvDicMapper.xml +++ b/backend/src/main/resources/mapper/qgc_base/SdHbrvDicMapper.xml @@ -5,31 +5,47 @@ - + + + + + + + + + + - \ No newline at end of file + diff --git a/backend/src/main/resources/mapper/qgc_base/SdHycdDicMapper.xml b/backend/src/main/resources/mapper/qgc_base/SdHycdDicMapper.xml index 4ed2f89c..a222e511 100644 --- a/backend/src/main/resources/mapper/qgc_base/SdHycdDicMapper.xml +++ b/backend/src/main/resources/mapper/qgc_base/SdHycdDicMapper.xml @@ -10,18 +10,28 @@ - - + + - + - + + + + + + + + + SELECT * FROM SD_HYCD_DIC - WHERE PHYCD IS NULL OR PHYCD = '' OR PHYCD = '0' + WHERE NVL(ENABLED, 1) = 1 + AND NVL(IS_DELETED, 0) = 0 + AND (PHYCD IS NULL OR PHYCD = '' OR PHYCD = '0') ORDER BY ORDER_INDEX ASC diff --git a/backend/src/main/resources/mapper/qgc_base/SdHydrobaseMapper.xml b/backend/src/main/resources/mapper/qgc_base/SdHydrobaseMapper.xml index 839bafd4..8e6a6398 100644 --- a/backend/src/main/resources/mapper/qgc_base/SdHydrobaseMapper.xml +++ b/backend/src/main/resources/mapper/qgc_base/SdHydrobaseMapper.xml @@ -10,14 +10,24 @@ - + + + + + + + + + SELECT * FROM SD_HYDROBASE - WHERE PBASEID IS NULL OR PBASEID = '' OR PBASEID = '0' + WHERE NVL(ENABLED, 1) = 1 + AND NVL(IS_DELETED, 0) = 0 + AND (PBASEID IS NULL OR PBASEID = '' OR PBASEID = '0') ORDER BY ORDER_INDEX ASC diff --git a/backend/src/main/resources/mapper/qgc_base/SdRvcdDicMapper.xml b/backend/src/main/resources/mapper/qgc_base/SdRvcdDicMapper.xml index e4f11d28..504dcc0b 100644 --- a/backend/src/main/resources/mapper/qgc_base/SdRvcdDicMapper.xml +++ b/backend/src/main/resources/mapper/qgc_base/SdRvcdDicMapper.xml @@ -15,19 +15,27 @@ + - - - + + + + + + + + SELECT * FROM SD_RVCD_DIC - WHERE GRD =3 AND - PRVCD IS NULL OR PRVCD = '' OR PRVCD = '0' + WHERE NVL(ENABLED, 1) = 1 + AND NVL(IS_DELETED, 0) = 0 + AND (PRVCD IS NULL OR PRVCD = '' OR PRVCD = '0') ORDER BY ORDER_INDEX ASC + + + +