From df405cc076294ecb5bb6778318c30a68658ee20e Mon Sep 17 00:00:00 2001
From: stqfdyr <89149493+stqfdyr@users.noreply.github.com>
Date: Wed, 23 Sep 2026 18:26:18 +0800
Subject: [PATCH] =?UTF-8?q?fix:=20=E6=81=A2=E5=A4=8D=E5=AE=9E=E6=97=B6?=
=?UTF-8?q?=E6=95=B0=E5=AD=97=E7=9A=84=E5=AE=9A=E5=AE=BD=E6=A7=BD=E4=BD=8D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
#7 在改到期天数时连带删掉了 #4 的 `Num` 槽位:摘要行、表格网速列、展开详情的网速行重新按最宽形态预留宽度,数字变化时两侧不再跳动。到期天数仍由 `expiresIn` 给出。
---
src/components/ServerTable.tsx | 66 +++++++++++++++++++++++++++++++---
1 file changed, 61 insertions(+), 5 deletions(-)
diff --git a/src/components/ServerTable.tsx b/src/components/ServerTable.tsx
index 1ecd696..061b856 100644
--- a/src/components/ServerTable.tsx
+++ b/src/components/ServerTable.tsx
@@ -105,6 +105,37 @@ function Bar({ pct, label }: { pct: number | null; label?: string }) {
)
}
+// The widest form each formatter writes, in `ch`, measured with tabular figures.
+// M is the widest unit letter, so each is measured in megabytes rather than the
+// gigabytes a reading is more often in: `compact` spans "0B" to "1023M", that is
+// 2.2 to 5.49; `bytes` reaches 7.19 at "1023 MB"; `rate` 10.09 at "1023.0 MB/s".
+// Rounded up, since other UI fonts are a few percent wider than the one these
+// were measured in.
+const SLOT = { compact: 5.6, bytes: 7.3, rate: 10.2 }
+
+/**
+ * A figure that changes on every push, held in a slot wide enough for the widest
+ * form it can take, so a node moving from 19K/s to 8.19K/s leaves the rest of the
+ * line where it was. Right-aligned, so the unit keeps its place and the digits
+ * grow towards the arrow instead.
+ *
+ * `ch` is the width of a digit under the tabular figures this selects, so a slot
+ * follows whatever size it is drawn at, down to the 10px the table uses on a
+ * phone. The width travels as a custom property rather than `min-width` itself,
+ * which is what allows a caller to drop the reservation where the column is too
+ * narrow to hold it: an inline style would outrank the class that does so.
+ */
+function Num({ ch, className, children }: { ch: number; className?: string; children: ReactNode }) {
+ return (
+
+ {children}
+
+ )
+}
+
function Expiry({ node }: { node: Node }) {
const days = expiresIn(node)
if (days === null) return {FOREVER}
@@ -181,7 +212,15 @@ function Details({ node }: { node: Node }) {