Files

256 lines
8.3 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
大屏素材 API
素材分类和素材管理
"""
import logging
from typing import List
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.database import get_db
from online_dev.screen_design.material_schema import (
MaterialCategoryCreateIn,
MaterialCategoryUpdateIn,
MaterialCategoryOut,
MaterialCreateIn,
MaterialUpdateIn,
MaterialOut,
)
from online_dev.screen_design.material_service import MaterialCategoryService, MaterialService
logger = logging.getLogger(__name__)
router = APIRouter(prefix='/screen/material', tags=['大屏素材'])
# ============ 素材分类 API ============
@router.get('/categories', response_model=List[MaterialCategoryOut], summary='素材分类列表')
async def list_material_categories(db: AsyncSession = Depends(get_db)):
"""获取所有素材分类"""
categories = await MaterialCategoryService.get_all(db)
result = []
for cat in categories:
count = await MaterialCategoryService.get_material_count(db, cat.id)
result.append(MaterialCategoryOut.from_orm_model(cat, material_count=count))
return result
@router.post('/categories', response_model=MaterialCategoryOut, summary='创建素材分类')
async def create_material_category(
data: MaterialCategoryCreateIn,
db: AsyncSession = Depends(get_db),
):
"""创建素材分类"""
# 检查编码是否已存在
if await MaterialCategoryService.check_code_exists(db, data.code):
raise HTTPException(status_code=400, detail=f"分类编码 {data.code} 已存在")
category = await MaterialCategoryService.create(db, data)
await db.commit()
return MaterialCategoryOut.from_orm_model(category, material_count=0)
@router.put('/categories/{category_id}', response_model=MaterialCategoryOut, summary='更新素材分类')
async def update_material_category(
category_id: str,
data: MaterialCategoryUpdateIn,
db: AsyncSession = Depends(get_db),
):
"""更新素材分类"""
category = await MaterialCategoryService.get_by_id(db, category_id)
if not category:
raise HTTPException(status_code=404, detail="分类不存在")
category = await MaterialCategoryService.update(db, category_id, data)
await db.commit()
count = await MaterialCategoryService.get_material_count(db, category.id)
return MaterialCategoryOut.from_orm_model(category, material_count=count)
@router.delete('/categories/{category_id}', summary='删除素材分类')
async def delete_material_category(
category_id: str,
db: AsyncSession = Depends(get_db),
):
"""删除素材分类(同时删除分类下的所有素材)"""
category = await MaterialCategoryService.get_by_id(db, category_id)
if not category:
raise HTTPException(status_code=404, detail="分类不存在")
await MaterialCategoryService.delete_with_materials(db, category_id)
await db.commit()
return {'success': True}
# ============ 素材 API ============
async def _get_file_info(db: AsyncSession, file_id: str):
"""获取文件信息"""
file_url = ''
file_type = 'image'
file_size = 0
if file_id:
try:
from core.file_manager.model import FileManager
stmt = select(FileManager).where(FileManager.id == file_id)
file_result = await db.execute(stmt)
file_obj = file_result.scalar_one_or_none()
if file_obj:
file_url = file_obj.url or ''
file_size = file_obj.size or 0
file_ext = (file_obj.file_ext or '').lower()
file_type = 'svg' if file_ext == 'svg' or file_ext == '.svg' else 'image'
except Exception as e:
logger.warning(f"获取文件信息失败: {e}")
return file_url, file_type, file_size
@router.get('/list', response_model=List[MaterialOut], summary='素材列表')
async def list_materials(
category_id: str = Query(default=None, alias="categoryId", description="分类ID"),
db: AsyncSession = Depends(get_db),
):
"""获取素材列表"""
materials = await MaterialService.get_list_by_category(db, category_id)
result = []
for material in materials:
# 获取分类名称
category_name = ''
if material.category_id:
category = await MaterialCategoryService.get_by_id(db, material.category_id)
if category:
category_name = category.name
# 获取文件信息
file_url, file_type, file_size = await _get_file_info(db, material.file_id)
result.append(MaterialOut.from_orm_model(
material,
category_name=category_name,
file_url=file_url,
file_type=file_type,
file_size=file_size,
))
return result
@router.post('/create', response_model=MaterialOut, summary='创建素材')
async def create_material(
data: MaterialCreateIn,
db: AsyncSession = Depends(get_db),
):
"""创建素材(关联已上传的文件)"""
# 验证分类(category_id 为空时表示无分类素材)
category = None
if data.category_id:
category = await MaterialCategoryService.get_by_id(db, data.category_id)
if not category:
raise HTTPException(status_code=400, detail="分类不存在")
# 验证文件
try:
from core.file_manager.model import FileManager
stmt = select(FileManager).where(FileManager.id == data.file_id)
file_result = await db.execute(stmt)
file_obj = file_result.scalar_one_or_none()
if not file_obj:
raise HTTPException(status_code=400, detail="文件不存在")
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=400, detail=f"验证文件失败: {e}")
# 创建素材
material = await MaterialService.create(db, data)
await db.commit()
# 获取文件信息
file_url = file_obj.url or ''
file_size = file_obj.size or 0
file_ext = (file_obj.file_ext or '').lower()
file_type = 'svg' if file_ext == 'svg' or file_ext == '.svg' else 'image'
return MaterialOut.from_orm_model(
material,
category_name=category.name if category else '',
file_url=file_url,
file_type=file_type,
file_size=file_size,
)
@router.put('/{material_id}', response_model=MaterialOut, summary='更新素材')
async def update_material(
material_id: str,
data: MaterialUpdateIn,
db: AsyncSession = Depends(get_db),
):
"""更新素材信息"""
material = await MaterialService.get_by_id(db, material_id)
if not material:
raise HTTPException(status_code=404, detail="素材不存在")
# 如果更新分类,验证分类存在
if data.category_id:
category = await MaterialCategoryService.get_by_id(db, data.category_id)
if not category:
raise HTTPException(status_code=400, detail="分类不存在")
material = await MaterialService.update(db, material_id, data)
await db.commit()
# 获取分类名称
category_name = ''
if material.category_id:
category = await MaterialCategoryService.get_by_id(db, material.category_id)
if category:
category_name = category.name
# 获取文件信息
file_url, file_type, file_size = await _get_file_info(db, material.file_id)
return MaterialOut.from_orm_model(
material,
category_name=category_name,
file_url=file_url,
file_type=file_type,
file_size=file_size,
)
@router.delete('/{material_id}', summary='删除素材')
async def delete_material(
material_id: str,
db: AsyncSession = Depends(get_db),
):
"""删除素材"""
material = await MaterialService.get_by_id(db, material_id)
if not material:
raise HTTPException(status_code=404, detail="素材不存在")
await MaterialService.delete(db, material_id)
await db.commit()
return {'success': True}
@router.delete('/batch', summary='批量删除素材')
async def batch_delete_materials(
ids: List[str] = Query(..., description="素材ID列表"),
db: AsyncSession = Depends(get_db),
):
"""批量删除素材"""
count = await MaterialService.batch_delete(db, ids)
await db.commit()
return {'count': count}