#!/usr/bin/env python3 from __future__ import annotations import json from collections import Counter, defaultdict from pathlib import Path ROOT = Path(__file__).resolve().parents[1] MANIFEST_PATH = ROOT / "deep-action-manifest-hc-pos.sqygj.cn.json" MIRROR_MANIFEST_PATH = ROOT / "mirror-manifest-hc-pos.sqygj.cn.json" REPORT_PATH = ROOT / "deep-action-report.md" SUMMARY_PATH = ROOT / "deep-action-summary.json" GAPS_PATH = ROOT / "deep-action-gaps.txt" def classify(label: str) -> str: pairs = [ ("统计", "统计"), ("详情", "详情"), ("查看", "查看"), ("编辑", "编辑"), ("新增", "新增"), ("新建", "新建"), ("创建", "创建"), ("添加", "添加"), ("记录", "记录"), ("工单", "工单"), ("复制", "复制"), ("绑定", "绑定"), ("确认", "确认"), ] for needle, category in pairs: if needle in label: return category return "其他" def route_key(url: str) -> str: return url.split("#/", 1)[1] if "#/" in url else url def main() -> int: manifest = json.loads(MANIFEST_PATH.read_text(encoding="utf-8")) items = manifest["items"] mirror_manifest = json.loads(MIRROR_MANIFEST_PATH.read_text(encoding="utf-8")) by_route: dict[str, list[dict]] = defaultdict(list) for item in items: by_route[item["source_url"]].append(item) route_rows = [] category_counter: Counter[str] = Counter() for source_url, route_items in sorted(by_route.items(), key=lambda kv: route_key(kv[0])): labels = [item["label"] for item in route_items] categories = Counter(classify(label) for label in labels) category_counter.update(categories) route_rows.append( { "source_url": source_url, "route": route_key(source_url), "count": len(route_items), "categories": dict(sorted(categories.items())), "labels": labels, "html_paths": [item["html_path"] for item in route_items], } ) summary = { "captured_deep_states": manifest["captured_deep_states"], "route_count": len(route_rows), "category_counts": dict(sorted(category_counter.items())), "routes": route_rows, } SUMMARY_PATH.write_text(json.dumps(summary, ensure_ascii=False, indent=2), encoding="utf-8") deep_urls = {item["source_url"] for item in items} gap_urls = sorted( page["source_url"] for page in mirror_manifest.get("pages", []) if page.get("source_url") not in deep_urls ) GAPS_PATH.write_text("\n".join(gap_urls) + ("\n" if gap_urls else ""), encoding="utf-8") lines = [ "# Deep Action Report", "", f"- Captured deep states: `{manifest['captured_deep_states']}`", f"- Source routes: `{len(route_rows)}`", f"- Uncaptured mirrored routes: `{len(gap_urls)}`", f"- Asset failures: `{len(manifest.get('asset_failures', []))}`", f"- Remaining failures: `{len(manifest.get('failures', []))}`", "", "## Category Counts", "", ] for category, count in sorted(category_counter.items()): lines.append(f"- {category}: `{count}`") lines.extend(["", "## Routes", ""]) for row in route_rows: lines.append(f"### `{row['route']}`") lines.append("") lines.append(f"- Source URL: `{row['source_url']}`") lines.append(f"- Captured states: `{row['count']}`") lines.append(f"- Categories: `{json.dumps(row['categories'], ensure_ascii=False)}`") lines.append("- Labels:") for label in row["labels"]: lines.append(f" - {label}") lines.append("") REPORT_PATH.write_text("\n".join(lines) + "\n", encoding="utf-8") print( json.dumps( { "report": str(REPORT_PATH), "summary": str(SUMMARY_PATH), "gaps": str(GAPS_PATH), "captured": manifest["captured_deep_states"], "routes": len(route_rows), "uncaptured_mirror_routes": len(gap_urls), }, ensure_ascii=False, indent=2, ) ) return 0 if __name__ == "__main__": raise SystemExit(main())