docs(changelog): #8457 车务首页新增「待确认接送变更」状态卡(管理后台)
changelog-filename-gate / validate (push) Failing after 2s
changelog-filename-gate / validate (push) Failing after 2s
GET /admin/profile/dashboard 车务角色 pendingStatusCards 由两项扩为三项, 第三项 transfer_change_pending 为全局计数、count 可为 null(未知)。 测试服 d10aada4d 网关实测 2→3→2,团期订单不计入。 Refs #8457 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
这个提交包含在:
@@ -0,0 +1,298 @@
|
||||
---
|
||||
schema: "hl-changelog/v2"
|
||||
ticket: "8457"
|
||||
title: "车务首页新增待确认接送变更状态卡"
|
||||
consumer: "admin"
|
||||
author: "wx(GIT)"
|
||||
change_type: "修改接口"
|
||||
backend_status: "deployed"
|
||||
gateway_status: "verified"
|
||||
frontend_status: "pending"
|
||||
frontend_owner: ""
|
||||
frontend_ref: ""
|
||||
target_release: ""
|
||||
verified_at: ""
|
||||
status_note: ""
|
||||
updated_at: "2026-09-28"
|
||||
base: "dev-v3"
|
||||
---
|
||||
|
||||
# hl-user-service: 车务首页新增待确认接送变更状态卡
|
||||
|
||||
**服务**: hl-user-service(计数由 hl-fleet-service 汇总,第三张卡的数据来自 hl-order-service-v3)
|
||||
**PR**: #8471(已合入 `dev-v3`,squash `d10aada4d`)
|
||||
**Issue**: #8457
|
||||
**日期**: 2026-09-28
|
||||
**影响范围**: 管理后台首页 `GET /admin/profile/dashboard`,仅车务管理员角色(`VEHICLE_MANAGER`)的响应
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 关键变化
|
||||
|
||||
- 车务角色响应里的 `pendingStatusCards` 由**固定两项**变为**固定三项**,新增第三项 `status=transfer_change_pending`、`statusLabel=待确认接送变更`。前两项的 `status`、`statusLabel`、顺序不变。
|
||||
- `pendingStatusCards[].count` 可以是 `null`:**只有第三项可能为 null**,表示「取不到、未知」;`0` 表示「确实没有」。前端对 `null` 和缺字段都按未知处理,显示「—」,不要显示成 0。
|
||||
- 第三项是**全局计数**,不受首页「近 7 天」窗口限制。守恒关系随之收窄:`unassigned` + `holding` 两项之和 == `pendingArrangeVehicle` == `upcomingTrips.length`,**第三项不参与**。不要把三张卡相加当作总数。
|
||||
|
||||
---
|
||||
|
||||
## 一、背景
|
||||
|
||||
大交通变更后需要车务确认的接送变更(#8435 引入的确认流程)此前只能在车务看板上逐单看到,车务首页没有入口,车务不知道还有多少单没确认。本单在车务首页加第三张状态卡,显示全部待确认接送变更的订单数,点卡片跳车务看板处理。
|
||||
|
||||
---
|
||||
|
||||
## 二、变更接口清单
|
||||
|
||||
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||||
|---|------|------|------|----------|------|
|
||||
| 1 | 管理后台首页仪表盘 | GET | `/admin/profile/dashboard` | 修改 | 车务角色响应的 `pendingStatusCards` 由两项扩为三项,`count` 可为 null |
|
||||
|
||||
---
|
||||
|
||||
## 三、接口详情
|
||||
|
||||
### 1. 管理后台首页仪表盘 `GET /admin/profile/dashboard`
|
||||
|
||||
**VO**: `无 ReqVO(Query 参数 period)→ LogisticsDashboardVO`
|
||||
|
||||
声明返回类型为 `Result<DashboardRoleRespVO>`,按登录角色返回不同的实现;车务管理员角色返回 `LogisticsDashboardVO`,本单只改这一个实现。
|
||||
|
||||
#### 使用场景
|
||||
|
||||
车务管理员登录后台进入首页,展示待安排车辆总数、三张未完成状态卡与近 7 天用车列表。第三张卡「待确认接送变更」点击后跳车务看板处理。
|
||||
|
||||
#### 入参字段表
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|------|------|------|------|------|------|
|
||||
| period | Query | String | 否 | 默认 `today`;取值 `today` / `week` / `month` | 其他角色仪表盘的时间范围。车务角色不使用该参数,传什么都返回同样的结果 |
|
||||
|
||||
无请求体。
|
||||
|
||||
#### 出参字段表
|
||||
|
||||
以下为车务角色 `data` 的全部字段;`pendingArrangeVehicle`、`upcomingTrips` 本单未改。
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| pendingArrangeVehicle | Integer | 待安排车辆数:行程开始日在今天起 7 天内(含今天)、存在待派车或待确认执行派车的订单数,按订单去重。本单未改 |
|
||||
| pendingStatusCards | Array<Object> | 未完成状态卡,固定三项,顺序固定为待派车、待确认、待确认接送变更 |
|
||||
| pendingStatusCards[].status | String | 状态键:`unassigned` / `holding` / `transfer_change_pending` |
|
||||
| pendingStatusCards[].statusLabel | String | 展示文案:`待派车` / `待确认` / `待确认接送变更` |
|
||||
| pendingStatusCards[].count | Integer \| null | 订单级计数,每单只计一次。前两项恒为整数;第三项为 null 表示未知,0 表示确实没有 |
|
||||
| upcomingTrips | Array<Object> | 即将出行/用车(近 7 天)。本单未改 |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```http
|
||||
GET /admin/profile/dashboard
|
||||
Authorization: Bearer <车务管理员登录 JWT>
|
||||
```
|
||||
|
||||
无请求体。
|
||||
|
||||
#### 响应示例
|
||||
|
||||
测试服车务测试账号实测原文(2026-09-28 12:51:10):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "成功",
|
||||
"data": {
|
||||
"pendingArrangeVehicle": 0,
|
||||
"pendingStatusCards": [
|
||||
{"status": "unassigned", "statusLabel": "待派车", "count": 0},
|
||||
{"status": "holding", "statusLabel": "待确认", "count": 0},
|
||||
{"status": "transfer_change_pending", "statusLabel": "待确认接送变更", "count": 2}
|
||||
],
|
||||
"upcomingTrips": []
|
||||
},
|
||||
"traceId": null,
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
第三项与前两项口径不同(见「业务边界」),两者数值互不相关,前两项为 0 时第三项可以非 0。
|
||||
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
- 没有任何待确认接送变更:第三项 `count=0`。
|
||||
- 取不到第三项计数(订单服务不可达、超时或返回失败):第三项 `count=null`;前两项、`pendingArrangeVehicle`、`upcomingTrips` 照常返回。
|
||||
- 取不到整份车务汇总(车务服务不可达或返回失败):仍返回三项,`count` 依次为 `0`、`0`、`null`;`pendingArrangeVehicle=0`,`upcomingTrips=[]`。
|
||||
- 车务服务未返回状态卡(旧版本车务服务):前两项由 `upcomingTrips` 推算,第三项 `count=null`。
|
||||
- 以上降级都返回 `code=200`、`success=true`,不报错;判断未知只看第三项 `count` 是否为 null 或缺字段。降级场景只有单测覆盖,测试服未造。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
鉴权失败由网关统一拦截,HTTP 状态恒为 200,看 body 的 `code`。下例为同一网关对 `/admin/` 路径缺 `Authorization` 头时的实测原文(取自另一个 `/admin/` 端点,网关对所有 `/admin/` 路径返回同一形态):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 401,
|
||||
"message": "缺少有效的 Authorization 头",
|
||||
"data": null,
|
||||
"traceId": "c34c4a77f4c449dc",
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
| 错误码 | 触发条件 |
|
||||
|---|---|
|
||||
| 401 | 网关拦截:缺 `Authorization` 头(「缺少有效的 Authorization 头」)、Token 无效(「Token 无效」)、Token 已过期或被撤销(「Token 已过期或被撤销」) |
|
||||
| 403 | 网关拦截:小程序用户 Token 访问管理端接口(「无权访问管理端接口」) |
|
||||
| 200208 | 用户服务未取到登录管理员身份(「未认证」) |
|
||||
|
||||
非车务角色调用不会报错,而是返回该角色自己的仪表盘,见「业务边界」。
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 三项顺序固定为 `unassigned`、`holding`、`transfer_change_pending`;前端按 `status` 取卡即可。
|
||||
- 前两项与第三项口径不同:前两项只看行程开始日在今天起 7 天内(含今天)的订单;第三项是全局计数,没有日期条件,也不受 `period` 影响。
|
||||
- 第三项只计非团期订单:已归入团期的订单改大交通不计入(团期接送变更不走车务确认);已删除订单不计入。
|
||||
- 第三项按订单计:一个订单无论改过几次大交通,只计 1 次;车务在看板上确认该订单的接送变更后,它立即不再计入。
|
||||
- `count=null` 与 `count=0` 含义不同:null 是「取不到」,0 是「确实没有」。
|
||||
- 只有车务管理员角色(`VEHICLE_MANAGER`)的响应带 `pendingStatusCards`。超管、管理员、定制师、房务、财务、物料等角色调用同一接口返回各自的仪表盘,不含这组字段。
|
||||
|
||||
---
|
||||
|
||||
## 四、契约约束与正确调用方式
|
||||
|
||||
| 场景 | 第三项 `count` | 前端展示 |
|
||||
|------|------|------|
|
||||
| 有待确认接送变更 | 正整数 | 显示数字 |
|
||||
| 没有待确认接送变更 | `0` | 显示 0 |
|
||||
| 取不到计数 | `null` 或缺字段 | 显示「—」,不显示 0 |
|
||||
|
||||
- 按 `status` 取卡并匹配样式;遇到不认识的 `status` 不要报错。
|
||||
- 首张统计「待安排车辆」用 `pendingArrangeVehicle`,不要用三张状态卡相加代替。
|
||||
- 点第三张卡跳车务看板 `/fleet/board` 时要清空出发日期范围。车务看板默认只列今年 1 月 1 日至今日出发的订单(按行程开始日过滤),而第三项是全局计数,不清空日期会看不到出发日在今天之后的待确认订单。不加状态筛选,也不加「只看待确认」。
|
||||
- 车务确认接送变更走 #8435 的 `POST /admin/fleet/board/orders/{orderId}/transfer-change/confirm`;确认成功后重新拉一次首页即可看到计数减少。
|
||||
|
||||
---
|
||||
|
||||
## 五、数据库行为
|
||||
|
||||
无表结构变更,不写库。三张卡都是只读计数。
|
||||
|
||||
---
|
||||
|
||||
## 六、边界行为
|
||||
|
||||
- 第三项与首页 7 天窗口无关:行程开始日在几个月以后的订单只要有待确认接送变更,也会计入第三项,但不会出现在前两项和 `upcomingTrips` 里。
|
||||
- 前两项之和恒等于 `pendingArrangeVehicle`,也等于 `upcomingTrips.length`;这一关系对第三项不成立。
|
||||
- 第三项取不到时不影响前两项和其他字段。
|
||||
|
||||
### 向后兼容
|
||||
|
||||
响应结构只在 `pendingStatusCards` 数组末尾追加一项,前两项的键、文案、顺序不变;`pendingArrangeVehicle`、`upcomingTrips` 不变。新增的是 `count` 可为 null 这一取值,前端对数字做运算或格式化前要先判空。
|
||||
|
||||
---
|
||||
|
||||
## 六.5、枚举 / 数据字典
|
||||
|
||||
`pendingStatusCards[].status`:
|
||||
|
||||
| status | statusLabel | 含义 | count 口径 |
|
||||
|------|------|------|------|
|
||||
| unassigned | 待派车 | 用车需求已展开但还没排车/司机 | 行程开始日在今天起 7 天内的订单数,整数 |
|
||||
| holding | 待确认 | 已锁定车/司机,待车务确认执行 | 行程开始日在今天起 7 天内的订单数,整数 |
|
||||
| transfer_change_pending | 待确认接送变更 | 客人改了大交通后接送需求有变化,待车务在看板确认(#8435) | 全局订单数(非团期、未删除),整数或 null |
|
||||
|
||||
---
|
||||
|
||||
## 六.6、修改前后对比
|
||||
|
||||
| 项 | 修前 | 修后 |
|
||||
|------|------|------|
|
||||
| `pendingStatusCards` 项数 | 固定 2 项 | 固定 3 项 |
|
||||
| 第三项 | 无 | `transfer_change_pending` / `待确认接送变更` |
|
||||
| `count` 取值 | 恒为整数 | 前两项恒为整数;第三项为整数或 null |
|
||||
| 守恒关系 | 两项之和 == `pendingArrangeVehicle` == `upcomingTrips` 唯一订单数 | `unassigned` + `holding` 两项之和 == `pendingArrangeVehicle` == `upcomingTrips.length`;第三项不参与 |
|
||||
|
||||
测试服实测第三项读数(车务测试账号):
|
||||
|
||||
| 时刻 | 操作 | 第三项 `count` |
|
||||
|------|------|------|
|
||||
| 12:51:10 | 基线 | 2 |
|
||||
| 13:05:24 | 核心订单车务已派车后,客人改到达航班时间 | 3 |
|
||||
| 13:05:54 | 车务在看板确认该订单的接送变更 | 2 |
|
||||
| 13:10:38 → 13:10:57 | 团期订单改大交通前后 | 2 → 2 |
|
||||
|
||||
---
|
||||
|
||||
## 六.7、影响评估
|
||||
|
||||
- **是否破坏向后兼容**: 否。只在数组末尾追加一项,`count` 新增 null 取值。
|
||||
- **前端是否必须同步上线**: 否。车务首页状态卡按数组循环渲染,第三张卡会自动出现(未配样式的键显示为灰色);但现有取值对 `count` 做了 `?? 0` 兜底,第三项为 null 时会显示成 0,与「确实没有」混淆。
|
||||
- **前端需要改的点**(依据工单 #8457「文档与交接」节,对照 hl-ui `v2.1` `1c555f544` 核对):
|
||||
1. 第三张卡 `count` 为 null 或缺字段时显示「—」,不显示 0(`VehicleDashboard.vue` 里 `count` 的 `?? 0` 兜底要改)。
|
||||
2. 为 `transfer_change_pending` 补卡片样式(`STATUS_CARD_PRESENTATION`)。
|
||||
3. 统计区由 3 张变 4 张(首张 `pendingArrangeVehicle` 加三张状态卡),栅格列数与骨架屏数量跟着调。
|
||||
4. 点第三张卡跳 `/fleet/board` 并清空出发日期范围,不加状态筛选,也不加「只看待确认」。
|
||||
5. 车务看板页目前不读任何路由参数(`openFleetBoard` 传的 `orderId` / `orderNo` / `statuses` 没有消费方),要支持读跳转参数来清空日期;参数名由前端定。
|
||||
- **前端 workaround 清理点**: 无。
|
||||
|
||||
---
|
||||
|
||||
## 七、不影响范围
|
||||
|
||||
- 超管、管理员、定制师、房务、财务、物料等角色的首页仪表盘。
|
||||
- `period` 参数的取值与含义。
|
||||
- 车务角色的 `pendingArrangeVehicle`、`upcomingTrips` 口径,以及前两张状态卡的口径。
|
||||
- 车务看板列表与详情接口、接送变更确认接口(#8435)。
|
||||
- 网关路由与鉴权规则(本单未改网关)。
|
||||
|
||||
---
|
||||
|
||||
## 八、测试环境已验证
|
||||
|
||||
部署:测试服 `hl-fleet-service`、`hl-order-service-v3`、`hl-user-service` 于 2026-09-28 12:19:44 至 12:22:27 先后滚到 `dev-v3 d10aada4d`(即本单合并提交),deploy-status 显示三者落后 0;`hl-gateway` 为 2026-09-27 部署的 `71def6dc5`,本单未改网关。
|
||||
|
||||
### 测试服网关实测(`GET /admin/profile/dashboard`,测试专用账号与自造夹具)
|
||||
|
||||
| 场景 | 检验点 | 结果 |
|
||||
|------|--------|------|
|
||||
| 车务账号请求首页 | 返回三项、顺序固定,第三项 `count=2`,前两项与 `upcomingTrips` 为空 | ✅ 原文见响应示例 |
|
||||
| 核心订单车务已派车后,客人改到达航班时间(该单接送服务日为 12 月) | 第三项 `count` 由 2 变 3,前两项仍为 0 | ✅ |
|
||||
| 车务在看板确认该订单接送变更(确认接口返回 `outcome=BASELINE_REFRESHED`) | 第三项 `count` 回到 2 | ✅ |
|
||||
| 团期订单改大交通 | 第三项 `count` 前后都是 2;该团期订单在车务看板详情里 `transferChange=null` | ✅ |
|
||||
| 超管、管理员、定制师调用同一接口 | 响应均不含 `pendingStatusCards`;超管与管理员顶层键为 `overview`、`publishedProducts`、`ranking`、`todos`、`totalAdmins`、`totalMiniAppUsers`、`totalProducts`、`trend`、`upcomingTrips`,定制师为 `calendarEvents`、`customerStats`、`funnel`、`overview`、`productStats`、`ranking`、`reviewStats`、`shortcuts`、`todos`、`trend`、`upcomingTrips` | ✅ |
|
||||
|
||||
### 单测覆盖(测试服未造「服务不可达」场景)
|
||||
|
||||
| 场景 | 用例 |
|
||||
|------|------|
|
||||
| 订单服务返回计数:第三项带出该值 | `FleetDashboardSummaryServiceTest.getSummary_transferChangeCountAvailable_thirdCardCarriesCount` |
|
||||
| 订单服务取不到:第三项 null,前两项不受影响 | `FleetDashboardSummaryServiceTest.getSummary_transferChangeCountNull_thirdCardNullOthersUnaffected` |
|
||||
| 无未完成订单:三项齐全 | `FleetDashboardSummaryServiceTest.getSummary_noIncompleteOrders_returnsThreeCardsAllZero` |
|
||||
| 订单服务返回 0 时给 0 不给 null;抛异常、返回失败、data 为 null、负数时给 null | `OrderQueryFacadeTest.countTransferChangePendingOrNull_*`(7 个) |
|
||||
| 订单服务调用失败走降级时不伪装成 0 | `TransferChangePendingCountFeignFallbackFactoryTest.create_transportFailure_returnsFailedResultNotZero` |
|
||||
| 车务服务不可达:三项 0 / 0 / null | `LogisticsDashboardServiceTest.getDashboard_allServicesFail_returnsAllZeros`、`FleetDashboardStatusCardsTest.degradedCards_fleetUnreachable_firstTwoZeroThirdNull`、`FleetDashboardSummaryFeignFallbackFactoryTest.fallback_returnsStableZeroStatusCards` |
|
||||
| 车务服务返回失败:三项、第三项 null | `LogisticsDashboardServiceTest.getDashboard_fleetReturnsNonSuccess_degradesToThreeCardsThirdNull` |
|
||||
| 透传保真:车务服务给 null 时输出 null,给 0 时输出 0 | `LogisticsDashboardServiceTest.getDashboard_fleetThirdCardNull_passesThroughNullNotZero`、`LogisticsDashboardServiceTest.getDashboard_fleetThirdCardZero_passesThroughZeroNotNull` |
|
||||
| 旧版本车务服务未返回状态卡:前两项推算、第三项 null | `LogisticsDashboardServiceTest.getDashboard_legacyFleetResponse_derivesCardsFromUpcomingTrips` |
|
||||
| 订单服务内部计数接口返回计数 | `OrderInternalForFleetControllerTest.countTransferChangePending_success_returnsCountAsData` |
|
||||
|
||||
---
|
||||
|
||||
## 十、相关文档
|
||||
|
||||
- 工单 #8457: https://git.1814.love/wx/HL/issues/8457
|
||||
- 同族工单 #8435(大交通改变时接送需求车务确认与看板标记):https://git.1814.love/wx/HL/issues/8435
|
||||
- 同族 changelog:`changelogs-v2/2026-09/28_8435_大交通改变时接送需求车务确认与看板标记-新增接口-管理后台.md`
|
||||
- 契约文档:`docs/order-v3/api/API-SPEC-FLEET-V1.5.html` §13.10 车务工作台摘要(版本历史 v1.5.105)
|
||||
|
||||
---
|
||||
|
||||
## 关联 / 联系人
|
||||
|
||||
### 链接
|
||||
|
||||
- **Issue**: [#8457](https://git.1814.love/wx/HL/issues/8457)
|
||||
- **PR**: [#8471](https://git.1814.love/wx/HL/pulls/8471)
|
||||
- **Merge commit**: [d10aada4d](https://git.1814.love/wx/HL/commit/d10aada4d)
|
||||
|
||||
### 联系人
|
||||
|
||||
- **后端负责人**: @wx
|
||||
在新工单中引用
屏蔽一个用户