顾问模块合并,都合完了哦,庆祝一下!!!
This commit is contained in:
@@ -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": "删除成功"}
|
||||||
@@ -12,9 +12,10 @@ def list_students(
|
|||||||
stu_no: str = Query(None),
|
stu_no: str = Query(None),
|
||||||
stu_name: str = Query(None),
|
stu_name: str = Query(None),
|
||||||
class_id: int = Query(None),
|
class_id: int = Query(None),
|
||||||
|
advisor_id: int = Query(None, description="按顾问筛选该顾问名下的学生"),
|
||||||
db: Session = Depends(get_db),
|
db: Session = Depends(get_db),
|
||||||
):
|
):
|
||||||
return wl_student_dao.search_students(db, stu_no, stu_name, class_id)
|
return wl_student_dao.search_students(db, stu_no, stu_name, class_id, advisor_id)
|
||||||
|
|
||||||
|
|
||||||
@router.post("", response_model=StudentOut)
|
@router.post("", response_model=StudentOut)
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
from fastapi import HTTPException
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from model.wl_advisor_model import Advisor
|
||||||
|
from model.wl_student_model import Student
|
||||||
|
from scheme.wl_advisor_scheme import AdvisorCreate, AdvisorUpdate
|
||||||
|
|
||||||
|
|
||||||
|
# ---- 增 ----
|
||||||
|
def create_advisor(db: Session, data: AdvisorCreate) -> Advisor:
|
||||||
|
db_advisor = Advisor(**data.model_dump())
|
||||||
|
db.add(db_advisor)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(db_advisor)
|
||||||
|
return db_advisor
|
||||||
|
|
||||||
|
|
||||||
|
# ---- 查(多条件 + 分页)----
|
||||||
|
def list_advisors(db: Session, adv_name=None, adv_phone=None, adv_region=None,
|
||||||
|
adv_gender=None, skip: int = 0, limit: int = 100):
|
||||||
|
q = db.query(Advisor).filter(Advisor.is_deleted == 0)
|
||||||
|
if adv_name:
|
||||||
|
q = q.filter(Advisor.adv_name.like(f"%{adv_name}%"))
|
||||||
|
if adv_phone:
|
||||||
|
q = q.filter(Advisor.adv_phone.like(f"%{adv_phone}%"))
|
||||||
|
if adv_region:
|
||||||
|
q = q.filter(Advisor.adv_region.like(f"%{adv_region}%"))
|
||||||
|
if adv_gender:
|
||||||
|
q = q.filter(Advisor.adv_gender == adv_gender)
|
||||||
|
# 后录进来的顾问排前面,方便前端看到最新数据
|
||||||
|
return q.order_by(Advisor.adv_id.desc()).offset(skip).limit(limit).all()
|
||||||
|
|
||||||
|
|
||||||
|
# ---- 根据编号查单个顾问 ----
|
||||||
|
def get_advisor_by_id(db: Session, adv_id: int) -> Advisor | None:
|
||||||
|
return db.query(Advisor).filter(
|
||||||
|
Advisor.adv_id == adv_id,
|
||||||
|
Advisor.is_deleted == 0,
|
||||||
|
).first()
|
||||||
|
|
||||||
|
|
||||||
|
# ---- 改 ----
|
||||||
|
def update_advisor(db: Session, adv_id: int, data: AdvisorUpdate) -> Advisor | None:
|
||||||
|
db_advisor = get_advisor_by_id(db, adv_id)
|
||||||
|
if not db_advisor:
|
||||||
|
return None
|
||||||
|
# exclude_unset:前端传了什么就改什么,没传的字段保持原值
|
||||||
|
for k, v in data.model_dump(exclude_unset=True).items():
|
||||||
|
setattr(db_advisor, k, v)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(db_advisor)
|
||||||
|
return db_advisor
|
||||||
|
|
||||||
|
|
||||||
|
# ---- 逻辑删除 ----
|
||||||
|
def delete_advisor(db: Session, adv_id: int) -> bool:
|
||||||
|
db_advisor = get_advisor_by_id(db, adv_id)
|
||||||
|
if not db_advisor:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 名下还挂着学生就不给删,处理方式和班级模块 delete_class 保持一致
|
||||||
|
student = db.query(Student).filter(
|
||||||
|
Student.advisor_id == adv_id,
|
||||||
|
Student.is_deleted == 0,
|
||||||
|
).first()
|
||||||
|
if student:
|
||||||
|
raise HTTPException(status_code=400, detail="该顾问名下还有学生,不能删除!")
|
||||||
|
|
||||||
|
db_advisor.is_deleted = 1
|
||||||
|
db.commit()
|
||||||
|
return True
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#项目初始化入口
|
#项目初始化入口
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
# 周学灵、熊浩钦、圣国伟、刘盼、彭少、赵康宁的路由
|
# 周学灵、熊浩钦、圣国伟、刘盼、彭少、赵康宁的路由
|
||||||
from api import wl_student_api,wl_class_api,wl_score_api,wl_teacher_api,statistics,wl_emp_api
|
from api import wl_student_api,wl_class_api,wl_score_api,wl_teacher_api,statistics,wl_emp_api,wl_advisor_api
|
||||||
from database import Base, engine
|
from database import Base, engine
|
||||||
# wl_emp_model 必须显式导入:否则 wl_emp 表只能靠 statistics 的传递导入进 metadata,
|
# wl_emp_model 必须显式导入:否则 wl_emp 表只能靠 statistics 的传递导入进 metadata,
|
||||||
# 一旦统计路由被拿掉,create_all 会漏建 wl_emp,Student.emp 关系随即报错
|
# 一旦统计路由被拿掉,create_all 会漏建 wl_emp,Student.emp 关系随即报错
|
||||||
@@ -17,6 +17,7 @@ app.include_router(wl_score_api.router)
|
|||||||
app.include_router(wl_teacher_api.router)
|
app.include_router(wl_teacher_api.router)
|
||||||
app.include_router(statistics.router)
|
app.include_router(statistics.router)
|
||||||
app.include_router(wl_emp_api.router)
|
app.include_router(wl_emp_api.router)
|
||||||
|
app.include_router(wl_advisor_api.router)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
from pydantic import BaseModel, Field, ConfigDict
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
# ---------- 请求模型 ----------
|
||||||
|
# 顾问模块:入参格式,字段长度跟 model/wl_advisor_model.py 里的列宽保持一致
|
||||||
|
class AdvisorCreate(BaseModel):
|
||||||
|
adv_name: str = Field(..., max_length=50, description="顾问姓名")
|
||||||
|
adv_gender: Optional[str] = Field(None, max_length=8, description="性别")
|
||||||
|
adv_phone: Optional[str] = Field(None, max_length=20, description="手机号")
|
||||||
|
adv_email: Optional[str] = Field(None, max_length=64, description="邮箱")
|
||||||
|
adv_region: Optional[str] = Field(None, max_length=64, description="负责区域/招生渠道")
|
||||||
|
|
||||||
|
class AdvisorUpdate(BaseModel):
|
||||||
|
adv_name: Optional[str] = Field(None, max_length=50)
|
||||||
|
adv_gender: Optional[str] = Field(None, max_length=8)
|
||||||
|
adv_phone: Optional[str] = Field(None, max_length=20)
|
||||||
|
adv_email: Optional[str] = Field(None, max_length=64)
|
||||||
|
adv_region: Optional[str] = Field(None, max_length=64)
|
||||||
|
|
||||||
|
# ---------- 响应模型 ----------
|
||||||
|
# is_deleted 是逻辑删除标记,不对外暴露
|
||||||
|
class AdvisorOut(BaseModel):
|
||||||
|
adv_id: int
|
||||||
|
adv_name: str
|
||||||
|
adv_gender: Optional[str] = None
|
||||||
|
adv_phone: Optional[str] = None
|
||||||
|
adv_email: Optional[str] = None
|
||||||
|
adv_region: Optional[str] = None
|
||||||
|
|
||||||
|
model_config = ConfigDict(from_attributes=True)
|
||||||
@@ -51,14 +51,3 @@ class TeacherResp(TeacherCreate):
|
|||||||
t_id: int
|
t_id: int
|
||||||
class Config:
|
class Config:
|
||||||
from_attributes = True
|
from_attributes = True
|
||||||
|
|
||||||
# ----------------顾问----------------
|
|
||||||
class AdvisorCreate(BaseModel):
|
|
||||||
t_name: str
|
|
||||||
gender: Optional[str] = None
|
|
||||||
phone: Optional[str] = None
|
|
||||||
|
|
||||||
class AdvisorResp(AdvisorCreate):
|
|
||||||
advisor_id: int
|
|
||||||
class Config:
|
|
||||||
from_attributes = True
|
|
||||||
Reference in New Issue
Block a user