feat: daily volume top20 rank per exchange in market page
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2928,6 +2928,117 @@ body.login-page {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.market-field-symbol .market-symbol-wrap {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: 6px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.market-field-symbol .market-symbol-wrap > input {
|
||||
flex: 1;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.market-vol-rank {
|
||||
position: relative;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.market-vol-rank > summary {
|
||||
list-style: none;
|
||||
cursor: pointer;
|
||||
height: 100%;
|
||||
min-height: 34px;
|
||||
padding: 0 10px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
border: 1px solid var(--border-soft);
|
||||
border-radius: 6px;
|
||||
background: var(--inset-surface);
|
||||
color: var(--accent);
|
||||
font-size: 0.78rem;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.market-vol-rank > summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.market-vol-rank[open] > summary {
|
||||
border-color: rgba(0, 255, 157, 0.35);
|
||||
background: rgba(0, 255, 157, 0.08);
|
||||
}
|
||||
|
||||
.market-vol-rank-panel {
|
||||
position: absolute;
|
||||
top: calc(100% + 4px);
|
||||
right: 0;
|
||||
z-index: 30;
|
||||
width: min(320px, 72vw);
|
||||
max-height: 360px;
|
||||
overflow: auto;
|
||||
border: 1px solid var(--border-soft);
|
||||
border-radius: 8px;
|
||||
background: var(--panel-bg, #1a1f2e);
|
||||
box-shadow: 0 10px 28px rgba(0, 0, 0, 0.4);
|
||||
padding: 8px 0 6px;
|
||||
}
|
||||
|
||||
.market-vol-rank-meta {
|
||||
padding: 0 10px 6px;
|
||||
font-size: 0.68rem;
|
||||
color: var(--muted);
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.market-vol-rank-list {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.market-vol-rank-item {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: 28px 1fr auto;
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
padding: 6px 10px;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: var(--text);
|
||||
font-size: 0.8rem;
|
||||
font-family: var(--font);
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.market-vol-rank-item:hover {
|
||||
background: var(--inset-surface);
|
||||
}
|
||||
|
||||
.market-vol-rank-item.is-active {
|
||||
background: rgba(0, 255, 157, 0.1);
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.market-vol-rank-no {
|
||||
color: var(--muted);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.market-vol-rank-sym {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.market-vol-rank-vol {
|
||||
color: var(--muted);
|
||||
font-size: 0.72rem;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.market-draw-menu {
|
||||
position: fixed;
|
||||
z-index: 1200;
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" media="print" onload="this.media='all'" />
|
||||
<noscript><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" /></noscript>
|
||||
<link rel="stylesheet" href="/assets/app.css?v=20260608-market-draw-v6" />
|
||||
<link rel="stylesheet" href="/assets/app.css?v=20260608-market-vol-rank" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="app-bg" aria-hidden="true"></div>
|
||||
@@ -80,9 +80,18 @@
|
||||
<span>交易所</span>
|
||||
<select id="market-exchange"></select>
|
||||
</label>
|
||||
<label class="market-field">
|
||||
<label class="market-field market-field-symbol">
|
||||
<span>币种</span>
|
||||
<input id="market-symbol" type="text" value="BTC/USDT" placeholder="BTC/USDT" autocomplete="off" />
|
||||
<div class="market-symbol-wrap">
|
||||
<input id="market-symbol" type="text" value="BTC/USDT" placeholder="BTC/USDT" autocomplete="off" />
|
||||
<details id="market-vol-rank" class="market-vol-rank">
|
||||
<summary title="昨日成交额 Top20(每早8点更新)">Top20</summary>
|
||||
<div class="market-vol-rank-panel">
|
||||
<div id="market-vol-rank-meta" class="market-vol-rank-meta">加载中…</div>
|
||||
<ol id="market-vol-rank-list" class="market-vol-rank-list"></ol>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</label>
|
||||
<label class="market-field">
|
||||
<span>周期</span>
|
||||
@@ -385,8 +394,8 @@
|
||||
|
||||
<div id="toast"></div>
|
||||
<script src="https://unpkg.com/lightweight-charts@4.2.0/dist/lightweight-charts.standalone.production.js"></script>
|
||||
<script src="/assets/chart_draw.js?v=20260608-market-draw-v6"></script>
|
||||
<script src="/assets/chart.js?v=20260608-market-draw-v6"></script>
|
||||
<script src="/assets/chart_draw.js?v=20260608-market-vol-rank"></script>
|
||||
<script src="/assets/chart.js?v=20260608-market-vol-rank"></script>
|
||||
<script src="/assets/archive.js?v=20260607-hub-archive-v6"></script>
|
||||
<script src="/assets/ai_review_render.js?v=2"></script>
|
||||
<script src="/assets/app.js?v=20260607-hub-archive-v1"></script>
|
||||
|
||||
Reference in New Issue
Block a user