From 787897e6d3cc035feed36218084eea6756b5ff0e Mon Sep 17 00:00:00 2001 From: selfrelease Date: Sat, 1 Aug 2026 19:05:20 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=91=98=E5=B7=A5?= =?UTF-8?q?=E7=AB=AF=E7=A6=BB=E8=81=8C=E7=94=B3=E8=AF=B7=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E6=97=B6=E7=BC=BA=E5=B0=91checklist=E5=92=8Ctype=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E5=AF=BC=E8=87=B4=E5=86=85=E9=83=A8=E9=94=99=E8=AF=AF?= =?UTF-8?q?;=20=E6=96=B0=E5=A2=9EE2E=E6=B5=8B=E8=AF=95=E5=9C=BA=E6=99=AF?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/routes/portal.routes.ts | 3 + docs/test-scenarios-e2e.md | 707 ++++++++++ docs/test-scenarios.md | 1917 +++++++++++++++++++++++++++ 3 files changed, 2627 insertions(+) create mode 100644 docs/test-scenarios-e2e.md create mode 100644 docs/test-scenarios.md diff --git a/backend/src/routes/portal.routes.ts b/backend/src/routes/portal.routes.ts index 87e6249..ada2714 100644 --- a/backend/src/routes/portal.routes.ts +++ b/backend/src/routes/portal.routes.ts @@ -792,9 +792,12 @@ router.post('/resignation/submit', portalAuth, async (req: any, res, next) => { const record = await (prisma as any).terminationRecord.create({ data: { employeeId, orgId, + type: 'RESIGNATION', reason: 'RESIGNATION', + resignationReason: reason, terminationDate: new Date(expectedDate), status: 'PENDING_APPROVAL', + checklist: [], remark: `员工自主申请:${reason}${remark ? ';备注:' + remark : ''}`, createdBy: employeeId, }, diff --git a/docs/test-scenarios-e2e.md b/docs/test-scenarios-e2e.md new file mode 100644 index 0000000..d8871e3 --- /dev/null +++ b/docs/test-scenarios-e2e.md @@ -0,0 +1,707 @@ +# TurboHR 企业全流程端到端测试场景 + +> **场景背景**:模拟一家新企业「上海明远制造有限公司」从零开始使用 TurboHR 的完整过程。 +> 包括:平台创建租户 → 企业管理员首次登录 → 企业配置 → 线下数据导入 → 日常操作 → 月度闭环 → 员工端使用 +> **测试环境**: https://on.hr8ai.top +> **日期范围**: 2026-08-01 ~ 2026-08-31 + +--- + +## 角色与账号 + +| 角色 | 手机号 | 密码 | 说明 | +|------|--------|------|------| +| 平台超管 | `superadmin` | (平台管理端密码) | SUPER_ADMIN,创建租户 | +| 企业管理员 | `13900005555` | `Init123456` | 新建租户的管理员 | +| HR 李萍 | `13900006666` | `Hr123456` | 企业内新增的 HR 用户 | +| 员工 张伟 | `13900007777` | (初始密码/验证码) | 生产车间,通过导入创建 | +| 员工 王芳 | `13900007888` | (初始密码/验证码) | 行政部,通过导入创建 | + +--- + +## 阶段一:租户创建与初始化 + +### E2E-001 平台管理员创建新企业 + +| 项目 | 内容 | +|------|------| +| **角色** | 平台超管(SUPER_ADMIN) | +| **Input** | POST `/api/v1/auth/platform-login` `{ phone: "superadmin", password: "xxx" }` | +| **Process** | 1. 平台超管登录 → 2. 进入 `/platform/orgs` → 3. 点击「新建组织」→ 4. 填写企业信息并提交 | +| **Input(创建组织)** | POST `/api/v1/platform/orgs` `{ name: "上海明远制造有限公司", contactName: "刘明远", contactPhone: "13900005555", adminName: "刘明远", adminPhone: "13900005555", adminPassword: "Init123456", city: "上海", plan: "PRO", maxEmployees: 50, payrollFrequency: 1 }` | +| **Output** | HTTP 201,`{ success: true, data: { id: "org-new-id", name: "上海明远制造有限公司", plan: "PRO", maxEmployees: 50 } }` | +| **验证** | 组织列表中出现「上海明远制造有限公司」,套餐 PRO,员工上限 50 | + +### E2E-002 企业管理员首次登录 + +| 项目 | 内容 | +|------|------| +| **角色** | 企业管理员(刘明远) | +| **Input** | POST `/api/v1/auth/login` `{ phone: "13900005555", password: "Init123456" }` | +| **Process** | 1. 访问登录页 → 2. 输入手机号和初始密码 → 3. 点击登录 | +| **Output** | HTTP 200,`{ success: true, data: { user: { id: "u-new", name: "刘明远", role: "ADMIN", phone: "13900005555" }, accessToken: "jwt-xxx", refreshToken: "jwt-refresh-xxx" } }` | +| **验证** | 跳转至 `/dashboard`,仪表盘显示空数据(0 员工、0 待办、0 风险) | + +### E2E-003 完善企业信息 + +| 项目 | 内容 | +|------|------| +| **角色** | 企业管理员 | +| **Input** | PUT `/api/v1/settings/org` `{ name: "上海明远制造有限公司", contactName: "刘明远", contactPhone: "13900005555", city: "上海", payrollFrequency: 1, retirementReminderEnabled: true }` | +| **Process** | 进入 `/settings` → 企业信息 → 修改/完善信息 → 保存 | +| **Output** | HTTP 200,`{ success: true }` | +| **验证** | 设置页显示更新后的企业名称「上海明远制造有限公司」,城市「上海」,发薪次数 1 次/月 | + +### E2E-004 添加 HR 用户 + +| 项目 | 内容 | +|------|------| +| **角色** | 企业管理员 | +| **Input** | POST `/api/v1/settings/users` `{ name: "李萍", phone: "13900006666", password: "Hr123456", role: "HR" }` | +| **Process** | 进入 `/settings` → 用户管理 → 点击「添加用户」→ 填写 HR 信息 → 保存 | +| **Output** | HTTP 201,`{ success: true, data: { id: "u-hr", name: "李萍", phone: "13900006666", role: "HR" } }` | +| **验证** | 用户列表显示 2 人:刘明远(ADMIN)、李萍(HR) | + +### E2E-005 HR 用户登录验证 + +| 项目 | 内容 | +|------|------| +| **角色** | HR(李萍) | +| **Input** | POST `/api/v1/auth/login` `{ phone: "13900006666", password: "Hr123456" }` | +| **Process** | 退出管理员账号 → 用 HR 账号登录 | +| **Output** | HTTP 200,`{ success: true, data: { user: { name: "李萍", role: "HR" } } }` | +| **验证** | 成功登录,跳转至 `/dashboard`,HR 角色可访问花名册、考勤、薪酬等模块 | + +--- + +## 阶段二:线下数据导入 + +### E2E-006 批量导入员工花名册 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | `FormData { file: 明远制造_花名册.xlsx }` | +| **文件内容** | Excel 包含以下列:姓名、性别、身份证号、手机号、部门、岗位、入职日期、月薪、合同类型、合同开始、合同结束 | +| **示例数据** | 张伟, 男, 310101199001011234, 13900007777, 生产车间, 操作工, 2022-03-01, 8000, 固定期限, 2022-03-01, 2025-02-28 | +| | 王芳, 女, 310102199505052345, 13900007888, 行政部, 行政专员, 2023-06-01, 9000, 固定期限, 2023-06-01, 2026-05-31 | +| | 陈强, 男, 310103199207073456, 13900007999, 生产车间, 技术员, 2021-01-01, 10000, 无固定期限, 2021-01-01, | +| | 赵敏, 女, 310104199808084567, 13900008000, 质检部, 质检员, 2024-01-01, 8500, 固定期限, 2024-01-01, 2027-12-31 | +| **Process** | 进入 `/roster` → 点击「批量导入」→ 上传 Excel 文件 → 确认导入 | +| **Output** | HTTP 200,`{ success: true, data: { total: 4, success: 4, failed: 0, errors: [] } }` | +| **验证** | 花名册列表显示 4 名员工,部门分布:生产车间 2 人、行政部 1 人、质检部 1 人 | + +### E2E-007 验证导入数据完整性 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | GET `/api/v1/employees?page=1&pageSize=10` | +| **Process** | 进入花名册 → 逐条检查员工信息 | +| **Output** | `{ data: [{ id: "e1", name: "张伟", gender: "男", phone: "13900007777", department: "生产车间", position: "操作工", hireDate: "2022-03-01", monthlySalary: 8000, contractType: "FIXED", contractStart: "2022-03-01", contractEnd: "2025-02-28", status: "ACTIVE" }, { id: "e2", name: "王芳", ... }, { id: "e3", name: "陈强", ... }, { id: "e4", name: "赵敏", ... }], pagination: { total: 4 } }` | +| **验证** | 4 名员工信息与导入文件一致,状态均为 ACTIVE | + +### E2E-008 手动补充员工档案详情 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | PUT `/api/v1/employees/e1` `{ emergencyContact: "张父", emergencyPhone: "13800001111", bank: "工商银行", account: "6222020100011234", address: "上海市浦东新区测试路100号", education: "高中", nativePlace: "安徽合肥" }` | +| **Process** | 花名册 → 点击「张伟」→ 员工详情 → 编辑档案 → 补充紧急联系人、银行账户、地址等 → 保存 | +| **Output** | HTTP 200,`{ success: true }` | +| **验证** | 员工详情页显示完整的档案信息 | + +### E2E-009 导入考勤数据 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | `FormData { file: 明远制造_考勤_2026-07.xlsx, month: "2026-07" }` | +| **文件内容** | Excel 包含:员工姓名、日期、上班打卡、下班打卡、状态 | +| **示例数据** | 张伟, 2026-07-01, 08:50, 18:10, 正常; 张伟, 2026-07-02, 09:05, 18:00, 迟到; 王芳, 2026-07-01, 08:45, 18:30, 正常; ... | +| **Process** | 进入 `/attendance` → 点击「导入考勤」→ 选择月份 2026-07 → 上传文件 → 确认 | +| **Output** | HTTP 200,`{ success: true, data: { total: 88, success: 86, failed: 2, errors: [{ row: 45, message: "2026-07-15 为周末,非排班日" }, { row: 88, message: "下班打卡时间早于上班打卡" }] } }` | +| **验证** | 考勤列表显示 2026-07 月数据,统计:张伟迟到 1 次,王芳全勤 | + +### E2E-010 配置考勤班次 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/attendance/shifts` `{ name: "白班", startTime: "08:00", endTime: "17:00", restMinutes: 60, color: "#4CAF50" }` | +| **Process** | 进入 `/attendance` → 班次管理 → 新建班次 → 填写信息 → 保存 | +| **Output** | HTTP 201,`{ success: true, data: { id: "shift1", name: "白班", startTime: "08:00", endTime: "17:00" } }` | +| **验证** | 班次列表显示「白班」 | + +### E2E-011 分配班次 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/attendance/shift-assignments` `{ employeeId: "e1", shiftId: "shift1", startDate: "2026-08-01", endDate: "2026-08-31" }` | +| **Process** | 考勤 → 排班 → 选择员工张伟 → 分配白班 → 保存 | +| **Output** | HTTP 201,`{ success: true }` | +| **验证** | 排班表显示张伟 8 月全月白班 | + +--- + +## 阶段三:社保与薪酬配置 + +### E2E-012 配置社保公积金 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/social/config` `{ city: "上海", effectiveFrom: "2026-07-01", type: "social", baseMin: 7384, baseMax: 36921, pension: { emp: 8, corp: 16 }, medical: { emp: 2, corp: 10 }, unemployment: { emp: 0.5, corp: 0.5 }, injury: { emp: 0, corp: 0.26 }, maternity: { emp: 0, corp: 1 } }` | +| **Process** | 进入 `/social-insurance` → 社保配置 → 新建配置 → 选择城市「上海」→ 填写基数和比例 → 保存 | +| **Output** | HTTP 201,`{ success: true, data: { id: "sc1", city: "上海", isCurrent: true } }` | +| **验证** | 社保配置页显示上海当前生效配置,下限 7384,上限 36921 | + +### E2E-013 配置公积金 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/social/config` `{ city: "上海", effectiveFrom: "2026-07-01", type: "housing", baseMin: 2800, baseMax: 36921, empRate: 7, corpRate: 7, supplementRate: 0 }` | +| **Process** | 社保公积金页 → 公积金配置 tab → 新建 → 填写 → 保存 | +| **Output** | HTTP 201,`{ success: true, data: { id: "hc1", city: "上海", type: "housing", isCurrent: true } }` | +| **验证** | 公积金配置显示上海当前配置,个人 7%,企业 7% | + +### E2E-014 创建薪酬模板 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/payroll/templates` `{ name: "明远制造标准模板", items: [{ name: "基本工资", type: "INCOME", formula: "monthlySalary", taxable: true }, { name: "岗位津贴", type: "INCOME", formula: "500", taxable: true }, { name: "交通补贴", type: "INCOME", formula: "200", taxable: false }, { name: "社保个人", type: "DEDUCT", formula: "socialEmp", taxable: false }, { name: "公积金个人", type: "DEDUCT", formula: "housingEmp", taxable: false }, { name: "个人所得税", type: "DEDUCT", formula: "tax", taxable: false }] }` | +| **Process** | 进入 `/money` → 薪酬模板 → 新建模板 → 添加薪资项 → 保存 | +| **Output** | HTTP 201,`{ success: true, data: { id: "pt1", name: "明远制造标准模板" } }` | +| **验证** | 模板列表显示「明远制造标准模板」,包含 6 个薪资项 | + +--- + +## 阶段四:制度发布与员工端启用 + +### E2E-015 创建考勤管理制度 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/policies` `{ title: "上海明远制造考勤管理制度", category: "考勤", content: "第一章 总则\n第一条 为规范公司考勤管理...\n第二章 工作时间\n第二条 工作时间为每日8:00-17:00,午休1小时...\n第三章 请假\n第三条 请假需提前1天通过系统提交..." }` | +| **Process** | 进入 `/policies` → 新建制度 → 填写标题、分类、正文 → 保存草稿 | +| **Output** | HTTP 201,`{ success: true, data: { id: "p1", title: "上海明远制造考勤管理制度", status: "DRAFT", currentStep: 1 } }` | +| **验证** | 制度列表显示草稿状态,当前步骤 1/4(起草) | + +### E2E-016 推进民主程序 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | 依次调用:POST `/api/v1/policies/p1/advance-step` `{ step: 2, note: "已组织全体职工讨论" }` → POST `/api/v1/policies/p1/advance-step` `{ step: 3, note: "已与工会代表协商一致" }` → POST `/api/v1/policies/p1/advance-step` `{ step: 4, note: "已通过企业微信公示5个工作日" }` | +| **Process** | 制度详情 → 依次完成「讨论」「协商」「公示」三个步骤,每步添加备注 → 发布 | +| **Output** | 每步返回 HTTP 200 `{ success: true }`,最终 currentStep = 4,status = `PUBLISHED` | +| **验证** | 制度状态变为「已发布」,4 个步骤全部完成 | + +### E2E-017 生成员工端自动登录令牌 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/portal/auto-login-token` `{ employeeId: "e1" }` | +| **Process** | 花名册 → 点击「张伟」→ 更多操作 → 「生成员工端登录链接」 | +| **Output** | HTTP 200,`{ success: true, data: { token: "auto-login-xxx-e1", url: "/portal/auto-login?token=auto-login-xxx-e1" } }` | +| **验证** | 生成可分享的员工端登录链接 | + +### E2E-018 员工首次登录员工端 + +| 项目 | 内容 | +|------|------| +| **角色** | 员工(张伟) | +| **Input** | GET `/api/v1/portal/auto-login?token=auto-login-xxx-e1` | +| **Process** | 员工通过手机浏览器打开链接 → 自动登录 | +| **Output** | HTTP 200,`{ success: true, data: { employee: { id: "e1", name: "张伟", department: "生产车间" }, token: "portal-token-xxx" } }` | +| **验证** | 跳转至 `/portal/home`,首页显示张伟的个人信息概览 | + +### E2E-019 员工查看并确认制度 + +| 项目 | 内容 | +|------|------| +| **角色** | 员工(张伟) | +| **Input** | 1. GET `/api/v1/portal/policies` → 2. GET `/api/v1/portal/policies/p1` → 3. POST `/api/v1/portal/policies/p1/read` | +| **Process** | 员工端 → 制度 tab → 查看考勤管理制度 → 阅读完毕 → 点击「已阅读」 | +| **Output** | 第一步:`[{ id: "p1", title: "上海明远制造考勤管理制度", read: false }]`;第三步:HTTP 200 `{ success: true }` | +| **验证** | 制度列表中该制度标记为已读,管理端阅读统计显示张伟已读 | + +### E2E-020 员工查看合同 + +| 项目 | 内容 | +|------|------| +| **角色** | 员工(张伟) | +| **Input** | GET `/api/v1/portal/contract` | +| **Process** | 员工端 → 合同 tab → 查看合同信息 | +| **Output** | `{ contract: { id: "c1", type: "FIXED", startDate: "2022-03-01", endDate: "2025-02-28", status: "EXPIRED", monthlySalary: 8000 } }` | +| **验证** | 显示合同已过期(2025-02-28 到期),状态 EXPIRED | + +--- + +## 阶段五:日常操作(8月) + +### E2E-021 仪表盘风险检查 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | GET `/api/v1/dashboard` | +| **Process** | 登录后查看仪表盘 | +| **Output** | `{ greeting: "上午好!今天有 2 件事需要处理", stats: { employeeCount: 4, highRiskCount: 1, todoCount: 2 }, todos: [{ id: "r1", type: "CONTRACT", priority: "URGENT", title: "张伟的合同已过期,请尽快续签", employeeName: "张伟", deadline: "2026-08-15" }, { id: "r2", type: "CONTRACT", priority: "MEDIUM", title: "王芳的合同将于2027-05-31到期", employeeName: "王芳" }] }` | +| **验证** | 仪表盘显示 4 名员工,1 条紧急待办(张伟合同过期),1 条中等待办(王芳合同即将到期) | + +### E2E-022 处理合同续签待办 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | 1. PATCH `/api/v1/dashboard/todos/r1/resolve` → 2. PUT `/api/v1/employees/e1` `{ contractType: "FIXED", contractStart: "2025-03-01", contractEnd: "2028-02-28", monthlySalary: 9000 }` | +| **Process** | 1. 仪表盘 → 点击张伟的待办 → 标记已处理 → 2. 进入花名册 → 张伟详情 → 编辑合同信息 → 续签 3 年,月薪调整为 9000 → 保存 | +| **Output** | 第一步:HTTP 200 `{ success: true }`;第二步:HTTP 200 `{ success: true }` | +| **验证** | 待办消失,张伟合同状态更新为正常(2025-03-01 至 2028-02-28),月薪 9000 | + +### E2E-023 录入考勤(8月每日) + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/attendance/daily` `{ employeeId: "e1", date: "2026-08-01", checkIn: "07:55", checkOut: "17:05", shiftId: "shift1", status: "NORMAL", overtime: 0 }` | +| **Process** | 考勤 → 每日考勤 → 逐日录入或批量导入 8 月考勤数据 | +| **Output** | HTTP 201,`{ success: true }` | +| **验证** | 考勤月报显示张伟 8 月出勤 22 天,迟到 0 次 | + +### E2E-024 请假审批 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/attendance/leave` `{ employeeId: "e2", type: "事假", startDate: "2026-08-10", endDate: "2026-08-12", reason: "家中有事", days: 3 }` | +| **Process** | 考勤 → 请假记录 → 新建请假 → 选择王芳 → 事假 3 天 → 提交 | +| **Output** | HTTP 201,`{ success: true, data: { id: "lv1", status: "APPROVED" } }` | +| **验证** | 请假记录显示王芳 8 月 10-12 日事假,考勤统计扣除 3 天出勤 | + +### E2E-025 发布考勤月报 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/attendance/monthly-report/publish` `{ month: "2026-08" }` | +| **Process** | 考勤 → 月度报表 → 选择 2026-08 → 确认数据无误 → 点击「发布」 | +| **Output** | HTTP 200,`{ success: true }` | +| **验证** | 考勤月报状态变为「已发布」,员工端可查看当月考勤 | + +--- + +## 阶段六:月度薪酬闭环(8月发薪) + +### E2E-026 创建发薪批次 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/payroll/batches` `{ month: "2026-08", templateId: "pt1", name: "2026年8月工资", payDate: "2026-09-10" }` | +| **Process** | 进入 `/money` → 发薪批次 → 新建批次 → 选择月份 8 月 → 选择模板「明远制造标准模板」→ 设置发薪日 → 保存 | +| **Output** | HTTP 201,`{ success: true, data: { id: "b1", month: "2026-08", status: "DRAFT", employeeCount: 4 } }` | +| **验证** | 批次列表显示 8 月发薪批次,状态 DRAFT,包含 4 名员工 | + +### E2E-027 计算工资 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/payroll/batches/b1/calculate` | +| **Process** | 发薪批次 → 选择 8 月批次 → 点击「计算」→ 系统自动计算所有员工工资 | +| **Output** | HTTP 200,`{ success: true, data: { results: [{ employeeId: "e1", employeeName: "张伟", baseSalary: 9000, allowance: 500, transport: 200, grossPay: 9700, socialEmp: 759.36, housingEmp: 630, tax: 421.32, netPay: 7889.32 }, { employeeId: "e2", employeeName: "王芳", baseSalary: 9000, allowance: 500, transport: 200, grossPay: 9700, socialEmp: 759.36, housingEmp: 630, tax: 421.32, netPay: 7889.32, leaveDeduction: 966.67, adjustedNetPay: 6922.65 }, { employeeId: "e3", employeeName: "陈强", baseSalary: 10000, allowance: 500, transport: 200, grossPay: 10700, socialEmp: 830.72, housingEmp: 700, tax: 533.28, netPay: 8636.00 }, { employeeId: "e4", employeeName: "赵敏", baseSalary: 8500, allowance: 500, transport: 200, grossPay: 9200, socialEmp: 712.64, housingEmp: 595, tax: 371.52, netPay: 7520.84 }] } }` | +| **验证** | 4 名员工工资计算完成,王芳因事假 3 天扣除 966.67 元,个税按累计预扣法计算 | + +### E2E-028 个税试算 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/payroll/tax-trial` `{ employeeId: "e1", month: "2026-08", grossPay: 9700, socialEmp: 759.36, housingEmp: 630, specialDeduction: 0, accumulatedIncome: 67900, accumulatedTaxPaid: 2946.24 }` | +| **Process** | 薪酬 → 个税试算 → 选择张伟 → 输入累计数据 → 计算 | +| **Output** | `{ tax: 421.32, accumulatedIncome: 77600, accumulatedTax: 3367.56, accumulatedTaxPaid: 2946.24, thisMonthTax: 421.32 }` | +| **验证** | 个税计算结果与发薪批次中一致 | + +### E2E-029 提交审批 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/payroll/batches/b1/submit` | +| **Process** | 发薪批次 → 确认数据 → 点击「提交审批」 | +| **Output** | HTTP 200,`{ success: true }`。状态变为 `PENDING_APPROVAL` | +| **验证** | 批次状态变为待审批 | + +### E2E-030 管理员审批发薪 + +| 项目 | 内容 | +|------|------| +| **角色** | 企业管理员(刘明远) | +| **Input** | POST `/api/v1/payroll/batches/b1/approve` `{ comment: "核对无误,同意发放" }` | +| **Process** | 管理员登录 → 薪酬 → 发薪批次 → 查看 8 月批次 → 审批通过 | +| **Output** | HTTP 200,`{ success: true }`。状态变为 `APPROVED` | +| **验证** | 批次状态变为已审批,工资条生成 | + +### E2E-031 员工查看工资条 + +| 项目 | 内容 | +|------|------| +| **角色** | 员工(张伟) | +| **Input** | GET `/api/v1/portal/payslip?month=2026-08` | +| **Process** | 员工端 → 工资条 tab → 选择 2026-08 | +| **Output** | `{ id: "ps1", month: "2026-08", baseSalary: 9000, allowance: 500, transport: 200, grossPay: 9700, socialEmp: 759.36, housingEmp: 630, tax: 421.32, netPay: 7889.32, confirmed: false }` | +| **验证** | 工资条显示完整明细,实发 7889.32 元,状态未确认 | + +### E2E-032 员工确认工资条 + +| 项目 | 内容 | +|------|------| +| **角色** | 员工(张伟) | +| **Input** | POST `/api/v1/portal/payslip/ps1/confirm` | +| **Process** | 员工端 → 工资条 → 点击「确认无误」 | +| **Output** | HTTP 200,`{ success: true }` | +| **验证** | 工资条状态变为 CONFIRMED | + +--- + +## 阶段七:社保月度办理 + +### E2E-033 查看社保月度变动 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | GET `/api/v1/social/monthly-changes?month=2026-08` | +| **Process** | 进入 `/social-insurance` → 月度办理 → 选择 2026-08 | +| **Output** | `{ additions: [{ employeeId: "e1", employeeName: "张伟", reason: "已参保", base: 9000 }, { employeeId: "e2", employeeName: "王芳", reason: "已参保", base: 9000 }, { employeeId: "e3", employeeName: "陈强", reason: "已参保", base: 10000 }, { employeeId: "e4", employeeName: "赵敏", reason: "已参保", base: 8500 }], reductions: [], current: [...] }` | +| **验证** | 4 名员工均在参保列表中,无减员 | + +### E2E-034 完成社保月度办理 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/social/monthly-process/complete` `{ month: "2026-08", type: "social" }` | +| **Process** | 社保页 → 月度办理 → 确认增减员无误 → 点击「完成社保办理」 | +| **Output** | HTTP 200,`{ success: true }` | +| **验证** | 社保办理状态变为已完成 | + +### E2E-035 完成公积金月度办理 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/social/monthly-process/complete` `{ month: "2026-08", type: "housing" }` | +| **Process** | 社保页 → 公积金 tab → 月度办理 → 点击「完成公积金办理」 | +| **Output** | HTTP 200,`{ success: true }` | +| **验证** | 公积金办理状态变为已完成 | + +--- + +## 阶段八:风险检查与合规 + +### E2E-036 用工体检诊断 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | GET `/api/v1/dashboard/health-check` | +| **Process** | 进入 `/tools/health-check` → 点击「开始诊断」 | +| **Output** | `{ year: 2026, totalScore: 90, level: "healthy", dimensions: { contract: 100, salary_social: 100, attendance: 100, policy: 80, termination: 100, evidence: 60 }, summary: "整体用工合规状况良好,建议完善证据链管理" }` | +| **验证** | 6 维度评分显示,总分 90,等级 healthy,证据链维度较低(60 分) | + +### E2E-037 保存体检诊断 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/dashboard/health-check/save` | +| **Process** | 诊断结果页 → 点击「保存诊断报告」 | +| **Output** | HTTP 200,`{ success: true, data: { id: "hc-new", year: 2026, totalScore: 90 } }` | +| **验证** | 诊断历史中出现 2026 年记录 | + +### E2E-038 AI 顾问咨询 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/ai/consultation` `{ type: "CHAT", question: "我们公司有员工合同过期了未续签,有什么法律风险?" }` | +| **Process** | 进入 `/ai-assistant` → 输入问题 → 发送 | +| **Output** | `{ conversationId: "conv-e2e", answer: "根据《劳动合同法》第十条和第八十二条,已建立劳动关系未同时订立书面劳动合同的,应当自用工之日起一个月内订立。超过一个月未续签的,应当向劳动者每月支付二倍工资。建议您尽快为合同过期的员工续签劳动合同...", confidence: 0.92, sources: [{ title: "劳动合同法第十条", url: "" }, { title: "劳动合同法第八十二条", url: "" }] }` | +| **验证** | AI 回答包含法律依据和操作建议,置信度 > 0.9 | + +--- + +## 阶段九:新员工入职流程 + +### E2E-039 创建入职工作流程 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/work-processes` `{ type: "ONBOARDING", title: "8月新员工入职-孙磊", data: { name: "孙磊", phone: "13900008888", department: "生产车间", position: "操作工", hireDate: "2026-08-15", salary: 8000, contractType: "FIXED", contractEnd: "2029-08-14" } }` | +| **Process** | 进入 `/work-process` → 新建 → 选择类型「入职」→ 填写新员工信息 → 保存 | +| **Output** | HTTP 201,`{ success: true, data: { id: "wp1", title: "8月新员工入职-孙磊", type: "ONBOARDING", status: "DRAFT" } }` | +| **验证** | 工作流程列表显示新入职流程 | + +### E2E-040 生成入职链接并发送 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/portal/auto-login-token` `{ employeeId: "e-new" }`(系统自动创建员工记录后) | +| **Process** | 工作流程详情 → 点击「生成入职链接」→ 将链接发送给新员工 | +| **Output** | `{ success: true, data: { token: "onboarding-token-sunlei", url: "/portal/onboarding?token=onboarding-token-sunlei" } }` | +| **验证** | 生成入职链接 | + +### E2E-041 新员工填写入职信息 + +| 项目 | 内容 | +|------|------| +| **角色** | 新员工(孙磊) | +| **Input** | 1. GET `/api/v1/portal/onboarding/onboarding-token-sunlei` → 2. POST `/api/v1/portal/onboarding` `{ token: "onboarding-token-sunlei", name: "孙磊", gender: "男", idCard: "310105200001015678", phone: "13900008888", bank: "建设银行", account: "6227000100025678", emergencyContact: "孙母", emergencyPhone: "13800002222", address: "上海市闵行区测试路200号" }` | +| **Process** | 新员工打开链接 → 查看入职须知 → 填写个人信息 → 提交 | +| **Output** | 第一步:`{ orgName: "上海明远制造有限公司", position: "操作工", expectedHireDate: "2026-08-15" }`;第二步:HTTP 200 `{ success: true, message: "入职信息提交成功" }` | +| **验证** | 入职信息提交成功 | + +### E2E-042 新员工上传入职文件 + +| 项目 | 内容 | +|------|------| +| **角色** | 新员工(孙磊) | +| **Input** | `FormData { file: 身份证正面.jpg }` → `FormData { file: 体检报告.pdf }` | +| **Process** | 入职页面 → 文件上传 → 上传身份证照片和体检报告 | +| **Output** | HTTP 200,`{ success: true, data: { url: "/uploads/onboarding/id-front.jpg" } }` | +| **验证** | 文件上传成功 | + +### E2E-043 HR 审核入职 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/work-processes/wp1/submit` | +| **Process** | 工作流程 → 入职流程 → 检查新员工提交的信息和文件 → 确认无误 → 提交 | +| **Output** | HTTP 200,`{ success: true }`。状态变为 `SUBMITTED` | +| **验证** | 入职流程完成,花名册新增孙磊(5 名员工),合同自动创建 | + +--- + +## 阶段十:解聘流程 + +### E2E-044 创建解聘草稿 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/termination/draft` `{ employeeId: "e3", reason: "协商解除", reasonDetail: "公司业务调整,岗位裁撤", lastDay: "2026-08-31" }` | +| **Process** | 进入 `/termination` → 新建解聘 → 选择陈强 → 选择原因「协商解除」→ 填写最后工作日 → 保存 | +| **Output** | HTTP 201,`{ success: true, data: { id: "td1", employeeId: "e3", employeeName: "陈强", reason: "协商解除", status: "DRAFT" } }` | +| **验证** | 解聘列表显示陈强的草稿 | + +### E2E-045 解聘风险评估 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | GET `/api/v1/termination/assess/e3?reason=协商解除` | +| **Process** | 解聘详情 → 点击「风险评估」 | +| **Output** | `{ riskLevel: "LOW", riskScore: 15, factors: [{ factor: "入职年限", description: "入职5.5年", impact: "medium" }, { factor: "合同状态", description: "无固定期限合同", impact: "medium" }, { factor: "协商解除", description: "双方协商一致", impact: "low" }], recommendations: ["建议支付N经济补偿(5.5个月)", "签署协商解除协议", "办理社保减员"] }` | +| **验证** | 风险等级 LOW,建议支付 5.5 个月补偿 | + +### E2E-046 查看解聘清单 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | GET `/api/v1/termination/checklist/协商解除?employeeId=e3` | +| **Process** | 解聘详情 → 查看「办理清单」 | +| **Output** | `{ items: [{ id: "cl1", title: "签署解除协议", required: true, completed: false }, { id: "cl2", title: "支付经济补偿(5.5个月×10000=55000元)", required: true, completed: false }, { id: "cl3", title: "工作交接", required: true, completed: false }, { id: "cl4", title: "社保公积金减员", required: true, completed: false }, { id: "cl5", title: "出具离职证明", required: true, completed: false }] }` | +| **验证** | 清单包含 5 项必须操作 | + +### E2E-047 更新解聘草稿 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | PUT `/api/v1/termination/draft/td1` `{ compensation: 55000, compensationMonths: 5.5, lastDay: "2026-08-31", checklist: [{ id: "cl1", completed: true }, { id: "cl2", completed: true }, { id: "cl3", completed: true }] }` | +| **Process** | 解聘详情 → 填写补偿金额 55000 → 逐项勾选已完成清单项 → 保存 | +| **Output** | HTTP 200,`{ success: true }` | +| **验证** | 草稿更新成功,3/5 清单项已完成 | + +### E2E-048 提交解聘审批 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/termination/draft/td1/submit` | +| **Process** | 解聘详情 → 确认信息 → 点击「提交审批」 | +| **Output** | HTTP 200,`{ success: true }`。状态变为 `PENDING_APPROVAL` | +| **验证** | 解聘状态变为待审批 | + +### E2E-049 管理员审批解聘 + +| 项目 | 内容 | +|------|------| +| **角色** | 企业管理员(刘明远) | +| **Input** | POST `/api/v1/termination/draft/td1/approve` `{ comment: "同意协商解除,补偿金额合理" }` | +| **Process** | 管理员登录 → 解聘管理 → 查看陈强解聘申请 → 审批通过 | +| **Output** | HTTP 200,`{ success: true }`。状态变为 `APPROVED` | +| **验证** | 解聘状态变为已审批 | + +### E2E-050 执行解聘 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | POST `/api/v1/termination/draft/td1/execute` | +| **Process** | 解聘详情 → 完成剩余清单项(社保减员、离职证明)→ 点击「执行解聘」 | +| **Output** | HTTP 200,`{ success: true }`。状态变为 `EXECUTED` | +| **验证** | 陈强员工状态变为 `RESIGNED`,社保公积金自动减员,花名册显示 4 名在职员工 | + +--- + +## 阶段十一:月末检查与审计 + +### E2E-051 查看薪酬仪表盘 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | GET `/api/v1/salary/dashboard?year=2026` | +| **Process** | 进入 `/money` → 薪酬分析 → 查看 2026 年数据 | +| **Output** | `{ year: 2026, monthly: [{ month: "2026-08", totalPay: 34200, avgPay: 8550, headcount: 4 }], departmentSalary: [{ department: "生产车间", avgSalary: 8500 }, { department: "行政部", avgSalary: 9000 }, { department: "质检部", avgSalary: 8500 }], salaryDistribution: [{ range: "8K-10K", count: 4 }], yoyChange: 0 }` | +| **验证** | 8 月总薪酬 34200 元,平均 8550 元,4 名员工 | + +### E2E-052 查看审计日志 + +| 项目 | 内容 | +|------|------| +| **角色** | 企业管理员 | +| **Input** | GET `/api/v1/audit?page=1&pageSize=20` | +| **Process** | 进入 `/audit` → 查看操作日志 | +| **Output** | `{ data: [{ id: "al1", entity: "EMPLOYEE", action: "IMPORT", operator: "李萍", target: "批量导入4名员工", timestamp: "2026-08-01T09:30:00Z" }, { id: "al2", entity: "PAYROLL", action: "APPROVE", operator: "刘明远", target: "2026年8月工资批次", timestamp: "2026-08-28T14:00:00Z" }, { id: "al3", entity: "TERMINATION", action: "EXECUTE", operator: "李萍", target: "陈强协商解除", timestamp: "2026-08-31T16:00:00Z" }], pagination: { total: 25 } }` | +| **验证** | 审计日志完整记录了导入、审批、解聘等关键操作 | + +### E2E-053 导出花名册 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | GET `/api/v1/export/roster?status=ACTIVE` | +| **Process** | 花名册 → 点击「导出」→ 选择在职员工 → 下载 | +| **Output** | HTTP 200,下载 `花名册_2026-08-31.xlsx`,包含 4 条在职员工记录(陈强已离职) | +| **验证** | 导出文件包含 4 名在职员工,不含已离职的陈强 | + +### E2E-054 导出工资条 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | GET `/api/v1/export/payslip?batchId=b1` | +| **Process** | 薪酬 → 8 月批次 → 点击「导出工资条」→ 下载 | +| **Output** | HTTP 200,下载 `工资条_2026-08.xlsx`,包含 4 条工资明细 | +| **验证** | 导出文件包含 4 名员工的完整工资明细 | + +--- + +## 阶段十二:员工离职申请(员工端发起) + +### E2E-055 员工提交离职申请 + +| 项目 | 内容 | +|------|------| +| **角色** | 员工(王芳) | +| **Input** | POST `/api/v1/portal/resignation/submit` `{ reason: "个人发展", expectedLastDay: "2026-09-30", description: "感谢公司三年培养,因个人职业规划调整申请离职" }` | +| **Process** | 员工端 → 离职申请 → 填写离职原因和期望最后工作日 → 提交 | +| **Output** | HTTP 201,`{ success: true, data: { id: "rg1", status: "PENDING" } }` | +| **验证** | 离职申请提交成功,状态待处理 | + +### E2E-056 HR 查看离职申请 + +| 项目 | 内容 | +|------|------| +| **角色** | HR | +| **Input** | GET `/api/v1/portal/resignation/status`(或管理端查看) | +| **Process** | 管理端 → 解聘管理 → 查看员工发起的离职申请 | +| **Output** | `[{ id: "rg1", employeeName: "王芳", reason: "个人发展", expectedLastDay: "2026-09-30", status: "PENDING", submittedAt: "2026-08-31T10:00:00Z" }]` | +| **验证** | 离职申请列表显示王芳的申请 | + +### E2E-057 员工撤回离职申请 + +| 项目 | 内容 | +|------|------| +| **角色** | 员工(王芳) | +| **Input** | POST `/api/v1/portal/resignation/rg1/withdraw` | +| **Process** | 员工端 → 离职申请 → 点击「撤回」 | +| **Output** | HTTP 200,`{ success: true }`。状态变为 `WITHDRAWN` | +| **验证** | 离职申请状态变为已撤回 | + +--- + +## 全流程验证检查清单 + +| # | 检查项 | 预期结果 | 实际结果 | +|---|--------|----------|----------| +| 1 | 租户创建成功 | 组织列表可见,管理员可登录 | ☐ | +| 2 | 企业信息配置完成 | 设置页显示完整企业信息 | ☐ | +| 3 | HR 子账号可登录 | HR 角色可访问各功能模块 | ☐ | +| 4 | 花名册导入成功 | 4 名员工数据完整 | ☐ | +| 5 | 考勤数据导入成功 | 考勤月报数据正确 | ☐ | +| 6 | 社保公积金配置生效 | 上海基数和比例正确 | ☐ | +| 7 | 薪酬模板创建成功 | 模板包含 6 个薪资项 | ☐ | +| 8 | 制度发布流程完整 | 4 步民主程序全部完成 | ☐ | +| 9 | 员工端可登录 | 自动登录成功,首页正常 | ☐ | +| 10 | 员工可查看制度并签收 | 制度标记为已读 | ☐ | +| 11 | 仪表盘风险提示正确 | 合同过期风险准确 | ☐ | +| 12 | 合同续签成功 | 员工合同状态更新 | ☐ | +| 13 | 考勤月报发布成功 | 员工端可查看当月考勤 | ☐ | +| 14 | 发薪批次计算正确 | 工资明细金额准确 | ☐ | +| 15 | 个税计算正确 | 累计预扣法计算无误 | ☐ | +| 16 | 发薪审批流程完整 | HR 提交 → 管理员审批 | ☐ | +| 17 | 员工可查看并确认工资条 | 工资条状态 CONFIRMED | ☐ | +| 18 | 社保月度办理完成 | 社保和公积金均已完成 | ☐ | +| 19 | 用工体检诊断正常 | 总分 ≥ 80,等级 healthy | ☐ | +| 20 | AI 顾问可咨询 | 回答包含法律依据 | ☐ | +| 21 | 新员工入职流程完整 | 入职 → 填信息 → 上传 → 审核 | ☐ | +| 22 | 解聘流程完整 | 草稿 → 风险评估 → 审批 → 执行 | ☐ | +| 23 | 解聘后员工状态正确 | 状态 RESIGNED,社保减员 | ☐ | +| 24 | 审计日志完整 | 关键操作均有记录 | ☐ | +| 25 | 数据导出正确 | 花名册和工资条导出无误 | ☐ | +| 26 | 员工离职申请流程 | 提交 → 查看 → 撤回 | ☐ | + +--- + +## 流程时间线 + +| 日期 | 操作 | 角色 | +|------|------|------| +| 2026-08-01 09:00 | 平台超管创建租户 | SUPER_ADMIN | +| 2026-08-01 09:15 | 企业管理员首次登录,完善信息 | 刘明远 | +| 2026-08-01 09:30 | 添加 HR 用户 | 刘明远 | +| 2026-08-01 09:45 | HR 登录,批量导入花名册 | 李萍 | +| 2026-08-01 10:00 | 导入 7 月考勤数据 | 李萍 | +| 2026-08-01 10:15 | 配置考勤班次和排班 | 李萍 | +| 2026-08-01 10:30 | 配置社保公积金 | 李萍 | +| 2026-08-01 11:00 | 创建薪酬模板 | 李萍 | +| 2026-08-01 14:00 | 创建考勤管理制度并推进民主程序 | 李萍 | +| 2026-08-01 15:00 | 生成员工端登录链接,员工首次登录 | 李萍 → 张伟 | +| 2026-08-01 15:30 | 员工查看制度并签收 | 张伟 | +| 2026-08-02 09:00 | 查看仪表盘风险,处理合同续签 | 李萍 | +| 2026-08-04~08-30 | 每日录入考勤 | 李萍 | +| 2026-08-10 | 王芳请假 3 天 | 李萍 | +| 2026-08-15 | 新员工孙磊入职 | 李萍 → 孙磊 | +| 2026-08-28 | 创建发薪批次,计算工资,提交审批 | 李萍 | +| 2026-08-28 14:00 | 管理员审批发薪 | 刘明远 | +| 2026-08-29 | 员工查看并确认工资条 | 张伟 | +| 2026-08-30 | 社保公积金月度办理 | 李萍 | +| 2026-08-30 | 用工体检诊断 | 李萍 | +| 2026-08-31 | 陈强协商解除解聘执行 | 李萍 → 刘明远 | +| 2026-08-31 | 导出花名册和工资条 | 李萍 | +| 2026-08-31 17:00 | 王芳提交离职申请后撤回 | 王芳 | diff --git a/docs/test-scenarios.md b/docs/test-scenarios.md new file mode 100644 index 0000000..54326b6 --- /dev/null +++ b/docs/test-scenarios.md @@ -0,0 +1,1917 @@ +# TurboHR 完整测试场景清单(含输入输出示例数据) + +> **版本**: v1.0 +> **更新日期**: 2026-08-01 +> **测试环境**: https://on.hr8ai.top +> **管理端账号**: `13800000010` / `12345678`(王建国·北京·PRO 套餐) +> **第二租户**: `13800000020` / `12345678`(李明华·深圳·ENTERPRISE 套餐) +> **第三租户**: `13800000030` / `12345678`(赵雪梅·杭州·FREE 套餐) +> **平台管理端**: SUPER_ADMIN 账号 +> **员工端**: 员工手机号 + 密码或验证码 + +--- + +## 目录 + +1. [认证与账户域](#1-认证与账户域) +2. [工作台与仪表盘域](#2-工作台与仪表盘域) +3. [花名册与员工档案域](#3-花名册与员工档案域) +4. [考勤排班域](#4-考勤排班域) +5. [薪税管理域](#5-薪税管理域) +6. [社保公积金域](#6-社保公积金域) +7. [解聘补偿域](#7-解聘补偿域) +8. [合规风控域](#8-合规风控域) +9. [规章制度域](#9-规章制度域) +10. [AI 顾问域](#10-ai-顾问域) +11. [工作流程域](#11-工作流程域) +12. [特殊状态台账域](#12-特殊状态台账域) +13. [日历与事件域](#13-日历与事件域) +14. [通知管理域](#14-通知管理域) +15. [系统设置域](#15-系统设置域) +16. [模板管理域](#16-模板管理域) +17. [证据链域](#17-证据链域) +18. [公司文件域](#18-公司文件域) +19. [审计日志域](#19-审计日志域) +20. [薪酬分析仪表盘域](#20-薪酬分析仪表盘域) +21. [平台管理端域](#21-平台管理端域) +22. [员工端 Portal 域](#22-员工端-portal-域) +23. [数据导入导出域](#23-数据导入导出域) +24. [全局搜索与命令面板域](#24-全局搜索与命令面板域) +25. [企业全流程端到端场景](#25-企业全流程端到端场景) + +--- + +## 1. 认证与账户域 + +### TC-AUTH-001 管理端登录(正确凭证) + +| 项目 | 内容 | +|------|------| +| **Input** | `phone: "13800000010"`, `password: "12345678"`, `remember: true` | +| **Process** | POST `/api/v1/auth/login` → 访问 `/login`,填入手机号和密码,点击「登录」 | +| **Output** | HTTP 200,响应 `{ success: true, data: { user: { id, orgId, name: "王建国", phone: "13800000010", role: "ADMIN" }, accessToken: "eyJ...", refreshToken: "eyJ..." } }`。页面跳转至 `/`,顶部显示「王建国」,localStorage 持久化 token | + +### TC-AUTH-002 管理端登录(错误密码) + +| 项目 | 内容 | +|------|------| +| **Input** | `phone: "13800000010"`, `password: "wrongpass"` | +| **Process** | POST `/api/v1/auth/login` | +| **Output** | HTTP 401,响应 `{ success: false, error: { code: "UNAUTHORIZED", message: "手机号或密码错误" } }`。页面显示「手机号或密码错误」,不跳转 | + +### TC-AUTH-003 管理端登录(空字段校验) + +| 项目 | 内容 | +|------|------| +| **Input** | `phone: ""`, `password: ""` | +| **Process** | 不填任何字段,点击「登录」 | +| **Output** | 前端表单校验提示「请输入手机号」「请输入密码」,不发起 API 请求 | + +### TC-AUTH-004 注册新企业 + +| 项目 | 内容 | +|------|------| +| **Input** | `orgName: "测试科技有限公司"`, `contactName: "张三"`, `phone: "13900001111"`, `password: "Test1234"`, `code: "123456"` | +| **Process** | POST `/api/v1/auth/register` | +| **Output** | HTTP 201,响应 `{ success: true, data: { orgId: "xxx", userId: "xxx" } }`。跳转至 `/login`,提示「注册成功,请登录」 | + +### TC-AUTH-005 忘记密码 + +| 项目 | 内容 | +|------|------| +| **Input** | `phone: "13800000010"`, `code: "123456"`, `newPassword: "NewPass123"` | +| **Process** | 1. POST `/api/v1/auth/forgot-password/send-code` `{ phone: "13800000010" }`;2. POST `/api/v1/auth/forgot-password/verify` `{ phone, code, newPassword }` | +| **Output** | 第一步 HTTP 200 `{ success: true, message: "验证码已发送" }`;第二步 HTTP 200 `{ success: true, message: "密码修改成功" }`。跳转至 `/login` | + +### TC-AUTH-006 Token 自动刷新 + +| 项目 | 内容 | +|------|------| +| **Input** | 过期的 accessToken,有效的 refreshToken | +| **Process** | 1. 登录后手动篡改 localStorage 中 accessToken 为 `invalid_token`;2. 触发任意 API 请求如 GET `/api/v1/dashboard` | +| **Output** | 拦截器收到 401 → POST `/api/v1/auth/refresh` `{ refreshToken }` → 获取新 accessToken → 原请求重试成功。localStorage 更新为新 token | + +### TC-AUTH-007 未登录路由保护 + +| 项目 | 内容 | +|------|------| +| **Input** | 未登录状态(清空 localStorage) | +| **Process** | 直接访问 `/roster`、`/money`、`/settings`、`/termination` 等受保护路由 | +| **Output** | 自动重定向至 `/login`,URL 变为 `https://on.hr8ai.top/login` | + +### TC-AUTH-008 退出登录 + +| 项目 | 内容 | +|------|------| +| **Input** | 已登录状态 | +| **Process** | 点击顶部导航栏「退出」按钮 | +| **Output** | localStorage 清除 `auth-storage`,QueryClient 缓存清空,跳转至 `/login` | + +--- + +## 2. 工作台与仪表盘域 + +### TC-DASH-001 工作台概览加载 + +| 项目 | 内容 | +|------|------| +| **Input** | 已登录管理端(orgId: 北京公司) | +| **Process** | GET `/api/v1/dashboard` | +| **Output** | HTTP 200,返回 `{ greeting: "下午好!今天有 4 件事需要处理", stats: { employeeCount: 6, highRiskCount: 4, todoCount: 4, monthlyOvertimePay: 0 }, todos: [...4条], payrollSummary: { month: "2026-08", totalPay: 0, ... }, monthlyActivities: { newContracts: 0, terminations: 0, ... }, yearCostSummary: { year: "2026", ... } }`。页面渲染统计卡片、待办列表、成本分析 | + +### TC-DASH-002 待办事项列表(按优先级排序) + +| 项目 | 内容 | +|------|------| +| **Input** | 已登录,存在 4 条 PENDING RiskItem | +| **Process** | GET `/api/v1/dashboard`,解析 `todos` 数组 | +| **Output** | `todos` 按优先级排序,示例:`[{ id: "r1", type: "TERMINATION", priority: "URGENT", title: "孙美丽处于孕期/哺乳期,解聘受限", deadline: "2026-08-01", employeeName: "孙美丽" }, { id: "r2", type: "CONTRACT", priority: "HIGH", title: "刘大壮的合同已到期520天未续签", deadline: "2026-08-04", employeeName: "刘大壮" }, ...]` | + +### TC-DASH-003 待办标记已处理 + +| 项目 | 内容 | +|------|------| +| **Input** | `todoId: "r1"` | +| **Process** | PATCH `/api/v1/dashboard/todos/r1/resolve` | +| **Output** | HTTP 200,`{ success: true }`。该待办从列表消失,toast 提示「已标记为已处理」,dashboard 数据刷新 | + +### TC-DASH-004 待办忽略 + +| 项目 | 内容 | +|------|------| +| **Input** | `todoId: "r2"` | +| **Process** | PATCH `/api/v1/dashboard/todos/r2/ignore` | +| **Output** | HTTP 200,`{ success: true }`。该待办从列表消失,toast 提示「已忽略」 | + +### TC-DASH-005 批量标记已处理 + +| 项目 | 内容 | +|------|------| +| **Input** | `ids: ["r1", "r2", "r3"]` | +| **Process** | PATCH `/api/v1/dashboard/todos/batch-resolve` `{ ids: ["r1","r2","r3"] }` | +| **Output** | HTTP 200,`{ success: true, data: { resolved: 3 } }`。3 条待办消失,选中集合清空 | + +### TC-DASH-006 批量忽略 + +| 项目 | 内容 | +|------|------| +| **Input** | `ids: ["r1", "r2"]` | +| **Process** | PATCH `/api/v1/dashboard/todos/batch-ignore` `{ ids: ["r1","r2"] }` | +| **Output** | HTTP 200,`{ success: true, data: { ignored: 2 } }`。2 条待办消失,选中集合清空 | + +### TC-DASH-007 合规健康度评分 + +| 项目 | 内容 | +|------|------| +| **Input** | 已登录 | +| **Process** | GET `/api/v1/dashboard/health-check` | +| **Output** | `{ year: 2026, totalScore: 80, level: "warning", dimensions: [{ key: "contract", name: "合同管理", score: 100, findings: [...], recommendations: [...] }, { key: "salary_social", name: "薪酬社保", score: 100 }, { key: "attendance", name: "考勤加班", score: 100 }, { key: "policy", name: "规章制度", score: 60 }, { key: "termination", name: "解聘合规", score: 100 }, { key: "evidence", name: "证据链", score: 20 }], summary: "整体用工存在中等风险(80分),建议优先处理低分维度问题" }`。页面渲染环形评分图 + 6 维度卡片 | + +### TC-DASH-008 成本分析 + +| 项目 | 内容 | +|------|------| +| **Input** | `month: "2026-08"` | +| **Process** | GET `/api/v1/dashboard/cost-analysis?month=2026-08` | +| **Output** | `{ current: { totalCost: 53000, perCapita: 8833.33 }, monthOnMonth: { prevTotal: 51000, change: 2000, changePercent: 3.9 }, yearOnYear: { lastYearTotal: 0, change: 0 }, factors: [], departmentCost: [] }`。页面渲染环比/同比卡片、人均成本 | + +### TC-DASH-009 人力信息总览 + +| 项目 | 内容 | +|------|------| +| **Input** | 已登录 | +| **Process** | GET `/api/v1/dashboard/workforce-stats` | +| **Output** | `{ gender: { male: 3, female: 3 }, ageGroups: [{ range: "25-35", count: 4 }, { range: "35-45", count: 2 }], education: [{ level: "大专", count: 3 }, { level: "本科", count: 2 }, { level: "硕士", count: 1 }], tenure: [{ range: "1-3年", count: 2 }, { range: "3-5年", count: 3 }, { range: "5-10年", count: 1 }] }`。页面渲染性别/年龄/学历/司龄分布图 | + +### TC-DASH-010 入离职趋势 + +| 项目 | 内容 | +|------|------| +| **Input** | `months: 12` | +| **Process** | GET `/api/v1/dashboard/turnover-stats?months=12` | +| **Output** | `{ months: ["2025-09","2025-10",...,"2026-08"], hired: [0,1,0,...,0], left: [0,0,0,...,0], current: [6,7,7,...,6], turnoverRate: [0,0,...,0] }`。页面渲染 12 个月趋势折线图 | + +### TC-DASH-011 绩效统计 + +| 项目 | 内容 | +|------|------| +| **Input** | `period: "2026"` | +| **Process** | GET `/api/v1/dashboard/performance-stats?period=2026` | +| **Output** | `{ periods: ["2026-Q1","2026-Q2","2026-Q3"], data: [], avgScore: 0 }` 或空数据时页面显示「暂无数据」 | + +### TC-DASH-012 合同到期预警弹窗 + +| 项目 | 内容 | +|------|------| +| **Input** | 已登录,存在即将到期合同 | +| **Process** | GET `/api/v1/roster/contracts/expiring` | +| **Output** | `[{ id: "c1", employeeName: "孙美丽", contractType: "FIXED", endDate: "2025-08-30", daysLeft: -336 }, ...]`。页面顶部显示红色预警条,点击展开弹窗显示到期员工列表 | + +### TC-DASH-013 任务中心 + +| 项目 | 内容 | +|------|------| +| **Input** | 已登录 | +| **Process** | 访问 `/`,查看「任务中心」区域 | +| **Output** | 显示 `5 项待处理`,包含草稿发薪批次、未完成月度办理等待办分类 | + +### TC-DASH-014 年度价值报告 + +| 项目 | 内容 | +|------|------| +| **Input** | `year: 2026` | +| **Process** | GET `/api/v1/dashboard/annual-value?year=2026` | +| **Output** | `{ year: 2026, sections: [...], overallScore: 75, highlights: [...] }`。页面渲染年度价值报告卡片 | + +--- + +## 3. 花名册与员工档案域 + +### TC-ROSTER-001 花名册分页列表 + +| 项目 | 内容 | +|------|------| +| **Input** | `page: 1, pageSize: 10, status: "ACTIVE", department: ""` | +| **Process** | GET `/api/v1/roster?page=1&pageSize=10&status=ACTIVE` | +| **Output** | `{ data: [{ id: "e1", name: "刘大壮", idCardMasked: "110****1001", department: "生产车间", status: "ACTIVE", salary: 8500, contractType: "FIXED", contractStatus: "EXPIRED", contractEndDate: "2025-02-27" }, ...共6条], pagination: { page: 1, pageSize: 10, total: 6, totalPages: 1 }, globalRiskStats: { expiring: 0, expired: 3, unsigned: 0 } }` | + +### TC-ROSTER-002 花名册搜索 + +| 项目 | 内容 | +|------|------| +| **Input** | `search: "孙"` | +| **Process** | GET `/api/v1/roster?search=孙&page=1&pageSize=10` | +| **Output** | `{ data: [{ id: "e4", name: "孙美丽", department: "行政部", status: "ACTIVE", salary: 11000 }], pagination: { total: 1 } }` | + +### TC-ROSTER-003 花名册筛选(合同状态) + +| 项目 | 内容 | +|------|------| +| **Input** | `contractStatus: "EXPIRED"` | +| **Process** | GET `/api/v1/roster?contractStatus=EXPIRED` | +| **Output** | `{ data: [孙美丽(已过期), 陈秀英(已过期), 刘大壮(已过期)], pagination: { total: 3 } }`。页面顶部显示红色风险提醒条 | + +### TC-ROSTER-004 花名册筛选(部门) + +| 项目 | 内容 | +|------|------| +| **Input** | `department: "生产车间"` | +| **Process** | GET `/api/v1/roster?department=生产车间` | +| **Output** | `{ data: [刘大壮, 陈秀英, 赵铁柱, 周大伟], pagination: { total: 4 } }` | + +### TC-ROSTER-005 部门列表 + +| 项目 | 内容 | +|------|------| +| **Input** | 无 | +| **Process** | GET `/api/v1/roster/departments` | +| **Output** | `["生产车间", "行政部", "质检部"]` | + +### TC-ROSTER-006 添加员工 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ name: "测试员工", gender: "男", department: "生产车间", phone: "13900009999", idCard: "110101199001011001", salary: 8000, hireDate: "2026-08-01", contractType: "FIXED", years: 3, probation: 3, probationSalary: 6400, bank: "工商银行", account: "6222020100019999", emergency: "测试父", emergencyPhone: "13800009998", address: "北京市朝阳区测试路1号" }` | +| **Process** | POST `/api/v1/employees` | +| **Output** | HTTP 201,`{ success: true, data: { id: "new-emp-id", name: "测试员工", status: "ACTIVE" } }`。列表刷新显示新员工 | + +### TC-ROSTER-007 员工详情档案 + +| 项目 | 内容 | +|------|------| +| **Input** | `employeeId: "e1"`(刘大壮) | +| **Process** | GET `/api/v1/roster/e1/profile` | +| **Output** | `{ employee: { id: "e1", name: "刘大壮", gender: "男", department: "生产车间", phone: "13900001001", salary: 8500, hireDate: "2022-03-01" }, contracts: [{ type: "FIXED", startDate: "2022-03-01", endDate: "2025-02-27", status: "EXPIRED" }], disciplinary: [], attendance: [], training: [], performance: [], payslips: [...6条], attachments: [] }` | + +### TC-ROSTER-008 调薪 + +| 项目 | 内容 | +|------|------| +| **Input** | `employeeId: "e1"`, `{ newSalary: 9500, effectiveDate: "2026-08-01", reason: "年度调薪" }` | +| **Process** | POST `/api/v1/roster/e1/salary-change` | +| **Output** | HTTP 200,`{ success: true }`。员工档案薪资更新为 9500 | + +### TC-ROSTER-009 调岗 + +| 项目 | 内容 | +|------|------| +| **Input** | `employeeId: "e1"`, `{ newDepartment: "质检部", effectiveDate: "2026-08-01", reason: "业务调整" }` | +| **Process** | POST `/api/v1/roster/e1/department-change` | +| **Output** | HTTP 200,`{ success: true }`。员工部门更新为「质检部」 | + +### TC-ROSTER-010 添加违纪记录 + +| 项目 | 内容 | +|------|------| +| **Input** | `employeeId: "e1"`, `{ violationDate: "2026-08-01", description: "迟到3次", action: "口头警告", evidence: "考勤记录" }` | +| **Process** | POST `/api/v1/roster/e1/disciplinary` | +| **Output** | HTTP 201,`{ success: true, data: { id: "d1", violationDate: "2026-08-01", description: "迟到3次" } }`。档案违纪 tab 显示新记录 | + +### TC-ROSTER-011 添加考勤记录 + +| 项目 | 内容 | +|------|------| +| **Input** | `employeeId: "e1"`, `{ date: "2026-08-01", checkIn: "08:50", checkOut: "18:10", status: "NORMAL" }` | +| **Process** | POST `/api/v1/roster/e1/attendance` | +| **Output** | HTTP 201,`{ success: true, data: { id: "a1", date: "2026-08-01" } }` | + +### TC-ROSTER-012 添加培训记录 + +| 项目 | 内容 | +|------|------| +| **Input** | `employeeId: "e1"`, `{ date: "2026-08-01", course: "安全生产培训", hours: 8, result: "合格" }` | +| **Process** | POST `/api/v1/roster/e1/training` | +| **Output** | HTTP 201,`{ success: true, data: { id: "t1", course: "安全生产培训" } }` | + +### TC-ROSTER-013 添加绩效记录 + +| 项目 | 内容 | +|------|------| +| **Input** | `employeeId: "e1"`, `{ period: "2026-Q3", score: 85, comment: "工作积极" }` | +| **Process** | POST `/api/v1/roster/e1/performance` | +| **Output** | HTTP 201,`{ success: true, data: { id: "p1", period: "2026-Q3", score: 85 } }` | + +### TC-ROSTER-014 添加合同 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ employeeId: "e1", type: "FIXED", startDate: "2026-08-01", years: 3, probation: 3, probationSalary: 7600 }` | +| **Process** | POST `/api/v1/employees/contracts` | +| **Output** | HTTP 201,`{ success: true, data: { id: "c-new", type: "FIXED", startDate: "2026-08-01", endDate: "2029-07-31" } }` | + +### TC-ROSTER-015 批量续签预检 + +| 项目 | 内容 | +|------|------| +| **Input** | `contractIds: ["c1", "c2", "c3"]` | +| **Process** | POST `/api/v1/employees/contracts/preview-renew` `{ contractIds: ["c1","c2","c3"] }` | +| **Output** | `{ data: [{ contractId: "c1", employeeName: "孙美丽", oldEndDate: "2025-08-30", newEndDate: "2028-08-29" }, ...] }` | + +### TC-ROSTER-016 批量续签 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ contractIds: ["c1", "c2"], years: 3 }` | +| **Process** | POST `/api/v1/employees/contracts/batch-renew` | +| **Output** | HTTP 200,`{ success: true, data: { renewed: 2 } }`。合同状态更新为正常 | + +### TC-ROSTER-017 删除员工 + +| 项目 | 内容 | +|------|------| +| **Input** | `employeeId: "e-new"`(测试员工) | +| **Process** | DELETE `/api/v1/employees/e-new` | +| **Output** | HTTP 200,`{ success: true }`。列表中该员工消失 | + +### TC-ROSTER-018 员工重新入职 + +| 项目 | 内容 | +|------|------| +| **Input** | `employeeId: "e-resigned"`, `{ hireDate: "2026-08-01", department: "生产车间", salary: 8000, contractType: "FIXED", years: 3 }` | +| **Process** | POST `/api/v1/employees/e-resigned/rehire` | +| **Output** | HTTP 200,`{ success: true, data: { status: "ACTIVE" } }`。员工状态从 RESIGNED 变为 ACTIVE | + +### TC-ROSTER-019 附件管理 + +| 项目 | 内容 | +|------|------| +| **Input** | `employeeId: "e1"`, `{ name: "身份证复印件", url: "/uploads/id-card.jpg", type: "image" }` | +| **Process** | POST `/api/v1/attachments`;GET `/api/v1/attachments/e1` | +| **Output** | 创建返回 HTTP 201;列表返回 `[{ id: "att1", name: "身份证复印件", url: "/uploads/id-card.jpg" }]` | + +--- + +## 4. 考勤排班域 + +### TC-ATT-001 考勤确认列表 + +| 项目 | 内容 | +|------|------| +| **Input** | `month: "2026-08", department: "", status: ""` | +| **Process** | GET `/api/v1/attendance?month=2026-08` | +| **Output** | `{ data: [], total: 0, stats: { total: 0, pending: 0, confirmed: 0, objected: 0 } }`。页面显示「本月暂无考勤确认记录」 | + +### TC-ATT-002 考勤统计 + +| 项目 | 内容 | +|------|------| +| **Input** | `month: "2026-08"` | +| **Process** | GET `/api/v1/attendance/stats?month=2026-08` | +| **Output** | `{ total: 0, pending: 0, confirmed: 0, objected: 0, attendanceRate: 0 }` | + +### TC-ATT-003 班次列表 + +| 项目 | 内容 | +|------|------| +| **Input** | 无 | +| **Process** | GET `/api/v1/attendance/shifts` | +| **Output** | `[{ id: "s1", name: "早班", startTime: "08:00", endTime: "17:00", color: "#4CAF50" }, { id: "s2", name: "晚班", startTime: "16:00", endTime: "23:00", color: "#FF9800" }]` 或空数组 | + +### TC-ATT-004 创建班次 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ name: "早班", startTime: "08:00", endTime: "17:00", color: "#4CAF50", restStart: "12:00", restEnd: "13:00" }` | +| **Process** | POST `/api/v1/attendance/shifts` | +| **Output** | HTTP 201,`{ success: true, data: { id: "s1", name: "早班", startTime: "08:00", endTime: "17:00" } }` | + +### TC-ATT-005 更新班次 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "s1"`, `{ name: "早班A", startTime: "08:00", endTime: "17:30" }` | +| **Process** | PUT `/api/v1/attendance/shifts/s1` | +| **Output** | HTTP 200,`{ success: true }`。班次名称更新为「早班A」 | + +### TC-ATT-006 删除班次 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "s1"` | +| **Process** | DELETE `/api/v1/attendance/shifts/s1` | +| **Output** | HTTP 200,`{ success: true }`。班次列表中该班次消失 | + +### TC-ATT-007 排班(按日期) + +| 项目 | 内容 | +|------|------| +| **Input** | `date: "2026-08-01"` | +| **Process** | GET `/api/v1/attendance/shift-assignments?date=2026-08-01` | +| **Output** | `{ data: [{ id: "sa1", employeeId: "e1", employeeName: "刘大壮", shiftId: "s1", shiftName: "早班", date: "2026-08-01" }] }` 或空数组 | + +### TC-ATT-008 批量排班 + +| 项目 | 内容 | +|------|------| +| **Input** | `items: [{ employeeId: "e1", shiftId: "s1", date: "2026-08-01" }, { employeeId: "e2", shiftId: "s1", date: "2026-08-01" }]` | +| **Process** | POST `/api/v1/attendance/shift-assignments/batch` `{ items: [...] }` | +| **Output** | HTTP 200,`{ success: true, data: { created: 2 } }` | + +### TC-ATT-009 每日出勤 + +| 项目 | 内容 | +|------|------| +| **Input** | `date: "2026-08-01"` | +| **Process** | GET `/api/v1/attendance/daily?date=2026-08-01` | +| **Output** | `{ data: [{ employeeId: "e1", employeeName: "刘大壮", shiftName: "早班", checkIn: "08:50", checkOut: "18:10", status: "NORMAL", overtime: 0 }] }` | + +### TC-ATT-010 月度报表 + +| 项目 | 内容 | +|------|------| +| **Input** | `month: "2026-08"` | +| **Process** | GET `/api/v1/attendance/monthly-report?month=2026-08` | +| **Output** | `{ data: [{ employeeId: "e1", employeeName: "刘大壮", normalDays: 22, lateTimes: 0, earlyLeaveTimes: 0, absentDays: 0, overtimeHours: 0, leaveDays: 0 }] }` | + +### TC-ATT-011 发布考勤 + +| 项目 | 内容 | +|------|------| +| **Input** | `month: "2026-08"` | +| **Process** | POST `/api/v1/attendance/publish` `{ month: "2026-08" }` | +| **Output** | HTTP 200,`{ success: true, data: { id: "pub1", month: "2026-08", status: "PUBLISHED" } }`。发布状态变为「已发布」 | + +### TC-ATT-012 取消发布 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "pub1"` | +| **Process** | POST `/api/v1/attendance/publish/pub1/cancel` | +| **Output** | HTTP 200,`{ success: true }`。发布状态变为「未发布」 | + +### TC-ATT-013 批量确认考勤 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ month: "2026-08", all: true }` | +| **Process** | POST `/api/v1/attendance/batch-confirm` `{ month: "2026-08", all: true }` | +| **Output** | HTTP 200,`{ success: true, data: { confirmed: 6 } }` | + +### TC-ATT-014 请假记录 + +| 项目 | 内容 | +|------|------| +| **Input** | 无(列表);创建:`{ employeeId: "e1", type: "事假", startDate: "2026-08-05", endDate: "2026-08-06", reason: "家事" }` | +| **Process** | GET `/api/v1/attendance/leaves`;POST `/api/v1/attendance/leaves` | +| **Output** | 列表返回 `[{ id: "l1", employeeName: "刘大壮", type: "事假", startDate: "2026-08-05", endDate: "2026-08-06" }]`;创建返回 HTTP 201 | + +--- + +## 5. 薪税管理域 + +### TC-PAY-001 发薪批次列表 + +| 项目 | 内容 | +|------|------| +| **Input** | `status: "", type: "", fromDate: "", toDate: ""` | +| **Process** | GET `/api/v1/payroll2/batches` | +| **Output** | `[]` 或 `[{ id: "b1", name: "2026年8月常规发薪", month: "2026-08", type: "NORMAL", status: "DRAFT", employeeCount: 6, totalPay: 53000 }]` | + +### TC-PAY-002 创建发薪批次 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ name: "2026年8月常规发薪", month: "2026-08", type: "NORMAL" }` | +| **Process** | POST `/api/v1/payroll2/batches` | +| **Output** | HTTP 201,`{ success: true, data: { id: "b1", name: "2026年8月常规发薪", month: "2026-08", type: "NORMAL", status: "DRAFT", employeeCount: 0 } }` | + +### TC-PAY-003 批次添加人员 + +| 项目 | 内容 | +|------|------| +| **Input** | `batchId: "b1"`, `employeeIds: ["e1", "e2", "e3", "e4", "e5", "e6"]` | +| **Process** | POST `/api/v1/payroll2/batches/b1/employees` `{ employeeIds: ["e1","e2","e3","e4","e5","e6"] }` | +| **Output** | HTTP 200,`{ success: true, data: { added: 6 } }`。批次 employeeCount 变为 6 | + +### TC-PAY-004 批次条目更新(手动调薪) + +| 项目 | 内容 | +|------|------| +| **Input** | `batchId: "b1"`, `employeeId: "e1"`, `{ baseSalary: 9000, overtimePay: 0, allowance: 500, deduction: 0, bonus: 1000 }` | +| **Process** | PUT `/api/v1/payroll2/batches/b1/entries/e1` | +| **Output** | HTTP 200,`{ success: true }`。条目 totalPay 自动计算更新 | + +### TC-PAY-005 算薪前 AI 校验 + +| 项目 | 内容 | +|------|------| +| **Input** | `batchId: "b1"` | +| **Process** | GET `/api/v1/payroll2/batches/b1/pre-check` | +| **Output** | `{ status: "ok", warnings: [], errors: [], suggestions: [{ type: "OVERTIME", message: "刘大壮本月加班36小时,超过法定上限" }] }` 或 `{ status: "ok", warnings: [], errors: [] }` | + +### TC-PAY-006 归档批次 + +| 项目 | 内容 | +|------|------| +| **Input** | `batchId: "b1"` | +| **Process** | POST `/api/v1/payroll2/batches/b1/archive` | +| **Output** | HTTP 200,`{ success: true }`。批次状态变为 `ARCHIVED` | + +### TC-PAY-007 取消归档 + +| 项目 | 内容 | +|------|------| +| **Input** | `batchId: "b1"` | +| **Process** | POST `/api/v1/payroll2/batches/b1/unarchive` | +| **Output** | HTTP 200,`{ success: true }`。批次状态回退为 `DRAFT` | + +### TC-PAY-008 发布工资条 + +| 项目 | 内容 | +|------|------| +| **Input** | `batchId: "b1"` | +| **Process** | POST `/api/v1/payroll2/batches/b1/publish` | +| **Output** | HTTP 200,`{ success: true }`。员工端可见工资条 | + +### TC-PAY-009 定时发送工资条 + +| 项目 | 内容 | +|------|------| +| **Input** | `batchId: "b1"`, `scheduledAt: "2026-08-15T10:00:00Z"` | +| **Process** | POST `/api/v1/payroll2/batches/b1/schedule` `{ scheduledAt: "2026-08-15T10:00:00Z" }` | +| **Output** | HTTP 200,`{ success: true, data: { scheduledAt: "2026-08-15T10:00:00Z" } }` | + +### TC-PAY-010 薪酬模版列表 + +| 项目 | 内容 | +|------|------| +| **Input** | 无 | +| **Process** | GET `/api/v1/payroll2/template` | +| **Output** | `[{ id: "t1", name: "基本工资", type: "INCOME", formula: "baseSalary", sortOrder: 1 }, { id: "t2", name: "加班费", type: "INCOME", formula: "overtimePay", sortOrder: 2 }, { id: "t3", name: "社保扣除", type: "DEDUCTION", formula: "socialEmp", sortOrder: 3 }]` | + +### TC-PAY-011 创建模版项 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ name: "交通补贴", type: "INCOME", formula: "allowance", sortOrder: 5 }` | +| **Process** | POST `/api/v1/payroll2/template` | +| **Output** | HTTP 201,`{ success: true, data: { id: "t-new", name: "交通补贴" } }` | + +### TC-PAY-012 加班费记录 + +| 项目 | 内容 | +|------|------| +| **Input** | `month: "2026-08"` | +| **Process** | GET `/api/v1/payroll/overtime?month=2026-08` | +| **Output** | `[{ id: "o1", employeeId: "e1", employeeName: "刘大壮", month: "2026-08", weekdayHours: 10, weekendHours: 0, holidayHours: 0, totalPay: 500 }]` 或空数组 | + +### TC-PAY-013 保存加班费记录 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ employeeId: "e1", month: "2026-08", weekdayHours: 10, weekendHours: 8, holidayHours: 0 }` | +| **Process** | POST `/api/v1/payroll/overtime` | +| **Output** | HTTP 201,`{ success: true, data: { id: "o1", totalPay: 850, weekdayHours: 10, weekendHours: 8 } }`。加班费按配置自动计算 | + +### TC-PAY-014 加班费配置 + +| 项目 | 内容 | +|------|------| +| **Input** | 无(查看);`{ weekdayRate: 1.5, weekendRate: 2.0, holidayRate: 3.0 }`(保存) | +| **Process** | GET `/api/v1/payroll/overtime/config`;POST `/api/v1/payroll/overtime/config` | +| **Output** | 查看返回 `{ weekdayRate: 1.5, weekendRate: 2.0, holidayRate: 3.0 }`;保存返回 HTTP 200 | + +### TC-PAY-015 个税试算 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ month: "2026-08", employeeId: "e1", baseSalary: 8500, overtimePay: 500, allowance: 0, socialEmp: 892.5, housingEmp: 850, specialDeduction: 2000 }` | +| **Process** | POST `/api/v1/payroll/tax-preview` | +| **Output** | `{ taxableIncome: 5407.5, tax: 540.75, netPay: 7609.75, details: { rate: "10%", deduction: 210 } }` | + +### TC-PAY-016 删除批次 + +| 项目 | 内容 | +|------|------| +| **Input** | `batchId: "b1"` | +| **Process** | DELETE `/api/v1/payroll2/batches/b1` | +| **Output** | HTTP 200,`{ success: true }`。批次从列表消失 | + +### TC-PAY-017 批次重命名 + +| 项目 | 内容 | +|------|------| +| **Input** | `batchId: "b1"`, `name: "8月第一批"` | +| **Process** | PUT `/api/v1/payroll2/batches/b1/name` `{ name: "8月第一批" }` | +| **Output** | HTTP 200,`{ success: true }`。批次名称更新 | + +--- + +## 6. 社保公积金域 + +### TC-SOC-001 社保配置(按城市) + +| 项目 | 内容 | +|------|------| +| **Input** | `city: "北京"` | +| **Process** | GET `/api/v1/social/config?city=北京` | +| **Output** | `{ id: "sc1", city: "北京", pensionOrg: 16, pensionEmp: 8, medicalOrg: 9.8, medicalEmp: 2, unemploymentOrg: 0.5, unemploymentEmp: 0.5, injuryOrg: 0.2, maternityOrg: 0.8, baseMin: 6326, baseMax: 33891, effectiveFrom: "2024-07-01", isCurrent: true }` | + +### TC-SOC-002 公积金配置 + +| 项目 | 内容 | +|------|------| +| **Input** | `city: "北京"` | +| **Process** | GET `/api/v1/social/housing-config?city=北京` | +| **Output** | `{ id: "hc1", city: "北京", housingOrg: 12, housingEmp: 12, baseMin: 6326, baseMax: 33891, effectiveFrom: "2024-07-01", isCurrent: true }` | + +### TC-SOC-003 社保计算 + +| 项目 | 内容 | +|------|------| +| **Input** | `base: 8500, city: "北京"` | +| **Process** | POST `/api/v1/social/calculate` `{ base: 8500, city: "北京" }` | +| **Output** | `{ base: 8500, orgTotal: 8500 * 0.273 = 2320.5, empTotal: 8500 * 0.105 = 892.5, details: { pensionOrg: 1360, pensionEmp: 680, medicalOrg: 833, medicalEmp: 170, ... } }` | + +### TC-SOC-004 公积金计算 + +| 项目 | 内容 | +|------|------| +| **Input** | `base: 8500, city: "北京"` | +| **Process** | POST `/api/v1/social/housing-calculate` `{ base: 8500, city: "北京" }` | +| **Output** | `{ base: 8500, orgTotal: 1020, empTotal: 1020, rate: 12 }` | + +### TC-SOC-005 创建社保配置版本 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ city: "北京", effectiveFrom: "2025-07-01", pensionOrg: 16, pensionEmp: 8, medicalOrg: 9.8, medicalEmp: 2, unemploymentOrg: 0.5, unemploymentEmp: 0.5, injuryOrg: 0.2, maternityOrg: 0.8, baseMin: 6821, baseMax: 35283 }` | +| **Process** | POST `/api/v1/social/config/versions` | +| **Output** | HTTP 201,`{ success: true, data: { id: "sc2", effectiveFrom: "2025-07-01", isCurrent: false } }` | + +### TC-SOC-006 社保配置版本列表 + +| 项目 | 内容 | +|------|------| +| **Input** | `city: "北京"` | +| **Process** | GET `/api/v1/social/config/versions?city=北京` | +| **Output** | `[{ id: "sc1", effectiveFrom: "2024-07-01", isCurrent: true, baseMin: 6326, baseMax: 33891 }, { id: "sc2", effectiveFrom: "2025-07-01", isCurrent: false, baseMin: 6821, baseMax: 35283 }]` | + +### TC-SOC-007 AI 社保建议 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ city: "北京", effectiveFrom: "2025-07-01", type: "social" }` | +| **Process** | POST `/api/v1/social/ai-suggest` | +| **Output** | `{ suggestion: "建议根据北京市2025年度社保缴费基数上下限调整配置,下限预计调整为6821元,上限35283元", confidence: 0.85, recommendedConfig: { baseMin: 6821, baseMax: 35283 } }` | + +### TC-SOC-008 月度办理状态 + +| 项目 | 内容 | +|------|------| +| **Input** | `month: "2026-08"` | +| **Process** | GET `/api/v1/social/monthly-process/status?month=2026-08` | +| **Output** | `{ social: false, housing: false, socialCompletedAt: null, housingCompletedAt: null }` | + +### TC-SOC-009 月度变动(社保增减员) + +| 项目 | 内容 | +|------|------| +| **Input** | `month: "2026-08"` | +| **Process** | GET `/api/v1/social/monthly-changes?month=2026-08` | +| **Output** | `{ additions: [{ employeeId: "e1", employeeName: "刘大壮", reason: "新入职", base: 8500 }], reductions: [], current: [{ employeeId: "e1", employeeName: "刘大壮", base: 8500 }] }` | + +### TC-SOC-010 公积金月度变动 + +| 项目 | 内容 | +|------|------| +| **Input** | `month: "2026-08"` | +| **Process** | GET `/api/v1/social/housing/monthly-changes?month=2026-08` | +| **Output** | `{ additions: [...], reductions: [...], current: [...] }` | + +### TC-SOC-011 完成月度办理 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ month: "2026-08", type: "social" }` | +| **Process** | POST `/api/v1/social/monthly-process/complete` `{ month: "2026-08", type: "social" }` | +| **Output** | HTTP 200,`{ success: true }`。状态更新为已完成 | + +### TC-SOC-012 专项附加扣除批量 + +| 项目 | 内容 | +|------|------| +| **Input** | `month: "2026-08"` | +| **Process** | GET `/api/v1/social/special-deduction/batch?month=2026-08` | +| **Output** | `[{ employeeId: "e1", employeeName: "刘大壮", housing: 1000, education: 1000, elderly: 0, total: 2000 }]` | + +### TC-SOC-013 保存专项附加扣除 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ employeeId: "e1", month: "2026-08", housing: 1000, education: 1000, elderly: 0, medical: 0 }` | +| **Process** | POST `/api/v1/social/special-deduction` | +| **Output** | HTTP 200,`{ success: true }` | + +### TC-SOC-014 活跃申报员工 + +| 项目 | 内容 | +|------|------| +| **Input** | `month: "2026-08"` | +| **Process** | GET `/api/v1/social/active-declaration?month=2026-08` | +| **Output** | `{ employees: [{ employeeId: "e1", employeeName: "刘大壮", base: 8500, socialStatus: "ACTIVE", housingStatus: "ACTIVE" }] }` | + +### TC-SOC-015 商业保险方案列表 + +| 项目 | 内容 | +|------|------| +| **Input** | 无 | +| **Process** | GET `/api/v1/commercial-insurance/plans` | +| **Output** | `[{ id: "ci1", name: "雇主责任险", insurer: "平安保险", premium: 200, coverage: 500000, enrolledCount: 6 }]` 或空数组 | + +### TC-SOC-016 创建商业保险方案 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ name: "雇主责任险", insurer: "平安保险", premium: 200, coverage: 500000, startDate: "2026-01-01", endDate: "2026-12-31" }` | +| **Process** | POST `/api/v1/commercial-insurance/plans` | +| **Output** | HTTP 201,`{ success: true, data: { id: "ci1", name: "雇主责任险" } }` | + +--- + +## 7. 解聘补偿域 + +### TC-TERM-001 解聘列表 + +| 项目 | 内容 | +|------|------| +| **Input** | `status: "", department: ""` | +| **Process** | GET `/api/v1/termination/drafts` | +| **Output** | `{ data: [], pagination: { total: 0 } }` 或 `[{ id: "t1", employeeName: "刘大壮", reason: "协商解除", status: "DRAFT", estimatedCompensation: 8500 }]` | + +### TC-TERM-002 创建解聘草稿 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ employeeId: "e1", reason: "协商解除", reasonDetail: "业务调整", lastDay: "2026-08-31" }` | +| **Process** | POST `/api/v1/termination/draft` | +| **Output** | HTTP 201,`{ success: true, data: { id: "td1", employeeId: "e1", employeeName: "刘大壮", reason: "协商解除", status: "DRAFT" } }` | + +### TC-TERM-003 解聘风险评估 + +| 项目 | 内容 | +|------|------| +| **Input** | `employeeId: "e1", reason: "协商解除"` | +| **Process** | GET `/api/v1/termination/assess/e1?reason=协商解除` | +| **Output** | `{ riskLevel: "LOW", riskScore: 20, factors: [{ factor: "入职年限", description: "入职4.4年", impact: "medium" }, { factor: "合同状态", description: "合同已到期", impact: "low" }], recommendations: ["建议协商解除,支付N经济补偿"] }` | + +### TC-TERM-004 解聘清单 + +| 项目 | 内容 | +|------|------| +| **Input** | `reason: "协商解除", employeeId: "e1"` | +| **Process** | GET `/api/v1/termination/checklist/协商解除?employeeId=e1` | +| **Output** | `{ items: [{ id: "cl1", title: "解除协议签署", required: true, completed: false }, { id: "cl2", title: "经济补偿支付", required: true, completed: false }, { id: "cl3", title: "工作交接", required: true, completed: false }, { id: "cl4", title: "社保公积金减员", required: true, completed: false }] }` | + +### TC-TERM-005 更新草稿 + +| 项目 | 内容 | +|------|------| +| **Input** | `draftId: "td1"`, `{ reason: "协商解除", compensation: 37400, compensationMonths: 4.4, lastDay: "2026-08-31", checklist: [{ id: "cl1", completed: true }] }` | +| **Process** | PUT `/api/v1/termination/draft/td1` | +| **Output** | HTTP 200,`{ success: true }` | + +### TC-TERM-006 提交审批 + +| 项目 | 内容 | +|------|------| +| **Input** | `draftId: "td1"` | +| **Process** | POST `/api/v1/termination/draft/td1/submit` | +| **Output** | HTTP 200,`{ success: true }`。状态变为 `PENDING_APPROVAL` | + +### TC-TERM-007 审批通过 + +| 项目 | 内容 | +|------|------| +| **Input** | `draftId: "td1"`, `comment: "同意解聘,补偿金额合理"` | +| **Process** | POST `/api/v1/termination/draft/td1/approve` `{ comment: "同意解聘,补偿金额合理" }` | +| **Output** | HTTP 200,`{ success: true }`。状态变为 `APPROVED` | + +### TC-TERM-008 审批驳回 + +| 项目 | 内容 | +|------|------| +| **Input** | `draftId: "td2"`, `comment: "补偿金额过高,请重新核算"` | +| **Process** | POST `/api/v1/termination/draft/td2/reject` `{ comment: "补偿金额过高,请重新核算" }` | +| **Output** | HTTP 200,`{ success: true }`。状态变为 `DRAFT`,附带驳回意见 | + +### TC-TERM-009 执行解聘 + +| 项目 | 内容 | +|------|------| +| **Input** | `draftId: "td1"` | +| **Process** | POST `/api/v1/termination/draft/td1/execute` | +| **Output** | HTTP 200,`{ success: true }`。状态变为 `EXECUTED`,员工状态变为 `RESIGNED`,社保公积金自动减员 | + +### TC-TERM-010 撤销解聘 + +| 项目 | 内容 | +|------|------| +| **Input** | `draftId: "td1"` | +| **Process** | POST `/api/v1/termination/draft/td1/cancel` | +| **Output** | HTTP 200,`{ success: true }`。状态变为 `CANCELLED` | + +### TC-TERM-011 撤回离职记录 + +| 项目 | 内容 | +|------|------| +| **Input** | `recordId: "tr1"` | +| **Process** | DELETE `/api/v1/termination/tr1/revoke` | +| **Output** | HTTP 200,`{ success: true }`。员工状态恢复为 `ACTIVE` | + +### TC-TERM-012 批量预览 + +| 项目 | 内容 | +|------|------| +| **Input** | `items: [{ employeeId: "e1", reason: "协商解除" }, { employeeId: "e2", reason: "协商解除" }]` | +| **Process** | POST `/api/v1/termination/batch/preview` `{ items: [...] }` | +| **Output** | `{ data: [{ employeeId: "e1", employeeName: "刘大壮", estimatedCompensation: 37400, riskLevel: "LOW" }, { employeeId: "e2", employeeName: "陈秀英", estimatedCompensation: 7500, riskLevel: "LOW" }] }` | + +--- + +## 8. 合规风控域 + +### TC-RISK-001 风险中心列表 + +| 项目 | 内容 | +|------|------| +| **Input** | 已登录 | +| **Process** | GET `/api/v1/dashboard/risks` | +| **Output** | `[{ id: "r1", type: "CONTRACT", level: "high", priority: "URGENT", title: "刘大壮的合同已到期520天未续签", employeeName: "刘大壮", employeeId: "e1", deadline: "2026-08-04", actionUrl: "/roster" }, { id: "r2", type: "TERMINATION", level: "high", priority: "URGENT", title: "孙美丽处于孕期/哺乳期,解聘受限", employeeName: "孙美丽", employeeId: "e4", deadline: "2026-08-01" }, { id: "r3", type: "CONTRACT", level: "high", title: "孙美丽的合同已到期336天未续签", employeeName: "孙美丽" }, { id: "r4", type: "CONTRACT", level: "high", title: "陈秀英的合同已到期49天未续签", employeeName: "陈秀英" }]` | + +### TC-RISK-002 风险分布统计 + +| 项目 | 内容 | +|------|------| +| **Input** | 已登录 | +| **Process** | GET `/api/v1/dashboard`,解析 `topRisks` 和风险分布 | +| **Output** | `{ contractRisk: 3, salaryRisk: 0, terminationRisk: 1 }`。页面渲染风险分布饼图 | + +### TC-RISK-003 用工体检诊断 + +| 项目 | 内容 | +|------|------| +| **Input** | 已登录 | +| **Process** | GET `/api/v1/dashboard/health-check`;访问 `/tools/health-check` | +| **Output** | 6 维度评分:`{ contract: 100, salary_social: 100, attendance: 100, policy: 60, termination: 100, evidence: 20 }`,总分 80,等级 `warning` | + +### TC-RISK-004 体检诊断历史 + +| 项目 | 内容 | +|------|------| +| **Input** | 已登录 | +| **Process** | GET `/api/v1/dashboard/health-check/history` | +| **Output** | `[{ id: "hc1", year: 2025, totalScore: 75, level: "warning", createdAt: "2025-12-01" }, { id: "hc2", year: 2026, totalScore: 80, level: "warning", createdAt: "2026-01-01" }]` | + +### TC-RISK-005 保存体检诊断 + +| 项目 | 内容 | +|------|------| +| **Input** | 无(自动保存当前诊断快照) | +| **Process** | POST `/api/v1/dashboard/health-check/save` | +| **Output** | HTTP 200,`{ success: true, data: { id: "hc-new", year: 2026, totalScore: 80 } }` | + +### TC-RISK-006 医疗期计算器 + +| 项目 | 内容 | +|------|------| +| **Input** | `employeeId: "e1"` 或手动输入 `workYears: 4, age: 41, condition: "普通疾病"` | +| **Process** | 访问 `/tools/medical-period`,输入参数计算 | +| **Output** | `{ medicalPeriod: 6, description: "本单位工作年限4年,医疗期为6个月", startDate: "2026-08-01", endDate: "2027-01-31" }` | + +--- + +## 9. 规章制度域 + +### TC-POL-001 制度列表 + +| 项目 | 内容 | +|------|------| +| **Input** | `page: 1, pageSize: 10, status: ""` | +| **Process** | GET `/api/v1/policies?page=1&pageSize=10` | +| **Output** | `{ data: [], pagination: { total: 0 } }` 或 `[{ id: "p1", title: "员工考勤管理制度", status: "PUBLISHED", currentStep: 4, createdAt: "2026-07-01" }]` | + +### TC-POL-002 创建制度 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ title: "员工考勤管理制度", category: "考勤", content: "第一章 总则\n第一条 为规范..." }` | +| **Process** | POST `/api/v1/policies` | +| **Output** | HTTP 201,`{ success: true, data: { id: "p1", title: "员工考勤管理制度", status: "DRAFT", currentStep: 1 } }` | + +### TC-POL-003 制度详情 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "p1"` | +| **Process** | GET `/api/v1/policies/p1` | +| **Output** | `{ id: "p1", title: "员工考勤管理制度", category: "考勤", content: "第一章 总则...", status: "DRAFT", currentStep: 1, steps: [{ step: 1, name: "起草", completed: true }, { step: 2, name: "讨论", completed: false }, { step: 3, name: "协商", completed: false }, { step: 4, name: "公示", completed: false }] }` | + +### TC-POL-004 推进民主程序步骤 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "p1"`, `step: 2, note: "已组织职工代表大会讨论"` | +| **Process** | POST `/api/v1/policies/p1/advance-step` `{ step: 2, note: "已组织职工代表大会讨论" }` | +| **Output** | HTTP 200,`{ success: true }`。currentStep 变为 2,step 2 标记为 completed | + +### TC-POL-005 更新制度 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "p1"`, `{ title: "员工考勤管理制度(修订版)", content: "第一章 总则\n第一条..." }` | +| **Process** | PUT `/api/v1/policies/p1` | +| **Output** | HTTP 200,`{ success: true }` | + +### TC-POL-006 删除制度 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "p1"` | +| **Process** | DELETE `/api/v1/policies/p1` | +| **Output** | HTTP 200,`{ success: true }`。列表中该制度消失 | + +### TC-POL-007 阅读签收统计 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "p1"` | +| **Process** | GET `/api/v1/policies/p1/read-stats` | +| **Output** | `{ total: 6, read: 3, unread: 3, readRate: 50, details: [{ employeeId: "e1", employeeName: "刘大壮", readAt: "2026-08-01T10:00:00Z" }, { employeeId: "e2", employeeName: "陈秀英", readAt: null }] }` | + +--- + +## 10. AI 顾问域 + +### TC-AI-001 智能问答 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ type: "CHAT", question: "员工入职没签合同怎么办?" }` | +| **Process** | POST `/api/v1/ai/consultation` `{ type: "CHAT", question: "员工入职没签合同怎么办?" }` | +| **Output** | HTTP 200,`{ success: true, data: { conversationId: "conv1", answer: "根据《劳动合同法》第十条规定,建立劳动关系应当订立书面劳动合同。已建立劳动关系未同时订立书面劳动合同的,应当自用工之日起一个月内订立...", confidence: 0.92, sources: [{ title: "劳动合同法第十条", url: "" }] } }` | + +### TC-AI-002 上下文问答 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ question: "我们公司有多少人合同到期了?", context: { orgId: "xxx", employeeData: true } }` | +| **Process** | POST `/api/v1/ai/context-ask` | +| **Output** | `{ answer: "根据您的花名册数据,目前有3名员工合同已到期:刘大壮(到期520天)、孙美丽(到期336天)、陈秀英(到期49天)。建议尽快续签合同...", confidence: 0.88 }` | + +### TC-AI-003 合同审查 + +| 项目 | 内容 | +|------|------| +| **Input** | `contractText: "甲方:XX公司\n乙方:张三\n第一条 合同期限:本合同为固定期限劳动合同,自2026年1月1日起至2026年12月31日止..."` | +| **Process** | POST `/api/v1/ai/review` `{ contractText: "..." }` | +| **Output** | `{ reviewId: "rv1", issues: [{ severity: "HIGH", clause: "第一条", issue: "合同期限不足一年,试用期不得超过一个月", suggestion: "建议将试用期调整为不超过一个月" }, { severity: "MEDIUM", clause: "第三条", issue: "未约定加班费计算基数", suggestion: "建议明确加班费计算基数为基本工资" }], overallScore: 75, summary: "合同存在2处风险点,建议修改后签署" }` | + +### TC-AI-004 合同审查上传文件 + +| 项目 | 内容 | +|------|------| +| **Input** | `FormData { file: contract.pdf }` | +| **Process** | POST `/api/v1/ai/review/upload` (multipart/form-data) | +| **Output** | `{ extractedText: "甲方:XX公司\n乙方:...", fileName: "contract.pdf" }` | + +### TC-AI-005 案例匹配 + +| 项目 | 内容 | +|------|------| +| **Input** | `scenario: "员工试用期被辞退,公司未支付经济补偿"` | +| **Process** | POST `/api/v1/ai/match-case` `{ scenario: "员工试用期被辞退,公司未支付经济补偿" }` | +| **Output** | `{ cases: [{ id: "case1", title: "张某诉某科技公司违法解除劳动合同案", court: "北京市朝阳区人民法院", result: "劳动者胜诉", keyPoints: ["试用期辞退需证明不符合录用条件", "未支付经济补偿属于违法解除"], relevance: 0.92 }], summary: "类似案件中劳动者胜诉率较高,建议谨慎处理试用期辞退" }` | + +### TC-AI-006 案例转待办 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ caseId: "case1", action: "审查当前试用期辞退流程", assignee: "王建国" }` | +| **Process** | POST `/api/v1/ai/case-to-todo` | +| **Output** | HTTP 200,`{ success: true, data: { todoId: "todo-new", title: "审查当前试用期辞退流程" } }` | + +### TC-AI-007 风险预测 + +| 项目 | 内容 | +|------|------| +| **Input** | 已登录,访问 AI 顾问「风险预测」tab | +| **Process** | POST `/api/v1/ai/consultation` `{ type: "PREDICT" }` | +| **Output** | `{ predictions: [{ riskType: "CONTRACT_EXPIRY", description: "未来30天内无合同到期", severity: "LOW" }, { riskType: "TERMINATION_RISK", description: "孙美丽处于孕期,解聘受限", severity: "HIGH" }] }` | + +### TC-AI-008 对话历史 + +| 项目 | 内容 | +|------|------| +| **Input** | `type: "CHAT"` | +| **Process** | GET `/api/v1/ai/conversations?type=CHAT` | +| **Output** | `[{ id: "conv1", title: "员工入职没签合同怎么办?", type: "CHAT", createdAt: "2026-08-01T10:00:00Z", messageCount: 2 }, { id: "conv2", title: "加班费计算", type: "CHAT", createdAt: "2026-08-01T11:00:00Z" }]` | + +### TC-AI-009 删除对话 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "conv1"` | +| **Process** | DELETE `/api/v1/ai/conversations/conv1` | +| **Output** | HTTP 200,`{ success: true }`。对话从历史列表消失 | + +### TC-AI-010 RAG 知识库列表 + +| 项目 | 内容 | +|------|------| +| **Input** | 无 | +| **Process** | GET `/api/v1/ai/rag/list` | +| **Output** | `[{ id: "rag1", title: "劳动合同法全文", category: "法律条文", createdAt: "2026-01-01" }, { id: "rag2", title: "社保缴纳指南", category: "政策文件", createdAt: "2026-02-01" }]` | + +### TC-AI-011 RAG 添加知识 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ title: "2026年最低工资标准", content: "北京市2026年最低工资标准为2420元/月...", category: "政策文件" }` | +| **Process** | POST `/api/v1/ai/rag/add` | +| **Output** | HTTP 201,`{ success: true, data: { id: "rag-new", title: "2026年最低工资标准" } }` | + +### TC-AI-012 RAG 帮助搜索 + +| 项目 | 内容 | +|------|------| +| **Input** | `query: "试用期最长可以约定几个月", topK: 8` | +| **Process** | POST `/api/v1/ai/rag/help-search` `{ query: "试用期最长可以约定几个月", topK: 8 }` | +| **Output** | `{ results: [{ id: "rag1", title: "劳动合同法全文", snippet: "第十九条 劳动合同期限三个月以上不满一年的,试用期不得超过一个月...", score: 0.95 }] }` | + +--- + +## 11. 工作流程域 + +### TC-WP-001 工作流程列表 + +| 项目 | 内容 | +|------|------| +| **Input** | `page: 1, pageSize: 10, type: "", status: ""` | +| **Process** | GET `/api/v1/work-processes?page=1&pageSize=10` | +| **Output** | `{ data: [], pagination: { total: 0 } }` 或 `[{ id: "wp1", title: "8月入职办理-测试员工", type: "ONBOARDING", status: "DRAFT", createdAt: "2026-08-01" }]` | + +### TC-WP-002 创建工作流程 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ type: "ONBOARDING", title: "8月入职办理-测试员工", employeeId: "e-new", data: { hireDate: "2026-08-01", department: "生产车间", salary: 8000 } }` | +| **Process** | POST `/api/v1/work-processes` | +| **Output** | HTTP 201,`{ success: true, data: { id: "wp1", title: "8月入职办理-测试员工", type: "ONBOARDING", status: "DRAFT" } }` | + +### TC-WP-003 工作流程详情 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "wp1"` | +| **Process** | GET `/api/v1/work-processes/wp1` | +| **Output** | `{ id: "wp1", title: "8月入职办理-测试员工", type: "ONBOARDING", status: "DRAFT", data: { hireDate: "2026-08-01", department: "生产车间", salary: 8000 }, steps: [{ step: 1, name: "信息录入", completed: true }, { step: 2, name: "合同签署", completed: false }] }` | + +### TC-WP-004 提交工作流程 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "wp1"` | +| **Process** | POST `/api/v1/work-processes/wp1/submit` | +| **Output** | HTTP 200,`{ success: true }`。状态变为 `SUBMITTED` | + +### TC-WP-005 取消工作流程 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "wp1"` | +| **Process** | POST `/api/v1/work-processes/wp1/cancel` | +| **Output** | HTTP 200,`{ success: true }`。状态变为 `CANCELLED` | + +### TC-WP-006 删除工作流程 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "wp1"` | +| **Process** | DELETE `/api/v1/work-processes/wp1` | +| **Output** | HTTP 200,`{ success: true }`。从列表消失 | + +### TC-WP-007 工作流程预览 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "wp1"` | +| **Process** | GET `/api/v1/work-processes/wp1/preview` | +| **Output** | `{ preview: { documents: [{ name: "劳动合同", template: "劳动合同模板", variables: { employeeName: "测试员工", department: "生产车间", salary: 8000 } }], steps: [...] } }` | + +--- + +## 12. 特殊状态台账域 + +### TC-SS-001 特殊状态列表 + +| 项目 | 内容 | +|------|------| +| **Input** | `page: 1, pageSize: 10, search: "", type: "", status: ""` | +| **Process** | GET `/api/v1/special-statuses?page=1&pageSize=10` | +| **Output** | `{ data: [{ id: "ss1", employeeId: "e4", employeeName: "孙美丽", type: "PREGNANCY", status: "ACTIVE", startDate: "2026-01-01", endDate: "2026-12-31", description: "孕期" }], pagination: { total: 1 } }` | + +### TC-SS-002 统计概览 + +| 项目 | 内容 | +|------|------| +| **Input** | 无 | +| **Process** | GET `/api/v1/special-statuses/stats/overview` | +| **Output** | `{ total: 1, byType: { PREGNANCY: 1, INJURY: 0, ILLNESS: 0, MATERNITY: 0 }, byStatus: { ACTIVE: 1, EXPIRED: 0 } }` | + +### TC-SS-003 创建特殊状态 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ employeeId: "e1", type: "INJURY", startDate: "2026-08-01", endDate: "2026-10-01", description: "工伤休养期" }` | +| **Process** | POST `/api/v1/special-statuses` | +| **Output** | HTTP 201,`{ success: true, data: { id: "ss2", employeeName: "刘大壮", type: "INJURY", status: "ACTIVE" } }` | + +### TC-SS-004 更新特殊状态 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "ss2"`, `{ endDate: "2026-11-01", description: "工伤休养期延长" }` | +| **Process** | PUT `/api/v1/special-statuses/ss2` | +| **Output** | HTTP 200,`{ success: true }` | + +### TC-SS-005 删除特殊状态 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "ss2"` | +| **Process** | DELETE `/api/v1/special-statuses/ss2` | +| **Output** | HTTP 200,`{ success: true }` | + +--- + +## 13. 日历与事件域 + +### TC-CAL-001 月度日历 + +| 项目 | 内容 | +|------|------| +| **Input** | `month: "2026-08"` | +| **Process** | GET `/api/v1/dashboard/calendar?month=2026-08` | +| **Output** | `{ events: [{ id: "ev1", date: "2026-08-01", type: "RISK_DEADLINE", title: "孙美丽处于孕期/哺乳期,解聘受限 处理截止日", employeeName: "孙美丽" }, { id: "ev2", date: "2026-08-04", type: "RISK_DEADLINE", title: "陈秀英的合同已到期49天未续签 处理截止日", employeeName: "陈秀英" }, { id: "ev3", date: "2026-08-04", type: "RISK_DEADLINE", title: "刘大壮的合同已到期520天未续签 处理截止日", employeeName: "刘大壮" }] }` | + +### TC-CAL-002 自定义事件列表 + +| 项目 | 内容 | +|------|------| +| **Input** | `month: "2026-08"` | +| **Process** | GET `/api/v1/calendar?month=2026-08` | +| **Output** | `[{ id: "ce1", title: "月度全员会议", date: "2026-08-15", type: "MEETING", description: "8月工作总结" }]` 或空数组 | + +### TC-CAL-003 创建自定义事件 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ title: "团队建设活动", date: "2026-08-20", type: "TEAM_BUILDING", description: "秋季团建" }` | +| **Process** | POST `/api/v1/calendar` | +| **Output** | HTTP 201,`{ success: true, data: { id: "ce1", title: "团队建设活动", date: "2026-08-20", type: "TEAM_BUILDING" } }` | + +### TC-CAL-004 删除自定义事件 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "ce1"` | +| **Process** | DELETE `/api/v1/calendar/ce1` | +| **Output** | HTTP 200,`{ success: true }`。事件从日历消失 | + +### TC-CAL-005 日历事件筛选 + +| 项目 | 内容 | +|------|------| +| **Input** | 筛选类型 `type: "RISK_DEADLINE"` | +| **Process** | 前端筛选日历事件 | +| **Output** | 仅显示风险截止类事件,隐藏其他类型 | + +--- + +## 14. 通知管理域 + +### TC-NOT-001 通知日志列表 + +| 项目 | 内容 | +|------|------| +| **Input** | `page: 1, pageSize: 10` | +| **Process** | GET `/api/v1/notifications/logs?page=1&pageSize=10` | +| **Output** | `{ data: [], pagination: { total: 0 } }` 或 `[{ id: "n1", type: "CONTRACT_EXPIRY", channel: "wechat", recipient: "王建国", status: "SENT", sentAt: "2026-08-01T10:00:00Z", content: "您有3名员工合同已到期" }]` | + +### TC-NOT-002 通知设置 + +| 项目 | 内容 | +|------|------| +| **Input** | 无(查看) | +| **Process** | GET `/api/v1/notifications/settings` | +| **Output** | `{ contractExpiryDays: 30, unsignedContractEnabled: true, overtimeAlertEnabled: true, payslipNotificationEnabled: true, channels: { wechat: true, email: false } }` | + +### TC-NOT-003 更新通知设置 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ contractExpiryDays: 60, unsignedContractEnabled: true, overtimeAlertEnabled: false, payslipNotificationEnabled: true, channels: { wechat: true, email: true } }` | +| **Process** | PUT `/api/v1/notifications/settings` | +| **Output** | HTTP 200,`{ success: true }`。页面显示「提前 60 天」 | + +### TC-NOT-004 检查合同到期 + +| 项目 | 内容 | +|------|------| +| **Input** | 无 | +| **Process** | POST `/api/v1/notifications/check-contracts` | +| **Output** | HTTP 200,`{ success: true, data: { checked: 6, alerts: 3 } }`。生成合同到期通知 | + +### TC-NOT-005 测试通知发送 + +| 项目 | 内容 | +|------|------| +| **Input** | `channel: "wechat"` | +| **Process** | POST `/api/v1/notifications/test` `{ channel: "wechat" }` | +| **Output** | HTTP 200,`{ success: true, message: "测试通知已发送" }` | + +--- + +## 15. 系统设置域 + +### TC-SET-001 企业信息 + +| 项目 | 内容 | +|------|------| +| **Input** | 无(查看) | +| **Process** | GET `/api/v1/settings/org` | +| **Output** | `{ id: "org1", name: "北京智造科技有限公司", contactName: "王建国", contactPhone: "13800000010", city: "北京", plan: "PRO", payrollFrequency: 1, retirementReminderEnabled: true }` | + +### TC-SET-002 更新企业信息 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ name: "北京智造科技有限公司(更新)", contactName: "王建国", contactPhone: "13800000010", payrollFrequency: 2 }` | +| **Process** | PUT `/api/v1/settings/org` | +| **Output** | HTTP 200,`{ success: true }`。发薪次数更新为「2次(半月一批)」 | + +### TC-SET-003 用户列表 + +| 项目 | 内容 | +|------|------| +| **Input** | 无 | +| **Process** | GET `/api/v1/settings/users` | +| **Output** | `[{ id: "u1", name: "王建国", phone: "13800000010", role: "ADMIN", disabled: false, createdAt: "2026-01-01" }]` | + +### TC-SET-004 添加用户 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ name: "李HR", phone: "13900008888", password: "Hr123456", role: "HR" }` | +| **Process** | POST `/api/v1/settings/users` | +| **Output** | HTTP 201,`{ success: true, data: { id: "u2", name: "李HR", phone: "13900008888", role: "HR" } }` | + +### TC-SET-005 更新用户 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "u2"`, `{ name: "李人事", role: "HR" }` | +| **Process** | PUT `/api/v1/settings/users/u2` | +| **Output** | HTTP 200,`{ success: true }` | + +### TC-SET-006 切换用户禁用状态 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "u2"` | +| **Process** | PATCH `/api/v1/settings/users/u2/toggle-disable` | +| **Output** | HTTP 200,`{ success: true, data: { disabled: true } }`。用户被禁用,无法登录 | + +### TC-SET-007 用量统计 + +| 项目 | 内容 | +|------|------| +| **Input** | 无 | +| **Process** | GET `/api/v1/settings/usage` | +| **Output** | `{ plan: "PRO", maxEmployees: 100, currentEmployees: 6, usagePercent: 6, features: { aiConsultation: true, contractReview: true, batchImport: true } }` | + +### TC-SET-008 更新套餐 + +| 项目 | 内容 | +|------|------| +| **Input** | `plan: "ENTERPRISE"` | +| **Process** | PUT `/api/v1/settings/plan` `{ plan: "ENTERPRISE" }` | +| **Output** | HTTP 200,`{ success: true }`。套餐更新为 ENTERPRISE | + +### TC-SET-009 退休政策 + +| 项目 | 内容 | +|------|------| +| **Input** | 无 | +| **Process** | GET `/api/v1/settings/retirement-policy` | +| **Output** | `{ id: "rp1", version: "v1", status: "PENDING_CONFIRMATION", rules: { male: { baseAge: 60, targetAge: 63, stepMonths: 4 }, femaleCadre: { baseAge: 55, targetAge: 58, stepMonths: 4 }, femaleWorker: { baseAge: 50, targetAge: 55, stepMonths: 2 } } }` | + +### TC-SET-010 确认退休政策生效 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "rp1"` | +| **Process** | POST `/api/v1/settings/retirement-policy/rp1/confirm` | +| **Output** | HTTP 200,`{ success: true }`。状态变为 `ACTIVE` | + +--- + +## 16. 模板管理域 + +### TC-TPL-001 系统模板列表 + +| 项目 | 内容 | +|------|------| +| **Input** | `category: ""` 或 `category: "合同"` | +| **Process** | GET `/api/v1/templates` 或 GET `/api/v1/templates?category=合同` | +| **Output** | `[{ id: "t1", name: "固定期限劳动合同模板", category: "合同", variables: ["employeeName", "department", "startDate", "endDate"] }, { id: "t2", name: "解除协议模板", category: "解聘", variables: ["employeeName", "compensation", "lastDay"] }]` | + +### TC-TPL-002 系统模板详情 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "t1"` | +| **Process** | GET `/api/v1/templates/t1` | +| **Output** | `{ id: "t1", name: "固定期限劳动合同模板", category: "合同", content: "甲方:{{orgName}}\n乙方:{{employeeName}}\n...", variables: [{ key: "employeeName", label: "员工姓名" }, { key: "department", label: "部门" }] }` | + +### TC-TPL-003 渲染系统模板 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "t1"`, `variables: { orgName: "北京智造科技", employeeName: "测试员工", department: "生产车间", startDate: "2026-08-01", endDate: "2029-07-31" }` | +| **Process** | POST `/api/v1/templates/t1/render` `{ variables: {...} }` | +| **Output** | `{ rendered: "甲方:北京智造科技\n乙方:测试员工\n..." }` | + +### TC-TPL-004 企业模板列表 + +| 项目 | 内容 | +|------|------| +| **Input** | `page: 1, pageSize: 10, category: ""` | +| **Process** | GET `/api/v1/enterprise-templates?page=1&pageSize=10` | +| **Output** | `{ data: [], pagination: { total: 0 } }` 或 `[{ id: "et1", name: "公司入职须知", category: "入职", createdAt: "2026-07-01" }]` | + +### TC-TPL-005 创建企业模板 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ name: "公司入职须知", category: "入职", content: "欢迎加入{{orgName}}...", variables: [{ key: "orgName", label: "企业名称" }] }` | +| **Process** | POST `/api/v1/enterprise-templates` | +| **Output** | HTTP 201,`{ success: true, data: { id: "et1", name: "公司入职须知" } }` | + +### TC-TPL-006 更新企业模板 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "et1"`, `{ name: "公司入职须知(2026版)", content: "..." }` | +| **Process** | PUT `/api/v1/enterprise-templates/et1` | +| **Output** | HTTP 200,`{ success: true }` | + +### TC-TPL-007 删除企业模板 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "et1"` | +| **Process** | DELETE `/api/v1/enterprise-templates/et1` | +| **Output** | HTTP 200,`{ success: true }` | + +### TC-TPL-008 渲染企业模板 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "et1"`, `variables: { orgName: "北京智造科技" }` | +| **Process** | POST `/api/v1/enterprise-templates/et1/render` `{ variables: { orgName: "北京智造科技" } }` | +| **Output** | `{ rendered: "欢迎加入北京智造科技..." }` | + +--- + +## 17. 证据链域 + +### TC-EVID-001 证据链列表 + +| 项目 | 内容 | +|------|------| +| **Input** | `page: 1, pageSize: 10, category: ""` | +| **Process** | GET `/api/v1/evidence?page=1&pageSize=10` | +| **Output** | `{ data: [], pagination: { total: 0 } }` 或 `[{ id: "ev1", category: "ONBOARDING", employeeName: "刘大壮", action: "入职登记", hash: "a1b2c3...", timestamp: "2022-03-01T08:00:00Z", verified: true }]` | + +### TC-EVID-002 全量验证 + +| 项目 | 内容 | +|------|------| +| **Input** | 无 | +| **Process** | GET `/api/v1/evidence/verify-all` | +| **Output** | `{ total: 0, verified: 0, failed: 0, details: [] }` 或 `{ total: 15, verified: 14, failed: 1, details: [{ id: "ev1", status: "VERIFIED" }, { id: "ev2", status: "FAILED", reason: "hash mismatch" }] }` | + +### TC-EVID-003 按类别筛选 + +| 项目 | 内容 | +|------|------| +| **Input** | `category: "CONTRACT"` | +| **Process** | GET `/api/v1/evidence?category=CONTRACT` | +| **Output** | `{ data: [{ id: "ev1", category: "CONTRACT", employeeName: "刘大壮", action: "合同签署" }], pagination: { total: 1 } }` | + +--- + +## 18. 公司文件域 + +### TC-CF-001 文件列表 + +| 项目 | 内容 | +|------|------| +| **Input** | `fileType: ""` 或 `fileType: "营业执照"` | +| **Process** | GET `/api/v1/company-files` | +| **Output** | `[{ id: "f1", name: "营业执照.pdf", fileType: "营业执照", url: "/uploads/biz-license.pdf", uploadedAt: "2026-01-01" }]` 或空数组 | + +### TC-CF-002 添加文件 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ name: "营业执照.pdf", fileType: "营业执照", url: "/uploads/biz-license.pdf" }` | +| **Process** | POST `/api/v1/company-files` | +| **Output** | HTTP 201,`{ success: true, data: { id: "f1", name: "营业执照.pdf" } }` | + +### TC-CF-003 删除文件 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "f1"` | +| **Process** | DELETE `/api/v1/company-files/f1` | +| **Output** | HTTP 200,`{ success: true }` | + +--- + +## 19. 审计日志域 + +### TC-AUD-001 审计日志列表 + +| 项目 | 内容 | +|------|------| +| **Input** | `page: 1, pageSize: 10, entity: "", dateFrom: "", dateTo: ""` | +| **Process** | GET `/api/v1/audit?page=1&pageSize=10` | +| **Output** | `{ data: [{ id: "al1", entity: "EMPLOYEE", action: "CREATE", operator: "王建国", target: "测试员工", timestamp: "2026-08-01T10:00:00Z", details: "创建员工档案" }], pagination: { total: 1 } }` | + +### TC-AUD-002 审计统计 + +| 项目 | 内容 | +|------|------| +| **Input** | 无 | +| **Process** | GET `/api/v1/audit/stats` | +| **Output** | `{ total: 15, byAction: { CREATE: 6, UPDATE: 5, DELETE: 2, LOGIN: 2 }, byEntity: { EMPLOYEE: 8, PAYROLL: 4, CONTRACT: 3 } }` | + +### TC-AUD-003 按实体筛选 + +| 项目 | 内容 | +|------|------| +| **Input** | `entity: "EMPLOYEE"` | +| **Process** | GET `/api/v1/audit?entity=EMPLOYEE` | +| **Output** | `{ data: [{ id: "al1", entity: "EMPLOYEE", action: "CREATE", operator: "王建国" }], pagination: { total: 8 } }` | + +### TC-AUD-004 按日期范围筛选 + +| 项目 | 内容 | +|------|------| +| **Input** | `dateFrom: "2026-08-01", dateTo: "2026-08-31"` | +| **Process** | GET `/api/v1/audit?dateFrom=2026-08-01&dateTo=2026-08-31` | +| **Output** | `{ data: [...], pagination: { total: 5 } }`。仅显示该日期范围内的日志 | + +--- + +## 20. 薪酬分析仪表盘域 + +### TC-SAL-001 薪酬仪表盘 + +| 项目 | 内容 | +|------|------| +| **Input** | `year: 2026` | +| **Process** | GET `/api/v1/salary/dashboard?year=2026` | +| **Output** | `{ year: 2026, monthly: [{ month: "2026-01", totalPay: 53000, avgPay: 8833, headcount: 6 }, ...], departmentSalary: [{ department: "生产车间", avgSalary: 8333 }, { department: "行政部", avgSalary: 11000 }], salaryDistribution: [{ range: "5K-10K", count: 4 }, { range: "10K-15K", count: 2 }], yoyChange: 0 }` | + +--- + +## 21. 平台管理端域 + +### TC-PLAT-001 平台登录 + +| 项目 | 内容 | +|------|------| +| **Input** | `phone: "superadmin"`, `password: "xxx"`(SUPER_ADMIN 账号) | +| **Process** | POST `/api/v1/auth/platform-login` | +| **Output** | HTTP 200,`{ success: true, data: { user: { role: "SUPER_ADMIN" }, accessToken: "..." } }`。跳转至 `/platform/dashboard` | + +### TC-PLAT-002 平台仪表盘 + +| 项目 | 内容 | +|------|------| +| **Input** | 已登录 SUPER_ADMIN | +| **Process** | GET `/api/v1/platform/dashboard` | +| **Output** | `{ totalOrgs: 3, totalUsers: 3, totalEmployees: 18, byPlan: { FREE: 1, PRO: 1, ENTERPRISE: 1 }, recentSignups: [...] }` | + +### TC-PLAT-003 组织列表 + +| 项目 | 内容 | +|------|------| +| **Input** | `page: 1, pageSize: 10, search: "", plan: ""` | +| **Process** | GET `/api/v1/platform/orgs?page=1&pageSize=10` | +| **Output** | `{ data: [{ id: "org1", name: "北京智造科技有限公司", plan: "PRO", maxEmployees: 100, currentEmployees: 6, adminName: "王建国", adminPhone: "13800000010", city: "北京", createdAt: "2026-01-01" }, { id: "org2", name: "深圳物流有限公司", plan: "ENTERPRISE", ... }, { id: "org3", name: "杭州科技工作室", plan: "FREE", ... }], pagination: { total: 3 } }` | + +### TC-PLAT-004 组织搜索 + +| 项目 | 内容 | +|------|------| +| **Input** | `search: "北京"` | +| **Process** | GET `/api/v1/platform/orgs?search=北京` | +| **Output** | `{ data: [{ id: "org1", name: "北京智造科技有限公司", plan: "PRO" }], pagination: { total: 1 } }` | + +### TC-PLAT-005 组织详情 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "org1"` | +| **Process** | GET `/api/v1/platform/orgs/org1` | +| **Output** | `{ id: "org1", name: "北京智造科技有限公司", plan: "PRO", maxEmployees: 100, currentEmployees: 6, adminName: "王建国", adminPhone: "13800000010", city: "北京", contactName: "王建国", contactPhone: "13800000010", payrollFrequency: 1, retirementReminderEnabled: true, socialConfig: { city: "北京", baseMin: 6326, baseMax: 33891 } }` | + +### TC-PLAT-006 创建组织 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ name: "测试新企业", contactName: "测试管理员", contactPhone: "13900007777", adminPhone: "13900007777", adminName: "测试管理员", city: "上海", plan: "PRO", maxEmployees: 50, payrollFrequency: 1 }` | +| **Process** | POST `/api/v1/platform/orgs` | +| **Output** | HTTP 201,`{ success: true, data: { id: "org-new", name: "测试新企业" } }` | + +### TC-PLAT-007 更新组织 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "org1"`, `{ name: "北京智造科技有限公司(更新)", plan: "ENTERPRISE", maxEmployees: 200 }` | +| **Process** | PUT `/api/v1/platform/orgs/org1` | +| **Output** | HTTP 200,`{ success: true }` | + +### TC-PLAT-008 更新组织管理员 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "org1"`, `{ adminName: "王建国", adminPhone: "13800000010", password: "NewPass123" }` | +| **Process** | PUT `/api/v1/platform/orgs/org1/admin` | +| **Output** | HTTP 200,`{ success: true }` | + +### TC-PLAT-009 删除组织 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "org-new"` | +| **Process** | DELETE `/api/v1/platform/orgs/org-new` | +| **Output** | HTTP 200,`{ success: true }` | + +### TC-PLAT-010 平台用户列表 + +| 项目 | 内容 | +|------|------| +| **Input** | `page: 1, pageSize: 10, search: "", orgId: ""` | +| **Process** | GET `/api/v1/platform/users?page=1&pageSize=10` | +| **Output** | `{ data: [{ id: "u1", name: "王建国", phone: "13800000010", role: "ADMIN", orgName: "北京智造科技有限公司", disabled: false }, { id: "u2", name: "李明华", phone: "13800000020", role: "ADMIN", orgName: "深圳物流有限公司" }], pagination: { total: 3 } }` | + +### TC-PLAT-011 切换用户状态 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "u2"` | +| **Process** | PUT `/api/v1/platform/users/u2/toggle` | +| **Output** | HTTP 200,`{ success: true, data: { disabled: true } }` | + +--- + +## 22. 员工端 Portal 域 + +### TC-PORTAL-001 员工端登录(密码) + +| 项目 | 内容 | +|------|------| +| **Input** | `phone: "13900001001"`, `password: "xxx"`(员工密码) | +| **Process** | POST `/api/v1/portal/login` `{ phone: "13900001001", password: "xxx" }` | +| **Output** | HTTP 200,`{ success: true, data: { employee: { id: "e1", name: "刘大壮", department: "生产车间" }, token: "portal-token-xxx" } }`。localStorage 保存 portalToken 和 portalEmployee | + +### TC-PORTAL-002 员工端登录(验证码) + +| 项目 | 内容 | +|------|------| +| **Input** | 1. `phone: "13900001001"` → 2. `phone: "13900001001", code: "123456"` | +| **Process** | 1. POST `/api/v1/portal/send-code` `{ phone: "13900001001" }`;2. POST `/api/v1/portal/verify-code` `{ phone: "13900001001", code: "123456" }` | +| **Output** | 第一步 HTTP 200 `{ success: true, message: "验证码已发送" }`;第二步 HTTP 200 `{ success: true, data: { employee: {...}, token: "xxx" } }` | + +### TC-PORTAL-003 自动登录(Token) + +| 项目 | 内容 | +|------|------| +| **Input** | `token: "auto-login-token-xxx"` | +| **Process** | GET `/api/v1/portal/auto-login?token=auto-login-token-xxx` | +| **Output** | HTTP 200,`{ success: true, data: { employee: {...}, token: "xxx" } }`。自动登录并跳转至 `/portal/home` | + +### TC-PORTAL-004 首页概览 + +| 项目 | 内容 | +|------|------| +| **Input** | 已登录员工端 | +| **Process** | GET `/api/v1/portal/home/overview` | +| **Output** | `{ employee: { name: "刘大壮", department: "生产车间", hireDate: "2022-03-01" }, latestPayslip: { month: "2026-07", totalPay: 8500 }, contractStatus: "EXPIRED", unreadPolicies: 0 }` | + +### TC-PORTAL-005 工资条 + +| 项目 | 内容 | +|------|------| +| **Input** | `month: "2026-07"` | +| **Process** | GET `/api/v1/portal/payslip?month=2026-07` | +| **Output** | `{ month: "2026-07", baseSalary: 8500, overtimePay: 0, allowance: 0, bonus: 0, socialEmp: 892.5, housingEmp: 850, tax: 540.75, netPay: 6217.75, confirmed: false }` | + +### TC-PORTAL-006 工资条历史 + +| 项目 | 内容 | +|------|------| +| **Input** | 无 | +| **Process** | GET `/api/v1/portal/payslip/history` | +| **Output** | `[{ id: "ps1", month: "2026-07", netPay: 6217.75, confirmed: false }, { id: "ps2", month: "2026-06", netPay: 6217.75, confirmed: true }]` | + +### TC-PORTAL-007 确认工资条 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "ps1"` | +| **Process** | POST `/api/v1/portal/payslip/ps1/confirm` | +| **Output** | HTTP 200,`{ success: true }`。工资条状态变为 `CONFIRMED` | + +### TC-PORTAL-008 我的合同 + +| 项目 | 内容 | +|------|------| +| **Input** | 无 | +| **Process** | GET `/api/v1/portal/contract` | +| **Output** | `{ contract: { id: "c1", type: "FIXED", startDate: "2022-03-01", endDate: "2025-02-27", status: "EXPIRED", monthlySalary: 8500 } }` 或 `{ contract: null }` | + +### TC-PORTAL-009 合同确认(发送验证码) + +| 项目 | 内容 | +|------|------| +| **Input** | `token: "contract-confirm-token-xxx"` | +| **Process** | POST `/api/v1/portal/contract-confirm/send-code` `{ token: "contract-confirm-token-xxx" }` | +| **Output** | HTTP 200,`{ success: true, message: "验证码已发送至手机" }` | + +### TC-PORTAL-010 合同确认(提交) + +| 项目 | 内容 | +|------|------| +| **Input** | `token: "contract-confirm-token-xxx"`, `verifyCode: "123456"` | +| **Process** | POST `/api/v1/portal/contract-confirm` `{ token: "xxx", agreed: true, verifyCode: "123456" }` | +| **Output** | HTTP 200,`{ success: true, message: "合同确认成功" }` | + +### TC-PORTAL-011 我的考勤 + +| 项目 | 内容 | +|------|------| +| **Input** | `month: "2026-08"` | +| **Process** | GET `/api/v1/portal/attendance?month=2026-08` | +| **Output** | `{ month: "2026-08", records: [{ date: "2026-08-01", checkIn: "08:50", checkOut: "18:10", status: "NORMAL" }], summary: { normalDays: 22, lateTimes: 0, overtimeHours: 0 } }` | + +### TC-PORTAL-012 制度列表 + +| 项目 | 内容 | +|------|------| +| **Input** | 无 | +| **Process** | GET `/api/v1/portal/policies` | +| **Output** | `[{ id: "p1", title: "员工考勤管理制度", category: "考勤", read: false, publishedAt: "2026-07-01" }]` 或空数组 | + +### TC-PORTAL-013 制度详情 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "p1"` | +| **Process** | GET `/api/v1/portal/policies/p1` | +| **Output** | `{ id: "p1", title: "员工考勤管理制度", content: "第一章 总则...", publishedAt: "2026-07-01" }` | + +### TC-PORTAL-014 制度阅读确认 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "p1"` | +| **Process** | POST `/api/v1/portal/policies/p1/read` | +| **Output** | HTTP 200,`{ success: true }`。制度标记为已读 | + +### TC-PORTAL-015 入职信息 + +| 项目 | 内容 | +|------|------| +| **Input** | `token: "onboarding-token-xxx"` | +| **Process** | GET `/api/v1/portal/onboarding/onboarding-token-xxx` | +| **Output** | `{ token: "xxx", orgName: "北京智造科技有限公司", position: "生产车间工人", expectedHireDate: "2026-08-01", requirements: ["身份证复印件", "学历证明", "体检报告"] }` | + +### TC-PORTAL-016 入职提交 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ token: "onboarding-token-xxx", name: "张三", gender: "男", idCard: "110101199001011001", phone: "13900009999", bank: "工商银行", account: "6222020100019999", emergencyContact: "张父", emergencyPhone: "13800009998", address: "北京市朝阳区测试路1号" }` | +| **Process** | POST `/api/v1/portal/onboarding` | +| **Output** | HTTP 200,`{ success: true, message: "入职信息提交成功" }` | + +### TC-PORTAL-017 入职文件上传 + +| 项目 | 内容 | +|------|------| +| **Input** | `token: "onboarding-token-xxx"`, `FormData { file: id-card.jpg }` | +| **Process** | POST `/api/v1/portal/onboarding/onboarding-token-xxx/upload` (multipart/form-data) | +| **Output** | HTTP 200,`{ success: true, data: { url: "/uploads/onboarding/id-card.jpg" } }` | + +### TC-PORTAL-018 入职进度 + +| 项目 | 内容 | +|------|------| +| **Input** | 无(已登录员工端) | +| **Process** | GET `/api/v1/portal/onboarding/progress` | +| **Output** | `{ steps: [{ step: 1, name: "信息填写", completed: true }, { step: 2, name: "文件上传", completed: true }, { step: 3, name: "HR审核", completed: false }], currentStep: 3, status: "PENDING" }` | + +### TC-PORTAL-019 离职申请状态 + +| 项目 | 内容 | +|------|------| +| **Input** | 无 | +| **Process** | GET `/api/v1/portal/resignation/status` | +| **Output** | `[]` 或 `[{ id: "rg1", reason: "个人发展", status: "PENDING", submittedAt: "2026-08-01" }]` | + +### TC-PORTAL-020 提交离职申请 + +| 项目 | 内容 | +|------|------| +| **Input** | `{ reason: "个人发展", expectedLastDay: "2026-09-01", description: "感谢公司培养" }` | +| **Process** | POST `/api/v1/portal/resignation/submit` | +| **Output** | HTTP 201,`{ success: true, data: { id: "rg1", status: "PENDING" } }` | + +### TC-PORTAL-021 撤回离职申请 + +| 项目 | 内容 | +|------|------| +| **Input** | `id: "rg1"` | +| **Process** | POST `/api/v1/portal/resignation/rg1/withdraw` | +| **Output** | HTTP 200,`{ success: true }`。状态变为 `WITHDRAWN` | + +### TC-PORTAL-022 重发合同确认链接 + +| 项目 | 内容 | +|------|------| +| **Input** | `contractId: "c1"`(管理端操作) | +| **Process** | POST `/api/v1/portal/contract-confirm/resend` `{ contractId: "c1" }` | +| **Output** | HTTP 200,`{ success: true, message: "合同确认链接已重新发送" }` | + +### TC-PORTAL-023 生成自动登录令牌 + +| 项目 | 内容 | +|------|------| +| **Input** | `employeeId: "e1"`(管理端操作) | +| **Process** | POST `/api/v1/portal/auto-login-token` `{ employeeId: "e1" }` | +| **Output** | HTTP 200,`{ success: true, data: { token: "auto-login-xxx", url: "/portal/auto-login?token=auto-login-xxx" } }` | + +--- + +## 23. 数据导入导出域 + +### TC-IMP-001 员工批量导入 + +| 项目 | 内容 | +|------|------| +| **Input** | `FormData { file: employees.xlsx }` | +| **Process** | POST `/api/v1/import/employees` (multipart/form-data) | +| **Output** | HTTP 200,`{ success: true, data: { total: 10, success: 9, failed: 1, errors: [{ row: 5, message: "身份证号格式不正确" }] } }` | + +### TC-IMP-002 考勤批量导入 + +| 项目 | 内容 | +|------|------| +| **Input** | `FormData { file: attendance.xlsx, month: "2026-08" }` | +| **Process** | POST `/api/v1/import/attendance` (multipart/form-data) | +| **Output** | HTTP 200,`{ success: true, data: { total: 120, success: 118, failed: 2, errors: [{ row: 15, message: "员工不存在" }] } }` | + +### TC-IMP-003 加班费批量导入 + +| 项目 | 内容 | +|------|------| +| **Input** | `items: [{ employeeId: "e1", month: "2026-08", weekdayHours: 10, weekendHours: 8 }]` | +| **Process** | POST `/api/v1/payroll/overtime/batch` `{ items: [...] }` | +| **Output** | HTTP 200,`{ success: true, data: { imported: 1 } }` | + +### TC-EXP-001 花名册导出 + +| 项目 | 内容 | +|------|------| +| **Input** | `status: "ACTIVE", department: ""` | +| **Process** | GET `/api/v1/export/roster?status=ACTIVE`(触发文件下载) | +| **Output** | HTTP 200,Content-Type: `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`,下载 `花名册_2026-08-01.xlsx`,包含 6 条员工记录 | + +### TC-EXP-002 工资条导出 + +| 项目 | 内容 | +|------|------| +| **Input** | `batchId: "b1"` | +| **Process** | GET `/api/v1/export/payslip?batchId=b1` | +| **Output** | HTTP 200,下载 `工资条_2026-08.xlsx`,包含 6 条工资条明细 | + +### TC-EXP-003 解聘记录导出 + +| 项目 | 内容 | +|------|------| +| **Input** | `status: ""` | +| **Process** | GET `/api/v1/export/termination` | +| **Output** | HTTP 200,下载 `解聘记录_2026-08-01.xlsx` | + +### TC-EXP-004 考勤月报导出 + +| 项目 | 内容 | +|------|------| +| **Input** | `month: "2026-08"` | +| **Process** | GET `/api/v1/export/attendance?month=2026-08` | +| **Output** | HTTP 200,下载 `考勤月报_2026-08.xlsx` | + +--- + +## 24. 全局搜索与命令面板域 + +### TC-SEARCH-001 全局搜索 + +| 项目 | 内容 | +|------|------| +| **Input** | `q: "刘大壮"` | +| **Process** | GET `/api/v1/search?q=刘大壮` | +| **Output** | `{ employees: [{ id: "e1", name: "刘大壮", department: "生产车间", type: "EMPLOYEE" }], contracts: [], policies: [] }` | + +### TC-SEARCH-002 命令面板 + +| 项目 | 内容 | +|------|------| +| **Input** | 已登录,按下 `Cmd+K`(macOS)或 `Ctrl+K`(Windows) | +| **Process** | 触发 CommandPalette 打开 | +| **Output** | 弹出命令面板浮层,输入「花名册」可快速跳转至 `/roster`,输入「薪酬」可跳转至 `/money` | + +### TC-SEARCH-003 搜索无结果 + +| 项目 | 内容 | +|------|------| +| **Input** | `q: "不存在的员工xyz"` | +| **Process** | GET `/api/v1/search?q=不存在的员工xyz` | +| **Output** | `{ employees: [], contracts: [], policies: [] }`。页面显示「未找到相关结果」 | + +--- + +## 附录:测试数据速查 + +| 角色 | 手机号 | 密码 | 说明 | +|------|--------|------|------| +| 管理员(北京·PRO) | `13800000010` | `12345678` | 王建国,6 名员工 | +| 管理员(深圳·ENTERPRISE) | `13800000020` | `12345678` | 李明华,7 名员工 | +| 管理员(杭州·FREE) | `13800000030` | `12345678` | 赵雪梅,3 名员工 | +| 员工(刘大壮) | `13900001001` | 见 seed | 生产车间 | +| 员工(孙美丽) | `13900001004` | 见 seed | 行政部,孕期 | + +| 员工 | 部门 | 月薪 | 合同状态 | 特殊状态 | +|------|------|------|----------|----------| +| 刘大壮 | 生产车间 | 8,500 | 已过期(520天) | - | +| 陈秀英 | 生产车间 | 7,500 | 已过期(49天) | - | +| 赵铁柱 | 生产车间 | 9,000 | 正常(无固定期) | - | +| 孙美丽 | 行政部 | 11,000 | 已过期(336天) | 孕期 | +| 周大伟 | 生产车间 | 7,000 | 正常 | - | +| 吴小红 | 质检部 | 9,500 | 正常 | - |