# 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-15 更新) | 批次 | 优先级 | 任务数 | 完成数 | 状态 | |------|--------|--------|--------|------| | 第一批 | P0 紧急 | 6 条 | 6 条 | ✅ 全部完成 | | 第二批 | P1 高 | 14 条 | 14 条 | ✅ 全部完成 | | 第三批 | P2 中 | 9 条 | 9 条 | ✅ 全部完成 | | 第四批 | P3 规划 | 2 项 | 2 项 | ✅ 全部完成 | | **合计** | | **31 条** | **31 条** | **✅ 100% 完成** | > 编译状态:前后端 TypeScript 编译均 0 错误。 > 数据库:Prisma schema 已同步(`prisma db push`),新增 8 个模型 + 2 个字段 + 1 个枚举值。 --- ## 批次总览 | 批次 | 优先级 | 任务数 | 目标 | 依赖 | |------|--------|--------|------|------| | 第一批 | P0 紧急 | 6 条 | 数据丢失/业务正确性/合规风险修复 | 无 | | 第二批 | P1 高 | 14 条 | 流程阻塞/合规校验缺失修复 | 第一批完成 | | 第三批 | P2 中 | 9 条 | 体验优化/功能增强 | 第二批完成(26 依赖 18/20/21/22/23) | | 第四批 | P3 规划 | 2 项 | 组织架构+审批流 / 客服工作台增强 | 第三批完成 | --- ## 第一批: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 快速流程 - **依赖**:无 - **优先级**: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] 生成后支持下载/打印 - **依赖**:无 - **优先级**: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` 自动预填 - **依赖**: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 的转正逻辑 - **依赖**: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] 后端新增批量生成接口 - **依赖**: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 辅助问答 → 操作日志记录 --- ## 任务依赖关系图 ``` 第一批(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(客服工作台) 独立 ``` --- ## 验收检查清单 ### 每个任务完成后必做 - [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(男职工三期)可能存在历史脏数据,提供查询列表但不自动修复。