Merge branch 'master' into codex/puzzle-clear-template-runtime-fixes
# Conflicts: # .hermes/shared-memory/decision-log.md # .hermes/shared-memory/project-overview.md # docs/【开发运维】本地开发验证与生产运维-2026-05-15.md # scripts/dev.test.ts # server-rs/crates/api-server/src/creation_entry_config.rs # server-rs/crates/api-server/src/wooden_fish.rs # server-rs/crates/module-auth/src/lib.rs # server-rs/crates/spacetime-client/src/wooden_fish.rs # server-rs/crates/spacetime-module/src/auth/procedures.rs # src/components/custom-world-home/creationWorkShelf.ts # src/components/platform-entry/PlatformEntryFlowShellImpl.tsx # src/components/rpg-entry/rpgEntryWorldPresentation.ts # src/services/miniGameDraftGenerationProgress.test.ts # src/services/miniGameDraftGenerationProgress.ts
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
- [审计与复盘](./audits/README.md):工程审查、文本/乱码审计、专项落地审计。
|
||||
- [系统设计](./design/README.md):玩法、关系、物品与对话设计。
|
||||
- [技术方案](./technical/README.md):动画、服务端、外部产品形态拆解。
|
||||
- [规划与优先级](./planning/README.md):当前阶段的迭代排序与落地优先级。
|
||||
- [规划与优先级](./planning/README.md):当前阶段的迭代排序与落地优先级;创作流程统一总计划见 [【玩法创作】创作流程统一总计划-2026-05-30.md](./planning/%E3%80%90%E7%8E%A9%E6%B3%95%E5%88%9B%E4%BD%9C%E3%80%91%E5%88%9B%E4%BD%9C%E6%B5%81%E7%A8%8B%E7%BB%9F%E4%B8%80%E6%80%BB%E8%AE%A1%E5%88%92-2026-05-30.md)。
|
||||
- [参考目录](./reference/README.md):脚本/Function 速查入口。
|
||||
重点补充:RPG 创作与运行时脚本职责地图见 [RPG_CREATION_AND_RUNTIME_SCRIPT_RESPONSIBILITY_MAP_2026-04-28.md](./reference/RPG_CREATION_AND_RUNTIME_SCRIPT_RESPONSIBILITY_MAP_2026-04-28.md)。
|
||||
- [埋点查询](./tracking/README.md):埋点原始事件与聚合投影的本地 SQL 查询。
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
从文字需求生成高一致性美术素材流程抽象出的发明专利交底稿见 [【专利交底】一种极低成本快速生成高质量2D小游戏高一致性美术素材的解决方案-2026-05-25.md](./%E3%80%90%E4%B8%93%E5%88%A9%E4%BA%A4%E5%BA%95%E3%80%91%E4%B8%80%E7%A7%8D%E6%9E%81%E4%BD%8E%E6%88%90%E6%9C%AC%E5%BF%AB%E9%80%9F%E7%94%9F%E6%88%90%E9%AB%98%E8%B4%A8%E9%87%8F2D%E5%B0%8F%E6%B8%B8%E6%88%8F%E9%AB%98%E4%B8%80%E8%87%B4%E6%80%A7%E7%BE%8E%E6%9C%AF%E7%B4%A0%E6%9D%90%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88-2026-05-25.md)。
|
||||
|
||||
微信小程序虚拟支付接入、`wechat_mp_virtual` 渠道、`wx.requestVirtualPayment` 承接页和后端签名配置见 [【技术方案】微信虚拟支付接入-2026-05-26.md](./%E3%80%90%E6%8A%80%E6%9C%AF%E6%96%B9%E6%A1%88%E3%80%91%E5%BE%AE%E4%BF%A1%E8%99%9A%E6%8B%9F%E6%94%AF%E4%BB%98%E6%8E%A5%E5%85%A5-2026-05-26.md)。
|
||||
|
||||
生产部署切换到 systemd + Nginx + SpacetimeDB 自托管的总方案见 [PRODUCTION_DEPLOYMENT_PLAN_2026-05-02.md](./technical/PRODUCTION_DEPLOYMENT_PLAN_2026-05-02.md),该文档也是当前生产 Jenkinsfile 的唯一入口。SpacetimeDB 表结构变更、自动迁移边界和保留旧数据的分阶段迁移流程见 [SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md](./technical/SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md);private 表迁移 JSON 导入导出、HTTP 413 分片导入和旧数据库迁移流水线经验见 [SPACETIMEDB_JSON_STRING_MIGRATION_PROCEDURE_2026-04-27.md](./technical/SPACETIMEDB_JSON_STRING_MIGRATION_PROCEDURE_2026-04-27.md) 与 [JENKINS_SPACETIMEDB_DATABASE_MIGRATION_PIPELINES_2026-04-29.md](./technical/JENKINS_SPACETIMEDB_DATABASE_MIGRATION_PIPELINES_2026-04-29.md);后台管理独立前端工程技术方案见 [ADMIN_WEB_CONSOLE_TECHNICAL_SOLUTION_2026-04-30.md](./technical/ADMIN_WEB_CONSOLE_TECHNICAL_SOLUTION_2026-04-30.md)。
|
||||
|
||||
SpacetimeDB 表结构变更、自动迁移边界和保留旧数据的分阶段迁移流程见 [SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md](./technical/SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md)。
|
||||
@@ -39,7 +41,7 @@ AI 文字游戏模板接入以 [AI_NATIVE_TEXT_GAME_TEMPLATE_MOKU_REFERENCE_PRD_
|
||||
|
||||
1. 先看 [经验沉淀](./experience/README.md),快速建立这个项目的开发共识。
|
||||
2. 再看 [工程审查总览](./audits/engineering/README.md) 和 [文本审计总览](./audits/text/README.md),了解当前风险。
|
||||
3. 需要排期时看 [规划与优先级](./planning/README.md)。
|
||||
3. 需要排期时看 [规划与优先级](./planning/README.md),创作链路相关任务优先看创作流程统一总计划。
|
||||
4. 需要补方案时进入 [系统设计](./design/README.md) / [技术方案](./technical/README.md);涉及后端先看 [当前后端实现基线](./technical/CURRENT_BACKEND_IMPLEMENTATION_BASELINE_2026-04-25.md),涉及生产发布链路先看 [生产部署计划](./technical/PRODUCTION_DEPLOYMENT_PLAN_2026-05-02.md),涉及 SpacetimeDB 表结构变更时再看 [表结构变更约束](./technical/SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md)。
|
||||
5. 需要对齐目标边界时再进入 [PRD](./prd)。
|
||||
|
||||
|
||||
13
docs/planning/README.md
Normal file
13
docs/planning/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# 规划与优先级
|
||||
|
||||
本目录保存仍处于推进中的阶段计划、并行任务拆分、可派发任务包和验收顺序。长期稳定的产品与架构口径仍以根部融合文档为准。
|
||||
|
||||
## 当前计划
|
||||
|
||||
- [【玩法创作】创作流程统一总计划-2026-05-30.md](./【玩法创作】创作流程统一总计划-2026-05-30.md):创作入口、统一创作页、统一生成页、结果页、发布、作品架、广场和运行态的阶段计划、进度记录、并行波次和可直接派发的任务包。
|
||||
|
||||
## 维护规则
|
||||
|
||||
- 计划文档只记录可执行阶段、负责人切分、验收门禁和当前状态。
|
||||
- 已经稳定为长期约定的内容,应同步沉淀到 `docs/【玩法创作】平台入口与玩法链路-2026-05-15.md` 或 `.hermes/shared-memory/`。
|
||||
- 若代码事实与计划冲突,以代码和当前融合文档为准,并回写更新本目录。
|
||||
375
docs/planning/【玩法创作】创作流程统一总计划-2026-05-30.md
Normal file
375
docs/planning/【玩法创作】创作流程统一总计划-2026-05-30.md
Normal file
@@ -0,0 +1,375 @@
|
||||
# 创作流程统一总计划
|
||||
|
||||
更新时间:`2026-05-30`
|
||||
|
||||
## 总览
|
||||
|
||||
| 项目 | 当前值 |
|
||||
| --- | --- |
|
||||
| 总轮次 | 5 |
|
||||
| 当前轮次 | Round 4(已收口) |
|
||||
| 当前阶段 | Phase 6 |
|
||||
| 当前状态 | Phase 0~6 已收口;统一创作页已升级为 `UnifiedCreationWorkspace`,平台壳不再直接依赖旧工作台文件 |
|
||||
| 当前并行波次 | 波次 D(验收与冻结) |
|
||||
| 当前重点 | 以跨玩法门禁作为后续新增玩法和回归的常规质量基线 |
|
||||
|
||||
## 目标与范围
|
||||
|
||||
本计划统一 Genarrative 所有玩法的创作链路,不再只跟踪首批的拼图、抓大鹅和敲木鱼。最终目标是让各玩法按同一条平台链路交付:
|
||||
|
||||
```text
|
||||
创作入口 -> 统一创作页/工作台 -> 统一生成页 -> 结果页 -> 试玩 -> 发布 -> 统一作品详情/作品架/广场 -> 正式 runtime
|
||||
```
|
||||
|
||||
统一不是把所有玩法 UI 做成同一个表单,而是统一阶段、契约、恢复、生成反馈、错误承接、发布后去向和验收门禁。各玩法工作台仍负责真实输入控件、资产槽位、校验和提交。
|
||||
|
||||
## 当前进度
|
||||
|
||||
| 阶段 | 状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| Phase 0 总计划与门禁 | 已完成 | 本文档、`docs/planning/README.md`、`docs/README.md` 和 `.hermes/shared-memory/document-map.md` 已补齐入口;后续按 phase 扩展门禁。 |
|
||||
| Phase 1 首批统一壳 | 已收口 | `puzzle`、`match3d`、`jump-hop`、`wooden-fish` 已接入 `UnifiedCreationPage` / `UnifiedGenerationPage`,竖屏滚动和字段契约已回归。 |
|
||||
| Phase 1 补充统一壳 | 已收口 | `jump-hop` 也已接入 `UnifiedCreationPage` / `UnifiedGenerationPage`,统一创作页现在接管拼图、抓大鹅、跳一跳和敲木鱼四条入口的可见外壳与滚动。 |
|
||||
| Phase 2 契约与配置治理 | 已完成 | `creationTypes[].unifiedCreationSpec`、前端 fallback、后台配置校验和文档门禁已按现有测试与 schema 检查收口。 |
|
||||
| Phase 3 剩余表单/图片工作台接入 | 已收口 | 跳一跳、宝贝识物、方洞结果页与首批普通工作台回归已通过;方洞、大鱼按当前形态纳入最小回归,后续若迁移工作台再单独立项。 |
|
||||
| Phase 4 特殊工作台接入策略 | 已收口 | RPG、视觉小说、汪汪声浪的最小例外/闭环回归已通过,例外口径已落到平台总链路文档。 |
|
||||
| Phase 5 结果页、发布、作品架与广场收口 | 已收口 | 结果页、发布、公开详情、推荐 runtime 与公开 read model 最小自动回归已通过,公开详情作者展示口径已统一。 |
|
||||
| Phase 6 全链路验收与冻结 | 已收口 | 跨玩法 smoke、移动端优先验收、回归矩阵、长期维护规则和冻结证据已补齐。 |
|
||||
|
||||
此表即总进度记录,后续每次 phase 收口、启动或回退时,只更新这里和下方任务状态。
|
||||
|
||||
当前已完成 Round 0~4 / Phase 0~6。后续新增玩法或统一链路改动以本文档和 `quality-gates/【玩法创作】跨玩法回归与冒烟门禁-2026-05-30.md` 为常规质量基线。
|
||||
|
||||
## 执行轮次
|
||||
|
||||
按可交付批次拆成 5 轮(Round 0~4)。当前已完成 Round 0~4,Round 4 / 波次 D 已作为冻结基线收口。
|
||||
|
||||
| 轮次 | 覆盖阶段 | 目标 | 状态 |
|
||||
| --- | --- | --- | --- |
|
||||
| Round 0 | Phase 0 | 补齐总计划、文档入口和并行任务表 | 已完成 |
|
||||
| Round 1 | Phase 2 | 契约与配置治理 | 已完成 |
|
||||
| Round 2 | Phase 3 + Phase 4 | 普通工作台并行接入,特殊工作台先定例外边界 | 已完成 |
|
||||
| Round 3 | Phase 5 | 结果页、发布、作品架与广场收口 | 已完成 |
|
||||
| Round 4 | Phase 6 | 全链路验收与冻结 | 已完成 |
|
||||
|
||||
## 阶段拆分
|
||||
|
||||
### Phase 0:总计划与执行门禁
|
||||
|
||||
目标:让团队有一个唯一可查的总计划、进度表和并行任务清单。
|
||||
|
||||
状态:已完成。
|
||||
|
||||
- 新增本计划文档和 `docs/planning/README.md`,并在 `docs/README.md`、`.hermes/shared-memory/document-map.md` 中补上规划入口。
|
||||
- 补齐 `当前进度`、`执行轮次` 和可并行任务表,后续每个 phase 完成后更新本文档的状态、验收命令和风险。
|
||||
|
||||
退出条件:
|
||||
|
||||
- 文档入口可从 `docs/README.md` 找到。
|
||||
- 总计划包含阶段、进度、并行任务、验收和风险。
|
||||
|
||||
### Phase 1:首批统一壳收口
|
||||
|
||||
目标:用低风险的四条链路验证统一创作/生成壳。
|
||||
|
||||
- 范围:`puzzle`、`match3d`、`jump-hop`、`wooden-fish`。
|
||||
- 创作页统一经过 `UnifiedCreationPage`,工作台保留各自真实输入能力。
|
||||
- 生成页统一经过 `UnifiedGenerationPage` 和 `CustomWorldGenerationView`。
|
||||
- 竖屏滚动由统一创作页承担,避免内层滚动窗。
|
||||
|
||||
状态:已收口。
|
||||
|
||||
### Phase 2:契约与配置治理
|
||||
|
||||
目标:把统一创作页从前端“能渲染”推进到平台配置“可治理”。
|
||||
|
||||
- 明确 `unifiedCreationSpec` 的字段种类、必填语义、阶段映射和兼容 fallback。
|
||||
- 后台配置、前台读取和 `api-server` 路由熔断继续以 SpacetimeDB 入口配置为事实源。
|
||||
- 前端本地 fallback 只服务旧后端或本地异常,不作为新增玩法事实源。
|
||||
- 为字段契约、入口开放状态、阶段映射补自动测试。
|
||||
|
||||
退出条件:
|
||||
|
||||
- `creation-entry config` 契约在前后端文档中闭合。
|
||||
- 新增玩法不能绕过统一入口配置接线。
|
||||
|
||||
状态:已完成。
|
||||
|
||||
验证:`npm run check:encoding`、`npm run typecheck`、`npm run admin-web:typecheck`、`npm run check:spacetime-schema` 和统一创作页 / 统一生成页相关测试已通过。
|
||||
|
||||
### Phase 3:剩余表单/图片工作台接入
|
||||
|
||||
目标:把结构相近的玩法先迁到统一创作与生成壳,扩大覆盖面。
|
||||
|
||||
候选范围:
|
||||
|
||||
- 第一批直接迁移:`jump-hop`、`baby-object-match`
|
||||
- 需要先做工作台形态评估:`square-hole`、`big-fish`
|
||||
- 其它已经是表单/图片输入工作台、且无复杂多阶段编辑器的玩法
|
||||
|
||||
统一要求:
|
||||
|
||||
- 继续复用 `CreativeImageInputPanel`、`CreativeAudioInputPanel` 等现有通用输入组件。
|
||||
- 不在工作台 UI 中默认写规则说明或功能解释。
|
||||
- 自动素材生成走统一生成页;没有自动生成的玩法需要明确跳过生成页的阶段策略。
|
||||
- 结果页和 runtime 不因迁移创作页而改业务真相。
|
||||
- `square-hole`、`big-fish` 先评估是否保留 Agent 形态还是迁到表单/图片工作台,再决定是否进入直接迁移实现。
|
||||
- `jump-hop` 已纳入统一创作壳,后续若要调整字段或视觉,只能在统一壳与工作台之间协同改,不再恢复独立入口壳。
|
||||
|
||||
退出条件:
|
||||
|
||||
- 每个接入玩法都有创作页、生成页或跳过生成页的明确验收。
|
||||
- 移动端竖屏能从标题、表单滚动到提交按钮。
|
||||
|
||||
状态:已收口。
|
||||
|
||||
2026-05-30 回归记录:
|
||||
|
||||
- `jump-hop`、`baby-object-match`、`big-fish`、`square-hole` 的核心工作台 / 结果页 / runtime 测试已补齐并通过。
|
||||
- `jump-hop` 结果页刷新恢复已补齐 `profileId -> getWorkDetail` 回读;直达 `/creation/jump-hop/result` 且缺少恢复参数时显示“跳一跳草稿未恢复”恢复面板,不再白屏。
|
||||
- `square-hole` 结果页的试玩 / 发布路径已补齐服务 mock 回归,确认保存成功后才触发试玩和发布回调。
|
||||
- 首批普通工作台回归通过:拼图、抓大鹅、敲木鱼、跳一跳、宝贝识物、方洞结果页。
|
||||
- 竖屏浏览器 smoke 已覆盖 `/creation/jump-hop`、`/creation/baby-object-match`、`/creation/square-hole`、`/creation/bark-battle`、`/creation/visual-novel`、`/creation/jump-hop/generating`、`/creation/jump-hop/result`、`/runtime/jump-hop`,截图保存在 `.app/browser-check/phase-flow-20260530/`。
|
||||
|
||||
### Phase 4:特殊工作台接入策略
|
||||
|
||||
目标:处理不能直接套表单/图片工作台的玩法,先定边界再迁移。
|
||||
|
||||
候选范围:
|
||||
|
||||
- RPG / 自定义世界
|
||||
- 视觉小说
|
||||
- 汪汪声浪(`bark-battle`)
|
||||
- 其它多阶段编辑器、对话式 Agent 或特殊创作流
|
||||
|
||||
统一要求:
|
||||
|
||||
- 必须在玩法文档中写明“创作工具模式例外”。
|
||||
- 例外只影响工作台内部,不影响入口配置、生成反馈、结果页、发布、作品架、广场和 runtime 的平台主链路。
|
||||
- 对话式或多阶段编辑器仍需和统一作品、统一错误、统一生成完成反馈对齐。
|
||||
- `bark-battle` 默认按特殊工作台收口;若后续产品决策确认可完全表单化,再单独前移到 Phase 3,不在本轮默认假设里。
|
||||
|
||||
退出条件:
|
||||
|
||||
- 每个特殊玩法都有例外声明、阶段映射和验收清单。
|
||||
- 没有新增平行入口系统、平行作品架或平行公开列表。
|
||||
|
||||
状态:已收口。
|
||||
|
||||
2026-05-30 回归记录:
|
||||
|
||||
- RPG 例外边界指定 interaction 测试通过。
|
||||
- Bark Battle 创作入口、结果页试玩/发布和正式 runtime 指定 interaction 测试通过。
|
||||
- 视觉小说工作台、生成阶段、结果页和运行态测试通过,`npm run check:visual-novel-vn11` 通过。
|
||||
|
||||
### Phase 5:结果页、发布、作品架与广场收口
|
||||
|
||||
目标:把“创作页统一”推进到“交付链路统一”。
|
||||
|
||||
- 发布成功默认进入统一作品详情或明确的 runtime 去向。
|
||||
- 草稿架能恢复生成中、失败、待发布和已发布状态。
|
||||
- 公开列表、发现流、详情页优先消费后端 read model 或 BFF 缓存。
|
||||
- 跨流程错误统一进入 `PlatformErrorDialog`,异步完成统一进入 `PlatformTaskCompletionDialog`。
|
||||
- 私有 generated 图片展示前必须换签。
|
||||
|
||||
退出条件:
|
||||
|
||||
- 每个可发布玩法都有作品架、公开详情、广场或明确不公开声明。
|
||||
- 生成中刷新、失败重试、发布后回读和登录切换都有测试或手测记录。
|
||||
|
||||
状态:已收口。
|
||||
|
||||
2026-05-30 回归记录:
|
||||
|
||||
- 发布到作品详情、已发布作品进入详情、体验按钮直达 runtime、详情 profile 回读指定 interaction 测试通过。
|
||||
- 拼图已发布作品进入首页和移动端游戏分类、Big Fish 公开隐藏口径、Match3D 推荐 runtime 资源回读指定 interaction 测试通过。
|
||||
- 公开详情作者展示统一为“公开昵称 · 陶泥号”,`PlatformWorkDetailView` 与公共作者展示 helper 测试已回归。
|
||||
- 本地 API smoke 已在重新拉起 `dev:spacetime` 和 `dev:api-server` 后通过:`GET http://127.0.0.1:8082/healthz` 返回 `{"ok":true,"service":"genarrative-api-server"}`。
|
||||
|
||||
### Phase 6:全链路验收与冻结
|
||||
|
||||
目标:形成后续新增玩法可复用的稳定门禁。
|
||||
|
||||
- 按玩法输出创作入口、生成页、结果页、试玩、发布、作品架、广场、runtime smoke 矩阵。
|
||||
- 增补 `quality-gates/README.md` 与跨玩法回归 / 冒烟门禁,不再只覆盖首批四条链路。
|
||||
- 固化移动端竖屏优先验收,桌面端作为兼容验证。
|
||||
- 补齐“新增玩法接入 PRD 检查块”和代码评审检查清单。
|
||||
|
||||
退出条件:
|
||||
|
||||
- 全部计划内玩法均有明确状态:已统一、例外接入、暂不接入。
|
||||
- `npm run typecheck`、`npm run check:encoding` 和对应玩法门禁通过。
|
||||
|
||||
状态:已收口。
|
||||
|
||||
2026-05-30 冻结记录:
|
||||
|
||||
- Phase 2 自动回归通过:入口配置、统一字段 spec、统一创作页和统一生成页测试共 11 项。
|
||||
- Phase 3 自动回归通过:拼图、抓大鹅、敲木鱼、跳一跳、宝贝识物、大鱼、方洞结果页相关测试共 67 项;跳一跳直达结果页恢复测试通过。
|
||||
- Phase 4 / Phase 5 指定交互回归通过:RPG 例外边界、Bark Battle 闭环、作品详情、推荐 runtime、公开 read model 与跳一跳恢复相关 interaction 测试共 18 项。
|
||||
- Phase 5 详情 / 弹窗 / 作品架回归通过:公开详情、错误弹窗、反馈弹窗、作品展示 helper、作品架交互测试共 63 项。
|
||||
- `npm run check:visual-novel-vn11`、`npm run check:spacetime-schema`、`npm run check:encoding` 均通过。
|
||||
- API smoke 通过:`GET http://127.0.0.1:8082/healthz` 返回 `{"ok":true,"service":"genarrative-api-server"}`。
|
||||
- 竖屏浏览器 smoke 通过并保存截图:`.app/browser-check/phase-flow-20260530-round5/`,覆盖 `/creation/jump-hop`、`/creation/visual-novel`、`/creation/square-hole`、`/creation/bark-battle`、`/creation/baby-object-match`、`/creation/jump-hop/generating`、`/creation/jump-hop/result`、`/runtime/jump-hop`。
|
||||
|
||||
### Phase 6 补充:跨玩法最小验收口径
|
||||
|
||||
Phase 6 不再继续拆新波次,当前只把 Phase 2 到 Phase 5 的最小验证集合收束成一份可直接执行的门禁矩阵。建议顺序如下:
|
||||
|
||||
| 阶段 | 最小命令 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| Phase 2 | `npm run check:encoding`、`npm run typecheck`、`npm run admin-web:typecheck`、`npm run test -- src/components/platform-entry/platformEntryCreationTypes.test.ts src/components/unified-creation/unifiedCreationSpecs.test.ts src/components/unified-creation/UnifiedCreationPage.test.tsx src/components/unified-creation/UnifiedGenerationPage.test.tsx` | 校验入口配置、统一字段 spec、统一创作页和统一生成页。 |
|
||||
| Phase 3 | `npm run test -- src/components/unified-creation/workspaces/PuzzleCreationWorkspace.interaction.test.tsx src/components/unified-creation/workspaces/Match3DCreationWorkspace.interaction.test.tsx src/components/unified-creation/workspaces/WoodenFishCreationWorkspace.test.tsx src/components/unified-creation/workspaces/JumpHopCreationWorkspace.test.tsx src/components/jump-hop-result/JumpHopResultView.test.tsx src/components/jump-hop-runtime/JumpHopRuntimeShell.test.tsx src/components/edutainment-creation/BabyObjectMatchWorkspace.test.tsx src/components/edutainment-result/BabyObjectMatchResultView.test.tsx src/components/edutainment-runtime/BabyObjectMatchRuntimeShell.test.tsx src/components/big-fish-creation/BigFishAgentWorkspace.interaction.test.tsx src/components/big-fish-result/BigFishResultView.test.tsx src/components/big-fish-runtime/BigFishRuntimeShell.test.tsx`;`npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "direct jump hop result route"` | 校验普通表单 / 图片 / 音频工作台仍按结构化 payload 提交,跳一跳结果页直达恢复不白屏,并把 BabyObjectMatch / BigFish 一并纳入最小回归。 |
|
||||
| Phase 4 | `npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "opening RPG agent workspace does not refetch session snapshot in a render loop|create tab resumes agent workspace when draft has no compiled result yet|create tab resumes agent workspace when session has no draft profile even if summary counts look compiled|opening a compiled draft with a missing agent session falls back to draft hub"`、`npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "create tab opens bark battle entry form from the template card|bark battle draft result can test before publish and publish to work detail|direct bark battle runtime public code opens published runtime"`、`npm run check:visual-novel-vn11` | 校验特殊工作台例外、Bark Battle 公开闭环和视觉小说负向门禁。 |
|
||||
| Phase 5 | `npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "agent draft result publishes to gallery from publish panel|creation hub published work enters existing detail view|creation hub published work experience button enters world directly|creation hub published work start uses loaded detail profile instead of library summary"`、`npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "published puzzle works appear on home and mobile game category channel|published big fish works stay hidden from platform home and mobile game category channel|home recommendation Match3D runtime keeps profile generated models when card summary is stale|home recommendation Match3D runtime passes top-level UI background assets|home recommendation Match3D runtime reloads detail when card only has UI assets"`、`npm run test -- src/components/platform-entry/PlatformWorkDetailView.test.tsx src/components/platform-entry/PlatformErrorDialog.test.tsx src/components/platform-entry/PlatformFeedbackView.test.tsx src/components/rpg-entry/rpgEntryWorldPresentation.test.ts`、`npm run test -- src/components/custom-world-home/CustomWorldCreationHub.test.tsx src/components/custom-world-home/CustomWorldCreationHub.interaction.test.tsx` | 校验结果页、发布、作品架、公开详情、推荐 runtime 和公开 read model,并补公开详情作者展示口径与作品架恢复矩阵。 |
|
||||
|
||||
如果这轮还改了 SpacetimeDB schema,追加 `npm run check:spacetime-schema`;如果还改了 API 路由、BFF、公开列表或 `/works/detail` 回读,追加 `npm run dev:api-server`,并另开终端从 `.app/dev-stack.json` 读取实际 `api-server` URL 后检查 `/healthz`。
|
||||
|
||||
## 可并行任务列表
|
||||
|
||||
| 任务 ID | 可并行 | 状态 | 任务 | 主要产出 | 依赖 | 建议 Owner |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| T0-1 | 否 | 已完成 | 总计划与文档入口 | 本文档、`docs/planning/README.md`、文档索引更新 | 无 | 文档 owner |
|
||||
| T1-1 | 否 | 已完成 | Phase 1 收口确认 | 三条首批链路验收记录、已知风险 | T0-1 | 前端 owner |
|
||||
| T2-1 | 是 | 已完成 | `unifiedCreationSpec` 契约审计 | 字段种类、必填、阶段映射、fallback 规则 | T0-1 | 契约 owner |
|
||||
| T2-2 | 是 | 已完成 | 后台入口配置治理 | 后台配置校验与配置说明 | T2-1 | 后台 owner |
|
||||
| T2-3 | 是 | 已完成 | 前端入口读取与 fallback 测试 | 入口配置单测、异常兜底测试 | T2-1 | 前端 owner |
|
||||
| T3-1 | 是 | 自动回归通过 | 跳一跳统一接入方案与实现 | 统一创作工作台、生成页迁移、验收 | T2-1 | 玩法 owner A |
|
||||
| T3-2 | 是 | 自动回归通过 | 宝贝识物统一接入方案与实现 | 创作页/生成页迁移、验收 | T2-1 | 玩法 owner B |
|
||||
| T3-3 | 是 | 最小回归通过 | 方洞工作台形态评估与迁移方案 | 保留 Agent 形态还是迁表单的决策、边界和风险清单 | T2-1 | 玩法 owner C |
|
||||
| T3-4 | 是 | 最小回归通过 | 大鱼工作台形态评估与迁移方案 | 保留 Agent 形态还是迁表单的决策、边界和风险清单 | T2-1 | 玩法 owner D |
|
||||
| T4-1 | 是 | 自动回归通过 | RPG 例外边界设计 | 例外声明、阶段映射、验收清单 | T2-1 | 特殊玩法 owner |
|
||||
| T4-2 | 是 | 自动回归通过 | 视觉小说例外边界设计 | 例外声明、阶段映射、验收清单 | T2-1 | 特殊玩法 owner |
|
||||
| T4-3 | 是 | 自动回归通过 | 汪汪声浪(bark-battle)统一/例外决策 | 接入或例外方案、验收清单 | T2-1 | 特殊玩法 owner |
|
||||
| T5-1 | 是 | 最小回归通过 | 统一结果页能力矩阵 | 每个玩法结果页能力与缺口表 | T3/T4 方案稳定 | 结果页 owner |
|
||||
| T5-2 | 是 | 最小回归通过 | 作品架恢复矩阵 | 生成中、失败、待发布、已发布恢复验收 | T3/T4 方案稳定 | 作品架 owner |
|
||||
| T5-3 | 是 | 最小回归通过 | 公开 read model 对齐 | 广场/详情/分享码缺口与执行清单 | T3/T4 方案稳定 | 后端 owner |
|
||||
| T5-4 | 是 | 最小回归通过 | 统一错误与完成反馈回归 | `PlatformErrorDialog`、`PlatformTaskCompletionDialog` 覆盖 | T3/T4 方案稳定 | 平台壳 owner |
|
||||
| T5-5 | 是 | 自动回归通过 | 统一创作壳滚动收口 | `UnifiedCreationPage` 统一接管四条入口滚动、跳一跳纳入统一壳 | T3/T4 方案稳定 | 平台壳 owner |
|
||||
| T6-1 | 否 | 已完成 | 全链路质量门禁扩展 | `quality-gates/README.md`、跨玩法回归 / 冒烟门禁、Phase 2 到 Phase 5 最小验证集合 | T3/T4/T5 完成 | QA owner |
|
||||
| T6-2 | 否 | 已完成 | 全量验收与冻结 | 状态表、未接入声明、最终测试记录 | T6-1 | Release owner |
|
||||
|
||||
并行原则:
|
||||
|
||||
- T2 系列已完成,T3/T4 已进入回归;后续缺口修补仍不得绕过 T2 已固定的入口配置和统一 spec 规则。
|
||||
- T3 各玩法可并行,但同一文件同一时间只允许一个 owner,尤其是 `PlatformEntryFlowShellImpl.tsx`、路由和 shared contracts。
|
||||
- T5 可以在 T3/T4 各玩法方案稳定后分块并行,不必等所有玩法实现完再开始。
|
||||
- T6 必须串行收尾,避免验收矩阵和实际实现漂移。
|
||||
|
||||
## 可直接派发的任务包
|
||||
|
||||
任务包是执行层最小分工单元。每个包都可以单独开分支、单独验收;如果两个包需要改同一个公共文件,先由公共 owner 合并接口或壳层改动,再由玩法 owner 接入,避免互相覆盖。
|
||||
|
||||
| 包 ID | 可并行对象 | 状态 | 目标 | 不做什么 | 交付物 | 验收 |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| P2-A 契约包 | 可与 P2-B、P2-C 并行 | 已完成 | 固定 `unifiedCreationSpec` 字段类型、必填、阶段映射、fallback 规则 | 不接新玩法,不改 UI 设计方向 | 前后端契约、配置字段文档、契约测试 | `npm run test -- src/components/unified-creation/unifiedCreationSpecs.test.ts src/components/platform-entry/platformEntryCreationTypes.test.ts`;涉及 schema 时追加 `npm run check:spacetime-schema` |
|
||||
| P2-B 后台配置包 | 可与 P2-A、P2-C 并行 | 已完成 | 后台入口配置能编辑、校验、保存统一创作契约 | 不做玩法工作台迁移 | 后台表单、保存校验、异常提示、后台单测 | `npm run admin-web:typecheck`;`npm run test -- apps/admin-web/src/pages/AdminCreationEntrySwitchPage.test.tsx` |
|
||||
| P2-C 前台读取包 | 可与 P2-A、P2-B 并行 | 已完成 | 前台从 `/api/creation-entry/config` 读取统一 spec,旧后端只走兜底 | 不把 fallback 当事实源,不恢复硬编码入口 | 入口派生、fallback 单测、统一创作/生成页回归 | `npm run test -- src/components/unified-creation/UnifiedCreationPage.test.tsx src/components/unified-creation/UnifiedGenerationPage.test.tsx` |
|
||||
| P3-A 跳一跳接入包 | 可与 P3-B、P3-C、P3-D 并行 | 自动回归通过 | `jump-hop` 接入统一创作壳、生成页或明确跳过策略 | 不改正式 runtime 规则真相,不重做作品架 | 入口阶段映射、统一工作台接入、生成/结果跳转、竖屏验收 | 跳一跳相关单测、统一创作页回归、移动端 `/creation/jump-hop` smoke |
|
||||
| P3-B 宝贝识物接入包 | 可与 P3-A、P3-C、P3-D 并行 | 自动回归通过 | `baby-object-match` 接入统一创作壳、生成页或明确跳过策略 | 不复制上传/历史素材逻辑 | 工作台接入、资产槽位复用、结果跳转、竖屏验收 | 宝贝识物相关单测、统一创作页回归、移动端 `/creation/baby-object-match` smoke |
|
||||
| P3-C 方洞评估包 | 可与 P3-A、P3-B、P3-D 并行 | 部分回归通过 | 判断 `square-hole` 保留 Agent 形态还是迁表单/图片工作台 | 不直接大改实现 | 例外或迁移方案、字段清单、风险、验收用例 | 文档评审通过;若改代码,补对应工作台测试 |
|
||||
| P3-D 大鱼评估包 | 可与 P3-A、P3-B、P3-C 并行 | 部分回归通过 | 判断 `big-fish` 保留 Agent 形态还是迁表单/图片工作台 | 不直接大改实现 | 例外或迁移方案、字段清单、风险、验收用例 | 文档评审通过;若改代码,补对应工作台测试 |
|
||||
| P4-A RPG 例外包 | 可与 P4-B、P4-C 并行 | 自动回归通过 | 明确 RPG 对话式工作台如何接入统一阶段、错误、完成、发布去向 | 不把 RPG 当新增玩法默认模板 | 例外声明、阶段映射、刷新恢复和发布验收 | RPG 指定 interaction 测试、作品详情/进入世界回归 |
|
||||
| P4-B 视觉小说例外包 | 可与 P4-A、P4-C 并行 | 自动回归通过 | 明确视觉小说特殊生成和结果页边界 | 不迁入外部平台社区、支付、榜单、回放 | 例外声明、上传资产口径、生成/结果/发布验收 | `npm run check:visual-novel-vn11` 和视觉小说相关测试 |
|
||||
| P4-C 汪汪声浪决策包 | 可与 P4-A、P4-B 并行 | 自动回归通过 | 判断 `bark-battle` 是特殊工作台例外还是回到表单模式 | 不同时做两套入口 | 决策记录、阶段映射、发布和 runtime 验收 | Bark Battle 创作、发布、runtime 指定测试 |
|
||||
| P5-A 结果页矩阵包 | 可与 P5-B、P5-C、P5-D 并行 | 最小回归通过 | 列清每个玩法结果页能力、缺口和最小补丁 | 不在结果页新增无需求的大功能 | 结果页能力矩阵、局部重试/上传/发布边界 | 对应结果页测试和手测记录 |
|
||||
| P5-B 作品架恢复包 | 可与 P5-A、P5-C、P5-D 并行 | 最小回归通过 | 生成中、失败、待发布、已发布都能从作品架恢复 | 不只靠前端内存 notice | 作品摘要字段、作品架 adapter、恢复测试 | 作品架相关 interaction 测试;移动端草稿 Tab smoke |
|
||||
| P5-C 公开 read model 包 | 可与 P5-A、P5-B、P5-D 并行 | 最小回归通过 | 公开列表、详情、分享和推荐 runtime 对齐后端 read model | 不让前端拼源表当事实源 | 后端 read model/BFF 缺口清单和实现 | 公开列表/详情/API smoke;必要时 `npm run dev:api-server` + `/healthz` |
|
||||
| P5-D 统一反馈包 | 可与 P5-A、P5-B、P5-C 并行 | 最小回归通过 | 错误和异步完成统一进入平台弹窗 | 不在页面内重复裸错误 banner | `PlatformErrorDialog`、`PlatformTaskCompletionDialog` 覆盖矩阵 | 平台弹窗测试、跨流程失败/完成手测 |
|
||||
| P6-A 门禁包 | 串行,依赖 P3/P4/P5 | 已完成 | 固化跨玩法自动测试、竖屏手测和 API smoke | 不继续接新玩法 | `quality-gates/`、冻结前命令集合 | 跨玩法回归与冒烟门禁通过 |
|
||||
| P6-B 冻结包 | 串行,依赖 P6-A | 已完成 | 更新总状态表,标记已统一、例外接入、暂不接入 | 不遗留“状态未知”玩法 | 总进度、风险清单、后续维护规则 | `npm run check:encoding`、关键门禁通过、文档索引有效 |
|
||||
|
||||
### 并行执行注意事项
|
||||
|
||||
- 公共壳层 owner 统一负责 `PlatformEntryFlowShellImpl.tsx`、`appPageRoutes.ts`、入口阶段类型、共享 contract 和统一生成页主流程;玩法 owner 只接自己的工作台和映射。
|
||||
- 后端 schema owner 统一负责 SpacetimeDB 表、`migration.rs`、表目录和 bindings;玩法 owner 不单独改 schema 后跳过生成绑定。
|
||||
- 文档 owner 每轮只更新本计划的状态、波次和风险,不把一次性聊天记录写进长期文档。
|
||||
- 同一波次内如果发现计划和代码事实冲突,先改计划和对应融合文档,再继续实现;不要在代码里临时绕开统一链路。
|
||||
|
||||
### 依赖关系摘要
|
||||
|
||||
- 可以并行启动:`T3-1`、`T3-2`、`T3-3`、`T3-4`,其中 `T3-3` 和 `T3-4` 先做形态评估,`T3-1` 和 `T3-2` 可以直接进入实现。
|
||||
- 可以并行启动:`T4-1`、`T4-2`、`T4-3`,但它们只做例外边界和决策,不直接扩散到新的玩法实现。
|
||||
- `T5-1`、`T5-2`、`T5-3`、`T5-4` 可以并行预研,但最好等至少一批 Phase 3 / 4 方案稳定后再落代码。
|
||||
- `T6-1`、`T6-2` 必须串行,且都依赖 Phase 3 到 Phase 5 的验证结果。
|
||||
|
||||
## 并行波次
|
||||
|
||||
### 波次 A:先定契约
|
||||
|
||||
状态:已完成。
|
||||
|
||||
- `T2-1` `unifiedCreationSpec` 契约审计
|
||||
- `T2-2` 后台入口配置治理
|
||||
- `T2-3` 前端入口读取与 fallback 测试
|
||||
|
||||
说明:三项可以并行,先把统一创作入口的真值源、后台编辑面和前端兜底一起收紧。
|
||||
|
||||
### 波次 B:第一批迁移与例外评估
|
||||
|
||||
状态:自动回归已通过,遗留形态评估按缺口任务继续跟踪。
|
||||
|
||||
- `T3-1` `jump-hop` 统一接入
|
||||
- `T5-5` 统一创作壳滚动收口
|
||||
- `T3-2` `baby-object-match` 统一接入
|
||||
- `T3-3` `square-hole` 工作台形态评估
|
||||
- `T3-4` `big-fish` 工作台形态评估
|
||||
- `T4-1` `RPG` 例外边界设计
|
||||
- `T4-2` `视觉小说` 例外边界设计
|
||||
- `T4-3` `汪汪声浪(bark-battle)` 统一/例外决策
|
||||
|
||||
说明:`jump-hop`、`baby-object-match` 已完成最小接入回归;`square-hole`、`big-fish` 的形态评估继续按缺口任务跟踪;特殊工作台例外边界已完成最小回归。
|
||||
|
||||
### 波次 C:交付链路收口
|
||||
|
||||
状态:最小回归通过。
|
||||
|
||||
- `T5-1` 统一结果页能力矩阵
|
||||
- `T5-2` 作品架恢复矩阵
|
||||
- `T5-3` 公开 read model 对齐
|
||||
- `T5-4` 统一错误与完成反馈回归
|
||||
|
||||
说明:交付链路已按页面 / read model / 弹窗分块完成最小回归,后续只处理验收发现的真实缺口。
|
||||
|
||||
### 波次 D:验收与冻结
|
||||
|
||||
状态:已收口。
|
||||
|
||||
- `T6-1` 全链路质量门禁扩展
|
||||
- `T6-2` 全量验收与冻结
|
||||
|
||||
说明:必须串行,先补门禁再冻结状态表。
|
||||
|
||||
## 验收矩阵
|
||||
|
||||
每个玩法推进时至少记录:
|
||||
|
||||
| 验收项 | 要求 |
|
||||
| --- | --- |
|
||||
| 创作入口 | 从创作 Tab 或直达 URL 能进入对应工作台,入口事实源来自 `/api/creation-entry/config`。 |
|
||||
| 创作页 | 统一标题/阶段壳存在,工作台不重复渲染巨大旧标题,移动端可滚动到提交按钮。 |
|
||||
| 输入控件 | 图片、音频、文本、选择器复用现有通用组件,不复制上传/历史图逻辑。 |
|
||||
| 生成页 | 自动生成玩法使用统一圆环生成页;无生成页玩法有明确跳转策略。 |
|
||||
| 结果页 | 能展示草稿、编辑作品信息、处理局部重生成、试玩和发布。 |
|
||||
| 恢复 | 刷新、退出登录、生成中、失败、作品架恢复都有可观察行为。 |
|
||||
| 发布与公开 | 发布后能进入统一详情或 runtime;公开列表/read model 不靠前端拼源表。 |
|
||||
| runtime | 试玩与正式运行态区分清楚,正式业务真相以后端为准。 |
|
||||
| 移动端 | 竖屏优先,无按钮遮挡、套滚动、文字溢出或固定底栏遮挡。 |
|
||||
|
||||
## 统一约束
|
||||
|
||||
- 不恢复前端硬编码入口配置。
|
||||
- 不新建平行创作入口系统、平行作品架或平行公开列表。
|
||||
- 不把功能说明、规则说明或开发解释默认写进 UI 面板。
|
||||
- 不让前端承接发布、计分、胜负、资产持久化或公开状态等业务真相。
|
||||
- 后端仍按 `server-rs + Axum + SpacetimeDB` 和 DDD 分层推进。
|
||||
- 涉及 SpacetimeDB schema 时必须同步 migration、表目录、生成绑定,并运行 schema 检查。
|
||||
|
||||
## 推荐推进顺序
|
||||
|
||||
1. 将 Round 4 / Phase 6 作为当前冻结基线,后续只做同口径回归,不再新增波次。
|
||||
2. 对 Phase 3、Phase 4、Phase 5 只处理回归发现的真实缺口,不扩新玩法。
|
||||
3. 更新冻结状态表,明确每个玩法是已统一、例外接入还是暂不接入。
|
||||
4. 后续新增玩法默认遵循本文档和 `quality-gates/【玩法创作】跨玩法回归与冒烟门禁-2026-05-30.md`,无需再补新的总计划轮次。
|
||||
|
||||
当前轮次看 Round 4 / Phase 6;Round 0~4 已作为历史完成记录保留。
|
||||
@@ -80,7 +80,7 @@ jump-hop-gallery-detail
|
||||
|
||||
新增前端组件建议:
|
||||
|
||||
1. `src/components/jump-hop-creation/JumpHopWorkspace.tsx`;
|
||||
1. `src/components/unified-creation/workspaces/JumpHopCreationWorkspace.tsx`;
|
||||
2. `src/components/jump-hop-result/JumpHopResultView.tsx`;
|
||||
3. `src/components/jump-hop-runtime/JumpHopRuntimeShell.tsx`;
|
||||
4. `src/services/jump-hop/jumpHopClient.ts`。
|
||||
|
||||
@@ -16,6 +16,8 @@ server-rs + Axum + SpacetimeDB
|
||||
|
||||
`server-rs/Cargo.toml` 是 workspace 事实源。默认构建成员为 `crates/api-server`;第三方依赖版本和 workspace 内 crate path 统一放在 `[workspace.dependencies]`。
|
||||
|
||||
SpacetimeDB 版本口径:当前 Rust crate `spacetimedb`、`spacetimedb-sdk`、`spacetimedb-lib` 统一锁定 `2.3.0`;本地 `spacetime` CLI / standalone、生成的 `spacetime-client` bindings 和容器压测镜像也必须与 `2.3.0` 对齐,避免 BSATN / procedure result 反序列化错配。
|
||||
|
||||
当前主要 crate:
|
||||
|
||||
- HTTP 服务:`api-server`。
|
||||
@@ -56,7 +58,7 @@ npm run check:server-rs-ddd
|
||||
- 个人中心:`/api/profile/*`,包括钱包流水、任务、领奖、充值、反馈、邀请、兑换、存档、历史浏览和游玩统计。
|
||||
- LLM 与语音:`/api/llm/*`、`/api/speech/volcengine/*`。
|
||||
- 资产:`/api/assets/*`,包括直传票据、STS、对象确认、实体绑定、读签名、读 bytes、历史资产、角色图像/动画和 Hyper3D 代理。
|
||||
- 创作入口配置:`/api/creation-entry/config` 与后台 `/admin/api/creation-entry/config`。
|
||||
- 创作入口配置:`/api/creation-entry/config`,后台 `/admin/api/creation-entry/config` 和 `/admin/api/creation-entry/config/banners`。
|
||||
- 自定义世界 / RPG:`/api/runtime/custom-world*`、`/api/story/*`、`/api/runtime/chat/*`。
|
||||
- 拼图:`/api/runtime/puzzle/*`。
|
||||
- 抓大鹅 Match3D:`/api/creation/match3d/*`、`/api/runtime/match3d/*`。
|
||||
@@ -240,10 +242,12 @@ npm run check:server-rs-ddd
|
||||
- Rust 结构体:`AuthStoreSnapshot`
|
||||
- 源码:`server-rs/crates/spacetime-module/src/auth/tables.rs`
|
||||
|
||||
认证恢复策略:`api-server` 启动时只从 SpacetimeDB 正式认证表(`user_account` / `auth_identity` / `refresh_session`)投影恢复进程内认证工作集;`auth_store_snapshot` 只保留行级快照备查,不再作为启动兜底来源。`module-auth` 只保留内存工作集和 JSON 导入 / 导出能力,不再写本地持久化文件;`auth-store.json` / `GENARRATIVE_AUTH_STORE_PATH` 不再是兼容恢复源,也不得在启动时回写覆盖 `auth_identity` / `user_account`。若启动恢复阶段 SpacetimeDB 不可连接或超时,`api-server` 进入依赖不可用模式并对请求返回 `503 SERVICE_UNAVAILABLE`,直到运维恢复 SpacetimeDB 并重启服务。
|
||||
认证恢复策略:`api-server` 启动时只从 SpacetimeDB 正式认证表(`user_account` / `auth_identity` / `refresh_session`)投影恢复进程内认证工作集;`auth_store_snapshot` 只保留行级快照备查,不再作为启动兜底来源。`module-auth` 只保留内存工作集和 JSON 导入 / 导出能力,不再写本地持久化文件;`auth-store.json` / `GENARRATIVE_AUTH_STORE_PATH` 不再是兼容恢复源,也不得在启动时回写覆盖 `auth_identity` / `user_account`。认证创建、登录会话、刷新、退出、改密、重置密码、绑定和资料变更等写操作必须在返回客户端前成功同步 SpacetimeDB 正式认证表;同步失败时接口返回错误,不允许把只存在于当前进程内存的账号或会话当成成功结果。新用户注册奖励、邀请码绑定和登录埋点必须排在认证同步成功之后,避免认证没落库时先写出钱包或邀请关系。若启动恢复阶段 SpacetimeDB 不可连接或超时,`api-server` 进入依赖不可用模式并对请求返回 `503 SERVICE_UNAVAILABLE`,直到运维恢复 SpacetimeDB 并重启服务。
|
||||
|
||||
`auth_store_snapshot` 禁止再写单行 `snapshot_id = "default"` 聚合 JSON。认证同步入口收到 `module-auth` 整份快照后必须拆成行级记录写入同一张表,当前行键前缀包括:`meta/next_user_id`、`user/<user_id>`、`phone/<phone+user>`、`session/<session_id>`、`session_hash/<hash+session>`、`wechat/<provider_uid+user>`、`union/<union+user>`。SpacetimeDB 模块只保留 `import_auth_store_snapshot_json` 与 `export_auth_store_snapshot_from_tables` 两个认证快照过程;旧 `get_auth_store_snapshot`、`upsert_auth_store_snapshot`、`import_auth_store_snapshot` 兼容入口已删除。导入正式表时只按主键 upsert 本次快照包含的用户、身份和会话,避免过期快照把其他用户整表删除。
|
||||
|
||||
导出认证快照时,`auth_identity` 与 `refresh_session` 只能引用仍存在于 `user_account` 的用户;孤儿手机号 identity、微信 identity、union 索引或 refresh session 必须被过滤,不能恢复成 `module-auth` 内存态里的 `phone_to_user_id` 死索引。`module-auth` 从 JSON 快照恢复时也要二次清理这些孤儿索引,避免历史坏快照导致密码登录提示错误、短信登录又提示手机号已存在。
|
||||
|
||||
### `bark_battle_draft_config`
|
||||
|
||||
- Rust 结构体:`BarkBattleDraftConfigRow`
|
||||
@@ -328,15 +332,15 @@ npm run check:server-rs-ddd
|
||||
|
||||
- Rust 结构体:`CreationEntryConfig`
|
||||
- 源码:`server-rs/crates/spacetime-module/src/runtime/creation_entry_config.rs`
|
||||
- 字段:`config_id`、`start_title`、`start_description`、`start_idle_badge`、`start_busy_badge`、`modal_title`、`modal_description`、`updated_at`、`event_title`、`event_description`、`event_cover_image_src`、`event_prize_pool_mud_points`、`event_starts_at_text`、`event_ends_at_text`。
|
||||
- 迁移兼容:旧迁移包缺少活动横幅字段时,由 `migration.rs` 写入 `None` / `58000` 默认值;运行态读取层再按 `module-runtime` 默认横幅归一,不覆盖后台已保存配置。
|
||||
- 字段:`config_id`、`start_title`、`start_description`、`start_idle_badge`、`start_busy_badge`、`modal_title`、`modal_description`、`updated_at`、`event_title`、`event_description`、`event_cover_image_src`、`event_prize_pool_mud_points`、`event_starts_at_text`、`event_ends_at_text`、`event_banners_json`。
|
||||
- 迁移兼容:旧迁移包缺少活动横幅字段时,由 `migration.rs` 写入 `None` / `58000` 默认值;旧库缺少 `event_banners_json` 时写入 `None`,运行态读取层再按 `module-runtime` 默认公告数组归一,不覆盖后台已保存配置。HTTP 响应同时返回 `eventBanners` 数组和旧 `eventBanner` 单条兼容字段,前端优先消费数组;后台新配置主格式为 HTML 公告字符串数组或 `{title, htmlCode}` 对象数组,旧结构化 banner 字段仅保留兼容。
|
||||
|
||||
### `creation_entry_type_config`
|
||||
|
||||
- Rust 结构体:`CreationEntryTypeConfig`
|
||||
- 源码:`server-rs/crates/spacetime-module/src/runtime/creation_entry_config.rs`
|
||||
- 字段:`id`、`title`、`subtitle`、`badge`、`image_src`、`visible`、`open`、`sort_order`、`updated_at`、`category_id`、`category_label`、`category_sort_order`。
|
||||
- 迁移兼容:旧迁移包缺少入口分类字段时,由 `migration.rs` 写入 `None` / `0` 默认值;入口分组展示由 `module-runtime` 和前端展示派生消费。
|
||||
- 字段:`id`、`title`、`subtitle`、`badge`、`image_src`、`visible`、`open`、`sort_order`、`updated_at`、`category_id`、`category_label`、`category_sort_order`、`unified_creation_spec_json`。
|
||||
- 迁移兼容:旧迁移包缺少入口分类字段或统一创作契约字段时,由 `migration.rs` 写入 `None` / `0` / `None` 默认值;入口分组展示由 `module-runtime` 和前端展示派生消费,统一创作契约由 `module-runtime` 解析为 `creationTypes[].unifiedCreationSpec`,为空时只回退首批 `puzzle`、`match3d`、`wooden-fish` 默认 spec。
|
||||
|
||||
### `custom_world_agent_message`
|
||||
|
||||
@@ -712,7 +716,7 @@ npm run check:server-rs-ddd
|
||||
跨玩法公开作品列表 / 详情主读模型是 `public_work_gallery_entry` 与 `public_work_detail_entry`。拼图、自定义世界等旧玩法公开列表 HTTP 路由保留原响应 shape,由 BFF mapper 从统一 public cache 映射回当前 DTO;旧 `*_gallery_card_view` / `*_gallery_view` / `custom_world_gallery_entry` 继续作为 source view 和兼容缓存。各玩法的个人作品列表、详情、发布、点赞、游玩记录、Remix 和其它需要鉴权或写入副作用的路径继续走 procedure / reducer;不要为了公开列表性能把这些 owner-specific 或 mutation 语义混进 public view。
|
||||
|
||||
`GET /api/creation-entry/config` 和入口熔断优先从订阅 cache 读取创作入口配置;cache 缺失时使用最近一次成功读取的内存快照,再兜底调用 `get_creation_entry_config` procedure 完成空库种子或旧库兼容。
|
||||
入口配置快照包含 start card、类型弹窗、活动横幅和入口类型列表;入口类型列表新增 `category_id`、`category_label`、`category_sort_order` 后,后台 upsert、`shared-contracts`、`module-runtime` 和 `spacetime-client` binding 必须同步,旧迁移 JSON 通过 `migration.rs` 默认值兼容。
|
||||
入口配置快照包含 start card、类型弹窗、公告位兼容字段和入口类型列表;入口类型列表新增 `category_id`、`category_label`、`category_sort_order` 后,后台 upsert、`shared-contracts`、`module-runtime` 和 `spacetime-client` binding 必须同步,旧迁移 JSON 通过 `migration.rs` 默认值兼容。
|
||||
|
||||
RPG 创作入口的配置 ID 是 `rpg`,当前 `visible=true`、`open=true`;历史 `custom-world` 路由仍是 RPG 的工程域与运行态源类型。入口熔断把 `/api/runtime/custom-world*`、`/api/story/*` 和 `/api/runtime/chat/*` 统一映射到 `rpg`,不要新增平行 `airp` 路由或用 `airp` 接管当前文字冒险链路。
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ npm run dev
|
||||
- 主站 Vite。
|
||||
- 后台 Vite。
|
||||
|
||||
`npm run dev` 和单模块 `npm run dev:web`、`npm run dev:api-server`、`npm run dev:spacetime`、`npm run dev:admin-web` 启动后都会更新根目录 `.app/dev-stack.json`。该文件记录本次命令、数据库、更新时间,以及 `spacetime`、`api-server`、`web`、`admin-web` 的 `pid`、监听 host / port、可访问 URL、启动状态和当前命令。`.app/` 是本地运行态目录,不提交 Git;端口漂移、服务重启或子进程退出后以该文件里的实际状态为准。
|
||||
|
||||
单独启动主站前端:
|
||||
|
||||
```bash
|
||||
@@ -43,12 +45,16 @@ npm run dev:web
|
||||
npm run dev:api-server
|
||||
```
|
||||
|
||||
Linux 本机多用户并发开发时,`npm run dev` 和 `npm run dev:*` 单模块命令会先在系统级端口段注册表里给当前用户分配一个端口段,再把该段映射为 `web = start`、`api = start + 1`、`spacetime = start + 2`、`admin-web = start + 3`。默认注册表目录是 `/var/tmp/genarrative-dev-port-ranges/`,其中 `registry.json` 记录各用户的活跃段,`registry.lock` 负责串行化分配;可以用 `GENARRATIVE_DEV_PORT_RANGE_REGISTRY_DIR` 覆盖目录。系统自动分配时从 `10000-10099` 开始,每次占用 100 个端口块,后续块按 `10100-10199`、`10200-10299` 递增;`GENARRATIVE_DEV_PORT_RANGE` 或 `--port-range` 只在 Linux 上生效,Windows 仍按原来的 3000 / 8082 / 3101 / 3102 端口探测与漂移逻辑运行,不读这个系统级注册表。
|
||||
|
||||
后端日志默认写入 `logs/api-server/`。后端 API smoke 使用 `npm run dev:api-server` 并检查 `/healthz`;不要使用旧 `api-server:maincloud` 或任何 `GENARRATIVE_SPACETIME_MAINCLOUD_*` 口径。
|
||||
|
||||
开发态 `npm run dev` 与 `npm run dev:api-server` 会默认注入 `GENARRATIVE_DEV_PASSWORD_ENTRY_AUTO_REGISTER_ENABLED=true`,因此密码登录在本地开发环境可直接注册未知手机号账号;生产环境仍按 `api-server` 配置默认关闭该开关。
|
||||
|
||||
本地只做账号/UI smoke 且需要短信登录时,`SMS_AUTH_PROVIDER` 应显式设为 `mock`,并把 `SMS_AUTH_MOCK_VERIFY_CODE` 设为固定值(当前常用 `123456`),再重启 `npm run dev` 或 `npm run dev:api-server`。如果 `.env.local` 还保留 `SMS_AUTH_PROVIDER=aliyun`,`POST /api/auth/phone/login` 用 mock 验证码会稳定报“验证码错误”,不是前端表单问题。真实短信联调再切回 `aliyun` 并重启。
|
||||
|
||||
微信小程序虚拟支付使用 `WECHAT_MINI_PROGRAM_VIRTUAL_PAYMENT_OFFER_ID`、`WECHAT_MINI_PROGRAM_VIRTUAL_PAYMENT_APP_KEY`、`WECHAT_MINI_PROGRAM_VIRTUAL_PAYMENT_SANDBOX_APP_KEY` 和 `WECHAT_MINI_PROGRAM_VIRTUAL_PAYMENT_ENV` 配置。小程序充值统一走 `wechat_mp_virtual` / `wx.requestVirtualPayment`:泥点属于代币(`coin`),`buyQuantity` 按当前充值商品快照里的 `points_amount` 传;会员和后台新增道具类商品走 `short_series_goods`,`productId` 对应微信后台道具 ID。旧登录快照若缺 `session_key`,需要用户在小程序内重新登录后再支付;客户端成功回调不是最终到账,仍以后端通知或查询确认订单为准。详细口径见 `docs/【技术方案】微信虚拟支付接入-2026-05-26.md`。
|
||||
|
||||
如果本地 `GET /api/creation-entry/config` 返回 `No such procedure`,或 `api-server` 日志出现 `no such table: puzzle_gallery_card_view` / `no such table: wooden_fish_gallery_card_view` 这类公开 view 缺失,通常是 `.env.local` 指向的 SpacetimeDB 库还没有发布当前 `spacetime-module`,或当前 CLI 身份无权发布该库。debug 构建的 `api-server` 会临时使用后端默认入口配置兜底,避免创作作品架整块消失;正式修复仍应切换到拥有目标库权限的 SpacetimeDB 身份后重新运行 `npm run dev` 完成发布,或用 gitignored 的 `spacetime.local.json` 指向可发布的本地库。
|
||||
|
||||
本地排查 schema 漂移时,先用当前 dev server 显式查询目标库,例如:
|
||||
@@ -61,9 +67,9 @@ spacetime sql <database> "SELECT * FROM puzzle_gallery_card_view LIMIT 1" --serv
|
||||
|
||||
本地 `npm run dev:spacetime` 发布模块时必须显式忽略仓库根目录的 `spacetime.json`,由脚本固定追加 `--no-config` 并使用命令参数里传入的数据库名和 `--server http://127.0.0.1:3101`。否则 CLI 可能把发布目标改写到配置文件里的其他数据库,导致 `dev:spacetime` 启动后又因发布失败自动退出,浏览器随后会在 `ws://127.0.0.1:3101/v1/database/.../subscribe` 看到连接拒绝。
|
||||
|
||||
本地 `spacetime` CLI / standalone 版本必须和 `server-rs/Cargo.toml` 里锁定的 `spacetimedb` 版本一致。若版本错配,procedure 返回值可能在宿主侧触发 `Failed to BSATN deserialize procedure return value`,api-server 最终表现为敲木鱼等创作动作的 `SpacetimeDB procedure 调用超时`。排障时先运行 `spacetime --version`,再对照 `server-rs/Cargo.toml` 的 `spacetimedb = "..."`;需要切版本时执行 `spacetime version install <version> && spacetime version use <version>`,然后重新启动 `npm run dev:spacetime`。当前 `scripts/dev.mjs` 会在启动和复用本地 SpacetimeDB 前写入并校验 `dev-spacetime-tool-version`,避免把旧 standalone 继续带进新一轮创作。
|
||||
本地 `spacetime` CLI / standalone 版本必须和 `server-rs/Cargo.toml` 里锁定的 `spacetimedb` 版本一致;当前统一版本为 `2.3.0`。若版本错配,procedure 返回值可能在宿主侧触发 `Failed to BSATN deserialize procedure return value`,api-server 最终表现为敲木鱼等创作动作的 `SpacetimeDB procedure 调用超时`。排障时先运行 `spacetime --version`,再对照 `server-rs/Cargo.toml` 的 `spacetimedb = "..."`;需要切版本时执行 `spacetime version install <version> && spacetime version use <version>`,然后重新启动 `npm run dev:spacetime`。当前 `scripts/dev.mjs` 会在启动和复用本地 SpacetimeDB 前写入并校验 `dev-spacetime-tool-version`,避免把旧 standalone 继续带进新一轮创作。
|
||||
|
||||
本地 `.env`、`.env.local` 或 `.env.secrets.local` 修改后必须重启 `api-server` 才会生效;若已经通过 `npm run dev` 启动完整联调,可在该终端输入 `rs api-server`。排查 RPG / 拼图 / 抓大鹅等 VectorEngine 生图链路时,确认 `VECTOR_ENGINE_BASE_URL`、`VECTOR_ENGINE_API_KEY` 和 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS` 只在本地或服务器密钥文件中配置,不能写入 Git。VectorEngine `gpt-image-2` 图片协议、URL / base64 响应解析、远端图片下载和 provider 侧结构化日志在 `server-rs/crates/platform-image`;`api-server` 只做配置、玩法编排、OSS / asset 持久化、计费和失败审计落库。开局 CG 故事板、首图、背景和图集都属于长耗时图片请求;后端默认会把 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS` 下限收口到 `1000000`,旧进程仍可能沿用重启前的短超时。若开局 CG 故事板在 `send()` 阶段失败且日志显示 `SendRequest`,先看同一 request_id 的 `request_body_bytes`、`reference_data_url_bytes`、`sourceChain` 和 `rootSource`;当前开局 CG 会把角色图与首幕背景图压到单边 768 的 JPEG 后再作为 generations `image` 数组发送,`/v1/images/generations` 使用默认 HTTP 协商,只有 multipart `/v1/images/edits` 单独强制 HTTP/1.1。
|
||||
本地 `.env`、`.env.local` 或 `.env.secrets.local` 修改后必须重启 `api-server` 才会生效;若已经通过 `npm run dev` 启动完整联调,可在该终端输入 `rs api-server`。排查 RPG / 拼图 / 抓大鹅等 VectorEngine 生图链路时,确认 `VECTOR_ENGINE_BASE_URL`、`VECTOR_ENGINE_API_KEY` 和 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS` 只在本地或服务器密钥文件中配置,不能写入 Git。VectorEngine `gpt-image-2` 图片协议、URL / base64 响应解析、远端图片下载和 provider 侧结构化日志在 `server-rs/crates/platform-image`;`api-server` 只做配置、玩法编排、OSS / asset 持久化、计费和失败审计落库。开局 CG 故事板、首图、背景和图集都属于长耗时图片请求;后端默认会把 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS` 下限收口到 `1000000`,旧进程仍可能沿用重启前的短超时。若 VectorEngine 在 `send()` 阶段失败且日志显示 `SendRequest`,先看同一 `request_id` 的 provider 日志字段 `source`、`source_chain`、`source_chain_depth`,再查 `external_api_call_failure.metadata_json.errorSource`;当前 multipart `/v1/images/edits` 单独强制 HTTP/1.1。拼图关卡资产按 `level_scene -> ui_spritesheet -> level_background` 顺序生成,日志会带 `slot`、`asset_kind` 和 `elapsed_ms`。
|
||||
|
||||
查看本地 Rust / SpacetimeDB 日志:
|
||||
|
||||
@@ -92,6 +98,8 @@ npm run build
|
||||
npm run check:content
|
||||
```
|
||||
|
||||
一期创作流程统一化新增 `quality-gates/` 提交前门禁。涉及拼图、抓大鹅、敲木鱼统一创作页、统一生成页或 dev 栈启动脚本时,先执行 `quality-gates/README.md` 列出的脚本,再按对应门禁文档完成体验检查。
|
||||
|
||||
综合检查:
|
||||
|
||||
```bash
|
||||
@@ -232,14 +240,18 @@ Jenkins 按 web / api / Spacetime module / build / deploy / publish 拆分
|
||||
|
||||
`Genarrative-Web-Build` 的主站构建失败若出现 Rollup 报错 `"xxx" is not exported by "src/services/publicWorkCode.ts"`,优先按前端公开作品号工具缺失处理,而不是排查 Jenkins 节点环境。修复时要让 `publicWorkCode.ts` 的 `build<Play>PublicWorkCode` 与 `isSame<Play>PublicWorkCode` 成对导出,并补 `src/services/publicWorkCode.test.ts` 覆盖对应玩法前缀;随后用 `npm run build:production-release -- --component web --name <临时名>` 复现 Jenkins web 构建路径。
|
||||
|
||||
生产 Jenkins 的 `Pipeline script from SCM` 由 Windows controller 读取 Jenkinsfile,SCM URL 继续使用 `https://git.genarrative.world/GenarrativeAI/Genarrative.git`。运行在 `linux && genarrative-build` 构建机上的 `Genarrative-Full-Build-And-Deploy` 源码解析阶段和 `Genarrative-Web-Build` checkout 阶段,优先使用 `http://127.0.0.1:3000/GenarrativeAI/Genarrative.git`,失败后回退到 `https://git.genarrative.world/GenarrativeAI/Genarrative.git`;两层 checkout 都必须保留单分支 refspec、`shallow=true`、`depth=1`、`noTags=true` 与 `honorRefspec=true`,后续二次源码确认继续走 `scripts/jenkins-checkout-source.sh`。
|
||||
`Genarrative-Web-Build` 会把 `build/<version>/web.tar.gz`、`web.tar.gz.sha256` 和 `release-manifest.json` 直接归档为 Jenkins 构建产物;`Genarrative-Web-Deploy` 只通过 `copyArtifacts` 从指定上游构建复制这些产物,再执行 `scripts/deploy/production-web-deploy.sh`。Web 发布不再读取构建机本地缓存目录,也不再通过 release agent `rsync` 回构建机拉取大包;如果 deploy 找不到 `web.tar.gz`,应先检查上游 Web Build 是否按同一 `BUILD_VERSION` 成功归档产物。
|
||||
|
||||
`Genarrative-Web-Build` 打包 `web.tar.gz` 前、`Genarrative-Web-Deploy` 解包后都会把 Web 静态目录规范为目录 `755`、文件 `644`。如果前端页面能打开但 public 图片、字体或音频返回 `403 Forbidden`,优先检查当前 `/srv/genarrative/web` 指向的 release 中对应文件权限是否被异常归档为 `600`,临时恢复可对该 release 的 `web` 目录执行目录 `755`、文件 `644` 的权限修正。
|
||||
|
||||
生产 Jenkins 的 `Pipeline script from SCM` 仍由 Jenkins controller 读取 Jenkinsfile,SCM URL 继续使用 `https://git.genarrative.world/GenarrativeAI/Genarrative.git`。现在所有生产流水线 job 的首次 checkout 都先走 `http://127.0.0.1:3000/GenarrativeAI/Genarrative.git`,失败后回退到 `https://git.genarrative.world/GenarrativeAI/Genarrative.git`;两层 checkout 都必须保留单分支 refspec、`shallow=true`、`depth=1`、`noTags=true` 与 `honorRefspec=true`,后续二次源码确认继续走 `scripts/jenkins-checkout-source.sh`。
|
||||
|
||||
|
||||
`Genarrative-Stdb-Module-Publish` 在 `Pipeline script from SCM` 阶段如果一开始就报 `No such DSL method 'pipeline'`,优先检查 `jenkins/Jenkinsfile.production-stdb-module-publish` 是否带 UTF-8 BOM。Jenkins Declarative Pipeline 的首个 token 必须是纯 `pipeline`;仓库中的 Jenkinsfile 应保存为 UTF-8 without BOM,只有临时写给 Windows PowerShell 5.1 `-File` 执行的 `.ps1` 才需要按对应 helper 转成带 BOM。验证时可检查文件前三字节不再是 `EF BB BF`,并运行 `validateDeclarativePipeline` 或重放该流水线。
|
||||
|
||||
`Genarrative-Stdb-Module-Build` 或 SpacetimeDB module 构建失败若出现 Rust `E0425 cannot find function migrate_*`,优先排查 `server-rs/crates/spacetime-module/src/runtime/creation_entry_config.rs` 等同文件内默认种子迁移 helper 是否在分支合并时只保留了调用、漏掉了函数定义。修复时不要直接删除迁移调用;应恢复只纠偏历史默认种子且不覆盖后台手动配置的 helper,并用 `cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml` 复现 Jenkins module 编译路径。
|
||||
`Genarrative-Stdb-Module-Build` 或 SpacetimeDB module 构建失败若出现 Rust `E0425 cannot find function migrate_*`,优先排查 `server-rs/crates/spacetime-module/src/runtime/creation_entry_config.rs` 等同文件内默认种子迁移 helper 是否在分支合并时只保留了调用、漏掉了函数定义。`Genarrative-Stdb-Module-Build` 现在运行在 `linux && genarrative-build` 节点上,Checkout 与 Build 都走 bash + cargo + sccache,不再依赖 Windows PowerShell 或 Git Bash。修复时不要直接删除迁移调用;应恢复只纠偏历史默认种子且不覆盖后台手动配置的 helper,并用 `cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml` 复现 Jenkins module 编译路径。
|
||||
|
||||
Windows Stdb module 构建流水线运行在 Jenkins `windows` 节点上。该流水线需要执行 PowerShell 逻辑时,统一通过 `bat` 显式调用 `%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe`,不要直接使用 Jenkins `powershell` step;本地 Jenkins durable-task 曾在 `Genarrative-Stdb-Module-Build` workspace 中启动裸 `powershell` 时触发 `CreateProcess error=5, 拒绝访问`。临时 `.ps1` 由 Jenkins `writeFile` 写出后要先转成 UTF-8 with BOM 再交给 Windows PowerShell 5.1 `-File` 解析,避免中文错误消息在无 BOM UTF-8 下被当成本地 ANSI 误解码。Checkout 阶段要优先复用 Jenkins GitSCM 已经完成的结果:`COMMIT_HASH` 为空或与当前 `HEAD` 一致时,不要再额外 `git clean` / `git checkout`,只在确实需要切到别的指定 commit 时才补 fetch、校验和切换。排查时先看对应 build log、`@tmp/durable-*` 下的 `powershellWrapper.ps1`,以及日志中的 `[jenkins-powershell] user/exe`。
|
||||
`Genarrative-Server-Provision` 现在也运行在 `linux && genarrative-build` / `linux && genarrative-release-deploy` 节点上,`Prepare Provision Tools` 会在 Linux build 节点直接准备 SpacetimeDB 与 `otelcol-contrib` 交付件,再 stash 给后续发布阶段;旧 Windows 下载 helper 已退役。`Genarrative-Stdb-Module-Build`、`Genarrative-Server-Provision` 和 `Genarrative-Notify-Email` 都不再需要单独的 Windows 节点口径。
|
||||
|
||||
生产环境变量模板:`deploy/env/api-server.env.example`。真实密钥只放服务器,不提交 Git,不写入文档示例。
|
||||
|
||||
@@ -250,9 +262,8 @@ Windows Stdb module 构建流水线运行在 Jenkins `windows` 节点上。该
|
||||
- `api-server` 生产模板默认 `GENARRATIVE_API_LISTEN_BACKLOG=1024`、`GENARRATIVE_API_WORKER_THREADS=4`;本地未设置 worker threads 时继续使用 Tokio 默认值。
|
||||
- `GENARRATIVE_API_MAX_CONCURRENT_REQUESTS=512` 开启应用内 HTTP 并发背压;`GENARRATIVE_API_GALLERY_MAX_CONCURRENT_REQUESTS=320`、`GENARRATIVE_API_DETAIL_MAX_CONCURRENT_REQUESTS=64`、`GENARRATIVE_API_ADMIN_MAX_CONCURRENT_REQUESTS=16` 分别限制公开列表、公开详情和后台 API 热路径。超过许可时直接返回 `429 Too Many Requests` 和 `Retry-After: 1`,`/healthz` 不受该限制。这些值不是 RPS 限速;如果压测中 429 上升但内存和 p95 收敛,说明背压正在保护进程。直连 `api-server` 的极高 RPS 压测若出现 `connection refused`,通常已经打到 TCP 监听 / accept 层,应同时检查 backlog、Nginx upstream keepalive 和前置限流。
|
||||
- `genarrative-api.service` 设置 `LimitNOFILE=65535`、`TasksMax=2048`;上线后用 `systemctl show genarrative-api.service -p LimitNOFILE -p TasksMax` 和 `cat /proc/$(pidof api-server)/limits` 核对。
|
||||
- Server provision 不在目标机联网下载 SpacetimeDB 或 `otelcol-contrib`。`Genarrative-Server-Provision` 先在 Windows Jenkins 节点执行 `Download Provision Tool Archives`,把 `spacetime-x86_64-unknown-linux-gnu.tar.gz` 和 `otelcol-contrib_0.151.0_linux_amd64.tar.gz` 先下载到工作区,再通过 `stash/unstash` 带到 `genarrative-build-01`;Windows 下载前会先查 GitHub release asset 的 `digest` 字段做 SHA256 校验,已有本地文件且 digest 一致就直接复用,不再重复下载。目标 Linux 节点上的 `scripts/prepare-server-provision-tools.sh` 只消费这些本地下载件生成 `provision-tools/`,再交给 `scripts/jenkins-server-provision.sh` 安装 `/stdb/spacetime`、`/stdb/bin/current/*` 和 `/usr/local/bin/otelcol-contrib`。Windows 侧的 `runWindowsPowerShell(...)` 现在会先 `writeFile` 生成 UTF-8 `.ps1`,再直接把脚本文本读入内存并通过 `ScriptBlock::Create(...)` 执行,避免对同一个 workspace 脚本做原地 BOM 重写。排查时除了看下载日志,还要看 `[jenkins-powershell] workspace:`、`[jenkins-powershell] script:` 和 `[jenkins-powershell] loaded bytes:`。注意 `scripts/jenkins-checkout-source.sh` 会执行 `git reset --hard` / `git clean`,因此被直接执行的新增脚本必须以 Git `100755` 模式提交,或在二次 checkout 之后再补 `chmod +x`。
|
||||
- Windows 下载阶段如果出现 `curl: (18)` 或响应体截断,流水线会保留同名 `.download` 临时文件并用 `curl -C -` 断点续传;只有完整返回但 SHA256 digest 仍不匹配时才删除临时文件后重新下载。目标 Linux 节点仍只接收 `stash/unstash` 带过去的本地下载件,不回退外网下载。
|
||||
- Windows 下载阶段如果走代理,在 `Genarrative-Server-Provision` 参数 `PROVISION_DOWNLOAD_PROXY` 填写 Windows Jenkins 节点可访问的 HTTP 代理,例如 `http://127.0.0.1:7890`;不要填写目标 release 机器视角的 `127.0.0.1`,除非代理确实运行在该 Windows 节点本机。Linux 目标机阶段会强制要求使用本地下载件,缺少文件直接失败,不再回退到外网下载。
|
||||
- Server provision 不再通过 Windows helper 下载。`Genarrative-Server-Provision` 的 `Prepare Provision Tools` 在 Linux build 节点直接准备 `spacetime-x86_64-unknown-linux-gnu.tar.gz` 和 `otelcol-contrib_0.151.0_linux_amd64.tar.gz`,再 stash `provision-tools/` 给后续发布阶段;如果 build 节点需要代理,在 `PROVISION_DOWNLOAD_PROXY` 配置 Linux 侧可访问的 HTTP 代理。后续 Linux 目标节点只消费 `provision-tools/`,不再回退到外网下载。
|
||||
- `Genarrative-Stdb-Module-Build`、`Genarrative-Web-Build`、`Genarrative-Api-Build`、`Genarrative-*Deploy`、`Genarrative-Database-Import/Export`、`Genarrative-Full-Build-And-Deploy` 和 `Genarrative-Notify-Email` 的生产流水线现都以 Linux agent 为主,统一走 `http://127.0.0.1:3000/GenarrativeAI/Genarrative.git` 优先、`https://git.genarrative.world/GenarrativeAI/Genarrative.git` 备用的 checkout 口径。
|
||||
- `otelcol-contrib.service` 作为可选系统服务加入 provision,默认监听 `127.0.0.1:4317/4318` 并使用 `deploy/otelcol/genarrative-debug.yaml`。api-server 是否发送 OTLP 仍由 `GENARRATIVE_OTEL_ENABLED` 控制,服务 unit 见 `deploy/systemd/otelcol-contrib.service`。
|
||||
- Nginx `/api/` 与 `/admin/api/` 通过 `genarrative_api` upstream 代理到 `127.0.0.1:8082`,upstream keepalive 为 64;`limit_conn` 负责连接 / 并发保护,`limit_req` 负责入口 RPS 快拒绝。当前模板把公开 gallery list 单独放到 `genarrative_gallery_rps`,默认 `rate=5000r/s`、`burst=4096`、`limit_conn=320`;公开详情和普通 API 放到 `genarrative_api_rps`,后台 API 放到 `genarrative_admin_rps`。通用 `/api` location 设置 `client_max_body_size 64m` 是反代兜底,防止拼图入口页 / 新增关卡本地参考图 Data URL 或旧兼容请求在到达 `api-server` 前被默认 1 MiB 上限拦截;拼图本地参考图前后端统一限制 6MB,历史图片仍提交 `referenceImageAssetObjectId(s)`。若线上出现 `413 Request Entity Too Large` 且 access log 中 `request_time=0.000`、`upstream_status=-`,说明请求在 Nginx 层被拦截,先用 `nginx -T | grep client_max_body_size` 检查 release 模板是否已渲染并 reload,同时检查前端是否超出 6MB 或错误提交了未压缩大图。`limit_conn_status 429` 和 `limit_req_status 429` 必须在 HTTP 与 HTTPS server 中同时生效;若线上压测看到 `limiting connections by zone "genarrative_api_conn"` 却返回 503,优先检查 `nginx -T` 里 HTTPS server 是否缺少这些状态码,以及 `/api/runtime/puzzle/gallery` 是否误落到通用 `location ~ ^/api` 的 `limit_conn=64`。压测时看 `/var/log/nginx/genarrative.access.log` 中的 `request_time`、`upstream_connect_time`、`upstream_header_time`、`upstream_response_time`、`upstream_status`、`request_id`。
|
||||
- 作品列表 K6 脚本一次 iteration 默认请求两个公开接口,因此约 50 HTTP req/s 的目标命令使用 `SCENARIO=spike START_RPS=5 PEAK_RPS=25 HOLD=60s END_RPS=5 DETAIL_RATIO=0 npm run loadtest:k6:works`。
|
||||
@@ -270,7 +281,7 @@ npm run container:k6
|
||||
npm run container:down
|
||||
```
|
||||
|
||||
容器方案默认暴露 `http://127.0.0.1:18080`,`api-server` 在容器内监听 `0.0.0.0:8082`,Nginx 通过 `api-server:8082` upstream 反代 `/api/` 和 `/admin/api/`。SpacetimeDB 也纳入 compose,容器内由 `spacetimedb:3101` 提供服务,宿主机通过 `http://127.0.0.1:13101` 进行模块发布;Collector 镜像使用 `otel/opentelemetry-collector-contrib:0.151.0`。生产 provision 侧则通过 Windows Jenkins 下载件在目标 Linux 节点生成 `provision-tools/otelcol-contrib`,再安装本机 `otelcol-contrib.service`,真实库名、token 和外部服务密钥只写本地 `deploy/container/api-server.env`,不提交 Git。完整拓扑、端口、k6 参数和 OTLP debug exporter 使用方法见 `deploy/container/README.md`。
|
||||
容器方案默认暴露 `http://127.0.0.1:18080`,`api-server` 在容器内监听 `0.0.0.0:8082`,Nginx 通过 `api-server:8082` upstream 反代 `/api/` 和 `/admin/api/`。SpacetimeDB 也纳入 compose,容器内由 `spacetimedb:3101` 提供服务,宿主机通过 `http://127.0.0.1:13101` 进行模块发布;Collector 镜像使用 `otel/opentelemetry-collector-contrib:0.151.0`。生产 provision 侧现在由 Linux build 节点直接准备 `provision-tools/otelcol-contrib`,再交给后续 Linux 发布阶段安装本机 `otelcol-contrib.service`,真实库名、token 和外部服务密钥只写本地 `deploy/container/api-server.env`,不提交 Git。完整拓扑、端口、k6 参数和 OTLP debug exporter 使用方法见 `deploy/container/README.md`。
|
||||
`npm run container:config` 默认只做 quiet 校验,避免把本地 env 中的 token 展开到终端;确需排查完整 compose 时再传 `-- --print`。
|
||||
|
||||
OpenTelemetry 现阶段默认开启 OTLP traces / metrics / logs,但本地日志与 Nginx 文件日志仍保留:
|
||||
@@ -283,7 +294,7 @@ OpenTelemetry 现阶段默认开启 OTLP traces / metrics / logs,但本地日
|
||||
- debug exporter / Rider 转发都会同时接收 traces、metrics 和 logs。
|
||||
- api-server 会随 metrics 发送进程级指标:`process.memory.usage`、`process.memory.virtual`、`process.cpu.time`、`genarrative.process.cpu.usage_percent`、`process.thread.count`、`genarrative.process.memory.private`;Windows 额外发送 `process.windows.handle.count`,Linux 额外发送 `process.unix.file_descriptor.count`。这些指标只描述当前进程,不携带请求、用户或作品 label。
|
||||
- HTTP 运行态补充发送 `genarrative.http.server.response_bodies.in_flight` 与 `genarrative.http.server.request_permits.available`,后者带低基数 `pool=default|gallery|detail|admin` label,用于区分业务 handler / 背压 permit 是否仍被占用;拼图广场热点缓存补充发送 `genarrative.puzzle_gallery.cache.*` 指标,记录 fresh hit、stale hit、未命中、后台刷新开始 / 失败、重建耗时和预序列化 data JSON 字节数。
|
||||
- 外部 API 失败统一发送 OTLP 并落库。当前 VectorEngine `gpt-image-2` 图片生成 / 编辑失败由 `platform-image` provider 输出低基数字段结构化日志,字段包括 provider、endpoint、failure_stage、status、status_class、timeout、retryable、latency_ms、prompt_chars、reference_image_count、image_model 和 raw_excerpt;`api-server` 再记录指标 `genarrative.external_api.failures{provider,failure_stage,status_class,retryable}`,并写入 `tracking_event`,`event_key = external_api_call_failure`、`module_key = external-api`、`scope_kind = module`、`scope_id = provider`。调用方能拿到身份上下文时,失败事件还会在行级 `user_id` / `owner_user_id` / `profile_id` 和 `metadata_json.userId` / `metadata_json.profileId` 中记录触发者与草稿 / 作品作用域。排障时先按 provider / failureStage 聚合,再下钻 userId / profileId,最后结合 request 日志和上游响应 excerpt 判断是限流、超时、解析失败还是未返回图片。
|
||||
- 外部 API 失败统一发送 OTLP 并落库。当前 VectorEngine `gpt-image-2` 图片生成 / 编辑失败由 `platform-image` provider 输出低基数字段结构化日志,字段包括 provider、endpoint、failure_stage、status、source、source_chain、source_chain_depth、timeout、retryable、latency_ms、prompt_chars、reference_image_count、image_model 和 raw_excerpt;`api-server` 再记录指标 `genarrative.external_api.failures{provider,failure_stage,status_class,retryable}`,并写入 `tracking_event`,`event_key = external_api_call_failure`、`module_key = external-api`、`scope_kind = module`、`scope_id = provider`。调用方能拿到身份上下文时,失败事件还会在行级 `user_id` / `owner_user_id` / `profile_id` 和 `metadata_json.userId` / `metadata_json.profileId` / `metadata_json.requestId` / `metadata_json.errorSource` 中记录触发者、草稿 / 作品作用域、请求标识和传输错误链。排障时先按 provider / failureStage 聚合,再下钻 userId / profileId,最后结合 request 日志、errorSource 和上游响应 excerpt 判断是限流、超时、解析失败还是未返回图片。
|
||||
- SpacetimeDB 观测分为两类:procedure / reducer 调用继续用 `genarrative.spacetime.procedure.*`,订阅本地 cache 读使用 `genarrative.spacetime.read.*`。`read=list_puzzle_gallery` 表示拼图广场当前从 `puzzle_gallery_card_view` 本地 cache 读取,不再每个 HTTP 请求调用 `list_puzzle_gallery` procedure。
|
||||
- 本地 Windows 直连压测的内存高水位要结合 K6 VU / 连接数解释。250 RPS 下过高 `PREALLOCATED_VUS` 可能让 300 个本地 Established 连接把 `api-server` private memory 瞬时推到 GB 级,且 `/healthz` 小响应也能复现;若压测结束后回落、`response_bodies.in_flight` 和背压 permit 未显示业务积压,应优先按连接 / 发送链路高水位处理,而不是判断为 SpacetimeDB 或 JSON 缓存泄漏。
|
||||
- Rider 的 Logs 面板只展示 log event 自身字段,不会自动展开父 span 的全部 attributes;请求完成日志会直接带 `request_id`、`http.request.method`、`http.route`、`url.scheme`、`url.path`、`http.response.status_code`、`status_class`、`latency_ms` 和 `slow_request`,完整链路继续到 Traces 面板按 trace/span 查看。
|
||||
@@ -342,7 +353,7 @@ cargo test -p platform-auth --manifest-path server-rs/Cargo.toml aliyun_send_sms
|
||||
|
||||
个人任务首版 scope 仅支持 `user`。后台、RPG、大鱼吃小鱼、Visual Novel、Story、Combat 等特定链路按 tracking 中间件排除规则处理;作品游玩统一使用 `work_play_start`。
|
||||
|
||||
外部 API 失败审计复用 `tracking_event`,不新增表。失败事件优先写入本机 tracking outbox,再由后台 worker 批量落库;如果 outbox 因权限、磁盘或保护阈值不可写,会回退同步直写 SpacetimeDB。`metadata_json` 包含 endpoint、operation、failureStage、statusCode、statusClass、timeout、retryable、errorMessage、latencyMs、promptChars、referenceImageCount、imageModel、rawExcerpt、userId 和 profileId;其中 `userId` 是触发生成的用户,`profileId` 是调用方传入的草稿 / 作品 / 场景作用域,入口拿不到上下文时允许为空。常用查询:
|
||||
外部 API 失败审计复用 `tracking_event`,不新增表。失败事件优先写入本机 tracking outbox,再由后台 worker 批量落库;如果 outbox 因权限、磁盘或保护阈值不可写,会回退同步直写 SpacetimeDB。`metadata_json` 包含 endpoint、operation、failureStage、statusCode、statusClass、timeout、retryable、errorMessage、errorSource、latencyMs、promptChars、referenceImageCount、imageModel、rawExcerpt、userId、profileId 和 requestId;其中 `userId` 是触发生成的用户,`profileId` 是调用方传入的草稿 / 作品 / 场景作用域,`requestId` 用于回查同一次 HTTP 请求日志,入口拿不到上下文时允许为空。常用查询:
|
||||
|
||||
```sql
|
||||
SELECT event_id, scope_id AS provider, metadata_json, occurred_at
|
||||
@@ -369,7 +380,7 @@ ORDER BY failures DESC, last_seen DESC
|
||||
LIMIT 100;
|
||||
```
|
||||
|
||||
VectorEngine `request_send` 且 `timeout = true` 的记录表示 `reqwest::Error::is_timeout()` 判定为超时,常见于连接、发送请求体、等待上游首包或上游长时间无响应;`errorSource = client error (SendRequest)` 是 Hyper 发送请求阶段的错误来源标签,不等于最终根因。若 `statusCode` 为空,应优先查同一时间窗口的 `api-server` request 日志、Nginx / 出口网络、VectorEngine 可用性和请求体大小;若已有 `502`、`429 moderation_blocked` 等状态码,则按上游网关或内容审核失败单独处理,不要和传输超时混为一类。
|
||||
VectorEngine `request_send` 且 `timeout = true` 的记录表示 `reqwest::Error::is_timeout()` 判定为超时,常见于连接、发送请求体、等待上游首包或上游长时间无响应;`errorSource` 会保存 reqwest 底层错误链,若只看到 `client error (SendRequest)`,表示 Hyper 只暴露到发送请求阶段,仍不等于最终根因。若 `statusCode` 为空,应优先查同一 `requestId` 的 `api-server` request 日志、provider 日志 `source_chain`、Nginx / 出口网络、VectorEngine 可用性和请求体大小;若已有 `502`、`429 moderation_blocked` 等状态码,则按上游网关或内容审核失败单独处理,不要和传输超时混为一类。
|
||||
|
||||
tracking outbox 默认配置:
|
||||
|
||||
|
||||
72
docs/【技术方案】微信虚拟支付接入-2026-05-26.md
Normal file
72
docs/【技术方案】微信虚拟支付接入-2026-05-26.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# 微信虚拟支付接入
|
||||
|
||||
更新时间:`2026-05-26`
|
||||
|
||||
## 接入口径
|
||||
|
||||
- 泥点充值在微信小程序 WebView 内走 `wechat_mp_virtual`,由小程序页调用 `wx.requestVirtualPayment` 的 `short_series_coin` 模式。
|
||||
- 会员商品在微信小程序 WebView 内同样走 `wechat_mp_virtual`,由小程序页调用 `wx.requestVirtualPayment` 的 `short_series_goods` 模式,并在 `signData` 内带 `productId` 与 `goodsPrice`。
|
||||
- H5 与桌面微信环境仍分别走 `wechat_h5` / `wechat_native`,不进入虚拟支付链路。
|
||||
- `session_key` 只保存在后端认证仓储内,用于计算虚拟支付用户态签名,不下发给前端。
|
||||
- 客户端支付成功回调只代表已拉起支付并返回成功;最终到账仍以后端虚拟支付消息推送写入订单为准,普通微信支付订单则继续走微信支付 V3 notify / query。虚拟支付订单的确认接口只读取本地订单真相,不再用普通微信支付 V3 查单。
|
||||
- 小程序 WebView 默认进入时会静默调用 `wx.login` 刷新后端微信登录态,避免历史登录用户只有前端 JWT、后端缺少 `session_key` 时无法生成虚拟支付签名。
|
||||
|
||||
## 关键文件
|
||||
|
||||
- 前端渠道选择:`src/services/payment/paymentPlatform.ts`
|
||||
- 充值入口:`src/components/rpg-entry/RpgEntryHomeView.tsx`
|
||||
- 小程序支付承接页:`miniprogram/pages/wechat-pay/index.shared.js`
|
||||
- API 契约:`packages/shared/src/contracts/runtime.ts`、`server-rs/crates/shared-contracts/src/runtime.rs`
|
||||
- 后端下单与签名:`server-rs/crates/api-server/src/runtime_profile.rs`
|
||||
- WebView 回流确认:`GET /api/profile/recharge/orders/{orderId}/wechat/events`、`POST /api/profile/recharge/orders/{orderId}/wechat/confirm`
|
||||
- 微信登录态保存:`server-rs/crates/platform-auth/src/lib.rs`、`server-rs/crates/module-auth/src/lib.rs`
|
||||
|
||||
## 后端配置
|
||||
|
||||
生产接入虚拟支付至少需要:
|
||||
|
||||
```bash
|
||||
WECHAT_PAY_ENABLED=true
|
||||
WECHAT_PAY_PROVIDER=real
|
||||
WECHAT_MINI_PROGRAM_VIRTUAL_PAYMENT_OFFER_ID=<微信虚拟支付 offerId>
|
||||
WECHAT_MINI_PROGRAM_VIRTUAL_PAYMENT_APP_KEY=<现网 AppKey>
|
||||
WECHAT_MINI_PROGRAM_VIRTUAL_PAYMENT_SANDBOX_APP_KEY=<沙箱 AppKey,可选>
|
||||
WECHAT_MINIPROGRAM_MESSAGE_TOKEN=<微信消息推送 Token>
|
||||
WECHAT_MINIPROGRAM_MESSAGE_ENCODING_AES_KEY=<微信消息推送 EncodingAESKey>
|
||||
WECHAT_MINI_PROGRAM_VIRTUAL_PAYMENT_ENV=0
|
||||
```
|
||||
|
||||
`WECHAT_MINI_PROGRAM_VIRTUAL_PAYMENT_ENV=0` 表示现网,`1` 表示沙箱。后端会按 env 选择 AppKey,并生成:
|
||||
|
||||
- `signData`:传给 `wx.requestVirtualPayment` 的订单数据。
|
||||
- `paySig`:`HMAC-SHA256(appKey, "requestVirtualPayment&" + signData)` 的小写 hex。
|
||||
- `signature`:`HMAC-SHA256(session_key, signData)` 的小写 hex。
|
||||
- 泥点属于微信虚拟支付代币(coin),`short_series_coin` 的 `buyQuantity` 必须使用当前泥点商品的 `points_amount`;例如 60 泥点商品应传 `buyQuantity: 60`。
|
||||
- 会员直购 `signData` 额外包含 `productId` 和 `goodsPrice`;`goodsPrice` 使用后端商品配置价,和微信后台道具价格校验保持一致。
|
||||
- 微信小程序“开发者服务器接收消息推送”必须配置为安全模式,数据格式选 JSON,URL 统一指向 `/api/profile/recharge/wechat/virtual-notify`。
|
||||
- `WECHAT_MINIPROGRAM_MESSAGE_TOKEN` 和 `WECHAT_MINIPROGRAM_MESSAGE_ENCODING_AES_KEY` 由环境变量注入;GET URL 验证按官方规则用 `Token/timestamp/nonce` 校验 `signature` 并原样返回 `echostr`,POST 安全模式推送再校验 `msg_signature`、用 `EncodingAESKey` 解密 `Encrypt`,然后按虚拟支付事件入账。
|
||||
- 安全模式下,POST 推送会先解密再解析 `xpay_goods_deliver_notify` / `xpay_coin_pay_notify`;不要把 GET URL 验证里的 `echostr` 当密文解密。
|
||||
|
||||
## 验收命令
|
||||
|
||||
```bash
|
||||
npm exec vitest run miniprogram/pages/wechat-pay/index.test.js src/services/payment/paymentPlatform.test.ts src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx
|
||||
cargo check -p api-server --manifest-path server-rs/Cargo.toml
|
||||
cargo test -p shared-contracts --manifest-path server-rs/Cargo.toml create_profile_recharge_order_response_serializes_virtual_wechat_payloads
|
||||
npm run typecheck
|
||||
npm run check:encoding
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 旧微信登录快照可能没有 `session_key`;小程序 WebView 会在普通进入时静默刷新一次微信登录态,刷新失败时仍允许匿名打开 WebView,但虚拟支付会继续由后端拦截并提示重新登录。
|
||||
- 小程序充值商品全部映射到虚拟支付;泥点使用 `short_series_coin`,会员使用 `short_series_goods`。
|
||||
- `short_series_coin` 只用于代币购买,后端从本次下单返回的充值中心商品快照读取 `points_amount` 并写入 `buyQuantity`;不要把 coin 商品当成道具,也不要把 `buyQuantity` 固定为 1。
|
||||
- 后台新增的会员类充值商品会直接把商品 `productId` 作为微信 `short_series_goods` 的道具 ID;例如微信后台道具 ID 为 `item01` 时,后台会员商品 `productId` 也应配置为 `item01`,且商品价格需要与微信后台道具价格一致。
|
||||
- 小程序页必须保留普通支付与虚拟支付双分支,按 pay params 字段判断调用 `wx.requestPayment` 或 `wx.requestVirtualPayment`。
|
||||
- 小程序支付承接页回传 `wx_pay_result` 时必须携带 `requestId:status:orderId[:error]`,并同时写入上一页 hash 与本地 storage;WebView `onShow` 会立即检查一次、延迟二次检查一次,且同名 hash 参数必须替换,避免支付状态停留在处理中或重复处理。
|
||||
- 微信虚拟支付消息推送使用独立后端入口 `/api/profile/recharge/wechat/virtual-notify`,按 `xpay_goods_deliver_notify` 和 `xpay_coin_pay_notify` 推进充值订单入账;回包需按入站格式返回 `ErrCode=0` / `ErrMsg=success`(JSON 入站回 JSON,XML 入站回 XML),错误时带具体 `ErrMsg` 便于微信侧重试与排障。
|
||||
- 沙箱或基础库失败会把微信返回的 `errCode` / `errMsg` 透传到前端失败弹窗,便于区分微信后台道具、沙箱 AppKey、签名和基础库能力问题。
|
||||
- Web 侧在拉起虚拟支付后会短时轮询 `wx_pay_result`,即使小程序 `web-view` 回写 hash 没触发浏览器 `hashchange`,也必须展示回写的微信错误内容。
|
||||
- WebView 返回但没有拿到 `wx_pay_result` 时,前端必须主动调用订单确认接口,并接入 `/api/profile/recharge/orders/{orderId}/wechat/events` 的 SSE 事件流作为服务端推送兜底;后端收到虚拟支付消息推送并入账后会发布订单更新,SSE 先推当前订单快照,再在订单结束时推 `done`。
|
||||
- WebView 返回后,在订单状态拉取或 SSE 等待期间展示不可关闭遮罩“正在确认支付”,阻止用户离开或继续操作;只有确认到最终订单状态后才展示一次最终结果弹窗,不能先弹“正在支付/支付已提交”再二次弹成功。
|
||||
@@ -1,24 +1,32 @@
|
||||
# 平台入口与玩法链路
|
||||
|
||||
更新时间:`2026-05-15`
|
||||
更新时间:`2026-06-03`
|
||||
|
||||
## 平台创作入口
|
||||
|
||||
创作入口配置事实源在 SpacetimeDB,通过 `GET /api/creation-entry/config` 下发;后台通过 `/admin/api/creation-entry/config` 管理。前端只在展示层派生可见卡片和入口状态,`api-server` 路由熔断也使用同一份配置。不要恢复前端硬编码入口配置文件。
|
||||
|
||||
当前创作 Tab 只承载赛事 banner、玩法模板分类和两列模板卡;点击模板卡后直接进入对应玩法已有的入口创作表单 stage,不再经过空白占位页,也不把旧表单嵌进创作 Tab 首屏。移动端创作 Tab 顶栏在 `陶泥儿` 品牌同一行显示真实账户泥点数,数据来自 `profileDashboard.walletBalance`,不得再把活动奖池当作账号余额展示。首屏 banner 结构按参考图拆成横向可滑动赛事卡、主体宣传图文区、奖池胶囊、开始 / 结束时间条和卡片内分页点;轮播只保留 `拼图主题创作赛` 和 `抓大鹅主题创作赛`,两个主题赛事奖池均为 `1000` 泥点数。玩法列表不再套外部边框卡片,移动端需要压缩横向边距和两列间距;玩法卡统一按“上图、左上状态标签(仅非开放态显示)、封面右下 `10-20泥点数`、下方白底标题/描述”结构展示,卡片高度保持紧凑但标题、描述和预估消耗点数都必须可见。创作 Tab 根容器不再使用 `platform-page-stage` 这类全局内容卡片壳,但继续保留 `platform-remap-surface` 作为主题和输入框样式命中钩子。创作首屏字号需要对齐平台普通 UI 档位:顶栏泥点组件、banner 正文、分类 Tab 和玩法卡标题 / 副标题 / 消耗说明优先使用 `11px` 到 `14px`,不使用 `text-lg`、`text-xl` 或更大的展示级字号。草稿 Tab 继续承接作品架。RPG、RPG 之外的各玩法入口分别落到既有的 `agent-workspace`、`big-fish-agent-workspace`、`match3d-agent-workspace`、`square-hole-agent-workspace`、`jump-hop-workspace`、`wooden-fish-workspace`、`puzzle-agent-workspace`、`bark-battle-workspace`、`visual-novel-agent-workspace`、`baby-object-match-workspace`,这些入口继续承接各玩法自己的表单、草稿恢复和后续编排,不作为创作 Tab 首屏内容。
|
||||
当前点击底部加号进入的创作入口页承载后台公告位、创作入口页签和两列模板卡;页签中只有真实后端作品架摘要存在时才展示“最近创作”,其余为玩法模板分类。点击模板卡后直接进入对应玩法已有的入口创作表单 stage,不再经过空白占位页,也不把旧表单嵌进创作入口页。移动端创作入口页顶栏在 `陶泥儿` 品牌同一行显示真实账户泥点数,数据来自 `profileDashboard.walletBalance`,不得再把公告内容或活动奖池当作账号余额展示。创作入口页公告位数据优先读取 `GET /api/creation-entry/config` 的 `eventBanners` 数组,多条配置时前端自动轮播,旧 `eventBanner` 仅作为单条兼容兜底。后台公告配置面向表单:每条公告包含标题和 HTML 内容,后台保存时序列化为后端 `eventBannersJson` 传输字段,由前端空权限沙箱 iframe 展示;旧结构化 banner 字段仅保留回显兼容,不再作为后台公告配置主格式;不得执行 JSX 或把后台代码直接注入 DOM。玩法列表不再套外部边框卡片,移动端需要压缩横向边距和两列间距;玩法卡统一按“上图、左上状态标签(仅非开放态显示)、封面右下 `10-20泥点数`、下方白底标题/描述”结构展示,卡片高度保持紧凑但标题、描述和预估消耗点数都必须可见。创作入口页根容器不再使用 `platform-page-stage` 这类全局内容卡片壳,但继续保留 `platform-remap-surface` 作为主题和输入框样式命中钩子。创作入口页字号需要对齐平台普通 UI 档位:顶栏泥点组件、公告正文、分类 Tab 和玩法卡标题 / 副标题 / 消耗说明优先使用 `11px` 到 `14px`,不使用 `text-lg`、`text-xl` 或更大的展示级字号。草稿 Tab 继续承接作品架;底部加号入口页的“最近创作”只用 7 天内的真实后端作品架摘要判断是否展示,并从摘要里推导最近使用过的模板 ID,页面必须展示“仅显示最近7天内使用过的模板”提示,列表内容必须复用其它页签里的模板卡样式、文案和点击行为,不展示具体作品名称、摘要或生成状态,也不新增独立最近创作卡组件。RPG、RPG 之外的各玩法入口分别落到既有的 `agent-workspace`、`big-fish-agent-workspace`、`match3d-agent-workspace`、`square-hole-agent-workspace`、`jump-hop-workspace`、`wooden-fish-workspace`、`puzzle-agent-workspace`、`bark-battle-workspace`、`visual-novel-agent-workspace`、`baby-object-match-workspace`,这些入口继续承接各玩法自己的表单、草稿恢复和后续编排,不作为创作入口页内容。
|
||||
|
||||
创作恢复参数只保留 `sessionId`、`profileId`、`draftId`、`workId` 这四个私有 query。它们只允许在同一条创作链路的结果页、生成页、工作台之间保留;切到首页、公开作品详情、runtime 或另一条玩法链路时必须清掉。生成页恢复时只认当前进入页的时间作为新的 `startedAtMs`,作品摘要里的 `updatedAt` 只用于排序与摘要展示,不再作为生成进度起点。
|
||||
创作页和草稿页顶栏右上角的泥点余额胶囊是补足泥点入口:如果当前运行环境开启充值入口,点击后直接打开账户充值弹窗;否则直接打开运营兑换码弹窗。该入口不再跳到账户面板或泥点账单,头像 / 设置等账号入口继续保留各自语义。
|
||||
|
||||
创作恢复参数只保留 `sessionId`、`profileId`、`draftId`、`workId` 这四个私有 query。它们只允许在同一条创作链路的结果页、生成页、工作台之间保留;切到首页、公开作品详情、runtime 或另一条玩法链路时必须清掉。生成页等待时间统一以生成状态里的 `startedAtMs` 为准;创建该状态时优先使用后端 session 下发的时间戳,作品摘要里的 `updatedAt` 仍只用于排序与摘要展示,不作为前端自行推导业务状态的真相。
|
||||
|
||||
统一创作入口覆盖当前可进入创作链路的已有模板:`rpg`、`big-fish`、`puzzle`、`match3d`、`jump-hop`、`wooden-fish`、`square-hole`、`bark-battle`、`visual-novel`、`baby-object-match` 和 `creative-agent`;`airp` 仍是未开放占位,不作为当前统一创作链路目标。拼图、抓大鹅、跳一跳和敲木鱼在前端继续经过 `UnifiedCreationWorkspace` 和 `UnifiedGenerationPage`:`UnifiedCreationWorkspace` 作为平台壳依赖的统一创作编排层,再内部调用 `src/components/unified-creation/workspaces/` 下的 `PuzzleCreationWorkspace`、`Match3DCreationWorkspace`、`JumpHopCreationWorkspace` 和 `WoodenFishCreationWorkspace`。其它已有模板由平台壳用 `UnifiedCreationPage` 包住既有工作台,复用统一标题栏、返回入口、页面级纵向滚动和隐藏字段契约,同时保留各玩法自己的表单、草稿恢复和后续编排。创作页字段清单由后端在 `GET /api/creation-entry/config` 的 `creationTypes[].unifiedCreationSpec` 下发,前端仅在该扩展位缺失时回退到本地默认 spec;字段类型只保留 `text`、`select`、`image`、`audio`。`UnifiedCreationPage` 不在 UI 中额外展示字段说明 chip,也不在右上角显示内部 `playId`、模板 ID 或工作台阶段名;竖屏移动端必须能从标题、表单一路滑到提交按钮。各玩法工作台负责渲染真实输入控件、上传、历史素材、校验和提交,但返回按钮只保留在统一页头,工作台内部不再重复渲染。暗色创作进度卡片位于 `platform-remap-surface` 内时,必须用组件专属 class 覆盖浅色主题 remap,确保白字、浅色边框和进度条底色不会被全局规则改成深色;不要只依赖通用 `text-white*` 类。敲木鱼的音效和功德词条面板不得放进独立内部滚动容器,移动端应跟随页面自然滚动展开。生成页统一展示阶段、当前步骤、总进度、错误和重试动作。
|
||||
|
||||
创作表单提交前的泥点余额前置校验只允许用独立弹窗提示失败原因,不得把用户退回创作入口或玩法模板列表,也不得清空当前表单状态。当前适用拼图、抓大鹅和汪汪声浪等会在前端提交前校验泥点的生成入口;余额不足、余额读取失败都应停留在当前工作台,由用户关闭提示后继续编辑或自行补足泥点。
|
||||
|
||||
平台入口、生成页、结果页、作品详情、作品架和运行态的跨流程错误统一收口到 `PlatformErrorDialog`。弹窗必须带明确错误来源,例如某个草稿、某次生成、作品详情或某个游玩实例,并提供复制按钮复制“错误来源 + 错误内容”。页面内不再重复渲染裸错误 banner;表单校验、发布确认弹窗里的局部业务错误可以保留在原弹窗内。
|
||||
平台入口、生成页、结果页、作品详情、作品架和运行态的跨流程错误统一收口到 `PlatformErrorDialog`。弹窗必须带明确错误来源,例如某个草稿、某次生成、作品详情或某个游玩实例,并提供复制按钮复制“错误来源 + 错误内容”。页面内不再重复渲染裸错误 banner;表单校验、发布确认弹窗里的局部业务错误可以保留在原弹窗内。生成任务在用户离开生成页后异步失败时,也必须通过同一弹窗通知用户,并把失败消息写入该 session 的草稿 notice,供草稿页和失败重试页恢复使用。
|
||||
|
||||
生成任务在用户离开生成页后异步完成时,平台壳层必须弹出 `PlatformTaskCompletionDialog`。完成弹窗同样要带来源,例如某个草稿或生成会话,并提供复制按钮复制“来源 + 状态”;如果用户仍停留在生成页并被自动带入结果页或试玩页,生成页 / 结果页本身即为完成反馈,不再额外叠加完成弹窗。
|
||||
|
||||
入口配置中的 `open=false` 表示关闭新建创作入口,不表示下架已有草稿、私有作品或公开作品。api-server 的入口熔断只允许拦截新建创作、新建草稿、首次生成入口和 Remix 成草稿等会产生新创作的请求;公开广场列表、公开详情、点赞、已发布作品启动、运行态过程请求、存档 / 浏览记录和已有作品回读不能因为创作入口关闭而返回 `creation_entry_disabled`。平台首页如果遇到旧服务端返回的 `creation_entry_disabled`,只能降级为空列表或隐藏入口,不弹平台级错误弹窗。
|
||||
|
||||
创作入口页的关闭态卡片必须有明显差异:卡片禁用点击,展示后台配置的关闭态 badge 或 `暂未开放`,不再显示 `10-20泥点数` 这类可创建成本提示;开放态卡片仍不显示普通 `可创建 / 可创作` badge。
|
||||
|
||||
`PlatformEntryFlowShellImpl.tsx` 仍是平台入口编排壳,后续维护时应优先把独立 UI 片段、公开作品映射、草稿生成 notice 和运行态状态 helper 拆到 `src/components/platform-entry/PlatformEntryFlowShellImpl/` 或同目录紧邻 helper 文件。拆分只允许改变文件组织,不改变入口配置事实源、默认导出、props、页面阶段、UI 文案或现有交互;其中拼图首访 onboarding 已拆为 `PlatformEntryFlowShellImpl/PuzzleOnboardingView.tsx`。
|
||||
|
||||
`platformEntryCreationTypes.ts` 只做前端展示派生,分组时必须把后端 `creationTypes` 里的 `categoryId` / `categoryLabel` 当作可缺失字段处理,空值统一回退到 `recent` / `最近创作`,避免旧数据、局部 mock 或异常返回把创作入口初始化直接打崩。
|
||||
`platformEntryCreationTypes.ts` 只做前端展示派生,分组时必须把后端 `creationTypes` 里的 `categoryId` / `categoryLabel` 当作可缺失字段处理,空值统一回退到 `recommended` / `热门推荐`,并把历史 `recent` / `最近创作` 归一到推荐分类。`最近创作` 不属于模板分类页签,只能由 7 天内的真实草稿 / 作品架后端数据决定是否展示;展示内容仍然从后端入口配置的模板卡中筛选,不读取或渲染作品标题、作品摘要、草稿阶段文案。
|
||||
|
||||
移动端底部一级导航是全局平台样式,不按单一玩法分叉。当前视觉统一为米白浮动胶囊底座、浅棕分隔线、棕色线性图标、橘色选中态和底部短下划线;中间 `创作` 入口保持凸起圆形主按钮,但凸起位移只能作用在按钮内容层,不能移动承载分隔线的 Tab 按钮容器,确保创作左右分隔线与其他分隔线垂直位置一致。Tab 名称和可见性仍由现有 `PlatformHomeTab` / 登录态规则决定,样式调整不得改写 Tab 文案或导航状态。
|
||||
|
||||
@@ -36,7 +44,7 @@
|
||||
|
||||
通用系列素材图集能力的实现真相源在 `platform-image::generated_asset_sheets`:`n` 是必选参数,模块负责组装 `n*n` sheet prompt、按 `n*n` 切片、绿幕 / 近白底透明化、导出 PNG 和 OSS 持久化请求。`api-server::generated_asset_sheets` 只保留 `AppError` / `AppState` 适配,不再承载图像处理和 OSS 请求构造细节。物品名称 prompt 和特殊设定 prompt 是可选输入;调用方可传入类似“每个物品生成五个不同视图”的视角约束,通用模块会把 sheet prompt、物品行 prompt、特殊设定 prompt 编码写入 OSS 元数据。玩法仍负责计费、物品规划、slot 映射、失败回写和把通用切片结果映射回自己的草稿 / profile / runtime 字段。
|
||||
|
||||
当前所有玩法生成页 UI 统一收敛为圆环主视觉:`media/create_bg_video.mp4` 作为生成页固定全屏背景层循环静音播放,主进度圆环居中覆盖在背景之上,围绕陶泥儿视觉展示;页面只保留当前步骤名称和当前步骤进度,不再渲染步骤列表块。视频层需要显式触发播放,不能只依赖 `autoPlay/loop/muted` 属性。共用生成页 `CustomWorldGenerationView` 和汪汪声浪生成页都必须遵循这一口径。
|
||||
当前所有玩法生成页 UI 统一收敛为圆环主视觉:`media/create_bg_video.mp4` 作为生成页固定全屏背景层循环静音播放,主进度圆环居中覆盖在背景之上,围绕陶泥儿视觉展示;页面只保留当前步骤名称和当前步骤进度,不再渲染步骤列表块。视频层需要显式触发播放,不能只依赖 `autoPlay/loop/muted` 属性。圆环内部保持 `400x400` SVG 坐标系,外层显示宽度以 `400px` 为上限,窄屏按视口宽度收缩,预计等待 / 已耗时信息卡在窄屏下落到圆环下方,避免右侧裁切。共用生成页 `CustomWorldGenerationView` 和汪汪声浪生成页都必须遵循这一口径。
|
||||
|
||||
## 草稿与作品架
|
||||
|
||||
@@ -45,12 +53,16 @@
|
||||
3. 草稿页与底部导航的未读提示点统一使用平台暖棕色点和暖棕光晕,不再使用红点或红色 glow;草稿 Tab 作品架卡片无论草稿 / 已发布都不外露作者信息;已发布作品卡右上角直接显示无边框分享 icon。删除等破坏性动作在作品卡上也要直接开放独立删除入口,左滑或长按仅作为辅助操作层。
|
||||
4. 生成中作品在整卡上加等待遮罩,但不移除作品基础信息。
|
||||
5. 生成中状态不能只存在前端内存 notice。后端作品摘要必须下发可恢复的 `generationStatus`;前端刷新或退出产品后,作品架优先用摘要状态恢复等待遮罩,本轮内存 notice 只作为即时反馈。
|
||||
6. 点击 `generationStatus=generating` 的草稿卡必须恢复对应玩法的生成进度页,不能进入空白结果页或普通工作区;恢复生成页的 `startedAtMs` 使用进入生成页的当前时间,作品摘要 `updatedAt` 只用于排序和摘要展示,不参与假进度起算。
|
||||
7. 从草稿 Tab 作品架打开草稿工作区、生成页或结果页时,返回按钮必须回到草稿 Tab 的同一作品架语境;从创作 Tab 新建或直接进入创作链路时才回到创作 Tab。平台壳层需要显式记录本次创作流的返回来源,不能让结果页返回动作固定跳到创作入口。
|
||||
8. 私有 generated 图片必须通过 `ResolvedAssetImage` / `/api/assets/read-url` 换签读取。
|
||||
9. 敲木鱼作品架读取当前用户作品列表时走 `GET /api/creation/wooden-fish/works`;发布成功后平台壳必须同时刷新作品架与公开广场,避免作品刚发布时仍停留在旧列表。
|
||||
6. 点击 `generationStatus=generating` 的草稿卡必须恢复对应玩法的生成进度页,不能进入空白结果页或普通工作区;恢复生成页的 `startedAtMs` 优先使用后端 session 的 `updatedAt`,没有 session 时再使用作品摘要 `updatedAt`,不得因重新进入页面从 0 秒重新计时。
|
||||
7. 生成失败必须按 session 独立记录,不能用一个失败打断或覆盖同玩法的其它生成任务。失败 notice 需要保存错误消息并覆盖作品架本地状态:即使后端摘要暂时仍是 `generationStatus=generating` 或只写出半成品投影,草稿卡也不得继续显示“生成中”,点击后必须进入失败 / 重试生成页,不能重新创建一轮生成;拼图这类失败半成品若没有有效 `workTitle`,作品架标题回退为“拼图草稿”,不暴露“第1关”空壳。
|
||||
8. 从草稿 Tab 作品架打开草稿工作区、生成页或结果页时,返回按钮必须回到草稿 Tab 的同一作品架语境;从创作 Tab 新建或直接进入创作链路时才回到创作 Tab。平台壳层需要显式记录本次创作流的返回来源,不能让结果页返回动作固定跳到创作入口。
|
||||
9. 私有 generated 图片必须通过 `ResolvedAssetImage` / `/api/assets/read-url` 换签读取。
|
||||
10. 敲木鱼作品架读取当前用户作品列表时走 `GET /api/creation/wooden-fish/works`;发布成功后平台壳必须同时刷新作品架与公开广场,避免作品刚发布时仍停留在旧列表。
|
||||
11. 移动端草稿页整体禁止长按选择文字,避免误触系统选区;输入框、文本域和可编辑区域仍必须保留文本选择能力。
|
||||
|
||||
发现 Tab、创作 Tab 与草稿 Tab 的页面根内容区不再套 `platform-page-stage` 外层全局卡片壳,让列表、筛选和玩法卡获得更宽的横向空间;推荐页和我的页仍按各自页面设计保留原有全局卡片口径。移动端“我的”页仍按顶部头像 / 昵称 / 陶泥号、会员横幅、三张统计卡、每日任务、五项常用功能宫格、设置入口和法律信息组织,不保留旧的底部“填邀请码”次级入口;每日任务卡必须读取 `/api/profile/tasks` 的当前任务摘要并在领取后同步刷新卡片进度。字号必须维持平台普通 UI 档位,不能因为窄屏把卡片标题、功能 label 或法律信息撑成展示级字号;最后一屏内容必须能在底部 dock 上方完整滚动露出,不得被固定底部导航遮挡。
|
||||
发现页 / 推荐页公开作品卡的作者行只显示可读公开昵称;不得把手机号掩码、`SY-*` 陶泥号或作品号拼接进卡片作者名。陶泥号搜索、作品号复制和完整作品身份只在搜索、详情页或明确的复制入口展示,避免卡片列表暴露账号标识。
|
||||
|
||||
发现 Tab、创作 Tab 与草稿 Tab 的页面根内容区不再套 `platform-page-stage` 外层全局卡片壳,让列表、筛选和玩法卡获得更宽的横向空间;推荐页和我的页仍按各自页面设计保留原有全局卡片口径。移动端“我的”页仍按顶部头像 / 昵称 / 陶泥号、会员横幅、三张统计卡、每日任务、五项常用功能宫格、设置入口和法律信息组织,不保留旧的底部“填邀请码”次级入口;常用功能当前只展示四项常驻入口时必须按四列铺满整行,不保留五列网格导致左对齐空位;每日任务卡必须读取 `/api/profile/tasks` 的当前任务摘要并在领取后同步刷新卡片进度。字号必须维持平台普通 UI 档位,不能因为窄屏把卡片标题、功能 label 或法律信息撑成展示级字号;最后一屏内容必须能在底部 dock 上方完整滚动露出,不得被固定底部导航遮挡。
|
||||
|
||||
## RPG / 自定义世界
|
||||
|
||||
@@ -93,9 +105,9 @@ RPG / 拼图等运行态存档仍以 `/api/profile/save-archives` 的后端列
|
||||
- 图像输入复用 `CreativeImageInputPanel`。
|
||||
- 结果页每关画面编辑复用 `CreativeImageInputPanel`;入口页和关卡画面只共享受控 UI 模块,不共享数据源、状态、action 或存储位置:入口页继续写 `formDraft` 与草稿编译 payload,关卡画面写 `levels[].pictureReference/pictureDescription` 并触发 `generate_puzzle_images`。结果页删除独立“素材配置”Tab,不再提供单独 UI 背景生成入口。通用图片面板的展示图和 AI 重绘参考图能力必须分开控制:结果页正式关卡图只作为预览图,不因存在正式图自动暴露 AI 重绘开关;只有本地上传、历史选择或已保存 `pictureReference` 可作为重绘参考图时,才显示 AI 重绘开关并把状态带入 `generate_puzzle_images`。用户在本次编辑中上传或选择历史图后,该图优先占据主图卡片,可删除、切换 AI 重绘,也可关闭 AI 重绘直用;仅有正式图预览时,画面描述框仍可上传多张参考图。关卡详情弹窗应使用加宽面板,关卡名称、画面图和画面描述合并在同一个纵向列表中,名称输入和画面编辑模块外层不再包独立 `platform-subpanel`;画面图卡仍必须保留稳定最小高度,避免弹窗内 `flex-1` 布局坍缩后只剩标题、描述输入和操作按钮。
|
||||
- 支持画面描述生图、多参考图生图、上传或历史生成主图后 AI 重绘、上传或历史生成主图后不重绘;主链要求浏览器先经 `/api/assets/direct-upload-tickets` 直传 OSS 并确认 `asset_object`,创作 action 只提交 `referenceImageAssetObjectId(s)`,由后端校验 owner / bucket / kind / MIME / size 后签发 OSS 只读 URL 并下载为 VectorEngine `/v1/images/edits` 的 multipart `image` part。本地上传 Data URL 与历史 `/generated-*` 图片路径仅保留为旧草稿、旧入口或未迁移客户端的兼容输入;关闭 AI 重绘时,后端统一解析为首关或当前关卡正式图后再持久化,不调用第一段拼图首图生成。
|
||||
- 草稿生成会先持久化 `generationStatus=generating` 的作品摘要,生成完成并回写关卡拼图画面、关卡画面参考图、UI spritesheet 和关卡背景图后再变为 `ready`;当前不自动生成背景音乐。生成页步骤推进必须跟随后端 session `progressPercent` 的真实里程碑:`88` 表示草稿编译完成并进入出图步骤,`94` 表示生成图已保存并进入 UI / 背景步骤,`96` 表示正式图与 UI 背景已确认并进入写入步骤,最终 action 成功或发布才进入完成态;每个步骤内部可以按实际等待时间使用假进度平滑推进,总进度按 `0-88`、`88-94`、`94-96`、`96-98` 的真实里程碑区间平滑推进。任一同步 action 回包到达时立即以真实完成/失败结果冻结进度。
|
||||
- 作品架拼图草稿的“生成中”遮罩只表示初始草稿还没有可查看结果;只要作品摘要、首关封面或任一关卡候选图已经可用,后续 UI 背景重生成和追加关卡生图都必须作为结果页局部生成态处理,不能阻止打开草稿结果页。
|
||||
- 拼图草稿编译是长耗时 action,前端 action 请求默认等待 `1_800_000ms`(30 分钟)且不自动重试。每次图片生成调用的预期用时按 90 秒计算,但 `生成拼图首图` 单独按 4 分钟展示;完整 AI 重绘路径为 `编译首关草稿` 8 秒、`生成关卡名称` 10 秒、`生成拼图首图` 4 分钟、`生成关卡画面` 90 秒、`生成UI与背景` 90 秒、`写入正式草稿` 10 秒,合计约 448 秒。上传图且关闭 AI 重绘时必须跳过 `生成拼图首图`,直接进入 `生成关卡画面` 和 `生成UI与背景`,合计约 208 秒。生成页恢复时必须使用进入生成页的当前时间作为原始 `startedAtMs`;失败/完成态用 `finishedAtMs` 冻结耗时。未收到对应后端里程碑前,后续步骤保持待处理;即使当前步骤预计时长耗尽,也只能让当前步骤内部进度停在 `98%` 内,不能自动完成当前步骤或跳到后续步骤。生成页每个步骤只展示标题和进度,不展示步骤详细描述。
|
||||
- 草稿生成会先持久化 `generationStatus=generating` 的作品摘要,生成完成并回写关卡拼图画面、关卡画面参考图、UI spritesheet 和关卡背景图后再变为 `ready`;当前不自动生成背景音乐。生成页步骤推进必须跟随后端 session `progressPercent` 的真实里程碑:`88` 表示草稿编译完成并进入出图步骤,`94` 表示生成图已保存并进入 UI / 背景步骤,`96` 表示正式图与 UI 背景已确认并进入写入步骤,最终 action 成功或发布才进入完成态;每个步骤内部可以按实际等待时间使用假进度平滑推进。`88/94/96` 只负责切换当前步骤,不作为总进度地板;总进度按已完成步骤权重加当前步骤内假进度推导,非完成态最多停在 `98%`。任一同步 action 回包到达时立即以真实完成/失败结果冻结进度。
|
||||
- 作品架拼图草稿的“生成中”遮罩只表示初始草稿还没有可查看结果;只要作品摘要、首关封面或任一关卡候选图已经可用,后续 UI 背景重生成和追加关卡生图都必须作为结果页局部生成态处理,不能阻止打开草稿结果页。生成失败后,同一浏览器会话内的失败 notice 必须覆盖后端可能仍短暂返回的 `generationStatus=generating` 摘要,作品架保留对应草稿卡但不再显示“生成中”,点击后回到失败 / 重试状态。
|
||||
- 拼图草稿编译是长耗时 action,前端 action 请求默认等待 `1_800_000ms`(30 分钟)且不自动重试。每次图片生成调用的预期用时按 90 秒计算,但 `生成拼图首图` 单独按 4 分钟展示;完整 AI 重绘路径为 `编译首关草稿` 8 秒、`生成关卡名称` 10 秒、`生成拼图首图` 4 分钟、`生成关卡画面` 90 秒、`生成UI与背景` 90 秒、`写入正式草稿` 10 秒,合计约 448 秒。上传图且关闭 AI 重绘时必须跳过 `生成拼图首图`,直接进入 `生成关卡画面` 和 `生成UI与背景`,合计约 208 秒。生成页恢复时必须使用后端 session `updatedAt` 或作品摘要 `updatedAt` 作为原始 `startedAtMs`;失败/完成态用 `finishedAtMs` 冻结耗时。未收到对应后端里程碑前,后续步骤保持待处理;即使当前步骤预计时长耗尽,也只能让当前步骤内部进度停在 `98%` 内,不能自动完成当前步骤或跳到后续步骤。生成页每个步骤只展示标题和进度,不展示步骤详细描述。
|
||||
- 前端创作、结果页、生成页和错误提示不展示 GPT / Gemini 等具体模型名称;如需在内部保留模型路由,UI 只使用“标准模式”“创意模式”等产品化名称。
|
||||
- 若浏览器锁屏、息屏或网络切换导致 compile 请求失败,前端在标记失败前必须先复读 `getPuzzleAgentSession(sessionId)`;只有最新 session 仍缺 `draft.coverImageSrc`、首关 `coverImageSrc` 或候选图时才展示失败,复读到已生成草稿时按成功收尾、刷新作品架并继续自动试玩/结果页链路。
|
||||
- 拼图参考图 AI 重绘走 VectorEngine `/v1/images/edits`;无参考图时走 `/v1/images/generations`。两者模型都使用 `gpt-image-2`,参考图由后端作为 multipart `image` part 传入编辑接口。
|
||||
@@ -105,7 +117,7 @@ RPG / 拼图等运行态存档仍以 `/api/profile/save-archives` 的后端列
|
||||
- 结果页单关测试只能把完整草稿持久化,并通过 `levelId` 指定运行态起始关卡;不得把单关快照作为整份草稿调用 `updatePuzzleWork`,否则 source session 和作品 profile 的 `levels` 会被覆盖成单关,退出重进后其它关卡会丢失。
|
||||
- 拼图试玩和正式运行态刷新恢复不复用创作私有 query。进入 `/runtime/puzzle` 时必须写入 `runtimeProfileId`、草稿 `runtimeSessionId`、可选 `runtimeLevelId`、公开作品 `work` 和 `mode=draft|published`;进入运行态的导航顺序必须先切到 `/runtime/puzzle`,再写这些 runtime query,避免被阶段导航清掉后刷新停在“正在进入拼图关卡”。
|
||||
- 结果页生成关卡图时若关卡名为空,前端必须传 `shouldAutoNameLevel=true`,后端复用首关命名契约先按画面描述生成关卡名,再在图片生成后用视觉命名结果精修,并把生成名和 UI 背景提示词随本次关卡快照写回。
|
||||
- 拼图运行态背景优先读取当前关卡 `levelBackgroundImageSrc/levelBackgroundImageObjectKey`,旧数据才兼容 `uiBackgroundImageSrc/uiBackgroundImageObjectKey`;本地试玩、直达指定关卡和正式 `next-level` 推进时,目标关卡缺关卡背景时必须继承同作品首个可用关卡背景,仍缺失时才沿用当前运行态快照背景或默认 UI。运行态按钮视觉优先读取当前关卡 `uiSpritesheetImageSrc/uiSpritesheetImageObjectKey`,先按透明 alpha 自动边界检测识别 spritesheet 中的独立按钮展示矩形,再按原图位置从左到右、从上到下映射到返回、设置、下一关、提示、原图、冻结;同一组件还要按较高 alpha 阈值派生紧致点击热区,透明留白和柔边低 alpha 区域尽量不响应点击。检测失败时回退旧固定六格裁切,缺失时才用现有图标按钮兜底。有 spritesheet 时,返回和设置按钮的点击容器只提供透明点击区,不再叠加默认白色圆形底;底部提示、原图、冻结三枚素材按检测矩形的原始宽高比显示,不能强行拉伸成正圆或铺满整列。底部道具区不再使用连片胶囊背景,提示、原图、冻结三个按钮均匀分布;运行态只展示按钮素材本身,不额外叠加“提示 / 原图 / 冻结”文字。
|
||||
- 拼图运行态背景优先读取当前关卡 `levelBackgroundImageSrc/levelBackgroundImageObjectKey`,旧数据才兼容 `uiBackgroundImageSrc/uiBackgroundImageObjectKey`;本地试玩、直达指定关卡和正式 `next-level` 推进时,目标关卡缺关卡背景时必须继承同作品首个可用关卡背景,仍缺失时才沿用当前运行态快照背景或默认 UI。运行态按钮视觉优先读取当前关卡 `uiSpritesheetImageSrc/uiSpritesheetImageObjectKey`,先按透明 alpha 自动边界检测识别 spritesheet 中的独立按钮展示矩形,再按原图位置从左到右、从上到下映射到返回、设置、下一关、提示、原图、冻结;同一组件还要按较高 alpha 阈值派生紧致点击热区,透明留白和柔边低 alpha 区域尽量不响应点击。检测失败时回退旧固定六格裁切,缺失时才用现有图标按钮兜底。有 spritesheet 时,返回、设置和下一关的点击容器只提供透明点击区,不再叠加默认白色圆形底、胶囊主按钮底或额外文字;下一关按钮在通关弹窗和底部入口中都直接使用 spritesheet 裁切出的 next 素材作为按钮本体。底部提示、原图、冻结三枚素材按检测矩形的原始宽高比显示,不能强行拉伸成正圆或铺满整列。底部道具区不再使用连片胶囊背景,提示、原图、冻结三个按钮均匀分布;运行态只展示按钮素材本身,不额外叠加“提示 / 原图 / 冻结”文字。
|
||||
- 推荐页本身不是登录门禁入口,未登录用户点击底部或侧边栏的推荐 Tab 应直接进入嵌入运行态,不主动打开登录弹窗。推荐页嵌入运行态必须按真实身份分流:已登录用户或本地已有 access token 时,启动拼图和后续排行榜 / 下一关等正式请求继续走账号 Bearer;只有确认为匿名访客时才申请并透传 runtime guest token。`/api/runtime/puzzle/runs*` 后端统一接受 `RuntimePrincipal`,可识别账号用户和匿名 runtime guest;推荐卡片的后台读写请求仍使用 local auth impact,避免单卡 401 清空整站登录态。创作、个人作品、删除、发布、Remix 等账号或所有权动作仍保持普通用户鉴权。
|
||||
- 拼图运行态棋盘不叠加分块蒙版、描边、阴影、选中底色或合并块 SVG 轮廓;拼图片本体需要裁切为圆角形状,单块使用独立圆角裁切,合并块使用 SVG 原生 `clipPath` 裁切整体外轮廓,外凸角和内凹角分别计算半径,内凹角半径要比外凸角更明显以避免手机 WebView 中看起来仍是直角。原图道具只在用户主动确认后打开独立原图查看层,不在当前拼图棋盘上叠加原图。
|
||||
- 拼图运行态拖拽必须完全跟随手指或鼠标位置,`pointermove` 期间即时写入可见拼块的 transform,不依赖等待后端回包、React 重渲染或下一帧动画队列;进入拖动后不展示拼块选中态或“已选择”提示,松手后再提交目标格同步规则真相。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 拼图生成页进度口径
|
||||
|
||||
更新时间:`2026-05-24`
|
||||
更新时间:`2026-06-02`
|
||||
|
||||
## 目标
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
|
||||
## 落地口径
|
||||
|
||||
- 总进度和当前步骤内百分比可以按已耗时平滑增长,但进入生成页的初始帧必须从 `0%` 开始,非完成态最多停在 `98%`。
|
||||
- 未收到首个真实里程碑前,页面仍停留在当前步骤,总进度在 `0-88` 区间内平滑推进;收到 `88/94/96` 里程碑后,分别在 `88-94`、`94-96`、`96-98` 区间内推进,避免步骤不跳时总进度也停死。
|
||||
- 后端 `progressPercent` 低于 `88` 只作为当前会话状态记录,不得把生成页阶段推到首个图片里程碑;低于首个里程碑时页面仍按当前视图进入时间从 `0%` 平滑展示。
|
||||
- 总进度和当前步骤内百分比可以按已耗时平滑增长;新发起的生成初始帧从 `0%` 开始,恢复持久化生成中草稿时必须按后端 session / 作品摘要时间戳推导已耗时,不能每次重新从 `0 秒` 起算。非完成态最多停在 `98%`。
|
||||
- 后端 `progressPercent` 的 `88/94/96` 只用于切换当前真实步骤,不得直接作为总进度地板;总进度应按已完成步骤权重加当前步骤内假进度推导,避免恢复或轮询后瞬间跳到 `88%`。
|
||||
- 后端 `progressPercent` 低于 `88` 只作为当前会话状态记录,不得把生成页阶段推到首个图片里程碑,也不得抬高首帧总进度。
|
||||
- 步骤状态以真实阶段为准:`phase` / 后端会话进度 / 最终完成或失败回包才允许跨步。
|
||||
- 拼图生成页恢复持久化 `generationStatus=generating` 草稿时,展示进度使用“进入生成页的当前时间”作为 `startedAtMs`;不得再用作品摘要 `updatedAt` 推导展示起点,避免刷新后首帧直接跳到 `80%+`。
|
||||
- 拼图和抓大鹅等生成页从作品架 / 刷新恢复进入时,前端应把展示态生成状态重基准到进入页面的当前时间;后台 session 的 `progressPercent` 与历史里程碑只保留为状态事实,不得直接作为首帧总进度。
|
||||
- 拼图和抓大鹅等生成页从作品架 / 刷新恢复进入时,前端应优先使用后端 session `updatedAt` 或作品摘要 `updatedAt` 作为展示态 `startedAtMs`,保证已耗时与后端生成时间对齐;后台 session 的 `progressPercent` 只负责真实步骤推进,不直接决定总进度百分比。
|
||||
- 生成失败时,生成页冻结为失败 / 重试状态;同一浏览器会话内返回草稿 Tab 时,失败草稿必须继续出现在作品架,且本地失败 notice 要覆盖后端仍可能短暂返回的 `generationStatus=generating` 摘要,不能继续显示“生成中”。
|
||||
- 当前步骤未完成时,后续步骤保持待处理;即使预计时间耗尽,也只能让当前步骤内部进度接近或达到上限,不能自动完成后续步骤。
|
||||
- 抓大鹅等非拼图小游戏的生成页也遵守初始帧 `0%`:没有后端资产计数时,当前步骤内假进度按玩法预计等待总时长从 `0` 平滑推进,不使用固定 `0.5` 这类常量起步。
|
||||
- 抓大鹅等非拼图小游戏的生成页也遵守同一恢复口径:没有后端资产计数时,当前步骤内假进度按玩法预计等待总时长平滑推进,不使用固定 `0.5` 这类常量起步,也不在未完成时显示 `100%`。
|
||||
- 步骤卡片只展示标题和进度,不展示详细描述。
|
||||
- 生成拼图首图步骤按 4 分钟预估;完整 AI 重绘路径总预计时长为 448 秒,上传图且关闭 AI 重绘时跳过首图生成,仍为 208 秒。
|
||||
|
||||
@@ -25,5 +25,6 @@
|
||||
- `src/services/miniGameDraftGenerationProgress.test.ts` 覆盖后端 `progressPercent < 88` 时不会抬高进入生成页的初始总进度。
|
||||
- `src/services/miniGameDraftGenerationProgress.test.ts` 覆盖抓大鹅等非拼图生成页初始总进度为 `0%`。
|
||||
- `src/components/CustomWorldGenerationView.test.tsx` 覆盖步骤详情不在生成页渲染。
|
||||
- `src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "persisted generating"` 覆盖刷新后继续生成中拼图 / 抓大鹅草稿不会继承旧 `updatedAt` 导致总进度首帧过高。
|
||||
- `src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "persisted generating"` 覆盖刷新后继续生成中拼图 / 抓大鹅草稿按后端时间戳恢复,且不会因后端里程碑直接跳到 `88%` 或 `100%`。
|
||||
- `src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "failed parallel puzzle generations"` 覆盖失败后的 pending 拼图草稿仍留在作品架,并且不再显示“生成中”。
|
||||
- 文档主图谱的拼图章节同步保留该口径。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 生成页圆环布局口径
|
||||
|
||||
更新时间:`2026-05-24`
|
||||
更新时间:`2026-06-02`
|
||||
|
||||
## 目标
|
||||
|
||||
@@ -12,11 +12,12 @@
|
||||
- 生成页背景视频必须留在生成页容器内部,直接作为 `fixed inset-0` 的底层背景,不要再通过 portal 挂到 `document.body`;页面根容器使用 `z-[1]`、背景容器使用 `z-0`,确保顶部导航、圆环和当前步骤卡都稳定覆盖在视频之上。
|
||||
- 预计等待 / 已耗时信息卡要压缩为更轻的半透明窄卡,标签使用 `9px-10px`,数值使用 `12px-13px`,字号对齐其他生成页 UI 的小字号,不再使用偏大的提示文本;卡片标题和时间值都居中显示,两个数值只展示时间本身,调用侧不要再拼接“预计还需”或“已耗时”前缀。圆环中心不再保留独立白底块,空心圆环只保留条状进度,圆弧半径继续加大,进度数字与“总进度”标题整体上移,靠近圆环上半区。
|
||||
- 顶部导航区采用“返回创作中心 / 状态胶囊”结构,返回按钮使用左箭头图标,字号使用 `text-xs-sm`,状态胶囊使用 `11px-12px`,展示 `素材生成中`、`草稿生成中` 等调用侧传入文案。
|
||||
- 圆弧区域不再包独立大卡片,左右悬浮信息卡只展示“预计等待”和“已耗时”;总进度数值放在圆弧内侧偏上的位置并保持更小字号。圆环本体固定在 `400x400` 的 SVG 画布上,圆弧使用 `r=166`、`strokeWidth=18` 的 SVG 描边,不再跟随页面宽度缩放,也不再使用 `conic-gradient + mask`,避免进度条边缘模糊。
|
||||
- 圆弧描边以圆心为中心整体按 `135deg` 起始;`270deg` 扫描角配合 `90deg` 正下方缺口时,轨道和填充都从同一个对称起点出发,轨道保持 `rotate(135 200 200)`,填充端点也使用 `rotate(135 200 200)`。圆环本体尺寸固定,不允许再随容器边长伸缩,只能由外层布局决定放置位置。
|
||||
- 圆弧区域不再包独立大卡片,信息卡只展示“预计等待”和“已耗时”;总进度数值放在圆弧内侧偏上的位置并保持更小字号。圆环内部坐标固定在 `400x400` 的 SVG `viewBox` 上,圆弧使用 `r=166`、`strokeWidth=18` 的 SVG 描边,外层显示宽度上限为 `400px`;窄屏视口按 `min(400px, calc(100vw - 2.5rem))` 等比收缩,避免等待页右侧被裁切。圆弧不再使用 `conic-gradient + mask`,避免进度条边缘模糊。
|
||||
- 圆弧描边以圆心为中心整体按 `135deg` 起始;`270deg` 扫描角配合 `90deg` 正下方缺口时,轨道和填充都从同一个对称起点出发,轨道保持 `rotate(135 200 200)`,填充端点也使用 `rotate(135 200 200)`。圆环只允许在可用宽度不足 `400px` 时等比收缩,不随宽屏容器继续放大。
|
||||
- 在窄屏下,预计等待 / 已耗时信息卡放到圆环下方两列排布;`sm` 及以上视口再回到圆环左右悬浮,避免左右悬浮卡和圆环共同超过视口宽度。
|
||||
- 总进度标题和百分比数字必须显式高于 SVG 圆环层级渲染,避免被圆环边缘压住;圆环本身只做背景层,不抢文字层。
|
||||
- 总进度标题和百分比数字要比圆环再上移一点,当前内容区上边距以 `pt-[2%]` 为准,桌面端可进一步微调到 `sm:pt-[1.5%]`,确保数字不与进度条弧线重合。
|
||||
- 从作品架或刷新后的持久化生成中草稿进入生成页时,前端必须重置“展示态 startedAtMs”为进入生成页的当前时间;后端 `progressPercent` 只用于后续真实步骤推进,不得参与首帧总进度展示,避免恢复生成页首帧直接显示 `80%+`。
|
||||
- 从作品架或刷新后的持久化生成中草稿进入生成页时,前端必须按后端 session `updatedAt` 或作品摘要 `updatedAt` 恢复展示态 `startedAtMs`,保证“已耗时”不因重新进入页面而清零;后端 `progressPercent` 只用于真实步骤推进,不得直接作为总进度地板,避免恢复生成页首帧直接显示 `88%` 或 `100%`。
|
||||
- 生成页只展示半透明“当前步骤”单卡,卡片内只保留步骤名称、步骤状态、步骤进度条和轻量加载指示;“当前步骤”标签使用 `10px-11px`,步骤名称使用 `14px-15px`,状态使用 `11px-12px`,不再渲染步骤列表或步骤详情。
|
||||
- 当前作品信息放在圆角信息卡中,标题固定使用 `13px`;有结构化字段时以两列信息块展示,例如“题材 / 素材数量”,无结构化字段时才展示纯文本设定。
|
||||
- 汪汪声浪生成页 `BarkBattleGeneratingView` 也必须对齐同一垂直布局,不再继续展示三行槽位列表或左右分栏抢占主视觉。
|
||||
@@ -28,4 +29,5 @@
|
||||
- `src/components/bark-battle-creation/BarkBattleGeneratingView.test.tsx` 覆盖汪汪声浪生成页对齐后的圆环布局。
|
||||
- 两个生成页都应在测试里断言页面根容器层级高于背景视频容器,且背景视频确实是页面子节点,避免 portal 背景把业务 UI 压住。
|
||||
- 还应断言圆弧正下方留空、圆环中心没有独立底色块,时间卡和总进度字号缩小后仍能在桌面与移动端正常排版;同时断言时间卡 `text-center`、标题行 `justify-center`、总进度内容区上移到 `pt-[2%]`,桌面端保持 `sm:pt-[1.5%]`,圆弧 DOM 为 SVG,包含清晰的 track/fill circle 描边。
|
||||
- 还应断言圆环容器使用 `w-[min(400px,calc(100vw-2.5rem))]`、`max-w-full` 和 `aspect-square`,窄屏截图至少覆盖 `280px / 320px / 360px / 390px` 宽度,确认右侧没有硬性裁切。
|
||||
- 页面在桌面和移动端都不应再出现生成步骤列表块,圆环和当前步骤卡不能被外层卡片嵌套出双层面板感。
|
||||
|
||||
@@ -95,7 +95,7 @@ server-rs + Axum + SpacetimeDB
|
||||
7. 主站入口已锁定移动端页面级缩放;单个游戏页面不要再重复实现整页缩放锁定。
|
||||
8. 图像输入通用 UI 统一走 `src/components/common/CreativeImageInputPanel.tsx`。外层页面持有业务状态,组件只承担上传卡、预览、参考图缩略图、AI 重绘开关、错误展示和提交按钮。
|
||||
9. 发现页 `分类` 子频道的筛选必须打开独立 dialog / drawer / modal,至少支持玩法类型过滤与排序切换;筛选结果为空时显示空状态,不把筛选内容展开在当前列表下方。
|
||||
10. 移动端“我的”页顶部品牌行承载扫码和设置入口,正文按参考图顺序组织为头像 / 昵称 / 陶泥号、会员横幅、三张统计卡、每日任务、五项常用功能宫格、设置入口和法律信息;`media/profile/` 中的陶泥素材作为该页图形资产。常用功能宫格固定承载泥点充值、邀请好友、兑换码、玩家社区、反馈与建议;页面不再提供独立存档按钮入口,也不在底部保留旧的填邀请码次级入口。填邀请码只由邀请链接 query 或其它明确引导打开独立弹窗,不作为“我的”页常驻按钮。
|
||||
10. 移动端“我的”页顶部品牌行承载扫码和设置入口,正文按参考图顺序组织为头像 / 昵称 / 陶泥号、会员横幅、三张统计卡、每日任务、五项常用功能宫格、设置入口和法律信息;`media/profile/` 中的陶泥素材作为该页图形资产。常用功能宫格固定承载泥点充值、邀请好友、兑换码、玩家社区、反馈与建议;当前只展示四项常驻入口时必须按四列铺满整行,不保留五列网格导致左对齐空位。页面不再提供独立存档按钮入口,也不在底部保留旧的填邀请码次级入口。填邀请码只由邀请链接 query 或其它明确引导打开独立弹窗,不作为“我的”页常驻按钮。
|
||||
11. “我的”页每日任务卡必须展示后端 `/api/profile/tasks` 返回的当前任务摘要,包括奖励泥点数、进度和领取 / 去完成 / 已完成状态;任务领取成功后,卡片摘要必须跟随返回的任务中心数据同步刷新,不能继续硬编码 `0 / 1` 或只更新弹窗内任务列表。
|
||||
12. “我的”页泥点、游戏时长、已玩游戏数量三张统计卡只展示各自标签和值,三个统计 icon 使用小尺寸普通 UI 档位,内容不换行,不在统计区底部展示“更新于”时间;移动端昵称、会员卡、每日任务、常用功能和法律信息也应保持 `10px` 到 `14px` 的普通 UI 字号区间,避免展示级字号挤压内容。
|
||||
13. 移动端“我的”页需要兼容窄屏:头像 / 昵称 / 陶泥号、三张统计卡、每日任务、五项常用功能和法律信息都必须能在底部固定 TabBar 上方完整滚动露出,不得与底部 dock、刘海 safe-area 或相邻 UI 元素遮挡重叠。
|
||||
|
||||
Reference in New Issue
Block a user