diff --git a/static/index.html b/static/index.html index 2010eca..3223e41 100644 --- a/static/index.html +++ b/static/index.html @@ -508,10 +508,25 @@ } .status-info { - background-color: var(--gray-50); + margin-top: 2rem; padding: 1.5rem; + background-color: var(--gray-50); border-radius: var(--border-radius-lg); border-left: 4px solid var(--info-color); + box-shadow: var(--shadow); + } + + .status-info h3 { + margin-bottom: 1rem; + } + + .status-info p { + margin: 0.5rem 0; + line-height: 1.6; + } + + .status-info .stat-card { + border-top: 4px solid var(--primary-color); } .status-info p { @@ -659,25 +674,20 @@
-

服务器状态

+
+

服务器状态

+
+
+ + 规则: -- +
+
+ + Hosts: -- +
+
+
-
- -
--
-
屏蔽规则数
-
- -
-
- -
- -
--
-
Hosts条目数
-
- -
-
--
@@ -739,6 +749,24 @@

服务器信息

+
+
+ +
--
+
屏蔽规则数
+
+ +
+
+
+ +
--
+
Hosts条目数
+
+ +
+
+

服务器地址: --

当前时间: --

运行状态: 正常运行

@@ -994,7 +1022,19 @@ display: false }, tooltip: { - enabled: false + enabled: true, + backgroundColor: 'rgba(0, 0, 0, 0.7)', + titleColor: '#fff', + bodyColor: '#fff', + borderColor: '#333', + borderWidth: 1, + cornerRadius: 4, + displayColors: false, + callbacks: { + label: function(context) { + return context.dataset.label + ': ' + context.parsed.y; + } + } } }, scales: { @@ -1006,7 +1046,11 @@ beginAtZero: true } }, - animation: false + animation: false, + interaction: { + intersect: false, + mode: 'index' + } } }); }); @@ -1073,54 +1117,86 @@ document.getElementById('current-time').textContent = new Date().toLocaleString('zh-CN'); fetch('/api/stats') - .then(response => response.json()) - .then(data => { - // 检查数据是否有变动 - if (isDataChanged(data, previousFullData)) { - console.log('数据有变动,正在更新页面...'); - - // 获取各项统计数据 - const rulesCount = (data.shield && (data.shield.domainRules + data.shield.regexRules)) || 0; - const hostsCount = (data.shield && data.shield.hostsRules) || 0; - const queryCount = (data.dns && data.dns.Queries) || 0; - const blockedCount = (data.dns && data.dns.Blocked) || 0; - - // 检查数据变化并添加动画 - checkAndAnimate('rules-count', rulesCount); - checkAndAnimate('hosts-count', hostsCount); - checkAndAnimate('query-count', queryCount); - checkAndAnimate('blocked-count', blockedCount); - - // 更新显示 - document.getElementById('rules-count').textContent = rulesCount; - document.getElementById('hosts-count').textContent = hostsCount; - document.getElementById('query-count').textContent = queryCount; - document.getElementById('blocked-count').textContent = blockedCount; - document.getElementById('server-address').textContent = window.location.hostname + ':8080'; - - // 更新数据历史记录 - updateDataHistory('rules', rulesCount); - updateDataHistory('hosts', hostsCount); - updateDataHistory('query', queryCount); - updateDataHistory('blocked', blockedCount); - - // 更新小型图表 - updateMiniChart('rules-chart', dataHistory.rules); - updateMiniChart('hosts-chart', dataHistory.hosts); - updateMiniChart('query-chart', dataHistory.query); - updateMiniChart('blocked-chart', dataHistory.blocked); - - // 更新完整数据缓存 - previousFullData = JSON.parse(JSON.stringify(data)); - - // 数据有变动时才加载其他相关数据 - loadChartData(); - loadTopDomains(); - } else { - console.log('数据无变动,不更新页面'); + .then(response => { + if (!response.ok) { + throw new Error('HTTP error! status: ' + response.status); } + return response.json(); }) - .catch(error => console.error('加载统计数据失败:', error)); + .then(data => { + console.log('获取到统计数据:', data); + + // 确保数据结构正确 + if (!data || !data.shield) { + console.error('返回的数据结构不正确,缺少shield字段'); + // 即使数据结构不正确,也尝试更新服务器地址 + document.getElementById('server-address').textContent = window.location.hostname + ':8080'; + return; + } + + // 获取各项统计数据 + const domainRules = data.shield.domainRules || 0; + const regexRules = data.shield.regexRules || 0; + const rulesCount = domainRules + regexRules; + const hostsCount = data.shield.hostsRules || 0; + const queryCount = (data.dns && data.dns.Queries) || 0; + const blockedCount = (data.dns && data.dns.Blocked) || 0; + + console.log(`规则统计: 域名规则=${domainRules}, 正则规则=${regexRules}, 总计=${rulesCount}`); + console.log(`Hosts统计: 条目数=${hostsCount}`); + + // 直接更新显示,同时更新顶部状态区域和统计卡片 + document.getElementById('rules-count').textContent = rulesCount; + document.getElementById('hosts-count').textContent = hostsCount; + document.getElementById('query-count').textContent = queryCount; + + // 更新顶部服务器状态区域的数据 + document.getElementById('rules-count-inline').textContent = rulesCount; + document.getElementById('hosts-count-inline').textContent = hostsCount; + + // 更新屏蔽次数显示,包含百分比 + const blockedPercentage = queryCount > 0 ? Math.round((blockedCount / queryCount) * 100) : 0; + const blockedElement = document.getElementById('blocked-count'); + if (blockedElement) { + blockedElement.innerHTML = blockedCount + + '' + blockedPercentage + '%'; + } + document.getElementById('server-address').textContent = window.location.hostname + ':8080'; + + // 更新数据历史记录 + updateDataHistory('rules', rulesCount); + updateDataHistory('hosts', hostsCount); + updateDataHistory('query', queryCount); + updateDataHistory('blocked', blockedCount); + + // 更新小型图表 + updateMiniChart('rules-chart', dataHistory.rules); + updateMiniChart('hosts-chart', dataHistory.hosts); + updateMiniChart('query-chart', dataHistory.query); + updateMiniChart('blocked-chart', dataHistory.blocked); + + // 更新完整数据缓存 + previousFullData = JSON.parse(JSON.stringify(data)); + + // 加载其他相关数据 + loadChartData(); + loadTopDomains(); + }) + .catch(error => { + console.error('加载统计数据失败:', error); + // 即使出错,也尝试更新服务器地址 + document.getElementById('server-address').textContent = window.location.hostname + ':8080'; + + // 尝试直接从本地文件加载规则和hosts数量(备用方案) + try { + console.log('尝试备用方案加载规则和hosts数量...'); + // 这里可以添加从其他接口或本地缓存获取数据的逻辑 + } catch (e) { + console.error('备用方案也失败:', e); + } + }); } // 保存上一次的图表数据,用于检测图表数据是否变化 @@ -1177,10 +1253,32 @@ function renderBlockChart(labels, data) { plugins: { legend: { position: 'top', + labels: { + padding: 20, + font: { + size: 14 + } + } }, tooltip: { mode: 'index', intersect: false, + backgroundColor: 'rgba(0, 0, 0, 0.8)', + titleColor: '#fff', + bodyColor: '#fff', + borderColor: '#333', + borderWidth: 1, + cornerRadius: 6, + padding: 12, + displayColors: false, + callbacks: { + title: function(tooltipItems) { + return tooltipItems[0].label + ' 时'; + }, + label: function(context) { + return '屏蔽次数: ' + context.parsed.y; + } + } } }, scales: { @@ -1188,6 +1286,9 @@ function renderBlockChart(labels, data) { beginAtZero: true, ticks: { precision: 0 + }, + grid: { + color: 'rgba(0, 0, 0, 0.05)' } }, x: {