mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-26 14:35:22 +08:00
ec6e113cf2
- Update version in package.json, Cargo.toml, tauri.conf.json - Add CHANGELOG entry for v3.9.0-beta.1 with: - Local Proxy Server feature - Auto Failover with circuit breaker - Skills multi-app support - Provider icon colors - 25+ bug fixes - Add proxy feature guide documentation (Chinese)
193 lines
5.8 KiB
TypeScript
193 lines
5.8 KiB
TypeScript
/**
|
|
* 代理服务状态管理 Hook
|
|
*/
|
|
|
|
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
import { invoke } from "@tauri-apps/api/core";
|
|
import { toast } from "sonner";
|
|
import { useTranslation } from "react-i18next";
|
|
import type {
|
|
ProxyStatus,
|
|
ProxyServerInfo,
|
|
ProxyTakeoverStatus,
|
|
} from "@/types/proxy";
|
|
import { extractErrorMessage } from "@/utils/errorUtils";
|
|
|
|
/**
|
|
* 代理服务状态管理
|
|
*/
|
|
export function useProxyStatus() {
|
|
const queryClient = useQueryClient();
|
|
const { t } = useTranslation();
|
|
|
|
// 查询状态(自动轮询)
|
|
const { data: status, isLoading } = useQuery({
|
|
queryKey: ["proxyStatus"],
|
|
queryFn: () => invoke<ProxyStatus>("get_proxy_status"),
|
|
// 仅在服务运行时轮询
|
|
refetchInterval: (query) => (query.state.data?.running ? 2000 : false),
|
|
// 保持之前的数据,避免闪烁
|
|
placeholderData: (previousData) => previousData,
|
|
});
|
|
|
|
// 查询各应用接管状态
|
|
const { data: takeoverStatus } = useQuery({
|
|
queryKey: ["proxyTakeoverStatus"],
|
|
queryFn: () => invoke<ProxyTakeoverStatus>("get_proxy_takeover_status"),
|
|
placeholderData: (previousData) => previousData,
|
|
});
|
|
|
|
// 启动服务器(总开关:仅启动服务,不接管)
|
|
const startProxyServerMutation = useMutation({
|
|
mutationFn: () => invoke<ProxyServerInfo>("start_proxy_server"),
|
|
onSuccess: (info) => {
|
|
toast.success(
|
|
t("proxy.server.started", {
|
|
defaultValue: `代理服务已启动 - ${info.address}:${info.port}`,
|
|
}),
|
|
{ closeButton: true },
|
|
);
|
|
queryClient.invalidateQueries({ queryKey: ["proxyStatus"] });
|
|
},
|
|
onError: (error: Error) => {
|
|
const detail = extractErrorMessage(error) || "未知错误";
|
|
toast.error(
|
|
t("proxy.server.startFailed", {
|
|
defaultValue: `启动代理服务失败: ${detail}`,
|
|
}),
|
|
);
|
|
},
|
|
});
|
|
|
|
// 停止服务器(总开关关闭:强制恢复所有已接管的 Live 配置)
|
|
const stopWithRestoreMutation = useMutation({
|
|
mutationFn: () => invoke("stop_proxy_with_restore"),
|
|
onSuccess: () => {
|
|
toast.success(
|
|
t("proxy.stoppedWithRestore", {
|
|
defaultValue: "代理服务已关闭,已恢复所有接管配置",
|
|
}),
|
|
{ closeButton: true },
|
|
);
|
|
queryClient.invalidateQueries({ queryKey: ["proxyStatus"] });
|
|
queryClient.invalidateQueries({ queryKey: ["proxyTakeoverStatus"] });
|
|
// 清除所有供应商健康状态缓存(后端已清空数据库记录)
|
|
queryClient.invalidateQueries({ queryKey: ["providerHealth"] });
|
|
},
|
|
onError: (error: Error) => {
|
|
const detail = extractErrorMessage(error) || "未知错误";
|
|
toast.error(
|
|
t("proxy.stopWithRestoreFailed", {
|
|
defaultValue: `停止失败: ${detail}`,
|
|
}),
|
|
);
|
|
},
|
|
});
|
|
|
|
// 按应用开启/关闭接管
|
|
const setTakeoverForAppMutation = useMutation({
|
|
mutationFn: ({ appType, enabled }: { appType: string; enabled: boolean }) =>
|
|
invoke("set_proxy_takeover_for_app", { appType, enabled }),
|
|
onSuccess: (_data, variables) => {
|
|
const appLabel =
|
|
variables.appType === "claude"
|
|
? "Claude"
|
|
: variables.appType === "codex"
|
|
? "Codex"
|
|
: "Gemini";
|
|
|
|
toast.success(
|
|
variables.enabled
|
|
? t("proxy.takeover.enabled", {
|
|
defaultValue: `已接管 ${appLabel} 配置(请求将走本地代理)`,
|
|
})
|
|
: t("proxy.takeover.disabled", {
|
|
defaultValue: `已恢复 ${appLabel} 配置`,
|
|
}),
|
|
{ closeButton: true },
|
|
);
|
|
|
|
queryClient.invalidateQueries({ queryKey: ["proxyStatus"] });
|
|
queryClient.invalidateQueries({ queryKey: ["proxyTakeoverStatus"] });
|
|
},
|
|
onError: (error: Error) => {
|
|
const detail = extractErrorMessage(error) || "未知错误";
|
|
toast.error(
|
|
t("proxy.takeover.failed", {
|
|
defaultValue: `操作失败: ${detail}`,
|
|
}),
|
|
);
|
|
},
|
|
});
|
|
|
|
// 代理模式切换供应商(热切换)
|
|
const switchProxyProviderMutation = useMutation({
|
|
mutationFn: ({
|
|
appType,
|
|
providerId,
|
|
}: {
|
|
appType: string;
|
|
providerId: string;
|
|
}) => invoke("switch_proxy_provider", { appType, providerId }),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ["proxyStatus"] });
|
|
},
|
|
onError: (error: Error) => {
|
|
const detail = extractErrorMessage(error) || "未知错误";
|
|
toast.error(`切换失败: ${detail}`);
|
|
},
|
|
});
|
|
|
|
// 检查是否运行中
|
|
const checkRunning = async () => {
|
|
try {
|
|
return await invoke<boolean>("is_proxy_running");
|
|
} catch {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
// 检查接管状态
|
|
const checkTakeoverActive = async () => {
|
|
try {
|
|
return await invoke<boolean>("is_live_takeover_active");
|
|
} catch {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
return {
|
|
status,
|
|
isLoading,
|
|
isRunning: status?.running || false,
|
|
takeoverStatus,
|
|
isTakeoverActive:
|
|
takeoverStatus?.claude ||
|
|
takeoverStatus?.codex ||
|
|
takeoverStatus?.gemini ||
|
|
false,
|
|
|
|
// 启动/停止(总开关)
|
|
startProxyServer: startProxyServerMutation.mutateAsync,
|
|
stopWithRestore: stopWithRestoreMutation.mutateAsync,
|
|
|
|
// 按应用接管开关
|
|
setTakeoverForApp: setTakeoverForAppMutation.mutateAsync,
|
|
|
|
// 代理模式下切换供应商
|
|
switchProxyProvider: switchProxyProviderMutation.mutateAsync,
|
|
|
|
// 状态检查
|
|
checkRunning,
|
|
checkTakeoverActive,
|
|
|
|
// 加载状态
|
|
isStarting: startProxyServerMutation.isPending,
|
|
isStopping: stopWithRestoreMutation.isPending,
|
|
isPending:
|
|
startProxyServerMutation.isPending ||
|
|
stopWithRestoreMutation.isPending ||
|
|
setTakeoverForAppMutation.isPending,
|
|
};
|
|
}
|