from __future__ import annotations import json import shutil from pathlib import Path from extract_music_template_assets import make_pptx ROOT = Path(__file__).resolve().parents[1] ASSET_ROOT = (ROOT / "public" / "ai-courseware-templates" / "extracted").resolve() MANIFEST = ASSET_ROOT / "manifest.json" # 视觉复核后的拒绝清单:纯底色或装饰覆盖率过低,缩略图中等同空白。 REJECTED = { "dark-lute": {2, 3, 5, 6, 7, 8}, "spring-outing": {7, 8, 9}, "ink-jiangnan": {1, 7, 8, 9, 10}, "rhythm-train": {2, 3, 5}, "sunset-drum": {10}, "ballroom-silhouette": {1}, "color-theory": {1}, } # 清理后仅剩封面,没有内容页能力,整套下架。 DROPPED_TEMPLATES = {"floral-jasmine"} def checked_template_dir(template_id: str) -> Path: target = (ASSET_ROOT / template_id).resolve() if target.parent != ASSET_ROOT: raise RuntimeError(f"拒绝处理资产目录之外的路径:{target}") return target def main() -> None: manifest = json.loads(MANIFEST.read_text(encoding="utf-8")) kept_items: list[dict[str, object]] = [] removed_files: list[str] = [] for item in manifest["items"]: template_id = str(item["id"]) target_dir = checked_template_dir(template_id) if template_id in DROPPED_TEMPLATES: if target_dir.exists(): shutil.rmtree(target_dir) removed_files.append(f"{template_id}/(整套)") continue rejected = REJECTED.get(template_id, set()) old_backgrounds = list(item.get("backgrounds", [])) old_sources = list(item.get("roleSourceSlides", [])) backgrounds: list[str] = [] sources: list[int] = [] for index, background in enumerate(old_backgrounds): path = target_dir / Path(str(background)).name asset_number = int(path.stem.rsplit("-", 1)[-1]) if asset_number in rejected: if path.exists(): path.unlink() removed_files.append(f"{template_id}/{path.name}") continue if not path.exists(): raise FileNotFoundError(f"有效模板背景缺失:{path}") backgrounds.append(str(background)) if index < len(old_sources): sources.append(old_sources[index]) if not backgrounds: raise RuntimeError(f"模板 {template_id} 清理后没有可用背景") template_file = target_dir / f"{template_id}.pptx" make_pptx([target_dir / Path(path).name for path in backgrounds], template_file) item["backgrounds"] = backgrounds item["roleSourceSlides"] = sources item["usableBackgroundCount"] = len(backgrounds) kept_items.append(item) MANIFEST.write_text(json.dumps({"items": kept_items}, ensure_ascii=False, indent=2), encoding="utf-8") print(json.dumps({"removed": removed_files, "templates": len(kept_items)}, ensure_ascii=False, indent=2)) if __name__ == "__main__": main()