7.6 KiB
7.6 KiB
前端工程
技术栈
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 消息格式
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 — 工程风格
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 — 任务草稿
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 — 生成状态
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 两种使用场景:
- 工程风格(ProjectPage):全量编辑,保存到后端
- 任务覆盖(GeneratePage):基于工程风格展示,高亮已覆盖的键,仅记录差异