fix: preserve rpg custom world detail profiles

This commit is contained in:
kdletters
2026-05-22 03:14:11 +08:00
parent a9d23a8a44
commit d74457faa2
19 changed files with 2726 additions and 109 deletions

View File

@@ -38,13 +38,29 @@
- 验证:`npm run test -- src/components/rpg-entry/useRpgCreationEnterWorld.test.tsx`;确认已发布场景下 `syncAgentDraftResultProfile``executePublishWorld` 均未被调用。
- 关联:`src/components/rpg-entry/useRpgCreationEnterWorld.ts``src/components/platform-entry/PlatformEntryFlowShellImpl.tsx``docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`
## RPG 点击启动黑屏先查 profile 归一化和角色选择兜底
## RPG 点击启动黑屏 / 默认 profile 先查 profile 归一化和摘要覆盖
- 现象:作品详情点击“启动”后页面切到 RPG runtime但用户只看到黑屏空白DevTools 里可能同时看到旧自动存档 `/api/runtime/save/snapshot` 被主动 cancel。
- 原因:`/custom-world-library` / `/custom-world-gallery` 详情接口可能返回历史或摘要式 `profile`,缺少 `playableNpcs``storyNpcs``landmarks``attributeSchema` 等运行态字段;前端 client 若直接把该对象传给 runtime角色选择首屏会在 `buildCustomWorldPlayableCharacters(profile)` 或后续属性解析处抛错。`save/snapshot (canceled)` 通常是切 runtime 或卸载时 `AbortController` 取消旧自动存档,不是黑屏根因。
- 处理RPG 入口作品库 client 在所有返回 `CustomWorldLibraryEntry<CustomWorldProfile>` 的接口边界统一调用 `normalizeCustomWorldProfileRecord`,并用 `profileId/worldName/subtitle/summaryText` 补齐旧数据缺字段;角色选择页对角色生成异常或空数组回退默认角色,并保留返回按钮/轻量空态;顶层 runtime 懒加载 fallback 不使用纯 `null`
- 验证:`npm run test -- src/services/rpg-entry/rpgEntryLibraryClient.test.ts``npm run test -- src/components/rpg-entry/RpgEntryCharacterSelectView.test.tsx``npm run typecheck`
- 关联:`src/services/rpg-entry/rpgEntryLibraryClient.ts``src/components/rpg-entry/RpgEntryCharacterSelectView.tsx``src/App.tsx``src/components/rpg-runtime-shell/RpgRuntimeShell.tsx``docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`
- 现象:作品详情点击“启动”后页面切到 RPG runtime但用户只看到黑屏空白,或进入默认角色 / 默认 profile从作品详情点“作品编辑”后开局 CG、封面、角色图、技能动作预览、初始物品图标或场景背景图丢失DevTools 里可能同时看到旧自动存档 `/api/runtime/save/snapshot` 被主动 cancel。
- 原因:`/custom-world-library` / `/custom-world-gallery` 详情接口可能返回历史或摘要式 `profile`,缺少 `playableNpcs``storyNpcs``landmarks``attributeSchema` 等运行态字段;前端 client 若直接把该对象传给 runtime角色选择首屏会在 `buildCustomWorldPlayableCharacters(profile)` 或后续属性解析处抛错。另一类常见原因是详情接口已回读完整 profile 后,`savedCustomWorldEntries` 里的列表摘要又把 `selectedDetailEntry` 覆盖回空 profile导致启动或编辑时只剩卡片摘要。发布 / 回读 result-view 若返回字段更少的旧视图,也可能把当前结果页已编辑资产降级掉。`save/snapshot (canceled)` 通常是切 runtime 或卸载时 `AbortController` 取消旧自动存档,不是黑屏根因。
- 处理RPG 入口作品库 client 在所有返回 `CustomWorldLibraryEntry<CustomWorldProfile>` 的接口边界统一调用 `normalizeCustomWorldProfileRecord`,并用 `profileId/worldName/subtitle/summaryText` 补齐旧数据缺字段;详情页已拿到运行态字段或资产槽位更多的完整 profile 时,不允许列表摘要覆盖当前详情;同一 `profile.id` 下,正式进入世界发布 / 回读不得用字段更少的后端旧视图降级当前结果页 profile。`normalizeCustomWorldProfileRecord` 必须近似无损保留 `cover``openingCg``camp.narrativeResidues``landmark.visualDescription/narrativeResidues``skills[].actionPreviewConfig``initialItems[].iconSrc``attributeSchema`、角色 `attributeProfile``sceneChapterBlueprints[].acts[]` 的背景与结构字段;只有背景资产的 act 也不能被过滤。角色选择页对角色生成异常或空数组回退默认角色,并保留返回按钮/轻量空态;顶层 runtime 懒加载 fallback 不使用纯 `null`
- 验证:`npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "creation hub published work start uses loaded detail profile instead of library summary|creation hub published work edit keeps loaded detail profile assets instead of library summary"``npm run test -- src/data/customWorldLibrary.test.ts -t "保留结果页封面和关键图片资产槽位|近似无损保留编辑态和运行态结构字段|保留只有背景资产的场景幕"``npm run test -- src/components/rpg-entry/useRpgEntryAgentDraftRestore.test.tsx -t "默认封面和角色编辑结构差异也不能被列表摘要覆盖"``npm run test -- src/components/rpg-entry/useRpgCreationEnterWorld.test.tsx -t "正式进入世界回读结果页字段更少时不降级当前完整 profile"``npm run typecheck`
- 关联:`src/components/rpg-entry/useRpgEntryLibraryDetail.ts``src/components/rpg-entry/useRpgCreationEnterWorld.ts``src/data/customWorldLibrary.ts``src/services/rpg-entry/rpgEntryLibraryClient.ts``src/components/rpg-entry/RpgEntryCharacterSelectView.tsx``src/App.tsx``src/components/rpg-runtime-shell/RpgRuntimeShell.tsx``docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`
## RPG 战后一轮战斗后卡在观察/试探/调息先查 post-battle finalization
- 现象RPG 一轮战斗胜利后,运行态只显示默认 `观察周围迹象 / 主动出声试探 / 原地调息`,这些按钮只有文字反馈;点“继续冒险”后又回到同样选项,点探索只播退场/进场动画,场景和剧情不推进。
- 原因:终局战斗 action 如果只走通用 `resolve_story_runtime_action` fallback而没有在后端调用 `finalize_post_battle_resolution(...)`,就不会持久写入 `story_continue_adventure``deferredOptions` 和下一幕 `currentSceneActState`。另外旧 bootstrap 快照可能只有 `connectedSceneIds` / `forwardSceneId`、没有 `connections`,战后选项生成若只读 `connections` 也会退回 `idle_explore_forward` 循环。
- 处理:`module-runtime-story` 在 story action 投影后统一调用 post-battle finalization`idle_explore_forward` 清理战斗态并生成下一段遭遇预览;`idle_travel_next_scene` / `camp_travel_home_scene` 由后端写入新 `currentScenePreset`、场景 act 状态、遭遇预览和 `runtimeStats.scenesTraveled`。前端只负责播放继续、探索和切场景动画,不承接正式剧情推进真相。
- 验证:`cargo test -p module-runtime-story --manifest-path server-rs\Cargo.toml battle_tests -- --nocapture` 应覆盖战斗终局持久化 `story_continue_adventure``deferredOptions`、下一幕 act以及 `idle_travel_next_scene` 真正切换场景。
- 关联:`server-rs/crates/module-runtime-story/src/session_action.rs``server-rs/crates/module-runtime-story/src/post_battle.rs``server-rs/crates/module-runtime-story/src/battle_tests.rs``docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`
## RPG 战斗飘字不要只靠低对比红绿文字
- 现象:暗色或棕黑噪声背景下,战斗伤害飘字看起来像背景纹理,尤其是远端敌人头顶的小号红字几乎不可读。
- 原因:旧 `CombatFloatingNumber` 主要依赖 `text-rose-200` / `text-emerald-200` 和 8px 同色 glow在暗红、棕黑、像素噪声背景上颜色与背景混在一起1px 深色描边也不足以形成轮廓。
- 处理:飘字本体使用高亮近白文字、小面积半透明深色底、明显深色描边和多层黑色阴影;只增强瞬时反馈,不新增说明面板,不遮挡主要战斗画面。
- 验证:`npm run test -- src/components/game-canvas/GameCanvasEntityLayer.test.tsx` 覆盖伤害/治疗飘字样式策略;运行态截图中敌方头顶伤害数字应能在暗场景上辨认。
- 关联:`src/components/game-canvas/GameCanvasEntityLayer.tsx``docs/【项目基线】当前产品与工程约束-2026-05-15.md`
## Windows provision 下载截断要断点续传而不是回退目标机下载
@@ -1119,3 +1135,11 @@
- 处理:打开草稿时把持久化 `generationStatus=generating` 等同于生成中 notice恢复对应玩法生成进度页恢复计时使用作品摘要 `updatedAt` 推导 `startedAtMs`
- 验证:`npm test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "persisted generating"`
- 关联:`src/components/platform-entry/PlatformEntryFlowShellImpl.tsx``src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx``docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`
## 存档选择入口不要只藏在“玩过”弹窗里
- 现象:用户有 RPG / 拼图运行态存档,但平台底部 `草稿` Tab 只展示作品架,个人中心只有点击 `玩过` 后才可能看到“可继续”,导致看起来没有存档选择入口。
- 原因:`/api/profile/save-archives` 已在入口 bootstrap 加载,但前端只把 `saveEntries` 注入 `ProfilePlayedWorksModal`;没有独立的存档入口。
- 处理:个人中心 `常用功能` 必须保留 `存档` 快捷入口,点击后打开独立存档选择弹窗并复用 `SaveArchiveCard`;恢复仍走 `/api/profile/save-archives/{worldKey}`,拼图存档继续走拼图 resume 分支RPG 走 `handleContinueGame(snapshot)`
- 验证:`npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "profile page exposes save archive picker"`
- 关联:`src/components/rpg-entry/RpgEntryHomeView.tsx``src/components/platform-entry/PlatformEntryFlowShellImpl.tsx``src/components/rpg-entry/useRpgEntryBootstrap.ts``docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`