2026-06-14 13:15:38 +08:00
|
|
|
-- =============================================
|
|
|
|
|
-- 智慧水务管理系统 - 供水生产 + 巡检 + 报警 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);
|
2026-06-14 16:05:51 +08:00
|
|
|
-- =============================================
|
|
|
|
|
-- 智慧水务管理系统 - 巡检问题上报 + 工单管理 DDL
|
|
|
|
|
-- 版本: V1
|
|
|
|
|
-- =============================================
|
|
|
|
|
|
|
|
|
|
-- 巡检问题上报表
|
|
|
|
|
CREATE TABLE IF NOT EXISTS patrol_problem (
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
problem_no VARCHAR(30) UNIQUE NOT NULL, -- 问题编号:WQ-2026-001
|
|
|
|
|
task_id BIGINT REFERENCES patrol_task(id),
|
|
|
|
|
point_seq INT,
|
|
|
|
|
device_id BIGINT,
|
|
|
|
|
device_name VARCHAR(200),
|
|
|
|
|
problem_type VARCHAR(50) NOT NULL, -- 设备故障/水质异常/安全隐患/环境卫生/其他
|
|
|
|
|
problem_level VARCHAR(20) DEFAULT 'normal', -- low/normal/high/critical
|
|
|
|
|
problem_title VARCHAR(200) NOT NULL,
|
|
|
|
|
problem_description TEXT,
|
|
|
|
|
location VARCHAR(300),
|
|
|
|
|
lng DOUBLE PRECISION,
|
|
|
|
|
lat DOUBLE PRECISION,
|
|
|
|
|
photo_urls JSONB, -- 现场照片URL数组
|
|
|
|
|
reporter_id BIGINT REFERENCES sys_user(id),
|
|
|
|
|
reporter_name VARCHAR(50),
|
|
|
|
|
report_time TIMESTAMP DEFAULT NOW(),
|
|
|
|
|
status VARCHAR(20) DEFAULT 'reported', -- reported/processing/completed/closed
|
|
|
|
|
work_order_id BIGINT, -- 关联工单ID
|
|
|
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
|
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|
|
|
|
);
|
|
|
|
|
COMMENT ON TABLE patrol_problem IS '巡检问题上报表';
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_problem_task ON patrol_problem(task_id);
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_problem_status ON patrol_problem(status);
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_problem_device ON patrol_problem(device_id);
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_problem_type ON patrol_problem(problem_type);
|
|
|
|
|
|
|
|
|
|
-- 工单表
|
|
|
|
|
CREATE TABLE IF NOT EXISTS work_order (
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
order_no VARCHAR(30) UNIQUE NOT NULL, -- 工单编号:WO-2026-001
|
|
|
|
|
problem_id BIGINT REFERENCES patrol_problem(id),
|
|
|
|
|
order_type VARCHAR(50) NOT NULL, -- 设备维修/水质处理/安全隐患处理/清洁/其他
|
|
|
|
|
priority VARCHAR(20) DEFAULT 'normal', -- low/normal/high/critical
|
|
|
|
|
title VARCHAR(200) NOT NULL,
|
|
|
|
|
description TEXT,
|
|
|
|
|
location VARCHAR(300),
|
|
|
|
|
contact_person VARCHAR(50),
|
|
|
|
|
contact_phone VARCHAR(20),
|
|
|
|
|
reporter_id BIGINT REFERENCES sys_user(id),
|
|
|
|
|
reporter_name VARCHAR(50),
|
|
|
|
|
assignee_id BIGINT REFERENCES sys_user(id),
|
|
|
|
|
assignee_name VARCHAR(50),
|
|
|
|
|
status VARCHAR(20) DEFAULT 'pending', -- pending/assigned/processing/completed/cancelled
|
|
|
|
|
process_status VARCHAR(20) DEFAULT 'created', -- created/accepted/in_progress/completed
|
|
|
|
|
estimated_duration INT, -- 预计工时(分钟)
|
|
|
|
|
actual_start_time TIMESTAMP,
|
|
|
|
|
actual_end_time TIMESTAMP,
|
|
|
|
|
completion_time TIMESTAMP,
|
|
|
|
|
photos_before JSONB, -- 处理前照片
|
|
|
|
|
photos_after JSONB, -- 处理后照片
|
|
|
|
|
solution_description TEXT, -- 处理方案描述
|
|
|
|
|
solution_result TEXT, -- 处理结果
|
|
|
|
|
customer_feedback TEXT, -- 客户反馈
|
|
|
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
|
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|
|
|
|
);
|
|
|
|
|
COMMENT ON TABLE work_order IS '工单表';
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_order_problem ON work_order(problem_id);
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_order_status ON work_order(status, process_status);
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_order_assignee ON work_order(assignee_id);
|
|
|
|
|
|
|
|
|
|
-- 工单处理记录表
|
|
|
|
|
CREATE TABLE IF NOT EXISTS work_order_process (
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
work_order_id BIGINT REFERENCES work_order(id),
|
|
|
|
|
process_step VARCHAR(50) NOT NULL, -- created/accepted/in_progress/completed
|
|
|
|
|
processor_id BIGINT REFERENCES sys_user(id),
|
|
|
|
|
processor_name VARCHAR(50),
|
|
|
|
|
action VARCHAR(50) NOT NULL, -- create/assign/start/complete/cancel
|
|
|
|
|
comment TEXT,
|
|
|
|
|
photos JSONB, -- 处理过程照片
|
|
|
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|
|
|
|
);
|
|
|
|
|
COMMENT ON TABLE work_order_process IS '工单处理记录表';
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_process_order ON work_order_process(work_order_id);
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_process_step ON work_order_process(process_step);
|
|
|
|
|
|
|
|
|
|
-- 工单附件表
|
|
|
|
|
CREATE TABLE IF NOT EXISTS work_order_attachment (
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
work_order_id BIGINT REFERENCES work_order(id),
|
|
|
|
|
file_name VARCHAR(200) NOT NULL,
|
|
|
|
|
file_path VARCHAR(500) NOT NULL,
|
|
|
|
|
file_type VARCHAR(50), -- image/pdf/doc/other
|
|
|
|
|
file_size BIGINT,
|
|
|
|
|
uploaded_by BIGINT REFERENCES sys_user(id),
|
|
|
|
|
uploaded_at TIMESTAMP DEFAULT NOW()
|
|
|
|
|
);
|
|
|
|
|
COMMENT ON TABLE work_order_attachment IS '工单附件表';
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_attachment_order ON work_order_attachment(work_order_id);
|
|
|
|
|
|
|
|
|
|
-- 巡检问题与工单关联触发记录
|
|
|
|
|
CREATE TABLE IF NOT EXISTS patrol_work_order_trigger (
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
patrol_problem_id BIGINT REFERENCES patrol_problem(id),
|
|
|
|
|
work_order_id BIGINT REFERENCES work_order(id),
|
|
|
|
|
trigger_type VARCHAR(20) NOT NULL, -- auto/manual
|
|
|
|
|
trigger_condition JSONB, -- 触发条件
|
|
|
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|
|
|
|
);
|
|
|
|
|
COMMENT ON TABLE patrol_work_order_trigger IS '巡检问题与工单关联触发记录';
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_trigger_problem ON patrol_work_order_trigger(patrol_problem_id);
|
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_trigger_order ON patrol_work_order_trigger(work_order_id);
|