Files
xiaoxia-saas/docs/前端页面重构改造计划.md
Audit Bot e62a5d5e39
CI/CD Pipeline / Validate Code Quality And Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
Deploy / Deploy Staging (push) Has been cancelled
Deploy / Build Production Runtime Images (push) Has been cancelled
Deploy / Deploy Production (push) Has been cancelled
Deploy / Production Browser E2E (push) Has been cancelled
docs: 添加前端页面重构改造计划文档
- 分析现有项目制路由结构和页面文件
- 设计扁平化新路由(去掉 Workspace/Project 层级)
- 列出页面改造/删除/新增清单
- API 路由变更映射(前后端对照)
- 移动端响应式策略
- 实施计划与风险评估

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-28 14:18:41 +08:00

507 lines
21 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 小虾 SaaS 前端页面重构改造计划
> 版本:v1.0 | 日期:2026-06-28 | 作者:前端编码
> 状态:规划阶段,暂未改动代码
---
## 一、背景与目标
### 1.1 背景
产品从「项目制」改为「扁平化」结构,去掉 Workspace(工作空间)和 Project(项目)两层嵌套。用户不再需要「先选工作空间 → 再选项目 → 再进入功能页」,而是直接面对各功能模块。
### 1.2 目标
- 去除 Workspace / Project 层级,所有资源归用户直接所有
- 页面路由扁平化,一级路由直达各功能
- 保留并适配现有功能:素材库、标题库、配音库、模板库、一键生成、生成记录、成品库、订阅管理
- 兼顾移动端响应式体验
---
## 二、现有代码结构分析
### 2.1 当前路由结构
```
/ → 重定向到 /projects
/login → 登录
/register → 注册
/forgot-password → 忘记密码
/reset-password → 重置密码
/projects → 工作空间/项目列表(WorkspaceList
/projects/:id/assets → 项目素材库(ProjectAssets
/projects/:id/titles → 项目标题库(ProjectTitles
/projects/:id/voices → 项目配音库(ProjectVoices
/projects/:id/generation → 项目视频剪辑(ProjectGeneration
/projects/:id/tasks → 项目任务列表(ProjectTasks
/projects/:id/results → 项目成片库(ProjectResults
/subscription → 订阅套餐(Plans)
/subscription/upgrade → 升级订阅(UpgradeSubscription
/subscription/billing → 账单管理(Billing
/admin → 管理后台(AdminComingSoon
/admin/users → 用户管理
/admin/analytics → 数据分析
/admin/monitor → 监控面板
/admin/logs → 日志查看
/profile → 个人设置(Settings
```
### 2.2 当前页面文件清单
| 文件路径 | 行数 | 功能 | 改造命运 |
|---------|------|------|---------|
| `pages/workspace/WorkspaceList.tsx` | 99 | 项目列表 + 工作空间选择 | **删除** |
| `pages/workspace/ProjectAssets.tsx` | 93 | 项目内素材管理 | **改造** → 全局素材库 |
| `pages/workspace/ProjectTitles.tsx` | 110 | 项目内标题管理 | **改造** → 全局标题库 |
| `pages/workspace/ProjectVoices.tsx` | 52 | 项目内配音管理 | **改造** → 全局配音库 |
| `pages/workspace/ProjectGeneration.tsx` | 423 | 项目内视频生成(核心页面) | **改造** → 一键生成 |
| `pages/workspace/ProjectTasks.tsx` | 131 | 项目内任务列表 | **改造** → 生成记录 |
| `pages/workspace/ProjectResults.tsx` | 51 | 项目内成片展示 | **改造** → 成品库 |
| `pages/subscription/Plans.tsx` | — | 订阅套餐 | **保留** |
| `pages/subscription/UpgradeSubscription.tsx` | — | 升级订阅 | **保留** |
| `pages/subscription/Billing.tsx` | — | 账单管理 | **保留** |
| `pages/admin/AdminComingSoon.tsx` | — | 管理后台占位 | **保留** |
| `pages/auth/Login.tsx` | — | 登录 | **保留** |
| `pages/auth/Register.tsx` | — | 注册 | **保留** |
| `pages/auth/ForgotPassword.tsx` | — | 忘记密码 | **保留** |
| `pages/auth/ResetPassword.tsx` | — | 重置密码 | **保留** |
| `pages/profile/Settings.tsx` | — | 个人设置 | **保留** |
### 2.3 当前 API 层分析
| API 文件 | 接口前缀 | 改造影响 |
|---------|---------|---------|
| `api/workspace.ts` | `/workspaces` | **删除** — 不再需要工作空间 CRUD |
| `api/assets.ts` | `/projects/:id/...`, `/asset-libraries`, `/assets`, `/upload` | **改造** — 去掉 `project_id` 参数 |
| `api/editPlans.ts` | `/projects/:id/edit-plans/...` | **改造** — 去掉 `projectId` 前缀 |
| `api/tasks.ts` | `/projects/:id/tasks`, `/tasks/:type/:id/retry` | **改造** — 去掉 `projectId` |
| `api/auth.ts` | `/auth/...` | **不变** |
| `api/client.ts` | Axios 实例 | **不变** |
### 2.4 关键组件与 Hook
| 文件 | 功能 | 改造命运 |
|------|------|---------|
| `components/layout/MainLayout.tsx` | 布局壳(Outlet | **保留**,微调 |
| `components/layout/Header.tsx` | 顶部导航,动态渲染项目子导航 | **改造** — 去掉 projectId 逻辑,改为固定一级导航 |
| `hooks/useWorkspace.ts` | 工作空间状态管理 | **删除** |
| `hooks/useAuth.ts` | 认证状态管理 | **保留** |
| `store/authStore.ts` | 认证 Zustand store | **保留** |
---
## 三、新路由结构设计
### 3.1 新路由表
```
/ → 重定向到 /assets(首页即素材库)
/login → 登录(不变)
/register → 注册(不变)
/forgot-password → 忘记密码(不变)
/reset-password → 重置密码(不变)
# ── 以下均在 MainLayout (ProtectedRoute) 内 ──
/assets → 素材库
/titles → 标题库
/voices → 配音库
/templates → 模板库(新增)
/generate → 一键生成
/history → 生成记录
/products → 成品库
/subscription → 订阅套餐(不变)
/subscription/upgrade → 升级订阅(不变)
/subscription/billing → 账单管理(不变)
/admin → 管理后台(不变)
/admin/users → 用户管理(不变)
/admin/analytics → 数据分析(不变)
/admin/monitor → 监控面板(不变)
/admin/logs → 日志查看(不变)
/profile → 个人设置(不变)
```
### 3.2 路由设计说明
| 新路由 | 对应旧路由 | 说明 |
|--------|-----------|------|
| `/assets` | `/projects/:id/assets` | 去掉 projectId,展示用户所有素材 |
| `/titles` | `/projects/:id/titles` | 去掉 projectId,展示用户所有标题 |
| `/voices` | `/projects/:id/voices` | 去掉 projectId,展示用户所有配音 |
| `/templates` | 无(新增) | 模板库,从 ProjectGeneration 的模板选择部分独立出来 |
| `/generate` | `/projects/:id/generation` | 去掉 projectId,一键生成入口 |
| `/history` | `/projects/:id/tasks` | 去掉 projectId,展示用户所有生成任务 |
| `/products` | `/projects/:id/results` | 去掉 projectId,展示用户所有成品 |
| `/subscription` | `/subscription` | 不变 |
| `/profile` | `/profile` | 不变 |
| `/admin/*` | `/admin/*` | 不变 |
### 3.3 默认首页
首页 `/` 重定向到 `/assets`(素材库),因为素材是视频制作流程的起点,用户最常访问。
---
## 四、页面改造详细方案
### 4.1 删除页面(1 个)
#### WorkspaceList.tsx → 删除
- 原因:不再有工作空间/项目概念
- 相关功能(如「创建项目」)迁移到素材库页面的「上传素材」流程中
### 4.2 改造页面(6 个)
#### ProjectAssets.tsx → `pages/assets/AssetLibrary.tsx`
- **重命名** + 移动到 `pages/assets/` 目录
- **去除** `projectId` 参数和路由依赖
- **改造** API 调用:`getAssetLibraries(projectId)``getAssetLibraries()`(后端需配合去掉 project_id
- 页面内「新建素材库」表单去掉 project_id 字段
- 上传流程简化:直接上传到用户空间,不再需要先选项目再选素材库
#### ProjectTitles.tsx → `pages/titles/TitleLibrary.tsx`
- **重命名** + 移动到 `pages/titles/` 目录
- **去除** projectId 相关逻辑
- API 调用适配(后端需提供无 projectId 的标题列表接口)
#### ProjectVoices.tsx → `pages/voices/VoiceLibrary.tsx`
- **重命名** + 移动到 `pages/voices/` 目录
- **去除** projectId 相关逻辑
- API 调用适配
#### ProjectGeneration.tsx → `pages/generate/GeneratePage.tsx`
- **重命名** + 移动到 `pages/generate/` 目录
- 这是最复杂的页面(423 行),包含:
- 模板选择 → 部分拆到 `/templates` 模板库
- 素材库选择 → 改为全局素材库下拉
- 标题选择 → 改为全局标题库下拉
- 配音选择 → 改为全局配音库下拉
- 编排计划生成/编辑 → 保留,去掉 projectId
- 生成任务提交 → 保留,去掉 projectId
- **拆分**:模板浏览部分独立为 `pages/templates/TemplateLibrary.tsx`
#### ProjectTasks.tsx → `pages/history/TaskHistory.tsx`
- **重命名** + 移动到 `pages/history/` 目录
- **去除** projectId 过滤
- 展示用户所有生成任务(后端需支持按 user_id 查询)
#### ProjectResults.tsx → `pages/products/ProductLibrary.tsx`
- **重命名** + 移动到 `pages/products/` 目录
- **去除** projectId 过滤
- 展示用户所有成品视频
### 4.3 新增页面(1 个)
#### `pages/templates/TemplateLibrary.tsx`(新增)
- 模板库,展示所有可用编辑模板
- 功能从 ProjectGeneration.tsx 的模板选择部分抽取
- 支持模板预览、收藏、按类型筛选
- API:需后端提供 `/templates` 全局模板列表接口
### 4.4 保留不变的页面(11 个)
| 页面 | 说明 |
|------|------|
| `pages/auth/Login.tsx` | 登录 |
| `pages/auth/Register.tsx` | 注册 |
| `pages/auth/ForgotPassword.tsx` | 忘记密码 |
| `pages/auth/ResetPassword.tsx` | 重置密码 |
| `pages/subscription/Plans.tsx` | 订阅套餐 |
| `pages/subscription/UpgradeSubscription.tsx` | 升级订阅 |
| `pages/subscription/Billing.tsx` | 账单管理 |
| `pages/admin/AdminComingSoon.tsx` | 管理后台占位 |
| `pages/profile/Settings.tsx` | 个人设置 |
---
## 五、组件与 Hook 改造
### 5.1 Header.tsx 改造
**现状**Header 通过 `extractProjectId(pathname)` 解析 URL 中的 projectId,动态渲染项目子导航。
**改造方案**
- 删除 `extractProjectId` 函数
- 导航项改为固定一级菜单:
```tsx
const navItems = [
{ key: 'assets', label: '素材库', path: '/assets' },
{ key: 'titles', label: '标题库', path: '/titles' },
{ key: 'voices', label: '配音库', path: '/voices' },
{ key: 'templates', label: '模板库', path: '/templates' },
{ key: 'generate', label: '一键生成', path: '/generate' },
{ key: 'history', label: '生成记录', path: '/history' },
{ key: 'products', label: '成品库', path: '/products' },
{ key: 'subscription', label: '订阅', path: '/subscription' },
];
```
- 移动端下导航收起为汉堡菜单(Drawer)
### 5.2 删除 Hook
- `hooks/useWorkspace.ts` — 删除,不再需要工作空间状态
### 5.3 删除 API 文件
- `api/workspace.ts` — 删除,不再需要工作空间 CRUD API
### 5.4 改造 API 文件
#### `api/assets.ts`
```diff
- export const getAssetLibraries = async (projectId: string) => {
- const response = await apiClient.get('/asset-libraries', { params: { project_id: projectId } });
+ export const getAssetLibraries = async () => {
+ const response = await apiClient.get('/asset-libraries');
return response.data.items;
};
- export const createAssetLibrary = async (data: { project_id: string; name: string; kind: '...' }) => {
+ export const createAssetLibrary = async (data: { name: string; kind: '...' }) => {
...
};
- export const uploadAssetDirect = async (data: { file: File; project_id: string; library_id: string }) => {
+ export const uploadAssetDirect = async (data: { file: File; library_id: string }) => {
...
};
```
#### `api/editPlans.ts`
```diff
- export const getEditTemplates = async (projectId: string) => {
- const response = await apiClient.get(`/projects/${projectId}/edit-plans/templates`);
+ export const getEditTemplates = async () => {
+ const response = await apiClient.get('/templates');
return response.data;
};
- export const createEditPlan = async ({ projectId, data }) => {
- const response = await apiClient.post(`/projects/${projectId}/edit-plans`, data);
+ export const createEditPlan = async (data: { asset_library_id: string; template_id?: string; title_id?: string }) => {
+ const response = await apiClient.post('/edit-plans', data);
return response.data;
};
// 同理:getEditPlans, getEditPlan, autoGenerateEditPlan, deleteEditPlan, updateEditPlan
// 全部去掉 projectId 参数
```
#### `api/tasks.ts`
```diff
- export const getProjectTasks = async (projectId: string) => {
- const response = await apiClient.get(`/projects/${projectId}/tasks`);
+ export const getUserTasks = async () => {
+ const response = await apiClient.get('/tasks');
return response.data.items;
};
```
---
## 六、新目录结构
```
src/
├── api/
│ ├── assets.ts # 改造:去掉 project_id
│ ├── auth.ts # 不变
│ ├── client.ts # 不变
│ ├── editPlans.ts # 改造:去掉 projectId
│ ├── tasks.ts # 改造:去掉 projectId
│ └── templates.ts # 新增:模板 API
│ ✗ workspace.ts # 删除
├── components/
│ └── layout/
│ ├── Header.tsx # 改造:固定一级导航
│ └── MainLayout.tsx # 微调
├── hooks/
│ ├── useAuth.ts # 不变
│ ✗ useWorkspace.ts # 删除
├── pages/
│ ├── auth/ # 不变
│ ├── assets/ # 新增目录
│ │ └── AssetLibrary.tsx # 改造自 ProjectAssets
│ ├── titles/ # 新增目录
│ │ └── TitleLibrary.tsx # 改造自 ProjectTitles
│ ├── voices/ # 新增目录
│ │ └── VoiceLibrary.tsx # 改造自 ProjectVoices
│ ├── templates/ # 新增目录
│ │ └── TemplateLibrary.tsx # 新增
│ ├── generate/ # 新增目录
│ │ └── GeneratePage.tsx # 改造自 ProjectGeneration
│ ├── history/ # 新增目录
│ │ └── TaskHistory.tsx # 改造自 ProjectTasks
│ ├── products/ # 新增目录
│ │ └── ProductLibrary.tsx # 改造自 ProjectResults
│ ├── subscription/ # 不变
│ ├── admin/ # 不变
│ └── profile/ # 不变
├── store/
│ └── authStore.ts # 不变
├── router/
│ └── index.tsx # 改造:全新路由表
└── test/
└── ... # 更新测试用例
```
---
## 七、API 路由变更映射(前后端对照)
> 需后端同步改造,以下为建议的新 API 路由
| 旧 API | 新 API | 说明 |
|--------|--------|------|
| `GET /workspaces` | — | 删除 |
| `GET /workspaces/:id` | — | 删除 |
| `POST /workspaces` | — | 删除 |
| `GET /workspaces/:id/members` | — | 删除 |
| `POST /workspaces/:id/members/invite` | — | 删除 |
| `DELETE /workspaces/:id/members/:mid` | — | 删除 |
| `PATCH /workspaces/:id/members/:mid/role` | — | 删除 |
| `GET /asset-libraries?project_id=X` | `GET /asset-libraries` | 按当前用户查询 |
| `POST /asset-libraries {project_id,...}` | `POST /asset-libraries {name, kind}` | 去掉 project_id |
| `GET /assets?library_id=X` | `GET /assets?library_id=X` | 不变 |
| `POST /upload` | `POST /upload` | 不变 |
| `POST /upload/direct/prepare {project_id,...}` | `POST /upload/direct/prepare {library_id,...}` | 去掉 project_id |
| `POST /upload/direct/complete {project_id,...}` | `POST /upload/direct/complete {library_id,...}` | 去掉 project_id |
| `GET /projects/:id/asset-diagnosis` | `GET /asset-diagnosis` | 按当前用户查询 |
| `POST /classification-jobs {project_id,...}` | `POST /classification-jobs {asset_id}` | 去掉 project_id |
| `GET /projects/:id/edit-plans/templates` | `GET /templates` | 全局模板列表 |
| `GET /projects/:id/edit-plans` | `GET /edit-plans` | 按当前用户查询 |
| `POST /projects/:id/edit-plans` | `POST /edit-plans` | 去掉 projectId |
| `GET /projects/:id/edit-plans/:pid` | `GET /edit-plans/:pid` | 去掉 projectId |
| `POST /projects/:id/edit-plans/auto-generate` | `POST /edit-plans/auto-generate` | 去掉 projectId |
| `PATCH /projects/:id/edit-plans/:pid` | `PATCH /edit-plans/:pid` | 去掉 projectId |
| `DELETE /projects/:id/edit-plans/:pid` | `DELETE /edit-plans/:pid` | 去掉 projectId |
| `GET /projects/:id/tasks` | `GET /tasks` | 按当前用户查询 |
| `POST /tasks/:type/:id/retry` | `POST /tasks/:type/:id/retry` | 不变 |
---
## 八、移动端响应式策略
### 8.1 现状
- 当前使用 Ant Design v5,内置 Grid 系统和响应式工具
- Header 导航在移动端无适配(水平排列,小屏会溢出)
- 页面内容区基本为单列布局,移动端兼容性尚可
### 8.2 改造方案
#### 导航层
- **顶部导航**Header):
- 桌面端(≥768px):水平导航,全部菜单项平铺
- 移动端(<768px):隐藏导航文字,显示汉堡菜单图标,点击展开侧边 Drawer
- Logo 始终可见
- **底部 Tab 栏**(可选,Phase 2):
- 移动端增加底部固定 Tab 栏,包含 5 个核心入口:素材库、一键生成、生成记录、成品库、我的
- 使用 Ant Design `TabBar` 或自定义实现
#### 内容层
- **素材库**
- 桌面端:卡片网格(4 列),支持拖拽上传
- 移动端:单列卡片,底部固定「上传」按钮,调用手机相机/相册
- **标题库 / 配音库**
- 桌面端:表格视图
- 移动端:列表视图,卡片样式
- **一键生成**
- 桌面端:左右分栏(左侧配置,右侧预览)
- 移动端:步骤条(Steps)纵向流程,分步填写
- **生成记录 / 成品库**
- 桌面端:表格 + 视频预览弹窗
- 移动端:卡片列表 + 全屏视频播放器
- **订阅管理**
- 桌面端:套餐对比表格
- 移动端:卡片式套餐展示,纵向排列
#### 技术实现
- 使用 CSS 媒体查询 + Ant Design `useBreakpoint` Hook
- 关键断点:`xs: 480px`, `sm: 576px`, `md: 768px`, `lg: 992px`, `xl: 1200px`
- 图片/视频缩略图使用响应式 `srcset` 或统一使用较小尺寸 + CSS 缩放
- 上传组件使用 Ant Design `Upload.Dragger`(桌面)和自定义移动端上传按钮
### 8.3 分阶段实施
- **Phase 1**(本次重构):Header 响应式改造 + 页面基本移动端适配
- **Phase 2**(后续):底部 Tab 栏 + 移动端专属交互优化(手势、滑动等)
---
## 九、实施计划与优先级
### Phase 1:基础重构(本次核心工作)
| 序号 | 任务 | 涉及文件 | 预估工时 |
|------|------|---------|---------|
| 1 | 路由表重构 | `router/index.tsx` | 0.5h |
| 2 | Header 导航改造 | `Header.tsx` | 1h |
| 3 | 素材库页面改造 | `ProjectAssets``AssetLibrary` | 2h |
| 4 | 标题库页面改造 | `ProjectTitles``TitleLibrary` | 1h |
| 5 | 配音库页面改造 | `ProjectVoices``VoiceLibrary` | 1h |
| 6 | 一键生成页面改造 | `ProjectGeneration``GeneratePage` | 4h |
| 7 | 生成记录页面改造 | `ProjectTasks``TaskHistory` | 1h |
| 8 | 成品库页面改造 | `ProjectResults``ProductLibrary` | 1h |
| 9 | API 层改造 | `assets.ts`, `editPlans.ts`, `tasks.ts` | 2h |
| 10 | 删除废弃代码 | `workspace.ts`, `useWorkspace.ts`, `WorkspaceList.tsx` | 0.5h |
| 11 | 模板库页面新建 | `TemplateLibrary.tsx`, `templates.ts` | 2h |
| 12 | 更新测试用例 | `test/` 目录 | 2h |
**合计:约 18h**
### Phase 2:移动端优化(后续)
- 底部 Tab 栏
- 移动端上传优化
- 手势交互
### Phase 3:功能增强(后续)
- AI 配音集成
- 高级时间线编辑器
- 模板市场
---
## 十、风险与注意事项
### 10.1 前后端协同
- API 路由变更需要后端同步改造,建议前后端并行开发
- 过渡期可保留旧 API 兼容层(后端同时支持带/不带 projectId 的接口)
- 前端可通过 feature flag 切换新旧路由
### 10.2 数据迁移
- 后端需将现有 `project_id` 关联的数据迁移到 `user_id` 直接关联
- 素材、标题、配音、编辑计划、任务、成品均需迁移
- 建议后端提供迁移脚本,前端无需关心
### 10.3 向后兼容
- 旧路由 `/projects/:id/*` 设置 301 重定向到新路由(前端 `Navigate` 组件实现)
- 重定向逻辑保留 1-2 个版本后移除
### 10.4 测试覆盖
- 现有 `WorkspaceList.test.tsx` 需删除或重写
- 每个改造页面需更新对应的 E2E / 集成测试
- 路由跳转测试需全面更新
---
## 附录 A:新旧路由快速对照表
| 旧路由 | 新路由 | 页面 |
|--------|--------|------|
| `/projects` | `/assets` | 素材库(原项目列表→素材库首页) |
| `/projects/:id/assets` | `/assets` | 素材库 |
| `/projects/:id/titles` | `/titles` | 标题库 |
| `/projects/:id/voices` | `/voices` | 配音库 |
| `/projects/:id/generation` | `/generate` | 一键生成 |
| `/projects/:id/tasks` | `/history` | 生成记录 |
| `/projects/:id/results` | `/products` | 成品库 |
| — | `/templates` | 模板库(新增) |
| `/subscription` | `/subscription` | 订阅管理(不变) |
| `/profile` | `/profile` | 个人设置(不变) |
| `/admin/*` | `/admin/*` | 管理后台(不变) |
---
*本文档为规划阶段产出,待评审通过后进入实施阶段。*