Phase 1 #18: PostgreSQL + TDengine 完整 DDL 建表脚本

- 15+张核心表: sys_*(部门/用户/角色/菜单/日志/字典/通知/文件)
- iot_*: 设备模型/设备实例/设备影子/设备事件/站点(PostGIS空间坐标)
- rev_*: 用水户/水价阶梯/水表档案/水表操作日志/抄表/账单/缴费/报装
- production: alert_rule(报警规则)/alert_event(报警事件)/dispatch_command(调度)/duty(值班)/patrol(巡检)/water_quality(水质)
- TDengine: iot_telemetry超级表(6类设备子表)+事件表+小时聚合
- 种子数据: admin管理员/5个角色/6个片区/基础字典
This commit is contained in:
bot_pm
2026-06-14 13:15:38 +08:00
parent e929f65948
commit f337ebedfd
6 changed files with 811 additions and 0 deletions
+210
View File
@@ -0,0 +1,210 @@
-- =============================================
-- 智慧水务管理系统 - PostgreSQL DDL
-- 版本: V1
-- 描述: 核心业务表建表脚本
-- =============================================
-- ==================== 系统管理 ====================
-- 部门表
CREATE TABLE IF NOT EXISTS sys_dept (
id BIGSERIAL PRIMARY KEY,
parent_id BIGINT,
dept_name VARCHAR(100) NOT NULL,
dept_type VARCHAR(20) NOT NULL DEFAULT 'water_company', -- water_bureau/water_company/ops
sort_order INT DEFAULT 0,
leader VARCHAR(50),
phone VARCHAR(20),
status SMALLINT DEFAULT 1,
deleted SMALLINT DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE sys_dept IS '部门表';
COMMENT ON COLUMN sys_dept.dept_type IS '部门类型: water_bureau(水利局)/water_company(水务公司)/ops(运维单位)';
-- 用户表
CREATE TABLE IF NOT EXISTS sys_user (
id BIGSERIAL PRIMARY KEY,
dept_id BIGINT REFERENCES sys_dept(id),
username VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
real_name VARCHAR(50),
nickname VARCHAR(50),
phone VARCHAR(20),
email VARCHAR(100),
avatar VARCHAR(500),
gender SMALLINT DEFAULT 0, -- 0:未知 1:男 2:女
role_type VARCHAR(30) DEFAULT 'operator', -- admin/leader/manager/operator/tech
status SMALLINT DEFAULT 1, -- 0:停用 1:启用
login_ip VARCHAR(50),
login_at TIMESTAMP,
deleted SMALLINT DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE sys_user IS '用户表';
COMMENT ON COLUMN sys_user.role_type IS '角色类型: admin/leader/manager/operator/tech';
-- 角色表
CREATE TABLE IF NOT EXISTS sys_role (
id BIGSERIAL PRIMARY KEY,
role_name VARCHAR(50) UNIQUE NOT NULL,
role_key VARCHAR(50) UNIQUE NOT NULL,
role_sort INT DEFAULT 0,
data_scope VARCHAR(20) DEFAULT 'SELF', -- ALL/DEPT/CUSTOM/SELF
status SMALLINT DEFAULT 1,
remark VARCHAR(500),
deleted SMALLINT DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE sys_role IS '角色表';
COMMENT ON COLUMN sys_role.role_key IS '角色标识: admin/supervisor/biz_manager/field_ops/tech_maintain';
COMMENT ON COLUMN sys_role.data_scope IS '数据权限范围: ALL/DEPT/CUSTOM/SELF';
-- 菜单表
CREATE TABLE IF NOT EXISTS sys_menu (
id BIGSERIAL PRIMARY KEY,
parent_id BIGINT DEFAULT 0,
menu_name VARCHAR(50) NOT NULL,
menu_type CHAR(1) DEFAULT 'M', -- M:目录 C:菜单 F:按钮
path VARCHAR(200),
component VARCHAR(255),
perms VARCHAR(100),
icon VARCHAR(100),
sort_order INT DEFAULT 0,
visible SMALLINT DEFAULT 1,
status SMALLINT DEFAULT 1,
deleted SMALLINT DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE sys_menu IS '菜单表';
-- 角色-菜单关联
CREATE TABLE IF NOT EXISTS sys_role_menu (
role_id BIGINT NOT NULL REFERENCES sys_role(id),
menu_id BIGINT NOT NULL REFERENCES sys_menu(id),
PRIMARY KEY (role_id, menu_id)
);
COMMENT ON TABLE sys_role_menu IS '角色菜单关联表';
-- 用户-角色关联
CREATE TABLE IF NOT EXISTS sys_user_role (
user_id BIGINT NOT NULL REFERENCES sys_user(id),
role_id BIGINT NOT NULL REFERENCES sys_role(id),
PRIMARY KEY (user_id, role_id)
);
COMMENT ON TABLE sys_user_role IS '用户角色关联表';
-- 操作日志表
CREATE TABLE IF NOT EXISTS sys_oper_log (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT,
username VARCHAR(50),
module VARCHAR(50),
operation VARCHAR(50),
method VARCHAR(200),
request_method VARCHAR(10),
request_url VARCHAR(500),
request_params TEXT,
response_result TEXT,
ip VARCHAR(50),
location VARCHAR(100),
duration BIGINT,
status SMALLINT DEFAULT 1,
error_msg TEXT,
created_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE sys_oper_log IS '操作日志表';
-- 登录日志表
CREATE TABLE IF NOT EXISTS sys_login_log (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(50),
ip VARCHAR(50),
location VARCHAR(100),
browser VARCHAR(100),
os VARCHAR(100),
status SMALLINT DEFAULT 1, -- 0:失败 1:成功
msg VARCHAR(500),
login_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE sys_login_log IS '登录日志表';
-- ==================== 数据字典 ====================
CREATE TABLE IF NOT EXISTS sys_dict_type (
id BIGSERIAL PRIMARY KEY,
dict_name VARCHAR(100) NOT NULL,
dict_key VARCHAR(100) UNIQUE NOT NULL,
status SMALLINT DEFAULT 1,
remark VARCHAR(500),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE sys_dict_type IS '字典类型表';
CREATE TABLE IF NOT EXISTS sys_dict_data (
id BIGSERIAL PRIMARY KEY,
dict_type_id BIGINT REFERENCES sys_dict_type(id),
dict_label VARCHAR(100) NOT NULL,
dict_value VARCHAR(100) NOT NULL,
css_class VARCHAR(100),
list_class VARCHAR(100),
sort_order INT DEFAULT 0,
status SMALLINT DEFAULT 1,
remark VARCHAR(500),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE sys_dict_data IS '字典数据表';
-- ==================== 通知方案 ====================
CREATE TABLE IF NOT EXISTS sys_notify_scheme (
id BIGSERIAL PRIMARY KEY,
scheme_name VARCHAR(100) NOT NULL,
channels VARCHAR(200), -- sms,app_push,websocket,wechat (逗号分隔)
template_id VARCHAR(50),
status SMALLINT DEFAULT 1,
created_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE sys_notify_scheme IS '通知方案表';
CREATE TABLE IF NOT EXISTS sys_notify_record (
id BIGSERIAL PRIMARY KEY,
scheme_id BIGINT REFERENCES sys_notify_scheme(id),
target_user_id BIGINT,
target_phone VARCHAR(20),
channel VARCHAR(20),
title VARCHAR(200),
content TEXT,
status VARCHAR(20) DEFAULT 'pending', -- pending/sent/failed/read
sent_at TIMESTAMP,
read_at TIMESTAMP,
error_msg VARCHAR(500),
created_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE sys_notify_record IS '通知记录表';
-- ==================== 文件管理 ====================
CREATE TABLE IF NOT EXISTS sys_file (
id BIGSERIAL PRIMARY KEY,
file_name VARCHAR(200) NOT NULL,
original_name VARCHAR(200),
file_path VARCHAR(500) NOT NULL,
file_size BIGINT,
mime_type VARCHAR(100),
file_ext VARCHAR(20),
storage_type VARCHAR(20) DEFAULT 'minio',
bucket VARCHAR(100) DEFAULT 'water-management',
module VARCHAR(50),
biz_id BIGINT,
upload_by BIGINT,
deleted SMALLINT DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE sys_file IS '文件管理表';
+101
View File
@@ -0,0 +1,101 @@
-- =============================================
-- 智慧水务管理系统 - 物联网设备相关 DDL
-- 版本: V1
-- =============================================
-- 扩展
CREATE EXTENSION IF NOT EXISTS postgis;
-- 设备模型定义
CREATE TABLE IF NOT EXISTS iot_device_model (
id BIGSERIAL PRIMARY KEY,
model_key VARCHAR(50) UNIQUE NOT NULL,
model_name VARCHAR(100) NOT NULL,
vendor VARCHAR(100),
protocol VARCHAR(20) NOT NULL, -- MQTT/Modbus/CoAP/HTTP
properties JSONB, -- [{key, name, unit, data_type, range_min, range_max}]
commands JSONB, -- [{key, name, params: [{key, name, type}]}]
status SMALLINT DEFAULT 1,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE iot_device_model IS '设备模型定义表';
COMMENT ON COLUMN iot_device_model.properties IS '属性定义JSON数组';
COMMENT ON COLUMN iot_device_model.commands IS '支持指令JSON数组';
-- 设备实例
CREATE TABLE IF NOT EXISTS 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_sensor/valve/water_quality/level_sensor/pump
position_type VARCHAR(20), -- water_plant/pressure_station/pipe_network/village
label VARCHAR(50), -- 设备标签(便于搜索)
loc_lng DOUBLE PRECISION,
loc_lat DOUBLE PRECISION,
geom GEOMETRY(Point, 4326),
area VARCHAR(50) NOT NULL, -- 所属片区
station_id BIGINT, -- 所属站点
address VARCHAR(300),
install_date DATE,
warranty_until DATE,
status VARCHAR(20) DEFAULT 'offline', -- online/offline/maintenance/fault
firmware_version VARCHAR(20),
last_report_time TIMESTAMP,
metadata JSONB,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE iot_device IS '设备实例表';
COMMENT ON COLUMN iot_device.geom IS 'PostGIS空间坐标点';
COMMENT ON COLUMN iot_device.metadata IS '扩展元数据';
-- 空间索引
CREATE INDEX IF NOT EXISTS idx_iot_device_geom ON iot_device USING GIST(geom);
CREATE INDEX IF NOT EXISTS idx_iot_device_area ON iot_device(area);
CREATE INDEX IF NOT EXISTS idx_iot_device_type ON iot_device(device_type);
CREATE INDEX IF NOT EXISTS idx_iot_device_status ON iot_device(status);
-- 设备影子
CREATE TABLE IF NOT EXISTS iot_device_shadow (
id BIGSERIAL PRIMARY KEY,
device_id BIGINT UNIQUE REFERENCES iot_device(id),
reported_state JSONB, -- 设备上报的最新状态
desired_state JSONB, -- 期望状态(云端下发)
delta_state JSONB, -- 差异状态
version BIGINT DEFAULT 1,
updated_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE iot_device_shadow IS '设备影子表';
-- 设备事件
CREATE TABLE IF NOT EXISTS iot_device_event (
id BIGSERIAL PRIMARY KEY,
device_id BIGINT REFERENCES iot_device(id),
device_sn VARCHAR(100) NOT NULL,
event_type VARCHAR(30) NOT NULL, -- online/offline/fault/recovery/ota
event_data JSONB,
created_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE iot_device_event IS '设备事件表';
CREATE INDEX IF NOT EXISTS idx_iot_device_event_sn ON iot_device_event(device_sn, created_at DESC);
-- 站点管理(水厂/调压站等)
CREATE TABLE IF NOT EXISTS iot_station (
id BIGSERIAL PRIMARY KEY,
station_name VARCHAR(100) NOT NULL,
station_type VARCHAR(30) NOT NULL, -- water_plant/pressure_station/pump_station
area VARCHAR(50) NOT NULL,
loc_lng DOUBLE PRECISION,
loc_lat DOUBLE PRECISION,
geom GEOMETRY(Point, 4326),
address VARCHAR(300),
manager VARCHAR(50),
manager_phone VARCHAR(20),
status SMALLINT DEFAULT 1,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE iot_station IS '站点管理表';
CREATE INDEX IF NOT EXISTS idx_iot_station_geom ON iot_station USING GIST(geom);
+189
View File
@@ -0,0 +1,189 @@
-- =============================================
-- 智慧水务管理系统 - 供水生产 + 巡检 + 报警 DDL
-- 版本: V1
-- =============================================
-- ==================== 报警规则 ====================
CREATE TABLE IF NOT EXISTS 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"
threshold_value DECIMAL(12,4),
debounce_sec INT DEFAULT 300, -- 去重窗口(秒)
notify_scheme_id BIGINT REFERENCES sys_notify_scheme(id),
enabled SMALLINT DEFAULT 1,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE alert_rule IS '报警规则表';
COMMENT ON COLUMN alert_rule.alert_level IS '报警等级: info/warning/critical/emergency';
CREATE TABLE IF NOT EXISTS alert_event (
id BIGSERIAL PRIMARY KEY,
rule_id BIGINT REFERENCES alert_rule(id),
device_id BIGINT,
device_sn VARCHAR(100) NOT NULL,
device_name VARCHAR(200),
area VARCHAR(50),
metric_key VARCHAR(50) NOT NULL,
metric_value DECIMAL(12,4),
threshold_value VARCHAR(50),
alert_level VARCHAR(10) NOT NULL,
title VARCHAR(200),
message TEXT,
confirmed_by BIGINT,
confirmed_at TIMESTAMP,
dispatched SMALLINT DEFAULT 0, -- 是否已派单
resolved_by BIGINT,
resolved_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE alert_event IS '报警事件表';
CREATE INDEX IF NOT EXISTS idx_alert_event_time ON alert_event(created_at DESC);
CREATE INDEX IF NOT EXISTS idx_alert_event_device ON alert_event(device_sn, created_at DESC);
-- ==================== 调度指令 ====================
CREATE TABLE IF NOT EXISTS dispatch_command (
id BIGSERIAL PRIMARY KEY,
command_no VARCHAR(30) UNIQUE NOT NULL,
command_type VARCHAR(30) NOT NULL, -- routine/emergency
command_title VARCHAR(200) NOT NULL,
command_content TEXT NOT NULL,
source VARCHAR(50), -- 来源: 平台/SCADA/上级
issuer_id BIGINT,
issuer_name VARCHAR(50),
target_type VARCHAR(30), -- station/device_area/person
target_ids JSONB, -- 目标站点/设备ID数组
priority VARCHAR(10) DEFAULT 'normal', -- low/normal/high/urgent
status VARCHAR(20) DEFAULT 'draft', -- draft/issued/received/executing/completed/rejected
issued_at TIMESTAMP,
received_at TIMESTAMP,
completed_at TIMESTAMP,
result_remark TEXT,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE dispatch_command IS '调度指令表';
CREATE TABLE IF NOT EXISTS dispatch_log (
id BIGSERIAL PRIMARY KEY,
command_id BIGINT REFERENCES dispatch_command(id),
action VARCHAR(20) NOT NULL, -- issue/receive/execute/complete/reject
operator_id BIGINT,
operator_name VARCHAR(50),
remark TEXT,
created_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE dispatch_log IS '调度指令操作日志';
-- ==================== 值班管理 ====================
CREATE TABLE IF NOT EXISTS duty_schedule (
id BIGSERIAL PRIMARY KEY,
schedule_name VARCHAR(100),
dept_id BIGINT REFERENCES sys_dept(id),
station_id BIGINT,
shift_type VARCHAR(20), -- day/night/full
start_time TIME NOT NULL,
end_time TIME NOT NULL,
status SMALLINT DEFAULT 1,
created_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE duty_schedule IS '值班班次表';
CREATE TABLE IF NOT EXISTS duty_record (
id BIGSERIAL PRIMARY KEY,
schedule_id BIGINT REFERENCES duty_schedule(id),
duty_date DATE NOT NULL,
user_id BIGINT REFERENCES sys_user(id),
shift_type VARCHAR(20),
on_duty_at TIMESTAMP,
off_duty_at TIMESTAMP,
status VARCHAR(20) DEFAULT 'pending', -- pending/on_duty/off_duty
handover_remark TEXT,
created_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE duty_record IS '值班记录表';
-- ==================== 巡检管理 ====================
CREATE TABLE IF NOT EXISTS patrol_route (
id BIGSERIAL PRIMARY KEY,
route_name VARCHAR(100) NOT NULL,
area VARCHAR(50) NOT NULL,
route_points JSONB, -- [{seq, lng, lat, name, device_ids}]
estim_duration INT, -- 预计时长(分钟)
status SMALLINT DEFAULT 1,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE patrol_route IS '巡检路线表';
CREATE TABLE IF NOT EXISTS patrol_task (
id BIGSERIAL PRIMARY KEY,
route_id BIGINT REFERENCES patrol_route(id),
assignee_id BIGINT REFERENCES sys_user(id),
task_name VARCHAR(200),
task_date DATE NOT NULL,
plan_start TIMESTAMP,
plan_end TIMESTAMP,
actual_start TIMESTAMP,
actual_end TIMESTAMP,
status VARCHAR(20) DEFAULT 'pending', -- pending/in_progress/completed/expired/cancelled
distance DECIMAL(8,2), -- 实际巡检距离(km)
score INT, -- 评分
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE patrol_task IS '巡检任务表';
CREATE INDEX IF NOT EXISTS idx_patrol_task_date ON patrol_task(task_date);
CREATE TABLE IF NOT EXISTS patrol_record (
id BIGSERIAL PRIMARY KEY,
task_id BIGINT REFERENCES patrol_task(id),
point_seq INT,
device_id BIGINT,
device_name VARCHAR(200),
check_items JSONB, -- [{item, result, value, photo_urls, remark}]
gps_lng DOUBLE PRECISION,
gps_lat DOUBLE PRECISION,
geom GEOMETRY(Point, 4326),
record_time TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE patrol_record IS '巡检记录表';
CREATE INDEX IF NOT EXISTS idx_patrol_record_geom ON patrol_record USING GIST(geom);
-- ==================== 水质检测 ====================
CREATE TABLE IF NOT EXISTS water_quality_record (
id BIGSERIAL PRIMARY KEY,
test_type VARCHAR(20) NOT NULL, -- manual/auto
test_point VARCHAR(100) NOT NULL, -- 检测点位名称
point_type VARCHAR(20), -- source_water/plant_out/pipe_network/terminal
area VARCHAR(50),
station_id BIGINT,
lng DOUBLE PRECISION,
lat DOUBLE PRECISION,
test_date DATE NOT NULL,
test_time TIME,
tester VARCHAR(50),
turbidity DECIMAL(8,2), -- 浊度(NTU)
ph DECIMAL(5,2),
residual_chlorine DECIMAL(8,2), -- 余氯(mg/L)
total_chlorine DECIMAL(8,2),
cod DECIMAL(8,2), -- 化学需氧量(mg/L)
ammonia DECIMAL(8,2), -- 氨氮(mg/L)
total_bacteria INT, -- 总大肠菌群(CFU/100mL)
extra_data JSONB, -- 扩展指标
is_qualified SMALLINT,
created_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE water_quality_record IS '水质检测记录表';
CREATE INDEX IF NOT EXISTS idx_wq_record_date ON water_quality_record(test_date);
CREATE INDEX IF NOT EXISTS idx_wq_record_area ON water_quality_record(area);
+164
View File
@@ -0,0 +1,164 @@
-- =============================================
-- 智慧水务管理系统 - 营业收费相关 DDL
-- 版本: V1
-- =============================================
-- 用水户
CREATE TABLE IF NOT EXISTS 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),
open_date DATE,
meter_count INT DEFAULT 0,
status VARCHAR(20) DEFAULT 'active', -- active/suspended/closed
remark VARCHAR(500),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE rev_customer IS '用水户表';
-- 水价阶梯
CREATE TABLE IF NOT EXISTS rev_water_price (
id BIGSERIAL PRIMARY KEY,
customer_type VARCHAR(20) NOT NULL, -- residential/business/enterprise/institution
tier_no INT NOT NULL, -- 第几阶梯
range_start DECIMAL(12,2) DEFAULT 0, -- 起始水量(立方米)
range_end DECIMAL(12,2), -- 结束水量(null=无上限)
water_price DECIMAL(10,4) NOT NULL, -- 水价(元/立方米)
sewage_price DECIMAL(10,4) DEFAULT 0, -- 污水处理费
effective_date DATE NOT NULL,
status SMALLINT DEFAULT 1,
created_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE rev_water_price IS '水价阶梯配置表';
-- 水表档案
CREATE TABLE IF NOT EXISTS 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), -- DN15/DN20/DN40/DN80+
meter_type VARCHAR(20), -- mechanical/ultrasonic/electromagnetic
manufacturer VARCHAR(100),
max_reading DECIMAL(10,2) DEFAULT 99999,
initial_reading DECIMAL(10,2) DEFAULT 0,
current_reading DECIMAL(10,2) DEFAULT 0,
install_date DATE,
install_address VARCHAR(300),
status VARCHAR(20) DEFAULT 'active', -- active/dismantled/scrapped/repaired/warehouse
remark VARCHAR(500),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE rev_meter IS '水表档案表';
-- 水表操作记录(全生命周期)
CREATE TABLE IF NOT EXISTS rev_meter_log (
id BIGSERIAL PRIMARY KEY,
meter_id BIGINT REFERENCES rev_meter(id),
operation_type VARCHAR(30) NOT NULL, -- install/dismantle/repair/change/scrap/calibrate/refurbish
old_reading DECIMAL(10,2),
new_reading DECIMAL(10,2),
new_meter_no VARCHAR(50),
operator_id BIGINT,
operator_name VARCHAR(50),
photos JSONB, -- 现场照片URL数组
remark VARCHAR(500),
created_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE rev_meter_log IS '水表操作记录表(全生命周期)';
-- 抄表记录
CREATE TABLE IF NOT EXISTS rev_reading (
id BIGSERIAL PRIMARY KEY,
meter_id BIGINT REFERENCES rev_meter(id),
reading_date DATE NOT NULL,
reading_period VARCHAR(10), -- 2026-06
prev_reading DECIMAL(10,2),
curr_reading DECIMAL(10,2),
consumption DECIMAL(10,2),
read_type VARCHAR(20) DEFAULT 'manual', -- manual/remote/estimate
reader_id BIGINT,
reader_name VARCHAR(50),
photo_urls JSONB, -- 拍照图片URL数组
abnormal_flag SMALLINT DEFAULT 0, -- 0:正常 1:异常
verified SMALLINT DEFAULT 0, -- 0:未审核 1:已审核
verified_by BIGINT,
verified_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE rev_reading IS '抄表记录表';
CREATE INDEX IF NOT EXISTS idx_reading_period ON rev_reading(reading_period);
-- 水费账单
CREATE TABLE IF NOT EXISTS rev_bill (
id BIGSERIAL PRIMARY KEY,
bill_no VARCHAR(30) UNIQUE NOT NULL,
customer_id BIGINT REFERENCES rev_customer(id),
meter_id BIGINT REFERENCES rev_meter(id),
reading_id BIGINT REFERENCES rev_reading(id),
bill_period VARCHAR(10) NOT NULL, -- 2026-06
prev_reading DECIMAL(10,2),
curr_reading DECIMAL(10,2),
consumption DECIMAL(10,2),
water_fee DECIMAL(10,2),
sewage_fee DECIMAL(10,2),
other_fee DECIMAL(10,2) DEFAULT 0, -- 污水处理费/垃圾处理费等
total_fee DECIMAL(10,2),
paid_fee DECIMAL(10,2) DEFAULT 0,
discount_fee DECIMAL(10,2) DEFAULT 0,
status VARCHAR(20) DEFAULT 'pending', -- pending/partial/paid/overdue/cancelled
due_date DATE,
paid_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE rev_bill IS '水费账单表';
CREATE INDEX IF NOT EXISTS idx_bill_customer ON rev_bill(customer_id, bill_period);
CREATE INDEX IF NOT EXISTS idx_bill_status ON rev_bill(status);
-- 缴费记录
CREATE TABLE IF NOT EXISTS rev_payment (
id BIGSERIAL PRIMARY KEY,
bill_id BIGINT REFERENCES rev_bill(id),
customer_id BIGINT REFERENCES rev_customer(id),
payment_no VARCHAR(50) UNIQUE NOT NULL,
amount DECIMAL(10,2) NOT NULL,
pay_method VARCHAR(20), -- wechat/alipay/cash/bank_transfer/pos
pay_channel VARCHAR(30), -- counter/app/wechat_mini/third_party
transaction_id VARCHAR(100),
operator_id BIGINT,
remark VARCHAR(500),
paid_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE rev_payment IS '缴费记录表';
-- 报装申请
CREATE TABLE IF NOT EXISTS rev_install (
id BIGSERIAL PRIMARY KEY,
application_no VARCHAR(30) UNIQUE NOT NULL,
applicant_name VARCHAR(50) NOT NULL,
applicant_phone VARCHAR(20) NOT NULL,
applicant_id_card VARCHAR(18),
area VARCHAR(50),
address VARCHAR(300),
customer_type VARCHAR(20), -- residential/business/enterprise
caliber VARCHAR(10), -- 申请管径
purpose VARCHAR(200),
status VARCHAR(20) DEFAULT 'pre_apply', -- pre_apply/engineering/pending_review/approved/rejected/completed
survey_date DATE,
survey_result TEXT,
approved_by BIGINT,
approved_at TIMESTAMP,
completed_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
COMMENT ON TABLE rev_install IS '报装申请表';
+79
View File
@@ -0,0 +1,79 @@
-- =============================================
-- 种子数据:管理员 + 基础角色 + 字典
-- =============================================
-- 插入部门
INSERT INTO sys_dept (id, parent_id, dept_name, dept_type, sort_order) VALUES
(1, NULL, '精河县水利局', 'water_bureau', 1),
(2, NULL, '安阜清源水务公司', 'water_company', 2),
(3, 2, '一体化水厂', 'water_company', 1),
(4, 2, '精芒片区', 'water_company', 2),
(5, 2, '八家户片区', 'water_company', 3),
(6, 2, '托里片区', 'water_company', 4),
(7, 2, '大镇阿合其片区', 'water_company', 5),
(8, 2, '托托片区', 'water_company', 6),
(9, 2, '运维中心', 'ops', 7)
ON CONFLICT DO NOTHING;
-- 重置序列
SELECT setval('sys_dept_id_seq', (SELECT MAX(id) FROM sys_dept));
-- 插入角色
INSERT INTO sys_role (id, role_name, role_key, role_sort, data_scope, remark) VALUES
(1, '系统管理员', 'admin', 1, 'ALL', '最高权限,管理全部功能'),
(2, '水务分管领导', 'leader', 2, 'ALL', '查看全部数据、BI看板'),
(3, '水务业务管理人员', 'manager', 3, 'DEPT', '调度、营收、水质管理'),
(4, '现场运维操作人员', 'operator', 4, 'DEPT', '巡检、值班、工单处理'),
(5, '系统技术维护人员', 'tech', 5, 'DEPT', '配置管理、设备维护')
ON CONFLICT (role_key) DO NOTHING;
-- 插入管理员用户 (密码: admin123, BCrypt加密)
INSERT INTO sys_user (id, dept_id, username, password, real_name, role_type, status) VALUES
(1, 1, 'admin', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lE9lBOsl7iAt6Z5Eh', '系统管理员', 'admin', 1)
ON CONFLICT (username) DO NOTHING;
-- 管理员关联角色
INSERT INTO sys_user_role (user_id, role_id) VALUES (1, 1) ON CONFLICT DO NOTHING;
-- 插入字典类型
INSERT INTO sys_dict_type (id, dict_key, dict_name) VALUES
(1, 'device_type', '设备类型'),
(2, 'area', '片区'),
(3, 'customer_type', '用水户类型'),
(4, 'alert_level', '报警等级'),
(5, 'meter_status', '水表状态')
ON CONFLICT (dict_key) DO NOTHING;
-- 插入字典数据
INSERT INTO sys_dict_data (dict_type_id, dict_label, dict_value, sort_order) VALUES
-- 设备类型
(1, '流量计', 'flow_meter', 1),
(1, '压力传感器', 'pressure_sensor', 2),
(1, '电动阀门', 'valve', 3),
(1, '水质监测仪', 'water_quality', 4),
(1, '液位计', 'level_sensor', 5),
(1, '水泵', 'pump', 6),
-- 片区
(2, '一体化水厂', '一体化水厂', 1),
(2, '精芒片区', '精芒片区', 2),
(2, '八家户片区', '八家户片区', 3),
(2, '托里片区', '托里片区', 4),
(2, '大镇阿合其片区', '大镇阿合其片区', 5),
(2, '托托片区', '托托片区', 6),
-- 用水户类型
(3, '居民', 'residential', 1),
(3, '商业', 'business', 2),
(3, '企业', 'enterprise', 3),
(3, '事业单位', 'institution', 4),
-- 报警等级
(4, '提示', 'info', 1),
(4, '一般', 'warning', 2),
(4, '严重', 'critical', 3),
(4, '紧急', 'emergency', 4),
-- 水表状态
(5, '正常使用', 'active', 1),
(5, '已拆除', 'dismantled', 2),
(5, '已报废', 'scrapped', 3),
(5, '维修中', 'repaired', 4),
(5, '库存', 'warehouse', 5)
ON CONFLICT DO NOTHING;
+68
View File
@@ -0,0 +1,68 @@
-- =============================================
-- 智慧水务管理系统 - TDengine 建表脚本
-- 用于物联网设备遥测数据存储
-- =============================================
-- 创建数据库
CREATE DATABASE IF NOT EXISTS water_iot
KEEP 365
DURATION 30
BUFFER 256
PAGES 256
PAGESIZE 4
WAL_LEVEL 1;
USE water_iot;
-- 遥测数据超级表
CREATE STABLE IF NOT EXISTS iot_telemetry (
ts TIMESTAMP,
device_sn NCHAR(100),
metric_key NCHAR(50),
metric_value DOUBLE,
quality TINYINT
) TAGS (
device_type NCHAR(30),
area NCHAR(50),
station NCHAR(100)
);
-- 按设备类型创建子表(模板,实际运行时动态创建)
CREATE TABLE IF NOT EXISTS telemetry_flow_meter USING iot_telemetry TAGS('flow_meter', 'default', 'default');
CREATE TABLE IF NOT EXISTS telemetry_pressure USING iot_telemetry TAGS('pressure_sensor', 'default', 'default');
CREATE TABLE IF NOT EXISTS telemetry_valve USING iot_telemetry TAGS('valve', 'default', 'default');
CREATE TABLE IF NOT EXISTS telemetry_water_quality USING iot_telemetry TAGS('water_quality', 'default', 'default');
CREATE TABLE IF NOT EXISTS telemetry_level USING iot_telemetry TAGS('level_sensor', 'default', 'default');
CREATE TABLE IF NOT EXISTS telemetry_pump USING iot_telemetry TAGS('pump', 'default', 'default');
-- 设备事件超级表
CREATE STABLE IF NOT EXISTS iot_device_event (
ts TIMESTAMP,
device_sn NCHAR(100),
event_type NCHAR(30),
event_data NCHAR(2000)
) TAGS (
device_type NCHAR(30),
area NCHAR(50)
);
-- 小时聚合超级表(自动聚合)
CREATE STABLE IF NOT EXISTS iot_telemetry_hourly (
ts TIMESTAMP,
device_sn NCHAR(100),
metric_key NCHAR(50),
min_value DOUBLE,
max_value DOUBLE,
avg_value DOUBLE,
count_value INT
) TAGS (
device_type NCHAR(30),
area NCHAR(50)
);
-- 日聚合视图(示例)
-- CREATE STREAM IF NOT EXISTS hourly_stream INTO iot_telemetry_hourly AS
-- SELECT _wstart as ts, device_sn, metric_key,
-- MIN(metric_value), MAX(metric_value), AVG(metric_value), COUNT(*)
-- FROM iot_telemetry
-- INTERVAL(1h);