import json import logging from fastapi import APIRouter, Depends, HTTPException from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.dependencies import get_admin_user, get_db from app.models.api.api_model_pricing import ApiModelPricing from app.models.image_engine import ImageEngine from app.models.user import User from app.models.video_engine import VideoEngine from app.schemas.admin_api.api_model_pricing import ApiModelPricingCreate, ApiModelPricingOut from app.utils.id_gen import generate_id logger = logging.getLogger("videogen") router = APIRouter(prefix="/admin/api-model-pricings", tags=["admin-api-model-pricings"]) async def _validate_pricing_engine(db: AsyncSession, req: ApiModelPricingCreate) -> None: """校验定价规则绑定的引擎是否存在。""" gen_type = (req.gen_type or "").lower().strip() engine_id = (req.model_config_id or "").strip() if gen_type not in ("image", "video"): raise HTTPException(status_code=400, detail="gen_type 仅支持 image 或 video") if not engine_id: raise HTTPException(status_code=400, detail="model_config_id 不能为空,当前字段用于保存图片/视频引擎ID") model = ImageEngine if gen_type == "image" else VideoEngine result = await db.execute( select(model).where(model.id == engine_id, model.deleted_at.is_(None)).limit(1) ) engine = result.scalar_one_or_none() if not engine: detail = "图片定价规则绑定的图片引擎不存在" if gen_type == "image" else "视频定价规则绑定的视频引擎不存在" raise HTTPException(status_code=400, detail=detail) @router.get("", response_model=list[ApiModelPricingOut]) async def list_pricings( admin: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db), ): """列出所有 API 模型价格。""" result = await db.execute( select(ApiModelPricing).order_by( ApiModelPricing.gen_type.desc(), ApiModelPricing.model_config_id.desc(), ) ) return result.scalars().all() @router.post("", response_model=ApiModelPricingOut) async def create_pricing( req: ApiModelPricingCreate, admin: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db), ): """创建 API 模型价格。""" await _validate_pricing_engine(db, req) data = req.model_dump() data["gen_type"] = data["gen_type"].lower().strip() data["model_config_id"] = data["model_config_id"].strip() pricing = ApiModelPricing(id=generate_id(), **data) db.add(pricing) await db.commit() await db.refresh(pricing) return pricing @router.put("/{pricing_id}", response_model=ApiModelPricingOut) async def update_pricing( pricing_id: str, req: ApiModelPricingCreate, admin: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db), ): """更新 API 模型价格。""" result = await db.execute( select(ApiModelPricing).where(ApiModelPricing.id == pricing_id).limit(1) ) pricing = result.scalar_one_or_none() if not pricing: raise HTTPException(status_code=404, detail="定价规则不存在") await _validate_pricing_engine(db, req) data = req.model_dump() data["gen_type"] = data["gen_type"].lower().strip() data["model_config_id"] = data["model_config_id"].strip() for k, v in data.items(): setattr(pricing, k, v) await db.commit() await db.refresh(pricing) return pricing @router.delete("/{pricing_id}") async def delete_pricing( pricing_id: str, admin: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db), ): """删除 API 模型价格。""" result = await db.execute( select(ApiModelPricing).where(ApiModelPricing.id == pricing_id).limit(1) ) pricing = result.scalar_one_or_none() if not pricing: raise HTTPException(status_code=404, detail="定价规则不存在") await db.delete(pricing) await db.commit() return {"message": "ok"} @router.get("/grouped", response_model=dict) async def list_pricings_grouped( admin: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db), ): """按 gen_type 分组列出价格。""" result = await db.execute(select(ApiModelPricing)) pricings = result.scalars().all() grouped = {} for pricing in pricings: if pricing.gen_type not in grouped: grouped[pricing.gen_type] = [] grouped[pricing.gen_type].append(ApiModelPricingOut.model_validate(pricing)) return grouped