From 15caf1cafc4a092ee15f85c247b3c63873f7fe72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Thu, 3 Sep 2026 11:05:04 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B6=E6=95=9B=20UI=20=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E5=99=A8=E9=94=81=E4=B8=8E=E5=8E=86=E5=8F=B2=E4=BA=8B=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增统一的加锁并包裹历史事务操作 将 AI 建议、识别、合并和批量绑定改用统一入口 --- .../src/features/ui-editor/useUiEditorState.ts | 7 +++++++ .../src/view/ui-editor/useUiEditorPage.ts | 13 +++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) 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 cf85bd10b..7d3966fd1 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 @@ -658,6 +658,12 @@ export function useUiEditorState(initialState: State = EMPTY_UI_EDITOR_STATE) { [], ); + const runWithStateLockedAndHistory = useCallback( + async (operation: (snapshot: State) => Promise): Promise => + runInHistoryTransaction(() => runWithStateLocked(operation)), + [runInHistoryTransaction, runWithStateLocked], + ); + const setImageName = useCallback( (id: UIDesignImageId, name: string): UiEditorOperationResult => { const blocked = guard(); @@ -1544,6 +1550,7 @@ export function useUiEditorState(initialState: State = EMPTY_UI_EDITOR_STATE) { endHistoryTransaction, cancelHistoryTransaction, runInHistoryTransaction, + runWithStateLockedAndHistory, resetHistory, isLocked, diff --git a/apps/ai-game-creator-shell/src/view/ui-editor/useUiEditorPage.ts b/apps/ai-game-creator-shell/src/view/ui-editor/useUiEditorPage.ts index e7a085ec6..29dc33c6a 100644 --- a/apps/ai-game-creator-shell/src/view/ui-editor/useUiEditorPage.ts +++ b/apps/ai-game-creator-shell/src/view/ui-editor/useUiEditorPage.ts @@ -942,7 +942,7 @@ export function useUiEditorSession( setSuggestionStatus(null); setIsSuggesting(true); try { - await editor.runWithStateLocked(async (snapshot) => { + await editor.runWithStateLockedAndHistory(async (snapshot) => { const suggestions = await invoke( 'suggest_ui_design_semantic', { projectPath, state: snapshot }, @@ -965,7 +965,7 @@ export function useUiEditorSession( setRecognitionStatus(null); setIsRecognizing(true); try { - await editor.runWithStateLocked(async (snapshot) => { + await editor.runWithStateLockedAndHistory(async (snapshot) => { const result = await invoke('recognize_ui', { projectPath, state: snapshot, @@ -990,7 +990,7 @@ export function useUiEditorSession( setMergeStatus(null); setIsMerging(true); try { - await editor.runWithStateLocked(async (snapshot) => { + await editor.runWithStateLockedAndHistory(async (snapshot) => { const result = await invoke('merge_ui', { state: snapshot }); editor.replaceState(applyMergeResult(snapshot, result)); setSelectedNodeId(null); @@ -1008,7 +1008,7 @@ export function useUiEditorSession( setBindingStatus(null); setIsBinding(true); try { - await editor.runWithStateLocked(async (snapshot) => { + await editor.runWithStateLockedAndHistory(async (snapshot) => { const allSpriteIds = Object.keys(snapshot.sprite_assets); const batches: string[][] = []; for ( @@ -1228,6 +1228,11 @@ export function useUiEditorSession( deleteNode, openClearDialog: () => setClearOpen(true), }, + history: { + ...editor.historyState, + undo: editor.undo, + redo: editor.redo, + }, inspector: { isLocked: editor.isLocked, projectPath,