import type { DownloadBoardPlanItem } from "@umt/contracts"; import { Check, X } from "lucide-react"; import { Link } from "react-router"; import { toast } from "sonner"; import { useDecideApproval, useIsAdminSession } from "~/api/agent.ts"; import { useCancelPlan, usePlanWhy } from "~/api/downloads.ts"; import { ConfirmDialog } from "~/components/console/confirm-dialog.tsx"; import { DetailSection } from "~/components/console/detail-sheet.tsx"; import { JsonView } from "~/components/console/json-view.tsx"; import { KvList } from "~/components/console/kv-list.tsx"; import { consolePath } from "~/components/console/nav.ts"; import { StatusBadge } from "~/components/console/status-badge.tsx"; import { TechInfo } from "~/components/console/tech-info.tsx"; import { Button } from "~/components/ui/button.tsx"; import { errorMessage } from "~/lib/api.ts"; import { reasonCode } from "~/lib/reasons.ts"; import { formatBytes, formatDateTime } from "~/lib/utils.ts"; import { PLAN_WAIT, PURPOSE_LABEL, planWaitHint, whyText } from "./plan-format.ts"; // DL-3:还没提交到下载器的下载(等批准 / 等磁盘空间 / 等开启自动化 / 准备提交)在下载面板里的状态、操作与详情; // 已提交的下载在详情里显示「为什么下这个」。 export function PlanWaitBadge({ p, hint = false }: { p: DownloadBoardPlanItem; hint?: boolean }) { const w = PLAN_WAIT[p.wait]; const h = hint ? planWaitHint(p) : null; return ( {w.label} {h ? {h} : null} ); } /** 批准 / 取消:等批准的走审批(拒绝后服务端取消这次下载);其余直接取消。都要确认 */ export function PlanActions({ p, size = "sm" }: { p: DownloadBoardPlanItem; size?: "sm" | "xs" }) { const decide = useDecideApproval(); const cancel = useCancelPlan(); const admin = useIsAdminSession(); const approval = p.approval; const stop = (e: { stopPropagation: () => void }) => e.stopPropagation(); const decideApproval = (status: "approved" | "rejected") => decide .mutateAsync({ id: approval?.id ?? "", status, payloadHash: approval?.payloadHash ?? "", ...(status === "rejected" ? { reason: "在下载面板取消" } : {}), }) .then( () => toast.success(status === "approved" ? "已批准,开始提交下载" : "已取消这次下载"), (err) => { toast.error(errorMessage(err)); throw err; }, ); return ( // biome-ignore lint/a11y/noStaticElementInteractions: 只拦截行点击 {approval ? ( 批准 } title={`批准下载「${p.name}」?`} description={`${p.sizeBytes !== null ? `${formatBytes(p.sizeBytes, 1)},` : ""}批准后立即提交到下载器。`} confirmLabel="批准" onConfirm={() => decideApproval("approved")} /> ) : null} 取消 } title={`取消下载「${p.name}」?`} description={ approval ? "不批准这次下载,智能体会收到结果。" : "释放为它预留的空间和额度,收录版本之后会重新找资源。" } confirmLabel="取消下载" cancelLabel="返回" destructive onConfirm={() => approval ? decideApproval("rejected") : cancel.mutateAsync(p.id).then( () => toast.success("已取消这次下载"), (err) => { toast.error(errorMessage(err)); throw err; }, ) } /> ); } /** 「为什么下这个」:来源 · 目的,下一行选中理由要点;原始评估进技术信息 */ export function WhySection({ planId, extraTech, }: { planId: string; extraTech?: { label: string; value: string | null }[]; }) { const why = usePlanWhy(planId); if (why.isPending || !why.data) return null; const t = whyText(why.data); return (

{t.head}

{t.points ?

{t.points}

: null} ({ ...x, wide: true })), ]} >
); } /** 还没提交的下载的详情(抽屉内容) */ export function PlanDetail({ p }: { p: DownloadBoardPlanItem }) { const hint = planWaitHint(p); return (
{PLAN_WAIT[p.wait].label}
{p.wait === "approval" ? (

这次下载要你批准后才提交,铃铛里也有提醒。

) : hint ? (

{hint}。

) : null} {p.media.title} {p.media.year ? ` (${p.media.year})` : ""} ) : null, }, { label: "大小", value: p.sizeBytes === null ? "未知" : formatBytes(p.sizeBytes, 2) }, { label: "用途", value: PURPOSE_LABEL[p.purpose] }, { label: "加入时间", value: formatDateTime(p.createdAt) }, ]} />
); }