import { useState } from "react"; import { Activity, Clock, TrendingUp, Server, ListOrdered, Settings, } from "lucide-react"; import { Button } from "@/components/ui/button"; import { useProxyStatus } from "@/hooks/useProxyStatus"; import { ProxySettingsDialog } from "./ProxySettingsDialog"; import { toast } from "sonner"; import { useProxyTargets } from "@/lib/query/failover"; import { ProviderHealthBadge } from "@/components/providers/ProviderHealthBadge"; import { useProviderHealth } from "@/lib/query/failover"; import type { ProxyStatus } from "@/types/proxy"; export function ProxyPanel() { const { status, isRunning } = useProxyStatus(); const [showSettings, setShowSettings] = useState(false); // 获取所有三个应用类型的代理目标列表 const { data: claudeTargets = [] } = useProxyTargets("claude"); const { data: codexTargets = [] } = useProxyTargets("codex"); const { data: geminiTargets = [] } = useProxyTargets("gemini"); const formatUptime = (seconds: number): string => { const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); const secs = seconds % 60; if (hours > 0) { return `${hours}h ${minutes}m ${secs}s`; } else if (minutes > 0) { return `${minutes}m ${secs}s`; } else { return `${secs}s`; } }; return ( <>
{isRunning && status ? (

服务地址

http://{status.address}:{status.port}

使用中

{status.active_targets && status.active_targets.length > 0 ? (
{status.active_targets.map((target) => (
{target.app_type} {target.provider_name}
))}
) : status.current_provider ? (

当前 Provider:{" "} {status.current_provider}

) : (

当前 Provider:等待首次请求…

)}
{/* 供应商队列 - 按应用类型分组展示 */} {(claudeTargets.length > 0 || codexTargets.length > 0 || geminiTargets.length > 0) && (

故障转移队列

{/* Claude 队列 */} {claudeTargets.length > 0 && ( )} {/* Codex 队列 */} {codexTargets.length > 0 && ( )} {/* Gemini 队列 */} {geminiTargets.length > 0 && ( )}
)}
} label="活跃连接" value={status.active_connections} /> } label="总请求数" value={status.total_requests} /> } label="成功率" value={`${status.success_rate.toFixed(1)}%`} variant={status.success_rate > 90 ? "success" : "warning"} /> } label="运行时间" value={formatUptime(status.uptime_seconds)} />
) : (

代理服务已停止

使用右上角开关即可启动服务

)}
); } interface StatCardProps { icon: React.ReactNode; label: string; value: string | number; variant?: "default" | "success" | "warning"; } function StatCard({ icon, label, value, variant = "default" }: StatCardProps) { const variantStyles = { default: "", success: "border-green-500/40 bg-green-500/5", warning: "border-yellow-500/40 bg-yellow-500/5", }; return (
{icon} {label}

{value}

); } interface ProviderQueueGroupProps { appType: string; appLabel: string; targets: Array<{ id: string; name: string; }>; status: ProxyStatus; } function ProviderQueueGroup({ appType, appLabel, targets, status, }: ProviderQueueGroupProps) { // 查找该应用类型的当前活跃目标 const activeTarget = status.active_targets?.find( (t) => t.app_type === appType, ); return (
{/* 应用类型标题 */}
{appLabel}
{/* 供应商列表 */}
{targets.map((target, index) => ( ))}
); } interface ProviderQueueItemProps { provider: { id: string; name: string; }; priority: number; appType: string; isCurrent: boolean; } function ProviderQueueItem({ provider, priority, appType, isCurrent, }: ProviderQueueItemProps) { const { data: health } = useProviderHealth(provider.id, appType); return (
{priority} {provider.name} {isCurrent && ( 使用中 )}
{/* 健康徽章 */}
); }