""" 统计分析API路由 """ from typing import Optional from fastapi import APIRouter, Depends, Query from sqlalchemy.ext.asyncio import AsyncSession from app.core.deps import get_db, get_current_user from app.models.user import User from app.schemas.base import ResponseModel from app.services.statistics_service import StatisticsService from app.core.logger import get_logger logger = get_logger(__name__) router = APIRouter(prefix="/statistics", tags=["statistics"]) @router.get("/key-metrics", response_model=ResponseModel) async def get_key_metrics( course_id: Optional[int] = Query(None, description="课程ID,不传则统计全部课程"), period: str = Query("month", description="时间范围: week/month/quarter/halfYear/year"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db) ): """ 获取关键指标 返回: - learningEfficiency: 学习效率 - knowledgeCoverage: 知识覆盖率 - avgTimePerQuestion: 平均用时 - progressSpeed: 进步速度 """ try: metrics = await StatisticsService.get_key_metrics( db=db, user_id=current_user.id, course_id=course_id, period=period ) return ResponseModel( code=200, message="获取关键指标成功", data=metrics ) except Exception as e: logger.error(f"获取关键指标失败: {e}", exc_info=True) return ResponseModel( code=500, message=f"获取关键指标失败: {str(e)}" ) @router.get("/score-distribution", response_model=ResponseModel) async def get_score_distribution( course_id: Optional[int] = Query(None, description="课程ID,不传则统计全部课程"), period: str = Query("month", description="时间范围: week/month/quarter/halfYear/year"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db) ): """ 获取成绩分布统计 返回各分数段的考试数量: - excellent: 优秀(90-100) - good: 良好(80-89) - medium: 中等(70-79) - pass: 及格(60-69) - fail: 不及格(<60) """ try: distribution = await StatisticsService.get_score_distribution( db=db, user_id=current_user.id, course_id=course_id, period=period ) return ResponseModel( code=200, message="获取成绩分布成功", data=distribution ) except Exception as e: logger.error(f"获取成绩分布失败: {e}", exc_info=True) return ResponseModel( code=500, message=f"获取成绩分布失败: {str(e)}" ) @router.get("/difficulty-analysis", response_model=ResponseModel) async def get_difficulty_analysis( course_id: Optional[int] = Query(None, description="课程ID,不传则统计全部课程"), period: str = Query("month", description="时间范围: week/month/quarter/halfYear/year"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db) ): """ 获取题目难度分析 返回各难度题目的正确率: - 简单题 - 中等题 - 困难题 - 综合题 - 应用题 """ try: analysis = await StatisticsService.get_difficulty_analysis( db=db, user_id=current_user.id, course_id=course_id, period=period ) return ResponseModel( code=200, message="获取难度分析成功", data=analysis ) except Exception as e: logger.error(f"获取难度分析失败: {e}", exc_info=True) return ResponseModel( code=500, message=f"获取难度分析失败: {str(e)}" ) @router.get("/knowledge-mastery", response_model=ResponseModel) async def get_knowledge_mastery( course_id: Optional[int] = Query(None, description="课程ID,不传则统计全部课程"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db) ): """ 获取知识点掌握度 返回知识点列表及其掌握度: - name: 知识点名称 - mastery: 掌握度(0-100) """ try: mastery = await StatisticsService.get_knowledge_mastery( db=db, user_id=current_user.id, course_id=course_id ) return ResponseModel( code=200, message="获取知识点掌握度成功", data=mastery ) except Exception as e: logger.error(f"获取知识点掌握度失败: {e}", exc_info=True) return ResponseModel( code=500, message=f"获取知识点掌握度失败: {str(e)}" ) @router.get("/study-time", response_model=ResponseModel) async def get_study_time_stats( course_id: Optional[int] = Query(None, description="课程ID,不传则统计全部课程"), period: str = Query("month", description="时间范围: week/month/quarter/halfYear/year"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db) ): """ 获取学习时长统计 返回学习时长和练习时长的日期分布: - labels: 日期标签列表 - studyTime: 学习时长列表(小时) - practiceTime: 练习时长列表(小时) """ try: time_stats = await StatisticsService.get_study_time_stats( db=db, user_id=current_user.id, course_id=course_id, period=period ) return ResponseModel( code=200, message="获取学习时长统计成功", data=time_stats ) except Exception as e: logger.error(f"获取学习时长统计失败: {e}", exc_info=True) return ResponseModel( code=500, message=f"获取学习时长统计失败: {str(e)}" ) @router.get("/detail", response_model=ResponseModel) async def get_detail_data( course_id: Optional[int] = Query(None, description="课程ID,不传则统计全部课程"), period: str = Query("month", description="时间范围: week/month/quarter/halfYear/year"), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db) ): """ 获取详细统计数据(按日期) 返回每日详细统计数据: - date: 日期 - examCount: 考试次数 - avgScore: 平均分 - studyTime: 学习时长(小时) - questionCount: 练习题数 - accuracy: 正确率 - improvement: 进步指数 """ try: detail = await StatisticsService.get_detail_data( db=db, user_id=current_user.id, course_id=course_id, period=period ) return ResponseModel( code=200, message="获取详细数据成功", data=detail ) except Exception as e: logger.error(f"获取详细数据失败: {e}", exc_info=True) return ResponseModel( code=500, message=f"获取详细数据失败: {str(e)}" )