Files
gen2d/docs/frontend.md
T

209 lines
7.6 KiB
Markdown
Raw 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.
# 前端工程
## 技术栈
Vite 6 + React 18 + TypeScript + zustand + react-router-dom
| 类别 | 选型 | 说明 |
|------|------|------|
| 构建 | Vite 6 | 开发服务器端口 3000,`/api` 代理到 `localhost:8080` |
| UI 框架 | React 18 | 函数组件 + Hooks |
| 状态管理 | zustand | 轻量,支持 devtools 中间件 |
| 路由 | react-router-dom v6 | SPA 模式 |
| 实时通信 | 原生 WebSocket | 连接后端 `/api/v1/generate/:jobId/ws` |
| HTTP 请求 | fetch + 封装层 | 统一错误处理、响应解包 |
## 目录结构
```
frontend/src/
├── main.tsx # 入口
├── App.tsx # 根组件 + 路由配置
├── api/ # API 封装层
│ ├── client.ts # fetch 封装:baseURL、统一错误处理、响应解包
│ ├── generate.ts # POST /generate、GET /generate/:jobId、GET /generate/:jobId/result
│ ├── project.ts # GET/PUT /projects/:projectId/style
│ └── types.ts # API 请求/响应类型定义(Task、Asset、Style、JobStatus 等)
├── stores/ # zustand stores
│ ├── project.ts # 工程风格(从 API 加载 + 本地编辑 + 持久化回写)
│ ├── task.ts # 当前任务草稿(用户文本、素材类型、任务风格覆盖、技术参数)
│ └── generation.ts # 生成状态(jobId、进度、阶段、结果、错误)
├── pages/ # 页面级组件
│ ├── ProjectPage.tsx # 工程首页:工程风格配置 + 任务列表
│ ├── GeneratePage.tsx # 生成页:提示词构建 + 提交
│ └── ResultPage.tsx # 结果页:素材预览 + 下载 + 元数据
├── components/ # 可复用组件
│ ├── StyleSelector.tsx # 风格选择器
│ ├── PromptEditor.tsx # 三段式提示词编辑器
│ ├── GenerateForm.tsx # 生成表单
│ ├── ProgressBar.tsx # 管线进度条(显示当前阶段)
│ └── AssetPreview.tsx # 素材预览(spritesheet 预览、单帧预览)
├── hooks/ # 自定义 Hooks
│ ├── useGenerate.ts # 提交生成任务 + WebSocket 订阅进度
│ └── useProjectStyle.ts # 工程风格加载/保存
├── router/ # 路由定义
│ └── index.tsx
└── utils/ # 工具函数
└── style.ts # 风格合并逻辑(与后端保持一致的 merge 算法)
```
## 路由规划
| 路径 | 页面 | 说明 |
|------|------|------|
| `/` | — | 重定向到默认工程 |
| `/projects/:projectId` | ProjectPage | 工程首页,配置工程风格,查看历史任务 |
| `/projects/:projectId/generate` | GeneratePage | 提示词构建 + 提交生成 |
| `/projects/:projectId/tasks/:taskId` | ResultPage | 任务结果页,预览素材、下载 |
## 组件树
```
<App>
<Router>
<ProjectPage>
<StyleSelector /> # 工程风格编辑
<TaskList /> # 历史任务列表
</ProjectPage>
<GeneratePage>
<GenerateForm>
<AssetTypePicker /> # sprite / background / UI / animation
<StyleSelector /> # 任务风格覆盖(基于工程风格,高亮差异)
<PromptEditor /> # 三段式提示词预览 & 编辑
<ParamsForm /> # 分辨率、帧数等技术参数
</GenerateForm>
<ProgressBar /> # 提交后显示管线进度
</GeneratePage>
<ResultPage>
<AssetPreview /> # 素材预览
<MetadataPanel /> # 元数据展示
<DownloadButton /> # 下载素材
</ResultPage>
</Router>
</App>
```
## 核心交互流程
### 生成流程
```
1. 用户进入 GeneratePage
2. 填写文本描述(prompt)
3. 选择素材类型(sprite / background / UI / animation)
4. StyleSelector 展示工程风格,用户可点选覆盖(任务风格)
5. PromptEditor 实时预览三段式提示词:
- 【主题】从用户文本提取
- 【约束】从风格选择自动生成(含负面提示词)
- 【内容】从素材类型 + 技术参数生成
6. 用户确认后提交
7. 前端 POST /api/v1/generate → 获取 jobId
8. 建立 WebSocket 连接 /api/v1/generate/:jobId/ws
9. ProgressBar 实时显示管线阶段:PromptBuilder → AssetGenerator → QualitySupervisor → FormatAdapter
10. 管线完成后跳转 ResultPage
```
### WebSocket 消息格式
```typescript
interface PipelineProgress {
stage: 'prompt_builder' | 'asset_generator' | 'quality_supervisor' | 'format_adapter';
status: 'running' | 'completed' | 'failed';
progress: number; // 0-100
message?: string; // 阶段描述
result?: { // 仅在 format_adapter completed 时返回
assets: Asset[];
};
error?: string; // 仅在 failed 时返回
}
```
### 风格编辑流程
```
1. 用户进入 ProjectPage
2. StyleSelector 从 API 加载工程风格(GET /projects/:id/style)
3. 用户按分类点选风格键值对(美术风格、色调、线条、场景、光照、情绪)
4. 实时展示当前风格配置
5. 保存 → PUT /projects/:id/style
6. 工程风格持久化到后端,后续生成任务自动继承
```
## 状态管理
### zustand stores
**project store** — 工程风格
```typescript
interface ProjectStore {
projectId: string;
style: Record<string, string>; // kvPairs
loading: boolean;
loadStyle: (projectId: string) => Promise<void>;
updateStyle: (kvPairs: Record<string, string>) => void;
saveStyle: () => Promise<void>;
}
```
**task store** — 任务草稿
```typescript
interface TaskStore {
prompt: string;
assetType: 'sprite' | 'background' | 'ui' | 'animation';
taskStyle: Record<string, string>; // 仅覆盖的键
params: {
resolution: number;
frames?: { directions: number; framesPerDirection: number };
format: string;
};
setPrompt: (text: string) => void;
setAssetType: (type: string) => void;
toggleTaskStyle: (key: string, value: string) => void;
setParams: (params: Partial<TaskStore['params']>) => void;
reset: () => void;
}
```
**generation store** — 生成状态
```typescript
interface GenerationStore {
jobId: string | null;
stage: PipelineProgress['stage'] | null;
progress: number;
status: 'idle' | 'submitting' | 'running' | 'completed' | 'failed';
assets: Asset[];
error: string | null;
submit: (projectId: string, task: TaskStore) => Promise<void>;
reset: () => void;
}
```
## API 封装
`api/client.ts` 统一封装:
- baseURL 从环境变量读取,开发模式默认 `/api/v1`
- 所有响应按 `{ code, message, data }` 解包,`code !== 0` 时抛错
- 统一 401/403/500 错误处理
- WebSocket 连接封装为 `createJobSocket(jobId)` 返回可订阅对象
## 预设风格键分类
前端 StyleSelector 以分类标签组织,用户点选:
| 分类 | 键名 | 可选值 |
|------|------|--------|
| 美术风格 | `artStyle` | pixel, cartoon, hand-drawn, vector, flat |
| 色调 | `palette` | warm, cool, neutral, vibrant, muted, monochrome |
| 线条 | `lineWeight` | none, thin, medium, thick |
| 场景 | `scene` | forest, dungeon, city, space, underwater, desert |
| 光照 | `lighting` | bright, dim, dramatic, ambient, neon |
| 情绪 | `mood` | cheerful, dark, mysterious, epic, calm |
StyleSelector 两种使用场景:
1. **工程风格**(ProjectPage):全量编辑,保存到后端
2. **任务覆盖**(GeneratePage):基于工程风格展示,高亮已覆盖的键,仅记录差异