import type { LocalMediaHit, MediaKind, SearchInventoryState, SearchSiteStatus } from "@umt/contracts"; import { Compass, type LucideIcon, Zap } from "lucide-react"; import type { StatusTone } from "~/components/console/status-badge.tsx"; import { MEDIA_KIND } from "~/components/library/labels.ts"; // 搜索结果的展示口径 export const mediaKindLabel = (k: MediaKind) => MEDIA_KIND[k] ?? k; /** 本地作品的一行摘要:订阅 / 版本 / 下载中 / 缺口 */ export function slotSummary(h: LocalMediaHit): string { const c = h.slotCounts; const parts: string[] = []; if (h.subscribed) parts.push("已订阅"); if (h.versionCount) parts.push(`${h.versionCount} 个版本`); if (h.downloadingCount) parts.push(`${h.downloadingCount} 个下载中`); const gaps = c.empty + c.attention + c.upgrade_pending; if (gaps) parts.push(`${gaps} 个收录版本未满足`); return parts.join(" · ") || "未订阅"; } export const actionIcon = (kind: "page" | "action"): LucideIcon => (kind === "page" ? Compass : Zap); export const INVENTORY_STATE: Record = { downloading: { label: "下载中", tone: "warning" }, gap: { label: "有缺口", tone: "warning" }, owned: { label: "已有版本", tone: "success" }, subscribed: { label: "已订阅", tone: "neutral" }, none: { label: "本地无版本", tone: "neutral" }, }; export const SITE_STATUS: Record = { ok: "正常", failed: "失败", timeout: "超时", skipped: "跳过", }; export const SORT_OPTIONS = [ { value: "default", label: "默认" }, { value: "seeders", label: "做种数" }, { value: "size", label: "大小" }, { value: "uploadedAt", label: "发布时间" }, { value: "site", label: "站点" }, ] as const; const PROMO: Record = { free: "免费", "2xfree": "2x 免费", "50%": "50%", "2x50%": "2x 50%", "30%": "30%", "2x": "2x 上传", }; /** 促销文案;none/unknown 返回 null */ export function promoLabel(type: string): string | null { if (!type || type === "none" || type === "unknown") return null; return PROMO[type] ?? type; } const GB = 1024 ** 3; export const gbToBytes = (s: string): number | undefined => { const n = Number(s); return s.trim() && Number.isFinite(n) && n >= 0 ? Math.round(n * GB) : undefined; };