批量测试 - 故障车辆手动恢复 前端对接指引

适用版本:feat-virture-order-contine-for-single-car 分支
后端服务:xp-robotaxi-operation-boot
文档版本:2026-06-07


一、需求背景

批量测试执行过程中,若某辆车发生故障(GPS 卡死、车端异常等)导致 ORDER_NEAR_DESTINATION_EVENT 事件无法上送,链式回调链路会中断,该车辆停留在某一段订单上无法继续。

为此新增「**故障车辆手动恢复**」功能:人工确认车辆已修复且旧订单已无法继续后,前端调用恢复接口,后端将卡住的旧订单标记为已取消并模拟链式回调推进下一段,使该车辆重新进入批量测试流程。


二、新增接口

POST /api/v1/xp-test-plan/manualResume

用途:手动恢复故障车辆,跳过当前卡死的订单,推进至下一段。

请求方式:application/x-www-form-urlencoded(Query / Form 参数,**非 JSON Body**)

参数 类型 必填 说明
testPlanId Long 是 测试计划 ID
vehicleId Long 是 故障车辆 ID
currentOrderId Long 是 该车辆当前进行中的故障订单 ID(必须等于车辆进度表中的 currentOrderId)

响应:

{
  "code": 200,
  "msg": "操作成功",
  "data": true
}

业务校验(任一失败均返回 500 错误,msg 中带具体原因):

校验 错误信息
订单 ID 必须能在进度表中查到 未找到订单对应的车辆进度: {orderId}
订单所属计划/车辆必须与传入参数一致 订单与测试计划/车辆不匹配,无法恢复
车辆进度状态必须是 RUNNING(0) 车辆进度非运行中,无法恢复

幂等性:恢复成功后,车辆进度的 currentOrderId 会被链式回调清空并替换为下一段订单 ID。前端再传旧 currentOrderId 会触发"订单与测试计划/车辆不匹配"。


三、前端调用前置条件

调用 manualResume 之前,必须确认以下信息(建议从 vehicleProgress 接口获取):

  1. 当前批次状态为 RUNNING(批次已取消则恢复无意义)
  2. 目标车辆 status = RUNNING(COMPLETED / ERROR / CANCELLED 不能恢复)
  3. 当前 currentOrderId 真实存在且确实卡死(建议先与现场人员确认)

四、推荐 UI 交互

入口位置

批量测试详情页 → 车辆进度列表 → 每行操作列。

显示条件

仅当 status === RUNNING 时显示「故障恢复」按钮。

二次确认弹窗

执行前必须强提示用户:

⚠️ 故障恢复将跳过订单 {currentOrderId},并立即派发该车辆的下一段订单。
- 此操作**仅适用于车辆故障已修复、旧订单确认无法继续的场景**
- 旧订单将被标记为「已取消」,**不会**通知车端
- 操作前请确认车端已不再执行旧订单,否则可能与新订单冲突

是否继续?

调用示例(伪代码)

// services/testPlan.ts
export const manualResume = (params: {
  testPlanId: number | string
  vehicleId: number | string
  currentOrderId: number | string
}) => request.post('/api/v1/xp-test-plan/manualResume', null, { params })

// 组件调用
const handleManualResume = async (row: VehicleProgressVO) => {
  await Modal.confirm({ /* 上面的二次确认文案 */ })
  const res = await manualResume({
    testPlanId,
    vehicleId: row.vehicleId,
    currentOrderId: row.currentOrderId,
  })
  if (res.code === 200) {
    message.success('已触发故障恢复')
    refreshVehicleProgress() // 刷新车辆进度列表
  } else {
    message.error(res.msg)
  }
}

五、相关接口(对接时可能用到)

完整批量测试模块可参考下表,**前端根据现有页面已有的对接情况选择性使用**:

接口 Method 路径 主要作用
启动批量 POST /api/v1/xp-test-plan/batchStart 启动批量测试,参数:{testPlanId, lapCount}
批次进度 GET /api/v1/xp-test-plan/batchProgress?testPlanId= 总进度(创建/完成/异常数 + 状态)
车辆进度 GET /api/v1/xp-test-plan/vehicleProgress?batchId= 故障恢复按钮所在列表的数据来源
重试失败 POST /api/v1/xp-test-plan/batchRetry?testPlanId= 批次结束后重跑 ERROR 车辆
故障恢复 POST /api/v1/xp-test-plan/manualResume 本次新增
取消批次 POST /api/v1/xp-test-plan/batchCancel?testPlanId= 强制中止整个批次

VehicleProgressVO 字段(车辆进度列表项)

字段 类型 说明
vehicleId Long 车辆 ID
plateNumber String 车牌号
currentLap Integer 当前圈数
currentSegment Integer 当前路线段索引
currentOrderId Long 当前进行中订单 ID(manualResume 必传)
totalLaps Integer 总圈数
totalSegments Integer 每圈路线段数
status String RUNNING / COMPLETED / ERROR / CANCELLED
errorMsg String 错误信息(仅 ERROR 状态有值)

BatchProgressVO 字段(批次进度)

字段 类型 说明
batchId Long 批次 ID
totalCount Integer 预计总订单数 = 车辆数 × 段数 × 圈数
createdCount Integer 已创建数
completedCount Integer 已完结数(**含手动恢复跳过的订单**)
errorCount Integer 异常数
status String RUNNING / SUCCESS / PARTIAL_SUCCESS / FAILED / CANCELLED
startTime DateTime 开始时间
endTime DateTime 结束时间

六、注意事项与对接 FAQ

Q1:故障恢复后,统计数字会怎么变化?
A:completedCount 会 +1(与正常订单完成等同处理),createdCount 在派发下一段后再 +1。**前端无需特殊展示"恢复"标记**,统计接口本身不区分。如需区分需另开发审计字段,本期未做。

Q2:手动恢复成功后是否需要前端轮询?
A:建议保持现有的车辆进度轮询节奏即可(一般 2-5s 一次),无需为本接口单独加轮询逻辑。后端动作是同步的,接口返回成功即代表"标记取消 + 链式回调推进"已执行完毕。

Q3:能否在批次已 CANCELLED 后调用?
A:不能。批次取消后会写入 Redis 取消标记,链式回调内部自动拦截。但前端最好在 UI 层就根据 status 隐藏按钮,避免误触发。

Q4:连续点击多次会不会重复推进?
A:不会。currentOrderId 校验天然幂等——第二次调用时旧 orderId 已不在进度表,会返回"订单与测试计划/车辆不匹配"。

Q5:恢复失败后该怎么办?
A:根据 msg 提示分情况:
- "未找到订单"/"不匹配" → 数据已变化,先刷新进度列表
- "非运行中" → 该车辆已 ERROR/CANCELLED,使用 batchRetry 而非本接口
- 网络/系统异常 → 建议提示用户稍后重试

Q6:是否需要权限控制?
A:与 batchStart/batchCancel 一致,已通过后端 @AdminOperationLog 记录操作日志。前端按现有运营管理后台的权限策略管控按钮即可。