Files
dns-server/static/js/modules/dashboard.js
Alex Yang 85320611cb web重做
2025-11-24 01:53:26 +08:00

246 lines
7.0 KiB
JavaScript

// 初始化仪表盘面板
function initDashboardPanel() {
// 加载统计数据
loadDashboardData();
}
// 加载仪表盘数据
function loadDashboardData() {
// 加载24小时统计数据
loadHourlyStats();
// 加载请求类型分布
loadRequestsDistribution();
// 加载最常屏蔽的域名
loadTopBlockedDomains();
// 加载最常解析的域名
loadTopResolvedDomains();
}
// 加载24小时统计数据
function loadHourlyStats() {
apiRequest('/api/hourly-stats')
.then(data => {
if (data && data.labels && data.data) {
// 只使用一组数据(假设是屏蔽请求数)
renderHourlyChart(data.labels, data.data, []);
}
})
.catch(error => {
console.error('获取24小时统计失败:', error);
});
}
// 渲染24小时统计图表
function renderHourlyChart(hours, blocked, allowed) {
const ctx = document.getElementById('hourly-chart');
if (!ctx) return;
// 销毁现有图表
if (window.hourlyChart) {
window.hourlyChart.destroy();
}
// 创建新图表
window.hourlyChart = new Chart(ctx, {
type: 'line',
data: {
labels: hours,
datasets: [
{
label: '屏蔽请求',
data: blocked,
borderColor: '#e74c3c',
backgroundColor: 'rgba(231, 76, 60, 0.1)',
borderWidth: 2,
tension: 0.3,
fill: true
},
{
label: '允许请求',
data: allowed,
borderColor: '#2ecc71',
backgroundColor: 'rgba(46, 204, 113, 0.1)',
borderWidth: 2,
tension: 0.3,
fill: true
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
title: {
display: true,
text: '请求数'
}
},
x: {
title: {
display: true,
text: '时间(小时)'
}
}
},
plugins: {
legend: {
position: 'top',
},
tooltip: {
mode: 'index',
intersect: false
}
}
}
});
}
// 加载请求类型分布
function loadRequestsDistribution() {
apiRequest('/api/stats')
.then(data => {
if (data && data.dns) {
// 构造饼图所需的数据
const labels = ['允许请求', '屏蔽请求', '错误请求'];
const requestData = [
data.dns.Allowed || 0,
data.dns.Blocked || 0,
data.dns.Error || 0
];
renderRequestsPieChart(labels, requestData);
}
})
.catch(error => {
console.error('获取请求类型分布失败:', error);
});
}
// 渲染请求类型饼图
function renderRequestsPieChart(labels, data) {
const ctx = document.getElementById('requests-pie-chart');
if (!ctx) return;
// 销毁现有图表
if (window.requestsPieChart) {
window.requestsPieChart.destroy();
}
// 创建新图表
window.requestsPieChart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: labels,
datasets: [{
data: data,
backgroundColor: [
'#2ecc71', // 允许
'#e74c3c', // 屏蔽
'#f39c12', // 错误
'#9b59b6' // 其他
],
borderWidth: 2,
borderColor: '#fff'
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'right',
},
tooltip: {
callbacks: {
label: function(context) {
const label = context.label || '';
const value = context.raw || 0;
const total = context.dataset.data.reduce((a, b) => a + b, 0);
const percentage = ((value / total) * 100).toFixed(1);
return `${label}: ${value} (${percentage}%)`;
}
}
}
},
cutout: '60%'
}
});
}
// 加载最常屏蔽的域名
function loadTopBlockedDomains() {
apiRequest('/api/top-blocked')
.then(data => {
renderTopBlockedDomains(data);
})
.catch(error => {
console.error('获取最常屏蔽域名失败:', error);
showError(document.getElementById('top-blocked-table').querySelector('tbody'), '获取数据失败');
});
}
// 渲染最常屏蔽的域名表格
function renderTopBlockedDomains(domains) {
const tbody = document.getElementById('top-blocked-table').querySelector('tbody');
if (!tbody) return;
if (!domains || domains.length === 0) {
showEmpty(tbody, '暂无屏蔽记录');
return;
}
tbody.innerHTML = '';
domains.forEach((domain, index) => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${domain.domain}</td>
<td>${formatNumber(domain.count)}</td>
`;
tbody.appendChild(row);
});
// 初始化表格排序
initTableSort('top-blocked-table');
}
// 加载最常解析的域名
function loadTopResolvedDomains() {
apiRequest('/api/top-resolved')
.then(data => {
renderTopResolvedDomains(data);
})
.catch(error => {
console.error('获取最常解析域名失败:', error);
showError(document.getElementById('top-resolved-table').querySelector('tbody'), '获取数据失败');
});
}
// 渲染最常解析的域名表格
function renderTopResolvedDomains(domains) {
const tbody = document.getElementById('top-resolved-table').querySelector('tbody');
if (!tbody) return;
if (!domains || domains.length === 0) {
showEmpty(tbody, '暂无解析记录');
return;
}
tbody.innerHTML = '';
domains.forEach((domain, index) => {
const row = document.createElement('tr');
row.innerHTML = `
<td>${domain.domain}</td>
<td>${formatNumber(domain.count)}</td>
`;
tbody.appendChild(row);
});
// 初始化表格排序
initTableSort('top-resolved-table');
}