diff --git a/web/admin-spa/src/components/accounts/ProxyConfig.vue b/web/admin-spa/src/components/accounts/ProxyConfig.vue index d38bb28b..c769f325 100644 --- a/web/admin-spa/src/components/accounts/ProxyConfig.vue +++ b/web/admin-spa/src/components/accounts/ProxyConfig.vue @@ -30,6 +30,45 @@ + +
+ +
+ + +
+

+ + {{ parseError }} +

+

+ + 代理配置已自动填充 +

+
+ +
+
props.modelValue, @@ -246,6 +290,122 @@ function emitUpdate() { }, 100) // 100ms 延迟 } +// 解析代理URL +function parseProxyUrl() { + parseError.value = '' + parseSuccess.value = false + + if (!proxyUrl.value) { + return + } + + try { + // 移除 # 后面的别名部分 + const urlWithoutAlias = proxyUrl.value.split('#')[0].trim() + + if (!urlWithoutAlias) { + return + } + + // 正则表达式匹配代理URL格式 + // 支持格式:protocol://[username:password@]host:port + const proxyPattern = /^(socks5|https?):\/\/(?:([^:@]+):([^@]+)@)?([^:]+):(\d+)$/i + const match = urlWithoutAlias.match(proxyPattern) + + if (!match) { + // 尝试简单格式:host:port(默认为socks5) + const simplePattern = /^([^:]+):(\d+)$/ + const simpleMatch = urlWithoutAlias.match(simplePattern) + + if (simpleMatch) { + proxy.value.type = 'socks5' + proxy.value.host = simpleMatch[1] + proxy.value.port = simpleMatch[2] + proxy.value.username = '' + proxy.value.password = '' + showAuth.value = false + parseSuccess.value = true + emitUpdate() + + // 3秒后清除成功提示 + setTimeout(() => { + parseSuccess.value = false + }, 3000) + return + } + + parseError.value = '无效的代理URL格式,请检查输入' + return + } + + // 解析匹配结果 + const [, protocol, username, password, host, port] = match + + // 填充表单 + proxy.value.type = protocol.toLowerCase() + proxy.value.host = host + proxy.value.port = port + + // 处理认证信息 + if (username && password) { + proxy.value.username = decodeURIComponent(username) + proxy.value.password = decodeURIComponent(password) + showAuth.value = true + } else { + proxy.value.username = '' + proxy.value.password = '' + showAuth.value = false + } + + parseSuccess.value = true + emitUpdate() + + // 3秒后清除成功提示 + setTimeout(() => { + parseSuccess.value = false + }, 3000) + } catch (error) { + // 解析代理URL失败 + parseError.value = '解析失败,请检查URL格式' + } +} + +// 清空快速配置输入 +function clearProxyUrl() { + proxyUrl.value = '' + parseError.value = '' + parseSuccess.value = false +} + +// 处理粘贴事件 +function handlePaste() { + // 延迟一下以确保v-model已经更新 + setTimeout(() => { + parseProxyUrl() + }, 0) +} + +// 处理输入事件 +function handleInput() { + // 检测是否输入了代理URL格式 + const value = proxyUrl.value.trim() + + // 如果输入包含://,说明可能是完整的代理URL + if (value.includes('://')) { + // 检查是否看起来像完整的URL(有协议、主机和端口) + if ( + /^(socks5|https?):\/\/[^:]+:\d+/i.test(value) || + /^(socks5|https?):\/\/[^:@]+:[^@]+@[^:]+:\d+/i.test(value) + ) { + parseProxyUrl() + } + } + // 如果是简单的 host:port 格式,并且端口号输入完整 + else if (/^[^:]+:\d{2,5}$/.test(value)) { + parseProxyUrl() + } +} + // 组件销毁时清理定时器 onUnmounted(() => { if (updateTimer) {