状态:部分链路已验证,页面闭环受限。证据组 2/2 已完成;检查通过 26,受限 2,失败 0,待验证 0;已校验截图 25 张。
编排与 API 已验证,教学页面闭环受限。需完成默认教学页面与正式任务运行的接线,才能从页面走完新模型对应的训练。
范围:编排 UI、默认教学入口、正式教学 API 分开验证。
| 模式 | 正式渠道 | 本轮 API 验证方法 | 必检项 | 默认界面边界 |
|---|---|---|---|---|
| 实装实训 | PHYSICAL | 正式 API 的 MANUAL 人工事件 | 三步顺序、失败重试、来源权限、事件幂等、提交与评定 | 默认离线识别页;设备 / 视觉接入另行联调 |
| 对抗训练 | CONFRONTATION | 正式 API 的红蓝两队共享运行 | 岗位权限、两队隔离、顺序、时限、命令幂等、提交与评定 | 默认本地工作台;不混同正式 API 运行 |
| 训练 ID | 名称 | 模式 | 状态 | 当前发布版本 | API 已测版本 | 步骤数 |
|---|---|---|---|---|---|---|
| 163 | 实测训练-牛奶卡车实装检查-20260905 | PHYSICAL | PUBLISHED | 217 | 215 | 3 |
| 164 | 实测训练-狐狸红蓝协同巡检-20260905 | CONFRONTATION | PUBLISHED | 216 | 216 | 2 |
训练 163:API任务50固定215;说明字段兼容修复后在217做UI及封面回归,未改写任务快照。
| 任务 ID | 运行 ID | 渠道 | 队伍 | 状态 | 完成度 | 评定分 |
|---|---|---|---|---|---|---|
| 50 | 44 | PHYSICAL | NEUTRAL | REVIEWED | 100 | 100 |
| 51 | 45 | CONFRONTATION | RED | REVIEWED | 100 | 100 |
| 51 | 46 | CONFRONTATION | BLUE | REVIEWED | 100 | 100 |
随机测试密码与登录会话不写入报告;保留新建数据用于追溯。
证据类型:UI。
{
"title": "实装实训与对抗训练真实流程测试",
"startedAt": "2026-09-05T15:37:32.805Z",
"status": "PASS_WITH_LIMITATIONS",
"checks": [
{
"title": "实装:创建、绑定牛奶卡车、3步配置、保存重开与发布",
"status": "PASS",
"screenshots": [
"screenshots/physical-settings-reopen.png",
"screenshots/physical-authoring.png",
"screenshots/physical-preflight.png",
"screenshots/physical-published.png"
],
"details": {
"id": "163",
"version": "215",
"progress": [
33,
67,
100
],
"profile": {
"type": "PHYSICAL",
"stationName": "牛奶卡车测试工位 A",
"equipmentCode": "E2E-TRUCK-163",
"gatewayProtocol": "HTTP 测试网关",
"sensorChannels": "人工外观确认;测试状态点位",
"safetyInterlocks": "测试工位隔离确认"
}
}
},
{
"title": "对抗:每队人数为小数时阻止发布",
"status": "PASS",
"screenshots": [
"screenshots/confrontation-invalid-team-size.png"
],
"details": {
"input": 2.5,
"message": "发布校验未通过\n×\n发现 1 个必须处理的问题\n\n2 个步骤 · 1 个目标 · 0 个故障 · 及格线 80 分\n\n!\n每队人数必须是 1 到 200 的整数\nmodeConfig.teamSize\ni\n本步骤尚未配置必选安全前置条件\nsteps[0].safetyRules\ni\n本步骤尚未配置必选安全前置条件\nsteps[1].safetyRules\ni\n尚未绑定离线讲解文件,运行时将保留字幕并使用默认本地语音\nsteps.audio\n关闭"
}
},
{
"title": "对抗:显式清空岗位后保存重开,不恢复默认授权",
"status": "PASS",
"screenshots": [
"screenshots/confrontation-empty-positions.png"
],
"details": {
"allowedPositions": [],
"published": false
}
},
{
"title": "对抗:狐狸场景、两步巡检、岗位配置、说明往返与发布",
"status": "PASS",
"screenshots": [
"screenshots/confrontation-positions.png",
"screenshots/confrontation-settings-reopen.png",
"screenshots/confrontation-authoring.png",
"screenshots/confrontation-preflight.png",
"screenshots/confrontation-published.png"
],
"details": {
"id": "164",
"version": "216",
"profile": {
"type": "CONFRONTATION",
"redTeamName": "狐狸巡检红队",
"blueTeamName": "狐狸巡检蓝队",
"teamSize": 2,
"roundDurationMinutes": 7,
"objective": "两队分别完成狐狸模型巡检并确认状态",
"winRule": "按已完成步骤与协同检查结果评分",
"submitPositions": [
"COMMANDER"
],
"roundDuration": 7,
"eventInjections": ""
},
"steps": [
{
"title": "识别狐狸巡检目标",
"summary": "红蓝两队分别识别场景中的狐狸模型,由指挥员确认目标。",
"allowedPositions": [
"COMMANDER"
]
},
{
"title": "完成狐狸状态检查",
"summary": "由指挥员完成状态确认,操作员协同观察;提交团队检查结果。",
"allowedPositions": [
"COMMANDER"
]
}
]
}
},
{
"title": "实装:说明兼容修复回写,重新截图封面及发布",
"status": "PASS",
"screenshots": [
"screenshots/physical-final-published.png"
],
"details": {
"projectId": "163",
"publishedVersionId": "217",
"apiTestVersionId": "215",
"note": "既有任务50固定215;本次仅回填说明与更新截图封面,未改写任务快照。",
"steps": [
{
"stepCode": "PHYSICAL-S01",
"actionCode": "PHYSICAL-A01",
"summary": "核对测试工位与牛奶卡车编号。",
"physicalEventRule": {
"source": "MANUAL",
"eventType": "step.physical-s01.confirmed",
"progressPercent": 33,
"manualConfirmAllowed": true
}
},
{
"stepCode": "PHYSICAL-S02",
"actionCode": "PHYSICAL-A02",
"summary": "人工确认卡车外观状态,使用受控事件记录检查。",
"physicalEventRule": {
"source": "MANUAL",
"eventType": "step.physical-s02.confirmed",
"progressPercent": 67,
"manualConfirmAllowed": true
}
},
{
"stepCode": "PHYSICAL-S03",
"actionCode": "PHYSICAL-A03",
"summary": "核实步骤记录并提交检查结果。",
"physicalEventRule": {
"source": "MANUAL",
"eventType": "step.physical-s03.confirmed",
"progressPercent": 100,
"manualConfirmAllowed": true
}
}
]
}
},
{
"title": "实装默认页面:离线播放与候选复核可操作,无法执行新卡车正式步骤",
"status": "BLOCKED",
"screenshots": [
"screenshots/physical-teaching-list.png",
"screenshots/physical-offline-preview.png",
"screenshots/physical-offline-confirmed.png"
],
"details": {
"assignmentId": "50",
"previewUrl": "/teaching/physical-training/preview/50",
"observed": "进入任务后仍显示固定45秒维修识别录像,确认只改变本次页面候选,未加载卡车三步正式运行。",
"businessWrites": [],
"required": "需将正式任务快照、场景、人工/设备事件及运行记录接入工作台。"
}
},
{
"title": "对抗默认页面:新建下拉仅有本地液压预设,无法选择已发布狐狸训练",
"status": "BLOCKED",
"screenshots": [
"screenshots/confrontation-final-entry.png",
"screenshots/confrontation-final-local-create.png"
],
"details": {
"options": [
"桥梁架设装备液压系统检测与维修训练"
],
"formalAssignmentId": "51",
"formalAssignmentExists": true,
"required": "需将默认任务清单、创建表单和执行入口接入正式对抗任务服务,并确认通用巡检与五阶段排故的适用范围。"
}
},
{
"title": "训练列表两种模式展示各自真实截图封面",
"status": "PASS",
"screenshots": [
"screenshots/physical-list-cover.png",
"screenshots/confrontation-list-cover.png"
],
"details": {
"projects": [
"163",
"164"
],
"authenticatedImagesLoaded": true
}
},
{
"title": "牛奶卡车实装检查:发布重开、模型实际可见、截图封面",
"status": "PASS",
"screenshots": [
"screenshots/physical-independent-reopen.png",
"screenshots/physical-independent-settings.png",
"screenshots/physical-final-cover.jpg"
],
"details": {
"state": "ready",
"meshes": 5,
"visibleMeshes": 5,
"skinnedMeshes": 0,
"position": [
4.2,
0.20617168998977797,
-0.4356763541543951
],
"scale": [
1.2323086149245381,
1.2323086149245381,
1.2323086149245381
],
"finiteBounds": true,
"size": [
3.4406057210321332,
3.390913184034896,
6.000000000000001
],
"camera": {
"position": [
10.565439077211714,
5.0456876852867705,
7.37050840519251
],
"target": [
4.2,
1.695456592017448,
0
]
},
"sample": {
"width": 320,
"height": 180,
"changedPixels": 11669
},
"scene": {
"projectId": "159",
"versionId": "209"
},
"targets": [
{
"id": "scene:OBJ-1788605199171-2",
"name": "牛奶卡车检验主装备",
"source": "scene"
},
{
"id": "scene:OBJ-1788605199171-2/part/interaction-1ba581e6",
"name": "Yup2Zup",
"source": "scene"
},
{
"id": "scene:OBJ-1788605199171-2/part/interaction-004dec41",
"name": "Cesium_Milk_Truck",
"source": "scene"
},
{
"id": "scene:OBJ-1788605199171-2/part/interaction-5f7e4bee",
"name": "Cesium_Milk_Truck_1",
"source": "scene"
},
{
"id": "scene:OBJ-1788605199171-2/part/interaction-607e4d81",
"name": "Cesium_Milk_Truck_2",
"source": "scene"
},
{
"id": "scene:OBJ-1788605199171-2/part/interaction-5d7e48c8",
"name": "Cesium_Milk_Truck_3",
"source": "scene"
},
{
"id": "scene:OBJ-1788605199171-2/part/interaction-5e7e4a5b",
"name": "Node",
"source": "scene"
},
{
"id": "scene:OBJ-1788605199171-2/part/interaction-ce2feac4",
"name": "Wheels",
"source": "scene"
},
{
"id": "scene:OBJ-1788605199171-2/part/interaction-637e523a",
"name": "Node001",
"source": "scene"
},
{
"id": "scene:OBJ-1788605199171-2/part/interaction-f417f82d",
"name": "Wheels001",
"source": "scene"
}
],
"steps": [
{
"title": "核对卡车工位与装备",
"targetId": "scene:OBJ-1788605199171-2",
"weight": 30
},
{
"title": "检查卡车外观状态",
"targetId": "scene:OBJ-1788605199171-2",
"weight": 30
},
{
"title": "确认检查完成",
"targetId": "scene:OBJ-1788605199171-2",
"weight": 40
}
],
"cover": {
"assetId": "2111",
"bytes": 42163,
"sha256": "efb7060464f840bde78744d89567c609dc7b7922216d1c948fe22c1eed3d41a4",
"width": 628,
"height": 640
},
"pageErrors": [],
"blockedWrites": []
}
},
{
"title": "狐狸红蓝协同巡检:发布重开、模型实际可见、截图封面",
"status": "PASS",
"screenshots": [
"screenshots/confrontation-independent-reopen.png",
"screenshots/confrontation-independent-settings.png",
"screenshots/confrontation-final-cover.jpg"
],
"details": {
"state": "ready",
"meshes": 1,
"visibleMeshes": 1,
"skinnedMeshes": 1,
"position": [
-7.5,
0.10930174852949677,
0.3440109341705351
],
"scale": [
0.03616375932570189,
0.03616375932570189,
0.03616375932570189
],
"finiteBounds": true,
"size": [
0.9658796100519353,
2.811899945787403,
6
],
"camera": {
"position": [
-0.04179225073787585,
6.099634646023559,
17.355036987378313
],
"target": [
-7.512232860974557,
1.4059499759307126,
-2.2204460492503126e-16
]
},
"sample": {
"width": 320,
"height": 180,
"changedPixels": 827
},
"scene": {
"projectId": "160",
"versionId": "210"
},
"targets": [
{
"id": "scene:OBJ-1788605873329-2",
"name": "维修装备主体 02",
"source": "scene"
},
{
"id": "scene:OBJ-1788605916565-6",
"name": "狐狸野外巡检目标",
"source": "scene"
},
{
"id": "scene:OBJ-1788605916565-6/part/interaction-a3d35c26",
"name": "fox",
"source": "scene"
}
],
"steps": [
{
"title": "识别狐狸巡检目标",
"targetId": "scene:OBJ-1788605916565-6",
"weight": 50
},
{
"title": "完成狐狸状态检查",
"targetId": "scene:OBJ-1788605916565-6",
"weight": 50
}
],
"cover": {
"assetId": "2108",
"bytes": 51257,
"sha256": "79779a9d1e40c0c160fa3dab25e83931639942f53e2ee3a5da12f9f86ad70081",
"width": 628,
"height": 640
},
"pageErrors": [],
"blockedWrites": []
}
}
],
"projects": [
{
"id": "163",
"name": "实测训练-牛奶卡车实装检查-20260905",
"mode": "PHYSICAL",
"status": "PUBLISHED",
"currentVersionId": "217",
"publishedVersionId": "217",
"sceneProjectId": "159",
"sceneVersionId": "209",
"stepCount": 3,
"totalScore": 100,
"cover": {
"assetId": "2111",
"image": "screenshots/physical-final-cover.jpg"
},
"trainingMode": "PHYSICAL",
"modeConfig": {
"type": "PHYSICAL",
"stationName": "牛奶卡车测试工位 A",
"equipmentCode": "E2E-TRUCK-163",
"gatewayProtocol": "HTTP 测试网关",
"sensorChannels": "人工外观确认;测试状态点位",
"safetyInterlocks": "测试工位隔离确认"
},
"steps": [
{
"stepCode": "PHYSICAL-S01",
"actionCode": "PHYSICAL-A01",
"title": "核对卡车工位与装备",
"summary": "核对测试工位与牛奶卡车编号。",
"targetId": "scene:OBJ-1788605199171-2",
"allowedPositions": [],
"physicalEventRule": {
"source": "MANUAL",
"eventType": "step.physical-s01.confirmed",
"progressPercent": 33,
"manualConfirmAllowed": true
},
"score": 30
},
{
"stepCode": "PHYSICAL-S02",
"actionCode": "PHYSICAL-A02",
"title": "检查卡车外观状态",
"summary": "人工确认卡车外观状态,使用受控事件记录检查。",
"targetId": "scene:OBJ-1788605199171-2",
"allowedPositions": [],
"physicalEventRule": {
"source": "MANUAL",
"eventType": "step.physical-s02.confirmed",
"progressPercent": 67,
"manualConfirmAllowed": true
},
"score": 30
},
{
"stepCode": "PHYSICAL-S03",
"actionCode": "PHYSICAL-A03",
"title": "确认检查完成",
"summary": "核实步骤记录并提交检查结果。",
"targetId": "scene:OBJ-1788605199171-2",
"allowedPositions": [],
"physicalEventRule": {
"source": "MANUAL",
"eventType": "step.physical-s03.confirmed",
"progressPercent": 100,
"manualConfirmAllowed": true
},
"score": 40
}
],
"apiTestVersionId": "215",
"apiVersionNote": "API任务50固定215;说明字段兼容修复后在217做UI及封面回归,未改写任务快照。"
},
{
"id": "164",
"name": "实测训练-狐狸红蓝协同巡检-20260905",
"mode": "CONFRONTATION",
"status": "PUBLISHED",
"currentVersionId": "216",
"publishedVersionId": "216",
"sceneProjectId": "160",
"sceneVersionId": "210",
"stepCount": 2,
"totalScore": 100,
"cover": {
"assetId": "2108",
"image": "screenshots/confrontation-final-cover.jpg"
},
"trainingMode": "CONFRONTATION",
"modeConfig": {
"type": "CONFRONTATION",
"redTeamName": "狐狸巡检红队",
"blueTeamName": "狐狸巡检蓝队",
"teamSize": 2,
"roundDurationMinutes": 7,
"objective": "两队分别完成狐狸模型巡检并确认状态",
"winRule": "按已完成步骤与协同检查结果评分",
"submitPositions": [
"COMMANDER"
],
"roundDuration": 7,
"eventInjections": ""
},
"steps": [
{
"stepCode": "CONFRONTATION-S01",
"actionCode": "CONFRONTATION-A01",
"title": "识别狐狸巡检目标",
"summary": "红蓝两队分别识别场景中的狐狸模型,由指挥员确认目标。",
"targetId": "scene:OBJ-1788605916565-6",
"allowedPositions": [
"COMMANDER"
],
"physicalEventRule": {},
"score": 50
},
{
"stepCode": "CONFRONTATION-S02",
"actionCode": "CONFRONTATION-A02",
"title": "完成狐狸状态检查",
"summary": "由指挥员完成状态确认,操作员协同观察;提交团队检查结果。",
"targetId": "scene:OBJ-1788605916565-6",
"allowedPositions": [
"COMMANDER"
],
"physicalEventRule": {},
"score": 50
}
],
"apiTestVersionId": "216"
}
],
"bugs": [],
"limitations": [
"实装为MANUAL人工事件合同测试,没有接真实PLC、摄像头、视觉识别服务或安全联锁设备。",
"两步狐狸巡检用于通用步骤与红蓝岗位合同,不是需要CONF-INSPECT等五个固定编码的完整排故作业;未宣称排故工作台阶段回写已打通。",
"对抗验证服务端设置了7分钟截止时刻,未等待自然超时触发;未把API账号请求视为多人跨浏览器实时协同UI测试。",
"牛奶卡车沿用原发布场景的视角,车间立柱遮挡部分车身;真实模型已渲染且封面来自该视口。",
"实装当前发布217仅回填兼容说明并更新封面;已完成教学任务50仍固定不可变版本215。",
"历史仅positionActions设置动作岗位的定义在教学读取侧与当前发布预检存在口径差异;本次按现有发布规则配置非空allowedPositions,未改后端岗位合同。",
"开发环境列表切换曾出现一次15秒超时,刷新后恢复;独立复测两种模式共6次查询均HTTP 200、耗时247–403ms,未复现稳定慢查询。详见list-api-latency.json。"
],
"pageErrors": [],
"development": [
"修复模式配置被旧channelProfiles覆盖,保持默认profile与modeConfig一致;对抗分钟/秒及旧roundDuration兼容。",
"保留显式空配置文本;每队人数范围与服务端1–200一致,无效数字阻止发布,不静默夹断。",
"保留步骤设备事件、人工确认、岗位与运行编码;增删排序后重新计算严格递增进度。",
"修复复制步骤编码冲突(含大小写),复制动作岗位映射随新动作编码迁移。",
"显式清空allowedPositions不再补回默认三岗位,保持权限边界并交由正式发布校验阻断。",
"修复instruction/summary双界面操作说明丢失及显式空提示恢复演示内容;用户实际编辑时同步。",
"正式targetId优先,目标选择同步语义引用、节点与动作,防止旧targetRef把新目标回退。",
"沿用上轮训练3D视口截图方案:受控TRAINING_COVER上传、同次保存资产与内容,保存/发布后列表正确显示截图。",
"本次均为正式工程合同适配与bugfix,未新增数据库字段、执行DDL或更改原型业务流程;测试数据通过开发API创建。"
],
"commands": [
{
"command": "pnpm run build",
"status": "PASS",
"details": "vue-tsc、Vite构建和legacy iframe分发校验均通过;仅已有包体积提示。"
},
{
"command": "node --test tools/training-*.test.mjs(本次8个聚焦文件)",
"status": "PASS",
"details": "94/94通过,涵盖封面、场景、真实模型、目标、元数据、模式与步骤兼容。"
},
{
"command": "pnpm run test:training-legacy",
"status": "PASS",
"details": "两项既有训练/地形合同检查通过。"
},
{
"command": "content-training-studio.spec.ts / Edge",
"status": "PASS",
"details": "7/7通过(mock API的工作台回归),无跳过、无不稳定用例,独立报告studio-regression/html/index.html。"
},
{
"command": "UTE2E_TRAINING_MODES=1 UTE2E_BASE_URL=http://192.168.31.168:6180 node tools/training-scene-visibility.e2e.mjs",
"status": "PASS",
"details": "独立Edge会话2/2通过,真实LAN服务、禁止业务写请求;模型可见像素差、固定场景依赖、JPEG尺寸与SHA-256全部通过。"
},
{
"command": "node tools/training-modes-api-live.mjs(163:215;164:216)",
"status": "PASS",
"details": "18/18检查组通过,90次正式教学API请求;含训练/场景/模型固定快照只读复核,详见api-evidence.json。"
}
],
"confirmationItems": [
"将实装工作台从固定离线识别回放扩展为读取正式任务、已发布场景和步骤,并接入人工/设备事件、提交与结果。",
"将对抗默认入口从本地预设任务接入正式任务清单、创建和执行链路;确认通用巡检步骤与五阶段排故工作台的适用范围。"
],
"finishedAt": "2026-09-05T15:58:39.239Z"
}
证据类型:API。
{
"title": "实装人工事件与红蓝对抗正式 API 闭环",
"status": "PASS",
"startedAt": "2026-09-05T15:48:46.342Z",
"baseURL": "http://127.0.0.1:6180",
"method": "真实 Auth / Gateway / Tran API;新建隔离学生与开发测试任务;不连接设备、视觉推理或外部通知。",
"references": {
"PHYSICAL": {
"projectId": "163",
"versionId": "215"
},
"CONFRONTATION": {
"projectId": "164",
"versionId": "216"
}
},
"checks": [
{
"title": "开始命令重放不会重复激活或递增次数",
"status": "PASS",
"details": {
"runId": "44",
"version": 2,
"attemptCount": 1
}
},
{
"title": "实装任务固定发布版本、分配学员并开始",
"status": "PASS",
"details": {
"assignmentId": "50",
"run": {
"id": "44",
"assignmentId": "50",
"status": "IN_PROGRESS",
"version": 2,
"progressPercent": 0,
"currentStepCode": "PHYSICAL-S01",
"score": null,
"passed": null
},
"content": {
"projectId": "163",
"versionId": "215"
},
"rules": [
{
"stepCode": "PHYSICAL-S01",
"source": "MANUAL",
"eventType": "step.physical-s01.confirmed",
"progressPercent": 33
},
{
"stepCode": "PHYSICAL-S02",
"source": "MANUAL",
"eventType": "step.physical-s02.confirmed",
"progressPercent": 67
},
{
"stepCode": "PHYSICAL-S03",
"source": "MANUAL",
"eventType": "step.physical-s03.confirmed",
"progressPercent": 100
}
]
}
},
{
"title": "实装拒绝普通进度接口、抢跑、提前提交及错误事件身份",
"status": "PASS",
"details": {
"runId": "44",
"forbiddenProgress": {
"status": 403,
"message": "实装运行只能由设备、视觉或人工确认事件推进"
},
"prematureSubmit": {
"status": 409,
"message": "训练步骤尚未全部完成,不能提交"
},
"skipped": {
"status": 409,
"message": "物理事件必须匹配当前待完成步骤,不能跳步或回退"
},
"untrustedDevice": {
"status": 403,
"message": "无权执行此操作"
},
"managerManual": {
"status": 403,
"message": "当前学员不是该运行成员"
},
"progressUnchanged": 0
}
},
{
"title": "实装不匹配事件失败,必须重试后才可继续",
"status": "PASS",
"details": {
"runId": "44",
"outcome": "UNMATCHED",
"beforeRetry": {
"status": 409,
"message": "实装步骤失败后必须先重试,完成后不能再次推进"
},
"facts": [
{
"stepCode": "PHYSICAL-S01",
"status": "IN_PROGRESS",
"targetProgressPercent": 33,
"attemptCount": 2,
"failureCount": 1,
"evidenceSourceCode": "COMMAND"
},
{
"stepCode": "PHYSICAL-S02",
"status": "PENDING",
"targetProgressPercent": 67,
"attemptCount": 0,
"failureCount": 0,
"evidenceSourceCode": "NONE"
},
{
"stepCode": "PHYSICAL-S03",
"status": "PENDING",
"targetProgressPercent": 100,
"attemptCount": 0,
"failureCount": 0,
"evidenceSourceCode": "NONE"
}
]
}
},
{
"title": "实装逐步人工确认、事件幂等与载荷冲突",
"status": "PASS",
"details": {
"runId": "44",
"progression": [
{
"stepCode": "PHYSICAL-S01",
"eventId": "MANUAL-FF103EF3-B498-4EAC-8F06-42DE46CC9CE4",
"progress": 33,
"replayVersion": 5,
"alteredEventStatus": 409
},
{
"stepCode": "PHYSICAL-S02",
"eventId": "MANUAL-9D8A36B7-C161-4736-A71E-D1700E55216B",
"progress": 67,
"replayVersion": 6,
"alteredEventStatus": 409
},
{
"stepCode": "PHYSICAL-S03",
"eventId": "MANUAL-1D1ADE8F-D32B-434B-A7D8-A2571E502137",
"progress": 100,
"replayVersion": 7,
"alteredEventStatus": 409
}
],
"facts": [
{
"stepCode": "PHYSICAL-S01",
"status": "COMPLETED",
"targetProgressPercent": 33,
"attemptCount": 2,
"failureCount": 1,
"evidenceSourceCode": "MANUAL"
},
{
"stepCode": "PHYSICAL-S02",
"status": "COMPLETED",
"targetProgressPercent": 67,
"attemptCount": 1,
"failureCount": 0,
"evidenceSourceCode": "MANUAL"
},
{
"stepCode": "PHYSICAL-S03",
"status": "COMPLETED",
"targetProgressPercent": 100,
"attemptCount": 1,
"failureCount": 0,
"evidenceSourceCode": "MANUAL"
}
]
}
},
{
"title": "PHYSICAL 提交、教员评定与结果回读",
"status": "PASS",
"details": {
"run": {
"id": "44",
"assignmentId": "50",
"status": "REVIEWED",
"version": 9,
"progressPercent": 100,
"currentStepCode": "PHYSICAL-S03",
"score": 100,
"passed": true
},
"submitReplay": true,
"reviewReplay": true,
"facts": [
{
"stepCode": "PHYSICAL-S01",
"status": "COMPLETED",
"targetProgressPercent": 33,
"attemptCount": 2,
"failureCount": 1,
"evidenceSourceCode": "MANUAL"
},
{
"stepCode": "PHYSICAL-S02",
"status": "COMPLETED",
"targetProgressPercent": 67,
"attemptCount": 1,
"failureCount": 0,
"evidenceSourceCode": "MANUAL"
},
{
"stepCode": "PHYSICAL-S03",
"status": "COMPLETED",
"targetProgressPercent": 100,
"attemptCount": 1,
"failureCount": 0,
"evidenceSourceCode": "MANUAL"
}
]
}
},
{
"title": "对抗红蓝两队各两人,按队伍共享且运行互相独立",
"status": "PASS",
"details": {
"assignmentId": "51",
"content": {
"projectId": "164",
"versionId": "216"
},
"configuration": {
"teamSize": 2,
"roundDurationMinutes": 7,
"submitPositions": [
"COMMANDER"
]
},
"runs": [
{
"id": "46",
"assignmentId": "51",
"status": "ACCEPTED",
"version": 1,
"progressPercent": 0,
"currentStepCode": "",
"score": null,
"passed": null
},
{
"id": "45",
"assignmentId": "51",
"status": "ACCEPTED",
"version": 1,
"progressPercent": 0,
"currentStepCode": "",
"score": null,
"passed": null
}
]
}
},
{
"title": "对抗学员不能读取另一队运行明细",
"status": "PASS",
"details": {
"requestingTeam": "RED",
"otherRunId": "46",
"response": {
"status": 403,
"message": "无权查看该训练运行"
}
}
},
{
"title": "开始命令重放不会重复激活或递增次数",
"status": "PASS",
"details": {
"runId": "45",
"version": 2,
"attemptCount": 1
}
},
{
"title": "RED 队岗位越权、跳步和提前提交均拒绝",
"status": "PASS",
"details": {
"runId": "45",
"wrongPosition": {
"status": 403,
"message": "当前岗位不能推进共享训练进度"
},
"skipped": {
"status": 400,
"message": "必须按发布顺序完成当前步骤,不能跳步或回退"
},
"earlySubmit": {
"status": 409,
"message": "训练步骤尚未全部完成,不能提交"
},
"deadlineAt": 1788623936,
"serverNow": 1788623517
}
},
{
"title": "RED 队授权动作逐步推进、重放幂等、提交负责人限制",
"status": "PASS",
"details": {
"runId": "45",
"progression": [
{
"stepCode": "CONFRONTATION-S01",
"progress": 50,
"replayVersion": 3,
"changedCommandStatus": 409
},
{
"stepCode": "CONFRONTATION-S02",
"progress": 100,
"replayVersion": 4,
"changedCommandStatus": 409
}
],
"wrongSubmitPosition": {
"status": 403,
"message": "共享训练仅允许任务声明的负责人岗位提交结果"
}
}
},
{
"title": "CONFRONTATION 提交、教员评定与结果回读",
"status": "PASS",
"details": {
"run": {
"id": "45",
"assignmentId": "51",
"status": "REVIEWED",
"version": 6,
"progressPercent": 100,
"currentStepCode": "CONFRONTATION-S02",
"score": 100,
"passed": true
},
"submitReplay": true,
"reviewReplay": true,
"facts": [
{
"stepCode": "CONFRONTATION-S01",
"status": "COMPLETED",
"targetProgressPercent": 50,
"attemptCount": 1,
"failureCount": 0,
"evidenceSourceCode": "COMMAND"
},
{
"stepCode": "CONFRONTATION-S02",
"status": "COMPLETED",
"targetProgressPercent": 100,
"attemptCount": 1,
"failureCount": 0,
"evidenceSourceCode": "COMMAND"
}
]
}
},
{
"title": "红队完成不会推进蓝队进度",
"status": "PASS",
"details": {
"redRunId": "45",
"blueRun": {
"id": "46",
"assignmentId": "51",
"status": "ACCEPTED",
"version": 1,
"progressPercent": 0,
"currentStepCode": "",
"score": null,
"passed": null
}
}
},
{
"title": "开始命令重放不会重复激活或递增次数",
"status": "PASS",
"details": {
"runId": "46",
"version": 2,
"attemptCount": 1
}
},
{
"title": "BLUE 队岗位越权、跳步和提前提交均拒绝",
"status": "PASS",
"details": {
"runId": "46",
"wrongPosition": {
"status": 403,
"message": "当前岗位不能推进共享训练进度"
},
"skipped": {
"status": 400,
"message": "必须按发布顺序完成当前步骤,不能跳步或回退"
},
"earlySubmit": {
"status": 409,
"message": "训练步骤尚未全部完成,不能提交"
},
"deadlineAt": 1788623942,
"serverNow": 1788623523
}
},
{
"title": "BLUE 队授权动作逐步推进、重放幂等、提交负责人限制",
"status": "PASS",
"details": {
"runId": "46",
"progression": [
{
"stepCode": "CONFRONTATION-S01",
"progress": 50,
"replayVersion": 3,
"changedCommandStatus": 409
},
{
"stepCode": "CONFRONTATION-S02",
"progress": 100,
"replayVersion": 4,
"changedCommandStatus": 409
}
],
"wrongSubmitPosition": {
"status": 403,
"message": "共享训练仅允许任务声明的负责人岗位提交结果"
}
}
},
{
"title": "CONFRONTATION 提交、教员评定与结果回读",
"status": "PASS",
"details": {
"run": {
"id": "46",
"assignmentId": "51",
"status": "REVIEWED",
"version": 6,
"progressPercent": 100,
"currentStepCode": "CONFRONTATION-S02",
"score": 100,
"passed": true
},
"submitReplay": true,
"reviewReplay": true,
"facts": [
{
"stepCode": "CONFRONTATION-S01",
"status": "COMPLETED",
"targetProgressPercent": 50,
"attemptCount": 1,
"failureCount": 0,
"evidenceSourceCode": "COMMAND"
},
{
"stepCode": "CONFRONTATION-S02",
"status": "COMPLETED",
"targetProgressPercent": 100,
"attemptCount": 1,
"failureCount": 0,
"evidenceSourceCode": "COMMAND"
}
]
}
},
{
"title": "正式任务快照固定训练、场景与模型发布版本",
"status": "PASS",
"details": {
"snapshots": [
{
"assignmentId": "50",
"channel": "PHYSICAL",
"content": {
"projectId": "163",
"versionId": "215"
},
"frozenScene": {
"projectId": "159",
"versionId": "209",
"models": [
{
"projectId": "156",
"versionId": "204",
"assetCode": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK"
}
]
}
},
{
"assignmentId": "51",
"channel": "CONFRONTATION",
"content": {
"projectId": "164",
"versionId": "216"
},
"frozenScene": {
"projectId": "160",
"versionId": "210",
"models": [
{
"projectId": "157",
"versionId": "201",
"assetCode": "MODEL_MTO6V5W6_09-FOX"
}
]
}
}
]
}
}
],
"assignments": [
{
"id": "50",
"code": "UTE2E-MODES-MTOK5BBA-PHYSICAL",
"channel": "PHYSICAL",
"contentProjectId": "163",
"contentVersionId": "215",
"status": "PUBLISHED",
"version": 1,
"frozenScene": {
"projectId": "159",
"versionId": "209",
"models": [
{
"projectId": "156",
"versionId": "204",
"assetCode": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK"
}
]
}
},
{
"id": "51",
"code": "UTE2E-MODES-MTOK5BBA-CONFRONTATION",
"channel": "CONFRONTATION",
"contentProjectId": "164",
"contentVersionId": "216",
"status": "PUBLISHED",
"version": 1,
"frozenScene": {
"projectId": "160",
"versionId": "210",
"models": [
{
"projectId": "157",
"versionId": "201",
"assetCode": "MODEL_MTO6V5W6_09-FOX"
}
]
}
}
],
"runs": [
{
"id": "44",
"assignmentId": "50",
"status": "REVIEWED",
"version": 9,
"progressPercent": 100,
"currentStepCode": "PHYSICAL-S03",
"score": 100,
"passed": true,
"channel": "PHYSICAL",
"team": "NEUTRAL",
"stepFacts": [
{
"stepCode": "PHYSICAL-S01",
"status": "COMPLETED",
"targetProgressPercent": 33,
"attemptCount": 2,
"failureCount": 1,
"evidenceSourceCode": "MANUAL"
},
{
"stepCode": "PHYSICAL-S02",
"status": "COMPLETED",
"targetProgressPercent": 67,
"attemptCount": 1,
"failureCount": 0,
"evidenceSourceCode": "MANUAL"
},
{
"stepCode": "PHYSICAL-S03",
"status": "COMPLETED",
"targetProgressPercent": 100,
"attemptCount": 1,
"failureCount": 0,
"evidenceSourceCode": "MANUAL"
}
]
},
{
"id": "45",
"assignmentId": "51",
"status": "REVIEWED",
"version": 6,
"progressPercent": 100,
"currentStepCode": "CONFRONTATION-S02",
"score": 100,
"passed": true,
"channel": "CONFRONTATION",
"team": "RED",
"stepFacts": [
{
"stepCode": "CONFRONTATION-S01",
"status": "COMPLETED",
"targetProgressPercent": 50,
"attemptCount": 1,
"failureCount": 0,
"evidenceSourceCode": "COMMAND"
},
{
"stepCode": "CONFRONTATION-S02",
"status": "COMPLETED",
"targetProgressPercent": 100,
"attemptCount": 1,
"failureCount": 0,
"evidenceSourceCode": "COMMAND"
}
]
},
{
"id": "46",
"assignmentId": "51",
"status": "REVIEWED",
"version": 6,
"progressPercent": 100,
"currentStepCode": "CONFRONTATION-S02",
"score": 100,
"passed": true,
"channel": "CONFRONTATION",
"team": "BLUE",
"stepFacts": [
{
"stepCode": "CONFRONTATION-S01",
"status": "COMPLETED",
"targetProgressPercent": 50,
"attemptCount": 1,
"failureCount": 0,
"evidenceSourceCode": "COMMAND"
},
{
"stepCode": "CONFRONTATION-S02",
"status": "COMPLETED",
"targetProgressPercent": 100,
"attemptCount": 1,
"failureCount": 0,
"evidenceSourceCode": "COMMAND"
}
]
}
],
"actors": [
{
"userId": "95",
"team": "RED",
"position": "COMMANDER",
"departmentId": "5"
},
{
"userId": "96",
"team": "RED",
"position": "OPERATOR",
"departmentId": "5"
},
{
"userId": "97",
"team": "BLUE",
"position": "COMMANDER",
"departmentId": "5"
},
{
"userId": "98",
"team": "BLUE",
"position": "OPERATOR",
"departmentId": "5"
}
],
"requests": [
{
"method": "POST",
"path": "/api/tran/v1/teaching/assignments",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/assignments/50/publish",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/assignments/50/accept",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/start",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/start",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/44/steps",
"status": 200
},
{
"method": "PUT",
"path": "/api/tran/v1/teaching/runs/44/progress",
"status": 403
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/submit",
"status": 409
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/physical-events",
"status": 409
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/physical-events",
"status": 403
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/physical-events",
"status": 403
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/44",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/physical-events",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/44/steps",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/44",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/physical-events",
"status": 409
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/start",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/44/steps",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/physical-events",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/44",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/physical-events",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/44",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/physical-events",
"status": 409
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/physical-events",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/44",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/physical-events",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/44",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/physical-events",
"status": 409
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/physical-events",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/44",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/physical-events",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/44",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/physical-events",
"status": 409
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/44/steps",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/submit",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/submit",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/review",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/44/review",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/44/steps",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/assignments",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/assignments/51/publish",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/assignments/51/accept",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/assignments/51/accept",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/assignments/51/accept",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/assignments/51/accept",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs?assignmentId=51&size=100",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/46",
"status": 403
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/45/start",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/45/start",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/45/steps",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/45/execution",
"status": 200
},
{
"method": "PUT",
"path": "/api/tran/v1/teaching/runs/45/progress",
"status": 403
},
{
"method": "PUT",
"path": "/api/tran/v1/teaching/runs/45/progress",
"status": 400
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/45/submit",
"status": 409
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/45",
"status": 200
},
{
"method": "PUT",
"path": "/api/tran/v1/teaching/runs/45/progress",
"status": 200
},
{
"method": "PUT",
"path": "/api/tran/v1/teaching/runs/45/progress",
"status": 200
},
{
"method": "PUT",
"path": "/api/tran/v1/teaching/runs/45/progress",
"status": 409
},
{
"method": "PUT",
"path": "/api/tran/v1/teaching/runs/45/progress",
"status": 200
},
{
"method": "PUT",
"path": "/api/tran/v1/teaching/runs/45/progress",
"status": 200
},
{
"method": "PUT",
"path": "/api/tran/v1/teaching/runs/45/progress",
"status": 409
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/45/submit",
"status": 403
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/45/submit",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/45/submit",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/45/review",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/45/review",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/45/steps",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/46",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/46/start",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/46/start",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/46/steps",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/46/execution",
"status": 200
},
{
"method": "PUT",
"path": "/api/tran/v1/teaching/runs/46/progress",
"status": 403
},
{
"method": "PUT",
"path": "/api/tran/v1/teaching/runs/46/progress",
"status": 400
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/46/submit",
"status": 409
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/46",
"status": 200
},
{
"method": "PUT",
"path": "/api/tran/v1/teaching/runs/46/progress",
"status": 200
},
{
"method": "PUT",
"path": "/api/tran/v1/teaching/runs/46/progress",
"status": 200
},
{
"method": "PUT",
"path": "/api/tran/v1/teaching/runs/46/progress",
"status": 409
},
{
"method": "PUT",
"path": "/api/tran/v1/teaching/runs/46/progress",
"status": 200
},
{
"method": "PUT",
"path": "/api/tran/v1/teaching/runs/46/progress",
"status": 200
},
{
"method": "PUT",
"path": "/api/tran/v1/teaching/runs/46/progress",
"status": 409
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/46/submit",
"status": 403
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/46/submit",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/46/submit",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/46/review",
"status": 200
},
{
"method": "POST",
"path": "/api/tran/v1/teaching/runs/46/review",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/runs/46/steps",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/assignments/50",
"status": 200
},
{
"method": "GET",
"path": "/api/tran/v1/teaching/assignments/51",
"status": 200
}
],
"limitations": [
"实装事件均为本次自动化提交的 MANUAL 人工确认或明确的权限拒绝测试,不代表真实设备、PLC、摄像机或视觉模型联调。",
"教学运行结果来自正式 API;默认实装离线回放和默认对抗本地工作台的显示另行记录,不混同为服务端运行闭环。",
"对抗按四名隔离学员的独立会话依次操作,检查服务端截止时间已生效;未等待整局自然超时,也不代表多人同时操作的压力或网络同步测试。",
"测试账号使用本次随机密码,密码与会话仅在运行内存中;报告只保留用户 ID、队伍和岗位以便追溯。"
],
"finishedAt": "2026-09-05T15:58:56.293Z",
"retainedData": {
"assignments": [
"50",
"51"
],
"runs": [
"44",
"45",
"46"
],
"users": [
"95",
"96",
"97",
"98"
],
"note": "仅新建本次开发测试数据,未修改或删除既有账号、任务与运行。"
}
}
报告生成:2026/9/6 00:01:37(Asia/Shanghai)。