Files
andyesfly f4454ad014 feat: 新增电工APP端与定时任务管理功能
- 新增电工APP独立鉴权中间件与登录注册接口
- 新增定时任务管理模块,支持任务配置、执行日志与手动触发
- 新增运维费定价与电工派单成本价目管理
- 新增电工资质证照管理与到期提醒定时任务
- 完善数据库实体与DTO校验,优化权限控制
2026-10-02 16:08:00 +08:00

92 lines
7.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tasks
> change-id: `add-om-pricing-and-worker-registry`
> 依赖顺序:Task 1 → 2 → (3,4,5,6,7 并行) → 8 → 9 → 10
- [x] Task 1: 数据库迁移与种子数据(全部后续任务的前置)
- [x] SubTask 1.1: 新建 `database/migrations/20261001_om_worker_registry.sql`
- ALTER `worker` 增加 `password_hash` / `audit_status`(默认 0, NOT NULL) / `audit_remark` / `audit_by` / `audit_at` / `last_login_at`
- CREATE TABLE `worker_cert`(含 `worker_id` IDX、`expire_date` IDX、UNIQUE(`worker_id`,`cert_type`,`cert_no`))
- CREATE TABLE `service_price`(含 `price_code` UNIQUE、(`price_mode`,`status`) IDX)
- ALTER `dispatch_price` 增加 `price_mode`(默认 1, NOT NULL) / `unit` / `status`(默认 1, NOT NULL) / `remark` / `updated_at`
- CREATE TABLE `sys_notice`(含 `receiver_id` IDX、UNIQUE(`notice_type`,`biz_id`,`receiver_id`))
- UPDATE `sys_menu` SET `menu_type=1` WHERE id=3;INSERT 菜单 id 34-46(3 个页面菜单 + 10 个按钮权限)+ ADMIN 角色绑定 + `setval('sys_menu_id_seq', …)`
- INSERT 新字典:`om_service_type` / `om_price_mode` / `om_price_unit` / `worker_cert_type` / `worker_audit_status`
- 全部语句使用 `IF NOT EXISTS` / `ON CONFLICT`,保证可重复执行
- [x] SubTask 1.2: 同步修订 `database/db_seed.sql`(菜单 / 字典 / 角色绑定与迁移脚本一致,更新末尾计数注释)
- [x] SubTask 1.3: 执行迁移脚本验证可跑通且可重复执行
- [x] Task 2: 后端实体层
- [x] SubTask 2.1: 修改 `server/src/entity/worker.entity.ts`(补 6 个字段 + 索引)
- [x] SubTask 2.2: 修改 `server/src/entity/dispatch_price.entity.ts`(补 5 个字段,开启 `updated_at`)
- [x] SubTask 2.3: 新建 `server/src/entity/worker_cert.entity.ts`
- [x] SubTask 2.4: 新建 `server/src/entity/service_price.entity.ts`
- [x] SubTask 2.5: 新建 `server/src/entity/sys_notice.entity.ts`
- [x] Task 3: 客户运维价目后端(依赖 Task 2)
- [x] SubTask 3.1: 新建 `dto/service_price.dto.ts`(创建 / 更新 / 查询 DTO + `class-validator` 校验)
- [x] SubTask 3.2: 新建 `service/service_price.service.ts`(分页搜索筛选、`price_code` 生成 `FW+YYYYMMDD+3位`、白名单更新、增删改)
- [x] SubTask 3.3: 新建 `controller/service_price.controller.ts`(`/api/service-prices`,统一返回结构)
- [x] Task 4: 电工派单成本价目后端(依赖 Task 2)
- [x] SubTask 4.1: 新建 `dto/dispatch_price.dto.ts`
- [x] SubTask 4.2: 新建 `service/dispatch_price.service.ts`(分页 + 关键词 + `dispatch_type`/`price_mode`/`status` 筛选 + CRUD + `price_code` 唯一冲突友好提示)
- [x] SubTask 4.3: 新建 `controller/dispatch_price.controller.ts`(`/api/dispatch-prices`)
- [x] Task 5: 电工登记与资质审核后端(依赖 Task 2)
- [x] SubTask 5.1: 扩展 `dto/worker.dto.ts`(登记创建 / 更新 / 审核 / 列表查询 / 证书行 DTO)
- [x] SubTask 5.2: 扩展 `service/worker.service.ts`
- 列表分页 + 关键词 + `status`/`auditStatus`/`certStatus` 筛选,批量聚合证书计算「资质状态」(避免 N+1)
- KPI 统计(总数 / 待审核 / 临期 / 已过期)
- 详情(含证书列表)
- 创建(手机号唯一、`audit_status=0`、可选生成默认密码 bcrypt)、更新、删除(级联删证书 + 派单引用校验)
- 审核通过 / 驳回(校验驳回理由必填、写 `audit_by`/`audit_at`/`cert_verified`)
- 证书行增删改(续期 / 删除时清理该证书未读通知)
- 保持 `/options`、`/recommend` 现有逻辑并按 Assumption 7 收紧为 `audit_status=1 AND status=1`
- [x] SubTask 5.3: 扩展 `controller/worker.controller.ts`(`/api/workers` 增补 list/detail/create/update/delete/audit/certs 接口,静态路径在动态路径之前)
- [x] Task 6: 站内通知后端 + 定时任务(依赖 Task 1、2)
- [x] SubTask 6.1: `server/package.json` 新增依赖 `@midwayjs/cron` 并安装
- [x] SubTask 6.2: 新建 `service/notice.service.ts`(本人通知分页、未读数、单条 / 全部已读、ADMIN 用户查询、证书到期扫描 + 幂等生成、按证书清理通知)
- [x] SubTask 6.3: 新建 `controller/notice.controller.ts`(`/api/notices`、`/api/notices/unread-count`、`/api/notices/:id/read`、`/api/notices/read-all`)
- [x] SubTask 6.4: 新建 `task/cert_expire.task.ts`(`@Cron` 每日 08:00,调用 `notice.service` 扫描生成)
- [x] Task 7: 电工 APP 后端接口(依赖 Task 5)
- [x] SubTask 7.1: 扩展 `util/token.ts`(`generateWorkerToken` / `verifyWorkerToken`)
- [x] SubTask 7.2: 新建 `middleware/worker_auth.middleware.ts`(`match=['/api/worker-app/*']`、`ignore=['/api/worker-app/auth/*']`,写 `ctx.state.worker`)
- [x] SubTask 7.3: 修改 `middleware/auth.middleware.ts` 与 `middleware/rbac.middleware.ts`(忽略 `/api/worker-app/*`;新增 `/api/service-prices`、`/api/dispatch-prices`、`/api/workers` 权限映射;`ignore` 增加白名单 `/api/workers/options`、`/api/workers/recommend`)
- [x] SubTask 7.4: 新建 `dto/worker_app.dto.ts`、`service/worker_app.service.ts`、`controller/worker_app.controller.ts`(注册 / 登录 / 资料 / 证书 CRUD / 重新提交审核 / 通知,全部以 `workerId` 为数据边界)
- [x] Task 8: 前端 API 层(依赖 Task 3、4、5、6)
- [x] SubTask 8.1: 新建 `client/src/api/servicePrice.ts`
- [x] SubTask 8.2: 新建 `client/src/api/dispatchPrice.ts`
- [x] SubTask 8.3: 新建 `client/src/api/workerRegistry.ts`(登记 / 审核 / 证书 / KPI 统计)
- [x] SubTask 8.4: 新建 `client/src/api/notice.ts`
- [x] Task 9: 前端页面与路由(依赖 Task 8)
- [x] SubTask 9.1: 新建 `client/src/views/dispatch/price/index.vue`(运维费定价)
- [x] SubTask 9.2: 新建 `client/src/views/dispatch/cost/index.vue`(电工派单成本价)
- [x] SubTask 9.3: 新建 `client/src/views/dispatch/worker/index.vue`(电工登记管理:KPI 卡 + 列表 + 编辑弹窗含证书子表与图片上传 + 审核弹窗)
- [x] SubTask 9.4: 修改 `client/src/router/index.ts`(`/dispatch` 重定向到 `/dispatch/price`,新增 3 条子路由与 `meta.permission`)
- [x] Task 10: 仪表盘提醒区块与消息中心(依赖 Task 8)
- [x] SubTask 10.1: 修改 `client/src/layouts/index.vue`(消息铃铛 + 未读红点角标 + 消息中心抽屉 + 跳转)
- [x] SubTask 10.2: 修改 `client/src/views/dashboard/index.vue`(新增「电工资质到期提醒」区块,展示临期 / 已过期证书清单并可跳转)
- [x] Task 11: 联调与验证
- [x] SubTask 11.1: 后端 `yarn dev` 启动无编译错误,逐条走通 AC-1 ~ AC-11
- [x] SubTask 11.2: 前端 `yarn dev` 启动,人工验证 AC-5、AC-7、AC-9(菜单可见性)
- [x] SubTask 11.3: 人工触发定时任务验证 AC-6 幂等
- [x] Task 12: 修复验证阶段发现的阻断性缺陷(Task 11 追加)
- [x] SubTask 12.1: 修复 `WorkerAuthMiddleware` 同时声明 `match` 与 `ignore` 导致 Midway 抛 `MIDWAY_10001`、**全站接口 500** 的问题(改为仅 `match`,登录/注册路径在 `resolve()` 内放行)
# Task Dependencies
- Task 2 依赖 Task 1(表结构必须先存在)
- Task 3 / Task 4 / Task 5 依赖 Task 2,彼此无依赖,可并行
- Task 6 依赖 Task 1、Task 2
- Task 7 依赖 Task 5(复用 worker 服务)与 Task 6(通知复用)
- Task 8 依赖 Task 3、4、5、6(接口契约已定)
- Task 9、Task 10 依赖 Task 8,彼此无依赖,可并行
- Task 11 依赖全部