| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- """
- 管理员模型管理API路由
- 提供模型列表、详情、创建、更新、价格设置等API端点
- Requirements: 7.1-7.4, 8.1-8.5, 9.1-9.4, 10.1-10.5, 11.1-11.7
- """
- import logging
- from typing import Optional
- from fastapi import APIRouter, Depends, HTTPException, status, Query, Request
- from sqlalchemy.orm import Session
- from app.database import get_db
- from app.schemas.admin_schema import (
- ModelListItem, ModelDetailResponse,
- ModelCreateRequest, ModelUpdateRequest, ModelPriceRequest, ModelStatusRequest
- )
- from app.schemas.model_schema import PaginatedResponse
- from app.services.admin_model_service import AdminModelService
- from app.services.operation_log_service import OperationLogService
- from app.dependencies.admin_auth import get_current_admin
- from app.models.admin import AdminUser
- logger = logging.getLogger(__name__)
- router = APIRouter(prefix="/api/admin/models", tags=["模型管理"])
- def _invalidate_model_caches():
- """清除模型相关的所有 Redis 缓存"""
- try:
- from app.core.redis import redis_manager
- r = redis_manager.get_sync_client()
- except Exception:
- return
- if not r:
- return
- try:
- for pattern in ("model_list:*", "model_featured:*", "model_pricing:*", "model_keywords"):
- cursor = 0
- while True:
- cursor, keys = r.scan(cursor, match=pattern, count=100)
- if keys:
- r.delete(*keys)
- if cursor == 0:
- break
- except Exception as e:
- logger.debug(f"模型缓存清除失败: {e}")
- ERROR_MESSAGES = {
- "MODEL_NOT_FOUND": "模型不存在",
- "MODEL_TITLE_EXISTS": "模型标识已存在",
- "INVALID_PRICE_TIERS": "价格阶梯配置无效",
- "INVALID_FIELD": "无效的字段"
- }
- @router.get("", response_model=PaginatedResponse)
- def list_models(
- keyword: Optional[str] = Query(None, description="搜索关键词"),
- category: Optional[int] = Query(None, description="模型分类"),
- supplier: Optional[str] = Query(None, description="供应商"),
- is_show_enabled: Optional[bool] = Query(None, description="是否展示"),
- is_api_enabled: Optional[bool] = Query(None, description="是否启用API"),
- page: int = Query(1, ge=1, description="页码"),
- size: int = Query(20, ge=1, le=100, description="每页数量"),
- current_admin: AdminUser = Depends(get_current_admin),
- db: Session = Depends(get_db)
- ):
- """获取模型列表"""
- from app.schemas.admin_schema import ModelListParams
-
- params = ModelListParams(
- keyword=keyword,
- category=category,
- supplier=supplier,
- is_show_enabled=is_show_enabled,
- is_api_enabled=is_api_enabled,
- page=page,
- size=size
- )
-
- service = AdminModelService(db)
- models, total = service.list_models(params)
-
- return PaginatedResponse(
- items=[m.model_dump() for m in models],
- total=total,
- page=page,
- page_size=size
- )
- @router.get("/{model_id}", response_model=ModelDetailResponse)
- def get_model_detail(
- model_id: int,
- current_admin: AdminUser = Depends(get_current_admin),
- db: Session = Depends(get_db)
- ):
- """获取模型详情"""
- service = AdminModelService(db)
- model = service.get_model_detail(model_id)
- if not model:
- raise HTTPException(
- status_code=status.HTTP_404_NOT_FOUND,
- detail={"code": "MODEL_NOT_FOUND", "message": "模型不存在"}
- )
- return model
- @router.post("")
- def create_model(
- data: ModelCreateRequest,
- request: Request,
- current_admin: AdminUser = Depends(get_current_admin),
- db: Session = Depends(get_db)
- ):
- """创建模型"""
- service = AdminModelService(db)
-
- try:
- model_id = service.create_model(data)
- _invalidate_model_caches()
- # 记录操作日志
- log_service = OperationLogService(db)
- log_service.create_log(
- admin_id=current_admin.id,
- operation_type="create",
- module="model",
- target_id=str(model_id),
- detail={"title": data.title, "name": data.name},
- ip_address=request.client.host if request.client else None
- )
-
- return {"message": "模型创建成功", "model_id": model_id}
- except ValueError as e:
- error_code = str(e)
- raise HTTPException(
- status_code=status.HTTP_409_CONFLICT if error_code == "MODEL_TITLE_EXISTS" else status.HTTP_400_BAD_REQUEST,
- detail={"code": error_code, "message": ERROR_MESSAGES.get(error_code, "操作失败")}
- )
- @router.put("/{model_id}")
- def update_model(
- model_id: int,
- data: ModelUpdateRequest,
- request: Request,
- current_admin: AdminUser = Depends(get_current_admin),
- db: Session = Depends(get_db)
- ):
- """更新模型信息"""
- service = AdminModelService(db)
-
- try:
- service.update_model(model_id, data)
- _invalidate_model_caches()
- # 记录操作日志
- log_service = OperationLogService(db)
- log_service.create_log(
- admin_id=current_admin.id,
- operation_type="update",
- module="model",
- target_id=str(model_id),
- detail=data.model_dump(exclude_unset=True),
- ip_address=request.client.host if request.client else None
- )
-
- return {"message": "模型更新成功", "model_id": model_id}
- except ValueError as e:
- error_code = str(e)
- status_code = status.HTTP_404_NOT_FOUND if error_code == "MODEL_NOT_FOUND" else status.HTTP_409_CONFLICT
- raise HTTPException(
- status_code=status_code,
- detail={"code": error_code, "message": ERROR_MESSAGES.get(error_code, "操作失败")}
- )
- @router.put("/{model_id}/price")
- def update_model_price(
- model_id: int,
- data: ModelPriceRequest,
- request: Request,
- current_admin: AdminUser = Depends(get_current_admin),
- db: Session = Depends(get_db)
- ):
- """更新模型价格"""
- service = AdminModelService(db)
-
- try:
- service.update_model_price(model_id, data)
- _invalidate_model_caches()
- # 记录操作日志
- log_service = OperationLogService(db)
- log_service.create_log(
- admin_id=current_admin.id,
- operation_type="update",
- module="model",
- target_id=str(model_id),
- detail={"action": "update_price", "pricing_mode": data.pricing_mode},
- ip_address=request.client.host if request.client else None
- )
-
- return {"message": "价格更新成功", "model_id": model_id}
- except ValueError as e:
- error_code = str(e)
- status_code = status.HTTP_404_NOT_FOUND if error_code == "MODEL_NOT_FOUND" else status.HTTP_400_BAD_REQUEST
- raise HTTPException(
- status_code=status_code,
- detail={"code": error_code, "message": ERROR_MESSAGES.get(error_code, "操作失败")}
- )
- @router.put("/{model_id}/status")
- def update_model_status(
- model_id: int,
- data: ModelStatusRequest,
- request: Request,
- current_admin: AdminUser = Depends(get_current_admin),
- db: Session = Depends(get_db)
- ):
- """更新模型状态"""
- service = AdminModelService(db)
-
- try:
- service.update_model_status(model_id, data.field, data.value)
- _invalidate_model_caches()
- # 记录操作日志
- log_service = OperationLogService(db)
- log_service.create_log(
- admin_id=current_admin.id,
- operation_type="update",
- module="model",
- target_id=str(model_id),
- detail={"action": "update_status", "field": data.field, "value": data.value},
- ip_address=request.client.host if request.client else None
- )
-
- return {"message": "状态更新成功", "model_id": model_id, data.field: data.value}
- except ValueError as e:
- error_code = str(e)
- raise HTTPException(
- status_code=status.HTTP_404_NOT_FOUND if error_code == "MODEL_NOT_FOUND" else status.HTTP_400_BAD_REQUEST,
- detail={"code": error_code, "message": ERROR_MESSAGES.get(error_code, "操作失败")}
- )
- @router.put("/batch/api-enabled")
- def batch_update_api_enabled(
- model_ids: list[int] = Query(..., description="模型ID列表"),
- enabled: bool = Query(..., description="是否启用API"),
- request: Request = None,
- current_admin: AdminUser = Depends(get_current_admin),
- db: Session = Depends(get_db)
- ):
- """
- 批量更新模型API权限
-
- 需求 13.2: 支持批量开启/关闭API权限
- 需求 13.3: 批量操作需要确认
- """
- from app.models.model import ModelNew
- updated_count = db.query(ModelNew).filter(
- ModelNew.id.in_(model_ids),
- ModelNew.is_local == False
- ).update(
- {ModelNew.is_api_enabled: enabled},
- synchronize_session=False
- )
- db.commit()
- _invalidate_model_caches()
- # 记录操作日志
- log_service = OperationLogService(db)
- log_service.create_log(
- admin_id=current_admin.id,
- operation_type="batch_update",
- module="model",
- target_id=",".join(map(str, model_ids)),
- detail={"action": "batch_api_enabled", "enabled": enabled, "count": updated_count},
- ip_address=request.client.host if request and request.client else None
- )
-
- return {"message": f"已更新{updated_count}个模型的API权限", "updated_count": updated_count}
|