diff --git a/app.py b/app.py index 98c043b..5b6f869 100644 --- a/app.py +++ b/app.py @@ -586,13 +586,15 @@ def api_open_url(iid: int): inst = get_instance(iid) if not inst: return jsonify({"ok": False, "msg": "不存在"}), 404 + tab = (request.args.get("tab") or "").strip() or None url = build_embed_open_url( inst["base_url"], bridge_token=inst["bridge_token"], embed_path=inst.get("embed_path") or "/embed", ttl_sec=3600, + tab=tab, ) - return jsonify({"ok": True, "url": url, "base_url": inst["base_url"]}) + return jsonify({"ok": True, "url": url, "base_url": inst["base_url"], "tab": tab}) @app.route("/api/settings/update/hub/version", methods=["GET"]) diff --git a/lib/cond_orders_cache_lib.py b/lib/cond_orders_cache_lib.py index 8b52a7e..3228d6b 100644 --- a/lib/cond_orders_cache_lib.py +++ b/lib/cond_orders_cache_lib.py @@ -33,6 +33,15 @@ def _sse_heartbeat_sec() -> float: return 25.0 +def _safe_float(v: Any) -> float | None: + if v is None or v == "": + return None + try: + return float(v) + except (TypeError, ValueError): + return None + + def _candidates_from_snaps(rows: list[dict[str, Any]]) -> list[dict[str, Any]]: out: list[dict[str, Any]] = [] for row in rows or []: @@ -45,6 +54,20 @@ def _candidates_from_snaps(rows: list[dict[str, Any]]) -> list[dict[str, Any]]: mode = str(inst.get("mode") or "").strip().lower() if mode not in ("sim", "live"): mode = "" + funds = snap.get("funds") if isinstance(snap.get("funds"), dict) else {} + # 开仓吃交易户;优先 avail,回退总额 + trading_usdt = _safe_float(funds.get("trading_usdt_avail")) + if trading_usdt is None: + trading_usdt = _safe_float(funds.get("trading_usdt")) + if trading_usdt is None: + trading_usdt = _safe_float(snap.get("trading_usdt")) + funding_usdt = _safe_float(funds.get("funding_usdt")) + if funding_usdt is None: + funding_usdt = _safe_float(snap.get("funding_usdt")) + if trading_usdt is not None: + trading_usdt = round(float(trading_usdt), 4) + if funding_usdt is not None: + funding_usdt = round(float(funding_usdt), 4) out.append( { "id": row.get("id"), @@ -55,6 +78,8 @@ def _candidates_from_snaps(rows: list[dict[str, Any]]) -> list[dict[str, Any]]: "selectable": selectable, "mode": mode, "error": row.get("error") or "", + "trading_usdt": trading_usdt, + "funding_usdt": funding_usdt, } ) return out diff --git a/lib/sso_lib.py b/lib/sso_lib.py index 6b55598..3e29d5f 100644 --- a/lib/sso_lib.py +++ b/lib/sso_lib.py @@ -24,11 +24,18 @@ def build_embed_open_url( bridge_token: str, embed_path: str = "/embed", ttl_sec: int = 120, + tab: str | None = None, ) -> str: root = (base_url or "").rstrip("/") path = embed_path or "/embed" if not path.startswith("/"): path = "/" + path + tab_s = "".join(c for c in str(tab or "").strip().lower() if c.isalnum() or c == "_")[ + :32 + ] + if tab_s: + joiner = "&" if "?" in path else "?" + path = f"{path}{joiner}tab={tab_s}" token = make_sso_token(bridge_token, ttl_sec=ttl_sec) q = urlencode({"token": token, "next": path}) return f"{root}/hub_sso?{q}" diff --git a/static/cond_orders.js b/static/cond_orders.js index a5ec452..df7e631 100644 --- a/static/cond_orders.js +++ b/static/cond_orders.js @@ -202,6 +202,36 @@ return m === "sim" || m === "live" ? m : ""; } + function fmtTradingU(v) { + if (v == null || v === "") return "—"; + const n = Number(v); + if (Number.isNaN(n)) return "—"; + return n.toFixed(2) + "U"; + } + + function openInstanceTab(instanceId, tab) { + if (!instanceId) return; + const q = tab ? "?tab=" + encodeURIComponent(tab) : ""; + fetch("/api/instances/" + encodeURIComponent(instanceId) + "/open_url" + q) + .then(function (r) { + return r.json(); + }) + .then(function (d) { + const url = + d && d.url + ? d.url + : "/desk?id=" + encodeURIComponent(instanceId); + window.open(url, "_blank", "noopener,noreferrer"); + }) + .catch(function () { + window.open( + "/desk?id=" + encodeURIComponent(instanceId), + "_blank", + "noopener,noreferrer" + ); + }); + } + function renderCandidateCard(it, checkedIds) { const disabled = !it.selectable; const tip = disabled @@ -215,7 +245,14 @@ : "可选"; const id = String(it.id); const checked = !disabled && checkedIds.indexOf(id) >= 0; + const fundsTip = + it.funding_usdt != null + ? "资金户 " + fmtTradingU(it.funding_usdt) + : ""; return ( + '