From c7722d8372dce6fbbc9a134f8dc7ee5c44d54914 Mon Sep 17 00:00:00 2001 From: Linghong Date: Wed, 5 Aug 2026 10:29:17 +0000 Subject: [PATCH] =?UTF-8?q?=E6=B8=85=E7=90=86=E4=B8=A5=E6=A0=BC=E5=B8=83?= =?UTF-8?q?=E5=B1=80=E4=BF=9D=E5=AD=98=E9=80=9A=E9=81=93=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E5=90=8E=E7=95=99=E4=B8=8B=E7=9A=84=E6=AD=BB=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 死代码扫描(八路并行 + cargo 全量核对)确认:Rust 侧零新增——13 条 dead_code 警告在 master 与 HEAD 上引用计数逐一相同,全是既有的。死代码集中在 TS 侧, 且几乎同源:2fa2f245c 删掉严格布局保存通道时,删了调用点没删被调用的能力。 本次清理四条真死代码 + 一条会导致类型漂移的重复声明: 1. snapSelectedLayerToPerfectPixels 的 catch 里「operation 已形成但 POST 未 发出」分支恒不可达。从 operation 赋值到 perfectPixelPostAttempted = true 之间只剩 Set.add、纯函数、状态更新器,以及带 .catch 的 flush 与内部吞异常 的 savePerfectPixelOperation,没有任何语句能抛。它挂着一句永不显示的用户 文案,留着只会让人以为该失败态另有提示。 2. retryPerfectPixelOperation 的 postAttempted 三元同理,一并去掉分档。 3. saveEditorProjectLayout 的第三参数(signal / deadlineAt 注入)与 EditorProjectLayoutSaveOptions 失去全部调用方,函数体内两处判断恒走默认。 这里正是「每次重试重起 60 秒 deadline」的所在处,留着会让人以为调用方还能 控制它。 4. 测试文件里 createEmptyEditorProjectSnapshot 全仓零引用——eslint 的 unused-imports 不覆盖模块级函数声明,门禁放过了它。 5. useImageCanvasGenerationWorkflow 改为 import 现成的 CanvasGenerationDialogDraft,删掉就地手写的同构类型。两份同构类型各自演化、 改一处不会让另一处报错,是实打实的类型漂移温床。 其余七条(多余的 export、只有测试消费的路径、决策日志里指向已删符号的历史 引用)符号本身都活着,属于表面整洁,本次不动。 Co-Authored-By: Claude Opus 5 --- .../useImageCanvasGenerationWorkflow.ts | 22 ++++++++------ .../useImageCanvasProjectPersistence.test.tsx | 24 --------------- .../image-editor/editorProjectClient.ts | 29 ++++++------------- 3 files changed, 22 insertions(+), 53 deletions(-) diff --git a/src/components/image-editor/useImageCanvasGenerationWorkflow.ts b/src/components/image-editor/useImageCanvasGenerationWorkflow.ts index 08b539202..bd81193d1 100644 --- a/src/components/image-editor/useImageCanvasGenerationWorkflow.ts +++ b/src/components/image-editor/useImageCanvasGenerationWorkflow.ts @@ -121,6 +121,7 @@ import { readPerfectPixelOperations, savePerfectPixelOperation, } from './perfectPixelOperationStore'; +import type { CanvasGenerationDialogDraft } from './useCanvasGenerationDialogs'; import { applyQueuedEditorGenerationProject, createEditorGenerationMediaUploadId, @@ -913,9 +914,7 @@ type GenerationWorkflowOptions = { layerCounterRef: MutableRefObject; generateDialog: GenerateDialogState | null; setGenerateDialog: Dispatch>; - openCanvasGenerationDialog: ( - dialog: Omit & { id?: string }, - ) => string; + openCanvasGenerationDialog: (dialog: CanvasGenerationDialogDraft) => string; activateCanvasGenerationDialog: ( targetDialog: CanvasGenerationDialogState, ) => void; @@ -2534,11 +2533,14 @@ export function useImageCanvasGenerationWorkflow({ // 中文注释:保留服务端原文(例如 assetKind 校验失败)便于定位,同时附上对账结论。 // 结果未知时必须保留 operation 快照并停在 pending-confirmation;这既不会把在途结果 // 谎报成失败,也不会开放一条会创建新 identity 的普通重提路径。 + // + // 这里曾有第三条分支「operation 已形成但 POST 未发出」。严格布局保存通道删除后它已 + // 不可达:从 operation 赋值到 `perfectPixelPostAttempted = true` 之间只剩 Set.add、 + // 纯函数、状态更新器,以及 `await flush(...).catch(() => undefined)` 与内部吞异常的 + // `savePerfectPixelOperation`,没有任何语句能抛。留着它只会让人以为该失败态另有提示。 const errorMessage = reconciledMessage ? `${serverMessage ? `${serverMessage} ` : ''}${reconciledMessage}请稍后继续核对,或显式重试同一操作。` - : perfectPixelOperation && !perfectPixelPostAttempted - ? `完美像素请求尚未发出:${serverMessage ?? '提交前准备失败'} 请在原占位重试,或删除占位后重来。` - : (serverMessage ?? '完美像素处理失败'); + : (serverMessage ?? '完美像素处理失败'); if ( perfectPixelDialogId && hasCanvasGenerationDialogById(perfectPixelDialogId) @@ -2763,12 +2765,14 @@ export function useImageCanvasGenerationWorkflow({ error instanceof Error && error.message.trim() ? error.message : '完美像素处理失败'; + // 中文注释:文案不再按 `postAttempted` 分档——严格布局保存通道删除后,从进入 try 到 + // `postAttempted = true` 之间已经没有任何能抛异常的语句(flush 带 `.catch`、 + // `savePerfectPixelOperation` 内部吞异常,其余是纯函数与状态更新器),所以走到这里 + // 时 POST 必然已经发出过。 updateCanvasGenerationDialogById(normalizedDialogId, (current) => ({ ...current, status: 'failed', - errorMessage: postAttempted - ? errorMessage - : `完美像素请求尚未发出:${errorMessage} 请在原占位重试同一操作。`, + errorMessage, })); } finally { releaseActiveInlineGenerationDialog(normalizedDialogId); diff --git a/src/components/image-editor/useImageCanvasProjectPersistence.test.tsx b/src/components/image-editor/useImageCanvasProjectPersistence.test.tsx index 72efe2db1..51b80e849 100644 --- a/src/components/image-editor/useImageCanvasProjectPersistence.test.tsx +++ b/src/components/image-editor/useImageCanvasProjectPersistence.test.tsx @@ -163,30 +163,6 @@ function createCompletedEditorProjectSnapshot( }; } -function createEmptyEditorProjectSnapshot( - revision = 0, - title = '空画布项目', -): EditorProjectSnapshot { - return { - projectId: 'editor-project-default', - title, - canvas: { - canvasId: 'editor-project-default:canvas:default', - projectId: 'editor-project-default', - title: '默认画布', - viewport: { x: 0, y: 0, scale: 1 }, - layers: [], - revision, - layoutStorageVersion: 0, - updatedAt: `2026-06-12T00:00:0${revision}.000Z`, - }, - viewport: { x: 0, y: 0, scale: 1 }, - layers: [], - resources: [], - updatedAt: `2026-06-12T00:00:0${revision}.000Z`, - }; -} - it('merges pending geometry and dialog edits while retaining backend additions and deletions', () => { const authoritativeItems: EditorProjectLayerSnapshot[] = [ { diff --git a/src/services/image-editor/editorProjectClient.ts b/src/services/image-editor/editorProjectClient.ts index c01531888..3135301fb 100644 --- a/src/services/image-editor/editorProjectClient.ts +++ b/src/services/image-editor/editorProjectClient.ts @@ -581,11 +581,6 @@ export type EditorProjectLayoutSaveInput = { expectedRevision: number; }; -export type EditorProjectLayoutSaveOptions = { - signal?: AbortSignal; - deadlineAt?: number; -}; - export type EditorProjectLayoutSaveResult = { projectId: string; canvasId: string; @@ -820,29 +815,23 @@ export async function deleteEditorProject(projectId: string) { return response.deletedProjectId; } +// 中文注释:这里曾接受第三参数(调用方注入的 `signal` / `deadlineAt`),只服务于已删除的 +// 严格布局保存通道;该通道删除后全部调用点都只传两个参数,注入分支恒不生效。一并摘掉, +// 免得后来者以为调用方还能控制这次保存的取消与截止。 export async function saveEditorProjectLayout( projectId: string, input: EditorProjectLayoutSaveInput, - options: EditorProjectLayoutSaveOptions = {}, ) { - const deadlineAt = - typeof options.deadlineAt === 'number' && - Number.isFinite(options.deadlineAt) - ? options.deadlineAt - : Date.now() + 60_000; return requestJson( `${EDITOR_PROJECT_API_BASE}/${encodeURIComponent(projectId)}`, - { - ...jsonRequest('PATCH', { - viewport: input.viewport, - layers: input.layers, - expectedRevision: input.expectedRevision, - }), - ...(options.signal ? { signal: options.signal } : {}), - }, + jsonRequest('PATCH', { + viewport: input.viewport, + layers: input.layers, + expectedRevision: input.expectedRevision, + }), '保存图片画布工程失败', // 布局保存会被生成提交链同步等待,必须连鉴权恢复和响应体读取一起有界。 - { deadlineAt }, + { deadlineAt: Date.now() + 60_000 }, ); }