- #2521 list 路径迁移 /transport-plans → /transport-plan/list - #2522 add 路径 + 错误码 581140-581143 + @Idempotent + @Lock4j - #2523 edit Method PUT → POST + 错误码 581144 - #2524 delete Method DELETE → POST + 桥接表级联软删 测试服 9443 真测全 ✅ (commit 15e2c7eeb 含 hotfix #2550) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7.8 KiB
7.8 KiB
大交通批次列表: 接口路径破坏性迁移 (transport-plans → transport-plan/list)
存放目录: 二期(v3,
order-v3标签)→changelogs-v2/2026-05/服务: hl-order-v3 (端口 8084) PR: #2544 (squash 后 commit
be3badaca) Issue: #2521 日期: 2026-05-18 影响范围: 管理后台「行程安排 - 接送站」区块 - 大交通批次列表
⚠️ 关键变化(破坏性 - 前端必同步)
一行红字说清:
- 本次变了什么: 大交通批次列表接口路径从
/transport-plans改为/transport-plan/list - 前端以前以为的是什么:
GET /v3/admin/order/{id}/transport-plans(旧式复数资源风格) - 实际现在是什么:
GET /v3/admin/order/{id}/transport-plan/list(统一 list/add/edit/delete 动词风格)
配套破坏性: §2.6 大交通批次模块 4 个接口路径风格 + 动词 + Method 全部统一迁移,见 #2522/#2523/#2524 changelog。前端需要 4 个接口一并改。
一、背景
V5.48 §2.6 大交通批次模块 4 个接口(list/add/edit/delete)统一为 /transport-plan/{动词} 子路径风格,与订单模块其他子资源(出行人 traveler/list、配房 hotel-requirement 等)保持一致:
| 风格 | 旧 (V5.47 之前) | 新 (V5.48) |
|---|---|---|
| 列表 | GET /transport-plans |
GET /transport-plan/list |
| 新增 | POST /transport-plans |
POST /transport-plan/add |
| 编辑 | PUT /transport-plans/{planId} |
POST /transport-plan/{planId}/edit |
| 软删 | DELETE /transport-plans/{planId} |
POST /transport-plan/{planId}/delete |
统一动词路径后,网关路由 / 权限 RBAC / 操作审计的资源前缀一致,便于配置和扫描。
二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 大交通批次列表 | GET | /v3/admin/order/{id}/transport-plan/list |
路径迁移 | 旧路径 /transport-plans 已下线 |
三、接口详情
1. 大交通批次列表 GET /v3/admin/order/{id}/transport-plan/list
VO: TransportPlanVO
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
id |
Path | Long | ✅ | - | 订单 ID |
出参 Result<List<TransportPlanVO>>
| 字段 | 类型 | 说明 |
|---|---|---|
id |
String | 批次 ID(雪花) |
orderId |
String | 订单 ID |
direction |
String | 方向 ARRIVAL / DEPARTURE |
transportType |
String | 类型 FLIGHT / TRAIN / SELF_DRIVE |
transportNo |
String | 航班号 / 车次号(SELF_DRIVE 时为 null) |
carrier |
String | 航司 / 铁路公司 |
departStation |
String | 出发站 |
arriveStation |
String | 到达站 |
departTime |
LocalDateTime | 出发时间(SELF_DRIVE 时为 null) |
arriveTime |
LocalDateTime | 到达时间(SELF_DRIVE 时为 null) |
selfDrivePeriod |
String | 仅 SELF_DRIVE: MORNING / AFTERNOON / EVENING |
selfDriveEta |
LocalDateTime | 仅 SELF_DRIVE: 预计抵达时间 |
travelers |
List | 桥接表关联出行人,元素 {id, name} |
remark |
String | 备注 |
请求示例
GET /v3/admin/order/60123456789012/transport-plan/list
响应示例
{
"code": 200,
"data": [
{
"id": "80012345",
"orderId": "60123456789012",
"direction": "ARRIVAL",
"transportType": "FLIGHT",
"transportNo": "CA1234",
"carrier": "中国国际航空",
"departStation": "北京首都T3",
"arriveStation": "长春龙嘉",
"departTime": "2026-06-01T08:30:00",
"arriveTime": "2026-06-01T10:15:00",
"selfDrivePeriod": null,
"selfDriveEta": null,
"travelers": [
{"id": "70123456789012", "name": "张三"},
{"id": "70123456789013", "name": "王小明"}
],
"remark": "需要接机举牌"
},
{
"id": "80012346",
"orderId": "60123456789012",
"direction": "DEPARTURE",
"transportType": "SELF_DRIVE",
"transportNo": null,
"carrier": null,
"departStation": null,
"arriveStation": null,
"departTime": null,
"arriveTime": null,
"selfDrivePeriod": "AFTERNOON",
"selfDriveEta": "2026-06-05T15:00:00",
"travelers": [
{"id": "70123456789012", "name": "张三"}
],
"remark": null
}
],
"msg": "success"
}
空数据响应
订单尚未登记任何大交通批次时:
{ "code": 200, "data": [], "msg": "success" }
错误响应
订单不存在:
{
"code": 581100,
"msg": "订单不存在",
"data": null
}
四、契约约束与正确调用方式
✅ 正确 / ❌ 错误调用对照
| 场景 | 请求 |
|---|---|
| ✅ 新路径 | GET /v3/admin/order/60123456789012/transport-plan/list |
| ❌ 旧路径(已下线 404) | GET /v3/admin/order/60123456789012/transport-plans |
字段语义约束
direction取值固定两值:ARRIVAL(到达) /DEPARTURE(离开)transportType三值:FLIGHT/TRAIN/SELF_DRIVESELF_DRIVE类型行:transportNo/departTime/arriveTime必为 null;selfDrivePeriod必有值FLIGHT/TRAIN类型行:transportNo/departTime/arriveTime必有值;selfDrivePeriod/selfDriveEta必为 nulltravelers数组永远非空(后端保证),元素至少 1 个
五、数据库行为
只读查询,无写动作。
| 查询步骤 | 表 | 说明 |
|---|---|---|
| 1 | order_transport_plan |
WHERE order_id = ? AND deleted = 0,主表批次记录 |
| 2 | LEFT JOIN order_transport_plan_traveler |
WHERE deleted = 0,桥接表关联出行人 ID |
| 3 | JOIN order_traveler |
WHERE deleted = 0,出行人姓名补全 |
| 4 | 内存装配 | 同一 plan 多 traveler 聚合为 travelers: [{id, name}] 数组 |
排序: ORDER BY direction ASC, depart_time ASC, id ASC (ARRIVAL 先于 DEPARTURE,同方向按时间升序)。
六、边界行为
- 未登录 → 401(网关拦截)
- 订单不存在 →
581100 - 订单存在但无任何批次 → 200 +
data: [](不报错) - 批次存在但桥接表全软删 →
travelers: [](理论上不应出现,后端保证) - 老数据(v2 历史 plan 无
mode字段)→ 字段为 null,不异常
七、不影响范围(显式声明,帮前端 / QA 缩小排查面)
- 仅影响: 管理后台 F21 行程安排 Tab 「接送站」区块 - 大交通批次列表渲染
- 零影响:
- C 端订单详情 mp 接口(不查 plan 表,只查 arrival_plan)
- 订单创建 / 支付 / 退款主流程
- 出行人模块(travelers list 仍走
/admin/order/{id}/traveler/list) - Feign 内部接口
GET /internal/order/orders/{orderId}/travelers(回传transportPlanIds,使用的是同表数据但聚合方向相反,不受路径变化影响)
八、测试环境已验证
测试服 9443 网关 + 真 admin token round-trip 验证:
GET https://web.test.1814.love:9443/v3/admin/order/{orderId}/transport-plan/list
→ 200 + data 数组 ✓
→ travelers 嵌套字段返回正确 (id+name) ✓
→ ARRIVAL/DEPARTURE 排序正确 ✓
→ 空订单返 data: [] ✓
(commit 15e2c7eeb 含 hotfix #2550 修复 conflict markers,4 接口一并 9443 真测过)
九、相关历史 PR
| PR | Issue | 说明 | 是否仍有效 |
|---|---|---|---|
| 本 PR #2544 | #2521 | 路径破坏性迁移 /transport-plans → /transport-plan/list |
✅ 最新 |
十、相关文档
- 关联 Issue: wx/HL#2521
- 关联 PR: wx/HL#2544
- API 文档:
docs/order-v3/api/API-SPEC-V5.48.html§2.6.1 - 配套破坏性: 见
18_#2522_transport-plan-add.md/18_#2523_transport-plan-edit.md/18_#2524_transport-plan-delete.md