web重做
This commit is contained in:
246
static/js/modules/dashboard.js
Normal file
246
static/js/modules/dashboard.js
Normal file
@@ -0,0 +1,246 @@
|
||||
// 初始化仪表盘面板
|
||||
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');
|
||||
}
|
||||
Reference in New Issue
Block a user