_bid_extract_ui.py 3.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. # -*- coding: utf-8 -*-
  2. """抽取已交付系统的真实界面截图,供技术方案第 2 章「系统功能展示」引用。
  3. 来源为各模块蓝图设计方案与功能设计说明中的实际系统截图(非示意图)。
  4. """
  5. import io
  6. import os
  7. import shutil
  8. import sys
  9. import tempfile
  10. from docx import Document
  11. from docx.oxml.ns import qn
  12. sys.stdout.reconfigure(encoding="utf-8", errors="replace")
  13. ROOT = (r"C:\Users\skygu\OneDrive\Projects\AIDOP\项目\项目管理"
  14. r"\产互联项目管理\交付文档")
  15. ASSETS = os.path.join(os.path.dirname(os.path.abspath(__file__)), "_bid_assets")
  16. os.makedirs(ASSETS, exist_ok=True)
  17. S0 = r"S0\S0-基础主数据建模-业务蓝图设计方案-V0.2.docx"
  18. S1 = r"S1\Tmp\S1-功能设计说明.docx"
  19. S2 = r"S2\Tmp\S2-功能设计说明.docx"
  20. S5 = r"S5\S5-物料仓储-业务蓝图设计方案.docx"
  21. S6 = r"S6\S6-生产执行-业务蓝图设计方案.docx"
  22. S7 = r"S7\S7-成品仓储-业务蓝图设计方案.docx"
  23. # (源文档, 文档内第几张图, 输出名, 图题)
  24. PICKS = [
  25. (S0, 5, "ui_s0_material", "物料主数据管理(FUNC-S0-020)"),
  26. (S0, 2, "ui_s0_customer", "客户主数据管理(FUNC-S0-021)"),
  27. (S0, 10, "ui_s0_supplier", "供应商主数据管理(FUNC-S0-027)"),
  28. (S0, 30, "ui_s0_bom", "标准 BOM 管理(FUNC-S0-001)"),
  29. (S0, 15, "ui_s0_routing", "标准工艺路线管理(FUNC-S0-002)"),
  30. (S0, 48, "ui_s0_location", "库位管理(FUNC-S0-034)"),
  31. # S1、S2 功能设计说明中的配图为早期线框原型(指标卡为「指标A/当前值/目标值」占位、
  32. # 列表仅一行样例数据),与其余模块的实际系统截图风格不一致,不用于响应文件。
  33. (S5, 2, "ui_s5_iqc", "来料检验申请列表"),
  34. (S5, 7, "ui_s5_stock", "库存查询"),
  35. (S5, 8, "ui_s5_inout", "进出存查询"),
  36. (S5, 11, "ui_s5_stocktake", "盘点结果查询"),
  37. (S6, 2, "ui_s6_ipqc", "过程检验单列表与详情"),
  38. (S6, 3, "ui_s6_equipment", "生产设备台账"),
  39. (S6, 4, "ui_s6_tooling", "模具工装台账管理"),
  40. (S7, 2, "ui_s7_prodin", "生产入库单列表"),
  41. (S7, 3, "ui_s7_shipment", "销售发货通知"),
  42. (S7, 4, "ui_s7_fqc_task", "FQC 检验任务列表"),
  43. (S7, 5, "ui_s7_fqc_result", "FQC 检验结果列表与详情"),
  44. ]
  45. def load(cache, rel, tmpdir):
  46. if rel not in cache:
  47. local = os.path.join(tmpdir, os.path.basename(rel))
  48. shutil.copy2(os.path.join(ROOT, rel), local)
  49. cache[rel] = Document(local)
  50. return cache[rel]
  51. def main():
  52. tmpdir = tempfile.mkdtemp()
  53. cache = {}
  54. manifest = []
  55. for rel, idx, name, caption in PICKS:
  56. doc = load(cache, rel, tmpdir)
  57. found, blob, ext = 0, None, ".png"
  58. for p in doc.paragraphs:
  59. for blip in p._p.findall(".//" + qn("a:blip")):
  60. found += 1
  61. if found == idx:
  62. part = doc.part.related_parts[blip.get(qn("r:embed"))]
  63. blob = part.blob
  64. ext = os.path.splitext(str(part.partname))[1] or ".png"
  65. break
  66. if blob is not None:
  67. break
  68. if blob is None:
  69. print(f" [缺] {rel} 第 {idx} 张")
  70. continue
  71. with open(os.path.join(ASSETS, name + ext), "wb") as f:
  72. f.write(blob)
  73. manifest.append((name + ext, len(blob) // 1024, caption, rel))
  74. print(f" [OK] {name + ext:<24} {len(blob) // 1024:>5} KB {caption}")
  75. shutil.rmtree(tmpdir, ignore_errors=True)
  76. with io.open(os.path.join(ASSETS, "_manifest_ui.txt"), "w",
  77. encoding="utf-8") as f:
  78. for n, kb, c, r in manifest:
  79. f.write(f"{n}\t{kb}KB\t{c}\t来源:{r}\n")
  80. print(f"\n共抽取 {len(manifest)} 张界面截图 -> {ASSETS}")
  81. if __name__ == "__main__":
  82. main()