"use client"; import { useMemo } from "react"; import { motion } from "framer-motion"; import { ArrowRight, Check, Copy, Sparkles, ChevronRight } from "lucide-react"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; import { SearchableSelect } from "@/components/ui/searchable-select"; import { Textarea } from "@/components/ui/textarea"; import { cn } from "@/lib/utils"; import { defaultAgentWorkflowUiConfig, flattenAgentWorkflowSteps, getEnabledAgentWorkflowStepTree, } from "@/lib/agents/workflow-ui-config"; import { AgentCanvasTopNavDark } from "@/components/agents/AgentCanvasTopNavDark"; import { AgentWorkflowShowcaseBanner } from "@/components/agents/AgentWorkflowShowcaseBanner"; import { buildAgentWorkflowComposerContext, getAgentWorkflowProgress, } from "@/lib/agents/workflow-composer"; import type { AgentWorkflowComposerSelection, AgentWorkflowMaterialSelections, AgentWorkflowShowcaseConfig, AgentWorkflowStepKey, AgentWorkflowUiConfig, } from "@/types/agent"; export interface AgentWorkflowInputs { primarySku: string; secondarySku: string; brand: string; store: string; } interface AgentWorkflowPanelDarkV2Props { config?: AgentWorkflowUiConfig | null; inputs: AgentWorkflowInputs; onInputsChange: (next: AgentWorkflowInputs) => void; materials: AgentWorkflowMaterialSelections; onMaterialsChange: (next: AgentWorkflowMaterialSelections) => void; selections: Partial>; onSelectionsChange: (next: Partial>) => void; onReset?: () => void; onNextStep?: () => void; onSkipStep?: () => void; siteName?: string | null; siteLogo?: string | null; siteLogoDark?: string | null; showcaseConfig?: AgentWorkflowShowcaseConfig | null; } function buildSelectionSummary(params: { config: AgentWorkflowUiConfig; selections: Partial>; }) { const result: AgentWorkflowComposerSelection[] = []; for (const { step } of flattenAgentWorkflowSteps(params.config.steps)) { const selectedOptionKey = params.selections[step.key]; if (!selectedOptionKey) continue; const option = step.options.find((item) => item.key === selectedOptionKey && item.enabled); if (!option) continue; result.push({ stepKey: step.key, stepTitle: step.title, optionKey: option.key, optionName: option.buttonName, promptFragment: option.promptFragment || "", }); } return result; } function StepOptionCard({ option, step, selected, onClick, index, }: { option: { key: string; buttonName: string; description?: string | null; previewImageUrl?: string | null }; step: { title: string }; selected: boolean; onClick: () => void; index: number; }) { return ( {/* 背景 */}
{option.previewImageUrl ? ( <> {option.buttonName}
) : (
)}
{/* 选中标记 */} {selected && ( )} {/* 步骤标签 */}
{step.title}
{/* 底部信息 */}

{option.buttonName}

{option.description && (

{option.description}

)}
{/* 选中边框 */} {selected && (
)} ); } export function AgentWorkflowPanelDarkV2({ config, inputs, onInputsChange, materials, onMaterialsChange, selections, onSelectionsChange, onNextStep, onSkipStep, siteName, siteLogo, siteLogoDark, showcaseConfig, }: AgentWorkflowPanelDarkV2Props) { const brandOptions = useMemo( () => config?.inputOptions?.brands || defaultAgentWorkflowUiConfig.inputOptions?.brands || [], [config?.inputOptions?.brands] ); const storeOptions = useMemo( () => config?.inputOptions?.stores || defaultAgentWorkflowUiConfig.inputOptions?.stores || [], [config?.inputOptions?.stores] ); const resolvedConfig = useMemo(() => { const source = config || defaultAgentWorkflowUiConfig; return { steps: getEnabledAgentWorkflowStepTree(source.steps || []), }; }, [config]); const flattenedResolvedSteps = useMemo( () => flattenAgentWorkflowSteps(resolvedConfig.steps).filter( ({ step }) => Array.isArray(step.options) && step.options.length > 0 ), [resolvedConfig.steps] ); const summary = useMemo( () => buildSelectionSummary({ config: resolvedConfig, selections }), [resolvedConfig, selections] ); const composerContext = useMemo( () => buildAgentWorkflowComposerContext({ config: resolvedConfig, inputs, materials, selections, }), [inputs, materials, resolvedConfig, selections] ); const progress = useMemo( () => getAgentWorkflowProgress({ config: resolvedConfig, selections }), [resolvedConfig, selections] ); const handleCopyPrompt = async () => { if (!composerContext?.promptText) { toast.error("当前还没有可复制的 Prompt"); return; } try { await navigator.clipboard.writeText(composerContext.promptText); toast.success("Prompt 已复制"); } catch { toast.error("复制失败"); } }; return (
{/* Hero Section */}
{ const target = document.getElementById("agent-workflow-content"); if (!target) return; target.scrollIntoView({ behavior: "smooth", block: "start" }); }} onSecondaryActionClick={onSkipStep} />
{/* Main Content */}
{/* 基础配置 */}

1 基础配置

onInputsChange({ ...inputs, brand: value })} /> onInputsChange({ ...inputs, store: value })} />
{/* 工作流步骤 */} {flattenedResolvedSteps.map(({ step, depth }, stepIndex) => ( 1 && "ml-3 border-l-4 border-l-emerald-500/30 sm:ml-6" )} initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.15 + stepIndex * 0.05 }} >

{stepIndex + 2} {step.title} {depth > 1 ? ( {depth === 2 ? "二级模块" : "三级模块"} ) : null}

{step.description && (

{step.description}

)}
{step.options.map((option, optionIndex) => ( onSelectionsChange({ ...selections, [step.key]: selections[step.key] === option.key ? undefined : option.key, }) } index={optionIndex} /> ))}
))} {/* 当前选择摘要 */} {summary.length > 0 && (

当前选择

{summary.map((item) => (
{item.stepTitle} {item.optionName}
))}
)} {/* Prompt 预览 */}

Prompt 预览