"use client"; import { memo } from "react"; import { CircleDot } from "lucide-react"; import { SparklesIcon } from "./icons"; type VideoGenerationPhase = "idle" | "queued" | "processing" | "finalizing" | "failed"; type VideoGenerationLoadingProps = { providerType?: string; modelName?: string; phase?: VideoGenerationPhase; elapsedSeconds?: number; }; const PROVIDER_MODEL_LABEL: Record = { "qianwen-video": "千问视频", "fal-video": "FAL 视频", "ruxa-video": "RUXA 视频", "volcano-video": "火山视频", runway: "Runway 视频", krea: "Krea 视频", }; const PHASE_HINT: Record = { idle: "任务已创建,正在初始化视频参数。", queued: "任务已进入队列,请稍候。", processing: "模型正在生成视频,请耐心等待。", finalizing: "视频已生成完成,正在同步到对话。", failed: "视频生成失败,正在尝试故障迁移。", }; const PROVIDER_GRADIENT_CLASS: Record = { "qianwen-video": "from-blue-400 via-purple-400 to-pink-400", "fal-video": "from-sky-400 via-cyan-400 to-indigo-400", "ruxa-video": "from-violet-400 via-fuchsia-400 to-pink-400", "volcano-video": "from-orange-400 via-amber-400 to-yellow-400", runway: "from-rose-400 via-orange-400 to-amber-400", krea: "from-blue-400 via-cyan-400 to-emerald-400", }; /** * 千问视频生成加载占位符组件 * 显示一个带有一闪一闪头像效果的动态卡片 */ export const QianwenVideoLoading = memo( ({ providerType, modelName, phase = "processing", elapsedSeconds = 0, }: VideoGenerationLoadingProps) => { const normalizedProviderType = providerType === "doubao-video" ? "volcano-video" : providerType || "qianwen-video"; const resolvedModelName = modelName?.trim() || PROVIDER_MODEL_LABEL[normalizedProviderType] || "AI 视频模型"; const elapsedLabel = elapsedSeconds > 0 ? `已等待 ${elapsedSeconds}s` : "预计 60~180 秒"; const phaseHint = PHASE_HINT[phase]; const isFailed = phase === "failed"; const palette = isFailed ? { ping: "bg-red-500/20", pulse: "bg-red-500/10", ring: "ring-red-500/30", spinner: "text-red-500", dot: "bg-red-500", } : { ping: "bg-blue-500/20", pulse: "bg-blue-500/10", ring: "ring-blue-500/30", spinner: "text-blue-500", dot: "bg-blue-500", }; const gradientClass = PROVIDER_GRADIENT_CLASS[normalizedProviderType] || PROVIDER_GRADIENT_CLASS["qianwen-video"]; return (
{/* 头像 - 和图片生成一样的一闪一闪效果 */}
{resolvedModelName}
{/* 文本提示 */}
正在生成视频
{/* 视频占位符 - 170x200 像素,带动态效果 */}
{/* 底层渐变背景 */}
{/* 动态模糊叠加层 1 */}
{/* 动态模糊叠加层 2 */}
{/* 噪点纹理效果 */}
{/* 模糊叠加 */}
{/* 中心图标 */}
{/* 外圈光晕 */}
{/* 视频图标 */}
{/* 流光效果 */}
{/* 提示文字 */}

{phaseHint}

{elapsedLabel}

{/* 流光动画样式 */}
); } ); QianwenVideoLoading.displayName = "QianwenVideoLoading";