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 <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-24 00:24:00 +08:00
parent 29d59d6a53
commit 6f1ae14b3d
7 changed files with 367 additions and 200 deletions
+24 -5
View File
@@ -236,11 +236,30 @@ def load_strategy_payload(exchange_key: str) -> dict[str, Any]:
} }
def strategy_meta_payload() -> dict[str, Any]: _STRATEGY_TAB_DISPLAY_PREF: dict[str, str] = {
tabs = [ "playbook_v2": "show_strategy_playbook_v2",
{"key": k, "label": STRATEGY_META[k]["label"], "title": STRATEGY_META[k]["title"]} "playbook": "show_strategy_playbook",
for k in STRATEGY_EXCHANGES "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} return {"ok": True, "exchanges": tabs}
+12 -1
View File
@@ -1119,6 +1119,16 @@ class SettingsDisplayBody(BaseModel):
show_nav_amp_stats: bool = True show_nav_amp_stats: bool = True
show_nav_help: bool = True show_nav_help: bool = True
show_nav_logs: 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): class SupervisorSettingsBody(BaseModel):
@@ -3348,7 +3358,8 @@ async def api_archive_sync():
@app.get("/api/strategy/meta") @app.get("/api/strategy/meta")
def 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") @app.get("/api/help/meta")
+12
View File
@@ -34,6 +34,18 @@ DEFAULT_DISPLAY = {
"show_nav_amp_stats": True, "show_nav_amp_stats": True,
"show_nav_help": True, "show_nav_help": True,
"show_nav_logs": 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 = [ DEFAULT_EXCHANGES = [
+127 -115
View File
@@ -3501,6 +3501,18 @@ button.btn-sm {
margin-top: 8px; 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 { .settings-display-hint {
margin: 8px 0 0; margin: 8px 0 0;
font-size: 0.78rem; font-size: 0.78rem;
@@ -11008,118 +11020,118 @@ html[data-theme="light"] .hub-logs-card-hint {
.amp-form { grid-template-columns: 1fr 1fr; } .amp-form { grid-template-columns: 1fr 1fr; }
.amp-actions { grid-column: 1 / -1; } .amp-actions { grid-column: 1 / -1; }
} }
/* --- strategy compare --- */ /* --- strategy compare --- */
#page-compare .toolbar { #page-compare .toolbar {
padding: 12px 16px; padding: 12px 16px;
margin-bottom: 14px; margin-bottom: 14px;
} }
.cmp-form { display: flex; flex-direction: column; gap: 14px; margin-bottom: 16px; } .cmp-form { display: flex; flex-direction: column; gap: 14px; margin-bottom: 16px; }
.cmp-form .card, .cmp-form .card,
.cmp-common-card, .cmp-common-card,
.cmp-sum-card, .cmp-sum-card,
.cmp-rec-card { .cmp-rec-card {
padding: 18px 20px; padding: 18px 20px;
} }
.cmp-common-card h2, .cmp-common-card h2,
.cmp-form .card h2 { .cmp-form .card h2 {
margin: 0 0 14px; margin: 0 0 14px;
font-size: 15px; font-size: 15px;
} }
.cmp-subhead { .cmp-subhead {
margin: 16px 0 10px; margin: 16px 0 10px;
font-size: 13px; font-size: 13px;
color: var(--muted); color: var(--muted);
font-weight: 600; font-weight: 600;
} }
.cmp-form-grid { .cmp-form-grid {
display: grid; display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 14px 16px; gap: 14px 16px;
} }
.cmp-field { .cmp-field {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 6px; gap: 6px;
font-size: 12px; font-size: 12px;
color: var(--muted); color: var(--muted);
} }
.cmp-field input, .cmp-field input,
.cmp-field select { .cmp-field select {
background: var(--inset-surface); background: var(--inset-surface);
border: 1px solid var(--border-soft); border: 1px solid var(--border-soft);
border-radius: 8px; border-radius: 8px;
color: var(--text); color: var(--text);
padding: 9px 12px; padding: 9px 12px;
font-size: 13px; font-size: 13px;
} }
.cmp-input-cols { .cmp-input-cols {
display: grid; display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 14px; gap: 14px;
} }
.cmp-summary { .cmp-summary {
display: grid; display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 14px; gap: 14px;
margin-bottom: 16px; margin-bottom: 16px;
} }
.cmp-sum-card h3 { margin: 0 0 12px; font-size: 14px; } .cmp-sum-card h3 { margin: 0 0 12px; font-size: 14px; }
.cmp-sum-row { .cmp-sum-row {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
gap: 12px; gap: 12px;
font-size: 12px; font-size: 12px;
margin: 6px 0; margin: 6px 0;
color: var(--muted); color: var(--muted);
} }
.cmp-sum-row strong { color: var(--text); font-weight: 600; } .cmp-sum-row strong { color: var(--text); font-weight: 600; }
.cmp-muted { color: var(--muted); font-size: 12px; margin: 0; } .cmp-muted { color: var(--muted); font-size: 12px; margin: 0; }
.cmp-table-wrap { margin-bottom: 16px; } .cmp-table-wrap { margin-bottom: 16px; }
.cmp-table-scroll { overflow-x: auto; } .cmp-table-scroll { overflow-x: auto; }
.cmp-table { .cmp-table {
width: 100%; width: 100%;
border-collapse: separate; border-collapse: separate;
border-spacing: 0; border-spacing: 0;
font-size: 13px; font-size: 13px;
background: var(--panel); background: var(--panel);
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: var(--radius); border-radius: var(--radius);
overflow: hidden; overflow: hidden;
} }
.cmp-table th, .cmp-table th,
.cmp-table td { .cmp-table td {
border-bottom: 1px solid var(--border-soft); border-bottom: 1px solid var(--border-soft);
padding: 14px 16px; padding: 14px 16px;
vertical-align: top; vertical-align: top;
text-align: left; text-align: left;
} }
.cmp-table th:first-child, .cmp-table th:first-child,
.cmp-table td:first-child { width: 22%; } .cmp-table td:first-child { width: 22%; }
.cmp-table tr:last-child td { border-bottom: none; } .cmp-table tr:last-child td { border-bottom: none; }
.cmp-cell-note { .cmp-cell-note {
margin-top: 6px; margin-top: 6px;
font-size: 11px; font-size: 11px;
color: var(--muted); color: var(--muted);
line-height: 1.4; line-height: 1.4;
} }
.cmp-pnl-pos { color: var(--green); font-weight: 600; } .cmp-pnl-pos { color: var(--green); font-weight: 600; }
.cmp-pnl-neg { color: var(--red); font-weight: 600; } .cmp-pnl-neg { color: var(--red); font-weight: 600; }
.cmp-rec-head { font-size: 16px; margin-bottom: 8px; } .cmp-rec-head { font-size: 16px; margin-bottom: 8px; }
.cmp-rec-reason { margin: 0 0 10px; color: var(--muted); font-size: 13px; } .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-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-warn { margin-top: 12px; font-size: 12px; color: var(--warn, #e6a23c); }
.cmp-foot-note { margin: 12px 0 0; font-size: 11px; color: var(--muted); } .cmp-foot-note { margin: 12px 0 0; font-size: 11px; color: var(--muted); }
@media (max-width: 900px) { @media (max-width: 900px) {
.cmp-form .card, .cmp-form .card,
.cmp-common-card, .cmp-common-card,
.cmp-sum-card, .cmp-sum-card,
.cmp-rec-card { .cmp-rec-card {
padding: 16px; padding: 16px;
} }
.cmp-form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .cmp-form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.cmp-input-cols, .cmp-input-cols,
.cmp-summary { grid-template-columns: 1fr; } .cmp-summary { grid-template-columns: 1fr; }
.cmp-table th, .cmp-table th,
.cmp-table td { padding: 12px 14px; } .cmp-table td { padding: 12px 14px; }
} }
+125 -74
View File
@@ -9,12 +9,42 @@
return !!d[key]; return !!d[key];
} }
window.hubDisplayPref = displayPref;
function showAccountPnlPref() { function showAccountPnlPref() {
return displayPref("show_account_pnl", true); return displayPref("show_account_pnl", true);
} }
window.hubShowAccountPnlPref = showAccountPnlPref; 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() { function showNavFundsPref() {
return displayPref("show_nav_funds", true); return displayPref("show_nav_funds", true);
} }
@@ -157,32 +187,33 @@
function syncDisplayPrefsUI(data) { function syncDisplayPrefsUI(data) {
const d = (data && data.display) || {}; const d = (data && data.display) || {};
const pnlCb = document.getElementById("pref-show-account-pnl"); const setChk = (id, key) => {
const fundsCb = document.getElementById("pref-show-nav-funds"); const el = document.getElementById(id);
const dashCb = document.getElementById("pref-show-nav-dashboard"); if (el) el.checked = d[key] !== false;
const planCb = document.getElementById("pref-show-nav-plan"); };
const archiveCb = document.getElementById("pref-show-nav-archive"); setChk("pref-show-account-pnl", "show_account_pnl");
const quotesCb = document.getElementById("pref-show-nav-quotes"); setChk("pref-show-nav-funds", "show_nav_funds");
const aiCb = document.getElementById("pref-show-nav-ai"); setChk("pref-show-nav-dashboard", "show_nav_dashboard");
const calcCb = document.getElementById("pref-show-nav-calculator"); setChk("pref-show-nav-plan", "show_nav_plan");
const compareCb = document.getElementById("pref-show-nav-compare"); setChk("pref-show-nav-archive", "show_nav_archive");
const strategyCb = document.getElementById("pref-show-nav-strategy"); setChk("pref-show-nav-quotes", "show_nav_quotes");
const ampCb = document.getElementById("pref-show-nav-amp-stats"); setChk("pref-show-nav-ai", "show_nav_ai");
const helpCb = document.getElementById("pref-show-nav-help"); setChk("pref-show-nav-calculator", "show_nav_calculator");
const logsCb = document.getElementById("pref-show-nav-logs"); setChk("pref-show-nav-compare", "show_nav_compare");
if (pnlCb) pnlCb.checked = d.show_account_pnl !== false; setChk("pref-show-nav-strategy", "show_nav_strategy");
if (fundsCb) fundsCb.checked = d.show_nav_funds !== false; setChk("pref-show-nav-amp-stats", "show_nav_amp_stats");
if (dashCb) dashCb.checked = d.show_nav_dashboard !== false; setChk("pref-show-nav-help", "show_nav_help");
if (planCb) planCb.checked = d.show_nav_plan !== false; setChk("pref-show-nav-logs", "show_nav_logs");
if (archiveCb) archiveCb.checked = d.show_nav_archive !== false; setChk("pref-show-monitor-binance", "show_monitor_binance");
if (quotesCb) quotesCb.checked = d.show_nav_quotes !== false; setChk("pref-show-monitor-okx-perp", "show_monitor_okx_perp");
if (aiCb) aiCb.checked = d.show_nav_ai !== false; setChk("pref-show-monitor-okx-options", "show_monitor_okx_options");
if (calcCb) calcCb.checked = d.show_nav_calculator !== false; setChk("pref-show-monitor-gate", "show_monitor_gate");
if (compareCb) compareCb.checked = d.show_nav_compare !== false; setChk("pref-show-strategy-playbook-v2", "show_strategy_playbook_v2");
if (strategyCb) strategyCb.checked = d.show_nav_strategy !== false; setChk("pref-show-strategy-playbook", "show_strategy_playbook");
if (ampCb) ampCb.checked = d.show_nav_amp_stats !== false; setChk("pref-show-strategy-behavior", "show_strategy_behavior");
if (helpCb) helpCb.checked = d.show_nav_help !== false; setChk("pref-show-strategy-binance", "show_strategy_binance");
if (logsCb) logsCb.checked = d.show_nav_logs !== false; setChk("pref-show-strategy-okx", "show_strategy_okx");
setChk("pref-show-strategy-gate", "show_strategy_gate");
syncNavVisibility(data); syncNavVisibility(data);
} }
@@ -1569,7 +1600,7 @@
if (upd) upd.textContent = txt; if (upd) upd.textContent = txt;
if (updSum) updSum.textContent = txt; if (updSum) updSum.textContent = txt;
} }
updateMonitorAlertSummary(rows || []); updateMonitorAlertSummary(filterVisibleMonitorRows(rows || []));
void refreshMacroRiskBanner(rows || []); void refreshMacroRiskBanner(rows || []);
renderMonitorGrid(rows || []); renderMonitorGrid(rows || []);
} }
@@ -2080,19 +2111,20 @@
if (lastMonitorRows.length && nowMobile !== wasMobile) { if (lastMonitorRows.length && nowMobile !== wasMobile) {
wasMobile = nowMobile; wasMobile = nowMobile;
renderMonitorGrid(lastMonitorRows); renderMonitorGrid(lastMonitorRows);
updateMonitorAlertSummary(lastMonitorRows); updateMonitorAlertSummary(filterVisibleMonitorRows(lastMonitorRows));
syncHubMobileTabActive(currentPage()); syncHubMobileTabActive(currentPage());
return; return;
} }
wasMobile = nowMobile; wasMobile = nowMobile;
const box = document.getElementById("monitor-grid"); const box = document.getElementById("monitor-grid");
if (box && lastMonitorRows.length) { if (box && lastMonitorRows.length) {
const split = monitorOptionsSplitActive(lastMonitorRows); const visible = filterVisibleMonitorRows(lastMonitorRows);
syncMonitorGridColumns(box, lastMonitorRows.length + (lastMonitorTotals ? 1 : 0), { const split = monitorOptionsSplitActive(visible);
syncMonitorGridColumns(box, visible.length + (lastMonitorTotals ? 1 : 0), {
statsFirst: !!lastMonitorTotals && !split, statsFirst: !!lastMonitorTotals && !split,
optionsSplit: split, optionsSplit: split,
}); });
updateMonitorAlertSummary(lastMonitorRows); updateMonitorAlertSummary(visible);
} }
syncHubMobileTabActive(currentPage()); syncHubMobileTabActive(currentPage());
}, 120); }, 120);
@@ -2486,11 +2518,12 @@
const fs = document.getElementById("exchange-fullscreen"); const fs = document.getElementById("exchange-fullscreen");
const fsInner = document.getElementById("exchange-fullscreen-inner"); const fsInner = document.getElementById("exchange-fullscreen-inner");
if (!box) return; 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(); closeExchangeFullscreen();
} }
const mobileTiles = isMobileLayout() && !expandedExchangeId; const mobileTiles = isMobileLayout() && !expandedExchangeId;
const displayRows = mobileTiles ? sortRowsForMobileDashboard(rows) : rows; const displayRows = mobileTiles ? sortRowsForMobileDashboard(visibleSource) : visibleSource;
const optionsSplit = monitorOptionsSplitActive(displayRows); const optionsSplit = monitorOptionsSplitActive(displayRows);
monitorGridOptionsSplit = optionsSplit; monitorGridOptionsSplit = optionsSplit;
const showStatsCard = !expandedExchangeId; const showStatsCard = !expandedExchangeId;
@@ -2503,20 +2536,33 @@
let cardsHtml = ""; let cardsHtml = "";
if (optionsSplit) { if (optionsSplit) {
const okxRow = displayRows.find((r) => rowHasOptionsLayout(r)); const okxRow = displayRows.find((r) => rowHasOptionsLayout(r));
const otherRows = displayRows.filter((r) => !rowHasOptionsLayout(r)); const otherByKey = {};
const ph = displayRows
'<div class="card card-monitor-split-side card-monitor-placeholder" aria-hidden="true"></div>'; .filter((r) => !rowHasOptionsLayout(r))
/* 平铺 2×2 顺序:永续|币安 / 期权|Gate —— 同行左右同高,多仓时该行一起长高 */ .forEach((r) => {
const cells = [ otherByKey[String(r.key || "").toLowerCase()] = r;
okxRow ? renderMonitorCard(okxRow, { okxPart: "perp", splitSide: true }) : ph, });
otherRows[0] ? renderMonitorCard(otherRows[0], { splitSide: true }) : ph, /* 平铺顺序尽量保持:永续|币安 / 期权|Gate;隐藏项不占位 */
okxRow ? renderMonitorCard(okxRow, { okxPart: "options", splitSide: true }) : ph, const cells = [];
otherRows[1] ? renderMonitorCard(otherRows[1], { splitSide: true }) : ph, if (okxRow && showMonitorOkxPerpPref()) {
]; cells.push(renderMonitorCard(okxRow, { okxPart: "perp", splitSide: true }));
for (let i = 2; i < otherRows.length; i++) {
cells.push(renderMonitorCard(otherRows[i], { splitSide: true }));
} }
cardsHtml = `<div class="monitor-split-body monitor-split-2x2">${cells.join("")}</div>`; 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
? `<div class="monitor-split-body monitor-split-2x2">${cells.join("")}</div>`
: "";
} else { } else {
cardsHtml = cardsHtml =
displayRows displayRows
@@ -2545,7 +2591,7 @@
} }
if (expandedExchangeId && fs && fsInner) { 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) { if (row) {
try { try {
fsInner.innerHTML = renderFullscreenExchange(row); fsInner.innerHTML = renderFullscreenExchange(row);
@@ -3900,7 +3946,8 @@
function monitorOptionsSplitActive(rows) { function monitorOptionsSplitActive(rows) {
if (isMobileLayout() || expandedExchangeId) return false; 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) { function renderPerpetualInnerCard(row, ag, pos, orders, trends, tickMap, intraday) {
@@ -5112,19 +5159,10 @@
function collectSettingsFromUI() { function collectSettingsFromUI() {
const rows = [...document.querySelectorAll("#settings-list .settings-card")]; const rows = [...document.querySelectorAll("#settings-list .settings-card")];
const pnlCb = document.getElementById("pref-show-account-pnl"); const chk = (id) => {
const fundsCb = document.getElementById("pref-show-nav-funds"); const el = document.getElementById(id);
const dashCb = document.getElementById("pref-show-nav-dashboard"); return el ? !!el.checked : true;
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 supEnabled = document.getElementById("supervisor-enabled"); const supEnabled = document.getElementById("supervisor-enabled");
const supProg = document.getElementById("supervisor-wechat-program"); const supProg = document.getElementById("supervisor-wechat-program");
const supWebhook = document.getElementById("supervisor-wechat-webhook"); const supWebhook = document.getElementById("supervisor-wechat-webhook");
@@ -5137,19 +5175,29 @@
return { return {
version: 1, version: 1,
display: { display: {
show_account_pnl: pnlCb ? !!pnlCb.checked : true, show_account_pnl: chk("pref-show-account-pnl"),
show_nav_funds: fundsCb ? !!fundsCb.checked : true, show_nav_funds: chk("pref-show-nav-funds"),
show_nav_dashboard: dashCb ? !!dashCb.checked : true, show_nav_dashboard: chk("pref-show-nav-dashboard"),
show_nav_plan: planCb ? !!planCb.checked : true, show_nav_plan: chk("pref-show-nav-plan"),
show_nav_archive: archiveCb ? !!archiveCb.checked : true, show_nav_archive: chk("pref-show-nav-archive"),
show_nav_quotes: quotesCb ? !!quotesCb.checked : true, show_nav_quotes: chk("pref-show-nav-quotes"),
show_nav_ai: aiCb ? !!aiCb.checked : true, show_nav_ai: chk("pref-show-nav-ai"),
show_nav_calculator: calcCb ? !!calcCb.checked : true, show_nav_calculator: chk("pref-show-nav-calculator"),
show_nav_compare: compareCb ? !!compareCb.checked : true, show_nav_compare: chk("pref-show-nav-compare"),
show_nav_strategy: strategyCb ? !!strategyCb.checked : true, show_nav_strategy: chk("pref-show-nav-strategy"),
show_nav_amp_stats: ampCb ? !!ampCb.checked : true, show_nav_amp_stats: chk("pref-show-nav-amp-stats"),
show_nav_help: helpCb ? !!helpCb.checked : true, show_nav_help: chk("pref-show-nav-help"),
show_nav_logs: logsCb ? !!logsCb.checked : true, 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: { supervisor: {
enabled: supEnabled ? !!supEnabled.checked : true, enabled: supEnabled ? !!supEnabled.checked : true,
@@ -5210,6 +5258,9 @@
if (window.hubDashboardPage && window.hubDashboardPage.refresh) { if (window.hubDashboardPage && window.hubDashboardPage.refresh) {
window.hubDashboardPage.refresh(); window.hubDashboardPage.refresh();
} }
if (window.hubStrategyPage && typeof window.hubStrategyPage.reloadMeta === "function") {
window.hubStrategyPage.reloadMeta();
}
if (!pageNavAllowed(currentPage())) { if (!pageNavAllowed(currentPage())) {
history.replaceState({}, "", "/monitor"); history.replaceState({}, "", "/monitor");
setActiveNav(); setActiveNav();
+47 -3
View File
@@ -16,7 +16,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" media="print" onload="this.media='all'" /> <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" media="print" onload="this.media='all'" />
<noscript><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" /></noscript> <noscript><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" /></noscript>
<link rel="stylesheet" href="/assets/app.css?v=20260723-cmp-pad" /> <link rel="stylesheet" href="/assets/app.css?v=20260724-display-hide" />
<link rel="stylesheet" href="/assets/trade_stats_calendar.css?v=4" /> <link rel="stylesheet" href="/assets/trade_stats_calendar.css?v=4" />
<link rel="stylesheet" href="/assets/account_risk_badge.css?v=4" /> <link rel="stylesheet" href="/assets/account_risk_badge.css?v=4" />
<script src="/assets/account_risk_badge.js?v=4"></script> <script src="/assets/account_risk_badge.js?v=4"></script>
@@ -1382,6 +1382,50 @@
<input type="checkbox" id="pref-show-nav-logs" checked /> <input type="checkbox" id="pref-show-nav-logs" checked />
顶栏显示「系统日志」 顶栏显示「系统日志」
</label> </label>
<p class="settings-display-subtitle">监控区卡片</p>
<p class="settings-display-hint">仅隐藏监控区界面卡片,不关闭账户与后台拉取.例:只做 OKX 期权与 Gate 时可关掉币安与 OKX 永续.</p>
<label class="chk-label settings-display-chk">
<input type="checkbox" id="pref-show-monitor-binance" checked />
监控区显示「币安」
</label>
<label class="chk-label settings-display-chk">
<input type="checkbox" id="pref-show-monitor-okx-perp" checked />
监控区显示「OKX 永续」
</label>
<label class="chk-label settings-display-chk">
<input type="checkbox" id="pref-show-monitor-okx-options" checked />
监控区显示「OKX 期权」
</label>
<label class="chk-label settings-display-chk">
<input type="checkbox" id="pref-show-monitor-gate" checked />
监控区显示「Gate」
</label>
<p class="settings-display-subtitle">策略说明页签</p>
<p class="settings-display-hint">关闭后该页签从策略说明中消失;顶栏「策略说明」入口仍由上方导航开关控制.</p>
<label class="chk-label settings-display-chk">
<input type="checkbox" id="pref-show-strategy-playbook-v2" checked />
策略说明显示「执行手册v2」
</label>
<label class="chk-label settings-display-chk">
<input type="checkbox" id="pref-show-strategy-playbook" checked />
策略说明显示「执行手册v1」
</label>
<label class="chk-label settings-display-chk">
<input type="checkbox" id="pref-show-strategy-behavior" checked />
策略说明显示「行为准则」
</label>
<label class="chk-label settings-display-chk">
<input type="checkbox" id="pref-show-strategy-binance" checked />
策略说明显示「币安」
</label>
<label class="chk-label settings-display-chk">
<input type="checkbox" id="pref-show-strategy-okx" checked />
策略说明显示「OKX」
</label>
<label class="chk-label settings-display-chk">
<input type="checkbox" id="pref-show-strategy-gate" checked />
策略说明显示「Gate」
</label>
<p class="settings-display-hint">保存至 hub_settings.json,换浏览器同样生效.关闭导航后对应页面将不可从顶栏进入,直接访问 URL 会跳回监控区.</p> <p class="settings-display-hint">保存至 hub_settings.json,换浏览器同样生效.关闭导航后对应页面将不可从顶栏进入,直接访问 URL 会跳回监控区.</p>
</section> </section>
@@ -1633,7 +1677,7 @@
<script src="/assets/quotes.js?v=20260717-quotes-feed"></script> <script src="/assets/quotes.js?v=20260717-quotes-feed"></script>
<script src="/assets/funds.js?v=20260717-funds-scroll-fix"></script> <script src="/assets/funds.js?v=20260717-funds-scroll-fix"></script>
<script src="/assets/dashboard.js?v=20260723-hide-pnl"></script> <script src="/assets/dashboard.js?v=20260723-hide-pnl"></script>
<script src="/assets/strategy.js?v=10"></script> <script src="/assets/strategy.js?v=11"></script>
<script src="/assets/amp_stats.js?v=5"></script> <script src="/assets/amp_stats.js?v=5"></script>
<script src="/assets/help.js?v=1"></script> <script src="/assets/help.js?v=1"></script>
<script src="/assets/logs.js?v=1"></script> <script src="/assets/logs.js?v=1"></script>
@@ -1642,6 +1686,6 @@
<script src="/assets/options_expiry_countdown.js?v=1"></script> <script src="/assets/options_expiry_countdown.js?v=1"></script>
<script src="/assets/options_position_cards.js?v=3"></script> <script src="/assets/options_position_cards.js?v=3"></script>
<script src="/assets/backup.js?v=1"></script> <script src="/assets/backup.js?v=1"></script>
<script src="/assets/app.js?v=20260723-compare"></script> <script src="/assets/app.js?v=20260724-display-hide"></script>
</body> </body>
</html> </html>
+20 -2
View File
@@ -74,6 +74,14 @@
function renderExchangeTabs() { function renderExchangeTabs() {
if (!tabsEl) return; 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 tabsEl.innerHTML = tabsMeta
.map( .map(
(t) => (t) =>
@@ -274,6 +282,15 @@
renderExchangeTabs(); 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) { async function printSection(mode) {
const part = mode === "checklist" ? "checklist" : "doc"; const part = mode === "checklist" ? "checklist" : "doc";
const url = `/api/strategy/${encodeURIComponent(activeKey)}/print?part=${encodeURIComponent(part)}`; const url = `/api/strategy/${encodeURIComponent(activeKey)}/print?part=${encodeURIComponent(part)}`;
@@ -334,7 +351,8 @@
setView(activeView); setView(activeView);
try { try {
await loadMeta(); await loadMeta();
await loadExchange(activeKey); if (tabsMeta.length) await loadExchange(activeKey);
else if (statusEl) statusEl.textContent = "当前无可显示的策略页签(可在系统设置·显示与导航中开启)";
} catch (e) { } catch (e) {
if (statusEl) statusEl.textContent = String(e); if (statusEl) statusEl.textContent = String(e);
} }
@@ -347,5 +365,5 @@
} }
} }
window.hubStrategyPage = { init, destroy }; window.hubStrategyPage = { init, destroy, reloadMeta };
})(); })();