restore_release_rudong.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """bug-2 修复: 从 v0.1.0 发行包把缺失的 release/如东/ 交付件恢复到 v0.2.0 安装目录。
  4. 根因: v0.2.0 包**根本没带** release/如东/ (0.2.0 zip 里 release/ 下只有 viewer/),
  5. 而 release/portal.html 的 #documents 区块用 iframe 指向
  6. http://127.0.0.1:28084/如东/如东治理清单_交付_20260901/02_治理清单/如东_液压系统治理清单_v1.2_2026-09-01.html
  7. 该路径由网关 _static() 从 release/ 目录取文件, 文件不在 → 404 {"err":"not found", "path": …},
  8. iframe 里就直接显示那段 JSON。v0.1.0 包里这份交付件是齐的 (76 项), 直接恢复。
  9. (release/如东/ 按 .gitignore 约定不入库 —— 客户交付物只在受保护工作区。)
  10. """
  11. from __future__ import annotations
  12. import pathlib
  13. import shutil
  14. import sys
  15. import zipfile
  16. ZIP = pathlib.Path(r"F:\temp\guanlan-rudong-v2_0.1.0_all.zip")
  17. REL = pathlib.Path(r"F:\temp\guanlan-rudong-v2_0.2.0\release")
  18. PREFIX = "release/如东/"
  19. def nm(info):
  20. raw = info.filename
  21. for enc in ("gbk", "utf-8"):
  22. try:
  23. return raw.encode("cp437").decode(enc)
  24. except Exception:
  25. continue
  26. return raw
  27. def main() -> int:
  28. if not ZIP.is_file():
  29. print(f" [X] 缺源包 {ZIP}")
  30. return 1
  31. print(f"源: {ZIP}")
  32. print(f"目标: {REL}\\如东\\\n")
  33. n_files = 0
  34. n_bytes = 0
  35. with zipfile.ZipFile(ZIP) as zf:
  36. items = [(nm(i), i) for i in zf.infolist()]
  37. rel = [(n.replace("\\", "/"), i) for n, i in items if n.replace("\\", "/").startswith(PREFIX)]
  38. if not rel:
  39. print(" [X] 源包里没有 release/如东/")
  40. return 1
  41. for name, info in rel:
  42. target = REL / name[len("release/"):]
  43. if info.is_dir():
  44. target.mkdir(parents=True, exist_ok=True)
  45. continue
  46. target.parent.mkdir(parents=True, exist_ok=True)
  47. with zf.open(info) as fsrc, open(target, "wb") as fdst:
  48. shutil.copyfileobj(fsrc, fdst, 1024 * 1024)
  49. if target.stat().st_size != info.file_size:
  50. print(f" [X] 大小不符: {target}")
  51. return 1
  52. n_files += 1
  53. n_bytes += info.file_size
  54. print(f"恢复 {n_files} 个文件, {n_bytes/1024/1024:.1f} MB")
  55. return 0
  56. if __name__ == "__main__":
  57. sys.exit(main())