feat: 新增电工APP端与定时任务管理功能
- 新增电工APP独立鉴权中间件与登录注册接口 - 新增定时任务管理模块,支持任务配置、执行日志与手动触发 - 新增运维费定价与电工派单成本价目管理 - 新增电工资质证照管理与到期提醒定时任务 - 完善数据库实体与DTO校验,优化权限控制
This commit is contained in:
1 parent
1803ad679c
commit
f4454ad014
57 files changed
+9388
-200
No files matched your search
+89
-7
@@ -17,7 +17,7 @@
|
||||
--
|
||||
-- 内容:
|
||||
-- 1. 初始角色(ADMIN / SALESMAN / WORKER / CUSTOMER)
|
||||
-- 2. 初始菜单(顶级 6 + 系统管理子菜单 5)
|
||||
-- 2. 初始菜单(顶级 6 + 系统管理子菜单 6 + 运营派单子菜单 13 等,共 50 条)
|
||||
-- 3. 初始字典(客户/设备/派单/支付等业务字典)
|
||||
-- 4. 管理员账户(admin / admin123456)
|
||||
-- 5. 用户-角色绑定 / 角色-菜单绑定
|
||||
@@ -43,12 +43,12 @@ ON CONFLICT (id) DO UPDATE SET
|
||||
SELECT setval('sys_role_id_seq', 4, true);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 2. 初始菜单(顶级菜单,显式指定 id:1-6,系统管理为目录类型 menu_type=1,其余为 menu_type=2)
|
||||
-- 2. 初始菜单(顶级菜单,显式指定 id:1-6,系统管理/运营派单为目录类型 menu_type=1,其余为 menu_type=2)
|
||||
-- ------------------------------------------------------------
|
||||
INSERT INTO sys_menu (id, parent_id, menu_name, menu_path, component, icon, sort_order, menu_type, permission, visible) VALUES
|
||||
(1, NULL, '客户管理', '/customer', NULL, 'TeamOutlined', 1, 1, 'customer:list', 1),
|
||||
(2, NULL, '项目管理', '/project', NULL, 'ProjectOutlined', 2, 1, 'project:list', 1),
|
||||
(3, NULL, '运营派单', '/dispatch', NULL, 'ScheduleOutlined', 3, 2, 'dispatch:list', 1),
|
||||
(3, NULL, '运营派单', '/dispatch', NULL, 'ScheduleOutlined', 3, 1, 'dispatch:list', 1),
|
||||
(4, NULL, '设备监控', '/device', NULL, 'MonitorOutlined', 4, 2, 'device:list', 1),
|
||||
(5, NULL, '统计报表', '/report', NULL, 'BarChartOutlined', 5, 2, 'report:list', 1),
|
||||
(6, NULL, '系统管理', '/system', NULL, 'SettingOutlined', 6, 1, 'system:list', 1)
|
||||
@@ -132,8 +132,34 @@ ON CONFLICT (id) DO UPDATE SET
|
||||
permission = EXCLUDED.permission,
|
||||
visible = EXCLUDED.visible;
|
||||
|
||||
-- 运营派单子菜单(parent_id=3,id:34-36 为菜单项,37-46 为按钮权限)
|
||||
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', 1, 2, 'dispatch:price', 1),
|
||||
(35, 3, '电工派单成本价', '/dispatch/cost', 'dispatch/cost/index', 'AccountBookOutlined', 2, 2, 'dispatch:cost', 1),
|
||||
(36, 3, '电工登记管理', '/dispatch/worker', 'dispatch/worker/index', 'ToolOutlined', 3, 2, 'dispatch:worker', 1),
|
||||
(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, 3, '新增成本价', NULL, NULL, NULL, 4, 3, 'cost:create', 1),
|
||||
(41, 3, '编辑成本价', NULL, NULL, NULL, 5, 3, 'cost:update', 1),
|
||||
(42, 3, '删除成本价', NULL, NULL, NULL, 6, 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;
|
||||
|
||||
-- 重置 sys_menu 自增序列
|
||||
SELECT setval('sys_menu_id_seq', 33, true);
|
||||
SELECT setval('sys_menu_id_seq', 50, true);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 3. 初始字典(sys_dict 无业务唯一键,清空重建以支持幂等执行)
|
||||
@@ -162,7 +188,28 @@ INSERT INTO sys_dict (dict_type, dict_label, dict_value, sort_order) VALUES
|
||||
('dispatch_type', '安装派单', 'install', 2),
|
||||
('dispatch_type', '报警派单', 'alarm', 3),
|
||||
('dispatch_type', '维修派单', 'repair', 4),
|
||||
('dispatch_type', '维保派单', 'maintenance', 5);
|
||||
('dispatch_type', '维保派单', 'maintenance', 5),
|
||||
('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);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 4. 管理员账户(显式指定 id=1,密码哈希为 bcrypt('admin123456'))
|
||||
@@ -188,13 +235,14 @@ INSERT INTO sys_user_role (user_id, role_id) VALUES (1, 1)
|
||||
ON CONFLICT (user_id, role_id) DO NOTHING;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 6. 角色-菜单绑定:ADMIN 拥有全部 32 条菜单,SALESMAN 拥有客户域+项目+统计报表
|
||||
-- 6. 角色-菜单绑定:ADMIN 拥有全部 46 条菜单,SALESMAN 拥有客户域+项目+统计报表
|
||||
-- WORKER、CUSTOMER 不绑定任何菜单
|
||||
-- ------------------------------------------------------------
|
||||
INSERT INTO sys_role_menu (role_id, menu_id) VALUES
|
||||
(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (1, 9), (1, 10), (1, 11),
|
||||
(1, 12), (1, 13), (1, 14), (1, 15), (1, 16), (1, 17), (1, 18), (1, 19), (1, 20), (1, 21), (1, 22), (1, 23),
|
||||
(1, 24), (1, 27), (1, 28), (1, 29), (1, 30), (1, 31), (1, 32), (1, 33),
|
||||
(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),
|
||||
(2, 1), (2, 2), (2, 5),
|
||||
(2, 12), (2, 13), (2, 14), (2, 15), (2, 16), (2, 17), (2, 18), (2, 19), (2, 20), (2, 21), (2, 22), (2, 23),
|
||||
(2, 24), (2, 27), (2, 28), (2, 29), (2, 30), (2, 31), (2, 32), (2, 33)
|
||||
@@ -204,8 +252,42 @@ ON CONFLICT (role_id, menu_id) DO NOTHING;
|
||||
DELETE FROM sys_role_menu WHERE menu_id IN (25, 26);
|
||||
DELETE FROM sys_menu WHERE id IN (25, 26);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 7. 定时任务域菜单(系统管理 parent_id=6,id:47 为菜单项,48-50 为按钮权限)
|
||||
-- ------------------------------------------------------------
|
||||
INSERT INTO sys_menu (id, parent_id, menu_name, menu_path, component, icon, sort_order, menu_type, permission, visible) VALUES
|
||||
(47, 6, '定时任务', '/system/job', 'system/job/index', 'ClockCircleOutlined', 6, 2, 'system:job', 1),
|
||||
(48, 47, '编辑定时任务', NULL, NULL, NULL, 1, 3, 'system:job:update', 1),
|
||||
(49, 47, '立即执行', NULL, NULL, NULL, 2, 3, 'system:job:run', 1),
|
||||
(50, 47, '清理日志', NULL, NULL, NULL, 3, 3, 'system:job:log:clear', 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)拥有 47-50
|
||||
INSERT INTO sys_role_menu (role_id, menu_id) VALUES
|
||||
(1, 47), (1, 48), (1, 49), (1, 50)
|
||||
ON CONFLICT (role_id, menu_id) DO NOTHING;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 8. 定时任务种子(sys_job,按 job_key 幂等)
|
||||
-- ------------------------------------------------------------
|
||||
INSERT INTO sys_job (job_key, job_name, cron_expression, params, retry_times, retry_interval, status, remark) VALUES
|
||||
('demo_heartbeat', '示例心跳', '*/5 * * * *', '{"message":"heartbeat"}'::jsonb, 0, 60, 1,
|
||||
'示例心跳任务:用于验证调度链路,默认每 5 分钟写入一条 info 日志'),
|
||||
('log_clean', '日志清理', '0 3 * * *', '{"keepDays":90}'::jsonb, 2, 60, 1,
|
||||
'日志清理任务:每日 03:00 清理早于 keepDays 天的操作日志与任务日志,默认保留 90 天')
|
||||
ON CONFLICT (job_key) DO NOTHING;
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- ============================================================
|
||||
-- 完 · 7 张系统表种子数据(4 角色 + 32 菜单 + 22 字典 + 1 管理员 + 绑定关系)
|
||||
-- 完 · 系统表种子数据(4 角色 + 50 菜单 + 43 字典 + 1 管理员 + 2 定时任务 + 绑定关系)
|
||||
-- ============================================================
|
||||
@@ -0,0 +1,221 @@
|
||||
-- 运维费定价 + 电工登记管理功能扩展
|
||||
-- 背景:运营派单域由「派单执行」扩展为「客户运维服务价目 + 电工派单成本价 + 电工登记审核」,
|
||||
-- 对应新增 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', 1, 2, 'dispatch:price', 1),
|
||||
(35, 3, '电工派单成本价', '/dispatch/cost', 'dispatch/cost/index', 'AccountBookOutlined', 2, 2, 'dispatch:cost', 1),
|
||||
(36, 3, '电工登记管理', '/dispatch/worker', 'dispatch/worker/index', 'ToolOutlined', 3, 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, 3, '新增成本价', NULL, NULL, NULL, 4, 3, 'cost:create', 1),
|
||||
(41, 3, '编辑成本价', NULL, NULL, NULL, 5, 3, 'cost:update', 1),
|
||||
(42, 3, '删除成本价', NULL, NULL, NULL, 6, 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;
|
||||
@@ -0,0 +1,123 @@
|
||||
-- 定时任务管理功能扩展
|
||||
-- 背景:系统周期性后台作业(物化视图刷新、日志清理等)分散在 pg_cron 与应用 @midwayjs/cron 注解中,
|
||||
-- 运维无法在管理端查看/启停/调频/追溯执行记录。本期新增「自研轻量调度器 + 内置任务注册表」,
|
||||
-- 新增 sys_job(任务定义与调度配置)、sys_job_log(执行日志)两张表,
|
||||
-- 并挂载系统管理下的「定时任务」菜单与按钮权限。
|
||||
-- 幂等:建表/索引用 IF NOT EXISTS;菜单/角色绑定用 ON CONFLICT;任务种子用 ON CONFLICT (job_key) DO NOTHING。
|
||||
-- 注意:菜单 id 47-50,避开并行规格 add-om-pricing-and-worker-registry 已占用的 34-46。
|
||||
BEGIN;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 1) 任务定义与调度配置表
|
||||
-- ------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS sys_job (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
job_key VARCHAR(64) NOT NULL UNIQUE, -- 任务键,与代码注册表一一对应
|
||||
job_name VARCHAR(64) NOT NULL, -- 任务名称
|
||||
cron_expression VARCHAR(64) NOT NULL, -- cron 表达式
|
||||
params JSONB NOT NULL DEFAULT '{}'::jsonb, -- 任务参数(受白名单约束)
|
||||
retry_times SMALLINT NOT NULL DEFAULT 0, -- 失败后最大重试次数 0-5
|
||||
retry_interval INT NOT NULL DEFAULT 60, -- 失败后重试间隔(秒 10-3600)
|
||||
status SMALLINT NOT NULL DEFAULT 1, -- 1启用 0停用
|
||||
remark VARCHAR(255), -- 备注
|
||||
last_run_at TIMESTAMPTZ, -- 上次执行时间
|
||||
last_run_status SMALLINT, -- 上次执行状态:1成功 2失败 3跳过
|
||||
last_run_cost_ms INT, -- 上次执行耗时(毫秒)
|
||||
last_error TEXT, -- 上次失败原因(成功时清空)
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
COMMENT ON TABLE sys_job IS '定时任务定义与调度配置表';
|
||||
COMMENT ON COLUMN sys_job.id IS '自增主键';
|
||||
COMMENT ON COLUMN sys_job.job_key IS '任务键,与代码注册表一一对应';
|
||||
COMMENT ON COLUMN sys_job.job_name IS '任务名称';
|
||||
COMMENT ON COLUMN sys_job.cron_expression IS 'cron 表达式(分 时 日 月 周,支持 6 段带秒)';
|
||||
COMMENT ON COLUMN sys_job.params IS '任务参数(受白名单字段约束)';
|
||||
COMMENT ON COLUMN sys_job.retry_times IS '失败后最大重试次数 0-5';
|
||||
COMMENT ON COLUMN sys_job.retry_interval IS '失败后重试间隔(秒 10-3600)';
|
||||
COMMENT ON COLUMN sys_job.status IS '状态:1启用 0停用';
|
||||
COMMENT ON COLUMN sys_job.remark IS '备注';
|
||||
COMMENT ON COLUMN sys_job.last_run_at IS '上次执行时间';
|
||||
COMMENT ON COLUMN sys_job.last_run_status IS '上次执行状态:1成功 2失败 3跳过';
|
||||
COMMENT ON COLUMN sys_job.last_run_cost_ms IS '上次执行耗时(毫秒)';
|
||||
COMMENT ON COLUMN sys_job.last_error IS '上次失败原因(成功时清空)';
|
||||
COMMENT ON COLUMN sys_job.created_at IS '创建时间';
|
||||
COMMENT ON COLUMN sys_job.updated_at IS '更新时间';
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS uk_sys_job_key ON sys_job (job_key);
|
||||
CREATE INDEX IF NOT EXISTS idx_sys_job_status ON sys_job (status);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 2) 任务执行日志表
|
||||
-- ------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS sys_job_log (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
job_id BIGINT NOT NULL REFERENCES sys_job(id) ON DELETE CASCADE, -- 任务ID(→ sys_job.id)
|
||||
job_key VARCHAR(64) NOT NULL, -- 任务键(冗余,便于查询)
|
||||
job_name VARCHAR(64) NOT NULL, -- 任务名称(冗余)
|
||||
trigger_type SMALLINT NOT NULL DEFAULT 1, -- 触发方式:1定时自动 2手动触发 3失败重试
|
||||
status SMALLINT NOT NULL, -- 1成功 2失败 3跳过
|
||||
attempt SMALLINT NOT NULL DEFAULT 1, -- 第几次尝试
|
||||
started_at TIMESTAMPTZ, -- 开始时间
|
||||
finished_at TIMESTAMPTZ, -- 结束时间
|
||||
cost_ms INT, -- 执行耗时(毫秒)
|
||||
message TEXT, -- 结果摘要
|
||||
error_stack TEXT, -- 异常堆栈(截断 4000 字符)
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
COMMENT ON TABLE sys_job_log IS '定时任务执行日志表';
|
||||
COMMENT ON COLUMN sys_job_log.id IS '自增主键';
|
||||
COMMENT ON COLUMN sys_job_log.job_id IS '任务ID(→ sys_job.id)';
|
||||
COMMENT ON COLUMN sys_job_log.job_key IS '任务键(冗余,便于查询)';
|
||||
COMMENT ON COLUMN sys_job_log.job_name IS '任务名称(冗余)';
|
||||
COMMENT ON COLUMN sys_job_log.trigger_type IS '触发方式:1定时自动 2手动触发 3失败重试';
|
||||
COMMENT ON COLUMN sys_job_log.status IS '执行状态:1成功 2失败 3跳过';
|
||||
COMMENT ON COLUMN sys_job_log.attempt IS '第几次尝试';
|
||||
COMMENT ON COLUMN sys_job_log.started_at IS '开始时间';
|
||||
COMMENT ON COLUMN sys_job_log.finished_at IS '结束时间';
|
||||
COMMENT ON COLUMN sys_job_log.cost_ms IS '执行耗时(毫秒)';
|
||||
COMMENT ON COLUMN sys_job_log.message IS '结果摘要';
|
||||
COMMENT ON COLUMN sys_job_log.error_stack IS '异常堆栈(截断 4000 字符)';
|
||||
COMMENT ON COLUMN sys_job_log.created_at IS '创建时间';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_sys_job_log_job_created ON sys_job_log (job_id, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_sys_job_log_created ON sys_job_log (created_at);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 3) 菜单与权限(系统管理 parent_id=6 下新增「定时任务」菜单 + 3 个按钮权限)
|
||||
-- ------------------------------------------------------------
|
||||
INSERT INTO sys_menu (id, parent_id, menu_name, menu_path, component, icon, sort_order, menu_type, permission, visible) VALUES
|
||||
(47, 6, '定时任务', '/system/job', 'system/job/index', 'ClockCircleOutlined', 6, 2, 'system:job', 1),
|
||||
(48, 47, '编辑定时任务', NULL, NULL, NULL, 1, 3, 'system:job:update', 1),
|
||||
(49, 47, '立即执行', NULL, NULL, NULL, 2, 3, 'system:job:run', 1),
|
||||
(50, 47, '清理日志', NULL, NULL, NULL, 3, 3, 'system:job:log:clear', 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)拥有 47~50
|
||||
INSERT INTO sys_role_menu (role_id, menu_id) VALUES
|
||||
(1, 47), (1, 48), (1, 49), (1, 50)
|
||||
ON CONFLICT (role_id, menu_id) DO NOTHING;
|
||||
|
||||
-- 重置 sys_menu 自增序列,避免后续插入 id 冲突
|
||||
SELECT setval('sys_menu_id_seq', 50, true);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 4) sys_job 内置任务种子(按 job_key 幂等)
|
||||
-- ------------------------------------------------------------
|
||||
INSERT INTO sys_job (job_key, job_name, cron_expression, params, retry_times, retry_interval, status, remark) VALUES
|
||||
('demo_heartbeat', '示例心跳', '*/5 * * * *', '{"message":"heartbeat"}'::jsonb, 0, 60, 1,
|
||||
'示例心跳任务:用于验证调度链路,默认每 5 分钟写入一条 info 日志'),
|
||||
('log_clean', '日志清理', '0 3 * * *', '{"keepDays":90}'::jsonb, 2, 60, 1,
|
||||
'日志清理任务:每日 03:00 清理早于 keepDays 天的操作日志与任务日志,默认保留 90 天')
|
||||
ON CONFLICT (job_key) DO NOTHING;
|
||||
|
||||
COMMIT;
|
||||
Reference in new issue
Block a user