init: AI HR Compliance Assistant

This commit is contained in:
freedakgmail
2026-07-23 12:34:43 +08:00
commit 820579e98d
81 changed files with 19327 additions and 0 deletions
+762
View File
@@ -0,0 +1,762 @@
# 劳动用工合规助手 — 开发任务清单
> **文档编号**: 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` 组件