第四版_完整

This commit is contained in:
jianqi
2026-09-14 15:23:26 +08:00
parent 06c329fdd1
commit c2909191d2
14 changed files with 84 additions and 64 deletions
-1
View File
@@ -8,7 +8,6 @@ from typing import List
from dao.cls_mgmt_dao import ClsMgmtDAO
from database import get_db
from scheme.cls_mgmt_scheme import ClsMgmtResponse, ClsMgmtCreate
from scheme.users import UserCreate, UserUpdate, UserResponse
router = APIRouter()
@router.get("/", response_model=List[ClsMgmtResponse])
+2 -4
View File
@@ -1,16 +1,14 @@
# api/employ_api.py
# 本文件定义 学生就业信息 的所有 API 路由(Controller 层)
# author:王博
from typing import List
from fastapi import APIRouter,HTTPException
from fastapi.params import Depends
from sqlalchemy.orm import Session
from database import get_db
from scheme.employ_scheme import EmployStatusCreate as EModel, EmployStatusResponse, EmployStatusQuery as QModel, \
EmployQueryResponse, EmployStatusDelete as DModel
from dao.employ_dao import StudentEmployManageDAO as Emp
# 创建路由器,前缀将在 main.py 中统一添加
router = APIRouter()
@@ -90,7 +88,7 @@ async def batch_delete_emp_reco(emp_sta:List[DModel],db:Session = Depends(get_db
raise HTTPException(status_code=404, detail="该学生就业记录不存在")
# ---------- 批量修改学生就业信息 ----------
@router.delete('/set_emp_reco/batch/',status_code=204, # response_model=EmployStatusResponse,
@router.put('/set_emp_reco/batch/',status_code=204, # response_model=EmployStatusResponse,
responses={404: {"description": "该学生就业记录不存在"}})
async def batch_set_emp_reco(emp_sta:List[EModel],db:Session = Depends(get_db)):
"""
+37 -20
View File
@@ -1,25 +1,18 @@
# 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, \
from scheme.statistics_scheme import ClassGenderDistributionItem, StuInfoAllExamAboveScore, FailingStudentItem, ClassExamAvgScoreItem, \
TopSalaryStudentItem, StudentEmpDurationItem, ClassAvgEmpDurationItem, StudentAgeDetailItem
router = APIRouter()
#### 2.6.1 基本信息动态统计
# - **动态年龄范围查询**:支持用户输入年龄阈值及比较条件(如大于、小于、等于、区间等),动态查询符合条件的学员信息。
# - **多维度班级统计**:统计每个班级的总人数,以及按性别(男、女)细分的人数分布。
@router.get("/api/stats/students/age_filter",
response_model=List[StudentAgeDetailItem],
summary="动态年龄范围查询",
@@ -47,20 +40,49 @@ def get_students_by_age_condition(db: Session = Depends(get_db),
max_age = max_age)
return data
# **多维度班级统计**:统计每个班级的总人数,以及按性别(男、女)细分的人数分布。
@router.get("/class/stats/gender",
response_model=List[StatsResponse],
@router.get("/api/stats/class/gender_distribution",
response_model=List[ClassGenderDistributionItem],
summary="班级性别统计",
description="统计每个班级的总人数,以及按性别(男、女)细分的人数分布。")
def get_class_stats(db: Session = Depends(get_db)):
data = StatisticsDao.get_cls_stats(db)
data = StatisticsDao.get_class_gender_distribution(db)
return data
#### 2.6.2 成绩综合统计: all
@router.get("/class_score",
summary="班级成绩综合统计",
description= """
1、查询每次考试成绩都在输入分数线(如80分)以上的学生的编号、姓名和成绩 -- 参数: 分数<br>
2、查询有输入指定次数(如两次)以上不及格的学生的姓名、班级和不及格成绩明细 -- 参数: 不及格次数<br>
3、统计每次考试每个班级的平均分,并支持按分数从高到低或从低到高动态排序 -- 参数: 1:低到高, 2:高到低<br>
""")
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 | float = Query(..., ge=0, le=100, description="输入的具体参数,参考提示")
):
if choose == 1:
# 查询每次考试成绩都在输入分数线(如80分)以上的学生的编号、姓名和成绩 -- 参数: 分数
if player_num > 100 or player_num < 0:
raise HTTPException(status_code=400, detail="成绩需要在[0-100]区间")
data = StatisticsDao.get_stu_info_all_exams_above_score(db, player_num)
elif choose == 2:
# 2、查询有输入指定次数(如两次)以上不及格的学生的姓名、班级和不及格成绩明细 -- 参数: 不及格次数
data = StatisticsDao.find_students_fail_count(db, player_num)
elif choose == 3:
# 统计每次考试每个班级的平均分,并支持按分数从高到低或从低到高动态排序 -- 参数: 1:低到高, 2:高到低
data = StatisticsDao.find_class_exam_averages(db, player_num)
return data
# 2.6.2 单个接口详细版本
"""
#### 2.6.2 成绩综合统计
# 1- 查询每次考试成绩都在输入分数线(如80分)以上的学生的编号、姓名和成绩。
# 2- 查询有输入指定次数(如两次)以上不及格的学生的姓名、班级和不及格成绩明细。
# 3- 统计每次考试每个班级的平均分,并支持按分数从高到低或从低到高动态排序。
@router.get("/api/stats/students/all_exams_above_score",
response_model = List[StuInfoAllExamAboveScore],
summary="查询成绩在xx分以上的学生信息",
@@ -95,13 +117,10 @@ def get_class_exams_avg_scores(
):
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",
@@ -112,7 +131,6 @@ def get_top_salary_students(
data = StatisticsDao.find_top_salary_students(db, top_n)
return data
# - 统计每个学生的就业时长(计算公式:offer下发时间 - 就业开放时间)。
@router.get("/api/stats/employment/job_seeking_duration",
response_model=List[StudentEmpDurationItem],
@@ -122,7 +140,6 @@ 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],
+1 -1
View File
@@ -95,7 +95,7 @@ async def create_student(
new_student = StudentDao.create(db, student_dict)
except Exception:
db.rollback()
raise HTTPException(status_code=400, detail="网络卡顿或有其他人同步上传,请重试")
raise HTTPException(status_code=400, detail="数据异常,请重试")
return new_student
#============= 修改 ============
@router.put("/{stu_id}", response_model=StudentResponse,summary="通过ID查找修改学生信息")
+1 -1
View File
@@ -21,7 +21,7 @@ async def create_score(
db: Session = Depends(get_db)
):
score_level = "优秀" if exam_score >= 90 else "普通" if exam_score >= 60 else "差劲"
warnings="该学生成绩被标记为差劲"if score_level=="差劲" else None
warnings="该学生成绩被标记为差劲, 请及时关注"if score_level=="差劲" else None
existing = StuScoreDAO.get_by_id_attempt_all(db, stu_id, exam_attempt)
if existing:
raise HTTPException(status_code=400, detail="本次考核成绩已存在,请重新确认")
+18 -12
View File
@@ -5,12 +5,13 @@ from typing import List
from database import get_db
from dao.teacher_dao import TeacherDao
from scheme.cls_mgmt_scheme import ClsMgmtResponse
from scheme.teacher_scheme import TeacherAdd,TeacherUpdate, TeacherResponse
router = APIRouter()
# 查询所有教师(支持分页)
@router.get("/get_all_teachers", response_model=List[TeacherResponse])
@router.get("/get_all_teachers", response_model=List[TeacherResponse],summary="查询所有教师")
async def get_all_teachers(
skip: int = Query(0, ge=0, description="跳过的记录数"),
limit: int = Query(100, ge=1, le=200, description="返回的最大记录数"),
@@ -21,7 +22,7 @@ async def get_all_teachers(
return teachers # FastAPI 自动根据 response_model 转换为 JSON
# 根据 ID 和 name 查询单个教师
@router.get("/get_teacher/{teacher_id_name}", response_model=TeacherResponse)
@router.get("/get_teacher/{teacher_id_name}", response_model=TeacherResponse,summary="查询单个教师")
async def get_teacher(
teacher_id_name: str = Path(..., description="要查询教师的id或姓名"),
db: Session = Depends(get_db)
@@ -32,18 +33,23 @@ async def get_teacher(
return teacher
# 根据 ID 查询教师带教的班级的信息
@router.get("/get_class_info/{teacher_id}")
@router.get("/get_class_info/{teacher_id}",response_model=ClsMgmtResponse,summary="教师ID查询带教班级信息")
async def get_class_info(
teacher_id: str = Path(..., description="要查询教师的id"),
db: Session = Depends(get_db)
):
teacher = TeacherDao.get_clss_info(db, teacher_id)
if not teacher:
raise HTTPException(status_code=404, detail="用户不存在")
return teacher
# 检查传入的id教师是否存在
existing = TeacherDao.get_by_id(db, teacher_id)
if not existing:
raise HTTPException(status_code=404, detail="该教师id不存在")
# 查询教师是否有带教班级
class_info = TeacherDao.get_clss_info(db, teacher_id)
if not class_info:
raise HTTPException(status_code=404, detail="无带教班级")
return class_info
# 添加教师信息
@router.post("/add_teacher", response_model=TeacherResponse)
@router.post("/add_teacher", response_model=TeacherResponse,summary="增加教师信息")
async def add_teacher(
teacher_data: TeacherAdd,
db: Session = Depends(get_db)
@@ -53,7 +59,7 @@ async def add_teacher(
return new_teacher
# 根据教师id更新教师信息
@router.put("/update_teacher/{teacher_id}", response_model=TeacherResponse)
@router.put("/update_teacher/{teacher_id}", response_model=TeacherResponse,summary="更新教师信息")
async def update_teacher(
teacher_id: str,
teacher_data: TeacherUpdate,
@@ -62,14 +68,14 @@ async def update_teacher(
# 检查传入的id教师是否存在
existing = TeacherDao.get_by_id(db, teacher_id)
if not existing:
raise HTTPException(status_code=404, detail="用户不存在")
raise HTTPException(status_code=404, detail="该教师不存在")
# 执行更新
updated = TeacherDao.update(db, teacher_id, teacher_data)
return updated
# 删除教师
@router.delete("/delete_teacher/{teacher_id}")
@router.delete("/delete_teacher/{teacher_id}",summary="删除教师")
async def delete_teacher(
teacher_id: str,
db: Session = Depends(get_db)
@@ -77,6 +83,6 @@ async def delete_teacher(
success = TeacherDao.delete(db, teacher_id)
if not success:
raise HTTPException(status_code=404, detail="用户不存在")
raise HTTPException(status_code=404, detail="教师不存在")
return "该教师已删除"