Update Match3D/image-generation docs & code

Adds/updates documentation, assets and implementation for Match3D and puzzle image generation workflows. Key changes: decision logs and pitfalls updated to prefer VectorEngine Gemini for Match3D material sheets and to require edits (multipart) for 1:1 container reference images; guidance added for when to use APIMart vs VectorEngine. .env.example clarified APIMart/Responses config. Many new public assets and PPT visuals added. Code changes across frontend and backend: updated shared contracts, server-rs match3d/puzzle/image-generation handlers, VectorEngine/OpenAI image generation clients, and multiple React components/tests to handle UI/background/container image signing, edits workflow, and puzzle UI background resolution. Added src/services/puzzle-runtime/puzzleUiBackgroundSource.ts and related test updates. Includes notes about multipart HTTP/1.1 requirement and test/verification commands in docs.
This commit is contained in:
2026-05-14 20:34:45 +08:00
parent d33c937ebc
commit 548db78ca7
103 changed files with 6687 additions and 3270 deletions

View File

@@ -67,6 +67,8 @@ Admin Web
`visible=false` 会让创作中心不展示对应入口;`open=false` 会让前端展示锁定态,并让 api-server 熔断对应玩法创作 / 运行态 API。隐藏入口但仍保留既有作品号、广场详情或试玩链路时应只关闭 `visible`,不要关闭 `open`
当前默认配置中,`visual-novel` 暂时从创作页隐藏并关闭入口,默认种子为 `visible=false``open=false`。如果后续只想恢复已发布作品试玩而不恢复创作入口,需要先明确 API 熔断范围,再通过后台入口开关调整,不能在前端硬编码恢复模板 Tab。
## 注意
- 前端后台页面只做管理表单,不成为配置事实源。

View File

@@ -34,13 +34,13 @@ GENARRATIVE_LLM_BASE_URL=
GENARRATIVE_LLM_API_KEY=
GENARRATIVE_LLM_MODEL=
# APIMart / OpenAI 兼容 Responses 文本网关与抓大鹅 nanobanana 物品素材图
# APIMart / OpenAI 兼容 Responses 文本网关
APIMART_BASE_URL=
APIMART_API_KEY=
APIMART_IMAGE_REQUEST_TIMEOUT_MS=180000
# VectorEngine / GPT-image-2 / Suno / Vidu 生成网关
VECTOR_ENGINE_BASE_URL=https://api.vectorengine.ai
# VectorEngine / Gemini 原生图片 / GPT-image-2 / Suno / Vidu 生成网关
VECTOR_ENGINE_BASE_URL=https://api.vectorengine.cn
VECTOR_ENGINE_API_KEY=
VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS=180000
VECTOR_ENGINE_AUDIO_REQUEST_TIMEOUT_MS=180000
@@ -102,13 +102,13 @@ HYPER3D_MODEL_REQUEST_TIMEOUT_MS / RODIN_MODEL_REQUEST_TIMEOUT_MS
3. 文本 LLM provider 为 `ark` 且未配置 `GENARRATIVE_LLM_BASE_URL` 时,仍回退到 Ark 公开基础 URL。
4. 角色视频 provider 复用 Ark 且未配置 `ARK_CHARACTER_VIDEO_BASE_URL` 时,仍回退到 Ark 公开基础 URL。
5. 具体模型名缺失时不在配置层伪造默认模型,调用到对应能力时由下游配置校验返回缺配置错误。
6. VectorEngine 图片与音频生成只读取 `VECTOR_ENGINE_BASE_URL` / `VECTOR_ENGINE_API_KEY`,其中 GPT-image-2 图片生成额外读取 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS`;不复用 `APIMART_*``GENARRATIVE_LLM_*` 或前端变量。拼图 Agent 的生成 action 不做前端自动重试,避免一次点击在上游超时后重复触发外部生图与钱包扣退费;若 VectorEngine 请求达到该超时窗口api-server 返回 `504 Gateway Timeout``error.details.provider``vector-engine`,并保留具体超时 message。
6. VectorEngine 图片与音频生成只读取 `VECTOR_ENGINE_BASE_URL` / `VECTOR_ENGINE_API_KEY`,其中 GPT-image-2 与抓大鹅 Gemini 素材 sheet 图片生成额外读取 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS`;不复用 `APIMART_*``GENARRATIVE_LLM_*` 或前端变量。拼图 Agent 的生成 action 不做前端自动重试,避免一次点击在上游超时后重复触发外部生图与钱包扣退费;若 VectorEngine 请求达到该超时窗口api-server 返回 `504 Gateway Timeout``error.details.provider``vector-engine`,并保留具体超时 message。
7. 火山引擎语音能力由 `platform-speech` 收口协议帧与上游鉴权,`api-server` 只暴露平台鉴权后的代理路由,不向前端返回任何密钥字段。
8. Hyper3D Rodin Gen-2 使用公开默认 `https://api.hyper3d.com/api/v2`API Key 只读取 `HYPER3D_API_KEY` / `RODIN_API_KEY`,不复用文本 LLM、图片或音频网关密钥。
9. APIMart 当前保留给创意 Agent 的 `gpt-5` Responses 文本/多模态理解链路,并用于抓大鹅物品素材 sheet`nanobanana2` / Gemini 图片模型;GPT-image-2 图片生成不得读取 APIMart 配置。
9. APIMart 当前保留给创意 Agent 的 `gpt-5` Responses 文本/多模态理解链路抓大鹅物品素材 sheetGPT-image-2 图片生成和音频生成都不得读取 APIMart 配置。
10. 本地 `npm run api-server``npm run dev:rust``npm run dev``npm run dev:web` 的环境文件优先级固定为非空外层 shell 变量最高,其后 `.env``.env.local``.env.secrets.local` 逐层覆盖;真实密钥建议放在 `.env.secrets.local`,防止 `.env` 中的空示例值覆盖私密配置。外层 shell 变量如果是空字符串或全空白,不再遮蔽本地 env 文件中的真实值。
11. OSS 客户端只在 `ALIYUN_OSS_BUCKET``ALIYUN_OSS_ENDPOINT``ALIYUN_OSS_ACCESS_KEY_ID``ALIYUN_OSS_ACCESS_KEY_SECRET` 四项齐全时初始化。四项全部缺失表示未启用 OSS部分缺失时 `api-server` 记录 warning 并继续启动,具体上传、换签或读取 generated 私有资产的接口返回 `OSS 未完成环境变量配置`,并在 `error.details.missingEnv` 中列出缺失变量。
12. 抓大鹅 2D 草稿素材生成需要同时具备 APIMart、VectorEngine 与 OSS 配置:APIMart `gemini-3.1-flash-image-preview` 负责生成 5x5 物品素材 sheetVectorEngine `gpt-image-2-all` 负责封面、9:16 背景图和 1:1 容器 UI 图OSS 负责保存切割后的五视角图片及其它生成图。缺少 APIMart、VectorEngine 或 OSS 时应通过 `error.details.reason` 向前端暴露具体缺项,不能只显示泛化“服务暂不可用”。素材图、封面图和背景图生成在调用外部生图前必须先预检 OSS避免已消耗外部生图后才发现无法落库。
12. 抓大鹅 2D 草稿素材生成需要同时具备 VectorEngine 与 OSS 配置:VectorEngine Gemini `gemini-3-pro-image-preview` 原生 `generateContent` 负责生成 5x5 物品素材 sheet封面和 `9:16` 背景图走 VectorEngine `/v1/images/generations` `gpt-image-2-all` JSON 链路;`1:1` 容器 UI 图走 VectorEngine `/v1/images/edits` multipart 链路,并把 `public/match3d-background-references/pot-fused-reference.png` 作为 `image` part 上传,不能再用 generations `image` 数组弱参考。OSS 负责保存切割后的五视角图片及其它生成图。缺少 VectorEngine 或 OSS 时应通过 `error.details.reason` 向前端暴露具体缺项,不能只显示泛化“服务暂不可用”。素材图、封面图和背景图生成在调用外部生图前必须先预检 OSS避免已消耗外部生图后才发现无法落库。
13. 拼图有参考图且开启 AI 重绘时使用 VectorEngine `POST /v1/images/edits` multipart 接口。若返回 `error sending request for url`,代表后端未收到 HTTP 响应;响应 `details` 会带 `reason``source``connect``body``timeout``endpoint`排查时优先检查服务器网络、DNS、防火墙、代理和参考图大小。拼图图片客户端强制 HTTP/1.1,以降低上游 multipart HTTP/2 连接中断风险。
14. 本地排查 `OSS 未完成环境变量配置` 时必须核对键名是否精确为 `ALIYUN_OSS_ACCESS_KEY_SECRET`。常见误写是把 `OSS` 的首字母 `O` 写成数字 `0`,例如 `ALIYUN_0SS_ACCESS_KEY_SECRET`;该键不会被 `api-server` 读取。

View File

@@ -21,7 +21,7 @@
- Puzzle Agent 图片生成动作 `compile_puzzle_draft``generate_puzzle_images`
- Puzzle Agent 动作 `publish_puzzle_work`
- Match3D / 抓大鹅草稿生成动作 `match3d_compile_draft`
- 拼图 / 抓大鹅结果页手动生成背景音乐、UI 背景与抓大鹅批量新增物品素材
- 拼图 / 抓大鹅结果页 UI 背景与抓大鹅批量新增物品素材;背景音乐和点击音效生成入口当前临时关闭,不进入计费范围
暂不接入以下入口:
@@ -34,7 +34,6 @@
- 每次可计费资产操作消耗 `1` 枚泥点。
- 例外Match3D / 抓大鹅草稿生成是一次完整草稿外部生成动作,固定消耗 `10` 枚泥点;流水仍复用 `asset_operation_consume` / `asset_operation_refund``asset_kind = match3d_draft_generation`
- 例外:拼图 / 抓大鹅背景音乐生成固定消耗 `5` 枚泥点;物品点击音效仍按单个音效任务消耗 `10` 枚泥点。
- 例外:拼图 / 抓大鹅 UI 背景重新生成固定消耗 `2` 枚泥点。
- 例外:抓大鹅结果页批量新增物品素材按实际可新增物品名计费,每 `5` 个消耗 `2` 枚泥点,不足 `5` 个向上按 `5` 个计。重复名称、作品中已有名称和超过容量上限的名称不进入计费数量。
- 图片生成和作品发布都按资产操作计费;余额不足时禁止继续执行。
@@ -42,6 +41,20 @@
- 如果图片生成、远程下载、OSS 写入、资产记录确认或发布 mutation 失败,资产操作服务自动发起同额退款。
- 如果退款失败,原始错误仍返回给调用方,同时服务端日志记录退款失败,便于后续人工核对。
## 前端确认交互
所有前端可见且会消耗泥点的按钮,点击后必须先弹出独立确认面板,面板标题使用 `确认消耗泥点`,正文只展示本次消耗数量,例如 `消耗 2 泥点`。用户点击 `确定` 后才允许调用后端扣费动作;点击 `取消` 或关闭面板不得触发接口。
2026-05-14 当前已覆盖的草稿页入口包括:
- 拼图入口 `AI重绘=true``生成拼图游戏草稿``2` 泥点;`AI重绘=false` 直接使用上传图,不显示泥点确认。
- 拼图结果页关卡 `生成画面` / `重新生成画面``2` 泥点。
- 拼图结果页 `素材配置 > UI``生成UI背景` / `重新生成``2` 泥点。
- 拼图结果页发布按钮:`1` 泥点,发布确认面板必须显示本次消耗数量。
- 抓大鹅入口 `生成抓大鹅草稿``10` 泥点。
- 抓大鹅结果页 `素材配置 > 物品` 的批量新增与批量重新生成:按实际计费数量展示动态泥点数。
- 抓大鹅结果页 `素材配置 > UI``素材配置 > 容器形象``重新生成`:各 `2` 泥点。
## 钱包流水
公开两个流水来源类型,统一覆盖“资产生成”和“资产发布”这两类资产操作。流水金额由具体资产操作成本决定,不再假定所有资产操作都是 `1` 枚泥点:

View File

@@ -47,3 +47,11 @@
5. 作品卡片以 `coverImageSrc` 作为整卡背景;若 `coverImageSrc` 为空,允许从同一作品已有的关卡图、背景图或素材图兜底,避免草稿页退回普通面板视觉。
6. 卡片不展示最后修改时间,`updatedAt` 只参与排序。
7. 现有创作中心交互测试通过。
## 2026-05-14 封面兜底补充
1. 货架视图模型仍只保存作品真实 `coverImageSrc` 或同作品真实素材兜底,不把玩法参考图写进数据模型,避免把 UI 兜底误认为作品资产。
2. `CustomWorldWorkCard``CreationWorkShelfKind``CustomWorldCoverArtwork` 传入本地玩法参考图;`ResolvedAssetImage` 在私有资源换签失败、普通图片 404 或真实封面缺失时使用该参考图作为卡片背景。
3. 兜底背景底色跟随百梦浅粉、暖白和珊瑚色调,不能继续使用深黑或暗蓝渐变作为草稿卡默认视觉。
4. 拼图作品列表摘要必须下发 `levels`,草稿页优先用关卡 `coverImageSrc`,再用选中候选图或最后一张候选图作为真实作品封面兜底。
5. 抓大鹅作品列表摘要必须保留 `generatedBackgroundAsset``generatedItemAssets` 中的 `imageObjectKey``containerImageObjectKey``imageViews[].imageObjectKey`;前端拿到 object key 后统一交给 `ResolvedAssetImage` 换签,不能因为缺少公开 URL 而退回黑卡。

View File

@@ -1,5 +1,15 @@
# 抓大鹅草稿素材生成流水线 2026-05-10
## 0. 2026-05-14 临时关闭音频生成
抓大鹅音频生成能力暂时关闭:
1. `match3d_compile_draft` 不再调用 Suno 生成背景音乐,也不再生成点击音效。
2. 结果页 `素材配置` 不再展示 `背景音乐` 子 Tab物品详情面板不再展示点击音效提示词和生成按钮。
3. 批量新增物品只生成 2D 五视角图片,不生成点击音效。
4. 通用 `/api/creation/audio/*` 路由对 `match3d_work` / `match3d_item` 暂时返回 `410 Gone`;视觉小说专用音频路由保持可用。
5. 历史 `generatedItemAssets[].backgroundMusic``clickSound` 字段保留,运行态仍可消费旧音频。
## 1. 范围
本方案用于改造 `生成抓大鹅草稿` 的首版生成链路:点击按钮后先进入独立生成过程页,生成结束后自动进入抓大鹅结果页,并在结果页 `素材配置 > 物品` 预览本次生成的 2D 多视角物品素材。
@@ -8,7 +18,7 @@
## 2. 前端流程
入口仍复用 `Match3DAgentWorkspace` 表单。点击 `生成抓大鹅草稿` 后:
入口仍复用 `Match3DAgentWorkspace` 表单。点击 `生成抓大鹅草稿`必须先弹出 `确认消耗泥点` 面板,展示 `消耗 10 泥点`;用户确认后才进入后端生成流程
1. 创建 Match3D session。
2. 后端先用当前题材和本地兜底元信息创建同一个 Match3D 草稿 profile草稿 Tab 必须立即能看到这份存档。
@@ -20,7 +30,7 @@
生成页步骤固定为:
```text
建立草稿存档 -> 生成作品计划 -> 生成背景提示词 -> 分批生成素材图 -> 切割独立图片 -> 上传图片资产 -> 校验素材结构 -> 生成背景音乐 -> 生成UI背景与容器 -> 写入草稿页
建立草稿存档 -> 生成作品计划 -> 生成背景提示词 -> 分批生成素材图 -> 切割独立图片 -> 上传图片资产 -> 校验素材结构 -> 生成UI背景与容器 -> 写入草稿页
```
生成页只展示题材和物品数量,不展示玩法规则说明。
@@ -29,29 +39,27 @@
## 3. 后端编排边界
外部生图、音频生成和 OSS 上传全部由 `api-server` 编排,不进入 SpacetimeDB reducer。SpacetimeDB 继续只负责 Match3D 会话、草稿和作品 profile 的确定性写入。
外部生图和 OSS 上传全部由 `api-server` 编排,不进入 SpacetimeDB reducer。音频生成当前临时关闭。SpacetimeDB 继续只负责 Match3D 会话、草稿和作品 profile 的确定性写入。
`match3d_compile_draft` action 的后端顺序为:
1. 读取 session config。
2. 对本次 `match3d_compile_draft` 生成动作按 `sessionId + profileId + action 时间戳` 构造幂等流水并预扣 `10` 泥点。余额不足时不继续创建草稿;后续任一步失败时自动按同额退款。
3. 草稿编译先创建可恢复 profile素材生成数量由入口页难度派生的物品种类决定轻松 `3` 种、标准 `9` 种、进阶 `15` 种、硬核 `21` 种。
4. 先调用 SpacetimeDB compile procedure 写入草稿。首次执行使用新 `profileId`;重试时复用 session draft / work profile 中已有 `profileId`。这一步不能等待 LLM、图片、音频或 OSS 成功后才执行。
5. 基于入口页题材设定文本调用文本模型生成作品生成计划。模型固定请求 `gpt-4o`,只返回 JSON其中 `gameName` 为 4 到 12 个中文字符的游戏名称,`summary` 为 18 到 48 个中文字符的作品描述。生成计划还必须包含 `tags``backgroundMusic.title``backgroundMusic.style``backgroundMusic.prompt``backgroundPrompt`,以及 `items[]` 中每个物品的 `name``soundPrompt``backgroundMusic.title` 是背景音乐名称,`backgroundMusic.prompt` 固定为空字符串,用于后续 Suno 纯音乐生成;`backgroundPrompt` 用于生成局内竖屏纯背景图只描述题材氛围、色彩和环境不得描述锅、圆盘、托盘、拼图槽、物品槽、HUD、UI、文字、按钮、倒计时、分数或物品。文本模型不可用时保留第 4 步的本地兜底,不阻断草稿。
4. 先调用 SpacetimeDB compile procedure 写入草稿。首次执行使用新 `profileId`;重试时复用 session draft / work profile 中已有 `profileId`。这一步不能等待 LLM、图片或 OSS 成功后才执行。
5. 基于入口页题材设定文本调用文本模型生成作品生成计划。模型固定请求 `gpt-4o`,只返回 JSON其中 `gameName` 为 4 到 12 个中文字符的游戏名称,`summary` 为 18 到 48 个中文字符的作品描述。生成计划还必须包含 `tags``backgroundPrompt`,以及 `items[]` 中每个物品的 `name``soundPrompt``soundPrompt` 只作为历史字段保留,当前不触发音效生成;`backgroundPrompt` 用于生成局内竖屏纯背景图只描述题材氛围、色彩和环境不得描述锅、圆盘、托盘、拼图槽、物品槽、HUD、UI、文字、按钮、倒计时、分数或物品。文本模型不可用时保留第 4 步的本地兜底,不阻断草稿。
6. 后端把生成计划中的 `gameName``summary` 写入 `match3d_work_profile` 作品信息后,自动调用作品标签生成器。标签生成器使用题材、作品名称和作品描述生成 3 到 6 个中文短标签;若调用失败或返回不足,则使用生成计划 tags 和本地兜底标签补齐。结果页手动 `AI生成作品标签` 也使用同一接口,并传入当前作品描述。
7. 后端从同一份作品生成计划读取当前难度所需数量的短物品名称和音效提示词;不得再只生成物品名称而丢失后续音效生成上下文
8. 调用 APIMart `nanobanana2` / Gemini 图片模型生成 `1:1``1K` 素材图,请求模型固定为 `gemini-3.1-flash-image-preview`,走 `POST {APIMART_BASE_URL}/images/generations`,并携带 `official_fallback = true`。提示词必须合入入口页选择的 `assetStylePrompt`,并强制每格使用统一纯绿色绿幕背景,避免白底或纹理背景进入运行态素材。该调整只作用于抓大鹅物品素材 sheet封面9:16 纯背景图1:1 容器 UI 图仍继续使用项目现有 VectorEngine `gpt-image-2-all` 链路
7. 后端从同一份作品生成计划读取当前难度所需数量的短物品名称,并兼容保存历史 `soundPrompt` 字段;当前不生成点击音效
8. 调用 VectorEngine Gemini 原生图片接口生成 `1:1` 素材图,请求模型固定为 `gemini-3-pro-image-preview`,走 `POST {VECTOR_ENGINE_BASE_URL}/v1beta/models/gemini-3-pro-image-preview:generateContent?key={VECTOR_ENGINE_API_KEY}`。请求体使用 `contents[].parts[].text``generationConfig.responseModalities = ["TEXT", "IMAGE"]``generationConfig.imageConfig.aspectRatio = "1:1"`,响应从 `candidates[].content.parts[].inlineData.data` / `inline_data.data` 读取 base64 图片。提示词必须合入入口页选择的 `assetStylePrompt`,并强制每格使用统一纯绿色绿幕背景,避免白底或纹理背景进入运行态素材。该调整只作用于抓大鹅物品素材 sheet封面`9:16` 纯背景图继续使用 VectorEngine `/v1/images/generations``gpt-image-2-all` JSON 链路,`1:1` 容器 UI 图必须使用 VectorEngine `/v1/images/edits` multipart 图生图链路,不能再把参考图作为 generations 的 `image` 数组弱参考
9. 每个物品固定需要 `5` 个不同视角。单张素材图固定为 `5*5 = 25` 格,因此单张图承载 `5` 个物品。若用户要求或难度派生的物品种类不是 `5` 的倍数,后端必须向上补齐物品名称和对应图片到最近的 `5` 的倍数;例如标准难度需要 `9` 种玩法物品,实际生成 `10` 个物品名称和对应五视角图片。若草稿物品数超过 `5`,后端按每批 `5` 个物品自动分批,多张素材图并行生成。
10. 将每张素材图按固定 `5 行 * 5 列` 切割成独立图片,并按物品顺序连续分配 `5` 张视角图。素材图提示词必须要求 `5*5` 严格均匀排布、每格主体完整居中、统一纯绿色绿幕背景、相邻物体主体至少保留 `1/4` 单格宽度空白间距、不得跨格、贴边或越界,避免裁剪后相邻格内容污染。切割前必须先在整张素材图上把绿幕背景处理为透明 alpha再在每个理论格子内按透明背景/前景像素做内容边界校准,并带少量安全留白导出;不能做固定内缩裁剪,避免贴近格线但未跨格的樱桃、叶片、把手等主体边缘被切掉。每个物品 JSON 写入 `imageViews[]`,同时把第一个视角兼容写入 `imageSrc/imageObjectKey`
11. 将素材图和每张独立视角图片上传到 OSS。每次获得可恢复的图片资产后都要回写 `match3d_work_profile.generated_item_assets_json`。成功素材状态为 `image_ready`;失败素材保留已成功图片引用并记录 `error`。每个素材 JSON 同步保存 `soundPrompt`,首个素材 JSON 同步保存 `backgroundMusicTitle``backgroundMusicStyle``backgroundMusicPrompt` 保存为空字符串作为兼容字段
12. 后端在图片素材生成后使用 `backgroundMusic.title` 提交 Suno 背景音乐任务,`prompt` 为空,`tags` 来自 `backgroundMusic.style`,并固定走纯音乐生成。轮询完成后通过通用创作音频资产链路转存 OSS、确认 `asset_object`、绑定到 `match3d_work/background_music`,再写回首个素材的 `backgroundMusic`。自动草稿阶段必须拿到非空 `backgroundMusic.audioSrc` 才能返回成功曲名为空、Suno 提交/轮询失败、音频下载失败、OSS 转存失败或资产绑定失败时,本次 `match3d_compile_draft` 返回失败并停留在生成页,不能进入结果页后显示“暂无音乐”
13. 草稿生成阶段不生成点击音效,只保存 `generatedItemAssets[].soundPrompt`;点击音效由结果页 `素材配置 > 物品` 详情面板手动生成并写回对应素材
14. UI 背景生成由 `api-server` 调用 VectorEngine `gpt-image-2-all` 分成两张资产:第一张是 `9:16` 纯背景图不传锅参考图且必须禁止锅、圆盘、托盘、拼图槽、物品槽、HUD、文字、按钮、倒计时、分数和物品第二张是 `1:1` 题材容器 UI 图,固定传入 `public/match3d-background-references/pot-fused-reference.png` 作为参考图,只生成一个贴合题材设定的圆形或浅盘状竞技容器,不生成整页背景、文字、按钮或物品。容器图必须沿用参考图的大尺寸轻俯视构图:外轮廓接近画布四边,宽度约占 `86%-92%`、高度约占 `82%-90%`,内口为横向椭圆,禁止生成小容器、正俯视圆盘、侧视碗、餐盘或小托盘。纯背景上传到 `generated-match3d-assets/{sessionId}/{profileId}/background/{taskId}/background.png`,容器 UI 图上传到 `generated-match3d-assets/{sessionId}/{profileId}/ui-container/{taskId}/container.png`,两者都作为 `backgroundAsset` 挂在首个 `generatedItemAssets[]` JSON 上HTTP DTO 同时顶层输出兼容的 `backgroundPrompt``backgroundImageSrc``backgroundImageObjectKey``generatedBackgroundAsset`,容器图通过 `generatedBackgroundAsset.containerImageSrc/containerImageObjectKey` 返回。若作品尚无用户自定义封面,草稿生成完成后默认把容器 UI 图写入 `coverImageSrc`,作为草稿架和作品信息的默认封面。
15. 在 HTTP 返回的 draft/profile DTO 中附带本次生成的素材资产预览信息、背景音乐资产信息、背景资产信息和默认封面;后续重进草稿页时从 work profile 的持久化 `generatedItemAssets``coverImageSrc` 恢复同一批素材、音乐、UI 与封面。
10. 将每张素材图按固定 `5 行 * 5 列` 切割成独立图片,并按物品顺序连续分配 `5` 张视角图。素材图提示词必须要求 `5*5` 严格均匀排布、每格主体完整居中、统一纯绿色绿幕背景、相邻物体主体至少保留 `1/4` 单格宽度空白间距、不得跨格、贴边或越界,避免裁剪后相邻格内容污染。切割前必须先在整张素材图上做透明背景处理:连通到 sheet 外边缘的绿幕/近白底要清成 alpha每格内部未连到外边缘但高置信的纯绿绿幕块也必须清成 alpha物品边缘的绿幕抗锯齿和近白白边要做透明或去污染处理不够纯的绿色主体像素不得被当作绿幕误删。随后再在每个理论格子内按透明背景/前景像素做内容边界校准,并带少量安全留白导出;不能做固定内缩裁剪,避免贴近格线但未跨格的樱桃、叶片、把手等主体边缘被切掉。每个物品 JSON 写入 `imageViews[]`,同时把第一个视角兼容写入 `imageSrc/imageObjectKey`
11. 将素材图和每张独立视角图片上传到 OSS。每次获得可恢复的图片资产后都要回写 `match3d_work_profile.generated_item_assets_json`。成功素材状态为 `image_ready`;失败素材保留已成功图片引用并记录 `error`。每个素材 JSON 可继续保存历史 `soundPrompt`;不再写入新的 `backgroundMusicTitle/backgroundMusicStyle/backgroundMusicPrompt`
12. UI 背景生成由 `api-server` 分成两张资产:第一张是 `9:16` 纯背景图,走 VectorEngine `/v1/images/generations``gpt-image-2-all` JSON 请求不传锅参考图且必须禁止锅、圆盘、托盘、拼图槽、物品槽、HUD、文字、按钮、倒计时、分数和物品第二张是 `1:1` 题材容器 UI 图,走 VectorEngine `/v1/images/edits` multipart 请求,把 `public/match3d-background-references/pot-fused-reference.png` 作为 `image` part 上传,只生成一个贴合题材设定的圆形或浅盘状竞技容器,不生成整页背景、文字、按钮或物品。容器图必须沿用参考图的大尺寸轻俯视构图:外轮廓接近画布四边,宽度约占 `86%-92%`、高度约占 `82%-90%`,内口为横向椭圆,禁止生成小容器、正俯视圆盘、侧视碗、餐盘或小托盘。纯背景上传到 `generated-match3d-assets/{sessionId}/{profileId}/background/{taskId}/background.png`,容器 UI 图上传到 `generated-match3d-assets/{sessionId}/{profileId}/ui-container/{taskId}/container.png`,两者都作为 `backgroundAsset` 挂在首个 `generatedItemAssets[]` JSON 上HTTP DTO 同时顶层输出兼容的 `backgroundPrompt``backgroundImageSrc``backgroundImageObjectKey``generatedBackgroundAsset`,容器图通过 `generatedBackgroundAsset.containerImageSrc/containerImageObjectKey` 返回。若作品尚无用户自定义封面,草稿生成完成后默认把容器 UI 图写入 `coverImageSrc`,作为草稿架和作品信息的默认封面
13. 在 HTTP 返回的 draft/profile DTO 中附带本次生成的素材资产预览信息、背景资产信息和默认封面;后续重进草稿页时从 work profile 的持久化 `generatedItemAssets``coverImageSrc` 恢复同一批素材、UI 与封面。历史音频字段只做兼容传递
若文本模型不可用或返回无法解析,后端必须降级为 `{themeText}抓大鹅`、本地作品描述与本地标签兜底,不阻断素材生成;标签仍通过作品标签生成器优先生成,失败后再用兜底标签补齐。
草稿生成阶段不再调用 Hyper3D Rodin不生成 GLB也不等待任何模型轮询。前端 `match3d_compile_draft` action 的长耗时主要来自文本生成、分批 1K 生图、切图、OSS 上传、纯背景图容器 UI 图和可选音频生成。批量新增物品由 `POST /api/creation/match3d/works/{profileId}/item-assets` 复用同一套 2D 素材图生成、固定 `5*5` 切图OSS 上传和可选点击音效链路;若本次新增数量不是 `5` 的倍数,同样向上补齐名称和图片到最近的 `5` 的倍数。整图生成完成后立即丢弃补齐用临时物品,只对用户实际新增项执行绿幕抠背景、切割和上传,并只把这些真实新增项的 `imageViews[]` 写回 `generatedItemAssets`
草稿生成阶段不再调用 Hyper3D Rodin不生成 GLB也不等待任何模型轮询。前端 `match3d_compile_draft` action 的长耗时主要来自文本生成、分批 1K 生图、切图、OSS 上传、纯背景图容器 UI 图。批量新增物品由 `POST /api/creation/match3d/works/{profileId}/item-assets` 复用同一套 2D 素材图生成、固定 `5*5` 切图OSS 上传链路;若本次新增数量不是 `5` 的倍数,同样向上补齐名称和图片到最近的 `5` 的倍数。整图生成完成后立即丢弃补齐用临时物品,只对用户实际新增项执行绿幕抠背景、切割和上传,并只把这些真实新增项的 `imageViews[]` 写回 `generatedItemAssets`批量重新生成同样调用该接口,但请求体增加 `mode = "replace"`,前端从现有素材列表收集用户确认的物品名称;后端只匹配已存在的同名素材,保留原 `itemId`、列表顺序、UI 背景、历史背景音乐和点击音效字段,只替换该素材的 `imageSrc/imageObjectKey/imageViews/status/error`,避免试玩和正式运行态的物品类型映射漂移。
## 4. 图片提示词
@@ -92,7 +100,7 @@ public/match3d-style-references/painterly-icon.png
public/match3d-background-references/pot-fused-reference.png
```
这张图只作为容器 UI 图的 VectorEngine `image` 参考输入,用来锁定“大尺寸轻俯视浅盘容器”的构图。参考图本身是 `1:1` 透明底容器素材,外轮廓接近画布四边,内口为横向椭圆;结果页没有真实生成容器时也只把它作为容器预览兜底,不能再作为 `9:16` 背景预览。每次草稿生成仍会根据 `backgroundPrompt` 生成新的题材化纯背景图;纯背景图不再传入该参考图,也不得生成锅或 UI 元素。
这张图只作为容器 UI 图的 VectorEngine `/v1/images/edits` multipart `image` part,用来锁定“大尺寸轻俯视浅盘容器”的构图。参考图本身是 `1:1` 透明底容器素材,外轮廓接近画布四边,内口为横向椭圆;结果页没有真实生成容器时也只把它作为容器预览兜底,不能再作为 `9:16` 背景预览。每次草稿生成仍会根据 `backgroundPrompt` 生成新的题材化纯背景图;纯背景图不再传入该参考图,也不得生成锅或 UI 元素。
## 5. OSS 路径
@@ -116,7 +124,9 @@ generated-match3d-assets/{sessionId}/{profileId}/background/{taskId}/background.
`itemSlug` 必须带 `itemId` 前缀,例如 `match3d-item-1-item`。中文物品名清洗后可能都退回 `item`,不能只用物品名做路径,否则多张切割图会写到同一个 object key导致草稿页预览图全部一致。
HTTP DTO 同时返回兼容字段 `imageSrc``imageObjectKey`,以及正式 2D 字段 `imageViews[]``backgroundAsset``status`。图片素材生成成功后 `status = image_ready`;纯背景和容器 UI 图都生成成功后首个素材的 `backgroundAsset.status = image_ready`,并携带 `containerImageSrc/containerImageObjectKey`。前端通过 `/api/assets/read-url` 将 generated legacy path 换签后加载私有图片,不直接请求裸 `/generated-match3d-assets/...` 路径。运行态背景图和容器 UI 图同样通过 `/api/assets/read-url` 换签后加载:背景作为全屏 `object-cover`,容器作为中心棋盘覆盖层
HTTP DTO 同时返回兼容字段 `imageSrc``imageObjectKey`,以及正式 2D 字段 `imageViews[]``backgroundAsset``status`。图片素材生成成功后 `status = image_ready`;纯背景和容器 UI 图都生成成功后首个素材的 `backgroundAsset.status = image_ready`,并携带 `containerImageSrc/containerImageObjectKey`。前端通过 `/api/assets/read-url` 将 generated legacy path 换签后加载私有图片,不直接请求裸 `/generated-match3d-assets/...` 路径。运行态背景图和容器 UI 图同样通过 `/api/assets/read-url` 换签后加载:背景作为全屏 `object-cover`,容器作为中心棋盘视觉层;当容器图成功解析为可渲染图片时,`Match3DRuntimeShell` 必须移除默认圆形锅壳、边框和径向底色,让生成容器接管棋盘外观
结果页手动点击 `素材配置 > UI > 重新生成` 时,目标库可能仍运行旧 SpacetimeDB wasm缺少钱包扣退费或 Match3D 写回相关 procedure。`api-server` 对这类 `No such procedure` 只做临时容错:泥点预扣阶段跳过扣费,背景图和容器 UI 已经生成但草稿写回失败时HTTP 响应仍返回本次生成的 `generatedBackgroundAsset` 和带该资产的内存 profile避免草稿页直接报错。该容错不等于持久化成功刷新、换设备或公开详情稳定恢复仍以发布最新 SpacetimeDB module、确认 procedure 导出和重新生成 bindings 为准。
## 5.1 运行态 2D 素材消费
@@ -124,25 +134,25 @@ HTTP DTO 同时返回兼容字段 `imageSrc`、`imageObjectKey`,以及正式 2
```text
Match3DWorkProfile / PlatformMatch3DGalleryCard
-> Match3DRuntimeShell(generatedItemAssets, backgroundImageSrc)
-> Match3DRuntimeShell(generatedItemAssets, generatedBackgroundAsset, backgroundImageSrc)
-> Match3DPhysicsBoard / Match3DTrayPreviewBoard
```
运行态按运行快照中的 `itemTypeId` 稳定排序后,把 `generatedItemAssets` 顺序映射到对应类型。加载某个物品实例时,从该类型素材的 `imageViews[]` 中按实例 id 稳定随机选择一个视角;若历史数据没有 `imageViews[]`,则回退到 `imageSrc/imageObjectKey`。没有生成图片或图片加载失败时,继续使用默认积木图标兜底。
运行态背景优先读取 `backgroundImageSrc` / `generatedBackgroundAsset.imageSrc`,为空时从 `generatedItemAssets[].backgroundAsset.imageSrc/imageObjectKey` 兜底。中心容器优先读取 `generatedItemAssets[].backgroundAsset.containerImageSrc/containerImageObjectKey`;为空时继续使用默认圆形容器样式。运行态入口判断是否需要补读作品详情时,只能把 `imageViews[]``imageSrc/imageObjectKey` 视为“已有物品图片素材”;`backgroundMusic.audioSrc``clickSound.audioSrc``backgroundAsset.image*``backgroundAsset.containerImage*` 是随物品素材一起传入的附属运行态资产,不能单独证明物品素材已完整。也不能继续只用历史 `modelSrc/modelObjectKey` 判断,否则新 2D 草稿会在试玩或推荐流中被当成“无素材”并回退默认积木。`Match3DRuntimeShell` 只保留顶部返回、倒计时、重开三个控件;这些顶部控件和底部备选栏统一使用题材无关的半透明玻璃组件样式,不能随背景题材改成木质、金属、果园、科幻等主题皮肤,也不能重新烘进 AI 背景图。进度、组数、版本等状态信息不得再作为顶部常驻 UI 出现,避免遮挡生成背景和中心容器。
运行态背景优先读取 `backgroundImageSrc` / 顶层 `generatedBackgroundAsset.imageSrc/imageObjectKey`,为空时从 `generatedItemAssets[].backgroundAsset.imageSrc/imageObjectKey` 兜底。中心容器优先读取顶层 `generatedBackgroundAsset.containerImageSrc/containerImageObjectKey`,再读取 `generatedItemAssets[].backgroundAsset.containerImageSrc/containerImageObjectKey`;为空或换签/图片加载失败时继续使用默认圆形容器样式。容器图成功加载后,`Match3DRuntimeShell` 的棋盘容器必须切换为透明、可溢出承载,不再叠加默认 `rounded-full` 圆形锅壳、金色边框和默认径向背景,避免 AI 生成的大尺寸轻俯视容器被裁切或被默认锅视觉覆盖。运行态入口判断是否需要补读作品详情时,只能把 `imageViews[]``imageSrc/imageObjectKey` 视为“已有物品图片素材”;`backgroundMusic.audioSrc``clickSound.audioSrc``generatedBackgroundAsset``backgroundAsset.image*``backgroundAsset.containerImage*` 是随物品素材一起传入的附属运行态资产,不能单独证明物品素材已完整。也不能继续只用历史 `modelSrc/modelObjectKey` 判断,否则新 2D 草稿会在试玩或推荐流中被当成“无素材”并回退默认积木。`Match3DRuntimeShell` 只保留顶部返回、倒计时、重开三个控件;这些顶部控件和底部备选栏统一使用题材无关的半透明玻璃组件样式,不能随背景题材改成木质、金属、果园、科幻等主题皮肤,也不能重新烘进 AI 背景图。进度、组数、版本等状态信息不得再作为顶部常驻 UI 出现,避免遮挡生成背景和中心容器。
前端加载规则:
1. 优先读取 `imageViews[]` 中的 `imageSrc/imageObjectKey`,为空时使用兼容字段 `imageSrc/imageObjectKey`
2. 对 generated legacy path 通过同源 `/api/assets/read-url` 换签后交给浏览器图片加载;结果页 `素材配置 > 背景音乐``素材配置 > 物品` 的音频试听控件也必须先换签,不能把裸 `/generated-match3d-assets/...` 音频路径直接交给 `<audio>`
2. 对 generated legacy path 通过同源 `/api/assets/read-url` 换签后交给浏览器图片加载;结果页音频试听入口当前隐藏,后续恢复时也必须先换签,不能把裸 `/generated-match3d-assets/...` 音频路径直接交给 `<audio>`
3. 场内物品、点击命中和备选栏继续使用后端快照中的 `itemInstanceId/itemTypeId/x/y/radius/layer`;生成 2D 图片只替换视觉表现,不承接规则真相。
4. 同一物品类型的多个实例可以展示不同视角,但同一实例在本局中应稳定使用同一个视角,避免移动或入槽时闪图。
5. 图片缺失、读取失败或解码失败时,继续使用默认积木素材,不能阻断开局、点击、入槽或结算。
结果页点击 `试玩` 时,前端必须把当前结果页可见的 `generatedItemAssets` 带入运行态启动入参。`PUT /api/runtime/match3d/works/{profileId}` 若因为并发或旧快照返回了缺少素材的 profile`Match3DResultView` 需要把当前 draft / profile 的素材重新合并到运行态 profile并在启动试玩前调用生成素材保存接口把当前可见的 `generatedItemAssets` 写回作品 profile不能只在内存里把素材补到 `onStartTestRun(profile)`。发布同理必须先落库当前素材,再调用 `publish_match3d_work`,否则公开推荐流和正式运行态只能读到旧 profile 快照。结果页顶部返回按钮固定回到平台创作页,不再回到抓大鹅专属内嵌入口表单;需要修改题材时由用户在创作页重新选择或从草稿继续进入。若历史草稿同时存在旧 `draft.generatedItemAssets` 和较新的 `profile.generatedItemAssets`,同 `itemId` 下以 profile 中已有的 `imageViews[]``imageSrc``imageObjectKey``backgroundMusic``backgroundAsset` 补齐 draft不能让旧 draft 把素材覆盖成空列表。`PlatformEntryFlowShellImpl` 在渲染 `match3d-runtime` 时按 `run.profileId` 优先使用当前 `match3dRuntimeProfile / match3dProfile.generatedItemAssets`,只有 profileId 不匹配时才读取 `selectedPublicWorkDetail.generatedItemAssets`;即使当前 profile 暂时没有物品图片,也不能把同 profile 的已有 `generatedItemAssets` 覆盖为空数组。推荐流内嵌正式运行态也必须走同一解析器;当推荐卡片摘要缺少物品图片素材时,启动前补读 `getMatch3DWorkDetail(profileId)`,把详情里的生成图片、背景音乐和 UI 素材写入 `match3dRuntimeProfile` 后再传给运行态。这样可以避免从公开详情页残留状态或推荐卡片旧摘要进入试玩 / 正式游戏时,把已生成草稿的 2D 素材、音乐或 UI 覆盖成空列表。
结果页点击 `试玩` 时,前端必须把当前结果页可见的 `generatedItemAssets` 带入运行态启动入参。`PUT /api/runtime/match3d/works/{profileId}` 若因为并发或旧快照返回了缺少素材的 profile`Match3DResultView` 需要把当前 draft / profile 的素材重新合并到运行态 profile并在启动试玩前调用生成素材保存接口把当前可见的 `generatedItemAssets` 写回作品 profile不能只在内存里把素材补到 `onStartTestRun(profile)`。发布同理必须先落库当前素材,再调用 `publish_match3d_work`,否则公开推荐流和正式运行态只能读到旧 profile 快照。结果页顶部返回按钮固定回到平台创作页,不再回到抓大鹅专属内嵌入口表单;需要修改题材时由用户在创作页重新选择或从草稿继续进入。若历史草稿同时存在旧 `draft.generatedItemAssets` 和较新的 `profile.generatedItemAssets`,同 `itemId` 下以 profile 中已有的 `imageViews[]``imageSrc``imageObjectKey``backgroundMusic``backgroundAsset` 补齐 draft不能让旧 draft 把素材覆盖成空列表。`PlatformEntryFlowShellImpl` 在渲染 `match3d-runtime` 时按 `run.profileId` 优先使用当前 `match3dRuntimeProfile / match3dProfile.generatedItemAssets`,只有 profileId 不匹配时才读取 `selectedPublicWorkDetail.generatedItemAssets`;即使当前 profile 暂时没有物品图片,也不能把同 profile 的已有 `generatedItemAssets` 覆盖为空数组。推荐流内嵌正式运行态也必须走同一解析器;当推荐卡片摘要缺少物品图片素材时,启动前补读 `getMatch3DWorkDetail(profileId)`,把详情里的生成图片、历史背景音乐和 UI 素材写入 `match3dRuntimeProfile` 后再传给运行态。这样可以避免从公开详情页残留状态或推荐卡片旧摘要进入试玩 / 正式游戏时,把已生成草稿的 2D 素材、历史音乐或 UI 覆盖成空列表。
2026-05-14 补充:`backgroundMusic` 虽然暂存在 `generatedItemAssets[]` 中,但语义上是作品级音乐。前端读取、保存、试玩、推荐流和运行态入口都必须先通过统一归一化逻辑把任意素材上的 `backgroundMusic/backgroundMusicTitle/backgroundMusicStyle/backgroundMusicPrompt` 迁移到首个素材,并清空其它素材上的作品级音乐字段,避免 `素材配置 > 背景音乐` 只读首项时显示“暂无音乐”,也避免 action response 中缺音乐的 draft assets 覆盖 work detail 中已经持久化的音乐。`match3d_compile_draft` action 完成后,如果同时拿到 `response.session.draft.generatedItemAssets``getMatch3DWorkDetail(profileId).item.generatedItemAssets`,必须以同 `itemId` 合并保留详情里的背景音乐、UI 背景和点击音效,再进入结果页或试玩。
2026-05-14 补充:`backgroundMusic` 虽然暂存在 `generatedItemAssets[]` 中,但语义上是作品级音乐。前端读取、保存、试玩、推荐流和运行态入口都必须先通过统一归一化逻辑把任意素材上的 `backgroundMusic/backgroundMusicTitle/backgroundMusicStyle/backgroundMusicPrompt` 迁移到首个素材,并清空其它素材上的作品级音乐字段,避免 action response 中缺音乐的 draft assets 覆盖 work detail 中已经持久化的音乐,也为未来恢复音乐入口保留稳定读取口径`match3d_compile_draft` action 完成后,如果同时拿到 `response.session.draft.generatedItemAssets``getMatch3DWorkDetail(profileId).item.generatedItemAssets`,必须以同 `itemId` 合并,保留详情里的历史背景音乐、UI 背景和点击音效,再进入结果页或试玩。
历史草稿若仍保存 `status = model_ready``modelSrc``modelObjectKey`,仅作为旧版本兼容读取,不再参与新素材生产。历史外部模型链接转存接口只用于清理旧数据,不能被新草稿生成、批量新增或结果页普通编辑入口调用。
@@ -152,9 +162,9 @@ Match3DWorkProfile / PlatformMatch3DGalleryCard
点击 `生成抓大鹅草稿` 后,草稿存档创建与素材生成解耦:
1. 首次 compile 必须先写 `match3d_work_profile` 草稿行,即使后续卡在文本模型、图片生成、音频生成或 OSS 上传任意阶段。
1. 首次 compile 必须先写 `match3d_work_profile` 草稿行,即使后续卡在文本模型、图片生成或 OSS 上传任意阶段。
2. 失败态前端要重新读取 session / work detail并刷新草稿作品架保证用户离开生成页后仍能在草稿 Tab 找到这份作品。
3. 重新生成时优先使用当前 session 的 `draft.profileId``publishedProfileId`,不得重新创建 session后端读取同一 profile 的 `generated_item_assets_json` 后,只补齐缺失图片或缺失音频的阶段
3. 重新生成时优先使用当前 session 的 `draft.profileId``publishedProfileId`,不得重新创建 session后端读取同一 profile 的 `generated_item_assets_json` 后,只补齐缺失图片、UI 背景或容器资源
4. 已有 `status = image_ready` 且带 `imageViews[]``imageSrc/imageObjectKey` 的素材视为完成,不再重复生成图片。
抓大鹅结果页的基础信息自动保存继续调用 `PUT /api/runtime/match3d/works/{profileId}` 更新名称、题材、描述、标签、封面、消除数和难度;该保存不得清空 `generated_item_assets_json`。结果页 `素材配置 > 物品` 只在独立面板中预览和编辑当前素材,不再提供单项重新生成入口;删除单项或批量新增成功后,都必须把当前素材列表重新序列化成 `generatedItemAssets` 并写回作品 profile否则试玩、发布和重进草稿会读取旧素材快照。SpacetimeDB `update_match3d_work` / `publish_match3d_work` 必须保留当前行的生成素材 JSON。
@@ -174,7 +184,7 @@ Match3DWorkProfile / PlatformMatch3DGalleryCard
1. `作品名称` 对应 Match3D `gameName`
2. `作品描述` 对应 Match3D `summary`,草稿生成阶段由同一次作品生成计划自动填入。
3. `作品标签` 对应 Match3D `tags`,草稿生成阶段在写入名称和描述后自动调用标签生成器填入;结果页仍允许用户继续编辑或再次 AI 生成。
4. 封面图与作品名称不再拆成左右两个大模块;封面只作为同一 Tab 内的可选入口,避免和作品基础信息割裂。草稿生成默认使用生成出的中心容器 UI 图作为 `coverImageSrc`。点击封面图必须弹出独立编辑面板,不允许在当前作品信息面板下方展开。封面面板布局参考拼图创作页上传卡:移动端优先左侧/上方为方形预览,右侧/下方为提示词与操作区。面板支持三类输入:本地上传图片、上传后开启 AI 重绘、直接引用 `物品素材` `UI素材` 中已有图片作为封面或 AI 重绘参考图。AI 重绘通过 `api-server` 的 Match3D 作品封面生成接口调用 VectorEngine `gpt-image-2-all`,生成结果转存到 `generated-match3d-assets/{sessionId}/{profileId}/cover/{taskId}/cover.png` 后再写回 `coverImageSrc`;关闭 AI 重绘时只把选中的 Data URL 或 generated legacy path 写入封面字段
4. 封面图与作品名称不再拆成左右两个大模块;封面只作为同一 Tab 内的可选入口,避免和作品基础信息割裂。旧称“碰面图”统一改为“封面图”。草稿生成默认使用生成出的中心容器 UI 图作为 `coverImageSrc`。点击封面图必须弹出独立编辑面板,不允许在当前作品信息面板下方展开。封面面板布局对齐拼图创作页上传卡:移动端优先左侧/上方为方形预览卡,预览卡本身就是上传热区;上传图片后,预览卡内出现和拼图入口一致的 `AI重绘` 开关与删除按钮,面板底部不再额外展示旧 `AI重绘` 选项。已有上传图时,右侧/下方输入框标题为 `AI重绘要求`;关闭 AI 重绘时只把上传图 Data URL 写入封面字段,不调用生图模型。没有上传图时,输入框标题为 `封面描述`,可选择多张参考图后调用 VectorEngine `gpt-image-2-all` 文生图链路,参考图通过请求体 `image` 数组传入;参考图来源支持直接引用 `物品素材` / `UI素材` 中已有图片,也支持自定义上传。上传图 AI 重绘与无上传图多参考图生成都通过 `api-server` 的 Match3D 作品封面生成接口完成,生成结果转存到 `generated-match3d-assets/{sessionId}/{profileId}/cover/{taskId}/cover.png` 后再写回 `coverImageSrc`
结果页 `难度配置` Tab 取代旧 `玩法配置`,不再展示旧的分散输入项。该 Tab 顶部使用横向离散拖动条调整难度,四个刻度分别为 `轻松 / 标准 / 进阶 / 硬核`;拖动条只能落在这四个点上,刻度标签可点击切换。该 Tab 必须与创作入口页使用同一组难度选项,并统一把原“类型素材图片 / 局内类型”等口径归一为 `物品种类`
@@ -187,36 +197,36 @@ Match3DWorkProfile / PlatformMatch3DGalleryCard
预览区展示 `需要消除``总物品数``物品种类``已生成物品种类`。历史草稿如果保存的是旧 `clearCount/difficulty`,前端按 `clearCount` 精确命中优先、否则按 `difficulty` 就近归一到上述选项,并把归一后的数值保存回 profile。发布校验以 `generatedItemAssets[]``image_ready` 且至少有 `5` 张有效 `imageViews[]` 的素材数量为准;试玩启动时用同一数量计算 `itemTypeCountOverride`,不足时自动降低,不修改草稿难度配置本身。历史单图 `imageSrc/imageObjectKey` 只作为运行态和预览兜底,不计入新发布素材完成数。
结果页 `素材配置` Tab 取代旧一级素材入口,包含三个子 Tab
结果页 `素材配置` Tab 取代旧一级素材入口,当前包含三个子 Tab
1. `物品`:显示 2D 物品素材列表、五视角预览素材名称点击音效提示词和点击音效生成入口
2. `UI`:预览生成的竖屏游戏纯背景图和中心容器 UI 图。背景读取顺序为 draft 顶层背景、draft `generatedBackgroundAsset`、profile 顶层背景、profile `generatedBackgroundAsset``generatedItemAssets[].backgroundAsset`、本地兜底图;容器读取 `generatedItemAssets[].backgroundAsset.containerImageSrc/containerImageObjectKey`,缺失时使用默认圆形容器。该页必须展示默认画面描述提示词,默认值来自草稿生成计划的 `backgroundPrompt` 或持久化 `backgroundAsset.prompt`;用户修改后点击重新生成,后端同时生成纯背景图和容器 UI 图,并把新的 `backgroundAsset` 写回同一份 `generated_item_assets_json`UI 子 Tab 还必须提供独立的运行态 UI 预览面板直接用当前纯背景图、容器 UI 图、顶部返回/倒计时/重开控件和底部默认托盘模拟竖屏页面,不在 Tab 下方内联展开。
3. `背景音乐`:承载原一级音乐 Tab 的背景音乐曲名、风格、生成进度和试听控件;背景音乐始终按纯音乐生成,前端不提供提示词输入
1. `物品`:显示 2D 物品素材列表、五视角预览素材名称点击音效提示词与生成入口已临时隐藏
2. `UI`:预览生成的竖屏游戏纯背景图,并在独立运行态 UI 预览面板中叠加当前中心容器形象。背景读取顺序为 draft 顶层背景、draft `generatedBackgroundAsset`、profile 顶层背景、profile `generatedBackgroundAsset``generatedItemAssets[].backgroundAsset`、本地兜底图;容器读取 `generatedItemAssets[].backgroundAsset.containerImageSrc/containerImageObjectKey`,缺失时使用默认圆形容器。该页必须展示默认画面描述提示词,默认值来自草稿生成计划的 `backgroundPrompt` 或持久化 `backgroundAsset.prompt`;用户修改后点击重新生成,先弹出 `确认消耗泥点` 面板并展示 `消耗 2 泥点`,确认后调用 `POST /api/creation/match3d/works/{profileId}/background-image`,现阶段后端仍会同时生成纯背景图和容器 UI 图,并把新的 `backgroundAsset` 写回同一份 `generated_item_assets_json`确认后按钮区域必须显示生成进度条,按 `90` 秒估算倒计时后端真实返回后立即收口。UI 子 Tab 的预览面板直接用当前纯背景图、容器 UI 图、顶部返回/倒计时/重开控件和底部默认托盘模拟竖屏页面,不在 Tab 下方内联展开。
3. `容器形象`:预览和重新生成 `1:1` 中心容器 UI 图,页面能力与 `UI` 子 Tab 对齐,包含方形容器预览、容器提示词输入、独立运行态 UI 预览面板、泥点确认和生成进度。默认提示词来自持久化 `backgroundAsset.containerPrompt`,缺失时从当前题材、作品描述和容器参考约束生成兜底提示词;用户修改后点击重新生成,先弹出 `确认消耗泥点` 面板并展示 `消耗 2 泥点`,确认后调用 `POST /api/creation/match3d/works/{profileId}/container-image`,按钮区域同样按 `90` 秒估算显示倒计时进度。该接口只重新生成并写回 `backgroundAsset.containerPrompt/containerImageSrc/containerImageObjectKey`,必须保留已有纯背景 `prompt/imageSrc/imageObjectKey`、物品素材、历史背景音乐和点击音效字段,避免用户只换容器时刷新掉背景图或物品素材
旧一级 `音乐` Tab 删除;抓大鹅背景音乐入口只保留在 `素材配置 > 背景音乐`
旧一级 `音乐` Tab 删除;`素材配置 > 背景音乐` 当前也不展示
`素材配置 > 物品` 详情页只保留:
1. 五视角预览区:优先展示 `imageViews[]`,缺失时展示兼容字段 `imageSrc/imageObjectKey`
2. 素材名称输入。
3. 可编辑的点击音效提示词输入。
4. 点击音效生成入口。
3. 不展示点击音效提示词输入或点击音效生成入口
五视角预览区采用“上方大预览 + 底部缩略图栏”的布局:上方是方形焦点预览区,中间横向排列当前物品的各视角图片,并用内框标出当前焦点;底部缩略图栏固定露出 `4` 个方形槽位,多出的第 `5` 个视角通过横向滚动访问。点击缩略图只切换焦点视角,不在面板内新增说明文案或额外规则区。
详情页不再展示参考图、用途、模型提示词、文生/图生切换、状态查询、下载列表、taskUuid 或 subscriptionKey。
`物品素材` 列表项点击必须弹出独立预览面板,不允许在列表右侧或列表下方内联展示。列表本身使用移动端至少两列的多列卡片布局;每个列表项只展示图片预览、物品名称和垃圾箱删除图标,不展示用途、状态胶囊、视角数量或 `2D素材` 标记。预览面板只承担查看五视角图片编辑素材名称、编辑点击音效提示词和生成点击音效;不再展示 `重新生成` 按钮。列表项自身支持单项删除,删除后立即把剩余 `generatedItemAssets` 写回作品 profile。批量新增通过列表顶部按钮打开独立面板面板内每个输入框只输入一个物品名称`新增物品名称` 按钮追加一个输入框;提交后按输入框顺序清洗、去重并调用 Match3D 作品批量生图接口。生成进度同时显示在批量新增面板和 `素材配置 > 物品` 列表顶部,面板可关闭,后台生成继续推进,不阻塞封面、音频等其他生成操作。后端复用草稿生成的素材图、切图OSS 上传和可选点击音效流程,但仅按实际可新增名称持久化,不重新生成已有物品不新增 SpacetimeDB 表,最终仍写回同一份 `generated_item_assets_json`。批量新增先补齐到 `5` 个参与整图生成,随后丢弃补齐用临时物品,只对真实新增物品抠背景、切割和上传。批量新增计费按实际新增名称每 `5` 个消耗 `2` 泥点,不足 `5` 个向上取整;重复名称、已有名称和超过容量上限的名称不计费。
`物品素材` 列表项点击必须弹出独立预览面板,不允许在列表右侧或列表下方内联展示。列表本身使用移动端至少两列的多列卡片布局;每个列表项只展示图片预览、物品名称和垃圾箱删除图标,不展示用途、状态胶囊、视角数量或 `2D素材` 标记。预览面板只承担查看五视角图片编辑素材名称;不再展示单项 `重新生成` 按钮。列表项自身支持单项删除,删除后立即把剩余 `generatedItemAssets` 写回作品 profile。批量新增通过列表顶部按钮打开独立面板面板内每个输入框只输入一个物品名称`新增物品名称` 按钮追加一个输入框;提交按钮点击后必须先弹出 `确认消耗泥点` 面板并展示按当前有效名称计算出的泥点数,用户确认后才按输入框顺序清洗、去重并调用 Match3D 作品批量生图接口。批量重新生成通过列表顶部另一个按钮打开独立面板,面板预填当前全部素材名称,用户可清空不需要重新生成的输入框;提交按钮点击后同样先弹出泥点确认面板,确认后按输入框顺序清洗、去重并以替换模式调用同一接口。生成进度同时显示在批量面板和 `素材配置 > 物品` 列表顶部,面板可关闭,后台生成继续推进,不阻塞封面或 UI 生成操作。后端复用草稿生成的素材图、切图OSS 上传流程,但新增模式仅按实际可新增名称持久化,不重新生成已有物品;替换模式仅按实际匹配到的已有名称持久化,不新增物品、不改变 `itemId`。两者都不新增 SpacetimeDB 表,最终仍写回同一份 `generated_item_assets_json`。批量新增和批量重新生成都先补齐到 `5` 个参与整图生成,随后丢弃补齐用临时物品,只对真实新增或真实替换物品抠背景、切割和上传。计费按实际新增或替换名称每 `5` 个消耗 `2` 泥点,不足 `5` 个向上取整;重复名称、已有名称、未匹配名称和超过容量上限的名称不计费。
## 6.1 音频生成与扣费
抓大鹅结果页音频生成复用通用创作音频路由
抓大鹅结果页音频生成当前临时关闭
1. `素材配置 > 背景音乐` 默认读取首个 `generatedItemAssets[0].backgroundMusicTitle/backgroundMusicStyle`,用户可继续编辑曲名和风格;`backgroundMusicPrompt` 保留为空字符串兼容旧 JSON生成请求固定传空 `prompt`
2. 物品点击音效默认读取对应 `generatedItemAssets[].soundPrompt`,用户可在 `素材配置 > 物品` 详情面板内编辑
3. 背景音乐与物品音效生成过程必须显示进度条;提交任务、等待生成、转存资产和完成分别推进到不同进度,不再只展示旋转图标
4. 音频生成完成后立即展示浏览器原生 audio 控件,支持试听
5. `POST /api/creation/audio/background-music/{task_id}/asset``POST /api/creation/audio/sound-effect/{task_id}/asset` 在真正拿到音频并转存资产前,由后端按 `taskId + 资产槽位` 幂等预扣;背景音乐扣 `5` 泥点,物品点击音效扣 `10` 泥点。任务仍在处理中时不扣费。资产下载、OSS 转存或资产绑定失败时后端自动退款。前端只展示生成按钮和进度,不自行计算或写入钱包。
1. `素材配置 > 背景音乐` 不展示
2. `素材配置 > 物品` 详情面板不展示点击音效提示词和生成入口
3. 通用 `/api/creation/audio/*` 路由对 `match3d_work` / `match3d_item` 暂时返回 `410 Gone`,防止旧前端或脚本继续触发抓大鹅扣费音频任务
4. 历史 `generatedItemAssets[].backgroundMusic``clickSound` 字段保留,运行态仍可消费旧音频;结果页不提供重新生成入口
创作入口不展示 `生成音效` Toggle。草稿生成阶段不产生物品点击音效任务也不产生点击音效相关扣费;入口只产生一次固定 `10` 泥点的草稿生成扣费。结果页 `素材配置 > UI` 重新生成背景固定扣 `2` 泥点。物品点击音效由结果页 `素材配置 > 物品` 详情面板手动触发,每个音效按单独任务和单独 `match3d_click_sound` 资产槽位扣费。音效生成失败不影响草稿,失败素材保留 `soundPrompt`,用户可在结果页物品详情面板手动重试
创作入口不展示 `生成音效` Toggle。草稿生成阶段不产生背景音乐或物品点击音效任务,也不产生音频相关扣费;入口只产生一次固定 `10` 泥点的草稿生成扣费。结果页 `素材配置 > UI` 重新生成背景固定扣 `2` 泥点`素材配置 > 容器形象` 单独重新生成容器同样固定扣 `2` 泥点
## 7. 验收
@@ -238,4 +248,4 @@ cargo check -p spacetime-client --manifest-path server-rs\Cargo.toml
cargo check -p spacetime-module --manifest-path server-rs\Cargo.toml
```
真实草稿生成需要本地私密环境配置 `APIMART_BASE_URL` / `APIMART_API_KEY` / `APIMART_IMAGE_REQUEST_TIMEOUT_MS` 用于物品素材 sheet,配置 `VECTOR_ENGINE_BASE_URL` / `VECTOR_ENGINE_API_KEY` 用于封面、背景和容器 UI补齐完整 `ALIYUN_OSS_BUCKET``ALIYUN_OSS_ENDPOINT``ALIYUN_OSS_ACCESS_KEY_ID``ALIYUN_OSS_ACCESS_KEY_SECRET`。如果只配置 bucket 和 endpoint抓大鹅素材、封面或背景生成会在调用外部生图前返回 `OSS 未完成环境变量配置``details.missingEnv` 会列出缺少的 AccessKey 项;不要回退到 Rodin/GLB 或伪造本地上传成功。开启音频生成还需要对应音频上游配置。后端改动后使用 `npm run api-server` 启动,并检查 `/healthz`
真实草稿生成需要本地私密环境配置 `VECTOR_ENGINE_BASE_URL` / `VECTOR_ENGINE_API_KEY` / `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS`;其中物品素材 sheet 走 VectorEngine Gemini 原生 `generateContent`,封面和 `9:16` 纯背景走 VectorEngine `/v1/images/generations` `gpt-image-2-all` JSON 链路,`1:1` 容器 UI 走 VectorEngine `/v1/images/edits` multipart 参考图链路。同时必须补齐完整 `ALIYUN_OSS_BUCKET``ALIYUN_OSS_ENDPOINT``ALIYUN_OSS_ACCESS_KEY_ID``ALIYUN_OSS_ACCESS_KEY_SECRET`。如果只配置 bucket 和 endpoint抓大鹅素材、封面或背景生成会在调用外部生图前返回 `OSS 未完成环境变量配置``details.missingEnv` 会列出缺少的 AccessKey 项;不要回退到 Rodin/GLB 或伪造本地上传成功。临时关闭期间不需要音频上游配置。后端改动后使用 `npm run api-server` 启动,并检查 `/healthz`

View File

@@ -18,7 +18,7 @@
1. 入口表单只展示 `画面描述`、参考图和图片模型选择;`画面描述` 是唯一必填字段。
2. 表单自动保存只保存 `pictureDescription`,不再保存入口作品名称、作品描述或推断标签。
3. 点击“生成草稿”后进入生成进度页,步骤固定对齐后端当前编排:“编译首关草稿 -> 生成关卡名称 / 生成首关画面 -> 生成背景音乐 / 生成UI背景 -> 写入正式草稿”。其中关卡名称文本生成与首关画面生成可并行;首关最终名称确定后,背景音乐与 UI 背景必须并行启动
3. 点击“生成草稿”后进入生成进度页,步骤固定对齐后端当前编排:“编译首关草稿 -> 生成关卡名称与 UI 背景提示词 / 生成首关画面 -> 生成UI背景 -> 写入正式草稿”。其中关卡名称文本生成、UI 背景提示词生成与首关画面生成可并行;首关最终名称确定后生成 UI 背景。背景音乐生成已于 2026-05-14 临时关闭
4. 生成进度页“当前拼图信息”只展示画面描述;不得展示空作品名称、空作品描述或旧五锚点结构。
5. 结果页打开后,作品名称默认使用首关名称,作品描述与作品标签保持为空,等待用户在作品信息 Tab 补全或触发 AI 标签生成。
@@ -90,8 +90,8 @@
12. `compile_puzzle_draft` 中的图片上游失败不得映射成 `400 BAD_REQUEST`。DashScope 返回 `InvalidParameter` 或任务失败时api-server 统一按 `502 UPSTREAM_ERROR` 暴露,并在 `details.message` 中保留“拼图图片生成失败:...”的业务原因,避免生成页只显示“请求参数不合法”。
13. `compile_puzzle_draft` 前置泥点预扣失败不得映射成 `400 BAD_REQUEST`。余额不足返回 `409 CONFLICT`SpacetimeDB procedure 不可用、绑定不匹配、钱包服务异常等统一按 `502 UPSTREAM_ERROR` 暴露,并在 `details.message` 中保留真实钱包错误。
14. 生成拼图作品草稿动作涉及的表单 seed prompt 与首图 prompt 来源选择统一收口在 `server-rs/crates/api-server/src/prompt/puzzle/draft.rs``puzzle.rs` 只负责调用 SpacetimeDB、计费、图片服务和持久化不再直接拼草稿 prompt 文本。
15. `compile_puzzle_draft_with_initial_cover` 中,首关文本名称生成与首关图片生成互不等待:首图 prompt 只读取画面描述OSS 临时路径使用已有名或确定性兜底名;首图返回后再用图片语义尝试精修最终关卡名。最终关卡名确定后,必须继续生成首关 UI 背景图与背景音乐,并在写入正式草稿前校验 `levels[0].uiBackgroundImageSrc/uiBackgroundImageObjectKey` `levels[0].backgroundMusic.audioSrc` 都不为空;任一资产失败时 `compile_puzzle_draft` 返回上游错误,生成页停留失败态,不能返回一个显示“暂无音乐”或默认 UI 的成功草稿
16. `compile_puzzle_draft_with_uploaded_cover` 中,上传图解析后,文本名称生成、图片语义名称生成和上传图转存 OSS 可并行;上传图转存失败必须立即返回,不得继续触发背景音乐或 UI 背景生成。上传图转存成功且最终关卡名确定后,同样必须生成并校验首关 UI 背景图与背景音乐。自动草稿阶段先生成 UI 背景,再生成会单独扣费的音乐资产,避免 UI 失败后留下未写入草稿的已扣费音频
15. `compile_puzzle_draft_with_initial_cover` 中,首关文本名称生成与首关图片生成互不等待:首图 prompt 只读取画面描述OSS 临时路径使用已有名或确定性兜底名;同一次首关命名 LLM 请求必须返回 `levelName``uiBackgroundPrompt`首图返回后再用图片语义尝试精修最终关卡名与 UI 背景提示词。最终关卡名确定后,必须继续用 AI 返回的 `uiBackgroundPrompt` 生成首关 UI 背景图;若命名模型未返回可用提示词,才按作品、关卡和标签拼接确定性兜底提示词。写入正式草稿前校验 `levels[0].uiBackgroundImageSrc/uiBackgroundImageObjectKey` 不为空UI 背景失败时 `compile_puzzle_draft` 返回上游错误,生成页停留失败态。背景音乐生成临时关闭,不再作为草稿完成门槛
16. `compile_puzzle_draft_with_uploaded_cover` 中,上传图解析后,文本名称生成、图片语义名称生成和上传图转存 OSS 可并行;上传图转存失败必须立即返回,不得继续触发 UI 背景生成。上传图转存成功且最终关卡名确定后,同样必须生成并校验首关 UI 背景图。自动草稿阶段不再触发音乐资产生成
## 结果页
@@ -99,22 +99,24 @@
1. 拼图关卡列表:默认展示草稿生成出的第一关。列表项参考 RPG 草稿卡片样式,显示画面图、关卡名称和轻量状态。支持新增关卡、删除关卡。点击列表项进入独立关卡详情页,不在列表项下方展开。关卡详情页可编辑关卡名称、画面描述、生成或重新生成画面,并在已有正式图后支持关卡测试。
2. 作品信息:展示并编辑作品名称、作品描述、作品标签。
3. 素材配置:对齐抓大鹅草稿页结构,内部包含 `UI` `背景音乐` 子 Tab。
3. 素材配置:对齐抓大鹅草稿页结构,当前只包含 `UI` 子 Tab`背景音乐` 子 Tab 已临时隐藏
`素材配置 > UI` 展示并编辑拼图运行态 UI 背景提示词。`compile_puzzle_draft` 草稿编译完成首图和背景音乐后,`api-server`基于作品名称、作品描述、标签和首关信息自动生成首关 9:16 纯背景图;结果页继续支持用户修改提示词并通过 `generate_puzzle_ui_background` 重新生成。图片生成调用 VectorEngine `gpt-image-2-all``9:16` 图片生成链路。生成结果写入首关 `levels_json``uiBackgroundPrompt``uiBackgroundImageSrc``uiBackgroundImageObjectKey`,不新增 SpacetimeDB 表字段。
`素材配置 > UI` 展示并编辑拼图运行态 UI 背景提示词。`compile_puzzle_draft` 草稿编译完成首图后,`api-server`优先使用首关命名 LLM 同次返回的 `uiBackgroundPrompt` 自动生成首关 9:16 纯背景图;只有模型未返回可用提示词时,才基于作品名称、作品描述、标签和首关信息拼接兜底提示词。结果页继续支持用户修改提示词并通过 `generate_puzzle_ui_background` 重新生成。图片生成调用 VectorEngine `gpt-image-2-all``9:16` 图片生成链路。生成结果写入首关 `levels_json``uiBackgroundPrompt``uiBackgroundImageSrc``uiBackgroundImageObjectKey`,不新增 SpacetimeDB 表字段。
`素材配置 > 背景音乐` 编辑并生成背景音乐,音乐资产暂存到首关 `levels_json[0].backgroundMusic`。拼图结果页不再保留一级 `UI` 或一级 `音乐` Tab。
历史 `levels_json[0].backgroundMusic` 字段继续兼容读取和运行态播放,但结果页暂不提供编辑或生成入口。拼图结果页不再保留一级 `UI` 或一级 `音乐` Tab。
### 2026-05-12 UI 背景生成补充
1. UI 背景图只生成拼图运行态的题材氛围纯背景不得把拼图槽、棋盘外框、按钮、HUD 或其它 UI 元素烘进图片。拼图槽位、棋盘边框和空格继续使用运行态默认样式绘制。
2. UI 背景图不得生成文字、水印、按钮文字、数字、拼图碎片、完整拼图图像、教程浮层、拼图槽或物品槽,避免与真实拼图图块和运行态 HUD 混淆。
3. 结果页 UI Tab 支持直接修改提示词并重新生成;点击生成前会把本地首关 `uiBackgroundPrompt` 同步进 `levelsJson`,使自动保存尚未完成时后端仍能拿到最新提示词。
3. 结果页 UI Tab 支持直接修改提示词并重新生成;点击生成前必须先弹出 `确认消耗泥点` 面板并展示 `消耗 2 泥点`,确认后会把本地首关 `uiBackgroundPrompt` 同步进 `levelsJson`,使自动保存尚未完成时后端仍能拿到最新提示词。
4. 草稿编译阶段自动生成 UI 背景失败时必须让 `compile_puzzle_draft` 失败并停留在生成页;不能保留一个成功状态但缺少 UI 背景的草稿。只有结果页内用户主动点击 `生成UI背景``重新生成` 时,失败才作为当前面板错误展示,由用户手动重试。
5. `api-server` 负责拼接生成 prompt、调用 VectorEngine、下载并转存 OSSSpacetimeDB 只通过 `save_puzzle_ui_background` procedure 保存结果,不做外部 I/O。
6. 拼图运行态读取 `currentLevel.uiBackgroundImageSrc` 渲染为全屏背景;无 UI 背景图时继续使用原封面模糊背景兜底。棋盘本身仍由正式拼图图生成,不能把 UI 背景当作拼图切块来源。
7. 生成完成后的自动试玩和结果页“试玩”走前端本地运行态兜底时,`startLocalPuzzleRun` 也必须从 `PuzzleWorkSummary.levels[]` 复制 `uiBackgroundImageSrc``backgroundMusic``currentLevel`;不得只带 `coverImageSrc`,否则草稿结果页有背景但试玩局内空白。
6. 拼图运行态读取 `currentLevel.uiBackgroundImageSrc` 渲染为全屏背景;`uiBackgroundImageSrc` 为空,则必须回退读取 `uiBackgroundImageObjectKey` 并交给 `/api/assets/read-url` 换签;无 UI 背景图时继续使用原封面模糊背景兜底。棋盘本身仍由正式拼图图生成,不能把 UI 背景当作拼图切块来源。
7. 生成完成后的自动试玩和结果页“试玩”走前端本地运行态兜底时,`startLocalPuzzleRun` 也必须从 `PuzzleWorkSummary.levels[]` 复制 `uiBackgroundImageSrc` / `uiBackgroundImageObjectKey``backgroundMusic``currentLevel`;不得只带 `coverImageSrc`,否则草稿结果页有背景但试玩局内空白。
8. 结果页在本地关卡处于 `generationStatus = generating` 时合并后端生成完成回包,必须同时合并 `uiBackgroundPrompt``uiBackgroundImageSrc``uiBackgroundImageObjectKey``backgroundMusic`。若只合并图片字段而漏掉音乐字段,随后自动保存会把空 `backgroundMusic` 写回 `puzzle_work_profile.levels_json`,导致素材配置显示“暂无音乐”并让自动试玩/试玩局内无音乐。
9. 结果页手动点击 `生成UI背景` / `重新生成` 时,如果目标 SpacetimeDB wasm 尚未发布到包含 `consume_profile_wallet_points_and_return``refund_profile_wallet_points_and_return``save_puzzle_ui_background` 的版本,`api-server` 必须把 `No such procedure` 视为后端版本漂移泥点预扣阶段降级跳过扣费UI 背景已经生成但保存失败时返回本次内存合成草稿快照,不能把原始 `No such procedure` 暴露到草稿页。该容错只保证当前页面可见本次图片;刷新后要稳定恢复仍必须重新发布最新 SpacetimeDB module 并重新生成 bindings。
10. 结果页 `UI背景提示词` 文本框只能展示后端已持久化的 `levels[0].uiBackgroundPrompt` 或用户正在编辑的本地值;后端字段为空时不得把前端兜底提示词直接填入文本框,避免把兜底模板误展示成 AI 已生成提示词。点击生成时仍可用同一兜底提示词作为空输入兜底。
### 2026-05-12 草稿生成完成自动试玩补充
@@ -145,7 +147,7 @@
1. 关卡详情页的 `画面图``画面描述` 模块对齐入口页拼图表单:画面图使用稳定正方形图卡,画面描述使用固定高度输入区并保留图片模型选择。
2. 新建关卡或无正式图关卡也展示 `画面图` 图卡;空图态只保留图标化占位和生成中状态,不追加规则说明文案。
3. 关卡详情页删除手填 `参考图链接或资产ID` 输入框。参考图只能通过本地上传或历史拼图素材选择进入本次生成请求;字段 `levels[].pictureReference` 继续作为后端生成后的复用字段透传,不作为用户可手填表单项。
4. 单关生成等待估算从 `30` 秒调整为 `90` 秒;生成按钮内展示小字 `等待时间可以制作更多关卡哦~`,不得另起说明面板。
4. 单关生成等待估算从 `30` 秒调整为 `90` 秒;生成按钮内展示小字 `等待时间可以制作更多关卡哦~`,不得另起说明面板。点击 `生成画面` / `重新生成画面` 前必须先弹出 `确认消耗泥点` 面板并展示 `消耗 2 泥点`
5. 触发某一关生成时,前端必须立即把该关 `generationStatus` 标为 `generating` 并随当前 `levelsJson` 写入草稿自动保存链路;后端生成完成后再写回 `ready`
6. `generationStatus = generating` 的关卡在详情弹窗关闭后仍保留进度展示,再次打开同一关详情能继续看到生成进度;关卡列表卡片也必须展示生成中的轻量状态。
7. 单关图片生成必须作为后台 action 执行,不占用拼图结果页全局 busy 状态;生成期间仍允许编辑作品信息、编辑关卡、新增关卡、删除其他关卡、关卡测试和继续触发其他可并行动作。
@@ -157,9 +159,9 @@
## 验收
1. 从拼图创作入口只能看到作品名称、作品描述、画面描述和参考图上传,不出现 Agent 聊天输入、补齐设定、锚点问答。
2. 点击确认后进入拼图草稿生成进度页,并自动完成草稿编译、首图生成、正式图选择、背景音乐生成和首关 UI 背景图生成。
2. 点击确认后进入拼图草稿生成进度页,并自动完成草稿编译、首图生成、正式图选择和首关 UI 背景图生成。
3. 首图生成请求使用玩家画面描述作为 prompt上传参考图时走图生图作品详情页展示玩家作品描述。
4. 结果页包含“拼图关卡”“作品信息”“素材配置”三个一级 Tab`素材配置` 内包含 `UI` `背景音乐` 子 Tab。关卡列表默认至少一关,支持新增、删除和进入关卡详情。
4. 结果页包含“拼图关卡”“作品信息”“素材配置”三个一级 Tab`素材配置`当前只包含 `UI` 子 Tab不展示背景音乐生成入口。关卡列表默认至少一关,支持新增、删除和进入关卡详情。
5. 关卡详情页支持生成或重新生成画面;已有正式图后显示吸底“关卡测试”入口。
6. 发布、作品测试、自动保存作品名称、作品描述、作品标签和关卡列表仍可用。
7. 草稿初次生成后首关默认带 `uiBackgroundImageSrc`UI Tab 可修改提示词并重新生成背景图;生成后运行态应显示 `uiBackgroundImageSrc`,拼图槽位和棋盘边界仍由默认运行态样式绘制。
7. 草稿初次生成后首关默认带 `uiBackgroundImageSrc`若后端只返回 `uiBackgroundImageObjectKey` 也必须能在结果页、试玩和运行态正常预览;UI Tab 可修改提示词并重新生成背景图;生成后运行态应显示 `uiBackgroundImageSrc` 或换签后的 `uiBackgroundImageObjectKey`,拼图槽位和棋盘边界仍由默认运行态样式绘制。

View File

@@ -1,20 +1,33 @@
# 拼图与抓大鹅结果页音乐入口 2026-05-11
> 2026-05-14 临时关闭:拼图与抓大鹅草稿生成阶段不再自动生成背景音乐;拼图结果页 `素材配置` 只保留 `UI` 子 Tab抓大鹅结果页 `素材配置` 只保留 `物品` 与 `UI` 子 Tab物品详情不展示点击音效生成入口。通用 `/api/creation/audio/*` 路由对拼图与抓大鹅目标暂时返回 `410 Gone`;视觉小说专用音频路由不受本次关闭影响。
## 0. 2026-05-14 临时关闭口径
拼图与抓大鹅的创作音频生成入口暂时关闭:
1. 拼图草稿编译阶段不再自动生成背景音乐,只生成首图与 UI 背景。
2. 抓大鹅草稿编译阶段不再自动生成背景音乐,也不再生成物品点击音效。
3. 拼图结果页 `素材配置` 只保留 `UI` 子 Tab隐藏 `背景音乐` 子 Tab 与重新生成入口。
4. 抓大鹅结果页 `素材配置` 只保留 `物品``UI` 子 Tab物品详情隐藏点击音效生成入口。
5. 通用 `/api/creation/audio/*` 路由对拼图与抓大鹅目标暂时返回 `410 Gone`;视觉小说专用音频路由保持可用。
6. 既有草稿或作品中的 `backgroundMusic` / `clickSound` 字段不清空,运行态仍按历史兼容逻辑播放已存在的音频。
## 1. 范围
本方案 VectorEngine 音频生成能力从视觉小说结果页扩展到拼图与抓大鹅结果页:
本方案记录 VectorEngine 音频生成能力从视觉小说结果页扩展到拼图与抓大鹅结果页;当前拼图与抓大鹅入口已临时关闭
1. 拼图结果页 `素材配置 > 背景音乐` 中支持通过 Suno 生成作品背景音乐;旧一级 `音乐` Tab 删除。
2. 抓大鹅结果页 `素材配置 > 背景音乐` 中支持通过 Suno 生成作品背景音乐;旧一级 `音乐` Tab 删除。
3. 抓大鹅 `素材配置 > 物品` 支持为每个生成物体通过 Vidu 手动生成点击音效;创作入口不展示点击音效生成开关
1. 拼图结果页不展示 `素材配置 > 背景音乐`旧一级 `音乐` Tab 继续删除。
2. 抓大鹅结果页不展示 `素材配置 > 背景音乐`旧一级 `音乐` Tab 继续删除。
3. 抓大鹅 `素材配置 > 物品` 详情面板不展示点击音效生成入口
4. 拼图运行态与抓大鹅运行态内置默认关卡音频配置:通用点击音效 `/audio/ui-click-soft.wav`、过关音效 `/audio/ui-level-clear.wav`、倒计时临界音效 `/audio/ui-countdown-warning.wav`
5. 拼图和抓大鹅草稿生成阶段会自动生成背景音乐并转存 OSS结果页继续支持试听和重新生成。
5. 拼图和抓大鹅草稿生成阶段生成背景音乐,也不因缺少背景音乐阻塞草稿完成。
本轮不新增 SpacetimeDB 表,不修改表字段,不把供应商密钥下发到前端。
## 2. 通用音频接口
后端在既有视觉小说音频路由外新增通用创作音频路由:
后端在既有视觉小说音频路由外新增通用创作音频路由。临时关闭期间,以下通用路由保留;对拼图或抓大鹅目标直接返回 `410 Gone`,不得被拼图或抓大鹅入口继续调用
| 方法 | 路由 | 用途 |
| --- | --- | --- |
@@ -32,7 +45,7 @@
5. 确认 `asset_object` 并绑定 `asset_entity_binding`
6. 音频真正可下载并准备转存时,按 `taskId + assetKind + entityId + slot` 幂等扣费;背景音乐固定扣除 `5` 泥点,物品点击音效固定扣除 `10` 泥点。任务仍在处理中不扣费,转存或资产绑定失败自动退款。
通用背景音乐提交允许 `prompt = ""`拼图和抓大鹅草稿生成都按纯音乐处理:后端提交 Suno 时固定带 `make_instrumental = true`,只用 `title``tags` 约束作品气质,不把歌词或规则描述写入 prompt。视觉小说路由保持兼容,内部继续复用同一套提交、轮询、转存逻辑。
通用背景音乐提交历史上允许 `prompt = ""`当前通用创作音频入口被后端显式熔断,不能通过该路由继续提交或转存音频。视觉小说专用路由保持兼容,内部继续复用同一套提交、轮询、转存逻辑。
## 3. 数据落点
@@ -53,7 +66,7 @@
}
```
草稿生成阶段在生成首关作品题目后,使用作品题目作为 Suno `title``prompt` 为空,`tags` 使用轻快、拼图、循环、instrumental。自动草稿编译必须拿到可播放的 `backgroundMusic.audioSrc` 后才返回成功;生成失败应返回上游错误并停留在生成页,不能进入结果页后显示“暂无音乐”。运行态从 `PuzzleRuntimeLevelSnapshot.backgroundMusic.audioSrc` 读取该字段作为背景音乐源,游戏开始后自动循环播放;历史草稿或手动删除音乐时字段为空,则保持静默背景音乐兜底。
当前草稿生成阶段跳过背景音乐生成;自动草稿编译只校验首图与 UI 背景。运行态仍兼容历史 `PuzzleRuntimeLevelSnapshot.backgroundMusic.audioSrc`,旧草稿若已有音乐可继续播放;新草稿默认保持静默背景音乐兜底。
### 3.2 抓大鹅
@@ -62,18 +75,16 @@
1. 作品背景音乐暂存到第一个 `Match3DGeneratedItemAsset.backgroundMusic`,表示当前 work profile 的作品级背景音乐。
2. 单个物体点击音效保存到对应 `Match3DGeneratedItemAsset.clickSound`
这是一个兼容性折中:当前 Match3D work profile 没有 work-level metadata 字段,而 `generated_item_assets_json` 已经随作品详情、草稿架、运行态入口稳定传递。草稿生成阶段的文本计划在生成物品名称时同步生成 `backgroundMusic.title` 作为背景音乐名称,`backgroundMusic.prompt` 固定为空字符串,后端用该名称作为 Suno `title` 并生成纯音乐。自动草稿编译必须把生成后的 `backgroundMusic.audioSrc` 写回首个素材后才返回成功;若 Suno 提交、轮询、下载、OSS 转存或资产绑定失败,本次草稿生成返回失败并允许用户重试同一 session/profile。后续若新增正式作品 metadata 表达,应迁移 `backgroundMusic` 到作品级字段。
这是一个兼容性折中:当前 Match3D work profile 没有 work-level metadata 字段,而 `generated_item_assets_json` 已经随作品详情、草稿架、运行态入口稳定传递。当前草稿生成阶段不再生成 `backgroundMusic``clickSound`;历史草稿中已有字段仍按旧兼容逻辑传递到运行态。后续若重新打开音频能力或新增正式作品 metadata 表达,应迁移 `backgroundMusic` 到作品级字段。
## 4. 前端交互
结果页 UI 保持轻量:
1. 拼图 `素材配置 > 背景音乐` 与抓大鹅 `素材配置 > 背景音乐` 只展示必要输入、生成按钮、状态音频预览,不展示供应商规则说明
1. 拼图与抓大鹅结果页暂不展示背景音乐生成输入、生成按钮、状态音频预览。
2. 生成完成后立即写回本地草稿状态,并触发既有保存链路或专用保存接口。
3. 抓大鹅每个物体音效生成入口放在对应素材详情面板内,不在列表下方展开大段配置
4. 抓大鹅物体音效提示词允许在素材详情面板内编辑;背景音乐只允许在 `素材配置 > 背景音乐` 编辑曲名和风格,生成请求固定使用空 `prompt`
5. 背景音乐和物体音效生成期间都显示进度条,生成完成后展示 audio 控件试听。
6. 背景音乐重新生成只要求曲名非空;重新生成继续按纯音乐提交,`prompt = ""`,按钮展示 `5` 泥点成本。
3. 抓大鹅每个物体详情面板只保留素材查看和名称编辑,不展示音效提示词或生成入口
4. 若历史素材已有 `backgroundMusic``clickSound`,结果页不提供重新生成入口;试玩和运行态仍可消费已存在字段
### 4.1 运行态默认点击音效
@@ -89,11 +100,11 @@
2026-05-13 修正:
1. 拼图 `素材配置 > 背景音乐` 的试听控件必须通过 `useResolvedAssetReadUrl` 对 generated legacy path 换签后再设置 `<audio src>`;签名未就绪或失败时只显示“音频已绑定”,不得把裸 `/generated-puzzle-assets/...` 路径交给浏览器请求
2. 抓大鹅结果页已使用同一换签口径,后续新增音频试听入口必须复用该模式
1. 拼图 `素材配置 > 背景音乐` 的试听控件当前隐藏;后续恢复时必须通过 `useResolvedAssetReadUrl` 对 generated legacy path 换签后再设置 `<audio src>`
2. 抓大鹅结果页后续恢复音频试听入口必须复用同一换签口径,不能把裸 `/generated-match3d-assets/...` 音频路径直接交给 `<audio>`
3. 拼图和抓大鹅运行态在开局时会尝试自动播放背景音乐;若浏览器因自动播放策略拒绝,玩家首次按下拼图块或点击抓大鹅物品时必须再次调用同一个背景音乐播放函数,避免草稿音乐已经传入运行态但局内始终无声。
4. 播放失败仍只做静默兜底,不弹出规则说明或阻断局内交互。
5. 拼图结果页合并后端生成完成回包时,若本地首关仍处于 `generationStatus = generating`,必须 `backgroundMusic` 与候选图、正式图、UI 背景一起合并进编辑态;否则音乐面板会继续显示“暂无音乐”,后续自动保存还会把空音乐写回 profile
5. 拼图结果页合并后端生成完成回包时,若本地首关仍处于 `generationStatus = generating`,必须保留回包中的历史 `backgroundMusic` 字段,避免自动保存把旧音频覆盖为空;该字段不再驱动可见音乐面板
## 5. 验收

View File

@@ -4,6 +4,8 @@
拼图创作入口继续保留填表式体验,但入口表单不再要求陶泥儿主提前填写作品名称和作品描述。入口只收集“拼图画面描述”,后端用该描述完成首图生成和第一关关卡名生成;进入结果页后再补作品信息。
2026-05-14 起,拼图草稿阶段的背景音乐生成临时关闭,结果页也不再展示背景音乐入口。
## 入口表单
1. 点击“开始创作”后的拼图表单只展示 `画面描述`、参考图和图片模型选择。
@@ -17,15 +19,15 @@
1. `compile` 展示为“编译首关草稿”:建立结果页草稿,不在本步骤生成作品标签。
2. `puzzle-level-name` 展示为“生成关卡名称”:按画面描述生成文本名,首图返回后可再基于图像语义精修最终关卡名。
3. `puzzle-images` 展示为“生成首关画面”:按画面描述、参考图和当前图片模型生成第一张拼图图;后端允许该步骤与 `puzzle-level-name` 文本名生成并行。
4. `puzzle-background-music` 展示为“生成背景音乐”:最终关卡名确定后生成纯音乐并转存音频资产
5. `puzzle-ui-background` 展示为“生成UI背景”最终关卡名确定后生成 9:16 纯背景图;后端必须与背景音乐并行启动
6. `puzzle-select-image` 展示为“写入正式草稿”:把首图、最终关卡名、可用音乐和可用 UI 背景同步到结果页草稿。
4. 背景音乐步骤当前临时隐藏,不再执行
5. `puzzle-ui-background` 展示为“生成UI背景”最终关卡名确定后生成 9:16 纯背景图。
6. `puzzle-select-image` 展示为“写入正式草稿”:把首图、最终关卡名和可用 UI 背景同步到结果页草稿。
7. `ready` 文案提示进入结果页补作品信息;不得暗示作品名称、作品描述或作品标签已经完整生成。
### 2026-05-08 进度页预计等待与步骤动效补充
1. 拼图草稿生成进度页预计等待时间固定按 `60` 秒展示和倒计时,后端真实完成后立即进入结果页,不强制等满 60 秒。
2. 前端进度按本地时间展示为多段估算;后端真实编排中,首关名称文本生成与首关画面生成可并行,背景音乐与 UI 背景在最终关卡名确定后并行生成。进度条只是等待接口返回时的体验估算,不作为后端任务调度依据。
2. 前端进度按本地时间展示为多段估算后端真实编排中首关名称文本生成与首关画面生成可并行UI 背景在最终关卡名确定后生成。进度条只是等待接口返回时的体验估算,不作为后端任务调度依据。
3. 生成中即使后端 `compile_puzzle_draft` 仍是一次同步 action前端也必须按本地计时推进总进度和当前步骤进度避免页面停在静态等待态。
4. 每个步骤卡片都展示独立进度条;已完成步骤显示 100%,当前步骤按该段预计时长推进,后续步骤保留 0% 待处理状态。
5. 后端未返回前总进度最多推进到 98%,防止 UI 提前宣称生成完成;只有 action 成功并写回 `ready` 后才显示 100%。

View File

@@ -98,7 +98,7 @@ size = 1024x1024
- 已上传图片时,输入框标题为 `画面AI重绘要求提示词`
- 展示图片模型切换。
- `compile_puzzle_draft` 携带 `aiRedraw: true`,继续走 VectorEngine 生图与 `PUZZLE_IMAGE_GENERATION_POINTS_COST = 2` 扣费链路。
- 生成按钮展示 `消耗2泥点`
- 生成按钮展示 `消耗2泥点`,点击后必须先弹出 `确认消耗泥点` 面板并展示 `消耗 2 泥点`,用户确认后才调用生成动作
2. `AI重绘=false`
- 隐藏画面描述输入框和模型切换。
- 必须上传拼图图片,按钮不展示 `消耗2泥点`
@@ -126,7 +126,7 @@ Rust 共享契约使用 `ai_redraw: Option<bool>` 并按 camelCase 序列化为
3. 图片模型切换仍可打开并选择 `gpt-image-2` / `nanobanana2`
4. 历史模板样例图文件可保留,但不出现在拼图入口表单。
5. 当前创作 Tab 顶部的拼图、方洞挑战、视觉小说和 AIRP 卡片能看到对应 `creation-type-references` 图片。
6. 默认 `AI重绘` 打开时,无图状态展示 `画面描述``消耗2泥点`;上传图片后输入框标题改为 `画面AI重绘要求提示词`
6. 默认 `AI重绘` 打开时,无图状态展示 `画面描述``消耗2泥点`;上传图片后输入框标题改为 `画面AI重绘要求提示词`;点击生成前必须确认本次 `2` 泥点消耗
7. 关闭 `AI重绘` 后隐藏画面描述输入框,生成按钮不展示 `消耗2泥点`,后端直接应用上传图片为第一关图片。
8. 上传非 1:1 图片时必须先通过拖拽裁剪框完成正方形裁剪。
9. gpt-image-2 Skill 校验通过,且脚本 dry-run 能输出计划请求而不泄露密钥。

View File

@@ -22,7 +22,7 @@
- [AUTH_GATE_LOGIN_RACE_GUARD_FIX_2026-05-09.md](./AUTH_GATE_LOGIN_RACE_GUARD_FIX_2026-05-09.md):记录 `AuthGate` 登录成功后又被旧 hydrate 覆盖回未登录态的竞态根因、版本号保护修复与回归测试。
- [HYPER3D_RODIN_GEN2_MODEL_GENERATION_2026-05-08.md](./HYPER3D_RODIN_GEN2_MODEL_GENERATION_2026-05-08.md):记录 Hyper3D Rodin Gen-2 文生 3D 模型、图生 3D 模型、状态查询和下载列表的后端代理、环境变量、请求约束与验收边界。
- [MATCH3D_RODIN_ASSET_TAB_2026-05-10.md](./MATCH3D_RODIN_ASSET_TAB_2026-05-10.md):历史记录抓大鹅 Rodin 3D 素材列表/详情页的早期接入边界;当前新草稿不再调用 Rodin 或生成 GLB。
- [MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md](./MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md):冻结抓大鹅草稿生成过程页、按题材生成 UI 背景提示词、VectorEngine 2D 五视角素材、UI 背景图、背景音乐和 OSS 回填草稿页的端到端边界。
- [MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md](./MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md):冻结抓大鹅草稿生成过程页、按题材生成 UI 背景提示词、VectorEngine 2D 五视角素材、UI 背景图和 OSS 回填草稿页的端到端边界;背景音乐和点击音效生成当前临时关闭
- [VOLCENGINE_SPEECH_STREAMING_INTEGRATION_2026-05-08.md](./VOLCENGINE_SPEECH_STREAMING_INTEGRATION_2026-05-08.md):记录火山引擎大模型 ASR 双向流式、TTS WebSocket 双向流式和 TTS HTTP SSE 单向流式的后端代理、环境变量、协议帧和验收边界。
- [VECTOR_ENGINE_AUDIO_GENERATION_SUNO_VIDU_2026-05-08.md](./VECTOR_ENGINE_AUDIO_GENERATION_SUNO_VIDU_2026-05-08.md):记录视觉小说结果页接入 VectorEngine Suno 文生背景音乐与 Vidu 文生音效的接口、环境变量、后端路由、OSS 资产回写和前端弹层交互边界。
- [PROFILE_FEEDBACK_BACKEND_INTEGRATION_2026-05-08.md](./PROFILE_FEEDBACK_BACKEND_INTEGRATION_2026-05-08.md):冻结“我的”页签帮助与反馈入口的后端接入方案,覆盖 `POST /api/profile/feedback``profile_feedback_submission`、凭证图片 Data URL 校验和前端预览/提交边界。

View File

@@ -19,18 +19,18 @@
`useMocapInput` 解析 mocap `hands[].landmarks` 时应优先用 MediaPipe 21 点里的 `wrist / index_mcp / middle_mcp / ring_mcp / pinky_mcp` 加权计算掌心派生点;少于 3 个掌心关键点时才回退到 `wrist` 或直出 `hand.x/y`。这样运行态光标不会直接贴在腕部或指尖。
拼图运行态已接入该层:
2026-05-14 临时关闭:拼图运行态不再调用 `useMocapInput`,也不渲染 mocap 光标或调试面板。`src/services/input-devices/` 仍保留为鼠标 / 触控等输入的统一拖拽状态机mocap 解析能力继续供儿童动作 Demo 和宝贝识物等明确需要体感输入的玩法使用。
拼图运行态当前接入该层:
- 鼠标/触控 `pointerdown / pointermove / pointerup` 进入同一个 drag controller。
- mocap `grab` 进入同一个 drag controller并强制使用持续拖拽语义
- mocap 光标按 60Hz 插值更新 UI 位置,并在拖拽中用插值后的当前点持续驱动输入层,避免输入包帧率低或抖动时出现明显跳变。
- 合并大块由拼图运行态把手部坐标命中到任一成员拼块;本地拼图运行时再按 `mergedGroupId` 执行整组平移。
- 合并大块由拼图运行态把指针坐标命中到任一成员拼块;本地拼图运行时再按 `mergedGroupId` 执行整组平移
## 调试模式
前端全局调试模式统一通过 `src/config/debugMode.ts` 判断。默认跟随 Vite 开发态:`import.meta.env.DEV` 为真时开启,生产构建默认关闭;如需显式覆盖,可设置 `VITE_DEBUG_MODE=true``VITE_DEBUG_MODE=false`
拼图运行态 mocap 调试面板只在全局调试模式下渲染。面板默认折叠,只保留一行连接状态,展开后才显示动作、手势、解析告警和原始包预览,避免开发诊断信息遮挡拼图棋盘和底部操作
拼图运行态不再渲染 mocap 调试面板。需要排查 mocap 数据源时,应在仍消费 `useMocapInput` 的儿童动作 Demo 或宝贝识物运行态中验证数据链路
## 接入规则
@@ -40,7 +40,7 @@
2. 设备适配层只负责把原始输入转换成通用输入事件。
3. 玩法壳层负责从通用输入点解析本玩法目标,例如拼块、洞口、角色或实体。
4. 玩法壳层负责决定 drop 后调用哪个本地运行态函数或后端接口。
5. 需要取消输入时优先按 `inputId` 取消,避免 mocap 丢帧误伤正在进行的鼠标/触控会话。
5. 需要取消输入时优先按 `inputId` 取消,避免某一输入设备误伤正在进行的鼠标/触控会话。
## 验证