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>
|
<span style="color:#8892b0;font-size:.75rem">统计页仍按北京时间 {{ stats_bundle.stats_reset_hour|default(reset_hour) }}:00 切日</span>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% 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>
|
<span style="color:#9aa">数据导出(v{{ data_export_version }} CSV,UTF-8;交易记录含开仓类型列,复盘单独导出):</span>
|
||||||
<a href="/export/trade_records">交易记录</a>
|
<a href="/export/trade_records">交易记录</a>
|
||||||
<a href="/export/journal_entries">复盘记录</a>
|
<a href="/export/journal_entries">复盘记录</a>
|
||||||
<a href="/export/key_monitors">关键位(当前)</a>
|
<a href="/export/key_monitors">关键位(当前)</a>
|
||||||
<a href="/export/key_monitor_history">关键位历史</a>
|
<a href="/export/key_monitor_history">关键位历史</a>
|
||||||
</div>
|
</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">{{ 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-total">{{ total }}</div></div>
|
||||||
<div class="stat-item"><div class="label">错过次数</div><div class="value" id="stat-miss">{{ miss_count }}</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">{{ 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 class="stat-item"><div class="label">当日资金(交易账户)</div><div class="value" id="current-capital">{{ funds_fmt(current_capital) }}U</div></div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% if include_transfer_block and not order_popup %}
|
{% if include_transfer_block and not order_popup %}
|
||||||
{% include 'gate_transfer_block.html' %}
|
{% include 'gate_transfer_block.html' %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
+20
-6
@@ -126,6 +126,10 @@ def register_embed_routes(
|
|||||||
if tab not in EMBED_TABS:
|
if tab not in EMBED_TABS:
|
||||||
tab = "trade"
|
tab = "trade"
|
||||||
session["hub_embed_shell"] = True
|
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")
|
return render_main_page_fn(tab, embed_mode="shell")
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@@ -140,13 +144,23 @@ def register_embed_routes(
|
|||||||
return jsonify({"ok": True, "page": tab, "html": html})
|
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:
|
def request_order_popup() -> bool:
|
||||||
return (request.args.get("order_popup") or "").strip().lower() in (
|
raw = (request.args.get("order_popup") or "").strip().lower()
|
||||||
"1",
|
if raw in ("1", "true", "yes", "on"):
|
||||||
"true",
|
return True
|
||||||
"yes",
|
return bool(session.get("hub_order_popup"))
|
||||||
"on",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def embed_context_extras(exchange_key: str) -> dict:
|
def embed_context_extras(exchange_key: str) -> dict:
|
||||||
|
|||||||
@@ -1900,8 +1900,12 @@ def api_instance_open_url(
|
|||||||
next: str = "/",
|
next: str = "/",
|
||||||
embed: str = "",
|
embed: str = "",
|
||||||
hub_theme: str = "",
|
hub_theme: str = "",
|
||||||
|
order_popup: str = "",
|
||||||
|
symbol: str = "",
|
||||||
):
|
):
|
||||||
"""已登录中控时生成实例 SSO 打开链接(2h 有效、单次使用,复用 HUB_BRIDGE_TOKEN)。"""
|
"""已登录中控时生成实例 SSO 打开链接(2h 有效、单次使用,复用 HUB_BRIDGE_TOKEN)。"""
|
||||||
|
from instance_embed_lib import merge_next_query
|
||||||
|
|
||||||
_require_hub_logged_in(request)
|
_require_hub_logged_in(request)
|
||||||
if not HUB_BRIDGE_TOKEN:
|
if not HUB_BRIDGE_TOKEN:
|
||||||
raise HTTPException(status_code=503, detail="未配置 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:
|
if not ex_key:
|
||||||
raise HTTPException(status_code=400, detail="该账户缺少 key(用于 SSO 校验)")
|
raise HTTPException(status_code=400, detail="该账户缺少 key(用于 SSO 校验)")
|
||||||
nxt = safe_next_path(next)
|
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)
|
token = mint_hub_sso_token(ex_key, nxt)
|
||||||
if not token:
|
if not token:
|
||||||
raise HTTPException(status_code=503, detail="签发 SSO 失败")
|
raise HTTPException(status_code=503, detail="签发 SSO 失败")
|
||||||
|
|||||||
@@ -419,8 +419,12 @@
|
|||||||
async function fetchInstanceOpenUrl(exchangeId, nextPath, opts) {
|
async function fetchInstanceOpenUrl(exchangeId, nextPath, opts) {
|
||||||
const options = opts || {};
|
const options = opts || {};
|
||||||
const next = nextPath || "/";
|
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.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") {
|
if (options.embed && globalThis.HubTheme && typeof HubTheme.get === "function") {
|
||||||
q.set("hub_theme", HubTheme.get());
|
q.set("hub_theme", HubTheme.get());
|
||||||
}
|
}
|
||||||
@@ -493,10 +497,12 @@
|
|||||||
async function openOrderPopup(exchangeId, opts) {
|
async function openOrderPopup(exchangeId, opts) {
|
||||||
const options = opts || {};
|
const options = opts || {};
|
||||||
const symbol = (options.symbol || "").trim();
|
const symbol = (options.symbol || "").trim();
|
||||||
let next = "/trade?order_popup=1";
|
|
||||||
if (symbol) next += "&symbol=" + encodeURIComponent(symbol);
|
|
||||||
try {
|
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 row = lastMonitorRows.find((x) => String(x.id) === String(exchangeId));
|
||||||
const title = row ? row.name : exchangeId;
|
const title = row ? row.name : exchangeId;
|
||||||
orderPopupCtx = { exchangeId: String(exchangeId), title, symbol };
|
orderPopupCtx = { exchangeId: String(exchangeId), title, symbol };
|
||||||
@@ -539,11 +545,11 @@
|
|||||||
const frame = document.getElementById("order-popup-frame");
|
const frame = document.getElementById("order-popup-frame");
|
||||||
if (!frame) return;
|
if (!frame) return;
|
||||||
try {
|
try {
|
||||||
let next = "/trade?order_popup=1";
|
const url = await fetchInstanceOpenUrl(orderPopupCtx.exchangeId, "/trade", {
|
||||||
if (orderPopupCtx.symbol) {
|
embed: true,
|
||||||
next += "&symbol=" + encodeURIComponent(orderPopupCtx.symbol);
|
orderPopup: true,
|
||||||
}
|
symbol: orderPopupCtx.symbol || undefined,
|
||||||
const url = await fetchInstanceOpenUrl(orderPopupCtx.exchangeId, next, { embed: true });
|
});
|
||||||
orderPopupUrl = url;
|
orderPopupUrl = url;
|
||||||
setOrderPopupLoading(true);
|
setOrderPopupLoading(true);
|
||||||
frame.src = url;
|
frame.src = url;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from instance_embed_lib import (
|
from instance_embed_lib import (
|
||||||
EMBED_TABS,
|
EMBED_TABS,
|
||||||
|
merge_next_query,
|
||||||
path_to_embed_tab,
|
path_to_embed_tab,
|
||||||
rewrite_embed_dest,
|
rewrite_embed_dest,
|
||||||
)
|
)
|
||||||
@@ -27,6 +28,12 @@ def test_rewrite_embed_dest_order_popup_query():
|
|||||||
assert "symbol=BTC" in url
|
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():
|
def test_embed_tabs_cover_main_nav():
|
||||||
assert "trade" in EMBED_TABS
|
assert "trade" in EMBED_TABS
|
||||||
assert "key_monitor" in EMBED_TABS
|
assert "key_monitor" in EMBED_TABS
|
||||||
|
|||||||
Reference in New Issue
Block a user