mirror of
https://github.com/Jerryplusy/rc-plugin.git
synced 2025-10-14 08:09:19 +00:00
🎈 pref: 优化网络监测组件
This commit is contained in:
parent
6afdf6972c
commit
be8c95e6fd
@ -4,13 +4,16 @@
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"axios": "^1.3.4",
|
||||
"chart.js": "^4.4.6",
|
||||
"form-data": "^4.0.1",
|
||||
"js-yaml": "^4.1.0",
|
||||
"next": "^14.2.16",
|
||||
"node-id3": "^0.2.6",
|
||||
"os-utils": "^0.0.14",
|
||||
"p-queue": "^8.0.1",
|
||||
"qrcode": "^1.5.3",
|
||||
"react": "^18.3.1",
|
||||
"react-chartjs-2": "^5.2.0",
|
||||
"react-circular-progressbar": "^2.1.0",
|
||||
"react-dom": "^18.3.1",
|
||||
"systeminformation": "^5.23.5"
|
||||
|
56
server/app/r/api/network2/route.js
Normal file
56
server/app/r/api/network2/route.js
Normal 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' },
|
||||
})
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import BotInfo from "../home/bot-info.jsx";
|
||||
import Network from "../home/network.jsx";
|
||||
import System from "../home/system.jsx";
|
||||
|
||||
export default function Home({ }) {
|
||||
@ -7,24 +8,7 @@ export default function Home({ }) {
|
||||
<div className="container mx-auto p-8">
|
||||
<BotInfo />
|
||||
<System />
|
||||
<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">
|
||||
<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>
|
||||
<Network />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
141
server/components/home/network.jsx
Normal file
141
server/components/home/network.jsx
Normal 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>
|
||||
);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user