clean_blank_template_assets.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. from __future__ import annotations
  2. import json
  3. import shutil
  4. from pathlib import Path
  5. from extract_music_template_assets import make_pptx
  6. ROOT = Path(__file__).resolve().parents[1]
  7. ASSET_ROOT = (ROOT / "public" / "ai-courseware-templates" / "extracted").resolve()
  8. MANIFEST = ASSET_ROOT / "manifest.json"
  9. # 视觉复核后的拒绝清单:纯底色或装饰覆盖率过低,缩略图中等同空白。
  10. REJECTED = {
  11. "dark-lute": {2, 3, 5, 6, 7, 8},
  12. "spring-outing": {7, 8, 9},
  13. "ink-jiangnan": {1, 7, 8, 9, 10},
  14. "rhythm-train": {2, 3, 5},
  15. "sunset-drum": {10},
  16. "ballroom-silhouette": {1},
  17. "color-theory": {1},
  18. }
  19. # 清理后仅剩封面,没有内容页能力,整套下架。
  20. DROPPED_TEMPLATES = {"floral-jasmine"}
  21. def checked_template_dir(template_id: str) -> Path:
  22. target = (ASSET_ROOT / template_id).resolve()
  23. if target.parent != ASSET_ROOT:
  24. raise RuntimeError(f"拒绝处理资产目录之外的路径:{target}")
  25. return target
  26. def main() -> None:
  27. manifest = json.loads(MANIFEST.read_text(encoding="utf-8"))
  28. kept_items: list[dict[str, object]] = []
  29. removed_files: list[str] = []
  30. for item in manifest["items"]:
  31. template_id = str(item["id"])
  32. target_dir = checked_template_dir(template_id)
  33. if template_id in DROPPED_TEMPLATES:
  34. if target_dir.exists():
  35. shutil.rmtree(target_dir)
  36. removed_files.append(f"{template_id}/(整套)")
  37. continue
  38. rejected = REJECTED.get(template_id, set())
  39. old_backgrounds = list(item.get("backgrounds", []))
  40. old_sources = list(item.get("roleSourceSlides", []))
  41. backgrounds: list[str] = []
  42. sources: list[int] = []
  43. for index, background in enumerate(old_backgrounds):
  44. path = target_dir / Path(str(background)).name
  45. asset_number = int(path.stem.rsplit("-", 1)[-1])
  46. if asset_number in rejected:
  47. if path.exists():
  48. path.unlink()
  49. removed_files.append(f"{template_id}/{path.name}")
  50. continue
  51. if not path.exists():
  52. raise FileNotFoundError(f"有效模板背景缺失:{path}")
  53. backgrounds.append(str(background))
  54. if index < len(old_sources):
  55. sources.append(old_sources[index])
  56. if not backgrounds:
  57. raise RuntimeError(f"模板 {template_id} 清理后没有可用背景")
  58. template_file = target_dir / f"{template_id}.pptx"
  59. make_pptx([target_dir / Path(path).name for path in backgrounds], template_file)
  60. item["backgrounds"] = backgrounds
  61. item["roleSourceSlides"] = sources
  62. item["usableBackgroundCount"] = len(backgrounds)
  63. kept_items.append(item)
  64. MANIFEST.write_text(json.dumps({"items": kept_items}, ensure_ascii=False, indent=2), encoding="utf-8")
  65. print(json.dumps({"removed": removed_files, "templates": len(kept_items)}, ensure_ascii=False, indent=2))
  66. if __name__ == "__main__":
  67. main()