Compare commits
18
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1558103dfa | ||
|
|
5c671020d7 | ||
|
|
de85f8ef06 | ||
|
|
1fe2b6bc60 | ||
|
|
8a1022390f | ||
|
|
ed151b55ae | ||
|
|
7cdad9a9fe | ||
|
|
e88306a555 | ||
|
|
6e526d9f6b | ||
|
|
1b9e5b8a57 | ||
|
|
e9288e3496 | ||
|
|
95714309c9 | ||
|
|
6bf636e76b | ||
|
|
33a6ab75da | ||
|
|
519e9b180a | ||
|
|
962a793d13 | ||
|
|
60d4066b99 | ||
|
|
d9a41a8738 |
+16
@@ -0,0 +1,16 @@
|
||||
.venv/
|
||||
.idea
|
||||
__pycache__/
|
||||
*.pyc
|
||||
.pytest_cache/
|
||||
.mypy_cache/
|
||||
.ruff_cache/
|
||||
tests/
|
||||
.git/
|
||||
.github/
|
||||
*.md
|
||||
!README.md
|
||||
.env
|
||||
.env.*
|
||||
Dockerfile
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
3.13
|
||||
@@ -1 +1,291 @@
|
||||
# 学生管理系统
|
||||
# 教培系统架构设计与开发
|
||||
|
||||
本项目旨在开发一个基于FastAPI的学生管理系统,提供**学生基本信息管理、考核成绩管理和就业管理**三大核心功能模块。
|
||||
|
||||
系统将采用RESTful API设计,支持前后端分离架构。
|
||||
|
||||
|
||||
|
||||
## 需求分期
|
||||
|
||||
团队对需求管理按照模块化解耦拆分开发,按照三个阶段开发
|
||||
|
||||
1. 基础需求:按照开发任务,完成5 + 1 统计模块的开发
|
||||
> todo: 每个人补充一下自己对本模块的理解
|
||||
|
||||
|
||||
2. 特色需求:
|
||||
|
||||
- 数据源配置
|
||||
|
||||
- 鉴权管理
|
||||
|
||||
- 添加部门管理,顾问管理模块
|
||||
|
||||
- 添加用户认证模块
|
||||
|
||||
- 开发前端应用
|
||||
|
||||
- 开发更多的分析查询接口
|
||||
|
||||
- 增加AI智能体和知识库开发
|
||||
|
||||
3. 脚手架集成
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### 第一阶段 - 基础需求
|
||||
|
||||
按照开发任务,完成5 + 1 统计模块的开发
|
||||
|
||||
- 学生
|
||||
- 班级
|
||||
- 老师
|
||||
- 成绩
|
||||
- 就业
|
||||
- 统计分析
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### 第二阶段 - 特色需求
|
||||
|
||||
- 数据源配置
|
||||
|
||||
- 鉴权管理
|
||||
|
||||
- 添加部门管理,顾问管理模块
|
||||
|
||||
- 添加用户认证模块
|
||||
|
||||
- 开发前端应用
|
||||
|
||||
- 开发更多的分析查询接口
|
||||
|
||||
- 增加AI智能体和知识库开发
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### 第三阶段 - 脚手架集成
|
||||
|
||||
核心组件
|
||||
|
||||
- 服务状态监控 - utc时区[还有哪些可替代?]
|
||||
- db ,中间件等组件是否活跃
|
||||
- 自身服务是否活跃
|
||||
- 认证模块: oauth2_scheme
|
||||
-
|
||||
-
|
||||
|
||||
|
||||
|
||||
## 业务拆分
|
||||
|
||||
> 业务范围划分
|
||||
>
|
||||
> - 实体
|
||||
> - 学生基本信息管理
|
||||
> - 考核成绩管理
|
||||
> - 就业管理
|
||||
> - 班级
|
||||
> - 老师
|
||||
> - 统计分析
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 数据架构设计
|
||||
|
||||
数据关系
|
||||
|
||||
- 学生:班级 = N: 1, 班级:老师 = 1 : 1 / [N:1], 学生: 成绩 = 1:N , 学生:就业 = 1:1,
|
||||
- 统计分析:
|
||||
|
||||
|
||||
|
||||
表结构优化
|
||||
|
||||
- 索引设置
|
||||
-
|
||||
|
||||
|
||||
|
||||
```sql
|
||||
create database student_management_system;
|
||||
use student_management_system;
|
||||
|
||||
-- students
|
||||
create table if not exists students(
|
||||
id int auto_increment primary key,
|
||||
snum int not null comment '学生编号',
|
||||
sname varchar(30) not null,
|
||||
age int not null,
|
||||
sex int not null,
|
||||
|
||||
home_place varchar(50) null comment '家乡',
|
||||
college varchar(50) null comment '毕业院校',
|
||||
specialty varchar(50) null comment '专业',
|
||||
enrollment_time datetime null comment '入学时间',
|
||||
graduate_time datetime null comment '毕业时间',
|
||||
education varchar(50) null comment '学历',
|
||||
|
||||
class_id int not null,
|
||||
|
||||
advisor_id int null comment '顾问id',
|
||||
advisor_num int null comment '顾问编号',
|
||||
|
||||
-- 通用字段
|
||||
create_time datetime not null,
|
||||
update_time datetime not null,
|
||||
is_detleted int not null comment '0 未删除,1'
|
||||
);
|
||||
|
||||
-- teachers
|
||||
create table if not exists teachers(
|
||||
id int auto_increment primary key,
|
||||
tnum int not null comment '老师编号',
|
||||
tname int not null,
|
||||
age int not null,
|
||||
sex int not null,
|
||||
|
||||
home_place varchar(50) null comment '家乡',
|
||||
college varchar(50) null comment '毕业院校',
|
||||
specialty varchar(50) null comment '专业',
|
||||
enrollment_time datetime null comment '入学时间',
|
||||
graduate_time datetime null comment '毕业时间',
|
||||
education varchar(50) null comment '学历',
|
||||
|
||||
-- 额外信息:工作经验/教学评级 ,教学方向:应用,项目,算法;
|
||||
work_experience text null comment '工作经验',
|
||||
coach_area text null comment '教学方向:应用,项目,算法',
|
||||
|
||||
-- 通用字段
|
||||
create_time datetime not null,
|
||||
update_time datetime not null,
|
||||
is_detleted int not null comment '0 未删除,1'
|
||||
);
|
||||
|
||||
|
||||
-- classes
|
||||
create table if not exists classes(
|
||||
id int auto_increment primary key,
|
||||
class_num int not null comment '班级编号',
|
||||
class_start_time datetime null comment '开课时间',
|
||||
head_teacher_id int null comment '班主任',
|
||||
head_teacher_num int null comment '班主任编号',
|
||||
|
||||
coach_teacher_id int null comment '授课老师',
|
||||
coach_teacher_num int null comment '授课老师编号',
|
||||
|
||||
tutor_teacher_id int null comment '助教老师',
|
||||
tutor_teacher_num int null comment '助教老师编号',
|
||||
|
||||
-- 通用字段
|
||||
create_time datetime not null,
|
||||
update_time datetime not null,
|
||||
is_detleted int not null comment '0 未删除,1'
|
||||
);
|
||||
|
||||
|
||||
-- scores
|
||||
create table if not exists scores(
|
||||
id int auto_increment primary key,
|
||||
sid int not null,
|
||||
snum int not null,
|
||||
score_num int not null comment '考核序次',
|
||||
score decimal(10,2) not null,
|
||||
|
||||
-- 通用字段
|
||||
create_time datetime not null,
|
||||
update_time datetime not null,
|
||||
is_detleted int not null comment '0 未删除,1'
|
||||
);
|
||||
|
||||
|
||||
-- employment
|
||||
create table if not exists employment(
|
||||
id int auto_increment primary key,
|
||||
sid int not null,
|
||||
snum int not null,
|
||||
sname varchar(30) not null,
|
||||
class_id int not null,
|
||||
class_num int not null comment '班级编号',
|
||||
|
||||
employment_open_time datetime null comment '就业开放时间',
|
||||
offer_recived_time datetime null comment 'offer下发时间',
|
||||
employment_company varchar(50) null comment '就业公司',
|
||||
employment_salary decimal(10,2) null comment '就业薪资',
|
||||
|
||||
-- 通用字段
|
||||
create_time datetime not null,
|
||||
update_time datetime not null,
|
||||
is_detleted int not null comment '0 未删除,1'
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 技术架构设计
|
||||
|
||||
### git 协作
|
||||
- 按照业务模块,每个人新建自己的分支,分支名称:user_module
|
||||
- main 分支:发版分支,test分支:做集成测试用
|
||||
|
||||
|
||||
### 构建环境适配
|
||||
|
||||
```bash
|
||||
# uv 统一
|
||||
pip install uv
|
||||
uv init
|
||||
uv add fastapi[standard] pymsql sqlalchemy # 添加依赖
|
||||
|
||||
# 运行测试
|
||||
uv run uvicorn main:app --reload # uv run fastapi dev
|
||||
|
||||
# 其他平台: sync 同步即可
|
||||
uv sync
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### 基础架构适配
|
||||
|
||||
- 后端框架:
|
||||
- web route / api docs / 数据校验 : FastAPI
|
||||
- ORM 框架: pymysql, sqlarchemy
|
||||
- 日志系统:loguru,
|
||||
-
|
||||
- 数据库:多数据源适配
|
||||
- dev : sqlite3
|
||||
- prod: MySQL, PG
|
||||
- 前端框架:
|
||||
- vue3
|
||||
-
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### 脚手架设计
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@app.get("/")
|
||||
def main():
|
||||
print("Hello from student-manage-system!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,12 @@
|
||||
[project]
|
||||
name = "student-manage-system"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"fastapi[standard]>=0.141.1",
|
||||
"pip>=26.2.1",
|
||||
"pymysql>=1.2.3",
|
||||
"sqlalchemy>=2.0.54",
|
||||
]
|
||||
@@ -0,0 +1,46 @@
|
||||
from fastapi import APIRouter, Depends,HTTPException
|
||||
from scores.database import get_db
|
||||
from scores.dao.score_dao import get_scores_dao,add_scores_dao,update_scores_dao,delete_scores_dao
|
||||
from scores.model.score_model import Score
|
||||
from scores.schema.score_request import ScoreRequest, ScoreResponse,ScoreQuery
|
||||
|
||||
score_api = APIRouter(tags=['成绩'])
|
||||
|
||||
@score_api.get('/Score',summary='成绩查询',description=f'查询条件为空即查询所有成绩')
|
||||
def get_scores(score:ScoreQuery=Depends(),db=Depends(get_db)):
|
||||
a = score.model_dump()
|
||||
aa = get_scores_dao(s=a,db=db)
|
||||
if aa:
|
||||
return aa
|
||||
raise HTTPException(status_code=404,detail='不存在')
|
||||
|
||||
@score_api.post('/Score',response_model=ScoreResponse
|
||||
,summary='成绩添加')
|
||||
def add_scores(score:ScoreRequest=Depends(),db=Depends(get_db)):
|
||||
a = score.model_dump()
|
||||
# print(a,type(a))
|
||||
aa = add_scores_dao(b=a,db=db)
|
||||
if aa:
|
||||
return ScoreResponse(data=a)
|
||||
raise HTTPException(status_code=500,detail='不可以')
|
||||
|
||||
@score_api.put('/Score',summary='成绩更新',description=f'查询条件为学号,班级号,考试序次,考试科目,然后更改这位同学此次科目的成绩')
|
||||
def update_scores(score:ScoreRequest,sid:int,cid:int,num:int,t_subject:int,db=Depends(get_db)):
|
||||
a = score.model_dump(exclude_unset=True,exclude={'id','sid','cid','num','t_subject'})
|
||||
aa = update_scores_dao(sid = sid,cid = cid,num = num,t_subject = t_subject,update_data = a,db=db)
|
||||
if aa==-1:
|
||||
raise HTTPException(status_code=500,detail='没有更新')
|
||||
if aa==0:
|
||||
raise HTTPException(status_code=404,detail='不存在')
|
||||
return {'message':'更新成功','data':a}
|
||||
|
||||
@score_api.delete('/Score',summary='成绩删除',description=f'查询条件为学号,班级号,考试科目,然后进行删除')
|
||||
def delete_scores(sid:int,cid:int,t_subject:int,db=Depends(get_db)):
|
||||
aaa = delete_scores_dao(sid,cid,t_subject,db)
|
||||
if aaa==1:
|
||||
raise HTTPException(status_code=500,detail='删除失败')
|
||||
if aaa==0:
|
||||
raise HTTPException(status_code=404,detail='记录不存在')
|
||||
return {'message':'更新成功','detail':aaa}
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
from scores.model.score_model import Score
|
||||
from datetime import datetime
|
||||
|
||||
def get_scores_dao(s,db):
|
||||
ab = db.query(Score).filter(Score.is_deleted ==0)
|
||||
if s.get('id'):
|
||||
ab = ab.filter(Score.id==s.get('id'))
|
||||
if s.get('sid'):
|
||||
ab = ab.filter(Score.sid==s.get('sid'))
|
||||
if s.get('cid'):
|
||||
ab = ab.filter(Score.cid==s.get('cid'))
|
||||
if s.get('num'):
|
||||
ab = ab.filter(Score.num==s.get('num'))
|
||||
if s.get('score'):
|
||||
ab = ab.filter(Score.score==s.get('score'))
|
||||
if s.get('t_subject'):
|
||||
ab = ab.filter(Score.t_subject==s.get('t_subject'))
|
||||
aa = ab.all()
|
||||
if aa:
|
||||
return [{'id':i.id,'sid':i.sid
|
||||
,'cid':i.cid,'num':i.num
|
||||
,'score': i.score,'t_subject':i.tsub
|
||||
,'create_date':i.create_date,'update_date':i.update_date
|
||||
,'is_deleted': i.is_deleted,'deleted_date': i.deleted_date
|
||||
}for i in aa]
|
||||
else:
|
||||
return []
|
||||
|
||||
def add_scores_dao(b,db):
|
||||
try:
|
||||
aa = db.query(Score).filter(Score.sid==b['sid']
|
||||
,Score.t_subject==b['t_subject']).all()
|
||||
if aa:
|
||||
raise ValueError
|
||||
else:
|
||||
z = Score(**b)
|
||||
db.add(z)
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
print(e)
|
||||
return False
|
||||
else:
|
||||
db.commit()
|
||||
return True
|
||||
|
||||
def update_scores_dao(sid:int,cid:int,num:int,t_subject:int,update_data:dict,db):
|
||||
if not update_data:
|
||||
return 0
|
||||
update_data['update_date']=datetime.now()
|
||||
try:
|
||||
aa = db.query(Score).filter(Score.sid == sid
|
||||
,Score.cid == cid
|
||||
,Score.num == num
|
||||
,Score.t_subject == t_subject ).update(update_data)
|
||||
db.commit()
|
||||
return aa
|
||||
except Exception :
|
||||
db.rollback()
|
||||
return -1
|
||||
|
||||
|
||||
def delete_scores_dao(sid:int,cid:int,t_subject:int,db):
|
||||
try:
|
||||
aaa = db.query(Score).filter(Score.sid ==sid
|
||||
,Score.cid == cid
|
||||
,Score.t_subject == t_subject
|
||||
,Score.is_deleted==0
|
||||
).update({'is_deleted':1
|
||||
,'deleted_date':datetime.now()})
|
||||
db.commit()
|
||||
return aaa
|
||||
except Exception as e :
|
||||
db.rollback()
|
||||
print(e)
|
||||
return -1
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
from sqlalchemy import *
|
||||
from sqlalchemy.orm import declarative_base,sessionmaker
|
||||
|
||||
# 导入.env参数
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv( )
|
||||
DB_USER = os.getenv("DB_USER", "root")
|
||||
DB_PASSWORD = os.getenv("DB_PASSWORD", "")
|
||||
DB_HOST = os.getenv("DB_HOST", "localhost")
|
||||
DB_PORT = os.getenv("DB_PORT", "3306")
|
||||
DB_NAME = os.getenv("DB_NAME", "student_manage_system")
|
||||
|
||||
db_url = f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}?charset=utf8mb4"
|
||||
engine = create_engine(db_url)
|
||||
|
||||
Base = declarative_base()
|
||||
Session = sessionmaker(bind=engine, autoflush = False, autocommit = False)
|
||||
|
||||
def get_db():
|
||||
db = Session()
|
||||
try:
|
||||
yield db
|
||||
finally:
|
||||
db.close()
|
||||
@@ -0,0 +1,17 @@
|
||||
from fastapi import FastAPI,APIRouter
|
||||
from scores.api.score_api import score_api
|
||||
from scores.database import engine,Base
|
||||
|
||||
# 合并接口
|
||||
Scores_API = APIRouter()
|
||||
Scores_API.include_router(score_api)
|
||||
|
||||
# 自测接口
|
||||
app = FastAPI(title='成绩管理系统')
|
||||
app.include_router(score_api)
|
||||
|
||||
Base.metadata.create_all(engine)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import uvicorn
|
||||
uvicorn.run('main:app',host='127.0.0.1',port=12346)
|
||||
@@ -0,0 +1,43 @@
|
||||
from scores.database import Base
|
||||
from datetime import datetime
|
||||
from sqlalchemy import DateTime,Column,Integer,String,Float,ForeignKey
|
||||
|
||||
|
||||
|
||||
class Score(Base):
|
||||
__tablename__='scores'
|
||||
id = Column(Integer
|
||||
,primary_key = True
|
||||
,autoincrement = True
|
||||
,comment ='编号'
|
||||
)
|
||||
sid = Column(Integer
|
||||
,ForeignKey('students.id')
|
||||
,comment ='学生ID'
|
||||
)
|
||||
cid = Column(Integer
|
||||
,ForeignKey('classes.id')
|
||||
,comment ='班级ID'
|
||||
)
|
||||
num = Column(Integer
|
||||
,comment ='考试序次'
|
||||
)
|
||||
score = Column(Integer,nullable = False)
|
||||
t_subject = Column(Integer
|
||||
,ForeignKey('subject.id')
|
||||
,nullable = False
|
||||
)
|
||||
create_date = Column(DateTime
|
||||
,default = datetime.now
|
||||
)
|
||||
update_date = Column(DateTime
|
||||
,default = datetime.now
|
||||
)
|
||||
is_deleted = Column(Integer
|
||||
,default = 0
|
||||
,comment='是否删除: 0-正常,1-已删除'
|
||||
)
|
||||
deleted_date=Column(DateTime
|
||||
,default=None
|
||||
,comment='删除时间'
|
||||
)
|
||||
@@ -0,0 +1,23 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
class ScoreRequest(BaseModel):
|
||||
# id:int
|
||||
sid:int
|
||||
cid:int
|
||||
num:int
|
||||
score:int
|
||||
t_subject:int
|
||||
|
||||
class ScoreQuery(BaseModel):
|
||||
id:int|None = None
|
||||
sid:int|None = None
|
||||
cid:int|None = None
|
||||
num:int|None = None
|
||||
score:int|None = None
|
||||
t_subject:int|None = None
|
||||
|
||||
class ScoreResponse(BaseModel):
|
||||
code:int = 200
|
||||
detail:str = 'OK'
|
||||
totals:int = 0
|
||||
data:str|dict|tuple|list
|
||||
Reference in New Issue
Block a user