feat(ui): 新建首页落地页
Deploy / Build Production Runtime Images (push) Has been cancelled
Deploy / Deploy Production (push) Has been cancelled
Deploy / Production Browser E2E (push) Has been cancelled
Deploy / Deploy Staging (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Failing after 193h58m42s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 193h58m51s

- 新增公开落地页 HomePage(/),包含 5 个区域:HeroSection、FeatureSection、WorkflowSection、PricingSection、CTASection
- 受保护路由基础路径从 / 迁移至 /app,使 / 可作为公开首页
- 新增 HomeRoute 组件:已登录用户自动跳转 /app/dashboard,未登录用户展示落地页
- 级联更新所有导航路径:Sidebar、Header、PageHead 全部迁移至 /app 前缀
- 零 antd 直接导入,全部使用 CSS 变量 + V21 Design System
- 响应式适配:768px / 480px 断点

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
灵应
2026-07-01 10:55:37 +08:00
parent 89c1e42f38
commit 95d1dedcb5
6 changed files with 967 additions and 61 deletions
+18 -18
View File
@@ -40,69 +40,69 @@ const NAV_ITEMS: NavItem[] = [
{
key: "dashboard",
label: "概览",
path: "/dashboard",
path: "/app/dashboard",
icon: <DashboardOutlined />,
},
{ key: "assets", label: "素材库", path: "/assets", icon: <FileOutlined /> },
{ key: "assets", label: "素材库", path: "/app/assets", icon: <FileOutlined /> },
{
key: "titles",
label: "标题库",
path: "/titles",
path: "/app/titles",
icon: <FileTextOutlined />,
},
{ key: "voices", label: "配音库", path: "/voices", icon: <AudioOutlined /> },
{ key: "voices", label: "配音库", path: "/app/voices", icon: <AudioOutlined /> },
{
key: "voice-clone",
label: "我的音色",
path: "/voice-clone",
path: "/app/voice-clone",
icon: <AudioOutlined />,
},
{
key: "accounts",
label: "账号管理",
path: "/accounts",
path: "/app/accounts",
icon: <AppstoreOutlined />,
},
{
key: "templates",
label: "模板库",
path: "/templates",
path: "/app/templates",
icon: <AppstoreOutlined />,
},
{
key: "editing-planner",
label: "剪辑编辑器",
path: "/editing-planner",
path: "/app/editing-planner",
icon: <EditOutlined />,
},
{
key: "my-templates",
label: "我的模板",
path: "/my-templates",
path: "/app/my-templates",
icon: <FolderOutlined />,
},
{
key: "generate",
label: "一键生成",
path: "/generate",
path: "/app/generate",
icon: <VideoCameraOutlined />,
},
{
key: "history",
label: "任务历史",
path: "/history",
path: "/app/history",
icon: <HistoryOutlined />,
},
{
key: "products",
label: "成品库",
path: "/products",
path: "/app/products",
icon: <TrophyOutlined />,
},
{
key: "duplication",
label: "查重",
path: "/duplication",
path: "/app/duplication",
icon: <ScanOutlined />,
},
];
@@ -120,13 +120,13 @@ const Header: React.FC = () => {
key: "profile",
icon: <UserOutlined />,
label: "个人设置",
onClick: () => navigate("/profile"),
onClick: () => navigate("/app/profile"),
},
{
key: "subscription",
icon: <SettingOutlined />,
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 = () => {
<button
className="xx-brand"
type="button"
onClick={() => navigate("/dashboard")}
onClick={() => navigate("/app/dashboard")}
>
<span className="xx-logo">🦐</span>
<span className="xx-brand-text">小虾自动剪辑</span>
+27 -27
View File
@@ -42,39 +42,39 @@ export interface PageHeadProps {
/* ── 路由 → 标题映射(用于自动生成面包屑) ────────────────── */
const ROUTE_TITLE_MAP: Record<string, string> = {
"/dashboard": "首页",
"/generate": "一键生成",
"/assets": "素材库",
"/voices": "配音库",
"/titles": "标题库",
"/products": "成片库",
"/templates": "模板库",
"/history": "任务历史",
"/admin": "控制台",
"/admin/users": "用户管理",
"/admin/analytics": "数据分析",
"/admin/monitor": "系统监控",
"/admin/logs": "系统日志",
"/subscription": "订阅管理",
"/subscription/upgrade": "升级订阅",
"/subscription/billing": "账单管理",
"/profile": "个人设置",
"/editing-planner": "剪辑规划",
"/my-templates": "我的模板",
"/voice-clone": "我的音色",
"/accounts": "账号管理",
"/duplication": "查重",
"/duplication/results": "查重结果",
"/app/dashboard": "首页",
"/app/generate": "一键生成",
"/app/assets": "素材库",
"/app/voices": "配音库",
"/app/titles": "标题库",
"/app/products": "成片库",
"/app/templates": "模板库",
"/app/history": "任务历史",
"/app/admin": "控制台",
"/app/admin/users": "用户管理",
"/app/admin/analytics": "数据分析",
"/app/admin/monitor": "系统监控",
"/app/admin/logs": "系统日志",
"/app/subscription": "订阅管理",
"/app/subscription/upgrade": "升级订阅",
"/app/subscription/billing": "账单管理",
"/app/profile": "个人设置",
"/app/editing-planner": "剪辑规划",
"/app/my-templates": "我的模板",
"/app/voice-clone": "我的音色",
"/app/accounts": "账号管理",
"/app/duplication": "查重",
"/app/duplication/results": "查重结果",
};
/* ── 自动生成面包屑 ─────────────────────────────────────── */
/** 根据当前路径生成面包屑 */
const generateBreadcrumb = (pathname: string): BreadcrumbItem[] => {
const items: BreadcrumbItem[] = [{ label: "首页", path: "/dashboard" }];
const items: BreadcrumbItem[] = [{ label: "首页", path: "/app/dashboard" }];
// 首页本身不需要面包屑
if (pathname === "/" || pathname === "/dashboard") {
if (pathname === "/app" || pathname === "/app/dashboard") {
return items;
}
@@ -125,8 +125,8 @@ const PageHead: React.FC<PageHeadProps> = ({
const showBreadcrumb =
!hideBreadcrumb &&
breadcrumbItems.length > 1 &&
location.pathname !== "/" &&
location.pathname !== "/dashboard";
location.pathname !== "/app" &&
location.pathname !== "/app/dashboard";
return (
<header className="xx-page-head">
+14 -14
View File
@@ -48,13 +48,13 @@ const MENU_GROUPS: SidebarMenuGroup[] = [
{
key: "dashboard",
label: "首页",
path: "/dashboard",
path: "/app/dashboard",
icon: <DashboardOutlined />,
},
{
key: "generate",
label: "一键生成",
path: "/generate",
path: "/app/generate",
icon: <VideoCameraOutlined />,
},
],
@@ -65,43 +65,43 @@ const MENU_GROUPS: SidebarMenuGroup[] = [
{
key: "assets",
label: "素材库",
path: "/assets",
path: "/app/assets",
icon: <FileOutlined />,
},
{
key: "voices",
label: "配音库",
path: "/voices",
path: "/app/voices",
icon: <AudioOutlined />,
},
{
key: "voice-clone",
label: "我的音色",
path: "/voice-clone",
path: "/app/voice-clone",
icon: <AudioOutlined />,
},
{
key: "accounts",
label: "账号管理",
path: "/accounts",
path: "/app/accounts",
icon: <AppstoreOutlined />,
},
{
key: "titles",
label: "标题库",
path: "/titles",
path: "/app/titles",
icon: <FileTextOutlined />,
},
{
key: "products",
label: "成片库",
path: "/products",
path: "/app/products",
icon: <TrophyOutlined />,
},
{
key: "templates",
label: "模板库",
path: "/templates",
path: "/app/templates",
icon: <AppstoreOutlined />,
},
],
@@ -112,19 +112,19 @@ const MENU_GROUPS: SidebarMenuGroup[] = [
{
key: "history",
label: "任务历史",
path: "/history",
path: "/app/history",
icon: <HistoryOutlined />,
},
{
key: "admin",
label: "控制台",
path: "/admin",
path: "/app/admin",
icon: <ControlOutlined />,
},
{
key: "subscription",
label: "订阅管理",
path: "/subscription",
path: "/app/subscription",
icon: <CrownOutlined />,
},
],
@@ -133,8 +133,8 @@ const MENU_GROUPS: SidebarMenuGroup[] = [
/** 判断菜单项是否激活 */
const isMenuItemActive = (pathname: string, path: string): boolean => {
if (path === "/dashboard") {
return pathname === "/" || pathname === "/dashboard";
if (path === "/app/dashboard") {
return pathname === "/app" || pathname === "/app/dashboard";
}
return pathname.startsWith(path);
};