Files
TurboHR/1-prd.md
T
2026-07-23 12:34:43 +08:00

1108 lines
42 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.
# 劳动用工合规助手 — 产品需求文档 (PRD)
> **文档编号**: 1-prd.md
> **版本**: v1.0
> **日期**: 2026-07-23
> **状态**: 草案
> **依据**: 0-req.md v3.0 需求规格说明书
---
## 1. 产品概述
### 1.1 产品定位
面向中小企业的**极简用工合规 SaaS 工具**,聚焦劳动仲裁三大高发领域(合同签订、工资加班费、解聘),辅以 AI 合规顾问,帮助企业事前预防、事中管控、事后追溯用工风险。
### 1.2 产品愿景
> 「让每个中小企业都有一个用得起的劳动法顾问」
### 1.3 核心价值主张
| 价值 | 说明 |
|------|------|
| 极简易用 | 三看三不用原则,不需要培训,打开就会用 |
| 自动合规 | 风险自动检测 + 人话提示,不用懂法也能合规 |
| AI 顾问 | 通义千问驱动,随时问、自动查、提前预警 |
| 安全可靠 | SaaS 云端存储,数据隔离,多设备访问 |
### 1.4 目标用户
| 用户角色 | 企业规模 | 使用频率 | 核心诉求 |
|---------|---------|---------|---------|
| 老板兼管 HR | 10-30人 | 每周1-2次 | 快速了解风险,解聘时算钱 |
| 行政兼 HR | 30-80人 | 每天5分钟 | 合同到期提醒,每月算加班费 |
| 初级 HR | 80-200人 | 日常使用 | 合同管理,工资计算,解聘流程 |
---
## 2. 用户故事
### 2.1 认证与注册
| 编号 | 用户故事 | 验收标准 |
|------|---------|---------|
| US-AUTH-01 | 作为企业管理者,我想注册账号,这样我就能开始使用系统管理用工合规 | 输入企业名称+手机号+密码 → 创建组织+管理员账号 → 自动登录跳转首页 |
| US-AUTH-02 | 作为用户,我想用手机号和密码登录,这样我能安全访问我的数据 | 输入手机号+密码 → 校验通过 → 返回 JWT Token → 跳转首页 |
| US-AUTH-03 | 作为管理员,我想添加 HR 用户,这样我的同事也能操作系统 | 设置页 → 用户管理 → 输入姓名+手机号+角色 → 创建成功 |
| US-AUTH-04 | 作为用户,我想找回密码,这样我忘记密码时还能登录 | 忘记密码 → 输入手机号 → 验证码重置 → 重新登录 |
### 2.2 首页风险总览
| 编号 | 用户故事 | 验收标准 |
|------|---------|---------|
| US-HOME-01 | 作为用户,我想打开首页就知道有没有风险,这样我不用到处翻找 | 顶部一句话:「今天有 X 件事需要处理」 |
| US-HOME-02 | 作为用户,我想看到具体待办事项,这样我知道该先处理什么 | 待办列表:信号灯+一句话描述+「去处理」按钮 |
| US-HOME-03 | 作为用户,我想看到风险分布,这样我知道哪类问题最多 | 进度条展示合同/工资/解聘三类风险数量 |
| US-HOME-04 | 作为用户,当没有风险时我想看到安心提示,这样我知道一切正常 | 显示绿色「✅ 暂无风险,继续保持!」 |
| US-HOME-05 | 作为用户,我想看到 AI 风险预测,这样我能提前防范 | 首页下方展示 AI 预测的未来30天风险卡片 |
### 2.3 合同管理
| 编号 | 用户故事 | 验收标准 |
|------|---------|---------|
| US-CON-01 | 作为 HR,我想添加员工和合同信息,这样系统帮我管理合规 | 添加按钮 → 分步表单(基本信息→合同信息)→ 保存成功 |
| US-CON-02 | 作为 HR,我想看到所有员工的合同状态,这样我一眼就知道谁有问题 | 列表5列:姓名/部门/入职日期/合同状态(信号灯)/操作 |
| US-CON-03 | 作为 HR,当合同即将到期时我想收到提醒,这样我不会忘记续签 | 到期前30天列表出现「续签」按钮 + 首页待办提醒 |
| US-CON-04 | 作为 HR,我想一键续签合同,这样我不用填一堆表单 | 点击「续签」→ 弹窗确认期限+签订方式 → 确认 → 状态变绿 |
| US-CON-05 | 作为 HR,我想选择纸质或电子合同签订方式,这样符合实际操作 | 添加/续签时可选「纸质合同」或「电子合同」 |
| US-CON-06 | 作为 HR,当员工入职很久没签合同时我想被提醒,这样避免双倍工资赔偿 | 入职超1个月未签 → 🔴 红色状态 + 首页待办 |
| US-CON-07 | 作为 HR,我想搜索员工,这样快速找到某人的合同 | 搜索框输入姓名 → 实时筛选列表 |
| US-CON-08 | 作为 HR,我想批量续签即将到期的合同,这样不用一个个点 | 全选 → 批量续签 → 弹窗确认 → 批量更新 |
### 2.4 钱的计算
| 编号 | 用户故事 | 验收标准 |
|------|---------|---------|
| US-MONEY-01 | 作为 HR,我想计算加班费,这样我知道该付多少 | 输入月工资+加班小时数 → 实时显示各类加班费明细+合计 |
| US-MONEY-02 | 作为 HR,当加班超过法定上限时我想被提醒,这样避免违法 | 月加班超36小时 → 结果区显示黄色警告 |
| US-MONEY-03 | 作为 HR,我想计算未签合同的双倍工资,这样我知道风险金额 | 输入月工资+入职日期+签订状态 → 显示起止日期+赔偿金额 |
| US-MONEY-04 | 作为 HR,我想计算经济补偿金,这样解聘时知道该赔多少 | 输入入职/离职日期+月工资+原因 → 显示工作年限+补偿金+赔偿金(×2) |
| US-MONEY-05 | 作为 HR,我想关联员工自动填入工资,这样不用手动输入 | 选择员工 → 月工资自动填入 |
### 2.5 解聘助手
| 编号 | 用户故事 | 验收标准 |
|------|---------|---------|
| US-TERM-01 | 作为 HR,我想一步步完成解聘流程,这样不会漏掉步骤 | 5步向导:选原因→选员工→合规检查→算钱→确认 |
| US-TERM-02 | 作为 HR,当解聘原因不同时我想看到对应的检查项,这样有针对性 | Step 3 根据Step 1选择动态展示检查项 |
| US-TERM-03 | 作为 HR,当员工属于禁止解聘情形时我想被警告,这样避免违法解聘 | 选员工后自动检查孕期/工伤/医疗期 → 红色警告弹窗 |
| US-TERM-04 | 作为 HR,我想看到解聘历史记录,这样可以追溯 | 解聘助手页面底部展示历史记录列表 |
| US-TERM-05 | 作为 HR,即使有未通过检查项我也想保存记录,这样尊重我的决策 | Step 5 显示红色警告但不阻止保存 |
### 2.6 AI 合规顾问
| 编号 | 用户故事 | 验收标准 |
|------|---------|---------|
| US-AI-01 | 作为用户,我想用大白话问劳动法问题,这样不用自己查法条 | 聊天界面输入问题 → AI 流式回答 + 法律依据 + 关联本企业数据 |
| US-AI-02 | 作为用户,我想看到 AI 预测的未来风险,这样提前防范 | 首页 AI 风险预测卡片,展示未来30天预计风险 |
| US-AI-03 | 作为 HR,我想让 AI 审查合同条款,这样知道有没有违法 | 粘贴/上传合同文本 → 逐条审查 + 红/黄/绿标注 + 合规评分 |
| US-AI-04 | 作为 HR,我想匹配相似仲裁案例,这样评估败诉风险 | 输入争议情况 → 展示相似案例 + 败诉概率 + 赔偿预估 |
| US-AI-05 | 作为用户,AI 回答时我想看到打字机效果,这样体验更好 | SSE 流式输出,逐字显示 |
### 2.7 系统设置
| 编号 | 用户故事 | 验收标准 |
|------|---------|---------|
| US-SET-01 | 作为管理员,我想设置企业地区,这样系统用对的最低工资标准 | 设置→企业信息→选择城市 → 自动填入最低工资/社平工资默认值 |
| US-SET-02 | 作为管理员,我想管理用户和权限,这样控制谁能看谁能改 | 设置→用户管理→添加/移除用户→分配角色 |
| US-SET-03 | 作为管理员,我想查看当前套餐和人数限制,这样知道是否需要升级 | 设置→套餐信息→显示当前套餐+已用人数+上限 |
### 2.8 员工端
| 编号 | 用户故事 | 验收标准 |
|------|---------|---------|
| US-EMP-01 | 作为员工,我想用手机号+密码登录,这样不用等验证码 | 输入手机号+密码→登录成功→跳转工资条 |
| US-EMP-02 | 作为员工,我想用手机号+验证码登录,这样不用记密码 | 输入手机号→获取验证码→输入验证码→登录成功→跳转工资条 |
| US-EMP-03 | 作为员工,我想扫描 HR 发的二维码直接进入员工端,这样不用手动输入网址 | 扫码→打开员工端登录页→选择登录方式→登录 |
| US-EMP-04 | 作为员工,我想查看月度工资条,这样知道工资明细 | 选择月份→显示基本工资+加班费拆分+应发合计 |
| US-EMP-05 | 作为员工,我想确认已阅工资条,这样 HR 知道我看过了 | 点击「确认已阅」→记录时间+IP→HR端显示已确认 |
| US-EMP-06 | 作为员工,我想查看我的合同信息,这样了解合同条款 | 我的合同页→显示合同类型/期限/试用期/工资/扫描件 |
| US-EMP-07 | 作为员工,HR 发二维码让我填报入职信息,这样不用 HR 手动录入 | 扫码→填写姓名/身份证/银行卡等→提交→HR审核入库 |
| US-EMP-08 | 作为员工,HR 发二维码让我确认电子合同,这样完成签署确认 | 扫码→查看合同内容→勾选确认→点击签署→记录时间+IP |
| US-EMP-09 | 作为 HR,我想生成入职填报二维码发给员工,这样通过微信即可发送 | 添加员工时选「生成填报二维码」→显示二维码+链接→保存图片/复制链接 |
| US-EMP-10 | 作为 HR,我想生成合同确认二维码发给员工,这样完成电子合同签署 | 合同详情→生成确认二维码→微信发给员工→员工确认后状态自动更新 |
| US-EMP-11 | 作为 HR,我想查看员工工资条确认状态,这样知道谁还没看 | 合同/工资管理→显示各员工确认状态(已确认/未确认) |
---
## 3. 用户流程
### 3.1 新用户注册流程
```
访问网站 → 注册页
├─ 输入企业名称
├─ 输入手机号
├─ 输入密码
├─ 点击注册
├─ 创建 Organization + Admin User
├─ 自动登录,返回 JWT Token
└─ 跳转首页(空状态)
├─ 显示新手引导弹窗(3步)
└─ 显示「添加第一个员工」引导卡片
```
### 3.2 日常使用流程
```
登录 → 首页风险总览
├─ 有待办? → 点击「去处理」→ 跳转对应模块 → 处理 → 返回首页
├─ 无待办? → 查看AI风险预测 → 了解未来风险
└─ 日常操作:
├─ 合同管理 → 添加员工/续签/查看详情
├─ 钱的计算 → 切换Tab计算加班费/双倍工资/补偿金
├─ 解聘助手 → 5步向导完成解聘
└─ AI顾问 → 问答/合同审查/案例匹配
```
### 3.3 合同到期续签流程
```
首页待办显示「🟡 XX合同还有20天到期」
└─ 点击「去续签」→ 合同管理页
└─ 点击「续签」→ 弹窗
├─ 确认新期限(默认3年)
├─ 选择签订方式(默认沿用上次)
├─ 确认新到期日
└─ 点击「确认续签」
├─ 更新合同记录
├─ 状态变 🟢 正常
├─ 风险项自动消除
└─ 首页待办减少
```
### 3.4 解聘流程
```
解聘助手 → Step 1: 选择解聘原因
└─ Step 2: 选择员工
├─ 自动检查禁止解聘情形
├─ 触发?→ 红色警告 → 用户确认继续
└─ Step 3: 合规检查(根据原因动态展示)
└─ Step 4: 自动计算补偿金
└─ Step 5: 确认汇总
├─ 有未通过项?→ 红色警告(不阻止)
├─ 点击保存
└─ 生成解聘记录
├─ 员工状态变更为离职
├─ 记录存档
└─ 审计日志记录
```
### 3.5 AI 智能问答流程
```
AI顾问页 → 输入问题(或点击预设问题)
├─ 前端构建上下文:
│ ├─ 当前企业数据摘要(员工数/风险项/合同状态)
│ └─ RAG 检索相关法律条文
├─ 调用 DashScope APIqwen-plus
├─ SSE 流式返回
│ ├─ 逐字显示回答
│ └─ 显示完成后附法律依据(可折叠)
└─ 支持多轮对话(保留上下文)
```
### 3.6 员工入职填报流程
```
HR 管理端 → 添加员工 → 选择「生成填报二维码」
├─ 生成一次性 token(24h 有效)
├─ 页面显示二维码图片 + 可复制链接
└─ HR 通过微信发送给员工(二维码图片或链接)
└─ 员工扫码/点击链接 → 填报页面
├─ 填写姓名/手机号/身份证/银行卡等
├─ 提交
└─ 信息进入「待审核」状态
└─ HR 管理端收到通知
├─ 审核 → 通过 → 正式入库
│ ├─ 创建 Employee 记录
│ └─ token 失效
└─ 审核 → 驳回 → 员工重新填报
```
### 3.7 电子合同签署确认流程
```
HR 管理端 → 录入电子合同 → 点击「生成确认二维码」
├─ 生成一次性 token(7天有效)
├─ 页面显示二维码图片 + 可复制链接
└─ HR 通过微信发送给员工(二维码图片或链接)
└─ 员工扫码/点击链接 → 合同确认页面
├─ 查看合同内容(类型/期限/试用期/工资)
├─ 查看合同文件(如有链接)
├─ 勾选「我已阅读,确认签署」
├─ 点击「确认签署」
└─ 系统记录:确认时间 + IP + 设备信息
└─ HR 端合同状态自动更新为「已确认签署」
├─ token 失效
└─ 审计日志记录
```
---
## 4. 功能规格
### 4.1 认证模块
#### 4.1.1 注册
- **页面**: `/register`
- **输入**: 企业名称、手机号、密码(8位以上)、确认密码
- **校验**: 手机号格式、密码长度、手机号未被注册
- **处理**: 创建 Organizationplan=free, maxEmployees=20+ Userrole=admin+ bcrypt 加密密码
- **输出**: JWT Token + 跳转首页
- **限流**: 同一 IP 每小时最多 5 次注册
#### 4.1.2 登录
- **页面**: `/login`
- **输入**: 手机号、密码
- **校验**: 手机号存在、密码匹配
- **输出**: Access Token2h+ Refresh Token7d
- **限流**: 同一 IP 每分钟最多 5 次登录
#### 4.1.3 Token 刷新
- **接口**: `POST /api/v1/auth/refresh`
- **输入**: Refresh Token
- **输出**: 新 Access Token
- **逻辑**: 校验 Refresh Token 有效性 → 签发新 Access Token
### 4.2 首页风险总览
#### 4.2.1 数据聚合接口
- **接口**: `GET /api/v1/dashboard`
- **返回数据**:
```json
{
"success": true,
"data": {
"greeting": "早上好!今天有 3 件事需要处理",
"stats": {
"employeeCount": 12,
"highRiskCount": 2,
"todoCount": 3,
"monthlyOvertimePay": 8000
},
"todos": [
{
"id": "risk_001",
"level": "high",
"title": "张三入职35天未签合同",
"actionUrl": "/contracts?employee=张三"
}
],
"riskDistribution": {
"contract": 5,
"salary": 2,
"termination": 1
},
"aiPrediction": {
"risks": [...],
"suggestion": "本周优先处理合同到期和未签问题"
}
}
}
```
#### 4.2.2 风险检测引擎
- **触发时机**: 数据变更时实时检测 + 每日凌晨定时全量扫描
- **检测规则**: 见 0-req.md 4.3.3 / 4.4.4 合规检查规则
- **风险生命周期**: `pending``resolved`(自动/手动)/ `ignored`(手动)
### 4.3 合同管理模块
#### 4.3.1 API 规格
| 接口 | 方法 | 路径 | 说明 |
|------|------|------|------|
| 员工列表 | GET | `/api/v1/employees` | 支持分页、搜索、部门筛选 |
| 添加员工 | POST | `/api/v1/employees` | 含合同信息 |
| 员工详情 | GET | `/api/v1/employees/:id` | 含合同+风险信息 |
| 编辑员工 | PUT | `/api/v1/employees/:id` | 更新员工+合同信息 |
| 删除员工 | DELETE | `/api/v1/employees/:id` | 软删除(status=resigned |
| 批量续签 | POST | `/api/v1/contracts/batch-renew` | 批量续签合同 |
| 上传附件 | POST | `/api/v1/contracts/:id/attachment` | 上传纸质合同扫描件 |
#### 4.3.2 合同状态自动计算
```
输入:signDate, startDate, endDate, contractType, renewalCount, hireDate
输出:status + statusText + riskLevel
逻辑:
if signDate == null:
daysSinceHire = today - hireDate
if daysSinceHire > 365: → "已视为无固定期限" 🔴
elif daysSinceHire > 30: → "未签合同(X天)" 🔴
else: → "未签合同(X天)" 🟡
elif endDate != null:
daysToExpire = endDate - today
if daysToExpire < 0: → "已到期未续签" 🔴
elif daysToExpire <= 30: → "即将到期(X天)" 🟡
else: → "正常" 🟢
else:
→ "无固定期限" 🟢
```
#### 4.3.3 试用期合法性校验
```
规则(劳动合同法第19条):
合同期 < 3个月 → 不能约定试用期
合同期 3个月~1年 → 试用期 ≤ 1个月
合同期 1年~3年 → 试用期 ≤ 2个月
合同期 ≥ 3年 → 试用期 ≤ 6个月
校验时机:添加/编辑合同时实时校验
校验失败:红色提示「X年期合同试用期最多Y个月,当前Z个月不合法」
```
### 4.4 钱的计算模块
#### 4.4.1 加班费计算
- **页面**: `/money` Tab 1
- **输入**: 月工资、工作日加班小时、休息日加班小时、节假日加班小时
- **计算**: 纯前端实时计算,无需调后端
- **公式**:
```
hourlyWage = monthlyWage / 21.75 / 8
weekdayPay = hourlyWage * 1.5 * weekdayHours
weekendPay = hourlyWage * 2.0 * weekendHours
holidayPay = hourlyWage * 3.0 * holidayHours
total = weekdayPay + weekendPay + holidayPay
```
- **预警**: 总加班小时 > 36 → 黄色警告
#### 4.4.2 双倍工资计算
- **页面**: `/money` Tab 2
- **输入**: 月工资、入职日期、合同签订日期(可选,默认未签订)
- **计算**: 纯前端实时计算
- **公式**:
```
if 未签订 or 签订日期 - 入职日期 > 30天:
起算日 = 入职日 + 1个月
截止日 = 入职日 + 1年(如未签订)或 签订日期
月数 = min(截止日 - 起算日 的月数, 11)
双倍工资差额 = 月工资 × 月数
```
#### 4.4.3 经济补偿金计算
- **页面**: `/money` Tab 3
- **输入**: 入职日期、离职日期、月平均工资、离职原因、当地社平工资(选填)
- **计算**: 纯前端实时计算
- **公式**:
```
工作年限 = (离职日期 - 入职日期) 转换为年月
满1年 → 1个月工资
满6个月不满1年 → 1个月工资
不满6个月 → 0.5个月工资
补偿月数 = 向上取整(工作年限月数 / 12) 或 半月
if 社平工资 > 0 and 月工资 > 社平工资 × 3:
月工资 = 社平工资 × 3
补偿月数 = min(补偿月数, 12)
经济补偿金 = 月工资 × 补偿月数
违法解除赔偿金 = 经济补偿金 × 2
```
### 4.5 解聘助手模块
#### 4.5.1 解聘向导状态管理
```typescript
interface TerminationWizardState {
step: 1 | 2 | 3 | 4 | 5;
reason: 'negotiated' | 'fault' | 'nonfault' | 'layoff' | 'expired' | null;
employeeId: string | null;
terminationDate: string | null;
checklist: {
item: string;
passed: boolean;
remark?: string;
}[];
compensation: number;
riskLevel: 'safe' | 'warning' | 'danger';
}
```
#### 4.5.2 动态检查项规则
| 解聘原因 | 检查项 |
|---------|--------|
| 协商解除 | 是否支付经济补偿金、是否签署协商解除协议 |
| 员工犯错 | 是否有规章制度依据、是否有证据材料、是否通知工会 |
| 员工没犯错但干不了 | 是否提前30天通知或支付代通知金、是否经过培训/调岗 |
| 公司裁员 | 是否提前30天向工会说明、是否听取职工意见、是否报劳动部门 |
| 合同到期不续签 | 是否提前通知、是否支付经济补偿金 |
#### 4.5.3 禁止解聘情形检查
- **触发**: Step 2 选择员工后自动检查
- **检查字段**: `employee.isPregnant` / `employee.isWorkInjured` / `employee.isInMedicalPeriod`
- **交互**: 弹出红色警告框 + 「我已了解风险,继续操作」确认按钮
- **不阻止流程**: 用户确认后可继续
### 4.6 AI 合规顾问模块
#### 4.6.1 智能问答
- **页面**: `/ai-assistant`
- **接口**: `POST /api/v1/ai/chat`SSE 流式)
- **请求**:
```json
{
"messages": [
{"role": "user", "content": "试用期最长可以约定几个月?"}
],
"context": {
"orgId": "xxx",
"employeeCount": 12,
"riskItems": [...]
}
}
```
- **后端处理**:
1. 构建系统 Prompt(劳动法专家角色 + 人话风格要求)
2. RAG 检索相关法律条文(pgvector 语义搜索)
3. 注入企业数据上下文
4. 调用 DashScope APIqwen-plus
5. SSE 流式返回前端
- **响应**: SSE 事件流
```
data: {"type": "chunk", "content": "根据"}
data: {"type": "chunk", "content": "《劳动合同法》"}
data: {"type": "chunk", "content": "第19条"}
...
data: {"type": "done", "legalBasis": "《劳动合同法》第19条"}
```
#### 4.6.2 风险预测
- **触发**: 每日凌晨定时任务 + 首页加载时读取缓存
- **接口**: `GET /api/v1/ai/prediction`
- **逻辑**:
1. 查询未来30天将到期的合同
2. 查询入职将满1年未签合同的员工
3. 分析上月加班趋势变化
4. 调用 LLM 生成优先级建议
- **缓存**: 结果存 Redis / 内存缓存,24h 有效
#### 4.6.3 合同审查
- **页面**: `/ai-assistant` 子 Tab
- **接口**: `POST /api/v1/ai/contract-review`
- **输入**: 合同文本(粘贴或文件上传解析)
- **后端处理**:
1. 调用 qwen-max 分析合同条款
2. 逐条标注红/黄/绿 + 修改建议
3. 计算合规评分(0-100
- **输出**:
```json
{
"success": true,
"data": {
"score": 72,
"items": [
{"level": "red", "clause": "试用期6个月", "issue": "超过法定上限", "suggestion": "调整为2个月"},
{"level": "yellow", "clause": "竞业限制", "issue": "未约定补偿标准", "suggestion": "约定月补偿不低于离职前12个月平均工资的30%"}
]
}
}
```
#### 4.6.4 案例匹配
- **页面**: `/ai-assistant` 子 Tab
- **接口**: `POST /api/v1/ai/case-match`
- **输入**: 争议情况描述
- **后端处理**:
1. 将描述向量化(DashScope text-embedding-v2
2. pgvector 检索相似案例(top 5
3. 调用 qwen-max 分析败诉概率和赔偿预估
- **输出**: 相似案例列表 + 败诉概率 + 赔偿预估 + 建议
#### 4.6.5 使用次数限制
- **中间件**: 每次 AI 请求前检查当月已用次数
- **计数**: Redis / 数据库按 `orgId + 月份 + 类型` 统计
- **超限**: 返回 `429 Too Many Requests` + 提示升级套餐
---
## 5. 页面规格
### 5.1 页面清单
**管理端**
| 页面 | 路由 | 访问控制 | 布局 |
|------|------|---------|------|
| 登录 | `/login` | 公开 | 居中卡片 |
| 注册 | `/register` | 公开 | 居中卡片 |
| 忘记密码 | `/forgot-password` | 公开 | 居中卡片 |
| 风险总览 | `/` | 登录 | 顶部导航 + 主内容 |
| 合同管理 | `/contracts` | 登录 | 顶部导航 + 主内容 |
| 钱的计算 | `/money` | 登录 | 顶部导航 + 主内容 |
| 解聘助手 | `/termination` | 登录 | 顶部导航 + 主内容 |
| AI 合规顾问 | `/ai-assistant` | 登录 | 顶部导航 + 主内容 |
| 系统设置 | `/settings` | 登录(admin) | 顶部导航 + 主内容 |
**员工端**
| 页面 | 路由 | 访问控制 | 布局 |
|------|------|---------|------|
| 员工登录 | `/portal/login` | 公开 | 居中卡片 |
| 工资条 | `/portal/payslip` | 员工Token | 极简布局 |
| 我的合同 | `/portal/contract` | 员工Token | 极简布局 |
| 入职填报 | `/portal/onboarding` | Token链接 | 极简布局 |
| 合同确认 | `/portal/contract-confirm` | Token链接 | 极简布局 |
### 5.2 响应式断点
| 断点 | 宽度 | 布局变化 |
|------|------|---------|
| 桌面 | ≥1280px | 顶部导航 + 960px 居中内容 |
| 平板 | 768-1279px | 顶部导航 + 全宽内容 |
| 手机 | 375-767px | 底部 Tab Bar + 全宽内容 |
### 5.3 空状态设计
| 场景 | 展示内容 |
|------|---------|
| 首页无员工 | 插图 + 「添加第一个员工」按钮 + 示例截图 |
| 合同列表无数据 | 插图 + 「还没有员工,点这里添加」按钮 |
| 无风险 | 绿色大勾 + 「✅ 暂无风险,继续保持!」 |
| AI 顾问无对话 | 欢迎语 + 预设问题快捷按钮 |
| 解聘无历史记录 | 插图 + 「还没有解聘记录」文字 |
| 员工端无工资条 | 插图 + 「暂无工资记录」文字 |
| 员工端无合同 | 插图 + 「暂无合同信息,请联系 HR」文字 |
| 入职填报链接失效 | 提示「链接已过期,请联系 HR 重新发送」 |
| 合同确认链接失效 | 提示「链接已过期,请联系 HR 重新发送」 |
---
## 6. API 规格
### 6.1 统一规范
- **前缀**: `/api/v1/`
- **认证**: `Authorization: Bearer <access_token>`
- **响应格式**:
```json
{
"success": true,
"data": {},
"error": null
}
```
- **错误格式**:
```json
{
"success": false,
"data": null,
"error": {
"code": "VALIDATION_ERROR",
"message": "手机号格式不正确"
}
}
```
- **分页**: `?page=1&pageSize=20` → 返回 `{ items: [], total: 100, page: 1, pageSize: 20 }`
### 6.2 API 清单
| 模块 | 方法 | 路径 | 说明 |
|------|------|------|------|
| 认证 | POST | `/auth/register` | 注册 |
| 认证 | POST | `/auth/login` | 登录 |
| 认证 | POST | `/auth/refresh` | 刷新 Token |
| 认证 | GET | `/auth/me` | 获取当前用户 |
| Dashboard | GET | `/dashboard` | 首页数据聚合 |
| 员工 | GET | `/employees` | 员工列表 |
| 员工 | POST | `/employees` | 添加员工 |
| 员工 | GET | `/employees/:id` | 员工详情 |
| 员工 | PUT | `/employees/:id` | 编辑员工 |
| 员工 | DELETE | `/employees/:id` | 删除员工(软删除) |
| 合同 | POST | `/contracts/batch-renew` | 批量续签 |
| 合同 | POST | `/contracts/:id/attachment` | 上传扫描件 |
| 加班 | GET | `/overtime` | 加班记录列表 |
| 加班 | POST | `/overtime` | 添加加班记录 |
| 解聘 | GET | `/termination` | 解聘记录列表 |
| 解聘 | POST | `/termination` | 创建解聘记录 |
| 风险 | GET | `/risks` | 风险列表 |
| 风险 | PUT | `/risks/:id` | 更新风险状态 |
| AI | POST | `/ai/chat` | 智能问答(SSE |
| AI | GET | `/ai/prediction` | 风险预测 |
| AI | POST | `/ai/contract-review` | 合同审查 |
| AI | POST | `/ai/case-match` | 案例匹配 |
| 设置 | GET | `/settings/org` | 企业信息 |
| 设置 | PUT | `/settings/org` | 更新企业信息 |
| 设置 | GET | `/settings/users` | 用户列表 |
| 设置 | POST | `/settings/users` | 添加用户 |
| 设置 | PUT | `/settings/users/:id` | 编辑用户 |
| 设置 | DELETE | `/settings/users/:id` | 移除用户 |
| 员工端 | POST | `/portal/auth/login` | 手机号+密码登录 |
| 员工端 | POST | `/portal/auth/send-code` | 发送验证码(v1.0 页面内显示) |
| 员工端 | POST | `/portal/auth/verify` | 验证码登录 |
| 员工端 | POST | `/portal/auth/change-password` | 修改密码 |
| 员工端 | GET | `/portal/payslip` | 工资条列表 |
| 员工端 | GET | `/portal/payslip/:month` | 指定月工资明细 |
| 员工端 | POST | `/portal/payslip/:month/confirm` | 确认已阅工资条 |
| 员工端 | GET | `/portal/contract` | 我的合同信息 |
| 员工端 | GET | `/portal/onboarding/:token` | 获取入职填报信息 |
| 员工端 | POST | `/portal/onboarding/:token` | 提交入职填报 |
| 员工端 | GET | `/portal/contract-confirm/:token` | 获取合同确认信息 |
| 员工端 | POST | `/portal/contract-confirm/:token` | 确认签署合同 |
| 管理端 | POST | `/employees/:id/generate-onboarding-qr` | 生成入职填报二维码 |
| 管理端 | POST | `/contracts/:id/generate-confirm-qr` | 生成合同确认二维码 |
| 管理端 | GET | `/payslip/confirm-status` | 工资条确认状态 |
---
## 7. 数据库设计
### 7.1 Prisma Schema 概要
```prisma
// 核心表
model Organization {
id String @id @default(cuid())
name String
plan Plan @default(FREE)
maxEmployees Int @default(20)
city String?
createdAt DateTime @default(now())
users User[]
employees Employee[]
contracts LaborContract[]
overtimeRecords OvertimeRecord[]
terminations TerminationRecord[]
riskItems RiskItem[]
auditLogs AuditLog[]
}
model User {
id String @id @default(cuid())
orgId String
org Organization @relation(fields: [orgId], references: [id])
phone String @unique
email String?
passwordHash String
name String
role Role @default(ADMIN)
createdAt DateTime @default(now())
lastLoginAt DateTime?
}
// 业务表
model Employee {
id String @id @default(cuid())
orgId String
org Organization @relation(fields: [orgId], references: [id])
name String
department String
hireDate DateTime
monthlySalary String // AES-256 加密存储
status EmployeeStatus @default(ACTIVE)
gender String?
isPregnant Boolean @default(false)
isInMedicalPeriod Boolean @default(false)
isWorkInjured Boolean @default(false)
phone String?
createdBy String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
contracts LaborContract[]
overtimeRecords OvertimeRecord[]
terminations TerminationRecord[]
}
model LaborContract {
id String @id @default(cuid())
orgId String
org Organization @relation(fields: [orgId], references: [id])
employeeId String
employee Employee @relation(fields: [employeeId], references: [id])
signDate DateTime?
startDate DateTime
endDate DateTime?
contractType ContractType
signMethod SignMethod @default(PAPER)
contractYears Int @default(3)
probationMonths Int @default(0)
probationSalary Int @default(0)
renewalCount Int @default(0)
attachmentName String?
attachmentUrl String?
electronicContractNo String?
electronicContractUrl String?
createdBy String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// 其余表参考 0-req.md 第5章数据模型
```
### 7.2 枚举定义
```prisma
enum Plan { FREE PRO ENTERPRISE }
enum Role { ADMIN HR VIEWER }
enum EmployeeStatus { ACTIVE RESIGNED }
enum ContractType { FIXED UNFIXED UNSIGNED }
enum SignMethod { PAPER ELECTRONIC }
enum RiskType { CONTRACT SALARY TERMINATION }
enum RiskLevel { HIGH MEDIUM LOW }
enum RiskStatus { PENDING RESOLVED IGNORED }
enum TerminationReason { NEGOTIATED FAULT NONFAULT LAYOFF EXPIRED }
enum RiskAssessment { SAFE WARNING DANGER }
enum OnboardingStatus { PENDING APPROVED REJECTED }
enum ContractConfirmStatus { UNCONFIRMED CONFIRMED EXPIRED }
// 员工端扩展表
model Payslip {
id String @id @default(cuid())
orgId String
employeeId String
employee Employee @relation(fields: [employeeId], references: [id])
month String // YYYY-MM
baseSalary Decimal // 基本工资
overtimePay Decimal // 加班费合计
weekdayOvertimePay Decimal
weekendOvertimePay Decimal
holidayOvertimePay Decimal
totalPay Decimal // 应发合计
confirmedAt DateTime? // 员工确认时间
confirmedIp String? // 确认 IP
createdAt DateTime @default(now())
@@unique([employeeId, month])
}
model OnboardingLink {
id String @id @default(cuid())
orgId String
employeeId String? // 关联员工(审核通过后关联)
token String @unique // 一次性 token
status OnboardingStatus @default(PENDING)
phone String // 员工手机号
expiresAt DateTime // 24h 有效
submittedAt DateTime? // 员工提交时间
submittedData Json? // 员工填报数据
reviewedBy String? // 审核人 userId
reviewedAt DateTime? // 审核时间
createdAt DateTime @default(now())
}
model ContractConfirmLink {
id String @id @default(cuid())
orgId String
contractId String
token String @unique // 一次性 token
status ContractConfirmStatus @default(UNCONFIRMED)
employeePhone String // 员工手机号
expiresAt DateTime // 7天有效
confirmedAt DateTime? // 员工确认时间
confirmedIp String? // 确认 IP
confirmedDevice String? // 设备信息
createdAt DateTime @default(now())
}
```
---
## 8. 前端架构
### 8.1 项目结构
```
frontend/
├── src/
│ ├── main.tsx # 入口
│ ├── App.tsx # 路由定义
│ ├── components/ # 通用组件
│ │ ├── layout/
│ │ │ ├── TopNav.tsx # 顶部导航
│ │ │ ├── MobileTabBar.tsx # 移动端底部导航
│ │ │ └── PageContainer.tsx
│ │ ├── ui/
│ │ │ ├── Button.tsx
│ │ │ ├── Card.tsx
│ │ │ ├── Signal.tsx # 信号灯组件
│ │ │ ├── Modal.tsx
│ │ │ ├── Input.tsx
│ │ │ ├── Select.tsx
│ │ │ ├── DatePicker.tsx
│ │ │ └── EmptyState.tsx
│ │ └── shared/
│ │ ├── RiskCard.tsx
│ │ ├── TodoList.tsx
│ │ └── ProgressBar.tsx
│ ├── pages/
│ │ ├── auth/
│ │ │ ├── Login.tsx
│ │ │ ├── Register.tsx
│ │ │ └── ForgotPassword.tsx
│ │ ├── Dashboard.tsx
│ │ ├── Contracts.tsx
│ │ ├── Money.tsx
│ │ ├── Termination.tsx
│ │ ├── AIAssistant.tsx
│ │ ├── Settings.tsx
│ │ └── portal/
│ │ ├── PortalLogin.tsx # 员工端登录
│ │ ├── Payslip.tsx # 工资条
│ │ ├── MyContract.tsx # 我的合同
│ │ ├── Onboarding.tsx # 入职填报
│ │ └── ContractConfirm.tsx # 合同确认
│ ├── hooks/
│ │ ├── useAuth.ts
│ │ ├── useApi.ts
│ │ └── useRiskEngine.ts
│ ├── lib/
│ │ ├── api.ts # Axios 实例 + 拦截器
│ │ ├── calculator.ts # 纯前端计算逻辑
│ │ ├── riskEngine.ts # 风险检测引擎
│ │ └── utils.ts
│ ├── store/
│ │ └── authStore.ts # Zustand 状态管理
│ └── types/
│ └── index.ts # TypeScript 类型定义
├── package.json
├── vite.config.ts
├── tailwind.config.ts
└── tsconfig.json
```
### 8.2 状态管理
- **认证状态**: Zustanduser, token, isAuthenticated
- **服务端数据**: TanStack QueryReact Query)缓存 + 自动刷新
- **表单状态**: React Hook Form + Zod 校验
- **AI 对话**: 本地 useState 管理消息列表 + SSE 流式追加
### 8.3 路由守卫
```typescript
// ProtectedRoute:未登录 → 跳转 /login
// AdminRoute:非 admin → 跳转 /
// PublicRoute:已登录 → 跳转 /
```
---
## 9. 后端架构
### 9.1 项目结构
```
backend/
├── src/
│ ├── index.ts # 入口
│ ├── app.ts # Express 应用
│ ├── routes/
│ │ ├── auth.routes.ts
│ │ ├── employee.routes.ts
│ │ ├── contract.routes.ts
│ │ ├── overtime.routes.ts
│ │ ├── termination.routes.ts
│ │ ├── risk.routes.ts
│ │ ├── ai.routes.ts
│ │ ├── settings.routes.ts
│ │ └── portal.routes.ts # 员工端路由
│ ├── middleware/
│ │ ├── auth.ts # JWT 校验
│ │ ├── orgFilter.ts # 多租户 orgId 注入
│ │ ├── rateLimit.ts # 限流
│ │ ├── errorHandler.ts # 统一错误处理
│ │ └── auditLog.ts # 审计日志
│ ├── services/
│ │ ├── auth.service.ts
│ │ ├── employee.service.ts
│ │ ├── contract.service.ts
│ │ ├── risk.service.ts
│ │ ├── ai.service.ts # DashScope 调用
│ │ ├── rag.service.ts # RAG 检索
│ │ ├── portal.service.ts # 员工端服务
│ │ └── qrcode.service.ts # 二维码生成
│ ├── lib/
│ │ ├── prisma.ts # Prisma 客户端
│ │ ├── jwt.ts # JWT 工具
│ │ ├── crypto.ts # AES-256 加解密
│ │ └── dashscope.ts # 通义千问 SDK 封装
│ ├── validators/
│ │ ├── auth.validator.ts # Zod schema
│ │ ├── employee.validator.ts
│ │ └── ...
│ └── jobs/
│ ├── riskScan.ts # 定时风险扫描
│ └── aiPrediction.ts # 定时 AI 预测
├── prisma/
│ ├── schema.prisma
│ └── migrations/
├── package.json
└── .env
```
### 9.2 环境变量
```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=... # AES-256 工资字段加密
# 存储
SUPABASE_URL=...
SUPABASE_KEY=...
# 二维码(前端生成,无需后端服务)
# 使用 qrcode.react 库在前端直接生成
# 部署
PORT=3000
CORS_ORIGIN=https://your-app.vercel.app
```
---
## 10. 验收标准
### 10.1 功能验收
| 模块 | 验收项 | 验收标准 |
|------|--------|---------|
| 注册 | 手机号注册 | 输入合法信息 → 创建成功 → 自动登录 |
| 登录 | 密码登录 | 正确密码 → 返回 Token;错误密码 → 提示错误 |
| 首页 | 数据聚合 | 登录后 → 显示员工数/风险数/待办/分布 |
| 合同 | 添加员工 | 4项必填 → 保存成功 → 列表显示 |
| 合同 | 信号灯状态 | 未签合同→🔴;即将到期→🟡;正常→🟢 |
| 合同 | 一键续签 | 点击续签→确认→状态变绿→风险消除 |
| 合同 | 纸质/电子 | 选择纸质→显示上传按钮;选择电子→显示编号/链接输入 |
| 钱的计算 | 加班费实时计算 | 输入数字→右侧结果实时更新 |
| 钱的计算 | 加班超时预警 | 总小时>36→黄色警告 |
| 解聘 | 5步向导 | 每步显示进度条→下一步→最终保存 |
| 解聘 | 禁止情形检查 | 选孕期员工→红色警告弹窗 |
| AI | 智能问答 | 输入问题→流式回答→附法律依据 |
| AI | 合同审查 | 粘贴合同→逐条标注→合规评分 |
| AI | 案例匹配 | 输入情况→相似案例→败诉概率 |
| 设置 | 用户管理 | admin可添加用户→分配角色 |
| 员工端 | 密码登录 | 输入手机号+密码→登录成功 |
| 员工端 | 验证码登录 | 输入手机号→收到验证码→登录成功 |
| 员工端 | 扫码进入 | HR 发二维码→员工扫码→打开员工端 |
| 员工端 | 工资条查看 | 选择月份→显示工资明细→确认已阅 |
| 员工端 | 合同查看 | 显示合同信息+扫描件+签署记录 |
| 员工端 | 入职填报 | 扫码→填写信息→提交→HR审核入库 |
| 员工端 | 合同确认 | 扫码→查看合同→勾选确认→记录时间IP |
| 管理端 | 生成填报二维码 | 添加员工→选生成二维码→显示二维码+链接→微信发送 |
| 管理端 | 生成确认二维码 | 合同详情→生成确认二维码→微信发送→员工确认后状态更新 |
### 10.2 非功能验收
| 类别 | 验收标准 |
|------|---------|
| 性能 | 首屏加载 < 2sAPI 响应 < 500msAI 首 token < 3s |
| 安全 | 密码 bcrypt 加密,工资 AES-256 加密,JWT 认证,orgId 隔离 |
| 响应式 | 桌面/平板/手机三端可用,导航自适应 |
| 兼容 | Chrome/Edge/Safari 最新版正常 |
| 数据隔离 | A 企业用户无法访问 B 企业数据 |
| 员工端隔离 | 员工只能查看自己的数据,不能查看他人 |
| 链接安全 | 入职/确认链接含一次性 token,过期失效 |
---
## 11. 发布计划
### 11.1 v1.0 发布范围
| 阶段 | 内容 | 预估工期 |
|------|------|---------|
| P0 | 项目搭建 + 路由骨架 + Prisma Schema | 2天 |
| P1 | 认证体系(注册/登录/JWT/路由守卫) | 2天 |
| P2 | 首页风险总览 + 风险检测引擎 | 2天 |
| P3 | 合同管理(列表/添加/续签/纸质电子) | 3天 |
| P4 | 钱的计算(3 Tab 计算器) | 2天 |
| P5 | 解聘助手(5步向导 + 禁止检查) | 2天 |
| P6 | AI 合规顾问(问答/预测/审查/案例 + RAG) | 4天 |
| P7 | 员工端(验证码登录 + 工资条 + 合同 + 入职填报 + 合同确认) | 3天 |
| P8 | 系统设置 + 新手引导 + 空状态 | 1天 |
| P9 | 移动端适配 + 联调 | 2天 |
| P10 | 部署上线 + 验证 | 1天 |
| **合计** | | **~24天** |
### 11.2 后续版本
| 版本 | 内容 | 预估 |
|------|------|------|
| v2.0 | 社保公积金模块 | +2周 |
| v3.0 | 人力成本分析 + 员工自助门户增强(考勤/请假) | +3周 |
---
## 12. 风险与对策
| 风险 | 影响 | 对策 |
|------|------|------|
| 通义千问 API 不稳定 | AI 功能不可用 | 降级为规则引擎回答 + 重试机制 |
| 法律规则地区差异大 | 计算结果不准 | 提供城市选择 + 默认值 + 用户可修改 |
| RAG 知识库构建耗时 | P6 延期 | 先用 Prompt 内嵌法条,后续再建向量库 |
| 中小企业付费意愿低 | 商业化困难 | free 套餐足够基础使用,AI 功能促付费 |
| 数据安全合规要求 | 法律风险 | 数据加密 + 身份证号加密存储 + 隐私协议 |
| 员工端使用率低 | 功能闲置 | HR 主动生成二维码通过微信发给员工,降低使用门槛 |