重大重构

This commit is contained in:
Alex Yang
2026-01-25 15:29:44 +08:00
parent 073f1961b1
commit 7fe06c35e6
53 changed files with 10191 additions and 73770 deletions

View File

@@ -34,7 +34,7 @@ let errorQueries = 0;
// 初始化仪表盘
async function initDashboard() {
try {
console.log('页面打开时强制刷新数据...');
// 优先加载初始数据,确保页面显示最新信息
await loadDashboardData();
@@ -63,14 +63,12 @@ function connectWebSocket() {
const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsUrl = `${wsProtocol}//${window.location.host}/ws/stats`;
console.log('正在连接WebSocket:', wsUrl);
// 创建WebSocket连接
dashboardWsConnection = new WebSocket(wsUrl);
// 连接打开事件
dashboardWsConnection.onopen = function() {
console.log('WebSocket连接已建立');
showNotification('数据更新成功', 'success');
// 清除重连计时器
@@ -86,7 +84,6 @@ function connectWebSocket() {
const data = JSON.parse(event.data);
if (data.type === 'initial_data' || data.type === 'stats_update') {
console.log('收到实时数据更新');
processRealTimeData(data.data);
}
} catch (error) {
@@ -122,7 +119,6 @@ function setupReconnect() {
}
const reconnectDelay = 5000; // 5秒后重连
console.log(`将在${reconnectDelay}ms后尝试重新连接WebSocket`);
dashboardWsReconnectTimer = setTimeout(() => {
connectWebSocket();
@@ -139,7 +135,6 @@ function processRealTimeData(stats) {
lastProcessedTime = now;
try {
console.log('收到实时数据:', stats);
// 确保stats是有效的对象
if (!stats || typeof stats !== 'object') {
@@ -179,15 +174,6 @@ function processRealTimeData(stats) {
allowedQueries = Number(stats.allowedQueries) || 0;
}
console.log('实时数据处理完成,更新后的值:', {
totalQueries,
allowedQueries,
blockedQueries,
errorQueries
});
if (document.getElementById('top-query-type')) {
const queryType = stats.topQueryType || '---';
document.getElementById('top-query-type').textContent = queryType;
@@ -472,7 +458,6 @@ function cleanupResources() {
// 更新统计卡片
function updateStatsCards(stats) {
console.log('更新统计卡片,收到数据:', stats);
// 适配不同的数据结构
// 保存当前显示的值,用于在数据缺失时保留
@@ -876,7 +861,6 @@ function updateStatsCards(stats) {
// 更新Top屏蔽域名表格
async function updateTopBlockedTable(domains) {
console.log('更新Top屏蔽域名表格收到数据:', domains);
const tableBody = document.getElementById('top-blocked-table');
let tableData = [];
@@ -902,7 +886,6 @@ async function updateTopBlockedTable(domains) {
{ name: '---.---.---', count: '---' },
{ name: '---.---.---', count: '---' }
];
console.log('使用示例数据填充Top屏蔽域名表格');
}
// 计算总拦截次数
@@ -985,12 +968,10 @@ async function updateTopBlockedTable(domains) {
// 更新最近屏蔽域名表格
function updateRecentBlockedTable(domains) {
console.log('更新最近屏蔽域名表格,收到数据:', domains);
const tableBody = document.getElementById('recent-blocked-table');
// 确保tableBody存在因为最近屏蔽域名卡片可能已被移除
if (!tableBody) {
console.log('未找到recent-blocked-table元素跳过更新');
return;
}
@@ -1015,7 +996,6 @@ function updateRecentBlockedTable(domains) {
{ name: '---.---.---', timestamp: now - 45 * 60 * 1000, type: '追踪' },
{ name: '---.---.---', timestamp: now - 60 * 60 * 1000, type: '恶意' }
];
console.log('使用示例数据填充最近屏蔽域名表格');
}
let html = '';
@@ -1217,7 +1197,6 @@ function isPrivateIP(ip) {
// 更新TOP客户端表格
async function updateTopClientsTable(clients) {
console.log('更新TOP客户端表格收到数据:', clients);
const tableBody = document.getElementById('top-clients-table');
// 确保tableBody存在
@@ -1260,7 +1239,6 @@ async function updateTopClientsTable(clients) {
{ ip: '---.---.---', count: '---' },
{ ip: '---.---.---', count: '---' }
];
console.log('使用示例数据填充TOP客户端表格');
}
@@ -1291,7 +1269,6 @@ async function updateTopClientsTable(clients) {
// 更新请求域名排行表格
async function updateTopDomainsTable(domains) {
console.log('更新请求域名排行表格,收到数据:', domains);
const tableBody = document.getElementById('top-domains-table');
// 确保tableBody存在
@@ -1325,7 +1302,6 @@ async function updateTopDomainsTable(domains) {
{ name: 'twitter.com', count: 35 },
{ name: 'youtube.com', count: 30 }
];
console.log('使用示例数据填充请求域名排行表格');
}
// 计算总请求次数
@@ -1415,7 +1391,6 @@ let detailedCurrentTimeRange = '24h'; // 详细图表当前时间范围
// 初始化时间范围切换
function initTimeRangeToggle() {
console.log('初始化时间范围切换');
// 查找所有可能的时间范围按钮类名
const allTimeRangeButtons = document.querySelectorAll('.time-range-btn, .time-range-button, .timerange-btn, button[data-range]');
@@ -1426,7 +1401,6 @@ function initTimeRangeToggle() {
return !chartModal || !chartModal.contains(button);
});
console.log('找到时间范围按钮数量:', timeRangeButtons.length, '排除了图表模态框内的按钮');
if (timeRangeButtons.length === 0) {
console.warn('未找到时间范围按钮请检查HTML中的类名');
@@ -1471,13 +1445,11 @@ function initTimeRangeToggle() {
// 移除鼠标悬停提示
console.log('为按钮设置初始样式:', button.textContent.trim(), '索引:', index, '类名:', Array.from(button.classList).join(', '));
button.addEventListener('click', function(event) {
event.preventDefault();
event.stopPropagation();
console.log('点击按钮:', button.textContent.trim(), '索引:', index);
// 重置所有按钮为非选中状态
timeRangeButtons.forEach((btn, btnIndex) => {
@@ -1520,7 +1492,6 @@ function initTimeRangeToggle() {
}
}
currentTimeRange = rangeValue;
console.log('更新时间范围为:', currentTimeRange);
// 重新加载数据
loadDashboardData();
@@ -1554,7 +1525,6 @@ function initTimeRangeToggle() {
defaultButton.classList.add('active');
defaultButton.classList.add(...defaultStyle.active);
defaultButton.classList.add(...defaultStyle.activeHover);
console.log('默认选中24小时按钮:', defaultButton.textContent.trim());
// 设置默认时间范围为24小时
currentTimeRange = '24h';
@@ -1877,12 +1847,10 @@ function initExpandButton() {
const closeModalBtn = document.getElementById('close-modal-btn'); // 修复ID匹配
// 添加调试日志
console.log('初始化展开按钮功能:', { expandBtn, chartModal, closeModalBtn });
if (expandBtn && chartModal && closeModalBtn) {
// 展开按钮点击事件
expandBtn.addEventListener('click', () => {
console.log('展开按钮被点击');
// 显示浮窗
chartModal.classList.remove('hidden');
@@ -1902,7 +1870,6 @@ function initExpandButton() {
// 关闭按钮点击事件
closeModalBtn.addEventListener('click', () => {
console.log('关闭按钮被点击');
chartModal.classList.add('hidden');
});
@@ -1910,7 +1877,6 @@ function initExpandButton() {
chartModal.addEventListener('click', (e) => {
// 检查点击目标是否是遮罩层本身即最外层div
if (e.target === chartModal) {
console.log('点击遮罩层关闭');
chartModal.classList.add('hidden');
}
});
@@ -1918,7 +1884,6 @@ function initExpandButton() {
// ESC键关闭浮窗
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && !chartModal.classList.contains('hidden')) {
console.log('ESC键关闭浮窗');
chartModal.classList.add('hidden');
}
});
@@ -1933,7 +1898,6 @@ function initDetailedTimeRangeToggle() {
const chartModal = document.getElementById('chart-modal');
const detailedTimeRangeButtons = chartModal ? chartModal.querySelectorAll('.time-range-btn') : [];
console.log('初始化详细图表时间范围切换,找到按钮数量:', detailedTimeRangeButtons.length);
// 初始化详细图表的默认状态,与主图表保持一致
detailedCurrentTimeRange = currentTimeRange;
@@ -2016,7 +1980,6 @@ function initDetailedTimeRangeToggle() {
}
}
detailedCurrentTimeRange = rangeValue;
console.log('详细图表更新时间范围为:', detailedCurrentTimeRange);
// 重新绘制详细图表
drawDetailedDNSRequestsChart();
@@ -2026,7 +1989,6 @@ function initDetailedTimeRangeToggle() {
// 绘制详细的DNS请求趋势图表
function drawDetailedDNSRequestsChart() {
console.log('绘制详细DNS请求趋势图表时间范围:', detailedCurrentTimeRange);
const ctx = document.getElementById('detailed-dns-requests-chart');
if (!ctx) {
@@ -2270,8 +2232,6 @@ function drawDNSRequestsChart() {
// 更新图表数据
function updateCharts(stats, queryTypeStats) {
console.log('更新图表,收到统计数据:', stats);
console.log('查询类型统计数据:', queryTypeStats);
// 空值检查
if (!stats) {
@@ -2497,7 +2457,6 @@ function getHostsCountFromStats(stats) {
// 初始化统计卡片折线图
function initStatCardCharts() {
console.log('===== 开始初始化统计卡片折线图 =====');
// 清理已存在的图表实例
for (const key in statCardCharts) {
@@ -2509,7 +2468,6 @@ function initStatCardCharts() {
statCardHistoryData = {};
// 检查Chart.js是否加载
console.log('Chart.js是否可用:', typeof Chart !== 'undefined');
// 统计卡片配置信息
const cardConfigs = [
@@ -2525,7 +2483,6 @@ function initStatCardCharts() {
{ id: 'hosts-chart', color: '#16a085', label: 'Hosts条目数' }
];
console.log('图表配置:', cardConfigs);
cardConfigs.forEach(config => {
const canvas = document.getElementById(config.id);
@@ -3011,7 +2968,6 @@ function addRetryEventListeners() {
const retryTopClientsBtn = document.getElementById('retry-top-clients');
if (retryTopClientsBtn) {
retryTopClientsBtn.addEventListener('click', async () => {
console.log('重试获取TOP客户端数据');
const clientsData = await api.getTopClients();
if (clientsData && !clientsData.error && Array.isArray(clientsData) && clientsData.length > 0) {
// 使用真实数据
@@ -3030,7 +2986,6 @@ function addRetryEventListeners() {
const retryTopDomainsBtn = document.getElementById('retry-top-domains');
if (retryTopDomainsBtn) {
retryTopDomainsBtn.addEventListener('click', async () => {
console.log('重试获取TOP域名数据');
const domainsData = await api.getTopDomains();
if (domainsData && !domainsData.error && Array.isArray(domainsData) && domainsData.length > 0) {
// 使用真实数据
@@ -3068,7 +3023,6 @@ window.addEventListener('DOMContentLoaded', () => {
});
});// 重写loadDashboardData函数修复语法错误
async function loadDashboardData() {
console.log('开始加载仪表盘数据');
try {
// 并行获取所有数据,提高加载效率
const [stats, queryTypeStatsResult, topBlockedDomainsResult, recentBlockedDomainsResult, topClientsResult] = await Promise.all([
@@ -3093,26 +3047,22 @@ async function loadDashboardData() {
return;
}
console.log('统计数据:', stats);
// 处理查询类型统计数据
let queryTypeStats = null;
if (queryTypeStatsResult) {
console.log('查询类型统计数据:', queryTypeStatsResult);
queryTypeStats = queryTypeStatsResult;
} else if (stats.dns && stats.dns.QueryTypes) {
queryTypeStats = Object.entries(stats.dns.QueryTypes).map(([type, count]) => ({
type,
count
}));
console.log('从stats中提取的查询类型统计:', queryTypeStats);
}
// 处理TOP被屏蔽域名
let topBlockedDomains = [];
if (topBlockedDomainsResult && Array.isArray(topBlockedDomainsResult)) {
topBlockedDomains = topBlockedDomainsResult;
console.log('TOP被屏蔽域名:', topBlockedDomains);
} else {
topBlockedDomains = [
{ domain: 'example-blocked.com', count: 15, lastSeen: new Date().toISOString() },
@@ -3125,7 +3075,6 @@ async function loadDashboardData() {
let recentBlockedDomains = [];
if (recentBlockedDomainsResult && Array.isArray(recentBlockedDomainsResult)) {
recentBlockedDomains = recentBlockedDomainsResult;
console.log('最近屏蔽域名:', recentBlockedDomains);
} else {
recentBlockedDomains = [
{ domain: '---.---.---', ip: '---.---.---.---', timestamp: new Date().toISOString() },
@@ -3145,7 +3094,6 @@ async function loadDashboardData() {
let topClients = [];
if (topClientsResult && !topClientsResult.error && Array.isArray(topClientsResult) && topClientsResult.length > 0) {
topClients = topClientsResult;
console.log('TOP客户端:', topClients);
} else {
console.warn('获取TOP客户端失败或数据无效使用模拟数据');
topClients = [
@@ -3162,7 +3110,6 @@ async function loadDashboardData() {
let topDomains = [];
try {
const domainsData = await api.getTopDomains();
console.log('TOP域名:', domainsData);
if (domainsData && !domainsData.error && Array.isArray(domainsData) && domainsData.length > 0) {
topDomains = domainsData;