From 347e6b55451cfac28bfc1ee521dc5d41d3c5e64a Mon Sep 17 00:00:00 2001 From: dekun Date: Thu, 25 Jun 2026 23:38:21 +0800 Subject: [PATCH] Fix order_popup flag through SSO and hide stats in hub order popup. Co-authored-by: Cursor --- embed_templates/embed_shell.html | 6 ++++-- instance_embed_lib.py | 26 ++++++++++++++++++++------ manual_trading_hub/hub.py | 9 +++++++++ manual_trading_hub/static/app.js | 24 +++++++++++++++--------- tests/test_instance_embed_lib.py | 7 +++++++ 5 files changed, 55 insertions(+), 17 deletions(-) diff --git a/embed_templates/embed_shell.html b/embed_templates/embed_shell.html index 369bfb3..ffeab1f 100644 --- a/embed_templates/embed_shell.html +++ b/embed_templates/embed_shell.html @@ -76,14 +76,15 @@ 统计页仍按北京时间 {{ stats_bundle.stats_reset_hour|default(reset_hour) }}:00 切日 {% endif %} -
+ {% if not order_popup %} +
数据导出(v{{ data_export_version }} CSV,UTF-8;交易记录含开仓类型列,复盘单独导出): 交易记录 复盘记录 关键位(当前) 关键位历史
-
+
交易所
{{ exchange_display }}
总交易
{{ total }}
错过次数
{{ miss_count }}
@@ -92,6 +93,7 @@
交易日
{{ trading_day }}
当日资金(交易账户)
{{ funds_fmt(current_capital) }}U
+ {% endif %} {% if include_transfer_block and not order_popup %} {% include 'gate_transfer_block.html' %} {% endif %} diff --git a/instance_embed_lib.py b/instance_embed_lib.py index 305569f..0e603b0 100644 --- a/instance_embed_lib.py +++ b/instance_embed_lib.py @@ -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: diff --git a/manual_trading_hub/hub.py b/manual_trading_hub/hub.py index 9d7e5f9..b04f9d0 100644 --- a/manual_trading_hub/hub.py +++ b/manual_trading_hub/hub.py @@ -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 失败") diff --git a/manual_trading_hub/static/app.js b/manual_trading_hub/static/app.js index a6447c3..0fdd14b 100644 --- a/manual_trading_hub/static/app.js +++ b/manual_trading_hub/static/app.js @@ -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; diff --git a/tests/test_instance_embed_lib.py b/tests/test_instance_embed_lib.py index fdfee57..8e0e9e4 100644 --- a/tests/test_instance_embed_lib.py +++ b/tests/test_instance_embed_lib.py @@ -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