refactor: improve proxy settings UI with type selector and structured fields
This commit is contained in:
@@ -1020,9 +1020,28 @@
|
||||
<div class="card">
|
||||
<div class="card-header"><span class="card-title" data-i18n="settings.proxySettings"></span></div>
|
||||
<div class="form-group">
|
||||
<label data-i18n="settings.proxyURL"></label>
|
||||
<input type="text" id="proxyURLInput" data-i18n-placeholder="settings.proxyURLPlaceholder">
|
||||
<small style="color:#64748b;font-size:12px;margin-top:4px;display:block" data-i18n="settings.proxyURLHint"></small>
|
||||
<label data-i18n="settings.proxyType"></label>
|
||||
<select id="proxyType" onchange="onProxyTypeChange()">
|
||||
<option value="none" data-i18n="settings.proxyNone"></option>
|
||||
<option value="socks5">SOCKS5</option>
|
||||
<option value="http">HTTP</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="proxyFields" style="display:none">
|
||||
<div class="form-group">
|
||||
<label data-i18n="settings.proxyHost"></label>
|
||||
<div style="display:flex;gap:8px;align-items:stretch">
|
||||
<input type="text" id="proxyHost" style="flex:1" placeholder="127.0.0.1">
|
||||
<input type="number" id="proxyPort" style="width:90px" placeholder="1080" min="1" max="65535">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label data-i18n="settings.proxyAuth"></label>
|
||||
<div style="display:flex;gap:8px">
|
||||
<input type="text" id="proxyUsername" style="flex:1" data-i18n-placeholder="settings.proxyUsername" autocomplete="off">
|
||||
<input type="password" id="proxyPassword" style="flex:1" data-i18n-placeholder="settings.proxyPassword" autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-primary" onclick="saveProxyConfig()" data-i18n="settings.saveProxy"></button>
|
||||
</div>
|
||||
@@ -1156,9 +1175,13 @@
|
||||
'settings.resetStats': '重置统计',
|
||||
'settings.confirmReset': '确定重置统计?',
|
||||
'settings.proxySettings': '出站代理设置',
|
||||
'settings.proxyURL': '代理地址',
|
||||
'settings.proxyURLPlaceholder': '留空则直连(不使用代理)',
|
||||
'settings.proxyURLHint': '支持 socks5://host:port、socks5://user:pass@host:port、http://host:port 格式,适用于网络受限地区的用户',
|
||||
'settings.proxyType': '代理类型',
|
||||
'settings.proxyNone': '直连(不使用代理)',
|
||||
'settings.proxyHost': '地址 / 端口',
|
||||
'settings.proxyAuth': '认证(可选)',
|
||||
'settings.proxyUsername': '用户名',
|
||||
'settings.proxyPassword': '密码',
|
||||
'settings.proxyHostRequired': '请填写代理地址和端口',
|
||||
'settings.saveProxy': '保存代理设置',
|
||||
'settings.proxySaved': '代理设置已保存,已即时生效',
|
||||
'api.endpoints': 'API 端点',
|
||||
@@ -1368,9 +1391,13 @@
|
||||
'settings.resetStats': 'Reset Statistics',
|
||||
'settings.confirmReset': 'Confirm reset statistics?',
|
||||
'settings.proxySettings': 'Outbound Proxy Settings',
|
||||
'settings.proxyURL': 'Proxy URL',
|
||||
'settings.proxyURLPlaceholder': 'Leave empty to connect directly',
|
||||
'settings.proxyURLHint': 'Supports socks5://host:port, socks5://user:pass@host:port, http://host:port. For users in restricted network regions.',
|
||||
'settings.proxyType': 'Proxy Type',
|
||||
'settings.proxyNone': 'Direct (no proxy)',
|
||||
'settings.proxyHost': 'Host / Port',
|
||||
'settings.proxyAuth': 'Authentication (optional)',
|
||||
'settings.proxyUsername': 'Username',
|
||||
'settings.proxyPassword': 'Password',
|
||||
'settings.proxyHostRequired': 'Please enter proxy host and port',
|
||||
'settings.saveProxy': 'Save Proxy Settings',
|
||||
'settings.proxySaved': 'Proxy settings saved and applied',
|
||||
'api.endpoints': 'API Endpoints',
|
||||
@@ -2045,12 +2072,45 @@
|
||||
async function loadProxyConfig() {
|
||||
const res = await fetch('/admin/api/proxy', { headers: { 'X-Admin-Password': password } });
|
||||
const d = await res.json();
|
||||
document.getElementById('proxyURLInput').value = d.proxyURL || '';
|
||||
const proxyURL = d.proxyURL || '';
|
||||
if (!proxyURL) {
|
||||
document.getElementById('proxyType').value = 'none';
|
||||
document.getElementById('proxyFields').style.display = 'none';
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const u = new URL(proxyURL);
|
||||
const scheme = u.protocol.replace(':', '');
|
||||
document.getElementById('proxyType').value = scheme.startsWith('socks5') ? 'socks5' : 'http';
|
||||
document.getElementById('proxyHost').value = u.hostname;
|
||||
document.getElementById('proxyPort').value = u.port;
|
||||
document.getElementById('proxyUsername').value = decodeURIComponent(u.username);
|
||||
document.getElementById('proxyPassword').value = decodeURIComponent(u.password);
|
||||
document.getElementById('proxyFields').style.display = '';
|
||||
} catch(e) {
|
||||
document.getElementById('proxyType').value = 'none';
|
||||
document.getElementById('proxyFields').style.display = 'none';
|
||||
}
|
||||
}
|
||||
function onProxyTypeChange() {
|
||||
const type = document.getElementById('proxyType').value;
|
||||
document.getElementById('proxyFields').style.display = type === 'none' ? 'none' : '';
|
||||
}
|
||||
async function saveProxyConfig() {
|
||||
const type = document.getElementById('proxyType').value;
|
||||
let proxyURL = '';
|
||||
if (type !== 'none') {
|
||||
const host = document.getElementById('proxyHost').value.trim();
|
||||
const port = document.getElementById('proxyPort').value.trim();
|
||||
if (!host || !port) { alert(t('settings.proxyHostRequired')); return; }
|
||||
const user = document.getElementById('proxyUsername').value.trim();
|
||||
const pass = document.getElementById('proxyPassword').value.trim();
|
||||
const auth = user ? (pass ? `${encodeURIComponent(user)}:${encodeURIComponent(pass)}@` : `${encodeURIComponent(user)}@`) : '';
|
||||
proxyURL = `${type}://${auth}${host}:${port}`;
|
||||
}
|
||||
const res = await fetch('/admin/api/proxy', {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Admin-Password': password },
|
||||
body: JSON.stringify({ proxyURL: document.getElementById('proxyURLInput').value.trim() })
|
||||
body: JSON.stringify({ proxyURL })
|
||||
});
|
||||
const d = await res.json();
|
||||
if (d.success) { alert(t('settings.proxySaved')); } else { alert(t('common.saveFailed') + ': ' + d.error); }
|
||||
|
||||
Reference in New Issue
Block a user