import logging from typing import Any, Optional from fastapi import APIRouter, Depends, Query, Body from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from app.models.resources_material import ResourcesMaterial from app.models.pre_test_template import PreTestTemplate from app.dependencies import get_db, get_current_user from app.schemas.resources_material import ResourcesMaterialListResponse, PreTestMaterialRequest from app.services.resources_material_service import get_resources_material_list from app.services.pre_test_queue import pre_test_queue from app.utils.id_gen import generate_id router = APIRouter(prefix="/resources-material", tags=["resources-material"]) @router.get( "/list", summary="查询素材列表", description="通过advertiser_id,material_id,upload_id,resource_type查询素材列表,同时返回关联的资源信息", response_model=ResourcesMaterialListResponse, ) async def get_resources_material_list_api( advertiser_id: Optional[str] = Query(None, description="广告主id"), material_id: Optional[str] = Query(None, description="素材id"), upload_id: Optional[str] = Query(None, description="上传资源平台id"), file_name: Optional[str] = Query(None, description="文件名"), resource_type: Optional[str] = Query(None, description="资源类型,image或者video"), page: int = Query(1, description="页码"), page_size: int = Query(20, description="每页数量"), db: AsyncSession = Depends(get_db), current_user: dict = Depends(get_current_user), ) -> Any | dict: items, total = await get_resources_material_list( db=db, advertiser_id=advertiser_id, material_id=material_id, upload_id=upload_id, file_name=file_name, resource_type=resource_type, page=page, page_size=page_size, user_id=current_user.id, ) return { "code": 0, "message": "查询成功", "data": items, "total": total, } #如果素材上传的时候没有指定前测,现在可以对已经上传好的素材进行前测 @router.post( "/pre-commit", summary="素材列表提交前测", description="通过素材列表提交未前测的素材,异步处理,立即返回任务ID,结果稍后通过列表查询", ) async def pre_test_material( req: PreTestMaterialRequest = Body(..., description="前测请求体"), db: AsyncSession = Depends(get_db), current_user: dict = Depends(get_current_user), ) -> Any | dict: try: invalid_ids = [] grouped_videos = {} #检查前测模板是否有效 pre_test_template = await db.execute( select(PreTestTemplate) .where( PreTestTemplate.id == req.pre_test_template_id, PreTestTemplate.user_id == current_user.id, PreTestTemplate.deleted_at.is_(None), ) ) pre_test_template = pre_test_template.scalar_one_or_none() if not pre_test_template: return {"code": 1, "message": f"前测模板{req.pre_test_template_id}不存在或不属于当前用户"} for resource_material_id in req.resources_material_ids: resource_material = await db.execute( select(ResourcesMaterial) .where( ResourcesMaterial.id == resource_material_id, ResourcesMaterial.user_id == current_user.id, ResourcesMaterial.deleted_at.is_(None), ) ) resource_material = resource_material.scalar_one_or_none() if not resource_material: invalid_ids.append(f"{resource_material_id}: 资源不存在或不属于当前用户") continue if resource_material.status is not None: invalid_ids.append(f"{resource_material_id}: 该资源已进行过前测") continue if not resource_material.upload_id: invalid_ids.append(f"{resource_material_id}: 该资源未上传到平台") continue if resource_material.resource_type != "video": invalid_ids.append(f"{resource_material_id}: 前测仅支持视频类型") continue key = f"{resource_material.oauth_id}|{resource_material.advertiser_id}" if key not in grouped_videos: grouped_videos[key] = [] grouped_videos[key].append({ "id": resource_material.id, "upload_id": resource_material.upload_id, }) if invalid_ids: return {"code": 1, "message": "; ".join(invalid_ids)} if not grouped_videos: return {"code": 1, "message": "没有有效的视频资源"} task_id = generate_id() await pre_test_queue.enqueue({ "task_id": task_id, "grouped_videos": grouped_videos, "pre_test_template_id": req.pre_test_template_id, }) return { "code": 0, "message": "任务已提交,正在处理中", "data": { "task_id": task_id, "total_groups": len(grouped_videos), }, } except ValueError as e: return {"code": 1, "message": str(e)} except Exception as e: return {"code": 1, "message": str(e)}