Files
gen2d/docs/api.md
T
wonder cba24349cb docs: 更新 API 与后端文档,对齐已实现功能
- api.md: 标记 register/login 接口为已完成(handler + User model)
- backend.md: 分层结构标注已有文件,与实际代码对齐
2026-05-24 13:34:44 +08:00

12 KiB
Raw Blame History

gen2d API 设计

所有接口统一前缀 /api/v1/,统一响应格式:

{ "code": 0, "message": "ok", "data": {} }

认证

除健康检查和注册登录外,所有接口需通过 httpOnly Cookie 携带 JWT。登录/注册成功后,服务端通过 Set-Cookie 响应头写入 Token,后续请求自动携带。

Cookie 属性:

  • Name: token
  • HttpOnly: true
  • SameSite: Lax
  • Path: /
  • MaxAge: 由 GEN2D_JWT_EXPIRE 控制(默认 7200 秒)

Token 过期或无效时返回:

{ "code": 401, "message": "未登录或 Token 已过期", "data": null }

权限不足时返回:

{ "code": 403, "message": "无权访问该资源", "data": null }

错误码

code 含义 场景
0 成功 —
400 请求参数错误 缺少必填字段、格式不合法
401 未认证 Token 缺失、过期、无效
403 无权访问 访问不属于自己的资源
404 资源不存在 工程/任务/素材 ID 不存在
409 冲突 用户名或邮箱已注册
429 请求过于频繁 触发速率限制
500 服务器内部错误 未预期异常

状态说明

  • 已完成
  • 规划中

基础设施

状态 方法 路径 说明
[x] GET /api/v1/health 健康检查

用户认证

状态 方法 路径 说明
[x] POST /api/v1/auth/register 用户注册
[x] POST /api/v1/auth/login 用户登录
[ ] GET /api/v1/auth/me 获取当前用户信息
[ ] PUT /api/v1/auth/password 修改密码

POST /api/v1/auth/register

{
  "username": "player1",
  "email": "player1@example.com",
  "password": "s3cretP@ss"
}
字段 类型 必填 说明
username string 是 3-64 字符,字母数字下划线
email string 是 邮箱地址
password string 是 8-128 字符

响应(Token 通过 Set-Cookie 响应头写入,不在 body 中返回):

{
  "code": 0,
  "message": "ok",
  "data": {
    "id": "user_a1B2c3D4",
    "username": "player1",
    "email": "player1@example.com"
  }
}

错误响应:

场景 code message
用户名格式不合法(非 3-64 字符或含特殊字符) 400 用户名格式不合法
密码长度不足 400 密码长度不能少于 8 位
邮箱格式不合法 400 邮箱格式不正确
用户名已存在 409 用户名已被注册
邮箱已存在 409 邮箱已被注册

POST /api/v1/auth/login

{
  "username": "player1",
  "password": "s3cretP@ss"
}

支持 username 或 email 登录:

{
  "email": "player1@example.com",
  "password": "s3cretP@ss"
}

响应(Token 通过 Set-Cookie 响应头写入,不在 body 中返回):

{
  "code": 0,
  "message": "ok",
  "data": {
    "id": "user_a1B2c3D4",
    "username": "player1",
    "email": "player1@example.com"
  }
}

GET /api/v1/auth/me

需认证。响应:

{
  "code": 0,
  "message": "ok",
  "data": {
    "id": "user_a1B2c3D4",
    "username": "player1",
    "email": "player1@example.com",
    "createdAt": "2026-05-24T10:00:00Z"
  }
}

PUT /api/v1/auth/password

需认证。

{
  "oldPassword": "s3cretP@ss",
  "newPassword": "n3wS3cretP@ss"
}

错误响应:

场景 code message
原密码错误 400 原密码不正确

工程管理

需认证。以下接口均需通过 Cookie 携带 Token,工程归属于当前登录用户。

状态 方法 路径 说明
[ ] GET /api/v1/projects 获取当前用户的工程列表
[ ] POST /api/v1/projects 创建工程
[ ] GET /api/v1/projects/:projectId 获取工程信息
[ ] DELETE /api/v1/projects/:projectId 删除工程(级联删除任务和素材)
[ ] GET /api/v1/projects/:projectId/tasks 获取工程下的任务列表

GET /api/v1/projects

获取当前用户的工程列表。

参数 类型 说明
page int 页码,默认 1
pageSize int 每页条数,默认 20

响应:

{
  "code": 0,
  "message": "ok",
  "data": {
    "total": 3,
    "projects": [
      {
        "id": "proj_abc123",
        "name": "我的像素游戏",
        "createdAt": "2026-05-24T10:00:00Z"
      }
    ]
  }
}

POST /api/v1/projects

{
  "name": "我的像素游戏"
}

响应:

{
  "code": 0,
  "message": "ok",
  "data": {
    "id": "proj_abc123",
    "name": "我的像素游戏",
    "style": { "kvPairs": {} },
    "createdAt": "2026-05-24T10:00:00Z"
  }
}

GET /api/v1/projects/:projectId

响应:

{
  "code": 0,
  "message": "ok",
  "data": {
    "id": "proj_abc123",
    "name": "我的像素游戏",
    "createdAt": "2026-05-24T10:00:00Z",
    "updatedAt": "2026-05-24T10:00:00Z"
  }
}

错误响应:

场景 code message
projectId 不存在 404 工程不存在
工程不属于当前用户 403 无权访问该工程

DELETE /api/v1/projects/:projectId

级联删除工程下的所有任务、素材及本地文件。

响应:

{
  "code": 0,
  "message": "ok",
  "data": null
}

GET /api/v1/projects/:projectId/tasks

参数 类型 说明
page int 页码,默认 1
pageSize int 每页条数,默认 20

响应:

{
  "code": 0,
  "message": "ok",
  "data": {
    "total": 42,
    "tasks": [
      {
        "id": "task_xyz789",
        "prompt": "一个拿剑的小人",
        "assetType": "sprite",
        "status": "completed",
        "createdAt": "2026-05-24T10:05:00Z"
      }
    ]
  }
}

工程风格

需认证。风格归属于工程,仅工程所属用户可操作。

状态 方法 路径 说明
[ ] GET /api/v1/projects/:projectId/style 获取工程风格
[ ] PUT /api/v1/projects/:projectId/style 更新工程风格

请求体示例 (PUT /api/v1/projects/:projectId/style):

{
  "kvPairs": {
    "artStyle": "pixel",
    "palette": "warm",
    "lineWeight": "thin",
    "lighting": "bright"
  }
}

素材生成

需认证。任务归属于当前用户的工程,跨用户访问返回 403。

状态 方法 路径 说明
[ ] POST /api/v1/generate 提交生成任务,返回 taskId
[ ] GET /api/v1/tasks/:taskId 查询任务状态与进度
[ ] GET /api/v1/tasks/:taskId/assets 获取生成结果(素材列表 + 元数据)
[ ] WS /api/v1/tasks/:taskId/ws WebSocket 实时进度推送

POST /api/v1/generate

请求体对应后端 PipelineInput:

{
  "projectId": "proj_abc123",
  "prompt": "一个拿剑的小人",
  "assetType": "sprite",
  "taskStyle": {
    "scene": "dungeon",
    "mood": "dark"
  },
  "params": {
    "resolution": 64,
    "frames": { "directions": 8, "framesPerDirection": 4 },
    "format": "spritesheet"
  }
}
字段 类型 必填 说明
projectId string 是 工程 ID,用于获取工程风格
prompt string 是 用户原始文本,后端 PromptBuilder 负责三段式重写
assetType string 是 素材类型:sprite / background / ui / animation
taskStyle object 否 任务级别风格覆盖(同名键覆盖工程风格)
params.resolution int 否 分辨率,默认 64
params.frames object 否 帧参数(仅 sprite/animation)
params.frames.directions int 否 方向数,默认 4
params.frames.framesPerDirection int 否 每方向帧数,默认 4
params.format string 否 输出格式:spritesheet / individual,默认 spritesheet

响应:

{
  "code": 0,
  "message": "ok",
  "data": {
    "taskId": "task_xyz789",
    "status": "pending"
  }
}

去重:相同 prompt + assetType + params 的并发请求返回已有 taskId,不重复创建任务。

错误响应:

场景 code message
projectId 不存在或不属于当前用户 403 无权访问该工程
prompt 为空 400 prompt 不能为空

GET /api/v1/tasks/:taskId

响应:

{
  "code": 0,
  "message": "ok",
  "data": {
    "taskId": "task_xyz789",
    "projectId": "proj_abc123",
    "prompt": "一个拿剑的小人",
    "assetType": "sprite",
    "taskStyle": null,
    "params": { "resolution": 64, "format": "spritesheet" },
    "status": "running",
    "stage": "asset_generator",
    "progress": 45,
    "retryCount": 0,
    "error": null,
    "createdAt": "2026-05-24T10:05:00Z",
    "updatedAt": "2026-05-24T10:05:30Z"
  }
}
字段 类型 说明
status string 任务状态:pending / running / completed / failed
stage string 当前管线阶段,running 时有值
progress int 0-100,整体进度
retryCount int 质检重试次数
error string 失败原因,仅 failed 时有值

状态机与管线阶段详见 异步任务。

错误响应:

场景 code message
taskId 不存在 404 任务不存在
任务不属于当前用户 403 无权访问该任务

GET /api/v1/tasks/:taskId/assets

任务状态为 completed 时返回素材列表,其他状态返回空数组。

{
  "code": 0,
  "message": "ok",
  "data": {
    "assets": [
      {
        "id": "asset_001",
        "url": "users/user_a1B2c3D4/projects/proj_abc123/tasks/task_xyz789/output/spritesheet.png",
        "format": "png",
        "width": 256,
        "height": 64,
        "metadata": {
          "frameWidth": 64,
          "frameHeight": 64,
          "frameCount": 4,
          "directions": 1
        }
      }
    ]
  }
}

WebSocket 消息格式

连接路径:ws://host/api/v1/tasks/:taskId/ws(通过 httpOnly Cookie 自动携带认证信息)

interface PipelineProgress {
  stage: 'prompt_builder' | 'asset_generator' | 'quality_supervisor' | 'format_adapter';
  status: 'running' | 'completed' | 'failed';
  progress: number;       // 0-100
  message?: string;       // 阶段描述
  retryCount?: number;    // 质检重试次数(仅 quality_supervisor 阶段)
  rejectReason?: string;  // 质检不通过原因(仅 quality_supervisor fail 时)
  result?: {              // 仅在 format_adapter completed 时返回
    assets: Asset[];
  };
  error?: string;         // 仅在 failed 时返回
}

消息示例(正常流程):

{"stage":"prompt_builder","status":"running","progress":0}
{"stage":"prompt_builder","status":"completed","progress":100}
{"stage":"asset_generator","status":"running","progress":0}
{"stage":"asset_generator","status":"completed","progress":100}
{"stage":"quality_supervisor","status":"running","progress":0}
{"stage":"quality_supervisor","status":"completed","progress":100}
{"stage":"format_adapter","status":"running","progress":0}
{"stage":"format_adapter","status":"completed","progress":100,"result":{"assets":[...]}}

消息示例(质检重试):

{"stage":"quality_supervisor","status":"running","progress":0}
{"stage":"quality_supervisor","status":"failed","progress":100,"retryCount":1,"rejectReason":"风格不一致"}
{"stage":"prompt_builder","status":"running","progress":0}
{"stage":"asset_generator","status":"running","progress":0}
{"stage":"quality_supervisor","status":"completed","progress":100}
{"stage":"format_adapter","status":"completed","progress":100,"result":{"assets":[...]}}