From 07854d7c6a25136e2e5afb7595b36bf42f97235b Mon Sep 17 00:00:00 2001 From: 134 Date: Thu, 18 Jun 2026 14:45:37 +0800 Subject: [PATCH] fix: unify detail processing placeholders --- app/api/canvas/local-edit/route.ts | 15 +- .../agents/AgentGenerationWorkspaceDarkV2.tsx | 650 +++++++++++++++--- 2 files changed, 553 insertions(+), 112 deletions(-) diff --git a/app/api/canvas/local-edit/route.ts b/app/api/canvas/local-edit/route.ts index eb73f081c..389f35ba4 100644 --- a/app/api/canvas/local-edit/route.ts +++ b/app/api/canvas/local-edit/route.ts @@ -479,23 +479,24 @@ function buildScaleAdjustPrompt( .join("\n"); return [ - "输入图片1是原始干净图,也是最终输出必须继承的唯一画面基底。", - "输入图片2是定位参考图:它只用于告诉你用户框选的目标主体位置。输入图片2里的彩色框、编号、标签、半透明遮罩、文字和 UI 只是定位标记,绝不能出现在最终画面中。", + "输入图片1是定位参考图:它只用于告诉你用户框选的目标主体位置。输入图片1里的彩色框、编号、标签、半透明遮罩、文字和 UI 只是定位标记,绝不能出现在最终画面中。", + "输入图片2是原始干净图,也是最终输出必须继承的唯一画面基底。如果系统或模型只能读取一张参考图,则必须使用输入图片1中的框选位置定位目标,同时主动去除所有定位标记并恢复干净画面。", "系统已根据用户框选区域计算出下方每个区域的原图坐标;框选区域只是定位目标主体的搜索范围,不是最终画面的裁切块、贴片或蒙版边界。", - "最终结果必须保持输入图片1的原始画幅比例、构图边界、镜头透视、光线、色温、材质质感和清晰度。", + "最终结果必须保持原始干净图的画幅比例、构图边界、镜头透视、光线、色温、材质质感和清晰度。", "请不要生成任何彩色框、矩形边框、编号圆点、提示词气泡、标注文字、UI 控件或半透明色块。", "", `任务:对用户框选的主体物体做“比例调整”,统一执行${actionLabel}。目标主体调整后的视觉尺寸必须约为原主体的 ${targetLabel},普通用户肉眼应能清楚看出主体尺寸已经变化;如果输出看起来和原图一样,就是失败。`, regionLines, "", "关键要求:", - `1. 只调整目标主体物体本身的整体视觉比例,必须等比缩放到约 ${targetLabel},不得保留原尺寸,不得压扁、拉伸、扭曲、改变外观结构、改变材质、改变颜色、改变文字或图案。`, + `1. 只调整目标主体物体本身的整体视觉比例,必须等比缩放到约 ${targetLabel},不得保留原尺寸;请把主体轮廓宽度和高度都调整到约 ${targetLabel},而不是仅改变亮度、清晰度、颜色或画面裁切。`, "2. 严禁把整个矩形框选区域当成图片块整体缩放、平移、复制、裁切或贴回;最终画面不得出现矩形拼接边缘、色差硬边、补丁感、裁切线或局部贴片痕迹。", - "3. 缩小时,目标主体应围绕原位置视觉中心自然变小;主体缩小后露出的区域必须根据周围真实背景、阴影、遮挡、纹理和透视进行无缝补全。", - "4. 放大时,目标主体应围绕原位置视觉中心自然变大;边缘与遮挡关系要合理,不能变形,也不能产生突兀裁切。", + `3. 缩小时,目标主体应围绕原位置视觉中心自然变小到约 ${targetLabel};主体缩小后,原来被遮挡的背景、桌面、墙面、阴影、纹理和透视必须被重新生成并无缝补全,选区内应出现明显新增留白或背景。`, + `4. 放大时,目标主体应围绕原位置视觉中心自然变大到约 ${targetLabel};边缘与遮挡关系要合理,不能变形,也不能产生突兀裁切。`, "5. 框选区域内非目标主体的背景、墙面、桌面、植物、文字和其它物体应保持原场景逻辑,不要跟着主体一起缩放。", "6. 未受比例调整影响的其它画面区域必须尽量保持原图不变,不允许整体重绘、改色、补光、移动物体或改变背景细节。", "7. 最终输出必须是一张完整、干净、无缝的照片,不得出现任何选区框、说明文字、对比线、比例数字或 UI 元素。", + "8. 输出前自检:如果目标主体大小与原图相比没有明显变化,必须重新生成;禁止返回看起来和原图相同的结果。", ].join("\n"); } @@ -607,7 +608,7 @@ export async function POST(request: NextRequest) { region.referenceImages.map((reference) => reference.url) ); const referenceImages = isScaleAdjustOperation - ? [sourceImageUrl, annotatedUpload.url, ...regionReferenceImageUrls] + ? [annotatedUpload.url, sourceImageUrl, ...regionReferenceImageUrls] : [sourceImageUrl, ...regionReferenceImageUrls]; const resolvedAspectRatio = resolveLocalEditAspectRatio( body.aspectRatio, diff --git a/components/agents/AgentGenerationWorkspaceDarkV2.tsx b/components/agents/AgentGenerationWorkspaceDarkV2.tsx index 3aae8dbfd..38bbeebad 100644 --- a/components/agents/AgentGenerationWorkspaceDarkV2.tsx +++ b/components/agents/AgentGenerationWorkspaceDarkV2.tsx @@ -10,6 +10,7 @@ import { useRef, useState, type CSSProperties, + type PointerEvent as ReactPointerEvent, type ReactNode, type SyntheticEvent, } from "react"; @@ -23,6 +24,7 @@ import { ChevronDown, ChevronUp, Download, + GitCompareArrows, ImagePlus, Loader2, Maximize2, @@ -733,6 +735,7 @@ type DirectDetailGenerationImage = { title?: string; subtitle?: string; copy?: string; + compareSourceUrl?: string | null; }; type DirectDetailReviewResult = { @@ -757,6 +760,21 @@ function isHttpImageUrl(url?: string) { return /^https?:\/\//i.test(String(url || "").trim()); } +function normalizeResultCompareSourceUrl( + resultUrl?: string | null, + sourceUrl?: string | null +) { + const normalizedResultUrl = String(resultUrl || "").trim(); + const normalizedSourceUrl = String(sourceUrl || "").trim(); + if (!isHttpImageUrl(normalizedSourceUrl)) { + return null; + } + if (normalizedResultUrl && normalizedSourceUrl === normalizedResultUrl) { + return null; + } + return normalizedSourceUrl; +} + function getDetailLocalEditUploadFileName(file: File) { const extension = file.name.toLowerCase().split(".").pop() || "jpg"; const baseName = @@ -809,8 +827,22 @@ function getDetailScaleAdjustLabel(scalePercent: DetailResultScalePercent) { return scalePercent > 0 ? `放大 ${scalePercent}%` : `缩小 ${Math.abs(scalePercent)}%`; } +function getDetailScaleAdjustTargetLabel(scalePercent: DetailResultScalePercent) { + return `${Math.round((1 + scalePercent / 100) * 100)}%`; +} + function getDetailScaleAdjustRegionPrompt(scalePercent: DetailResultScalePercent | null) { - return scalePercent ? `比例调整:${getDetailScaleAdjustLabel(scalePercent)}` : "比例调整"; + if (!scalePercent) return "比例调整"; + const actionLabel = getDetailScaleAdjustLabel(scalePercent); + const targetLabel = getDetailScaleAdjustTargetLabel(scalePercent); + const scaleVerb = scalePercent > 0 ? "放大" : "缩小"; + return [ + `对框选范围内的主物体执行等比${actionLabel},调整后主体视觉尺寸必须约为原来的 ${targetLabel},需要肉眼明显看出已经${scaleVerb}。`, + "只改变目标主体的尺寸,不改变主体外观、颜色、材质、图案和文字内容;不要把整个框选矩形当成图片块缩放。", + scalePercent < 0 + ? "主体缩小后露出的背景、桌面、墙面、阴影和遮挡关系必须自然补全。" + : "主体放大后边缘、遮挡和透视必须自然衔接。", + ].join(" "); } function DetailResultLocalEditDialog({ @@ -1182,6 +1214,7 @@ function DetailResultLocalEditDialog({ ) : null} {submitting ? ( ) : null} @@ -1705,6 +1738,7 @@ interface ReplacementResultRecord { text: string; status: Extract; updatedAt: number; + compareSourceUrl?: string | null; } interface ReplacementExecutionContext { @@ -1929,68 +1963,162 @@ function saveStoredAgentPendingGenerations(items: LocalGenerationPendingState[]) } } -function DetailResultProcessingScanOverlay({ label }: { label: string }) { +const DETAIL_RESULT_PROCESSING_STAGES = [ + "解码图像", + "定位选区", + "分离主体", + "重绘背景", + "融合边缘", + "检查细节", + "输出结果", +]; + +function DetailResultProcessingScanOverlay({ + imageUrl, + label, +}: { + imageUrl?: string; + label: string; +}) { + const [progress, setProgress] = useState(6); + + useEffect(() => { + const startedAt = Date.now(); + const durationMs = 240_000; + const timer = window.setInterval(() => { + const elapsed = Date.now() - startedAt; + const linear = Math.min(1, elapsed / durationMs); + const eased = 1 - Math.pow(1 - linear, 1.8); + const drift = Math.sin(elapsed / 3200) * 1.2; + const next = Math.max(6, Math.min(96, Math.round(eased * 96 + drift))); + setProgress((current) => Math.max(current, next)); + }, 720); + + return () => window.clearInterval(timer); + }, [imageUrl, label]); + + const stageIndex = Math.min( + DETAIL_RESULT_PROCESSING_STAGES.length - 1, + Math.floor((progress / 100) * DETAIL_RESULT_PROCESSING_STAGES.length) + ); + const stageName = DETAIL_RESULT_PROCESSING_STAGES[stageIndex] || "处理中"; + return ( -
- + + {isHttpImageUrl(imageUrl) ? ( + + ) : ( +
+ )} +
-
-
-
-
- - -
- - {label}
+
+
+ + {label} + {progress}% +
+
+ {String(stageIndex + 1).padStart(2, "0")} + {stageName} +
+
+
+
+
+ ); +} + +function DetailResultProcessingPlaceholderCard({ + imageUrl, + label, +}: { + imageUrl?: string | null; + label: string; +}) { + return ( +
+
); } @@ -2012,6 +2140,169 @@ function ResultProcessedHintBubble({ label }: { label: string }) { ); } +function DetailResultCompareImage({ + resultUrl, + compareSourceUrl, + alt, + imageClassName, + imageStyle, + previewWidth = 720, + previewQuality = 78, + onClick, + onError, + toggleClassName, +}: { + resultUrl: string; + compareSourceUrl?: string | null; + alt: string; + imageClassName?: string; + imageStyle?: CSSProperties; + previewWidth?: number; + previewQuality?: number; + onClick?: () => void; + onError?: (event: SyntheticEvent) => void; + toggleClassName?: string; +}) { + const compareFrameRef = useRef(null); + const [isCompareMode, setIsCompareMode] = useState(false); + const [compareSplitPercent, setCompareSplitPercent] = useState(50); + const [isDraggingCompare, setIsDraggingCompare] = useState(false); + const sourceUrl = normalizeResultCompareSourceUrl(resultUrl, compareSourceUrl); + + useEffect(() => { + setIsCompareMode(false); + setCompareSplitPercent(50); + setIsDraggingCompare(false); + }, [resultUrl, sourceUrl]); + + const updateCompareSplit = useCallback((clientX: number) => { + const frame = compareFrameRef.current; + if (!frame) return; + const rect = frame.getBoundingClientRect(); + if (rect.width <= 0) return; + const nextPercent = ((clientX - rect.left) / rect.width) * 100; + setCompareSplitPercent(Math.max(5, Math.min(95, nextPercent))); + }, []); + + const handleComparePointerDown = useCallback( + (event: ReactPointerEvent) => { + if (!sourceUrl) return; + event.preventDefault(); + event.stopPropagation(); + updateCompareSplit(event.clientX); + setIsDraggingCompare(true); + try { + event.currentTarget.setPointerCapture(event.pointerId); + } catch { + // Pointer capture can fail if the browser has already cancelled the pointer. + } + }, + [sourceUrl, updateCompareSplit] + ); + + const handleComparePointerMove = useCallback( + (event: ReactPointerEvent) => { + if (!isDraggingCompare || !sourceUrl) return; + event.preventDefault(); + event.stopPropagation(); + updateCompareSplit(event.clientX); + }, + [isDraggingCompare, sourceUrl, updateCompareSplit] + ); + + const handleComparePointerEnd = useCallback( + (event: ReactPointerEvent) => { + if (!isDraggingCompare) return; + event.preventDefault(); + event.stopPropagation(); + setIsDraggingCompare(false); + try { + event.currentTarget.releasePointerCapture(event.pointerId); + } catch { + // Ignore release failures for cancelled pointer sequences. + } + }, + [isDraggingCompare] + ); + + return ( +
+ + {isCompareMode && sourceUrl ? ( + <> +
+ +
+
+
+ +
+
+ 新图 +
+
+ 原图 +
+ + ) : null} + {sourceUrl ? ( + + ) : null} +
+ ); +} + function AnimatedGenerationPlaceholderCard(params: { title: string; description: string; @@ -2257,6 +2548,9 @@ export function AgentGenerationWorkspaceDarkV2({ const [processedResultHintByUrl, setProcessedResultHintByUrl] = useState< Record >({}); + const [resultCompareSourceByUrl, setResultCompareSourceByUrl] = useState< + Record + >({}); const [replacementResultState, setReplacementResultState] = useState( () => createEmptyReplacementResultState() ); @@ -3565,20 +3859,36 @@ export function AgentGenerationWorkspaceDarkV2({ return; } const inferredStatus = inferReplacementCardStatusFromText(result.text); + const previousRecord = nextModeState[cardId]; + const referenceCard = + currentResultModeType === "detail_replacement" + ? detailReplacementReferenceCards.find((card) => card.id === cardId) + : skuReplacementReferenceCards.find((card) => card.id === cardId); + const resultUrl = result.url || null; + const previousUrl = + previousRecord?.url && previousRecord.url !== resultUrl + ? previousRecord.url + : null; + const referenceSourceUrl = + referenceCard?.imageUrl || referenceCard?.previewUrl || null; const nextRecord: ReplacementResultRecord = { - url: result.url || null, + url: resultUrl, text: result.text || "", status: inferredStatus === "passthrough" || inferredStatus === "fallback" ? inferredStatus : "completed", updatedAt: Date.now(), + compareSourceUrl: normalizeResultCompareSourceUrl( + resultUrl, + previousUrl || referenceSourceUrl || previousRecord?.compareSourceUrl || null + ), }; - const previousRecord = nextModeState[cardId]; if ( previousRecord?.url === nextRecord.url && previousRecord?.text === nextRecord.text && - previousRecord?.status === nextRecord.status + previousRecord?.status === nextRecord.status && + previousRecord?.compareSourceUrl === nextRecord.compareSourceUrl ) { return; } @@ -3595,7 +3905,13 @@ export function AgentGenerationWorkspaceDarkV2({ [currentResultModeType]: nextModeState, }; }); - }, [currentReplacementExecutionCardIds, currentResultModeType, latestReplacementResults]); + }, [ + currentReplacementExecutionCardIds, + currentResultModeType, + detailReplacementReferenceCards, + latestReplacementResults, + skuReplacementReferenceCards, + ]); const detailReplacementResultUrls = useMemo( () => detailReplacementReferenceCards @@ -3785,6 +4101,11 @@ export function AgentGenerationWorkspaceDarkV2({ : localPassthroughResultUrl ? MANUAL_PASSTHROUGH_RESULT_TEXT : ""; + const compareSourceUrl = normalizeResultCompareSourceUrl( + resultUrl, + resultMeta?.compareSourceUrl || + (!localPassthroughResultUrl ? card.imageUrl || card.previewUrl || null : null) + ); const activeRunIndex = pendingGeneration?.modeType === "detail_replacement" && Array.isArray(pendingGeneration.requestedCardIds) @@ -3795,6 +4116,7 @@ export function AgentGenerationWorkspaceDarkV2({ index, resultUrl, resultText, + compareSourceUrl, queuePosition: activeRunIndex >= 0 && pendingGeneration?.modeType === "detail_replacement" ? activeRunIndex + 1 @@ -3847,6 +4169,11 @@ export function AgentGenerationWorkspaceDarkV2({ : localPassthroughResultUrl ? MANUAL_PASSTHROUGH_RESULT_TEXT : ""; + const compareSourceUrl = normalizeResultCompareSourceUrl( + resultUrl, + resultMeta?.compareSourceUrl || + (!localPassthroughResultUrl ? card.imageUrl || card.previewUrl || null : null) + ); const activeRunIndex = pendingGeneration?.modeType === "sku_replacement" && Array.isArray(pendingGeneration.requestedCardIds) @@ -3857,6 +4184,7 @@ export function AgentGenerationWorkspaceDarkV2({ index, resultUrl, resultText, + compareSourceUrl, status: getReplacementCardStatus({ index, resultUrl, @@ -4003,6 +4331,9 @@ export function AgentGenerationWorkspaceDarkV2({ id: url || `grid-result-placeholder-${activeResultModeType}-${index}`, index, url, + compareSourceUrl: url + ? normalizeResultCompareSourceUrl(url, resultCompareSourceByUrl[url]) + : null, status: url ? ("completed" as const) : activeResultModeType === "detail_generation" && @@ -4023,6 +4354,7 @@ export function AgentGenerationWorkspaceDarkV2({ detailGenerationProgress.status, gridPendingRemainingCount, gridResultCardCount, + resultCompareSourceByUrl, ] ); const shouldShowGridResultSection = @@ -4626,11 +4958,16 @@ export function AgentGenerationWorkspaceDarkV2({ url: string | null; text?: string | null; status?: Extract; + compareSourceUrl?: string | null; }) => { setReplacementResultState((current) => { const currentModeState = current[params.modeType]; const previousRecord = currentModeState[params.cardId]; const inferredStatus = inferReplacementCardStatusFromText(params.text); + const explicitCompareSourceUrl = + params.compareSourceUrl === undefined + ? undefined + : normalizeResultCompareSourceUrl(params.url, params.compareSourceUrl); const nextRecord: ReplacementResultRecord = { url: params.url, text: String(params.text || "").trim(), @@ -4642,12 +4979,17 @@ export function AgentGenerationWorkspaceDarkV2({ previousRecord?.status || "completed", updatedAt: Date.now(), + compareSourceUrl: + explicitCompareSourceUrl === undefined + ? previousRecord?.compareSourceUrl || null + : explicitCompareSourceUrl, }; if ( previousRecord?.url === nextRecord.url && previousRecord?.text === nextRecord.text && - previousRecord?.status === nextRecord.status + previousRecord?.status === nextRecord.status && + previousRecord?.compareSourceUrl === nextRecord.compareSourceUrl ) { return current; } @@ -4728,6 +5070,7 @@ export function AgentGenerationWorkspaceDarkV2({ url: nextUrl, text: "已完成去水印处理。", status: "completed", + compareSourceUrl: rawUrl, }); setActiveResultModeType("detail_replacement"); setSelectedResultUrl(nextUrl); @@ -5080,6 +5423,7 @@ export function AgentGenerationWorkspaceDarkV2({ url: result.originalUrl, text: "已在当前页面完成文字编辑。", status: "completed", + compareSourceUrl: replacementTextEditTarget.imageUrl, }); setReplacementTextEditTarget((current) => current @@ -5155,6 +5499,35 @@ export function AgentGenerationWorkspaceDarkV2({ } return uploadedUrl; }, []); + const registerResultCompareSource = useCallback( + (resultUrl?: string | null, sourceUrl?: string | null) => { + const normalizedResultUrl = String(resultUrl || "").trim(); + if (!isHttpImageUrl(normalizedResultUrl)) { + return; + } + + const normalizedSourceUrl = normalizeResultCompareSourceUrl( + normalizedResultUrl, + sourceUrl + ); + setResultCompareSourceByUrl((current) => { + if (!normalizedSourceUrl) { + if (!(normalizedResultUrl in current)) return current; + const next = { ...current }; + delete next[normalizedResultUrl]; + return next; + } + if (current[normalizedResultUrl] === normalizedSourceUrl) { + return current; + } + return { + ...current, + [normalizedResultUrl]: normalizedSourceUrl, + }; + }); + }, + [] + ); const handleSceneResultResizeComplete = useCallback( async (resizedImageUrl: string) => { if (!onResultPreviewUrlsChange) { @@ -5187,15 +5560,26 @@ export function AgentGenerationWorkspaceDarkV2({ ); onResultPreviewUrlsChange("scene_generation", nextSceneUrls); + registerResultCompareSource(finalUrl, sceneResizeEditorTargetUrl); setActiveResultModeType("scene_generation"); setSelectedResultUrl(finalUrl); setSceneResizeEditorTargetUrl(null); toast.success("尺寸调整结果已加入场景结果区"); }, - [mergedResultCollections.scene_generation, onResultPreviewUrlsChange, uploadBase64ResultToStorage] + [ + mergedResultCollections.scene_generation, + onResultPreviewUrlsChange, + registerResultCompareSource, + sceneResizeEditorTargetUrl, + uploadBase64ResultToStorage, + ] ); const appendResultUrlToCollection = useCallback( - (modeType: AgentGenerationResultModeType, imageUrl: string) => { + ( + modeType: AgentGenerationResultModeType, + imageUrl: string, + options?: { compareSourceUrl?: string | null } + ) => { const normalizedUrl = String(imageUrl || "").trim(); if (!normalizedUrl || !onResultPreviewUrlsChange) { return false; @@ -5208,12 +5592,20 @@ export function AgentGenerationWorkspaceDarkV2({ ]) ); onResultPreviewUrlsChange(modeType, nextUrls); + if (options && "compareSourceUrl" in options) { + registerResultCompareSource(normalizedUrl, options.compareSourceUrl); + } if (activeResultModeType === modeType) { setSelectedResultUrl(normalizedUrl); } return true; }, - [activeResultModeType, mergedResultCollections, onResultPreviewUrlsChange] + [ + activeResultModeType, + mergedResultCollections, + onResultPreviewUrlsChange, + registerResultCompareSource, + ] ); const showProcessedResultHint = useCallback((imageUrl: string, label: string) => { const normalizedUrl = String(imageUrl || "").trim(); @@ -5275,12 +5667,17 @@ export function AgentGenerationWorkspaceDarkV2({ url: nextUrl, text: "已完成高清处理。", status: "completed", + compareSourceUrl: imageUrl, }); setActiveResultModeType("detail_replacement"); setActiveDetailReferenceCardId(cardId); setSelectedResultUrl(nextUrl); } else { - if (!appendResultUrlToCollection("detail_generation", nextUrl)) { + if ( + !appendResultUrlToCollection("detail_generation", nextUrl, { + compareSourceUrl: imageUrl, + }) + ) { throw new Error("当前项目未接入结果保存能力"); } setActiveResultModeType("detail_generation"); @@ -5383,12 +5780,17 @@ export function AgentGenerationWorkspaceDarkV2({ url: nextUrl, text: isScaleAdjust ? "已完成比例调整处理。" : "已完成局部编辑处理。", status: "completed", + compareSourceUrl: imageUrl, }); setActiveResultModeType("detail_replacement"); setActiveDetailReferenceCardId(cardId); setSelectedResultUrl(nextUrl); } else { - if (!appendResultUrlToCollection("detail_generation", nextUrl)) { + if ( + !appendResultUrlToCollection("detail_generation", nextUrl, { + compareSourceUrl: imageUrl, + }) + ) { throw new Error("当前项目未接入结果保存能力"); } setActiveResultModeType("detail_generation"); @@ -5440,15 +5842,27 @@ export function AgentGenerationWorkspaceDarkV2({ ); const handlePsdDerivedImageCreated = useCallback( (imageUrl: string) => { - appendResultUrlToCollection(psdTemplateDialogResultModeType, imageUrl); + appendResultUrlToCollection(psdTemplateDialogResultModeType, imageUrl, { + compareSourceUrl: psdTemplateDialogSourceUrl, + }); }, - [appendResultUrlToCollection, psdTemplateDialogResultModeType] + [ + appendResultUrlToCollection, + psdTemplateDialogResultModeType, + psdTemplateDialogSourceUrl, + ] ); const handlePsdRenderedResultCreated = useCallback( (imageUrl: string) => { - appendResultUrlToCollection(psdTemplateDialogResultModeType, imageUrl); + appendResultUrlToCollection(psdTemplateDialogResultModeType, imageUrl, { + compareSourceUrl: psdTemplateDialogSourceUrl, + }); }, - [appendResultUrlToCollection, psdTemplateDialogResultModeType] + [ + appendResultUrlToCollection, + psdTemplateDialogResultModeType, + psdTemplateDialogSourceUrl, + ] ); const handleDeleteResultImage = useCallback( (modeType: AgentGenerationResultModeType, imageUrl: string) => { @@ -5477,6 +5891,12 @@ export function AgentGenerationWorkspaceDarkV2({ delete next[normalizedUrl]; return next; }); + setResultCompareSourceByUrl((current) => { + if (!(normalizedUrl in current)) return current; + const next = { ...current }; + delete next[normalizedUrl]; + return next; + }); onDeleteResultImage(modeType, normalizedUrl); toast.success("结果图已删除"); @@ -8384,10 +8804,11 @@ export function AgentGenerationWorkspaceDarkV2({ > {hasResult ? (
- @@ -8556,7 +8977,10 @@ export function AgentGenerationWorkspaceDarkV2({
{processingLabel ? ( - + ) : null}
) : ( @@ -8564,18 +8988,14 @@ export function AgentGenerationWorkspaceDarkV2({ className="aspect-[5/3]" onClick={() => setActiveDetailReferenceCardId(card.id)} > -
@@ -9086,13 +9506,15 @@ export function AgentGenerationWorkspaceDarkV2({ className="aspect-[5/3]" onClick={() => setActiveSkuReferenceCardId(card.id)} > -
)} @@ -9194,10 +9616,11 @@ export function AgentGenerationWorkspaceDarkV2({
{card.url ? ( <> - @@ -9376,30 +9799,47 @@ export function AgentGenerationWorkspaceDarkV2({ ) : null} {processingLabel ? ( - + ) : null} ) : ( - + isDetailGenerationCard ? ( + + ) : ( + + ) )}