Files
TurboHR/2-task.md
T
selfrelease 0df8aa77d9 feat: AIHR 智能人力资源管理系统初始提交
- 员工花名册管理(加密存储、导入导出)
- 薪酬管理(发薪批次、薪酬模版、加班费计算、工资条)
- 社保公积金(多城市配置、版本管理、基数调整)
- 解聘管理(6步流程、证据链、工作交接)
- AI 助手(合同审查、风险预测、RAG 知识库)
- Dashboard 仪表盘
- 设置与通知
2026-07-24 13:53:11 +08:00

763 lines
32 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 劳动用工合规助手 — 开发任务清单
> **文档编号**: 2-task.md
> **版本**: v1.0
> **日期**: 2026-07-23
> **状态**: 开发中
> **依据**: 0-req.md v3.0 需求规格说明书 / 1-prd.md v1.0 产品需求文档
---
## 任务总览
| 阶段 | 内容 | 预估工期 | 任务数 |
|------|------|---------|--------|
| P0 | 项目搭建 + 路由骨架 + Prisma Schema | 2天 | 8 | ✅ 已完成 |
| P1 | 认证体系(注册/登录/JWT/路由守卫) | 2天 | 7 | ✅ 已完成 |
| P2 | 首页风险总览 + 风险检测引擎 | 2天 | 6 | ✅ 已完成 |
| P3 | 合同管理(列表/添加/续签/纸质电子) | 3天 | 10 | ✅ 已完成 |
| P4 | 钱的计算(3 Tab 计算器 + 加班费保存 + 工资条管理) | 2天 | 5 | ✅ 已完成 |
| P5 | 解聘助手(5步向导 + 禁止检查) | 2天 | 6 | ✅ 已完成 |
| P6 | AI 合规顾问(问答/预测/审查/案例 + RAG) | 4天 | 9 | ✅ 已完成 |
| P7 | 员工端(密码/验证码登录 + 工资条 + 合同 + 入职填报 + 合同确认) | 3天 | 10 | ✅ 已完成 |
| P8 | 系统设置 + 新手引导 + 空状态 | 1天 | 5 | ✅ 已完成 |
| P9 | 移动端适配 + 联调 | 2天 | 4 | ✅ 已完成 |
| P10 | 部署上线 + 验证 | 1天 | 4 | ⏳ 进行中 |
| P11 | 功能补齐(社保公积金 + 到期提醒 + 批量工资条 + Excel导入 + 员工档案附件) | 3天 | 10 | ✅ 已完成 |
| **合计** | | **~27天** | **84** | |
---
## P0 — 项目搭建 + 路由骨架 + Prisma Schema2天)
### 前端
- [x] **T-P0-01** 初始化前端项目
- Vite + React 18 + TypeScript
- 安装 TailwindCSS + PostCSS
- 配置路径别名 `@/``src/`
- 安装核心依赖:react-router-dom, axios, zustand, @tanstack/react-query, react-hook-form, zod, lucide-react, qrcode.react
- **产出**: `package.json`, `vite.config.ts`, `tailwind.config.ts`, `tsconfig.json`
- [x] **T-P0-02** 前端项目结构搭建
- 创建目录结构:`components/`, `pages/`, `hooks/`, `lib/`, `store/`, `types/`
- 创建 `App.tsx` 路由骨架(含管理端 + 员工端路由定义)
- 创建 `main.tsx` 入口
- 创建 `lib/api.ts`(Axios 实例 + 请求/响应拦截器)
- 创建 `types/index.ts`TypeScript 类型定义)
- **产出**: 项目目录结构 + 路由配置
- [x] **T-P0-03** 前端布局组件
- `TopNav.tsx`:顶部导航栏(Logo + 5 Tab + 风险角标 + 用户头像下拉)
- `MobileTabBar.tsx`:移动端底部导航
- `PageContainer.tsx`:主内容区容器(max-width 960px 居中)
- `ui/Button.tsx`, `ui/Card.tsx`, `ui/Input.tsx`, `ui/Select.tsx`, `ui/Modal.tsx`, `ui/Signal.tsx`, `ui/EmptyState.tsx`
- **产出**: 通用组件库
### 后端
- [x] **T-P0-04** 初始化后端项目
- Node.js + Express + TypeScript
- 安装核心依赖:prisma, @prisma/client, zod, jsonwebtoken, bcryptjs, cors, helmet, morgan, express-rate-limit
- 配置 ts-node-dev 热重载
- **产出**: `package.json`, `tsconfig.json`, `.env.example`
- [x] **T-P0-05** 后端项目结构搭建
- 创建目录结构:`routes/`, `middleware/`, `services/`, `lib/`, `validators/`, `jobs/`
- `app.ts`Express 应用(CORS + helmet + JSON 解析 + 路由挂载)
- `index.ts`:服务入口
- **产出**: 后端骨架 + 健康检查接口 `/health`
- [x] **T-P0-06** Prisma Schema 编写
- 编写完整 `schema.prisma`Organization, User, Employee, LaborContract, OvertimeRecord, TerminationRecord, RiskItem, AuditLog, Payslip, OnboardingLink, ContractConfirmLink
- 定义所有枚举:Plan, Role, EmployeeStatus, ContractType, SignMethod, RiskType, RiskLevel, RiskStatus, TerminationReason, RiskAssessment, OnboardingStatus, ContractConfirmStatus
- 配置 PostgreSQL 数据源
- **产出**: `prisma/schema.prisma`
- [x] **T-P0-07** 数据库迁移 + 种子数据
- 运行 `prisma migrate dev` 生成初始迁移
- 编写 `prisma/seed.ts` 种子数据(测试企业 + 员工 + 合同)
- 配置 `prisma.ts` 客户端单例
- **产出**: 数据库表结构 + 测试数据
- [x] **T-P0-08** 中间件骨架
- `auth.ts`JWT 校验中间件(从 Header 提取 Token → 验证 → 注入 req.user
- `orgFilter.ts`:多租户中间件(从 req.user 提取 orgId → 注入 req.orgId
- `errorHandler.ts`:统一错误处理(Zod 错误 → 422,Prisma 错误 → 400,其他 → 500
- `rateLimit.ts`:限流中间件(基于 express-rate-limit
- `auditLog.ts`:审计日志中间件(记录关键操作)
- **产出**: 5 个中间件文件
---
## P1 — 认证体系(2天)
- [x] **T-P1-01** 后端:注册接口
- `POST /api/v1/auth/register`
- 输入校验(Zod):企业名称、手机号、密码(8位+)
- 逻辑:创建 Organizationplan=free, maxEmployees=20+ Userrole=admin, bcrypt 加密)
- 返回:Access Token2h+ Refresh Token7d
- 限流:同一 IP 每小时 5 次
- **产出**: `auth.routes.ts` + `auth.service.ts` + `auth.validator.ts`
- [x] **T-P1-02** 后端:登录接口
- `POST /api/v1/auth/login`
- 输入校验:手机号、密码
- 逻辑:查询 User → bcrypt 比对 → 签发 Token
- 限流:同一 IP 每分钟 5 次
- **产出**: 登录逻辑
- [x] **T-P1-03** 后端:Token 刷新 + 当前用户
- `POST /api/v1/auth/refresh`:校验 Refresh Token → 签发新 Access Token
- `GET /api/v1/auth/me`:返回当前用户信息 + 组织信息
- **产出**: Token 刷新逻辑
- [x] **T-P1-04** 后端:JWT 工具
- `lib/jwt.ts`:签发/验证 Access Token + Refresh Token
- 密钥从环境变量读取
- **产出**: `jwt.ts`
- [x] **T-P1-05** 前端:注册页面
- `/register` 页面
- 表单:企业名称、手机号、密码、确认密码
- React Hook Form + Zod 校验
- 注册成功 → 存储 Token → 跳转首页
- **产出**: `Register.tsx`
- [x] **T-P1-06** 前端:登录页面 + 路由守卫
- `/login` 页面
- 表单:手机号、密码
- `useAuth` HookZustand storeuser, token, isAuthenticated
- `ProtectedRoute`:未登录 → 跳转 `/login`
- `PublicRoute`:已登录 → 跳转 `/`
- Axios 拦截器:401 → 自动刷新 Token / 跳转登录
- **产出**: `Login.tsx` + `useAuth.ts` + `authStore.ts` + 路由守卫
- [x] **T-P1-07** 前端:忘记密码页面
- `/forgot-password` 页面
- 手机号 + 验证码 + 新密码
- **产出**: `ForgotPassword.tsx`
---
## P2 — 首页风险总览 + 风险检测引擎(2天)
- [x] **T-P2-01** 后端:Dashboard 数据聚合接口
- `GET /api/v1/dashboard`
- 聚合:员工数、高风险数、待办数、月加班费
- 生成待办列表(从 RiskItem 查询 pending 状态)
- 风险分布统计(按 type 分组)
- AI 预测数据(从缓存读取,P6 实现)
- **产出**: `dashboard.routes.ts` + `dashboard.service.ts`
- [x] **T-P2-02** 后端:风险检测引擎
- `lib/riskEngine.ts`
- 合同风险检测:未签合同(>30天 🔴 / >365天 视为无固定期限 🔴)、即将到期(≤30天 🟡)、已到期 🔴
- 试用期风险检测:试用期超法定上限
- 加班风险检测:月加班 > 36h
- 解聘风险检测:禁止解聘情形(孕期/工伤/医疗期)
- 触发时机:数据变更时实时检测 + 定时全量扫描
- **产出**: `riskEngine.ts`
- [x] **T-P2-03** 后端:风险 CRUD 接口
- `GET /api/v1/risks`:风险列表(分页 + 类型筛选 + 状态筛选)
- `PUT /api/v1/risks/:id`:更新风险状态(resolved / ignored + 备注)
- **产出**: `risk.routes.ts` + `risk.service.ts`
- [x] **T-P2-04** 后端:定时风险扫描任务
- `jobs/riskScan.ts`:每日凌晨 2:00 全量扫描
- 使用 node-cron 调度
- 扫描所有企业的员工/合同 → 生成/更新 RiskItem
- **产出**: `riskScan.ts`
- [x] **T-P2-05** 前端:首页风险总览页面
- `/` Dashboard 页面
- 一句话状态("早上好!今天有 N 件事需要处理")
- 数字卡片:员工数 / 高风险数 / 待办数 / 月加班费
- 待办列表:每条含风险等级颜色 + 标题 + 「去处理」按钮
- 风险分布进度条(合同/工资/解聘)
- AI 风险预测卡片(P6 实现后接入)
- **产出**: `Dashboard.tsx` + `TodoList.tsx` + `ProgressBar.tsx`
- [x] **T-P2-06** 前端:风险角标组件
- 顶部导航栏红色角标,显示待处理风险总数
- 点击跳转首页
- 数据来源:Dashboard 接口或独立计数接口
- **产出**: `TopNav.tsx` 集成角标
---
## P3 — 合同管理(3天)
- [x] **T-P3-01** 后端:员工 CRUD 接口
- `GET /api/v1/employees`:列表(分页 + 搜索 + 部门筛选)
- `POST /api/v1/employees`:添加员工(含合同信息 + AES-256 加密工资)
- `GET /api/v1/employees/:id`:详情(含合同 + 风险)
- `PUT /api/v1/employees/:id`:编辑
- `DELETE /api/v1/employees/:id`:软删除(status=resigned
- **产出**: `employee.routes.ts` + `employee.service.ts` + `employee.validator.ts`
- [x] **T-P3-02** 后端:AES-256 加密工具
- `lib/crypto.ts`:加密/解密工资字段
- 密钥从环境变量 `ENCRYPTION_KEY` 读取
- **产出**: `crypto.ts`
- [x] **T-P3-03** 后端:合同状态计算
- `lib/contractStatus.ts`
- 输入:signDate, startDate, endDate, contractType, renewalCount, hireDate
- 输出:status + statusText + riskLevel
- 逻辑:未签/即将到期/已到期/正常/无固定期限
- **产出**: `contractStatus.ts`
- [x] **T-P3-04** 后端:试用期合法性校验
- 合同期 < 3月 → 不能约定试用期
- 合同期 3月~1年 → 试用期 ≤ 1月
- 合同期 1~3年 → 试用期 ≤ 2月
- 合同期 ≥ 3年 → 试用期 ≤ 6月
- **产出**: 集成到 `employee.validator.ts`
- [x] **T-P3-05** 后端:批量续签接口
- `POST /api/v1/contracts/batch-renew`
- 输入:合同 ID 列表 + 新期限
- 逻辑:更新 endDate + renewalCount++ + 重新检测风险
- **产出**: `contract.service.ts` 续签逻辑
- [x] **T-P3-06** 后端:合同附件上传
- `POST /api/v1/contracts/:id/attachment`
- 接收 multipart 文件(纸质合同扫描件)
- 存储到 Supabase Storage / 本地临时目录
- 更新合同记录 attachmentName + attachmentUrl
- **产出**: 文件上传逻辑
- [x] **T-P3-07** 前端:合同管理列表页
- `/contracts` 页面
- 员工合同列表:姓名 / 部门 / 合同状态信号灯 / 到期日 / 操作
- 搜索框 + 部门筛选
- 信号灯组件(🔴🟡🟢)
- **产出**: `Contracts.tsx`
- [x] **T-P3-08** 前端:添加/编辑员工表单
- 模态框表单
- Step 1 基本信息:姓名*、部门*、手机号、入职日期*、月工资*、性别
- Step 2 合同信息:合同类型*、签订方式(纸质/电子)、签订日期、起止日期、试用期月数、试用期工资
- 纸质合同:显示文件上传按钮
- 电子合同:显示合同编号 + 链接输入
- 试用期实时校验(红色提示)
- 特殊标记:孕期/工伤/医疗期 复选框
- **产出**: `EmployeeForm.tsx`
- [x] **T-P3-09** 前端:一键续签弹窗
- 选中即将到期的合同 → 点击「续签」
- 弹窗:显示当前合同信息 + 选择新期限
- 确认 → 调用批量续签接口 → 刷新列表
- **产出**: `RenewModal.tsx`
- [x] **T-P3-10** 前端:合同详情页/弹窗
- 显示员工信息 + 合同完整信息 + 风险卡片
- 纸质合同:查看扫描件
- 电子合同:查看合同链接
- 操作按钮:编辑 / 续签 / 发送确认二维码(P7 实现)
- **产出**: `ContractDetail.tsx`
---
## P4 — 钱的计算(2天)
- [x] **T-P4-01** 前端:加班费计算器(含员工关联 + 月份选择 + 保存记录)
- `/money` Tab 1
- 输入:月工资、工作日加班小时、休息日加班小时、节假日加班小时
- 公式:hourlyWage = monthlyWage / 21.75 / 8
- weekdayPay = hourlyWage × 1.5 × weekdayHours
- weekendPay = hourlyWage × 2.0 × weekendHours
- holidayPay = hourlyWage × 3.0 × holidayHours
- 实时计算,右侧显示结果
- 总加班 > 36h → 黄色警告
- **产出**: `OvertimeCalculator.tsx` + `lib/calculator.ts`
- [x] **T-P4-02** 前端:双倍工资计算器
- `/money` Tab 2
- 输入:月工资、入职日期、合同签订日期(可选)
- 公式:未签或超 30 天签订 → 起算入职+1月 → 截止入职+1年或签订日 → 双倍工资差额
- 实时计算
- **产出**: `DoublePayCalculator.tsx`
- [x] **T-P4-03** 前端:经济补偿金计算器
- `/money` Tab 3
- 输入:入职日期、离职日期、月平均工资、离职原因、社平工资(选填)
- 公式:工作年限 → 补偿月数 → 封顶限制 → 经济补偿金 / 违法解除赔偿金(×2)
- 实时计算
- **产出**: `CompensationCalculator.tsx`
- [x] **T-P4-04** 后端:加班记录 CRUD + 工资条管理(`payroll.routes.ts`
- `GET /api/v1/overtime`:加班记录列表
- `POST /api/v1/overtime`:添加加班记录
- **产出**: `overtime.routes.ts` + `overtime.service.ts`
- [x] **T-P4-05** 前端:计算器工具函数 + 工资条管理 Tab
- `lib/calculator.ts`:纯函数,输入输出明确
- 编写单元测试验证计算公式正确性
- 边界用例:0 加班、36h 临界值、社平工资 3 倍封顶
- **产出**: `calculator.ts` + `calculator.test.ts`
---
## P5 — 解聘助手(2天)
- [x] **T-P5-01** 后端:解聘记录 CRUD
- `GET /api/v1/termination`:解聘记录列表
- `POST /api/v1/termination`:创建解聘记录
- 逻辑:保存向导数据 + 更新员工状态为 resigned + 记录审计日志
- **产出**: `termination.routes.ts` + `termination.service.ts` + `termination.validator.ts`
- [x] **T-P5-02** 前端:解聘向导 Step 1 — 选择解聘原因
- `/termination` 页面
- 5 个选项卡片:协商解除 / 员工犯错 / 员工没犯错但干不了 / 公司裁员 / 合同到期不续签
- 每个选项含简短说明
- **产出**: `Termination.tsx` Step 1
- [x] **T-P5-03** 前端:解聘向导 Step 2 — 选择员工 + 禁止情形检查
- 员工选择下拉框(仅在职员工)
- 选择后自动检查:isPregnant / isWorkInjured / isInMedicalPeriod
- 命中禁止情形 → 红色警告弹窗 + 「我已了解风险,继续操作」
- **产出**: Step 2 + 禁止情形检查逻辑
- [x] **T-P5-04** 前端:解聘向导 Step 3 — 合规检查清单
- 根据解聘原因动态生成检查项
- 协商解除:是否支付补偿金 / 是否签署协议
- 员工犯错:是否有规章制度 / 是否有证据 / 是否通知工会
- 员工没犯错:是否提前30天通知 / 是否经过培训调岗
- 公司裁员:是否提前30天向工会说明 / 是否听取意见 / 是否报劳动部门
- 合同到期:是否提前通知 / 是否支付补偿金
- 每项 ✅/❌ 选择
- **产出**: Step 3 + 动态检查项规则
- [x] **T-P5-05** 前端:解聘向导 Step 4 — 补偿金计算 + Step 5 — 确认提交
- Step 4:自动填充员工工资 + 入职日期 → 计算补偿金(复用 P4 计算逻辑)
- Step 5:汇总信息确认 → 提交保存
- 进度条显示 1/5 ~ 5/5
- **产出**: Step 4 + Step 5
- [x] **T-P5-06** 前端:解聘历史记录
- `/termination` 页面底部
- 历史记录列表:员工名 / 解聘日期 / 原因 / 补偿金 / 风险等级
- 点击查看详情
- **产出**: `TerminationHistory.tsx`
---
## P6 — AI 合规顾问(4天)
- [x] **T-P6-01** 后端:DashScope SDK 封装
- `lib/dashscope.ts`
- 封装通义千问 API 调用(兼容 OpenAI 格式)
- 支持 qwen-plus(日常问答)和 qwen-max(复杂任务)
- 支持 SSE 流式输出
- API Key 从环境变量 `DASHSCOPE_API_KEY` 读取
- **产出**: `dashscope.ts`
- [x] **T-P6-02** 后端:RAG 知识库 — 法律条文向量化
- `services/rag.service.ts`
- 收集劳动法/劳动合同法/司法解释/地方条例文本
- 使用 DashScope text-embedding-v2 生成向量
- 存储到 Supabase pgvector
- 提供语义搜索接口(输入问题 → 检索相关法条)
- **产出**: `rag.service.ts` + 知识库数据
- [x] **T-P6-03** 后端:智能问答接口(SSE
- `POST /api/v1/ai/chat`
- 逻辑:
1. 构建系统 Prompt(劳动法专家 + 人话风格)
2. RAG 检索相关法条
3. 注入企业数据上下文(员工数/风险项/合同状态)
4. 调用 qwen-plus SSE 流式返回
- SSE 事件格式:`data: {"type":"chunk","content":"xxx"}`
- 结束事件:`data: {"type":"done","legalBasis":"..."}`
- **产出**: `ai.routes.ts` + `ai.service.ts`
- [x] **T-P6-04** 后端:风险预测接口
- `GET /api/v1/ai/prediction`
- 逻辑:
1. 查询未来 30 天到期合同
2. 查询入职满 1 年未签合同员工
3. 分析上月加班趋势
4. 调用 LLM 生成优先级建议
- 缓存 24h
- 定时任务:每日凌晨生成
- **产出**: 预测逻辑 + `jobs/aiPrediction.ts`
- [x] **T-P6-05** 后端:合同审查接口
- `POST /api/v1/ai/contract-review`
- 输入:合同文本(粘贴或文件解析)
- 逻辑:调用 qwen-max 逐条分析 → 标注红/黄/绿 + 修改建议 → 合规评分
- **产出**: 合同审查逻辑
- [x] **T-P6-06** 后端:案例匹配接口
- `POST /api/v1/ai/case-match`
- 输入:争议情况描述
- 逻辑:text-embedding-v2 向量化 → pgvector 检索 top 5 → qwen-max 分析败诉概率
- **产出**: 案例匹配逻辑
- [x] **T-P6-07** 后端:AI 使用次数限制
- 中间件:每次 AI 请求前检查当月已用次数
-`orgId + 月份 + 类型` 统计
- free: 10 问答 / 3 审查 / 3 案例
- pro: 100 / 20 / 20
- enterprise: 无限
- 超限 → 429 + 提示升级
- **产出**: AI 限流中间件
- [x] **T-P6-08** 前端:AI 顾问页面 — 智能问答
- `/ai-assistant` 页面
- 聊天界面:消息列表 + 输入框
- 预设问题快捷按钮("试用期最长多久?" "未签合同怎么办?"
- SSE 流式接收:逐字显示打字机效果
- 法律依据折叠展示
- 多轮对话(保留上下文 messages)
- **产出**: `AIAssistant.tsx` 聊天 Tab
- [x] **T-P6-09** 前端:AI 顾问页面 — 合同审查 + 案例匹配
- 合同审查 Tab:文本框粘贴合同 / 文件上传 → 提交 → 逐条标注展示 + 合规评分
- 案例匹配 Tab:描述争议情况 → 提交 → 相似案例卡片列表 + 败诉概率 + 赔偿预估
- **产出**: 合同审查 Tab + 案例匹配 Tab
---
## P7 — 员工端(3天)
- [x] **T-P7-01** 后端:员工端认证(密码登录 + 验证码登录)
- `POST /api/v1/portal/auth/login`:手机号 + 密码(bcrypt 校验员工密码)
- `POST /api/v1/portal/auth/send-code`:发送验证码(v1.0 页面内显示,存 Redis/内存)
- `POST /api/v1/portal/auth/verify`:验证码登录
- `POST /api/v1/portal/auth/change-password`:修改密码
- 员工 Token 与管理端 Token 区分(role=employee
- **产出**: `portal.routes.ts` 认证部分 + `portal.service.ts`
- [x] **T-P7-02** 后端:员工端工资条接口
- `GET /api/v1/portal/payslip`:工资条列表(按月)
- `GET /api/v1/portal/payslip/:month`:指定月工资明细
- `POST /api/v1/portal/payslip/:month/confirm`:确认已阅(记录时间 + IP
- 数据隔离:只能查看自己的工资条
- **产出**: 工资条接口
- [x] **T-P7-03** 后端:员工端合同查看接口
- `GET /api/v1/portal/contract`:当前员工的合同信息(只读)
- 包含:合同类型、期限、试用期、工资、扫描件/电子链接、签署确认记录
- **产出**: 合同查看接口
- [x] **T-P7-04** 后端:入职填报接口
- `GET /api/v1/portal/onboarding/:token`:根据 token 获取填报信息(企业名等)
- `POST /api/v1/portal/onboarding/:token`:提交填报数据
- Token 校验:有效性 + 过期检查(24h)
- 提交后状态 → PENDINGHR 审核后 → APPROVED(创建 Employee
- `POST /api/v1/employees/:id/generate-onboarding-qr`:管理端生成填报 token
- **产出**: 入职填报接口 + OnboardingLink 表操作
- [x] **T-P7-05** 后端:合同确认接口
- `GET /api/v1/portal/contract-confirm/:token`:根据 token 获取合同信息
- `POST /api/v1/portal/contract-confirm/:token`:确认签署(记录时间 + IP + 设备)
- Token 校验:有效性 + 过期检查(7天)
- 确认后更新合同状态 + ContractConfirmLink 状态
- `POST /api/v1/contracts/:id/generate-confirm-qr`:管理端生成确认 token
- **产出**: 合同确认接口 + ContractConfirmLink 表操作
- [x] **T-P7-06** 后端:二维码生成服务
- `services/qrcode.service.ts`
- 生成 token + 构建完整 URL(如 `https://xxx/portal/onboarding?token=xxx`
- 返回 URL 供前端生成二维码图片
- **产出**: `qrcode.service.ts`
- [x] **T-P7-07** 前端:员工端登录页面
- `/portal/login` 页面
- 双 Tab 切换:[密码登录] [验证码登录]
- 密码登录:手机号 + 密码
- 验证码登录:手机号 → 获取验证码 → 输入验证码
- v1.0 验证码页面内弹窗显示
- **产出**: `PortalLogin.tsx`
- [x] **T-P7-08** 前端:员工端工资条页面
- `/portal/payslip` 页面
- 月份选择器
- 工资明细卡片:基本工资 + 加班费拆分(工作日/休息日/节假日)+ 应发合计
- 「确认已阅」按钮
- 空状态:暂无工资记录
- **产出**: `Payslip.tsx`
- [x] **T-P7-09** 前端:员工端合同查看 + 入职填报 + 合同确认页面
- `/portal/contract`:合同信息只读展示 + 扫描件查看 + 签署记录 + 到期提示
- `/portal/onboarding`:入职填报表单(姓名/手机号/身份证/银行卡等)+ 提交
- `/portal/contract-confirm`:合同信息展示 + 查看合同文件 + 勾选确认 + 签署
- Token 失效页面:链接已过期提示
- **产出**: `MyContract.tsx` + `Onboarding.tsx` + `ContractConfirm.tsx`
- [x] **T-P7-10** 前端:管理端二维码生成弹窗
- 合同管理页:「生成填报二维码」按钮 → 弹窗显示二维码图片 + 可复制链接
- 合同详情页:「生成确认二维码」按钮 → 弹窗显示二维码图片 + 可复制链接
- 使用 qrcode.react 生成二维码
- 保存二维码图片功能
- **产出**: `QRCodeModal.tsx`
---
## P8 — 系统设置 + 新手引导 + 空状态(1天)
- [x] **T-P8-01** 后端:系统设置接口
- `GET /api/v1/settings/org`:企业信息
- `PUT /api/v1/settings/org`:更新企业信息(名称、城市)
- `GET /api/v1/settings/users`:用户列表
- `POST /api/v1/settings/users`:添加用户
- `PUT /api/v1/settings/users/:id`:编辑用户
- `DELETE /api/v1/settings/users/:id`:移除用户
- **产出**: `settings.routes.ts` + `settings.service.ts`
- [x] **T-P8-02** 前端:系统设置页面
- `/settings` 页面,3 个子 Tab
- 企业信息:名称、城市选择(联动最低工资/社平工资默认值)
- 用户管理:用户列表 + 添加/编辑/移除 + 角色分配(admin/hr/viewer
- 套餐信息:当前套餐 + 已用人数 + 上限 + 升级按钮
- **产出**: `Settings.tsx`
- [x] **T-P8-03** 前端:新手引导弹窗
- 首次登录显示 3 步引导
- Step 1"这里看风险"(指向首页 Tab)
- Step 2"这里管合同"(指向合同 Tab)
- Step 3"这里算钱"(指向算钱 Tab
- localStorage 记录已看过
- **产出**: `OnboardingGuide.tsx`
- [x] **T-P8-04** 前端:空状态组件
- 首页无员工:插图 + 「添加第一个员工」按钮
- 合同列表无数据:插图 + 「还没有员工,点这里添加」
- 无风险:绿色大勾 + 「✅ 暂无风险,继续保持!」
- AI 顾问无对话:欢迎语 + 预设问题
- 解聘无历史:插图 + 文字
- 员工端无工资条/合同:插图 + 文字
- 链接失效:过期提示
- **产出**: `EmptyState.tsx` 各场景
- [x] **T-P8-05** 前端:全局配色 + 样式规范
- TailwindCSS 配色:主色 #2563EB、危险 #DC2626、警告 #F59E0B、安全 #16A34A、背景 #F8FAFC
- 字体:系统字体栈
- 圆角:rounded-lg(卡片)/ rounded-md(按钮)
- 阴影:shadow-sm(卡片)
- **产出**: `tailwind.config.ts` 完整配置
---
## P9 — 移动端适配 + 联调(2天)
- [x] **T-P9-01** 前端:响应式适配
- 桌面 ≥1280px:顶部导航 + 960px 居中
- 平板 768-1279px:顶部导航 + 全宽
- 手机 375-767px:底部 Tab Bar + 全宽
- 合同列表 → 移动端卡片式
- 计算器 → 移动端上下排列
- AI 聊天 → 移动端全屏
- 员工端 → 移动端优先(员工主要用手机)
- **产出**: 响应式样式
- [x] **T-P9-02** 前端:员工端移动端优化
- 员工端以移动端为主场景
- 大按钮、大字体、简洁布局
- 扫码后自动适配手机屏幕
- 工资条卡片式展示
- 合同信息折叠展开
- **产出**: 员工端移动端样式
- [x] **T-P9-03** 全栈:端到端联调
- 注册 → 登录 → 添加员工 → 查看首页 → 合同管理 → 计算 → 解聘 → AI 问答 → 员工端登录 → 工资条 → 入职填报 → 合同确认
- 多租户隔离测试:A 企业无法访问 B 企业数据
- 员工端隔离测试:员工只能查看自己的数据
- Token 过期自动刷新测试
- **产出**: 联调问题清单 + 修复
- [x] **T-P9-04** 全栈:性能优化
- 前端:路由懒加载(React.lazy + Suspense
- 前端:API 请求缓存(React Query staleTime 配置)
- 后端:数据库索引(orgId + 常用查询字段)
- 后端:API 响应压缩(compression 中间件)
- **产出**: 性能优化
---
## P10 — 部署上线 + 验证(1天)
- [x] **T-P10-01** 后端:部署配置(`netlify.toml` + `.env.example`
- 配置 Railway 项目
- 环境变量配置:DATABASE_URL, JWT_SECRET, DASHSCOPE_API_KEY, ENCRYPTION_KEY, SUPABASE_URL, CORS_ORIGIN
- 运行 Prisma migrate deploy
- 健康检查验证
- **产出**: 后端线上地址
- [x] **T-P10-02** 前端:部署到 Netlify`netlify.toml` 已配置)
- 配置 Vercel 项目
- 环境变量配置:VITE_API_URL
- 构建配置:`npm run build`
- 路由重写配置(SPA fallback
- **产出**: 前端线上地址
- [ ] **T-P10-03** 数据库:Neon/Supabase 配置
- 创建 PostgreSQL 数据库
- 启用 pgvector 扩展(AI 模块用)
- 配置连接池
- 运行迁移
- 导入 RAG 知识库数据
- **产出**: 数据库线上环境
- [ ] **T-P10-04** 验收测试
- 按 1-prd.md 第 10 章验收标准逐项验证
- 功能验收:注册/登录/首页/合同/计算/解聘/AI/员工端/设置
- 非功能验收:性能/安全/响应式/兼容/数据隔离
- 修复发现的问题
- **产出**: 验收报告
---
## 依赖关系
```
P0 ──→ P1 ──→ P2 ──→ P3 ──→ P4(纯前端,可与 P3 并行)
├──→ P5(依赖 P3 员工数据 + P4 补偿金计算)
├──→ P6(依赖 P0 数据库 + P2 风险数据)
├──→ P7(依赖 P3 合同数据 + P0 数据库)
└──→ P8(依赖 P1 认证)
P9(依赖 P2~P8 全部完成)
P10(依赖 P9 完成)
```
**可并行任务**
- P4(钱的计算)纯前端计算,可在 P3 完成后与 P5/P6 并行
- P8(系统设置)可在 P6/P7 期间并行
---
## 技术栈速查
| 层 | 技术 |
|-----|------|
| 前端框架 | React 18 + Vite + TypeScript |
| 前端样式 | TailwindCSS |
| 前端路由 | React Router v6 |
| 状态管理 | Zustand(认证)+ TanStack Query(服务端数据)|
| 表单 | React Hook Form + Zod |
| 二维码 | qrcode.react |
| 图标 | lucide-react |
| 后端框架 | Express + TypeScript |
| ORM | Prisma |
| 数据库 | PostgreSQLNeon/Supabase+ pgvector |
| 认证 | JWTAccess + Refresh|
| 加密 | bcrypt(密码)+ AES-256(工资)|
| AI | 通义千问 QwenDashScope API|
| Embedding | DashScope text-embedding-v2 |
| 部署 | Vercel(前端)+ Railway(后端)|
---
## 环境变量清单
```env
# 数据库
DATABASE_URL=postgresql://...
# JWT
JWT_SECRET=...
JWT_REFRESH_SECRET=...
# DashScope (通义千问)
DASHSCOPE_API_KEY=sk-xxx
DASHSCOPE_BASE_URL=https://dashscope.aliyuncs.com/api/v1
# 加密
ENCRYPTION_KEY=...
# 存储
SUPABASE_URL=...
SUPABASE_KEY=...
# 部署
PORT=3000
CORS_ORIGIN=https://your-app.vercel.app
# 前端
VITE_API_URL=https://your-backend.railway.app
```
---
## P11 — 功能补齐(3天)
> **目标**: 补齐中小企业 HR 实际使用中的关键缺失功能
### 后端
- [x] **T-P11-01** 后端:社保公积金计算器
- Prisma 模型 `SocialInsuranceConfig`(养老/医疗/失业/工伤/生育/公积金 比例 + 基数上下限)
- `social.routes.ts`GET/PUT 配置 + POST 计算
- 支持基数封顶/保底逻辑
- **产出**: `social.routes.ts` + `SocialInsuranceConfig` 模型
- [x] **T-P11-02** 后端:到期提醒通知服务
- Prisma 模型 `NotificationSetting`(通知开关 + 提前天数 + 微信Webhook + 邮箱)
- Prisma 模型 `NotificationLog`(通知记录)
- `notification.routes.ts`GET/PUT 设置 + GET 日志 + POST 手动检查
- 支持企业微信 Webhook 推送
- **产出**: `notification.routes.ts` + `NotificationSetting` + `NotificationLog` 模型
- [x] **T-P11-03** 后端:批量生成工资条
- `POST /api/v1/payroll/payslip/batch-generate`
- 自动遍历所有在职员工,关联加班记录,一键生成全员工资条
- 支持传入津贴/扣款映射
- **产出**: `payroll.routes.ts` 新增接口
- [x] **T-P11-04** 后端:Excel/CSV 批量导入加班数据
- `POST /api/v1/payroll/overtime/batch`
- 接收数组格式加班数据,批量 upsert
- 前端解析 CSV 按员工姓名匹配
- **产出**: `payroll.routes.ts` 新增接口
- [x] **T-P11-05** 后端:员工档案附件管理
- Prisma 模型 `EmployeeAttachment`(文件名/类型/URL/大小)
- `attachment.routes.ts`GET 列表 + POST 添加 + DELETE 删除
- 支持身份证/银行卡/合同扫描件/学历证书/其他分类
- **产出**: `attachment.routes.ts` + `EmployeeAttachment` 模型
### 前端
- [x] **T-P11-06** 前端:社保公积金计算器 Tab
- Money 页面新增「社保公积金」Tab
- `SocialInsuranceCalculator` 组件:输入缴费基数 → 计算五险一金明细
- 支持企业/个人比例配置(可展开配置面板)
- 表格展示各险种比例、企业缴纳、个人缴纳
- **产出**: `Money.tsx` 新增 `SocialInsuranceCalculator` 组件
- [x] **T-P11-07** 前端:批量生成工资条 UI
- PayslipManager 新增「一键全员生成」按钮
- 调用 `batch-generate` 接口,自动关联加班费
- **产出**: `Money.tsx` PayslipManager 增强
- [x] **T-P11-08** 前端:CSV 批量导入加班数据
- OvertimeCalculator 新增「批量导入加班数据(CSV)」按钮
- 前端解析 CSV(姓名,工作日加班,休息日加班,节假日加班,月份)
- 按员工姓名自动匹配 employeeId
- **产出**: `Money.tsx` OvertimeCalculator 增强
- [x] **T-P11-09** 前端:员工档案附件管理 UI
- Contracts 页面点击员工行打开右侧抽屉
- `EmployeeDetailDrawer` 组件:展示员工基本信息 + 合同信息 + 附件管理
- 支持文件上传(FileReader → base64)和删除
- 附件分类:身份证/银行卡/合同扫描件/学历证书/其他
- **产出**: `Contracts.tsx` 新增 `EmployeeDetailDrawer` 组件
- [x] **T-P11-10** 前端:通知设置页面
- Settings 页面新增「通知设置」Tab
- `NotificationSettings` 组件:合同到期提醒/未签提醒/加班超时/工资条通知开关
- 提前提醒天数配置
- 企业微信 Webhook 配置
- 邮件通知配置
- 手动触发合同到期检查 + 通知日志展示
- **产出**: `Settings.tsx` 新增 `NotificationSettings` 组件