# 劳动用工合规助手 — 开发任务清单

> **文档编号**: 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 Schema（2天）

### 前端

- [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位+）
  - 逻辑：创建 Organization（plan=free, maxEmployees=20）+ User（role=admin, bcrypt 加密）
  - 返回：Access Token（2h）+ Refresh Token（7d）
  - 限流：同一 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` Hook（Zustand store：user, 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）
  - 提交后状态 → PENDING，HR 审核后 → 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 |
| 数据库 | PostgreSQL（Neon/Supabase）+ pgvector |
| 认证 | JWT（Access + Refresh）|
| 加密 | bcrypt（密码）+ AES-256（工资）|
| AI | 通义千问 Qwen（DashScope 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` 组件
