-- 运维费定价 + 电工登记管理功能扩展 -- 背景:运营派单域由「派单执行」扩展为「客户运维服务价目 + 电工派单成本价 + 电工登记审核」, -- 对应新增 service_price(客户运维服务价目)、worker_cert(电工资质证照)、 -- sys_notice(证照到期站内通知)三张表,并为 worker / dispatch_price 补齐 -- 登录、审核、计价方式等业务字段,同时挂载运营派单子菜单与按钮权限。 -- 幂等:新增列一律带 DEFAULT + IF NOT EXISTS;建表/索引用 IF NOT EXISTS; -- 菜单/角色绑定用 ON CONFLICT;字典用「先 DELETE 再 INSERT」收敛。 -- 注意:本文件不 TRUNCATE sys_dict(避免清空其它字典及重置 id 影响 db_seed.sql)。 BEGIN; -- ------------------------------------------------------------ -- 1) worker 表扩展:电工 APP 登录与入驻审核 -- ------------------------------------------------------------ ALTER TABLE worker ADD COLUMN IF NOT EXISTS password_hash VARCHAR(255); -- 电工APP登录密码bcrypt哈希 ALTER TABLE worker ADD COLUMN IF NOT EXISTS audit_status SMALLINT NOT NULL DEFAULT 0; -- 审核状态:0待审核 1已通过 2已驳回 ALTER TABLE worker ADD COLUMN IF NOT EXISTS audit_remark VARCHAR(255); -- 驳回理由/审核备注 ALTER TABLE worker ADD COLUMN IF NOT EXISTS audit_by BIGINT; -- 审核人(→ sys_user.id) ALTER TABLE worker ADD COLUMN IF NOT EXISTS audit_at TIMESTAMPTZ; -- 审核时间 ALTER TABLE worker ADD COLUMN IF NOT EXISTS last_login_at TIMESTAMPTZ; -- 最后登录时间 COMMENT ON COLUMN worker.password_hash IS '电工APP登录密码bcrypt哈希'; COMMENT ON COLUMN worker.audit_status IS '审核状态:0待审核 1已通过 2已驳回'; COMMENT ON COLUMN worker.audit_remark IS '驳回理由/审核备注'; COMMENT ON COLUMN worker.audit_by IS '审核人(→ sys_user.id)'; COMMENT ON COLUMN worker.audit_at IS '审核时间'; COMMENT ON COLUMN worker.last_login_at IS '最后登录时间'; -- 电工登记台账按审核状态过滤/统计 CREATE INDEX IF NOT EXISTS idx_worker_audit_status ON worker (audit_status); -- ------------------------------------------------------------ -- 2) 电工资质证照表(电工登记管理的资质附件与到期提醒依据) -- ------------------------------------------------------------ CREATE TABLE IF NOT EXISTS worker_cert ( id BIGSERIAL PRIMARY KEY, worker_id BIGINT NOT NULL REFERENCES worker(id) ON DELETE CASCADE, cert_type VARCHAR(64), -- 证书类型(字典 worker_cert_type) cert_no VARCHAR(64), -- 证书编号 issue_authority VARCHAR(128), -- 发证机关 issue_date DATE, -- 发证日期 expire_date DATE, -- 有效期至(到期提醒依据;NULL=长期有效) cert_image_url VARCHAR(512), -- 证照图片对象key created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); COMMENT ON TABLE worker_cert IS '电工资质证照表'; COMMENT ON COLUMN worker_cert.id IS '自增主键'; COMMENT ON COLUMN worker_cert.worker_id IS '共享电工ID(→ worker)'; COMMENT ON COLUMN worker_cert.cert_type IS '证书类型(字典 worker_cert_type)'; COMMENT ON COLUMN worker_cert.cert_no IS '证书编号'; COMMENT ON COLUMN worker_cert.issue_authority IS '发证机关'; COMMENT ON COLUMN worker_cert.issue_date IS '发证日期'; COMMENT ON COLUMN worker_cert.expire_date IS '有效期至(到期提醒依据;NULL=长期有效)'; COMMENT ON COLUMN worker_cert.cert_image_url IS '证照图片对象key'; COMMENT ON COLUMN worker_cert.created_at IS '创建时间'; COMMENT ON COLUMN worker_cert.updated_at IS '更新时间'; CREATE INDEX IF NOT EXISTS idx_worker_cert_worker ON worker_cert (worker_id); CREATE INDEX IF NOT EXISTS idx_worker_cert_expire ON worker_cert (expire_date); CREATE UNIQUE INDEX IF NOT EXISTS uk_worker_cert_type_no ON worker_cert (worker_id, cert_type, cert_no); -- ------------------------------------------------------------ -- 3) 客户运维服务价目表(运维费定价) -- ------------------------------------------------------------ CREATE TABLE IF NOT EXISTS service_price ( id BIGSERIAL PRIMARY KEY, price_code VARCHAR(64) NOT NULL UNIQUE, price_name VARCHAR(64) NOT NULL, service_type VARCHAR(32), price_mode SMALLINT NOT NULL DEFAULT 1, unit_price NUMERIC(10,2) NOT NULL DEFAULT 0, unit VARCHAR(16), status SMALLINT NOT NULL DEFAULT 1, remark VARCHAR(255), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); COMMENT ON TABLE service_price IS '客户运维服务价目表'; COMMENT ON COLUMN service_price.id IS '自增主键'; COMMENT ON COLUMN service_price.price_code IS '价目编码(唯一,FW+YYYYMMDD+3位)'; COMMENT ON COLUMN service_price.price_name IS '价目名称'; COMMENT ON COLUMN service_price.service_type IS '服务类型:维修/维保/报警处理/巡检/其他'; COMMENT ON COLUMN service_price.price_mode IS '计价方式:1按次 2按工时 3材料'; COMMENT ON COLUMN service_price.unit_price IS '单价'; COMMENT ON COLUMN service_price.unit IS '计价单位:次/小时/个/米/根'; COMMENT ON COLUMN service_price.status IS '状态:1启用 0停用'; COMMENT ON COLUMN service_price.remark IS '备注'; COMMENT ON COLUMN service_price.created_at IS '创建时间'; COMMENT ON COLUMN service_price.updated_at IS '更新时间'; CREATE UNIQUE INDEX IF NOT EXISTS uk_service_price_code ON service_price (price_code); CREATE INDEX IF NOT EXISTS idx_service_price_mode_status ON service_price (price_mode, status); -- ------------------------------------------------------------ -- 4) dispatch_price 表扩展:电工派单成本价 -- ------------------------------------------------------------ ALTER TABLE dispatch_price ADD COLUMN IF NOT EXISTS price_mode SMALLINT NOT NULL DEFAULT 1; -- 计价方式:1按次 2按工时 ALTER TABLE dispatch_price ADD COLUMN IF NOT EXISTS unit VARCHAR(16) DEFAULT '次'; -- 计价单位 ALTER TABLE dispatch_price ADD COLUMN IF NOT EXISTS status SMALLINT NOT NULL DEFAULT 1; -- 状态:1启用 0停用 ALTER TABLE dispatch_price ADD COLUMN IF NOT EXISTS remark VARCHAR(255); -- 备注 ALTER TABLE dispatch_price ADD COLUMN IF NOT EXISTS updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(); COMMENT ON COLUMN dispatch_price.price_mode IS '计价方式:1按次 2按工时'; COMMENT ON COLUMN dispatch_price.unit IS '计价单位'; COMMENT ON COLUMN dispatch_price.status IS '状态:1启用 0停用'; COMMENT ON COLUMN dispatch_price.remark IS '备注'; COMMENT ON COLUMN dispatch_price.updated_at IS '更新时间'; CREATE INDEX IF NOT EXISTS idx_dispatch_price_status ON dispatch_price (status); -- ------------------------------------------------------------ -- 5) 站内通知表(当前用途:电工资质证照到期提醒) -- ------------------------------------------------------------ CREATE TABLE IF NOT EXISTS sys_notice ( id BIGSERIAL PRIMARY KEY, notice_type VARCHAR(32) NOT NULL, title VARCHAR(128) NOT NULL, content VARCHAR(512), biz_type VARCHAR(32), biz_id BIGINT, receiver_id BIGINT NOT NULL, is_read SMALLINT NOT NULL DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); COMMENT ON TABLE sys_notice IS '站内通知表'; COMMENT ON COLUMN sys_notice.id IS '自增主键'; COMMENT ON COLUMN sys_notice.notice_type IS '通知类型:cert_expire证照到期'; COMMENT ON COLUMN sys_notice.title IS '通知标题'; COMMENT ON COLUMN sys_notice.content IS '通知内容'; COMMENT ON COLUMN sys_notice.biz_type IS '业务类型:worker_cert电工资质证照'; COMMENT ON COLUMN sys_notice.biz_id IS '业务主键(→ worker_cert.id)'; COMMENT ON COLUMN sys_notice.receiver_id IS '接收人(→ sys_user.id)'; COMMENT ON COLUMN sys_notice.is_read IS '是否已读:0未读 1已读'; COMMENT ON COLUMN sys_notice.created_at IS '创建时间'; CREATE INDEX IF NOT EXISTS idx_sys_notice_receiver ON sys_notice (receiver_id, is_read); CREATE UNIQUE INDEX IF NOT EXISTS uk_sys_notice_biz ON sys_notice (notice_type, biz_id, receiver_id); -- ------------------------------------------------------------ -- 6) 菜单与权限 -- 「运营派单」由顶级菜单项改为目录,运维费定价/电工登记作为其子菜单(勘察费用归属「项目管理」) -- ------------------------------------------------------------ UPDATE sys_menu SET menu_type = 1 WHERE id = 3; INSERT INTO sys_menu (id, parent_id, menu_name, menu_path, component, icon, sort_order, menu_type, permission, visible) VALUES (34, 3, '运维费定价', '/dispatch/price', 'dispatch/price/index', 'MoneyCollectOutlined', 2, 2, 'dispatch:price', 1), (35, 2, '勘察费用', '/dispatch/cost', 'dispatch/cost/index', 'AccountBookOutlined', 8, 2, 'dispatch:cost', 1), (36, 3, '电工登记管理', '/dispatch/worker', 'dispatch/worker/index', 'ToolOutlined', 1, 2, 'dispatch:worker', 1) ON CONFLICT (id) DO UPDATE SET parent_id = EXCLUDED.parent_id, menu_name = EXCLUDED.menu_name, menu_path = EXCLUDED.menu_path, component = EXCLUDED.component, icon = EXCLUDED.icon, sort_order = EXCLUDED.sort_order, menu_type = EXCLUDED.menu_type, permission = EXCLUDED.permission, visible = EXCLUDED.visible; -- 按钮权限(menu_type=3,无路由/组件/图标) INSERT INTO sys_menu (id, parent_id, menu_name, menu_path, component, icon, sort_order, menu_type, permission, visible) VALUES (37, 3, '新增价目', NULL, NULL, NULL, 1, 3, 'price:create', 1), (38, 3, '编辑价目', NULL, NULL, NULL, 2, 3, 'price:update', 1), (39, 3, '删除价目', NULL, NULL, NULL, 3, 3, 'price:delete', 1), (40, 2, '新增勘察费用', NULL, NULL, NULL, 9, 3, 'cost:create', 1), (41, 2, '编辑勘察费用', NULL, NULL, NULL, 10, 3, 'cost:update', 1), (42, 2, '删除勘察费用', NULL, NULL, NULL, 11, 3, 'cost:delete', 1), (43, 3, '新增电工', NULL, NULL, NULL, 7, 3, 'worker:create', 1), (44, 3, '编辑电工', NULL, NULL, NULL, 8, 3, 'worker:update', 1), (45, 3, '删除电工', NULL, NULL, NULL, 9, 3, 'worker:delete', 1), (46, 3, '审核电工', NULL, NULL, NULL, 10, 3, 'worker:audit', 1) ON CONFLICT (id) DO UPDATE SET parent_id = EXCLUDED.parent_id, menu_name = EXCLUDED.menu_name, menu_path = EXCLUDED.menu_path, component = EXCLUDED.component, icon = EXCLUDED.icon, sort_order = EXCLUDED.sort_order, menu_type = EXCLUDED.menu_type, permission = EXCLUDED.permission, visible = EXCLUDED.visible; -- 角色绑定:ADMIN(role_id=1)拥有 34~46 INSERT INTO sys_role_menu (role_id, menu_id) VALUES (1, 34), (1, 35), (1, 36), (1, 37), (1, 38), (1, 39), (1, 40), (1, 41), (1, 42), (1, 43), (1, 44), (1, 45), (1, 46) ON CONFLICT (role_id, menu_id) DO NOTHING; -- 重置 sys_menu 自增序列,避免后续插入 id 冲突 SELECT setval('sys_menu_id_seq', 46, true); -- ------------------------------------------------------------ -- 7) 字典(sys_dict 无业务唯一键,先 DELETE 目标 dict_type 再 INSERT,保证幂等) -- ------------------------------------------------------------ DELETE FROM sys_dict WHERE dict_type IN ( 'om_service_type', 'om_price_mode', 'om_price_unit', 'worker_cert_type', 'worker_audit_status' ); INSERT INTO sys_dict (dict_type, dict_label, dict_value, sort_order) VALUES ('om_service_type', '维修', '维修', 1), ('om_service_type', '维保', '维保', 2), ('om_service_type', '报警处理', '报警处理', 3), ('om_service_type', '巡检', '巡检', 4), ('om_service_type', '其他', '其他', 5), ('om_price_mode', '按次', '1', 1), ('om_price_mode', '按工时', '2', 2), ('om_price_mode', '材料', '3', 3), ('om_price_unit', '次', '次', 1), ('om_price_unit', '小时', '小时', 2), ('om_price_unit', '个', '个', 3), ('om_price_unit', '米', '米', 4), ('om_price_unit', '根', '根', 5), ('worker_cert_type', '低压电工证', '低压电工证', 1), ('worker_cert_type', '高压电工证', '高压电工证', 2), ('worker_cert_type', '特种作业证', '特种作业证', 3), ('worker_cert_type', '登高证', '登高证', 4), ('worker_cert_type', '其他', '其他', 5), ('worker_audit_status', '待审核', '0', 1), ('worker_audit_status', '已通过', '1', 2), ('worker_audit_status', '已驳回', '2', 3); COMMIT;