收口未保存离开确认弹窗
新增 PlatformUnsavedLeaveConfirmDialog 统一承接未保存离开确认壳层 迁移 RPG 创作编辑器的关闭未保存修改与退出未保存结果确认复用共享组件 补充共享组件测试并更新 PlatformUiKit 收口文档与决策记录
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
/* @vitest-environment jsdom */
|
||||
|
||||
import { fireEvent, render, screen, within } from '@testing-library/react';
|
||||
import { expect, test, vi } from 'vitest';
|
||||
|
||||
import { PlatformUnsavedLeaveConfirmDialog } from './PlatformUnsavedLeaveConfirmDialog';
|
||||
|
||||
test('renders the platform variant with leave/continue actions', () => {
|
||||
const onClose = vi.fn();
|
||||
const onConfirm = vi.fn();
|
||||
|
||||
render(
|
||||
<PlatformUnsavedLeaveConfirmDialog
|
||||
open
|
||||
title="确认关闭"
|
||||
onClose={onClose}
|
||||
onConfirm={onConfirm}
|
||||
>
|
||||
当前修改尚未保存,确认关闭吗?
|
||||
</PlatformUnsavedLeaveConfirmDialog>,
|
||||
);
|
||||
|
||||
const dialog = screen.getByRole('dialog', { name: '确认关闭' });
|
||||
|
||||
expect(within(dialog).getByText('当前修改尚未保存,确认关闭吗?')).toBeTruthy();
|
||||
|
||||
fireEvent.click(within(dialog).getByRole('button', { name: '继续编辑' }));
|
||||
expect(onClose).toHaveBeenCalledTimes(1);
|
||||
|
||||
fireEvent.click(within(dialog).getByRole('button', { name: '确认关闭' }));
|
||||
expect(onConfirm).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('supports pixel variant with custom confirm label', () => {
|
||||
render(
|
||||
<PlatformUnsavedLeaveConfirmDialog
|
||||
open
|
||||
title="确认退出"
|
||||
confirmLabel="仍然退出"
|
||||
variant="pixel"
|
||||
onClose={() => {}}
|
||||
onConfirm={() => {}}
|
||||
>
|
||||
当前生成画面还未保存。
|
||||
</PlatformUnsavedLeaveConfirmDialog>,
|
||||
);
|
||||
|
||||
const dialog = screen.getByRole('dialog', { name: '确认退出' });
|
||||
|
||||
expect(dialog.className).toContain('pixel-modal-shell');
|
||||
expect(within(dialog).getByRole('button', { name: '仍然退出' })).toBeTruthy();
|
||||
expect(within(dialog).getByRole('button', { name: '继续编辑' })).toBeTruthy();
|
||||
});
|
||||
92
src/components/common/PlatformUnsavedLeaveConfirmDialog.tsx
Normal file
92
src/components/common/PlatformUnsavedLeaveConfirmDialog.tsx
Normal file
@@ -0,0 +1,92 @@
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
import { UnifiedConfirmDialog } from './UnifiedConfirmDialog';
|
||||
|
||||
type PlatformUnsavedLeaveConfirmDialogProps = {
|
||||
open: boolean;
|
||||
title?: string;
|
||||
children?: ReactNode;
|
||||
onClose: () => void;
|
||||
onConfirm: () => void;
|
||||
confirmLabel?: string;
|
||||
cancelLabel?: string;
|
||||
showCloseButton?: boolean;
|
||||
closeOnBackdrop?: boolean;
|
||||
portal?: boolean;
|
||||
size?: 'sm' | 'md';
|
||||
variant?: 'platform' | 'pixel';
|
||||
overlayClassName?: string;
|
||||
panelClassName?: string;
|
||||
};
|
||||
|
||||
function resolveUnsavedLeaveOverlayClassName(
|
||||
variant: 'platform' | 'pixel',
|
||||
overlayClassName?: string,
|
||||
) {
|
||||
if (overlayClassName) {
|
||||
return overlayClassName;
|
||||
}
|
||||
|
||||
return variant === 'pixel' ? 'z-[140]' : 'z-[140] !items-center';
|
||||
}
|
||||
|
||||
function resolveUnsavedLeavePanelClassName(
|
||||
variant: 'platform' | 'pixel',
|
||||
panelClassName?: string,
|
||||
) {
|
||||
if (panelClassName) {
|
||||
return panelClassName;
|
||||
}
|
||||
|
||||
return variant === 'platform'
|
||||
? 'platform-remap-surface rounded-[1.5rem]'
|
||||
: undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台未保存离开确认弹窗。
|
||||
* 统一承接关闭 / 退出前的“继续编辑 + 确认离开”语义和默认平台壳层。
|
||||
*/
|
||||
export function PlatformUnsavedLeaveConfirmDialog({
|
||||
open,
|
||||
title = '确认退出',
|
||||
children,
|
||||
onClose,
|
||||
onConfirm,
|
||||
confirmLabel,
|
||||
cancelLabel = '继续编辑',
|
||||
showCloseButton = true,
|
||||
closeOnBackdrop = true,
|
||||
portal = true,
|
||||
size = 'sm',
|
||||
variant = 'platform',
|
||||
overlayClassName,
|
||||
panelClassName,
|
||||
}: PlatformUnsavedLeaveConfirmDialogProps) {
|
||||
return (
|
||||
<UnifiedConfirmDialog
|
||||
open={open}
|
||||
title={title}
|
||||
onClose={onClose}
|
||||
onConfirm={onConfirm}
|
||||
confirmLabel={confirmLabel ?? title}
|
||||
cancelLabel={cancelLabel}
|
||||
showCloseButton={showCloseButton}
|
||||
closeOnBackdrop={closeOnBackdrop}
|
||||
showCancel
|
||||
portal={portal}
|
||||
size={size}
|
||||
variant={variant}
|
||||
overlayClassName={resolveUnsavedLeaveOverlayClassName(
|
||||
variant,
|
||||
overlayClassName,
|
||||
)}
|
||||
panelClassName={resolveUnsavedLeavePanelClassName(
|
||||
variant,
|
||||
panelClassName,
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</UnifiedConfirmDialog>
|
||||
);
|
||||
}
|
||||
@@ -105,9 +105,9 @@ import { PlatformSlotBadge } from '../common/PlatformSlotBadge';
|
||||
import { PlatformStatusDialog } from '../common/PlatformStatusDialog';
|
||||
import { PlatformStatusMessage } from '../common/PlatformStatusMessage';
|
||||
import { PlatformSubpanel } from '../common/PlatformSubpanel';
|
||||
import { PlatformUnsavedLeaveConfirmDialog } from '../common/PlatformUnsavedLeaveConfirmDialog';
|
||||
import { PlatformUploadPreviewCard } from '../common/PlatformUploadPreviewCard';
|
||||
import { PlatformUploadTile } from '../common/PlatformUploadTile';
|
||||
import { UnifiedConfirmDialog } from '../common/UnifiedConfirmDialog';
|
||||
import { CustomWorldCoverArtwork } from '../CustomWorldCoverArtwork';
|
||||
import { CustomWorldNpcPortrait } from '../CustomWorldNpcVisualEditor';
|
||||
import {
|
||||
@@ -1471,19 +1471,15 @@ function CloseConfirmDialog({
|
||||
confirmLabel?: string;
|
||||
}) {
|
||||
return (
|
||||
<UnifiedConfirmDialog
|
||||
<PlatformUnsavedLeaveConfirmDialog
|
||||
open
|
||||
title="确认关闭"
|
||||
onClose={onCancel}
|
||||
confirmLabel={confirmLabel}
|
||||
cancelLabel="继续编辑"
|
||||
showCancel
|
||||
onConfirm={onConfirm}
|
||||
overlayClassName="z-[140] !items-center"
|
||||
panelClassName="platform-remap-surface rounded-[1.5rem]"
|
||||
>
|
||||
{message}
|
||||
</UnifiedConfirmDialog>
|
||||
</PlatformUnsavedLeaveConfirmDialog>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3383,22 +3379,19 @@ function SceneImageGenerationModal({
|
||||
</ModalShell>
|
||||
|
||||
{isExitConfirmOpen ? (
|
||||
<UnifiedConfirmDialog
|
||||
<PlatformUnsavedLeaveConfirmDialog
|
||||
open
|
||||
title="确认退出"
|
||||
onClose={() => setIsExitConfirmOpen(false)}
|
||||
confirmLabel="仍然退出"
|
||||
cancelLabel="继续编辑"
|
||||
showCancel
|
||||
onConfirm={() => {
|
||||
setIsExitConfirmOpen(false);
|
||||
onClose();
|
||||
}}
|
||||
variant="pixel"
|
||||
overlayClassName="z-[140]"
|
||||
>
|
||||
当前生成画面还未保存,退出后将丢失这次生成结果,仍然退出吗?
|
||||
</UnifiedConfirmDialog>
|
||||
</PlatformUnsavedLeaveConfirmDialog>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
@@ -4029,22 +4022,18 @@ function CoverImageGenerationModal({
|
||||
</ModalShell>
|
||||
|
||||
{isExitConfirmOpen ? (
|
||||
<UnifiedConfirmDialog
|
||||
<PlatformUnsavedLeaveConfirmDialog
|
||||
open
|
||||
title="确认退出"
|
||||
onClose={() => setIsExitConfirmOpen(false)}
|
||||
overlayClassName="z-[140]"
|
||||
panelClassName="platform-remap-surface rounded-[1.5rem]"
|
||||
confirmLabel="确认退出"
|
||||
cancelLabel="继续编辑"
|
||||
showCancel
|
||||
onConfirm={() => {
|
||||
setIsExitConfirmOpen(false);
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
当前生成结果还没有保存,确认退出吗?
|
||||
</UnifiedConfirmDialog>
|
||||
</PlatformUnsavedLeaveConfirmDialog>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user