diff --git a/crypto_monitor_binance/app.py b/crypto_monitor_binance/app.py index 41fbbc3..f7f7202 100644 --- a/crypto_monitor_binance/app.py +++ b/crypto_monitor_binance/app.py @@ -7343,6 +7343,7 @@ def render_main_page(page="trade", embed_mode=None): **display_prefs_template_context(get_db), **settings_page_context( page, + instance_base_dir=BASE_DIR, exchange_key="binance", exchange_display=EXCHANGE_DISPLAY_NAME, risk_status=risk_status, diff --git a/crypto_monitor_gate/app.py b/crypto_monitor_gate/app.py index e246323..ac864a7 100644 --- a/crypto_monitor_gate/app.py +++ b/crypto_monitor_gate/app.py @@ -7146,6 +7146,7 @@ def render_main_page(page="trade", embed_mode=None): **display_prefs_template_context(get_db), **settings_page_context( page, + instance_base_dir=BASE_DIR, exchange_key="gate", exchange_display=EXCHANGE_DISPLAY_NAME, risk_status=risk_status, diff --git a/crypto_monitor_okx/app.py b/crypto_monitor_okx/app.py index 1bc0cfc..dded600 100644 --- a/crypto_monitor_okx/app.py +++ b/crypto_monitor_okx/app.py @@ -6747,6 +6747,7 @@ def render_main_page(page="trade", embed_mode=None): **display_prefs_template_context(get_db), **settings_page_context( page, + instance_base_dir=BASE_DIR, exchange_key="okx", exchange_display=EXCHANGE_DISPLAY_NAME, risk_status=risk_status, diff --git a/lib/common/static/instance_settings_prefs.js b/lib/common/static/instance_settings_prefs.js index 2e4c9cc..2bc300d 100644 --- a/lib/common/static/instance_settings_prefs.js +++ b/lib/common/static/instance_settings_prefs.js @@ -56,13 +56,29 @@ return d[key] !== false; } - async function loadDisplayPrefsForm() { - const pane = document.querySelector('.embed-tab-pane.is-active-pane') || document; - const root = pane.querySelector ? pane.querySelector("#display-prefs-form") : document.getElementById("display-prefs-form"); - if (!root) { - const fallback = document.getElementById("display-prefs-form"); - if (!fallback) return; - return loadDisplayPrefsFormIn(fallback); + function displayPrefsRoot() { + const pane = document.querySelector(".embed-tab-pane.is-active-pane"); + if (pane) { + const inPane = pane.querySelector("#display-prefs-form"); + if (inPane) return inPane; + } + return document.getElementById("display-prefs-form"); + } + + function envConfigGrid() { + const pane = document.querySelector(".embed-tab-pane.is-active-pane"); + if (pane) { + const inPane = pane.querySelector("#env-config-grid"); + if (inPane) return inPane; + } + return document.getElementById("env-config-grid"); + } + + async function loadDisplayPrefsForm(force) { + const root = displayPrefsRoot(); + if (!root) return; + if (!force && root.getAttribute("data-prefs-ssr") === "1" && root.querySelector("[data-pref-key]")) { + return; } return loadDisplayPrefsFormIn(root); } @@ -96,6 +112,7 @@ section.appendChild(grid); root.appendChild(section); }); + root.setAttribute("data-prefs-ssr", "1"); } catch (e) { root.innerHTML = '' + (e.message || "加载失败") + ""; } @@ -103,8 +120,9 @@ async function saveDisplayPrefs() { const status = document.getElementById("display-prefs-status"); + const root = displayPrefsRoot(); const display = {}; - document.querySelectorAll("#display-prefs-form input[data-pref-key]").forEach((cb) => { + (root ? root.querySelectorAll("input[data-pref-key]") : []).forEach((cb) => { display[cb.dataset.prefKey] = !!cb.checked; }); try { @@ -165,12 +183,13 @@ return card; } - async function loadEnvConfig() { - const pane = document.querySelector('.embed-tab-pane.is-active-pane') || document; - const grid = pane.querySelector ? pane.querySelector("#env-config-grid") : document.getElementById("env-config-grid"); - const target = grid || document.getElementById("env-config-grid"); - if (!target) return; - return loadEnvConfigIn(target); + async function loadEnvConfig(force) { + const grid = envConfigGrid(); + if (!grid) return; + if (!force && grid.getAttribute("data-env-ssr") === "1" && grid.querySelector("[data-env-key]")) { + return; + } + return loadEnvConfigIn(grid); } async function loadEnvConfigIn(grid) { @@ -192,14 +211,17 @@ card.appendChild(inner); grid.appendChild(card); }); + grid.setAttribute("data-env-ssr", "1"); } catch (e) { grid.innerHTML = '' + (e.message || "加载失败") + ""; } } function collectEnvValues() { + const grid = envConfigGrid(); const values = {}; - document.querySelectorAll(".env-field-input[data-env-key]").forEach((el) => { + const scope = grid || document; + scope.querySelectorAll(".env-field-input[data-env-key]").forEach((el) => { values[el.dataset.envKey] = el.value; }); return values; @@ -276,15 +298,15 @@ const eRestart = document.getElementById("env-config-save-restart"); if (eRestart) eRestart.addEventListener("click", () => saveEnvConfig(true)); const eReload = document.getElementById("env-config-reload"); - if (eReload) eReload.addEventListener("click", loadEnvConfig); + if (eReload) eReload.addEventListener("click", () => loadEnvConfig(true)); const pSave = document.getElementById("pwd-save-btn"); if (pSave) pSave.addEventListener("click", savePassword); } function initPage() { bindEvents(); - if (document.getElementById("display-prefs-form")) loadDisplayPrefsForm(); - if (document.getElementById("env-config-grid")) loadEnvConfig(); + loadDisplayPrefsForm(false); + loadEnvConfig(false); if (global.__INSTANCE_DISPLAY__) applyDisplayToNav(global.__INSTANCE_DISPLAY__); } diff --git a/lib/instance/instance_display_prefs_lib.py b/lib/instance/instance_display_prefs_lib.py index ca5b02e..e814641 100644 --- a/lib/instance/instance_display_prefs_lib.py +++ b/lib/instance/instance_display_prefs_lib.py @@ -84,7 +84,7 @@ def save_display_prefs(get_db: Callable, prefs: dict) -> dict[str, bool]: def display_prefs_template_context(get_db: Callable) -> dict[str, Any]: prefs = get_display_prefs(get_db) - return {"display": prefs} + return {"display": prefs, "display_meta": display_meta_for_ui()} def tab_allowed(tab: str, display: Optional[dict[str, bool]] = None) -> bool: diff --git a/lib/instance/instance_settings_lib.py b/lib/instance/instance_settings_lib.py index cacbd65..9024171 100644 --- a/lib/instance/instance_settings_lib.py +++ b/lib/instance/instance_settings_lib.py @@ -183,8 +183,15 @@ def build_instance_settings_view( } -def settings_page_context(page: str, **kwargs: Any) -> dict[str, Any]: +def settings_page_context(page: str, *, instance_base_dir: str | None = None, **kwargs: Any) -> dict[str, Any]: p = (page or "").strip() if p not in ("settings", "risk_policy", "env_config"): return {} - return {"instance_settings": build_instance_settings_view(**kwargs)} + ctx: dict[str, Any] = {"instance_settings": build_instance_settings_view(**kwargs)} + if p == "env_config" and instance_base_dir: + from lib.env.env_schema import build_env_payload + + env_path = os.path.join(instance_base_dir, ".env") + example_path = os.path.join(instance_base_dir, ".env.example") + ctx["env_config_groups"] = build_env_payload(example_path, env_path).get("groups") or [] + return ctx diff --git a/lib/instance/templates/display_prefs_panel.html b/lib/instance/templates/display_prefs_panel.html index 5fc8fb6..3177c7c 100644 --- a/lib/instance/templates/display_prefs_panel.html +++ b/lib/instance/templates/display_prefs_panel.html @@ -1,9 +1,25 @@ -{# 系统设置 · 导航显示开关 #} +{# 系统设置 · 导航显示开关(SSR 预渲染,保存仍走 API) #}
以下开关控制顶栏导航与系统设置内区块是否显示,保存后立即生效。关键位监控、实盘下单、系统设置为固定项。
-