Files
video-gen/video-gen-api/app/api/v1/pre_test_template.py
T

359 lines
12 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.
import json
from typing import Any, Optional, Dict
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from app.models.pre_test_template import PreTestTemplate
from app.utils.douyinApi import DouyinApi
from app.utils.area import parse_district_data, get_area_by_level, get_cached_area_data, fetch_and_cache_area_data
from app.dependencies import get_current_user, get_db
from app.models.user import User
from app.schemas.pre_test_template import (
PreTestTemplateCreate,
PreTestTemplateListResponse,
PreTestTemplateOut,
PreTestTemplateUpdate,
)
from app.services.pre_test_template_service import (
create_pre_test_template,
delete_pre_test_template,
get_default_template,
get_pre_test_template,
get_pre_test_template_list,
update_pre_test_template,
)
router = APIRouter(prefix="/pre-test-template", tags=["前测模板"])
def _template_to_dict(template):
return {
"id": template.id,
"name": template.name,
"note": template.note,
"platform": template.platform,
"external_action": template.external_action,
"cpa_bid": template.cpa_bid,
"audience_gender": template.audience_gender,
"audience_age": json.loads(template.audience_age) if template.audience_age else None,
"audience_region": json.loads(template.audience_region) if template.audience_region else None,
"audience_network": json.loads(template.audience_network) if template.audience_network else None,
"cus_name": template.cus_name,
"pricing_type": template.pricing_type,
"cost_cap": template.cost_cap,
"target_cost": template.target_cost,
"nobid": template.nobid,
"cpc_bid": template.cpc_bid,
"budget": template.budget,
"is_default": template.is_default,
"user_id": template.user_id,
"created_at": template.created_at,
"updated_at": template.updated_at,
}
@router.post(
"/create",
summary="创建前测模板",
description="创建一个新的前测模板",
)
async def create_template(
req: PreTestTemplateCreate,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
) -> Any:
try:
#新增一个判断,如果模板名称重复,提示用户修改
result = await db.execute(
select(PreTestTemplate).where(
PreTestTemplate.name == req.name,
PreTestTemplate.user_id == current_user.id,
PreTestTemplate.deleted_at.is_(None),
)
)
existing_template = result.scalar()
if existing_template:
raise ValueError("模板名称已存在")
template = await create_pre_test_template(
user_id=current_user.id,
db=db,
name=req.name,
note=req.note,
platform=req.platform,
external_action=req.external_action,
cpa_bid=req.cpa_bid,
audience_gender=req.audience_gender,
audience_age=req.audience_age,
audience_region=req.audience_region,
audience_network=req.audience_network,
cus_name=req.cus_name,
pricing_type=req.pricing_type,
cost_cap=req.cost_cap,
target_cost=req.target_cost,
nobid=req.nobid,
cpc_bid=req.cpc_bid,
budget=req.budget,
is_default=req.is_default,
)
return {
"code": 0,
"message": "创建成功",
}
except ValueError as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e),
)
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"创建失败: {str(e)}",
)
@router.get(
"/list",
summary="获取前测模板列表",
description="获取当前用户的前测模板列表,支持按平台筛选和分页",
response_model=PreTestTemplateListResponse,
)
async def list_templates(
platform: Optional[str] = Query(None, description="投放平台筛选(AD/QIANCHUAN/LOCAL"),
page: int = Query(1, description="页码,默认1"),
page_size: int = Query(10, description="每页数量,默认10,最大100"),
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
) -> Any:
try:
result = await get_pre_test_template_list(
user_id=current_user.id,
db=db,
platform=platform,
page=page,
page_size=page_size,
)
return {
"code": 0,
"message": "查询成功",
"data": [_template_to_dict(t) for t in result["data"]],
"pagination": {
"page": result["page"],
"page_size": result["page_size"],
"total": result["total"],
"total_pages": (result["total"] + result["page_size"] - 1) // result["page_size"],
},
}
except ValueError as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e),
)
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"查询失败: {str(e)}",
)
@router.get(
"/default",
summary="获取默认前测模板",
description="获取当前用户的默认前测模板",
)
async def get_default(
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
) -> Any:
try:
template = await get_default_template(current_user.id, db)
if not template:
return {
"code": 0,
"message": "未设置默认模板",
"data": None,
}
return {
"code": 0,
"message": "查询成功",
"data": _template_to_dict(template),
}
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"查询失败: {str(e)}",
)
@router.get(
"/select/{template_id}",
summary="获取前测模板详情",
description="根据模板id获取前测模板详情",
)
async def get_template(
template_id: str,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
) -> Any:
try:
template = await get_pre_test_template(template_id, current_user.id, db)
if not template:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="模板不存在",
)
return {
"code": 0,
"message": "查询成功",
"data": _template_to_dict(template),
}
except HTTPException:
raise
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"查询失败: {str(e)}",
)
@router.post(
"/update/{template_id}",
summary="更新前测模板",
description="更新指定的前测模板",
)
async def update_template(
template_id: str,
req: PreTestTemplateUpdate,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
) -> Any:
try:
update_data = req.dict(exclude_none=True)
template = await update_pre_test_template(template_id, current_user.id, db, **update_data)
if not template:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="模板不存在",
)
return {
"code": 0,
"message": "更新成功",
"data": _template_to_dict(template),
}
except HTTPException:
raise
except ValueError as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e),
)
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"更新失败: {str(e)}",
)
@router.get(
"/delete/{template_id}",
summary="删除前测模板",
description="软删除指定的前测模板",
)
async def delete_template(
template_id: str,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
) -> Any:
try:
success = await delete_pre_test_template(template_id, current_user.id, db)
if not success:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="模板不存在",
)
return {
"code": 0,
"message": "删除成功",
}
except HTTPException:
raise
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"删除失败: {str(e)}",
)
@router.get(
"/getArea",
summary="获取行政区域信息",
description="获取指定级别的行政区域信息,支持一级、二级、三级区域,如果需要更新地区,执行:/api/pre-test-template/getArea?oauth_id=0019ecab9b8bc57d964&advertiser_id=1836693172153543",
)
async def get_template_area(
oauth_id: str = Query(None, description="授权ID选填,更新地区必填"),
advertiser_id: str = Query(default="1836693172153543", description="授权ID选填,更新地区必填"),
code: Optional[str] = Query("CN", description="行政区域编码,默认中国CN,选填"),
level: Optional[str] = Query("ONE_LEVEL", description="行政区域层级,可选值:ONE_LEVEL(获取省份)、TWO_LEVEL(市级)、THREE_LEVEL(区级)"),
parent_code: Optional[str] = Query(None, description="父级区域编码,获取二级时传一级编码,获取三级时传二级编码"),
) -> Any:
try:
# 1. 先检查缓存是否存在
area_list = get_cached_area_data()
# 2. 如果缓存不存在,调用接口获取数据并保存到缓存
if not area_list:
area_list = await fetch_and_cache_area_data(oauth_id, advertiser_id, code)
# 3. 根据 level 参数过滤区域
if level == "ONE_LEVEL":
result = get_area_by_level(area_list, "ONE_LEVEL")
elif level == "TWO_LEVEL":
result = get_area_by_level(area_list, "TWO_LEVEL", parent_code)
elif level == "THREE_LEVEL":
if not parent_code:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="获取三级区域需要提供二级区域编码(parent_code)",
)
result = get_area_by_level(area_list, "THREE_LEVEL", parent_code)
else:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"不支持的级别: {level}",
)
# 4. 转换为字典格式返回
result_dict = [area.to_dict() for area in result]
return {
"code": 0,
"message": "成功",
"data": result_dict,
}
except HTTPException:
raise
except ValueError as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e),
)
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"获取区域信息失败: {str(e)}",
)