diff --git a/lib/common/static/instance_embed.js b/lib/common/static/instance_embed.js index 35e2fc5..54d030b 100644 --- a/lib/common/static/instance_embed.js +++ b/lib/common/static/instance_embed.js @@ -18,6 +18,7 @@ let navToken = 0; let loadingTab = false; + let pendingTabLoad = null; const tabPanes = new Map(); const tabBooted = new Set(); @@ -221,6 +222,10 @@ credentials: "same-origin", headers: { "X-Instance-Soft-Nav": "1" }, }); + const ct = (r.headers.get("content-type") || "").toLowerCase(); + if (!ct.includes("application/json")) { + throw new Error("加载失败(HTTP " + r.status + ")"); + } const j = await r.json(); if (!j.ok || !j.html) throw new Error(j.msg || "加载失败"); return j.html; @@ -325,7 +330,10 @@ return; } - if (loadingTab) return; + if (loadingTab) { + pendingTabLoad = { tab: tab, opts: options }; + return; + } const token = ++navToken; loadingTab = true; try { @@ -343,6 +351,11 @@ } } finally { if (token === navToken) loadingTab = false; + if (pendingTabLoad) { + const pending = pendingTabLoad; + pendingTabLoad = null; + if (pending.tab !== tab) void loadTab(pending.tab, pending.opts); + } } } diff --git a/lib/common/static/instance_settings_prefs.js b/lib/common/static/instance_settings_prefs.js index 2bc300d..5cebe58 100644 --- a/lib/common/static/instance_settings_prefs.js +++ b/lib/common/static/instance_settings_prefs.js @@ -98,7 +98,7 @@ section.appendChild(title); const grid = document.createElement("div"); grid.className = "display-prefs-checks"; - (group.keys || []).forEach((item) => { + (group.items || []).forEach((item) => { const label = document.createElement("label"); label.className = "chk-label"; const cb = document.createElement("input"); diff --git a/lib/env/env_schema.py b/lib/env/env_schema.py index cea5ac7..f351dae 100644 --- a/lib/env/env_schema.py +++ b/lib/env/env_schema.py @@ -8,6 +8,8 @@ from typing import Any, Optional from lib.env.env_file_lib import env_get, env_get_all, read_env_lines _GROUP_RE = re.compile(r"^#\s*=+\s*(.+?)\s*=+\s*$") +_SEPARATOR_RE = re.compile(r"^#\s*=+\s*$") +_SECTION_DASH_RE = re.compile(r"^#\s*---\s*(.+?)\s*---\s*$") _KEY_LINE = re.compile(r"^([A-Za-z_][A-Za-z0-9_]*)\s*=") RESTART_REQUIRED_EXACT = frozenset({ @@ -146,10 +148,14 @@ def parse_env_example_schema(example_path: str) -> list[dict[str, Any]]: lines = read_env_lines(example_path) groups: list[dict[str, Any]] = [] group_map: dict[str, dict[str, Any]] = {} - current_group = "应用与鉴权" + current_group = "基础配置" pending_note: list[str] = [] + in_section_block = False + section_title_set = False + allow_section_blocks = False def _ensure_group(title: str) -> dict[str, Any]: + title = (title or "").strip() or "其他" if title not in group_map: group_map[title] = {"title": title, "fields": []} groups.append(group_map[title]) @@ -161,9 +167,41 @@ def parse_env_example_schema(example_path: str) -> list[dict[str, Any]]: if not stripped: pending_note = [] continue + if _SEPARATOR_RE.match(stripped): + if not allow_section_blocks: + continue + if not in_section_block: + in_section_block = True + section_title_set = False + else: + in_section_block = False + continue + if in_section_block and stripped.startswith("#"): + note = stripped.lstrip("#").strip() + if note and not section_title_set: + current_group = note + _ensure_group(current_group) + section_title_set = True + elif note: + pending_note.append(note) + continue gm = _GROUP_RE.match(stripped) if gm: - current_group = gm.group(1).strip() + title = gm.group(1).strip() + if title and title != "=": + current_group = title + _ensure_group(current_group) + in_section_block = False + section_title_set = False + pending_note = [] + continue + dash = _SECTION_DASH_RE.match(stripped) + if dash: + allow_section_blocks = True + current_group = dash.group(1).strip() + _ensure_group(current_group) + in_section_block = False + section_title_set = False pending_note = [] continue if stripped.startswith("#"): @@ -175,6 +213,7 @@ def parse_env_example_schema(example_path: str) -> list[dict[str, Any]]: if not km: continue key = km.group(1) + allow_section_blocks = True default_val = env_get(lines, key) or "" grp = _ensure_group(current_group) note = " ".join(pending_note).strip() @@ -191,7 +230,7 @@ def parse_env_example_schema(example_path: str) -> list[dict[str, Any]]: } ) pending_note = [] - return groups + return [g for g in groups if g.get("fields")] def build_env_payload(example_path: str, env_path: str) -> dict[str, Any]: diff --git a/lib/instance/instance_display_prefs_lib.py b/lib/instance/instance_display_prefs_lib.py index e814641..88dcda9 100644 --- a/lib/instance/instance_display_prefs_lib.py +++ b/lib/instance/instance_display_prefs_lib.py @@ -113,6 +113,6 @@ def display_meta_for_ui() -> list[dict[str, Any]]: "show_settings_options_transfer", ] return [ - {"group": "顶栏导航", "keys": [{"key": k, "label": DISPLAY_LABELS[k]} for k in nav_keys]}, - {"group": "系统设置区块", "keys": [{"key": k, "label": DISPLAY_LABELS[k]} for k in settings_keys]}, + {"group": "顶栏导航", "items": [{"key": k, "label": DISPLAY_LABELS[k]} for k in nav_keys]}, + {"group": "系统设置区块", "items": [{"key": k, "label": DISPLAY_LABELS[k]} for k in settings_keys]}, ] diff --git a/lib/instance/templates/display_prefs_panel.html b/lib/instance/templates/display_prefs_panel.html index 3177c7c..05c5626 100644 --- a/lib/instance/templates/display_prefs_panel.html +++ b/lib/instance/templates/display_prefs_panel.html @@ -8,7 +8,7 @@

{{ group.group }}

- {% for item in group.keys %} + {% for item in group.items %}