Files
gen2d/docs/frontend.md
T
wonder a603f5548c refactor: 前端重构为项目+任务双核心模型
- 新增 HomePage 项目画廊页,支持新建/删除工程
- 新增 ProjectDetailPage 三栏工作台(配置+生成+任务列表)
- 新增 CustomTagsEditor 支持自定义风格标签(custom: 前缀存入 kvPairs)
- 重构 project store 为 draft/commit 模式,支持手动保存/取消
- 新增 projectList store 管理工程列表
- 扩展 mock.ts 为多工程数据结构
- 扩展 api/project.ts 新增项目 CRUD API(mock-gated)
- 简化 ResultPage,仅展示素材预览
- 删除 GeneratePage、ProjectPage 及未使用的 hooks
- 更新 docs/ 文档(frontend.md、api.md、style-keys.md、_index.md)
2026-05-25 16:15:31 +08:00

12 KiB
Executable File
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 模式
实时通信 HTTP 轮询 每 1.5s 轮询任务状态(WebSocket 待后端实现)
HTTP 请求 fetch + 封装层 统一错误处理、响应解包

目录结构

frontend/src/
├── main.tsx                  # 入口
├── App.tsx                   # 根组件
├── api/                      # API 封装层
│   ├── client.ts             # fetch 封装:统一错误处理、响应解包(get/post/put/del)
│   ├── auth.ts               # 注册/登录(真实后端调用)
│   ├── project.ts            # 工程 CRUD + 风格 + 任务列表(mock 切换)
│   ├── generate.ts           # POST /generate、GET /tasks/:taskId、GET /tasks/:taskId/assets
│   ├── prompt.ts             # 提示词优化 + extractTags
│   ├── mock.ts               # 多工程 Mock 数据 + 模拟 WebSocket 管线进度
│   └── types.ts              # API 类型定义
├── stores/                   # zustand stores
│   ├── auth.ts               # 用户认证状态
│   ├── project.ts            # 当前工程详情(含 draft/commit 风格编辑)
│   ├── projectList.ts        # 工程列表(画廊页)
│   ├── task.ts               # 任务草稿(生成表单状态)
│   ├── generation.ts         # 生成状态(提交、轮询、结果)
│   ├── theme.ts              # 主题切换(light/dark)
│   └── toast.ts              # Toast 通知
├── pages/                    # 页面级组件
│   ├── LoginPage.tsx         # 登录页
│   ├── RegisterPage.tsx      # 注册页
│   ├── HomePage.tsx          # 项目画廊(工程列表 + 新建弹窗)
│   ├── ProjectDetailPage.tsx # 三栏工作台(配置 + 生成 + 任务列表)
│   └── ResultPage.tsx        # 结果页(素材预览 + 下载)
├── components/               # 可复用组件
│   ├── Layout.tsx            # 导航栏 + Outlet + ToastContainer
│   ├── StyleSelector.tsx     # 预设风格选择器(pill 按钮)
│   ├── CustomTagsEditor.tsx  # 自定义标签编辑器(可添加/删除)
│   ├── PromptEditor.tsx      # 三段式提示词编辑器
│   ├── GenerateForm.tsx      # 生成表单(素材类型 + 风格覆盖 + 提示词 + 参数)
│   ├── ProgressBar.tsx       # 管线进度条
│   ├── AssetPreview.tsx      # 素材预览
│   ├── ProjectCard.tsx       # 画廊卡片
│   ├── CreateProjectModal.tsx # 新建工程弹窗
│   ├── ProjectConfigPanel.tsx # 左栏:工程配置编辑面板
│   ├── TaskListPanel.tsx     # 右栏:任务列表面板
│   ├── StatusBadge.tsx       # 状态徽标组件
│   ├── EmptyState.tsx        # 空状态占位
│   ├── Skeleton.tsx          # 加载骨架屏
│   └── Toast.tsx             # Toast 通知容器
├── router/                   # 路由定义
│   └── index.tsx
├── styles/                   # 全局样式
│   └── global.css            # 暗色/亮色主题 CSS 变量 + reset
└── utils/                    # 工具函数
    └── style.ts              # 风格合并、预设分类、自定义标签工具

实现状态

模块 状态 说明
API 封装层 [x] client.ts 统一 fetch 封装,auth.ts 真实调用,project/generate 使用 mock
Mock 层 [x] mock.ts 提供多工程 mock 数据 + 模拟 WebSocket 管线进度
认证流程 [x] 注册/登录/退出/token 持久化,真实后端对接
zustand stores [x] auth/project/projectList/task/generation/theme/toast 七个 store
页面 [x] 5 个页面(Login/Register/Home/ProjectDetail/Result)
组件 [x] StyleSelector/CustomTagsEditor/PromptEditor/GenerateForm/ProgressBar/AssetPreview/ProjectCard/CreateProjectModal/ProjectConfigPanel/TaskListPanel/StatusBadge 等
路由 [x] 含 ProtectedRoute 守卫
自定义标签 [x] custom: 前缀存入 kvPairs,零后端改动

路由规划

路径 页面 说明
/ HomePage 项目画廊,展示所有工程
/projects/:projectId ProjectDetailPage 三栏工作台(配置 + 生成 + 任务列表)
/projects/:projectId/tasks/:taskId ResultPage 素材预览 + 下载

组件树

graph TD
    App --> Router
    Router --> HomePage
    Router --> ProjectDetailPage
    Router --> ResultPage

    HomePage --> ProjectCard["ProjectCard(工程卡片)"]
    HomePage --> CreateProjectModal["CreateProjectModal(新建弹窗)"]
    CreateProjectModal --> StyleSelector
    CreateProjectModal --> CustomTagsEditor

    ProjectDetailPage --> ProjectConfigPanel["ProjectConfigPanel(左栏配置)"]
    ProjectDetailPage --> GenerateForm["GenerateForm(中间上半)"]
    ProjectDetailPage --> ProgressBar["ProgressBar(中间下半)"]
    ProjectDetailPage --> TaskListPanel["TaskListPanel(右栏任务)"]

    ProjectConfigPanel --> StyleSelector2["StyleSelector"]
    ProjectConfigPanel --> CustomTagsEditor2["CustomTagsEditor"]
    TaskListPanel --> StatusBadge["StatusBadge"]

    GenerateForm --> PromptEditor["PromptEditor"]
    GenerateForm --> StyleSelector3["StyleSelector(任务覆盖)"]

    ResultPage --> AssetPreview["AssetPreview"]

三栏工作台布局

ProjectDetailPage 采用 CSS Grid 三栏布局:

grid-template-columns: 260px 1fr 320px
区域 宽度 内容
左栏 260px 工程名(可编辑)、预设风格选择器、自定义标签编辑器、保存/取消按钮
中间 flex-1 上半:生成表单;下半:当前任务进度条(提交后显示)
右栏 320px 任务列表(所有状态),15 秒自动刷新

核心交互流程

项目管理流程

sequenceDiagram
    actor User
    participant HP as HomePage
    participant API as 后端 API

    User->>HP: 进入首页
    HP->>API: GET /api/v1/projects
    API-->>HP: 工程列表
    HP->>HP: 画廊展示 ProjectCard

    User->>HP: 点击「新建工程」
    HP->>HP: 弹出 CreateProjectModal
    User->>HP: 输入名称、选择风格、添加自定义标签
    HP->>API: POST /api/v1/projects
    API-->>HP: 新工程
    HP->>HP: 跳转到 ProjectDetailPage

生成流程

sequenceDiagram
    actor User
    participant PDP as ProjectDetailPage
    participant API as 后端 API

    User->>PDP: 填写 prompt、选择素材类型
    User->>PDP: 点击提交
    PDP->>API: POST /api/v1/generate
    API-->>PDP: 返回 taskId
    PDP->>PDP: ProgressBar 显示进度

    loop 轮询任务状态(1.5s)
        PDP->>API: GET /api/v1/tasks/:taskId
        API-->>PDP: 任务状态 + 进度
        PDP->>PDP: 更新 ProgressBar
    end

    API-->>PDP: status = completed
    PDP->>API: GET /api/v1/tasks/:taskId/assets
    API-->>PDP: 素材列表
    PDP->>PDP: 显示「查看结果」按钮

风格编辑流程(手动保存)

sequenceDiagram
    actor User
    participant PCP as ProjectConfigPanel
    participant Store as project store
    participant API as 后端 API

    User->>PCP: 进入工程页
    PCP->>Store: startEditing() — 复制 style 到 draftStyle
    User->>PCP: 修改预设风格 / 添加自定义标签
    PCP->>Store: updateDraft(key, value) — 更新 draftStyle
    Store->>Store: hasUnsavedChanges = true

    alt 点击保存
        User->>PCP: 点击「保存」
        PCP->>Store: commitDraft()
        Store->>API: PUT /api/v1/projects/:id/style
        Store->>API: PUT /api/v1/projects/:id(如名称变更)
        Store->>Store: style = draftStyle, hasUnsavedChanges = false
    else 点击取消
        User->>PCP: 点击「取消」
        PCP->>Store: discardDraft()
        Store->>Store: draftStyle = style, hasUnsavedChanges = false
    end

自定义标签

在预设风格分类之外,用户可添加自定义标签。标签存储在工程风格的 kvPairs 中,使用 custom: 前缀区分:

{
  "artStyle": "pixel",
  "palette": "warm",
  "custom:cel-shading": "true",
  "custom:glow-effects": "true"
}

工具函数(utils/style.ts):

  • isCustomKey(key) — 判断是否为自定义标签
  • getCustomTags(style) — 提取自定义标签列表
  • addCustomTag(style, tag) — 添加标签
  • removeCustomTag(style, tag) — 删除标签

extractTags() 函数在提取标签时自动包含自定义标签值。

状态管理

zustand stores

projectList store — 工程列表(HomePage)

interface ProjectListState {
  projects: Project[];
  loading: boolean;
  loadProjects: () => Promise<void>;
  createProject: (name: string, style?: Record<string, string>) => Promise<Project>;
  deleteProject: (projectId: string) => Promise<void>;
}

project store — 当前工程详情(ProjectDetailPage)

interface ProjectState {
  projectId: string;
  name: string;
  style: Record<string, string>;
  draftStyle: Record<string, string>;
  draftName: string;
  hasUnsavedChanges: boolean;
  loading: boolean;
  loadProject: (projectId: string) => Promise<void>;
  loadStyle: (projectId: string) => Promise<void>;
  startEditing: () => void;
  updateDraft: (key: string, value: string) => void;
  setDraftStyle: (style: Record<string, string>) => void;
  setDraftName: (name: string) => void;
  discardDraft: () => void;
  commitDraft: () => Promise<void>;
}

task store — 任务草稿

interface TaskState {
  prompt: string;
  assetType: 'sprite' | 'background' | 'ui' | 'animation';
  taskStyle: Record<string, string>;
  params: TaskParams;
  enableAI: boolean;
  optimizedPrompt: string | null;
  // ... setters, runOptimize, reset
}

generation store — 生成状态

interface GenerationState {
  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: (req: GenerateRequest) => Promise<void>;
  reset: () => void;
}

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

interface Project {
  id: string;
  name: string;
  style: { kvPairs: Record<string, string> };
  createdAt: string;
  taskCount?: number;
  lastActivityAt?: string;
}

interface CreateProjectRequest {
  name: string;
  style?: Record<string, string>;
}

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

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

预设风格键分类

前端 StyleSelector 以分类标签组织,完整键值表见 预设风格键。

StyleSelector 两种使用场景:

  1. 工程风格(ProjectConfigPanel / CreateProjectModal):全量编辑,保存到后端
  2. 任务覆盖(GenerateForm):基于工程风格展示,仅记录差异