zyc ffe92f7b15 Initial commit: 即梦视频生成平台
- web/: React + Vite + TypeScript 前端
- backend/: Django + DRF + SimpleJWT 后端
- prototype/: HTML 设计原型
- docs/: PRD 和设计评审文档
- test: 单元测试 + E2E 极限测试
2026-03-13 09:59:33 +08:00

73 KiB
Raw Permalink Blame History

产品需求文档 (PRD)

1. 项目概述

  • 项目名称: Jimeng Clone — AI 视频生成平台
  • 一句话描述: 1:1 还原即梦平台 (jimeng.jianying.com) 的 AI 视频生成页面,包含完整的用户认证体系、视频生成输入界面、后台管理系统和用户个人中心
  • 目标用户: 前端开发学习者、AI 视频产品原型验证团队、平台管理员
  • 项目范围: 视频生成输入栏InputBar及其交互逻辑 + Django 后端 API + 用户登录注册 + 后台管理(生成秒数统计与限制) + 用户个人中心(消费概览与记录)

开发阶段划分

阶段 范围 状态
Phase 1 纯前端视频生成输入界面InputBar、工具栏、上传、模式切换 已完成
Phase 2 Django 后端 + 用户认证 + 前端路由 + 管理后台(基于调用次数) 已完成
Phase 3 计量单位变更(次数→秒数)+ 管理后台重做(多页面 Sidebar+ 用户个人中心 🔲 待开发

当前迭代范围: Phase 3。Phase 1 和 Phase 2 功能已完成。Phase 3 在 Phase 2 基础上进行重大重构和新增功能。文档中 [Phase 3] 标记用于区分本次迭代的新增/修改内容。

Phase 3 核心变更摘要

  1. 计量单位变更: 所有「调用次数」改为「生成秒数」,用户每次生成视频消耗的是秒数(= 视频时长),不是次数
  2. 后台管理系统重做: 从单页面改为多页面 + 左侧 Sidebar 导航(仪表盘/用户管理/消费记录/系统设置)
  3. 新增用户个人中心 /profile: 消费概览 + 消费记录 + 趋势迷你图
  4. 图表库引入: 使用 EChartsecharts + echarts-for-react展示趋势图、排行榜、环形进度条
  5. 设计升级: 管理后台深色主题Linear/Vercel 风格)、骨架屏加载、页面过渡动画

2. 功能需求

2.1 核心功能P0

已有前端功能

  • 深色主题全屏页面 — 背景色 #0a0a0f,页面无滚动,输入栏固定在底部居中,最大宽度 ~900px
  • InputBar 容器 — 背景 #16161e,边框 1px solid #2a2a38,圆角 20px,内部分为上半区(上传+输入)和下半区(工具栏)
  • 提示词多行文本输入框 — 自适应高度min 1行max ~6行支持换行输入placeholder 根据当前模式动态切换
  • 全能参考模式(默认模式) — 左侧 [+ 参考内容] 上传按钮,支持上传 1-5 张图片/视频文件上传后显示缩略图网格每张标注「图片1」「图片2」等序号每个缩略图右上角有 × 关闭按钮;上传区与文本输入框左右排列
  • 首尾帧模式 — 上传区变为 [首帧缩略图] ↔ [+ 尾帧] 双框布局,中间双向箭头图标连接;首帧和尾帧各上传一张图片
  • 模式切换下拉 — 工具栏中「全能参考/首尾帧」下拉菜单,点击切换模式,切换时联动:上传区 UI、比例选项、时长默认值
  • 工具栏按钮行 — 一行横排按钮,透明背景,灰色文字 #8a8a9ahover 时微亮背景
  • 发送按钮 — 圆形按钮,内含上箭头图标;无内容时灰色不可点击,有内容(文字或上传文件)时变为蓝色 #00b8e6 可点击

[Phase 2] 用户认证系统

  • 用户注册页面 — 前端注册页 /register,包含用户名、邮箱、密码、确认密码字段,提交后调用后端注册 API
  • 用户登录页面 — 前端登录页 /login,包含用户名/邮箱、密码字段,登录成功后获取 JWT Token 并存储到 localStorage
  • JWT 认证机制 — 后端签发 Access Token有效期 2 小时)+ Refresh Token有效期 7 天),前端请求自动附加 Authorization Bearer Token
  • 登录状态保持 — 前端全局 Auth 状态管理Zustand未登录用户自动跳转到登录页已登录用户显示用户信息和退出按钮
  • Token 自动刷新 — Access Token 过期时自动使用 Refresh Token 刷新,刷新失败则跳转到登录页

[Phase 2] Django 后端服务

  • Django 项目初始化 — 在 backend/ 子目录创建 Django 项目,连接 MySQL 云数据库
  • RESTful API — 使用 Django REST Framework (DRF) 提供用户认证、视频生成记录等 API
  • CORS 配置 — 允许前端开发服务器localhost:5173跨域访问后端 API

[Phase 3] 计量单位变更(次数 → 秒数)

  • 用户配额字段变更 — User 模型的 daily_limit / monthly_limit(次数)改为 daily_seconds_limit / monthly_seconds_limit(秒数),默认值分别为 600秒/日、6000秒/月
  • 消费记录增加秒数字段 — GenerationRecord 模型新增 seconds_consumed 字段FloatField记录每次生成消耗的秒数= 视频时长 duration
  • 配额检查逻辑变更 — 后端配额检查从「今日调用次数 < daily_limit」改为「今日消费秒数 < daily_seconds_limit」
  • 前端展示变更 — 所有显示「剩余次数」的地方改为「剩余秒数」UserInfoBar 组件配额显示改为秒数

[Phase 3] 后台管理系统重做

  • 管理后台布局 — 采用左侧 Sidebar + 右侧内容区的经典管理后台布局Sidebar 固定宽度 240px支持折叠
  • Sidebar 导航菜单 — 包含 4 个导航项:仪表盘、用户管理、消费记录、系统设置,当前项高亮,使用 react-router 嵌套路由
  • 管理后台路由/admin 为管理后台根路由(重定向到 /admin/dashboard),子路由:/admin/dashboard/admin/users/admin/records/admin/settings

[Phase 3] 用户个人中心

  • 个人中心页面 — 新增 /profile 路由,已登录用户可访问,展示个人消费概览和历史记录
  • 消费概览卡片 — 显示已用秒数/总额度(环形进度条,使用 ECharts gauge、今日已用/日限额、本月已用/月限额

2.2 重要功能P1

已有前端功能

  • 视频生成下拉按钮 — 蓝色文字 #00b8e6 + 视频图标 + 下拉箭头,点击展开下拉菜单(菜单项仅 UI 展示,如"视频生成"/"图片生成"等)
  • 模型选择按钮 — 显示「Seedance 2.0」+ 钻石图标,点击展开模型选择下拉(仅 UI 展示,如 Seedance 2.0 / Seedance 2.0 Fast
  • 比例选择按钮 — 全能参考模式下显示屏幕图标 + 当前比例值,点击弹出选项:16:9 / 9:16 / 1:1 / 21:9 / 4:3 / 3:4,默认 21:9;首尾帧模式下显示「自动匹配」不可选择
  • 时长选择按钮 — 时钟图标 + 当前时长值,点击弹出选项:5s / 10s / 15s;全能参考模式默认 15s,首尾帧模式默认 5s
  • @ 按钮 — 仅在全能参考模式下显示,点击插入 @ 符号到文本输入框光标位置
  • 文件上传交互 — 点击上传区触发文件选择器accept 为 image/*,video/*;上传后生成本地预览缩略图;支持拖拽上传
  • 上传数量限制 — 全能参考模式最多 5 张,超出时 toast 提示;首尾帧模式首帧/尾帧各 1 张

[Phase 2] 后台管理与生成接入

  • Django Admin 集成 — 启用 Django Admin 面板(/admin/),管理员可查看和管理所有用户、视频生成记录
  • 发送按钮接入后端 — 点击发送按钮时,调用后端 /api/v1/video/generate 接口(需登录),后端记录调用并检查配额

[Phase 3] 仪表盘页面(/admin/dashboard

  • 核心指标卡片 — 4 个统计卡片:总用户数、今日新增用户、今日消费秒数、本月消费秒数。每个卡片显示数值 + 环比变化百分比 + 趋势箭头(↑绿色/↓红色)
  • 消费趋势折线图 — 使用 ECharts 折线图展示近 30 天每日消费秒数趋势,支持 tooltip 悬浮显示具体数值X轴为日期Y轴为秒数
  • 用户消费排行柱状图 — 使用 ECharts 水平柱状图展示消费 Top 10 用户(按本月消费秒数降序),柱状图标签显示用户名和秒数
  • 时间范围选择器 — 支持「今日 / 近7天 / 近30天 / 自定义时间范围」切换,图表数据联动更新
  • 图表 Mock 数据 — 开发阶段使用 30 天的真实结构 Mock 数据(随机波动、周末低谷),确保图表有真实感

[Phase 3] 用户管理页面(/admin/users

  • 用户列表表格 — 分页展示所有用户(每页 20 条),列:头像、用户名、邮箱、注册时间、状态(启用/禁用)、日限额(秒)、月限额(秒)、今日消费(秒)、本月消费(秒)、操作
  • 搜索和筛选 — 支持按用户名/邮箱关键字搜索 + 按状态筛选(全部/启用/禁用)
  • 配额编辑 — 每个用户行的操作列有「编辑配额」按钮,点击弹出模态框,可修改日限额秒数和月限额秒数
  • 用户状态管理 — 操作列有「启用/禁用」开关按钮,点击后调用 API 切换用户 is_active 状态
  • 用户详情抽屉 — 点击用户名展开右侧抽屉面板,显示用户详情 + 该用户近期消费记录列表

[Phase 3] 消费记录页面(/admin/records

  • 消费明细表格 — 分页展示所有用户的消费记录时间、用户名、消费秒数、视频描述prompt 截断)、生成模式、状态
  • 时间范围筛选 — 日期选择器,支持选择起止日期筛选记录
  • 用户筛选 — 支持按用户名搜索筛选特定用户的消费记录
  • 导出功能 — 「导出 CSV」按钮将当前筛选条件下的消费记录导出为 CSV 文件

[Phase 3] 系统设置页面(/admin/settings

  • 全局默认配额设置 — 表单修改全局默认日限额秒数和月限额秒数(新注册用户自动获得此配额)
  • 系统公告管理 — 公告文本编辑框 + 启用/禁用开关,启用后公告内容展示在用户端页面顶部

[Phase 3] 用户个人中心详细功能

  • 消费记录列表 — 分页展示当前用户的消费记录每条记录显示时间、消费秒数、生成的视频描述prompt、生成模式、状态
  • 消费趋势迷你图 — 使用 ECharts Sparkline 样式展示近 7 天 / 近 30 天每日消费秒数趋势,可切换时间范围
  • 配额提示 — 当日额度消费超过 80% 时显示黄色警告提示,超过 100% 时显示红色禁用提示

2.3 锦上添花P2

  • 下拉菜单动画 — 下拉展开/收起有 fade + slide 动画过渡
  • 文本输入框自动聚焦 — 页面加载后自动 focus 到文本输入框
  • 键盘快捷键Ctrl/Cmd + Enter 触发发送(等同点击发送按钮)
  • 上传进度条 — 文件上传时缩略图上显示加载进度
  • 拖拽排序 — 全能参考模式下已上传的缩略图支持拖拽调整顺序
  • 响应式适配 — 移动端窄屏下工具栏按钮文字隐藏只显示图标,输入栏宽度自适应
  • Tooltip 提示 — 工具栏按钮 hover 显示功能说明 tooltip
  • [Phase 2] 忘记密码 — 邮箱验证码找回密码流程
  • [Phase 2] 用户个人资料编辑 — 查看和修改个人信息(头像、昵称)
  • [Phase 3] 页面切换过渡动画 — 路由切换时使用 fade/slide 过渡动画,提升体验流畅度
  • [Phase 3] 数据加载骨架屏 — 管理后台和个人中心的数据加载使用骨架屏Skeleton替代 loading spinner
  • [Phase 3] Sidebar 折叠模式 — 管理后台 Sidebar 支持折叠为图标模式,增大内容区宽度

3. 技术栈建议

3.1 现有技术栈(保留)

层级 技术选型 说明
前端框架 React 18 + TypeScript 函数组件 + Hooks
构建工具 Vite 5 极速 HMR原生 ESM
UI 组件库 @arco-design/web-react 字节跳动设计系统,即梦同款
状态管理 Zustand 轻量、TypeScript 友好
样式方案 CSS Modules + Arco Design Token 深色主题定制
图标 @arco-design/web-react/icon + 自定义 SVG 工具栏图标
文件处理 浏览器原生 File API 本地预览、缩略图生成

3.2 [Phase 2] 已有前端依赖(保留)

依赖 说明
react-router-dom v7 前端路由(登录页、注册页、管理页)
axios HTTP 请求库,支持拦截器实现 Token 自动附加和刷新

3.3 [Phase 3] 新增前端依赖

依赖 说明
echarts 图表库核心,用于折线图、柱状图、环形图等数据可视化
echarts-for-react ECharts 的 React 封装组件,声明式使用图表

组件优先级: 如果 Arco Design 内置了对应组件(如 Table、Modal、Skeleton、DatePicker优先使用 Arco 组件ECharts 仅用于复杂图表。

3.4 [Phase 2] 后端技术栈(保留)

层级 技术选型 说明
后端框架 Django 4.2+ (LTS) Python Web 框架
API 框架 Django REST Framework (DRF) RESTful API 开发
认证方案 djangorestframework-simplejwt JWT Token 签发与验证
数据库 MySQL 8.0(阿里云 RDS 云数据库,已提供连接信息
数据库驱动 mysqlclient Django 官方推荐的 MySQL 驱动
CORS django-cors-headers 跨域请求支持
后端管理 Django Admin 内置管理后台
部署 Gunicorn + Nginx 生产环境部署方案

后端代码目录: 所有后端代码放在项目根目录下的 backend/ 子目录中。

3.5 数据库连接配置(不变)

# backend/config/settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'video_auto',
        'USER': 'ai_video',
        'PASSWORD': 'JogNQdtrd3WY8CBCAiYfYEGx',
        'HOST': 'rm-7xv1uaw910558p1788o.mysql.rds.aliyuncs.com',
        'PORT': '3306',
        'OPTIONS': {
            'charset': 'utf8mb4',
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        },
    }
}

4. 页面列表

4.1 [已有] 视频生成页 (/)

整体布局:

┌─────────────────────────────────────────────┐
│  [Phase 3 修改] 顶部用户信息:              │
│  用户名 | 剩余: 345s/600s(日) | [个人中心] [退出]│
│                                             │
│           深色背景空白区域                     │
│           #0a0a0f                            │
│                                             │
│  ┌─────────────────────────────────────┐    │
│  │         InputBar (底部固定)           │    │
│  │  max-width: 900px, 居中              │    │
│  │  背景: #16161e                       │    │
│  │  边框: #2a2a38, 圆角: 20px           │    │
│  │                                     │    │
│  │  ┌──────┐ ┌──────────────────────┐  │    │
│  │  │上传区 │ │ 提示词文本输入框       │  │    │
│  │  │      │ │                      │  │    │
│  │  └──────┘ └──────────────────────┘  │    │
│  │                                     │    │
│  │  ─────────── 工具栏按钮行 ──────────  │    │
│  │  [视频生成▼][模型][模式▼][比例][时长]  │    │
│  │  [@]          flex空白    [发送⬆]    │    │
│  └─────────────────────────────────────┘    │
└─────────────────────────────────────────────┘
  • [Phase 3 修改] 顶部用户信息区的配额显示从「剩余 N 次」改为「剩余 N 秒」,增加「个人中心」链接
  • [Phase 2] 需要登录才能访问,未登录重定向到 /login

全能参考模式 — 上传区细节:

┌──────────┐
│    +     │  ← 初始状态: [+ 参考内容] 按钮
│ 参考内容  │     虚线边框,点击触发上传
└──────────┘

┌───┐┌───┐┌──────┐
│图1││图2││  +   │  ← 已上传状态: 缩略图网格 + 添加按钮
│ × ││ × ││      │     每张有序号标签和关闭按钮
└───┘└───┘└──────┘

首尾帧模式 — 上传区细节:

┌──────┐      ┌──────┐
│ 首帧  │  ↔  │+ 尾帧 │  ← 两个独立上传框
│      │      │      │     中间双向箭头
└──────┘      └──────┘

工具栏按钮排布:

全能参考模式:
[🎬 视频生成 ▼] [💎 Seedance 2.0] [✨ 全能参考 ▼] [🖥 21:9] [🕐 15s] [@]   ——flex空白——   [⬆ 发送]

首尾帧模式:
[🎬 视频生成 ▼] [💎 Seedance 2.0] [🔀 首尾帧 ▼] [自动匹配] [🕐 5s]   ——flex空白——   [⬆ 发送]

4.2 [已有] 登录页 (/login)

┌─────────────────────────────────────────────┐
│                                             │
│           深色背景 #0a0a0f                   │
│                                             │
│        ┌──────────────────────┐             │
│        │     Jimeng Clone     │             │
│        │                      │             │
│        │  用户名/邮箱: [____] │             │
│        │  密码:       [____]  │             │
│        │                      │             │
│        │    [ 登录 ]           │             │
│        │                      │             │
│        │  没有账号?去注册 →    │             │
│        └──────────────────────┘             │
│                                             │
└─────────────────────────────────────────────┘
  • 表单验证:用户名/邮箱必填,密码最少 6 位
  • 登录成功后跳转到 /(视频生成页)
  • 风格与主应用一致:深色主题,卡片式表单

4.3 [已有] 注册页 (/register)

┌─────────────────────────────────────────────┐
│                                             │
│           深色背景 #0a0a0f                   │
│                                             │
│        ┌──────────────────────┐             │
│        │     创建账号          │             │
│        │                      │             │
│        │  用户名:    [____]    │             │
│        │  邮箱:      [____]   │             │
│        │  密码:      [____]   │             │
│        │  确认密码:   [____]   │             │
│        │                      │             │
│        │    [ 注册 ]           │             │
│        │                      │             │
│        │  已有账号?去登录 →    │             │
│        └──────────────────────┘             │
│                                             │
└─────────────────────────────────────────────┘
  • 表单验证:用户名 3-20 位、邮箱格式校验、密码最少 6 位、两次密码一致
  • 注册成功后自动登录并跳转到 /

4.4 [Phase 3] 管理后台布局(/admin/*

┌──────────────────────────────────────────────────────────────┐
│  Jimeng Admin                               [管理员名] [退出] │
├────────────┬─────────────────────────────────────────────────┤
│            │                                                 │
│  SIDEBAR   │            CONTENT AREA                         │
│  240px     │            (根据子路由渲染不同页面)                │
│            │                                                 │
│  ┌──────┐  │                                                 │
│  │ 📊   │  │                                                 │
│  │仪表盘 │  │                                                 │
│  ├──────┤  │                                                 │
│  │ 👥   │  │                                                 │
│  │用户   │  │                                                 │
│  │管理   │  │                                                 │
│  ├──────┤  │                                                 │
│  │ 📋   │  │                                                 │
│  │消费   │  │                                                 │
│  │记录   │  │                                                 │
│  ├──────┤  │                                                 │
│  │ ⚙️   │  │                                                 │
│  │系统   │  │                                                 │
│  │设置   │  │                                                 │
│  └──────┘  │                                                 │
│            │                                                 │
│  ─────── │                                                 │
│  [返回首页] │                                                 │
│            │                                                 │
├────────────┴─────────────────────────────────────────────────┤
│  Jimeng Clone Admin v3.0                                     │
└──────────────────────────────────────────────────────────────┘

设计规范(管理后台专用):

  • 整体风格参考 Linear / Vercel Dashboard深色主题
  • 背景色 #0a0a0fSidebar 背景 #111118,内容区背景 #0a0a0f
  • Sidebar 当前项背景 rgba(255, 255, 255, 0.08),文字 #ffffff
  • 非当前项文字 #8a8a9ahover 背景 rgba(255, 255, 255, 0.04)
  • 卡片背景 #16161e,边框 1px solid #2a2a38,圆角 12px
  • 数据加载时显示 Arco Skeleton 骨架屏

4.5 [Phase 3] 仪表盘页面(/admin/dashboard

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  仪表盘                        [今日] [近7天] [近30天] [自定义]│
│                                                             │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐      │
│  │ 总用户数  │ │今日新增   │ │今日消费   │ │本月消费   │      │
│  │  1,234   │ │  +23     │ │ 4,560s   │ │ 89,010s  │      │
│  │  ↑12%    │ │  ↑15%    │ │  ↓5%     │ │  ↑8%     │      │
│  └──────────┘ └──────────┘ └──────────┘ └──────────┘      │
│                                                             │
│  ┌──────────────────────────────────────────────────────┐  │
│  │  消费趋势 (ECharts 折线图)                             │  │
│  │                                                      │  │
│  │  Y轴: 秒数    ___/\___                               │  │
│  │             /        \___/\                           │  │
│  │  ___/\___/                  \___                      │  │
│  │                                                      │  │
│  │  X轴: 日期 (3/1  3/5  3/10  3/15  3/20  3/25  3/30) │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                             │
│  ┌──────────────────────────────────────────────────────┐  │
│  │  用户消费排行 Top 10 (ECharts 水平柱状图)               │  │
│  │                                                      │  │
│  │  user_a  ████████████████████████  2,340s             │  │
│  │  user_b  ██████████████████  1,890s                   │  │
│  │  user_c  ████████████████  1,560s                     │  │
│  │  ...                                                  │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘
  • is_staff=True 的用户可访问
  • 统计卡片使用 Arco Card 组件 + 自定义样式
  • 折线图使用 ECharts line 类型,开启 tooltipdataZoom 交互
  • 柱状图使用 ECharts bar 类型,水平方向,标签显示用户名和秒数
  • 时间范围选择器使用 Arco DatePicker.RangePicker
  • 数据来源:GET /api/v1/admin/stats

4.6 [Phase 3] 用户管理页面(/admin/users

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  用户管理                                                    │
│                                                             │
│  [🔍 搜索用户名/邮箱___________]  [状态: 全部 ▼]  [刷新]    │
│                                                             │
│  ┌──────────────────────────────────────────────────────┐  │
│  │ 用户名    │ 邮箱          │ 注册时间  │ 状态  │ 日限额│  │
│  │          │              │          │      │ (秒) │  │
│  │ 月限额   │ 今日消费(秒)  │ 本月消费(秒)│ 操作         │  │
│  ├──────────┼──────────────┼──────────┼──────┼──────┤  │
│  │ user_a   │ a@test.com   │ 3/1      │ ✅   │ 600  │  │
│  │ 6000     │ 123          │ 2345     │[编辑][禁用]    │  │
│  ├──────────┼──────────────┼──────────┼──────┼──────┤  │
│  │ user_b   │ b@test.com   │ 3/5      │ ❌   │ 300  │  │
│  │ 3000     │ 0            │ 0        │[编辑][启用]    │  │
│  └──────────┴──────────────┴──────────┴──────┴──────┘  │
│                                                             │
│  共 56 条  [< 1 2 3 >]                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘
  • 使用 Arco Table 组件(分页、排序)
  • 搜索使用 Arco Input.Search
  • 状态筛选使用 Arco Select
  • 编辑配额使用 Arco Modal 弹窗
  • 用户详情使用 Arco Drawer 右侧抽屉
  • 数据来源:GET /api/v1/admin/users

4.7 [Phase 3] 消费记录页面(/admin/records

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  消费记录                                      [导出 CSV]    │
│                                                             │
│  [用户名搜索____]  [时间: 2026-03-01 ~ 2026-03-12]  [查询]  │
│                                                             │
│  ┌──────────────────────────────────────────────────────┐  │
│  │ 时间              │ 用户名  │ 消费秒数│ 视频描述     │  │
│  │                   │        │        │ (prompt截断) │  │
│  │ 模式    │ 状态                                       │  │
│  ├───────────────────┼────────┼────────┼─────────────┤  │
│  │ 3/12 14:30:00     │ user_a │ 15s    │ 一只猫在...  │  │
│  │ 全能参考 │ 已完成                                    │  │
│  ├───────────────────┼────────┼────────┼─────────────┤  │
│  │ 3/12 14:25:00     │ user_b │ 5s     │ 日落海边...  │  │
│  │ 首尾帧   │ 生成中                                    │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                             │
│  共 1,234 条  [< 1 2 3 ... 62 >]                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘
  • 使用 Arco Table 组件(分页)
  • 时间范围筛选使用 Arco DatePicker.RangePicker
  • 导出 CSV前端调用 API 获取全部数据并生成 CSV 文件下载
  • 数据来源:GET /api/v1/admin/records

4.8 [Phase 3] 系统设置页面(/admin/settings

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  系统设置                                                    │
│                                                             │
│  ┌──────────────────────────────────────────────────────┐  │
│  │  全局默认配额                                         │  │
│  │                                                      │  │
│  │  默认每日限额 (秒):  [____600____]                    │  │
│  │  默认每月限额 (秒):  [____6000___]                    │  │
│  │                                                      │  │
│  │  [保存配额设置]                                       │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                             │
│  ┌──────────────────────────────────────────────────────┐  │
│  │  系统公告                            [启用公告: ON]    │  │
│  │                                                      │  │
│  │  ┌──────────────────────────────────────────────┐    │  │
│  │  │                                              │    │  │
│  │  │  公告内容 (支持纯文本)                         │    │  │
│  │  │                                              │    │  │
│  │  └──────────────────────────────────────────────┘    │  │
│  │                                                      │  │
│  │  [保存公告]                                           │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘
  • 使用 Arco Form、InputNumber、Switch、Input.TextArea 组件
  • 保存后 showToast 提示「设置已保存」
  • 数据来源:GET/PUT /api/v1/admin/settings

4.9 [Phase 3] 用户个人中心(/profile

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  [← 返回首页]        个人中心              [用户名] [退出]    │
│                                                             │
│  ┌──────────────────────────────────────────────────────┐  │
│  │  消费概览                                             │  │
│  │                                                      │  │
│  │  ┌────────┐  ┌──────────────┐  ┌──────────────┐     │  │
│  │  │ (环形图)│  │ 今日额度      │  │ 本月额度      │     │  │
│  │  │        │  │              │  │              │     │  │
│  │  │ 已用   │  │ 已用: 123s   │  │ 已用: 2345s  │     │  │
│  │  │ 345s   │  │ 限额: 600s   │  │ 限额: 6000s  │     │  │
│  │  │ /600s  │  │ ████████░░░  │  │ ████░░░░░░░  │     │  │
│  │  │        │  │ 20.5%        │  │ 39.1%        │     │  │
│  │  └────────┘  └──────────────┘  └──────────────┘     │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                             │
│  ┌──────────────────────────────────────────────────────┐  │
│  │  消费趋势                           [近7天] [近30天]   │  │
│  │  ___/\___/\___  (Sparkline 迷你折线图)                │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                             │
│  ┌──────────────────────────────────────────────────────┐  │
│  │  消费记录                                             │  │
│  │                                                      │  │
│  │  3/12 14:30  │ 15s  │ 一只猫在花园... │ 全能参考 │ 完成│  │
│  │  3/12 14:25  │ 5s   │ 日落海边散步... │ 首尾帧   │ 完成│  │
│  │  3/12 13:00  │ 10s  │ 城市夜景延时... │ 全能参考 │ 失败│  │
│  │  ...                                                  │  │
│  │                                                      │  │
│  │  [加载更多]                                           │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘
  • 环形进度条使用 ECharts gauge 类型(半环或全环)
  • 进度条使用 Arco Progress 组件
  • 消费记录列表使用 Arco List 或 Table 组件,支持「加载更多」分页
  • Sparkline 迷你图使用 ECharts line 类型(无坐标轴,仅曲线)
  • 数据来源:GET /api/v1/profile/overview + GET /api/v1/profile/records
  • 深色主题风格与主应用一致

5. API 设计

5.1 [已有] 视频生成Phase 3 修改配额返回字段)

POST /api/v1/video/generate
Content-Type: multipart/form-data
Authorization: Bearer <access_token>

Request:
{
  "prompt": string,
  "mode": "universal" | "keyframe",
  "model": "seedance_2.0" | "seedance_2.0_fast",
  "aspect_ratio": "16:9" | "9:16" | "1:1" | "21:9" | "4:3" | "3:4" | "auto",
  "duration": 5 | 10 | 15,
  "references": File[],
  "first_frame": File | null,
  "last_frame": File | null
}

Response: 202 Accepted
{
  "task_id": "uuid",
  "status": "queued",
  "estimated_time": 120,
  "seconds_consumed": 15,              ← [Phase 3] 本次消耗秒数
  "remaining_seconds_today": 345       ← [Phase 3] 今日剩余秒数
}

Error Response: 429 Too Many Requests
{
  "error": "quota_exceeded",
  "message": "您今日的生成额度已用完",          ← [Phase 3] 改为秒数描述
  "daily_seconds_limit": 600,
  "daily_seconds_used": 600,
  "reset_at": "2026-03-13T00:00:00+08:00"
}

5.2 [已有] 文件上传(不变)

POST /api/v1/upload
Content-Type: multipart/form-data
Authorization: Bearer <access_token>

Request:
{
  "file": File,
  "type": "image" | "video"
}

Response: 200 OK
{
  "file_id": "uuid",
  "url": "https://cdn.example.com/...",
  "thumbnail_url": "https://cdn.example.com/.../thumb.jpg",
  "width": 1920,
  "height": 1080,
  "duration": 10.5
}

5.3 [已有] 用户注册(不变)

POST /api/v1/auth/register
Content-Type: application/json

Request:
{
  "username": "string (3-20字符)",
  "email": "string (合法邮箱)",
  "password": "string (最少6位)"
}

Response: 201 Created
{
  "user": {
    "id": 1,
    "username": "johndoe",
    "email": "john@example.com"
  },
  "tokens": {
    "access": "eyJ...",
    "refresh": "eyJ..."
  }
}

Error Response: 400 Bad Request
{
  "username": ["该用户名已被注册"],
  "email": ["该邮箱已被注册"]
}

5.4 [已有] 用户登录(不变)

POST /api/v1/auth/login
Content-Type: application/json

Request:
{
  "username": "string (用户名或邮箱)",
  "password": "string"
}

Response: 200 OK
{
  "user": {
    "id": 1,
    "username": "johndoe",
    "email": "john@example.com",
    "is_staff": false
  },
  "tokens": {
    "access": "eyJ...",
    "refresh": "eyJ..."
  }
}

Error Response: 401 Unauthorized
{
  "error": "invalid_credentials",
  "message": "用户名或密码错误"
}

5.5 [已有] Token 刷新(不变)

POST /api/v1/auth/token/refresh
Content-Type: application/json

Request:
{
  "refresh": "eyJ..."
}

Response: 200 OK
{
  "access": "eyJ..."
}

5.6 [已有] 获取当前用户信息Phase 3 修改配额字段)

GET /api/v1/auth/me
Authorization: Bearer <access_token>

Response: 200 OK
{
  "id": 1,
  "username": "johndoe",
  "email": "john@example.com",
  "is_staff": false,
  "quota": {
    "daily_seconds_limit": 600,          ← [Phase 3] 改为秒数
    "daily_seconds_used": 123,
    "monthly_seconds_limit": 6000,
    "monthly_seconds_used": 2345
  }
}

5.7 [Phase 3] 管理后台 — 仪表盘统计

GET /api/v1/admin/stats?period=30d
Authorization: Bearer <access_token>
(requires is_staff=True)

Query Parameters:
  period: "today" | "7d" | "30d" | "custom"
  start_date: "2026-03-01" (当 period=custom 时必填)
  end_date: "2026-03-12" (当 period=custom 时必填)

Response: 200 OK
{
  "total_users": 1234,
  "new_users_today": 23,
  "seconds_consumed_today": 4560,
  "seconds_consumed_this_month": 89010,
  "today_change_percent": -5.0,
  "month_change_percent": 8.0,
  "daily_trend": [
    {"date": "2026-02-11", "seconds": 3200},
    {"date": "2026-02-12", "seconds": 4100},
    ...
  ],
  "top_users": [
    {
      "user_id": 1,
      "username": "user_a",
      "seconds_consumed": 2340
    },
    ...
  ]
}

5.8 [Phase 3] 管理后台 — 用户列表

GET /api/v1/admin/users?page=1&page_size=20&search=&status=&sort_by=created_at&order=desc
Authorization: Bearer <access_token>
(requires is_staff=True)

Query Parameters:
  page: int (默认 1)
  page_size: int (默认 20最大 100)
  search: string (按用户名或邮箱模糊搜索)
  status: "active" | "disabled" | "" (空表示全部)
  sort_by: "created_at" | "seconds_today" | "seconds_month" (排序字段)
  order: "asc" | "desc"

Response: 200 OK
{
  "total": 56,
  "page": 1,
  "page_size": 20,
  "results": [
    {
      "id": 1,
      "username": "user_a",
      "email": "a@test.com",
      "is_active": true,
      "date_joined": "2026-03-01T10:00:00+08:00",
      "daily_seconds_limit": 600,
      "monthly_seconds_limit": 6000,
      "seconds_today": 123,
      "seconds_this_month": 2345
    },
    ...
  ]
}

5.9 [Phase 3] 管理后台 — 用户详情 + 消费记录

GET /api/v1/admin/users/:id
Authorization: Bearer <access_token>
(requires is_staff=True)

Response: 200 OK
{
  "id": 1,
  "username": "user_a",
  "email": "a@test.com",
  "is_active": true,
  "is_staff": false,
  "date_joined": "2026-03-01T10:00:00+08:00",
  "daily_seconds_limit": 600,
  "monthly_seconds_limit": 6000,
  "seconds_today": 123,
  "seconds_this_month": 2345,
  "seconds_total": 5678,
  "recent_records": [
    {
      "id": 101,
      "created_at": "2026-03-12T14:30:00+08:00",
      "seconds_consumed": 15,
      "prompt": "一只猫在花园里追蝴蝶",
      "mode": "universal",
      "model": "seedance_2.0",
      "status": "completed"
    },
    ...
  ]
}

5.10 [Phase 3] 管理后台 — 修改用户配额

PUT /api/v1/admin/users/:id/quota
Authorization: Bearer <access_token>
(requires is_staff=True)
Content-Type: application/json

Request:
{
  "daily_seconds_limit": 900,
  "monthly_seconds_limit": 9000
}

Response: 200 OK
{
  "user_id": 1,
  "username": "user_a",
  "daily_seconds_limit": 900,
  "monthly_seconds_limit": 9000,
  "updated_at": "2026-03-12T14:30:00+08:00"
}

5.11 [Phase 3] 管理后台 — 启用/禁用用户

PATCH /api/v1/admin/users/:id/status
Authorization: Bearer <access_token>
(requires is_staff=True)
Content-Type: application/json

Request:
{
  "is_active": false
}

Response: 200 OK
{
  "user_id": 1,
  "username": "user_a",
  "is_active": false,
  "updated_at": "2026-03-12T14:30:00+08:00"
}

5.12 [Phase 3] 管理后台 — 消费记录列表

GET /api/v1/admin/records?page=1&page_size=20&search=&start_date=&end_date=
Authorization: Bearer <access_token>
(requires is_staff=True)

Query Parameters:
  page: int (默认 1)
  page_size: int (默认 20最大 100)
  search: string (按用户名搜索)
  start_date: "2026-03-01" (起始日期)
  end_date: "2026-03-12" (结束日期)

Response: 200 OK
{
  "total": 1234,
  "page": 1,
  "page_size": 20,
  "results": [
    {
      "id": 101,
      "created_at": "2026-03-12T14:30:00+08:00",
      "user_id": 1,
      "username": "user_a",
      "seconds_consumed": 15,
      "prompt": "一只猫在花园里追蝴蝶",
      "mode": "universal",
      "model": "seedance_2.0",
      "aspect_ratio": "16:9",
      "status": "completed"
    },
    ...
  ]
}

5.13 [Phase 3] 管理后台 — 系统设置

GET /api/v1/admin/settings
Authorization: Bearer <access_token>
(requires is_staff=True)

Response: 200 OK
{
  "default_daily_seconds_limit": 600,
  "default_monthly_seconds_limit": 6000,
  "announcement": "系统将于今晚 22:00 进行维护",
  "announcement_enabled": true
}

PUT /api/v1/admin/settings
Authorization: Bearer <access_token>
(requires is_staff=True)
Content-Type: application/json

Request:
{
  "default_daily_seconds_limit": 600,
  "default_monthly_seconds_limit": 6000,
  "announcement": "系统将于今晚 22:00 进行维护",
  "announcement_enabled": true
}

Response: 200 OK
{
  "default_daily_seconds_limit": 600,
  "default_monthly_seconds_limit": 6000,
  "announcement": "系统将于今晚 22:00 进行维护",
  "announcement_enabled": true,
  "updated_at": "2026-03-12T14:30:00+08:00"
}

5.14 [Phase 3] 用户个人中心 — 消费概览

GET /api/v1/profile/overview?period=7d
Authorization: Bearer <access_token>

Query Parameters:
  period: "7d" | "30d" (趋势数据的时间范围)

Response: 200 OK
{
  "daily_seconds_limit": 600,
  "daily_seconds_used": 123,
  "monthly_seconds_limit": 6000,
  "monthly_seconds_used": 2345,
  "total_seconds_used": 5678,
  "daily_trend": [
    {"date": "2026-03-06", "seconds": 45},
    {"date": "2026-03-07", "seconds": 120},
    {"date": "2026-03-08", "seconds": 0},
    {"date": "2026-03-09", "seconds": 88},
    {"date": "2026-03-10", "seconds": 200},
    {"date": "2026-03-11", "seconds": 156},
    {"date": "2026-03-12", "seconds": 123}
  ]
}

5.15 [Phase 3] 用户个人中心 — 消费记录

GET /api/v1/profile/records?page=1&page_size=20
Authorization: Bearer <access_token>

Query Parameters:
  page: int (默认 1)
  page_size: int (默认 20)

Response: 200 OK
{
  "total": 45,
  "page": 1,
  "page_size": 20,
  "results": [
    {
      "id": 101,
      "created_at": "2026-03-12T14:30:00+08:00",
      "seconds_consumed": 15,
      "prompt": "一只猫在花园里追蝴蝶",
      "mode": "universal",
      "model": "seedance_2.0",
      "aspect_ratio": "16:9",
      "status": "completed"
    },
    ...
  ]
}

6. 数据模型

6.1 已有前端 Store 类型(保留)

// 创作模式
type CreationMode = 'universal' | 'keyframe';

// 模型选项
type ModelOption = 'seedance_2.0' | 'seedance_2.0_fast';

// 宽高比
type AspectRatio = '16:9' | '9:16' | '1:1' | '21:9' | '4:3' | '3:4';

// 时长
type Duration = 5 | 10 | 15;

// 上传文件
interface UploadedFile {
  id: string;
  file: File;
  type: 'image' | 'video';
  previewUrl: string;
  label: string;
}

// 输入栏状态 Store
interface InputBarStore {
  mode: CreationMode;
  setMode: (mode: CreationMode) => void;
  model: ModelOption;
  setModel: (model: ModelOption) => void;
  aspectRatio: AspectRatio;
  setAspectRatio: (ratio: AspectRatio) => void;
  duration: Duration;
  setDuration: (duration: Duration) => void;
  prompt: string;
  setPrompt: (prompt: string) => void;
  references: UploadedFile[];
  addReference: (file: File) => void;
  removeReference: (id: string) => void;
  clearReferences: () => void;
  firstFrame: UploadedFile | null;
  lastFrame: UploadedFile | null;
  setFirstFrame: (file: File | null) => void;
  setLastFrame: (file: File | null) => void;
  canSubmit: () => boolean;
  switchMode: (mode: CreationMode) => void;
  submit: () => void;
  reset: () => void;
}

6.2 已有下拉菜单配置(保留)

interface DropdownOption {
  label: string;
  value: string;
  icon?: string;
  disabled?: boolean;
}

const generationTypes: DropdownOption[] = [
  { label: '视频生成', value: 'video', icon: 'video' },
  { label: '图片生成', value: 'image', icon: 'image' },
];

const modelOptions: DropdownOption[] = [
  { label: 'Seedance 2.0', value: 'seedance_2.0', icon: 'diamond' },
  { label: 'Seedance 2.0 Fast', value: 'seedance_2.0_fast', icon: 'diamond' },
];

const modeOptions: DropdownOption[] = [
  { label: '全能参考', value: 'universal', icon: 'sparkle' },
  { label: '首尾帧', value: 'keyframe', icon: 'swap' },
];

const aspectRatioOptions: DropdownOption[] = [
  { label: '16:9', value: '16:9' },
  { label: '9:16', value: '9:16' },
  { label: '1:1', value: '1:1' },
  { label: '21:9', value: '21:9' },
  { label: '4:3', value: '4:3' },
  { label: '3:4', value: '3:4' },
];

const durationOptions: DropdownOption[] = [
  { label: '5s', value: '5' },
  { label: '10s', value: '10' },
  { label: '15s', value: '15' },
];

6.3 [Phase 2] 前端 Auth Store 类型Phase 3 修改配额字段)

interface User {
  id: number;
  username: string;
  email: string;
  is_staff: boolean;
}

// [Phase 3] 配额字段改为秒数
interface Quota {
  daily_seconds_limit: number;      // 原 daily_limit
  daily_seconds_used: number;       // 原 daily_used
  monthly_seconds_limit: number;    // 原 monthly_limit
  monthly_seconds_used: number;     // 原 monthly_used
}

interface AuthStore {
  // 状态
  user: User | null;
  accessToken: string | null;
  refreshToken: string | null;
  isAuthenticated: boolean;
  isLoading: boolean;

  // 操作
  login: (username: string, password: string) => Promise<void>;
  register: (username: string, email: string, password: string) => Promise<void>;
  logout: () => void;
  refreshAccessToken: () => Promise<void>;
  fetchUserInfo: () => Promise<void>;

  // 配额
  quota: Quota | null;
  fetchQuota: () => Promise<void>;
}

6.4 [Phase 3] 前端新增类型

// 管理后台统计数据
interface AdminStats {
  total_users: number;
  new_users_today: number;
  seconds_consumed_today: number;        // 原 calls_today
  seconds_consumed_this_month: number;   // 原 calls_this_month
  today_change_percent: number;
  month_change_percent: number;
  daily_trend: { date: string; seconds: number }[];
  top_users: { user_id: number; username: string; seconds_consumed: number }[];
}

// 管理后台用户列表项
interface AdminUser {
  id: number;
  username: string;
  email: string;
  is_active: boolean;
  date_joined: string;
  daily_seconds_limit: number;
  monthly_seconds_limit: number;
  seconds_today: number;
  seconds_this_month: number;
}

// 管理后台消费记录
interface AdminRecord {
  id: number;
  created_at: string;
  user_id: number;
  username: string;
  seconds_consumed: number;
  prompt: string;
  mode: CreationMode;
  model: ModelOption;
  aspect_ratio: string;
  status: 'queued' | 'processing' | 'completed' | 'failed';
}

// 系统设置
interface SystemSettings {
  default_daily_seconds_limit: number;
  default_monthly_seconds_limit: number;
  announcement: string;
  announcement_enabled: boolean;
}

// 用户个人中心概览
interface ProfileOverview {
  daily_seconds_limit: number;
  daily_seconds_used: number;
  monthly_seconds_limit: number;
  monthly_seconds_used: number;
  total_seconds_used: number;
  daily_trend: { date: string; seconds: number }[];
}

// 用户消费记录
interface ProfileRecord {
  id: number;
  created_at: string;
  seconds_consumed: number;
  prompt: string;
  mode: CreationMode;
  model: ModelOption;
  aspect_ratio: string;
  status: 'queued' | 'processing' | 'completed' | 'failed';
}

// 分页响应
interface PaginatedResponse<T> {
  total: number;
  page: number;
  page_size: number;
  results: T[];
}

6.5 后端数据模型Django Models

[Phase 2 → Phase 3 修改] 用户模型

# backend/apps/accounts/models.py

from django.contrib.auth.models import AbstractUser
from django.db import models

class User(AbstractUser):
    """扩展用户模型 — Phase 3: 配额单位改为秒数"""
    email = models.EmailField(unique=True, verbose_name='邮箱')
    # [Phase 3] 改为秒数限制
    daily_seconds_limit = models.IntegerField(default=600, verbose_name='每日秒数上限')
    monthly_seconds_limit = models.IntegerField(default=6000, verbose_name='每月秒数上限')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')

    class Meta:
        verbose_name = '用户'
        verbose_name_plural = '用户'

迁移说明: 需要创建 Django migration 将 daily_limitdaily_seconds_limitmonthly_limitmonthly_seconds_limit,并将现有数据按「原次数 × 15」换算为秒数假设平均每次生成 15 秒)。

[Phase 2 → Phase 3 修改] 生成记录模型

# backend/apps/generation/models.py

import uuid
from django.db import models
from django.conf import settings

class GenerationRecord(models.Model):
    """视频生成记录 — Phase 3: 新增消费秒数字段"""
    MODE_CHOICES = [
        ('universal', '全能参考'),
        ('keyframe', '首尾帧'),
    ]
    MODEL_CHOICES = [
        ('seedance_2.0', 'Seedance 2.0'),
        ('seedance_2.0_fast', 'Seedance 2.0 Fast'),
    ]
    STATUS_CHOICES = [
        ('queued', '排队中'),
        ('processing', '生成中'),
        ('completed', '已完成'),
        ('failed', '失败'),
    ]

    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='generation_records',
        verbose_name='用户'
    )
    task_id = models.UUIDField(default=uuid.uuid4, unique=True, verbose_name='任务ID')
    prompt = models.TextField(blank=True, verbose_name='提示词')
    mode = models.CharField(max_length=20, choices=MODE_CHOICES, verbose_name='创作模式')
    model = models.CharField(max_length=30, choices=MODEL_CHOICES, verbose_name='模型')
    aspect_ratio = models.CharField(max_length=10, verbose_name='宽高比')
    duration = models.IntegerField(verbose_name='视频时长(秒)')
    seconds_consumed = models.FloatField(default=0, verbose_name='消费秒数')   # [Phase 3] 新增
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='queued', verbose_name='状态')
    created_at = models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='创建时间')

    class Meta:
        verbose_name = '生成记录'
        verbose_name_plural = '生成记录'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['user', 'created_at']),
        ]

消费秒数逻辑: seconds_consumed = 视频 duration5/10/15秒在调用生成 API 时自动设置。

[Phase 2 → Phase 3 修改] 配额配置模型

# backend/apps/generation/models.py (续)

class QuotaConfig(models.Model):
    """全局配额配置 — Phase 3: 改为秒数"""
    default_daily_seconds_limit = models.IntegerField(default=600, verbose_name='默认每日秒数上限')
    default_monthly_seconds_limit = models.IntegerField(default=6000, verbose_name='默认每月秒数上限')
    announcement = models.TextField(blank=True, default='', verbose_name='系统公告')          # [Phase 3] 新增
    announcement_enabled = models.BooleanField(default=False, verbose_name='启用公告')  # [Phase 3] 新增
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = '系统配置'
        verbose_name_plural = '系统配置'

    def save(self, *args, **kwargs):
        # 单例模式,确保只有一条记录
        self.pk = 1
        super().save(*args, **kwargs)

7. 非功能需求

性能要求

  • 首屏加载 < 2sVite 构建,代码分割)
  • 文件上传后缩略图预览 < 200ms使用 URL.createObjectURL 本地生成)
  • 下拉菜单展开/收起动画 < 150ms
  • 文本输入无感知延迟(非受控组件或 debounce
  • [Phase 2] 后端 API 响应时间 < 500ms除文件上传外
  • [Phase 2] JWT Token 验证 < 50ms
  • [Phase 3] ECharts 图表渲染 < 300ms含数据加载
  • [Phase 3] 管理后台页面切换 < 200ms路由级代码分割
  • [Phase 3] 分页列表请求 < 300ms

安全要求

  • 文件上传仅限 image/* 和 video/* MIME 类型
  • 文件大小限制:图片 < 20MB视频 < 100MB
  • 使用 URL.createObjectURL 生成预览,组件卸载时调用 URL.revokeObjectURL 释放内存
  • [Phase 2] 密码使用 Django 默认的 PBKDF2 算法加密存储
  • [Phase 2] JWT Access Token 有效期 2 小时Refresh Token 有效期 7 天
  • [Phase 2] 数据库密码等敏感配置通过环境变量管理(生产环境),开发环境可硬编码在 settings 中
  • [Phase 2] API 接口对未认证请求返回 401对权限不足返回 403
  • [Phase 2] 管理接口仅 is_staff=True 用户可访问
  • [Phase 3] 管理后台操作(修改配额、禁用用户)需记录操作日志
  • [Phase 3] CSV 导出需要防止 CSV 注入攻击prompt 字段可能包含特殊字符)

响应式设计要求

  • 桌面端≥1024pxInputBar 最大宽度 900px 居中;管理后台 Sidebar 240px + 内容区自适应
  • 平板端768px-1023pxInputBar 宽度 90% 居中;管理后台 Sidebar 折叠为图标模式
  • 移动端(<768pxInputBar 宽度 95%,工具栏按钮文字隐藏仅显示图标;管理后台 Sidebar 隐藏,使用汉堡菜单

浏览器兼容

  • Chrome 90+、Firefox 90+、Safari 15+、Edge 90+

8. 验收标准

重要: Phase 1 和 Phase 2 功能已完成。当前验收范围为 Phase 3 全部功能。Phase 1/2 功能保持不变,不重复验收。

Phase 1 验收标准(已通过)

P0已全部通过

  1. 页面打开后显示深色全屏背景 #0a0a0f,底部居中显示 InputBar
  2. InputBar 样式与参考截图视觉一致:背景 #16161e、边框 #2a2a38、圆角 20px
  3. 默认处于「全能参考」模式,显示 [+ 参考内容] 上传按钮 + 提示词输入框
  4. 点击 [+ 参考内容] 可选择图片/视频文件,上传后显示带序号的缩略图
  5. 上传 1-5 张文件后缩略图正确显示,每个有 × 关闭按钮可删除
  6. 切换到「首尾帧」模式后,上传区变为首帧 ↔ 尾帧双框布局
  7. 工具栏所有按钮正确显示,布局与参考截图一致
  8. 发送按钮状态正确:无内容时灰色,有内容时蓝色 #00b8e6

P1已全部通过

  1. 「视频生成」下拉、「模型选择」下拉、「模式切换」下拉均可正常展开和选择
  2. 比例选择按钮点击弹出 6 个选项,选中后按钮文字更新
  3. 时长选择按钮点击弹出 3 个选项,选中后按钮文字更新
  4. 切换模式时联动正确:全能参考→首尾帧时比例变为「自动匹配」、时长变为 5s、隐藏 @ 按钮
  5. 文件上传支持拖拽

P2已全部通过

  1. 下拉菜单有动画过渡效果
  2. Ctrl/Cmd + Enter 可触发发送
  3. 页面加载后文本输入框自动聚焦
  4. 移动端下工具栏按钮自适应

Phase 2 验收标准(已通过)

P0已全部通过

  1. 未登录用户访问 / 自动跳转到 /login
  2. 注册页表单验证正确,注册成功后自动登录跳转到首页
  3. 登录页输入正确凭据后成功登录,获取 JWT Token
  4. 后端 Django 服务正常启动,能连接 MySQL 数据库
  5. 发送按钮点击后调用后端 API后端记录调用并返回剩余配额

P1已全部通过

  1. 管理员登录后可访问管理后台,普通用户无法访问
  2. 管理后台正确显示用户总数、调用统计等指标
  3. 管理员可修改用户的每日/每月调用限额
  4. 超出限额时前端显示友好提示,后端返回 429 状态码
  5. Django Admin 后台(/admin/)可管理用户和生成记录

Phase 3 验收标准(当前迭代)

P0必须全部通过

  1. 所有「调用次数」展示改为「生成秒数」—— UserInfoBar 显示「剩余 Ns/Ns(日)」而非「剩余 N 次」
  2. 后端 User 模型字段 daily_limit/monthly_limit 迁移为 daily_seconds_limit/monthly_seconds_limit
  3. GenerationRecord 模型新增 seconds_consumed 字段,生成 API 返回 seconds_consumedremaining_seconds_today
  4. 管理后台使用左侧 Sidebar + 右侧内容区布局Sidebar 包含 4 个导航项(仪表盘/用户管理/消费记录/系统设置)
  5. /admin/dashboard 仪表盘页面显示 4 个统计卡片(总用户、今日新增、今日消费秒数、本月消费秒数)+ ECharts 消费趋势折线图 + 用户消费排行柱状图
  6. /admin/users 用户管理页面支持分页列表、搜索筛选、编辑配额、启用/禁用用户
  7. /profile 用户个人中心显示消费概览(环形进度条)+ 消费记录列表

P1

  1. /admin/records 消费记录页面显示所有用户消费明细,支持时间范围筛选和导出 CSV
  2. /admin/settings 系统设置页面支持修改全局默认配额和管理系统公告
  3. 用户个人中心显示消费趋势 Sparkline 迷你图(近 7天/30天 切换)
  4. 仪表盘统计卡片显示环比变化百分比 + 趋势箭头
  5. 用户管理页面点击用户名展开详情抽屉,显示用户详情 + 近期消费记录
  6. 管理后台深色主题与 Linear/Vercel Dashboard 风格一致
  7. 数据加载使用骨架屏Skeleton

P2

  1. 管理后台 Sidebar 支持折叠为图标模式
  2. 页面切换有 fade/slide 过渡动画
  3. 当日额度消费超过 80% 时用户端显示黄色警告提示

9. 模式切换联动逻辑

切换动作 上传区 比例 时长 @ 按钮 Placeholder
→ 全能参考 [+ 参考内容] 多文件上传 恢复用户之前选择(默认 21:9 恢复用户之前选择(默认 15s 显示 "上传1-5张参考图或视频输入文字自由组合图、文、音、视频多元素定义精彩互动。"
→ 首尾帧 [首帧] ↔ [+ 尾帧] 自动匹配(灰色不可选) 5s可切换 隐藏 "输入描述,定义首帧到尾帧的运动过程"

注意: 切换模式时不清空已输入的提示词文本,但上传的文件会被清空(因为两种模式的上传逻辑不同)。

10. 设计规范Design Token

颜色

Token 用途
--color-bg-page #0a0a0f 页面背景
--color-bg-input-bar #16161e InputBar 背景
--color-border-input-bar #2a2a38 InputBar 边框
--color-primary #00b8e6 主强调色(发送按钮、视频生成文字)
--color-text-primary #ffffff 主文字
--color-text-secondary #8a8a9a 次文字工具栏按钮、placeholder
--color-text-disabled #4a4a5a 禁用文字
--color-bg-hover rgba(255, 255, 255, 0.06) 按钮 hover 背景
--color-bg-dropdown #1e1e2a 下拉菜单背景
--color-bg-upload rgba(255, 255, 255, 0.04) 上传区背景
--color-border-upload #2a2a38 上传区虚线边框
--color-btn-send-disabled #3a3a4a 发送按钮禁用状态
--color-btn-send-active #00b8e6 发送按钮激活状态

[Phase 3] 管理后台专用颜色

Token 用途
--color-bg-sidebar #111118 Sidebar 背景
--color-sidebar-active rgba(255, 255, 255, 0.08) Sidebar 当前项背景
--color-sidebar-hover rgba(255, 255, 255, 0.04) Sidebar hover 背景
--color-bg-card #16161e 卡片/面板背景
--color-border-card #2a2a38 卡片边框
--color-success #00b894 正向指标(↑绿色)
--color-danger #e74c3c 负向指标(↓红色) / 禁用状态
--color-warning #f39c12 警告提示(额度 80%+

圆角

Token 用途
--radius-input-bar 20px InputBar 容器
--radius-btn 8px 工具栏按钮
--radius-send-btn 50% 发送按钮(圆形)
--radius-thumbnail 8px 缩略图
--radius-dropdown 12px 下拉菜单
--radius-card 12px [Phase 3] 管理后台卡片

尺寸

Token 用途
--input-bar-max-width 900px InputBar 最大宽度
--send-btn-size 36px 发送按钮直径
--thumbnail-size 80px 上传缩略图尺寸
--toolbar-height 44px 工具栏行高
--toolbar-btn-height 32px 工具栏按钮高度
--sidebar-width 240px [Phase 3] Sidebar 宽度
--sidebar-collapsed-width 64px [Phase 3] Sidebar 折叠宽度

11. 组件树结构

App
├── AuthProvider                        // [Phase 2] 认证上下文
├── Router                              // [Phase 2] 路由
│   ├── /login → LoginPage              // [Phase 2] 登录页
│   ├── /register → RegisterPage        // [Phase 2] 注册页
│   ├── / → ProtectedRoute              // [Phase 2] 需要登录
│   │   └── VideoGenerationPage
│   │       ├── UserInfoBar             // [Phase 2] 顶部用户信息 + [Phase 3] 秒数配额 + 个人中心链接
│   │       ├── PageBackground
│   │       └── InputBar
│   │           ├── InputArea
│   │           │   ├── UploadSection
│   │           │   │   ├── UniversalUpload
│   │           │   │   │   ├── UploadButton
│   │           │   │   │   └── ThumbnailGrid
│   │           │   │   │       └── ThumbnailItem
│   │           │   │   └── KeyframeUpload
│   │           │   │       ├── FrameUpload
│   │           │   │       ├── ArrowIcon
│   │           │   │       └── FrameUpload
│   │           │   └── PromptInput
│   │           └── Toolbar
│   │               ├── GenerationTypeDropdown
│   │               ├── ModelSelector
│   │               ├── ModeDropdown
│   │               ├── AspectRatioSelector
│   │               ├── DurationSelector
│   │               ├── AtButton
│   │               ├── FlexSpacer
│   │               └── SendButton
│   ├── /profile → ProtectedRoute                    // [Phase 3] 用户个人中心
│   │   └── ProfilePage
│   │       ├── ProfileHeader                        // 返回首页 + 用户信息
│   │       ├── ConsumptionOverview                  // 消费概览卡片
│   │       │   ├── EChartsGauge                     // 环形进度条
│   │       │   ├── DailyQuotaCard                   // 今日额度进度条
│   │       │   └── MonthlyQuotaCard                 // 本月额度进度条
│   │       ├── ConsumptionTrend                     // Sparkline 迷你趋势图
│   │       └── ConsumptionRecordList                // 消费记录列表
│   ├── /admin → ProtectedRoute (requireAdmin)       // [Phase 3] 管理后台
│   │   └── AdminLayout                              // Sidebar + Content 布局
│   │       ├── AdminSidebar                         // 左侧导航栏
│   │       │   ├── SidebarLogo                      // Logo
│   │       │   ├── SidebarNav                       // 导航菜单
│   │       │   │   ├── NavItem (仪表盘)
│   │       │   │   ├── NavItem (用户管理)
│   │       │   │   ├── NavItem (消费记录)
│   │       │   │   └── NavItem (系统设置)
│   │       │   └── SidebarFooter                    // 返回首页链接
│   │       └── AdminContent                         // 右侧内容区 (Outlet)
│   │           ├── /admin/dashboard → DashboardPage
│   │           │   ├── StatsCards                   // 4 个指标卡片
│   │           │   ├── TrendLineChart               // ECharts 折线图
│   │           │   └── TopUsersBarChart             // ECharts 柱状图
│   │           ├── /admin/users → UsersPage
│   │           │   ├── UserSearchBar                // 搜索 + 筛选
│   │           │   ├── UserTable                    // Arco Table
│   │           │   ├── QuotaEditModal               // 配额编辑弹窗
│   │           │   └── UserDetailDrawer             // 用户详情抽屉
│   │           ├── /admin/records → RecordsPage
│   │           │   ├── RecordFilters                // 筛选条件
│   │           │   ├── RecordTable                  // Arco Table
│   │           │   └── ExportButton                 // 导出 CSV
│   │           └── /admin/settings → SettingsPage
│   │               ├── QuotaSettingsCard            // 全局配额表单
│   │               └── AnnouncementCard             // 公告管理
│   └── * → Navigate to /

12. 后端项目结构

backend/
├── manage.py
├── requirements.txt
├── config/                     # Django 项目配置
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   ├── wsgi.py
│   └── asgi.py
├── apps/
│   ├── accounts/               # 用户认证模块
│   │   ├── __init__.py
│   │   ├── models.py           # User 扩展模型 (Phase 3: 秒数字段)
│   │   ├── serializers.py      # 注册/登录序列化器
│   │   ├── views.py            # 注册/登录/Token刷新 API
│   │   ├── urls.py
│   │   └── admin.py            # 用户管理 Admin
│   └── generation/             # 视频生成模块
│       ├── __init__.py
│       ├── models.py           # GenerationRecord (Phase 3: +seconds_consumed) + QuotaConfig (Phase 3: +announcement)
│       ├── serializers.py      # [Phase 3] 新增管理后台 + 个人中心序列化器
│       ├── views.py            # [Phase 3] 新增管理后台 API (stats/users/records/settings) + 个人中心 API (overview/records)
│       ├── urls.py             # [Phase 3] 新增路由
│       ├── admin.py            # 生成记录 Admin
│       └── middleware.py       # 配额检查中间件 (Phase 3: 改为秒数检查)

13. 参考截图说明

参考截图存放于 /Users/maidong/Desktop/zyc/研究openclaw/视频生成平台/ 目录:

文件 内容描述
20260311-154443.jpeg 空状态全貌 — 完整展示了 InputBar 在无输入时的样式
20260311-154432.jpeg 已上传状态 — 展示了上传 1 张图片后的 InputBar
20260311-154407.jpeg 有内容状态 — 展示了输入完整提示词 + 多张图片引用后的 InputBar

14. 修订历史

日期 版本 变更内容
2026-03-11 v1.0 初始版本 — 纯前端视频生成输入界面
2026-03-12 v2.0 增量迭代 — 新增 Django 后端、用户认证系统、后台管理系统
2026-03-12 v2.1 需求修订BUG-002 — 引入开发阶段划分Phase 1 / Phase 2验收标准按阶段分组
2026-03-12 v2.2 需求修订BUG-002 后续) — Phase 2 功能已完成开发,更新阶段状态和验收范围
2026-03-12 v3.0 重大迭代 — Phase 3 — 计量单位从「调用次数」改为「生成秒数」;管理后台从单页面重做为多页面 Sidebar 布局(仪表盘/用户管理/消费记录/系统设置);新增用户个人中心(/profile含消费概览、环形进度条、消费趋势 Sparkline、消费记录列表引入 ECharts 图表库;管理后台深色主题升级(参考 Linear/Vercel 风格);新增骨架屏加载和页面过渡动画;新增 8 个 API 端点、修改 3 个已有 API 端点