Files
game-cards-poker-design/backend/apps/templates/template_apply.py
Developer 7417a4a893 feat: 模板预设机制 - 4 套模板各绑一组 JQK/Joker + 背景
经典 → 古典宫廷(王子/皇后/国王/小丑)
现代 → 现代人物(小孩/女青年/男青年/小丑鱼)
卡通 → 现代人物 + 暖色调 + 圆边框
复古 → 简笔符号 + 深色边框 + 米色背景

后端:
- CardTemplate 新增 theme_id(绑预设主题)+ design_override(背景/边框/字体等覆盖)
- 新增 apply_template_to_project():把 LibraryAsset 复制到项目素材 + 写 design
- 创建项目时支持传 template_id,自动套用整套预设
- 模板列表 API 附加 library 预览(4 张图缩略)

前端 Home.vue:
- 4 套模板卡片每张带 4 张缩略图(来自 library 预览)
- 点模板一键创建项目 + 跳转到编辑器
- '新建空白项目' 保留为独立按钮

init_system 同步:4 套模板配置 + 应用到示例项目
2026-06-02 15:08:37 +08:00

111 lines
4.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
模板应用工具:把 CardTemplate 的预设theme + background + design应用到 Project。
- 复制 LibraryAsset 中的素材到 projects/<pid>/<asset_type>/<asset_key>_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/<pid>/<asset_type>/ 下,并在 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
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_cardjoker -> 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,
}