1782 lines
65 KiB
Markdown
1782 lines
65 KiB
Markdown
# 智慧水务管理系统 — 详细设计规格书
|
||
|
||
> 版本:v2.0 | 日期:2026-06-14 | 作者:bot_pm
|
||
> 基于:requirements.md (需求) + architecture.md (架构)
|
||
> 用途:直接指导开发实现,每个 Issue 标注对应章节
|
||
|
||
---
|
||
|
||
## 第1章 项目框架与基础设施
|
||
|
||
### 1.1 Maven 模块结构
|
||
|
||
```
|
||
water-management-system/
|
||
├── pom.xml # 父 POM (Spring Boot 3.x + Cloud Alibaba 2024.x)
|
||
├── wm-common/ # 公共模块
|
||
│ └── src/main/java/com/water/common/
|
||
│ ├── core/
|
||
│ │ ├── result/R.java # 统一响应
|
||
│ │ ├── exception/BizException.java # 业务异常
|
||
│ │ ├── exception/GlobalExceptionHandler.java
|
||
│ │ └── constant/ErrorCode.java # 错误码枚举
|
||
│ ├── web/
|
||
│ │ ├── config/WebMvcConfig.java
|
||
│ │ └── interceptor/AuthInterceptor.java
|
||
│ └── util/
|
||
│ ├── FileUtil.java
|
||
│ ├── CaptchaUtil.java
|
||
│ └── DictUtil.java
|
||
├── wm-base/ # 基础服务 (8081)
|
||
│ └── src/main/java/com/water/base/
|
||
│ ├── controller/ # UserController, RoleController, DeptController...
|
||
│ ├── service/ # UserService, RoleService, DeptService...
|
||
│ ├── mapper/ # MyBatis-Plus Mapper
|
||
│ └── entity/ # SysUser, SysRole, SysDept, SysMenu, SysLog...
|
||
├── wm-gateway/ # API 网关 (8080)
|
||
│ └── src/main/resources/
|
||
│ └── application.yml # Spring Cloud Gateway 路由配置
|
||
├── wm-iot/ # 物联网平台 (8082)
|
||
├── wm-data-engine/ # 数据引擎 (8083)
|
||
├── wm-bpm/ # 流程引擎 (8084)
|
||
├── wm-production/ # 供水生产管理 (8085)
|
||
├── wm-revenue/ # 营业收费 (8086)
|
||
├── wm-patrol/ # 巡检管理 (8087)
|
||
├── wm-bi/ # 大数据分析 (8088)
|
||
├── wm-notify/ # 消息通知 (8089)
|
||
├── wm-job/ # 定时任务 (8090)
|
||
├── frontend/ # Vue3 前端
|
||
│ └── src/
|
||
│ ├── api/ # 接口封装
|
||
│ ├── views/ # 页面
|
||
│ ├── router/ # 路由
|
||
│ ├── stores/ # Pinia
|
||
│ └── components/ # 公共组件
|
||
├── mobile/ # Flutter APP
|
||
│ └── lib/
|
||
│ ├── pages/
|
||
│ ├── services/
|
||
│ ├── models/
|
||
│ └── widgets/
|
||
├── db/
|
||
│ ├── postgresql/ # PostgreSQL DDL 脚本
|
||
│ ├── tdengine/ # TDengine 建库脚本
|
||
│ └── seed/ # 种子数据
|
||
├── docker/ # Docker Compose
|
||
└── docs/ # 文档
|
||
```
|
||
|
||
**对应 Issue**:#17 项目框架搭建
|
||
|
||
### 1.2 数据库完整 DDL
|
||
|
||
> **对应 Issue**:#18 数据库设计
|
||
|
||
#### 1.2.1 系统管理表 (wm-base)
|
||
|
||
```sql
|
||
-- 部门表
|
||
CREATE TABLE sys_dept (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
parent_id BIGINT DEFAULT 0,
|
||
dept_name VARCHAR(100) NOT NULL,
|
||
dept_type VARCHAR(30) DEFAULT 'water_company', -- water_bureau/water_company/ops
|
||
sort_order INT DEFAULT 0,
|
||
status SMALLINT DEFAULT 1, -- 1启用 0停用
|
||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
COMMENT ON TABLE sys_dept IS '部门组织架构表';
|
||
COMMENT ON COLUMN sys_dept.dept_type IS 'water_bureau(水利局)/water_company(水务公司)/ops(运维单位)';
|
||
|
||
-- 用户表
|
||
CREATE TABLE sys_user (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
dept_id BIGINT REFERENCES sys_dept(id),
|
||
username VARCHAR(50) UNIQUE NOT NULL,
|
||
password VARCHAR(255) NOT NULL, -- BCrypt 加密
|
||
real_name VARCHAR(50),
|
||
phone VARCHAR(20),
|
||
email VARCHAR(100),
|
||
role_type VARCHAR(30) DEFAULT 'operator', -- admin/leader/manager/operator/tech
|
||
status SMALLINT DEFAULT 1, -- 1启用 0停用
|
||
last_login_at TIMESTAMPTZ,
|
||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
COMMENT ON TABLE sys_user IS '系统用户表';
|
||
COMMENT ON COLUMN sys_user.role_type IS 'admin(系统管理员)/leader(分管领导)/manager(业务管理)/operator(现场运维)/tech(技术维护)';
|
||
|
||
-- 角色表
|
||
CREATE TABLE sys_role (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
role_name VARCHAR(50) UNIQUE NOT NULL,
|
||
role_key VARCHAR(50) UNIQUE NOT NULL, -- admin/supervisor/biz_manager/field_ops/tech_maintain
|
||
data_scope VARCHAR(20) DEFAULT 'DEPT', -- ALL/DEPT/SELF
|
||
description VARCHAR(200),
|
||
status SMALLINT DEFAULT 1,
|
||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 角色-菜单权限
|
||
CREATE TABLE sys_role_menu (
|
||
role_id BIGINT REFERENCES sys_role(id),
|
||
menu_id BIGINT REFERENCES sys_menu(id),
|
||
PRIMARY KEY (role_id, menu_id)
|
||
);
|
||
|
||
-- 用户-角色关联 (多角色)
|
||
CREATE TABLE sys_user_role (
|
||
user_id BIGINT REFERENCES sys_user(id),
|
||
role_id BIGINT REFERENCES sys_role(id),
|
||
PRIMARY KEY (user_id, role_id)
|
||
);
|
||
|
||
-- 菜单表
|
||
CREATE TABLE sys_menu (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
parent_id BIGINT DEFAULT 0,
|
||
menu_name VARCHAR(50) NOT NULL,
|
||
menu_type VARCHAR(20) DEFAULT 'menu', -- menu/button
|
||
path VARCHAR(200), -- 前端路由
|
||
component VARCHAR(200), -- 前端组件
|
||
icon VARCHAR(100),
|
||
permission VARCHAR(100), -- 权限标识 e.g. production:alert:confirm
|
||
sort_order INT DEFAULT 0,
|
||
visible SMALLINT DEFAULT 1,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 操作日志表
|
||
CREATE TABLE sys_log (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
user_id BIGINT,
|
||
username VARCHAR(50),
|
||
operation VARCHAR(100), -- 操作类型 e.g. LOGIN/DELETE/UPDATE
|
||
method VARCHAR(200), -- 请求方法
|
||
params TEXT, -- 请求参数 JSON
|
||
ip VARCHAR(50),
|
||
duration_ms INT, -- 执行耗时
|
||
status SMALLINT DEFAULT 1, -- 1成功 0失败
|
||
error_msg TEXT,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
CREATE INDEX idx_sys_log_user_id ON sys_log(user_id);
|
||
CREATE INDEX idx_sys_log_created_at ON sys_log(created_at);
|
||
```
|
||
|
||
#### 1.2.2 物联网设备表 (wm-iot)
|
||
|
||
```sql
|
||
-- 设备模型定义
|
||
CREATE TABLE iot_device_model (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
model_key VARCHAR(50) UNIQUE NOT NULL, -- e.g. water_meter_dn15
|
||
model_name VARCHAR(100) NOT NULL, -- DN15远传水表
|
||
vendor VARCHAR(100), -- 厂商名称
|
||
protocol VARCHAR(30) NOT NULL, -- MQTT/Modbus/CoAP/HTTP
|
||
properties JSONB NOT NULL DEFAULT '[]', -- [{key, name, unit, data_type, range_min, range_max}]
|
||
commands JSONB DEFAULT '[]', -- [{key, name, params:[{key,type,required}]}]
|
||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 协议适配器配置
|
||
CREATE TABLE iot_protocol_adapter (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
adapter_key VARCHAR(30) UNIQUE NOT NULL, -- mqtt/modbus/coap/http
|
||
adapter_name VARCHAR(50) NOT NULL,
|
||
config JSONB NOT NULL DEFAULT '{}', -- 连接参数 e.g. {host, port, keepalive}
|
||
enabled SMALLINT DEFAULT 1,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 设备实例
|
||
CREATE TABLE iot_device (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
device_sn VARCHAR(100) UNIQUE NOT NULL, -- 设备序列号
|
||
device_name VARCHAR(200) NOT NULL,
|
||
model_id BIGINT REFERENCES iot_device_model(id),
|
||
device_type VARCHAR(30) NOT NULL, -- flow_meter/pressure/valve/water_quality/level
|
||
position_type VARCHAR(30), -- water_plant/pressure_station/pipe_network/village
|
||
area VARCHAR(50) NOT NULL, -- 一体化水厂/精芒片区/八家户片区/托里片区/大镇阿合其/托托片区
|
||
station_id BIGINT, -- 所属站点
|
||
loc_lng DOUBLE PRECISION, -- 经度
|
||
loc_lat DOUBLE PRECISION, -- 纬度
|
||
geom GEOMETRY(Point, 4326), -- PostGIS 空间坐标
|
||
status VARCHAR(20) DEFAULT 'offline', -- online/offline/maintenance/fault
|
||
firmware_ver VARCHAR(30),
|
||
last_report_at TIMESTAMPTZ,
|
||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
CREATE INDEX idx_iot_device_area ON iot_device(area);
|
||
CREATE INDEX idx_iot_device_type ON iot_device(device_type);
|
||
CREATE INDEX idx_iot_device_status ON iot_device(status);
|
||
CREATE INDEX idx_iot_device_geom ON iot_device USING GIST(geom);
|
||
|
||
-- 设备遥测数据 (实时缓存表,最终入TDengine)
|
||
CREATE TABLE iot_device_telemetry (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
device_id BIGINT REFERENCES iot_device(id),
|
||
device_sn VARCHAR(100) NOT NULL,
|
||
metric_key VARCHAR(50) NOT NULL, -- flow_rate/pressure/turbidity/ph/chlorine/level...
|
||
metric_value DOUBLE PRECISION,
|
||
reported_at TIMESTAMPTZ NOT NULL,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
CREATE INDEX idx_iot_telemetry_device ON iot_device_telemetry(device_sn, metric_key, reported_at);
|
||
|
||
-- 设备影子 (Redis 为主,PostgreSQL 为灾备持久化)
|
||
CREATE TABLE iot_device_shadow (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
device_sn VARCHAR(100) UNIQUE NOT NULL,
|
||
reported_state JSONB DEFAULT '{}', -- 设备上报的最新状态
|
||
desired_state JSONB DEFAULT '{}', -- 期望状态(待下发)
|
||
version BIGINT DEFAULT 1, -- 乐观锁版本号
|
||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- OTA 固件版本
|
||
CREATE TABLE iot_firmware (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
model_key VARCHAR(50) NOT NULL,
|
||
version VARCHAR(30) NOT NULL,
|
||
file_url VARCHAR(500) NOT NULL, -- MinIO 存储路径
|
||
file_size BIGINT,
|
||
checksum VARCHAR(64), -- SHA256
|
||
changelog TEXT,
|
||
status VARCHAR(20) DEFAULT 'draft', -- draft/published/deprecated
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- OTA 升级任务
|
||
CREATE TABLE iot_ota_task (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
firmware_id BIGINT REFERENCES iot_firmware(id),
|
||
device_sn VARCHAR(100) NOT NULL,
|
||
status VARCHAR(20) DEFAULT 'pending', -- pending/downloading/installing/success/failed
|
||
progress SMALLINT DEFAULT 0, -- 0-100
|
||
error_msg TEXT,
|
||
started_at TIMESTAMPTZ,
|
||
completed_at TIMESTAMPTZ,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
```
|
||
|
||
#### 1.2.3 时序数据库 (TDengine)
|
||
|
||
```sql
|
||
-- 超级表:设备遥测时序数据
|
||
CREATE STABLE iot_telemetry (
|
||
ts TIMESTAMP,
|
||
device_sn NCHAR(100),
|
||
metric_key NCHAR(50),
|
||
metric_value DOUBLE,
|
||
quality TINYINT -- 数据质量 0异常 1正常
|
||
) TAGS (
|
||
device_type NCHAR(30),
|
||
area NCHAR(50)
|
||
);
|
||
|
||
-- 按设备类型创建子表
|
||
CREATE TABLE flow_meter_data USING iot_telemetry TAGS('flow_meter', 'default');
|
||
CREATE TABLE pressure_data USING iot_telemetry TAGS('pressure', 'default');
|
||
CREATE TABLE level_data USING iot_telemetry TAGS('level', 'default');
|
||
CREATE TABLE water_quality_data USING iot_telemetry TAGS('water_quality', 'default');
|
||
CREATE TABLE valve_status_data USING iot_telemetry TAGS('valve', 'default');
|
||
|
||
-- 小时级聚合表
|
||
CREATE TABLE iot_telemetry_hourly (
|
||
ts TIMESTAMP,
|
||
device_sn NCHAR(100),
|
||
metric_key NCHAR(50),
|
||
avg_value DOUBLE,
|
||
min_value DOUBLE,
|
||
max_value DOUBLE,
|
||
sample_count INT
|
||
) TAGS (
|
||
device_type NCHAR(30),
|
||
area NCHAR(50)
|
||
);
|
||
```
|
||
|
||
#### 1.2.4 营业收费表 (wm-revenue)
|
||
|
||
```sql
|
||
-- 用水户档案
|
||
CREATE TABLE rev_customer (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
customer_no VARCHAR(30) UNIQUE NOT NULL, -- 户号
|
||
customer_name VARCHAR(100) NOT NULL,
|
||
customer_type VARCHAR(20) NOT NULL, -- residential/business/enterprise/institution
|
||
area VARCHAR(50) NOT NULL,
|
||
address VARCHAR(300),
|
||
phone VARCHAR(20),
|
||
id_card VARCHAR(18),
|
||
contract_no VARCHAR(50),
|
||
status VARCHAR(20) DEFAULT 'active', -- active/inactive/cancelled
|
||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
CREATE INDEX idx_rev_customer_area ON rev_customer(area);
|
||
CREATE INDEX idx_rev_customer_type ON rev_customer(customer_type);
|
||
|
||
-- 水表档案 (全生命周期)
|
||
CREATE TABLE rev_meter (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
meter_no VARCHAR(50) UNIQUE NOT NULL,
|
||
customer_id BIGINT REFERENCES rev_customer(id),
|
||
device_id BIGINT, -- 关联IoT设备(远传表)
|
||
caliber VARCHAR(10) NOT NULL, -- DN15/DN20/DN40/DN50/DN80/DN100...
|
||
meter_type VARCHAR(20) NOT NULL, -- mechanical/ultrasonic/electromagnetic/remote
|
||
initial_reading DECIMAL(12,3),
|
||
install_date DATE,
|
||
warranty_expire DATE,
|
||
status VARCHAR(20) DEFAULT 'in_stock', -- in_stock/installed/dismantled/scrapped/repairing/repaired
|
||
prev_status VARCHAR(20), -- 前状态(用于拆换追溯)
|
||
status_changed_at TIMESTAMPTZ,
|
||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
COMMENT ON TABLE rev_meter IS '水表全生命周期档案表';
|
||
CREATE INDEX idx_rev_meter_customer ON rev_meter(customer_id);
|
||
CREATE INDEX idx_rev_meter_status ON rev_meter(status);
|
||
|
||
-- 水表操作流水 (入库/出库/安装/拆换/报废/翻新/校表)
|
||
CREATE TABLE rev_meter_log (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
meter_id BIGINT REFERENCES rev_meter(id),
|
||
operation VARCHAR(20) NOT NULL, -- stock_in/stock_out/install/dismantle/swap/scrap/renovate/calibrate
|
||
old_reading DECIMAL(12,3),
|
||
new_reading DECIMAL(12,3),
|
||
old_meter_no VARCHAR(50), -- 换表时的旧表编号
|
||
new_meter_no VARCHAR(50), -- 换表时的新表编号
|
||
operator_id BIGINT,
|
||
remark TEXT,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 抄表记录
|
||
CREATE TABLE rev_reading (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
meter_id BIGINT REFERENCES rev_meter(id),
|
||
reading_date DATE NOT NULL,
|
||
prev_reading DECIMAL(12,3),
|
||
curr_reading DECIMAL(12,3),
|
||
consumption DECIMAL(12,3), -- 用水量 = curr - prev
|
||
read_type VARCHAR(20) NOT NULL, -- manual/remote/estimate
|
||
reader_id BIGINT,
|
||
photo_url VARCHAR(500),
|
||
verified SMALLINT DEFAULT 0, -- 0未核实 1已核实 2异常
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
CREATE INDEX idx_rev_reading_date ON rev_reading(reading_date);
|
||
CREATE INDEX idx_rev_reading_meter ON rev_reading(meter_id, reading_date);
|
||
|
||
-- 水费账单
|
||
CREATE TABLE rev_bill (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
customer_id BIGINT REFERENCES rev_customer(id),
|
||
meter_id BIGINT REFERENCES rev_meter(id),
|
||
bill_no VARCHAR(50) UNIQUE NOT NULL,
|
||
bill_period VARCHAR(10) NOT NULL, -- 2026-06
|
||
consumption DECIMAL(12,3),
|
||
water_fee DECIMAL(12,2),
|
||
sewage_fee DECIMAL(12,2),
|
||
other_fee DECIMAL(12,2) DEFAULT 0,
|
||
total_fee DECIMAL(12,2),
|
||
paid_fee DECIMAL(12,2) DEFAULT 0,
|
||
status VARCHAR(20) DEFAULT 'pending', -- pending/partial/paid/overdue/cancelled
|
||
due_date DATE,
|
||
paid_at TIMESTAMPTZ,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
CREATE INDEX idx_rev_bill_customer ON rev_bill(customer_id, bill_period);
|
||
CREATE INDEX idx_rev_bill_status ON rev_bill(status);
|
||
|
||
-- 支付记录
|
||
CREATE TABLE rev_payment (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
bill_id BIGINT REFERENCES rev_bill(id),
|
||
pay_no VARCHAR(100) UNIQUE, -- 第三方支付单号
|
||
pay_channel VARCHAR(20) NOT NULL, -- counter/pos/alipay/wechat
|
||
pay_amount DECIMAL(12,2) NOT NULL,
|
||
pay_status VARCHAR(20) DEFAULT 'processing', -- processing/success/failed/refunded
|
||
pay_at TIMESTAMPTZ,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 电子发票
|
||
CREATE TABLE rev_invoice (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
bill_id BIGINT REFERENCES rev_bill(id),
|
||
invoice_no VARCHAR(50) UNIQUE NOT NULL,
|
||
invoice_type VARCHAR(20) DEFAULT 'electronic', -- paper/electronic/vat
|
||
amount DECIMAL(12,2) NOT NULL,
|
||
tax_amount DECIMAL(12,2) DEFAULT 0,
|
||
status VARCHAR(20) DEFAULT 'issued', -- issued/voided/red_invoiced
|
||
issued_at TIMESTAMPTZ DEFAULT NOW(),
|
||
voided_at TIMESTAMPTZ,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 应收应付账务
|
||
CREATE TABLE rev_account (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
customer_id BIGINT REFERENCES rev_customer(id),
|
||
account_type VARCHAR(20) NOT NULL, -- receivable/payable
|
||
amount DECIMAL(12,2) NOT NULL,
|
||
balance DECIMAL(12,2) NOT NULL,
|
||
period VARCHAR(10),
|
||
status VARCHAR(20) DEFAULT 'open', -- open/partial/closing/closed
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 水价阶梯配置
|
||
CREATE TABLE rev_water_price (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
customer_type VARCHAR(20) NOT NULL, -- residential/business/enterprise
|
||
tier SMALLINT NOT NULL, -- 1/2/3
|
||
min_usage DECIMAL(12,3), -- 下限(m³)
|
||
max_usage DECIMAL(12,3), -- 上限(m³) NULL=无上限
|
||
unit_price DECIMAL(8,4) NOT NULL, -- 水价(元/m³)
|
||
sewage_price DECIMAL(8,4) DEFAULT 0, -- 污水处理费
|
||
effective_date DATE NOT NULL,
|
||
expired_date DATE,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
```
|
||
|
||
#### 1.2.5 报装管理表
|
||
|
||
```sql
|
||
-- 报装申请
|
||
CREATE TABLE rev_install (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
app_no VARCHAR(30) UNIQUE NOT NULL, -- 申请编号
|
||
applicant_name VARCHAR(50) NOT NULL,
|
||
applicant_phone VARCHAR(20) NOT NULL,
|
||
customer_type VARCHAR(20) NOT NULL,
|
||
area VARCHAR(50),
|
||
address VARCHAR(300),
|
||
caliber VARCHAR(10), -- 申请管径
|
||
usage_type VARCHAR(30), -- 生活/商业/工业/消防
|
||
status VARCHAR(20) DEFAULT 'pre_accept', -- pre_accept/ site_survey/ engineering/ dispatched/ constructing/ completed/ cancelled
|
||
survey_result TEXT, -- 现场踏勘结论
|
||
designer_id BIGINT, -- 设计人员
|
||
constructor_id BIGINT, -- 施工人员
|
||
completed_at TIMESTAMPTZ,
|
||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
CREATE INDEX idx_rev_install_status ON rev_install(status);
|
||
```
|
||
|
||
#### 1.2.6 客服与微信网厅
|
||
|
||
```sql
|
||
-- 知识库
|
||
CREATE TABLE cs_kb_article (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
title VARCHAR(200) NOT NULL,
|
||
category VARCHAR(50) NOT NULL, -- policy/guide/common_qa/water_knowledge
|
||
content TEXT NOT NULL, -- Markdown
|
||
tags VARCHAR(500), -- 逗号分隔
|
||
view_count INT DEFAULT 0,
|
||
like_count INT DEFAULT 0,
|
||
status SMALLINT DEFAULT 1,
|
||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
CREATE INDEX idx_cs_kb_category ON cs_kb_article(category);
|
||
|
||
-- 公告板
|
||
CREATE TABLE cs_announcement (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
title VARCHAR(200) NOT NULL,
|
||
ann_type VARCHAR(30) NOT NULL, -- water_outage/water_quality/service/notice/news
|
||
content TEXT NOT NULL,
|
||
target_scope VARCHAR(50) DEFAULT 'all', -- all/{area}
|
||
publish_status VARCHAR(20) DEFAULT 'draft', -- draft/published/revoked
|
||
published_at TIMESTAMPTZ,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 微信支付订单
|
||
CREATE TABLE rev_wx_pay_order (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
bill_id BIGINT REFERENCES rev_bill(id),
|
||
wx_order_no VARCHAR(100) UNIQUE,
|
||
wx_transaction_id VARCHAR(100),
|
||
amount DECIMAL(12,2) NOT NULL,
|
||
status VARCHAR(20) DEFAULT 'created', -- created/paying/paid/refunding/refunded/closed
|
||
paid_at TIMESTAMPTZ,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- FAQ
|
||
CREATE TABLE cs_faq (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
question VARCHAR(500) NOT NULL,
|
||
answer TEXT NOT NULL,
|
||
category VARCHAR(50),
|
||
keywords VARCHAR(300),
|
||
priority INT DEFAULT 0,
|
||
view_count INT DEFAULT 0,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
```
|
||
|
||
#### 1.2.7 工单管理
|
||
|
||
```sql
|
||
CREATE TABLE wo_template (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
template_name VARCHAR(100) NOT NULL,
|
||
wo_type VARCHAR(30) NOT NULL, -- repair/alert/meter_change/quality/scheduling
|
||
form_schema JSONB DEFAULT '{}', -- 表单字段定义
|
||
flow_def_key VARCHAR(100), -- 流程定义KEY
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
CREATE TABLE wo_order (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
wo_no VARCHAR(30) UNIQUE NOT NULL,
|
||
template_id BIGINT REFERENCES wo_template(id),
|
||
wo_type VARCHAR(30) NOT NULL,
|
||
title VARCHAR(200) NOT NULL,
|
||
description TEXT,
|
||
priority VARCHAR(10) DEFAULT 'normal', -- low/normal/high/urgent
|
||
source VARCHAR(30), -- manual/alert_rules/patrol/scheduling
|
||
source_ref_id BIGINT, -- 来源关联ID (报警/巡检/Schedule)
|
||
assignee_id BIGINT,
|
||
creator_id BIGINT,
|
||
status VARCHAR(20) DEFAULT 'created', -- created/assigned/processing/completed/closed
|
||
resolved_at TIMESTAMPTZ,
|
||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
CREATE INDEX idx_wo_status ON wo_order(status);
|
||
CREATE INDEX idx_wo_assignee ON wo_order(assignee_id);
|
||
|
||
-- 工单处理记录
|
||
CREATE TABLE wo_process_log (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
wo_id BIGINT REFERENCES wo_order(id),
|
||
action VARCHAR(30) NOT NULL, -- create/assign/accept/process/complete/close/reject
|
||
operator_id BIGINT,
|
||
comment TEXT,
|
||
attachments JSONB DEFAULT '[]', -- [{url, name, type}]
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
```
|
||
|
||
#### 1.2.8 巡检系统
|
||
|
||
```sql
|
||
-- 巡检区域
|
||
CREATE TABLE patrol_area (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
area_name VARCHAR(100) NOT NULL,
|
||
area_code VARCHAR(30) UNIQUE,
|
||
parent_id BIGINT DEFAULT 0,
|
||
sort_order INT DEFAULT 0,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 巡检路线
|
||
CREATE TABLE patrol_route (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
route_name VARCHAR(100) NOT NULL,
|
||
area_id BIGINT REFERENCES patrol_area(id),
|
||
checkpoints JSONB NOT NULL, -- [{seq, name, lng, lat, device_ids:[], check_items:[{item,standard}]}]
|
||
estim_duration INT, -- 预计时长(分钟)
|
||
status SMALLINT DEFAULT 1,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 巡检表单模板
|
||
CREATE TABLE patrol_form_template (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
template_name VARCHAR(100) NOT NULL,
|
||
category VARCHAR(30), -- device/water_quality/safety/hygiene
|
||
items JSONB NOT NULL, -- [{item, type(text/photo/number/select), required, options}]
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 巡检任务
|
||
CREATE TABLE patrol_task (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
route_id BIGINT REFERENCES patrol_route(id),
|
||
assignee_id BIGINT,
|
||
plan_date DATE NOT NULL,
|
||
plan_start TIME,
|
||
plan_end TIME,
|
||
actual_start TIMESTAMPTZ,
|
||
actual_end TIMESTAMPTZ,
|
||
status VARCHAR(20) DEFAULT 'pending', -- pending/in_progress/completed/expired
|
||
distance DECIMAL(8,2), -- 实际里程(km)
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- GPS轨迹点
|
||
CREATE TABLE patrol_gps_track (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
task_id BIGINT REFERENCES patrol_task(id),
|
||
lng DOUBLE PRECISION NOT NULL,
|
||
lat DOUBLE PRECISION NOT NULL,
|
||
altitude DOUBLE PRECISION,
|
||
accuracy DOUBLE PRECISION,
|
||
recorded_at TIMESTAMPTZ NOT NULL,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
CREATE INDEX idx_patrol_gps_task ON patrol_gps_track(task_id, recorded_at);
|
||
|
||
-- 巡检记录
|
||
CREATE TABLE patrol_record (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
task_id BIGINT REFERENCES patrol_task(id),
|
||
checkpoint_seq INT NOT NULL, -- 路线第几个检查点
|
||
device_id BIGINT,
|
||
form_data JSONB NOT NULL, -- [{item, result, value, photo_url, remark}]
|
||
gps_lng DOUBLE PRECISION,
|
||
gps_lat DOUBLE PRECISION,
|
||
recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
);
|
||
|
||
-- 巡检问题上报
|
||
CREATE TABLE patrol_issue (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
task_id BIGINT REFERENCES patrol_task(id),
|
||
patrol_record_id BIGINT REFERENCES patrol_record(id),
|
||
issue_type VARCHAR(30) NOT NULL, -- device_fault/leak/quality/safety/other
|
||
severity VARCHAR(10) DEFAULT 'normal', -- normal/important/urgent
|
||
description TEXT NOT NULL,
|
||
photo_urls TEXT, -- JSON数组
|
||
voice_url VARCHAR(500),
|
||
wo_id BIGINT REFERENCES wo_order(id), -- 生成工单ID
|
||
status VARCHAR(20) DEFAULT 'reported', -- reported/assigned/processing/resolved
|
||
resolved_at TIMESTAMPTZ,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 巡检统计缓存表
|
||
CREATE TABLE patrol_stats_daily (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
stat_date DATE NOT NULL,
|
||
assignee_id BIGINT,
|
||
area_id BIGINT,
|
||
task_count INT DEFAULT 0,
|
||
completed_count INT DEFAULT 0,
|
||
total_distance DECIMAL(8,2),
|
||
total_duration INT, -- 分钟
|
||
issue_count INT DEFAULT 0,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
CREATE UNIQUE INDEX idx_patrol_stats_uk ON patrol_stats_daily(stat_date, assignee_id, area_id);
|
||
```
|
||
|
||
#### 1.2.9 供水生产管理
|
||
|
||
```sql
|
||
-- 能耗记录
|
||
CREATE TABLE prod_energy (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
energy_type VARCHAR(20) NOT NULL, -- electricity/water_consumption
|
||
station_id BIGINT,
|
||
metric_value DOUBLE PRECISION,
|
||
unit VARCHAR(10) DEFAULT 'kWh',
|
||
recorded_at TIMESTAMPTZ NOT NULL,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 药耗记录
|
||
CREATE TABLE prod_chemical (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
chemical_type VARCHAR(30) NOT NULL, -- coagulant/disinfectant/flocculant
|
||
station_id BIGINT,
|
||
dosage_rate DOUBLE PRECISION, -- 投加速率
|
||
consumption DOUBLE PRECISION, -- 消耗量(kg)
|
||
recorded_at TIMESTAMPTZ NOT NULL,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 水质检测点位
|
||
CREATE TABLE prod_quality_point (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
point_name VARCHAR(100) NOT NULL,
|
||
point_type VARCHAR(30) NOT NULL, -- source/plant/pipe_end/network
|
||
area VARCHAR(50),
|
||
water_plant VARCHAR(100),
|
||
location VARCHAR(200),
|
||
sample_freq VARCHAR(20), -- daily/weekly/monthly
|
||
status SMALLINT DEFAULT 1,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 水质检测记录
|
||
CREATE TABLE prod_quality_record (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
point_id BIGINT REFERENCES prod_quality_point(id),
|
||
test_date DATE NOT NULL,
|
||
test_type VARCHAR(20) DEFAULT 'manual', -- manual/auto
|
||
turbidity DOUBLE PRECISION, -- NTU
|
||
ph DOUBLE PRECISION,
|
||
residual_cl DOUBLE PRECISION, -- 余氯 mg/L
|
||
cod_mn DOUBLE PRECISION, -- 高锰酸盐指数
|
||
coliform INT, -- 总大肠菌群
|
||
qualified SMALLINT, -- 合格判定 (GB5749-2022)
|
||
tester_id BIGINT,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 调度指令
|
||
CREATE TABLE prod_dispatch_cmd (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
cmd_no VARCHAR(30) UNIQUE NOT NULL,
|
||
cmd_type VARCHAR(30) NOT NULL, -- valve_control/pump_start/flow_adjust/alert_response
|
||
cmd_content TEXT NOT NULL,
|
||
target_device VARCHAR(100),
|
||
priority VARCHAR(10) DEFAULT 'normal',
|
||
issuer_id BIGINT,
|
||
issued_at TIMESTAMPTZ DEFAULT NOW(),
|
||
deadline TIMESTAMPTZ,
|
||
status VARCHAR(20) DEFAULT 'issued', -- issued/received/executing/completed/rejected
|
||
executed_by BIGINT,
|
||
executed_at TIMESTAMPTZ,
|
||
result TEXT
|
||
);
|
||
|
||
-- 应急推演方案
|
||
CREATE TABLE prod_emergency_plan (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
plan_name VARCHAR(100) NOT NULL,
|
||
scenario VARCHAR(30) NOT NULL, -- pipe_burst/water_quality/fire_supply/equipment_fault
|
||
steps JSONB NOT NULL, -- [{seq, action, target, duration, responsible_role}]
|
||
status SMALLINT DEFAULT 1,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 值班表
|
||
CREATE TABLE prod_duty_schedule (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
schedule_date DATE NOT NULL,
|
||
shift VARCHAR(20) DEFAULT 'day', -- day/night
|
||
user_id BIGINT,
|
||
dept_id BIGINT,
|
||
phone VARCHAR(20),
|
||
status VARCHAR(20) DEFAULT 'on_duty',
|
||
handover_note TEXT,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
```
|
||
|
||
#### 1.2.10 报警管理
|
||
|
||
```sql
|
||
-- 报警规则
|
||
CREATE TABLE alert_rule (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
rule_name VARCHAR(100) NOT NULL,
|
||
device_type VARCHAR(30),
|
||
metric_key VARCHAR(50) NOT NULL,
|
||
alert_level VARCHAR(10) NOT NULL, -- info/warning/critical/emergency
|
||
condition_expr VARCHAR(200) NOT NULL, -- "> 0.5" 或 "ABS_DELTA > 10" 或 "<= 0.2"
|
||
threshold_value VARCHAR(50),
|
||
debounce_sec INT DEFAULT 300, -- 去重窗口(秒)
|
||
notify_scheme JSONB DEFAULT '{"sms":false,"push":true,"ws":true}',
|
||
enabled SMALLINT DEFAULT 1,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 报警事件
|
||
CREATE TABLE alert_event (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
rule_id BIGINT REFERENCES alert_rule(id),
|
||
device_id BIGINT,
|
||
device_sn VARCHAR(100),
|
||
metric_key VARCHAR(50),
|
||
metric_value DOUBLE PRECISION,
|
||
threshold VARCHAR(50),
|
||
alert_level VARCHAR(10),
|
||
message VARCHAR(500),
|
||
area VARCHAR(50),
|
||
confirmed_by BIGINT,
|
||
confirmed_at TIMESTAMPTZ,
|
||
dispatched SMALLINT DEFAULT 0, -- 是否生成工单
|
||
resolved_at TIMESTAMPTZ,
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
CREATE INDEX idx_alert_level ON alert_event(alert_level, created_at);
|
||
CREATE INDEX idx_alert_device ON alert_event(device_sn, created_at);
|
||
```
|
||
|
||
#### 1.2.11 配置中心
|
||
|
||
```sql
|
||
-- 系统配置
|
||
CREATE TABLE sys_config (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
config_key VARCHAR(100) UNIQUE NOT NULL,
|
||
config_value TEXT NOT NULL,
|
||
config_type VARCHAR(30) DEFAULT 'string', -- string/number/json/bool
|
||
description VARCHAR(300),
|
||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 阈值配置
|
||
CREATE TABLE sys_threshold (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
metric_key VARCHAR(50) NOT NULL,
|
||
area VARCHAR(50) DEFAULT 'all',
|
||
min_value DOUBLE PRECISION,
|
||
max_value DOUBLE PRECISION,
|
||
unit VARCHAR(20),
|
||
description VARCHAR(200),
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
|
||
-- 文档管理
|
||
CREATE TABLE sys_document (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
doc_name VARCHAR(200) NOT NULL,
|
||
doc_category VARCHAR(50), -- manual/report/standard/other
|
||
file_url VARCHAR(500) NOT NULL,
|
||
file_size BIGINT,
|
||
file_type VARCHAR(20),
|
||
version INT DEFAULT 1,
|
||
tags VARCHAR(300),
|
||
uploader_id BIGINT,
|
||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
CREATE INDEX idx_sys_doc_category ON sys_document(doc_category);
|
||
```
|
||
|
||
### 1.3 认证授权系统设计
|
||
|
||
> **对应 Issue**:#19 认证授权系统
|
||
|
||
**职责边界**:提供统一认证(登录/JWT签发/Token校验/刷新)、RBAC角色权限管理、数据权限(按片区/部门隔离)。
|
||
|
||
#### 认证流程
|
||
|
||
```
|
||
用户 → POST /api/auth/login {username, password}
|
||
→ Sa-Token 校验密码 (BCrypt)
|
||
→ 签发 JWT (含 userId, roleKeys[])
|
||
→ 返回 {token, refreshToken, userInfo}
|
||
|
||
后续请求 → Header: Authorization: Bearer <token>
|
||
→ Sa-Token 拦截器校验
|
||
→ @SaCheckPermission 注解校验菜单权限
|
||
→ AOP 切面注入数据权限 scope → SQL 自动拼接 WHERE area IN (...)
|
||
```
|
||
|
||
#### API 端点
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| POST | /api/auth/login | 用户名密码登录,返回 JWT |
|
||
| POST | /api/auth/refresh | 刷新 Token |
|
||
| POST | /api/auth/logout | 退出登录 |
|
||
| GET | /api/auth/current | 获取当前用户信息+权限列表 |
|
||
| POST | /api/oauth2/token | OAuth2 Token端点 |
|
||
| POST | /api/oauth2/authorize | OAuth2 授权端点 |
|
||
| POST | /api/sso/clients | 注册 SSO 客户端应用 |
|
||
| GET | /api/sso/clients | 查询已注册应用列表 |
|
||
| DELETE | /api/sso/clients/{id} | 注销应用 |
|
||
|
||
#### 数据权限策略
|
||
|
||
```java
|
||
// 数据权限注解
|
||
@Target(ElementType.METHOD)
|
||
@Retention(RetentionPolicy.RUNTIME)
|
||
public @interface DataScope {
|
||
String column() default "area"; // 需要过滤的字段
|
||
String deptColumn() default "dept_id";
|
||
}
|
||
// SQL 拦截器自动拼接: AND area IN (用户的片区列表)
|
||
```
|
||
|
||
**模块依赖**:
|
||
- 依赖:wm-base(用户/角色表)
|
||
- 提供:给所有微服务提供 JWT 认证 + 数据权限
|
||
|
||
### 1.4 GIS 引擎集成
|
||
|
||
> **对应 Issue**:#21 GIS引擎集成
|
||
|
||
**部署架构**:
|
||
```
|
||
GeoServer 2.25 (Tomcat)
|
||
├── Workspace: water_supply
|
||
│ ├── DataStore: postgis_water (连接 PostgreSQL)
|
||
│ ├── Layer: iot_device (监测点位 WMS)
|
||
│ ├── Layer: pipeline (管网矢量 WMS)
|
||
│ ├── Layer: dma_zones (DMA 分区面 WMS)
|
||
│ └── Layer group: 综合管网图
|
||
└── Cache: GeoWebCache (WMTS 瓦片加速)
|
||
```
|
||
|
||
**前端分层**:
|
||
```
|
||
Leaflet (2D)
|
||
├── 底图: 高德/天地图 WMTS
|
||
├── 管网图层: GeoServer WMS
|
||
├── 监测点位: GeoJSON 动态图层 (轮询 30s)
|
||
│ ├── Marker: 流量/压力/液位/水质/阀门 (不同图标+颜色)
|
||
│ └── Popup: 实时数据面板
|
||
├── 热力图: leaflet.heat (点位密度)
|
||
├── DMA 分区: GeoJSON 面图层 (漏损率颜色)
|
||
└── 轨迹回放: Leaflet.MovingMarker (巡检GPS)
|
||
```
|
||
|
||
**关键 API**:
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | /api/gis/points | 获取监测点位列表 (含坐标/类型/实时值) |
|
||
| GET | /api/gis/points/heatmap | 获取热力图数据 |
|
||
| GET | /api/gis/pipelines | 获取管网数据 |
|
||
| GET | /api/gis/spatial-query | 矩形/圆形空间查询 |
|
||
| GET | /api/gis/wms-proxy/** | GeoServer WMS 代理 |
|
||
|
||
**模块依赖**:
|
||
- 依赖:wm-iot(设备坐标数据)、PostGIS 扩展
|
||
- 提供:给供水生产(地图监测)、巡检(路线/GPS轨迹)、DMA(分区面图层)
|
||
|
||
### 1.5 IoT 设备接入层
|
||
|
||
> **对应 Issue**:#22 IoT接入层
|
||
|
||
**EMQX 配置要点**:
|
||
```
|
||
# emqx.conf
|
||
listener.tcp.external = 1883
|
||
listener.ssl.external = 8883
|
||
# 设备认证
|
||
listener.tcp.external.enable_authn = true
|
||
# HTTP 回调认证
|
||
auth.http.auth_req.url = "http://wm-iot:8082/api/iot/auth/device"
|
||
# Kafka 桥接
|
||
bridges.kafka.iot_raw.servers = "kafka:9092"
|
||
bridges.kafka.iot_raw.topic = "iot.raw.${device_type}"
|
||
```
|
||
|
||
**Kafka Topic 规划**:
|
||
|
||
| Topic | 用途 | 分区数 | 保留时间 |
|
||
|-------|------|:---:|:---:|
|
||
| iot.raw.flow_meter | 流量计原始数据 | 6 | 7d |
|
||
| iot.raw.pressure | 压力传感器原始数据 | 3 | 7d |
|
||
| iot.raw.water_quality | 水质传感器原始数据 | 3 | 7d |
|
||
| iot.raw.level | 液位计原始数据 | 3 | 7d |
|
||
| iot.raw.valve | 阀门状态数据 | 3 | 7d |
|
||
| iot.cmd.downlink | 下行指令 | 3 | 1d |
|
||
| iot.event.online | 设备上下线事件 | 1 | 30d |
|
||
| iot.event.alarm | 报警事件 | 3 | 90d |
|
||
|
||
**API 端点**:
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| POST | /api/iot/device | 注册设备 |
|
||
| GET | /api/iot/device | 设备列表(分页/按类型/片区/状态过滤) |
|
||
| GET | /api/iot/device/{sn} | 设备详情 |
|
||
| PUT | /api/iot/device/{sn} | 更新设备信息 |
|
||
| DELETE | /api/iot/device/{sn} | 注销设备 |
|
||
| POST | /api/iot/device/{sn}/cmd | 下发指令 |
|
||
| GET | /api/iot/telemetry/{sn} | 查询设备实时遥测数据 |
|
||
|
||
### 1.6 消息通知模块
|
||
|
||
> **对应 Issue**:#26 消息通知模块
|
||
|
||
**多渠道策略**:
|
||
|
||
| 渠道 | 技术 | 适用场景 |
|
||
|------|------|----------|
|
||
| WebSocket | Spring WebSocket + STOMP | 实时报警弹窗、网页端通知 |
|
||
| APP 推送 | 极光推送 (JPush) | 移动端报警、待办提醒 |
|
||
| 短信 | 阿里云 SMS | 紧急报警、停水通知 |
|
||
| 邮件 | JavaMail + 模板 | 日报周报推送 |
|
||
|
||
**通知模板表**:
|
||
```sql
|
||
CREATE TABLE notify_template (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
template_code VARCHAR(50) UNIQUE NOT NULL,
|
||
template_name VARCHAR(100),
|
||
channels VARCHAR(50) DEFAULT 'ws', -- ws,sms,push,email 逗号分隔
|
||
title_tpl VARCHAR(200),
|
||
content_tpl TEXT NOT NULL, -- 支持变量 ${device_sn} ${metric_key} ${value}
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
```
|
||
|
||
---
|
||
|
||
## 第2章 物联网平台
|
||
|
||
### 2.1 多协议适配器
|
||
|
||
> **对应 Issue**:#28 MQTT 协议适配器 + 设备注册/发现, #29 Modbus/CoAP/HTTP 协议适配
|
||
|
||
**适配器接口**:
|
||
```java
|
||
public interface DeviceAdapter {
|
||
String getProtocol(); // "MQTT"/"Modbus"/"CoAP"/"HTTP"
|
||
void onMessage(byte[] payload); // 处理设备上行数据
|
||
void sendCommand(String deviceSn, Command cmd); // 发送下行指令
|
||
DeviceInfo parseDeviceInfo(byte[] payload); // 解析设备注册信息
|
||
}
|
||
```
|
||
|
||
**AdapterFactory**:
|
||
```java
|
||
@Component
|
||
public class AdapterFactory {
|
||
private final Map<String, DeviceAdapter> adapters = new HashMap<>();
|
||
|
||
public void register(String protocol, DeviceAdapter adapter) { ... }
|
||
public DeviceAdapter get(String protocol) { ... }
|
||
}
|
||
```
|
||
|
||
**MQTT 适配器核心逻辑**:
|
||
```
|
||
订阅 iot.raw.* → 解析 JSON payload → DeviceModelMapper.convert()
|
||
→ 写入 Kafka (iot.raw.{device_type})
|
||
→ 写入 Redis (最新值缓存)
|
||
→ 判断报警规则 → 触发报警
|
||
```
|
||
|
||
**数据格式转换(DeviceModelMapper)**:
|
||
```java
|
||
// 统一设备上报格式
|
||
{
|
||
"deviceSn": "FLOW_001",
|
||
"ts": 1718340000000,
|
||
"metrics": [
|
||
{"key": "flow_rate", "value": 12.5, "unit": "m³/h"},
|
||
{"key": "total_flow", "value": 15230.8, "unit": "m³"}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 2.2 设备影子服务
|
||
|
||
> **对应 Issue**:#30 设备影子服务 + OTA 固件升级
|
||
|
||
**Redis 存储结构**:
|
||
```
|
||
Key: shadow:{deviceSn}
|
||
Value: {
|
||
"reported": {"flow_rate": 12.5, "status": "online"},
|
||
"desired": {"report_interval": 60},
|
||
"version": 5,
|
||
"lastSync": 1718340000000
|
||
}
|
||
```
|
||
|
||
**影子同步流程**:
|
||
```
|
||
设备上报 → adapter.onMessage()
|
||
→ Redis: shadow.{sn}.reported = 最新状态
|
||
→ 检查 desired 是否有待下发指令 → 下发
|
||
→ 指令下发后 → iot.cmd.downlink → EMQX → 设备
|
||
|
||
设备离线 → 指令缓存到 Redis desired
|
||
设备上线 → 拉取 desired → 逐条下发 → 确认后清除
|
||
```
|
||
|
||
### 2.3 IoT 前端页面
|
||
|
||
> **对应 Issue**:#31 设备管理前端页面
|
||
|
||
**路由**:
|
||
```
|
||
/iot/devices → DeviceListView.vue (表格+筛选)
|
||
/iot/devices/:sn → DeviceDetailView.vue (详情+遥测图表)
|
||
/iot/devices/map → DeviceMapView.vue (GIS地图叠加)
|
||
/iot/ota → FirmwareListView.vue (固件管理)
|
||
```
|
||
|
||
**DeviceListView** 组件树:
|
||
```
|
||
DeviceListView
|
||
├── SearchBar (片区下拉/设备类型下拉/状态多选/关键词输入)
|
||
├── DeviceTable (分页表格)
|
||
│ └── columns: SN/名称/类型/片区/状态/最后上报时间/操作
|
||
└── DeviceFormDialog (新增/编辑 弹窗)
|
||
```
|
||
|
||
---
|
||
|
||
## 第3章 流程引擎
|
||
|
||
> **对应 Issue**:#32 BPM流程核心, #33 BPMN.js设计器, #34 流程统计, #35 跨系统编排
|
||
|
||
### 3.1 Camunda 集成
|
||
|
||
**职责边界**:基于 Camunda 7 提供 BPMN 2.0 流程引擎,封装流程定义、启动、任务处理 API。
|
||
|
||
**Camunda 配置**:
|
||
```yaml
|
||
camunda.bpm:
|
||
admin-user:
|
||
id: admin
|
||
password: ${CAMUNDA_PASSWORD}
|
||
database:
|
||
type: postgres
|
||
history-level: full
|
||
auto-deployment-enabled: true
|
||
deployment-resource-pattern: classpath:/processes/*.bpmn
|
||
```
|
||
|
||
**API 端点**:
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| POST | /api/bpm/process/deploy | 部署 BPMN 流程定义 |
|
||
| POST | /api/bpm/process/start | 启动流程实例 |
|
||
| GET | /api/bpm/task/todo | 查询待办任务 (分页/筛选) |
|
||
| GET | /api/bpm/task/done | 查询已办任务 |
|
||
| POST | /api/bpm/task/{taskId}/approve | 审批通过 |
|
||
| POST | /api/bpm/task/{taskId}/reject | 驳回 |
|
||
| POST | /api/bpm/task/{taskId}/transfer | 转办 |
|
||
| POST | /api/bpm/task/{taskId}/delegate | 委派 |
|
||
| POST | /api/bpm/task/{taskId}/add-sign | 加签 |
|
||
| GET | /api/bpm/instance/{id}/diagram | 获取流程进度图 |
|
||
| GET | /api/bpm/stats/efficiency | 流程效率统计 |
|
||
| GET | /api/bpm/stats/bottleneck | 瓶颈节点分析 |
|
||
|
||
**BPMN.js 设计器集成**:
|
||
```
|
||
前端: bpmn-js (BPMN 2.0 建模器)
|
||
├── 自定义属性面板 (扩展 assignee/candidateGroups/deadline)
|
||
├── 流程模板保存/加载 (bpmn XML → 后端存储)
|
||
└── 模板发布 → Camunda 自动部署
|
||
```
|
||
|
||
**跨系统编排**:
|
||
```java
|
||
// Webhook 回调机制
|
||
@Component
|
||
public class ProcessWebhookService {
|
||
// 流程节点执行完成后回调外部系统
|
||
public void fireEvent(String processInstanceId, String activityId) {
|
||
// 查询该节点的 Webhook 配置 → HTTP POST 回调
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 第4章 数据引擎
|
||
|
||
### 4.1 实时数据采集
|
||
|
||
> **对应 Issue**:#41 实时流数据采集
|
||
|
||
**Kafka Consumer 设计**:
|
||
```java
|
||
@KafkaListener(topics = "iot.raw.#{__listener.topicPattern}")
|
||
public void consumeIotData(ConsumerRecord<String, String> record) {
|
||
TelemetryData data = parseMessage(record.value());
|
||
// 1. 写入 TDengine (批量写入 1000条/5秒)
|
||
tdengineBuffer.add(data);
|
||
// 2. 写入 Redis (最新值)
|
||
redisTemplate.opsForHash().put("telemetry:latest", data.getDeviceSn()+":"+data.getMetricKey(), data);
|
||
// 3. 触发报警规则检查
|
||
alertChecker.check(data);
|
||
}
|
||
```
|
||
|
||
### 4.2 数据接入层
|
||
|
||
> **对应 Issue**:#42 数据接入层
|
||
|
||
**多种接入方式**:
|
||
|
||
| 方式 | 端点 | 说明 |
|
||
|------|------|------|
|
||
| REST Push | POST /api/data/ingest/rest | 第三方系统推送 JSON |
|
||
| WebSocket | ws://host/data/ws | 实时数据流双向通信 |
|
||
| 批量导入 | POST /api/data/ingest/batch | CSV/Excel 文件上传解析 |
|
||
| 数据库直连 | JDBC Source Connector | 定时拉取外部数据库 |
|
||
|
||
**批量导入处理**:
|
||
```
|
||
上传文件 → 格式校验(文件头/列映射) → 数据预览(前100行)
|
||
→ 用户确认映射 → 异步处理(Spring @Async)
|
||
→ 逐行校验(水利标准字段映射) → 写入 TDengine/PostgreSQL
|
||
→ 返回处理结果(成功X条/失败Y条)
|
||
```
|
||
|
||
### 4.3 数据存储层
|
||
|
||
> **对应 Issue**:#43 数据存储层
|
||
|
||
**TDengine 存储策略**:
|
||
- 原始数据:保留 90 天 (iot_telemetry)
|
||
- 小时聚合:保留 3 年 (iot_telemetry_hourly)
|
||
- 日聚合:保留 10 年 (iot_telemetry_daily)
|
||
|
||
**MinIO 存储策略**:
|
||
- 文件按 `{bucket}/{yyyy}/{MM}/{dd}/{uuid}.{ext}` 命名
|
||
- 视频录像:保留 30 天 (lifecycle policy)
|
||
- 照片附件:保留 1 年
|
||
- 固件文件:永久保留
|
||
|
||
### 4.4 数据治理
|
||
|
||
> **对应 Issue**:#44 数据治理
|
||
|
||
**水利数据对象标准映射表**:
|
||
```sql
|
||
CREATE TABLE data_field_mapping (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
source_field VARCHAR(100) NOT NULL, -- 原始字段名
|
||
source_system VARCHAR(50), -- 来源系统
|
||
target_field VARCHAR(100) NOT NULL, -- 标准字段名
|
||
data_type VARCHAR(20), -- VARCHAR/INT/DOUBLE/DATE
|
||
unit VARCHAR(20),
|
||
transform_rule VARCHAR(200), -- 转换规则 (e.g. *1000, DATE_FORMAT)
|
||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||
);
|
||
```
|
||
|
||
**清洗规则链**:
|
||
```
|
||
原始数据 → 空值检查(填充/丢弃)→ 异常值检测(IQR/3σ) → 格式转换
|
||
→ 去重(时间窗口内) → 质量评分(0-100) → 入仓
|
||
```
|
||
|
||
---
|
||
|
||
## 第5章 供水生产管理
|
||
|
||
### 5.1 生产总览大屏
|
||
|
||
> **对应 Issue**:#61 总览大屏
|
||
|
||
**数据聚合 API**:
|
||
```
|
||
GET /api/production/dashboard/summary?area={area}
|
||
Response:
|
||
{
|
||
"area": "一体化水厂",
|
||
"todayInflow": 15230.5, // m³
|
||
"todayOutflow": 14890.2,
|
||
"yesterdayTotalSupply": 31000.0,
|
||
"sourceWaterQuality": { "turbidity": 3.2, "ph": 7.8 },
|
||
"treatedWaterQuality": { "turbidity": 0.3, "residualCl": 0.5, "qualified": true },
|
||
"activeAlerts": [...],
|
||
"deviceStats": { "total": 156, "online": 142, "fault": 3 },
|
||
"energy": { "electricity": 1250.5, "waterUse": 320.0 },
|
||
"chemical": { "coagulant": 85.2, "disinfectant": 12.5 }
|
||
}
|
||
```
|
||
|
||
**前端 ECharts 组件**:
|
||
```
|
||
DashboardView.vue
|
||
├── AreaSelector (片区下拉,系统管理员看全部)
|
||
├── SummaryCards (4个数字卡片: 进水/出水/昨日供水/设备在线率)
|
||
├── WaterInOutChart (进出水量趋势折线图,24h)
|
||
├── WaterQualityChart (水质指标仪表盘)
|
||
├── AlertList (实时报警滚动列表)
|
||
├── DeviceStatusPie (设备状态饼图)
|
||
├── EnergyBar (能耗柱状图)
|
||
└── ChemicalBar (药耗柱状图)
|
||
```
|
||
|
||
### 5.2 在线监测列表
|
||
|
||
> **对应 Issue**:#62 在线监测列表
|
||
|
||
**路由**:`/production/monitor`
|
||
|
||
```
|
||
MonitorListView.vue
|
||
├── FilterPanel
|
||
│ ├── 片区 (select: 6个片区)
|
||
│ ├── 位置类型 (select: 水厂/调压站/管网/村队)
|
||
│ ├── 设备类型 (select: 全部/流量计/压力/液位/水质/阀门)
|
||
│ ├── 状态 (checkbox: 在线/离线/故障)
|
||
│ └── 关键词搜索
|
||
├── MonitorTable
|
||
│ └── columns: 站点名称/片区/位置类型/设备SN/实时值(Multi-metric)/采集时间/状态
|
||
├── ExportButton (导出 Excel)
|
||
└── AutoRefresh (5s/10s/30s 切换)
|
||
```
|
||
|
||
### 5.3 视频监控与 AI
|
||
|
||
> **对应 Issue**:#63 视频监控+AI闯入检测
|
||
|
||
**视频流接入**:
|
||
```
|
||
摄像头(RTSP/GB28181) → NVR/视频平台 → RTSP 流地址
|
||
→ wm-production 代理 → 前端 HLS/WebRTC 播放
|
||
```
|
||
|
||
**AI 闯入检测**:
|
||
```
|
||
视频帧 → YOLOv8 推理 → 人员检测 → 闯入区域判断
|
||
→ 触发 Alert (level=emergency) → WebSocket 实时弹窗
|
||
→ 录制 30s 视频快照 → MinIO 存储
|
||
```
|
||
|
||
### 5.4 GIS 地图展示
|
||
|
||
> **对应 Issue**:#64 GIS地图展示
|
||
|
||
**点位分类展示**:
|
||
```
|
||
图层:
|
||
├── 流量计 (蓝色水滴)
|
||
├── 压力传感器 (绿色圆形)
|
||
├── 液位计 (青色三角形)
|
||
├── 水质传感器 (紫色菱形)
|
||
├── 阀门 (红色方形: 开/绿: 关)
|
||
└── 管网 (蓝色线条 → WMS 瓦片)
|
||
```
|
||
|
||
### 5.5 水质管控
|
||
|
||
> **对应 Issue**:#65 药剂投加监控, #66 水质检测台账
|
||
|
||
**全工艺监控参数**:
|
||
```
|
||
混凝: 进水浊度 → 絮凝剂投加速率
|
||
沉淀: 沉淀池液位、出水浊度
|
||
过滤: 滤池液位、过滤速度
|
||
消毒: 消毒剂投加速率 → 出厂水余氯
|
||
```
|
||
|
||
**合格判定 (GB5749-2022)**:
|
||
```java
|
||
public boolean isQualified(QualityRecord record) {
|
||
return record.getTurbidity() <= 1.0 // NTU
|
||
&& record.getPh() >= 6.5 && record.getPh() <= 8.5
|
||
&& record.getResidualCl() >= 0.3 // mg/L
|
||
&& record.getColiform() == 0;
|
||
}
|
||
```
|
||
|
||
### 5.6 调度工作台
|
||
|
||
> **对应 Issue**:#68 值班管理, #69 调度指令, #70 应急推演
|
||
|
||
**值班流程图**:
|
||
```
|
||
排班(按月) → 值班开始 → 实时监测+指令处理 → 交接班(记录日志) → 值班结束
|
||
```
|
||
|
||
**应急推演四场景**:
|
||
1. 爆管模拟:选择管线位置 → 分析阀门关闭策略 → 生成受影响区域 → 应急供水方案
|
||
2. 水质异常:选择污染源 → 扩散范围模拟 → 排放/关闭方案
|
||
3. 设备故障:选择设备 → 切换备用方案
|
||
4. 停水预案:区域选择 → 影响用户统计 → 通知方案
|
||
|
||
### 5.7 报警管理
|
||
|
||
> **对应 Issue**:#65(含药剂报警), #67(报警管理中心)
|
||
|
||
**报警生命周期**:
|
||
```
|
||
规则命中 → 创建 Alert(去重检查) → WebSocket推送 + APP推送
|
||
→ 未确认(持续提醒) → 确认 → 派单(生成工单) → 处理 → 恢复 → 归档
|
||
```
|
||
|
||
### 5.8 系统管理
|
||
|
||
> **对应 Issue**:#74 系统管理
|
||
|
||
**路由**:
|
||
```
|
||
/system/roles → 角色管理 (CRUD + 权限分配树)
|
||
/system/users → 用户管理 (CRUD + 角色分配)
|
||
/system/depts → 部门管理 (树形表格 + 拖拽排序)
|
||
/system/menus → 菜单管理 (树形表格)
|
||
/system/logs → 日志查看 (搜索 + 导出)
|
||
/system/dict → 字典管理 (CRUD)
|
||
```
|
||
|
||
---
|
||
|
||
## 第6章 营业收费
|
||
|
||
### 6.1 营收统一管理
|
||
|
||
> **对应 Issue**:#46 SSO 单点登录, #47 平台运维审计 + 用户授权
|
||
|
||
**OAuth2 授权码流程**:
|
||
```
|
||
用户访问客户端 → 重定向 /oauth2/authorize → 登录 → 授权确认
|
||
→ 回调 redirect_uri?code=xxx → 客户端换取 access_token
|
||
→ POST /oauth2/token {grant_type: authorization_code, code, client_id, client_secret}
|
||
→ {access_token, refresh_token, expires_in}
|
||
```
|
||
|
||
### 6.2 报装管理系统
|
||
|
||
> **对应 Issue**:#48 报装核心流程, #49 报装查询统计
|
||
|
||
**状态机**:
|
||
```
|
||
pre_accept → site_survey → engineering → dispatched → constructing → completed
|
||
↘ 驳回 → pre_accept (重新提交)
|
||
```
|
||
|
||
**报装首页概览 API**:
|
||
```
|
||
GET /api/revenue/install/overview
|
||
→ { total, pending, inProgress, completedThisMonth, avgDays }
|
||
```
|
||
|
||
### 6.3 抄表与收费
|
||
|
||
> **对应 Issue**:#50 抄表管理, #51 账单生成+多支付渠道
|
||
|
||
**阶梯水价计算公式**:
|
||
```java
|
||
// 以居民用水为例 (三阶梯):
|
||
// Tier 1: 0-15 m³ → 2.80 元/m³
|
||
// Tier 2: 15-25 m³ → 4.20 元/m³
|
||
// Tier 3: > 25 m³ → 8.40 元/m³
|
||
BigDecimal calcWaterFee(BigDecimal usage, String customerType) {
|
||
List<PriceTier> tiers = priceService.getTiers(customerType);
|
||
BigDecimal fee = BigDecimal.ZERO;
|
||
BigDecimal remaining = usage;
|
||
for (PriceTier tier : tiers) {
|
||
BigDecimal tierUsage = min(remaining, tier.getRange());
|
||
fee = fee.add(tierUsage.multiply(tier.getUnitPrice()));
|
||
remaining = remaining.subtract(tierUsage);
|
||
if (remaining.compareTo(BigDecimal.ZERO) <= 0) break;
|
||
}
|
||
return fee;
|
||
}
|
||
```
|
||
|
||
**支付渠道集成**:
|
||
|
||
| 渠道 | 接口 | 回调 |
|
||
|------|------|------|
|
||
| 支付宝 | /api/revenue/payment/alipay/create | /api/revenue/payment/alipay/notify |
|
||
| 微信支付 | /api/revenue/payment/wechat/create | /api/revenue/payment/wechat/notify |
|
||
| 柜台 | /api/revenue/payment/counter/pay | 无需回调 |
|
||
| POS | /api/revenue/payment/pos/pay | 无需回调 |
|
||
|
||
### 6.4 表务管理
|
||
|
||
> **对应 Issue**:#53 表务管理
|
||
|
||
**水表全生命周期状态机**:
|
||
```
|
||
采购入库(in_stock) → 安装出库 → 已安装(installed)
|
||
→ 暂拆(dismantled) → 复接(installed)
|
||
→ 故障换表 - 旧表(scrapped) + 新表(installed)
|
||
→ 周期换表 - 旧表(scrapped/renovated) + 新表(installed)
|
||
→ 销户撤表(scrapped)
|
||
已安装 → 校表(calibrating) → 已校表 → 重新安装 或 报废
|
||
```
|
||
|
||
**12 个操作**:入库、出库、安装、暂拆、复接、故障换表、周期换表、销户撤表、新表交回、旧表交回、报废、翻新。
|
||
|
||
### 6.5 集抄系统
|
||
|
||
> **对应 Issue**:#58 远传集抄, #59 DMA分区计量+漏损分析
|
||
|
||
**批量抄表**:
|
||
```
|
||
定时任务 (每日0点) → MQTT 批量抄表指令 → 远传水表响应
|
||
→ Kafka → 数据引擎解析 → 写入 rev_reading
|
||
→ 标记异常读数 (负值/突变/零值超过N天) → 生成核查工单
|
||
```
|
||
|
||
**DMA 分区漏损分析**:
|
||
```
|
||
DMA 入口流量计 - Σ(分区内所有户表) = 漏损量
|
||
夜间最小流量法 (02:00-04:00) → 排除正常用水 → 估算物理漏损
|
||
ECharts:
|
||
├── 分区漏损率柱状图
|
||
├── 漏损量趋势折线 (日/周/月)
|
||
├── 夜间最小流量趋势 (7天)
|
||
└── 供售水量对比 (桑基图 or 并排柱状)
|
||
```
|
||
|
||
### 6.6 工单管理
|
||
|
||
> **对应 Issue**:#60 工单管理
|
||
|
||
**工单流转**:
|
||
```
|
||
创建(手动/报警触发/巡检上报) → 分派(按片区/技能) → 接受 → 处理中
|
||
→ 处理完成(填写结果+拍照) → 审核 → 关闭
|
||
→ 驳回 → 处理中
|
||
```
|
||
|
||
**跨模块联动**:
|
||
- 报警中心 → 自动创建报警工单
|
||
- 巡检问题上报 → 自动创建巡检工单
|
||
- 设备故障 → 自动创建维修工单
|
||
- BPM 流程引擎 → 复杂审批流程
|
||
|
||
---
|
||
|
||
## 第7章 巡检管理系统
|
||
|
||
> **对应 Issue**:#75 巡检路线+任务, #76 巡检执行+GPS, #77 问题上报+工单, #78 统计分析
|
||
|
||
### 7.1 巡检配置
|
||
|
||
**路线设计**:
|
||
```json
|
||
{
|
||
"routeName": "托里片区巡检路线A",
|
||
"area": "托里片区",
|
||
"checkpoints": [
|
||
{"seq": 1, "name": "托里水厂进水口", "lng": 82.123, "lat": 44.567,
|
||
"deviceIds": [101,102], "checkItems": [{"item":"流量计读数","standard":"正常范围"},
|
||
{"item":"管道外观","standard":"无泄漏"}]}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 7.2 巡检执行
|
||
|
||
**GPS 轨迹记录策略**:
|
||
- 巡检开始 → 启动 GPS 采集 (每 10s 上报一次坐标)
|
||
- 到达检查点 → 系统自动判断 (距离 < 30m)
|
||
- 填写检查项 → 拍照 → 签字确认
|
||
- 异常 → 问题上报 (拍照+文字+语音)
|
||
- 巡检结束 → 停止 GPS → 计算总里程
|
||
|
||
### 7.3 统计分析
|
||
|
||
**统计维度**:
|
||
```sql
|
||
-- 每日汇总 (由 cron 凌晨执行)
|
||
INSERT INTO patrol_stats_daily
|
||
SELECT
|
||
CURRENT_DATE, assignee_id, area_id,
|
||
COUNT(*),
|
||
SUM(CASE WHEN status='completed' THEN 1 ELSE 0 END),
|
||
SUM(distance),
|
||
SUM(EXTRACT(EPOCH FROM actual_end - actual_start)/60),
|
||
(SELECT COUNT(*) FROM patrol_issue WHERE task_id IN (...))
|
||
FROM patrol_task WHERE plan_date = CURRENT_DATE - 1
|
||
GROUP BY assignee_id, area_id
|
||
```
|
||
|
||
**统计 API**:
|
||
```
|
||
GET /api/patrol/stats/completion-rate?start=2026-06-01&end=2026-06-14
|
||
GET /api/patrol/stats/mileage?assigneeId={id}&month=2026-06
|
||
GET /api/patrol/stats/attendance?month=2026-06
|
||
GET /api/patrol/stats/issues?category=device_fault&start=2026-06-01
|
||
GET /api/patrol/rank?type=mileage&start=2026-06-01&end=2026-06-14&limit=20
|
||
```
|
||
|
||
---
|
||
|
||
## 第8章 移动APP
|
||
|
||
> **对应 Issue**:#79 Flutter统一入口, #80 供水管理移动端, #81 巡检+营收移动端
|
||
|
||
### 8.1 Flutter 项目结构
|
||
|
||
```
|
||
mobile/lib/
|
||
├── main.dart # App入口,路由配置
|
||
├── app.dart # MaterialApp + Provider 注入
|
||
├── pages/
|
||
│ ├── login/login_page.dart # 统一登录页 (SSO)
|
||
│ ├── home/home_page.dart # 三合一底部导航首页
|
||
│ ├── production/ # 供水管理
|
||
│ │ ├── monitor_page.dart # 实时监测列表
|
||
│ │ ├── alert_page.dart # 报警列表
|
||
│ │ └── dispatch_page.dart # 调度指令
|
||
│ ├── patrol/ # 巡检
|
||
│ │ ├── task_list_page.dart # 任务列表
|
||
│ │ ├── patrol_page.dart # 巡检执行 (GPS+拍照)
|
||
│ │ ├── gps_track_page.dart # 轨迹查看
|
||
│ │ └── issue_report_page.dart # 问题上报
|
||
│ └── revenue/ # 营收
|
||
│ ├── meter_read_page.dart # 移动抄表
|
||
│ ├── bill_query_page.dart # 账单查询
|
||
│ └── install_progress_page.dart # 报装进度
|
||
├── services/ # API 服务层
|
||
│ ├── auth_service.dart
|
||
│ ├── production_service.dart
|
||
│ ├── patrol_service.dart
|
||
│ └── revenue_service.dart
|
||
├── models/ # 数据模型
|
||
└── widgets/ # 公共组件
|
||
```
|
||
|
||
### 8.2 底部 Tab 导航
|
||
|
||
```
|
||
供水管理 | 巡检 | 营收
|
||
🏭 🔍 💰
|
||
```
|
||
|
||
### 8.3 离线缓存策略
|
||
|
||
巡检场景(山区/偏远站点可能无网络):
|
||
```dart
|
||
// 使用 Hive 本地存储
|
||
Future<void> syncTaskData() async {
|
||
if (await hasNetwork()) {
|
||
var tasks = await patrolService.fetchTasks();
|
||
await hiveBox.put('tasks', tasks);
|
||
}
|
||
}
|
||
// 离线巡检:数据暂存本地,网络恢复后自动上传
|
||
Future<void> reportIssue(Issue issue) async {
|
||
if (await hasNetwork()) {
|
||
await patrolService.reportIssue(issue);
|
||
} else {
|
||
await offlineBox.add(issue.toJson());
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 第9章 大数据分析
|
||
|
||
> **对应 Issue**:#36 ETL管道, #37 BI看板, #38 运营仪表盘, #39 需水量预测, #40 报告生成
|
||
|
||
### 9.1 ETL 数据管道
|
||
|
||
**Flink 流式处理**:
|
||
```
|
||
Kafka(iot.raw.*) → Flink 作业
|
||
→ 数据解析 → 异常过滤 → 聚合(1min窗口)
|
||
→ Sink: TDengine (时序) + PostgreSQL (汇总)
|
||
```
|
||
|
||
### 9.2 BI 看板集成
|
||
|
||
**推荐方案**:Apache Superset 嵌入
|
||
```
|
||
前端 iframe 嵌入 Superset Dashboard (SSO token 透传)
|
||
├── 供水运营总览
|
||
├── 营收分析
|
||
├── 巡检统计
|
||
└── 自定义 SQL 查询
|
||
```
|
||
|
||
### 9.3 专供水专题大屏
|
||
|
||
**大屏布局 (1920×1080)**:
|
||
```
|
||
┌─────────────────────────────────────────────────────┐
|
||
│ 精河县智慧水务综合管理平台 2026-06-14 14:30 │
|
||
├──────────┬──────────┬──────────┬──────────────────────┤
|
||
│ 今日进水 │ 今日出水 │ 昨日供水 │ 设备在线率 │
|
||
├──────────┴──────────┴──────────┴──────────────────────┤
|
||
│ 进出水量趋势 (折线图) │ 供水区域 GIS 地图 │
|
||
│ │ (监测点位+报警闪烁) │
|
||
├───────────────────────────┤ │
|
||
│ 水质达标率 (仪表盘) │ │
|
||
│ 报警分布 (饼图) │ │
|
||
│ 能耗药耗 (柱状图) │ │
|
||
├──────────────────────────────────────────────────────┤
|
||
│ 实时报警滚动 | 巡检任务统计 | 营收总额统计 │
|
||
└──────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 9.4 需水量预测
|
||
|
||
**模型选择**:
|
||
- 短期 (24h):ARIMA 时间序列 (数据量要求低,可快速部署)
|
||
- 长期 (月):LSTM 神经网络 (需积累 > 12个月历史数据后启用)
|
||
|
||
**API**:
|
||
```
|
||
GET /api/bi/predict/water-demand?area={area}&hours=24
|
||
Response: [{ts, predicted, lowerBound, upperBound}, ...]
|
||
```
|
||
|
||
---
|
||
|
||
## 文档版本
|
||
|
||
| 版本 | 日期 | 修订内容 | 修订人 |
|
||
|------|------|----------|--------|
|
||
| v2.0 | 2026-06-14 | 详细设计规格书,含全部模块DB/API/组件/数据流 | bot_pm |
|
||
|
||
---
|
||
|
||
## 附录:Issue ↔ 章节对照表
|
||
|
||
| Issue # | 标题 | 设计文档章节 |
|
||
|:---:|------|------|
|
||
| 17 | 项目框架搭建 | §1.1 Maven模块结构 |
|
||
| 18 | 数据库设计 | §1.2 数据库完整DDL |
|
||
| 19 | 认证授权系统 | §1.3 认证授权系统设计 |
|
||
| 20 | 通用模块 | §1.1 wm-common + §1.3 统一响应 |
|
||
| 21 | GIS引擎集成 | §1.4 GIS引擎集成 |
|
||
| 22 | IoT设备接入层 | §1.5 IoT设备接入层 |
|
||
| 23 | 前端框架搭建 | §1.1 frontend/ 结构 + §5.1 组件树 |
|
||
| 24 | Flutter移动端框架 | §8.1 Flutter项目结构 |
|
||
| 25 | DevOps | §1.1 docker/ + §1.2 技术栈 |
|
||
| 26 | 消息通知模块 | §1.6 消息通知模块 |
|
||
| 28 | MQTT协议适配器 | §2.1 多协议适配器 |
|
||
| 29 | Modbus/CoAP/HTTP适配 | §2.1 AdapterFactory |
|
||
| 30 | 设备影子+OTA | §2.2 设备影子服务 |
|
||
| 31 | 设备管理前端 | §2.3 IoT前端页面 |
|
||
| 32 | BPM流程引擎核心 | §3.1 Camunda集成 |
|
||
| 33 | BPMN.js设计器 | §3.1 BPMN.js集成 |
|
||
| 34 | BPM统计评估 | §3.1 API端点 (stats) |
|
||
| 35 | BPM跨系统编排 | §3.1 Webhook回调 |
|
||
| 36 | ETL数据管道 | §9.1 ETL数据管道 |
|
||
| 37 | BI看板 | §9.2 BI看板集成 |
|
||
| 38 | 运营仪表盘+大屏 | §9.3 供水专题大屏 |
|
||
| 39 | 需水量预测 | §9.4 需水量预测 |
|
||
| 40 | 报告生成 | §9.4 报告生成 |
|
||
| 41 | 实时流数据采集 | §4.1 实时数据采集 |
|
||
| 42 | 数据接入层 | §4.2 数据接入层 |
|
||
| 43 | 数据存储层 | §4.3 数据存储层 |
|
||
| 44 | 数据治理 | §4.4 数据治理 |
|
||
| 46 | SSO单点登录 | §6.1 营收统一管理 |
|
||
| 48 | 报装核心流程 | §6.2 报装管理系统 |
|
||
| 49 | 报装查询统计 | §6.2 状态机+概览 |
|
||
| 50 | 抄表管理 | §6.3 抄表与收费 |
|
||
| 51 | 账单+多支付 | §6.3 阶梯水价+支付 |
|
||
| 53 | 表务管理 | §6.4 表务管理 |
|
||
| 54 | 客服工作台 | §1.2.6 cs_kb_article |
|
||
| 56 | 微信网厅前端 | §1.2.6 rev_wx_pay_order |
|
||
| 58 | 远传集抄 | §6.5 批量抄表 |
|
||
| 60 | 工单管理 | §6.6 工单管理 |
|
||
| 61 | 总览大屏 | §5.1 生产总览大屏 |
|
||
| 62 | 在线监测列表 | §5.2 在线监测列表 |
|
||
| 63 | 视频监控+AI | §5.3 视频监控与AI |
|
||
| 64 | GIS地图展示 | §5.4 GIS地图展示 |
|
||
| 65 | 药剂投加监控 | §5.5 水质管控 |
|
||
| 66 | 水质检测台账 | §5.5 合格判定 |
|
||
| 68 | 值班管理 | §5.6 调度工作台 |
|
||
| 69 | 调度指令 | §5.6 指令台账 |
|
||
| 70 | 应急推演 | §5.6 应急推演四场景 |
|
||
| 74 | 系统管理 | §5.8 系统管理 |
|
||
| 75 | 巡检路线+任务 | §7.1 巡检配置 |
|
||
| 76 | 巡检执行+GPS | §7.2 巡检执行 |
|
||
| 77 | 问题上报+工单 | §1.2.8 patrol_issue |
|
||
| 78 | 统计分析 | §7.3 统计分析 |
|
||
| 79 | Flutter统一入口 | §8.2 底部Tab导航 |
|
||
| 80 | 供水管理移动端 | §8.1 production/ 页面 |
|
||
| 81 | 巡检+营收移动端 | §8.1 patrol/ + revenue/ |
|
||
|
||
> 📌 已关闭 Issue 也列入对照表,方便追溯。
|