201 lines
7.4 KiB
Python
201 lines
7.4 KiB
Python
"""
|
|
学生管理模块 - API 层(路由)
|
|
"""
|
|
from typing import List
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Path
|
|
from sqlalchemy.orm import Session
|
|
|
|
from dao import student_dao
|
|
from dao.student_dao import search_student, BusinessException, DuplicateStudentNo, get_student, student_dict, create_student, update_student, delete_student
|
|
from database import get_db
|
|
from schema.student_schema import StudentQuery, StudentCreate, StudentUpdate, AgeQuery, workTimeResponse, \
|
|
failMoreResponse, countAvgOrderResponse, higherScoreResponse, ClassGenderFlatItem
|
|
|
|
router = APIRouter()
|
|
|
|
# 按性别统计人数
|
|
@router.get("/count_gender",summary="按性别统计人数",response_model=List[ClassGenderFlatItem])
|
|
def count_gender(db:Session =Depends(get_db)):
|
|
res=student_dao.get_class_gender(db)
|
|
return res
|
|
|
|
# 统计分数高于分数线的
|
|
@router.get("/count_score_higherScores/{score}",summary="统计高于分数线的人数",response_model=List[higherScoreResponse])
|
|
def higher_score(score: int,db:Session =Depends(get_db)):
|
|
res = student_dao.get_higher_score(db, score)
|
|
return res
|
|
|
|
# 统计每个学生就业时长
|
|
@router.get("/search_workTime",summary="统计每个学生就业时长",response_model=List[workTimeResponse])
|
|
def work_time(db:Session =Depends(get_db)):
|
|
res = student_dao.work_time(db)
|
|
return res
|
|
|
|
# 统计不及格次数大于指定次数
|
|
@router.get("/fail_more",summary="统计不及格次数大于指定次数",response_model=List[failMoreResponse])
|
|
def fail_more_api(fail_times:int,db:Session =Depends(get_db)):
|
|
res = student_dao.get_fail_more_than(db,fail_times)
|
|
return res
|
|
|
|
# 统计平均分,可以切换排序方式
|
|
@router.get("/count_avg",summary="统计平均分,可以切换排序方式",response_model=List[countAvgOrderResponse])
|
|
def count_avg_api(order_type:str,db:Session =Depends(get_db)):
|
|
res = student_dao.count_avg(db,order_type)
|
|
return res
|
|
|
|
# 按年龄区间自定义比较
|
|
@router.post("/order_age",summary="按年龄区间自定义比较")
|
|
def get_students_by_age(query:AgeQuery,db:Session =Depends(get_db)):
|
|
res = student_dao.get_students_by_age(db,query)
|
|
return res
|
|
|
|
# 按就业信息排名查询学生
|
|
@router.get("get_top_salary",summary="按就业信息排名查询学生")
|
|
def get_top_n_salary(rank:int,db:Session =Depends(get_db)):
|
|
res = student_dao.get_top_n_salary(db,rank)
|
|
return res
|
|
|
|
# 统计每个班级的平均就业时长
|
|
@router.get("avg_work_time_by_class",summary="统计每个班级的平均就业时长")
|
|
def avg_work_time_by_class(db:Session =Depends(get_db)):
|
|
res = student_dao.avg_work_time_by_class(db)
|
|
return res
|
|
|
|
# ====================查询学生=====================
|
|
@router.get("/api/get/student",summary="模糊查询学生")
|
|
def list_student_api(
|
|
student_query: StudentQuery = Depends(),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""
|
|
支持按学号、姓名(模糊)、班级筛选,分页返回。
|
|
|
|
请求示例:GET /api/student/?student_name=张&page=1&size=10
|
|
"""
|
|
try:
|
|
return search_student(
|
|
db,
|
|
student_no=student_query.student_no,
|
|
student_name=student_query.student_name,
|
|
class_id=student_query.class_id,
|
|
page=student_query.page,
|
|
size=student_query.size,
|
|
)
|
|
except BusinessException as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
# ====================查询学生详情====================
|
|
@router.get("/get/student/{sid}", summary="查询学生详情")
|
|
def get_student_api(
|
|
sid: int = Path(..., ge=1, description="学生ID"),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
student = get_student(db, sid)
|
|
if student is None:
|
|
raise HTTPException(status_code=404, detail=f"学生 {sid} 不存在")
|
|
return student_dict(student)
|
|
except BusinessException as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
# ==================== 2. 创建学生 ====================
|
|
@router.post("/api/create/student")
|
|
def create_student_api(
|
|
student_create:StudentCreate, # 不加 Depends -> 走 JSON 请求体
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""
|
|
请求体:测试数据
|
|
|
|
{
|
|
"student_no": "S2023011",
|
|
"student_name": "李四",
|
|
"class_id": 1,
|
|
"flag": 1,
|
|
"advisor_id": 1,
|
|
"native_place": "江苏南京",
|
|
"school": "东南大学",
|
|
"major": "软件工程",
|
|
"enrollment_time": "2023-09-01",
|
|
"graduation_time": "2026-06-30",
|
|
"education": "本科",
|
|
"age": 20,
|
|
"gender": "男",
|
|
"state": "在读"
|
|
}
|
|
"""
|
|
try:
|
|
student = create_student(
|
|
db,
|
|
student_no=student_create.student_no,
|
|
student_name=student_create.student_name,
|
|
class_id=student_create.class_id,
|
|
flag=student_create.flag,
|
|
advisor_id=student_create.advisor_id,
|
|
native_place=student_create.native_place,
|
|
school=student_create.school,
|
|
major=student_create.major,
|
|
enrollment_time=student_create.enrollment_time,
|
|
graduation_time=student_create.graduation_time,
|
|
education=student_create.education,
|
|
age=student_create.age,
|
|
gender=student_create.gender,
|
|
state=student_create.state,
|
|
)
|
|
return {"message": "创建成功", "data": student_dict(student)}
|
|
except DuplicateStudentNo as e:
|
|
raise HTTPException(status_code=409, detail=str(e))
|
|
except BusinessException as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
# ==================== 3. 更新学生 ====================
|
|
@router.put("/api/update/student/{sid}", summary="更新学生")
|
|
def update_student_api(
|
|
params: StudentUpdate,
|
|
sid: int = Path(..., ge=1, description="学生ID"),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""
|
|
学号不在更新范围内(业务主键不可改)。
|
|
"""
|
|
try:
|
|
student = update_student(
|
|
db,
|
|
sid=sid,
|
|
student_name=params.student_name,
|
|
class_id=params.class_id,
|
|
flag=params.flag,
|
|
advisor_id=params.advisor_id,
|
|
native_place=params.native_place,
|
|
school=params.school,
|
|
major=params.major,
|
|
enrollment_time=params.enrollment_time,
|
|
graduation_time=params.graduation_time,
|
|
education=params.education,
|
|
age=params.age,
|
|
gender=params.gender,
|
|
state=params.state,
|
|
)
|
|
if student is None:
|
|
raise HTTPException(status_code=404, detail=f"学生 {sid} 不存在")
|
|
return {"message": "更新成功", "data": student_dict(student)}
|
|
except BusinessException as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
|
|
# ==================== 4. 删除学生(逻辑删除) ====================
|
|
@router.delete("/api/delete/student/{sid}", summary="删除学生(逻辑删除)")
|
|
def delete_student_api(
|
|
sid: int = Path(..., ge=1, description="学生ID"),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""逻辑删除:把 flag 置 0,数据行仍然保留。"""
|
|
try:
|
|
student = delete_student(db, sid)
|
|
if student is None:
|
|
raise HTTPException(status_code=404, detail=f"学生 {sid} 不存在或已删除")
|
|
return {"message": f"学生 {student.student_name} 删除成功"}
|
|
except BusinessException as e:
|
|
raise HTTPException(status_code=500, detail=str(e)) |