--- schema: "hl-changelog/v2" ticket: "8767" title: "车务新增内部接口「按团期列出团车活跃派车行」(order-v3 出团通知书调用):车型车牌、司机与脱敏手机,排除已取消" consumer: "internal" author: "jw(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 /internal/fleet/dispatch/group-batch/:groupBatchId/vehicles,供 order-v3 出团通知书拼团车车辆、判「车辆未派司机」。内部接口不经网关(公网网关返回 code 403「接口不可访问」),直连 fleet 须带 X-Internal-Token,缺失返回 HTTP 403;前端无需对接。司机手机在 fleet 侧脱敏后才出域。已合并 dev-v3(PR #8794,merge commit a281744c8)并部署 TEST,两实例直连实测。管理后台侧变化见同日 04_8767 修改接口那份。" updated_at: "2026-10-04" base: "dev-v3" --- # fleet: 新增内部接口「按团期列出团车活跃派车行」 > **服务**: hl-fleet-service(端口 8087 / 8187,双实例;内部接口,网关不放行) > **PR**: `#8794`(已合入 `dev-v3`,合并提交 `a281744c8`) > **Issue**: #8767 --- ## ⚠️ 关键变化 🟢 新增 `GET /internal/fleet/dispatch/group-batch/:groupBatchId/vehicles`:按团期返回团车(整团派车)的活跃派车行,每行一天一辆车,带车型、车牌、司机与脱敏手机;`driverId` 为空表示「只排了车、没排司机」。 🟢 首个调用方:order-v3 出团通知书(`FleetGroupDispatchFeignClient`,contextId `fleetGroupDispatchVehicle`)。 🟢 出参载体是共享 DTO `com.hulalv.common.dto.fleet.GroupDispatchVehicleDTO`(hl-common-core,纯新增类)。 --- ## 一、背景 团车的车辆与司机只存在车务的 `fleet_group_dispatch`,order-v3 的逐户派车快照里没有团车户的行,出团通知书既拼不出团车车辆,也判不出「车辆未派司机」。车务原有的团车读口(团期配车总览)要先回调 order-v3 取团期基线,被 order-v3 调用会形成同步环,所以另开一个只读本域表的内部读口。 --- ## 二、变更接口清单 | # | 接口 | 方法 | 路径 | 变更类型 | 说明 | |---|------|------|------|----------|------| | 1 | 按团期列出团车活跃派车行 | GET | `/internal/fleet/dispatch/group-batch/:groupBatchId/vehicles` | 新增 | 内部接口,order-v3 出团通知书调用 | --- ## 三、接口详情 ### 1. 按团期列出团车活跃派车行 `GET /internal/fleet/dispatch/group-batch/:groupBatchId/vehicles` **VO**: `GroupDispatchVehicleDTO`(入参只有路径参数)→ `Result>` #### 使用场景 order-v3 读、存出团通知书时各调一次:拼默认车辆信息 `bus`,并判断下发门 `DRIVER`。只在写事务之外调用。 #### 入参字段表 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |------|------|------|------|------|------| | groupBatchId | Path | Long | ✅ | 团期主订单 ID | 单个团期,不涉及批量分片 | | X-Internal-Token | Header | String | ✅ | 内部令牌 | 由公共 Feign 拦截器自动附带 | #### 出参字段表 | 字段 | 类型 | 说明 | |------|------|------| | dispatchId | String | 团期配车行 ID(Long 序列化为字符串) | | tripDate | String | 服务日,`yyyy-MM-dd` | | vehicleId | String | 车辆 ID | | vehiclePlateNo | String | 车牌;车已删除时为 `null` | | vehicleModelName | String | 车型名称(车辆型号,如「丰田考斯特」);车已删除时为 `null` | | driverId | String | 司机 ID;为 `null` 表示只排了车、没排司机 | | driverName | String | 司机姓名;没排司机或司机档案已删除时为 `null` | | driverPhone | String | **脱敏**司机手机,形如 `135****5020`;没有时为 `null` | | status | String | 派车状态 `ASSIGNED`(已派车)/ `CONFIRMED`(已确认);`CANCELLED` 不返回 | #### 请求示例 ```http GET /internal/fleet/dispatch/group-batch/2104962917969608705/vehicles HTTP/1.1 Host: 192.168.100.236:8087 X-Internal-Token: <内部令牌> ``` #### 响应示例 取自 TEST(团期 T27-5637,两辆车三天,节选前两行): ```json { "code": 200, "message": "成功", "data": [ { "dispatchId": "2104969512002682882", "tripDate": "2027-03-18", "vehicleId": "2089691299660644353", "vehiclePlateNo": "蒙P318A", "vehicleModelName": "坦克300", "driverId": "2089691297869651969", "driverName": "P3测试司机18", "driverPhone": "139****0018", "status": "CONFIRMED" }, { "dispatchId": "2104969512002682883", "tripDate": "2027-03-18", "vehicleId": "2104029270659780610", "vehiclePlateNo": "C0927T01", "vehicleModelName": "别克GL8", "driverId": "2104030084715433986", "driverName": "测B0927司机甲", "driverPhone": "199****0001", "status": "CONFIRMED" } ] } ``` #### 空数据 / 降级响应 - 该团没有团车(只用逐户派车,或派车全部已取消):`data=[]`。 - 调用方(order-v3)侧:fleet 不可用或超时,降级返回错误结果(`584072`「车务司机车辆信息暂时不可用」),**不会**伪装成空数组;通知书据此报 `DRIVER_UNAVAILABLE`。 ```json { "code": 200, "message": "成功", "data": [] } ``` #### 错误响应 | HTTP / code | 条件 | |---|---| | HTTP 403 / `403` | 未带或带错 `X-Internal-Token`:`内部接口禁止外部访问` | | 网关 `403` | 经公网网关访问:`接口不可访问` | ```json { "code": 403, "msg": "内部接口禁止外部访问" } ``` #### 业务边界 - 只读车务本域表,**不回调 order-v3**,不校验团期是否存在(团期不存在即返回 `[]`)。 - 「已取消不返回」与车务「团期配车总览」、团车就绪判定同一口径:总览上看不到的行这里也不返回。 - 同一辆车多天各一行;去重、拼接由调用方负责。 - 司机手机只有脱敏形态,明文不出车务服务。 --- ## 四、契约约束与正确调用方式 - 只能服务间调用:走 Feign(`name=hl-fleet-service`,`path=/internal/fleet/dispatch`),不经网关。 - `driverId` 为空才算「没派司机」;`driverName` 为空但 `driverId` 有值是「派过、司机档案已删」,不算缺司机。 - 失败要保留为失败,不要把降级当成空数组(空数组的含义是「没有团车」)。 --- ## 五、数据库行为 - 只读:`fleet_group_dispatch`(存活行),批量取 `fleet_vehicle`、`fleet_driver`;零写入、零表结构变更。 --- ## 六、边界行为 - 返回顺序:服务日升序,同日按配车行 ID 升序。 - 车或司机已软删:对应展示字段为 `null`,ID 照给。 --- ## 七、不影响范围 - 车务既有接口(团期配车总览、重配、释放、覆盖查询等):不变。 - 其他依赖 hl-common-core 的服务:只多了一个类,行为不变。 - 管理后台、小程序:不直接调用本接口。 --- ## 八、测试环境已验证 **环境**:TEST,fleet 两实例直连(8087 / 8187) **验证时间**:2026-10-04 17:01~17:13 **构建身份**:fleet 部署 `dev-v3 @ a281744c8`(本单合并提交),新路径两实例均返回 `code=200`(旧字节无此路径)。 | 用例 | 结果 | |---|---| | 团期 T27-5637,带内部令牌 | 两实例均 `code=200`,6 行(2 辆车 × 3 天),手机全为 `ddd****dddd` 形态 | | 不带内部令牌 | 两实例均 HTTP 403「内部接口禁止外部访问」 | | 经公网网关(不带 / 带管理员 token) | 均 `code=403`「接口不可访问」 | | 自建团期插入两行(一行有司机、一行无司机) | 无司机那行 `driverId=null`;补派后带司机,通知书读数与本接口推算逐字一致 | | 日志 | 验收窗口内两实例按司机脱敏号前三后四检索明文手机号零命中 | 本地:fleet `dispatch` 包 + 红线架构测试 517/0/0(跳过 2,需显式开启的容器类),含本读口 4 条单测与「与总览同一分母」一致性用例。 --- ## 十、相关文档 - Issue `#8767`;PR `#8794` - 调用方变化:同日 `04_8767` 修改接口(管理后台)那份 - 团车 CANCELLED 口径来源:Issue `#8550` ## 关联 / 联系人 ### 链接 - **Issue**: [#8767](https://git.1814.love/wx/HL/issues/8767) - **PR**: [#8794](https://git.1814.love/wx/HL/pulls/8794) - **Merge commit**: [a281744c8](https://git.1814.love/wx/HL/commit/a281744c8) ### 联系人 - **后端负责人**: @jw