# 产品需求文档 (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. **图表库引入**: 使用 ECharts（echarts + echarts-for-react）展示趋势图、排行榜、环形进度条
5. **设计升级**: 管理后台深色主题（Linear/Vercel 风格）、骨架屏加载、页面过渡动画

## 2. 功能需求

### 2.1 核心功能（P0）

#### 已有前端功能

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

#### [Phase 2] 用户认证系统

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

#### [Phase 2] Django 后端服务

- [x] **Django 项目初始化** — 在 `backend/` 子目录创建 Django 项目，连接 MySQL 云数据库
- [x] **RESTful API** — 使用 Django REST Framework (DRF) 提供用户认证、视频生成记录等 API
- [x] **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）

#### 已有前端功能

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

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

- [x] **Django Admin 集成** — 启用 Django Admin 面板（`/admin/`），管理员可查看和管理所有用户、视频生成记录
- [x] **发送按钮接入后端** — 点击发送按钮时，调用后端 `/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）

- [x] **下拉菜单动画** — 下拉展开/收起有 fade + slide 动画过渡
- [x] **文本输入框自动聚焦** — 页面加载后自动 focus 到文本输入框
- [x] **键盘快捷键** — `Ctrl/Cmd + Enter` 触发发送（等同点击发送按钮）
- [ ] **上传进度条** — 文件上传时缩略图上显示加载进度
- [ ] **拖拽排序** — 全能参考模式下已上传的缩略图支持拖拽调整顺序
- [x] **响应式适配** — 移动端窄屏下工具栏按钮文字隐藏只显示图标，输入栏宽度自适应
- [ ] **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 数据库连接配置（不变）

```python
# 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，深色主题
- 背景色 `#0a0a0f`，Sidebar 背景 `#111118`，内容区背景 `#0a0a0f`
- Sidebar 当前项背景 `rgba(255, 255, 255, 0.08)`，文字 `#ffffff`
- 非当前项文字 `#8a8a9a`，hover 背景 `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` 类型，开启 `tooltip`、`dataZoom` 交互
- 柱状图使用 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 类型（保留）

```typescript
// 创作模式
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 已有下拉菜单配置（保留）

```typescript
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 修改配额字段）

```typescript
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] 前端新增类型

```typescript
// 管理后台统计数据
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 修改] 用户模型

```python
# 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_limit` → `daily_seconds_limit`，`monthly_limit` → `monthly_seconds_limit`，并将现有数据按「原次数 × 15」换算为秒数（假设平均每次生成 15 秒）。

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

```python
# 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` = 视频 `duration`（5/10/15秒），在调用生成 API 时自动设置。

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

```python
# 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. 非功能需求

### 性能要求
- 首屏加载 < 2s（Vite 构建，代码分割）
- 文件上传后缩略图预览 < 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 字段可能包含特殊字符）

### 响应式设计要求
- 桌面端（≥1024px）：InputBar 最大宽度 900px 居中；管理后台 Sidebar 240px + 内容区自适应
- 平板端（768px-1023px）：InputBar 宽度 90% 居中；管理后台 Sidebar 折叠为图标模式
- 移动端（<768px）：InputBar 宽度 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（已全部通过）
9. 「视频生成」下拉、「模型选择」下拉、「模式切换」下拉均可正常展开和选择
10. 比例选择按钮点击弹出 6 个选项，选中后按钮文字更新
11. 时长选择按钮点击弹出 3 个选项，选中后按钮文字更新
12. 切换模式时联动正确：全能参考→首尾帧时比例变为「自动匹配」、时长变为 5s、隐藏 @ 按钮
13. 文件上传支持拖拽

#### P2（已全部通过）
14. 下拉菜单有动画过渡效果
15. `Ctrl/Cmd + Enter` 可触发发送
16. 页面加载后文本输入框自动聚焦
17. 移动端下工具栏按钮自适应

### Phase 2 验收标准（已通过）

#### P0（已全部通过）
18. 未登录用户访问 `/` 自动跳转到 `/login`
19. 注册页表单验证正确，注册成功后自动登录跳转到首页
20. 登录页输入正确凭据后成功登录，获取 JWT Token
21. 后端 Django 服务正常启动，能连接 MySQL 数据库
22. 发送按钮点击后调用后端 API，后端记录调用并返回剩余配额

#### P1（已全部通过）
23. 管理员登录后可访问管理后台，普通用户无法访问
24. 管理后台正确显示用户总数、调用统计等指标
25. 管理员可修改用户的每日/每月调用限额
26. 超出限额时前端显示友好提示，后端返回 429 状态码
27. Django Admin 后台（`/admin/`）可管理用户和生成记录

### Phase 3 验收标准（当前迭代）

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

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

#### P2
42. 管理后台 Sidebar 支持折叠为图标模式
43. 页面切换有 fade/slide 过渡动画
44. 当日额度消费超过 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 端点 |
