This commit is contained in:
2026-05-10 22:20:54 +08:00
parent d6219f1a0c
commit 192accd796
92 changed files with 7045 additions and 1559 deletions

View File

@@ -32,15 +32,15 @@
- 数据来源沿用 `featuredEntries + latestEntries` 去重后的公开作品列表。
- 首个可运行作品自动进入推荐页内嵌运行态,主视口不再展示作品封面卡。
- 主视口占据顶部栏与作品信息区之间的主要空间,使用平台主题 token 控制运行容器背景、边框、阴影、加载态文字和错误态按钮;亮色主题不得残留纯黑底白字加载块。
- 主视口下方展示当前作品的游玩、点赞、评论/改造等紧凑指标、作者头像、作者名作品名,不写规则说明类文案。
- 主视口下方展示当前作品操作区与基础信息:作者头像、作者名作品名、点赞按钮、点赞数、分享按钮、改造按钮;不展示游玩次数、评论入口或额外心形收藏入口,不写规则说明类文案。
- 作品信息区不再提供详情箭头或点击详情入口;点击该区域无效,上滑切换下一个推荐作品,下滑切换上一个推荐作品。
- 推荐页切换参考短视频上下滑交互:当前运行画布位于中间,上一个/下一个作品的封面预览提前挂载在画布上下屏幕外;拖动作品信息区时三屏轨道跟随位移,松手后完成切换或回弹。
- 用户停留在推荐页时,底部当前 Tab 从“推荐”切换为“下一个”,图标使用向下的倒三角 / 双下箭头语义,点击后切换下一个推荐作品。
- 推荐页不再展示额外的底部作品切换块;当前作品的完整操作继续收敛在详情页和作品自身运行态
- 推荐页不再展示额外的底部作品切换块;当前作品的点赞、分享与改造在推荐页底部操作区直接完成,其它作品深层操作继续详情页和作品自身运行态承接
- 推荐页嵌入运行只调整平台外壳容器、主题注入和玩法壳层配色,不改写作品数据、关卡设定、道具设定或图片资产。
- 屏幕外预览只允许使用公开封面、作品名和类型,不提前启动其它作品 run不触发道具、计时、存档或作品数据变更。
- 推荐页嵌入拼图玩法时隐藏拼图左上返回按钮,并在设置弹层中隐藏退出入口;作品切换前对当前拼图 run 执行既有“保存并退出”收口,正式 run 的交互状态以已写回后端的快照为准。
- 点赞、改造、复制作品号等完整操作继续收敛在详情页,详情入口由作品自身运行态或其它广场列表承接,推荐页作品信息区只负责展示和上下切换。
- 底部操作区移除游玩次数、评论功能和额外心形收藏入口;点赞按钮可直接点击并刷新公开读模型返回的点赞数,分享按钮复制作品号与公开作品链接,改造按钮只保留改造 icon 并复用既有改造入口。操作按钮只响应自身点击,按钮外的信息区点击无效,拖动时仍跟随整张推荐卡上下切换作品
- 无数据、加载中、启动失败和暂不支持内嵌运行的作品沿用短状态文案。
桌面端仍保持现有首页布局,只把一级导航文案从“首页”改为“推荐”。
@@ -93,6 +93,7 @@
11. 仅推荐页嵌入拼图态隐藏返回与设置内退出入口;详情页、新手引导和普通拼图运行态继续保留原有退出能力。
12. 推荐页切换作品前,如果当前作品是拼图,必须先执行当前拼图 run 的退出收口,再启动下一作品。
13. 已登录推荐页的上/下滑切换必须展示相邻作品的屏幕外预览,并在拖动不足阈值时回弹;相邻预览不得提前启动玩法运行态。
14. 推荐页底部区域不展示游玩次数、评论入口和额外心形收藏入口;点赞、分享和改造都使用 icon 按钮,点赞数紧邻点赞按钮展示。
## 8. 2026-05-07 未登录三栏补充

View File

@@ -65,7 +65,7 @@
1. 玩家需要优先依赖画面主体、构图和色块识别位置。
2. 编号覆盖会削弱“完整图片被逐步复原”的视觉奖励。
3. 合成后的拼图块只保留原图切片、外轮廓描边和必要的拖拽层级,不叠加额外的色块、暗层或蒙版,避免破坏原图识别。
3. 单块和合成后的拼图块只保留原图切片、外轮廓描边和必要的拖拽层级,不叠加额外的色块、暗层或蒙版,避免破坏原图识别。
### 3. 设置能力

View File

@@ -1,6 +1,6 @@
# AI 原生抓大鹅 Match3D 玩法创作工具与玩法系统 PRD
更新时间:`2026-04-30`
更新时间:`2026-05-10`
## 0. 文档目的
@@ -16,7 +16,7 @@
## 1. 一句话定义
让百梦主通过 Agent 对话确认题材、需要消除次数难度,系统编译出一个可试玩、可发布的单局抓大鹅玩法作品;玩家在 `10` 分钟倒计时内点击圆形空间中可见物品,把物品放入下方 `7` 格备选栏,每凑齐 `3` 个同物品 id 自动消除,最终清空圆形空间内全部物品即胜利。
让百梦主在创作页通过表单确认题材主题和难度选项,系统根据难度选项派生需要消除次数难度数值,并编译出一个可试玩、可发布的单局抓大鹅玩法作品;玩家在 `10` 分钟倒计时内点击圆形空间中可见物品,把物品放入下方 `7` 格备选栏,每凑齐 `3` 个同物品 id 自动消除,最终清空圆形空间内全部物品即胜利。
---
@@ -36,7 +36,7 @@
```text
平台创作入口
-> 选择“抓大鹅”
-> Agent 对话确认题材、需要消除次数、难度
-> 入口表单确认题材主题、难度选项
-> 生成待发布结果页
-> 编辑作品基础信息
-> 发布前试玩
@@ -62,7 +62,7 @@
## 3.1 复用什么
1. 复用平台创作中心入口。
2. 复用 Agent-first 创作体验。
2. 复用拼图式创作页入口表单体验。
3. 复用“创作会话 -> 结果页 -> 发布 -> 运行态”的平台主链。
4. 复用作品基础信息、标签、封面、发布接口和作品管理体验。
5. 复用现有 Rust / SpacetimeDB 后端基线。
@@ -93,13 +93,13 @@ Match3D 必须形成独立玩法域,后续技术方案至少需要覆盖:
首版 demo 必须满足:
1. 平台新增“抓大鹅”玩法创作入口。
2. 创建流程采用 Agent 对话收集关键配置。
3. Agent 必须在进入结果页前确认:
2. 创建流程采用入口表单收集关键配置。
3. 表单必须在进入结果页前确认:
- 题材主题
- 需要消除次数
- 难度 `1~10`
4. 支持系统自动补全配置,用户确认后开始创造
5. 题材阶段允许上传参考图片
- 3D 素材风格
- 难度选项
4. `需要消除次数` 与难度 `1~10` 数值不再作为独立输入框展示,由难度选项派生
5. 生成抓大鹅草稿消耗 `20` 光点,生成按钮必须显式展示
6. 结果页支持编辑游戏名称、标签、封面图等基础发布信息。
7. 发布前支持试玩,并允许随时停止和修改配置。
8. 发布不要求试玩通关。
@@ -110,7 +110,8 @@ Match3D 必须形成独立玩法域,后续技术方案至少需要覆盖:
13. 清空圆形空间中全部物品即胜利。
14. 倒计时结束或备选栏满即失败。
15. 胜利 / 失败后展示结算界面。
16. 点击、入槽、消除、失败、胜利的即时反馈效果由前端先行呈现,后端负责权威确认、状态落库和成绩可信性
16. 入口页的 3D 素材风格选择会进入素材图提示词,并作为结果页手动 Rodin 3D 模型生成的默认提示词依据
17. 点击、入槽、消除、失败、胜利的即时反馈效果由前端先行呈现,后端负责权威确认、状态落库和成绩可信性。
---
@@ -137,13 +138,22 @@ Match3D 必须形成独立玩法域,后续技术方案至少需要覆盖:
## 6.1 创作方式
Match3D 首版参考拼图早期的 Agent 对话收集锚点,而不是拼图后期的纯表单入口
Match3D 首版参考拼图后期的入口表单收集方式,而不是早期的 Agent 对话锚点收集
Agent 的职责是帮助用户确认可以直接编译 demo 的最小配置:
表单的职责是帮助用户确认可以直接编译 demo 的最小配置:
1. 题材主题。
2. 需要消除次数
3. 游戏难度。
2. 3D 素材风格
3. 游戏难度选项
`需要消除次数` 与游戏难度数值仍属于后端会话配置,但不再要求用户手填。当前入口页固定采用以下映射:
```text
轻松 -> 需要消除 8 次,难度 2
标准 -> 需要消除 12 次,难度 4
进阶 -> 需要消除 16 次,难度 6
硬核 -> 需要消除 20 次,难度 8
```
## 6.2 必填配置
@@ -151,13 +161,13 @@ Agent 的职责是帮助用户确认可以直接编译 demo 的最小配置:
题材决定后续生成或选择物品素材的方向。用户可以自定义主题,例如水果、玩具、食物、符号等。
首版 demo 不接入真实图片生成。当前运行态可消除物统一使用参考图方向的 25 个积木件类型表现,不使用透明气泡,也不在图案上放文字标识。前端首版用差异化颜色、积木造型和 3D 程序化模型表现可消除物,避免玩家在堆叠状态下难以辨认。
首版 demo 不接入真实图片生成。当前运行态可消除物统一使用题材方向的 25 个积木件类型表现,不使用透明气泡,也不在图案上放文字标识。前端首版用差异化颜色、积木造型和 3D 程序化模型表现可消除物,避免玩家在堆叠状态下难以辨认。
可消除物尺寸使用五档相对体积规则XL 型相对体积为 `1.60~2.30`L 型为 `1.25~1.60`M 型为 `1.00`XS 型为 `0.65~0.85`S 型为 `0.35~0.50`。单局中 XL / L / M / XS / S 按本局使用的消除物类型数的 `20% / 30% / 30% / 15% / 5%` 分配;非整数配额按最大余数补齐,确保总数等于本局使用类型数量。同一关卡内同一个颜色和造型的物品只能对应一个尺寸档位;可存在同尺寸但不同颜色和造型的物品。后端运行态通过 `radius` 下发权威尺寸,前端只按快照表现。
### 需要消除次数
用户输入任意正整数
该字段由难度选项派生,不作为入口页独立输入框展示
该字段不是胜利条件,而是本局总物品规模配置:
@@ -169,21 +179,23 @@ Agent 的职责是帮助用户确认可以直接编译 demo 的最小配置:
### 难度
用户输入 `1~10` 的数字,代表从低到高的难度感受
用户选择 `轻松 / 标准 / 进阶 / 硬核` 之一,系统派生 `1~10` 范围内的难度数值
首版 demo 中,用户只需凭感觉选择难度;具体难度规则由系统内部解释。后续优化阶段再细化难度曲线、生成算法和遮挡策略。
## 6.3 自动配置
### 3D 素材风格
如果用户不想逐项填写,系统可以自动补全题材、需要消除次数和难度。
入口页在题材主题与难度之间展示 `3D素材风格` 横向滑动选择。首批固定选项为:
自动补全后的配置必须展示给用户确认,用户确认后才能开始创造。
```text
黏土手作 / 低多边形 / 玩具塑料 / 木质雕刻 / 体素积木 / 金属机甲 / 自定义
```
## 6.4 参考图片
每个内置选项使用 VectorEngine `gpt-image-2-all` 生成的画风参考图展示;参考图保存在 `public/match3d-style-references/`,只作为入口选择的视觉提示,不作为用户上传参考图。选择内置风格时,前端提交 `assetStyleId``assetStyleLabel` 与对应 `assetStylePrompt`。选择 `自定义` 时必须弹出独立面板,用户填写描述后才允许应用;自定义描述作为 `assetStylePrompt` 进入后端生成链路。
题材阶段允许用户上传参考图片
## 6.3 参考图片
首版只支持图片参考,不支持视频参考。参考图片用于影响题材表现,不作为运行时规则裁决依据
抓大鹅入口页不展示参考图片上传。题材表现先由题材文本和草稿切割图片链路承接;后续需要 3D 模型时,在结果页 `3D素材` Tab 以切割图片作为图生模型参考图手动触发
---
@@ -210,9 +222,9 @@ Agent 的职责是帮助用户确认可以直接编译 demo 的最小配置:
## 7.3 素材生成边界
首版结果页暂时不生成额外素材
抓大鹅草稿生成链路会生成首批 `3` 个题材物品素材文本模型生成物品名VectorEngine 生成 `2*2` 素材图并切割独立图片。入口页选择的 `assetStylePrompt` 必须写入素材图提示词;结果页手动 Rodin 图生模型时,继续以该物品图片和默认提示词作为起点
后续如果需要生成题材物品、伪 3D 物品、场景背景或封面图,需要先补充本文档或新增技术方案,再进入编码
生成出的独立图片先作为草稿页 `3D素材` Tab 的预览资产返回,状态为 `image_ready`模型文件为空。正式平台资产绑定、Rodin 生成模型转存和二次编辑流程以后续技术方案为准
## 7.4 发布前试玩
@@ -415,15 +427,14 @@ itemTypeCount = clearCount <= 25 ? clearCount : 25
前端负责所有游戏过程中需要即时呈现的反馈效果:
1. 展示 Agent 创作界面。
1. 展示表单式创作界面。
2. 展示结果页和基础编辑表单。
3. 上传参考图片
4. 展示运行态场景、物品、倒计时和备选栏
5. 基于最新后端快照执行 2D 命中检测、悬停、按压和选中反馈
6. 发送玩家点击意图
7. 在等待后端确认期间,先行播放飞入、入槽、三消、腾格、胜利和失败过渡效果
8. 收到后端确认后,把本地表现校正到权威快照
9. 展示结算界面。
3. 展示运行态场景、物品、倒计时和备选栏
4. 基于最新后端快照执行 2D 命中检测、悬停、按压和选中反馈
5. 发送玩家点击意图
6. 在等待后端确认期间,先行播放飞入、入槽、三消、腾格、胜利和失败过渡效果
7. 收到后端确认后,把本地表现校正到权威快照
8. 展示结算界面
前端可以做即时表现预判,但不得把预判结果作为最终规则真相或成绩来源。
@@ -444,7 +455,7 @@ itemTypeCount = clearCount <= 25 ? clearCount : 25
```ts
interface Match3DCreatorConfig {
themeText: string;
referenceImageSrc?: string;
referenceImageSrc?: string | null;
clearCount: number;
difficulty: number;
}
@@ -453,9 +464,9 @@ interface Match3DCreatorConfig {
字段说明:
1. `themeText`:题材主题。
2. `referenceImageSrc`可选参考图片
3. `clearCount`:需要消除次数,必须为正整数。
4. `difficulty`:难度,范围为 `1~10`
2. `referenceImageSrc`历史兼容字段,入口页固定提交为 `null`
3. `clearCount`由难度选项派生的需要消除次数,必须为正整数。
4. `difficulty`难度选项派生的难度数值,范围为 `1~10`
## 11.2 作品结构
@@ -656,15 +667,17 @@ GET /api/runtime/match3d/runs/:runId
创作入口只展示必要信息,不默认堆叠玩法规则说明。
## 14.2 Agent 工作区
## 14.2 入口表单
Agent 每轮优先追问最影响 demo 生成的一个问题。
入口表单只展示三个输入块:
已确认的信息应清晰展示给用户确认:
1. `想做一个什么题材的抓大鹅?` 大文本输入框。
2. `3D素材风格` 横向滑动风格卡,最后一个为 `自定义`
3. `难度` 选项按钮。
1. 题材主题
2. 需要消除次数。
3. 难度
入口页不展示参考图、`需要消除次数` 数值输入、`难度数值` 滑杆,也不展示 `题材 / 物品 / 难度` 三个摘要框。`需要消除次数``difficulty` 由难度选项派生后提交给后端
抓大鹅入口页必须适配移动端创作页一屏内展示,页面自身不产生纵向滚动。题材输入框、风格横滑区、难度按钮和生成按钮根据可视高度自适应压缩,风格区只允许横向滑动
## 14.3 结果页
@@ -689,22 +702,24 @@ Agent 每轮优先追问最影响 demo 生成的一个问题。
首版 PRD 对应 demo 验收标准:
1. 用户可从平台创作入口进入“抓大鹅”模板。
2. Agent 能确认题材、需要消除次数难度。
3. 用户可上传参考图
4. 系统可生成待发布结果页
5. 用户可编辑游戏名称、标签、封面图等基础信息
6. 用户可发布前试玩,且试玩失败不阻断发布
7. 运行态能展示圆形空间、倒计时、物品和 `7` 格备选栏
8. 物品可重叠、遮挡、堆叠
9. 被完全遮挡物品不可点击,露出可点击区域的物品可点击
10. 点击通过后物品飞入备选栏
11. 备选栏中 `3` 个相同物品 id 自动消除
12. 清空空间中全部物品后胜利
13. 倒计时结束或备选栏满后失败
14. 胜利结算展示使用时间
15. 失败结算展示完成进度和重新开始按钮
16. 局内即时反馈由前端先行呈现,关键状态以后端确认快照校正
17. 相关中文文档通过编码检查
2. 入口表单能确认题材主题、3D 素材风格和难度选项,并提交派生后的消除次数难度数值
3. 入口页不展示参考图上传
4. 内置风格显示画风参考图,自定义风格通过独立面板填写并进入提交 payload
5. 移动端入口页所有内容一屏展示,不产生纵向滚动
6. 系统可生成待发布结果页,并在草稿中返回首批切割图片素材预览
7. 用户可编辑游戏名称、标签、封面图等基础信息
8. 用户可发布前试玩,且试玩失败不阻断发布
9. 运行态能展示圆形空间、倒计时、物品和 `7` 格备选栏
10. 物品可重叠、遮挡、堆叠
11. 被完全遮挡物品不可点击,露出可点击区域的物品可点击
12. 点击通过后物品飞入备选栏
13. 备选栏中 `3` 个相同物品 id 自动消除
14. 清空空间中全部物品后胜利。
15. 倒计时结束或备选栏满后失败
16. 胜利结算展示使用时间
17. 失败结算展示完成进度和重新开始按钮
18. 局内即时反馈由前端先行呈现,关键状态以后端确认快照校正。
19. 相关中文文档通过编码检查。
---
@@ -719,7 +734,7 @@ Agent 每轮优先追问最影响 demo 生成的一个问题。
## 阶段 B创作与结果页
1. 新增平台创作入口。
2. 接入 Agent 会话。
2. 接入创作会话。
3. 编译草稿并进入结果页。
4. 复用基础信息编辑和发布链。

View File

@@ -110,9 +110,10 @@
```text
平台创作中心
-> 选择视觉小说
-> 选择创作起点:一句话 / 文档 / 空白
-> 进入 visual-novel-agent-workspace
-> Agent 生成或补齐底稿
-> 视觉小说入口页只展示一句话创作输入框和视觉画风选项
-> 点击生成草稿
-> 进入 visual-novel-generating
-> 生成或补齐底稿
-> 进入 visual-novel-result
-> 编辑世界观、角色、场景、剧情阶段、资产和运行时配置
-> 点击试玩
@@ -154,10 +155,11 @@
1. 作品标题。
2. 一句话简介。
3. 世界观摘要
4. 玩家身份
5. 3 到 6 个主要角色
6. 3 到 8可用场景
3. 视觉画风
4. 世界观摘要
5. 玩家身份
6. 3 到 6主要角色
7. 3 到 8 个可用场景。
7. 3 到 6 个剧情阶段。
8. 初始场景、初始旁白和第一轮可选行动。
@@ -772,20 +774,23 @@ service client 要复用现有请求封装、鉴权和错误提示风格,不
### 12.1 工作台
工作台只展示创作需要的输入和状态:
入口页只展示创作需要的输入和状态:
1. 创作起点选择:一句话、文档、空白
2. 文本输入框和文档上传
3. Agent 对话区域
4. 底稿生成进度
5. 进入结果页按钮。
1. 一句话创作输入框
2. 视觉画风选项,参考抓大鹅入口页的横向卡片选择结构
3. 生成草稿按钮
4. 错误、忙碌与禁用态
点击生成草稿后进入 `visual-novel-generating` 过程页,过程页复用平台已有生成进度面板,展示一句话输入、画风和草稿生成阶段;完成后自动进入 `visual-novel-result` 草稿页。
不展示:
1. 平台规则说明。
2. 外部仓库平台功能介绍。
3. 回放、分享回放、录像、复盘入口。
4. 大段字段解释
3. 文档 / 空白创建入口。
4. Agent 对话侧栏
5. 回放、分享回放、录像、复盘入口。
6. 大段字段解释。
### 12.2 结果页

View File

@@ -105,6 +105,7 @@ HYPER3D_MODEL_REQUEST_TIMEOUT_MS / RODIN_MODEL_REQUEST_TIMEOUT_MS
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 文本/多模态理解链路GPT-image-2 图片生成不得再读取 APIMart 配置。
10. 本地 `npm run api-server``npm run dev:rust``npm run dev` 的环境文件优先级固定为外层 shell 变量最高,其后 `.env``.env.local``.env.secrets.local` 逐层覆盖;真实密钥建议放在 `.env.secrets.local`,防止 `.env` 中的空示例值覆盖私密配置。
## 示例文件

View File

@@ -44,7 +44,8 @@ RODIN_MODEL_REQUEST_TIMEOUT_MS
1. `HYPER3D_API_KEY` / `RODIN_API_KEY` 只允许写入本地或生产私密环境,不提交到 Git。
2. 缺少 API Key 时,后端返回 `503 SERVICE_UNAVAILABLE`
3. `HYPER3D_BASE_URL` 默认使用公开 API 基础地址;如果团队后续改用代理网关,可通过环境变量覆盖
3. 本地真实联调推荐把 key 放在 `.env.secrets.local``npm run api-server``npm run dev:rust``npm run dev` 均应保持“外层 shell 变量优先,随后 `.env``.env.local``.env.secrets.local` 逐层覆盖”的口径,避免 `.env` 里的空示例值压掉私密 key
4. `HYPER3D_BASE_URL` 默认使用公开 API 基础地址;如果团队后续改用代理网关,可通过环境变量覆盖。
## 4. 后端路由
@@ -91,6 +92,7 @@ RODIN_MODEL_REQUEST_TIMEOUT_MS
6. `meshMode` 限定为 `Quad/Raw`,默认 `Quad`
7. `addons` 首版只允许 `HighPack`
8. `bboxCondition` 必须为 3 个正数,按上游要求序列化为 JSON 字符串。
9. `subscriptionKey` 是 Hyper3D 返回的 opaque token状态查询只校验非空不在本地做 256 字符等固定长度限制,避免长 token 阻断抓大鹅草稿内联模型生成。
## 6. 返回语义

View File

@@ -0,0 +1,130 @@
# 抓大鹅草稿素材生成流水线 2026-05-10
## 1. 范围
本方案用于改造 `生成抓大鹅草稿` 的首版生成链路:点击按钮后先进入独立生成过程页,生成结束后自动进入抓大鹅草稿页,并在草稿页 `3D素材` Tab 预览本次生成的 3D 模型。
本次只把任意难度都收敛为 `3` 件物品。后续难度曲线恢复时,再把物品数、网格数和手动 3D 任务数量从配置中放开。
## 2. 前端流程
入口仍复用 `Match3DAgentWorkspace` 表单。点击 `生成抓大鹅草稿` 后:
1. 创建 Match3D session。
2. 进入 `match3d-generating` 生成过程页。
3. 过程页复用拼图生成页的 `CustomWorldGenerationView` 结构。
4. 生成成功后自动进入 `match3d-result`
5. 生成失败时停留在生成过程页,允许重新生成或返回创作中心。
生成页步骤固定为:
```text
生成物品名称 -> 生成素材图 -> 切割独立图片 -> 生成 3D 模型 -> 上传图片与模型资产 -> 写入草稿页
```
生成页只展示题材和物品数量,不展示玩法规则说明。
## 3. 后端编排边界
外部模型和 OSS 上传全部由 `api-server` 编排,不进入 SpacetimeDB reducer。SpacetimeDB 继续只负责 Match3D 会话、草稿和作品 profile 的确定性写入。
`match3d_compile_draft` action 的后端顺序为:
1. 读取 session config。
2. 将本次 MVP 的 `clearCount` 固定为 `3`,并同步用于草稿编译。
3. 调用文本模型生成 `3` 个题材下的短物品名称。
4. 调用项目当前图片链路 VectorEngine `gpt-image-2-all` 生成一张 `1:1` 素材图,提示词必须合入入口页选择的 `assetStylePrompt`。历史 `nanobanana2` 图片选项当前按项目统一决策回落到 VectorEngine不重新接入 APIMart 图片网关。
5. 将素材图按 `n*n` 网格切割成独立图片。当前 `3` 件物品使用 `2*2` 网格,取前 `3` 格。
6. 将素材图和每张独立图片上传到 OSS其中独立图片作为 Rodin 图生模型参考图。
7. 对每张独立图片调用 Hyper3D Rodin Gen-2 图生模型,等待任务完成,读取 GLB 下载文件并转存到 `generated-match3d-assets`
8. 调用现有 SpacetimeDB compile procedure 写入草稿,并把本次生成的独立物品图片与模型文件引用序列化写入 `match3d_work_profile.generated_item_assets_json`。这一步对标拼图的 `save_puzzle_generated_images`:生成资产不能只挂在本次 HTTP response 上,否则退出结果页后从草稿架读取 `getMatch3DWorkDetail` 会丢失素材列表。
9. 在 HTTP 返回的 draft/profile DTO 中附带本次生成的素材资产预览信息,模型生成成功时状态为 `model_ready`;后续重进草稿页时从 work profile 的持久化 `generatedItemAssets` 恢复同一批素材。
草稿生成阶段会调用 Hyper3D Rodin并等待 GLB 模型文件可下载;不得把上游下载 URL 直接写入 Match3D profile必须先转存 OSS再保存 `/generated-match3d-assets/...` 引用。结果页 `3D素材` Tab 的重新生成按钮仍可手动触发 Rodin 任务,但正式持久化仍以后端草稿生成链路写入的模型文件为准。
## 4. 图片提示词
素材图提示词必须显式包含:
```text
生成一张1:1图片
生成2*2网格素材图
整体画风遵循:...
只绘制这些物品:...
不要出现文字、水印、UI、边框
```
`包含若干个物品名称` 在落地中解释为“按生成出的物品名称绘制对应主体”,不要求图片上写出物品名称。这样可以避免文字渲染污染切图和后续手动 3D 模型参考。
入口页内置风格参考图通过同一 VectorEngine `gpt-image-2-all` 能力生成,保存路径固定为:
```text
public/match3d-style-references/clay-toy.png
public/match3d-style-references/low-poly.png
public/match3d-style-references/toy-plastic.png
public/match3d-style-references/wood-carved.png
public/match3d-style-references/voxel-block.png
public/match3d-style-references/metal-mecha.png
```
这些图片只作为入口页风格选择的视觉参考,不进入用户草稿资产,不替代生成时的物品素材图。
## 5. OSS 路径
新增 generated legacy prefix
```text
generated-match3d-assets
```
建议对象分组:
```text
generated-match3d-assets/{sessionId}/{profileId}/material-sheet/{taskId}/sheet.png
generated-match3d-assets/{sessionId}/{profileId}/items/{itemSlug}/image.png
generated-match3d-assets/{sessionId}/{profileId}/items/{itemSlug}/model/{taskUuid}/model.glb
```
`itemSlug` 必须带 `itemId` 前缀,例如 `match3d-item-1-item`。中文物品名清洗后可能都退回 `item`,不能只用物品名做路径,否则多张切割图会写到同一个 object key导致草稿页预览图全部一致。
HTTP DTO 同时返回 `imageSrc``imageObjectKey``modelSrc``modelObjectKey``modelFileName``taskUuid``subscriptionKey``status = model_ready`。前端模型预览不得直接请求裸 `/generated-match3d-assets/...` 路径;需要通过 `/api/assets/read-bytes` 读取模型字节,转成 Blob URL 后交给 Three.js GLTFLoader 加载,以绕开私有 bucket CORS。
## 6. 自动保存与草稿恢复
抓大鹅结果页的基础信息自动保存继续调用 `PUT /api/runtime/match3d/works/{profileId}` 更新名称、题材、描述、标签、封面、消除数和难度;该保存不得清空 `generated_item_assets_json`。SpacetimeDB `update_match3d_work` / `publish_match3d_work` 必须保留当前行的生成素材 JSON。
草稿架重进路径为:
```text
草稿 Tab -> getMatch3DWorkDetail(profileId) -> Match3DResultView(profile.generatedItemAssets)
```
因此 `map_match3d_work_summary_response` / `map_match3d_work_profile_response` 需要从 work profile snapshot 反序列化 `generated_item_assets_json` 并输出 `generatedItemAssets`。前端 `Match3DResultView` 仍保持现有优先级:本次生成流程内有 `draft.generatedItemAssets` 时用 draft从草稿架重进没有 draft 时,用 `profile.generatedItemAssets`;两者都没有才回退到默认 3D 素材占位。
`3D素材` 详情页只保留:
1. 模型预览区:优先加载 `modelSrc` 对应 GLB支持拖动旋转没有模型时展示空预览。
2. 素材名称输入。
3. `重新生成` 按钮。
详情页不再展示参考图、用途、提示词、文生/图生切换、状态查询、下载列表、taskUuid 或 subscriptionKey。
## 7. 验收
建议执行:
```powershell
npm run check:encoding
npm run test -- src\services\miniGameDraftGenerationProgress.test.ts
npm run test -- src\components\match3d-result\Match3DResultView.test.tsx
npm run typecheck
cargo test -p shared-contracts match3d --manifest-path server-rs\Cargo.toml
cargo test -p spacetime-client match3d --manifest-path server-rs\Cargo.toml
cargo test -p platform-oss --manifest-path server-rs\Cargo.toml
cargo test -p api-server match3d --manifest-path server-rs\Cargo.toml
cargo check -p api-server --manifest-path server-rs\Cargo.toml
cargo check -p spacetime-client --manifest-path server-rs\Cargo.toml
cargo check -p spacetime-module --manifest-path server-rs\Cargo.toml
```
真实草稿生成需要本地私密环境配置 `VECTOR_ENGINE_API_KEY``HYPER3D_API_KEY` 和 OSS 访问变量。后端改动后使用 `npm run api-server` 启动,并检查 `/healthz`

View File

@@ -1,6 +1,10 @@
# 抓大鹅 Match3D F1 创作入口与 Agent UI 落地记录 2026-04-30
> 2026-05-08 更新:抓大鹅创作端入口已重新开放,当前 `match3d.visible` 为 `true`。本文件记录 F1 接入能力,入口是否展示以 `NEW_WORK_ENTRY_CONFIG_2026-05-01.md` 和 `src/config/newWorkEntryConfig.ts` 为准。
>
> 2026-05-10 更新:抓大鹅入口页对齐拼图入口页,直接嵌入创作页模板 Tab。入口表单不再展示参考图、消除次数输入、难度数值滑杆和题材/物品/难度摘要框,仅保留题材主题大输入框和难度选项。难度选项负责派生 `clearCount` 与 `difficulty`,生成按钮必须展示 `消耗20光点`。
>
> 2026-05-10 补充:入口页新增 `3D素材风格` 横向滑动选择,首批风格参考图通过 VectorEngine `gpt-image-2-all` 生成并保存到 `public/match3d-style-references/`。最后一个选项为 `自定义`,点击后弹出独立面板填写画风描述。
## 1. 阶段边界
@@ -30,19 +34,38 @@ badge: 可创建
入口来源统一走 `getVisiblePlatformCreationTypes()`,因此创作首页首屏卡带与“选择创作类型”弹层会同时出现抓大鹅。
## 4. Agent 工作区
## 4. 入口表单工作区
新增 `Match3DAgentWorkspace`复用通用 `CreationAgentWorkspace`
新增 `Match3DAgentWorkspace`组件名继续兼容既有路由、草稿恢复和父层分流;当前主入口已从固定 Agent 追问收口为拼图式表单
Agent 只收集三类锚点:
创作页 `选择模板` Tab 中切换到 `抓大鹅` 时,直接渲染该表单,不创建会话,也不跳到独立工作台。点击生成后才创建 Match3D 会话并执行 `match3d_compile_draft`
1. 题材主题。
2. 需要消除次数。
3. 难度。
表单只展示三个输入块:
工作区支持参考图片上传入口。图片在 F1 中先以 Data URL 形式随消息 payload 带给 mock clientB5 接入后由后端 facade 替换为正式资产上传与引用
1. `想做一个什么题材的抓大鹅?`:大文本输入框,收集 `themeText`
2. `3D素材风格`:横向滑动风格卡,选择会写入 `assetStyleId``assetStyleLabel``assetStylePrompt`
3. `难度`:四个选项按钮,选项内部派生消除次数和难度数值。
UI 中不默认展示玩法规则长文,只展示进度、锚点、聊天内容和必要按钮。
当前难度映射固定为:
```text
轻松 -> clearCount 8, difficulty 2
标准 -> clearCount 12, difficulty 4
进阶 -> clearCount 16, difficulty 6
硬核 -> clearCount 20, difficulty 8
```
入口页不再上传参考图,提交 payload 中 `referenceImageSrc` 固定为 `null`。如果从旧会话或旧草稿恢复,前端只根据已有 `difficulty` 选择最接近的难度选项,并按当前选项重新派生 `clearCount``difficulty`
内置风格选项为:
```text
黏土手作 / 低多边形 / 玩具塑料 / 木质雕刻 / 体素积木 / 金属机甲 / 自定义
```
自定义风格必须在弹出面板中填写描述后才能应用。入口表单必须在移动端创作页可视区内完成题材、风格、难度和生成按钮的展示,页面自身不产生纵向滚动;风格卡只允许横向滑动。
生成按钮文案为 `生成抓大鹅草稿`,按钮内必须同时展示 `消耗20光点`。UI 中不默认展示玩法规则长文,也不展示隐藏派生数值的摘要框。
## 5. mock client
@@ -84,10 +107,13 @@ POST /api/creation/match3d/sessions/:sessionId/compile
## 8. 验收口径
1. 创作首页能看到“抓大鹅 / 经典消除玩法
2. 弹层选择“抓大鹅”能进入 Agent 工作区
3. 输入题材、消除次数、难度后进度到 `100%`
4. 点击“生成结果页”进入草稿承接页
5. 可从草稿承接页返回 Agent 修改
6. `npm run check:encoding` 通过
7. `npm run typecheck` 通过。
1. 创作`选择模板` Tab 能看到 `抓大鹅 / 经典消除玩法`
2. 切换到 `抓大鹅` Tab 后,页面内直接显示抓大鹅入口表单,不提前创建会话
3. 表单不展示参考图、`需要消除次数``难度数值``题材``物品``难度`摘要框
4. 输入题材、选择风格和难度后,提交 payload 包含派生后的 `clearCount``difficulty``referenceImageSrc``null`,并包含 `assetStyleId``assetStyleLabel``assetStylePrompt`
5. 生成按钮展示 `消耗20光点`
6. 点击 `自定义` 风格弹出独立面板,填写后应用到提交 payload未填写时不能应用空自定义风格
7. 移动端创作页内抓大鹅入口内容不产生纵向滚动,风格卡横向滑动。
8. 点击生成后创建会话并进入草稿生成/结果页链路。
9. `npm run check:encoding` 通过。
10. `npm run typecheck` 通过。

View File

@@ -0,0 +1,75 @@
# 抓大鹅 Rodin 3D 素材 Tab 接入方案 2026-05-10
## 1. 范围
本方案用于把抓大鹅结果页调整为多 Tab 工作台,并新增 `3D素材` Tab。该 Tab 专门服务抓大鹅玩法内物件、奖励、障碍等 3D 素材的 Rodin 生成试验。
本次复用已有 Hyper3D Rodin Gen-2 后端安全代理,不新增 SpacetimeDB 表;草稿生成链路会把 Rodin 模型转存到 OSS并通过 Match3D 作品 profile 的 `generatedItemAssets` 恢复。不得把 Hyper3D API Key、上游下载 URL 或本地 Data URL 写成正式资产真相。
## 2. 页面结构
抓大鹅结果页拆为三个 Tab
1. `作品信息`:承接封面、游戏名称、标签、简介。
2. `玩法配置`:承接题材、消除次数、难度、参考图与局内数量摘要。
3. `3D素材`:展示 Rodin 素材列表,点击列表项进入详情生成页。
`3D素材` Tab 的列表布局参考 RPG 结果页角色列表:移动端纵向卡片,桌面端多列紧凑卡片;卡片展示素材名和状态。详情页只保留模型预览、素材名称和 `重新生成` 按钮。
## 3. Rodin 任务边界
前端只维护当前页面内的临时重新生成任务状态:
1. 素材槽位名称。
2. 模型预览。草稿生成的 `/generated-match3d-assets/...` GLB 必须通过同源 `/api/assets/read-bytes` 由后端换签并读取字节,前端再转成 Blob URL 后交给 Three.js GLTFLoader避免浏览器直接 `fetch` OSS 签名 URL 时被 CORS 拦截。
3. 图生模型参考图只作为重新生成的隐藏输入来源,不在详情页展示。上传图片在前端直接读成 Data URL草稿生成的 `/generated-match3d-assets/...` 图片必须通过 `/api/assets/read-bytes` 转成 Data URL 后提交给 Hyper3D。
4. Hyper3D `taskUuid``subscriptionKey`
5. 查询到的状态、进度与下载文件列表。
正式资产链后续再接:
1. 下载文件转存 OSS。
2. `asset_object` 确认。
3. `asset_entity_binding` 绑定到 Match3D 作品或物件槽位。
首版不得把上游下载 URL 直接写入 Match3D profile也不得把 Data URL 持久化到 SpacetimeDB。
## 4. 接口复用
继续使用既有前端 client
```text
src/services/hyper3dModelGenerationService.ts
```
对应后端路由:
```text
POST /api/assets/hyper3d/text-to-model
POST /api/assets/hyper3d/image-to-model
POST /api/assets/hyper3d/status
POST /api/assets/hyper3d/download
```
请求参数默认使用:
```text
geometryFileFormat = glb
material = PBR
quality = medium
meshMode = Quad
previewRender = true
conditionMode = concat
```
## 5. 验收
建议执行:
```powershell
npm run check:encoding
npm run test -- src\components\match3d-result\Match3DResultView.test.tsx
npm run typecheck
```
真实 Rodin 生成会消耗 Hyper3D Credit只在本地私密环境配置 `HYPER3D_API_KEY``RODIN_API_KEY` 后手动验证。

View File

@@ -262,3 +262,14 @@ cannon-es
3. 可见 mesh 初始以较小比例显示,再用缓动动画放大到完整尺寸;视觉缩放不得反向修改 body shape、质量、边界半径或生成高度避让计算。
4. 入场动画继续服从第 18 节的创建限流和第 19 节的生成高度避让;不能为了动画效果把物体直接放进已有堆叠内部。
5. 动画结束后 mesh 缩放必须回到 `1`,避免影响后续点击可读性和托盘对应关系。
## 21. 高 DPR 移动端 WebGL 画布尺寸锁定
2026-05-10 针对移动端试玩入口中 3D 锅体和物体从中心区域向右下溢出的问题,补充 WebGL canvas 布局口径。
编码口径:
1. 中心 3D 棋盘和托盘 3D 预览都允许通过 `renderer.setPixelRatio(...)` 提升绘制清晰度,但 `WebGLRenderer.domElement` 的 CSS 显示尺寸必须单独锁定为 `position: absolute; inset: 0; width: 100%; height: 100%; display: block`
2. `renderer.setSize(width, height, false)` 只负责绘图缓冲区与当前容器尺寸同步,不能依赖 canvas 默认属性尺寸承载 CSS 布局;否则高 DPR 设备会把绘图缓冲区尺寸当成页面尺寸显示,导致棋盘内容放大并从容器右下溢出。
3. 移动端验收仍以 `390px` 竖屏为基准:顶部状态、圆形棋盘和 `7` 格备选栏都必须完整可见,锅体内容应落在屏幕中间的圆形区域内。
4. 该修复只影响 WebGL 画布 CSS 布局,不改变相机、物理世界、碰撞体、点击命中、后端权威快照或托盘规则。

View File

@@ -76,13 +76,14 @@
4. 首图文生图 prompt 由 api-server 拼接固定拼图约束后统一压缩到 `500` 字符以内,避免玩家长画面描述触发 DashScope 参数非法;进度页和结果页仍展示玩家原始画面描述,不展示压缩后的内部 prompt。
5. 图片生成仍在 api-server 内完成,遵守 SpacetimeDB reducer 不做网络 I/O 的约束。
6. 参考图以 Data URL 进入 `POST /api/runtime/puzzle/agent/sessions``POST /api/runtime/puzzle/agent/sessions/{sessionId}/actions`,这两条路由必须单独放宽 JSON body 上限;不要放大全局默认 body limit。
7. 前端仍应优先压缩参考图;后端 body 上限只用于容纳合理尺寸的单张参考图,超大原图不应直接落入 SpacetimeDB 或作为作品字段持久化。
8. 作品更新接口 `PUT /api/runtime/puzzle/works/{profileId}` 必须支持作品信息和关卡列表一起写入,前端自动保存不得只写旧单关字段
9. `StartPuzzleRunRequest` 新增可选 `levelId`。详情页或草稿结果页单独体验某关时传入目标关卡,后端从作品/草稿的 `levels` 中选取该关卡生成运行态
10. `ExecutePuzzleAgentActionRequest` 必须保留 `pictureDescription` 字段。表单直达生成时,`compile_puzzle_draft` 优先用 `pictureDescription` 作为首图 prompt再回退到旧 `promptText`;避免生成页展示的是玩家画面描述,但后端实际用作品名称或旧摘要出图
11. `compile_puzzle_draft` 中的图片上游失败不得映射成 `400 BAD_REQUEST`。DashScope 返回 `InvalidParameter` 或任务失败时api-server 统一按 `502 UPSTREAM_ERROR` 暴露,并在 `details.message` 中保留“拼图图片生成失败:...”的业务原因,避免生成页只显示“请求参数不合法”
12. `compile_puzzle_draft` 前置光点预扣失败不得映射成 `400 BAD_REQUEST`余额不足返回 `409 CONFLICT`SpacetimeDB procedure 不可用、绑定不匹配、钱包服务异常等统一按 `502 UPSTREAM_ERROR` 暴露,并在 `details.message` 中保留真实钱包错误
13. 生成拼图作品草稿动作涉及的表单 seed prompt 与首图 prompt 来源选择统一收口在 `server-rs/crates/api-server/src/prompt/puzzle/draft.rs``puzzle.rs` 只负责调用 SpacetimeDB、计费、图片服务和持久化不再直接拼草稿 prompt 文本
7. 前端仍应优先压缩参考图,入口上传图和裁剪图统一压到单边 1024 以内;后端 body 上限只用于容纳合理尺寸的单张参考图,超大原图不应直接落入 SpacetimeDB 或作为作品字段持久化,后端解析后会拒绝超过 8MB 字节的参考图
8. `aiRedraw = true` 且存在 `referenceImageSrc`api-server 必须走 VectorEngine `POST /v1/images/edits` multipart 图生图接口;无参考图或入口页 `aiRedraw = false` 时不走图生图,关闭 AI 重绘会直接应用上传图为首关正式图
9. 作品更新接口 `PUT /api/runtime/puzzle/works/{profileId}` 必须支持作品信息和关卡列表一起写入,前端自动保存不得只写旧单关字段
10. `StartPuzzleRunRequest` 新增可选 `levelId`。详情页或草稿结果页单独体验某关时传入目标关卡,后端从作品/草稿的 `levels` 中选取该关卡生成运行态
11. `ExecutePuzzleAgentActionRequest` 必须保留 `pictureDescription` 字段。表单直达生成时,`compile_puzzle_draft` 优先用 `pictureDescription` 作为首图 prompt再回退到旧 `promptText`;避免生成页展示的是玩家画面描述,但后端实际用作品名称或旧摘要出图
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 文本。
## 结果页
@@ -104,10 +105,23 @@
4. 底部吸底操作区只承载动作按钮,不默认写玩法说明或规则解释,避免压缩移动端编辑空间。
5. 关卡详情面板内触发生成画面时,前端必须把当前编辑态完整 `levelsJson``generate_puzzle_images` action 一起提交。这样新建关卡在自动保存完成前立即生成,也能由后端写回目标关卡。
6. api-server 处理 `generate_puzzle_images` 时,若 action 带有 `levelsJson`,必须用这份关卡快照覆盖本次生成的草稿关卡视图后再定位 `levelId`。若请求明确传入 `levelId` 但关卡列表中不存在该关卡,必须返回错误,不得静默回退第一关。
7. 历史拼图素材入口只在已有正式图的 `画面图` 区域右下角展示,不再放在 `画面描述` 输入区;本地上传参考图入口仍保留在画面描述输入区右下角
7. 历史拼图素材入口和本地上传参考图入口统一收口到 `画面图` 图卡右下角,避免 `画面描述` 输入区同时承载文本编辑和素材入口;无正式图时也展示空图态图卡
8. 历史拼图素材列表必须由服务端按当前登录账号过滤,只返回 `asset_kind = puzzle_cover_image``owner_user_id = 当前账号` 的资产;不得依赖前端过滤,也不得展示其他账号素材。
9. `画面图` 图卡本身就是上传热区,详情页不再保留右下角独立“上传参考图”按钮;历史入口统一使用带 `History` 图标和 `历史` 小字的按钮。入口页空图态的“点击上传拼图图片”只作为图卡内轻量提示,不使用胶囊按钮、边框或背景样式。
画面描述区域不再展示候选图实际 prompt 或“请生成一张适合……”之类内部提示词模块。参考图入口保留在画面描述编辑区域内,便于重新生成时继续带入。结果页编辑关卡画面描述时只同步该关卡 `pictureDescription`;作品描述只在作品信息 Tab 编辑,作品详情页不得再回退使用画面描述。
### 2026-05-10 关卡生图交互补充
1. 关卡详情页的 `画面图``画面描述` 模块对齐入口页拼图表单:画面图使用稳定正方形图卡,画面描述使用固定高度输入区并保留图片模型选择。
2. 新建关卡或无正式图关卡也展示 `画面图` 图卡;空图态只保留图标化占位和生成中状态,不追加规则说明文案。
3. 关卡详情页删除手填 `参考图链接或资产ID` 输入框。参考图只能通过本地上传或历史拼图素材选择进入本次生成请求;字段 `levels[].pictureReference` 继续作为后端生成后的复用字段透传,不作为用户可手填表单项。
4. 单关生成等待估算从 `30` 秒调整为 `90` 秒;生成按钮内展示小字 `等待时间可以制作更多关卡哦~`,不得另起说明面板。
5. 触发某一关生成时,前端必须立即把该关 `generationStatus` 标为 `generating` 并随当前 `levelsJson` 写入草稿自动保存链路;后端生成完成后再写回 `ready`
6. `generationStatus = generating` 的关卡在详情弹窗关闭后仍保留进度展示,再次打开同一关详情能继续看到生成进度;关卡列表卡片也必须展示生成中的轻量状态。
7. 单关图片生成必须作为后台 action 执行,不占用拼图结果页全局 busy 状态;生成期间仍允许编辑作品信息、编辑关卡、新增关卡、删除其他关卡、关卡测试和继续触发其他可并行动作。
8. 发布是唯一必须等待全部图片生成完成的草稿结果页动作;发布检查需要把 `generationStatus = generating` 的关卡列为 blocker避免未完成资源进入广场。
9. 后台生图回包只合并对应关卡的图片候选、正式图、资产 ID 与生成状态,不得覆盖用户等待期间对关卡名、画面描述、作品信息或新增关卡所做的本地编辑。
画面描述区域不再展示候选图实际 prompt 或“请生成一张适合……”之类内部提示词模块。参考图入口统一放在画面图图卡内,便于重新生成时继续带入,同时保持画面描述输入区只负责文本编辑。结果页编辑关卡画面描述时只同步该关卡 `pictureDescription`;作品描述只在作品信息 Tab 编辑,作品详情页不得再回退使用画面描述。
## 验收

View File

@@ -10,9 +10,12 @@
- [VECTOR_ENGINE_GPT_IMAGE_2_GENERATION_2026-05-09.md](./VECTOR_ENGINE_GPT_IMAGE_2_GENERATION_2026-05-09.md):记录 GPT-image-2 图片生成从 APIMart 迁移到 VectorEngine `gpt-image-2-all` 的接口、环境变量、尺寸映射、错误口径和验收命令。
- [SPACETIMEDB_PUBLISH_SCCACHE_FALLBACK_2026-05-09.md](./SPACETIMEDB_PUBLISH_SCCACHE_FALLBACK_2026-05-09.md):记录本地 `spacetime publish` 被 sccache wrapper 通信异常阻断时的根因、debug 构建参数口径和手动排障命令。
- [AUTH_RESTORE_AND_RECOMMEND_LOADING_FIX_2026-05-09.md](./AUTH_RESTORE_AND_RECOMMEND_LOADING_FIX_2026-05-09.md):记录刷新网页后登录态失效和推荐页作品卡卡在加载中的联合修复,覆盖 `AuthGate` 本地 token 优先恢复、refresh 失败不清 token、推荐页启动请求版本保护和错误态收口。
- [USER_TAG_INVITE_AND_PUZZLE_LEADERBOARD_2026-05-10.md](./USER_TAG_INVITE_AND_PUZZLE_LEADERBOARD_2026-05-10.md):冻结用户标签字段、后台邀请码授予标签、用户填写邀请码后合并账号标签,以及拼图排行榜只展示白名单标签 `北科` 的落地口径。
- [RECOMMEND_RUNTIME_AUTH_FAILURE_ISOLATION_FIX_2026-05-09.md](./RECOMMEND_RUNTIME_AUTH_FAILURE_ISOLATION_FIX_2026-05-09.md):记录平台推荐页自动加载作品、公开拼图作品完整运行态、平台 bootstrap 私有投影刷新和展示层图片换签的局部请求 `401` 不应扩散成全局登出的修复,覆盖 `authImpact: local` 请求策略、推荐页 embedded 运行态启动、拼图开局/排行榜/下一关和回归测试。
- [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):记录抓大鹅结果页多 Tab 改造与 Rodin 3D 素材列表/详情页的前端接入边界,明确首版只复用 Hyper3D 后端代理,不新增表或正式资产写入。
- [MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md](./MATCH3D_DRAFT_ASSET_GENERATION_PIPELINE_2026-05-10.md)冻结抓大鹅草稿生成过程页、3 件物品名称生成、VectorEngine 1:1 素材图、n*n 切图、并行 Rodin 图生 3D 与 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 校验和前端预览/提交边界。
@@ -81,7 +84,7 @@
- [PROFILE_INVITE_CODE_REGISTRATION_AND_ADMIN_2026-04-30.md](./PROFILE_INVITE_CODE_REGISTRATION_AND_ADMIN_2026-04-30.md):冻结邀请码从“我的 Tab 填写”迁到注册环节的前后端边界、`profile_invite_code.metadata_json` 表结构扩展、管理员邀请码虚拟主体和奖励规则。
- [MATCH3D_CREATION_AND_RUNTIME_MINIMAL_IMPLEMENTATION_2026-04-30.md](./MATCH3D_CREATION_AND_RUNTIME_MINIMAL_IMPLEMENTATION_2026-04-30.md):冻结抓大鹅 Match3D 首版 demo 的独立玩法域、表与 procedure、HTTP facade、前端即时反馈/后端权威确认协议,以及可并行开发包。
- [MATCH3D_DOMAIN_AND_CONTRACTS_STAGE1_2026-04-30.md](./MATCH3D_DOMAIN_AND_CONTRACTS_STAGE1_2026-04-30.md):冻结抓大鹅 Match3D B1+B2 的纯领域规则 crate、Rust/TypeScript shared contracts以及 Stage1 不触碰 SpacetimeDB 表和 api-server 的边界。
- [MATCH3D_F1_CREATION_ENTRY_AND_AGENT_UI_2026-04-30.md](./MATCH3D_F1_CREATION_ENTRY_AND_AGENT_UI_2026-04-30.md):记录抓大鹅 F1 创作入口、Agent 工作区、参考图入口、本地 mock client 与后续 B5 HTTP facade 替换点
- [MATCH3D_F1_CREATION_ENTRY_AND_AGENT_UI_2026-04-30.md](./MATCH3D_F1_CREATION_ENTRY_AND_AGENT_UI_2026-04-30.md):记录抓大鹅 F1 创作入口与当前拼图式内嵌 Tab 表单,明确入口页仅保留题材大输入框和难度选项,由难度选项派生消除次数与难度数值
- [MATCH3D_F2_RESULT_AND_PUBLISH_2026-04-30.md](./MATCH3D_F2_RESULT_AND_PUBLISH_2026-04-30.md):冻结抓大鹅 F2 结果页、基础信息编辑、发布前试玩入口、发布门槛、自动保存和已发布作品二次编辑恢复口径。
- [MATCH3D_SPACETIME_CLIENT_AND_API_FACADE_2026-04-30.md](./MATCH3D_SPACETIME_CLIENT_AND_API_FACADE_2026-04-30.md):记录抓大鹅 B4+B5 已落地的 SpacetimeDB bindings、`spacetime-client` facade、`api-server` HTTP 路由、shared contract 对齐和验收命令。
- [MATCH3D_CREATION_ENTRY_COMING_SOON_2026-05-01.md](./MATCH3D_CREATION_ENTRY_COMING_SOON_2026-05-01.md):记录抓大鹅创作页入口重新开放、首屏与弹层分流一致,以及公开广场失败不污染创作错误态的边界。

View File

@@ -71,8 +71,9 @@ SELECT * FROM auth_store_snapshot WHERE snapshot_id = 'default';
### `user_account`
- 作用:用户账号主表,保存用户名、公开百梦号、手机号掩码、登录方式、密码登录开关token 版本。
- 结构:`user_id PK: String`, `public_user_code: String`, `username: String`, `display_name: String`, `avatar_url: Option<String>`, `phone_number_masked: Option<String>`, `phone_number_e164: Option<String>`, `login_method: String`, `binding_status: String`, `wechat_bound: bool`, `password_hash: Option<String>`, `password_login_enabled: bool`, `token_version: u64`
- 作用:用户账号主表,保存用户名、公开百梦号、手机号掩码、登录方式、密码登录开关token 版本和默认不前端展示的运营标签
- 结构:`user_id PK: String`, `public_user_code: String`, `username: String`, `display_name: String`, `avatar_url: Option<String>`, `phone_number_masked: Option<String>`, `phone_number_e164: Option<String>`, `login_method: String`, `binding_status: String`, `wechat_bound: bool`, `password_hash: String`, `password_login_enabled: bool`, `token_version: u64`, `user_tags: Vec<String>`
- 说明:`user_tags` 默认空数组,只允许后端白名单投影到特定业务接口;不得在登录态、个人资料等通用前端响应中直接暴露。
- 索引:`username`, `public_user_code`
```sql
@@ -255,10 +256,11 @@ SELECT * FROM profile_redeem_code_usage WHERE user_id = '<user_id>';
### `profile_invite_code`
- 作用:用户邀请中心的邀请码主表,也承载后台运营预置邀请码。
- 结构:`user_id PK: String`, `invite_code: String`, `metadata_json: String`, `created_at: Timestamp`, `updated_at: Timestamp`
- 作用:用户邀请中心的邀请码主表,也承载后台运营预置邀请码和使用后授予账号的运营标签
- 结构:`user_id PK: String`, `invite_code: String`, `metadata_json: String`, `created_at: Timestamp`, `updated_at: Timestamp`, `starts_at: Option<Timestamp>`, `expires_at: Option<Timestamp>`, `granted_user_tags: Vec<String>`
- 索引:主键 `user_id`,唯一索引 `invite_code`
- 后台读取:`GET /admin/api/profile/invite-codes` 只返回 `user_id``admin:` 开头的后台预置码;普通用户自己的邀请码不得进入后台运营列表。
- 说明:`granted_user_tags` 默认空数组;用户注册填写该邀请码后合并进 `user_account.user_tags`,不回改历史用户。
```sql
SELECT * FROM profile_invite_code WHERE user_id = '<user_id>';
@@ -661,8 +663,9 @@ SELECT * FROM match3d_agent_message WHERE session_id = '<session_id>' ORDER BY c
### `match3d_work_profile`
- 作用:抓大鹅 Match3D 作品主表,保存作品基础信息、配置、发布状态游玩次数。
- 结构:`profile_id PK: String`, `owner_user_id: String`, `source_session_id: String`, `author_display_name: String`, `game_name: String`, `theme_text: String`, `summary_text: String`, `tags_json: String`, `cover_image_src: String`, `cover_asset_id: String`, `clear_count: u32`, `difficulty: u32`, `config_json: String`, `publication_status: String`, `play_count: u32`, `updated_at: Timestamp`, `published_at: Option<Timestamp>`
- 作用:抓大鹅 Match3D 作品主表,保存作品基础信息、配置、发布状态游玩次数和草稿生成出的独立物品素材引用
- 结构:`profile_id PK: String`, `owner_user_id: String`, `source_session_id: String`, `author_display_name: String`, `game_name: String`, `theme_text: String`, `summary_text: String`, `tags_json: String`, `cover_image_src: String`, `cover_asset_id: String`, `clear_count: u32`, `difficulty: u32`, `config_json: String`, `publication_status: String`, `play_count: u32`, `updated_at: Timestamp`, `published_at: Option<Timestamp>`, `generated_item_assets_json: Option<String>`
- 说明:`generated_item_assets_json` 保存 `Match3DGeneratedItemAsset` 数组 JSON用于草稿页退出后从作品架重进时恢复 `3D素材` Tab 中的切割图片预览;基础信息自动保存和发布必须保留该字段。
- 索引:`owner_user_id`, `publication_status`
```sql

View File

@@ -0,0 +1,102 @@
# 用户标签、邀请码授予与拼图榜单展示方案
更新时间:`2026-05-10`
## 1. 目标
本次新增用户标签系统的最小闭环:
1. `user_account` 增加账号标签字段,默认空。
2. 后台预置邀请码可配置授予标签。
3. 用户填写带标签的邀请码后,把标签合并到自己的账号。
4. 标签默认不在前端资料页、邀请中心或通用接口展示。
5. 拼图排行榜仅对白名单标签做展示,首版只展示 `北科`
## 2. 数据字段
### `user_account.user_tags`
- 类型:`Vec<String>`
- 默认:空数组。
- 语义:账号级运营标签,属于后台与服务端投影数据,不作为普通前端个人资料字段。
- 写入:首版只由邀请码兑换链路合并写入。
- 迁移:旧迁移包和旧数据库按空数组兼容。
### `profile_invite_code.granted_user_tags`
- 类型:`Vec<String>`
- 默认:空数组。
- 语义:使用该邀请码后授予被邀请账号的标签列表。
- 范围:后台运营预置码和普通用户个人邀请码都可存字段,但后台表单首版只允许管理员配置预置码。
- 迁移:旧邀请码按空数组兼容。
## 3. 标签归一化
标签由 `module-runtime` 提供统一归一化:
1. trim 后为空的标签丢弃。
2. 同一邀请码或同一账号内标签去重,保留首次出现顺序。
3. 单个标签最长 `16` 字符,单次最多 `8` 个标签。
4. 当前不做中英文互译,不把中文标签改写为英文。
## 4. 邀请码授予流程
用户填写邀请码时,后端按原有校验顺序完成身份、绑定状态、邀请码存在、自邀请与时间窗校验。校验通过后:
1. 写入 `profile_referral_relation`
2. 发放原有双方奖励。
3. 读取 `profile_invite_code.granted_user_tags`
4. 将这些标签合并进 `user_account.user_tags`
管理员更新邀请码时,`grantedUserTags` 代表覆盖该邀请码之后授予的标签集合;空数组代表不授予标签。更新邀请码不会回溯修改已经使用过该邀请码的账号。
## 5. API 契约
后台邀请码 upsert 请求增加:
```json
{
"inviteCode": "BEIKE2026",
"grantedUserTags": ["北科"],
"metadata": {},
"startsAt": null,
"expiresAt": null
}
```
后台邀请码列表和 upsert 返回增加同名字段:
```json
{
"inviteCode": "BEIKE2026",
"grantedUserTags": ["北科"]
}
```
用户侧邀请中心、账号资料、登录返回和普通 profile 接口不返回 `userTags`
## 6. 拼图排行榜展示
拼图排行榜返回项增加 `visibleTags: string[]`
服务端构造排行榜时,从 `user_account.user_tags` 中仅投影允许公开展示的标签。首版公开展示白名单:
```text
北科
```
前端拼图通关弹窗按如下规则展示:
1. 昵称保持第一行。
2. `visibleTags` 非空时在昵称下方显示小标签。
3. 没有 `visibleTags` 时不占额外文案。
4. 本地兜底 run 的榜单 `visibleTags` 始终为空。
## 7. 验收
1. 新账号 `user_account.user_tags` 默认为空。
2. 后台创建邀请码时可填写 `北科`,列表和结果面板可回显。
3. 用户填写该邀请码后,账号表 `user_tags` 包含 `北科`
4. 不带标签的邀请码不改变账号标签。
5. 拼图排行榜中带 `北科` 的用户昵称下方显示 `北科`,其它标签不显示。
6. 执行 `npm run check:encoding``cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml`,并按影响范围执行后台 typecheck / 拼图前端测试。

View File

@@ -110,12 +110,13 @@ VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS=180000
1. 所有 GPT-image-2 生图请求都走 `POST {VECTOR_ENGINE_BASE_URL}/v1/images/generations`
2. 请求体 `model = gpt-image-2-all`,尺寸为 VectorEngine 支持的像素尺寸。
3. 请求体不再包含 `official_fallback`
4. 参考图字段使用 `image`,不再使用 APIMart 的 `image_urls`
4. 参考图使用 `POST {VECTOR_ENGINE_BASE_URL}/v1/images/generations`;有参考图且处于 AI 重绘时改走 `POST {VECTOR_ENGINE_BASE_URL}/v1/images/edits`;入口页关闭 AI 重绘时直接应用上传图,不调用图片生成
5. 拼图入口页上传图生成首图后,返回的首关 `pictureReference` 保留该 Data URL结果页重新生成在用户未重新上传参考图时会继续把 `pictureReference` 作为 `referenceImageSrc` 传给后端。
6. 缺少 `VECTOR_ENGINE_BASE_URL``VECTOR_ENGINE_API_KEY` 时返回 `503 SERVICE_UNAVAILABLE``details.provider = "vector-engine"`
7. 上游错误映射为 `502 UPSTREAM_ERROR`,保留 `upstreamStatus`、业务 message 和截断后的 raw excerpt
8. 运行 `npm run check:encoding``cargo test -p api-server openai_image --manifest-path server-rs/Cargo.toml``cargo test -p api-server puzzle --manifest-path server-rs/Cargo.toml``cargo test -p api-server custom_world_ai --manifest-path server-rs/Cargo.toml``cargo test -p api-server character_visual --manifest-path server-rs/Cargo.toml`
9. 后端改动后使用 `npm run api-server` 重启,并确认 `/healthz`
6. 拼图有参考图时,后端 prompt 会显式要求以参考图为第一优先级,保留主体、构图、视角、姿态、配色和光影氛围;入口页会把参考图压到单边 1024 以内,后端拒绝超过 8MB 的参考图字节
7. 缺少 `VECTOR_ENGINE_BASE_URL``VECTOR_ENGINE_API_KEY` 时返回 `503 SERVICE_UNAVAILABLE``details.provider = "vector-engine"`
8. 上游错误映射为 `502 UPSTREAM_ERROR`,保留 `upstreamStatus`、业务 message 和截断后的 raw excerpt
9. 运行 `npm run check:encoding``cargo test -p api-server openai_image --manifest-path server-rs/Cargo.toml``cargo test -p api-server puzzle --manifest-path server-rs/Cargo.toml``cargo test -p api-server custom_world_ai --manifest-path server-rs/Cargo.toml``cargo test -p api-server character_visual --manifest-path server-rs/Cargo.toml`
10. 后端改动后使用 `npm run api-server` 重启,并确认 `/healthz`
## 拼图链路排障日志