diff --git a/_build/_cmsg10.txt b/_build/_cmsg10.txt
new file mode 100644
index 0000000..5a5483d
--- /dev/null
+++ b/_build/_cmsg10.txt
@@ -0,0 +1,75 @@
+🚨 修一个严重 bug:管理页所有按钮又失效了(同一个坑踩第二次)
+
+== 症状 ==
+
+在**真实中转**上实测管理页时,用 node --check 检查页面内嵌的 JS:
+
+ SyntaxError: Invalid or unexpected token (第 46 行)
+
+整段 ,
+ 或者 JS 用到了 node 不认的语法)-> 假警报
+
+这个脚本把可疑的那一行原样打出来,人肉判断是哪种。
+'''
+from __future__ import annotations
+
+import json
+import re
+import subprocess
+import sys
+import tempfile
+import urllib.request
+from pathlib import Path
+
+sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "_build"))
+from devssh import run as ssh_run # noqa: E402
+
+BASE = "https://relay.xxmxxs.top"
+UA = {"User-Agent": "LanRemote/1.8.2"}
+
+
+def main() -> int:
+ _c, out, _e = ssh_run(
+ "cat /root/lanremote-relay/data/admin_key.txt", timeout=60, quiet=True)
+ key = (out or "").strip().splitlines()[0]
+
+ req = urllib.request.Request(BASE + "/zhongzhuanzhan",
+ headers={**UA, "X-Admin": key})
+ with urllib.request.urlopen(req, timeout=25) as resp:
+ html = resp.read().decode("utf-8", "replace")
+
+ scripts = re.findall(r"", html, re.S)
+ inline = [s for s in scripts if s.strip()]
+ print(" 页面上有 %d 段内嵌脚本,长度: %s"
+ % (len(inline), [len(s) for s in inline]))
+
+ js = inline[0]
+ lines = js.splitlines()
+ print(" 第 1 段共 %d 行" % len(lines))
+ print()
+ print(" ════ 第 40~54 行原样 ════")
+ for i in range(39, min(54, len(lines))):
+ marker = " <<<< 报错行" if i == 45 else ""
+ print(" %3d| %s%s" % (i + 1, lines[i], marker))
+ print()
+
+ # 把这一段单独跑 node --check,确认能复现
+ with tempfile.NamedTemporaryFile("w", suffix=".js", delete=False,
+ encoding="utf-8") as fh:
+ fh.write(js)
+ path = fh.name
+ proc = subprocess.run(["node", "--check", path],
+ capture_output=True, text=True,
+ encoding="utf-8", errors="replace")
+ print(" node --check 退出码: %d" % proc.returncode)
+ if proc.stderr:
+ print(" stderr:")
+ for line in proc.stderr.splitlines()[:12]:
+ print(" " + line)
+ Path(path).unlink(missing_ok=True)
+
+ # 也检查每一行里有没有裸控制字符
+ print()
+ print(" ════ 有没有裸控制字符 ════")
+ bad = 0
+ for i, line in enumerate(lines, 1):
+ for ch in line:
+ if ord(ch) < 32 and ch not in "\t":
+ print(" 第 %d 行有控制字符 0x%02x" % (i, ord(ch)))
+ bad += 1
+ break
+ if not bad:
+ print(" ✓ 没有")
+
+ # 反引号 / 模板字面量 / 正则 里可能藏着截断问题
+ print()
+ print(" ════ 源 HTML 里 出现几次 ════")
+ print(" %d 次(正常应该等于 "))
+ print(" ", html, re.S)
+ inline = [s for s in scripts if s.strip()]
+ check("有内嵌脚本", bool(inline), "一个都没有")
+
+ for i, js in enumerate(inline, 1):
+ with tempfile.NamedTemporaryFile("w", suffix=".js", delete=False,
+ encoding="utf-8") as fh:
+ fh.write(js)
+ path = fh.name
+ try:
+ proc = subprocess.run(["node", "--check", path],
+ capture_output=True, text=True,
+ encoding="utf-8", errors="replace",
+ timeout=30)
+ ok = proc.returncode == 0
+ detail = ""
+ if not ok:
+ # 把报错那一行附近打出来,方便定位
+ err = (proc.stderr or "")
+ m = re.search(r":(\d+)\n", err)
+ if m:
+ ln = int(m.group(1))
+ lines = js.splitlines()
+ lo = max(0, ln - 3)
+ hi = min(len(lines), ln + 2)
+ detail = "第 %d 行:\n" % ln + "\n".join(
+ " %3d| %s" % (k + 1, lines[k])
+ for k in range(lo, hi))
+ else:
+ detail = err[:300]
+ check("第 %d 段内嵌 JS 语法合法" % i, ok, detail)
+ except FileNotFoundError:
+ print(" [SKIP] 没装 node")
+ finally:
+ Path(path).unlink(missing_ok=True)
+
+ # 再检查一遍:注释行里有没有被 Python 吃掉转义的痕迹
+ for i, js in enumerate(inline, 1):
+ lines = js.splitlines()
+ bad = []
+ for k, line in enumerate(lines):
+ s = line.strip()
+ if s.startswith("//"):
+ # 注释行里出现裸控制字符
+ for ch in line:
+ if ord(ch) < 32 and ch != "\t":
+ bad.append(k + 1)
+ break
+ check("第 %d 段没有裸控制字符" % i, not bad, "行号 %s" % bad)
+
+ print()
+ print("=" * 58)
+ print(" 通过 %d 项,失败 %d 项" % (passed, failed))
+ return 0 if failed == 0 else 1
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/_tests/test_admin_live.py b/_tests/test_admin_live.py
new file mode 100644
index 0000000..536b0f1
--- /dev/null
+++ b/_tests/test_admin_live.py
@@ -0,0 +1,214 @@
+# -*- coding: utf-8 -*-
+r'''在**真实中转**上实测【二】管理页的两个功能。
+
+== 为什么要单独做这个测试 ==
+
+单元测试是直接调 Relay 对象的 Python 方法,而用户是在浏览器上点。
+中间隔着 HTTP、HTML、JS 三层。之前就踩过「23 项测试全绿但按钮全是死的」:
+admin.py 里一个 \n 写错(Python 三引号字符串把 \n 变成真换行),
+拼进 JS 就是字符串里的裸换行 -> 整段 ", html, re.S)
+ inline = [s for s in scripts if s.strip()]
+ check("页面上有内嵌脚本", bool(inline), "一个