1
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
2026-04-28 10:57:40 +08:00
parent bb4100fca4
commit a9febe7678
28 changed files with 1342 additions and 89 deletions

View File

@@ -0,0 +1,58 @@
# 拼图结果页自动保存与标签发布门槛修复
## 背景
拼图结果页此前存在两个串联问题:
1. 创作者在结果页修改 `关卡名`、新增标签、删除标签,只会改前端本地 `editState`,不会立即写回拼图作品 profile。
2. 发布弹窗同时混用了旧 session 内的 `publishReady` 与前端本地编辑态,导致标签已经在界面里补够,但发布校验仍然盯着旧草稿里的标签数量,用户无法通过发布检验。
这会直接破坏拼图创作主链的可用性:用户明明已经在结果页补齐正式标签,却因为没有自动保存、也没有按当前编辑态重算门槛而卡在发布前。
## 修复目标
1. 拼图结果页中的 `关卡名``添加标签``删除标签` 统一接入自动保存。
2. 自动保存复用现有 `PUT /api/runtime/puzzle/works/:profileId`,不新增新系统。
3. 前端发布门槛与后端 `module-puzzle` 规则显式对齐,统一采用 `3~6` 个正式标签。
4. 发布弹窗要基于“当前可编辑态”判断是否通过,不再被旧 session 中可由本地编辑修复的 blocker 卡死。
## 实现口径
### 1. 结果页自动保存
- `src/components/platform-entry/PlatformEntryFlowShellImpl.tsx`
- 为拼图结果页显式透传稳定 `profileId`
- 草稿结果页默认按 `puzzle-session-* -> puzzle-profile-*` 规则推导 profileId已发布作品优先复用 `publishedProfileId`
- `src/components/puzzle-result/PuzzleResultView.tsx`
-`levelName / summary / themeTags` 相对当前 `draft` 发生变化时,触发防抖自动保存。
- 自动保存复用 `updatePuzzleWork(...)`,同步写回:
- `levelName`
- `summary`
- `themeTags`
- 当前正式图 `coverImageSrc / coverAssetId`
- 顶部只展示轻量保存状态角标:`保存中 / 已自动保存 / 保存失败`
### 2. 发布门槛统一
- 前端结果页发布判定不再使用“至少 1 个标签”的旧口径。
- 统一改为和后端 `module-puzzle` 一致的规则:正式标签数量必须在 `3 到 6` 之间。
### 3. 结果页 blocker 重算策略
`session.resultPreview.blockers` 中与可编辑字段直接相关的 blocker
- `MISSING_LEVEL_NAME`
- `INVALID_TAG_COUNT`
- `MISSING_COVER_IMAGE`
这些项不再原样阻断前端发布按钮,而是改由结果页基于当前 `editState + formalImageSrc` 重新计算。
其余后端 blocker 仍继续保留,避免前端绕过真正不可编辑的发布门禁。
## 验收点
1. 修改拼图关卡名后,不点发布也会自动写回作品 profile。
2. 添加标签、删除标签后,不点发布也会自动写回作品 profile。
3. 标签少于 `3` 个时,发布弹窗明确提示“正式标签数量必须在 3 到 6 之间”。
4. 标签补到 `3~6` 个后,无需刷新页面即可通过前端发布校验。
5. 结果页顶部能看到轻量自动保存状态,不额外堆叠说明文案。

View File

@@ -4,6 +4,7 @@
## 文档列表
- [PUZZLE_RESULT_AUTOSAVE_AND_TAG_GATE_FIX_2026-04-28.md](./PUZZLE_RESULT_AUTOSAVE_AND_TAG_GATE_FIX_2026-04-28.md):记录拼图结果页名称与标签编辑自动保存、发布门槛统一到 `3~6` 标签,以及前端发布校验不再被旧 session blocker 卡死的修复口径。
- [SPACETIMEDB_START_SH_EARLY_EXIT_DIAGNOSTICS_2026-04-27.md](./SPACETIMEDB_START_SH_EARLY_EXIT_DIAGNOSTICS_2026-04-27.md):记录发布包 `start.sh` 只输出“SpacetimeDB 进程在就绪前退出”时的诊断补强,启动失败或超时时自动回显 `logs/spacetimedb.log``server ping`、端口监听和 root-dir 相关进程。
- [RPG_AND_AGENT_CHAT_TRUE_SSE_STREAMING_2026-04-26.md](./RPG_AND_AGENT_CHAT_TRUE_SSE_STREAMING_2026-04-26.md):记录 RPG 运行时 NPC 聊天、RPG/自定义世界 Agent 与大鱼 Agent 从“拼完整 SSE 字符串后一次性返回”改为 `mpsc + Sse<Event>` 真流式输出的后端落地口径。
- [SPACETIMEDB_START_SH_ROOT_OWNER_FALSE_POSITIVE_FIX_2026-04-27.md](./SPACETIMEDB_START_SH_ROOT_OWNER_FALSE_POSITIVE_FIX_2026-04-27.md):记录发布包 `start.sh` root-dir 占用检测把 `grep -F .../.spacetimedb` 误判为 SpacetimeDB 实例的根因、脚本修复和现场处理方式。

View File

@@ -96,6 +96,9 @@
4. 前端 `storyChoiceContinuation` / `useRpgRuntimeNpcInteraction`
- `fight_defeat` 不能再被当成“本地 NPC 战斗胜利”进入战后收束
- 玩家死亡后必须直接走死亡复活链,且复活时重置到开局场景第一幕,不能先推进下一幕
5. 前端 `postBattleFlow`
- 复活回到开局场景时,必须重新走首幕 encounter preview 恢复链
- 第一幕主交互 NPC 与同幕陪衬 NPC 要继续沿用既有场景槽位,不能退化成全部站成一排
## 继续收口2026-04-28
@@ -118,6 +121,24 @@
- 非 NPC 通用敌对战斗 `!inBattle`
5. 这样可以保证作品测试、幕预览与正式游戏在“死亡后回开局第一幕”这一口径上继续对齐
## 继续收口:复活后首幕 NPC 与站位恢复2026-04-28
在继续复测后,又确认死亡复活链还有一层表现问题:
1. 角色虽然已经回到开局场景第一幕;
2. 但复活态旧实现只是重置 `currentSceneActState`,没有重新恢复第一幕 encounter preview
3. 于是画布只能把第一幕 NPC 都按普通 ambient 角色绘制;
4. 视觉上就会表现为:
- 主交互 NPC 没有按首幕重新成为前景目标
- 同幕 NPC 失去原本的前后排关系
- 最终看起来像“所有人站成一排”
本轮补充修正如下:
1. `buildRevivedFirstSceneState(...)` 在重置到首幕之后,立即复用 `ensureSceneEncounterPreview(...)`
2. 这样复活链与“开局进入世界 / 场景正常进场”继续共用同一套首幕恢复逻辑
3. 第一幕主交互 NPC、同幕陪衬 NPC 与既有槽位会一起恢复,不再额外发明一套复活专用站位规则
## 结论
本次修复后RPG 战斗 compat 主链的胜负判定口径变为:

View File

@@ -200,3 +200,47 @@
1. 自定义世界角色型敌人在战斗态不会再重复叠加场景立绘下沉偏移;
2. 相关战斗编队、runtime gateway 与 battle plan 既有回归继续通过。
## 9. 本轮继续修正:战斗结束后和平态站位被战斗坐标污染
在前面解决“开战瞬间跳位”后,用户继续反馈战斗结束时敌对角色站位仍会被改掉。继续顺着 NPC 战斗收尾链核对后,确认这次的问题不在画布层,而在“战后恢复使用了哪一份 encounter 真相”。
### 9.1 根因梳理
此前 `fight_victory` 收尾时,恢复 `currentEncounter` 的优先级仍可能落到:
1. 战斗中的 `currentEncounter`
2. `activeBattleHostiles[0]?.encounter`
这两份 encounter 都已经是战斗态里被压到前排中心位后的数据,`xMeters` 往往已经变成 `3.2`。因此即使战前和平态 NPC 原本站在更靠后的场景位置,战斗结束后也会被错误恢复到战斗中心位,表现为“打完架后角色站位被改掉”。
### 9.2 本次收口
这次修正把“战前原始 encounter 保存”和“战后 encounter 恢复”两端一起收口:
1. `sceneEncounterPreviews.ts`
- NPC 自动开战时立即保存战前原始 encounter
- 复用现有 `sparReturnEncounter` 存槽,避免新增一套并行状态
2. `rpgRuntimeStoryGateway.ts`
- 若服务端战斗快照未带回 `sparReturnEncounter`
- 网关自动沿用进入战斗前的原始 NPC encounter 回填
3. `useRpgRuntimeNpcInteraction.ts`
- `fight_victory` 恢复和平态时,优先使用保存下来的战前 encounter
- 只在缺失时才退回到 battle encounter / fallback encounter
### 9.3 效果
这样处理后:
1. 战斗结束后恢复到场景中的 NPC会回到战前那份 encounter 对应的位置;
2. 不会再把战斗前排中心位误带回和平态;
3. `fight``spar` 两条 NPC 战斗收尾链恢复口径保持一致;
4. 作品测试、幕预览与正式运行的战后站位表现继续对齐。
### 9.4 验证
本轮新增并通过了以下回归验证:
1. 负好感 NPC 自动开战后会保存战前 encounter
2. `npc_fight` 服务端空战场快照桥接后会保留战前 encounter
3. `fight_victory` 收尾时会恢复战前 encounter而不是战斗态 encounter。