284 lines
12 KiB
TypeScript
284 lines
12 KiB
TypeScript
import { useEffect, useRef, useState } from "react";
|
||
import "../../styles/pages/model-generation-showcase.css";
|
||
|
||
type ShowMode = "agent" | "image" | "video";
|
||
|
||
const MODE_TABS = [
|
||
{ key: "agent" as const, icon: "🤖", title: "Agent 模式", desc: "文本生成,对话式交互,智能推理" },
|
||
{ key: "image" as const, icon: "🖼️", title: "图片模式", desc: "图像生成,风格迁移,场景合成" },
|
||
{ key: "video" as const, icon: "🎬", title: "视频模式", desc: "视频生成,动态场景,数字人演绎" },
|
||
];
|
||
|
||
const AGENT_OUTPUTS = [
|
||
{ tag: "Agent", title: "营销文案", preview: "「未来已来,腕间即达」—— 全新智能手表,让每一秒都充满可能。健康监测、智能提醒、时尚设计,三合一体验。从晨跑配速到会议提醒,它比你更懂你的节奏。" },
|
||
{ tag: "Agent", title: "产品描述", preview: "搭载最新AI芯片,支持实时心率/血氧/睡眠监测,50米防水,AMOLED视网膜屏,续航长达14天。钛合金表壳 + 硅胶快拆表带,商务运动自由切换。" },
|
||
{ tag: "Agent", title: "剧本大纲", preview: "第一幕:品牌故事引入 → 第二幕:产品亮点展示 → 第三幕:用户见证与CTA引导。" },
|
||
];
|
||
|
||
const IMAGE_OUTPUTS = [
|
||
{ tag: "Image", title: "写实风格", icon: "📷", styleClass: "realistic" },
|
||
{ tag: "Image", title: "插画风格", icon: "🎨", styleClass: "illustration" },
|
||
{ tag: "Image", title: "电商风格", icon: "🛍️", styleClass: "ecommerce" },
|
||
];
|
||
|
||
const VIDEO_OUTPUTS = [
|
||
{ tag: "Video", title: "数字人播报", duration: "0:15" },
|
||
{ tag: "Video", title: "场景动画", duration: "0:30" },
|
||
{ tag: "Video", title: "产品展示", duration: "0:20" },
|
||
];
|
||
|
||
function ModelGenerationShowcase() {
|
||
const [mode, setMode] = useState<ShowMode>("agent");
|
||
const [selectedImageOpt, setSelectedImageOpt] = useState(0);
|
||
const [, setAnimated] = useState(false);
|
||
const containerRef = useRef<HTMLDivElement>(null);
|
||
|
||
useEffect(() => {
|
||
const el = containerRef.current;
|
||
if (!el) return;
|
||
const observer = new IntersectionObserver(
|
||
([entry]) => {
|
||
if (entry?.isIntersecting) {
|
||
setAnimated(true);
|
||
observer.disconnect();
|
||
}
|
||
},
|
||
{ threshold: 0.2 },
|
||
);
|
||
observer.observe(el);
|
||
return () => observer.disconnect();
|
||
}, []);
|
||
|
||
const workflowSteps = [
|
||
{ label: "选择模式", active: mode === "agent" },
|
||
{ label: "输入描述", active: mode === "image" },
|
||
{ label: "AI生成", active: mode === "video" },
|
||
{ label: "输出内容", active: false },
|
||
];
|
||
|
||
return (
|
||
<div className="omni-model-gen-showcase" ref={containerRef}>
|
||
{/* Left Panel */}
|
||
<div className="mgs-left-panel">
|
||
<div className="mgs-brand-section">
|
||
<h1>模型生成<br />多模态内容一键产出</h1>
|
||
<p className="mgs-subtitle">通过AI模型生成文本、图片、视频,三种模式覆盖全内容类型</p>
|
||
</div>
|
||
|
||
<div className="mgs-mode-tabs">
|
||
{MODE_TABS.map((tab) => (
|
||
<div
|
||
key={tab.key}
|
||
className={`mgs-mode-tab${mode === tab.key ? " is-active" : ""}`}
|
||
onClick={() => setMode(tab.key)}
|
||
role="button"
|
||
tabIndex={0}
|
||
onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") setMode(tab.key); }}
|
||
>
|
||
<div className="mgs-mode-icon">{tab.icon}</div>
|
||
<div className="mgs-mode-info">
|
||
<h3>{tab.title}</h3>
|
||
<p>{tab.desc}</p>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
|
||
<div className="mgs-workflow">
|
||
<div className="mgs-workflow-title">工作流程</div>
|
||
<div className="mgs-workflow-steps">
|
||
{workflowSteps.map((step, i) => (
|
||
<span key={step.label}>
|
||
{i > 0 && <span className="mgs-wf-arrow">→</span>}
|
||
<span className={`mgs-wf-step${step.active ? " is-active" : ""}`}>{step.label}</span>
|
||
</span>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Center Area */}
|
||
<div className="mgs-center-area">
|
||
<div className="mgs-input-card">
|
||
{/* Agent Mode */}
|
||
{mode === "agent" && (
|
||
<div className="mgs-mode-content is-active">
|
||
<div className="mgs-card-header">
|
||
<div className="mgs-card-mode-badge"><span className="mgs-dot" /> Agent 模式</div>
|
||
<div className="mgs-card-status">在线 · GPT-4o</div>
|
||
</div>
|
||
<div className="mgs-prompt-area">
|
||
<textarea
|
||
className="mgs-prompt-input"
|
||
placeholder="描述你的需求... 例如:帮我生成一段智能手表的营销文案,突出健康监测功能"
|
||
readOnly
|
||
/>
|
||
</div>
|
||
<div className="mgs-options">
|
||
{["营销文案", "产品描述", "剧本大纲", "数据分析"].map((opt, i) => (
|
||
<span key={opt} className={`mgs-opt${i === 0 ? " is-selected" : ""}`}>{opt}</span>
|
||
))}
|
||
</div>
|
||
<div className="mgs-agent-output-area">
|
||
<div className="mgs-agent-result">
|
||
<div className="mgs-agent-result-label">AI 生成结果</div>
|
||
<div className="mgs-agent-result-text">
|
||
「未来已来,腕间即达」—— 全新智能手表,让每一秒都充满可能。健康监测、智能提醒、时尚设计,三合一体验。从晨跑配速到会议提醒,它比你更懂你的节奏。
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div className="mgs-chat-input-row">
|
||
<input className="mgs-chat-input" placeholder="继续对话或修改需求..." readOnly />
|
||
<button className="mgs-chat-send" type="button" tabIndex={-1}>◆ 生成</button>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* Image Mode */}
|
||
{mode === "image" && (
|
||
<div className="mgs-mode-content is-active">
|
||
<div className="mgs-card-header">
|
||
<div className="mgs-card-mode-badge"><span className="mgs-dot" /> 图片模式</div>
|
||
<div className="mgs-card-status">SDXL · Flux</div>
|
||
</div>
|
||
<div className="mgs-prompt-area">
|
||
<textarea
|
||
className="mgs-prompt-input"
|
||
placeholder="描述你想生成的图片... 例如:未来科技感城市,赛博朋克风格,霓虹灯光"
|
||
readOnly
|
||
/>
|
||
</div>
|
||
<div className="mgs-options">
|
||
{["写实风", "插画风", "电商风", "3D渲染"].map((opt, i) => (
|
||
<span
|
||
key={opt}
|
||
className={`mgs-opt${selectedImageOpt === i ? " is-selected" : ""}`}
|
||
onClick={() => setSelectedImageOpt(i)}
|
||
>
|
||
{opt}
|
||
</span>
|
||
))}
|
||
</div>
|
||
<div className="mgs-img-grid">
|
||
<div className="mgs-img-cell">🎨</div>
|
||
<div className="mgs-img-cell">🖼️</div>
|
||
<div className="mgs-img-cell">✨</div>
|
||
<div className="mgs-img-cell">🌈</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* Video Mode */}
|
||
{mode === "video" && (
|
||
<div className="mgs-mode-content is-active">
|
||
<div className="mgs-card-header">
|
||
<div className="mgs-card-mode-badge"><span className="mgs-dot" /> 视频模式</div>
|
||
<div className="mgs-card-status">Sora · Kling</div>
|
||
</div>
|
||
<div className="mgs-video-config">
|
||
<div className="mgs-config-row">
|
||
<span className="mgs-config-label">分辨率</span>
|
||
<span className="mgs-config-value">1080p</span>
|
||
</div>
|
||
<div className="mgs-config-row">
|
||
<span className="mgs-config-label">时长</span>
|
||
<span className="mgs-config-value">15s</span>
|
||
</div>
|
||
<div className="mgs-config-row">
|
||
<span className="mgs-config-label">帧率</span>
|
||
<span className="mgs-config-value">30fps</span>
|
||
</div>
|
||
<div className="mgs-config-row">
|
||
<span className="mgs-config-label">风格</span>
|
||
<span className="mgs-config-value">数字人</span>
|
||
</div>
|
||
</div>
|
||
<div className="mgs-video-preview">
|
||
<div className="mgs-play-btn">
|
||
<svg viewBox="0 0 24 24"><polygon points="6,3 20,12 6,21" /></svg>
|
||
</div>
|
||
</div>
|
||
<div className="mgs-video-timeline">
|
||
<div className="mgs-video-timeline-fill" />
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
|
||
{/* Right Panel */}
|
||
<div className="mgs-right-panel">
|
||
{/* Agent Outputs */}
|
||
{mode === "agent" && (
|
||
<div className="mgs-output-section">
|
||
<div className="mgs-section-label">
|
||
<span className="mgs-section-dot is-green" />
|
||
Agent 文本产出
|
||
</div>
|
||
<div className="mgs-output-cards">
|
||
{AGENT_OUTPUTS.map((item) => (
|
||
<div key={item.title} className="mgs-out-card">
|
||
<div className="mgs-out-card-top">
|
||
<span className="mgs-out-tag">{item.tag}</span>
|
||
<span className="mgs-out-title">{item.title}</span>
|
||
</div>
|
||
<div className="mgs-out-preview">{item.preview}</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* Image Outputs */}
|
||
{mode === "image" && (
|
||
<div className="mgs-output-section">
|
||
<div className="mgs-section-label">
|
||
<span className="mgs-section-dot is-blue" />
|
||
图片产出
|
||
</div>
|
||
<div className="mgs-output-cards">
|
||
{IMAGE_OUTPUTS.map((item) => (
|
||
<div key={item.title} className="mgs-out-card">
|
||
<div className="mgs-out-card-top">
|
||
<span className="mgs-out-tag is-img">{item.tag}</span>
|
||
<span className="mgs-out-title">{item.title}</span>
|
||
</div>
|
||
<div className={`mgs-out-img-placeholder is-${item.styleClass}`}>{item.icon}</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* Video Outputs */}
|
||
{mode === "video" && (
|
||
<div className="mgs-output-section">
|
||
<div className="mgs-section-label">
|
||
<span className="mgs-section-dot is-purple" />
|
||
视频产出
|
||
</div>
|
||
<div className="mgs-output-cards">
|
||
{VIDEO_OUTPUTS.map((item) => (
|
||
<div key={item.title} className="mgs-out-card">
|
||
<div className="mgs-out-card-top">
|
||
<span className="mgs-out-tag is-video">{item.tag}</span>
|
||
<span className="mgs-out-title">{item.title}</span>
|
||
</div>
|
||
<div className="mgs-out-video-placeholder">
|
||
<div className="mgs-mini-play">
|
||
<svg viewBox="0 0 24 24"><polygon points="6,3 20,12 6,21" /></svg>
|
||
</div>
|
||
<span className="mgs-video-duration">{item.duration}</span>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export default ModelGenerationShowcase;
|