# 小虾 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/*` | 管理后台(不变) | --- *本文档为规划阶段产出,待评审通过后进入实施阶段。*