import type { ReactNode } from 'react' import { ArrowDown, ArrowUp, Film, HardDrive, Rss, Trash2 } from 'lucide-react' import { imageURL } from '../api/client' import type { DownloadCardItem } from './downloadTaskCardModel' export function DownloadTaskCard({ item, removable, onRemove, }: { item: DownloadCardItem removable?: boolean onRemove?: () => Promise }) { const progress = pct(item.progress) const visual = item.poster_url || item.backdrop_url const downloaded = item.downloaded || (item.size ? Math.round(item.size * (item.progress || 0)) : 0) return (
{visual ? ( {item.title} ) : (
{item.title}
)} {stateLabel(item)}

{item.title}

{item.overview || item.save_path || '已隐藏原始种子 URL,避免泄露私有 Token。'}

进度 {progress.toFixed(1)}% {fmtBytes(downloaded)} / {fmtBytes(item.size)}
} value={fmtSpeed(item.dlspeed)} /> } value={fmtSpeed(item.upspeed)} /> } value={`${item.num_seeds ?? 0} / ${item.num_leechs ?? 0}`} /> } value={fmtBytes(item.size)} />
{item.save_path || '默认下载目录'} {item.created_at && {new Date(item.created_at).toLocaleString()}}
{removable && onRemove && (
)}
) } function DownloadMetric({ icon, value }: { icon: ReactNode; value: string }) { return (
{icon} {value}
) } function fmtBytes(n?: number): string { if (!n || n <= 0) return '0 B' const u = ['B', 'KB', 'MB', 'GB', 'TB'] let v = n let i = 0 while (v >= 1024 && i < u.length - 1) { v /= 1024 i++ } return `${v.toFixed(v >= 100 ? 0 : 1)} ${u[i]}` } function fmtSpeed(n?: number): string { return `${fmtBytes(n)}/s` } function pct(progress?: number): number { if (!Number.isFinite(progress)) return 0 return Math.min(100, Math.max(0, Math.round((progress ?? 0) * 1000) / 10)) } function stateLabel(item: DownloadCardItem): string { const state = (item.state || item.status || 'queued').toLowerCase() if (state.includes('down') || state.includes('meta')) return '下载中' if (state.includes('up') || state.includes('seed')) return '做种中' if (state.includes('pause')) return '已暂停' if (state.includes('error')) return '出错' if (state.includes('complete') || pct(item.progress) >= 100) return '已完成' if (state.includes('queue')) return '排队中' return item.state || item.status || '等待中' } function statusTone(item: DownloadCardItem): string { const state = stateLabel(item) if (state === '已完成' || state === '做种中') return 'bg-emerald-50 text-emerald-600' if (state === '出错') return 'bg-red-50 text-red-500' if (state === '已暂停') return 'bg-amber-50 text-amber-600' return 'bg-primary-400/10 text-brand-500' }