64 KiB
黑石咀水库系统详细设计文档
第4章 项目总体设计
4.1 总体架构
4.1.1 四层分布式体系架构
黑石咀水库系统作为湖北省山洪灾害监测预报预警"四预"系统的重要组成部分,采用面向服务的架构模型,建立了完整的"基础支撑层-数据支撑层-业务支撑层-业务应用层"分布式体系架构。
架构层次设计
基础支撑层:
- 感知设备体系:集成雨量站、水位站、图像站、末端预警站等监测设备
- 传输网络架构:水利专网和互联网双通道数据传输
- 基础资源平台:基于省政务云水利专区的计算资源、存储资源、安全资源和资源调度服务
- 设备接入管理:通过
StPptnR、StRsvrR、StRiverR等实体模型实现设备数据的标准化接入
数据支撑层:
- 多源数据整合:建设汇聚库、主题库、基础库、共享库、专题库五级数据体系
- 数据治理平台:对各类基础数据、地理空间数据、监测预报数据进行集成、存储、处理、共享
- 数据同步机制:通过
DataTaskHsz定时任务实现5分钟间隔的多源数据同步 - 数据质量控制:实现数据清洗、验证、标准化处理
业务支撑层:
- 算法模型体系:
- 小流域分布式水文模型集成(
flood_algorithm库) - 简化淹没范围与水深分析模型
- GRIB2气象数据处理模型(
ForecastService) - 空间数据分析模型(JTS集成)
- 小流域分布式水文模型集成(
- 应用支撑平台:
- GIS引擎:基于JTS的空间数据处理能力
- 微服务管理:Spring Boot 3.x原生微服务支持
- 数据支撑平台:MyBatis-Plus 3.5.7 ORM框架
- 消息中心:
MessageCenterService预警消息管理 - 文件管理:MinIO/S3兼容对象存储
业务应用层:
- 预报系统:气象预报和洪水预测功能
- 预警系统:多级别、多类型的预警信息管理
- 预演系统:考核评估和演练管理
- 预案系统:应急响应和决策支持
4.1.2 技术架构实现
微服务架构设计
系统采用Spring Boot 3.x微服务架构,实现服务的模块化部署和独立扩展:
@GunShiApplication
@MapperScan(basePackages = {"com.gunshi.**.mapper", "com.gunshi.**.model"})
@EnableMPP
@EnableCaching
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
分层架构模式
控制器层:132个REST API控制器,提供统一的HTTP接口服务
- 统一异常处理:
MyE500UnknownExceptionResolver - 参数验证:JSR-303验证注解
- API文档:Swagger 3.0自动生成
服务层:业务逻辑处理核心
- 事务管理:
@Transactional(rollbackFor = Exception.class) - 缓存策略:
@Cacheable和@CacheEvict注解 - 异步处理:
@Async和@Scheduled注解
数据访问层:基于MyBatis-Plus的数据持久化
- Lambda查询:类型安全的查询构建
- 动态SQL:灵活的查询条件组合
- 分页插件:高效的数据分页处理
数据流转架构
外部数据源 → HTTP API → 数据同步任务 → 数据清洗 → PostgreSQL
↓
实时数据表 → 历史数据表 → 整编数据表(小时/天)
↓
Redis缓存 → 业务服务调用 → 前端展示
4.2 网络架构
4.2.1 多网络区域架构设计
根据云平台整体架构规划,系统网络接入采用多区域隔离设计,包括互联网接入区、政务外网接入区,每个接入区的业务处理网络彼此隔离。
政务外网及专网区实现
网络分区设计:
-
接入区:提供专线接入湖北省水利厅专网
- 荆楚水库API:
jcskPath: http://64.97.142.113:8002/shareddata/api/v1/monitdata - Token认证:
jcskTokenAPI访问令牌管理 - IP白名单:
reloadCache动态缓存清理机制
- 荆楚水库API:
-
核心交换区:完成各功能分区之间数据流量的高速交换
- 数据库主从同步:PostgreSQL主备架构
- Redis缓存集群:多实例缓存服务
- 负载均衡:基于docker-compose的服务编排
-
运维区:提供远程运维接入服务
- SSH远程访问:
deploy_rsa密钥认证 - 日志监控:应用日志和系统日志统一管理
- 性能监控:数据库和应用性能指标监控
- SSH远程访问:
-
管理区域:提供数据中心整体的管理功能
- 用户管理:基于RuoYi框架的权限管理
- 配置管理:多环境配置文件管理
- 审计日志:操作日志和安全审计
安全隔离区实现
容器化安全隔离:
services:
hsz:
image: openjdk:21
container_name: hsz
network_mode: host
restart: no
volumes:
- /root/gunshiApp/hsz:/app
environment:
- SPRING_PROFILES_ACTIVE=dev
- TZ=Asia/Shanghai
网络安全配置:
- 网络模式:
network_mode: host实现负载分担 - 端口管理:统一的服务端口管理(24205)
- 访问控制:基于Token的API访问控制
4.2.2 外部网络集成
三网接入支持
多网络接入架构:
- 电信接入:通过外部API配置支持电信网络接入
- 联通接入:多网络负载均衡和冗余设计
- 移动接入:移动网络接入支持
外部API集成体系:
# 气象数据API
shqxjsCloudowrCnPath: http://shqxjs.cloudowr.cn/service/
# 水库数据API
owrsvrPath: http://owrsvr.cloudowr.cn/
# IP白名单管理
reloadCache: http://223.75.53.124:8002/shareddata/sys/whitelists/reloadCache
# 数据同步API
apiPath: http://223.75.53.141:8000/shzh/monitdata/datasync/getData
# 预警信息API
shqxjsWarnPath: http://223.75.53.141:8000/shzh/met/zyqxfw/api/warning/getGroupWarning
4.3 部署架构
4.3.1 容器化部署架构
前端服务器配置
VPC部署设计:
- 独立VPC环境,分配弹性IP
- 集群技术实现负载分担和高可用
- 等保三级安全要求:WAF、防DDOS、IPS等安全服务
网络优化配置:
server:
port: 24205
servlet:
context-path: /gunshiApp/hsz
compression:
enabled: true
mime-types: application/javascript,text/css,application/json,application/xml,text/html,text/xml
后端服务器配置
独立VPC部署:
- 后端服务器在单独的VPC,不分配弹性IP
- 内部IP地址交互,提高安全性
- 云防火墙安全隔离
容器编排配置:
- 基础镜像:
openjdk:21 - 数据存储:
/root/gunshiApp/hsz:/app - 时区配置:
TZ=Asia/Shanghai - 环境配置:
SPRING_PROFILES_ACTIVE=dev
4.3.2 数据引擎部署
PostgreSQL主备架构
主数据库配置:
spring:
datasource:
dynamic:
datasource:
master:
url: jdbc:postgresql://postgres:5432/hsz?stringtype=unspecified
username: gunshiiot
password: 1234567a
driver-class-name: org.postgresql.Driver
备用数据库配置:
- 主从同步:基于PostgreSQL流复制
- 故障转移:自动主备切换机制
- 连接池:HikariCP高性能连接管理
缓存系统部署
Redis集群配置:
data:
redis:
host: redis
port: 6379
database: 4
缓存策略:
- 会话管理:用户登录状态缓存
- 查询缓存:热点数据查询优化
- 分布式缓存:多实例数据一致性
4.4 数据架构
4.4.1 数据源体系
行业外数据源
气象数据源:
- 数据来源:省气象局气象监测雨量和预报雨量
- 接入方式:
shqxjsCloudowrCnPathAPI接口 - 数据类型:GRIB2气象文件、实时监测数据
- 处理服务:
ForecastService气象预报处理
水文数据源:
- 数据来源:省水文处水文监测雨量
- 接入方式:荆楚水库API专线接入
- 数据类型:降雨量、水位、流量
- 同步频率:5分钟定时同步
水库数据源:
- 数据来源:省水库处水库监测数据
- 接入方式:
owrsvrPathAPI接口 - 数据类型:水库水位、蓄水量
- 处理机制:实时数据和历史数据分离
行业内数据源
基础地理数据:
- 数据来源:中国水科院提供的107条小流域风险隐患调查数据
- 数据类型:空间地理数据、流域边界、风险隐患要素
- 处理方式:GIS空间分析和可视化
行政区划数据:
- 数据来源:各区县水利局提供的行政区划信息
- 数据类型:行政区划边界、责任人信息
- 管理服务:
StAddvcdDService行政区划管理
4.4.2 数据支撑平台
数据处理能力
气象文件处理:
- GRIB2文件解析:
grb.RainGrib2Layer网格数据模型 - 雷达数据处理:短临预报数据处理
- 网格计算:基于JTS的空间插值算法
数据计算分析:
- 面雨量计算:泰森多边形权重计算
- 时间序列分析:历史数据趋势分析
- 多维分析:基于MyBatis-Plus的数据统计
算法模型对接:
- 洪水算法库:
flood_algorithm库集成 - 空间分析:JTS几何计算引擎
- 预测模型:气象预报和水文预测模型
数据交换共享平台
数据同步机制:
@Async
@Scheduled(fixedRate = 5, timeUnit = TimeUnit.MINUTES)
public void getPptnData() // 5分钟雨量数据同步
@Async
@Scheduled(fixedRate = 5, timeUnit = TimeUnit.MINUTES)
public void getRiverData() // 5分钟水情数据同步
数据汇聚中心:
- 25个县区山洪监测数据汇聚
- 一站双发数据采集机制
- 数据质量控制和异常处理
4.4.3 数据库体系
基础数据库设计
实体模型体系:
- 监测数据模型:
StPptnR、StRsvrR、StRiverR - 预警数据模型:
MessageCenter、OsmoticWarnR - 业务数据模型:
AssessTask、PrePlace、ByPlan
数据关系设计:
- 一对多关系:防治对象与监测设备关系
- 多对多关系:考核任务与考核对象关系
- 层级关系:行政区划层级结构
专题数据库设计
预报专题库:
- 气象预报数据:24小时预报和逐小时预报
- 网格降雨数据:基于GIS的空间网格数据
- 历史比对数据:历史同期数据对比分析
预警专题库:
- 预警规则配置:
OsmoticWarnRule预警规则管理 - 预警消息记录:分级预警消息存储
- 预警统计分析:预警频次和类型统计
4.4.4 数据应用体系
水雨情监测应用
实时监测功能:
- 实时数据展示:
StPptnRRealService实时降雨监测 - 历史数据查询:
StPptnRService历史数据检索 - 数据统计报表:多维度数据统计分析
监测站点管理:
- 站点信息管理:监测站点基本信息维护
- 站点状态监控:设备运行状态实时监控
- 数据质量评估:监测数据质量评估和报警
预报应用专题
天气预报功能:
- GRIB2数据处理:专业气象文件解析
- 网格降雨量计算:空间插值算法
- 预报结果展示:多时间尺度预报展示
洪水预报功能:
- 水位预测:基于历史数据的水位预测
- 流量预测:基于水文模型的流量预测
- 风险评估:洪水风险评估和预警
预警应用专题
多级预警机制:
- 水位预警:超校核水位、超设计水位、超汛限水位
- 渗压预警:渗流压力监测和预警
- 降雨预警:强降雨监测和预警
预警消息管理:
- 消息推送:基于角色的预警消息推送
- 状态管理:预警消息的确认和处理状态
- 统计分析:预警数据统计和分析
4.5 安全架构
4.5.1 总体安全策略
数据安全策略
敏感数据保护:
- 数据库连接加密:PostgreSQL SSL连接
- API访问认证:基于Token的身份认证
- 密码安全:数据库密码加密存储
输入数据安全:
- XSS防护:自定义Jackson反序列化器
- SQL注入防护:MyBatis-Plus参数化查询
- 输入验证:JSR-303验证注解
系统安全策略
访问控制:
- 基于角色的权限控制:RuoYi框架集成
- API访问控制:Token认证机制
- 数据访问控制:基于用户权限的数据访问
审计安全:
- 操作日志记录:用户操作行为审计
- 系统日志监控:系统运行状态监控
- 安全事件审计:安全事件记录和分析
4.5.2 网络安全等级保护
等保三级要求
网络安全防护:
- 网络隔离:政务外网和互联网区域隔离
- 访问控制:基于IP和端口的访问控制
- 入侵检测:网络入侵检测和防护
数据安全防护:
- 数据加密:敏感数据传输和存储加密
- 数据备份:定期数据备份和恢复
- 数据完整性:数据完整性校验和验证
应用安全防护:
- 应用防火墙:Web应用防火墙防护
- 漏洞管理:定期漏洞扫描和修复
- 安全编码:安全编码规范和检查
4.5.3 安全技术体系
计算环境安全
容器安全:
- Docker容器隔离:进程和网络隔离
- 镜像安全:基础镜像安全扫描
- 运行时安全:容器运行时监控
应用安全:
- Spring Security:安全框架集成
- 会话管理:安全的会话管理机制
- 异常处理:统一的异常处理机制
数据安全:
- 数据库安全:PostgreSQL安全配置
- 文件安全:MinIO对象存储安全
- 缓存安全:Redis缓存安全配置
安全区域边界
网络边界安全:
- 防火墙:网络边界防火墙防护
- 负载均衡:安全的负载均衡配置
- DDoS防护:分布式拒绝服务攻击防护
应用边界安全:
- API网关:统一的API访问控制
- 请求限流:API访问频率限制
- 参数验证:输入参数严格验证
4.5.4 安全管理体系
安全策略管理
安全策略制定:
- 数据安全策略:敏感数据保护策略
- 网络安全策略:网络安全防护策略
- 应用安全策略:应用系统安全策略
安全管理制度:
- 访问控制制度:基于角色的访问控制
- 数据管理制度:数据分类和管理制度
- 应急响应制度:安全事件应急响应流程
安全运维管理
安全监控:
- 实时监控:系统安全状态实时监控
- 日志审计:安全日志审计和分析
- 异常检测:安全异常行为检测
安全维护:
- 漏洞修复:定期漏洞扫描和修复
- 安全更新:系统和应用安全更新
- 备份恢复:数据备份和恢复演练
4.6 数据流向
4.6.1 数据采集流程
多源数据采集
山洪5分钟雨量监测数据:
- 数据源:全省74个县的山洪5分钟雨量监测数据
- 采集方式:一站双发形式,确保数据可靠性
- 处理机制:
DataTaskHsz.getPptnData()定时同步 - 数据存储:
StPptnR实时数据表和StPptnRH历史数据表
气象1小时雨量监测数据:
- 数据源:省气象局Oracle数据库
- 采集方式:先上报到省气象局,再通过数据汇集与共享平台同步
- 处理机制:GRIB2文件解析和网格化处理
- 数据存储:
ForecastService处理后的网格数据
水库1小时雨量监测数据:
- 数据源:省水库处SqlServer数据库
- 采集方式:通过数据汇集与共享平台同步
- 处理机制:
DataTaskHsz.getRiverData()定时同步 - 数据存储:
StRsvrR水库水位数据表
数据质量控制
数据验证机制:
- 完整性检查:数据字段完整性验证
- 格式检查:数据格式和类型验证
- 范围检查:数据值范围合理性验证
数据清洗流程:
- 异常数据处理:识别和处理异常数据
- 重复数据去重:基于时间戳和设备ID去重
- 数据标准化:统一数据格式和单位
4.6.2 数据处理流程
实时数据处理
实时数据流入:
外部API → HTTP请求 → 数据解析 → 数据验证 → PostgreSQL存储
↓
Redis缓存更新 → 业务服务消费 → 前端实时展示
数据同步机制:
@Async
@Scheduled(fixedRate = 5, timeUnit = TimeUnit.MINUTES)
public void getPptnData() {
// HTTP请求获取数据
// 数据解析和验证
// 批量保存到数据库
// 更新Redis缓存
}
历史数据处理
数据整编处理:
- 小时数据整编:基于5分钟数据生成小时统计数据
- 天数据整编:基于小时数据生成天统计数据
- 月数据整编:基于天数据生成月统计数据
数据归档策略:
- 实时数据:保留最近30天实时数据
- 历史数据:长期保存历史整编数据
- 统计数据:保存各类统计数据
4.6.3 数据应用流程
业务数据应用
预报数据应用:
- 气象预报数据:GRIB2文件处理和网格化展示
- 洪水预报数据:基于水文模型的洪水预测
- 预警数据应用:基于阈值的预警信息发布
管理数据应用:
- 考核数据管理:
AssessTaskService考核任务管理 - 防治对象管理:
PrePlaceService防治点管理 - 维护管理:
MentencePlanService维护计划管理
对外数据共享
数据接口服务:
- REST API:标准化的数据访问接口
- 文件导出:Excel、PDF等格式数据导出
- 实时推送:WebSocket实时数据推送
数据安全保障:
- 访问控制:基于权限的数据访问
- 数据脱敏:敏感信息脱敏处理
- 审计日志:数据访问日志记录
4.7 技术路线
4.7.1 微服务架构
服务拆分策略
业务模块化:
- 按业务领域划分:预报、预警、预演、预案
- 按数据类型划分:监测数据、管理数据、统计数据
- 按用户角色划分:管理员、县级用户、普通用户
技术组件化:
- 数据同步组件:
DataTaskHsz定时任务组件 - 预警处理组件:
MessageCenterService预警消息组件 - 预报计算组件:
ForecastService气象预报组件
服务治理机制
服务注册发现:
- Spring Boot原生服务注册
- 配置中心:多环境配置管理
- 健康检查:服务健康状态监控
服务间通信:
- HTTP REST:同步服务调用
- 异步消息:基于消息队列的异步处理
- 事件驱动:基于事件的松耦合架构
4.7.2 云计算技术
云平台部署
政务云集成:
- 省政务云水利专区部署
- 专属云平台和云产品
- 独立物理机房安全保障
容器化部署:
- Docker容器化部署
- docker-compose服务编排
- 持续集成和持续部署
云原生技术
微服务支持:
- Spring Boot 3.x微服务框架
- 云原生配置管理
- 弹性伸缩和负载均衡
DevOps实践:
- 自动化构建:Maven构建工具
- 自动化测试:JUnit单元测试
- 自动化部署:容器化部署脚本
4.8 接口设计
4.8.1 用户接口设计
REST API接口
接口标准化:
- RESTful设计:符合REST架构风格
- 统一响应格式:JSON格式标准化响应
- 错误处理:统一的异常处理机制
API文档管理:
@OpenAPIDefinition(
servers = {
@Server(url = "http://localhost:24105/gunshiApp/hsz", description = "本地测试环境"),
@Server(url = "http://local.gunshiiot.com:18083/gunshiApp/hsz", description = "线上测试环境")
}
)
接口分组管理:
- 按业务模块分组:预报、预警、管理、系统
- 按用户角色分组:管理员、县级用户、普通用户
- 按功能类型分组:查询接口、管理接口、统计接口
前端集成接口
数据查询接口:
- 实时数据查询:
/api/realtime/data - 历史数据查询:
/api/history/data - 统计数据查询:
/api/statistics/data
业务操作接口:
- 预警发布接口:
/api/warning/publish - 考核管理接口:
api/assessment/manage - 系统管理接口:
/api/system/manage
4.8.2 外部接口设计
气象数据接口
GRIB2数据获取:
@Value("${shqxjsCloudowrCnPath}")
private String shqxjsCloudowrCnPath;
数据处理流程:
- 文件获取:从气象服务器获取GRIB2文件
- 数据解析:解析气象网格数据
- 结果计算:计算面雨量和预报结果
水文数据接口
荆楚水库API:
@Value("${jcskPath}")
private String jcskPath; // 荆楚水库API路径
@Value("${jcskToken}")
private String jcskToken; // API访问令牌
数据同步机制:
- Token认证:API访问安全认证
- IP白名单:访问IP地址控制
- 重试机制:网络异常重试处理
4.8.3 内部接口设计
服务层接口
业务服务接口:
- 预报服务:
ForecastService气象预报服务 - 预警服务:
MessageCenterService预警消息服务 - 考核服务:
AssessTaskService考核任务服务
数据服务接口:
- 实时数据服务:
StPptnRRealService实时数据服务 - 历史数据服务:
StPptnRService历史数据服务 - 统计数据服务:各种统计数据服务
数据访问接口
Mapper接口设计:
- 基础CRUD:继承
BaseMapper基础操作 - 自定义查询:复杂业务查询方法
- 动态SQL:基于条件的动态查询构建
缓存接口设计:
- 查询缓存:
@Cacheable查询结果缓存 - 更新缓存:
@CacheEvict缓存更新和清除 - 分布式缓存:Redis分布式缓存支持
第5章 功能设计
5.1 梳理集成基础数据
5.1.1 设计思路
为梳理集成完整的、准确的、权威的湖北山洪灾害基础数据,需对基础数据进行全量调研和评估,分析其质量、完整性、准确性,识别可能存在的数据缺失、错误或不一致等问题。
数据质量评估体系
数据完整性评估:
- 必填字段检查:确保关键字段不为空
- 数据范围验证:验证数据在合理范围内
- 时间连续性检查:确保时间序列数据的连续性
数据准确性评估:
- 数据一致性检查:跨表数据一致性验证
- 业务逻辑验证:基于业务规则的逻辑验证
- 异常值检测:识别和处理异常数据
数据权威性评估:
- 数据来源确认:确认数据来源的权威性
- 数据更新机制:确保数据的及时更新
- 数据版本管理:维护数据的历史版本
5.1.2 防治对象调查评价成果集成
调查评价成果数据管理
防治对象数据模型:
// 防治点实体模型
public class PrePlace {
private Long id;
private String placeName; // 防治点名称
private String placeCode; // 防治点编码
private String placeType; // 防治点类型
private String location; // 地理位置
private String riskLevel; // 风险等级
// ... 其他字段
}
防治部位详细管理:
// 防治部位实体模型
public class PrePlaceDetail {
private Long id;
private Long placeId; // 关联防治点ID
private String detailName; // 部位名称
private String detailType; // 部位类型
private String status; // 状态
// ... 其他字段
}
成果数据集成实现
调查评价成果报告管理:
- 文档存储:基于MinIO的对象存储
- 元数据管理:文档的基本信息和分类
- 版本控制:文档版本管理和历史追踪
图集管理系统:
- 图像存储:防治对象相关图像存储
- 空间关联:图像与防治对象的空间关联
- 展示管理:图集的在线展示和查询
成果数据管理:
- 电子数据:结构化数据存储和管理
- 纸质数据:纸质文档的数字化管理
- 照片数据:相关照片的存储和管理
5.1.3 风险隐患调查与影响分析成果集成
风险隐患数据模型设计
风险隐患要素数据:
// 风险隐患要素实体
public class RiskHazard {
private Long id;
private String hazardCode; // 隐患编码
private String hazardType; // 隐患类型
private String hazardName; // 隐患名称
private String location; // 位置信息
private String riskLevel; // 风险等级
private Geometry geometry; // 空间几何信息
// ... 其他字段
}
断面数据管理:
// 断面数据实体
public class SectionData {
private Long id;
private String sectionCode; // 断面编码
private String sectionName; // 断面名称
private String riverCode; // 河流编码
private BigDecimal elevation; // 高程
private Geometry sectionLine; // 断面线几何
// ... 其他字段
}
成果报表管理实现
重点关注对象详查名录表:
- 对象管理:重点防治对象的详细信息管理
- 风险评估:对象风险评估和等级划分
- 监测关联:与监测设备的关联管理
防治对象-监测设备关系表:
- 关系映射:防治对象与监测设备的对应关系
- 设备信息:监测设备的基本信息和状态
- 数据关联:监测数据与防治对象的关联
山洪灾害防治对象名录:
- 名录管理:防治对象的统一名录管理
- 分类管理:按类型、区域等分类管理
- 状态管理:防治对象的状态跟踪
跨沟道路、桥涵、塘(堰)坝调查成果表:
- 设施管理:跨沟设施的管理和维护
- 安全评估:设施安全状况评估
- 风险分析:设施对山洪的影响分析
5.1.4 数据治理入库和应用集成
数据治理流程设计
数据提取阶段:
- 多源数据采集:从不同数据源提取原始数据
- 数据格式转换:统一数据格式和编码
- 数据质量检查:初步的数据质量评估
数据清洗阶段:
- 异常数据处理:识别和处理异常数据
- 重复数据去重:基于业务规则的去重处理
- 数据标准化:统一数据标准和规范
数据整合阶段:
- 数据关联:建立数据间的关联关系
- 数据融合:多源数据的融合处理
- 数据验证:业务逻辑验证和一致性检查
数据转换阶段:
- 数据映射:源数据到目标数据的映射
- 数据计算:派生数据的计算和生成
- 数据聚合:数据的汇总和聚合处理
数据解耦和重组阶段:
- 数据分层:按业务需求进行数据分层
- 数据分区:按时间和区域进行数据分区
- 数据索引:建立高效的数据索引
数据入库阶段:
- 批量导入:高效的数据批量导入
- 事务管理:确保数据导入的事务一致性
- 完整性检查:数据完整性和一致性验证
数据治理服务实现
数据质量监控服务:
@Service
public class DataQualityService {
public DataQualityReport checkDataQuality(String dataType) {
// 数据质量检查逻辑
return qualityReport;
}
public List<DataAnomaly> detectAnomalies(String dataset) {
// 异常数据检测逻辑
return anomalyList;
}
}
数据标准化服务:
@Service
public class DataStandardizationService {
public StandardizedData standardizeData(RawData rawData) {
// 数据标准化处理逻辑
return standardizedData;
}
public ValidationResult validateStandards(StandardizedData data) {
// 标准验证逻辑
return validationResult;
}
}
5.1.5 小流域治理单元建档立卡
小流域基础信息管理
小流域治理单元数据模型:
// 小流域治理单元实体
public class WatershedUnit {
private Long id;
private String unitCode; // 单元编码
private String unitName; // 单元名称
private String area; // 流域面积
private String riverLength; // 河流长度
private String avgElevation; // 平均高程
private Geometry boundary; // 流域边界
// ... 其他字段
}
基础信息梳理功能:
- 全省1309个小流域治理单元基础信息管理
- 流域特征参数计算和管理
- 空间拓扑关系建立和维护
监测站点信息集成
雨量(水位)站点信息管理:
// 监测站点实体
public class MonitoringStation {
private Long id;
private String stationCode; // 站点编码
private String stationName; // 站点名称
private String stationType; // 站点类型
private BigDecimal longitude; // 经度
private BigDecimal latitude; // 纬度
private Geometry location; // 空间位置
// ... 其他字段
}
站点关联管理:
- 空间关联:监测站点与小流域的空间关联
- 数据关联:监测数据与小流域的数据关联
- 状态监控:监测站点运行状态监控
降雨预报成果数据集成
网格化降雨预报数据:
// 降雨预报网格数据实体
public class RainfallGrid {
private Long id;
private String gridCode; // 网格编码
private BigDecimal rainfall; // 降雨量
private String forecastTime; // 预报时间
private Integer forecastHour; // 预报小时数
private Geometry gridGeometry; // 网格几何
// ... 其他字段
}
预报成果管理功能:
- 网格数据存储和管理
- 时间序列预报数据管理
- 空间插值和计算功能
流域关系管理
流域拓扑关系建立:
@Service
public class WatershedRelationService {
public WatershedTopology buildTopology(List<WatershedUnit> units) {
// 构建流域拓扑关系
return topology;
}
public List<WatershedUnit> getUpstreamUnits(Long unitId) {
// 获取上游流域单元
return upstreamUnits;
}
public List<WatershedUnit> getDownstreamUnits(Long unitId) {
// 获取下游流域单元
return downstreamUnits;
}
}
空间分析算法:
- 河流网络提取:基于DEM数据的河流网络提取
- 流域边界识别:小流域边界的自动识别
- 拓扑关系生成:上下游关系的自动生成
5.2 算法模型建设方案
5.2.1 模型建模范围确定
小流域设计暴雨计算
暴雨参数计算模型:
@Service
public class DesignStormService {
public DesignStormResult calculateDesignStorm(String watershedCode,
int returnPeriod) {
// 基于《湖北省暴雨统计参数等值线图集》计算设计暴雨
DesignStormResult result = new DesignStormResult();
// 计算标准历时点雨量均值
BigDecimal tenMinMean = calculate10MinMean(watershedCode);
BigDecimal oneHourMean = calculate1HourMean(watershedCode);
BigDecimal sixHourMean = calculate6HourMean(watershedCode);
BigDecimal twentyFourHourMean = calculate24HourMean(watershedCode);
// 计算设计暴雨
result.setTenMinDesign(calculateDesignRainfall(tenMinMean, returnPeriod));
result.setOneHourDesign(calculateDesignRainfall(oneHourMean, returnPeriod));
result.setSixHourDesign(calculateDesignRainfall(sixHourMean, returnPeriod));
result.setTwentyFourHourDesign(calculateDesignRainfall(twentyFourHourMean, returnPeriod));
return result;
}
private BigDecimal calculateDesignRainfall(BigDecimal mean, int returnPeriod) {
// 设计暴雨计算逻辑
return mean.multiply(getFrequencyFactor(returnPeriod));
}
}
暴雨时程分配模型:
- 时程分配模式:基于典型暴雨过程的时程分配
- 时间步长处理:按小时或更小时间步长分配
- 空间分布:考虑暴雨空间分布的不均匀性
小流域设计洪水计算
净雨计算模型:
@Service
public class NetRainfallService {
public List<NetRainfall> calculateNetRainfall(DesignStormResult designStorm,
WatershedUnit watershed) {
// 净雨计算逻辑
List<NetRainfall> netRainfallList = new ArrayList<>();
// 初损计算
BigDecimal initialLoss = calculateInitialLoss(watershed);
// 下渗计算
BigDecimal infiltrationRate = calculateInfiltrationRate(watershed);
// 净雨过程计算
for (StormData stormData : designStorm.getStormData()) {
NetRainfall netRainfall = new NetRainfall();
netRainfall.setTime(stormData.getTime());
netRainfall.setGrossRainfall(stormData.getRainfall());
netRainfall.setNetRainfall(calculateNetAmount(
stormData.getRainfall(), initialLoss, infiltrationRate));
netRainfallList.add(netRainfall);
}
return netRainfallList;
}
}
单位线法洪水计算:
@Service
public class UnitHydrographService {
public FloodHydrograph calculateFloodHydrograph(List<NetRainfall> netRainfall,
WatershedUnit watershed) {
// 单位线法洪水计算
FloodHydrograph hydrograph = new FloodHydrograph();
// 获取单位线
UnitHydrograph unitHydrograph = getUnitHydrograph(watershed.getUnitCode());
// 卷积计算
List<BigDecimal> discharge = new ArrayList<>();
for (int i = 0; i < netRainfall.size(); i++) {
BigDecimal q = BigDecimal.ZERO;
for (int j = 0; j <= i; j++) {
q = q.add(netRainfall.get(j).getNetRainfall()
.multiply(unitHydrograph.getOrdinate(i - j)));
}
discharge.add(q);
}
hydrograph.setDischarge(discharge);
return hydrograph;
}
}
经验公式法洪水计算:
@Service
public class EmpiricalFormulaService {
public BigDecimal calculatePeakDischarge(WatershedUnit watershed,
int returnPeriod) {
// 经验公式法计算洪峰流量
BigDecimal area = new BigDecimal(watershed.getArea());
BigDecimal coefficient = getCoefficient(watershed, returnPeriod);
BigDecimal exponent = getExponent(watershed);
// Q = C * A^n
return coefficient.multiply(area.pow(exponent));
}
private BigDecimal getCoefficient(WatershedUnit watershed, int returnPeriod) {
// 根据水文分区和重现期获取系数
return coefficientRepository.findByWatershedAndReturnPeriod(
watershed.getHydrologicalZone(), returnPeriod);
}
}
HEC-RAS二维水动力学模型
淹没范围分析模型:
@Service
public class InundationAnalysisService {
public InundationResult analyzeInundation(WatershedUnit watershed,
FloodHydrograph hydrograph, int returnPeriod) {
// HEC-RAS二维水动力学模型调用
InundationResult result = new InundationResult();
// 模型输入准备
ModelInput input = prepareModelInput(watershed, hydrograph);
// 调用HEC-RAS模型
ModelOutput output = callHECRASModel(input);
// 结果处理
result.setInundationArea(output.getInundationArea());
result.setMaxDepth(output.getMaxDepth());
result.setInundationMap(output.getInundationMap());
result.setVelocityMap(output.getVelocityMap());
return result;
}
private ModelOutput callHECRASModel(ModelInput input) {
// 调用HEC-RAS模型的实现
// 这里可以集成外部HEC-RAS计算引擎
return hcrasEngine.run(input);
}
}
不同重现期洪水分析:
- 50年一遇洪水:中等风险洪水淹没分析
- 100年一遇洪水:高风险洪水淹没分析
- 300年一遇洪水:极高风险洪水淹没分析
5.2.2 小流域分布式水文模型精细建模
小流域计算单元划分
计算单元属性提取:
@Service
public class CalculationUnitService {
public List<CalculationUnit> divideCalculationUnits(WatershedUnit watershed) {
// 小流域计算单元划分
List<CalculationUnit> units = new ArrayList<>();
// 基于DEM数据进行单元划分
List<Subcatchment> subcatchments = extractSubcatchments(watershed);
for (Subcatchment subcatchment : subcatchments) {
CalculationUnit unit = new CalculationUnit();
unit.setUnitCode(generateUnitCode(subcatchment));
unit.setArea(subcatchment.getArea());
unit.setAvgSlope(calculateAvgSlope(subcatchment));
unit.setFlowLength(calculateFlowLength(subcatchment));
unit.setCentroid(subcatchment.getCentroid());
unit.setBoundary(subcatchment.getBoundary());
// 提取其他属性
unit.setLandUseType(extractLandUseType(subcatchment));
unit.setSoilType(extractSoilType(subcatchment));
unit.setVegetationCover(extractVegetationCover(subcatchment));
units.add(unit);
}
return units;
}
private BigDecimal calculateAvgSlope(Subcatchment subcatchment) {
// 基于DEM计算平均坡度
return demAnalyzer.calculateAvgSlope(subcatchment);
}
private BigDecimal calculateFlowLength(Subcatchment subcatchment) {
// 计算流径长度
return flowAnalyzer.calculateFlowLength(subcatchment);
}
}
小流域统一编码:
@Service
public class WatershedCodingService {
public String generateWatershedCode(WatershedUnit watershed) {
// 小流域统一编码生成
StringBuilder code = new StringBuilder();
// 省级编码
code.append("42"); // 湖北省编码
// 市级编码
code.append(String.format("%02d", watershed.getCityCode()));
// 县级编码
code.append(String.format("%02d", watershed.getCountyCode()));
// 流域编码
code.append(String.format("%03d", watershed.getRiverBasinCode()));
// 小流域编码
code.append(String.format("%04d", watershed.getUnitNumber()));
return code.toString();
}
}
面雨量权重值计算
泰森多边形权重计算:
@Service
public class ThiessenPolygonService {
public Map<String, BigDecimal> calculateThiessenWeights(
List<MonitoringStation> stations, WatershedUnit watershed) {
// 泰森多边形权重计算
Map<String, BigDecimal> weights = new HashMap<>();
// 创建泰森多边形
List<Polygon> thiessenPolygons = createThiessenPolygons(stations);
// 计算每个站点在流域内的权重
Geometry watershedBoundary = watershed.getBoundary();
for (int i = 0; i < stations.size(); i++) {
Polygon stationPolygon = thiessenPolygons.get(i);
// 计算站点多边形与流域的交集
Geometry intersection = stationPolygon.intersection(watershedBoundary);
// 计算权重
BigDecimal stationArea = new BigDecimal(intersection.getArea());
BigDecimal watershedArea = new BigDecimal(watershedBoundary.getArea());
BigDecimal weight = stationArea.divide(watershedArea, 8, RoundingMode.HALF_UP);
weights.put(stations.get(i).getStationCode(), weight);
}
return weights;
}
private List<Polygon> createThiessenPolygons(List<MonitoringStation> stations) {
// 创建泰森多边形
// 使用JTS的Voronoi图算法
GeometryFactory geometryFactory = new GeometryFactory();
// 创建站点点集
Coordinate[] coordinates = stations.stream()
.map(station -> station.getLocation().getCoordinate())
.toArray(Coordinate[]::new);
// 生成Voronoi图
VoronoiDiagramBuilder voronoiBuilder = new VoronoiDiagramBuilder();
voronoiBuilder.setSites(coordinates);
Geometry voronoiDiagram = voronoiBuilder.getDiagram(geometryFactory);
// 提取多边形
return extractPolygons(voronoiDiagram);
}
}
反距离权重插值:
@Service
public class IDWInterpolationService {
public Map<String, BigDecimal> calculateIDWWeights(
List<MonitoringStation> stations, WatershedUnit watershed) {
// 反距离权重插值
Map<String, BigDecimal> weights = new HashMap<>();
// 生成流域内网格点
List<Coordinate> gridPoints = generateGridPoints(watershed);
for (Coordinate gridPoint : gridPoints) {
BigDecimal totalWeight = BigDecimal.ZERO;
BigDecimal weightedRainfall = BigDecimal.ZERO;
// 计算每个站点对网格点的权重
for (MonitoringStation station : stations) {
BigDecimal distance = calculateDistance(gridPoint,
station.getLocation().getCoordinate());
// 避免除零错误
if (distance.compareTo(BigDecimal.ZERO) == 0) {
distance = new BigDecimal("0.0001");
}
// 权重 = 1 / distance^2
BigDecimal weight = BigDecimal.ONE.divide(
distance.pow(2), 8, RoundingMode.HALF_UP);
totalWeight = totalWeight.add(weight);
weightedRainfall = weightedRainfall.add(
weight.multiply(station.getCurrentRainfall()));
}
// 计算网格点降雨量
BigDecimal gridRainfall = weightedRainfall.divide(totalWeight,
2, RoundingMode.HALF_UP);
weights.put(getGridPointCode(gridPoint), gridRainfall);
}
return weights;
}
}
蒸散发量计算
潜在蒸散发计算:
@Service
public class EvapotranspirationService {
public BigDecimal calculatePET(EtData data) {
// 潜在蒸散发计算(Penman-Monteith方程)
BigDecimal delta = calculateSlopeVaporPressure(data.getTemperature());
BigDecimal gamma = calculatePsychrometricConstant(data.getPressure());
BigDecimal u2 = data.getWindSpeed();
BigDecimal es = calculateSaturationVaporPressure(data.getTemperature());
BigDecimal ea = calculateActualVaporPressure(data.getTemperature(),
data.getRelativeHumidity());
BigDecimal rn = data.getNetRadiation();
BigDecimal g = data.getSoilHeatFlux();
// Penman-Monteith方程
BigDecimal numerator = delta.multiply(rn.subtract(g))
.add(K_CONSTANT.multiply(rho_AIR.multiply(CP_AIR).multiply(u2)
.multiply(es.subtract(ea))));
BigDecimal denominator = delta.add(gamma.multiply(
BigDecimal.ONE.add(C_D_CONSTANT.multiply(u2))));
return numerator.divide(denominator, 2, RoundingMode.HALF_UP);
}
private BigDecimal calculateSlopeVaporPressure(BigDecimal temperature) {
// 饱和水汽压斜率计算
BigDecimal temp = temperature.add(BigDecimal.valueOf(237.3));
BigDecimal numerator = BigDecimal.valueOf(4098).multiply(
BigDecimal.valueOf(0.6108).multiply(
BigDecimal.valueOf(17.27).multiply(temperature).divide(temp,
8, RoundingMode.HALF_UP).exp()));
BigDecimal denominator = temp.pow(2);
return numerator.divide(denominator, 8, RoundingMode.HALF_UP);
}
}
实际蒸散发计算:
public BigDecimal calculateAET(BigDecimal pet, BigDecimal soilMoisture,
BigDecimal fieldCapacity) {
// 实际蒸散发计算
BigDecimal moistureRatio = soilMoisture.divide(fieldCapacity,
8, RoundingMode.HALF_UP);
if (moistureRatio.compareTo(BigDecimal.ONE) >= 0) {
return pet; // 土壤水分充足,实际蒸散发等于潜在蒸散发
} else {
// 土壤水分不足,按比例减少
return pet.multiply(moistureRatio);
}
}
产流模型参数确定
SCS-CN产流模型:
@Service
public class SCSModelService {
public BigDecimal calculateSCSRunoff(BigDecimal rainfall,
BigDecimal cn, BigDecimal initialAbstraction) {
// SCS-CN产流模型
BigDecimal s = BigDecimal.valueOf(25400).divide(cn,
8, RoundingMode.HALF_UP).subtract(BigDecimal.valueOf(254));
BigDecimal ia = initialAbstraction.multiply(s);
if (rainfall.compareTo(ia) <= 0) {
return BigDecimal.ZERO; // 降雨小于初损,无产流
}
BigDecimal numerator = rainfall.subtract(ia).pow(2);
BigDecimal denominator = rainfall.subtract(ia).add(s);
return numerator.divide(denominator, 2, RoundingMode.HALF_UP);
}
public BigDecimal calculateCNValue(LandUseType landUse, SoilType soil,
BigDecimal antecedentMoisture) {
// CN值计算
// 基于土地利用类型、土壤类型和前期湿度条件
return cnTableRepository.findByLandUseAndSoil(landUse, soil, antecedentMoisture);
}
}
Green-Ampt渗透模型:
@Service
public class GreenAmptService {
public BigDecimal calculateInfiltration(BigDecimal time, BigDecimal initialMoisture,
BigDecimal saturatedMoisture, BigDecimal hydraulicConductivity,
BigDecimal suctionHead, BigDecimal cumulativeInfiltration) {
// Green-Ampt渗透模型
BigDecimal thetaS = saturatedMoisture;
BigDecimal thetaI = initialMoisture;
BigDecimal deltaTheta = thetaS.subtract(thetaI);
BigDecimal Ks = hydraulicConductivity;
BigDecimal psi = suctionHead;
BigDecimal F = cumulativeInfiltration;
// Green-Ampt方程
BigDecimal numerator = Ks.multiply(time).multiply(deltaTheta).multiply(psi).add(F);
BigDecimal denominator = F.add(Ks.multiply(time).multiply(deltaTheta));
BigDecimal newF = numerator.divide(denominator, 8, RoundingMode.HALF_UP);
return newF.subtract(F); // 当前时段渗透量
}
}
单位线提取
瞬时单位线计算:
@Service
public class InstantaneousUnitHydrographService {
public List<BigDecimal> calculateIUH(WatershedUnit watershed,
List<CalculationUnit> units) {
// 瞬时单位线计算
List<BigDecimal> iuh = new ArrayList<>();
// 计算流域特征参数
BigDecimal avgSlope = calculateAvgSlope(units);
BigDecimal avgFlowLength = calculateAvgFlowLength(units);
BigDecimal avgVelocity = calculateAvgVelocity(avgSlope);
// 计算汇流时间
BigDecimal tc = avgFlowLength.divide(avgVelocity,
8, RoundingMode.HALF_UP);
// Nash瞬时单位线模型
int n = 2; // 线性水库数
BigDecimal k = tc.divide(BigDecimal.valueOf(n),
8, RoundingMode.HALF_UP); // 水库蓄量常数
// 生成单位线纵坐标
for (int t = 0; t < 100; t++) {
BigDecimal ordinate = calculateNashIUHOrdinate(t, n, k);
iuh.add(ordinate);
}
return iuh;
}
private BigDecimal calculateNashIUHOrdinate(int t, int n, BigDecimal k) {
// Nash瞬时单位线纵坐标计算
if (t == 0) return BigDecimal.ZERO;
BigDecimal numerator = BigDecimal.ONE.pow(n - 1);
BigDecimal denominator = BigDecimal.valueOf(factorial(n - 1))
.multiply(k.pow(n));
BigDecimal timeTerm = BigDecimal.valueOf(t).pow(n - 1);
BigDecimal expTerm = BigDecimal.valueOf(-t).divide(k,
8, RoundingMode.HALF_UP).exp();
return numerator.multiply(timeTerm).multiply(expTerm).divide(denominator,
8, RoundingMode.HALF_UP);
}
}
河道演进模型参数确定
马斯京根法河道演进:
@Service
public class MuskingumRoutingService {
public List<BigDecimal> routeFloodWave(List<BigDecimal> inflow,
BigDecimal k, BigDecimal x, BigDecimal dt) {
// 马斯京根法河道演进
List<BigDecimal> outflow = new ArrayList<>();
// 计算演进系数
BigDecimal c0 = calculateC0(k, x, dt);
BigDecimal c1 = calculateC1(k, x, dt);
BigDecimal c2 = calculateC2(k, x, dt);
// 初始条件
outflow.add(inflow.get(0)); // 假设初始出流等于入流
// 演进计算
for (int i = 1; i < inflow.size(); i++) {
BigDecimal qOut = c0.multiply(inflow.get(i))
.add(c1.multiply(inflow.get(i - 1)))
.add(c2.multiply(outflow.get(i - 1)));
outflow.add(qOut);
}
return outflow;
}
private BigDecimal calculateC0(BigDecimal k, BigDecimal x, BigDecimal dt) {
BigDecimal denominator = k.multiply(BigDecimal.valueOf(2).multiply(x).subtract(BigDecimal.ONE))
.add(dt);
return dt.subtract(k.multiply(x)).divide(denominator,
8, RoundingMode.HALF_UP);
}
private BigDecimal calculateC1(BigDecimal k, BigDecimal x, BigDecimal dt) {
BigDecimal denominator = k.multiply(BigDecimal.valueOf(2).multiply(x).subtract(BigDecimal.ONE))
.add(dt);
return dt.add(k.multiply(x)).divide(denominator,
8, RoundingMode.HALF_UP);
}
private BigDecimal calculateC2(BigDecimal k, BigDecimal x, BigDecimal dt) {
BigDecimal denominator = k.multiply(BigDecimal.valueOf(2).multiply(x).subtract(BigDecimal.ONE))
.add(dt);
return BigDecimal.ONE.subtract(denominator).divide(denominator,
8, RoundingMode.HALF_UP);
}
}
5.3 预警功能设计
5.3.1 动态预警指标设计
预警规则配置模型:
// 预警规则实体
public class OsmoticWarnRule {
private Long id;
private String ruleName; // 规则名称
private String ruleType; // 规则类型:1-渗压,2-渗流,3-位移
private String deviceCode; // 设备编码
private BigDecimal threshold1; // 一级阈值
private BigDecimal threshold2; // 二级阈值
private BigDecimal threshold3; // 三级阈值
private String logicRelation; // 逻辑关系:AND/OR
private Integer status; // 状态:0-禁用,1-启用
// ... 其他字段
}
预警条件判断算法:
@Service
public class WarningRuleService {
public WarningResult evaluateWarningRules(List<OsmoticWarnRule> rules,
Map<String, BigDecimal> sensorData) {
WarningResult result = new WarningResult();
List<WarningEvent> events = new ArrayList<>();
for (OsmoticWarnRule rule : rules) {
if (rule.getStatus() == 0) continue; // 跳过禁用规则
BigDecimal currentValue = sensorData.get(rule.getDeviceCode());
if (currentValue == null) continue;
// 评估预警级别
int level = evaluateWarningLevel(rule, currentValue);
if (level > 0) {
WarningEvent event = new WarningEvent();
event.setRuleId(rule.getId());
event.setRuleName(rule.getRuleName());
event.setLevel(level);
event.setCurrentValue(currentValue);
event.setThreshold(getThresholdForLevel(rule, level));
event.setTimestamp(LocalDateTime.now());
events.add(event);
}
}
result.setEvents(events);
result.setHasWarning(!events.isEmpty());
return result;
}
private int evaluateWarningLevel(OsmoticWarnRule rule, BigDecimal value) {
if (rule.getThreshold3() != null && value.compareTo(rule.getThreshold3()) > 0) {
return 3; // 三级预警
} else if (rule.getThreshold2() != null && value.compareTo(rule.getThreshold2()) > 0) {
return 2; // 二级预警
} else if (rule.getThreshold1() != null && value.compareTo(rule.getThreshold1()) > 0) {
return 1; // 一级预警
}
return 0; // 无预警
}
}
5.3.2 预警发布系统设计
预警消息管理:
@Service
public class MessageCenterService {
public void publishWaterLevelWarning(List<StRsvrR> waterLevelData) {
// 水位预警发布
for (StRsvrR data : waterLevelData) {
// 检查水位预警条件
if (checkWaterLevelWarning(data)) {
MessageCenter message = new MessageCenter();
message.setTitle("水位预警");
message.setContent(String.format("%s水库水位预警:当前水位%.2fm,超过警戒水位",
data.getStnm(), data.getRz()));
message.setWarningLevel(calculateWarningLevel(data));
message.setStationCode(data.getStcd());
message.setCreateTime(LocalDateTime.now());
message.setStatus(0); // 未读状态
// 保存预警消息
save(message);
// 推送给相关用户
pushToUsers(message);
}
}
}
public void publishOsmoticWarning(OsmoticWarnR warnData, String description) {
// 渗压预警发布
MessageCenter message = new MessageCenter();
message.setTitle("渗压预警");
message.setContent(String.format("%s渗压预警:%s",
warnData.getDeviceName(), description));
message.setWarningLevel(warnData.getWarningLevel());
message.setDeviceCode(warnData.getDeviceCode());
message.setCreateTime(LocalDateTime.now());
message.setStatus(0);
save(message);
pushToUsers(message);
}
}
用户推送机制:
@Service
public class UserPushService {
public void pushToUsers(MessageCenter message) {
// 根据预警级别和用户角色推送消息
List<User> targetUsers = getTargetUsers(message);
for (User user : targetUsers) {
// 创建用户消息记录
UserMessage userMessage = new UserMessage();
userMessage.setUserId(user.getId());
userMessage.setMessageId(message.getId());
userMessage.setReadStatus(0); // 未读状态
userMessage.setPushTime(LocalDateTime.now());
userMessageRepository.save(userMessage);
// 实时推送(WebSocket或其他推送机制)
if (user.isOnline()) {
pushRealTimeNotification(user, message);
}
}
}
private List<User> getTargetUsers(MessageCenter message) {
// 根据预警级别确定目标用户
switch (message.getWarningLevel()) {
case 3: // 三级预警(最高级别)
return userRepository.findByRoleIn(Arrays.asList("ADMIN", "COUNTY_MANAGER"));
case 2: // 二级预警
return userRepository.findByRole("COUNTY_MANAGER");
case 1: // 一级预警
return userRepository.findByRoleIn(Arrays.asList("COUNTY_MANAGER", "FIELD_STAFF"));
default:
return Collections.emptyList();
}
}
}
5.3.3 预警统计分析
预警统计服务:
@Service
public class WarningStatisticsService {
public WarningStatistics getMonthlyStatistics(int year, int month) {
// 月度预警统计
WarningStatistics stats = new WarningStatistics();
// 查询当月预警数据
List<MessageCenter> warnings = messageCenterRepository
.findByYearAndMonth(year, month);
// 按类型统计
stats.setWaterLevelCount(warnings.stream()
.filter(w -> "水位预警".equals(w.getTitle()))
.count());
stats.setOsmoticCount(warnings.stream()
.filter(w -> "渗压预警".equals(w.getTitle()))
.count());
// 按级别统计
stats.setLevel1Count(warnings.stream()
.filter(w -> w.getWarningLevel() == 1)
.count());
stats.setLevel2Count(warnings.stream()
.filter(w -> w.getWarningLevel() == 2)
.count());
stats.setLevel3Count(warnings.stream()
.filter(w -> w.getWarningLevel() == 3)
.count());
return stats;
}
public List<WarningTrend> getWarningTrend(int days) {
// 预警趋势分析
List<WarningTrend> trends = new ArrayList<>();
LocalDate endDate = LocalDate.now();
LocalDate startDate = endDate.minusDays(days);
for (LocalDate date = startDate; date.isBefore(endDate); date = date.plusDays(1)) {
WarningTrend trend = new WarningTrend();
trend.setDate(date);
trend.setCount(messageCenterRepository.countByDate(date));
trends.add(trend);
}
return trends;
}
}
5.4 县级用户功能设计
5.4.1 考核管理系统
考核任务工作流程:
@Service
public class AssessTaskService {
public AssessTask createTask(AssessTaskDTO dto) {
// 创建考核任务
AssessTask task = new AssessTask();
BeanUtils.copyProperties(dto, task);
task.setStatus(0); // 未启动状态
task.setCreateTime(LocalDateTime.now());
// 分配考核对象
List<AssessObject> objects = assessObjectRepository.findByRegion(dto.getRegion());
task.setAssessObjects(objects);
// 设置考核指标
List<AssessIndicator> indicators = assessIndicatorRepository.findByTaskType(dto.getTaskType());
task.setIndicators(indicators);
return assessTaskRepository.save(task);
}
@Transactional
public String startTask(Long taskId) {
// 启动考核任务
AssessTask task = assessTaskRepository.findById(taskId)
.orElseThrow(() -> new RuntimeException("任务不存在"));
if (task.getStatus() != 0) {
throw new RuntimeException("任务状态不允许启动");
}
task.setStatus(1); // 进行中状态
task.setStartTime(LocalDateTime.now());
// 通知考核对象
notifyAssessObjects(task);
assessTaskRepository.save(task);
return "任务启动成功";
}
public List<AssessTask> getPendingTasks(Long userId) {
// 获取用户待办任务
User user = userRepository.findById(userId)
.orElseThrow(() -> new RuntimeException("用户不存在"));
return assessTaskRepository.findByAssessorAndStatus(user, 1);
}
public List<AssessResultVo> getResult(Long taskId) {
// 获取考核结果
AssessTask task = assessTaskRepository.findById(taskId)
.orElseThrow(() -> new RuntimeException("任务不存在"));
List<AssessResult> results = assessResultRepository.findByTaskId(taskId);
return results.stream().map(result -> {
AssessResultVo vo = new AssessResultVo();
vo.setObjectName(result.getObjectName());
vo.setIndicatorName(result.getIndicatorName());
vo.setScore(result.getScore());
vo.setComment(result.getComment());
return vo;
}).collect(Collectors.toList());
}
}
考核对象管理:
@Service
public class AssessObjectService {
public List<AssessObject> getObjectsByRegion(String region) {
// 按区域获取考核对象
return assessObjectRepository.findByRegion(region);
}
public List<AssessObject> getObjectsByType(String objectType) {
// 按类型获取考核对象
return assessObjectRepository.findByObjectType(objectType);
}
public void assignToTask(Long taskId, List<Long> objectIds) {
// 分配考核对象到任务
AssessTask task = assessTaskRepository.findById(taskId)
.orElseThrow(() -> new RuntimeException("任务不存在"));
List<AssessObject> objects = assessObjectRepository.findByIdIn(objectIds);
task.setAssessObjects(objects);
assessTaskRepository.save(task);
}
}
5.4.2 权限管理系统
基于角色的权限控制:
@Service
public class PermissionService {
public boolean hasPermission(Long userId, String permission) {
// 检查用户权限
User user = userRepository.findById(userId)
.orElseThrow(() -> new RuntimeException("用户不存在"));
return user.getRoles().stream()
.flatMap(role -> role.getPermissions().stream())
.anyMatch(p -> p.getCode().equals(permission));
}
public List<String> getUserPermissions(Long userId) {
// 获取用户权限列表
User user = userRepository.findById(userId)
.orElseThrow(() -> new RuntimeException("用户不存在"));
return user.getRoles().stream()
.flatMap(role -> role.getPermissions().stream())
.map(Permission::getCode)
.distinct()
.collect(Collectors.toList());
}
}
5.5 系统改进功能
5.5.1 防治点管理
防治点树形结构管理:
@Service
public class PrePlaceService {
public List<PrePlaceTreeVo> getPlaceTree() {
// 获取防治点树形结构
List<PrePlace> places = prePlaceRepository.findAllByOrderByParentIdAsc();
return buildTree(places, null);
}
private List<PrePlaceTreeVo> buildTree(List<PrePlace> places, Long parentId) {
List<PrePlaceTreeVo> tree = new ArrayList<>();
for (PrePlace place : places) {
if ((parentId == null && place.getParentId() == null) ||
(parentId != null && parentId.equals(place.getParentId()))) {
PrePlaceTreeVo vo = new PrePlaceTreeVo();
vo.setId(place.getId());
vo.setName(place.getPlaceName());
vo.setCode(place.getPlaceCode());
vo.setType(place.getPlaceType());
vo.setChildren(buildTree(places, place.getId()));
tree.add(vo);
}
}
return tree;
}
public List<PrePlaceDetail> getPlaceDetails(Long placeId) {
// 获取防治点详细信息
return prePlaceDetailRepository.findByPlaceId(placeId);
}
}
5.5.2 维护管理功能
维护计划管理:
@Service
public class MentenancePlanService {
public MentenancePlan createAnnualPlan(MentenancePlanDTO dto) {
// 创建年度维护计划
MentenancePlan plan = new MentenancePlan();
BeanUtils.copyProperties(dto, plan);
plan.setStatus(0); // 未启动状态
plan.setCreateTime(LocalDateTime.now());
// 创建维护详情
List<MentencePlanDetail> details = dto.getDetails().stream()
.map(detailDto -> {
MentenancePlanDetail detail = new MentenancePlanDetail();
BeanUtils.copyProperties(detailDto, detail);
detail.setPlan(plan);
return detail;
})
.collect(Collectors.toList());
plan.setDetails(details);
return mentenancePlanRepository.save(plan);
}
public void updatePlanStatus(Long planId, Integer status) {
// 更新计划状态
MentenancePlan plan = mentenancePlanRepository.findById(planId)
.orElseThrow(() -> new RuntimeException("计划不存在"));
plan.setStatus(status);
if (status == 1) {
plan.setStartTime(LocalDateTime.now());
} else if (status == 2) {
plan.setEndTime(LocalDateTime.now());
}
mentenancePlanRepository.save(plan);
}
}
这些功能设计完整地覆盖了黑石咀水库系统的核心业务需求,包括基础数据管理、算法模型建设、预警功能、县级用户管理和系统改进功能,为系统的开发和实施提供了详细的技术指导。