项目介绍
随着高等教育规模的不断扩大,学生信息管理工作日益繁重,传统的手工管理或基于单机应用的管理方式已难以满足现代高校对信息化管理的需求。为解决学生信息管理效率低下、数据可视化能力不足等问题,本文设计并实现了一套基于 B/S 架构的学生信息管理系统。
本系统采用前后端分离的开发模式,前端使用 Vue 3 框架结合 Element Plus 组件库和 ECharts 数据可视化库进行开发,后端使用 Python Flask 框架提供 RESTful API 接口,数据库采用 MySQL 8.0 进行数据持久化存储。系统实现了用户认证与授权、学生信息管理、班级信息管理、数据统计可视化等核心功能模块。在用户认证方面,采用 JWT(JSON Web Token)机制实现无状态的身份验证;在数据展示方面,利用 ECharts 图表库实现了性别比例饼图、班级人数柱状图、年龄分布图、注册趋势折线图及班级男女比例堆叠图等多维度的数据可视化功能。
经过系统测试表明,本系统功能完善、运行稳定、界面友好、操作便捷,能够有效提升学生信息管理的工作效率和数据分析能力,具有较好的实用价值和推广意义。
系统展示






核心代码
""" 学生信息管理系统 - Flask 后端 """
from flask import Flask, request, jsonify
from flask_cors import CORS
from flask_sqlalchemy SQLAlchemy
datetime datetime, timedelta, timezone
functools wraps
jwt
app = Flask(__name__)
app.config[] =
app.config[] =
app.config[] =
app.config[] =
CORS(app, supports_credentials=)
db = SQLAlchemy(app)
(db.Model):
__tablename__ =
= db.Column(db.Integer, primary_key=, autoincrement=)
username = db.Column(db.String(), unique=, nullable=)
password = db.Column(db.String(), nullable=)
nickname = db.Column(db.String())
avatar = db.Column(db.String())
created_at = db.Column(db.DateTime, default=datetime.now)
updated_at = db.Column(db.DateTime, default=datetime.now, onupdate=datetime.now)
(db.Model):
__tablename__ =
= db.Column(db.Integer, primary_key=, autoincrement=)
name = db.Column(db.String(), nullable=)
code = db.Column(db.String(), unique=, nullable=)
description = db.Column(db.String())
created_at = db.Column(db.DateTime, default=datetime.now)
updated_at = db.Column(db.DateTime, default=datetime.now, onupdate=datetime.now)
students = db.relationship(, backref=, lazy=)
(db.Model):
__tablename__ =
= db.Column(db.Integer, primary_key=, autoincrement=)
student_no = db.Column(db.String(), unique=, nullable=)
name = db.Column(db.String(), nullable=)
gender = db.Column(db.SmallInteger, default=)
age = db.Column(db.Integer)
phone = db.Column(db.String())
email = db.Column(db.String())
address = db.Column(db.String())
class_id = db.Column(db.Integer, db.ForeignKey())
created_at = db.Column(db.DateTime, default=datetime.now)
updated_at = db.Column(db.DateTime, default=datetime.now, onupdate=datetime.now)
():
():
auth_header = request.headers.get(, )
token = auth_header.replace(, ) auth_header.startswith()
token:
jsonify({: , : }),
:
data = jwt.decode(token, app.config[], algorithms=[])
current_user = db.session.get(User, data[])
current_user:
jsonify({: , : }),
jwt.ExpiredSignatureError:
jsonify({: , : }),
jwt.InvalidTokenError:
jsonify({: , : }),
f(current_user, *args, **kwargs)
decorated
():
jsonify({: , : message, : data})
():
jsonify({: code, : message}), code
():
data = request.get_json()
username = data.get(, ).strip()
password = data.get(, ).strip()
username password:
error()
user = User.query.filter_by(username=username).first()
user user.password != password:
error()
token = jwt.encode({
: user.,
: datetime.now(timezone.utc) + timedelta(hours=)
}, app.config[], algorithm=)
success({
: token,
: {
: user.,
: user.username,
: user.nickname,
: user.avatar
}
}, )
():
success({
: current_user.,
: current_user.username,
: current_user.nickname,
: current_user.avatar
})
():
page = request.args.get(, , =)
per_page = request.args.get(, , =)
keyword = request.args.get(, ).strip()
query = Clazz.query
keyword:
query = query.(
db.or_(
Clazz.name.like(),
Clazz.code.like()
)
)
per_page == -:
classes = query.order_by(Clazz..asc()).()
success({
: [{
: c.,
: c.name,
: c.code,
: c.description,
: (c.students),
: c.created_at.strftime() c.created_at
} c classes],
: (classes)
})
pagination = query.order_by(Clazz..desc()).paginate(page=page, per_page=per_page, error_out=)
success({
: [{
: c.,
: c.name,
: c.code,
: c.description,
: (c.students),
: c.created_at.strftime() c.created_at
} c pagination.items],
: pagination.total,
: page,
: per_page
})
():
data = request.get_json()
name = data.get(, ).strip()
code = data.get(, ).strip()
description = data.get(, ).strip()
name code:
error()
Clazz.query.filter_by(code=code).first():
error()
clazz = Clazz(name=name, code=code, description=description)
db.session.add(clazz)
db.session.commit()
success(message=)
():
clazz = db.session.get(Clazz, class_id)
clazz:
error(, )
data = request.get_json()
name = data.get(, ).strip()
code = data.get(, ).strip()
name code:
error()
existing = Clazz.query.(Clazz.code == code, Clazz. != class_id).first()
existing:
error()
clazz.name = name
clazz.code = code
clazz.description = data.get(, ).strip()
db.session.commit()
success(message=)
():
clazz = db.session.get(Clazz, class_id)
clazz:
error(, )
(clazz.students) > :
error()
db.session.delete(clazz)
db.session.commit()
success(message=)
():
page = request.args.get(, , =)
per_page = request.args.get(, , =)
keyword = request.args.get(, ).strip()
class_id = request.args.get(, =)
query = Student.query
keyword:
query = query.(
db.or_(
Student.name.like(),
Student.student_no.like(),
Student.phone.like()
)
)
class_id:
query = query.filter_by(class_id=class_id)
pagination = query.order_by(Student..desc()).paginate(page=page, per_page=per_page, error_out=)
success({
: [{
: s.,
: s.student_no,
: s.name,
: s.gender,
: s.age,
: s.phone,
: s.email,
: s.address,
: s.class_id,
: s.clazz.name s.clazz ,
: s.created_at.strftime() s.created_at
} s pagination.items],
: pagination.total,
: page,
: per_page
})
():
data = request.get_json()
student_no = data.get(, ).strip()
name = data.get(, ).strip()
student_no name:
error()
Student.query.filter_by(student_no=student_no).first():
error()
student = Student(
student_no=student_no,
name=name,
gender=data.get(, ),
age=data.get(),
phone=data.get(, ).strip(),
email=data.get(, ).strip(),
address=data.get(, ).strip(),
class_id=data.get()
)
db.session.add(student)
db.session.commit()
success(message=)
():
student = db.session.get(Student, student_id)
student:
error(, )
data = request.get_json()
student_no = data.get(, ).strip()
name = data.get(, ).strip()
student_no name:
error()
existing = Student.query.(Student.student_no == student_no, Student. != student_id).first()
existing:
error()
student.student_no = student_no
student.name = name
student.gender = data.get(, )
student.age = data.get()
student.phone = data.get(, ).strip()
student.email = data.get(, ).strip()
student.address = data.get(, ).strip()
student.class_id = data.get()
db.session.commit()
success(message=)
():
student = db.session.get(Student, student_id)
student:
error(, )
db.session.delete(student)
db.session.commit()
success(message=)
():
sqlalchemy func, extract
student_count = Student.query.count()
class_count = Clazz.query.count()
male_count = Student.query.filter_by(gender=).count()
female_count = Student.query.filter_by(gender=).count()
classes = Clazz.query.()
class_distribution = [{: c.name, : (c.students)} c classes]
class_gender_distribution = []
c classes:
male = ( s c.students s.gender == )
female = ( s c.students s.gender == )
class_gender_distribution.append({: c.name, : male, : female})
students = Student.query.()
age_groups = {}
s students:
s.age :
age = s.age
age < :
key =
age <= :
key =
age <= :
key =
age <= :
key =
:
key =
age_groups[key] = age_groups.get(key, ) +
age_order = [, , , , ]
age_distribution = [{: k, : age_groups.get(k, )} k age_order]
now = datetime.now()
monthly_trend = []
i (, -, -):
month_offset = now.month - i
year = now.year
month_offset <= :
month_offset +=
year -=
month = month_offset
count = Student.query.(extract(, Student.created_at) == year, extract(, Student.created_at) == month).count()
monthly_trend.append({: , : count})
success({
: student_count,
: class_count,
: male_count,
: female_count,
: class_distribution,
: class_gender_distribution,
: age_distribution,
: monthly_trend
})
__name__ == :
app.run(debug=, host=, port=)


