_gen_flow_diagrams.py 3.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. # -*- coding: utf-8 -*-
  2. """生成蓝图用业务流程图(每功能 1 张 + 每模块总体 1 张),S1 蓝图风格:横向流程框图。
  3. 输出:doc/_tmp_docx_out/flows/{module}_{key}.png
  4. """
  5. from __future__ import annotations
  6. import sys
  7. from pathlib import Path
  8. import matplotlib
  9. matplotlib.use("Agg")
  10. import matplotlib.pyplot as plt
  11. from matplotlib.patches import FancyArrowPatch, FancyBboxPatch
  12. HERE = Path(__file__).resolve().parent
  13. sys.path.insert(0, str(HERE))
  14. from _gen_s9_modules_data import MODULES # noqa: E402
  15. OUT = HERE / "_tmp_docx_out" / "flows"
  16. OUT.mkdir(parents=True, exist_ok=True)
  17. plt.rcParams["font.family"] = ["Microsoft YaHei"]
  18. plt.rcParams["axes.unicode_minus"] = False
  19. # 模块总体流程(手工概括,与文档 1.2 总体业务流程图呼应)
  20. OVERALL = {
  21. "系统集成": ["第三方系统(ERP/MES/WMS)", "数据源登记/标准API推数(方式丙)", "同步任务执行与清洗标准化", "贴源/标准/指标层入仓", "业务模块与看板消费", "出站回写第三方系统"],
  22. "S9": ["运营指标主数据", "指标层日批计算", "九宫格总览(红黄绿预警)", "格子下钻模块看板", "联动智慧诊断"],
  23. "运营诊断": ["看板未达标指标", "智慧诊断环节识别", "七维下钻根因溯源", "诊断结论与报告", "转改善闭环"],
  24. "运营改善": ["诊断问题建档", "审批派单到责任人", "行动项执行跟踪", "有效性验证(前后对比)", "复盘闭环与经验固化"],
  25. "ChatBI": ["看板/九宫格上下文", "自然语言提问", "意图解析与指标聚合", "结论与建议输出", "跳转看板或诊断"],
  26. }
  27. MODULE_PREFIX = {"系统集成": "int", "S9": "s9", "运营诊断": "od", "运营改善": "oi", "ChatBI": "cb"}
  28. def draw_flow(title: str, steps: list[tuple[str, str]], out: Path):
  29. """steps: [(活动名称, 执行角色)],横向框图 + 箭头。"""
  30. n = len(steps)
  31. w = max(8.0, 1.9 * n + 1.2)
  32. fig, ax = plt.subplots(figsize=(w, 1.9), dpi=200)
  33. ax.set_xlim(0, n * 1.9 + 0.4)
  34. ax.set_ylim(0, 1.9)
  35. ax.axis("off")
  36. ax.text(n * 0.95 + 0.2, 1.68, title, ha="center", va="center", fontsize=12, fontweight="bold", color="#1F3864")
  37. box_w, box_h, y0 = 1.55, 0.78, 0.42
  38. for i, (name, role) in enumerate(steps):
  39. x0 = 0.2 + i * 1.9
  40. box = FancyBboxPatch((x0, y0), box_w, box_h, boxstyle="round,pad=0.06",
  41. fc="#E8F1FA", ec="#2E75B6", lw=1.4)
  42. ax.add_patch(box)
  43. ax.text(x0 + box_w / 2, y0 + box_h * 0.62, name, ha="center", va="center",
  44. fontsize=10.5, fontweight="bold", color="#1F3864", wrap=True)
  45. ax.text(x0 + box_w / 2, y0 + box_h * 0.24, role, ha="center", va="center",
  46. fontsize=8.5, color="#595959")
  47. if i < n - 1:
  48. ar = FancyArrowPatch((x0 + box_w + 0.07, y0 + box_h / 2), (x0 + 1.9 + 0.13, y0 + box_h / 2),
  49. arrowstyle="-|>", mutation_scale=16, color="#2E75B6", lw=1.6)
  50. ax.add_patch(ar)
  51. fig.savefig(out, bbox_inches="tight", facecolor="white")
  52. plt.close(fig)
  53. print("FLOW", out.name)
  54. def main():
  55. for mod_key, mod in MODULES.items():
  56. prefix = MODULE_PREFIX[mod_key]
  57. draw_flow(f"{mod['module_title']}·总体业务流程", [(s, "") for s in OVERALL[mod_key]],
  58. OUT / f"{prefix}_overall.png")
  59. for feat in mod["features"]:
  60. if feat.get("impl_status") == "未实现":
  61. continue
  62. steps = [(name, role) for _no, name, role, _desc, _inp, _out in feat["flow_steps"]]
  63. draw_flow(f"{feat['name']}({feat['func']})业务流程", steps,
  64. OUT / f"{prefix}_{feat['func'].lower().replace('-', '_')}.png")
  65. if __name__ == "__main__":
  66. main()