# api/stats # 本文件定义统计分析相关的所有 API 路由(Controller 层) from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.orm import Session from typing import List, Optional from database import get_db from dao.statistics_dao import StatisticsDao from scheme.statistics_scheme import ClassGenderDistributionItem, \ TopSalaryStudentItem, StudentEmpDurationItem, ClassAvgEmpDurationItem, StudentAgeDetailItem router = APIRouter() #### 2.6.1 基本信息动态统计 # - **动态年龄范围查询**:支持用户输入年龄阈值及比较条件(如大于、小于、等于、区间等),动态查询符合条件的学员信息。 @router.get("/students/age_filter", response_model=List[StudentAgeDetailItem], summary="动态年龄范围查询", description="支持用户输入年龄阈值及比较条件(如大于、小于、等于、区间等),动态查询符合条件的学员信息。") def get_students_by_age_condition(db: Session = Depends(get_db), operator: str = Query(..., description="""比较条件: gt/ge/lt/le/eq/between
或者:>/>=/"""), age: Optional[int] = Query(None, ge=0, description="单值比较时的年龄(gt/lt/eq等用)"), min_age: Optional[int] = Query(None, ge=0, description="区间比较时的最小年龄(between用)"), max_age: Optional[int] = Query(None, ge=0, description="区间比较时的最大年龄(between用)") ): if operator == "between": if min_age is None or max_age is None: raise HTTPException(status_code=400, detail="between功能: 最大/最小值 都得输入") if min_age > max_age: raise HTTPException(status_code=400, detail="between功能: 最小值 要 小于 最大值!") else: if age is None: raise HTTPException(status_code=400, detail="非between功能: age 不能不写!") data = StatisticsDao.find_students_by_age_condition(db = db, operator = operator, age = age, min_age = min_age, max_age = max_age) return data # **多维度班级统计**:统计每个班级的总人数,以及按性别(男、女)细分的人数分布。 @router.get("/class/gender_distribution", response_model=List[ClassGenderDistributionItem], summary="班级人数及性别统计", description="统计每个班级的总人数,以及按性别(男、女)细分的人数分布。") def get_class_stats(db: Session = Depends(get_db)): data = StatisticsDao.get_class_gender_distribution(db) return data #### 2.6.2 成绩综合统计: all @router.get("/class_score", summary="班级成绩综合统计", description= """ 1、查询每次考试成绩都在输入分数线(如80分)以上的学生的编号、姓名和成绩 -- 参数: 分数
2、查询有输入指定次数(如两次)以上不及格的学生的姓名、班级和不及格成绩明细 -- 参数: 不及格次数
3、统计每次考试每个班级的平均分,并支持按分数从高到低或从低到高动态排序 -- 参数: 1:低到高, 2:高到低
""") def get_students_all_exams_above_score( db: Session = Depends(get_db), choose: int = Query(..., ge=1, le=3, description="功能选择(1-3): 参考提示"), param: int | float = Query(..., description="输入的具体参数,参考提示") ): if choose == 1: # 查询每次考试成绩都在输入分数线(如80分)以上的学生的编号、姓名和成绩 -- 参数: 分数 if param > 100 or param < 0: raise HTTPException(status_code=400, detail="成绩需要在[0-100]区间") data = StatisticsDao.get_stu_info_all_exams_above_score(db, param) elif choose == 2: # 2、查询有输入指定次数(如两次)以上不及格的学生的姓名、班级和不及格成绩明细 -- 参数: 不及格次数 data = StatisticsDao.find_students_fail_count(db, param) elif choose == 3: # 统计每次考试每个班级的平均分,并支持按分数从高到低或从低到高动态排序 -- 参数: 1:低到高, 2:高到低 if param not in [1, 2]: raise HTTPException(status_code=400, detail="排序只有两种: 1:低到高, 2:高到低") data = StatisticsDao.find_class_exam_averages(db, param) return data # 2.6.2 单个接口详细版本 """ #### 2.6.2 成绩综合统计 # 1- 查询每次考试成绩都在输入分数线(如80分)以上的学生的编号、姓名和成绩。 @router.get("/api/stats/students/all_exams_above_score", response_model = List[StuInfoAllExamAboveScore], summary="查询成绩在xx分以上的学生信息", description= "查询成绩在xx分以上的学生信息") def get_students_all_exams_above_score( db: Session = Depends(get_db), score: float = Query(..., ge=0.0, le=100.0, description="输入最低成绩(包含)"), ): data = StatisticsDao.get_stu_info_all_exams_above_score(db, score) return data # 查询有输入指定次数(如两次)以上不及格的学生的姓名、班级和不及格成绩明细。 @router.get("/api/stats/failing_records", response_model=List[FailingStudentItem], summary="查询有输入指定次数不及格学生", description="查询有输入指定次数(如两次)以上不及格的学生的姓名、班级和不及格成绩明细。") def get_frequent_failing_students( db: Session = Depends(get_db), fail_cnt: int = Query(..., ge = 0, le = 100, description="不及格次数") ): data = StatisticsDao.find_students_fail_count(db, fail_cnt) return data # 统计每次考试每个班级的平均分,并支持按分数从高到低或从低到高动态排序。 @router.get("/api/stats/class/exam_avg_scores", response_model=List[ClassExamAvgScoreItem], summary="统计每次考试每个班级的平均分", description="统计每次考试每个班级的平均分,并支持按分数从高到低或从低到高动态排序") def get_class_exams_avg_scores( db: Session = Depends(get_db), order_choose: int = Query(..., ge = 1, le = 2, description="1: 升序, 2: 降序") ): data = StatisticsDao.find_class_exam_averages(db, order_choose) return data """ #### 2.6.3 就业数据统计: all @router.get("/employment_time", summary="就业数据统计", description= """ 1、统计就业薪资排名 Top N(动态输入 N)的学生的姓名、班级、就业时间和就业公司。 -- 参数: top_N
2、统计每个学生的就业时长(计算公式:offer下发时间 - 就业开放时间) -- 参数: 无
3、统计每个班级的平均就业时长(仅统计进入就业阶段,即有就业开放时间的学生) -- 参数: 无
""") def get_students_all_exams_above_score( db: Session = Depends(get_db), choose: int = Query(..., ge=1, le=3, description="功能选择(1-3): 参考提示"), player_num: int = Query(10, ge=0, le=100, description="功能1 输入的具体参数,参考提示(其他功能无效)") ): if choose == 1: # 1、统计就业薪资排名 Top N(动态输入 N)的学生的姓名、班级、就业时间和就业公司。 -- 参数: top_N data = StatisticsDao.find_top_salary_students(db, player_num) elif choose == 2: # 2、统计每个学生的就业时长(计算公式:offer下发时间 - 就业开放时间) -- 参数: 无 data = StatisticsDao.find_students_employment_duration(db) elif choose == 3: # 3、统计每个班级的平均就业时长(仅统计进入就业阶段,即有就业开放时间的学生) -- 参数: 无
data = StatisticsDao.find_class_avg_employment_duration(db) return data # 2.6.3 就业数据统计 单独版 """ #### 2.6.3 就业数据统计 # - 统计就业薪资排名 Top N(动态输入 N)的学生的姓名、班级、就业时间和就业公司。 @router.get("/employment/top_salaries", response_model=List[TopSalaryStudentItem], summary="就业薪资top_N", description="统计就业薪资排名 Top N(动态输入 N)的学生的姓名、班级、就业时间和就业公司") def get_top_salary_students( db: Session = Depends(get_db), top_n: int = Query(default=5, ge=1, description="获取前N名")): data = StatisticsDao.find_top_salary_students(db, top_n) return data # - 统计每个学生的就业时长(计算公式:offer下发时间 - 就业开放时间)。 @router.get("/employment/job_seeking_duration", response_model=List[StudentEmpDurationItem], summary="统计就业时长", description="统计每个学生的就业时长(计算公式:offer下发时间 - 就业开放时间)") def get_students_job_seeking_duration(db: Session = Depends(get_db)): data = StatisticsDao.find_students_employment_duration(db) return data # - 统计每个班级的平均就业时长(仅统计进入就业阶段,即有就业开放时间的学生) @router.get("/class/avg_employment_duration", response_model=List[ClassAvgEmpDurationItem], summary="班级平均就业时长", description="统计每个班级的平均就业时长(仅统计进入就业阶段,即有就业开放时间的学生)") def get_class_avg_employment_duration(db: Session = Depends(get_db)): data = StatisticsDao.find_class_avg_employment_duration(db) return data """