关键位现价改与顶栏同源公开行情,前端无价时回退 nav tickers。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-09-30 23:56:40 +08:00
parent ee635bcd55
commit e7cafd6dbc
5 changed files with 119 additions and 36 deletions
+66 -7
View File
@@ -1,5 +1,6 @@
/**
* 表单币种输入:防抖 + 定时刷新,展示交易所最新价(/api/order_defaults).
* BTC/ETH 在 order_defaults 无价时回退 /api/nav_spot_tickers(与顶栏同源).
*/
(function (global) {
"use strict";
@@ -65,6 +66,41 @@
el.title = "交易所最新价(约 " + pollMs() / 1000 + "s 刷新)";
}
function symbolBase(sym) {
return String(sym || "")
.trim()
.toUpperCase()
.split("/")[0]
.split(":")[0];
}
function fetchNavLast(sym) {
const base = symbolBase(sym);
if (base !== "BTC" && base !== "ETH") {
return Promise.resolve(null);
}
return fetch("/api/nav_spot_tickers")
.then(function (r) {
return r.json().catch(function () {
return null;
});
})
.then(function (d) {
if (!d || !d.ok || !Array.isArray(d.tickers)) return null;
for (let i = 0; i < d.tickers.length; i++) {
const t = d.tickers[i] || {};
if (String(t.base || "").toUpperCase() === base && t.last != null) {
const n = Number(t.last);
return Number.isFinite(n) && n > 0 ? n : null;
}
}
return null;
})
.catch(function () {
return null;
});
}
function bindOne(el) {
if (!el || bound.has(el)) return;
bound.add(el);
@@ -87,6 +123,15 @@
pollTimer = setInterval(refresh, pollMs());
}
function applyPrice(sym, px) {
if (px === null || typeof px === "undefined") {
paint(el, sym, null, "无法读取交易所价格");
return;
}
paint(el, sym, px, "");
if (!pollTimer) startPoll();
}
function refresh() {
const symEl = $(symId);
const sym = symbolValue(symEl);
@@ -116,21 +161,35 @@
el.classList.remove("symbol-live-price--loading");
const data = res.data || {};
if (res.status >= 400 || !data || !data.ok) {
paint(el, sym, null, (data && data.msg) || "读取失败");
return;
return fetchNavLast(sym).then(function (navPx) {
if (seq !== fetchSeq) return;
if (navPx != null) {
applyPrice(sym, navPx);
return;
}
paint(el, sym, null, (data && data.msg) || "读取失败");
});
}
const px = data.last_price != null ? data.last_price : data.price;
if (px === null || typeof px === "undefined") {
paint(el, data.symbol || sym, null, "无法读取交易所价格");
return;
return fetchNavLast(sym).then(function (navPx) {
if (seq !== fetchSeq) return;
applyPrice(data.symbol || sym, navPx);
});
}
paint(el, data.symbol || sym, px, "");
if (!pollTimer) startPoll();
applyPrice(data.symbol || sym, px);
})
.catch(function () {
if (seq !== fetchSeq) return;
el.classList.remove("symbol-live-price--loading");
paint(el, sym, null, "网络错误");
fetchNavLast(sym).then(function (navPx) {
if (seq !== fetchSeq) return;
if (navPx != null) {
applyPrice(sym, navPx);
return;
}
paint(el, sym, null, "网络错误");
});
});
}
+1 -1
View File
@@ -135,7 +135,7 @@ const ORDER_ENTRY_MODEL_CODE_TO_CATEGORY = {{ entry_model_code_to_category | toj
</script>
<script src="/static/order_entry_model.js?v=5"></script>
<script src="/static/manual_order_rr_preview.js?v=5"></script>
<script src="/static/symbol_live_price.js?v=2"></script>
<script src="/static/symbol_live_price.js?v=3"></script>
<script src="/static/key_monitor_form.js?v=2"></script>
<script src="/static/instance_stats.js?v=5"></script>
{% include 'embed_boot_scripts.html' %}
+1 -1
View File
@@ -458,7 +458,7 @@ const ORDER_ENTRY_MODEL_CODE_TO_CATEGORY = {{ entry_model_code_to_category | toj
</script>
<script src="/static/order_entry_model.js?v=5"></script>
<script src="/static/manual_order_rr_preview.js?v=5"></script>
<script src="/static/symbol_live_price.js?v=2"></script>
<script src="/static/symbol_live_price.js?v=3"></script>
<script src="/static/strategy_roll.js?v=6"></script>
<script src="/static/instance_stats.js?v=5"></script>
<script>
+1 -1
View File
@@ -5,7 +5,7 @@
<script src="/static/instance_theme.js?v=5"></script>
<title>{{ exchange_display }} | 关键位放大</title>
<link rel="stylesheet" href="/static/instance_theme.css?v=50">
<script src="/static/symbol_live_price.js?v=2"></script>
<script src="/static/symbol_live_price.js?v=3"></script>
<link rel="stylesheet" href="/static/focus_chart_page.css?v=1">
</head>
<body class="focus-page" data-price-refresh-ms="{{ price_refresh_seconds * 1000 }}">