Files
gen2d/docs/frontend.md
T
wonder 172914c7f2 docs: 后端采用 Eino 框架编排管线,完善前后端文档对齐
- 后端管线从手写编排改为 Eino compose.Graph,含质检重试分支
- 移除 CORS 中间件
- api.md 补充工程管理接口、任务状态机、管线阶段、WebSocket 消息示例
- frontend.md 组件树和交互流程改用 mermaid 图,stores 对齐 PipelineInput/Output
- CLAUDE.md 修复死链,技术栈补充 Eino
2026-05-24 10:22:15 +08:00

9.3 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/tasks/:taskId/ws
HTTP 请求 fetch + 封装层 统一错误处理、响应解包

目录结构

frontend/src/
├── main.tsx                  # 入口
├── App.tsx                   # 根组件 + 路由配置
├── api/                      # API 封装层
│   ├── client.ts             # fetch 封装:baseURL、统一错误处理、响应解包
│   ├── project.ts            # 工程 CRUD + 风格 GET/PUT
│   ├── generate.ts           # POST /generate、GET /tasks/:taskId、GET /tasks/:taskId/assets
│   └── types.ts              # API 请求/响应类型定义(Task、Asset、Style、PipelineProgress 等)
├── stores/                   # zustand stores
│   ├── project.ts            # 当前工程(id、风格、任务列表)
│   ├── task.ts               # 当前任务草稿(用户文本、素材类型、任务风格覆盖、技术参数)
│   └── generation.ts         # 生成状态(taskId、进度、阶段、结果、错误)
├── 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 任务结果页,预览素材、下载

组件树

graph TD
    App --> Router
    Router --> ProjectPage
    Router --> GeneratePage
    Router --> ResultPage

    ProjectPage --> StyleSelector["StyleSelector(工程风格编辑)"]
    ProjectPage --> TaskList["TaskList(历史任务列表)"]

    GeneratePage --> GenerateForm
    GenerateForm --> AssetTypePicker["AssetTypePicker"]
    GenerateForm --> StyleSelector2["StyleSelector(任务风格覆盖)"]
    GenerateForm --> PromptEditor["PromptEditor(三段式预览)"]
    GenerateForm --> ParamsForm["ParamsForm(分辨率、帧数)"]
    GeneratePage --> ProgressBar["ProgressBar(管线进度)"]

    ResultPage --> AssetPreview["AssetPreview(素材预览)"]
    ResultPage --> MetadataPanel["MetadataPanel(元数据)"]
    ResultPage --> DownloadButton["DownloadButton"]

核心交互流程

生成流程

sequenceDiagram
    actor User
    participant GP as GeneratePage
    participant API as 后端 API
    participant WS as WebSocket

    User->>GP: 填写 prompt、选择素材类型
    User->>GP: StyleSelector 点选任务风格覆盖
    GP->>GP: PromptEditor 实时预览三段式提示词
    User->>GP: 点击提交
    GP->>API: POST /api/v1/generate
    API-->>GP: 返回 taskId
    GP->>WS: ws://host/api/v1/tasks/:taskId/ws
    loop 管线执行中
        WS-->>GP: PipelineProgress(stage + progress)
        GP->>GP: ProgressBar 更新阶段和进度
    end
    WS-->>GP: format_adapter completed + assets
    GP->>GP: 跳转 ResultPage

管线阶段对应 Eino Graph 节点,ProgressBar 展示:

阶段 说明 ProgressBar 展示
prompt_builder 合并风格,生成三段式提示词 第 1 步
asset_generator 调用 AI 推理 API 出图 第 2 步
quality_supervisor 视觉模型质检 第 3 步(可能回退到第 1 步)
format_adapter 格式转换、spritesheet 打包 第 4 步

质检重试时,ProgressBar 显示回退动画和重试次数。

风格编辑流程

sequenceDiagram
    actor User
    participant SP as StyleSelector
    participant API as 后端 API

    User->>SP: 进入 ProjectPage
    SP->>API: GET /api/v1/projects/:id/style
    API-->>SP: 返回 kvPairs
    SP->>SP: 按分类展示风格键值对
    User->>SP: 点选/修改风格
    SP->>SP: 实时展示当前配置
    User->>SP: 点击保存
    SP->>API: PUT /api/v1/projects/:id/style
    API-->>SP: 保存成功

状态管理

zustand stores

project store — 当前工程

interface ProjectStore {
  projectId: string;
  name: string;
  style: Record<string, string>;  // kvPairs
  loading: boolean;
  loadProject: (projectId: string) => Promise<void>;
  loadStyle: (projectId: string) => Promise<void>;
  updateStyle: (kvPairs: Record<string, string>) => void;
  saveStyle: () => Promise<void>;
}

task store — 任务草稿(对应后端 PipelineInput)

interface TaskStore {
  prompt: string;
  assetType: 'sprite' | 'background' | 'ui' | 'animation';
  taskStyle: Record<string, string>;  // 仅覆盖的键
  params: {
    resolution: number;
    frames?: { directions: number; framesPerDirection: number };
    format: 'spritesheet' | 'individual';
  };
  setPrompt: (text: string) => void;
  setAssetType: (type: TaskStore['assetType']) => void;
  toggleTaskStyle: (key: string, value: string) => void;
  setParams: (params: Partial<TaskStore['params']>) => void;
  reset: () => void;
}

generation store — 生成状态

interface GenerationStore {
  taskId: string | null;
  stage: PipelineStage | null;
  progress: number;
  status: 'idle' | 'submitting' | 'running' | 'completed' | 'failed';
  retryCount: number;
  rejectReason: string | null;
  assets: Asset[];
  error: string | null;
  submit: (projectId: string, task: TaskStore) => Promise<void>;
  reset: () => void;
}

type PipelineStage =
  | 'prompt_builder'
  | 'asset_generator'
  | 'quality_supervisor'
  | 'format_adapter';

API 封装

api/client.ts 统一封装:

  • baseURL 从环境变量读取,开发模式默认 /api/v1
  • 所有响应按 { code, message, data } 解包,code !== 0 时抛错
  • 统一 401/403/500 错误处理
  • WebSocket 连接封装为 createTaskSocket(taskId) 返回可订阅对象

API 类型定义(api/types.ts)

// 请求
interface CreateProjectRequest {
  name: string;
}

interface GenerateRequest {
  projectId: string;
  prompt: string;
  assetType: 'sprite' | 'background' | 'ui' | 'animation';
  taskStyle?: Record<string, string>;
  params?: {
    resolution?: number;
    frames?: { directions?: number; framesPerDirection?: number };
    format?: 'spritesheet' | 'individual';
  };
}

interface UpdateStyleRequest {
  kvPairs: Record<string, string>;
}

// 响应
interface Project {
  id: string;
  name: string;
  style: { kvPairs: Record<string, string> };
  createdAt: string;
}

interface Task {
  id: string;
  projectId: string;
  prompt: string;
  assetType: string;
  status: 'pending' | 'running' | 'completed' | 'failed';
  stage?: PipelineStage;
  progress?: number;
  retryCount?: number;
  createdAt: string;
  updatedAt: string;
}

interface Asset {
  id: string;
  url: string;
  format: string;
  width: number;
  height: number;
  metadata: {
    frameWidth?: number;
    frameHeight?: number;
    frameCount?: number;
    directions?: number;
  };
}

// WebSocket 消息
interface PipelineProgress {
  stage: PipelineStage;
  status: 'running' | 'completed' | 'failed';
  progress: number;
  message?: string;
  retryCount?: number;
  rejectReason?: string;
  result?: { assets: Asset[] };
  error?: string;
}

预设风格键分类

前端 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):基于工程风格展示,高亮已覆盖的键,仅记录差异