import { motion } from 'motion/react'; import type { CustomWorldGenerationProgress } from '../../packages/shared/src/contracts/runtime'; import type { CustomWorldStructuredAnchorEntry } from '../services/customWorldAgentGenerationProgress'; interface CustomWorldGenerationViewProps { settingText: string; anchorEntries?: CustomWorldStructuredAnchorEntry[]; progress: CustomWorldGenerationProgress | null; isGenerating: boolean; error: string | null; onBack: () => void; onEditSetting: () => void; onRetry: () => void; onInterrupt?: () => void; backLabel?: string; settingActionLabel?: string; retryLabel?: string; interruptLabel?: string; settingTitle?: string; settingDescription?: string; progressTitle?: string; activeBadgeLabel?: string; pausedBadgeLabel?: string; idleBadgeLabel?: string; structuredEmptyText?: string; } function formatDuration(ms: number) { const safeMs = Math.max(0, Math.round(ms)); const totalSeconds = Math.ceil(safeMs / 1000); const minutes = Math.floor(totalSeconds / 60); const seconds = totalSeconds % 60; if (minutes <= 0) { return `${Math.max(1, seconds)} 秒`; } if (seconds === 0) { return `${minutes} 分钟`; } return `${minutes} 分 ${seconds} 秒`; } function getProgressPercentage(progress: CustomWorldGenerationProgress | null) { return Math.max(0, Math.min(100, progress?.overallProgress ?? 0)); } function buildFallbackRenderKey( value: string | null | undefined, fallback: string, ) { const normalizedValue = value?.trim(); return normalizedValue ? normalizedValue : fallback; } export function CustomWorldGenerationView({ settingText, anchorEntries = [], progress, isGenerating, error, onBack, onEditSetting, onRetry, onInterrupt, backLabel = '返回', settingActionLabel = '修改设定', retryLabel = '重新开始生成', interruptLabel = '中断世界生成', settingTitle = '玩家设定', settingDescription = '这段文本会直接驱动本轮世界框架、角色与场景生成。', progressTitle = '生成进度', activeBadgeLabel = '世界建设中', pausedBadgeLabel = '生成已暂停', idleBadgeLabel = '等待操作', structuredEmptyText = '正在整理当前设定结构,请稍后。', }: CustomWorldGenerationViewProps) { const progressValue = getProgressPercentage(progress); const steps = progress?.steps ?? []; const hasStructuredAnchors = anchorEntries.length > 0; const estimatedWaitText = progress?.estimatedRemainingMs != null ? `预计还需 ${formatDuration(progress.estimatedRemainingMs)}` : '正在校准预计等待时间'; const elapsedText = progress != null ? `已耗时 ${formatDuration(progress.elapsedMs)}` : '正在启动世界生成'; return (
{isGenerating ? activeBadgeLabel : error ? pausedBadgeLabel : idleBadgeLabel}
{progressTitle}
{progress?.phaseLabel ?? '正在启动世界生成'}
{progress?.phaseDetail ?? '正在初始化世界生成链路与阶段监控。'}
总进度
{progressValue}%
当前批次
{progress?.batchLabel ?? '准备中'}
预计等待
{estimatedWaitText}
计时
{elapsedText}
{steps.map((step, index) => (
{step.label}
{step.completed}/{step.total}
{step.detail}
))}
{error ? (
{error}
) : null}
{!isGenerating ? ( <> ) : onInterrupt ? ( ) : null}
{settingTitle}
{settingDescription}
{hasStructuredAnchors ? (
{anchorEntries.map((entry, index) => (
{entry.label}
{entry.value}
))}
) : (
{settingText || structuredEmptyText}
)}
); }