1
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
> **For Hermes:** Use subagent-driven-development skill to implement this plan task-by-task.
|
||||
|
||||
**Goal:** 在百梦后台新增“埋点数据”页,展示每条埋点原始事件的详细字段,并支持导出为 Excel 可直接打开的表格文件。
|
||||
**Goal:** 在陶泥儿后台新增“埋点数据”页,展示每条埋点原始事件的详细字段,并支持导出为 Excel 可直接打开的表格文件。
|
||||
|
||||
**Architecture:** 后端继续由 `api-server` 作为后台 BFF,经 SpacetimeDB HTTP SQL 只读查询 `tracking_event`,不改变表结构和 reducer。前端在 `apps/admin-web` 中新增独立路由与页面,页面渲染后端返回的原始明细,并在浏览器侧导出 Excel 兼容的 `.xls` HTML 表格,避免新增依赖。
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
修复:
|
||||
|
||||
1. 在 `map_password_entry_error(...)` 中补充 `InvalidPublicUserCode`
|
||||
2. 返回中文错误文案 `百梦号格式不正确`
|
||||
2. 返回中文错误文案 `陶泥号格式不正确`
|
||||
|
||||
### 3.3 `module-custom-world` 的 `Display` 分支未覆盖新字段错误
|
||||
|
||||
|
||||
@@ -34,9 +34,10 @@ GENARRATIVE_LLM_BASE_URL=
|
||||
GENARRATIVE_LLM_API_KEY=
|
||||
GENARRATIVE_LLM_MODEL=
|
||||
|
||||
# APIMart / OpenAI 兼容 Responses 文本网关
|
||||
# APIMart / OpenAI 兼容 Responses 文本网关与抓大鹅 nanobanana 物品素材图
|
||||
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
|
||||
@@ -104,10 +105,10 @@ HYPER3D_MODEL_REQUEST_TIMEOUT_MS / RODIN_MODEL_REQUEST_TIMEOUT_MS
|
||||
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。
|
||||
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 配置。
|
||||
9. APIMart 当前保留给创意 Agent 的 `gpt-5` Responses 文本/多模态理解链路,并用于抓大鹅物品素材 sheet 的 `nanobanana2` / Gemini 图片模型;GPT-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 草稿素材生成需要同时具备 VectorEngine 与 OSS 配置:VectorEngine 负责 `gpt-image-2-all` 生成 1K 素材图,OSS 负责保存 5x5 切割后的五视角图片。缺少 VectorEngine 或 OSS 时应通过 `error.details.reason` 向前端暴露具体缺项,不能只显示泛化“服务暂不可用”。素材图生成、封面生成和背景图生成在调用 VectorEngine 前必须先预检 OSS,避免已消耗外部生图后才发现无法落库。
|
||||
12. 抓大鹅 2D 草稿素材生成需要同时具备 APIMart、VectorEngine 与 OSS 配置:APIMart `gemini-3.1-flash-image-preview` 负责生成 5x5 物品素材 sheet,VectorEngine `gpt-image-2-all` 负责封面、9:16 背景图和 1:1 容器 UI 图,OSS 负责保存切割后的五视角图片及其它生成图。缺少 APIMart、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` 读取。
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 资产操作光点消耗接入方案
|
||||
# 资产操作泥点消耗接入方案
|
||||
|
||||
## 背景
|
||||
|
||||
当前光点钱包余额、充值流水与邀请奖励已经收口到 `server-rs/crates/spacetime-module/src/runtime/profile.rs`。资产图片生成和作品发布由 Axum API 调用外部模型或写入业务状态,SpacetimeDB reducer/procedure 不能直接执行外部网络生成,因此计费需要拆成两层:
|
||||
当前泥点钱包余额、充值流水与邀请奖励已经收口到 `server-rs/crates/spacetime-module/src/runtime/profile.rs`。资产图片生成和作品发布由 Axum API 调用外部模型或写入业务状态,SpacetimeDB reducer/procedure 不能直接执行外部网络生成,因此计费需要拆成两层:
|
||||
|
||||
- SpacetimeDB 负责钱包余额和流水的原子变更。
|
||||
- Axum 资产操作服务负责在执行业务资产操作前扣费,并在生成、持久化或发布失败时补偿退款。
|
||||
@@ -26,17 +26,17 @@
|
||||
暂不接入以下入口:
|
||||
|
||||
- 旧资产工坊角色主形象/动作生成接口:当前仍使用 `asset-tool` 作为兼容归属,无法确认真实用户。
|
||||
- 手动上传封面:不调用外部生成模型,不消耗光点。
|
||||
- 手动上传封面:不调用外部生成模型,不消耗泥点。
|
||||
- 自定义世界草稿自动补图链路:属于后台补全流程,避免一次用户操作触发多笔不可预期扣费。
|
||||
- 文本实体、NPC 生成:本次需求聚焦图片资产和发布资产操作,首期只覆盖可明确归属的入口。
|
||||
|
||||
## 计费规则
|
||||
|
||||
- 每次可计费资产操作消耗 `1` 枚光点。
|
||||
- 例外:Match3D / 抓大鹅草稿生成是一次完整草稿外部生成动作,固定消耗 `10` 枚光点;流水仍复用 `asset_operation_consume` / `asset_operation_refund`,`asset_kind = match3d_draft_generation`。
|
||||
- 例外:拼图 / 抓大鹅背景音乐生成固定消耗 `5` 枚光点;物品点击音效仍按单个音效任务消耗 `10` 枚光点。
|
||||
- 例外:拼图 / 抓大鹅 UI 背景重新生成固定消耗 `2` 枚光点。
|
||||
- 例外:抓大鹅结果页批量新增物品素材按实际可新增物品名计费,每 `5` 个消耗 `2` 枚光点,不足 `5` 个向上按 `5` 个计。重复名称、作品中已有名称和超过容量上限的名称不进入计费数量。
|
||||
- 每次可计费资产操作消耗 `1` 枚泥点。
|
||||
- 例外:Match3D / 抓大鹅草稿生成是一次完整草稿外部生成动作,固定消耗 `10` 枚泥点;流水仍复用 `asset_operation_consume` / `asset_operation_refund`,`asset_kind = match3d_draft_generation`。
|
||||
- 例外:拼图 / 抓大鹅背景音乐生成固定消耗 `5` 枚泥点;物品点击音效仍按单个音效任务消耗 `10` 枚泥点。
|
||||
- 例外:拼图 / 抓大鹅 UI 背景重新生成固定消耗 `2` 枚泥点。
|
||||
- 例外:抓大鹅结果页批量新增物品素材按实际可新增物品名计费,每 `5` 个消耗 `2` 枚泥点,不足 `5` 个向上按 `5` 个计。重复名称、作品中已有名称和超过容量上限的名称不进入计费数量。
|
||||
- 图片生成和作品发布都按资产操作计费;余额不足时禁止继续执行。
|
||||
- 在调用外部图片生成或发布 mutation 前预扣,余额不足时直接返回业务错误,不继续调用后续资产操作。
|
||||
- 如果图片生成、远程下载、OSS 写入、资产记录确认或发布 mutation 失败,资产操作服务自动发起同额退款。
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
## 钱包流水
|
||||
|
||||
公开两个流水来源类型,统一覆盖“资产生成”和“资产发布”这两类资产操作。流水金额由具体资产操作成本决定,不再假定所有资产操作都是 `1` 枚光点:
|
||||
公开两个流水来源类型,统一覆盖“资产生成”和“资产发布”这两类资产操作。流水金额由具体资产操作成本决定,不再假定所有资产操作都是 `1` 枚泥点:
|
||||
|
||||
- `asset_operation_consume`:资产操作预扣,`amount_delta = -points_cost`。
|
||||
- `asset_operation_refund`:资产操作失败退款,`amount_delta = +points_cost`。
|
||||
|
||||
@@ -34,7 +34,7 @@ Stage 1 已把 Rust 鉴权快照同步到 SpacetimeDB 的 `auth_store_snapshot`
|
||||
| 字段 | 类型 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `user_id` | `String` | 主键。 |
|
||||
| `public_user_code` | `String` | 公开百梦号。 |
|
||||
| `public_user_code` | `String` | 公开陶泥号。 |
|
||||
| `username` | `String` | 当前账号用户名。 |
|
||||
| `display_name` | `String` | 展示名。 |
|
||||
| `phone_number_masked` | `Option<String>` | 脱敏手机号。 |
|
||||
|
||||
@@ -44,5 +44,6 @@
|
||||
2. 草稿 / 已发布筛选计数统一从 `CreationWorkShelfItem.status` 读取。
|
||||
3. 卡片渲染不再直接判断 `publicationStatus` 或不同 works schema 的标题字段。
|
||||
4. 统一货架按 `updatedAt` 倒序排序,兼容 ISO 字符串和 `seconds.microsZ` 后端时间文本。
|
||||
5. 作品卡片以 `coverImageSrc` 作为整卡背景;卡片不展示最后修改时间,`updatedAt` 只参与排序。
|
||||
6. 现有创作中心交互测试通过。
|
||||
5. 作品卡片以 `coverImageSrc` 作为整卡背景;若 `coverImageSrc` 为空,允许从同一作品已有的关卡图、背景图或素材图兜底,避免草稿页退回普通面板视觉。
|
||||
6. 卡片不展示最后修改时间,`updatedAt` 只参与排序。
|
||||
7. 现有创作中心交互测试通过。
|
||||
|
||||
@@ -582,7 +582,7 @@ puzzle_creative_level_generation_plan
|
||||
- Agent 选择理由
|
||||
- 支持单关卡、多关卡或二者皆可
|
||||
- 计划关卡数
|
||||
- 预计积分范围,例如 `预计消耗 8 到 18 光点`
|
||||
- 预计积分范围,例如 `预计消耗 8 到 18 泥点`
|
||||
|
||||
积分范围来自拼图模板协议:
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# 自定义世界草稿场景幕事件与任务字段落地设计(2026-04-25)
|
||||
# 自定义世界草稿场景幕事件与任务字段落地设计(2026-04-25)
|
||||
|
||||
## 背景
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
- 当前场景的核心任务描述。
|
||||
- 文本会作为游戏中首次进入某个场景生成章节任务的关键上下文。
|
||||
- 必须结合场景描述、场景入口钩子、出场角色与 3 幕事件,说明玩家首次进入该场景时要完成什么。
|
||||
- 世界档案的场景详情页必须直接展示该字段,便于百梦主确认每个场景的默认章节任务。
|
||||
- 世界档案的场景详情页必须直接展示该字段,便于陶泥儿主确认每个场景的默认章节任务。
|
||||
|
||||
### Landmark 生成源字段
|
||||
|
||||
|
||||
@@ -408,7 +408,7 @@ Node 侧入口位于:
|
||||
|
||||
## 10.2 2026-05-01 新用户注册赠送修正
|
||||
|
||||
新注册用户默认获得 `10` 个光点,注册链路通过 SpacetimeDB procedure 写入 `profile_dashboard_state.wallet_balance` 与 `profile_wallet_ledger`。流水来源为 `new_user_registration_reward`,流水 ID 固定为 `new-user-registration:{user_id}`,重复调用不重复发放。
|
||||
新注册用户默认获得 `10` 个泥点,注册链路通过 SpacetimeDB procedure 写入 `profile_dashboard_state.wallet_balance` 与 `profile_wallet_ledger`。流水来源为 `new_user_registration_reward`,流水 ID 固定为 `new-user-registration:{user_id}`,重复调用不重复发放。
|
||||
|
||||
注册赠送、邀请码奖励、充值、兑换码、资产扣费等都属于真实平台钱包流水。用户只要已经存在非 `snapshot_sync` 钱包流水,后续 `runtime_snapshot.game_state.playerCurrency` 不再覆盖 `wallet_balance`,只继续刷新游玩时长和玩过世界,避免首次保存旧运行态货币字段时把注册赠送覆盖成 `0`。
|
||||
|
||||
|
||||
@@ -34,17 +34,17 @@
|
||||
`match3d_compile_draft` action 的后端顺序为:
|
||||
|
||||
1. 读取 session config。
|
||||
2. 对本次 `match3d_compile_draft` 生成动作按 `sessionId + profileId + action 时间戳` 构造幂等流水并预扣 `10` 光点。余额不足时不继续创建草稿;后续任一步失败时自动按同额退款。
|
||||
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 步的本地兜底,不阻断草稿。
|
||||
6. 后端把生成计划中的 `gameName` 和 `summary` 写入 `match3d_work_profile` 作品信息后,自动调用作品标签生成器。标签生成器使用题材、作品名称和作品描述生成 3 到 6 个中文短标签;若调用失败或返回不足,则使用生成计划 tags 和本地兜底标签补齐。结果页手动 `AI生成作品标签` 也使用同一接口,并传入当前作品描述。
|
||||
7. 后端从同一份作品生成计划读取当前难度所需数量的短物品名称和音效提示词;不得再只生成物品名称而丢失后续音效生成上下文。
|
||||
8. 调用项目当前图片链路 VectorEngine `gpt-image-2-all` 生成 `1:1`、`1024x1024` 素材图,提示词必须合入入口页选择的 `assetStylePrompt`,并强制每格使用统一纯绿色绿幕背景,避免白底或纹理背景进入运行态素材。历史 `nanobanana2` 图片选项当前按项目统一决策回落到 VectorEngine,不重新接入 APIMart 图片网关。
|
||||
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` 链路。
|
||||
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`。音乐生成失败只记录 warning,不阻断草稿页进入,用户可在结果页 `素材配置 > 背景音乐` 重试。
|
||||
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 与封面。
|
||||
@@ -204,7 +204,7 @@ Match3DWorkProfile / PlatformMatch3DGalleryCard
|
||||
|
||||
详情页不再展示参考图、用途、模型提示词、文生/图生切换、状态查询、下载列表、taskUuid 或 subscriptionKey。
|
||||
|
||||
`物品素材` 列表项点击必须弹出独立预览面板,不允许在列表右侧或列表下方内联展示。列表本身使用移动端至少两列的多列卡片布局;每个列表项只展示图片预览、物品名称和垃圾箱删除图标,不展示用途、状态胶囊、视角数量或 `2D素材` 标记。预览面板只承担查看五视角图片、编辑素材名称、编辑点击音效提示词和生成点击音效;不再展示 `重新生成` 按钮。列表项自身支持单项删除,删除后立即把剩余 `generatedItemAssets` 写回作品 profile。批量新增通过列表顶部按钮打开独立面板,面板内每个输入框只输入一个物品名称,`新增物品名称` 按钮追加一个输入框;提交后按输入框顺序清洗、去重并调用 Match3D 作品批量生图接口。生成进度同时显示在批量新增面板和 `素材配置 > 物品` 列表顶部,面板可关闭,后台生成继续推进,不阻塞封面、音频等其他生成操作。后端复用草稿生成的素材图、切图、OSS 上传和可选点击音效流程,但仅按实际可新增名称持久化,不重新生成已有物品,不新增 SpacetimeDB 表,最终仍写回同一份 `generated_item_assets_json`。批量新增先补齐到 `5` 个参与整图生成,随后丢弃补齐用临时物品,只对真实新增物品抠背景、切割和上传。批量新增计费按实际可新增名称每 `5` 个消耗 `2` 光点,不足 `5` 个向上取整;重复名称、已有名称和超过容量上限的名称不计费。
|
||||
`物品素材` 列表项点击必须弹出独立预览面板,不允许在列表右侧或列表下方内联展示。列表本身使用移动端至少两列的多列卡片布局;每个列表项只展示图片预览、物品名称和垃圾箱删除图标,不展示用途、状态胶囊、视角数量或 `2D素材` 标记。预览面板只承担查看五视角图片、编辑素材名称、编辑点击音效提示词和生成点击音效;不再展示 `重新生成` 按钮。列表项自身支持单项删除,删除后立即把剩余 `generatedItemAssets` 写回作品 profile。批量新增通过列表顶部按钮打开独立面板,面板内每个输入框只输入一个物品名称,`新增物品名称` 按钮追加一个输入框;提交后按输入框顺序清洗、去重并调用 Match3D 作品批量生图接口。生成进度同时显示在批量新增面板和 `素材配置 > 物品` 列表顶部,面板可关闭,后台生成继续推进,不阻塞封面、音频等其他生成操作。后端复用草稿生成的素材图、切图、OSS 上传和可选点击音效流程,但仅按实际可新增名称持久化,不重新生成已有物品,不新增 SpacetimeDB 表,最终仍写回同一份 `generated_item_assets_json`。批量新增先补齐到 `5` 个参与整图生成,随后丢弃补齐用临时物品,只对真实新增物品抠背景、切割和上传。批量新增计费按实际可新增名称每 `5` 个消耗 `2` 泥点,不足 `5` 个向上取整;重复名称、已有名称和超过容量上限的名称不计费。
|
||||
|
||||
## 6.1 音频生成与扣费
|
||||
|
||||
@@ -214,9 +214,9 @@ Match3DWorkProfile / PlatformMatch3DGalleryCard
|
||||
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 转存或资产绑定失败时后端自动退款。前端只展示生成按钮和进度,不自行计算或写入钱包。
|
||||
5. `POST /api/creation/audio/background-music/{task_id}/asset` 和 `POST /api/creation/audio/sound-effect/{task_id}/asset` 在真正拿到音频并转存资产前,由后端按 `taskId + 资产槽位` 幂等预扣;背景音乐扣 `5` 泥点,物品点击音效扣 `10` 泥点。任务仍在处理中时不扣费。资产下载、OSS 转存或资产绑定失败时后端自动退款。前端只展示生成按钮和进度,不自行计算或写入钱包。
|
||||
|
||||
创作入口不展示 `生成音效` Toggle。草稿生成阶段不产生物品点击音效任务,也不产生点击音效相关扣费;入口只产生一次固定 `10` 光点的草稿生成扣费。结果页 `素材配置 > UI` 重新生成背景固定扣 `2` 光点。物品点击音效由结果页 `素材配置 > 物品` 详情面板手动触发,每个音效按单独任务和单独 `match3d_click_sound` 资产槽位扣费。音效生成失败不影响草稿,失败素材保留 `soundPrompt`,用户可在结果页物品详情面板手动重试。
|
||||
创作入口不展示 `生成音效` Toggle。草稿生成阶段不产生物品点击音效任务,也不产生点击音效相关扣费;入口只产生一次固定 `10` 泥点的草稿生成扣费。结果页 `素材配置 > UI` 重新生成背景固定扣 `2` 泥点。物品点击音效由结果页 `素材配置 > 物品` 详情面板手动触发,每个音效按单独任务和单独 `match3d_click_sound` 资产槽位扣费。音效生成失败不影响草稿,失败素材保留 `soundPrompt`,用户可在结果页物品详情面板手动重试。
|
||||
|
||||
## 7. 验收
|
||||
|
||||
@@ -238,4 +238,4 @@ cargo check -p spacetime-client --manifest-path server-rs\Cargo.toml
|
||||
cargo check -p spacetime-module --manifest-path server-rs\Cargo.toml
|
||||
```
|
||||
|
||||
真实草稿生成需要本地私密环境配置 `VECTOR_ENGINE_BASE_URL` / `VECTOR_ENGINE_API_KEY`,以及完整 `ALIYUN_OSS_BUCKET`、`ALIYUN_OSS_ENDPOINT`、`ALIYUN_OSS_ACCESS_KEY_ID`、`ALIYUN_OSS_ACCESS_KEY_SECRET`。如果只配置 bucket 和 endpoint,抓大鹅素材、封面或背景生成会在调用 VectorEngine 前返回 `OSS 未完成环境变量配置`,`details.missingEnv` 会列出缺少的 AccessKey 项;不要回退到 Rodin/GLB 或伪造本地上传成功。开启音频生成还需要对应音频上游配置。后端改动后使用 `npm run api-server` 启动,并检查 `/healthz`。
|
||||
真实草稿生成需要本地私密环境配置 `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`。
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
>
|
||||
> 2026-05-13 补充:草稿素材实际生成数量按 `5` 的倍数向上补齐,补齐物品同样需要生成名称和五视角图片。素材图提示词固定要求 `5*5` 严格均匀排布,禁止主体跨格、贴边或越界影响裁剪效果。
|
||||
>
|
||||
> 2026-05-13 补充:创作页隐藏抓大鹅 `生成音效` Toggle;草稿生成固定预扣 `10` 光点,按钮展示 `消耗10光点`。点击音效生成只保留在结果页 `素材配置 > 物品` 详情面板中手动触发。
|
||||
> 2026-05-13 补充:创作页隐藏抓大鹅 `生成音效` Toggle;草稿生成固定预扣 `10` 泥点,按钮展示 `消耗10泥点`。点击音效生成只保留在结果页 `素材配置 > 物品` 详情面板中手动触发。
|
||||
|
||||
## 1. 阶段边界
|
||||
|
||||
@@ -69,7 +69,7 @@ badge: 可创建
|
||||
|
||||
自定义风格必须在弹出面板中填写描述后才能应用。入口表单必须在移动端创作页可视区内完成题材、风格、难度和生成按钮的展示,页面自身不产生纵向滚动;风格卡只允许横向滑动。
|
||||
|
||||
生成按钮文案为 `生成抓大鹅草稿`,按钮内必须同时展示 `消耗10光点`。UI 中不默认展示玩法规则长文,也不展示隐藏派生数值的摘要框。
|
||||
生成按钮文案为 `生成抓大鹅草稿`,按钮内必须同时展示 `消耗10泥点`。UI 中不默认展示玩法规则长文,也不展示隐藏派生数值的摘要框。
|
||||
|
||||
## 5. mock client
|
||||
|
||||
@@ -115,7 +115,7 @@ POST /api/creation/match3d/sessions/:sessionId/compile
|
||||
2. 切换到 `抓大鹅` Tab 后,页面内直接显示抓大鹅入口表单,不提前创建会话。
|
||||
3. 表单不展示参考图、`需要消除次数`、`难度数值`、`题材`、`物品`、`难度`摘要框。
|
||||
4. 输入题材、选择风格和难度后,提交 payload 包含派生后的 `clearCount` 与 `difficulty`,`referenceImageSrc` 为 `null`,并包含 `assetStyleId`、`assetStyleLabel` 与 `assetStylePrompt`。
|
||||
5. 生成按钮展示 `消耗10光点`,创作页不展示 `生成音效` Toggle。
|
||||
5. 生成按钮展示 `消耗10泥点`,创作页不展示 `生成音效` Toggle。
|
||||
6. 点击 `自定义` 风格弹出独立面板,填写后应用到提交 payload;未填写时不能应用空自定义风格。
|
||||
7. 移动端创作页内抓大鹅入口内容不产生纵向滚动,风格卡横向滑动。
|
||||
8. 点击生成后创建会话并进入草稿生成/结果页链路。
|
||||
|
||||
@@ -6,33 +6,33 @@
|
||||
|
||||
本轮在“我的”页面的“会员充值”入口落地账户充值弹窗,包含两个页签:
|
||||
|
||||
1. `光点充值`
|
||||
1. `泥点充值`
|
||||
2. `会员卡充值`
|
||||
|
||||
前端只负责展示与发起购买,套餐、价格、赠送规则、会员权益、生效时间、钱包余额与交易流水统一由 `server-rs` 后端返回。普通 H5 / 本地联调继续使用 `mock` 渠道:创建订单后立即写入余额或会员状态,并返回最新账户中心快照。微信小程序 web-view 使用 `wechat_mp` 渠道:创建订单时只写入 `pending` 订单并返回小程序 `wx.requestPayment` 参数,真实到账以后端微信支付通知为准。
|
||||
|
||||
## 2. 产品规则
|
||||
|
||||
### 2.1 光点充值套餐
|
||||
### 2.1 泥点充值套餐
|
||||
|
||||
| productId | 光点 | 金额分 | 徽标 | 说明 |
|
||||
| productId | 泥点 | 金额分 | 徽标 | 说明 |
|
||||
| ------------- | ---: | -----: | -------- | -------------- |
|
||||
| `points_60` | 60 | 600 | 首充双倍 | 首充送60光点 |
|
||||
| `points_180` | 180 | 1800 | 首充双倍 | 首充送180光点 |
|
||||
| `points_300` | 300 | 3000 | 首充双倍 | 首充送300光点 |
|
||||
| `points_680` | 680 | 6800 | 首充双倍 | 首充送680光点 |
|
||||
| `points_1280` | 1280 | 12800 | 首充双倍 | 首充送1280光点 |
|
||||
| `points_3280` | 3280 | 32800 | 首充双倍 | 首充送3280光点 |
|
||||
| `points_60` | 60 | 600 | 首充双倍 | 首充送60泥点 |
|
||||
| `points_180` | 180 | 1800 | 首充双倍 | 首充送180泥点 |
|
||||
| `points_300` | 300 | 3000 | 首充双倍 | 首充送300泥点 |
|
||||
| `points_680` | 680 | 6800 | 首充双倍 | 首充送680泥点 |
|
||||
| `points_1280` | 1280 | 12800 | 首充双倍 | 首充送1280泥点 |
|
||||
| `points_3280` | 3280 | 32800 | 首充双倍 | 首充送3280泥点 |
|
||||
|
||||
光点充值固定为 `¥6 / ¥18 / ¥30 / ¥68 / ¥128 / ¥328` 六个档位。全部档位参与首充双倍:用户历史上没有 `points_recharge` 流水时,本次购买到账光点为基础光点与等额赠送光点之和;已有充值流水后只到账基础光点。实际到账光点写入交易流水,余额以 SpacetimeDB projection 为准。
|
||||
泥点充值固定为 `¥6 / ¥18 / ¥30 / ¥68 / ¥128 / ¥328` 六个档位。全部档位参与首充双倍:用户历史上没有 `points_recharge` 流水时,本次购买到账泥点为基础泥点与等额赠送泥点之和;已有充值流水后只到账基础泥点。实际到账泥点写入交易流水,余额以 SpacetimeDB projection 为准。
|
||||
|
||||
### 2.2 会员卡套餐
|
||||
|
||||
| productId | 类型 | 天数 | 金额分 | 权益 |
|
||||
| --------------- | ---- | ---: | -----: | --------------------------------- |
|
||||
| `member_month` | 月卡 | 30 | 2800 | 免光点回合数100,每日签到加成0% |
|
||||
| `member_season` | 季卡 | 90 | 7800 | 免光点回合数100,每日签到加成100% |
|
||||
| `member_year` | 年卡 | 365 | 24800 | 免光点回合数100,每日签到加成210% |
|
||||
| `member_month` | 月卡 | 30 | 2800 | 免泥点回合数100,每日签到加成0% |
|
||||
| `member_season` | 季卡 | 90 | 7800 | 免泥点回合数100,每日签到加成100% |
|
||||
| `member_year` | 年卡 | 365 | 24800 | 免泥点回合数100,每日签到加成210% |
|
||||
|
||||
购买会员时,如果当前会员仍有效,则从当前到期时间顺延;如果已过期或从未购买,则从当前服务端时间开始计算。状态只区分 `普通` 与已生效会员,前端不自行推断。
|
||||
|
||||
@@ -42,8 +42,8 @@
|
||||
|
||||
需要 Bearer JWT。返回:
|
||||
|
||||
1. 当前光点余额、会员状态、到期时间
|
||||
2. 光点套餐与会员套餐
|
||||
1. 当前泥点余额、会员状态、到期时间
|
||||
2. 泥点套餐与会员套餐
|
||||
3. 会员权益表
|
||||
4. 最近订单摘要
|
||||
|
||||
@@ -65,8 +65,8 @@
|
||||
1. 校验 `productId`
|
||||
2. `paymentChannel = "mock"` 时后端创建已支付订单
|
||||
3. `paymentChannel = "wechat_mp"` 时后端创建待支付订单,并调用微信支付 JSAPI 下单生成小程序支付参数
|
||||
4. mock 光点套餐立即写入钱包余额与流水,mock 会员套餐立即写入会员状态
|
||||
5. wechat_mp 订单不提前发光点或会员,只返回待支付订单、账户中心快照与 `wechatMiniProgramPayParams`
|
||||
4. mock 泥点套餐立即写入钱包余额与流水,mock 会员套餐立即写入会员状态
|
||||
5. wechat_mp 订单不提前发泥点或会员,只返回待支付订单、账户中心快照与 `wechatMiniProgramPayParams`
|
||||
|
||||
兼容路径:`POST /api/runtime/profile/recharge/orders`
|
||||
|
||||
@@ -113,15 +113,15 @@
|
||||
|
||||
1. “我的”页会员充值按钮打开独立弹窗,不在当前面板下方展开。
|
||||
2. 弹窗顶部标题为 `账户充值`,右上角关闭。
|
||||
3. 默认打开 `光点充值`,可切换到 `会员卡充值`。
|
||||
3. 默认打开 `泥点充值`,可切换到 `会员卡充值`。
|
||||
4. 点击套餐后调用下单接口,按钮进入处理中状态;小程序环境走 native 支付页拉起 `wx.requestPayment`,支付页返回后刷新 `profileDashboard`。
|
||||
5. 弹窗内不写大段说明文案,只保留必要金额、光点、会员权益和状态反馈。
|
||||
5. 弹窗内不写大段说明文案,只保留必要金额、泥点、会员权益和状态反馈。
|
||||
6. 会员卡充值区以套餐卡片优先展示周期、价格和处理状态;移动端单列,桌面端三列,权益表允许横向滚动,避免小屏挤压。
|
||||
|
||||
## 5. 验收
|
||||
|
||||
1. 普通用户打开弹窗能看到光点与会员套餐。
|
||||
2. 光点购买后余额增加,流水来源为 `points_recharge`。
|
||||
3. 首充赠送只在首次光点充值时生效。
|
||||
1. 普通用户打开弹窗能看到泥点与会员套餐。
|
||||
2. 泥点购买后余额增加,流水来源为 `points_recharge`。
|
||||
3. 首充赠送只在首次泥点充值时生效。
|
||||
4. 会员购买后会员状态与到期时间立即更新。
|
||||
5. 移动端弹窗单列可滚动,桌面端接近参考图卡片网格。
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
|
||||
## 2. 前端交互
|
||||
|
||||
### 2.1 百梦号复制
|
||||
### 2.1 陶泥号复制
|
||||
|
||||
1. 点击“我的”页百梦号后的复制按钮后,按钮文案临时切换为 `已复制`。
|
||||
1. 点击“我的”页陶泥号后的复制按钮后,按钮文案临时切换为 `已复制`。
|
||||
2. 复制失败时临时切换为 `复制失败`。
|
||||
3. 状态自动恢复为 `复制`。
|
||||
|
||||
@@ -84,7 +84,7 @@ SpacetimeDB 正式表 `user_account` 需要增加 `avatar_url: Option<String>`
|
||||
## 5. 验收
|
||||
|
||||
1. 创作页已发布作品分享按钮点击后显示 `已复制`。
|
||||
2. “我的”页百梦号复制按钮点击后显示 `已复制`。
|
||||
2. “我的”页陶泥号复制按钮点击后显示 `已复制`。
|
||||
3. “我的”页不展示 `手机号` 与 `正常` 标签。
|
||||
4. 昵称编辑成功后,资料卡与顶部账号入口同步新昵称。
|
||||
5. 昵称与头像裁剪弹窗面板不透明,不能露出底层页面内容。
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
在现有“我的”Tab 功能入口区(常用功能)落地三个轻量入口,入口顺序固定为 `邀请好友`、`填邀请码`、`玩家社区`:
|
||||
|
||||
1. `邀请好友`:弹出面板展示当前账号绑定的邀请码、邀请奖励规则和成功邀请用户列表。
|
||||
2. `填邀请码`:弹出面板填写邀请码,成功后邀请者与被邀请者各获得 `30` 光点。
|
||||
2. `填邀请码`:弹出面板填写邀请码,成功后邀请者与被邀请者各获得 `30` 泥点。
|
||||
3. `玩家社区`:弹出面板展示微信群与 QQ 群正式二维码图片。
|
||||
|
||||
## 后端边界
|
||||
|
||||
- 邀请码、邀请关系与奖励发放全部存入 `server-rs/crates/spacetime-module`。
|
||||
- Axum 只做鉴权、参数转发与响应映射,不在 API 层自行计算奖励。
|
||||
- 前端只读取后端状态与调用提交接口,不做本地加光点。
|
||||
- 前端只读取后端状态与调用提交接口,不做本地加泥点。
|
||||
- 钱包余额继续复用 `profile_dashboard_state.wallet_balance`。
|
||||
- 奖励流水继续复用 `profile_wallet_ledger`,新增来源类型:
|
||||
- `invite_inviter_reward`
|
||||
@@ -43,7 +43,7 @@
|
||||
- 每个用户拥有一个稳定邀请码,首次进入邀请中心时自动生成。
|
||||
- 用户不能填写自己的邀请码。
|
||||
- 用户最多填写一个邀请码,成功后不可修改。
|
||||
- 被邀请者绑定成功后获得 `30` 光点。
|
||||
- 被邀请者绑定成功后获得 `30` 泥点。
|
||||
- 邀请者每天最多获得 `10` 次邀请奖励,超过后关系仍可绑定,被邀请者仍获得奖励,邀请者当次不再加分。
|
||||
- 每次奖励都写入钱包流水,钱包余额以后端返回为准。
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
"invitedUsers": [
|
||||
{
|
||||
"userId": "user_001",
|
||||
"displayName": "百梦玩家",
|
||||
"displayName": "陶泥儿玩家",
|
||||
"avatarUrl": null,
|
||||
"boundAt": "2026-05-01T08:00:00Z"
|
||||
}
|
||||
@@ -89,10 +89,10 @@
|
||||
- `server-rs/crates/spacetime-module` 已新增邀请码与邀请关系表,邀请中心读取和填码绑定均通过 SpacetimeDB procedure 执行。
|
||||
- `server-rs/crates/api-server` 已挂接 `/api/runtime/profile/referrals/*` 与 `/api/profile/referrals/*` 两组路由。
|
||||
- 前端“我的”Tab 三个功能入口均打开独立弹窗,玩家社区使用 `media/social-media-group/wechat.png` 与 `media/social-media-group/qq.png` 两张正式二维码图片。
|
||||
- 复制邀请会复制邀请码和邀请链接;填码成功后刷新个人看板光点。
|
||||
- 邀请好友弹窗展示 `邀请一个用户注册,双方都可获得 30 光点。每日最多获得十次邀请奖励。`,不再展示“邀请 / 已奖 / 今日”三项统计。
|
||||
- 复制邀请会复制邀请码和邀请链接;填码成功后刷新个人看板泥点。
|
||||
- 邀请好友弹窗展示 `邀请一个用户注册,双方都可获得 30 泥点。每日最多获得十次邀请奖励。`,不再展示“邀请 / 已奖 / 今日”三项统计。
|
||||
- 邀请好友弹窗底部展示成功邀请用户头像和昵称列表;没有成功邀请时展示短空状态。
|
||||
- “我的”页 `邀请好友` 按钮副标题展示 `双方得30(光点icon)`;`玩家社区` 按钮副标题展示 `每日领福利`。
|
||||
- “我的”页 `邀请好友` 按钮副标题展示 `双方得30(泥点icon)`;`玩家社区` 按钮副标题展示 `每日领福利`。
|
||||
- “我的”页功能入口区不展示 `常用功能` 标题和 `快捷入口` 副标题,避免首屏重复说明类文案。
|
||||
|
||||
## 前端交互
|
||||
|
||||
@@ -36,5 +36,5 @@
|
||||
3. 未开放玩法点击态保持禁用,不应进入鉴权或创建会话链路。
|
||||
4. 已开放玩法点击后必须进入对应创建链路;若用户未登录,先走登录保护。
|
||||
5. 创作 Tab 首屏应显示“10分钟创作一个精品互动玩法”,并默认展示拼图创作表单。
|
||||
6. 智能创作入口隐藏后,不应出现“Hi, 朋友”“问一问百梦”或“一句话生成闪应用”等旧首页入口。
|
||||
6. 智能创作入口隐藏后,不应出现“Hi, 朋友”“问一问陶泥儿”或“一句话生成闪应用”等旧首页入口。
|
||||
7. 方洞挑战入口隐藏后,不应出现在创作 Tab 模板入口、创作中心顶部卡带、平台创作类型弹层和创作页作品架中;既有 `SH-` 作品号、广场详情和试玩 runtime 链路不因此删除。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 密码登录入口历史落地设计
|
||||
|
||||
> 2026-04-25 更新:当前产品策略已调整为“不开放密码注册”。新用户必须通过手机号验证码注册/登录,密码登录只面向已经登录后设置过密码的手机号账号。`POST /api/auth/entry` 只接受 `phone + password`,不支持邮箱、用户名或百梦号登录,也不承担自动建号能力。本文原有“密码自动建号”内容仅作为历史背景保留,当前落地以本更新和 [PASSWORD_LOGIN_CHANGE_RESET_DESIGN_2026-04-24.md](./PASSWORD_LOGIN_CHANGE_RESET_DESIGN_2026-04-24.md) 为准。
|
||||
> 2026-04-25 更新:当前产品策略已调整为“不开放密码注册”。新用户必须通过手机号验证码注册/登录,密码登录只面向已经登录后设置过密码的手机号账号。`POST /api/auth/entry` 只接受 `phone + password`,不支持邮箱、用户名或陶泥号登录,也不承担自动建号能力。本文原有“密码自动建号”内容仅作为历史背景保留,当前落地以本更新和 [PASSWORD_LOGIN_CHANGE_RESET_DESIGN_2026-04-24.md](./PASSWORD_LOGIN_CHANGE_RESET_DESIGN_2026-04-24.md) 为准。
|
||||
>
|
||||
> 2026-04-28 更新:为开发期本地/测试服联调新增服务端环境变量 `GENARRATIVE_DEV_PASSWORD_ENTRY_AUTO_REGISTER_ENABLED`,默认 `false`。仅当该变量显式为 `true` 时,`POST /api/auth/entry` 可对未知手机号用本次密码直接创建账号并登录;默认关闭时仍严格保持未知手机号返回 `401` 的生产语义。该开关不得用于生产环境,也不新增任何前端规则说明文案。
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
1. `api-server` 对外只暴露 `phone + password` 的最小接口。
|
||||
2. `module-auth` 只负责已存在手机号账号的密码校验。
|
||||
3. 密码入口不创建账号,不接收邮箱、用户名或百梦号。
|
||||
3. 密码入口不创建账号,不接收邮箱、用户名或陶泥号。
|
||||
4. 登录成功后与 JWT、refresh cookie 的衔接方式。
|
||||
|
||||
## 1.1 当前冻结结论
|
||||
@@ -239,7 +239,7 @@
|
||||
1. 未知手机号密码登录返回 `401`,且不创建账号。
|
||||
2. 已登录手机号账号设置密码后可用 `phone + password` 登录。
|
||||
3. 同手机号错误密码返回 `401`。
|
||||
4. 邮箱、用户名或百梦号作为密码登录标识返回 `400`。
|
||||
4. 邮箱、用户名或陶泥号作为密码登录标识返回 `400`。
|
||||
5. 登录成功时返回 access token。
|
||||
6. 登录成功时写回 refresh cookie。
|
||||
7. `GENARRATIVE_DEV_PASSWORD_ENTRY_AUTO_REGISTER_ENABLED` 默认关闭时行为不变。
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
沿用现有 `POST /api/auth/entry`:
|
||||
|
||||
1. 请求字段固定为 `phone`、`password`,前端只提交手机号。
|
||||
2. 后端只按标准手机号归一化后查找账号,不兼容邮箱、用户名、百梦号或历史开发游客标识。
|
||||
2. 后端只按标准手机号归一化后查找账号,不兼容邮箱、用户名、陶泥号或历史开发游客标识。
|
||||
3. 手机号不存在时返回 `401`,不创建账号。
|
||||
4. 手机号存在但未设置密码时返回 `401`。
|
||||
5. 校验成功后签发 access token,并写入 refresh cookie。
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
3. 匹配忽略大小写,允许用户输入去掉空格、连字符或下划线后的连续片段,例如 `PZEPUBLIC1` 命中 `PZ-EPUBLIC1`。
|
||||
4. 输入完整公开作品号并本地命中时,保留既有作品号直达行为。
|
||||
5. 输入模糊片段命中公开作品时,在首页直接展示搜索结果列表,点击结果打开对应作品详情。
|
||||
6. 当前公开作品列表无命中时,保留既有公开编号直达兜底,继续支持远端按作品号或百梦号查找。
|
||||
6. 当前公开作品列表无命中时,保留既有公开编号直达兜底,继续支持远端按作品号或陶泥号查找。
|
||||
|
||||
## 验收标准
|
||||
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
# 百梦产品命名规范落地说明
|
||||
# 陶泥儿产品命名规范落地说明
|
||||
|
||||
## 背景
|
||||
|
||||
平台对外中文命名统一使用以下称谓:
|
||||
|
||||
- 产品中文展示名:`百梦`
|
||||
- 平台内消费单位:`光点`
|
||||
- 公开账号标识:`百梦号`
|
||||
- 创作侧面向创作者称谓:`百梦主`
|
||||
- 产品中文展示名:`陶泥儿`
|
||||
- 平台内消费单位:`泥点`
|
||||
- 公开账号标识:`陶泥号`
|
||||
- 创作侧面向创作者称谓:`陶泥儿主`
|
||||
|
||||
## 落地边界
|
||||
|
||||
1. 前端页面、弹窗、测试断言和后端返回给用户的中文错误文案统一使用新称谓。
|
||||
2. SpacetimeDB 表字段、Rust/TypeScript contract 字段、流水来源枚举、`points_*` 商品 ID、`public_user_code` 字段名继续保持不变,避免引入数据库迁移和历史数据兼容风险。
|
||||
3. 公开编号现有 `SY-XXXXXXXX` 格式本轮不迁移,只调整用户可见标签为“百梦号”;编号格式如需改为新前缀,应另起迁移方案并同步老用户兼容策略。
|
||||
3. 公开编号现有 `SY-XXXXXXXX` 格式本轮不迁移,只调整用户可见标签为“陶泥号”;编号格式如需改为新前缀,应另起迁移方案并同步老用户兼容策略。
|
||||
4. 历史日志、构建产物、第三方依赖和生成绑定不参与本轮文本替换。
|
||||
|
||||
## 验收点
|
||||
|
||||
1. 首页、登录绑定页、我的页和搜索结果不再展示旧产品名。
|
||||
2. 钱包、充值、邀请、兑换码、资产计费和拼图道具确认文案统一展示“光点”。
|
||||
3. 账号公开标识相关错误和搜索空状态统一展示“百梦号”。
|
||||
4. 创作相关可见默认称谓使用“百梦主”。
|
||||
2. 钱包、充值、邀请、兑换码、资产计费和拼图道具确认文案统一展示“泥点”。
|
||||
3. 账号公开标识相关错误和搜索空状态统一展示“陶泥号”。
|
||||
4. 创作相关可见默认称谓使用“陶泥儿主”。
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
# 百梦产品命名替换落地说明
|
||||
# 陶泥儿产品命名替换落地说明
|
||||
|
||||
## 1. 本轮目标
|
||||
|
||||
本轮统一平台对外中文命名,当前生效称谓如下:
|
||||
|
||||
- 产品中文展示名:`百梦`
|
||||
- 平台内消费单位:`光点`
|
||||
- 公开账号标识:`百梦号`
|
||||
- 创作侧面向创作者称谓:`百梦主`
|
||||
- 产品中文展示名:`陶泥儿`
|
||||
- 平台内消费单位:`泥点`
|
||||
- 公开账号标识:`陶泥号`
|
||||
- 创作侧面向创作者称谓:`陶泥儿主`
|
||||
|
||||
## 2. 落地范围
|
||||
|
||||
1. 前端网页、管理后台、HTML 标题、metadata 与品牌标识统一展示“百梦”。
|
||||
2. 钱包、充值、邀请、兑换码、资产计费、拼图道具与作者激励统一展示“光点”。
|
||||
3. 公开账号标识、搜索兜底、登录限制与错误信息统一展示“百梦号”。
|
||||
4. 创作侧面向创作者的称谓统一展示“百梦主”。
|
||||
1. 前端网页、管理后台、HTML 标题、metadata 与品牌标识统一展示“陶泥儿”。
|
||||
2. 钱包、充值、邀请、兑换码、资产计费、拼图道具与作者激励统一展示“泥点”。
|
||||
3. 公开账号标识、搜索兜底、登录限制与错误信息统一展示“陶泥号”。
|
||||
4. 创作侧面向创作者的称谓统一展示“陶泥儿主”。
|
||||
5. 后端错误信息、默认商品文案、测试断言与文档说明同步更新。
|
||||
|
||||
## 3. 非目标
|
||||
|
||||
@@ -49,7 +49,7 @@ admin:{管理员用户名}:{邀请码}
|
||||
## 验收标准
|
||||
|
||||
1. 未登录用户访问 `/?inviteCode=ABC123` 自动打开注册弹窗并预填 `ABC123`。
|
||||
2. 有效邀请码注册成功后,被邀请人获得光点奖励,邀请关系落库。
|
||||
2. 有效邀请码注册成功后,被邀请人获得泥点奖励,邀请关系落库。
|
||||
3. 无效邀请码注册成功但不绑定,并返回短提示。
|
||||
4. 管理员可添加邀请码并写入 metadata,重复提交同管理员同码更新 metadata。
|
||||
5. 管理员邀请码被使用时不产生 `admin:*` 虚拟主体的钱包流水。
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 新用户注册默认光点落地说明
|
||||
# 新用户注册默认泥点落地说明
|
||||
|
||||
## 目标
|
||||
|
||||
每个新注册用户默认获得 `10` 个光点。赠送必须由后端统一落账,前端只展示余额和流水,不在本地补发或推算。
|
||||
每个新注册用户默认获得 `10` 个泥点。赠送必须由后端统一落账,前端只展示余额和流水,不在本地补发或推算。
|
||||
|
||||
## 落账规则
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
`runtime_snapshot.game_state.playerCurrency` 是运行态内的旧货币字段,不允许覆盖已经存在真实钱包业务流水的账户余额。只要用户已有非 `snapshot_sync` 的钱包流水,后续存档同步只能累计游玩时长和玩过世界,不再用 `playerCurrency` 回写 `wallet_balance`。
|
||||
|
||||
这样可以避免新用户注册赠送的 `10` 个光点,在首次保存 `playerCurrency = 0` 的运行态快照时被覆盖成 `0`。
|
||||
这样可以避免新用户注册赠送的 `10` 个泥点,在首次保存 `playerCurrency = 0` 的运行态快照时被覆盖成 `0`。
|
||||
|
||||
## 影响文件
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
## 1. 目标
|
||||
|
||||
本轮在现有“我的”资料与钱包 projection 上新增兑换码能力。用户兑换成功后直接增加光点余额,写入 `profile_wallet_ledger`,并同步刷新 `profile_dashboard_state.wallet_balance`。
|
||||
本轮在现有“我的”资料与钱包 projection 上新增兑换码能力。用户兑换成功后直接增加泥点余额,写入 `profile_wallet_ledger`,并同步刷新 `profile_dashboard_state.wallet_balance`。
|
||||
|
||||
管理侧本轮只提供后端 API,不新增管理后台页面。私有兑换码创建时支持内部 `userId` 与公开百梦号两类输入,后端创建阶段统一解析成内部 `userId` 存储。
|
||||
管理侧本轮只提供后端 API,不新增管理后台页面。私有兑换码创建时支持内部 `userId` 与公开陶泥号两类输入,后端创建阶段统一解析成内部 `userId` 存储。
|
||||
|
||||
## 2. 兑换码类型
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
| --- | --- | --- |
|
||||
| `code` | `String` | 主键,标准化后的兑换码。 |
|
||||
| `mode` | `RuntimeProfileRedeemCodeMode` | 兑换码模式。 |
|
||||
| `reward_points` | `u64` | 单次到账光点。 |
|
||||
| `reward_points` | `u64` | 单次到账泥点。 |
|
||||
| `max_uses` | `u32` | 公共码为单用户上限,唯一码/私有码为全局上限。 |
|
||||
| `global_used_count` | `u32` | 全局已使用次数。公共码也记录总使用次数,但不参与公共码上限判断。 |
|
||||
| `enabled` | `bool` | 是否启用。 |
|
||||
@@ -42,7 +42,7 @@
|
||||
| `usage_id` | `String` | 主键,格式 `redeem:{code}:{user_id}:{micros}:{sequence}`。 |
|
||||
| `code` | `String` | 兑换码。 |
|
||||
| `user_id` | `String` | 兑换用户。 |
|
||||
| `amount_granted` | `u64` | 到账光点。 |
|
||||
| `amount_granted` | `u64` | 到账泥点。 |
|
||||
| `created_at` | `Timestamp` | 兑换时间。 |
|
||||
|
||||
索引:`code`、`user_id`、`(code, user_id)`。
|
||||
@@ -121,7 +121,7 @@
|
||||
|
||||
“我的”页头像右侧入口由 `会员充值` 改为 `兑换码`。点击打开独立模态窗口,窗口内只保留输入框、兑换按钮和后端返回提示,不展示兑换规则说明。
|
||||
|
||||
成功后展示 `已到账 X 光点`,并刷新 profile dashboard。失败后直接展示后端 `message`。
|
||||
成功后展示 `已到账 X 泥点`,并刷新 profile dashboard。失败后直接展示后端 `message`。
|
||||
|
||||
## 8. 测试矩阵
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## 1. 目标
|
||||
|
||||
本轮新增一套可配置的个人任务系统,并补齐任务依赖的埋点统计能力。首个任务为“每日登录”,奖励 `10` 光点,入口放在“我的”页签;后台可修改任务配置。
|
||||
本轮新增一套可配置的个人任务系统,并补齐任务依赖的埋点统计能力。首个任务为“每日登录”,奖励 `10` 泥点,入口放在“我的”页签;后台可修改任务配置。
|
||||
|
||||
## 2. 核心边界
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
- 任务配置写入 `profile_task_config`,默认配置包含 `daily_login`,后台修改后不得被默认初始化覆盖。
|
||||
- 任务进度写入 `profile_task_progress`,用于任务中心快速读取状态。
|
||||
- 领奖记录写入 `profile_task_reward_claim`,与钱包流水 `profile_wallet_ledger` 同事务写入。
|
||||
- “星光”奖励复用现有“光点”钱包,不新增第二种货币。
|
||||
- “星光”奖励复用现有“泥点”钱包,不新增第二种货币。
|
||||
|
||||
## 3. 埋点分层
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
## 9. 验收
|
||||
|
||||
1. `profile_task_config` 默认存在 `daily_login`,后台可修改奖励、阈值、标题和启用状态。
|
||||
2. “我的”页可以打开每日任务面板,登录后任务可领取 `10` 光点。
|
||||
2. “我的”页可以打开每日任务面板,登录后任务可领取 `10` 泥点。
|
||||
3. 登录成功会幂等记录 `daily_login`;重复打开任务中心只记录 `task_center_view`,不会重复增加领取资格。
|
||||
4. 重复领奖不会重复发放。
|
||||
5. 表目录、迁移白名单、Rust/TypeScript 契约和前端入口同步更新。
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## 1. 背景
|
||||
|
||||
当前前端展示的“百梦号”由前端基于 `AuthUser.id` 临时拼装:
|
||||
当前前端展示的“陶泥号”由前端基于 `AuthUser.id` 临时拼装:
|
||||
|
||||
- 前缀固定为 `SY-`
|
||||
- 取 `user.id` 或 `username` 去除非字母数字字符后的末 8 位
|
||||
@@ -174,7 +174,7 @@
|
||||
1. `id` 返回内部 ID 仅供当前工程内部跳转与资源读取使用,不在 UI 上直接暴露为文案
|
||||
2. 不返回手机号、登录方式、绑定状态、tokenVersion 等敏感字段
|
||||
3. 未命中返回 `404`
|
||||
4. `by-id` 仅接受内部 `user_XXXXXXXX` 这类用户 ID,用于工程内跳转、运营排查或已有资源引用,不替代公开百梦号主搜索语义
|
||||
4. `by-id` 仅接受内部 `user_XXXXXXXX` 这类用户 ID,用于工程内跳转、运营排查或已有资源引用,不替代公开陶泥号主搜索语义
|
||||
|
||||
## 5.2 广场作品公开编号搜索
|
||||
|
||||
@@ -251,7 +251,7 @@
|
||||
|
||||
## 7.1 账号展示
|
||||
|
||||
当前首页资料卡和桌面顶部都展示前端拼装百梦号,改为:
|
||||
当前首页资料卡和桌面顶部都展示前端拼装陶泥号,改为:
|
||||
|
||||
1. 直接展示 `authUi.user.publicUserCode`
|
||||
2. 复制按钮复制后端返回值
|
||||
@@ -262,7 +262,7 @@
|
||||
广场作品卡和详情页增加:
|
||||
|
||||
1. 作品号 `CW-XXXXXXXX`
|
||||
2. 作者百梦号 `SY-XXXXXXXX`
|
||||
2. 作者陶泥号 `SY-XXXXXXXX`
|
||||
|
||||
展示要求:
|
||||
|
||||
@@ -284,7 +284,7 @@
|
||||
用户搜索命中后的最小行为:
|
||||
|
||||
1. 打开独立用户搜索结果面板或对话框
|
||||
2. 展示头像字母、显示名、百梦号
|
||||
2. 展示头像字母、显示名、陶泥号
|
||||
3. 提供“查看该作者作品”入口
|
||||
|
||||
作品搜索命中后的行为:
|
||||
@@ -325,7 +325,7 @@
|
||||
|
||||
## 11. 当前落地说明
|
||||
|
||||
1. 首页百梦号展示已优先读取后端 `publicUserCode`,原本基于 `AuthUser.id/username` 的前端拼装仅保留为兼容兜底,避免老会话未刷新时界面直接空白。
|
||||
1. 首页陶泥号展示已优先读取后端 `publicUserCode`,原本基于 `AuthUser.id/username` 的前端拼装仅保留为兼容兜底,避免老会话未刷新时界面直接空白。
|
||||
2. 用户公开搜索与广场作品公开搜索均已改为调用后端匿名接口,前端只负责输入、展示与跳转,不再自行决定最终编号格式。
|
||||
3. 自定义世界发布链路已改为从认证服务读取真实 `public_user_code` 写入作品真相与广场读模型,不再从内部 `user_id` 临时反推 `SY-XXXXXXXX`。
|
||||
4. 当前作品号 `public_work_code` 仍采用基于 `profile_id` 的稳定 fallback 方案生成 `CW-XXXXXXXX`;若后续补独立计数表,需要在不改变读写接口的前提下替换生成来源。
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
5. 参考图入口继续在画面描述输入框右下角,模型选择在左下角,两者不得遮挡文本。
|
||||
6. 表单创建 session、自动保存表单草稿、首图生成失败重试时都要保留当前模型选择。
|
||||
7. 结果页关卡重新生成时将当前模型随 `generate_puzzle_images` action 传给后端。
|
||||
8. “生成草稿”和关卡详情“生成画面 / 重新生成画面”按钮文本右侧展示 `消耗2光点`。
|
||||
9. 关卡详情点击“生成画面 / 重新生成画面”后先弹出确认消耗光点弹窗,确认后开始请求;按钮区域切换为 30 秒倒计时进度条,并展示预计剩余生成完成时间。
|
||||
8. “生成草稿”和关卡详情“生成画面 / 重新生成画面”按钮文本右侧展示 `消耗2泥点`。
|
||||
9. 关卡详情点击“生成画面 / 重新生成画面”后先弹出确认消耗泥点弹窗,确认后开始请求;按钮区域切换为 30 秒倒计时进度条,并展示预计剩余生成完成时间。
|
||||
|
||||
## 后端路由
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
7. `save_puzzle_generated_images` 写回草稿时若遇到 SpacetimeDB 连接级 `503` 或断线,API 层基于本次生成结果合成 session 快照返回给前端,避免 VectorEngine 已成功出图却被后置持久化误报成服务不可用。余额不足、参数错误、上游生图失败仍按原错误返回,不做伪成功。
|
||||
8. 结果页 `generate_puzzle_images` 会携带当前作品信息和 `levelsJson`。当 SpacetimeDB 在读取 session 阶段就返回连接级 `503` 或断线时,后端必须先用这份结果页快照构造最小内存 session,再继续调用 VectorEngine;外部图片已经生成后仍按第 6、7 条处理持久化降级。余额不足、参数错误、缺少草稿快照、关卡不存在等业务错误不走此降级。
|
||||
9. VectorEngine 错误统一映射为 `502 UPSTREAM_ERROR`,`details.provider = "vector-engine"`,保留上游状态码、业务 message 和截断后的 raw excerpt。
|
||||
10. 拼图首图生成 `compile_puzzle_draft` 与关卡图片生成 `generate_puzzle_images` 每次预扣 `2` 光点;余额不足仍返回 `409 CONFLICT`,SpacetimeDB 连接级 503 仍按既有降级策略处理。
|
||||
10. 拼图首图生成 `compile_puzzle_draft` 与关卡图片生成 `generate_puzzle_images` 每次预扣 `2` 泥点;余额不足仍返回 `409 CONFLICT`,SpacetimeDB 连接级 503 仍按既有降级策略处理。
|
||||
|
||||
## 关卡名多模态生成
|
||||
|
||||
@@ -79,6 +79,6 @@ VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS=180000
|
||||
4. 历史 `original` 或空模型值不会再触发 DashScope,统一按 `gpt-image-2` 请求 VectorEngine。
|
||||
5. 选择图片模型时,请求 `POST {VECTOR_ENGINE_BASE_URL}/v1/images/generations`,使用 `Authorization: Bearer {VECTOR_ENGINE_API_KEY}`,上游 `model = gpt-image-2-all`,不携带 `official_fallback`,`size = 1024x1024`。
|
||||
6. 首图和结果页关卡重新生图成功后,Network 中应先完成 VectorEngine 图片生成,再调用 APIMart `POST {APIMART_BASE_URL}/chat/completions`,请求模型为 `gpt-4o-mini`,消息同时包含画面描述文本和正式图 `image_url` Data URL。
|
||||
7. “生成草稿”和关卡详情生图按钮展示 `消耗2光点`;关卡详情确认后展示 30 秒预计剩余进度条。
|
||||
7. “生成草稿”和关卡详情生图按钮展示 `消耗2泥点`;关卡详情确认后展示 30 秒预计剩余进度条。
|
||||
8. 不改 SpacetimeDB 表结构,因此无需更新 `migration.rs` 或重新生成 bindings。
|
||||
9. 后端改动后运行对应 Rust 测试,并按项目约束用 `npm run api-server` 重启验证。
|
||||
|
||||
@@ -201,7 +201,7 @@ Rust DTO 只承载对前端公开的 HTTP contract,不直接泄露 `module-puz
|
||||
1. 每次生成 2 张候选图。
|
||||
2. 候选图通过 `api-server` 写入 OSS,兼容展示路径统一为 `/generated-puzzle-assets/...`,禁止再落到仓库 `public/` 目录。
|
||||
3. Axum 把候选图 URL、assetId、prompt snapshot 回写到 Spacetime session draft。
|
||||
4. 百梦主在结果页选择其中 1 张作为正式图。
|
||||
4. 陶泥儿主在结果页选择其中 1 张作为正式图。
|
||||
|
||||
这样可以保证:
|
||||
|
||||
@@ -211,7 +211,7 @@ Rust DTO 只承载对前端公开的 HTTP contract,不直接泄露 `module-puz
|
||||
|
||||
### 6.1 发布前编辑真相补充
|
||||
|
||||
结果页允许百梦主在发布前直接编辑:
|
||||
结果页允许陶泥儿主在发布前直接编辑:
|
||||
|
||||
1. `关卡名`
|
||||
2. `摘要`
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
1. 限定时间内未完成时弹出失败面板。
|
||||
2. 失败面板提供两个选择:
|
||||
- `重新开始`:重新开启当前拼图关卡,不扣光点。
|
||||
- `继续1分钟`:先弹出确认窗口,确认后消耗 `1` 光点,并把当前失败关卡恢复为 `playing`,剩余时间固定为 `60000ms`。
|
||||
- `重新开始`:重新开启当前拼图关卡,不扣泥点。
|
||||
- `继续1分钟`:先弹出确认窗口,确认后消耗 `1` 泥点,并把当前失败关卡恢复为 `playing`,剩余时间固定为 `60000ms`。
|
||||
3. 进入拼图作品后立即写入 `profile_save_archive`,存档页显示拼图存档。
|
||||
4. 每次进入下一关后更新同一条拼图存档,使存档恢复时指向最新可继续的关卡。
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
`PuzzleRuntimePropKind` 增加 `extendTime`,沿用现有道具确认与扣费接口:
|
||||
|
||||
1. 前端只在 `runtimeStatus = failed` 时开放 `继续1分钟`。
|
||||
2. 点击后打开独立确认弹窗,文案只显示短标题和 `消耗 1 光点`。
|
||||
2. 点击后打开独立确认弹窗,文案只显示短标题和 `消耗 1 泥点`。
|
||||
3. 正式 run 继续走 `POST /api/runtime/puzzle/runs/:runId/props`。
|
||||
4. `api-server` 将 `extendTime` 映射为账单 `asset_kind = puzzle_prop_extend_time`。
|
||||
5. SpacetimeDB 侧只允许失败关卡续时;续时成功后:
|
||||
@@ -37,7 +37,7 @@
|
||||
- 清空暂停与冻结生效点
|
||||
- 调整 `paused_accumulated_ms`,保证从确认成功那一刻开始完整倒计时 `60` 秒
|
||||
|
||||
本地调试 run 没有真实钱包,沿用本地道具兜底:仍弹确认窗,但不扣真实光点。
|
||||
本地调试 run 没有真实钱包,沿用本地道具兜底:仍弹确认窗,但不扣真实泥点。
|
||||
|
||||
### 重新开始
|
||||
|
||||
@@ -91,7 +91,7 @@ SpacetimeDB 拼图运行态每次持久化 run 时同步刷新存档:
|
||||
|
||||
1. 倒计时归零后失败弹窗有 `重新开始` 和 `继续1分钟`。
|
||||
2. 点击 `继续1分钟` 后先出现扣费确认,确认成功后失败弹窗关闭并恢复 `60` 秒倒计时。
|
||||
3. 光点余额不足时确认弹窗保留,并展示错误。
|
||||
3. 泥点余额不足时确认弹窗保留,并展示错误。
|
||||
4. 点击 `重新开始` 后当前关卡重新打乱并重置倒计时。
|
||||
5. 进入拼图作品后,存档页出现 `worldType = PUZZLE` 的拼图存档。
|
||||
6. 通过一关后,只要后端确认同作品下一关存在,同一条存档立即更新到新关卡;没有同作品下一关时保留已完成关卡,等待玩家选择相似作品。
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
2. 新 session 的 `seedText` 允许为空;SpacetimeDB 侧用空锚点和空表单草稿初始化,不得把默认题材文案写入玩家草稿字段。
|
||||
3. 初始表单输入自动保存到 session 的 `draft_json` 与 `puzzle_work_profile` 投影。保存字段只包含 `workTitle`、`workDescription`、`pictureDescription`、可推断标签和一个 `generationStatus = idle` 的默认关卡;草稿设置阶段默认关卡名称必须为空,不得写入“第一关”“第1关”或作品名称作为默认值。生成前的参考图只保存在当前前端会话内;一旦用于首图生成并成功返回,后端必须把该参考图写入首关 `pictureReference`,供结果页后续重新生成继续复用。
|
||||
4. 玩家在生成草稿前退出,再次从创作中心点击这条拼图草稿时,必须恢复到填表页,并回填之前自动保存的作品名称、作品描述和画面描述;只有执行 `compile_puzzle_draft` 且生成结果页草稿后,草稿入口才进入结果页。
|
||||
5. 表单自动保存走 `save_puzzle_form_draft` action,不消耗光点,不生成图片,不改变 `stage = collecting_anchors`;生成草稿按钮仍单独触发 `compile_puzzle_draft` 并进入进度页。
|
||||
5. 表单自动保存走 `save_puzzle_form_draft` action,不消耗泥点,不生成图片,不改变 `stage = collecting_anchors`;生成草稿按钮仍单独触发 `compile_puzzle_draft` 并进入进度页。
|
||||
6. 点击拼图入口始终创建新草稿,不复用上一次未完成 session;恢复旧草稿只通过“我的创作”中的草稿卡进入。
|
||||
7. 若运行中的旧 wasm 缺少 `save_puzzle_form_draft` procedure,前端提交生成或生成失败页重试时不得继续复用空 `seedText` 的表单 session,必须用当前表单 payload 新建带真实 seed 的 session 再执行 `compile_puzzle_draft`。
|
||||
8. api-server 也要兼容旧 wasm:`save_puzzle_form_draft` 缺失时,自动保存 action 降级返回当前 session;`compile_puzzle_draft` 前置保存缺失且当前 session 为空 seed 时,创建一条带表单 seed 的替代 session 后继续编译,避免再次暴露 `No such procedure`。
|
||||
@@ -88,10 +88,10 @@
|
||||
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` 中保留真实钱包错误。
|
||||
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 背景图通过 `tokio::join!` 并行生成,任一失败只记录 warning 并保留草稿。
|
||||
16. `compile_puzzle_draft_with_uploaded_cover` 中,上传图解析后,文本名称生成、图片语义名称生成和上传图转存 OSS 可并行;上传图转存失败必须立即返回,不得继续触发背景音乐或 UI 背景生成。上传图转存成功且最终关卡名确定后,背景音乐与首关 UI 背景图同样并行生成。
|
||||
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 失败后留下未写入草稿的已扣费音频。
|
||||
|
||||
## 结果页
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
1. UI 背景图只生成拼图运行态的题材氛围纯背景,不得把拼图槽、棋盘外框、按钮、HUD 或其它 UI 元素烘进图片。拼图槽位、棋盘边框和空格继续使用运行态默认样式绘制。
|
||||
2. UI 背景图不得生成文字、水印、按钮文字、数字、拼图碎片、完整拼图图像、教程浮层、拼图槽或物品槽,避免与真实拼图图块和运行态 HUD 混淆。
|
||||
3. 结果页 UI Tab 支持直接修改提示词并重新生成;点击生成前会把本地首关 `uiBackgroundPrompt` 同步进 `levelsJson`,使自动保存尚未完成时后端仍能拿到最新提示词。
|
||||
4. 草稿编译阶段自动生成 UI 背景失败时只记录 warning,并保留草稿进入结果页;用户可在 UI Tab 重新生成,不因背景图上游波动阻断首图草稿主流程。
|
||||
4. 草稿编译阶段自动生成 UI 背景失败时必须让 `compile_puzzle_draft` 失败并停留在生成页;不能保留一个成功状态但缺少 UI 背景的草稿。只有结果页内用户主动点击 `生成UI背景` 或 `重新生成` 时,失败才作为当前面板错误展示,由用户手动重试。
|
||||
5. `api-server` 负责拼接生成 prompt、调用 VectorEngine、下载并转存 OSS;SpacetimeDB 只通过 `save_puzzle_ui_background` procedure 保存结果,不做外部 I/O。
|
||||
6. 拼图运行态读取 `currentLevel.uiBackgroundImageSrc` 渲染为全屏背景;无 UI 背景图时继续使用原封面模糊背景兜底。棋盘本身仍由正式拼图图生成,不能把 UI 背景当作拼图切块来源。
|
||||
7. 生成完成后的自动试玩和结果页“试玩”走前端本地运行态兜底时,`startLocalPuzzleRun` 也必须从 `PuzzleWorkSummary.levels[]` 复制 `uiBackgroundImageSrc` 与 `backgroundMusic` 到 `currentLevel`;不得只带 `coverImageSrc`,否则草稿结果页有背景但试玩局内空白。
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
5. 文生图正向 prompt 必须由后端压缩到 `500` 字符以内,优先保留玩家画面描述开头与固定拼图约束,避免上游把超长 prompt 判为“请求参数不合法”。
|
||||
6. VectorEngine 上游失败时,api-server 必须在错误 details 中保留业务 message、`upstreamStatus` 和截断后的 `rawExcerpt`,日志也要记录同样的摘要,避免生成进度页只能看到通用 HTTP 文案。
|
||||
7. 图片生成仍由 `api-server` 执行。SpacetimeDB reducer 不做网络 I/O。
|
||||
8. 光点预扣失败属于钱包或 SpacetimeDB 服务链路错误,不得映射成 `400 BAD_REQUEST`。除余额不足返回 `409 CONFLICT` 外,其余预扣异常统一按上游/服务错误暴露,避免生成页误提示“请求参数不合法”。
|
||||
8. 泥点预扣失败属于钱包或 SpacetimeDB 服务链路错误,不得映射成 `400 BAD_REQUEST`。除余额不足返回 `409 CONFLICT` 外,其余预扣异常统一按上游/服务错误暴露,避免生成页误提示“请求参数不合法”。
|
||||
|
||||
### 2. 前端规则裁决
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
3. 下载音频字节。
|
||||
4. 写入 OSS 私有对象。
|
||||
5. 确认 `asset_object` 并绑定 `asset_entity_binding`。
|
||||
6. 音频真正可下载并准备转存时,按 `taskId + assetKind + entityId + slot` 幂等扣费;背景音乐固定扣除 `5` 光点,物品点击音效固定扣除 `10` 光点。任务仍在处理中不扣费,转存或资产绑定失败自动退款。
|
||||
6. 音频真正可下载并准备转存时,按 `taskId + assetKind + entityId + slot` 幂等扣费;背景音乐固定扣除 `5` 泥点,物品点击音效固定扣除 `10` 泥点。任务仍在处理中不扣费,转存或资产绑定失败自动退款。
|
||||
|
||||
通用背景音乐提交允许 `prompt = ""`。拼图和抓大鹅草稿生成都按纯音乐处理:后端提交 Suno 时固定带 `make_instrumental = true`,只用 `title` 和 `tags` 约束作品气质,不把歌词或规则描述写入 prompt。视觉小说原路由保持兼容,内部继续复用同一套提交、轮询、转存逻辑。
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
}
|
||||
```
|
||||
|
||||
草稿生成阶段在生成首关作品题目后,使用作品题目作为 Suno `title`,`prompt` 为空,`tags` 使用轻快、拼图、循环、instrumental。生成失败只记录 warning,不阻断草稿进入结果页。运行态从 `PuzzleRuntimeLevelSnapshot.backgroundMusic.audioSrc` 读取该字段作为背景音乐源,游戏开始后自动循环播放;若字段为空,保持静默背景音乐兜底。
|
||||
草稿生成阶段在生成首关作品题目后,使用作品题目作为 Suno `title`,`prompt` 为空,`tags` 使用轻快、拼图、循环、instrumental。自动草稿编译必须拿到可播放的 `backgroundMusic.audioSrc` 后才返回成功;生成失败应返回上游错误并停留在生成页,不能进入结果页后显示“暂无音乐”。运行态从 `PuzzleRuntimeLevelSnapshot.backgroundMusic.audioSrc` 读取该字段作为背景音乐源,游戏开始后自动循环播放;历史草稿或手动删除音乐时字段为空,则保持静默背景音乐兜底。
|
||||
|
||||
### 3.2 抓大鹅
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
1. 作品背景音乐暂存到第一个 `Match3DGeneratedItemAsset.backgroundMusic`,表示当前 work profile 的作品级背景音乐。
|
||||
2. 单个物体点击音效保存到对应 `Match3DGeneratedItemAsset.clickSound`。
|
||||
|
||||
这是一个兼容性折中:当前 Match3D work profile 没有 work-level metadata 字段,而 `generated_item_assets_json` 已经随作品详情、草稿架、运行态入口稳定传递。草稿生成阶段的文本计划在生成物品名称时同步生成 `backgroundMusic.title` 作为背景音乐名称,`backgroundMusic.prompt` 固定为空字符串,后端用该名称作为 Suno `title` 并生成纯音乐。后续若新增正式作品 metadata 表达,应迁移 `backgroundMusic` 到作品级字段。
|
||||
这是一个兼容性折中:当前 Match3D work profile 没有 work-level metadata 字段,而 `generated_item_assets_json` 已经随作品详情、草稿架、运行态入口稳定传递。草稿生成阶段的文本计划在生成物品名称时同步生成 `backgroundMusic.title` 作为背景音乐名称,`backgroundMusic.prompt` 固定为空字符串,后端用该名称作为 Suno `title` 并生成纯音乐。自动草稿编译必须把生成后的 `backgroundMusic.audioSrc` 写回首个素材后才返回成功;若 Suno 提交、轮询、下载、OSS 转存或资产绑定失败,本次草稿生成返回失败并允许用户重试同一 session/profile。后续若新增正式作品 metadata 表达,应迁移 `backgroundMusic` 到作品级字段。
|
||||
|
||||
## 4. 前端交互
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
3. 抓大鹅每个物体音效生成入口放在对应素材详情面板内,不在列表下方展开大段配置。
|
||||
4. 抓大鹅物体音效提示词允许在素材详情面板内编辑;背景音乐只允许在 `素材配置 > 背景音乐` 编辑曲名和风格,生成请求固定使用空 `prompt`。
|
||||
5. 背景音乐和物体音效生成期间都显示进度条,生成完成后展示 audio 控件试听。
|
||||
6. 背景音乐重新生成只要求曲名非空;重新生成继续按纯音乐提交,`prompt = ""`,按钮展示 `5` 光点成本。
|
||||
6. 背景音乐重新生成只要求曲名非空;重新生成继续按纯音乐提交,`prompt = ""`,按钮展示 `5` 泥点成本。
|
||||
|
||||
### 4.1 运行态默认点击音效
|
||||
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
## 背景
|
||||
|
||||
拼图创作入口继续保留填表式体验,但入口表单不再要求百梦主提前填写作品名称和作品描述。入口只收集“拼图画面描述”,后端用该描述完成首图生成和第一关关卡名生成;进入结果页后再补作品信息。
|
||||
拼图创作入口继续保留填表式体验,但入口表单不再要求陶泥儿主提前填写作品名称和作品描述。入口只收集“拼图画面描述”,后端用该描述完成首图生成和第一关关卡名生成;进入结果页后再补作品信息。
|
||||
|
||||
## 入口表单
|
||||
|
||||
1. 点击“开始创作”后的拼图表单只展示 `画面描述`、参考图和图片模型选择。
|
||||
2. `画面描述` 是唯一必填字段,提交时写入 `pictureDescription`,并作为 `promptText` 传给 `compile_puzzle_draft`。
|
||||
3. `workTitle`、`workDescription` 不再从入口表单传入;`seedText` 只由画面描述组成,格式为 `画面描述:...`。
|
||||
4. 表单自动保存只保存画面描述,不生成图片,不消耗光点。
|
||||
4. 表单自动保存只保存画面描述,不生成图片,不消耗泥点。
|
||||
5. 生成进度页“当前拼图信息”只展示画面描述,不再展示空作品名称或空作品描述。
|
||||
|
||||
## 生成进度步骤
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
拼图结果页此前存在两个串联问题:
|
||||
|
||||
1. 百梦主在结果页修改 `关卡名`、新增标签、删除标签,只会改前端本地 `editState`,不会立即写回拼图作品 profile。
|
||||
1. 陶泥儿主在结果页修改 `关卡名`、新增标签、删除标签,只会改前端本地 `editState`,不会立即写回拼图作品 profile。
|
||||
2. 发布弹窗同时混用了旧 session 内的 `publishReady` 与前端本地编辑态,导致标签已经在界面里补够,但发布校验仍然盯着旧草稿里的标签数量,用户无法通过发布检验。
|
||||
|
||||
这会直接破坏拼图创作主链的可用性:用户明明已经在结果页补齐正式标签,却因为没有自动保存、也没有按当前编辑态重算门槛而卡在发布前。
|
||||
@@ -59,6 +59,6 @@
|
||||
|
||||
## 2026-05-09 发布失败提示补充
|
||||
|
||||
`publish_puzzle_work` 属于资产操作发布入口,按 `ASSET_GENERATION_POINTS_CONSUMPTION_2026-04-27.md` 会在发布 mutation 前预扣 `1` 枚光点。余额不足时后端返回 `409 CONFLICT`,响应 `details.message` 为 `光点余额不足`,这属于业务拒绝,不是拼图发布接口不可用。
|
||||
`publish_puzzle_work` 属于资产操作发布入口,按 `ASSET_GENERATION_POINTS_CONSUMPTION_2026-04-27.md` 会在发布 mutation 前预扣 `1` 枚泥点。余额不足时后端返回 `409 CONFLICT`,响应 `details.message` 为 `泥点余额不足`,这属于业务拒绝,不是拼图发布接口不可用。
|
||||
|
||||
结果页发布弹窗必须在用户点击发布后继续展示后端错误原因,不能只把错误写到弹窗背后的页面 banner。这样余额不足、SpacetimeDB 发布门禁或其他后端业务错误都会在当前独立发布面板中直接可见。
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
1. 不同难度有明确倒计时,超时即失败。
|
||||
2. 底部固定 3 个轻量道具:提示、查看原图、冻结时间。
|
||||
3. 道具使用必须经过确认弹窗并消耗 `1` 光点,确认弹窗期间暂停关卡计时。
|
||||
3. 道具使用必须经过确认弹窗并消耗 `1` 泥点,确认弹窗期间暂停关卡计时。
|
||||
|
||||
本设计只处理拼图运行时,不改拼图创作链、发布链和广场推荐链。
|
||||
|
||||
@@ -95,7 +95,7 @@ remainingMs = max(0, timeLimitMs - effectiveElapsedMs)
|
||||
|
||||
## 计费规则
|
||||
|
||||
每次确认使用道具消耗 `1` 光点。
|
||||
每次确认使用道具消耗 `1` 泥点。
|
||||
|
||||
正式后端运行态复用现有资产操作钱包预扣链路,新增道具 `asset_kind`:
|
||||
|
||||
|
||||
@@ -98,11 +98,11 @@ size = 1024x1024
|
||||
- 已上传图片时,输入框标题为 `画面AI重绘要求(提示词)`。
|
||||
- 展示图片模型切换。
|
||||
- `compile_puzzle_draft` 携带 `aiRedraw: true`,继续走 VectorEngine 生图与 `PUZZLE_IMAGE_GENERATION_POINTS_COST = 2` 扣费链路。
|
||||
- 生成按钮展示 `消耗2光点`。
|
||||
- 生成按钮展示 `消耗2泥点`。
|
||||
2. `AI重绘=false`
|
||||
- 隐藏画面描述输入框和模型切换。
|
||||
- 必须上传拼图图片,按钮不展示 `消耗2光点`。
|
||||
- `compile_puzzle_draft` 携带 `aiRedraw: false`,后端只编译草稿和生成首关名,不调用 VectorEngine,不进入光点扣费 wrapper。
|
||||
- 必须上传拼图图片,按钮不展示 `消耗2泥点`。
|
||||
- `compile_puzzle_draft` 携带 `aiRedraw: false`,后端只编译草稿和生成首关名,不调用 VectorEngine,不进入泥点扣费 wrapper。
|
||||
- 后端把上传图片 Data URL 按拼图资产路径持久化,构造 `sourceType=uploaded` 的候选图并直接选为第一关正式图。
|
||||
3. 上传裁剪
|
||||
- 前端读取上传图原始宽高。
|
||||
@@ -126,8 +126,8 @@ Rust 共享契约使用 `ai_redraw: Option<bool>` 并按 camelCase 序列化为
|
||||
3. 图片模型切换仍可打开并选择 `gpt-image-2` / `nanobanana2`。
|
||||
4. 历史模板样例图文件可保留,但不出现在拼图入口表单。
|
||||
5. 当前创作 Tab 顶部的拼图、方洞挑战、视觉小说和 AIRP 卡片能看到对应 `creation-type-references` 图片。
|
||||
6. 默认 `AI重绘` 打开时,无图状态展示 `画面描述` 与 `消耗2光点`;上传图片后输入框标题改为 `画面AI重绘要求(提示词)`。
|
||||
7. 关闭 `AI重绘` 后隐藏画面描述输入框,生成按钮不展示 `消耗2光点`,后端直接应用上传图片为第一关图片。
|
||||
6. 默认 `AI重绘` 打开时,无图状态展示 `画面描述` 与 `消耗2泥点`;上传图片后输入框标题改为 `画面AI重绘要求(提示词)`。
|
||||
7. 关闭 `AI重绘` 后隐藏画面描述输入框,生成按钮不展示 `消耗2泥点`,后端直接应用上传图片为第一关图片。
|
||||
8. 上传非 1:1 图片时必须先通过拖拽裁剪框完成正方形裁剪。
|
||||
9. gpt-image-2 Skill 校验通过,且脚本 dry-run 能输出计划请求而不泄露密钥。
|
||||
10. `npm run check:encoding` 通过。
|
||||
|
||||
@@ -6,18 +6,18 @@
|
||||
|
||||
1. 拼图草稿页“新增关卡”按钮下方显示一行小字:“获得更多积分激励”。
|
||||
2. 创作页的已发布拼图作品卡展示当前作品的积分激励总数、待领取积分数和领取按钮。
|
||||
3. 用户在他人已发布拼图作品中消耗光点时,作品作者获得消耗光点数量的一半作为积分激励。
|
||||
4. 作者领取时只能领取整数个光点,待领取值向下取整;未满 1 个光点的半数余额继续保留。
|
||||
3. 用户在他人已发布拼图作品中消耗泥点时,作品作者获得消耗泥点数量的一半作为积分激励。
|
||||
4. 作者领取时只能领取整数个泥点,待领取值向下取整;未满 1 个泥点的半数余额继续保留。
|
||||
|
||||
## 2. 数据模型
|
||||
|
||||
拼图作品激励归属到 `puzzle_work_profile`。
|
||||
|
||||
1. `point_incentive_total_half_points: u64`
|
||||
- 记录该作品累计获得的激励,单位为“半个光点”。
|
||||
- 每消耗 `N` 个光点,增加 `N` 个 half points;当前拼图道具每次消耗 1 个光点,因此每次为作者增加 0.5。
|
||||
- 记录该作品累计获得的激励,单位为“半个泥点”。
|
||||
- 每消耗 `N` 个泥点,增加 `N` 个 half points;当前拼图道具每次消耗 1 个泥点,因此每次为作者增加 0.5。
|
||||
2. `point_incentive_claimed_points: u64`
|
||||
- 记录作者已领取的整数光点数量。
|
||||
- 记录作者已领取的整数泥点数量。
|
||||
3. 前端展示:
|
||||
- 激励总数 = `pointIncentiveTotalHalfPoints / 2`,允许展示一位小数。
|
||||
- 待领取积分 = `floor(pointIncentiveTotalHalfPoints / 2) - pointIncentiveClaimedPoints`。
|
||||
@@ -33,7 +33,7 @@
|
||||
- 只允许作品作者领取。
|
||||
- 计算可领取整数 `claimable = total_half_points / 2 - claimed_points`。
|
||||
- `claimable <= 0` 时拒绝领取。
|
||||
- 同一事务内更新作品 `claimed_points += claimable`,并向作者钱包增加 `claimable` 光点,钱包流水来源使用 `puzzle_author_incentive_claim`。
|
||||
- 同一事务内更新作品 `claimed_points += claimable`,并向作者钱包增加 `claimable` 泥点,钱包流水来源使用 `puzzle_author_incentive_claim`。
|
||||
|
||||
## 4. API 与前端
|
||||
|
||||
@@ -55,6 +55,6 @@
|
||||
2. 已发布拼图作品卡展示“积分激励总数”和“待领取”两个数值。
|
||||
3. 待领取积分为 0 时领取按钮禁用。
|
||||
4. 非作者游玩他人拼图并使用付费道具后,该作品累计 half points 增加。
|
||||
5. 作者领取后钱包增加向下取整后的整数光点,作品待领取数归零或保留不足 1 的小数余额。
|
||||
5. 作者领取后钱包增加向下取整后的整数泥点,作品待领取数归零或保留不足 1 的小数余额。
|
||||
6. 领取成功后顶部/我的页钱包余额随个人看板刷新。
|
||||
7. 修改后运行编码检查、SpacetimeDB 绑定生成、Rust 检查和必要前端测试。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# 技术方案
|
||||
# 技术方案
|
||||
|
||||
这一组文档偏技术选型、实现路线和外部产品形态拆解。
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
- [CREATIVE_INTERACTIVE_CONTENT_AGENT_TECHNICAL_SOLUTION_2026-05-05.md](./CREATIVE_INTERACTIVE_CONTENT_AGENT_TECHNICAL_SOLUTION_2026-05-05.md):冻结基于 LangChain-Rust 的创意互动内容生成 Agent 技术方案,明确首版只支持拼图模板、必须显式展示模板选择和积分范围,通过拼图模块 Tool/模板协议填充同一份草稿字段,支持单关卡与多关卡图片生成、立即试玩、表单化编辑和 Agent 自然语言修订草稿字段。
|
||||
- [VISUAL_NOVEL_PROMPT_AND_LLM_TOOLS_VN03_2026-05-05.md](./VISUAL_NOVEL_PROMPT_AND_LLM_TOOLS_VN03_2026-05-05.md):记录视觉小说模板 `VN-03` Prompt / LLM 工具落地,包含创作底稿 Prompt、运行时 GM Prompt、repair Prompt、工具参数 schema、Responses 请求口径和定向验证结果。
|
||||
- [VISUAL_NOVEL_IMPLEMENTATION_HANDOFF_2026-05-07.md](./VISUAL_NOVEL_IMPLEMENTATION_HANDOFF_2026-05-07.md):记录视觉小说模板 `VN-13` 实现收口、当前正式入口、表目录、路由、作品 / 运行 / 资产和负向扫描口径。
|
||||
- [PROFILE_TASK_AND_TRACKING_SYSTEM_2026-05-03.md](./PROFILE_TASK_AND_TRACKING_SYSTEM_2026-05-03.md):冻结个人任务与埋点系统首版方案,明确 `tracking_event`、`tracking_daily_stat`、`profile_task_config`、任务进度、领奖记录和光点钱包流水的边界。
|
||||
- [PROFILE_TASK_AND_TRACKING_SYSTEM_2026-05-03.md](./PROFILE_TASK_AND_TRACKING_SYSTEM_2026-05-03.md):冻结个人任务与埋点系统首版方案,明确 `tracking_event`、`tracking_daily_stat`、`profile_task_config`、任务进度、领奖记录和泥点钱包流水的边界。
|
||||
- [SQUARE_HOLE_IMAGE_SLOT_AND_RUNTIME_INTERACTION_FIX_2026-05-06.md](./SQUARE_HOLE_IMAGE_SLOT_AND_RUNTIME_INTERACTION_FIX_2026-05-06.md):记录方洞挑战结果页图片槽位局部生成、洞口图历史素材、运行态拖拽与点击投放交互的修正口径。
|
||||
- [MAINCLOUD_REFERENCE_REMOVAL_POLICY_2026-05-06.md](./MAINCLOUD_REFERENCE_REMOVAL_POLICY_2026-05-06.md):冻结 Maincloud 历史残留引用禁用策略,明确后续不得新增、运行或引用 `api-server:maincloud`、`GENARRATIVE_SPACETIME_MAINCLOUD_*` 和相关测试/文档口径。
|
||||
- [PRODUCTION_DEPLOYMENT_PLAN_2026-05-02.md](./PRODUCTION_DEPLOYMENT_PLAN_2026-05-02.md):冻结单机生产部署目标,从旧一体化启动脚本切到 Nginx、systemd 托管 SpacetimeDB 与 Rust `api-server`,并记录生产 Jenkins 流水线拆分计划和首批部署骨架。
|
||||
@@ -83,7 +83,7 @@
|
||||
- [SERVER_RS_DDD_PARALLEL_TASKLIST_2026-04-29.md](./SERVER_RS_DDD_PARALLEL_TASKLIST_2026-04-29.md):把 `server-rs` DDD 一次性重构拆成全局可并行工作包,覆盖 `module-*`、`spacetime-module`、`spacetime-client`、`api-server`、`platform-*`、共享契约和前端接入的依赖、边界与验收命令。
|
||||
- [SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md](./SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md):冻结 `server-rs` 一次性 DDD 重构总纲,明确 crate 依赖方向、模块目录、上下文聚合/命令/事件/读模型、SpacetimeDB adapter 映射和表结构变更约束。
|
||||
- [SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md](./SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md):冻结 SpacetimeDB 表结构变更约束、自动迁移可接受范围、冲突后的系统行为,以及保留旧数据的增量迁移流程;凡涉及 `spacetime publish`、表字段调整或 `migration.rs` 对齐时优先参考。
|
||||
- [PRODUCT_NAMING_BAIMENG_RENAME_2026-05-01.md](./PRODUCT_NAMING_BAIMENG_RENAME_2026-05-01.md):冻结当前对外中文命名,产品展示名统一为“百梦”,消费单位为“光点”,公开账号标识为“百梦号”,创作侧称谓为“百梦主”。
|
||||
- [PRODUCT_NAMING_BAIMENG_RENAME_2026-05-01.md](./PRODUCT_NAMING_BAIMENG_RENAME_2026-05-01.md):冻结当前对外中文命名,产品展示名统一为“陶泥儿”,消费单位为“泥点”,公开账号标识为“陶泥号”,创作侧称谓为“陶泥儿主”。
|
||||
- [SPACETIMEDB_CLOUD_CONFIG_REMOVAL_2026-05-02.md](./SPACETIMEDB_CLOUD_CONFIG_REMOVAL_2026-05-02.md):记录旧云端 SpacetimeDB 配置、发布脚本和默认文档口径的移除结果,冻结后续仅使用本地或显式 `SERVER_URL` 的运维规则。
|
||||
- [SPACETIMEDB_LOCAL_REPLICA_IDENTITY_MISMATCH_FIX_2026-04-30.md](./SPACETIMEDB_LOCAL_REPLICA_IDENTITY_MISMATCH_FIX_2026-04-30.md):记录本地 standalone 启动时报 `mismatched database identity` 的数据目录/replica 数据残留根因、备份重建步骤和脚本诊断口径。
|
||||
- [AUTH_SNAPSHOT_AND_MATCH3D_LOCAL_DEV_FIX_2026-05-01.md](./AUTH_SNAPSHOT_AND_MATCH3D_LOCAL_DEV_FIX_2026-05-01.md):记录远端库挂起导致认证快照同步和抓大鹅创作失败的根因、认证同步非阻断修复、`/api/creation` Vite 代理补齐和本地 SpacetimeDB 可跑链路。
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## 背景
|
||||
|
||||
世界创作结果页已经提供“作品测试”入口,但测试运行时此前缺少与“幕预览”一致的显式退出按钮。百梦主进入测试后只能依赖浏览器返回、刷新或其他间接链路离开,不符合独立运行时面板的交互语义。
|
||||
世界创作结果页已经提供“作品测试”入口,但测试运行时此前缺少与“幕预览”一致的显式退出按钮。陶泥儿主进入测试后只能依赖浏览器返回、刷新或其他间接链路离开,不符合独立运行时面板的交互语义。
|
||||
|
||||
## 本次约束
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## 背景
|
||||
|
||||
幕预览和测试作品用于百梦主检查玩法表现,不能被当作玩家正式游玩记录。若这类运行时复用正式 RPG 壳、story action 或 snapshot 接口,必须在进入个人存档页、游玩统计、作品游玩历史前被过滤。
|
||||
幕预览和测试作品用于陶泥儿主检查玩法表现,不能被当作玩家正式游玩记录。若这类运行时复用正式 RPG 壳、story action 或 snapshot 接口,必须在进入个人存档页、游玩统计、作品游玩历史前被过滤。
|
||||
|
||||
## 落地约束
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
1. 草稿层可以承载 `scene chapter / scene act`
|
||||
2. 后端可以把 `scene_chapter` 编译成正式蓝图
|
||||
3. 百梦主可以在现有场景编辑弹层里看到并编辑多幕配置
|
||||
3. 陶泥儿主可以在现有场景编辑弹层里看到并编辑多幕配置
|
||||
4. 编辑后的幕信息可以正确写回 `sceneChapterBlueprints`
|
||||
5. 运行时共享层先具备读取幕背景、主角色、相遇 NPC 池的基础能力
|
||||
6. 当前幕主角色的负好感 `5` 轮聊天限制先形成首个可运行闭环
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
前端已完成第一批接入:
|
||||
|
||||
1. `scene_chapter` 不再作为独立 Tab / 独立卡片暴露给百梦主
|
||||
1. `scene_chapter` 不再作为独立 Tab / 独立卡片暴露给陶泥儿主
|
||||
2. 多幕配置已内嵌到 `CustomWorldEntityEditorModal.tsx` 的 `LandmarkEditor`
|
||||
3. 单幕编辑已从文本表单切成“背景大图预览 + 3 个角色槽位”的轻量交互
|
||||
4. “幕标题 / 幕摘要 / 幕目标 / 过渡钩子”已从场景手工编辑区移除,继续留在草稿生成与编译层
|
||||
@@ -88,7 +88,7 @@
|
||||
7. 幕预览运行时已补 custom world NPC 的视觉兜底链路,优先使用 `visual / imageSrc` 渲染,避免角色形象或动画空白
|
||||
8. 当前幕小预览已调整为左侧玩家、右侧敌对/相遇角色的构图,NPC 站位采用一前两后
|
||||
前排主角色与玩家角色保持同一 y 轴;后排两个角色改为同一列、x 轴对齐并上下分布,且后排整体 y 轴中点与前排主角色一致
|
||||
9. 新增幕默认只带 1 个主角色,后续槽位由百梦主按需补充
|
||||
9. 新增幕默认只带 1 个主角色,后续槽位由陶泥儿主按需补充
|
||||
10. 小预览里的名字已移动到角色头顶,角色渲染不再带方形底板,避免遮挡场景背景
|
||||
11. 幕预览复用真实游戏壳时隐藏左上角角色等级徽标,退出入口固定在上方画面区域底部居中,并使用“结束预览”作为操作文案
|
||||
12. 创作侧场景列表封面、多幕配置卡片、配置背景弹层统一读取同一张场景显示图;在任一幕保存背景时同步回全部幕背景字段和场景兼容图,避免同一场景在不同层级出现不同预览图
|
||||
|
||||
@@ -411,7 +411,7 @@ Access-Control-Allow-Credentials: true
|
||||
|
||||
职责:
|
||||
|
||||
- 面向百梦主、运营、内部编辑器
|
||||
- 面向陶泥儿主、运营、内部编辑器
|
||||
- 必须鉴权
|
||||
- 必须审计
|
||||
- 不建议对公网完全开放
|
||||
@@ -471,7 +471,7 @@ flowchart TD
|
||||
当出现这些需求时,再进入下一阶段:
|
||||
|
||||
- 多人同时在线
|
||||
- 多百梦主协作
|
||||
- 多陶泥儿主协作
|
||||
- 图片/视频生成任务变多
|
||||
- 需要账号体系、存档、云同步
|
||||
- 需要审计和版本回滚
|
||||
|
||||
@@ -109,7 +109,7 @@ src/
|
||||
|
||||
聚合:
|
||||
|
||||
1. `AuthUser`:账号、公开百梦号、登录方式、绑定状态、token version。
|
||||
1. `AuthUser`:账号、公开陶泥号、登录方式、绑定状态、token version。
|
||||
2. `RefreshSession`:refresh token hash、客户端信息、过期、吊销、last seen。
|
||||
3. `SmsVerification`:手机号、场景、验证码状态、冷却、失败次数。
|
||||
4. `WechatBinding`:微信 provider 身份、union id、绑定状态。
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
10. `RefreshSessionRecord`
|
||||
11. `AuthStoreSnapshotRecord`
|
||||
12. 密码长度、短信验证码长度、验证码 TTL、冷却、失败次数等领域常量。
|
||||
13. 手机号规范化、手机号脱敏、公开百梦号规范化、验证码 key 构造等纯函数。
|
||||
13. 手机号规范化、手机号脱敏、公开陶泥号规范化、验证码 key 构造等纯函数。
|
||||
|
||||
本次将以下写入输入落入 `commands.rs`:
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
本次继续把留在 SpacetimeDB adapter 中的纯规则收回 `module-runtime`:
|
||||
|
||||
1. played world、snapshot wallet ledger、save archive、recharge order、recharge wallet ledger、redeem usage、redeem ledger 等 ID 生成规则。
|
||||
2. 首充光点奖励计算。
|
||||
2. 首充泥点奖励计算。
|
||||
3. 会员购买续期时间计算。
|
||||
4. 邀请码 deterministic 生成、邀请链接、每日奖励窗口和邀请人奖励上限判断。
|
||||
5. 兑换码 public / unique / private 模式使用资格校验。
|
||||
|
||||
@@ -206,7 +206,7 @@
|
||||
|
||||
1. 密码登录仍由 `user_account.password_hash` 承担
|
||||
2. 本轮不引入 `password` provider identity
|
||||
3. 密码登录只接受已绑定手机号的账号,不支持邮箱、用户名或百梦号作为登录身份
|
||||
3. 密码登录只接受已绑定手机号的账号,不支持邮箱、用户名或陶泥号作为登录身份
|
||||
4. 密码登录不创建账号,新账号只由手机号验证码登录创建
|
||||
|
||||
### 9.2 `POST /api/auth/phone/login`
|
||||
|
||||
@@ -82,7 +82,7 @@ SELECT * FROM auth_store_projection_meta WHERE meta_id = 'default';
|
||||
|
||||
### `user_account`
|
||||
|
||||
- 作用:用户账号主表,保存用户名、公开百梦号、手机号掩码、登录方式、密码登录开关、token 版本和默认不前端展示的运营标签。
|
||||
- 作用:用户账号主表,保存用户名、公开陶泥号、手机号掩码、登录方式、密码登录开关、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: Option<Vec<String>>`。
|
||||
- 说明:`user_tags` 数据库默认 `None`,业务读取时按空数组归一化;只允许后端白名单投影到特定业务接口,不得在登录态、个人资料等通用前端响应中直接暴露。
|
||||
- 索引:`username`, `public_user_code`。
|
||||
@@ -154,7 +154,7 @@ SELECT * FROM user_browse_history WHERE user_id = '<user_id>' AND owner_user_id
|
||||
- 作用:个人主页聚合状态,保存钱包余额和总游玩时长。
|
||||
- 结构:`user_id PK: String`, `wallet_balance: u64`, `total_play_time_ms: u64`, `created_at: Timestamp`, `updated_at: Timestamp`。
|
||||
- 索引:主键 `user_id`。
|
||||
- 新用户注册成功后默认写入 `10` 个光点,余额仍以后端钱包 projection 为准。
|
||||
- 新用户注册成功后默认写入 `10` 个泥点,余额仍以后端钱包 projection 为准。
|
||||
|
||||
```sql
|
||||
SELECT * FROM profile_dashboard_state WHERE user_id = '<user_id>';
|
||||
@@ -244,7 +244,7 @@ SELECT * FROM profile_task_reward_claim WHERE claim_id = '<user_id>:daily_login:
|
||||
|
||||
### `profile_redeem_code`
|
||||
|
||||
- 作用:运营发放的光点兑换码,支持公共码、唯一码和私有码。
|
||||
- 作用:运营发放的泥点兑换码,支持公共码、唯一码和私有码。
|
||||
- 结构:`code PK: String`, `mode: RuntimeProfileRedeemCodeMode`, `reward_points: u64`, `max_uses: u32`, `global_used_count: u32`, `enabled: bool`, `allowed_user_ids: Vec<String>`, `created_by: String`, `created_at: Timestamp`, `updated_at: Timestamp`。
|
||||
- 索引:主键 `code`。
|
||||
- 后台读取:`GET /admin/api/profile/redeem-codes` 从该表返回已有兑换码,后台列表点击后通过 upsert 修改同一条记录。
|
||||
@@ -338,7 +338,7 @@ SELECT * FROM profile_membership WHERE user_id = '<user_id>';
|
||||
|
||||
### `profile_recharge_order`
|
||||
|
||||
- 作用:充值订单表,记录用户购买光点或会员的订单、支付渠道、支付时间、积分变更和会员到期时间。
|
||||
- 作用:充值订单表,记录用户购买泥点或会员的订单、支付渠道、支付时间、积分变更和会员到期时间。
|
||||
- 结构:`order_id PK: String`, `user_id: String`, `product_id: String`, `product_title: String`, `kind: RuntimeProfileRechargeProductKind`, `amount_cents: u64`, `status: RuntimeProfileRechargeOrderStatus`, `payment_channel: String`, `paid_at: Option<Timestamp>`, `provider_transaction_id: Option<String>`, `created_at: Timestamp`, `points_delta: i64`, `membership_expires_at: Option<Timestamp>`。
|
||||
- 支付口径:`mock` 渠道创建后立即 `paid` 并入账;微信小程序 `wechat_mp` 渠道创建时为 `pending`,微信支付通知确认后改为 `paid`,`provider_transaction_id` 保存微信支付平台订单号。
|
||||
- 索引:`user_id`, `(user_id, created_at)`。
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
- 发布
|
||||
3. 完整复制外部 TXT 模式的运行机制:
|
||||
- 玩家游玩会话
|
||||
- 百梦主测试/读档会话
|
||||
- 陶泥儿主测试/读档会话
|
||||
- 流式动作执行
|
||||
- 文本模式显示
|
||||
- 历史记录
|
||||
@@ -101,7 +101,7 @@
|
||||
- 属性面板
|
||||
5. 双会话机制:
|
||||
- 玩家游玩会话
|
||||
- 百梦主测试/读档会话
|
||||
- 陶泥儿主测试/读档会话
|
||||
6. 流式动作接口与事件协议:
|
||||
- `start`
|
||||
- `raw_text`
|
||||
@@ -553,7 +553,7 @@ TXT 模式后续必须完整落地双会话机制:
|
||||
1. 玩家游玩会话
|
||||
- 对应外部 `POST /api/optical/games/session/create`
|
||||
- 用于正式游玩
|
||||
2. 百梦主测试/读档会话
|
||||
2. 陶泥儿主测试/读档会话
|
||||
- 对应外部 `POST /api/visual/session/create`
|
||||
- 用于测试体验与加载指定存档
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ Accept: text/event-stream
|
||||
|
||||
```json
|
||||
{
|
||||
"text": "你好,欢迎来到百梦。",
|
||||
"text": "你好,欢迎来到陶泥儿。",
|
||||
"speaker": "zh_female_cancan_mars_bigtts",
|
||||
"audioParams": {
|
||||
"format": "mp3",
|
||||
|
||||
Reference in New Issue
Block a user