适用版本:
feat-virture-order-contine-for-single-car分支
后端服务:xp-robotaxi-operation-boot
文档版本:2026-06-07
批量测试执行过程中,若某辆车发生故障(GPS 卡死、车端异常等)导致 ORDER_NEAR_DESTINATION_EVENT 事件无法上送,链式回调链路会中断,该车辆停留在某一段订单上无法继续。
为此新增「**故障车辆手动恢复**」功能:人工确认车辆已修复且旧订单已无法继续后,前端调用恢复接口,后端将卡住的旧订单标记为已取消并模拟链式回调推进下一段,使该车辆重新进入批量测试流程。
/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 接口获取):
status = RUNNING(COMPLETED / ERROR / CANCELLED 不能恢复)currentOrderId 真实存在且确实卡死(建议先与现场人员确认)批量测试详情页 → 车辆进度列表 → 每行操作列。
仅当 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 | 结束时间 |
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 记录操作日志。前端按现有运营管理后台的权限策略管控按钮即可。