ai-chatbot/components/agents/AgentWorkflowShowcaseBanner.tsx
Your Name 55774ef43e
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
style: refine agent generation workspace dark ui
2026-03-18 02:25:36 +08:00

148 lines
6.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { motion } from "framer-motion";
import { ArrowRight, ImageIcon, PlayCircle } from "lucide-react";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { defaultAgentWorkflowShowcaseConfig } from "@/lib/agents/workflow-showcase-config";
import type { AgentWorkflowShowcaseConfig } from "@/types/agent";
interface AgentWorkflowShowcaseBannerProps {
config?: AgentWorkflowShowcaseConfig | null;
onActionClick?: () => void;
actionLabel?: string;
secondaryActionLabel?: string;
onSecondaryActionClick?: () => void;
className?: string;
}
export function AgentWorkflowShowcaseBanner({
config,
onActionClick,
actionLabel,
secondaryActionLabel,
onSecondaryActionClick,
className,
}: AgentWorkflowShowcaseBannerProps) {
const resolved = config || defaultAgentWorkflowShowcaseConfig;
const hasVideo = Boolean(resolved.videoUrl);
const hasPoster = Boolean(resolved.posterUrl);
const shouldRenderMedia = resolved.enabled !== false;
const resolvedActionLabel = actionLabel || resolved.actionText;
return (
<div className={cn("space-y-12 pt-6 md:space-y-14 md:pt-8", className)}>
<motion.div
className="text-center"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
>
<h1 className="mb-3 text-3xl font-bold text-white md:text-4xl">{resolved.title}</h1>
<p className="mb-8 text-base text-white/50 md:mb-9">{resolved.subtitle}</p>
{resolvedActionLabel || secondaryActionLabel ? (
<div className="flex flex-col items-center justify-center gap-4 sm:flex-row">
{resolvedActionLabel ? (
<Button
type="button"
onClick={onActionClick}
className={cn(
"h-12 gap-2 rounded-full px-8",
"bg-gradient-to-r from-emerald-500 to-teal-500",
"text-base font-medium text-white",
"hover:from-emerald-400 hover:to-teal-400",
"shadow-[0_0_30px_rgba(16,185,129,0.3)]",
"transition-all duration-300"
)}
>
{resolvedActionLabel}
<ArrowRight className="h-5 w-5" />
</Button>
) : null}
{secondaryActionLabel ? (
<Button
type="button"
variant="outline"
onClick={onSecondaryActionClick}
className="h-12 rounded-full border-white/20 bg-transparent px-12 text-base font-medium text-white hover:border-emerald-400/50 hover:bg-white/[0.04]"
>
{secondaryActionLabel}
</Button>
) : null}
</div>
) : null}
</motion.div>
{shouldRenderMedia ? (
<motion.div
className="relative overflow-hidden rounded-[28px] border border-white/12 bg-[#101214] shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]"
initial={{ opacity: 0, scale: 0.96 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.6, delay: 0.15 }}
>
<div className="aspect-[10/3] w-full">
{hasVideo ? (
<video
key={resolved.videoUrl}
className="h-full w-full object-cover"
src={resolved.videoUrl}
poster={resolved.posterUrl || undefined}
autoPlay
muted
loop
playsInline
preload="metadata"
/>
) : hasPoster ? (
<img
src={resolved.posterUrl || ""}
alt={resolved.overlayText || resolved.title}
className="h-full w-full object-cover"
/>
) : (
<div className="flex h-full w-full flex-col items-center justify-center bg-[radial-gradient(circle_at_top,#1b2430_0%,#0e1013_55%,#070809_100%)] text-center">
<div className="mb-4 flex h-20 w-20 items-center justify-center rounded-3xl border border-white/10 bg-white/[0.04]">
<PlayCircle className="h-10 w-10 text-white/25" />
</div>
<div className="text-base font-medium text-white/70">顶部视频海报待配置</div>
<div className="mt-2 max-w-lg text-sm text-white/35">
在智能体系统设置中上传视频或封面图后,这里会自动展示循环播放海报。
</div>
</div>
)}
</div>
<div className="pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_center,rgba(16,185,129,0.12),transparent_42%)]" />
<div className="pointer-events-none absolute inset-0 bg-gradient-to-t from-black/70 via-black/10 to-black/35" />
{resolved.overlayText ? (
<div className="pointer-events-none absolute inset-0 flex items-center justify-center px-8 text-center">
<div className="max-w-[78%] text-2xl font-semibold tracking-[0.18em] text-white/22 sm:text-3xl lg:text-5xl">
{resolved.overlayText}
</div>
</div>
) : null}
<div className="pointer-events-none absolute inset-x-0 top-0 flex items-center justify-between px-5 py-5 sm:px-7">
<div className="rounded-full border border-white/14 bg-black/30 px-3 py-1 text-xs font-medium text-white/70 backdrop-blur-md">
视频海报
</div>
{hasVideo || hasPoster ? (
<div className="rounded-full border border-white/14 bg-black/30 px-3 py-1 text-xs text-white/55 backdrop-blur-md">
固定比例 10:3
</div>
) : null}
</div>
{resolved.footerText ? (
<div className="pointer-events-none absolute bottom-5 left-5 flex items-center gap-2 rounded-full border border-white/14 bg-black/35 px-3 py-1.5 text-sm text-white/75 backdrop-blur-md sm:left-7">
<ImageIcon className="h-4 w-4" />
<span>{resolved.footerText}</span>
</div>
) : null}
</motion.div>
) : null}
</div>
);
}