Files
crypto_okx/lib/common/static/nav_spot_tickers.js
T
2026-08-17 11:42:19 +08:00

121 lines
3.5 KiB
JavaScript

/**
* 导航栏 BTC/ETH 现货报价:相对北京 08:00 开盘涨跌.
*/
(function (global) {
"use strict";
const DEFAULT_POLL_MS = 5000;
let timer = null;
let inflight = false;
function pollMs() {
const raw =
(document.body && document.body.getAttribute("data-price-refresh-ms")) || "";
const n = Number(raw);
return Number.isFinite(n) && n >= 2000 ? n : DEFAULT_POLL_MS;
}
function fmtPrice(n) {
const v = Number(n);
if (!Number.isFinite(v)) return "—";
const abs = Math.abs(v);
let digits = 2;
if (abs >= 10000) digits = 1;
else if (abs >= 1000) digits = 2;
else if (abs >= 100) digits = 2;
else if (abs >= 1) digits = 3;
else digits = 4;
try {
return v.toLocaleString("en-US", {
minimumFractionDigits: digits,
maximumFractionDigits: digits,
});
} catch (_) {
return v.toFixed(digits);
}
}
function fmtSigned(n, isPct) {
const v = Number(n);
if (!Number.isFinite(v)) return "—";
const abs = Math.abs(v);
let digits = isPct ? 2 : abs >= 100 ? 1 : 2;
if (!isPct && abs < 1) digits = 3;
const body = abs.toLocaleString("en-US", {
minimumFractionDigits: digits,
maximumFractionDigits: digits,
});
const sign = v > 0 ? "" : v < 0 ? "-" : "";
return sign + body + (isPct ? "%" : "");
}
function dirClass(n) {
const v = Number(n);
if (!Number.isFinite(v) || v === 0) return "nav-spot--flat";
return v > 0 ? "nav-spot--up" : "nav-spot--down";
}
function paintRow(row, t) {
if (!row || !t) return;
const lastEl = row.querySelector('[data-field="last"]');
const chgEl = row.querySelector('[data-field="change"]');
const pctEl = row.querySelector('[data-field="change_pct"]');
const dir = dirClass(t.change);
row.classList.remove("nav-spot--up", "nav-spot--down", "nav-spot--flat");
row.classList.add(dir);
if (lastEl) lastEl.textContent = fmtPrice(t.last);
if (chgEl) chgEl.textContent = fmtSigned(t.change, false);
if (pctEl) pctEl.textContent = fmtSigned(t.change_pct, true);
const openHint =
t.open != null
? "开盘 " + fmtPrice(t.open) + " (" + (t.anchor || "BJ 08:00") + ")"
: t.anchor || "BJ 08:00";
row.title = (t.symbol || "") + " " + openHint;
}
function apply(data) {
const root = document.getElementById("nav-spot-tickers");
if (!root) return;
const list = (data && data.tickers) || [];
list.forEach(function (t) {
const base = (t.base || "").toUpperCase();
if (!base) return;
const row = root.querySelector('.nav-spot-row[data-base="' + base + '"]');
paintRow(row, t);
});
}
function refresh() {
const root = document.getElementById("nav-spot-tickers");
if (!root || inflight) return;
inflight = true;
fetch("/api/nav_spot_tickers")
.then(function (r) {
return r.json();
})
.then(function (data) {
if (data && data.ok !== false) apply(data);
})
.catch(function () {})
.finally(function () {
inflight = false;
});
}
function start() {
if (!document.getElementById("nav-spot-tickers")) return;
refresh();
if (timer) clearInterval(timer);
timer = setInterval(refresh, pollMs());
}
global.refreshNavSpotTickers = refresh;
global.startNavSpotTickers = start;
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", start);
} else {
start();
}
})(window);