diff --git a/public/css/style.css b/public/css/style.css index 4a5cef9..3fcd38c 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -1982,102 +1982,4 @@ input:checked+.slider:before { .stat-cards { grid-template-columns: 1fr; } -} - -/* ---- Network Summary Stats Premium Layout ---- */ -.network-summary-grid { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 16px; - padding: 8px 0; - margin: 12px 0; - animation: slideInDown 0.4s cubic-bezier(0.16, 1, 0.3, 1); -} - -.summary-stat-item { - display: flex; - align-items: center; - gap: 16px; - padding: 20px; - background: linear-gradient(145deg, rgba(255, 255, 255, 0.03), rgba(255, 255, 255, 0.01)); - border: 1px solid rgba(255, 255, 255, 0.05); - border-radius: var(--radius-lg); - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - position: relative; - overflow: hidden; -} - -.summary-stat-item::after { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: radial-gradient(circle at top left, rgba(99, 102, 241, 0.05), transparent 70%); - opacity: 0; - transition: opacity 0.3s; -} - -.summary-stat-item:hover { - background: rgba(99, 102, 241, 0.08); - border-color: rgba(99, 102, 241, 0.3); - transform: translateY(-3px) scale(1.01); - box-shadow: 0 10px 20px -10px rgba(0, 0, 0, 0.5), 0 0 15px rgba(99, 102, 241, 0.1); -} - -.summary-stat-item:hover::after { - opacity: 1; -} - -.stat-icon-wrapper { - width: 44px; - height: 44px; - display: flex; - align-items: center; - justify-content: center; - border-radius: var(--radius-md); - background: rgba(99, 102, 241, 0.15); - color: var(--accent-indigo); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); - flex-shrink: 0; -} - -.stat-rx .stat-icon-wrapper { background: rgba(34, 211, 238, 0.12); color: #22d3ee; } -.stat-tx .stat-icon-wrapper { background: rgba(99, 102, 241, 0.12); color: #818cf8; } -.stat-p95 .stat-icon-wrapper { background: rgba(244, 63, 94, 0.12); color: #fb7185; } -.stat-total .stat-icon-wrapper { background: rgba(16, 185, 129, 0.12); color: #34d399; } - -.stat-info { - display: flex; - flex-direction: column; - gap: 4px; -} - -.summary-stat-label { - font-size: 0.72rem; - color: var(--text-muted); - text-transform: uppercase; - letter-spacing: 0.08em; - font-weight: 700; -} - -.summary-stat-value { - font-size: 1.3rem; - font-weight: 800; - color: var(--text-primary); - font-family: var(--font-mono); - letter-spacing: -0.01em; - line-height: 1; -} - -@keyframes slideInDown { - from { opacity: 0; transform: translateY(-10px); } - to { opacity: 1; transform: translateY(0); } -} - -@media (max-width: 600px) { - .network-summary-grid { - grid-template-columns: 1fr; - } } \ No newline at end of file diff --git a/public/js/app.js b/public/js/app.js index 6f3b983..7c572fe 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -948,7 +948,7 @@
-
+
@@ -967,8 +967,7 @@
- -
+
@@ -1074,93 +1073,12 @@ data.series = null; // This tells MetricChart to draw a single line instead of stacked area } - if (metricKey === 'networkTrend') { - const stats = calculateHistoryStats(data); - const summaryDiv = document.getElementById(`summary-${metricKey}`); - const wrapperDiv = document.getElementById(`wrapper-${metricKey}`); - if (summaryDiv && wrapperDiv) { - summaryDiv.style.display = 'block'; - wrapperDiv.style.display = 'none'; // Hide the chart canvas - summaryDiv.innerHTML = ` -
-
-
- -
-
- 24h 接收总量 - ${formatBytes(stats.rxTotal)} -
-
-
-
- -
-
- 24h 发送总量 - ${formatBytes(stats.txTotal)} -
-
-
-
- -
-
- 95计费 (上行) - ${formatBandwidth(stats.p95)} -
-
-
-
- -
-
- 24h 网络总流量 - ${formatBytes(stats.total)} -
-
-
- `; - } - } else { - chart.setData(data); - } + chart.setData(data); } catch (err) { console.error(`Error loading history for ${metricKey}:`, err); } }; - function calculateHistoryStats(data) { - if (!data.timestamps || data.timestamps.length < 2) { - return { rxTotal: 0, txTotal: 0, p95: 0, total: 0 }; - } - - const tx = data.tx || []; - const rx = data.rx || []; - const ts = data.timestamps; - - let rxTotal = 0; - let txTotal = 0; - - for (let i = 0; i < ts.length - 1; i++) { - const duration = (ts[i+1] - ts[i]) / 1000; // in seconds - rxTotal += (rx[i] || 0) * duration; - txTotal += (tx[i] || 0) * duration; - } - - // P95 calculation for TX - const sortedTx = [...tx].sort((a, b) => a - b); - const p95Idx = Math.floor(sortedTx.length * 0.95); - const p95 = sortedTx.length > 0 ? sortedTx[p95Idx] : 0; - - return { - rxTotal, - txTotal, - p95, - total: rxTotal + txTotal - }; - } - window.loadCustomMetricHistory = async function (metricKey, event) { if (event) event.stopPropagation();