'use client'; import { useEffect, useMemo, useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { ProxyRouteService } from '@/lib/services/openflare'; type UptimeKumaSiteSelectModalProps = { open: boolean; selectedSites: string[]; onOpenChange: (open: boolean) => void; onSave: (sites: string[]) => void; }; export function UptimeKumaSiteSelectModal({ open, selectedSites, onOpenChange, onSave, }: UptimeKumaSiteSelectModalProps) { const [searchTerm, setSearchTerm] = useState(''); const [tempSelected, setTempSelected] = useState>(new Set()); const routesQuery = useQuery({ queryKey: ['openflare', 'proxy-routes'], queryFn: () => ProxyRouteService.list(), enabled: open, }); useEffect(() => { if (!open) return; setTempSelected( new Set(selectedSites.map((site) => site.trim()).filter(Boolean)), ); setSearchTerm(''); }, [open, selectedSites]); const filteredRoutes = useMemo(() => { const routes = routesQuery.data ?? []; const keyword = searchTerm.trim().toLowerCase(); if (!keyword) return routes; return routes.filter((route) => { const domains = (route.zone_domains ?? []) .map((item) => item.domain) .join(' '); return ( route.site_name.toLowerCase().includes(keyword) || domains.toLowerCase().includes(keyword) ); }); }, [routesQuery.data, searchTerm]); const toggleSite = (siteName: string) => { setTempSelected((previous) => { const next = new Set(previous); if (next.has(siteName)) next.delete(siteName); else next.add(siteName); return next; }); }; const handleSelectAll = () => { setTempSelected((previous) => { const next = new Set(previous); filteredRoutes.forEach((route) => next.add(route.site_name)); return next; }); }; const handleDeselectAll = () => { setTempSelected((previous) => { const next = new Set(previous); filteredRoutes.forEach((route) => next.delete(route.site_name)); return next; }); }; return ( 选择监控站点 选择要同步到 Uptime Kuma 的反代站点,支持按站点名称和域名搜索。
setSearchTerm(event.target.value)} placeholder='按名称或域名搜索...' />
{routesQuery.isLoading ? (

加载站点列表...

) : routesQuery.isError ? (

{routesQuery.error instanceof Error ? routesQuery.error.message : '加载站点失败'}

) : filteredRoutes.length === 0 ? (

无匹配的站点

) : ( {filteredRoutes.map((route) => { const checked = tempSelected.has(route.site_name); return ( toggleSite(route.site_name)} > ); })}
选择 站点名称 主域名
event.stopPropagation()} > toggleSite(route.site_name)} className='size-4 rounded border-input' /> {route.site_name} {(route.zone_domains ?? []) .map((item) => item.domain) .join(', ') || '—'}
)}

已选择 {tempSelected.size} 个监控站点

); }