更新web显示
This commit is contained in:
@@ -508,10 +508,25 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.status-info {
|
.status-info {
|
||||||
background-color: var(--gray-50);
|
margin-top: 2rem;
|
||||||
padding: 1.5rem;
|
padding: 1.5rem;
|
||||||
|
background-color: var(--gray-50);
|
||||||
border-radius: var(--border-radius-lg);
|
border-radius: var(--border-radius-lg);
|
||||||
border-left: 4px solid var(--info-color);
|
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 {
|
.status-info p {
|
||||||
@@ -659,25 +674,20 @@
|
|||||||
|
|
||||||
<!-- 概览面板 -->
|
<!-- 概览面板 -->
|
||||||
<div id="dashboard" class="tab-content active">
|
<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="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">
|
<div class="stat-card">
|
||||||
<i class="fas fa-question-circle"></i>
|
<i class="fas fa-question-circle"></i>
|
||||||
<div class="stat-value" id="query-count">--</div>
|
<div class="stat-value" id="query-count">--</div>
|
||||||
@@ -739,6 +749,24 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="status-info">
|
<div class="status-info">
|
||||||
<h3 style="margin-bottom: 1rem; font-size: 1.25rem; color: var(--gray-700);">服务器信息</h3>
|
<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="server-address">--</span></p>
|
||||||
<p><strong>当前时间:</strong> <span id="current-time">--</span></p>
|
<p><strong>当前时间:</strong> <span id="current-time">--</span></p>
|
||||||
<p><strong>运行状态:</strong> <span class="badge badge-success">正常运行</span></p>
|
<p><strong>运行状态:</strong> <span class="badge badge-success">正常运行</span></p>
|
||||||
@@ -994,7 +1022,19 @@
|
|||||||
display: false
|
display: false
|
||||||
},
|
},
|
||||||
tooltip: {
|
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: {
|
scales: {
|
||||||
@@ -1006,7 +1046,11 @@
|
|||||||
beginAtZero: true
|
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');
|
document.getElementById('current-time').textContent = new Date().toLocaleString('zh-CN');
|
||||||
|
|
||||||
fetch('/api/stats')
|
fetch('/api/stats')
|
||||||
.then(response => response.json())
|
.then(response => {
|
||||||
.then(data => {
|
if (!response.ok) {
|
||||||
// 检查数据是否有变动
|
throw new Error('HTTP error! status: ' + response.status);
|
||||||
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('数据无变动,不更新页面');
|
|
||||||
}
|
}
|
||||||
|
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: {
|
plugins: {
|
||||||
legend: {
|
legend: {
|
||||||
position: 'top',
|
position: 'top',
|
||||||
|
labels: {
|
||||||
|
padding: 20,
|
||||||
|
font: {
|
||||||
|
size: 14
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
mode: 'index',
|
mode: 'index',
|
||||||
intersect: false,
|
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: {
|
scales: {
|
||||||
@@ -1188,6 +1286,9 @@ function renderBlockChart(labels, data) {
|
|||||||
beginAtZero: true,
|
beginAtZero: true,
|
||||||
ticks: {
|
ticks: {
|
||||||
precision: 0
|
precision: 0
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
color: 'rgba(0, 0, 0, 0.05)'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
x: {
|
x: {
|
||||||
|
|||||||
Reference in New Issue
Block a user