"use client"; import { useEffect, useState } from "react"; import { Activity, Clock3, RadioTower, RefreshCw, Sparkles } from "lucide-react"; import { fetchJson } from "@/lib/fetch-json"; import { cn } from "@/lib/utils"; import { RECOMMENDATION_CARRIERS, carrierLabels, type LatencyRecommendation, } from "@/services/latency-recommendation-types"; interface RecommendationPayload { items: LatencyRecommendation[]; updatedAt: string; refreshIntervalMs: number; } const REFRESH_INTERVAL_MS = 5 * 60 * 1000; export const OPEN_PROXY_PLAN_EVENT = "jboard:open-proxy-plan"; function formatTime(value: string | null) { if (!value) return "等待刷新"; return new Date(value).toLocaleTimeString("zh-CN", { hour: "2-digit", minute: "2-digit", }); } function getLatencyTone(latencyMs?: number) { if (latencyMs == null) return "border-dashed bg-muted/20 text-muted-foreground"; if (latencyMs <= 80) return "border-emerald-500/20 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300"; if (latencyMs <= 150) return "border-primary/20 bg-primary/10 text-primary"; return "border-amber-500/20 bg-amber-500/10 text-amber-700 dark:text-amber-300"; } function openRecommendedPlan(planId: string) { window.dispatchEvent( new CustomEvent(OPEN_PROXY_PLAN_EVENT, { detail: { planId }, }), ); } export function StoreLatencyRecommendations({ initialItems, }: { initialItems: LatencyRecommendation[]; }) { const [items, setItems] = useState(initialItems); const [updatedAt, setUpdatedAt] = useState(initialItems[0]?.checkedAt ?? null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); useEffect(() => { let cancelled = false; async function load() { setLoading(true); try { const payload = await fetchJson("/api/latency/recommendations"); if (cancelled) return; setItems(payload.items); setUpdatedAt(payload.updatedAt); setError(null); } catch { if (!cancelled) setError("推荐线路暂时无法刷新"); } finally { if (!cancelled) setLoading(false); } } const timer = window.setInterval(() => void load(), REFRESH_INTERVAL_MS); return () => { cancelled = true; window.clearInterval(timer); }; }, []); const itemMap = new Map(items.map((item) => [item.carrier, item])); return (
三网推荐

按最低延迟优先选节点

三网最低延迟,5 分钟刷新。

{loading ? : } {formatTime(updatedAt)} 更新 {error && 自动重试中}
{RECOMMENDATION_CARRIERS.map((carrier) => { const item = itemMap.get(carrier); return ( ); })}
); }