""" 系统API - 供外部服务回调使用 """ import logging from typing import List, Dict, Any, Optional from fastapi import APIRouter, Depends, HTTPException, status, Header from sqlalchemy.ext.asyncio import AsyncSession from pydantic import BaseModel, Field from app.core.deps import get_db from app.schemas.base import ResponseModel from app.schemas.course import KnowledgePointCreate from app.services.course_service import knowledge_point_service, course_service logger = logging.getLogger(__name__) router = APIRouter(prefix="/system") class KnowledgePointData(BaseModel): """知识点数据模型""" name: str = Field(..., description="知识点名称") description: str = Field(default="", description="知识点描述") type: str = Field(default="理论知识", description="知识点类型") source: int = Field(default=1, description="来源:0=手动,1=AI分析") topic_relation: Optional[str] = Field(None, description="与主题的关系描述") class KnowledgeCallbackRequest(BaseModel): """知识点回调请求模型(已弃用,保留向后兼容)""" course_id: int = Field(..., description="课程ID") material_id: int = Field(..., description="资料ID") knowledge_points: List[KnowledgePointData] = Field(..., description="知识点列表") @router.post("/knowledge", response_model=ResponseModel[Dict[str, Any]]) async def create_knowledge_points_callback( request: KnowledgeCallbackRequest, authorization: str = Header(None), db: AsyncSession = Depends(get_db), ): """ 创建知识点回调接口(已弃用) 注意:此接口已弃用,知识点分析现使用 Python 原生实现。 保留此接口仅为向后兼容。 """ try: # API密钥验证(已弃用的接口,保留向后兼容) expected_token = "Bearer callback-token-2025" if authorization != expected_token: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="无效的授权令牌" ) # 验证课程是否存在 course = await course_service.get_by_id(db, request.course_id) if not course: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"课程 {request.course_id} 不存在" ) # 验证资料是否存在 materials = await course_service.get_course_materials(db, course_id=request.course_id) material = next((m for m in materials if m.id == request.material_id), None) if not material: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"资料 {request.material_id} 不存在" ) # 创建知识点 created_points = [] for kp_data in request.knowledge_points: try: knowledge_point_create = KnowledgePointCreate( name=kp_data.name, description=kp_data.description, type=kp_data.type, source=kp_data.source, # AI分析来源=1 topic_relation=kp_data.topic_relation, material_id=request.material_id # 关联资料ID ) # 使用系统用户ID (假设为1,或者可以配置) system_user_id = 1 knowledge_point = await knowledge_point_service.create_knowledge_point( db=db, course_id=request.course_id, point_in=knowledge_point_create, created_by=system_user_id ) created_points.append({ "id": knowledge_point.id, "name": knowledge_point.name, "description": knowledge_point.description, "type": knowledge_point.type, "source": knowledge_point.source, "material_id": knowledge_point.material_id }) except Exception as e: logger.error( f"创建知识点失败 - name: {kp_data.name}, error: {str(e)}" ) # 继续处理其他知识点,不因为单个失败而中断 continue logger.info( f"知识点回调成功 - course_id: {request.course_id}, material_id: {request.material_id}, created_points: {len(created_points)}" ) return ResponseModel( data={ "course_id": request.course_id, "material_id": request.material_id, "knowledge_points_count": len(created_points), "knowledge_points": created_points }, message=f"成功创建 {len(created_points)} 个知识点" ) except HTTPException: raise except Exception as e: logger.error( f"知识点回调处理失败 - course_id: {request.course_id}, material_id: {request.material_id}, error: {str(e)}", exc_info=True ) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="知识点创建失败" )