Fix settings tab 500 and env config grouping in UI
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
Vendored
+42
-3
@@ -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]:
|
||||
|
||||
@@ -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]},
|
||||
]
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<div class="display-prefs-group">
|
||||
<h3 class="settings-subcard-title">{{ group.group }}</h3>
|
||||
<div class="display-prefs-checks">
|
||||
{% for item in group.keys %}
|
||||
{% for item in group.items %}
|
||||
<label class="chk-label">
|
||||
<input type="checkbox" data-pref-key="{{ item.key }}"{% if display.get(item.key, true) %} checked{% endif %}>
|
||||
{{ item.label }}
|
||||
|
||||
@@ -103,8 +103,8 @@ 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=3"></script>
|
||||
<script src="/static/instance_settings_prefs.js?v=4"></script>
|
||||
<script src="/static/instance_live.js?v=4"></script>
|
||||
<script src="/static/instance_embed.js?v=18"></script>
|
||||
<script src="/static/instance_embed.js?v=19"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -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=3"></script>
|
||||
<script src="/static/instance_settings_prefs.js?v=4"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user