diff --git a/.gitignore b/.gitignore index 435bd7a..a646dba 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ node_modules/ .env .env.* !.env.example +reports/**/build.log artifacts/html-report/ artifacts/test-results/ artifacts/trace-inspect-*/ diff --git a/reports/login-role-layout-20260905/login-1920.png b/reports/login-role-layout-20260905/login-1920.png new file mode 100644 index 0000000..c9a1e87 Binary files /dev/null and b/reports/login-role-layout-20260905/login-1920.png differ diff --git a/reports/login-role-layout-20260905/login-card.png b/reports/login-role-layout-20260905/login-card.png new file mode 100644 index 0000000..764dcdf Binary files /dev/null and b/reports/login-role-layout-20260905/login-card.png differ diff --git a/reports/login-role-layout-20260905/login-mobile.png b/reports/login-role-layout-20260905/login-mobile.png new file mode 100644 index 0000000..fb88272 Binary files /dev/null and b/reports/login-role-layout-20260905/login-mobile.png differ diff --git a/reports/login-role-layout-20260905/verification.json b/reports/login-role-layout-20260905/verification.json new file mode 100644 index 0000000..7028c93 --- /dev/null +++ b/reports/login-role-layout-20260905/verification.json @@ -0,0 +1,71 @@ +{ + "time": "2026-09-05T08:14:53.190Z", + "results": [ + { + "viewport": 1920, + "columns": "124.656px 124.672px 124.656px", + "container": 388, + "roles": [ + { + "role": "teacher", + "width": 124.65625, + "text": "教员" + }, + { + "role": "student", + "width": 124.671875, + "text": "学员" + }, + { + "role": "admin", + "width": 124.65625, + "text": "系统管理员" + } + ] + }, + { + "viewport": 1440, + "columns": "124.656px 124.672px 124.656px", + "container": 388, + "roles": [ + { + "role": "teacher", + "width": 124.65625, + "text": "教员" + }, + { + "role": "student", + "width": 124.671875, + "text": "学员" + }, + { + "role": "admin", + "width": 124.65625, + "text": "系统管理员" + } + ] + }, + { + "viewport": 390, + "columns": "102px 102px 102px", + "container": 320, + "roles": [ + { + "role": "teacher", + "width": 102, + "text": "教员" + }, + { + "role": "student", + "width": 102, + "text": "学员" + }, + { + "role": "admin", + "width": 102, + "text": "系统管理员" + } + ] + } + ] +} \ No newline at end of file diff --git a/reports/model-cover-20260905/evidence.json b/reports/model-cover-20260905/evidence.json new file mode 100644 index 0000000..5a3c03e --- /dev/null +++ b/reports/model-cover-20260905/evidence.json @@ -0,0 +1,284 @@ +{ + "date": "2026-09-05", + "baseURL": "http://127.0.0.1:6180", + "browser": "Microsoft Edge", + "role": "教员", + "evidence": [ + { + "title": "首次手动保存卡车:截取当前场景并绑定JPEG封面", + "status": "PASS", + "details": { + "id": "156", + "name": "实测模型-牛奶卡车-已验证-20260905", + "coverUri": "fsvc://unreal-tran/image/2026/09/05/4e12ee526680085650c48934bc0305e1.jpg", + "versionId": "203", + "projectVersion": 13, + "coverAssetId": "2040", + "sha256": "15caa821e90a70d5b0f8ba1554c0d0d6db332a9b5e53b0d5e94de24d7663533e", + "bytes": 17889, + "width": 640, + "height": 346, + "image": "screenshots/01-truck-cover.jpg", + "cache": "no-cache, private" + }, + "helpersRestored": true, + "screenshot": "screenshots/01-truck-cover-editor.png", + "coverImage": "screenshots/01-truck-cover.jpg" + }, + { + "title": "更换卡车视角再次保存:替换当前封面且辅助控件恢复", + "status": "PASS", + "details": { + "id": "156", + "name": "实测模型-牛奶卡车-已验证-20260905", + "coverUri": "fsvc://unreal-tran/image/2026/09/05/67b2a5d15f9c1fc47a0a760f28fd2e2e.jpg", + "versionId": "204", + "projectVersion": 18, + "coverAssetId": "2055", + "sha256": "7b7cc4cc75a3a355f26e2ff15ae1d26b5964ad7b370061691a94ce5f6f4b9158", + "bytes": 17821, + "width": 640, + "height": 346, + "image": "screenshots/02-truck-new-view.jpg", + "cache": "no-cache, private" + }, + "helpersRestored": true, + "screenshot": "screenshots/02-truck-new-view-editor.png", + "coverImage": "screenshots/02-truck-new-view.jpg" + }, + { + "title": "更换相机视角更新封面,已发布历史版本保留旧封面", + "status": "PASS", + "details": { + "oldVersionId": "203", + "newVersionId": "204", + "oldSha256": "15caa821e90a70d5b0f8ba1554c0d0d6db332a9b5e53b0d5e94de24d7663533e", + "newSha256": "7b7cc4cc75a3a355f26e2ff15ae1d26b5964ad7b370061691a94ce5f6f4b9158" + }, + "coverImage": "screenshots/02-truck-new-view.jpg" + }, + { + "title": "手动保存狐狸:生成与卡车不同的真实模型封面", + "status": "PASS", + "details": { + "id": "157", + "name": "实测模型-狐狸动画-已验证-20260905", + "coverUri": "fsvc://unreal-tran/image/2026/09/05/3d78768edb7ce9b4a89a75c4d68de597.jpg", + "versionId": "202", + "projectVersion": 12, + "coverAssetId": "2058", + "sha256": "6ace0cf199626a3e8ecd4b360d62c0a6ec9b39309293554765dca8128a2ec5e9", + "bytes": 13163, + "width": 640, + "height": 346, + "image": "screenshots/03-fox-cover.jpg", + "cache": "no-cache, private" + }, + "helpersRestored": true, + "screenshot": "screenshots/03-fox-cover-editor.png", + "coverImage": "screenshots/03-fox-cover.jpg" + }, + { + "title": "注入封面上传503:模型位置保存成功,旧封面保留并提示", + "status": "PASS", + "details": { + "httpStatus": 503, + "contentSaveStatus": 200, + "originalX": 0.25, + "savedX": 0.35, + "coverUnchanged": true + }, + "screenshot": "screenshots/04-upload-failure-content-saved.png" + }, + { + "title": "实际自动保存周期保存位置变更,不再次上传封面", + "status": "PASS", + "details": { + "elapsedMs": 16159, + "coverUploads": 0, + "savedX": 0.45, + "coverUnchanged": true + }, + "screenshot": "screenshots/05-auto-save-no-cover-upload.png" + }, + { + "title": "解除故障并恢复原模型位置:封面再次更新成功", + "status": "PASS", + "details": { + "id": "157", + "name": "实测模型-狐狸动画-已验证-20260905", + "coverUri": "fsvc://unreal-tran/image/2026/09/05/c09a49efd4423dcf8ccbc46b46d1e209.jpg", + "versionId": "202", + "projectVersion": 15, + "coverAssetId": "2067", + "sha256": "6ace0cf199626a3e8ecd4b360d62c0a6ec9b39309293554765dca8128a2ec5e9", + "bytes": 13163, + "width": 640, + "height": 346, + "image": "screenshots/06-fox-restored-cover.jpg", + "cache": "no-cache, private" + }, + "helpersRestored": true, + "screenshot": "screenshots/06-fox-restored-cover-editor.png", + "coverImage": "screenshots/06-fox-restored-cover.jpg" + }, + { + "title": "列表显示真实封面;读取失败回退后,同条件搜索可以重试恢复", + "status": "PASS", + "details": { + "failedReads": 1, + "restoredImages": 2, + "sort": "CREATED_DESC" + }, + "screenshot": "screenshots/07-real-model-covers-list.png" + }, + { + "title": "离开缓存列表后取消封面请求并释放Blob URL", + "status": "PASS", + "details": { + "releasedUrls": 2 + } + }, + { + "title": "首次导入GLB自动生成封面,模型文件与图片均完成受控绑定", + "status": "PASS", + "details": { + "id": "158", + "source": "01-Box.glb", + "uploads": [ + { + "status": 200, + "type": "MODEL_FILE", + "code": "MODEL_MTO82QGT_01-BOX" + }, + { + "status": 200, + "type": "IMAGE", + "code": "MODEL_COVER" + } + ], + "sha256": "6e99933505dfeb91a14d16ef1ddf53df2ea022add1b866de835c08403685b7b6", + "bytes": 11446, + "width": 640, + "height": 346, + "image": "screenshots/08-import-box-cover.jpg", + "cache": "no-cache, private" + }, + "screenshot": "screenshots/08-import-box-editor.png", + "coverImage": "screenshots/08-import-box-cover.jpg" + }, + { + "title": "清理首次导入临时模型", + "status": "PASS", + "details": { + "id": "158", + "status": "业务软删除", + "readAfterDelete": 404 + } + }, + { + "title": "封面读取边界:未登录401、无封面404、图片Range正确", + "status": "PASS", + "details": { + "anonymous": 401, + "missing": 404, + "range": 206, + "rangeBytes": 32 + } + }, + { + "title": "最终两条保留模型显示独立封面,创建时间倒序保持", + "status": "PASS", + "screenshot": "screenshots/09-final-two-covers.png" + }, + { + "title": "全新浏览器会话显示两张持久化封面,重开模型不自动上传图片", + "status": "PASS", + "details": { + "projects": [ + { + "id": "156", + "status": "PUBLISHED", + "versionId": "204" + }, + { + "id": "157", + "status": "DRAFT", + "versionId": "202" + } + ], + "unexpectedUploads": 0 + }, + "screenshot": "screenshots/10-fresh-session-covers.png" + } + ], + "projects": [ + { + "id": "156", + "name": "实测模型-牛奶卡车-已验证-20260905", + "originalStatus": "PUBLISHED", + "originalCover": "", + "originalVersionId": "200", + "cover": { + "id": "156", + "name": "实测模型-牛奶卡车-已验证-20260905", + "coverUri": "fsvc://unreal-tran/image/2026/09/05/67b2a5d15f9c1fc47a0a760f28fd2e2e.jpg", + "versionId": "204", + "projectVersion": 18, + "coverAssetId": "2055", + "sha256": "7b7cc4cc75a3a355f26e2ff15ae1d26b5964ad7b370061691a94ce5f6f4b9158", + "bytes": 17821, + "width": 640, + "height": 346, + "image": "screenshots/02-truck-new-view.jpg", + "cache": "no-cache, private" + }, + "finalStatus": "PUBLISHED", + "finalVersionId": "204", + "retained": true + }, + { + "id": "157", + "name": "实测模型-狐狸动画-已验证-20260905", + "originalStatus": "DRAFT", + "originalCover": "", + "originalVersionId": "202", + "cover": { + "id": "157", + "name": "实测模型-狐狸动画-已验证-20260905", + "coverUri": "fsvc://unreal-tran/image/2026/09/05/c09a49efd4423dcf8ccbc46b46d1e209.jpg", + "versionId": "202", + "projectVersion": 15, + "coverAssetId": "2067", + "sha256": "6ace0cf199626a3e8ecd4b360d62c0a6ec9b39309293554765dca8128a2ec5e9", + "bytes": 13163, + "width": 640, + "height": 346, + "image": "screenshots/06-fox-restored-cover.jpg", + "cache": "no-cache, private" + }, + "finalStatus": "DRAFT", + "finalVersionId": "202", + "retained": true + } + ], + "issues": [], + "commands": [ + { + "command": "pnpm run build", + "status": "PASS", + "details": "最终web类型检查、Vite构建、10个生成包payload哈希与API桥接/凭据门禁通过;现有Three资源URL与chunk体积警告未阻断构建。" + }, + { + "command": "mvn -B -ntp -pl ut_tran -Dtest=ContentProjectServiceTest,ContentAssetServiceTest,ContentControllerRangeTest,ContentAuthorizerTest test", + "status": "PASS", + "details": "Java17,93项通过。" + }, + { + "command": "node --test --test-reporter=spec tools/model-cover-capture.test.mjs tools/model-cover-api.test.mjs", + "status": "PASS", + "details": "截图12项+封面事务8项,20/20通过;既有模型API与导入失败保护回归也通过。" + } + ], + "retainedData": "保留156卡车、157狐狸及新封面;卡车恢复已发布,狐狸保留原草稿状态。故障测试位置改动已恢复。158首次导入临时工程已通过业务接口软删除。历史发布版本及封面保留。" +} \ No newline at end of file diff --git a/reports/model-cover-20260905/index.html b/reports/model-cover-20260905/index.html new file mode 100644 index 0000000..5c35bc5 --- /dev/null +++ b/reports/model-cover-20260905/index.html @@ -0,0 +1,200 @@ + + +模型截图封面验证报告 · 2026-09-05 +
+
MODEL COVER · IMPLEMENTED

模型截图封面验证报告

截图封面功能已实施并完成下列真实浏览器验证:视口截图作为受控图片资产与工程关联保存,列表读取真实封面,模型列表按创建时间倒序显示。

2026-09-05 · http://127.0.0.1:6180 · Microsoft Edge · 教员

Markdown 报告
+
14 / 14证据项通过
0非 PASS 证据项
15图片文件已校验
+

最终模型封面

实测模型-牛奶卡车-已验证-20260905

项目 156 最终封面
项目 156 最终封面 · 点击查看原图
项目 / 最终状态
156 / PUBLISHED
工程版本 / 封面资产
204 / 2055
图片规格
640 × 346 · 17821 字节
封面持久化证据
{
+  "id": "156",
+  "name": "实测模型-牛奶卡车-已验证-20260905",
+  "coverUri": "fsvc://unreal-tran/image/2026/09/05/67b2a5d15f9c1fc47a0a760f28fd2e2e.jpg",
+  "versionId": "204",
+  "projectVersion": 18,
+  "coverAssetId": "2055",
+  "sha256": "7b7cc4cc75a3a355f26e2ff15ae1d26b5964ad7b370061691a94ce5f6f4b9158",
+  "bytes": 17821,
+  "width": 640,
+  "height": 346,
+  "image": "screenshots/02-truck-new-view.jpg",
+  "cache": "no-cache, private"
+}

实测模型-狐狸动画-已验证-20260905

项目 157 最终封面
项目 157 最终封面 · 点击查看原图
项目 / 最终状态
157 / DRAFT
工程版本 / 封面资产
202 / 2067
图片规格
640 × 346 · 13163 字节
封面持久化证据
{
+  "id": "157",
+  "name": "实测模型-狐狸动画-已验证-20260905",
+  "coverUri": "fsvc://unreal-tran/image/2026/09/05/c09a49efd4423dcf8ccbc46b46d1e209.jpg",
+  "versionId": "202",
+  "projectVersion": 15,
+  "coverAssetId": "2067",
+  "sha256": "6ace0cf199626a3e8ecd4b360d62c0a6ec9b39309293554765dca8128a2ec5e9",
+  "bytes": 13163,
+  "width": 640,
+  "height": 346,
+  "image": "screenshots/06-fox-restored-cover.jpg",
+  "cache": "no-cache, private"
+}
+

最终列表现场

两条保留模型的真实封面与创建时间倒序列表
两条保留模型的真实封面与创建时间倒序列表 · 点击查看原图
+

验证记录

通过数只统计 status 为 PASS 的记录;故障注入中预期的 503、401 或 404 不等于用例失败。

1. 首次手动保存卡车:截取当前场景并绑定JPEG封面

PASS
检查细节
{
+  "details": {
+    "id": "156",
+    "name": "实测模型-牛奶卡车-已验证-20260905",
+    "coverUri": "fsvc://unreal-tran/image/2026/09/05/4e12ee526680085650c48934bc0305e1.jpg",
+    "versionId": "203",
+    "projectVersion": 13,
+    "coverAssetId": "2040",
+    "sha256": "15caa821e90a70d5b0f8ba1554c0d0d6db332a9b5e53b0d5e94de24d7663533e",
+    "bytes": 17889,
+    "width": 640,
+    "height": 346,
+    "image": "screenshots/01-truck-cover.jpg",
+    "cache": "no-cache, private"
+  },
+  "helpersRestored": true
+}
浏览器现场
浏览器现场 · 点击查看原图
实际生成封面
实际生成封面 · 点击查看原图

2. 更换卡车视角再次保存:替换当前封面且辅助控件恢复

PASS
检查细节
{
+  "details": {
+    "id": "156",
+    "name": "实测模型-牛奶卡车-已验证-20260905",
+    "coverUri": "fsvc://unreal-tran/image/2026/09/05/67b2a5d15f9c1fc47a0a760f28fd2e2e.jpg",
+    "versionId": "204",
+    "projectVersion": 18,
+    "coverAssetId": "2055",
+    "sha256": "7b7cc4cc75a3a355f26e2ff15ae1d26b5964ad7b370061691a94ce5f6f4b9158",
+    "bytes": 17821,
+    "width": 640,
+    "height": 346,
+    "image": "screenshots/02-truck-new-view.jpg",
+    "cache": "no-cache, private"
+  },
+  "helpersRestored": true
+}
浏览器现场
浏览器现场 · 点击查看原图
实际生成封面
实际生成封面 · 点击查看原图

3. 更换相机视角更新封面,已发布历史版本保留旧封面

PASS
检查细节
{
+  "details": {
+    "oldVersionId": "203",
+    "newVersionId": "204",
+    "oldSha256": "15caa821e90a70d5b0f8ba1554c0d0d6db332a9b5e53b0d5e94de24d7663533e",
+    "newSha256": "7b7cc4cc75a3a355f26e2ff15ae1d26b5964ad7b370061691a94ce5f6f4b9158"
+  }
+}
实际生成封面
实际生成封面 · 点击查看原图

4. 手动保存狐狸:生成与卡车不同的真实模型封面

PASS
检查细节
{
+  "details": {
+    "id": "157",
+    "name": "实测模型-狐狸动画-已验证-20260905",
+    "coverUri": "fsvc://unreal-tran/image/2026/09/05/3d78768edb7ce9b4a89a75c4d68de597.jpg",
+    "versionId": "202",
+    "projectVersion": 12,
+    "coverAssetId": "2058",
+    "sha256": "6ace0cf199626a3e8ecd4b360d62c0a6ec9b39309293554765dca8128a2ec5e9",
+    "bytes": 13163,
+    "width": 640,
+    "height": 346,
+    "image": "screenshots/03-fox-cover.jpg",
+    "cache": "no-cache, private"
+  },
+  "helpersRestored": true
+}
浏览器现场
浏览器现场 · 点击查看原图
实际生成封面
实际生成封面 · 点击查看原图

5. 注入封面上传503:模型位置保存成功,旧封面保留并提示

PASS
检查细节
{
+  "details": {
+    "httpStatus": 503,
+    "contentSaveStatus": 200,
+    "originalX": 0.25,
+    "savedX": 0.35,
+    "coverUnchanged": true
+  }
+}
浏览器现场
浏览器现场 · 点击查看原图

6. 实际自动保存周期保存位置变更,不再次上传封面

PASS
检查细节
{
+  "details": {
+    "elapsedMs": 16159,
+    "coverUploads": 0,
+    "savedX": 0.45,
+    "coverUnchanged": true
+  }
+}
浏览器现场
浏览器现场 · 点击查看原图

7. 解除故障并恢复原模型位置:封面再次更新成功

PASS
检查细节
{
+  "details": {
+    "id": "157",
+    "name": "实测模型-狐狸动画-已验证-20260905",
+    "coverUri": "fsvc://unreal-tran/image/2026/09/05/c09a49efd4423dcf8ccbc46b46d1e209.jpg",
+    "versionId": "202",
+    "projectVersion": 15,
+    "coverAssetId": "2067",
+    "sha256": "6ace0cf199626a3e8ecd4b360d62c0a6ec9b39309293554765dca8128a2ec5e9",
+    "bytes": 13163,
+    "width": 640,
+    "height": 346,
+    "image": "screenshots/06-fox-restored-cover.jpg",
+    "cache": "no-cache, private"
+  },
+  "helpersRestored": true
+}
浏览器现场
浏览器现场 · 点击查看原图
实际生成封面
实际生成封面 · 点击查看原图

8. 列表显示真实封面;读取失败回退后,同条件搜索可以重试恢复

PASS
检查细节
{
+  "details": {
+    "failedReads": 1,
+    "restoredImages": 2,
+    "sort": "CREATED_DESC"
+  }
+}
浏览器现场
浏览器现场 · 点击查看原图

9. 离开缓存列表后取消封面请求并释放Blob URL

PASS
检查细节
{
+  "details": {
+    "releasedUrls": 2
+  }
+}

10. 首次导入GLB自动生成封面,模型文件与图片均完成受控绑定

PASS
检查细节
{
+  "details": {
+    "id": "158",
+    "source": "01-Box.glb",
+    "uploads": [
+      {
+        "status": 200,
+        "type": "MODEL_FILE",
+        "code": "MODEL_MTO82QGT_01-BOX"
+      },
+      {
+        "status": 200,
+        "type": "IMAGE",
+        "code": "MODEL_COVER"
+      }
+    ],
+    "sha256": "6e99933505dfeb91a14d16ef1ddf53df2ea022add1b866de835c08403685b7b6",
+    "bytes": 11446,
+    "width": 640,
+    "height": 346,
+    "image": "screenshots/08-import-box-cover.jpg",
+    "cache": "no-cache, private"
+  }
+}
浏览器现场
浏览器现场 · 点击查看原图
实际生成封面
实际生成封面 · 点击查看原图

11. 清理首次导入临时模型

PASS
检查细节
{
+  "details": {
+    "id": "158",
+    "status": "业务软删除",
+    "readAfterDelete": 404
+  }
+}

12. 封面读取边界:未登录401、无封面404、图片Range正确

PASS
检查细节
{
+  "details": {
+    "anonymous": 401,
+    "missing": 404,
+    "range": 206,
+    "rangeBytes": 32
+  }
+}

13. 最终两条保留模型显示独立封面,创建时间倒序保持

PASS
浏览器现场
浏览器现场 · 点击查看原图

14. 全新浏览器会话显示两张持久化封面,重开模型不自动上传图片

PASS
检查细节
{
+  "details": {
+    "projects": [
+      {
+        "id": "156",
+        "status": "PUBLISHED",
+        "versionId": "204"
+      },
+      {
+        "id": "157",
+        "status": "DRAFT",
+        "versionId": "202"
+      }
+    ],
+    "unexpectedUploads": 0
+  }
+}
浏览器现场
浏览器现场 · 点击查看原图
+

数据保留与清理

保留156卡车、157狐狸及新封面;卡车恢复已发布,狐狸保留原草稿状态。故障测试位置改动已恢复。158首次导入临时工程已通过业务接口软删除。历史发布版本及封面保留。

项目初始状态最终状态
156 · 实测模型-牛奶卡车-已验证-20260905PUBLISHEDPUBLISHED
157 · 实测模型-狐狸动画-已验证-20260905DRAFTDRAFT

首次导入验证使用的临时项目 158 已通过业务软删除,删除后读取返回 404;报告保留操作证据,不宣称物理文件已删除。

+

问题记录

当前证据未登记未解决问题。

+

实际命令与结果

pnpm run build

{
+  "status": "PASS",
+  "details": "最终web类型检查、Vite构建、10个生成包payload哈希与API桥接/凭据门禁通过;现有Three资源URL与chunk体积警告未阻断构建。"
+}

mvn -B -ntp -pl ut_tran -Dtest=ContentProjectServiceTest,ContentAssetServiceTest,ContentControllerRangeTest,ContentAuthorizerTest test

{
+  "status": "PASS",
+  "details": "Java17,93项通过。"
+}

node --test --test-reporter=spec tools/model-cover-capture.test.mjs tools/model-cover-api.test.mjs

{
+  "status": "PASS",
+  "details": "截图12项+封面事务8项,20/20通过;既有模型API与导入失败保护回归也通过。"
+}
+

当前行为与限制

+ +
\ No newline at end of file diff --git a/reports/model-cover-20260905/report.md b/reports/model-cover-20260905/report.md new file mode 100644 index 0000000..c4e674f --- /dev/null +++ b/reports/model-cover-20260905/report.md @@ -0,0 +1,320 @@ +# 模型截图封面验证报告 + +截图封面功能已实施并完成下列真实浏览器验证:视口截图作为受控图片资产与工程关联保存,列表读取真实封面,模型列表按创建时间倒序显示。 + +2026-09-05 · http://127.0.0.1:6180 · Microsoft Edge · 教员 + +证据通过:**14 / 14**;非 PASS:0;已校验图片:15。 + +## 最终模型封面 + +### 实测模型-牛奶卡车-已验证-20260905 + +项目 156;最终状态:PUBLISHED;工程版本 ID:204;封面资产 ID:2055。 + +[![项目 156 最终封面](screenshots/02-truck-new-view.jpg)](screenshots/02-truck-new-view.jpg) + +### 实测模型-狐狸动画-已验证-20260905 + +项目 157;最终状态:DRAFT;工程版本 ID:202;封面资产 ID:2067。 + +[![项目 157 最终封面](screenshots/06-fox-restored-cover.jpg)](screenshots/06-fox-restored-cover.jpg) + +## 最终列表现场 + +[![最终两条模型封面列表](screenshots/09-final-two-covers.png)](screenshots/09-final-two-covers.png) + +## 验证记录 + +通过统计只认 status 为 PASS;预期故障响应不视为用例失败。 + +| 序号 | 检查项 | 结果 | 图片 | +|---|---|---|---| +| 1 | 首次手动保存卡车:截取当前场景并绑定JPEG封面 | PASS | [图片 1](screenshots/01-truck-cover-editor.png) · [图片 2](screenshots/01-truck-cover.jpg) | +| 2 | 更换卡车视角再次保存:替换当前封面且辅助控件恢复 | PASS | [图片 1](screenshots/02-truck-new-view-editor.png) · [图片 2](screenshots/02-truck-new-view.jpg) | +| 3 | 更换相机视角更新封面,已发布历史版本保留旧封面 | PASS | [图片 1](screenshots/02-truck-new-view.jpg) | +| 4 | 手动保存狐狸:生成与卡车不同的真实模型封面 | PASS | [图片 1](screenshots/03-fox-cover-editor.png) · [图片 2](screenshots/03-fox-cover.jpg) | +| 5 | 注入封面上传503:模型位置保存成功,旧封面保留并提示 | PASS | [图片 1](screenshots/04-upload-failure-content-saved.png) | +| 6 | 实际自动保存周期保存位置变更,不再次上传封面 | PASS | [图片 1](screenshots/05-auto-save-no-cover-upload.png) | +| 7 | 解除故障并恢复原模型位置:封面再次更新成功 | PASS | [图片 1](screenshots/06-fox-restored-cover-editor.png) · [图片 2](screenshots/06-fox-restored-cover.jpg) | +| 8 | 列表显示真实封面;读取失败回退后,同条件搜索可以重试恢复 | PASS | [图片 1](screenshots/07-real-model-covers-list.png) | +| 9 | 离开缓存列表后取消封面请求并释放Blob URL | PASS | — | +| 10 | 首次导入GLB自动生成封面,模型文件与图片均完成受控绑定 | PASS | [图片 1](screenshots/08-import-box-editor.png) · [图片 2](screenshots/08-import-box-cover.jpg) | +| 11 | 清理首次导入临时模型 | PASS | — | +| 12 | 封面读取边界:未登录401、无封面404、图片Range正确 | PASS | — | +| 13 | 最终两条保留模型显示独立封面,创建时间倒序保持 | PASS | [图片 1](screenshots/09-final-two-covers.png) | +| 14 | 全新浏览器会话显示两张持久化封面,重开模型不自动上传图片 | PASS | [图片 1](screenshots/10-fresh-session-covers.png) | + +
首次手动保存卡车:截取当前场景并绑定JPEG封面:检查细节 + +
+{
+  "id": "156",
+  "name": "实测模型-牛奶卡车-已验证-20260905",
+  "coverUri": "fsvc://unreal-tran/image/2026/09/05/4e12ee526680085650c48934bc0305e1.jpg",
+  "versionId": "203",
+  "projectVersion": 13,
+  "coverAssetId": "2040",
+  "sha256": "15caa821e90a70d5b0f8ba1554c0d0d6db332a9b5e53b0d5e94de24d7663533e",
+  "bytes": 17889,
+  "width": 640,
+  "height": 346,
+  "image": "screenshots/01-truck-cover.jpg",
+  "cache": "no-cache, private"
+}
+
+ +
+ +
更换卡车视角再次保存:替换当前封面且辅助控件恢复:检查细节 + +
+{
+  "id": "156",
+  "name": "实测模型-牛奶卡车-已验证-20260905",
+  "coverUri": "fsvc://unreal-tran/image/2026/09/05/67b2a5d15f9c1fc47a0a760f28fd2e2e.jpg",
+  "versionId": "204",
+  "projectVersion": 18,
+  "coverAssetId": "2055",
+  "sha256": "7b7cc4cc75a3a355f26e2ff15ae1d26b5964ad7b370061691a94ce5f6f4b9158",
+  "bytes": 17821,
+  "width": 640,
+  "height": 346,
+  "image": "screenshots/02-truck-new-view.jpg",
+  "cache": "no-cache, private"
+}
+
+ +
+ +
更换相机视角更新封面,已发布历史版本保留旧封面:检查细节 + +
+{
+  "oldVersionId": "203",
+  "newVersionId": "204",
+  "oldSha256": "15caa821e90a70d5b0f8ba1554c0d0d6db332a9b5e53b0d5e94de24d7663533e",
+  "newSha256": "7b7cc4cc75a3a355f26e2ff15ae1d26b5964ad7b370061691a94ce5f6f4b9158"
+}
+
+ +
+ +
手动保存狐狸:生成与卡车不同的真实模型封面:检查细节 + +
+{
+  "id": "157",
+  "name": "实测模型-狐狸动画-已验证-20260905",
+  "coverUri": "fsvc://unreal-tran/image/2026/09/05/3d78768edb7ce9b4a89a75c4d68de597.jpg",
+  "versionId": "202",
+  "projectVersion": 12,
+  "coverAssetId": "2058",
+  "sha256": "6ace0cf199626a3e8ecd4b360d62c0a6ec9b39309293554765dca8128a2ec5e9",
+  "bytes": 13163,
+  "width": 640,
+  "height": 346,
+  "image": "screenshots/03-fox-cover.jpg",
+  "cache": "no-cache, private"
+}
+
+ +
+ +
注入封面上传503:模型位置保存成功,旧封面保留并提示:检查细节 + +
+{
+  "httpStatus": 503,
+  "contentSaveStatus": 200,
+  "originalX": 0.25,
+  "savedX": 0.35,
+  "coverUnchanged": true
+}
+
+ +
+ +
实际自动保存周期保存位置变更,不再次上传封面:检查细节 + +
+{
+  "elapsedMs": 16159,
+  "coverUploads": 0,
+  "savedX": 0.45,
+  "coverUnchanged": true
+}
+
+ +
+ +
解除故障并恢复原模型位置:封面再次更新成功:检查细节 + +
+{
+  "id": "157",
+  "name": "实测模型-狐狸动画-已验证-20260905",
+  "coverUri": "fsvc://unreal-tran/image/2026/09/05/c09a49efd4423dcf8ccbc46b46d1e209.jpg",
+  "versionId": "202",
+  "projectVersion": 15,
+  "coverAssetId": "2067",
+  "sha256": "6ace0cf199626a3e8ecd4b360d62c0a6ec9b39309293554765dca8128a2ec5e9",
+  "bytes": 13163,
+  "width": 640,
+  "height": 346,
+  "image": "screenshots/06-fox-restored-cover.jpg",
+  "cache": "no-cache, private"
+}
+
+ +
+ +
列表显示真实封面;读取失败回退后,同条件搜索可以重试恢复:检查细节 + +
+{
+  "failedReads": 1,
+  "restoredImages": 2,
+  "sort": "CREATED_DESC"
+}
+
+ +
+ +
离开缓存列表后取消封面请求并释放Blob URL:检查细节 + +
+{
+  "releasedUrls": 2
+}
+
+ +
+ +
首次导入GLB自动生成封面,模型文件与图片均完成受控绑定:检查细节 + +
+{
+  "id": "158",
+  "source": "01-Box.glb",
+  "uploads": [
+    {
+      "status": 200,
+      "type": "MODEL_FILE",
+      "code": "MODEL_MTO82QGT_01-BOX"
+    },
+    {
+      "status": 200,
+      "type": "IMAGE",
+      "code": "MODEL_COVER"
+    }
+  ],
+  "sha256": "6e99933505dfeb91a14d16ef1ddf53df2ea022add1b866de835c08403685b7b6",
+  "bytes": 11446,
+  "width": 640,
+  "height": 346,
+  "image": "screenshots/08-import-box-cover.jpg",
+  "cache": "no-cache, private"
+}
+
+ +
+ +
清理首次导入临时模型:检查细节 + +
+{
+  "id": "158",
+  "status": "业务软删除",
+  "readAfterDelete": 404
+}
+
+ +
+ +
封面读取边界:未登录401、无封面404、图片Range正确:检查细节 + +
+{
+  "anonymous": 401,
+  "missing": 404,
+  "range": 206,
+  "rangeBytes": 32
+}
+
+ +
+ +
全新浏览器会话显示两张持久化封面,重开模型不自动上传图片:检查细节 + +
+{
+  "projects": [
+    {
+      "id": "156",
+      "status": "PUBLISHED",
+      "versionId": "204"
+    },
+    {
+      "id": "157",
+      "status": "DRAFT",
+      "versionId": "202"
+    }
+  ],
+  "unexpectedUploads": 0
+}
+
+ +
+ +## 数据保留与清理 + +保留156卡车、157狐狸及新封面;卡车恢复已发布,狐狸保留原草稿状态。故障测试位置改动已恢复。158首次导入临时工程已通过业务接口软删除。历史发布版本及封面保留。 + +| 项目 | 初始状态 | 最终状态 | +|---|---|---| +| 156 · 实测模型-牛奶卡车-已验证-20260905 | PUBLISHED | PUBLISHED | +| 157 · 实测模型-狐狸动画-已验证-20260905 | DRAFT | DRAFT | + +首次导入验证使用的临时项目 158 已通过业务软删除,删除后读取返回 404;报告保留操作证据,不宣称物理文件已删除。 + +## 问题记录 + +当前证据未登记未解决问题。 + +## 实际命令与结果 + +**pnpm run build** + +
+{
+  "status": "PASS",
+  "details": "最终web类型检查、Vite构建、10个生成包payload哈希与API桥接/凭据门禁通过;现有Three资源URL与chunk体积警告未阻断构建。"
+}
+
+ +**mvn -B -ntp -pl ut_tran -Dtest=ContentProjectServiceTest,ContentAssetServiceTest,ContentControllerRangeTest,ContentAuthorizerTest test** + +
+{
+  "status": "PASS",
+  "details": "Java17,93项通过。"
+}
+
+ +**node --test --test-reporter=spec tools/model-cover-capture.test.mjs tools/model-cover-api.test.mjs** + +
+{
+  "status": "PASS",
+  "details": "截图12项+封面事务8项,20/20通过;既有模型API与导入失败保护回归也通过。"
+}
+
+ +## 当前行为与限制 + +- 仅手动保存和首次导入模型时生成或更新封面,封面取自当前三维视口。 +- 自动保存只保存工程变更,不重新截图或上传封面。 +- 截图或封面上传失败时保留旧封面,并提示失败;工程保存仍按其实际请求结果判断。 + +报告由 evidence.json 生成,未修改原始证据;图片均已校验存在且非空,点击图片可查看原图。 diff --git a/reports/model-cover-20260905/screenshots/01-truck-cover-editor.png b/reports/model-cover-20260905/screenshots/01-truck-cover-editor.png new file mode 100644 index 0000000..aa3955b Binary files /dev/null and b/reports/model-cover-20260905/screenshots/01-truck-cover-editor.png differ diff --git a/reports/model-cover-20260905/screenshots/01-truck-cover.jpg b/reports/model-cover-20260905/screenshots/01-truck-cover.jpg new file mode 100644 index 0000000..2c763e5 Binary files /dev/null and b/reports/model-cover-20260905/screenshots/01-truck-cover.jpg differ diff --git a/reports/model-cover-20260905/screenshots/02-truck-new-view-editor.png b/reports/model-cover-20260905/screenshots/02-truck-new-view-editor.png new file mode 100644 index 0000000..be5ced5 Binary files /dev/null and b/reports/model-cover-20260905/screenshots/02-truck-new-view-editor.png differ diff --git a/reports/model-cover-20260905/screenshots/02-truck-new-view.jpg b/reports/model-cover-20260905/screenshots/02-truck-new-view.jpg new file mode 100644 index 0000000..edff860 Binary files /dev/null and b/reports/model-cover-20260905/screenshots/02-truck-new-view.jpg differ diff --git a/reports/model-cover-20260905/screenshots/03-fox-cover-editor.png b/reports/model-cover-20260905/screenshots/03-fox-cover-editor.png new file mode 100644 index 0000000..d7ba2be Binary files /dev/null and b/reports/model-cover-20260905/screenshots/03-fox-cover-editor.png differ diff --git a/reports/model-cover-20260905/screenshots/03-fox-cover.jpg b/reports/model-cover-20260905/screenshots/03-fox-cover.jpg new file mode 100644 index 0000000..3f39784 Binary files /dev/null and b/reports/model-cover-20260905/screenshots/03-fox-cover.jpg differ diff --git a/reports/model-cover-20260905/screenshots/04-upload-failure-content-saved.png b/reports/model-cover-20260905/screenshots/04-upload-failure-content-saved.png new file mode 100644 index 0000000..efd9fb4 Binary files /dev/null and b/reports/model-cover-20260905/screenshots/04-upload-failure-content-saved.png differ diff --git a/reports/model-cover-20260905/screenshots/05-auto-save-no-cover-upload.png b/reports/model-cover-20260905/screenshots/05-auto-save-no-cover-upload.png new file mode 100644 index 0000000..05625f4 Binary files /dev/null and b/reports/model-cover-20260905/screenshots/05-auto-save-no-cover-upload.png differ diff --git a/reports/model-cover-20260905/screenshots/06-fox-restored-cover-editor.png b/reports/model-cover-20260905/screenshots/06-fox-restored-cover-editor.png new file mode 100644 index 0000000..fd37931 Binary files /dev/null and b/reports/model-cover-20260905/screenshots/06-fox-restored-cover-editor.png differ diff --git a/reports/model-cover-20260905/screenshots/06-fox-restored-cover.jpg b/reports/model-cover-20260905/screenshots/06-fox-restored-cover.jpg new file mode 100644 index 0000000..3f39784 Binary files /dev/null and b/reports/model-cover-20260905/screenshots/06-fox-restored-cover.jpg differ diff --git a/reports/model-cover-20260905/screenshots/07-real-model-covers-list.png b/reports/model-cover-20260905/screenshots/07-real-model-covers-list.png new file mode 100644 index 0000000..f03113a Binary files /dev/null and b/reports/model-cover-20260905/screenshots/07-real-model-covers-list.png differ diff --git a/reports/model-cover-20260905/screenshots/08-import-box-cover.jpg b/reports/model-cover-20260905/screenshots/08-import-box-cover.jpg new file mode 100644 index 0000000..41acb8c Binary files /dev/null and b/reports/model-cover-20260905/screenshots/08-import-box-cover.jpg differ diff --git a/reports/model-cover-20260905/screenshots/08-import-box-editor.png b/reports/model-cover-20260905/screenshots/08-import-box-editor.png new file mode 100644 index 0000000..0900b14 Binary files /dev/null and b/reports/model-cover-20260905/screenshots/08-import-box-editor.png differ diff --git a/reports/model-cover-20260905/screenshots/09-final-two-covers.png b/reports/model-cover-20260905/screenshots/09-final-two-covers.png new file mode 100644 index 0000000..bc64e73 Binary files /dev/null and b/reports/model-cover-20260905/screenshots/09-final-two-covers.png differ diff --git a/reports/model-cover-20260905/screenshots/10-fresh-session-covers.png b/reports/model-cover-20260905/screenshots/10-fresh-session-covers.png new file mode 100644 index 0000000..01b11a4 Binary files /dev/null and b/reports/model-cover-20260905/screenshots/10-fresh-session-covers.png differ diff --git a/reports/model-created-sort-20260905/cover-plan.md b/reports/model-created-sort-20260905/cover-plan.md new file mode 100644 index 0000000..8fed4e2 --- /dev/null +++ b/reports/model-created-sort-20260905/cover-plan.md @@ -0,0 +1,27 @@ +# 模型文件存储与截图封面方案 + +2026-09-05。用户已确认,本方案已实施;验证结果见[截图封面实施报告](../model-cover-20260905/index.html)。以下保留方案与存储说明。 + +## 当前文件存储 + +GLB 经 `/api/tran/v1/content/projects/{id}/assets/upload` 上传到业务服务,完成格式和大小校验后,由业务服务提交至 `http://1.14.103.234:6180/fileapi/upload`。 + +文件按 `unreal-tran/model/年/月/日/随机ID.glb` 归档。当前 file_svc 部署配置根目录为 `/data/file_svc/files`,未登录远端核查实际磁盘目录。数据库保存 `fsvc://` 文件引用、大小、SHA-256、项目及版本关联;工程 JSON 保存节点、材质和动画。上传成功后删除本机临时文件。 + +应用内模型读取经过鉴权下载接口。远端 `/f/` 是静态读取地址;本次对两条测试资源的匿名 HEAD 均返回 200,不能将文件本体描述为完全私有。 + +## 建议的保存封面流程 + +1. 用户调整到希望保留的相机视角,点击“保存”。 +2. 仅截取 3D 视口,沿用当前相机和模型姿态;临时隐藏选中框、变换控件和网格,截图后立即恢复,不截菜单和属性面板。 +3. 同步复制已渲染画布,缩放并编码 JPEG,建议最长边 640 像素,避免黑图与过大图片。 +4. 通过既有上传接口上传 IMAGE 资产,将上传票据、封面资产与工程放入同一保存队列,保存成功后更新 `coverUri`。 +5. 列表通过受控图片下载解析为 Blob URL 展示,并在页面释放时回收;不把 `fsvc://` 直接当作图片地址,也不为读取缩略图逐条加载完整模型工程。 + +复用现有 `coverUri` 和 IMAGE 资产类型,无需新增表。固定封面资产编码用于当前版本替换,历史版本引用保留。 + +建议首次导入完成与手动保存时更新封面;每 30 秒的自动保存仅保存工程,避免持续生成图片。截图或上传失败时继续保存模型内容,保留旧封面并提示封面更新失败。 + +## 实施时需要补齐的接点 + +当前编辑器已有视口截图方法,但尚未连接保存流程。模型上传方法写死 MODEL_FILE,需要增加 IMAGE 分支;保存指纹需包含封面变化。列表当前直接使用 `img src=coverUri`,必须同步补图片资产读取映射及鉴权加载,才是完整功能。 diff --git a/reports/model-created-sort-20260905/evidence.json b/reports/model-created-sort-20260905/evidence.json new file mode 100644 index 0000000..abe48fb --- /dev/null +++ b/reports/model-created-sort-20260905/evidence.json @@ -0,0 +1,280 @@ +{ + "date": "2026-09-05", + "baseURL": "http://127.0.0.1:6180", + "browser": "Microsoft Edge", + "role": "系统管理员", + "retainedData": "本次仅查询和筛选,未创建或修改模型数据。", + "build": { + "command": "pnpm run build", + "status": "PASS", + "details": "类型检查、Vite构建与产物门禁通过;现有Three资源URL和chunk体积警告仍在。" + }, + "results": [ + { + "title": "默认按创建时间倒序,列表与服务端分页一致", + "status": "PASS", + "type": "MODEL", + "sort": "CREATED_DESC", + "rows": [ + { + "id": "157", + "name": "实测模型-狐狸动画-已验证-20260905", + "created": 1788600787, + "updated": "2026-09-05T17:53:56" + }, + { + "id": "156", + "name": "实测模型-牛奶卡车-已验证-20260905", + "created": 1788600271, + "updated": "2026-09-05T17:47:29" + }, + { + "id": "155", + "name": "测试", + "created": 1788596734, + "updated": "2026-09-05T17:53:11" + }, + { + "id": "151", + "name": "野外山地场景与桥梁架设装备", + "created": 1788316127, + "updated": "2026-09-02T11:02:50" + }, + { + "id": "94", + "name": "桥梁架设装备整机模型", + "created": 1788074748, + "updated": "2026-09-02T11:02:50" + }, + { + "id": "48", + "name": "UAT 挖掘机装备模型", + "created": 1786413935, + "updated": "2026-09-01T09:48:57" + } + ], + "screenshot": "screenshots/01-created-default.png" + }, + { + "title": "手动选择排序仍可用,URL保留显式选择", + "status": "PASS", + "type": "MODEL", + "sort": "UPDATED_DESC", + "rows": [ + { + "id": "157", + "name": "实测模型-狐狸动画-已验证-20260905", + "created": 1788600787, + "updated": "2026-09-05T17:53:56" + }, + { + "id": "155", + "name": "测试", + "created": 1788596734, + "updated": "2026-09-05T17:53:11" + }, + { + "id": "156", + "name": "实测模型-牛奶卡车-已验证-20260905", + "created": 1788600271, + "updated": "2026-09-05T17:47:29" + }, + { + "id": "151", + "name": "野外山地场景与桥梁架设装备", + "created": 1788316127, + "updated": "2026-09-02T11:02:50" + }, + { + "id": "94", + "name": "桥梁架设装备整机模型", + "created": 1788074748, + "updated": "2026-09-02T11:02:50" + }, + { + "id": "48", + "name": "UAT 挖掘机装备模型", + "created": 1786413935, + "updated": "2026-09-01T09:48:57" + } + ] + }, + { + "title": "重置恢复创建时间倒序", + "status": "PASS", + "type": "MODEL", + "sort": "CREATED_DESC", + "rows": [ + { + "id": "157", + "name": "实测模型-狐狸动画-已验证-20260905", + "created": 1788600787, + "updated": "2026-09-05T17:53:56" + }, + { + "id": "156", + "name": "实测模型-牛奶卡车-已验证-20260905", + "created": 1788600271, + "updated": "2026-09-05T17:47:29" + }, + { + "id": "155", + "name": "测试", + "created": 1788596734, + "updated": "2026-09-05T17:53:11" + }, + { + "id": "151", + "name": "野外山地场景与桥梁架设装备", + "created": 1788316127, + "updated": "2026-09-02T11:02:50" + }, + { + "id": "94", + "name": "桥梁架设装备整机模型", + "created": 1788074748, + "updated": "2026-09-02T11:02:50" + }, + { + "id": "48", + "name": "UAT 挖掘机装备模型", + "created": 1786413935, + "updated": "2026-09-01T09:48:57" + } + ], + "screenshot": "screenshots/02-created-reset.png" + }, + { + "title": "整页刷新保持默认创建时间倒序", + "status": "PASS", + "type": "MODEL", + "sort": "CREATED_DESC", + "rows": [ + { + "id": "157", + "name": "实测模型-狐狸动画-已验证-20260905", + "created": 1788600787, + "updated": "2026-09-05T17:53:56" + }, + { + "id": "156", + "name": "实测模型-牛奶卡车-已验证-20260905", + "created": 1788600271, + "updated": "2026-09-05T17:47:29" + }, + { + "id": "155", + "name": "测试", + "created": 1788596734, + "updated": "2026-09-05T17:53:11" + }, + { + "id": "151", + "name": "野外山地场景与桥梁架设装备", + "created": 1788316127, + "updated": "2026-09-02T11:02:50" + }, + { + "id": "94", + "name": "桥梁架设装备整机模型", + "created": 1788074748, + "updated": "2026-09-02T11:02:50" + }, + { + "id": "48", + "name": "UAT 挖掘机装备模型", + "created": 1786413935, + "updated": "2026-09-01T09:48:57" + } + ] + }, + { + "title": "无效排序参数回退到创建时间倒序", + "status": "PASS", + "type": "MODEL", + "sort": "CREATED_DESC", + "rows": [ + { + "id": "157", + "name": "实测模型-狐狸动画-已验证-20260905", + "created": 1788600787, + "updated": "2026-09-05T17:53:56" + }, + { + "id": "156", + "name": "实测模型-牛奶卡车-已验证-20260905", + "created": 1788600271, + "updated": "2026-09-05T17:47:29" + }, + { + "id": "155", + "name": "测试", + "created": 1788596734, + "updated": "2026-09-05T17:53:11" + }, + { + "id": "151", + "name": "野外山地场景与桥梁架设装备", + "created": 1788316127, + "updated": "2026-09-02T11:02:50" + }, + { + "id": "94", + "name": "桥梁架设装备整机模型", + "created": 1788074748, + "updated": "2026-09-02T11:02:50" + }, + { + "id": "48", + "name": "UAT 挖掘机装备模型", + "created": 1786413935, + "updated": "2026-09-01T09:48:57" + } + ] + }, + { + "title": "场景列表保留现有默认排序", + "status": "PASS", + "type": "SCENE", + "sort": "UPDATED_DESC", + "rows": [ + { + "id": "131", + "name": "真实装备车库整机进场点检场景", + "created": 1788139208, + "updated": "2026-09-02T14:48:53" + }, + { + "id": "152", + "name": "真实野外山地桥梁架设训练场", + "created": 1788316127, + "updated": "2026-09-02T11:02:50" + }, + { + "id": "49", + "name": "UAT 综合检验车间", + "created": 1786413935, + "updated": "2026-08-31T10:42:12" + }, + { + "id": "95", + "name": "桥梁架设装备架桥作业训练场", + "created": 1788074748, + "updated": "2026-08-31T10:34:44" + }, + { + "id": "50", + "name": "UAT 室外对抗训练场", + "created": 1786413935, + "updated": "2026-08-11T02:05:35" + } + ], + "screenshot": "screenshots/03-scene-default.png" + }, + { + "title": "局域网前端访问正常", + "status": "PASS", + "httpStatus": 200 + } + ] +} \ No newline at end of file diff --git a/reports/model-created-sort-20260905/index.html b/reports/model-created-sort-20260905/index.html new file mode 100644 index 0000000..6d37a13 --- /dev/null +++ b/reports/model-created-sort-20260905/index.html @@ -0,0 +1 @@ +模型列表创建时间排序验证

模型列表创建时间排序验证

7/7 项通过 · 2026-09-05 · Microsoft Edge

本次仅查询和筛选,未创建或修改模型数据。

完整数据证据 · 文件存储与截图封面方案(待确认)

pnpm run build:通过类型检查、Vite构建与产物门禁。既有Three资源URL和chunk体积警告未阻断构建。

默认按创建时间倒序,列表与服务端分页一致:PASS

实际请求:MODEL / CREATED_DESC

默认按创建时间倒序,列表与服务端分页一致

手动选择排序仍可用,URL保留显式选择:PASS

实际请求:MODEL / UPDATED_DESC

重置恢复创建时间倒序:PASS

实际请求:MODEL / CREATED_DESC

重置恢复创建时间倒序

整页刷新保持默认创建时间倒序:PASS

实际请求:MODEL / CREATED_DESC

无效排序参数回退到创建时间倒序:PASS

实际请求:MODEL / CREATED_DESC

场景列表保留现有默认排序:PASS

实际请求:SCENE / UPDATED_DESC

场景列表保留现有默认排序

局域网前端访问正常:PASS

\ No newline at end of file diff --git a/reports/model-created-sort-20260905/screenshots/01-created-default.png b/reports/model-created-sort-20260905/screenshots/01-created-default.png new file mode 100644 index 0000000..68bae6a Binary files /dev/null and b/reports/model-created-sort-20260905/screenshots/01-created-default.png differ diff --git a/reports/model-created-sort-20260905/screenshots/02-created-reset.png b/reports/model-created-sort-20260905/screenshots/02-created-reset.png new file mode 100644 index 0000000..4a56e7a Binary files /dev/null and b/reports/model-created-sort-20260905/screenshots/02-created-reset.png differ diff --git a/reports/model-created-sort-20260905/screenshots/03-scene-default.png b/reports/model-created-sort-20260905/screenshots/03-scene-default.png new file mode 100644 index 0000000..4a741f5 Binary files /dev/null and b/reports/model-created-sort-20260905/screenshots/03-scene-default.png differ diff --git a/reports/model-live-20260905/evidence.json b/reports/model-live-20260905/evidence.json new file mode 100644 index 0000000..a4f52e2 --- /dev/null +++ b/reports/model-live-20260905/evidence.json @@ -0,0 +1,24797 @@ +{ + "date": "2026-09-05", + "baseURL": "http://127.0.0.1:6180", + "browser": "Microsoft Edge", + "role": "teacher", + "accountDisplayName": "系统管理员", + "projects": [ + { + "index": 0, + "name": "实测模型-牛奶卡车-已验证-20260905", + "file": "08-CesiumMilkTruck.glb", + "mesh": "Cesium_Milk_Truck", + "clip": "0", + "clipName": "Wheels", + "clips": 1, + "description": "轻量 GLB 实测:车辆多部件、节点编辑、车轮动画、保存重开和发布。保留供后续模型/场景测试使用。", + "id": "156", + "code": "MODEL-3FA24629D59E4509", + "steps": [ + { + "step": "UI创建项目", + "status": "PASS", + "httpStatus": 200 + }, + { + "step": "文件服务地址修复后重新上传", + "status": "PASS", + "httpStatus": 200, + "details": "首次上传失败保留于问题证据;修复地址后已实际上传成功并校验文件哈希", + "screenshot": "screenshots/03b-upload-error-log.png", + "initialHttpStatus": 503 + }, + { + "step": "GLB上传、两阶段绑定、SHA256与活跃模型核验", + "status": "PASS", + "screenshot": "screenshots/1-01-imported.png" + }, + { + "step": "组合节点 X 位置与原生动画选择保存", + "status": "PASS", + "details": { + "x": 0.35, + "clip": "Wheels", + "versionBefore": 5, + "versionAfter": 6 + }, + "screenshot": "screenshots/1-02-edited.png" + }, + { + "step": "整页刷新后模型、节点、材质、动画选择恢复", + "status": "PASS", + "screenshot": "screenshots/1-03-reopened.png" + }, + { + "step": "原生动画实播:播放时间与轮子/骨骼姿态确实变化", + "status": "PASS", + "screenshot": "screenshots/1-04-animation.png" + }, + { + "step": "车身子网格材质粗糙度修改、保存、刷新恢复", + "status": "PASS", + "details": { + "node": "Cesium_Milk_Truck_1", + "roughness": 0.3, + "persistedAfterReload": true + }, + "screenshot": "screenshots/1-04b-material-reopened.png" + }, + { + "step": "发布到场景资源库并核对服务端发布版本", + "status": "PASS", + "httpStatus": 200, + "screenshot": "screenshots/1-05-published.png" + }, + { + "step": "全新浏览器上下文从服务端载入已发布模型", + "status": "PASS", + "details": { + "source": "08-CesiumMilkTruck.glb", + "apiMode": true, + "clip": "Wheels" + }, + "screenshot": "screenshots/1-06-fresh-session.png" + }, + { + "step": "已发布模型改名保存为 V2 草稿,项目及版本更新时间刷新", + "status": "PASS", + "details": { + "status": "PASS", + "before": { + "project": "2026-09-05T17:24:34", + "version": "2026-09-05T17:24:34" + }, + "after": { + "project": "2026-09-05T17:47:05", + "version": "2026-09-05T17:47:05" + }, + "draftVersionId": "200", + "versionNo": 2 + }, + "screenshot": "screenshots/1-07-update-time.png" + }, + { + "step": "V2 重新发布成功,发布版本及更新时间正确", + "status": "PASS", + "details": { + "versionNo": 2, + "versionId": "200", + "updateTime": "2026-09-05T17:47:29" + }, + "screenshot": "screenshots/1-08-published-v2.png" + }, + { + "step": "V2 全新浏览器上下文重开,模型文件、动画选择、发布版本均正确", + "status": "PASS", + "details": { + "source": "08-CesiumMilkTruck.glb", + "clip": "Wheels", + "versionNo": 2 + }, + "screenshot": "screenshots/1-09-fresh-session-v2.png" + } + ], + "before": { + "projectId": "156", + "code": "MODEL-3FA24629D59E4509", + "name": "实测模型-牛奶卡车-20260905", + "status": "DRAFT", + "version": 2, + "publishedVersionId": null, + "currentVersionId": "198", + "versionNo": 1, + "checksum": "a4251429c16f0a79288ef0d50adc43cbbd5998ff840d00a1b944134220743a22", + "schema": "digital-twin-editor-project", + "modelResource": { + "kind": "builtin", + "id": "bridge-erector-vehicle", + "name": "桥梁架设装备整机", + "assetCode": "MODEL_BRIDGE-ERECTOR-VEHICLE", + "code": "MODEL_BRIDGE-ERECTOR-VEHICLE", + "storageUri": "/models/bridge-erector-vehicle.glb", + "resourceUrl": "/models/bridge-erector-vehicle.glb", + "sourceName": "bridge-erector-vehicle.glb", + "sizeBytes": 31140540, + "lastModified": 0, + "mimeType": "model/gltf-binary", + "thumbnail": "/models/bridge-erector-vehicle-thumb.png", + "vertices": 574222, + "triangles": 436616, + "nodes": 186, + "meshes": 114, + "materials": 114, + "textures": 5, + "animations": 0, + "animationDurationSeconds": 0, + "modelMetadata": { + "nodeCount": 186, + "meshCount": 114, + "materialCount": 114, + "textureCount": 5, + "animations": [], + "animationDurationSeconds": 0 + }, + "nativeAnimations": [] + }, + "nativeAnimation": { + "clipIndex": 0, + "clipName": "" + }, + "modelObjects": { + "equipment-root": { + "name": "桥梁架设装备整机", + "nodeName": "桥梁架设装备整机", + "nodePath": "@root", + "interactionId": "interaction-fc0e9f4a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-0": { + "name": "", + "nodeName": "Group", + "nodePath": "0", + "interactionId": "interaction-1223a52e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 7.463825679732139e-8, + 0.7182123701337901, + 0.15487073466297074 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1.1415944032239054, + 1.1415944032239054, + 1.1415944032239054 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-1": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/0", + "interactionId": "interaction-ed434099", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529039764404296, + 0.05721450805664063, + 3.316722412109375 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-2": { + "name": "底盘车_3", + "nodeName": "底盘车_3", + "nodePath": "0/0/0", + "interactionId": "interaction-12d89236", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-3": { + "name": "底盘车_3_1", + "nodeName": "底盘车_3_1", + "nodePath": "0/0/0/0", + "interactionId": "interaction-daa5ef71", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "4f4f4f", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-4": { + "name": "底盘车_3_2", + "nodeName": "底盘车_3_2", + "nodePath": "0/0/0/1", + "interactionId": "interaction-d9a5edde", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "929292", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.9, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-5": { + "name": "底盘车_3_3", + "nodeName": "底盘车_3_3", + "nodePath": "0/0/0/2", + "interactionId": "interaction-d8a5ec4b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-6": { + "name": "底盘车_3_4", + "nodeName": "底盘车_3_4", + "nodePath": "0/0/0/3", + "interactionId": "interaction-d7a5eab8", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-7": { + "name": "底盘车_3_5", + "nodeName": "底盘车_3_5", + "nodePath": "0/0/0/4", + "interactionId": "interaction-dea5f5bd", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-8": { + "name": "底盘车_3_6", + "nodeName": "底盘车_3_6", + "nodePath": "0/0/0/5", + "interactionId": "interaction-dda5f42a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-9": { + "name": "底盘车_3_7", + "nodeName": "底盘车_3_7", + "nodePath": "0/0/0/6", + "interactionId": "interaction-dca5f297", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-10": { + "name": "底盘车_3_8", + "nodeName": "底盘车_3_8", + "nodePath": "0/0/0/7", + "interactionId": "interaction-dba5f104", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "404040", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-11": { + "name": "底盘车_3_9", + "nodeName": "底盘车_3_9", + "nodePath": "0/0/0/8", + "interactionId": "interaction-d2a5e2d9", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "cbcbcb", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.9, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-12": { + "name": "底盘车_3_10", + "nodeName": "底盘车_3_10", + "nodePath": "0/0/0/9", + "interactionId": "interaction-d1a5e146", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "749f62", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-13": { + "name": "底盘车_3_11", + "nodeName": "底盘车_3_11", + "nodePath": "0/0/0/10", + "interactionId": "interaction-8e358daa", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-14": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/1", + "interactionId": "interaction-ec433f06", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.152912826538086, + 0.05720820426940918, + 3.31687255859375 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-15": { + "name": "底盘车_5", + "nodeName": "底盘车_5", + "nodePath": "0/1/0", + "interactionId": "interaction-b800bd61", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-16": { + "name": "底盘车_5_1", + "nodeName": "底盘车_5_1", + "nodePath": "0/1/0/0", + "interactionId": "interaction-11211c8e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "4f4f4f", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-17": { + "name": "底盘车_5_2", + "nodeName": "底盘车_5_2", + "nodePath": "0/1/0/1", + "interactionId": "interaction-12211e21", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "929292", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.9, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-18": { + "name": "底盘车_5_3", + "nodeName": "底盘车_5_3", + "nodePath": "0/1/0/2", + "interactionId": "interaction-0f211968", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-19": { + "name": "底盘车_5_4", + "nodeName": "底盘车_5_4", + "nodePath": "0/1/0/3", + "interactionId": "interaction-10211afb", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-20": { + "name": "底盘车_5_5", + "nodeName": "底盘车_5_5", + "nodePath": "0/1/0/4", + "interactionId": "interaction-152122da", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-21": { + "name": "底盘车_5_6", + "nodeName": "底盘车_5_6", + "nodePath": "0/1/0/5", + "interactionId": "interaction-1621246d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.45, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-22": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/2", + "interactionId": "interaction-eb433d73", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529016876220703, + 0.057205944061279296, + 3.3168429565429687 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-23": { + "name": "底盘车_1", + "nodeName": "底盘车_1", + "nodePath": "0/2/0", + "interactionId": "interaction-bc8a1bec", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-24": { + "name": "底盘车_1_1", + "nodeName": "底盘车_1_1", + "nodePath": "0/2/0/0", + "interactionId": "interaction-1f66056b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-25": { + "name": "底盘车_1_2", + "nodeName": "底盘车_1_2", + "nodePath": "0/2/0/1", + "interactionId": "interaction-1e6603d8", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-26": { + "name": "底盘车_1_3", + "nodeName": "底盘车_1_3", + "nodePath": "0/2/0/2", + "interactionId": "interaction-21660891", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-27": { + "name": "底盘车_1_4", + "nodeName": "底盘车_1_4", + "nodePath": "0/2/0/3", + "interactionId": "interaction-206606fe", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-28": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/3", + "interactionId": "interaction-ea433be0", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529024505615235, + 0.05720912456512451, + 3.31684814453125 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-29": { + "name": "底盘车_7", + "nodeName": "底盘车_7", + "nodePath": "0/3/0", + "interactionId": "interaction-61b24717", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-30": { + "name": "底盘车_7_1", + "nodeName": "底盘车_7_1", + "nodePath": "0/3/0/0", + "interactionId": "interaction-d67fccc8", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-31": { + "name": "底盘车_7_2", + "nodeName": "底盘车_7_2", + "nodePath": "0/3/0/1", + "interactionId": "interaction-d77fce5b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-32": { + "name": "底盘车_7_3", + "nodeName": "底盘车_7_3", + "nodePath": "0/3/0/2", + "interactionId": "interaction-d87fcfee", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-33": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/4", + "interactionId": "interaction-f14346e5", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1524486541748047, + 0.05721979141235352, + 3.316885681152344 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-34": { + "name": "底盘车_6", + "nodeName": "底盘车_6", + "nodePath": "0/4/0", + "interactionId": "interaction-5de8014a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-35": { + "name": "底盘车_6_1", + "nodeName": "底盘车_6_1", + "nodePath": "0/4/0/0", + "interactionId": "interaction-e59c68dd", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "4f4f4f", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-36": { + "name": "底盘车_6_2", + "nodeName": "底盘车_6_2", + "nodePath": "0/4/0/1", + "interactionId": "interaction-e49c674a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "929292", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.9, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-37": { + "name": "底盘车_6_3", + "nodeName": "底盘车_6_3", + "nodePath": "0/4/0/2", + "interactionId": "interaction-e39c65b7", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3b76d0", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-38": { + "name": "底盘车_6_4", + "nodeName": "底盘车_6_4", + "nodePath": "0/4/0/3", + "interactionId": "interaction-e29c6424", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-39": { + "name": "底盘车_6_5", + "nodeName": "底盘车_6_5", + "nodePath": "0/4/0/4", + "interactionId": "interaction-e19c6291", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-40": { + "name": "底盘车_6_6", + "nodeName": "底盘车_6_6", + "nodePath": "0/4/0/5", + "interactionId": "interaction-e09c60fe", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-41": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/5", + "interactionId": "interaction-f0434552", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1528985595703125, + 0.057159042358398436, + 3.3168621826171876 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-42": { + "name": "底盘车_2", + "nodeName": "底盘车_2", + "nodePath": "0/5/0", + "interactionId": "interaction-e3af5dd5", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-43": { + "name": "底盘车_2_1", + "nodeName": "底盘车_2_1", + "nodePath": "0/5/0/0", + "interactionId": "interaction-fdaafb1a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-44": { + "name": "底盘车_2_2", + "nodeName": "底盘车_2_2", + "nodePath": "0/5/0/1", + "interactionId": "interaction-feaafcad", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-45": { + "name": "底盘车_2_3", + "nodeName": "底盘车_2_3", + "nodePath": "0/5/0/2", + "interactionId": "interaction-fbaaf7f4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-46": { + "name": "底盘车_2_4", + "nodeName": "底盘车_2_4", + "nodePath": "0/5/0/3", + "interactionId": "interaction-fcaaf987", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-47": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/6", + "interactionId": "interaction-ef4343bf", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.152901382446289, + 0.057154388427734376, + 3.3168765258789064 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-49": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/7", + "interactionId": "interaction-ee43422c", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529015350341798, + 0.057218170166015624, + 3.3169009399414064 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-51": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/8", + "interactionId": "interaction-f5434d31", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529015350341798, + 0.05720924377441406, + 3.316878662109375 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-55": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/9", + "interactionId": "interaction-f4434b9e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.083279571533203, + -0.04030906677246094, + 3.3168756103515626 + ], + "rotation": [ + -1.5707963267948966, + 0.08726646040099466, + 0 + ], + "scale": [ + 0.003937009043006274, + 0.003937008790671825, + 0.003937009043006274 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-60": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/10", + "interactionId": "interaction-23dc8202", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.152901382446289, + 0.05717395782470703, + 3.3169152832031252 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-62": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/11", + "interactionId": "interaction-24dc8395", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.152901382446289, + 0.057208557128906254, + 3.3169476318359377 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-70": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/12", + "interactionId": "interaction-21dc7edc", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529014587402344, + 0.05719829559326172, + 3.31669677734375 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-75": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/13", + "interactionId": "interaction-22dc806f", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529014587402344, + 0.057202301025390624, + 3.316808776855469 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-77": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/14", + "interactionId": "interaction-1fdc7bb6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.152901611328125, + 0.05720479965209961, + 3.316877746582031 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-78": { + "name": "副梁和滑道总成", + "nodeName": "副梁和滑道总成", + "nodePath": "0/14/0", + "interactionId": "interaction-e187b4f1", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-79": { + "name": "副梁和滑道总成_1", + "nodeName": "副梁和滑道总成_1", + "nodePath": "0/14/0/0", + "interactionId": "interaction-5a96af7e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-80": { + "name": "副梁和滑道总成_2", + "nodeName": "副梁和滑道总成_2", + "nodePath": "0/14/0/1", + "interactionId": "interaction-5b96b111", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-81": { + "name": "副梁和滑道总成_3", + "nodeName": "副梁和滑道总成_3", + "nodePath": "0/14/0/2", + "interactionId": "interaction-5896ac58", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-82": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/15", + "interactionId": "interaction-20dc7d49", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529014587402344, + 0.057201995849609374, + 3.3168780517578127 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-84": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/16", + "interactionId": "interaction-1ddc7890", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + -0.11929863929748535, + 0.13276389122009277, + 0.08761335372924804 + ], + "rotation": [ + 4.3021095220366097e-16, + -1.570796247945363, + 0 + ], + "scale": [ + 0.003937008790671834, + 0.003937008790671827, + 0.003937008790671834 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-85": { + "name": "定位传力销", + "nodeName": "定位传力销", + "nodePath": "0/16/0", + "interactionId": "interaction-8c767327", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-86": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/17", + "interactionId": "interaction-1edc7a23", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529014587402344, + 0.05720605850219727, + 3.3169268798828124 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-92": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/18", + "interactionId": "interaction-2bdc8e9a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.152901382446289, + 0.05720489501953125, + 3.316749267578125 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-94": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/19", + "interactionId": "interaction-2cdc902d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1528977203369142, + 0.057184276580810545, + 3.3170480346679687 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-95": { + "name": "油滤", + "nodeName": "油滤", + "nodePath": "0/19/0", + "interactionId": "interaction-df1beba2", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "d96e6e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-96": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/20", + "interactionId": "interaction-9dd97079", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1528977203369142, + 0.057184276580810545, + 3.3170480346679687 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-97": { + "name": "阀", + "nodeName": "阀", + "nodePath": "0/20/0", + "interactionId": "interaction-f263f616", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "929292", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.9, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-98": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/21", + "interactionId": "interaction-9cd96ee6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1528977203369142, + 0.057184276580810545, + 3.3170483398437502 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-99": { + "name": "开关", + "nodeName": "开关", + "nodePath": "0/21/0", + "interactionId": "interaction-978c2141", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "929292", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.9, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-100": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/22", + "interactionId": "interaction-9bd96d53", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1528923797607422, + 0.05718547821044922, + 3.31912109375 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-101": { + "name": "支承座", + "nodeName": "支承座", + "nodePath": "0/22/0", + "interactionId": "interaction-9d52b44c", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-102": { + "name": "支承座_1", + "nodeName": "支承座_1", + "nodePath": "0/22/0/0", + "interactionId": "interaction-1ba943cb", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-103": { + "name": "支承座_2", + "nodeName": "支承座_2", + "nodePath": "0/22/0/1", + "interactionId": "interaction-1aa94238", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-104": { + "name": "支承座_3", + "nodeName": "支承座_3", + "nodePath": "0/22/0/2", + "interactionId": "interaction-1da946f1", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-105": { + "name": "支承座_4", + "nodeName": "支承座_4", + "nodePath": "0/22/0/3", + "interactionId": "interaction-1ca9455e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-106": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/23", + "interactionId": "interaction-9ad96bc0", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529158020019532, + 0.05718589782714844, + 3.319119567871094 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-108": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/24", + "interactionId": "interaction-a1d976c5", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1516650390625, + 0.05719955444335938, + 3.319119567871094 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-116": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/25", + "interactionId": "interaction-a0d97532", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.152901153564453, + 0.05720237731933594, + 3.319119567871094 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-120": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/26", + "interactionId": "interaction-9fd9739f", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1528968811035156, + 0.05721282958984375, + 3.319122314453125 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-124": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/27", + "interactionId": "interaction-9ed9720c", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529075622558593, + 0.05719169616699219, + 3.3191217041015624 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-128": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/28", + "interactionId": "interaction-a5d97d11", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529489898681642, + 0.05719955444335938, + 3.3168780517578127 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-132": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/29", + "interactionId": "interaction-a4d97b7e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529019927978517, + 0.0572225570678711, + 3.3168762207031253 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-136": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/30", + "interactionId": "interaction-97d72870", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0.0017780303955078126, + 0.3220759201049805, + 1.3452468872070313 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-137": { + "name": "回转支承座", + "nodeName": "回转支承座", + "nodePath": "0/30/0", + "interactionId": "interaction-6b3b2087", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-138": { + "name": "回转支承座_1", + "nodeName": "回转支承座_1", + "nodePath": "0/30/0/0", + "interactionId": "interaction-2a202958", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-139": { + "name": "回转支承座_2", + "nodeName": "回转支承座_2", + "nodePath": "0/30/0/1", + "interactionId": "interaction-2b202aeb", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-140": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/31", + "interactionId": "interaction-98d72a03", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + -0.12935433387756348, + 0.008271529674530029, + 1.601549072265625 + ], + "rotation": [ + 1.6292068494296025e-7, + -4.7683715820308365e-7, + 6.347578170550195e-14 + ], + "scale": [ + 1.0000000000001137, + 1.0000000000000133, + 1.000000000000127 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-141": { + "name": "柱塞泵相关", + "nodeName": "柱塞泵相关", + "nodePath": "0/31/0", + "interactionId": "interaction-46b18f9c", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "4f4f4f", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-142": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/32", + "interactionId": "interaction-99d72b96", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + -0.5312847137451172, + 0.26239418029785155, + 0.3595037841796875 + ], + "rotation": [ + -6.979189167354852e-8, + -1.570796123024582, + 0 + ], + "scale": [ + 0.9555317759513993, + 0.9555317759514067, + 1.000000000000024 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-143": { + "name": "灯控制", + "nodeName": "灯控制", + "nodePath": "0/32/0", + "interactionId": "interaction-4188cd51", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-144": { + "name": "灯控制_1", + "nodeName": "灯控制_1", + "nodePath": "0/32/0/0", + "interactionId": "interaction-72066dde", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-145": { + "name": "灯控制_2", + "nodeName": "灯控制_2", + "nodePath": "0/32/0/1", + "interactionId": "interaction-73066f71", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "4f4f4f", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-146": { + "name": "灯控制_3", + "nodeName": "灯控制_3", + "nodePath": "0/32/0/2", + "interactionId": "interaction-70066ab8", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-147": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/33", + "interactionId": "interaction-9ad72d29", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529014587402344, + 0.05721702575683594, + 3.1155499267578124 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-151": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/34", + "interactionId": "interaction-9bd72ebc", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529014587402344, + 0.057251663208007814, + 3.1154907226562503 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-153": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/35", + "interactionId": "interaction-9cd7304f", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529015350341798, + 0.057218170166015624, + 3.1155255126953127 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-155": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/36", + "interactionId": "interaction-9dd731e2", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529015350341798, + 0.057200660705566404, + 3.1155792236328126 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-157": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/37", + "interactionId": "interaction-9ed73375", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529015350341798, + 0.05718978881835938, + 3.1155810546875 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-159": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/38", + "interactionId": "interaction-9fd73508", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.152901382446289, + 0.05720100402832031, + 3.1154833984375 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-167": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/39", + "interactionId": "interaction-a0d7369b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529015350341798, + 0.05719390869140625, + 3.1155206298828126 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-171": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/40", + "interactionId": "interaction-a1e8814f", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529015350341798, + 0.057197647094726564, + 3.1154998779296874 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-173": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/41", + "interactionId": "interaction-a0e87fbc", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529119110107422, + 0.05719699859619141, + 3.115636901855469 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-177": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/42", + "interactionId": "interaction-a3e88475", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529014587402344, + 0.05720073699951172, + 3.1155523681640624 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-181": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/43", + "interactionId": "interaction-a2e882e2", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529014587402344, + 0.057207679748535155, + 3.1155569458007815 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-71": { + "name": "前横梁总成", + "nodeName": "前横梁总成", + "nodePath": "0/12/0", + "interactionId": "interaction-37d62b3b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.3161459274047846, + -0.13338907115591614, + 1.5716647929548482 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-72": { + "name": "前横梁总成_1", + "nodeName": "前横梁总成_1", + "nodePath": "0/12/0/0", + "interactionId": "interaction-1586e7a4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-73": { + "name": "前横梁总成_2", + "nodeName": "前横梁总成_2", + "nodePath": "0/12/0/1", + "interactionId": "interaction-1686e937", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-74": { + "name": "前横梁总成_3", + "nodeName": "前横梁总成_3", + "nodePath": "0/12/0/2", + "interactionId": "interaction-1786eaca", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-87": { + "name": "后横梁总成", + "nodeName": "后横梁总成", + "nodePath": "0/17/0", + "interactionId": "interaction-66afadbc", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.316481498195647, + 0.09219811319424576, + 5.598526923989661 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-88": { + "name": "后横梁总成_1", + "nodeName": "后横梁总成_1", + "nodePath": "0/17/0/0", + "interactionId": "interaction-f3ec261b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-89": { + "name": "后横梁总成_2", + "nodeName": "后横梁总成_2", + "nodePath": "0/17/0/1", + "interactionId": "interaction-f2ec2488", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-90": { + "name": "后横梁总成_3", + "nodeName": "后横梁总成_3", + "nodePath": "0/17/0/2", + "interactionId": "interaction-f5ec2941", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-91": { + "name": "后横梁总成_4", + "nodeName": "后横梁总成_4", + "nodePath": "0/17/0/3", + "interactionId": "interaction-f4ec27ae", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-182": { + "name": "后支座", + "nodeName": "后支座", + "nodePath": "0/43/0", + "interactionId": "interaction-e34d0c85", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.316145795730941, + -0.1466403098263228, + 5.820431585950951 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-183": { + "name": "后支座_1", + "nodeName": "后支座_1", + "nodePath": "0/43/0/0", + "interactionId": "interaction-57f74eea", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-184": { + "name": "后支座_2", + "nodeName": "后支座_2", + "nodePath": "0/43/0/1", + "interactionId": "interaction-58f7507d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-185": { + "name": "后支座_3", + "nodeName": "后支座_3", + "nodePath": "0/43/0/2", + "interactionId": "interaction-55f74bc4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-109": { + "name": "下臂架油缸", + "nodeName": "下臂架油缸", + "nodePath": "0/24/0", + "interactionId": "interaction-beb1632a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.314420773379884, + -0.35887045728099454, + 2.251160314116218 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-110": { + "name": "下臂架油缸_1", + "nodeName": "下臂架油缸_1", + "nodePath": "0/24/0/0", + "interactionId": "interaction-53fc183d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-111": { + "name": "下臂架油缸_2", + "nodeName": "下臂架油缸_2", + "nodePath": "0/24/0/1", + "interactionId": "interaction-52fc16aa", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "4f4f4f", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-112": { + "name": "下臂架油缸_3", + "nodeName": "下臂架油缸_3", + "nodePath": "0/24/0/2", + "interactionId": "interaction-51fc1517", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "929292", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.9, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-113": { + "name": "下臂架油缸_4", + "nodeName": "下臂架油缸_4", + "nodePath": "0/24/0/3", + "interactionId": "interaction-50fc1384", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-114": { + "name": "下臂架油缸_5", + "nodeName": "下臂架油缸_5", + "nodePath": "0/24/0/4", + "interactionId": "interaction-4ffc11f1", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-115": { + "name": "下臂架油缸_6", + "nodeName": "下臂架油缸_6", + "nodePath": "0/24/0/5", + "interactionId": "interaction-4efc105e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-117": { + "name": "下臂架", + "nodeName": "下臂架", + "nodePath": "0/25/0", + "interactionId": "interaction-c33ac1b5", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.3158319147770576, + -0.35886723470157866, + 2.251160314116218 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-118": { + "name": "下臂架_1", + "nodeName": "下臂架_1", + "nodePath": "0/25/0/0", + "interactionId": "interaction-6290b2fa", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-119": { + "name": "下臂架_2", + "nodeName": "下臂架_2", + "nodePath": "0/25/0/1", + "interactionId": "interaction-6390b48d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-133": { + "name": "回转支承", + "nodeName": "回转支承", + "nodePath": "0/29/0", + "interactionId": "interaction-6e9a79c9", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.3158328728412083, + -0.35884419761359243, + 2.248599321544777 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-134": { + "name": "回转支承_1", + "nodeName": "回转支承_1", + "nodePath": "0/29/0/0", + "interactionId": "interaction-233fb486", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-135": { + "name": "回转支承_2", + "nodeName": "回转支承_2", + "nodePath": "0/29/0/1", + "interactionId": "interaction-243fb619", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-107": { + "name": "四连杆机构", + "nodeName": "四连杆机构", + "nodePath": "0/23/0", + "interactionId": "interaction-427adf77", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0.7377842289012164, + -0.9109434053346417, + 2.251188596561066 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-121": { + "name": "上臂架油缸", + "nodeName": "上臂架油缸", + "nodePath": "0/26/0", + "interactionId": "interaction-48b26c60", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0.7377626289094563, + -0.9109126601850798, + 2.2511917320437407 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-122": { + "name": "上臂架油缸_1", + "nodeName": "上臂架油缸_1", + "nodePath": "0/26/0/0", + "interactionId": "interaction-7b6a2b97", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-123": { + "name": "上臂架油缸_2", + "nodeName": "上臂架油缸_2", + "nodePath": "0/26/0/1", + "interactionId": "interaction-7a6a2a04", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-125": { + "name": "上臂架", + "nodeName": "上臂架", + "nodePath": "0/27/0", + "interactionId": "interaction-edda978b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0.7377748224531919, + -0.9109367859823281, + 2.251191035269813 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-126": { + "name": "上臂架_1", + "nodeName": "上臂架_1", + "nodePath": "0/27/0/0", + "interactionId": "interaction-32344114", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-127": { + "name": "上臂架_2", + "nodeName": "上臂架_2", + "nodePath": "0/27/0/1", + "interactionId": "interaction-333442a7", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-129": { + "name": "插销机构", + "nodeName": "插销机构", + "nodePath": "0/28/0", + "interactionId": "interaction-ea60039e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0.7378221159835381, + -0.9109278150180083, + 2.2486296943114077 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-130": { + "name": "插销机构_1", + "nodeName": "插销机构_1", + "nodePath": "0/28/0/0", + "interactionId": "interaction-2085c469", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-131": { + "name": "插销机构_2", + "nodeName": "插销机构_2", + "nodePath": "0/28/0/1", + "interactionId": "interaction-1f85c2d6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-93": { + "name": "架设架连接座", + "nodeName": "架设架连接座", + "nodePath": "0/18/0", + "interactionId": "interaction-04e2b10d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3161455982201753, + -0.11300762252172991, + 5.990716063154325 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-154": { + "name": "摆块", + "nodeName": "摆块", + "nodePath": "0/35/0", + "interactionId": "interaction-72107e30", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3161457724136572, + -0.11299246768880133, + 5.761000150784408 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-156": { + "name": "架设架结构", + "nodeName": "架设架结构", + "nodePath": "0/36/0", + "interactionId": "interaction-ec98d385", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3161457724136572, + -0.11301245639085367, + 5.76106146689005 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-158": { + "name": "推桥机构", + "nodeName": "推桥机构", + "nodePath": "0/37/0", + "interactionId": "interaction-6770daba", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3161457724136572, + -0.1130248676764416, + 5.761063557211832 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-172": { + "name": "托轮", + "nodeName": "托轮", + "nodePath": "0/40/0", + "interactionId": "interaction-68c4b730", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3161457724136572, + -0.11301589671212187, + 5.760970886279441 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-148": { + "name": "导梁推进机构", + "nodeName": "导梁推进机构", + "nodePath": "0/33/0", + "interactionId": "interaction-1bc207e6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.3161457737853004, + -1.0104967206858395, + 6.9852963589055435 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-149": { + "name": "导梁推进机构_1", + "nodeName": "导梁推进机构_1", + "nodePath": "0/33/0/0", + "interactionId": "interaction-afdce241", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-150": { + "name": "导梁推进机构_2", + "nodeName": "导梁推进机构_2", + "nodePath": "0/33/0/1", + "interactionId": "interaction-aedce0ae", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-152": { + "name": "Obj_销齿轮", + "nodeName": "Obj_销齿轮", + "nodePath": "0/34/0", + "interactionId": "interaction-969a0f1b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3161457737853004, + -1.0104571787654397, + 6.985228771834551 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-160": { + "name": "变幅缸", + "nodeName": "变幅缸", + "nodePath": "0/38/0", + "interactionId": "interaction-42e749cf", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.316145687374381, + -0.25901294072285297, + 3.06952481638734 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-161": { + "name": "变幅缸_1", + "nodeName": "变幅缸_1", + "nodePath": "0/38/0/0", + "interactionId": "interaction-6dd1f3b0", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-162": { + "name": "变幅缸_2", + "nodeName": "变幅缸_2", + "nodePath": "0/38/0/1", + "interactionId": "interaction-6ed1f543", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "4f4f4f", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-163": { + "name": "变幅缸_3", + "nodeName": "变幅缸_3", + "nodePath": "0/38/0/2", + "interactionId": "interaction-6fd1f6d6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "929292", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.9, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-164": { + "name": "变幅缸_4", + "nodeName": "变幅缸_4", + "nodePath": "0/38/0/3", + "interactionId": "interaction-70d1f869", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-165": { + "name": "变幅缸_5", + "nodeName": "变幅缸_5", + "nodePath": "0/38/0/4", + "interactionId": "interaction-71d1f9fc", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-166": { + "name": "变幅缸_6", + "nodeName": "变幅缸_6", + "nodePath": "0/38/0/5", + "interactionId": "interaction-72d1fb8f", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-168": { + "name": "调整油缸", + "nodeName": "调整油缸", + "nodePath": "0/39/0", + "interactionId": "interaction-bdbf5104", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.316145861567863, + -0.25902104071976306, + 3.0695673195969326 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-169": { + "name": "调整油缸_1", + "nodeName": "调整油缸_1", + "nodePath": "0/39/0/0", + "interactionId": "interaction-d47c7d13", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-170": { + "name": "调整油缸_2", + "nodeName": "调整油缸_2", + "nodePath": "0/39/0/1", + "interactionId": "interaction-d37c7b80", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-83": { + "name": "滚轮组", + "nodeName": "滚轮组", + "nodePath": "0/15/0", + "interactionId": "interaction-bcfe2406", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3688697145386657, + -0.3732708259369022, + 3.9266870250363364 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-174": { + "name": "移动架_1", + "nodeName": "移动架_1", + "nodePath": "0/41/0", + "interactionId": "interaction-8d4e481b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.3688816467921785, + -0.3732765307734356, + 3.696951254609478 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-175": { + "name": "移动架_1_1", + "nodeName": "移动架_1_1", + "nodePath": "0/41/0/0", + "interactionId": "interaction-9bec7e84", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-176": { + "name": "移动架_1_2", + "nodeName": "移动架_1_2", + "nodePath": "0/41/0/1", + "interactionId": "interaction-9cec8017", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-178": { + "name": "移动架_2", + "nodeName": "移动架_2", + "nodePath": "0/42/0", + "interactionId": "interaction-5e2513ba", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.3688697145386657, + -0.3732722630331281, + 3.696854751420484 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-179": { + "name": "移动架_2_1", + "nodeName": "移动架_2_1", + "nodePath": "0/42/0/0", + "interactionId": "interaction-bdb455ad", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-180": { + "name": "移动架_2_2", + "nodeName": "移动架_2_2", + "nodePath": "0/42/0/1", + "interactionId": "interaction-bcb4541a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-50": { + "name": "托架滚轮组", + "nodeName": "托架滚轮组", + "nodePath": "0/7/0", + "interactionId": "interaction-8d1135ab", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3145652919526403, + -1.0109180900249655, + 1.7384498676566733 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-56": { + "name": "托架体", + "nodeName": "托架体", + "nodePath": "0/9/0", + "interactionId": "interaction-0f0e4c69", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.2350852480784664, + -1.1222546378758222, + 1.7384209515386715 + ], + "rotation": [ + -1.5707963267948966, + 0.08726646040099466, + 0 + ], + "scale": [ + 0.00004494467488937866, + 0.00004494467200874272, + 0.00004494467488937866 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-57": { + "name": "托架体_1", + "nodeName": "托架体_1", + "nodePath": "0/9/0/0", + "interactionId": "interaction-c9c25926", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-58": { + "name": "托架体_2", + "nodeName": "托架体_2", + "nodePath": "0/9/0/1", + "interactionId": "interaction-cac25ab9", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-59": { + "name": "托架体_3", + "nodeName": "托架体_3", + "nodePath": "0/9/0/2", + "interactionId": "interaction-c7c25600", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-61": { + "name": "托架座", + "nodeName": "托架座", + "nodePath": "0/10/0", + "interactionId": "interaction-8dd4efa5", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3145651177591584, + -1.010968562586357, + 1.7384662418439754 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-63": { + "name": "托架变幅油缸", + "nodeName": "托架变幅油缸", + "nodePath": "0/11/0", + "interactionId": "interaction-08acf6da", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.3145651177591584, + -1.0109290642143276, + 1.738503170862146 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-64": { + "name": "托架变幅油缸_1", + "nodeName": "托架变幅油缸_1", + "nodePath": "0/11/0/0", + "interactionId": "interaction-388bf34d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-65": { + "name": "托架变幅油缸_2", + "nodeName": "托架变幅油缸_2", + "nodePath": "0/11/0/1", + "interactionId": "interaction-378bf1ba", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "4f4f4f", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-66": { + "name": "托架变幅油缸_3", + "nodeName": "托架变幅油缸_3", + "nodePath": "0/11/0/2", + "interactionId": "interaction-368bf027", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "929292", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.9, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-67": { + "name": "托架变幅油缸_4", + "nodeName": "托架变幅油缸_4", + "nodePath": "0/11/0/3", + "interactionId": "interaction-358bee94", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-68": { + "name": "托架变幅油缸_5", + "nodeName": "托架变幅油缸_5", + "nodePath": "0/11/0/4", + "interactionId": "interaction-348bed01", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-69": { + "name": "托架变幅油缸_6", + "nodeName": "托架变幅油缸_6", + "nodePath": "0/11/0/5", + "interactionId": "interaction-338beb6e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-76": { + "name": "托架托轮", + "nodeName": "托架托轮", + "nodePath": "0/13/0", + "interactionId": "interaction-120f65d0", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3145652048558993, + -1.010936206147087, + 1.738344654793583 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-52": { + "name": "前推送装置", + "nodeName": "前推送装置", + "nodePath": "0/8/0", + "interactionId": "interaction-8996a1be", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.2808613094338743, + -1.0595352662334152, + 0.18907815325162325 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-53": { + "name": "前推送装置_1", + "nodeName": "前推送装置_1", + "nodePath": "0/8/0/0", + "interactionId": "interaction-30e9aa09", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-54": { + "name": "前推送装置_2", + "nodeName": "前推送装置_2", + "nodePath": "0/8/0/1", + "interactionId": "interaction-2fe9a876", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-48": { + "name": "销齿轮", + "nodeName": "销齿轮", + "nodePath": "0/6/0", + "interactionId": "interaction-e7e90a80", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3161457737853004, + -1.2148948643750737, + 0.007635582405807195 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + } + }, + "assets": [ + { + "code": "MODEL_BRIDGE-ERECTOR-VEHICLE", + "name": "桥梁架设装备整机", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "", + "storageUri": "/models/bridge-erector-vehicle.glb", + "builtIn": true + } + ] + }, + "imported": { + "sha256": "09371b34608116de5842d23abe260bf11acf3e1554daf334a647eb566eee5c49", + "bytes": 369980, + "mutations": [ + { + "status": 200, + "registeredTicket": true, + "sourceName": "bridge-erector-vehicle.glb", + "assetCode": "MODEL_BRIDGE-ERECTOR-VEHICLE" + }, + { + "status": 200, + "registeredTicket": false, + "sourceName": "08-CesiumMilkTruck.glb", + "assetCode": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK" + } + ], + "server": { + "projectId": "156", + "code": "MODEL-3FA24629D59E4509", + "name": "实测模型-牛奶卡车-20260905", + "status": "DRAFT", + "version": 4, + "publishedVersionId": null, + "currentVersionId": "198", + "versionNo": 1, + "checksum": "30ee74fe8f8763e6342f1bbc36607a06db0f6f79061471ab7334e61028029d01", + "schema": "digital-twin-editor-project", + "modelResource": { + "kind": "imported", + "id": "imported-model_mto6wi6k_08-cesiummilktruck", + "name": "08-CesiumMilkTruck", + "assetCode": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "code": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb", + "resourceUrl": "", + "sourceName": "08-CesiumMilkTruck.glb", + "sizeBytes": 369980, + "lastModified": 0, + "mimeType": "model/gltf-binary", + "thumbnail": "", + "vertices": 4823, + "triangles": 3624, + "nodes": 10, + "meshes": 5, + "materials": 5, + "textures": 1, + "animations": 1, + "animationDurationSeconds": 1.25, + "modelMetadata": { + "nodeCount": 10, + "meshCount": 5, + "materialCount": 5, + "textureCount": 1, + "animations": [ + { + "index": 0, + "name": "Wheels", + "start": 0, + "end": 1.25, + "duration": 1.25, + "trackCount": 2 + } + ], + "animationDurationSeconds": 1.25 + }, + "nativeAnimations": [ + { + "index": 0, + "name": "Wheels", + "start": 0, + "end": 1.25, + "duration": 1.25, + "trackCount": 2 + } + ] + }, + "nativeAnimation": { + "clipIndex": 0, + "clipName": "Wheels" + }, + "modelObjects": { + "equipment-root": { + "name": "08-CesiumMilkTruck", + "nodeName": "08-CesiumMilkTruck", + "nodePath": "@root", + "interactionId": "interaction-182987e1", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-0": { + "name": "Scene", + "nodeName": "Scene", + "nodePath": "0", + "interactionId": "interaction-9beb9729", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0.1328080408740111, + -0.00684373075768363 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1.9306168791349512, + 1.9306168791349512, + 1.9306168791349512 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-1": { + "name": "Yup2Zup", + "nodeName": "Yup2Zup", + "nodePath": "0/0", + "interactionId": "interaction-1ba581e6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 1.57079626719025, + 0, + 1.5707963267948966 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-2": { + "name": "Cesium_Milk_Truck", + "nodeName": "Cesium_Milk_Truck", + "nodePath": "0/0/0", + "interactionId": "interaction-004dec41", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-3": { + "name": "Cesium_Milk_Truck_1", + "nodeName": "Cesium_Milk_Truck_1", + "nodePath": "0/0/0/0", + "interactionId": "interaction-5f7e4bee", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-4": { + "name": "Cesium_Milk_Truck_2", + "nodeName": "Cesium_Milk_Truck_2", + "nodePath": "0/0/0/1", + "interactionId": "interaction-607e4d81", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "003928", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-5": { + "name": "Cesium_Milk_Truck_3", + "nodeName": "Cesium_Milk_Truck_3", + "nodePath": "0/0/0/2", + "interactionId": "interaction-5d7e48c8", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "484848", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-6": { + "name": "Node", + "nodeName": "Node", + "nodePath": "0/0/0/3", + "interactionId": "interaction-5e7e4a5b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.432669997215271, + 0, + -0.4277220070362091 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-7": { + "name": "Wheels", + "nodeName": "Wheels", + "nodePath": "0/0/0/3/0", + "interactionId": "interaction-ce2feac4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + -0.1772035344764946, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-8": { + "name": "Node001", + "nodeName": "Node001", + "nodePath": "0/0/0/4", + "interactionId": "interaction-637e523a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + -1.352329969406128, + 0, + -0.4277220070362091 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-9": { + "name": "Wheels001", + "nodeName": "Wheels001", + "nodePath": "0/0/0/4/0", + "interactionId": "interaction-f417f82d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + -0.1772035344764946, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + } + }, + "assets": [ + { + "code": "MODEL_BRIDGE-ERECTOR-VEHICLE", + "name": "桥梁架设装备整机", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "", + "storageUri": "/models/bridge-erector-vehicle.glb", + "builtIn": true + }, + { + "code": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "name": "08-CesiumMilkTruck.glb", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "09371b34608116de5842d23abe260bf11acf3e1554daf334a647eb566eee5c49", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb" + } + ] + }, + "live": { + "sourceName": "08-CesiumMilkTruck.glb", + "assetCode": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "nodes": 10, + "meshes": 5, + "materials": 5, + "clips": [ + { + "name": "Wheels", + "duration": 1.25, + "tracks": 2 + } + ], + "clipIndex": 0, + "playing": false, + "time": 0, + "mesh": { + "name": "Cesium_Milk_Truck", + "editorId": "model-imported-model_mto6wi6k_08-cesiummilktruck-2", + "position": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "isSkinnedMesh": false, + "bones": 0 + }, + "moving": [ + { + "name": "Wheels", + "quaternion": [ + 0, + 0.08848588913679123, + 0, + -0.9960774183273315 + ] + }, + { + "name": "Wheels001", + "quaternion": [ + 0, + 0.08848588913679123, + 0, + -0.9960774183273315 + ] + } + ], + "onlyActivePivot": true + }, + "status": "PASS" + }, + "editBefore": { + "projectId": "156", + "code": "MODEL-3FA24629D59E4509", + "name": "实测模型-牛奶卡车-20260905", + "status": "DRAFT", + "version": 5, + "publishedVersionId": null, + "currentVersionId": "198", + "versionNo": 1, + "checksum": "a96172afc4ddbcc3dfbe7da8c9de272e277a28b8e999de24e4b49f4285a30db6", + "schema": "digital-twin-editor-project", + "modelResource": { + "kind": "imported", + "id": "imported-model_mto6wi6k_08-cesiummilktruck", + "name": "08-CesiumMilkTruck", + "assetCode": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "code": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb", + "resourceUrl": "", + "sourceName": "08-CesiumMilkTruck.glb", + "sizeBytes": 369980, + "lastModified": 0, + "mimeType": "model/gltf-binary", + "thumbnail": "", + "vertices": 4823, + "triangles": 3624, + "nodes": 10, + "meshes": 5, + "materials": 5, + "textures": 1, + "animations": 1, + "animationDurationSeconds": 1.25, + "modelMetadata": { + "nodeCount": 10, + "meshCount": 5, + "materialCount": 5, + "textureCount": 1, + "animations": [ + { + "index": 0, + "name": "Wheels", + "start": 0, + "end": 1.25, + "duration": 1.25, + "trackCount": 2 + } + ], + "animationDurationSeconds": 1.25 + }, + "nativeAnimations": [ + { + "index": 0, + "name": "Wheels", + "start": 0, + "end": 1.25, + "duration": 1.25, + "trackCount": 2 + } + ] + }, + "nativeAnimation": { + "clipIndex": 0, + "clipName": "Wheels" + }, + "modelObjects": { + "equipment-root": { + "name": "08-CesiumMilkTruck", + "nodeName": "08-CesiumMilkTruck", + "nodePath": "@root", + "interactionId": "interaction-182987e1", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-0": { + "name": "Scene", + "nodeName": "Scene", + "nodePath": "0", + "interactionId": "interaction-9beb9729", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0.1328080408740111, + -0.00684373075768363 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1.9306168791349512, + 1.9306168791349512, + 1.9306168791349512 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-1": { + "name": "Yup2Zup", + "nodeName": "Yup2Zup", + "nodePath": "0/0", + "interactionId": "interaction-1ba581e6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 1.57079626719025, + 0, + 1.5707963267948966 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-2": { + "name": "Cesium_Milk_Truck", + "nodeName": "Cesium_Milk_Truck", + "nodePath": "0/0/0", + "interactionId": "interaction-004dec41", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-3": { + "name": "Cesium_Milk_Truck_1", + "nodeName": "Cesium_Milk_Truck_1", + "nodePath": "0/0/0/0", + "interactionId": "interaction-5f7e4bee", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-4": { + "name": "Cesium_Milk_Truck_2", + "nodeName": "Cesium_Milk_Truck_2", + "nodePath": "0/0/0/1", + "interactionId": "interaction-607e4d81", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "003928", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-5": { + "name": "Cesium_Milk_Truck_3", + "nodeName": "Cesium_Milk_Truck_3", + "nodePath": "0/0/0/2", + "interactionId": "interaction-5d7e48c8", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "484848", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-6": { + "name": "Node", + "nodeName": "Node", + "nodePath": "0/0/0/3", + "interactionId": "interaction-5e7e4a5b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.432669997215271, + 0, + -0.4277220070362091 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-7": { + "name": "Wheels", + "nodeName": "Wheels", + "nodePath": "0/0/0/3/0", + "interactionId": "interaction-ce2feac4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + -0.1772035344764946, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-8": { + "name": "Node001", + "nodeName": "Node001", + "nodePath": "0/0/0/4", + "interactionId": "interaction-637e523a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + -1.352329969406128, + 0, + -0.4277220070362091 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-9": { + "name": "Wheels001", + "nodeName": "Wheels001", + "nodePath": "0/0/0/4/0", + "interactionId": "interaction-f417f82d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + -0.1772035344764946, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + } + }, + "assets": [ + { + "code": "MODEL_BRIDGE-ERECTOR-VEHICLE", + "name": "桥梁架设装备整机", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "", + "storageUri": "/models/bridge-erector-vehicle.glb", + "builtIn": true + }, + { + "code": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "name": "08-CesiumMilkTruck.glb", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "09371b34608116de5842d23abe260bf11acf3e1554daf334a647eb566eee5c49", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb" + } + ] + }, + "expectedX": 0.35, + "edited": { + "server": { + "projectId": "156", + "code": "MODEL-3FA24629D59E4509", + "name": "实测模型-牛奶卡车-20260905", + "status": "DRAFT", + "version": 6, + "publishedVersionId": null, + "currentVersionId": "198", + "versionNo": 1, + "checksum": "495aaedac19971b06dec73ad43bdebfcfb63d0604fabaf48f460c7bc1cdcc229", + "schema": "digital-twin-editor-project", + "modelResource": { + "kind": "imported", + "id": "imported-model_mto6wi6k_08-cesiummilktruck", + "name": "08-CesiumMilkTruck", + "assetCode": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "code": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb", + "resourceUrl": "", + "sourceName": "08-CesiumMilkTruck.glb", + "sizeBytes": 369980, + "lastModified": 0, + "mimeType": "model/gltf-binary", + "thumbnail": "", + "vertices": 4823, + "triangles": 3624, + "nodes": 10, + "meshes": 5, + "materials": 5, + "textures": 1, + "animations": 1, + "animationDurationSeconds": 1.25, + "modelMetadata": { + "nodeCount": 10, + "meshCount": 5, + "materialCount": 5, + "textureCount": 1, + "animations": [ + { + "index": 0, + "name": "Wheels", + "start": 0, + "end": 1.25, + "duration": 1.25, + "trackCount": 2 + } + ], + "animationDurationSeconds": 1.25 + }, + "nativeAnimations": [ + { + "index": 0, + "name": "Wheels", + "start": 0, + "end": 1.25, + "duration": 1.25, + "trackCount": 2 + } + ] + }, + "nativeAnimation": { + "clipIndex": 0, + "clipName": "Wheels" + }, + "modelObjects": { + "equipment-root": { + "name": "08-CesiumMilkTruck", + "nodeName": "08-CesiumMilkTruck", + "nodePath": "@root", + "interactionId": "interaction-182987e1", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-0": { + "name": "Scene", + "nodeName": "Scene", + "nodePath": "0", + "interactionId": "interaction-9beb9729", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0.1328080408740111, + -0.00684373075768363 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1.9306168791349512, + 1.9306168791349512, + 1.9306168791349512 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-1": { + "name": "Yup2Zup", + "nodeName": "Yup2Zup", + "nodePath": "0/0", + "interactionId": "interaction-1ba581e6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 1.57079626719025, + 0, + 1.5707963267948966 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-2": { + "name": "Cesium_Milk_Truck", + "nodeName": "Cesium_Milk_Truck", + "nodePath": "0/0/0", + "interactionId": "interaction-004dec41", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0.35, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-3": { + "name": "Cesium_Milk_Truck_1", + "nodeName": "Cesium_Milk_Truck_1", + "nodePath": "0/0/0/0", + "interactionId": "interaction-5f7e4bee", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-4": { + "name": "Cesium_Milk_Truck_2", + "nodeName": "Cesium_Milk_Truck_2", + "nodePath": "0/0/0/1", + "interactionId": "interaction-607e4d81", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "003928", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-5": { + "name": "Cesium_Milk_Truck_3", + "nodeName": "Cesium_Milk_Truck_3", + "nodePath": "0/0/0/2", + "interactionId": "interaction-5d7e48c8", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "484848", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-6": { + "name": "Node", + "nodeName": "Node", + "nodePath": "0/0/0/3", + "interactionId": "interaction-5e7e4a5b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.432669997215271, + 0, + -0.4277220070362091 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-7": { + "name": "Wheels", + "nodeName": "Wheels", + "nodePath": "0/0/0/3/0", + "interactionId": "interaction-ce2feac4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + -0.1772035344764946, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-8": { + "name": "Node001", + "nodeName": "Node001", + "nodePath": "0/0/0/4", + "interactionId": "interaction-637e523a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + -1.352329969406128, + 0, + -0.4277220070362091 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-9": { + "name": "Wheels001", + "nodeName": "Wheels001", + "nodePath": "0/0/0/4/0", + "interactionId": "interaction-f417f82d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + -0.1772035344764946, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + } + }, + "assets": [ + { + "code": "MODEL_BRIDGE-ERECTOR-VEHICLE", + "name": "桥梁架设装备整机", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "", + "storageUri": "/models/bridge-erector-vehicle.glb", + "builtIn": true + }, + { + "code": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "name": "08-CesiumMilkTruck.glb", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "09371b34608116de5842d23abe260bf11acf3e1554daf334a647eb566eee5c49", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb" + } + ] + }, + "live": { + "sourceName": "08-CesiumMilkTruck.glb", + "assetCode": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "nodes": 10, + "meshes": 5, + "materials": 5, + "clips": [ + { + "name": "Wheels", + "duration": 1.25, + "tracks": 2 + } + ], + "clipIndex": 0, + "playing": false, + "time": 0, + "mesh": { + "name": "Cesium_Milk_Truck", + "editorId": "model-imported-model_mto6wi6k_08-cesiummilktruck-2", + "position": [ + 0.35, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "isSkinnedMesh": false, + "bones": 0 + }, + "moving": [ + { + "name": "Wheels", + "quaternion": [ + 0, + 0.08848588913679123, + 0, + -0.9960774183273315 + ] + }, + { + "name": "Wheels001", + "quaternion": [ + 0, + 0.08848588913679123, + 0, + -0.9960774183273315 + ] + } + ], + "onlyActivePivot": true + }, + "status": "PASS" + }, + "reopened": { + "server": { + "projectId": "156", + "code": "MODEL-3FA24629D59E4509", + "name": "实测模型-牛奶卡车-20260905", + "status": "DRAFT", + "version": 6, + "publishedVersionId": null, + "currentVersionId": "198", + "versionNo": 1, + "checksum": "495aaedac19971b06dec73ad43bdebfcfb63d0604fabaf48f460c7bc1cdcc229", + "schema": "digital-twin-editor-project", + "modelResource": { + "kind": "imported", + "id": "imported-model_mto6wi6k_08-cesiummilktruck", + "name": "08-CesiumMilkTruck", + "assetCode": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "code": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb", + "resourceUrl": "", + "sourceName": "08-CesiumMilkTruck.glb", + "sizeBytes": 369980, + "lastModified": 0, + "mimeType": "model/gltf-binary", + "thumbnail": "", + "vertices": 4823, + "triangles": 3624, + "nodes": 10, + "meshes": 5, + "materials": 5, + "textures": 1, + "animations": 1, + "animationDurationSeconds": 1.25, + "modelMetadata": { + "nodeCount": 10, + "meshCount": 5, + "materialCount": 5, + "textureCount": 1, + "animations": [ + { + "index": 0, + "name": "Wheels", + "start": 0, + "end": 1.25, + "duration": 1.25, + "trackCount": 2 + } + ], + "animationDurationSeconds": 1.25 + }, + "nativeAnimations": [ + { + "index": 0, + "name": "Wheels", + "start": 0, + "end": 1.25, + "duration": 1.25, + "trackCount": 2 + } + ] + }, + "nativeAnimation": { + "clipIndex": 0, + "clipName": "Wheels" + }, + "modelObjects": { + "equipment-root": { + "name": "08-CesiumMilkTruck", + "nodeName": "08-CesiumMilkTruck", + "nodePath": "@root", + "interactionId": "interaction-182987e1", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-0": { + "name": "Scene", + "nodeName": "Scene", + "nodePath": "0", + "interactionId": "interaction-9beb9729", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0.1328080408740111, + -0.00684373075768363 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1.9306168791349512, + 1.9306168791349512, + 1.9306168791349512 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-1": { + "name": "Yup2Zup", + "nodeName": "Yup2Zup", + "nodePath": "0/0", + "interactionId": "interaction-1ba581e6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 1.57079626719025, + 0, + 1.5707963267948966 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-2": { + "name": "Cesium_Milk_Truck", + "nodeName": "Cesium_Milk_Truck", + "nodePath": "0/0/0", + "interactionId": "interaction-004dec41", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0.35, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-3": { + "name": "Cesium_Milk_Truck_1", + "nodeName": "Cesium_Milk_Truck_1", + "nodePath": "0/0/0/0", + "interactionId": "interaction-5f7e4bee", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-4": { + "name": "Cesium_Milk_Truck_2", + "nodeName": "Cesium_Milk_Truck_2", + "nodePath": "0/0/0/1", + "interactionId": "interaction-607e4d81", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "003928", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-5": { + "name": "Cesium_Milk_Truck_3", + "nodeName": "Cesium_Milk_Truck_3", + "nodePath": "0/0/0/2", + "interactionId": "interaction-5d7e48c8", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "484848", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-6": { + "name": "Node", + "nodeName": "Node", + "nodePath": "0/0/0/3", + "interactionId": "interaction-5e7e4a5b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.432669997215271, + 0, + -0.4277220070362091 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-7": { + "name": "Wheels", + "nodeName": "Wheels", + "nodePath": "0/0/0/3/0", + "interactionId": "interaction-ce2feac4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + -0.1772035344764946, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-8": { + "name": "Node001", + "nodeName": "Node001", + "nodePath": "0/0/0/4", + "interactionId": "interaction-637e523a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + -1.352329969406128, + 0, + -0.4277220070362091 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-9": { + "name": "Wheels001", + "nodeName": "Wheels001", + "nodePath": "0/0/0/4/0", + "interactionId": "interaction-f417f82d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + -0.1772035344764946, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + } + }, + "assets": [ + { + "code": "MODEL_BRIDGE-ERECTOR-VEHICLE", + "name": "桥梁架设装备整机", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "", + "storageUri": "/models/bridge-erector-vehicle.glb", + "builtIn": true + }, + { + "code": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "name": "08-CesiumMilkTruck.glb", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "09371b34608116de5842d23abe260bf11acf3e1554daf334a647eb566eee5c49", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb" + } + ] + }, + "live": { + "sourceName": "08-CesiumMilkTruck.glb", + "assetCode": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "nodes": 10, + "meshes": 5, + "materials": 5, + "clips": [ + { + "name": "Wheels", + "duration": 1.25, + "tracks": 2 + } + ], + "clipIndex": 0, + "playing": false, + "time": 0, + "mesh": { + "name": "Cesium_Milk_Truck", + "editorId": "model-imported-model_mto6wi6k_08-cesiummilktruck-2", + "position": [ + 0.35, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "isSkinnedMesh": false, + "bones": 0 + }, + "moving": [ + { + "name": "Wheels", + "quaternion": [ + 0, + -0.08848588805258345, + 0, + 0.9960774305321578 + ] + }, + { + "name": "Wheels001", + "quaternion": [ + 0, + -0.08848588805258345, + 0, + 0.9960774305321578 + ] + } + ], + "onlyActivePivot": true + }, + "status": "PASS" + }, + "animation": { + "clip": "Wheels", + "before": { + "sourceName": "08-CesiumMilkTruck.glb", + "assetCode": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "nodes": 10, + "meshes": 5, + "materials": 5, + "clips": [ + { + "name": "Wheels", + "duration": 1.25, + "tracks": 2 + } + ], + "clipIndex": 0, + "playing": true, + "time": 0.017299999952316285, + "mesh": { + "name": "Cesium_Milk_Truck", + "editorId": "model-imported-model_mto6wi6k_08-cesiummilktruck-2", + "position": [ + 0.35, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "isSkinnedMesh": false, + "bones": 0 + }, + "moving": [ + { + "name": "Wheels", + "quaternion": [ + 0, + -0.13047994768115828, + 0, + 0.9914509466299196 + ] + }, + { + "name": "Wheels001", + "quaternion": [ + 0, + -0.13047994768115828, + 0, + 0.9914509466299196 + ] + } + ], + "onlyActivePivot": true + }, + "after": { + "sourceName": "08-CesiumMilkTruck.glb", + "assetCode": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "nodes": 10, + "meshes": 5, + "materials": 5, + "clips": [ + { + "name": "Wheels", + "duration": 1.25, + "tracks": 2 + } + ], + "clipIndex": 0, + "playing": true, + "time": 0.11699999999999999, + "mesh": { + "name": "Cesium_Milk_Truck", + "editorId": "model-imported-model_mto6wi6k_08-cesiummilktruck-2", + "position": [ + 0.35, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "isSkinnedMesh": false, + "bones": 0 + }, + "moving": [ + { + "name": "Wheels", + "quaternion": [ + 0, + -0.36567363439496653, + 0, + 0.9307431551377918 + ] + }, + { + "name": "Wheels001", + "quaternion": [ + 0, + -0.36567363439496653, + 0, + 0.9307431551377918 + ] + } + ], + "onlyActivePivot": true + }, + "movingChanged": true, + "status": "PASS" + }, + "materialCheck": { + "node": "Cesium_Milk_Truck_1", + "roughness": 0.3, + "persistedAfterReload": true + }, + "published": { + "projectId": "156", + "code": "MODEL-3FA24629D59E4509", + "name": "实测模型-牛奶卡车-已验证-20260905", + "status": "PUBLISHED", + "version": 12, + "publishedVersionId": "200", + "currentVersionId": "200", + "versionNo": 2, + "checksum": "1c9b1233dda661537c9bd4014208f1eb2851d392e5cd9b4260e53570b0820751", + "schema": "digital-twin-editor-project", + "modelResource": { + "kind": "imported", + "id": "imported-model_mto6wi6k_08-cesiummilktruck", + "name": "08-CesiumMilkTruck", + "assetCode": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "code": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb", + "resourceUrl": "", + "sourceName": "08-CesiumMilkTruck.glb", + "sizeBytes": 369980, + "lastModified": 0, + "mimeType": "model/gltf-binary", + "thumbnail": "", + "vertices": 4823, + "triangles": 3624, + "nodes": 10, + "meshes": 5, + "materials": 5, + "textures": 1, + "animations": 1, + "animationDurationSeconds": 1.25, + "modelMetadata": { + "nodeCount": 10, + "meshCount": 5, + "materialCount": 5, + "textureCount": 1, + "animations": [ + { + "index": 0, + "name": "Wheels", + "start": 0, + "end": 1.25, + "duration": 1.25, + "trackCount": 2 + } + ], + "animationDurationSeconds": 1.25 + }, + "nativeAnimations": [ + { + "index": 0, + "name": "Wheels", + "start": 0, + "end": 1.25, + "duration": 1.25, + "trackCount": 2 + } + ] + }, + "nativeAnimation": { + "clipIndex": 0, + "clipName": "Wheels" + }, + "modelObjects": { + "equipment-root": { + "name": "08-CesiumMilkTruck", + "nodeName": "08-CesiumMilkTruck", + "nodePath": "@root", + "interactionId": "interaction-182987e1", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-0": { + "name": "Scene", + "nodeName": "Scene", + "nodePath": "0", + "interactionId": "interaction-9beb9729", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0.1328080408740111, + -0.00684373075768363 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1.9306168791349512, + 1.9306168791349512, + 1.9306168791349512 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-1": { + "name": "Yup2Zup", + "nodeName": "Yup2Zup", + "nodePath": "0/0", + "interactionId": "interaction-1ba581e6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 1.57079626719025, + 0, + 1.5707963267948966 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-2": { + "name": "Cesium_Milk_Truck", + "nodeName": "Cesium_Milk_Truck", + "nodePath": "0/0/0", + "interactionId": "interaction-004dec41", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0.35, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-3": { + "name": "Cesium_Milk_Truck_1", + "nodeName": "Cesium_Milk_Truck_1", + "nodePath": "0/0/0/0", + "interactionId": "interaction-5f7e4bee", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-4": { + "name": "Cesium_Milk_Truck_2", + "nodeName": "Cesium_Milk_Truck_2", + "nodePath": "0/0/0/1", + "interactionId": "interaction-607e4d81", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "003928", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-5": { + "name": "Cesium_Milk_Truck_3", + "nodeName": "Cesium_Milk_Truck_3", + "nodePath": "0/0/0/2", + "interactionId": "interaction-5d7e48c8", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "484848", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-6": { + "name": "Node", + "nodeName": "Node", + "nodePath": "0/0/0/3", + "interactionId": "interaction-5e7e4a5b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.432669997215271, + 0, + -0.4277220070362091 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-7": { + "name": "Wheels", + "nodeName": "Wheels", + "nodePath": "0/0/0/3/0", + "interactionId": "interaction-ce2feac4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + -3.141592653589793, + -0.603571861900947, + -3.141592653589793 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-8": { + "name": "Node001", + "nodeName": "Node001", + "nodePath": "0/0/0/4", + "interactionId": "interaction-637e523a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + -1.352329969406128, + 0, + -0.4277220070362091 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-9": { + "name": "Wheels001", + "nodeName": "Wheels001", + "nodePath": "0/0/0/4/0", + "interactionId": "interaction-f417f82d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + -3.141592653589793, + -0.603571861900947, + -3.141592653589793 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + } + }, + "assets": [ + { + "code": "MODEL_BRIDGE-ERECTOR-VEHICLE", + "name": "桥梁架设装备整机", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "", + "storageUri": "/models/bridge-erector-vehicle.glb", + "builtIn": true + }, + { + "code": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "name": "08-CesiumMilkTruck.glb", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "09371b34608116de5842d23abe260bf11acf3e1554daf334a647eb566eee5c49", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb" + } + ], + "updateTime": "2026-09-05T17:47:29" + }, + "freshSession": { + "status": "PASS", + "live": { + "source": "08-CesiumMilkTruck.glb", + "apiMode": true, + "clip": "Wheels" + }, + "server": { + "projectId": "156", + "code": "MODEL-3FA24629D59E4509", + "name": "实测模型-牛奶卡车-已验证-20260905", + "status": "PUBLISHED", + "version": 12, + "publishedVersionId": "200", + "currentVersionId": "200", + "versionNo": 2, + "checksum": "1c9b1233dda661537c9bd4014208f1eb2851d392e5cd9b4260e53570b0820751", + "schema": "digital-twin-editor-project", + "modelResource": { + "kind": "imported", + "id": "imported-model_mto6wi6k_08-cesiummilktruck", + "name": "08-CesiumMilkTruck", + "assetCode": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "code": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb", + "resourceUrl": "", + "sourceName": "08-CesiumMilkTruck.glb", + "sizeBytes": 369980, + "lastModified": 0, + "mimeType": "model/gltf-binary", + "thumbnail": "", + "vertices": 4823, + "triangles": 3624, + "nodes": 10, + "meshes": 5, + "materials": 5, + "textures": 1, + "animations": 1, + "animationDurationSeconds": 1.25, + "modelMetadata": { + "nodeCount": 10, + "meshCount": 5, + "materialCount": 5, + "textureCount": 1, + "animations": [ + { + "index": 0, + "name": "Wheels", + "start": 0, + "end": 1.25, + "duration": 1.25, + "trackCount": 2 + } + ], + "animationDurationSeconds": 1.25 + }, + "nativeAnimations": [ + { + "index": 0, + "name": "Wheels", + "start": 0, + "end": 1.25, + "duration": 1.25, + "trackCount": 2 + } + ] + }, + "nativeAnimation": { + "clipIndex": 0, + "clipName": "Wheels" + }, + "modelObjects": { + "equipment-root": { + "name": "08-CesiumMilkTruck", + "nodeName": "08-CesiumMilkTruck", + "nodePath": "@root", + "interactionId": "interaction-182987e1", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-0": { + "name": "Scene", + "nodeName": "Scene", + "nodePath": "0", + "interactionId": "interaction-9beb9729", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0.1328080408740111, + -0.00684373075768363 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1.9306168791349512, + 1.9306168791349512, + 1.9306168791349512 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-1": { + "name": "Yup2Zup", + "nodeName": "Yup2Zup", + "nodePath": "0/0", + "interactionId": "interaction-1ba581e6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 1.57079626719025, + 0, + 1.5707963267948966 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-2": { + "name": "Cesium_Milk_Truck", + "nodeName": "Cesium_Milk_Truck", + "nodePath": "0/0/0", + "interactionId": "interaction-004dec41", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0.35, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-3": { + "name": "Cesium_Milk_Truck_1", + "nodeName": "Cesium_Milk_Truck_1", + "nodePath": "0/0/0/0", + "interactionId": "interaction-5f7e4bee", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-4": { + "name": "Cesium_Milk_Truck_2", + "nodeName": "Cesium_Milk_Truck_2", + "nodePath": "0/0/0/1", + "interactionId": "interaction-607e4d81", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "003928", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-5": { + "name": "Cesium_Milk_Truck_3", + "nodeName": "Cesium_Milk_Truck_3", + "nodePath": "0/0/0/2", + "interactionId": "interaction-5d7e48c8", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "484848", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-6": { + "name": "Node", + "nodeName": "Node", + "nodePath": "0/0/0/3", + "interactionId": "interaction-5e7e4a5b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.432669997215271, + 0, + -0.4277220070362091 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-7": { + "name": "Wheels", + "nodeName": "Wheels", + "nodePath": "0/0/0/3/0", + "interactionId": "interaction-ce2feac4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + -3.141592653589793, + -0.603571861900947, + -3.141592653589793 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-8": { + "name": "Node001", + "nodeName": "Node001", + "nodePath": "0/0/0/4", + "interactionId": "interaction-637e523a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + -1.352329969406128, + 0, + -0.4277220070362091 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6wi6k_08-cesiummilktruck-9": { + "name": "Wheels001", + "nodeName": "Wheels001", + "nodePath": "0/0/0/4/0", + "interactionId": "interaction-f417f82d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + -3.141592653589793, + -0.603571861900947, + -3.141592653589793 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 1, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + } + }, + "assets": [ + { + "code": "MODEL_BRIDGE-ERECTOR-VEHICLE", + "name": "桥梁架设装备整机", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "", + "storageUri": "/models/bridge-erector-vehicle.glb", + "builtIn": true + }, + { + "code": "MODEL_MTO6WI6K_08-CESIUMMILKTRUCK", + "name": "08-CesiumMilkTruck.glb", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "09371b34608116de5842d23abe260bf11acf3e1554daf334a647eb566eee5c49", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb" + } + ] + } + }, + "retained": true, + "timestampCheck": { + "status": "PASS", + "before": { + "project": "2026-09-05T17:24:34", + "version": "2026-09-05T17:24:34" + }, + "after": { + "project": "2026-09-05T17:47:05", + "version": "2026-09-05T17:47:05" + }, + "draftVersionId": "200", + "versionNo": 2 + } + }, + { + "index": 1, + "name": "实测模型-狐狸动画-已验证-20260905", + "file": "09-Fox.glb", + "mesh": "fox", + "clip": "2", + "clipName": "Run", + "clips": 3, + "description": "轻量 GLB 实测:骨骼蒙皮、Survey/Walk/Run 动画、节点编辑、保存重开和发布。保留供后续模型/场景测试使用。", + "id": "157", + "code": "MODEL-70875AA932B94685", + "steps": [ + { + "step": "UI创建项目", + "status": "PASS", + "httpStatus": 200 + }, + { + "step": "GLB上传、两阶段绑定、SHA256与活跃模型核验", + "status": "PASS", + "screenshot": "screenshots/2-01-imported.png" + }, + { + "step": "节点 X 位置、材质粗糙度、原生动画选择保存", + "status": "PASS", + "details": { + "x": 0.25, + "roughness": 0.3, + "clip": "Run", + "versionBefore": 4, + "versionAfter": 5 + }, + "screenshot": "screenshots/2-02-edited.png" + }, + { + "step": "整页刷新后模型、节点、材质、动画选择恢复", + "status": "PASS", + "screenshot": "screenshots/2-03-reopened.png" + }, + { + "step": "原生动画实播:播放时间与轮子/骨骼姿态确实变化", + "status": "PASS", + "screenshot": "screenshots/2-04-animation.png" + }, + { + "step": "Survey、Walk、Run 三个原生片段逐一实播", + "status": "PASS", + "details": [ + { + "name": "Survey", + "playing": true, + "timeAdvanced": true, + "bonesChanged": true + }, + { + "name": "Walk", + "playing": true, + "timeAdvanced": true, + "bonesChanged": true + }, + { + "name": "Run", + "playing": true, + "timeAdvanced": true, + "bonesChanged": true + } + ] + }, + { + "step": "发布到场景资源库并核对服务端发布版本", + "status": "PASS", + "httpStatus": 200, + "screenshot": "screenshots/2-05-published.png" + }, + { + "step": "全新浏览器上下文从服务端载入已发布模型", + "status": "PASS", + "details": { + "source": "09-Fox.glb", + "apiMode": true, + "clip": "Run" + }, + "screenshot": "screenshots/2-06-fresh-session.png" + }, + { + "step": "已发布模型改名保存为 V2 草稿,项目及版本更新时间刷新", + "status": "PASS", + "details": { + "status": "PASS", + "before": { + "project": "2026-09-05T17:33:10", + "version": "2026-09-05T17:33:10" + }, + "after": { + "project": "2026-09-05T17:47:39", + "version": "2026-09-05T17:47:39" + }, + "draftVersionId": "201", + "versionNo": 2 + }, + "screenshot": "screenshots/2-07-update-time.png" + }, + { + "step": "V2 重新发布成功,发布版本及更新时间正确", + "status": "PASS", + "details": { + "versionNo": 2, + "versionId": "201", + "updateTime": "2026-09-05T17:48:04" + }, + "screenshot": "screenshots/2-08-published-v2.png" + }, + { + "step": "V2 全新浏览器上下文重开,模型文件、动画选择、发布版本均正确", + "status": "PASS", + "details": { + "source": "09-Fox.glb", + "clip": "Run", + "versionNo": 2 + }, + "screenshot": "screenshots/2-09-fresh-session-v2.png" + } + ], + "before": { + "projectId": "157", + "code": "MODEL-70875AA932B94685", + "name": "实测模型-狐狸动画-20260905", + "status": "DRAFT", + "version": 2, + "publishedVersionId": null, + "currentVersionId": "199", + "versionNo": 1, + "checksum": "b5f6edbc00ebd54a4891626b1c25f6e98ca934d611fb2ba93589f7278ea12711", + "schema": "digital-twin-editor-project", + "modelResource": { + "kind": "builtin", + "id": "bridge-erector-vehicle", + "name": "桥梁架设装备整机", + "assetCode": "MODEL_BRIDGE-ERECTOR-VEHICLE", + "code": "MODEL_BRIDGE-ERECTOR-VEHICLE", + "storageUri": "/models/bridge-erector-vehicle.glb", + "resourceUrl": "/models/bridge-erector-vehicle.glb", + "sourceName": "bridge-erector-vehicle.glb", + "sizeBytes": 31140540, + "lastModified": 0, + "mimeType": "model/gltf-binary", + "thumbnail": "/models/bridge-erector-vehicle-thumb.png", + "vertices": 574222, + "triangles": 436616, + "nodes": 186, + "meshes": 114, + "materials": 114, + "textures": 5, + "animations": 0, + "animationDurationSeconds": 0, + "modelMetadata": { + "nodeCount": 186, + "meshCount": 114, + "materialCount": 114, + "textureCount": 5, + "animations": [], + "animationDurationSeconds": 0 + }, + "nativeAnimations": [] + }, + "nativeAnimation": { + "clipIndex": 0, + "clipName": "" + }, + "modelObjects": { + "equipment-root": { + "name": "桥梁架设装备整机", + "nodeName": "桥梁架设装备整机", + "nodePath": "@root", + "interactionId": "interaction-fc0e9f4a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-0": { + "name": "", + "nodeName": "Group", + "nodePath": "0", + "interactionId": "interaction-1223a52e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 7.463825679732139e-8, + 0.7182123701337901, + 0.15487073466297074 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1.1415944032239054, + 1.1415944032239054, + 1.1415944032239054 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-1": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/0", + "interactionId": "interaction-ed434099", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529039764404296, + 0.05721450805664063, + 3.316722412109375 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-2": { + "name": "底盘车_3", + "nodeName": "底盘车_3", + "nodePath": "0/0/0", + "interactionId": "interaction-12d89236", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-3": { + "name": "底盘车_3_1", + "nodeName": "底盘车_3_1", + "nodePath": "0/0/0/0", + "interactionId": "interaction-daa5ef71", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "4f4f4f", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-4": { + "name": "底盘车_3_2", + "nodeName": "底盘车_3_2", + "nodePath": "0/0/0/1", + "interactionId": "interaction-d9a5edde", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "929292", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.9, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-5": { + "name": "底盘车_3_3", + "nodeName": "底盘车_3_3", + "nodePath": "0/0/0/2", + "interactionId": "interaction-d8a5ec4b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-6": { + "name": "底盘车_3_4", + "nodeName": "底盘车_3_4", + "nodePath": "0/0/0/3", + "interactionId": "interaction-d7a5eab8", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-7": { + "name": "底盘车_3_5", + "nodeName": "底盘车_3_5", + "nodePath": "0/0/0/4", + "interactionId": "interaction-dea5f5bd", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-8": { + "name": "底盘车_3_6", + "nodeName": "底盘车_3_6", + "nodePath": "0/0/0/5", + "interactionId": "interaction-dda5f42a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-9": { + "name": "底盘车_3_7", + "nodeName": "底盘车_3_7", + "nodePath": "0/0/0/6", + "interactionId": "interaction-dca5f297", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-10": { + "name": "底盘车_3_8", + "nodeName": "底盘车_3_8", + "nodePath": "0/0/0/7", + "interactionId": "interaction-dba5f104", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "404040", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-11": { + "name": "底盘车_3_9", + "nodeName": "底盘车_3_9", + "nodePath": "0/0/0/8", + "interactionId": "interaction-d2a5e2d9", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "cbcbcb", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.9, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-12": { + "name": "底盘车_3_10", + "nodeName": "底盘车_3_10", + "nodePath": "0/0/0/9", + "interactionId": "interaction-d1a5e146", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "749f62", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-13": { + "name": "底盘车_3_11", + "nodeName": "底盘车_3_11", + "nodePath": "0/0/0/10", + "interactionId": "interaction-8e358daa", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-14": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/1", + "interactionId": "interaction-ec433f06", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.152912826538086, + 0.05720820426940918, + 3.31687255859375 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-15": { + "name": "底盘车_5", + "nodeName": "底盘车_5", + "nodePath": "0/1/0", + "interactionId": "interaction-b800bd61", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-16": { + "name": "底盘车_5_1", + "nodeName": "底盘车_5_1", + "nodePath": "0/1/0/0", + "interactionId": "interaction-11211c8e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "4f4f4f", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-17": { + "name": "底盘车_5_2", + "nodeName": "底盘车_5_2", + "nodePath": "0/1/0/1", + "interactionId": "interaction-12211e21", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "929292", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.9, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-18": { + "name": "底盘车_5_3", + "nodeName": "底盘车_5_3", + "nodePath": "0/1/0/2", + "interactionId": "interaction-0f211968", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-19": { + "name": "底盘车_5_4", + "nodeName": "底盘车_5_4", + "nodePath": "0/1/0/3", + "interactionId": "interaction-10211afb", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-20": { + "name": "底盘车_5_5", + "nodeName": "底盘车_5_5", + "nodePath": "0/1/0/4", + "interactionId": "interaction-152122da", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-21": { + "name": "底盘车_5_6", + "nodeName": "底盘车_5_6", + "nodePath": "0/1/0/5", + "interactionId": "interaction-1621246d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.45, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-22": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/2", + "interactionId": "interaction-eb433d73", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529016876220703, + 0.057205944061279296, + 3.3168429565429687 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-23": { + "name": "底盘车_1", + "nodeName": "底盘车_1", + "nodePath": "0/2/0", + "interactionId": "interaction-bc8a1bec", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-24": { + "name": "底盘车_1_1", + "nodeName": "底盘车_1_1", + "nodePath": "0/2/0/0", + "interactionId": "interaction-1f66056b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-25": { + "name": "底盘车_1_2", + "nodeName": "底盘车_1_2", + "nodePath": "0/2/0/1", + "interactionId": "interaction-1e6603d8", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-26": { + "name": "底盘车_1_3", + "nodeName": "底盘车_1_3", + "nodePath": "0/2/0/2", + "interactionId": "interaction-21660891", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-27": { + "name": "底盘车_1_4", + "nodeName": "底盘车_1_4", + "nodePath": "0/2/0/3", + "interactionId": "interaction-206606fe", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-28": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/3", + "interactionId": "interaction-ea433be0", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529024505615235, + 0.05720912456512451, + 3.31684814453125 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-29": { + "name": "底盘车_7", + "nodeName": "底盘车_7", + "nodePath": "0/3/0", + "interactionId": "interaction-61b24717", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-30": { + "name": "底盘车_7_1", + "nodeName": "底盘车_7_1", + "nodePath": "0/3/0/0", + "interactionId": "interaction-d67fccc8", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-31": { + "name": "底盘车_7_2", + "nodeName": "底盘车_7_2", + "nodePath": "0/3/0/1", + "interactionId": "interaction-d77fce5b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-32": { + "name": "底盘车_7_3", + "nodeName": "底盘车_7_3", + "nodePath": "0/3/0/2", + "interactionId": "interaction-d87fcfee", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-33": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/4", + "interactionId": "interaction-f14346e5", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1524486541748047, + 0.05721979141235352, + 3.316885681152344 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-34": { + "name": "底盘车_6", + "nodeName": "底盘车_6", + "nodePath": "0/4/0", + "interactionId": "interaction-5de8014a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-35": { + "name": "底盘车_6_1", + "nodeName": "底盘车_6_1", + "nodePath": "0/4/0/0", + "interactionId": "interaction-e59c68dd", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "4f4f4f", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-36": { + "name": "底盘车_6_2", + "nodeName": "底盘车_6_2", + "nodePath": "0/4/0/1", + "interactionId": "interaction-e49c674a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "929292", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.9, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-37": { + "name": "底盘车_6_3", + "nodeName": "底盘车_6_3", + "nodePath": "0/4/0/2", + "interactionId": "interaction-e39c65b7", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3b76d0", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-38": { + "name": "底盘车_6_4", + "nodeName": "底盘车_6_4", + "nodePath": "0/4/0/3", + "interactionId": "interaction-e29c6424", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-39": { + "name": "底盘车_6_5", + "nodeName": "底盘车_6_5", + "nodePath": "0/4/0/4", + "interactionId": "interaction-e19c6291", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-40": { + "name": "底盘车_6_6", + "nodeName": "底盘车_6_6", + "nodePath": "0/4/0/5", + "interactionId": "interaction-e09c60fe", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-41": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/5", + "interactionId": "interaction-f0434552", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1528985595703125, + 0.057159042358398436, + 3.3168621826171876 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-42": { + "name": "底盘车_2", + "nodeName": "底盘车_2", + "nodePath": "0/5/0", + "interactionId": "interaction-e3af5dd5", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-43": { + "name": "底盘车_2_1", + "nodeName": "底盘车_2_1", + "nodePath": "0/5/0/0", + "interactionId": "interaction-fdaafb1a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-44": { + "name": "底盘车_2_2", + "nodeName": "底盘车_2_2", + "nodePath": "0/5/0/1", + "interactionId": "interaction-feaafcad", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-45": { + "name": "底盘车_2_3", + "nodeName": "底盘车_2_3", + "nodePath": "0/5/0/2", + "interactionId": "interaction-fbaaf7f4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-46": { + "name": "底盘车_2_4", + "nodeName": "底盘车_2_4", + "nodePath": "0/5/0/3", + "interactionId": "interaction-fcaaf987", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-47": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/6", + "interactionId": "interaction-ef4343bf", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.152901382446289, + 0.057154388427734376, + 3.3168765258789064 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-49": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/7", + "interactionId": "interaction-ee43422c", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529015350341798, + 0.057218170166015624, + 3.3169009399414064 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-51": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/8", + "interactionId": "interaction-f5434d31", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529015350341798, + 0.05720924377441406, + 3.316878662109375 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-55": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/9", + "interactionId": "interaction-f4434b9e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.083279571533203, + -0.04030906677246094, + 3.3168756103515626 + ], + "rotation": [ + -1.5707963267948966, + 0.08726646040099466, + 0 + ], + "scale": [ + 0.003937009043006274, + 0.003937008790671825, + 0.003937009043006274 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-60": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/10", + "interactionId": "interaction-23dc8202", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.152901382446289, + 0.05717395782470703, + 3.3169152832031252 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-62": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/11", + "interactionId": "interaction-24dc8395", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.152901382446289, + 0.057208557128906254, + 3.3169476318359377 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-70": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/12", + "interactionId": "interaction-21dc7edc", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529014587402344, + 0.05719829559326172, + 3.31669677734375 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-75": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/13", + "interactionId": "interaction-22dc806f", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529014587402344, + 0.057202301025390624, + 3.316808776855469 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-77": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/14", + "interactionId": "interaction-1fdc7bb6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.152901611328125, + 0.05720479965209961, + 3.316877746582031 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-78": { + "name": "副梁和滑道总成", + "nodeName": "副梁和滑道总成", + "nodePath": "0/14/0", + "interactionId": "interaction-e187b4f1", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-79": { + "name": "副梁和滑道总成_1", + "nodeName": "副梁和滑道总成_1", + "nodePath": "0/14/0/0", + "interactionId": "interaction-5a96af7e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-80": { + "name": "副梁和滑道总成_2", + "nodeName": "副梁和滑道总成_2", + "nodePath": "0/14/0/1", + "interactionId": "interaction-5b96b111", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-81": { + "name": "副梁和滑道总成_3", + "nodeName": "副梁和滑道总成_3", + "nodePath": "0/14/0/2", + "interactionId": "interaction-5896ac58", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-82": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/15", + "interactionId": "interaction-20dc7d49", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529014587402344, + 0.057201995849609374, + 3.3168780517578127 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-84": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/16", + "interactionId": "interaction-1ddc7890", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + -0.11929863929748535, + 0.13276389122009277, + 0.08761335372924804 + ], + "rotation": [ + 4.3021095220366097e-16, + -1.570796247945363, + 0 + ], + "scale": [ + 0.003937008790671834, + 0.003937008790671827, + 0.003937008790671834 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-85": { + "name": "定位传力销", + "nodeName": "定位传力销", + "nodePath": "0/16/0", + "interactionId": "interaction-8c767327", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-86": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/17", + "interactionId": "interaction-1edc7a23", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529014587402344, + 0.05720605850219727, + 3.3169268798828124 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-92": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/18", + "interactionId": "interaction-2bdc8e9a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.152901382446289, + 0.05720489501953125, + 3.316749267578125 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-94": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/19", + "interactionId": "interaction-2cdc902d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1528977203369142, + 0.057184276580810545, + 3.3170480346679687 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-95": { + "name": "油滤", + "nodeName": "油滤", + "nodePath": "0/19/0", + "interactionId": "interaction-df1beba2", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "d96e6e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-96": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/20", + "interactionId": "interaction-9dd97079", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1528977203369142, + 0.057184276580810545, + 3.3170480346679687 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-97": { + "name": "阀", + "nodeName": "阀", + "nodePath": "0/20/0", + "interactionId": "interaction-f263f616", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "929292", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.9, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-98": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/21", + "interactionId": "interaction-9cd96ee6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1528977203369142, + 0.057184276580810545, + 3.3170483398437502 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-99": { + "name": "开关", + "nodeName": "开关", + "nodePath": "0/21/0", + "interactionId": "interaction-978c2141", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "929292", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.9, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-100": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/22", + "interactionId": "interaction-9bd96d53", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1528923797607422, + 0.05718547821044922, + 3.31912109375 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-101": { + "name": "支承座", + "nodeName": "支承座", + "nodePath": "0/22/0", + "interactionId": "interaction-9d52b44c", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-102": { + "name": "支承座_1", + "nodeName": "支承座_1", + "nodePath": "0/22/0/0", + "interactionId": "interaction-1ba943cb", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-103": { + "name": "支承座_2", + "nodeName": "支承座_2", + "nodePath": "0/22/0/1", + "interactionId": "interaction-1aa94238", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-104": { + "name": "支承座_3", + "nodeName": "支承座_3", + "nodePath": "0/22/0/2", + "interactionId": "interaction-1da946f1", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-105": { + "name": "支承座_4", + "nodeName": "支承座_4", + "nodePath": "0/22/0/3", + "interactionId": "interaction-1ca9455e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-106": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/23", + "interactionId": "interaction-9ad96bc0", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529158020019532, + 0.05718589782714844, + 3.319119567871094 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-108": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/24", + "interactionId": "interaction-a1d976c5", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1516650390625, + 0.05719955444335938, + 3.319119567871094 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-116": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/25", + "interactionId": "interaction-a0d97532", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.152901153564453, + 0.05720237731933594, + 3.319119567871094 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-120": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/26", + "interactionId": "interaction-9fd9739f", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1528968811035156, + 0.05721282958984375, + 3.319122314453125 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-124": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/27", + "interactionId": "interaction-9ed9720c", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529075622558593, + 0.05719169616699219, + 3.3191217041015624 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-128": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/28", + "interactionId": "interaction-a5d97d11", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529489898681642, + 0.05719955444335938, + 3.3168780517578127 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-132": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/29", + "interactionId": "interaction-a4d97b7e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529019927978517, + 0.0572225570678711, + 3.3168762207031253 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-136": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/30", + "interactionId": "interaction-97d72870", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0.0017780303955078126, + 0.3220759201049805, + 1.3452468872070313 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-137": { + "name": "回转支承座", + "nodeName": "回转支承座", + "nodePath": "0/30/0", + "interactionId": "interaction-6b3b2087", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-138": { + "name": "回转支承座_1", + "nodeName": "回转支承座_1", + "nodePath": "0/30/0/0", + "interactionId": "interaction-2a202958", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-139": { + "name": "回转支承座_2", + "nodeName": "回转支承座_2", + "nodePath": "0/30/0/1", + "interactionId": "interaction-2b202aeb", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-140": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/31", + "interactionId": "interaction-98d72a03", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + -0.12935433387756348, + 0.008271529674530029, + 1.601549072265625 + ], + "rotation": [ + 1.6292068494296025e-7, + -4.7683715820308365e-7, + 6.347578170550195e-14 + ], + "scale": [ + 1.0000000000001137, + 1.0000000000000133, + 1.000000000000127 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-141": { + "name": "柱塞泵相关", + "nodeName": "柱塞泵相关", + "nodePath": "0/31/0", + "interactionId": "interaction-46b18f9c", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "4f4f4f", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-142": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/32", + "interactionId": "interaction-99d72b96", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + -0.5312847137451172, + 0.26239418029785155, + 0.3595037841796875 + ], + "rotation": [ + -6.979189167354852e-8, + -1.570796123024582, + 0 + ], + "scale": [ + 0.9555317759513993, + 0.9555317759514067, + 1.000000000000024 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-143": { + "name": "灯控制", + "nodeName": "灯控制", + "nodePath": "0/32/0", + "interactionId": "interaction-4188cd51", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.01, + 0.01, + 0.01 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-144": { + "name": "灯控制_1", + "nodeName": "灯控制_1", + "nodePath": "0/32/0/0", + "interactionId": "interaction-72066dde", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-145": { + "name": "灯控制_2", + "nodeName": "灯控制_2", + "nodePath": "0/32/0/1", + "interactionId": "interaction-73066f71", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "4f4f4f", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-146": { + "name": "灯控制_3", + "nodeName": "灯控制_3", + "nodePath": "0/32/0/2", + "interactionId": "interaction-70066ab8", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-147": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/33", + "interactionId": "interaction-9ad72d29", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529014587402344, + 0.05721702575683594, + 3.1155499267578124 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-151": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/34", + "interactionId": "interaction-9bd72ebc", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529014587402344, + 0.057251663208007814, + 3.1154907226562503 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-153": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/35", + "interactionId": "interaction-9cd7304f", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529015350341798, + 0.057218170166015624, + 3.1155255126953127 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-155": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/36", + "interactionId": "interaction-9dd731e2", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529015350341798, + 0.057200660705566404, + 3.1155792236328126 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-157": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/37", + "interactionId": "interaction-9ed73375", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529015350341798, + 0.05718978881835938, + 3.1155810546875 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-159": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/38", + "interactionId": "interaction-9fd73508", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.152901382446289, + 0.05720100402832031, + 3.1154833984375 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-167": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/39", + "interactionId": "interaction-a0d7369b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529015350341798, + 0.05719390869140625, + 3.1155206298828126 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-171": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/40", + "interactionId": "interaction-a1e8814f", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529015350341798, + 0.057197647094726564, + 3.1154998779296874 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-173": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/41", + "interactionId": "interaction-a0e87fbc", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529119110107422, + 0.05719699859619141, + 3.115636901855469 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-177": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/42", + "interactionId": "interaction-a3e88475", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529014587402344, + 0.05720073699951172, + 3.1155523681640624 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-181": { + "name": "", + "nodeName": "Object3D", + "nodePath": "0/43", + "interactionId": "interaction-a2e882e2", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.1529014587402344, + 0.057207679748535155, + 3.1155569458007815 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.003937008790671825, + 0.003937008790671825, + 0.003937008790671825 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-71": { + "name": "前横梁总成", + "nodeName": "前横梁总成", + "nodePath": "0/12/0", + "interactionId": "interaction-37d62b3b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.3161459274047846, + -0.13338907115591614, + 1.5716647929548482 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-72": { + "name": "前横梁总成_1", + "nodeName": "前横梁总成_1", + "nodePath": "0/12/0/0", + "interactionId": "interaction-1586e7a4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-73": { + "name": "前横梁总成_2", + "nodeName": "前横梁总成_2", + "nodePath": "0/12/0/1", + "interactionId": "interaction-1686e937", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-74": { + "name": "前横梁总成_3", + "nodeName": "前横梁总成_3", + "nodePath": "0/12/0/2", + "interactionId": "interaction-1786eaca", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-87": { + "name": "后横梁总成", + "nodeName": "后横梁总成", + "nodePath": "0/17/0", + "interactionId": "interaction-66afadbc", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.316481498195647, + 0.09219811319424576, + 5.598526923989661 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-88": { + "name": "后横梁总成_1", + "nodeName": "后横梁总成_1", + "nodePath": "0/17/0/0", + "interactionId": "interaction-f3ec261b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-89": { + "name": "后横梁总成_2", + "nodeName": "后横梁总成_2", + "nodePath": "0/17/0/1", + "interactionId": "interaction-f2ec2488", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-90": { + "name": "后横梁总成_3", + "nodeName": "后横梁总成_3", + "nodePath": "0/17/0/2", + "interactionId": "interaction-f5ec2941", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-91": { + "name": "后横梁总成_4", + "nodeName": "后横梁总成_4", + "nodePath": "0/17/0/3", + "interactionId": "interaction-f4ec27ae", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-182": { + "name": "后支座", + "nodeName": "后支座", + "nodePath": "0/43/0", + "interactionId": "interaction-e34d0c85", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.316145795730941, + -0.1466403098263228, + 5.820431585950951 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-183": { + "name": "后支座_1", + "nodeName": "后支座_1", + "nodePath": "0/43/0/0", + "interactionId": "interaction-57f74eea", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-184": { + "name": "后支座_2", + "nodeName": "后支座_2", + "nodePath": "0/43/0/1", + "interactionId": "interaction-58f7507d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-185": { + "name": "后支座_3", + "nodeName": "后支座_3", + "nodePath": "0/43/0/2", + "interactionId": "interaction-55f74bc4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-109": { + "name": "下臂架油缸", + "nodeName": "下臂架油缸", + "nodePath": "0/24/0", + "interactionId": "interaction-beb1632a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.314420773379884, + -0.35887045728099454, + 2.251160314116218 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-110": { + "name": "下臂架油缸_1", + "nodeName": "下臂架油缸_1", + "nodePath": "0/24/0/0", + "interactionId": "interaction-53fc183d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-111": { + "name": "下臂架油缸_2", + "nodeName": "下臂架油缸_2", + "nodePath": "0/24/0/1", + "interactionId": "interaction-52fc16aa", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "4f4f4f", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-112": { + "name": "下臂架油缸_3", + "nodeName": "下臂架油缸_3", + "nodePath": "0/24/0/2", + "interactionId": "interaction-51fc1517", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "929292", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.9, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-113": { + "name": "下臂架油缸_4", + "nodeName": "下臂架油缸_4", + "nodePath": "0/24/0/3", + "interactionId": "interaction-50fc1384", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-114": { + "name": "下臂架油缸_5", + "nodeName": "下臂架油缸_5", + "nodePath": "0/24/0/4", + "interactionId": "interaction-4ffc11f1", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-115": { + "name": "下臂架油缸_6", + "nodeName": "下臂架油缸_6", + "nodePath": "0/24/0/5", + "interactionId": "interaction-4efc105e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-117": { + "name": "下臂架", + "nodeName": "下臂架", + "nodePath": "0/25/0", + "interactionId": "interaction-c33ac1b5", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.3158319147770576, + -0.35886723470157866, + 2.251160314116218 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-118": { + "name": "下臂架_1", + "nodeName": "下臂架_1", + "nodePath": "0/25/0/0", + "interactionId": "interaction-6290b2fa", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-119": { + "name": "下臂架_2", + "nodeName": "下臂架_2", + "nodePath": "0/25/0/1", + "interactionId": "interaction-6390b48d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-133": { + "name": "回转支承", + "nodeName": "回转支承", + "nodePath": "0/29/0", + "interactionId": "interaction-6e9a79c9", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.3158328728412083, + -0.35884419761359243, + 2.248599321544777 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-134": { + "name": "回转支承_1", + "nodeName": "回转支承_1", + "nodePath": "0/29/0/0", + "interactionId": "interaction-233fb486", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-135": { + "name": "回转支承_2", + "nodeName": "回转支承_2", + "nodePath": "0/29/0/1", + "interactionId": "interaction-243fb619", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-107": { + "name": "四连杆机构", + "nodeName": "四连杆机构", + "nodePath": "0/23/0", + "interactionId": "interaction-427adf77", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0.7377842289012164, + -0.9109434053346417, + 2.251188596561066 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-121": { + "name": "上臂架油缸", + "nodeName": "上臂架油缸", + "nodePath": "0/26/0", + "interactionId": "interaction-48b26c60", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0.7377626289094563, + -0.9109126601850798, + 2.2511917320437407 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-122": { + "name": "上臂架油缸_1", + "nodeName": "上臂架油缸_1", + "nodePath": "0/26/0/0", + "interactionId": "interaction-7b6a2b97", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-123": { + "name": "上臂架油缸_2", + "nodeName": "上臂架油缸_2", + "nodePath": "0/26/0/1", + "interactionId": "interaction-7a6a2a04", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-125": { + "name": "上臂架", + "nodeName": "上臂架", + "nodePath": "0/27/0", + "interactionId": "interaction-edda978b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0.7377748224531919, + -0.9109367859823281, + 2.251191035269813 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-126": { + "name": "上臂架_1", + "nodeName": "上臂架_1", + "nodePath": "0/27/0/0", + "interactionId": "interaction-32344114", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-127": { + "name": "上臂架_2", + "nodeName": "上臂架_2", + "nodePath": "0/27/0/1", + "interactionId": "interaction-333442a7", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-129": { + "name": "插销机构", + "nodeName": "插销机构", + "nodePath": "0/28/0", + "interactionId": "interaction-ea60039e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0.7378221159835381, + -0.9109278150180083, + 2.2486296943114077 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-130": { + "name": "插销机构_1", + "nodeName": "插销机构_1", + "nodePath": "0/28/0/0", + "interactionId": "interaction-2085c469", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-131": { + "name": "插销机构_2", + "nodeName": "插销机构_2", + "nodePath": "0/28/0/1", + "interactionId": "interaction-1f85c2d6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-93": { + "name": "架设架连接座", + "nodeName": "架设架连接座", + "nodePath": "0/18/0", + "interactionId": "interaction-04e2b10d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3161455982201753, + -0.11300762252172991, + 5.990716063154325 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-154": { + "name": "摆块", + "nodeName": "摆块", + "nodePath": "0/35/0", + "interactionId": "interaction-72107e30", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3161457724136572, + -0.11299246768880133, + 5.761000150784408 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-156": { + "name": "架设架结构", + "nodeName": "架设架结构", + "nodePath": "0/36/0", + "interactionId": "interaction-ec98d385", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3161457724136572, + -0.11301245639085367, + 5.76106146689005 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-158": { + "name": "推桥机构", + "nodeName": "推桥机构", + "nodePath": "0/37/0", + "interactionId": "interaction-6770daba", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3161457724136572, + -0.1130248676764416, + 5.761063557211832 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-172": { + "name": "托轮", + "nodeName": "托轮", + "nodePath": "0/40/0", + "interactionId": "interaction-68c4b730", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3161457724136572, + -0.11301589671212187, + 5.760970886279441 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-148": { + "name": "导梁推进机构", + "nodeName": "导梁推进机构", + "nodePath": "0/33/0", + "interactionId": "interaction-1bc207e6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.3161457737853004, + -1.0104967206858395, + 6.9852963589055435 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-149": { + "name": "导梁推进机构_1", + "nodeName": "导梁推进机构_1", + "nodePath": "0/33/0/0", + "interactionId": "interaction-afdce241", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-150": { + "name": "导梁推进机构_2", + "nodeName": "导梁推进机构_2", + "nodePath": "0/33/0/1", + "interactionId": "interaction-aedce0ae", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-152": { + "name": "Obj_销齿轮", + "nodeName": "Obj_销齿轮", + "nodePath": "0/34/0", + "interactionId": "interaction-969a0f1b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3161457737853004, + -1.0104571787654397, + 6.985228771834551 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-160": { + "name": "变幅缸", + "nodeName": "变幅缸", + "nodePath": "0/38/0", + "interactionId": "interaction-42e749cf", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.316145687374381, + -0.25901294072285297, + 3.06952481638734 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-161": { + "name": "变幅缸_1", + "nodeName": "变幅缸_1", + "nodePath": "0/38/0/0", + "interactionId": "interaction-6dd1f3b0", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-162": { + "name": "变幅缸_2", + "nodeName": "变幅缸_2", + "nodePath": "0/38/0/1", + "interactionId": "interaction-6ed1f543", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "4f4f4f", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-163": { + "name": "变幅缸_3", + "nodeName": "变幅缸_3", + "nodePath": "0/38/0/2", + "interactionId": "interaction-6fd1f6d6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "929292", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.9, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-164": { + "name": "变幅缸_4", + "nodeName": "变幅缸_4", + "nodePath": "0/38/0/3", + "interactionId": "interaction-70d1f869", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-165": { + "name": "变幅缸_5", + "nodeName": "变幅缸_5", + "nodePath": "0/38/0/4", + "interactionId": "interaction-71d1f9fc", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-166": { + "name": "变幅缸_6", + "nodeName": "变幅缸_6", + "nodePath": "0/38/0/5", + "interactionId": "interaction-72d1fb8f", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-168": { + "name": "调整油缸", + "nodeName": "调整油缸", + "nodePath": "0/39/0", + "interactionId": "interaction-bdbf5104", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.316145861567863, + -0.25902104071976306, + 3.0695673195969326 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-169": { + "name": "调整油缸_1", + "nodeName": "调整油缸_1", + "nodePath": "0/39/0/0", + "interactionId": "interaction-d47c7d13", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-170": { + "name": "调整油缸_2", + "nodeName": "调整油缸_2", + "nodePath": "0/39/0/1", + "interactionId": "interaction-d37c7b80", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-83": { + "name": "滚轮组", + "nodeName": "滚轮组", + "nodePath": "0/15/0", + "interactionId": "interaction-bcfe2406", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3688697145386657, + -0.3732708259369022, + 3.9266870250363364 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-174": { + "name": "移动架_1", + "nodeName": "移动架_1", + "nodePath": "0/41/0", + "interactionId": "interaction-8d4e481b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.3688816467921785, + -0.3732765307734356, + 3.696951254609478 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-175": { + "name": "移动架_1_1", + "nodeName": "移动架_1_1", + "nodePath": "0/41/0/0", + "interactionId": "interaction-9bec7e84", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-176": { + "name": "移动架_1_2", + "nodeName": "移动架_1_2", + "nodePath": "0/41/0/1", + "interactionId": "interaction-9cec8017", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-178": { + "name": "移动架_2", + "nodeName": "移动架_2", + "nodePath": "0/42/0", + "interactionId": "interaction-5e2513ba", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.3688697145386657, + -0.3732722630331281, + 3.696854751420484 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-179": { + "name": "移动架_2_1", + "nodeName": "移动架_2_1", + "nodePath": "0/42/0/0", + "interactionId": "interaction-bdb455ad", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-180": { + "name": "移动架_2_2", + "nodeName": "移动架_2_2", + "nodePath": "0/42/0/1", + "interactionId": "interaction-bcb4541a", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-50": { + "name": "托架滚轮组", + "nodeName": "托架滚轮组", + "nodePath": "0/7/0", + "interactionId": "interaction-8d1135ab", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3145652919526403, + -1.0109180900249655, + 1.7384498676566733 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-56": { + "name": "托架体", + "nodeName": "托架体", + "nodePath": "0/9/0", + "interactionId": "interaction-0f0e4c69", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.2350852480784664, + -1.1222546378758222, + 1.7384209515386715 + ], + "rotation": [ + -1.5707963267948966, + 0.08726646040099466, + 0 + ], + "scale": [ + 0.00004494467488937866, + 0.00004494467200874272, + 0.00004494467488937866 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-57": { + "name": "托架体_1", + "nodeName": "托架体_1", + "nodePath": "0/9/0/0", + "interactionId": "interaction-c9c25926", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-58": { + "name": "托架体_2", + "nodeName": "托架体_2", + "nodePath": "0/9/0/1", + "interactionId": "interaction-cac25ab9", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-59": { + "name": "托架体_3", + "nodeName": "托架体_3", + "nodePath": "0/9/0/2", + "interactionId": "interaction-c7c25600", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-61": { + "name": "托架座", + "nodeName": "托架座", + "nodePath": "0/10/0", + "interactionId": "interaction-8dd4efa5", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3145651177591584, + -1.010968562586357, + 1.7384662418439754 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-63": { + "name": "托架变幅油缸", + "nodeName": "托架变幅油缸", + "nodePath": "0/11/0", + "interactionId": "interaction-08acf6da", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.3145651177591584, + -1.0109290642143276, + 1.738503170862146 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-64": { + "name": "托架变幅油缸_1", + "nodeName": "托架变幅油缸_1", + "nodePath": "0/11/0/0", + "interactionId": "interaction-388bf34d", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-65": { + "name": "托架变幅油缸_2", + "nodeName": "托架变幅油缸_2", + "nodePath": "0/11/0/1", + "interactionId": "interaction-378bf1ba", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "4f4f4f", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-66": { + "name": "托架变幅油缸_3", + "nodeName": "托架变幅油缸_3", + "nodePath": "0/11/0/2", + "interactionId": "interaction-368bf027", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "929292", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.9, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-67": { + "name": "托架变幅油缸_4", + "nodeName": "托架变幅油缸_4", + "nodePath": "0/11/0/3", + "interactionId": "interaction-358bee94", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "3d4b3b", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-68": { + "name": "托架变幅油缸_5", + "nodeName": "托架变幅油缸_5", + "nodePath": "0/11/0/4", + "interactionId": "interaction-348bed01", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-69": { + "name": "托架变幅油缸_6", + "nodeName": "托架变幅油缸_6", + "nodePath": "0/11/0/5", + "interactionId": "interaction-338beb6e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "9da3a4", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.42, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-76": { + "name": "托架托轮", + "nodeName": "托架托轮", + "nodePath": "0/13/0", + "interactionId": "interaction-120f65d0", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3145652048558993, + -1.010936206147087, + 1.738344654793583 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-52": { + "name": "前推送装置", + "nodeName": "前推送装置", + "nodePath": "0/8/0", + "interactionId": "interaction-8996a1be", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 1.2808613094338743, + -1.0595352662334152, + 0.18907815325162325 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [] + }, + "model-bridge-erector-vehicle-53": { + "name": "前推送装置_1", + "nodeName": "前推送装置_1", + "nodePath": "0/8/0/0", + "interactionId": "interaction-30e9aa09", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-54": { + "name": "前推送装置_2", + "nodeName": "前推送装置_2", + "nodePath": "0/8/0/1", + "interactionId": "interaction-2fe9a876", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.5, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + }, + "model-bridge-erector-vehicle-48": { + "name": "销齿轮", + "nodeName": "销齿轮", + "nodePath": "0/6/0", + "interactionId": "interaction-e7e90a80", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 1.3161457737853004, + -1.2148948643750737, + 0.007635582405807195 + ], + "rotation": [ + -1.5707963267948963, + 0, + 0 + ], + "scale": [ + 0.00004494467200874272, + 0.00004494467200874272, + 0.00004494467200874272 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "322e2e", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0.8, + "roughness": 0.55, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + } + }, + "assets": [ + { + "code": "MODEL_BRIDGE-ERECTOR-VEHICLE", + "name": "桥梁架设装备整机", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "", + "storageUri": "/models/bridge-erector-vehicle.glb", + "builtIn": true + } + ] + }, + "imported": { + "sha256": "d97044e701822bac5a62696459b27d7b375aada5de8574ed4362edbba94771f7", + "bytes": 162852, + "mutations": [ + { + "status": 200, + "registeredTicket": true, + "sourceName": "bridge-erector-vehicle.glb", + "assetCode": "MODEL_BRIDGE-ERECTOR-VEHICLE" + }, + { + "status": 200, + "registeredTicket": false, + "sourceName": "09-Fox.glb", + "assetCode": "MODEL_MTO6V5W6_09-FOX" + } + ], + "server": { + "projectId": "157", + "code": "MODEL-70875AA932B94685", + "name": "实测模型-狐狸动画-20260905", + "status": "DRAFT", + "version": 4, + "publishedVersionId": null, + "currentVersionId": "199", + "versionNo": 1, + "checksum": "3bfa16814a65c4576b1627e92032c61d2d986145a19d1b4027e570209e306e0d", + "schema": "digital-twin-editor-project", + "modelResource": { + "kind": "imported", + "id": "imported-model_mto6v5w6_09-fox", + "name": "09-Fox", + "assetCode": "MODEL_MTO6V5W6_09-FOX", + "code": "MODEL_MTO6V5W6_09-FOX", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb", + "resourceUrl": "", + "sourceName": "09-Fox.glb", + "sizeBytes": 162852, + "lastModified": 0, + "mimeType": "model/gltf-binary", + "thumbnail": "", + "vertices": 1728, + "triangles": 576, + "nodes": 27, + "meshes": 1, + "materials": 1, + "textures": 1, + "animations": 3, + "animationDurationSeconds": 3.4166667461395264, + "modelMetadata": { + "nodeCount": 27, + "meshCount": 1, + "materialCount": 1, + "textureCount": 1, + "animations": [ + { + "index": 0, + "name": "Survey", + "start": 0, + "end": 3.4166667461395264, + "duration": 3.4166667461395264, + "trackCount": 21 + }, + { + "index": 1, + "name": "Walk", + "start": 0, + "end": 0.7083333134651184, + "duration": 0.7083333134651184, + "trackCount": 21 + }, + { + "index": 2, + "name": "Run", + "start": 0, + "end": 1.1583333015441895, + "duration": 1.1583333015441895, + "trackCount": 21 + } + ], + "animationDurationSeconds": 3.4166667461395264 + }, + "nativeAnimations": [ + { + "index": 0, + "name": "Survey", + "start": 0, + "end": 3.4166667461395264, + "duration": 3.4166667461395264, + "trackCount": 21 + }, + { + "index": 1, + "name": "Walk", + "start": 0, + "end": 0.7083333134651184, + "duration": 0.7083333134651184, + "trackCount": 21 + }, + { + "index": 2, + "name": "Run", + "start": 0, + "end": 1.1583333015441895, + "duration": 1.1583333015441895, + "trackCount": 21 + } + ] + }, + "nativeAnimation": { + "clipIndex": 0, + "clipName": "Survey" + }, + "modelObjects": { + "equipment-root": { + "name": "09-Fox", + "nodeName": "09-Fox", + "nodePath": "@root", + "interactionId": "interaction-b9240aaa", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-0": { + "name": "", + "nodeName": "Group", + "nodePath": "0", + "interactionId": "interaction-02351bce", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 3.875009990661482e-8, + 0.007396563645075124, + 0.6522089834776823 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.06075496488891343, + 0.06075496488891343, + 0.06075496488891343 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-1": { + "name": "root", + "nodeName": "root", + "nodePath": "0/0", + "interactionId": "interaction-a4d35db9", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-2": { + "name": "_rootJoint", + "nodeName": "_rootJoint", + "nodePath": "0/0/0", + "interactionId": "interaction-4476c556", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-3": { + "name": "b_Root_00", + "nodeName": "b_Root_00", + "nodePath": "0/0/0/0", + "interactionId": "interaction-ffc45d11", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + -1.5708000357176293, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-4": { + "name": "b_Hip_01", + "nodeName": "b_Hip_01", + "nodePath": "0/0/0/0/0", + "interactionId": "interaction-7a75e39e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 26.748403549194336, + 42.93817138671875 + ], + "rotation": [ + 0.36315579795853176, + -1.5707952841394475, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-5": { + "name": "b_Spine01_02", + "nodeName": "b_Spine01_02", + "nodePath": "0/0/0/0/0/0", + "interactionId": "interaction-663ea469", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 12.850601196289062, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -1.2631477544403162 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-6": { + "name": "b_Spine02_03", + "nodeName": "b_Spine02_03", + "nodePath": "0/0/0/0/0/0/0", + "interactionId": "interaction-46867126", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 21.65575408935547, + -0.000118255615234375, + 0 + ], + "rotation": [ + 0, + 0, + 0.03482566467786662 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-7": { + "name": "b_Neck_04", + "nodeName": "b_Neck_04", + "nodePath": "0/0/0/0/0/0/0/0", + "interactionId": "interaction-27148d81", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 25.64914321899414, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0.616473876457289 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-8": { + "name": "b_Head_05", + "nodeName": "b_Head_05", + "nodePath": "0/0/0/0/0/0/0/0/0", + "interactionId": "interaction-b24eef2e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 13.376960754394531, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.8236565613916008 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-9": { + "name": "b_RightUpperArm_06", + "nodeName": "b_RightUpperArm_06", + "nodePath": "0/0/0/0/0/0/0/1", + "interactionId": "interaction-26148bee", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.677913665771484, + -4.297340393066406, + 6.9675750732421875 + ], + "rotation": [ + 0.000020649684502855715, + -0.0012920321082461929, + -1.5851959113548921 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-10": { + "name": "b_RightForeArm_07", + "nodeName": "b_RightForeArm_07", + "nodePath": "0/0/0/0/0/0/0/1/0", + "interactionId": "interaction-36896559", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 23.04512596130371, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0.07426886741269867 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-11": { + "name": "b_RightHand_08", + "nodeName": "b_RightHand_08", + "nodePath": "0/0/0/0/0/0/0/1/0/0", + "interactionId": "interaction-57a124f6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 19.350055694580078, + -0.14598655700683594, + 0 + ], + "rotation": [ + -0.014166329641847676, + -0.024975147923384556, + 0.9571872589843109 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-12": { + "name": "b_LeftUpperArm_09", + "nodeName": "b_LeftUpperArm_09", + "nodePath": "0/0/0/0/0/0/0/2", + "interactionId": "interaction-25148a5b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.67791748046875, + -4.297344207763672, + -6.967987060546875 + ], + "rotation": [ + -0.0005581520651140974, + -0.0019469460390509152, + -1.5849355765797046 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-13": { + "name": "b_LeftForeArm_010", + "nodeName": "b_LeftForeArm_010", + "nodePath": "0/0/0/0/0/0/0/2/0", + "interactionId": "interaction-5c502ac4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 23.045124053955078, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0.07426886741269867 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-14": { + "name": "b_LeftHand_011", + "nodeName": "b_LeftHand_011", + "nodePath": "0/0/0/0/0/0/0/2/0/0", + "interactionId": "interaction-192b4cd3", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 19.350051879882812, + -0.14599037170410156, + 0 + ], + "rotation": [ + 0.016442303987465122, + 0.04008733863576039, + 0.9560742489627883 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-15": { + "name": "b_Tail01_012", + "nodeName": "b_Tail01_012", + "nodePath": "0/0/0/0/0/1", + "interactionId": "interaction-653ea2d6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 4.2603759765625, + 15.958770751953125, + 0 + ], + "rotation": [ + 0, + 0, + 2.760415362743526 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-16": { + "name": "b_Tail02_013", + "nodeName": "b_Tail02_013", + "nodePath": "0/0/0/0/0/1/0", + "interactionId": "interaction-6c4d3691", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 12.411918640136719, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.1393470463625701 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-17": { + "name": "b_Tail03_014", + "nodeName": "b_Tail03_014", + "nodePath": "0/0/0/0/0/1/0/0", + "interactionId": "interaction-e93e191e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 24.24032211303711, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.10771755940908084 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-18": { + "name": "b_LeftLeg01_015", + "nodeName": "b_LeftLeg01_015", + "nodePath": "0/0/0/0/0/2", + "interactionId": "interaction-643ea143", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 4.813770294189453, + 5.154018402099609, + -6.968006134033203 + ], + "rotation": [ + 0.0003332048354397326, + 0.00008348584072415229, + -2.6505924384110937 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-19": { + "name": "b_LeftLeg02_016", + "nodeName": "b_LeftLeg02_016", + "nodePath": "0/0/0/0/0/2/0", + "interactionId": "interaction-7175f8dc", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.944175720214844, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.7538085117951059 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-20": { + "name": "b_LeftFoot01_017", + "nodeName": "b_LeftFoot01_017", + "nodePath": "0/0/0/0/0/2/0/0", + "interactionId": "interaction-f5ed353b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 17.942811965942383, + 0, + 0 + ], + "rotation": [ + 0.00044152629033825986, + 0.0002277846223534801, + 0.9525774122187588 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-21": { + "name": "b_LeftFoot02_018", + "nodeName": "b_LeftFoot02_018", + "nodePath": "0/0/0/0/0/2/0/0/0", + "interactionId": "interaction-1bbe01a4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 15.779938697814941, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 1.158241570830627 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-22": { + "name": "b_RightLeg01_019", + "nodeName": "b_RightLeg01_019", + "nodePath": "0/0/0/0/0/3", + "interactionId": "interaction-633e9fb0", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 4.813777923583984, + 5.154026031494141, + 6.967563629150391 + ], + "rotation": [ + 0, + 0, + -2.6501210928667223 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-23": { + "name": "b_RightLeg02_020", + "nodeName": "b_RightLeg02_020", + "nodePath": "0/0/0/0/0/3/0", + "interactionId": "interaction-95ff89c7", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.944183349609375, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.7538085672160094 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-24": { + "name": "b_RightFoot01_021", + "nodeName": "b_RightFoot01_021", + "nodePath": "0/0/0/0/0/3/0/0", + "interactionId": "interaction-a157d498", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 17.94281005859375, + 0, + 0 + ], + "rotation": [ + -0.00027284186307510456, + -0.00014053656253775514, + 0.9512842084783865 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-25": { + "name": "b_RightFoot02_022", + "nodeName": "b_RightFoot02_022", + "nodePath": "0/0/0/0/0/3/0/0/0", + "interactionId": "interaction-ebd38e3f", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 15.779935836791992, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 1.158241570830627 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-26": { + "name": "fox", + "nodeName": "fox", + "nodePath": "0/1", + "interactionId": "interaction-a3d35c26", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 0.58, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + } + }, + "assets": [ + { + "code": "MODEL_BRIDGE-ERECTOR-VEHICLE", + "name": "桥梁架设装备整机", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "", + "storageUri": "/models/bridge-erector-vehicle.glb", + "builtIn": true + }, + { + "code": "MODEL_MTO6V5W6_09-FOX", + "name": "09-Fox.glb", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "d97044e701822bac5a62696459b27d7b375aada5de8574ed4362edbba94771f7", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb" + } + ] + }, + "live": { + "sourceName": "09-Fox.glb", + "assetCode": "MODEL_MTO6V5W6_09-FOX", + "nodes": 27, + "meshes": 1, + "materials": 1, + "clips": [ + { + "name": "Survey", + "duration": 3.4166667461395264, + "tracks": 21 + }, + { + "name": "Walk", + "duration": 0.7083333134651184, + "tracks": 21 + }, + { + "name": "Run", + "duration": 1.1583333015441895, + "tracks": 21 + } + ], + "clipIndex": 0, + "playing": false, + "time": 0, + "mesh": { + "name": "fox", + "editorId": "model-imported-model_mto6v5w6_09-fox-26", + "position": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "isSkinnedMesh": true, + "bones": 24 + }, + "moving": [ + { + "name": "_rootJoint", + "quaternion": [ + 0, + 0, + 0, + 1 + ] + }, + { + "name": "b_Root_00", + "quaternion": [ + -0.7071080924875391, + 0, + 0, + 0.7071054698831242 + ] + }, + { + "name": "b_Hip_01", + "quaternion": [ + 0.12769094176175547, + -0.6954820192393762, + -0.12769022650601444, + 0.695481840425441 + ] + }, + { + "name": "b_Spine01_02", + "quaternion": [ + 0, + 0, + -0.5904157638238317, + 0.8070992664030376 + ] + }, + { + "name": "b_Spine02_03", + "quaternion": [ + 0, + 0, + 0.017411952404281082, + 0.9998484004655261 + ] + }, + { + "name": "b_Neck_04", + "quaternion": [ + 0, + 0, + 0.30337914028264346, + 0.9528699267168443 + ] + }, + { + "name": "b_Head_05", + "quaternion": [ + 0, + 0, + -0.4002854151487349, + 0.9163905206947555 + ] + }, + { + "name": "b_RightUpperArm_06", + "quaternion": [ + 0.0004673273262011562, + -0.0004461484692255928, + -0.7121792881110691, + 0.7019973248825985 + ] + }, + { + "name": "b_RightForeArm_07", + "quaternion": [ + 0, + 0, + 0.03712589977348744, + 0.9993105961441663 + ] + }, + { + "name": "b_RightHand_08", + "quaternion": [ + -0.012037406914797018, + -0.00782221012465276, + 0.4605623277185148, + 0.8875112709988741 + ] + }, + { + "name": "b_LeftUpperArm_09", + "quaternion": [ + 0.0004972619220940174, + -0.0008821923166442875, + -0.7120874929914663, + 0.7020900061903927 + ] + }, + { + "name": "b_LeftForeArm_010", + "quaternion": [ + 0, + 0, + 0.03712589977348744, + 0.9993105961441663 + ] + }, + { + "name": "b_LeftHand_011", + "quaternion": [ + 0.01651791440721507, + 0.014013739873997781, + 0.46007557521271, + 0.8876154790736099 + ] + }, + { + "name": "b_Tail01_012", + "quaternion": [ + 0, + 0, + 0.9818928940656295, + 0.1894369145214904 + ] + }, + { + "name": "b_Tail02_013", + "quaternion": [ + 0, + 0, + -0.0696171663387466, + 0.9975737818081244 + ] + }, + { + "name": "b_Tail03_014", + "quaternion": [ + 0, + 0, + -0.05383274484207684, + 0.9985499664927979 + ] + }, + { + "name": "b_LeftLeg01_015", + "quaternion": [ + 0, + -0.0001717522536559936, + 0.9700158834020681, + -0.2430414706359161 + ] + }, + { + "name": "b_LeftLeg02_016", + "quaternion": [ + 0, + 0, + -0.36804378855511655, + 0.9298084586117706 + ] + }, + { + "name": "b_LeftFoot01_017", + "quaternion": [ + 0.0002484105929664666, + 0, + 0.4584841122585099, + 0.888702569535333 + ] + }, + { + "name": "b_LeftFoot02_018", + "quaternion": [ + 0, + 0, + 0.5472882949090243, + 0.8369441571906533 + ] + }, + { + "name": "b_RightLeg01_019", + "quaternion": [ + 0, + 0, + 0.9699585942054535, + -0.24327006705918533 + ] + }, + { + "name": "b_RightLeg02_020", + "quaternion": [ + 0, + 0, + -0.36804381432052885, + 0.9298084484131106 + ] + }, + { + "name": "b_RightFoot01_021", + "quaternion": [ + -0.00015345455876803163, + 0, + 0.4579093746168346, + 0.888998864504178 + ] + }, + { + "name": "b_RightFoot02_022", + "quaternion": [ + 0, + 0, + 0.5472882949090243, + 0.8369441571906533 + ] + } + ], + "onlyActivePivot": true + }, + "status": "PASS" + }, + "editBefore": { + "projectId": "157", + "code": "MODEL-70875AA932B94685", + "name": "实测模型-狐狸动画-20260905", + "status": "DRAFT", + "version": 4, + "publishedVersionId": null, + "currentVersionId": "199", + "versionNo": 1, + "checksum": "3bfa16814a65c4576b1627e92032c61d2d986145a19d1b4027e570209e306e0d", + "schema": "digital-twin-editor-project", + "modelResource": { + "kind": "imported", + "id": "imported-model_mto6v5w6_09-fox", + "name": "09-Fox", + "assetCode": "MODEL_MTO6V5W6_09-FOX", + "code": "MODEL_MTO6V5W6_09-FOX", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb", + "resourceUrl": "", + "sourceName": "09-Fox.glb", + "sizeBytes": 162852, + "lastModified": 0, + "mimeType": "model/gltf-binary", + "thumbnail": "", + "vertices": 1728, + "triangles": 576, + "nodes": 27, + "meshes": 1, + "materials": 1, + "textures": 1, + "animations": 3, + "animationDurationSeconds": 3.4166667461395264, + "modelMetadata": { + "nodeCount": 27, + "meshCount": 1, + "materialCount": 1, + "textureCount": 1, + "animations": [ + { + "index": 0, + "name": "Survey", + "start": 0, + "end": 3.4166667461395264, + "duration": 3.4166667461395264, + "trackCount": 21 + }, + { + "index": 1, + "name": "Walk", + "start": 0, + "end": 0.7083333134651184, + "duration": 0.7083333134651184, + "trackCount": 21 + }, + { + "index": 2, + "name": "Run", + "start": 0, + "end": 1.1583333015441895, + "duration": 1.1583333015441895, + "trackCount": 21 + } + ], + "animationDurationSeconds": 3.4166667461395264 + }, + "nativeAnimations": [ + { + "index": 0, + "name": "Survey", + "start": 0, + "end": 3.4166667461395264, + "duration": 3.4166667461395264, + "trackCount": 21 + }, + { + "index": 1, + "name": "Walk", + "start": 0, + "end": 0.7083333134651184, + "duration": 0.7083333134651184, + "trackCount": 21 + }, + { + "index": 2, + "name": "Run", + "start": 0, + "end": 1.1583333015441895, + "duration": 1.1583333015441895, + "trackCount": 21 + } + ] + }, + "nativeAnimation": { + "clipIndex": 0, + "clipName": "Survey" + }, + "modelObjects": { + "equipment-root": { + "name": "09-Fox", + "nodeName": "09-Fox", + "nodePath": "@root", + "interactionId": "interaction-b9240aaa", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-0": { + "name": "", + "nodeName": "Group", + "nodePath": "0", + "interactionId": "interaction-02351bce", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 3.875009990661482e-8, + 0.007396563645075124, + 0.6522089834776823 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.06075496488891343, + 0.06075496488891343, + 0.06075496488891343 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-1": { + "name": "root", + "nodeName": "root", + "nodePath": "0/0", + "interactionId": "interaction-a4d35db9", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-2": { + "name": "_rootJoint", + "nodeName": "_rootJoint", + "nodePath": "0/0/0", + "interactionId": "interaction-4476c556", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-3": { + "name": "b_Root_00", + "nodeName": "b_Root_00", + "nodePath": "0/0/0/0", + "interactionId": "interaction-ffc45d11", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + -1.5708000357176293, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-4": { + "name": "b_Hip_01", + "nodeName": "b_Hip_01", + "nodePath": "0/0/0/0/0", + "interactionId": "interaction-7a75e39e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 26.748403549194336, + 42.93817138671875 + ], + "rotation": [ + 0.36315579795853176, + -1.5707952841394475, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-5": { + "name": "b_Spine01_02", + "nodeName": "b_Spine01_02", + "nodePath": "0/0/0/0/0/0", + "interactionId": "interaction-663ea469", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 12.850601196289062, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -1.2631477544403162 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-6": { + "name": "b_Spine02_03", + "nodeName": "b_Spine02_03", + "nodePath": "0/0/0/0/0/0/0", + "interactionId": "interaction-46867126", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 21.65575408935547, + -0.000118255615234375, + 0 + ], + "rotation": [ + 0, + 0, + 0.03482566467786662 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-7": { + "name": "b_Neck_04", + "nodeName": "b_Neck_04", + "nodePath": "0/0/0/0/0/0/0/0", + "interactionId": "interaction-27148d81", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 25.64914321899414, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0.616473876457289 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-8": { + "name": "b_Head_05", + "nodeName": "b_Head_05", + "nodePath": "0/0/0/0/0/0/0/0/0", + "interactionId": "interaction-b24eef2e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 13.376960754394531, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.8236565613916008 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-9": { + "name": "b_RightUpperArm_06", + "nodeName": "b_RightUpperArm_06", + "nodePath": "0/0/0/0/0/0/0/1", + "interactionId": "interaction-26148bee", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.677913665771484, + -4.297340393066406, + 6.9675750732421875 + ], + "rotation": [ + 0.000020649684502855715, + -0.0012920321082461929, + -1.5851959113548921 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-10": { + "name": "b_RightForeArm_07", + "nodeName": "b_RightForeArm_07", + "nodePath": "0/0/0/0/0/0/0/1/0", + "interactionId": "interaction-36896559", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 23.04512596130371, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0.07426886741269867 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-11": { + "name": "b_RightHand_08", + "nodeName": "b_RightHand_08", + "nodePath": "0/0/0/0/0/0/0/1/0/0", + "interactionId": "interaction-57a124f6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 19.350055694580078, + -0.14598655700683594, + 0 + ], + "rotation": [ + -0.014166329641847676, + -0.024975147923384556, + 0.9571872589843109 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-12": { + "name": "b_LeftUpperArm_09", + "nodeName": "b_LeftUpperArm_09", + "nodePath": "0/0/0/0/0/0/0/2", + "interactionId": "interaction-25148a5b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.67791748046875, + -4.297344207763672, + -6.967987060546875 + ], + "rotation": [ + -0.0005581520651140974, + -0.0019469460390509152, + -1.5849355765797046 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-13": { + "name": "b_LeftForeArm_010", + "nodeName": "b_LeftForeArm_010", + "nodePath": "0/0/0/0/0/0/0/2/0", + "interactionId": "interaction-5c502ac4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 23.045124053955078, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0.07426886741269867 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-14": { + "name": "b_LeftHand_011", + "nodeName": "b_LeftHand_011", + "nodePath": "0/0/0/0/0/0/0/2/0/0", + "interactionId": "interaction-192b4cd3", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 19.350051879882812, + -0.14599037170410156, + 0 + ], + "rotation": [ + 0.016442303987465122, + 0.04008733863576039, + 0.9560742489627883 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-15": { + "name": "b_Tail01_012", + "nodeName": "b_Tail01_012", + "nodePath": "0/0/0/0/0/1", + "interactionId": "interaction-653ea2d6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 4.2603759765625, + 15.958770751953125, + 0 + ], + "rotation": [ + 0, + 0, + 2.760415362743526 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-16": { + "name": "b_Tail02_013", + "nodeName": "b_Tail02_013", + "nodePath": "0/0/0/0/0/1/0", + "interactionId": "interaction-6c4d3691", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 12.411918640136719, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.1393470463625701 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-17": { + "name": "b_Tail03_014", + "nodeName": "b_Tail03_014", + "nodePath": "0/0/0/0/0/1/0/0", + "interactionId": "interaction-e93e191e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 24.24032211303711, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.10771755940908084 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-18": { + "name": "b_LeftLeg01_015", + "nodeName": "b_LeftLeg01_015", + "nodePath": "0/0/0/0/0/2", + "interactionId": "interaction-643ea143", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 4.813770294189453, + 5.154018402099609, + -6.968006134033203 + ], + "rotation": [ + 0.0003332048354397326, + 0.00008348584072415229, + -2.6505924384110937 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-19": { + "name": "b_LeftLeg02_016", + "nodeName": "b_LeftLeg02_016", + "nodePath": "0/0/0/0/0/2/0", + "interactionId": "interaction-7175f8dc", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.944175720214844, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.7538085117951059 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-20": { + "name": "b_LeftFoot01_017", + "nodeName": "b_LeftFoot01_017", + "nodePath": "0/0/0/0/0/2/0/0", + "interactionId": "interaction-f5ed353b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 17.942811965942383, + 0, + 0 + ], + "rotation": [ + 0.00044152629033825986, + 0.0002277846223534801, + 0.9525774122187588 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-21": { + "name": "b_LeftFoot02_018", + "nodeName": "b_LeftFoot02_018", + "nodePath": "0/0/0/0/0/2/0/0/0", + "interactionId": "interaction-1bbe01a4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 15.779938697814941, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 1.158241570830627 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-22": { + "name": "b_RightLeg01_019", + "nodeName": "b_RightLeg01_019", + "nodePath": "0/0/0/0/0/3", + "interactionId": "interaction-633e9fb0", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 4.813777923583984, + 5.154026031494141, + 6.967563629150391 + ], + "rotation": [ + 0, + 0, + -2.6501210928667223 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-23": { + "name": "b_RightLeg02_020", + "nodeName": "b_RightLeg02_020", + "nodePath": "0/0/0/0/0/3/0", + "interactionId": "interaction-95ff89c7", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.944183349609375, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.7538085672160094 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-24": { + "name": "b_RightFoot01_021", + "nodeName": "b_RightFoot01_021", + "nodePath": "0/0/0/0/0/3/0/0", + "interactionId": "interaction-a157d498", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 17.94281005859375, + 0, + 0 + ], + "rotation": [ + -0.00027284186307510456, + -0.00014053656253775514, + 0.9512842084783865 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-25": { + "name": "b_RightFoot02_022", + "nodeName": "b_RightFoot02_022", + "nodePath": "0/0/0/0/0/3/0/0/0", + "interactionId": "interaction-ebd38e3f", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 15.779935836791992, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 1.158241570830627 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-26": { + "name": "fox", + "nodeName": "fox", + "nodePath": "0/1", + "interactionId": "interaction-a3d35c26", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 0.58, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + } + }, + "assets": [ + { + "code": "MODEL_BRIDGE-ERECTOR-VEHICLE", + "name": "桥梁架设装备整机", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "", + "storageUri": "/models/bridge-erector-vehicle.glb", + "builtIn": true + }, + { + "code": "MODEL_MTO6V5W6_09-FOX", + "name": "09-Fox.glb", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "d97044e701822bac5a62696459b27d7b375aada5de8574ed4362edbba94771f7", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb" + } + ] + }, + "expectedX": 0.25, + "expectedRoughness": 0.3, + "edited": { + "server": { + "projectId": "157", + "code": "MODEL-70875AA932B94685", + "name": "实测模型-狐狸动画-20260905", + "status": "DRAFT", + "version": 5, + "publishedVersionId": null, + "currentVersionId": "199", + "versionNo": 1, + "checksum": "041667300586ffea8aaba2ba29004cf4ca50dc0f01351215a664f64fa82ab5b9", + "schema": "digital-twin-editor-project", + "modelResource": { + "kind": "imported", + "id": "imported-model_mto6v5w6_09-fox", + "name": "09-Fox", + "assetCode": "MODEL_MTO6V5W6_09-FOX", + "code": "MODEL_MTO6V5W6_09-FOX", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb", + "resourceUrl": "", + "sourceName": "09-Fox.glb", + "sizeBytes": 162852, + "lastModified": 0, + "mimeType": "model/gltf-binary", + "thumbnail": "", + "vertices": 1728, + "triangles": 576, + "nodes": 27, + "meshes": 1, + "materials": 1, + "textures": 1, + "animations": 3, + "animationDurationSeconds": 3.4166667461395264, + "modelMetadata": { + "nodeCount": 27, + "meshCount": 1, + "materialCount": 1, + "textureCount": 1, + "animations": [ + { + "index": 0, + "name": "Survey", + "start": 0, + "end": 3.4166667461395264, + "duration": 3.4166667461395264, + "trackCount": 21 + }, + { + "index": 1, + "name": "Walk", + "start": 0, + "end": 0.7083333134651184, + "duration": 0.7083333134651184, + "trackCount": 21 + }, + { + "index": 2, + "name": "Run", + "start": 0, + "end": 1.1583333015441895, + "duration": 1.1583333015441895, + "trackCount": 21 + } + ], + "animationDurationSeconds": 3.4166667461395264 + }, + "nativeAnimations": [ + { + "index": 0, + "name": "Survey", + "start": 0, + "end": 3.4166667461395264, + "duration": 3.4166667461395264, + "trackCount": 21 + }, + { + "index": 1, + "name": "Walk", + "start": 0, + "end": 0.7083333134651184, + "duration": 0.7083333134651184, + "trackCount": 21 + }, + { + "index": 2, + "name": "Run", + "start": 0, + "end": 1.1583333015441895, + "duration": 1.1583333015441895, + "trackCount": 21 + } + ] + }, + "nativeAnimation": { + "clipIndex": 2, + "clipName": "Run" + }, + "modelObjects": { + "equipment-root": { + "name": "09-Fox", + "nodeName": "09-Fox", + "nodePath": "@root", + "interactionId": "interaction-b9240aaa", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-0": { + "name": "", + "nodeName": "Group", + "nodePath": "0", + "interactionId": "interaction-02351bce", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 3.875009990661482e-8, + 0.007396563645075124, + 0.6522089834776823 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.06075496488891343, + 0.06075496488891343, + 0.06075496488891343 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-1": { + "name": "root", + "nodeName": "root", + "nodePath": "0/0", + "interactionId": "interaction-a4d35db9", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-2": { + "name": "_rootJoint", + "nodeName": "_rootJoint", + "nodePath": "0/0/0", + "interactionId": "interaction-4476c556", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-3": { + "name": "b_Root_00", + "nodeName": "b_Root_00", + "nodePath": "0/0/0/0", + "interactionId": "interaction-ffc45d11", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + -1.5708000357176293, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-4": { + "name": "b_Hip_01", + "nodeName": "b_Hip_01", + "nodePath": "0/0/0/0/0", + "interactionId": "interaction-7a75e39e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 26.748403549194336, + 42.93817138671875 + ], + "rotation": [ + 0.36315579795853176, + -1.5707952841394475, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-5": { + "name": "b_Spine01_02", + "nodeName": "b_Spine01_02", + "nodePath": "0/0/0/0/0/0", + "interactionId": "interaction-663ea469", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 12.850601196289062, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -1.2631477544403162 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-6": { + "name": "b_Spine02_03", + "nodeName": "b_Spine02_03", + "nodePath": "0/0/0/0/0/0/0", + "interactionId": "interaction-46867126", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 21.65575408935547, + -0.000118255615234375, + 0 + ], + "rotation": [ + 0, + 0, + 0.03482566467786662 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-7": { + "name": "b_Neck_04", + "nodeName": "b_Neck_04", + "nodePath": "0/0/0/0/0/0/0/0", + "interactionId": "interaction-27148d81", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 25.64914321899414, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0.616473876457289 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-8": { + "name": "b_Head_05", + "nodeName": "b_Head_05", + "nodePath": "0/0/0/0/0/0/0/0/0", + "interactionId": "interaction-b24eef2e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 13.376960754394531, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.8236565613916008 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-9": { + "name": "b_RightUpperArm_06", + "nodeName": "b_RightUpperArm_06", + "nodePath": "0/0/0/0/0/0/0/1", + "interactionId": "interaction-26148bee", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.677913665771484, + -4.297340393066406, + 6.9675750732421875 + ], + "rotation": [ + 0.000020649684502855715, + -0.0012920321082461929, + -1.5851959113548921 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-10": { + "name": "b_RightForeArm_07", + "nodeName": "b_RightForeArm_07", + "nodePath": "0/0/0/0/0/0/0/1/0", + "interactionId": "interaction-36896559", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 23.04512596130371, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0.07426886741269867 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-11": { + "name": "b_RightHand_08", + "nodeName": "b_RightHand_08", + "nodePath": "0/0/0/0/0/0/0/1/0/0", + "interactionId": "interaction-57a124f6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 19.350055694580078, + -0.14598655700683594, + 0 + ], + "rotation": [ + -0.014166329641847676, + -0.024975147923384556, + 0.9571872589843109 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-12": { + "name": "b_LeftUpperArm_09", + "nodeName": "b_LeftUpperArm_09", + "nodePath": "0/0/0/0/0/0/0/2", + "interactionId": "interaction-25148a5b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.67791748046875, + -4.297344207763672, + -6.967987060546875 + ], + "rotation": [ + -0.0005581520651140974, + -0.0019469460390509152, + -1.5849355765797046 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-13": { + "name": "b_LeftForeArm_010", + "nodeName": "b_LeftForeArm_010", + "nodePath": "0/0/0/0/0/0/0/2/0", + "interactionId": "interaction-5c502ac4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 23.045124053955078, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0.07426886741269867 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-14": { + "name": "b_LeftHand_011", + "nodeName": "b_LeftHand_011", + "nodePath": "0/0/0/0/0/0/0/2/0/0", + "interactionId": "interaction-192b4cd3", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 19.350051879882812, + -0.14599037170410156, + 0 + ], + "rotation": [ + 0.016442303987465122, + 0.04008733863576039, + 0.9560742489627883 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-15": { + "name": "b_Tail01_012", + "nodeName": "b_Tail01_012", + "nodePath": "0/0/0/0/0/1", + "interactionId": "interaction-653ea2d6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 4.2603759765625, + 15.958770751953125, + 0 + ], + "rotation": [ + 0, + 0, + 2.760415362743526 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-16": { + "name": "b_Tail02_013", + "nodeName": "b_Tail02_013", + "nodePath": "0/0/0/0/0/1/0", + "interactionId": "interaction-6c4d3691", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 12.411918640136719, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.1393470463625701 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-17": { + "name": "b_Tail03_014", + "nodeName": "b_Tail03_014", + "nodePath": "0/0/0/0/0/1/0/0", + "interactionId": "interaction-e93e191e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 24.24032211303711, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.10771755940908084 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-18": { + "name": "b_LeftLeg01_015", + "nodeName": "b_LeftLeg01_015", + "nodePath": "0/0/0/0/0/2", + "interactionId": "interaction-643ea143", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 4.813770294189453, + 5.154018402099609, + -6.968006134033203 + ], + "rotation": [ + 0.0003332048354397326, + 0.00008348584072415229, + -2.6505924384110937 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-19": { + "name": "b_LeftLeg02_016", + "nodeName": "b_LeftLeg02_016", + "nodePath": "0/0/0/0/0/2/0", + "interactionId": "interaction-7175f8dc", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.944175720214844, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.7538085117951059 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-20": { + "name": "b_LeftFoot01_017", + "nodeName": "b_LeftFoot01_017", + "nodePath": "0/0/0/0/0/2/0/0", + "interactionId": "interaction-f5ed353b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 17.942811965942383, + 0, + 0 + ], + "rotation": [ + 0.00044152629033825986, + 0.0002277846223534801, + 0.9525774122187588 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-21": { + "name": "b_LeftFoot02_018", + "nodeName": "b_LeftFoot02_018", + "nodePath": "0/0/0/0/0/2/0/0/0", + "interactionId": "interaction-1bbe01a4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 15.779938697814941, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 1.158241570830627 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-22": { + "name": "b_RightLeg01_019", + "nodeName": "b_RightLeg01_019", + "nodePath": "0/0/0/0/0/3", + "interactionId": "interaction-633e9fb0", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 4.813777923583984, + 5.154026031494141, + 6.967563629150391 + ], + "rotation": [ + 0, + 0, + -2.6501210928667223 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-23": { + "name": "b_RightLeg02_020", + "nodeName": "b_RightLeg02_020", + "nodePath": "0/0/0/0/0/3/0", + "interactionId": "interaction-95ff89c7", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.944183349609375, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.7538085672160094 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-24": { + "name": "b_RightFoot01_021", + "nodeName": "b_RightFoot01_021", + "nodePath": "0/0/0/0/0/3/0/0", + "interactionId": "interaction-a157d498", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 17.94281005859375, + 0, + 0 + ], + "rotation": [ + -0.00027284186307510456, + -0.00014053656253775514, + 0.9512842084783865 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-25": { + "name": "b_RightFoot02_022", + "nodeName": "b_RightFoot02_022", + "nodePath": "0/0/0/0/0/3/0/0/0", + "interactionId": "interaction-ebd38e3f", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 15.779935836791992, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 1.158241570830627 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-26": { + "name": "fox", + "nodeName": "fox", + "nodePath": "0/1", + "interactionId": "interaction-a3d35c26", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0.25, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + } + }, + "assets": [ + { + "code": "MODEL_BRIDGE-ERECTOR-VEHICLE", + "name": "桥梁架设装备整机", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "", + "storageUri": "/models/bridge-erector-vehicle.glb", + "builtIn": true + }, + { + "code": "MODEL_MTO6V5W6_09-FOX", + "name": "09-Fox.glb", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "d97044e701822bac5a62696459b27d7b375aada5de8574ed4362edbba94771f7", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb" + } + ] + }, + "live": { + "sourceName": "09-Fox.glb", + "assetCode": "MODEL_MTO6V5W6_09-FOX", + "nodes": 27, + "meshes": 1, + "materials": 1, + "clips": [ + { + "name": "Survey", + "duration": 3.4166667461395264, + "tracks": 21 + }, + { + "name": "Walk", + "duration": 0.7083333134651184, + "tracks": 21 + }, + { + "name": "Run", + "duration": 1.1583333015441895, + "tracks": 21 + } + ], + "clipIndex": 2, + "playing": false, + "time": 0, + "mesh": { + "name": "fox", + "editorId": "model-imported-model_mto6v5w6_09-fox-26", + "position": [ + 0.25, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "isSkinnedMesh": true, + "bones": 24 + }, + "moving": [ + { + "name": "_rootJoint", + "quaternion": [ + 0, + 0, + 0, + 1 + ] + }, + { + "name": "b_Root_00", + "quaternion": [ + -0.7071080924875391, + 0, + 0, + 0.7071054698831242 + ] + }, + { + "name": "b_Hip_01", + "quaternion": [ + 0.12769094176175547, + -0.6954820192393762, + -0.12769022650601444, + 0.695481840425441 + ] + }, + { + "name": "b_Spine01_02", + "quaternion": [ + 0, + 0, + -0.5904157638238317, + 0.8070992664030376 + ] + }, + { + "name": "b_Spine02_03", + "quaternion": [ + 0, + 0, + 0.017411952404281082, + 0.9998484004655261 + ] + }, + { + "name": "b_Neck_04", + "quaternion": [ + 0, + 0, + 0.30337914028264346, + 0.9528699267168443 + ] + }, + { + "name": "b_Head_05", + "quaternion": [ + 0, + 0, + -0.4002854151487349, + 0.9163905206947555 + ] + }, + { + "name": "b_RightUpperArm_06", + "quaternion": [ + 0.0004673273262011562, + -0.0004461484692255928, + -0.7121792881110691, + 0.7019973248825985 + ] + }, + { + "name": "b_RightForeArm_07", + "quaternion": [ + 0, + 0, + 0.03712589977348744, + 0.9993105961441663 + ] + }, + { + "name": "b_RightHand_08", + "quaternion": [ + -0.012037406914797018, + -0.00782221012465276, + 0.4605623277185148, + 0.8875112709988741 + ] + }, + { + "name": "b_LeftUpperArm_09", + "quaternion": [ + 0.0004972619220940174, + -0.0008821923166442875, + -0.7120874929914663, + 0.7020900061903927 + ] + }, + { + "name": "b_LeftForeArm_010", + "quaternion": [ + 0, + 0, + 0.03712589977348744, + 0.9993105961441663 + ] + }, + { + "name": "b_LeftHand_011", + "quaternion": [ + 0.01651791440721507, + 0.014013739873997781, + 0.46007557521271, + 0.8876154790736099 + ] + }, + { + "name": "b_Tail01_012", + "quaternion": [ + 0, + 0, + 0.9818928940656295, + 0.1894369145214904 + ] + }, + { + "name": "b_Tail02_013", + "quaternion": [ + 0, + 0, + -0.0696171663387466, + 0.9975737818081244 + ] + }, + { + "name": "b_Tail03_014", + "quaternion": [ + 0, + 0, + -0.05383274484207684, + 0.9985499664927979 + ] + }, + { + "name": "b_LeftLeg01_015", + "quaternion": [ + 0, + -0.0001717522536559936, + 0.9700158834020681, + -0.2430414706359161 + ] + }, + { + "name": "b_LeftLeg02_016", + "quaternion": [ + 0, + 0, + -0.36804378855511655, + 0.9298084586117706 + ] + }, + { + "name": "b_LeftFoot01_017", + "quaternion": [ + 0.0002484105929664666, + 0, + 0.4584841122585099, + 0.888702569535333 + ] + }, + { + "name": "b_LeftFoot02_018", + "quaternion": [ + 0, + 0, + 0.5472882949090243, + 0.8369441571906533 + ] + }, + { + "name": "b_RightLeg01_019", + "quaternion": [ + 0, + 0, + 0.9699585942054535, + -0.24327006705918533 + ] + }, + { + "name": "b_RightLeg02_020", + "quaternion": [ + 0, + 0, + -0.36804381432052885, + 0.9298084484131106 + ] + }, + { + "name": "b_RightFoot01_021", + "quaternion": [ + -0.00015345455876803163, + 0, + 0.4579093746168346, + 0.888998864504178 + ] + }, + { + "name": "b_RightFoot02_022", + "quaternion": [ + 0, + 0, + 0.5472882949090243, + 0.8369441571906533 + ] + } + ], + "onlyActivePivot": true + }, + "status": "PASS" + }, + "reopened": { + "server": { + "projectId": "157", + "code": "MODEL-70875AA932B94685", + "name": "实测模型-狐狸动画-20260905", + "status": "DRAFT", + "version": 5, + "publishedVersionId": null, + "currentVersionId": "199", + "versionNo": 1, + "checksum": "041667300586ffea8aaba2ba29004cf4ca50dc0f01351215a664f64fa82ab5b9", + "schema": "digital-twin-editor-project", + "modelResource": { + "kind": "imported", + "id": "imported-model_mto6v5w6_09-fox", + "name": "09-Fox", + "assetCode": "MODEL_MTO6V5W6_09-FOX", + "code": "MODEL_MTO6V5W6_09-FOX", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb", + "resourceUrl": "", + "sourceName": "09-Fox.glb", + "sizeBytes": 162852, + "lastModified": 0, + "mimeType": "model/gltf-binary", + "thumbnail": "", + "vertices": 1728, + "triangles": 576, + "nodes": 27, + "meshes": 1, + "materials": 1, + "textures": 1, + "animations": 3, + "animationDurationSeconds": 3.4166667461395264, + "modelMetadata": { + "nodeCount": 27, + "meshCount": 1, + "materialCount": 1, + "textureCount": 1, + "animations": [ + { + "index": 0, + "name": "Survey", + "start": 0, + "end": 3.4166667461395264, + "duration": 3.4166667461395264, + "trackCount": 21 + }, + { + "index": 1, + "name": "Walk", + "start": 0, + "end": 0.7083333134651184, + "duration": 0.7083333134651184, + "trackCount": 21 + }, + { + "index": 2, + "name": "Run", + "start": 0, + "end": 1.1583333015441895, + "duration": 1.1583333015441895, + "trackCount": 21 + } + ], + "animationDurationSeconds": 3.4166667461395264 + }, + "nativeAnimations": [ + { + "index": 0, + "name": "Survey", + "start": 0, + "end": 3.4166667461395264, + "duration": 3.4166667461395264, + "trackCount": 21 + }, + { + "index": 1, + "name": "Walk", + "start": 0, + "end": 0.7083333134651184, + "duration": 0.7083333134651184, + "trackCount": 21 + }, + { + "index": 2, + "name": "Run", + "start": 0, + "end": 1.1583333015441895, + "duration": 1.1583333015441895, + "trackCount": 21 + } + ] + }, + "nativeAnimation": { + "clipIndex": 2, + "clipName": "Run" + }, + "modelObjects": { + "equipment-root": { + "name": "09-Fox", + "nodeName": "09-Fox", + "nodePath": "@root", + "interactionId": "interaction-b9240aaa", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-0": { + "name": "", + "nodeName": "Group", + "nodePath": "0", + "interactionId": "interaction-02351bce", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 3.875009990661482e-8, + 0.007396563645075124, + 0.6522089834776823 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.06075496488891343, + 0.06075496488891343, + 0.06075496488891343 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-1": { + "name": "root", + "nodeName": "root", + "nodePath": "0/0", + "interactionId": "interaction-a4d35db9", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-2": { + "name": "_rootJoint", + "nodeName": "_rootJoint", + "nodePath": "0/0/0", + "interactionId": "interaction-4476c556", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-3": { + "name": "b_Root_00", + "nodeName": "b_Root_00", + "nodePath": "0/0/0/0", + "interactionId": "interaction-ffc45d11", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + -1.5708000357176293, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-4": { + "name": "b_Hip_01", + "nodeName": "b_Hip_01", + "nodePath": "0/0/0/0/0", + "interactionId": "interaction-7a75e39e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 26.748403549194336, + 42.93817138671875 + ], + "rotation": [ + 0.36315579795853176, + -1.5707952841394475, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-5": { + "name": "b_Spine01_02", + "nodeName": "b_Spine01_02", + "nodePath": "0/0/0/0/0/0", + "interactionId": "interaction-663ea469", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 12.850601196289062, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -1.2631477544403162 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-6": { + "name": "b_Spine02_03", + "nodeName": "b_Spine02_03", + "nodePath": "0/0/0/0/0/0/0", + "interactionId": "interaction-46867126", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 21.65575408935547, + -0.000118255615234375, + 0 + ], + "rotation": [ + 0, + 0, + 0.03482566467786662 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-7": { + "name": "b_Neck_04", + "nodeName": "b_Neck_04", + "nodePath": "0/0/0/0/0/0/0/0", + "interactionId": "interaction-27148d81", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 25.64914321899414, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0.616473876457289 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-8": { + "name": "b_Head_05", + "nodeName": "b_Head_05", + "nodePath": "0/0/0/0/0/0/0/0/0", + "interactionId": "interaction-b24eef2e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 13.376960754394531, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.8236565613916008 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-9": { + "name": "b_RightUpperArm_06", + "nodeName": "b_RightUpperArm_06", + "nodePath": "0/0/0/0/0/0/0/1", + "interactionId": "interaction-26148bee", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.677913665771484, + -4.297340393066406, + 6.9675750732421875 + ], + "rotation": [ + 0.000020649684502855715, + -0.0012920321082461929, + -1.5851959113548921 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-10": { + "name": "b_RightForeArm_07", + "nodeName": "b_RightForeArm_07", + "nodePath": "0/0/0/0/0/0/0/1/0", + "interactionId": "interaction-36896559", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 23.04512596130371, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0.07426886741269867 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-11": { + "name": "b_RightHand_08", + "nodeName": "b_RightHand_08", + "nodePath": "0/0/0/0/0/0/0/1/0/0", + "interactionId": "interaction-57a124f6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 19.350055694580078, + -0.14598655700683594, + 0 + ], + "rotation": [ + -0.014166329641847676, + -0.024975147923384556, + 0.9571872589843109 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-12": { + "name": "b_LeftUpperArm_09", + "nodeName": "b_LeftUpperArm_09", + "nodePath": "0/0/0/0/0/0/0/2", + "interactionId": "interaction-25148a5b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.67791748046875, + -4.297344207763672, + -6.967987060546875 + ], + "rotation": [ + -0.0005581520651140974, + -0.0019469460390509152, + -1.5849355765797046 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-13": { + "name": "b_LeftForeArm_010", + "nodeName": "b_LeftForeArm_010", + "nodePath": "0/0/0/0/0/0/0/2/0", + "interactionId": "interaction-5c502ac4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 23.045124053955078, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0.07426886741269867 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-14": { + "name": "b_LeftHand_011", + "nodeName": "b_LeftHand_011", + "nodePath": "0/0/0/0/0/0/0/2/0/0", + "interactionId": "interaction-192b4cd3", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 19.350051879882812, + -0.14599037170410156, + 0 + ], + "rotation": [ + 0.016442303987465122, + 0.04008733863576039, + 0.9560742489627883 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-15": { + "name": "b_Tail01_012", + "nodeName": "b_Tail01_012", + "nodePath": "0/0/0/0/0/1", + "interactionId": "interaction-653ea2d6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 4.2603759765625, + 15.958770751953125, + 0 + ], + "rotation": [ + 0, + 0, + 2.760415362743526 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-16": { + "name": "b_Tail02_013", + "nodeName": "b_Tail02_013", + "nodePath": "0/0/0/0/0/1/0", + "interactionId": "interaction-6c4d3691", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 12.411918640136719, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.1393470463625701 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-17": { + "name": "b_Tail03_014", + "nodeName": "b_Tail03_014", + "nodePath": "0/0/0/0/0/1/0/0", + "interactionId": "interaction-e93e191e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 24.24032211303711, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.10771755940908084 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-18": { + "name": "b_LeftLeg01_015", + "nodeName": "b_LeftLeg01_015", + "nodePath": "0/0/0/0/0/2", + "interactionId": "interaction-643ea143", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 4.813770294189453, + 5.154018402099609, + -6.968006134033203 + ], + "rotation": [ + 0.0003332048354397326, + 0.00008348584072415229, + -2.6505924384110937 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-19": { + "name": "b_LeftLeg02_016", + "nodeName": "b_LeftLeg02_016", + "nodePath": "0/0/0/0/0/2/0", + "interactionId": "interaction-7175f8dc", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.944175720214844, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.7538085117951059 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-20": { + "name": "b_LeftFoot01_017", + "nodeName": "b_LeftFoot01_017", + "nodePath": "0/0/0/0/0/2/0/0", + "interactionId": "interaction-f5ed353b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 17.942811965942383, + 0, + 0 + ], + "rotation": [ + 0.00044152629033825986, + 0.0002277846223534801, + 0.9525774122187588 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-21": { + "name": "b_LeftFoot02_018", + "nodeName": "b_LeftFoot02_018", + "nodePath": "0/0/0/0/0/2/0/0/0", + "interactionId": "interaction-1bbe01a4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 15.779938697814941, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 1.158241570830627 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-22": { + "name": "b_RightLeg01_019", + "nodeName": "b_RightLeg01_019", + "nodePath": "0/0/0/0/0/3", + "interactionId": "interaction-633e9fb0", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 4.813777923583984, + 5.154026031494141, + 6.967563629150391 + ], + "rotation": [ + 0, + 0, + -2.6501210928667223 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-23": { + "name": "b_RightLeg02_020", + "nodeName": "b_RightLeg02_020", + "nodePath": "0/0/0/0/0/3/0", + "interactionId": "interaction-95ff89c7", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.944183349609375, + 0, + 0 + ], + "rotation": [ + 0, + 0, + -0.7538085672160094 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-24": { + "name": "b_RightFoot01_021", + "nodeName": "b_RightFoot01_021", + "nodePath": "0/0/0/0/0/3/0/0", + "interactionId": "interaction-a157d498", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 17.94281005859375, + 0, + 0 + ], + "rotation": [ + -0.00027284186307510456, + -0.00014053656253775514, + 0.9512842084783865 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-25": { + "name": "b_RightFoot02_022", + "nodeName": "b_RightFoot02_022", + "nodePath": "0/0/0/0/0/3/0/0/0", + "interactionId": "interaction-ebd38e3f", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 15.779935836791992, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 1.158241570830627 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-26": { + "name": "fox", + "nodeName": "fox", + "nodePath": "0/1", + "interactionId": "interaction-a3d35c26", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0.25, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + } + }, + "assets": [ + { + "code": "MODEL_BRIDGE-ERECTOR-VEHICLE", + "name": "桥梁架设装备整机", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "", + "storageUri": "/models/bridge-erector-vehicle.glb", + "builtIn": true + }, + { + "code": "MODEL_MTO6V5W6_09-FOX", + "name": "09-Fox.glb", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "d97044e701822bac5a62696459b27d7b375aada5de8574ed4362edbba94771f7", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb" + } + ] + }, + "live": { + "sourceName": "09-Fox.glb", + "assetCode": "MODEL_MTO6V5W6_09-FOX", + "nodes": 27, + "meshes": 1, + "materials": 1, + "clips": [ + { + "name": "Survey", + "duration": 3.4166667461395264, + "tracks": 21 + }, + { + "name": "Walk", + "duration": 0.7083333134651184, + "tracks": 21 + }, + { + "name": "Run", + "duration": 1.1583333015441895, + "tracks": 21 + } + ], + "clipIndex": 2, + "playing": false, + "time": 0, + "mesh": { + "name": "fox", + "editorId": "model-imported-model_mto6v5w6_09-fox-26", + "position": [ + 0.25, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "isSkinnedMesh": true, + "bones": 24 + }, + "moving": [ + { + "name": "_rootJoint", + "quaternion": [ + 0, + 0, + 0, + 1 + ] + }, + { + "name": "b_Root_00", + "quaternion": [ + -0.7071080924875393, + 0, + 0, + 0.7071054698831241 + ] + }, + { + "name": "b_Hip_01", + "quaternion": [ + 0.12769065070251467, + -0.6954815672583988, + -0.12769051756523134, + 0.6954822924064228 + ] + }, + { + "name": "b_Spine01_02", + "quaternion": [ + 0, + 0, + -0.5904157638238317, + 0.8070992664030376 + ] + }, + { + "name": "b_Spine02_03", + "quaternion": [ + 0, + 0, + 0.017411952404281082, + 0.9998484004655261 + ] + }, + { + "name": "b_Neck_04", + "quaternion": [ + 0, + 0, + 0.30337914028264346, + 0.9528699267168442 + ] + }, + { + "name": "b_Head_05", + "quaternion": [ + 0, + 0, + -0.4002854151487349, + 0.9163905206947555 + ] + }, + { + "name": "b_RightUpperArm_06", + "quaternion": [ + 0.00046732732620115617, + -0.00044614846922559273, + -0.7121792881110691, + 0.7019973248825985 + ] + }, + { + "name": "b_RightForeArm_07", + "quaternion": [ + 0, + 0, + 0.03712589977348744, + 0.9993105961441663 + ] + }, + { + "name": "b_RightHand_08", + "quaternion": [ + -0.01203740691479702, + -0.00782221012465276, + 0.4605623277185148, + 0.887511270998874 + ] + }, + { + "name": "b_LeftUpperArm_09", + "quaternion": [ + 0.0004972619220940176, + -0.0008821923166442874, + -0.7120874929914663, + 0.7020900061903925 + ] + }, + { + "name": "b_LeftForeArm_010", + "quaternion": [ + 0, + 0, + 0.03712589977348744, + 0.9993105961441663 + ] + }, + { + "name": "b_LeftHand_011", + "quaternion": [ + 0.016517914407215076, + 0.014013739873997785, + 0.46007557521271003, + 0.8876154790736098 + ] + }, + { + "name": "b_Tail01_012", + "quaternion": [ + 0, + 0, + 0.9818928940656295, + 0.18943691452149047 + ] + }, + { + "name": "b_Tail02_013", + "quaternion": [ + 0, + 0, + -0.0696171663387466, + 0.9975737818081244 + ] + }, + { + "name": "b_Tail03_014", + "quaternion": [ + 0, + 0, + -0.05383274484207684, + 0.9985499664927979 + ] + }, + { + "name": "b_LeftLeg01_015", + "quaternion": [ + -1.3552527156068805e-20, + 0.00017175225365599357, + -0.970015883402068, + 0.24304147063591605 + ] + }, + { + "name": "b_LeftLeg02_016", + "quaternion": [ + 0, + 0, + -0.36804378855511655, + 0.9298084586117705 + ] + }, + { + "name": "b_LeftFoot01_017", + "quaternion": [ + 0.0002484105929664666, + 1.3552527156068805e-20, + 0.4584841122585098, + 0.888702569535333 + ] + }, + { + "name": "b_LeftFoot02_018", + "quaternion": [ + 0, + 0, + 0.5472882949090243, + 0.8369441571906532 + ] + }, + { + "name": "b_RightLeg01_019", + "quaternion": [ + 0, + 0, + -0.9699585942054534, + 0.2432700670591853 + ] + }, + { + "name": "b_RightLeg02_020", + "quaternion": [ + 0, + 0, + -0.36804381432052885, + 0.9298084484131105 + ] + }, + { + "name": "b_RightFoot01_021", + "quaternion": [ + -0.00015345455876803165, + 0, + 0.45790937461683456, + 0.888998864504178 + ] + }, + { + "name": "b_RightFoot02_022", + "quaternion": [ + 0, + 0, + 0.5472882949090243, + 0.8369441571906532 + ] + } + ], + "onlyActivePivot": true + }, + "status": "PASS" + }, + "animation": { + "clip": "Run", + "before": { + "sourceName": "09-Fox.glb", + "assetCode": "MODEL_MTO6V5W6_09-FOX", + "nodes": 27, + "meshes": 1, + "materials": 1, + "clips": [ + { + "name": "Survey", + "duration": 3.4166667461395264, + "tracks": 21 + }, + { + "name": "Walk", + "duration": 0.7083333134651184, + "tracks": 21 + }, + { + "name": "Run", + "duration": 1.1583333015441895, + "tracks": 21 + } + ], + "clipIndex": 2, + "playing": true, + "time": 0.017099999904632568, + "mesh": { + "name": "fox", + "editorId": "model-imported-model_mto6v5w6_09-fox-26", + "position": [ + 0.25, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "isSkinnedMesh": true, + "bones": 24 + }, + "moving": [ + { + "name": "_rootJoint", + "quaternion": [ + 0, + 0, + 0, + 1 + ] + }, + { + "name": "b_Root_00", + "quaternion": [ + -0.7071080924875393, + 0, + 0, + 0.7071054698831241 + ] + }, + { + "name": "b_Hip_01", + "quaternion": [ + 0.16991514822336803, + -0.68638833346742, + -0.16991430763560345, + 0.6863883930725825 + ] + }, + { + "name": "b_Spine01_02", + "quaternion": [ + -1.2776481012083008e-7, + -1.1013624619697844e-7, + -0.5623607656474715, + 0.8268919937091913 + ] + }, + { + "name": "b_Spine02_03", + "quaternion": [ + 4.539715822229708e-8, + 1.1884002693239777e-8, + 0.2532443739326937, + 0.967402339810813 + ] + }, + { + "name": "b_Neck_04", + "quaternion": [ + 3.200580452933074e-15, + -2.8741309463544697e-16, + -0.08944042489738022, + 0.9959921738619115 + ] + }, + { + "name": "b_Head_05", + "quaternion": [ + 1.7757515590255584e-8, + -3.3990733685192647e-9, + -0.18800281307827543, + 0.9821684897585824 + ] + }, + { + "name": "b_RightUpperArm_06", + "quaternion": [ + -0.004116540287453186, + -0.0070894787068181975, + -0.8334808289241821, + 0.5524875569930349 + ] + }, + { + "name": "b_RightForeArm_07", + "quaternion": [ + 2.7909125175183022e-8, + 2.4651837932162735e-8, + 0.660485894127654, + 0.7508384537691126 + ] + }, + { + "name": "b_RightHand_08", + "quaternion": [ + -0.008992157051067998, + 0.009789583541467162, + -0.3575138603635345, + 0.9338132201428498 + ] + }, + { + "name": "b_LeftUpperArm_09", + "quaternion": [ + 0.08204589068680045, + -0.010486924736425901, + 0.9855621554884437, + -0.1477353447174665 + ] + }, + { + "name": "b_LeftForeArm_010", + "quaternion": [ + 3.4187555353785944e-8, + 3.1884524369027206e-8, + 0.7272007051782857, + 0.6864249098981012 + ] + }, + { + "name": "b_LeftHand_011", + "quaternion": [ + 0.087838458592476, + 0.025652862473672274, + -0.695062376790579, + 0.7131021173061576 + ] + }, + { + "name": "b_Tail01_012", + "quaternion": [ + -1.1265437347297536e-7, + 2.9762947247670616e-7, + 0.9764503680868666, + 0.21574220875054664 + ] + }, + { + "name": "b_Tail02_013", + "quaternion": [ + 1.291933291173545e-22, + 2.0261843698663746e-22, + -0.20179254486125706, + 0.9794282956537566 + ] + }, + { + "name": "b_Tail03_014", + "quaternion": [ + -1.908022984424946e-23, + 1.4448632219805905e-22, + -0.20639585440533034, + 0.9784685745001185 + ] + }, + { + "name": "b_LeftLeg01_015", + "quaternion": [ + -0.04603984620334452, + -0.0787759971758508, + 0.8964379776626956, + -0.43367458111915125 + ] + }, + { + "name": "b_LeftLeg02_016", + "quaternion": [ + 9.619476719571785e-9, + 1.658504428737043e-8, + -0.6192219938561454, + 0.7852159732072508 + ] + }, + { + "name": "b_LeftFoot01_017", + "quaternion": [ + -0.027549151248469964, + -0.11546479069907195, + 0.6720924736268539, + 0.7308903018021551 + ] + }, + { + "name": "b_LeftFoot02_018", + "quaternion": [ + 0, + 0, + 0.5472882949090243, + 0.8369441571906532 + ] + }, + { + "name": "b_RightLeg01_019", + "quaternion": [ + -0.036771968158973385, + -0.0731022107438237, + -0.7136630897029559, + 0.6956930912256976 + ] + }, + { + "name": "b_RightLeg02_020", + "quaternion": [ + 6.478740643014005e-9, + 1.7237121126490877e-8, + -0.5329208428274621, + 0.8461651114569708 + ] + }, + { + "name": "b_RightFoot01_021", + "quaternion": [ + 0.06483073357521733, + 0.1544673050289487, + 0.5406460759117439, + 0.824401994334333 + ] + }, + { + "name": "b_RightFoot02_022", + "quaternion": [ + 0, + 0, + 0.5472882949090243, + 0.8369441571906532 + ] + } + ], + "onlyActivePivot": true + }, + "after": { + "sourceName": "09-Fox.glb", + "assetCode": "MODEL_MTO6V5W6_09-FOX", + "nodes": 27, + "meshes": 1, + "materials": 1, + "clips": [ + { + "name": "Survey", + "duration": 3.4166667461395264, + "tracks": 21 + }, + { + "name": "Walk", + "duration": 0.7083333134651184, + "tracks": 21 + }, + { + "name": "Run", + "duration": 1.1583333015441895, + "tracks": 21 + } + ], + "clipIndex": 2, + "playing": true, + "time": 0.133, + "mesh": { + "name": "fox", + "editorId": "model-imported-model_mto6v5w6_09-fox-26", + "position": [ + 0.25, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "isSkinnedMesh": true, + "bones": 24 + }, + "moving": [ + { + "name": "_rootJoint", + "quaternion": [ + 0, + 0, + 0, + 1 + ] + }, + { + "name": "b_Root_00", + "quaternion": [ + -0.7071080924875393, + 0, + 0, + 0.7071054698831241 + ] + }, + { + "name": "b_Hip_01", + "quaternion": [ + 0.16103866992304935, + -0.6885249867758381, + -0.16103793404344358, + 0.6885249982199388 + ] + }, + { + "name": "b_Spine01_02", + "quaternion": [ + -1.283108929607995e-7, + -1.0949951724032763e-7, + -0.5664657324997473, + 0.8240852952841085 + ] + }, + { + "name": "b_Spine02_03", + "quaternion": [ + 4.574153513682658e-8, + 1.0480651468166865e-8, + 0.22334063212197255, + 0.9747404588111419 + ] + }, + { + "name": "b_Neck_04", + "quaternion": [ + 3.2111464479742967e-15, + -1.2190028995108914e-16, + -0.037934258309708466, + 0.9992802369938537 + ] + }, + { + "name": "b_Head_05", + "quaternion": [ + 1.7685306086292584e-8, + -3.756728202934336e-9, + -0.2077847175230104, + 0.9781745811274603 + ] + }, + { + "name": "b_RightUpperArm_06", + "quaternion": [ + -0.002815660160155366, + -0.0299247372923505, + -0.7015845596875624, + 0.7119520556025267 + ] + }, + { + "name": "b_RightForeArm_07", + "quaternion": [ + 2.689088777560911e-8, + 2.716181064542615e-8, + 0.6741215221773824, + 0.7386204441267535 + ] + }, + { + "name": "b_RightHand_08", + "quaternion": [ + 0.0018818183534198285, + 0.02659835068723313, + -0.22535992817657416, + 0.9739106215265912 + ] + }, + { + "name": "b_LeftUpperArm_09", + "quaternion": [ + 0.0016633618002732022, + -0.0004334499182036145, + 0.819288253374246, + -0.5733792897410207 + ] + }, + { + "name": "b_LeftForeArm_010", + "quaternion": [ + 2.8407917327021963e-8, + 2.4645703788229868e-8, + 0.6553329842648986, + 0.7553401182410117 + ] + }, + { + "name": "b_LeftHand_011", + "quaternion": [ + 0.013529175248387827, + -0.011110225346678418, + -0.7889365795285913, + 0.6142251855764741 + ] + }, + { + "name": "b_Tail01_012", + "quaternion": [ + -3.936283659524742e-8, + 3.1579248644713764e-7, + 0.8981361695246144, + 0.4397174472524852 + ] + }, + { + "name": "b_Tail02_013", + "quaternion": [ + -2.2568892350889094e-23, + -6.228353307318982e-24, + 0.11008060792562613, + 0.9939226700248508 + ] + }, + { + "name": "b_Tail03_014", + "quaternion": [ + -6.27135586859007e-24, + 1.3734036132740435e-24, + -0.14941593686354118, + 0.9887744342525416 + ] + }, + { + "name": "b_LeftLeg01_015", + "quaternion": [ + -0.04116859225888361, + -0.07052216832632746, + 0.9944988833187012, + 0.06560318271421245 + ] + }, + { + "name": "b_LeftLeg02_016", + "quaternion": [ + -2.4050162155048397e-9, + 1.60669887278214e-8, + -0.22487623923621733, + 0.9743873341885019 + ] + }, + { + "name": "b_LeftFoot01_017", + "quaternion": [ + -0.04256852646434424, + -0.0798386539213618, + 0.45839718735623874, + 0.8841299288098983 + ] + }, + { + "name": "b_LeftFoot02_018", + "quaternion": [ + 0, + 0, + 0.5472882949090243, + 0.8369441571906532 + ] + }, + { + "name": "b_RightLeg01_019", + "quaternion": [ + -0.043037967707905904, + -0.04819878633134017, + -0.8485756555186044, + 0.5251132764352214 + ] + }, + { + "name": "b_RightLeg02_020", + "quaternion": [ + 1.3947855795135538e-8, + 1.3668498182199692e-8, + -0.5202749549175736, + 0.8539988122272281 + ] + }, + { + "name": "b_RightFoot01_021", + "quaternion": [ + 0.0483777047847701, + 0.1586582372708204, + 0.6216248882373624, + 0.7655518661395584 + ] + }, + { + "name": "b_RightFoot02_022", + "quaternion": [ + 0, + 0, + 0.5472882949090243, + 0.8369441571906532 + ] + } + ], + "onlyActivePivot": true + }, + "movingChanged": true, + "status": "PASS" + }, + "allClipChecks": [ + { + "name": "Survey", + "playing": true, + "timeAdvanced": true, + "bonesChanged": true + }, + { + "name": "Walk", + "playing": true, + "timeAdvanced": true, + "bonesChanged": true + }, + { + "name": "Run", + "playing": true, + "timeAdvanced": true, + "bonesChanged": true + } + ], + "published": { + "projectId": "157", + "code": "MODEL-70875AA932B94685", + "name": "实测模型-狐狸动画-已验证-20260905", + "status": "PUBLISHED", + "version": 10, + "publishedVersionId": "201", + "currentVersionId": "201", + "versionNo": 2, + "checksum": "fbb1c9ad102a20aa3f0add103167a165d2454a9935f470df2e415731ff0a160d", + "schema": "digital-twin-editor-project", + "modelResource": { + "kind": "imported", + "id": "imported-model_mto6v5w6_09-fox", + "name": "09-Fox", + "assetCode": "MODEL_MTO6V5W6_09-FOX", + "code": "MODEL_MTO6V5W6_09-FOX", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb", + "resourceUrl": "", + "sourceName": "09-Fox.glb", + "sizeBytes": 162852, + "lastModified": 0, + "mimeType": "model/gltf-binary", + "thumbnail": "", + "vertices": 1728, + "triangles": 576, + "nodes": 27, + "meshes": 1, + "materials": 1, + "textures": 1, + "animations": 3, + "animationDurationSeconds": 3.4166667461395264, + "modelMetadata": { + "nodeCount": 27, + "meshCount": 1, + "materialCount": 1, + "textureCount": 1, + "animations": [ + { + "index": 0, + "name": "Survey", + "start": 0, + "end": 3.4166667461395264, + "duration": 3.4166667461395264, + "trackCount": 21 + }, + { + "index": 1, + "name": "Walk", + "start": 0, + "end": 0.7083333134651184, + "duration": 0.7083333134651184, + "trackCount": 21 + }, + { + "index": 2, + "name": "Run", + "start": 0, + "end": 1.1583333015441895, + "duration": 1.1583333015441895, + "trackCount": 21 + } + ], + "animationDurationSeconds": 3.4166667461395264 + }, + "nativeAnimations": [ + { + "index": 0, + "name": "Survey", + "start": 0, + "end": 3.4166667461395264, + "duration": 3.4166667461395264, + "trackCount": 21 + }, + { + "index": 1, + "name": "Walk", + "start": 0, + "end": 0.7083333134651184, + "duration": 0.7083333134651184, + "trackCount": 21 + }, + { + "index": 2, + "name": "Run", + "start": 0, + "end": 1.1583333015441895, + "duration": 1.1583333015441895, + "trackCount": 21 + } + ] + }, + "nativeAnimation": { + "clipIndex": 2, + "clipName": "Run" + }, + "modelObjects": { + "equipment-root": { + "name": "09-Fox", + "nodeName": "09-Fox", + "nodePath": "@root", + "interactionId": "interaction-b9240aaa", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-0": { + "name": "", + "nodeName": "Group", + "nodePath": "0", + "interactionId": "interaction-02351bce", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 3.875009990661482e-8, + 0.007396563645075124, + 0.6522089834776823 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.06075496488891343, + 0.06075496488891343, + 0.06075496488891343 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-1": { + "name": "root", + "nodeName": "root", + "nodePath": "0/0", + "interactionId": "interaction-a4d35db9", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-2": { + "name": "_rootJoint", + "nodeName": "_rootJoint", + "nodePath": "0/0/0", + "interactionId": "interaction-4476c556", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-3": { + "name": "b_Root_00", + "nodeName": "b_Root_00", + "nodePath": "0/0/0/0", + "interactionId": "interaction-ffc45d11", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + -1.5708000357176293, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-4": { + "name": "b_Hip_01", + "nodeName": "b_Hip_01", + "nodePath": "0/0/0/0/0", + "interactionId": "interaction-7a75e39e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0.000001241521920852674, + 22.061977333358605, + 34.62373020761327 + ], + "rotation": [ + 0.44722050284761794, + -1.5707951637404125, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-5": { + "name": "b_Spine01_02", + "nodeName": "b_Spine01_02", + "nodePath": "0/0/0/0/0/0", + "interactionId": "interaction-663ea469", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 12.850601196289062, + 0, + 0 + ], + "rotation": [ + -3.357310257291308e-7, + -3.316574913360067e-8, + -1.2102038452161539 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-6": { + "name": "b_Spine02_03", + "nodeName": "b_Spine02_03", + "nodePath": "0/0/0/0/0/0/0", + "interactionId": "interaction-46867126", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 21.65575408935547, + -0.000118255615234375, + 0 + ], + "rotation": [ + 8.772651057591018e-8, + 3.3355428835535634e-8, + 0.3633406824515624 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-7": { + "name": "b_Neck_04", + "nodeName": "b_Neck_04", + "nodePath": "0/0/0/0/0/0/0/0", + "interactionId": "interaction-27148d81", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 25.64914321899414, + 0, + 0 + ], + "rotation": [ + 6.423807629998062e-15, + 1.9993472402144555e-16, + 0.031113979193075042 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-8": { + "name": "b_Head_05", + "nodeName": "b_Head_05", + "nodePath": "0/0/0/0/0/0/0/0/0", + "interactionId": "interaction-b24eef2e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 13.376960754394531, + 0, + 0 + ], + "rotation": [ + 3.253825627358364e-8, + -1.577320798309453e-8, + -0.451380500897834 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-9": { + "name": "b_RightUpperArm_06", + "nodeName": "b_RightUpperArm_06", + "nodePath": "0/0/0/0/0/0/0/1", + "interactionId": "interaction-26148bee", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.677913665771484, + -4.297340393066406, + 6.9675750732421875 + ], + "rotation": [ + -0.035644184619881884, + -0.047001863061712265, + -1.2972005346348685 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-10": { + "name": "b_RightForeArm_07", + "nodeName": "b_RightForeArm_07", + "nodePath": "0/0/0/0/0/0/0/1/0", + "interactionId": "interaction-36896559", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 23.04512596130371, + 0, + 0 + ], + "rotation": [ + 2.1355818997049898e-8, + 7.233656206674673e-8, + 1.2561843405841544 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-11": { + "name": "b_RightHand_08", + "nodeName": "b_RightHand_08", + "nodePath": "0/0/0/0/0/0/0/1/0/0", + "interactionId": "interaction-57a124f6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 19.350055694580078, + -0.14598655700683594, + 0 + ], + "rotation": [ + 0.005245101551986586, + 0.05200705984217871, + -0.267165337534188 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-12": { + "name": "b_LeftUpperArm_09", + "nodeName": "b_LeftUpperArm_09", + "nodePath": "0/0/0/0/0/0/0/2", + "interactionId": "interaction-25148a5b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.67791748046875, + -4.297344207763672, + -6.967987060546875 + ], + "rotation": [ + -0.00020118104561539401, + 0.0009350561550523671, + -1.5148902559141275 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-13": { + "name": "b_LeftForeArm_010", + "nodeName": "b_LeftForeArm_010", + "nodePath": "0/0/0/0/0/0/0/2/0", + "interactionId": "interaction-5c502ac4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 23.045124053955078, + 0, + 0 + ], + "rotation": [ + 2.5220861991717696e-8, + 7.109903232964989e-8, + 1.2307106255258764 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-14": { + "name": "b_LeftHand_011", + "nodeName": "b_LeftHand_011", + "nodePath": "0/0/0/0/0/0/0/2/0/0", + "interactionId": "interaction-192b4cd3", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 19.350051879882812, + -0.14599037170410156, + 0 + ], + "rotation": [ + 0.004279557751527162, + -0.03344276494440009, + -1.5985291598689726 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-15": { + "name": "b_Tail01_012", + "nodeName": "b_Tail01_012", + "nodePath": "0/0/0/0/0/1", + "interactionId": "interaction-653ea2d6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 4.2603759765625, + 15.958770751953125, + 0 + ], + "rotation": [ + -5.364745216052604e-7, + 3.424797608447095e-7, + 1.9941304874941974 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-16": { + "name": "b_Tail02_013", + "nodeName": "b_Tail02_013", + "nodePath": "0/0/0/0/0/1/0", + "interactionId": "interaction-6c4d3691", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 12.411918640136719, + 0, + 0 + ], + "rotation": [ + -6.738507958375962e-23, + -5.2439168243310865e-23, + 0.3128105211171357 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-17": { + "name": "b_Tail03_014", + "nodeName": "b_Tail03_014", + "nodePath": "0/0/0/0/0/1/0/0", + "interactionId": "interaction-e93e191e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 24.24032211303711, + 0, + 0 + ], + "rotation": [ + -5.7486339033124146e-24, + 1.1669178332583734e-22, + -0.012937892408322462 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-18": { + "name": "b_LeftLeg01_015", + "nodeName": "b_LeftLeg01_015", + "nodePath": "0/0/0/0/0/2", + "interactionId": "interaction-643ea143", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 4.813770294189453, + 5.154018402099609, + -6.968006134033203 + ], + "rotation": [ + 0.1223493637902729, + -0.09724770930295147, + 2.9630295165414986 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-19": { + "name": "b_LeftLeg02_016", + "nodeName": "b_LeftLeg02_016", + "nodePath": "0/0/0/0/0/2/0", + "interactionId": "interaction-7175f8dc", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.944175720214844, + 0, + 0 + ], + "rotation": [ + 1.2545483692289454e-8, + 3.728483680761731e-8, + -0.522293355530293 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-20": { + "name": "b_LeftFoot01_017", + "nodeName": "b_LeftFoot01_017", + "nodePath": "0/0/0/0/0/2/0/0", + "interactionId": "interaction-f5ed353b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 17.942811965942383, + 0, + 0 + ], + "rotation": [ + -0.03128474386729028, + -0.15471927051895154, + 0.7774909055508243 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-21": { + "name": "b_LeftFoot02_018", + "nodeName": "b_LeftFoot02_018", + "nodePath": "0/0/0/0/0/2/0/0/0", + "interactionId": "interaction-1bbe01a4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 15.779938697814941, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 1.158241570830627 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-22": { + "name": "b_RightLeg01_019", + "nodeName": "b_RightLeg01_019", + "nodePath": "0/0/0/0/0/3", + "interactionId": "interaction-633e9fb0", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 4.813777923583984, + 5.154026031494141, + 6.967563629150391 + ], + "rotation": [ + -0.10137208185544387, + 0.05534659522395753, + -2.3613690068554236 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-23": { + "name": "b_RightLeg02_020", + "nodeName": "b_RightLeg02_020", + "nodePath": "0/0/0/0/0/3/0", + "interactionId": "interaction-95ff89c7", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.944183349609375, + 0, + 0 + ], + "rotation": [ + 2.7890192431350882e-8, + 1.4750479199499402e-8, + -1.0710323806538369 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-24": { + "name": "b_RightFoot01_021", + "nodeName": "b_RightFoot01_021", + "nodePath": "0/0/0/0/0/3/0/0", + "interactionId": "interaction-a157d498", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 17.94281005859375, + 0, + 0 + ], + "rotation": [ + -0.14401413968163027, + 0.2814735368347316, + 1.4591240233677443 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-25": { + "name": "b_RightFoot02_022", + "nodeName": "b_RightFoot02_022", + "nodePath": "0/0/0/0/0/3/0/0/0", + "interactionId": "interaction-ebd38e3f", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 15.779935836791992, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 1.158241570830627 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-26": { + "name": "fox", + "nodeName": "fox", + "nodePath": "0/1", + "interactionId": "interaction-a3d35c26", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0.25, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + } + }, + "assets": [ + { + "code": "MODEL_BRIDGE-ERECTOR-VEHICLE", + "name": "桥梁架设装备整机", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "", + "storageUri": "/models/bridge-erector-vehicle.glb", + "builtIn": true + }, + { + "code": "MODEL_MTO6V5W6_09-FOX", + "name": "09-Fox.glb", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "d97044e701822bac5a62696459b27d7b375aada5de8574ed4362edbba94771f7", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb" + } + ], + "updateTime": "2026-09-05T17:48:04" + }, + "freshSession": { + "status": "PASS", + "live": { + "source": "09-Fox.glb", + "apiMode": true, + "clip": "Run" + }, + "server": { + "projectId": "157", + "code": "MODEL-70875AA932B94685", + "name": "实测模型-狐狸动画-已验证-20260905", + "status": "PUBLISHED", + "version": 10, + "publishedVersionId": "201", + "currentVersionId": "201", + "versionNo": 2, + "checksum": "fbb1c9ad102a20aa3f0add103167a165d2454a9935f470df2e415731ff0a160d", + "schema": "digital-twin-editor-project", + "modelResource": { + "kind": "imported", + "id": "imported-model_mto6v5w6_09-fox", + "name": "09-Fox", + "assetCode": "MODEL_MTO6V5W6_09-FOX", + "code": "MODEL_MTO6V5W6_09-FOX", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb", + "resourceUrl": "", + "sourceName": "09-Fox.glb", + "sizeBytes": 162852, + "lastModified": 0, + "mimeType": "model/gltf-binary", + "thumbnail": "", + "vertices": 1728, + "triangles": 576, + "nodes": 27, + "meshes": 1, + "materials": 1, + "textures": 1, + "animations": 3, + "animationDurationSeconds": 3.4166667461395264, + "modelMetadata": { + "nodeCount": 27, + "meshCount": 1, + "materialCount": 1, + "textureCount": 1, + "animations": [ + { + "index": 0, + "name": "Survey", + "start": 0, + "end": 3.4166667461395264, + "duration": 3.4166667461395264, + "trackCount": 21 + }, + { + "index": 1, + "name": "Walk", + "start": 0, + "end": 0.7083333134651184, + "duration": 0.7083333134651184, + "trackCount": 21 + }, + { + "index": 2, + "name": "Run", + "start": 0, + "end": 1.1583333015441895, + "duration": 1.1583333015441895, + "trackCount": 21 + } + ], + "animationDurationSeconds": 3.4166667461395264 + }, + "nativeAnimations": [ + { + "index": 0, + "name": "Survey", + "start": 0, + "end": 3.4166667461395264, + "duration": 3.4166667461395264, + "trackCount": 21 + }, + { + "index": 1, + "name": "Walk", + "start": 0, + "end": 0.7083333134651184, + "duration": 0.7083333134651184, + "trackCount": 21 + }, + { + "index": 2, + "name": "Run", + "start": 0, + "end": 1.1583333015441895, + "duration": 1.1583333015441895, + "trackCount": 21 + } + ] + }, + "nativeAnimation": { + "clipIndex": 2, + "clipName": "Run" + }, + "modelObjects": { + "equipment-root": { + "name": "09-Fox", + "nodeName": "09-Fox", + "nodePath": "@root", + "interactionId": "interaction-b9240aaa", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-0": { + "name": "", + "nodeName": "Group", + "nodePath": "0", + "interactionId": "interaction-02351bce", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 3.875009990661482e-8, + 0.007396563645075124, + 0.6522089834776823 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 0.06075496488891343, + 0.06075496488891343, + 0.06075496488891343 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-1": { + "name": "root", + "nodeName": "root", + "nodePath": "0/0", + "interactionId": "interaction-a4d35db9", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-2": { + "name": "_rootJoint", + "nodeName": "_rootJoint", + "nodePath": "0/0/0", + "interactionId": "interaction-4476c556", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-3": { + "name": "b_Root_00", + "nodeName": "b_Root_00", + "nodePath": "0/0/0/0", + "interactionId": "interaction-ffc45d11", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0, + 0, + 0 + ], + "rotation": [ + -1.5708000357176293, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-4": { + "name": "b_Hip_01", + "nodeName": "b_Hip_01", + "nodePath": "0/0/0/0/0", + "interactionId": "interaction-7a75e39e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 0.000001241521920852674, + 22.061977333358605, + 34.62373020761327 + ], + "rotation": [ + 0.44722050284761794, + -1.5707951637404125, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-5": { + "name": "b_Spine01_02", + "nodeName": "b_Spine01_02", + "nodePath": "0/0/0/0/0/0", + "interactionId": "interaction-663ea469", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 12.850601196289062, + 0, + 0 + ], + "rotation": [ + -3.357310257291308e-7, + -3.316574913360067e-8, + -1.2102038452161539 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-6": { + "name": "b_Spine02_03", + "nodeName": "b_Spine02_03", + "nodePath": "0/0/0/0/0/0/0", + "interactionId": "interaction-46867126", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 21.65575408935547, + -0.000118255615234375, + 0 + ], + "rotation": [ + 8.772651057591018e-8, + 3.3355428835535634e-8, + 0.3633406824515624 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-7": { + "name": "b_Neck_04", + "nodeName": "b_Neck_04", + "nodePath": "0/0/0/0/0/0/0/0", + "interactionId": "interaction-27148d81", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 25.64914321899414, + 0, + 0 + ], + "rotation": [ + 6.423807629998062e-15, + 1.9993472402144555e-16, + 0.031113979193075042 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-8": { + "name": "b_Head_05", + "nodeName": "b_Head_05", + "nodePath": "0/0/0/0/0/0/0/0/0", + "interactionId": "interaction-b24eef2e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 13.376960754394531, + 0, + 0 + ], + "rotation": [ + 3.253825627358364e-8, + -1.577320798309453e-8, + -0.451380500897834 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-9": { + "name": "b_RightUpperArm_06", + "nodeName": "b_RightUpperArm_06", + "nodePath": "0/0/0/0/0/0/0/1", + "interactionId": "interaction-26148bee", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.677913665771484, + -4.297340393066406, + 6.9675750732421875 + ], + "rotation": [ + -0.035644184619881884, + -0.047001863061712265, + -1.2972005346348685 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-10": { + "name": "b_RightForeArm_07", + "nodeName": "b_RightForeArm_07", + "nodePath": "0/0/0/0/0/0/0/1/0", + "interactionId": "interaction-36896559", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 23.04512596130371, + 0, + 0 + ], + "rotation": [ + 2.1355818997049898e-8, + 7.233656206674673e-8, + 1.2561843405841544 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-11": { + "name": "b_RightHand_08", + "nodeName": "b_RightHand_08", + "nodePath": "0/0/0/0/0/0/0/1/0/0", + "interactionId": "interaction-57a124f6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 19.350055694580078, + -0.14598655700683594, + 0 + ], + "rotation": [ + 0.005245101551986586, + 0.05200705984217871, + -0.267165337534188 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-12": { + "name": "b_LeftUpperArm_09", + "nodeName": "b_LeftUpperArm_09", + "nodePath": "0/0/0/0/0/0/0/2", + "interactionId": "interaction-25148a5b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.67791748046875, + -4.297344207763672, + -6.967987060546875 + ], + "rotation": [ + -0.00020118104561539401, + 0.0009350561550523671, + -1.5148902559141275 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-13": { + "name": "b_LeftForeArm_010", + "nodeName": "b_LeftForeArm_010", + "nodePath": "0/0/0/0/0/0/0/2/0", + "interactionId": "interaction-5c502ac4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 23.045124053955078, + 0, + 0 + ], + "rotation": [ + 2.5220861991717696e-8, + 7.109903232964989e-8, + 1.2307106255258764 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-14": { + "name": "b_LeftHand_011", + "nodeName": "b_LeftHand_011", + "nodePath": "0/0/0/0/0/0/0/2/0/0", + "interactionId": "interaction-192b4cd3", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 19.350051879882812, + -0.14599037170410156, + 0 + ], + "rotation": [ + 0.004279557751527162, + -0.03344276494440009, + -1.5985291598689726 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-15": { + "name": "b_Tail01_012", + "nodeName": "b_Tail01_012", + "nodePath": "0/0/0/0/0/1", + "interactionId": "interaction-653ea2d6", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 4.2603759765625, + 15.958770751953125, + 0 + ], + "rotation": [ + -5.364745216052604e-7, + 3.424797608447095e-7, + 1.9941304874941974 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-16": { + "name": "b_Tail02_013", + "nodeName": "b_Tail02_013", + "nodePath": "0/0/0/0/0/1/0", + "interactionId": "interaction-6c4d3691", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 12.411918640136719, + 0, + 0 + ], + "rotation": [ + -6.738507958375962e-23, + -5.2439168243310865e-23, + 0.3128105211171357 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-17": { + "name": "b_Tail03_014", + "nodeName": "b_Tail03_014", + "nodePath": "0/0/0/0/0/1/0/0", + "interactionId": "interaction-e93e191e", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 24.24032211303711, + 0, + 0 + ], + "rotation": [ + -5.7486339033124146e-24, + 1.1669178332583734e-22, + -0.012937892408322462 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-18": { + "name": "b_LeftLeg01_015", + "nodeName": "b_LeftLeg01_015", + "nodePath": "0/0/0/0/0/2", + "interactionId": "interaction-643ea143", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 4.813770294189453, + 5.154018402099609, + -6.968006134033203 + ], + "rotation": [ + 0.1223493637902729, + -0.09724770930295147, + 2.9630295165414986 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-19": { + "name": "b_LeftLeg02_016", + "nodeName": "b_LeftLeg02_016", + "nodePath": "0/0/0/0/0/2/0", + "interactionId": "interaction-7175f8dc", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.944175720214844, + 0, + 0 + ], + "rotation": [ + 1.2545483692289454e-8, + 3.728483680761731e-8, + -0.522293355530293 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-20": { + "name": "b_LeftFoot01_017", + "nodeName": "b_LeftFoot01_017", + "nodePath": "0/0/0/0/0/2/0/0", + "interactionId": "interaction-f5ed353b", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 17.942811965942383, + 0, + 0 + ], + "rotation": [ + -0.03128474386729028, + -0.15471927051895154, + 0.7774909055508243 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-21": { + "name": "b_LeftFoot02_018", + "nodeName": "b_LeftFoot02_018", + "nodePath": "0/0/0/0/0/2/0/0/0", + "interactionId": "interaction-1bbe01a4", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 15.779938697814941, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 1.158241570830627 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-22": { + "name": "b_RightLeg01_019", + "nodeName": "b_RightLeg01_019", + "nodePath": "0/0/0/0/0/3", + "interactionId": "interaction-633e9fb0", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 4.813777923583984, + 5.154026031494141, + 6.967563629150391 + ], + "rotation": [ + -0.10137208185544387, + 0.05534659522395753, + -2.3613690068554236 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-23": { + "name": "b_RightLeg02_020", + "nodeName": "b_RightLeg02_020", + "nodePath": "0/0/0/0/0/3/0", + "interactionId": "interaction-95ff89c7", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 18.944183349609375, + 0, + 0 + ], + "rotation": [ + 2.7890192431350882e-8, + 1.4750479199499402e-8, + -1.0710323806538369 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-24": { + "name": "b_RightFoot01_021", + "nodeName": "b_RightFoot01_021", + "nodePath": "0/0/0/0/0/3/0/0", + "interactionId": "interaction-a157d498", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 17.94281005859375, + 0, + 0 + ], + "rotation": [ + -0.14401413968163027, + 0.2814735368347316, + 1.4591240233677443 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-25": { + "name": "b_RightFoot02_022", + "nodeName": "b_RightFoot02_022", + "nodePath": "0/0/0/0/0/3/0/0/0", + "interactionId": "interaction-ebd38e3f", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": false, + "animatable": true + }, + "position": [ + 15.779935836791992, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 1.158241570830627 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [] + }, + "model-imported-model_mto6v5w6_09-fox-26": { + "name": "fox", + "nodeName": "fox", + "nodePath": "0/1", + "interactionId": "interaction-a3d35c26", + "capabilities": { + "selectable": true, + "transform": true, + "visible": true, + "material": true, + "animatable": true + }, + "position": [ + 0.25, + 0, + 0 + ], + "rotation": [ + 0, + 0, + 0 + ], + "scale": [ + 1, + 1, + 1 + ], + "visible": true, + "customComponents": [], + "materials": [ + { + "color": "ffffff", + "emissive": "000000", + "emissiveIntensity": 1, + "metalness": 0, + "roughness": 0.3, + "opacity": 1, + "transparent": false, + "depthWrite": true + } + ] + } + }, + "assets": [ + { + "code": "MODEL_BRIDGE-ERECTOR-VEHICLE", + "name": "桥梁架设装备整机", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "", + "storageUri": "/models/bridge-erector-vehicle.glb", + "builtIn": true + }, + { + "code": "MODEL_MTO6V5W6_09-FOX", + "name": "09-Fox.glb", + "type": "MODEL_FILE", + "status": "READY", + "sha256": "d97044e701822bac5a62696459b27d7b375aada5de8574ed4362edbba94771f7", + "storageUri": "fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb" + } + ] + } + }, + "retained": true, + "timestampCheck": { + "status": "PASS", + "before": { + "project": "2026-09-05T17:33:10", + "version": "2026-09-05T17:33:10" + }, + "after": { + "project": "2026-09-05T17:47:39", + "version": "2026-09-05T17:47:39" + }, + "draftVersionId": "201", + "versionNo": 2 + } + } + ], + "evidence": [ + { + "type": "final-list", + "status": "PASS", + "rows": [ + "MODEL-70875AA932B94685 · 整机装备实测模型-狐狸动画-20260905节点 27 · 材质 1 · 动画 1系统管理员更新:2026/09/05 17:33已发布进入编辑更多", + "MODEL-3FA24629D59E4509 · 整机装备实测模型-牛奶卡车-20260905节点 10 · 材质 5 · 动画 1系统管理员更新:2026/09/05 17:24已发布进入编辑更多" + ], + "screenshot": "screenshots/00-two-published-models.png" + }, + { + "type": "build", + "status": "PASS", + "command": "pnpm run build", + "details": "类型检查、Vite 构建、public/dist hash、API 桥接与凭据门禁均通过" + }, + { + "type": "scope", + "details": "通过实际页面操作创建/导入/编辑/播放/保存/发布;只读 API 与全新浏览器会话交叉核验。未创建场景,未执行训练业务蓝图,未改表结构或账号权限。" + }, + { + "type": "final-list", + "status": "PASS", + "details": "最终 V2 列表:狐狸 17:48 排在卡车 17:47 之前,最近更新排序与服务端保存、发布时间一致。", + "rows": [ + "MODEL-70875AA932B94685 · 整机装备实测模型-狐狸动画-已验证-20260905节点 27 · 材质 1 · 动画 1系统管理员更新:2026/09/05 17:48已发布进入编辑更多", + "MODEL-3FA24629D59E4509 · 整机装备实测模型-牛奶卡车-已验证-20260905节点 10 · 材质 5 · 动画 1系统管理员更新:2026/09/05 17:47已发布进入编辑更多" + ], + "screenshot": "screenshots/00b-two-published-models-v2.png" + }, + { + "type": "backend-regression", + "status": "PASS", + "command": "mvn -B -ntp -pl ut_tran -Dtest=ContentProjectServiceTest test", + "details": "Java 17;70项用例通过,0失败/错误/跳过。新增用例先复现旧时间写回,再验证修复。" + }, + { + "type": "build-final", + "status": "PASS", + "details": "最终 pnpm run build 通过;stage生成camera-fit统一LF后,10个payload的public/dist哈希、API桥接与凭据门禁通过,git diff --check通过。", + "command": "pnpm run build" + }, + { + "type": "cover-display", + "details": "两条测试数据未设置自定义封面,列表沿用现有默认装备缩略图;编辑器内已分别验证真实卡车与狐狸。若需要导入后自动生成模型封面,属于另行确认的功能增强。" + } + ], + "issues": [ + { + "title": "模型编辑器生成包陈旧,页面实际运行本地模式", + "status": "已修复并验证", + "impact": "新建记录存在,但旧编辑器未读取项目 ID,模型编辑和自动保存未写入内容制作 API。", + "fix": "从现有接口版源码重建并暂存编辑器包,增加 build 产物 API 桥接检查。", + "screenshot": "screenshots/01-editor-initialization.png" + }, + { + "title": "GLB 上传被文件服务 503 阻断", + "status": "已修复并验证", + "impact": "上传未成功,原工程模型与资产仍保留。", + "screenshot": "screenshots/03b-upload-error-log.png", + "requestId": "69785305-558a-4a43-99bf-655b4adda274", + "cause": "用户级 UT_FILE_SERVICE_BASE_URL / CONTENT_BASE_URL 残留关闭的 127.0.0.1:17180 代理地址", + "fix": "恢复到现有配置的远端真实文件服务,保留密钥,仅重启 ut-tran;实际 GLB 上传已返回200" + }, + { + "title": "列表“动画”统计口径需确认", + "status": "待确认,未改功能", + "impact": "狐狸实际有 Survey、Walk、Run 3 个原生片段,全部实播通过;列表显示动画1,统计的是1条自编时间轴轨道。", + "suggestion": "可将列表文案明确为“动画轨道”,或增加“原生动画3段 / 自编轨道1条”的分项展示,待用户确认后实施。", + "screenshot": "screenshots/00-two-published-models.png" + }, + { + "title": "保存和发布没有刷新项目/版本更新时间", + "status": "已修复并验证", + "cause": "读取实体携带旧 updateTime,updateById 再次写回旧值,数据库自动更新时间未生效。", + "fix": "项目、版本两个统一更新方法显式设置当前秒精度时间;无表结构变更。", + "verification": "两模型改名生成 V2 草稿并重新发布;API时间、页面时间、最近更新排序和全新浏览器重开均通过。", + "screenshot": "screenshots/00b-two-published-models-v2.png" + } + ], + "retainedData": "保留本次创建的两条模型工程与上传资产,供用户继续测试。" +} \ No newline at end of file diff --git a/reports/model-live-20260905/index.html b/reports/model-live-20260905/index.html new file mode 100644 index 0000000..aa82da9 --- /dev/null +++ b/reports/model-live-20260905/index.html @@ -0,0 +1,55 @@ +真实模型制作实测报告 · 2026-09-05

开发环境 · 真实模型制作

真实模型制作实测报告 · 2026-09-05

已记录 2/2 个模型项目、23 项步骤:23 项通过,0 项失败,0 项其他或未记录结论。

+

环境与身份

+
项目记录
测试日期2026-09-05
页面地址http://127.0.0.1:6180
浏览器Microsoft Edge
账号角色teacher
账号显示名称系统管理员
+
+

统计仅来自明确记录的步骤结论;缺失字段、仅有数据或仅有截图均不视为通过。

+

模型 1:实测模型-牛奶卡车-已验证-20260905

+
项目记录
项目名称实测模型-牛奶卡车-已验证-20260905
项目编码MODEL-3FA24629D59E4509
项目 ID156
来源素材08-CesiumMilkTruck.glb
测试节点Cesium_Milk_Truck
动画Wheels;编号 0;数量 1
原生动画片段1 段:Wheels
+

轻量 GLB 实测:车辆多部件、节点编辑、车轮动画、保存重开和发布。保留供后续模型/场景测试使用。

+

操作步骤

+
序号步骤结论证据摘要
1UI创建项目通过HTTP 状态:200
2文件服务地址修复后重新上传通过HTTP 状态:200;详情:首次上传失败保留于问题证据;修复地址后已实际上传成功并校验文件哈希;initialHttpStatus:503
3GLB上传、两阶段绑定、SHA256与活跃模型核验通过未记录
4组合节点 X 位置与原生动画选择保存通过详情 / x:0.35;详情 / 动画编号:Wheels;详情 / versionBefore:5;详情 / versionAfter:6
5整页刷新后模型、节点、材质、动画选择恢复通过未记录
6原生动画实播:播放时间与轮子/骨骼姿态确实变化通过未记录
7车身子网格材质粗糙度修改、保存、刷新恢复通过详情 / node:Cesium_Milk_Truck_1;详情 / roughness:0.3;详情 / persistedAfterReload:true
8发布到场景资源库并核对服务端发布版本通过HTTP 状态:200
9全新浏览器上下文从服务端载入已发布模型通过详情 / source:08-CesiumMilkTruck.glb;详情 / apiMode:true;详情 / 动画编号:Wheels
10已发布模型改名保存为 V2 草稿,项目及版本更新时间刷新通过详情 / 状态:PASS;详情 / 变更前 / project:2026-09-05T17:24:34;详情 / 变更前 / 版本:2026-09-05T17:24:34;详情 / 变更后 / project:2026-09-05T17:47:05;详情 / 变更后 / 版本:2026-09-05T17:47:05;详情 / draftVersionId:200;详情 / versionNo:2
11V2 重新发布成功,发布版本及更新时间正确通过详情 / versionNo:2;详情 / versionId:200;详情 / updateTime:2026-09-05T17:47:29
12V2 全新浏览器上下文重开,模型文件、动画选择、发布版本均正确通过详情 / source:08-CesiumMilkTruck.glb;详情 / 动画编号:Wheels;详情 / versionNo:2
+
+

导入校验

通过

SHA-256
09371b34608116de5842d23abe260bf11acf3e1554daf334a647eb566eee5c49
文件字节数
369980
变更记录 1 / 状态
200
变更记录 1 / registeredTicket
true
变更记录 1 / sourceName
bridge-erector-vehicle.glb
变更记录 1 / assetCode
MODEL_BRIDGE-ERECTOR-VEHICLE
变更记录 2 / 状态
200
变更记录 2 / registeredTicket
false
变更记录 2 / sourceName
08-CesiumMilkTruck.glb
变更记录 2 / assetCode
MODEL_MTO6WI6K_08-CESIUMMILKTRUCK
服务端 / projectId
156
服务端 / 编码
MODEL-3FA24629D59E4509
服务端 / 名称
实测模型-牛奶卡车-20260905
服务端 / 状态
DRAFT
服务端 / 版本
4
服务端 / currentVersionId
198
服务端 / versionNo
1
服务端 / checksum
30ee74fe8f8763e6342f1bbc36607a06db0f6f79061471ab7334e61028029d01
服务端 / schema
digital-twin-editor-project
服务端 / modelResource / kind
imported
服务端 / modelResource / ID
imported-model_mto6wi6k_08-cesiummilktruck
服务端 / modelResource / 名称
08-CesiumMilkTruck
服务端 / modelResource / assetCode
MODEL_MTO6WI6K_08-CESIUMMILKTRUCK
服务端 / modelResource / 编码
MODEL_MTO6WI6K_08-CESIUMMILKTRUCK
服务端 / modelResource / storageUri
fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb
服务端 / modelResource / sourceName
08-CesiumMilkTruck.glb
服务端 / modelResource / sizeBytes
369980
服务端 / modelResource / lastModified
0
服务端 / modelResource / mimeType
model/gltf-binary
服务端 / modelResource / vertices
4823
服务端 / modelResource / triangles
3624
服务端 / modelResource / 节点数
10
服务端 / modelResource / 网格数
5
服务端 / modelResource / 材质数
5
服务端 / modelResource / 纹理数
1
服务端 / modelResource / 动画
1
服务端 / modelResource / animationDurationSeconds
1.25
服务端 / modelResource / modelMetadata / nodeCount
10
服务端 / modelResource / modelMetadata / 网格数
5
服务端 / modelResource / modelMetadata / materialCount
5
服务端 / modelResource / modelMetadata / textureCount
1
服务端 / modelResource / modelMetadata / 动画
已记录,完整内容见 evidence.json
服务端 / modelResource / modelMetadata / animationDurationSeconds
1.25
更多记录
见 evidence.json
更多记录
见 evidence.json
更多记录
见 evidence.json
+

编辑与保存

通过

服务端 / projectId
156
服务端 / 编码
MODEL-3FA24629D59E4509
服务端 / 名称
实测模型-牛奶卡车-20260905
服务端 / 状态
DRAFT
服务端 / 版本
6
服务端 / currentVersionId
198
服务端 / versionNo
1
服务端 / checksum
495aaedac19971b06dec73ad43bdebfcfb63d0604fabaf48f460c7bc1cdcc229
服务端 / schema
digital-twin-editor-project
服务端 / modelResource / kind
imported
服务端 / modelResource / ID
imported-model_mto6wi6k_08-cesiummilktruck
服务端 / modelResource / 名称
08-CesiumMilkTruck
服务端 / modelResource / assetCode
MODEL_MTO6WI6K_08-CESIUMMILKTRUCK
服务端 / modelResource / 编码
MODEL_MTO6WI6K_08-CESIUMMILKTRUCK
服务端 / modelResource / storageUri
fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb
服务端 / modelResource / sourceName
08-CesiumMilkTruck.glb
服务端 / modelResource / sizeBytes
369980
服务端 / modelResource / lastModified
0
服务端 / modelResource / mimeType
model/gltf-binary
服务端 / modelResource / vertices
4823
服务端 / modelResource / triangles
3624
服务端 / modelResource / 节点数
10
服务端 / modelResource / 网格数
5
服务端 / modelResource / 材质数
5
服务端 / modelResource / 纹理数
1
服务端 / modelResource / 动画
1
服务端 / modelResource / animationDurationSeconds
1.25
服务端 / modelResource / modelMetadata / nodeCount
10
服务端 / modelResource / modelMetadata / 网格数
5
服务端 / modelResource / modelMetadata / materialCount
5
服务端 / modelResource / modelMetadata / textureCount
1
服务端 / modelResource / modelMetadata / 动画
已记录,完整内容见 evidence.json
服务端 / modelResource / modelMetadata / animationDurationSeconds
1.25
更多记录
见 evidence.json
更多记录
见 evidence.json
更多记录
见 evidence.json
+

保存后重开

通过

服务端 / projectId
156
服务端 / 编码
MODEL-3FA24629D59E4509
服务端 / 名称
实测模型-牛奶卡车-20260905
服务端 / 状态
DRAFT
服务端 / 版本
6
服务端 / currentVersionId
198
服务端 / versionNo
1
服务端 / checksum
495aaedac19971b06dec73ad43bdebfcfb63d0604fabaf48f460c7bc1cdcc229
服务端 / schema
digital-twin-editor-project
服务端 / modelResource / kind
imported
服务端 / modelResource / ID
imported-model_mto6wi6k_08-cesiummilktruck
服务端 / modelResource / 名称
08-CesiumMilkTruck
服务端 / modelResource / assetCode
MODEL_MTO6WI6K_08-CESIUMMILKTRUCK
服务端 / modelResource / 编码
MODEL_MTO6WI6K_08-CESIUMMILKTRUCK
服务端 / modelResource / storageUri
fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb
服务端 / modelResource / sourceName
08-CesiumMilkTruck.glb
服务端 / modelResource / sizeBytes
369980
服务端 / modelResource / lastModified
0
服务端 / modelResource / mimeType
model/gltf-binary
服务端 / modelResource / vertices
4823
服务端 / modelResource / triangles
3624
服务端 / modelResource / 节点数
10
服务端 / modelResource / 网格数
5
服务端 / modelResource / 材质数
5
服务端 / modelResource / 纹理数
1
服务端 / modelResource / 动画
1
服务端 / modelResource / animationDurationSeconds
1.25
服务端 / modelResource / modelMetadata / nodeCount
10
服务端 / modelResource / modelMetadata / 网格数
5
服务端 / modelResource / modelMetadata / materialCount
5
服务端 / modelResource / modelMetadata / textureCount
1
服务端 / modelResource / modelMetadata / 动画
已记录,完整内容见 evidence.json
服务端 / modelResource / modelMetadata / animationDurationSeconds
1.25
更多记录
见 evidence.json
更多记录
见 evidence.json
更多记录
见 evidence.json
+

动画检查

通过

动画编号
Wheels
变更前 / sourceName
08-CesiumMilkTruck.glb
变更前 / assetCode
MODEL_MTO6WI6K_08-CESIUMMILKTRUCK
变更前 / 节点数
10
变更前 / 网格数
5
变更前 / 材质数
5
变更前 / 动画数 1 / 名称
Wheels
变更前 / 动画数 1 / duration
1.25
变更前 / 动画数 1 / tracks
2
变更前 / clipIndex
0
变更前 / 正在播放
true
变更前 / 时间
0.017299999952316285
变更前 / mesh / 名称
Cesium_Milk_Truck
变更前 / mesh / editorId
model-imported-model_mto6wi6k_08-cesiummilktruck-2
变更前 / mesh / 位置
0.35、0、0
变更前 / mesh / 缩放
1、1、1
变更前 / mesh / isSkinnedMesh
false
变更前 / mesh / bones
0
变更前 / moving 1 / 名称
Wheels
变更前 / moving 1 / quaternion
已记录,完整内容见 evidence.json
变更前 / moving 2 / 名称
Wheels001
变更前 / moving 2 / quaternion
已记录,完整内容见 evidence.json
变更前 / onlyActivePivot
true
变更后 / sourceName
08-CesiumMilkTruck.glb
变更后 / assetCode
MODEL_MTO6WI6K_08-CESIUMMILKTRUCK
变更后 / 节点数
10
变更后 / 网格数
5
变更后 / 材质数
5
变更后 / 动画数 1 / 名称
Wheels
变更后 / 动画数 1 / duration
1.25
变更后 / 动画数 1 / tracks
2
变更后 / clipIndex
0
变更后 / 正在播放
true
变更后 / 时间
0.11699999999999999
变更后 / mesh / 名称
Cesium_Milk_Truck
变更后 / mesh / editorId
model-imported-model_mto6wi6k_08-cesiummilktruck-2
变更后 / mesh / 位置
0.35、0、0
变更后 / mesh / 缩放
1、1、1
变更后 / mesh / isSkinnedMesh
false
变更后 / mesh / bones
0
变更后 / moving 1 / 名称
Wheels
变更后 / moving 1 / quaternion
已记录,完整内容见 evidence.json
变更后 / moving 2 / 名称
Wheels001
变更后 / moving 2 / quaternion
已记录,完整内容见 evidence.json
变更后 / onlyActivePivot
true
更多记录
见 evidence.json
+

发布状态

已发布

projectId
156
编码
MODEL-3FA24629D59E4509
名称
实测模型-牛奶卡车-已验证-20260905
状态
PUBLISHED
版本
12
publishedVersionId
200
currentVersionId
200
versionNo
2
checksum
1c9b1233dda661537c9bd4014208f1eb2851d392e5cd9b4260e53570b0820751
schema
digital-twin-editor-project
modelResource / kind
imported
modelResource / ID
imported-model_mto6wi6k_08-cesiummilktruck
modelResource / 名称
08-CesiumMilkTruck
modelResource / assetCode
MODEL_MTO6WI6K_08-CESIUMMILKTRUCK
modelResource / 编码
MODEL_MTO6WI6K_08-CESIUMMILKTRUCK
modelResource / storageUri
fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb
modelResource / sourceName
08-CesiumMilkTruck.glb
modelResource / sizeBytes
369980
modelResource / lastModified
0
modelResource / mimeType
model/gltf-binary
modelResource / vertices
4823
modelResource / triangles
3624
modelResource / 节点数
10
modelResource / 网格数
5
modelResource / 材质数
5
modelResource / 纹理数
1
modelResource / 动画
1
modelResource / animationDurationSeconds
1.25
modelResource / modelMetadata / nodeCount
10
modelResource / modelMetadata / 网格数
5
modelResource / modelMetadata / materialCount
5
modelResource / modelMetadata / textureCount
1
modelResource / modelMetadata / 动画
1 项,完整内容见 evidence.json
modelResource / modelMetadata / animationDurationSeconds
1.25
更多记录
见 evidence.json
更多记录
见 evidence.json
+
+

现场截图

+ +
+

模型 2:实测模型-狐狸动画-已验证-20260905

+
项目记录
项目名称实测模型-狐狸动画-已验证-20260905
项目编码MODEL-70875AA932B94685
项目 ID157
来源素材09-Fox.glb
测试节点fox
动画Run;编号 2;数量 3
原生动画片段3 段:Survey、Walk、Run
+

轻量 GLB 实测:骨骼蒙皮、Survey/Walk/Run 动画、节点编辑、保存重开和发布。保留供后续模型/场景测试使用。

+

操作步骤

+
序号步骤结论证据摘要
1UI创建项目通过HTTP 状态:200
2GLB上传、两阶段绑定、SHA256与活跃模型核验通过未记录
3节点 X 位置、材质粗糙度、原生动画选择保存通过详情 / x:0.25;详情 / roughness:0.3;详情 / 动画编号:Run;详情 / versionBefore:4;详情 / versionAfter:5
4整页刷新后模型、节点、材质、动画选择恢复通过未记录
5原生动画实播:播放时间与轮子/骨骼姿态确实变化通过未记录
6Survey、Walk、Run 三个原生片段逐一实播通过详情 1 / 名称:Survey;详情 1 / 正在播放:true;详情 1 / timeAdvanced:true;详情 1 / bonesChanged:true;详情 2 / 名称:Walk;详情 2 / 正在播放:true;详情 2 / timeAdvanced:true;详情 2 / bonesChanged:true;详情 3 / 名称:Run;详情 3 / 正在播放:true;详情 3 / timeAdvanced:true;详情 3 / bonesChanged:true
7发布到场景资源库并核对服务端发布版本通过HTTP 状态:200
8全新浏览器上下文从服务端载入已发布模型通过详情 / source:09-Fox.glb;详情 / apiMode:true;详情 / 动画编号:Run
9已发布模型改名保存为 V2 草稿,项目及版本更新时间刷新通过详情 / 状态:PASS;详情 / 变更前 / project:2026-09-05T17:33:10;详情 / 变更前 / 版本:2026-09-05T17:33:10;详情 / 变更后 / project:2026-09-05T17:47:39;详情 / 变更后 / 版本:2026-09-05T17:47:39;详情 / draftVersionId:201;详情 / versionNo:2
10V2 重新发布成功,发布版本及更新时间正确通过详情 / versionNo:2;详情 / versionId:201;详情 / updateTime:2026-09-05T17:48:04
11V2 全新浏览器上下文重开,模型文件、动画选择、发布版本均正确通过详情 / source:09-Fox.glb;详情 / 动画编号:Run;详情 / versionNo:2
+
+

导入校验

通过

SHA-256
d97044e701822bac5a62696459b27d7b375aada5de8574ed4362edbba94771f7
文件字节数
162852
变更记录 1 / 状态
200
变更记录 1 / registeredTicket
true
变更记录 1 / sourceName
bridge-erector-vehicle.glb
变更记录 1 / assetCode
MODEL_BRIDGE-ERECTOR-VEHICLE
变更记录 2 / 状态
200
变更记录 2 / registeredTicket
false
变更记录 2 / sourceName
09-Fox.glb
变更记录 2 / assetCode
MODEL_MTO6V5W6_09-FOX
服务端 / projectId
157
服务端 / 编码
MODEL-70875AA932B94685
服务端 / 名称
实测模型-狐狸动画-20260905
服务端 / 状态
DRAFT
服务端 / 版本
4
服务端 / currentVersionId
199
服务端 / versionNo
1
服务端 / checksum
3bfa16814a65c4576b1627e92032c61d2d986145a19d1b4027e570209e306e0d
服务端 / schema
digital-twin-editor-project
服务端 / modelResource / kind
imported
服务端 / modelResource / ID
imported-model_mto6v5w6_09-fox
服务端 / modelResource / 名称
09-Fox
服务端 / modelResource / assetCode
MODEL_MTO6V5W6_09-FOX
服务端 / modelResource / 编码
MODEL_MTO6V5W6_09-FOX
服务端 / modelResource / storageUri
fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb
服务端 / modelResource / sourceName
09-Fox.glb
服务端 / modelResource / sizeBytes
162852
服务端 / modelResource / lastModified
0
服务端 / modelResource / mimeType
model/gltf-binary
服务端 / modelResource / vertices
1728
服务端 / modelResource / triangles
576
服务端 / modelResource / 节点数
27
服务端 / modelResource / 网格数
1
服务端 / modelResource / 材质数
1
服务端 / modelResource / 纹理数
1
服务端 / modelResource / 动画
3
服务端 / modelResource / animationDurationSeconds
3.4166667461395264
服务端 / modelResource / modelMetadata / nodeCount
27
服务端 / modelResource / modelMetadata / 网格数
1
服务端 / modelResource / modelMetadata / materialCount
1
服务端 / modelResource / modelMetadata / textureCount
1
服务端 / modelResource / modelMetadata / 动画
已记录,完整内容见 evidence.json
服务端 / modelResource / modelMetadata / animationDurationSeconds
3.4166667461395264
更多记录
见 evidence.json
更多记录
见 evidence.json
更多记录
见 evidence.json
+

编辑与保存

通过

服务端 / projectId
157
服务端 / 编码
MODEL-70875AA932B94685
服务端 / 名称
实测模型-狐狸动画-20260905
服务端 / 状态
DRAFT
服务端 / 版本
5
服务端 / currentVersionId
199
服务端 / versionNo
1
服务端 / checksum
041667300586ffea8aaba2ba29004cf4ca50dc0f01351215a664f64fa82ab5b9
服务端 / schema
digital-twin-editor-project
服务端 / modelResource / kind
imported
服务端 / modelResource / ID
imported-model_mto6v5w6_09-fox
服务端 / modelResource / 名称
09-Fox
服务端 / modelResource / assetCode
MODEL_MTO6V5W6_09-FOX
服务端 / modelResource / 编码
MODEL_MTO6V5W6_09-FOX
服务端 / modelResource / storageUri
fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb
服务端 / modelResource / sourceName
09-Fox.glb
服务端 / modelResource / sizeBytes
162852
服务端 / modelResource / lastModified
0
服务端 / modelResource / mimeType
model/gltf-binary
服务端 / modelResource / vertices
1728
服务端 / modelResource / triangles
576
服务端 / modelResource / 节点数
27
服务端 / modelResource / 网格数
1
服务端 / modelResource / 材质数
1
服务端 / modelResource / 纹理数
1
服务端 / modelResource / 动画
3
服务端 / modelResource / animationDurationSeconds
3.4166667461395264
服务端 / modelResource / modelMetadata / nodeCount
27
服务端 / modelResource / modelMetadata / 网格数
1
服务端 / modelResource / modelMetadata / materialCount
1
服务端 / modelResource / modelMetadata / textureCount
1
服务端 / modelResource / modelMetadata / 动画
已记录,完整内容见 evidence.json
服务端 / modelResource / modelMetadata / animationDurationSeconds
3.4166667461395264
更多记录
见 evidence.json
更多记录
见 evidence.json
更多记录
见 evidence.json
+

保存后重开

通过

服务端 / projectId
157
服务端 / 编码
MODEL-70875AA932B94685
服务端 / 名称
实测模型-狐狸动画-20260905
服务端 / 状态
DRAFT
服务端 / 版本
5
服务端 / currentVersionId
199
服务端 / versionNo
1
服务端 / checksum
041667300586ffea8aaba2ba29004cf4ca50dc0f01351215a664f64fa82ab5b9
服务端 / schema
digital-twin-editor-project
服务端 / modelResource / kind
imported
服务端 / modelResource / ID
imported-model_mto6v5w6_09-fox
服务端 / modelResource / 名称
09-Fox
服务端 / modelResource / assetCode
MODEL_MTO6V5W6_09-FOX
服务端 / modelResource / 编码
MODEL_MTO6V5W6_09-FOX
服务端 / modelResource / storageUri
fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb
服务端 / modelResource / sourceName
09-Fox.glb
服务端 / modelResource / sizeBytes
162852
服务端 / modelResource / lastModified
0
服务端 / modelResource / mimeType
model/gltf-binary
服务端 / modelResource / vertices
1728
服务端 / modelResource / triangles
576
服务端 / modelResource / 节点数
27
服务端 / modelResource / 网格数
1
服务端 / modelResource / 材质数
1
服务端 / modelResource / 纹理数
1
服务端 / modelResource / 动画
3
服务端 / modelResource / animationDurationSeconds
3.4166667461395264
服务端 / modelResource / modelMetadata / nodeCount
27
服务端 / modelResource / modelMetadata / 网格数
1
服务端 / modelResource / modelMetadata / materialCount
1
服务端 / modelResource / modelMetadata / textureCount
1
服务端 / modelResource / modelMetadata / 动画
已记录,完整内容见 evidence.json
服务端 / modelResource / modelMetadata / animationDurationSeconds
3.4166667461395264
更多记录
见 evidence.json
更多记录
见 evidence.json
更多记录
见 evidence.json
+

动画检查

通过

动画编号
Run
变更前 / sourceName
09-Fox.glb
变更前 / assetCode
MODEL_MTO6V5W6_09-FOX
变更前 / 节点数
27
变更前 / 网格数
1
变更前 / 材质数
1
变更前 / 动画数 1 / 名称
Survey
变更前 / 动画数 1 / duration
3.4166667461395264
变更前 / 动画数 1 / tracks
21
变更前 / 动画数 2 / 名称
Walk
变更前 / 动画数 2 / duration
0.7083333134651184
变更前 / 动画数 2 / tracks
21
变更前 / 动画数 3 / 名称
Run
变更前 / 动画数 3 / duration
1.1583333015441895
变更前 / 动画数 3 / tracks
21
变更前 / clipIndex
2
变更前 / 正在播放
true
变更前 / 时间
0.017099999904632568
变更前 / mesh / 名称
fox
变更前 / mesh / editorId
model-imported-model_mto6v5w6_09-fox-26
变更前 / mesh / 位置
0.25、0、0
变更前 / mesh / 缩放
1、1、1
变更前 / mesh / isSkinnedMesh
true
变更前 / mesh / bones
24
变更前 / moving 1 / 名称
_rootJoint
变更前 / moving 1 / quaternion
已记录,完整内容见 evidence.json
变更前 / moving 2 / 名称
b_Root_00
变更前 / moving 2 / quaternion
已记录,完整内容见 evidence.json
变更前 / moving 3 / 名称
b_Hip_01
变更前 / moving 3 / quaternion
已记录,完整内容见 evidence.json
变更前 / moving
共 24 项,完整内容见 evidence.json
更多记录
见 evidence.json
更多记录
见 evidence.json
+

发布状态

已发布

projectId
157
编码
MODEL-70875AA932B94685
名称
实测模型-狐狸动画-已验证-20260905
状态
PUBLISHED
版本
10
publishedVersionId
201
currentVersionId
201
versionNo
2
checksum
fbb1c9ad102a20aa3f0add103167a165d2454a9935f470df2e415731ff0a160d
schema
digital-twin-editor-project
modelResource / kind
imported
modelResource / ID
imported-model_mto6v5w6_09-fox
modelResource / 名称
09-Fox
modelResource / assetCode
MODEL_MTO6V5W6_09-FOX
modelResource / 编码
MODEL_MTO6V5W6_09-FOX
modelResource / storageUri
fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb
modelResource / sourceName
09-Fox.glb
modelResource / sizeBytes
162852
modelResource / lastModified
0
modelResource / mimeType
model/gltf-binary
modelResource / vertices
1728
modelResource / triangles
576
modelResource / 节点数
27
modelResource / 网格数
1
modelResource / 材质数
1
modelResource / 纹理数
1
modelResource / 动画
3
modelResource / animationDurationSeconds
3.4166667461395264
modelResource / modelMetadata / nodeCount
27
modelResource / modelMetadata / 网格数
1
modelResource / modelMetadata / materialCount
1
modelResource / modelMetadata / textureCount
1
modelResource / modelMetadata / 动画
3 项,完整内容见 evidence.json
modelResource / modelMetadata / animationDurationSeconds
3.4166667461395264
更多记录
见 evidence.json
更多记录
见 evidence.json
+
+

现场截图

+ +
+

补充验证

+

最终项目列表

类别
final-list
状态
PASS
列表核验结果
MODEL-70875AA932B94685 · 整机装备实测模型-狐狸动画-20260905节点 27 · 材质 1 · 动画 1系统管理员更新:2026/09/05 17:33已发布进入编辑更多、MODEL-3FA24629D59E4509 · 整机装备实测模型-牛奶卡车-20260905节点 10 · 材质 5 · 动画 1系统管理员更新:2026/09/05 17:24已发布进入编辑更多
+

构建检查

类别
build
状态
PASS
执行命令
pnpm run build
详情
类型检查、Vite 构建、public/dist hash、API 桥接与凭据门禁均通过
+

实测范围

类别
scope
详情
通过实际页面操作创建/导入/编辑/播放/保存/发布;只读 API 与全新浏览器会话交叉核验。未创建场景,未执行训练业务蓝图,未改表结构或账号权限。
+

最终项目列表

类别
final-list
状态
PASS
详情
最终 V2 列表:狐狸 17:48 排在卡车 17:47 之前,最近更新排序与服务端保存、发布时间一致。
列表核验结果
MODEL-70875AA932B94685 · 整机装备实测模型-狐狸动画-已验证-20260905节点 27 · 材质 1 · 动画 1系统管理员更新:2026/09/05 17:48已发布进入编辑更多、MODEL-3FA24629D59E4509 · 整机装备实测模型-牛奶卡车-已验证-20260905节点 10 · 材质 5 · 动画 1系统管理员更新:2026/09/05 17:47已发布进入编辑更多
+

backend-regression

类别
backend-regression
状态
PASS
执行命令
mvn -B -ntp -pl ut_tran -Dtest=ContentProjectServiceTest test
详情
Java 17;70项用例通过,0失败/错误/跳过。新增用例先复现旧时间写回,再验证修复。
+

build-final

类别
build-final
状态
PASS
详情
最终 pnpm run build 通过;stage生成camera-fit统一LF后,10个payload的public/dist哈希、API桥接与凭据门禁通过,git diff --check通过。
执行命令
pnpm run build
+

cover-display

类别
cover-display
详情
两条测试数据未设置自定义封面,列表沿用现有默认装备缩略图;编辑器内已分别验证真实卡车与狐狸。若需要导入后自动生成模型封面,属于另行确认的功能增强。
+
+

补充截图

+ +
+

遗留数据与保留说明

+
项目ID编码保留/清理结论
实测模型-牛奶卡车-已验证-20260905156MODEL-3FA24629D59E4509保留
实测模型-狐狸动画-已验证-20260905157MODEL-70875AA932B94685保留
+
记录
保留本次创建的两条模型工程与上传资产,供用户继续测试。
+

本报告生成过程不修改项目数据。数据保留与清理结果以证据记录为准。

+

问题与待确认项

+
标题
模型编辑器生成包陈旧,页面实际运行本地模式
状态
已修复并验证
impact
新建记录存在,但旧编辑器未读取项目 ID,模型编辑和自动保存未写入内容制作 API。
fix
从现有接口版源码重建并暂存编辑器包,增加 build 产物 API 桥接检查。
标题
GLB 上传被文件服务 503 阻断
状态
已修复并验证
impact
上传未成功,原工程模型与资产仍保留。
requestId
69785305-558a-4a43-99bf-655b4adda274
cause
用户级 UT_FILE_SERVICE_BASE_URL / CONTENT_BASE_URL 残留关闭的 127.0.0.1:17180 代理地址
fix
恢复到现有配置的远端真实文件服务,保留密钥,仅重启 ut-tran;实际 GLB 上传已返回200
标题
列表“动画”统计口径需确认
状态
待确认,未改功能
impact
狐狸实际有 Survey、Walk、Run 3 个原生片段,全部实播通过;列表显示动画1,统计的是1条自编时间轴轨道。
suggestion
可将列表文案明确为“动画轨道”,或增加“原生动画3段 / 自编轨道1条”的分项展示,待用户确认后实施。
标题
保存和发布没有刷新项目/版本更新时间
状态
已修复并验证
cause
读取实体携带旧 updateTime,updateById 再次写回旧值,数据库自动更新时间未生效。
fix
项目、版本两个统一更新方法显式设置当前秒精度时间;无表结构变更。
verification
两模型改名生成 V2 草稿并重新发布;API时间、页面时间、最近更新排序和全新浏览器重开均通过。
+
+
\ No newline at end of file diff --git a/reports/model-live-20260905/report.md b/reports/model-live-20260905/report.md new file mode 100644 index 0000000..a2ddafb --- /dev/null +++ b/reports/model-live-20260905/report.md @@ -0,0 +1,657 @@ +# 真实模型制作实测报告 · 2026-09-05 + +已记录 2/2 个模型项目、23 项步骤:23 项通过,0 项失败,0 项其他或未记录结论。 + +统计仅来自明确记录的步骤结论;缺失字段、仅有数据或仅有截图均不视为通过。 + +## 环境与身份 + +| 项目 | 记录 | +| --- | --- | +| 测试日期 | 2026-09-05 | +| 页面地址 | http://127.0.0.1:6180 | +| 浏览器 | Microsoft Edge | +| 账号角色 | teacher | +| 账号显示名称 | 系统管理员 | + +## 模型 1:实测模型-牛奶卡车-已验证-20260905 + +| 项目 | 记录 | +| --- | --- | +| 项目名称 | 实测模型-牛奶卡车-已验证-20260905 | +| 项目编码 | MODEL-3FA24629D59E4509 | +| 项目 ID | 156 | +| 来源素材 | 08-CesiumMilkTruck.glb | +| 测试节点 | Cesium\_Milk\_Truck | +| 动画 | Wheels;编号 0;数量 1 | +| 原生动画片段 | 1 段:Wheels | + +轻量 GLB 实测:车辆多部件、节点编辑、车轮动画、保存重开和发布。保留供后续模型/场景测试使用。 + +### 操作步骤 + +| 序号 | 步骤 | 结论 | 证据摘要 | +| --- | --- | --- | --- | +| 1 | UI创建项目 | 通过 | HTTP 状态:200 | +| 2 | 文件服务地址修复后重新上传 | 通过 | HTTP 状态:200;详情:首次上传失败保留于问题证据;修复地址后已实际上传成功并校验文件哈希;initialHttpStatus:503 | +| 3 | GLB上传、两阶段绑定、SHA256与活跃模型核验 | 通过 | 未记录 | +| 4 | 组合节点 X 位置与原生动画选择保存 | 通过 | 详情 / x:0.35;详情 / 动画编号:Wheels;详情 / versionBefore:5;详情 / versionAfter:6 | +| 5 | 整页刷新后模型、节点、材质、动画选择恢复 | 通过 | 未记录 | +| 6 | 原生动画实播:播放时间与轮子/骨骼姿态确实变化 | 通过 | 未记录 | +| 7 | 车身子网格材质粗糙度修改、保存、刷新恢复 | 通过 | 详情 / node:Cesium\_Milk\_Truck\_1;详情 / roughness:0.3;详情 / persistedAfterReload:true | +| 8 | 发布到场景资源库并核对服务端发布版本 | 通过 | HTTP 状态:200 | +| 9 | 全新浏览器上下文从服务端载入已发布模型 | 通过 | 详情 / source:08-CesiumMilkTruck.glb;详情 / apiMode:true;详情 / 动画编号:Wheels | +| 10 | 已发布模型改名保存为 V2 草稿,项目及版本更新时间刷新 | 通过 | 详情 / 状态:PASS;详情 / 变更前 / project:2026-09-05T17:24:34;详情 / 变更前 / 版本:2026-09-05T17:24:34;详情 / 变更后 / project:2026-09-05T17:47:05;详情 / 变更后 / 版本:2026-09-05T17:47:05;详情 / draftVersionId:200;详情 / versionNo:2 | +| 11 | V2 重新发布成功,发布版本及更新时间正确 | 通过 | 详情 / versionNo:2;详情 / versionId:200;详情 / updateTime:2026-09-05T17:47:29 | +| 12 | V2 全新浏览器上下文重开,模型文件、动画选择、发布版本均正确 | 通过 | 详情 / source:08-CesiumMilkTruck.glb;详情 / 动画编号:Wheels;详情 / versionNo:2 | + +### 导入校验 + +结论:通过 + +- SHA-256:09371b34608116de5842d23abe260bf11acf3e1554daf334a647eb566eee5c49 +- 文件字节数:369980 +- 变更记录 1 / 状态:200 +- 变更记录 1 / registeredTicket:true +- 变更记录 1 / sourceName:bridge-erector-vehicle.glb +- 变更记录 1 / assetCode:MODEL\_BRIDGE-ERECTOR-VEHICLE +- 变更记录 2 / 状态:200 +- 变更记录 2 / registeredTicket:false +- 变更记录 2 / sourceName:08-CesiumMilkTruck.glb +- 变更记录 2 / assetCode:MODEL\_MTO6WI6K\_08-CESIUMMILKTRUCK +- 服务端 / projectId:156 +- 服务端 / 编码:MODEL-3FA24629D59E4509 +- 服务端 / 名称:实测模型-牛奶卡车-20260905 +- 服务端 / 状态:DRAFT +- 服务端 / 版本:4 +- 服务端 / currentVersionId:198 +- 服务端 / versionNo:1 +- 服务端 / checksum:30ee74fe8f8763e6342f1bbc36607a06db0f6f79061471ab7334e61028029d01 +- 服务端 / schema:digital-twin-editor-project +- 服务端 / modelResource / kind:imported +- 服务端 / modelResource / ID:imported-model\_mto6wi6k\_08-cesiummilktruck +- 服务端 / modelResource / 名称:08-CesiumMilkTruck +- 服务端 / modelResource / assetCode:MODEL\_MTO6WI6K\_08-CESIUMMILKTRUCK +- 服务端 / modelResource / 编码:MODEL\_MTO6WI6K\_08-CESIUMMILKTRUCK +- 服务端 / modelResource / storageUri:fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb +- 服务端 / modelResource / sourceName:08-CesiumMilkTruck.glb +- 服务端 / modelResource / sizeBytes:369980 +- 服务端 / modelResource / lastModified:0 +- 服务端 / modelResource / mimeType:model/gltf-binary +- 服务端 / modelResource / vertices:4823 +- 服务端 / modelResource / triangles:3624 +- 服务端 / modelResource / 节点数:10 +- 服务端 / modelResource / 网格数:5 +- 服务端 / modelResource / 材质数:5 +- 服务端 / modelResource / 纹理数:1 +- 服务端 / modelResource / 动画:1 +- 服务端 / modelResource / animationDurationSeconds:1.25 +- 服务端 / modelResource / modelMetadata / nodeCount:10 +- 服务端 / modelResource / modelMetadata / 网格数:5 +- 服务端 / modelResource / modelMetadata / materialCount:5 +- 服务端 / modelResource / modelMetadata / textureCount:1 +- 服务端 / modelResource / modelMetadata / 动画:已记录,完整内容见 evidence.json +- 服务端 / modelResource / modelMetadata / animationDurationSeconds:1.25 +- 更多记录:见 evidence.json +- 更多记录:见 evidence.json +- 更多记录:见 evidence.json + +### 编辑与保存 + +结论:通过 + +- 服务端 / projectId:156 +- 服务端 / 编码:MODEL-3FA24629D59E4509 +- 服务端 / 名称:实测模型-牛奶卡车-20260905 +- 服务端 / 状态:DRAFT +- 服务端 / 版本:6 +- 服务端 / currentVersionId:198 +- 服务端 / versionNo:1 +- 服务端 / checksum:495aaedac19971b06dec73ad43bdebfcfb63d0604fabaf48f460c7bc1cdcc229 +- 服务端 / schema:digital-twin-editor-project +- 服务端 / modelResource / kind:imported +- 服务端 / modelResource / ID:imported-model\_mto6wi6k\_08-cesiummilktruck +- 服务端 / modelResource / 名称:08-CesiumMilkTruck +- 服务端 / modelResource / assetCode:MODEL\_MTO6WI6K\_08-CESIUMMILKTRUCK +- 服务端 / modelResource / 编码:MODEL\_MTO6WI6K\_08-CESIUMMILKTRUCK +- 服务端 / modelResource / storageUri:fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb +- 服务端 / modelResource / sourceName:08-CesiumMilkTruck.glb +- 服务端 / modelResource / sizeBytes:369980 +- 服务端 / modelResource / lastModified:0 +- 服务端 / modelResource / mimeType:model/gltf-binary +- 服务端 / modelResource / vertices:4823 +- 服务端 / modelResource / triangles:3624 +- 服务端 / modelResource / 节点数:10 +- 服务端 / modelResource / 网格数:5 +- 服务端 / modelResource / 材质数:5 +- 服务端 / modelResource / 纹理数:1 +- 服务端 / modelResource / 动画:1 +- 服务端 / modelResource / animationDurationSeconds:1.25 +- 服务端 / modelResource / modelMetadata / nodeCount:10 +- 服务端 / modelResource / modelMetadata / 网格数:5 +- 服务端 / modelResource / modelMetadata / materialCount:5 +- 服务端 / modelResource / modelMetadata / textureCount:1 +- 服务端 / modelResource / modelMetadata / 动画:已记录,完整内容见 evidence.json +- 服务端 / modelResource / modelMetadata / animationDurationSeconds:1.25 +- 更多记录:见 evidence.json +- 更多记录:见 evidence.json +- 更多记录:见 evidence.json + +### 保存后重开 + +结论:通过 + +- 服务端 / projectId:156 +- 服务端 / 编码:MODEL-3FA24629D59E4509 +- 服务端 / 名称:实测模型-牛奶卡车-20260905 +- 服务端 / 状态:DRAFT +- 服务端 / 版本:6 +- 服务端 / currentVersionId:198 +- 服务端 / versionNo:1 +- 服务端 / checksum:495aaedac19971b06dec73ad43bdebfcfb63d0604fabaf48f460c7bc1cdcc229 +- 服务端 / schema:digital-twin-editor-project +- 服务端 / modelResource / kind:imported +- 服务端 / modelResource / ID:imported-model\_mto6wi6k\_08-cesiummilktruck +- 服务端 / modelResource / 名称:08-CesiumMilkTruck +- 服务端 / modelResource / assetCode:MODEL\_MTO6WI6K\_08-CESIUMMILKTRUCK +- 服务端 / modelResource / 编码:MODEL\_MTO6WI6K\_08-CESIUMMILKTRUCK +- 服务端 / modelResource / storageUri:fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb +- 服务端 / modelResource / sourceName:08-CesiumMilkTruck.glb +- 服务端 / modelResource / sizeBytes:369980 +- 服务端 / modelResource / lastModified:0 +- 服务端 / modelResource / mimeType:model/gltf-binary +- 服务端 / modelResource / vertices:4823 +- 服务端 / modelResource / triangles:3624 +- 服务端 / modelResource / 节点数:10 +- 服务端 / modelResource / 网格数:5 +- 服务端 / modelResource / 材质数:5 +- 服务端 / modelResource / 纹理数:1 +- 服务端 / modelResource / 动画:1 +- 服务端 / modelResource / animationDurationSeconds:1.25 +- 服务端 / modelResource / modelMetadata / nodeCount:10 +- 服务端 / modelResource / modelMetadata / 网格数:5 +- 服务端 / modelResource / modelMetadata / materialCount:5 +- 服务端 / modelResource / modelMetadata / textureCount:1 +- 服务端 / modelResource / modelMetadata / 动画:已记录,完整内容见 evidence.json +- 服务端 / modelResource / modelMetadata / animationDurationSeconds:1.25 +- 更多记录:见 evidence.json +- 更多记录:见 evidence.json +- 更多记录:见 evidence.json + +### 动画检查 + +结论:通过 + +- 动画编号:Wheels +- 变更前 / sourceName:08-CesiumMilkTruck.glb +- 变更前 / assetCode:MODEL\_MTO6WI6K\_08-CESIUMMILKTRUCK +- 变更前 / 节点数:10 +- 变更前 / 网格数:5 +- 变更前 / 材质数:5 +- 变更前 / 动画数 1 / 名称:Wheels +- 变更前 / 动画数 1 / duration:1.25 +- 变更前 / 动画数 1 / tracks:2 +- 变更前 / clipIndex:0 +- 变更前 / 正在播放:true +- 变更前 / 时间:0.017299999952316285 +- 变更前 / mesh / 名称:Cesium\_Milk\_Truck +- 变更前 / mesh / editorId:model-imported-model\_mto6wi6k\_08-cesiummilktruck-2 +- 变更前 / mesh / 位置:0.35、0、0 +- 变更前 / mesh / 缩放:1、1、1 +- 变更前 / mesh / isSkinnedMesh:false +- 变更前 / mesh / bones:0 +- 变更前 / moving 1 / 名称:Wheels +- 变更前 / moving 1 / quaternion:已记录,完整内容见 evidence.json +- 变更前 / moving 2 / 名称:Wheels001 +- 变更前 / moving 2 / quaternion:已记录,完整内容见 evidence.json +- 变更前 / onlyActivePivot:true +- 变更后 / sourceName:08-CesiumMilkTruck.glb +- 变更后 / assetCode:MODEL\_MTO6WI6K\_08-CESIUMMILKTRUCK +- 变更后 / 节点数:10 +- 变更后 / 网格数:5 +- 变更后 / 材质数:5 +- 变更后 / 动画数 1 / 名称:Wheels +- 变更后 / 动画数 1 / duration:1.25 +- 变更后 / 动画数 1 / tracks:2 +- 变更后 / clipIndex:0 +- 变更后 / 正在播放:true +- 变更后 / 时间:0.11699999999999999 +- 变更后 / mesh / 名称:Cesium\_Milk\_Truck +- 变更后 / mesh / editorId:model-imported-model\_mto6wi6k\_08-cesiummilktruck-2 +- 变更后 / mesh / 位置:0.35、0、0 +- 变更后 / mesh / 缩放:1、1、1 +- 变更后 / mesh / isSkinnedMesh:false +- 变更后 / mesh / bones:0 +- 变更后 / moving 1 / 名称:Wheels +- 变更后 / moving 1 / quaternion:已记录,完整内容见 evidence.json +- 变更后 / moving 2 / 名称:Wheels001 +- 变更后 / moving 2 / quaternion:已记录,完整内容见 evidence.json +- 变更后 / onlyActivePivot:true +- 更多记录:见 evidence.json + +### 发布状态 + +结论:已发布 + +- projectId:156 +- 编码:MODEL-3FA24629D59E4509 +- 名称:实测模型-牛奶卡车-已验证-20260905 +- 状态:PUBLISHED +- 版本:12 +- publishedVersionId:200 +- currentVersionId:200 +- versionNo:2 +- checksum:1c9b1233dda661537c9bd4014208f1eb2851d392e5cd9b4260e53570b0820751 +- schema:digital-twin-editor-project +- modelResource / kind:imported +- modelResource / ID:imported-model\_mto6wi6k\_08-cesiummilktruck +- modelResource / 名称:08-CesiumMilkTruck +- modelResource / assetCode:MODEL\_MTO6WI6K\_08-CESIUMMILKTRUCK +- modelResource / 编码:MODEL\_MTO6WI6K\_08-CESIUMMILKTRUCK +- modelResource / storageUri:fsvc://unreal-tran/model/2026/09/05/a75de903d95b0590307632d7bed44111.glb +- modelResource / sourceName:08-CesiumMilkTruck.glb +- modelResource / sizeBytes:369980 +- modelResource / lastModified:0 +- modelResource / mimeType:model/gltf-binary +- modelResource / vertices:4823 +- modelResource / triangles:3624 +- modelResource / 节点数:10 +- modelResource / 网格数:5 +- modelResource / 材质数:5 +- modelResource / 纹理数:1 +- modelResource / 动画:1 +- modelResource / animationDurationSeconds:1.25 +- modelResource / modelMetadata / nodeCount:10 +- modelResource / modelMetadata / 网格数:5 +- modelResource / modelMetadata / materialCount:5 +- modelResource / modelMetadata / textureCount:1 +- modelResource / modelMetadata / 动画:1 项,完整内容见 evidence.json +- modelResource / modelMetadata / animationDurationSeconds:1.25 +- 更多记录:见 evidence.json +- 更多记录:见 evidence.json + +### 现场截图 + +![文件服务地址修复后重新上传](screenshots/03b-upload-error-log.png) + +![GLB上传、两阶段绑定、SHA256与活跃模型核验](screenshots/1-01-imported.png) + +![组合节点 X 位置与原生动画选择保存](screenshots/1-02-edited.png) + +![整页刷新后模型、节点、材质、动画选择恢复](screenshots/1-03-reopened.png) + +![原生动画实播:播放时间与轮子/骨骼姿态确实变化](screenshots/1-04-animation.png) + +![车身子网格材质粗糙度修改、保存、刷新恢复](screenshots/1-04b-material-reopened.png) + +![发布到场景资源库并核对服务端发布版本](screenshots/1-05-published.png) + +![全新浏览器上下文从服务端载入已发布模型](screenshots/1-06-fresh-session.png) + +![已发布模型改名保存为 V2 草稿,项目及版本更新时间刷新](screenshots/1-07-update-time.png) + +![V2 重新发布成功,发布版本及更新时间正确](screenshots/1-08-published-v2.png) + +![V2 全新浏览器上下文重开,模型文件、动画选择、发布版本均正确](screenshots/1-09-fresh-session-v2.png) + +## 模型 2:实测模型-狐狸动画-已验证-20260905 + +| 项目 | 记录 | +| --- | --- | +| 项目名称 | 实测模型-狐狸动画-已验证-20260905 | +| 项目编码 | MODEL-70875AA932B94685 | +| 项目 ID | 157 | +| 来源素材 | 09-Fox.glb | +| 测试节点 | fox | +| 动画 | Run;编号 2;数量 3 | +| 原生动画片段 | 3 段:Survey、Walk、Run | + +轻量 GLB 实测:骨骼蒙皮、Survey/Walk/Run 动画、节点编辑、保存重开和发布。保留供后续模型/场景测试使用。 + +### 操作步骤 + +| 序号 | 步骤 | 结论 | 证据摘要 | +| --- | --- | --- | --- | +| 1 | UI创建项目 | 通过 | HTTP 状态:200 | +| 2 | GLB上传、两阶段绑定、SHA256与活跃模型核验 | 通过 | 未记录 | +| 3 | 节点 X 位置、材质粗糙度、原生动画选择保存 | 通过 | 详情 / x:0.25;详情 / roughness:0.3;详情 / 动画编号:Run;详情 / versionBefore:4;详情 / versionAfter:5 | +| 4 | 整页刷新后模型、节点、材质、动画选择恢复 | 通过 | 未记录 | +| 5 | 原生动画实播:播放时间与轮子/骨骼姿态确实变化 | 通过 | 未记录 | +| 6 | Survey、Walk、Run 三个原生片段逐一实播 | 通过 | 详情 1 / 名称:Survey;详情 1 / 正在播放:true;详情 1 / timeAdvanced:true;详情 1 / bonesChanged:true;详情 2 / 名称:Walk;详情 2 / 正在播放:true;详情 2 / timeAdvanced:true;详情 2 / bonesChanged:true;详情 3 / 名称:Run;详情 3 / 正在播放:true;详情 3 / timeAdvanced:true;详情 3 / bonesChanged:true | +| 7 | 发布到场景资源库并核对服务端发布版本 | 通过 | HTTP 状态:200 | +| 8 | 全新浏览器上下文从服务端载入已发布模型 | 通过 | 详情 / source:09-Fox.glb;详情 / apiMode:true;详情 / 动画编号:Run | +| 9 | 已发布模型改名保存为 V2 草稿,项目及版本更新时间刷新 | 通过 | 详情 / 状态:PASS;详情 / 变更前 / project:2026-09-05T17:33:10;详情 / 变更前 / 版本:2026-09-05T17:33:10;详情 / 变更后 / project:2026-09-05T17:47:39;详情 / 变更后 / 版本:2026-09-05T17:47:39;详情 / draftVersionId:201;详情 / versionNo:2 | +| 10 | V2 重新发布成功,发布版本及更新时间正确 | 通过 | 详情 / versionNo:2;详情 / versionId:201;详情 / updateTime:2026-09-05T17:48:04 | +| 11 | V2 全新浏览器上下文重开,模型文件、动画选择、发布版本均正确 | 通过 | 详情 / source:09-Fox.glb;详情 / 动画编号:Run;详情 / versionNo:2 | + +### 导入校验 + +结论:通过 + +- SHA-256:d97044e701822bac5a62696459b27d7b375aada5de8574ed4362edbba94771f7 +- 文件字节数:162852 +- 变更记录 1 / 状态:200 +- 变更记录 1 / registeredTicket:true +- 变更记录 1 / sourceName:bridge-erector-vehicle.glb +- 变更记录 1 / assetCode:MODEL\_BRIDGE-ERECTOR-VEHICLE +- 变更记录 2 / 状态:200 +- 变更记录 2 / registeredTicket:false +- 变更记录 2 / sourceName:09-Fox.glb +- 变更记录 2 / assetCode:MODEL\_MTO6V5W6\_09-FOX +- 服务端 / projectId:157 +- 服务端 / 编码:MODEL-70875AA932B94685 +- 服务端 / 名称:实测模型-狐狸动画-20260905 +- 服务端 / 状态:DRAFT +- 服务端 / 版本:4 +- 服务端 / currentVersionId:199 +- 服务端 / versionNo:1 +- 服务端 / checksum:3bfa16814a65c4576b1627e92032c61d2d986145a19d1b4027e570209e306e0d +- 服务端 / schema:digital-twin-editor-project +- 服务端 / modelResource / kind:imported +- 服务端 / modelResource / ID:imported-model\_mto6v5w6\_09-fox +- 服务端 / modelResource / 名称:09-Fox +- 服务端 / modelResource / assetCode:MODEL\_MTO6V5W6\_09-FOX +- 服务端 / modelResource / 编码:MODEL\_MTO6V5W6\_09-FOX +- 服务端 / modelResource / storageUri:fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb +- 服务端 / modelResource / sourceName:09-Fox.glb +- 服务端 / modelResource / sizeBytes:162852 +- 服务端 / modelResource / lastModified:0 +- 服务端 / modelResource / mimeType:model/gltf-binary +- 服务端 / modelResource / vertices:1728 +- 服务端 / modelResource / triangles:576 +- 服务端 / modelResource / 节点数:27 +- 服务端 / modelResource / 网格数:1 +- 服务端 / modelResource / 材质数:1 +- 服务端 / modelResource / 纹理数:1 +- 服务端 / modelResource / 动画:3 +- 服务端 / modelResource / animationDurationSeconds:3.4166667461395264 +- 服务端 / modelResource / modelMetadata / nodeCount:27 +- 服务端 / modelResource / modelMetadata / 网格数:1 +- 服务端 / modelResource / modelMetadata / materialCount:1 +- 服务端 / modelResource / modelMetadata / textureCount:1 +- 服务端 / modelResource / modelMetadata / 动画:已记录,完整内容见 evidence.json +- 服务端 / modelResource / modelMetadata / animationDurationSeconds:3.4166667461395264 +- 更多记录:见 evidence.json +- 更多记录:见 evidence.json +- 更多记录:见 evidence.json + +### 编辑与保存 + +结论:通过 + +- 服务端 / projectId:157 +- 服务端 / 编码:MODEL-70875AA932B94685 +- 服务端 / 名称:实测模型-狐狸动画-20260905 +- 服务端 / 状态:DRAFT +- 服务端 / 版本:5 +- 服务端 / currentVersionId:199 +- 服务端 / versionNo:1 +- 服务端 / checksum:041667300586ffea8aaba2ba29004cf4ca50dc0f01351215a664f64fa82ab5b9 +- 服务端 / schema:digital-twin-editor-project +- 服务端 / modelResource / kind:imported +- 服务端 / modelResource / ID:imported-model\_mto6v5w6\_09-fox +- 服务端 / modelResource / 名称:09-Fox +- 服务端 / modelResource / assetCode:MODEL\_MTO6V5W6\_09-FOX +- 服务端 / modelResource / 编码:MODEL\_MTO6V5W6\_09-FOX +- 服务端 / modelResource / storageUri:fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb +- 服务端 / modelResource / sourceName:09-Fox.glb +- 服务端 / modelResource / sizeBytes:162852 +- 服务端 / modelResource / lastModified:0 +- 服务端 / modelResource / mimeType:model/gltf-binary +- 服务端 / modelResource / vertices:1728 +- 服务端 / modelResource / triangles:576 +- 服务端 / modelResource / 节点数:27 +- 服务端 / modelResource / 网格数:1 +- 服务端 / modelResource / 材质数:1 +- 服务端 / modelResource / 纹理数:1 +- 服务端 / modelResource / 动画:3 +- 服务端 / modelResource / animationDurationSeconds:3.4166667461395264 +- 服务端 / modelResource / modelMetadata / nodeCount:27 +- 服务端 / modelResource / modelMetadata / 网格数:1 +- 服务端 / modelResource / modelMetadata / materialCount:1 +- 服务端 / modelResource / modelMetadata / textureCount:1 +- 服务端 / modelResource / modelMetadata / 动画:已记录,完整内容见 evidence.json +- 服务端 / modelResource / modelMetadata / animationDurationSeconds:3.4166667461395264 +- 更多记录:见 evidence.json +- 更多记录:见 evidence.json +- 更多记录:见 evidence.json + +### 保存后重开 + +结论:通过 + +- 服务端 / projectId:157 +- 服务端 / 编码:MODEL-70875AA932B94685 +- 服务端 / 名称:实测模型-狐狸动画-20260905 +- 服务端 / 状态:DRAFT +- 服务端 / 版本:5 +- 服务端 / currentVersionId:199 +- 服务端 / versionNo:1 +- 服务端 / checksum:041667300586ffea8aaba2ba29004cf4ca50dc0f01351215a664f64fa82ab5b9 +- 服务端 / schema:digital-twin-editor-project +- 服务端 / modelResource / kind:imported +- 服务端 / modelResource / ID:imported-model\_mto6v5w6\_09-fox +- 服务端 / modelResource / 名称:09-Fox +- 服务端 / modelResource / assetCode:MODEL\_MTO6V5W6\_09-FOX +- 服务端 / modelResource / 编码:MODEL\_MTO6V5W6\_09-FOX +- 服务端 / modelResource / storageUri:fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb +- 服务端 / modelResource / sourceName:09-Fox.glb +- 服务端 / modelResource / sizeBytes:162852 +- 服务端 / modelResource / lastModified:0 +- 服务端 / modelResource / mimeType:model/gltf-binary +- 服务端 / modelResource / vertices:1728 +- 服务端 / modelResource / triangles:576 +- 服务端 / modelResource / 节点数:27 +- 服务端 / modelResource / 网格数:1 +- 服务端 / modelResource / 材质数:1 +- 服务端 / modelResource / 纹理数:1 +- 服务端 / modelResource / 动画:3 +- 服务端 / modelResource / animationDurationSeconds:3.4166667461395264 +- 服务端 / modelResource / modelMetadata / nodeCount:27 +- 服务端 / modelResource / modelMetadata / 网格数:1 +- 服务端 / modelResource / modelMetadata / materialCount:1 +- 服务端 / modelResource / modelMetadata / textureCount:1 +- 服务端 / modelResource / modelMetadata / 动画:已记录,完整内容见 evidence.json +- 服务端 / modelResource / modelMetadata / animationDurationSeconds:3.4166667461395264 +- 更多记录:见 evidence.json +- 更多记录:见 evidence.json +- 更多记录:见 evidence.json + +### 动画检查 + +结论:通过 + +- 动画编号:Run +- 变更前 / sourceName:09-Fox.glb +- 变更前 / assetCode:MODEL\_MTO6V5W6\_09-FOX +- 变更前 / 节点数:27 +- 变更前 / 网格数:1 +- 变更前 / 材质数:1 +- 变更前 / 动画数 1 / 名称:Survey +- 变更前 / 动画数 1 / duration:3.4166667461395264 +- 变更前 / 动画数 1 / tracks:21 +- 变更前 / 动画数 2 / 名称:Walk +- 变更前 / 动画数 2 / duration:0.7083333134651184 +- 变更前 / 动画数 2 / tracks:21 +- 变更前 / 动画数 3 / 名称:Run +- 变更前 / 动画数 3 / duration:1.1583333015441895 +- 变更前 / 动画数 3 / tracks:21 +- 变更前 / clipIndex:2 +- 变更前 / 正在播放:true +- 变更前 / 时间:0.017099999904632568 +- 变更前 / mesh / 名称:fox +- 变更前 / mesh / editorId:model-imported-model\_mto6v5w6\_09-fox-26 +- 变更前 / mesh / 位置:0.25、0、0 +- 变更前 / mesh / 缩放:1、1、1 +- 变更前 / mesh / isSkinnedMesh:true +- 变更前 / mesh / bones:24 +- 变更前 / moving 1 / 名称:\_rootJoint +- 变更前 / moving 1 / quaternion:已记录,完整内容见 evidence.json +- 变更前 / moving 2 / 名称:b\_Root\_00 +- 变更前 / moving 2 / quaternion:已记录,完整内容见 evidence.json +- 变更前 / moving 3 / 名称:b\_Hip\_01 +- 变更前 / moving 3 / quaternion:已记录,完整内容见 evidence.json +- 变更前 / moving:共 24 项,完整内容见 evidence.json +- 更多记录:见 evidence.json +- 更多记录:见 evidence.json + +### 发布状态 + +结论:已发布 + +- projectId:157 +- 编码:MODEL-70875AA932B94685 +- 名称:实测模型-狐狸动画-已验证-20260905 +- 状态:PUBLISHED +- 版本:10 +- publishedVersionId:201 +- currentVersionId:201 +- versionNo:2 +- checksum:fbb1c9ad102a20aa3f0add103167a165d2454a9935f470df2e415731ff0a160d +- schema:digital-twin-editor-project +- modelResource / kind:imported +- modelResource / ID:imported-model\_mto6v5w6\_09-fox +- modelResource / 名称:09-Fox +- modelResource / assetCode:MODEL\_MTO6V5W6\_09-FOX +- modelResource / 编码:MODEL\_MTO6V5W6\_09-FOX +- modelResource / storageUri:fsvc://unreal-tran/model/2026/09/05/3fc69ae0d435f869afca1fcd943486d1.glb +- modelResource / sourceName:09-Fox.glb +- modelResource / sizeBytes:162852 +- modelResource / lastModified:0 +- modelResource / mimeType:model/gltf-binary +- modelResource / vertices:1728 +- modelResource / triangles:576 +- modelResource / 节点数:27 +- modelResource / 网格数:1 +- modelResource / 材质数:1 +- modelResource / 纹理数:1 +- modelResource / 动画:3 +- modelResource / animationDurationSeconds:3.4166667461395264 +- modelResource / modelMetadata / nodeCount:27 +- modelResource / modelMetadata / 网格数:1 +- modelResource / modelMetadata / materialCount:1 +- modelResource / modelMetadata / textureCount:1 +- modelResource / modelMetadata / 动画:3 项,完整内容见 evidence.json +- modelResource / modelMetadata / animationDurationSeconds:3.4166667461395264 +- 更多记录:见 evidence.json +- 更多记录:见 evidence.json + +### 现场截图 + +![GLB上传、两阶段绑定、SHA256与活跃模型核验](screenshots/2-01-imported.png) + +![节点 X 位置、材质粗糙度、原生动画选择保存](screenshots/2-02-edited.png) + +![整页刷新后模型、节点、材质、动画选择恢复](screenshots/2-03-reopened.png) + +![原生动画实播:播放时间与轮子/骨骼姿态确实变化](screenshots/2-04-animation.png) + +![发布到场景资源库并核对服务端发布版本](screenshots/2-05-published.png) + +![全新浏览器上下文从服务端载入已发布模型](screenshots/2-06-fresh-session.png) + +![已发布模型改名保存为 V2 草稿,项目及版本更新时间刷新](screenshots/2-07-update-time.png) + +![V2 重新发布成功,发布版本及更新时间正确](screenshots/2-08-published-v2.png) + +![V2 全新浏览器上下文重开,模型文件、动画选择、发布版本均正确](screenshots/2-09-fresh-session-v2.png) + +## 补充验证 + +### 最终项目列表 + +- 类别:final-list +- 状态:PASS +- 列表核验结果:MODEL-70875AA932B94685 · 整机装备实测模型-狐狸动画-20260905节点 27 · 材质 1 · 动画 1系统管理员更新:2026/09/05 17:33已发布进入编辑更多、MODEL-3FA24629D59E4509 · 整机装备实测模型-牛奶卡车-20260905节点 10 · 材质 5 · 动画 1系统管理员更新:2026/09/05 17:24已发布进入编辑更多 + +### 构建检查 + +- 类别:build +- 状态:PASS +- 执行命令:pnpm run build +- 详情:类型检查、Vite 构建、public/dist hash、API 桥接与凭据门禁均通过 + +### 实测范围 + +- 类别:scope +- 详情:通过实际页面操作创建/导入/编辑/播放/保存/发布;只读 API 与全新浏览器会话交叉核验。未创建场景,未执行训练业务蓝图,未改表结构或账号权限。 + +### 最终项目列表 + +- 类别:final-list +- 状态:PASS +- 详情:最终 V2 列表:狐狸 17:48 排在卡车 17:47 之前,最近更新排序与服务端保存、发布时间一致。 +- 列表核验结果:MODEL-70875AA932B94685 · 整机装备实测模型-狐狸动画-已验证-20260905节点 27 · 材质 1 · 动画 1系统管理员更新:2026/09/05 17:48已发布进入编辑更多、MODEL-3FA24629D59E4509 · 整机装备实测模型-牛奶卡车-已验证-20260905节点 10 · 材质 5 · 动画 1系统管理员更新:2026/09/05 17:47已发布进入编辑更多 + +### backend-regression + +- 类别:backend-regression +- 状态:PASS +- 执行命令:mvn -B -ntp -pl ut\_tran -Dtest=ContentProjectServiceTest test +- 详情:Java 17;70项用例通过,0失败/错误/跳过。新增用例先复现旧时间写回,再验证修复。 + +### build-final + +- 类别:build-final +- 状态:PASS +- 详情:最终 pnpm run build 通过;stage生成camera-fit统一LF后,10个payload的public/dist哈希、API桥接与凭据门禁通过,git diff --check通过。 +- 执行命令:pnpm run build + +### cover-display + +- 类别:cover-display +- 详情:两条测试数据未设置自定义封面,列表沿用现有默认装备缩略图;编辑器内已分别验证真实卡车与狐狸。若需要导入后自动生成模型封面,属于另行确认的功能增强。 + +## 补充截图 + +![补充证据](screenshots/00-two-published-models.png) + +![补充证据](screenshots/00b-two-published-models-v2.png) + +![模型编辑器生成包陈旧,页面实际运行本地模式](screenshots/01-editor-initialization.png) + +## 遗留数据与保留说明 + +| 项目 | ID | 编码 | 保留/清理结论 | +| --- | --- | --- | --- | +| 实测模型-牛奶卡车-已验证-20260905 | 156 | MODEL-3FA24629D59E4509 | 保留 | +| 实测模型-狐狸动画-已验证-20260905 | 157 | MODEL-70875AA932B94685 | 保留 | + +- 记录:保留本次创建的两条模型工程与上传资产,供用户继续测试。 + +本报告生成过程不修改项目数据。数据保留与清理结果以证据记录为准。 + +## 问题与待确认项 + +### 1 + +- 标题:模型编辑器生成包陈旧,页面实际运行本地模式 +- 状态:已修复并验证 +- impact:新建记录存在,但旧编辑器未读取项目 ID,模型编辑和自动保存未写入内容制作 API。 +- fix:从现有接口版源码重建并暂存编辑器包,增加 build 产物 API 桥接检查。 + +### 2 + +- 标题:GLB 上传被文件服务 503 阻断 +- 状态:已修复并验证 +- impact:上传未成功,原工程模型与资产仍保留。 +- requestId:69785305-558a-4a43-99bf-655b4adda274 +- cause:用户级 UT\_FILE\_SERVICE\_BASE\_URL / CONTENT\_BASE\_URL 残留关闭的 127.0.0.1:17180 代理地址 +- fix:恢复到现有配置的远端真实文件服务,保留密钥,仅重启 ut-tran;实际 GLB 上传已返回200 + +### 3 + +- 标题:列表“动画”统计口径需确认 +- 状态:待确认,未改功能 +- impact:狐狸实际有 Survey、Walk、Run 3 个原生片段,全部实播通过;列表显示动画1,统计的是1条自编时间轴轨道。 +- suggestion:可将列表文案明确为“动画轨道”,或增加“原生动画3段 / 自编轨道1条”的分项展示,待用户确认后实施。 + +### 4 + +- 标题:保存和发布没有刷新项目/版本更新时间 +- 状态:已修复并验证 +- cause:读取实体携带旧 updateTime,updateById 再次写回旧值,数据库自动更新时间未生效。 +- fix:项目、版本两个统一更新方法显式设置当前秒精度时间;无表结构变更。 +- verification:两模型改名生成 V2 草稿并重新发布;API时间、页面时间、最近更新排序和全新浏览器重开均通过。 + +共 23 张可用截图。完整结构化记录见 evidence.json;模型对象明细未展开。 diff --git a/reports/model-live-20260905/screenshots/00-two-published-models.png b/reports/model-live-20260905/screenshots/00-two-published-models.png new file mode 100644 index 0000000..cbf964d Binary files /dev/null and b/reports/model-live-20260905/screenshots/00-two-published-models.png differ diff --git a/reports/model-live-20260905/screenshots/00b-two-published-models-v2.png b/reports/model-live-20260905/screenshots/00b-two-published-models-v2.png new file mode 100644 index 0000000..9fb0295 Binary files /dev/null and b/reports/model-live-20260905/screenshots/00b-two-published-models-v2.png differ diff --git a/reports/model-live-20260905/screenshots/01-editor-initialization.png b/reports/model-live-20260905/screenshots/01-editor-initialization.png new file mode 100644 index 0000000..40c5c9b Binary files /dev/null and b/reports/model-live-20260905/screenshots/01-editor-initialization.png differ diff --git a/reports/model-live-20260905/screenshots/02-after-build-state.png b/reports/model-live-20260905/screenshots/02-after-build-state.png new file mode 100644 index 0000000..493b228 Binary files /dev/null and b/reports/model-live-20260905/screenshots/02-after-build-state.png differ diff --git a/reports/model-live-20260905/screenshots/03-upload-service-error.png b/reports/model-live-20260905/screenshots/03-upload-service-error.png new file mode 100644 index 0000000..4e4a244 Binary files /dev/null and b/reports/model-live-20260905/screenshots/03-upload-service-error.png differ diff --git a/reports/model-live-20260905/screenshots/03b-upload-error-log.png b/reports/model-live-20260905/screenshots/03b-upload-error-log.png new file mode 100644 index 0000000..b2f4a09 Binary files /dev/null and b/reports/model-live-20260905/screenshots/03b-upload-error-log.png differ diff --git a/reports/model-live-20260905/screenshots/1-01-imported.png b/reports/model-live-20260905/screenshots/1-01-imported.png new file mode 100644 index 0000000..2ac5d87 Binary files /dev/null and b/reports/model-live-20260905/screenshots/1-01-imported.png differ diff --git a/reports/model-live-20260905/screenshots/1-02-edited.png b/reports/model-live-20260905/screenshots/1-02-edited.png new file mode 100644 index 0000000..da67802 Binary files /dev/null and b/reports/model-live-20260905/screenshots/1-02-edited.png differ diff --git a/reports/model-live-20260905/screenshots/1-03-reopened.png b/reports/model-live-20260905/screenshots/1-03-reopened.png new file mode 100644 index 0000000..6df5d1e Binary files /dev/null and b/reports/model-live-20260905/screenshots/1-03-reopened.png differ diff --git a/reports/model-live-20260905/screenshots/1-04-animation.png b/reports/model-live-20260905/screenshots/1-04-animation.png new file mode 100644 index 0000000..9a9720d Binary files /dev/null and b/reports/model-live-20260905/screenshots/1-04-animation.png differ diff --git a/reports/model-live-20260905/screenshots/1-04b-material-reopened.png b/reports/model-live-20260905/screenshots/1-04b-material-reopened.png new file mode 100644 index 0000000..70a23a1 Binary files /dev/null and b/reports/model-live-20260905/screenshots/1-04b-material-reopened.png differ diff --git a/reports/model-live-20260905/screenshots/1-05-published.png b/reports/model-live-20260905/screenshots/1-05-published.png new file mode 100644 index 0000000..bcc71df Binary files /dev/null and b/reports/model-live-20260905/screenshots/1-05-published.png differ diff --git a/reports/model-live-20260905/screenshots/1-06-fresh-session.png b/reports/model-live-20260905/screenshots/1-06-fresh-session.png new file mode 100644 index 0000000..c279c1b Binary files /dev/null and b/reports/model-live-20260905/screenshots/1-06-fresh-session.png differ diff --git a/reports/model-live-20260905/screenshots/1-07-update-time.png b/reports/model-live-20260905/screenshots/1-07-update-time.png new file mode 100644 index 0000000..e3453a2 Binary files /dev/null and b/reports/model-live-20260905/screenshots/1-07-update-time.png differ diff --git a/reports/model-live-20260905/screenshots/1-08-published-v2.png b/reports/model-live-20260905/screenshots/1-08-published-v2.png new file mode 100644 index 0000000..3a2646f Binary files /dev/null and b/reports/model-live-20260905/screenshots/1-08-published-v2.png differ diff --git a/reports/model-live-20260905/screenshots/1-09-fresh-session-v2.png b/reports/model-live-20260905/screenshots/1-09-fresh-session-v2.png new file mode 100644 index 0000000..21b0e43 Binary files /dev/null and b/reports/model-live-20260905/screenshots/1-09-fresh-session-v2.png differ diff --git a/reports/model-live-20260905/screenshots/2-01-imported.png b/reports/model-live-20260905/screenshots/2-01-imported.png new file mode 100644 index 0000000..9a81409 Binary files /dev/null and b/reports/model-live-20260905/screenshots/2-01-imported.png differ diff --git a/reports/model-live-20260905/screenshots/2-02-edited.png b/reports/model-live-20260905/screenshots/2-02-edited.png new file mode 100644 index 0000000..d686417 Binary files /dev/null and b/reports/model-live-20260905/screenshots/2-02-edited.png differ diff --git a/reports/model-live-20260905/screenshots/2-03-reopened.png b/reports/model-live-20260905/screenshots/2-03-reopened.png new file mode 100644 index 0000000..d7e8ef8 Binary files /dev/null and b/reports/model-live-20260905/screenshots/2-03-reopened.png differ diff --git a/reports/model-live-20260905/screenshots/2-04-animation.png b/reports/model-live-20260905/screenshots/2-04-animation.png new file mode 100644 index 0000000..6ae3153 Binary files /dev/null and b/reports/model-live-20260905/screenshots/2-04-animation.png differ diff --git a/reports/model-live-20260905/screenshots/2-05-published.png b/reports/model-live-20260905/screenshots/2-05-published.png new file mode 100644 index 0000000..42e03be Binary files /dev/null and b/reports/model-live-20260905/screenshots/2-05-published.png differ diff --git a/reports/model-live-20260905/screenshots/2-06-fresh-session.png b/reports/model-live-20260905/screenshots/2-06-fresh-session.png new file mode 100644 index 0000000..73b8aae Binary files /dev/null and b/reports/model-live-20260905/screenshots/2-06-fresh-session.png differ diff --git a/reports/model-live-20260905/screenshots/2-07-update-time.png b/reports/model-live-20260905/screenshots/2-07-update-time.png new file mode 100644 index 0000000..aa7b401 Binary files /dev/null and b/reports/model-live-20260905/screenshots/2-07-update-time.png differ diff --git a/reports/model-live-20260905/screenshots/2-08-published-v2.png b/reports/model-live-20260905/screenshots/2-08-published-v2.png new file mode 100644 index 0000000..9444317 Binary files /dev/null and b/reports/model-live-20260905/screenshots/2-08-published-v2.png differ diff --git a/reports/model-live-20260905/screenshots/2-09-fresh-session-v2.png b/reports/model-live-20260905/screenshots/2-09-fresh-session-v2.png new file mode 100644 index 0000000..e1315a3 Binary files /dev/null and b/reports/model-live-20260905/screenshots/2-09-fresh-session-v2.png differ diff --git a/reports/scene-live-20260905/evidence.json b/reports/scene-live-20260905/evidence.json new file mode 100644 index 0000000..3eabdab --- /dev/null +++ b/reports/scene-live-20260905/evidence.json @@ -0,0 +1,293 @@ +{ + "date": "2026-09-05", + "baseURL": "http://127.0.0.1:6180", + "browser": "Microsoft Edge", + "role": "教员", + "correction": { + "title": "狐狸场景验证更正:撤回原完整通过结论", + "summary": "用户指出狐狸没有出现在场景中,经复现确认属实。原报告的 7/7 仅证明引用、保存、封面上传和发布等链路,漏掉了模型真正可见的视觉检查,因此撤回原“完整 E2E 通过”结论。下列修复后证据增加了真实画面和像素差异验证。", + "previousConclusion": "原狐狸检查把对象树存在 fox、模型依赖有效以及接口返回成功当作模型已加载可见;旧截图实际没有显示狐狸。两项旧狐狸证据标记为已更正历史记录并移出当前通过率,原文件继续保留用于追溯。", + "rootCauses": [ + "计算蒙皮模型包围盒前没有同步骨骼矩阵,得到失真的尺寸。", + "适配场景尺寸时使用 setScalar 覆盖模型已有的归一化缩放;两者叠加将狐狸放大到约 1000 个场景单位,使模型超出视锥。" + ], + "fixes": [ + "同步蒙皮矩阵后计算真实包围盒,并保留已有归一化缩放进行相对缩放;新导入模型与已保存模型均使用修正后的尺寸处理。", + "修复场景 160 的狐狸比例和默认镜头,保存并发布为版本 208;重新生成服务器 JPEG 封面资产 2084。狐狸包围盒约为 0.966 × 2.812 × 6 个场景单位。", + "同样复核并修正场景 159,保存并发布为版本 209,重新生成服务器 JPEG 封面资产 2087。未修改模型发布版本或数据库表结构。" + ], + "verification": [ + "真实 UI 从资源库新增狐狸后立即可见,最长边为 6;该新增操作仅在隔离浏览器会话中测试,未保存、无写请求。", + "两个场景修改、保存、发布后,通过独立新浏览器会话重新打开,使用保存的默认镜头验证;没有未完成模型加载,也没有产生写请求。", + "关闭模型投影后,对同一画面中模型显示与隐藏的像素进行比较:320 × 180 采样中狐狸改变 4472 像素、牛奶卡车改变 7515 像素,均超过 500 像素阈值。截图中可直接辨认狐狸与卡车。", + "牛奶卡车默认镜头下部分车身被场景立柱遮挡,但模型确实可见;报告保留这一限制。", + "最终列表显示狐狸在卡车之前,虽然卡车更新于 19:32、狐狸更新于 19:31,确认排序依据仍为创建时间。" + ], + "screenshots": [ + { + "path": "screenshots/26-fox-visual-regression.png", + "caption": "修复后独立浏览器重新打开场景 160:狐狸模型清晰可见,并完成像素差异验证。" + } + ] + }, + "evidence": [ + { + "title": "创建牛奶卡车检验区场景", + "status": "PASS", + "checks": [ + "通过列表新建并进入真实场景编辑器", + "首次加载认证服务短暂503,点击重新加载后成功;原创建记录159复用" + ], + "screenshot": "screenshots/03-truck-created-ready.png" + }, + { + "title": "牛奶卡车场景保存并回读封面", + "status": "PASS", + "checks": [ + "场景资源库双击引用模型 156 的已发布版本 204", + "编辑对象坐标与设备绑定后,未保存状态 2.5 秒内无上传或项目写入", + "保存草稿发出 SCENE_COVER JPEG 上传与同一次项目 PUT", + "认证访问 /cover 返回 JPEG,封面尺寸 640×408,列表可用的 coverUri 已写入" + ], + "screenshots": [ + "screenshots/05-truck-model-imported.png", + "screenshots/06-truck-transformed-unsaved.png", + "screenshots/07-truck-scene-cover.png", + "screenshots/08-truck-saved-with-cover.png" + ] + }, + { + "title": "牛奶卡车场景刷新恢复并发布", + "status": "PASS", + "checks": [ + "整页刷新后模型 156/版本 204、对象名称、X=4.2 和设备编号均恢复", + "发布前校验 8 项全部通过", + "发布动作先成功保存再成功发布,最终状态为 PUBLISHED" + ], + "screenshots": [ + "screenshots/09-truck-reloaded-persisted.png", + "screenshots/10-truck-published.png" + ], + "details": { + "total": 8, + "warnings": 0, + "text": "✓\n场景环境已配置\n真实装备车库\n✓\n模型资源加载完成\n全部受控模型已就绪\n✓\n场景用途配置有效\n1 个实训装备\n✓\n对象设备编号完整\n用于接收物理设备和消息事件\n✓\n物模型绑定完整\n用于训练步骤和动作映射\n✓\n设备编号不重复\n设备编号唯一\n✓\n物模型编号不重复\n物模型编号唯一\n✓\n受控资源引用正常\n2 个导入模型可跨刷新恢复" + } + }, + { + "title": "狐狸野外场景保存并锁定已发布模型版本", + "status": "PASS", + "superseded": true, + "checks": [ + "切换到真实野外训练场模板并导入模型 157", + "模型 157 当前草稿版本为 202,但场景严格依赖其已发布版本 201", + "保存草稿上传 SCENE_COVER JPEG,并在同次项目 PUT 写入 content、依赖和 coverUri", + "认证回读 /cover 返回 JPEG,尺寸 640×408" + ], + "screenshots": [ + "screenshots/12-fox-outdoor-template.png", + "screenshots/13-fox-model-imported.png", + "screenshots/14-fox-scene-cover.png", + "screenshots/15-fox-saved-with-cover.png" + ] + }, + { + "title": "场景封面上传失败保留原封面", + "status": "PASS", + "checks": [ + "对 SCENE_COVER 上传实施浏览器网络故障注入", + "保存请求仍成功,场景内容继续提交", + "coverUri 保持为保存前的旧值,未产生空封面或错误替换" + ], + "screenshot": "screenshots/16-fox-cover-upload-failed-content-saved.png", + "details": { + "sceneId": "160", + "oldCoverUri": "fsvc://unreal-tran/image/2026/09/05/bb1e8717cd2e7ba6ca10f16b817b1ec5.jpg", + "putRequests": 1 + } + }, + { + "title": "狐狸野外场景刷新恢复并发布", + "status": "PASS", + "superseded": true, + "checks": [ + "整页刷新后狐狸模型依赖仍为项目 157 的已发布版本 201", + "封面上传失败后的场景正文编辑 X=-7.5 已恢复", + "8 项发布校验全部通过,发布时重新保存并成功发布", + "发布后的 coverUri 有效;保存前封面与发布后封面均由当前场景视图生成" + ], + "screenshots": [ + "screenshots/17-fox-reloaded-persisted.png", + "screenshots/18-fox-published.png" + ], + "details": { + "validation": { + "total": 8, + "warnings": 0, + "text": "✓\n场景环境已配置\n真实野外训练场\n✓\n模型资源加载完成\n全部受控模型已就绪\n✓\n场景用途配置有效\n3 个实训装备\n✓\n对象设备编号完整\n用于接收物理设备和消息事件\n✓\n物模型绑定完整\n用于训练步骤和动作映射\n✓\n设备编号不重复\n设备编号唯一\n✓\n物模型编号不重复\n物模型编号唯一\n✓\n受控资源引用正常\n2 个导入模型可跨刷新恢复" + }, + "coverBeforePublish": "fsvc://unreal-tran/image/2026/09/05/bb1e8717cd2e7ba6ca10f16b817b1ec5.jpg", + "coverAfterPublish": "fsvc://unreal-tran/image/2026/09/05/62e5d4a05316badb631e252f44ecbec3.jpg" + } + }, + { + "title": "场景列表创建时间倒序与封面展示", + "status": "PASS", + "checks": [ + "列表请求默认携带 sort=CREATED_DESC", + "较晚创建的狐狸野外场景显示在较早创建的牛奶卡车场景之前", + "卡车于 19:32 更新,晚于狐狸的 19:31,但狐狸仍排在卡车之前,证实没有按更新时间倒序", + "两条场景均通过受控 /cover 接口展示修复后服务器 JPEG 封面;列表中可辨认狐狸和卡车" + ], + "screenshot": "screenshots/28-scene-list-fixed.png", + "details": { + "foxIndex": 0, + "truckIndex": 1, + "rows": [ + { "name": "狐狸野外场景", "projectId": "160", "addTime": 1788605625, "updateTime": "2026-09-05T19:31:30", "imageIsBlob": true }, + { "name": "牛奶卡车场景", "projectId": "159", "addTime": 1788603808, "updateTime": "2026-09-05T19:32:28", "imageIsBlob": true } + ] + } + }, + { + "title": "修复后狐狸新增导入、保存发布与刷新可见性", + "status": "PASS", + "checks": [ + "从真实 UI 资源库新增模型 157 / 已发布版本 201,默认缩放约 0.0361637593,包围盒约 0.966 × 2.812 × 6,狐狸在视口中可见;该临时新增未保存、无写请求", + "场景 160 原狐狸修复尺寸和镜头后,保存并发布为版本 208;服务器封面资产 2084 为真实 JPEG,640 × 408,45706 字节", + "独立 Edge / Playwright 新会话按保存的镜头重新打开场景,狐狸网格已加载且可见,pendingLoads=0", + "显示/隐藏狐狸前后进行像素对比,禁用模型投影排除仅阴影可见:320 × 180 采样改变 4472 像素(7.764%),超过 500 像素阈值", + "实际检查发布截图、独立刷新截图及服务器 JPEG,均可辨认狐狸;模型 157 草稿 202 仍为 DRAFT,已发布版本仍为 201" + ], + "screenshots": [ + { "path": "screenshots/25-fox-fresh-import-visible.png", "caption": "真实 UI 新增狐狸后尺寸正常且可见;临时测试未保存。" }, + { "path": "screenshots/21-fox-corrected-published.png", "caption": "场景 160 修复后保存发布为版本 208。" }, + { "path": "screenshots/22-fox-final-cover.jpg", "caption": "从服务器回读的最终狐狸 JPEG 封面,资产 2084。" }, + { "path": "screenshots/26-fox-visual-regression.png", "caption": "独立浏览器重新打开后狐狸可见;像素差异 4472。" } + ], + "details": { + "sceneId": "160", + "currentVersionId": "208", + "publishedVersionId": "208", + "modelProjectId": "157", + "modelVersionId": "201", + "newImportWriteRequests": [], + "visibilityEvidence": "visibility-evidence.json", + "changedPixels": 4472, + "changedPercentage": 7.764, + "pendingLoads": 0, + "boundsSize": [0.9658796100519353, 2.811899945787403, 6] + } + }, + { + "title": "修复后牛奶卡车保存发布与刷新可见性", + "status": "PASS", + "checks": [ + "场景 159 保持模型 156 / 已发布版本 204,修复比例和镜头后保存并发布为版本 209", + "独立 Edge / Playwright 新会话重新打开场景,按保存镜头确认卡车 5 个网格均可见、pendingLoads=0", + "显示/隐藏卡车前后对比,禁用模型投影:320 × 180 采样改变 7515 像素(13.047%),超过 500 像素阈值", + "服务器回读最终封面资产 2087 为真实 JPEG,640 × 408,32937 字节;封面及刷新截图可辨认卡车", + "默认镜头部分车身被立柱遮挡,属于本次可见画面的已知限制" + ], + "screenshots": [ + { "path": "screenshots/23-truck-corrected-published.png", "caption": "场景 159 修复后保存发布为版本 209。" }, + { "path": "screenshots/24-truck-final-cover.jpg", "caption": "从服务器回读的最终卡车 JPEG 封面,资产 2087;部分车身被立柱遮挡。" }, + { "path": "screenshots/27-truck-visual-regression.png", "caption": "独立浏览器重新打开后卡车可见;像素差异 7515。" } + ], + "details": { + "sceneId": "159", + "currentVersionId": "209", + "publishedVersionId": "209", + "modelProjectId": "156", + "modelVersionId": "204", + "visibilityEvidence": "visibility-evidence.json", + "changedPixels": 7515, + "changedPercentage": 13.047, + "pendingLoads": 0, + "boundsSize": [3.4406057210321332, 3.390913184034896, 6.000000000000001] + } + } + ], + "projects": [ + { + "id": "159", + "name": "实测场景-牛奶卡车检验区-20260905", + "modelId": "156", + "modelVersionId": "204", + "finalStatus": "PUBLISHED", + "finalVersionId": "209", + "cover": { + "image": "screenshots/24-truck-final-cover.jpg", + "width": 640, + "height": 408, + "sizeBytes": 32937, + "assetId": "2087", + "versionId": "209", + "mimeType": "image/jpeg", + "sha256": "e103a473b74f3809365890296180c42f6c37a8005f2fd4c27fb64c437c245786", + "storageUri": "fsvc://unreal-tran/image/2026/09/05/d29810b273d75e43dff07622424f333f.jpg" + } + }, + { + "id": "160", + "name": "实测场景-狐狸野外训练区-20260905", + "modelId": "157", + "modelVersionId": "201", + "finalStatus": "PUBLISHED", + "finalVersionId": "208", + "cover": { + "image": "screenshots/22-fox-final-cover.jpg", + "width": 640, + "height": 408, + "sizeBytes": 45706, + "assetId": "2084", + "versionId": "208", + "mimeType": "image/jpeg", + "sha256": "1b6e4d1eb6e65ccc15ba820a8ae4bd40ab1bee900cf91d4ec3db9af82153618d", + "storageUri": "fsvc://unreal-tran/image/2026/09/05/c176d359087fc9bea4235e43dd43a691.jpg" + } + } + ], + "finalListScreenshot": "screenshots/28-scene-list-fixed.png", + "issues": [ + { + "title": "狐狸存在于对象树但不在真实视口中显示", + "status": "FIXED_AND_VISUALLY_VERIFIED", + "details": "原完整 E2E 通过结论已撤回。同步蒙皮矩阵并保留归一化缩放,修复场景数据和镜头后,新增导入、保存发布、独立刷新与像素可见性均通过;详见更正区。" + } + ], + "limitations": [ + "牛奶卡车场景保存的默认镜头中,车身部分被场景立柱遮挡;真实网格可见且像素差异验证通过。需要观察完整车身时可旋转镜头。" + ], + "followUpIssues": [ + { + "scope": "independent", + "title": "fsvc 新资产上传票据绑定校验", + "details": "既存流程的 fsvc URI 分支未完整覆盖上传票据绑定校验;本次未扩大修改范围,应单独补齐并验证历史资产、版本复制与引用兼容性。" + } + ], + "commands": [ + { + "command": "pnpm run build", + "status": "PASS", + "details": "前端生产构建及遗留模型编辑器产物校验通过。" + }, + { + "command": "node --test tools/scene-cover-api.test.mjs tools/scene-cover-capture.test.mjs tools/scene-model-placement.test.mjs", + "status": "PASS", + "details": "33 / 33 通过:封面同次 PUT、异常回退、并发队列、项目切换、截图尺寸、渲染状态恢复,以及蒙皮模型包围盒与归一化缩放回归。" + }, + { + "command": "原 Microsoft Edge 场景链路 E2E(更正说明)", + "status": "SUPERSEDED", + "details": "原 7/7 只覆盖模型引用、保存、封面上传和发布等链路,未证明狐狸真实可见;完整通过结论已撤回,当前视觉验证见下列独立浏览器 E2E。" + }, + { + "command": "node tools/scene-model-visibility.e2e.mjs", + "status": "PASS", + "details": "独立 Edge / Playwright 会话重开 160/208 与 159/209,使用保存镜头,显示/隐藏模型并禁用投影进行像素比较;狐狸 4472 像素、卡车 7515 像素,均超过 500 阈值。证据保存在 visibility-evidence.json,截图 26 / 27;无写请求。" + } + ], + "retainedData": "保留开发环境场景 159(牛奶卡车检验区,PUBLISHED,当前及已发布版本 209,模型 156 / 已发布版本 204)和场景 160(狐狸野外训练区,PUBLISHED,当前及已发布版本 208,模型 157 / 已发布版本 201)。模型原发布版本未修改;模型 157 的当前草稿版本 202 继续保留,未发布或修改。本次无需 DDL 变更。", + "cleanup": "保留两条真实场景及历史截图用于后续测试和追溯。新增导入狐狸仅在隔离浏览器会话中测试,未保存、无写请求;测试结束后丢弃临时对象。" +} diff --git a/reports/scene-live-20260905/index.html b/reports/scene-live-20260905/index.html new file mode 100644 index 0000000..05d10b1 --- /dev/null +++ b/reports/scene-live-20260905/index.html @@ -0,0 +1,157 @@ + + +真实场景与截图封面验证报告 · 2026-09-05 +
+
SCENE LIVE · 功能已实施

真实场景与截图封面验证报告

场景保存截图封面及列表按创建时间倒序的功能已实施。本报告记录使用现有模型创建真实场景、保存当前三维视口封面及异常回退的实际验证结果。

2026-09-05 · http://127.0.0.1:6180 · Microsoft Edge · 教员

Markdown 报告
+

狐狸场景验证更正:撤回原完整通过结论

用户指出狐狸没有出现在场景中,经复现确认属实。原报告的 7/7 仅证明引用、保存、封面上传和发布等链路,漏掉了模型真正可见的视觉检查,因此撤回原“完整 E2E 通过”结论。下列修复后证据增加了真实画面和像素差异验证。

原结论与漏验

根因

修复内容

修复后验证

修复后独立浏览器重新打开场景 160:狐狸模型清晰可见,并完成像素差异验证。
修复后独立浏览器重新打开场景 160:狐狸模型清晰可见,并完成像素差异验证。 · 点击查看原图

下方标为“历史记录(已更正)”的检查及截图保留用于追溯,不计入当前通过率,也不作为狐狸已经可见的证据。

+
7 / 7当前证据项通过
0失败
0其他或未标注
2已更正历史记录
22图片文件已校验
+

保留场景与封面证据

实测场景-牛奶卡车检验区-20260905

场景 159 保存后封面回读证据
场景 159 保存后封面回读证据 · 点击查看原图
场景 / 状态
159 / PUBLISHED
当前工程版本
209
引用模型 / 版本
156 / 204
封面大小
32937 字节 · 640 × 408
封面持久化与项目证据
{
+  "id": "159",
+  "name": "实测场景-牛奶卡车检验区-20260905",
+  "modelId": "156",
+  "modelVersionId": "204",
+  "finalStatus": "PUBLISHED",
+  "finalVersionId": "209",
+  "cover": {
+    "image": "screenshots/24-truck-final-cover.jpg",
+    "width": 640,
+    "height": 408,
+    "sizeBytes": 32937,
+    "assetId": "2087",
+    "versionId": "209",
+    "mimeType": "image/jpeg",
+    "sha256": "e103a473b74f3809365890296180c42f6c37a8005f2fd4c27fb64c437c245786",
+    "storageUri": "fsvc://unreal-tran/image/2026/09/05/d29810b273d75e43dff07622424f333f.jpg"
+  }
+}

实测场景-狐狸野外训练区-20260905

场景 160 保存后封面回读证据
场景 160 保存后封面回读证据 · 点击查看原图
场景 / 状态
160 / PUBLISHED
当前工程版本
208
引用模型 / 版本
157 / 201
封面大小
45706 字节 · 640 × 408
封面持久化与项目证据
{
+  "id": "160",
+  "name": "实测场景-狐狸野外训练区-20260905",
+  "modelId": "157",
+  "modelVersionId": "201",
+  "finalStatus": "PUBLISHED",
+  "finalVersionId": "208",
+  "cover": {
+    "image": "screenshots/22-fox-final-cover.jpg",
+    "width": 640,
+    "height": 408,
+    "sizeBytes": 45706,
+    "assetId": "2084",
+    "versionId": "208",
+    "mimeType": "image/jpeg",
+    "sha256": "1b6e4d1eb6e65ccc15ba820a8ae4bd40ab1bee900cf91d4ec3db9af82153618d",
+    "storageUri": "fsvc://unreal-tran/image/2026/09/05/c176d359087fc9bea4235e43dd43a691.jpg"
+  }
+}
+

最终列表与创建时间倒序

保留场景的实际封面与创建时间倒序列表
保留场景的实际封面与创建时间倒序列表 · 点击查看原图
+

逐项验证记录

通过数仅统计未被更正且 status 明确为 PASS 的当前证据项;历史记录单独标注。checks 用于展示实际断言,不重复累加。故障注入中的预期错误响应不等于用例失败;缺少状态时不推断通过。图片文件存在校验不等于视觉内容验证。

1. 创建牛奶卡车检验区场景

PASS
  • 通过列表新建并进入真实场景编辑器
  • 首次加载认证服务短暂503,点击重新加载后成功;原创建记录159复用
浏览器现场
浏览器现场 · 点击查看原图

2. 牛奶卡车场景保存并回读封面

PASS
  • 场景资源库双击引用模型 156 的已发布版本 204
  • 编辑对象坐标与设备绑定后,未保存状态 2.5 秒内无上传或项目写入
  • 保存草稿发出 SCENE_COVER JPEG 上传与同一次项目 PUT
  • 认证访问 /cover 返回 JPEG,封面尺寸 640×408,列表可用的 coverUri 已写入
浏览器现场
浏览器现场 · 点击查看原图
浏览器现场
浏览器现场 · 点击查看原图
浏览器现场
浏览器现场 · 点击查看原图
浏览器现场
浏览器现场 · 点击查看原图

3. 牛奶卡车场景刷新恢复并发布

PASS
  • 整页刷新后模型 156/版本 204、对象名称、X=4.2 和设备编号均恢复
  • 发布前校验 8 项全部通过
  • 发布动作先成功保存再成功发布,最终状态为 PUBLISHED
检查详情
{
+  "details": {
+    "total": 8,
+    "warnings": 0,
+    "text": "✓\n场景环境已配置\n真实装备车库\n✓\n模型资源加载完成\n全部受控模型已就绪\n✓\n场景用途配置有效\n1 个实训装备\n✓\n对象设备编号完整\n用于接收物理设备和消息事件\n✓\n物模型绑定完整\n用于训练步骤和动作映射\n✓\n设备编号不重复\n设备编号唯一\n✓\n物模型编号不重复\n物模型编号唯一\n✓\n受控资源引用正常\n2 个导入模型可跨刷新恢复"
+  }
+}
浏览器现场
浏览器现场 · 点击查看原图
浏览器现场
浏览器现场 · 点击查看原图

4. 狐狸野外场景保存并锁定已发布模型版本

历史记录(已更正)
  • 切换到真实野外训练场模板并导入模型 157
  • 模型 157 当前草稿版本为 202,但场景严格依赖其已发布版本 201
  • 保存草稿上传 SCENE_COVER JPEG,并在同次项目 PUT 写入 content、依赖和 coverUri
  • 认证回读 /cover 返回 JPEG,尺寸 640×408
检查详情
{
+  "superseded": true
+}
历史截图(不作为修复后的视觉通过证据):原测试现场
历史截图(不作为修复后的视觉通过证据):原测试现场 · 点击查看原图
历史截图(不作为修复后的视觉通过证据):原测试现场
历史截图(不作为修复后的视觉通过证据):原测试现场 · 点击查看原图
历史截图(不作为修复后的视觉通过证据):原测试现场
历史截图(不作为修复后的视觉通过证据):原测试现场 · 点击查看原图
历史截图(不作为修复后的视觉通过证据):原测试现场
历史截图(不作为修复后的视觉通过证据):原测试现场 · 点击查看原图

5. 场景封面上传失败保留原封面

PASS
  • 对 SCENE_COVER 上传实施浏览器网络故障注入
  • 保存请求仍成功,场景内容继续提交
  • coverUri 保持为保存前的旧值,未产生空封面或错误替换
检查详情
{
+  "details": {
+    "sceneId": "160",
+    "oldCoverUri": "fsvc://unreal-tran/image/2026/09/05/bb1e8717cd2e7ba6ca10f16b817b1ec5.jpg",
+    "putRequests": 1
+  }
+}
浏览器现场
浏览器现场 · 点击查看原图

6. 狐狸野外场景刷新恢复并发布

历史记录(已更正)
  • 整页刷新后狐狸模型依赖仍为项目 157 的已发布版本 201
  • 封面上传失败后的场景正文编辑 X=-7.5 已恢复
  • 8 项发布校验全部通过,发布时重新保存并成功发布
  • 发布后的 coverUri 有效;保存前封面与发布后封面均由当前场景视图生成
检查详情
{
+  "superseded": true,
+  "details": {
+    "validation": {
+      "total": 8,
+      "warnings": 0,
+      "text": "✓\n场景环境已配置\n真实野外训练场\n✓\n模型资源加载完成\n全部受控模型已就绪\n✓\n场景用途配置有效\n3 个实训装备\n✓\n对象设备编号完整\n用于接收物理设备和消息事件\n✓\n物模型绑定完整\n用于训练步骤和动作映射\n✓\n设备编号不重复\n设备编号唯一\n✓\n物模型编号不重复\n物模型编号唯一\n✓\n受控资源引用正常\n2 个导入模型可跨刷新恢复"
+    },
+    "coverBeforePublish": "fsvc://unreal-tran/image/2026/09/05/bb1e8717cd2e7ba6ca10f16b817b1ec5.jpg",
+    "coverAfterPublish": "fsvc://unreal-tran/image/2026/09/05/62e5d4a05316badb631e252f44ecbec3.jpg"
+  }
+}
历史截图(不作为修复后的视觉通过证据):原测试现场
历史截图(不作为修复后的视觉通过证据):原测试现场 · 点击查看原图
历史截图(不作为修复后的视觉通过证据):原测试现场
历史截图(不作为修复后的视觉通过证据):原测试现场 · 点击查看原图

7. 场景列表创建时间倒序与封面展示

PASS
  • 列表请求默认携带 sort=CREATED_DESC
  • 较晚创建的狐狸野外场景显示在较早创建的牛奶卡车场景之前
  • 卡车于 19:32 更新,晚于狐狸的 19:31,但狐狸仍排在卡车之前,证实没有按更新时间倒序
  • 两条场景均通过受控 /cover 接口展示修复后服务器 JPEG 封面;列表中可辨认狐狸和卡车
检查详情
{
+  "details": {
+    "foxIndex": 0,
+    "truckIndex": 1,
+    "rows": [
+      {
+        "name": "狐狸野外场景",
+        "projectId": "160",
+        "addTime": 1788605625,
+        "updateTime": "2026-09-05T19:31:30",
+        "imageIsBlob": true
+      },
+      {
+        "name": "牛奶卡车场景",
+        "projectId": "159",
+        "addTime": 1788603808,
+        "updateTime": "2026-09-05T19:32:28",
+        "imageIsBlob": true
+      }
+    ]
+  }
+}
浏览器现场
浏览器现场 · 点击查看原图

8. 修复后狐狸新增导入、保存发布与刷新可见性

PASS
  • 从真实 UI 资源库新增模型 157 / 已发布版本 201,默认缩放约 0.0361637593,包围盒约 0.966 × 2.812 × 6,狐狸在视口中可见;该临时新增未保存、无写请求
  • 场景 160 原狐狸修复尺寸和镜头后,保存并发布为版本 208;服务器封面资产 2084 为真实 JPEG,640 × 408,45706 字节
  • 独立 Edge / Playwright 新会话按保存的镜头重新打开场景,狐狸网格已加载且可见,pendingLoads=0
  • 显示/隐藏狐狸前后进行像素对比,禁用模型投影排除仅阴影可见:320 × 180 采样改变 4472 像素(7.764%),超过 500 像素阈值
  • 实际检查发布截图、独立刷新截图及服务器 JPEG,均可辨认狐狸;模型 157 草稿 202 仍为 DRAFT,已发布版本仍为 201
检查详情
{
+  "details": {
+    "sceneId": "160",
+    "currentVersionId": "208",
+    "publishedVersionId": "208",
+    "modelProjectId": "157",
+    "modelVersionId": "201",
+    "newImportWriteRequests": [],
+    "visibilityEvidence": "visibility-evidence.json",
+    "changedPixels": 4472,
+    "changedPercentage": 7.764,
+    "pendingLoads": 0,
+    "boundsSize": [
+      0.9658796100519353,
+      2.811899945787403,
+      6
+    ]
+  }
+}
真实 UI 新增狐狸后尺寸正常且可见;临时测试未保存。
真实 UI 新增狐狸后尺寸正常且可见;临时测试未保存。 · 点击查看原图
场景 160 修复后保存发布为版本 208。
场景 160 修复后保存发布为版本 208。 · 点击查看原图
从服务器回读的最终狐狸 JPEG 封面,资产 2084。
从服务器回读的最终狐狸 JPEG 封面,资产 2084。 · 点击查看原图
独立浏览器重新打开后狐狸可见;像素差异 4472。
独立浏览器重新打开后狐狸可见;像素差异 4472。 · 点击查看原图

9. 修复后牛奶卡车保存发布与刷新可见性

PASS
  • 场景 159 保持模型 156 / 已发布版本 204,修复比例和镜头后保存并发布为版本 209
  • 独立 Edge / Playwright 新会话重新打开场景,按保存镜头确认卡车 5 个网格均可见、pendingLoads=0
  • 显示/隐藏卡车前后对比,禁用模型投影:320 × 180 采样改变 7515 像素(13.047%),超过 500 像素阈值
  • 服务器回读最终封面资产 2087 为真实 JPEG,640 × 408,32937 字节;封面及刷新截图可辨认卡车
  • 默认镜头部分车身被立柱遮挡,属于本次可见画面的已知限制
检查详情
{
+  "details": {
+    "sceneId": "159",
+    "currentVersionId": "209",
+    "publishedVersionId": "209",
+    "modelProjectId": "156",
+    "modelVersionId": "204",
+    "visibilityEvidence": "visibility-evidence.json",
+    "changedPixels": 7515,
+    "changedPercentage": 13.047,
+    "pendingLoads": 0,
+    "boundsSize": [
+      3.4406057210321332,
+      3.390913184034896,
+      6.000000000000001
+    ]
+  }
+}
场景 159 修复后保存发布为版本 209。
场景 159 修复后保存发布为版本 209。 · 点击查看原图
从服务器回读的最终卡车 JPEG 封面,资产 2087;部分车身被立柱遮挡。
从服务器回读的最终卡车 JPEG 封面,资产 2087;部分车身被立柱遮挡。 · 点击查看原图
独立浏览器重新打开后卡车可见;像素差异 7515。
独立浏览器重新打开后卡车可见;像素差异 7515。 · 点击查看原图
+

数据保留与清理

保留开发环境场景 159(牛奶卡车检验区,PUBLISHED,当前及已发布版本 209,模型 156 / 已发布版本 204)和场景 160(狐狸野外训练区,PUBLISHED,当前及已发布版本 208,模型 157 / 已发布版本 201)。模型原发布版本未修改;模型 157 的当前草稿版本 202 继续保留,未发布或修改。本次无需 DDL 变更。
场景模型 / 发布版本最终状态当前版本
159 · 实测场景-牛奶卡车检验区-20260905156 / 204PUBLISHED209
160 · 实测场景-狐狸野外训练区-20260905157 / 201PUBLISHED208
保留两条真实场景及历史截图用于后续测试和追溯。新增导入狐狸仅在隔离浏览器会话中测试,未保存、无写请求;测试结束后丢弃临时对象。
+

本次问题记录

{
+  "title": "狐狸存在于对象树但不在真实视口中显示",
+  "status": "FIXED_AND_VISUALLY_VERIFIED",
+  "details": "原完整 E2E 通过结论已撤回。同步蒙皮矩阵并保留归一化缩放,修复场景数据和镜头后,新增导入、保存发布、独立刷新与像素可见性均通过;详见更正区。"
+}
+

后续独立事项

既存受控文件资产的 fsvc URI 分支未完整覆盖上传票据绑定校验,属于本次场景封面变更前已存在的问题。本次保留现有流程,后续应独立补齐校验并验证历史资产、版本复制与引用兼容性;不计入本次场景功能失败数。

{
+  "scope": "independent",
+  "title": "fsvc 新资产上传票据绑定校验",
+  "details": "既存流程的 fsvc URI 分支未完整覆盖上传票据绑定校验;本次未扩大修改范围,应单独补齐并验证历史资产、版本复制与引用兼容性。"
+}
+

实际命令与结果

pnpm run build

{
+  "status": "PASS",
+  "details": "前端生产构建及遗留模型编辑器产物校验通过。"
+}

node --test tools/scene-cover-api.test.mjs tools/scene-cover-capture.test.mjs tools/scene-model-placement.test.mjs

{
+  "status": "PASS",
+  "details": "33 / 33 通过:封面同次 PUT、异常回退、并发队列、项目切换、截图尺寸、渲染状态恢复,以及蒙皮模型包围盒与归一化缩放回归。"
+}

原 Microsoft Edge 场景链路 E2E(更正说明)

{
+  "status": "SUPERSEDED",
+  "details": "原 7/7 只覆盖模型引用、保存、封面上传和发布等链路,未证明狐狸真实可见;完整通过结论已撤回,当前视觉验证见下列独立浏览器 E2E。"
+}

node tools/scene-model-visibility.e2e.mjs

{
+  "status": "PASS",
+  "details": "独立 Edge / Playwright 会话重开 160/208 与 159/209,使用保存镜头,显示/隐藏模型并禁用投影进行像素比较;狐狸 4472 像素、卡车 7515 像素,均超过 500 阈值。证据保存在 visibility-evidence.json,截图 26 / 27;无写请求。"
+}
+

当前行为与限制

+ +
\ No newline at end of file diff --git a/reports/scene-live-20260905/report.md b/reports/scene-live-20260905/report.md new file mode 100644 index 0000000..85f1cae --- /dev/null +++ b/reports/scene-live-20260905/report.md @@ -0,0 +1,451 @@ +# 真实场景与截图封面验证报告 + +场景保存截图封面及列表按创建时间倒序的功能已实施。本报告记录使用现有模型创建真实场景、保存当前三维视口封面及异常回退的实际验证结果。 + +2026-09-05 · http://127.0.0.1:6180 · Microsoft Edge · 教员 + +## 狐狸场景验证更正:撤回原完整通过结论 + +> **测试结论更正:** 用户指出狐狸没有出现在场景中,经复现确认属实。原报告的 7/7 仅证明引用、保存、封面上传和发布等链路,漏掉了模型真正可见的视觉检查,因此撤回原“完整 E2E 通过”结论。下列修复后证据增加了真实画面和像素差异验证。 + +### 原结论与漏验 + +- 原狐狸检查把对象树存在 fox、模型依赖有效以及接口返回成功当作模型已加载可见;旧截图实际没有显示狐狸。两项旧狐狸证据标记为已更正历史记录并移出当前通过率,原文件继续保留用于追溯。 + +### 根因 + +- 计算蒙皮模型包围盒前没有同步骨骼矩阵,得到失真的尺寸。 +- 适配场景尺寸时使用 setScalar 覆盖模型已有的归一化缩放;两者叠加将狐狸放大到约 1000 个场景单位,使模型超出视锥。 + +### 修复内容 + +- 同步蒙皮矩阵后计算真实包围盒,并保留已有归一化缩放进行相对缩放;新导入模型与已保存模型均使用修正后的尺寸处理。 +- 修复场景 160 的狐狸比例和默认镜头,保存并发布为版本 208;重新生成服务器 JPEG 封面资产 2084。狐狸包围盒约为 0.966 × 2.812 × 6 个场景单位。 +- 同样复核并修正场景 159,保存并发布为版本 209,重新生成服务器 JPEG 封面资产 2087。未修改模型发布版本或数据库表结构。 + +### 修复后验证 + +- 真实 UI 从资源库新增狐狸后立即可见,最长边为 6;该新增操作仅在隔离浏览器会话中测试,未保存、无写请求。 +- 两个场景修改、保存、发布后,通过独立新浏览器会话重新打开,使用保存的默认镜头验证;没有未完成模型加载,也没有产生写请求。 +- 关闭模型投影后,对同一画面中模型显示与隐藏的像素进行比较:320 × 180 采样中狐狸改变 4472 像素、牛奶卡车改变 7515 像素,均超过 500 像素阈值。截图中可直接辨认狐狸与卡车。 +- 牛奶卡车默认镜头下部分车身被场景立柱遮挡,但模型确实可见;报告保留这一限制。 +- 最终列表显示狐狸在卡车之前,虽然卡车更新于 19:32、狐狸更新于 19:31,确认排序依据仍为创建时间。 + +[![修复后独立浏览器重新打开场景 160:狐狸模型清晰可见,并完成像素差异验证。](screenshots/26-fox-visual-regression.png)](screenshots/26-fox-visual-regression.png) + +下方标为“历史记录(已更正)”的检查及截图保留用于追溯,不计入当前通过率,也不作为狐狸已经可见的证据。 + +当前证据项通过 7 / 7;失败 0;其他或未标注 0;已更正历史记录 2;已校验图片文件 22。 + +## 保留场景与封面证据 + +### 实测场景-牛奶卡车检验区-20260905 + +场景 159;状态 PUBLISHED;当前版本 209;引用模型 156 / 发布版本 204。 + +[![场景 159 保存后封面回读证据](screenshots/24-truck-final-cover.jpg)](screenshots/24-truck-final-cover.jpg) + +
封面持久化与项目证据 + +
+{
+  "id": "159",
+  "name": "实测场景-牛奶卡车检验区-20260905",
+  "modelId": "156",
+  "modelVersionId": "204",
+  "finalStatus": "PUBLISHED",
+  "finalVersionId": "209",
+  "cover": {
+    "image": "screenshots/24-truck-final-cover.jpg",
+    "width": 640,
+    "height": 408,
+    "sizeBytes": 32937,
+    "assetId": "2087",
+    "versionId": "209",
+    "mimeType": "image/jpeg",
+    "sha256": "e103a473b74f3809365890296180c42f6c37a8005f2fd4c27fb64c437c245786",
+    "storageUri": "fsvc://unreal-tran/image/2026/09/05/d29810b273d75e43dff07622424f333f.jpg"
+  }
+}
+
+ +
+ +### 实测场景-狐狸野外训练区-20260905 + +场景 160;状态 PUBLISHED;当前版本 208;引用模型 157 / 发布版本 201。 + +[![场景 160 保存后封面回读证据](screenshots/22-fox-final-cover.jpg)](screenshots/22-fox-final-cover.jpg) + +
封面持久化与项目证据 + +
+{
+  "id": "160",
+  "name": "实测场景-狐狸野外训练区-20260905",
+  "modelId": "157",
+  "modelVersionId": "201",
+  "finalStatus": "PUBLISHED",
+  "finalVersionId": "208",
+  "cover": {
+    "image": "screenshots/22-fox-final-cover.jpg",
+    "width": 640,
+    "height": 408,
+    "sizeBytes": 45706,
+    "assetId": "2084",
+    "versionId": "208",
+    "mimeType": "image/jpeg",
+    "sha256": "1b6e4d1eb6e65ccc15ba820a8ae4bd40ab1bee900cf91d4ec3db9af82153618d",
+    "storageUri": "fsvc://unreal-tran/image/2026/09/05/c176d359087fc9bea4235e43dd43a691.jpg"
+  }
+}
+
+ +
+ +## 最终列表与创建时间倒序 + +[![保留场景的封面与创建时间倒序列表](screenshots/28-scene-list-fixed.png)](screenshots/28-scene-list-fixed.png) + +## 逐项验证记录 + +通过数仅统计未被更正且 status 明确为 PASS 的当前证据项;历史记录单独标注。checks 不重复累加。预期故障响应不等于用例失败,缺少状态不推断通过。图片文件存在校验不等于视觉内容验证。 + +| 序号 | 检查项 | 结果 | 图片 | +|---|---|---|---| +| 1 | 创建牛奶卡车检验区场景 | PASS | [图片 1](screenshots/03-truck-created-ready.png) | +| 2 | 牛奶卡车场景保存并回读封面 | PASS | [图片 1](screenshots/05-truck-model-imported.png) · [图片 2](screenshots/06-truck-transformed-unsaved.png) · [图片 3](screenshots/07-truck-scene-cover.png) · [图片 4](screenshots/08-truck-saved-with-cover.png) | +| 3 | 牛奶卡车场景刷新恢复并发布 | PASS | [图片 1](screenshots/09-truck-reloaded-persisted.png) · [图片 2](screenshots/10-truck-published.png) | +| 4 | 狐狸野外场景保存并锁定已发布模型版本 | 历史记录(已更正) | [图片 1](screenshots/12-fox-outdoor-template.png) · [图片 2](screenshots/13-fox-model-imported.png) · [图片 3](screenshots/14-fox-scene-cover.png) · [图片 4](screenshots/15-fox-saved-with-cover.png) | +| 5 | 场景封面上传失败保留原封面 | PASS | [图片 1](screenshots/16-fox-cover-upload-failed-content-saved.png) | +| 6 | 狐狸野外场景刷新恢复并发布 | 历史记录(已更正) | [图片 1](screenshots/17-fox-reloaded-persisted.png) · [图片 2](screenshots/18-fox-published.png) | +| 7 | 场景列表创建时间倒序与封面展示 | PASS | [图片 1](screenshots/28-scene-list-fixed.png) | +| 8 | 修复后狐狸新增导入、保存发布与刷新可见性 | PASS | [图片 1](screenshots/25-fox-fresh-import-visible.png) · [图片 2](screenshots/21-fox-corrected-published.png) · [图片 3](screenshots/22-fox-final-cover.jpg) · [图片 4](screenshots/26-fox-visual-regression.png) | +| 9 | 修复后牛奶卡车保存发布与刷新可见性 | PASS | [图片 1](screenshots/23-truck-corrected-published.png) · [图片 2](screenshots/24-truck-final-cover.jpg) · [图片 3](screenshots/27-truck-visual-regression.png) | + +### 1. 创建牛奶卡车检验区场景 · PASS + +- 通过列表新建并进入真实场景编辑器 +- 首次加载认证服务短暂503,点击重新加载后成功;原创建记录159复用 + +[![验证现场](screenshots/03-truck-created-ready.png)](screenshots/03-truck-created-ready.png) + +### 2. 牛奶卡车场景保存并回读封面 · PASS + +- 场景资源库双击引用模型 156 的已发布版本 204 +- 编辑对象坐标与设备绑定后,未保存状态 2.5 秒内无上传或项目写入 +- 保存草稿发出 SCENE\_COVER JPEG 上传与同一次项目 PUT +- 认证访问 /cover 返回 JPEG,封面尺寸 640×408,列表可用的 coverUri 已写入 + +[![验证现场](screenshots/05-truck-model-imported.png)](screenshots/05-truck-model-imported.png) + +[![验证现场](screenshots/06-truck-transformed-unsaved.png)](screenshots/06-truck-transformed-unsaved.png) + +[![验证现场](screenshots/07-truck-scene-cover.png)](screenshots/07-truck-scene-cover.png) + +[![验证现场](screenshots/08-truck-saved-with-cover.png)](screenshots/08-truck-saved-with-cover.png) + +### 3. 牛奶卡车场景刷新恢复并发布 · PASS + +- 整页刷新后模型 156/版本 204、对象名称、X=4.2 和设备编号均恢复 +- 发布前校验 8 项全部通过 +- 发布动作先成功保存再成功发布,最终状态为 PUBLISHED + +
检查详情 + +
+{
+  "details": {
+    "total": 8,
+    "warnings": 0,
+    "text": "✓\n场景环境已配置\n真实装备车库\n✓\n模型资源加载完成\n全部受控模型已就绪\n✓\n场景用途配置有效\n1 个实训装备\n✓\n对象设备编号完整\n用于接收物理设备和消息事件\n✓\n物模型绑定完整\n用于训练步骤和动作映射\n✓\n设备编号不重复\n设备编号唯一\n✓\n物模型编号不重复\n物模型编号唯一\n✓\n受控资源引用正常\n2 个导入模型可跨刷新恢复"
+  }
+}
+
+ +
+ +[![验证现场](screenshots/09-truck-reloaded-persisted.png)](screenshots/09-truck-reloaded-persisted.png) + +[![验证现场](screenshots/10-truck-published.png)](screenshots/10-truck-published.png) + +### 4. 狐狸野外场景保存并锁定已发布模型版本 · 历史记录(已更正) + +- 切换到真实野外训练场模板并导入模型 157 +- 模型 157 当前草稿版本为 202,但场景严格依赖其已发布版本 201 +- 保存草稿上传 SCENE\_COVER JPEG,并在同次项目 PUT 写入 content、依赖和 coverUri +- 认证回读 /cover 返回 JPEG,尺寸 640×408 + +
检查详情 + +
+{
+  "superseded": true
+}
+
+ +
+ +[![历史截图(不作为修复后的视觉通过证据):原测试现场](screenshots/12-fox-outdoor-template.png)](screenshots/12-fox-outdoor-template.png) + +[![历史截图(不作为修复后的视觉通过证据):原测试现场](screenshots/13-fox-model-imported.png)](screenshots/13-fox-model-imported.png) + +[![历史截图(不作为修复后的视觉通过证据):原测试现场](screenshots/14-fox-scene-cover.png)](screenshots/14-fox-scene-cover.png) + +[![历史截图(不作为修复后的视觉通过证据):原测试现场](screenshots/15-fox-saved-with-cover.png)](screenshots/15-fox-saved-with-cover.png) + +### 5. 场景封面上传失败保留原封面 · PASS + +- 对 SCENE\_COVER 上传实施浏览器网络故障注入 +- 保存请求仍成功,场景内容继续提交 +- coverUri 保持为保存前的旧值,未产生空封面或错误替换 + +
检查详情 + +
+{
+  "details": {
+    "sceneId": "160",
+    "oldCoverUri": "fsvc://unreal-tran/image/2026/09/05/bb1e8717cd2e7ba6ca10f16b817b1ec5.jpg",
+    "putRequests": 1
+  }
+}
+
+ +
+ +[![验证现场](screenshots/16-fox-cover-upload-failed-content-saved.png)](screenshots/16-fox-cover-upload-failed-content-saved.png) + +### 6. 狐狸野外场景刷新恢复并发布 · 历史记录(已更正) + +- 整页刷新后狐狸模型依赖仍为项目 157 的已发布版本 201 +- 封面上传失败后的场景正文编辑 X=-7.5 已恢复 +- 8 项发布校验全部通过,发布时重新保存并成功发布 +- 发布后的 coverUri 有效;保存前封面与发布后封面均由当前场景视图生成 + +
检查详情 + +
+{
+  "superseded": true,
+  "details": {
+    "validation": {
+      "total": 8,
+      "warnings": 0,
+      "text": "✓\n场景环境已配置\n真实野外训练场\n✓\n模型资源加载完成\n全部受控模型已就绪\n✓\n场景用途配置有效\n3 个实训装备\n✓\n对象设备编号完整\n用于接收物理设备和消息事件\n✓\n物模型绑定完整\n用于训练步骤和动作映射\n✓\n设备编号不重复\n设备编号唯一\n✓\n物模型编号不重复\n物模型编号唯一\n✓\n受控资源引用正常\n2 个导入模型可跨刷新恢复"
+    },
+    "coverBeforePublish": "fsvc://unreal-tran/image/2026/09/05/bb1e8717cd2e7ba6ca10f16b817b1ec5.jpg",
+    "coverAfterPublish": "fsvc://unreal-tran/image/2026/09/05/62e5d4a05316badb631e252f44ecbec3.jpg"
+  }
+}
+
+ +
+ +[![历史截图(不作为修复后的视觉通过证据):原测试现场](screenshots/17-fox-reloaded-persisted.png)](screenshots/17-fox-reloaded-persisted.png) + +[![历史截图(不作为修复后的视觉通过证据):原测试现场](screenshots/18-fox-published.png)](screenshots/18-fox-published.png) + +### 7. 场景列表创建时间倒序与封面展示 · PASS + +- 列表请求默认携带 sort=CREATED\_DESC +- 较晚创建的狐狸野外场景显示在较早创建的牛奶卡车场景之前 +- 卡车于 19:32 更新,晚于狐狸的 19:31,但狐狸仍排在卡车之前,证实没有按更新时间倒序 +- 两条场景均通过受控 /cover 接口展示修复后服务器 JPEG 封面;列表中可辨认狐狸和卡车 + +
检查详情 + +
+{
+  "details": {
+    "foxIndex": 0,
+    "truckIndex": 1,
+    "rows": [
+      {
+        "name": "狐狸野外场景",
+        "projectId": "160",
+        "addTime": 1788605625,
+        "updateTime": "2026-09-05T19:31:30",
+        "imageIsBlob": true
+      },
+      {
+        "name": "牛奶卡车场景",
+        "projectId": "159",
+        "addTime": 1788603808,
+        "updateTime": "2026-09-05T19:32:28",
+        "imageIsBlob": true
+      }
+    ]
+  }
+}
+
+ +
+ +[![验证现场](screenshots/28-scene-list-fixed.png)](screenshots/28-scene-list-fixed.png) + +### 8. 修复后狐狸新增导入、保存发布与刷新可见性 · PASS + +- 从真实 UI 资源库新增模型 157 / 已发布版本 201,默认缩放约 0.0361637593,包围盒约 0.966 × 2.812 × 6,狐狸在视口中可见;该临时新增未保存、无写请求 +- 场景 160 原狐狸修复尺寸和镜头后,保存并发布为版本 208;服务器封面资产 2084 为真实 JPEG,640 × 408,45706 字节 +- 独立 Edge / Playwright 新会话按保存的镜头重新打开场景,狐狸网格已加载且可见,pendingLoads=0 +- 显示/隐藏狐狸前后进行像素对比,禁用模型投影排除仅阴影可见:320 × 180 采样改变 4472 像素(7.764%),超过 500 像素阈值 +- 实际检查发布截图、独立刷新截图及服务器 JPEG,均可辨认狐狸;模型 157 草稿 202 仍为 DRAFT,已发布版本仍为 201 + +
检查详情 + +
+{
+  "details": {
+    "sceneId": "160",
+    "currentVersionId": "208",
+    "publishedVersionId": "208",
+    "modelProjectId": "157",
+    "modelVersionId": "201",
+    "newImportWriteRequests": [],
+    "visibilityEvidence": "visibility-evidence.json",
+    "changedPixels": 4472,
+    "changedPercentage": 7.764,
+    "pendingLoads": 0,
+    "boundsSize": [
+      0.9658796100519353,
+      2.811899945787403,
+      6
+    ]
+  }
+}
+
+ +
+ +[![真实 UI 新增狐狸后尺寸正常且可见;临时测试未保存。](screenshots/25-fox-fresh-import-visible.png)](screenshots/25-fox-fresh-import-visible.png) + +[![场景 160 修复后保存发布为版本 208。](screenshots/21-fox-corrected-published.png)](screenshots/21-fox-corrected-published.png) + +[![从服务器回读的最终狐狸 JPEG 封面,资产 2084。](screenshots/22-fox-final-cover.jpg)](screenshots/22-fox-final-cover.jpg) + +[![独立浏览器重新打开后狐狸可见;像素差异 4472。](screenshots/26-fox-visual-regression.png)](screenshots/26-fox-visual-regression.png) + +### 9. 修复后牛奶卡车保存发布与刷新可见性 · PASS + +- 场景 159 保持模型 156 / 已发布版本 204,修复比例和镜头后保存并发布为版本 209 +- 独立 Edge / Playwright 新会话重新打开场景,按保存镜头确认卡车 5 个网格均可见、pendingLoads=0 +- 显示/隐藏卡车前后对比,禁用模型投影:320 × 180 采样改变 7515 像素(13.047%),超过 500 像素阈值 +- 服务器回读最终封面资产 2087 为真实 JPEG,640 × 408,32937 字节;封面及刷新截图可辨认卡车 +- 默认镜头部分车身被立柱遮挡,属于本次可见画面的已知限制 + +
检查详情 + +
+{
+  "details": {
+    "sceneId": "159",
+    "currentVersionId": "209",
+    "publishedVersionId": "209",
+    "modelProjectId": "156",
+    "modelVersionId": "204",
+    "visibilityEvidence": "visibility-evidence.json",
+    "changedPixels": 7515,
+    "changedPercentage": 13.047,
+    "pendingLoads": 0,
+    "boundsSize": [
+      3.4406057210321332,
+      3.390913184034896,
+      6.000000000000001
+    ]
+  }
+}
+
+ +
+ +[![场景 159 修复后保存发布为版本 209。](screenshots/23-truck-corrected-published.png)](screenshots/23-truck-corrected-published.png) + +[![从服务器回读的最终卡车 JPEG 封面,资产 2087;部分车身被立柱遮挡。](screenshots/24-truck-final-cover.jpg)](screenshots/24-truck-final-cover.jpg) + +[![独立浏览器重新打开后卡车可见;像素差异 7515。](screenshots/27-truck-visual-regression.png)](screenshots/27-truck-visual-regression.png) + +## 数据保留与清理 + +
+保留开发环境场景 159(牛奶卡车检验区,PUBLISHED,当前及已发布版本 209,模型 156 / 已发布版本 204)和场景 160(狐狸野外训练区,PUBLISHED,当前及已发布版本 208,模型 157 / 已发布版本 201)。模型原发布版本未修改;模型 157 的当前草稿版本 202 继续保留,未发布或修改。本次无需 DDL 变更。
+
+ +| 场景 | 模型 / 发布版本 | 最终状态 | 当前版本 | +|---|---|---|---| +| 159 · 实测场景-牛奶卡车检验区-20260905 | 156 / 204 | PUBLISHED | 209 | +| 160 · 实测场景-狐狸野外训练区-20260905 | 157 / 201 | PUBLISHED | 208 | + +
+保留两条真实场景及历史截图用于后续测试和追溯。新增导入狐狸仅在隔离浏览器会话中测试,未保存、无写请求;测试结束后丢弃临时对象。
+
+ +## 本次问题记录 + +
+{
+  "title": "狐狸存在于对象树但不在真实视口中显示",
+  "status": "FIXED_AND_VISUALLY_VERIFIED",
+  "details": "原完整 E2E 通过结论已撤回。同步蒙皮矩阵并保留归一化缩放,修复场景数据和镜头后,新增导入、保存发布、独立刷新与像素可见性均通过;详见更正区。"
+}
+
+ +## 后续独立事项 + +既存受控文件资产的 fsvc URI 分支未完整覆盖上传票据绑定校验,属于本次场景封面变更前已存在的问题。本次保留现有流程,后续应独立补齐校验并验证历史资产、版本复制与引用兼容性;不计入本次场景功能失败数。 + +
+{
+  "scope": "independent",
+  "title": "fsvc 新资产上传票据绑定校验",
+  "details": "既存流程的 fsvc URI 分支未完整覆盖上传票据绑定校验;本次未扩大修改范围,应单独补齐并验证历史资产、版本复制与引用兼容性。"
+}
+
+ +## 实际命令与结果 + +**pnpm run build** + +
+{
+  "status": "PASS",
+  "details": "前端生产构建及遗留模型编辑器产物校验通过。"
+}
+
+ +**node --test tools/scene-cover-api.test.mjs tools/scene-cover-capture.test.mjs tools/scene-model-placement.test.mjs** + +
+{
+  "status": "PASS",
+  "details": "33 / 33 通过:封面同次 PUT、异常回退、并发队列、项目切换、截图尺寸、渲染状态恢复,以及蒙皮模型包围盒与归一化缩放回归。"
+}
+
+ +**原 Microsoft Edge 场景链路 E2E(更正说明)** + +
+{
+  "status": "SUPERSEDED",
+  "details": "原 7/7 只覆盖模型引用、保存、封面上传和发布等链路,未证明狐狸真实可见;完整通过结论已撤回,当前视觉验证见下列独立浏览器 E2E。"
+}
+
+ +**node tools/scene-model-visibility.e2e.mjs** + +
+{
+  "status": "PASS",
+  "details": "独立 Edge / Playwright 会话重开 160/208 与 159/209,使用保存镜头,显示/隐藏模型并禁用投影进行像素比较;狐狸 4472 像素、卡车 7515 像素,均超过 500 阈值。证据保存在 visibility-evidence.json,截图 26 / 27;无写请求。"
+}
+
+ +## 当前行为与限制 + +- 手动保存从当前三维视口生成封面;新封面与场景内容、模型引用在同一次工程更新中关联保存。发布前的保存沿用该流程。 +- 截图或封面上传失败时保留旧封面;工程是否保存成功以实际更新请求为准。版本冲突不覆盖其他已保存的内容。 +- 自动恢复及重新打开工程不生成或上传新封面;恢复后的修改需由用户保存后更新封面。 +- 列表按创建时间倒序展示。再次保存不会改变创建时间,也不应因此改变创建时间排序。 +- 牛奶卡车场景保存的默认镜头中,车身部分被场景立柱遮挡;真实网格可见且像素差异验证通过。需要观察完整车身时可旋转镜头。 + +报告来自 evidence.json,未修改原始证据;所有引用图片已校验存在且非空,点击可查看原图。通过数随证据更新。 diff --git a/reports/scene-live-20260905/screenshots/00-role-inspect.png b/reports/scene-live-20260905/screenshots/00-role-inspect.png new file mode 100644 index 0000000..3a28b8b Binary files /dev/null and b/reports/scene-live-20260905/screenshots/00-role-inspect.png differ diff --git a/reports/scene-live-20260905/screenshots/02-scene-load-diagnostic.png b/reports/scene-live-20260905/screenshots/02-scene-load-diagnostic.png new file mode 100644 index 0000000..b33a939 Binary files /dev/null and b/reports/scene-live-20260905/screenshots/02-scene-load-diagnostic.png differ diff --git a/reports/scene-live-20260905/screenshots/03-truck-created-ready.png b/reports/scene-live-20260905/screenshots/03-truck-created-ready.png new file mode 100644 index 0000000..b8f7186 Binary files /dev/null and b/reports/scene-live-20260905/screenshots/03-truck-created-ready.png differ diff --git a/reports/scene-live-20260905/screenshots/04-truck-editor-before-import.png b/reports/scene-live-20260905/screenshots/04-truck-editor-before-import.png new file mode 100644 index 0000000..e8be1af Binary files /dev/null and b/reports/scene-live-20260905/screenshots/04-truck-editor-before-import.png differ diff --git a/reports/scene-live-20260905/screenshots/05-truck-model-imported.png b/reports/scene-live-20260905/screenshots/05-truck-model-imported.png new file mode 100644 index 0000000..5fe778a Binary files /dev/null and b/reports/scene-live-20260905/screenshots/05-truck-model-imported.png differ diff --git a/reports/scene-live-20260905/screenshots/06-truck-transformed-unsaved.png b/reports/scene-live-20260905/screenshots/06-truck-transformed-unsaved.png new file mode 100644 index 0000000..3097627 Binary files /dev/null and b/reports/scene-live-20260905/screenshots/06-truck-transformed-unsaved.png differ diff --git a/reports/scene-live-20260905/screenshots/07-truck-scene-cover.png b/reports/scene-live-20260905/screenshots/07-truck-scene-cover.png new file mode 100644 index 0000000..7566957 Binary files /dev/null and b/reports/scene-live-20260905/screenshots/07-truck-scene-cover.png differ diff --git a/reports/scene-live-20260905/screenshots/08-truck-saved-with-cover.png b/reports/scene-live-20260905/screenshots/08-truck-saved-with-cover.png new file mode 100644 index 0000000..ee063e8 Binary files /dev/null and b/reports/scene-live-20260905/screenshots/08-truck-saved-with-cover.png differ diff --git a/reports/scene-live-20260905/screenshots/09-truck-reloaded-persisted.png b/reports/scene-live-20260905/screenshots/09-truck-reloaded-persisted.png new file mode 100644 index 0000000..61d9661 Binary files /dev/null and b/reports/scene-live-20260905/screenshots/09-truck-reloaded-persisted.png differ diff --git a/reports/scene-live-20260905/screenshots/10-truck-published.png b/reports/scene-live-20260905/screenshots/10-truck-published.png new file mode 100644 index 0000000..1c630a4 Binary files /dev/null and b/reports/scene-live-20260905/screenshots/10-truck-published.png differ diff --git a/reports/scene-live-20260905/screenshots/11-fox-created-editor.png b/reports/scene-live-20260905/screenshots/11-fox-created-editor.png new file mode 100644 index 0000000..6954db0 Binary files /dev/null and b/reports/scene-live-20260905/screenshots/11-fox-created-editor.png differ diff --git a/reports/scene-live-20260905/screenshots/12-fox-outdoor-template.png b/reports/scene-live-20260905/screenshots/12-fox-outdoor-template.png new file mode 100644 index 0000000..8aa8208 Binary files /dev/null and b/reports/scene-live-20260905/screenshots/12-fox-outdoor-template.png differ diff --git a/reports/scene-live-20260905/screenshots/13-fox-model-imported.png b/reports/scene-live-20260905/screenshots/13-fox-model-imported.png new file mode 100644 index 0000000..d78cc22 Binary files /dev/null and b/reports/scene-live-20260905/screenshots/13-fox-model-imported.png differ diff --git a/reports/scene-live-20260905/screenshots/14-fox-scene-cover.png b/reports/scene-live-20260905/screenshots/14-fox-scene-cover.png new file mode 100644 index 0000000..20b7fdd Binary files /dev/null and b/reports/scene-live-20260905/screenshots/14-fox-scene-cover.png differ diff --git a/reports/scene-live-20260905/screenshots/15-fox-saved-with-cover.png b/reports/scene-live-20260905/screenshots/15-fox-saved-with-cover.png new file mode 100644 index 0000000..9f03d94 Binary files /dev/null and b/reports/scene-live-20260905/screenshots/15-fox-saved-with-cover.png differ diff --git a/reports/scene-live-20260905/screenshots/16-fox-cover-upload-failed-content-saved.png b/reports/scene-live-20260905/screenshots/16-fox-cover-upload-failed-content-saved.png new file mode 100644 index 0000000..abaff4c Binary files /dev/null and b/reports/scene-live-20260905/screenshots/16-fox-cover-upload-failed-content-saved.png differ diff --git a/reports/scene-live-20260905/screenshots/17-fox-reloaded-persisted.png b/reports/scene-live-20260905/screenshots/17-fox-reloaded-persisted.png new file mode 100644 index 0000000..d62e612 Binary files /dev/null and b/reports/scene-live-20260905/screenshots/17-fox-reloaded-persisted.png differ diff --git a/reports/scene-live-20260905/screenshots/18-fox-published.png b/reports/scene-live-20260905/screenshots/18-fox-published.png new file mode 100644 index 0000000..b4dc25c Binary files /dev/null and b/reports/scene-live-20260905/screenshots/18-fox-published.png differ diff --git a/reports/scene-live-20260905/screenshots/19-scene-created-sort-and-covers.png b/reports/scene-live-20260905/screenshots/19-scene-created-sort-and-covers.png new file mode 100644 index 0000000..c8a063e Binary files /dev/null and b/reports/scene-live-20260905/screenshots/19-scene-created-sort-and-covers.png differ diff --git a/reports/scene-live-20260905/screenshots/20-fox-render-bug-before.png b/reports/scene-live-20260905/screenshots/20-fox-render-bug-before.png new file mode 100644 index 0000000..5929b8e Binary files /dev/null and b/reports/scene-live-20260905/screenshots/20-fox-render-bug-before.png differ diff --git a/reports/scene-live-20260905/screenshots/21-fox-corrected-published.png b/reports/scene-live-20260905/screenshots/21-fox-corrected-published.png new file mode 100644 index 0000000..63fe8da Binary files /dev/null and b/reports/scene-live-20260905/screenshots/21-fox-corrected-published.png differ diff --git a/reports/scene-live-20260905/screenshots/22-fox-final-cover.jpg b/reports/scene-live-20260905/screenshots/22-fox-final-cover.jpg new file mode 100644 index 0000000..f5d9927 Binary files /dev/null and b/reports/scene-live-20260905/screenshots/22-fox-final-cover.jpg differ diff --git a/reports/scene-live-20260905/screenshots/23-truck-corrected-published.png b/reports/scene-live-20260905/screenshots/23-truck-corrected-published.png new file mode 100644 index 0000000..bc4cbe2 Binary files /dev/null and b/reports/scene-live-20260905/screenshots/23-truck-corrected-published.png differ diff --git a/reports/scene-live-20260905/screenshots/24-truck-final-cover.jpg b/reports/scene-live-20260905/screenshots/24-truck-final-cover.jpg new file mode 100644 index 0000000..6d18db1 Binary files /dev/null and b/reports/scene-live-20260905/screenshots/24-truck-final-cover.jpg differ diff --git a/reports/scene-live-20260905/screenshots/25-fox-fresh-import-visible.png b/reports/scene-live-20260905/screenshots/25-fox-fresh-import-visible.png new file mode 100644 index 0000000..4016137 Binary files /dev/null and b/reports/scene-live-20260905/screenshots/25-fox-fresh-import-visible.png differ diff --git a/reports/scene-live-20260905/screenshots/26-fox-visual-regression.png b/reports/scene-live-20260905/screenshots/26-fox-visual-regression.png new file mode 100644 index 0000000..e354917 Binary files /dev/null and b/reports/scene-live-20260905/screenshots/26-fox-visual-regression.png differ diff --git a/reports/scene-live-20260905/screenshots/27-truck-visual-regression.png b/reports/scene-live-20260905/screenshots/27-truck-visual-regression.png new file mode 100644 index 0000000..86923ac Binary files /dev/null and b/reports/scene-live-20260905/screenshots/27-truck-visual-regression.png differ diff --git a/reports/scene-live-20260905/screenshots/28-scene-list-fixed.png b/reports/scene-live-20260905/screenshots/28-scene-list-fixed.png new file mode 100644 index 0000000..a9d0762 Binary files /dev/null and b/reports/scene-live-20260905/screenshots/28-scene-list-fixed.png differ diff --git a/reports/scene-live-20260905/visibility-evidence.json b/reports/scene-live-20260905/visibility-evidence.json new file mode 100644 index 0000000..919e74b --- /dev/null +++ b/reports/scene-live-20260905/visibility-evidence.json @@ -0,0 +1,183 @@ +{ + "generatedAt": "2026-09-05T11:32:36.450Z", + "baseURL": "http://127.0.0.1:6180", + "browser": "Microsoft Edge / Playwright", + "method": "Fresh context; saved camera; compare rendered pixels with model roots visible versus hidden; model shadow casting disabled in both samples.", + "threshold": { + "sampleWidth": 320, + "sampleHeight": 180, + "minimumChangedPixelsExclusive": 500, + "minimumRgbDelta": 12 + }, + "status": "PASS", + "results": [ + { + "sceneId": "160", + "modelProjectId": "157", + "modelVersionId": "201", + "label": "狐狸野外训练区", + "screenshot": "screenshots/26-fox-visual-regression.png", + "status": "PASS", + "blockedWrites": [], + "session": { + "role": "teacher", + "roleSwitchAttempts": 1 + }, + "project": { + "id": "160", + "name": "实测场景-狐狸野外训练区-20260905", + "status": "PUBLISHED", + "currentVersionId": "208", + "publishedVersionId": "208" + }, + "visibility": { + "camera": { + "position": [ + -2.508014030799152, + 4.171439329448699, + 5.794358645466257 + ], + "target": [ + -7.512232860974557, + 1.4059499759307126, + -2.2204460492503126e-16 + ], + "fov": 45 + }, + "ready": true, + "pendingLoads": 0, + "modelRoots": [ + { + "name": "狐狸野外巡检目标", + "sceneObjectId": "OBJ-1788605916565-6", + "targetProjectId": "157", + "targetVersionId": "201", + "visible": true, + "meshes": 1, + "visibleMeshes": 1, + "skinnedMeshes": 1, + "position": [ + -7.5, + 0.10930174852949677, + 0.3440109341705351 + ], + "scale": [ + 0.03616375932570189, + 0.03616375932570189, + 0.03616375932570189 + ], + "bounds": { + "min": [ + -7.995172666000524, + 3.037011225837105e-9, + -3.0000000000000004 + ], + "max": [ + -7.029293055948589, + 2.811899948824414, + 3 + ], + "size": [ + 0.9658796100519353, + 2.811899945787403, + 6 + ] + }, + "finiteBounds": true + } + ], + "sample": { + "width": 320, + "height": 180, + "changedPixels": 4472, + "changedPercentage": 7.764, + "rgbDeltaSum": 683026 + } + } + }, + { + "sceneId": "159", + "modelProjectId": "156", + "modelVersionId": "204", + "label": "牛奶卡车检验区", + "screenshot": "screenshots/27-truck-visual-regression.png", + "status": "PASS", + "blockedWrites": [], + "session": { + "role": "teacher", + "roleSwitchAttempts": 1 + }, + "project": { + "id": "159", + "name": "实测场景-牛奶卡车检验区-20260905", + "status": "PUBLISHED", + "currentVersionId": "209", + "publishedVersionId": "209" + }, + "visibility": { + "camera": { + "position": [ + 10.565439077211714, + 5.0456876852867705, + 7.37050840519251 + ], + "target": [ + 4.2, + 1.695456592017448, + 0 + ], + "fov": 45 + }, + "ready": true, + "pendingLoads": 0, + "modelRoots": [ + { + "name": "牛奶卡车检验主装备", + "sceneObjectId": "OBJ-1788605199171-2", + "targetProjectId": "156", + "targetVersionId": "204", + "visible": true, + "meshes": 5, + "visibleMeshes": 5, + "skinnedMeshes": 0, + "position": [ + 4.2, + 0.20617168998977797, + -0.4356763541543951 + ], + "scale": [ + 1.2323086149245381, + 1.2323086149245381, + 1.2323086149245381 + ], + "bounds": { + "min": [ + 2.4796971394839336, + 0, + -3.0000000000000004 + ], + "max": [ + 5.920302860516067, + 3.390913184034896, + 3.0000000000000004 + ], + "size": [ + 3.4406057210321332, + 3.390913184034896, + 6.000000000000001 + ] + }, + "finiteBounds": true + } + ], + "sample": { + "width": 320, + "height": 180, + "changedPixels": 7515, + "changedPercentage": 13.047, + "rgbDeltaSum": 948690 + } + } + } + ] +} diff --git a/tools/build-model-cover-report.mjs b/tools/build-model-cover-report.mjs new file mode 100644 index 0000000..d6ca751 --- /dev/null +++ b/tools/build-model-cover-report.mjs @@ -0,0 +1,158 @@ +import fs from 'node:fs' +import path from 'node:path' +import { fileURLToPath } from 'node:url' + +const reportDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../reports/model-cover-20260905') +const sourcePath = path.join(reportDir, 'evidence.json') +const sensitiveKey = /password|secret|token|ticket|authorization|cookie|signature|credential/i +const cleanText = value => String(value ?? '') + .replace(/\bBearer\s+[^\s"'<>]+/gi, 'Bearer [已隐藏]') + .replace(/(https?:\/\/)[^\s/@]+:[^\s/@]+@/gi, '$1[已隐藏]@') + .replace(/\b((?:access|refresh)?[_-]?token|password|secret|uploadTicket|signature|api[_-]?key)\s*[:=]\s*(?:"[^"]*"|'[^']*'|[^\s,;}]+)/gi, '$1=[已隐藏]') + +function sanitize(value) { + if (typeof value === 'string') return cleanText(value) + if (Array.isArray(value)) return value.map(sanitize) + if (value && typeof value === 'object') { + return Object.fromEntries(Object.entries(value) + .filter(([key]) => !sensitiveKey.test(key)) + .map(([key, item]) => [key, sanitize(item)])) + } + return value +} + +const data = sanitize(JSON.parse(fs.readFileSync(sourcePath, 'utf8').replace(/^\uFEFF/, ''))) +const evidence = Array.isArray(data.evidence) ? data.evidence : [] +const projects = Array.isArray(data.projects) ? data.projects : [] +const issues = Array.isArray(data.issues) ? data.issues : data.issues ? [data.issues] : [] +const commands = Array.isArray(data.commands) ? data.commands : data.commands ? [data.commands] : [] +const passCount = evidence.filter(item => item.status === 'PASS').length +const nonPassCount = evidence.length - passCount +const imageFields = new Set(['screenshot', 'screenshots', 'coverImage', 'image', 'finalListScreenshot']) +const imagePaths = new Set() + +function collectImages(value, key = '') { + if (typeof value === 'string' && imageFields.has(key) && value) imagePaths.add(value) + else if (Array.isArray(value)) value.forEach(item => collectImages(item, key)) + else if (value && typeof value === 'object') { + Object.entries(value).forEach(([childKey, item]) => collectImages(item, childKey)) + } +} +collectImages(data) + +const realReportDir = fs.realpathSync(reportDir) +for (const relative of imagePaths) { + const normalized = relative.replaceAll('\\', '/') + if (path.isAbsolute(relative) || /^[a-z][a-z\d+.-]*:/i.test(relative) + || !/\.(png|jpe?g|webp)$/i.test(relative)) { + throw new Error(`图片必须是报告目录中的 PNG/JPEG/WebP 相对路径:${relative}`) + } + const absolute = path.resolve(reportDir, normalized) + const underRoot = path.relative(reportDir, absolute) + if (underRoot.startsWith('..') || path.isAbsolute(underRoot) + || !fs.existsSync(absolute) || !fs.statSync(absolute).isFile() || fs.statSync(absolute).size === 0) { + throw new Error(`图片不存在、为空或越出报告目录:${relative}`) + } + const realRelative = path.relative(realReportDir, fs.realpathSync(absolute)) + if (realRelative.startsWith('..') || path.isAbsolute(realRelative)) { + throw new Error(`图片链接目标越出报告目录:${relative}`) + } +} + +const html = value => cleanText(value).replace(/[&<>"']/g, char => ({ + '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', +})[char]) +const md = value => cleanText(value).replaceAll('\\', '\\\\').replaceAll('|', '\\|').replace(/\r?\n/g, ' ') +const url = value => String(value).replaceAll('\\', '/').split('/').map(encodeURIComponent).join('/') +const pretty = value => typeof value === 'string' ? value : JSON.stringify(value, null, 2) +const status = value => value || '未记录' +const statusClass = value => value === 'PASS' ? 'pass' : value === 'FAIL' ? 'fail' : 'neutral' +const picturesOf = item => [...new Set([ + item.screenshot, + ...(Array.isArray(item.screenshots) ? item.screenshots : []), + item.coverImage, +].filter(Boolean))] +const figure = (src, caption, className = '') => src + ? `
${html(caption)}
${html(caption)} · 点击查看原图
` + : '

尚未记录图片。

' +const mdImage = (src, caption) => src ? `[![${md(caption)}](${url(src)})](${url(src)})` : '尚未记录图片。' + +const finalList = data.finalListScreenshot || [...evidence].reverse().find(item => item.screenshot + && (/最终.*(?:列表|模型|封面)/.test(item.title || '') || /final.*(?:covers|list)/i.test(item.screenshot)))?.screenshot +const cleanup = evidence.find(item => String(item.details?.id) === '158' && item.status === 'PASS' + && (item.details?.readAfterDelete === 404 || /清理|软删/.test(item.title || ''))) +const cleanupText = cleanup + ? '首次导入验证使用的临时项目 158 已通过业务软删除,删除后读取返回 404;报告保留操作证据,不宣称物理文件已删除。' + : '临时项目 158 的业务软删除结果尚未在 evidence.json 中完整记录,请以补充后的证据为准。' +const retainedText = data.retainedData ? pretty(data.retainedData) : projects.length + ? `项目 ${projects.map(item => item.id).join('、')} 保留在开发环境,供继续查看模型、封面及历史版本。` + : '尚未记录需要保留的项目。' +const limitations = [ + '仅手动保存和首次导入模型时生成或更新封面,封面取自当前三维视口。', + '自动保存只保存工程变更,不重新截图或上传封面。', + '截图或封面上传失败时保留旧封面,并提示失败;工程保存仍按其实际请求结果判断。', +] +const featureText = '截图封面功能已实施并完成下列真实浏览器验证:视口截图作为受控图片资产与工程关联保存,列表读取真实封面,模型列表按创建时间倒序显示。' +const environment = `${data.date || '日期未记录'} · ${data.baseURL || '地址未记录'} · ${data.browser || '浏览器未记录'} · ${data.role || '角色未记录'}` +const commandParts = item => typeof item === 'string' + ? { command: item, result: '未记录执行结果' } + : { command: item.command || item.cmd || item.name || '命令未记录', + result: pretty(Object.fromEntries(Object.entries(item).filter(([key]) => !['command', 'cmd', 'name'].includes(key)))) } + +const outputHtml = ` + +模型截图封面验证报告 · ${html(data.date)} +
+
MODEL COVER · IMPLEMENTED

模型截图封面验证报告

${html(featureText)}

${html(environment)}

Markdown 报告
+
${passCount} / ${evidence.length}证据项通过
${nonPassCount}非 PASS 证据项
${imagePaths.size}图片文件已校验
+

最终模型封面

${projects.map(project => { + const cover = project.cover || {} + return `

${html(project.name || `项目 ${project.id}`)}

${figure(cover.image, `项目 ${project.id} 最终封面`, 'cover-image')}
项目 / 最终状态
${html(project.id)} / ${html(status(project.finalStatus))}
工程版本 / 封面资产
${html(project.finalVersionId || cover.versionId || '未记录')} / ${html(cover.coverAssetId || '未记录')}
图片规格
${html(cover.width || '?')} × ${html(cover.height || '?')} · ${html(cover.bytes ?? '?')} 字节
封面持久化证据
${html(pretty(cover))}
` +}).join('')}
+

最终列表现场

${figure(finalList, '两条保留模型的真实封面与创建时间倒序列表')}
+

验证记录

通过数只统计 status 为 PASS 的记录;故障注入中预期的 503、401 或 404 不等于用例失败。

${evidence.map((item, index) => { + const pictures = picturesOf(item) + const extra = Object.fromEntries(Object.entries(item).filter(([key]) => !['title', 'status', 'screenshot', 'screenshots', 'coverImage'].includes(key))) + return `

${index + 1}. ${html(item.title)}

${html(status(item.status))}
${Object.keys(extra).length ? `
检查细节
${html(pretty(extra))}
` : ''}
${pictures.map(src => figure(src, /\.jpe?g$/i.test(src) ? '实际生成封面' : '浏览器现场')).join('')}
` +}).join('')}
+

数据保留与清理

${html(retainedText)}

${projects.map(project => ``).join('')}
项目初始状态最终状态
${html(project.id)} · ${html(project.name)}${html(status(project.originalStatus))}${html(status(project.finalStatus))}

${html(cleanupText)}

+

问题记录

${issues.length ? issues.map(issue => `
${html(pretty(issue))}
`).join('') : '

当前证据未登记未解决问题。

'}
+

实际命令与结果

${commands.length ? commands.map(item => { const entry = commandParts(item); return `

${html(entry.command)}

${html(entry.result)}
` }).join('') : '

本次 evidence.json 尚未记录命令结果;不据此宣称构建或命令行测试通过。

'}
+

当前行为与限制

+ +
` + +const outputMarkdown = [ + '# 模型截图封面验证报告', '', featureText, '', environment, '', + `证据通过:**${passCount} / ${evidence.length}**;非 PASS:${nonPassCount};已校验图片:${imagePaths.size}。`, '', + '## 最终模型封面', '', + ...projects.flatMap(project => [ + `### ${project.name || `项目 ${project.id}`}`, '', + `项目 ${project.id};最终状态:${status(project.finalStatus)};工程版本 ID:${project.finalVersionId || project.cover?.versionId || '未记录'};封面资产 ID:${project.cover?.coverAssetId || '未记录'}。`, '', + mdImage(project.cover?.image, `项目 ${project.id} 最终封面`), '', + ]), + '## 最终列表现场', '', mdImage(finalList, '最终两条模型封面列表'), '', + '## 验证记录', '', '通过统计只认 status 为 PASS;预期故障响应不视为用例失败。', '', + '| 序号 | 检查项 | 结果 | 图片 |', '|---|---|---|---|', + ...evidence.map((item, index) => `| ${index + 1} | ${md(item.title)} | ${md(status(item.status))} | ${picturesOf(item).map((src, i) => `[图片 ${i + 1}](${url(src)})`).join(' · ') || '—'} |`), '', + ...evidence.filter(item => item.details !== undefined).flatMap(item => [ + `
${html(item.title)}:检查细节`, '', '
', html(pretty(item.details)), '
', '', '
', '', + ]), + '## 数据保留与清理', '', retainedText, '', + '| 项目 | 初始状态 | 最终状态 |', '|---|---|---|', + ...projects.map(project => `| ${md(project.id)} · ${md(project.name)} | ${md(status(project.originalStatus))} | ${md(status(project.finalStatus))} |`), '', + cleanupText, '', '## 问题记录', '', + ...(issues.length ? issues.flatMap(issue => [pretty(issue), '']) : ['当前证据未登记未解决问题。', '']), + '## 实际命令与结果', '', + ...(commands.length ? commands.flatMap(item => { const entry = commandParts(item); return [`**${md(entry.command)}**`, '', '
', html(entry.result), '
', ''] }) + : ['本次 evidence.json 尚未记录命令结果;不据此宣称构建或命令行测试通过。', '']), + '## 当前行为与限制', '', ...limitations.map(item => `- ${item}`), '', + '报告由 evidence.json 生成,未修改原始证据;图片均已校验存在且非空,点击图片可查看原图。', '', +].join('\n') + +fs.writeFileSync(path.join(reportDir, 'index.html'), outputHtml, 'utf8') +fs.writeFileSync(path.join(reportDir, 'report.md'), outputMarkdown, 'utf8') +console.log(JSON.stringify({ report: 'reports/model-cover-20260905/index.html', passed: passCount, + total: evidence.length, nonPass: nonPassCount, imagesValidated: imagePaths.size, commandsRecorded: commands.length })) diff --git a/tools/build-model-live-report.mjs b/tools/build-model-live-report.mjs new file mode 100644 index 0000000..1f5aa68 --- /dev/null +++ b/tools/build-model-live-report.mjs @@ -0,0 +1,265 @@ +import { existsSync } from 'node:fs'; +import { readFile, writeFile } from 'node:fs/promises'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const DEFAULT_REPORT_DIR = fileURLToPath(new URL('../reports/model-live-20260905/', import.meta.url)); +const missing = '未记录'; +const has = (value) => value !== undefined && value !== null && value !== ''; +const list = (value) => Array.isArray(value) ? value : has(value) ? [value] : []; +const escape = (value) => String(value).replace(/[&<>"']/g, (char) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[char]); +const markdown = (value) => String(value).replace(/([\\`*_[\]<>|])/g, '\\$1').replace(/\r?\n/g, ' / '); +const display = (value) => has(value) ? String(value) : missing; +const first = (...values) => values.find(has); +const labels = { + status: '状态', result: '结果', passed: '检查通过', success: '操作成功', + server: '服务端', live: '页面运行时', sha256: 'SHA-256', bytes: '文件字节数', + mutations: '变更记录', name: '名称', code: '编码', id: 'ID', httpStatus: 'HTTP 状态', + message: '说明', details: '详情', note: '备注', reason: '原因', issue: '问题', + saved: '已保存', persisted: '已持久化', reopened: '重开', published: '发布', + publishedAt: '发布时间', version: '版本', title: '标题', file: '来源文件', + sourcePath: '素材路径', assetUrl: '资源地址', modelUrl: '模型地址', url: '地址', + objectCount: '对象数', meshCount: '网格数', animationCount: '动画数', + animations: '动画', clip: '动画编号', clipName: '动画名称', clips: '动画数', + playing: '正在播放', time: '时间', before: '变更前', after: '变更后', + position: '位置', rotation: '旋转', scale: '缩放', visible: '可见', + retained: '保留状态', cleanup: '清理记录', retainedData: '保留数据', + nodes: '节点数', meshes: '网格数', materials: '材质数', textures: '纹理数', + type: '类别', command: '执行命令', rows: '列表核验结果', +}; + +function status(value) { + if (value && typeof value === 'object') value = first(value.status, value.result, value.passed, value.success); + if (!has(value)) return { label: missing, tone: 'unknown' }; + if (value === true) return { label: '通过', tone: 'pass' }; + if (value === false) return { label: '失败', tone: 'fail' }; + const raw = String(value); + const normalized = raw.toUpperCase(); + if (['PASS', 'PASSED', 'SUCCESS', 'OK', '通过', '成功'].includes(normalized)) return { label: '通过', tone: 'pass' }; + if (['FAIL', 'FAILED', 'ERROR', '失败', '错误'].includes(normalized)) return { label: '失败', tone: 'fail' }; + if (['SKIP', 'SKIPPED', '跳过'].includes(normalized)) return { label: '跳过', tone: 'unknown' }; + if (['PENDING', 'TODO', 'NOT_RUN', '未执行', '待验证'].includes(normalized)) return { label: '待验证', tone: 'unknown' }; + if (normalized === 'PUBLISHED') return { label: '已发布', tone: 'info' }; + if (normalized === 'DRAFT') return { label: '草稿', tone: 'info' }; + return { label: raw, tone: 'info' }; +} + +function safeText(value) { + return String(value) + .replace(/Bearer\s+[A-Za-z0-9._~+/=-]+/gi, 'Bearer [已隐藏]') + .replace(/eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/g, '[令牌已隐藏]') + .slice(0, 700); +} + +// Keep useful scalar evidence, with bounded nesting; never dump scene documents. +function details(value, prefix = '', depth = 0) { + if (!has(value)) return []; + if (typeof value !== 'object') return [[prefix || '记录', safeText(value)]]; + if (Array.isArray(value)) { + if (!value.length) return [[prefix || '记录', '0 项']]; + if (value.every((item) => item === null || typeof item !== 'object')) { + return [[prefix || '记录', safeText(value.slice(0, 8).join('、')) + (value.length > 8 ? `(共 ${value.length} 项)` : '')]]; + } + if (depth >= 3) return [[prefix || '记录', `${value.length} 项,完整内容见 evidence.json`]]; + return value.slice(0, 3).flatMap((item, index) => details(item, `${prefix || '记录'} ${index + 1}`, depth + 1)) + .concat(value.length > 3 ? [[prefix || '记录', `共 ${value.length} 项,完整内容见 evidence.json`]] : []); + } + const rows = []; + for (const [key, item] of Object.entries(value)) { + if (['screenshot', 'screenshots'].includes(key) || !has(item)) continue; + const label = [prefix, labels[key] || key].filter(Boolean).join(' / '); + if (/password|passwd|secret|token|authorization|cookie|credential/i.test(key)) { + rows.push([label, '[已隐藏]']); + } else if (/^(modelObjects|objects|nodes|meshes|materials|textures|buffers|bufferViews|accessors)$/i.test(key)) { + rows.push([label, typeof item === 'object' + ? `${Array.isArray(item) ? item.length : Object.keys(item).length} 项(省略明细)` + : safeText(item)]); + } else if (depth >= 3 && typeof item === 'object') { + rows.push([label, '已记录,完整内容见 evidence.json']); + } else { + rows.push(...details(item, label, depth + 1)); + } + if (rows.length >= 24) { + rows.push(['更多记录', '见 evidence.json']); + break; + } + } + return rows; +} + +function tableHtml(headers, rows) { + return `
${headers.map((cell) => ``).join('')}${rows.map((row) => `${row.map((cell) => ``).join('')}`).join('')}
${escape(cell)}
${cell}
`; +} + +function tableMarkdown(headers, rows) { + return [`| ${headers.map(markdown).join(' | ')} |`, `| ${headers.map(() => '---').join(' | ')} |`, ...rows.map((row) => `| ${row.map(markdown).join(' | ')} |`)].join('\n'); +} + +function badge(value) { + const item = status(value); + return `${escape(item.label)}`; +} + +function record(value) { + const rows = details(value); + return { + html: rows.length ? `
${rows.map(([key, item]) => `
${escape(key)}
${escape(item)}
`).join('')}
` : `

${missing}

`, + md: rows.length ? rows.map(([key, item]) => `- ${markdown(key)}:${markdown(item)}`).join('\n') : missing, + }; +} + +export function renderModelLiveReport(evidence, { reportDir = DEFAULT_REPORT_DIR } = {}) { + if (!evidence || typeof evidence !== 'object' || Array.isArray(evidence)) throw new Error('evidence.json 必须为对象'); + const projects = list(evidence.projects).filter((item) => item && typeof item === 'object'); + const steps = projects.flatMap((project) => list(project.steps)); + const counts = { pass: 0, fail: 0, other: 0 }; + for (const step of steps) { + const tone = status(step).tone; + counts[tone === 'pass' || tone === 'fail' ? tone : 'other'] += 1; + } + const title = `真实模型制作实测报告 · ${display(evidence.date)}`; + const summary = `已记录 ${projects.length}/2 个模型项目、${steps.length} 项步骤:${counts.pass} 项通过,${counts.fail} 项失败,${counts.other} 项其他或未记录结论。`; + const environment = [ + ['测试日期', display(evidence.date)], ['页面地址', display(evidence.baseURL)], + ['浏览器', display(evidence.browser)], ['账号角色', display(evidence.role)], + ['账号显示名称', display(evidence.accountDisplayName)], + ]; + const html = [`

开发环境 · 真实模型制作

${escape(title)}

${escape(summary)}

`, '

环境与身份

', tableHtml(['项目', '记录'], environment.map((row) => row.map(escape))), '
']; + const md = [`# ${title}`, summary, '统计仅来自明确记录的步骤结论;缺失字段、仅有数据或仅有截图均不视为通过。', '## 环境与身份', tableMarkdown(['项目', '记录'], environment)]; + html.push('

统计仅来自明确记录的步骤结论;缺失字段、仅有数据或仅有截图均不视为通过。

'); + const seenPictures = new Set(); + let imageCount = 0; + const imageProblems = []; + + function screenshots(value, fallback) { + const pictures = []; + function visit(item, caption) { + if (!item || typeof item !== 'object') return; + if (Array.isArray(item)) return item.forEach((child) => visit(child, caption)); + const label = first(item.step, item.title, item.caption, item.name, caption); + for (const field of ['screenshot', 'screenshots']) { + for (const picture of list(item[field])) { + const location = typeof picture === 'string' ? picture : first(picture?.path, picture?.screenshot, picture?.file); + if (has(location)) pictures.push({ path: String(location).replaceAll('\\', '/'), title: first(picture?.caption, picture?.title, label, fallback) }); + } + } + for (const [key, child] of Object.entries(item)) { + if (!['screenshot', 'screenshots', 'modelObjects', 'objects', 'nodes', 'meshes', 'materials', 'textures', 'buffers', 'bufferViews', 'accessors'].includes(key) && typeof child === 'object') visit(child, label); + } + } + visit(value, fallback); + const htmlPictures = []; + const mdPictures = []; + for (const picture of pictures) { + if (seenPictures.has(picture.path)) continue; + seenPictures.add(picture.path); + const safePath = /^screenshots\/[a-zA-Z0-9_\-./\u3400-\u9fff ]+\.(png|jpe?g|webp)$/i.test(picture.path) && !picture.path.split('/').some((part) => part === '.' || part === '..' || !part); + if (!safePath || !existsSync(path.join(reportDir, picture.path))) { + const problem = `${picture.title}:${safePath ? '截图文件未找到' : '截图路径不受支持'}(${picture.path})`; + imageProblems.push(problem); + htmlPictures.push(`

${escape(problem)}

`); + mdPictures.push(markdown(problem)); + continue; + } + imageCount += 1; + const href = picture.path.split('/').map(encodeURIComponent).join('/'); + htmlPictures.push(`
${escape(picture.title)}
${escape(picture.title)}
`); + mdPictures.push(`![${markdown(picture.title)}](${href})`); + } + return { html: htmlPictures.length ? `` : '', md: mdPictures.join('\n\n') }; + } + + for (const [index, project] of projects.entries()) { + const name = display(project.name); + const heading = `模型 ${index + 1}:${name}`; + const nativeClips = project.imported?.live?.clips; + const identity = [ + ['项目名称', name], ['项目编码', display(project.code)], ['项目 ID', display(project.id)], + ['来源素材', display(first(project.sourcePath, project.file))], + ['测试节点', display(project.mesh)], + ['动画', `${display(project.clipName)};编号 ${display(project.clip)};数量 ${display(project.clips)}`], + ['原生动画片段', Array.isArray(nativeClips) + ? `${nativeClips.length} 段${nativeClips.length ? `:${nativeClips.map((clip) => display(clip?.name)).join('、')}` : ''}` + : missing], + ]; + html.push(`

${escape(heading)}

`, tableHtml(['项目', '记录'], identity.map((row) => row.map(escape)))); + md.push(`## ${heading}`, tableMarkdown(['项目', '记录'], identity)); + if (has(project.description)) { html.push(`

${escape(safeText(project.description))}

`); md.push(safeText(project.description)); } + const projectSteps = list(project.steps); + html.push('

操作步骤

'); md.push('### 操作步骤'); + if (projectSteps.length) { + const rows = projectSteps.map((step, stepIndex) => [String(stepIndex + 1), display(step?.step), status(step).label, + details(typeof step === 'object' && step !== null ? Object.fromEntries(Object.entries(step).filter(([key]) => !['step', 'status', 'result', 'passed', 'success'].includes(key))) : undefined).map(([key, value]) => `${key}:${value}`).join(';') || missing]); + html.push(tableHtml(['序号', '步骤', '结论', '证据摘要'], rows.map((row, stepIndex) => row.map((cell, cellIndex) => cellIndex === 2 ? badge(projectSteps[stepIndex]) : escape(cell))))); + md.push(tableMarkdown(['序号', '步骤', '结论', '证据摘要'], rows)); + } else { html.push(`

${missing}

`); md.push(missing); } + const stages = [ + ['导入校验', project.imported], ['编辑与保存', first(project.edited, project.saved)], + ['保存后重开', project.reopened], ['动画检查', first(project.animationCheck, project.animation, project.animationChecks)], + ['发布状态', project.published], + ]; + html.push('
'); + for (const [stageTitle, value] of stages) { + const result = record(value); + const conclusion = has(value) && status(value).label === missing ? '已记录,未给出结论' : status(value).label; + html.push(`

${escape(stageTitle)}

${escape(conclusion)}

${result.html}
`); + md.push(`### ${stageTitle}`, `结论:${conclusion}`, result.md); + } + html.push('
'); + const pictures = screenshots(project, name); + if (pictures.html) { html.push('

现场截图

', pictures.html); md.push('### 现场截图', pictures.md); } + html.push('
'); + } + if (projects.length < 2) { + const warning = `当前仅记录 ${projects.length}/2 个项目,其余项目尚无证据。`; + html.push(`

${warning}

`); md.push(warning); + } + const supplemental = list(evidence.evidence); + if (supplemental.length) { + const titles = { 'final-list': '最终项目列表', build: '构建检查', scope: '实测范围' }; + html.push('

补充验证

'); md.push('## 补充验证'); + for (const [index, item] of supplemental.entries()) { + const heading = first(titles[item?.type], item?.title, item?.type, `补充记录 ${index + 1}`); + const result = record(item); + html.push(`

${escape(heading)}

${result.html}
`); + md.push(`### ${heading}`, result.md); + } + html.push('
'); + } + const extraPictures = screenshots({ evidence: evidence.evidence, screenshots: evidence.screenshots, issues: evidence.issues }, '补充证据'); + if (extraPictures.html) { html.push('

补充截图

', extraPictures.html, '
'); md.push('## 补充截图', extraPictures.md); } + const retention = record(first(evidence.retainedData, evidence.retention, evidence.dataRetention, evidence.cleanup)); + const retainedRows = projects.map((project) => [display(project.name), display(project.id), display(project.code), has(project.retained) ? (typeof project.retained === 'boolean' ? project.retained ? '保留' : '不保留' : String(project.retained)) : '未记录保留/清理结论']); + html.push('

遗留数据与保留说明

', tableHtml(['项目', 'ID', '编码', '保留/清理结论'], retainedRows.map((row) => row.map(escape))), retention.html, '

本报告生成过程不修改项目数据。数据保留与清理结果以证据记录为准。

'); + md.push('## 遗留数据与保留说明', tableMarkdown(['项目', 'ID', '编码', '保留/清理结论'], retainedRows), retention.md, '本报告生成过程不修改项目数据。数据保留与清理结果以证据记录为准。'); + const issues = list(evidence.issues).map((issue) => record(issue)); + projects.forEach((project) => list(project.issues).forEach((issue) => issues.push(record({ project: project.name, issue })))); + imageProblems.forEach((problem) => issues.push(record(problem))); + const noIssues = Array.isArray(evidence.issues) ? '问题数组为空;未执行或缺失的检查仍不视为通过。' : '问题清单未记录。'; + html.push('

问题与待确认项

', issues.length ? issues.map((issue) => `
${issue.html}
`).join('') : `

${noIssues}

`, '
'); + md.push('## 问题与待确认项', issues.length ? issues.map((issue, index) => `### ${index + 1}\n\n${issue.md}`).join('\n\n') : noIssues); + const footer = `共 ${imageCount} 张可用截图。完整结构化记录见 evidence.json;模型对象明细未展开。`; + html.push(`
`); md.push(footer); + return { + html: `${escape(title)}${html.join('\n')}`, + markdown: `${md.join('\n\n')}\n`, + summary: { projects: projects.length, steps: steps.length, ...counts, screenshots: imageCount, missingScreenshots: imageProblems.length }, + }; +} + +const STYLE = `*{box-sizing:border-box}body{margin:0;background:#eef3f2;color:#223c36;font:15px/1.7 "Microsoft YaHei","Segoe UI",sans-serif}header{padding:36px max(24px,calc((100vw - 1160px)/2));background:#153e34;color:#f5fffb}header h1{font-size:28px;line-height:1.45;margin:4px 0 12px}.eyebrow{font-size:13px;color:#b8dacf;margin:0}.links{display:flex;gap:24px}.links a{color:#d1f4e7}main{max-width:1200px;margin:24px auto;padding:0 20px 40px}section{background:white;border:1px solid #dce7e2;border-radius:12px;padding:28px;margin:20px 0}h2{font-size:22px;margin:0 0 18px}h3{font-size:17px;margin:18px 0 10px}p{margin:10px 0}a{color:#12674f}table{border-collapse:collapse;width:100%;font-size:14px}th,td{border:1px solid #dce7e2;text-align:left;vertical-align:top;padding:10px 12px;overflow-wrap:anywhere}th{background:#edf5f1}tbody tr:nth-child(even){background:#fafcfb}.table-wrap{overflow:auto}.badge{display:inline-block;padding:2px 10px;border-radius:20px;font-size:13px;white-space:nowrap}.pass{color:#07513b;background:#dff5e8}.fail{color:#972328;background:#fee6e8}.unknown{color:#7c4b0d;background:#fff0d5}.info{color:#25566d;background:#e4f1f8}.notice{background:#fff5e1;border-left:4px solid #b5791a;padding:12px 16px;color:#6d4815}.muted{color:#576e65}.stages{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin:20px 0}.stages article{border:1px solid #dce7e2;border-radius:8px;padding:0 16px 12px}.records{margin:8px 0;font-size:13px}.records>div{padding:6px 0;border-bottom:1px solid #edf2ef}.records dt{color:#5b7168}.records dd{margin:0;overflow-wrap:anywhere;white-space:pre-wrap}.gallery{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}figure{margin:0;border:1px solid #dce7e2;border-radius:8px;overflow:hidden;background:#f2f6f4}figure img{width:100%;height:auto;display:block}figcaption{padding:10px 14px;font-size:13px;overflow-wrap:anywhere}.issue{border-left:3px solid #b5791a;padding:0 14px;margin:16px 0}footer{font-size:13px;color:#576e65;margin:28px 0}@media(max-width:760px){header{padding:24px 20px}header h1{font-size:23px}main{padding:0 12px}section{padding:18px}.stages,.gallery{grid-template-columns:1fr}}@media print{body{background:white}header{background:white;color:#153e34;padding:0}header .eyebrow,header .links{display:none}main{max-width:none;padding:0}section{padding:18px 0;border:0;border-radius:0}.gallery{grid-template-columns:1fr}figure{break-inside:avoid}h2,h3{break-after:avoid}.stages{display:block}}`; + +export async function buildModelLiveReport(reportDir = DEFAULT_REPORT_DIR) { + const evidence = JSON.parse((await readFile(path.join(reportDir, 'evidence.json'), 'utf8')).replace(/^\uFEFF/, '')); + const result = renderModelLiveReport(evidence, { reportDir }); + await writeFile(path.join(reportDir, 'index.html'), result.html, 'utf8'); + await writeFile(path.join(reportDir, 'report.md'), result.markdown, 'utf8'); + return result.summary; +} + +if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { + buildModelLiveReport().then((summary) => console.log(JSON.stringify(summary))).catch((error) => { + console.error(`报告生成失败:${error.message}`); + process.exitCode = 1; + }); +} diff --git a/tools/build-scene-live-report.mjs b/tools/build-scene-live-report.mjs new file mode 100644 index 0000000..994f190 --- /dev/null +++ b/tools/build-scene-live-report.mjs @@ -0,0 +1,244 @@ +import fs from 'node:fs' +import path from 'node:path' +import { fileURLToPath } from 'node:url' + +// Evidence is prepared by the real browser run. This script never changes it. +// +// Expected shape (all fields other than `evidence` are optional): +// { +// date, baseURL, browser, role, +// evidence: [{ title, status: 'PASS' | 'FAIL' | string, checks: [], +// screenshot: 'screenshots/example.png', screenshots: [{ path, caption }], details, +// superseded: true /* historical evidence excluded from current pass counts */ }], +// correction: { title, summary, previousConclusion, rootCauses: [], fixes: [], +// verification: [], screenshots: [{ path, caption }] }, +// projects: [{ id, name, finalStatus, finalVersionId, modelId, modelVersionId, +// cover: { image, width, height, bytes, sizeBytes, assetId, sha256, storageUri } }], +// finalListScreenshot, issues, followUpIssues, commands, retainedData, cleanup +// } +// Image values must be report-relative PNG/JPEG/WebP paths. Sensitive fields are removed +// before rendering, so evidence may safely retain raw API responses locally. +const reportDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../reports/scene-live-20260905') +const sourcePath = path.join(reportDir, 'evidence.json') +const sensitiveKey = /password|secret|token|ticket|authorization|cookie|signature|credential|api[_-]?key/i +const cleanText = value => String(value ?? '') + .replace(/\bBearer\s+[^\s"'<>]+/gi, 'Bearer [已隐藏]') + .replace(/(https?:\/\/)[^\s/@]+:[^\s/@]+@/gi, '$1[已隐藏]@') + .replace(/\b((?:access|refresh)?[_-]?token|password|secret|uploadTicket|signature|api[_-]?key|X-Amz-(?:Signature|Credential|Security-Token))\s*[:=]\s*(?:"[^"]*"|'[^']*'|[^\s,;&}]+)/gi, '$1=[已隐藏]') + .replace(/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g, '[已隐藏]') + +function sanitize(value) { + if (typeof value === 'string') return cleanText(value) + if (Array.isArray(value)) return value.map(sanitize) + if (value && typeof value === 'object') { + return Object.fromEntries(Object.entries(value) + .filter(([key]) => !sensitiveKey.test(key)) + .map(([key, item]) => [key, sanitize(item)])) + } + return value +} + +const data = sanitize(JSON.parse(fs.readFileSync(sourcePath, 'utf8').replace(/^\uFEFF/, ''))) +const asArray = value => Array.isArray(value) ? value : value === undefined || value === null ? [] : [value] +const evidence = asArray(data.evidence) +const currentEvidence = evidence.filter(item => item.superseded !== true) +const historicalCount = evidence.length - currentEvidence.length +const correction = data.correction && typeof data.correction === 'object' ? data.correction : null +const projects = asArray(data.projects) +const commands = asArray(data.commands) +const allIssues = asArray(data.issues) +const issueText = issue => typeof issue === 'string' ? issue : JSON.stringify(issue ?? '') +const fsvcTicketFinding = /(?:\bfsvc\b[\s\S]{0,160}(?:upload[\s_-]*ticket|上传票据|票据)|(?:upload[\s_-]*ticket|上传票据|票据)[\s\S]{0,160}\bfsvc\b)/i +const isIndependent = issue => { + if (!issue) return false + if (typeof issue === 'object' + && /^(?:existing|pre-existing|independent|follow-up)$/i.test(issue.scope || issue.category || '')) return true + const text = issueText(issue) + return fsvcTicketFinding.test(text) + || /(?:既存|独立|后续).{0,30}票据|票据.{0,30}(?:既存|独立|后续)/.test(text) +} +const issues = allIssues.filter(issue => !isIndependent(issue)) +const independentIssues = [...new Map([...allIssues.filter(isIndependent), ...asArray(data.followUpIssues)] + .map(issue => [JSON.stringify(issue), issue])).values()] +const passCount = currentEvidence.filter(item => item.status === 'PASS').length +const failCount = currentEvidence.filter(item => item.status === 'FAIL').length +const otherCount = currentEvidence.length - passCount - failCount + +const html = value => cleanText(value).replace(/[&<>"']/g, char => ({ + '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', +})[char]) +const md = value => html(value).replaceAll('\\', '\\\\').replace(/[|\[\]*_`]/g, char => `\\${char}`).replace(/\r?\n/g, ' ') +const url = value => String(value).replaceAll('\\', '/').split('/').map(encodeURIComponent).join('/') +const pretty = value => typeof value === 'string' ? value : JSON.stringify(value, null, 2) +const recorded = value => value === undefined || value === null || value === '' ? '未记录' : value +const statusClass = value => value === 'PASS' ? 'pass' : value === 'FAIL' ? 'fail' : 'neutral' +const imageFields = new Set(['screenshot', 'screenshots', 'coverImage', 'image', 'finalListScreenshot']) +const imagePaths = new Set() + +function imageRefs(value) { + return asArray(value).flatMap(item => { + if (!item) return [] + if (typeof item === 'string') return [{ path: item, caption: '' }] + if (typeof item === 'object') { + const imagePath = item.path || item.src || item.image + if (typeof imagePath === 'string' && imagePath) return [{ path: imagePath, caption: item.caption || item.title || '' }] + } + throw new Error('图片引用应为相对路径字符串或 { path, caption } 对象。') + }) +} + +function collectImages(value) { + if (Array.isArray(value)) return value.forEach(collectImages) + if (!value || typeof value !== 'object') return + for (const [key, item] of Object.entries(value)) { + if (imageFields.has(key)) imageRefs(item).forEach(ref => imagePaths.add(ref.path)) + else collectImages(item) + } +} +collectImages(data) + +// Fail before writing either report when any referenced image is missing or unsafe. +const realReportDir = fs.realpathSync(reportDir) +for (const relative of imagePaths) { + if (path.isAbsolute(relative) || /^[a-z][a-z\d+.-]*:/i.test(relative) + || !/\.(png|jpe?g|webp)$/i.test(relative)) { + throw new Error(`图片必须是报告目录中的 PNG/JPEG/WebP 相对路径:${relative}`) + } + const absolute = path.resolve(reportDir, relative.replaceAll('\\', '/')) + const underRoot = path.relative(reportDir, absolute) + if (underRoot === '..' || underRoot.startsWith(`..${path.sep}`) || path.isAbsolute(underRoot) + || !fs.existsSync(absolute) || !fs.statSync(absolute).isFile() || fs.statSync(absolute).size === 0) { + throw new Error(`图片不存在、为空或越出报告目录:${relative}`) + } + const realRelative = path.relative(realReportDir, fs.realpathSync(absolute)) + if (realRelative === '..' || realRelative.startsWith(`..${path.sep}`) || path.isAbsolute(realRelative)) { + throw new Error(`图片链接目标越出报告目录:${relative}`) + } +} + +function picturesOf(item) { + const refs = [item.screenshot, item.screenshots, item.coverImage].flatMap(imageRefs) + return refs.filter((ref, index) => refs.findIndex(other => other.path === ref.path) === index) + .map(ref => item.superseded === true + ? { ...ref, caption: `历史截图(不作为修复后的视觉通过证据):${ref.caption || '原测试现场'}` } + : ref) +} +const coverOf = project => imageRefs(project.cover?.image || project.coverImage || project.cover?.screenshot)[0] +const finalList = imageRefs(data.finalListScreenshot)[0] || [...evidence].reverse() + .filter(item => /(?:最终|倒序|排序).*列表|列表.*(?:最终|倒序|排序)/.test(item.title || '')) + .flatMap(picturesOf)[0] +const figure = (ref, caption, className = '') => ref + ? `
${html(ref.caption || caption)}
${html(ref.caption || caption)} · 点击查看原图
` + : '

尚未记录本地图片。

' +const mdImage = (ref, caption) => ref + ? `[![${md(ref.caption || caption)}](${url(ref.path)})](${url(ref.path)})` + : '尚未记录本地图片。' +const extraOf = item => Object.fromEntries(Object.entries(item) + .filter(([key]) => !['title', 'status', 'checks', 'screenshot', 'screenshots', 'coverImage'].includes(key))) +const checkText = check => typeof check === 'string' ? check : pretty(check) +const evidenceStatus = item => item.superseded === true ? '历史记录(已更正)' : recorded(item.status) +const correctionSections = correction ? [ + ['原结论与漏验', asArray(correction.previousConclusion)], + ['根因', asArray(correction.rootCauses)], + ['修复内容', asArray(correction.fixes)], + ['修复后验证', asArray(correction.verification)], +].filter(([, items]) => items.length) : [] +const correctionPictures = correction ? picturesOf(correction) : [] +const correctionHtml = correction ? `

${html(correction.title || '狐狸场景验证更正')}

${correction.summary ? `

${html(correction.summary)}

` : ''}${correctionSections.map(([title, items]) => `

${html(title)}

`).join('')}
${correctionPictures.map(ref => figure(ref, '修复后视觉验证')).join('')}

下方标为“历史记录(已更正)”的检查及截图保留用于追溯,不计入当前通过率,也不作为狐狸已经可见的证据。

` : '' +const correctionMarkdown = correction ? [ + `## ${md(correction.title || '狐狸场景验证更正')}`, '', + ...(correction.summary ? [`> **测试结论更正:** ${md(correction.summary)}`, ''] : []), + ...correctionSections.flatMap(([title, items]) => [`### ${md(title)}`, '', ...items.map(item => `- ${md(checkText(item))}`), '']), + ...correctionPictures.flatMap(ref => [mdImage(ref, '修复后视觉验证'), '']), + '下方标为“历史记录(已更正)”的检查及截图保留用于追溯,不计入当前通过率,也不作为狐狸已经可见的证据。', '', +] : [] +const projectStatus = project => recorded(project.finalStatus || project.status) +const projectVersion = project => recorded(project.finalVersionId || project.currentVersionId || project.cover?.versionId) +const commandParts = item => typeof item === 'string' + ? { command: item, result: '未记录执行结果' } + : { command: item.command || item.cmd || item.name || '命令未记录', + result: pretty(Object.fromEntries(Object.entries(item).filter(([key]) => !['command', 'cmd', 'name'].includes(key)))) } +const featureText = '场景保存截图封面及列表按创建时间倒序的功能已实施。本报告记录使用现有模型创建真实场景、保存当前三维视口封面及异常回退的实际验证结果。' +const environment = `${recorded(data.date)} · ${recorded(data.baseURL)} · ${recorded(data.browser)} · ${recorded(data.role)}` +const retainedText = data.retainedData ? pretty(data.retainedData) : projects.length + ? `本次创建的 ${projects.length} 条场景保留在开发环境:${projects.map(project => `${project.id}(${project.name || '未命名'})`).join('、')}。模型引用固定到下表记录的已发布版本。` + : '尚未记录保留场景。' +const cleanupText = data.cleanup ? pretty(data.cleanup) : '未记录额外清理操作;报告不据此宣称测试文件或历史版本已删除。' +const limitations = [ + '手动保存从当前三维视口生成封面;新封面与场景内容、模型引用在同一次工程更新中关联保存。发布前的保存沿用该流程。', + '截图或封面上传失败时保留旧封面;工程是否保存成功以实际更新请求为准。版本冲突不覆盖其他已保存的内容。', + '自动恢复及重新打开工程不生成或上传新封面;恢复后的修改需由用户保存后更新封面。', + '列表按创建时间倒序展示。再次保存不会改变创建时间,也不应因此改变创建时间排序。', + ...asArray(data.limitations).map(checkText), +] +const independentText = '既存受控文件资产的 fsvc URI 分支未完整覆盖上传票据绑定校验,属于本次场景封面变更前已存在的问题。本次保留现有流程,后续应独立补齐校验并验证历史资产、版本复制与引用兼容性;不计入本次场景功能失败数。' +const countText = `当前证据项通过 ${passCount} / ${currentEvidence.length};失败 ${failCount};其他或未标注 ${otherCount};已更正历史记录 ${historicalCount};已校验图片文件 ${imagePaths.size}。` + +const outputHtml = ` + +真实场景与截图封面验证报告 · ${html(data.date)} +
+
SCENE LIVE · 功能已实施

真实场景与截图封面验证报告

${html(featureText)}

${html(environment)}

Markdown 报告
+${correctionHtml} +
${passCount} / ${currentEvidence.length}当前证据项通过
${failCount}失败
${otherCount}其他或未标注
${historicalCount ? `
${historicalCount}已更正历史记录
` : ''}
${imagePaths.size}图片文件已校验
+

保留场景与封面证据

${projects.map(project => { + const cover = project.cover || {} + return `

${html(project.name || `场景 ${project.id}`)}

${figure(coverOf(project), `场景 ${project.id} 保存后封面回读证据`, 'cover-image')}
场景 / 状态
${html(project.id)} / ${html(projectStatus(project))}
当前工程版本
${html(projectVersion(project))}
引用模型 / 版本
${html(recorded(project.modelId))} / ${html(recorded(project.modelVersionId))}
封面大小
${html(recorded(cover.sizeBytes ?? cover.bytes))} 字节${cover.width && cover.height ? ` · ${html(cover.width)} × ${html(cover.height)}` : ''}
封面持久化与项目证据
${html(pretty(project))}
` +}).join('') || '

尚未记录场景项目。

'}
+

最终列表与创建时间倒序

${figure(finalList, '保留场景的实际封面与创建时间倒序列表')}
+

逐项验证记录

通过数仅统计未被更正且 status 明确为 PASS 的当前证据项;历史记录单独标注。checks 用于展示实际断言,不重复累加。故障注入中的预期错误响应不等于用例失败;缺少状态时不推断通过。图片文件存在校验不等于视觉内容验证。

${evidence.map((item, index) => { + const pictures = picturesOf(item) + const extra = extraOf(item) + return `

${index + 1}. ${html(item.title || '未命名检查')}

${html(evidenceStatus(item))}
${asArray(item.checks).length ? `
    ${asArray(item.checks).map(check => `
  • ${html(checkText(check))}
  • `).join('')}
` : ''}${Object.keys(extra).length ? `
检查详情
${html(pretty(extra))}
` : ''}
${pictures.map(ref => figure(ref, /\.jpe?g$/i.test(ref.path) ? '实际生成的场景封面' : '浏览器现场')).join('')}
` +}).join('') || '

尚未记录验证结果。

'}
+

数据保留与清理

${html(retainedText)}
${projects.map(project => ``).join('')}
场景模型 / 发布版本最终状态当前版本
${html(project.id)} · ${html(project.name)}${html(recorded(project.modelId))} / ${html(recorded(project.modelVersionId))}${html(projectStatus(project))}${html(projectVersion(project))}
${html(cleanupText)}
+

本次问题记录

${issues.length ? issues.map(issue => `
${html(pretty(issue))}
`).join('') : '

当前证据未登记本次新增的未解决问题。

'}
+

后续独立事项

${html(independentText)}

${independentIssues.map(issue => `
${html(pretty(issue))}
`).join('')}
+

实际命令与结果

${commands.length ? commands.map(item => { const entry = commandParts(item); return `

${html(entry.command)}

${html(entry.result)}
` }).join('') : '

evidence.json 尚未记录命令结果;不据此宣称构建或命令行测试通过。

'}
+

当前行为与限制

+ +
` + +const outputMarkdown = [ + '# 真实场景与截图封面验证报告', '', featureText, '', md(environment), '', ...correctionMarkdown, countText, '', + '## 保留场景与封面证据', '', + ...projects.flatMap(project => [ + `### ${md(project.name || `场景 ${project.id}`)}`, '', + `场景 ${md(project.id)};状态 ${md(projectStatus(project))};当前版本 ${md(projectVersion(project))};引用模型 ${md(recorded(project.modelId))} / 发布版本 ${md(recorded(project.modelVersionId))}。`, '', + mdImage(coverOf(project), `场景 ${project.id} 保存后封面回读证据`), '', + '
封面持久化与项目证据', '', '
', html(pretty(project)), '
', '', '
', '', + ]), + '## 最终列表与创建时间倒序', '', mdImage(finalList, '保留场景的封面与创建时间倒序列表'), '', + '## 逐项验证记录', '', + '通过数仅统计未被更正且 status 明确为 PASS 的当前证据项;历史记录单独标注。checks 不重复累加。预期故障响应不等于用例失败,缺少状态不推断通过。图片文件存在校验不等于视觉内容验证。', '', + '| 序号 | 检查项 | 结果 | 图片 |', '|---|---|---|---|', + ...evidence.map((item, index) => `| ${index + 1} | ${md(item.title || '未命名检查')} | ${md(evidenceStatus(item))} | ${picturesOf(item).map((ref, i) => `[图片 ${i + 1}](${url(ref.path)})`).join(' · ') || '—'} |`), '', + ...evidence.flatMap((item, index) => [ + `### ${index + 1}. ${md(item.title || '未命名检查')} · ${md(evidenceStatus(item))}`, '', + ...asArray(item.checks).map(check => `- ${md(checkText(check))}`), '', + ...(Object.keys(extraOf(item)).length ? ['
检查详情', '', '
', html(pretty(extraOf(item))), '
', '', '
', ''] : []), + ...picturesOf(item).flatMap(ref => [mdImage(ref, '验证现场'), '']), + ]), + '## 数据保留与清理', '', '
', html(retainedText), '
', '', + '| 场景 | 模型 / 发布版本 | 最终状态 | 当前版本 |', '|---|---|---|---|', + ...projects.map(project => `| ${md(project.id)} · ${md(project.name)} | ${md(recorded(project.modelId))} / ${md(recorded(project.modelVersionId))} | ${md(projectStatus(project))} | ${md(projectVersion(project))} |`), '', + '
', html(cleanupText), '
', '', + '## 本次问题记录', '', + ...(issues.length ? issues.flatMap(issue => ['
', html(pretty(issue)), '
', '']) : ['当前证据未登记本次新增的未解决问题。', '']), + '## 后续独立事项', '', independentText, '', + ...independentIssues.flatMap(issue => ['
', html(pretty(issue)), '
', '']), + '## 实际命令与结果', '', + ...(commands.length ? commands.flatMap(item => { const entry = commandParts(item); return [`**${md(entry.command)}**`, '', '
', html(entry.result), '
', ''] }) + : ['evidence.json 尚未记录命令结果;不据此宣称构建或命令行测试通过。', '']), + '## 当前行为与限制', '', ...limitations.map(item => `- ${item}`), '', + '报告来自 evidence.json,未修改原始证据;所有引用图片已校验存在且非空,点击可查看原图。通过数随证据更新。', '', +].join('\n') + +fs.writeFileSync(path.join(reportDir, 'index.html'), outputHtml, 'utf8') +fs.writeFileSync(path.join(reportDir, 'report.md'), outputMarkdown, 'utf8') +console.log(JSON.stringify({ report: 'reports/scene-live-20260905/index.html', passed: passCount, + total: currentEvidence.length, historical: historicalCount, failed: failCount, other: otherCount, imagesValidated: imagePaths.size, + projectsRecorded: projects.length, commandsRecorded: commands.length })) diff --git a/tools/model-cover-api.test.mjs b/tools/model-cover-api.test.mjs new file mode 100644 index 0000000..2e9de33 --- /dev/null +++ b/tools/model-cover-api.test.mjs @@ -0,0 +1,272 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; +import { + ModelApiError, + ModelContentProjectSession, +} from '../../unreal_tran/src/model-content-api.js'; + +const clone = value => structuredClone(value); +const jpeg = () => new Blob(['test-jpeg'], { type: 'image/jpeg' }); +const deferred = () => { + let resolve; + let reject; + const promise = new Promise((yes, no) => { resolve = yes; reject = no; }); + return { promise, resolve, reject }; +}; +const tick = () => new Promise(resolve => setImmediate(resolve)); +const oldCoverUri = `content://sha256/${'b'.repeat(64)}`; +const initialDocument = () => ({ + schema: 'digital-twin-editor-project', + version: 4, + name: 'Original model', + modelId: 'test-model', + modelResource: { + kind: 'imported', + assetCode: 'MODEL_MAIN', + code: 'MODEL_MAIN', + storageUri: `content://sha256/${'a'.repeat(64)}`, + sourceName: 'model.glb', + }, + model: { objects: {} }, + camera: { position: [1, 2, 3], target: [0, 0, 0] }, +}); + +async function fixture() { + const state = { + id: '876', + type: 'MODEL', + code: 'MODEL_TEST', + name: 'Original model', + description: 'Cover transaction test', + categoryCode: 'EQUIPMENT', + status: 'DRAFT', + version: 7, + coverUri: oldCoverUri, + content: initialDocument(), + assets: [ + { + id: '101', code: 'MODEL_MAIN', name: 'model.glb', type: 'MODEL_FILE', + storageUri: `content://sha256/${'a'.repeat(64)}`, mimeType: 'model/gltf-binary', + sizeBytes: 100, sha256: 'a'.repeat(64), metadata: {}, status: 'READY', sortOrder: 0, + }, + { + id: '102', code: 'MODEL_COVER', name: 'Old cover', type: 'IMAGE', + storageUri: oldCoverUri, mimeType: 'image/jpeg', + sizeBytes: 40, sha256: 'b'.repeat(64), metadata: {}, status: 'READY', sortOrder: 1, + }, + ], + dependencies: [], + }; + const controls = { postError: null, putError: null, postBarrier: null, putBarrier: null }; + const requests = []; + const tickets = new Map(); + let uploadCount = 0; + const response = () => ({ + project: { ...clone(state), content: undefined, assets: undefined, currentVersionId: String(700 + state.version) }, + currentVersion: { + id: String(700 + state.version), versionNo: state.version, + content: clone(state.content), assets: clone(state.assets), dependencies: clone(state.dependencies), + }, + }); + const client = { + async request(path, options = {}) { + const method = options.method ?? 'GET'; + assert.ok(path === '/content/projects/876' || path === '/content/projects/876/assets/upload'); + if (method === 'GET') return response(); + if (method === 'POST') { + assert.equal(path, '/content/projects/876/assets/upload'); + const form = options.body; + const request = { + method, version: Number(form.get('projectVersion')), + code: form.get('code'), type: form.get('type'), + file: form.get('file'), sortOrder: Number(form.get('sortOrder')), + metadata: JSON.parse(form.get('metadata')), + }; + requests.push(request); + if (controls.postBarrier) await controls.postBarrier.promise; + if (controls.postError) throw controls.postError; + assert.equal(request.version, state.version, 'upload must use the current project version'); + uploadCount += 1; + const sha256 = String(uploadCount + 2).repeat(64); + const asset = { + code: request.code, name: form.get('name'), type: request.type, + storageUri: `content://sha256/${sha256}`, mimeType: request.file.type, + sizeBytes: request.file.size, sha256, metadata: request.metadata, + status: 'READY', sortOrder: request.sortOrder, uploadTicket: `cover-ticket-${uploadCount}`, + }; + tickets.set(asset.uploadTicket, clone(asset)); + return clone(asset); + } + assert.equal(method, 'PUT'); + const payload = clone(options.json); + requests.push({ method, payload }); + if (controls.putBarrier) await controls.putBarrier.promise; + if (controls.putError) throw controls.putError; + assert.equal(payload.version, state.version, 'save must use the current project version'); + assert.equal(new Set(payload.assets.map(asset => asset.code)).size, payload.assets.length); + for (const asset of payload.assets) { + if (!asset.uploadTicket) continue; + const uploaded = tickets.get(asset.uploadTicket); + assert.ok(uploaded, 'each upload ticket must exist and be consumed once'); + assert.equal(asset.storageUri, uploaded.storageUri); + tickets.delete(asset.uploadTicket); + } + state.version += 1; + state.name = payload.name; + state.content = clone(payload.content); + state.coverUri = payload.coverUri; + state.assets = payload.assets.map((asset, index) => { + const persisted = { ...asset, id: String(200 + index), versionId: String(700 + state.version) }; + delete persisted.uploadTicket; + return persisted; + }); + return response(); + }, + }; + const api = new ModelContentProjectSession({ projectId: state.id, client }); + await api.loadProject(); + api.markDocumentLoaded(state.content); + return { api, state, controls, requests, tickets }; +} + +test('persists edited content and the uploaded cover in one PUT, replacing fixed MODEL_COVER', async () => { + const f = await fixture(); + const document = { ...initialDocument(), name: 'Edited model' }; + await f.api.queueSave(document, { coverImage: jpeg() }); + assert.deepEqual(f.requests.map(request => request.method), ['POST', 'PUT']); + const post = f.requests[0]; + assert.equal(post.code, 'MODEL_COVER'); + assert.equal(post.type, 'IMAGE'); + assert.equal(post.file.name, 'model-cover.jpg'); + assert.equal(post.file.type, 'image/jpeg'); + assert.equal(post.sortOrder, 1); + assert.equal(post.metadata.usage, 'model-cover'); + const payload = f.requests[1].payload; + assert.equal(payload.content.name, 'Edited model'); + assert.equal(payload.assets.length, 2); + const cover = payload.assets.find(asset => asset.code === 'MODEL_COVER'); + assert.equal(payload.coverUri, cover.storageUri); + assert.equal(cover.uploadTicket, 'cover-ticket-1'); + assert.equal(f.api.project.coverUri, payload.coverUri); + assert.equal(f.api.project.version, 8); + assert.equal(f.api.pendingUploads.size, 0); + assert.equal(f.tickets.size, 0); + + await f.api.queueSave(document, { coverImage: jpeg() }); + assert.equal(f.state.assets.filter(asset => asset.code === 'MODEL_COVER').length, 1); + assert.notEqual(f.state.coverUri, payload.coverUri); + assert.equal(f.state.assets.find(asset => asset.code === 'MODEL_MAIN').storageUri, initialDocument().modelResource.storageUri); +}); + +test('cover POST failure still saves edited content with the previous cover', async () => { + const f = await fixture(); + const error = new ModelApiError('upload unavailable', 'SERVER_ERROR', '', 503); + f.controls.postError = error; + const warnings = []; + await f.api.queueSave({ ...initialDocument(), name: 'Content survives' }, { + coverImage: jpeg(), onCoverError: value => warnings.push(value), + }); + assert.deepEqual(warnings, [error]); + assert.deepEqual(f.requests.map(request => request.method), ['POST', 'PUT']); + assert.equal(f.state.content.name, 'Content survives'); + assert.equal(f.state.coverUri, oldCoverUri); + assert.equal(f.requests[1].payload.assets.some(asset => asset.uploadTicket), false); +}); + +test('cover POST 409 stops the transaction before any PUT', async () => { + const f = await fixture(); + const error = new ModelApiError('version conflict', 'CONFLICT', '', 409); + f.controls.postError = error; + const previous = clone(f.api.project); + let warnings = 0; + await assert.rejects(f.api.queueSave({ ...initialDocument(), name: 'Stale content' }, { + coverImage: jpeg(), onCoverError: () => { warnings += 1; }, + }), actual => actual === error); + assert.deepEqual(f.requests.map(request => request.method), ['POST']); + assert.deepEqual(f.api.project, previous); + assert.equal(warnings, 0); +}); + +for (const status of [409, 503]) { + test(`final PUT ${status} preserves the old cover and cannot leak its ticket into a later autosave`, async () => { + const f = await fixture(); + const error = new ModelApiError('save failed', 'SAVE_FAILED', '', status); + f.controls.putError = error; + const previous = clone(f.api.project); + const fingerprint = f.api.lastSavedFingerprint; + const document = { ...initialDocument(), name: 'Still unsaved' }; + await assert.rejects(f.api.queueSave(document, { coverImage: jpeg() }), actual => actual === error); + assert.deepEqual(f.api.project, previous); + assert.equal(f.api.lastSavedFingerprint, fingerprint); + assert.equal(f.api.pendingUploads.size, 0); + f.controls.putError = null; + await f.api.queueSave(document); + const later = f.requests.at(-1).payload; + assert.equal(later.coverUri, oldCoverUri); + assert.equal(later.assets.some(asset => asset.uploadTicket), false); + assert.equal(f.state.coverUri, oldCoverUri); + assert.equal(f.requests.filter(request => request.method === 'POST').length, 1); + }); +} + +test('automatic saves never upload a cover, and unchanged content skips PUT before and after cover replacement', async () => { + const f = await fixture(); + const document = initialDocument(); + await f.api.queueSave(document); + assert.equal(f.requests.length, 0); + document.name = 'Automatic content edit'; + await f.api.queueSave(document); + await f.api.queueSave(document); + assert.deepEqual(f.requests.map(request => request.method), ['PUT']); + await f.api.queueSave(document, { coverImage: jpeg() }); + const count = f.requests.length; + await f.api.queueSave(document); + assert.equal(f.requests.length, count, 'consumed cover ticket must not cause another save'); +}); + +test('asynchronous JPEG encoding owns the queue until upload and final PUT finish', async () => { + const f = await fixture(); + const image = deferred(); + const postBarrier = deferred(); + f.controls.postBarrier = postBarrier; + const first = f.api.queueSave({ ...initialDocument(), name: 'Manual snapshot' }, { coverImage: image.promise }); + const laterDocument = { ...initialDocument(), name: 'Later automatic snapshot' }; + const later = f.api.queueSave(laterDocument); + laterDocument.name = 'Mutation after enqueue must not leak'; + await tick(); + assert.equal(f.requests.length, 0, 'later autosave cannot pass pending JPEG encoding'); + image.resolve(jpeg()); + await tick(); + assert.deepEqual(f.requests.map(request => request.method), ['POST']); + postBarrier.resolve(); + await Promise.all([first, later]); + assert.deepEqual(f.requests.map(request => request.method), ['POST', 'PUT', 'PUT']); + assert.equal(f.requests[0].version, 7); + assert.equal(f.requests[1].payload.version, 7); + assert.equal(f.requests[2].payload.version, 8); + assert.equal(f.requests[1].payload.content.name, 'Manual snapshot'); + assert.equal(f.state.content.name, 'Later automatic snapshot'); + assert.equal(f.requests[2].payload.coverUri, f.requests[1].payload.coverUri); +}); + +test('JPEG rejection while another save owns the queue is observed immediately and falls back safely', async () => { + const f = await fixture(); + const barrier = deferred(); + f.controls.putBarrier = barrier; + const first = f.api.queueSave({ ...initialDocument(), name: 'First save' }); + await tick(); + const captureError = new Error('JPEG encoding failed'); + const image = deferred(); + const warnings = []; + const later = f.api.queueSave({ ...initialDocument(), name: 'Fallback content' }, { + coverImage: image.promise, onCoverError: error => warnings.push(error), + }); + image.reject(captureError); + await tick(); + barrier.resolve(); + await Promise.all([first, later]); + assert.deepEqual(warnings, [captureError]); + assert.deepEqual(f.requests.map(request => request.method), ['PUT', 'PUT']); + assert.equal(f.state.content.name, 'Fallback content'); + assert.equal(f.state.coverUri, oldCoverUri); +}); diff --git a/tools/model-cover-capture.test.mjs b/tools/model-cover-capture.test.mjs new file mode 100644 index 0000000..ffc0c0d --- /dev/null +++ b/tools/model-cover-capture.test.mjs @@ -0,0 +1,141 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; +import { captureModelCover } from '../../unreal_tran/src/model-cover-capture.js'; + +function fixture({ width = 1600, height = 900, drawError, renderError, encodeError, blob } = {}) { + const events = []; + const selectionHelper = { visible: true }; + const transformHelper = { visible: false }; + const grid = { visible: true }; + const originalVisibility = [true, false, true]; + const visibility = () => [selectionHelper.visible, transformHelper.visible, grid.visible]; + const scene = {}; + const camera = Object.freeze({ position: Object.freeze({ x: 1, y: 2, z: 3 }) }); + const modelPivot = {}; + const source = { width, height }; + let renders = 0; + const renderer = { + domElement: source, + render(actualScene, actualCamera) { + assert.equal(actualScene, scene); + assert.equal(actualCamera, camera); + events.push({ operation: 'render', visibility: visibility() }); + renders += 1; + if (renders === 1 && renderError) throw renderError; + }, + }; + const editor = { + renderer, scene, camera, modelPivot, selectionHelper, grid, + transform: { getHelper: () => transformHelper }, + selected: { name: 'selected-model-node' }, + }; + const canvas = { + width: 0, + height: 0, + getContext(kind) { + assert.equal(kind, '2d'); + return { + drawImage(...args) { + events.push({ operation: 'copy', visibility: visibility() }); + assert.deepEqual(args, [source, 0, 0, canvas.width, canvas.height]); + if (drawError) throw drawError; + }, + }; + }, + toBlob(callback, type, quality) { + events.push({ operation: 'encode', visibility: visibility(), type, quality }); + if (encodeError) throw encodeError; + queueMicrotask(() => callback(blob === undefined ? new Blob(['jpeg'], { type }) : blob)); + }, + }; + const document = { createElement: tag => { assert.equal(tag, 'canvas'); return canvas; } }; + return { editor, canvas, document, events, visibility, originalVisibility }; +} + +test('copies the helper-free frame synchronously, restores the view, then encodes JPEG', async () => { + const f = fixture(); + const selected = f.editor.selected; + const pending = captureModelCover(f.editor, { document: f.document }); + // No await has occurred: copying and restoration must already be complete. + assert.deepEqual(f.events.map(event => event.operation), ['render', 'copy', 'render', 'encode']); + assert.deepEqual(f.events[0].visibility, [false, false, false]); + assert.deepEqual(f.events[1].visibility, [false, false, false]); + assert.deepEqual(f.events[2].visibility, f.originalVisibility); + assert.deepEqual(f.events[3].visibility, f.originalVisibility); + assert.equal(f.events[3].type, 'image/jpeg'); + assert.equal(f.events[3].quality, 0.85); + assert.equal(f.editor.selected, selected); + assert.deepEqual(f.editor.camera.position, { x: 1, y: 2, z: 3 }); + const result = await pending; + assert.equal(result.type, 'image/jpeg'); + assert.equal(result.size, 4); +}); + +for (const { width, height, maxWidth, expected } of [ + { width: 1600, height: 900, expected: [640, 360] }, + { width: 900, height: 1600, expected: [360, 640] }, + { width: 320, height: 180, expected: [320, 180] }, + { width: 1600, height: 900, maxWidth: 320, expected: [320, 180] }, +]) { + test(`bounds a ${width} x ${height} view at ${maxWidth ?? 640} pixels without stretching`, async () => { + const f = fixture({ width, height }); + await captureModelCover(f.editor, { document: f.document, maxWidth }); + assert.deepEqual([f.canvas.width, f.canvas.height], expected); + }); +} + +for (const failure of ['drawError', 'renderError']) { + test(`restores every helper and redraws the original viewport after ${failure}`, async () => { + const error = new Error(failure); + const f = fixture({ [failure]: error }); + await assert.rejects(captureModelCover(f.editor, { document: f.document }), actual => actual === error); + assert.deepEqual(f.visibility(), f.originalVisibility); + assert.equal(f.events.at(-1).operation, 'render'); + assert.deepEqual(f.events.at(-1).visibility, f.originalVisibility); + assert.equal(f.events.some(event => event.operation === 'encode'), false); + }); +} + +test('restores a helper referenced in more than one editor slot exactly once', async () => { + const f = fixture(); + f.editor.transform.getHelper = () => f.editor.selectionHelper; + await captureModelCover(f.editor, { document: f.document }); + assert.equal(f.editor.selectionHelper.visible, true); + assert.equal(f.editor.grid.visible, true); +}); + +for (const blob of [null, new Blob([])]) { + test(`rejects ${blob === null ? 'missing' : 'empty'} encoded images after restoring the viewport`, async () => { + const f = fixture({ blob }); + await assert.rejects(captureModelCover(f.editor, { document: f.document }), /empty image/); + assert.deepEqual(f.visibility(), f.originalVisibility); + }); +} + +test('propagates encoder errors with the original viewport already restored', async () => { + const error = new Error('encoding failed'); + const f = fixture({ encodeError: error }); + await assert.rejects(captureModelCover(f.editor, { document: f.document }), actual => actual === error); + assert.deepEqual(f.visibility(), f.originalVisibility); +}); + +test('rejects unready viewports and invalid sizes before touching editor helpers', async () => { + for (const change of [ + f => { f.editor.renderer = null; }, + f => { f.editor.renderer.domElement.width = 0; }, + f => { f.editor.renderer.domElement.height = Number.NaN; }, + f => { f.editor.scene = null; }, + f => { f.editor.camera = null; }, + f => { f.editor.modelPivot = null; }, + ]) { + const f = fixture(); + change(f); + await assert.rejects(captureModelCover(f.editor, { document: f.document }), /not ready/); + assert.deepEqual(f.visibility(), f.originalVisibility); + assert.equal(f.events.length, 0); + } + const f = fixture(); + await assert.rejects(captureModelCover(f.editor, { document: f.document, maxWidth: 0 }), /positive/); + assert.deepEqual(f.visibility(), f.originalVisibility); + assert.equal(f.events.length, 0); +}); diff --git a/tools/scene-cover-api.test.mjs b/tools/scene-cover-api.test.mjs new file mode 100644 index 0000000..a879331 --- /dev/null +++ b/tools/scene-cover-api.test.mjs @@ -0,0 +1,207 @@ +import assert from 'node:assert/strict' +import test from 'node:test' +import { readFileSync } from 'node:fs' +import { createRequire } from 'node:module' + +const requireWeb = createRequire(new URL('../../unreal_tran_web/package.json', import.meta.url)) +const ts = requireWeb('typescript') +const source = readFileSync(new URL('../../unreal_tran_web/src/features/scene-legacy/contentApiClient.ts', import.meta.url), 'utf8') +const compiled = ts.transpileModule(source, { compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext } }).outputText +const { LegacySceneContentApiClient, LegacySceneOperationQueue, saveSceneDocumentWithCover } = await import(`data:text/javascript;base64,${Buffer.from(compiled).toString('base64')}`) +const clone = value => structuredClone(value) +const jpeg = () => new Blob(['scene screenshot'], { type: 'image/jpeg' }) +const oldUri = `content://sha256/${'a'.repeat(64)}` +const defer = () => { + let resolve, reject + const promise = new Promise((yes, no) => { resolve = yes; reject = no }) + return { promise, resolve, reject } +} + +function fixture() { + const state = { + id: '987', type: 'SCENE', code: 'SCENE_TEST', name: 'Test scene', description: '', categoryCode: 'OUTDOOR', + version: 7, status: 'DRAFT', currentVersionId: '107', publishedVersionId: '106', coverUri: oldUri, + content: { objects: [] }, dependencies: [], + assets: [{ id: '200', code: 'SCENE_COVER', name: 'Old cover', type: 'IMAGE', storageUri: oldUri, + mimeType: 'image/jpeg', sizeBytes: 12, sha256: 'a'.repeat(64), metadata: {}, status: 'READY', sortOrder: 2 }], + } + const controls = { uploadStatus: 200, putStatus: 200, uploadBarrier: null, uploadPatch: null } + const requests = [] + const published = clone(state) + const client = new LegacySceneContentApiClient(state.id, { + tokenStorage: { accessToken: () => '', refreshToken: () => '', store() {}, clear() {}, notifyExpired() {} }, + lockManager: null, + fetchImpl: async (url, init) => { + const reply = (status, data) => new Response(JSON.stringify({ code: status, message: status >= 400 ? 'test failure' : 'ok', data }), { status }) + if (init.method === 'POST') { + assert.equal(url, '/api/tran/v1/content/projects/987/assets/upload') + const form = init.body + requests.push({ method: 'POST', version: Number(form.get('projectVersion')), code: form.get('code'), + type: form.get('type'), file: form.get('file'), metadata: JSON.parse(form.get('metadata')) }) + if (controls.uploadBarrier) await controls.uploadBarrier.promise + if (controls.uploadStatus !== 200) return reply(controls.uploadStatus, null) + assert.equal(Number(form.get('projectVersion')), state.version) + return reply(200, { code: form.get('code'), name: form.get('name'), type: form.get('type'), + storageUri: `content://sha256/${'b'.repeat(64)}`, mimeType: form.get('file').type, sizeBytes: form.get('file').size, + sha256: 'b'.repeat(64), metadata: JSON.parse(form.get('metadata')), status: 'READY', + sortOrder: Number(form.get('sortOrder')), uploadTicket: 'scene-cover-ticket', ...controls.uploadPatch }) + } + assert.equal(init.method, 'PUT') + const body = JSON.parse(init.body) + requests.push({ method: 'PUT', body }) + if (controls.putStatus !== 200) return reply(controls.putStatus, null) + assert.equal(body.version, state.version) + Object.assign(state, clone(body), { version: state.version + 1 }) + state.assets.forEach(asset => { delete asset.uploadTicket }) + return reply(200, state) + }, + }) + return { client, state, controls, requests, published } +} + +test('scene image ticket, fixed asset replacement, dependencies and coverUri commit in one versioned PUT', async () => { + const f = fixture() + const original = clone(f.state) + const document = { objects: [{ targetProjectId: '156', targetVersionId: '184', position: [2, 0, 0] }] } + const saved = await saveSceneDocumentWithCover(f.client, original, document, { image: jpeg() }) + assert.deepEqual(f.requests.map(r => r.method), ['POST', 'PUT']) + assert.equal(f.requests[0].code, 'SCENE_COVER') + assert.equal(f.requests[0].type, 'IMAGE') + assert.equal(f.requests[0].file.type, 'image/jpeg') + assert.equal(f.requests[0].file.name, 'scene-cover.jpg') + assert.equal(f.requests[0].metadata.usage, 'scene-cover') + const put = f.requests[1].body + assert.equal(put.assets.length, 1) + assert.equal(put.assets[0].uploadTicket, 'scene-cover-ticket') + assert.equal(put.assets[0].sortOrder, 2) + assert.equal(put.coverUri, put.assets[0].storageUri) + assert.deepEqual(put.content, document) + assert.deepEqual(put.dependencies, [{ targetProjectId: '156', targetVersionId: '184', relationType: 'SCENE_MODEL', required: true }]) + assert.equal(saved.project.version, 8) + assert.equal(saved.coverFailed, false) + assert.deepEqual(original, f.published, 'input and immutable published snapshot remain unchanged') +}) + +test('capture failure saves content with the previous cover and reports a warning result', async () => { + const f = fixture() + const saved = await saveSceneDocumentWithCover(f.client, clone(f.state), { objects: [], label: 'edited' }, { error: new Error('tainted canvas') }) + assert.deepEqual(f.requests.map(r => r.method), ['PUT']) + assert.equal(saved.coverFailed, true) + assert.equal(saved.project.coverUri, oldUri) + assert.equal(saved.project.content.label, 'edited') +}) + +test('upload failure keeps the previous cover but still saves scene content once', async () => { + const f = fixture() + f.controls.uploadStatus = 503 + const saved = await saveSceneDocumentWithCover(f.client, clone(f.state), { objects: [], label: 'edited' }, { image: jpeg() }) + assert.deepEqual(f.requests.map(r => r.method), ['POST', 'PUT']) + assert.equal(saved.coverFailed, true) + assert.equal(saved.project.coverUri, oldUri) + assert.equal(f.requests[1].body.assets[0].uploadTicket, undefined) +}) + +test('upload conflict propagates without any content PUT', async () => { + const f = fixture() + f.controls.uploadStatus = 409 + await assert.rejects(saveSceneDocumentWithCover(f.client, clone(f.state), { objects: [] }, { image: jpeg() }), error => error.status === 409) + assert.deepEqual(f.requests.map(r => r.method), ['POST']) + assert.equal(f.state.version, 7) +}) + +for (const status of [409, 503]) { + test(`final PUT ${status} keeps old project and never leaks the ticket into a later plain save`, async () => { + const f = fixture() + const original = clone(f.state) + f.controls.putStatus = status + await assert.rejects(saveSceneDocumentWithCover(f.client, original, { objects: [], label: 'failed' }, { image: jpeg() }), error => error.status === status) + assert.deepEqual(original, f.published) + assert.deepEqual(f.state, f.published) + f.controls.putStatus = 200 + const saved = await saveSceneDocumentWithCover(f.client, original, { objects: [], label: 'plain' }) + assert.equal(saved.project.coverUri, oldUri) + assert.equal(f.requests.at(-1).body.assets[0].uploadTicket, undefined) + assert.deepEqual(f.requests.map(r => r.method), ['POST', 'PUT', 'PUT']) + }) +} + +test('malformed image upload response is treated as optional cover failure', async () => { + const f = fixture() + f.controls.uploadPatch = { storageUri: 'blob:temporary' } + const saved = await saveSceneDocumentWithCover(f.client, clone(f.state), { objects: [] }, { image: jpeg() }) + assert.equal(saved.coverFailed, true) + assert.equal(saved.project.coverUri, oldUri) +}) + +test('switching project while upload is pending prevents the old document PUT', async () => { + const f = fixture() + f.controls.uploadBarrier = defer() + let current = true + const pending = saveSceneDocumentWithCover(f.client, clone(f.state), { objects: [] }, { image: jpeg() }, () => { + if (!current) throw new Error('project switched') + }) + current = false + f.controls.uploadBarrier.resolve() + await assert.rejects(pending, /project switched/) + assert.deepEqual(f.requests.map(r => r.method), ['POST']) + assert.equal(f.state.version, 7) +}) + +test('the shared operation queue serializes cover upload and final PUT before the next write', async () => { + const f = fixture() + const queue = new LegacySceneOperationQueue() + f.controls.uploadBarrier = defer() + const first = queue.enqueue(() => saveSceneDocumentWithCover(f.client, clone(f.state), { objects: [], label: 'cover' }, { image: jpeg() })) + const second = queue.enqueue(() => saveSceneDocumentWithCover(f.client, clone(f.state), { objects: [], label: 'next' })) + await new Promise(resolve => setImmediate(resolve)) + assert.deepEqual(f.requests.map(r => r.method), ['POST']) + f.controls.uploadBarrier.resolve() + await Promise.all([first, second]) + assert.deepEqual(f.requests.map(r => r.method), ['POST', 'PUT', 'PUT']) + assert.deepEqual(f.requests.filter(r => r.body).map(r => r.body.version), [7, 8]) +}) + +const editorSource = readFileSync(new URL('../../unreal_tran_web/src/features/guide-legacy/demo-src/scene-editor.js', import.meta.url), 'utf8').replace(/\r\n?/g, '\n') +const saveMethod = editorSource.slice(editorSource.indexOf(' async saveProject() {'), editorSource.indexOf(' /**\n * 读取已存场景')).trim() +const { saveProject } = new Function(`return ({ ${saveMethod} })`)() +function editorFixture(saveDocument) { + return { + readySettled: true, pendingLoads: 0, readOnly: false, destroyed: false, saving: false, dirty: false, changeRevision: 0, + context: { saveDocument }, serialize: () => ({ objects: [] }), applyAccessMode() {}, setSaveState() {}, + updateHistoryControls() {}, messages: [], toast(message, type) { this.messages.push({ message, type }) }, + } +} + +test('editor displays the partial-save warning instead of a success toast', async () => { + const editor = editorFixture(async () => ({ warning: '场景已保存,封面更新失败,已保留原封面' })) + await saveProject.call(editor) + assert.equal(editor.dirty, false) + assert.equal(editor.saving, false) + assert.equal(editor.messages.at(-1).type, 'warn') + assert.match(editor.messages.at(-1).message, /封面更新失败/) +}) + +test('editor failure remains dirty and duplicate clicks do not issue a second save', async () => { + const barrier = defer() + let calls = 0 + const editor = editorFixture(async () => { calls += 1; await barrier.promise }) + const pending = saveProject.call(editor) + await saveProject.call(editor) + assert.equal(calls, 1) + barrier.reject(new Error('conflict')) + await pending + assert.equal(editor.dirty, true) + assert.equal(editor.saving, false) + assert.match(editor.messages.at(-1).message, /保存失败.*conflict/) +}) + +test('changes made while cover uploads remain dirty after the earlier snapshot saves', async () => { + const barrier = defer() + const editor = editorFixture(() => barrier.promise) + const pending = saveProject.call(editor) + editor.changeRevision += 1 + barrier.resolve({}) + await pending + assert.equal(editor.dirty, true) + assert.match(editor.messages.at(-1).message, /新修改仍待保存/) +}) diff --git a/tools/scene-cover-capture.test.mjs b/tools/scene-cover-capture.test.mjs new file mode 100644 index 0000000..81c796b --- /dev/null +++ b/tools/scene-cover-capture.test.mjs @@ -0,0 +1,190 @@ +import assert from 'node:assert/strict' +import { readFile } from 'node:fs/promises' +import test from 'node:test' +import ts from 'typescript' + +const sourceUrl = new URL('../../unreal_tran_web/src/features/scene-legacy/sceneCoverCapture.ts', import.meta.url) +const source = await readFile(sourceUrl, 'utf8') +const output = ts.transpileModule(source, { + compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ES2022 }, + reportDiagnostics: true, +}) +assert.deepEqual(output.diagnostics, []) +const { captureSceneCover } = await import(`data:text/javascript;base64,${Buffer.from(output.outputText).toString('base64')}`) + +function fixture({ width = 1600, height = 900, renderError, drawError, encodeError, blob } = {}) { + const events = [] + const transformHelper = { visible: true } + const grid = { visible: false } + const boundsHelper = { visible: true } + const materials = [ + { original: { id: 'single-original' }, current: { id: 'single-highlighted' } }, + { original: [{ id: 'array-original-1' }, { id: 'array-original-2' }], current: [{ id: 'array-highlighted-1' }, { id: 'array-highlighted-2' }] }, + ] + const entries = materials.map(({ original, current }) => ({ child: { material: current }, original, highlighted: current })) + const sourceCanvas = { width, height } + const scene = { children: [transformHelper, grid, boundsHelper, ...entries.map(entry => entry.child)] } + const camera = Object.freeze({ position: Object.freeze({ x: 1, y: 2, z: 3 }) }) + const selected = entries[0].child + const visibility = () => [transformHelper.visible, grid.visible, boundsHelper.visible] + const snapshot = operation => ({ operation, visibility: visibility(), materials: entries.map(entry => entry.child.material) }) + let renders = 0 + const neverCalled = () => assert.fail('capture must not reset, detach, or dispose selection') + const editor = { + scene, camera, destroyed: false, selected, + controls: { target: Object.freeze({ x: 0, y: 0, z: 0 }), update: neverCalled }, + transform: { getHelper: () => transformHelper, detach: neverCalled }, + grid, + selectionHighlight: { + helper: boundsHelper, materialEntries: entries, object: selected, + setObject: neverCalled, clear: neverCalled, update: neverCalled, + }, + renderer: { + domElement: sourceCanvas, + render(actualScene, actualCamera) { + assert.equal(actualScene, scene) + assert.equal(actualCamera, camera) + events.push(snapshot('render')) + renders += 1 + if (renders === 1 && renderError) throw renderError + }, + }, + } + const canvas = { + width: 0, height: 0, + getContext(kind) { + assert.equal(kind, '2d') + return { + drawImage(...args) { + assert.deepEqual(args, [sourceCanvas, 0, 0, canvas.width, canvas.height]) + events.push(snapshot('copy')) + if (drawError) throw drawError + }, + } + }, + toBlob(callback, type, quality) { + events.push({ ...snapshot('encode'), type, quality }) + if (encodeError) throw encodeError + queueMicrotask(() => callback(blob === undefined ? new Blob(['jpeg'], { type }) : blob)) + }, + } + const document = { createElement: tag => { assert.equal(tag, 'canvas'); return canvas } } + const assertRestored = () => { + assert.deepEqual(visibility(), [true, false, true]) + entries.forEach((entry, index) => { + assert.equal(entry.child.material, materials[index].current) + assert.equal(entry.original, materials[index].original) + assert.equal(entry.highlighted, materials[index].current) + }) + assert.equal(editor.selectionHighlight.materialEntries, entries) + assert.equal(editor.selectionHighlight.object, selected) + assert.equal(editor.selected, selected) + assert.equal(scene.children.length, 5) + assert.deepEqual(camera.position, { x: 1, y: 2, z: 3 }) + assert.deepEqual(editor.controls.target, { x: 0, y: 0, z: 0 }) + } + return { editor, document, events, canvas, materials, entries, assertRestored } +} + +test('copies synchronously without bounds, gizmo, grid or selection glow, then restores before JPEG encoding', async () => { + const f = fixture() + const pending = captureSceneCover(f.editor, { document: f.document }) + assert.deepEqual(f.events.map(event => event.operation), ['render', 'copy', 'render', 'encode']) + for (const event of f.events.slice(0, 2)) { + assert.deepEqual(event.visibility, [false, false, false]) + event.materials.forEach((material, index) => assert.equal(material, f.materials[index].original)) + } + for (const event of f.events.slice(2)) { + assert.deepEqual(event.visibility, [true, false, true]) + event.materials.forEach((material, index) => assert.equal(material, f.materials[index].current)) + } + f.assertRestored() + assert.equal(f.events[3].type, 'image/jpeg') + assert.equal(f.events[3].quality, 0.85) + const result = await pending + assert.equal(result.type, 'image/jpeg') + assert.equal(result.size, 4) +}) + +for (const { width, height, maxWidth, expected } of [ + { width: 1600, height: 900, expected: [640, 360] }, + { width: 900, height: 1600, expected: [360, 640] }, + { width: 320, height: 180, expected: [320, 180] }, + { width: 1600, height: 900, maxWidth: 320, expected: [320, 180] }, +]) { + test(`preserves the ${width} x ${height} ratio within ${maxWidth ?? 640}px and never upscales`, async () => { + const f = fixture({ width, height }) + await captureSceneCover(f.editor, { document: f.document, maxWidth }) + assert.deepEqual([f.canvas.width, f.canvas.height], expected) + f.assertRestored() + }) +} + +for (const failure of ['drawError', 'renderError', 'encodeError']) { + test(`restores helper visibility, scalar/array materials and selection after ${failure}`, async () => { + const error = new Error(failure) + const f = fixture({ [failure]: error }) + await assert.rejects(captureSceneCover(f.editor, { document: f.document }), actual => actual === error) + f.assertRestored() + assert.equal(f.events.filter(event => event.operation === 'render').length, 2) + if (failure !== 'encodeError') assert.equal(f.events.some(event => event.operation === 'encode'), false) + }) +} + +test('restores the actual material reference even if it differs from the recorded highlighted clone', async () => { + const f = fixture() + const replacement = { id: 'material-changed-after-selection' } + f.entries[0].child.material = replacement + await captureSceneCover(f.editor, { document: f.document }) + assert.equal(f.entries[0].child.material, replacement) + assert.equal(f.events[0].materials[0], f.materials[0].original) +}) + +test('supports a ready scene without selection helpers', async () => { + const f = fixture() + delete f.editor.transform + delete f.editor.grid + delete f.editor.selectionHighlight + assert.equal((await captureSceneCover(f.editor, { document: f.document })).type, 'image/jpeg') +}) + +test('deduplicates shared helper objects before recording visibility', async () => { + const f = fixture() + f.editor.transform.getHelper = () => f.editor.selectionHighlight.helper + await captureSceneCover(f.editor, { document: f.document }) + f.assertRestored() +}) + +for (const blob of [null, new Blob([])]) { + test(`rejects ${blob === null ? 'missing' : 'empty'} encoded images without disturbing the editor`, async () => { + const f = fixture({ blob }) + await assert.rejects(captureSceneCover(f.editor, { document: f.document }), /编码结果为空/) + f.assertRestored() + }) +} + +test('refuses an unready or destroyed renderer before changing any scene state', async () => { + for (const change of [ + f => { f.editor.destroyed = true }, + f => { f.editor.renderer = null }, + f => { f.editor.renderer.domElement.width = 0 }, + f => { f.editor.renderer.domElement.height = Number.NaN }, + f => { f.editor.scene = null }, + f => { f.editor.camera = null }, + ]) { + const f = fixture() + change(f) + await assert.rejects(captureSceneCover(f.editor, { document: f.document }), /视口尚未准备好/) + f.assertRestored() + assert.equal(f.events.length, 0) + } +}) + +test('refuses invalid dimensions and unavailable 2D canvas before changing scene state', async () => { + const f = fixture() + await assert.rejects(captureSceneCover(f.editor, { document: f.document, maxWidth: 0 }), /正数像素/) + f.canvas.getContext = () => null + await assert.rejects(captureSceneCover(f.editor, { document: f.document }), /不支持场景封面编码/) + f.assertRestored() + assert.equal(f.events.length, 0) +}) diff --git a/tools/scene-model-placement.test.mjs b/tools/scene-model-placement.test.mjs new file mode 100644 index 0000000..e43d4b9 --- /dev/null +++ b/tools/scene-model-placement.test.mjs @@ -0,0 +1,123 @@ +import assert from 'node:assert/strict' +import { readFile } from 'node:fs/promises' +import { createRequire } from 'node:module' +import { pathToFileURL } from 'node:url' +import test from 'node:test' +import ts from 'typescript' + +const requireWeb = createRequire(new URL('../../unreal_tran_web/package.json', import.meta.url)) +const threeUrl = pathToFileURL(requireWeb.resolve('three')).href +const THREE = await import(threeUrl) +const source = await readFile(new URL('../../unreal_tran_web/src/features/scene-legacy/modelPlacement.ts', import.meta.url), 'utf8') +const output = ts.transpileModule(source, { + compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ES2022 }, + reportDiagnostics: true, +}) +assert.deepEqual(output.diagnostics, []) +const compiled = output.outputText.replace(/from 'three'/g, `from '${threeUrl}'`) +const { fitSceneModel, refreshSceneModelBounds, parseSceneScale, formatSceneScale } = await import( + `data:text/javascript;base64,${Buffer.from(compiled).toString('base64')}`, +) + +function close(actual, expected, tolerance = 1e-8) { + assert.ok(Math.abs(actual - expected) <= tolerance, `${actual} != ${expected}`) +} + +function skinFixture() { + const root = new THREE.Group() + const bone = new THREE.Bone() + const geometry = new THREE.BoxGeometry(2, 4, 10) + geometry.translate(0, 2, 0) + const count = geometry.getAttribute('position').count + const indices = new Uint16Array(count * 4) + const weights = new Float32Array(count * 4) + for (let i = 0; i < count; i += 1) weights[i * 4] = 1 + geometry.setAttribute('skinIndex', new THREE.Uint16BufferAttribute(indices, 4)) + geometry.setAttribute('skinWeight', new THREE.Float32BufferAttribute(weights, 4)) + const mesh = new THREE.SkinnedMesh(geometry, new THREE.MeshBasicMaterial()) + root.add(bone, mesh) + root.updateMatrixWorld(true) + mesh.bind(new THREE.Skeleton([bone])) + // The published model has already been normalized and may be saved at an + // animation pose. This is the same stale matrix/cache state as loaded GLTF. + root.scale.setScalar(0.1) + root.position.set(1, 2, 3) + bone.position.y = 5 + return { root, bone, mesh } +} + +test('fresh skinned placement reaches the requested size and floor after authored scale/pose replay', () => { + const { root, mesh } = skinFixture() + // Populate the wrong cached skin box just as the previous import path did. + const stale = new THREE.Box3().setFromObject(root).getSize(new THREE.Vector3()) + assert.ok(stale.z < 1) + const box = fitSceneModel(root, 6) + const size = box.getSize(new THREE.Vector3()) + close(size.x, 1.2) + close(size.y, 2.4) + close(size.z, 6) + close(root.scale.x, 0.6) + close(box.min.y, 0) + close(box.getCenter(new THREE.Vector3()).x, 0) + close(box.getCenter(new THREE.Vector3()).z, 0) + const vertex = new THREE.Vector3() + for (let i = 0; i < mesh.geometry.getAttribute('position').count; i += 1) { + mesh.getVertexPosition(i, vertex) + assert.ok(mesh.boundingSphere.containsPoint(vertex)) + } +}) + +test('fresh static placement preserves authored non-uniform proportions', () => { + const root = new THREE.Group() + root.add(new THREE.Mesh(new THREE.BoxGeometry(2, 4, 10), new THREE.MeshBasicMaterial())) + root.scale.set(2, 0.5, 3) + root.position.set(-4, 8, 6) + const box = fitSceneModel(root, 6) + root.scale.toArray().forEach((value, i) => close(value, [0.4, 0.1, 0.6][i])) + close(box.getSize(new THREE.Vector3()).z, 6) + close(box.min.y, 0) +}) + +test('restoring skin caches keeps existing scene transforms and authored bone poses unchanged', () => { + const { root, bone, mesh } = skinFixture() + refreshSceneModelBounds(root) + root.position.set(-7.5, 1.06, -0.45) + root.rotation.set(0.1, 0.4, -0.2) + root.scale.set(6, 4, 2) + bone.position.set(1, 17, 3) + const before = { position: root.position.toArray(), rotation: root.rotation.toArray(), scale: root.scale.toArray(), bone: bone.position.toArray() } + const staleBox = mesh.boundingBox.clone() + const box = refreshSceneModelBounds(root) + assert.deepEqual({ position: root.position.toArray(), rotation: root.rotation.toArray(), scale: root.scale.toArray(), bone: bone.position.toArray() }, before) + assert.notDeepEqual(mesh.boundingBox, staleBox) + const vertex = new THREE.Vector3() + const generousBox = box.clone().expandByScalar(1e-8) + for (let i = 0; i < mesh.geometry.getAttribute('position').count; i += 1) { + mesh.getVertexPosition(i, vertex) + assert.ok(vertex.distanceTo(mesh.boundingSphere.center) <= mesh.boundingSphere.radius + 1e-8) + assert.ok(generousBox.containsPoint(vertex.applyMatrix4(mesh.matrixWorld))) + } +}) + +test('declared terrain ground datum stays on the scene floor', () => { + const root = new THREE.Group() + root.add(new THREE.Mesh(new THREE.BoxGeometry(8, 4, 10), new THREE.MeshBasicMaterial())) + fitSceneModel(root, 20, -1.5) + close(-1.5 * root.scale.y + root.position.y, 0) +}) + +test('scale input accepts real GLTF normalization factors below 0.05', () => { + close(parseSceneScale('0.0361637593257', 6), 0.0361637593257) + close(parseSceneScale('0.000001', 6), 0.000001) + close(parseSceneScale('1e-9', 6), 0.000001) + for (const value of ['', ' ', 'invalid', 'NaN', 'Infinity', '0', '-2']) { + close(parseSceneScale(value, 0.036164), 0.036164) + } +}) + +test('scale display preserves small factors and trims unnecessary zeros', () => { + assert.equal(formatSceneScale(0.0361637593257), '0.03616376') + assert.equal(formatSceneScale(0.000001), '0.000001') + assert.equal(formatSceneScale(1), '1') + assert.equal(formatSceneScale(0.6), '0.6') +}) diff --git a/tools/scene-model-visibility.e2e.mjs b/tools/scene-model-visibility.e2e.mjs new file mode 100644 index 0000000..a46d010 --- /dev/null +++ b/tools/scene-model-visibility.e2e.mjs @@ -0,0 +1,224 @@ +import assert from 'node:assert/strict'; +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { chromium, expect } from '@playwright/test'; +import { localCredentials } from './review-api.mjs'; + +// Run against the local Vite application after saving the intended scene camera: +// node tools/scene-model-visibility.e2e.mjs +// Every scene uses a fresh browser context. Content and asset writes are blocked; +// the only server mutations permitted are login and active-role session changes. +const baseURL = process.env.SCENE_VISIBILITY_BASE_URL || 'http://127.0.0.1:6180'; +const reportDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../reports/scene-live-20260905'); +const cases = [ + { sceneId: '160', modelProjectId: '157', modelVersionId: '201', label: '狐狸野外训练区', screenshot: '26-fox-visual-regression.png' }, + { sceneId: '159', modelProjectId: '156', modelVersionId: '204', label: '牛奶卡车检验区', screenshot: '27-truck-visual-regression.png' }, +]; +const credentials = localCredentials(); +const evidence = { + generatedAt: new Date().toISOString(), + baseURL, + browser: 'Microsoft Edge / Playwright', + method: 'Fresh context; saved camera; compare rendered pixels with model roots visible versus hidden; model shadow casting disabled in both samples.', + threshold: { sampleWidth: 320, sampleHeight: 180, minimumChangedPixelsExclusive: 500, minimumRgbDelta: 12 }, + status: 'RUNNING', + results: [], +}; +fs.mkdirSync(path.join(reportDir, 'screenshots'), { recursive: true }); + +function persist() { + fs.writeFileSync(path.join(reportDir, 'visibility-evidence.json'), `${JSON.stringify(evidence, null, 2)}\n`); +} + +function safeError(error) { + let message = error instanceof Error ? error.message : String(error); + for (const value of [credentials.username, credentials.password]) { + if (value) message = message.split(value).join('[redacted]'); + } + return message.replace(/Bearer\s+\S+/gi, 'Bearer [redacted]'); +} + +async function signIn(page) { + await page.goto('/login', { waitUntil: 'domcontentloaded' }); + await expect(page.locator('[data-role-code="admin"]')).toBeVisible({ timeout: 45_000 }); + await page.locator('[data-role-code="admin"]').click(); + await page.locator('input[name="username"]').fill(credentials.username); + await page.locator('input[name="password"]').fill(credentials.password); + await page.getByRole('button', { name: '登录系统', exact: true }).click(); + await expect(page.locator('.platform-shell')).toBeVisible({ timeout: 60_000 }); + await page.goto('/profile', { waitUntil: 'domcontentloaded' }); + const teacher = page.locator('.profile-role-switcher button').filter({ hasText: '教员' }); + await expect(teacher).toBeVisible(); + let roleSwitchAttempts = 0; + while (!(await teacher.getAttribute('class'))?.includes('active') && roleSwitchAttempts < 3) { + roleSwitchAttempts += 1; + await teacher.click(); + try { + await expect(teacher).toHaveClass(/active/, { timeout: 15_000 }); + } catch { + // The local auth service occasionally rejects the initial role switch. + // Retry only while the requested role is still inactive; never retry or + // weaken any scene, version, visibility or pixel-contribution assertion. + if (roleSwitchAttempts === 3) throw new Error('Teacher role remained inactive after three session-switch attempts'); + } + } + await expect(teacher).toHaveClass(/active/); + return { role: 'teacher', roleSwitchAttempts }; +} + +async function readPixelContribution(page, testCase) { + return page.evaluate(async ({ modelProjectId, modelVersionId }) => { + const editor = globalThis.__visibilityScene; + const THREE = globalThis.__visibilityThree; + if (!editor?.readySettled || editor.destroyed) throw new Error('Scene editor is not ready'); + if (!THREE) throw new Error('The editor Three runtime was not exposed'); + editor.selectObject(null); + const roots = editor.objects.filter(object => String(object.userData?.targetProjectId) === modelProjectId); + if (!roots.length) throw new Error(`Scene contains no model reference for project ${modelProjectId}`); + if (roots.some(object => String(object.userData?.targetVersionId) !== modelVersionId)) { + throw new Error(`Scene references an unexpected published model version for project ${modelProjectId}`); + } + + const inheritedVisible = object => { + for (let node = object; node; node = node.parent) if (!node.visible) return false; + return true; + }; + const measurements = roots.map(root => { + root.updateMatrixWorld(true); + const bounds = new THREE.Box3().setFromObject(root); + const size = bounds.getSize(new THREE.Vector3()); + let meshes = 0; + let visibleMeshes = 0; + let skinnedMeshes = 0; + root.traverse(node => { + if (!node.isMesh) return; + meshes += 1; + if (inheritedVisible(node)) visibleMeshes += 1; + if (node.isSkinnedMesh) skinnedMeshes += 1; + }); + return { + name: root.userData.displayName || root.name, + sceneObjectId: root.userData.sceneId, + targetProjectId: String(root.userData.targetProjectId), + targetVersionId: String(root.userData.targetVersionId), + visible: inheritedVisible(root), meshes, visibleMeshes, skinnedMeshes, + position: root.position.toArray(), scale: root.scale.toArray(), + bounds: { min: bounds.min.toArray(), max: bounds.max.toArray(), size: size.toArray() }, + finiteBounds: !bounds.isEmpty() && [...bounds.min.toArray(), ...bounds.max.toArray()].every(Number.isFinite), + }; + }); + + const sample = document.createElement('canvas'); + sample.width = 320; + sample.height = 180; + const sampleContext = sample.getContext('2d', { willReadFrequently: true }); + if (!sampleContext) throw new Error('2D pixel sampling is unavailable'); + const readPixels = () => { + editor.renderer.render(editor.scene, editor.camera); + sampleContext.clearRect(0, 0, sample.width, sample.height); + sampleContext.drawImage(editor.renderer.domElement, 0, 0, sample.width, sample.height); + return sampleContext.getImageData(0, 0, sample.width, sample.height).data; + }; + const visibility = roots.map(root => root.visible); + const shadowCasters = []; + let before; + let withoutModels; + try { + // A shadow alone must not satisfy the visibility check. + for (const root of roots) root.traverse(node => { + if (node.isMesh) { shadowCasters.push([node, node.castShadow]); node.castShadow = false; } + }); + editor.renderer.shadowMap.needsUpdate = true; + before = readPixels(); + for (const root of roots) root.visible = false; + editor.renderer.shadowMap.needsUpdate = true; + withoutModels = readPixels(); + } finally { + roots.forEach((root, index) => { root.visible = visibility[index]; }); + shadowCasters.forEach(([mesh, castShadow]) => { mesh.castShadow = castShadow; }); + editor.renderer.shadowMap.needsUpdate = true; + editor.renderer.render(editor.scene, editor.camera); + } + let changedPixels = 0; + let rgbDeltaSum = 0; + for (let offset = 0; offset < before.length; offset += 4) { + const delta = Math.abs(before[offset] - withoutModels[offset]) + + Math.abs(before[offset + 1] - withoutModels[offset + 1]) + + Math.abs(before[offset + 2] - withoutModels[offset + 2]); + rgbDeltaSum += delta; + if (delta >= 12) changedPixels += 1; + } + return { + camera: { position: editor.camera.position.toArray(), target: editor.controls.target.toArray(), fov: editor.camera.fov }, + ready: editor.readySettled, pendingLoads: editor.pendingLoads, modelRoots: measurements, + sample: { width: 320, height: 180, changedPixels, changedPercentage: Number((changedPixels / 576).toFixed(3)), rgbDeltaSum }, + }; + }, testCase); +} + +const browser = await chromium.launch({ channel: 'msedge', headless: true }); +try { + for (const testCase of cases) { + const blockedWrites = []; + const context = await browser.newContext({ baseURL, viewport: { width: 1920, height: 1080 }, locale: 'zh-CN', timezoneId: 'Asia/Shanghai' }); + const result = { ...testCase, status: 'RUNNING', blockedWrites }; + evidence.results.push(result); + try { + await context.route('**/*', async route => { + const request = route.request(); + const pathname = new URL(request.url()).pathname; + if (!['GET', 'HEAD', 'OPTIONS'].includes(request.method()) && (pathname.startsWith('/api/tran/') || pathname.startsWith('/fileapi/'))) { + blockedWrites.push({ method: request.method(), path: pathname }); + await route.abort('blockedbyclient'); + return; + } + await route.continue(); + }); + const page = await context.newPage(); + page.setDefaultTimeout(45_000); + // Read handles are injected into the module already loaded by the page. + // Re-importing an unversioned URL after HMR would create a second editor + // module and observe the wrong instance. No business logic is replaced. + await page.route('**/src/features/guide-legacy/demo-src/scene-editor.js*', async route => { + const response = await route.fetch(); + const body = await response.text(); + const marker = 'activeSceneEditor = new WorkshopSceneEditor(container, context);'; + assert.ok(body.includes(marker), 'Scene editor instrumentation anchor must exist'); + await route.fulfill({ response, body: body.replace(marker, + `${marker} globalThis.__visibilityScene = activeSceneEditor; globalThis.__visibilityThree = THREE;`) }); + }); + result.session = await signIn(page); + const sceneRead = page.waitForResponse(response => response.request().method() === 'GET' + && new URL(response.url()).pathname === `/api/tran/v1/content/projects/${testCase.sceneId}`); + await page.goto(`/content/scenes/${testCase.sceneId}/edit`, { waitUntil: 'domcontentloaded' }); + const response = await sceneRead; + assert.equal(response.status(), 200, 'Scene project API must return 200'); + const { data } = await response.json(); + result.project = { id: String(data.project.id), name: data.project.name, status: data.project.status, currentVersionId: String(data.currentVersion.id), publishedVersionId: String(data.project.publishedVersionId) }; + const shell = page.locator('.se-shell'); + await expect(shell).toHaveAttribute('data-ready', 'true', { timeout: 180_000 }); + await expect(shell).not.toHaveClass(/model-loading/, { timeout: 180_000 }); + result.visibility = await readPixelContribution(page, testCase); + result.screenshot = `screenshots/${testCase.screenshot}`; + await page.screenshot({ path: path.join(reportDir, result.screenshot), fullPage: true, timeout: 60_000 }); + assert.ok(result.visibility.modelRoots.every(root => root.visible && root.visibleMeshes > 0 && root.finiteBounds), 'Model meshes and finite bounds must be visible'); + assert.ok(result.visibility.sample.changedPixels > 500, `Expected more than 500 model-contributed pixels; received ${result.visibility.sample.changedPixels}`); + assert.equal(blockedWrites.length, 0, 'Read-only regression must not attempt content or file writes'); + result.status = 'PASS'; + console.log(JSON.stringify({ sceneId: testCase.sceneId, status: result.status, changedPixels: result.visibility.sample.changedPixels, screenshot: result.screenshot })); + } catch (error) { + result.status = 'FAIL'; + result.error = safeError(error); + console.error(JSON.stringify({ sceneId: testCase.sceneId, status: result.status, error: result.error })); + } finally { + await context.close(); + persist(); + } + } + evidence.status = evidence.results.every(result => result.status === 'PASS') ? 'PASS' : 'FAIL'; + persist(); + if (evidence.status !== 'PASS') process.exitCode = 1; +} finally { + await browser.close(); +}