import { useState, useEffect } from "react";
import {
Activity,
Clock,
TrendingUp,
Server,
ListOrdered,
Save,
Loader2,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Switch } from "@/components/ui/switch";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { useProxyStatus } from "@/hooks/useProxyStatus";
import { toast } from "sonner";
import { useFailoverQueue } from "@/lib/query/failover";
import { ProviderHealthBadge } from "@/components/providers/ProviderHealthBadge";
import { useProviderHealth } from "@/lib/query/failover";
import {
useProxyTakeoverStatus,
useSetProxyTakeoverForApp,
useGlobalProxyConfig,
useUpdateGlobalProxyConfig,
} from "@/lib/query/proxy";
import type { ProxyStatus } from "@/types/proxy";
import { useTranslation } from "react-i18next";
export function ProxyPanel() {
const { t } = useTranslation();
const { status, isRunning } = useProxyStatus();
// 获取应用接管状态
const { data: takeoverStatus } = useProxyTakeoverStatus();
const setTakeoverForApp = useSetProxyTakeoverForApp();
// 获取全局代理配置
const { data: globalConfig } = useGlobalProxyConfig();
const updateGlobalConfig = useUpdateGlobalProxyConfig();
// 监听地址/端口的本地状态
const [listenAddress, setListenAddress] = useState("127.0.0.1");
const [listenPort, setListenPort] = useState(5000);
// 同步全局配置到本地状态
useEffect(() => {
if (globalConfig) {
setListenAddress(globalConfig.listenAddress);
setListenPort(globalConfig.listenPort);
}
}, [globalConfig]);
// 获取所有三个应用类型的故障转移队列(不包含当前供应商)
// 当前供应商始终优先,队列仅用于失败后的备用顺序
const { data: claudeQueue = [] } = useFailoverQueue("claude");
const { data: codexQueue = [] } = useFailoverQueue("codex");
const { data: geminiQueue = [] } = useFailoverQueue("gemini");
const handleTakeoverChange = async (appType: string, enabled: boolean) => {
try {
await setTakeoverForApp.mutateAsync({ appType, enabled });
toast.success(
enabled
? t("proxy.takeover.enabled", {
app: appType,
defaultValue: `${appType} 接管已启用`,
})
: t("proxy.takeover.disabled", {
app: appType,
defaultValue: `${appType} 接管已关闭`,
}),
{ closeButton: true },
);
} catch (error) {
toast.error(
t("proxy.takeover.failed", {
defaultValue: "切换接管状态失败",
}),
);
}
};
const handleLoggingChange = async (enabled: boolean) => {
if (!globalConfig) return;
try {
await updateGlobalConfig.mutateAsync({
...globalConfig,
enableLogging: enabled,
});
toast.success(
enabled
? t("proxy.logging.enabled", { defaultValue: "日志记录已启用" })
: t("proxy.logging.disabled", { defaultValue: "日志记录已关闭" }),
{ closeButton: true },
);
} catch (error) {
toast.error(
t("proxy.logging.failed", { defaultValue: "切换日志状态失败" }),
);
}
};
const handleSaveBasicConfig = async () => {
if (!globalConfig) return;
try {
await updateGlobalConfig.mutateAsync({
...globalConfig,
listenAddress,
listenPort,
});
toast.success(
t("proxy.settings.configSaved", { defaultValue: "代理配置已保存" }),
{ closeButton: true },
);
} catch (error) {
toast.error(
t("proxy.settings.configSaveFailed", { defaultValue: "保存配置失败" }),
);
}
};
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 (
<>
{t("proxy.panel.serviceAddress", {
defaultValue: "服务地址",
})}
{t("proxy.settings.restartRequired", {
defaultValue: "修改监听地址/端口需要先停止代理服务",
})}
{t("provider.inUse")}
{t("proxy.panel.currentProvider", {
defaultValue: "当前 Provider:",
})}{" "}
{status.current_provider}
{t("proxy.panel.waitingFirstRequest", {
defaultValue: "当前 Provider:等待首次请求…",
})}
{t("proxyConfig.appTakeover", {
defaultValue: "应用接管",
})}
{t("proxy.settings.fields.enableLogging.description", {
defaultValue: "记录所有代理请求,便于排查问题",
})}
{t("proxy.failoverQueue.title")}
{t("proxy.settings.basic.description", {
defaultValue: "配置代理服务监听的地址与端口。",
})}
{t("proxy.settings.fields.listenAddress.description", {
defaultValue:
"代理服务器监听的 IP 地址(推荐 127.0.0.1)",
})}
{t("proxy.settings.fields.listenPort.description", {
defaultValue: "代理服务器监听的端口号(1024 ~ 65535)",
})}
{t("proxy.panel.stoppedTitle", {
defaultValue: "代理服务已停止",
})}
{t("proxy.panel.stoppedDescription", {
defaultValue: "使用右上角开关即可启动服务",
})}
http://{status.address}:{status.port}
{t("proxy.settings.basic.title", {
defaultValue: "基础设置",
})}
{value}