'use client'; import { marked } from 'marked'; import { useEffect, useState } from 'react'; import { EmptyState } from '@/components/feedback/empty-state'; import { ErrorState } from '@/components/feedback/error-state'; import { LoadingState } from '@/components/feedback/loading-state'; import { AppCard } from '@/components/ui/app-card'; import { AppModal } from '@/components/ui/app-modal'; import { StatusBadge } from '@/components/ui/status-badge'; import type { LatestReleaseInfo, ReleaseChannel, UploadedServerBinaryInfo, } from '@/features/update/types'; import { PrimaryButton, ResourceField, ResourceInput, SecondaryButton, } from '@/features/shared/components/resource-primitives'; import { formatDateTime, formatRelativeTime } from '@/lib/utils/date'; interface VersionUpgradeModalProps { isOpen: boolean; onClose: () => void; currentVersion: string; frontendVersion: string; startTime?: number; release: LatestReleaseInfo | null | undefined; selectedChannel: ReleaseChannel; uploadedBinary: UploadedServerBinaryInfo | null; isLoading: boolean; releaseErrorMessage?: string; manualStatusMessage?: string; manualErrorMessage?: string; canUpgrade: boolean; isChecking: boolean; isUpgrading: boolean; isUploadingBinary: boolean; isConfirmingManualUpgrade: boolean; onCheckStable: () => void; onCheckPreview: () => void; onUpgrade: () => void; onUploadBinary: (file: File) => void; onConfirmManualUpgrade: () => void; } function getUpgradeBadge(release: LatestReleaseInfo | null | undefined) { if (!release) { return { label: '未检查', variant: 'info' as const }; } if (release.in_progress) { return { label: '升级中', variant: 'warning' as const }; } if (release.has_update) { return { label: '可升级', variant: 'warning' as const }; } return { label: '最新', variant: 'success' as const }; } export function VersionUpgradeModal({ isOpen, onClose, currentVersion, frontendVersion, startTime, release, selectedChannel, uploadedBinary, isLoading, releaseErrorMessage, manualStatusMessage, manualErrorMessage, canUpgrade, isChecking, isUpgrading, isUploadingBinary, isConfirmingManualUpgrade, onCheckStable, onCheckPreview, onUpgrade, onUploadBinary, onConfirmManualUpgrade, }: VersionUpgradeModalProps) { const upgradeBadge = getUpgradeBadge(release); const [selectedBinary, setSelectedBinary] = useState(null); const selectedChannelLabel = selectedChannel === 'preview' ? '预览版' : '正式版'; useEffect(() => { if (!isOpen) { setSelectedBinary(null); } }, [isOpen]); return ( {isChecking && selectedChannel === 'stable' ? '检查中...' : '检查正式版'} {isChecking && selectedChannel === 'preview' ? '检查中...' : '检查预览版'} { if (selectedBinary) { onUploadBinary(selectedBinary); } }} disabled={ !selectedBinary || isUploadingBinary || isConfirmingManualUpgrade } > {isUploadingBinary ? '上传检查中...' : '上传并检查'} {isConfirmingManualUpgrade ? '升级中...' : '确认手动升级'} {isUpgrading ? '升级中...' : release?.in_progress ? '升级中...' : selectedChannel === 'preview' ? '升级到预览版' : '升级到正式版'} ) : undefined } >

{frontendVersion}

{currentVersion || 'unknown'}

{release?.tag_name || '未检查'}

{startTime ? formatDateTime(new Date(startTime * 1000)) : '未知'}

{isLoading ? : null} {!isLoading && releaseErrorMessage ? ( ) : null} {!isLoading && !releaseErrorMessage && !release ? ( ) : null} {!isLoading && !releaseErrorMessage && release ? (
{release.prerelease ? ( ) : ( )} {!release.upgrade_supported ? ( ) : null} {release.in_progress ? ( ) : null}
) : null} {canUpgrade ? (
{ const file = event.target.files?.[0] ?? null; setSelectedBinary(file); }} disabled={isUploadingBinary || isConfirmingManualUpgrade} /> {manualErrorMessage ? ( ) : null} {!manualErrorMessage && manualStatusMessage ? (
{manualStatusMessage}
) : null} {uploadedBinary ? (
{!uploadedBinary.upgrade_supported ? ( ) : null}

文件名

{uploadedBinary.file_name}

上传时间

{uploadedBinary.uploaded_at ? formatDateTime(uploadedBinary.uploaded_at) : '未知'}

当前版本

{uploadedBinary.current_version}

上传版本

{uploadedBinary.detected_version}

{uploadedBinary.comparison_message}

) : ( )}
) : null}
); }