添加刷新按钮

This commit is contained in:
CN-JS-HuiBai
2026-04-06 23:13:50 +08:00
parent 1bfee2026f
commit c94b697319
4 changed files with 55 additions and 10 deletions

View File

@@ -1873,6 +1873,11 @@ input:checked+.slider:before {
} }
/* ---- Animations ---- */ /* ---- Animations ---- */
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes fadeInUp { @keyframes fadeInUp {
from { from {
opacity: 0; opacity: 0;

View File

@@ -242,6 +242,13 @@
</svg> </svg>
网络流量趋势 (24h) 网络流量趋势 (24h)
</h2> </h2>
<div class="chart-header-actions">
<button class="btn-icon" id="btnRefreshNetwork" title="刷新流量趋势">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="width: 16px; height: 16px;">
<path d="M23 4v6h-6M1 20v-6h6M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path>
</svg>
</button>
</div>
</div> </div>
<div class="chart-legend"> <div class="chart-legend">
<span class="legend-item" id="legendRx" style="cursor: pointer;" title="点击切换 接收 (RX) 显示/隐藏"><span <span class="legend-item" id="legendRx" style="cursor: pointer;" title="点击切换 接收 (RX) 显示/隐藏"><span

View File

@@ -110,6 +110,7 @@
partitionHeader: document.getElementById('partitionHeader'), partitionHeader: document.getElementById('partitionHeader'),
globeCard: document.getElementById('globeCard'), globeCard: document.getElementById('globeCard'),
btnExpandGlobe: document.getElementById('btnExpandGlobe'), btnExpandGlobe: document.getElementById('btnExpandGlobe'),
btnRefreshNetwork: document.getElementById('btnRefreshNetwork'),
// Footer & Filing // Footer & Filing
icpFilingInput: document.getElementById('icpFilingInput'), icpFilingInput: document.getElementById('icpFilingInput'),
psFilingInput: document.getElementById('psFilingInput'), psFilingInput: document.getElementById('psFilingInput'),
@@ -353,6 +354,25 @@
}); });
} }
if (dom.btnRefreshNetwork) {
dom.btnRefreshNetwork.addEventListener('click', async () => {
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 // Keyboard shortcut
document.addEventListener('keydown', (e) => { document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') { if (e.key === 'Escape') {
@@ -693,9 +713,10 @@
} }
// ---- Fetch Metrics ---- // ---- Fetch Metrics ----
async function fetchMetrics() { async function fetchMetrics(force = false) {
try { 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(); const data = await response.json();
allServersData = data.servers || []; allServersData = data.servers || [];
updateDashboard(data); updateDashboard(data);
@@ -1619,9 +1640,10 @@
}; };
// ---- Network History ---- // ---- Network History ----
async function fetchNetworkHistory() { async function fetchNetworkHistory(force = false) {
try { 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(); const data = await response.json();
networkChart.setData(data); networkChart.setData(data);
if (dom.trafficP95 && networkChart.p95) { if (dom.trafficP95 && networkChart.p95) {

View File

@@ -663,7 +663,7 @@ app.post('/api/settings', requireAuth, async (req, res) => {
// ==================== Metrics Aggregation ==================== // ==================== Metrics Aggregation ====================
// Reusable function to get overview metrics // 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"'); const [sources] = await db.query('SELECT * FROM prometheus_sources WHERE is_server_source = 1 AND type != "blackbox"');
if (sources.length === 0) { if (sources.length === 0) {
return { return {
@@ -680,8 +680,12 @@ async function getOverview() {
const allMetrics = await Promise.all(sources.map(async (source) => { const allMetrics = await Promise.all(sources.map(async (source) => {
const cacheKey = `source_metrics:${source.url}:${source.name}`; const cacheKey = `source_metrics:${source.url}:${source.name}`;
const cached = await cache.get(cacheKey); if (force) {
if (cached) return cached; await cache.del(cacheKey);
} else {
const cached = await cache.get(cacheKey);
if (cached) return cached;
}
try { try {
const metrics = await prometheusService.getOverviewMetrics(source.url, source.name); const metrics = await prometheusService.getOverviewMetrics(source.url, source.name);
@@ -790,7 +794,8 @@ async function getOverview() {
// Get all aggregated metrics from all Prometheus sources // Get all aggregated metrics from all Prometheus sources
app.get('/api/metrics/overview', async (req, res) => { app.get('/api/metrics/overview', async (req, res) => {
try { try {
const overview = await getOverview(); const force = req.query.force === 'true';
const overview = await getOverview(force);
res.json(overview); res.json(overview);
} catch (err) { } catch (err) {
console.error('Error fetching overview metrics:', 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 // Get network traffic history (past 24h) from Prometheus
app.get('/api/metrics/network-history', async (req, res) => { app.get('/api/metrics/network-history', async (req, res) => {
try { try {
const force = req.query.force === 'true';
const cacheKey = 'network_history_all'; 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"'); const [sources] = await db.query('SELECT * FROM prometheus_sources WHERE is_server_source = 1 AND type != "blackbox"');
if (sources.length === 0) { if (sources.length === 0) {