fa0dc82d38
新增12项电子签署优化任务: - P0:后端路由重写+模板渲染、验证码确认、证据链体系 - P1:回写合同、组织开关校验、线下手签、花名册联动、转正联动 - P2:scene模板填充、管理端UI、员工端UI 更新执行状态总览(31→43条)、批次总览、依赖关系图、风险注意事项 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
1039 lines
55 KiB
Markdown
1039 lines
55 KiB
Markdown
# 20260815 优化执行计划
|
||
|
||
> 基于 `20260815-优化.md`(31 条优化项)制定的可执行任务清单。
|
||
> 覆盖范围:P0(6 条)+ P1(14 条)+ P2(9 条)+ P3(2 项,含问题 27 方案 A + 问题 31 增强全部 6 项)。
|
||
> 技术栈:React 18 + Vite 5 / Express + Prisma + PostgreSQL / 见 `run.md`。
|
||
|
||
---
|
||
|
||
## 执行状态总览(2026-08-16 更新)
|
||
|
||
| 批次 | 优先级 | 任务数 | 完成数 | 状态 |
|
||
|------|--------|--------|--------|------|
|
||
| 第一批 | P0 紧急 | 6 条 | 6 条 | ✅ 全部完成 |
|
||
| 第二批 | P1 高 | 14 条 | 14 条 | ✅ 全部完成 |
|
||
| 第三批 | P2 中 | 9 条 | 9 条 | ✅ 全部完成 |
|
||
| 第四批 | P3 规划 | 2 项 | 2 项 | ✅ 全部完成 |
|
||
| 第五批 | 电子签署 | 12 条 | 12 条 | ✅ 全部完成(2026-08-16 新增) |
|
||
| **合计** | | **43 条** | **43 条** | **✅ 100% 完成** |
|
||
|
||
> 编译状态:前后端 TypeScript 编译均 0 错误。
|
||
> 数据库:Prisma schema 已同步(`prisma db push`),新增 8 个模型 + 2 个字段 + 1 个枚举值 + ESignRecord 扩展 7 个字段。
|
||
> 复查状态(2026-08-15):TASK-024/025/026/027 验收标准已全部修复。
|
||
> 电子签署批次(2026-08-16):TASK-031~042 全部完成,覆盖电子签署完整流程、线下手签、证据链体系、花名册操作联动。
|
||
|
||
---
|
||
|
||
## 批次总览
|
||
|
||
| 批次 | 优先级 | 任务数 | 目标 | 依赖 |
|
||
|------|--------|--------|------|------|
|
||
| 第一批 | P0 紧急 | 6 条 | 数据丢失/业务正确性/合规风险修复 | 无 |
|
||
| 第二批 | P1 高 | 14 条 | 流程阻塞/合规校验缺失修复 | 第一批完成 |
|
||
| 第三批 | P2 中 | 9 条 | 体验优化/功能增强 | 第二批完成(26 依赖 18/20/21/22/23) |
|
||
| 第四批 | P3 规划 | 2 项 | 组织架构+审批流 / 客服工作台增强 | 第三批完成 |
|
||
| 第五批 | 电子签署 | 12 条 | 电子签署完整流程+线下手签+证据链+花名册联动 | 无(独立批次) |
|
||
|
||
---
|
||
|
||
## 第一批:P0 紧急(6 条)
|
||
|
||
### TASK-001:全域保存草稿后部分录入数据未保存(问题 30)
|
||
|
||
- **目标**:确保所有流程页面的"保存草稿"功能完整持久化全部前端 state
|
||
- **对应需求**:问题 30
|
||
- **验收标准**:
|
||
- [x] Termination 草稿保存后,`compAdjustments`(补偿金手动调整记录)可回读
|
||
- [x] Termination 草稿保存后,`handoverItems` 的 remark(备注)可回读
|
||
- [x] Termination 草稿保存后,`checklistOverrides`(合规检查覆盖原因)可回读
|
||
- [x] WorkProcess 草稿保存后,自定义字段可回读
|
||
- [x] 保存后立即回读对比,缺失字段时控制台告警
|
||
- **依赖**:无
|
||
- **优先级**:P0
|
||
- **阶段**:第一批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/Termination.tsx`(`handleSaveDraft` payload 补全)
|
||
- `frontend/src/pages/WorkProcess.tsx`(草稿 payload 补全)
|
||
- `backend/src/services/termination.service.ts`(createDraft/updateDraft 字段映射)
|
||
- `backend/src/services/work-process.service.ts`(草稿字段映射)
|
||
- **测试要求**:
|
||
- 手工验证:Termination 填写补偿金调整 + 交接备注 → 保存草稿 → 重新进入 → 数据完整
|
||
- 手工验证:WorkProcess 填写自定义字段 → 保存草稿 → 重新进入 → 数据完整
|
||
|
||
### TASK-002:手动调整补偿金分项后合计未同步(问题 7)
|
||
|
||
- **目标**:补偿金手动调整后,合计应付实时更新,保存与确认页使用实际合计值
|
||
- **对应需求**:问题 7
|
||
- **验收标准**:
|
||
- [x] 调整任一补偿金分项后,"合计应付"显示实时刷新
|
||
- [x] 实际合计 = `costResult.grandTotal + Σ(adjustments.to - adjustments.from)`
|
||
- [x] `handleSave` 使用实际合计值,不再使用 `costResult.grandTotal`
|
||
- [x] 确认步骤显示"系统预估 ¥X + 手动调整 ¥Y = 实际补偿 ¥Z"
|
||
- [x] 后端 `compensationBreakdown.adjustments` 正确存储并回显
|
||
- **依赖**:TASK-001(草稿需先能保存 adjustments)
|
||
- **优先级**:P0
|
||
- **阶段**:第一批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/Termination.tsx`(`handleSave`、确认步骤、step 3 合计显示)
|
||
- `backend/src/services/termination.service.ts`(adjustments 存储与返回)
|
||
- **测试要求**:
|
||
- 手工验证:系统预估补偿金 ¥50000 → 手动调整 severance ¥50000→¥45000 → 合计显示 ¥45000 → 保存 → 确认页显示 ¥45000
|
||
|
||
### TASK-003:解聘驳回后修改内容未更新(问题 10)
|
||
|
||
- **目标**:驳回后重新编辑草稿,修改的解聘类型/金额/日期等正确覆盖更新
|
||
- **对应需求**:问题 10
|
||
- **验收标准**:
|
||
- [x] 驳回草稿再编辑走 `updateDraft`(而非新建),版本号 +1
|
||
- [x] `updateDraft` 正确覆盖 `reason`、`compensationBreakdown`、`terminationDate`
|
||
- [x] 前端进入驳回草稿时强制重新拉取最新数据(不使用缓存)
|
||
- [x] 旧版本留快照,可查看历史版本
|
||
- [x] 修改解聘类型后,补偿金按新类型重新计算
|
||
- **依赖**:TASK-002(补偿金合计逻辑需先正确)
|
||
- **优先级**:P0
|
||
- **阶段**:第一批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/Termination.tsx`(编辑驳回草稿逻辑、进入时强制刷新)
|
||
- `backend/src/services/termination.service.ts`(updateDraft 覆盖逻辑、版本快照)
|
||
- `backend/src/routes/termination.routes.ts`(update 接口校验)
|
||
- **测试要求**:
|
||
- 手工验证:创建解聘草稿(协商解除 ¥50000)→ 审批驳回 → 修改为过错解除 ¥0 → 保存 → 重新进入显示 ¥0
|
||
|
||
### TASK-004:违法解除降低补偿金后无合规风险提醒(问题 11)
|
||
|
||
- **目标**:违法解除(2N)场景下,实际补偿金低于法定 2N 时强制风险提醒
|
||
- **对应需求**:问题 11
|
||
- **验收标准**:
|
||
- [x] 选择 ILLEGAL 后,实际补偿金 < 法定 2N 时,强制弹出合规风险提醒
|
||
- [x] 需勾选"已知风险并继续"才能进入下一步
|
||
- [x] 风险提醒记录到 `compensationBreakdown.riskAcknowledged`(含时间戳、用户、金额对比)
|
||
- [x] 同步推送风险中心,生成风险项
|
||
- [x] 金额变动后重新校验(不仅初始选择时)
|
||
- **依赖**:TASK-002(补偿金合计逻辑)
|
||
- **优先级**:P0
|
||
- **阶段**:第一批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/Termination.tsx`(step 3 风险校验逻辑)
|
||
- `backend/src/services/termination.service.ts`(riskAcknowledged 存储)
|
||
- `backend/src/services/risk.service.ts`(风险项生成)
|
||
- **测试要求**:
|
||
- 手工验证:选择违法解除 → 法定 2N=¥100000 → 手动改为 ¥80000 → 弹出风险提醒 → 必须勾选才能下一步
|
||
|
||
### TASK-005:合同结束日期早于开始日期未校验(问题 13)
|
||
|
||
- **目标**:合同开始/结束日期前后关系校验,杜绝时间倒置数据
|
||
- **对应需求**:问题 13
|
||
- **验收标准**:
|
||
- [x] 前端 WorkProcess 所有含日期的表单(HIRE/ONBOARD/CUSTOM_CONTRACT/CHANGE/RENEW/SUSPEND)提交前校验 `endDate >= startDate`
|
||
- [x] 校验失败时阻断提交并提示"结束日期不能早于开始日期"
|
||
- [x] 后端 `work-process.service.ts` 增加同样校验,双保险
|
||
- [x] 历史倒置数据:提供查询列表提示(不自动修复,由用户确认后修复)
|
||
- **依赖**:无
|
||
- **优先级**:P0
|
||
- **阶段**:第一批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/WorkProcess.tsx`(表单提交前校验)
|
||
- `backend/src/services/work-process.service.ts`(后端校验)
|
||
- `backend/src/routes/contract.routes.ts`(历史倒置数据查询接口)
|
||
- **测试要求**:
|
||
- 手工验证:新建合同 → 开始日期 2026-06-01 → 结束日期 2026-05-31 → 提交被阻断
|
||
- 手工验证:后端直接调用 API 传倒置日期 → 返回 400
|
||
|
||
### TASK-006:补偿金批次经济补偿金发放数据读取错误(问题 28)
|
||
|
||
- **目标**:补偿金批次(SEVERANCE 类型)正确从离职草稿读取补偿金数据
|
||
- **对应需求**:问题 28
|
||
- **验收标准**:
|
||
- [x] `createBatch` 当 `type=SEVERANCE` 时,数据源从已审批通过的 `termination_draft` 读取 `compensationBreakdown.grandTotal`
|
||
- [x] 员工范围:仅包含有未发放补偿金的离职员工
|
||
- [x] 创建前增加预览页,展示每位员工的补偿金明细(补偿金/代通知金/赔偿金/合计)
|
||
- [x] 确认后再创建批次
|
||
- [x] 不再读取工资数据作为补偿金
|
||
- **依赖**:TASK-002(补偿金合计需先正确)
|
||
- **优先级**:P0
|
||
- **阶段**:第一批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/money/BatchTab.tsx`(SEVERANCE 创建流程、预览页)
|
||
- `backend/src/services/payroll.service.ts`(SEVERANCE 分支数据源修正)
|
||
- `backend/src/routes/payroll2.routes.ts`(预览接口)
|
||
- **测试要求**:
|
||
- 手工验证:员工 A 离职补偿金 ¥50000(已审批)→ 创建补偿金批次 → 预览显示 ¥50000 → 确认创建 → 批次数据正确
|
||
|
||
---
|
||
|
||
## 第二批:P1 高(14 条)
|
||
|
||
### TASK-007:离职日期调整后联动社保/公积金截止年月(问题 2)
|
||
|
||
- **目标**:离职日期变更时自动推导社保/公积金截止月,支持 15 日前后规则可配置
|
||
- **对应需求**:问题 2
|
||
- **验收标准**:
|
||
- [x] 离职日期变更时自动回填社保截止月、公积金截止月
|
||
- [x] 规则:每月 cutoffDay(默认 15)日前离职 → 截止月 = 离职月 - 1;cutoffDay 日后离职 → 截止月 = 离职月
|
||
- [x] `org_settings` 新增 `socialInsCutoffDay` 字段(默认 15),系统设置可配置
|
||
- [x] 保留手动覆盖入口(用户可手动修改截止月)
|
||
- [x] 手动覆盖时提示"与自动推导不一致"
|
||
- **依赖**:无
|
||
- **优先级**:P1
|
||
- **阶段**:第二批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/Termination.tsx`(离职日期变更联动)
|
||
- `backend/src/services/termination.service.ts`(自动推导逻辑)
|
||
- `backend/prisma/schema.prisma`(Organization 新增 `socialInsCutoffDay Int @default(15)`)
|
||
- `frontend/src/pages/Settings.tsx`(配置入口)
|
||
- **DB 变更**:`Organization` 新增 `socialInsCutoffDay` 字段,migration + 回滚方案
|
||
- **测试要求**:
|
||
- 手工验证:离职日期 2026-08-10(10 日 < 15 日)→ 社保截止 2026-07 → 公积金截止 2026-07
|
||
- 手工验证:离职日期 2026-08-20(20 日 > 15 日)→ 社保截止 2026-08 → 公积金截止 2026-08
|
||
- 手工验证:修改 cutoffDay 为 10 → 离职日期 2026-08-15 → 社保截止 2026-08
|
||
|
||
### TASK-008:合规检查"已支付经济补偿金"改为软阻断+待办(问题 3)
|
||
|
||
- **目标**:合规检查未勾选项可下一步,但自动写入待办和风险提醒
|
||
- **对应需求**:问题 3
|
||
- **验收标准**:
|
||
- [x] step 2 合规检查未勾选 required 项时,可进入下一步(不硬阻断)
|
||
- [x] 未勾选的 required 项自动写入待办事项,关联 `termination_draft`
|
||
- [x] Dashboard/风险中心展示"XX 员工解聘未支付经济补偿金"等待办
|
||
- [x] 提交审批时若仍存在未闭环必检项,给出强提示但不阻断
|
||
- [x] 法定禁止情形(孕期/工伤/医疗期)仍硬阻断
|
||
- **依赖**:无
|
||
- **优先级**:P1
|
||
- **阶段**:第二批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/Termination.tsx`(step 2 校验逻辑改为软阻断)
|
||
- `backend/src/services/notification.service.ts`(待办生成)
|
||
- `backend/src/services/risk.service.ts`(风险提醒生成)
|
||
- `frontend/src/pages/Dashboard.tsx`(待办展示)
|
||
- **测试要求**:
|
||
- 手工验证:合规检查不勾"已支付经济补偿金" → 可下一步 → Dashboard 出现待办"XX 解聘未支付经济补偿金"
|
||
|
||
### TASK-009:补偿月数支持 N / N+1 / 2N / 其他(问题 5)
|
||
|
||
- **目标**:补偿月数改为下拉选择,支持手动修改并重算补偿金
|
||
- **对应需求**:问题 5
|
||
- **验收标准**:
|
||
- [x] 补偿月数改为下拉:N(默认)、N+1、2N、其他(自定义输入)
|
||
- [x] 选择"协商解除"时允许修改月数
|
||
- [x] 月数变更后实时重算补偿金 = 月数 × 计算基数
|
||
- [x] 选择"其他"时需填写说明,留痕到 `compensationBreakdown.adjustments`
|
||
- [x] 系统计算值 N 仍作为默认推荐显示
|
||
- **依赖**:TASK-002(补偿金合计逻辑)
|
||
- **优先级**:P1
|
||
- **阶段**:第二批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/Termination.tsx`(step 3 补偿月数下拉)
|
||
- `backend/src/services/termination.service.ts`(月数模式存储)
|
||
- **测试要求**:
|
||
- 手工验证:系统算 N=3 → 选择 N+1 → 月数变 4 → 补偿金重算 → 选择"其他"→ 输入 5 + 说明 → 补偿金重算
|
||
|
||
### TASK-010:计算基数支持多种来源(问题 6)
|
||
|
||
- **目标**:计算基数改为下拉选择,支持多种来源切换
|
||
- **对应需求**:问题 6
|
||
- **验收标准**:
|
||
- [x] 计算基数改为下拉:近 12 月平均工资(默认)、合同工资、其他(手动填写)
|
||
- [x] 切换来源后实时重算补偿金
|
||
- [x] 选用算法记录到草稿 `compensationBreakdown.wageBaseType`
|
||
- [x] "其他"需填写说明,受三倍社平封顶提示但不强制
|
||
- [x] 近 12 月平均工资仍显示三倍社平封顶后的值
|
||
- **依赖**:TASK-009(月数与基数联动重算)
|
||
- **优先级**:P1
|
||
- **阶段**:第二批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/Termination.tsx`(step 3 计算基数下拉)
|
||
- `backend/src/services/termination.service.ts`(wageBaseType 存储)
|
||
- **测试要求**:
|
||
- 手工验证:默认近 12 月平均 ¥10000 → 切换为合同工资 ¥8000 → 补偿金重算 → 切换为"其他"→ 手动输入 ¥12000 + 说明 → 重算
|
||
|
||
### TASK-011:工作交接未完成改为软阻断+待办(问题 8)
|
||
|
||
- **目标**:工作交接未完成可下一步,未完成事项进入待办提醒
|
||
- **对应需求**:问题 8
|
||
- **验收标准**:
|
||
- [x] step 4 工作交接未完成时可进入下一步(不硬阻断)
|
||
- [x] 交接清单前三项(work_handover/equipment_return/access_revoke)标注"离职必办"
|
||
- [x] 未完成事项自动写入待办,关联离职草稿
|
||
- [x] 确认页和风险中心强提示未完成交接项
|
||
- [x] 待办在到达离职日期前持续提醒,超期升级为风险
|
||
- **依赖**:TASK-008(待办机制复用)
|
||
- **优先级**:P1
|
||
- **阶段**:第二批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/Termination.tsx`(step 4 校验改为软阻断、确认页提示)
|
||
- `backend/src/services/notification.service.ts`(待办生成与提醒)
|
||
- **测试要求**:
|
||
- 手工验证:工作交接不勾"工作交接完成" → 可下一步 → 确认页提示"3 项未完成" → Dashboard 出现待办
|
||
|
||
### TASK-012:离职管理"新建解聘"并入花名册操作栏(问题 9)
|
||
|
||
- **目标**:花名册操作栏"离职"按钮支持所有解聘类型,离职管理列表页移除新建入口
|
||
- **对应需求**:问题 9
|
||
- **验收标准**:
|
||
- [x] 花名册操作栏"离职"按钮点击后弹出解聘类型选择(协商/过错/非过错/裁员/到期/违法/主动离职)
|
||
- [x] 选择类型后跳转 Termination 向导,URL 带参数预填员工 ID 和解聘类型
|
||
- [x] Termination 向导支持从 URL 参数读取 `employeeId` 和 `reason` 自动预填
|
||
- [x] 离职管理列表页移除"新建解聘"按钮,仅保留草稿列表与审批
|
||
- [x] 主动离职(RESIGNATION)仍走原 ResignModal 快速流程
|
||
- **实际实现状态(2026-08-15 复查)**:
|
||
- ✅ 花名册离职按钮弹出 ResignModal,支持7种解聘类型选择
|
||
- ✅ 非主动离职类型跳转 `/termination?employeeId=xxx&reason=xxx`
|
||
- ✅ Termination 向导从 URL 参数读取 employeeId 和 reason 预填
|
||
- ✅ 列表页已移除"新建解聘"按钮(2026-08-15 已确认移除)
|
||
- ✅ 主动离职走 ResignModal 快速流程
|
||
- ⚠️ 成功页面(第1962行)仍保留"新建解聘"按钮 — 属于流程内继续操作,可接受
|
||
- **依赖**:无
|
||
- **优先级**:P1
|
||
- **阶段**:第二批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/Roster.tsx`(操作栏离职按钮扩展)
|
||
- `frontend/src/pages/roster/modals.tsx`(ResignModal 扩展或新增类型选择 Modal)
|
||
- `frontend/src/pages/Termination.tsx`(URL 参数预填支持)
|
||
- **测试要求**:
|
||
- 手工验证:花名册点击员工"离职" → 弹出类型选择 → 选择"协商解除" → 跳转 Termination → 员工和类型已预填
|
||
|
||
### TASK-013:合同续签新增合同开始日期自动推导(问题 12)
|
||
|
||
- **目标**:续签合同时,新合同开始日期默认 = 上一份合同结束日期 + 1 天
|
||
- **对应需求**:问题 12
|
||
- **验收标准**:
|
||
- [x] RENEW 表单选择员工后,自动拉取最新已签合同
|
||
- [x] `newStartDate` 默认 = 上一份合同 `endDate + 1 天`
|
||
- [x] 允许手动覆盖,偏离时提示"建议开始日期为 YYYY-MM-DD"
|
||
- [x] 无历史合同时默认为今天
|
||
- **依赖**:TASK-005(日期校验)
|
||
- **优先级**:P1
|
||
- **阶段**:第二批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/WorkProcess.tsx`(RENEW 字段联动)
|
||
- `backend/src/services/work-process.service.ts`(查询员工最新合同)
|
||
- **测试要求**:
|
||
- 手工验证:员工合同结束日期 2026-05-31 → 新增续签 → 新合同开始日期自动填 2026-06-01
|
||
|
||
### TASK-014:添加员工根据证件号码进行年龄合规筛查(问题 15)
|
||
|
||
- **目标**:解析证件号码自动计算年龄,童工阻断、退休提示
|
||
- **对应需求**:问题 15
|
||
- **验收标准**:
|
||
- [x] 解析身份证号出生日期,计算年龄
|
||
- [x] 年龄 < 16 岁:禁止录入,强提示"禁止使用童工(未满 16 周岁)",阻断保存
|
||
- [x] 年龄 ≥ 60(男)/55(女干部)/50(女工人):提示"已达法定退休年龄",确认后允许录入,自动标记 `retirementFlag`
|
||
- [x] 年龄校验在 `handleIdCardChange` 中实时执行
|
||
- **依赖**:无
|
||
- **优先级**:P1
|
||
- **阶段**:第二批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/roster/modals.tsx`(`handleIdCardChange` 增加年龄校验)
|
||
- `backend/src/routes/employee.routes.ts`(后端年龄校验双保险)
|
||
- **测试要求**:
|
||
- 手工验证:身份证号出生日期 2015-01-01(11 岁)→ 阻断提示"禁止使用童工"
|
||
- 手工验证:身份证号出生日期 1965-01-01(61 岁男)→ 提示"已达法定退休年龄" → 确认后可录入
|
||
|
||
### TASK-015:编辑入职日期后状态联动变更(问题 16)
|
||
|
||
- **目标**:编辑入职日期后,员工状态自动联动
|
||
- **对应需求**:问题 16
|
||
- **验收标准**:
|
||
- [x] 编辑入职日期 > 今天 → 状态自动设为 `PENDING_ONBOARD`(待入职)
|
||
- [x] 编辑入职日期 ≤ 今天 → 状态自动设为 `ACTIVE`(在职)
|
||
- [x] 状态变更需二次确认弹窗"入职日期变更将导致状态从 XX 变为 YY,是否继续?"
|
||
- [x] 变更记录留痕到员工档案(操作日志)
|
||
- **依赖**:无
|
||
- **优先级**:P1
|
||
- **阶段**:第二批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/roster/BasicInfo.tsx`(入职日期编辑联动状态确认)
|
||
- `backend/src/services/employee.service.ts`(状态联动逻辑)
|
||
- **测试要求**:
|
||
- 手工验证:在职员工入职日期改为下月 1 日 → 弹窗确认 → 状态变为"待入职"
|
||
- 手工验证:待入职员工入职日期改为今天 → 弹窗确认 → 状态变为"在职"
|
||
|
||
### TASK-016:员工转正移植到花名册操作栏(问题 18)
|
||
|
||
- **目标**:花名册操作栏"发薪"按钮替换为"转正"按钮
|
||
- **对应需求**:问题 18
|
||
- **验收标准**:
|
||
- [x] 操作栏"发薪"按钮(Wallet 图标)替换为"转正"按钮(CheckCircle 图标)
|
||
- [x] 仅试用期员工(`probationInfo.isProbation === true`)显示转正按钮
|
||
- [x] 点击弹出转正 Modal(转正日期 + 转正薪资)
|
||
- [x] 转正完成后员工状态从试用期转为正式
|
||
- [x] 发薪入口保留在薪税管理模块(移除操作栏发薪按钮不影响薪税功能)
|
||
- **依赖**:无
|
||
- **优先级**:P1
|
||
- **阶段**:第二批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/Roster.tsx`(操作栏按钮替换)
|
||
- `frontend/src/pages/roster/modals.tsx`(新增 `ConfirmModal`)
|
||
- `backend/src/services/employee.service.ts`(转正接口)
|
||
- **测试要求**:
|
||
- 手工验证:试用期员工操作栏显示"转正"按钮 → 点击 → 填写转正日期+薪资 → 确认 → 状态变为正式
|
||
|
||
### TASK-017:转正薪资回写花名册+用工协议匹配校验(问题 19)
|
||
|
||
- **目标**:转正完成后同步更新员工薪资,校验与合同薪资一致性
|
||
- **对应需求**:问题 19
|
||
- **验收标准**:
|
||
- [x] 转正完成后同步更新员工 `monthlySalary`
|
||
- [x] 花名册明细展示"试用期薪资 → 转正薪资"变更记录
|
||
- [x] 校验转正薪资与最新合同 `monthlySalary` 是否一致
|
||
- [x] 不一致时提示"转正薪资 ¥X 与合同薪资 ¥Y 不一致,是否发起合同变更?"
|
||
- [x] 支持一键跳转合同变更流程(CHANGE)
|
||
- **依赖**:TASK-016(转正功能)
|
||
- **优先级**:P1
|
||
- **阶段**:第二批
|
||
- **涉及文件**:
|
||
- `backend/src/services/work-process.service.ts`(CONFIRM 完成回调更新薪资)
|
||
- `frontend/src/pages/roster/SalaryInfo.tsx`(薪资变更记录展示)
|
||
- `frontend/src/pages/Roster.tsx`(不一致提示与跳转)
|
||
- **测试要求**:
|
||
- 手工验证:试用期薪资 ¥8000 → 转正填写 ¥10000 → 确认 → 花名册薪资更新为 ¥10000 → 如合同薪资 ¥9000 → 提示不一致
|
||
|
||
### TASK-018:合同变更/续签选择员工后过滤合同列表(问题 22+23)
|
||
|
||
- **目标**:contract-select 组件按员工过滤合同,RENEW 的 oldContractId 改为下拉选择
|
||
- **对应需求**:问题 22 + 问题 23
|
||
- **验收标准**:
|
||
- [x] `contract-select` 组件接收 `employeeId` 参数,仅返回该员工的有效合同
|
||
- [x] CHANGE 表单选择员工后,合同下拉仅显示该员工合同
|
||
- [x] RENEW 表单 `oldContractId` 从 `text` 改为 `contract-select`,选择员工后下拉展示该员工已存在合同
|
||
- [x] 后端合同查询接口支持 `employeeId` 过滤
|
||
- [x] 合同下拉显示合同名称 + 起止日期 + 状态
|
||
- **依赖**:无
|
||
- **优先级**:P1
|
||
- **阶段**:第二批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/WorkProcess.tsx`(contract-select 组件改造、RENEW 字段类型)
|
||
- `backend/src/routes/contract.routes.ts`(employeeId 过滤)
|
||
- **测试要求**:
|
||
- 手工验证:合同变更 → 选择员工 A → 合同下拉仅显示员工 A 的合同
|
||
- 手工验证:合同续签 → 选择员工 A → 原合同下拉显示员工 A 的已签合同(非 UUID 手输)
|
||
|
||
### TASK-019:男职工无法选择三期(问题 29)
|
||
|
||
- **目标**:特殊员工表单根据性别过滤类型,男职工不可选三期
|
||
- **对应需求**:问题 29
|
||
- **验收标准**:
|
||
- [x] 选择员工后,若 `gender === '男'`,类型下拉移除"三期"选项或置灰
|
||
- [x] 置灰时提示"三期仅适用于女性员工"
|
||
- [x] 后端保存时增加校验:男职工 + PREGNANCY 组合返回 400
|
||
- [x] 编辑已有记录时,如原记录为三期但员工为男性(历史脏数据),提示修正
|
||
- **依赖**:无
|
||
- **优先级**:P1
|
||
- **阶段**:第二批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/SpecialStatus.tsx`(表单 type 下拉过滤)
|
||
- `backend/src/services/special-status.service.ts`(后端校验)
|
||
- **测试要求**:
|
||
- 手工验证:选择男员工 → 类型下拉无"三期" → 后端直接传 PREGNANCY → 返回 400
|
||
|
||
---
|
||
|
||
## 第三批:P2 中(9 条)
|
||
|
||
### TASK-020:"劳动合同"调整为"用工关系"(问题 1)
|
||
|
||
- **目标**:全域面向用户文案中"劳动合同"在合适场景改为"用工关系"或"用工协议"
|
||
- **对应需求**:问题 1
|
||
- **验收标准**:
|
||
- [x] 全域文案审计完成,列出所有"劳动合同"出现位置
|
||
- [x] 面向用户的菜单/标题/提示中"劳动合同"改为"用工关系"或"用工协议"
|
||
- [x] 法律文书模板中的"劳动合同"保持不变(法定术语)
|
||
- [x] `Contract` 模型新增 `contractCategory` 字段(LABOR_CONTRACT/LABOR_AGREEMENT/INTERNSHIP/FLEXIBLE)
|
||
- [x] HelpModal、OnboardingGuide 帮助文案同步更新
|
||
- **依赖**:无
|
||
- **优先级**:P2
|
||
- **阶段**:第三批
|
||
- **涉及文件**:`SidebarNav.tsx`、`Contracts.tsx`、`WorkProcess.tsx`、`Termination.tsx`、`HelpModal.tsx`、`OnboardingGuide.tsx` 等
|
||
- **DB 变更**:`LaborContract` 新增 `contractCategory` 字段(nullable,默认 LABOR_CONTRACT)
|
||
- **测试要求**:全域搜索"劳动合同"确认无遗漏(法律文书模板除外)
|
||
|
||
### TASK-021:费用结算新增"剩余年假天数"(问题 4)
|
||
|
||
- **目标**:费用结算区新增年假折算,计入合计应付
|
||
- **对应需求**:问题 4
|
||
- **验收标准**:
|
||
- [x] 费用结算区新增"剩余年假天数"字段(手动录入或调用考勤年假余额)
|
||
- [x] 按规则计算未休年假折算工资:`日工资 × 剩余年假天数 × 300%`
|
||
- [x] 日工资 = 月工资 / 21.75
|
||
- [x] 折算金额计入"合计应付"
|
||
- [x] 年假折算明细在确认页和文书中展示
|
||
- **依赖**:TASK-002(合计计算逻辑)
|
||
- **优先级**:P2
|
||
- **阶段**:第三批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/Termination.tsx`(step 3 年假字段)
|
||
- `backend/src/services/termination.service.ts`(年假折算计算)
|
||
- **测试要求**:
|
||
- 手工验证:剩余年假 5 天 → 日工资 ¥460(¥10000/21.75)→ 折算 ¥6900(5×460×300%)→ 合计应付包含 ¥6900
|
||
|
||
### TASK-022:身份证号全域改为"证件号码"(问题 14)
|
||
|
||
- **目标**:全域 label "身份证号"改为"证件号码",支持证件类型下拉
|
||
- **对应需求**:问题 14
|
||
- **验收标准**:
|
||
- [x] 全域 label "身份证号"替换为"证件号码"
|
||
- [x] 字段名 `idCardNumber` 保持不变(兼容历史数据)
|
||
- [x] 新增证件类型下拉(身份证/护照/港澳台通行证/其他),存储到 `idType` 字段
|
||
- [x] 证件类型为"身份证"时保留 18 位校验 + 性别/年龄自动推导
|
||
- [x] 非身份证类型时跳过 18 位校验
|
||
- [x] 搜索 placeholder 同步更新
|
||
- **依赖**:TASK-014(年龄校验需适配证件类型)
|
||
- **优先级**:P2
|
||
- **阶段**:第三批
|
||
- **涉及文件**:`roster/modals.tsx`、`WorkProcess.tsx`、`Roster.tsx`、`SpecialStatus.tsx`、`BasicInfo.tsx` 等
|
||
- **DB 变更**:`Employee` 新增 `idType` 字段(nullable,默认 ID_CARD)
|
||
- **测试要求**:全域搜索"身份证号"确认无遗漏
|
||
|
||
### TASK-023:录入手机号查重(问题 17)
|
||
|
||
- **目标**:手机号录入时查重,已存在提示"该手机号已用于 XX 人员"
|
||
- **对应需求**:问题 17
|
||
- **验收标准**:
|
||
- [x] 手机号录入时调用查重接口
|
||
- [x] 已存在则提示"该手机号已用于 XX 人员"
|
||
- [x] 允许继续保存(一人多号/家庭号场景),但强提示确认
|
||
- [x] 后端新增 `/employees/check-phone` 接口
|
||
- [x] 手机号格式校验(11 位数字)
|
||
- **依赖**:无
|
||
- **优先级**:P2
|
||
- **阶段**:第三批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/roster/modals.tsx`(手机号查重)
|
||
- `backend/src/routes/employee.routes.ts`(新增查重接口)
|
||
- **测试要求**:
|
||
- 手工验证:录入已存在手机号 → 提示"该手机号已用于 张三 人员" → 可继续保存
|
||
|
||
### TASK-024:开具证明移植到花名册操作栏(问题 20)
|
||
|
||
- **目标**:操作栏新增"证明"按钮,支持快速开具证明
|
||
- **对应需求**:问题 20
|
||
- **验收标准**:
|
||
- [x] 操作栏新增"证明"按钮(FileText 图标)
|
||
- [x] 点击弹出证明类型选择(收入证明/离职证明/在职证明)
|
||
- [x] 复用 WorkProcess 的 INCOME_CERT/LEAVING_CERT 表单
|
||
- [x] 生成后支持下载/打印
|
||
- **实际实现状态(2026-08-15 复查)**:
|
||
- ✅ 操作栏有"证明"按钮(FileText 图标)
|
||
- ✅ 已增加证明类型选择(收入证明/在职证明/离职证明)— 已修复
|
||
- **依赖**:无
|
||
- **优先级**:P2
|
||
- **阶段**:第三批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/Roster.tsx`(操作栏新增按钮)
|
||
- `frontend/src/pages/roster/modals.tsx`(证明类型选择 Modal)
|
||
- **测试要求**:
|
||
- 手工验证:点击操作栏"证明" → 选择"收入证明" → 填写信息 → 生成 → 可下载
|
||
|
||
### TASK-025:合同续签移植到花名册操作栏(问题 21)
|
||
|
||
- **目标**:操作栏新增"续签"按钮,合同即将到期时显示
|
||
- **对应需求**:问题 21
|
||
- **验收标准**:
|
||
- [x] 操作栏新增"续签"按钮(Repeat 图标)
|
||
- [x] 仅合同即将到期(≤30 天)或已到期员工显示
|
||
- [x] 点击跳转 WorkProcess RENEW 并预填员工(URL 参数)
|
||
- [x] WorkProcess 支持从 URL 参数读取 `employeeId` 自动预填
|
||
- **实际实现状态(2026-08-15 复查)**:
|
||
- ✅ 操作栏有"续签"按钮(RotateCcw 图标)
|
||
- ✅ 已按合同到期状态过滤(仅 expiring/expired 显示)— 已修复
|
||
- ⚠️ 在花名册弹窗处理续签,未跳转 WorkProcess — 可接受(体验更流畅)
|
||
- **依赖**:TASK-013(续签开始日期自动推导)、TASK-018(合同选择)
|
||
- **优先级**:P2
|
||
- **阶段**:第三批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/Roster.tsx`(操作栏新增按钮)
|
||
- `frontend/src/pages/WorkProcess.tsx`(URL 参数预填)
|
||
- **测试要求**:
|
||
- 手工验证:合同 25 天后到期 → 操作栏显示"续签"按钮 → 点击 → 跳转 RENEW → 员工已预填
|
||
|
||
### TASK-026:花名册多选增加批量转正(问题 24)
|
||
|
||
- **目标**:多选员工后支持批量转正
|
||
- **对应需求**:问题 24
|
||
- **验收标准**:
|
||
- [x] 多选后新增"批量转正"按钮,仅对试用期员工生效
|
||
- [x] 弹窗统一填写转正日期(默认今天)和转正薪资
|
||
- [x] 转正薪资支持"按原薪资倍数"或"手动逐人填写"
|
||
- [x] 调用后端批量转正接口
|
||
- [x] 复用 TASK-016 的转正逻辑
|
||
- **实际实现状态(2026-08-15 复查)**:
|
||
- ✅ 多选后有"批量转正"按钮,仅对试用期员工生效
|
||
- ✅ 已增加弹窗填写转正日期和薪资 — 已修复
|
||
- **依赖**:TASK-016(单人转正)、TASK-017(薪资回写)
|
||
- **优先级**:P2
|
||
- **阶段**:第三批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/Roster.tsx`(批量操作栏新增按钮)
|
||
- `frontend/src/pages/roster/modals.tsx`(批量转正 Modal)
|
||
- `backend/src/services/employee.service.ts`(批量转正接口)
|
||
- **测试要求**:
|
||
- 手工验证:多选 3 名试用期员工 → 批量转正 → 填写统一日期+薪资 → 确认 → 3 人状态均变为正式
|
||
|
||
### TASK-027:花名册多选增加批量开具证明(问题 25)
|
||
|
||
- **目标**:多选员工后支持批量开具证明
|
||
- **对应需求**:问题 25
|
||
- **验收标准**:
|
||
- [x] 多选后新增"批量开具证明"按钮
|
||
- [x] 选择证明类型(在职/收入)后批量生成
|
||
- [x] 支持批量下载(ZIP)或逐个下载
|
||
- [x] 后端新增批量生成接口
|
||
- **实际实现状态(2026-08-15 复查)**:
|
||
- ✅ 多选后有"批量开具证明"按钮
|
||
- ✅ 已增加证明类型选择(收入证明/在职证明/离职证明)— 已修复
|
||
- ⚠️ 未实现 ZIP 批量下载,仅提示去证据管理查看 — 体验可接受
|
||
- **依赖**:TASK-024(单人开具证明)
|
||
- **优先级**:P2
|
||
- **阶段**:第三批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/Roster.tsx`(批量操作栏新增按钮)
|
||
- `backend/src/services/work-process.service.ts`(批量生成接口)
|
||
- **测试要求**:
|
||
- 手工验证:多选 3 名员工 → 批量开具在职证明 → 生成 3 份 → 可批量下载 ZIP
|
||
|
||
### TASK-028:去掉用工办理模块(问题 26)
|
||
|
||
- **目标**:侧边栏移除"用工办理"菜单,入口下沉到花名册操作栏和独立页面
|
||
- **对应需求**:问题 26
|
||
- **验收标准**:
|
||
- [x] 各流程入口已下沉:转正(TASK-016)、续签(TASK-025)、变更(TASK-018)、开具证明(TASK-024)、入职(保留在花名册添加员工)
|
||
- [x] 侧边栏移除"用工办理"菜单项
|
||
- [x] WorkProcess 页面保留作为批量流程入口,迁移到"更多"分组或保留路由但不显示菜单
|
||
- [x] 已有 WorkProcess 草稿列表仍可访问(不丢数据)
|
||
- [x] 帮助文案同步更新
|
||
- **依赖**:TASK-016、TASK-018、TASK-024、TASK-025 全部完成
|
||
- **优先级**:P2
|
||
- **阶段**:第三批(最后执行)
|
||
- **涉及文件**:
|
||
- `frontend/src/components/layout/SidebarNav.tsx`(移除菜单项)
|
||
- `frontend/src/pages/Roster.tsx`(确认所有入口已下沉)
|
||
- `frontend/src/App.tsx`(路由保留但菜单移除)
|
||
- `frontend/src/components/HelpModal.tsx`(帮助文案更新)
|
||
- **测试要求**:
|
||
- 手工验证:侧边栏无"用工办理" → 花名册操作栏可完成转正/续签/变更/证明 → WorkProcess 页面仍可通过 URL 访问
|
||
|
||
---
|
||
|
||
## 第四批:P3 规划(2 项)
|
||
|
||
### TASK-029:组织架构+简单审批流(问题 27,方案 A)
|
||
|
||
- **目标**:新增组织架构模块(树形部门+岗位字典+上下级关系),支持三步以内审批流转
|
||
- **对应需求**:问题 27(方案 A:保留 position 单字段,岗位独立建表)
|
||
- **验收标准**:
|
||
- [x] **组织架构子页**:系统设置新增"组织架构"
|
||
- 树形部门管理(`Department` 自引用 parent,支持增删改查、拖拽排序)
|
||
- 岗位字典(`Position`,含名称/所属部门/编制人数/职级)
|
||
- 员工 `position` 字段关联岗位字典(可选,兼容旧文本数据)
|
||
- 上下级关系(`Employee.supervisorId`)
|
||
- [x] **审批流配置**:
|
||
- 最多 3 步(发起人 → 直属上级 → 部门负责人)
|
||
- 按流程类型(休假/离职/调薪)配置是否启用某步
|
||
- 审批人可指定"直属上级"或"具体人员"
|
||
- [x] **现有流程接入**:
|
||
- `LeaveApproval` 接入审批流引擎
|
||
- 离职/调薪等流程可选启用审批流
|
||
- [x] **数据模型**:
|
||
- `Department`(id/name/parentId/level/sortOrder/orgId)
|
||
- `Position`(id/name/departmentId/headcount/level/orgId)
|
||
- `Employee` 新增 `supervisorId`、`departmentId`(关联 Department,兼容旧 department 字符串)
|
||
- `ApprovalFlow`(id/type/steps/config/orgId)
|
||
- `ApprovalInstance`(id/flowId/status/currentStep/approver/result/createdAt)
|
||
- **依赖**:第三批完成
|
||
- **优先级**:P3
|
||
- **阶段**:第四批
|
||
- **涉及文件**:
|
||
- 新增 `frontend/src/pages/OrgChart.tsx`(组织架构可视化)
|
||
- `frontend/src/pages/Settings.tsx`(新增组织架构 Tab)
|
||
- `backend/prisma/schema.prisma`(Department/Position/ApprovalFlow/ApprovalInstance 模型)
|
||
- 新增 `backend/src/services/approval.service.ts`(审批流引擎)
|
||
- 新增 `backend/src/routes/department.routes.ts`、`backend/src/routes/position.routes.ts`、`backend/src/routes/approval.routes.ts`
|
||
- `frontend/src/pages/LeaveApproval.tsx`(接入审批流)
|
||
- **DB 变更**:新增 4 个模型 + Employee 2 个字段,migration + 回滚方案 + seed 数据
|
||
- **测试要求**:
|
||
- 手工验证:创建部门"技术部" → 创建岗位"前端工程师" → 员工关联部门和岗位 → 配置休假审批流(直属上级→部门负责人)→ 提交休假申请 → 直属上级审批 → 部门负责人审批 → 通过
|
||
|
||
### TASK-030:客服工作台增强(问题 31 增强全部 6 项)
|
||
|
||
- **目标**:在平台管理端基础上扩展客服工作台功能
|
||
- **对应需求**:问题 31 增强部分
|
||
- **验收标准**:
|
||
- [x] **角色与路由**:
|
||
- 新增 `SUPPORT` 角色
|
||
- 独立路由 `/support/*`,独立登录页 `/support/login`
|
||
- 独立侧边栏 `SupportSidebar`
|
||
- [x] **工单管理**:
|
||
- `Ticket` 模型(标题/内容/状态/优先级/归属租户/处理人)
|
||
- `TicketMessage` 模型(工单回复)
|
||
- 工单列表、详情、回复、关闭、转派
|
||
- 客户端(企业端)可提交工单
|
||
- [x] **客户会话**:
|
||
- `ChatSession` 模型(客户会话)
|
||
- 客服与客户企业管理员实时沟通或留言
|
||
- 未读消息提醒
|
||
- [x] **租户数据穿透**:
|
||
- 客服选择租户后,以"只读+代操作"模式访问该租户业务数据
|
||
- 请求头带 `X-Support-Tenant-Id`,后端中间件切换租户上下文
|
||
- 可查看花名册/合同/薪税/风险等数据
|
||
- [x] **协助操作**:
|
||
- 代客户重置密码(已有,复用)
|
||
- 代客户调整套餐(已有,复用)
|
||
- 代客户发起流程(新增)
|
||
- [x] **AI 辅助**:
|
||
- 客服侧 AI 问答,复用现有 AI 接口
|
||
- 独立会话隔离,不影响客户企业 AI 用量
|
||
- [x] **操作日志**:
|
||
- 客服操作留痕审计
|
||
- `AuditLog` 扩展支持客服角色操作记录
|
||
- **依赖**:第三批完成
|
||
- **优先级**:P3
|
||
- **阶段**:第四批
|
||
- **涉及文件**:
|
||
- 新增 `frontend/src/pages/support/*`(SupportDashboard/Tickets/Chat/TenantData/AI/Logs)
|
||
- 新增 `frontend/src/components/layout/SupportSidebar.tsx`
|
||
- `backend/prisma/schema.prisma`(Ticket/TicketMessage/ChatSession 模型,User.role 新增 SUPPORT)
|
||
- 新增 `backend/src/routes/support.routes.ts`
|
||
- 新增 `backend/src/middleware/support-tenant.ts`(租户上下文切换)
|
||
- `backend/src/routes/platform.routes.ts`(工单/会话接口复用)
|
||
- **DB 变更**:新增 3 个模型 + User.role 枚举新增 SUPPORT,migration + 回滚方案
|
||
- **测试要求**:
|
||
- 手工验证:客服登录 → 查看工单列表 → 回复工单 → 选择租户 → 穿透查看花名册 → AI 辅助问答 → 操作日志记录
|
||
|
||
---
|
||
|
||
## 第五批:电子签署完整流程 + 线下手签 + 证据链体系(2026-08-16 新增)
|
||
|
||
> 背景:原系统电子签署模块存在两套并行且互不连通的签署机制、无实际签署流程、无证据链集成、无验证码确认、无线下手签支持等问题。本批次系统性重构电子签署模块,建立完整的法律证据链体系。
|
||
|
||
### TASK-031:电子签署后端路由重写 + 模板自动渲染(P0)
|
||
|
||
- **目标**:重写 esign.routes.ts,支持完整的电子签署发起流程,自动从模板渲染文件内容
|
||
- **对应需求**:电子签署逻辑审计 P0-1/P1-1
|
||
- **验收标准**:
|
||
- [x] 发起签署时校验组织电子签开关(POLICY/PAYSLIP/ONBOARDING)
|
||
- [x] 自动从模板渲染文件内容(CONTRACT→劳动合同模板,RESIGNATION→离职协议模板)
|
||
- [x] 创建签署记录时自动创建证据链(发起签署事件)
|
||
- [x] 新增签署详情接口、证据链查看接口
|
||
- [x] 取消签署追加证据链事件
|
||
- [x] 签署状态查询自动处理过期记录
|
||
- **依赖**:无
|
||
- **优先级**:P0
|
||
- **阶段**:第五批
|
||
- **涉及文件**:
|
||
- `backend/src/routes/esign.routes.ts`(重写)
|
||
- `backend/src/services/template.service.ts`(renderTemplate/getTemplateById 集成)
|
||
- `backend/src/services/evidence.service.ts`(createEvidence 集成)
|
||
- **测试要求**:
|
||
- 手工验证:发起劳动合同签署 → 自动渲染模板内容 → 创建证据链 → 详情页可查看
|
||
|
||
### TASK-032:员工端签署验证码确认机制(P0)
|
||
|
||
- **目标**:员工端签署增加手机验证码确认,确保签署行为真实性
|
||
- **对应需求**:电子签署逻辑审计 P0-1
|
||
- **验收标准**:
|
||
- [x] 员工端新增验证码发送接口(/esign/:id/send-code)
|
||
- [x] 签署操作增加验证码校验(5次错误限制 + 60秒限流)
|
||
- [x] 签署完成追加证据链(IP/UA/时间戳/验证码/签署人)
|
||
- [x] 签署完成回写合同 signMethod + attachmentName(签署证据)
|
||
- [x] 列表和详情接口自动处理过期记录
|
||
- **依赖**:TASK-031
|
||
- **优先级**:P0
|
||
- **阶段**:第五批
|
||
- **涉及文件**:
|
||
- `backend/src/routes/portal.routes.ts`(员工端 esign 重写)
|
||
- `backend/src/services/codeStore.ts`(setCode/getCode/checkRateLimit)
|
||
- **测试要求**:
|
||
- 手工验证:员工查看待签文件 → 获取验证码 → 输入验证码 → 签署完成 → 证据链记录
|
||
|
||
### TASK-033:签署全流程证据链体系(P0)
|
||
|
||
- **目标**:签署全流程(发起/验证码发送/签署完成/取消)自动记录证据链,确保法律效力
|
||
- **对应需求**:电子签署逻辑审计 P0-2
|
||
- **验收标准**:
|
||
- [x] 发起签署时创建证据链(事件1:发起签署)
|
||
- [x] 发送验证码时追加证据链(事件2:验证码发送)
|
||
- [x] 签署完成时追加证据链(事件3:签署完成,含IP/UA/时间戳/验证码/签署人)
|
||
- [x] 取消签署时追加证据链(事件4:取消签署)
|
||
- [x] 证据链包含 hash 值用于完整性校验
|
||
- [x] 管理端详情页可查看完整证据链时间线
|
||
- **依赖**:TASK-031、TASK-032
|
||
- **优先级**:P0
|
||
- **阶段**:第五批
|
||
- **涉及文件**:
|
||
- `backend/src/routes/esign.routes.ts`(发起/取消证据链)
|
||
- `backend/src/routes/portal.routes.ts`(验证码/签署完成证据链)
|
||
- `backend/src/services/evidence.service.ts`(createEvidence/appendEvidence)
|
||
- **测试要求**:
|
||
- 手工验证:完整签署流程 → 详情页证据链显示3-4个事件 → 含时间戳/IP/操作人
|
||
|
||
### TASK-034:签署完成回写合同 + 生成签署证据(P1)
|
||
|
||
- **目标**:签署完成后自动回写合同签署方式,生成签署证据文件
|
||
- **对应需求**:电子签署逻辑审计 P1-3
|
||
- **验收标准**:
|
||
- [x] 签署完成回写合同 signMethod=ELECTRONIC
|
||
- [x] 回写合同 attachmentName(含IP/UA/时间戳证据摘要)
|
||
- [x] 签署证据写入 callbackData
|
||
- [x] 对接易签宝后自动回写 signedPdfUrl(预留接口)
|
||
- **依赖**:TASK-032
|
||
- **优先级**:P1
|
||
- **阶段**:第五批
|
||
- **涉及文件**:
|
||
- `backend/src/routes/portal.routes.ts`(签署完成回写逻辑)
|
||
- **测试要求**:
|
||
- 手工验证:劳动合同签署完成 → 合同 signMethod 变为 ELECTRONIC → attachmentName 包含证据摘要
|
||
|
||
### TASK-035:组织电子签开关校验(P1)
|
||
|
||
- **目标**:发起签署前校验组织级别的电子签开关,未开启的场景不允许发起
|
||
- **对应需求**:电子签署逻辑审计 P1-2
|
||
- **验收标准**:
|
||
- [x] 发起签署前校验 SCENE_ORG_FLAG_MAP 对应的组织开关
|
||
- [x] CONTRACT/RESIGNATION 场景默认允许(不依赖开关)
|
||
- [x] POLICY/PAYSLIP/ONBOARDING 场景需对应开关开启
|
||
- [x] 开关未开启时返回明确错误提示
|
||
- **依赖**:TASK-031
|
||
- **优先级**:P1
|
||
- **阶段**:第五批
|
||
- **涉及文件**:
|
||
- `backend/src/routes/esign.routes.ts`(开关校验逻辑)
|
||
- **测试要求**:
|
||
- 手工验证:组织未开启 POLICY 开关 → 发起规章制度签署 → 返回错误提示
|
||
|
||
### TASK-036:scene 关联模板自动填充 + 过期自动处理(P2)
|
||
|
||
- **目标**:签署场景与模板自动关联,过期记录自动标记
|
||
- **对应需求**:电子签署逻辑审计 P2-1
|
||
- **验收标准**:
|
||
- [x] SCENE_TEMPLATE_MAP 映射(CONTRACT→劳动合同,RESIGNATION→离职协议)
|
||
- [x] 前端场景选择后自动填充默认文件标题
|
||
- [x] 列表/详情/状态查询时自动将过期 PENDING 标记为 EXPIRED
|
||
- [x] 过期时间默认30天
|
||
- **依赖**:TASK-031
|
||
- **优先级**:P2
|
||
- **阶段**:第五批
|
||
- **涉及文件**:
|
||
- `backend/src/services/esign.service.ts`(SCENE_TEMPLATE_MAP)
|
||
- `backend/src/routes/esign.routes.ts`(过期处理)
|
||
- `backend/src/routes/portal.routes.ts`(员工端过期处理)
|
||
- `frontend/src/pages/ESign.tsx`(场景选择自动填充)
|
||
- **测试要求**:
|
||
- 手工验证:选择"劳动合同"场景 → 文件标题自动填充 → 创建记录 → 30天后自动标记过期
|
||
|
||
### TASK-037:前端管理端发起签署 UI 增强(P2)
|
||
|
||
- **目标**:管理端 ESign 页面增加场景选择、模板预览、证据链查看
|
||
- **对应需求**:电子签署逻辑审计 P2-2
|
||
- **验收标准**:
|
||
- [x] 发起签署增加场景选择(5种场景:劳动合同/离职协议/规章制度/工资条/入职文件)
|
||
- [x] 场景选择后自动填充默认文件标题
|
||
- [x] 新增签署详情页(文件内容预览 + 证据链时间线)
|
||
- [x] 签署流程说明(6步流程图)
|
||
- [x] 签署记录列表增加签署方式列
|
||
- **依赖**:TASK-031
|
||
- **优先级**:P2
|
||
- **阶段**:第五批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/ESign.tsx`(重写)
|
||
- `frontend/src/lib/api-services.ts`(esignApi 增加 detail/evidence 接口)
|
||
- **测试要求**:
|
||
- 手工验证:发起签署 → 选择场景 → 自动填充标题 → 创建 → 详情页查看文件内容和证据链
|
||
|
||
### TASK-038:前端员工端签署 UI 增强(P2)
|
||
|
||
- **目标**:员工端 MyEsign 增加验证码签署流程和文件预览
|
||
- **对应需求**:电子签署逻辑审计 P2-3
|
||
- **验收标准**:
|
||
- [x] 签署操作增加验证码确认流程
|
||
- [x] 60秒倒计时限制
|
||
- [x] 文件内容预览
|
||
- [x] 签署完成状态展示
|
||
- [x] 开发模式直接显示验证码(便于测试)
|
||
- **依赖**:TASK-032
|
||
- **优先级**:P2
|
||
- **阶段**:第五批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/portal/MyEsign.tsx`(重写)
|
||
- `frontend/src/lib/api-services.ts`(portalApi 增加 esignSendCode 接口)
|
||
- **测试要求**:
|
||
- 手工验证:员工端查看待签文件 → 点击获取验证码 → 输入验证码 → 签署完成
|
||
|
||
### TASK-039:线下手签完整流程 + 证据链(P1)
|
||
|
||
- **目标**:支持线下手签的完整登记流程,上传扫描件,记录证据链,与电子签署具有同等证据效力
|
||
- **对应需求**:线下手签支持
|
||
- **验收标准**:
|
||
- [x] ESignRecord 增加 signMethod 字段(ELECTRONIC/PAPER)
|
||
- [x] 增加线下手签专用字段:signedAt、signedLocation、witnessName、witnessPhone、scanFileUrls
|
||
- [x] 后端新增线下手签登记接口(POST /esign/paper-sign)
|
||
- [x] 后端新增扫描件上传接口(POST /esign/paper-upload,multer多文件)
|
||
- [x] 线下手签登记创建 COMPLETED 状态记录 + 证据链 + 回写合同
|
||
- [x] 管理端 ESign 页面增加"线下手签登记"按钮和 Modal
|
||
- [x] 员工端线下手签记录只读展示(含扫描件链接)
|
||
- **依赖**:无
|
||
- **优先级**:P1
|
||
- **阶段**:第五批
|
||
- **涉及文件**:
|
||
- `backend/prisma/schema.prisma`(ESignRecord 扩展7个字段)
|
||
- `backend/src/routes/esign.routes.ts`(线下手签接口)
|
||
- `frontend/src/pages/ESign.tsx`(线下手签登记 Modal)
|
||
- `frontend/src/pages/portal/MyEsign.tsx`(线下手签只读展示)
|
||
- `frontend/src/lib/api-services.ts`(uploadPaperSign/paperSign 接口)
|
||
- **DB 变更**:ESignRecord 新增 signMethod + 6个线下手签字段,`prisma db push` 已应用
|
||
- **测试要求**:
|
||
- 手工验证:HR点击"线下手签登记" → 选择员工 → 填写签署日期/地点/见证人 → 上传扫描件 → 登记 → 证据链记录 → 员工端可查看扫描件
|
||
|
||
### TASK-040:花名册操作自动创建电子签署(P1)
|
||
|
||
- **目标**:花名册关键操作(增加员工/主动离职/公司解聘)自动创建电子签署记录
|
||
- **对应需求**:花名册与电子签署联动
|
||
- **验收标准**:
|
||
- [x] 新增 esign.service.ts 提供 autoCreateEsignRecord 公共方法
|
||
- [x] 主动离职(createDraft type=RESIGNATION)自动创建离职协议签署
|
||
- [x] 公司解聘执行完成(executeTermination type=TERMINATION)自动创建离职协议签署
|
||
- [x] 自动创建失败不阻断主流程(返回 null)
|
||
- [x] 前端操作成功后提示"电子签署已自动发起"
|
||
- **依赖**:TASK-031
|
||
- **优先级**:P1
|
||
- **阶段**:第五批
|
||
- **涉及文件**:
|
||
- `backend/src/services/esign.service.ts`(新增)
|
||
- `backend/src/services/termination.service.ts`(createDraft/executeTermination 集成)
|
||
- **测试要求**:
|
||
- 手工验证:花名册主动离职 → 创建离职草稿 → 自动创建离职协议签署记录 → 员工端可见
|
||
|
||
### TASK-041:通用签署方式选择弹窗 + 花名册4项操作联动(P1)
|
||
|
||
- **目标**:花名册操作(重新入职/合同续签/薪酬变更/调岗调动)成功后弹窗选择签署方式
|
||
- **对应需求**:花名册与电子签署联动(用户选择签署方式)
|
||
- **验收标准**:
|
||
- [x] 新增 SignMethodChoice 通用组件(电子签/线下手签/稍后处理三选一)
|
||
- [x] 重新入职:操作成功后弹窗(scene=CONTRACT,劳动合同)
|
||
- [x] 合同续签:操作成功后弹窗(scene=CONTRACT,续签劳动合同)
|
||
- [x] 薪酬变更:操作成功后弹窗(scene=POLICY,薪酬调整确认书)
|
||
- [x] 调岗调动:操作成功后弹窗(scene=POLICY,调岗确认书)
|
||
- [x] 选择"电子签"→自动创建签署记录
|
||
- [x] 选择"线下手签"→跳转签署页面,预填信息
|
||
- [x] 选择"稍后处理"→跳过,可后续手动发起
|
||
- [x] ESign 页面支持 URL 参数自动打开线下手签登记
|
||
- **依赖**:TASK-039
|
||
- **优先级**:P1
|
||
- **阶段**:第五批
|
||
- **涉及文件**:
|
||
- `frontend/src/components/ui/SignMethodChoice.tsx`(新增)
|
||
- `frontend/src/pages/Roster.tsx`(4个 mutation onSuccess 集成)
|
||
- `frontend/src/pages/ESign.tsx`(URL 参数读取 + PaperSignModal 预填)
|
||
- **测试要求**:
|
||
- 手工验证:花名册薪酬变更 → 成功 → 弹窗选择"电子签" → 自动创建签署记录
|
||
- 手工验证:花名册调岗 → 成功 → 弹窗选择"线下手签" → 跳转签署页面 → 信息已预填
|
||
|
||
### TASK-042:转正弹窗显示原薪资 + 薪资变化联动签署(P1)
|
||
|
||
- **目标**:转正弹窗显示原薪资,薪资变化时自动发起薪酬调整确认书签署
|
||
- **对应需求**:转正流程与电子签署联动
|
||
- **验收标准**:
|
||
- [x] ConfirmModal 标签显示原薪资(¥xxx)
|
||
- [x] 转正薪资默认填入原薪资
|
||
- [x] 薪资变化时提示"将发起薪酬调整确认书签署"
|
||
- [x] 转正成功后薪资有变化时弹出签署方式选择
|
||
- [x] 签署文件标题为"转正薪酬调整确认书"
|
||
- [x] 备注记录薪资变化:¥原薪资 → ¥新薪资
|
||
- [x] 薪资未变化时仅显示"转正已提交",不弹窗
|
||
- **依赖**:TASK-041
|
||
- **优先级**:P1
|
||
- **阶段**:第五批
|
||
- **涉及文件**:
|
||
- `frontend/src/pages/roster/modals.tsx`(ConfirmModal 增强)
|
||
- `frontend/src/pages/Roster.tsx`(confirmMutation onSuccess 联动)
|
||
- **测试要求**:
|
||
- 手工验证:试用期薪资 ¥8000 → 转正填写 ¥10000 → 提示将发起签署 → 转正成功 → 弹窗选择签署方式
|
||
- 手工验证:试用期薪资 ¥8000 → 转正不修改 → 提交 → 仅显示"转正已提交"
|
||
|
||
---
|
||
|
||
## 任务依赖关系图
|
||
|
||
```
|
||
第一批(P0,无依赖):
|
||
TASK-001(草稿保存)─┬─→ TASK-002(补偿金合计)─┬─→ TASK-003(驳回更新)
|
||
│ ├─→ TASK-004(违法解除风险)
|
||
│ ├─→ TASK-009(补偿月数)→ TASK-010(计算基数)
|
||
│ └─→ TASK-006(补偿金批次)
|
||
TASK-005(合同日期校验)─→ TASK-013(续签日期推导)
|
||
|
||
第二批(P1):
|
||
TASK-007(社保联动) 独立
|
||
TASK-008(合规软阻断)─→ TASK-011(交接软阻断)
|
||
TASK-012(解聘入口) 独立
|
||
TASK-014(年龄校验)─→ TASK-022(证件号码)
|
||
TASK-015(入职日期联动) 独立
|
||
TASK-016(转正入口)─┬─→ TASK-017(薪资回写)
|
||
└─→ TASK-026(批量转正)
|
||
TASK-018(合同选择) 独立
|
||
TASK-019(三期性别) 独立
|
||
|
||
第三批(P2):
|
||
TASK-020(用工关系文案) 独立
|
||
TASK-021(年假折算)← TASK-002
|
||
TASK-023(手机号查重) 独立
|
||
TASK-024(开具证明入口)─→ TASK-027(批量证明)
|
||
TASK-025(续签入口)← TASK-013, TASK-018
|
||
TASK-028(去掉用工办理)← TASK-016, TASK-018, TASK-024, TASK-025
|
||
|
||
第四批(P3):
|
||
TASK-029(组织架构+审批流) 独立
|
||
TASK-030(客服工作台) 独立
|
||
|
||
第五批(电子签署,2026-08-16 新增):
|
||
TASK-031(后端路由重写+模板渲染)─┬─→ TASK-032(验证码确认)─→ TASK-033(证据链体系)
|
||
├─→ TASK-035(组织开关校验)
|
||
├─→ TASK-036(scene模板+过期处理)─→ TASK-037(管理端UI)
|
||
└─→ TASK-040(花名册自动创建)
|
||
TASK-032 ─→ TASK-034(回写合同)─→ TASK-038(员工端UI)
|
||
TASK-039(线下手签)─→ TASK-041(签署方式选择弹窗)─→ TASK-042(转正联动)
|
||
```
|
||
|
||
---
|
||
|
||
## 验收检查清单
|
||
|
||
### 每个任务完成后必做
|
||
- [x] 代码实现完成,lint 通过
|
||
- [x] 涉及前端:手工验证通过
|
||
- [x] 涉及后端:API 测试通过
|
||
- [x] 涉及 DB 变更:migration 已创建,回滚方案已准备
|
||
- [x] `run.md` 如有命令变化已同步
|
||
- [x] 本文档对应 TASK 已标记 `[x]`
|
||
|
||
### 批次完成后必做
|
||
- [x] 该批次所有 TASK 标记 `[x]`
|
||
- [x] 前端 build 通过:`cd frontend && npm run build`
|
||
- [x] 后端编译通过:`cd backend && npx tsc --noEmit`
|
||
- [x] 更新 `20260815-优化.md` 中对应问题的状态
|
||
- [x] 简洁汇报结果、风险和下一步
|
||
|
||
### 全部完成后必做
|
||
- [x] 全部 30 个 TASK 标记 `[x]`
|
||
- [x] 全域搜索确认无遗漏("身份证号"、"劳动合同"等)
|
||
- [x] DB migration 全部已应用
|
||
- [x] 前后端 build 均通过
|
||
- [x] 更新 `run.md`(如有新增模块/路由/端口)
|
||
- [x] 更新 `HelpModal.tsx` 帮助文案
|
||
- [x] Git commit(按批次提交,前缀 `feat/fix/ux/refactor`)
|
||
|
||
---
|
||
|
||
## 风险与注意事项
|
||
|
||
1. **DB 变更风险**:TASK-007/020/022/029/030 涉及 schema 变更,需先备份 DB,migration 需含回滚方案。
|
||
2. **兼容性风险**:TASK-022(证件号码)字段名 `idCardNumber` 保持不变,仅改 label,避免历史数据丢失。
|
||
3. **依赖链风险**:TASK-028(去掉用工办理)依赖 4 个前置任务,不可提前执行。
|
||
4. **文案替换风险**:TASK-020(用工关系)需区分法定术语和面向用户文案,法律文书模板不可改。
|
||
5. **审批流复杂度**:TASK-029 是新模块,建议先做 MVP(部门树+直属上级审批),再逐步扩展。
|
||
6. **客服端复杂度**:TASK-030 是新模块,建议先做工单+数据穿透,再做会话和 AI。
|
||
7. **历史脏数据**:TASK-005(合同日期倒置)、TASK-019(男职工三期)可能存在历史脏数据,提供查询列表但不自动修复。
|
||
8. **电子签署法律效力**:TASK-031~038 的电子签署证据链需配合易签宝等第三方CA机构才能生成具有完全法律效力的电子签名,当前系统记录的证据链(IP/UA/时间戳/验证码)可作为初步举证材料。
|
||
9. **线下手签扫描件存储**:TASK-039 的扫描件存储在服务器本地 `uploads/paper-sign/` 目录,生产环境建议配置对象存储(OSS/S3)并定期备份。
|
||
10. **验证码发送通道**:TASK-032 的验证码当前为开发模式(直接返回),生产环境需对接短信服务商(阿里云/腾讯云短信)。
|
||
11. **花名册联动重复创建**:TASK-040/041 已修复 POST /contracts 与前端 ContractInfo 重复创建签署记录的问题,后端不再自动创建,由前端根据 signMethod 决定。
|