diff --git a/src/components/DirectCountrySelect.tsx b/src/components/DirectCountrySelect.tsx new file mode 100644 index 0000000..27b9998 --- /dev/null +++ b/src/components/DirectCountrySelect.tsx @@ -0,0 +1,49 @@ +import { cn } from "@/lib/utils"; +import ServerFlag from "@/components/ServerFlag"; + +type DirectCountrySelectProps = { + countries: string[]; + currentCountry: string; + onChange: (country: string) => void; +}; + +// 这是一个简单的直接选择组件,避免可能的事件传播问题 +export default function DirectCountrySelect({ + countries, + currentCountry, + onChange +}: DirectCountrySelectProps) { + return ( +
+
+ + + {countries.map((country) => ( + + ))} +
+
+ ); +} \ No newline at end of file diff --git a/src/components/GroupSwitch.tsx b/src/components/GroupSwitch.tsx index b24ee8d..3c2ad99 100644 --- a/src/components/GroupSwitch.tsx +++ b/src/components/GroupSwitch.tsx @@ -43,56 +43,28 @@ export default function GroupSwitch({ } }, []) - useEffect(() => { - const container = scrollRef.current - if (!container) return - - const isOverflowing = container.scrollWidth > container.clientWidth - if (!isOverflowing) return - - const onWheel = (e: WheelEvent) => { - e.preventDefault() - container.scrollLeft += e.deltaY + // 处理标签点击 + function handleClick(tab: string) { + // 避免重复点击当前选中的标签 + if (tab === currentTab) return; + + try { + // 直接调用父组件传递的回调 + setCurrentTab(tab); + console.log(`[${isCountrySwitch ? '国家' : '分组'}] 切换到: ${tab}`); + + // 手动滚动到可见区域 + const index = tabs.indexOf(tab); + if (index !== -1 && tagRefs.current[index]?.current) { + tagRefs.current[index].current?.scrollIntoView({ + behavior: "smooth", + block: "nearest", + inline: "center" + }); + } + } catch (error) { + console.error('切换标签出错:', error); } - - container.addEventListener("wheel", onWheel, { passive: false }) - - return () => { - container.removeEventListener("wheel", onWheel) - } - }, []) - - useEffect(() => { - const storageKey = isCountrySwitch ? "selectedCountry" : "selectedGroup" - const savedValue = sessionStorage.getItem(storageKey) - if (savedValue && tabs.includes(savedValue)) { - setCurrentTab(savedValue) - } - }, [tabs, setCurrentTab, isCountrySwitch]) - - // 当tabs变化时更新tagRefs - useEffect(() => { - tagRefs.current = tabs.map(() => createRef()) - }, [tabs]) - - // 处理选中标签的滚动逻辑 - useEffect(() => { - const currentTagIndex = tabs.indexOf(currentTab) - if (currentTagIndex === -1) return // 如果当前选中的标签不在tabs中,不执行滚动 - - const currentTagRef = tagRefs.current[currentTagIndex] - if (currentTagRef && currentTagRef.current) { - currentTagRef.current.scrollIntoView({ - behavior: "smooth", - block: "nearest", - inline: "center", - }) - } - }, [currentTab, tabs]) - - const handleTabClick = (tab: string) => { - if (tab === currentTab) return; // 如果点击的是当前选中的标签,不执行操作 - setCurrentTab(tab) } return ( @@ -109,7 +81,7 @@ export default function GroupSwitch({
handleTabClick(tab)} + onClick={() => handleClick(tab)} className={cn( "relative cursor-pointer rounded-3xl px-2.5 py-[8px] text-[13px] font-[600] transition-all duration-500", currentTab === tab ? "text-black dark:text-white" : "text-stone-400 dark:text-stone-500", diff --git a/src/pages/Server.tsx b/src/pages/Server.tsx index 761cfcc..8bf80bd 100644 --- a/src/pages/Server.tsx +++ b/src/pages/Server.tsx @@ -1,5 +1,4 @@ import GlobalMap from "@/components/GlobalMap" -import GroupSwitch from "@/components/GroupSwitch" import ServerCard from "@/components/ServerCard" import ServerOverview from "@/components/ServerOverview" import { ServiceTracker } from "@/components/ServiceTracker" @@ -17,8 +16,9 @@ import { NezhaWebsocketResponse } from "@/types/nezha-api" import { ServerGroup } from "@/types/nezha-api" import { ArrowDownIcon, ArrowUpIcon, ArrowsUpDownIcon, ChartBarSquareIcon, MapIcon } from "@heroicons/react/20/solid" import { useQuery } from "@tanstack/react-query" -import { useEffect, useRef, useState } from "react" +import { useCallback, useEffect, useRef, useState } from "react" import { useTranslation } from "react-i18next" +import DirectCountrySelect from "@/components/DirectCountrySelect" export default function Servers() { const { t } = useTranslation() @@ -52,25 +52,16 @@ export default function Servers() { } } - const handleTagChange = (newGroup: string) => { - groupRef.current = newGroup - countryRef.current = "All" // 切换组时重置国家筛选 + const handleCountryChange = useCallback((newCountry: string) => { + countryRef.current = newCountry; - setCurrentGroup(newGroup) - setCurrentCountry("All") + // 强制立即更新状态 + setCurrentCountry(newCountry); - sessionStorage.setItem("selectedGroup", newGroup) - sessionStorage.setItem("selectedCountry", "All") - sessionStorage.setItem("scrollPosition", String(containerRef.current?.scrollTop || 0)) - } - - const handleCountryChange = (newCountry: string) => { - countryRef.current = newCountry - setCurrentCountry(newCountry) - - sessionStorage.setItem("selectedCountry", newCountry) - sessionStorage.setItem("scrollPosition", String(containerRef.current?.scrollTop || 0)) - } + // 保存到会话存储 + sessionStorage.setItem("selectedCountry", newCountry); + sessionStorage.setItem("scrollPosition", String(containerRef.current?.scrollTop || 0)); + }, []); useEffect(() => { const showServicesState = localStorage.getItem("showServices") @@ -124,6 +115,7 @@ export default function Servers() { useEffect(() => { if (!lastMessage || !initializedRef.current) return; + // 保持用户选择的筛选状态 setCurrentGroup(groupRef.current) setCurrentCountry(countryRef.current) }, [lastMessage]) @@ -137,15 +129,6 @@ export default function Servers() { .sort() : [] - const groupTabs = [ - "All", - ...(groupData?.data - ?.filter((item: ServerGroup) => { - return Array.isArray(item.servers) && item.servers.some((serverId) => nezhaWsData?.servers?.some((server) => server.id === serverId)) - }) - ?.map((item: ServerGroup) => item.group.name) || []), - ] - const countryTabs = [ "All", ...availableCountries.map(code => code.toUpperCase()) @@ -347,8 +330,6 @@ export default function Servers() { })} /> - - @@ -411,7 +392,17 @@ export default function Servers() {
{showMap === "1" && } {showServices === "1" && } -
+ + {/* 优化直接国家选择器 */} +
+ tab !== "All")} + currentCountry={currentCountry} + onChange={handleCountryChange} + /> +
+ +
{filteredServers.map((serverInfo) => { // 查找服务器所属的分组 const serverGroup = groupData?.data?.find(