Files
pyGoEdge-UserPanel/templates/domains/settings.html
2025-11-18 03:36:49 +08:00

185 lines
9.9 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends 'base.html' %}
{% block title %}功能设置 - {{ domain.name }}{% endblock %}
{% block extra_head %}
<style>
.form-text { font-size: 0.85rem; }
.sidebar-sticky { position: sticky; top: 80px; }
@media (max-width: 991.98px){ .sidebar-sticky { position: static; } }
textarea.json-field { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; }
.disabled-hint { color: #6c757d; font-size: 0.85rem; }
</style>
{% endblock %}
{% block content %}
<div class="row g-4">
<div class="col-lg-2 col-md-3">
<div class="sidebar-sticky">
<div class="list-group">
<a class="list-group-item list-group-item-action" href="{% url 'domains:detail' domain_id=domain.id %}">概览</a>
<a class="list-group-item list-group-item-action" href="{% url 'domains:detail' domain_id=domain.id %}#stats">统计</a>
<a class="list-group-item list-group-item-action" href="{% url 'domains:detail' domain_id=domain.id %}#cname">接入信息</a>
<a class="list-group-item list-group-item-action active" href="#">设置</a>
</div>
</div>
</div>
<div class="col-lg-10 col-md-9">
<div class="d-flex justify-content-between align-items-center mb-3">
<h3>功能设置:{{ domain.name }}</h3>
<div class="btn-group">
<a href="{% url 'domains:detail' domain_id=domain.id %}" class="btn btn-outline-secondary">返回详情</a>
</div>
</div>
<div class="alert alert-info">
根据当前套餐的功能开关,部分设置可能不可用或被禁用。变更套餐可启用更多功能。
</div>
<form method="post" action="{% url 'domains:settings' domain_id=domain.id %}">
{% csrf_token %}
<div class="card mb-4">
<div class="card-header">安全与网络</div>
<div class="card-body">
<div class="form-check form-switch mb-2">
<input type="checkbox" class="form-check-input" id="id_waf_enabled" name="waf_enabled" {% if form.waf_enabled.value %}checked{% endif %} {% if not plan_features.waf_enabled %}disabled{% endif %}>
<label class="form-check-label" for="id_waf_enabled">启用 WAF</label>
{% if not plan_features.waf_enabled %}<div class="disabled-hint">当前套餐不支持 WAF。</div>{% endif %}
</div>
<div class="form-check form-switch mb-2">
<input type="checkbox" class="form-check-input" id="id_http3_enabled" name="http3_enabled" {% if form.http3_enabled.value %}checked{% endif %} {% if not plan_features.http3_enabled %}disabled{% endif %}>
<label class="form-check-label" for="id_http3_enabled">启用 HTTP/3</label>
{% if not plan_features.http3_enabled %}<div class="disabled-hint">当前套餐不支持 HTTP/3。</div>{% endif %}
</div>
<div class="form-check form-switch mb-2">
<input type="checkbox" class="form-check-input" id="id_websocket_enabled" name="websocket_enabled" {% if form.websocket_enabled.value %}checked{% endif %} {% if not plan_features.websocket_enabled %}disabled{% endif %}>
<label class="form-check-label" for="id_websocket_enabled">启用 WebSocket</label>
{% if not plan_features.websocket_enabled %}<div class="disabled-hint">当前套餐不支持 WebSocket。</div>{% endif %}
</div>
<div class="form-check form-switch mb-2">
<input type="checkbox" class="form-check-input" id="id_logs_enabled" name="logs_enabled" {% if form.logs_enabled.value %}checked{% endif %} {% if not plan_features.logs_enabled %}disabled{% endif %}>
<label class="form-check-label" for="id_logs_enabled">启用日志下载</label>
{% if not plan_features.logs_enabled %}<div class="disabled-hint">当前套餐不支持实时/离线日志。</div>{% endif %}
</div>
<div class="form-check form-switch mb-2">
<input type="checkbox" class="form-check-input" id="id_redirect_https_enabled" name="redirect_https_enabled" {% if form.redirect_https_enabled.value %}checked{% endif %}>
<label class="form-check-label" for="id_redirect_https_enabled">强制 HTTP→HTTPS 跳转</label>
</div>
</div>
</div>
<div class="card mb-4">
<div class="card-header">缓存与页面规则</div>
<div class="card-body">
<div class="mb-2">
<div class="btn-group">
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="applyCacheTemplate('static')">套用静态资源缓存</button>
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="applyPageTemplate('redirect_https')">套用强制 HTTPS 跳转</button>
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="applyPageTemplate('rewrite_www')">套用 www→非www 重写</button>
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="downloadJson('id_cache_rules_json')">导出缓存 JSON</button>
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="downloadJson('id_page_rules_json')">导出页面规则 JSON</button>
</div>
</div>
<div class="mb-3">
<label for="id_cache_rules_json" class="form-label">缓存规则JSON</label>
<textarea class="form-control json-field" id="id_cache_rules_json" name="cache_rules_json" rows="6">{{ form.cache_rules_json.value }}</textarea>
<div class="form-text">示例:{"rules": [{"path": "/images/*", "ttl": 3600}]}</div>
</div>
<div class="mb-3">
<label for="id_page_rules_json" class="form-label">页面规则JSON</label>
<textarea class="form-control json-field" id="id_page_rules_json" name="page_rules_json" rows="6">{{ form.page_rules_json.value }}</textarea>
<div class="form-text">示例:{"rules": [{"match": "example.com/*", "action": "cache_bypass"}]}</div>
</div>
</div>
</div>
<div class="card mb-4">
<div class="card-header">IP 控制</div>
<div class="card-body">
<div class="mb-3">
<label for="id_ip_whitelist" class="form-label">IP 白名单(逗号分隔)</label>
<input type="text" class="form-control" id="id_ip_whitelist" name="ip_whitelist" value="{{ form.ip_whitelist.value }}">
<div class="form-text">示例1.2.3.4, 10.0.0.1</div>
</div>
<div class="mb-3">
<label for="id_ip_blacklist" class="form-label">IP 黑名单(逗号分隔)</label>
<input type="text" class="form-control" id="id_ip_blacklist" name="ip_blacklist" value="{{ form.ip_blacklist.value }}">
<div class="form-text">示例203.0.113.0/24</div>
</div>
</div>
</div>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary" onclick="return confirm('保存设置会立即影响后端配置,确认提交?');">保存设置</button>
<a href="{% url 'domains:detail' domain_id=domain.id %}" class="btn btn-outline-secondary">取消</a>
</div>
</form>
<div class="card mt-4">
<div class="card-header">套餐功能可用性</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<ul class="list-group list-group-flush">
<li class="list-group-item">WAF{% if plan_features.waf_enabled %}<span class="text-success">可用</span>{% else %}<span class="text-muted">不可用</span>{% endif %}</li>
<li class="list-group-item">HTTP/3{% if plan_features.http3_enabled %}<span class="text-success">可用</span>{% else %}<span class="text-muted">不可用</span>{% endif %}</li>
<li class="list-group-item">WebSocket{% if plan_features.websocket_enabled %}<span class="text-success">可用</span>{% else %}<span class="text-muted">不可用</span>{% endif %}</li>
</ul>
</div>
<div class="col-md-6">
<ul class="list-group list-group-flush">
<li class="list-group-item">日志下载:{% if plan_features.logs_enabled %}<span class="text-success">可用</span>{% else %}<span class="text-muted">不可用</span>{% endif %}</li>
<li class="list-group-item">自定义规则:{% if plan_features.page_rules_limit %}<span class="text-success">上限 {{ plan_features.page_rules_limit }}</span>{% else %}<span class="text-muted">不可用</span>{% endif %}</li>
</ul>
</div>
</div>
<div class="small text-muted mt-2">提示:套餐功能由管理员在“套餐管理”中配置。</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_scripts %}
<script>
function applyCacheTemplate(name){
var el = document.getElementById('id_cache_rules_json');
if(!el) return;
var tpl = {};
if(name === 'static'){
tpl = {
rules: [
{ path: '/static/*', ttl: 3600 },
{ path: '/images/*', ttl: 3600 },
{ path: '/css/*', ttl: 1800 },
{ path: '/js/*', ttl: 1800 }
]
};
}
el.value = JSON.stringify(tpl, null, 2);
}
function applyPageTemplate(name){
var el = document.getElementById('id_page_rules_json');
if(!el) return;
var tpl = {};
if(name === 'redirect_https'){
tpl = { redirectToHTTPS: { isOn: true } };
var chk = document.getElementById('id_redirect_https_enabled');
if(chk) chk.checked = true;
}
if(name === 'rewrite_www'){
tpl = { rewriteRules: [{ pattern: '^www\\.(.*)$', replace: '$1', flags: 'R=301' }] };
}
el.value = JSON.stringify(tpl, null, 2);
}
function downloadJson(textareaId){
var el = document.getElementById(textareaId);
if(!el) return;
var blob = new Blob([el.value || '{}'], {type: 'application/json'});
var a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = textareaId + '.json';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
</script>
{% endblock %}