Fix settings and env config stuck on loading via SSR form render
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 = '<span class="err">' + (e.message || "加载失败") + "</span>";
|
||||
}
|
||||
@@ -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 = '<span class="err">' + (e.message || "加载失败") + "</span>";
|
||||
}
|
||||
}
|
||||
|
||||
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__);
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,9 +1,25 @@
|
||||
{# 系统设置 · 导航显示开关 #}
|
||||
{# 系统设置 · 导航显示开关(SSR 预渲染,保存仍走 API) #}
|
||||
<div class="card settings-card settings-card--standalone" id="display-prefs-card">
|
||||
<h2>导航显示</h2>
|
||||
<p class="settings-env-hint">以下开关控制顶栏导航与系统设置内区块是否显示,保存后立即生效。关键位监控、实盘下单、系统设置为固定项。</p>
|
||||
<div id="display-prefs-form" class="display-prefs-form">
|
||||
<div id="display-prefs-form" class="display-prefs-form" data-prefs-ssr="1">
|
||||
{% if display_meta %}
|
||||
{% for group in display_meta %}
|
||||
<div class="display-prefs-group">
|
||||
<h3 class="settings-subcard-title">{{ group.group }}</h3>
|
||||
<div class="display-prefs-checks">
|
||||
{% for item in group.keys %}
|
||||
<label class="chk-label">
|
||||
<input type="checkbox" data-pref-key="{{ item.key }}"{% if display.get(item.key, true) %} checked{% endif %}>
|
||||
{{ item.label }}
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<div class="display-prefs-loading muted">加载中…</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="settings-actions-row">
|
||||
<button type="button" class="btn-primary btn-sm" id="display-prefs-save">保存导航设置</button>
|
||||
|
||||
@@ -103,7 +103,7 @@ const ORDER_ENTRY_MODEL_CODE_TO_CATEGORY = {{ entry_model_code_to_category | toj
|
||||
<script>
|
||||
window.__INSTANCE_DISPLAY__ = {{ display | tojson }};
|
||||
</script>
|
||||
<script src="/static/instance_settings_prefs.js?v=2"></script>
|
||||
<script src="/static/instance_settings_prefs.js?v=3"></script>
|
||||
<script src="/static/instance_live.js?v=4"></script>
|
||||
<script src="/static/instance_embed.js?v=18"></script>
|
||||
</body>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{# env配置:按功能分组,三列卡片布局 #}
|
||||
{# env配置:按功能分组,三列卡片布局(SSR 预渲染) #}
|
||||
<div class="env-config-page">
|
||||
<div class="env-config-head card">
|
||||
<h2>env 配置</h2>
|
||||
@@ -10,7 +10,46 @@
|
||||
<span class="settings-status-line" id="env-config-status"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="env-config-grid" class="env-config-grid">
|
||||
<div id="env-config-grid" class="env-config-grid"{% if env_config_groups %} data-env-ssr="1"{% endif %}>
|
||||
{% if env_config_groups %}
|
||||
{% for group in env_config_groups %}
|
||||
<div class="card env-group-card">
|
||||
<h3 class="env-group-title">{{ group.title or '其他' }}</h3>
|
||||
<div class="env-group-fields">
|
||||
{% for field in group.fields %}
|
||||
<div class="env-field-card">
|
||||
<label class="env-field-label">{{ field.key }}</label>
|
||||
{% if field.note %}
|
||||
<div class="env-field-note muted">{{ field.note }}</div>
|
||||
{% endif %}
|
||||
{% if field.type == 'bool' %}
|
||||
<select class="env-field-input" data-env-key="{{ field.key }}">
|
||||
{% set cur = (field.current or field.default or 'false')|lower %}
|
||||
<option value="true"{% if cur in ('true', '1', 'yes', 'on') %} selected{% endif %}>true</option>
|
||||
<option value="false"{% if cur not in ('true', '1', 'yes', 'on') %} selected{% endif %}>false</option>
|
||||
</select>
|
||||
{% else %}
|
||||
<input
|
||||
class="env-field-input"
|
||||
type="{% if field.sensitive %}password{% else %}text{% endif %}"
|
||||
data-env-key="{{ field.key }}"
|
||||
{% if field.sensitive and field.has_value %}
|
||||
placeholder="{{ field.masked or '留空不修改' }}"
|
||||
{% else %}
|
||||
value="{{ field.current or field.default or '' }}"
|
||||
{% endif %}
|
||||
>
|
||||
{% endif %}
|
||||
<span class="env-field-badge {% if field.restart_required %}env-badge-restart{% else %}env-badge-hot{% endif %}">
|
||||
{% if field.restart_required %}需重启{% else %}保存即生效{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<div class="env-config-loading muted">加载配置中…</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2038,6 +2038,6 @@ setInterval(refreshPriceSnapshotConditional, {{ price_refresh_seconds * 1000 }})
|
||||
<script>
|
||||
window.__INSTANCE_DISPLAY__ = {{ display | tojson }};
|
||||
</script>
|
||||
<script src="/static/instance_settings_prefs.js?v=2"></script>
|
||||
<script src="/static/instance_settings_prefs.js?v=3"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user