2026-06-02 12:38:01 +08:00
|
|
|
|
import {
|
|
|
|
|
|
ArrowRightOutlined,
|
|
|
|
|
|
DashboardOutlined,
|
|
|
|
|
|
FileSearchOutlined,
|
|
|
|
|
|
PlayCircleOutlined,
|
|
|
|
|
|
PlusOutlined,
|
|
|
|
|
|
ShoppingOutlined,
|
|
|
|
|
|
ThunderboltOutlined,
|
|
|
|
|
|
} from "@ant-design/icons";
|
|
|
|
|
|
import { useCallback, useEffect, useMemo, useRef, useState, type CSSProperties } from "react";
|
2026-06-02 18:58:13 +08:00
|
|
|
|
import type { WebViewKey, WebImageWorkbenchTool } from "../../types";
|
2026-06-02 17:37:51 +08:00
|
|
|
|
import { useScrollEntrance } from "../../hooks/useScrollEntrance";
|
2026-06-02 12:38:01 +08:00
|
|
|
|
import WelcomeSplash from "./WelcomeSplash";
|
2026-06-02 18:58:13 +08:00
|
|
|
|
import ToolboxSection from "./ToolboxSection";
|
2026-06-02 22:45:16 +08:00
|
|
|
|
import ScriptReviewShowcase from "./ScriptReviewShowcase";
|
|
|
|
|
|
import ModelGenerationShowcase from "./ModelGenerationShowcase";
|
2026-06-03 10:45:58 +08:00
|
|
|
|
const ecommerceTemplate1 = "https://www.omniai.net.cn/static/home-ecommerce-template-1.png";
|
|
|
|
|
|
const ecommerceTemplate2 = "https://www.omniai.net.cn/static/home-ecommerce-template-2.png";
|
|
|
|
|
|
const ecommerceTemplate3 = "https://www.omniai.net.cn/static/home-ecommerce-template-3.png";
|
2026-06-02 14:34:55 +08:00
|
|
|
|
|
2026-06-02 17:37:51 +08:00
|
|
|
|
function ScrollEntrance({ children, className, ...rest }: { children: React.ReactNode; className?: string } & React.HTMLAttributes<HTMLElement>) {
|
|
|
|
|
|
const { ref, isVisible } = useScrollEntrance<HTMLElement>();
|
|
|
|
|
|
return (
|
|
|
|
|
|
<section ref={ref} className={`${className ?? ""} scroll-entrance${isVisible ? " is-visible" : ""}`} {...rest}>
|
|
|
|
|
|
{children}
|
|
|
|
|
|
</section>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2026-06-02 14:34:55 +08:00
|
|
|
|
|
|
|
|
|
|
const OSS_MUBAN = "https://stringtest.oss-cn-hangzhou.aliyuncs.com/muban";
|
|
|
|
|
|
const heroImage1 = `${OSS_MUBAN}/hero-1.png`;
|
|
|
|
|
|
const heroImage2 = `${OSS_MUBAN}/hero-2.png`;
|
|
|
|
|
|
const heroImage3 = `${OSS_MUBAN}/hero-3.png`;
|
|
|
|
|
|
const featureEcommerceImage = `${OSS_MUBAN}/feature-ecommerce.jpg`;
|
|
|
|
|
|
const featureScriptImage = `${OSS_MUBAN}/feature-script.jpg`;
|
|
|
|
|
|
const featureTokenImage = `${OSS_MUBAN}/feature-token.jpg`;
|
2026-06-02 12:38:01 +08:00
|
|
|
|
|
|
|
|
|
|
interface HomePageProps {
|
|
|
|
|
|
onOpenGenerate: () => void;
|
|
|
|
|
|
onOpenCanvas?: () => void;
|
|
|
|
|
|
onOpenEcommerce: () => void;
|
|
|
|
|
|
onOpenScriptReview?: () => void;
|
|
|
|
|
|
onOpenTokenMonitor?: () => void;
|
2026-06-02 18:58:13 +08:00
|
|
|
|
onSelectView: (view: WebViewKey) => void;
|
|
|
|
|
|
onOpenImageTool?: (tool: WebImageWorkbenchTool) => void;
|
2026-06-02 12:38:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-03 01:39:06 +08:00
|
|
|
|
const HOME_BACKGROUND_VIDEO = "https://stringtest.oss-cn-hangzhou.aliyuncs.com/muban/hero-bg.mp4";
|
2026-06-02 12:38:01 +08:00
|
|
|
|
|
|
|
|
|
|
const HOME_CAROUSEL_IMAGES = [
|
|
|
|
|
|
{ imageUrl: heroImage1, title: "灵感生成" },
|
|
|
|
|
|
{ imageUrl: heroImage2, title: "画布创作" },
|
|
|
|
|
|
{ imageUrl: heroImage3, title: "商业素材" },
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
const HOME_FEATURES = [
|
|
|
|
|
|
{
|
|
|
|
|
|
key: "script",
|
|
|
|
|
|
eyebrow: "Script Review",
|
|
|
|
|
|
title: "剧本智能测评",
|
|
|
|
|
|
description: "用六维雷达评分拆解剧本质量,从结构、节奏、人物到商业潜力给出可执行的优化路径。",
|
|
|
|
|
|
imageUrl: featureScriptImage,
|
|
|
|
|
|
actionLabel: "开始测评",
|
|
|
|
|
|
icon: <FileSearchOutlined />,
|
|
|
|
|
|
stats: ["六维评分", "质量量化", "逐项优化"],
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
2026-06-02 22:45:16 +08:00
|
|
|
|
key: "model",
|
|
|
|
|
|
eyebrow: "AI Generation",
|
|
|
|
|
|
title: "模型生成",
|
|
|
|
|
|
description: "通过AI模型生成文本、图片、视频,三种模式覆盖全内容类型,Agent对话式交互智能产出。",
|
2026-06-02 12:38:01 +08:00
|
|
|
|
imageUrl: featureTokenImage,
|
2026-06-02 22:45:16 +08:00
|
|
|
|
actionLabel: "开始生成",
|
|
|
|
|
|
icon: <ThunderboltOutlined />,
|
|
|
|
|
|
stats: ["文本生成", "图片生成", "视频生成"],
|
2026-06-02 12:38:01 +08:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: "ecommerce",
|
|
|
|
|
|
eyebrow: "AI Commerce",
|
|
|
|
|
|
title: "AI 电商生成",
|
|
|
|
|
|
description: "上传产品图后自动生成主图、场景图、详情素材和短视频方案,快速覆盖多平台商品视觉。",
|
|
|
|
|
|
imageUrl: featureEcommerceImage,
|
|
|
|
|
|
actionLabel: "开始生成",
|
|
|
|
|
|
icon: <ShoppingOutlined />,
|
|
|
|
|
|
stats: ["多场景", "多角度", "批量输出"],
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
const HOME_EXPERIENCE_POINTS = [
|
|
|
|
|
|
{ label: "生成", meta: "图像 / 视频", tone: "green" },
|
|
|
|
|
|
{ label: "测评", meta: "剧本质量", tone: "cyan" },
|
|
|
|
|
|
{ label: "成本", meta: "Token 用量", tone: "violet" },
|
|
|
|
|
|
{ label: "电商", meta: "商品视觉", tone: "amber" },
|
|
|
|
|
|
];
|
|
|
|
|
|
|
2026-06-02 22:45:16 +08:00
|
|
|
|
const HOME_ECOMMERCE_TEMPLATES = [
|
|
|
|
|
|
{
|
|
|
|
|
|
title: "卖点详情图",
|
|
|
|
|
|
tag: "详情",
|
|
|
|
|
|
meta: "中文卖点标注",
|
|
|
|
|
|
imageUrl: ecommerceTemplate1,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
title: "场景主图",
|
|
|
|
|
|
tag: "主图",
|
|
|
|
|
|
meta: "商品氛围构图",
|
|
|
|
|
|
imageUrl: ecommerceTemplate2,
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
title: "虚拟模特",
|
|
|
|
|
|
tag: "模特",
|
|
|
|
|
|
meta: "使用场景延展",
|
|
|
|
|
|
imageUrl: ecommerceTemplate3,
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
const HOME_ECOMMERCE_TOOLS = [
|
|
|
|
|
|
{ title: "主图", meta: "平台首图" },
|
|
|
|
|
|
{ title: "详情", meta: "卖点拆解" },
|
|
|
|
|
|
{ title: "模特", meta: "虚拟模特" },
|
|
|
|
|
|
{ title: "短视频", meta: "首帧方案" },
|
|
|
|
|
|
];
|
|
|
|
|
|
|
2026-06-02 12:38:01 +08:00
|
|
|
|
const HOME_CAROUSEL_SLOTS = [-4, -3, -2, -1, 0, 1, 2, 3, 4];
|
|
|
|
|
|
const HOME_CAROUSEL_TRANSITION_MS = 860;
|
|
|
|
|
|
|
|
|
|
|
|
interface HomeCarouselMotion {
|
|
|
|
|
|
direction: number;
|
|
|
|
|
|
progress: 0 | 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getPositiveModulo(value: number, length: number) {
|
|
|
|
|
|
return ((value % length) + length) % length;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function getHomeCarouselCardStyle(offset: number): CSSProperties {
|
|
|
|
|
|
const depth = Math.abs(offset);
|
|
|
|
|
|
const direction = Math.sign(offset);
|
|
|
|
|
|
const isActive = depth === 0;
|
|
|
|
|
|
const xByDepth = [0, 286, 456, 610, 735, 840];
|
|
|
|
|
|
const yByDepth = [8, -2, -8, -13, -18, -24];
|
|
|
|
|
|
const scaleByDepth = [1, 0.98, 0.94, 0.91, 0.88, 0.84];
|
|
|
|
|
|
const x = direction * (xByDepth[depth] ?? xByDepth[xByDepth.length - 1]!);
|
|
|
|
|
|
const y = yByDepth[depth] ?? yByDepth[yByDepth.length - 1]!;
|
|
|
|
|
|
const z = isActive ? 90 : 28 - depth;
|
|
|
|
|
|
const scale = scaleByDepth[depth] ?? scaleByDepth[scaleByDepth.length - 1]!;
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
"--apple-card-offset": offset,
|
|
|
|
|
|
"--apple-card-depth": depth,
|
|
|
|
|
|
"--apple-card-z": 80 - depth,
|
|
|
|
|
|
"--apple-card-x": `${x}px`,
|
|
|
|
|
|
"--apple-card-y": `${y}px`,
|
|
|
|
|
|
"--apple-card-z-offset": `${z}px`,
|
|
|
|
|
|
"--apple-card-rotate-y": "0deg",
|
|
|
|
|
|
"--apple-card-rotate-z": "0deg",
|
|
|
|
|
|
"--apple-card-scale": String(scale),
|
|
|
|
|
|
"--apple-card-opacity": String(depth > 4 ? 0 : 1),
|
|
|
|
|
|
} as CSSProperties;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-02 22:45:16 +08:00
|
|
|
|
function EcommerceFeatureShowcase() {
|
|
|
|
|
|
return (
|
|
|
|
|
|
<div className="omni-home-ecommerce-showcase">
|
|
|
|
|
|
<div className="omni-home-ecommerce-showcase__depth" />
|
|
|
|
|
|
<div className="omni-home-ecommerce-showcase__grain" />
|
|
|
|
|
|
|
|
|
|
|
|
<div className="omni-home-ecommerce-showcase__prompt">
|
|
|
|
|
|
<span>商品图 + 生成要求</span>
|
|
|
|
|
|
<strong>生成整套电商视觉</strong>
|
|
|
|
|
|
<p>主图、详情页、虚拟模特、短视频首帧一次整理。</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div className="omni-home-ecommerce-showcase__tools" aria-hidden="true">
|
|
|
|
|
|
{HOME_ECOMMERCE_TOOLS.map((item) => (
|
|
|
|
|
|
<div key={item.title} className="omni-home-ecommerce-showcase__tool">
|
|
|
|
|
|
<b>{item.title}</b>
|
|
|
|
|
|
<small>{item.meta}</small>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div className="omni-home-ecommerce-showcase__gallery" aria-hidden="true">
|
|
|
|
|
|
{HOME_ECOMMERCE_TEMPLATES.map((item, index) => (
|
|
|
|
|
|
<article key={item.title} className={`omni-home-ecommerce-showcase__shot is-${index + 1}`}>
|
|
|
|
|
|
<img src={item.imageUrl} alt="" />
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<span>{item.tag}</span>
|
|
|
|
|
|
<strong>{item.title}</strong>
|
|
|
|
|
|
<small>{item.meta}</small>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</article>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-03 01:39:06 +08:00
|
|
|
|
function HomePage({ onOpenGenerate, onOpenCanvas, onOpenEcommerce, onOpenScriptReview, onOpenTokenMonitor, onSelectView, onOpenImageTool }: HomePageProps) {
|
2026-06-02 12:38:01 +08:00
|
|
|
|
const [splashDismissed, setSplashDismissed] = useState(() => sessionStorage.getItem("omniai:splash-seen") === "1");
|
|
|
|
|
|
const [activeSlideIndex, setActiveSlideIndex] = useState(0);
|
|
|
|
|
|
const [carouselMotion, setCarouselMotion] = useState<HomeCarouselMotion | null>(null);
|
|
|
|
|
|
const [carouselIsResetting, setCarouselIsResetting] = useState(false);
|
|
|
|
|
|
const carouselFrameRef = useRef<number | null>(null);
|
|
|
|
|
|
const carouselResetFrameRef = useRef<number | null>(null);
|
|
|
|
|
|
const carouselTimerRef = useRef<number | null>(null);
|
|
|
|
|
|
const carouselSlotOffsets = useMemo(() => {
|
|
|
|
|
|
const direction = carouselMotion?.direction ?? 0;
|
|
|
|
|
|
const minSlot = HOME_CAROUSEL_SLOTS[0]! + Math.min(direction, 0);
|
|
|
|
|
|
const maxSlot = HOME_CAROUSEL_SLOTS[HOME_CAROUSEL_SLOTS.length - 1]! + Math.max(direction, 0);
|
|
|
|
|
|
return Array.from({ length: maxSlot - minSlot + 1 }, (_, index) => minSlot + index);
|
|
|
|
|
|
}, [carouselMotion?.direction]);
|
|
|
|
|
|
|
|
|
|
|
|
const startCarouselShift = useCallback(
|
|
|
|
|
|
(rawDirection: number) => {
|
|
|
|
|
|
const direction = Math.sign(rawDirection);
|
|
|
|
|
|
if (!direction || HOME_CAROUSEL_IMAGES.length <= 1 || carouselMotion) return;
|
|
|
|
|
|
|
|
|
|
|
|
if (carouselFrameRef.current !== null) {
|
|
|
|
|
|
window.cancelAnimationFrame(carouselFrameRef.current);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (carouselTimerRef.current !== null) {
|
|
|
|
|
|
window.clearTimeout(carouselTimerRef.current);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (carouselResetFrameRef.current !== null) {
|
|
|
|
|
|
window.cancelAnimationFrame(carouselResetFrameRef.current);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
setCarouselIsResetting(false);
|
|
|
|
|
|
setCarouselMotion({ direction, progress: 0 });
|
|
|
|
|
|
carouselFrameRef.current = window.requestAnimationFrame(() => {
|
|
|
|
|
|
carouselFrameRef.current = window.requestAnimationFrame(() => {
|
|
|
|
|
|
setCarouselMotion((current) => (current?.direction === direction ? { direction, progress: 1 } : current));
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
carouselTimerRef.current = window.setTimeout(() => {
|
|
|
|
|
|
setCarouselIsResetting(true);
|
|
|
|
|
|
setActiveSlideIndex((current) => getPositiveModulo(current + direction, HOME_CAROUSEL_IMAGES.length));
|
|
|
|
|
|
setCarouselMotion(null);
|
|
|
|
|
|
carouselResetFrameRef.current = window.requestAnimationFrame(() => {
|
|
|
|
|
|
carouselResetFrameRef.current = window.requestAnimationFrame(() => {
|
|
|
|
|
|
setCarouselIsResetting(false);
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}, HOME_CAROUSEL_TRANSITION_MS);
|
|
|
|
|
|
},
|
|
|
|
|
|
[carouselMotion],
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
const timerId = window.setInterval(() => {
|
|
|
|
|
|
startCarouselShift(-1);
|
|
|
|
|
|
}, 2600);
|
|
|
|
|
|
return () => window.clearInterval(timerId);
|
|
|
|
|
|
}, [startCarouselShift]);
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(
|
|
|
|
|
|
() => () => {
|
|
|
|
|
|
if (carouselFrameRef.current !== null) {
|
|
|
|
|
|
window.cancelAnimationFrame(carouselFrameRef.current);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (carouselTimerRef.current !== null) {
|
|
|
|
|
|
window.clearTimeout(carouselTimerRef.current);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (carouselResetFrameRef.current !== null) {
|
|
|
|
|
|
window.cancelAnimationFrame(carouselResetFrameRef.current);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
[],
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const handleFeatureOpen = (featureKey: string) => {
|
|
|
|
|
|
if (featureKey === "script") {
|
|
|
|
|
|
(onOpenScriptReview ?? onOpenGenerate)();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-06-02 22:45:16 +08:00
|
|
|
|
if (featureKey === "model") {
|
|
|
|
|
|
onOpenGenerate();
|
2026-06-02 12:38:01 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (featureKey === "ecommerce") {
|
|
|
|
|
|
onOpenEcommerce();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
onOpenGenerate();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<>
|
|
|
|
|
|
{!splashDismissed && (
|
|
|
|
|
|
<WelcomeSplash
|
|
|
|
|
|
onEnter={() => {
|
|
|
|
|
|
sessionStorage.setItem("omniai:splash-seen", "1");
|
|
|
|
|
|
setSplashDismissed(true);
|
|
|
|
|
|
}}
|
|
|
|
|
|
/>
|
|
|
|
|
|
)}
|
|
|
|
|
|
<section className="omni-home page-motion">
|
|
|
|
|
|
{splashDismissed && (
|
|
|
|
|
|
<video
|
|
|
|
|
|
className="omni-home__bg-video"
|
|
|
|
|
|
src={HOME_BACKGROUND_VIDEO}
|
|
|
|
|
|
autoPlay
|
|
|
|
|
|
muted
|
|
|
|
|
|
loop
|
|
|
|
|
|
playsInline
|
|
|
|
|
|
preload="metadata"
|
|
|
|
|
|
aria-hidden="true"
|
|
|
|
|
|
/>
|
|
|
|
|
|
)}
|
|
|
|
|
|
<div className="omni-home__scrim" aria-hidden="true" />
|
|
|
|
|
|
<div className="omni-home__shell">
|
|
|
|
|
|
<section className="omni-home__hero" aria-label="OmniAI 首页">
|
|
|
|
|
|
<div className="omni-home__copy">
|
|
|
|
|
|
<h1>OmniAI 创作中心</h1>
|
2026-06-03 01:39:06 +08:00
|
|
|
|
<p>从灵感到成片,一站式整合生成、AIGC与电商,让创作安静专注。</p>
|
2026-06-02 12:38:01 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div className={`omni-home__carousel${carouselIsResetting ? " is-resetting" : ""}`} aria-label="创作案例轮播">
|
|
|
|
|
|
<div className="omni-home__carousel-stage">
|
|
|
|
|
|
<div className="omni-home__carousel-deck">
|
|
|
|
|
|
{carouselSlotOffsets.map((slotOffset) => {
|
|
|
|
|
|
const itemIndex = getPositiveModulo(activeSlideIndex + slotOffset, HOME_CAROUSEL_IMAGES.length);
|
|
|
|
|
|
const slide = HOME_CAROUSEL_IMAGES[itemIndex];
|
|
|
|
|
|
const visualOffset = slotOffset - (carouselMotion?.direction ?? 0) * (carouselMotion?.progress ?? 0);
|
|
|
|
|
|
const isActive = visualOffset === 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (!slide) return null;
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<button
|
|
|
|
|
|
key={slotOffset}
|
|
|
|
|
|
type="button"
|
|
|
|
|
|
className={`omni-home__carousel-card${isActive ? " is-active" : ""}`}
|
|
|
|
|
|
style={getHomeCarouselCardStyle(visualOffset)}
|
|
|
|
|
|
aria-label={`切换到${slide.title}`}
|
|
|
|
|
|
aria-pressed={isActive}
|
|
|
|
|
|
onClick={() => {
|
|
|
|
|
|
if (!isActive) startCarouselShift(slotOffset);
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
<img src={slide.imageUrl} alt={slide.title} />
|
|
|
|
|
|
</button>
|
|
|
|
|
|
);
|
|
|
|
|
|
})}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div className="omni-home__actions" aria-label="首页入口">
|
|
|
|
|
|
<button type="button" className="omni-home__entry" onClick={onOpenGenerate}>
|
|
|
|
|
|
<PlusOutlined />
|
|
|
|
|
|
<span>新手</span>
|
|
|
|
|
|
</button>
|
2026-06-03 01:39:06 +08:00
|
|
|
|
<button type="button" className="omni-home__entry omni-home__entry--primary" onClick={onOpenCanvas || onOpenGenerate}>
|
2026-06-02 12:38:01 +08:00
|
|
|
|
<PlayCircleOutlined />
|
|
|
|
|
|
<span>老手</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button type="button" className="omni-home__entry" onClick={onOpenEcommerce}>
|
|
|
|
|
|
<ShoppingOutlined />
|
|
|
|
|
|
<span>电商</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<main className="omni-home__feature-pages" aria-label="OmniAI 功能介绍">
|
|
|
|
|
|
{HOME_FEATURES.map((feature, index) => (
|
|
|
|
|
|
<section key={feature.key} className={`omni-home__feature-page is-${feature.key}${index % 2 ? " is-alt" : ""}`}>
|
|
|
|
|
|
<div className="omni-home__feature-copy">
|
|
|
|
|
|
<span>
|
|
|
|
|
|
{feature.icon}
|
|
|
|
|
|
{feature.eyebrow}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
<h2>{feature.title}</h2>
|
|
|
|
|
|
<p>{feature.description}</p>
|
|
|
|
|
|
<button type="button" onClick={() => handleFeatureOpen(feature.key)}>
|
|
|
|
|
|
{feature.actionLabel}
|
|
|
|
|
|
<ArrowRightOutlined />
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="omni-home__feature-visual" aria-hidden="true">
|
2026-06-02 18:58:13 +08:00
|
|
|
|
{feature.key === "script" ? (
|
2026-06-02 22:45:16 +08:00
|
|
|
|
<ScriptReviewShowcase />
|
|
|
|
|
|
) : feature.key === "model" ? (
|
|
|
|
|
|
<ModelGenerationShowcase />
|
|
|
|
|
|
) : feature.key === "ecommerce" ? (
|
|
|
|
|
|
<EcommerceFeatureShowcase />
|
2026-06-02 18:58:13 +08:00
|
|
|
|
) : (
|
|
|
|
|
|
<img src={feature.imageUrl} alt="" />
|
|
|
|
|
|
)}
|
2026-06-02 12:38:01 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div className="omni-home__feature-stats" aria-hidden="true">
|
|
|
|
|
|
{feature.stats.map((item) => (
|
|
|
|
|
|
<span key={item}>{item}</span>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
))}
|
|
|
|
|
|
|
|
|
|
|
|
<section className="omni-home__experience" aria-label="点击体验">
|
|
|
|
|
|
<div className="omni-home__experience-copy">
|
|
|
|
|
|
<span>
|
|
|
|
|
|
<ThunderboltOutlined />
|
|
|
|
|
|
Click To Experience
|
|
|
|
|
|
</span>
|
|
|
|
|
|
<h2>一站进入 OmniAI</h2>
|
|
|
|
|
|
<p>选择入口,直接开始生成、评测、监控或电商作图。</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="omni-home__experience-visual" aria-hidden="true">
|
|
|
|
|
|
<div className="omni-home__experience-line is-top" />
|
|
|
|
|
|
<div className="omni-home__experience-line is-bottom" />
|
|
|
|
|
|
<div className="omni-home__experience-routes">
|
|
|
|
|
|
{HOME_EXPERIENCE_POINTS.map((point) => (
|
|
|
|
|
|
<span key={point.label} className={`omni-home__experience-route is-${point.tone}`}>
|
|
|
|
|
|
<b>{point.label}</b>
|
|
|
|
|
|
<small>{point.meta}</small>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="omni-home__experience-actions">
|
|
|
|
|
|
<button type="button" className="is-primary" onClick={onOpenGenerate}>
|
|
|
|
|
|
<PlayCircleOutlined />
|
|
|
|
|
|
立即体验生成
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button type="button" onClick={onOpenEcommerce}>
|
|
|
|
|
|
<ShoppingOutlined />
|
|
|
|
|
|
体验电商生成
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
2026-06-02 18:58:13 +08:00
|
|
|
|
|
|
|
|
|
|
<ToolboxSection onSelectView={onSelectView} onOpenImageTool={onOpenImageTool} />
|
2026-06-02 12:38:01 +08:00
|
|
|
|
</main>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
</>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export default HomePage;
|