Fix order_popup flag through SSO and hide stats in hub order popup.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -76,14 +76,15 @@
|
||||
<span style="color:#8892b0;font-size:.75rem">统计页仍按北京时间 {{ stats_bundle.stats_reset_hour|default(reset_hour) }}:00 切日</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="export-bar instance-desktop-only{% if order_popup %} embed-order-popup-hide{% endif %}">
|
||||
{% if not order_popup %}
|
||||
<div class="export-bar instance-desktop-only">
|
||||
<span style="color:#9aa">数据导出(v{{ data_export_version }} CSV,UTF-8;交易记录含开仓类型列,复盘单独导出):</span>
|
||||
<a href="/export/trade_records">交易记录</a>
|
||||
<a href="/export/journal_entries">复盘记录</a>
|
||||
<a href="/export/key_monitors">关键位(当前)</a>
|
||||
<a href="/export/key_monitor_history">关键位历史</a>
|
||||
</div>
|
||||
<div class="stat-box instance-desktop-only{% if order_popup %} embed-order-popup-hide{% endif %}">
|
||||
<div class="stat-box instance-desktop-only">
|
||||
<div class="stat-item"><div class="label">交易所</div><div class="value">{{ exchange_display }}</div></div>
|
||||
<div class="stat-item"><div class="label">总交易</div><div class="value" id="stat-total">{{ total }}</div></div>
|
||||
<div class="stat-item"><div class="label">错过次数</div><div class="value" id="stat-miss">{{ miss_count }}</div></div>
|
||||
@@ -92,6 +93,7 @@
|
||||
<div class="stat-item"><div class="label">交易日</div><div class="value">{{ trading_day }}</div></div>
|
||||
<div class="stat-item"><div class="label">当日资金(交易账户)</div><div class="value" id="current-capital">{{ funds_fmt(current_capital) }}U</div></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if include_transfer_block and not order_popup %}
|
||||
{% include 'gate_transfer_block.html' %}
|
||||
{% endif %}
|
||||
|
||||
+20
-6
@@ -126,6 +126,10 @@ def register_embed_routes(
|
||||
if tab not in EMBED_TABS:
|
||||
tab = "trade"
|
||||
session["hub_embed_shell"] = True
|
||||
if request_order_popup():
|
||||
session["hub_order_popup"] = True
|
||||
else:
|
||||
session.pop("hub_order_popup", None)
|
||||
return render_main_page_fn(tab, embed_mode="shell")
|
||||
|
||||
@login_required
|
||||
@@ -140,13 +144,23 @@ def register_embed_routes(
|
||||
return jsonify({"ok": True, "page": tab, "html": html})
|
||||
|
||||
|
||||
def merge_next_query(path: str, **params: str) -> str:
|
||||
"""把 query 参数合并进 next 路径(SSO / embed 跳转用)。"""
|
||||
split = urlsplit(path or "/")
|
||||
q = dict(parse_qsl(split.query, keep_blank_values=True))
|
||||
for k, v in params.items():
|
||||
val = (v or "").strip()
|
||||
if val:
|
||||
q[k] = val
|
||||
base = split.path or "/"
|
||||
return f"{base}?{urlencode(q)}" if q else base
|
||||
|
||||
|
||||
def request_order_popup() -> bool:
|
||||
return (request.args.get("order_popup") or "").strip().lower() in (
|
||||
"1",
|
||||
"true",
|
||||
"yes",
|
||||
"on",
|
||||
)
|
||||
raw = (request.args.get("order_popup") or "").strip().lower()
|
||||
if raw in ("1", "true", "yes", "on"):
|
||||
return True
|
||||
return bool(session.get("hub_order_popup"))
|
||||
|
||||
|
||||
def embed_context_extras(exchange_key: str) -> dict:
|
||||
|
||||
@@ -1900,8 +1900,12 @@ def api_instance_open_url(
|
||||
next: str = "/",
|
||||
embed: str = "",
|
||||
hub_theme: str = "",
|
||||
order_popup: str = "",
|
||||
symbol: str = "",
|
||||
):
|
||||
"""已登录中控时生成实例 SSO 打开链接(2h 有效、单次使用,复用 HUB_BRIDGE_TOKEN)。"""
|
||||
from instance_embed_lib import merge_next_query
|
||||
|
||||
_require_hub_logged_in(request)
|
||||
if not HUB_BRIDGE_TOKEN:
|
||||
raise HTTPException(status_code=503, detail="未配置 HUB_BRIDGE_TOKEN,无法签发实例打开链接")
|
||||
@@ -1915,6 +1919,11 @@ def api_instance_open_url(
|
||||
if not ex_key:
|
||||
raise HTTPException(status_code=400, detail="该账户缺少 key(用于 SSO 校验)")
|
||||
nxt = safe_next_path(next)
|
||||
if (order_popup or "").strip().lower() in ("1", "true", "yes", "on"):
|
||||
nxt = merge_next_query(nxt, order_popup="1")
|
||||
sym = (symbol or "").strip()
|
||||
if sym:
|
||||
nxt = merge_next_query(nxt, symbol=sym)
|
||||
token = mint_hub_sso_token(ex_key, nxt)
|
||||
if not token:
|
||||
raise HTTPException(status_code=503, detail="签发 SSO 失败")
|
||||
|
||||
@@ -419,8 +419,12 @@
|
||||
async function fetchInstanceOpenUrl(exchangeId, nextPath, opts) {
|
||||
const options = opts || {};
|
||||
const next = nextPath || "/";
|
||||
const q = new URLSearchParams({ exchange_id: String(exchangeId), next });
|
||||
const q = new URLSearchParams();
|
||||
q.set("exchange_id", String(exchangeId));
|
||||
q.set("next", next);
|
||||
if (options.embed) q.set("embed", "1");
|
||||
if (options.orderPopup) q.set("order_popup", "1");
|
||||
if (options.symbol) q.set("symbol", String(options.symbol));
|
||||
if (options.embed && globalThis.HubTheme && typeof HubTheme.get === "function") {
|
||||
q.set("hub_theme", HubTheme.get());
|
||||
}
|
||||
@@ -493,10 +497,12 @@
|
||||
async function openOrderPopup(exchangeId, opts) {
|
||||
const options = opts || {};
|
||||
const symbol = (options.symbol || "").trim();
|
||||
let next = "/trade?order_popup=1";
|
||||
if (symbol) next += "&symbol=" + encodeURIComponent(symbol);
|
||||
try {
|
||||
const url = await fetchInstanceOpenUrl(exchangeId, next, { embed: true });
|
||||
const url = await fetchInstanceOpenUrl(exchangeId, "/trade", {
|
||||
embed: true,
|
||||
orderPopup: true,
|
||||
symbol: symbol || undefined,
|
||||
});
|
||||
const row = lastMonitorRows.find((x) => String(x.id) === String(exchangeId));
|
||||
const title = row ? row.name : exchangeId;
|
||||
orderPopupCtx = { exchangeId: String(exchangeId), title, symbol };
|
||||
@@ -539,11 +545,11 @@
|
||||
const frame = document.getElementById("order-popup-frame");
|
||||
if (!frame) return;
|
||||
try {
|
||||
let next = "/trade?order_popup=1";
|
||||
if (orderPopupCtx.symbol) {
|
||||
next += "&symbol=" + encodeURIComponent(orderPopupCtx.symbol);
|
||||
}
|
||||
const url = await fetchInstanceOpenUrl(orderPopupCtx.exchangeId, next, { embed: true });
|
||||
const url = await fetchInstanceOpenUrl(orderPopupCtx.exchangeId, "/trade", {
|
||||
embed: true,
|
||||
orderPopup: true,
|
||||
symbol: orderPopupCtx.symbol || undefined,
|
||||
});
|
||||
orderPopupUrl = url;
|
||||
setOrderPopupLoading(true);
|
||||
frame.src = url;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from instance_embed_lib import (
|
||||
EMBED_TABS,
|
||||
merge_next_query,
|
||||
path_to_embed_tab,
|
||||
rewrite_embed_dest,
|
||||
)
|
||||
@@ -27,6 +28,12 @@ def test_rewrite_embed_dest_order_popup_query():
|
||||
assert "symbol=BTC" in url
|
||||
|
||||
|
||||
def test_merge_next_query_order_popup():
|
||||
url = merge_next_query("/trade", order_popup="1", symbol="BTC/USDT")
|
||||
assert "order_popup=1" in url
|
||||
assert "symbol=BTC" in url
|
||||
|
||||
|
||||
def test_embed_tabs_cover_main_nav():
|
||||
assert "trade" in EMBED_TABS
|
||||
assert "key_monitor" in EMBED_TABS
|
||||
|
||||
Reference in New Issue
Block a user