|
|
@@ -0,0 +1,67 @@
|
|
|
+#!/usr/bin/env python3
|
|
|
+# -*- coding: utf-8 -*-
|
|
|
+"""bug-2 修复: 从 v0.1.0 发行包把缺失的 release/如东/ 交付件恢复到 v0.2.0 安装目录。
|
|
|
+
|
|
|
+根因: v0.2.0 包**根本没带** release/如东/ (0.2.0 zip 里 release/ 下只有 viewer/),
|
|
|
+而 release/portal.html 的 #documents 区块用 iframe 指向
|
|
|
+ http://127.0.0.1:28084/如东/如东治理清单_交付_20260901/02_治理清单/如东_液压系统治理清单_v1.2_2026-09-01.html
|
|
|
+该路径由网关 _static() 从 release/ 目录取文件, 文件不在 → 404 {"err":"not found", "path": …},
|
|
|
+iframe 里就直接显示那段 JSON。v0.1.0 包里这份交付件是齐的 (76 项), 直接恢复。
|
|
|
+
|
|
|
+(release/如东/ 按 .gitignore 约定不入库 —— 客户交付物只在受保护工作区。)
|
|
|
+"""
|
|
|
+from __future__ import annotations
|
|
|
+
|
|
|
+import pathlib
|
|
|
+import shutil
|
|
|
+import sys
|
|
|
+import zipfile
|
|
|
+
|
|
|
+ZIP = pathlib.Path(r"F:\temp\guanlan-rudong-v2_0.1.0_all.zip")
|
|
|
+REL = pathlib.Path(r"F:\temp\guanlan-rudong-v2_0.2.0\release")
|
|
|
+PREFIX = "release/如东/"
|
|
|
+
|
|
|
+
|
|
|
+def nm(info):
|
|
|
+ raw = info.filename
|
|
|
+ for enc in ("gbk", "utf-8"):
|
|
|
+ try:
|
|
|
+ return raw.encode("cp437").decode(enc)
|
|
|
+ except Exception:
|
|
|
+ continue
|
|
|
+ return raw
|
|
|
+
|
|
|
+
|
|
|
+def main() -> int:
|
|
|
+ if not ZIP.is_file():
|
|
|
+ print(f" [X] 缺源包 {ZIP}")
|
|
|
+ return 1
|
|
|
+ print(f"源: {ZIP}")
|
|
|
+ print(f"目标: {REL}\\如东\\\n")
|
|
|
+ n_files = 0
|
|
|
+ n_bytes = 0
|
|
|
+ with zipfile.ZipFile(ZIP) as zf:
|
|
|
+ items = [(nm(i), i) for i in zf.infolist()]
|
|
|
+ rel = [(n.replace("\\", "/"), i) for n, i in items if n.replace("\\", "/").startswith(PREFIX)]
|
|
|
+ if not rel:
|
|
|
+ print(" [X] 源包里没有 release/如东/")
|
|
|
+ return 1
|
|
|
+ for name, info in rel:
|
|
|
+ target = REL / name[len("release/"):]
|
|
|
+ if info.is_dir():
|
|
|
+ target.mkdir(parents=True, exist_ok=True)
|
|
|
+ continue
|
|
|
+ target.parent.mkdir(parents=True, exist_ok=True)
|
|
|
+ with zf.open(info) as fsrc, open(target, "wb") as fdst:
|
|
|
+ shutil.copyfileobj(fsrc, fdst, 1024 * 1024)
|
|
|
+ if target.stat().st_size != info.file_size:
|
|
|
+ print(f" [X] 大小不符: {target}")
|
|
|
+ return 1
|
|
|
+ n_files += 1
|
|
|
+ n_bytes += info.file_size
|
|
|
+ print(f"恢复 {n_files} 个文件, {n_bytes/1024/1024:.1f} MB")
|
|
|
+ return 0
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ sys.exit(main())
|