Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

161 строка
29 KiB

  1. // Default-route controls only. The unmounted Vue workspace is documented separately.
  2. export const sceneSources = {
  3. router: '../../../unreal_tran_web/src/router/index.ts',
  4. runtime: '../../../unreal_tran_web/src/features/guide-legacy/demo-src/scene-editor.js',
  5. host: '../../../unreal_tran_web/src/views/content/LegacyScenePageView.vue',
  6. api: '../../../unreal_tran_web/src/features/scene-legacy/contentApiClient.ts',
  7. assets: '../../../unreal_tran_web/src/features/scene-legacy/serverAssetStore.ts',
  8. storage: '../../../unreal_tran_web/src/features/scene-legacy/runtime.ts',
  9. cover: '../../../unreal_tran_web/src/features/scene-legacy/sceneCoverCapture.ts',
  10. placement: '../../../unreal_tran_web/src/features/scene-legacy/modelPlacement.ts',
  11. enclosure: '../../../unreal_tran_web/src/features/guide-legacy/demo-src/garage-enclosure.js',
  12. selection: '../../../unreal_tran_web/src/features/guide-legacy/demo-src/scene-selection.js',
  13. history: '../../../unreal_tran_web/src/features/guide-legacy/demo-src/scene-history.js',
  14. formal: '../../../unreal_tran_web/src/features/editors/scene/SceneEditorWorkspace.vue',
  15. list: '../../../unreal_tran_web/src/views/content/ContentProjectsView.vue',
  16. }
  17. // [stable ID, name, source key:search text, scope/boundary, observable acceptance]
  18. export const sceneGroups = [
  19. ['工程入口与顶部命令', [
  20. ['project.load', '按真实项目 ID 打开已存场景', 'host:async function loadProject', '服务端 content 与版本是真值;不得以模板种子覆盖有效旧工程。', '独立新会话打开,真实模型可见、固定版本及对象字段一致。'],
  21. ['project.retry', '项目或挂载加载失败后重新加载', 'host:mountError', '错误详情自动消退,保留中性失败状态与重试按钮。', '注入加载失败;无可写半场景;恢复网络后按钮重试成功。'],
  22. ['project.title', '当前场景名称与项目说明按钮', 'runtime:project: () => this.toast', '现有标题显示服务端名称;说明按钮不是重命名输入框。', '长名称完整 title 正确;点击说明反映内容 API 管理。'],
  23. ['project.new', '顶部新建独立工程', 'runtime:new: () =>', '基线代码重置当前模板;本轮由宿主接真实创建 API,必须保留原项目。', '取消/失败不清原工程;成功新 ID;保存重开与列表对应。'],
  24. ['project.back', '返回场景制作列表并保留场景标签', 'runtime:back: () =>', '平台约定返回列表等同切换标签,保留场景缓存和未存稿,不弹关闭确认;真正关闭标签才询问。', '未存状态返回列表不写服务器、不丢场景;重新点原标签恢复输入和选择。'],
  25. ['project.save', '保存草稿按钮', 'runtime:async saveProject()', '只有服务器保存完成才显示成功;本地恢复缓冲不是自动入库。', '编辑后真实 PUT,刷新值一致,version 前进一次。'],
  26. ['project.save-key', 'Ctrl/Meta+S 保存快捷键', 'runtime:handleKeyboard(event)', '键盘与按钮走相同保存/权限/忙碌守卫。', '实际按键触发一次保存;表单内与非表单焦点分别核查。'],
  27. ['project.save-failure', '保存失败保留修改和恢复稿', 'runtime:async saveProject()', '网络失败或业务拒绝不能清 dirty;不弹虚假保存成功。', '定向 503 后对象/字段保留,恢复后重试与刷新成功。'],
  28. ['project.conflict', '409 乐观锁冲突保护', 'host:function describeSaveError', '服务器最新版本不覆盖;恢复副本可下载/隔离。', '独立副本制造版本冲突;验证失败提示、旧版本不覆盖与本地稿保留。'],
  29. ['project.concurrent-save', '重复保存与保存中继续编辑', 'runtime:const saveRevision = this.changeRevision', '提交快照与后续编辑分开;后续修改不能随早先请求完成清掉。', '延迟 PUT、连点保存并继续改值;一次旧提交、新修改仍 dirty。'],
  30. ]],
  31. ['工程文件与资源导入', [
  32. ['json.export', '导出当前场景 JSON', 'runtime:exportProject()', '导出 edit3dv4.scene、对象/部件覆盖、渲染和稳定资源引用;不冒称自包含 GLB 包。', '打开下载 JSON 核对内容、结构和无临时 blob 依赖。'],
  33. ['json.import', '导入有效场景工程 JSON', 'runtime:importProject(event)', '替换当前编辑文档后仍需保存;不得写入另一个项目身份。', '导出后实际文件导入、保存、重开;对象与渲染参数往返一致。'],
  34. ['json.invalid', '非法 JSON / 错误 schema 拒绝', 'runtime:importProject(event)', '解析或结构错误不得清空当前场景。', '非法 JSON 与非场景文档各一次,原工程和模型仍可编辑。'],
  35. ['json.missing-resource', 'JSON 缺失/错误受控引用拒绝与回滚', 'runtime:async restoreImportedObject', '错误资产编码不能回退为另一个模型;恢复失败不半替换。', '导入显式不存在编码/版本;原对象保留或明确阻断,零错误发布。'],
  36. ['json.rendering', '相机、灯光、雾和环境序列化往返', 'runtime:serializeRendering()', '当前默认 UI 不提供全部渲染编辑器;导入/保存仍须保留其文档参数。', '合法带渲染参数文档导入、实际画面比对、保存重开字段一致。'],
  37. ['glb.import', '本地 GLB 上传并加入当前场景', 'runtime:async importGLB(event)', '上传到内容服务,消费票据后解析;对象加入不等于工程已保存。', '真实选择小 GLB,上传/登记/可见/保存重开均完成。'],
  38. ['glb.invalid', '非 GLB / 损坏 GLB / 上传失败处理', 'runtime:async importGLB(event)', '上传或解析失败不插入占位对象;原场景应保留,提示可重试。', '错误格式及损坏文件、上传 503;验证对象数/旧资产/后续成功导入。'],
  39. ['glb.pending', '资源加载/上传期间操作互斥', 'runtime:setModelLoading(loading', '加载中的模型不能被半保存、导出或发布;不能离开造成旧请求污染新项目。', '延迟下载/上传,操作禁用与待完成状态一致,完成后恢复。'],
  40. ['glb.references', '本项目 GLB 稳定资产引用', 'assets:async put(blob', '自导入使用 content://asset/scene/{projectId}/{assetCode} 和 READY 资产;blob 只供运行。', '重新会话受控下载成功,主对象/资产身份一致,无本地缓存依赖。'],
  41. ]],
  42. ['左侧目录与资源放置', [
  43. ['panel.left-tabs', '场景大纲 / 资源库 / 场景模板切换', 'runtime:const leftTab =', '切面板不写业务文档;筛选状态行为需一致。', '三页签均可达,无 DOM 异常或资源目录中断。'],
  44. ['search.tree', '对象/部件名称搜索与清空', 'runtime:renderTree()', '根名与部件名可命中;无匹配状态应清楚,非删除对象。', '根名/部件名/无结果/清空分别核对行和真实对象数。'],
  45. ['search.assets', '资源搜索与异步刷新保留筛选', 'runtime:applyLeftFilter()', '只筛当前目录;异步重绘不复活不匹配卡片。', '命中、无结果、清空,目录重绘后过滤仍正确。'],
  46. ['search.templates', '模板搜索与清空', 'runtime:filterLeft(query)', '模板卡片与同一搜索框联动。', '中文模板关键字过滤、无结果和清空。'],
  47. ['assets.catalog', '真实已发布模型成果目录', 'api:async listPublishedModels', '目录由 API 预加载,当前默认不以 localStorage 发布清单为真值。', '显示发布模型名称/版本,草稿不冒充已发布,空态可操作。'],
  48. ['assets.model-double-click', '双击已发布模型放置', 'runtime:async placeEditorAsset', '按固定 project/version/assetCode 导入当前实例,继承发布部件和材质。', '狐狸和卡车分别双击加入、真实可见、保存重开固定版本。'],
  49. ['assets.model-drop', '拖入已发布模型放置', 'runtime:handleDrop(event)', '拖放实际命中地平面;与双击共用受控资产链路。', '真实指针拖放到不同位置,坐标/实例数/固定引用准确。'],
  50. ['assets.basic-double-click', '双击基础资源放置', 'runtime:onRootDblClick', '以当前轨道目标落地;每次生成独立对象身份。', '双击生成对象,变换、保存后仍可见。'],
  51. ['assets.basic-drop', '基础资源拖入与拖放提示', 'runtime:handleDrop(event)', 'MIME 和 text/plain 回退协议一致;离开视口清提示。', '真实拖放命中位置与 0.5m 吸附、dragleave/drop 提示复位。'],
  52. ['assets.model-link', '打开/返回模型编辑器入口', 'runtime:open-model-editor', '当前基线只有跳模型列表,来源按钮不得冒称直达正确源项目。', '空资源库和选中模型来源两入口,跳转/未保存保护正确。'],
  53. ...[
  54. ['diagnostic', '液压诊断工位'], ['equipment', '维修装备主体'], ['workbench', '检修工作台'], ['shelf', '器材存放架'],
  55. ['safety-zone', '安全作业区域'], ['camera', '视觉采集设备'], ['worker', '训练人员占位'], ['light', '区域照明'],
  56. ].map(([id, name]) => [`asset.${id}`, `基础资源:${name}`, `runtime:id: '${id}'`, '现有程序化场景资源;名称不代表已连接物理设备或真实人员。', '实际放置可见,独立编号、位置和保存重开一致;照明应区分灯具外观与光源效果。']),
  57. ['asset.vehicle-depot', '场地资源:真实装备车库', "runtime:id: 'vehicle-depot'", '整体场地 GLB 与维修车间分开;重复放置按既有规则处理。', '资源拖放或双击加载、比例/落地正常、重复放置不产生错误重叠。'],
  58. ['asset.field-terrain', '场地资源:真实野外地形', "runtime:id: 'field-terrain'", '真实地形资源和指定落地基准;不能以程序地板代替。', '加载后真实起伏地形可见,保存重开资源、地面高度一致。'],
  59. ]],
  60. ['全部可达场景模板', [
  61. ...[
  62. ['depot-1', '真实装备车库'], ['terrain-1', '真实野外训练场'], ['workshop-1', '综合检验车间'], ['workshop-real', '演示维修车间(可拆分)'],
  63. ['workshop-2', '总成拆卸车间'], ['workshop-3', '部件分解车间'], ['workshop-4', '清洗检测车间'], ['workshop-5', '复装调试车间'], ['outdoor-1', '室外综合训练场'],
  64. ].map(([id, name]) => [`template.${id}`, name, `runtime:id: '${id}'`, '模板场地与种子布局须有实际执行;切模板不是创建新的业务项目。', '独立副本点击模板、确认/取消未存操作、真实画面、保存重开 presetId/环境/对象一致。']),
  65. ['template.switch-cancel', '未保存模板切换取消', 'runtime:async loadPreset', '取消保留原场景、选择与 dirty;请求中不能切换半场景。', '有未存修改时取消/确认分别验证,取消零对象和服务端变更。'],
  66. ]],
  67. ['三维视口、选择与变换', [
  68. ['view.orbit', '鼠标旋转相机', 'runtime:new OrbitControls', '相机轨道操作不应误选、拖动物体。', '实际鼠标拖动,相机变化且对象姿态不变。'],
  69. ['view.pan', '鼠标平移相机', 'runtime:new OrbitControls', '轨道目标平移与物体位置分开。', '实际右键/约定鼠标平移,目标变化且对象数据不变。'],
  70. ['view.zoom', '滚轮缩放相机', 'runtime:new OrbitControls', '改变观察距离,不改对象 scale。', '滚轮前后模型可见且对象 scale 不变。'],
  71. ['view.perspective', '透视按钮', 'runtime:data-camera="perspective"', '基线按钮无处理分支;需明确恢复相机视角,不静默无效。', '顶视切回透视,实际相机位置与激活样式变化。'],
  72. ['view.top', '顶视图按钮', 'runtime:setTopView()', '仍为透视相机顶视位置,不冒称正交投影。', '实际点击后顶视方向与目标一致。'],
  73. ['view.focus', '聚焦选中对象', 'runtime:focusSelected()', '按对象真实 bounds 调整相机;无选中应提示。', '狐狸/卡车/环境分别聚焦可见;无选中提示不异常。'],
  74. ['view.grid', '网格显隐', 'runtime:toggleGrid(button)', '当前视图辅助选项;不默认要求跨重开持久化。', '真实网格出现/消失、状态同步、截图封面不含网格。'],
  75. ['view.enclosure-full', '车库外壳完整显示', 'enclosure:createGarageEnclosureControls', '完整显示屋顶/墙体/玻璃;仅车库资源存在时出现控制。', '实际点击、对象材料和显示恢复,状态与画面一致。'],
  76. ['view.enclosure-xray', '车库外壳透明查看', 'enclosure:createGarageEnclosureControls', '车库多种围护材料联动;不等于普通相机透视。', '实际外壳透明且内部模型可辨,材质无串改。'],
  77. ['view.enclosure-hidden', '隐藏车库外壳', 'enclosure:createGarageEnclosureControls', '隐藏围护后保留内部及地面;序列化 enclosureMode 与 dirty 契约须核对。', '隐藏/还原、保存重开和只读浏览行为准确。'],
  78. ['selection.viewport', '点击视口选中根对象/部件', 'runtime:selectFromViewport(event)', '只命中真实可选择可见对象;拖相机超过阈值不误选。', '真实像素点击目标、树/属性/高亮一致,点击空白清选择。'],
  79. ['selection.tree', '大纲根对象与部件选中', 'runtime:const treeItem =', '大纲显示所有可编辑实例和部件;环境锁定提示不是折叠控件。', '树选中与视口高亮/属性联动、筛选后仍可选。'],
  80. ['selection.hidden', '隐藏祖先与软删除部件不可误拾取', 'selection:chooseSceneSelection', '父隐藏/子隐藏/软删除状态不能被射线重新命中。', '用重叠模型/部件实测,命中应落可见有效对象。'],
  81. ['selection.highlight', '选中高亮与恢复原材质', 'runtime:updateSelectionHighlight()', '高亮是暂态,不写入模型/场景材质,不进入封面。', '切换对象/清选择/预览/保存截图后材质原值恢复。'],
  82. ['transform.translate', '移动工具及真实 XYZ 手柄', 'runtime:setTransform(mode)', '对象实例位置;部件按发布能力限制。', '真实拖动平移手柄,属性联动、撤销重做、保存重开一致。'],
  83. ['transform.rotate', '旋转工具及真实旋转手柄', 'runtime:setTransform(mode)', 'UI 度数与保存弧度转换;不能仅用脚本改姿态代替拖动。', '实际旋转手柄改变姿态并重开一致。'],
  84. ['transform.scale', '缩放工具及真实缩放手柄', 'runtime:setTransform(mode)', '归一化模型已有 scale 必须保留,负/零/小值合同明确。', '真实缩放与属性数值一致;狐狸不突然放成超大或消失。'],
  85. ['transform.keys', 'W/E/R 快捷键', 'runtime:handleKeyboard(event)', '键盘焦点在表单时不切工具,失活缓存页不能抢键。', '视口按键切工具;名称输入包含 w/e/r 正常;只读不改。'],
  86. ['transform.snap', '吸附 0.5m 与旋转 15° 开关', 'runtime:toggleSnap()', '开关同时控制拖放/变换吸附;当前视图工具参数与业务值区分。', '开/关实际拖动位置、旋转角度,按钮/页脚状态一致。'],
  87. ]],
  88. ['对象属性、部件与底部面板', [
  89. ['property.name', '显示名称', 'runtime:handleInput(event)', '对象/部件 displayName 与项目名称分开。', '修改名称,树/对象条/属性同步,保存重开保留。'],
  90. ['property.visible', '在场景中可见', 'runtime:handleChange(event)', '实例显隐可保存;受保护蒙皮部件不得独立隐藏。', '开/关可见性、恢复、保存重开,视口与树状态准确。'],
  91. ['property.operable', '可作为实训目标', 'runtime:handleChange(event)', 'operable/capabilities 进入场景定义;不能扩大平台操作权限。', '开/关并保存重开,发布数据的目标能力一致。'],
  92. ['property.position', '位置 X/Y/Z 数值', 'runtime:handleInput(event)', '三个输入回写局部 position;不使用纯展示假字段。', '三个轴独立输入与手柄联动、失焦/history/重开准确。'],
  93. ['property.rotation', '旋转 X/Y/Z 数值', 'runtime:handleInput(event)', 'UI 为角度,文档为弧度。', '非整角/负角输入、实际姿态与 JSON/重开一致。'],
  94. ['property.scale', '缩放 X/Y/Z 数值及有效值', 'placement:parseSceneScale', '支持小数归一化 scale,避免小值格式化成零;非法值不得破坏模型。', '小正数、负数/零/清空按合同处理,三轴保存往返正常。'],
  95. ['property.device-id', '设备编号', 'runtime:handleInput(event)', '根对象绑定字符串;重复/空值由预检与后端核查。', '修改后绑定表同步、保存重开,重复值能被阻断。'],
  96. ['property.model-id', '物模型编号', 'runtime:handleInput(event)', '与受控 assetCode、来源项目 ID 分开。', '修改后只改业务编号,源 GLB 仍加载正确。'],
  97. ['property.semantic', '语义类型六个选项', 'runtime:handleChange(event)', '实训装备/工位设施/安全区域/采集设备/训练人员/环境设施。', '逐项可选且保存重开保留;绑定表显示实际类型。'],
  98. ['part.source', '模型来源与部件权限说明', 'runtime:renderInspector()', '固定模型版本/源节点;蒙皮仅查看高亮,非骨骼独立变换。', '狐狸蒙皮与卡车刚性部件说明/禁用态准确。'],
  99. ['part.transform', '刚性部件独立变换并保存覆盖', 'runtime:captureModelPartOverrides(root)', 'partOverrides 与稳定 interactionId;多个实例互不串改。', '两卡车实例改单部件,保存重开另一实例不受影响。'],
  100. ['part.soft-delete', '部件软删除与恢复', 'runtime:deleteSelected()', '被允许的部件 sceneDeleted/visible 持久化;可撤销恢复。', '实际删除、撤销、保存重开均一致;蒙皮不允许破坏骨架。'],
  101. ['object.delete', '删除根对象按钮 / Delete', 'runtime:deleteSelected()', '移除当前场景实例,不删除源模型项目/固定发布版本。', '按钮和键盘各验证;源项目不变,撤销和重开正确。'],
  102. ['panel.objects', '底部对象列表与选中', 'runtime:renderBottom(mode', '基线显示前 6 个摘要,完整对象仍在大纲;需明确截断。', '大于 6 个对象时列表说明准确,摘要点击选择正确。'],
  103. ['panel.binding', '设备绑定总表', 'runtime:renderBottom(mode', '基线语义列恒写已绑定;需要真实类型/缺失/冲突反馈。', '编辑字段即时同步,空/重复数据不得假标已绑定。'],
  104. ['panel.validation', '底部发布检查面板', 'runtime:renderBottom(mode', '显示当前逐项检查,不等于已发布。', '顶部校验/发布失败可定位检查面板,内容随修改更新。'],
  105. ['panel.logs', '操作日志', 'runtime:renderBottom(mode', '基线为静态示例且误称本地存储;本轮只需真实本次运行日志,不扩展服务端审计。', '实际操作产生对应时间/结果;API 模式不显示本地存储为真值。'],
  106. ]],
  107. ['历史与预览', [
  108. ['history.undo', '回退按钮 / Ctrl+Z', 'runtime:async undo()', '输入连续修改合并成合理历史步;恢复对象/模板/选择。', '属性、添加、删除、模板分别撤销,真实画面与文档一致。'],
  109. ['history.redo', '前进按钮 / Ctrl+Y / Ctrl+Shift+Z', 'runtime:async redo()', '撤销后重做,分叉编辑清 redo。', '按钮与两种快捷键各执行;新编辑后旧 redo 不可用。'],
  110. ['history.capacity', '60 步历史上限与边界', 'runtime:new SceneHistory(60)', '历史属于本次编辑会话;不宣称服务端版本历史。', '聚焦测试验证 60 步边界、空 undo/redo 与失焦快照。'],
  111. ['history.failure', '异步历史恢复失败/互斥', 'runtime:async restoreHistoryState', '失败不能推进索引或丢当前有效场景;忙碌时写操作需一致。', 'GLB 恢复失败、并发 undo/redo、保存混入均不半提交。'],
  112. ['preview.enter', '进入运行预览', 'runtime:togglePreview()', '当前默认预览只展示场景,未接模型 timeline/blueprint 自动执行。', '实际进入,辅助选择/手柄状态正常,模型可见。'],
  113. ['preview.exit', '按钮 / Escape 退出预览', 'runtime:handleKeyboard(event)', '退出后恢复编辑选择与状态;不得丢未存变换。', '两种退出方式均有效,输入焦点与缓存激活行为正确。'],
  114. ['preview.lock', '预览中禁止编辑', 'runtime:togglePreview()', '显示“场景编辑锁定”必须覆盖属性、删除、模板、导入和快捷键。', '尝试所有写入口,预览时文档不改变;退出后正常。'],
  115. ]],
  116. ['保存封面、发布与依赖', [
  117. ['cover.capture', '保存时截取当前三维场景封面', 'cover:export async function captureSceneCover', 'JPEG 最大边 640、当前相机;隐藏手柄/网格/高亮且恢复现场。', '截图与服务端图片可辨一致,像素实际有模型,UI 状态不被破坏。'],
  118. ['cover.atomic', '封面资产与文档同次保存', 'host:saveSceneDocumentWithCover', '封面 upload ticket 与 version 同一次 PUT 消费,不另存过期文档。', '检查资产/封面字段/当前版本相同,并真实列表加载图片。'],
  119. ['cover.failure', '截图/封面上传失败保留原封面', 'host:coverFailed', '正文可保存时给真实 warning;409 必须阻断且不得覆盖。', '截图失败、上传503、PUT409各自核对保留/提示/零错误发布。'],
  120. ['validation.complete', '环境、对象用途、模型加载检查', 'runtime:verifyScene(showToast', '纯环境允许;模型未完成解析必须阻断。', '空地板/纯环境/带模型和加载中分别核对检查结果。'],
  121. ['validation.bindings', '设备/物模型编号完整与唯一', 'runtime:verifyScene(showToast', '空白、重复编号按前后端合同处理,不自动替用户分配新业务身份。', '空、空格、重复与合法编号;错误项可见,发布被阻断。'],
  122. ['validation.references', '受控资源引用完整性', 'assets:hasReferenceSync', 'project/version/assetCode/sourceAssetId 必须指向实际固定资产,不能只测有字段。', '不存在编码/错误资产类型/跨项目引用显式拒绝;正确依赖通过。'],
  123. ['publish.saved', '发布场景按钮的真实 API 闭环', 'runtime:async publishScene()', '有编辑权时先保存含封面再发布;两步均成功才显示已发布。', 'POST 真正发布当前版本,列表状态与下游目录一致。'],
  124. ['publish.only', '只有发布权限时发布已存版本', 'runtime:if (this.readOnly)', 'publish-only 不先 PUT、不上传封面、不要求 update;服务器校验真值。', '隔离权限会话发布已存有效版本,零 update/upload 请求。'],
  125. ['publish.failure', '预检/保存/发布失败阻断', 'runtime:async publishScene()', '保存失败不 POST 发布;发布失败不假标已发布;保持错误恢复能力。', '预检错误、PUT409/503、POST失败及重试,版本/状态准确。'],
  126. ['publish.concurrent', '重复发布与上传/保存队列', 'host:publishDocument:', '整条 POST 完成前仍占 FIFO;重复操作不串版本。', '延迟上传/保存/发布并触发竞争,服务端只有完整合法版本。'],
  127. ['publish.fixed-model', '固定 SCENE_MODEL 版本与多个实例', 'api:collectSceneModelDependencies', '去重精确模型版本,不能随模型新发布静默换源版本。', '同模型多实例及另模型新版本,场景重开仍使用所存固定版本。'],
  128. ['publish.downstream', '发布场景供训练选择和静态还原', 'runtime:场景已发布,训练编排可以引用', '本轮只验证版本/目标/静态可见性;不承诺模型蓝图或原生动画自动执行。', '新场景出现在正式训练目录,绑定后狐狸/卡车可见且目标身份一致。'],
  129. ]],
  130. ['权限、缓存与未保存恢复', [
  131. ['permission.update', '场景细分编辑权限', 'runtime:this.readOnly =', '只按 content.scene.update;基线残留 content.update 需修,不由角色名推断。', '具更新权会话可编辑;无更新权的写入口和接口全部拒绝。'],
  132. ['permission.publish', '场景细分发布权限', 'runtime:this.canPublish =', '页面 content.scene 与 publish 动作分开;更新权不隐含发布。', '只更新不能发布;仅发布可发布已存版本;无页面权不可访问。'],
  133. ['permission.readonly', '只读仍可查看、搜索、选中和预览', 'runtime:applyAccessMode()', '禁写不应误禁观察控件;临时视图不保存到服务器。', '真实键盘搜索、选择、相机、预览,零内容写请求。'],
  134. ['recovery.autobuffer', '800ms 未保存恢复缓冲', 'runtime:markDirty(label', '仅写隔离浏览器恢复稿,不伪称自动入库。', '实际修改后等待,恢复稿存在但无自动 PUT;手动保存后入库。'],
  135. ['recovery.same-version', '同版本真实未保存恢复', 'host:sceneRecoveryMatchesProjectVersion', '先回到视口,须显式保存才入库;相同文档不应产生假恢复。', '真实修改后刷新,恢复/保存/再刷新;无注入假 localStorage 代替。'],
  136. ['recovery.stale-version', '不同版本恢复稿隔离', 'host:sceneRecoveryMatchesProjectVersion', '旧稿不能自动覆盖新服务器版本;下载供人工合并。', '另一会话先保存,新会话面对旧稿只能下载/隔离/明确丢弃。'],
  137. ['recovery.discard', '下载、保留、丢弃恢复稿', 'host:async function quarantineRecovery', '关闭/Escape 不算明确丢弃;他会话新写入稿不得被误删。', '按钮逐项核对本地隔离键、下载文件与服务器无意外写入。'],
  138. ['recovery.multi-session', '多标签/多会话恢复所有权', 'host:recoveryStoragePrefix', '会话键/nonce/锁避免覆盖别的未存稿;本地缓冲不冒充权限。', '两个编辑会话产生不同草稿,保存/丢弃一份不删另一份。'],
  139. ['leave.cancel', '关闭场景标签时取消离开', 'host:async function confirmLeave', '关闭确认保留当前 dirty 与恢复副本;返回列表或切普通标签不应提示。', '真实关闭确认的关闭/Escape、继续编辑,数据未丢;不把返回列表当关闭。'],
  140. ['leave.save', '保存并离开 / 放弃修改', 'host:async function confirmLeave', '等待保存完成并确认最终 dirty;明确放弃只影响当前工程会话。', '保存成功才离开;503/409留原页;放弃按确认执行。'],
  141. ['leave.busy', '加载/上传/发布途中离开', 'host:const resourcesBusy =', '资源未就绪阻止离开;进行中的保存/发布须等待最终结果。', '延迟资源与提交各验证取消/等待,旧请求不污染新项目。'],
  142. ['leave.role-switch', '角色切换覆盖后台场景未存稿', 'host:registerWorkspaceLeaveGuard', '全体守卫确认后才切角色;后一页取消不能抹掉前页 dirty。', '含后台场景的切角色确认取消/保存失败/成功后权限重建。'],
  143. ['lifecycle.cache', '标签失活 pause / 激活 resume', 'runtime:pause()', '停止后台 RAF、恢复时重算视口;后台实例不能抢当前页键盘。', '两场景标签切换、选择和未存值保留、后台无写/快捷键误动作。'],
  144. ['lifecycle.destroy', '关闭释放 WebGL/监听/资源', 'runtime:destroy()', '销毁后的异步回调无 DOM 写入,无残留全局事件和资产 URL。', '反复打开/关闭、加载中关闭边界,控制台无异常/泄漏事件。'],
  145. ['lifecycle.resize-theme', '桌面尺寸与明亮/暗黑可读性', 'runtime:resize()', '继承正式主题;所有可达控件可读、无截断遮挡。', '1920/1440 下工具栏、属性、模板与弹窗截图,主题切换无低对比。'],
  146. ]],
  147. ]
  148. export const unmountedWorkspace = [
  149. ['正式工作区入口', 'SceneEditorView.vue → SceneEditorWorkspace.vue 存在实现;当前场景路由不引用,不能纳入默认入口已通过数。'],
  150. ['对象管理', '正式工作区有层级折叠、锁定、复制、软删除恢复按钮;默认 legacy 大纲没有对应全部控件。'],
  151. ['变换和相机', '正式工作区有局部/世界空间、自定义移动吸附、前视/右视、双击与 F 聚焦;默认入口只提供既有 W/E/R、固定吸附、顶视/透视/聚焦。'],
  152. ['材质和阴影', '正式工作区提供颜色、透明度、投射/接收阴影;默认场景属性没有这些编辑控件,只还原模型发布数据。'],
  153. ['原生动画', '正式工作区有片段、速度、自动播放、循环和播放按钮;默认 legacy 场景没有这些控件,也未在 animate 中播放模型原生动画。'],
  154. ['运行组件', '正式工作区有持续旋转/往复/呼吸缩放/热点组件及启用、名称、轴、速度、幅度;默认入口未显示组件页签。'],
  155. ['语义扩展', '正式工作区有交互标识、标签、能力清单与资源引用详情;默认只有显示名、可见、实训目标、设备/物模型编号和语义类型。'],
  156. ['环境渲染编辑', '正式工作区有背景/透明背景/曝光/环境强度、半球光/主光、雾范围、车间剖切;默认入口只保存/恢复文档中的渲染参数。'],
  157. ['底部面板', '正式工作区有真实日志、绑定状态、问题定位、底部折叠;默认入口对应基线有静态信息和六项对象摘要。'],
  158. ]