diff --git a/app/canvas/[id]/CanvasEditorLegacyPageClient.tsx b/app/canvas/[id]/CanvasEditorLegacyPageClient.tsx index fecd8da0c..941c5471e 100644 --- a/app/canvas/[id]/CanvasEditorLegacyPageClient.tsx +++ b/app/canvas/[id]/CanvasEditorLegacyPageClient.tsx @@ -321,17 +321,6 @@ const AgentGenerationWorkspaceDarkV2 = dynamic( } ); -const AgentPresetPanelDarkV2 = dynamic( - () => - import("@/components/agents/AgentPresetPanelDarkV2").then( - (module) => module.AgentPresetPanelDarkV2 - ), - { - loading: () => , - ssr: false, - } -); - const AgentProjectListSheet = dynamic( () => import("@/components/agents/AgentProjectListSheet").then( @@ -1830,8 +1819,6 @@ export default function CanvasEditorLegacyPage({ params }: PageProps) { () => getAgentWorkflowBusinessModeSettings(resolvedWorkflowUiConfig), [resolvedWorkflowUiConfig] ); - const isWorkflowPresetStepEnabled = - workflowPageFeatureSettings.presetStepEnabled !== false; const isWorkflowMaterialStepEnabled = workflowPageFeatureSettings.materialStepEnabled !== false; const isBatchProcessingEnabled = @@ -8412,9 +8399,7 @@ export default function CanvasEditorLegacyPage({ params }: PageProps) { selections: workflowSelectionsRef.current, }); }, [resolvedWorkflowUiConfig]); - const effectiveSelectedAgentPresetId = isWorkflowPresetStepEnabled - ? selectedAgentPresetId - : null; + const effectiveSelectedAgentPresetId = null; const { data: selectedAgentPresetResponse } = useSWR<{ success?: boolean; data?: AgentPreset; @@ -8800,7 +8785,7 @@ export default function CanvasEditorLegacyPage({ params }: PageProps) { isWorkflowMaterialStepEnabled ? ( setSelectedAgentPresetId(null)} onDeleteResultImage={handleAgentResultImageDelete} onOpenCanvasEditor={() => { updateCanvasSearchParams({ @@ -8825,16 +8809,6 @@ export default function CanvasEditorLegacyPage({ params }: PageProps) { }} onResultPreviewUrlsChange={handleAgentResultPreviewUrlsChange} onWorkspaceStateChange={setAgentWorkspaceState} - presetPanel={ - isWorkflowPresetStepEnabled ? ( - - ) : null - } projectId={agentProjectId} resultCollections={agentProjectResultCollections} selectedAgentPresetId={ diff --git a/components/agents/AgentGenerationWorkspaceDarkV2.tsx b/components/agents/AgentGenerationWorkspaceDarkV2.tsx index cdd213ab7..4fea9e333 100644 --- a/components/agents/AgentGenerationWorkspaceDarkV2.tsx +++ b/components/agents/AgentGenerationWorkspaceDarkV2.tsx @@ -105,6 +105,7 @@ import type { AgentWorkflowShowcaseConfig, AgentWorkflowComposerContext, AgentWorkflowBusinessModeKey, + AgentWorkflowBusinessModeConfig, AgentWorkflowBusinessModeSettings, AgentWorkflowMaterialQueryType, AgentWorkflowPageFeatureSettings, @@ -129,11 +130,9 @@ interface AgentGenerationWorkspaceDarkV2Props { workflowPromptOptimizationEnabled?: boolean; getLatestWorkflowContext?: () => AgentWorkflowComposerContext | null; onBack?: () => void; - presetPanel?: ReactNode; brandStorePanel?: ReactNode; materialSelectionPanel?: ReactNode; brandModelPanel?: ReactNode; - onClearPreset?: () => void; siteName?: string | null; siteLogo?: string | null; siteLogoDark?: string | null; @@ -262,13 +261,23 @@ function getTaskDetailReferenceSourceLabel(source: AgentTaskDetailReferenceSourc return source === "main" ? "主图" : source === "sku" ? "SKU图" : "详情图"; } -function getBusinessModeKeyByResultMode( - modeType: AgentGenerationResultModeType -): AgentWorkflowBusinessModeKey { - if (modeType === "detail_generation" || modeType === "detail_replacement") { - return "detail"; +function getResultModeTypeByBusinessMode( + mode: AgentWorkflowBusinessModeConfig | null | undefined, + method: "reference_replace" | "ai_detail_generate" +): AgentGenerationResultModeType { + if (mode?.key !== "detail") { + return "scene_generation"; } - return "main_sku"; + + const canReferenceReplace = mode.referenceReplaceEnabled !== false; + const canAiDetailGenerate = mode.aiDetailGenerateEnabled !== false; + if (method === "ai_detail_generate" && canAiDetailGenerate) { + return "detail_generation"; + } + if (canReferenceReplace) { + return "detail_replacement"; + } + return canAiDetailGenerate ? "detail_generation" : "detail_replacement"; } function normalizeResultCollectionUrls(urls?: string[] | null) { @@ -980,11 +989,9 @@ export function AgentGenerationWorkspaceDarkV2({ workflowPromptOptimizationEnabled = true, getLatestWorkflowContext, onBack, - presetPanel, brandStorePanel, materialSelectionPanel, brandModelPanel, - onClearPreset, siteName, siteLogo, siteLogoDark, @@ -1048,10 +1055,10 @@ export function AgentGenerationWorkspaceDarkV2({ () => normalizeAgentWorkflowBusinessModeSettings(workflowBusinessModeSettings), [workflowBusinessModeSettings] ); - const isPresetStepEnabled = resolvedWorkflowFeatureSettings.presetStepEnabled !== false; + const isBusinessModeStepEnabled = resolvedWorkflowFeatureSettings.presetStepEnabled !== false; const isMaterialStepEnabled = resolvedWorkflowFeatureSettings.materialStepEnabled !== false; const isPsdTemplateEnabled = resolvedWorkflowFeatureSettings.psdTemplateEnabled !== false; - const requiresPresetSelection = isPresetStepEnabled; + const requiresPresetSelection = false; const isDirectModelGenerationMode = !requiresPresetSelection; const hasMaterialStep = isMaterialStepEnabled && Boolean(materialSelectionPanel); @@ -1233,42 +1240,45 @@ export function AgentGenerationWorkspaceDarkV2({ detailReplacementState.method === "ai_detail_generate" ? "ai_detail_generate" : "reference_replace"; + const detailReplacementReferenceCards = detailReplacementState.references; + const skuReplacementState = resolvedAgentModeState.skuReplacement; + const skuReplacementReferenceCards = skuReplacementState.references; const presetModeConfig = useMemo( () => normalizeAgentPresetModeConfig(selectedAgentPreset?.defaultParams), [selectedAgentPreset?.defaultParams] ); - const isSceneGenerationPreset = - selectedAgentPreset?.type === "image" && presetModeConfig.modeType === "scene_generation"; - const isDetailReplacementPreset = - selectedAgentPreset?.type === "image" && presetModeConfig.modeType === "detail_replacement"; - const isSkuReplacementPreset = - selectedAgentPreset?.type === "image" && presetModeConfig.modeType === "sku_replacement"; - const isDetailAiGenerationMethod = - isDetailReplacementPreset && detailReplacementMethod === "ai_detail_generate"; - const isReplacementPreset = - (isDetailReplacementPreset && !isDetailAiGenerationMethod) || isSkuReplacementPreset; - const currentResultModeType: AgentGenerationResultModeType = - isDetailReplacementPreset && isDetailAiGenerationMethod - ? "detail_generation" - : isDetailReplacementPreset - ? "detail_replacement" - : isSkuReplacementPreset - ? "sku_replacement" - : "scene_generation"; const businessModeCards = resolvedBusinessModeSettings.modes.length > 0 ? resolvedBusinessModeSettings.modes : defaultAgentWorkflowBusinessModeSettings.modes; const activeBusinessMode = businessModeCards.find((mode) => mode.key === activeBusinessModeKey) || businessModeCards[0] || defaultAgentWorkflowBusinessModeSettings.modes[0]; - const currentPresetBusinessModeKey = getBusinessModeKeyByResultMode(currentResultModeType); + const presetDrivenResultModeType: AgentGenerationResultModeType = + selectedAgentPreset?.type === "image" && presetModeConfig.modeType === "detail_replacement" + ? detailReplacementMethod === "ai_detail_generate" + ? "detail_generation" + : "detail_replacement" + : selectedAgentPreset?.type === "image" && presetModeConfig.modeType === "sku_replacement" + ? "sku_replacement" + : "scene_generation"; + const businessModeResultModeType = getResultModeTypeByBusinessMode( + activeBusinessMode, + detailReplacementMethod + ); + const currentResultModeType: AgentGenerationResultModeType = requiresPresetSelection + ? presetDrivenResultModeType + : businessModeResultModeType; + const isSceneGenerationPreset = currentResultModeType === "scene_generation"; + const isDetailReplacementPreset = + currentResultModeType === "detail_replacement" || + currentResultModeType === "detail_generation"; + const isSkuReplacementPreset = currentResultModeType === "sku_replacement"; + const isDetailAiGenerationMethod = currentResultModeType === "detail_generation"; + const isReplacementPreset = + currentResultModeType === "detail_replacement" || currentResultModeType === "sku_replacement"; const isSelectedBusinessModeUnavailable = activeBusinessMode?.enabled === false; - const isBusinessModePresetMismatch = - Boolean(selectedAgentPresetId) && - activeBusinessModeKey !== "buyer_show" && - activeBusinessModeKey !== currentPresetBusinessModeKey; const productSlotCount = - selectedAgentPreset?.type === "image" + selectedAgentPreset?.type === "image" && requiresPresetSelection ? isSceneGenerationPreset ? presetModeConfig.scene.productImageSlotCount : isDetailReplacementPreset @@ -1278,7 +1288,7 @@ export function AgentGenerationWorkspaceDarkV2({ : 2 : 2; const modelSlotEnabled = - selectedAgentPreset?.type === "image" + selectedAgentPreset?.type === "image" && requiresPresetSelection ? isSceneGenerationPreset ? presetModeConfig.scene.includeModelSlot : isDetailReplacementPreset @@ -1286,7 +1296,7 @@ export function AgentGenerationWorkspaceDarkV2({ : isSkuReplacementPreset ? presetModeConfig.sku.includeModelSlot : true - : false; + : isSceneGenerationPreset || isDetailReplacementPreset || isSkuReplacementPreset; const modelSlotIndex = modelSlotEnabled ? productSlotCount : -1; const hasAgentUploadSlots = Boolean( hasMaterialStep && selectedAgentPreset && selectedAgentPreset.type !== "text" @@ -1327,7 +1337,8 @@ export function AgentGenerationWorkspaceDarkV2({ const detailReferenceSourceLabel = getTaskDetailReferenceSourceLabel(detailReferenceTarget); const skuReferenceSourceLabel = getTaskDetailReferenceSourceLabel(skuReferenceTarget); const workflowStoreName = String(workflowContext?.store || "").trim(); - const shouldAllowModelOverride = !isSceneGenerationPreset || presetModeConfig.scene.allowModelOverride; + const shouldAllowModelOverride = + isDirectModelGenerationMode || !isSceneGenerationPreset || presetModeConfig.scene.allowModelOverride; const brandModelAttachmentKeys = useMemo(() => { const keys = new Set(); referenceImages @@ -1407,7 +1418,19 @@ export function AgentGenerationWorkspaceDarkV2({ const sceneMessageAttachments = useMemo(() => { if (isDirectModelGenerationMode && hasMaterialStep) { const seenKeys = new Set(); - return referenceImages + const pushUnique = (attachment: PickedAttachment | null) => { + if (!attachment) return null; + const key = getAttachmentIdentityKey(attachment); + if (key && seenKeys.has(key)) { + return null; + } + if (key) { + seenKeys.add(key); + } + return attachment; + }; + + const workflowAttachments = referenceImages .map((image) => toWorkflowReferenceAttachment({ url: image.url, @@ -1417,17 +1440,37 @@ export function AgentGenerationWorkspaceDarkV2({ assetId: image.assetId || null, }) ) - .filter((attachment): attachment is PickedAttachment => { - if (!attachment) return false; - const key = getAttachmentIdentityKey(attachment); - if (key && seenKeys.has(key)) { - return false; - } - if (key) { - seenKeys.add(key); - } - return true; - }); + .map(pushUnique) + .filter((attachment): attachment is PickedAttachment => Boolean(attachment)); + const replacementAttachments = + currentResultModeType === "detail_replacement" + ? detailReplacementReferenceCards.map((card, index) => + toWorkflowReferenceAttachment({ + url: card.imageUrl, + name: `详情参考图 ${index + 1}`, + label: card.label, + mimeType: "image/png", + assetId: null, + }) + ) + : currentResultModeType === "sku_replacement" + ? skuReplacementReferenceCards.map((card, index) => + toWorkflowReferenceAttachment({ + url: card.imageUrl, + name: `SKU参考图 ${index + 1}`, + label: card.label, + mimeType: "image/png", + assetId: null, + }) + ) + : []; + + return [ + ...workflowAttachments, + ...replacementAttachments + .map(pushUnique) + .filter((attachment): attachment is PickedAttachment => Boolean(attachment)), + ]; } if (isDirectReferenceUploadEnabled) { @@ -1492,6 +1535,8 @@ export function AgentGenerationWorkspaceDarkV2({ }, [ attachments, hasMaterialStep, + currentResultModeType, + detailReplacementReferenceCards, isDirectModelGenerationMode, isDirectReferenceUploadEnabled, isSceneGenerationPreset, @@ -1500,6 +1545,7 @@ export function AgentGenerationWorkspaceDarkV2({ sceneSecondaryReferenceAttachments, selectedModelAttachment, selectedProductAttachments, + skuReplacementReferenceCards, ]); const filledProductAttachmentCount = selectedProductAttachments.length; const missingAttachmentCount = Math.max( @@ -1543,7 +1589,6 @@ export function AgentGenerationWorkspaceDarkV2({ const detailReplacementQueryInput = detailReplacementState.query; const detailReplacementCandidates = detailReplacementState.candidates; const detailReplacementSelectedCandidateId = detailReplacementState.selectedCandidateId; - const detailReplacementReferenceCards = detailReplacementState.references; const detailGenerationMode = normalizeAgentDetailGenerationMode( detailReplacementState.generationMode ); @@ -1615,12 +1660,10 @@ export function AgentGenerationWorkspaceDarkV2({ detailGenerationProductCount, detailGenerationRequiredProductCount, ]); - const skuReplacementState = resolvedAgentModeState.skuReplacement; const skuReplacementQueryInput = skuReplacementState.query; const skuReplacementQueryType = skuReplacementState.queryType; const skuReplacementCandidates = skuReplacementState.candidates; const skuReplacementSelectedCandidateId = skuReplacementState.selectedCandidateId; - const skuReplacementReferenceCards = skuReplacementState.references; const transportStateRef = useRef<{ selectedAgentPresetId: string | null; selectedAgentPresetType: AgentPreset["type"] | null; @@ -1690,21 +1733,21 @@ export function AgentGenerationWorkspaceDarkV2({ () => selectableModels.find((model) => model.id === selectedModelId) || selectableModels[0], [selectableModels, selectedModelId] ); - const [activeToolStep, setActiveToolStep] = useState("preset"); + const [activeToolStep, setActiveToolStep] = useState("settings"); const hasBrandModelStep = Boolean(brandModelPanel) && modelSlotEnabled; const hasBrandStoreStep = Boolean(brandStorePanel); - const hasWorkflowStyleStep = Boolean(workflowStylePanel) || hasBrandModelStep || Boolean(presetPanel); + const hasWorkflowStyleStep = Boolean(workflowStylePanel) || hasBrandModelStep; const shouldShowDirectUploadInStyleStep = isDirectReferenceUploadEnabled && hasWorkflowStyleStep; const visibleWorkflowSectionKeys = useMemo( () => [ ...(hasBrandStoreStep ? ["brand"] : []), ...(hasWorkflowStyleStep ? ["style"] : []), - ...(isPresetStepEnabled ? ["mode"] : []), + ...(isBusinessModeStepEnabled ? ["mode"] : []), ...(hasMaterialStep ? ["materials"] : []), "generate", ], - [hasBrandStoreStep, hasMaterialStep, hasWorkflowStyleStep, isPresetStepEnabled] + [hasBrandStoreStep, hasMaterialStep, hasWorkflowStyleStep, isBusinessModeStepEnabled] ); const getWorkflowSectionBadge = useCallback( (key: "brand" | "mode" | "materials" | "style" | "generate") => { @@ -1720,7 +1763,7 @@ export function AgentGenerationWorkspaceDarkV2({ ? "agent-anchor-brand" : hasWorkflowStyleStep ? "agent-anchor-style" - : isPresetStepEnabled + : isBusinessModeStepEnabled ? "agent-anchor-mode" : hasMaterialStep ? "agent-anchor-materials" @@ -1747,8 +1790,7 @@ export function AgentGenerationWorkspaceDarkV2({ modelsData?.defaultModelId || transportState.selectedModelId; const replacementModePayload = - transportState.selectedAgentPresetType === "image" && - (transportState.isDetailReplacementPreset || transportState.isSkuReplacementPreset) + transportState.isDetailReplacementPreset || transportState.isSkuReplacementPreset ? { modeType: transportState.isDetailReplacementPreset ? ("detail_replacement" as const) @@ -2428,19 +2470,6 @@ export function AgentGenerationWorkspaceDarkV2({ const toolSteps = useMemo( () => [ - ...(isPresetStepEnabled - ? [ - { - key: "preset" as const, - label: "风格模板", - description: "先确定通用风格化模板,再选择输出模式", - icon: Wand2, - disabled: false, - completed: Boolean(selectedAgentPresetId), - optional: false, - }, - ] - : []), ...(hasBrandModelStep ? [ { @@ -2448,7 +2477,7 @@ export function AgentGenerationWorkspaceDarkV2({ label: "品牌模特", description: "根据品牌选择模特图", icon: UserRound, - disabled: requiresPresetSelection && !selectedAgentPresetId, + disabled: false, completed: hasBrandModelSelection, optional: true, }, @@ -2459,10 +2488,9 @@ export function AgentGenerationWorkspaceDarkV2({ label: mergedSettingsStepLabel, description: mergedSettingsStepDescription, icon: Settings2, - disabled: requiresPresetSelection && !selectedAgentPresetId, + disabled: false, completed: - (!requiresPresetSelection || Boolean(selectedAgentPresetId)) && - (Boolean(input.trim()) || hasMaterialSelections || hasSatisfiedSlotRequirement), + Boolean(input.trim()) || hasMaterialSelections || hasSatisfiedSlotRequirement, optional: false, }, ], @@ -2471,13 +2499,10 @@ export function AgentGenerationWorkspaceDarkV2({ hasBrandModelStep, hasMaterialSelections, hasSatisfiedSlotRequirement, - isPresetStepEnabled, mergedSettingsStepDescription, mergedSettingsStepLabel, hasMaterialStep, input, - requiresPresetSelection, - selectedAgentPresetId, ] ); @@ -2575,13 +2600,6 @@ export function AgentGenerationWorkspaceDarkV2({ setActiveResultModeType(currentResultModeType); }, [currentResultModeType]); - useEffect(() => { - if (!selectedAgentPresetId) { - return; - } - setActiveBusinessModeKey(currentPresetBusinessModeKey); - }, [currentPresetBusinessModeKey, selectedAgentPresetId]); - useEffect(() => { if (!pendingGeneration) { return; @@ -2873,16 +2891,12 @@ export function AgentGenerationWorkspaceDarkV2({ toast.error("当前生图模式暂未开放"); return; } - if (isBusinessModePresetMismatch) { - toast.error("当前风格化模板与生图模式不匹配,请先切换对应模板"); - return; - } if (isDetailReplacementPreset && isDetailAiGenerationMethod) { void handleRunAiDetailGeneration(); return; } if (requiresPresetSelection && !selectedAgentPresetId) { - toast.error("请先选择风格化模板"); + toast.error("请先选择生图模式"); return; } if (isDetailReplacementPreset && detailReplacementReferenceCards.length === 0) { @@ -3022,7 +3036,6 @@ export function AgentGenerationWorkspaceDarkV2({ input, isDetailAiGenerationMethod, isDetailReplacementPreset, - isBusinessModePresetMismatch, isSelectedBusinessModeUnavailable, isSkuReplacementPreset, modelsData?.defaultModelId, @@ -3203,12 +3216,12 @@ export function AgentGenerationWorkspaceDarkV2({ const nextStep = toolSteps.find((step) => step.key === nextKey); if (!nextStep) return; if (nextStep.disabled) { - toast.error(requiresPresetSelection ? "请先选择风格化模板" : "当前步骤暂不可用"); + toast.error("当前步骤暂不可用"); return; } setActiveToolStep(nextKey); }, - [requiresPresetSelection, toolSteps] + [toolSteps] ); const scrollToSection = useCallback((sectionId: string) => { if ( @@ -3538,10 +3551,6 @@ export function AgentGenerationWorkspaceDarkV2({ [updateDetailGenerationSlot] ); async function handleRunAiDetailGeneration() { - if (!selectedAgentPresetId) { - toast.error("请先选择风格化模板"); - return; - } if (detailGenerationMode !== "classic") { toast.error("AGENT排版模式将在共享画布文字层能力接入后开放,当前请先使用经典详情"); return; @@ -4386,7 +4395,7 @@ export function AgentGenerationWorkspaceDarkV2({ ) : (

- 先选择风格化模板,系统会按模板配置展示对应的产品图和模特图槽位。 + 当前生图模式会直接使用上方已选素材;如需补充图片,可在素材选择或生成参数里上传。

)} @@ -4496,7 +4505,7 @@ export function AgentGenerationWorkspaceDarkV2({ ) : (
- 先选择风格化模板,系统会按模板配置展示对应的产品图和模特图槽位。 + 当前生图模式暂无需要手动补充的输入槽位,请在上方选择素材或直接生成。
)} @@ -4577,68 +4586,12 @@ export function AgentGenerationWorkspaceDarkV2({
{shouldShowDirectUploadInStyleStep ? attachmentSlotPanel : null} {workflowStylePanel} - {isPresetStepEnabled ? ( -
-
-
-

风格化模板

-

- 这里沿用现有模板库作为生成执行配置;后续固定业务模式会接管前台入口展示。 -

-
-
- {selectedAgentPreset ? ( -
- {selectedAgentPreset.avatarUrl ? ( - {selectedAgentPreset.name} - ) : ( -
- -
- )} -
-
{selectedAgentPreset.name}
-
- {currentPresetBusinessModeKey === "detail" - ? "详情执行模板" - : "主图/SKU执行模板"} -
-
-
- ) : null} - {selectedAgentPreset && onClearPreset ? ( - - ) : null} -
-
- - {presetPanel ? ( -
- {presetPanel} -
- ) : ( -
- 暂无可用的风格化模板配置。 -
- )} -
- ) : null} {hasBrandModelStep ? brandModelPanel : null}
) : null} - {isPresetStepEnabled ? ( + {isBusinessModeStepEnabled ? (
@@ -4650,11 +4603,6 @@ export function AgentGenerationWorkspaceDarkV2({

生图模式只决定输出链路和素材规则,前面配置好的风格化提示词会在不同模式中共用。

- {isBusinessModePresetMismatch ? ( -

- 当前风格化模板与所选生图模式不匹配,请在上方模板库切换到对应类型后再生成。 -

- ) : null}
@@ -4671,8 +4619,8 @@ export function AgentGenerationWorkspaceDarkV2({ ? "预留中" : mode.enabled === false ? "已关闭" - : mode.key === currentPresetBusinessModeKey - ? "当前模板匹配" + : isActive + ? "当前模式" : "可选择"; return ( @@ -4891,7 +4839,7 @@ export function AgentGenerationWorkspaceDarkV2({ ) : (
- 当前模板已锁定模型: + 当前生图模式已锁定模型: {selectedAgentPreset?.defaultModel?.displayName || currentModel?.displayName || "未配置"} @@ -6347,14 +6295,10 @@ export function AgentGenerationWorkspaceDarkV2({

- {!requiresPresetSelection || selectedAgentPresetId - ? `${getResultModeLabel(activeResultModeType)}结果暂为空` - : "请选择风格化模板"} + {`${getResultModeLabel(activeResultModeType)}结果暂为空`}

- {!requiresPresetSelection || selectedAgentPresetId - ? "选择模型并开始生成后,结果会保留在当前项目的对应分类中。" - : "请先完成上方风格化模板配置"} + 选择模型并开始生成后,结果会保留在当前项目的对应分类中。

{isPsdTemplateEnabled ? ( <>