Compare commits

6 Commits
Author SHA1 Message Date
maruizhi 79da6dc3a0 Merge pull request 'Conding' (#7) from conding into master
Reviewed-on: #7
2026-09-22 20:22:40 +08:00
maruizhi da935f93bd Merge pull request 'Conding' (#6) from conding into master
Reviewed-on: #6
2026-09-22 12:22:56 +08:00
maruizhi 92b98226d8 Merge pull request 'Conding' (#5) from conding into master
Reviewed-on: #5
2026-09-21 11:23:21 +08:00
maruizhi e13ace8616 Merge pull request 'Conding' (#4) from conding into master
Reviewed-on: #4
2026-09-21 09:56:48 +08:00
maruizhi 46faa300a8 Merge pull request 'Conding' (#2) from conding into master
Reviewed-on: #2
2026-09-21 09:24:39 +08:00
maruizhi 26429d6b6f Merge pull request 'Conding' (#1) from conding into master
Reviewed-on: #1
2026-09-19 16:39:12 +08:00
14 changed files with 131 additions and 211 deletions
+7 -15
View File
@@ -1,32 +1,24 @@
from fastapi import APIRouter, Depends, Query
from typing import Annotated
from fastapi import APIRouter, Depends
from util.database import get_db
from schema.cla_schema import claRequest
from dao.cla_dao import add_class_dao, get_class_dao, update_class_dao, delete_class_dao
from dao.cla_dao import add_class_dao,get_class_dao,update_class_dao,delete_class_dao
claAPI = APIRouter(prefix="/class", tags=["班级管理模块"])
@claAPI.post("/", summary="新增班级信息")
def add_class(data: claRequest, Session=Depends(get_db)):
def add_class(data: claRequest, Session = Depends(get_db)):
return add_class_dao(data, Session)
@claAPI.get("/list", summary="查询班级信息")
def list_class(
n: Annotated[int, Query(ge=1, description="页码,从1开始")],
m: Annotated[int, Query(ge=1, description="每页条数")],
Session=Depends(get_db)):
return get_class_dao(n, m, Session)
def list_class(n:int,m:int,Session = Depends(get_db)):
return get_class_dao(n,m,Session)
@claAPI.put("/{class_id}", summary="更新班级信息")
def update_class(class_id: int, data: claRequest, Session=Depends(get_db)):
def update_class(class_id: int, data: claRequest, Session = Depends(get_db)):
return update_class_dao(class_id, data, Session)
@claAPI.delete("/{class_id}", summary="逻辑删除班级信息")
def delete_class(class_id: int, Session=Depends(get_db)):
def delete_class(class_id: int, Session = Depends(get_db)):
return delete_class_dao(class_id, Session)
+11 -19
View File
@@ -6,24 +6,16 @@ from util.database import get_db
from typing import Optional
emp_api = APIRouter(tags=['学生就业管理模块'])
@emp_api.get('/employment/student/{stu_id}',response_model=list[EmploymentResponse],summary='获取学生就业信息')
def get_emp_info1(stu_id: Optional[int]=Path(description='学生编号')
,db=Depends(get_db)):
e = employment_dao.get_emp_dao(stu_id=stu_id, db=db)
if e:
return e
raise HTTPException(status_code=404, detail='该学生就业信息不存在')
@emp_api.get('/employment/class/{class_id}',response_model=list[EmploymentResponse],summary='获取班级学生就业信息')
def get_emp_info2(class_id: Optional[int]=Path(description='班级编号')
def get_emp_info1(class_id: Optional[int]=Path(description='班级编号')
,db=Depends(get_db)):
e1 = employment_dao.get_emp_dao(class_id=class_id, db=db)
if e1:
return e1
raise HTTPException(status_code=404, detail='该班级就业信息不存在')
@emp_api.get('/employment/students',response_model=list[EmploymentResponse],summary='按照学⽣编号,公司名字,⼯资范围查询学⽣就业信息')
def get_emp_info3(stu_id:int|None = Query(None,description='学生编号')
@emp_api.get('/employment/students/{stu_id}',response_model=list[EmploymentResponse],summary='按照学⽣编号,公司名字,⼯资范围查询学⽣就业信息')
def get_emp_info2(stu_id:int = Path(description='学生编号')
,company_name: str|None = Query(None,description='公司名称')
,min_salary: float|None = Query(None,ge=0,description='最低工资')
,max_salary: float|None = Query(None,ge=0,description='最高工资')
@@ -39,24 +31,24 @@ def get_emp_info3(stu_id:int|None = Query(None,description='学生编号')
raise HTTPException(status_code=404,detail='该学生就业信息不存在!')
return l1
@emp_api.post('/employment/student/{stu_id}',summary='新增学生就业信息')
@emp_api.post('/employment/students/{stu_id}',response_model=EmploymentResponse,summary='新增学生就业信息')
def create_emp_info(emp:EmploymentRequest=Form(),db=Depends(get_db)):
d=emp.model_dump(exclude_unset=False)
r=add_emp_dao(d,db)
if not r:
raise HTTPException(status_code=500,detail='服务器繁忙,请稍后添加!')
return {'code':200,'detail':'插入成功!'}
return r
@emp_api.put('/employment/students/{stu_id}',summary='更新学生就业信息')
def update_emp_info(stu_id:int,emp:UpdateEmpRequest,db=Depends(get_db)):
r = update_emp_dao(stu_id,emp.model_dump(exclude_unset=True),db)
@emp_api.put('/employment/students/{emp_id}',summary='更新学生就业信息')
def update_emp_info(emp_id:int,emp:UpdateEmpRequest,db=Depends(get_db)):
r = update_emp_dao(emp_id,emp.model_dump(exclude_unset=True),db)
if not r:
raise HTTPException(status_code=500,detail='没有更新!')
return {'code':200,'totals':r,'detail':'更新成功!'}
@emp_api.delete('/employment/{stu_id}',summary='删除学生就业信息')
def delete_emp_info(stu_id:int=Path(description='序号'),db=Depends(get_db)):
rows = delete_emp_dao(stu_id, db)
@emp_api.delete('/employment/{emp_id}',summary='删除学生就业信息')
def delete_emp_info(emp_id:int=Path(description='序号'),db=Depends(get_db)):
rows = delete_emp_dao(emp_id, db)
if not rows:
raise HTTPException(status_code=500, detail='没有删除!')
return {'code':200,'detail':'删除成功!'}
+6 -7
View File
@@ -19,13 +19,6 @@ def get_grade(stu_id: int,db=Depends(get_db)):
except Exception as e:
raise HTTPException(status_code=500,detail=f'数据库查询异常:{str(e)}')
@gradeAPI.delete('/{stu_id}',summary='删除成绩')
def delete_grade(stu_id:int,db=Depends(get_db)):
r = delete_grade_dao(stu_id=stu_id,db=db)
if not r:
raise HTTPException(status_code=404,detail='删除失败')
return {'code':200,'totals':r,'detail':'删除成功'}
@gradeAPI.post('/grade',summary='添加学生成绩')
def post_grade(o:GradeRequest,db=Depends(get_db)):
d=o.model_dump()
@@ -79,3 +72,9 @@ def put_grade(
return {"code": 200, "totals": rows, "detail": "更新成功"}
@gradeAPI.delete('/{score_id}',summary='删除成绩')
def delete_grade(score_id:int,db=Depends(get_db)):
r = delete_grade_dao(stu_id=score_id,db=db)
if not r:
raise HTTPException(status_code=404,detail='删除失败')
return {'code':200,'totals':r,'detail':'删除成功'}
+1 -1
View File
@@ -17,7 +17,7 @@ def get_students(db=Depends(get_db)):
return l
@StatisticsAPI.get("/score",response_model=list[GetScoreResponse],summary='根据成绩查询学生信息')
def get_students(min_score:int|None=Query(None,ge=0,le=150),max_score:int|None=Query(None,ge=0,le=150),db=Depends(get_db)):
def get_students(min_score:int|None=None,max_score:int|None=None,db=Depends(get_db)):
l = select_score(min_score,max_score,db)
return l
+20 -20
View File
@@ -1,4 +1,4 @@
from fastapi import APIRouter, HTTPException, Depends, Query, Path
from fastapi import APIRouter,HTTPException,Depends
from dao.student_dao import *
from schema.student_schema import *
from util.database import get_db
@@ -6,6 +6,24 @@ from util.database import get_db
StudentAPI = APIRouter(tags=['学生基本信息管理模块'])
@StudentAPI.get('/students',response_model=StuPageResponse,summary='学生信息查询接口',description='查询学生信息')
def get_students(stu_id:int|None=None
,stu_name:str|None=None
,class_id:int|None=None
,db=Depends(get_db)
,page:int=1
,page_size:int=10):
r, total = get_student_dao(stu_id=stu_id
,stu_name=stu_name
,class_id=class_id
,page=page
,page_size=page_size
,db=db)
return StuPageResponse(page=page,
page_size=page_size,
totals=total,
data=r)
@StudentAPI.post('/students',response_model=StugetResponse,summary='学生信息新增接口',description='新增学生信息')
def add_students(s:StudentRequest
,db=Depends(get_db)):
@@ -19,24 +37,6 @@ def add_students(s:StudentRequest
raise HTTPException(status_code=500, detail='添加失败,请稍后重试')
return r
@StudentAPI.get('/students',response_model=StuPageResponse,summary='学生信息查询接口',description='查询学生信息')
def get_students(stu_id:int=Query(None,description='学生id')
,stu_name:str=Query(None,description='学生姓名')
,class_id:int=Query(None,description='班级编号')
,db=Depends(get_db)
,page:int=Query(None,description='页数')
,page_size:int=Query(None,description='行数')):
r, total = get_student_dao(stu_id=stu_id
,stu_name=stu_name
,class_id=class_id
,page=page
,page_size=page_size
,db=db)
return StuPageResponse(page=page
,page_size=page_size
,totals=total
,data=r)
@StudentAPI.put('/students/{stu_id}',summary='学生信息更新接口',description='更新学生信息')
def update_students(stu_id:int
,s:StuUpdateRequest
@@ -53,7 +53,7 @@ def update_students(stu_id:int
return {'code':200,'totals':r,'detail':'更新成功'}
@StudentAPI.delete('/students/{stu_id}',response_model= StudelResponse,summary='学生信息删除接口',description='删除学生信息')
def del_students(stu_id:int= Path(description='班级编号')
def del_students(stu_id:int
,db=Depends(get_db)):
rows=delete_student_dao( stu_id=stu_id,db=db )
if not rows:
+17 -83
View File
@@ -2,111 +2,45 @@ from model.all_model import ClassManagement
from fastapi import HTTPException
from schema.cla_schema import claRequest
from datetime import datetime
from sqlalchemy.exc import SQLAlchemyError
import logging
logger = logging.getLogger(__name__)
def add_class_dao(c: claRequest, session):
try:
# ---------- 校验:班级名称不能重复 ----------
# 只查未删除的记录,含义是:已逻辑删除的班级允许重建同名
exists = (
session.query(ClassManagement)
.filter(ClassManagement.class_name == c.class_name)
.filter(ClassManagement.delete_status == 0)
.first()
)
if exists:
raise HTTPException(400, f"班级 '{c.class_name}' 已存在,不能重复添加")
# 班主任和授课教师可以是同一个人,无需校验
data = c.model_dump()
d = ClassManagement(**data)
session.add(d)
session.commit()
session.refresh(d)
return d
except HTTPException:
raise
except SQLAlchemyError as e:
except:
session.rollback()
logger.error(f"新增班级失败: {e}")
raise HTTPException(400, "输入有误,请重新添加班级!")
def get_class_dao(n: int, m: int, session):
def get_class_dao(n,m,session):
try:
if n < 1 or m < 1:
return []
class_list = (
session.query(ClassManagement)
.filter(ClassManagement.delete_status == 0)
.offset((n - 1) * m)
.limit(m)
.all()
)
class_list=session.query(ClassManagement).filter(ClassManagement.delete_status==0).offset((n-1)*m).limit(m).all()
return class_list
except SQLAlchemyError as e:
logger.error(f"查询班级列表失败: {e}")
raise HTTPException(status_code=400, detail="查询失败,请稍后重试!")
except:
raise HTTPException(status_code=406,detail="输入查询信息有误,请重新输入!")
def update_class_dao(class_id: int, req: claRequest, session):
def update_class_dao(id:int,req:claRequest,session):
try:
rows = (
session.query(ClassManagement)
.filter(ClassManagement.class_id == class_id)
.filter(ClassManagement.delete_status == 0)
.update(req.model_dump(exclude_unset=True), synchronize_session=False)
)
session.query(ClassManagement).filter(ClassManagement.class_id==id)\
.filter(ClassManagement.delete_status==0).update(req.model_dump(exclude_unset=True))
session.commit()
if rows == 0:
raise HTTPException(status_code=404, detail="该班级不存在或已被删除")
except HTTPException:
session.rollback()
raise
except SQLAlchemyError as e:
session.rollback()
logger.error(f"更新班级失败: {e}")
raise HTTPException(status_code=400, detail="更新失败,请检查参数")
return {"code": 200, "msg": "更新成功"}
except:
raise HTTPException(status_code=400,detail="更新格式错误或参数缺失,请重新输入!")
return '更新成功,请核对信息!'
def delete_class_dao(class_id: int, session):
def delete_class_dao(id:int,session):
try:
# 先按 class_id 查记录,再判断状态,从而区分"不存在"和"已删除"
obj = (
session.query(ClassManagement)
.filter(ClassManagement.class_id == class_id)
.first()
)
# 情况 1:记录不存在
if obj is None:
raise HTTPException(status_code=404, detail="该班级不存在")
# 情况 2:记录存在但已删除 → 提示"已删除"
if obj.delete_status == 1:
raise HTTPException(status_code=400, detail="该班级已被删除,请勿重复操作")
# 情况 3:执行逻辑删除
obj.delete_status = 1
obj.delete_time = datetime.now()
session.query(ClassManagement).filter(ClassManagement.class_id==id,ClassManagement.delete_status==0)\
.update({'delete_status': 1,'delete_time': datetime.now()})
session.commit()
except:
raise HTTPException(status_code=404, detail="删除异常,请重新核对之后删除!")
return '删除成功,请核对信息!'
except HTTPException:
session.rollback()
raise
except SQLAlchemyError as e:
session.rollback()
logger.error(f"删除班级失败: {e}")
raise HTTPException(status_code=400, detail="删除异常,请核对后重试!")
return {"code": 200, "msg": "删除成功"}
+8 -8
View File
@@ -41,35 +41,35 @@ def add_emp_dao(o,db):
if not stu:
raise HTTPException(status_code=404, detail='该学生不存在,无法添加就业信息')
exist = db.query(Employment_info).filter(Employment_info.stu_id == o['stu_id']
,Employment_info.delete_status == 0).first()
exist = (db.query(Employment_info).filter(Employment_info.stu_id == o['stu_id']
,Employment_info.delete_status == 0).first())
if exist:
raise HTTPException(status_code=409, detail='该学生已有就业信息,请勿重复增加!')
e1 = Employment_info(**o)
db.add(e1)
db.commit()
return o
return e1
except Exception as e:
db.rollback()
raise HTTPException(status_code=500, detail=f'新增就业信息失败: {e}')
def update_emp_dao(stu_id,emp,db):
def update_emp_dao(emp_id,emp,db):
try:
rows = db.query(Employment_info)\
.filter(Employment_info.stu_id == stu_id,Employment_info.delete_status == 0)\
.filter(Employment_info.emp_id == emp_id,Employment_info.delete_status == 0)\
.update(emp)
db.commit()
return rows
except:
db.rollback()
raise HTTPException(status_code=404,detail='该就业记录不存在')
raise HTTPException(status_code=404,detail='该就业记录已存在')
def delete_emp_dao(stu_id:int,db):
def delete_emp_dao(emp_id:int,db):
try:
rows = db.query(Employment_info)\
.filter(Employment_info.stu_id == stu_id
.filter(Employment_info.emp_id == emp_id
,Employment_info.delete_status == 0)\
.update({'delete_status':1,'delete_time': datetime.now()})
db.commit()
+8 -14
View File
@@ -19,19 +19,14 @@ def get_score_by_stu_exam_order_dao(stu_id:str,exam_order:int,db):
def get_grade_dao( stu_id:int , db):
r1 =(db.query( WlScore.score_id
,WlScore.stu_id
,Student_Model.stu_name
,WlScore.exam_order
,WlScore.score
,ClassManagement.class_name
r1 =(db.query( WlScore.score_id
,WlScore.stu_id
,Student_Model.stu_name
,WlScore.exam_order
,WlScore.score
)
.join( Student_Model,WlScore.stu_id == Student_Model.stu_id)
.join(ClassManagement,Student_Model.class_id==ClassManagement.class_id)
.filter( WlScore.stu_id == stu_id
,WlScore.delete_status == 0
,Student_Model.delete_status == 0
,ClassManagement.delete_status == 0)
.join(Student_Model,WlScore.stu_id == Student_Model.stu_id)
.filter(WlScore.stu_id == stu_id,WlScore.delete_status == 0,Student_Model.delete_status == 0)
.all())
if r1:
data_list = []
@@ -41,8 +36,7 @@ def get_grade_dao( stu_id:int , db):
"stu_id": row.stu_id,
"stu_name": row.stu_name,
"exam_order": row.exam_order,
"score": row.score,
"class_name": row.class_name,
"score": row.score
})
return data_list
else:
+30 -30
View File
@@ -5,11 +5,11 @@ from sqlalchemy.exc import IntegrityError
def add_student_dao(o,db):
if o.get('id_card'):
o1 = (db.query(Student_Model)
conflict = (db.query(Student_Model)
.filter(Student_Model.id_card == o['id_card'],
Student_Model.delete_status == 0)
.first())
if o1:
if conflict:
return 'conflict'
try:
o2 = Student_Model(**o)
@@ -23,23 +23,17 @@ def add_student_dao(o,db):
db.rollback()
return 'error'
def get_student_dao(stu_id:Optional[int]
,stu_name:Optional[str]
,class_id:Optional[int]
,page: int
,page_size: int
,db
) -> tuple[List[Dict[str, Any]], int]:
q = db.query(Student_Model).filter(Student_Model.delete_status == 0)
if stu_id:
q = q.filter(Student_Model.stu_id == stu_id)
if stu_name and stu_name.strip() != "":
q = q.filter(Student_Model.stu_name.like(f"%{stu_name}%"))
if class_id:
q = q.filter(Student_Model.class_id == class_id)
total = q.count()
r = q.offset((page - 1) * page_size).limit(page_size).all()
return r, total
def delete_student_dao(stu_id, db):
try:
rows = (db.query(Student_Model)
.filter(Student_Model.stu_id == stu_id,
Student_Model.delete_status == 0)
.update({'delete_status': 1, 'delete_time': datetime.now()}))
db.commit()
return rows
except Exception:
db.rollback()
raise
def update_student_dao(stu_id, update_data, db):
if not update_data:
@@ -58,14 +52,20 @@ def update_student_dao(stu_id, update_data, db):
return 'error'
return rows
def delete_student_dao(stu_id, db):
try:
rows = (db.query(Student_Model)
.filter(Student_Model.stu_id == stu_id,
Student_Model.delete_status == 0)
.update({'delete_status': 1, 'delete_time': datetime.now()}))
db.commit()
return rows
except Exception:
db.rollback()
raise
def get_student_dao(stu_id:Optional[int]
,stu_name:Optional[str]
,class_id:Optional[int]
,page: int
,page_size: int
,db
) -> tuple[List[Dict[str, Any]], int]:
q = db.query(Student_Model).filter(Student_Model.delete_status == 0)
if stu_id:
q = q.filter(Student_Model.stu_id == stu_id)
if stu_name and stu_name.strip() != "":
q = q.filter(Student_Model.stu_name.like(f"%{stu_name}%"))
if class_id:
q = q.filter(Student_Model.class_id == class_id)
total = q.count()
r = q.offset((page - 1) * page_size).limit(page_size).all()
return r, total
+1 -1
View File
@@ -18,7 +18,7 @@ app = FastAPI(title='沃林学生管理系统',openapi_tags=tags_metadata)
app.include_router(StudentAPI)
app.include_router(StatisticsAPI) #实现路由分发
app.include_router(StatisticsAPI)
app.include_router(teacher_api)
app.include_router(emp_api)
app.include_router(gradeAPI)
+1 -1
View File
@@ -72,7 +72,7 @@ class ClassManagement(Base):
delete_status = Column(Integer,default=0,comment='删除状态:0未删除,1已删除')
delete_time = Column(DATETIME,comment='删除时间') #只有删除时更新时间
delete_time = Column(DATETIME,comment='删除时间')
class Teacher_Model(Base):
__tablename__ = 'wl_teacher'
+18 -2
View File
@@ -1,10 +1,26 @@
from datetime import date
from pydantic import BaseModel
class claRequest(BaseModel): #请求体,获取json格式数据给api层再给schema校验,校验后给dao层操作数据库
class claRequest(BaseModel):
class_name : str|None = None
start_class_date :date
head_teacher_id : int|None = None
class_teacher_id : int|None = None
class claResponse(BaseModel):
code: int = 200
detail: str = 'ok'
class_name: str | None = None
start_class_date: date
head_teacher_id: int | None = None
class_teacher_id: int | None = None
+1 -1
View File
@@ -3,7 +3,7 @@ from datetime import date
from typing import Optional
class EmploymentRequest(BaseModel):
stu_id: int=Field(ge=1, description='学生编号')
stu_id: int=Field(ge=1,description='学生编号')
email: Optional[str] = Field(None, description='邮箱')
employment_opening_date:Optional[date] = Field(None, description='就业开放日期')
offer_issuance_date:Optional[date] = Field(None, description='offer下发日期')
+2 -9
View File
@@ -1,5 +1,5 @@
from datetime import date
from typing import Self,List,Optional
from typing import Self,List
from pydantic import BaseModel, field_serializer, field_validator,model_validator,ConfigDict
@@ -53,13 +53,6 @@ class StuUpdateRequest(BaseModel):
raise ValueError('年龄不能为负数')
return v
@field_validator('id_card')
@classmethod
def check_id_card(cls, v):
if len(v) != 18 or len(v) != 19 :
raise ValueError('身份证输入有误')
return v
@model_validator(mode='after')
def check_admission_graduation(self) -> Self:
if self.admission_date and self.graduation_date:
@@ -84,7 +77,7 @@ class StugetResponse(BaseModel):
degree: str | None = None
admission_date: date | None = None
graduation_date: date | None = None
progress: Optional[int]
progress: int
@field_serializer('progress')
def progress_to_label(self, progress):