# -*- coding: utf-8 -*- """重做中转管理页的界面。 功能一个不少: 公网地址展示 + 一键复制、统计卡片、设备表格、 单台删除、批量删除、删除全部、登录保护 界面上的改进: * 头部:品牌 + 状态灯 + 版本/运行时长 * 公网地址做成醒目的大卡片,带「复制」按钮 * 统计卡片换成更清楚的样式 * 表格:在线/离线用徽章,配对码用等宽 chip,行悬停高亮 * 空状态给一句人话,而不是一行灰字 * 加「自动刷新」开关(默认 10 秒一次),省得手动 F5 * 窄屏(手机)表格自动变成卡片式,不用左右拖 * 操作结果用页面内提示条,不再打断式 alert(删除确认仍用 confirm) ⚠️ 两个必须注意的坑: 1. 这段是 f-string,CSS/JS 里的花括号都要写两遍 {{{{ }}}} 2. JS 字符串里的换行要写 \\\\n(源码里两反斜杠), 否则 f-string 会把它变成真换行,整段脚本报错(幽灵按键) """ from __future__ import annotations import ast import re import sys from pathlib import Path RELAY = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote\relay" r"\relay.py") NEW_PAGE = ''' def _admin_page(self) -> None: snap = RELAY.snapshot() rows = [] for device in snap["devices"]: online = device["online"] badge = ("在线" if online else "离线") rows.append( "" "" f'' "" f'' f'' f'{_esc(device["name"])}
' f'{_esc(device["deviceId"])}
' f'{_esc(device["code"])}' f'{badge}' f'{device["idleSeconds"]}s' f'{device["queuedToClient"]} / {device["queuedToAgent"]}' f'{_kb(device["bytesIn"])} / {_kb(device["bytesOut"])}' '' "") online_count = sum(1 for d in snap["devices"] if d["online"]) url_text = public_url() or "" url_display = _esc(url_text) if url_text else "(还没有地址,隧道可能没起来)" empty = ('' '
还没有电脑连上来
' '
在被控端双击 ykxmz.exe 设好配对码,' '手表上输那 6 位数字就能连上。
') html = f""" ykxmz 中转服务器

ykxmz 中转服务器

远程控制 · 跨网络中转
版本 {_esc(snap['version'])} · 已运行 {_uptime(snap['uptimeSeconds'])}
本进程内存 {snap['memoryKB'] // 1024} MB · 累计请求 {snap['totalRequests']}
当前公网地址 —— 手表「中转设置」里填这个
{url_display}
{len(snap['devices'])}
登记设备
{online_count}
在线
{snap['sessions']}
手表会话
{len(RELAY.codes)}
配对码占用
删除会连配对码一起清掉,那台设备下次可以重新设码。
{''.join(rows) or empty}
设备配对码状态 空闲待发(表/机)流量(入/出)
""" self._send(200, html.encode("utf-8"), "text/html; charset=utf-8") ''' def main() -> int: text = RELAY.read_text(encoding="utf-8") lines = text.splitlines(keepends=True) start = None end = None for index, line in enumerate(lines): if line.startswith(" def _admin_page(self) -> None:"): start = index elif start is not None and index > start and ( line.startswith(" def ") or line.startswith("def ") or line.startswith("class ")): end = index break if start is None or end is None: print(" [失败] 找不到 _admin_page 的边界") return 1 new_text = "".join(lines[:start]) + NEW_PAGE + "\n" + "".join(lines[end:]) try: ast.parse(new_text) except SyntaxError as exc: print(f" [失败] 生成的代码语法错误: 行 {exc.lineno}: {exc.msg}") return 1 RELAY.write_text(new_text, encoding="utf-8", newline="\n") print(f" 已重写 _admin_page({end - start} 行 -> " f"{NEW_PAGE.count(chr(10))} 行)") return 0 if __name__ == "__main__": sys.exit(main())