diff --git a/src/components/setting/mods/clash-port-viewer.tsx b/src/components/setting/mods/clash-port-viewer.tsx index dca9f02d5..ac1fe86ab 100644 --- a/src/components/setting/mods/clash-port-viewer.tsx +++ b/src/components/setting/mods/clash-port-viewer.tsx @@ -4,8 +4,16 @@ import { useVerge } from "@/hooks/use-verge"; import { showNotice } from "@/services/noticeService"; import getSystem from "@/utils/get-system"; import { Shuffle } from "@mui/icons-material"; -import { IconButton, List, ListItem, ListItemText, TextField } from "@mui/material"; -import { useLockFn } from "ahooks"; +import { + CircularProgress, + IconButton, + List, + ListItem, + ListItemText, + Stack, + TextField +} from "@mui/material"; +import { useLockFn, useRequest } from "ahooks"; import { forwardRef, useImperativeHandle, useState } from "react"; import { useTranslation } from "react-i18next"; @@ -42,6 +50,30 @@ export const ClashPortViewer = forwardRef { + const { clashConfig, vergeConfig } = params; + await Promise.all([ + patchInfo(clashConfig), + patchVerge(vergeConfig) + ]); + }, + { + manual: true, + onSuccess: () => { + setOpen(false); + showNotice("success", t("Port settings saved")); // 调用提示函数 + }, + onError: () => { + showNotice("error", t("Failed to save settings")); // 调用提示函数 + } + } + ); + useImperativeHandle(ref, () => ({ open: () => { setMixedPort(verge?.verge_mixed_port ?? clashInfo?.mixed_port ?? 7897); @@ -53,7 +85,7 @@ export const ClashPortViewer = forwardRef setOpen(false), })); @@ -69,48 +101,80 @@ export const ClashPortViewer = forwardRef p !== -1); if (new Set(portList).size !== portList.length) { - showNotice("error", t("Port Conflict")); return; } - try { - // 更新Clash配置 - await patchInfo({ - "mixed-port": mixedPort, - "socks-port": socksPort, - port: httpPort, - "redir-port": redirPort, - "tproxy-port": tproxyPort - } as any); + // 验证端口范围 + const isValidPort = (port: number) => port >= 1 && port <= 65535; + const allPortsValid = [ + mixedPort, + socksEnabled ? socksPort : 0, + httpEnabled ? httpPort : 0, + redirEnabled ? redirPort : 0, + tproxyEnabled ? tproxyPort : 0 + ].every(port => port === 0 || isValidPort(port)); - // 更新Verge配置 - await patchVerge({ - verge_mixed_port: mixedPort, - verge_socks_port: socksPort, - verge_socks_enabled: socksEnabled, - verge_port: httpPort, - verge_http_enabled: httpEnabled, - verge_redir_port: redirPort, - verge_redir_enabled: redirEnabled, - verge_tproxy_port: tproxyPort, - verge_tproxy_enabled: tproxyEnabled - }); - - setOpen(false); - showNotice("success", t("Port settings saved")); - } catch (err) { - showNotice("error", t("Failed to save settings")); + if (!allPortsValid) { + return; } + + // 准备配置数据 + const clashConfig = { + "mixed-port": mixedPort, + "socks-port": socksPort, + port: httpPort, + "redir-port": redirPort, + "tproxy-port": tproxyPort + }; + + const vergeConfig = { + verge_mixed_port: mixedPort, + verge_socks_port: socksPort, + verge_socks_enabled: socksEnabled, + verge_port: httpPort, + verge_http_enabled: httpEnabled, + verge_redir_port: redirPort, + verge_redir_enabled: redirEnabled, + verge_tproxy_port: tproxyPort, + verge_tproxy_enabled: tproxyEnabled + }; + + // 提交保存请求 + await saveSettings({ clashConfig, vergeConfig }); }); + // 优化的数字输入处理 + const handleNumericChange = (setter: (value: number) => void) => (e: React.ChangeEvent) => { + const value = e.target.value.replace(/\D+/, ''); + if (value === '') { + setter(0); + return; + } + + const num = parseInt(value, 10); + if (!isNaN(num) && num >= 0 && num <= 65535) { + setter(num); + } + }; + return ( + + {t("Saving...")} + + ) : t("Save") + } cancelBtn={t("Cancel")} onClose={() => setOpen(false)} + onCancel={() => setOpen(false)} onOk={onSave} > diff --git a/src/locales/en.json b/src/locales/en.json index 92de208b4..508ebd5cb 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -628,5 +628,8 @@ "Configuration saved successfully": "Configuration saved successfully", "Last generated": "Last generated", "External Controller Config": "External Controller Config", - "Enable one-click random API port and key. Click to randomize the port and key": "Enable one-click random API port and key. Click to randomize the port and key" + "Enable one-click random API port and key. Click to randomize the port and key": "Enable one-click random API port and key. Click to randomize the port and key", + "Saving...": "Saving...", + "Port settings saved": "Port settings saved", + "Failed to save settings": "Failed to save settings" } diff --git a/src/locales/zh.json b/src/locales/zh.json index 167456801..414261006 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -274,7 +274,7 @@ "Unified Delay Info": "开启统一延迟时,会进行两次延迟测试,以消除连接握手等带来的不同类型节点的延迟差异", "Log Level": "日志等级", "Log Level Info": "仅对日志目录 Service 文件夹下的内核日志文件生效", - "Port Configuration": "端口设置", + "Port Configuration": "端口配置设置", "Random Port": "随机端口", "Mixed Port": "混合代理端口", "Socks Port": "SOCKS 代理端口", @@ -628,5 +628,8 @@ "Configuration saved successfully": "随机配置,保存完成", "Last generated": "记录生成", "External Controller Config": "API配置", - "Enable one-click random API port and key. Click to randomize the port and key": "开启一键随机API端口和密钥,点进去就可以随机端口和密钥" + "Enable one-click random API port and key. Click to randomize the port and key": "开启一键随机API端口和密钥,点进去就可以随机端口和密钥", + "Saving...": "保存中...", + "Port settings saved": "端口设置已保存", + "Failed to save settings": "端口设置失败" }