# API 变更通知 **更新时间**: 2026-05-08 15:00 **PR**: #1878 feat(order-v2): 到达/返程信息支持区分一起/多批两种模式 + #1887 修正接口描述 --- ## 破坏性变更:POST /mp/order/{orderId}/arrival 语义彻底变更 ### 变了什么(前端视角) **单数接口从「追加一条」变成「该方向全量替换 1 条」。** | 行为 | 旧逻辑(PR 前) | 新逻辑(PR 后) | |------|----------------|----------------| | 连续调 2 次 | 产生 2 条批次(追加) | 第 2 次会把第 1 次清掉,只保留最新 1 条 | | 想分批到达 | 多次调单数接口 | 必须改用 /arrival/batch(提交多元素数组) | | 已有批次被覆盖范围 | 无此逻辑 | 只清同一 direction 的旧批次,不影响另一方向 | 如果小程序之前通过多次调 POST /arrival 实现「分批到达」,现在必须改为调 POST /arrival/batch。 --- ## Bug 修复:POST /mp/order/{orderId}/arrival/batch 不再误删另一方向 | 行为 | 旧行为(有 bug) | 新行为(已修复) | |------|----------------|----------------| | 提交返程多批 | 把已填的到达批次也一起删掉 | 只删 direction=DEPARTURE 的旧批次,ARRIVAL 不受影响 | | 提交到达多批 | 把已填的返程批次也一起删掉 | 只删 direction=ARRIVAL 的旧批次,DEPARTURE 不受影响 | 如果前端之前因为这个 bug 做了「先查再保」之类的 workaround,可以清理掉。 --- ## 新增:GET 接口返回 mode + modeLabel 字段 GET /mp/order/{orderId}/arrival 返回的每个批次对象新增 2 个字段: | 字段 | 类型 | 说明 | |------|------|------| | mode | String | 模式枚举:TOGETHER 或 SEPARATE | | modeLabel | String | 按方向拼出的中文标签(见下表) | modeLabel 的 4 种值: | direction | mode | modeLabel | |-----------|------|----------| | ARRIVAL | TOGETHER | 一起到达 | | ARRIVAL | SEPARATE | 多批到达 | | DEPARTURE | TOGETHER | 一起返程 | | DEPARTURE | SEPARATE | 多批返程 | 前端可以用 arrivals[0]?.mode(或 departures[0]?.mode)来判断该方向当前 tab 模式,决定进入页面时默认选中哪个选项卡。 --- ## 新增错误码:580010 BATCH_DIRECTION_MIXED POST /mp/order/{orderId}/arrival/batch 增加新校验:请求数组里所有元素的 direction 必须一致(不能同一次 batch 里混提 ARRIVAL 和 DEPARTURE)。 | 错误码 | message | |--------|--------| | 580010 | 批量提交的批次必须同一方向(到达或返程) | 响应示例(错误): ```json { "code": 580010, "message": "批量提交的批次必须同一方向(到达或返程)", "data": null } ``` --- ## 涉及的接口汇总 | # | 接口 | 方法 | 路径 | 变更类型 | 说明 | |---|------|------|------|----------|------| | 1 | 查询订单全量批次 | GET | /mp/order/{orderId}/arrival | 字段新增 | 每个批次对象新增 mode + modeLabel | | 2 | 新增交通批次 | POST | /mp/order/{orderId}/arrival | 语义破坏性变更 | 从追加改为该方向全量替换 1 条 | | 3 | 全量替换批次(多批) | POST | /mp/order/{orderId}/arrival/batch | Bug 修复 + 新增校验 | 修方向隔离 bug;新增 direction 混用校验 | | 4 | 修改交通批次 | PUT | /mp/order/{orderId}/arrival/plan/{planId} | 无变化 | - | | 5 | 删除交通批次 | DELETE | /mp/order/{orderId}/arrival/plan/{planId} | 无变化 | - | --- ## 接口详细定义 ### 1. GET /mp/order/{orderId}/arrival — 查询订单全量到达/离开批次 - **使用场景**:进入订单详情/行程页时查询,用返回的 arrivals[0]?.mode 和 departures[0]?.mode 决定各方向 tab 默认状态 - **路径参数**: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | orderId | Long | 是 | 订单 ID | - **响应字段(data 对象)**: | 字段 | 类型 | 说明 | |------|------|------| | orderId | Long | 订单 ID | | arrivals | Array | direction=ARRIVAL 的批次列表 | | departures | Array | direction=DEPARTURE 的批次列表 | arrivals/departures 内每个批次对象字段(MpArrivalPlanRespVO): | 字段 | 类型 | 说明 | |------|------|------| | planId | Long | 批次 ID | | orderId | Long | 订单 ID | | direction | String | ARRIVAL/DEPARTURE | | directionLabel | String | 到达/离开 | | mode | String | **[本次新增]** TOGETHER/SEPARATE | | modeLabel | String | **[本次新增]** 一起到达/多批到达/一起返程/多批返程 | | transportType | String | FLIGHT/TRAIN/SELF_DRIVE | | transportTypeLabel | String | 飞机/火车/自驾 | | transportNo | String | 航班号/车次号(自驾为 null) | | carrier | String | 航司/铁路公司 | | departStation | String | 出发站/机场 | | arriveStation | String | 到达站/机场 | | departTime | String | 出发时间,格式 yyyy-MM-dd HH:mm:ss | | arriveTime | String | 到达时间,格式 yyyy-MM-dd HH:mm:ss | | selfDrivePeriod | String | 自驾时段(MORNING/AFTERNOON/EVENING),非自驾为 null | | selfDrivePeriodLabel | String | 上午/下午/晚上,非自驾为 null | | selfDriveEta | String | 自驾预计到达精确时间,非自驾为 null | | remark | String | 用户备注 | | creatorType | String | USER/ADMIN | | createTime | String | 创建时间 | | travelers | Array | 本批次出行人列表 | travelers 内每个出行人字段: | 字段 | 类型 | 说明 | |------|------|------| | travelerId | Long | 出行人 ID | | name | String | 姓名 | | travelerType | String | ADULT/CHILD/YOUNG_CHILD/BABY | - **响应示例(完整)**: ```json { "code": 200, "message": "success", "data": { "orderId": 700001, "arrivals": [ { "planId": 800001, "orderId": 700001, "direction": "ARRIVAL", "directionLabel": "到达", "mode": "TOGETHER", "modeLabel": "一起到达", "transportType": "FLIGHT", "transportTypeLabel": "飞机", "transportNo": "CZ6255", "carrier": "南方航空", "departStation": "北京首都T3", "arriveStation": "海拉尔东山", "departTime": "2026-07-10 08:30:00", "arriveTime": "2026-07-10 11:00:00", "selfDrivePeriod": null, "selfDrivePeriodLabel": null, "selfDriveEta": null, "remark": "带小孩,需婴儿座椅", "creatorType": "USER", "createTime": "2026-07-01 10:00:00", "travelers": [ { "travelerId": 10001, "name": "张三", "travelerType": "ADULT" } ] } ], "departures": [ { "planId": 800002, "orderId": 700001, "direction": "DEPARTURE", "directionLabel": "离开", "mode": "SEPARATE", "modeLabel": "多批返程", "transportType": "TRAIN", "transportTypeLabel": "火车", "transportNo": "K209", "carrier": null, "departStation": "海拉尔", "arriveStation": "北京", "departTime": "2026-07-15 10:00:00", "arriveTime": "2026-07-16 08:00:00", "selfDrivePeriod": null, "selfDrivePeriodLabel": null, "selfDriveEta": null, "remark": null, "creatorType": "USER", "createTime": "2026-07-02 09:00:00", "travelers": [ { "travelerId": 10001, "name": "张三", "travelerType": "ADULT" } ] } ] } } ``` --- ### 2. POST /mp/order/{orderId}/arrival — 新增交通批次(单条,该方向全量替换) - **使用场景**:用户在「一起到达」或「一起返程」tab 填写单条信息并提交 - **语义重申**:调用此接口会把同 direction 的所有旧批次软删,再插入 1 条新批次。最终该方向只剩 1 条,mode 固定为 TOGETHER - **路径参数**: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | orderId | Long | 是 | 订单 ID | - **请求参数(JSON Body)**: | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | direction | String | 是 | ARRIVAL=到达 / DEPARTURE=离开 | | transportType | String | 是 | FLIGHT=飞机 / TRAIN=火车 / SELF_DRIVE=自驾 | | transportNo | String | 条件必填 | 航班号/车次号;FLIGHT/TRAIN 必填,SELF_DRIVE 不填 | | carrier | String | 否 | 航司/铁路公司,最长 64 字符 | | departStation | String | 条件必填 | 出发站/机场;DEPARTURE+FLIGHT/TRAIN 必填;ARRIVAL 可选 | | arriveStation | String | 条件必填 | 到达站/机场;ARRIVAL+FLIGHT/TRAIN 必填;DEPARTURE 可选 | | departTime | String | 条件必填 | 出发时间;DEPARTURE+FLIGHT/TRAIN 必填;格式 yyyy-MM-dd HH:mm:ss | | arriveTime | String | 条件必填 | 到达时间;ARRIVAL+FLIGHT/TRAIN 必填;格式 yyyy-MM-dd HH:mm:ss | | selfDrivePeriod | String | 条件必填 | 自驾时段;SELF_DRIVE 必填;MORNING/AFTERNOON/EVENING | | selfDriveEta | String | 否 | 自驾预计到达精确时间;SELF_DRIVE 可选;格式 yyyy-MM-dd HH:mm:ss | | remark | String | 否 | 用户备注,最长 255 字符 | | travelerIds | Array | 是 | 出行人 ID 列表,至少 1 人,必须属于本订单 | - **请求示例(到达+飞机)**: ```json { "direction": "ARRIVAL", "transportType": "FLIGHT", "transportNo": "CZ6255", "carrier": "南方航空", "departStation": "北京首都T3", "arriveStation": "海拉尔东山", "departTime": "2026-07-10 08:30:00", "arriveTime": "2026-07-10 11:00:00", "remark": "带小孩,需婴儿座椅", "travelerIds": [ 10001, 10002 ] } ``` - **响应示例(完整)**: ```json { "code": 200, "message": "success", "data": { "planId": 800001, "orderId": 700001, "direction": "ARRIVAL", "directionLabel": "到达", "mode": "TOGETHER", "modeLabel": "一起到达", "transportType": "FLIGHT", "transportTypeLabel": "飞机", "transportNo": "CZ6255", "carrier": "南方航空", "departStation": "北京首都T3", "arriveStation": "海拉尔东山", "departTime": "2026-07-10 08:30:00", "arriveTime": "2026-07-10 11:00:00", "selfDrivePeriod": null, "selfDrivePeriodLabel": null, "selfDriveEta": null, "remark": "带小孩,需婴儿座椅", "creatorType": "USER", "createTime": "2026-07-01 10:00:00", "travelers": [ { "travelerId": 10001, "name": "张三", "travelerType": "ADULT" }, { "travelerId": 10002, "name": "李四", "travelerType": "CHILD" } ] } } ``` --- ### 3. POST /mp/order/{orderId}/arrival/batch — 全量替换批次(多批模式) - **使用场景**:用户在「多批到达」或「多批返程」tab,一次性提交该方向所有批次 - **Bug 修复**:旧版本会把订单全部旧批次删掉(含另一方向),新版本只删 body 第一条元素对应的 direction - **新增校验**:body 数组里所有元素的 direction 必须一致,混提返回 code=580010 - **路径参数**: | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | orderId | Long | 是 | 订单 ID | - **请求参数(JSON Body,数组)**:字段同上面单条接口,外层包数组 - **请求示例(多批返程)**: ```json [ { "direction": "DEPARTURE", "transportType": "FLIGHT", "transportNo": "CZ6256", "carrier": "南方航空", "departStation": "海拉尔东山", "arriveStation": "北京首都T3", "departTime": "2026-07-15 12:00:00", "arriveTime": "2026-07-15 15:30:00", "travelerIds": [ 10001 ] }, { "direction": "DEPARTURE", "transportType": "TRAIN", "transportNo": "K209", "departStation": "海拉尔", "arriveStation": "北京", "departTime": "2026-07-15 10:00:00", "arriveTime": "2026-07-16 08:00:00", "travelerIds": [ 10002 ] } ] ``` - **响应示例(完整)**: ```json { "code": 200, "message": "success", "data": { "orderId": 700001, "arrivals": [], "departures": [ { "planId": 800003, "orderId": 700001, "direction": "DEPARTURE", "directionLabel": "离开", "mode": "SEPARATE", "modeLabel": "多批返程", "transportType": "FLIGHT", "transportTypeLabel": "飞机", "transportNo": "CZ6256", "carrier": "南方航空", "departStation": "海拉尔东山", "arriveStation": "北京首都T3", "departTime": "2026-07-15 12:00:00", "arriveTime": "2026-07-15 15:30:00", "selfDrivePeriod": null, "selfDrivePeriodLabel": null, "selfDriveEta": null, "remark": null, "creatorType": "USER", "createTime": "2026-07-01 11:00:00", "travelers": [ { "travelerId": 10001, "name": "张三", "travelerType": "ADULT" } ] }, { "planId": 800004, "orderId": 700001, "direction": "DEPARTURE", "directionLabel": "离开", "mode": "SEPARATE", "modeLabel": "多批返程", "transportType": "TRAIN", "transportTypeLabel": "火车", "transportNo": "K209", "carrier": null, "departStation": "海拉尔", "arriveStation": "北京", "departTime": "2026-07-15 10:00:00", "arriveTime": "2026-07-16 08:00:00", "selfDrivePeriod": null, "selfDrivePeriodLabel": null, "selfDriveEta": null, "remark": null, "creatorType": "USER", "createTime": "2026-07-01 11:00:00", "travelers": [ { "travelerId": 10002, "name": "李四", "travelerType": "CHILD" } ] } ] } } ``` --- ## 枚举 / 字典值(完整) ### transport_direction(方向) | 值 | 中文 | 说明 | |----|------|------| | ARRIVAL | 到达 | 游客到达目的地 | | DEPARTURE | 离开 | 游客离开目的地(返程) | ### mode(模式,本次新增) | 值 | 中文 | 说明 | |----|------|------| | TOGETHER | 一起 | 该方向所有出行人同一批次 | | SEPARATE | 多批 | 该方向出行人分多个批次 | ### modeLabel(按 direction + mode 拼,本次新增) | direction | mode | modeLabel | |-----------|------|-----------| | ARRIVAL | TOGETHER | 一起到达 | | ARRIVAL | SEPARATE | 多批到达 | | DEPARTURE | TOGETHER | 一起返程 | | DEPARTURE | SEPARATE | 多批返程 | ### transport_type(交通方式) | 值 | 中文 | |----|------| | FLIGHT | 飞机 | | TRAIN | 火车 | | SELF_DRIVE | 自驾 | ### self_drive_period(自驾时段) | 值 | 中文 | 时间范围 | |----|------|---------| | MORNING | 上午 | 06:00-12:00 | | AFTERNOON | 下午 | 12:00-18:00 | | EVENING | 晚上 | 18:00 以后 | ### creator_type(创建者类型) | 值 | 中文 | |----|------| | USER | 用户自填 | | ADMIN | 定制师代录 | ### traveler_type(出行人类型) | 值 | 中文 | |----|------| | ADULT | 成人 | | CHILD | 儿童 | | YOUNG_CHILD | 幼儿 | | BABY | 婴儿 | --- ## 错误码(本模块完整) | code | message | 触发场景 | |------|---------|---------| | 580001 | 订单当前状态不可修改交通信息: {状态} | 订单不在可编辑状态 | | 580002 | 出行人列表不能为空 | travelerIds 为空 | | 580003 | 以下出行人不属于本订单: {ids} | travelerIds 包含不属于此订单的 ID | | 580004 | 航班号/车次号不能为空 | FLIGHT/TRAIN 时 transportNo 未填 | | 580005 | 到达机场/车站不能为空 | ARRIVAL+FLIGHT/TRAIN 时 arriveStation 未填 | | 580006 | 到达时间不能为空 | ARRIVAL+FLIGHT/TRAIN 时 arriveTime 未填 | | 580007 | 出发机场/车站不能为空 | DEPARTURE+FLIGHT/TRAIN 时 departStation 未填 | | 580008 | 出发时间不能为空 | DEPARTURE+FLIGHT/TRAIN 时 departTime 未填 | | 580009 | 自驾时段不能为空 | SELF_DRIVE 时 selfDrivePeriod 未填 | | 580010 | 批量提交的批次必须同一方向(到达或返程) | batch 接口 body 内 direction 混用(本次新增) | --- ## 业务规则 / 校验规则 1. POST /arrival(单数):提交即清空同 direction 旧批次,再插入 1 条。最终该方向只有 1 条批次,mode 固定为 TOGETHER。 2. POST /arrival/batch:提交即清空同 direction 旧批次,再批量插入。有 2 条及以上时 mode 为 SEPARATE;仅 1 条时 mode 也是 SEPARATE(因为用户选择了「多批」入口)。 3. 两个接口只影响自己提交的 direction,不互相干扰(本次 bug 修复要点)。 4. PUT /arrival/plan/{planId} 修改单条,不影响其他批次,不改变 mode。 5. DELETE /arrival/plan/{planId} 只软删单条。 6. 以上操作均需订单处于可编辑状态,否则返回 580001。 --- ## 前端实现建议 --- ## 补充说明 - GET 接口新增 mode/modeLabel 字段,向后兼容(纯新增,无删改名),已有代码不受影响 - POST 单数接口语义变更属于破坏性变更,旧版用多次调单数接口实现分批的需改用 batch - 服务重启:需重启 hl-order-service-v2 和 hl-mp-service 后生效