feat: 单位切换按钮(Mbps / MB/s,仅影响显示,数据库仍存 Mbps)
This commit is contained in:
@@ -63,8 +63,25 @@
|
|||||||
#startBtn:hover { transform: translateY(-1px); filter: brightness(1.08); }
|
#startBtn:hover { transform: translateY(-1px); filter: brightness(1.08); }
|
||||||
#startBtn:disabled { opacity: .55; cursor: not-allowed; transform: none; }
|
#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 {
|
.stat {
|
||||||
background: var(--card); border: 1px solid var(--border); border-radius: 14px;
|
background: var(--card); border: 1px solid var(--border); border-radius: 14px;
|
||||||
padding: 16px 10px; text-align: center;
|
padding: 16px 10px; text-align: center;
|
||||||
@@ -160,6 +177,14 @@
|
|||||||
<button id="startBtn">开始测速</button>
|
<button id="startBtn">开始测速</button>
|
||||||
</section>
|
</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">
|
<section class="stats">
|
||||||
<div class="stat" id="cardLatency">
|
<div class="stat" id="cardLatency">
|
||||||
@@ -221,6 +246,44 @@ const statUpload = document.getElementById('statUpload');
|
|||||||
let running = false;
|
let running = false;
|
||||||
let gaugeMode = 'speed'; // speed | latency
|
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) {
|
function drawGauge(frac) {
|
||||||
const ctx = gauge.getContext('2d');
|
const ctx = gauge.getContext('2d');
|
||||||
@@ -267,8 +330,10 @@ function speedFrac(mbps) {
|
|||||||
|
|
||||||
function updateGaugeSpeed(mbps) {
|
function updateGaugeSpeed(mbps) {
|
||||||
gaugeMode = 'speed';
|
gaugeMode = 'speed';
|
||||||
gaugeValue.textContent = (mbps >= 100 ? mbps.toFixed(0) : mbps.toFixed(1));
|
lastGaugeMbps = mbps;
|
||||||
gaugeUnit.textContent = '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));
|
drawGauge(speedFrac(mbps));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,8 +615,8 @@ function renderRanking(rows) {
|
|||||||
'<td><span class="rank-no ' + cls + '">' + r.rank + '</span></td>' +
|
'<td><span class="rank-no ' + cls + '">' + r.rank + '</span></td>' +
|
||||||
'<td>' + user + (r.is_mine ? '<span class="mine-tag">我的成绩</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-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-dl">' + fmtSpeed(r.download_mbps) + ' <span class="unit-sm">' + unit + '</span></td>' +
|
||||||
'<td class="val-up">' + r.upload_mbps.toFixed(2) + ' <span class="unit-sm">Mbps</span></td>' +
|
'<td class="val-up">' + fmtSpeed(r.upload_mbps) + ' <span class="unit-sm">' + unit + '</span></td>' +
|
||||||
'<td class="time">' + r.created_at + '</td>' +
|
'<td class="time">' + r.created_at + '</td>' +
|
||||||
'</tr>';
|
'</tr>';
|
||||||
}).join('');
|
}).join('');
|
||||||
@@ -606,14 +671,16 @@ async function runTest() {
|
|||||||
// 2. 下载(固定 10 秒)
|
// 2. 下载(固定 10 秒)
|
||||||
setPhase('下载测速准备中…');
|
setPhase('下载测速准备中…');
|
||||||
const download = await downloadTest();
|
const download = await downloadTest();
|
||||||
statDownload.textContent = download.toFixed(2);
|
lastResult = { download, upload: 0 };
|
||||||
|
statDownload.textContent = fmtSpeed(download);
|
||||||
updateGaugeSpeed(download);
|
updateGaugeSpeed(download);
|
||||||
markDone(document.getElementById('cardDownload'));
|
markDone(document.getElementById('cardDownload'));
|
||||||
|
|
||||||
// 3. 上传(固定 10 秒)
|
// 3. 上传(固定 10 秒)
|
||||||
setPhase('上传测速准备中…');
|
setPhase('上传测速准备中…');
|
||||||
const upload = await uploadTest();
|
const upload = await uploadTest();
|
||||||
statUpload.textContent = upload.toFixed(2);
|
lastResult = { download, upload };
|
||||||
|
statUpload.textContent = fmtSpeed(upload);
|
||||||
updateGaugeSpeed(upload);
|
updateGaugeSpeed(upload);
|
||||||
markDone(document.getElementById('cardUpload'));
|
markDone(document.getElementById('cardUpload'));
|
||||||
|
|
||||||
@@ -640,6 +707,7 @@ startBtn.addEventListener('click', runTest);
|
|||||||
|
|
||||||
/* ================= 初始化 ================= */
|
/* ================= 初始化 ================= */
|
||||||
drawGauge(0);
|
drawGauge(0);
|
||||||
|
updateUnitButtons();
|
||||||
updateSortHeaders();
|
updateSortHeaders();
|
||||||
loadRankings(false);
|
loadRankings(false);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user