import { useQueryClient } from "@tanstack/react-query"; import type { DownloadBoardState } from "@umt/contracts"; import { EventType } from "@umt/contracts"; import { RefreshCw } from "lucide-react"; import { useMemo, useState } from "react"; import { Link } from "react-router"; import { useDownloadBoard } from "~/api/downloads.ts"; import { DataTable } from "~/components/console/data-table.tsx"; import { DetailSheet } from "~/components/console/detail-sheet.tsx"; import { consolePath } from "~/components/console/nav.ts"; import { PageHeader } from "~/components/console/page-header.tsx"; import { readBoardState, writeBoardState } from "~/components/downloads/board-format.ts"; import { CacheVolumes } from "~/components/downloads/cache-volumes.tsx"; import { activeColumns, BOARD_EMPTY, BoardSegments, completedColumns, TransferLine, } from "~/components/downloads/download-board.tsx"; import { DownloadDetail } from "~/components/downloads/download-detail.tsx"; import { DownloadsTabs } from "~/components/downloads/downloads-tabs.tsx"; import { Button } from "~/components/ui/button.tsx"; import { useSse } from "~/lib/sse.ts"; export const meta = () => [{ title: "下载面板 · UHD 媒体自动化控制台" }]; // DL-2:默认只看进行中;已完成单独一段(本浏览器记住选择)。页面可见时每 4 秒刷新速度,切到后台停。 export default function DownloadsPage() { // SPA 模式:路由组件只在浏览器渲染,可直接读本地记住的分段 const [state, setStateRaw] = useState(readBoardState); const setState = (s: DownloadBoardState) => { setStateRaw(s); writeBoardState(s); }; const [openId, setOpenId] = useState(null); const qc = useQueryClient(); const board = useDownloadBoard(state); // 状态变化、阈值事件到达时立即刷新(速度靠轮询) useSse( [ EventType.downloadProgress, EventType.downloadStatusChanged, EventType.downloadSubmitted, EventType.downloadThreshold, ], () => void qc.invalidateQueries({ queryKey: ["downloads"] }), ); const pages = board.data?.pages; const rows = pages?.flatMap((p) => p.items); const first = pages?.[0]; const open = rows?.find((t) => t.id === openId) ?? null; const columns = useMemo(() => (state === "active" ? activeColumns() : completedColumns()), [state]); const empty = BOARD_EMPTY[state]; return ( <> void qc.invalidateQueries({ queryKey: ["downloads"] })}> 刷新 } />
t.id} loading={board.isPending} error={board.error} onRetry={() => void board.refetch()} onRowClick={(t) => setOpenId(t.id)} selectedKey={openId} hasMore={board.hasNextPage} onLoadMore={() => void board.fetchNextPage()} loadingMore={board.isFetchingNextPage} empty={empty} /> !o && setOpenId(null)} width="lg" title={open?.name ?? ""} footer={ open ? ( ) : null } > {open ? : null} ); }