From 6f1ae14b3d4e7f3602c893c97019d1a3bf1ffb68 Mon Sep 17 00:00:00 2001 From: dekun Date: Fri, 24 Jul 2026 00:24:00 +0800 Subject: [PATCH] Add display toggles to hide monitor cards and strategy tabs. Keep unused exchanges/docs out of the UI without disabling accounts. Co-authored-by: Cursor --- lib/hub/hub_strategy_lib.py | 29 ++- manual_trading_hub/hub.py | 13 +- manual_trading_hub/settings_store.py | 12 ++ manual_trading_hub/static/app.css | 242 ++++++++++++++------------ manual_trading_hub/static/app.js | 199 +++++++++++++-------- manual_trading_hub/static/index.html | 50 +++++- manual_trading_hub/static/strategy.js | 22 ++- 7 files changed, 367 insertions(+), 200 deletions(-) diff --git a/lib/hub/hub_strategy_lib.py b/lib/hub/hub_strategy_lib.py index 2c90a83..5751665 100644 --- a/lib/hub/hub_strategy_lib.py +++ b/lib/hub/hub_strategy_lib.py @@ -236,11 +236,30 @@ def load_strategy_payload(exchange_key: str) -> dict[str, Any]: } -def strategy_meta_payload() -> dict[str, Any]: - tabs = [ - {"key": k, "label": STRATEGY_META[k]["label"], "title": STRATEGY_META[k]["title"]} - for k in STRATEGY_EXCHANGES - ] +_STRATEGY_TAB_DISPLAY_PREF: dict[str, str] = { + "playbook_v2": "show_strategy_playbook_v2", + "playbook": "show_strategy_playbook", + "behavior": "show_strategy_behavior", + "binance": "show_strategy_binance", + "okx": "show_strategy_okx", + "gate": "show_strategy_gate", +} + + +def strategy_meta_payload(display: dict[str, Any] | None = None) -> dict[str, Any]: + prefs = display if isinstance(display, dict) else {} + tabs = [] + for k in STRATEGY_EXCHANGES: + pref_key = _STRATEGY_TAB_DISPLAY_PREF.get(k) + if pref_key and prefs.get(pref_key) is False: + continue + tabs.append( + { + "key": k, + "label": STRATEGY_META[k]["label"], + "title": STRATEGY_META[k]["title"], + } + ) return {"ok": True, "exchanges": tabs} diff --git a/manual_trading_hub/hub.py b/manual_trading_hub/hub.py index 3ddf8df..8292d61 100644 --- a/manual_trading_hub/hub.py +++ b/manual_trading_hub/hub.py @@ -1119,6 +1119,16 @@ class SettingsDisplayBody(BaseModel): show_nav_amp_stats: bool = True show_nav_help: bool = True show_nav_logs: bool = True + show_monitor_binance: bool = True + show_monitor_okx_perp: bool = True + show_monitor_okx_options: bool = True + show_monitor_gate: bool = True + show_strategy_playbook_v2: bool = True + show_strategy_playbook: bool = True + show_strategy_behavior: bool = True + show_strategy_binance: bool = True + show_strategy_okx: bool = True + show_strategy_gate: bool = True class SupervisorSettingsBody(BaseModel): @@ -3348,7 +3358,8 @@ async def api_archive_sync(): @app.get("/api/strategy/meta") def api_strategy_meta(): - return strategy_meta_payload() + display = (load_settings() or {}).get("display") or {} + return strategy_meta_payload(display) @app.get("/api/help/meta") diff --git a/manual_trading_hub/settings_store.py b/manual_trading_hub/settings_store.py index 03b75ee..f102d30 100644 --- a/manual_trading_hub/settings_store.py +++ b/manual_trading_hub/settings_store.py @@ -34,6 +34,18 @@ DEFAULT_DISPLAY = { "show_nav_amp_stats": True, "show_nav_help": True, "show_nav_logs": True, + # 监控区卡片(仅隐藏界面,不关闭账户) + "show_monitor_binance": True, + "show_monitor_okx_perp": True, + "show_monitor_okx_options": True, + "show_monitor_gate": True, + # 策略说明页签 + "show_strategy_playbook_v2": True, + "show_strategy_playbook": True, + "show_strategy_behavior": True, + "show_strategy_binance": True, + "show_strategy_okx": True, + "show_strategy_gate": True, } DEFAULT_EXCHANGES = [ diff --git a/manual_trading_hub/static/app.css b/manual_trading_hub/static/app.css index f477184..e7c0879 100644 --- a/manual_trading_hub/static/app.css +++ b/manual_trading_hub/static/app.css @@ -3501,6 +3501,18 @@ button.btn-sm { margin-top: 8px; } +.settings-display-subtitle { + margin: 16px 0 6px; + font-size: 0.82rem; + font-weight: 600; + color: var(--text); +} + +.settings-display-subtitle + .settings-display-hint { + margin-top: 0; + margin-bottom: 8px; +} + .settings-display-hint { margin: 8px 0 0; font-size: 0.78rem; @@ -11008,118 +11020,118 @@ html[data-theme="light"] .hub-logs-card-hint { .amp-form { grid-template-columns: 1fr 1fr; } .amp-actions { grid-column: 1 / -1; } } - -/* --- strategy compare --- */ -#page-compare .toolbar { - padding: 12px 16px; - margin-bottom: 14px; -} -.cmp-form { display: flex; flex-direction: column; gap: 14px; margin-bottom: 16px; } -.cmp-form .card, -.cmp-common-card, -.cmp-sum-card, -.cmp-rec-card { - padding: 18px 20px; -} -.cmp-common-card h2, -.cmp-form .card h2 { - margin: 0 0 14px; - font-size: 15px; -} -.cmp-subhead { - margin: 16px 0 10px; - font-size: 13px; - color: var(--muted); - font-weight: 600; -} -.cmp-form-grid { - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 14px 16px; -} -.cmp-field { - display: flex; - flex-direction: column; - gap: 6px; - font-size: 12px; - color: var(--muted); -} -.cmp-field input, -.cmp-field select { - background: var(--inset-surface); - border: 1px solid var(--border-soft); - border-radius: 8px; - color: var(--text); - padding: 9px 12px; - font-size: 13px; -} -.cmp-input-cols { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 14px; -} -.cmp-summary { - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 14px; - margin-bottom: 16px; -} -.cmp-sum-card h3 { margin: 0 0 12px; font-size: 14px; } -.cmp-sum-row { - display: flex; - justify-content: space-between; - gap: 12px; - font-size: 12px; - margin: 6px 0; - color: var(--muted); -} -.cmp-sum-row strong { color: var(--text); font-weight: 600; } -.cmp-muted { color: var(--muted); font-size: 12px; margin: 0; } -.cmp-table-wrap { margin-bottom: 16px; } -.cmp-table-scroll { overflow-x: auto; } -.cmp-table { - width: 100%; - border-collapse: separate; - border-spacing: 0; - font-size: 13px; - background: var(--panel); - border: 1px solid var(--border); - border-radius: var(--radius); - overflow: hidden; -} -.cmp-table th, -.cmp-table td { - border-bottom: 1px solid var(--border-soft); - padding: 14px 16px; - vertical-align: top; - text-align: left; -} -.cmp-table th:first-child, -.cmp-table td:first-child { width: 22%; } -.cmp-table tr:last-child td { border-bottom: none; } -.cmp-cell-note { - margin-top: 6px; - font-size: 11px; - color: var(--muted); - line-height: 1.4; -} -.cmp-pnl-pos { color: var(--green); font-weight: 600; } -.cmp-pnl-neg { color: var(--red); font-weight: 600; } -.cmp-rec-head { font-size: 16px; margin-bottom: 8px; } -.cmp-rec-reason { margin: 0 0 10px; color: var(--muted); font-size: 13px; } -.cmp-rec-list { margin: 0; padding-left: 20px; font-size: 13px; line-height: 1.55; } -.cmp-warn { margin-top: 12px; font-size: 12px; color: var(--warn, #e6a23c); } -.cmp-foot-note { margin: 12px 0 0; font-size: 11px; color: var(--muted); } -@media (max-width: 900px) { - .cmp-form .card, - .cmp-common-card, - .cmp-sum-card, - .cmp-rec-card { - padding: 16px; - } - .cmp-form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } - .cmp-input-cols, - .cmp-summary { grid-template-columns: 1fr; } - .cmp-table th, - .cmp-table td { padding: 12px 14px; } -} + +/* --- strategy compare --- */ +#page-compare .toolbar { + padding: 12px 16px; + margin-bottom: 14px; +} +.cmp-form { display: flex; flex-direction: column; gap: 14px; margin-bottom: 16px; } +.cmp-form .card, +.cmp-common-card, +.cmp-sum-card, +.cmp-rec-card { + padding: 18px 20px; +} +.cmp-common-card h2, +.cmp-form .card h2 { + margin: 0 0 14px; + font-size: 15px; +} +.cmp-subhead { + margin: 16px 0 10px; + font-size: 13px; + color: var(--muted); + font-weight: 600; +} +.cmp-form-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 14px 16px; +} +.cmp-field { + display: flex; + flex-direction: column; + gap: 6px; + font-size: 12px; + color: var(--muted); +} +.cmp-field input, +.cmp-field select { + background: var(--inset-surface); + border: 1px solid var(--border-soft); + border-radius: 8px; + color: var(--text); + padding: 9px 12px; + font-size: 13px; +} +.cmp-input-cols { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 14px; +} +.cmp-summary { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 14px; + margin-bottom: 16px; +} +.cmp-sum-card h3 { margin: 0 0 12px; font-size: 14px; } +.cmp-sum-row { + display: flex; + justify-content: space-between; + gap: 12px; + font-size: 12px; + margin: 6px 0; + color: var(--muted); +} +.cmp-sum-row strong { color: var(--text); font-weight: 600; } +.cmp-muted { color: var(--muted); font-size: 12px; margin: 0; } +.cmp-table-wrap { margin-bottom: 16px; } +.cmp-table-scroll { overflow-x: auto; } +.cmp-table { + width: 100%; + border-collapse: separate; + border-spacing: 0; + font-size: 13px; + background: var(--panel); + border: 1px solid var(--border); + border-radius: var(--radius); + overflow: hidden; +} +.cmp-table th, +.cmp-table td { + border-bottom: 1px solid var(--border-soft); + padding: 14px 16px; + vertical-align: top; + text-align: left; +} +.cmp-table th:first-child, +.cmp-table td:first-child { width: 22%; } +.cmp-table tr:last-child td { border-bottom: none; } +.cmp-cell-note { + margin-top: 6px; + font-size: 11px; + color: var(--muted); + line-height: 1.4; +} +.cmp-pnl-pos { color: var(--green); font-weight: 600; } +.cmp-pnl-neg { color: var(--red); font-weight: 600; } +.cmp-rec-head { font-size: 16px; margin-bottom: 8px; } +.cmp-rec-reason { margin: 0 0 10px; color: var(--muted); font-size: 13px; } +.cmp-rec-list { margin: 0; padding-left: 20px; font-size: 13px; line-height: 1.55; } +.cmp-warn { margin-top: 12px; font-size: 12px; color: var(--warn, #e6a23c); } +.cmp-foot-note { margin: 12px 0 0; font-size: 11px; color: var(--muted); } +@media (max-width: 900px) { + .cmp-form .card, + .cmp-common-card, + .cmp-sum-card, + .cmp-rec-card { + padding: 16px; + } + .cmp-form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } + .cmp-input-cols, + .cmp-summary { grid-template-columns: 1fr; } + .cmp-table th, + .cmp-table td { padding: 12px 14px; } +} diff --git a/manual_trading_hub/static/app.js b/manual_trading_hub/static/app.js index 4e4ea8d..c36b148 100644 --- a/manual_trading_hub/static/app.js +++ b/manual_trading_hub/static/app.js @@ -9,12 +9,42 @@ return !!d[key]; } + window.hubDisplayPref = displayPref; + function showAccountPnlPref() { return displayPref("show_account_pnl", true); } window.hubShowAccountPnlPref = showAccountPnlPref; + function showMonitorBinancePref() { + return displayPref("show_monitor_binance", true); + } + + function showMonitorOkxPerpPref() { + return displayPref("show_monitor_okx_perp", true); + } + + function showMonitorOkxOptionsPref() { + return displayPref("show_monitor_okx_options", true); + } + + function showMonitorGatePref() { + return displayPref("show_monitor_gate", true); + } + + function monitorExchangeKeyVisible(key) { + const k = String(key || "").toLowerCase(); + if (k === "binance") return showMonitorBinancePref(); + if (k === "gate") return showMonitorGatePref(); + if (k === "okx") return showMonitorOkxPerpPref() || showMonitorOkxOptionsPref(); + return true; + } + + function filterVisibleMonitorRows(rows) { + return (rows || []).filter((r) => monitorExchangeKeyVisible(r && r.key)); + } + function showNavFundsPref() { return displayPref("show_nav_funds", true); } @@ -157,32 +187,33 @@ function syncDisplayPrefsUI(data) { const d = (data && data.display) || {}; - const pnlCb = document.getElementById("pref-show-account-pnl"); - const fundsCb = document.getElementById("pref-show-nav-funds"); - const dashCb = document.getElementById("pref-show-nav-dashboard"); - const planCb = document.getElementById("pref-show-nav-plan"); - const archiveCb = document.getElementById("pref-show-nav-archive"); - const quotesCb = document.getElementById("pref-show-nav-quotes"); - const aiCb = document.getElementById("pref-show-nav-ai"); - const calcCb = document.getElementById("pref-show-nav-calculator"); - const compareCb = document.getElementById("pref-show-nav-compare"); - const strategyCb = document.getElementById("pref-show-nav-strategy"); - const ampCb = document.getElementById("pref-show-nav-amp-stats"); - const helpCb = document.getElementById("pref-show-nav-help"); - const logsCb = document.getElementById("pref-show-nav-logs"); - if (pnlCb) pnlCb.checked = d.show_account_pnl !== false; - if (fundsCb) fundsCb.checked = d.show_nav_funds !== false; - if (dashCb) dashCb.checked = d.show_nav_dashboard !== false; - if (planCb) planCb.checked = d.show_nav_plan !== false; - if (archiveCb) archiveCb.checked = d.show_nav_archive !== false; - if (quotesCb) quotesCb.checked = d.show_nav_quotes !== false; - if (aiCb) aiCb.checked = d.show_nav_ai !== false; - if (calcCb) calcCb.checked = d.show_nav_calculator !== false; - if (compareCb) compareCb.checked = d.show_nav_compare !== false; - if (strategyCb) strategyCb.checked = d.show_nav_strategy !== false; - if (ampCb) ampCb.checked = d.show_nav_amp_stats !== false; - if (helpCb) helpCb.checked = d.show_nav_help !== false; - if (logsCb) logsCb.checked = d.show_nav_logs !== false; + const setChk = (id, key) => { + const el = document.getElementById(id); + if (el) el.checked = d[key] !== false; + }; + setChk("pref-show-account-pnl", "show_account_pnl"); + setChk("pref-show-nav-funds", "show_nav_funds"); + setChk("pref-show-nav-dashboard", "show_nav_dashboard"); + setChk("pref-show-nav-plan", "show_nav_plan"); + setChk("pref-show-nav-archive", "show_nav_archive"); + setChk("pref-show-nav-quotes", "show_nav_quotes"); + setChk("pref-show-nav-ai", "show_nav_ai"); + setChk("pref-show-nav-calculator", "show_nav_calculator"); + setChk("pref-show-nav-compare", "show_nav_compare"); + setChk("pref-show-nav-strategy", "show_nav_strategy"); + setChk("pref-show-nav-amp-stats", "show_nav_amp_stats"); + setChk("pref-show-nav-help", "show_nav_help"); + setChk("pref-show-nav-logs", "show_nav_logs"); + setChk("pref-show-monitor-binance", "show_monitor_binance"); + setChk("pref-show-monitor-okx-perp", "show_monitor_okx_perp"); + setChk("pref-show-monitor-okx-options", "show_monitor_okx_options"); + setChk("pref-show-monitor-gate", "show_monitor_gate"); + setChk("pref-show-strategy-playbook-v2", "show_strategy_playbook_v2"); + setChk("pref-show-strategy-playbook", "show_strategy_playbook"); + setChk("pref-show-strategy-behavior", "show_strategy_behavior"); + setChk("pref-show-strategy-binance", "show_strategy_binance"); + setChk("pref-show-strategy-okx", "show_strategy_okx"); + setChk("pref-show-strategy-gate", "show_strategy_gate"); syncNavVisibility(data); } @@ -1569,7 +1600,7 @@ if (upd) upd.textContent = txt; if (updSum) updSum.textContent = txt; } - updateMonitorAlertSummary(rows || []); + updateMonitorAlertSummary(filterVisibleMonitorRows(rows || [])); void refreshMacroRiskBanner(rows || []); renderMonitorGrid(rows || []); } @@ -2080,19 +2111,20 @@ if (lastMonitorRows.length && nowMobile !== wasMobile) { wasMobile = nowMobile; renderMonitorGrid(lastMonitorRows); - updateMonitorAlertSummary(lastMonitorRows); + updateMonitorAlertSummary(filterVisibleMonitorRows(lastMonitorRows)); syncHubMobileTabActive(currentPage()); return; } wasMobile = nowMobile; const box = document.getElementById("monitor-grid"); if (box && lastMonitorRows.length) { - const split = monitorOptionsSplitActive(lastMonitorRows); - syncMonitorGridColumns(box, lastMonitorRows.length + (lastMonitorTotals ? 1 : 0), { + const visible = filterVisibleMonitorRows(lastMonitorRows); + const split = monitorOptionsSplitActive(visible); + syncMonitorGridColumns(box, visible.length + (lastMonitorTotals ? 1 : 0), { statsFirst: !!lastMonitorTotals && !split, optionsSplit: split, }); - updateMonitorAlertSummary(lastMonitorRows); + updateMonitorAlertSummary(visible); } syncHubMobileTabActive(currentPage()); }, 120); @@ -2486,11 +2518,12 @@ const fs = document.getElementById("exchange-fullscreen"); const fsInner = document.getElementById("exchange-fullscreen-inner"); if (!box) return; - if (expandedExchangeId && !rows.some((r) => String(r.id) === String(expandedExchangeId))) { + const visibleSource = filterVisibleMonitorRows(rows); + if (expandedExchangeId && !visibleSource.some((r) => String(r.id) === String(expandedExchangeId))) { closeExchangeFullscreen(); } const mobileTiles = isMobileLayout() && !expandedExchangeId; - const displayRows = mobileTiles ? sortRowsForMobileDashboard(rows) : rows; + const displayRows = mobileTiles ? sortRowsForMobileDashboard(visibleSource) : visibleSource; const optionsSplit = monitorOptionsSplitActive(displayRows); monitorGridOptionsSplit = optionsSplit; const showStatsCard = !expandedExchangeId; @@ -2503,20 +2536,33 @@ let cardsHtml = ""; if (optionsSplit) { const okxRow = displayRows.find((r) => rowHasOptionsLayout(r)); - const otherRows = displayRows.filter((r) => !rowHasOptionsLayout(r)); - const ph = - ''; - /* 平铺 2×2 顺序:永续|币安 / 期权|Gate —— 同行左右同高,多仓时该行一起长高 */ - const cells = [ - okxRow ? renderMonitorCard(okxRow, { okxPart: "perp", splitSide: true }) : ph, - otherRows[0] ? renderMonitorCard(otherRows[0], { splitSide: true }) : ph, - okxRow ? renderMonitorCard(okxRow, { okxPart: "options", splitSide: true }) : ph, - otherRows[1] ? renderMonitorCard(otherRows[1], { splitSide: true }) : ph, - ]; - for (let i = 2; i < otherRows.length; i++) { - cells.push(renderMonitorCard(otherRows[i], { splitSide: true })); + const otherByKey = {}; + displayRows + .filter((r) => !rowHasOptionsLayout(r)) + .forEach((r) => { + otherByKey[String(r.key || "").toLowerCase()] = r; + }); + /* 平铺顺序尽量保持:永续|币安 / 期权|Gate;隐藏项不占位 */ + const cells = []; + if (okxRow && showMonitorOkxPerpPref()) { + cells.push(renderMonitorCard(okxRow, { okxPart: "perp", splitSide: true })); } - cardsHtml = `
${cells.join("")}
`; + if (otherByKey.binance && showMonitorBinancePref()) { + cells.push(renderMonitorCard(otherByKey.binance, { splitSide: true })); + } + if (okxRow && showMonitorOkxOptionsPref()) { + cells.push(renderMonitorCard(okxRow, { okxPart: "options", splitSide: true })); + } + if (otherByKey.gate && showMonitorGatePref()) { + cells.push(renderMonitorCard(otherByKey.gate, { splitSide: true })); + } + Object.keys(otherByKey).forEach((k) => { + if (k === "binance" || k === "gate") return; + cells.push(renderMonitorCard(otherByKey[k], { splitSide: true })); + }); + cardsHtml = cells.length + ? `
${cells.join("")}
` + : ""; } else { cardsHtml = displayRows @@ -2545,7 +2591,7 @@ } if (expandedExchangeId && fs && fsInner) { - const row = rows.find((r) => String(r.id) === String(expandedExchangeId)); + const row = visibleSource.find((r) => String(r.id) === String(expandedExchangeId)); if (row) { try { fsInner.innerHTML = renderFullscreenExchange(row); @@ -3900,7 +3946,8 @@ function monitorOptionsSplitActive(rows) { if (isMobileLayout() || expandedExchangeId) return false; - return (rows || []).some((r) => rowHasOptionsLayout(r)); + if (!(rows || []).some((r) => rowHasOptionsLayout(r))) return false; + return showMonitorOkxPerpPref() || showMonitorOkxOptionsPref(); } function renderPerpetualInnerCard(row, ag, pos, orders, trends, tickMap, intraday) { @@ -5112,19 +5159,10 @@ function collectSettingsFromUI() { const rows = [...document.querySelectorAll("#settings-list .settings-card")]; - const pnlCb = document.getElementById("pref-show-account-pnl"); - const fundsCb = document.getElementById("pref-show-nav-funds"); - const dashCb = document.getElementById("pref-show-nav-dashboard"); - const planCb = document.getElementById("pref-show-nav-plan"); - const archiveCb = document.getElementById("pref-show-nav-archive"); - const quotesCb = document.getElementById("pref-show-nav-quotes"); - const aiCb = document.getElementById("pref-show-nav-ai"); - const calcCb = document.getElementById("pref-show-nav-calculator"); - const compareCb = document.getElementById("pref-show-nav-compare"); - const strategyCb = document.getElementById("pref-show-nav-strategy"); - const ampCb = document.getElementById("pref-show-nav-amp-stats"); - const helpCb = document.getElementById("pref-show-nav-help"); - const logsCb = document.getElementById("pref-show-nav-logs"); + const chk = (id) => { + const el = document.getElementById(id); + return el ? !!el.checked : true; + }; const supEnabled = document.getElementById("supervisor-enabled"); const supProg = document.getElementById("supervisor-wechat-program"); const supWebhook = document.getElementById("supervisor-wechat-webhook"); @@ -5137,19 +5175,29 @@ return { version: 1, display: { - show_account_pnl: pnlCb ? !!pnlCb.checked : true, - show_nav_funds: fundsCb ? !!fundsCb.checked : true, - show_nav_dashboard: dashCb ? !!dashCb.checked : true, - show_nav_plan: planCb ? !!planCb.checked : true, - show_nav_archive: archiveCb ? !!archiveCb.checked : true, - show_nav_quotes: quotesCb ? !!quotesCb.checked : true, - show_nav_ai: aiCb ? !!aiCb.checked : true, - show_nav_calculator: calcCb ? !!calcCb.checked : true, - show_nav_compare: compareCb ? !!compareCb.checked : true, - show_nav_strategy: strategyCb ? !!strategyCb.checked : true, - show_nav_amp_stats: ampCb ? !!ampCb.checked : true, - show_nav_help: helpCb ? !!helpCb.checked : true, - show_nav_logs: logsCb ? !!logsCb.checked : true, + show_account_pnl: chk("pref-show-account-pnl"), + show_nav_funds: chk("pref-show-nav-funds"), + show_nav_dashboard: chk("pref-show-nav-dashboard"), + show_nav_plan: chk("pref-show-nav-plan"), + show_nav_archive: chk("pref-show-nav-archive"), + show_nav_quotes: chk("pref-show-nav-quotes"), + show_nav_ai: chk("pref-show-nav-ai"), + show_nav_calculator: chk("pref-show-nav-calculator"), + show_nav_compare: chk("pref-show-nav-compare"), + show_nav_strategy: chk("pref-show-nav-strategy"), + show_nav_amp_stats: chk("pref-show-nav-amp-stats"), + show_nav_help: chk("pref-show-nav-help"), + show_nav_logs: chk("pref-show-nav-logs"), + show_monitor_binance: chk("pref-show-monitor-binance"), + show_monitor_okx_perp: chk("pref-show-monitor-okx-perp"), + show_monitor_okx_options: chk("pref-show-monitor-okx-options"), + show_monitor_gate: chk("pref-show-monitor-gate"), + show_strategy_playbook_v2: chk("pref-show-strategy-playbook-v2"), + show_strategy_playbook: chk("pref-show-strategy-playbook"), + show_strategy_behavior: chk("pref-show-strategy-behavior"), + show_strategy_binance: chk("pref-show-strategy-binance"), + show_strategy_okx: chk("pref-show-strategy-okx"), + show_strategy_gate: chk("pref-show-strategy-gate"), }, supervisor: { enabled: supEnabled ? !!supEnabled.checked : true, @@ -5210,6 +5258,9 @@ if (window.hubDashboardPage && window.hubDashboardPage.refresh) { window.hubDashboardPage.refresh(); } + if (window.hubStrategyPage && typeof window.hubStrategyPage.reloadMeta === "function") { + window.hubStrategyPage.reloadMeta(); + } if (!pageNavAllowed(currentPage())) { history.replaceState({}, "", "/monitor"); setActiveNav(); diff --git a/manual_trading_hub/static/index.html b/manual_trading_hub/static/index.html index e6e682e..51b502b 100644 --- a/manual_trading_hub/static/index.html +++ b/manual_trading_hub/static/index.html @@ -16,7 +16,7 @@ - + @@ -1382,6 +1382,50 @@ 顶栏显示「系统日志」 +

监控区卡片

+

仅隐藏监控区界面卡片,不关闭账户与后台拉取.例:只做 OKX 期权与 Gate 时可关掉币安与 OKX 永续.

+ + + + +

策略说明页签

+

关闭后该页签从策略说明中消失;顶栏「策略说明」入口仍由上方导航开关控制.

+ + + + + +

保存至 hub_settings.json,换浏览器同样生效.关闭导航后对应页面将不可从顶栏进入,直接访问 URL 会跳回监控区.

@@ -1633,7 +1677,7 @@ - + @@ -1642,6 +1686,6 @@ - + diff --git a/manual_trading_hub/static/strategy.js b/manual_trading_hub/static/strategy.js index 92127e7..13246d6 100644 --- a/manual_trading_hub/static/strategy.js +++ b/manual_trading_hub/static/strategy.js @@ -74,6 +74,14 @@ function renderExchangeTabs() { if (!tabsEl) return; + if (!tabsMeta.length) { + tabsEl.innerHTML = ""; + if (statusEl) statusEl.textContent = "当前无可显示的策略页签(可在系统设置·显示与导航中开启)"; + if (docBody) docBody.innerHTML = ""; + if (docToc) docToc.innerHTML = ""; + if (checklistBody) checklistBody.innerHTML = ""; + return; + } tabsEl.innerHTML = tabsMeta .map( (t) => @@ -274,6 +282,15 @@ renderExchangeTabs(); } + async function reloadMeta() { + try { + await loadMeta(); + if (tabsMeta.length) await loadExchange(activeKey); + } catch (e) { + if (statusEl) statusEl.textContent = String(e); + } + } + async function printSection(mode) { const part = mode === "checklist" ? "checklist" : "doc"; const url = `/api/strategy/${encodeURIComponent(activeKey)}/print?part=${encodeURIComponent(part)}`; @@ -334,7 +351,8 @@ setView(activeView); try { await loadMeta(); - await loadExchange(activeKey); + if (tabsMeta.length) await loadExchange(activeKey); + else if (statusEl) statusEl.textContent = "当前无可显示的策略页签(可在系统设置·显示与导航中开启)"; } catch (e) { if (statusEl) statusEl.textContent = String(e); } @@ -347,5 +365,5 @@ } } - window.hubStrategyPage = { init, destroy }; + window.hubStrategyPage = { init, destroy, reloadMeta }; })();