feat: 预设素材库 - 4 套主题 × 4 张图 = 16 张 PNG

主题:classical 古典宫廷(王子/皇后/国王/小丑)
      modern    现代人物(小孩/女青年/男青年/小丑鱼)
      astronomy 天文(星星/月亮/太阳/黑洞)
      minimal   简笔符号(圆点/♀/♂/叉)

改动:
- 新增 LibraryAsset 模型(全局素材库,theme_id/role/asset_id 索引)
- 新增 seed_library 管理命令,用 Pillow 画 16 张 PNG 素材
- 新增 /api/projects/library/ 列表 API
- 新增 /api/projects/{pid}/library/{id}/apply/ 应用 API
  把预设素材复制到 projects/<pid>/joker 或 face_card 下,作为该牌位的素材
- AssetPanel 加 tab 切换:「我的素材」+「预设主题」,主题可筛选、点击套用到当前牌
- 修复 generate_card_png 的 joker asset 匹配 bug:which 应该是 card_key(含前缀)才能匹配 asset_key

设计要点:
- 预设素材只画上半身(y=0~150),下半留空,让系统的'自动对称'流水线正确工作
- 预设素材 PNG 200×300,深色描边 + 半透明浅色填充,在任意牌面背景上叠加都清晰
This commit is contained in:
Developer
2026-06-02 14:39:52 +08:00
parent 0a22a0c0d2
commit 5ca000b8ab
24 changed files with 815 additions and 47 deletions

View File

@@ -104,3 +104,28 @@ class CardLayer(models.Model):
class Meta:
ordering = ['card_key', 'z_index']
class LibraryAsset(models.Model):
"""预设素材库(与 Project 无关,全局共享)
主题分类classical/modern/astronomy/minimal ...
角色J / Q / K / joker
"""
id = models.BigAutoField(primary_key=True)
theme_id = models.CharField(max_length=50, db_index=True) # classical / modern ...
theme_name = models.CharField(max_length=100) # 古典宫廷 / 现代人物 ...
role = models.CharField(max_length=10, db_index=True) # 'J' / 'Q' / 'K' / 'joker'
role_name = models.CharField(max_length=50) # '王子' / '皇后' ...
asset_id = models.CharField(max_length=50) # 'prince' / 'queen' ...
label = models.CharField(max_length=100) # '古典·王子'
description = models.CharField(max_length=255, blank=True)
file_path = models.CharField(max_length=255) # library/classical/prince.svg
file_name = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'{self.theme_name}/{self.role_name}'
class Meta:
ordering = ['theme_id', 'role', 'asset_id']
unique_together = [['theme_id', 'asset_id']]