This commit is contained in:
Donald Zou
2025-08-27 17:48:28 +08:00
parent 48ec4c7f6f
commit 45524eaee5
3 changed files with 203 additions and 64 deletions

View File

@@ -1,3 +1,5 @@
import shutil
import subprocess
import time import time
import threading import threading
import psutil import psutil
@@ -29,6 +31,7 @@ class SystemStatus:
}, },
"Disks": self.Disks, "Disks": self.Disks,
"NetworkInterfaces": self.NetworkInterfaces, "NetworkInterfaces": self.NetworkInterfaces,
"NetworkInterfacesPriority": self.NetworkInterfaces.getInterfacePriorities(),
"Processes": self.Processes "Processes": self.Processes
} }
@@ -117,7 +120,23 @@ class Disk:
class NetworkInterfaces: class NetworkInterfaces:
def __init__(self): def __init__(self):
self.interfaces = {} self.interfaces = {}
def getInterfacePriorities(self):
if shutil.which("ip"):
result = subprocess.check_output(["ip", "route", "show"]).decode()
priorities = {}
for line in result.splitlines():
if "metric" in line and "dev" in line:
parts = line.split()
dev = parts[parts.index("dev")+1]
metric = int(parts[parts.index("metric")+1])
if dev not in priorities:
priorities[dev] = metric
return priorities
return {}
def getData(self): def getData(self):
self.interfaces.clear()
try: try:
network = psutil.net_io_counters(pernic=True, nowrap=True) network = psutil.net_io_counters(pernic=True, nowrap=True)
for i in network.keys(): for i in network.keys():

View File

@@ -0,0 +1,161 @@
<script setup lang="ts">
import {computed} from "vue";
import {
Chart,
LineElement,
BarElement,
BarController,
LineController,
LinearScale,
Legend,
Title,
Tooltip,
CategoryScale,
PointElement,
Filler
} from 'chart.js';
import {Line} from "vue-chartjs";
Chart.register(
LineElement,
BarElement,
BarController,
LineController,
LinearScale,
Legend,
Title,
Tooltip,
CategoryScale,
PointElement,
Filler
);
import {GetLocale} from "@/utilities/locale.js";
import LocaleText from "@/components/text/localeText.vue";
const props = defineProps([
'historicalChartTimestamp', 'historicalNetworkSpeed',
'interfaceName', 'interface'
])
const networkSpeedChartOption = computed(() => {
return {
responsive: true,
plugins: {
legend: {
display: true
},
tooltip: {
callbacks: {
label: (tooltipItem) => {
return `${tooltipItem.formattedValue} MB/s`
}
}
}
},
scales: {
x: {
ticks: {
display: false,
},
grid: {
display: false
},
},
y:{
ticks: {
callback: (val, index) => {
return `${Math.round(val * 10000) / 10000} MB/s`
}
},
grid: {
display: false
},
}
}
}
})
const networkSpeedHistoricalChartData = computed(() => {
return {
labels: [...props.historicalChartTimestamp],
datasets: [
{
label: GetLocale('Real Time Received Data Usage'),
data: [...props.historicalNetworkSpeed.bytes_recv],
fill: 'origin',
borderColor: '#0dcaf0',
backgroundColor: '#0dcaf090',
tension: 0,
pointRadius: 2,
borderWidth: 1,
},
{
label: GetLocale('Real Time Sent Data Usage'),
data: [...props.historicalNetworkSpeed.bytes_sent],
fill: 'origin',
backgroundColor: '#ffc10790',
borderColor: '#ffc107',
tension: 0,
pointRadius: 2,
borderWidth: 1,
}
]
}
})
</script>
<template>
<div
class="col-sm-6 fadeIn d-flex gap-2 flex-column">
<div>
<div class="d-flex mb-2">
<h6 class="mb-0">
<samp>{{interfaceName}}</samp>
</h6>
<h6 class="mb-0 ms-auto d-flex gap-2">
<span class="text-info">
<i class="bi bi-arrow-down"></i>
{{ Math.round((interface.bytes_recv / 1024000000 + Number.EPSILON) * 10000) / 10000}} GB
</span>
<span class="text-warning">
<i class="bi bi-arrow-up"></i>
{{ Math.round((interface.bytes_sent / 1024000000 + Number.EPSILON) * 10000) / 10000}} GB
</span>
</h6>
</div>
<div class="progress" role="progressbar" style="height: 10px">
<div class="progress-bar bg-info"
v-if="interface.bytes_recv > 0"
:style="{width: `${(interface.bytes_recv / (interface.bytes_sent + interface.bytes_recv)) * 100}%` }"></div>
<div class="progress-bar bg-warning"
v-if="interface.bytes_sent > 0"
:style="{width: `${(interface.bytes_sent / (interface.bytes_sent + interface.bytes_recv)) * 100}%` }"></div>
</div>
</div>
<div class="card rounded-3">
<div class="card-header d-flex align-items-center gap-3">
<small>
<LocaleText t="Realtime Speed"></LocaleText>
</small>
<small class="text-info ms-auto">
<i class="bi bi-arrow-down-circle me-2"></i>
{{ historicalNetworkSpeed.bytes_recv[historicalNetworkSpeed.bytes_recv.length - 1] }} MB/s
</small>
<small class="text-warning">
<i class="bi bi-arrow-up-circle me-2"></i>
{{ historicalNetworkSpeed.bytes_sent[historicalNetworkSpeed.bytes_sent.length - 1] }} MB/s
</small>
</div>
<div class="card-body">
<Line
:options="networkSpeedChartOption"
:data="networkSpeedHistoricalChartData"
style="width: 100%; height: 300px; max-height: 300px"
></Line>
</div>
</div>
</div>
</template>
<style scoped>
</style>

View File

@@ -1,5 +1,5 @@
<script setup> <script setup>
import {computed, onBeforeUnmount, onMounted, ref} from "vue"; import {computed, onBeforeUnmount, onMounted, reactive, ref} from "vue";
import {fetchGet} from "@/utilities/fetch.js"; import {fetchGet} from "@/utilities/fetch.js";
import LocaleText from "@/components/text/localeText.vue"; import LocaleText from "@/components/text/localeText.vue";
import CpuCore from "@/components/systemStatusComponents/cpuCore.vue"; import CpuCore from "@/components/systemStatusComponents/cpuCore.vue";
@@ -29,6 +29,7 @@ import {
import {Line} from "vue-chartjs"; import {Line} from "vue-chartjs";
import dayjs from "dayjs"; import dayjs from "dayjs";
import {GetLocale} from "@/utilities/locale.js"; import {GetLocale} from "@/utilities/locale.js";
import NetworkInterface from "@/components/systemStatusComponents/networkInterface.vue";
Chart.register( Chart.register(
LineElement, LineElement,
BarElement, BarElement,
@@ -62,9 +63,8 @@ const historicalNetworkData = ref({
bytes_recv: [], bytes_recv: [],
bytes_sent: [] bytes_sent: []
}) })
const historicalNetworkSpeed = ref({ const historicalNetworkSpeed = reactive({
bytes_recv: [],
bytes_sent: []
}) })
const getData = () => { const getData = () => {
@@ -75,23 +75,16 @@ const getData = () => {
historicalVirtualMemoryUsage.value.push(res.data.Memory.VirtualMemory.percent) historicalVirtualMemoryUsage.value.push(res.data.Memory.VirtualMemory.percent)
historicalSwapMemoryUsage.value.push(res.data.Memory.SwapMemory.percent) historicalSwapMemoryUsage.value.push(res.data.Memory.SwapMemory.percent)
historicalNetworkSpeed.value.bytes_recv.push( for (let i of Object.keys(res.data.NetworkInterfaces)){
Object.values(res.data.NetworkInterfaces).map(x => x.realtime.recv).reduce((x, y) => x + y) if (!Object.keys(historicalNetworkSpeed).includes(i)){
) historicalNetworkSpeed[i] = {
historicalNetworkSpeed.value.bytes_sent.push( bytes_recv: [],
Object.values(res.data.NetworkInterfaces).map(x => x.realtime.sent).reduce((x, y) => x + y) bytes_sent: []
) }
}
// if (historicalNetworkData.value.bytes_recv.length === 1 && historicalNetworkData.value.bytes_sent.length === 1){ historicalNetworkSpeed[i].bytes_recv.push(res.data.NetworkInterfaces[i].realtime.recv)
// historicalNetworkSpeed.value.bytes_recv.push(0) historicalNetworkSpeed[i].bytes_sent.push(res.data.NetworkInterfaces[i].realtime.sent)
// historicalNetworkSpeed.value.bytes_sent.push(0) }
// }else{
// let bytes_recv_diff = historicalNetworkData.value.bytes_recv[historicalNetworkData.value.bytes_recv.length - 1] - historicalNetworkData.value.bytes_recv[historicalNetworkData.value.bytes_recv.length - 2]
// let bytes_sent_diff = historicalNetworkData.value.bytes_sent[historicalNetworkData.value.bytes_sent.length - 1] - historicalNetworkData.value.bytes_sent[historicalNetworkData.value.bytes_sent.length - 2]
// historicalNetworkSpeed.value.bytes_recv.push(Math.round(((bytes_recv_diff / 1024 / 1024) + Number.EPSILON) * 10000) / 10000)
// historicalNetworkSpeed.value.bytes_sent.push(Math.round(((bytes_sent_diff / 1024 / 1024) + Number.EPSILON) * 10000) / 10000)
// }
}) })
} }
@@ -381,50 +374,16 @@ const networkSpeedHistoricalChartData = computed(() => {
</h3> </h3>
</div> </div>
<div> <div>
<h5 class="mb-0 text-end" v-if="data">
<span class="text-info">
<i class="bi bi-arrow-down"></i>
{{ historicalNetworkSpeed.bytes_recv[historicalNetworkSpeed.bytes_recv.length - 1] }} MB/s
</span>
<span class="text-warning">
<i class="bi bi-arrow-up"></i>
{{ historicalNetworkSpeed.bytes_sent[historicalNetworkSpeed.bytes_sent.length - 1] }} MB/s
</span>
</h5>
</div> </div>
<Line <div v-if="data" class="row g-4">
:options="networkSpeedChartOption" <NetworkInterface
:data="networkSpeedHistoricalChartData" v-for="key in Object.keys(data.NetworkInterfaces).sort()"
style="width: 100%; height: 300px; max-height: 300px" :interface="data.NetworkInterfaces[key]"
></Line> :interfaceName="key"
<div v-if="data" class="row g-3"> :historicalChartTimestamp="historicalChartTimestamp"
<div v-for="key in Object.keys(data.NetworkInterfaces).sort()" :historicalNetworkSpeed="historicalNetworkSpeed[key]"
class="col-sm-6 fadeIn"> :key="key"
<div class="d-flex mb-2"> ></NetworkInterface>
<h6 class="mb-0">
<samp>{{key}}</samp>
</h6>
<h6 class="mb-0 ms-auto d-flex gap-2">
<span class="text-info">
<i class="bi bi-arrow-down"></i>
{{ Math.round((data.NetworkInterfaces[key].bytes_recv / 1024000000 + Number.EPSILON) * 10000) / 10000}} GB
</span>
<span class="text-warning">
<i class="bi bi-arrow-up"></i>
{{ Math.round((data.NetworkInterfaces[key].bytes_sent / 1024000000 + Number.EPSILON) * 10000) / 10000}} GB
</span>
</h6>
</div>
<div class="progress" role="progressbar" style="height: 10px">
<div class="progress-bar bg-info"
v-if="data.NetworkInterfaces[key].bytes_recv > 0"
:style="{width: `${(data.NetworkInterfaces[key].bytes_recv / (data.NetworkInterfaces[key].bytes_sent + data.NetworkInterfaces[key].bytes_recv)) * 100}%` }"></div>
<div class="progress-bar bg-warning"
v-if="data.NetworkInterfaces[key].bytes_sent > 0"
:style="{width: `${(data.NetworkInterfaces[key].bytes_sent / (data.NetworkInterfaces[key].bytes_sent + data.NetworkInterfaces[key].bytes_recv)) * 100}%` }"></div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>