Files
TurboHR/20260730-优化.md
freedakgmail 42e0c650a4 feat: 实现20260730优化方案全部功能
- AI文件审查:.docx上传提取文本,支持多种文档类型
- 用工办理工作流:WorkProcess页面+后端API,支持入职/续签/终止等流程
- 企业自建文本库:Templates页面Tab切换,企业模板CRUD+渲染+下载Word
- 考勤发布:Attendance发布/取消发布按钮,员工端MyAttendance页面
- 工资条发布:Money发布/定时发送按钮+弹窗,portal端publishStatus过滤
- 合同到期弹窗:Dashboard合同到期预警可点击打开弹窗,支持续签/终止操作
- Prisma schema新增WorkProcess/EnterpriseTemplate/AttendancePublish模型
- 前后端编译验证全部通过
2026-07-30 10:21:22 +08:00

21 KiB
Raw Permalink Blame History

TurboHR 优化方案(20260730

日期:2026-07-30 依据:白话用工侠完整运行测试报告对比分析 + 功能缺口梳理 优先级:P0(紧急/核心)、P1(重要补全)、P2(增强优化)


背景

将「白话用工侠完整运行测试报告」中列出的功能与本系统(TurboHR)实际代码逐一对比后,识别出以下功能缺口:

已实现功能(14项)

功能 对应文件
登录与全局框架 Login.tsxSidebarNavTopNav
工作台(合规健康度/风险预警/待办) Dashboard.tsx
AI 智能问答(流式/历史/语音/转律师) AIAssistant.tsx ChatTab
AI 判赔预测(12类争议场景) AIAssistant.tsx PredictTab
AI 合同审查(粘贴文本) AIAssistant.tsx ReviewTab
AI 案例匹配 AIAssistant.tsx CaseTab
花名册(搜索/筛选/导入/导出/二维码邀请) Roster.tsx
考勤管理(记录/导入/统计/排班/休假) Attendance.tsx
合同管理(列表/查询/查看/下载/删除) Contracts.tsx
规章制度民主程序(四步流程) Policies.tsx
用工体检诊断(6维度评分) HealthCheck.tsx
文本模板库(87模板/下载Word/变量渲染) Templates.tsx
通知管理(发布/目标人群/定时) Notifications.tsx
计算器(五险一金/医疗期) SocialInsurance.tsxMedicalPeriodCalculator.tsx

部分实现功能(3项)

功能 已有部分 缺失部分
AI 文件审查 粘贴合同文本审查、结构化风险报告 不支持上传 doc/docx 文件,无文书类型选择
考勤管理 考勤记录导入、查看、统计 无"发布考勤表"功能
工资条管理 工资条生成、员工端查看 无"发布工资条"和"定时发送"功能

未实现功能(5项)

功能 说明
用工办理工作流(13类流程) 最大的功能缺口,无统一办理工作流系统
背景调查 完全未实现(本次暂不纳入)
视频中心 完全未实现(本次暂不纳入)
企业自建文本库 无企业自建文本管理功能
合同到期处理弹窗 有到期提醒但无多选项处理弹窗(本次暂不纳入)

本次优化聚焦4项功能:用工办理工作流、企业自建文本库、考勤/工资条发布、AI文件审查上传。


P0AI文件审查上传功能

问题描述

现有 AIAssistant.tsx ReviewTab 仅支持粘贴合同文本进行审查,无法上传 doc/docx 文件。白话用工侠支持上传文件并选择文书类型(劳动合同/协商解除/劳务协议/实习协议/保密协议)。

涉及文件

文件 改动
backend/src/routes/ai.routes.ts 新增 POST /ai/review/upload 接口
frontend/src/pages/AIAssistant.tsx ReviewTab 新增文件上传区 + 文书类型选择
backend/package.json 新增 mammoth 依赖

实现方案

后端:文件上传 + 文本提取

// ai.routes.ts 新增
import mammoth from 'mammoth'

const upload = multer({
  storage: multer.memoryStorage(),
  limits: { fileSize: 100 * 1024 * 1024 }, // 100MB
  fileFilter: (req, file, cb) => {
    const ext = path.extname(file.originalname).toLowerCase()
    if (ext !== '.docx' && ext !== '.doc') {
      return cb(new Error('仅支持 .doc 和 .docx 文件'))
    }
    cb(null, true)
  },
})

router.post('/review/upload', authMiddleware, upload.single('file'), async (req: AuthRequest, res, next) => {
  try {
    if (!req.file) return res.status(400).json({ success: false, error: { code: 'NO_FILE', message: '请上传文件' } })
    const ext = path.extname(req.file.originalname).toLowerCase()
    let text = ''
    if (ext === '.docx') {
      const result = await mammoth.extractRawText({ buffer: req.file.buffer })
      text = result.value
    } else {
      // .doc 旧格式:提示用户转换为 .docx
      return res.status(400).json({ success: false, error: { code: 'UNSUPPORTED', message: '暂不支持 .doc 格式,请将文件另存为 .docx 后上传' } })
    }
    // 截断超长文本
    if (text.length > 50000) {
      text = text.slice(0, 50000) + '\n\n[文本过长,已截断]'
    }
    res.json({ success: true, data: { text } })
  } catch (err) { next(err) }
})

前端:ReviewTab 改造

在现有粘贴文本输入框上方新增:

合同审查 Tab:
├── 文书类型选择(下拉:劳动合同/协商解除协议/劳务协议/实习协议/保密协议)
├── 文件上传区(拖拽或点击上传 .docx)
│   ├── 上传后调用 /ai/review/upload 提取文本
│   └── 提取成功后自动填入下方输入框
├── 文本输入框(现有,用户可编辑提取后的文本)
├── 开始审查按钮(现有)
└── 审查结果展示(现有)

依赖安装

cd backend && npm install mammoth

安全考虑

  • 文件大小限制:100MBmulter limits
  • 文件类型校验:仅 .docx.doc 提示转换
  • 提取后不保存原文件,仅返回文本
  • 文本长度截断:超过 50000 字符时截断并提示

P0:用工办理工作流系统(13类流程)

问题描述

本系统有 Termination.tsx(离职管理)和 Contracts.tsx(合同管理),但缺少统一的用工办理工作流系统。白话用工侠提供13类办理流程:员工录用、员工入职、自定义合同签署、员工信息提交、员工转正、合同变更、合同续签、合同中止、开具收入证明、合同终止、合同解除、开具离职证明、灵活用工。

13类流程定义

编号 流程名称 类型代码 核心表单字段 关联模块
1 员工录用 HIRE 人员选择、入职时间、公司地址、部门、岗位、直属上级、联系方式、试用期薪酬、转正薪酬、携带材料 员工创建+合同起草
2 员工入职 ONBOARD 入职日期、岗位确认、合同签署方式、材料提交清单 员工状态→ACTIVE
3 自定义合同签署 CUSTOM_CONTRACT 合同模板选择、变量填充、签署方、期限 合同管理
4 员工信息提交 INFO_SUBMIT 信息变更字段、证明材料 员工档案更新
5 员工转正 CONFIRM 转正日期、转正薪资、考核结果 员工状态+薪资变更
6 合同变更 CHANGE 变更类型、变更内容、生效日期 合同管理
7 合同续签 RENEW 续签次数、新期限、新薪资 合同管理
8 合同中止 SUSPEND 中止原因、中止期限、预计恢复日期 合同状态
9 开具收入证明 INCOME_CERT 用途、收入期间、接收方 文本模板渲染
10 合同终止 TERMINATE 终止原因、终止日期、经济补偿 合同状态+离职
11 合同解除 RESCIND 解除原因、解除方式、协商/单方 复用 Termination 模块
12 开具离职证明 LEAVING_CERT 离职日期、离职原因、接收方 文本模板渲染
13 灵活用工 FLEXIBLE 人员信息、用工类型、协议期限、计酬方式 合同管理(LABOR)

数据模型

// 用工办理流程
model WorkProcess {
  id          String   @id @default(cuid())
  orgId       String
  org         Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
  type        String   // HIRE/ONBOARD/CUSTOM_CONTRACT/INFO_SUBMIT/CONFIRM/CHANGE/RENEW/SUSPEND/INCOME_CERT/TERMINATE/RESCIND/LEAVING_CERT/FLEXIBLE
  title       String
  employeeId  String?
  employee    Employee? @relation(fields: [employeeId], references: [id])
  status      String   @default("DRAFT") // DRAFT/PENDING_APPROVAL/APPROVED/REJECTED/EXECUTING/COMPLETED/CANCELLED
  formData    Json     // 表单数据 JSON
  documents   Json?    // 生成的文书列表 [{name, content, type}]
  approverId  String?
  approvedAt  DateTime?
  remark      String?
  createdBy   String
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  @@index([orgId, status])
  @@index([orgId, type])
  @@index([orgId, createdBy])
}

后端接口

POST   /api/v1/work-processes              # 创建办理(含草稿)
GET    /api/v1/work-processes              # 列表查询(支持type/status筛选)
GET    /api/v1/work-processes/:id          # 详情
PATCH  /api/v1/work-processes/:id          # 更新草稿
POST   /api/v1/work-processes/:id/submit   # 提交办理
POST   /api/v1/work-processes/:id/approve  # 审批通过
POST   /api/v1/work-processes/:id/reject   # 驳回
POST   /api/v1/work-processes/:id/cancel   # 撤销
DELETE /api/v1/work-processes/:id          # 删除草稿
GET    /api/v1/work-processes/:id/preview  # 预览生成的文书

前端架构

新增页面frontend/src/pages/WorkProcess.tsx

页面结构:
├── 发起办理(13类流程卡片选择)
├── 办理记录(列表+筛选:类型/状态/日期)
├── 办理草稿(仅 DRAFT 状态)
└── 流程详情(步骤条+表单+预览+操作)

流程详情组件(通用 Wizard):

  • 步骤条:填写信息 → 预览文书 → 存草稿/提交
  • 表单根据 type 动态渲染字段
  • 预览:调用文本模板渲染接口生成文书
  • 提交后根据流程类型执行对应业务逻辑

复用已有模块

  • 合同解除(#11)→ 复用 Termination.tsx 的 Wizard 逻辑
  • 合同续签(#7)→ 复用 Contracts.tsx 的合同管理逻辑
  • 收入证明(#9)/ 离职证明(#12)→ 复用 Templates.tsx 的模板渲染
  • 员工录用(#1)→ 复用 roster/modals.tsx 的添加员工逻辑

提交后业务联动

流程类型 提交后执行
HIRE 创建员工记录 + 创建劳动合同
ONBOARD 更新员工状态为 ACTIVE + 记录入职日期
CUSTOM_CONTRACT 创建劳动合同
INFO_SUBMIT 更新员工档案字段
CONFIRM 更新试用期结束 + 调整薪资
CHANGE 更新合同字段 + 记录变更历史
RENEW 关闭旧合同 + 创建新合同
SUSPEND 合同状态改为 SUSPENDED
INCOME_CERT 生成收入证明文书(不改变业务数据)
TERMINATE 合同状态改为 TERMINATED + 触发离职流程
RESCIND 调用已有 Termination 逻辑
LEAVING_CERT 生成离职证明文书
FLEXIBLE 创建劳务协议合同

涉及文件

文件 改动
backend/prisma/schema.prisma 新增 WorkProcess 模型
backend/src/routes/work-process.routes.ts 新增,办理 CRUD + 提交/审批/撤销
backend/src/services/work-process.service.ts 新增13类流程的业务联动逻辑
backend/src/index.ts 注册新路由
frontend/src/pages/WorkProcess.tsx 新增,办理页面
frontend/src/App.tsx 注册路由
frontend/src/components/layout/SidebarNav.tsx 新增菜单项

实施分阶段

  1. Phase 1:数据模型 + 基础 CRUD + 列表/草稿页面
  2. Phase 2:员工录用、员工入职、合同续签、合同终止(4个高频流程)
  3. Phase 3:剩余9类流程 + 文书预览生成
  4. Phase 4:审批流程 + 办理记录导出

P1:企业自建文本库

问题描述

现有 Templates.tsx 仅提供系统预置模板(87个,只读),企业无法创建和管理自己的文本模板。白话用工侠有"企业文本库"功能,支持自建文本。

数据模型

// 企业自建文本模板
model EnterpriseTemplate {
  id          String   @id @default(cuid())
  orgId       String
  org         Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
  name        String
  category    String   // CONTRACT/RULES/NOTICE/AGREEMENT/OTHER
  description String?
  content     String   @db.Text
  variables   String[] // 变量名列表
  status      String   @default("ACTIVE") // ACTIVE/ARCHIVED
  createdBy   String
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  @@index([orgId, category])
}

后端接口

# 现有模板路由:/api/v1/templates(系统预置,只读)
# 新增企业模板路由:/api/v1/enterprise-templates

GET    /api/v1/enterprise-templates            # 列表(支持category/search
POST   /api/v1/enterprise-templates            # 新建
GET    /api/v1/enterprise-templates/:id        # 详情
PUT    /api/v1/enterprise-templates/:id        # 更新
DELETE /api/v1/enterprise-templates/:id        # 删除
POST   /api/v1/enterprise-templates/:id/render # 渲染(复用现有 renderTemplate 逻辑)
GET    /api/v1/enterprise-templates/:id/download # 下载Word

前端方案

改造页面frontend/src/pages/Templates.tsx

在现有模板库页面顶部新增 Tab 切换:

  • 系统模板库(现有功能不变)
  • 企业文本库(新增)

企业文本库 Tab 内容:

├── 查询栏(名称搜索 + 分类筛选)
├── 新建/编辑弹窗(名称、分类、变量配置、内容编辑)
├── 模板卡片列表(复用现有卡片样式)
├── 详情弹窗(变量填写 → 渲染 → 下载Word/复制)
└── 操作:编辑、复制、删除、归档

涉及文件

文件 改动
backend/prisma/schema.prisma 新增 EnterpriseTemplate 模型
backend/src/routes/enterprise-template.routes.ts 新增CRUD + 渲染 + 下载
backend/src/index.ts 注册新路由
frontend/src/pages/Templates.tsx 顶部新增 Tab 切换 + 企业文本库面板

实现要点

  • 变量提取:编辑内容时自动扫描 {{变量名}} 提取变量列表
  • 渲染逻辑:复用 template.service.tsrenderTemplate 函数
  • 内容编辑器:使用 textarea + 变量插入按钮(点击插入 {{变量名}}
  • 权限:ADMIN/HR 可增删改,VIEWER 只读

P1:考勤发布流程

问题描述

现有 Attendance.tsx 有考勤记录和统计功能,但缺少"发布考勤表"功能。白话用工侠支持 HR 发布月度考勤表,员工在员工端查看确认。

数据模型

// 考勤发布记录
model AttendancePublish {
  id          String   @id @default(cuid())
  orgId       String
  org         Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
  month       String   // 2026-07
  title       String   // 如"2026年7月考勤表"
  status      String   @default("PUBLISHED") // PUBLISHED/CANCELLED
  publishDate DateTime @default(now())
  createdBy   String
  createdAt   DateTime @default(now())

  @@unique([orgId, month])
  @@index([orgId, month])
}

后端接口

POST   /api/v1/attendance/publish             # 发布考勤表
GET    /api/v1/attendance/publish-records      # 发布记录列表
POST   /api/v1/attendance/publish/:id/cancel   # 取消发布
GET    /api/v1/portal/attendance?month=2026-07 # 员工查看自己的月度考勤

前端改造

Attendance.tsx — 在「考勤确认」Tab 工具栏新增:

  • 「发布考勤表」按钮:弹窗确认 → 选择月份 → 发布
  • 「发布记录」入口:查看历史发布记录,可取消发布

portal/ 新增考勤查看页面portal/MyAttendance.tsx

  • 员工登录后查看已发布月份的考勤记录
  • 显示每日考勤状态、上下班时间
  • 支持月度切换

涉及文件

文件 改动
backend/prisma/schema.prisma 新增 AttendancePublish 模型
backend/src/routes/attendance.routes.ts 新增发布/取消/记录接口
backend/src/routes/portal.routes.ts 新增员工端考勤查看接口
frontend/src/pages/Attendance.tsx 新增发布按钮和发布记录弹窗
frontend/src/pages/portal/MyAttendance.tsx 新增,员工端考勤查看
frontend/src/App.tsx 注册员工端考勤路由
frontend/src/components/layout/PortalLayout.tsx 员工端导航新增考勤入口

P1:工资条发布与定时发送

问题描述

现有 Money.tsx 可生成工资条,员工端 portal/Payslip.tsx 可查看,但缺少"发布工资条"和"定时发送"功能。白话用工侠支持 HR 发布工资条后员工才能看到,并支持定时发送。

数据模型

复用已有 Payslip 模型,新增发布状态字段:

// 在 Payslip 模型新增字段
model Payslip {
  // ...已有字段
  publishStatus   String?  // UNPUBLISHED/PUBLISHED/SCHEDULED
  publishedAt     DateTime?
  scheduledAt     DateTime? // 定时发送时间
  // confirmedAt 已有
}

后端接口

POST   /api/v1/payroll/batches/:batchId/publish     # 发布工资条
POST   /api/v1/payroll/batches/:batchId/schedule    # 定时发送
GET    /api/v1/payroll/schedule-records              # 定时发送记录
POST   /api/v1/payroll/schedule/:id/cancel           # 取消定时发送

前端改造

Money.tsx — 在批次详情页新增:

  • 「发布工资条」按钮:将批次内所有工资条标记为 PUBLISHED
  • 「定时发送」选项:选择发送时间,到点自动发布
  • 「定时发送记录」入口:查看定时发送列表,可取消

portal/Payslip.tsx — 调整查询逻辑:

  • 发布前:员工端不显示该月工资条
  • 发布后:员工端显示工资条,可查看和确认
  • 定时发送:到点后状态从 SCHEDULED → PUBLISHED

定时发送实现

  • 使用 node-cron 或现有定时任务机制
  • 每分钟检查 scheduledAt <= now && publishStatus = SCHEDULED 的记录
  • 自动更新为 PUBLISHED 并发送通知

涉及文件

文件 改动
backend/prisma/schema.prisma Payslip 模型新增 publishStatus/publishedAt/scheduledAt 字段
backend/src/routes/payroll.routes.tspayroll2.routes.ts 新增发布/定时发送/取消接口
backend/src/index.ts 注册定时任务
frontend/src/pages/Money.tsx 批次详情页新增发布/定时发送按钮
frontend/src/pages/portal/Payslip.tsx 查询逻辑增加 publishStatus 过滤
backend/src/routes/portal.routes.ts 员工端 payslip 接口增加 publishStatus 过滤

P2:合同到期处理弹窗(增强)

问题描述

现有 Dashboard.tsx 有合同到期提醒,但仅显示列表。白话用工侠支持到期合同弹窗处理:发送续签通知、已线下续签、终止合同、自定义签署,并可查看合同PDF。

前端改造

Dashboard.tsx — 合同到期待办项增加操作弹窗:

合同到期处理弹窗:
├── 员工信息 + 合同信息(类型/期限/到期日)
├── 合同PDF查看链接(如有附件)
└── 操作按钮:
    ├── 发送续签通知 → 调用通知接口
    ├── 已线下续签 → 更新合同状态 + 创建新合同记录
    ├── 终止合同 → 跳转 Termination 模块
    └── 自定义签署 → 跳转 WorkProcess CUSTOM_CONTRACT

涉及文件

文件 改动
frontend/src/pages/Dashboard.tsx 合同到期待办增加操作弹窗
backend/src/routes/dashboard.routes.ts 如需新增批量操作接口

实施计划

优先级排序

优先级 功能 预估工作量 建议时间
P0 AI文件审查上传 1-2天 立即
P0 用工办理工作流 Phase 1-2 5-7天 本周
P1 企业自建文本库 2-3天 下周
P1 考勤发布 2天 下周
P1 工资条发布与定时发送 2-3天 下周
P0 用工办理工作流 Phase 3-4 5-7天 第三周
P2 合同到期处理弹窗 1-2天 第三周

分周计划

  • 第1周:AI文件审查上传 + 用工办理 Phase 1-2(数据模型 + CRUD + 4个高频流程)
  • 第2周:企业文本库 + 考勤发布 + 工资条发布
  • 第3周:用工办理 Phase 3-4(剩余9类流程 + 审批) + 合同到期弹窗 + 联调测试

总工作量

约 18-26 个工作日

数据库迁移

所有新增模型和字段变更需要执行:

cd backend && npx prisma db push

风险与注意事项

  1. 用工办理工作流是最复杂的功能,建议先实现4个高频流程(录用/入职/续签/终止),验证架构后再扩展剩余9类
  2. 企业文本库的变量提取逻辑需与系统模板保持一致,复用 renderTemplate 函数
  3. 工资条发布涉及薪资敏感数据,需确保只有发布后员工端才能看到,发布前 publishStatus = UNPUBLISHED 的记录在员工端不可见
  4. AI文件审查的 .doc 旧格式支持有限,建议仅支持 .docx 并提示用户转换
  5. 定时发送需要确保服务器进程持续运行(PM2 已有保障),定时任务需做幂等处理防止重复发布
  6. 用工办理工作流的13类流程提交后业务联动逻辑较复杂,每类流程需独立编写 executeWorkProcess(type, formData) 逻辑
  7. 考勤发布需考虑已取消发布的月份是否允许重新发布(@@unique([orgId, month]) 约束需处理)
  8. 合同到期弹窗的"发送续签通知"需复用现有通知模块 Notifications.tsx 的逻辑