# -*- coding: utf-8 -*- """Insert 8.28 screenshots back into 9.19 markdown manuals.""" import json, re from pathlib import Path ROOT = Path(r"D:\产线\大洋\大洋操作手册汇总9.19") IMG = ROOT / "images" IMG_RE = re.compile(r"^\s*!\[.*?\]\(images/.*?\)\s*$") CAP_RE = re.compile(r"^\s*

.*$$") FASCICLES = [ "1、系统管理操作手册.md", "2、设备管理操作手册.md", "3、物料管理操作手册.md", "4、质量管理操作手册.md", "5、生产管理操作手册.md", "6、ERP对接操作手册.md", "7、生产线管理操作手册.md", "8、PDA操作说明操作手册.md", "9、MES系统客户端员工扫码操作手册.md", ] def norm(s): s = (s or "").replace(" ", "").replace(" ", "") s = s.replace("→", "").replace("—", "").replace("-", "") s = re.sub(r"^\d+(\.\d+)*\.?", "", s) return s def parse_sections(lines): """Return list of {level,title,start,end} covering body after heading.""" secs = [] for i, line in enumerate(lines): m = re.match(r"^(#{2,6})\s+(.*)$", line) if m: secs.append({"level": len(m.group(1)), "title": m.group(2).strip(), "start": i}) for i, sec in enumerate(secs): sec["end"] = secs[i + 1]["start"] if i + 1 < len(secs) else len(lines) return secs def strip_old_images(text): lines = text.splitlines() out = [] i = 0 while i < len(lines): line = lines[i] if IMG_RE.match(line) or line.startswith('

') or line.strip() == "*(界面截图取自 8.28 手册,现场如有改动以实际为准。)*": i += 1 # skip following blank if i < len(lines) and not lines[i].strip(): i += 1 continue if line.strip() == "## 原手册界面截图(8.28)": # drop this section until next heading i += 1 while i < len(lines) and not re.match(r"^## ", lines[i]): i += 1 continue out.append(line) i += 1 return "\n".join(out).rstrip() + "\n" def score(sec, cap, heading, body=""): title = sec["title"] tn, cn, hn = norm(title), norm(cap), norm(heading) blob = tn + norm(body) s = 0 if cn and (cn in tn or tn in cn): s += 60 if hn and (hn in tn or tn in hn): s += 45 hay = (title + " " + body).upper() for code in set(re.findall(r"OP\d+", (cap + heading).upper())): if code and code in hay: s += 80 keys = re.findall(r"[\u4e00-\u9fff]{2,}", cap + " " + heading) for k in keys: if k in title or k in body[:800]: s += 12 return s def image_md(item): cap = item.get("caption") or "界面截图" rel = item["file"] if not rel.startswith("images/"): rel = "images/" + rel return "\n![%s](%s)\n\n*(界面截图取自 8.28 手册,现场如有改动以实际为准。)*\n" % (cap, rel) def insert_into(md_name, items): path = ROOT / md_name text = strip_old_images(path.read_text(encoding="utf-8")) lines = text.splitlines() secs = parse_sections(lines) if not secs: path.write_text(text + "\n## 原手册界面截图(8.28)\n" + "".join(image_md(x) for x in items), encoding="utf-8") return len(items), 0 buckets = {id(sec): [] for sec in secs} unmatched = [] for item in items: best, best_s = None, 0 for sec in secs: body = "\n".join(lines[sec["start"]:sec["end"]]) sc = score(sec, item.get("caption", ""), item.get("heading", ""), body) if sc > best_s or (best is not None and sc == best_s and sec["level"] > best["level"]): best, best_s = sec, sc # special: login / home screens cap = item.get("caption") or "" if "登录" in cap: for sec in secs: if "登录" in sec["title"] or "安装" in sec["title"]: best, best_s = sec, max(best_s, 80) if "主功能" in cap or "我的界面" in cap: for sec in secs: if "界面" in sec["title"]: best, best_s = sec, max(best_s, 80) if best is None or best_s < 12: unmatched.append(item) else: buckets[id(best)].append(item) # insert from bottom so indexes stay valid for sec in reversed(secs): imgs = buckets[id(sec)] if not imgs: continue # insert before sec['end'] (start of next heading), after trailing blanks of this section pos = sec["end"] while pos > sec["start"] + 1 and pos <= len(lines) and (pos == len(lines) or not lines[pos - 1].strip()): pos -= 1 block = "".join(image_md(x) for x in imgs).splitlines() lines[pos:pos] = [""] + block + [""] text = "\n".join(lines).rstrip() + "\n" if unmatched: extra = ["", "## 原手册界面截图(8.28)", "", "以下截图未能自动对上新目录,仍予保留。", ""] for x in unmatched: extra.extend(image_md(x).splitlines()) text = text.rstrip() + "\n" + "\n".join(extra) + "\n" path.write_text(text, encoding="utf-8") return len(items) - len(unmatched), len(unmatched) def main(): total_m, total_u = 0, 0 for md in FASCICLES: stem = md[:-3] man = IMG / stem / "manifest.json" if not man.exists(): print("no manifest", stem) continue items = json.loads(man.read_text(encoding="utf-8")) # keep only files that exist ok = [] for it in items: p = ROOT / it["file"] if p.exists(): ok.append(it) m, u = insert_into(md, ok) total_m += m total_u += u print(stem, "matched", m, "appendix", u, "total", len(ok)) print("ALL matched", total_m, "appendix", total_u) if __name__ == "__main__": main()