文件
hl-api-changelog/changelogs-v2/2026-09/29_8536_团期配车读口团期不存在统一600015与就绪零行文案-修改接口-管理后台.md
T

22 KiB
原始文件 Blame 文件历史

schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
schema ticket title consumer author change_type backend_status gateway_status frontend_status frontend_owner frontend_ref target_release verified_at status_note updated_at base
hl-changelog/v2 8536 团期配车四个读口团期不存在统一收敛为 600015;就绪判定零配车行文案调整 admin wx(GIT) 修改接口 deployed verified not_required PR #8554 合并 dev-v3(e2982739e8);hl-fleet-service dev-v3 分支部署测试网关 @ e2982739e8 并实测:四个读口对不存在团期均返回 600015;有效团期零共用关系仍返回 200+data=[];就绪判定零配车行场景文案已改为「本团尚未创建任何配车行」。 2026-09-30 dev-v3

团期配车四个读口:团期不存在统一收敛为 600015;就绪判定零配车行文案调整

存放目录: changelogs-v2/2026-09/ 服务: hl-fleet-service (端口 8087) PR: #8554 Issue: #8536 #8537 日期: 2026-09-29 影响范围: 管理后台团期配车页四个只读端点(总览/就绪判定/共用关系查询/共用成员候选)


⚠️ 关键变化

  • 🔴 破坏性变更(共用关系查询):此前对不存在的团期调用 GET share-groups 会返回 HTTP 200 + code=200 + data=[],与"团期确有效存在但零共用关系"完全同形,前端无法区分。现在改为返回 code=600015(团期不存在)。有效团期确实零关系时仍然是 code=200 + data=[],未变化。
  • 四个读口(总览/就绪判定/共用关系查询/共用成员候选)对"团期不存在"场景统一改用 600015 作为失败关闭码,与各自原先分散的、语义偏"可重试"的码区分开:600015 是永久性否定,前端不应引导重试。
  • 就绪判定端点在"该团尚无任何配车行"这一具体场景下,blockers[].message 文案从 本团有 0 条配车行尚未确认 改为 本团尚未创建任何配车行;code 仍是 BLOCK_NOT_CONFIRMED,未拆分新码。

二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 团期配车总览 GET /admin/fleet/group-dispatch/batches/{groupBatchId}/overview 错误码语义收敛 团期不存在统一改返 600015
2 团期配车就绪判定 GET /admin/fleet/group-dispatch/batches/{groupBatchId}/readiness 错误码语义收敛 + 文案调整 团期不存在统一改返 600015;零配车行 blocker 文案调整
3 查询团期车辆共用关系 GET /admin/fleet/group-dispatch/batches/{groupBatchId}/share-groups 🔴 破坏性变更 团期不存在从 200+data=[] 改为 600015
4 查询共用成员候选清单 GET /admin/fleet/group-dispatch/batches/{groupBatchId}/share-member-candidates 错误码语义收敛 团期不存在统一改返 600015

三、接口详情

1. 团期配车总览 GET /admin/fleet/group-dispatch/batches/{groupBatchId}/overview

VO: (无请求体,仅路径参数) → GroupDispatchOverviewRespVO

使用场景

车务打开团期配车页时调用,取按权威服务日逐日铺开的已排车、空洞日与逐户接送机缺口。本次改动只影响"团期不存在"时的响应,成功路径字段结构未变。

入参

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ - 团期主订单 ID

出参 Result<GroupDispatchOverviewRespVO>

字段 类型 说明
groupBatchId Long→String 团期主订单 ID
batchNo String 团号
departDate / endDate LocalDate 出团日 / 返团日
serviceDates List<LocalDate> 权威服务日集合
requirementConfirmed Boolean 整团需求是否已确认
vehicleReady Boolean 配车是否已就绪
days List 逐日行,按 serviceDates 铺满
missingDates List<LocalDate> 空洞日
orders List 逐户行
transferPendingTotal Integer 全团接送机未配计数
conversationKey String 团期车务会话键

以上字段结构本次均未改动。

请求示例

GET /admin/fleet/group-dispatch/batches/1934567890123456789/overview

响应示例

{ "code": 200, "message": "成功", "data": { "groupBatchId": "1934567890123456789", "batchNo": "T26-8867", "departDate": "2026-09-12", "endDate": "2026-09-16", "requirementConfirmed": true, "vehicleReady": false, "transferPendingTotal": 3, "conversationKey": "GROUP_FLEET:1934567890123456789" }, "success": true }

空数据 / 降级响应

无空对象/空 200 形态:团期不存在时不再返回任何形式的空数据,而是抛 600015,见错误响应;上游确实不可达(非团期不存在)时仍返回原有的可重试码 600012。

错误响应

{ "code": 600015, "message": "团期不存在: 9107777777777777777", "data": null, "success": false }

业务边界

  • 团期不存在时统一改抛 600015(永久性否定),前端不应引导用户重试;此前该场景返回的是可重试语义的 600012,含义已变化。
  • 上游确实不可达(超时/熔断/降级,而非团期不存在)时仍返回原有的 600012,含义不变。
  • 600015 的判定统一由服务端集中完成,不因具体是哪个下游 Feign 端点而有条件遗漏。

2. 团期配车就绪判定 GET /admin/fleet/group-dispatch/batches/{groupBatchId}/readiness

VO: (无请求体,仅路径参数) → GroupDispatchReadinessRespVO

使用场景

车务打开团期配车页时调用,判定"硬拦三项"是否全过(ready)与"只提醒两项"是否有黄牌(warned)。本次改动:①团期不存在统一改返 600015;②该团尚无任何配车行时的 blocker 文案调整。

入参

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ - 团期主订单 ID

出参 Result<GroupDispatchReadinessRespVO>

字段 类型 说明
groupBatchId / requirementId Long→String 团期主订单 ID / 判定所依据的正式需求 ID
requirementVersion Integer 判定所依据的需求版本
planVersion Long fleet 侧当前计划版本
ready Boolean = blockers.isEmpty(),硬拦三项是否全过
warned Boolean = !warnings.isEmpty(),是否有只提醒项,与 ready 互相独立
blockers / warnings List 硬拦未过项 / 只提醒项,每项含 code + message
groups List 逐组覆盖明细,与配车写口 coverage 同源
shareGroupCount Integer 本团 active 共用关系数

以上字段结构本次均未改动,仅 blockers[].message 在特定场景下文案调整(见下)。

请求示例

GET /admin/fleet/group-dispatch/batches/2104838272570245121/readiness

响应示例

该团级需求已确认、但尚无任何物理配车行(真实实测取值):

{ "code": 200, "message": "成功", "data": { "groupBatchId": "2104838272570245121", "ready": false, "blockers": [ { "code": "BLOCK_NOT_CONFIRMED", "message": "本团尚未创建任何配车行" } ] }, "success": true }

空数据 / 降级响应

无空对象/空 200 形态:团期不存在时不再返回默认就绪对象,而是抛 600015,见错误响应;blockers/warnings 均可以是空数组(表示该维度全部通过/无提醒),空数组不是错误也不是降级。

错误响应

{ "code": 600015, "message": "团期不存在: 9107777777777777777", "data": null, "success": false }

业务边界

  • BLOCK_NOT_CONFIRMED 这一个 code 现在对应两种不同的 message 文案(该团尚无任何配车行 / 该团有 N 条配车行尚未确认);两种场景下前端的处置动作相同(引导去配车页排车/确认),如果此前是按 message 文本内容做分支判断,请改成按 code 判断,不要再解析 message 里的具体文案或数字。
  • 团期不存在时统一改抛 600015(永久性否定),不应引导重试;602113(基线不可用或该团未声明任何乘车分组)含义不变,仍是可重试语义。
  • ready 与 warned 互相独立,ready=true && warned=true 是合法组合,本次改动未影响这一既有语义。

3. 查询团期车辆共用关系 GET /admin/fleet/group-dispatch/batches/{groupBatchId}/share-groups

VO: ShareGroupQueryReqVO → List<ShareGroupRespVO>

使用场景

车务在团期配车页查看本团当前(及可选的历史)车辆共用关系。🔴 本次改动是破坏性变更:团期不存在时的响应形状发生变化。

入参

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ - 团期主订单 ID
serviceDate Query LocalDate 否 yyyy-MM-dd 不传=全部服务日
resourceType Query String 否 VEHICLE/DRIVER 不传=两者;非法枚举按入参非法拒绝
includeReleased Query Boolean 否 默认 false 是否一并返回已解除的关系与变更历史

出参 Result<List<ShareGroupRespVO>>

字段 类型 说明
shareGroupId / groupBatchId Long→String 共用关系 ID / 运营团期 ID
serviceDate LocalDate 共用发生的服务日
resourceType String VEHICLE / DRIVER
resourceId Long→String 车辆或司机 ID
status String ACTIVE / RELEASED
costBearer String GROUP / ORDER
costBearerOrderId Long→String costBearer=ORDER 时的承担订单 ID
costBearerTeamNo String 承担订单的团号
costSourceRefNo String 车费来源引用,格式 SHARE-{shareGroupId}
members List 成员全集
confirmedBy / confirmedAt Long→String / LocalDateTime 确认人 / 确认时间
version Integer 乐观锁版本号
history List 变更历史;仅 includeReleased=true 时返回

以上字段结构本次未改动,仅"团期不存在"场景的响应形状变化,见下方请求/响应示例。

请求示例

GET /admin/fleet/group-dispatch/batches/2104840641651556353/share-groups

响应示例

真实实测:团期 2104840641651556353 存在且零共用关系:

{ "code": 200, "message": "成功", "data": [], "success": true }

空数据 / 降级响应

团期确有效存在但零共用关系时,返回 HTTP 200 + code=200 + data=[](上方响应示例即为此场景的真实实测结果)——这与"团期不存在"的 600015 是两个不同的信号,前端必须能区分两者,不能再把"拿到 600015 错误"当成"data 是空数组"来处理。

错误响应

{ "code": 600015, "message": "团期不存在: 9107777777777777777", "data": null, "success": false }

业务边界

  • 🔴 此前对不存在的团期调用本接口返回 code=200 + data=[],与"团期确有效存在但零共用关系"完全同形,无法区分;现在不存在的团期改为返回 code=600015。
  • 有效团期确实零共用关系时的响应未变化,仍是 code=200 + data=[](见响应示例,真实实测)。
  • 如果此前把 data.length===0 当作"该团无共用关系"的唯一判据,现在必须新增对 600015 的分支处理,否则遇到不存在的团期会因为拿到错误响应、取不到 data 数组而报错或白屏,而不是正确显示"查无此团"。
  • includeReleased=true 时才返回非空的 history 字段,默认 false 时行为不变。

4. 查询共用成员候选清单 GET /admin/fleet/group-dispatch/batches/{groupBatchId}/share-member-candidates

VO: ShareMemberCandidateQueryReqVO → List<ShareMemberCandidateRespVO>

使用场景

车务在团期配车页勾选共用关系成员时调用,返回的 sourceType + sourceId 直接喂给确认写口 POST share-groups 的 members[]。本次改动只影响"团期不存在"时的响应,候选行结构未变。

入参

字段 位置 类型 必填 约束 说明
groupBatchId Path Long ✅ - 团期主订单 ID
serviceDate Query LocalDate ✅ yyyy-MM-dd 必须落在该团基线 serviceDates 内,窗外抛 602104
resourceType Query String ✅ VEHICLE/DRIVER 非法字面量抛 INVALID_PARAM
resourceId Query Long 否 - 不传=浏览态,此时 occupying/selectable 恒为 null(未判定)

出参 Result<List<ShareMemberCandidateRespVO>>

字段 类型 说明
sourceType String ASSIGNMENT(逐户接送派单)/ GROUP_DISPATCH(团级配车行)
sourceId Long→String 成员来源 ID,确认写口 members[].sourceId 直接用它
requirementId / orderId Long→String 用车需求 ID / 订单 ID(团级配车行为空)
orderNo / teamNo / customerName String 订单号 / 团号(GROUP_DISPATCH 行与无团号为 null)/ 客户名
headcount Integer 人数
pickupAt / dropoffAt String 接客地 / 送客地
pickupParticipant / dropoffParticipant Integer 当日是否参与接机/送机,1=是
groupCode String 车务分组编码(非团号)
vehicleModel String 车型,仅 ASSIGNMENT 行有值
occupiedVehicleId / occupiedVehiclePlate Long→String / String 当前占用车辆 ID / 车牌
occupiedDriverId / occupiedDriverName Long→String / String 当前占用司机 ID / 姓名
occupying Boolean 三态:null=未判定(resourceId 未传时)
shareGroupId Long→String 本行已属的 ACTIVE 共用关系 ID,不属任何关系为 null
selectable Boolean 三态:true=可选 / false=不可选 / null=未判定
unselectableReason / unselectableDetail String 不可选原因(机器可读)/ 人读补充

以上字段结构本次未改动,仅"团期不存在"场景的响应形状变化。

请求示例

GET /admin/fleet/group-dispatch/batches/8801/share-member-candidates?serviceDate=2026-09-12&resourceType=VEHICLE

响应示例

以下取值取自该 VO 源码 @ApiModelProperty 声明的示例值(非本轮实测输出,实测仅覆盖下方"错误响应"的团期不存在场景),用于说明字段形状:

{ "code": 200, "message": "成功", "data": [ { "sourceType": "ASSIGNMENT", "sourceId": "88001", "requirementId": "5501", "orderId": "70123", "orderNo": "26-0503", "teamNo": "26-0480", "customerName": "赵先生", "headcount": 3, "pickupAt": "海拉尔机场", "dropoffAt": "满洲里口岸", "pickupParticipant": 1, "dropoffParticipant": 0, "groupCode": "G1", "vehicleModel": "别克GL8", "occupiedVehicleId": "2001", "occupiedVehiclePlate": "京A·····", "occupiedDriverId": "3001", "occupiedDriverName": "王师傅", "occupying": true, "shareGroupId": "360462416850587648", "selectable": true } ], "success": true }

空数据 / 降级响应

无匹配候选时返回 data=[],这是正常结果,不是错误;与"团期不存在"的 600015 不同。

错误响应

{ "code": 600015, "message": "团期不存在: 9107777777777777777", "data": null, "success": false }

业务边界

  • 团期不存在时统一改抛 600015,与另外三个读口一致。
  • occupying / selectable 三态字段语义本次不变:不传 resourceId 时恒为 null(未判定),不会误报 false。
  • shareGroupId 非空表示该行已属某个共用关系;本读口不知道调用方正在编辑哪一个关系——若在追加同一关系的成员,前端仍需把该关系已有成员一并带上(成员是全集不是增量),这一点本次未变化。
  • selectable=true 不是提交必成功的承诺,候选清单是时点快照、不加锁,提交时仍可能撞 602106,本次未变化。

四、契约约束与正确调用方式(接口类必写)

本节只写后端接受/拒绝 payload 的规则,不写 UI 渲染建议。

✅ 正确 / ❌ 错误 payload 对照

场景 payload / 响应
✅ 查询存在的团期 四个读口均正常返回 code=200
✅ 查询存在但零共用关系的团期(share-groups) code=200 + data=[]
❌ 查询不存在的团期(四个读口) code=600015
❌ 继续把 data.length===0 当作"团期不存在"的判据 遇到 600015 时拿不到 data 数组,需新增 600015 分支

切换状态时的必要动作

前端拦到 code=600015 时应提示"团期不存在"类文案并阻断当前页面的后续操作(如返回列表页重新选择团期),不要自动重试;600012/602113/600009 等其余错误码仍按原"可重试"逻辑处理,含义未变。


五、数据库行为(涉及写操作时必写)

本次涉及的四个接口均为只读查询,无任何数据库写操作。改动只影响 Feign 出向调用失败时的错误码分流逻辑与部分错误/提示文案,不涉及任何表结构或存量数据变化。


六、边界行为

  • 未登录 → 401(网关拦截)
  • 团期不存在 → 600015(四个读口统一,本次新行为)
  • 上游确实不可达(非团期不存在,如超时/熔断降级)→ 仍返回各读口原有的可重试码(overview=600012,readiness=602113,share-groups 查询=600009,share-member-candidates=600009),含义未变
  • share-groups / share-member-candidates 无匹配数据 → data=[],不是错误
  • readiness 的 blockers/warnings 为空数组 → 表示该维度全部通过/无提醒,不是错误

六.5、枚举 / 数据字典(接口出现枚举时必写)

团期不存在错误码(GroupDispatchErrorCode)

所属字段: 无(HTTP 响应顶层 code) | 类型: Integer

值 中文 说明
600015 团期不存在 上游 order-v3 明确回"团期不存在"(含已软删)时的失败关闭码;本 changelog 覆盖的四个读口统一适用;永久性否定,不应自动重试

BLOCK_NOT_CONFIRMED 不是新增枚举值,本次只是其 message 文案按"零配车行/有配车行未确认"两种子场景分化,见六.6。

六.6、修改前后对比(修改/删除类接口必写,新增跳过)

字段级对比

本次无响应字段新增或删除,四个接口的成功路径字段结构均未改动。

行为级对比

场景 改前 改后
四个读口对不存在团期的响应 overview / readiness / share-member-candidates 返回各自原有的可重试码;share-groups 返回 code=200 + data=[] 统一返回 code=600015(永久性否定)
readiness 该团尚无任何配车行 blockers[].message = "本团有 0 条配车行尚未确认" blockers[].message = "本团尚未创建任何配车行"(code 仍是 BLOCK_NOT_CONFIRMED)
readiness 该团有配车行但部分未确认 blockers[].message = "本团有 N 条配车行尚未确认" 不变,仍是 "本团有 N 条配车行尚未确认"

六.7、影响评估(修改/删除类必写)

  • 是否破坏向后兼容: 是——share-groups 对不存在团期的响应形状变化(200+data=[] → 600015)是唯一的结构性破坏点;overview/readiness/share-member-candidates 原本就是错误响应分支,只是错误码数值变了(code 判断逻辑需同步更新,但不是从"成功"变"失败")。
  • 前端是否必须同步上线: 是——针对 share-groups,若继续沿用旧的 data.length===0 判断"无共用关系",遇到不存在的团期会因为拿到 600015 错误响应、取不到 data 数组而报错,而不是正确显示"查无此团";针对 readiness 若有按 message 文本内容做分支判断的逻辑需要改成按 code 判断。
  • 前端 workaround 清理点: 若此前为"team not found 但 share-groups 返回空数组"这类情况写过特殊兼容逻辑,可以确认改造后不再需要,因为现在有独立的 600015 信号可用。

七、不影响范围(显式声明, 帮前端/QA 缩小排查面)

  • 仅影响: 管理后台团期配车页四个只读端点在"团期不存在"场景下的响应;就绪判定端点"该团尚无任何配车行"这一特定场景的提示文案。
  • 零影响:
    • 四个读口成功路径的响应字段结构(除本 changelog 描述的错误码分流与 readiness 文案外,无字段增删)
    • 其余可重试错误码(600009 / 600012 / 602113 等)的含义与返回条件
    • readiness 端点"该团有配车行但部分未确认"场景的提示文案
    • 团期配车写口(reconfigure/confirm)与共用关系写口(confirm/release),本次改动仅涉及只读端点

八、测试环境已验证

服务:hl-fleet-service,dev-v3 分支部署测试网关 @ e2982739e8(含 #8536/#8537 所在提交),测试网关 https://api.test.1814.love:

✓ 不存在团期 groupBatchId=9107777777777777777 → 总览/就绪判定/共用关系查询/共用成员候选 四个读口均返回 code=600015, message="团期不存在: 9107777777777777777"
✓ 团期 groupBatchId=2104840641651556353(存在且零共用关系)→ GET share-groups 返回 code=200, data=[](与不存在团期的 600015 可区分)
✓ 团期 groupBatchId=2104838272570245121(团级需求已确认、零物理配车行)→ GET readiness 返回 blockers=[{"code":"BLOCK_NOT_CONFIRMED","message":"本团尚未创建任何配车行"}]

十、相关文档

关联 / 联系人

链接

联系人

  • 后端负责人: @wx