# TurboHR 优化方案(20260730) > 日期:2026-07-30 > 依据:白话用工侠完整运行测试报告对比分析 + 功能缺口梳理 > 优先级:P0(紧急/核心)、P1(重要补全)、P2(增强优化) --- ## 背景 将「白话用工侠完整运行测试报告」中列出的功能与本系统(TurboHR)实际代码逐一对比后,识别出以下功能缺口: ### 已实现功能(14项) | 功能 | 对应文件 | |------|---------| | 登录与全局框架 | `Login.tsx`、`SidebarNav`、`TopNav` | | 工作台(合规健康度/风险预警/待办) | `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.tsx`、`MedicalPeriodCalculator.tsx` | ### 部分实现功能(3项) | 功能 | 已有部分 | 缺失部分 | |------|---------|---------| | AI 文件审查 | 粘贴合同文本审查、结构化风险报告 | 不支持上传 doc/docx 文件,无文书类型选择 | | 考勤管理 | 考勤记录导入、查看、统计 | 无"发布考勤表"功能 | | 工资条管理 | 工资条生成、员工端查看 | 无"发布工资条"和"定时发送"功能 | ### 未实现功能(5项) | 功能 | 说明 | |------|------| | 用工办理工作流(13类流程) | 最大的功能缺口,无统一办理工作流系统 | | 背景调查 | 完全未实现(本次暂不纳入) | | 视频中心 | 完全未实现(本次暂不纳入) | | 企业自建文本库 | 无企业自建文本管理功能 | | 合同到期处理弹窗 | 有到期提醒但无多选项处理弹窗(本次暂不纳入) | **本次优化聚焦4项功能**:用工办理工作流、企业自建文本库、考勤/工资条发布、AI文件审查上传。 --- ## P0:AI文件审查上传功能 ### 问题描述 现有 `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` 依赖 | ### 实现方案 #### 后端:文件上传 + 文本提取 ```typescript // 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 提取文本 │ └── 提取成功后自动填入下方输入框 ├── 文本输入框(现有,用户可编辑提取后的文本) ├── 开始审查按钮(现有) └── 审查结果展示(现有) ``` #### 依赖安装 ```bash cd backend && npm install mammoth ``` ### 安全考虑 - 文件大小限制:100MB(multer 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) | ### 数据模型 ```prisma // 用工办理流程 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个,只读),企业无法创建和管理自己的文本模板。白话用工侠有"企业文本库"功能,支持自建文本。 ### 数据模型 ```prisma // 企业自建文本模板 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.ts` 的 `renderTemplate` 函数 - 内容编辑器:使用 textarea + 变量插入按钮(点击插入 `{{变量名}}`) - 权限:ADMIN/HR 可增删改,VIEWER 只读 --- ## P1:考勤发布流程 ### 问题描述 现有 `Attendance.tsx` 有考勤记录和统计功能,但缺少"发布考勤表"功能。白话用工侠支持 HR 发布月度考勤表,员工在员工端查看确认。 ### 数据模型 ```prisma // 考勤发布记录 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` 模型,新增发布状态字段: ```prisma // 在 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.ts` 或 `payroll2.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 个工作日 ### 数据库迁移 所有新增模型和字段变更需要执行: ```bash 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` 的逻辑