更新web显示
This commit is contained in:
@@ -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 @@
|
||||
|
||||
<!-- 概览面板 -->
|
||||
<div id="dashboard" class="tab-content active">
|
||||
<h2 style="margin-bottom: 1.5rem;">服务器状态</h2>
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 1.5rem;">
|
||||
<h2>服务器状态</h2>
|
||||
<div style="display: flex; gap: 1rem;">
|
||||
<div style="background-color: white; padding: 0.5rem 1rem; border-radius: var(--border-radius-md); box-shadow: var(--shadow); display: flex; align-items: center; gap: 0.5rem;">
|
||||
<i class="fas fa-ban" style="color: var(--primary-color);"></i>
|
||||
<span style="font-size: 1rem; font-weight: 600;">规则: <span id="rules-count-inline">--</span></span>
|
||||
</div>
|
||||
<div style="background-color: white; padding: 0.5rem 1rem; border-radius: var(--border-radius-md); box-shadow: var(--shadow); display: flex; align-items: center; gap: 0.5rem;">
|
||||
<i class="fas fa-file-alt" style="color: var(--primary-color);"></i>
|
||||
<span style="font-size: 1rem; font-weight: 600;">Hosts: <span id="hosts-count-inline">--</span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<i class="fas fa-ban"></i>
|
||||
<div class="stat-value" id="rules-count">--</div>
|
||||
<div class="stat-label">屏蔽规则数</div>
|
||||
<div class="mini-chart-container">
|
||||
<canvas id="rules-chart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-card">
|
||||
<i class="fas fa-file-alt"></i>
|
||||
<div class="stat-value" id="hosts-count">--</div>
|
||||
<div class="stat-label">Hosts条目数</div>
|
||||
<div class="mini-chart-container">
|
||||
<canvas id="hosts-chart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<i class="fas fa-question-circle"></i>
|
||||
<div class="stat-value" id="query-count">--</div>
|
||||
@@ -739,6 +749,24 @@
|
||||
</div>
|
||||
<div class="status-info">
|
||||
<h3 style="margin-bottom: 1rem; font-size: 1.25rem; color: var(--gray-700);">服务器信息</h3>
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 1rem; margin-bottom: 1.5rem;">
|
||||
<div class="stat-card">
|
||||
<i class="fas fa-ban"></i>
|
||||
<div class="stat-value" id="rules-count">--</div>
|
||||
<div class="stat-label">屏蔽规则数</div>
|
||||
<div class="mini-chart-container">
|
||||
<canvas id="rules-chart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<i class="fas fa-file-alt"></i>
|
||||
<div class="stat-value" id="hosts-count">--</div>
|
||||
<div class="stat-label">Hosts条目数</div>
|
||||
<div class="mini-chart-container">
|
||||
<canvas id="hosts-chart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p><strong>服务器地址:</strong> <span id="server-address">--</span></p>
|
||||
<p><strong>当前时间:</strong> <span id="current-time">--</span></p>
|
||||
<p><strong>运行状态:</strong> <span class="badge badge-success">正常运行</span></p>
|
||||
@@ -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 +
|
||||
'<span style="position: absolute; top: -10px; right: -20px; ' +
|
||||
'background-color: #ff6b6b; color: white; border-radius: 50%; padding: 2px 6px; ' +
|
||||
'font-size: 0.7rem; font-weight: bold;">' + blockedPercentage + '%</span>';
|
||||
}
|
||||
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: {
|
||||
|
||||
Reference in New Issue
Block a user