134 lines
7.2 KiB
Python
134 lines
7.2 KiB
Python
# api/stats
|
|
# 本文件定义统计分析相关的所有 API 路由(Controller 层)
|
|
from itertools import count
|
|
from pydoc import describe
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
from sqlalchemy.orm import Session
|
|
from typing import List, Optional
|
|
from sqlalchemy import func
|
|
from starlette import status
|
|
|
|
from database import get_db
|
|
from dao.statistics_dao import StatisticsDao
|
|
from model.stu_model import StuInfo
|
|
from scheme.statistics_scheme import StatsResponse, StuInfoAllExamAboveScore, FailingStudentItem, ClassExamAvgScoreItem, \
|
|
TopSalaryStudentItem, StudentEmpDurationItem, ClassAvgEmpDurationItem, StudentAgeDetailItem
|
|
|
|
router = APIRouter()
|
|
|
|
#### 2.6.1 基本信息动态统计
|
|
# - **动态年龄范围查询**:支持用户输入年龄阈值及比较条件(如大于、小于、等于、区间等),动态查询符合条件的学员信息。
|
|
# - **多维度班级统计**:统计每个班级的总人数,以及按性别(男、女)细分的人数分布。
|
|
@router.get("/api/stats/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/gte/lt/lte/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="最大/最小值 都得输入")
|
|
if min_age > max_age:
|
|
raise HTTPException(status_code=400, detail="最小值 要 小于 最大值!")
|
|
else:
|
|
if age is None:
|
|
raise HTTPException(status_code=400, detail="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/stats/gender",
|
|
response_model=List[StatsResponse],
|
|
summary="班级性别统计",
|
|
description="统计每个班级的总人数,以及按性别(男、女)细分的人数分布。")
|
|
def get_class_stats(db: Session = Depends(get_db)):
|
|
data = StatisticsDao.get_cls_stats(db)
|
|
return data
|
|
|
|
#### 2.6.2 成绩综合统计
|
|
# 1- 查询每次考试成绩都在输入分数线(如80分)以上的学生的编号、姓名和成绩。
|
|
# 2- 查询有输入指定次数(如两次)以上不及格的学生的姓名、班级和不及格成绩明细。
|
|
# 3- 统计每次考试每个班级的平均分,并支持按分数从高到低或从低到高动态排序。
|
|
@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 就业数据统计
|
|
|
|
# - 统计就业薪资排名 Top N(动态输入 N)的学生的姓名、班级、就业时间和就业公司。
|
|
# - 统计每个学生的就业时长(计算公式:offer下发时间 - 就业开放时间)。
|
|
# - 统计每个班级的平均就业时长(仅统计进入就业阶段,即有就业开放时间的学生)
|
|
@router.get("/api/stats/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("/api/stats/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("/api/stats/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
|