ss
This commit is contained in:
@@ -118,9 +118,17 @@ type HubDashboard = {
|
||||
tx_bytes?: number;
|
||||
rx_packets?: number;
|
||||
tx_packets?: number;
|
||||
rx_bps?: number;
|
||||
tx_bps?: number;
|
||||
sample_interval_seconds?: number;
|
||||
speed_mbps?: number | null;
|
||||
operstate?: string;
|
||||
}>;
|
||||
total_rx_bytes?: number;
|
||||
total_tx_bytes?: number;
|
||||
total_rx_bps?: number;
|
||||
total_tx_bps?: number;
|
||||
sample_interval_seconds?: number;
|
||||
};
|
||||
live_events?: {
|
||||
pm2_tail?: string[];
|
||||
@@ -221,6 +229,11 @@ function formatBytes(value?: number) {
|
||||
return `${n.toFixed(n >= 10 || i === 0 ? 0 : 1)} ${u[i]}`;
|
||||
}
|
||||
|
||||
function formatRate(value?: number) {
|
||||
const text = formatBytes(value);
|
||||
return text === "—" ? text : `${text}/s`;
|
||||
}
|
||||
|
||||
function statusPill(status: string) {
|
||||
if (status === "online" || status === "running")
|
||||
return "bg-emerald-500/15 text-emerald-300 ring-1 ring-emerald-500/30";
|
||||
@@ -1181,11 +1194,26 @@ export default function LiveControlApp() {
|
||||
<div className="rounded-2xl border border-cyan-500/15 bg-gradient-to-br from-cyan-500/[0.07] to-transparent p-5">
|
||||
<h3 className="flex items-center gap-2 text-sm font-semibold text-white">
|
||||
<Wifi className="h-4 w-4 text-cyan-300" />
|
||||
{t("网络流量(累计)", "Network I/O (cumulative)")}
|
||||
{t("网络带宽 / 流量", "Network bandwidth / traffic")}
|
||||
</h3>
|
||||
<p className="mt-1 text-[11px] text-zinc-500">
|
||||
{t("自开机以来各接口收发字节;非实时速率。", "Per-interface RX/TX since boot (not a live bitrate).")}
|
||||
{t(
|
||||
"实时速率由总览自动刷新间隔计算;累计值来自系统网卡计数器。",
|
||||
"Live rates are calculated from dashboard refresh deltas; totals come from kernel counters.",
|
||||
)}
|
||||
</p>
|
||||
<div className="mt-4 grid gap-3 sm:grid-cols-2">
|
||||
<div className="rounded-xl border border-white/[0.06] bg-black/25 px-4 py-3 font-mono text-[11px]">
|
||||
<p className="text-[10px] uppercase tracking-[0.08em] text-cyan-300/70">{t("实时下行", "Live down")}</p>
|
||||
<p className="mt-1 text-lg font-semibold text-cyan-100">{formatRate(dash.network.total_rx_bps)}</p>
|
||||
<p className="mt-1 text-zinc-500">{t("累计", "Total")}: {formatBytes(dash.network.total_rx_bytes)}</p>
|
||||
</div>
|
||||
<div className="rounded-xl border border-white/[0.06] bg-black/25 px-4 py-3 font-mono text-[11px]">
|
||||
<p className="text-[10px] uppercase tracking-[0.08em] text-cyan-300/70">{t("实时上行", "Live up")}</p>
|
||||
<p className="mt-1 text-lg font-semibold text-cyan-100">{formatRate(dash.network.total_tx_bps)}</p>
|
||||
<p className="mt-1 text-zinc-500">{t("累计", "Total")}: {formatBytes(dash.network.total_tx_bytes)}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{(dash.network.interfaces || []).slice(0, 6).map((iface) => (
|
||||
<div
|
||||
@@ -1198,11 +1226,13 @@ export default function LiveControlApp() {
|
||||
{iface.speed_mbps ? `${iface.speed_mbps} Mbps` : t("未知速率", "unknown speed")}
|
||||
</p>
|
||||
<p className="mt-2 text-zinc-500">
|
||||
↓ {formatBytes(iface.rx_bytes)} <span className="text-zinc-600">·</span>{" "}
|
||||
↓ {formatRate(iface.rx_bps)} <span className="text-zinc-600">·</span>{" "}
|
||||
{formatBytes(iface.rx_bytes)} <span className="text-zinc-600">·</span>{" "}
|
||||
{iface.rx_packets?.toLocaleString() ?? "—"} pkt
|
||||
</p>
|
||||
<p className="mt-0.5 text-zinc-500">
|
||||
↑ {formatBytes(iface.tx_bytes)} <span className="text-zinc-600">·</span>{" "}
|
||||
↑ {formatRate(iface.tx_bps)} <span className="text-zinc-600">·</span>{" "}
|
||||
{formatBytes(iface.tx_bytes)} <span className="text-zinc-600">·</span>{" "}
|
||||
{iface.tx_packets?.toLocaleString() ?? "—"} pkt
|
||||
</p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user