Files
gen2d/docs/frontend.md
T

7.6 KiB
Raw Blame History

前端工程

技术栈

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 两种使用场景:

  1. 工程风格(ProjectPage):全量编辑,保存到后端
  2. 任务覆盖(GeneratePage):基于工程风格展示,高亮已覆盖的键,仅记录差异