'use client'; import { useEffect, useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { ErrorState } from '@/components/feedback/error-state'; import { LoadingState } from '@/components/feedback/loading-state'; import { AppModal } from '@/components/ui/app-modal'; import { getProxyRoutes } from '@/features/proxy-routes/api/proxy-routes'; import { PrimaryButton, ResourceField, ResourceInput, SecondaryButton, } from '@/features/shared/components/resource-primitives'; function getErrorMessage(error: unknown) { return error instanceof Error ? error.message : '加载站点列表失败。'; } export function UptimeKumaSiteSelectModal({ isOpen, selectedSites, onClose, onSave, }: { isOpen: boolean; selectedSites: string[]; onClose: () => void; onSave: (sites: string[]) => void; }) { const [searchTerm, setSearchTerm] = useState(''); const [tempSelected, setTempSelected] = useState>(new Set()); const { data: routes = [], isLoading, error } = useQuery({ queryKey: ['proxy-routes'], queryFn: getProxyRoutes, enabled: isOpen, }); useEffect(() => { if (isOpen) { setTempSelected(new Set(selectedSites.map(s => s.trim()).filter(Boolean))); setSearchTerm(''); } }, [isOpen, selectedSites]); const toggleSite = (siteName: string) => { setTempSelected((prev) => { const next = new Set(prev); if (next.has(siteName)) { next.delete(siteName); } else { next.add(siteName); } return next; }); }; const handleSelectAll = () => { setTempSelected((prev) => { const next = new Set(prev); filteredRoutes.forEach((route) => { next.add(route.site_name); }); return next; }); }; const handleDeselectAll = () => { setTempSelected((prev) => { const next = new Set(prev); filteredRoutes.forEach((route) => { next.delete(route.site_name); }); return next; }); }; const handleSave = () => { onSave(Array.from(tempSelected)); onClose(); }; const filteredRoutes = routes.filter( (route) => route.site_name.toLowerCase().includes(searchTerm.toLowerCase()) || route.primary_domain.toLowerCase().includes(searchTerm.toLowerCase()), ); return ( 取消 保存选择 } >
setSearchTerm(event.target.value)} placeholder="按名称或域名搜索..." />
全选过滤项 清空过滤项
{isLoading ? : null} {error ? ( ) : null} {!isLoading && !error && routes.length === 0 ? (
暂无可用的代理站点。
) : null} {!isLoading && !error && routes.length > 0 ? (
{filteredRoutes.map((route) => { const isChecked = tempSelected.has(route.site_name); return ( toggleSite(route.site_name)} className="cursor-pointer hover:bg-[var(--surface-elevated)]" > ); })} {filteredRoutes.length === 0 ? ( ) : null}
选择 站点名称 主域名 状态
e.stopPropagation()}> toggleSite(route.site_name)} className="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500" /> {route.site_name} {route.primary_domain} {route.enabled ? '启用' : '禁用'}
无匹配的站点
) : null}
已选择 {tempSelected.size} 个监控站点
); }