763 lines
32 KiB
Markdown
763 lines
32 KiB
Markdown
# 劳动用工合规助手 — 开发任务清单
|
||
|
||
> **文档编号**: 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` 组件
|