# -*- coding: utf-8 -*- u"""底板铺铜「按名字对账」+ 只补缺的块(2026-09-14)。 /c/Python314/python .claude/r2/pour_guard.py # 只读:板上铺铜 vs pour_base.plan() 逐块比 /c/Python314/python .claude/r2/pour_guard.py --fix # 缺的按计划补建 → 界面「重建所有」→ 查功率铜面 → 存盘 ## 为什么要有它 内层 GND 瓦片(`GND-L2-0~7` / `GND-L3-0~7`)**两次整块消失**,DRC 报几十条 GND 连接性, 而 DRC 间距检查和 `board_check` 都看不出来。本机的服务器备份 (`Documents/LCEDA-Pro/online-projects-backup/PhoneRail-R2/*.zip`)显示:09-11 ~ 09-13 的 10 份备份里 这 16 块**从来没进过服务器**,只存在于客户端内存。关掉客户端再打开就没了。 页面重载(`location.reload`)读回来却是全的 ⇒ **重载验证不了是否真存上,只有退出客户端再打开才算数**。 ⇒ 每次重开客户端之后、交接前、投板前跑一次本脚本(只读模式)。 ⚠ 不删任何铺铜,也不重建计划外的块。计划外的块只报告,不处理。 ⚠ 不要用 `reload_base.py` 做验证,它会先删掉**全部**铺铜再重载。 """ import json import os import sys sys.stdout.reconfigure(encoding='utf-8') HERE = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, os.path.dirname(HERE)) sys.path.insert(0, HERE) import pour_base as PB # noqa: E402 JS_NAMES = PB.OPEN + u""" const f = new Set(); for (const q of await eda.pcb_PrimitivePoured.getAll()) f.add(q.getState_PourPrimitiveId()); return (await eda.pcb_PrimitivePour.getAll()).map(p => [String(p.getState_PourName() || '').toUpperCase(), p.getState_Layer(), f.has(p.getState_PrimitiveId()) ? 1 : 0]); """ def audit(): ps = PB.plan() rows = PB.call(JS_NAMES, timeout=300) board = {(n, l) for n, l, _f in rows} plan = {(p[0].upper(), p[2]): p for p in ps} missing = [plan[k] for k in sorted(plan) if k not in board] extra = sorted(k for k in board if k not in plan) filled = sum(f for _n, _l, f in rows) per = {} for n, l, _f in rows: per[l] = per.get(l, 0) + 1 print(u'板上铺铜 %d 块(填出 %d),计划 %d 块;分层 %s' % (len(rows), filled, len(ps), per)) print(u'缺:%s' % (' '.join(p[0] for p in missing) or u'无')) if extra: print(u'计划外(只报告不处理):%s' % ' '.join('%s@L%s' % k for k in extra)) return missing def fix(missing): arr = [{'name': n, 'net': net, 'layer': l, 'prio': p, 'src': PB.rrect_src(*r)} for (n, net, l, r, p) in missing] made = PB.call(PB.JS_MAKE % json.dumps(arr, ensure_ascii=False), timeout=600)['made'] want = {p[0].upper() for p in missing} print(u'补建 %d / %d' % (len(want & set(made)), len(want))) PB.rebuild() # 界面「重建所有」+ 存盘 if not PB.verify_fill(): sys.exit(u'!! 功率铜面有空的') if __name__ == '__main__': miss = audit() if '--fix' in sys.argv and miss: fix(miss) audit() print(u'⚠ 是否真存进服务器,只有退出客户端再打开之后重跑本脚本才算数(页面重载不算)') sys.exit(1 if (miss and '--fix' not in sys.argv) else 0)