diff --git a/apps/web/src/components/layout/Header.tsx b/apps/web/src/components/layout/Header.tsx index 2f8ad52ba..5821eb260 100644 --- a/apps/web/src/components/layout/Header.tsx +++ b/apps/web/src/components/layout/Header.tsx @@ -40,69 +40,69 @@ const NAV_ITEMS: NavItem[] = [ { key: "dashboard", label: "概览", - path: "/dashboard", + path: "/app/dashboard", icon: , }, - { key: "assets", label: "素材库", path: "/assets", icon: }, + { key: "assets", label: "素材库", path: "/app/assets", icon: }, { key: "titles", label: "标题库", - path: "/titles", + path: "/app/titles", icon: , }, - { key: "voices", label: "配音库", path: "/voices", icon: }, + { key: "voices", label: "配音库", path: "/app/voices", icon: }, { key: "voice-clone", label: "我的音色", - path: "/voice-clone", + path: "/app/voice-clone", icon: , }, { key: "accounts", label: "账号管理", - path: "/accounts", + path: "/app/accounts", icon: , }, { key: "templates", label: "模板库", - path: "/templates", + path: "/app/templates", icon: , }, { key: "editing-planner", label: "剪辑编辑器", - path: "/editing-planner", + path: "/app/editing-planner", icon: , }, { key: "my-templates", label: "我的模板", - path: "/my-templates", + path: "/app/my-templates", icon: , }, { key: "generate", label: "一键生成", - path: "/generate", + path: "/app/generate", icon: , }, { key: "history", label: "任务历史", - path: "/history", + path: "/app/history", icon: , }, { key: "products", label: "成品库", - path: "/products", + path: "/app/products", icon: , }, { key: "duplication", label: "查重", - path: "/duplication", + path: "/app/duplication", icon: , }, ]; @@ -120,13 +120,13 @@ const Header: React.FC = () => { key: "profile", icon: , label: "个人设置", - onClick: () => navigate("/profile"), + onClick: () => navigate("/app/profile"), }, { key: "subscription", icon: , label: "订阅管理", - onClick: () => navigate("/subscription"), + onClick: () => navigate("/app/subscription"), }, { type: "divider" }, { @@ -139,8 +139,8 @@ const Header: React.FC = () => { /** 判断导航项是否激活 */ const isActive = (path: string) => { - if (path === "/dashboard") { - return location.pathname === "/" || location.pathname === "/dashboard"; + if (path === "/app/dashboard") { + return location.pathname === "/app" || location.pathname === "/app/dashboard"; } return location.pathname.startsWith(path); }; @@ -151,7 +151,7 @@ const Header: React.FC = () => { + + + + + {/* 右侧视觉 */} +
+
+
+ 🎬 +
+ +
+
+
+ ✨ AI智能剪辑 + ⚡ 30秒生成 +
+ 可发布 +
+
+ + + ); +}; + +/* ── FeatureSection ──────────────────────────────────────── */ + +const FEATURES = [ + { + icon: "🤖", + title: "AI 智能剪辑", + desc: "自动识别视频高光片段,智能去除冗余内容,一键生成精彩短视频。", + }, + { + icon: "🎙️", + title: "AI 配音克隆", + desc: "克隆您的声音,支持多种音色风格,自动生成自然流畅的配音。", + }, + { + icon: "📝", + title: "智能字幕标题", + desc: "自动语音识别生成精准字幕,AI 创作吸睛标题,提升内容传播力。", + }, + { + icon: "📱", + title: "多平台一键发布", + desc: "支持抖音、快手、小红书、微信视频号等主流平台,一键同步发布。", + }, +]; + +const FeatureSection: React.FC = () => { + return ( +
+
+

核心功能

+

+ 从素材上传到视频发布,全流程 AI 赋能,让短视频创作更简单 +

+
+ {FEATURES.map((f) => ( +
+
{f.icon}
+

{f.title}

+

{f.desc}

+
+ ))} +
+
+
+ ); +}; + +/* ── WorkflowSection ─────────────────────────────────────── */ + +const STEPS = [ + { icon: "📤", title: "上传素材", desc: "拖拽或选择视频素材,支持批量上传" }, + { icon: "🧠", title: "AI 处理", desc: "AI 自动分析、剪辑、配音、加字幕" }, + { icon: "👀", title: "预览调整", desc: "在线预览生成结果,支持微调编辑" }, + { icon: "🚀", title: "一键发布", desc: "多平台同步发布,追踪数据表现" }, +]; + +const WorkflowSection: React.FC = () => { + return ( +
+
+

工作流程

+

+ 四步完成短视频创作,从素材到发布仅需 30 秒 +

+
+ {STEPS.map((step, idx) => ( +
+
{idx + 1}
+
{step.icon}
+

{step.title}

+

{step.desc}

+ {idx < STEPS.length - 1 &&
} +
+ ))} +
+
+
+ ); +}; + +/* ── PricingSection ──────────────────────────────────────── */ + +const PLANS = [ + { + name: "基础版", + price: "免费", + period: "", + desc: "适合个人体验,快速上手", + features: ["每月 5 次 AI 生成", "720p 视频导出", "基础模板库", "1 个平台账号绑定"], + highlighted: false, + cta: "免费开始", + }, + { + name: "专业版", + price: "¥99", + period: "/月", + desc: "适合内容创作者,高效产出", + features: [ + "每月 100 次 AI 生成", + "1080p 视频导出", + "全部模板库", + "4 个平台账号绑定", + "AI 配音克隆", + "优先客服支持", + ], + highlighted: true, + cta: "立即订阅", + }, + { + name: "企业版", + price: "¥399", + period: "/月", + desc: "适合团队与企业,规模化运营", + features: [ + "无限次 AI 生成", + "4K 视频导出", + "全部模板 + 定制模板", + "无限平台账号绑定", + "团队协作管理", + "API 接入支持", + "专属客户经理", + ], + highlighted: false, + cta: "联系销售", + }, +]; + +const PricingSection: React.FC = () => { + const navigate = useNavigate(); + + return ( +
+
+

定价方案

+

选择适合您的方案,随时升级或取消

+
+ {PLANS.map((plan) => ( +
+ {plan.highlighted &&
推荐
} +

{plan.name}

+
+ {plan.price} + {plan.period && {plan.period}} +
+

{plan.desc}

+
    + {plan.features.map((f) => ( +
  • + + {f} +
  • + ))} +
+ +
+ ))} +
+
+
+ ); +}; + +/* ── CTASection ──────────────────────────────────────────── */ + +const CTASection: React.FC = () => { + const navigate = useNavigate(); + + return ( +
+
+

开始用 AI 创作短视频

+

+ 免费注册,立即体验 AI 智能视频创作。无需信用卡,零风险上手。 +

+ +
+
+ ); +}; + +/* ── 主页面 ─────────────────────────────────────────────── */ + +const HomePage: React.FC = () => { + const isAuthenticated = useAuthStore((state) => state.isAuthenticated); + const navigate = useNavigate(); + + // 已登录用户自动跳转到 dashboard + React.useEffect(() => { + if (isAuthenticated) { + navigate("/app/dashboard", { replace: true }); + } + }, [isAuthenticated, navigate]); + + return ( +
+ {/* 顶部导航栏 */} +
+
+ +
+ + +
+
+
+ + {/* 5 个区域 */} + + + + + + + {/* 底部 */} +
+

© 2026 小虾智剪 · AI智能视频创作平台

+
+
+ ); +}; + +export default HomePage; diff --git a/apps/web/src/pages/home/home-page.css b/apps/web/src/pages/home/home-page.css new file mode 100644 index 000000000..489623749 --- /dev/null +++ b/apps/web/src/pages/home/home-page.css @@ -0,0 +1,583 @@ +/** + * 首页落地页 — V21 Design System + * + * 5 个区域:HeroSection / FeatureSection / WorkflowSection + * / PricingSection / CTASection + * 全部使用 CSS 变量,零 antd 直接导入 + */ + +/* ── 页面容器 ────────────────────────────────────────────── */ + +.hp-page { + min-height: 100vh; + background: var(--bg-base, #fafafa); + color: var(--text-primary, #1a1a2e); + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + overflow-x: hidden; +} + +/* ── 顶部导航 ────────────────────────────────────────────── */ + +.hp-nav { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 100; + background: rgba(255, 255, 255, 0.72); + backdrop-filter: blur(16px); + -webkit-backdrop-filter: blur(16px); + border-bottom: 1px solid var(--line, rgba(0, 0, 0, 0.06)); +} + +.hp-nav-inner { + max-width: 1200px; + margin: 0 auto; + padding: 0 24px; + height: 60px; + display: flex; + align-items: center; + justify-content: space-between; +} + +.hp-nav-brand { + display: flex; + align-items: center; + gap: 8px; + background: none; + border: none; + cursor: pointer; + padding: 0; +} + +.hp-nav-logo { + font-size: 24px; +} + +.hp-nav-brand-text { + font-size: 18px; + font-weight: 700; + color: var(--text-primary, #1a1a2e); +} + +.hp-nav-actions { + display: flex; + align-items: center; + gap: 12px; +} + +/* ── HeroSection ─────────────────────────────────────────── */ + +.hp-hero { + padding: 120px 24px 60px; + background: linear-gradient(180deg, rgba(99, 102, 241, 0.04) 0%, transparent 60%); +} + +.hp-hero-inner { + max-width: 1200px; + margin: 0 auto; + display: grid; + grid-template-columns: 1fr 420px; + gap: 48px; + align-items: center; +} + +.hp-hero-content { + display: flex; + flex-direction: column; + gap: 20px; +} + +.hp-hero-tag { + display: inline-flex; + align-self: flex-start; + padding: 6px 16px; + border-radius: var(--radius-sm, 8px); + background: rgba(99, 102, 241, 0.08); + color: var(--primary, #6366f1); + font-size: 14px; + font-weight: 500; +} + +.hp-hero-title { + font-size: 44px; + font-weight: 800; + line-height: 1.2; + color: var(--text-primary, #1a1a2e); + margin: 0; + letter-spacing: -0.02em; +} + +.hp-hero-desc { + font-size: 17px; + line-height: 1.7; + color: var(--text-secondary, #6b7280); + margin: 0; + max-width: 520px; +} + +.hp-hero-actions { + display: flex; + gap: 12px; + margin-top: 8px; +} + +/* Hero 右侧视觉 */ +.hp-hero-visual { + display: flex; + flex-direction: column; + gap: 16px; +} + +.hp-hero-video { + position: relative; + border-radius: var(--radius-lg, 16px); + overflow: hidden; + background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%); + aspect-ratio: 16 / 10; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 20px 60px rgba(99, 102, 241, 0.18); +} + +.hp-hero-video-inner { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; +} + +.hp-hero-video-placeholder { + font-size: 64px; + opacity: 0.6; +} + +.hp-hero-play { + position: absolute; + width: 56px; + height: 56px; + border-radius: 50%; + background: rgba(255, 255, 255, 0.92); + border: none; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-size: 20px; + color: var(--primary, #6366f1); + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.hp-hero-play:hover { + transform: scale(1.08); + box-shadow: 0 6px 28px rgba(0, 0, 0, 0.2); +} + +.hp-hero-info { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.hp-hero-badges { + display: flex; + gap: 8px; +} + +.hp-hero-badge { + padding: 6px 14px; + border-radius: var(--radius-sm, 8px); + background: var(--bg-surface, #fff); + border: 1px solid var(--line, rgba(0, 0, 0, 0.06)); + font-size: 13px; + font-weight: 500; + color: var(--text-primary, #1a1a2e); + white-space: nowrap; +} + +.hp-hero-pill { + padding: 5px 14px; + border-radius: 20px; + background: rgba(16, 185, 129, 0.1); + color: #059669; + font-size: 13px; + font-weight: 600; +} + +/* ── 通用 Section 样式 ──────────────────────────────────── */ + +.hp-section-inner { + max-width: 1200px; + margin: 0 auto; + padding: 0 24px; +} + +.hp-section-title { + font-size: 32px; + font-weight: 700; + text-align: center; + margin: 0 0 12px; + color: var(--text-primary, #1a1a2e); +} + +.hp-section-desc { + font-size: 16px; + text-align: center; + color: var(--text-secondary, #6b7280); + margin: 0 0 48px; +} + +/* ── FeatureSection ──────────────────────────────────────── */ + +.hp-features { + padding: 80px 0; +} + +.hp-feature-grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 24px; +} + +.hp-feature-card { + padding: 32px 24px; + border-radius: var(--radius-lg, 16px); + background: var(--bg-surface, #fff); + border: 1px solid var(--line, rgba(0, 0, 0, 0.06)); + text-align: center; + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.hp-feature-card:hover { + transform: translateY(-4px); + box-shadow: 0 12px 40px rgba(0, 0, 0, 0.08); +} + +.hp-feature-icon { + width: 56px; + height: 56px; + margin: 0 auto 16px; + border-radius: var(--radius-md, 12px); + background: rgba(99, 102, 241, 0.08); + display: flex; + align-items: center; + justify-content: center; + font-size: 28px; +} + +.hp-feature-title { + font-size: 17px; + font-weight: 600; + margin: 0 0 8px; + color: var(--text-primary, #1a1a2e); +} + +.hp-feature-desc { + font-size: 14px; + line-height: 1.6; + color: var(--text-secondary, #6b7280); + margin: 0; +} + +/* ── WorkflowSection ─────────────────────────────────────── */ + +.hp-workflow { + padding: 80px 0; + background: linear-gradient(180deg, transparent 0%, rgba(99, 102, 241, 0.03) 50%, transparent 100%); +} + +.hp-step-grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 24px; + position: relative; +} + +.hp-step-card { + position: relative; + padding: 32px 24px; + border-radius: var(--radius-lg, 16px); + background: var(--bg-surface, #fff); + border: 1px solid var(--line, rgba(0, 0, 0, 0.06)); + text-align: center; +} + +.hp-step-number { + position: absolute; + top: -12px; + left: 50%; + transform: translateX(-50%); + width: 28px; + height: 28px; + border-radius: 50%; + background: var(--primary, #6366f1); + color: #fff; + font-size: 13px; + font-weight: 700; + display: flex; + align-items: center; + justify-content: center; +} + +.hp-step-icon { + font-size: 36px; + margin: 8px 0 12px; +} + +.hp-step-title { + font-size: 17px; + font-weight: 600; + margin: 0 0 8px; + color: var(--text-primary, #1a1a2e); +} + +.hp-step-desc { + font-size: 14px; + line-height: 1.6; + color: var(--text-secondary, #6b7280); + margin: 0; +} + +.hp-step-arrow { + position: absolute; + right: -18px; + top: 50%; + transform: translateY(-50%); + font-size: 20px; + color: var(--text-secondary, #6b7280); + opacity: 0.4; + z-index: 1; +} + +/* ── PricingSection ──────────────────────────────────────── */ + +.hp-pricing { + padding: 80px 0; +} + +.hp-pricing-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 24px; + align-items: start; +} + +.hp-pricing-card { + position: relative; + padding: 36px 28px; + border-radius: var(--radius-lg, 16px); + background: var(--bg-surface, #fff); + border: 1px solid var(--line, rgba(0, 0, 0, 0.06)); + display: flex; + flex-direction: column; + gap: 16px; + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.hp-pricing-card:hover { + transform: translateY(-4px); + box-shadow: 0 12px 40px rgba(0, 0, 0, 0.08); +} + +.hp-pricing-card--highlight { + border-color: var(--primary, #6366f1); + box-shadow: 0 8px 32px rgba(99, 102, 241, 0.12); +} + +.hp-pricing-badge { + position: absolute; + top: -12px; + right: 20px; + padding: 4px 14px; + border-radius: 20px; + background: var(--primary, #6366f1); + color: #fff; + font-size: 12px; + font-weight: 600; +} + +.hp-pricing-name { + font-size: 20px; + font-weight: 600; + margin: 0; + color: var(--text-primary, #1a1a2e); +} + +.hp-pricing-price { + font-size: 36px; + font-weight: 800; + color: var(--text-primary, #1a1a2e); + line-height: 1; +} + +.hp-pricing-period { + font-size: 15px; + font-weight: 400; + color: var(--text-secondary, #6b7280); +} + +.hp-pricing-desc { + font-size: 14px; + color: var(--text-secondary, #6b7280); + margin: 0; +} + +.hp-pricing-features { + list-style: none; + padding: 0; + margin: 0; + display: flex; + flex-direction: column; + gap: 10px; +} + +.hp-pricing-features li { + display: flex; + align-items: center; + gap: 8px; + font-size: 14px; + color: var(--text-primary, #1a1a2e); +} + +.hp-pricing-check { + color: #10b981; + font-weight: 700; + font-size: 14px; +} + +/* ── CTASection ──────────────────────────────────────────── */ + +.hp-cta { + padding: 80px 24px; +} + +.hp-cta-inner { + max-width: 680px; + margin: 0 auto; + text-align: center; + padding: 60px 40px; + border-radius: var(--radius-lg, 16px); + background: linear-gradient(135deg, rgba(99, 102, 241, 0.06) 0%, rgba(139, 92, 246, 0.06) 100%); + border: 1px solid var(--line, rgba(0, 0, 0, 0.06)); + display: flex; + flex-direction: column; + align-items: center; + gap: 16px; +} + +.hp-cta-title { + font-size: 30px; + font-weight: 700; + margin: 0; + color: var(--text-primary, #1a1a2e); +} + +.hp-cta-desc { + font-size: 16px; + line-height: 1.6; + color: var(--text-secondary, #6b7280); + margin: 0; +} + +/* ── 底部 ────────────────────────────────────────────────── */ + +.hp-footer { + padding: 32px 24px; + text-align: center; + border-top: 1px solid var(--line, rgba(0, 0, 0, 0.06)); +} + +.hp-footer p { + margin: 0; + font-size: 13px; + color: var(--text-secondary, #6b7280); +} + +/* ── 响应式 768px ────────────────────────────────────────── */ + +@media (max-width: 768px) { + .hp-hero-inner { + grid-template-columns: 1fr; + gap: 32px; + } + + .hp-hero-visual { + max-width: 400px; + margin: 0 auto; + } + + .hp-hero-title { + font-size: 32px; + } + + .hp-hero { + padding: 100px 24px 48px; + } + + .hp-feature-grid { + grid-template-columns: repeat(2, 1fr); + } + + .hp-step-grid { + grid-template-columns: repeat(2, 1fr); + } + + .hp-step-arrow { + display: none; + } + + .hp-pricing-grid { + grid-template-columns: 1fr; + max-width: 400px; + margin: 0 auto; + } + + .hp-section-title { + font-size: 26px; + } + + .hp-cta-inner { + padding: 40px 24px; + } + + .hp-cta-title { + font-size: 24px; + } +} + +/* ── 响应式 480px ────────────────────────────────────────── */ + +@media (max-width: 480px) { + .hp-hero-title { + font-size: 26px; + } + + .hp-hero-desc { + font-size: 15px; + } + + .hp-hero-actions { + flex-direction: column; + } + + .hp-hero-badges { + flex-direction: column; + gap: 6px; + } + + .hp-feature-grid { + grid-template-columns: 1fr; + } + + .hp-step-grid { + grid-template-columns: 1fr; + } + + .hp-nav-actions { + gap: 8px; + } +} diff --git a/apps/web/src/router/index.tsx b/apps/web/src/router/index.tsx index 99cb36012..1f6430271 100644 --- a/apps/web/src/router/index.tsx +++ b/apps/web/src/router/index.tsx @@ -9,6 +9,7 @@ import Login from "@/pages/auth/Login"; import Register from "@/pages/auth/Register"; import ForgotPassword from "@/pages/auth/ForgotPassword"; import ResetPassword from "@/pages/auth/ResetPassword"; +import HomePage from "@/pages/home/HomePage"; import { useAuthStore } from "@/store/authStore"; /** 受保护的路由组件 */ @@ -24,8 +25,24 @@ const ProtectedRoute = ({ children }: { children: React.ReactNode }) => { return <>{children}; }; +/** 首页路由组件:已登录跳 dashboard,未登录显示落地页 */ +const HomeRoute: React.FC = () => { + const isAuthenticated = useAuthStore((state) => state.isAuthenticated); + const hasAccessToken = Boolean(localStorage.getItem("access_token")); + + if (isAuthenticated && hasAccessToken) { + return ; + } + + return ; +}; + /** 路由配置 */ export const router = createBrowserRouter([ + { + path: "/", + element: , + }, { path: "/login", element: , @@ -43,7 +60,7 @@ export const router = createBrowserRouter([ element: , }, { - path: "/", + path: "/app", element: ( @@ -52,7 +69,7 @@ export const router = createBrowserRouter([ children: [ { index: true, - element: , + element: , }, { path: "dashboard",