# 绩效管理模块 - 错误码文档

> **module**: performance
> **doc_type**: ErrorCodes
> **status**: Active
> **owner**: FFOA 开发团队
> **upstream_docs**: 07-api.md, 04-state-machine.md
> **last_verified**: 2026-03-20

---

### 错误码格式

```
PERF_{分类}_{序号}
```

- **分类**：CYCLE（周期）、KPI、E360（360评估）、CAL（校准）、RESULT（结果）、REPORT（统计）、COMMON（通用）
- **序号**：三位数字

> **已废弃分类**（功能已移出当前版本，错误码不再使用）：INTERVIEW（面谈）、FEEDBACK（持续反馈）、EVAL（评估，语义已合并到 KPI 分类）

> **空数据不是错误**：列表/概览类 API 在无数据时返回 200 + 空结构（`{ items: [], total: 0 }` 或 `{ distribution: [] }` 等），不使用 404/400 表示"暂无数据"。

### 错误码清单

#### 通用错误码

| 错误码 | HTTP | 说明 | 处理建议 |
|--------|------|------|----------|
| PERF_COMMON_001 | 401 | 未认证或 Token 失效 | 重新登录获取 Token |
| PERF_COMMON_002 | 403 | 无权限访问资源 | 检查权限或联系管理员 |
| PERF_COMMON_003 | 400 | 参数校验失败 | 修正请求参数 |
| PERF_COMMON_004 | 404 | 资源不存在 | 检查资源 ID |
| PERF_COMMON_005 | 500 | 服务器内部错误 | 联系管理员 |
| PERF_COMMON_006 | 409 | 重复操作（幂等性冲突） | 刷新页面查看最新状态 |
| PERF_COMMON_007 | 403 | 跨组织访问被拒绝 | 检查组织权限 |

#### 周期管理错误码

| 错误码 | HTTP | 说明 | 处理建议 |
|--------|------|------|----------|
| PERF_CYCLE_001 | 404 | 绩效周期不存在 | 检查周期 ID |
| PERF_CYCLE_002 | 400 | 周期日期配置无效 | 结束日期必须晚于开始日期 |
| PERF_CYCLE_003 | 400 | 周期日期与现有周期冲突 | 调整日期范围避免重叠 |
| PERF_CYCLE_004 | 409 | 周期状态不允许该操作 | 检查当前周期状态 |
| PERF_CYCLE_005 | 409 | 无法删除非草稿周期 | 仅可删除 DRAFT 状态的周期 |
| PERF_CYCLE_006 | 400 | 周期已归档不可修改 | 归档数据为只读 |
| PERF_CYCLE_007 | 400 | 存在未完成评估无法完成周期 | 先完成或关闭所有评估 |
| PERF_CYCLE_008 | 403 | 无权限管理周期（当前实现统一使用 PERF_COMMON_002，本码保留但未使用） | 需要 HR 角色 |

#### KPI 错误码

| 错误码 | HTTP | 说明 | 处理建议 |
|--------|------|------|----------|
| PERF_KPI_001 | 404 | KPI 不存在 | 检查 KPI ID |
| PERF_KPI_002 | 404 | KPI 分配不存在 | 检查分配 ID |
| PERF_KPI_003 | 404 | KPI 考核记录不存在 | 检查考核 ID |
| PERF_KPI_004 | 400 | KPI 权重总和必须为 100% | 调整各 KPI 权重 |
| ~~PERF_KPI_005~~ | — | ~~已废弃（指标库重复分配，功能已移出）~~ | — |
| PERF_KPI_006 | 400 | 考核状态不允许该操作 | 检查考核当前状态 |
| PERF_KPI_007 | 400 | 自评已提交不可修改 | 自评已锁定 |
| PERF_KPI_008 | 409 | 需先完成自评（业务前置条件不满足） | 等待员工提交自评 |
| PERF_KPI_009 | 400 | 评分超出有效范围 | 评分应在 0-100 之间 |
| PERF_KPI_010 | 403 | 只能评估直属下属 | 无权评估该员工 |
| ~~PERF_KPI_011~~ | — | ~~已废弃（指标库权限，功能已移出）~~ | — |
| PERF_KPI_012 | 400 | 年度/季度目标不一致 | 季度合计需等于年度目标 |
| PERF_KPI_013 | 400 | 年度目标缺失 | 请先设置年度目标 |
| PERF_KPI_014 | 400 | KPI 名称重复（同一员工同一周期） | 修改 KPI 名称 |
| PERF_KPI_015 | 409 | KPI 已提交，不可编辑 | 联系经理驳回后再编辑 |
| PERF_KPI_016 | 400 | 跨部门依赖人不存在或不在目标组织 | 检查依赖人 ID |
| PERF_KPI_017 | 409 | 依赖已确认，不可重复操作 | 无需重复确认 |
| PERF_KPI_018 | 409 | 存在未确认依赖，无法提交全部 KPI | 等待依赖方确认 |
| PERF_KPI_019 | 404 | KPI 依赖记录不存在 | 检查依赖 ID |

> **关于 EVAL 分类**：原 PERF_EVAL_001/002/003 与 KPI_007/009/008 语义重复，代码实现统一使用 KPI 分类错误码，EVAL 分类已废弃。04-state-machine.md 中的 PERF_EVAL_003 引用等价于 PERF_KPI_008，PERF_EVAL_002 等价于 PERF_KPI_009。

#### 360 评估错误码

| 错误码 | HTTP | 说明 | 处理建议 |
|--------|------|------|----------|
| PERF_E360_001 | 404 | 360 评估不存在 | 检查评估 ID |
| PERF_E360_002 | 404 | 评估任务不存在 | 检查任务 ID |
| PERF_E360_003 | 400 | 评估状态不允许该操作 | 检查评估当前状态 |
| PERF_E360_004 | 400 | 评估人数不足 | 需达到最低评估者人数 |
| PERF_E360_005 | 400 | 评估问卷未配置 | 请选择评估模板 |
| PERF_E360_006 | 400 | 评估已过截止日期 | 无法提交过期任务 |
| PERF_E360_007 | 400 | 评估任务已提交 | 不可重复提交 |
| PERF_E360_008 | 400 | 必填评估维度未完成 | 请完成所有必填项 |
| PERF_E360_009 | 400 | 评分超出有效范围 | 评分应在 1-5 之间 |
| PERF_E360_010 | 400 | 结果未达到最低提交数 | 需等待更多评估者提交 |
| PERF_E360_011 | 403 | 无权查看该评估 | 仅被评估者和 HR 可查看 |
| PERF_E360_012 | 403 | 无权发起 360 评估 | 需要 HR 或经理角色 |
| PERF_E360_013 | 400 | 评估关系已存在 | 不可重复添加评估者 |
| PERF_E360_014 | 400 | 未配置 360 模板，无法发起评估 | 先配置模板 |
| PERF_E360_015 | 409 | 同一评估者已提交，不可重复提交 | 无需重复提交 |
| PERF_E360_016 | 400 | 评估维度不匹配模板定义 | 检查模板配置 |

#### 绩效校准错误码

| 错误码 | HTTP | 说明 | 处理建议 |
|--------|------|------|----------|
| PERF_CAL_003 | 400 | 等级调整原因不能为空 | 请填写调整原因 |
| PERF_CAL_004 | 400 | 等级分布校验不通过 | 调整等级分布 |
| PERF_CAL_005 | 403 | 无权校准 | 需要 HR 权限 |

> **已废弃**：PERF_CAL_001（校准会议不存在）、PERF_CAL_002（校准会议状态不允许）——校准会议功能已废弃，当前校准为直接等级调整。

#### 绩效结果错误码

| 错误码 | HTTP | 说明 | 处理建议 |
|--------|------|------|----------|
| PERF_RESULT_001 | 404 | 绩效结果不存在 | 检查结果 ID |
| PERF_RESULT_002 | 403 | 结果未发布不可查看 | 等待发布 |
| PERF_RESULT_003 | 400 | 权重合计必须为 100% | 调整权重配置 |
| PERF_RESULT_004 | 400 | KPI 评估未完成 | 完成评估后重试 |
| PERF_RESULT_005 | 409 | 结果已确认，不可重复确认 | 无需重复操作 |
| PERF_RESULT_006 | 400 | 申诉原因为空或过短（<10字符） | 填写详细申诉原因 |
| PERF_RESULT_007 | 409 | 结果未发布，员工无法确认/申诉 | 等待 HR 发布结果 |
| PERF_RESULT_010 | 400 | 该结果未处于申诉状态，无法处理申诉 | 确认结果状态为 APPEALED |

#### 统计分析错误码

| 错误码 | HTTP | 说明 | 处理建议 |
|--------|------|------|----------|
| PERF_REPORT_001 | 400 | 缺少必要参数 | 检查 cycleId/departmentId |
| PERF_REPORT_002 | 403 | 无权查看报表 | 检查权限 |

---

### 错误响应格式

```json
{
  "code": "PERF_KPI_004",
  "message": "KPI 权重总和必须为 100%",
  "details": {
    "currentTotal": 80,
    "expected": 100
  }
}
```

### 错误处理流程

```mermaid
graph TD
    A[API 请求] --> B{参数校验}
    B -->|失败| C[返回 PERF_COMMON_003]
    B -->|成功| D{权限检查}
    D -->|失败| E[返回 PERF_COMMON_002]
    D -->|成功| F{业务逻辑}
    F -->|资源不存在| G[返回 PERF_XXX_001]
    F -->|状态不允许| H[返回 PERF_XXX_003/004]
    F -->|业务规则违反| I[返回具体错误码]
    F -->|成功| J[返回成功响应]
```

### 前端错误处理建议

| 错误类型 | 处理方式 |
|----------|----------|
| 401 | 跳转登录页 |
| 403 | 显示无权限提示 |
| 404 | 显示资源不存在提示 |
| 400 | 显示具体错误信息 |
| 500 | 显示通用错误提示 |

### 国际化

错误信息需支持中英文，使用 i18n key：

```
performance.error.PERF_KPI_004=KPI 权重总和必须为 100%
performance.error.PERF_KPI_004.en=KPI weights must sum to 100%
```

### 代码对齐待办

所有项已完成对齐，代码均通过 `PERFORMANCE_ERROR_CODES` 常量引用：

| 代码位置 | 常量键 | 错误码 | 状态 |
|----------|--------|--------|------|
| `kpi.service.ts` submitAllKpi | `KPI_DEPENDENCY_UNCONFIRMED` | `PERF_KPI_018` | ✅ 已完成 |
| `kpi.service.ts` confirmDependency/rejectDependency | `KPI_DEPENDENCY_NOT_FOUND` | `PERF_KPI_019` | ✅ 已完成 |
| `result.service.ts` resolveAppeal | `RESULT_NOT_APPEALED` | `PERF_RESULT_010` | ✅ 已完成 |

---

**创建时间**: 2025-12-25
**更新时间**: 2026-03-20
**状态**: Active
**版本**: v3.6
