# 审批中心 - API 文档

> **版本**: v1.0  
> **最后更新**: 2026-01-21  
> **维护者**: 后端团队  
> **状态**: 🚧 Draft

---

## ✅ 机器读取区（必填）

### 实际调用前缀（v2.x 现状）

> ⚠️ **没有 `/approval-center/*` 这套后端接口**。审批中心是**前端模块名**，
> 后端实现复用 `approval-engine` 的全部路由。前端的"我发起 / 待办 / 已办 / 管理员数据中心"
> 直接调用 `/api/v1/approval/...` 下的接口分组：

| 用户场景 | 实际调用前缀 | 说明 |
|---------|--------------|------|
| 发起审批 | `POST /api/v1/approval/start` | 启动流程 |
| 我的待办 / 已办 / 我发起 / 抄送 | `GET /api/v1/approval/my/...` | 用户态查询 |
| 审批操作（通过/驳回/退回/转发等） | `POST /api/v1/approval/instances/:id/...` | 任务操作 |
| 管理员数据中心（统计/明细/导出） | `/api/v1/approval/admin/...` | 管理员视图 |

详见 [approval-engine/07-api.md](../approval-engine/07-api.md)。

### 统一约定

- Base URL: `/api/v1/approval`（与 approval-engine 同前缀）
- 认证: Bearer Token (JWT)
- 错误码: [08-error-codes.md](./08-error-codes.md)
- 统一拦截器: 成功响应由 `TransformInterceptor` 统一包装；错误响应由 `AllExceptionsFilter` 统一格式化
- 响应封装:
  - 成功: `{ "success": true, "data": {...}, "message": "success", "timestamp": "...", "path": "/api/v1/..." }`
  - 失败: `{ "success": false, "error": { "code": "<ERROR_CODE>", "message": "<i18n.key>", "...": "..." }, "timestamp": "...", "path": "/api/v1/...", "method": "GET", "statusCode": 400 }`
- 说明: 本文档主要覆盖审批中心「管理员数据中心」相关接口；审批引擎的完整接口清单（54 个）由 [approval-engine/07-api.md](../approval-engine/07-api.md) 维护。

### 通用状态码

| 状态码 | 说明 |
|-------|------|
| 200 | 成功 |
| 400 | 参数错误/业务校验失败 |
| 401 | 未认证 |
| 403 | 无权限 |
| 404 | 资源不存在 |
| 409 | 业务冲突 |
| 422 | 数据校验失败 |

### 接口数量汇总

- 总计: 7 个接口
- 统计口径: 下方“接口清单（按域）”中的全部路径

---

## 接口清单（按域）

### 1) 管理员数据中心（7）

| 序号 | 方法 | 路径 | 权限 |
|------|------|------|------|
| 001 | GET | /admin/analytics | approval:admin |
| 002 | GET | /admin/instances | approval:admin |
| 003 | POST | /admin/instances/export | approval:admin |
| 004 | GET | /admin/exports | approval:admin |
| 005 | GET | /admin/exports/{taskId} | approval:admin |
| 006 | GET | /admin/settings | approval:admin |
| 007 | PUT | /admin/settings | approval:admin |

---

## 数据结构定义（字段级）

### 通用响应封装

#### SuccessResponse<T>

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| success | Boolean | ✅ | 成功标记，固定为 true |
| data | T | ✅ | 业务数据 |
| message | String | ✅ | 提示信息，默认 `success` |
| timestamp | DateTime | ✅ | 响应时间 |
| path | String | ✅ | 请求路径 |

#### ErrorResponse

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| success | Boolean | ✅ | 成功标记，固定为 false |
| error.code | String | ✅ | 错误码 |
| error.message | String | ✅ | i18n key 或可读信息 |
| error.details | JSON | ❌ | 额外上下文 |
| timestamp | DateTime | ✅ | 响应时间 |
| path | String | ✅ | 请求路径 |
| method | String | ✅ | HTTP 方法 |
| statusCode | Int | ✅ | HTTP 状态码 |

### 业务实体与 DTO

#### AdminAnalyticsQuery

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| formKey | String | ❌ | 表单 key |
| formDefinitionId | UUID | ❌ | 表单定义 ID |
| businessType | String | ❌ | 业务类型（FORM_INSTANCE） |
| approvalRequired | Boolean | ❌ | 是否需要审批 |
| status | String | ❌ | 状态筛选 |
| timeFrom | Date | ❌ | 开始日期（含） |
| timeTo | Date | ❌ | 结束日期（含） |
| submitterId | UUID | ❌ | 提交人 ID |
| organizationId | UUID | ❌ | 组织 ID |
| departmentId | UUID | ❌ | 部门 ID |
| keyword | String | ❌ | 关键字 |

#### AdminInstancesQuery

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| page | Int | ❌ | 页码（默认 1） |
| limit | Int | ❌ | 每页数量（默认 20） |
| 其余字段 |  |  | 同 AdminAnalyticsQuery |

#### UserInfo

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | UUID | ✅ | 用户 ID |
| name | String | ✅ | 展示名称 |
| avatar | String | ❌ | 头像 URL |

#### AdminInstanceItem

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| instanceId | UUID | ❌ | 审批实例 ID |
| businessInstanceId | UUID | ✅ | 业务实例 ID |
| businessType | String | ✅ | 业务类型 |
| formKey | String | ❌ | 表单 key |
| formName | String | ❌ | 表单名称 |
| submitter | UserInfo | ✅ | 提交人 |
| status | String | ✅ | 当前状态 |
| currentNode | String | ❌ | 当前节点名称 |
| submittedAt | DateTime | ✅ | 提交时间 |
| durationMs | Int | ❌ | 耗时毫秒 |
| approvalRequired | Boolean | ✅ | 是否需要审批 |

#### AdminInstancesResponse

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| items | AdminInstanceItem[] | ✅ | 明细列表 |
| total | Int | ✅ | 总数 |
| page | Int | ✅ | 当前页 |
| limit | Int | ✅ | 每页数量 |
| totalPages | Int | ✅ | 总页数 |
| hasNext | Boolean | ✅ | 是否有下一页 |
| hasPrev | Boolean | ✅ | 是否有上一页 |

#### AdminAnalyticsResponse

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| summary.totalSubmissions | Int | ✅ | 总提交数 |
| summary.approvalRate | Number | ✅ | 通过率（%） |
| summary.rejectRate | Number | ✅ | 拒绝率（%） |
| summary.avgDurationMs | Int | ✅ | 平均耗时（ms） |
| summary.runningCount | Int | ✅ | 审批中数量 |
| trends[].date | Date | ✅ | 日期 |
| trends[].submissions | Int | ✅ | 提交数 |
| trends[].approvals | Int | ✅ | 通过数 |
| trends[].rejections | Int | ✅ | 拒绝数 |
| distribution[].formKey | String | ✅ | 表单 key |
| distribution[].formName | String | ✅ | 表单名称 |
| distribution[].count | Int | ✅ | 数量 |

#### AdminExportCreateRequest

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| format | String | ✅ | 导出格式（xlsx/csv） |
| businessType | String | ✅ | 业务类型（FORM_INSTANCE） |
| 其余字段 |  |  | 同 AdminAnalyticsQuery |

#### AdminExportItem

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | UUID | ✅ | 导出任务 ID |
| status | String | ✅ | PENDING/PROCESSING/SUCCESS/FAILED/EXPIRED |
| format | String | ✅ | 导出格式 |
| fileName | String | ❌ | 文件名 |
| fileSize | Int | ❌ | 文件大小 |
| contentType | String | ❌ | 内容类型 |
| downloadUrl | String | ❌ | 下载链接 |
| createdAt | DateTime | ✅ | 创建时间 |
| completedAt | DateTime | ❌ | 完成时间 |
| expiresAt | DateTime | ❌ | 过期时间 |

#### AdminSettings

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| exportRetentionDays | Int | ✅ | 导出保留天数（7-365） |

---

## 统一格式 + 简短示例

### 1) 管理员数据中心（7）

**[001] GET /admin/analytics**
- 说明: 管理员数据中心统计
- 请求 Query: AdminAnalyticsQuery
- 响应 Data: AdminAnalyticsResponse
- 示例请求: `GET /api/v1/approval/admin/analytics?approvalRequired=true`
- 示例响应:
  ```json
  {
    "success": true,
    "data": {
      "summary": {
        "totalSubmissions": 12,
        "approvalRate": 90,
        "rejectRate": 10,
        "avgDurationMs": 32000,
        "runningCount": 2
      },
      "trends": [{ "date": "2026-01-21", "submissions": 5, "approvals": 4, "rejections": 1 }],
      "distribution": [{ "formKey": "form_xxx", "formName": "示例表单", "count": 5 }]
    },
    "message": "success",
    "timestamp": "2026-01-21T00:00:00.000Z",
    "path": "/api/v1/approval/admin/analytics"
  }
  ```
- 状态码: 200, 401, 403

**[002] GET /admin/instances**
- 说明: 管理员明细列表
- 请求 Query: AdminInstancesQuery
- 响应 Data: AdminInstancesResponse
- 示例请求: `GET /api/v1/approval/admin/instances?page=1&limit=20`
- 示例响应:
  ```json
  {
    "success": true,
    "data": {
      "items": [
        {
          "businessInstanceId": "uuid",
          "businessType": "FORM_INSTANCE",
          "formKey": "form_xxx",
          "formName": "示例表单",
          "submitter": { "id": "uuid", "name": "IT Administrator" },
          "status": "SUBMITTED",
          "submittedAt": "2026-01-21T00:00:00.000Z",
          "approvalRequired": false
        }
      ],
      "total": 1,
      "page": 1,
      "limit": 20,
      "totalPages": 1,
      "hasNext": false,
      "hasPrev": false
    },
    "message": "success",
    "timestamp": "2026-01-21T00:00:00.000Z",
    "path": "/api/v1/approval/admin/instances"
  }
  ```
- 状态码: 200, 401, 403

**[003] POST /admin/instances/export**
- 说明: 创建导出任务
- 请求 Body: AdminExportCreateRequest
- 响应 Data: `{ taskId: UUID }`
- 示例请求: `POST /api/v1/approval/admin/instances/export`
- 示例响应:
  ```json
  {
    "success": true,
    "data": { "taskId": "uuid" },
    "message": "success",
    "timestamp": "2026-01-21T00:00:00.000Z",
    "path": "/api/v1/approval/admin/instances/export"
  }
  ```
- 状态码: 200, 401, 403

**[004] GET /admin/exports**
- 说明: 导出任务列表
- 请求 Query: 无
- 响应 Data: AdminExportItem[]
- 示例请求: `GET /api/v1/approval/admin/exports`
- 示例响应:
  ```json
  {
    "success": true,
    "data": [{ "id": "uuid", "status": "SUCCESS", "format": "xlsx", "createdAt": "2026-01-21T00:00:00.000Z" }],
    "message": "success",
    "timestamp": "2026-01-21T00:00:00.000Z",
    "path": "/api/v1/approval/admin/exports"
  }
  ```
- 状态码: 200, 401, 403

**[005] GET /admin/exports/{taskId}**
- 说明: 导出任务详情
- 请求 Path: taskId
- 响应 Data: AdminExportItem
- 示例请求: `GET /api/v1/approval/admin/exports/uuid`
- 状态码: 200, 401, 403, 404

**[006] GET /admin/settings**
- 说明: 获取导出设置
- 响应 Data: AdminSettings
- 示例请求: `GET /api/v1/approval/admin/settings`
- 状态码: 200, 401, 403

**[007] PUT /admin/settings**
- 说明: 更新导出设置
- 请求 Body: AdminSettings
- 响应 Data: AdminSettings
- 示例请求: `PUT /api/v1/approval/admin/settings`
- 状态码: 200, 400, 401, 403

---

## 前后端枚举与约束

### ApprovalMode 前后端枚举映射

| 前端（designer） | 后端（workflow） | 含义 |
|-----------------|-----------------|------|
| SINGLE | OR_SIGN | 单人审批 |
| AND | COUNTERSIGN | 会签（所有人必须审批） |
| OR | OR_SIGN | 或签 |
| SEQUENTIAL | SEQUENTIAL | 依次审批 |

转换由 `mapApprovalModeForWorkflow()` 处理，历史数据由 `normalizeApprovalMode()` 在响应时标准化。

### ADMIN_APPROVE/REJECT 后端约束

- 执行管理员代审批/代拒绝时，必须记录 `targetUser`（被代审批人）为 `task.assignee`
- 当前前端通过推断 workaround，后端应在写入时持久化 targetUser

### InstanceStatus 前后端对齐

- 前端应使用：RUNNING | SUSPENDED | APPROVED | REJECTED | WITHDRAWN | TERMINATED | FAILED
- 前端不应使用 COMPLETED（后端无此状态）
