Files
ProxyAuto/templates/settings.html

260 lines
11 KiB
HTML

{% extends "base.html" %}
{% block title %}系统设置 - ProxyAuto Pro{% endblock %}
{% block content %}
<div class="page-header">
<h1>系统设置</h1>
</div>
<form id="settings-form" class="form-card">
<section class="form-section">
<h2 class="section-title">AWS 凭证</h2>
<div class="form-grid">
<div class="form-group">
<label for="aws_access_key">AWS Access Key</label>
{% if config.aws_access_key %}
<div class="current-value">当前: {{ mask_secret(config.aws_access_key) }}</div>
{% endif %}
<input type="text" id="aws_access_key" name="aws_access_key"
placeholder="输入新的 Access Key">
<small class="form-hint">留空则保持原值不变</small>
</div>
<div class="form-group">
<label for="aws_secret_key">AWS Secret Key</label>
{% if config.aws_secret_key %}
<div class="current-value">当前: {{ mask_secret(config.aws_secret_key) }}</div>
{% endif %}
<input type="password" id="aws_secret_key" name="aws_secret_key"
placeholder="输入新的 Secret Key">
<small class="form-hint">留空则保持原值不变</small>
</div>
</div>
<div class="form-group" style="margin-top: 1rem;">
<label class="checkbox-label">
<input type="checkbox" id="release_old_eip" name="release_old_eip"
{% if config.release_old_eip %}checked{% endif %}>
<span class="checkbox-text">自动释放旧 Elastic IP</span>
<small class="form-hint" style="display: block; margin-left: 1.5rem;">建议开启,避免产生闲置 IP 费用</small>
</label>
</div>
</section>
<div class="form-divider"></div>
<section class="form-section">
<h2 class="section-title">Cloudflare 认证</h2>
<p style="color: var(--text-muted); font-size: 0.85rem; margin-bottom: 1rem;">
Cloudflare 凭证用于更新 DNS 记录。每台机器的域名绑定请在<a href="{{ url_for('machines') }}">节点管理</a>中配置。
</p>
<div class="form-group">
<label>认证方式</label>
<div class="segmented-control">
<input type="radio" id="auth_api_token" name="cloudflare_auth_type" value="api_token"
{% if config.cloudflare_auth_type != 'global_key' %}checked{% endif %}>
<label for="auth_api_token">API Token</label>
<input type="radio" id="auth_global_key" name="cloudflare_auth_type" value="global_key"
{% if config.cloudflare_auth_type == 'global_key' %}checked{% endif %}>
<label for="auth_global_key">Global API Key</label>
</div>
</div>
<div id="api-token-fields" class="auth-fields" style="{% if config.cloudflare_auth_type == 'global_key' %}display: none;{% endif %}">
<div class="form-group">
<label for="cf_api_token">API Token</label>
{% if config.cf_api_token %}
<div class="current-value">当前: {{ mask_secret(config.cf_api_token) }}</div>
{% endif %}
<input type="password" id="cf_api_token" name="cf_api_token"
placeholder="输入新的 API Token">
<small class="form-hint">留空则保持原值不变</small>
</div>
</div>
<div id="global-key-fields" class="auth-fields" style="{% if config.cloudflare_auth_type != 'global_key' %}display: none;{% endif %}">
<div class="form-grid">
<div class="form-group">
<label for="cf_email">Cloudflare Email</label>
{% if config.cf_email %}
<div class="current-value">当前: {{ config.cf_email }}</div>
{% endif %}
<input type="email" id="cf_email" name="cf_email" value="{{ config.cf_email or '' }}"
placeholder="输入 Cloudflare 账户邮箱">
</div>
<div class="form-group">
<label for="cf_api_key">Global API Key</label>
{% if config.cf_api_key %}
<div class="current-value">当前: {{ mask_secret(config.cf_api_key) }}</div>
{% endif %}
<input type="password" id="cf_api_key" name="cf_api_key"
placeholder="输入新的 Global API Key">
<small class="form-hint">留空则保持原值不变</small>
</div>
</div>
</div>
</section>
<div class="form-divider"></div>
<section class="form-section">
<h2 class="section-title">邮件通知设置</h2>
<p style="color: var(--text-muted); font-size: 0.85rem; margin-bottom: 1rem;">
配置 SMTP 服务器用于发送流量预警邮件通知。
</p>
<div class="form-grid">
<div class="form-group">
<label for="smtp_host">SMTP 服务器</label>
<input type="text" id="smtp_host" name="smtp_host" value="{{ config.smtp_host or '' }}"
placeholder="例如: smtp.gmail.com">
</div>
<div class="form-group">
<label for="smtp_port">端口</label>
<input type="number" id="smtp_port" name="smtp_port" value="{{ config.smtp_port or 587 }}"
placeholder="587">
</div>
</div>
<div class="form-grid">
<div class="form-group">
<label for="smtp_user">SMTP 用户名</label>
<input type="text" id="smtp_user" name="smtp_user" value="{{ config.smtp_user or '' }}"
placeholder="发件邮箱地址">
</div>
<div class="form-group">
<label for="smtp_password">SMTP 密码</label>
{% if config.smtp_password %}
<div class="current-value">当前: {{ mask_secret(config.smtp_password) }}</div>
{% endif %}
<input type="password" id="smtp_password" name="smtp_password"
placeholder="输入新密码 (留空保持原值)">
</div>
</div>
<div class="form-grid">
<div class="form-group">
<label for="alert_email">预警接收邮箱</label>
<input type="email" id="alert_email" name="alert_email" value="{{ config.alert_email or '' }}"
placeholder="接收预警通知的邮箱">
</div>
<div class="form-group" style="display: flex; align-items: center; padding-top: 1.5rem;">
<label class="checkbox-label">
<input type="checkbox" id="smtp_use_tls" name="smtp_use_tls"
{% if config.smtp_use_tls %}checked{% endif %}>
<span class="checkbox-text">使用 STARTTLS</span>
</label>
</div>
</div>
<div class="form-group" style="margin-top: 0.5rem;">
<button type="button" class="btn btn-secondary btn-sm" onclick="testEmail()">
<svg class="btn-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/>
<polyline points="22,6 12,13 2,6"/>
</svg>
发送测试邮件
</button>
</div>
</section>
<div class="form-actions">
<button type="submit" class="btn btn-primary btn-lg">
<span class="btn-text">保存系统配置</span>
<span class="btn-loading" style="display: none;">
<svg class="spinner" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="3" fill="none" stroke-dasharray="32" stroke-linecap="round"/>
</svg>
保存中...
</span>
</button>
</div>
</form>
{% endblock %}
{% block scripts %}
<script>
// 切换认证方式
document.querySelectorAll('input[name="cloudflare_auth_type"]').forEach(radio => {
radio.addEventListener('change', function() {
document.getElementById('api-token-fields').style.display =
this.value === 'api_token' ? 'block' : 'none';
document.getElementById('global-key-fields').style.display =
this.value === 'global_key' ? 'block' : 'none';
});
});
// 提交表单
document.getElementById('settings-form').addEventListener('submit', async function(e) {
e.preventDefault();
const btn = this.querySelector('button[type="submit"]');
const btnText = btn.querySelector('.btn-text');
const btnLoading = btn.querySelector('.btn-loading');
btn.disabled = true;
btnText.style.display = 'none';
btnLoading.style.display = 'flex';
const formData = {
aws_access_key: document.getElementById('aws_access_key').value,
aws_secret_key: document.getElementById('aws_secret_key').value,
cloudflare_auth_type: document.querySelector('input[name="cloudflare_auth_type"]:checked').value,
cf_api_token: document.getElementById('cf_api_token').value,
cf_email: document.getElementById('cf_email').value,
cf_api_key: document.getElementById('cf_api_key').value,
release_old_eip: document.getElementById('release_old_eip').checked,
smtp_host: document.getElementById('smtp_host').value,
smtp_port: parseInt(document.getElementById('smtp_port').value) || 587,
smtp_user: document.getElementById('smtp_user').value,
smtp_password: document.getElementById('smtp_password').value,
smtp_use_tls: document.getElementById('smtp_use_tls').checked,
alert_email: document.getElementById('alert_email').value,
};
try {
const response = await fetch('/api/settings', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData)
});
const result = await response.json();
if (result.ok) {
showToast('success', '配置已更新!');
setTimeout(() => location.reload(), 1000);
} else {
showToast('error', result.message);
}
} catch (error) {
showToast('error', `保存失败: ${error.message}`);
} finally {
btn.disabled = false;
btnText.style.display = 'inline';
btnLoading.style.display = 'none';
}
});
// 测试邮件发送
async function testEmail() {
const smtpHost = document.getElementById('smtp_host').value;
const alertEmail = document.getElementById('alert_email').value;
if (!smtpHost || !alertEmail) {
showToast('error', '请先填写 SMTP 服务器和接收邮箱');
return;
}
try {
const response = await fetch('/api/test-email', { method: 'POST' });
const result = await response.json();
if (result.ok) {
showToast('success', '测试邮件发送成功,请检查收件箱');
} else {
showToast('error', result.message);
}
} catch (error) {
showToast('error', `发送失败: ${error.message}`);
}
}
</script>
{% endblock %}