diff --git a/src/components/proxy/AutoFailoverConfigPanel.tsx b/src/components/proxy/AutoFailoverConfigPanel.tsx
index 182dbce5c..9daeaed0d 100644
--- a/src/components/proxy/AutoFailoverConfigPanel.tsx
+++ b/src/components/proxy/AutoFailoverConfigPanel.tsx
@@ -6,51 +6,67 @@ import { Label } from "@/components/ui/label";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Save, Loader2, Info } from "lucide-react";
import { toast } from "sonner";
-import {
- useCircuitBreakerConfig,
- useUpdateCircuitBreakerConfig,
-} from "@/lib/query/failover";
+import { useAppProxyConfig, useUpdateAppProxyConfig } from "@/lib/query/proxy";
export interface AutoFailoverConfigPanelProps {
- enabled?: boolean;
- onEnabledChange?: (enabled: boolean) => void;
+ appType: string;
+ disabled?: boolean;
}
export function AutoFailoverConfigPanel({
- enabled = true,
- onEnabledChange: _onEnabledChange,
-}: AutoFailoverConfigPanelProps = {}) {
- // Note: onEnabledChange is currently unused but kept in the interface
- // for potential future use by parent components
- void _onEnabledChange;
+ appType,
+ disabled = false,
+}: AutoFailoverConfigPanelProps) {
const { t } = useTranslation();
- const { data: config, isLoading, error } = useCircuitBreakerConfig();
- const updateConfig = useUpdateCircuitBreakerConfig();
+ const { data: config, isLoading, error } = useAppProxyConfig(appType);
+ const updateConfig = useUpdateAppProxyConfig();
const [formData, setFormData] = useState({
- failureThreshold: 5,
- successThreshold: 2,
- timeoutSeconds: 60,
- errorRateThreshold: 0.5,
- minRequests: 10,
+ autoFailoverEnabled: false,
+ maxRetries: 3,
+ streamingFirstByteTimeout: 30,
+ streamingIdleTimeout: 60,
+ nonStreamingTimeout: 300,
+ circuitFailureThreshold: 5,
+ circuitSuccessThreshold: 2,
+ circuitTimeoutSeconds: 60,
+ circuitErrorRateThreshold: 0.5,
+ circuitMinRequests: 10,
});
useEffect(() => {
if (config) {
setFormData({
- ...config,
+ autoFailoverEnabled: config.autoFailoverEnabled,
+ maxRetries: config.maxRetries,
+ streamingFirstByteTimeout: config.streamingFirstByteTimeout,
+ streamingIdleTimeout: config.streamingIdleTimeout,
+ nonStreamingTimeout: config.nonStreamingTimeout,
+ circuitFailureThreshold: config.circuitFailureThreshold,
+ circuitSuccessThreshold: config.circuitSuccessThreshold,
+ circuitTimeoutSeconds: config.circuitTimeoutSeconds,
+ circuitErrorRateThreshold: config.circuitErrorRateThreshold,
+ circuitMinRequests: config.circuitMinRequests,
});
}
}, [config]);
const handleSave = async () => {
+ if (!config) return;
try {
await updateConfig.mutateAsync({
- failureThreshold: formData.failureThreshold,
- successThreshold: formData.successThreshold,
- timeoutSeconds: formData.timeoutSeconds,
- errorRateThreshold: formData.errorRateThreshold,
- minRequests: formData.minRequests,
+ appType,
+ enabled: config.enabled,
+ autoFailoverEnabled: formData.autoFailoverEnabled,
+ maxRetries: formData.maxRetries,
+ streamingFirstByteTimeout: formData.streamingFirstByteTimeout,
+ streamingIdleTimeout: formData.streamingIdleTimeout,
+ nonStreamingTimeout: formData.nonStreamingTimeout,
+ circuitFailureThreshold: formData.circuitFailureThreshold,
+ circuitSuccessThreshold: formData.circuitSuccessThreshold,
+ circuitTimeoutSeconds: formData.circuitTimeoutSeconds,
+ circuitErrorRateThreshold: formData.circuitErrorRateThreshold,
+ circuitMinRequests: formData.circuitMinRequests,
});
toast.success(
t("proxy.autoFailover.configSaved", "自动故障转移配置已保存"),
@@ -66,7 +82,16 @@ export function AutoFailoverConfigPanel({
const handleReset = () => {
if (config) {
setFormData({
- ...config,
+ autoFailoverEnabled: config.autoFailoverEnabled,
+ maxRetries: config.maxRetries,
+ streamingFirstByteTimeout: config.streamingFirstByteTimeout,
+ streamingIdleTimeout: config.streamingIdleTimeout,
+ nonStreamingTimeout: config.nonStreamingTimeout,
+ circuitFailureThreshold: config.circuitFailureThreshold,
+ circuitSuccessThreshold: config.circuitSuccessThreshold,
+ circuitTimeoutSeconds: config.circuitTimeoutSeconds,
+ circuitErrorRateThreshold: config.circuitErrorRateThreshold,
+ circuitMinRequests: config.circuitMinRequests,
});
}
};
@@ -79,16 +104,10 @@ export function AutoFailoverConfigPanel({
);
}
+ const isDisabled = disabled || updateConfig.isPending;
+
return (
- {/* Header Switch moved to parent accordion logic or kept here absolutely positioned if styling permits.
- Since we need it in the accordion header, and this component is inside the content, we can use a portal or
- absolute positioning trick similar to ProxyPanel, OR cleaner, just duplicate the switch logic in SettingsPage
- and pass it down. But for now, let's use the absolute positioning trick to "lift" it visually.
- Better yet, let's just render the content directly without the wrapping Card header/collapse logic
- since the user requested "click to expand is detailed info, no need to fold again" (implying the accordion handles folding).
- */}
-
{error && (
@@ -114,22 +133,48 @@ export function AutoFailoverConfigPanel({
+
+
+
+ {t("proxy.autoFailover.failureThreshold", "失败阈值")}
+
+
+ setFormData({
+ ...formData,
+ circuitFailureThreshold: parseInt(e.target.value) || 5,
+ })
+ }
+ disabled={isDisabled}
/>
{t(
@@ -138,59 +183,123 @@ export function AutoFailoverConfigPanel({
)}
+
+
+ {/* 超时配置 */}
+
+
+ {t("proxy.autoFailover.timeoutSettings", "超时配置")}
+
+
+
-
- {t("proxy.autoFailover.timeout", "恢复等待时间(秒)")}
+
+ {t(
+ "proxy.autoFailover.streamingFirstByte",
+ "流式首字节超时(秒)",
+ )}
setFormData({
...formData,
- timeoutSeconds: parseInt(e.target.value) || 60,
+ streamingFirstByteTimeout: parseInt(e.target.value) || 30,
})
}
- disabled={!enabled}
+ disabled={isDisabled}
/>
{t(
- "proxy.autoFailover.timeoutHint",
- "熔断器打开后,等待多久后尝试恢复(建议: 30-120)",
+ "proxy.autoFailover.streamingFirstByteHint",
+ "等待首个数据块的最大时间",
+ )}
+
+
+
+
+
+ {t("proxy.autoFailover.streamingIdle", "流式静默超时(秒)")}
+
+
+ setFormData({
+ ...formData,
+ streamingIdleTimeout: parseInt(e.target.value) || 60,
+ })
+ }
+ disabled={isDisabled}
+ />
+
+ {t(
+ "proxy.autoFailover.streamingIdleHint",
+ "数据块之间的最大间隔",
+ )}
+
+
+
+
+
+ {t("proxy.autoFailover.nonStreaming", "非流式超时(秒)")}
+
+
+ setFormData({
+ ...formData,
+ nonStreamingTimeout: parseInt(e.target.value) || 300,
+ })
+ }
+ disabled={isDisabled}
+ />
+
+ {t(
+ "proxy.autoFailover.nonStreamingHint",
+ "非流式请求的总超时时间",
)}
- {/* 熔断器高级配置 */}
+ {/* 熔断器配置 */}
- {t("proxy.autoFailover.circuitBreakerSettings", "熔断器高级设置")}
+ {t("proxy.autoFailover.circuitBreakerSettings", "熔断器配置")}
-
+
+
+
+
{t("proxy.autoFailover.errorRate", "错误率阈值 (%)")}
setFormData({
...formData,
- errorRateThreshold: (parseInt(e.target.value) || 50) / 100,
+ circuitErrorRateThreshold:
+ (parseInt(e.target.value) || 50) / 100,
})
}
- disabled={!enabled}
+ disabled={isDisabled}
/>
{t(
@@ -228,22 +364,22 @@ export function AutoFailoverConfigPanel({
-
+
{t("proxy.autoFailover.minRequests", "最小请求数")}
setFormData({
...formData,
- minRequests: parseInt(e.target.value) || 10,
+ circuitMinRequests: parseInt(e.target.value) || 10,
})
}
- disabled={!enabled}
+ disabled={isDisabled}
/>
{t(
@@ -257,17 +393,10 @@ export function AutoFailoverConfigPanel({
{/* 操作按钮 */}
-
+
{t("common.reset", "重置")}
-
+
{updateConfig.isPending ? (
<>
@@ -281,59 +410,6 @@ export function AutoFailoverConfigPanel({
)}
-
- {/* 说明信息 */}
-
-
- {t("proxy.autoFailover.explanationTitle", "工作原理")}
-
-
-
- •{" "}
-
- {t("proxy.autoFailover.failureThresholdLabel", "失败阈值")}
-
- :
- {t(
- "proxy.autoFailover.failureThresholdExplain",
- "连续失败达到此次数时,熔断器打开,该供应商暂时不可用",
- )}
-
-
- •{" "}
-
- {t("proxy.autoFailover.timeoutLabel", "恢复等待时间")}
-
- :
- {t(
- "proxy.autoFailover.timeoutExplain",
- "熔断器打开后,等待此时间后尝试半开状态",
- )}
-
-
- •{" "}
-
- {t("proxy.autoFailover.successThresholdLabel", "恢复成功阈值")}
-
- :
- {t(
- "proxy.autoFailover.successThresholdExplain",
- "半开状态下,成功达到此次数时关闭熔断器,供应商恢复可用",
- )}
-
-
- •{" "}
-
- {t("proxy.autoFailover.errorRateLabel", "错误率阈值")}
-
- :
- {t(
- "proxy.autoFailover.errorRateExplain",
- "错误率超过此值时,即使未达到失败阈值也会打开熔断器",
- )}
-
-
-
);
diff --git a/src/components/proxy/ProxyPanel.tsx b/src/components/proxy/ProxyPanel.tsx
index 66a1c829e..537b8ff68 100644
--- a/src/components/proxy/ProxyPanel.tsx
+++ b/src/components/proxy/ProxyPanel.tsx
@@ -1,26 +1,54 @@
-import { useState } from "react";
+import { useState, useEffect } from "react";
import {
Activity,
Clock,
TrendingUp,
Server,
ListOrdered,
- Settings,
+ 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 { ProxySettingsDialog } from "./ProxySettingsDialog";
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 [showSettings, setShowSettings] = useState(false);
+
+ // 获取应用接管状态
+ 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]);
// 获取所有三个应用类型的故障转移队列(不包含当前供应商)
// 当前供应商始终优先,队列仅用于失败后的备用顺序
@@ -28,6 +56,69 @@ export function ProxyPanel() {
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);
@@ -49,22 +140,11 @@ export function ProxyPanel() {
-
-
- {t("proxy.panel.serviceAddress", {
- defaultValue: "服务地址",
- })}
-
-
setShowSettings(true)}
- className="h-7 gap-1.5 text-xs"
- >
-
- {t("common.settings")}
-
-
+
+ {t("proxy.panel.serviceAddress", {
+ defaultValue: "服务地址",
+ })}
+
http://{status.address}:{status.port}
@@ -87,6 +167,11 @@ export function ProxyPanel() {
{t("common.copy")}
+
+ {t("proxy.settings.restartRequired", {
+ defaultValue: "修改监听地址/端口需要先停止代理服务",
+ })}
+
@@ -130,6 +215,63 @@ export function ProxyPanel() {
)}
+ {/* 应用接管开关 */}
+
+
+ {t("proxyConfig.appTakeover", {
+ defaultValue: "应用接管",
+ })}
+
+
+ {(["claude", "codex", "gemini"] as const).map((appType) => {
+ const isEnabled =
+ takeoverStatus?.[
+ appType as keyof typeof takeoverStatus
+ ] ?? false;
+ return (
+
+
+ {appType}
+
+
+ handleTakeoverChange(appType, checked)
+ }
+ disabled={setTakeoverForApp.isPending}
+ />
+
+ );
+ })}
+
+
+
+ {/* 日志记录开关 */}
+
+
+
+
+ {t("proxy.settings.fields.enableLogging.label", {
+ defaultValue: "启用日志记录",
+ })}
+
+
+ {t("proxy.settings.fields.enableLogging.description", {
+ defaultValue: "记录所有代理请求,便于排查问题",
+ })}
+
+
+
+
+
+
{/* 供应商队列 - 按应用类型分组展示 */}
{(claudeQueue.length > 0 ||
codexQueue.length > 0 ||
@@ -217,36 +359,109 @@ export function ProxyPanel() {
) : (
-
-
-
+
+ {/* 空白区域避免冲突 */}
+
+
+ {/* 基础设置 - 监听地址/端口 */}
+
+
+
+ {t("proxy.settings.basic.title", {
+ defaultValue: "基础设置",
+ })}
+
+
+ {t("proxy.settings.basic.description", {
+ defaultValue: "配置代理服务监听的地址与端口。",
+ })}
+
+
+
+
+
+
+ {t("proxy.settings.fields.listenAddress.label", {
+ defaultValue: "监听地址",
+ })}
+
+
setListenAddress(e.target.value)}
+ placeholder="127.0.0.1"
+ />
+
+ {t("proxy.settings.fields.listenAddress.description", {
+ defaultValue:
+ "代理服务器监听的 IP 地址(推荐 127.0.0.1)",
+ })}
+
+
+
+
+
+ {t("proxy.settings.fields.listenPort.label", {
+ defaultValue: "监听端口",
+ })}
+
+
+ setListenPort(parseInt(e.target.value) || 5000)
+ }
+ placeholder="5000"
+ />
+
+ {t("proxy.settings.fields.listenPort.description", {
+ defaultValue: "代理服务器监听的端口号(1024 ~ 65535)",
+ })}
+
+
+
+
+
+
+ {updateGlobalConfig.isPending ? (
+ <>
+
+ {t("common.saving", { defaultValue: "保存中..." })}
+ >
+ ) : (
+ <>
+
+ {t("common.save", { defaultValue: "保存" })}
+ >
+ )}
+
+
+
+
+ {/* 代理服务已停止提示 */}
+
+
+
+
+
+ {t("proxy.panel.stoppedTitle", {
+ defaultValue: "代理服务已停止",
+ })}
+
+
+ {t("proxy.panel.stoppedDescription", {
+ defaultValue: "使用右上角开关即可启动服务",
+ })}
+
-
- {t("proxy.panel.stoppedTitle", {
- defaultValue: "代理服务已停止",
- })}
-
-
- {t("proxy.panel.stoppedDescription", {
- defaultValue: "使用右上角开关即可启动服务",
- })}
-
-
setShowSettings(true)}
- className="gap-1.5"
- >
-
- {t("proxy.panel.openSettings", {
- defaultValue: "配置代理服务",
- })}
-
)}
-
-
>
);
}
diff --git a/src/components/proxy/ProxySettingsDialog.tsx b/src/components/proxy/ProxySettingsDialog.tsx
deleted file mode 100644
index b697312c0..000000000
--- a/src/components/proxy/ProxySettingsDialog.tsx
+++ /dev/null
@@ -1,553 +0,0 @@
-/**
- * 代理服务设置对话框
- */
-
-import {
- Form,
- FormControl,
- FormField,
- FormItem,
- FormLabel,
- FormDescription,
- FormMessage,
-} from "@/components/ui/form";
-import { Input } from "@/components/ui/input";
-import { Button } from "@/components/ui/button";
-import { Switch } from "@/components/ui/switch";
-import { useForm } from "react-hook-form";
-import { zodResolver } from "@hookform/resolvers/zod";
-import { z } from "zod";
-import { useProxyConfig } from "@/hooks/useProxyConfig";
-import { useEffect, useMemo } from "react";
-import { AlertCircle } from "lucide-react";
-import { Alert, AlertDescription } from "@/components/ui/alert";
-import { FullScreenPanel } from "@/components/common/FullScreenPanel";
-import { useTranslation } from "react-i18next";
-import type { TFunction } from "i18next";
-import type { ProxyConfig } from "@/types/proxy";
-
-// 表单数据类型(仅包含可编辑字段)
-type ProxyConfigForm = Pick<
- ProxyConfig,
- | "listen_address"
- | "listen_port"
- | "max_retries"
- | "request_timeout"
- | "enable_logging"
- | "streaming_first_byte_timeout"
- | "streaming_idle_timeout"
- | "non_streaming_timeout"
->;
-
-const createProxyConfigSchema = (t: TFunction) => {
- // 流式首字节超时:0 或 1-180 秒
- const streamingFirstByteSchema = z
- .number()
- .min(0)
- .refine((val) => val === 0 || (val >= 1 && val <= 180), {
- message: t("proxy.settings.validation.streamingFirstByteRange", {
- defaultValue: "请输入 0 或 1-180 之间的数值",
- }),
- });
-
- // 流式静默期超时:0 或 60-600 秒
- const streamingIdleSchema = z
- .number()
- .min(0)
- .refine((val) => val === 0 || (val >= 60 && val <= 600), {
- message: t("proxy.settings.validation.streamingIdleRange", {
- defaultValue: "请输入 0 或 60-600 之间的数值",
- }),
- });
-
- // 非流式总超时:0 或 60-1800 秒
- const nonStreamingSchema = z
- .number()
- .min(0)
- .refine((val) => val === 0 || (val >= 60 && val <= 1800), {
- message: t("proxy.settings.validation.nonStreamingRange", {
- defaultValue: "请输入 0 或 60-1800 之间的数值",
- }),
- });
-
- // 旧版请求超时(兼容)
- const requestTimeoutSchema = z.number().min(0);
-
- return z.object({
- listen_address: z.string().regex(
- /^(\d{1,3}\.){3}\d{1,3}$/,
- t("proxy.settings.validation.addressInvalid", {
- defaultValue: "请输入有效的IP地址",
- }),
- ),
- listen_port: z
- .number()
- .min(
- 1024,
- t("proxy.settings.validation.portMin", {
- defaultValue: "端口必须大于1024",
- }),
- )
- .max(
- 65535,
- t("proxy.settings.validation.portMax", {
- defaultValue: "端口必须小于65535",
- }),
- ),
- max_retries: z
- .number()
- .min(
- 0,
- t("proxy.settings.validation.retryMin", {
- defaultValue: "重试次数不能为负",
- }),
- )
- .max(
- 10,
- t("proxy.settings.validation.retryMax", {
- defaultValue: "重试次数不能超过10",
- }),
- ),
- request_timeout: requestTimeoutSchema,
- enable_logging: z.boolean(),
- streaming_first_byte_timeout: streamingFirstByteSchema,
- streaming_idle_timeout: streamingIdleSchema,
- non_streaming_timeout: nonStreamingSchema,
- });
-};
-
-interface ProxySettingsDialogProps {
- open: boolean;
- onOpenChange: (open: boolean) => void;
-}
-
-export function ProxySettingsDialog({
- open,
- onOpenChange,
-}: ProxySettingsDialogProps) {
- const { config, isLoading, updateConfig, isUpdating } = useProxyConfig();
- const { t } = useTranslation();
- const schema = useMemo(() => createProxyConfigSchema(t), [t]);
-
- const closePanel = () => onOpenChange(false);
-
- const form = useForm
({
- resolver: zodResolver(schema),
- defaultValues: {
- listen_address: "127.0.0.1",
- listen_port: 5000,
- max_retries: 3,
- request_timeout: 300,
- enable_logging: true,
- streaming_first_byte_timeout: 30,
- streaming_idle_timeout: 60,
- non_streaming_timeout: 600,
- },
- });
-
- // 当配置加载完成后更新表单
- useEffect(() => {
- if (config) {
- form.reset({
- listen_address: config.listen_address,
- listen_port: config.listen_port,
- max_retries: config.max_retries,
- request_timeout: config.request_timeout,
- enable_logging: config.enable_logging,
- streaming_first_byte_timeout: config.streaming_first_byte_timeout ?? 30,
- streaming_idle_timeout: config.streaming_idle_timeout ?? 60,
- non_streaming_timeout: config.non_streaming_timeout ?? 300,
- });
- }
- }, [config, form]);
-
- const onSubmit = async (data: ProxyConfigForm) => {
- try {
- await updateConfig(data);
- closePanel();
- } catch (error) {
- console.error("Save config failed:", error);
- }
- };
-
- const formId = "proxy-settings-form";
-
- return (
-
-
- {t("common.cancel", { defaultValue: "取消" })}
-
-
- {isUpdating
- ? t("common.saving", { defaultValue: "保存中..." })
- : t("proxy.settings.actions.save", { defaultValue: "保存配置" })}
-
- >
- }
- >
-
-
- {t("proxy.settings.description", {
- defaultValue:
- "配置本地代理服务器的监听地址、端口和运行参数,保存后立即生效。",
- })}
-
-
-
-
- {t("proxy.settings.alert.autoApply", {
- defaultValue:
- "保存后将自动同步到正在运行的代理服务,无需手动重启。",
- })}
-
-
-
-
-
-
-
- );
-}
diff --git a/src/components/proxy/index.ts b/src/components/proxy/index.ts
index b645228d8..0abc65408 100644
--- a/src/components/proxy/index.ts
+++ b/src/components/proxy/index.ts
@@ -3,4 +3,3 @@
*/
export { ProxyPanel } from "./ProxyPanel";
-export { ProxySettingsDialog } from "./ProxySettingsDialog";