From b40fcbdd350472160b3bb6c452898f1138f22e7a Mon Sep 17 00:00:00 2001 From: yu <191972707@qq.com> Date: Thu, 29 Oct 2026 15:33:07 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=A0=B9=E6=B2=BB=E4=BF=9D=E5=AD=98?= =?UTF-8?q?=E5=BF=85=E5=BC=B9=E7=A3=81=E7=9B=98=E5=86=B2=E7=AA=81=E2=80=94?= =?UTF-8?q?=E2=80=94=E7=BC=96=E8=BE=91=E4=B8=8D=E5=86=8D=E6=B1=A1=E6=9F=93?= =?UTF-8?q?=E4=B9=90=E8=A7=82=E9=94=81=E5=9F=BA=E5=87=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - editorStore 新增 baseUpdatedAt(磁盘基准版本),仅 loadFlow/syncSavedFlow 更新 - 保存 expectedUpdatedAt 改用 baseUpdatedAt;此前用每次编辑都会拨快的 flow.meta.updatedAt 做比对,导致任何编辑后首次保存必然误判冲突 - 移除 flows:save/get 诊断日志(保留内容一致放行逻辑) --- src/main/index.ts | 4 +++- src/renderer/src/pages/EditorPage.tsx | 4 +++- src/renderer/src/store/editorStore.ts | 20 +++++++++++++++++--- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/main/index.ts b/src/main/index.ts index 77fda1c..9291957 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -127,7 +127,9 @@ function registerIpc(): void { for (const flow of createExampleFlows(url)) saveFlow(flow); return listFlows(); }); - ipcMain.handle("flows:get", (_event, id: string) => getFlow(id)); + ipcMain.handle("flows:get", (_event, id: string) => { + return getFlow(id); + }); ipcMain.handle("flows:save", (_event, flow: FlowDefinition, opts?: FlowSaveOptions): FlowSaveResult => { if (!opts?.force && opts?.expectedUpdatedAt) { let disk: FlowDefinition | null = null; diff --git a/src/renderer/src/pages/EditorPage.tsx b/src/renderer/src/pages/EditorPage.tsx index d1373f6..f0bf626 100644 --- a/src/renderer/src/pages/EditorPage.tsx +++ b/src/renderer/src/pages/EditorPage.tsx @@ -65,7 +65,9 @@ export function EditorPage({ catalog, onToast, onBack }: EditorPageProps) { setSaving(true); try { const result = await window.rpa.flows.save(current, { - expectedUpdatedAt: current.meta?.updatedAt || undefined + // 用「磁盘基准版本」做乐观锁,不能用 current.meta.updatedAt—— + // 每次本地编辑都会拨快它,会导致每次保存都误判磁盘冲突 + expectedUpdatedAt: useEditorStore.getState().baseUpdatedAt || undefined }); if (result.conflict) { if (opts?.interactive) { diff --git a/src/renderer/src/store/editorStore.ts b/src/renderer/src/store/editorStore.ts index 1c2bf21..5e0e736 100644 --- a/src/renderer/src/store/editorStore.ts +++ b/src/renderer/src/store/editorStore.ts @@ -57,6 +57,10 @@ function uniqueOutputVar(base: string, nodes: FlowNode[]): string { interface EditorState { flow: FlowDefinition | null; + /** 乐观锁基准:最近一次从磁盘加载/保存成功返回的 meta.updatedAt。 + * 保存时以此为 expectedUpdatedAt;不能直接用 flow.meta.updatedAt, + * 因为 commit() 每次编辑都会拨快它,会导致每次保存都误判磁盘冲突。 */ + baseUpdatedAt: string | null; catalog: Catalog | null; selectedNodeId: string | null; dirty: boolean; @@ -104,6 +108,7 @@ export const useEditorStore = create((set, get) => { return { flow: null, + baseUpdatedAt: null, catalog: null, selectedNodeId: null, dirty: false, @@ -116,7 +121,14 @@ export const useEditorStore = create((set, get) => { // 切换流程时清掉上一次的运行面板状态,避免显示旧流程的运行结果 const runState = useRunStore.getState(); if (!runState.running) runState.clear(); - set({ flow, selectedNodeId: null, dirty: false, past: [], future: [] }); + set({ + flow, + selectedNodeId: null, + dirty: false, + past: [], + future: [], + baseUpdatedAt: flow.meta?.updatedAt ?? null + }); }, selectNode: (id) => set({ selectedNodeId: id }), @@ -340,9 +352,11 @@ export const useEditorStore = create((set, get) => { }, markSaved: () => set({ dirty: false }), - syncSavedFlow: (flow) => set({ flow, dirty: false }), + syncSavedFlow: (flow) => + set({ flow, dirty: false, baseUpdatedAt: flow.meta?.updatedAt ?? null }), - reset: () => set({ flow: null, selectedNodeId: null, dirty: false, past: [], future: [] }) + reset: () => + set({ flow: null, baseUpdatedAt: null, selectedNodeId: null, dirty: false, past: [], future: [] }) }; });