🎈 pref: 优化网络监测组件

This commit is contained in:
zhiyu1998 2024-11-22 13:57:10 +08:00
parent 6afdf6972c
commit be8c95e6fd
4 changed files with 202 additions and 18 deletions

View File

@ -4,13 +4,16 @@
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"axios": "^1.3.4", "axios": "^1.3.4",
"chart.js": "^4.4.6",
"form-data": "^4.0.1", "form-data": "^4.0.1",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"next": "^14.2.16", "next": "^14.2.16",
"node-id3": "^0.2.6", "node-id3": "^0.2.6",
"os-utils": "^0.0.14",
"p-queue": "^8.0.1", "p-queue": "^8.0.1",
"qrcode": "^1.5.3", "qrcode": "^1.5.3",
"react": "^18.3.1", "react": "^18.3.1",
"react-chartjs-2": "^5.2.0",
"react-circular-progressbar": "^2.1.0", "react-circular-progressbar": "^2.1.0",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"systeminformation": "^5.23.5" "systeminformation": "^5.23.5"

View File

@ -0,0 +1,56 @@
import os from 'os';
let lastBytesReceived = 0;
let lastBytesSent = 0;
let lastTimestamp = Date.now();
function getNetworkStats() {
const networkInterfaces = os.networkInterfaces();
let bytesReceived = 0;
let bytesSent = 0;
// 累加所有网络接口的数据
Object.values(networkInterfaces).forEach(interfaces => {
interfaces.forEach(netInterface => {
if (netInterface.internal === false) {
bytesReceived += netInterface.bytes_received || 0;
bytesSent += netInterface.bytes_sent || 0;
}
});
});
const now = Date.now();
const timeDiff = (now - lastTimestamp) / 1000; // 转换为秒
// 计算速率(字节/秒)
const downloadSpeed = (bytesReceived - lastBytesReceived) / timeDiff;
const uploadSpeed = (bytesSent - lastBytesSent) / timeDiff;
// 更新上次的值
lastBytesReceived = bytesReceived;
lastBytesSent = bytesSent;
lastTimestamp = now;
return {
downloadSpeed: (downloadSpeed / 1024).toFixed(2), // KB/s
uploadSpeed: (uploadSpeed / 1024).toFixed(2), // KB/s
totalReceived: (bytesReceived / (1024 * 1024 * 1024)).toFixed(2), // GB
totalSent: (bytesSent / (1024 * 1024 * 1024)).toFixed(2), // GB
timestamp: now
};
}
export async function GET() {
try {
const stats = getNetworkStats();
return new Response(JSON.stringify(stats), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
} catch (error) {
return new Response(JSON.stringify({ error: error.message }), {
status: 500,
headers: { 'Content-Type': 'application/json' },
})
}
}

View File

@ -1,5 +1,6 @@
import React from 'react'; import React from 'react';
import BotInfo from "../home/bot-info.jsx"; import BotInfo from "../home/bot-info.jsx";
import Network from "../home/network.jsx";
import System from "../home/system.jsx"; import System from "../home/system.jsx";
export default function Home({ }) { export default function Home({ }) {
@ -7,24 +8,7 @@ export default function Home({ }) {
<div className="container mx-auto p-8"> <div className="container mx-auto p-8">
<BotInfo /> <BotInfo />
<System /> <System />
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8"> <Network />
{/* 监控卡片 */ }
<div className="card bg-base-100 shadow-xl col-span-1 lg:col-span-3">
<div className="card-body">
<h2 className="card-title text-lg font-bold">监控</h2>
<div className="flex justify-between">
<div>
<p>上传: 0.87 KB/s</p>
<p>下载: 3.21 KB/s</p>
</div>
<div>
<p>总发送: 21.17 GB</p>
<p>总接收: 90.46 GB</p>
</div>
</div>
</div>
</div>
</div>
</div> </div>
); );
} }

View File

@ -0,0 +1,141 @@
import React, { useEffect, useState } from "react";
import { Line } from "react-chartjs-2";
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend
} from 'chart.js';
ChartJS.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend
);
const MAX_DATA_POINTS = 30;
export default function Network() {
const [networkData, setNetworkData] = useState({
uploadSpeed: 0,
downloadSpeed: 0,
totalSent: 0,
totalReceived: 0
});
const [chartData, setChartData] = useState({
labels: [],
datasets: [
{
label: '上传速度 (KB/s)',
data: [],
borderColor: 'rgb(75, 192, 192)',
tension: 0.1
},
{
label: '下载速度 (KB/s)',
data: [],
borderColor: 'rgb(255, 99, 132)',
tension: 0.1
}
]
});
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('/r/api/network2');
const data = await response.json();
setNetworkData({
uploadSpeed: data.uploadSpeed,
downloadSpeed: data.downloadSpeed,
totalSent: data.totalSent,
totalReceived: data.totalReceived
});
setChartData(prevData => {
const newLabels = [...prevData.labels, new Date().toLocaleTimeString()];
const newUploadData = [...prevData.datasets[0].data, data.uploadSpeed];
const newDownloadData = [...prevData.datasets[1].data, data.downloadSpeed];
// 30
if (newLabels.length > MAX_DATA_POINTS) {
newLabels.shift();
newUploadData.shift();
newDownloadData.shift();
}
return {
labels: newLabels,
datasets: [
{
...prevData.datasets[0],
data: newUploadData
},
{
...prevData.datasets[1],
data: newDownloadData
}
]
};
});
} catch (error) {
console.error('获取网络数据失败:', error);
}
};
//
const interval = setInterval(fetchData, 1000);
return () => clearInterval(interval);
}, []);
const chartOptions = {
responsive: true,
animation: {
duration: 0
},
scales: {
y: {
beginAtZero: true
}
},
plugins: {
legend: {
position: 'top'
}
}
};
return (
<div className="container mx-auto p-8">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
<div className="card bg-base-100 shadow-xl col-span-1 lg:col-span-3">
<div className="card-body">
<h2 className="card-title text-lg font-bold">网络监控</h2>
<div className="flex justify-between mb-4">
<div>
<p>上传: {networkData.uploadSpeed} KB/s</p>
<p>下载: {networkData.downloadSpeed} KB/s</p>
</div>
<div>
<p>总发送: {networkData.totalSent} GB</p>
<p>总接收: {networkData.totalReceived} GB</p>
</div>
</div>
<div className="h-[300px]">
<Line data={chartData} options={chartOptions} />
</div>
</div>
</div>
</div>
</div>
);
}