收口标准泥点确认弹窗
新增 PlatformMudPointConfirmDialog 统一承接标准泥点消耗确认壳层 迁移拼图与抓大鹅创作工作台复用共享泥点确认弹窗 迁移拼图与抓大鹅结果页素材生成流程复用共享泥点确认弹窗 补充共享组件测试并更新 PlatformUiKit 收口文档与决策记录
This commit is contained in:
53
src/components/common/PlatformMudPointConfirmDialog.test.tsx
Normal file
53
src/components/common/PlatformMudPointConfirmDialog.test.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
/* @vitest-environment jsdom */
|
||||
|
||||
import { fireEvent, render, screen, within } from '@testing-library/react';
|
||||
import { expect, test, vi } from 'vitest';
|
||||
|
||||
import { PlatformMudPointConfirmDialog } from './PlatformMudPointConfirmDialog';
|
||||
|
||||
test('renders standard mud point confirmation copy and forwards confirm', () => {
|
||||
const onClose = vi.fn();
|
||||
const onConfirm = vi.fn();
|
||||
|
||||
render(
|
||||
<PlatformMudPointConfirmDialog
|
||||
open
|
||||
points={8}
|
||||
onClose={onClose}
|
||||
onConfirm={onConfirm}
|
||||
portal={false}
|
||||
/>,
|
||||
);
|
||||
|
||||
const dialog = screen.getByRole('dialog', { name: '确认消耗泥点' });
|
||||
|
||||
expect(within(dialog).getByText('消耗 8 泥点')).toBeTruthy();
|
||||
|
||||
fireEvent.click(within(dialog).getByRole('button', { name: '确定' }));
|
||||
expect(onConfirm).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('supports extra detail copy and close button override', () => {
|
||||
const onClose = vi.fn();
|
||||
|
||||
render(
|
||||
<PlatformMudPointConfirmDialog
|
||||
open
|
||||
points={7}
|
||||
title="保存正式素材"
|
||||
description="角色形象"
|
||||
onClose={onClose}
|
||||
onConfirm={vi.fn()}
|
||||
showCloseButton={false}
|
||||
portal={false}
|
||||
>
|
||||
本次会覆盖当前待确认素材。
|
||||
</PlatformMudPointConfirmDialog>,
|
||||
);
|
||||
|
||||
const dialog = screen.getByRole('dialog', { name: '保存正式素材' });
|
||||
|
||||
expect(within(dialog).getByText('消耗 7 泥点')).toBeTruthy();
|
||||
expect(within(dialog).getByText('本次会覆盖当前待确认素材。')).toBeTruthy();
|
||||
expect(screen.queryByRole('button', { name: '关闭' })).toBeNull();
|
||||
});
|
||||
64
src/components/common/PlatformMudPointConfirmDialog.tsx
Normal file
64
src/components/common/PlatformMudPointConfirmDialog.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
import { UnifiedConfirmDialog } from './UnifiedConfirmDialog';
|
||||
|
||||
type PlatformMudPointConfirmDialogProps = {
|
||||
open: boolean;
|
||||
points: number;
|
||||
onClose: () => void;
|
||||
onConfirm: () => void;
|
||||
confirmDisabled?: boolean;
|
||||
confirmLabel?: string;
|
||||
title?: string;
|
||||
description?: ReactNode;
|
||||
children?: ReactNode;
|
||||
showCloseButton?: boolean;
|
||||
portal?: boolean;
|
||||
size?: 'sm' | 'md';
|
||||
overlayClassName?: string;
|
||||
panelClassName?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* 平台泥点消耗确认弹窗。
|
||||
* 统一承接“确认消耗泥点 + 消耗 N 泥点”的标准确认壳层,业务侧只保留点数与确认动作。
|
||||
*/
|
||||
export function PlatformMudPointConfirmDialog({
|
||||
open,
|
||||
points,
|
||||
onClose,
|
||||
onConfirm,
|
||||
confirmDisabled = false,
|
||||
confirmLabel = '确定',
|
||||
title = '确认消耗泥点',
|
||||
description,
|
||||
children,
|
||||
showCloseButton = true,
|
||||
portal = true,
|
||||
size = 'sm',
|
||||
overlayClassName,
|
||||
panelClassName,
|
||||
}: PlatformMudPointConfirmDialogProps) {
|
||||
return (
|
||||
<UnifiedConfirmDialog
|
||||
open={open}
|
||||
title={title}
|
||||
description={description}
|
||||
onClose={onClose}
|
||||
onConfirm={onConfirm}
|
||||
confirmLabel={confirmLabel}
|
||||
confirmDisabled={confirmDisabled}
|
||||
showCancel
|
||||
showCloseButton={showCloseButton}
|
||||
portal={portal}
|
||||
size={size}
|
||||
overlayClassName={overlayClassName}
|
||||
panelClassName={panelClassName}
|
||||
>
|
||||
<div className="space-y-2">
|
||||
<div className="font-semibold">消耗 {points} 泥点</div>
|
||||
{children}
|
||||
</div>
|
||||
</UnifiedConfirmDialog>
|
||||
);
|
||||
}
|
||||
@@ -59,6 +59,7 @@ import { PlatformIconButton } from '../common/PlatformIconButton';
|
||||
import { PlatformMediaFrame } from '../common/PlatformMediaFrame';
|
||||
import { PlatformMediaTileGrid } from '../common/PlatformMediaTileGrid';
|
||||
import { PlatformModalCloseButton } from '../common/PlatformModalCloseButton';
|
||||
import { PlatformMudPointConfirmDialog } from '../common/PlatformMudPointConfirmDialog';
|
||||
import { PlatformPillBadge } from '../common/PlatformPillBadge';
|
||||
import { PlatformPillSwitch } from '../common/PlatformPillSwitch';
|
||||
import { PlatformProgressBar } from '../common/PlatformProgressBar';
|
||||
@@ -69,7 +70,6 @@ import { PlatformSubpanel } from '../common/PlatformSubpanel';
|
||||
import { PlatformTagEditor } from '../common/PlatformTagEditor';
|
||||
import { PlatformTextField } from '../common/PlatformTextField';
|
||||
import { PlatformUploadPreviewCard } from '../common/PlatformUploadPreviewCard';
|
||||
import { UnifiedConfirmDialog } from '../common/UnifiedConfirmDialog';
|
||||
import {
|
||||
MATCH3D_RUNTIME_BOARD_BASE_CLASS,
|
||||
MATCH3D_RUNTIME_BOARD_FALLBACK_CLASS,
|
||||
@@ -2370,24 +2370,20 @@ function Match3DBatchAddItemsPanel({
|
||||
生成物品素材 · {pointsCost}泥点
|
||||
</PlatformActionButton>
|
||||
|
||||
<UnifiedConfirmDialog
|
||||
<PlatformMudPointConfirmDialog
|
||||
open={isCostConfirmOpen}
|
||||
title="确认消耗泥点"
|
||||
points={pointsCost}
|
||||
onClose={() => setIsCostConfirmOpen(false)}
|
||||
onConfirm={() => {
|
||||
setIsCostConfirmOpen(false);
|
||||
onSubmit();
|
||||
}}
|
||||
confirmLabel="确定"
|
||||
confirmDisabled={parsedNames.length <= 0 || isGenerating}
|
||||
showCancel
|
||||
showCloseButton={false}
|
||||
portal={false}
|
||||
overlayClassName="platform-modal-backdrop z-[90]"
|
||||
panelClassName="platform-remap-surface max-w-xs rounded-[1.35rem] shadow-[0_24px_70px_rgba(15,23,42,0.22)]"
|
||||
>
|
||||
<div className="font-semibold">消耗 {pointsCost} 泥点</div>
|
||||
</UnifiedConfirmDialog>
|
||||
/>
|
||||
</div>
|
||||
</Match3DModalShell>
|
||||
);
|
||||
@@ -2465,24 +2461,20 @@ function Match3DBatchRegenerateItemsPanel({
|
||||
重新生成物品素材 · {pointsCost}泥点
|
||||
</PlatformActionButton>
|
||||
|
||||
<UnifiedConfirmDialog
|
||||
<PlatformMudPointConfirmDialog
|
||||
open={isCostConfirmOpen}
|
||||
title="确认消耗泥点"
|
||||
points={pointsCost}
|
||||
onClose={() => setIsCostConfirmOpen(false)}
|
||||
onConfirm={() => {
|
||||
setIsCostConfirmOpen(false);
|
||||
onSubmit();
|
||||
}}
|
||||
confirmLabel="确定"
|
||||
confirmDisabled={targetItemNames.length <= 0 || isGenerating}
|
||||
showCancel
|
||||
showCloseButton={false}
|
||||
portal={false}
|
||||
overlayClassName="platform-modal-backdrop z-[90]"
|
||||
panelClassName="platform-remap-surface max-w-xs rounded-[1.35rem] shadow-[0_24px_70px_rgba(15,23,42,0.22)]"
|
||||
>
|
||||
<div className="font-semibold">消耗 {pointsCost} 泥点</div>
|
||||
</UnifiedConfirmDialog>
|
||||
/>
|
||||
</div>
|
||||
</Match3DModalShell>
|
||||
);
|
||||
|
||||
@@ -28,6 +28,7 @@ import { PlatformFieldLabel } from '../common/PlatformFieldLabel';
|
||||
import { PlatformIconBadge } from '../common/PlatformIconBadge';
|
||||
import { PlatformIconButton } from '../common/PlatformIconButton';
|
||||
import { PlatformMediaFrame } from '../common/PlatformMediaFrame';
|
||||
import { PlatformMudPointConfirmDialog } from '../common/PlatformMudPointConfirmDialog';
|
||||
import { PlatformPillBadge } from '../common/PlatformPillBadge';
|
||||
import { PlatformProgressBar } from '../common/PlatformProgressBar';
|
||||
import { PlatformSegmentedTabs } from '../common/PlatformSegmentedTabs';
|
||||
@@ -36,7 +37,6 @@ import { PlatformSubpanel } from '../common/PlatformSubpanel';
|
||||
import { PlatformTagEditor } from '../common/PlatformTagEditor';
|
||||
import { PlatformTextField } from '../common/PlatformTextField';
|
||||
import { PlatformUploadPreviewCard } from '../common/PlatformUploadPreviewCard';
|
||||
import { UnifiedConfirmDialog } from '../common/UnifiedConfirmDialog';
|
||||
import PuzzleHistoryAssetPickerDialog from '../unified-creation/shared/PuzzleHistoryAssetPickerDialog';
|
||||
import {
|
||||
PUZZLE_IMAGE_MODEL_GPT_IMAGE_2,
|
||||
@@ -815,22 +815,16 @@ function PuzzleLevelDetailDialog({
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<UnifiedConfirmDialog
|
||||
<PlatformMudPointConfirmDialog
|
||||
open={isCostConfirmOpen}
|
||||
title="确认消耗泥点"
|
||||
points={PUZZLE_IMAGE_GENERATION_POINT_COST}
|
||||
onClose={() => setIsCostConfirmOpen(false)}
|
||||
onConfirm={executeGeneration}
|
||||
confirmLabel="确定"
|
||||
confirmDisabled={isBusy || generationProgress.isGenerating}
|
||||
showCancel
|
||||
portal={false}
|
||||
overlayClassName="absolute z-20 bg-black/45"
|
||||
panelClassName="platform-remap-surface rounded-[1.5rem] shadow-[0_24px_80px_rgba(0,0,0,0.45)]"
|
||||
>
|
||||
<div className="font-semibold">
|
||||
消耗 {PUZZLE_IMAGE_GENERATION_POINT_COST} 泥点
|
||||
</div>
|
||||
</UnifiedConfirmDialog>
|
||||
/>
|
||||
|
||||
{isHistoryPickerOpen ? (
|
||||
<PuzzleHistoryAssetPickerDialog
|
||||
|
||||
@@ -14,7 +14,7 @@ import { PlatformSegmentedTabs } from '../../common/PlatformSegmentedTabs';
|
||||
import { PlatformStatusMessage } from '../../common/PlatformStatusMessage';
|
||||
import { PlatformSubpanel } from '../../common/PlatformSubpanel';
|
||||
import { PlatformTextField } from '../../common/PlatformTextField';
|
||||
import { UnifiedConfirmDialog } from '../../common/UnifiedConfirmDialog';
|
||||
import { PlatformMudPointConfirmDialog } from '../../common/PlatformMudPointConfirmDialog';
|
||||
|
||||
type Match3DCreationWorkspaceProps = {
|
||||
session: Match3DAgentSessionSnapshot | null;
|
||||
@@ -351,19 +351,15 @@ export function Match3DCreationWorkspace({
|
||||
</PlatformActionButton>
|
||||
</div>
|
||||
|
||||
<UnifiedConfirmDialog
|
||||
<PlatformMudPointConfirmDialog
|
||||
open={isPointCostConfirmOpen}
|
||||
title="确认消耗泥点"
|
||||
points={mudPointCost}
|
||||
onClose={() => setIsPointCostConfirmOpen(false)}
|
||||
onConfirm={executeSubmitForm}
|
||||
confirmLabel="确定"
|
||||
confirmDisabled={!canSubmit}
|
||||
showCancel
|
||||
overlayClassName="platform-modal-backdrop z-[80]"
|
||||
panelClassName="platform-remap-surface max-w-xs rounded-[1.35rem] shadow-[0_24px_70px_rgba(15,23,42,0.22)]"
|
||||
>
|
||||
<div className="font-semibold">消耗 {mudPointCost} 泥点</div>
|
||||
</UnifiedConfirmDialog>
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
clampSquareImageCropRect,
|
||||
type SquareImageCropRect,
|
||||
} from '../../common/squareImageCropModel';
|
||||
import { UnifiedConfirmDialog } from '../../common/UnifiedConfirmDialog';
|
||||
import { PlatformMudPointConfirmDialog } from '../../common/PlatformMudPointConfirmDialog';
|
||||
import PuzzleHistoryAssetPickerDialog from '../shared/PuzzleHistoryAssetPickerDialog';
|
||||
import {
|
||||
normalizePuzzleImageModel,
|
||||
@@ -747,19 +747,15 @@ export function PuzzleCreationWorkspace({
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
<UnifiedConfirmDialog
|
||||
<PlatformMudPointConfirmDialog
|
||||
open={isPointCostConfirmOpen}
|
||||
title="确认消耗泥点"
|
||||
points={mudPointCost}
|
||||
onClose={() => setIsPointCostConfirmOpen(false)}
|
||||
onConfirm={executeSubmitForm}
|
||||
confirmLabel="确定"
|
||||
confirmDisabled={!canSubmit}
|
||||
showCancel
|
||||
overlayClassName="platform-modal-backdrop z-[80]"
|
||||
panelClassName="platform-remap-surface max-w-xs rounded-[1.35rem] shadow-[0_24px_70px_rgba(15,23,42,0.22)]"
|
||||
>
|
||||
<div className="font-semibold">消耗 {mudPointCost} 泥点</div>
|
||||
</UnifiedConfirmDialog>
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user