feat: 初始化考培练系统项目
- 从服务器拉取完整代码 - 按框架规范整理项目结构 - 配置 Drone CI 测试环境部署 - 包含后端(FastAPI)、前端(Vue3)、管理端 技术栈: Vue3 + TypeScript + FastAPI + MySQL
This commit is contained in:
139
backend/app/api/v1/system.py
Normal file
139
backend/app/api/v1/system.py
Normal file
@@ -0,0 +1,139 @@
|
||||
"""
|
||||
系统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="知识点创建失败"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user