Files
CC-Switch/src/components/proxy/ProxyToggle.tsx
T
Jason 5cc864c6aa fix(proxy): resolve 404 error and auto-setup proxy targets
Issues fixed:
1. Route prefix mismatch - Live config was set to use /claude, /codex,
   /gemini prefixes but server only had routes without prefixes
2. Proxy targets not auto-configured - start_with_takeover only modified
   Live config but didn't set is_proxy_target=true for current providers

Changes:
- Add prefixed routes (/claude/v1/messages, /codex/v1/*, /gemini/v1beta/*)
  to server.rs for backward compatibility
- Remove URL prefixes from takeover_live_configs() - server can route
  by API endpoint path alone (/v1/messages=Claude, /v1/chat/completions=Codex)
- Add setup_proxy_targets() method that automatically sets current providers
  as proxy targets when starting proxy with takeover
- Unify proxy toggle in SettingsPage to use takeover mode (same as main UI)
- Fix error message extraction in useProxyStatus hooks
- Fix provider switch logic to check both takeover flag AND proxy running state
2025-12-10 19:58:43 +08:00

83 lines
2.0 KiB
TypeScript

/**
* 代理模式切换开关组件
*
* 放置在主界面头部,用于一键启用/关闭代理模式
* 启用时自动接管 Live 配置,关闭时恢复原始配置
*/
import { Radio, Loader2 } from "lucide-react";
import { Switch } from "@/components/ui/switch";
import { useProxyStatus } from "@/hooks/useProxyStatus";
import { cn } from "@/lib/utils";
interface ProxyToggleProps {
className?: string;
}
export function ProxyToggle({ className }: ProxyToggleProps) {
const {
isRunning,
isTakeoverActive,
startWithTakeover,
stopWithRestore,
isPending,
status,
} = useProxyStatus();
const handleToggle = async (checked: boolean) => {
if (checked) {
await startWithTakeover();
} else {
await stopWithRestore();
}
};
const isActive = isRunning && isTakeoverActive;
const tooltipText = isActive
? `代理模式运行中 - ${status?.address}:${status?.port}\n切换供应商为热切换`
: "开启代理模式\n启用后自动接管 Live 配置";
return (
<div
className={cn(
"flex items-center gap-2 px-3 py-1.5 rounded-lg transition-all cursor-default",
isActive
? "bg-emerald-500/10 border border-emerald-500/30"
: "bg-muted/50 hover:bg-muted",
className,
)}
title={tooltipText}
>
{isPending ? (
<Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
) : (
<Radio
className={cn(
"h-4 w-4 transition-colors",
isActive
? "text-emerald-500 animate-pulse"
: "text-muted-foreground",
)}
/>
)}
<span
className={cn(
"text-sm font-medium transition-colors select-none",
isActive
? "text-emerald-600 dark:text-emerald-400"
: "text-muted-foreground",
)}
>
Proxy
</span>
<Switch
checked={isActive}
onCheckedChange={handleToggle}
disabled={isPending}
className="ml-1"
/>
</div>
);
}