文件
hl-api-changelog/changelogs-v2/2026-10/22_9120_回收站列表接口-新增接口-管理后台.md
T
2026-10-22 18:16:38 +08:00

199 行
11 KiB
Markdown
原始文件 Blame 文件历史

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
---
schema: "hl-changelog/v2"
ticket: "9120"
title: "派车工作台回收站列表(撤下派车行分页、来源筛选、能否恢复)"
consumer: "admin"
author: "wx(GIT)"
change_type: "新增接口"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "pending"
frontend_owner: ""
frontend_ref: ""
target_release: "v2.1"
verified_at: "2026-10-22"
status_note: "后端 PR #9126 已合并 dev-v3(squash ead771c42),已部署<测试服>并双实例 is UP;真登录经网关实测 GET 两个筛选均 HTTP 200 / code 200(测试库当前无撤下行,records 为空,31 字段由单测映射用例覆盖)。本单只读,无表/Flyway/菜单/网关变更。"
updated_at: "2026-10-22"
base: "dev-v3"
---
# 派车工作台回收站列表(新增接口)
> 面向:管理后台前端(hl-ui)
> 日期:2026-10-22 | 后端:hl-fleet-service(二期 dev-v3)
> 范围:**纯新增**一个只读分页接口,供「派车工作台 → 回收站」弹窗列出被撤下的派车行,并显示每行能否恢复。
## 一、背景(选填)
3.9「撤下派车行」把行置为 CANCELLED 并写撤下日志,撤销后这些行不再出现在派车工作台的正常列表里。回收站是这些行的只读入口:按撤下时间倒序列出,可按团号/司机/车牌/车队名称搜索,可按撤下来源筛选,并逐行告诉前端「此刻能不能恢复、不能恢复时为什么」。点「恢复」不调本接口,仍走 3.10(请求体带本接口返回的 dispatchVehicleId 与 version)。
本单只交付列表;撤下/恢复事务(3.9/3.10)由后续工单接线,故本单上线后列表可能为空,这是数据现状,不是接口异常。
## 二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 回收站列表 | GET | `/admin/fleet/dispatch-recycle/page` | 新增接口 | 撤下派车行分页,按撤下时间倒序;每行带 restorable/unrestorableReason |
## 三、接口详情
### 1. 回收站列表 `GET /admin/fleet/dispatch-recycle/page`
**VO**: `FleetDispatchRecyclePageReqVO` / `FleetDispatchRecycleRespVO`
#### 使用场景
派车工作台点「回收站」打开弹窗时调用第一页;改关键词/团/撤下来源时从头查;点「恢复」前用本行 restorable 判断按钮是否可点,不可点时把 unrestorableReason 悬浮显示。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|------|------|------|------|------|------|
| keyword | Query | String | 否 | 最长 50 字,trim 后空等于不传 | 任意一样包含:团号/司机姓名/车牌/车队名称;不拆词 |
| focusDispatchVehicleId | Query | String | 否 | 数字 ID | 命中时排到请求页第一条,原位置不再重复;不命中按正常排序 |
| dispatchGroupId | Query | String | 否 | 数字 ID | 只看该团撤下的行 |
| cancelSource | Query | String | 否 | MANUAL/UNASSIGN_ALL/NO_VEHICLE/RETIRED/DATE_CHANGED/REQUIREMENT_CANCELLED | 撤下来源;MANUAL 同时包含 cancel_source 为 NULL 的历史行 |
| page | Query | Integer | 否 | ≥1,默认 1 | 页码 |
| pageSize | Query | Integer | 否 | 1–100,默认 20 | 每页条数 |
#### 出参 `Result<PageResult<FleetDispatchRecycleRespVO>>`
| 字段 | 类型 | 说明 |
|------|------|------|
| dispatchVehicleId | String | 派车行 ID(雪花号,字符串避免精度丢失) |
| version | Integer | 行版本号,点「恢复」时原样回传给 3.10 做乐观锁 |
| dispatchGroupId | String | 所属团 ID;团已不存在也照旧返回 |
| teamNo | String | 团号;团不存在或老数据为空时为 null |
| sourceType | String | 团来源:GROUP/CORE/CUSTOM;团不存在时为 null |
| sourceTypeName | String | 团来源中文 |
| memberOrderId | String | 成员订单 ID;整行/接送关联的户 |
| memberTeamNo | String | 成员团号;为空表示整行或未关联户 |
| contactName | String | 联系人姓名,仅团期产品且成员团号为空时有值 |
| useType | String | 用车类型:TOUR/PICKUP/DROPOFF/MID_SWAP |
| useTypeName | String | 用车类型中文 |
| vehicleTypeId | String | 车型 ID |
| vehicleTypeName | String | 车型名称 |
| fleetTeamId | String | 车队 ID |
| fleetTeamName | String | 车队名称 |
| driverId | String | 司机 ID |
| driverName | String | 司机姓名 |
| plate | String | 车牌 |
| serviceStartDate | String | 服务开始日 yyyy-MM-dd |
| serviceEndDate | String | 服务结束日 yyyy-MM-dd |
| amount | String | 金额,两位小数;无金额为 null |
| lineStatusBeforeCancel | String | 撤下前状态:PENDING/SENT_TO_FLEET/ASSIGNED |
| lineStatusBeforeCancelName | String | 撤下前状态中文 |
| cancelledAt | String | 撤下时间 yyyy-MM-dd HH:mm:ss |
| cancelReason | String | 撤下原因 |
| cancelSource | String | 撤下来源六值之一;老数据为 null 时按 MANUAL 输出 |
| cancelSourceName | String | 撤下来源中文 |
| cancelOperatorId | String | 撤下操作人 ID;系统或旧系统迁来为 null |
| cancelOperatorName | String | 撤下操作人;系统或旧系统迁来为「系统」 |
| restorable | Boolean | 此刻能否恢复;true 表示可点恢复 |
| unrestorableReason | String | 不能恢复时的提示语,取自 3.10 对应错误码;可恢复为 null |
分页外壳 `data` 另有 `total`(Integer,总条数,不受分页影响)、`page`(Integer,当前页)、`pageSize`(Integer,每页条数);顶层为 `code`/`message`/`data`/`success`/`traceId`。
#### 请求示例
```http
GET /admin/fleet/dispatch-recycle/page?page=1&pageSize=20&keyword=沪A12345&cancelSource=MANUAL
Authorization: Bearer <token>
```
#### 响应示例
```json
{"code":200,"message":"成功","data":{"records":[{"dispatchVehicleId":"2103791490167999001","version":3,"dispatchGroupId":"2103791490167888001","teamNo":"HL20261020001","sourceType":"GROUP","sourceTypeName":"团期","memberOrderId":"2103791490167999101","memberTeamNo":"T-0007","contactName":null,"useType":"TOUR","useTypeName":"带团","vehicleTypeId":"2103791490167000001","vehicleTypeName":"7座商务","fleetTeamId":"2103791490166000001","fleetTeamName":"华东车队","driverId":"2103791490165000001","driverName":"王师傅","plate":"沪A12345","serviceStartDate":"2026-10-18","serviceEndDate":"2026-10-20","amount":"3600.00","lineStatusBeforeCancel":"ASSIGNED","lineStatusBeforeCancelName":"已派车","cancelledAt":"2026-10-20 15:12:33","cancelReason":"客户改期","cancelSource":"MANUAL","cancelSourceName":"撤下","cancelOperatorId":"2103791490167934978","cancelOperatorName":"ha_r1_su","restorable":true,"unrestorableReason":null}],"total":1,"page":1,"pageSize":20},"success":true}
```
#### 空数据 / 降级响应
无数据时 `records` 为空数组,`total=0`,HTTP 与业务 code 仍为 200:
```json
{"code":200,"message":"成功","data":{"records":[],"total":0,"page":1,"pageSize":20},"success":true}
```
#### 错误响应
参数非法(page<1、pageSize 不在 1–100、keyword 超过 50 字、cancelSource 不在六值、ID 非数字)统一返回 100001;HTTP 状态码按全局约定:
```json
{"code":100001,"message":"参数非法: page 必须大于等于 1","data":null,"success":false}
```
#### 业务边界
- 只读,不写库;无幂等/并发语义。
- 只列 `line_status='CANCELLED'` 的行;软删行不出现。
- 排序固定 `cancelled_at DESC, dispatch_vehicle_id DESC`(同秒按 ID 大→小),不接受排序参数。
- `restorable` 是「拉列表那一刻」的判定;点恢复时 3.10 会从头重判,可能由可恢复变为不可恢复。
- 不可恢复提示语来自 3.10 的四个错误码:603009 团不存在、603002 团来源订单已取消、603302 这一户已退团、603110 需求已取消。
- 团不存在时 teamNo/sourceType 等团字段为 null,但该行仍会列出(dispatchGroupId 照旧)。
- 关键词不拆词:整串对团号/司机姓名/车牌/车队名称做包含匹配。
## 四、契约约束与正确调用方式(接口类必写)
### ✅ 正确 / ❌ 错误 payload 对照
| 场景 | 查询串 |
|------|--------|
| ✅ 默认第一页 | `?page=1&pageSize=20` |
| ✅ 只看某团 | `?page=1&pageSize=20&dispatchGroupId=2103791490167888001` |
| ✅ 只看手工撤下 | `?page=1&pageSize=20&cancelSource=MANUAL` |
| ❌ pageSize 超过 100 | `?page=1&pageSize=101` → 100001 |
| ❌ cancelSource 拼错 | `?cancelSource=manual` → 100001(区分大小写) |
### 切换状态时的必要动作
- 从回收站点「恢复」时,请求体必须带**本行返回的** `dispatchVehicleId` 与 `version`,不要用列表缓存里的旧 version;恢复成功后应重新拉当前页。
- 搜索框输入需 trim;空串等价于不传 keyword,不要传空串以外的占位符。
## 六、边界行为
- 未登录 → 401(网关拦截)。
- 无权限(缺 `fleet:dispatch-recycle:list`)→ 403(网关/权限拦截)。
- 参数非法 → 100001。
- 无数据 → 200 + 空 records。
- 团/户/需求在列表之后被取消 → 本接口不感知;下次拉列表时 restorable 才变 false。
## 七、不影响范围(显式声明,帮前端/QA 缩小排查面)
- **仅影响**:新增 `GET /admin/fleet/dispatch-recycle/page` 一个只读端点。
- **零影响**:
- 派车工作台团列表/详情/建议接口
- `/admin/fleet/dispatch-groups/counts` 的 recycleCount 计算(本接口只读复用其口径)
- 3.9 撤下与 3.10 恢复(均不在本单)
- 表结构、索引、Flyway、菜单、网关路由(全部沿用现状)
## 八、测试环境已验证
真实登录(`POST /admin/auth/login`,账号 ha_r1_su,非铸 token)后经测试服网关:
```text
GET /admin/fleet/dispatch-recycle/page?page=1&pageSize=10 → 200 + code 200,total=0,records=[],page=1,pageSize=10 ✓
GET /admin/fleet/dispatch-recycle/page?page=1&pageSize=10&cancelSource=MANUAL → 200 + code 200,total=0 ✓
GET /admin/fleet/dispatch-groups/counts → 200 + code 200,recycleCount=0 ✓
```
说明:测试库当前没有 line_status=CANCELLED 的行(回收站 total 与 /counts 的 recycleCount 双向均为 0),因此响应 records 为空;31 个字段名与顺序由单测映射用例覆盖,不是线上真行核对。前端可先用空列表开发页面骨架,接上 3.9 后自然有数据。
## 十、相关文档
- 关联 Issue: [wx/HL#9120](https://git.1814.love/wx/HL/issues/9120)
- 关联 PR: [wx/HL#9126](https://git.1814.love/wx/HL/pulls/9126)
- 设计文档:`docs/fleet-workbench/1-2接口文档.md` 第 12.2 节「回收站」;`docs/fleet-workbench/1-3详细设计.md` F12.2 与 R12
## 关联 / 联系人
### 链接
- **Issue**: [#9120](https://git.1814.love/wx/HL/issues/9120)
- **PR**: [#9126](https://git.1814.love/wx/HL/pulls/9126)
- **Merge commit**: [ead771c42](https://git.1814.love/wx/HL/commit/ead771c42fadd256adeac6a579f84229b396038e)
### 联系人
- **后端负责人**: @wx