Feat/游戏场景需求v1.0 (#139)
Project CI / Repository checks (push) Has been cancelled
Project CI / Frontend tests (push) Has been cancelled
Project CI / Backend tests (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled

实现[游戏场景需求v1.0](https://kcnz41bksl1c.feishu.cn/wiki/JSF3wdhduinpqhkrVGKcZFp4nng?psg_id=8477599259997387860&refer_index=1&refer_type=citation)。

---------

Co-authored-by: 段舒康 <kdletters@qq.com>
Co-authored-by: suzmii <suzmii@foxmail.com>
Reviewed-on: http://192.168.35.82/git/GenarrativeAI/Genarrative/pulls/139
Co-authored-by: 董羽秦 <suzmii@qq.com>
Co-committed-by: 董羽秦 <suzmii@qq.com>
This commit was merged in pull request #139.
This commit is contained in:
2026-08-08 10:25:42 +08:00
committed by 段舒康
parent fc0dcb0782
commit 72f268e088
64 changed files with 3441 additions and 120 deletions
@@ -0,0 +1,166 @@
# 图片画布游戏场景生成链路
更新时间:`2026-08-04`
## 1. 目标
在现役图片画布中补齐单张、静态、非分层游戏环境背景的专用生成链路:
```text
首页游戏场景 / 画布底部游戏场景
-> 场景专用生成表单
-> 后端确定性组装场景 Prompt
-> 现有 editor_image_generation 队列与 Worker
-> 现有计费、失败、资源持久化和 canvasCompletion
```
本期不是 Agent 工作流,不新增场景 Agent、场景 Worker、场景任务表或场景专属计费系统。
## 2. 输入和默认值
用户输入:
- 必填画面内容。
- 视觉风格:日系动画、清透水彩、平面几何、定格模型、自定义。
- 自定义风格下必填自定义画风。
- 可选用户参考图,沿用普通图片生成的参考图处理能力。
- 图片比例、清晰度和图片模型。
默认值:
- 图片比例:`16:9`。
- 清晰度:`1K`。
- 模型:`gemini-3.1-flash-image-preview`,产品展示名沿用现有画布。
- 视觉风格:日系动画。
- 参考图:无。
`model`、`aspectRatio`、`imageSize` 继续使用现有编辑器的字符串契约、模型选项、尺寸选项和后端标准化函数,不维护场景专属枚举列表。
## 3. 前端边界
前端只保存和提交结构化场景意图,不保存或拼接完整场景 Prompt。
正式场景状态使用 `GenerateDialogState.mode = "scene"`,不沿用前端壳中的 `generatorVariant = "game-scene"` Demo 标识。
交接壳复用范围:
- 画风选择控件、交互和局部样式。
- 自定义画风条件输入框。
- 底部游戏场景按钮。
- 四张固定画风预览图。
不复用:
- Demo `App.tsx`。
- `setTimeout` 模拟生成。
- FileReader Data URL 正式请求。
- 复制出的整套画布和缩减版类型。
四张固定图片只用于前端预览,不进入 `generationReferences`,不随生成请求提交。保留原分辨率,只做轻量无损压缩;画风菜单打开时不同时挂载全部预览图,只在用户悬停、键盘聚焦或点击对应预览入口时按需挂载当前图片。点击同一入口可关闭预览,保证无 hover 的触屏设备可用。
## 4. API 契约
主站新增:
```text
POST /api/editor/scenes/generations
```
请求字段:
```text
sceneContent
stylePreset
customStyle?
model?
aspectRatio?
imageSize?
referenceImageSrcs?
projectId?
generationInputs?
assetFolderId?
assetLabel?
canvasCompletion?
```
请求不接受前端组装后的完整 `prompt`。通用 `/api/editor/images/generations` 与 `/api/external/v1/editor/images/generations` 共用同一边界校验,均拒绝 `kind = scene` 或 `assetKind = scene`,防止调用方绕过结构化字段校验和后端 Prompt 组装。External v1 当前没有场景专用路由,因此不能通过通用图片接口提交结构化场景;主站 `/api/editor/scenes/generations` 构造规范请求后直接复用队列,不经过通用入口校验。
完整 Provider Prompt 仍只能由后端生成。
场景参考图沿用普通图片生成的客户端前置门禁,最多 5 张;超限时不得发送 HTTP 请求。场景生成 POST 使用生成专用零重试策略,避免 inline 响应丢失后重复调用 Provider。
后端对模型、比例和清晰度先沿用 `normalize_editor_generation_options` 标准化,再使用标准化比例决定画幅描述和入队价格。
## 5. Prompt
场景 Prompt 在 `server-rs/crates/api-server/src/prompt/editor_scene.rs` 中维护,经 `api-server::prompt` 现役模块出口编译,沿用现有后端 Prompt 常量和 builder 模式,不拆分为运行时文本模板文件,不调用 LLM 润色、扩写或改写。旧 `prompt/scene_background.rs` 属于已退役的自定义世界 / RPG 场景链路,不作为本功能复用入口。
提示词来源为产品提供的 `scene_prompt.md`:
- 删除文档章节编号和 `[图片]` 占位。
- 保留场景结构约束和四套完整预设风格正文。
- 自定义模式只使用用户自定义画风,不附加预设风格正文。
- `视觉风格:` 标题只由场景结构模板输出,预设正文不重复携带标题。
- 先替换受控的比例和画幅方向,再切分静态用户占位符并一次性拼入画面内容与画风正文;用户输入中的模板占位符按原文保留,不参与后续替换。
画幅方向按标准化比例映射:
- `16:9`、`4:3`、`3:2`:横幅。
- `1:1`:方形。
- `9:16`、`2:3`:竖幅。
## 6. 队列和计费
场景请求在后端组装完整 Prompt 后,转换成现有 `EditorImageGenerationRequest`:
```text
kind = scene
assetKind = scene
prompt = 后端完整 Prompt
```
随后复用 `enqueue_editor_image_generation_for_owner`,队列类型继续是 `editor_image_generation`,Worker 继续执行 `generate_editor_image_for_owner`。
队列标题固定为“图片画布生成游戏场景”。任务摘要只展示 `generationInputs.fields` 中的“画面内容”,不得把队列 payload 里的后端完整 Prompt 暴露到任务侧栏;历史错误摘要在投影刷新时按同一规则重新派生。`assetLabel` 省略、空字符串或纯空白时统一使用“游戏场景”,不能退回完整 Prompt 作为素材名称。
计费规则:
- 前端展示价继续读取 `/api/editor/generation-pricing`。
- 入队时按标准化后的模型和清晰度由后端计算并固化 `external_generation_job.price_mud_points`。
- Worker 按入队价格扣费,不能在场景接口增加第二层扣费。
- `scene` 明确按普通图片模型档位计价。
- Provider 失败、执行取消和 lease 耗尽沿用现有扣退费语义。
- Provider 成功后的持久化或画布写回失败语义不在本期调整。
- inline 响应中的通用生成告警必须在队列终态处理前转发;有项目画布占位但响应缺少权威 `project` 快照时,不得追加本地图层或把占位标记为已完成。
- 队列任务进入 `completed` 后,首次项目快照仍可能短暂保留同一 `dialogId` 的 `generating` 占位。场景提交必须把 completion 的 `dialogId` 传给统一项目回读逻辑;首个权威快照仍未收口时做一次有界延迟重读,不能把该快照当作最终状态永久套用。
## 7. 数据落点
不修改 SpacetimeDB schema,继续复用:
- `external_generation_job`。
- `editor_canvas_generation_dialog`。
- `editor_project_resource`。
- `editor_asset`。
- `editor_canvas_layer`。
- `asset_object` / `asset_entity_binding`。
- 现有钱包流水和 `asset_operation_wallet_settlement`。
字段语义:
- `prompt`:后端最终提交给图片 Provider 的完整场景 Prompt。
- `actual_prompt`:Provider 返回的 actual/revised Prompt。
- `asset_kind`:`scene`。
- `generation_inputs_json`:画面内容、视觉风格、自定义画风和用户参考图引用。
## 8. 验收
- 首页和底部按钮进入同一个场景生成器。
- 默认值为 `16:9 / 1K / Banana / 日系动画 / 无参考图`。
- 预设顺序和自定义条件输入正确。
- 预览图不进入请求参考图。
- 前端请求中不存在完整场景 Prompt。
- 后端正确组装四种预设、一个自定义风格和三类画幅。
- 展示价、入队价、实际扣费和资源成本一致。
- 任务复用现有等待、失败、轮询、资源入库和画布添加逻辑。
- 场景产物以 `assetKind = scene` 持久化,画布图层右上角显示“场景”标签,不降级为“未知”。