# 劳动用工合规 SaaS — 功能层面优化清单

> **文档编号**: 20260723-优化-3.md
> **日期**: 2026-07-23
> **来源**: 对 Money.tsx、Termination.tsx、SocialInsurance.tsx、Roster.tsx 四个核心业务页面深入研究后得出

---

## 一、高优先级（核心业务缺陷）

### 1. Money — 发薪批次创建后无法重命名

**现状**: 批次列表只显示自动生成的名称（如"2026-01 第1批 发薪"），创建后名称固定不可修改。当企业有多个批次（按部门/按职级分批发薪）时，列表难以区分。

**建议**:
- 后端：PUT `/payroll2/batches/:id` 支持更新 `name` 字段
- 前端：在 `BatchDetail` 右上角增加「重命名」按钮，弹出编辑框修改批次名称

**涉及文件**: `backend/src/routes/payroll2.routes.ts`、`frontend/src/pages/Money.tsx`

---

### 2. Termination — 费用计算与表单完全割裂

**现状**: `costResult` 是纯前端 `useMemo` 计算，但编辑表单字段（解聘日期、解聘原因）时不会实时触发重算。用户必须切到 Step 4 才能看到费用变化，导致操作反馈链路过长。

**建议**:
- 将 `costResult` 的依赖项（`terminationDate`、`socialAvgWage`、`reason`）用 `useEffect` 驱动，每次表单变更实时展示费用预览
- 在 Step 1（选择员工）和 Step 2（解聘方式）之间增加一个「实时费用预览区」，显示经济补偿金、赔偿金、代通知金的大致金额，降低误操作风险

**涉及文件**: `frontend/src/pages/Termination.tsx`

---

### 3. Termination — 模拟计算结果被静默覆盖

**现状**: `handleSimulate` 只将数据存入本地 state `savedItems`，`costResult` 依赖的是表单实时值。当用户修改参数后，之前的模拟结果会被静默覆盖，无法对比不同参数下的补偿金额。

**建议**:
- `savedItems` 每条记录增加 `version` 字段和 `isSimulated: boolean` 标记
- 每次模拟生成新版本而非覆盖，用户可在右侧列表查看多个版本的对比
- 模拟结果与实际保存结果分开展示，避免混淆

**涉及文件**: `frontend/src/pages/Termination.tsx`

---

### 4. Roster — 批量续签无合规预检

**现状**: 批量续签直接提交 `contractIds`，无任何预览或合规检查。用户可能对已连续签订两次固定期限合同的员工续签固定期（法律上应签无固定期限）。

**建议**:
- 选择员工后，先调用后端接口 `GET /employees/contracts/preview-renew` 返回每个员工的合规提示
- 展示预览列表：每个员工一行，显示「可续签固定期」或「应签无固定期限（已连续签订X次）」等提示
- 用户确认后再提交，避免法律风险

**涉及文件**: `frontend/src/pages/Roster.tsx`、`backend/src/routes/employee.routes.ts`

---

### 5. SocialInsurance — 社保基数调整只能一次性操作

**现状**: `adjustmentDone` 标志为 true 后无法再次调整基数。但实践中基数可能需要多次修正（员工投诉、基数算错、重新申报）。

**建议**:
- 增加「重置调整」接口 `POST /social/config/:id/reset-adjustment`，允许管理员撤销本次调整重新来过
- 或改为记录每次调整的版本历史，支持查看历史调整记录

**涉及文件**: `backend/src/routes/social.routes.ts`、`frontend/src/pages/SocialInsurance.tsx`

---

## 二、中优先级（高频操作体验）

### 6. Roster — 员工搜索无分页、无法多选过滤

**现状**: 花名册仅支持姓名/部门 substring 搜索，无分页和高级过滤。添加人员到批次时取 `pageSize: 100`，超过 100 人就覆盖不全。

**建议**:
- 花名册搜索增加状态过滤（在职/预入职/离职）、合同状态过滤（正常/即将到期/已过期/未签合同）、合同到期时间范围过滤
- 添加人员到批次改为服务端搜索，支持分页 + 关键词搜索 + 多选，超 100 人场景也能覆盖

**涉及文件**: `frontend/src/pages/Roster.tsx`、`backend/src/routes/roster.routes.ts`、`backend/src/routes/payroll2.routes.ts`

---

### 7. Money — 批次列表无月份范围筛选

**现状**: 只有单月筛选，企业要查看历史所有批次只能逐月切换，且无状态（草稿/归档）过滤。

**建议**:
- 批次列表增加月份范围选择器（开始月份 ~ 结束月份）
- 增加状态过滤（全部/草稿/已归档）
- 增加批次类型过滤（全部/常规发薪/离职结算/年终奖/补偿金）

**涉及文件**: `frontend/src/pages/Money.tsx`、`backend/src/routes/payroll2.routes.ts`

---

### 8. Termination — 无批量解聘能力

**现状**: 只能逐个处理。当企业裁员时（如一次性解除 20 人），需重复操作 20 次，体验极差。

**建议**:
- 在「解聘补偿」页面增加「批量解聘」入口
- 选择员工后批量填写共性参数（解聘日期、解聘原因、社保截止月份），差异项（补偿金金额）可逐个补充或批量默认
- 批量提交后统一生成解聘记录和调薪批次

**涉及文件**: `frontend/src/pages/Termination.tsx`、`backend/src/services/termination.service.ts`

---

### 9. Roster — 合同到期预警机制缺失

**现状**: 花名册表头显示合同状态标签（`expiring`、`expired`），但系统无主动预警。用户需主动逐个查看。

**建议**:
- Dashboard 增加合同到期预警卡片，显示 30 天内到期、60 天内到期、90 天内到期的员工数量
- 点击卡片跳转花名册，预设筛选条件为「合同到期时间 ≤ N 天」
- Roster 列表页增加「合同到期时间」列，支持按到期时间排序

**涉及文件**: `frontend/src/pages/Dashboard.tsx`、`frontend/src/pages/Roster.tsx`、`backend/src/routes/roster.routes.ts`

---

### 10. Money — 无工资条税率试算预览

**现状**: `PayslipManager` 只能从批次汇总生成工资条，无法单独查看某员工的个税明细和实发金额分解。

**建议**:
- 在批次详情页或员工 profile 的 payslip tab 中，增加「税率试算」功能
- 展示个税计算过程：应发金额 → 社保公积金扣除 → 个税起征点扣除 → 应纳税所得额 → 税率/速算扣除数 → 个税 → 实发金额
- 支持单员工试算，不依赖批次

**涉及文件**: `frontend/src/pages/Money.tsx`、`frontend/src/pages/Roster.tsx`、`backend/src/services/payroll.service.ts`

---

## 三、低优先级（功能补全）

### 11. SocialInsurance — 仅支持北京配置，无多城市扩展

**现状**: `newVersion` 硬编码北京配置，版本历史中城市字段存在但无人使用。

**建议**:
- 后续扩展多城市时，社保配置表增加 `cityCode` 字段
- 版本历史按城市分组展示
- 城市列表可配置（新增城市配置时自动出现在下拉）

**涉及文件**: `backend/prisma/schema.prisma`、`frontend/src/pages/SocialInsurance.tsx`

---

### 12. Termination — 离职与解聘入口分离不清晰

**现状**: `ResignModal`（员工主动离职）和解聘向导（公司主导）是两套流程，但在同一个「解聘补偿」模块中容易让用户困惑。

**建议**:
- 在 Step 1 员工选择后，优先展示「员工主动离职」vs「公司解聘」两个入口
- 选择「主动离职」则弹出简化版离职表单（仅需离职日期和原因）
- 选择「公司解聘」则进入完整解聘向导

**涉及文件**: `frontend/src/pages/Termination.tsx`、`frontend/src/pages/Roster.tsx`

---

### 13. Roster — 员工附件上传无预览

**现状**: 合同扫描件以 DataURL 形式存储，无文件大小校验，无 PDF/Word 在线预览。

**建议**:
- 附件上传增加文件类型限制（仅 PDF/图片）和大小限制（最大 10MB）
- 员工 profile 附件 tab 增加文件预览功能（图片直接显示，PDF 用 iframe 或第三方预览组件）
- 上传前显示文件大小提示

**涉及文件**: `frontend/src/pages/Roster.tsx`

---

### 14. Money — 加班费 CSV 导入无批量编辑

**现状**: CSV 导入后只能整体确认，无法逐条修改导入数据中的工时数值。

**建议**:
- 导入预览阶段支持逐行编辑工时数据（工作日/休息日/节假日小时数）
- 增加「校验」按钮，对齐员工姓名未匹配的记录高亮提示
- 支持从预览中删除不需要的记录

**涉及文件**: `frontend/src/pages/Money.tsx`（OvertimeCalculator 组件）

---

## 四、优先级总览

| 优先级 | 编号 | 功能 | 工作量 |
|--------|------|------|--------|
| P0 | 1 | 发薪批次重命名 | 小 |
| P0 | 2 | 费用计算实时预览 | 中 |
| P0 | 4 | 批量续签合规预检 | 中 |
| P0 | 5 | 社保基数调整可重复操作 | 小 |
| P1 | 3 | 模拟计算版本管理 | 小 |
| P1 | 6 | 员工搜索分页+多选过滤 | 中 |
| P1 | 7 | 批次列表范围筛选 | 小 |
| P1 | 8 | 批量解聘 | 大 |
| P1 | 9 | 合同到期预警 | 中 |
| P1 | 10 | 工资条税率试算 | 中 |
| P2 | 12 | 离职/解聘入口分离 | 小 |
| P2 | 13 | 附件上传预览 | 中 |
| P2 | 14 | 加班费导入批量编辑 | 中 |
| P3 | 11 | 多城市社保配置 | 大 |