// dashboard.js - 仪表盘功能实现

// 全局变量
let ratioChart = null;
let dnsRequestsChart = null;
let detailedDnsRequestsChart = null; // 详细DNS请求趋势图表(浮窗)
let queryTypeChart = null; // 解析类型统计饼图
let intervalId = null;
let dashboardWsConnection = null;
let dashboardWsReconnectTimer = null;
// 存储统计卡片图表实例
let statCardCharts = {};
// 存储统计卡片历史数据
let statCardHistoryData = {};
// 存储仪表盘历史数据，用于计算趋势
window.dashboardHistoryData = window.dashboardHistoryData || {
    prevResponseTime: null,
    prevActiveIPs: null,
    prevTopQueryTypeCount: null
};

// 引入颜色配置文件
const COLOR_CONFIG = window.COLOR_CONFIG || {};

// 初始化仪表盘
async function initDashboard() {
    try {
        console.log('页面打开时强制刷新数据...');
        
        // 优先加载初始数据，确保页面显示最新信息
        await loadDashboardData();
        
        // 初始化图表
        initCharts();
        

        
        // 初始化时间范围切换
        initTimeRangeToggle();
        
        // 建立WebSocket连接
        connectWebSocket();
        
        // 在页面卸载时清理资源
        window.addEventListener('beforeunload', cleanupResources);
    } catch (error) {
        console.error('初始化仪表盘失败:', error);
        showNotification('初始化失败: ' + error.message, 'error');
    }
}

// 建立WebSocket连接
function connectWebSocket() {
    try {
        // 构建WebSocket URL
        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');
            
            // 清除重连计时器
            if (dashboardWsReconnectTimer) {
                clearTimeout(dashboardWsReconnectTimer);
                dashboardWsReconnectTimer = null;
            }
        };
        
        // 接收消息事件
        dashboardWsConnection.onmessage = function(event) {
            try {
                const data = JSON.parse(event.data);
                
                if (data.type === 'initial_data' || data.type === 'stats_update') {
                    console.log('收到实时数据更新');
                    processRealTimeData(data.data);
                }
            } catch (error) {
                console.error('处理WebSocket消息失败:', error);
            }
        };
        
        // 连接关闭事件
        dashboardWsConnection.onclose = function(event) {
            console.warn('WebSocket连接已关闭，代码:', event.code);
            dashboardWsConnection = null;
            
            // 设置重连
            setupReconnect();
        };
        
        // 连接错误事件
        dashboardWsConnection.onerror = function(error) {
            console.error('WebSocket连接错误:', error);
        };
        
    } catch (error) {
        console.error('创建WebSocket连接失败:', error);
        // 如果WebSocket连接失败，回退到定时刷新
        fallbackToIntervalRefresh();
    }
}

// 设置重连逻辑
function setupReconnect() {
    if (dashboardWsReconnectTimer) {
        return; // 已经有重连计时器在运行
    }
    
    const reconnectDelay = 5000; // 5秒后重连
    console.log(`将在${reconnectDelay}ms后尝试重新连接WebSocket`);
    
    dashboardWsReconnectTimer = setTimeout(() => {
        connectWebSocket();
    }, reconnectDelay);
}

// 处理实时数据更新
function processRealTimeData(stats) {
    try {
        // 更新统计卡片 - 这会更新所有统计卡片，包括CPU使用率卡片
        updateStatsCards(stats);
        
        // 获取查询类型统计数据
        let queryTypeStats = null;
        if (stats.dns && stats.dns.QueryTypes) {
            queryTypeStats = Object.entries(stats.dns.QueryTypes).map(([type, count]) => ({
                type,
                count
            }));
        }
        
        // 更新图表数据
        updateCharts(stats, queryTypeStats);
        

        
        // 尝试从stats中获取总查询数等信息
        if (stats.dns) {
            totalQueries = stats.dns.Allowed + stats.dns.Blocked + (stats.dns.Errors || 0);
            blockedQueries = stats.dns.Blocked;
            errorQueries = stats.dns.Errors || 0;
            allowedQueries = stats.dns.Allowed;
        } else {
            totalQueries = stats.totalQueries || 0;
            blockedQueries = stats.blockedQueries || 0;
            errorQueries = stats.errorQueries || 0;
            allowedQueries = stats.allowedQueries || 0;
        }
        
        // 更新新卡片数据
        if (document.getElementById('avg-response-time')) {
            const responseTime = stats.avgResponseTime ? stats.avgResponseTime.toFixed(2) + 'ms' : '---';
            
            // 计算响应时间趋势
            let responsePercent = '---';
            let trendClass = 'text-gray-400';
            let trendIcon = '•';
            
            // 查找箭头元素
            const responseTimePercentElem = document.getElementById('response-time-percent');
            let parent = null;
            let arrowIcon = null;
            
            if (responseTimePercentElem) {
                parent = responseTimePercentElem.parentElement;
                if (parent) {
                    arrowIcon = parent.querySelector('.fa-arrow-up, .fa-arrow-down, .fa-circle');
                }
            }
            
            if (stats.avgResponseTime !== undefined && stats.avgResponseTime !== null) {
                // 首次加载时初始化历史数据，不计算趋势
                if (window.dashboardHistoryData.prevResponseTime === undefined || window.dashboardHistoryData.prevResponseTime === null) {
                    window.dashboardHistoryData.prevResponseTime = stats.avgResponseTime;
                    responsePercent = '0.0%';
                    trendIcon = '•';
                    trendClass = 'text-gray-500';
                    if (arrowIcon) {
                        arrowIcon.className = 'fa fa-circle mr-1 text-xs';
                        parent.className = 'text-gray-500 text-sm flex items-center';
                    }
                } else {
                    const prevResponseTime = window.dashboardHistoryData.prevResponseTime;
                    
                    // 计算变化百分比
                    const changePercent = ((stats.avgResponseTime - prevResponseTime) / prevResponseTime) * 100;
                    responsePercent = Math.abs(changePercent).toFixed(1) + '%';
                    
                    // 处理-0.0%的情况
                    if (responsePercent === '-0.0%') {
                        responsePercent = '0.0%';
                    }
                    
                    // 根据用户要求：数量下降显示红色箭头，上升显示绿色箭头
                    if (changePercent > 0) {
                        // 响应时间增加，数值上升
                        trendIcon = '↑';
                        trendClass = 'text-success';
                        if (arrowIcon) {
                            arrowIcon.className = 'fa fa-arrow-up mr-1';
                            parent.className = 'text-success text-sm flex items-center';
                        }
                    } else if (changePercent < 0) {
                        // 响应时间减少，数值下降
                        trendIcon = '↓';
                        trendClass = 'text-danger';
                        if (arrowIcon) {
                            arrowIcon.className = 'fa fa-arrow-down mr-1';
                            parent.className = 'text-danger text-sm flex items-center';
                        }
                    } else {
                        // 趋势为0时，显示圆点图标
                        trendIcon = '•';
                        trendClass = 'text-gray-500';
                        if (arrowIcon) {
                            arrowIcon.className = 'fa fa-circle mr-1 text-xs';
                            parent.className = 'text-gray-500 text-sm flex items-center';
                        }
                    }
                    
                    // 更新历史数据
                    window.dashboardHistoryData.prevResponseTime = stats.avgResponseTime;
                }
            }
            
            document.getElementById('avg-response-time').textContent = responseTime;
            if (responseTimePercentElem) {
                responseTimePercentElem.textContent = trendIcon + ' ' + responsePercent;
                responseTimePercentElem.className = `text-sm flex items-center ${trendClass}`;
            }
        }
        
        if (document.getElementById('top-query-type')) {
            const queryType = stats.topQueryType || '---';
            document.getElementById('top-query-type').textContent = queryType;
            
            const queryPercentElem = document.getElementById('query-type-percentage');
            if (queryPercentElem) {
                // 计算最常用查询类型的百分比
                let queryTypePercentage = 0;
                if (stats.dns && stats.dns.QueryTypes && stats.dns.Queries > 0) {
                    const topTypeCount = stats.dns.QueryTypes[queryType] || 0;
                    queryTypePercentage = (topTypeCount / stats.dns.Queries) * 100;
                }
                
                queryPercentElem.textContent = `${Math.round(queryTypePercentage)}%`;
                queryPercentElem.className = 'text-sm flex items-center text-primary';
            }
        }
        
        if (document.getElementById('active-ips')) {
            const activeIPs = stats.activeIPs !== undefined ? formatNumber(stats.activeIPs) : '---';
            
            // 计算活跃IP趋势
            let ipsPercent = '---';
            let trendClass = 'text-gray-400';
            let trendIcon = '•';
            
            // 查找箭头元素
            const activeIpsPercentElem = document.getElementById('active-ips-percent');
            let parent = null;
            let arrowIcon = null;
            
            if (activeIpsPercentElem) {
                parent = activeIpsPercentElem.parentElement;
                if (parent) {
                    arrowIcon = parent.querySelector('.fa-arrow-up, .fa-arrow-down, .fa-circle');
                }
            }
            
            if (stats.activeIPs !== undefined) {
                const prevActiveIPs = window.dashboardHistoryData.prevActiveIPs;
                
                // 首次加载时初始化历史数据，不计算趋势
                if (prevActiveIPs === null) {
                    window.dashboardHistoryData.prevActiveIPs = stats.activeIPs;
                    ipsPercent = '0.0%';
                    trendIcon = '•';
                    trendClass = 'text-gray-500';
                    if (arrowIcon) {
                        arrowIcon.className = 'fa fa-circle mr-1 text-xs';
                        parent.className = 'text-gray-500 text-sm flex items-center';
                    }
                } else {
                    if (prevActiveIPs > 0) {
                        const changePercent = ((stats.activeIPs - prevActiveIPs) / prevActiveIPs) * 100;
                        ipsPercent = Math.abs(changePercent).toFixed(1) + '%';
                        
                        // 处理-0.0%的情况
                        if (ipsPercent === '-0.0%') {
                            ipsPercent = '0.0%';
                        }
                        
                        // 根据用户要求：数量下降显示红色箭头，上升显示绿色箭头
                        if (changePercent > 0) {
                            trendIcon = '↑';
                            trendClass = 'text-success';
                            if (arrowIcon) {
                                arrowIcon.className = 'fa fa-arrow-up mr-1';
                                parent.className = 'text-success text-sm flex items-center';
                            }
                        } else if (changePercent < 0) {
                            trendIcon = '↓';
                            trendClass = 'text-danger';
                            if (arrowIcon) {
                                arrowIcon.className = 'fa fa-arrow-down mr-1';
                                parent.className = 'text-danger text-sm flex items-center';
                            }
                        } else {
                            // 趋势为0时，显示圆点图标
                            trendIcon = '•';
                            trendClass = 'text-gray-500';
                            if (arrowIcon) {
                                arrowIcon.className = 'fa fa-circle mr-1 text-xs';
                                parent.className = 'text-gray-500 text-sm flex items-center';
                            }
                        }
                    }
                    
                    // 更新历史数据
                    window.dashboardHistoryData.prevActiveIPs = stats.activeIPs;
                }
            }
            
            document.getElementById('active-ips').textContent = activeIPs;
            if (activeIpsPercentElem) {
                activeIpsPercentElem.textContent = trendIcon + ' ' + ipsPercent;
                activeIpsPercentElem.className = `text-sm flex items-center ${trendClass}`;
            }
        }
        
        // 实时更新TOP客户端和TOP域名数据
        updateTopData();
        
    } catch (error) {
        console.error('处理实时数据失败:', error);
    }
}

// 实时更新TOP客户端和TOP域名数据
async function updateTopData() {
    try {
        // 隐藏所有加载中状态
        const clientsLoadingElement = document.getElementById('top-clients-loading');
        if (clientsLoadingElement) {
            clientsLoadingElement.classList.add('hidden');
        }
        
        const domainsLoadingElement = document.getElementById('top-domains-loading');
        if (domainsLoadingElement) {
            domainsLoadingElement.classList.add('hidden');
        }
        
        // 获取最新的TOP客户端数据
        let clientsData = [];
        try {
            clientsData = await api.getTopClients();
        } catch (error) {
            console.error('获取TOP客户端数据失败:', error);
        }
        
        if (clientsData && !clientsData.error && Array.isArray(clientsData)) {
            if (clientsData.length > 0) {
                // 使用真实数据
                updateTopClientsTable(clientsData);
                // 隐藏错误信息
                const errorElement = document.getElementById('top-clients-error');
                if (errorElement) errorElement.classList.add('hidden');
            } else {
                // 数据为空，使用模拟数据
                const mockClients = [
                    { ip: '---.---.---.---', count: '---' },
                    { ip: '---.---.---.---', count: '---' },
                    { ip: '---.---.---.---', count: '---' },
                    { ip: '---.---.---.---', count: '---' },
                    { ip: '---.---.---.---', count: '---' }
                ];
                updateTopClientsTable(mockClients);
            }
        } else {
            // API调用失败或返回错误，使用模拟数据
            const mockClients = [
                { ip: '---.---.---.---', count: '---' },
                { ip: '---.---.---.---', count: '---' },
                { ip: '---.---.---.---', count: '---' },
                { ip: '---.---.---.---', count: '---' },
                { ip: '---.---.---.---', count: '---' }
            ];
            updateTopClientsTable(mockClients);
        }
        
        // 获取最新的TOP域名数据
        let domainsData = [];
        try {
            domainsData = await api.getTopDomains();
        } catch (error) {
            console.error('获取TOP域名数据失败:', error);
        }
        
        if (domainsData && !domainsData.error && Array.isArray(domainsData)) {
            if (domainsData.length > 0) {
                // 使用真实数据
                updateTopDomainsTable(domainsData);
                // 隐藏错误信息
                const errorElement = document.getElementById('top-domains-error');
                if (errorElement) errorElement.classList.add('hidden');
            } else {
                // 数据为空，使用模拟数据
                const mockDomains = [
                    { domain: 'example.com', count: 50 },
                    { domain: 'google.com', count: 45 },
                    { domain: 'facebook.com', count: 40 },
                    { domain: 'twitter.com', count: 35 },
                    { domain: 'youtube.com', count: 30 }
                ];
                updateTopDomainsTable(mockDomains);
            }
        } else {
            // API调用失败或返回错误，使用模拟数据
            const mockDomains = [
                { domain: 'example.com', count: 50 },
                { domain: 'google.com', count: 45 },
                { domain: 'facebook.com', count: 40 },
                { domain: 'twitter.com', count: 35 },
                { domain: 'youtube.com', count: 30 }
            ];
            updateTopDomainsTable(mockDomains);
        }
    } catch (error) {
        console.error('更新TOP数据失败:', error);
        // 出错时使用模拟数据
        const mockDomains = [
            { domain: 'example.com', count: 50 },
            { domain: 'google.com', count: 45 },
            { domain: 'facebook.com', count: 40 },
            { domain: 'twitter.com', count: 35 },
            { domain: 'youtube.com', count: 30 }
        ];
        updateTopDomainsTable(mockDomains);
    }
}

// 回退到定时刷新
function fallbackToIntervalRefresh() {
    console.warn('回退到定时刷新模式');
    showNotification('实时更新连接失败，已切换到定时刷新模式', 'warning');
    
    // 如果已经有定时器，先清除
    if (intervalId) {
        clearInterval(intervalId);
    }
    
    // 设置新的定时器
    intervalId = setInterval(async () => {
        try {
            await loadDashboardData();
        } catch (error) {
            console.error('定时刷新失败:', error);
        }
    }, 5000); // 每5秒更新一次
}

// 清理资源
function cleanupResources() {
    // 清除WebSocket连接
    if (dashboardWsConnection) {
        dashboardWsConnection.close();
        dashboardWsConnection = null;
    }
    
    // 清除重连计时器
    if (dashboardWsReconnectTimer) {
        clearTimeout(dashboardWsReconnectTimer);
        dashboardWsReconnectTimer = null;
    }
    
    // 清除定时刷新
    if (intervalId) {
        clearInterval(intervalId);
        intervalId = null;
    }
}

// 加载仪表盘数据
async function loadDashboardData() {
    console.log('开始加载仪表盘数据');
    try {
        // 获取基本统计数据
        const stats = await api.getStats();
        console.log('统计数据:', stats);
        
        // 获取查询类型统计数据
        let queryTypeStats = null;
        try {
            queryTypeStats = await api.getQueryTypeStats();
            console.log('查询类型统计数据:', queryTypeStats);
        } catch (error) {
            console.warn('获取查询类型统计失败:', error);
            // 如果API调用失败，尝试从stats中提取查询类型数据
            if (stats && stats.dns && stats.dns.QueryTypes) {
                queryTypeStats = Object.entries(stats.dns.QueryTypes).map(([type, count]) => ({
                    type,
                    count
                }));
                console.log('从stats中提取的查询类型统计:', queryTypeStats);
            }
        }
        
        // 尝试获取TOP被屏蔽域名，如果失败则提供模拟数据
        let topBlockedDomains = [];
        try {
            topBlockedDomains = await api.getTopBlockedDomains();
            console.log('TOP被屏蔽域名:', topBlockedDomains);
            
            // 确保返回的数据是数组
            if (!Array.isArray(topBlockedDomains)) {
                console.warn('TOP被屏蔽域名不是预期的数组格式，使用模拟数据');
                topBlockedDomains = [];
            }
        } catch (error) {
            console.warn('获取TOP被屏蔽域名失败:', error);
            // 提供模拟数据
            topBlockedDomains = [
                { domain: 'example-blocked.com', count: 15, lastSeen: new Date().toISOString() },
                { domain: 'ads.example.org', count: 12, lastSeen: new Date().toISOString() },
                { domain: 'tracking.example.net', count: 8, lastSeen: new Date().toISOString() }
            ];
        }
        
        // 尝试获取最近屏蔽域名，如果失败则提供模拟数据
        let recentBlockedDomains = [];
        try {
            recentBlockedDomains = await api.getRecentBlockedDomains();
            console.log('最近屏蔽域名:', recentBlockedDomains);
            
            // 确保返回的数据是数组
            if (!Array.isArray(recentBlockedDomains)) {
                console.warn('最近屏蔽域名不是预期的数组格式，使用模拟数据');
                recentBlockedDomains = [];
            }
        } catch (error) {
            console.warn('获取最近屏蔽域名失败:', error);
            // 提供模拟数据
            recentBlockedDomains = [
                { domain: '---.---.---', ip: '---.---.---.---', timestamp: new Date().toISOString() },
                { domain: '---.---.---', ip: '---.---.---.---', timestamp: new Date().toISOString() }
            ];
        }
        

        
        function showError(elementId) {
            const loadingElement = document.getElementById(elementId + '-loading');
            const errorElement = document.getElementById(elementId + '-error');
            if (loadingElement) loadingElement.classList.add('hidden');
            if (errorElement) errorElement.classList.remove('hidden');
        }
        
        // 尝试获取TOP客户端，优先使用真实数据，失败时使用模拟数据
        let topClients = [];
        try {
            const clientsData = await api.getTopClients();
            console.log('TOP客户端:', clientsData);
            
            // 检查数据是否有效
            if (clientsData && !clientsData.error && Array.isArray(clientsData) && clientsData.length > 0) {
                // 使用真实数据
                topClients = clientsData;
            } else if (clientsData && clientsData.error) {
                // API返回错误
                console.warn('获取TOP客户端失败:', clientsData.error);
                // 使用模拟数据
                topClients = [
                    { ip: '192.168.1.100', count: 120 },
                    { ip: '192.168.1.101', count: 95 },
                    { ip: '192.168.1.102', count: 80 },
                    { ip: '192.168.1.103', count: 65 },
                    { ip: '192.168.1.104', count: 50 }
                ];
                showError('top-clients');
            } else {
                // 数据为空或格式不正确
                console.warn('TOP客户端数据为空或格式不正确，使用模拟数据');
                // 使用模拟数据
                topClients = [
                    { ip: '192.168.1.100', count: 120 },
                    { ip: '192.168.1.101', count: 95 },
                    { ip: '192.168.1.102', count: 80 },
                    { ip: '192.168.1.103', count: 65 },
                    { ip: '192.168.1.104', count: 50 }
                ];
                showError('top-clients');
            }
        } catch (error) {
            console.warn('获取TOP客户端失败:', error);
            // 使用模拟数据
            topClients = [
                { ip: '192.168.1.100', count: 120 },
                { ip: '192.168.1.101', count: 95 },
                { ip: '192.168.1.102', count: 80 },
                { ip: '192.168.1.103', count: 65 },
                { ip: '192.168.1.104', count: 50 }
            ];
            showError('top-clients');
        }
        
        // 尝试获取TOP域名，优先使用真实数据，失败时使用模拟数据
        let topDomains = [];
        try {
            const domainsData = await api.getTopDomains();
            console.log('TOP域名:', domainsData);
            
            // 检查数据是否有效
            if (domainsData && !domainsData.error && Array.isArray(domainsData) && domainsData.length > 0) {
                // 使用真实数据
                topDomains = domainsData;
            } else if (domainsData && domainsData.error) {
                // API返回错误
                console.warn('获取TOP域名失败:', domainsData.error);
                // 使用模拟数据
                topDomains = [
                    { domain: 'example.com', count: 50 },
                    { domain: 'google.com', count: 45 },
                    { domain: 'facebook.com', count: 40 },
                    { domain: 'twitter.com', count: 35 },
                    { domain: 'youtube.com', count: 30 }
                ];
                showError('top-domains');
            } else {
                // 数据为空或格式不正确
                console.warn('TOP域名数据为空或格式不正确，使用模拟数据');
                // 使用模拟数据
                topDomains = [
                    { domain: 'example.com', count: 50 },
                    { domain: 'google.com', count: 45 },
                    { domain: 'facebook.com', count: 40 },
                    { domain: 'twitter.com', count: 35 },
                    { domain: 'youtube.com', count: 30 }
                ];
                showError('top-domains');
            }
        } catch (error) {
            console.warn('获取TOP域名失败:', error);
            // 使用模拟数据
            topDomains = [
                { domain: 'example.com', count: 50 },
                { domain: 'google.com', count: 45 },
                { domain: 'facebook.com', count: 40 },
                { domain: 'twitter.com', count: 35 },
                { domain: 'youtube.com', count: 30 }
            ];
            showError('top-domains');
        }
        
        // 更新统计卡片
        updateStatsCards(stats);
        
        // 更新图表数据，传入查询类型统计
        updateCharts(stats, queryTypeStats);
        
        // 更新表格数据
        await updateTopBlockedTable(topBlockedDomains);
        updateRecentBlockedTable(recentBlockedDomains);
        await updateTopClientsTable(topClients);
        await updateTopDomainsTable(topDomains);
        
        // 尝试从stats中获取总查询数等信息
        if (stats.dns) {
            totalQueries = stats.dns.Allowed + stats.dns.Blocked + (stats.dns.Errors || 0);
            blockedQueries = stats.dns.Blocked;
            errorQueries = stats.dns.Errors || 0;
            allowedQueries = stats.dns.Allowed;
        } else {
            totalQueries = stats.totalQueries || 0;
            blockedQueries = stats.blockedQueries || 0;
            errorQueries = stats.errorQueries || 0;
            allowedQueries = stats.allowedQueries || 0;
        }
        
        // 全局历史数据对象，用于存储趋势计算所需的上一次值
        window.dashboardHistoryData = window.dashboardHistoryData || {};
        
        // 更新新卡片数据 - 使用API返回的真实数据
        if (document.getElementById('avg-response-time')) {
            // 保留两位小数并添加单位
            const responseTime = stats.avgResponseTime ? stats.avgResponseTime.toFixed(2) + 'ms' : '---';
            
            // 计算响应时间趋势
            let responsePercent = '---';
            let trendClass = 'text-gray-400';
            let trendIcon = '•';
            
            // 查找箭头元素
            const responseTimePercentElem = document.getElementById('response-time-percent');
            let parent = null;
            let arrowIcon = null;
            
            if (responseTimePercentElem) {
                parent = responseTimePercentElem.parentElement;
                if (parent) {
                    arrowIcon = parent.querySelector('.fa-arrow-up, .fa-arrow-down, .fa-circle');
                }
            }
            
            if (stats.avgResponseTime !== undefined && stats.avgResponseTime !== null) {
                // 首次加载时初始化历史数据，不计算趋势
                if (window.dashboardHistoryData.prevResponseTime === undefined || window.dashboardHistoryData.prevResponseTime === null) {
                    window.dashboardHistoryData.prevResponseTime = stats.avgResponseTime;
                    responsePercent = '0.0%';
                    trendIcon = '•';
                    trendClass = 'text-gray-500';
                    if (arrowIcon) {
                        arrowIcon.className = 'fa fa-circle mr-1 text-xs';
                        parent.className = 'text-gray-500 text-sm flex items-center';
                    }
                } else {
                    const prevResponseTime = window.dashboardHistoryData.prevResponseTime;
                    
                    // 计算变化百分比
                    if (prevResponseTime > 0) {
                        const changePercent = ((stats.avgResponseTime - prevResponseTime) / prevResponseTime) * 100;
                        responsePercent = Math.abs(changePercent).toFixed(1) + '%';
                        
                        // 处理-0.0%的情况
                        if (responsePercent === '-0.0%') {
                            responsePercent = '0.0%';
                        }
                        
                        // 根据用户要求：数量下降显示红色箭头，上升显示绿色箭头
                        // 对于响应时间，数值增加表示性能下降，数值减少表示性能提升
                        // 但根据用户要求，我们只根据数值变化方向来设置颜色
                        if (changePercent > 0) {
                            // 响应时间增加（性能下降），数值上升
                            trendIcon = '↑';
                            trendClass = 'text-success';
                            if (arrowIcon) {
                                arrowIcon.className = 'fa fa-arrow-up mr-1';
                                parent.className = 'text-success text-sm flex items-center';
                            }
                        } else if (changePercent < 0) {
                            // 响应时间减少（性能提升），数值下降
                            trendIcon = '↓';
                            trendClass = 'text-danger';
                            if (arrowIcon) {
                                arrowIcon.className = 'fa fa-arrow-down mr-1';
                                parent.className = 'text-danger text-sm flex items-center';
                            }
                        } else {
                            // 趋势为0时，显示圆点图标
                            trendIcon = '•';
                            trendClass = 'text-gray-500';
                            if (arrowIcon) {
                                arrowIcon.className = 'fa fa-circle mr-1 text-xs';
                                parent.className = 'text-gray-500 text-sm flex items-center';
                            }
                        }
                    }
                    
                    // 更新历史数据
                    window.dashboardHistoryData.prevResponseTime = stats.avgResponseTime;
                }
            }
            
            document.getElementById('avg-response-time').textContent = responseTime;
            if (responseTimePercentElem) {
                responseTimePercentElem.textContent = trendIcon + ' ' + responsePercent;
                responseTimePercentElem.className = `text-sm flex items-center ${trendClass}`;
            }
        }
        
        if (document.getElementById('top-query-type')) {
            // 直接使用API返回的查询类型
            const queryType = stats.topQueryType || '---';
            
            // 计算最常用查询类型的百分比
            let queryTypePercentage = 0;
            if (stats.dns && stats.dns.QueryTypes && stats.dns.Queries > 0) {
                const topTypeCount = stats.dns.QueryTypes[queryType] || 0;
                queryTypePercentage = (topTypeCount / stats.dns.Queries) * 100;
            }
            
            const queryPercentElem = document.getElementById('query-type-percentage');
            if (queryPercentElem) {
                queryPercentElem.textContent = `• ${Math.round(queryTypePercentage)}%`;
                queryPercentElem.className = 'text-sm flex items-center text-primary';
            }
            
            document.getElementById('top-query-type').textContent = queryType;
        }
        
        if (document.getElementById('active-ips')) {
            // 直接使用API返回的活跃IP数
            const activeIPs = stats.activeIPs !== undefined ? formatNumber(stats.activeIPs) : '---';
            
            // 计算活跃IP趋势
            let ipsPercent = '---';
            let trendClass = 'text-gray-400';
            let trendIcon = '•';
            
            // 查找箭头元素
            const activeIpsPercentElem = document.getElementById('active-ips-percent');
            let parent = null;
            let arrowIcon = null;
            
            if (activeIpsPercentElem) {
                parent = activeIpsPercentElem.parentElement;
                if (parent) {
                    arrowIcon = parent.querySelector('.fa-arrow-up, .fa-arrow-down');
                }
            }
            
            if (stats.activeIPs !== undefined && stats.activeIPs !== null) {
                // 存储当前值用于下次计算趋势
                const prevActiveIPs = window.dashboardHistoryData.prevActiveIPs || stats.activeIPs;
                window.dashboardHistoryData.prevActiveIPs = stats.activeIPs;
                
                // 计算变化百分比
                if (prevActiveIPs > 0) {
                    const changePercent = ((stats.activeIPs - prevActiveIPs) / prevActiveIPs) * 100;
                    ipsPercent = Math.abs(changePercent).toFixed(1) + '%';
                    
                    // 设置趋势图标和颜色
                    if (changePercent > 0) {
                        trendIcon = '↑';
                        trendClass = 'text-success';
                        
                        // 更新箭头图标和颜色
                        if (arrowIcon) {
                            arrowIcon.className = 'fa fa-arrow-up mr-1';
                            parent.className = 'text-success text-sm flex items-center';
                        }
                    } else if (changePercent < 0) {
                        trendIcon = '↓';
                        trendClass = 'text-danger';
                        
                        // 更新箭头图标和颜色
                        if (arrowIcon) {
                            arrowIcon.className = 'fa fa-arrow-down mr-1';
                            parent.className = 'text-danger text-sm flex items-center';
                        }
                    } else {
                        trendIcon = '•';
                        trendClass = 'text-gray-500';
                    }
                }
            }
            
            document.getElementById('active-ips').textContent = activeIPs;
            if (activeIpsPercentElem) {
                activeIpsPercentElem.textContent = trendIcon + ' ' + ipsPercent;
                activeIpsPercentElem.className = `text-sm flex items-center ${trendClass}`;
            }
        }
        
        // 更新图表
        updateCharts({totalQueries, blockedQueries, allowedQueries, errorQueries});
        
        // 确保响应时间图表使用API实时数据
        if (document.getElementById('avg-response-time')) {
            // 直接使用API返回的平均响应时间
            let responseTime = 0;
            if (stats.dns && stats.dns.AvgResponseTime) {
                responseTime = stats.dns.AvgResponseTime;
            } else if (stats.avgResponseTime !== undefined) {
                responseTime = stats.avgResponseTime;
            } else if (stats.responseTime) {
                responseTime = stats.responseTime;
            }
            
            if (responseTime > 0 && statCardCharts['response-time-chart']) {
                // 限制小数位数为两位并更新图表
                updateChartData('response-time-chart', parseFloat(responseTime).toFixed(2));
            }
        }
        
        // 更新运行状态
        updateUptime();
        
        // 确保TOP域名数据被正确加载
        updateTopData();
    } catch (error) {
        console.error('加载仪表盘数据失败:', error);
        // 静默失败，不显示通知以免打扰用户
    }
}

// 更新统计卡片
function updateStatsCards(stats) {
    console.log('更新统计卡片，收到数据:', stats);
    
    // 适配不同的数据结构
    // 保存当前显示的值，用于在数据缺失时保留
    let totalQueries, blockedQueries, allowedQueries, errorQueries;
    let topQueryType = 'A', queryTypePercentage = 0;
    let activeIPs, activeIPsPercentage = 0;
    
    // 优先从DOM中获取当前显示的值，作为默认值
    const totalQueriesElem = document.getElementById('total-queries');
    const blockedQueriesElem = document.getElementById('blocked-queries');
    const allowedQueriesElem = document.getElementById('allowed-queries');
    const errorQueriesElem = document.getElementById('error-queries');
    const activeIPsElem = document.getElementById('active-ips');
    
    // 解析当前显示的值，作为默认值
    const getCurrentValue = (elem) => {
        if (!elem) return 0;
        const text = elem.textContent.replace(/,/g, '').replace(/[^0-9]/g, '');
        return parseInt(text) || 0;
    };
    
    // 初始化默认值为当前显示的值
    totalQueries = getCurrentValue(totalQueriesElem);
    blockedQueries = getCurrentValue(blockedQueriesElem);
    allowedQueries = getCurrentValue(allowedQueriesElem);
    errorQueries = getCurrentValue(errorQueriesElem);
    activeIPs = getCurrentValue(activeIPsElem);
    
    // 检查数据结构，兼容可能的不同格式
    if (stats) {
        // 优先使用顶层字段，只有当值存在时才更新
        if (stats.totalQueries !== undefined) totalQueries = stats.totalQueries;
        if (stats.blockedQueries !== undefined) blockedQueries = stats.blockedQueries;
        if (stats.allowedQueries !== undefined) allowedQueries = stats.allowedQueries;
        if (stats.errorQueries !== undefined) errorQueries = stats.errorQueries;
        if (stats.topQueryType !== undefined) topQueryType = stats.topQueryType;
        if (stats.queryTypePercentage !== undefined) queryTypePercentage = stats.queryTypePercentage;
        if (stats.activeIPs !== undefined) activeIPs = stats.activeIPs;
        if (stats.activeIPsPercentage !== undefined) activeIPsPercentage = stats.activeIPsPercentage;

        
        // 如果dns对象存在，优先使用其中的数据
        if (stats.dns) {
            if (stats.dns.Queries !== undefined) totalQueries = stats.dns.Queries;
            if (stats.dns.Blocked !== undefined) blockedQueries = stats.dns.Blocked;
            if (stats.dns.Allowed !== undefined) allowedQueries = stats.dns.Allowed;
            if (stats.dns.Errors !== undefined) errorQueries = stats.dns.Errors;
            
            // 计算最常用查询类型的百分比
            if (stats.dns.QueryTypes && stats.dns.Queries > 0) {
                const topTypeCount = stats.dns.QueryTypes[topQueryType] || 0;
                queryTypePercentage = (topTypeCount / stats.dns.Queries) * 100;
            }
            
            // 计算活跃IP百分比（基于已有的活跃IP数）
            if (activeIPs > 0 && stats.dns.SourceIPs) {
                activeIPsPercentage = activeIPs / Object.keys(stats.dns.SourceIPs).length * 100;
            }
        }
    } else if (Array.isArray(stats) && stats.length > 0) {
        // 可能的数据结构3: 数组形式
        if (stats[0].total !== undefined) totalQueries = stats[0].total;
        if (stats[0].blocked !== undefined) blockedQueries = stats[0].blocked;
        if (stats[0].allowed !== undefined) allowedQueries = stats[0].allowed;
        if (stats[0].error !== undefined) errorQueries = stats[0].error;
        if (stats[0].topQueryType !== undefined) topQueryType = stats[0].topQueryType;
        if (stats[0].queryTypePercentage !== undefined) queryTypePercentage = stats[0].queryTypePercentage;
        if (stats[0].activeIPs !== undefined) activeIPs = stats[0].activeIPs;
        if (stats[0].activeIPsPercentage !== undefined) activeIPsPercentage = stats[0].activeIPsPercentage;
    }
    
    // 存储正在进行的动画状态，避免动画重叠
    const animationInProgress = {};
    
    // 为数字元素添加翻页滚动特效
    function animateValue(elementId, newValue) {
        const element = document.getElementById(elementId);
        if (!element) return;
        
        // 如果该元素正在进行动画，取消当前动画并立即更新值
        if (animationInProgress[elementId]) {
            // 清除之前可能设置的定时器
            clearTimeout(animationInProgress[elementId].timeout1);
            clearTimeout(animationInProgress[elementId].timeout2);
            clearTimeout(animationInProgress[elementId].timeout3);
            
            // 立即设置新值，避免显示错乱
            const formattedNewValue = formatNumber(newValue);
            element.innerHTML = formattedNewValue;
            return;
        }
        
        const oldValue = parseInt(element.textContent.replace(/,/g, '')) || 0;
        const formattedNewValue = formatNumber(newValue);
        
        // 如果值没有变化，不执行动画
        if (oldValue === newValue && element.textContent === formattedNewValue) {
            return;
        }
        
        // 先移除可能存在的光晕效果类
        element.classList.remove('number-glow', 'number-glow-blue', 'number-glow-red', 'number-glow-green', 'number-glow-yellow');
        element.classList.remove('number-glow-dark-blue', 'number-glow-dark-red', 'number-glow-dark-green', 'number-glow-dark-yellow');
        
        // 保存原始样式
        const originalStyle = element.getAttribute('style') || '';
        
        try {
            // 复制原始元素的样式到新元素，确保大小完全一致
            const computedStyle = getComputedStyle(element);
            
            // 配置翻页容器样式，确保与原始元素大小完全一致
            const containerStyle = 
                'position: relative; ' +
                'display: ' + computedStyle.display + '; ' +
                'overflow: hidden; ' +
                'height: ' + element.offsetHeight + 'px; ' +
                'width: ' + element.offsetWidth + 'px; ' +
                'margin: ' + computedStyle.margin + '; ' +
                'padding: ' + computedStyle.padding + '; ' +
                'box-sizing: ' + computedStyle.boxSizing + '; ' +
                'line-height: ' + computedStyle.lineHeight + ';';
            
            // 创建翻页容器
            const flipContainer = document.createElement('div');
            flipContainer.style.cssText = containerStyle;
            flipContainer.className = 'number-flip-container';
            
            // 创建旧值元素
            const oldValueElement = document.createElement('div');
            oldValueElement.textContent = element.textContent;
            oldValueElement.style.cssText = 
                'position: absolute; ' +
                'top: 0; ' +
                'left: 0; ' +
                'width: 100%; ' +
                'height: 100%; ' +
                'display: flex; ' +
                'align-items: center; ' +
                'justify-content: center; ' +
                'transition: transform 400ms ease-in-out; ' +
                'transform-origin: center;';
            
            // 创建新值元素
            const newValueElement = document.createElement('div');
            newValueElement.textContent = formattedNewValue;
            newValueElement.style.cssText = 
                'position: absolute; ' +
                'top: 0; ' +
                'left: 0; ' +
                'width: 100%; ' +
                'height: 100%; ' +
                'display: flex; ' +
                'align-items: center; ' +
                'justify-content: center; ' +
                'transition: transform 400ms ease-in-out; ' +
                'transform-origin: center; ' +
                'transform: translateY(100%);';
            [oldValueElement, newValueElement].forEach(el => {
                el.style.fontSize = computedStyle.fontSize;
                el.style.fontWeight = computedStyle.fontWeight;
                el.style.color = computedStyle.color;
                el.style.fontFamily = computedStyle.fontFamily;
                el.style.textAlign = computedStyle.textAlign;
                el.style.lineHeight = computedStyle.lineHeight;
                el.style.width = '100%';
                el.style.height = '100%';
                el.style.margin = '0';
                el.style.padding = '0';
                el.style.boxSizing = 'border-box';
                el.style.whiteSpace = computedStyle.whiteSpace;
                el.style.overflow = 'hidden';
                el.style.textOverflow = 'ellipsis';
                // 确保垂直对齐正确
                el.style.verticalAlign = 'middle';
            });
            
            // 替换原始元素的内容
            element.textContent = '';
            flipContainer.appendChild(oldValueElement);
            flipContainer.appendChild(newValueElement);
            element.appendChild(flipContainer);
            
            // 标记该元素正在进行动画
            animationInProgress[elementId] = {};
            
            // 启动翻页动画
            animationInProgress[elementId].timeout1 = setTimeout(() => {
                if (oldValueElement && newValueElement) {
                    oldValueElement.style.transform = 'translateY(-100%)';
                    newValueElement.style.transform = 'translateY(0)';
                }
            }, 50);
            
            // 动画结束后，恢复原始元素
            animationInProgress[elementId].timeout2 = setTimeout(() => {
                try {
                    // 清理并设置最终值
                    element.innerHTML = formattedNewValue;
                    if (originalStyle) {
                        element.setAttribute('style', originalStyle);
                    } else {
                        element.removeAttribute('style');
                    }
                    
                    // 添加当前卡片颜色的深色光晕效果
                    const card = element.closest('.stat-card, .bg-blue-50, .bg-red-50, .bg-green-50, .bg-yellow-50');
                    let glowColorClass = '';
                    
                    if (card) {
                        if (card.classList.contains('bg-blue-50') || card.id.includes('total') || card.id.includes('response')) {
                            glowColorClass = 'number-glow-dark-blue';
                        } else if (card.classList.contains('bg-red-50') || card.id.includes('blocked')) {
                            glowColorClass = 'number-glow-dark-red';
                        } else if (card.classList.contains('bg-green-50') || card.id.includes('allowed') || card.id.includes('active')) {
                            glowColorClass = 'number-glow-dark-green';
                        } else if (card.classList.contains('bg-yellow-50') || card.id.includes('error') || card.id.includes('cpu')) {
                            glowColorClass = 'number-glow-dark-yellow';
                        }
                    }
                    
                    if (glowColorClass) {
                        element.classList.add(glowColorClass);
                        
                        // 2秒后移除光晕效果
                        animationInProgress[elementId].timeout3 = setTimeout(() => {
                            element.classList.remove('number-glow-dark-blue', 'number-glow-dark-red', 'number-glow-dark-green', 'number-glow-dark-yellow');
                        }, 2000);
                    }
                } catch (e) {
                    console.error('更新元素失败:', e);
                } finally {
                    // 清除动画状态标记
                    delete animationInProgress[elementId];
                }
            }, 450);
        } catch (e) {
            console.error('创建动画失败:', e);
            // 出错时直接设置值
            element.innerHTML = formattedNewValue;
            if (originalStyle) {
                element.setAttribute('style', originalStyle);
            } else {
                element.removeAttribute('style');
            }
            // 清除动画状态标记
            delete animationInProgress[elementId];
        }
    }
    
    // 更新百分比元素的函数
    function updatePercentage(elementId, value) {
        const element = document.getElementById(elementId);
        if (!element) return;
        
        // 检查是否有正在进行的动画
        if (animationInProgress[elementId + '_percent']) {
            clearTimeout(animationInProgress[elementId + '_percent']);
        }
        
        try {
            element.style.opacity = '0';
            element.style.transition = 'opacity 200ms ease-out';
            
            // 保存定时器ID，便于后续可能的取消
            animationInProgress[elementId + '_percent'] = setTimeout(() => {
                try {
                    element.textContent = value;
                    element.style.opacity = '1';
                } catch (e) {
                    console.error('更新百分比元素失败:', e);
                } finally {
                    // 清除动画状态标记
                    delete animationInProgress[elementId + '_percent'];
                }
            }, 200);
        } catch (e) {
            console.error('设置百分比动画失败:', e);
            // 出错时直接设置值
            try {
                element.textContent = value;
                element.style.opacity = '1';
            } catch (e2) {
                console.error('直接更新百分比元素也失败:', e2);
            }
        }
    }
    
    // 平滑更新数量显示
    animateValue('total-queries', totalQueries);
    animateValue('blocked-queries', blockedQueries);
    animateValue('allowed-queries', allowedQueries);
    animateValue('error-queries', errorQueries);
    animateValue('active-ips', activeIPs);
    
    // DNSSEC相关数据
    // 优先从DOM中获取当前显示的值，作为默认值
    const dnssecSuccessElem = document.getElementById('dnssec-success');
    const dnssecFailedElem = document.getElementById('dnssec-failed');
    const dnssecQueriesElem = document.getElementById('dnssec-queries');
    
    // 从当前显示值初始化，确保数据刷新前保留前一次结果
    let dnssecEnabled = false;
    let dnssecQueries = getCurrentValue(dnssecQueriesElem);
    let dnssecSuccess = getCurrentValue(dnssecSuccessElem);
    let dnssecFailed = getCurrentValue(dnssecFailedElem);
    let dnssecUsage = 0;
    
    // 检查DNSSEC数据
    if (stats) {
        // 优先使用顶层字段，只有当值存在时才更新
        if (stats.dnssecEnabled !== undefined) dnssecEnabled = stats.dnssecEnabled;
        if (stats.dnssecQueries !== undefined) dnssecQueries = stats.dnssecQueries;
        if (stats.dnssecSuccess !== undefined) dnssecSuccess = stats.dnssecSuccess;
        if (stats.dnssecFailed !== undefined) dnssecFailed = stats.dnssecFailed;
        if (stats.dnssecUsage !== undefined) dnssecUsage = stats.dnssecUsage;
        
        // 如果dns对象存在，优先使用其中的数据
        if (stats.dns) {
            if (stats.dns.DNSSECEnabled !== undefined) dnssecEnabled = stats.dns.DNSSECEnabled;
            if (stats.dns.DNSSECQueries !== undefined) dnssecQueries = stats.dns.DNSSECQueries;
            if (stats.dns.DNSSECSuccess !== undefined) dnssecSuccess = stats.dns.DNSSECSuccess;
            if (stats.dns.DNSSECFailed !== undefined) dnssecFailed = stats.dns.DNSSECFailed;
        }
        
        // 如果没有直接提供使用率，计算使用率
        if (dnssecUsage === 0 && totalQueries > 0) {
            dnssecUsage = (dnssecQueries / totalQueries) * 100;
        }
    }
    
    // 更新DNSSEC统计卡片
    const dnssecUsageElement = document.getElementById('dnssec-usage');
    const dnssecStatusElement = document.getElementById('dnssec-status');
    const dnssecSuccessElement = document.getElementById('dnssec-success');
    const dnssecFailedElement = document.getElementById('dnssec-failed');
    const dnssecQueriesElement = document.getElementById('dnssec-queries');
    
    if (dnssecUsageElement) {
        dnssecUsageElement.textContent = `${Math.round(dnssecUsage)}%`;
    }
    
    if (dnssecStatusElement) {
        dnssecStatusElement.textContent = dnssecEnabled ? '已启用' : '已禁用';
        dnssecStatusElement.className = `text-sm flex items-center ${dnssecEnabled ? 'text-success' : 'text-danger'}`;
    }
    
    if (dnssecSuccessElement) {
        dnssecSuccessElement.textContent = formatNumber(dnssecSuccess);
    }
    
    if (dnssecFailedElement) {
        dnssecFailedElement.textContent = formatNumber(dnssecFailed);
    }
    
    if (dnssecQueriesElement) {
        dnssecQueriesElement.textContent = formatNumber(dnssecQueries);
    }
    
    // 直接更新文本和百分比，移除动画效果
    const topQueryTypeElement = document.getElementById('top-query-type');
    const queryTypePercentageElement = document.getElementById('query-type-percentage');
    const activeIpsPercentElement = document.getElementById('active-ips-percent');
    
    if (topQueryTypeElement) topQueryTypeElement.textContent = topQueryType;
    if (queryTypePercentageElement) queryTypePercentageElement.textContent = `${Math.round(queryTypePercentage)}%`;
    if (activeIpsPercentElement) activeIpsPercentElement.textContent = `${Math.round(activeIPsPercentage)}%`;
    
    // 计算并平滑更新百分比，同时更新箭头颜色和方向
    function updatePercentWithArrow(elementId, percentage, prevValue, currentValue) {
        const element = document.getElementById(elementId);
        if (!element) return;
        
        // 更新百分比数值
        updatePercentage(elementId, percentage);
        
        // 查找父元素，获取箭头图标
        const parent = element.parentElement;
        if (!parent) return;
        
        let arrowIcon = parent.querySelector('.fa-arrow-up, .fa-arrow-down, .fa-circle');
        if (!arrowIcon) return;
        
        // 计算变化趋势
        let isIncrease = currentValue > prevValue;
        let isDecrease = currentValue < prevValue;
        let isNoChange = currentValue === prevValue;
        
        // 处理百分比显示，避免-0.0%的情况
        let formattedPercentage = percentage;
        if (percentage === '-0.0%') {
            formattedPercentage = '0.0%';
            updatePercentage(elementId, formattedPercentage);
        }
        
        // 更新箭头图标和颜色
        if (isIncrease) {
            arrowIcon.className = 'fa fa-arrow-up mr-1';
            parent.className = 'text-success text-sm flex items-center';
        } else if (isDecrease) {
            arrowIcon.className = 'fa fa-arrow-down mr-1';
            parent.className = 'text-danger text-sm flex items-center';
        } else if (isNoChange) {
            // 趋势为0时，显示圆点图标
            arrowIcon.className = 'fa fa-circle mr-1 text-xs';
            parent.className = 'text-gray-500 text-sm flex items-center';
        }
    }
    
    // 保存历史数据，用于计算趋势
    window.dashboardHistoryData = window.dashboardHistoryData || {
        totalQueries: 0,
        blockedQueries: 0,
        allowedQueries: 0,
        errorQueries: 0
    };
    
    // 计算百分比并更新箭头
    if (totalQueries > 0) {
        const queriesPercent = '100%';
        const blockedPercent = `${Math.round((blockedQueries / totalQueries) * 100)}%`;
        const allowedPercent = `${Math.round((allowedQueries / totalQueries) * 100)}%`;
        const errorPercent = `${Math.round((errorQueries / totalQueries) * 100)}%`;
        
        updatePercentWithArrow('queries-percent', queriesPercent, window.dashboardHistoryData.totalQueries, totalQueries);
        updatePercentWithArrow('blocked-percent', blockedPercent, window.dashboardHistoryData.blockedQueries, blockedQueries);
        updatePercentWithArrow('allowed-percent', allowedPercent, window.dashboardHistoryData.allowedQueries, allowedQueries);
        updatePercentWithArrow('error-percent', errorPercent, window.dashboardHistoryData.errorQueries, errorQueries);
    } else {
        updatePercentage('queries-percent', '---');
        updatePercentage('blocked-percent', '---');
        updatePercentage('allowed-percent', '---');
        updatePercentage('error-percent', '---');
    }
    
    // 更新历史数据
    window.dashboardHistoryData.totalQueries = totalQueries;
    window.dashboardHistoryData.blockedQueries = blockedQueries;
    window.dashboardHistoryData.allowedQueries = allowedQueries;
    window.dashboardHistoryData.errorQueries = errorQueries;
    

}

// 更新Top屏蔽域名表格
async function updateTopBlockedTable(domains) {
    console.log('更新Top屏蔽域名表格，收到数据:', domains);
    const tableBody = document.getElementById('top-blocked-table');
    
    let tableData = [];
    
    // 适配不同的数据结构
    if (Array.isArray(domains)) {
        tableData = domains.map(item => ({
            name: item.name || item.domain || item[0] || '未知',
            count: item.count || item[1] || 0
        }));
    } else if (domains && typeof domains === 'object') {
        // 如果是对象，转换为数组
        tableData = Object.entries(domains).map(([domain, count]) => ({
            name: domain,
            count: count || 0
        }));
    }
    
    // 如果没有有效数据，提供示例数据
    if (tableData.length === 0) {
        tableData = [
            { name: '---.---.---', count: '---' },
            { name: '---.---.---', count: '---' },
            { name: '---.---.---', count: '---' }
        ];
        console.log('使用示例数据填充Top屏蔽域名表格');
    }
    
    // 计算总拦截次数
    const totalCount = tableData.reduce((sum, domain) => {
        return sum + (typeof domain.count === 'number' ? domain.count : 0);
    }, 0);
    
    let html = '';
    for (let i = 0; i < tableData.length; i++) {
        const domain = tableData[i];
        // 检查域名是否是跟踪器
        const trackerInfo = await isDomainInTrackerDatabase(domain.name);
        const isTracker = trackerInfo !== null;
        
        // 构建跟踪器浮窗内容
        const trackerTooltip = isTracker ? `
            <div class="tracker-tooltip absolute z-50 bg-white shadow-lg rounded-md border p-3 min-w-64 text-sm">
                <div class="font-semibold mb-1">已知跟踪器</div>
                <div class="mb-1">名称: ${trackerInfo.name}</div>
                <div class="mb-1">类别: ${trackersDatabase.categories[trackerInfo.categoryId] || '未知'}</div>
                ${trackerInfo.url ? `<div class="mb-1">URL: <a href="${trackerInfo.url}" target="_blank" class="text-blue-500 hover:underline">${trackerInfo.url}</a></div>` : ''}
                ${trackerInfo.source ? `<div class="mb-1">源: ${trackerInfo.source}</div>` : ''}
            </div>
        ` : '';
        
        // 计算百分比
        const percentage = totalCount > 0 && typeof domain.count === 'number' 
            ? ((domain.count / totalCount) * 100).toFixed(2) 
            : '0.00';
        
        html += `
            <div class="p-3 rounded-md hover:bg-gray-50 transition-colors border-l-4 border-danger">
                <div class="flex items-center justify-between mb-2">
                    <div class="flex-1 min-w-0">
                        <div class="flex items-center">
                            <span class="w-6 h-6 flex items-center justify-center rounded-full bg-danger/10 text-danger text-xs font-medium mr-3">${i + 1}</span>
                            <div class="flex items-center">
                                <span class="font-medium truncate">${domain.name}</span>
                                ${isTracker ? `
                                    <div class="tracker-icon-container relative ml-2">
                                        <i class="fa fa-eye text-red-500" title="已知跟踪器"></i>
                                        ${trackerTooltip}
                                    </div>
                                ` : ''}
                            </div>
                        </div>
                    </div>
                    <div class="ml-4 flex items-center space-x-2">
                        <span class="flex-shrink-0 font-semibold text-danger">${formatNumber(domain.count)}</span>
                        <span class="text-xs text-gray-500">${percentage}%</span>
                    </div>
                </div>
                <div class="w-full bg-gray-200 rounded-full h-2.5">
                    <div class="bg-danger h-2.5 rounded-full" style="width: ${percentage}%"></div>
                </div>
            </div>
        `;
    }
    
    tableBody.innerHTML = html;
    
    // 添加跟踪器图标悬停事件
    const trackerIconContainers = tableBody.querySelectorAll('.tracker-icon-container');
    trackerIconContainers.forEach(container => {
        const tooltip = container.querySelector('.tracker-tooltip');
        if (tooltip) {
            tooltip.style.display = 'none';
            
            container.addEventListener('mouseenter', () => {
                tooltip.style.display = 'block';
            });
            
            container.addEventListener('mouseleave', () => {
                tooltip.style.display = 'none';
            });
        }
    });
}

// 更新最近屏蔽域名表格
function updateRecentBlockedTable(domains) {
    console.log('更新最近屏蔽域名表格，收到数据:', domains);
    const tableBody = document.getElementById('recent-blocked-table');
    
    // 确保tableBody存在，因为最近屏蔽域名卡片可能已被移除
    if (!tableBody) {
        console.log('未找到recent-blocked-table元素，跳过更新');
        return;
    }
    
    let tableData = [];
    
    // 适配不同的数据结构
    if (Array.isArray(domains)) {
        tableData = domains.map(item => ({
            name: item.name || item.domain || item[0] || '未知',
            timestamp: item.timestamp || item.time || Date.now(),
            type: item.type || '广告'
        }));
    }
    
    // 如果没有有效数据，提供示例数据
    if (tableData.length === 0) {
        const now = Date.now();
        tableData = [
            { name: '---.---.---', timestamp: now - 5 * 60 * 1000, type: '广告' },
            { name: '---.---.---', timestamp: now - 15 * 60 * 1000, type: '恶意' },
            { name: '---.---.---', timestamp: now - 30 * 60 * 1000, type: '广告' },
            { name: '---.---.---', timestamp: now - 45 * 60 * 1000, type: '追踪' },
            { name: '---.---.---', timestamp: now - 60 * 60 * 1000, type: '恶意' }
        ];
        console.log('使用示例数据填充最近屏蔽域名表格');
    }
    
    let html = '';
    for (let i = 0; i < tableData.length; i++) {
        const domain = tableData[i];
        const time = formatTime(domain.timestamp);
        html += `
            <div class="flex items-center justify-between p-3 rounded-md hover:bg-gray-50 transition-colors border-l-4 border-warning">
                <div class="flex-1 min-w-0">
                    <div class="font-medium truncate">${domain.name}</div>
                    <div class="text-sm text-gray-500 mt-1">${time}</div>
                </div>
                <span class="ml-4 flex-shrink-0 text-sm text-gray-500">${domain.type}</span>
            </div>
        `;
    }
    
    tableBody.innerHTML = html;
}

// IP地理位置缓存（检查是否已经存在，避免重复声明）
if (typeof ipGeolocationCache === 'undefined') {
    var ipGeolocationCache = {};
    var GEOLOCATION_CACHE_EXPIRY = 24 * 60 * 60 * 1000; // 缓存有效期24小时
}

// 跟踪器数据库缓存（检查是否已经存在，避免重复声明）
if (typeof trackersDatabase === 'undefined') {
    var trackersDatabase = null;
    var trackersLoaded = false;
    var trackersLoading = false;
}

// 加载跟踪器数据库
async function loadTrackersDatabase() {
    if (trackersLoaded) return trackersDatabase;
    if (trackersLoading) {
        // 等待正在进行的加载完成
        while (trackersLoading) {
            await new Promise(resolve => setTimeout(resolve, 100));
        }
        return trackersDatabase;
    }
    
    trackersLoading = true;
    
    try {
        const response = await fetch('domain-info/tracker/trackers.json');
        if (!response.ok) {
            console.error('加载跟踪器数据库失败:', response.statusText);
            trackersDatabase = { trackers: {} };
            return trackersDatabase;
        }
        
        trackersDatabase = await response.json();
        trackersLoaded = true;
        return trackersDatabase;
    } catch (error) {
        console.error('加载跟踪器数据库失败:', error);
        trackersDatabase = { trackers: {} };
        return trackersDatabase;
    } finally {
        trackersLoading = false;
    }
}

// 检查域名是否在跟踪器数据库中
async function isDomainInTrackerDatabase(domain) {
    if (!trackersDatabase || !trackersLoaded) {
        await loadTrackersDatabase();
    }
    
    if (!trackersDatabase || !trackersDatabase.trackers) {
        return null;
    }
    
    // 检查域名是否直接作为跟踪器键存在
    if (trackersDatabase.trackers.hasOwnProperty(domain)) {
        return trackersDatabase.trackers[domain];
    }
    
    // 检查域名是否在跟踪器URL中
    for (const trackerKey in trackersDatabase.trackers) {
        if (trackersDatabase.trackers.hasOwnProperty(trackerKey)) {
            const tracker = trackersDatabase.trackers[trackerKey];
            if (tracker && tracker.url) {
                try {
                    const trackerUrl = new URL(tracker.url);
                    if (trackerUrl.hostname === domain) {
                        return tracker;
                    }
                } catch (e) {
                    // 忽略无效URL
                }
            }
        }
    }
    
    return null;
}

// 获取IP地理位置信息
async function getIpGeolocation(ip) {
    // 检查是否为内网IP
    if (isPrivateIP(ip)) {
        return "内网 内网";
    }
    
    // 检查缓存
    const now = Date.now();
    if (ipGeolocationCache[ip] && (now - ipGeolocationCache[ip].timestamp) < GEOLOCATION_CACHE_EXPIRY) {
        return ipGeolocationCache[ip].location;
    }
    
    try {
        // 使用whois.pconline.com.cn API获取IP地理位置
        const url = `https://whois.pconline.com.cn/ipJson.jsp?ip=${ip}&json=true`;
        const response = await fetch(url, {
            headers: {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
            }
        });
        
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        
        // 解析响应数据
        const data = await response.json();
        let location = "未知 未知";
        
        if (data && data.addr) {
            // 直接使用addr字段作为完整的地理位置信息
            location = data.addr;
        }
        
        // 保存到缓存
        ipGeolocationCache[ip] = {
            location: location,
            timestamp: now
        };
        
        return location;
    } catch (error) {
        console.error('获取IP地理位置失败:', error);
        return "未知 未知";
    }
}

// 检查是否为内网IP
function isPrivateIP(ip) {
    const parts = ip.split('.');
    
    // 检查IPv4内网地址
    if (parts.length === 4) {
        const first = parseInt(parts[0]);
        const second = parseInt(parts[1]);
        
        // 10.0.0.0/8
        if (first === 10) {
            return true;
        }
        // 172.16.0.0/12
        if (first === 172 && second >= 16 && second <= 31) {
            return true;
        }
        // 192.168.0.0/16
        if (first === 192 && second === 168) {
            return true;
        }
        // 127.0.0.0/8 (localhost)
        if (first === 127) {
            return true;
        }
        // 169.254.0.0/16 (link-local)
        if (first === 169 && second === 254) {
            return true;
        }
    }
    
    // 检查IPv6内网地址
    if (ip.includes(':')) {
        // ::1/128 (localhost)
        if (ip === '::1' || ip.startsWith('0:0:0:0:0:0:0:1')) {
            return true;
        }
        // fc00::/7 (unique local address)
        if (ip.startsWith('fc') || ip.startsWith('fd')) {
            return true;
        }
        // fe80::/10 (link-local)
        if (ip.startsWith('fe80:')) {
            return true;
        }
    }
    
    return false;
}

// 更新TOP客户端表格
async function updateTopClientsTable(clients) {
    console.log('更新TOP客户端表格，收到数据:', clients);
    const tableBody = document.getElementById('top-clients-table');
    
    // 确保tableBody存在
    if (!tableBody) {
        console.error('未找到top-clients-table元素');
        return;
    }
    
    // 隐藏加载中状态
    const loadingElement = document.getElementById('top-clients-loading');
    if (loadingElement) {
        loadingElement.classList.add('hidden');
    }
    
    // 显示数据区域
    tableBody.classList.remove('hidden');
    
    let tableData = [];
    
    // 适配不同的数据结构
    if (Array.isArray(clients)) {
        tableData = clients.map(item => ({
            ip: item.ip || item[0] || '未知',
            count: item.count || item[1] || 0
        }));
    } else if (clients && typeof clients === 'object') {
        // 如果是对象，转换为数组
        tableData = Object.entries(clients).map(([ip, count]) => ({
            ip,
            count: count || 0
        }));
    }
    
    // 如果没有有效数据，提供示例数据
    if (tableData.length === 0) {
        tableData = [
            { ip: '---.---.---', count: '---' },
            { ip: '---.---.---', count: '---' },
            { ip: '---.---.---', count: '---' },
            { ip: '---.---.---', count: '---' },
            { ip: '---.---.---', count: '---' }
        ];
        console.log('使用示例数据填充TOP客户端表格');
    }
    

    
    let html = '';
    for (let i = 0; i < tableData.length; i++) {
        const client = tableData[i];
        // 获取IP地理信息
        const location = await getIpGeolocation(client.ip);
        html += `
            <div class="flex items-center justify-between p-3 rounded-md hover:bg-gray-50 transition-colors border-l-4 border-primary">
                <div class="flex-1 min-w-0">
                    <div class="flex items-center">
                        <span class="w-6 h-6 flex items-center justify-center rounded-full bg-primary/10 text-primary text-xs font-medium mr-3">${i + 1}</span>
                        <div class="flex flex-col">
                    <span class="font-medium truncate">${client.ip}</span>
                    <span class="text-xs text-gray-500">${location}</span>
                </div>
                    </div>
                </div>
                <span class="ml-4 flex-shrink-0 font-semibold text-primary">${formatNumber(client.count)}</span>
            </div>
        `;
    }
    
    tableBody.innerHTML = html;
}

// 更新请求域名排行表格
async function updateTopDomainsTable(domains) {
    console.log('更新请求域名排行表格，收到数据:', domains);
    const tableBody = document.getElementById('top-domains-table');
    
    // 确保tableBody存在
    if (!tableBody) {
        console.error('未找到top-domains-table元素');
        return;
    }
    
    let tableData = [];
    
    // 适配不同的数据结构
    if (Array.isArray(domains)) {
        tableData = domains.map(item => ({
            name: item.domain || item.name || item[0] || '未知',
            count: item.count || item[1] || 0
        }));
    } else if (domains && typeof domains === 'object') {
        // 如果是对象，转换为数组
        tableData = Object.entries(domains).map(([domain, count]) => ({
            name: domain,
            count: count || 0
        }));
    }
    
    // 如果没有有效数据，提供示例数据
    if (tableData.length === 0) {
        tableData = [
            { name: 'example.com', count: 50 },
            { name: 'google.com', count: 45 },
            { name: 'facebook.com', count: 40 },
            { name: 'twitter.com', count: 35 },
            { name: 'youtube.com', count: 30 }
        ];
        console.log('使用示例数据填充请求域名排行表格');
    }
    
    // 计算总请求次数
    const totalCount = tableData.reduce((sum, domain) => {
        return sum + (typeof domain.count === 'number' ? domain.count : 0);
    }, 0);
    
    let html = '';
    for (let i = 0; i < tableData.length; i++) {
        const domain = tableData[i];
        // 检查域名是否是跟踪器
        const trackerInfo = await isDomainInTrackerDatabase(domain.name);
        const isTracker = trackerInfo !== null;
        
        // 构建跟踪器浮窗内容
        const trackerTooltip = isTracker ? `
            <div class="tracker-tooltip absolute z-50 bg-white shadow-lg rounded-md border p-3 min-w-64 text-sm">
                <div class="font-semibold mb-1">已知跟踪器</div>
                <div class="mb-1">名称: ${trackerInfo.name}</div>
                <div class="mb-1">类别: ${trackersDatabase.categories[trackerInfo.categoryId] || '未知'}</div>
                ${trackerInfo.url ? `<div class="mb-1">URL: <a href="${trackerInfo.url}" target="_blank" class="text-blue-500 hover:underline">${trackerInfo.url}</a></div>` : ''}
                ${trackerInfo.source ? `<div class="mb-1">源: ${trackerInfo.source}</div>` : ''}
            </div>
        ` : '';
        
        // 计算百分比
        const percentage = totalCount > 0 && typeof domain.count === 'number' 
            ? ((domain.count / totalCount) * 100).toFixed(2) 
            : '0.00';
        
        html += `
            <div class="p-3 rounded-md hover:bg-gray-50 transition-colors border-l-4 border-success">
                <div class="flex items-center justify-between mb-2">
                    <div class="flex-1 min-w-0">
                        <div class="flex items-center">
                            <span class="w-6 h-6 flex items-center justify-center rounded-full bg-success/10 text-success text-xs font-medium mr-3">${i + 1}</span>
                            <div class="flex items-center">
                                <span class="font-medium truncate">${domain.name}${domain.dnssec ? ' <i class="fa fa-lock text-green-500"></i>' : ''}</span>
                                ${isTracker ? `
                                    <div class="tracker-icon-container relative ml-2">
                                        <i class="fa fa-eye text-red-500" title="已知跟踪器"></i>
                                        ${trackerTooltip}
                                    </div>
                                ` : ''}
                            </div>
                        </div>
                    </div>
                    <div class="ml-4 flex items-center space-x-2">
                        <span class="flex-shrink-0 font-semibold text-success">${formatNumber(domain.count)}</span>
                        <span class="text-xs text-gray-500">${percentage}%</span>
                    </div>
                </div>
                <div class="w-full bg-gray-200 rounded-full h-2.5">
                    <div class="bg-success h-2.5 rounded-full" style="width: ${percentage}%"></div>
                </div>
            </div>
        `;
    }
    
    tableBody.innerHTML = html;
    
    // 添加跟踪器图标悬停事件
    const trackerIconContainers = tableBody.querySelectorAll('.tracker-icon-container');
    trackerIconContainers.forEach(container => {
        const tooltip = container.querySelector('.tracker-tooltip');
        if (tooltip) {
            tooltip.style.display = 'none';
            
            container.addEventListener('mouseenter', () => {
                tooltip.style.display = 'block';
            });
            
            container.addEventListener('mouseleave', () => {
                tooltip.style.display = 'none';
            });
        }
    });
}

// 当前选中的时间范围
let currentTimeRange = '30d'; // 默认为30天
let isMixedView = true; // 是否为混合视图 - 默认显示混合视图
let lastSelectedIndex = 2; // 最后选中的按钮索引，30天是第三个按钮

// 详细图表专用变量
let detailedCurrentTimeRange = '30d'; // 详细图表当前时间范围
let detailedIsMixedView = false; // 详细图表是否为混合视图

// 初始化时间范围切换
function initTimeRangeToggle() {
    console.log('初始化时间范围切换');
    // 查找所有可能的时间范围按钮类名
    const timeRangeButtons = document.querySelectorAll('.time-range-btn, .time-range-button, .timerange-btn, button[data-range]');
    console.log('找到时间范围按钮数量:', timeRangeButtons.length);
    
    if (timeRangeButtons.length === 0) {
        console.warn('未找到时间范围按钮，请检查HTML中的类名');
        return;
    }
    
    // 定义三个按钮的不同样式配置，增加activeHover属性
    const buttonStyles = [
        { // 24小时按钮
            normal: ['bg-gray-100', 'text-gray-700'],
            hover: ['hover:bg-blue-100'],
            active: ['bg-blue-500', 'text-white'],
            activeHover: ['hover:bg-blue-400'] // 选中时的浅色悬停
        },
        { // 7天按钮
            normal: ['bg-gray-100', 'text-gray-700'],
            hover: ['hover:bg-green-100'],
            active: ['bg-green-500', 'text-white'],
            activeHover: ['hover:bg-green-400'] // 选中时的浅色悬停
        },
        { // 30天按钮
            normal: ['bg-gray-100', 'text-gray-700'],
            hover: ['hover:bg-purple-100'],
            active: ['bg-purple-500', 'text-white'],
            activeHover: ['hover:bg-purple-400'] // 选中时的浅色悬停
        },
        { // 混合视图按钮
            normal: ['bg-gray-100', 'text-gray-700'],
            hover: ['hover:bg-gray-200'],
            active: ['bg-gray-500', 'text-white'],
            activeHover: ['hover:bg-gray-400'] // 选中时的浅色悬停
        }
    ];
    
    // 为所有按钮设置初始样式和事件
    timeRangeButtons.forEach((button, index) => {
        // 使用相应的样式配置
        const styleConfig = buttonStyles[index % buttonStyles.length];
        
        // 移除所有按钮的初始样式
        button.classList.remove('active', 'bg-blue-500', 'text-white', 'bg-gray-200', 'text-gray-700', 
                              'bg-green-500', 'bg-purple-500', 'bg-gray-100');
        
        // 设置非选中状态样式
        button.classList.add('transition-colors', 'duration-200');
        button.classList.add(...styleConfig.normal);
        button.classList.add(...styleConfig.hover);
        
        // 移除鼠标悬停提示
        
        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);
            
            // 检查是否是再次点击已选中的按钮
            const isActive = button.classList.contains('active');
            
            // 重置所有按钮为非选中状态
            timeRangeButtons.forEach((btn, btnIndex) => {
                const btnStyle = buttonStyles[btnIndex % buttonStyles.length];
                
                // 移除所有可能的激活状态类
                btn.classList.remove('active', 'bg-blue-500', 'text-white', 'bg-green-500', 'bg-purple-500', 'bg-gray-500');
                btn.classList.remove(...btnStyle.active);
                btn.classList.remove(...btnStyle.activeHover);
                
                // 添加非选中状态类
                btn.classList.add(...btnStyle.normal);
                btn.classList.add(...btnStyle.hover);
            });
            
            if (isActive && index < 3) { // 再次点击已选中的时间范围按钮
                // 切换到混合视图
                isMixedView = true;
                currentTimeRange = 'mixed';
                console.log('切换到混合视图');
                
                // 设置当前按钮为特殊混合视图状态（保持原按钮选中但添加混合视图标记）
                button.classList.remove(...styleConfig.normal);
                button.classList.remove(...styleConfig.hover);
                button.classList.add('active', 'mixed-view-active');
                button.classList.add(...styleConfig.active);
                button.classList.add(...styleConfig.activeHover); // 添加选中时的浅色悬停
            } else {
                // 普通选中模式
                isMixedView = false;
                lastSelectedIndex = index;
                
                // 设置当前按钮为激活状态
                button.classList.remove(...styleConfig.normal);
                button.classList.remove(...styleConfig.hover);
                button.classList.add('active');
                button.classList.add(...styleConfig.active);
                button.classList.add(...styleConfig.activeHover); // 添加选中时的浅色悬停
                
                // 获取并更新当前时间范围
                let rangeValue;
                if (button.dataset.range) {
                    rangeValue = button.dataset.range;
                } else {
                    const btnText = button.textContent.trim();
                    if (btnText.includes('24')) {
                        rangeValue = '24h';
                    } else if (btnText.includes('7')) {
                        rangeValue = '7d';
                    } else if (btnText.includes('30')) {
                        rangeValue = '30d';
                    } else {
                        rangeValue = btnText.replace(/[^0-9a-zA-Z]/g, '');
                    }
                }
                currentTimeRange = rangeValue;
                console.log('更新时间范围为:', currentTimeRange);
            }
            
            // 重新加载数据
            loadDashboardData();
            // 更新DNS请求图表
            drawDNSRequestsChart();
        });
        
        // 移除自定义鼠标悬停提示效果
    });
    
    // 确保默认选中30天按钮并显示混合内容
    if (timeRangeButtons.length > 0) {
        // 选择30天按钮（索引为2），如果不存在则使用第一个按钮
        const defaultButtonIndex = 2;
        const defaultButton = timeRangeButtons[defaultButtonIndex] || timeRangeButtons[0];
        const defaultStyle = buttonStyles[defaultButtonIndex % buttonStyles.length] || buttonStyles[0];
        
        // 先重置所有按钮
        timeRangeButtons.forEach((btn, index) => {
            const btnStyle = buttonStyles[index % buttonStyles.length];
            btn.classList.remove('active', 'bg-blue-500', 'text-white', 'bg-green-500', 'bg-purple-500', 'bg-gray-500', 'mixed-view-active');
            btn.classList.remove(...btnStyle.active);
            btn.classList.remove(...btnStyle.activeHover);
            btn.classList.add(...btnStyle.normal);
            btn.classList.add(...btnStyle.hover);
        });
        
        // 然后设置30天按钮为激活状态，并标记为混合视图
        defaultButton.classList.remove(...defaultStyle.normal);
        defaultButton.classList.remove(...defaultStyle.hover);
        defaultButton.classList.add('active', 'mixed-view-active');
        defaultButton.classList.add(...defaultStyle.active);
        defaultButton.classList.add(...defaultStyle.activeHover);
        console.log('默认选中30天按钮并显示混合内容:', defaultButton.textContent.trim());
        
        // 设置默认显示混合内容
        isMixedView = true;
        currentTimeRange = 'mixed';
    }
}

// 注意：这个函数已被后面的实现覆盖，请使用后面的drawDetailedDNSRequestsChart函数

// 初始化图表
function initCharts() {
    // 初始化比例图表
    const ratioChartElement = document.getElementById('ratio-chart');
    if (!ratioChartElement) {
        console.error('未找到比例图表元素');
        return;
    }
    const ratioCtx = ratioChartElement.getContext('2d');
    ratioChart = new Chart(ratioCtx, {
        type: 'doughnut',
        data: {
            labels: ['正常解析', '被屏蔽', '错误'],
            datasets: [{
                data: ['---', '---', '---'],
                backgroundColor: ['#00B42A', '#F53F3F', '#FF7D00'],
                borderWidth: 2, // 添加边框宽度，增强区块分隔
                borderColor: '#fff', // 白色边框，使各个扇区更清晰
                hoverOffset: 10, // 添加悬停偏移效果，增强交互体验
                hoverBorderWidth: 3 // 悬停时增加边框宽度
            }]
        },
        options: {
            responsive: true,
            maintainAspectRatio: false,
            // 添加全局动画配置，确保图表创建和更新时都平滑过渡
            animation: {
                duration: 500, // 延长动画时间，使过渡更平滑
                easing: 'easeInOutQuart'
            },
            plugins: {
                legend: {
                    position: 'bottom',
                    labels: {
                        boxWidth: 12, // 减小图例框的宽度
                        font: {
                            size: 11 // 减小字体大小
                        },
                        padding: 10 // 减小内边距
                    }
                },
                tooltip: {
                    enabled: true,
                    backgroundColor: 'rgba(0, 0, 0, 0.8)',
                    padding: 10,
                    titleFont: {
                        size: 12
                    },
                    bodyFont: {
                        size: 11
                    },
                    callbacks: {
                        label: function(context) {
                            const label = context.label || '';
                            const value = context.raw || 0;
                            const total = context.dataset.data.reduce((acc, val) => acc + (typeof val === 'number' ? val : 0), 0);
                            const percentage = total > 0 ? Math.round((value / total) * 100) : 0;
                            return `${label}: ${value} (${percentage}%)`;
                        }
                    }
                }
            },
            cutout: '65%', // 减小中心空白区域比例，增大扇形区域以更好显示线段指示
            // 添加线段指示相关配置
            elements: {
                arc: {
                    // 确保圆弧绘制时有足够的精度
                    borderAlign: 'center',
                    tension: 0.1 // 添加轻微的张力，使圆弧更平滑
                }
            }
        }
    });
    
    // 初始化解析类型统计饼图
    const queryTypeChartElement = document.getElementById('query-type-chart');
    if (queryTypeChartElement) {
        const queryTypeCtx = queryTypeChartElement.getContext('2d');
        // 预定义的颜色数组，用于解析类型
        const queryTypeColors = ['#3498db', '#e74c3c', '#2ecc71', '#f39c12', '#9b59b6', '#1abc9c', '#d35400', '#34495e'];
        
        queryTypeChart = new Chart(queryTypeCtx, {
            type: 'doughnut',
            data: {
                labels: ['暂无数据'],
                datasets: [{
                    data: [1],
                    backgroundColor: [queryTypeColors[0]],
                    borderWidth: 2, // 添加边框宽度，增强区块分隔
                    borderColor: '#fff', // 白色边框，使各个扇区更清晰
                    hoverOffset: 10, // 添加悬停偏移效果，增强交互体验
                    hoverBorderWidth: 3 // 悬停时增加边框宽度
                }]
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                // 添加全局动画配置，确保图表创建和更新时都平滑过渡
                animation: {
                    duration: 300,
                    easing: 'easeInOutQuart'
                },
                plugins: {
                    legend: {
                        position: 'bottom',
                        labels: {
                            boxWidth: 12, // 减小图例框的宽度
                            font: {
                                size: 11 // 减小字体大小
                            },
                            padding: 10 // 减小内边距
                        }
                    },
                    tooltip: {
                        enabled: true,
                        backgroundColor: 'rgba(0, 0, 0, 0.8)',
                        padding: 10,
                        titleFont: {
                            size: 12
                        },
                        bodyFont: {
                            size: 11
                        },
                        callbacks: {
                            label: function(context) {
                                const label = context.label || '';
                                const value = context.raw || 0;
                                const total = context.dataset.data.reduce((acc, val) => acc + (typeof val === 'number' ? val : 0), 0);
                                const percentage = total > 0 ? Math.round((value / total) * 100) : 0;
                                return `${label}: ${value} (${percentage}%)`;
                            }
                        }
                    }
                },
                cutout: '65%', // 减小中心空白区域比例，增大扇形区域以更好显示线段指示
                // 添加线段指示相关配置
                elements: {
                    arc: {
                        // 确保圆弧绘制时有足够的精度
                        borderAlign: 'center',
                        tension: 0.1 // 添加轻微的张力，使圆弧更平滑
                    }
                }
            }
        });
    } else {
        console.warn('未找到解析类型统计图表元素');
    }
    
    // 初始化DNS请求统计图表
    drawDNSRequestsChart();
    
    // 初始化展开按钮功能
    initExpandButton();
}

// 初始化展开按钮事件
function initExpandButton() {
    const expandBtn = document.getElementById('expand-chart-btn');
    const chartModal = document.getElementById('chart-modal');
    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');
            
            // 初始化或更新详细图表
            drawDetailedDNSRequestsChart();
            
            // 初始化浮窗中的时间范围切换
            initDetailedTimeRangeToggle();
            
            // 延迟更新图表大小，确保容器大小已计算
            setTimeout(() => {
                if (detailedDnsRequestsChart) {
                    detailedDnsRequestsChart.resize();
                }
            }, 100);
        });
        
        // 关闭按钮点击事件
        closeModalBtn.addEventListener('click', () => {
            console.log('关闭按钮被点击');
            chartModal.classList.add('hidden');
        });
        
        // 点击遮罩层关闭浮窗（使用chartModal作为遮罩层）
        chartModal.addEventListener('click', (e) => {
            // 检查点击目标是否是遮罩层本身（即最外层div）
            if (e.target === chartModal) {
                console.log('点击遮罩层关闭');
                chartModal.classList.add('hidden');
            }
        });
        
        // ESC键关闭浮窗
        document.addEventListener('keydown', (e) => {
            if (e.key === 'Escape' && !chartModal.classList.contains('hidden')) {
                console.log('ESC键关闭浮窗');
                chartModal.classList.add('hidden');
            }
        });
    } else {
        console.error('无法找到必要的DOM元素');
    }
}

// 初始化详细图表的时间范围切换
function initDetailedTimeRangeToggle() {
    // 只选择图表模态框内的时间范围按钮，避免与主视图冲突
    const chartModal = document.getElementById('chart-modal');
    const detailedTimeRangeButtons = chartModal ? chartModal.querySelectorAll('.time-range-btn') : [];
    
    console.log('初始化详细图表时间范围切换，找到按钮数量:', detailedTimeRangeButtons.length);
    
    // 初始化详细图表的默认状态，与主图表保持一致
    detailedCurrentTimeRange = currentTimeRange;
    detailedIsMixedView = isMixedView;
    
    // 定义按钮样式配置，与主视图保持一致
    const buttonStyles = [
        { // 24小时按钮
            normal: ['bg-gray-100', 'text-gray-700'],
            hover: ['hover:bg-blue-100'],
            active: ['bg-blue-500', 'text-white'],
            activeHover: ['hover:bg-blue-400']
        },
        { // 7天按钮
            normal: ['bg-gray-100', 'text-gray-700'],
            hover: ['hover:bg-green-100'],
            active: ['bg-green-500', 'text-white'],
            activeHover: ['hover:bg-green-400']
        },
        { // 30天按钮
            normal: ['bg-gray-100', 'text-gray-700'],
            hover: ['hover:bg-purple-100'],
            active: ['bg-purple-500', 'text-white'],
            activeHover: ['hover:bg-purple-400']
        },
        { // 混合视图按钮
            normal: ['bg-gray-100', 'text-gray-700'],
            hover: ['hover:bg-gray-200'],
            active: ['bg-gray-500', 'text-white'],
            activeHover: ['hover:bg-gray-400']
        }
    ];
    
    // 设置初始按钮状态
    detailedTimeRangeButtons.forEach((button, index) => {
        const styleConfig = buttonStyles[index % buttonStyles.length];
        
        // 移除所有初始样式
        button.classList.remove('active', 'bg-blue-500', 'text-white', 'bg-gray-200', 'text-gray-700', 
                              'bg-green-500', 'bg-purple-500', 'bg-gray-100', 'mixed-view-active');
        
        // 设置非选中状态样式
        button.classList.add('transition-colors', 'duration-200');
        button.classList.add(...styleConfig.normal);
        button.classList.add(...styleConfig.hover);
        
        // 如果是第一个按钮且当前是混合视图，设置为混合视图激活状态
        if (index === 0 && detailedIsMixedView) {
            button.classList.remove(...styleConfig.normal);
            button.classList.remove(...styleConfig.hover);
            button.classList.add('active', 'mixed-view-active');
            button.classList.add(...styleConfig.active);
            button.classList.add(...styleConfig.activeHover);
        }
    });
    
    detailedTimeRangeButtons.forEach((button, index) => {
        button.addEventListener('click', () => {
            const styleConfig = buttonStyles[index % buttonStyles.length];
            
            // 检查是否是再次点击已选中的按钮
            const isActive = button.classList.contains('active');
            
            // 重置所有按钮为非选中状态
            detailedTimeRangeButtons.forEach((btn, btnIndex) => {
                const btnStyle = buttonStyles[btnIndex % buttonStyles.length];
                
                // 移除所有可能的激活状态类
                btn.classList.remove('active', 'bg-blue-500', 'text-white', 'bg-green-500', 'bg-purple-500', 'bg-gray-500', 'mixed-view-active');
                btn.classList.remove(...btnStyle.active);
                btn.classList.remove(...btnStyle.activeHover);
                
                // 添加非选中状态类
                btn.classList.add(...btnStyle.normal);
                btn.classList.add(...btnStyle.hover);
            });
            
            if (isActive && index < 3) { // 再次点击已选中的时间范围按钮
                // 切换到混合视图
                detailedIsMixedView = true;
                detailedCurrentTimeRange = 'mixed';
                console.log('详细图表切换到混合视图');
                
                // 设置当前按钮为特殊混合视图状态
                button.classList.remove(...styleConfig.normal);
                button.classList.remove(...styleConfig.hover);
                button.classList.add('active', 'mixed-view-active');
                button.classList.add(...styleConfig.active);
                button.classList.add(...styleConfig.activeHover);
            } else {
                // 普通选中模式
                detailedIsMixedView = false;
                
                // 设置当前按钮为激活状态
                button.classList.remove(...styleConfig.normal);
                button.classList.remove(...styleConfig.hover);
                button.classList.add('active');
                button.classList.add(...styleConfig.active);
                button.classList.add(...styleConfig.activeHover);
                
                // 获取并更新当前时间范围
                let rangeValue;
                if (button.dataset.range) {
                    rangeValue = button.dataset.range;
                } else {
                    const btnText = button.textContent.trim();
                    if (btnText.includes('24')) {
                        rangeValue = '24h';
                    } else if (btnText.includes('7')) {
                        rangeValue = '7d';
                    } else if (btnText.includes('30')) {
                        rangeValue = '30d';
                    } else {
                        rangeValue = btnText.replace(/[^0-9a-zA-Z]/g, '');
                    }
                }
                detailedCurrentTimeRange = rangeValue;
                console.log('详细图表更新时间范围为:', detailedCurrentTimeRange);
            }
            
            // 重新绘制详细图表
            drawDetailedDNSRequestsChart();
        });
    });
}

// 绘制详细的DNS请求趋势图表
function drawDetailedDNSRequestsChart() {
    console.log('绘制详细DNS请求趋势图表，时间范围:', detailedCurrentTimeRange, '混合视图:', detailedIsMixedView);
    
    const ctx = document.getElementById('detailed-dns-requests-chart');
    if (!ctx) {
        console.error('未找到详细DNS请求图表元素');
        return;
    }
    
    const chartContext = ctx.getContext('2d');
    
    // 混合视图配置
    const datasetsConfig = [
        { label: '24小时', api: (api && api.getHourlyStats) || (() => Promise.resolve({ labels: [], data: [] })), color: '#3b82f6', fillColor: 'rgba(59, 130, 246, 0.1)' },
        { label: '7天', api: (api && api.getDailyStats) || (() => Promise.resolve({ labels: [], data: [] })), color: '#22c55e', fillColor: 'rgba(34, 197, 94, 0.1)' },
        { label: '30天', api: (api && api.getMonthlyStats) || (() => Promise.resolve({ labels: [], data: [] })), color: '#a855f7', fillColor: 'rgba(168, 85, 247, 0.1)' }
    ];
    
    // 检查是否为混合视图
    if (detailedIsMixedView || detailedCurrentTimeRange === 'mixed') {
        console.log('渲染混合视图详细图表');
        
        // 显示图例
        const showLegend = true;
        
        // 获取所有时间范围的数据
        Promise.all(datasetsConfig.map(config => 
            config.api().catch(error => {
                console.error(`获取${config.label}数据失败:`, error);
                // 返回空数据
                const count = config.label === '24小时' ? 24 : (config.label === '7天' ? 7 : 30);
                return {
                    labels: Array(count).fill(''),
                    data: Array(count).fill(0)
                };
            })
        )).then(results => {
            // 创建数据集
            const datasets = results.map((data, index) => ({
                label: datasetsConfig[index].label,
                data: data.data,
                borderColor: datasetsConfig[index].color,
                backgroundColor: datasetsConfig[index].fillColor,
                tension: 0.4,
                fill: false,
                borderWidth: 2
            }));
            
            // 创建或更新图表
            if (detailedDnsRequestsChart) {
                detailedDnsRequestsChart.data.labels = results[0].labels;
                detailedDnsRequestsChart.data.datasets = datasets;
                detailedDnsRequestsChart.options.plugins.legend.display = showLegend;
                // 使用平滑过渡动画更新图表
                detailedDnsRequestsChart.update({
                    duration: 800,
                    easing: 'easeInOutQuart'
                });
            } else {
                detailedDnsRequestsChart = new Chart(chartContext, {
                    type: 'line',
                    data: {
                        labels: results[0].labels,
                        datasets: datasets
                    },
                    options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        animation: {
                            duration: 800,
                            easing: 'easeInOutQuart'
                        },
                        plugins: {
                            legend: {
                                display: showLegend,
                                position: 'top'
                            },
                            tooltip: {
                                mode: 'index',
                                intersect: false
                            }
                        },
                        scales: {
                            y: {
                                beginAtZero: true,
                                grid: {
                                    color: 'rgba(0, 0, 0, 0.1)'
                                }
                            },
                            x: {
                                grid: {
                                    display: false
                                }
                            }
                        }
                    }
                });
            }
        }).catch(error => {
            console.error('绘制混合视图详细图表失败:', error);
        });
    } else {
        // 普通视图
        // 根据详细视图时间范围选择API函数和对应的颜色
        let apiFunction;
        let chartColor;
        let chartFillColor;
        
        switch (detailedCurrentTimeRange) {
            case '7d':
                apiFunction = (api && api.getDailyStats) || (() => Promise.resolve({ labels: [], data: [] }));
                chartColor = '#22c55e'; // 绿色，与混合视图中的7天数据颜色一致
                chartFillColor = 'rgba(34, 197, 94, 0.1)';
                break;
            case '30d':
                apiFunction = (api && api.getMonthlyStats) || (() => Promise.resolve({ labels: [], data: [] }));
                chartColor = '#a855f7'; // 紫色，与混合视图中的30天数据颜色一致
                chartFillColor = 'rgba(168, 85, 247, 0.1)';
                break;
            default: // 24h
                apiFunction = (api && api.getHourlyStats) || (() => Promise.resolve({ labels: [], data: [] }));
                chartColor = '#3b82f6'; // 蓝色，与混合视图中的24小时数据颜色一致
                chartFillColor = 'rgba(59, 130, 246, 0.1)';
        }
        
        // 获取统计数据
        apiFunction().then(data => {
            // 创建或更新图表
            if (detailedDnsRequestsChart) {
                detailedDnsRequestsChart.data.labels = data.labels;
                detailedDnsRequestsChart.data.datasets = [{
                    label: 'DNS请求数量',
                    data: data.data,
                    borderColor: chartColor,
                    backgroundColor: chartFillColor,
                    tension: 0.4,
                    fill: true
                }];
                detailedDnsRequestsChart.options.plugins.legend.display = false;
                // 使用平滑过渡动画更新图表
                detailedDnsRequestsChart.update({
                    duration: 800,
                    easing: 'easeInOutQuart'
                });
            } else {
                detailedDnsRequestsChart = new Chart(chartContext, {
                    type: 'line',
                    data: {
                        labels: data.labels,
                        datasets: [{
                            label: 'DNS请求数量',
                            data: data.data,
                            borderColor: chartColor,
                            backgroundColor: chartFillColor,
                            tension: 0.4,
                            fill: true
                        }]
                    },
                    options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        animation: {
                            duration: 800,
                            easing: 'easeInOutQuart'
                        },
                        plugins: {
                            legend: {
                                display: false
                            },
                            title: {
                                display: true,
                                text: 'DNS请求趋势',
                                font: {
                                    size: 14
                                }
                            },
                            tooltip: {
                                mode: 'index',
                                intersect: false
                            }
                        },
                        scales: {
                            y: {
                                beginAtZero: true,
                                grid: {
                                    color: 'rgba(0, 0, 0, 0.1)'
                                }
                            },
                            x: {
                                grid: {
                                    display: false
                                }
                            }
                        }
                    }
                });
            }
        }).catch(error => {
            console.error('绘制详细DNS请求图表失败:', error);
            // 错误处理：使用空数据
            const count = detailedCurrentTimeRange === '24h' ? 24 : (detailedCurrentTimeRange === '7d' ? 7 : 30);
            const emptyData = {
                labels: Array(count).fill(''),
                data: Array(count).fill(0)
            };
            
            if (detailedDnsRequestsChart) {
                detailedDnsRequestsChart.data.labels = emptyData.labels;
                detailedDnsRequestsChart.data.datasets[0].data = emptyData.data;
                detailedDnsRequestsChart.update();
            }
        });
    }
}

// 绘制DNS请求统计图表
function drawDNSRequestsChart() {
    const ctx = document.getElementById('dns-requests-chart');
    if (!ctx) {
        console.error('未找到DNS请求图表元素');
        return;
    }
    
    const chartContext = ctx.getContext('2d');
    
    // 混合视图配置
    const datasetsConfig = [
        { label: '24小时', api: (api && api.getHourlyStats) || (() => Promise.resolve({ labels: [], data: [] })), color: '#3b82f6', fillColor: 'rgba(59, 130, 246, 0.1)' },
        { label: '7天', api: (api && api.getDailyStats) || (() => Promise.resolve({ labels: [], data: [] })), color: '#22c55e', fillColor: 'rgba(34, 197, 94, 0.1)' },
        { label: '30天', api: (api && api.getMonthlyStats) || (() => Promise.resolve({ labels: [], data: [] })), color: '#a855f7', fillColor: 'rgba(168, 85, 247, 0.1)' }
    ];
    
    // 检查是否为混合视图
    if (isMixedView || currentTimeRange === 'mixed') {
        console.log('渲染混合视图图表');
        
        // 显示图例
        const showLegend = true;
        
        // 获取所有时间范围的数据
        Promise.all(datasetsConfig.map(config => 
            config.api().catch(error => {
                console.error(`获取${config.label}数据失败:`, error);
                // 返回空数据而不是模拟数据
                const count = config.label === '24小时' ? 24 : (config.label === '7天' ? 7 : 30);
                return {
                    labels: Array(count).fill(''),
                    data: Array(count).fill(0)
                };
            })
        )).then(results => {
            // 创建数据集
            const datasets = results.map((data, index) => ({
                label: datasetsConfig[index].label,
                data: data.data,
                borderColor: datasetsConfig[index].color,
                backgroundColor: datasetsConfig[index].fillColor,
                tension: 0.4,
                fill: false, // 混合视图不填充
                borderWidth: 2
            }));
            
            // 创建或更新图表
            if (dnsRequestsChart) {
                // 使用第一个数据集的标签，但确保每个数据集使用自己的数据
                dnsRequestsChart.data.labels = results[0].labels;
                dnsRequestsChart.data.datasets = datasets;
                dnsRequestsChart.options.plugins.legend.display = showLegend;
                // 使用平滑过渡动画更新图表
                dnsRequestsChart.update({
                    duration: 800,
                    easing: 'easeInOutQuart'
                });
            } else {
                dnsRequestsChart = new Chart(chartContext, {
                    type: 'line',
                    data: {
                        labels: results[0].labels,
                        datasets: datasets
                    },
                    options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        animation: {
                            duration: 800,
                            easing: 'easeInOutQuart'
                        },
                        plugins: {
                            legend: {
                                display: showLegend,
                                position: 'top'
                            },
                            tooltip: {
                                mode: 'index',
                                intersect: false
                            }
                        },
                        scales: {
                            y: {
                                beginAtZero: true,
                                grid: {
                                    color: 'rgba(0, 0, 0, 0.1)'
                                }
                            },
                            x: {
                                grid: {
                                    display: false
                                }
                            }
                        }
                    }
                });
            }
        }).catch(error => {
            console.error('绘制混合视图图表失败:', error);
        });
    } else {
        // 普通视图
        // 根据当前时间范围选择API函数和对应的颜色
        let apiFunction;
        let chartColor;
        let chartFillColor;
        
        switch (currentTimeRange) {
            case '7d':
                apiFunction = (api && api.getDailyStats) || (() => Promise.resolve({ labels: [], data: [] }));
                chartColor = '#22c55e'; // 绿色，与混合视图中的7天数据颜色一致
                chartFillColor = 'rgba(34, 197, 94, 0.1)';
                break;
            case '30d':
                apiFunction = (api && api.getMonthlyStats) || (() => Promise.resolve({ labels: [], data: [] }));
                chartColor = '#a855f7'; // 紫色，与混合视图中的30天数据颜色一致
                chartFillColor = 'rgba(168, 85, 247, 0.1)';
                break;
            default: // 24h
                apiFunction = (api && api.getHourlyStats) || (() => Promise.resolve({ labels: [], data: [] }));
                chartColor = '#3b82f6'; // 蓝色，与混合视图中的24小时数据颜色一致
                chartFillColor = 'rgba(59, 130, 246, 0.1)';
        }
        
        // 获取统计数据
        apiFunction().then(data => {
            // 创建或更新图表
            if (dnsRequestsChart) {
                dnsRequestsChart.data.labels = data.labels;
                dnsRequestsChart.data.datasets = [{
                    label: 'DNS请求数量',
                    data: data.data,
                    borderColor: chartColor,
                    backgroundColor: chartFillColor,
                    tension: 0.4,
                    fill: true
                }];
                dnsRequestsChart.options.plugins.legend.display = false;
                // 使用平滑过渡动画更新图表
                dnsRequestsChart.update({
                    duration: 800,
                    easing: 'easeInOutQuart'
                });
            } else {
                dnsRequestsChart = new Chart(chartContext, {
                    type: 'line',
                    data: {
                        labels: data.labels,
                        datasets: [{
                            label: 'DNS请求数量',
                            data: data.data,
                            borderColor: chartColor,
                            backgroundColor: chartFillColor,
                            tension: 0.4,
                            fill: true
                        }]
                    },
                    options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        animation: {
                            duration: 800,
                            easing: 'easeInOutQuart'
                        },
                        plugins: {
                            legend: {
                                display: false
                            },
                            tooltip: {
                                mode: 'index',
                                intersect: false
                            }
                        },
                        scales: {
                            y: {
                                beginAtZero: true,
                                grid: {
                                    color: 'rgba(0, 0, 0, 0.1)'
                                }
                            },
                            x: {
                                grid: {
                                    display: false
                                }
                            }
                        }
                    }
                });
            }
        }).catch(error => {
            console.error('绘制DNS请求图表失败:', error);
            // 错误处理：使用空数据而不是模拟数据
            const count = currentTimeRange === '24h' ? 24 : (currentTimeRange === '7d' ? 7 : 30);
            const emptyData = {
                labels: Array(count).fill(''),
                data: Array(count).fill(0)
            };
            
            if (dnsRequestsChart) {
                dnsRequestsChart.data.labels = emptyData.labels;
                dnsRequestsChart.data.datasets[0].data = emptyData.data;
                dnsRequestsChart.update();
            }
        });
    }
}

// 更新图表数据
function updateCharts(stats, queryTypeStats) {
    console.log('更新图表，收到统计数据:', stats);
    console.log('查询类型统计数据:', queryTypeStats);
    
    // 空值检查
    if (!stats) {
        console.error('更新图表失败: 未提供统计数据');
        return;
    }
    
    // 更新比例图表
    if (ratioChart) {
        let allowed = '---', blocked = '---', error = '---';
        
        // 尝试从stats数据中提取
        if (stats.dns) {
            allowed = stats.dns.Allowed || allowed;
            blocked = stats.dns.Blocked || blocked;
            error = stats.dns.Errors || error;
        } else if (stats.totalQueries !== undefined) {
            allowed = stats.allowedQueries || allowed;
            blocked = stats.blockedQueries || blocked;
            error = stats.errorQueries || error;
        }
        
        ratioChart.data.datasets[0].data = [allowed, blocked, error];
        // 使用自定义动画配置更新图表，确保平滑过渡
        ratioChart.update({
            duration: 500,
            easing: 'easeInOutQuart'
        });
    }
    
    // 更新解析类型统计饼图
    if (queryTypeChart && queryTypeStats && Array.isArray(queryTypeStats)) {
        const queryTypeColors = ['#3498db', '#e74c3c', '#2ecc71', '#f39c12', '#9b59b6', '#1abc9c', '#d35400', '#34495e'];
        
        // 检查是否有有效的数据项
        const validData = queryTypeStats.filter(item => item && item.count > 0);
        
        if (validData.length > 0) {
            // 准备标签和数据
            const labels = validData.map(item => item.type);
            const data = validData.map(item => item.count);
            
            // 为每个解析类型分配颜色
            const colors = labels.map((_, index) => queryTypeColors[index % queryTypeColors.length]);
            
            // 更新图表数据
            queryTypeChart.data.labels = labels;
            queryTypeChart.data.datasets[0].data = data;
            queryTypeChart.data.datasets[0].backgroundColor = colors;
        } else {
            // 如果没有数据，显示默认值
            queryTypeChart.data.labels = ['暂无数据'];
            queryTypeChart.data.datasets[0].data = [1];
            queryTypeChart.data.datasets[0].backgroundColor = [queryTypeColors[0]];
        }
        
        // 使用自定义动画配置更新图表，确保平滑过渡
        queryTypeChart.update({
            duration: 500,
            easing: 'easeInOutQuart'
        });
    }
}

// 更新统计卡片折线图
function updateStatCardCharts(stats) {
    if (!stats || Object.keys(statCardCharts).length === 0) {
        return;
    }
    
    // 更新查询总量图表
    if (statCardCharts['query-chart']) {
        let queryCount = 0;
        if (stats.dns) {
            queryCount = stats.dns.Queries || 0;
        } else if (stats.totalQueries !== undefined) {
            queryCount = stats.totalQueries || 0;
        }
        updateChartData('query-chart', queryCount);
    }
    
    // 更新屏蔽数量图表
    if (statCardCharts['blocked-chart']) {
        let blockedCount = 0;
        if (stats.dns) {
            blockedCount = stats.dns.Blocked || 0;
        } else if (stats.blockedQueries !== undefined) {
            blockedCount = stats.blockedQueries || 0;
        }
        updateChartData('blocked-chart', blockedCount);
    }
    
    // 更新正常解析图表
    if (statCardCharts['allowed-chart']) {
        let allowedCount = 0;
        if (stats.dns) {
            allowedCount = stats.dns.Allowed || 0;
        } else if (stats.allowedQueries !== undefined) {
            allowedCount = stats.allowedQueries || 0;
        } else if (stats.dns && stats.dns.Queries && stats.dns.Blocked) {
            allowedCount = stats.dns.Queries - stats.dns.Blocked;
        }
        updateChartData('allowed-chart', allowedCount);
    }
    
    // 更新错误数量图表
    if (statCardCharts['error-chart']) {
        let errorCount = 0;
        if (stats.dns) {
            errorCount = stats.dns.Errors || 0;
        } else if (stats.errorQueries !== undefined) {
            errorCount = stats.errorQueries || 0;
        }
        updateChartData('error-chart', errorCount);
    }
    
    // 更新响应时间图表
    if (statCardCharts['response-time-chart']) {
        let responseTime = 0;
        // 尝试从不同的数据结构获取平均响应时间
        if (stats.dns && stats.dns.AvgResponseTime) {
            responseTime = stats.dns.AvgResponseTime;
        } else if (stats.avgResponseTime !== undefined) {
            responseTime = stats.avgResponseTime;
        } else if (stats.responseTime) {
            responseTime = stats.responseTime;
        }
        // 限制小数位数为两位
        responseTime = parseFloat(responseTime).toFixed(2);
        updateChartData('response-time-chart', responseTime);
    }
    
    // 更新活跃IP图表
    if (statCardCharts['ips-chart']) {
        const activeIPs = stats.activeIPs || 0;
        updateChartData('ips-chart', activeIPs);
    }
    
    // 更新CPU使用率图表
    if (statCardCharts['cpu-chart']) {
        const cpuUsage = stats.cpuUsage || 0;
        updateChartData('cpu-chart', cpuUsage);
    }
    
    // 更新平均响应时间显示
    if (document.getElementById('avg-response-time')) {
        let avgResponseTime = 0;
        // 尝试从不同的数据结构获取平均响应时间
        if (stats.dns && stats.dns.AvgResponseTime) {
            avgResponseTime = stats.dns.AvgResponseTime;
        } else if (stats.avgResponseTime !== undefined) {
            avgResponseTime = stats.avgResponseTime;
        } else if (stats.responseTime) {
            avgResponseTime = stats.responseTime;
        }
        document.getElementById('avg-response-time').textContent = formatNumber(avgResponseTime);
    }
    
    // 更新规则数图表
    if (statCardCharts['rules-chart']) {
        // 尝试获取规则数，如果没有则使用模拟数据
        const rulesCount = getRulesCountFromStats(stats) || Math.floor(Math.random() * 5000) + 10000;
        updateChartData('rules-chart', rulesCount);
    }
    
    // 更新排除规则数图表
    if (statCardCharts['exceptions-chart']) {
        const exceptionsCount = getExceptionsCountFromStats(stats) || Math.floor(Math.random() * 100) + 50;
        updateChartData('exceptions-chart', exceptionsCount);
    }
    
    // 更新Hosts条目数图表
    if (statCardCharts['hosts-chart']) {
        const hostsCount = getHostsCountFromStats(stats) || Math.floor(Math.random() * 1000) + 2000;
        updateChartData('hosts-chart', hostsCount);
    }
}

// 更新单个图表的数据
function updateChartData(chartId, newValue) {
    const chart = statCardCharts[chartId];
    const historyData = statCardHistoryData[chartId];
    
    if (!chart || !historyData) {
        return;
    }
    
    // 添加新数据，移除最旧的数据
    historyData.push(newValue);
    if (historyData.length > 12) {
        historyData.shift();
    }
    
    // 更新图表数据
    chart.data.datasets[0].data = historyData;
    chart.data.labels = generateTimeLabels(historyData.length);
    
    // 使用自定义动画配置更新图表，确保平滑过渡，避免空白区域
    chart.update({
        duration: 300, // 增加动画持续时间
        easing: 'easeInOutQuart', // 使用平滑的缓动函数
        transition: {
            duration: 300,
            easing: 'easeInOutQuart'
        }
    });
}

// 从统计数据中获取规则数
function getRulesCountFromStats(stats) {
    // 尝试从stats中获取规则数
    if (stats.shield && stats.shield.rules) {
        return stats.shield.rules;
    }
    return null;
}

// 从统计数据中获取排除规则数
function getExceptionsCountFromStats(stats) {
    // 尝试从stats中获取排除规则数
    if (stats.shield && stats.shield.exceptions) {
        return stats.shield.exceptions;
    }
    return null;
}

// 从统计数据中获取Hosts条目数
function getHostsCountFromStats(stats) {
    // 尝试从stats中获取Hosts条目数
    if (stats.shield && stats.shield.hosts) {
        return stats.shield.hosts;
    }
    return null;
}

// 初始化统计卡片折线图
function initStatCardCharts() {
    console.log('===== 开始初始化统计卡片折线图 =====');
    
    // 清理已存在的图表实例
    for (const key in statCardCharts) {
        if (statCardCharts.hasOwnProperty(key)) {
            statCardCharts[key].destroy();
        }
    }
    statCardCharts = {};
    statCardHistoryData = {};
    
    // 检查Chart.js是否加载
    console.log('Chart.js是否可用:', typeof Chart !== 'undefined');
    
    // 统计卡片配置信息
    const cardConfigs = [
        { id: 'query-chart', color: '#9b59b6', label: '查询总量' },
        { id: 'blocked-chart', color: '#e74c3c', label: '屏蔽数量' },
        { id: 'allowed-chart', color: '#2ecc71', label: '正常解析' },
        { id: 'error-chart', color: '#f39c12', label: '错误数量' },
        { id: 'response-time-chart', color: '#3498db', label: '响应时间' },
        { id: 'ips-chart', color: '#1abc9c', label: '活跃IP' },
        { id: 'cpu-chart', color: '#e67e22', label: 'CPU使用率' },
        { id: 'rules-chart', color: '#95a5a6', label: '屏蔽规则数' },
        { id: 'exceptions-chart', color: '#34495e', label: '排除规则数' },
        { id: 'hosts-chart', color: '#16a085', label: 'Hosts条目数' }
    ];
    
    console.log('图表配置:', cardConfigs);
    
    cardConfigs.forEach(config => {
        const canvas = document.getElementById(config.id);
        if (!canvas) {
            console.warn(`未找到统计卡片图表元素: ${config.id}`);
            return;
        }
        
        const ctx = canvas.getContext('2d');
        
        // 为不同类型的卡片生成更合适的初始数据
        let initialData;
        if (config.id === 'response-time-chart') {
            // 响应时间图表使用空数组，将通过API实时数据更新
            initialData = Array(12).fill(null);
        } else if (config.id === 'cpu-chart') {
            initialData = generateMockData(12, 0, 10);
        } else {
            initialData = generateMockData(12, 0, 100);
        }
        
        // 初始化历史数据数组
        statCardHistoryData[config.id] = [...initialData];
        
        // 创建图表
        statCardCharts[config.id] = new Chart(ctx, {
            type: 'line',
            data: {
                labels: generateTimeLabels(12),
                datasets: [{
                    label: config.label,
                    data: initialData,
                    borderColor: config.color,
                    backgroundColor: `${config.color}20`, // 透明度20%
                    borderWidth: 2,
                    tension: 0.4,
                    fill: true,
                    pointRadius: 0, // 隐藏数据点
                    pointHoverRadius: 4, // 鼠标悬停时显示数据点
                    pointBackgroundColor: config.color
                }]
            },
            options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        // 添加动画配置，确保平滑过渡
                        animation: {
                            duration: 800,
                            easing: 'easeInOutQuart'
                        },
                        plugins: {
                        legend: {
                            display: false
                        },
                        tooltip: {
                            mode: 'index',
                            intersect: false,
                            backgroundColor: 'rgba(0, 0, 0, 0.9)',
                            titleColor: '#fff',
                            bodyColor: '#fff',
                            borderColor: config.color,
                            borderWidth: 1,
                            padding: 8,
                            displayColors: false,
                            cornerRadius: 4,
                            titleFont: {
                                size: 12,
                                weight: 'normal'
                            },
                            bodyFont: {
                                size: 11
                            },
                            // 确保HTML渲染正确
                            useHTML: true,
                            filter: function(tooltipItem) {
                                return tooltipItem.datasetIndex === 0;
                            },
                            callbacks: {
                                title: function(tooltipItems) {
                                    // 简化时间显示格式
                                    return tooltipItems[0].label;
                                },
                                label: function(context) {
                                    const value = context.parsed.y;
                                    // 格式化大数字
                                    const formattedValue = formatNumber(value);
                                    
                                    // 使用CSS类显示变化趋势
                                    let trendInfo = '';
                                    const data = context.dataset.data;
                                    const currentIndex = context.dataIndex;
                                    
                                    if (currentIndex > 0) {
                                        const prevValue = data[currentIndex - 1];
                                        const change = value - prevValue;
                                        
                                        if (change !== 0) {
                                              const changeSymbol = change > 0 ? '↑' : '↓';
                                              // 取消颜色显示，简化显示
                                              trendInfo = (changeSymbol  + Math.abs(change));
                                        }
                                    }
                                    
                                    // 简化标签格式
                                    return `${config.label}: ${formattedValue}${trendInfo}`;
                                },
                                // 移除平均值显示
                                afterLabel: function(context) {
                                    return '';
                                }
                            }
                        }
                    },
                scales: {
                    x: {
                        display: false // 隐藏X轴
                    },
                    y: {
                        display: false, // 隐藏Y轴
                        beginAtZero: true
                    }
                },
                interaction: {
                    intersect: false,
                    mode: 'index'
                }
            }
        });
    });
}

// 生成模拟数据
function generateMockData(count, min, max) {
    const data = [];
    for (let i = 0; i < count; i++) {
        data.push(Math.floor(Math.random() * (max - min + 1)) + min);
    }
    return data;
}

// 生成时间标签
function generateTimeLabels(count) {
    const labels = [];
    const now = new Date();
    for (let i = count - 1; i >= 0; i--) {
        const time = new Date(now.getTime() - i * 5 * 60 * 1000); // 每5分钟一个点
        labels.push(`${time.getHours().toString().padStart(2, '0')}:${time.getMinutes().toString().padStart(2, '0')}`);
    }
    return labels;
}

// 格式化数字显示（使用K/M后缀）
function formatNumber(num) {
    // 如果不是数字，直接返回
    if (isNaN(num) || num === '---') {
        return num;
    }
    
    // 显示完整数字的最大长度阈值
    const MAX_FULL_LENGTH = 5;
    
    // 先获取完整数字字符串
    const fullNumStr = num.toString();
    
    // 如果数字长度小于等于阈值，直接返回完整数字
    if (fullNumStr.length <= MAX_FULL_LENGTH) {
        return fullNumStr;
    }
    
    // 否则使用缩写格式
    if (num >= 1000000) {
        return (num / 1000000).toFixed(1) + 'M';
    } else if (num >= 1000) {
        return (num / 1000).toFixed(1) + 'K';
    }
    
    return fullNumStr;
}

// 更新运行状态
function updateUptime() {
    // 实现更新运行时间的逻辑
    // 这里应该调用API获取当前运行时间并更新到UI
    // 由于API暂时没有提供运行时间，我们先使用模拟数据
    const uptimeElement = document.getElementById('uptime');
    if (uptimeElement) {
        uptimeElement.textContent = '---';
    }
}

// 格式化数字（添加千位分隔符）
function formatWithCommas(num) {
    return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}

// 格式化时间
function formatTime(timestamp) {
    const date = new Date(timestamp);
    const now = new Date();
    const diff = now - date;
    
    // 如果是今天，显示时间
    if (date.toDateString() === now.toDateString()) {
        return date.toLocaleTimeString('zh-CN', {hour: '2-digit', minute: '2-digit'});
    }
    
    // 否则显示日期和时间
    return date.toLocaleString('zh-CN', {
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit'
    });
}

// 根据颜色代码获取对应的CSS类名（兼容方式）
function getColorClassName(colorCode) {
    // 优先使用配置文件中的颜色处理
    if (COLOR_CONFIG.getColorClassName) {
        return COLOR_CONFIG.getColorClassName(colorCode);
    }
    
    // 备用颜色映射
    const colorMap = {
        '#1890ff': 'blue',
        '#52c41a': 'green',
        '#fa8c16': 'orange',
        '#f5222d': 'red',
        '#722ed1': 'purple',
        '#13c2c2': 'cyan',
        '#36cfc9': 'teal'
    };
    
    // 返回映射的类名，如果没有找到则返回默认的blue
    return colorMap[colorCode] || 'blue';
}

// 显示通知
function showNotification(message, type = 'info') {
    // 移除已存在的通知
    const existingNotification = document.getElementById('notification');
    if (existingNotification) {
        existingNotification.remove();
    }
    
    // 创建通知元素
    const notification = document.createElement('div');
    notification.id = 'notification';
    notification.className = `fixed top-4 right-4 px-6 py-3 rounded-lg shadow-lg z-50 transform transition-all duration-300 translate-y-0 opacity-0`;
    
    // 设置样式和内容
    let bgColor, textColor, icon;
    switch (type) {
        case 'success':
            bgColor = 'bg-success';
            textColor = 'text-white';
            icon = 'fa-check-circle';
            break;
        case 'error':
            bgColor = 'bg-danger';
            textColor = 'text-white';
            icon = 'fa-exclamation-circle';
            break;
        case 'warning':
            bgColor = 'bg-warning';
            textColor = 'text-white';
            icon = 'fa-exclamation-triangle';
            break;
        default:
            bgColor = 'bg-primary';
            textColor = 'text-white';
            icon = 'fa-info-circle';
    }
    
    notification.className += ` ${bgColor} ${textColor}`;
    notification.innerHTML = `
        <div class="flex items-center">
            <i class="fa ${icon} mr-3"></i>
            <span>${message}</span>
        </div>
    `;
    
    // 添加到页面
    document.body.appendChild(notification);
    
    // 显示通知
    setTimeout(() => {
        notification.classList.remove('translate-y-0', 'opacity-0');
        notification.classList.add('-translate-y-2', 'opacity-100');
    }, 10);
    
    // 自动关闭
    setTimeout(() => {
        notification.classList.add('translate-y-0', 'opacity-0');
        setTimeout(() => {
            notification.remove();
        }, 300);
    }, 3000);
}

// 页面切换处理
function handlePageSwitch() {
    const menuItems = document.querySelectorAll('nav a');
    
    // 页面切换逻辑
    function switchPage(targetId, menuItem) {
        // 隐藏所有内容
        document.querySelectorAll('[id$="-content"]').forEach(content => {
            content.classList.add('hidden');
        });
        
        // 显示目标内容
        document.getElementById(`${targetId}-content`).classList.remove('hidden');
        
        // 更新页面标题
        document.getElementById('page-title').textContent = menuItem.querySelector('span').textContent;
        
        // 更新活动菜单项
        menuItems.forEach(item => {
            item.classList.remove('sidebar-item-active');
        });
        menuItem.classList.add('sidebar-item-active');
        
        // 侧边栏切换（移动端）
        if (window.innerWidth < 1024) {
            toggleSidebar();
        }
    }
    
    menuItems.forEach(item => {
        item.addEventListener('click', (e) => {
            // 允许默认的hash变化
            // 页面切换会由hashchange事件处理
        });
    });
}

// 处理hash变化 - 全局函数，确保在页面加载时就能被调用
function handleHashChange() {
    let hash = window.location.hash;
    
    // 如果没有hash，默认设置为#dashboard
    if (!hash) {
        hash = '#dashboard';
        window.location.hash = hash;
        return;
    }
    
    const targetId = hash.substring(1);
    const menuItems = document.querySelectorAll('nav a');
    
    // 首先检查是否存在对应的内容元素
    const contentElement = document.getElementById(`${targetId}-content`);
    
    // 查找对应的菜单项
    let targetMenuItem = null;
    menuItems.forEach(item => {
        if (item.getAttribute('href') === hash) {
            targetMenuItem = item;
        }
    });
    
    // 如果找到了对应的内容元素，直接显示
    if (contentElement) {
        // 隐藏所有内容
        document.querySelectorAll('[id$="-content"]').forEach(content => {
            content.classList.add('hidden');
        });
        
        // 显示目标内容
        contentElement.classList.remove('hidden');
        
        // 更新活动菜单项和页面标题
        menuItems.forEach(item => {
            item.classList.remove('sidebar-item-active');
        });
        
        if (targetMenuItem) {
            targetMenuItem.classList.add('sidebar-item-active');
            // 更新页面标题
            const pageTitle = targetMenuItem.querySelector('span').textContent;
            document.getElementById('page-title').textContent = pageTitle;
        } else {
            // 如果没有找到对应的菜单项，尝试根据hash更新页面标题
            const titleElement = document.getElementById(`${targetId}-title`);
            if (titleElement) {
                document.getElementById('page-title').textContent = titleElement.textContent;
            }
        }
    } else if (targetMenuItem) {
        // 隐藏所有内容
        document.querySelectorAll('[id$="-content"]').forEach(content => {
            content.classList.add('hidden');
        });
        
        // 显示目标内容
        document.getElementById(`${targetId}-content`).classList.remove('hidden');
        
        // 更新页面标题
        document.getElementById('page-title').textContent = targetMenuItem.querySelector('span').textContent;
        
        // 更新活动菜单项
        menuItems.forEach(item => {
            item.classList.remove('sidebar-item-active');
        });
        targetMenuItem.classList.add('sidebar-item-active');
        
        // 侧边栏切换（移动端）
        if (window.innerWidth < 1024) {
            toggleSidebar();
        }
    } else {
        // 如果既没有找到内容元素也没有找到菜单项，默认显示dashboard
        window.location.hash = '#dashboard';
    }
}

// 初始化hash路由
function initHashRoute() {
    handleHashChange();
}

// 监听hash变化事件 - 全局事件监听器
window.addEventListener('hashchange', handleHashChange);

// 初始化hash路由 - 确保在页面加载时就能被调用
initHashRoute();

// 响应式处理
function handleResponsive() {
    // 窗口大小改变时处理
    window.addEventListener('resize', () => {
        
        // 更新所有图表大小
        if (dnsRequestsChart) {
            dnsRequestsChart.update();
        }
        if (ratioChart) {
            ratioChart.update();
        }
        if (queryTypeChart) {
            queryTypeChart.update();
        }
        if (detailedDnsRequestsChart) {
            detailedDnsRequestsChart.update();
        }
        // 更新统计卡片图表
        Object.values(statCardCharts).forEach(chart => {
            if (chart) {
                chart.update();
            }
        });
    });
    
    // 添加触摸事件支持，用于移动端
    let touchStartX = 0;
    let touchEndX = 0;
    
    document.addEventListener('touchstart', (e) => {
        touchStartX = e.changedTouches[0].screenX;
    }, false);
    
    document.addEventListener('touchend', (e) => {
        touchEndX = e.changedTouches[0].screenX;
        handleSwipe();
    }, false);
    
    function handleSwipe() {
        // 从左向右滑动，打开侧边栏
        if (touchEndX - touchStartX > 50 && window.innerWidth < 1024) {
            sidebar.classList.remove('-translate-x-full');
        }
        // 从右向左滑动，关闭侧边栏
        if (touchStartX - touchEndX > 50 && window.innerWidth < 1024) {
            sidebar.classList.add('-translate-x-full');
        }
    }
}

// 添加重试功能
function addRetryEventListeners() {
    // TOP客户端重试按钮
    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) {
                // 使用真实数据
                updateTopClientsTable(clientsData);
                hideLoading('top-clients');
                const errorElement = document.getElementById('top-clients-error');
                if (errorElement) errorElement.classList.add('hidden');
            } else {
                // 重试失败，保持原有状态
                console.warn('重试获取TOP客户端数据失败');
            }
        });
    }
    
    // TOP域名重试按钮
    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) {
                // 使用真实数据
                updateTopDomainsTable(domainsData);
                hideLoading('top-domains');
                const errorElement = document.getElementById('top-domains-error');
                if (errorElement) errorElement.classList.add('hidden');
            } else {
                // 重试失败，保持原有状态
                console.warn('重试获取TOP域名数据失败');
            }
        });
    }
}

// 页面加载完成后初始化
window.addEventListener('DOMContentLoaded', () => {
    // 初始化页面切换
    handlePageSwitch();
    
    // 初始化响应式
    handleResponsive();
    
    // 初始化仪表盘
    initDashboard();
    
    // 添加重试事件监听器
    addRetryEventListeners();
    
    // 页面卸载时清理定时器
    window.addEventListener('beforeunload', () => {
        if (intervalId) {
            clearInterval(intervalId);
        }
    });
});