diff --git a/static/index.html b/static/index.html index fa54319..1f1acac 100644 --- a/static/index.html +++ b/static/index.html @@ -51,7 +51,95 @@ } } - + + +
@@ -140,7 +228,7 @@
-
+
@@ -166,7 +254,7 @@
-
+
@@ -192,7 +280,7 @@
-
+
@@ -218,7 +306,7 @@
-
+
diff --git a/static/js/dashboard.js b/static/js/dashboard.js index 43236e6..795d299 100644 --- a/static/js/dashboard.js +++ b/static/js/dashboard.js @@ -16,7 +16,9 @@ const COLOR_CONFIG = window.COLOR_CONFIG || {}; // 初始化仪表盘 async function initDashboard() { try { - // 加载初始数据 + console.log('页面打开时强制刷新数据...'); + + // 优先加载初始数据,确保页面显示最新信息 await loadDashboardData(); // 初始化图表 @@ -342,31 +344,94 @@ function updateStatsCards(stats) { activeIPsPercentage = stats[0].activeIPsPercentage || 0; } - // 更新数量显示 - document.getElementById('total-queries').textContent = formatNumber(totalQueries); - document.getElementById('blocked-queries').textContent = formatNumber(blockedQueries); - document.getElementById('allowed-queries').textContent = formatNumber(allowedQueries); - document.getElementById('error-queries').textContent = formatNumber(errorQueries); - document.getElementById('active-ips').textContent = formatNumber(activeIPs); + // 为数字元素添加平滑过渡效果和光晕效果的函数 + function animateValue(elementId, newValue) { + const element = document.getElementById(elementId); + if (!element) 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'); + + // 添加淡入淡出动画 + element.style.opacity = '0'; + element.style.transition = 'opacity 200ms ease-out'; + + setTimeout(() => { + element.textContent = formattedNewValue; + element.style.opacity = '1'; + + // 添加光晕效果 + // 根据父级卡片类型确定光晕颜色 + const card = element.closest('.stat-card, .bg-blue-50, .bg-red-50, .bg-green-50, .bg-yellow-50'); + if (card) { + // 设置光晕颜色类 + if (card.classList.contains('bg-blue-50') || card.id.includes('total')) { + element.classList.add('number-glow-blue'); + } else if (card.classList.contains('bg-red-50') || card.id.includes('blocked')) { + element.classList.add('number-glow-red'); + } else if (card.classList.contains('bg-green-50') || card.id.includes('allowed')) { + element.classList.add('number-glow-green'); + } else if (card.classList.contains('bg-yellow-50') || card.id.includes('error')) { + element.classList.add('number-glow-yellow'); + } + } else { + // 默认光晕效果 + element.classList.add('number-glow'); + } + + // 2秒后移除光晕效果 + setTimeout(() => { + element.classList.remove('number-glow', 'number-glow-blue', 'number-glow-red', 'number-glow-green', 'number-glow-yellow'); + }, 2000); + }, 200); + } - // 更新最常查询类型 - document.getElementById('top-query-type').textContent = topQueryType; - document.getElementById('query-type-percentage').textContent = `${Math.round(queryTypePercentage)}%`; + // 更新百分比元素的函数 + function updatePercentage(elementId, value) { + const element = document.getElementById(elementId); + if (!element) return; + + element.style.opacity = '0'; + element.style.transition = 'opacity 200ms ease-out'; + + setTimeout(() => { + element.textContent = value; + element.style.opacity = '1'; + }, 200); + } - // 更新活跃来源IP百分比 - document.getElementById('active-ips-percent').textContent = `${Math.round(activeIPsPercentage)}%`; + // 平滑更新数量显示 + animateValue('total-queries', totalQueries); + animateValue('blocked-queries', blockedQueries); + animateValue('allowed-queries', allowedQueries); + animateValue('error-queries', errorQueries); + animateValue('active-ips', activeIPs); - // 计算并更新百分比 + // 平滑更新文本和百分比 + updatePercentage('top-query-type', topQueryType); + updatePercentage('query-type-percentage', `${Math.round(queryTypePercentage)}%`); + updatePercentage('active-ips-percent', `${Math.round(activeIPsPercentage)}%`); + + // 计算并平滑更新百分比 if (totalQueries > 0) { - document.getElementById('blocked-percent').textContent = `${Math.round((blockedQueries / totalQueries) * 100)}%`; - document.getElementById('allowed-percent').textContent = `${Math.round((allowedQueries / totalQueries) * 100)}%`; - document.getElementById('error-percent').textContent = `${Math.round((errorQueries / totalQueries) * 100)}%`; - document.getElementById('queries-percent').textContent = `100%`; + updatePercentage('blocked-percent', `${Math.round((blockedQueries / totalQueries) * 100)}%`); + updatePercentage('allowed-percent', `${Math.round((allowedQueries / totalQueries) * 100)}%`); + updatePercentage('error-percent', `${Math.round((errorQueries / totalQueries) * 100)}%`); + updatePercentage('queries-percent', '100%'); } else { - document.getElementById('queries-percent').textContent = '---'; - document.getElementById('blocked-percent').textContent = '---'; - document.getElementById('allowed-percent').textContent = '---'; - document.getElementById('error-percent').textContent = '---'; + updatePercentage('queries-percent', '---'); + updatePercentage('blocked-percent', '---'); + updatePercentage('allowed-percent', '---'); + updatePercentage('error-percent', '---'); } }