扩展状态弹窗承接提示类 notice

扩展 PlatformStatusDialog 支持标题栏提示与关闭路径
PlatformEntryFlowShellImpl 改用共享状态弹窗承接泥点提示与作品不可用提示
RpgCreationEntityEditorShared 改用共享状态弹窗承接编辑器提示
补充状态弹窗与编辑器提示测试并更新文档记录
This commit is contained in:
2026-06-10 20:52:34 +08:00
parent 547e771f75
commit a076faf652
7 changed files with 127 additions and 25 deletions

View File

@@ -46,6 +46,7 @@
- 2026-06-10 追加RPG 首页个人中心的泥点账单、每日任务和兑换码弹层统一抽到 `src/components/platform-entry/PlatformProfileWalletLedgerModal.tsx``src/components/platform-entry/PlatformProfileTaskCenterModal.tsx``src/components/platform-entry/PlatformProfileRewardCodeRedeemModal.tsx``RpgEntryHomeView` 只保留打开条件和数据流,标准 profile 弹层内容以后优先沉到 `platform-entry` 独立组件,不在首页继续堆叠。 - 2026-06-10 追加RPG 首页个人中心的泥点账单、每日任务和兑换码弹层统一抽到 `src/components/platform-entry/PlatformProfileWalletLedgerModal.tsx``src/components/platform-entry/PlatformProfileTaskCenterModal.tsx``src/components/platform-entry/PlatformProfileRewardCodeRedeemModal.tsx``RpgEntryHomeView` 只保留打开条件和数据流,标准 profile 弹层内容以后优先沉到 `platform-entry` 独立组件,不在首页继续堆叠。
- 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 追加:个人中心支付结果提示与支付确认遮罩统一抽到 `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` 支持自定义图标、图标可访问标签以及动作按钮 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-09 追加:通用输入 Composer 的上传参考图、发送和移除参考图已迁移到 `PlatformIconButton`;图标上传仍使用 `asChild="label"` 保留 label + file input 语义,公共组件会自动写入隐藏文本,确保内嵌 file input 继承可访问名称。 - 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 追加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` - 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`

View File

@@ -241,6 +241,7 @@
19.3.17. RPG 首页个人中心的账户充值弹层抽到 `src/components/platform-entry/PlatformProfileRechargeModal.tsx`;组件承接 Native 二维码生成、点数 / 会员 tab、套餐卡片、空态和错误重试继续复用 `PlatformProfileModalShell` 与平台白底卡片 token`RpgEntryHomeView` 不再内联 `useWechatNativeQrCode``RechargeProductCard``ProfileRechargeModal`。组件级验证新增 `src/components/platform-entry/PlatformProfileRechargeModal.test.tsx`,首页继续复用 `RpgEntryHomeView.recharge.test.tsx` 的充值入口与 Native 二维码断言。验证命令:`npm run test -- src/components/platform-entry/PlatformProfileRechargeModal.test.tsx src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "renders point products and forwards buy action|shows empty state when the selected tab has no products|profile recharge modal shows native qr code on desktop web by default|create tab wallet chip opens recharge when recharge entry is enabled"``npm run typecheck` 19.3.17. RPG 首页个人中心的账户充值弹层抽到 `src/components/platform-entry/PlatformProfileRechargeModal.tsx`;组件承接 Native 二维码生成、点数 / 会员 tab、套餐卡片、空态和错误重试继续复用 `PlatformProfileModalShell` 与平台白底卡片 token`RpgEntryHomeView` 不再内联 `useWechatNativeQrCode``RechargeProductCard``ProfileRechargeModal`。组件级验证新增 `src/components/platform-entry/PlatformProfileRechargeModal.test.tsx`,首页继续复用 `RpgEntryHomeView.recharge.test.tsx` 的充值入口与 Native 二维码断言。验证命令:`npm run test -- src/components/platform-entry/PlatformProfileRechargeModal.test.tsx src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "renders point products and forwards buy action|shows empty state when the selected tab has no products|profile recharge modal shows native qr code on desktop web by default|create tab wallet chip opens recharge when recharge entry is enabled"``npm run typecheck`
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.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.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. 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

@@ -2,6 +2,7 @@
import { import {
cleanup, cleanup,
fireEvent,
render, render,
screen, screen,
waitFor, waitFor,
@@ -857,11 +858,15 @@ test('可扮演角色至少保留一个背景章节时使用统一提示弹窗',
await user.click(deleteChapterButtons()[0]!); await user.click(deleteChapterButtons()[0]!);
const dialog = await screen.findByRole('dialog', { name: '提示' }); const dialog = await screen.findByRole('dialog', { name: '提示' });
const actionButton = within(dialog).getByRole('button', { name: '知道了' });
expect(within(dialog).getByText('至少保留一个背景章节。')).toBeTruthy(); expect(within(dialog).getByText('至少保留一个背景章节。')).toBeTruthy();
expect(dialog.querySelector('.platform-icon-badge')).toBeTruthy();
expect(actionButton.className).toContain('platform-button');
expect(alertSpy).not.toHaveBeenCalled(); expect(alertSpy).not.toHaveBeenCalled();
expect(screen.getByText('编辑角色:沈砺')).toBeTruthy(); expect(screen.getByText('编辑角色:沈砺')).toBeTruthy();
await user.click(within(dialog).getByRole('button', { name: '知道了' })); await user.click(actionButton);
await waitFor(() => { await waitFor(() => {
expect(screen.queryByRole('dialog', { name: '提示' })).toBeNull(); expect(screen.queryByRole('dialog', { name: '提示' })).toBeNull();
}); });
@@ -1798,12 +1803,15 @@ test('场景连接缺少可连接目标时使用统一提示弹窗', async () =>
await user.click(screen.getByText('北')); await user.click(screen.getByText('北'));
const dialog = await screen.findByRole('dialog', { name: '提示' }); const dialog = await screen.findByRole('dialog', { name: '提示' });
const overlay = dialog.parentElement as HTMLElement;
expect( expect(
within(dialog).getByText('请先保留至少一个其他场景,才能配置连接关系。'), within(dialog).getByText('请先保留至少一个其他场景,才能配置连接关系。'),
).toBeTruthy(); ).toBeTruthy();
expect(overlay.className).toContain('rpg-editor-notice-dialog-overlay');
expect(alertSpy).not.toHaveBeenCalled(); expect(alertSpy).not.toHaveBeenCalled();
await user.click(within(dialog).getByRole('button', { name: '知道了' })); fireEvent.click(overlay);
await waitFor(() => { await waitFor(() => {
expect(screen.queryByRole('dialog', { name: '提示' })).toBeNull(); expect(screen.queryByRole('dialog', { name: '提示' })).toBeNull();
}); });
@@ -2000,6 +2008,11 @@ test('场景保存缺少主角色时使用统一提示弹窗', async () => {
expect(alertSpy).not.toHaveBeenCalled(); expect(alertSpy).not.toHaveBeenCalled();
expect(screen.getByText('编辑场景:空港栈桥')).toBeTruthy(); expect(screen.getByText('编辑场景:空港栈桥')).toBeTruthy();
fireEvent.keyDown(window, { key: 'Escape' });
await waitFor(() => {
expect(screen.queryByRole('dialog', { name: '提示' })).toBeNull();
});
alertSpy.mockRestore(); alertSpy.mockRestore();
}); });

View File

@@ -96,3 +96,37 @@ test('supports custom badge icon label and action button styling', () => {
expect(action.className).toContain('border-slate-950'); expect(action.className).toContain('border-slate-950');
expect(action.className).toContain('bg-slate-950'); expect(action.className).toContain('bg-slate-950');
}); });
test('supports header notice layout with body content and close button', () => {
const onClose = vi.fn();
render(
<PlatformStatusDialog
status="error"
title="泥点不足"
description="当前表单不会丢失,关闭后可继续编辑或补足泥点再继续。"
onClose={onClose}
showHeader
showCloseButton
closeOnBackdrop
action={{ label: '知道了', onClick: onClose, surface: 'platform' }}
>
6 5
</PlatformStatusDialog>,
);
const dialog = screen.getByRole('dialog', { name: '泥点不足' });
expect(
dialog.querySelector('.mt-4.text-xl.font-black.text-\\[var\\(--platform-text-strong\\)\\]'),
).toBeNull();
expect(screen.getByText('本次需要 6 泥点,当前 5 泥点。')).toBeTruthy();
expect(
screen.getByText(
'当前表单不会丢失,关闭后可继续编辑或补足泥点再继续。',
),
).toBeTruthy();
fireEvent.click(screen.getByRole('button', { name: '关闭' }));
expect(onClose).toHaveBeenCalledTimes(1);
});

View File

@@ -39,8 +39,15 @@ type PlatformStatusDialogProps = {
status: PlatformStatusDialogStatus; status: PlatformStatusDialogStatus;
title: string; title: string;
description?: ReactNode; description?: ReactNode;
children?: ReactNode;
onClose: () => void; onClose: () => void;
action?: PlatformStatusDialogAction; action?: PlatformStatusDialogAction;
showHeader?: boolean;
showBodyTitle?: boolean;
showCloseButton?: boolean;
closeOnBackdrop?: boolean;
closeOnEscape?: boolean;
closeLabel?: string;
closeDisabled?: boolean; closeDisabled?: boolean;
zIndexClassName?: string; zIndexClassName?: string;
overlayClassName?: string; overlayClassName?: string;
@@ -101,8 +108,15 @@ export function PlatformStatusDialog({
status, status,
title, title,
description, description,
children,
onClose, onClose,
action, action,
showHeader = false,
showBodyTitle,
showCloseButton = false,
closeOnBackdrop = false,
closeOnEscape = false,
closeLabel,
closeDisabled = false, closeDisabled = false,
zIndexClassName = 'z-[90]', zIndexClassName = 'z-[90]',
overlayClassName = DEFAULT_OVERLAY_CLASS, overlayClassName = DEFAULT_OVERLAY_CLASS,
@@ -114,24 +128,26 @@ export function PlatformStatusDialog({
}: PlatformStatusDialogProps) { }: PlatformStatusDialogProps) {
const visualConfig = getStatusVisualConfig(status); const visualConfig = getStatusVisualConfig(status);
const badgeIcon = icon ?? visualConfig.icon; const badgeIcon = icon ?? visualConfig.icon;
const shouldRenderBodyTitle = showBodyTitle ?? !showHeader;
return ( return (
<UnifiedModal <UnifiedModal
open={open} open={open}
title={title} title={title}
onClose={onClose} onClose={onClose}
showHeader={false} showHeader={showHeader}
showCloseButton={false} showCloseButton={showCloseButton}
closeLabel={closeLabel}
closeDisabled={closeDisabled} closeDisabled={closeDisabled}
closeOnBackdrop={false} closeOnBackdrop={closeOnBackdrop}
closeOnEscape={false} closeOnEscape={closeOnEscape}
portal={false} portal={false}
size="sm" size="sm"
zIndexClassName={zIndexClassName} zIndexClassName={zIndexClassName}
overlayClassName={overlayClassName} overlayClassName={overlayClassName}
panelClassName={panelClassName} panelClassName={panelClassName}
bodyClassName={bodyClassName} bodyClassName={bodyClassName}
> >
<PlatformIconBadge <PlatformIconBadge
icon={badgeIcon} icon={badgeIcon}
label={iconLabel} label={iconLabel}
@@ -145,9 +161,16 @@ export function PlatformStatusDialog({
.filter(Boolean) .filter(Boolean)
.join(' ')} .join(' ')}
/> />
<div className="mt-4 text-xl font-black text-[var(--platform-text-strong)]"> {shouldRenderBodyTitle ? (
{title} <div className="mt-4 text-xl font-black text-[var(--platform-text-strong)]">
</div> {title}
</div>
) : null}
{children ? (
<div className="mt-3 text-sm font-semibold leading-6 text-[var(--platform-text-base)]">
{children}
</div>
) : null}
{description ? ( {description ? (
<div className="mt-3 text-sm font-semibold leading-6 text-[var(--platform-text-soft)]"> <div className="mt-3 text-sm font-semibold leading-6 text-[var(--platform-text-soft)]">
{description} {description}

View File

@@ -365,6 +365,7 @@ import type { CustomWorldProfile } from '../../types';
import { useAuthUi } from '../auth/AuthUiContext'; import { useAuthUi } from '../auth/AuthUiContext';
import { PlatformActionButton } from '../common/PlatformActionButton'; import { PlatformActionButton } from '../common/PlatformActionButton';
import { PlatformFieldLabel } from '../common/PlatformFieldLabel'; import { PlatformFieldLabel } from '../common/PlatformFieldLabel';
import { PlatformStatusDialog } from '../common/PlatformStatusDialog';
import { PlatformStatusMessage } from '../common/PlatformStatusMessage'; import { PlatformStatusMessage } from '../common/PlatformStatusMessage';
import { PlatformSubpanel } from '../common/PlatformSubpanel'; import { PlatformSubpanel } from '../common/PlatformSubpanel';
import { PublishShareModal } from '../common/PublishShareModal'; import { PublishShareModal } from '../common/PublishShareModal';
@@ -16996,19 +16997,30 @@ export function PlatformEntryFlowShellImpl({
}} }}
/> />
) : null} ) : null}
<UnifiedConfirmDialog <PlatformStatusDialog
open={Boolean(draftGenerationPointNotice)} open={Boolean(draftGenerationPointNotice)}
status="error"
title={draftGenerationPointNotice?.title ?? '泥点提示'} title={draftGenerationPointNotice?.title ?? '泥点提示'}
description={draftGenerationPointNoticeDescription} description={draftGenerationPointNoticeDescription}
onClose={() => setDraftGenerationPointNotice(null)} onClose={() => setDraftGenerationPointNotice(null)}
confirmLabel="知道了" showHeader
showCloseButton
closeOnBackdrop closeOnBackdrop
size="sm"
overlayClassName={`platform-theme ${platformThemeClass} !items-center`} overlayClassName={`platform-theme ${platformThemeClass} !items-center`}
panelClassName="platform-remap-surface rounded-[1.75rem]" panelClassName="platform-remap-surface rounded-[1.75rem]"
iconClassName={
draftGenerationPointNotice?.title === '读取泥点余额失败'
? undefined
: 'bg-amber-100/80 text-amber-600'
}
action={{
label: '知道了',
onClick: () => setDraftGenerationPointNotice(null),
surface: 'platform',
}}
> >
{draftGenerationPointNotice?.message} {draftGenerationPointNotice?.message}
</UnifiedConfirmDialog> </PlatformStatusDialog>
<PublishShareModal <PublishShareModal
open={Boolean(publishSharePayload)} open={Boolean(publishSharePayload)}
payload={publishSharePayload} payload={publishSharePayload}
@@ -17026,18 +17038,24 @@ export function PlatformEntryFlowShellImpl({
overlayClassName={`platform-theme ${platformThemeClass} !items-center`} overlayClassName={`platform-theme ${platformThemeClass} !items-center`}
panelClassName="platform-remap-surface rounded-[1.5rem]" panelClassName="platform-remap-surface rounded-[1.5rem]"
/> />
<UnifiedConfirmDialog <PlatformStatusDialog
open={Boolean(workNotFoundRecoveryDialog)} open={Boolean(workNotFoundRecoveryDialog)}
status="error"
title="作品不可用" title="作品不可用"
onClose={confirmWorkNotFoundRecovery} onClose={confirmWorkNotFoundRecovery}
confirmLabel="知道了" showHeader
showCloseButton
closeOnBackdrop closeOnBackdrop
size="sm"
overlayClassName={`platform-theme ${platformThemeClass} !items-center`} overlayClassName={`platform-theme ${platformThemeClass} !items-center`}
panelClassName="platform-remap-surface rounded-[1.75rem]" panelClassName="platform-remap-surface rounded-[1.75rem]"
action={{
label: '知道了',
onClick: confirmWorkNotFoundRecovery,
surface: 'platform',
}}
> >
{workNotFoundRecoveryDialog?.message} {workNotFoundRecoveryDialog?.message}
</UnifiedConfirmDialog> </PlatformStatusDialog>
<UnifiedConfirmDialog <UnifiedConfirmDialog
open={Boolean(pendingDeleteCreationWork)} open={Boolean(pendingDeleteCreationWork)}
title="删除作品" title="删除作品"

View File

@@ -102,6 +102,7 @@ import { PlatformModalCloseButton } from '../common/PlatformModalCloseButton';
import { PlatformOverlayBadge } from '../common/PlatformOverlayBadge'; import { PlatformOverlayBadge } from '../common/PlatformOverlayBadge';
import { PlatformPillBadge } from '../common/PlatformPillBadge'; import { PlatformPillBadge } from '../common/PlatformPillBadge';
import { PlatformSlotBadge } from '../common/PlatformSlotBadge'; import { PlatformSlotBadge } from '../common/PlatformSlotBadge';
import { PlatformStatusDialog } from '../common/PlatformStatusDialog';
import { PlatformStatusMessage } from '../common/PlatformStatusMessage'; import { PlatformStatusMessage } from '../common/PlatformStatusMessage';
import { PlatformSubpanel } from '../common/PlatformSubpanel'; import { PlatformSubpanel } from '../common/PlatformSubpanel';
import { PlatformUploadPreviewCard } from '../common/PlatformUploadPreviewCard'; import { PlatformUploadPreviewCard } from '../common/PlatformUploadPreviewCard';
@@ -1494,16 +1495,27 @@ function EditorNoticeDialog({
onClose: () => void; onClose: () => void;
}) { }) {
return ( return (
<UnifiedConfirmDialog <PlatformStatusDialog
open status="error"
title="提示" title="提示"
description={message}
onClose={onClose} onClose={onClose}
confirmLabel="知道了" showHeader
overlayClassName="z-[140] !items-center" showCloseButton
closeOnBackdrop
closeOnEscape
action={{
label: '知道了',
onClick: onClose,
surface: 'platform',
size: 'sm',
fullWidth: false,
className: 'min-h-0 rounded-full px-4 py-2',
}}
zIndexClassName="z-[140]"
overlayClassName="rpg-editor-notice-dialog-overlay !items-center"
panelClassName="platform-remap-surface rounded-[1.5rem]" panelClassName="platform-remap-surface rounded-[1.5rem]"
> />
{message}
</UnifiedConfirmDialog>
); );
} }