拆分规则阻断与搜索未命中状态弹窗
CustomWorldEntityCatalog 改用共享状态弹窗承接 minimum-playable 提示 PlatformEntryFlowShellImpl 将公开编号搜索未命中分支改用共享状态弹窗 保留命中用户摘要弹层布局并补充相关测试与文档记录
This commit is contained in:
@@ -47,6 +47,7 @@
|
||||
- 2026-06-10 追加:个人中心支付结果提示与支付确认遮罩统一抽到 `src/components/common/PlatformStatusDialog.tsx`,扫码面板统一抽到 `src/components/platform-entry/PlatformProfileQrScannerModal.tsx`;`RpgEntryHomeView` 只保留支付结果 kind 到 `success / loading / cancel / error` 的映射、确认遮罩开关和扫码结果写回,不再内联 profile 状态弹层壳层、二维码摄像头启动或 `BarcodeDetector` 轮询。后续 profile 侧同类“状态图标 + 标题正文 + 可选主动作”弹层优先复用 `PlatformStatusDialog`,扫码类弹层优先复用 `PlatformProfileQrScannerModal`。
|
||||
- 2026-06-10 追加:`PlatformStatusDialog` 支持自定义图标、图标可访问标签以及动作按钮 surface / size / className 透传,用来承接玩法结果页里保留品牌视觉但语义仍是“状态结果弹层”的场景;大鱼吃小鱼结果页的发布失败弹层已迁移到这套组件,业务页不再保留 `UnifiedConfirmDialog + PlatformIconBadge` 的专用组合。
|
||||
- 2026-06-10 追加:`PlatformStatusDialog` 继续支持 header notice 布局、body content、close button、backdrop / Escape 关闭路径,用来承接“提示 / 规则阻断 / 作品不可用 / 泥点不足”这类带标题栏的状态 notice;平台入口的 `draftGenerationPointNotice`、`workNotFoundRecoveryDialog` 和 RPG 大编辑器里的 `EditorNoticeDialog` 已迁移到这套共享组件,不再各自维护 `UnifiedConfirmDialog` 壳层和关闭策略。
|
||||
- 2026-06-10 追加:`CustomWorldEntityCatalog` 的 `minimum-playable` 规则阻断提示也统一迁到 `PlatformStatusDialog`,不再和删除角色 / 批量删除共用 `UnifiedConfirmDialog` 配置;同日平台入口公开编号搜索把 error 分支从用户摘要 modal 中拆出,未命中结果单独走 `PlatformStatusDialog`,命中用户继续保留 `UnifiedModal + PlatformSubpanel` 信息布局。
|
||||
- 2026-06-09 追加:通用输入 Composer 的上传参考图、发送和移除参考图已迁移到 `PlatformIconButton`;图标上传仍使用 `asChild="label"` 保留 label + file input 语义,公共组件会自动写入隐藏文本,确保内嵌 file input 继承可访问名称。
|
||||
- 2026-06-10 追加:creation-agent composer 的上传文档 / 上传参考图入口使用 `PlatformIconButton` 默认 `platformIcon`;工作台只保留动态 label、title、busy 状态和 picker 回调,发送按钮继续保留主题色动作布局。验证命令:`npm run test -- src/components/creation-agent/CreationAgentWorkspace.test.tsx src/components/common/PlatformIconButton.test.tsx`。
|
||||
- 2026-06-10 追加:作品详情顶部返回 / 分享和封面轮播上一张 / 下一张入口使用 `PlatformIconButton variant="platformIcon"`;详情页保留原 `platform-work-detail__*` 局部 class 控制位置和尺寸,点赞、复制三态等专用动作暂不迁移。验证命令:`npm run test -- src/components/platform-entry/PlatformWorkDetailView.test.tsx src/components/common/PlatformIconButton.test.tsx`。
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
19.3.18. RPG 首页个人中心的泥点账单、每日任务和兑换码三类标准 profile 弹层分别抽到 `src/components/platform-entry/PlatformProfileWalletLedgerModal.tsx`、`src/components/platform-entry/PlatformProfileTaskCenterModal.tsx` 与 `src/components/platform-entry/PlatformProfileRewardCodeRedeemModal.tsx`;账单继续复用 `PlatformProfileSecondaryModalShell`,任务和兑换码继续复用 `PlatformProfileModalShell`,页面不再内联账单余额 badge、任务领取列表和兑换码输入提交实现。三者均新增组件级测试,并继续复用 `RpgEntryHomeView.recharge.test.tsx` 的真实入口断言。验证命令:`npm run test -- src/components/platform-entry/PlatformProfileWalletLedgerModal.test.tsx src/components/platform-entry/PlatformProfileTaskCenterModal.test.tsx src/components/platform-entry/PlatformProfileRewardCodeRedeemModal.test.tsx src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "renders ledger entries with shared balance presentation|retries from the shared error state|renders claimable tasks and forwards claim action|keeps incomplete tasks disabled|submits on button click and enter key|disables submit when the code is blank|opens wallet ledger modal from narrative coin card|profile daily task shortcut reflects task progress and claim updates|wallet ledger modal shows empty and error states|opens reward code modal from profile action on mobile|create tab wallet chip opens reward code when recharge entry is hidden"`、`npm run typecheck`。
|
||||
19.3.19. RPG 首页个人中心的支付结果提示、支付确认遮罩与扫码面板继续向共享组件收口:支付结果 / 确认中弹层统一抽到 `src/components/common/PlatformStatusDialog.tsx`,扫码面板统一抽到 `src/components/platform-entry/PlatformProfileQrScannerModal.tsx`;`RpgEntryHomeView` 仅保留支付状态映射、扫码打开关闭和结果写回,不再内联 `RechargePaymentResultModal`、`RechargePaymentConfirmationMask`、`ProfileQrScannerModal`、`BarcodeDetector` 启动逻辑和 profile 弹层壳层参数。组件级验证新增 `src/components/common/PlatformStatusDialog.test.tsx` 与 `src/components/platform-entry/PlatformProfileQrScannerModal.test.tsx`,首页继续复用 `RpgEntryHomeView.recharge.test.tsx` 的支付 / 扫码入口断言。验证命令:`npm run test -- src/components/common/PlatformStatusDialog.test.tsx`、`npm run test -- src/components/platform-entry/PlatformProfileQrScannerModal.test.tsx`、`npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "profile recharge modal jumps to h5 payment on mobile web by default|profile recharge modal posts mini program payment request and reacts to success hash result|profile recharge modal releases submitting state and shows virtual payment failure detail|profile recharge modal eventually shows error text even when hashchange is not dispatched|profile recharge modal resumes virtual payment confirmation when pageshow returns with paid order|profile recharge modal blocks tab navigation while virtual payment confirmation is pending|profile scan action opens camera scanner instead of recharge panel"`、`npm run typecheck`。
|
||||
19.3.20. `PlatformStatusDialog` 继续扩展到 notice 场景:组件新增 header notice 布局、body content、close button、backdrop / Escape 关闭路径以及动作按钮样式透传;`PlatformEntryFlowShellImpl` 里的 `draftGenerationPointNotice` / `workNotFoundRecoveryDialog` 和 `RpgCreationEntityEditorShared.tsx` 里的 `EditorNoticeDialog` 已接入。创作入口泥点不足、作品不可用恢复和 RPG 大编辑器规则阻断提示不再各自维护 `UnifiedConfirmDialog` 壳层,只保留标题、正文、辅助提示和关闭回调。验证命令:`npm run test -- src/components/common/PlatformStatusDialog.test.tsx`、`npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "bark battle form checks mud points before creating a draft|puzzle form checks mud points before creating a draft|match3d form checks mud points before creating a draft|direct missing public work detail shows unified dialog before returning home"`、`npm run test -- src/components/CustomWorldEntityEditorModal.test.tsx -t "可扮演角色至少保留一个背景章节时使用统一提示弹窗|场景连接缺少可连接目标时使用统一提示弹窗|场景保存缺少主角色时使用统一提示弹窗"`、`npm run typecheck`。
|
||||
19.3.21. `PlatformStatusDialog` 继续收口规则阻断和搜索未命中提示:`CustomWorldEntityCatalog.tsx` 的 `minimum-playable` 规则阻断从删除确认分支中拆出,改由独立 `PlatformStatusDialog` 承接;`PlatformEntryFlowShellImpl` 的公开编号搜索弹层拆成“命中用户继续走 `UnifiedModal + PlatformSubpanel`”与“未找到结果改走 `PlatformStatusDialog`”两条分支。业务页不再让规则阻断提示和危险删除确认共用同一套 confirm config,也不再在搜索结果 modal 内同时维护用户信息和错误态两套内容布局。验证命令:`npm run test -- src/components/CustomWorldEntityEditorModal.test.tsx -t "最后一个可扮演角色不可删除时使用平台状态弹窗"`、`npm run test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "searching unmatched public work code shows not-found search result dialog|public code search shows public user summary in shared search result modal and clears it on close"`、`npm run typecheck`。
|
||||
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.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`。
|
||||
|
||||
@@ -29,6 +29,7 @@ import { PlatformMediaFrame } from './common/PlatformMediaFrame';
|
||||
import { PlatformPillBadge } from './common/PlatformPillBadge';
|
||||
import { PlatformProgressBar } from './common/PlatformProgressBar';
|
||||
import { PlatformStatGrid } from './common/PlatformStatGrid';
|
||||
import { PlatformStatusDialog } from './common/PlatformStatusDialog';
|
||||
import { PlatformStatusMessage } from './common/PlatformStatusMessage';
|
||||
import { PlatformSubpanel } from './common/PlatformSubpanel';
|
||||
import { PlatformTextField } from './common/PlatformTextField';
|
||||
@@ -934,20 +935,10 @@ export function CustomWorldEntityCatalog({
|
||||
};
|
||||
|
||||
const confirmDialogConfig = (() => {
|
||||
if (!confirmState) {
|
||||
if (!confirmState || confirmState.kind === 'minimum-playable') {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (confirmState.kind === 'minimum-playable') {
|
||||
return {
|
||||
title: '无法删除',
|
||||
confirmLabel: '知道了',
|
||||
confirmTone: 'primary' as const,
|
||||
showCancel: false,
|
||||
body: '至少保留一个可扮演角色,才能正常进入自定义世界。',
|
||||
};
|
||||
}
|
||||
|
||||
if (confirmState.kind === 'delete-playable') {
|
||||
return {
|
||||
title: '删除角色',
|
||||
@@ -1450,11 +1441,24 @@ export function CustomWorldEntityCatalog({
|
||||
confirmLabel={confirmDialogConfig.confirmLabel}
|
||||
confirmTone={confirmDialogConfig.confirmTone}
|
||||
showCancel={confirmDialogConfig.showCancel}
|
||||
closeOnBackdrop={confirmState?.kind !== 'minimum-playable'}
|
||||
>
|
||||
{confirmDialogConfig.body}
|
||||
</UnifiedConfirmDialog>
|
||||
) : null}
|
||||
{confirmState?.kind === 'minimum-playable' ? (
|
||||
<PlatformStatusDialog
|
||||
status="error"
|
||||
title="无法删除"
|
||||
description="至少保留一个可扮演角色,才能正常进入自定义世界。"
|
||||
onClose={closeConfirmDialog}
|
||||
closeOnBackdrop={false}
|
||||
action={{
|
||||
label: '知道了',
|
||||
onClick: closeConfirmDialog,
|
||||
surface: 'platform',
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1257,7 +1257,7 @@ test('可扮演角色删除改用统一确认弹窗', async () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('最后一个可扮演角色不可删除时使用统一提示弹窗', async () => {
|
||||
test('最后一个可扮演角色不可删除时使用平台状态弹窗', async () => {
|
||||
const user = userEvent.setup();
|
||||
const handleProfileChange = vi.fn();
|
||||
|
||||
@@ -1283,6 +1283,9 @@ test('最后一个可扮演角色不可删除时使用统一提示弹窗', async
|
||||
),
|
||||
).toBeTruthy();
|
||||
|
||||
fireEvent.click(dialog.parentElement as HTMLElement);
|
||||
expect(screen.getByRole('dialog', { name: '无法删除' })).toBeTruthy();
|
||||
|
||||
await user.click(within(dialog).getByRole('button', { name: '知道了' }));
|
||||
|
||||
expect(handleProfileChange).not.toHaveBeenCalled();
|
||||
|
||||
@@ -17079,7 +17079,32 @@ export function PlatformEntryFlowShellImpl({
|
||||
{pendingDeleteCreationWork?.detail}
|
||||
</UnifiedConfirmDialog>
|
||||
<AnimatePresence>
|
||||
{searchedPublicUser || publicSearchError ? (
|
||||
{publicSearchError ? (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
>
|
||||
<PlatformStatusDialog
|
||||
status="error"
|
||||
title="未找到结果"
|
||||
description="公开编号搜索"
|
||||
onClose={closePublicSearchResult}
|
||||
showHeader
|
||||
showCloseButton
|
||||
closeLabel="关闭搜索结果"
|
||||
overlayClassName={`platform-theme ${platformThemeClass} !items-center bg-black/45 !p-4`}
|
||||
panelClassName="platform-remap-surface rounded-[1.6rem]"
|
||||
action={{
|
||||
label: '知道了',
|
||||
onClick: closePublicSearchResult,
|
||||
surface: 'platform',
|
||||
}}
|
||||
>
|
||||
{publicSearchError}
|
||||
</PlatformStatusDialog>
|
||||
</motion.div>
|
||||
) : searchedPublicUser ? (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
@@ -17087,7 +17112,7 @@ export function PlatformEntryFlowShellImpl({
|
||||
>
|
||||
<UnifiedModal
|
||||
open
|
||||
title={publicSearchError ? '未找到结果' : '命中用户'}
|
||||
title="命中用户"
|
||||
description="公开编号搜索"
|
||||
onClose={closePublicSearchResult}
|
||||
closeOnBackdrop={false}
|
||||
@@ -17097,26 +17122,20 @@ export function PlatformEntryFlowShellImpl({
|
||||
overlayClassName={`platform-theme ${platformThemeClass} !items-center bg-black/45 !p-4`}
|
||||
panelClassName="platform-remap-surface rounded-[1.6rem]"
|
||||
>
|
||||
{publicSearchError ? (
|
||||
<PlatformStatusMessage tone="neutral" surface="platform" size="md">
|
||||
{publicSearchError}
|
||||
</PlatformStatusMessage>
|
||||
) : searchedPublicUser ? (
|
||||
<PlatformSubpanel
|
||||
as="section"
|
||||
surface="flat"
|
||||
radius="sm"
|
||||
padding="md"
|
||||
title={searchedPublicUser.displayName}
|
||||
titleVariant="strong"
|
||||
bodyClassName="mt-3"
|
||||
>
|
||||
<PlatformFieldLabel>陶泥号</PlatformFieldLabel>
|
||||
<div className="mt-1 text-sm font-semibold text-[var(--platform-text-base)]">
|
||||
{searchedPublicUser.publicUserCode}
|
||||
</div>
|
||||
</PlatformSubpanel>
|
||||
) : null}
|
||||
<PlatformSubpanel
|
||||
as="section"
|
||||
surface="flat"
|
||||
radius="sm"
|
||||
padding="md"
|
||||
title={searchedPublicUser.displayName}
|
||||
titleVariant="strong"
|
||||
bodyClassName="mt-3"
|
||||
>
|
||||
<PlatformFieldLabel>陶泥号</PlatformFieldLabel>
|
||||
<div className="mt-1 text-sm font-semibold text-[var(--platform-text-base)]">
|
||||
{searchedPublicUser.publicUserCode}
|
||||
</div>
|
||||
</PlatformSubpanel>
|
||||
</UnifiedModal>
|
||||
</motion.div>
|
||||
) : null}
|
||||
|
||||
Reference in New Issue
Block a user