feat: daily volume top20 rank per exchange in market page

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-08 15:46:36 +08:00
parent 09eb9dc475
commit 4bf0c2363f
11 changed files with 763 additions and 6 deletions
+67
View File
@@ -89,6 +89,9 @@
const elExchange = document.getElementById("market-exchange");
const elSymbol = document.getElementById("market-symbol");
const elVolRankMeta = document.getElementById("market-vol-rank-meta");
const elVolRankList = document.getElementById("market-vol-rank-list");
const elVolRankDetails = document.getElementById("market-vol-rank");
const elTf = document.getElementById("market-timeframe");
const elRefresh = document.getElementById("market-refresh");
const elStatus = document.getElementById("market-status");
@@ -2613,6 +2616,68 @@
void postChartUnwatch();
}
function renderVolumeRank(data) {
if (!elVolRankMeta || !elVolRankList) return;
elVolRankList.innerHTML = "";
if (!data || !data.ok || !data.items || !data.items.length) {
elVolRankMeta.textContent =
(data && data.msg) || "暂无排名数据(请稍后或检查实例 /api/hub/volume-rank";
return;
}
const resetHour = data.reset_hour != null ? data.reset_hour : 8;
const rankDate = data.rank_date || "—";
const updated = data.updated_at || "—";
elVolRankMeta.textContent =
"昨日成交 Top20 · 交易日 " + rankDate + " · 每早 " + resetHour + ":00 更新 · " + updated;
const curSym = (elSymbol && elSymbol.value.trim().toUpperCase()) || "";
data.items.forEach(function (row) {
const li = document.createElement("li");
const btn = document.createElement("button");
btn.type = "button";
btn.className = "market-vol-rank-item";
if (row.symbol && row.symbol.toUpperCase() === curSym) {
btn.classList.add("is-active");
}
btn.dataset.symbol = row.symbol || "";
btn.innerHTML =
'<span class="market-vol-rank-no">' +
(row.rank || "") +
'</span><span class="market-vol-rank-sym">' +
(row.symbol || "") +
'</span><span class="market-vol-rank-vol">' +
(row.volume_label || "") +
"</span>";
btn.addEventListener("click", function () {
if (!elSymbol || !row.symbol) return;
elSymbol.value = row.symbol;
if (elVolRankDetails) elVolRankDetails.open = false;
loadChart(false);
});
li.appendChild(btn);
elVolRankList.appendChild(li);
});
}
async function loadVolumeRank() {
const exKey = (elExchange && elExchange.value) || "";
if (!exKey || !elVolRankMeta) return;
elVolRankMeta.textContent = "加载排名…";
if (elVolRankList) elVolRankList.innerHTML = "";
try {
const r = await fetch(
"/api/chart/volume-rank?exchange_key=" + encodeURIComponent(exKey),
{ credentials: "same-origin" }
);
const data = await r.json();
if (!r.ok) {
throw new Error((data && data.detail) || (data && data.msg) || "加载失败");
}
renderVolumeRank(data);
} catch (e) {
renderVolumeRank({ ok: false, msg: String(e.message || e) });
}
}
async function loadMeta() {
const r = await fetch("/api/chart/meta", { credentials: "same-origin" });
chartMeta = await r.json();
@@ -2628,6 +2693,7 @@
readQuery();
applyDefaults();
updateExchangeDisplay();
void loadVolumeRank();
}
async function loadChart(force, options) {
@@ -2767,6 +2833,7 @@
updateExchangeDisplay();
syncFsToolbarFromMain();
lastViewKey = "";
void loadVolumeRank();
loadChart(false);
});
}