From c94b697319830c32b1d02fd44904a5302fd6953d Mon Sep 17 00:00:00 2001 From: CN-JS-HuiBai Date: Mon, 6 Apr 2026 23:13:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=88=B7=E6=96=B0=E6=8C=89?= =?UTF-8?q?=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/css/style.css | 5 +++++ public/index.html | 7 +++++++ public/js/app.js | 30 ++++++++++++++++++++++++++---- server/index.js | 23 +++++++++++++++++------ 4 files changed, 55 insertions(+), 10 deletions(-) diff --git a/public/css/style.css b/public/css/style.css index 88c7544..3952dab 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -1873,6 +1873,11 @@ input:checked+.slider:before { } /* ---- Animations ---- */ +@keyframes spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + @keyframes fadeInUp { from { opacity: 0; diff --git a/public/index.html b/public/index.html index a296192..163cd2b 100644 --- a/public/index.html +++ b/public/index.html @@ -242,6 +242,13 @@ 网络流量趋势 (24h) +
+ +
{ + const icon = dom.btnRefreshNetwork.querySelector('svg'); + if (icon) icon.style.animation = 'spin 0.8s ease-in-out'; + + // Force refresh all Prometheus 24h data and overview + await Promise.all([ + fetchNetworkHistory(true), + fetchMetrics(true) + ]); + + if (icon) { + setTimeout(() => { + icon.style.animation = ''; + }, 800); + } + }); + } + // Keyboard shortcut document.addEventListener('keydown', (e) => { if (e.key === 'Escape') { @@ -693,9 +713,10 @@ } // ---- Fetch Metrics ---- - async function fetchMetrics() { + async function fetchMetrics(force = false) { try { - const response = await fetch('/api/metrics/overview'); + const url = `/api/metrics/overview${force ? '?force=true' : ''}`; + const response = await fetch(url); const data = await response.json(); allServersData = data.servers || []; updateDashboard(data); @@ -1619,9 +1640,10 @@ }; // ---- Network History ---- - async function fetchNetworkHistory() { + async function fetchNetworkHistory(force = false) { try { - const response = await fetch('/api/metrics/network-history'); + const url = `/api/metrics/network-history${force ? '?force=true' : ''}`; + const response = await fetch(url); const data = await response.json(); networkChart.setData(data); if (dom.trafficP95 && networkChart.p95) { diff --git a/server/index.js b/server/index.js index 071fa35..f5220a0 100644 --- a/server/index.js +++ b/server/index.js @@ -663,7 +663,7 @@ app.post('/api/settings', requireAuth, async (req, res) => { // ==================== Metrics Aggregation ==================== // Reusable function to get overview metrics -async function getOverview() { +async function getOverview(force = false) { const [sources] = await db.query('SELECT * FROM prometheus_sources WHERE is_server_source = 1 AND type != "blackbox"'); if (sources.length === 0) { return { @@ -680,8 +680,12 @@ async function getOverview() { const allMetrics = await Promise.all(sources.map(async (source) => { const cacheKey = `source_metrics:${source.url}:${source.name}`; - const cached = await cache.get(cacheKey); - if (cached) return cached; + if (force) { + await cache.del(cacheKey); + } else { + const cached = await cache.get(cacheKey); + if (cached) return cached; + } try { const metrics = await prometheusService.getOverviewMetrics(source.url, source.name); @@ -790,7 +794,8 @@ async function getOverview() { // Get all aggregated metrics from all Prometheus sources app.get('/api/metrics/overview', async (req, res) => { try { - const overview = await getOverview(); + const force = req.query.force === 'true'; + const overview = await getOverview(force); res.json(overview); } catch (err) { console.error('Error fetching overview metrics:', err); @@ -801,9 +806,15 @@ app.get('/api/metrics/overview', async (req, res) => { // Get network traffic history (past 24h) from Prometheus app.get('/api/metrics/network-history', async (req, res) => { try { + const force = req.query.force === 'true'; const cacheKey = 'network_history_all'; - const cached = await cache.get(cacheKey); - if (cached) return res.json(cached); + + if (force) { + await cache.del(cacheKey); + } else { + const cached = await cache.get(cacheKey); + if (cached) return res.json(cached); + } const [sources] = await db.query('SELECT * FROM prometheus_sources WHERE is_server_source = 1 AND type != "blackbox"'); if (sources.length === 0) {