# 售后申诉中心 — 管理后台新增接口

- **端类型**：管理后台
- **变更类型**：新增接口
- **日期**：2026-06-22
- **关联 Issue**：https://git.1814.love:8443/wx/HL/issues/4161
- **关联 PR**：#4162 / #4165 / #4168 / #4185 / #4187
- **后端负责人**：腰苏图（yaosutu）

---

## 一、接口背景

v3 全新售后服务中心（com.hulalv.aftersale）上线，支持投诉与申诉两大类工单的完整生命周期管理。

管理后台侧新增 4 个接口：工单分页列表、工单详情、受理工单、处置工单。客服在管理后台完成工单全流程操作，其中退款类处置会触发企微 OA 审批，OA 通过后由系统自动驱动退款。

本次为全新域，不影响任何已有接口。

---

## 二、变更清单

| 编号 | 方法 | 路径 | 说明 |
|------|------|------|------|
| 1 | GET | /v3/admin/aftersale/ticket/page | 售后工单分页列表 |
| 2 | GET | /v3/admin/aftersale/ticket/{id} | 售后工单详情 |
| 3 | POST | /v3/admin/aftersale/ticket/{id}/process | 受理工单（SUBMITTED → PROCESSING） |
| 4 | POST | /v3/admin/aftersale/ticket/{id}/resolve | 处置工单（PROCESSING → RESOLVED/CLOSED） |

---

## 三、接口详情

| 属性 | 说明 |
|------|------|
| 认证方式 | JWT Bearer Token（管理端 Token，Gateway 校验） |
| 幂等性 | GET 天然幂等；POST 接口状态守卫保证重复提交不会二次流转 |
| 限流 | Gateway 默认限流策略 |
| 路径前缀 | /v3/admin/aftersale/ticket |

---

## 四、接口入参

### 4.1 GET /v3/admin/aftersale/ticket/page — 工单分页列表

Query 参数（均可选）：

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| pageNo | Integer | 否 | 页码，默认 1 |
| pageSize | Integer | 否 | 每页条数，默认 10 |
| status | String | 否 | 工单状态过滤，见 §六枚举 |
| category | String | 否 | 大类过滤：COMPLAINT / APPEAL |
| orderId | String（Long） | 否 | 关联订单 ID 精确匹配 |

### 4.2 GET /v3/admin/aftersale/ticket/{id} — 工单详情

路径参数：id（String/Long）必填，工单 ID。

### 4.3 POST /v3/admin/aftersale/ticket/{id}/process — 受理工单

路径参数：id（String/Long）必填，工单 ID。

请求体（JSON，Body 整体可不传，效果等同传空对象）：

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| assigneeId | Long | 否 | 指定处理客服 ID；不传则当前登录管理员自动接单 |
| remark | String | 否 | 受理备注 |

### 4.4 POST /v3/admin/aftersale/ticket/{id}/resolve — 处置工单

路径参数：id（String/Long）必填，工单 ID。

请求体（JSON）：

| 字段 | 类型 | 必填 | 约束 | 说明 |
|------|------|------|------|------|
| decision | String | 是 | APPROVE / REJECT | 处置决定 |
| resolutionType | String | 条件必填 | REFUND / RECTIFY / REJECT | decision=APPROVE 时必填；COMPENSATION 首期不实现，传入返回 586020 |
| resolutionAmount | Number | 条件必填 | >= 0 | decision=APPROVE 且 resolutionType=REFUND 时必填 |
| remark | String | 否 | — | 处置说明，建议填写便于通知用户 |

---

## 五、出参字段

### 5.1 分页接口 — PageResult 结构

```json
{
  "code": 200,
  "data": {
    "list": [],
    "total": 42,
    "pageNo": 1,
    "pageSize": 10
  }
}
```

### 5.2 详情及列表行 — TicketAdminRespVO 字段

| 字段 | 类型 | 说明 |
|------|------|------|
| id | String（Long） | 工单 ID |
| orderId | String（Long） | 关联订单 ID |
| category | String | 大类枚举值：COMPLAINT / APPEAL |
| categoryLabel | String | 大类中文名：投诉 / 申诉 |
| type | String | 细分类型枚举值，见 §六 |
| typeLabel | String | 细分类型中文名 |
| targetRefType | String | 关联对象类型：ORDER / REFUND_APPLICATION |
| targetRefId | String（Long） | 关联对象主键 |
| sourceChannel | String | 来源渠道：MP / ADMIN |
| title | String | 工单标题 |
| description | String | 诉求描述 |
| claimType | String | 用户诉求类型（可选） |
| claimAmount | Number | 用户期望金额（可选，仅供参考，无约束力） |
| attachments | Array<String> | 附件 URL 列表 |
| status | String | 工单状态枚举值，见 §六 |
| statusLabel | String | 工单状态中文名 |
| assigneeId | String（Long） | 处理客服 ID，未受理时为 null |
| decision | String | 处置决定：APPROVE / REJECT，未处置时为 null |
| resolutionType | String | 处置类型，未处置时为 null |
| resolutionAmount | Number | 后台核定金额，非退款类为 null |
| resolutionRemark | String | 处置说明 |
| approvalNo | String | 企微 OA 审批单号，非 REFUND 处置时为 null |
| linkedRefundId | String（Long） | 关联退款单 ID（OA 通过触发退款后回填），null 表示未触发 |
| createdAt | String（ISO 8601） | 创建时间，如 2026-06-22T10:30:00 |
| updatedAt | String（ISO 8601） | 更新时间 |

### 5.3 受理 / 处置接口

```json
{"code": 200, "data": null}
```

---

## 六、枚举 / 数据字典

### AftersaleCategory — 工单大类

| 枚举值 | 中文名 | 场景 |
|--------|--------|------|
| COMPLAINT | 投诉 | 对已发生的服务质量不满 |
| APPEAL | 申诉 | 对某个处理结果不服，求复核 |

### AftersaleTicketType — 细分类型（type 字段）

| 枚举值 | 中文名 | 归属大类 |
|--------|--------|----------|
| ITINERARY | 行程 | COMPLAINT |
| HOTEL | 酒店 | COMPLAINT |
| VEHICLE | 车 | COMPLAINT |
| GUIDE | 导游 | COMPLAINT |
| OTHER | 其他 | COMPLAINT |
| REFUND_REJECTED | 退款被拒 | APPEAL |
| REFUND_AMOUNT_DISPUTE | 退款金额异议 | APPEAL |

注：type 必须与 category 匹配，否则返回 586012。

### AftersaleTicketStatus — 工单状态

| 枚举值 | 中文名 | 终态 | 说明 |
|--------|--------|------|------|
| SUBMITTED | 已提交 | 否 | 等待受理 |
| PROCESSING | 处理中 | 否 | 客服受理中 / OA 审批进行中 |
| RESOLVED | 已处置 | 否 | 处置方案落定，等待退款到账后关闭 |
| CLOSED | 已关闭 | 是 | 流程终结 |
| WITHDRAWN | 已撤回 | 是 | 用户主动撤回 |

状态流转：

```
SUBMITTED -[受理]-> PROCESSING -[APPROVE+REFUND]-> RESOLVED -[退款到账]-> CLOSED
                  |
                  +-[APPROVE+RECTIFY]-> CLOSED
                  +-[decision=REJECT]-> CLOSED
                  +-[用户撤回]-> WITHDRAWN
SUBMITTED -[用户撤回]-> WITHDRAWN
```

### AftersaleDecision — 处置决定

| 枚举值 | 中文名 | 说明 |
|--------|--------|------|
| APPROVE | 通过 | 诉求成立，按 resolutionType 执行 |
| REJECT | 驳回 | 诉求不成立，直接关单 |

### AftersaleResolutionType — 处置类型

| 枚举值 | 中文名 | 走 OA | 说明 |
|--------|--------|------|------|
| REFUND | 退款 | 是 | 提交企微 OA 审批，通过后自动触发退款 |
| RECTIFY | 整改 | 否 | 道歉/整改/解释，直接关单 |
| REJECT | 驳回 | 否 | 诉求不成立，通知用户 |
| COMPENSATION | 补偿（预留） | — | 首期不实现，传入返回 586020 |

### AftersaleTargetRefType — 关联对象类型

| 枚举值 | 中文名 | 场景 |
|--------|--------|------|
| ORDER | 订单 | 投诉场景 |
| REFUND_APPLICATION | 退款申请 | 申诉场景 |

### AftersaleSourceChannel — 来源渠道

| 枚举值 | 中文名 |
|--------|--------|
| MP | 小程序 |
| ADMIN | 管理后台 |

### claimType — 用户诉求类型（可选字段，无强制枚举约束）

| 常见值 | 中文名 |
|--------|--------|
| REFUND | 退款 |
| RECTIFY | 整改 |
| EXPLANATION | 要个说法 |

---

## 七、错误码

| 错误码 | 说明 | 触发场景 |
|--------|------|----------|
| 586009 | 工单不存在 | 传入 id 找不到工单 |
| 586010 | 工单状态不允许该操作 | 通用状态守卫 |
| 586011 | 同一对象已存在活跃工单 | 防重复提交 |
| 586012 | category 与 type 不匹配 | 如 COMPLAINT 传了 REFUND_REJECTED |
| 586017 | 受理时状态非法 | 只有 SUBMITTED 可受理 |
| 586018 | 处置时状态非法 | 只有 PROCESSING 可处置 |
| 586019 | 核定金额非法 | REFUND 处置时 resolutionAmount 为空或负数 |
| 586020 | COMPENSATION 处置首期未实现 | resolutionType=COMPENSATION |

---

## 八、示例

### 8.1 典型成功 — 受理工单（指定客服）

请求：
```
POST /v3/admin/aftersale/ticket/1895000000000001/process
Authorization: Bearer {admin_token}
Content-Type: application/json

{"assigneeId": 42, "remark": "已联系供应商核实中"}
```

响应：
```json
{"code": 200, "data": null}
```

### 8.2 典型成功 — 处置工单（REFUND 类，触发企微 OA）

请求：
```
POST /v3/admin/aftersale/ticket/1895000000000001/resolve
Authorization: Bearer {admin_token}
Content-Type: application/json

{
  "decision": "APPROVE",
  "resolutionType": "REFUND",
  "resolutionAmount": 500.00,
  "remark": "经核实酒店确实降级，同意退差价 500 元"
}
```

响应：```json
{"code": 200, "data": null}
```

注：响应返回后工单仍为 PROCESSING，等待企微 OA 审批通过后系统自动推进，无需前端轮询。

### 8.3 边界情况 — 受理不传 Body（当前管理员自动接单）

```
POST /v3/admin/aftersale/ticket/1895000000000001/process
Authorization: Bearer {admin_token}
```

响应：```json
{"code": 200, "data": null}
```

### 8.4 边界情况 — 处置驳回（decision=REJECT，无需 resolutionType 和金额）

```json
{"decision": "REJECT", "remark": "经核实酒店等级属实，不予退款"}
```

响应：```json
{"code": 200, "data": null}
``` 工单直接变 CLOSED。

### 8.5 业务失败 — REFUND 处置未填金额

```json
{"decision": "APPROVE", "resolutionType": "REFUND"}
```

响应：
```json
{"code": 586019, "msg": "处置涉钱（REFUND）时 resolutionAmount 不能为空或负数"}
```

### 8.6 业务失败 — 受理已 PROCESSING 工单

```json
{"code": 586017, "msg": "受理时工单状态非法（只有 SUBMITTED 可受理）"}
```

---

## 九、业务边界

适用：
- 工单处于正确状态时方可操作（受理须 SUBMITTED，处置须 PROCESSING）
- assigneeId 不传时当前登录管理员自动接单
- decision=REJECT 时 resolutionType / resolutionAmount 可不传，工单直接 CLOSED

不适用：
- 终态工单（CLOSED / WITHDRAWN）不可再受理或处置
- COMPENSATION 处置类型首期未实现，传入直接 586020

特殊边界：
- REFUND 处置后工单不立即关闭，停在 PROCESSING 等企微 OA 审批，OA 通过后系统自动推进
- resolutionAmount（后台核定）与 claimAmount（用户期望）完全独立，前端展示时请区分两者语义

---

## 十、修改前后对比

本次为全新域新增接口，无旧接口对比。

---

## 十一、影响评估 / 回滚

本次为全新域，不影响任何已有接口，可独立上线。

回滚方案：回滚后端服务版本即可；Flyway DDL 由后端管理，前端无感知。

---

## 十二、注意事项

1. 双金额区分：claimAmount（用户期望，无约束力）和 resolutionAmount（后台核定，唯一退款依据）是两个独立字段，请在列表和详情页分别展示，不要混用。
2. REFUND 处置的异步性：调用 resolve 后工单状态仍为 PROCESSING；可根据 decision=APPROVE + resolutionType=REFUND + approvalNo 非空，展示等待 OA 审批的状态。
3. 所有 ID 字段为字符串：id / orderId / assigneeId / targetRefId / linkedRefundId 均序列化为字符串（雪花 ID 防 JS 精度丢失），前端不要转 Number。
4. attachments 为 URL 数组：直接用于展示或下载，无需额外解析。

---

## 十三、关联 / 联系人

- Issue：https://git.1814.love:8443/wx/HL/issues/4161
- PR #4162（售后基建 + 分页/详情）：https://git.1814.love:8443/wx/HL/pulls/4162
- PR #4165（受理/处置接口 + 企微 OA 接入）：https://git.1814.love:8443/wx/HL/pulls/4165
- PR #4168（OA 回调内部接口）：https://git.1814.love:8443/wx/HL/pulls/4168
- PR #4185（小程序端接口）：https://git.1814.love:8443/wx/HL/pulls/4185
- PR #4187（退款驱动联动）：https://git.1814.love:8443/wx/HL/pulls/4187
- 后端负责人：腰苏图（yaosutu）
