# 前端工程 ## 技术栈 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 | 任务结果页,预览素材、下载 | ## 组件树 ``` # 工程风格编辑 # 历史任务列表 # sprite / background / UI / animation # 任务风格覆盖(基于工程风格,高亮差异) # 三段式提示词预览 & 编辑 # 分辨率、帧数等技术参数 # 提交后显示管线进度 # 素材预览 # 元数据展示 # 下载素材 ``` ## 核心交互流程 ### 生成流程 ``` 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; // kvPairs loading: boolean; loadStyle: (projectId: string) => Promise; updateStyle: (kvPairs: Record) => void; saveStyle: () => Promise; } ``` **task store** — 任务草稿 ```typescript interface TaskStore { prompt: string; assetType: 'sprite' | 'background' | 'ui' | 'animation'; taskStyle: Record; // 仅覆盖的键 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) => 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; 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):基于工程风格展示,高亮已覆盖的键,仅记录差异