from __future__ import annotations from fastapi import APIRouter, Depends, Query from sqlalchemy.ext.asyncio import AsyncSession from app.dependencies import get_db from app.enums.home_material import HomeMaterialMediaType, HomeMaterialPublicResponseMode from app.schemas.home_material import ( HomeMaterialPublicCategoryListOut, HomeMaterialPublicFlatOut, HomeMaterialPublicGroupedOut, ) from app.services.home_material import home_material_service router = APIRouter(prefix="/home-materials", tags=["home-materials"]) @router.get( "/categories", response_model=HomeMaterialPublicCategoryListOut, summary="获取首页素材行业列表", description=( "获取首页素材行业列表,用于前端渲染行业 Tab/筛选。" "只返回已启用、未软删行业;only_has_assets=true 时只返回存在 success + is_active + watermarked_url 的行业。" "统计素材数量时不连表,先查行业列表,再按 category_id 批量 group by 查询素材数量并 map 回填。" ), ) async def get_public_home_material_categories( with_asset_count: bool = Query(True, description="是否返回每个行业下可展示素材数量。"), media_type: HomeMaterialMediaType | None = Query(None, description="统计指定素材类型:image图片,video视频。不传表示全部。"), only_has_assets: bool = Query(True, description="是否只返回有可展示素材的行业。"), db: AsyncSession = Depends(get_db), ): return await home_material_service.get_public_categories( db, with_asset_count=with_asset_count, media_type=media_type, only_has_assets=only_has_assets, ) @router.get( "", response_model=HomeMaterialPublicGroupedOut | HomeMaterialPublicFlatOut, summary="获取首页素材展示数据", description=( "获取首页素材展示数据。支持不传行业返回全部行业分组;支持 category_id/category_key/category_ids/category_keys 按行业过滤," "优先级为 category_id > category_key > category_ids > category_keys。" "response_mode=grouped 时按行业分组并限制每个行业 limit_per_category 条;" "response_mode=flat 时返回平铺分页素材流。前台接口只返回水印素材 url,不返回原始素材 original_url。" ), ) async def get_public_home_materials( category_id: str | None = Query(None, description="单个行业ID。优先级最高。"), category_key: str | None = Query(None, description="单个行业key。未传 category_id 时生效。"), category_ids: str | None = Query(None, description="多个行业ID,英文逗号分隔。未传单行业参数时生效。"), category_keys: str | None = Query(None, description="多个行业key,英文逗号分隔。优先级最低。"), media_type: HomeMaterialMediaType | None = Query(None, description="素材类型筛选:image图片,video视频。不传表示全部。"), limit_per_category: int = Query(8, ge=1, le=50, description="grouped 模式下每个行业最多返回几条素材,默认8,最大50。"), include_empty_categories: bool = Query(False, description="grouped 模式下是否返回无素材行业。默认 false。"), response_mode: HomeMaterialPublicResponseMode = Query(HomeMaterialPublicResponseMode.GROUPED, description="返回模式:grouped按行业分组,flat平铺分页。"), page: int = Query(1, ge=1, description="flat 模式页码,默认1。"), page_size: int = Query(20, ge=1, le=100, description="flat 模式每页数量,默认20,最大100。"), db: AsyncSession = Depends(get_db), ): return await home_material_service.get_public_home_materials( db, category_id=category_id, category_key=category_key, category_ids=category_ids, category_keys=category_keys, media_type=media_type, limit_per_category=limit_per_category, include_empty_categories=include_empty_categories, response_mode=response_mode, page=page, page_size=page_size, )