geo/backend/app/api/image.py

182 lines
5.1 KiB
Python
Raw Permalink 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.

"""图片生成 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,
)