# -*- coding: utf-8 -*-
"""给导入的各仿真页注入统一外壳: 顶栏 + 配色 token + 返回链接。
只做**加法**(追加一段 style + 在 body 开头插一个顶栏), 不改页面原有 DOM 与 JS,
所以不会破坏各页自己的 canvas 绘制逻辑。canvas 内部配色由各页 JS 决定, 本层不动 —— 这是已知边界。"""
import pathlib, re, sys
SIM = pathlib.Path("/Users/yuanying/guanlan-rudong-v2/outputs/rudong/windscada/_demo/sim")
MARK = "guanlan-shell-v1"
PAGES = {
"涡激共振模拟器.html": ("涡激共振模拟器", "机理通识 · 十二款机型预设"),
"涡激实测核验.html": ("涡激实测核验", "实测 · 九台秒级"),
"偏航滑移事件回放.html": ("偏航滑移事件回放", "实测 · 单台"),
"故障分布三维视图.html": ("故障分布三维视图", "实测 · 机组 × 系统 × 月份"),
"变流器故障仿真.html": ("变流器故障仿真", "注入 · 波形为合成"),
"变桨故障仿真.html": ("变桨故障仿真", "注入 · 波形为合成"),
"整机联调台_1.5MW.html": ("整机联调台 · 1.5 MW", "正演 · 控制核心层参数"),
"整机联调台_4MW.html": ("整机联调台 · 4 MW", "正演 · 控制核心层参数"),
}
SHELL_CSS = """
""" % MARK
def shell(title, sub):
return (f'
')
def apply(path, title, sub):
s = path.read_text(encoding="utf-8")
if MARK in s:
# 幂等剥离。注意: 不能用 .*?
—— 非贪婪会一路扫进页面正文,
# 把内容一起删掉(曾把一页删掉 4 KB)。改用唯一的结束锚: 顶栏最后是 。
s = re.sub(r'\s*' % MARK, "", s, flags=re.S)
s = re.sub(r'.*?返回仿真集成台
\s*', "", s, flags=re.S, count=1)
# 主路径: 有 /
m = re.search(r"", s, re.I)
if m:
s = s[:m.start()] + SHELL_CSS + s[m.start():]
else:
# 回退: 片段式 HTML (无 head/body 标签, 浏览器容忍)。锚到 或最后一个 之后
a = re.search(r"", s, re.I) or re.search(r"(?![\s\S]*)", s, re.I)
if not a: return None
s = s[:a.end()] + "\n" + SHELL_CSS + s[a.end():]
b = re.search(r"]*>", s, re.I)
if b:
s = s[:b.end()] + "\n" + shell(title, sub) + s[b.end():]
else:
# 回退: 插在最后一个 之后 (即样式区结束、可见内容开始处)
c = None
for c in re.finditer(r"", s, re.I): pass
if not c: return None
s = s[:c.end()] + "\n" + shell(title, sub) + s[c.end():]
path.write_text(s, encoding="utf-8"); return len(s)
ok = 0
for f,(t,sub) in PAGES.items():
p = SIM/f
if not p.exists(): print(f" 缺: {f}"); continue
n = apply(p, t, sub)
if n: ok += 1; print(f" ✓ {f} ({n//1024} KB)")
else: print(f" ✗ {f} 结构不符, 未注入")
print(f"\n注入 {ok}/{len(PAGES)} 页")