"use client"; import { ServerApi } from "@/app/types/nezha-api"; import ServerCard from "@/components/ServerCard"; import ServerCardInline from "@/components/ServerCardInline"; import Switch from "@/components/Switch"; import getEnv from "@/lib/env-entry"; import { useFilter } from "@/lib/network-filter-context"; import { useStatus } from "@/lib/status-context"; import { cn, nezhaFetcher } from "@/lib/utils"; import { MapIcon, ViewColumnsIcon } from "@heroicons/react/20/solid"; import { useTranslations } from "next-intl"; import { useRouter } from "next/navigation"; import { useEffect, useRef, useState } from "react"; import useSWR from "swr"; export default function ServerListClient() { const { status } = useStatus(); const { filter } = useFilter(); const t = useTranslations("ServerListClient"); const containerRef = useRef(null); const defaultTag = "defaultTag"; const router = useRouter(); const [tag, setTag] = useState(defaultTag); const [inline, setInline] = useState("0"); useEffect(() => { const inlineState = localStorage.getItem("inline"); if (inlineState !== null) { console.log("inlineState", inlineState); setInline(inlineState); } }, []); useEffect(() => { const savedTag = sessionStorage.getItem("selectedTag") || defaultTag; setTag(savedTag); restoreScrollPosition(); }, []); const handleTagChange = (newTag: string) => { setTag(newTag); sessionStorage.setItem("selectedTag", newTag); sessionStorage.setItem( "scrollPosition", String(containerRef.current?.scrollTop || 0), ); }; const restoreScrollPosition = () => { const savedPosition = sessionStorage.getItem("scrollPosition"); if (savedPosition && containerRef.current) { containerRef.current.scrollTop = Number(savedPosition); } }; useEffect(() => { const handleRouteChange = () => { restoreScrollPosition(); }; window.addEventListener("popstate", handleRouteChange); return () => { window.removeEventListener("popstate", handleRouteChange); }; }, []); const { data, error } = useSWR("/api/server", nezhaFetcher, { refreshInterval: Number(getEnv("NEXT_PUBLIC_NezhaFetchInterval")) || 2000, }); if (error) return (

{error.message}

{t("error_message")}

); if (!data?.result) return null; const { result } = data; const sortedServers = result.sort((a, b) => { const displayIndexDiff = (b.display_index || 0) - (a.display_index || 0); if (displayIndexDiff !== 0) return displayIndexDiff; return a.id - b.id; }); const filteredServersByStatus = status === "all" ? sortedServers : sortedServers.filter((server) => [status].includes(server.online_status ? "online" : "offline"), ); const allTag = filteredServersByStatus .map((server) => server.tag) .filter(Boolean); const uniqueTags = [...new Set(allTag)]; uniqueTags.unshift(defaultTag); const filteredServers = tag === defaultTag ? filteredServersByStatus : filteredServersByStatus.filter((server) => server.tag === tag); if (filter) { // 根据使用速度进行从高到低排序 filteredServers.sort((a, b) => { return ( b.status.NetInSpeed + b.status.NetOutSpeed - (a.status.NetInSpeed + b.status.NetOutSpeed) ); }); } const tagCountMap: Record = {}; filteredServersByStatus.forEach((server) => { if (server.tag) { tagCountMap[server.tag] = (tagCountMap[server.tag] || 0) + 1; } }); return ( <>
{getEnv("NEXT_PUBLIC_ShowTag") === "true" && ( )}
{inline === "1" && (
{filteredServers.map((serverInfo) => ( ))}
)} {inline === "0" && (
{filteredServers.map((serverInfo) => ( ))}
)} ); }