继续收口拼图运行态阻断层

新增拼图下一关阻断层薄壳并接入 PlatformEntryFlowShellImpl
补充 PlatformUiKit 收口文档与共享决策记录
This commit is contained in:
2026-06-11 22:45:02 +08:00
parent f7404a07ef
commit 9d1dd493a6
5 changed files with 77 additions and 10 deletions

View File

@@ -2133,6 +2133,14 @@
- 验证方式:后台修改 `mudPointCost` 后保存,`GET /api/creation-entry/config` 返回同名数字字段;底部加号创作入口卡显示前端格式化后的泥点消耗;创作表单泥点不足提示和后端实际钱包扣费都使用该数字;关闭态卡片仍只显示 `暂未开放` - 验证方式:后台修改 `mudPointCost` 后保存,`GET /api/creation-entry/config` 返回同名数字字段;底部加号创作入口卡显示前端格式化后的泥点消耗;创作表单泥点不足提示和后端实际钱包扣费都使用该数字;关闭态卡片仍只显示 `暂未开放`
- 关联文档:`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md` - 关联文档:`docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`
## 2026-06-11 拼图与拼消消运行态剩余阻断层继续局部收口
- 背景:账号弹窗、拼图 runtime、抓大鹅结算、跳一跳结算和拼图 onboarding 收口后,允许范围内仍剩拼图“正在准备下一关”阻断层与拼消消 runtime 的等待 / 结算层各自手写 overlay它们结构相近但又都带着玩法本地语义。
- 决策:平台入口里的拼图“正在准备下一关”只在 `src/components/platform-entry/PlatformEntryFlowShellImpl/` 下新增 `PuzzleRuntimeBlockingOverlay.tsx` 做本地薄壳,继续复用 `UnifiedModal` 的遮罩、dialog 语义和关闭禁用策略,但不把这类运行态等待面板上推到 `common/`。拼消消 runtime 则在 `src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.tsx` 内新增 `PuzzleClearRuntimeOverlayShell``PuzzleClearRuntimePendingOverlay``PuzzleClearRuntimeSettlementDialog`,统一 `!activeRun``level_cleared``finished``level_failed` 三类局部 overlay 的结构和动作出口。拖拽 ghost、swap flight、补牌 / 消除动画和全屏 runtime 容器继续视为玩法专属视觉层,不算旧 modal 债务。
- 影响范围:`src/components/platform-entry/PlatformEntryFlowShellImpl.tsx``src/components/platform-entry/PlatformEntryFlowShellImpl/PuzzleRuntimeBlockingOverlay.tsx``src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.tsx`、相关测试与 PlatformUiKit 收口文档。
- 验证方式:`npm run test -- src/components/platform-entry/PlatformEntryFlowShellImpl/PuzzleRuntimeBlockingOverlay.test.tsx src/components/platform-entry/PlatformEntryFlowShellImpl.test.ts src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.test.tsx``npm run typecheck``npm run check:encoding``git diff --check`
- 关联文档:`docs/technical/【前端架构】PlatformUiKit弹窗组件收口计划-2026-06-08.md`
## 2026-05-31 拼消消底图 prompt 与 atlas 切片提示词收口 ## 2026-05-31 拼消消底图 prompt 与 atlas 切片提示词收口
- 背景:拼消消生成资产检查时,用户需要区分主题词、场地底图主题词和复合图 atlas prompt 的职责;若小图案显式画出切分线或边框,运行态 1x1 切片会显得像错误素材。 - 背景:拼消消生成资产检查时,用户需要区分主题词、场地底图主题词和复合图 atlas prompt 的职责;若小图案显式画出切分线或边框,运行态 1x1 切片会显得像错误素材。

View File

@@ -282,6 +282,7 @@
19.3.52. profile 白底 modal 里的摘要头、列表骨架和内容行继续沉到 `src/components/common/PlatformProfileSummaryHeader.tsx``src/components/common/PlatformProfileSkeletonList.tsx``src/components/common/PlatformProfileContentRow.tsx`;这三个 Module 只承接 `kicker + title + badge` 的摘要层次、重复 skeleton 列表行,以及 `PlatformSubpanel` 上的 `div / button` 内容行语义,不持有账单金额、任务进度、邀请用户信息、充值商品结构或 modal 状态切换逻辑。`PlatformProfileWalletLedgerModal.tsx``PlatformProfileTaskCenterModal.tsx``PlatformProfilePlayedWorksModal.tsx``PlatformProfileReferralModal.tsx``PlatformProfileRechargeModal.tsx` 已接入;后续 profile 副弹层若只是重复这三类白底内容骨架,优先继续复用这组薄组件,不再把 skeleton、摘要头和 row chrome 写回各自 modal。验证命令`npx vitest run src/components/common/PlatformProfileModalContent.shared.test.tsx src/components/platform-entry/PlatformProfileTaskCenterModal.test.tsx src/components/platform-entry/PlatformProfileWalletLedgerModal.test.tsx src/components/platform-entry/PlatformProfilePlayedWorksModal.test.tsx src/components/platform-entry/PlatformProfileReferralModal.test.tsx src/components/platform-entry/PlatformProfileRechargeModal.test.tsx``npm run typecheck``npm run check:encoding``git diff --check` 19.3.52. profile 白底 modal 里的摘要头、列表骨架和内容行继续沉到 `src/components/common/PlatformProfileSummaryHeader.tsx``src/components/common/PlatformProfileSkeletonList.tsx``src/components/common/PlatformProfileContentRow.tsx`;这三个 Module 只承接 `kicker + title + badge` 的摘要层次、重复 skeleton 列表行,以及 `PlatformSubpanel` 上的 `div / button` 内容行语义,不持有账单金额、任务进度、邀请用户信息、充值商品结构或 modal 状态切换逻辑。`PlatformProfileWalletLedgerModal.tsx``PlatformProfileTaskCenterModal.tsx``PlatformProfilePlayedWorksModal.tsx``PlatformProfileReferralModal.tsx``PlatformProfileRechargeModal.tsx` 已接入;后续 profile 副弹层若只是重复这三类白底内容骨架,优先继续复用这组薄组件,不再把 skeleton、摘要头和 row chrome 写回各自 modal。验证命令`npx vitest run src/components/common/PlatformProfileModalContent.shared.test.tsx src/components/platform-entry/PlatformProfileTaskCenterModal.test.tsx src/components/platform-entry/PlatformProfileWalletLedgerModal.test.tsx src/components/platform-entry/PlatformProfilePlayedWorksModal.test.tsx src/components/platform-entry/PlatformProfileReferralModal.test.tsx src/components/platform-entry/PlatformProfileRechargeModal.test.tsx``npm run typecheck``npm run check:encoding``git diff --check`
19.3.53. 认证入口白底弹窗壳层收口到 `src/components/auth/PlatformAuthModalShell.tsx`;该 Module 只承接平台主题 overlay、`platform-auth-card`、标准标题栏、关闭按钮、点击遮罩关闭和禁用 Escape 的认证弹窗策略,不持有短信 / 密码登录、重置密码、邀请码规范化、法律协议或错误状态。`LoginScreen.tsx``RegistrationInviteModal.tsx` 已接入,业务组件只保留表单状态与提交流程。后续认证域新增同形态白底弹窗时优先复用该壳层;账号安全详情和绑定手机号这类布局差异较大的卡片先独立评估,不把 auth shell 扩成万能认证容器。验证命令:`npx vitest run src/components/auth/PlatformAuthModalShell.test.tsx src/components/auth/AuthGate.test.tsx``npm run typecheck``npm run check:encoding``git diff --check` 19.3.53. 认证入口白底弹窗壳层收口到 `src/components/auth/PlatformAuthModalShell.tsx`;该 Module 只承接平台主题 overlay、`platform-auth-card`、标准标题栏、关闭按钮、点击遮罩关闭和禁用 Escape 的认证弹窗策略,不持有短信 / 密码登录、重置密码、邀请码规范化、法律协议或错误状态。`LoginScreen.tsx``RegistrationInviteModal.tsx` 已接入,业务组件只保留表单状态与提交流程。后续认证域新增同形态白底弹窗时优先复用该壳层;账号安全详情和绑定手机号这类布局差异较大的卡片先独立评估,不把 auth shell 扩成万能认证容器。验证命令:`npx vitest run src/components/auth/PlatformAuthModalShell.test.tsx src/components/auth/AuthGate.test.tsx``npm run typecheck``npm run check:encoding``git diff --check`
19.3.54. 账号 / 运行态 / onboarding 这轮继续分场景收口:`AccountModal.tsx` 的设置入口外层 overlay 与 auth card 壳层复用 `PlatformAuthModalShell`,并通过 `overlaySpacing``overlayStyle``showHeader` 和尺寸透传保留账号弹窗的 safe-area 与 direct account 唯一 dialog 语义;拼图运行态新增 `src/components/puzzle-runtime/PuzzleRuntimeModalShell.tsx`,只在 `puzzle-runtime` 内承接道具确认、设置、退出改造提示、失败弹窗和通关结算的 overlay / dialog / footer / button 骨架,原图查看、拖拽 ghost、飞行动画和全屏 runtime 容器不纳入 modal 收口;抓大鹅与跳一跳结算弹窗分别在 `Match3DRuntimeShell.tsx``JumpHopRuntimeShell.tsx` 内提取本地结算壳层 / summary / actions保留玩法视觉身份拼图 onboarding 首屏继续保留沉浸式全屏体验,只把登录保存覆盖层迁入 `UnifiedModal`,保持无关闭按钮、禁用遮罩关闭和禁用 Escape。后续 runtime 专属弹窗优先先抽玩法目录内薄壳;只有出现跨玩法稳定同构接口时再上升到 `common/`,不要把 `PlatformToolModalShell` 强行套到像素 / 游戏运行态 overlay。验证命令`npm run test -- src/components/auth/AccountModal.test.tsx src/components/auth/PlatformAuthModalShell.test.tsx src/components/platform-entry/PlatformEntryFlowShellImpl/PuzzleOnboardingView.test.tsx src/components/match3d-runtime/Match3DRuntimeShell.test.tsx src/components/jump-hop-runtime/JumpHopRuntimeShell.test.tsx src/components/puzzle-runtime/PuzzleRuntimeShell.test.tsx``npm run typecheck``npm run check:encoding``git diff --check` 19.3.54. 账号 / 运行态 / onboarding 这轮继续分场景收口:`AccountModal.tsx` 的设置入口外层 overlay 与 auth card 壳层复用 `PlatformAuthModalShell`,并通过 `overlaySpacing``overlayStyle``showHeader` 和尺寸透传保留账号弹窗的 safe-area 与 direct account 唯一 dialog 语义;拼图运行态新增 `src/components/puzzle-runtime/PuzzleRuntimeModalShell.tsx`,只在 `puzzle-runtime` 内承接道具确认、设置、退出改造提示、失败弹窗和通关结算的 overlay / dialog / footer / button 骨架,原图查看、拖拽 ghost、飞行动画和全屏 runtime 容器不纳入 modal 收口;抓大鹅与跳一跳结算弹窗分别在 `Match3DRuntimeShell.tsx``JumpHopRuntimeShell.tsx` 内提取本地结算壳层 / summary / actions保留玩法视觉身份拼图 onboarding 首屏继续保留沉浸式全屏体验,只把登录保存覆盖层迁入 `UnifiedModal`,保持无关闭按钮、禁用遮罩关闭和禁用 Escape。后续 runtime 专属弹窗优先先抽玩法目录内薄壳;只有出现跨玩法稳定同构接口时再上升到 `common/`,不要把 `PlatformToolModalShell` 强行套到像素 / 游戏运行态 overlay。验证命令`npm run test -- src/components/auth/AccountModal.test.tsx src/components/auth/PlatformAuthModalShell.test.tsx src/components/platform-entry/PlatformEntryFlowShellImpl/PuzzleOnboardingView.test.tsx src/components/match3d-runtime/Match3DRuntimeShell.test.tsx src/components/jump-hop-runtime/JumpHopRuntimeShell.test.tsx src/components/puzzle-runtime/PuzzleRuntimeShell.test.tsx``npm run typecheck``npm run check:encoding``git diff --check`
19.3.55. 拼图 / 拼消消运行态的剩余阻断层继续按玩法目录局部收口:`src/components/platform-entry/PlatformEntryFlowShellImpl/PuzzleRuntimeBlockingOverlay.tsx` 只承接平台入口里拼图“正在准备下一关”的短暂阻断层,继续复用 `UnifiedModal` 的遮罩、dialog 语义和关闭禁用策略,但不把这类运行态等待面板直接提升到 `common/``src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.tsx` 则在玩法目录内新增 `PuzzleClearRuntimeOverlayShell``PuzzleClearRuntimePendingOverlay``PuzzleClearRuntimeSettlementDialog`,把 `!activeRun` 的等待层和 `level_cleared / finished / level_failed` 的结算层统一成一条本地结构线,同时保留拼消消自己的视觉和动作分流。拖拽 ghost、swap flight、补牌 / 消除动画、全屏 runtime 容器和其它强玩法视觉层不算旧 modal 债务,不跟这条线混收。验证命令:`npm run test -- src/components/platform-entry/PlatformEntryFlowShellImpl/PuzzleRuntimeBlockingOverlay.test.tsx src/components/platform-entry/PlatformEntryFlowShellImpl.test.ts src/components/puzzle-clear-runtime/PuzzleClearRuntimeShell.test.tsx``npm run typecheck``npm run check:encoding``git diff --check`
19.3. creative-agent 首页的侧边栏菜单、账号入口、开启新对话、我的创作、首页激励 CTA 和 prompt suggestion 按钮迁移到 `PlatformIconButton` / `PlatformActionButton`;首页继续保留 `creative-agent-home__*` 本地 class 承接透明顶栏、抽屉和品牌化胶囊视觉,不把视觉回收和语义收口绑成一次大改。`Beta` 徽标和历史记录纯文本行暂保留本地实现,等出现更多同构轻量列表行后再评估是否抽新的共享 row primitive。 19.3. creative-agent 首页的侧边栏菜单、账号入口、开启新对话、我的创作、首页激励 CTA 和 prompt suggestion 按钮迁移到 `PlatformIconButton` / `PlatformActionButton`;首页继续保留 `creative-agent-home__*` 本地 class 承接透明顶栏、抽屉和品牌化胶囊视觉,不把视觉回收和语义收口绑成一次大改。`Beta` 徽标和历史记录纯文本行暂保留本地实现,等出现更多同构轻量列表行后再评估是否抽新的共享 row primitive。
19.4. 大鱼吃小鱼结果页 hero 的返回入口迁移到 `PlatformIconButton variant="darkMini"`,测试 / 发布动作迁移到 `PlatformActionButton surface="editorDark"`;结果页只保留测试运行、发布提交和文案状态语义,不再手写 hero 顶栏按钮壳。 19.4. 大鱼吃小鱼结果页 hero 的返回入口迁移到 `PlatformIconButton variant="darkMini"`,测试 / 发布动作迁移到 `PlatformActionButton surface="editorDark"`;结果页只保留测试运行、发布提交和文案状态语义,不再手写 hero 顶栏按钮壳。
19.4.1. 大鱼吃小鱼结果页的发布失败弹层迁移到 `src/components/common/PlatformStatusDialog.tsx``PlatformStatusDialog` 补充自定义图标、可访问标签和动作按钮样式透传后,`BigFishResultView` 不再保留 `BigFishResultErrorModal` 内联的 `UnifiedConfirmDialog + PlatformIconBadge` 组合。结果页只保留失败文案和关闭回调,发布失败的状态图标、遮罩、白底面板和“知道了”主动作统一由共享状态弹层承接。验证命令:`npm run test -- src/components/common/PlatformStatusDialog.test.tsx src/components/big-fish-result/BigFishResultView.test.tsx``npm run typecheck` 19.4.1. 大鱼吃小鱼结果页的发布失败弹层迁移到 `src/components/common/PlatformStatusDialog.tsx``PlatformStatusDialog` 补充自定义图标、可访问标签和动作按钮样式透传后,`BigFishResultView` 不再保留 `BigFishResultErrorModal` 内联的 `UnifiedConfirmDialog + PlatformIconBadge` 组合。结果页只保留失败文案和关闭回调,发布失败的状态图标、遮罩、白底面板和“知道了”主动作统一由共享状态弹层承接。验证命令:`npm run test -- src/components/common/PlatformStatusDialog.test.tsx src/components/big-fish-result/BigFishResultView.test.tsx``npm run typecheck`

View File

@@ -1,4 +1,3 @@
import { Loader2 } from 'lucide-react';
import { AnimatePresence, motion } from 'motion/react'; import { AnimatePresence, motion } from 'motion/react';
import { import {
type Dispatch, type Dispatch,
@@ -514,6 +513,7 @@ import {
type PuzzleOnboardingPhase, type PuzzleOnboardingPhase,
PuzzleOnboardingView, PuzzleOnboardingView,
} from './PlatformEntryFlowShellImpl/PuzzleOnboardingView'; } from './PlatformEntryFlowShellImpl/PuzzleOnboardingView';
import { PuzzleRuntimeBlockingOverlay } from './PlatformEntryFlowShellImpl/PuzzleRuntimeBlockingOverlay';
import { import {
PlatformEntryHomeView, PlatformEntryHomeView,
type PlatformHomeTab, type PlatformHomeTab,
@@ -16561,15 +16561,10 @@ export function PlatformEntryFlowShellImpl({
/> />
</Suspense> </Suspense>
{isPuzzleNextLevelGenerating ? ( {isPuzzleNextLevelGenerating ? (
<div className="fixed inset-0 z-[120] flex items-center justify-center bg-slate-950/62 px-5 backdrop-blur-sm"> <PuzzleRuntimeBlockingOverlay
<div className="flex max-w-[18rem] flex-col items-center gap-3 rounded-[1.5rem] border border-white/12 bg-slate-950/92 px-6 py-5 text-center text-white shadow-[0_28px_80px_rgba(0,0,0,0.35)]"> title="正在准备下一关"
<Loader2 className="h-6 w-6 animate-spin text-amber-200" /> description="广场暂无可接续作品,正在生成新的候选图。"
<div className="text-sm font-bold"></div> />
<div className="text-xs leading-5 text-white/68">
广
</div>
</div>
</div>
) : null} ) : null}
{puzzleOnboardingDraft && {puzzleOnboardingDraft &&
puzzleRun?.currentLevel?.status === 'cleared' ? ( puzzleRun?.currentLevel?.status === 'cleared' ? (

View File

@@ -0,0 +1,24 @@
/* @vitest-environment jsdom */
import { render, screen } from '@testing-library/react';
import { describe, expect, test } from 'vitest';
import { PuzzleRuntimeBlockingOverlay } from './PuzzleRuntimeBlockingOverlay';
describe('PuzzleRuntimeBlockingOverlay', () => {
test('展示阻断标题与说明,并关闭背景与 Escape 关闭', () => {
render(
<PuzzleRuntimeBlockingOverlay
title="正在准备下一关"
description="广场暂无可接续作品,正在生成新的候选图。"
/>,
);
expect(screen.getByRole('dialog', { name: '正在准备下一关' })).toBeTruthy();
expect(screen.getByText('正在准备下一关')).toBeTruthy();
expect(
screen.getByText('广场暂无可接续作品,正在生成新的候选图。'),
).toBeTruthy();
expect(screen.queryByRole('button', { name: '关闭' })).toBeNull();
});
});

View File

@@ -0,0 +1,39 @@
import { Loader2 } from 'lucide-react';
import { UnifiedModal } from '../../common/UnifiedModal';
type PuzzleRuntimeBlockingOverlayProps = {
title: string;
description: string;
};
/**
* 拼图运行态局部阻断层壳子。
* 仅承接平台入口里拼图运行态的短暂等待态,不把玩法局部视觉强行上推到 common。
*/
export function PuzzleRuntimeBlockingOverlay({
title,
description,
}: PuzzleRuntimeBlockingOverlayProps) {
return (
<UnifiedModal
open
title={title}
onClose={() => undefined}
portal={false}
showHeader={false}
showCloseButton={false}
closeOnBackdrop={false}
closeOnEscape={false}
size="sm"
zIndexClassName="z-[120]"
overlayClassName="!items-center bg-slate-950/62 !px-5 !py-6 text-white backdrop-blur-sm"
panelClassName="!max-w-[18rem] !rounded-[1.5rem] border border-white/12 bg-slate-950/92 text-white shadow-[0_28px_80px_rgba(0,0,0,0.35)]"
bodyClassName="flex flex-col items-center gap-3 !px-6 !py-5 text-center"
>
<Loader2 className="h-6 w-6 animate-spin text-amber-200" />
<div className="text-sm font-bold">{title}</div>
<div className="text-xs leading-5 text-white/68">{description}</div>
</UnifiedModal>
);
}