diff --git a/manual_trading_hub/hub.py b/manual_trading_hub/hub.py index 752c816..6a21cc1 100644 --- a/manual_trading_hub/hub.py +++ b/manual_trading_hub/hub.py @@ -737,6 +737,8 @@ def api_get_settings(): class SettingsDisplayBody(BaseModel): show_account_pnl: bool = True + show_nav_funds: bool = True + show_nav_dashboard: bool = True class SettingsBody(BaseModel): diff --git a/manual_trading_hub/settings_store.py b/manual_trading_hub/settings_store.py index a4a4e26..142852e 100644 --- a/manual_trading_hub/settings_store.py +++ b/manual_trading_hub/settings_store.py @@ -11,6 +11,8 @@ SETTINGS_PATH = DIR / "hub_settings.json" DEFAULT_DISPLAY = { "show_account_pnl": True, + "show_nav_funds": True, + "show_nav_dashboard": True, } DEFAULT_EXCHANGES = [ @@ -72,8 +74,9 @@ def env_force_disabled_ids() -> set[str]: def normalize_display_prefs(raw: dict | None) -> dict: out = dict(DEFAULT_DISPLAY) if isinstance(raw, dict): - if "show_account_pnl" in raw: - out["show_account_pnl"] = bool(raw.get("show_account_pnl")) + for key in DEFAULT_DISPLAY: + if key in raw: + out[key] = bool(raw.get(key)) return out diff --git a/manual_trading_hub/static/app.css b/manual_trading_hub/static/app.css index 2d170be..ba7bb98 100644 --- a/manual_trading_hub/static/app.css +++ b/manual_trading_hub/static/app.css @@ -326,6 +326,10 @@ a:hover { transition: background 0.15s, color 0.15s, box-shadow 0.15s; } +.top-nav a.nav-hidden { + display: none !important; +} + .top-nav a:hover { color: var(--text); background: var(--panel-hover); @@ -2176,9 +2180,16 @@ button.btn-sm { } .settings-display-chk { + display: flex; + align-items: center; + gap: 8px; font-size: 0.88rem; } +.settings-display-chk + .settings-display-chk { + margin-top: 8px; +} + .settings-display-hint { margin: 8px 0 0; font-size: 0.78rem; diff --git a/manual_trading_hub/static/app.js b/manual_trading_hub/static/app.js index 7c05dbb..54a6479 100644 --- a/manual_trading_hub/static/app.js +++ b/manual_trading_hub/static/app.js @@ -3,17 +3,47 @@ let settingsCache = null; let authState = { required: false, logged_in: true }; - function showAccountPnlPref() { + function displayPref(key, defaultOn) { const d = settingsCache && settingsCache.display; - if (!d || d.show_account_pnl === undefined) return true; - return !!d.show_account_pnl; + if (!d || d[key] === undefined) return defaultOn !== false; + return !!d[key]; + } + + function showAccountPnlPref() { + return displayPref("show_account_pnl", true); + } + + function showNavFundsPref() { + return displayPref("show_nav_funds", true); + } + + function showNavDashboardPref() { + return displayPref("show_nav_dashboard", true); + } + + function syncNavVisibility(data) { + const d = (data && data.display) || {}; + const navFunds = document.getElementById("nav-funds"); + const navDash = document.getElementById("nav-dashboard"); + if (navFunds) navFunds.classList.toggle("nav-hidden", d.show_nav_funds === false); + if (navDash) navDash.classList.toggle("nav-hidden", d.show_nav_dashboard === false); + } + + function pageNavAllowed(page) { + if (page === "funds") return showNavFundsPref(); + if (page === "dashboard") return showNavDashboardPref(); + return true; } function syncDisplayPrefsUI(data) { - const cb = document.getElementById("pref-show-account-pnl"); - if (!cb) return; - const show = data && data.display ? data.display.show_account_pnl : true; - cb.checked = show !== false; + 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"); + 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; + syncNavVisibility(data); } function positionTableHeadHtml(compact) { @@ -662,7 +692,11 @@ } function setActiveNav() { - const page = currentPage(); + let page = currentPage(); + if (!pageNavAllowed(page)) { + history.replaceState({}, "", "/monitor"); + page = "monitor"; + } const pageId = pageElementId(page); document.querySelectorAll(".top-nav a").forEach((a) => { const href = (a.getAttribute("href") || "").split("?")[0]; @@ -857,6 +891,7 @@ async function loadSettings() { const r = await apiFetch("/api/settings"); settingsCache = await r.json(); + syncNavVisibility(settingsCache); return settingsCache; } @@ -3055,10 +3090,14 @@ 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"); 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, }, exchanges: rows.map((card) => { const caps = []; @@ -3100,6 +3139,10 @@ await loadSettingsUI(); } if (lastMonitorRows.length) renderMonitorGrid(lastMonitorRows); + if (!pageNavAllowed(currentPage())) { + history.replaceState({}, "", "/monitor"); + setActiveNav(); + } } else showToast("保存失败", true); } catch (e) { showToast(String(e), true); diff --git a/manual_trading_hub/static/index.html b/manual_trading_hub/static/index.html index 88af80c..e4a9100 100644 --- a/manual_trading_hub/static/index.html +++ b/manual_trading_hub/static/index.html @@ -502,12 +502,20 @@

-

监控区显示

+

显示与导航

-

关闭后监控区不显示上述数值;保存至 hub_settings.json,换浏览器同样生效。

+ + +

保存至 hub_settings.json,换浏览器同样生效。关闭导航后对应页面将不可从顶栏进入。

@@ -547,6 +555,6 @@ - + diff --git a/manual_trading_hub/使用说明.md b/manual_trading_hub/使用说明.md index c27116a..d2fd798 100644 --- a/manual_trading_hub/使用说明.md +++ b/manual_trading_hub/使用说明.md @@ -236,6 +236,14 @@ Chrome **桌面快捷方式**图标来自站点 `favicon` / `manifest`(已配 **可用**:打开 http://127.0.0.1:5100/settings ,修改表格后点 **保存设置** 即写入 `hub_settings.json`;**重新加载** 从磁盘/默认再读(会重新套用 `HUB_DISABLED_IDS`)。保存后监控区立即使用新 URL/启用状态,**无需重启 hub**。 +**显示与导航**(`hub_settings.json` → `display`): + +| 开关 | 说明 | +|------|------| +| 监控区资金/浮盈 | 关闭后监控卡片不显示资金户、交易户、浮盈亏列 | +| 顶栏「资金概况」 | 关闭后隐藏导航;直接访问 `/funds` 会跳回监控区 | +| 顶栏「数据看板」 | 关闭后隐藏导航;直接访问 `/dashboard` 会跳回监控区 | + **下单、关键位、策略交易**:请在监控卡片点击 **「实例」** 或 **「策略交易」**(SSO),进入各 `crypto_monitor_*` 网页(`/trade`、`/key_monitor`、`/strategy`、`/strategy/records` 等)。中控 **不** 提供下单区;**策略交易记录** 仅在实例顶栏查看(见 [策略交易说明.md](../策略交易说明.md) §五)。 | 列 | 含义 |