feat(downloads): live speeds and active/completed split on the download panel (DL-2)
- GET /download-tasks/board?state=active|completed: per-torrent dl/up speed, ETA, seeds/leechs, downloader total speed (transfer/info), counts for both groups, latest organize result (status, reason code, open decision) - live qB data cached per instance for 2 s with in-flight coalescing - panel: total speed line, 进行中 / 已完成 segments remembered locally, 4 s polling while the page is visible, mobile layout, "—" for zero speed Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
8086250ec2
commit
3b340745bf
17 files changed
+1113
-93
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import type { DownloadTask } from "@umt/contracts";
|
||||
import type { DownloadLive, DownloadTask } from "@umt/contracts";
|
||||
import { Bot, FolderInput, Pause, Play, ShieldAlert } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
@@ -23,6 +23,7 @@ import { relTime } from "~/components/workbench/release-fields.ts";
|
||||
import { errorMessage } from "~/lib/api.ts";
|
||||
import { planReasonText } from "~/lib/labels.ts";
|
||||
import { formatBytes, formatDateTime } from "~/lib/utils.ts";
|
||||
import { liveItems } from "./board-format.ts";
|
||||
import { BusinessTimeline } from "./business-timeline.tsx";
|
||||
|
||||
const PLAN_PURPOSE_LABEL: Record<string, string> = { fill: "补缺", upgrade: "升级", replace_source: "换源" };
|
||||
@@ -89,7 +90,7 @@ export function PauseResume({ t, size = "sm" }: { t: DownloadTask; size?: "sm" |
|
||||
}
|
||||
|
||||
/** 下载任务详情:状态、阈值说明、业务时间线、文件、关联计划 */
|
||||
export function DownloadDetail({ task }: { task: DownloadTask }) {
|
||||
export function DownloadDetail({ task, live }: { task: DownloadTask; live?: DownloadLive | null }) {
|
||||
const plan = usePlan(task.acquisitionPlanId);
|
||||
const names = useDownloaderNames();
|
||||
const trace = useDownloadTrace(task, plan.data);
|
||||
@@ -141,13 +142,14 @@ export function DownloadDetail({ task }: { task: DownloadTask }) {
|
||||
) : null}
|
||||
|
||||
<DetailSection title="进度">
|
||||
<ProgressLine t={task} />
|
||||
<ProgressLine t={live ? { ...task, progress: live.progress } : task} />
|
||||
<KvList
|
||||
className="mt-3"
|
||||
items={[
|
||||
{ label: "下载器", value: names.data?.get(task.instanceId) ?? task.instanceId.slice(0, 8) },
|
||||
{ label: "大小", value: task.sizeBytes === null ? "未知" : formatBytes(task.sizeBytes, 2) },
|
||||
{ label: "剩余", value: task.remainingBytes === null ? "未知" : formatBytes(task.remainingBytes, 2) },
|
||||
...liveItems(live),
|
||||
{ label: "分享率", value: task.ratio === null ? "—" : task.ratio.toFixed(2) },
|
||||
{ label: "最近进展", value: relTime(task.lastProgressAt) },
|
||||
{ label: "最近同步", value: relTime(task.lastSyncedAt) },
|
||||
|
||||
Reference in new issue
Block a user