diff --git a/public/index.html b/public/index.html index 0b93e1c..36e0bb4 100644 --- a/public/index.html +++ b/public/index.html @@ -519,10 +519,6 @@ 硬盘总量统计 0 GB -
- 24h 网络总流量 - 0 B -
diff --git a/public/js/app.js b/public/js/app.js index 8ba7756..80e94df 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -93,8 +93,7 @@ detailPartitionsContainer: document.getElementById('detailPartitionsContainer'), detailPartitionsList: document.getElementById('detailPartitionsList'), partitionSummary: document.getElementById('partitionSummary'), - partitionHeader: document.getElementById('partitionHeader'), - detailTraffic24h: document.getElementById('detailTraffic24h') + partitionHeader: document.getElementById('partitionHeader') }; // ---- State ---- @@ -916,11 +915,6 @@ dom.detailDiskTotal.textContent = formatBytes(totalDiskSize); } - // 24h Traffic Total - if (dom.detailTraffic24h && data.traffic24h) { - dom.detailTraffic24h.textContent = formatBytes((data.traffic24h.rx || 0) + (data.traffic24h.tx || 0)); - } - // Define metrics to show const cpuValueHtml = `
@@ -953,30 +947,31 @@
-
-
-
-
- - - - -
-
- -
-
- - - - +
+
+
+
+ + + + +
+
+ +
+
+ + + + +
+ +
+ +
-
- -
-
`).join(''); @@ -1079,12 +1074,73 @@ data.series = null; // This tells MetricChart to draw a single line instead of stacked area } - chart.setData(data); + 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); + } } 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();