diff --git a/backend/docs/业务模块开发技术规范.md b/backend/docs/业务模块开发技术规范.md new file mode 100644 index 0000000..3037fe0 --- /dev/null +++ b/backend/docs/业务模块开发技术规范.md @@ -0,0 +1,579 @@ +# WholeProcessPlatform Backend 业务模块开发技术规范 + +## 1. 文档目的 + +本文档用于统一 `d:\shuili\WholeProcessPlatform\backend` 项目中业务模块的开发方式,重点覆盖: + +- 模块目录与分层设计规范 +- Controller、Service、Mapper、VO、Domain 的职责边界 +- 基于 `Spring Boot 4.0.3 + Java 21 + MyBatis/MyBatis-Plus` 的编码约束 +- 当前项目已形成的事实标准 +- 新增业务模块、旧系统迁移模块、字典/基础数据模块的推荐实现方式 +- SQL、异常、接口返回、分页、文档、测试、性能与安全要求 + +本文档适用于本项目所有新增或改造的业务模块,尤其适用于 `env` 目录下的生态环境类业务。 + +## 2. 技术基线 + +根据项目当前 `pom.xml`,本项目业务开发技术基线如下: + +- JDK:21 +- Spring Boot:4.0.3 +- Spring Web:MVC +- Spring Security:已引入 +- Springdoc OpenAPI:3.0.2 +- MyBatis:3.5.16 +- MyBatis Spring Boot Starter:4.0.1 +- MyBatis-Plus:3.5.16,使用 `mybatis-plus-spring-boot4-starter` +- 数据库驱动:MySQL、Oracle、达梦 +- 工具库:Hutool、Lombok、Guava、POI + +## 3. 外部参考原则 + +本文档参考了当前主流的 Spring Boot 4 / 现代 Spring 开发建议,并结合项目现状做了落地约束,核心依据如下: + +- Spring Boot 官方文档强调代码结构、配置类组织、依赖注入、外部化配置、日志、Web、Data、Validation、Actuator 等能力应作为应用开发基础。 +- Springdoc 官方文档建议使用 `springdoc-openapi-starter-webmvc-ui` 作为 OpenAPI/Swagger UI 集成方式,并通过注解与配置文件维持接口文档。 +- MyBatis Spring Boot Starter 官方文档强调在 Boot 4 体系中使用官方 starter、自动扫描 Mapper、使用配置项统一管理 MyBatis 行为。 +- MyBatis-Plus 官方文档明确支持 Spring Boot 4,推荐使用 Boot 4 对应 starter,并采用 `BaseMapper`、`ServiceImpl`、分页对象等标准方式实现常规 CRUD。 + +说明: + +- 本规范不是照搬互联网通用模板,而是“以本项目实际代码为准,吸收外部最佳实践后形成的可执行规范”。 +- 若通用建议与现有项目框架存在冲突,优先保证现有项目兼容性,再逐步演进。 + +## 4. 当前项目模块结构总结 + +`env` 模块已经形成两类主流实现风格。 + +### 4.1 基础资料型模块 + +典型文件: + +- `controller/SdCountryBController.java` +- `service/ISdCountryBService.java` +- `service/impl/SdCountryBServiceImpl.java` +- `mapper/SdCountryBMapper.java` +- `domain/SdCountryB.java` + +特征: + +- 面向单表或轻量多表的增删改查 +- Service 通常继承 `ServiceImpl` +- 使用 `BaseMapper` 和 MyBatis-Plus `lambdaQuery()` +- Controller 以分页查询、列表查询、详情查询为主 + +适用场景: + +- 字典表 +- 基础资料表 +- 标准后台管理页面 + +### 4.2 业务查询/迁移型模块 + +典型文件: + +- `controller/SdWTMonitorController.java` +- `service/SdWtMonitorService.java` +- `service/impl/SdWtMonitorServiceImpl.java` +- `service/AlongListService.java` +- `service/impl/AlongListServiceImpl.java` +- `mapper/AlongDetailMapper.java` +- `mapper/SdWtMonitorMapper.java` +- `entity/vo/*` + +特征: + +- 来自旧系统迁移的复杂业务查询较多 +- Controller 聚合多个业务接口 +- Service 接口与实现手写,通常不继承 `ServiceImpl` +- 同时存在注解 SQL、动态 SQL、MyBatis-Plus 分页 +- 使用 `DataSourceRequest`、`DataSourceResult` 适配旧平台 Kendo/DevExtreme 风格 + +适用场景: + +- 旧系统模块迁移 +- 复杂统计、图表、对比分析、联表明细 +- 需要兼容旧平台入参与返回结构的接口 + +## 5. 模块分层规范 + +### 5.1 Controller 层职责 + +Controller 仅负责: + +- 暴露路由 +- 参数接收 +- 基础空值校验 +- 调用 Service +- 统一包装 `ResponseResult` + +Controller 禁止: + +- 拼接 SQL +- 大段业务判断 +- 循环组装复杂结果 +- 直接操作 Mapper + +当前项目推荐写法: + +- 类上使用 `@RestController` +- 类上使用 `@RequestMapping` +- 类上使用 `@Tag` +- 方法上使用 `@Operation` +- 返回值统一为 `ResponseResult` + +示例风格: + +- 业务聚合 Controller:`SdWTMonitorController` +- 管理型 Controller:`SdCountryBController` + +### 5.2 Service 层职责 + +Service 层负责: + +- 业务编排 +- 参数解析 +- 分页对象生成 +- 调用 Mapper +- Java 层补充计算 +- 返回对象组装 + +Service 层应根据模块类型选择实现方式: + +- 基础 CRUD:优先 `IxxxService + ServiceImpl` +- 复杂业务查询:优先 `XxxService + XxxServiceImpl` +- 旧系统迁移模块:优先显式定义业务接口,避免泛化成通用 CRUD Service + +### 5.3 Mapper 层职责 + +Mapper 层负责: + +- 数据查询与数据写入 +- 注解 SQL 或 XML SQL +- 复杂 join、exists、聚合、分页 SQL + +Mapper 层禁止: + +- 放业务语义不清的万能 SQL +- 将参数语义不明确地混在同一个方法中 +- 为了省事直接将前端字段名等同于数据库字段名而不做映射说明 + +### 5.4 VO / DTO / Domain 职责 + +当前项目已存在三类对象: + +- `domain`:数据库实体,主要服务于 MyBatis-Plus CRUD +- `entity/vo`:前端返回对象、业务查询对象 +- `common`:分页、过滤、排序、结果包装对象 + +规范要求: + +- 单表管理页优先使用 `domain` +- 复杂查询、聚合结果、旧接口兼容结构必须使用独立 VO +- 不允许复用 `domain` 直接承接复杂联表查询结果 +- 前端字段名与数据库字段名不一致时,SQL 必须用旧字段名作为别名返回 + +## 6. 推荐目录规范 + +新增业务模块建议按如下目录落位: + +```text +src/main/java/com/yfd/platform// + controller/ + service/ + service/impl/ + mapper/ + domain/ + entity/vo/ +``` + +命名建议: + +- Controller:`XxxController` +- Service:`XxxService` +- ServiceImpl:`XxxServiceImpl` +- Mapper:`XxxMapper` +- 管理类 Service:`IXxxService` +- 管理类 ServiceImpl:`XxxServiceImpl extends ServiceImpl` +- Domain:与表/业务实体对应 +- VO:以业务含义命名,如 `SdYearListVO`、`WtFishVo` + +## 7. 接口设计规范 + +### 7.1 返回结构规范 + +本项目统一返回对象为 `ResponseResult`,必须使用: + +- `ResponseResult.success()` +- `ResponseResult.successData(data)` +- `ResponseResult.error(msg)` + +禁止: + +- Controller 直接返回裸对象 +- 不同模块返回结构不一致 +- 同类接口同时混用 `Map`、实体、裸数组作为顶层响应 + +### 7.2 异常规范 + +业务异常统一使用 `BizException`。 + +适用场景: + +- 必填参数缺失 +- 业务前置条件不满足 +- 站点、工程、字典等基础数据不存在 +- 旧接口兼容校验失败 + +推荐写法: + +```java +if (StrUtil.isBlank(stcd)) { + throw new BizException("站点编码不能为空."); +} +``` + +禁止: + +- `throw new RuntimeException(...)` +- Controller 静默吞异常 +- Service 返回 `null` 表示明确错误 + +### 7.3 参数接收规范 + +当前项目主要有两类接口: + +- Kendo/DevExtreme 风格:`@RequestBody DataSourceRequest` +- 标准后台管理风格:`@RequestParam` + 分页参数 + +规范要求: + +- 旧平台迁移接口优先保留 `DataSourceRequest` +- 后台管理接口优先使用显式参数 +- 不允许将大量业务字段塞入 `Map` 作为常规入参 +- `Map` 仅用于动态字段更新、非结构化补丁写入等少数场景 + +## 8. 分页与筛选规范 + +### 8.1 `DataSourceRequest` 适用范围 + +`DataSourceRequest` 是本项目重要的兼容层对象,适用于: + +- 迁移旧平台 Kendo Grid 接口 +- 需要复杂 filter/group/sort/select 的业务页面 +- 旧接口需要兼容前端请求结构时 + +规范要求: + +- 迁移旧接口时优先从 `DataSourceRequest` 中提取明确字段 +- 尽量封装公共提取逻辑,如使用 `QgcQueryWrapperUtil.getFilterFieldValue(...)` +- 对必要参数要先做空值校验 + +### 8.2 `DataSourceResult` 规范 + +使用 `DataSourceResult` 时应设置: + +- `data` +- `total` +- `aggregates` + +推荐: + +- 无聚合时设置空 `HashMap<>` +- 无数据时返回空列表而不是 `null` + +## 9. 依赖注入规范 + +现状: + +- 项目中大量使用 `@Resource` 字段注入 + +建议: + +- 存量代码允许继续使用 `@Resource` +- 新增业务模块优先使用构造器注入 +- 若为了保持模块风格一致,可在同一文件中延续现有注入方式 + +统一要求: + +- 不允许通过 `SpringContextHolder` 主动取 Bean 代替正常依赖注入,除非是历史兼容场景且无法重构 + +## 10. SQL 与数据访问规范 + +### 10.1 选型原则 + +优先级如下: + +1. 单表 CRUD、简单条件分页:MyBatis-Plus +2. 明确的小型查询:Mapper 注解 SQL +3. 复杂迁移查询、动态列、旧 SQL 兼容:`MicroservicDynamicSQLMapper` +4. 复杂 XML 已有现成资产且迁移成本高:可保留 XML + +### 10.2 MyBatis-Plus 适用规范 + +适用于: + +- 基础字典 +- 台账管理 +- 后台标准分页列表 + +要求: + +- 使用 `lambdaQuery()`、`lambdaUpdate()` +- 条件判断写在链式条件中 +- 避免大量手写 SQL 替代简单 CRUD + +### 10.3 动态 SQL 适用规范 + +当前项目已有 `MicroservicDynamicSQLMapper`,适用于: + +- 旧系统 SQL 平移 +- 表结构拆分后的复杂重写 +- 返回 VO 列较多且结构动态 + +使用规范: + +- 动态 SQL 必须先在 Service 中拼装完整语义,不允许把参数语义留给前端猜测 +- SQL 返回字段必须使用 VO 字段名别名 +- 参数统一通过 `Map` 绑定,禁止字符串直接拼接用户输入 +- 非必要不要在 Service 中写多个层层嵌套的查询,优先压缩为可维护的单条 SQL 或小规模明确查询 + +### 10.4 SQL 编写要求 + +必须遵循: + +- 过滤条件尽量前置 +- 明确 `IS_DELETED = 0` +- 与旧系统兼容时保留 `USFL`、`MWAY`、`DTIN_TYPE`、`STTP` 等业务条件 +- 联表字段语义必须先确认再关联 +- 能用 `EXISTS` 的场景优先评估是否优于无谓 join +- 排序字段应稳定,避免前端列表顺序漂移 + +禁止: + +- 用错误语义字段强行 join +- 在 SQL 中随意猜测旧字段映射 +- 使用无法参数化的用户输入拼接 SQL + +### 10.5 旧系统迁移专项规则 + +迁移模块时必须先做三件事: + +1. 找到旧 Controller/Service/Mapper/XML 主入口 +2. 梳理旧表关系和字段语义 +3. 建立旧表到新表的映射说明 + +禁止: + +- 未分析旧 SQL 语义就直接按字段名猜测重写 +- 把旧“横表字段”误当成新“关系表字段” +- 为了快速实现,破坏旧接口请求和返回结构 + +## 11. 业务模块编码规范 + +### 11.1 Controller 编码规范 + +- 一个 Controller 只承载同一业务域或同一前端页面聚合能力 +- 聚合型 Controller 可以包含多个子接口,但应保持前缀一致 +- 方法名与 `@Operation(summary = "...")` 应表达真实业务语义 +- 空值校验放在 Controller 或 Service 入口,不能完全依赖底层报错 + +### 11.2 Service 编码规范 + +- 一个方法只表达一个明确业务能力 +- 复杂逻辑可拆为少量私有方法,但不要抽象出与旧业务语义脱节的“工具方法泛滥” +- 允许在 Service 层做二次排序、月份格式化、标志位组装、列头组装等 Java 后处理 +- 数据库语义判断优先放 SQL,纯展示逻辑优先放 Java + +### 11.3 VO 编码规范 + +- VO 字段必须服务于前端返回,不要无意义堆字段 +- 对旧接口兼容字段要保持命名稳定 +- 使用 Lombok 时优先 `@Data` 或 `@Getter/@Setter` +- 对外 VO 建议加 `@Schema` 注释 + +### 11.4 Domain 编码规范 + +- Domain 应与真实表结构对齐 +- 建议保持字段名、注释、表映射一致 +- 不要将 VO 字段、临时业务字段塞进 Domain + +## 12. 文档与 OpenAPI 规范 + +项目当前已引入 `springdoc-openapi-starter-webmvc-ui`,因此新增接口必须同时维护接口文档。 + +要求: + +- Controller 类使用 `@Tag` +- 方法使用 `@Operation` +- 复杂 VO 使用 `@Schema` +- 对外接口要有清晰的 `summary` + +推荐: + +- 对关键参数补充 `description` +- 对复杂返回结构单独定义 VO,不返回匿名 `Map` +- 将生产环境的 OpenAPI/Swagger UI 访问权限纳入安全控制 + +## 13. 配置管理规范 + +根据 Spring Boot 官方建议,配置应外部化管理。 + +项目要求: + +- 数据源、缓存、安全、文档开关、日志级别等必须放配置文件 +- 多环境配置使用 profile 管理 +- 不允许将数据库地址、账号、密码、第三方密钥硬编码进 Java 代码 +- 与数据库方言相关的行为尽量通过配置或基础层封装统一管理 + +## 14. 日志与可观测性规范 + +项目已引入 `spring-boot-starter-actuator`,因此新增模块应具备基本可观测性意识。 + +要求: + +- 业务异常使用统一异常体系,不在正常分支打 error 日志 +- 大查询、长耗时任务、批量处理建议记录 info/debug 级别日志 +- 不记录敏感字段原文 +- 生产问题定位优先结合 Actuator、日志、SQL 条件进行 + +建议: + +- 对复杂迁移接口记录关键参数与结果数量 +- 对导入、导出、批处理记录耗时 + +## 15. 安全规范 + +由于项目已引入 Spring Security,新增模块应遵循最小暴露原则。 + +要求: + +- Swagger/OpenAPI 文档在生产环境应受控 +- 任何写接口必须考虑权限控制与审计要求 +- 参数校验必须前置,避免越权探测和异常信息泄露 +- 对动态 SQL 特别关注注入风险,所有用户输入都必须通过参数绑定 + +## 16. 测试规范 + +### 16.1 必测场景 + +新增业务模块至少要验证: + +- 正常查询 +- 必填参数缺失 +- 空数据返回 +- 关键筛选条件命中 +- 排序/分页正确 + +### 16.2 测试建议 + +- 单表 CRUD 模块:优先补 Service/Mapper 单元或集成测试 +- 迁移型查询模块:至少保留典型请求体样例和 SQL 验证说明 +- 高风险接口:建议补接口级集成测试 + +### 16.3 不建议 + +- 为了补测试而写无价值的样板测试 +- 完全重复实现逻辑本身的测试 + +## 17. 性能规范 + +### 17.1 查询性能 + +- 优先明确主表与过滤条件 +- 少用无必要的多层嵌套子查询 +- 大表统计优先关注时间条件、站点条件、逻辑删除条件是否下推 +- `ROWNUM = 1`、`FETCH FIRST 1 ROWS ONLY` 等默认值查询必须确保排序稳定 + +### 17.2 Java 21 使用建议 + +本项目使用 Java 21,但业务模块默认仍以同步 MVC 为主。 + +建议: + +- 普通查询接口保持同步风格,避免过早引入响应式复杂度 +- CPU 密集或 I/O 密集的异步能力需经过明确评估后再引入 +- 语言特性应以可读性优先,避免为了“新语法”牺牲团队可维护性 + +## 18. 新增业务模块推荐模板 + +### 18.1 基础管理模块模板 + +- `domain/Xxx.java` +- `mapper/XxxMapper.java` +- `service/IXxxService.java` +- `service/impl/XxxServiceImpl.java` +- `controller/XxxController.java` + +适用: + +- 国家、流域、字典、基础表管理 + +### 18.2 复杂查询模块模板 + +- `entity/vo/XxxVO.java` +- `mapper/XxxMapper.java` +- `service/XxxService.java` +- `service/impl/XxxServiceImpl.java` +- `controller/XxxController.java` + +适用: + +- 旧平台迁移 +- 统计分析 +- 图表联查 +- 多表业务判断 + +## 19. 开发禁止项 + +以下行为在新增业务模块中原则上禁止: + +- Controller 直接操作 Mapper +- 直接返回裸 `Map` 作为通用接口响应 +- 大量复制旧 SQL 但不校验字段语义 +- 将前端字段名直接拼成 SQL 片段 +- 业务异常使用 `RuntimeException` +- 多个接口返回结构风格不统一 +- 在 Service 中堆积无法复用、语义不清的“万能工具方法” +- 未确认表语义就擅自把旧表字段映射到新表字段 +- 对外接口无 `@Operation` 文档说明 + +## 20. 迁移模块专项检查清单 + +新增或改造迁移模块时,提交前必须自检: + +- 是否定位了旧入口 Controller/Service/Mapper/XML +- 是否梳理了旧表职责与表关系 +- 是否建立了旧表到新表的映射说明 +- 是否保持了旧接口路径、入参名、返回字段的兼容性 +- 是否校验了关键 SQL 的过滤条件、排序条件和时间口径 +- 是否补充了空值、默认值、无数据场景处理 +- 是否检查了 `IS_DELETED`、`USFL`、`MWAY`、`DTIN_TYPE` 等业务条件 +- 是否校验了 `ResponseResult`、`DataSourceResult`、VO 返回结构 +- 是否完成最基本的诊断或测试验证 + +## 21. 推荐落地原则 + +本项目业务模块开发建议遵循以下顺序: + +1. 先确认业务语义与表关系 +2. 再确定模块属于 CRUD 型还是迁移查询型 +3. 再选择 MyBatis-Plus、注解 SQL 或动态 SQL +4. 再定义 VO/Domain/Service/Controller 落位 +5. 最后补异常、文档、校验、测试与性能检查 + +一句话原则: + +以项目现有架构为主线,以 Spring Boot 4.0 现代实践为约束,以“业务语义正确、接口兼容、SQL 可维护、结构可复用”为最终标准。 + +## 22. 附录:外部参考资料 + +- Spring Boot Documentation Overview + - https://docs.spring.io/spring-boot/documentation.html +- springdoc OpenAPI Getting Started + - https://springdoc.org/getting-started.html +- MyBatis-Plus Quick Start + - https://baomidou.com/en/getting-started/ +- MyBatis Spring Boot Starter Reference + - https://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/ diff --git a/backend/src/main/java/com/yfd/platform/common/MicroservicDynamicSQLMapper.java b/backend/src/main/java/com/yfd/platform/common/MicroservicDynamicSQLMapper.java index 930d806..56b6017 100644 --- a/backend/src/main/java/com/yfd/platform/common/MicroservicDynamicSQLMapper.java +++ b/backend/src/main/java/com/yfd/platform/common/MicroservicDynamicSQLMapper.java @@ -1,28 +1,52 @@ package com.yfd.platform.common; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.bean.copier.CopyOptions; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Mapper; +import java.util.List; +import java.util.Map; +import java.util.ArrayList; +import java.lang.reflect.Constructor; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; -import java.util.List; -import java.util.Map; - @Mapper public interface MicroservicDynamicSQLMapper { + @Select({""}) + List> pageAllList(Page page, @Param("sql") String sql, @Param("map") Map map); - @Select({"${sql}"}) - List> pageAllList(Page page, String sql, @Param("map") Map map); + default List pageAllListWithResultType(Page page, + String sql, + Map map, + Class resultType) { + return convertList(pageAllList(page, sql, map), resultType); + } - @Select({"${sql}"}) - List pageAllListWithResultType(Page page, @Param("sql") String sql, @Param("map") Map map, @Param("resultType") Class resultType); + @Select({""}) + Map getOneBySql(@Param("sql") String sql, @Param("map") Map map); - @Select({"${sql}"}) - List getAllList(String sql, @Param("map") Map map); - @Select({"${sql}"}) - List getAllListWithResultType(@Param("sql") String sql, @Param("map") Map map, @Param("resultType") Class resultType); + default R getOneBySqlWithResultType(String sql, + Map map, + Class resultType) { + Map resultMap = getOneBySql(sql, map); + CopyOptions copyOptions = CopyOptions.create() + .setIgnoreCase(true) + .setIgnoreError(true); + return BeanUtil.fillBeanWithMap(resultMap, createTargetBean(resultType), copyOptions); + } + + + @Select({""}) + List> getAllList(@Param("sql") String sql, @Param("map") Map map); + + default List getAllListWithResultType(String sql, + Map map, + Class resultType) { + return convertList(getAllList(sql, map), resultType); + } @Select({"select count(1) count from ${sql} and ${ew.sqlSegment}"}) Integer count(@Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); @@ -31,31 +55,36 @@ public interface MicroservicDynamicSQLMapper { Integer countNoWrapper(@Param("select") String select, @Param("sql") String sql); @Select({"select ${select} from ${sql} and ${ew.sqlSegment}"}) - List pageList(Page page, @Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); + List> pageList(Page page, @Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); - @Select({"select ${select} from ${sql} and ${ew.sqlSegment}"}) - List pageListWithResultType(Page page, @Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper, @Param("resultType") Class resultType); + default List pageListWithResultType(Page page, + String select, + String sql, + QueryWrapper queryWrapper, + Class resultType) { + return convertList(pageList(page, select, sql, queryWrapper), resultType); + } @Select({"select ${select} from ${sql} ${ew.sqlSegment}"}) - List pageNoFilterList(Page page, @Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); + List> pageNoFilterList(Page page, @Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); @Select({"select ${select} from ${sql}"}) - List pageListNoWrapper(Page page, @Param("select") String select, @Param("sql") String sql); + List> pageListNoWrapper(Page page, @Param("select") String select, @Param("sql") String sql); @Select({"select ${select} from ${sql} and ${ew.sqlSegment}"}) - List getList(@Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); + List> getList(@Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); @Select({"select ${select} from ${sql} and ${ew.sqlSegment}"}) - List getListWithResultType(@Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); + List> getListWithResultType(@Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); @Select({"select ${select} from ${table} where ${condition}"}) - List getSingleTableList(@Param("select") String select, @Param("table") String table, @Param("condition") String condition); + List> getSingleTableList(@Param("select") String select, @Param("table") String table, @Param("condition") String condition); @Select({"select ${select} from ${sql} ${ew.sqlSegment}"}) - List getNoFilterList(@Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); + List> getNoFilterList(@Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); @Select({"select ${select} from ${sql}"}) - List getListNoWrapper(@Param("select") String select, @Param("sql") String sql); + List> getListNoWrapper(@Param("select") String select, @Param("sql") String sql); @Select({"select ${select} from ${sql} and ${ew.sqlSegment}"}) Map totalSummary(@Param("select") String select, @Param("sql") String sql, @Param("ew") QueryWrapper queryWrapper); @@ -77,4 +106,29 @@ public interface MicroservicDynamicSQLMapper { @Select({"select ${info} from ${joinsql} group by ${info}"}) List getGroup(@Param("info") String info, @Param("joinsql") String joinsql); -} \ No newline at end of file + + static List convertList(List> sourceList, Class resultType) { + List resultList = new ArrayList<>(); + if (sourceList == null || sourceList.isEmpty()) { + return resultList; + } + CopyOptions copyOptions = CopyOptions.create() + .setIgnoreCase(true) + .setIgnoreError(true); + for (Map row : sourceList) { + R bean = BeanUtil.fillBeanWithMap(row, createTargetBean(resultType), copyOptions); + resultList.add(bean); + } + return resultList; + } + + static R createTargetBean(Class resultType) { + try { + Constructor constructor = resultType.getDeclaredConstructor(); + constructor.setAccessible(true); + return constructor.newInstance(); + } catch (Exception e) { + throw new IllegalStateException("动态SQL结果映射失败,目标类型必须提供无参构造器: " + resultType.getName(), e); + } + } +} 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 ac00ba5..ba6eb18 100644 --- a/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java +++ b/backend/src/main/java/com/yfd/platform/config/SecurityConfig.java @@ -59,7 +59,7 @@ public class SecurityConfig { .requestMatchers("/system/user/auditUser").permitAll() .requestMatchers("/eng/**").permitAll() .requestMatchers("/env/**").permitAll() - .requestMatchers("/sw/**").permitAll() + .requestMatchers("/wt/**").permitAll() .requestMatchers("/data/**").permitAll() .requestMatchers("/sms/**").permitAll() .requestMatchers(HttpMethod.GET, "/").permitAll() diff --git a/backend/src/main/java/com/yfd/platform/env/controller/SdAlongDetailController.java b/backend/src/main/java/com/yfd/platform/env/controller/SdAlongDetailController.java deleted file mode 100644 index 4be5593..0000000 --- a/backend/src/main/java/com/yfd/platform/env/controller/SdAlongDetailController.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.yfd.platform.env.controller; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.yfd.platform.common.DataSourceRequest; -import com.yfd.platform.common.DataSourceResult; -import com.yfd.platform.config.ResponseResult; -import com.yfd.platform.env.entity.vo.BatchDeleteAo; -import com.yfd.platform.env.entity.vo.WtrvInfo; -import com.yfd.platform.env.service.AlongDetailService; -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.*; - -import java.util.Map; - -@RestController -@RequestMapping("/sw/alongDetail") -@Tag(name = "沿程水温变化二级数据接口") -@Validated -public class SdAlongDetailController { - - @Resource - private AlongDetailService alongDetailService; - - - @PostMapping("/GetKendoListCust") - @Operation(summary = "查询沿程水温变化二级数据列表") - public ResponseResult getKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { - DataSourceResult result = alongDetailService.processKendoList(dataSourceRequest, null, new Page<>()); - return ResponseResult.successData(result); - } - - @PostMapping("/updateWtrvRData") - @Operation(summary = "修改表层水温日数据") - public ResponseResult updateWtrvRData(@RequestBody Map updateData) { - alongDetailService.updateWtrvRData(updateData); - return ResponseResult.success(); - } - - @PostMapping("/day/GetKendoListCust") - @Operation(summary = "查询出库水温日数据") - public ResponseResult getKendoDayListCust(@RequestBody DataSourceRequest dataSourceRequest) { - DataSourceResult result = alongDetailService.processDayKendoList(dataSourceRequest, null, new Page<>(), null); - return ResponseResult.successData(result); - } - - @PostMapping("/drtp/GetKendoListCust") - @Operation(summary = "查询出库水温周旬月季年数据") - public ResponseResult getKendoDrtpListCust(@RequestBody DataSourceRequest dataSourceRequest) { - DataSourceResult result = alongDetailService.processDrtpKendoList(dataSourceRequest, null, new Page<>(), null); - return ResponseResult.successData(result); - } - - @PostMapping("/drtp/removeKendoByIds") - @Operation(summary = "删除出库水温周旬月季年数据") - public ResponseResult removeKendoByIds(@RequestBody BatchDeleteAo batchDeleteAo) { - alongDetailService.removeKendoByIds(batchDeleteAo); - return ResponseResult.success(); - } - -// @PostMapping("/qgc/GetKendoListCust") -// @Operation(summary = "环保部查询出入库水温、出入库流量、入库水温、天然水温、降雨、气温数据") -// public ResponseResult getQgcKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { -// DataSourceResult result = alongDetailService.getQgcKendoListCust(dataSourceRequest); -// return ResponseResult.successData(result); -// } - - @GetMapping("/qgc/stcdCheck") - @Operation(summary = "判断出库水温站、垂向水温站或者低温水减缓设施所属的电站是否有出库水温站、垂向水温站和低温水减缓设施") - public ResponseResult getQgcStcdCheck(@RequestParam String stcd) { - WtrvInfo result = alongDetailService.getWtrvInfoByStcd2(stcd); - return ResponseResult.successData(result); - } - - @GetMapping("/qgc/stcdCheck2") - @Operation(summary = "判断出库水温站、垂向水温站所属的电站是否有出库水温站、垂向水温站") - public ResponseResult getQgcStcdCheck2(@RequestParam String stcd) { - WtrvInfo result = alongDetailService.getWtrvInfoByStcd3(stcd); - return ResponseResult.successData(result); - } -} diff --git a/backend/src/main/java/com/yfd/platform/env/controller/SdAlongListController.java b/backend/src/main/java/com/yfd/platform/env/controller/SdAlongListController.java deleted file mode 100644 index a169ad3..0000000 --- a/backend/src/main/java/com/yfd/platform/env/controller/SdAlongListController.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.yfd.platform.env.controller; - -import com.yfd.platform.common.DataSourceRequest; -import com.yfd.platform.common.DataSourceResult; -import com.yfd.platform.config.ResponseResult; -import com.yfd.platform.env.service.AlongListService; -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; - -/** - * 沿程水温变化一级折线图 - * - * @author lyl - * @date 2023/04/18 19:22 - */ -@RestController -@RequestMapping("/sw/alongList") -@Tag(name = "沿程水温变化一级折线图") -@Validated -public class SdAlongListController{ - - @Resource - private AlongListService alongListService; - - - @PostMapping({"/limit"}) - @Operation(summary = "获取流域沿程水温限值") - public ResponseResult getWtLimit(@RequestBody DataSourceRequest dataSourceRequest) { - return ResponseResult.successData(alongListService.getWtLimit(dataSourceRequest)); - } - - @PostMapping({"/default/rvcd"}) - @Operation(summary = "获取沿程水温变化默认有数据的河流") - public ResponseResult getDefaultStcd(@RequestBody DataSourceRequest dataSourceRequest) { - - return ResponseResult.successData(alongListService.getDefaultRvcd(dataSourceRequest)); - } - - @PostMapping({"/qgc/GetKendoListCust"}) - @Operation(summary = "按时间范围查询沿程水温站最新数据时间的数据") - public ResponseResult getALongKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { - return ResponseResult.successData(this.alongListService.getALongKendoListCust(dataSourceRequest)); - } - -} \ No newline at end of file diff --git a/backend/src/main/java/com/yfd/platform/env/controller/SdWTMonitorController.java b/backend/src/main/java/com/yfd/platform/env/controller/SdWTMonitorController.java new file mode 100644 index 0000000..c503cc2 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/controller/SdWTMonitorController.java @@ -0,0 +1,225 @@ +package com.yfd.platform.env.controller; + +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.exception.BizException; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.env.entity.vo.BatchDeleteAo; +import com.yfd.platform.env.entity.vo.WtrvInfo; +import com.yfd.platform.env.service.*; +import com.yfd.platform.utils.QgcQueryWrapperUtil; +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.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("/wt") +@Tag(name = "水温监测") +@Validated +public class SdWTMonitorController { + + + @Resource + private AlongDetailService alongDetailService; + + @Resource + private AlongListService alongListService; + + @Resource + private SdWtMonitorService sdWtMonitorService; + + @Resource + private SdRvwtSInOutOneService sdRvwtSInOutOneService; + + @Resource + private SdDzChuiXiangListService sdDzChuiXiangListService; + + @Resource + private SdWtvtRService sdWtvtRService; + + + @PostMapping("/alongDetail/GetKendoListCust") + @Operation(summary = "查询沿程水温变化二级数据列表") + public ResponseResult getKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + DataSourceResult result = alongDetailService.processKendoList(dataSourceRequest, null, new Page<>()); + return ResponseResult.successData(result); + } + + @PostMapping("/alongDetail/updateWtrvRData") + @Operation(summary = "修改表层水温日数据") + public ResponseResult updateWtrvRData(@RequestBody Map updateData) { + alongDetailService.updateWtrvRData(updateData); + return ResponseResult.success(); + } + + @PostMapping("/alongDetail/day/GetKendoListCust") + @Operation(summary = "查询出库水温日数据") + public ResponseResult getKendoDayListCust(@RequestBody DataSourceRequest dataSourceRequest) { + DataSourceResult result = alongDetailService.processDayKendoList(dataSourceRequest, null, new Page<>(), null); + return ResponseResult.successData(result); + } + + @PostMapping("/alongDetail/drtp/GetKendoListCust") + @Operation(summary = "查询出库水温周旬月季年数据") + public ResponseResult getKendoDrtpListCust(@RequestBody DataSourceRequest dataSourceRequest) { + DataSourceResult result = alongDetailService.processDrtpKendoList(dataSourceRequest, null, new Page<>(), null); + return ResponseResult.successData(result); + } + + @PostMapping("/alongDetail/drtp/removeKendoByIds") + @Operation(summary = "删除出库水温周旬月季年数据") + public ResponseResult removeKendoByIds(@RequestBody BatchDeleteAo batchDeleteAo) { + alongDetailService.removeKendoByIds(batchDeleteAo); + return ResponseResult.success(); + } + + @PostMapping("/alongDetail/qgc/GetKendoListCust") + @Operation(summary = "环保部查询出入库水温、出入库流量、入库水温、天然水温、降雨、气温数据") + public ResponseResult getQgcKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + String stcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd"); + if (StrUtil.isBlank(stcd)) { + throw new BizException("站点编码不能为空."); + } + WtrvInfo wtrvInfo = alongDetailService.getWtrvInfoByStcd(stcd); + if (wtrvInfo == null) { + throw new BizException("获取站点信息失败,请检查是否站点存在."); + } + DataSourceResult result = alongDetailService.processKendoList(dataSourceRequest, null, new Page<>()); + if (wtrvInfo.getType() == 3 || result == null || result.getData() == null || result.getTotal() == 0) { + return ResponseResult.successData(result); + } + DataSourceResult qgcResult = alongDetailService.processQgcKendList(result, wtrvInfo); + return ResponseResult.successData(qgcResult); + } + + @GetMapping("/alongDetail/qgc/stcdCheck") + @Operation(summary = "判断出库水温站、垂向水温站或者低温水减缓设施所属的电站是否有出库水温站、垂向水温站和低温水减缓设施") + public ResponseResult getQgcStcdCheck(@RequestParam String stcd) { + WtrvInfo result = alongDetailService.getWtrvInfoByStcd2(stcd); + return ResponseResult.successData(result); + } + + @GetMapping("/alongDetail/qgc/stcdCheck2") + @Operation(summary = "判断出库水温站、垂向水温站所属的电站是否有出库水温站、垂向水温站") + public ResponseResult getQgcStcdCheck2(@RequestParam String stcd) { + if (StrUtil.isBlank(stcd)) { + throw new BizException("站点编码不能为空."); + } + WtrvInfo result = alongDetailService.getWtrvInfoByStcd3(stcd); + return ResponseResult.successData(result); + } + + + @PostMapping({"/alongList/limit"}) + @Operation(summary = "获取流域沿程水温限值") + public ResponseResult getWtLimit(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(alongListService.getWtLimit(dataSourceRequest)); + } + + @PostMapping({"/alongList/default/rvcd"}) + @Operation(summary = "获取沿程水温变化默认有数据的河流") + public ResponseResult getDefaultRVCD(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(alongListService.getDefaultRvcd(dataSourceRequest)); + } + + @PostMapping({"/alongList/qgc/GetKendoListCust"}) + @Operation(summary = "按时间范围查询沿程水温站最新数据时间的数据") + public ResponseResult getALongKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(this.alongListService.getALongKendoListCust(dataSourceRequest)); + } + + @PostMapping("/monthList/avgMon/GetKendoListCust") + @Operation(summary = "获取月平均水温历史对比数据") + public ResponseResult getMonthKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(this.alongListService.getMonthKendoListCust(dataSourceRequest)); + } + + @PostMapping("/yearList/default/stcd") + @Operation(summary = "获取水温年内分布默认有数据的电站") + public ResponseResult getYearDefaultStcd(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(this.alongListService.getYearDefaultStcd(dataSourceRequest)); + } + + @PostMapping("/yearList/GetKendoListCust") + @Operation(summary = "水温年内分布与天然水温对比") + public ResponseResult getYearList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(this.alongListService.getYearList(dataSourceRequest)); + } + + + @PostMapping("/base/evnmAutoMonitor/GetKendoListCust") + @Operation(summary = "查询水温监测数量") + public ResponseResult getWTDataCount(@RequestBody(required = false) DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(sdWtMonitorService.getEvnmAutoMonitorList()); + } + + @PostMapping("/base/vmsstbprpt/GetKendoList") + @Operation(summary = "根据类型查询水温表基本数据") + public ResponseResult getVmsstbprptList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(sdWtMonitorService.getVmsstbprptList(dataSourceRequest)); + } + + @PostMapping("/cxDetail/GetKendoListCust") + @Operation(summary = "查询垂向水温明细") + public ResponseResult getCxDetailList(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(sdWtMonitorService.getCxDetailList(dataSourceRequest)); + } + + @PostMapping("/wtvt/defaultYear/GetKendoListCust") + @Operation(summary = "获取垂向水温有数据的年份") + public ResponseResult getWtrvDefaultYear(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(sdWtvtRService.getWtrvDefaultYear(dataSourceRequest)); + } + + @PostMapping("/wtrv/fish/GetKendoListCust") + @Operation(summary = "鱼类繁殖适宜性分析") + public ResponseResult getWtFishAnalysis(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(sdWtMonitorService.getWtFishAnalysis(dataSourceRequest)); + } + + @GetMapping("/wtrv/getIoWtrvFlag") + @Operation(summary = "根据站点编码判断是否出入水温站且关联的电站是否有垂向水温站") + public ResponseResult getFlagByStcd(@RequestParam String stcd) { + if (StrUtil.isBlank(stcd)) { + throw new BizException("站点编码不能为空!"); + } + return ResponseResult.successData(sdWtMonitorService.getFlagByStcd(stcd)); + } + + + @PostMapping("/inOutOne/GetKendoListCust") + @Operation(summary = "查询出入库水温一级列表") + public ResponseResult getOneLevelCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(sdRvwtSInOutOneService.processKendoList(dataSourceRequest)); + } + + @PostMapping("/inOutOne/details") + @Operation(summary = "一次性返回出库水温和入库水温详情") + public ResponseResult getDetails(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(sdRvwtSInOutOneService.getDetails(dataSourceRequest)); + } + + @PostMapping("/inOutOne/default/stcd") + @Operation(summary = "获取出入库水温默认有数据的电站") + public ResponseResult getDefaultStcd(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(sdRvwtSInOutOneService.getDefaultStcd(dataSourceRequest)); + } + + + + @PostMapping({"/dzCxList/GetKendoListCust"}) + @Operation(summary = "电站专题垂向水温一级面板数据列表") + public ResponseResult getOneLevelListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(sdDzChuiXiangListService.processKendoList(dataSourceRequest)); + } +} diff --git a/backend/src/main/java/com/yfd/platform/env/controller/SdWtvtRController.java b/backend/src/main/java/com/yfd/platform/env/controller/SdWtvtRController.java new file mode 100644 index 0000000..0eae5df --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/controller/SdWtvtRController.java @@ -0,0 +1,36 @@ +package com.yfd.platform.env.controller; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.env.service.SdWtvtRService; +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; + +/** + * 垂向水温Controller + * + * @author + * @date 2023/04/18 19:22 + */ +@RestController +@RequestMapping("/sw/wtvt") +@Tag(name = "垂向水温") +@Validated +public class SdWtvtRController { + + @Resource + private SdWtvtRService sdWtvtRService; + + @PostMapping({"/defaultYear/GetKendoListCust"}) + @Operation(summary = "获取垂向水温有数据的年份") + public ResponseResult getWtrvDefaultYear(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(sdWtvtRService.getWtrvDefaultYear(dataSourceRequest)); + } +} diff --git a/backend/src/main/java/com/yfd/platform/env/entity/vo/FishSpawnVo.java b/backend/src/main/java/com/yfd/platform/env/entity/vo/FishSpawnVo.java new file mode 100644 index 0000000..0cd81a8 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/entity/vo/FishSpawnVo.java @@ -0,0 +1,21 @@ +package com.yfd.platform.env.entity.vo; + +import lombok.Data; + +import java.util.List; + +@Data +public class FishSpawnVo { + + private String id; + + private String name; + + private String spawnMonthStr; + + private List spawnMonth; + + private String pretempStr; + + private List pretemp; +} diff --git a/backend/src/main/java/com/yfd/platform/env/entity/vo/SdDzChuiXiangListVO.java b/backend/src/main/java/com/yfd/platform/env/entity/vo/SdDzChuiXiangListVO.java new file mode 100644 index 0000000..7caa7bf --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/entity/vo/SdDzChuiXiangListVO.java @@ -0,0 +1,21 @@ +package com.yfd.platform.env.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.FieldNameConstants; + +import java.math.BigDecimal; + +@Getter +@Setter +@FieldNameConstants +@Schema(description = "电站专题垂向水温一级面板VO") +public class SdDzChuiXiangListVO { + + @Schema(description = "水温深度") + private BigDecimal wthg; + + @Schema(description = "水温") + private BigDecimal vwt; +} diff --git a/backend/src/main/java/com/yfd/platform/env/entity/vo/SdRvwtSVO.java b/backend/src/main/java/com/yfd/platform/env/entity/vo/SdRvwtSVO.java new file mode 100644 index 0000000..065ccaf --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/entity/vo/SdRvwtSVO.java @@ -0,0 +1,56 @@ +package com.yfd.platform.env.entity.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.FieldNameConstants; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +@Getter +@Setter +@FieldNameConstants +@Schema(description = "出入库水温数据VO") +public class SdRvwtSVO implements Serializable { + + private static final long serialVersionUID = 1L; + + public static final String DWTP_IWT = "IWT"; + + public static final String DWTP_DWT = "DWT"; + + @Schema(description = "站码") + private String stcd; + + @Schema(description = "站名") + private String stnm; + + @Schema(description = "时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date dt; + + @Schema(description = "时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date tm; + + @Schema(description = "水温") + private BigDecimal wt; + + @Schema(description = "类型:IWT=入库,DWT=出库") + private String dwtp; + + @Schema(description = "所属电站入库水温编码") + private String engIwtCode; + + @Schema(description = "所属电站出库水温编码") + private String engDwtCode; + + @Schema(description = "入库水温值") + private BigDecimal iwtValue; + + @Schema(description = "出库水温值") + private BigDecimal dwtValue; +} diff --git a/backend/src/main/java/com/yfd/platform/env/entity/vo/SdWtBaseInfoVO.java b/backend/src/main/java/com/yfd/platform/env/entity/vo/SdWtBaseInfoVO.java new file mode 100644 index 0000000..d329860 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/entity/vo/SdWtBaseInfoVO.java @@ -0,0 +1,50 @@ +package com.yfd.platform.env.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@Data +@Schema(description = "水温表基本数据") +public class SdWtBaseInfoVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "基地名称") + private String baseName; + + @Schema(description = "站名") + private String stnm; + + @Schema(description = "电站名称") + private String ennm; + + @Schema(description = "建成日期") + private Date jcdt; + + @Schema(description = "监测指标") + private String stindx; + + @Schema(description = "开展环保自动检测工作状态:1=正常 0=暂无数据") + private Integer coenvwState; + + @Schema(description = "站类") + private String sttpCode; + + @Schema(description = "站码") + private String stcd; + + @Schema(description = "所属电站编码") + private String rstcd; + + @Schema(description = "所属测站编码") + private String stCode; + + @Schema(description = "所属测站名称") + private String stName; + + @Schema(description = "开发方式") + private String dvtp; +} diff --git a/backend/src/main/java/com/yfd/platform/env/entity/vo/SdWtMonitorCountVO.java b/backend/src/main/java/com/yfd/platform/env/entity/vo/SdWtMonitorCountVO.java new file mode 100644 index 0000000..86e51ce --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/entity/vo/SdWtMonitorCountVO.java @@ -0,0 +1,31 @@ +package com.yfd.platform.env.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +@Data +@Schema(description = "水温监测数量统计") +public class SdWtMonitorCountVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "数量") + private Long cnt; + + @Schema(description = "排序号") + private Integer orderInx; + + @Schema(description = "排序号名称") + private String orderInxName; + + @Schema(description = "站类完整路径") + private String sttpFullPath; + + @Schema(description = "站类编码") + private String sttpCode; + + @Schema(description = "站类名称") + private String sttpName; +} diff --git a/backend/src/main/java/com/yfd/platform/env/entity/vo/SdWtvtYearVo.java b/backend/src/main/java/com/yfd/platform/env/entity/vo/SdWtvtYearVo.java new file mode 100644 index 0000000..8d10ac4 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/entity/vo/SdWtvtYearVo.java @@ -0,0 +1,21 @@ +package com.yfd.platform.env.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.FieldNameConstants; + +import java.math.BigDecimal; + +@Getter +@Setter +@FieldNameConstants +@Schema(description = "垂向水温年份列表VO") +public class SdWtvtYearVo { + + @Schema(description = "站码") + private String stcd; + + @Schema(description = "年份") + private String yr; +} diff --git a/backend/src/main/java/com/yfd/platform/env/entity/vo/SdYearListVO.java b/backend/src/main/java/com/yfd/platform/env/entity/vo/SdYearListVO.java new file mode 100644 index 0000000..f123e9f --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/entity/vo/SdYearListVO.java @@ -0,0 +1,40 @@ +package com.yfd.platform.env.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.math.BigDecimal; + +@Getter +@Setter +@Schema(description = "水温年内分布VO") +public class SdYearListVO { + + @Schema(description = "站码") + private String stcd; + + @Schema(description = "所属电站编码") + private String rstcd; + + @Schema(description = "站名") + private String stnm; + + @Schema(description = "年份") + private String year; + + @Schema(description = "月份排序值") + private Integer monthInt; + + @Schema(description = "月份") + private String month; + + @Schema(description = "实测值水温") + private BigDecimal actualTemp; + + @Schema(description = "天然水温") + private BigDecimal naturalTemp; + + @Schema(description = "维度类型") + private String drtp; +} diff --git a/backend/src/main/java/com/yfd/platform/env/entity/vo/StcdVo.java b/backend/src/main/java/com/yfd/platform/env/entity/vo/StcdVo.java new file mode 100644 index 0000000..a2eea88 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/entity/vo/StcdVo.java @@ -0,0 +1,21 @@ +package com.yfd.platform.env.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; + +@Getter +@Setter +@Schema(description = "默认电站信息") +public class StcdVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "站码") + private String stcd; + + @Schema(description = "站名") + private String stnm; +} diff --git a/backend/src/main/java/com/yfd/platform/env/entity/vo/WtFishVo.java b/backend/src/main/java/com/yfd/platform/env/entity/vo/WtFishVo.java new file mode 100644 index 0000000..e068481 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/entity/vo/WtFishVo.java @@ -0,0 +1,21 @@ +package com.yfd.platform.env.entity.vo; + +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +@Data +public class WtFishVo { + + private Date dt; + + private BigDecimal wt; + + private BigDecimal beforeWt; + + private String hbrvcd; + + private List fishList; +} diff --git a/backend/src/main/java/com/yfd/platform/env/entity/vo/WtrvVo.java b/backend/src/main/java/com/yfd/platform/env/entity/vo/WtrvVo.java new file mode 100644 index 0000000..8e2d88e --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/entity/vo/WtrvVo.java @@ -0,0 +1,27 @@ +package com.yfd.platform.env.entity.vo; + +import lombok.Data; +import lombok.experimental.FieldNameConstants; + +import java.math.BigDecimal; +import java.util.Date; + +@Data +public class WtrvVo { + + private String stcd; + + private Date tm; + + private Boolean isIoWtrv; + + private Boolean hasRstcdWtvt; + + private BigDecimal wt; + + private BigDecimal avgwt; + + private BigDecimal minwt; + + private BigDecimal maxwt; +} diff --git a/backend/src/main/java/com/yfd/platform/env/mapper/AlongDetailMapper.java b/backend/src/main/java/com/yfd/platform/env/mapper/AlongDetailMapper.java index 2e997a2..16a3f3a 100644 --- a/backend/src/main/java/com/yfd/platform/env/mapper/AlongDetailMapper.java +++ b/backend/src/main/java/com/yfd/platform/env/mapper/AlongDetailMapper.java @@ -20,13 +20,20 @@ import java.util.Map; @Mapper public interface AlongDetailMapper extends BaseMapper { + @Select("SELECT wt.STCD AS stcd, wt.STNM AS stnm, wt.RSTCD AS rstcd, eng.ENNM AS ennm, " + + "CASE WHEN rel.ENG_IWT_CODE = wt.RSTCD THEN 1 WHEN rel.ENG_DWT_CODE = wt.RSTCD THEN 2 ELSE 3 END AS type, " + + "wt.STTP AS sttpCode " + + "FROM SD_WT_B_H wt " + + "LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.RSTCD " + + "LEFT JOIN SD_WTENGRLTN_B rel ON rel.STCD = wt.STCD AND rel.IS_DELETED = 0 " + + "WHERE wt.IS_DELETED = 0 AND wt.STTP = 'WTRV' AND wt.STCD = #{stcd}") WtrvInfo getWtrvInfoByStcd(@Param("stcd") String stcd); //电站数据 @Select("SELECT AVG(a.QI) AS qi, AVG(a.QO) AS qo, a.tm, AVG(a.RZ) AS rz, AVG(a.DZ) AS dz " + "FROM SD_HYDROPW_R a " + - "INNER JOIN MS_STBPRP_T b ON a.STCD = b.RSTCD " + - "WHERE b.IS_DELETED = 0 AND a.IS_DELETED = 0 " + - "AND b.STCD = #{stcd} AND a.TM BETWEEN #{startTime} AND #{endTime} " + + "WHERE a.IS_DELETED = 0 " + + "AND a.STCD = (SELECT RSTCD FROM SD_WT_B_H WHERE STCD = #{stcd} AND IS_DELETED = 0) " + + "AND a.TM BETWEEN #{startTime} AND #{endTime} " + "GROUP BY a.TM") List> getHydropwDataList(@Param("stcd") String stcd, @Param("startTime") Date startTime, @@ -34,7 +41,7 @@ public interface AlongDetailMapper extends BaseMapper { //天然水温 @Select("") String getAlongLatestTm(@Param("rvcd") String rvcd); @Select("") List getAlongListData(@Param("rvcd") String rvcd,@Param("baseId") String baseId,@Param("maxTime") Date maxTime); @Select("") Date getMaxTime(@Param("rvcd") String rvcd,@Param("baseId") String baseId,@Param("startTime") Date startTime,@Param("endTime") Date endTime); diff --git a/backend/src/main/java/com/yfd/platform/env/mapper/SdDzChuiXiangListMapper.java b/backend/src/main/java/com/yfd/platform/env/mapper/SdDzChuiXiangListMapper.java new file mode 100644 index 0000000..af0d535 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/mapper/SdDzChuiXiangListMapper.java @@ -0,0 +1,30 @@ +package com.yfd.platform.env.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.env.entity.vo.SdDzChuiXiangListVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * 电站专题垂向水温一级面板Mapper + * + * @author + * @since 2023-04-23 09:32:10 + */ +@Mapper +public interface SdDzChuiXiangListMapper extends BaseMapper { + + @Select("SELECT t1.WTHG, t1.VWT " + + "FROM SD_WTVTDRTP_S t1 " + + "WHERE t1.DRTP = 'MON' " + + "AND t1.MONTH = #{mon} " + + "AND t1.YEAR = #{year} " + + "AND t1.STCD = #{stcd} " + + "ORDER BY t1.WTHG ASC") + List getYearTempChange(@Param("stcd") String stcd, + @Param("mon") Integer mon, + @Param("year") String year); +} diff --git a/backend/src/main/java/com/yfd/platform/env/mapper/SdRvwtSInOutOneMapper.java b/backend/src/main/java/com/yfd/platform/env/mapper/SdRvwtSInOutOneMapper.java new file mode 100644 index 0000000..fb61d66 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/mapper/SdRvwtSInOutOneMapper.java @@ -0,0 +1,60 @@ +package com.yfd.platform.env.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.env.entity.vo.SdRvwtSVO; +import com.yfd.platform.env.entity.vo.StcdVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.Date; +import java.util.List; + +@Mapper +public interface SdRvwtSInOutOneMapper extends BaseMapper { + + @Select("SELECT STCD AS stcd, ENG_IWT_CODE AS engIwtCode, ENG_DWT_CODE AS engDwtCode " + + "FROM SD_PRWTRLTN_B " + + "WHERE IS_DELETED = 0 AND STCD = #{stcd}") + SdRvwtSVO getRelationByEngStcd(@Param("stcd") String stcd); + + @Select({ + "" + }) + List getDefaultStcd(@Param("baseIdList") List baseIdList, + @Param("rvcdList") List rvcdList, + @Param("startTime") Date startTime, + @Param("endTime") Date endTime); +} diff --git a/backend/src/main/java/com/yfd/platform/env/mapper/SdWtMonitorMapper.java b/backend/src/main/java/com/yfd/platform/env/mapper/SdWtMonitorMapper.java new file mode 100644 index 0000000..258a0f8 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/mapper/SdWtMonitorMapper.java @@ -0,0 +1,26 @@ +package com.yfd.platform.env.mapper; + +import com.yfd.platform.env.entity.vo.SdWtMonitorCountVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +@Mapper +public interface SdWtMonitorMapper { + + @Select("SELECT COUNT(1) AS cnt, 26 AS orderInx, '26' AS orderInxName, " + + " 'ENV,ENVM,WT,' AS sttpFullPath, NULL AS sttpCode, '表层水温监测' AS sttpName " + + "FROM SD_WT_B_H " + + "WHERE IS_DELETED = 0 AND STTP = 'WTRV' AND DTIN_TYPE = 0 " + + "UNION ALL " + + "SELECT COUNT(1) AS cnt, 27 AS orderInx, '27' AS orderInxName, " + + " 'ENV,ENVM,WT,' AS sttpFullPath, NULL AS sttpCode, '垂向水温监测' AS sttpName " + + "FROM SD_WT_B_H " + + "WHERE IS_DELETED = 0 AND STTP = 'WTVT' AND DTIN_TYPE = 0") + List getMonitorCountList(); + + @Select("SELECT WT_DEVICE_TYPE FROM SD_WT_B_H WHERE STCD = #{stcd} AND IS_DELETED = 0") + Integer getWtDeviceTypeByStcd(@Param("stcd") String stcd); +} diff --git a/backend/src/main/java/com/yfd/platform/env/mapper/SdWtvtRMapper.java b/backend/src/main/java/com/yfd/platform/env/mapper/SdWtvtRMapper.java new file mode 100644 index 0000000..9aaaad8 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/mapper/SdWtvtRMapper.java @@ -0,0 +1,31 @@ +package com.yfd.platform.env.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yfd.platform.env.entity.vo.SdWtvtYearVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +/** + * 垂向水温年份数据Mapper + * + * @author + * @since 2023-04-23 09:32:10 + */ +@Mapper +public interface SdWtvtRMapper extends BaseMapper { + + @Select("") + List getWtrvDefaultYear(@Param("stcd") String stcd); +} diff --git a/backend/src/main/java/com/yfd/platform/env/service/AlongListService.java b/backend/src/main/java/com/yfd/platform/env/service/AlongListService.java index 8cb241d..db1449f 100644 --- a/backend/src/main/java/com/yfd/platform/env/service/AlongListService.java +++ b/backend/src/main/java/com/yfd/platform/env/service/AlongListService.java @@ -3,6 +3,8 @@ package com.yfd.platform.env.service; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.env.entity.vo.SdYearListVO; +import com.yfd.platform.env.entity.vo.StcdVo; import org.springframework.web.bind.annotation.RequestBody; import java.util.Map; @@ -18,4 +20,7 @@ public interface AlongListService { Map getWtLimit(DataSourceRequest dataSourceRequest); DataSourceResult getDefaultRvcd(@RequestBody DataSourceRequest dataSourceRequest); DataSourceResult getALongKendoListCust(DataSourceRequest dataSourceRequest); -} \ No newline at end of file + DataSourceResult getMonthKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getYearDefaultStcd(DataSourceRequest dataSourceRequest); + DataSourceResult getYearList(DataSourceRequest dataSourceRequest); +} diff --git a/backend/src/main/java/com/yfd/platform/env/service/SdDzChuiXiangListService.java b/backend/src/main/java/com/yfd/platform/env/service/SdDzChuiXiangListService.java new file mode 100644 index 0000000..7da963e --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/service/SdDzChuiXiangListService.java @@ -0,0 +1,23 @@ +package com.yfd.platform.env.service; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; + +import java.util.Map; + +/** + * 电站专题垂向水温一级面板Service接口 + * + * @author + * @since 2023-04-23 09:32:10 + */ +public interface SdDzChuiXiangListService { + + /** + * 处理kendo列表数据 + * + * @param dataSourceRequest 数据源请求 + * @return 数据源结果 + */ + DataSourceResult processKendoList(DataSourceRequest dataSourceRequest); +} diff --git a/backend/src/main/java/com/yfd/platform/env/service/SdRvwtSInOutOneService.java b/backend/src/main/java/com/yfd/platform/env/service/SdRvwtSInOutOneService.java new file mode 100644 index 0000000..dad16f7 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/service/SdRvwtSInOutOneService.java @@ -0,0 +1,15 @@ +package com.yfd.platform.env.service; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.env.entity.vo.SdRvwtSVO; +import com.yfd.platform.env.entity.vo.StcdVo; + +public interface SdRvwtSInOutOneService { + + DataSourceResult processKendoList(DataSourceRequest dataSourceRequest); + + DataSourceResult getDetails(DataSourceRequest dataSourceRequest); + + DataSourceResult getDefaultStcd(DataSourceRequest dataSourceRequest); +} diff --git a/backend/src/main/java/com/yfd/platform/env/service/SdWtMonitorService.java b/backend/src/main/java/com/yfd/platform/env/service/SdWtMonitorService.java new file mode 100644 index 0000000..1f4001a --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/service/SdWtMonitorService.java @@ -0,0 +1,18 @@ +package com.yfd.platform.env.service; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.env.entity.vo.WtrvVo; + +public interface SdWtMonitorService { + + DataSourceResult getEvnmAutoMonitorList(); + + DataSourceResult getVmsstbprptList(DataSourceRequest dataSourceRequest); + + DataSourceResult getCxDetailList(DataSourceRequest dataSourceRequest); + + DataSourceResult getWtFishAnalysis(DataSourceRequest dataSourceRequest); + + WtrvVo getFlagByStcd(String stcd); +} diff --git a/backend/src/main/java/com/yfd/platform/env/service/SdWtvtRService.java b/backend/src/main/java/com/yfd/platform/env/service/SdWtvtRService.java new file mode 100644 index 0000000..4ad1f92 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/service/SdWtvtRService.java @@ -0,0 +1,21 @@ +package com.yfd.platform.env.service; + +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; + +/** + * 垂向水温Service接口 + * + * @author + * @since 2023-04-23 09:32:10 + */ +public interface SdWtvtRService { + + /** + * 获取垂向水温有数据的年份列表 + * + * @param dataSourceRequest 数据源请求 + * @return 数据源结果 + */ + DataSourceResult getWtrvDefaultYear(DataSourceRequest dataSourceRequest); +} diff --git a/backend/src/main/java/com/yfd/platform/env/service/impl/AlongDetailServiceImpl.java b/backend/src/main/java/com/yfd/platform/env/service/impl/AlongDetailServiceImpl.java index 3320d89..453c754 100644 --- a/backend/src/main/java/com/yfd/platform/env/service/impl/AlongDetailServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/env/service/impl/AlongDetailServiceImpl.java @@ -7,11 +7,13 @@ import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.yfd.platform.common.*; +import com.yfd.platform.common.exception.BizException; import com.yfd.platform.env.entity.vo.*; import com.yfd.platform.env.mapper.AlongDetailMapper; import com.yfd.platform.env.mapper.SdWtrvdrtpSMapper; import com.yfd.platform.env.service.AlongDetailService; import com.yfd.platform.utils.CollectionExtUtils; +import com.yfd.platform.utils.QgcQueryWrapperUtil; import com.yfd.platform.utils.SecurityUtils; import jakarta.annotation.Resource; import org.springframework.jdbc.core.JdbcTemplate; @@ -33,6 +35,8 @@ public class AlongDetailServiceImpl extends ServiceImpl filterResult, Page page) { DataSourceResult dataSourceResult = new DataSourceResult(); - StringBuilder sql = new StringBuilder("SELECT t.tm,t.mon, t.stcd, t.wt, t.stnm, t.basename,t.mway,t.rstcd\n" + - "FROM (SELECT DISTINCT r.tm,to_char(r.tm,'MM') mon, r.stcd, r.WT,r.TASK_ID,r.TASK_STATUS ,t2.stnm,t2.BASE_Id AS baseId, t2.BASE_NAME baseName,t2.MWAY AS mway, t2.rstcd\n" + - " FROM SD_WTRV_R r\n" + - //" inner join MS_ALONGDET_B b on r.stcd=b.stcd and b.is_deleted=0 inner join MS_ALONG_B a on a.ID=b.ALONG_ID and a.code='common' " + - " LEFT JOIN MS_STBPRP_T t2 ON r.STCD = t2.STCD \n" + - " WHERE r.is_deleted=0 and t2.is_deleted=0 " + - " order by r.tm DESC, r.stcd) t where 1=1 "); - - sql. append(" AND (TASK_ID IS NULL OR TASK_ID ='' OR TASK_STATUS ='Approved') "); - if (ObjectUtil.isNotEmpty(filterResult.get(CommonConstant.DEFAULT))) { - if (StrUtil.isNotBlank(filterResult.get(CommonConstant.DEFAULT).getGroupSql())) { - sql.append(" and ").append(filterResult.get(CommonConstant.DEFAULT).getGroupSql()); - } - - if (StrUtil.isNotBlank(filterResult.get(CommonConstant.DEFAULT).getOrderBySql())) { - sql.append(" ").append(filterResult.get(CommonConstant.DEFAULT).getOrderBySql()); + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + String stcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd"); + String tm = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "tm"); + if (StrUtil.isBlank(tm)) { + throw new BizException("时间(tm)不能为空."); + } + Date startTime = null; + Date endTime = null; + String[] tmArr = tm.split(","); + if (tmArr.length == 2) { + Date first = DateUtil.parse(tmArr[0].trim()); + Date second = DateUtil.parse(tmArr[1].trim()); + if (first.after(second)) { + startTime = second; + endTime = first; + } else { + startTime = first; + endTime = second; } } - Map map = new HashMap(); - Iterator iterator = filterResult.keySet().iterator(); - while (iterator.hasNext()) { - String key = (String) iterator.next(); - map.putAll(filterResult.get(key).getParamMap()); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT t.tm, t.mon, t.stcd, t.wt, t.stnm, t.baseName ") + .append("FROM (") + .append(" SELECT DISTINCT r.tm, TO_NUMBER(TO_CHAR(r.tm,'MM')) mon, r.stcd, r.wt, ") + .append(" wt.stnm, hb.basename AS baseName, wt.mway, wt.rstcd ") + .append(" FROM SD_WTRV_R r ") + .append(" LEFT JOIN SD_WT_B_H wt ON r.STCD = wt.STCD ") + .append(" LEFT JOIN SD_ENGINFO_B_H eng ON wt.RSTCD = eng.STCD ") + .append(" LEFT JOIN SD_HYDROBASE hb ON eng.BASE_ID = hb.BASEID ") + .append(" WHERE r.IS_DELETED = 0 ") + .append(" AND wt.IS_DELETED = 0 ") + .append(" AND wt.STTP = 'WTRV' ") + .append(" AND r.TM BETWEEN #{map.startTime} AND #{map.endTime} "); + if (StrUtil.isNotBlank(stcd)) { + sql.append(" AND r.STCD = #{map.stcd} "); } - List list = this.dynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), map, SdAlongDetailVO.class); + sql.append(") t WHERE 1=1 "); + if (dataSourceRequest.getSort() != null && !dataSourceRequest.getSort().isEmpty()) { + DataSourceRequest.SortDescriptor sortDescriptor = dataSourceRequest.getSort().get(0); + String orderField = "tm"; + if ("stcd".equalsIgnoreCase(sortDescriptor.getField())) { + orderField = "stcd"; + } else if ("stnm".equalsIgnoreCase(sortDescriptor.getField())) { + orderField = "stnm"; + } else if ("wt".equalsIgnoreCase(sortDescriptor.getField())) { + orderField = "wt"; + } + String orderDir = "desc".equalsIgnoreCase(sortDescriptor.getDir()) ? "DESC" : "ASC"; + sql.append(" ORDER BY t.").append(orderField).append(" ").append(orderDir); + } else { + sql.append(" ORDER BY t.tm ASC "); + } + + Map map = new HashMap<>(); + map.put("startTime", startTime); + map.put("endTime", endTime); + if (StrUtil.isNotBlank(stcd)) { + map.put("stcd", stcd); + } + PageInfo pageInfo = QgcQueryWrapperUtil.getPageInfo(loadOptions); + Page currentPage = pageInfo.getHasPageInfo() ? pageInfo.getPage() : page; + List list = this.microservicDynamicSQLMapper.pageAllListWithResultType(currentPage, sql.toString(), map, SdAlongDetailVO.class); dataSourceResult.setData(list); - dataSourceResult.setTotal(ObjectUtil.isNotEmpty(page) ? page.getTotal() : (long) list.size()); + dataSourceResult.setTotal(ObjectUtil.isNotEmpty(currentPage) ? currentPage.getTotal() : (long) list.size()); return dataSourceResult; } @@ -142,7 +183,7 @@ public class AlongDetailServiceImpl extends ServiceImpl> list = (List>) dataSourceResult.getData(); + List list = (List) dataSourceResult.getData(); if (list == null || list.isEmpty()) { dr.setData(new ArrayList<>()); @@ -150,8 +191,8 @@ public class AlongDetailServiceImpl extends ServiceImpl 0) { Date tmpDate = startTime; @@ -162,7 +203,7 @@ public class AlongDetailServiceImpl extends ServiceImpl> iwtDataVoList = new ArrayList<>(); List> dwtDataVoList = new ArrayList<>(); List> wtvtDataVoList = new ArrayList<>(); - List> hydropwDataVoList = new ArrayList<>(); +// List> hydropwDataVoList = new ArrayList<>(); List> pptnDataVoList = new ArrayList<>(); List> tmpDataVoList = new ArrayList<>(); List> wtnpDataVoList; @@ -187,17 +228,17 @@ public class AlongDetailServiceImpl extends ServiceImpl> dwtDataMap = dwtDataVoList.stream() .collect(Collectors.toMap(it -> (Date) it.get("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(this.alongDetailMapper.getHydropwDataList(wtrvInfo.getStcd(), startTime, endTime)); +// Map> hydropwDataMap = hydropwDataVoList.stream() +// .collect(Collectors.toMap(it -> (Date) it.get("tm"), Function.identity())); - pptnDataVoList.addAll(this.alongDetailMapper.getPptnDataList(wtrvInfo.getStcd(), startTime, endTime)); - Map> pptnDataMap = pptnDataVoList.stream() - .collect(Collectors.toMap(it -> (Date) it.get("tm"), Function.identity())); +// pptnDataVoList.addAll(this.alongDetailMapper.getPptnDataList(wtrvInfo.getStcd(), startTime, endTime)); +// Map> pptnDataMap = pptnDataVoList.stream() +// .collect(Collectors.toMap(it -> (Date) it.get("tm"), Function.identity())); - tmpDataVoList.addAll(this.alongDetailMapper.getTmpDataList(wtrvInfo.getStcd(), startTime, endTime)); - Map> tmpDataMap = tmpDataVoList.stream() - .collect(Collectors.toMap(it -> (Date) it.get("tm"), Function.identity())); +// tmpDataVoList.addAll(this.alongDetailMapper.getTmpDataList(wtrvInfo.getStcd(), startTime, endTime)); +// Map> tmpDataMap = tmpDataVoList.stream() +// .collect(Collectors.toMap(it -> (Date) it.get("tm"), Function.identity())); Map wtnpDataMap = new HashMap<>(); if (StrUtil.isNotBlank(wtrvInfo.getRstcd())) { @@ -213,42 +254,42 @@ public class AlongDetailServiceImpl extends ServiceImpl> qgcWtrvDataVoList = new ArrayList<>(); list.forEach(it -> { Map vo = new HashMap<>(); - vo.put("stcd", it.get("stcd")); - vo.put("stnm", it.get("stnm")); - vo.put("wt", it.get("wt")); - vo.put("tm", it.get("tm")); + vo.put("stcd", it.getStcd()); + vo.put("stnm", it.getStnm()); + vo.put("wt", it.getWt()); + vo.put("tm", it.getTm()); vo.put("ennm", wtrvInfo.getEnnm()); vo.put("rstcd", wtrvInfo.getRstcd()); vo.put("type", wtrvInfo.getType()); - vo.put("natureTmp", wtnpDataMap.get(it.get("mon"))); - vo.put("hydropwDataVo", hydropwDataMap.get(it.get("tm"))); - vo.put("pptnDataVo", pptnDataMap.get(it.get("tm"))); - vo.put("tmpDataVo", tmpDataMap.get(it.get("tm"))); + vo.put("natureTmp", wtnpDataMap.get(it.getMon())); +// vo.put("hydropwDataVo", hydropwDataMap.get(it.getTm())); +// vo.put("pptnDataVo", pptnDataMap.get(it.getTm())); +// vo.put("tmpDataVo", tmpDataMap.get(it.getTm())); if (wtrvInfo.getType() == 1) { Map iwtVo = new HashMap<>(); - iwtVo.put("tm", it.get("tm")); - iwtVo.put("wt", it.get("wt")); + iwtVo.put("tm", it.getTm()); + iwtVo.put("wt", it.getWt()); vo.put("iwtDataVo", iwtVo); - vo.put("dwtDataVo", dwtDataMap.get(it.get("tm"))); + vo.put("dwtDataVo", dwtDataMap.get(it.getTm())); } if (wtrvInfo.getType() == 2) { Map dwtVo = new HashMap<>(); - dwtVo.put("tm", it.get("tm")); - dwtVo.put("wt", it.get("wt")); + dwtVo.put("tm", it.getTm()); + dwtVo.put("wt", it.getWt()); vo.put("dwtDataVo", dwtVo); - vo.put("iwtDataVo", iwtDataMap.get(it.get("tm"))); + vo.put("iwtDataVo", iwtDataMap.get(it.getTm())); - if (it.get("wt") != null && wtvtDataVoMap != null) { - List> vtList = wtvtDataVoMap.get(it.get("tm")); + if (it.getWt() != null && wtvtDataVoMap != null) { + List> 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"))); - if (vtMap.containsKey(it.get("wt"))) { - vo.put("wtvtDataVo", vtMap.get(it.get("wt")).get(0)); + if (vtMap.containsKey(it.getWt())) { + vo.put("wtvtDataVo", vtMap.get(it.getWt()).get(0)); qgcWtrvDataVoList.add(vo); return; } @@ -262,7 +303,7 @@ public class AlongDetailServiceImpl extends ServiceImpl> resultList = dynamicSQLMapper.getAllList(sql, null); - if(!CollectionUtils.isEmpty(resultList)){ + List> resultList = dynamicSQLMapper.getAllList(sql, null); + if(!CollectionUtils.isEmpty(resultList)){ return resultList.get(0); - } + } return null; } @@ -62,8 +69,8 @@ public class AlongListServiceImpl extends ServiceImpl= #{tm} AND TM <= #{tm_1} AND WT IS NOT NULL ) t3 " + "\tON t1.STCD = t3.STCD ORDER BY SORT ASC " + @@ -76,7 +83,7 @@ public class AlongListServiceImpl extends ServiceImpl(); + List filters = new ArrayList<>(); + collectFilters(dataSourceRequest.getFilter(), filters); + + String rvcd = null; + String baseId = null; + Object startTime = null; + Object endTime = null; + Integer year = null; + Integer month = null; + for (DataSourceRequest.FilterDescriptor filter : filters) { + if ("rvcd".equals(filter.getField())) { + rvcd = toStringValue(filter.getValue()); + } else if ("baseId".equals(filter.getField())) { + baseId = toStringValue(filter.getValue()); + } else if ("year".equals(filter.getField())) { + year = toIntegerValue(filter.getValue()); + } else if ("month".equals(filter.getField())) { + month = toIntegerValue(filter.getValue()); + } else if ("tm".equals(filter.getField()) && "gte".equalsIgnoreCase(filter.getOperator())) { + startTime = filter.getValue(); + } else if ("tm".equals(filter.getField()) && "lte".equalsIgnoreCase(filter.getOperator())) { + endTime = filter.getValue(); + } + } + + if (year == null || month == null) { + dataSourceResult.setData(new ArrayList<>()); + dataSourceResult.setTotal(0L); + return dataSourceResult; + } + + int beforeYear = year - 1; + StringBuilder sql = new StringBuilder(); + sql.append("SELECT t1.stcd, t1.rstcd, t1.sttp, t1.temperature, t1.tm, t1.stnm, t1.engDwtCode, ") + .append("W.WT AS actualTemp, M.WT AS lastTemp, R.WT AS naturalTemp ") + .append("FROM (") + .append("SELECT t.stcd, t.rstcd, t.rvcd, t.sttp, t.temperature, t.tm, t.rvcdSort, t.sort, t.stnm, t.engDwtCode, ") + .append("RANK() OVER (PARTITION BY t.stcd ORDER BY t.tm DESC NULLS LAST) AS rank ") + .append("FROM (") + .append("SELECT SARC.STCD AS stcd, ") + .append("SARC.RSTCD AS rstcd, ") + .append("MAB.RVCD AS rvcd, ") + .append("MAB.ORDER_INDEX AS rvcdSort, ") + .append("SARC.SORT AS sort, ") + .append("CASE WHEN SARC.STTP = 'ENG' THEN '1' WHEN SARC.STTP = 'WTRV' THEN '2' END AS sttp, ") + .append("SWR.WT AS temperature, ") + .append("SWR.TM AS tm, ") + .append("CASE WHEN SARC.STTP = 'ENG' THEN ENG.ENNM ELSE WT.STNM END AS stnm, ") + .append("REL.ENG_DWT_CODE AS engDwtCode ") + .append("FROM MS_ALONG_B MAB ") + .append("INNER JOIN MS_ALONGDET_B SARC ON MAB.ID = SARC.ALONG_ID ") + .append("LEFT JOIN SD_ENGINFO_B_H ENG ON ENG.STCD = SARC.STCD ") + .append("LEFT JOIN SD_WT_B_H WT ON WT.STCD = SARC.STCD AND WT.IS_DELETED = 0 AND WT.STTP = 'WTRV' ") + .append("LEFT JOIN SD_WTENGRLTN_B REL ON REL.STCD = SARC.STCD AND REL.IS_DELETED = 0 ") + .append("LEFT JOIN SD_WTRV_R SWR ON SWR.STCD = SARC.STCD AND SWR.IS_DELETED = 0 "); + if (startTime != null) { + sql.append("AND SWR.TM >= TO_DATE(#{map.startTime}, 'YYYY-MM-DD HH24:MI:SS') "); + } + if (endTime != null) { + sql.append("AND SWR.TM <= TO_DATE(#{map.endTime}, 'YYYY-MM-DD HH24:MI:SS') "); + } + sql.append("WHERE MAB.CODE = 'common' ") + .append("AND MAB.IS_DELETED = 0 ") + .append("AND SARC.IS_DELETED = 0 ") + .append("AND (SARC.STTP = 'ENG' OR (SARC.STTP = 'WTRV' AND REL.ENG_DWT_CODE IS NOT NULL)) "); + if (StrUtil.isNotBlank(rvcd)) { + sql.append("AND MAB.RVCD = #{map.rvcd} "); + } + if (StrUtil.isNotBlank(baseId)) { + sql.append("AND MAB.RVCD IN (SELECT HBRVCD FROM SD_HBRV_DIC WHERE IS_DELETED = 0 AND ENABLED = 1 AND BASEID = #{map.baseId}) "); + } + sql.append(") t ") + .append(") t1 ") + .append("LEFT JOIN (") + .append("SELECT s.STCD, s.WT ") + .append("FROM SD_WTRVDRTP_S s ") + .append("INNER JOIN SD_WT_B_H wtMon ON wtMon.STCD = s.STCD AND wtMon.IS_DELETED = 0 AND wtMon.STTP = 'WTRV' AND wtMon.USFL = 1 AND wtMon.MWAY = 2 ") + .append("WHERE s.IS_DELETED = 0 AND s.DRTP = 'MON' AND s.YEAR = #{map.year} AND s.MONTH = #{map.month}") + .append(") W ON t1.STCD = W.STCD ") + .append("LEFT JOIN (") + .append("SELECT s.STCD, s.WT ") + .append("FROM SD_WTRVDRTP_S s ") + .append("INNER JOIN SD_WT_B_H wtMon ON wtMon.STCD = s.STCD AND wtMon.IS_DELETED = 0 AND wtMon.STTP = 'WTRV' AND wtMon.USFL = 1 AND wtMon.MWAY = 2 ") + .append("WHERE s.IS_DELETED = 0 AND s.DRTP = 'MON' AND s.YEAR = #{map.beforeYear} AND s.MONTH = #{map.month}") + .append(") M ON t1.STCD = M.STCD ") + .append("LEFT JOIN (") + .append("SELECT STCD, WT FROM SD_WTNP_B WHERE IS_DELETED = 0 AND WTTP = 1 AND MNTH = #{map.month}") + .append(") R ON t1.STCD = R.STCD ") + .append("WHERE t1.rank = 1 ") + .append("ORDER BY t1.rvcdSort ASC, t1.sort ASC"); + + Map paramMap = new HashMap<>(); + paramMap.put("rvcd", rvcd); + paramMap.put("baseId", baseId); + paramMap.put("startTime", startTime); + paramMap.put("endTime", endTime); + paramMap.put("year", year); + paramMap.put("beforeYear", beforeYear); + paramMap.put("month", month); + + Page page = buildPage(dataSourceRequest.toDevRequest()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, SdAlongVO.class); + List resultList = rebuildMonthList(list); + dataSourceResult.setData(resultList); + dataSourceResult.setTotal(page != null ? page.getTotal() : (long) resultList.size()); + return dataSourceResult; + } + + @Override + public DataSourceResult getYearDefaultStcd(DataSourceRequest dataSourceRequest) { + DataSourceResult dataSourceResult = new DataSourceResult<>(); + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + String year = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "year"); + String baseId = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId"); + + if (StrUtil.isBlank(year)) { + dataSourceResult.setData(new ArrayList<>()); + dataSourceResult.setTotal(0L); + return dataSourceResult; + } + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT t1.STCD AS stcd, t1.STNM AS stnm ") + .append("FROM (") + .append(" SELECT wt.STCD, wt.STNM ") + .append(" FROM SD_WT_B_H wt ") + .append(" LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.RSTCD ") + .append(" WHERE wt.STTP = 'WTRV' ") + .append(" AND wt.USFL = 1 ") + .append(" AND wt.IS_DELETED = 0 "); + if (StrUtil.isNotBlank(baseId)) { + sql.append(" AND eng.BASE_ID = #{map.baseId} "); + } + sql.append(") t1 ") + .append("INNER JOIN (") + .append(" SELECT DISTINCT STCD ") + .append(" FROM SD_WTRVDRTP_S ") + .append(" WHERE IS_DELETED = 0 ") + .append(" AND YEAR = #{map.year} ") + .append(" AND DRTP = 'MON' ") + .append(") t2 ON t1.STCD = t2.STCD ") + .append("WHERE ROWNUM = 1"); + + Map paramMap = new HashMap<>(); + paramMap.put("year", year); + paramMap.put("baseId", baseId); + List resultList = microservicDynamicSQLMapper.pageAllListWithResultType(null, sql.toString(), paramMap, StcdVo.class); + dataSourceResult.setData(resultList); + dataSourceResult.setTotal(resultList.size()); + return dataSourceResult; + } + + @Override + public DataSourceResult getYearList(DataSourceRequest dataSourceRequest) { + DataSourceResult dataSourceResult = new DataSourceResult<>(); + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + String stcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd"); + String year = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "year"); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT t.stcd AS stcd, t.rstcd AS rstcd, t.stnm AS stnm, t.YEAR AS year, t.MONTH AS month, ") + .append("t.actualTemp AS actualTemp, t.naturalTemp AS naturalTemp, t.drtp AS drtp ") + .append("FROM (") + .append(" SELECT t1.stcd, t1.rstcd, t1.stnm, t1.YEAR, t1.MONTH, t1.WT AS actualTemp, t2.WT AS naturalTemp, t1.drtp ") + .append(" FROM (") + .append(" SELECT sms.STCD, wt.RSTCD, wt.STNM, sms.YEAR, sms.MONTH, sms.WT, sms.DRTP ") + .append(" FROM SD_WTRVDRTP_S sms ") + .append(" LEFT JOIN SD_WT_B_H wt ON wt.STCD = sms.STCD ") + .append(" AND wt.STTP = 'WTRV' AND wt.USFL = 1 AND wt.IS_DELETED = 0 ") + .append(" WHERE sms.IS_DELETED = 0 ") + .append(" ) t1 ") + .append(" LEFT JOIN (SELECT STCD, WT, MNTH FROM SD_WTNP_B WHERE IS_DELETED = 0) t2 ") + .append(" ON t2.STCD = t1.RSTCD AND t2.MNTH = t1.MONTH ") + .append(") t ") + .append("WHERE t.DRTP = 'MON' "); + if (StrUtil.isNotBlank(stcd)) { + sql.append("AND t.STCD = #{map.stcd} "); + } + if (StrUtil.isNotBlank(year)) { + sql.append("AND t.YEAR = #{map.year} "); + } + + Map paramMap = new HashMap<>(); + paramMap.put("stcd", stcd); + paramMap.put("year", year); + Page page = buildPage(loadOptions); + List voList = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, SdYearListVO.class); + for (SdYearListVO vo : voList) { + if (StrUtil.isNotBlank(vo.getMonth())) { + vo.setMonthInt(Integer.parseInt(vo.getMonth())); + vo.setMonth(vo.getMonth() + "月"); + } + } + List resultList = voList.stream() + .sorted(Comparator.comparing(SdYearListVO::getMonthInt, Comparator.nullsLast(Comparator.naturalOrder()))) + .collect(Collectors.toList()); + dataSourceResult.setData(resultList); + dataSourceResult.setTotal(page != null ? page.getTotal() : (long) voList.size()); + return dataSourceResult; + } + + private Page buildPage(DataSourceLoadOptionsBase loadOptions) { + PageInfo pageInfo = QgcQueryWrapperUtil.getPageInfo(loadOptions); + if (Boolean.TRUE.equals(pageInfo.getHasPageInfo())) { + return pageInfo.getPage(); + } + return null; + } + + + + + private void collectFilters(DataSourceRequest.FilterDescriptor filter, List result) { + if (filter == null) { + return; + } + if (filter.getFilters() == null || filter.getFilters().isEmpty()) { + if (StrUtil.isNotBlank(filter.getField())) { + result.add(filter); + } + return; + } + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + collectFilters(child, result); + } + } + + private String toStringValue(Object value) { + return value == null ? null : String.valueOf(value); + } + + private Integer toIntegerValue(Object value) { + if (value == null || StrUtil.isBlank(String.valueOf(value))) { + return null; + } + return Integer.parseInt(String.valueOf(value)); + } + + private List rebuildMonthList(List list) { + if (CollectionUtils.isEmpty(list)) { + return new ArrayList<>(); + } + List sttpList = list.stream().map(SdAlongVO::getSttp).collect(Collectors.toList()); + int firstEnvIndex = sttpList.indexOf(SdAlongVO.TYPE_ENV); + if (firstEnvIndex == -1) { + return new ArrayList<>(); + } + if (firstEnvIndex - 1 >= 0) { + list = new ArrayList<>(list.subList(firstEnvIndex - 1, list.size())); + sttpList = new ArrayList<>(sttpList.subList(firstEnvIndex - 1, sttpList.size())); + } + int lastEnvIndex = sttpList.lastIndexOf(SdAlongVO.TYPE_ENV); + if (lastEnvIndex != -1 && lastEnvIndex + 2 <= list.size()) { + list = new ArrayList<>(list.subList(0, lastEnvIndex + 2)); + } + + Set rstcdSet = list.stream() + .filter(sdAlongVO -> SdAlongVO.TYPE_ENV.equals(sdAlongVO.getSttp())) + .map(SdAlongVO::getRstcd) + .collect(Collectors.toSet()); + list = list.stream() + .filter(sdAlongVO -> SdAlongVO.TYPE_ENV.equals(sdAlongVO.getSttp()) || rstcdSet.contains(sdAlongVO.getStcd())) + .collect(Collectors.toList()); + + SdAlongVO maxTmVo = list.stream() + .filter(sdAlongVO -> StringUtils.isNotBlank(sdAlongVO.getTm())) + .max(Comparator.comparing(SdAlongVO::getTm)) + .orElse(null); + if (!CollectionUtils.isEmpty(list)) { + list.get(0).setMinTm(maxTmVo == null ? null : maxTmVo.getTm()); + } + + List engList = new ArrayList<>(); + List wtList = new ArrayList<>(); + for (SdAlongVO item : list) { + if (StringUtils.equals(SdAlongVO.TYPE_ENG, item.getSttp())) { + engList.add(item); + } else if (StringUtils.equals(SdAlongVO.TYPE_ENV, item.getSttp())) { + wtList.add(item); + } + } + + List result = new ArrayList<>(); + for (SdAlongVO engVo : engList) { + result.add(engVo); + for (SdAlongVO wtVo : wtList) { + if (StringUtils.equals(engVo.getStcd(), wtVo.getEngDwtCode())) { + result.add(wtVo); + } + } + } + return result; + } + +} diff --git a/backend/src/main/java/com/yfd/platform/env/service/impl/SdDzChuiXiangListServiceImpl.java b/backend/src/main/java/com/yfd/platform/env/service/impl/SdDzChuiXiangListServiceImpl.java new file mode 100644 index 0000000..25d931a --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/service/impl/SdDzChuiXiangListServiceImpl.java @@ -0,0 +1,49 @@ +package com.yfd.platform.env.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.common.DataSourceLoadOptionsBase; +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.env.entity.vo.SdDzChuiXiangListVO; +import com.yfd.platform.env.mapper.SdDzChuiXiangListMapper; +import com.yfd.platform.env.service.SdDzChuiXiangListService; +import com.yfd.platform.utils.QgcQueryWrapperUtil; +import com.yfd.platform.utils.QueryWrapperUtil; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * 电站专题垂向水温一级面板Service实现类 + * + * @author + * @since 2023-04-23 09:32:10 + */ +@Service +public class SdDzChuiXiangListServiceImpl extends ServiceImpl implements SdDzChuiXiangListService { + + @Resource + private SdDzChuiXiangListMapper sdDzChuiXiangListMapper; + + @Override + public DataSourceResult processKendoList(DataSourceRequest dataSourceRequest) { + DataSourceResult dataSourceResult = new DataSourceResult<>(); + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + String stcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd"); + String year = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "year"); + + int m = 12; + Map> map = new LinkedHashMap<>(); + for (int i = 1; i <= m; i++) { + List list = sdDzChuiXiangListMapper.getYearTempChange(stcd, i, year); + map.put(String.valueOf(i), list != null ? list : List.of()); + } + dataSourceResult.setData(null); + dataSourceResult.setTotal(map.size()); + dataSourceResult.setAggregates(map); + return dataSourceResult; + } +} diff --git a/backend/src/main/java/com/yfd/platform/env/service/impl/SdRvwtSInOutOneServiceImpl.java b/backend/src/main/java/com/yfd/platform/env/service/impl/SdRvwtSInOutOneServiceImpl.java new file mode 100644 index 0000000..9d1d37e --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/service/impl/SdRvwtSInOutOneServiceImpl.java @@ -0,0 +1,354 @@ +package com.yfd.platform.env.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.common.*; +import com.yfd.platform.env.entity.vo.SdRvwtSVO; +import com.yfd.platform.env.entity.vo.StcdVo; +import com.yfd.platform.env.mapper.SdRvwtSInOutOneMapper; +import com.yfd.platform.env.service.SdRvwtSInOutOneService; +import com.yfd.platform.utils.QgcQueryWrapperUtil; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@Service +public class SdRvwtSInOutOneServiceImpl extends ServiceImpl implements SdRvwtSInOutOneService { + + private static final String TYPE_IWT = "IWT"; + + private static final String TYPE_DWT = "DWT"; + + @Resource + private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; + + @Resource + private SdRvwtSInOutOneMapper sdRvwtSInOutOneMapper; + + @Override + public DataSourceResult processKendoList(DataSourceRequest dataSourceRequest) { + return doProcessKendoList(dataSourceRequest, null, null); + } + + @Override + public DataSourceResult getDetails(DataSourceRequest dataSourceRequest) { + DataSourceResult dwtResult = doProcessKendoList(dataSourceRequest, true, TYPE_DWT); + DataSourceResult iwtResult = doProcessKendoList(dataSourceRequest, true, TYPE_IWT); + + List dList = dwtResult.getData() == null ? new ArrayList<>() : dwtResult.getData(); + List iList = iwtResult.getData() == null ? new ArrayList<>() : iwtResult.getData(); + + LinkedHashMap resultMap = new LinkedHashMap<>(); + String sortField = getPrimarySortField(dataSourceRequest.getSort()); + if ("dwtValue".equals(sortField)) { + mergeDetailList(resultMap, dList, TYPE_DWT); + mergeDetailList(resultMap, iList, TYPE_IWT); + } else { + mergeDetailList(resultMap, iList, TYPE_IWT); + mergeDetailList(resultMap, dList, TYPE_DWT); + } + + List resultList = new ArrayList<>(resultMap.values()); + DataSourceResult result = new DataSourceResult<>(); + result.setData(resultList); + long total = dwtResult.getTotal() != 0 ? dwtResult.getTotal() + : (iwtResult.getTotal() != 0 ? iwtResult.getTotal() : resultList.size()); + result.setTotal(total); + return result; + } + + @Override + public DataSourceResult getDefaultStcd(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + Date[] timeRange = parseTimeRange(QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "dt")); + List baseIdList = splitFilterValues(QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId")); + List rvcdList = splitFilterValues(QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rvcd")); + + List resultList = sdRvwtSInOutOneMapper.getDefaultStcd( + baseIdList, + rvcdList, + timeRange[0], + timeRange[1] + ); + DataSourceResult result = new DataSourceResult<>(); + result.setData(resultList); + result.setTotal(resultList.size()); + return result; + } + + private DataSourceResult doProcessKendoList(DataSourceRequest dataSourceRequest, + Boolean forceDetail, + String forceType) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + String engStcd = normalizeFilterValue(QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd")); + String engIwtCode = normalizeFilterValue(QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "engIwtCode")); + String engDwtCode = normalizeFilterValue(QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "engDwtCode")); + if (StrUtil.isBlank(engIwtCode) && StrUtil.isNotBlank(engStcd)) { + engIwtCode = engStcd; + } + if (StrUtil.isBlank(engDwtCode) && StrUtil.isNotBlank(engStcd)) { + engDwtCode = engStcd; + } + String url = normalizeFilterValue(QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "url")); + boolean isDetail = forceDetail != null ? forceDetail : "details".equals(url); + + String tableName = isDetail ? "SD_WTRV_R" : "SD_WTRVDAY_S"; + String timeColumn = isDetail ? "SWS.TM" : "SWS.DT"; + Date[] timeRange = parseTimeRange(resolveTimeFilterValue(loadOptions)); + List baseIdList = splitFilterValues(QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "baseId")); + List rvcdList = splitFilterValues(QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rvcd")); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT SWT.STCD AS stcd, ") + .append("SWT.STNM AS stnm, ") + .append(timeColumn).append(" AS tm, ") + .append(timeColumn).append(" AS dt, ") + .append("SWS.WT AS wt, ") + .append("REL.ENG_IWT_CODE AS engIwtCode, ") + .append("REL.ENG_DWT_CODE AS engDwtCode ") + .append("FROM SD_WT_B_H SWT ") + .append("INNER JOIN ").append(tableName).append(" SWS ON SWS.STCD = SWT.STCD ") + .append("INNER JOIN SD_WTENGRLTN_B REL ON REL.STCD = SWT.STCD ") + .append("INNER JOIN SD_ENGINFO_B_H SEG ON SEG.STCD = SWT.RSTCD ") + .append("WHERE SWS.IS_DELETED = 0 ") + .append("AND SWT.IS_DELETED = 0 ") + .append("AND REL.IS_DELETED = 0 ") + .append("AND SWT.USFL = 1 ") + .append("AND SWT.MWAY = 2 ") + .append("AND SWT.STTP = 'WTRV' ") + .append("AND SEG.USFL = 1 "); + + Map paramMap = new HashMap<>(); + if (timeRange[0] != null && timeRange[1] != null) { + paramMap.put("startTime", timeRange[0]); + paramMap.put("endTime", timeRange[1]); + sql.append("AND ").append(timeColumn).append(" >= #{map.startTime} ") + .append("AND ").append(timeColumn).append(" <= #{map.endTime} "); + } + + if (isDetail) { + appendDetailCondition(sql, paramMap, forceType, engIwtCode, engDwtCode); + } else { + if (StrUtil.isNotBlank(engIwtCode) && StrUtil.isNotBlank(engDwtCode)) { + paramMap.put("engIwtCode", engIwtCode); + paramMap.put("engDwtCode", engDwtCode); + sql.append("AND ((REL.ENG_IWT_CODE = #{map.engIwtCode}) OR (REL.ENG_DWT_CODE = #{map.engDwtCode})) "); + } else if (StrUtil.isNotBlank(engIwtCode)) { + paramMap.put("engIwtCode", engIwtCode); + sql.append("AND REL.ENG_IWT_CODE = #{map.engIwtCode} "); + } else if (StrUtil.isNotBlank(engDwtCode)) { + paramMap.put("engDwtCode", engDwtCode); + sql.append("AND REL.ENG_DWT_CODE = #{map.engDwtCode} "); + } + appendInCondition(sql, paramMap, "SEG.BASE_ID", "baseId", baseIdList); + appendInCondition(sql, paramMap, "SEG.RVCD", "rvcd", rvcdList); + } + + sql.append(buildOrderBySql(dataSourceRequest.getSort(), timeColumn)); + Page page = buildPage(loadOptions); + List resultList = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, SdRvwtSVO.class); + + if (!isDetail) { + fillDwtp(resultList, engIwtCode, engDwtCode); + } + + DataSourceResult result = new DataSourceResult<>(); + result.setData(resultList); + result.setTotal(ObjectUtil.isNotEmpty(page) ? page.getTotal() : resultList.size()); + return result; + } + + private void appendDetailCondition(StringBuilder sql, + Map paramMap, + String forceType, + String engIwtCode, + String engDwtCode) { + if (TYPE_IWT.equals(forceType)) { + sql.append("AND SWT.WT_TYPE = 'IWT' "); + if (StrUtil.isNotBlank(engIwtCode)) { + paramMap.put("detailEngIwtCode", engIwtCode); + sql.append("AND REL.ENG_IWT_CODE = #{map.detailEngIwtCode} "); + } + } else if (TYPE_DWT.equals(forceType)) { + sql.append("AND SWT.WT_TYPE = 'DWT' "); + if (StrUtil.isNotBlank(engDwtCode)) { + paramMap.put("detailEngDwtCode", engDwtCode); + sql.append("AND REL.ENG_DWT_CODE = #{map.detailEngDwtCode} "); + } + } else if (StrUtil.isNotBlank(engDwtCode)) { + paramMap.put("detailEngDwtCode", engDwtCode); + sql.append("AND SWT.WT_TYPE = 'DWT' ") + .append("AND REL.ENG_DWT_CODE = #{map.detailEngDwtCode} "); + } else if (StrUtil.isNotBlank(engIwtCode)) { + paramMap.put("detailEngIwtCode", engIwtCode); + sql.append("AND SWT.WT_TYPE = 'IWT' ") + .append("AND REL.ENG_IWT_CODE = #{map.detailEngIwtCode} "); + } + } + + private void fillDwtp(List voList, String engIwtCode, String engDwtCode) { + for (SdRvwtSVO vo : voList) { + if (StrUtil.isNotBlank(vo.getEngIwtCode()) + && StrUtil.isNotBlank(engIwtCode) + && vo.getEngIwtCode().contains(engIwtCode)) { + vo.setDwtp(SdRvwtSVO.DWTP_IWT); + } else if (StrUtil.isNotBlank(vo.getEngDwtCode()) + && StrUtil.isNotBlank(engDwtCode) + && vo.getEngDwtCode().contains(engDwtCode)) { + vo.setDwtp(SdRvwtSVO.DWTP_DWT); + } + } + } + + private void mergeDetailList(LinkedHashMap resultMap, List sourceList, String type) { + for (SdRvwtSVO source : sourceList) { + Date key = source.getTm(); + SdRvwtSVO target = resultMap.computeIfAbsent(key, item -> { + SdRvwtSVO vo = new SdRvwtSVO(); + vo.setDt(item); + vo.setTm(item); + return vo; + }); + if (TYPE_IWT.equals(type)) { + target.setIwtValue(source.getWt()); + } else if (TYPE_DWT.equals(type)) { + target.setDwtValue(source.getWt()); + } + } + } + + private Page buildPage(DataSourceLoadOptionsBase loadOptions) { + PageInfo pageInfo = QgcQueryWrapperUtil.getPageInfo(loadOptions); + if (Boolean.TRUE.equals(pageInfo.getHasPageInfo())) { + return pageInfo.getPage(); + } + return null; + } + + private String buildOrderBySql(List sortList, String timeColumn) { + List orderColumns = new ArrayList<>(); + if (sortList != null) { + for (DataSourceRequest.SortDescriptor sortDescriptor : sortList) { + String field = sortDescriptor.getField(); + String dir = "desc".equalsIgnoreCase(sortDescriptor.getDir()) ? "DESC" : "ASC"; + if ("tm".equals(field) || "dt".equals(field)) { + orderColumns.add(timeColumn + " " + dir); + } else if ("wt".equals(field) || "iwtValue".equals(field) || "dwtValue".equals(field)) { + orderColumns.add("SWS.WT " + dir); + } else if ("stcd".equals(field)) { + orderColumns.add("SWS.STCD " + dir); + } else if ("stnm".equals(field)) { + orderColumns.add("SWT.STNM " + dir); + } + } + } + if (orderColumns.isEmpty()) { + return " ORDER BY tm ASC"; + } + return " ORDER BY " + String.join(", ", orderColumns); + } + + private String getPrimarySortField(List sortList) { + if (sortList == null || sortList.isEmpty()) { + return null; + } + return sortList.get(0).getField(); + } + + private List pagingMemoryList(List sourceList, DataSourceRequest dataSourceRequest) { + int skip = Math.max(dataSourceRequest.getSkip(), 0); + int take = dataSourceRequest.getTake(); + if (take <= 0) { + return sourceList; + } + if (skip >= sourceList.size()) { + return new ArrayList<>(); + } + int end = Math.min(skip + take, sourceList.size()); + return new ArrayList<>(sourceList.subList(skip, end)); + } + + private void appendInCondition(StringBuilder sql, + Map paramMap, + String columnName, + String keyPrefix, + List valueList) { + if (valueList == null || valueList.isEmpty()) { + return; + } + sql.append("AND ").append(columnName).append(" IN ("); + for (int i = 0; i < valueList.size(); i++) { + String key = keyPrefix + i; + paramMap.put(key, valueList.get(i)); + if (i > 0) { + sql.append(", "); + } + sql.append("#{map.").append(key).append("}"); + } + sql.append(") "); + } + + private List splitFilterValues(String value) { + String filterValue = normalizeFilterValue(value); + List resultList = new ArrayList<>(); + if (StrUtil.isBlank(filterValue)) { + return resultList; + } + String[] values = filterValue.split(","); + for (String item : values) { + String valueItem = item == null ? null : item.trim(); + if (StrUtil.isNotBlank(valueItem) && !resultList.contains(valueItem)) { + resultList.add(valueItem); + } + } + return resultList; + } + + private String normalizeFilterValue(String value) { + if (StrUtil.isBlank(value)) { + return null; + } + return value.replace("[", "") + .replace("]", "") + .replace("\"", "") + .replace("'", "") + .trim(); + } + + private Date[] parseTimeRange(String timeValue) { + String filterValue = normalizeFilterValue(timeValue); + if (StrUtil.isBlank(filterValue)) { + return new Date[]{null, null}; + } + String[] values = filterValue.split(","); + if (values.length == 0) { + return new Date[]{null, null}; + } + Date startTime = DateUtil.parse(values[0].trim()); + Date endTime = values.length > 1 ? DateUtil.parse(values[1].trim()) : startTime; + if (startTime.after(endTime)) { + Date temp = startTime; + startTime = endTime; + endTime = temp; + } + return new Date[]{startTime, endTime}; + } + + private String resolveTimeFilterValue(DataSourceLoadOptionsBase loadOptions) { + String timeValue = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "tm"); + if (StrUtil.isBlank(normalizeFilterValue(timeValue))) { + timeValue = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "dt"); + } + return timeValue; + } + +} diff --git a/backend/src/main/java/com/yfd/platform/env/service/impl/SdWtMonitorServiceImpl.java b/backend/src/main/java/com/yfd/platform/env/service/impl/SdWtMonitorServiceImpl.java new file mode 100644 index 0000000..5313d49 --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/service/impl/SdWtMonitorServiceImpl.java @@ -0,0 +1,728 @@ +package com.yfd.platform.env.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yfd.platform.common.*; +import com.yfd.platform.env.entity.vo.FishSpawnVo; +import com.yfd.platform.env.entity.vo.SdWtMonitorCountVO; +import com.yfd.platform.env.entity.vo.SdWtBaseInfoVO; +import com.yfd.platform.env.entity.vo.WtrvVo; +import com.yfd.platform.env.entity.vo.WtFishVo; +import com.yfd.platform.env.mapper.SdWtMonitorMapper; +import com.yfd.platform.env.service.SdWtMonitorService; +import com.yfd.platform.utils.QgcQueryWrapperUtil; +import jakarta.annotation.Resource; +import lombok.Data; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +@Service +public class SdWtMonitorServiceImpl implements SdWtMonitorService { + + @Resource + private SdWtMonitorMapper sdWtMonitorMapper; + + @Resource + private MicroservicDynamicSQLMapper microservicDynamicSQLMapper; + + @Override + public DataSourceResult getEvnmAutoMonitorList() { + List list = sdWtMonitorMapper.getMonitorCountList(); + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(list == null ? 0 : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @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 EXISTS ( " + + " SELECT 1 FROM SD_WT_B_H vt " + + " WHERE vt.RSTCD = wt.RSTCD " + + " AND vt.STTP = 'WTVT' " + + " AND vt.IS_DELETED = 0 " + + " AND vt.MWAY = 2" + + ") THEN 1 ELSE 0 END AS hasRstcdWtvt " + + "FROM SD_WT_B_H wt " + + "LEFT JOIN SD_WTENGRLTN_B rel ON rel.STCD = wt.STCD AND rel.IS_DELETED = 0 " + + "WHERE wt.STCD = #{map.stcd} " + + " AND wt.STTP = 'WTRV' " + + " AND wt.IS_DELETED = 0"; + Map paramMap = new HashMap<>(); + paramMap.put("stcd", stcd); + WtrvVo vo = (WtrvVo) microservicDynamicSQLMapper.getOneBySqlWithResultType(sql, paramMap, WtrvVo.class); + if (vo == null ) { + return buildDefaultWtrvVo(stcd); + } + return vo; + } + + @Override + public DataSourceResult getWtFishAnalysis(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + String startTime = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "startTime"); + String endTime = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "endTime"); + String stcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stcd"); + DataSourceResult result = new DataSourceResult<>(); + if (StrUtil.isBlank(stcd) || StrUtil.isBlank(startTime) || StrUtil.isBlank(endTime)) { + result.setData(new ArrayList<>()); + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("t1.DT AS dt, ") + .append("t2.WT AS wt, ") + .append("eng.HBRVCD AS hbrvcd, ") + .append("t3.WT AS beforeWt ") + .append("FROM (SELECT TRUNC(TO_DATE(#{map.startTime}, 'YYYY-MM-DD HH24:MI:SS')) + LEVEL - 1 AS DT ") + .append(" FROM DUAL ") + .append(" CONNECT BY TRUNC(TO_DATE(#{map.startTime}, 'YYYY-MM-DD HH24:MI:SS')) + LEVEL - 1 <= TRUNC(TO_DATE(#{map.endTime}, 'YYYY-MM-DD HH24:MI:SS'))) t1 ") + .append("LEFT JOIN (SELECT STCD, WT, DT FROM SD_WTRVDAY_S ") + .append(" WHERE IS_DELETED = 0 ") + .append(" AND STCD = #{map.stcd} ") + .append(" AND DT >= TO_DATE(#{map.startTime}, 'YYYY-MM-DD HH24:MI:SS') ") + .append(" AND DT <= TO_DATE(#{map.endTime}, 'YYYY-MM-DD HH24:MI:SS')) t2 ") + .append(" ON t1.DT = t2.DT ") + .append("LEFT JOIN (SELECT STCD, WT, DT FROM SD_WTRVDAY_S ") + .append(" WHERE IS_DELETED = 0 ") + .append(" AND STCD = #{map.stcd} ") + .append(" AND DT >= ADD_MONTHS(TO_DATE(#{map.startTime}, 'YYYY-MM-DD HH24:MI:SS'), -12) ") + .append(" AND DT <= ADD_MONTHS(TO_DATE(#{map.endTime}, 'YYYY-MM-DD HH24:MI:SS'), -12)) t3 ") + .append(" ON t1.DT = ADD_MONTHS(t3.DT, 12) ") + .append("LEFT JOIN SD_WT_B_H wt ON wt.STCD = #{map.stcd} AND wt.IS_DELETED = 0 AND wt.STTP = 'WTRV' ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.RSTCD ") + .append("WHERE (t2.WT IS NOT NULL OR t3.WT IS NOT NULL) ") + .append(" AND t1.DT <= SYSDATE ") + .append("ORDER BY t1.DT DESC"); + + Map paramMap = new HashMap<>(); + paramMap.put("stcd", stcd); + paramMap.put("startTime", startTime); + paramMap.put("endTime", endTime); + + Page page = buildPage(dataSourceRequest.toDevRequest()); + List wtFishVoList = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, WtFishVo.class); + String hbrvcd = wtFishVoList.isEmpty() ? null : wtFishVoList.get(0).getHbrvcd(); + + if (StrUtil.isNotBlank(hbrvcd)) { + String fishSql = "SELECT t1.ID AS id, " + + "t1.NAME AS name, " + + "t1.PRETEMP AS pretempStr, " + + "t1.SPAWN_MONTH AS spawnMonthStr " + + "FROM SD_FISHDICTORY_B t1 " + + "INNER JOIN SD_FISHDICTORY_RLTN_B t2 ON t1.ID = t2.ZY_FISH_ID " + + "WHERE t1.IS_DELETED = 0 " + + " AND t2.IS_DELETED = 0 " + + " AND t2.RVCD = #{map.hbrvcd} " + + " AND t1.PRETEMP IS NOT NULL " + + " AND t1.SPAWN_MONTH IS NOT NULL " + + "ORDER BY NVL(t2.ORDER_INDEX, 999999), NVL(t1.ORDER_INDEX, 999999), t1.NAME"; + Map fishParamMap = new HashMap<>(); + fishParamMap.put("hbrvcd", hbrvcd); + List fishSpawnVoList = microservicDynamicSQLMapper.getAllListWithResultType(fishSql, fishParamMap, FishSpawnVo.class); + fillFishList(wtFishVoList, fishSpawnVoList); + } + + result.setData(wtFishVoList); + result.setTotal(page != null ? page.getTotal() : wtFishVoList.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getVmsstbprptList(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest.toDevRequest(); + String mway = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "mway"); + String sttpCode = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "sttpCode"); + String rstcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "rstcd"); + String stnm = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "stnm"); + String coenvwState = QgcQueryWrapperUtil.getFilterFieldValue(loadOptions, "coenvwState"); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append("hb.BASENAME AS baseName, ") + .append("wt.STNM AS stnm, ") + .append("eng.ENNM AS ennm, ") + .append("wt.JCDT AS jcdt, ") + .append("wt.STINDX AS stindx, ") + .append("CASE ") + .append("WHEN wt.STTP = 'WTRV' AND rvRecent.STCD IS NOT NULL THEN 1 ") + .append("WHEN wt.STTP = 'WTVT' AND vtRecent.STCD IS NOT NULL THEN 1 ") + .append("ELSE 0 END AS coenvwState, ") + .append("wt.STTP AS sttpCode, ") + .append("wt.STCD AS stcd, ") + .append("wt.RSTCD AS rstcd, ") + .append("NULL AS stCode, ") + .append("NULL AS stName, ") + .append("eng.DVTP AS dvtp, ") + .append("hb.ORDER_INDEX AS baseStepSort, ") + .append("eng.HBRVCD AS hbrvcd, ") + .append("eng.ORDER_INDEX AS rstcdStepSort, ") + .append("wt.ORDER_INDEX AS siteStepSort ") + .append("FROM SD_WT_B_H wt ") + .append("LEFT JOIN SD_ENGINFO_B_H eng ON eng.STCD = wt.RSTCD ") + .append("LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID ") + .append("LEFT JOIN (SELECT DISTINCT STCD FROM SD_WTRV_R WHERE IS_DELETED = 0 AND TM >= SYSDATE - 1) rvRecent ON rvRecent.STCD = wt.STCD ") + .append("LEFT JOIN (SELECT DISTINCT STCD FROM SD_WTVT_R WHERE IS_DELETED = 0 AND TM >= SYSDATE - 1) vtRecent ON vtRecent.STCD = wt.STCD ") + .append("WHERE wt.IS_DELETED = 0 AND wt.DTIN_TYPE = 0 "); + + Map paramMap = new HashMap<>(); + if (mway != null && !mway.isBlank()) { + paramMap.put("mway", mway); + sql.append("AND wt.MWAY = #{map.mway} "); + } + if (sttpCode != null && !sttpCode.isBlank()) { + paramMap.put("sttpCode", sttpCode); + sql.append("AND wt.STTP = #{map.sttpCode} "); + } + if (rstcd != null && !rstcd.isBlank()) { + paramMap.put("rstcd", rstcd); + sql.append("AND wt.RSTCD = #{map.rstcd} "); + } + if (stnm != null && !stnm.isBlank()) { + paramMap.put("stnm", "%" + stnm + "%"); + sql.append("AND wt.STNM LIKE #{map.stnm} "); + } + if (coenvwState != null && !coenvwState.isBlank()) { + paramMap.put("coenvwState", coenvwState); + sql.append("AND CASE ") + .append("WHEN wt.STTP = 'WTRV' AND rvRecent.STCD IS NOT NULL THEN 1 ") + .append("WHEN wt.STTP = 'WTVT' AND vtRecent.STCD IS NOT NULL THEN 1 ") + .append("ELSE 0 END = #{map.coenvwState} "); + } + + sql.append(buildVmsstbprptOrderBySql(dataSourceRequest.getSort())); + Page page = buildPage(loadOptions); + List list = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, SdWtBaseInfoVO.class); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + @Override + public DataSourceResult getCxDetailList(DataSourceRequest dataSourceRequest) { + List filters = new ArrayList<>(); + collectFilters(dataSourceRequest.getFilter(), filters); + + String stcd = null; + String drtp = null; + Object startTime = null; + Object endTime = null; + Integer startYear = null; + Integer endYear = null; + Integer startMonth = null; + Integer endMonth = null; + Integer startDr = null; + Integer endDr = null; + + for (DataSourceRequest.FilterDescriptor filter : filters) { + if ("stcd".equals(filter.getField())) { + stcd = toStringValue(filter.getValue()); + } else if ("drtp".equals(filter.getField())) { + drtp = toStringValue(filter.getValue()); + } else if ("tm".equals(filter.getField()) && "gte".equals(filter.getOperator())) { + startTime = filter.getValue(); + } else if ("tm".equals(filter.getField()) && "lte".equals(filter.getOperator())) { + endTime = filter.getValue(); + } else if ("startYear".equals(filter.getField()) && "gte".equals(filter.getOperator())) { + startYear = toIntegerValue(filter.getValue()); + } else if ("endYear".equals(filter.getField()) && "lte".equals(filter.getOperator())) { + endYear = toIntegerValue(filter.getValue()); + } else if ("startMonth".equals(filter.getField()) && "gte".equals(filter.getOperator())) { + startMonth = toIntegerValue(filter.getValue()); + } else if ("endMonth".equals(filter.getField()) && "lte".equals(filter.getOperator())) { + endMonth = toIntegerValue(filter.getValue()); + } else if ("startDr".equals(filter.getField()) && "gte".equals(filter.getOperator())) { + startDr = toIntegerValue(filter.getValue()); + } else if ("endDr".equals(filter.getField()) && "lte".equals(filter.getOperator())) { + endDr = toIntegerValue(filter.getValue()); + } + } + + if (StrUtil.isBlank(stcd)) { + return null; + } + + Integer wtDeviceType = sdWtMonitorMapper.getWtDeviceTypeByStcd(stcd); + StringBuilder sql = new StringBuilder(); + Map paramMap = new HashMap<>(); + paramMap.put("stcd", stcd); + + if ("DAY".equals(drtp)) { + if (startTime == null || endTime == null) { + return emptyCxDetailResult(wtDeviceType, drtp); + } + sql.append("SELECT t1.STCD AS stcd, ") + .append("wt.STNM AS stnm, ") + .append("TO_CHAR(t1.DT, 'YYYY-MM-DD') AS dt, ") + .append("LISTAGG(TO_CHAR(t1.WTHG), ',') WITHIN GROUP(ORDER BY t1.VWT) AS wthg, ") + .append("LISTAGG(TO_CHAR(t1.VWT), ',') WITHIN GROUP(ORDER BY t1.VWT) AS vwt ") + .append("FROM SD_WTVTDAY_S t1 ") + .append("INNER JOIN SD_WT_B_H wt ON t1.STCD = wt.STCD ") + .append("WHERE t1.STCD = #{map.stcd} ") + .append("AND t1.IS_DELETED = 0 ") + .append("AND wt.IS_DELETED = 0 ") + .append("AND wt.STTP = 'WTVT' ") + .append("AND t1.DT <= #{map.endTime} ") + .append("AND t1.DT >= #{map.startTime} ") + .append("AND t1.WTHG IS NOT NULL ") + .append("AND t1.VWT IS NOT NULL ") + .append("GROUP BY t1.DT, t1.STCD, wt.STNM "); + paramMap.put("startTime", startTime); + paramMap.put("endTime", endTime); + } else if ("HOUR".equals(drtp)) { + if (startTime == null || endTime == null) { + return emptyCxDetailResult(wtDeviceType, drtp); + } + sql.append("SELECT t1.STCD AS stcd, ") + .append("wt.STNM AS stnm, ") + .append("TO_CHAR(t1.TM, 'YYYY-MM-DD HH24:MI:SS') AS dt, ") + .append("LISTAGG(TO_CHAR(t1.WTHG), ',') WITHIN GROUP(ORDER BY t1.WTHG) AS wthg, ") + .append("LISTAGG(TO_CHAR(t1.VWT), ',') WITHIN GROUP(ORDER BY t1.WTHG) AS vwt ") + .append("FROM SD_WTVT_R t1 ") + .append("INNER JOIN SD_WT_B_H wt ON t1.STCD = wt.STCD ") + .append("WHERE t1.STCD = #{map.stcd} ") + .append("AND t1.IS_DELETED = 0 ") + .append("AND wt.IS_DELETED = 0 ") + .append("AND wt.STTP = 'WTVT' ") + .append("AND t1.TM <= TO_DATE(#{map.endTime}, 'YYYY-MM-DD HH24:MI:SS') ") + .append("AND t1.TM >= TO_DATE(#{map.startTime}, 'YYYY-MM-DD HH24:MI:SS') ") + .append("AND t1.WTHG IS NOT NULL ") + .append("AND t1.VWT IS NOT NULL ") + .append("GROUP BY t1.TM, t1.STCD, wt.STNM "); + paramMap.put("startTime", startTime); + paramMap.put("endTime", endTime); + } else if ("YEAR".equals(drtp)) { + if (startYear == null || endYear == null) { + return emptyCxDetailResult(wtDeviceType, drtp); + } + sql.append("SELECT t1.STCD AS stcd, ") + .append("wt.STNM AS stnm, ") + .append("t1.YEAR || '年' AS dt, ") + .append("LISTAGG(TO_CHAR(t1.WTHG), ',') WITHIN GROUP(ORDER BY t1.WTHG) AS wthg, ") + .append("LISTAGG(TO_CHAR(t1.VWT), ',') WITHIN GROUP(ORDER BY t1.WTHG) AS vwt ") + .append("FROM SD_WTVTDRTP_S t1 ") + .append("LEFT JOIN SD_WT_B_H wt ON t1.STCD = wt.STCD ") + .append("WHERE t1.DRTP = 'YEAR' ") + .append("AND t1.STCD = #{map.stcd} ") + .append("AND t1.IS_DELETED = 0 ") + .append("AND wt.IS_DELETED = 0 ") + .append("AND wt.STTP = 'WTVT' ") + .append("AND t1.YEAR >= #{map.startYear} ") + .append("AND t1.YEAR <= #{map.endYear} ") + .append("GROUP BY t1.STCD, wt.STNM, t1.YEAR "); + paramMap.put("startYear", startYear); + paramMap.put("endYear", endYear); + } else if ("MON".equals(drtp)) { + if (startYear == null || endYear == null || startMonth == null || endMonth == null) { + return emptyCxDetailResult(wtDeviceType, drtp); + } + sql.append("SELECT t1.STCD AS stcd, ") + .append("wt.STNM AS stnm, ") + .append("t1.YEAR || '-' || LPAD(t1.MONTH, 2, '0') AS dt, ") + .append("LISTAGG(TO_CHAR(t1.WTHG), ',') WITHIN GROUP(ORDER BY t1.WTHG) AS wthg, ") + .append("LISTAGG(TO_CHAR(t1.VWT), ',') WITHIN GROUP(ORDER BY t1.WTHG) AS vwt ") + .append("FROM SD_WTVTDRTP_S t1 ") + .append("LEFT JOIN SD_WT_B_H wt ON t1.STCD = wt.STCD ") + .append("WHERE t1.DRTP = 'MON' ") + .append("AND t1.STCD = #{map.stcd} ") + .append("AND t1.IS_DELETED = 0 ") + .append("AND wt.IS_DELETED = 0 ") + .append("AND wt.STTP = 'WTVT' ") + .append("AND TO_DATE(t1.YEAR || '-' || t1.MONTH, 'YYYY-MM') >= TO_DATE(#{map.startYearMonth}, 'YYYY-MM') ") + .append("AND TO_DATE(t1.YEAR || '-' || t1.MONTH, 'YYYY-MM') <= TO_DATE(#{map.endYearMonth}, 'YYYY-MM') ") + .append("GROUP BY t1.STCD, wt.STNM, t1.YEAR, t1.MONTH "); + paramMap.put("startYearMonth", startYear + "-" + startMonth); + paramMap.put("endYearMonth", endYear + "-" + endMonth); + } else if ("QUA".equals(drtp)) { + if (startYear == null || endYear == null || startDr == null || endDr == null) { + return emptyCxDetailResult(wtDeviceType, drtp); + } + sql.append("SELECT t1.STCD AS stcd, ") + .append("wt.STNM AS stnm, ") + .append("t1.YEAR || '年' || t1.DR || '季度' AS dt, ") + .append("LISTAGG(TO_CHAR(t1.WTHG), ',') WITHIN GROUP(ORDER BY t1.WTHG) AS wthg, ") + .append("LISTAGG(TO_CHAR(t1.VWT), ',') WITHIN GROUP(ORDER BY t1.WTHG) AS vwt ") + .append("FROM SD_WTVTDRTP_S t1 ") + .append("LEFT JOIN SD_WT_B_H wt ON t1.STCD = wt.STCD ") + .append("WHERE t1.DRTP = 'QUA' ") + .append("AND t1.STCD = #{map.stcd} ") + .append("AND t1.IS_DELETED = 0 ") + .append("AND wt.IS_DELETED = 0 ") + .append("AND wt.STTP = 'WTVT' ") + .append("AND t1.YEAR >= #{map.startYear} ") + .append("AND t1.YEAR <= #{map.endYear} ") + .append("AND t1.DR >= #{map.startDr} ") + .append("AND t1.DR <= #{map.endDr} ") + .append("GROUP BY t1.STCD, wt.STNM, t1.YEAR, t1.DR "); + paramMap.put("startYear", startYear); + paramMap.put("endYear", endYear); + paramMap.put("startDr", startDr); + paramMap.put("endDr", endDr); + } else if ("TEN".equals(drtp)) { + if (startYear == null || endYear == null || startMonth == null || endMonth == null || startDr == null || endDr == null) { + return emptyCxDetailResult(wtDeviceType, drtp); + } + sql.append("SELECT t1.STCD AS stcd, ") + .append("wt.STNM AS stnm, ") + .append("t1.YEAR || '年' || t1.MONTH || '月' || CASE t1.DR WHEN 1 THEN '上' WHEN 2 THEN '中' WHEN 3 THEN '下' ELSE '' END || '旬' AS dt, ") + .append("LISTAGG(TO_CHAR(t1.WTHG), ',') WITHIN GROUP(ORDER BY t1.WTHG) AS wthg, ") + .append("LISTAGG(TO_CHAR(t1.VWT), ',') WITHIN GROUP(ORDER BY t1.WTHG) AS vwt ") + .append("FROM SD_WTVTDRTP_S t1 ") + .append("LEFT JOIN SD_WT_B_H wt ON t1.STCD = wt.STCD ") + .append("WHERE t1.DRTP = 'TEN' ") + .append("AND t1.STCD = #{map.stcd} ") + .append("AND t1.IS_DELETED = 0 ") + .append("AND wt.IS_DELETED = 0 ") + .append("AND wt.STTP = 'WTVT' ") + .append("AND t1.YEAR >= #{map.startYear} ") + .append("AND t1.YEAR <= #{map.endYear} ") + .append("AND t1.MONTH >= #{map.startMonth} ") + .append("AND t1.MONTH <= #{map.endMonth} ") + .append("AND t1.DR >= #{map.startDr} ") + .append("AND t1.DR <= #{map.endDr} ") + .append("GROUP BY t1.STCD, wt.STNM, t1.YEAR, t1.MONTH, t1.DR "); + paramMap.put("startYear", startYear); + paramMap.put("endYear", endYear); + paramMap.put("startMonth", startMonth); + paramMap.put("endMonth", endMonth); + paramMap.put("startDr", startDr); + paramMap.put("endDr", endDr); + } else { + return emptyCxDetailResult(wtDeviceType, drtp); + } + + appendCxDetailOrderBy(sql, dataSourceRequest.getSort()); + Page page = buildPage(dataSourceRequest.toDevRequest()); + List rowList = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, WtCxDetailRow.class); + + List verticalList = getVerticals(rowList, wtDeviceType); + List> resultData = new ArrayList<>(); + for (WtCxDetailRow row : rowList) { + Map result = new LinkedHashMap<>(); + result.put("stcd", row.getStcd()); + result.put("stnm", row.getStnm()); + result.put("dt", row.getDt()); + + Map dataList = new LinkedHashMap<>(); + for (Double vertical : verticalList) { + dataList.put(Double.toString(vertical), "-"); + } + + List wthgList = splitValue(row.getWthg()); + List vwtList = splitValue(row.getVwt()); + for (int i = 0; i < wthgList.size(); i++) { + try { + Double wthg = Double.parseDouble(wthgList.get(i)); + String key = Double.toString(wthg); + String vwt = i < vwtList.size() ? vwtList.get(i) : null; + dataList.put(key, vwt); + } catch (NumberFormatException ignored) { + } + } + result.put("dataList", dataList); + resultData.add(result); + } + + List> columns = new ArrayList<>(); + columns.add(buildColumn("stnm", "测站名称", true, "stnm", false, null, null)); + String dateFormat = "yyyy-MM-dd HH:mm"; + if ("DAY".equals(drtp)) { + dateFormat = "yyyy-MM-dd"; + } else if ("MON".equals(drtp)) { + dateFormat = "yyyy-MM"; + } + columns.add(buildColumn("dt", "时间", true, "dt", false, "date", dateFormat)); + for (Double vertical : verticalList) { + String key = Double.toString(vertical); + String title = (wtDeviceType == null || wtDeviceType == 1) ? "水深" + vertical + "m(℃)" : "高程" + vertical + "m(℃)"; + columns.add(buildColumn(key, title, true, key, false, null, null)); + } + + Map table = new LinkedHashMap<>(); + table.put("columns", columns); + table.put("dataSource", resultData); + table.put("wtDeviceType", wtDeviceType); + + DataSourceResult> result = new DataSourceResult<>(); + result.setData(Collections.singletonList(table)); + result.setTotal(page != null ? page.getTotal() : rowList.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private Page buildPage(DataSourceLoadOptionsBase loadOptions) { + PageInfo pageInfo = QgcQueryWrapperUtil.getPageInfo(loadOptions); + if (Boolean.TRUE.equals(pageInfo.getHasPageInfo())) { + return pageInfo.getPage(); + } + return null; + } + + private String buildVmsstbprptOrderBySql(List sortList) { + List orderColumns = new ArrayList<>(); + if (sortList != null) { + for (DataSourceRequest.SortDescriptor sortDescriptor : sortList) { + String field = sortDescriptor.getField(); + String dir = "desc".equalsIgnoreCase(sortDescriptor.getDir()) ? "DESC" : "ASC"; + if ("baseStepSort".equals(field)) { + orderColumns.add("NVL(hb.ORDER_INDEX, 999999) " + dir); + } else if ("hbrvcd".equals(field)) { + orderColumns.add("NVL(eng.HBRVCD, '~') " + dir); + } else if ("rstcdStepSort".equals(field)) { + orderColumns.add("NVL(eng.ORDER_INDEX, 999999) " + dir); + } else if ("siteStepSort".equals(field)) { + orderColumns.add("NVL(wt.ORDER_INDEX, 999999) " + dir); + } else if ("stnm".equals(field)) { + orderColumns.add("wt.STNM " + dir); + } else if ("ennm".equals(field)) { + orderColumns.add("eng.ENNM " + dir); + } else if ("stcd".equals(field)) { + orderColumns.add("wt.STCD " + dir); + } + } + } + if (orderColumns.isEmpty()) { + return " ORDER BY NVL(hb.ORDER_INDEX, 999999) ASC, NVL(eng.HBRVCD, '~') ASC, NVL(eng.ORDER_INDEX, 999999) ASC, NVL(wt.ORDER_INDEX, 999999) ASC"; + } + return " ORDER BY " + String.join(", ", orderColumns); + } + + private void collectFilters(DataSourceRequest.FilterDescriptor filter, List result) { + if (filter == null) { + return; + } + if (filter.getFilters() == null || filter.getFilters().isEmpty()) { + if (StrUtil.isNotBlank(filter.getField())) { + result.add(filter); + } + return; + } + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + collectFilters(child, result); + } + } + + private String toStringValue(Object value) { + return value == null ? null : String.valueOf(value); + } + + private Integer toIntegerValue(Object value) { + if (value == null || StrUtil.isBlank(String.valueOf(value))) { + return null; + } + return Integer.parseInt(String.valueOf(value)); + } + + private void appendCxDetailOrderBy(StringBuilder sql, List sortList) { + if (sortList == null || sortList.isEmpty()) { + return; + } + List orderColumns = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sortDescriptor : sortList) { + String dir = "desc".equalsIgnoreCase(sortDescriptor.getDir()) ? "DESC" : "ASC"; + if ("dt".equals(sortDescriptor.getField())) { + orderColumns.add("dt " + dir); + } else if ("stcd".equals(sortDescriptor.getField())) { + orderColumns.add("stcd " + dir); + } else if ("stnm".equals(sortDescriptor.getField())) { + orderColumns.add("stnm " + dir); + } + } + if (!orderColumns.isEmpty()) { + sql.append(" ORDER BY ").append(String.join(", ", orderColumns)); + } + } + + private List> emptyTableList(Integer wtDeviceType, String drtp) { + List> columns = new ArrayList<>(); + columns.add(buildColumn("stnm", "测站名称", true, "stnm", false, null, null)); + String dateFormat = "yyyy-MM-dd HH:mm"; + if ("DAY".equals(drtp)) { + dateFormat = "yyyy-MM-dd"; + } else if ("MON".equals(drtp)) { + dateFormat = "yyyy-MM"; + } + columns.add(buildColumn("dt", "时间", true, "dt", false, "date", dateFormat)); + Map table = new LinkedHashMap<>(); + table.put("columns", columns); + table.put("dataSource", new ArrayList<>()); + table.put("wtDeviceType", wtDeviceType); + return Collections.singletonList(table); + } + + private DataSourceResult emptyCxDetailResult(Integer wtDeviceType, String drtp) { + DataSourceResult> result = new DataSourceResult<>(); + result.setData(emptyTableList(wtDeviceType, drtp)); + result.setTotal(0); + result.setAggregates(new HashMap<>()); + return result; + } + + private Map buildColumn(String dataIndex, + String title, + boolean visible, + String key, + boolean merge, + String dataType, + String dataFormat) { + Map column = new LinkedHashMap<>(); + column.put("dataIndex", dataIndex); + column.put("title", title); + column.put("visible", visible); + column.put("key", key); + column.put("unit", null); + column.put("merge", merge); + column.put("dataType", dataType); + column.put("dataFormat", dataFormat); + column.put("children", new ArrayList<>()); + return column; + } + + private List splitValue(String value) { + if (StrUtil.isBlank(value)) { + return Collections.emptyList(); + } + String[] values = value.split(","); + List result = new ArrayList<>(values.length); + for (String item : values) { + result.add(item == null ? null : item.trim()); + } + return result; + } + + private List getVerticals(List rowList, Integer wtDeviceType) { + List verticals = new ArrayList<>(); + for (WtCxDetailRow row : rowList) { + for (String wthg : splitValue(row.getWthg())) { + try { + verticals.add(Double.parseDouble(wthg)); + } catch (NumberFormatException ignored) { + } + } + } + return verticals.stream() + .filter(Objects::nonNull) + .distinct() + .sorted((wtDeviceType == null || wtDeviceType == 1) ? Comparator.naturalOrder() : Comparator.reverseOrder()) + .collect(Collectors.toList()); + } + + private void fillFishList(List wtFishVoList, List fishSpawnVoList) { + if (wtFishVoList == null || wtFishVoList.isEmpty() || fishSpawnVoList == null || fishSpawnVoList.isEmpty()) { + return; + } + for (WtFishVo wtFishVo : wtFishVoList) { + List fishList = new ArrayList<>(); + Date dt = wtFishVo.getDt(); + BigDecimal wt = wtFishVo.getWt(); + if (dt == null || wt == null) { + wtFishVo.setFishList(fishList); + continue; + } + Calendar calendar = Calendar.getInstance(); + calendar.setTime(dt); + int month = calendar.get(Calendar.MONTH) + 1; + for (FishSpawnVo fishSpawnVo : fishSpawnVoList) { + if (!matchSpawnMonth(fishSpawnVo.getSpawnMonthStr(), month)) { + continue; + } + BigDecimal[] range = parsePretempRange(fishSpawnVo.getPretempStr()); + if (range == null) { + continue; + } + if (wt.compareTo(range[0]) >= 0 && wt.compareTo(range[1]) <= 0) { + fishList.add(fishSpawnVo); + } + } + wtFishVo.setFishList(fishList); + } + } + + private boolean matchSpawnMonth(String spawnMonthStr, int month) { + if (StrUtil.isBlank(spawnMonthStr)) { + return false; + } + for (String monthStr : spawnMonthStr.split(",")) { + if (StrUtil.isBlank(monthStr)) { + continue; + } + try { + if (Integer.parseInt(monthStr.trim()) == month) { + return true; + } + } catch (NumberFormatException ignored) { + } + } + return false; + } + + private BigDecimal[] parsePretempRange(String pretempStr) { + if (StrUtil.isBlank(pretempStr)) { + return null; + } + String temp = pretempStr.replace("℃", "").trim(); + String[] split = temp.contains("~") ? temp.split("~") : temp.split("~"); + if (split.length != 2) { + return null; + } + try { + return new BigDecimal[]{new BigDecimal(split[0].trim()), new BigDecimal(split[1].trim())}; + } catch (Exception ignored) { + return null; + } + } + + private WtrvVo buildDefaultWtrvVo(String stcd) { + WtrvVo vo = new WtrvVo(); + vo.setStcd(stcd); + vo.setIsIoWtrv(false); + vo.setHasRstcdWtvt(false); + return vo; + } + + private Boolean toBooleanValue(Object value) { + if (value == null) { + return false; + } + if (value instanceof Boolean boolValue) { + return boolValue; + } + if (value instanceof Number number) { + return number.intValue() != 0; + } + String strValue = String.valueOf(value).trim(); + return "1".equals(strValue) || "true".equalsIgnoreCase(strValue) || "Y".equalsIgnoreCase(strValue); + } + + @Data + private static class WtCxDetailRow { + private String stcd; + private String dt; + private String stnm; + private String wthg; + private String vwt; + } + +} diff --git a/backend/src/main/java/com/yfd/platform/env/service/impl/SdWtvtRServiceImpl.java b/backend/src/main/java/com/yfd/platform/env/service/impl/SdWtvtRServiceImpl.java new file mode 100644 index 0000000..8f8abcd --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/env/service/impl/SdWtvtRServiceImpl.java @@ -0,0 +1,47 @@ +package com.yfd.platform.env.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yfd.platform.common.DataSourceLoadOptionsBase; +import com.yfd.platform.common.DataSourceRequest; +import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.env.entity.vo.SdWtvtYearVo; +import com.yfd.platform.env.mapper.SdWtvtRMapper; +import com.yfd.platform.env.service.SdWtvtRService; +import com.yfd.platform.utils.QgcQueryWrapperUtil; +import com.yfd.platform.utils.QueryWrapperUtil; +import jakarta.annotation.Resource; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 垂向水温Service实现类 + * + * @author + * @since 2023-04-23 09:32:10 + */ +@Service +public class SdWtvtRServiceImpl extends ServiceImpl implements SdWtvtRService { + + @Resource + private SdWtvtRMapper sdWtvtRMapper; + + @Override + public DataSourceResult getWtrvDefaultYear(DataSourceRequest dataSourceRequest) { + DataSourceResult dataSourceResult = new DataSourceResult<>(); + DataSourceLoadOptionsBase loadOptionsBase = dataSourceRequest.toDevRequest(); + String stcd = QgcQueryWrapperUtil.getFilterFieldValue(loadOptionsBase, "stcd"); + + if (StringUtils.isNotBlank(stcd)) { + stcd = stcd.replaceAll("\\[", "") + .replaceAll("]", "") + .replaceAll("\"", ""); + } + + List result = sdWtvtRMapper.getWtrvDefaultYear(stcd); + dataSourceResult.setTotal(result.size()); + dataSourceResult.setData(result); + return dataSourceResult; + } +} diff --git a/backend/src/main/java/com/yfd/platform/utils/QgcQueryWrapperUtil.java b/backend/src/main/java/com/yfd/platform/utils/QgcQueryWrapperUtil.java index bdbb6ac..9db62f6 100644 --- a/backend/src/main/java/com/yfd/platform/utils/QgcQueryWrapperUtil.java +++ b/backend/src/main/java/com/yfd/platform/utils/QgcQueryWrapperUtil.java @@ -116,8 +116,7 @@ public class QgcQueryWrapperUtil { } if (columnName != null && columnName.equals(fieldName)) { - if (StrUtil.isEmpty((CharSequence) value)) { - StringBuffer var9 = null; + if (value == null || (value instanceof String && StrUtil.isEmpty((String) value))) { return; } diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index 03a78ea..cd6f706 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -1,6 +1,6 @@ spring: profiles: - active: devtw + active: prod jasypt: encryptor: