统一UI编辑器新建节点组件状态

前端新建页面根和人工节点默认组件状态设为通过

识别与合并新建节点默认组件状态设为通过

保留组件绑定结果对已触碰节点的状态回写

补充新建节点状态测试与技术方案说明
This commit is contained in:
2026-08-18 21:10:41 +08:00
parent 37f7f710f3
commit 33258657c3
5 changed files with 45 additions and 5 deletions
@@ -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);
}
}
@@ -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,
@@ -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',
@@ -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());
@@ -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<NodeId>`;切换界面图保留,跨界面移动随节点保留,清空、重新加载、删除节点或删除界面图时清理失效 ID。