""" 模板应用工具:把 CardTemplate 的预设(theme + background + design)应用到 Project。 - 复制 LibraryAsset 中的素材到 projects///_xxx.png - 在 Project 的 design 中写 background_color / border_color / suit_colors 等 """ import os import shutil from time import time from django.conf import settings from apps.projects.models import Project, Asset, LibraryAsset def _copy_lib_to_project(project, lib, asset_type, asset_key): """把 LibraryAsset 的文件复制到 projects/// 下,并在 Project.assets 建记录""" project_media_dir = f'projects/{project.id}/{asset_type}' full_dir = os.path.join(settings.MEDIA_ROOT, project_media_dir) os.makedirs(full_dir, exist_ok=True) src = os.path.join(settings.MEDIA_ROOT, lib.file_path) if not os.path.exists(src): return None ts = int(time() * 1000) fn = f'{asset_key}_{ts}_{lib.file_name}' dst_rel = f'{project_media_dir}/{fn}' shutil.copy2(src, os.path.join(settings.MEDIA_ROOT, dst_rel)) # 读图尺寸 width = height = None try: from PIL import Image with Image.open(os.path.join(settings.MEDIA_ROOT, dst_rel)) as im: width, height = im.size except Exception: pass # 删除同 (asset_type, asset_key) 的旧记录 Asset.objects.filter(project=project, asset_type=asset_type, asset_key=asset_key).delete() return Asset.objects.create( project=project, asset_type=asset_type, asset_key=asset_key, file_path=dst_rel, file_name=fn, width=width, height=height, ) def apply_template_to_project(project, template): """根据 CardTemplate 的预设填充项目:写 design + 复制 JQK/Joker 素材 默认行为: - 整副牌 background_color / border_color 等设计项按模板的 design_override 写入 - 模板绑定的 theme_id 对应的所有 LibraryAsset 复制成 JQK/Joker 资产 - 应用到所有 4 个花色 + 大小王 """ # 1. 应用 design 覆盖 base_design = dict(project.design or {}) override = template.design_override or {} base_design.update(override) # 同步花色颜色 if 'suit_symbols' not in base_design: base_design['suit_symbols'] = {} base_design['suit_symbols']['spade'] = {'type': 'text', 'value': '♠', 'color': template.color_spade, 'asset_id': None} base_design['suit_symbols']['heart'] = {'type': 'text', 'value': '♥', 'color': template.color_heart, 'asset_id': None} base_design['suit_symbols']['club'] = {'type': 'text', 'value': '♣', 'color': template.color_club, 'asset_id': None} base_design['suit_symbols']['diamond'] = {'type': 'text', 'value': '♦', 'color': template.color_diamond, 'asset_id': None} # 背景色 base_design['background_color'] = template.color_background project.design = base_design # 2. 初始化背面设计(如果尚未设置) if not project.back_design: from apps.projects.models import default_back_design project.back_design = default_back_design() project.save() # 2. 复制主题素材(如果绑定了 theme_id) theme_id = template.theme_id if not theme_id: return {'applied': 0, 'theme_id': None} libs = LibraryAsset.objects.filter(theme_id=theme_id) if not libs.exists(): return {'applied': 0, 'theme_id': theme_id, 'warning': f'no library assets for theme {theme_id}'} applied = [] for lib in libs: # asset_type: J/Q/K -> face_card;joker -> joker if lib.role == 'joker': asset_type = 'joker' # 默认应用到 joker-big asset_key = 'joker-big' # 同主题如果有 small 的角色素材就分别处理 if lib.asset_id == 'small': asset_key = 'joker-small' else: asset_type = 'face_card' # 4 个花色都复制 for suit in ('spade', 'heart', 'club', 'diamond'): asset_key = f'{suit}-{lib.role}' a = _copy_lib_to_project(project, lib, asset_type, asset_key) if a: applied.append(a.id) continue a = _copy_lib_to_project(project, lib, asset_type, asset_key) if a: applied.append(a.id) return { 'applied': len(applied), 'theme_id': theme_id, 'asset_ids': applied, }