新增共享 PlatformBackActionButton 承接结果页轻量返回入口 将拼图方洞拼消消视觉小说等结果页返回按钮收口到共享组件 将拼消消跳一跳敲木鱼宝贝识物结果页返回按钮收口到共享组件 补充对应测试并更新 PlatformUiKit 收口计划与共享决策记录
216 lines
7.2 KiB
TypeScript
216 lines
7.2 KiB
TypeScript
import { Loader2, Play, RefreshCcw, Send } from 'lucide-react';
|
|
import { useState } from 'react';
|
|
|
|
import type {
|
|
PuzzleClearDraftResponse,
|
|
PuzzleClearWorkProfileResponse,
|
|
} from '../../../packages/shared/src/contracts/puzzleClear';
|
|
import { PlatformActionButton } from '../common/PlatformActionButton';
|
|
import { PlatformBackActionButton } from '../common/PlatformBackActionButton';
|
|
import { PlatformMediaFrame } from '../common/PlatformMediaFrame';
|
|
import { PlatformMediaTileGrid } from '../common/PlatformMediaTileGrid';
|
|
import { PlatformStatGrid } from '../common/PlatformStatGrid';
|
|
import { PlatformStatusMessage } from '../common/PlatformStatusMessage';
|
|
import { PlatformSubpanel } from '../common/PlatformSubpanel';
|
|
|
|
type PuzzleClearResultViewProps = {
|
|
profile: PuzzleClearDraftResponse | PuzzleClearWorkProfileResponse;
|
|
isBusy?: boolean;
|
|
error?: string | null;
|
|
onBack: () => void;
|
|
onEdit: () => void;
|
|
onStartTestRun: () => void;
|
|
onPublish: () => void;
|
|
onRegenerateAtlas: () => void;
|
|
};
|
|
|
|
function isPuzzleClearWorkProfile(
|
|
profile: PuzzleClearResultViewProps['profile'],
|
|
): profile is PuzzleClearWorkProfileResponse {
|
|
return 'summary' in profile;
|
|
}
|
|
|
|
function getDraft(profile: PuzzleClearResultViewProps['profile']) {
|
|
return isPuzzleClearWorkProfile(profile) ? profile.draft : profile;
|
|
}
|
|
|
|
export function PuzzleClearResultView({
|
|
profile,
|
|
isBusy = false,
|
|
error = null,
|
|
onBack,
|
|
onEdit,
|
|
onStartTestRun,
|
|
onPublish,
|
|
onRegenerateAtlas,
|
|
}: PuzzleClearResultViewProps) {
|
|
const [isPublishing, setIsPublishing] = useState(false);
|
|
const isWorkProfile = isPuzzleClearWorkProfile(profile);
|
|
const draft = getDraft(profile);
|
|
const summary = isWorkProfile ? profile.summary : null;
|
|
const title =
|
|
summary?.workTitle?.trim() || draft.workTitle.trim() || '拼消消';
|
|
const description =
|
|
summary?.workDescription?.trim() || draft.workDescription.trim();
|
|
const boardBackgroundAsset = isWorkProfile
|
|
? (profile.boardBackgroundAsset ?? draft.boardBackgroundAsset)
|
|
: draft.boardBackgroundAsset;
|
|
const atlasAsset = isWorkProfile ? profile.atlasAsset : draft.atlasAsset;
|
|
const patternGroups = isWorkProfile
|
|
? profile.patternGroups
|
|
: draft.patternGroups;
|
|
const cardAssets = isWorkProfile ? profile.cardAssets : draft.cardAssets;
|
|
const previewCards = cardAssets.slice(0, 24);
|
|
const canPublish = Boolean(isWorkProfile && summary?.publishReady);
|
|
|
|
const handlePublish = async () => {
|
|
setIsPublishing(true);
|
|
try {
|
|
await Promise.resolve(onPublish());
|
|
} finally {
|
|
setIsPublishing(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="platform-remap-surface mx-auto flex h-full min-h-0 w-full max-w-6xl flex-col px-3 pb-3 pt-3 sm:px-4 sm:pt-4">
|
|
<div className="mb-3 flex items-center justify-between gap-3">
|
|
<PlatformBackActionButton
|
|
onClick={onBack}
|
|
variant="regular"
|
|
/>
|
|
<PlatformActionButton
|
|
onClick={onRegenerateAtlas}
|
|
disabled={isBusy}
|
|
tone="ghost"
|
|
size="xs"
|
|
className="min-h-0 gap-2 py-2 text-sm"
|
|
>
|
|
<RefreshCcw className="h-4 w-4" />
|
|
图集
|
|
</PlatformActionButton>
|
|
</div>
|
|
|
|
<div className="grid min-h-0 flex-1 gap-3 lg:grid-cols-[minmax(0,1.05fr)_minmax(19rem,0.95fr)]">
|
|
<PlatformSubpanel className="flex min-h-0 flex-col" radius="md">
|
|
<div className="text-2xl font-black text-[var(--platform-text-strong)]">
|
|
{title}
|
|
</div>
|
|
{description ? (
|
|
<div className="mt-2 text-sm leading-6 text-[var(--platform-text-base)]">
|
|
{description}
|
|
</div>
|
|
) : null}
|
|
|
|
<div className="mt-4 grid min-h-0 flex-1 gap-3 sm:grid-cols-[minmax(0,0.92fr)_minmax(0,1.08fr)]">
|
|
<PlatformSubpanel
|
|
as="div"
|
|
surface="flat"
|
|
radius="sm"
|
|
padding="none"
|
|
className="overflow-hidden bg-white/80"
|
|
>
|
|
<PlatformMediaFrame
|
|
src={boardBackgroundAsset?.imageSrc}
|
|
alt="场地底图"
|
|
fallbackLabel="底图"
|
|
aspect="portrait"
|
|
surface="none"
|
|
className="rounded-none"
|
|
fallbackClassName="tracking-normal text-[var(--platform-text-soft)]"
|
|
/>
|
|
</PlatformSubpanel>
|
|
|
|
<div className="flex min-h-0 flex-col gap-3">
|
|
<PlatformSubpanel
|
|
as="div"
|
|
surface="flat"
|
|
radius="sm"
|
|
padding="none"
|
|
className="overflow-hidden bg-white/80"
|
|
>
|
|
<PlatformMediaFrame
|
|
src={atlasAsset?.imageSrc}
|
|
alt="素材图集"
|
|
fallbackLabel="图集"
|
|
aspect="square"
|
|
surface="none"
|
|
className="rounded-none"
|
|
fallbackClassName="tracking-normal text-[var(--platform-text-soft)]"
|
|
/>
|
|
</PlatformSubpanel>
|
|
|
|
<PlatformMediaTileGrid
|
|
items={previewCards.map((card) => ({
|
|
id: card.cardId,
|
|
src: card.imageSrc,
|
|
fallbackLabel: '卡片',
|
|
}))}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</PlatformSubpanel>
|
|
|
|
<aside className="flex min-h-0 flex-col gap-3 overflow-y-auto">
|
|
<PlatformSubpanel>
|
|
<PlatformStatGrid
|
|
items={[
|
|
{ label: '图案组', value: patternGroups.length },
|
|
{ label: '卡片', value: cardAssets.length },
|
|
{ label: '状态', value: draft.generationStatus },
|
|
]}
|
|
density="compact"
|
|
itemClassName="rounded-[0.9rem] py-3"
|
|
/>
|
|
</PlatformSubpanel>
|
|
|
|
{error ? (
|
|
<PlatformStatusMessage tone="error" surface="platform" size="md">
|
|
{error}
|
|
</PlatformStatusMessage>
|
|
) : null}
|
|
|
|
<PlatformSubpanel className="mt-auto">
|
|
<div className="grid gap-2">
|
|
<PlatformActionButton
|
|
onClick={onStartTestRun}
|
|
disabled={isBusy || !isWorkProfile}
|
|
size="md"
|
|
className="min-h-11 gap-2"
|
|
>
|
|
<Play className="h-4 w-4" />
|
|
试玩
|
|
</PlatformActionButton>
|
|
<PlatformActionButton
|
|
onClick={handlePublish}
|
|
disabled={isBusy || isPublishing || !canPublish}
|
|
tone="secondary"
|
|
size="md"
|
|
className="min-h-11 gap-2"
|
|
>
|
|
{isPublishing ? (
|
|
<Loader2 className="h-4 w-4 animate-spin" />
|
|
) : (
|
|
<Send className="h-4 w-4" />
|
|
)}
|
|
发布
|
|
</PlatformActionButton>
|
|
<PlatformActionButton
|
|
onClick={onEdit}
|
|
disabled={isBusy}
|
|
tone="ghost"
|
|
size="md"
|
|
className="min-h-11"
|
|
>
|
|
编辑
|
|
</PlatformActionButton>
|
|
</div>
|
|
</PlatformSubpanel>
|
|
</aside>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default PuzzleClearResultView;
|