Files
2025-11-18 03:36:49 +08:00

339 lines
14 KiB
HTML
Raw Permalink 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>
.sidebar-sticky { position: sticky; top: 80px; }
.list-group .list-group-item.active { background-color: #0d6efd; border-color: #0d6efd; }
.card .badge { font-size: 0.9rem; }
.progress { height: 20px; }
.progress-bar { font-size: 0.8rem; }
@media (max-width: 991.98px){ .sidebar-sticky { position: static; } }
.table td, .table th { vertical-align: middle; }
.text-muted.small { line-height: 1.2; }
</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 active" href="#">概览</a>
<a class="list-group-item list-group-item-action" href="#">统计</a>
<a class="list-group-item list-group-item-action" href="#">接入信息</a>
<a class="list-group-item list-group-item-action" href="{% url 'domains:settings' domain_id=domain.id %}">设置</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:list' %}" class="btn btn-outline-secondary">返回列表</a>
<a href="{% url 'domains:upgrade' domain_id=domain.id %}" class="btn btn-primary" onclick="return confirm('升级套餐将影响后续计费,确认继续?');">升级套餐</a>
<a href="{% url 'domains:logs' domain_id=domain.id %}" class="btn btn-outline-primary">访问日志</a>
</div>
</div>
<div class="card mb-4">
<div class="card-header">概览</div>
<div class="card-body">
<div class="row mb-3">
<div class="col-md-6">
<div>当前套餐:{% if domain.current_plan %}{{ domain.current_plan.name }}{% else %}-{% endif %}</div>
<div>状态:{{ domain.get_status_display }}</div>
</div>
<div class="col-md-6">
<div class="mb-1">本月流量:{{ used_gb }} GB / {{ total_quota_gb }} GB</div>
<div class="progress" role="progressbar" aria-label="Monthly usage" aria-valuenow="{{ progress_pct }}" aria-valuemin="0" aria-valuemax="100">
<div class="progress-bar" style="width: {{ progress_pct }}%">{{ progress_pct }}%</div>
</div>
</div>
</div>
</div>
</div>
<div class="card mb-4">
<div class="card-header">统计近30天</div>
<div class="card-body">
<div class="row mb-3">
<div class="col-md-4">
<div class="fw-semibold">近 7 天合计</div>
<div><span class="badge bg-primary">{{ last7_total_gb|default:0 }} GB</span></div>
<div class="text-muted small">均值:{{ last7_avg_gb|default:0 }} GB/日</div>
</div>
<div class="col-md-4">
<div class="fw-semibold">近 30 天合计</div>
<div><span class="badge bg-info text-dark">{{ last30_total_gb|default:0 }} GB</span></div>
<div class="text-muted small">均值:{{ last30_avg_gb|default:0 }} GB/日</div>
</div>
<div class="col-md-4">
<div class="fw-semibold">峰值日(流量)</div>
<div>
{% if peak_volume_day %}
<span class="badge bg-warning text-dark">{{ peak_volume_day.day }} / {{ peak_volume_day.gb }} GB</span>
{% else %}
<span class="text-muted">无数据</span>
{% endif %}
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-md-4">
<div class="fw-semibold">峰值日(带宽)</div>
<div>
{% if peak_bandwidth_day %}
<span class="badge bg-secondary">{{ peak_bandwidth_day.day }} / {{ peak_bandwidth_day.mbps }} Mbps</span>
{% else %}
<span class="text-muted">无数据</span>
{% endif %}
</div>
</div>
<div class="col-md-8">
<div class="fw-semibold">请求数 / 状态码分布</div>
<div class="mb-2">
{% if requests_24h_total %}
近 24 小时请求数:<span class="badge bg-primary">{{ requests_24h_total }}</span>
{% else %}
<span class="text-muted">请求数不可用(请在设置启用访问日志)</span>
{% endif %}
</div>
{% if status_bins %}
<div class="d-flex gap-2 flex-wrap">
<span class="badge text-bg-success">2xx {{ status_bins.2xx }}</span>
<span class="badge text-bg-info">3xx {{ status_bins.3xx }}</span>
<span class="badge text-bg-warning text-dark">4xx {{ status_bins.4xx }}</span>
<span class="badge text-bg-danger">5xx {{ status_bins.5xx }}</span>
</div>
{% if status_top %}
<div class="text-muted small mt-1">Top 状态码:
{% for code,count in status_top %}
<span class="me-2"><code>{{ code }}</code> {{ count }}</span>
{% endfor %}
</div>
{% endif %}
{% else %}
<div class="text-muted small">状态码分布不可用。</div>
{% endif %}
</div>
</div>
{% if traffic_rows %}
<canvas id="trafficChart" height="120" class="mb-3" style="width: 100%;"></canvas>
<div class="table-responsive">
<table class="table table-sm align-middle">
<thead>
<tr>
<th>日期</th>
<th>流量GB</th>
<th>峰值带宽Mbps</th>
</tr>
</thead>
<tbody>
{% for r in traffic_rows %}
<tr>
<td>{{ r.day }}</td>
<td>{{ r.gb }}</td>
<td>{% if r.peak_mbps %}{{ r.peak_mbps }}{% else %}<span class="text-muted">-</span>{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-muted">暂无统计数据。</div>
{% endif %}
<div class="small text-muted">说明:统计数据来源于 GoEdge 每日拉取结果,仅供参考。</div>
</div>
</div>
<div class="card mb-4">
<div class="card-header">接入信息CNAME</div>
<div class="card-body">
<table class="table table-sm">
<thead>
<tr>
<th>主机名</th>
<th>期望 CNAME 目标</th>
<th>实际解析</th>
<th>状态</th>
</tr>
</thead>
<tbody>
{% if cname_results %}
{% for r in cname_results %}
<tr>
<td>{{ r.hostname }}</td>
<td><code>{{ r.expected }}</code></td>
<td>
{% if r.actual %}
{% for a in r.actual %}<code>{{ a }}</code>{% if not forloop.last %}, {% endif %}{% endfor %}
{% else %}
<span class="text-muted">(无)</span>
{% endif %}
</td>
<td>
{% if r.ok %}
<span class="badge text-bg-success">正确</span>
{% else %}
<span class="badge text-bg-warning">未匹配</span>
{% if r.error %}<div class="text-muted">{{ r.error }}</div>{% endif %}
{% endif %}
</td>
</tr>
{% endfor %}
{% else %}
{% for host, target in domain.cname_targets.items %}
<tr>
<td>{{ host }}</td>
<td><code>{{ target }}</code></td>
<td class="text-muted">(未检测)</td>
<td><span class="badge text-bg-secondary">未知</span></td>
</tr>
{% endfor %}
{% endif %}
</tbody>
</table>
<form method="post" action="{% url 'domains:check_dns' domain_id=domain.id %}" class="mt-2">
{% csrf_token %}
<button type="submit" class="btn btn-primary">立即检测 DNS 生效</button>
</form>
</div>
</div>
<div class="card mb-4">
<div class="card-header">GoEdge 同步状态</div>
<div class="card-body">
{% if goedge_status and not goedge_status.error %}
<div class="row g-3">
<div class="col-md-3">
<div class="fw-semibold">Web ID</div>
<div>{% if goedge_status.webId %}<span class="badge text-bg-secondary">{{ goedge_status.webId }}</span>{% else %}<span class="text-muted">未获取</span>{% endif %}</div>
</div>
<div class="col-md-3">
<div class="fw-semibold">访问日志</div>
{% if goedge_status.accessLog.isOn %}
<span class="badge text-bg-success">已启用</span>
{% elif goedge_status.accessLog.isOn is not none %}
<span class="badge text-bg-secondary">未启用</span>
{% else %}
<span class="text-muted">未知</span>
{% endif %}
{% if goedge_status.accessLog.policyId %}
<div class="text-muted small">PolicyId: {{ goedge_status.accessLog.policyId }}</div>
{% endif %}
</div>
<div class="col-md-3">
<div class="fw-semibold">WebSocket</div>
{% if goedge_status.websocket.isOn %}
<span class="badge text-bg-success">已启用</span>
{% elif goedge_status.websocket.isOn is not none %}
<span class="badge text-bg-secondary">未启用</span>
{% else %}
<span class="text-muted">未知</span>
{% endif %}
</div>
<div class="col-md-3">
<div class="fw-semibold">WAF</div>
{% if goedge_status.firewall.isOn %}
<span class="badge text-bg-success">已启用</span>
{% elif goedge_status.firewall.isOn is not none %}
<span class="badge text-bg-secondary">未启用</span>
{% else %}
<span class="text-muted">未知</span>
{% endif %}
{% if goedge_status.firewall.policyId %}
<div class="text-muted small">PolicyId: {{ goedge_status.firewall.policyId }}</div>
{% endif %}
</div>
<div class="col-md-3">
<div class="fw-semibold">SSL策略</div>
<div>{% if goedge_status.sslPolicy.id %}<span class="badge text-bg-secondary">{{ goedge_status.sslPolicy.id }}</span>{% else %}<span class="text-muted">未获取</span>{% endif %}</div>
</div>
<div class="col-md-3">
<div class="fw-semibold">HTTP/3</div>
{% if goedge_status.sslPolicy.http3Enabled %}
<span class="badge text-bg-success">已启用</span>
{% elif goedge_status.sslPolicy.http3Enabled is not none %}
<span class="badge text-bg-secondary">未启用</span>
{% else %}
<span class="text-muted">未知</span>
{% endif %}
</div>
</div>
{% elif goedge_status and goedge_status.error %}
<div class="alert alert-warning">状态查询失败:{{ goedge_status.error }}</div>
{% else %}
<div class="text-muted">当前域名尚未关联 GoEdge 服务或无可查询信息。</div>
{% endif %}
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_scripts %}
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var rows = [
{% for r in traffic_rows reversed %}
{ day: '{{ r.day|date:"Y-m-d" }}', gb: {{ r.gb|default:0 }}, peak_mbps: {% if r.peak_mbps %}{{ r.peak_mbps }}{% else %}null{% endif %} },
{% endfor %}
];
if (!rows.length || !window.Chart) return;
var labels = rows.map(function(x){ return x.day; });
var dataGb = rows.map(function(x){ return x.gb || 0; });
var dataMbps = rows.map(function(x){ return x.peak_mbps === null ? null : x.peak_mbps; });
var el = document.getElementById('trafficChart');
if (!el) return;
var ctx = el.getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [
{
label: '流量GB',
data: dataGb,
borderColor: '#0d6efd',
backgroundColor: 'rgba(13,110,253,0.15)',
fill: true,
tension: 0.3,
yAxisID: 'yGb'
},
{
label: '峰值带宽Mbps',
data: dataMbps,
borderColor: '#6f42c1',
backgroundColor: 'rgba(111,66,193,0.08)',
fill: false,
tension: 0.3,
yAxisID: 'yMbps'
}
]
},
options: {
responsive: true,
interaction: { mode: 'index', intersect: false },
plugins: {
legend: { position: 'bottom' },
tooltip: {
callbacks: {
label: function(ctx){
var suffix = ctx.dataset.yAxisID === 'yGb' ? ' GB' : ' Mbps';
return ctx.dataset.label + ': ' + ctx.formattedValue + suffix;
}
}
}
},
scales: {
yGb: { type: 'linear', position: 'left', title: { display: true, text: 'GB' } },
yMbps: { type: 'linear', position: 'right', title: { display: true, text: 'Mbps' }, grid: { drawOnChartArea: false } }
}
}
});
});
</script>
{% endblock %}