api
This commit is contained in:
BIN
Binary file not shown.
+110
@@ -0,0 +1,110 @@
|
||||
from typing import List
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Path, Query
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from dao.wl_statistics_dao import StatisticDao
|
||||
from database import get_db
|
||||
from dao import wl_statistics_dao
|
||||
from scheme.wl_statistics_scheme import (AgeCompareOp, ClassAvgEmpTimeOut,
|
||||
ClassAvgScoreOut, ClassGenderStatOut,
|
||||
EmpTopOut, FailCountModel,
|
||||
ScoreOutLine, SortOrder, EmpTimeOut)
|
||||
from scheme.wl_student_scheme import StudentOut
|
||||
|
||||
router = APIRouter(prefix='/statistics',tags=["统计分析模块"])
|
||||
|
||||
|
||||
# ---- 2.6.1.1 动态年龄范围查询 ----
|
||||
@router.get(
|
||||
"/students/age",
|
||||
response_model=list[StudentOut],
|
||||
summary="动态年龄范围查询",
|
||||
responses={400: {"description": "查询参数不合法,例如区间查询缺少上界 value2"}},
|
||||
)
|
||||
def query_age_range(
|
||||
op: AgeCompareOp = Query(AgeCompareOp.gt, description="比较条件:gt/ge/lt/le/eq/between"),
|
||||
value: int = Query(..., description="年龄阈值"),
|
||||
value2: int | None = Query(None, description="年龄上界,仅 op=between 时必填"),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
try:
|
||||
return StatisticDao.search_students_by_age(db, op, value, value2)
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
|
||||
# ---- 2.6.1.2 多维度班级统计 ----
|
||||
@router.get(
|
||||
'/classes/count',
|
||||
summary="多维度班级统计",
|
||||
response_model=list[ClassGenderStatOut]
|
||||
)
|
||||
def query_classes_count(db: Session = Depends(get_db)):
|
||||
return StatisticDao.statistic_classes_count(db)
|
||||
|
||||
# 查询每次考试成绩都在输入分数线(如80分)以上的学生的编号、姓名和成绩
|
||||
@router.get(
|
||||
'/scores/out_score_line/{score_line}',
|
||||
summary='统计每次超分数线的学生',
|
||||
response_model=list[ScoreOutLine]
|
||||
)
|
||||
def query_out_score_line(score_line:float,db:Session=Depends(get_db)):
|
||||
return StatisticDao.query_score_by_line(db, score_line)
|
||||
|
||||
# 查询有输入指定次数(如两次)以上不及格的学生的姓名、班级和不及格成绩明细
|
||||
@router.get(
|
||||
'/scores/fail_score/{fail_count}',
|
||||
summary='统计不及格次数超过指定次数的学生信息',
|
||||
response_model=list[FailCountModel]
|
||||
)
|
||||
def query_info_by_fail_count(fail_count:int,db: Session = Depends(get_db)):
|
||||
return StatisticDao.query_by_fail_count(db,fail_count)
|
||||
|
||||
# 统计每次考试每个班级的平均分,并支持按分数从高到低或从低到高动态排序
|
||||
@router.get(
|
||||
'/scores/get_class_avg_score',
|
||||
summary='统计每次考试每个班级的平均分,并支持按分数从高到低或从低到高动态排序',
|
||||
response_model=list[ClassAvgScoreOut]
|
||||
)
|
||||
def get_class_avg_score(
|
||||
sort_order: SortOrder | None = Query(
|
||||
None, description="排序方向:asc 从低到高,desc 从高到低;不传则按班级+考试序次"),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
return StatisticDao.get_class_avg_score(db, sort_order)
|
||||
|
||||
# 统计就业薪资排名Top N(动态输入N)的学生的姓名、班级、就业时间和就业公司
|
||||
@router.get(
|
||||
'/emp/top_rank/{rank}',
|
||||
summary='统计就业薪资排名Top N',
|
||||
response_model=list[EmpTopOut]
|
||||
)
|
||||
def get_top_rank(
|
||||
rank: int = Path(..., gt=0, description="取薪资排名前 N 名"),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
return StatisticDao.get_info_by_rank(db, rank)
|
||||
|
||||
# 统计每个学生的就业时长(计算公式:offer下发时间-就业开放时间)
|
||||
@router.get(
|
||||
'/emp/emp_time',
|
||||
summary='统计每个学生的就业时长',
|
||||
response_model=list[EmpTimeOut]
|
||||
)
|
||||
def get_emp_time(db: Session = Depends(get_db)):
|
||||
return StatisticDao.get_emp_time(db)
|
||||
|
||||
# 统计每个班级的平均就业时长(仅统计已进入就业阶段且已拿到 offer 的学生)
|
||||
@router.get(
|
||||
'/emp/class_avg_emp_time',
|
||||
summary='统计每个班级的平均就业时长',
|
||||
response_model=list[ClassAvgEmpTimeOut]
|
||||
)
|
||||
def get_class_avg_emp_time(
|
||||
sort_order: SortOrder | None = Query(
|
||||
None, description="排序方向:asc 从低到高,desc 从高到低;不传则按班级编号"),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
return StatisticDao.get_class_avg_emp_time(db, sort_order)
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from dao import wl_advisor_dao
|
||||
from database import get_db
|
||||
from scheme.wl_advisor_scheme import AdvisorCreate, AdvisorOut, AdvisorUpdate
|
||||
|
||||
router = APIRouter(prefix="/advisor", tags=["顾问管理"])
|
||||
|
||||
|
||||
# 查询顾问列表(支持姓名/手机号/区域/性别模糊筛选 + 分页)
|
||||
# 注意:本路由必须写在 /{adv_id} 前面,否则 "/advisor/" 会被当成 adv_id 去解析
|
||||
@router.get("/", response_model=list[AdvisorOut])
|
||||
def query_list(
|
||||
adv_name: str = Query(None),
|
||||
adv_phone: str = Query(None),
|
||||
adv_region: str = Query(None),
|
||||
adv_gender: str = Query(None),
|
||||
skip: int = 0,
|
||||
limit: int = 100,
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
return wl_advisor_dao.list_advisors(
|
||||
db, adv_name, adv_phone, adv_region, adv_gender, skip, limit
|
||||
)
|
||||
|
||||
|
||||
# 新增顾问
|
||||
@router.post("/", response_model=AdvisorOut, status_code=201)
|
||||
def add_advisor(body: AdvisorCreate, db: Session = Depends(get_db)):
|
||||
return wl_advisor_dao.create_advisor(db, body)
|
||||
|
||||
|
||||
# 根据编号查询单个顾问
|
||||
@router.get("/{adv_id}", response_model=AdvisorOut)
|
||||
def query_one(adv_id: int, db: Session = Depends(get_db)):
|
||||
advisor = wl_advisor_dao.get_advisor_by_id(db, adv_id)
|
||||
if not advisor:
|
||||
raise HTTPException(status_code=404, detail="顾问不存在")
|
||||
return advisor
|
||||
|
||||
|
||||
# 修改顾问
|
||||
@router.put("/{adv_id}", response_model=AdvisorOut)
|
||||
def edit_advisor(adv_id: int, body: AdvisorUpdate, db: Session = Depends(get_db)):
|
||||
advisor = wl_advisor_dao.update_advisor(db, adv_id, body)
|
||||
if not advisor:
|
||||
raise HTTPException(status_code=404, detail="顾问不存在")
|
||||
return advisor
|
||||
|
||||
|
||||
# 逻辑删除顾问
|
||||
@router.delete("/{adv_id}")
|
||||
def remove_advisor(adv_id: int, db: Session = Depends(get_db)):
|
||||
if not wl_advisor_dao.delete_advisor(db, adv_id):
|
||||
raise HTTPException(status_code=404, detail="顾问不存在")
|
||||
return {"code": 200, "msg": "删除成功"}
|
||||
@@ -0,0 +1,49 @@
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy.orm import Session
|
||||
from typing import List
|
||||
from database import get_db
|
||||
from scheme.wl_class_scheme import ClassCreate,ClassUpdate,ClassOut
|
||||
from dao import wl_class_dao
|
||||
from fastapi import HTTPException
|
||||
|
||||
# 创建班级模块的路由,统一前缀 /classes
|
||||
router = APIRouter(prefix="/classes", tags=["班级管理"])
|
||||
|
||||
# 1. 新增班级
|
||||
@router.post("/", response_model=ClassOut)
|
||||
def create_class(class_data: ClassCreate, db: Session = Depends(get_db)):
|
||||
return wl_class_dao.create_class(db, class_data.model_dump())
|
||||
|
||||
#为了合并先注释的部分
|
||||
# @router.post("/", response_model=ClassOut)
|
||||
# def create_class(class_data: ClassCreate, db: Session = Depends(get_db)):
|
||||
# 把 pydantic 对象转成字典,再传给 dao
|
||||
# if not db_class:
|
||||
# raise HTTPException(status_code=404, detail="班级不存在")
|
||||
|
||||
# 2. 获取班级列表
|
||||
@router.get("/", response_model=List[ClassOut])
|
||||
def read_classes(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
|
||||
return wl_class_dao.get_classes(db, skip, limit)
|
||||
|
||||
# 3. 获取单个班级详情
|
||||
@router.get("/{class_id}", response_model=ClassOut)
|
||||
def read_class(class_id: int, db: Session = Depends(get_db)):
|
||||
db_class = wl_class_dao.get_class_by_id(db, class_id)
|
||||
if not db_class:
|
||||
raise HTTPException(status_code=404, detail="班级不存在")
|
||||
return db_class
|
||||
|
||||
# 4. 修改班级
|
||||
@router.put("/{class_id}", response_model=ClassOut)
|
||||
def update_class(class_id: int, class_data: ClassUpdate, db: Session = Depends(get_db)):
|
||||
db_class = wl_class_dao.update_class(db, class_id, class_data.model_dump(exclude_unset=True))
|
||||
if not db_class:
|
||||
raise HTTPException(status_code=404, detail="班级不存在")
|
||||
return db_class
|
||||
|
||||
# 5. 删除班级(逻辑删除)
|
||||
@router.delete("/{class_id}")
|
||||
def delete_class(class_id: int, db: Session = Depends(get_db)):
|
||||
# 直接把 dao 的结果返回给前端,前端根据 code 判断是否成功
|
||||
return wl_class_dao.delete_class(db, class_id)
|
||||
@@ -0,0 +1,56 @@
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from dao.wl_emp_dao import EmpDAO
|
||||
from database import get_db
|
||||
from scheme.wl_emp_scheme import EmpCreate, EmpOut, EmpUpdate
|
||||
|
||||
router = APIRouter(prefix="/emp", tags=["就业管理"])
|
||||
|
||||
|
||||
# 查询就业列表
|
||||
@router.get("/", response_model=list[EmpOut])
|
||||
def query_list(
|
||||
skip: int = 0,
|
||||
limit: int = 100,
|
||||
company_name: Optional[str] = None,
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
return EmpDAO.list_emps(db, skip, limit, company_name)
|
||||
|
||||
|
||||
# 根据学号查询就业信息
|
||||
@router.get("/{stu_no}", response_model=EmpOut)
|
||||
def query_one(stu_no: str, db: Session = Depends(get_db)):
|
||||
emp = EmpDAO.get_emp(db, stu_no)
|
||||
if not emp:
|
||||
raise HTTPException(status_code=404, detail="就业信息不存在")
|
||||
return emp
|
||||
|
||||
|
||||
# 新增就业信息
|
||||
@router.post("/", response_model=EmpOut, status_code=201)
|
||||
def add_emp(body: EmpCreate, db: Session = Depends(get_db)):
|
||||
try:
|
||||
return EmpDAO.create_emp(db, body)
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
|
||||
|
||||
# 修改就业信息
|
||||
@router.put("/{stu_no}", response_model=EmpOut)
|
||||
def edit_emp(stu_no: str, body: EmpUpdate, db: Session = Depends(get_db)):
|
||||
emp = EmpDAO.update_emp(db, stu_no, body)
|
||||
if not emp:
|
||||
raise HTTPException(status_code=404, detail="就业信息不存在")
|
||||
return emp
|
||||
|
||||
|
||||
# 逻辑删除就业信息
|
||||
@router.delete("/{stu_no}")
|
||||
def remove_emp(stu_no: str, db: Session = Depends(get_db)):
|
||||
if not EmpDAO.delete_emp(db, stu_no):
|
||||
raise HTTPException(status_code=404, detail="就业信息不存在")
|
||||
return {"code": 200, "msg": "删除成功"}
|
||||
Reference in New Issue
Block a user