/** * TransferPanel - 传输队列面板 * * 显示文件上传/下载的传输队列;进行中任务置顶。 */ import { useMemo } from 'react' import { useTranslation } from 'react-i18next' import { ChevronDown, ChevronUp } from 'lucide-react' import { TransferItem } from './TransferItem' import type { TransferTask } from '../../../shared/types/sftp.types' interface TransferPanelProps { tasks: TransferTask[] isOpen: boolean onToggle: () => void onCancel?: (id: string) => void onRemove: (id: string) => void onRetry?: (id: string) => void } /** transferring → pending → failed/canceled → completed(组内保持原相对顺序) */ // eslint-disable-next-line react-refresh/only-export-components -- pure helper used by tests and panel export function sortTransferTasks(tasks: TransferTask[]): TransferTask[] { const rank = (status: TransferTask['status']): number => { switch (status) { case 'transferring': return 0 case 'pending': return 1 case 'failed': case 'canceled': return 2 case 'completed': return 3 default: return 4 } } return tasks .map((task, index) => ({ task, index })) .sort((a, b) => { const byStatus = rank(a.task.status) - rank(b.task.status) return byStatus !== 0 ? byStatus : a.index - b.index }) .map(({ task }) => task) } export function TransferPanel({ tasks, isOpen, onToggle, onCancel, onRemove, onRetry }: TransferPanelProps) { const { t } = useTranslation('sftp') const orderedTasks = useMemo(() => sortTransferTasks(tasks), [tasks]) const activeCount = tasks.filter((task) => task.status === 'pending' || task.status === 'transferring').length const completedCount = tasks.filter((task) => task.status === 'completed').length return (