"""图片生成 API 路由""" from typing import Optional from fastapi import APIRouter, HTTPException, status from pydantic import BaseModel, Field from app.services.image_generator import ( IMAGE_STYLES, LAYOUT_OPTIONS, ImageGenerator, ImageGenerationError, PLATFORM_IMAGE_SPECS, ) router = APIRouter(prefix="/image", tags=["图片生成"]) class GenerateCoverRequest(BaseModel): """生成封面图请求""" title: str = Field(..., description="文章标题") platform: str = Field(..., description="目标平台") image_type: str = Field(default="cover", description="图片类型: cover/inline") style: str = Field(default="modern", description="风格选项") layout: str = Field(default="centered", description="排版选项") custom_prompt: Optional[str] = Field(default=None, description="自定义提示词") class ImageResultResponse(BaseModel): """图片生成结果响应""" url: str width: int height: int prompt: str platform: str task_id: str class ImageSpecsResponse(BaseModel): """平台图片规格响应""" platform: str specs: dict class StyleOption(BaseModel): """风格选项""" value: str name: str class LayoutOption(BaseModel): """排版选项""" value: str name: str class ImageConfigResponse(BaseModel): """图片生成配置响应""" platforms: list[str] styles: list[StyleOption] layouts: list[LayoutOption] @router.post("/generate-cover", response_model=ImageResultResponse) async def generate_cover(request: GenerateCoverRequest): """生成封面图 基于阿里云百炼(万相-文生图V1)生成封面图,自动适配目标平台的尺寸规格。 Args: request: 生成请求参数 Returns: ImageResultResponse: 包含图片URL和元数据 Raises: HTTPException: 当平台不支持或API调用失败时 """ # 验证平台是否支持 supported_platforms = ImageGenerator.get_supported_platforms() if request.platform not in supported_platforms: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"不支持的平台: {request.platform},支持的平台: {', '.join(supported_platforms)}", ) # 验证风格选项 if request.style not in IMAGE_STYLES: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"不支持的风格: {request.style},支持的风格: {', '.join(IMAGE_STYLES.keys())}", ) # 验证排版选项 if request.layout not in LAYOUT_OPTIONS: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"不支持的排版: {request.layout},支持的排版: {', '.join(LAYOUT_OPTIONS.keys())}", ) # 验证图片类型 if request.image_type not in ("cover", "inline"): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="图片类型只支持: cover, inline", ) generator = ImageGenerator() try: result = await generator.generate_cover( title=request.title, platform=request.platform, image_type=request.image_type, style=request.style, layout=request.layout, custom_prompt=request.custom_prompt, ) return ImageResultResponse( url=result.url, width=result.width, height=result.height, prompt=result.prompt, platform=result.platform, task_id=result.task_id, ) except ImageGenerationError as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"图片生成失败: {str(e)}", ) @router.get("/platforms", response_model=list[str]) async def get_supported_platforms(): """获取支持的平台列表""" return ImageGenerator.get_supported_platforms() @router.get("/platforms/{platform}/specs", response_model=ImageSpecsResponse) async def get_platform_specs(platform: str): """获取指定平台的图片规格 Args: platform: 平台标识 Returns: ImageSpecsResponse: 平台图片规格 Raises: HTTPException: 当平台不支持时 """ specs = ImageGenerator.get_platform_specs(platform) if specs is None: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"不支持的平台: {platform}", ) return ImageSpecsResponse(platform=platform, specs=specs) @router.get("/config", response_model=ImageConfigResponse) async def get_image_config(): """获取图片生成配置(风格、排版选项等)""" styles = [ StyleOption(value=key, name=value["name"]) for key, value in IMAGE_STYLES.items() ] layouts = [ LayoutOption(value=key, name=value["name"]) for key, value in LAYOUT_OPTIONS.items() ] return ImageConfigResponse( platforms=ImageGenerator.get_supported_platforms(), styles=styles, layouts=layouts, )