From 33258657c3bba75c003e8bc959518465aef853d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Tue, 18 Aug 2026 21:10:41 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=9F=E4=B8=80UI=E7=BC=96=E8=BE=91=E5=99=A8?= =?UTF-8?q?=E6=96=B0=E5=BB=BA=E8=8A=82=E7=82=B9=E7=BB=84=E4=BB=B6=E7=8A=B6?= =?UTF-8?q?=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 前端新建页面根和人工节点默认组件状态设为通过 识别与合并新建节点默认组件状态设为通过 保留组件绑定结果对已触碰节点的状态回写 补充新建节点状态测试与技术方案说明 --- .../src-tauri/src/ui_editor/commands/merge.rs | 3 +- .../src/ui_editor/commands/recognition.rs | 5 +-- .../features/ui-editor/useUiEditorState.ts | 4 +-- .../tests/uiEditorState.test.ts | 34 +++++++++++++++++++ ...案】AI游戏创作智能体App实施计划-2026-06-24.md | 4 +++ 5 files changed, 45 insertions(+), 5 deletions(-) diff --git a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/merge.rs b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/merge.rs index e36f6bb41..206e545c7 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/merge.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/merge.rs @@ -283,7 +283,7 @@ mod materialize { name: container_name, description: container_description, layout_status: StageStatus::Passed, - components_status: StageStatus::Pending, + components_status: StageStatus::Passed, allow_llm_edit_layout: true, allow_llm_edit_component: true, source: NodeSource::Llm, @@ -451,6 +451,7 @@ mod tests { result.root.children_display_mode, ChildrenDisplayMode::Exclusive ); + assert_eq!(result.root.metadata.components_status, StageStatus::Passed); assert_eq!(result.root.children.len(), 2); } } diff --git a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/recognition.rs b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/recognition.rs index 0485f6013..0deabad40 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/recognition.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/ui_editor/commands/recognition.rs @@ -274,7 +274,7 @@ fn convert_node( name: source.name.clone(), description: source.description.clone(), layout_status: status, - components_status: StageStatus::Pending, + components_status: StageStatus::Passed, allow_llm_edit_layout: true, allow_llm_edit_component: true, source: NodeSource::Llm, @@ -436,6 +436,7 @@ mod tests { converted.transform.resolve(&root_rect), UIRect::new(Point2::new(50.0, 25.0), Vector2::new(100.0, 50.0)), ); + assert_eq!(converted.metadata.components_status, StageStatus::Passed); } #[test] @@ -646,7 +647,7 @@ pub(crate) async fn recognize_ui_impl( name: "页面根节点".to_string(), description: String::new(), layout_status: StageStatus::Passed, - components_status: StageStatus::Pending, + components_status: StageStatus::Passed, allow_llm_edit_layout: true, allow_llm_edit_component: true, source: NodeSource::System, diff --git a/apps/ai-game-creator-shell/src/features/ui-editor/useUiEditorState.ts b/apps/ai-game-creator-shell/src/features/ui-editor/useUiEditorState.ts index 2cb34d10d..0c151489a 100644 --- a/apps/ai-game-creator-shell/src/features/ui-editor/useUiEditorState.ts +++ b/apps/ai-game-creator-shell/src/features/ui-editor/useUiEditorState.ts @@ -103,7 +103,7 @@ function createPageRoot(state: State): Node { name: '页面根节点', description: '', layout_status: 'Passed', - components_status: 'Pending', + components_status: 'Passed', allow_llm_edit_layout: true, allow_llm_edit_component: true, source: 'System', @@ -127,7 +127,7 @@ function createHumanNode(state: State): Node { name: '新节点', description: '', layout_status: 'Passed', - components_status: 'Pending', + components_status: 'Passed', allow_llm_edit_layout: true, allow_llm_edit_component: true, source: 'Human', diff --git a/apps/ai-game-creator-shell/tests/uiEditorState.test.ts b/apps/ai-game-creator-shell/tests/uiEditorState.test.ts index 3f8ff0873..73b7f1da6 100644 --- a/apps/ai-game-creator-shell/tests/uiEditorState.test.ts +++ b/apps/ai-game-creator-shell/tests/uiEditorState.test.ts @@ -225,11 +225,45 @@ describe('useUiEditorState', () => { expect(result.current.state.ui_design_images['section-a']).toMatchObject({ metadata: { name: '任务页', role: 'Section', slave_to: 'page-a' }, }); + expect(result.current.state.ui_trees).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + root: expect.objectContaining({ + metadata: expect.objectContaining({ + layout_status: 'Passed', + components_status: 'Passed', + }), + }), + }), + ]), + ); expect( validateComponentRecognitionPrerequisites(result.current.state), ).toEqual([]); }); + it('marks manually inserted nodes as passed before component binding', () => { + const { result } = renderHook(() => useUiEditorState()); + act(() => { + result.current.addDesignImages([{ id: 'page', image: image('Page') }]); + }); + const rootId = result.current.state.ui_trees[0]!.root.id; + + act(() => { + expect(result.current.insertNode('page', rootId)).toEqual({ + ok: true, + value: expect.any(String), + }); + }); + + expect( + result.current.state.ui_trees[0]!.root.children[0]?.metadata, + ).toMatchObject({ + layout_status: 'Passed', + components_status: 'Passed', + }); + }); + it('adds a batch atomically and rejects duplicates and limits', () => { const { result } = renderHook(() => useUiEditorState()); diff --git a/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md b/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md index 686401ad9..8eabae4fe 100644 --- a/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md +++ b/docs/technical/【技术方案】AI游戏创作智能体App实施计划-2026-06-24.md @@ -1108,6 +1108,10 @@ game-project/ - UI State 原子安装保留最近一个有效 `.previous` 恢复副本。主文件损坏时仅在恢复副本通过同一严格校验后恢复;恢复安装与保存共用项目写锁,并在持锁后重新读取主文件,已有并发保存的有效新版本时直接返回而不安装旧副本。任一候选均不可信则停在加载错误,前端禁编辑和保存。新建 UI 资源先登记并安装合法 envelope,任一步失败补偿 manifest/文件,避免把空 JSON 留给资源卡。 - 图片路径只需是安全项目相对路径,不要求外部图片仍存在或已登记为 manifest asset;缺失媒体只导致 preview 占位。`imageOrder`、当前选择、缩放、面板开关和 preview URL 不写入 State,加载后由 State 派生。保存冻结提交快照,保存期间的新编辑继续保持 dirty;AI state lock 和加载期间禁保存。 +## 2026-08-18 UI Editor 新建节点组件状态 + +- 所有非组件绑定流程创建的 UI Editor 节点,`components_status` 与 `layout_status` 一致初始化为 `Passed`,覆盖前端新建页面根 / 人工节点,以及 Rust 结构识别与合并产生的节点。组件绑定命令仍只对 LLM 显式返回的节点写入其 `Passed` 或 `NeedReview` 结果;未返回的节点状态不变。 + ## 2026-08-18 UI Editor 节点预览可见性 - 节点显示 / 隐藏是编辑器页面级临时状态,不新增 Rust `Node` 字段,不进入 UI State 保存快照、运行时数据或后端契约。`NodeId` 在 State 内全局唯一,隐藏状态直接使用页面会话级 `Set`;切换界面图保留,跨界面移动随节点保留,清空、重新加载、删除节点或删除界面图时清理失效 ID。