397 lines
13 KiB
Markdown
397 lines
13 KiB
Markdown
# AirShelf 前端架构
|
||
|
||
> 适用目录:`core/frontend`。
|
||
> 最后核对:2026-07-18。
|
||
<!-- architecture-sync-commit: bfca22677cd0637b151c801fe53e68eb4ed8a6e3 -->
|
||
> 本文描述当前代码结构;系统级拓扑见 [core/ARCHITECTURE.md](../ARCHITECTURE.md)。
|
||
|
||
## 1. 定位
|
||
|
||
`core/frontend` 是 AirShelf 正式业务前端,是独立的 Vite + React + TypeScript 单页应用,不是 Next.js。
|
||
|
||
主要覆盖:
|
||
|
||
- 登录注册、团队和账户。
|
||
- 工作台、商品库、模特库、视频项目。
|
||
- 五阶段生产管线。
|
||
- 资产库和垃圾桶。
|
||
- 图片创作、模特上身图、平台套图。
|
||
- 自由视频创作。
|
||
- 通知、设置和平台超管后台。
|
||
|
||
设计稿位于 `public/exact`;正式业务页面位于 `src/routes`。设计稿用于视觉对照,不承载线上业务逻辑。
|
||
|
||
## 2. 技术栈
|
||
|
||
| 类别 | 当前实现 |
|
||
| --- | --- |
|
||
| UI 框架 | React 19 |
|
||
| 类型系统 | TypeScript strict |
|
||
| 构建工具 | Vite 7 |
|
||
| 图标 | Lucide React + 项目图标组件 |
|
||
| 路由 | 自研 History API 路由 |
|
||
| 状态 | React state/effect,未引入 Redux/Zustand |
|
||
| 请求 | 原生 fetch 的统一封装 |
|
||
| 请求缓存 | 无 TanStack Query 等统一缓存层 |
|
||
| 样式 | 全局 CSS、页面 CSS、共享设计系统 CSS |
|
||
| 部署 | 两阶段 Docker 构建 + Nginx |
|
||
|
||
## 3. 目录结构
|
||
|
||
```text
|
||
core/frontend/
|
||
├─ src/
|
||
│ ├─ main.tsx React 挂载和全局样式入口
|
||
│ ├─ App.tsx 应用总控制器
|
||
│ ├─ api.ts 用户侧和超管侧 API SDK
|
||
│ ├─ types.ts 前后端数据契约类型
|
||
│ ├─ generation-error.ts 生成错误展示语义
|
||
│ ├─ model-display.ts 模型展示辅助
|
||
│ ├─ routes/
|
||
│ │ ├─ route-config.ts 路由解析、路径生成、导航定义
|
||
│ │ ├─ stage-config.ts 五阶段顺序、状态和积分格式
|
||
│ │ ├─ auth-screen.tsx 登录注册
|
||
│ │ ├─ dashboard.tsx 工作台
|
||
│ │ ├─ products.tsx 商品列表、商品详情、商品创建入口
|
||
│ │ ├─ models.tsx 模特库
|
||
│ │ ├─ projects.tsx 项目列表和项目创建向导
|
||
│ │ ├─ pipeline.tsx 五阶段生产管线
|
||
│ │ ├─ library.tsx 资产库
|
||
│ │ ├─ ai-tools.tsx 图片创作工作台
|
||
│ │ ├─ free-create.tsx 自由视频创作
|
||
│ │ ├─ account.tsx 账户和积分
|
||
│ │ ├─ team.tsx 团队成员和额度
|
||
│ │ ├─ messages.tsx 消息中心
|
||
│ │ ├─ settings.tsx 设置
|
||
│ │ ├─ trash.tsx 垃圾桶
|
||
│ │ └─ admin/ 平台超管后台
|
||
│ ├─ components/
|
||
│ │ ├─ app-shell.tsx 左侧导航、顶栏和应用外壳
|
||
│ │ ├─ overlays.tsx Modal、Drawer、Confirm、Lightbox
|
||
│ │ ├─ product-create-drawer.tsx
|
||
│ │ ├─ model-library.tsx 模特选择与模特库交互
|
||
│ │ ├─ pipeline-stage.tsx 管线阶段组件
|
||
│ │ ├─ pager.tsx 分页
|
||
│ │ ├─ loading.tsx 加载状态
|
||
│ │ ├─ review-badge.tsx 审核状态标记
|
||
│ │ ├─ use-view-mode.ts 网格/列表视图持久化
|
||
│ │ └─ free-create/ 自由创作子组件
|
||
│ ├─ design-restraint.css 共享 token 和组件样式
|
||
│ ├─ styles.css 全局布局和通用样式
|
||
│ └─ *-page.css 页面级样式
|
||
├─ public/
|
||
│ ├─ assets/ 字体、图标和静态素材
|
||
│ └─ exact/ HTML 设计稿基线与 mock 素材
|
||
├─ package.json
|
||
├─ tsconfig.json
|
||
├─ vite.config.ts
|
||
├─ Dockerfile
|
||
└─ nginx.conf
|
||
```
|
||
|
||
## 4. 应用入口
|
||
|
||
### 4.1 `main.tsx`
|
||
|
||
`main.tsx` 负责:
|
||
|
||
- 创建 React Root。
|
||
- 挂载 `<App />`。
|
||
- 集中导入全局、设计系统和页面 CSS。
|
||
|
||
当前没有 CSS Modules。页面样式通过类名和统一导入生效,因此新增通用类时必须注意跨页面污染。
|
||
|
||
### 4.2 `App.tsx`
|
||
|
||
`App.tsx` 是当前应用总控制器,主要负责:
|
||
|
||
- 当前 URL 和认证模式。
|
||
- Token 启动恢复。
|
||
- User、Team、Role。
|
||
- 商品和项目列表及总数。
|
||
- 模型配置、积分摘要、通知未读数。
|
||
- 当前商品、当前项目和项目详情。
|
||
- 全局 loading、notice 和页面分发。
|
||
- 用户侧与平台超管侧入口守卫。
|
||
|
||
页面组件通过 props 获取全局数据和操作函数;页面自己的重数据、轮询和交互状态通常保留在页面内部。
|
||
|
||
`App.tsx` 已经承担较多职责。新增全局状态前,应先判断它是否真正跨页面共享,避免继续把页面局部状态上提。
|
||
|
||
## 5. 路由架构
|
||
|
||
前端没有使用 React Router。`routes/route-config.ts` 负责:
|
||
|
||
- 读取 `window.location.pathname`、query 和 hash。
|
||
- 将路径解析成内部 `Page`。
|
||
- 用 `history.pushState` / `replaceState` 切换地址。
|
||
- 处理浏览器前进和后退。
|
||
- 生成商品详情、项目管线等带参数路径。
|
||
- 提供导航项、页面标签和父级导航关系。
|
||
|
||
主要业务路径:
|
||
|
||
```text
|
||
/dashboard
|
||
/products
|
||
/products/new
|
||
/products/:id
|
||
/models
|
||
/projects
|
||
/projects/new
|
||
/pipeline
|
||
/pipeline/:id
|
||
/library
|
||
/account
|
||
/team
|
||
/messages
|
||
/asset-factory
|
||
/free-create
|
||
/image-optimize
|
||
/model-photo
|
||
/platform-cover
|
||
/settings
|
||
/trash
|
||
/admin/*
|
||
```
|
||
|
||
Nginx 对未知前端路径执行 `try_files ... /index.html`,因此刷新 SPA 路径时仍由同一前端入口解析。
|
||
|
||
## 6. API 层
|
||
|
||
`src/api.ts` 是统一 API SDK:
|
||
|
||
- 使用 `VITE_API_BASE_URL`;为空时调用同源 `/api`。
|
||
- 自动读取登录 Token。
|
||
- 自动添加 `Authorization: Token ...`。
|
||
- JSON 请求自动添加 content type。
|
||
- FormData 请求跳过 JSON header,让浏览器生成 multipart boundary。
|
||
- 将 DRF 的 `detail`、字段错误和常见权限错误转换成可读消息。
|
||
- 将用户侧接口收敛到 `api`。
|
||
- 将平台超管接口收敛到 `adminApi`。
|
||
|
||
页面不应自行复制 Token、基础 URL 和错误解析逻辑。新接口优先加入 `api.ts` 并在 `types.ts` 声明返回类型。
|
||
|
||
当前没有统一请求缓存层。数据刷新、轮询、请求去重和乐观更新主要由各页面自行处理。
|
||
|
||
## 7. 登录、存储与权限
|
||
|
||
### 7.1 Token
|
||
|
||
- 勾选“记住我”时:Token 和用户名信息写入 `localStorage`,有效期七天。
|
||
- 不勾选时:Token 写入 `sessionStorage`,关闭浏览器会话后失效。
|
||
- 过期后清除 Token 和记住信息,并要求重新登录。
|
||
|
||
### 7.2 权限
|
||
|
||
- owner 才能访问团队和账户级页面。
|
||
- `is_platform_admin` 决定是否可以访问 `/admin`。
|
||
- 普通用户访问超管路由会回到用户侧工作台。
|
||
- 无团队的平台超管登录后进入超管后台。
|
||
|
||
前端守卫只负责体验,后端仍必须执行真实权限校验和团队数据隔离。
|
||
|
||
### 7.3 其他本地状态
|
||
|
||
项目还使用本地存储保存部分体验状态,例如:
|
||
|
||
- 侧栏折叠。
|
||
- 网格/列表视图。
|
||
- 图片工作台模型和临时状态。
|
||
- 管线场景草稿。
|
||
- 待重试删除队列。
|
||
- 部分聊天或进度恢复信息。
|
||
|
||
本地状态不能替代后端事实。需要跨浏览器、跨成员或长期保存的数据必须进入后端。
|
||
|
||
## 8. 页面模块
|
||
|
||
### 8.1 商品
|
||
|
||
`products.tsx` 当前同时导出:
|
||
|
||
- 商品列表页。
|
||
- 商品卡片。
|
||
- 上传创建商品页。
|
||
- 商品详情页。
|
||
|
||
商品页处理搜索、筛选、视图切换、创建、详情、商品图、关联项目和批量删除。
|
||
|
||
### 8.2 视频项目
|
||
|
||
`projects.tsx` 包含:
|
||
|
||
- `ProjectsPage`:项目列表、状态筛选、时间筛选和删除。
|
||
- `ProjectWizardPage`:选择或创建商品、填写项目参数并创建项目。
|
||
|
||
项目创建后进入 `/pipeline/:id`。
|
||
|
||
### 8.3 生产管线
|
||
|
||
`pipeline.tsx` 是核心业务页面,覆盖:
|
||
|
||
- 脚本 Agent 流式生成和改稿。
|
||
- 脚本段编辑和实体引用。
|
||
- 人物、场景、商品基础资产。
|
||
- 三视图、审核和版本采用。
|
||
- 故事板镜头和候选版本。
|
||
- 视频片段生成和轮询。
|
||
- 配音、BGM、字幕、时间线和导出。
|
||
- 本地草稿、删除重试和刷新恢复。
|
||
|
||
五阶段顺序由 `stage-config.ts` 定义:
|
||
|
||
```text
|
||
script → base_assets → storyboard → video → export
|
||
```
|
||
|
||
该文件是当前前端最大复杂度中心。后续拆分应按阶段、领域状态和副作用边界进行,不能只按 JSX 长度机械拆组件。
|
||
|
||
### 8.4 图片创作
|
||
|
||
`ai-tools.tsx` 覆盖:
|
||
|
||
- 图片创作。
|
||
- 模特上身图。
|
||
- 平台套图。
|
||
- 商品关联。
|
||
- 模型选择。
|
||
- 图片会话、批次、历史结果和任务中心。
|
||
- 删除、恢复、收藏等任务操作。
|
||
|
||
生成结果通过 `batch_id`、会话和任务关系归组。页面需要同时处理提交、后端恢复、轮询和用户操作,是第二个主要复杂度中心。
|
||
|
||
### 8.5 自由视频创作
|
||
|
||
`free-create.tsx` 支持:
|
||
|
||
- 图片、视频和音频参考素材。
|
||
- 首尾帧等模式约束。
|
||
- 模型、比例、分辨率、时长和 seed。
|
||
- 上传、任务提交、重新生成和下载。
|
||
- 分页/继续加载。
|
||
- 渐进轮询和平滑进度展示。
|
||
- 全屏视频详情。
|
||
|
||
前端显示的平滑进度是体验层估计,任务终态必须以后端返回为准。
|
||
|
||
### 8.6 资产库与垃圾桶
|
||
|
||
`library.tsx` 聚合可复用和成品资产;`trash.tsx` 展示已删除的图片会话、任务或资产批次,并调用后端执行恢复或最终删除。
|
||
|
||
垃圾桶展示必须与后端软删除语义一致,不能仅靠前端数组过滤模拟删除。
|
||
|
||
### 8.7 平台超管后台
|
||
|
||
`routes/admin/admin-app.tsx` 提供独立后台壳,子页面覆盖:
|
||
|
||
- 邀请码。
|
||
- 团队和用户。
|
||
- 提示词和质量词。
|
||
- 资产审核。
|
||
- AI 任务监控。
|
||
- 模型供应商和模型配置。
|
||
- 积分流水、计费配置和额度策略。
|
||
- 项目治理和完整性检查。
|
||
|
||
后台使用 `adminApi`,并依赖后端的平台超管权限校验。
|
||
|
||
## 9. AI 慢任务交互
|
||
|
||
前端面对多种执行方式:
|
||
|
||
- 脚本 Agent:SSE 流式事件。
|
||
- 生图和视频:创建任务后轮询。
|
||
- 自由视频:渐进轮询并恢复页面进度。
|
||
- 导出:轮询 ExportJob。
|
||
- 审核:调用项目/后台审核状态接口。
|
||
|
||
轮询实现需要满足:
|
||
|
||
- 页面卸载后清理 timer。
|
||
- 同一任务避免重复启动多个 timer。
|
||
- 终态及时停止。
|
||
- 网络错误采用退避或可控重试。
|
||
- 刷新后可从后端任务恢复。
|
||
- 失败时显示后端标准化的用户错误。
|
||
- 不使用前端进度推断扣费是否成功。
|
||
|
||
## 10. 样式与设计稿关系
|
||
|
||
### 10.1 正式样式
|
||
|
||
- `design-restraint.css`:共享设计 token 和基础组件。
|
||
- `styles.css`:应用全局结构与通用样式。
|
||
- `*-page.css`:页面级布局和状态。
|
||
|
||
设计相关修改必须遵守仓库 `AGENTS.md` 和 `电商AI平台/design.md`,优先复用共享类和 token。
|
||
|
||
### 10.2 `public/exact`
|
||
|
||
`public/exact` 保留原始 HTML、视觉规范、mock 数据和静态素材,用于像素级对照。它不是第二套业务前端,也不应接入真实 API。
|
||
|
||
## 11. 构建与部署
|
||
|
||
### 11.1 本地
|
||
|
||
```bash
|
||
npm install
|
||
npm run dev
|
||
```
|
||
|
||
Vite 开发环境根据配置将 API 请求转发到本地 Django。
|
||
|
||
### 11.2 构建
|
||
|
||
```bash
|
||
npm run build
|
||
```
|
||
|
||
构建先执行 TypeScript 校验,再由 Vite 生成 `dist`。
|
||
|
||
### 11.3 容器
|
||
|
||
Docker 第一阶段使用 Node 构建,第二阶段使用 Nginx 托管产物。生产默认同源调用 `/api`,避免额外 CORS 配置。
|
||
|
||
Nginx 还负责:
|
||
|
||
- `/api/` 反代 Django。
|
||
- `/django-admin/` 和 `/static/` 反代 Django。
|
||
- 静态 assets 长缓存。
|
||
- `index.html` 禁止长期缓存。
|
||
- SPA 路由回落。
|
||
|
||
## 12. 当前风险与演进原则
|
||
|
||
### 12.1 超大页面
|
||
|
||
`pipeline.tsx`、`ai-tools.tsx` 和 `App.tsx` 同时承担状态、副作用和渲染,维护成本较高。拆分优先级:
|
||
|
||
1. 提取独立领域 hook。
|
||
2. 提取任务轮询和恢复逻辑。
|
||
3. 提取阶段或工作台容器。
|
||
4. 最后拆纯展示组件。
|
||
|
||
### 12.2 无统一服务端状态层
|
||
|
||
当前未使用 TanStack Query 等库。是否引入应以重复请求、缓存一致性和轮询复杂度为依据,不应只为了技术栈完整度引入。
|
||
|
||
### 12.3 全局 CSS
|
||
|
||
页面 CSS 全局生效。新增类名应使用清晰的页面或组件前缀;共享类只在设计系统文件维护,避免页面覆盖造成回归。
|
||
|
||
### 12.4 前后端类型漂移
|
||
|
||
`types.ts` 是手写契约,后端没有 OpenAPI 自动生成。接口字段变化时必须同步 serializer、`api.ts`、`types.ts` 和调用页面。
|
||
|
||
## 13. 文档同步规则
|
||
|
||
出现以下变化时必须更新本文:
|
||
|
||
- 一级目录、页面路由或核心组件重命名。
|
||
- `App.tsx` 全局状态边界变化。
|
||
- API SDK、Token 保存或权限守卫变化。
|
||
- 五阶段流程和慢任务交互变化。
|
||
- 图片会话、任务归组、垃圾桶或恢复逻辑变化。
|
||
- CSS 组织、构建或 Nginx 部署变化。
|