feat: 单位切换按钮(Mbps / MB/s,仅影响显示,数据库仍存 Mbps)

This commit is contained in:
dsh
2026-08-17 23:25:58 -04:00
parent b244e33b96
commit faaa68cae1
+75 -7
View File
@@ -63,8 +63,25 @@
#startBtn:hover { transform: translateY(-1px); filter: brightness(1.08); }
#startBtn:disabled { opacity: .55; cursor: not-allowed; transform: none; }
/* ---------- 单位切换 ---------- */
.toolbar { display: flex; justify-content: flex-end; margin-top: 16px; }
.unit-switch {
display: inline-flex; gap: 2px; padding: 3px;
background: var(--card); border: 1px solid var(--border); border-radius: 999px;
}
.unit-btn {
padding: 5px 16px; font-size: 13px; color: var(--muted);
background: transparent; border: none; border-radius: 999px;
cursor: pointer; transition: all .15s;
}
.unit-btn:hover { color: var(--text); }
.unit-btn.active {
color: #06121f; font-weight: 700;
background: linear-gradient(90deg, var(--accent1), var(--accent2));
}
/* ---------- 统计卡片 ---------- */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-top: 18px; }
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-top: 12px; }
.stat {
background: var(--card); border: 1px solid var(--border); border-radius: 14px;
padding: 16px 10px; text-align: center;
@@ -160,6 +177,14 @@
<button id="startBtn">开始测速</button>
</section>
<!-- 单位切换 -->
<div class="toolbar">
<div class="unit-switch">
<button class="unit-btn active" data-unit="Mbps">Mbps</button>
<button class="unit-btn" data-unit="MB/s">MB/s</button>
</div>
</div>
<!-- 结果统计 -->
<section class="stats">
<div class="stat" id="cardLatency">
@@ -221,6 +246,44 @@ const statUpload = document.getElementById('statUpload');
let running = false;
let gaugeMode = 'speed'; // speed | latency
/* ================= 单位切换 =================
* 显示单位:Mbps(兆比特/秒,默认)或 MB/s(兆字节/秒 = Mbps ÷ 8
* 数据库始终以 Mbps 存储,仅影响显示。
*/
let unit = localStorage.getItem('speedtest_unit') === 'MB/s' ? 'MB/s' : 'Mbps';
let lastGaugeMbps = 0; // 仪表盘当前速率(Mbps 原值)
let lastResult = null; // 最近一次测速结果(Mbps 原值)
function fmtSpeed(mbps) {
const v = unit === 'MB/s' ? mbps / 8 : mbps;
return v.toFixed(2);
}
function updateUnitButtons() {
document.querySelectorAll('.unit-btn').forEach(b => {
b.classList.toggle('active', b.dataset.unit === unit);
});
}
// 切换单位后刷新所有速度显示(仪表盘 / 统计卡 / 排行榜)
function refreshSpeedDisplays() {
if (gaugeMode === 'speed') updateGaugeSpeed(lastGaugeMbps);
if (lastResult) {
statDownload.textContent = fmtSpeed(lastResult.download);
statUpload.textContent = fmtSpeed(lastResult.upload);
}
loadRankings(false);
}
document.querySelectorAll('.unit-btn').forEach(b => {
b.addEventListener('click', () => {
unit = b.dataset.unit;
localStorage.setItem('speedtest_unit', unit);
updateUnitButtons();
refreshSpeedDisplays();
});
});
/* ================= 仪表盘 ================= */
function drawGauge(frac) {
const ctx = gauge.getContext('2d');
@@ -267,8 +330,10 @@ function speedFrac(mbps) {
function updateGaugeSpeed(mbps) {
gaugeMode = 'speed';
gaugeValue.textContent = (mbps >= 100 ? mbps.toFixed(0) : mbps.toFixed(1));
gaugeUnit.textContent = 'Mbps';
lastGaugeMbps = mbps;
const v = unit === 'MB/s' ? mbps / 8 : mbps;
gaugeValue.textContent = (v >= 100 ? v.toFixed(0) : v.toFixed(1));
gaugeUnit.textContent = unit;
drawGauge(speedFrac(mbps));
}
@@ -550,8 +615,8 @@ function renderRanking(rows) {
'<td><span class="rank-no ' + cls + '">' + r.rank + '</span></td>' +
'<td>' + user + (r.is_mine ? '<span class="mine-tag">我的成绩</span>' : '') + '</td>' +
'<td class="val-la">' + r.latency_ms.toFixed(1) + ' <span class="unit-sm">ms</span></td>' +
'<td class="val-dl">' + r.download_mbps.toFixed(2) + ' <span class="unit-sm">Mbps</span></td>' +
'<td class="val-up">' + r.upload_mbps.toFixed(2) + ' <span class="unit-sm">Mbps</span></td>' +
'<td class="val-dl">' + fmtSpeed(r.download_mbps) + ' <span class="unit-sm">' + unit + '</span></td>' +
'<td class="val-up">' + fmtSpeed(r.upload_mbps) + ' <span class="unit-sm">' + unit + '</span></td>' +
'<td class="time">' + r.created_at + '</td>' +
'</tr>';
}).join('');
@@ -606,14 +671,16 @@ async function runTest() {
// 2. 下载(固定 10 秒)
setPhase('下载测速准备中…');
const download = await downloadTest();
statDownload.textContent = download.toFixed(2);
lastResult = { download, upload: 0 };
statDownload.textContent = fmtSpeed(download);
updateGaugeSpeed(download);
markDone(document.getElementById('cardDownload'));
// 3. 上传(固定 10 秒)
setPhase('上传测速准备中…');
const upload = await uploadTest();
statUpload.textContent = upload.toFixed(2);
lastResult = { download, upload };
statUpload.textContent = fmtSpeed(upload);
updateGaugeSpeed(upload);
markDone(document.getElementById('cardUpload'));
@@ -640,6 +707,7 @@ startBtn.addEventListener('click', runTest);
/* ================= 初始化 ================= */
drawGauge(0);
updateUnitButtons();
updateSortHeaders();
loadRankings(false);