--- AIGC: Label: "1" ContentProducer: 001191110102MACQD9K64018705 ProduceID: 15868733686388_0/project_7655981463858544923-files/docs/frontend-v21-ui-development-plan.md ReservedCode1: "" ContentPropagator: 001191110102MACQD9K64028705 PropagateID: 15868733686388#1782829027273 ReservedCode2: "" --- # V21 UI 前端开发指令文档 > 版本:V21 UI 1:1 还原开发指南 > 更新时间:2024年 > 技术栈:React 18 + TypeScript + Ant Design 5 + Tailwind CSS + React Query --- ## 目录 1. [全局设计系统规范](#1-全局设计系统规范) 2. [全局布局规范](#2-全局布局规范) 3. [逐页开发指令](#3-逐页开发指令) 4. [新增页面开发指令](#4-新增页面开发指令) 5. [基础组件封装规范](#5-基础组件封装规范) 6. [执行顺序建议](#6-执行顺序建议) --- ## 1. 全局设计系统规范 ### 1.1 CSS 变量定义(global.css) 从原型中提取的完整 CSS 变量系统: ```css /* ========== global.css ========== */ :root { /* ==================== 颜色系统 ==================== */ /* 主色调 */ --primary: #4f46e5; /* 主色 */ --primary-dark: #4338ca; /* 主色深 */ --primary-soft: #eef2ff; /* 主色浅(背景) */ --primary-light: #818cf8; /* 主色亮 */ /* 中性色 */ --slate: #0f172a; /* 标题/重要文字 */ --muted: #64748b; /* 次要文字/占位符 */ --line: #e2e8f0; /* 边框/分隔线 */ --bg: #f8fafc; /* 页面背景 */ /* 功能色 */ --green: #10b981; /* 成功/通过 */ --amber: #f59e0b; /* 警告/进行中 */ --red: #ef4444; /* 错误/高风险 */ /* ==================== 圆角系统 ==================== */ --radius-sm: 14px; /* 小圆角(按钮、内边距) */ --radius-md: 18px; /* 中圆角(卡片、模态框) */ --radius-lg: 24px; /* 大圆角(容器) */ --radius-xl: 28px; /* 超大圆角(主内容卡片) */ /* ==================== 阴影系统 ==================== */ --shadow-sm: 0 10px 30px rgba(15, 23, 42, 0.06); /* 小阴影 */ --shadow-md: 0 24px 70px rgba(15, 23, 42, 0.09); /* 中阴影(卡片默认) */ /* ==================== 间距系统(已对齐) ==================== */ --space-xs: 4px; --space-sm: 8px; --space-md: 12px; --space-lg: 16px; --space-xl: 20px; --space-2xl: 24px; --space-3xl: 32px; /* ==================== 布局尺寸 ==================== */ --sidebar-width: 240px; --header-height: 68px; --max-content-width: 1440px; /* ==================== 字体系统 ==================== */ --font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", Arial, sans-serif; --font-size-xs: 11px; --font-size-sm: 12px; --font-size-base: 14px; --font-size-md: 15px; --font-size-lg: 16px; --font-size-xl: 18px; --font-size-2xl: 22px; --font-size-3xl: 26px; --font-size-4xl: 28px; --font-size-hero: 44px; /* ==================== 动效 ==================== */ --transition-fast: 0.15s ease; --transition-base: 0.18s ease; --transition-slow: 0.3s ease; } ``` ### 1.2 颜色使用规范 | 颜色名 | 色值 | 使用场景 | |--------|------|----------| | `--primary` | #4f46e5 | 主按钮、选中状态、强调文字 | | `--primary-soft` | #eef2ff | 选中/激活背景、标签背景 | | `--primary-light` | #818cf8 | 图标、渐变色 | | `--slate` | #0f172a | 标题、主要文字 | | `--muted` | #64748b | 次要文字、时间戳 | | `--line` | #e2e8f0 | 边框、分隔线 | | `--bg` | #f8fafc | 页面背景 | | `--green` | #10b981 | 成功、通过、可发布 | | `--amber` | #f59e0b | 警告、进行中、待复核 | | `--red` | #ef4444 | 错误、高风险、删除 | ### 1.3 标签(Tag/Pill)样式规范 ```css /* 标签通用样式 */ .tag { display: inline-flex; padding: 6px 12px; border-radius: 999px; border: 1px solid #c7d2fe; background: #eef2ff; color: #4338ca; font-weight: 700; font-size: 13px; } /* 状态胶囊样式 */ .pill { font-size: 11px; padding: 4px 8px; border-radius: 999px; font-weight: 700; display: inline-block; } .pill.ok { /* 成功/已通过 */ background: #dcfce7; color: #166534; } .pill.warn { /* 警告/待复核 */ background: #ffedd5; color: #c2410c; } .pill.bad { /* 错误/高风险 */ background: #ffe4e6; color: #be123c; } .pill.info { /* 信息/视频类型 */ background: #dbeafe; color: #1d4ed8; } .pill.muted { /* 禁用/品牌类 */ background: #f1f5f9; color: #64748b; } ``` ### 1.4 按钮样式规范 ```css /* 按钮基础样式 */ .btn { border: 0; border-radius: var(--radius-sm); /* 14px */ padding: 11px 18px; font-weight: 700; cursor: pointer; transition: var(--transition-base); display: inline-flex; align-items: center; justify-content: center; gap: 7px; font-size: var(--font-size-base); } /* 主要按钮(渐变) */ .btn.primary { background: linear-gradient(135deg, #6366f1, #4f46e5); color: #fff; box-shadow: 0 14px 26px rgba(79, 70, 229, 0.22); } .btn.primary:hover { transform: translateY(-2px); box-shadow: 0 18px 34px rgba(79, 70, 229, 0.28); } /* 次要按钮(幽灵) */ .btn.ghost { background: #fff; border: 1px solid var(--line); color: #475569; } .btn.ghost:hover { border-color: #c7d2fe; color: #4338ca; background: #f8faff; } /* 小按钮 */ .btn.sm { padding: 8px 14px; font-size: var(--font-size-sm); } /* 激活态 */ .btn:active { transform: translateY(0); } /* 禁用态 */ .btn:disabled { opacity: 0.5; cursor: not-allowed; } ``` ### 1.5 卡片样式规范 ```css /* 通用卡片 */ .card { background: rgba(255, 255, 255, 0.94); border: 1px solid rgba(226, 232, 240, 0.95); border-radius: var(--radius-xl); /* 28px */ box-shadow: var(--shadow-md); padding: 28px; } /* 网格卡片(Hover效果) */ .card-hover { transition: var(--transition-base); } .card-hover:hover { transform: translateY(-3px); box-shadow: var(--shadow-sm); } ``` --- ## 2. 全局布局规范 ### 2.1 主应用布局(AppLayout) ``` ┌─────────────────────────────────────────────────────────────────┐ │ Header (height: 68px, sticky) │ ├──────────────┬──────────────────────────────────────────────────┤ │ │ │ │ Sidebar │ Main Content │ │ (240px) │ (flex: 1) │ │ │ │ │ - Logo │ ┌─────────────────────────────────────────┐ │ │ - Nav │ │ Page Head (flex space-between) │ │ │ - Divider │ │ - Title + Description │ │ │ - Bottom │ │ - Action Buttons │ │ │ │ └─────────────────────────────────────────┘ │ │ │ │ │ │ ┌─────────────────────────────────────────┐ │ │ │ │ Content Area │ │ │ │ │ (根据页面类型不同布局) │ │ │ │ └─────────────────────────────────────────┘ │ │ │ │ └──────────────┴──────────────────────────────────────────────────┘ ``` **布局实现代码:** ```tsx // components/layout/AppLayout.tsx import React from 'react'; import { Outlet } from 'react-router-dom'; import Sidebar from './Sidebar'; import Header from './Header'; const AppLayout: React.FC = () => { return (
{/* 全局背景 */}
); }; export default AppLayout; ``` ### 2.2 侧边栏导航结构(Sidebar) ```tsx // components/layout/Sidebar.tsx const navItems = [ { icon: '📊', label: '控制台', path: '/dashboard' }, { icon: '📝', label: '标题库', path: '/titles' }, { icon: '📦', label: '素材库', path: '/assets' }, { icon: '🎙️', label: '配音库', path: '/voices' }, { icon: '🎨', label: '模板库', path: '/templates' }, ]; const navItems2 = [ { icon: '✨', label: '一键生成', path: '/generate', highlight: true }, { icon: '🎬', label: '成片库', path: '/products' }, { icon: '📋', label: '任务历史', path: '/history' }, { icon: '🔍', label: '查重检测', path: '/duplication' }, { icon: '✂️', label: '剪辑计划', path: '/editing-planner' }, { icon: '🎤', label: '我的音色', path: '/voice-clone' }, { icon: '🔑', label: '账号管理', path: '/accounts' }, ]; const bottomItems = [ { icon: '💎', label: '订阅管理', path: '/subscription' }, ]; ``` **侧边栏样式(来自原型):** ```tsx // Sidebar CSS const sidebarStyle = { background: 'rgba(255, 255, 255, 0.88)', backdropFilter: 'blur(18px)', borderRight: '1px solid rgba(226, 232, 240, 0.9)', padding: '24px 16px', position: 'sticky' as const, top: '68px', height: 'calc(100vh - 68px)', overflowY: 'auto' as const, }; const sidebarItemStyle = { display: 'flex', alignItems: 'center', gap: '12px', padding: '12px 14px', borderRadius: 'var(--radius-sm)', color: 'var(--muted)', cursor: 'pointer', fontWeight: 600, fontSize: '14px', transition: '0.15s ease', }; const sidebarItemActiveStyle = { ...sidebarItemStyle, background: 'var(--primary-soft)', color: 'var(--primary)', fontWeight: 700, }; const iconStyle = { width: '36px', height: '36px', borderRadius: '10px', display: 'grid', placeItems: 'center', fontSize: '18px', background: '#f1f5f9', }; const iconActiveStyle = { ...iconStyle, background: 'var(--primary)', color: '#fff', }; ``` ### 2.3 页面头部(PageHead) ```tsx // components/common/PageHead.tsx interface PageHeadProps { title: string; description?: string; tag?: string; actions?: React.ReactNode; } const PageHead: React.FC = ({ title, description, tag, actions }) => { return (
{tag && {tag}}

{title}

{description && (

{description}

)}
{actions &&
{actions}
}
); }; ``` ### 2.4 页面容器(Wrap) ```tsx // 全局页面包装器 const Wrap: React.FC<{ children: React.ReactNode }> = ({ children }) => (
{children}
); ``` --- ## 3. 逐页开发指令 ### 3.1 控制台 (Dashboard) **文件路径:** `pages/dashboard/Dashboard.tsx` **路由:** `/dashboard` **当前状态:** - ✅ API 调用逻辑已实现 - ✅ 统计数据获取逻辑已实现 - ⚠️ KPI 卡片使用 Ant Design 样式 - ⚠️ 最近任务使用 Table 布局,需改为卡片式 - ⚠️ 缺少快速入口卡片网格(4列布局) **UI 差异清单:** | 差异项 | 当前状态 | 原型状态 | 优先级 | |--------|----------|----------|--------| | KPI 卡片样式 | Ant Design Card | 渐变背景 + 大号数字 + 趋势 | P2 | | 最近任务布局 | Table | 卡片式列表 | P2 | | 快速入口网格 | 无 | 4列 feature-grid | P2 | | 页面头部欢迎语 | - | 带用户名的欢迎语 + 日期 | P2 | **具体修改指令:** #### 3.1.1 KPI 卡片网格 **改什么:** 将现有的 KPI 卡片改为原型设计的渐变背景卡片 **改成什么样子:** ``` ┌────────────┬────────────┬────────────┬────────────┐ │ 12 │ 486 │ 156 │ 2.4GB │ │ 项目总数 │ 素材总数 │ 本月生成数 │ 存储空间 │ │ ↑2本月新增 │ ↑38本月上传 │ ↑23% vs上月│ 已用24% │ └────────────┴────────────┴────────────┴────────────┘ ``` **使用 Ant Design/Tailwind 组件:** ```tsx // 使用 Tailwind + 自定义样式
{kpiData.map((item) => (
{item.value}
{item.label}
{item.trend}
))}
``` #### 3.1.2 最近任务卡片列表 **改什么:** 将 Table 布局改为卡片式列表 **改成什么样子:** ```tsx
{recentTasks.map((task) => (
{/* 任务信息 */}

{task.name}

{task.type} · 模板:{task.template}
{/* 状态标签 */} {/* 时间 */}
{task.date} {task.status === 'completed' ? `耗时 ${task.duration}` : '进行中'}
{/* 操作按钮 */}
))}
``` #### 3.1.3 快速入口卡片网格 **改什么:** 新增快速入口区域,使用 4 列 feature-grid **改成什么样子:** ```tsx

快速入口

{quickEntries.map((entry) => (
navigate(entry.path)} >
{entry.icon}

{entry.title}

{entry.description}

))}
``` **新增数据:** ```tsx const quickEntries = [ { id: 'titles', icon: '📝', iconGradient: 'linear-gradient(135deg, #6366f1, #4f46e5)', title: '标题库', description: '24条标题 · 5个分类', path: '/titles' }, { id: 'assets', icon: '📦', iconGradient: 'linear-gradient(135deg, #0ea5e9, #0284c7)', title: '素材库', description: '486个素材 · 3个素材库', path: '/assets' }, { id: 'generate', icon: '✨', iconGradient: 'linear-gradient(135deg, #10b981, #059669)', title: '一键生成', description: '开始创作新视频', path: '/generate' }, { id: 'products', icon: '🎬', iconGradient: 'linear-gradient(135deg, #f59e0b, #d97706)', title: '成片库', description: '89个成片 · 3个待复核', path: '/products' }, ]; ``` **优先级:** P2 --- ### 3.2 一键生成 (Generate) **文件路径:** `pages/generate/GeneratePage.tsx` **路由:** `/generate` **当前状态:** - ✅ API 调用逻辑已实现 - ❌ 缺失克隆声音展开区域 - ❌ 缺失时间线预览区域 - ❌ 缺失视频预览区域 - ❌ 缺失重新生成按钮 - ⚠️ 步骤条样式需调整 - ⚠️ 表单卡片式选择需调整 - ⚠️ 左右分栏布局需调整 **UI 差异清单:** | 差异项 | 当前状态 | 原型状态 | 优先级 | |--------|----------|----------|--------| | 克隆声音展开区 | 无 | 展开/收起音频上传区 | P1 | | 时间线预览 | 无 | 右侧 sticky 预览 | P1 | | 视频预览区 | 无 | 9:16 竖版预览 | P1 | | 重新生成按钮 | 无 | 预览区左下角 | P1 | | 步骤条 | - | 居中 4 步骤 | P2 | | 选择卡片 | - | 选中带对勾图标 | P2 | | 左右分栏 | - | 1fr:320px | P2 | **具体修改指令:** #### 3.2.1 整体布局改造 **改什么:** 改为左右分栏布局(1fr : 320px) ```tsx
{/* 左侧表单区 */}
{/* ... */}
{/* 右侧预览区 */}
{/* ... */}
``` #### 3.2.2 步骤条组件 **改什么:** 实现居中 4 步骤条 ```tsx
{[ { num: 1, label: '选择模板', active: true }, { num: 2, label: '选择素材', active: false }, { num: 3, label: '选择标题', active: false }, { num: 4, label: '选择配音', active: false }, ].map((step, idx) => ( {idx > 0 && }
{step.num}
{step.label}
))}
``` #### 3.2.3 选择卡片组件 **改什么:** 模板/配音选择使用卡片式,带选中状态和勾选图标 ```tsx
{options.map((opt) => (
setSelectedId(opt.id)} style={{ background: '#fff', border: `2px solid ${selectedId === opt.id ? 'var(--primary)' : 'var(--line)'}`, borderRadius: 'var(--radius-md)', padding: '14px', cursor: 'pointer', position: 'relative', textAlign: 'center', transition: 'var(--transition-base)', }} > {/* 选中对勾 */} {selectedId === opt.id && (
)} {/* 缩略图 */}
{opt.thumb}

{opt.title}

{opt.desc}

))}
``` #### 3.2.4 克隆声音展开区域 **改什么:** 在选择配音的第4步,点击"克隆我的声音"选项后展开音频上传区域 ```tsx {/* 克隆声音选项被选中时显示 */} {selectedVoice === 'clone' && (

🎤 克隆我的声音

上传你的声音,AI将用你的音色生成配音

{/* 上传区域 */}
🎵

拖拽或点击上传音频文件(MP3/WAV,10秒以上)

支持格式:MP3、WAV · 建议时长:10秒~3分钟

{/* 录音按钮 */}
{/* 提示 */}

💡 建议上传10秒~3分钟的清晰语音,环境安静、语速均匀效果最佳

{/* 已克隆音色选择 */}

或选择已克隆的音色:

{clonedVoices.map((voice) => ( ))}
{/* 开始克隆按钮 */}
)} ``` #### 3.2.5 右侧预览区域 **改什么:** 实现 sticky 定位的视频预览、时间线预览 ```tsx
{/* 视频预览 */}
{/* 渐变叠加 */}
{/* 播放按钮 */}
{/* 标题预览 */}
{selectedTitle}
{/* 剪辑计划标题 */}
剪辑计划预览
{/* 时间线 */}
{timeline.map((item, idx) => (
{idx + 1}
{item.scene} {item.time}
))}
{/* 操作按钮 */}
``` **优先级:** P1 --- ### 3.3 标题库 (Title Library) **文件路径:** `pages/titles/TitleLibrary.tsx` **路由:** `/titles` **当前状态:** - ✅ CRUD + 批量导入已实现 - ❌ 缺失左侧分类列表(需两栏布局) - ❌ 缺失标题卡片网格布局 - ❌ 缺失收藏功能(★/☆切换) **UI 差异清单:** | 差异项 | 当前状态 | 原型状态 | 优先级 | |--------|----------|----------|--------| | 左侧分类列表 | 无 | 两栏布局左侧 | P1 | | 标题卡片网格 | Table | 3列卡片网格 | P1 | | 收藏功能 | 无 | ★/☆切换 | P1 | | 页面头部 | - | 批量导入 + 新增按钮 | P2 | **具体修改指令:** #### 3.3.1 两栏布局 ```tsx
{/* 左侧分类列表 */}
{categories.map((cat) => (
setSelectedCategory(cat.id)} style={{ border: `1px solid ${selectedCategory === cat.id ? 'var(--primary)' : 'var(--line)'}`, background: selectedCategory === cat.id ? 'var(--primary-soft)' : '#fff', borderRadius: 'var(--radius-sm)', padding: '14px', cursor: 'pointer', transition: '0.15s ease', }} >

{cat.name}

{cat.count} 条
))}
{/* 右侧标题卡片网格 */}
{titles.map((title) => ( ))}
``` #### 3.3.2 标题卡片组件 ```tsx interface TitleCardProps { title: { id: string; content: string; category: string; usageCount: number; isFavorited: boolean; }; } const TitleCard: React.FC = ({ title }) => { const [isFavorited, setIsFavorited] = useState(title.isFavorited); return (
{title.content}
{title.category} 使用 {title.usageCount} 次
{ e.stopPropagation(); setIsFavorited(!isFavorited); }} style={{ color: isFavorited ? 'var(--amber)' : 'var(--muted)', fontSize: '16px', cursor: 'pointer', }} > {isFavorited ? '★' : '☆'}
); }; ``` **优先级:** P1 --- ### 3.4 素材库 (Asset Library) **文件路径:** `pages/assets/AssetLibrary.tsx` **路由:** `/assets` **当前状态:** - ✅ 上传功能、素材库管理已实现 - ❌ 缺失左侧素材库列表(需两栏布局) - ⚠️ 素材卡片样式、状态标签、诊断按钮需对齐 **UI 差异清单:** | 差异项 | 当前状态 | 原型状态 | 优先级 | |--------|----------|----------|--------| | 左侧素材库列表 | 无 | 260px 宽列表 | P1 | | 素材卡片样式 | - | 9:16 竖版缩略图 | P2 | | 状态标签 | - | ok/warn/bad/info | P2 | | 诊断按钮 | - | 卡片底部 | P2 | **具体修改指令:** #### 3.4.1 两栏布局 ```tsx
{/* 左侧素材库列表 */}
{assetLibraries.map((lib) => (

{lib.name}

{lib.count} 个素材 · {lib.size}
))}
{/* 右侧素材网格 */}
{assets.map((asset) => ( ))}
``` #### 3.4.2 素材卡片组件 ```tsx const AssetCard: React.FC<{ asset: Asset }> = ({ asset }) => (
{/* 缩略图 */}
{/* 信息 */}

{asset.name}

{asset.duration}
); ``` **优先级:** P1 --- ### 3.5 配音库 (Voice Library) **文件路径:** `pages/voices/VoiceLibrary.tsx` **路由:** `/voices` **当前状态:** - ✅ AI生成、CRUD 功能已实现 - ❌ 缺失左侧配音库分类列表 - ❌ 缺失配音卡片布局(voice-card + voice-wave 波形) **UI 差异清单:** | 差异项 | 当前状态 | 原型状态 | 优先级 | |--------|----------|----------|--------| | 左侧分类列表 | 无 | 220px 宽 | P1 | | 配音卡片 | 表格 | voice-card 布局 | P1 | | 波形可视化 | 无 | 灰色波形条 | P1 | | 页面头部 | - | 新建配音库+AI生成+上传 | P2 | **具体修改指令:** #### 3.5.1 配音库两栏布局 ```tsx
{/* 左侧配音库分类 */}
{voiceLibraries.map((lib) => (

{lib.name}

{lib.count} 条配音
))}
{/* 右侧配音卡片列表 */}
{voices.map((voice) => ( ))}
``` #### 3.5.2 配音卡片组件 ```tsx const VoiceCard: React.FC<{ voice: Voice }> = ({ voice }) => (
{/* 头像 */}
🎙️
{/* 信息 */}

{voice.name}

{voice.library} · {voice.duration} · {voice.gender}
{/* 波形 */}
{/* 操作 */}
); ``` **优先级:** P1 --- ### 3.6 成片库 (Product Library) **文件路径:** `pages/products/ProductLibrary.tsx` **路由:** `/products` **当前状态:** - ✅ 下载/预览/删除/查重率展示已实现 - ❌ 缺失批量选择功能 - ❌ 缺失批量发布/批量下载按钮 - ❌ 缺失已发布状态角标 **UI 差异清单:** | 差异项 | 当前状态 | 原型状态 | 优先级 | |--------|----------|----------|--------| | 批量选择 | 无 | 复选框 + 全选 | P1 | | 批量操作按钮 | 无 | 发布 + 下载 | P1 | | 已发布角标 | 无 | 右上角绿色角标 | P1 | | 选中效果 | 无 | 边框高亮 + 阴影 | P1 | **具体修改指令:** #### 3.6.1 页面头部批量操作 ```tsx

成片库

查看和管理生成的视频成品

{/* 全选复选框 */} {/* 已选计数 */} 已选 {selectedCount} 个视频 {/* 批量发布按钮 */} {/* 批量下载 */}
``` #### 3.6.2 成片卡片(含批量选择) ```tsx const ProductCard: React.FC<{ product: Product }> = ({ product }) => { const [isSelected, setIsSelected] = useState(false); return (
{/* 选择复选框 */}
setIsSelected(!isSelected)} style={{ width: '18px', height: '18px', accentColor: 'var(--primary)', opacity: product.isPublished ? 0.4 : 1, }} />
{/* 已发布角标 */} {product.isPublished && (
已发布
)} {/* 缩略图 */}
{product.duration}
{/* 信息 */}

{product.name}

{product.date}
{product.isPublished ? ( ✅ 已发布 ) : ( )}
); }; ``` **优先级:** P1 --- ### 3.7 任务历史 (Task History) **文件路径:** `pages/history/TaskHistory.tsx` **路由:** `/history` **当前状态:** - ✅ 状态筛选逻辑、重试功能已实现 - ⚠️ 状态筛选 Tab 样式需调整 - ⚠️ 任务列表需改为卡片布局 **UI 差异清单:** | 差异项 | 当前状态 | 原型状态 | 优先级 | |--------|----------|----------|--------| | 状态 Tab | - | 圆角胶囊样式 | P2 | | 任务列表 | Table | 卡片式布局 | P2 | **具体修改指令:** #### 3.7.1 Tab 切换样式 ```tsx
{[ { key: 'all', label: '全部', count: 156 }, { key: 'running', label: '进行中', count: 3 }, { key: 'done', label: '已完成', count: 150 }, { key: 'failed', label: '失败', count: 3 }, ].map((tab) => (
setActiveTab(tab.key)} style={{ padding: '8px 16px', borderRadius: 'var(--radius-sm)', cursor: 'pointer', fontWeight: 600, fontSize: '14px', color: activeTab === tab.key ? 'var(--primary)' : 'var(--muted)', background: activeTab === tab.key ? 'var(--primary-soft)' : 'transparent', transition: '0.15s ease', }} > {tab.label} ({tab.count})
))}
``` #### 3.7.2 任务卡片列表 ```tsx
{tasks.map((task) => (
{/* 任务信息 */}

{task.name}

{task.type} · 模板:{task.template}
{/* 状态 */} {/* 时间 */}
{task.date} {task.status === 'failed' ? '失败' : task.status === 'running' ? '进行中' : `耗时 ${task.duration}`}
{/* 操作 */}
))}
``` **优先级:** P2 --- ### 3.8 模板库 (Template Library) **文件路径:** `pages/templates/TemplateLibrary.tsx` **路由:** `/templates` **当前状态:** - ✅ 搜索/筛选/收藏逻辑已实现 - ⚠️ 分类筛选改为按钮组 - ⚠️ 卡片 4 列布局 - ⚠️ 创建模板按钮位置 **UI 差异清单:** | 差异项 | 当前状态 | 原型状态 | 优先级 | |--------|----------|----------|--------| | 分类筛选 | 下拉框 | 胶囊按钮组 | P2 | | 模板卡片 | - | 4列网格 | P2 | | 卡片样式 | - | 16:9 缩略图 | P2 | | 页面头部 | - | 标题+创建模板按钮 | P2 | **具体修改指令:** #### 3.8.1 工具栏(搜索 + 分类按钮组) ```tsx
{/* 搜索框 */}
🔍
{/* 分类按钮组 */}
{['全部', '口播', '种草', '产品', '品牌'].map((cat) => ( ))}
``` #### 3.8.2 模板卡片 ```tsx
{templates.map((tmpl) => (
{/* 缩略图 */}
{tmpl.code}
{/* 信息 */}

{tmpl.name}

使用 {tmpl.usageCount} 次
))}
``` **优先级:** P2 --- ### 3.9 订阅管理 (Subscription) **文件路径:** `pages/subscription/SubscriptionPage.tsx` **路由:** `/subscription` **当前状态:** - ✅ 订阅逻辑已实现 - ⚠️ 定价卡片样式、特性列表、价格展示需对齐 - ⚠️ 当前套餐信息卡片样式 - ❌ 账单记录表格 **UI 差异清单:** | 差异项 | 当前状态 | 原型状态 | 优先级 | |--------|----------|----------|--------| | 定价卡片样式 | - | 原型卡片样式 | P2 | | 特性列表 | - | 带勾选列表 | P2 | | 当前套餐卡片 | - | 标签+按钮组 | P2 | | 账单记录表格 | 无 | 完整表格 | P1 | **具体修改指令:** #### 3.9.1 账单记录表格 ```tsx

账单记录

{['订单号', '套餐', '金额', '支付方式', '时间', '状态'].map((h) => ( ))} {bills.map((bill) => ( ))}
{h}
{bill.orderNo} {bill.plan} ¥{bill.amount.toLocaleString()} {bill.paymentMethod} {bill.date}
``` **优先级:** P1(账单表格)、P2(其他样式) --- ### 3.10 剪辑计划编辑器 (Editing Planner) **文件路径:** `pages/editing-planner/EditingPlanner.tsx` **路由:** `/editing-planner` **当前状态:** - ✅ 核心功能已实现 - ⚠️ 模式切换按钮样式 - ⚠️ 面板样式对齐 **优先级:** P2 --- ## 4. 新增页面开发指令 ### 4.1 查重检测页面组 **目录:** `pages/duplication/` **涉及文件:** - `DuplicationUpload.tsx` - 上传页面 - `DuplicationResults.tsx` - 结果页面 - `DuplicationDetail.tsx` - 详情页面 **路由配置:** ```tsx { path: '/duplication', element: , children: [ { path: '', element: }, { path: 'results/:id', element: }, { path: 'detail/:id', element: }, ] } ``` #### 4.1.1 DuplicationUpload 页面规格 **页面布局:** 左右分栏(1fr : 1fr) ```tsx // pages/duplication/DuplicationUpload.tsx const DuplicationUpload: React.FC = () => { return (
{/* 左侧上传区 */}
📤

拖拽上传视频文件

或点击选择文件上传

支持格式:MP4 / AVI / MOV / MKV,单文件 ≤ 2GB
{/* 右侧结果区 */}
); }; ``` #### 4.1.2 DuplicationResults 页面规格 ```tsx // pages/duplication/DuplicationResults.tsx const DuplicationResults: React.FC = () => { const { id } = useParams(); return ( 📥 下载报告 } />
{/* 相似度圆环 */}
12%
相似度

该视频相似度较低,原创性良好

{/* 匹配列表 */}

匹配的视频片段

{matches.map((match) => (

{match.videoName}

相似片段:{match.segment}

{match.similarity}%
))}
); }; ``` **优先级:** P1 --- ### 4.2 我的音色 (Voice Clone) **目录:** `pages/voice-clone/` **文件:** `VoiceClone.tsx` **路由:** `/voice-clone` #### 4.2.1 页面规格 ```tsx // pages/voice-clone/VoiceClone.tsx const VoiceClone: React.FC = () => { return ( ✨ 克隆新音色 } /> {/* 音色卡片网格 */}
{clonedVoices.map((voice) => ( ))}
{/* 空状态 */} {clonedVoices.length === 0 && (
🎤

还没有克隆音色

上传你的声音,AI将克隆你的专属音色

)} ); }; ``` #### 4.2.2 音色克隆卡片组件 ```tsx interface VoiceCloneCardProps { voice: { id: string; name: string; duration: string; createdAt: string; status: 'ready' | 'processing'; }; } const VoiceCloneCard: React.FC = ({ voice }) => (
{/* 操作按钮 */}
{/* 头部信息 */}
🎤

{voice.name}

{/* 元信息 */}
🎵 时长:{voice.duration}
📅 创建于:{voice.createdAt}
{/* 操作区 */}
); ``` #### 4.2.3 克隆音色 Modal ```tsx // components/modals/CloneVoiceModal.tsx const CloneVoiceModal: React.FC<{ visible: boolean; onClose: () => void }> = ({ visible, onClose, }) => { const [step, setStep] = useState<'input' | 'uploading' | 'success'>('input'); return ( {/* 音色名称 */} {/* 上传区域 */}
🎵

拖拽音频文件到此处

支持 MP3、WAV 格式

{/* 或分隔 */}
{/* 录音 */}

点击按钮开始录制你的声音

{/* 提示 */}
💡 建议上传10秒~3分钟的清晰语音,环境安静、语速均匀效果最佳
{/* 按钮 */}
); }; ``` **优先级:** P1 --- ### 4.3 账号管理 (Accounts) **目录:** `pages/accounts/` **文件:** `Accounts.tsx` **路由:** `/accounts` #### 4.3.1 页面规格 ```tsx // pages/accounts/Accounts.tsx const Accounts: React.FC = () => { const platforms = [ { id: 'douyin', name: '抖音', icon: '📱', gradient: 'linear-gradient(135deg, #fe2c55, #25f4ee)' }, { id: 'kuaishou', name: '快手', icon: '🎬', gradient: 'linear-gradient(135deg, #ff4906, #ffba00)' }, { id: 'xiaohongshu', name: '小红书', icon: '📕', gradient: 'linear-gradient(135deg, #ff2442, #ff6b6b)' }, { id: 'wechat', name: '微信视频号', icon: '💬', gradient: 'linear-gradient(135deg, #07c160, #4cd964)' }, ]; return (
{platforms.map((platform) => ( ))}
{/* 底部统计 */}
📊 已绑定 4 个账号 / 支持 4 个平台
); }; ``` #### 4.3.2 平台账号卡片组件 ```tsx interface PlatformCardProps { platform: { id: string; name: string; subName: string; icon: string; gradient: string; }; } const PlatformCard: React.FC = ({ platform }) => { const accounts = useAccounts(platform.id); return (
{/* 平台头部 */}
{platform.icon}

{platform.name}

{platform.subName}

{/* 账号列表 */}
{accounts.length > 0 ? ( accounts.map((account) => (
{account.avatar || platform.icon}
{account.name}
)) ) : (
🔓

暂未绑定账号

)}
{/* 绑定按钮 */}
); }; ``` **优先级:** P1 --- ### 4.4 首页 (Landing Page) **目录:** `pages/home/` **文件:** `HomePage.tsx` **路由:** `/` #### 4.4.1 页面规格 ```tsx // pages/home/HomePage.tsx const HomePage: React.FC = () => { return (
{/* Hero 区域 */} {/* 功能卡片 */} {/* 工作流程 */} {/* 定价预览 */} {/* CTA */}
); }; ``` #### 4.4.2 Hero 区域组件 ```tsx const HeroSection: React.FC = () => (
🦐 小虾智剪 · AI智能视频创作平台

上传素材,AI自动剪辑
一键生成短视频

面向口播、产品介绍、直播切片和企业宣传的智能视频创作平台。

✨ AI智能剪辑 ⚡ 30秒生成
可发布
); ``` **优先级:** P3 --- ## 5. 基础组件封装规范 ### 5.1 StatusPill 状态标签 ```tsx // components/common/StatusPill.tsx type StatusType = 'ok' | 'warn' | 'bad' | 'info' | 'muted'; interface StatusPillProps { status: StatusType; label?: string; } const statusConfig: Record = { ok: { bg: '#dcfce7', color: '#166534', defaultLabel: '已通过' }, warn: { bg: '#ffedd5', color: '#c2410c', defaultLabel: '待复核' }, bad: { bg: '#ffe4e6', color: '#be123c', defaultLabel: '高风险' }, info: { bg: '#dbeafe', color: '#1d4ed8', defaultLabel: '视频' }, muted: { bg: '#f1f5f9', color: '#64748b', defaultLabel: '品牌' }, }; export const StatusPill: React.FC = ({ status, label }) => { const config = statusConfig[status]; return ( {label || config.defaultLabel} ); }; ``` ### 5.2 CategoryPill 分类标签 ```tsx // components/common/CategoryPill.tsx const categoryConfig: Record = { 口播: { bg: '#dbeafe', color: '#1d4ed8' }, 种草: { bg: '#dcfce7', color: '#166534' }, 产品: { bg: '#ffedd5', color: '#c2410c' }, 品牌: { bg: '#f1f5f9', color: '#64748b' }, 直播: { bg: '#fef3c7', color: '#92400e' }, 教程: { bg: '#e0e7ff', color: '#4338ca' }, }; interface CategoryPillProps { category: string; } export const CategoryPill: React.FC = ({ category }) => { const config = categoryConfig[category] || categoryConfig['口播']; return ( {category} ); }; ``` ### 5.3 IconBox 图标盒子 ```tsx // components/common/IconBox.tsx interface IconBoxProps { icon: string; gradient?: string; size?: number; } export const IconBox: React.FC = ({ icon, gradient = 'linear-gradient(135deg, #6366f1, #4f46e5)', size = 44, }) => (
{icon}
); ``` ### 5.4 UploadZone 上传区域 ```tsx // components/common/UploadZone.tsx interface UploadZoneProps { accept?: string; maxSize?: number; // MB onUpload: (file: File) => void; } export const UploadZone: React.FC = ({ accept = '*', maxSize = 2048, onUpload, }) => { const [isDragging, setIsDragging] = useState(false); const handleDrop = (e: React.DragEvent) => { e.preventDefault(); setIsDragging(false); const file = e.dataTransfer.files[0]; if (file && file.size <= maxSize * 1024 * 1024) { onUpload(file); } }; return (
{ e.preventDefault(); setIsDragging(true); }} onDragLeave={() => setIsDragging(false)} onDrop={handleDrop} style={{ border: `2px dashed ${isDragging ? 'var(--primary-light)' : 'var(--line)'}`, borderRadius: 'var(--radius-lg)', padding: '60px', textAlign: 'center', background: isDragging ? 'var(--primary-soft)' : 'linear-gradient(180deg, #fff, #f8fafc)', transition: 'var(--transition-base)', cursor: 'pointer', }} >

拖拽上传文件

或点击选择文件

); }; ``` ### 5.5 EmptyState 空状态 ```tsx // components/common/EmptyState.tsx interface EmptyStateProps { icon?: string; title: string; description?: string; action?: { label: string; onClick: () => void; type?: 'primary' | 'ghost'; }; } export const EmptyState: React.FC = ({ icon = '📭', title, description, action, }) => (

{title}

{description && (

{description}

)} {action && ( )}
); ``` --- ## 6. 执行顺序建议 ### Phase 1: 基础对齐(5-7 人天) | 序号 | 任务 | 文件 | 优先级 | 预估人天 | |------|------|------|--------|----------| | 1.1 | 设计系统 CSS 变量统一 | `global.css` | P0 | 0.5 | | 1.2 | 主布局组件 AppLayout | `components/layout/AppLayout.tsx` | P0 | 1 | | 1.3 | 侧边栏组件 Sidebar | `components/layout/Sidebar.tsx` | P0 | 1 | | 1.4 | 页面头部组件 PageHead | `components/common/PageHead.tsx` | P0 | 0.5 | | 1.5 | 基础组件封装 | `components/common/*` | P1 | 2 | ### Phase 2: 核心页面改造(8-10 人天) | 序号 | 任务 | 文件 | 优先级 | 预估人天 | |------|------|------|--------|----------| | 2.1 | 一键生成页面 | `pages/generate/GeneratePage.tsx` | P1 | 2 | | 2.2 | 素材库页面 | `pages/assets/AssetLibrary.tsx` | P1 | 1.5 | | 2.3 | 配音库页面 | `pages/voices/VoiceLibrary.tsx` | P1 | 1.5 | | 2.4 | 标题库页面 | `pages/titles/TitleLibrary.tsx` | P1 | 1.5 | | 2.5 | 成片库页面 | `pages/products/ProductLibrary.tsx` | P1 | 2 | ### Phase 3: 次要页面改造(5-7 人天) | 序号 | 任务 | 文件 | 优先级 | 预估人天 | |------|------|------|--------|----------| | 3.1 | 控制台页面 | `pages/dashboard/Dashboard.tsx` | P2 | 1.5 | | 3.2 | 模板库页面 | `pages/templates/TemplateLibrary.tsx` | P2 | 1 | | 3.3 | 任务历史页面 | `pages/history/TaskHistory.tsx` | P2 | 1 | | 3.4 | 订阅管理页面 | `pages/subscription/SubscriptionPage.tsx` | P2 | 1.5 | | 3.5 | 剪辑计划编辑器 | `pages/editing-planner/EditingPlanner.tsx` | P2 | 1 | ### Phase 4: 新增页面(3-5 人天) | 序号 | 任务 | 文件 | 优先级 | 预估人天 | |------|------|------|--------|----------| | 4.1 | 查重检测上传页 | `pages/duplication/DuplicationUpload.tsx` | P1 | 0.5 | | 4.2 | 查重检测结果页 | `pages/duplication/DuplicationResults.tsx` | P1 | 0.5 | | 4.3 | 查重检测详情页 | `pages/duplication/DuplicationDetail.tsx` | P1 | 0.5 | | 4.4 | 我的音色页面 | `pages/voice-clone/VoiceClone.tsx` | P1 | 1 | | 4.5 | 音色克隆 Modal | `components/modals/CloneVoiceModal.tsx` | P1 | 1 | | 4.6 | 账号管理页面 | `pages/accounts/Accounts.tsx` | P1 | 1 | | 4.7 | 首页落地页 | `pages/home/HomePage.tsx` | P3 | 1 | --- ## 附录 ### A. 路由配置参考 ```tsx // router/index.tsx const router = createBrowserRouter([ // 公开页面 { path: '/', element: }, { path: '/login', element: }, { path: '/subscription', element: }, // 受保护页面(需要登录) { path: '/app', element: , children: [ { index: true, element: }, { path: 'dashboard', element: }, { path: 'titles', element: }, { path: 'assets', element: }, { path: 'voices', element: }, { path: 'templates', element: }, { path: 'generate', element: }, { path: 'products', element: }, { path: 'history', element: }, { path: 'editing-planner', element: }, { path: 'subscription', element: }, { path: 'duplication/*', element: }, { path: 'voice-clone', element: }, { path: 'accounts', element: }, ], }, ]); ``` ### B. 样式文件结构 ``` src/ ├── styles/ │ ├── global.css # CSS 变量、reset、通用样式 │ ├── components.css # 组件样式(可选) │ └── pages/ │ ├── dashboard.css │ ├── generate.css │ └── ... ``` ### C. 注意事项 1. **不删除现有功能**:所有已有的 API 调用逻辑、数据获取/提交逻辑必须保持不变 2. **不改变业务逻辑**:只修改 UI 展示层 3. **保持路由一致**:路由配置必须与原型保持一致 4. **响应式适配**:参考原型中的 `@media` 断点进行响应式处理 --- > 文档版本:V21.1 > 最后更新:2024年 --- > 本内容由 Coze AI 生成,请遵循相关法律法规及《人工智能生成合成内容标识办法》使用与传播。