Files
game-cards-poker-design/backend/apps/projects/views_library.py

115 lines
3.9 KiB
Python
Raw Normal View History

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from django.conf import settings
from .models import LibraryAsset, Project, Asset
from .serializers import LibraryAssetSerializer
import os
@api_view(['GET'])
def library_list(request):
"""列出所有预设素材(按主题分组)"""
assets = LibraryAsset.objects.all()
serializer = LibraryAssetSerializer(assets, many=True, context={'request': request})
# 按 theme_id 分组
grouped = {}
for a in serializer.data:
a['file_url'] = f'{settings.MEDIA_URL}{a["file_path"]}'
grouped.setdefault(a['theme_id'], {
'theme_id': a['theme_id'],
'theme_name': a['theme_name'],
'description': a['description'],
'items': [],
})['items'].append(a)
return Response(list(grouped.values()))
@api_view(['GET'])
def library_themes(request):
"""返回所有主题的元信息(不含具体素材项,用于渲染主题筛选器)"""
themes = LibraryAsset.objects.values('theme_id', 'theme_name', 'description').distinct()
return Response(list(themes))
@api_view(['GET'])
def library_detail(request, pk):
"""单个预设素材的详情"""
try:
a = LibraryAsset.objects.get(pk=pk)
except LibraryAsset.DoesNotExist:
return Response({'error': 'Not found'}, status=status.HTTP_404_NOT_FOUND)
data = LibraryAssetSerializer(a, context={'request': request}).data
data['file_url'] = f'{settings.MEDIA_URL}{data["file_path"]}'
return Response(data)
@api_view(['POST'])
def library_apply(request, project_pk, pk):
"""把预设素材应用到项目某张牌默认spade-J / joker-big 等)
请求体: { card_key?: 'spade-J' } 可选不传则用预设素材的 role + 默认 spade
"""
try:
project = Project.objects.get(pk=project_pk)
lib = LibraryAsset.objects.get(pk=pk)
except (Project.DoesNotExist, LibraryAsset.DoesNotExist):
return Response({'error': 'not found'}, status=status.HTTP_404_NOT_FOUND)
card_key = request.data.get('card_key')
if not card_key:
# 默认: spade-{role} 或 joker-{which}
if lib.role == 'joker':
card_key = 'joker-big' # 默认应用到 big用户可换
else:
card_key = f'spade-{lib.role}'
# 决定 asset_type: J/Q/K -> face_cardjoker -> joker
asset_type = 'face_card' if lib.role in ('J', 'Q', 'K') else 'joker'
asset_key = card_key
# 删除该项目同 (asset_type, asset_key) 的旧记录(避免重复)
Asset.objects.filter(project=project, asset_type=asset_type, asset_key=asset_key).delete()
# 复制 library 文件到 projects/<pid>/ 下,避免污染原文件
import shutil
from time import time
project_media_dir = os.path.join('projects', str(project.id), asset_type)
full_dir = os.path.join(settings.MEDIA_ROOT, project_media_dir)
os.makedirs(full_dir, exist_ok=True)
src_path = os.path.join(settings.MEDIA_ROOT, lib.file_path)
ts = int(time() * 1000)
new_file_name = f'{asset_key}_{ts}_{lib.file_name}'
dst_rel = os.path.join(project_media_dir, new_file_name)
dst_abs = os.path.join(settings.MEDIA_ROOT, dst_rel)
shutil.copy2(src_path, dst_abs)
# 读 svg 尺寸
width = height = None
try:
from PIL import Image
with Image.open(dst_abs) as im:
width, height = im.size
except Exception:
pass
asset = Asset.objects.create(
project=project,
asset_type=asset_type,
asset_key=asset_key,
file_path=dst_rel,
file_name=new_file_name,
width=width,
height=height,
)
return Response({
'ok': True,
'asset_id': asset.id,
'card_key': card_key,
'asset_type': asset_type,
'file_url': f'{settings.MEDIA_URL}{dst_rel}',
}, status=status.HTTP_201_CREATED)