文件
hl-api-changelog/changelogs-v2/2026-09/30_8593_待配车团期清单接送机未配计数改为真值-修改接口-管理后台.md
T

268 行
14 KiB
Markdown
原始文件 Blame 文件历史

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
---
schema: "hl-changelog/v2"
ticket: "8593"
title: "待配车团期清单 transferPendingCount 由硬编码 0 改为真值,取不到给 null"
consumer: "admin"
author: "wx(GIT)"
change_type: "修改接口"
backend_status: "deployed"
gateway_status: "not_required"
frontend_status: "not_required"
frontend_owner: ""
frontend_ref: ""
target_release: ""
verified_at: ""
status_note: "GET /admin/fleet/group-dispatch/pending-batches 响应体每行新增真值语义:records[].transferPendingCount 此前恒为硬编码 0,本次改为按团期实际接送机声明缺口计算的真值,且新增 null 语义——取不到时返回 null 而不是 0,前端必须把 null 渲染成未知态(如「—」),不得折算成 0;0 表示查过了确无缺口,null 表示本团有没有缺口未知。该字段与团期配车总览端点(GET /admin/fleet/group-dispatch/batches/{groupBatchId}/overview)的 transferPendingTotal 走同一判定方法,服务端保证两者恒等。声明数据经内部 Feign 端点(order-v3 提供,仅供服务间调用,非管理后台直接可调)按页批量整取,不做逐团 N+1 请求;该内部读口不可达时不会静默返回空列表,会返回失败结果,使 transferPendingCount 整页退化为 null,不影响该页其余字段(包括 unreadCount,是另一个独立软依赖,user-service 不可达时退化为 0)。字段类型未变(仍是 Integer),仅新增 null 作为合法取值;若前端此前对该字段做过兜底成 0 或完全未渲染,需要补上 null 分支与展示逻辑。清单本身的分页/过滤/排序、其余字段与错误码(600012/600013/401)均未变化。backend_status=deployed:hl-fleet-service 已部署测试服并与本条目所依据的源码提交一致(deploy-status.sh 实测 COMMIT=d57498d38,STATE=ok,2026-09-30 05:34:07 部署);该路由已实测可达(未登录态返 200 信封 code=401)。"
updated_at: "2026-09-30"
base: "dev-v3"
---
# 车务团期配车:待配车团期清单接送机未配计数改为真值
> **存放目录**: 二期(order-v3/fleet)→ `changelogs-v2/2026-09/`
>
> **服务**: hl-fleet-service(端口 8087)
> **PR**: [#8617](https://git.1814.love:8443/wx/HL/pulls/8617)
> **Issue**: [#8593](https://git.1814.love:8443/wx/HL/issues/8593)
> **日期**: 2026-09-30
> **影响范围**: 管理后台「待配车团期清单」列表页的 `transferPendingCount` 一列
---
## ⚠️ 关键变化
「待配车团期清单」(`pending-batches`)每行的 `transferPendingCount` 字段,此前**恒为硬编码 0**,不反映任何真实数据——前端如果曾据此判断「所有团都没有接送机缺口」,这个判断从一开始就是假的。本次改为**真实计算值**,并引入 **`null` 语义**:取不到声明数据时返回 `null` 而不是 `0`。**`0` 与 `null` 含义不同,不能互相折算**:`0` = 查过了、确无接送机缺口;`null` = 这一刻没查到、本团有没有缺口未知。前端如果沿用旧的「反正恒为 0,不用管」的假设,现在会看到非零真值和偶发 `null`,必须补上渲染逻辑。
---
## 二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 待配车团期清单 | GET | `/admin/fleet/group-dispatch/pending-batches` | 修改接口 | `transferPendingCount` 由硬编码 0 改为真值+null 语义 |
---
## 三、接口详情
### 1. 待配车团期清单 `GET /admin/fleet/group-dispatch/pending-batches`
**VO**: `GroupDispatchPendingBatchPageReqVO → PageResult<GroupDispatchPendingBatchRespVO>`
#### 使用场景
车务在「团期配车」列表页查看尚未完成配车(`requirementConfirmed=true` 且 `vehicleReady=false`)的团期,支持按出发日区间、团号/团名关键词、配车进度过滤。本次改动只影响列表行里的 `transferPendingCount` 一列,接口路径、分页参数、其余字段均未变化。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|------|------|------|------|------|------|
| departDateFrom | Query | LocalDate(ISO,`yyyy-MM-dd`) | - | 不传=不限 | 出发日下界(含) |
| departDateTo | Query | LocalDate(ISO,`yyyy-MM-dd`) | - | 不传=不限 | 出发日上界(含) |
| keyword | Query | String | - | ≤50 字符 | 团号/团名模糊关键词 |
| dispatchProgress | Query | String | - | 仅 `NOT_STARTED`/`PARTIAL`/`FULL` | 配车进度过滤(fleet 侧内存过滤,先分页后过滤) |
| page | Query | Integer | - | ≥1,默认 1 | 页码 |
| pageSize | Query | Integer | - | 1-100,默认 20 | 每页条数 |
#### 出参 `Result<PageResult<GroupDispatchPendingBatchRespVO>>`
| 字段 | 类型 | 说明 |
|------|------|------|
| records | Array | 团期行列表,见下 |
| records[].groupBatchId | String(Long 转字符串) | 团期主订单 ID |
| records[].batchNo | String | 团号 |
| records[].batchName | String | 团名 |
| records[].batchStatus | String | 团期状态 |
| records[].departDate | String(`yyyy-MM-dd`) | 出发日 |
| records[].endDate | String(`yyyy-MM-dd`) | 结束日 |
| records[].serviceDayCount | Integer | 服务日天数 |
| records[].enrolledOrders | Integer | 报名子订单数 |
| records[].enrolledPeople | Integer | 报名人数 |
| records[].requirementConfirmed | Boolean | 需求是否已确认 |
| records[].vehicleReady | Boolean | 车辆是否已就绪 |
| records[].dispatchedDayCount | Integer | 已排车天数 |
| records[].dispatchProgress | String | 配车进度:`NOT_STARTED`/`PARTIAL`/`FULL` |
| records[].**transferPendingCount** | Integer(可空) | **本次变更字段**:本团接送机未配计数;`null`=未取到(前端须渲染未知态),`0`=确无缺口 |
| records[].unreadCount | Integer | 团期车务会话团队未读数(软依赖,取不到退 0) |
| total | Integer | 总记录数(`dispatchProgress` 过滤前) |
| page | Integer | 当前页码 |
| pageSize | Integer | 每页条数 |
#### 请求示例
```http
GET /admin/fleet/group-dispatch/pending-batches?departDateFrom=2026-09-01&departDateTo=2026-09-30&keyword=T26-8867&dispatchProgress=PARTIAL&page=1&pageSize=20
```
#### 响应示例
```json
{
"code": 200,
"message": "成功",
"data": {
"records": [
{
"groupBatchId": "1934567890123456789",
"batchNo": "T26-8867",
"batchName": "额吉的故乡 9/12 团",
"batchStatus": "RESOURCE_PREPARING",
"departDate": "2026-09-12",
"endDate": "2026-09-16",
"serviceDayCount": 5,
"enrolledOrders": 6,
"enrolledPeople": 17,
"requirementConfirmed": true,
"vehicleReady": false,
"dispatchedDayCount": 2,
"dispatchProgress": "PARTIAL",
"transferPendingCount": 2,
"unreadCount": 3
}
],
"total": 1,
"page": 1,
"pageSize": 20
},
"success": true
}
```
#### 空数据 / 降级响应
当没有满足过滤条件的团期时,返回 `records: [], total: 0`(HTTP 200,非错误)。当 order-v3 的接送机声明批量读口不可达时,**本页所有行的 `transferPendingCount` 一律返回 `null`**(不是 0,也不会让整个请求失败)——前端必须把 `transferPendingCount=null` 渲染成未知态(如「—」),不能当作「确认无缺口」折算成 0。`unreadCount` 是另一个独立的软依赖:user-service 不可达时退化为 0,清单其余字段照常返回,不受影响。
#### 错误响应
```json
{
"code": 600013,
"message": "参数非法: 页码必须≥1",
"success": false,
"data": null
}
```
其余可能返回的错误码:
| code | 触发条件 | message |
|---|---|---|
| 600012 | order-v3 团期候选基线不可达(降级/返错),**不会静默返空列表** | `团期配车基线不可达,请稍后重试` |
| 600013 | 日期区间倒置、分页越界、关键词超长(>50 字)、`dispatchProgress` 枚举非法 | `参数非法: {具体原因}` |
| 401 | 未登录(网关统一信封,HTTP 状态码仍是 200,信封内 `code=401`) | `缺少有效的 Authorization 头` |
#### 业务边界
- `dispatchProgress` 是 fleet 侧内存过滤(order-v3 侧没有配车事实,无法下推),是「先分页再过滤」——单页返回条数可能少于 `pageSize`,`total` 是过滤**前**的总数。
- `transferPendingCount` 与团期配车总览端点(`GET /admin/fleet/group-dispatch/batches/{groupBatchId}/overview`)的 `transferPendingTotal` 走**同一个判定方法**,服务端保证两者恒等——清单页与详情页的这个数字不会对不上。
- 声明数据经内部批量读口整页一次取齐(每页最多按团期数一次 Feign 调用),不做逐团 N+1 请求。
- `transferPendingCount` 的 `null` 与 `unreadCount` 的「退 0」是两种不同的降级策略,分别对应各自读口的可靠性设计,不要混用同一套判空逻辑处理。
- 主候选数据(团期本身)取不到时整个请求失败关闭(600012),不会把「后端没拿到」渲染成「该团没有需求」;这与 `transferPendingCount` 单列退化为 `null`(其余字段正常返回)是两个不同粒度的降级,不要合并处理。
---
## 四、契约约束与正确调用方式
### 正确渲染 `transferPendingCount` 的方式
| 取值 | 含义 | 渲染建议 |
|------|------|----------|
| `0` | 查过了,确无接送机缺口 | 正常展示 `0` |
| 正整数 | 查过了,有对应数量的缺口 | 正常展示数值,可高亮提醒 |
| `null` | 本次没有取到该团的声明数据,缺口未知 | 渲染成未知态(如「—」),**不要**当作 `0` |
❌ 错误用法:`transferPendingCount ?? 0` 或任何把 `null` 静默折算成 `0` 的写法——这会把「未知」误报成「已确认无缺口」,反而比改动前的硬编码 0 更危险(因为界面上看起来像是「查过了」)。
---
## 六、边界行为
- 未登录 → 网关统一信封 `code=401`(HTTP 状态码 200,非 HTTP 401)
- 无匹配团期 → `records: [], total: 0`,HTTP 200
- `dispatchProgress` 过滤导致单页为空 → `records: []`,但 `total` 仍是过滤前总数,不为 0
- order-v3 团期候选基线不可达 → 600012,整个请求失败,不返回部分数据
- order-v3 接送机声明批量读口不可达 → 请求仍然成功,仅 `transferPendingCount` 整页退化为 `null`
- user-service 不可达 → 请求仍然成功,仅 `unreadCount` 退化为 `0`
---
## 六.5、枚举 / 数据字典
### dispatchProgress(配车进度)
**所属字段**: `records[].dispatchProgress`(`GroupDispatchPendingBatchRespVO`),同名字段也用于入参过滤 | **类型**: `String`
| 值 | 中文 | 说明 |
|----|------|------|
| `NOT_STARTED` | 未开始 | 已排车天数为 0 |
| `PARTIAL` | 部分配车 | 已排车天数大于 0 但未盖满全部服务日 |
| `FULL` | 已配齐 | 已排车天数盖满全部权威服务日 |
---
## 六.6、修改前后对比
### 字段级对比
| 字段 | 改前 | 改后 |
|------|------|------|
| `transferPendingCount` | 恒为 `0`(硬编码占位符,从未反映真实缺口) | 真实计算值;取不到声明数据时为 `null`(不是 `0`) |
### 行为级对比
| 行为 | 改前 | 改后 |
|------|------|------|
| 声明数据获取方式 | 未获取,字段硬编码为 0 | 按页批量调用 order-v3 内部读口一次取齐(非逐团 N+1),取不到时该列整体退化为 `null` |
| 与 overview 端点的一致性 | 无法比较(清单侧恒 0,overview 侧是真值,两者结构性不可能相等) | 清单与 overview 走同一判定方法,服务端保证恒等 |
| 字段类型 | `Integer`,实际恒非空 | `Integer`,新增合法取值 `null` |
## 六.7、影响评估
- **是否破坏向后兼容**: 否——字段名与类型(`Integer`)未变,只是语义从「恒定占位符」变为「真实业务值 + 可空」。原本恒为 0 意味着这个字段此前对使用方没有任何信息量,语义上不存在"旧行为被依赖"的合理场景。
- **前端是否必须同步上线**: 是——如果前端此前完全没有渲染这个字段(因为它恒为 0、没有展示价值),现在需要补充展示逻辑,包括 `null` 的未知态处理;如果前端此前渲染了这个字段但做了 `?? 0` 之类的兜底,需要去掉这个兜底、改为区分 `0` 与 `null`。
- **前端 workaround 清理点**: 若前端此前因为「这个字段没用、永远是 0」而完全跳过读取或做了防御性兜底,需要重新接入并按上方「正确渲染方式」处理;无其它 workaround。
---
## 七、不影响范围
- **仅影响**: 「待配车团期清单」列表每行的 `transferPendingCount` 字段
- **零影响**:
- 清单接口的分页参数、过滤参数(`departDateFrom`/`departDateTo`/`keyword`/`dispatchProgress`)语义
- `records[]` 内除 `transferPendingCount` 外的其余字段
- `unreadCount` 字段的取值逻辑(软依赖降级策略本身未变)
- 团期配车总览端点 `GET /admin/fleet/group-dispatch/batches/{groupBatchId}/overview` 的路径、参数、响应结构(其 `transferPendingTotal` 此前就已经是真值,本次不涉及该端点改动,只是清单侧现在与它口径一致)
- 错误码 600012/600013/401 的触发条件与数值
---
## 八、测试环境已验证
- `deploy-status.sh`(测试服现状表)实测:`hl-fleet-service` COMMIT=`d57498d38`、STATE=ok,2026-09-30 05:34:07 部署——与本条目所依据的源码提交(含 #8593 合并提交 `d57498d381`)一致。
- 测试服内网 `curl` 实测路由已挂载且鉴权前置生效:
```
GET http://127.0.0.1:8080/admin/fleet/group-dispatch/pending-batches?page=1&pageSize=1 (无 Authorization 头)
→ HTTP 200
{"code":401,"message":"缺少有效的 Authorization 头","data":null,"traceId":"e0e9988b33394199","success":false}
```
---
## 十、相关文档
- 关联 Issue: [wx/HL#8593](https://git.1814.love:8443/wx/HL/issues/8593)
- 关联 PR: [wx/HL#8617](https://git.1814.love:8443/wx/HL/pulls/8617)
## 关联 / 联系人
### 链接
- **Issue**: [#8593](https://git.1814.love:8443/wx/HL/issues/8593)
- **PR**: [#8617](https://git.1814.love:8443/wx/HL/pulls/8617)
- **Merge commit**: [`d57498d381`](https://git.1814.love:8443/wx/HL/commit/d57498d38138fd37ce7e844b6f2b01c190706950)
### 联系人
- **后端负责人**: @wx