fix: 完善拼消消模板运行规则

This commit is contained in:
2026-06-11 00:50:18 +08:00
parent c98c3de96d
commit 21ac5642e8
19 changed files with 1952 additions and 317 deletions

View File

@@ -120,6 +120,22 @@
- 验证:`npm run test -- src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.test.tsx`,浏览器里确认局部拼合会闪、完整消除会放大淡出、补牌在淡出后段才开始掉落。
- 关联:`src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.tsx``src/index.css``src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.test.tsx`
## 拼消消补牌下落叠层不能比动画提前卸载
- 现象:小牌补牌下落时看起来只是闪一下就切到目标格,下滑过程不连贯,途中还会闪出白色底。
- 原因:补牌叠层的清理时间只按消除动画固定时长计算,没有覆盖每张卡自己的下落延迟、下落距离时长和收尾缓冲;同时下落叠层曾带 `bg-white` / `border-white` 外壳,动画起点透明度和提亮滤镜会把外壳闪成白块。
- 处理:下落卡片按距离写入 `--puzzle-clear-drop-duration`,清理定时器取 `delay + duration + settle buffer` 的最大值CSS 下落动画使用 `translate3d`、轻微过冲和回弹,叠层保持透明、无边框、无亮度提升,只渲染真实卡片图。
- 验证:`npm run test -- src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.test.tsx src/index.test.ts`;浏览器里完整消除后新补入小牌应有连续下滑和轻微落位感,过程中不应出现白色闪块。
- 关联:`src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.tsx``src/index.css``src/index.test.ts``docs/technical/【玩法创作】拼消消玩法模板技术方案-2026-05-30.md`
## 拼消消替换飞行层要飞目标卡且不能带白底
- 现象:按下卡牌、拖动覆盖另一张卡并完成替换时,被替换的小卡在新位置先闪一下白底,然后才显示正确图像。
- 原因:替换飞行层如果复用被拖动的源卡,并且容器本身带 `background: white` / 白色边框,就会和拖拽 ghost 同向叠在目标格附近;真正应该回到源空位的目标卡没有覆盖源位空槽,视觉上就会露出白壳或白底。
- 处理:拖拽 ghost 只负责源卡落到目标格;`swapFlight` 必须使用被覆盖的 `target.card`,从目标格飞回源空位。飞行层容器保持透明、无边框,阴影只加在真实卡图上。
- 验证:`npm run test -- src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.test.tsx src/index.test.ts` 覆盖目标卡图片进入 `puzzle-clear-swap-flight`,并断言 `.puzzle-clear-swap-flight` 不再出现白底或白边。
- 关联:`src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.tsx``src/index.css``src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.test.tsx``src/index.test.ts`
## 首页推荐分流参数不能条件性调用 hook
- 现象:桌面首页或移动首页在 HMR、断点切换或重新渲染后直接报 React hook 顺序错误,页面停在“正在加载内容”。
@@ -1825,6 +1841,22 @@
- 验证:浏览器拖拽时能看到跟手 ghost、源位空槽、落点飞入和整组拼接层`src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.test.tsx` 应覆盖这些行为。
- 关联:`src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.tsx``src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.test.tsx``src/index.css`
## 拼消消整组拖拽越界要前端回弹,不要发无效 swap
- 现象:正式拼消消 runtime 玩到已有局部拼接组后把整组拖到棋盘边缘外侧前端弹出“puzzle-clear 坐标无效”,后端日志里对应 `/api/runtime/puzzle-clear/runs/{runId}/swap`
- 原因:后端 `move_locked_group` 会按整组平移后的每个格子做边界校验;前端早期只校验松手目标格存在,没有校验整组的其它格子是否会越界,因此会把后端必然拒绝的动作发出去。
- 处理:拖动带 `lockedGroupId` 的拼接组时,前端先用当前 board snapshot 计算 `rowDelta/colDelta`,确认组内所有格子平移后仍在棋盘内;越界时只播放回弹,不调用 `onSwapCards`。后端继续保留最终规则裁决;`puzzle-clear 坐标无效`、缺卡、非 playing、超时这类玩法动作校验错误应映射为 400避免误判为网关问题。
- 验证:`npm run test -- src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.test.tsx` 覆盖“已拼接局部拖到会越界的位置时只回弹不提交后端动作”;`cargo check -p api-server --manifest-path server-rs/Cargo.toml` 通过。
- 关联:`src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.tsx``src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.test.tsx``server-rs/crates/module-puzzle-clear/src/application.rs``server-rs/crates/api-server/src/puzzle_clear.rs`
## 拼消消多行局部拼合要按连通块整体锁定和拖起
- 现象:`2x2``2x3` 图案拼成 L 形、转角或多行局部后,玩家拖起已拼合组时会看到有一张卡没有被拿起,仍留在格子层里,并被格子白底或锁定组覆盖层压住。
- 原因:半锁定局部拼接组如果只按 `partY/partX` 排序后的线性相邻关系判断,会漏掉 2D 形状里的分叉 / 转角连通块;前端如果只隐藏起点和线性邻格,也会让未写入同一 `lockedGroupId` 的卡继续按普通格子层渲染。
- 处理:本地草稿 runtime 和 Rust `module-puzzle-clear` 都要按同组卡牌“素材坐标相邻且棋盘格相邻”的连通块识别半锁定组,`1x3``2x2``2x3` 的局部拼合必须整体写入同一个 `lockedGroupId`。前端拖起锁定组时,活动组覆盖层不再渲染;组内所有源格标记为 `drag-group-source`,格子层不渲染卡图,只保留透明空槽,卡图只出现在 `document.body` portal 里的 drag ghost。
- 验证:`npm run test -- src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.test.tsx src/services/puzzle-clear/puzzleClearLocalRuntime.test.ts``cargo test -p module-puzzle-clear --manifest-path server-rs/Cargo.toml`
- 关联:`src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.tsx``src/services/puzzle-clear/puzzleClearLocalRuntime.ts``server-rs/crates/module-puzzle-clear/src/application.rs``src/index.css`
## 拼消消空格位必须允许落位,不能当成不可交互死格
- 现象:运行到某一关后,棋盘里出现空格位,用户能看见空洞但拖不进去,也点不动。