基于React+Flask的班级积分管理系统
一个基于React + Flask的班级积分管理系统,支持班级管理、学生积分跟踪、兑换物品管理、排行榜展示等功能。
项目地址:https://github.com/atuo-200/classMaster
安装与运行
后端
cd backend
pip install -r requirements.txt
python app.py
前端
cd frontend
npm install
npm start
一键式运行
在安装好后端(pip install -r requirements.txt)及前端所需依赖包(npm install)之后,也可双击项目文件夹里的start.bat运行该项目,班级积分管理页面会自动打开。
使用说明
1.班级管理
- 创建班级:快速创建新的班级。
- 批量导入学生名单:点击“下载模板”下载Excel模板文件,填写学生学号、姓名,然后点击“导入学生”上传填写好的学生名单文件,即可完成导入。
- 删除班级:安全删除班级(为防止误触,需要密钥验证,密钥默认为123456,如需修改可在项目文件夹下的backend\app.py中修改app.config[‘SECRET_KEY’]字段)。
- 班级列表:查看所有班级及学生数量统计。
2.学生管理
学生列表:查看班级学生信息及积分状态
单个添加/删除学生:支持手动添加单个学生信息以及手动删除单个学生信息。
加分/扣分:可为每个学生加扣分,可默认加/扣1分,或者根据“加/扣分规则”中设置的规则来进行加/扣分。
兑换奖品:可根据学生的兑换币数量为其兑换奖品,需要在“兑换设置”中设置兑奖的项目。
3.加/扣分规则管理
为加/扣分添加、编辑、删除规则。
4.兑换设置
设置兑奖项目:名称、描述以及所需兑换币数量等。
5.段位管理
设置段位名称、段位代表颜色、所需积分区间等等。以下是简单的段位设置参考:
段位名称 | 积分区间 | 段位描述 |
---|---|---|
最强学霸 | 180~200分 | 每节课近乎满分,额外挑战全部完成! |
荣耀学尊 | 160~179分 | 稳定高效完成任务,积极参与所有环节 |
永恒钻石 | 140~159分 | 作业全勤+高质量,纪律优异,主动回答问题 |
尊贵铂金 | 110~139分 | 按时完成任务,遵守纪律,偶尔回答问题(达标中上水平) |
荣耀黄金 | 80~109分 | 基础任务完成,纪律合格(中等努力即可达到) |
秩序白银 | 50~79分 | 缺勤部分任务或纪律分,需加强参与 |
倔强青铜 | 20~49分 | 任务漏交较多,课堂参与度低 |
6.排行榜
积分排行榜、兑换币排行榜、段位统计数据实时显示。
7.随机点名
随机从班级中抽取学生。
开发说明
技术栈
前端:React + TypeScript + Ant Design
后端:Flask + SQLAlchemy + SQLite
文件处理:openpyxl (Excel处理)
数据库数据模型
1. 班级表(Class)
字段名 | 类型 | 是否必填 | 默认值 | 说明 |
---|---|---|---|---|
id | Integer | 是 | - | 主键 |
name | String(100) | 是 | - | 班级名称 |
created_at | DateTime | 否 | 当前时间 | 创建时间 |
2.学生表(Student)
字段名 | 类型 | 是否必填 | 默认值 | 说明 |
---|---|---|---|---|
id | Integer | 是 | - | 主键 |
name | String(100) | 是 | - | 学生姓名 |
student_id | String(50) | 是 | - | 学号 |
points | Integer | 否 | 0 | 当前积分 |
exchange_coins | Integer | 否 | 0 | 可兑换的硬币数 |
class_id | Integer | 是 | - | 所属班级ID |
created_at | DateTime | 否 | 当前时间 | 创建时间 |
3. 兑换物品表(ExchangeItem)
字段名 | 类型 | 是否必填 | 默认值 | 说明 |
---|---|---|---|---|
id | Integer | 是 | - | 主键 |
name | String(100) | 是 | - | 物品名称 |
description | Text | 否 | - | 物品描述 |
coins_required | Integer | 是 | - | 所需硬币数 |
created_at | DateTime | 否 | 当前时间 | 创建时间 |
4. 积分历史记录表(PointHistory)
字段名 | 类型 | 是否必填 | 默认值 | 说明 |
---|---|---|---|---|
id | Integer | 是 | - | 主键 |
student_id | Integer | 是 | - | 学生ID |
operation_type | String(20) | 是 | - | 操作类型 |
points_change | Integer | 否 | 0 | 积分变化量 |
coins_change | Integer | 否 | 0 | 硬币变化量 |
description | String(200) | 否 | - | 操作描述 |
created_at | DateTime | 否 | 当前时间 | 创建时间 |
5. 积分规则表(PointRule)
字段名 | 类型 | 是否必填 | 默认值 | 说明 |
---|---|---|---|---|
id | Integer | 是 | - | 主键 |
name | String(100) | 是 | - | 规则名称 |
points_change | Integer | 是 | - | 积分变化量(正负值表示加减) |
rule_type | String(20) | 是 | - | 规则类型(add/subtract) |
is_active | Boolean | 否 | True | 是否启用 |
created_at | DateTime | 否 | 当前时间 | 创建时间 |
6.段位表(Rank)
字段名 | 类型 | 是否必填 | 默认值 | 说明 |
---|---|---|---|---|
id | Integer | 是 | - | 主键 |
name | String(100) | 是 | - | 段位名称 |
min_points | Integer | 是 | - | 最低积分要求 |
max_points | Integer | 是 | - | 最高积分限制 |
description | Text | 否 | - | 段位描述 |
color | String(20) | 否 | #1890ff | 段位颜色 |
sort_order | Integer | 否 | 0 | 排序顺序 |
is_active | Boolean | 否 | True | 是否启用 |
created_at | DateTime | 否 | 当前时间 | 创建时间 |
后端API接口
1.班级管理API
路由 | 方法 | 描述 | 参数 | 返回值 |
---|---|---|---|---|
/api/classes |
GET | 获取所有班级列表 | 无 | 班级数组(含学生数) |
/api/classes |
POST | 创建新班级 | {name: string} | 新班级详情 |
/api/classes/<int:class_id> |
DELETE | 删除班级(需SECRET_KEY) | 无 | 删除结果 |
/api/classes/<int:class_id>/students/template |
GET | 下载学生名单模板 | 无 | Excel文件 |
/api/classes/<int:class_id>/students/import |
POST | 导入学生名单 | .xlsx文件 | 导入结果 |
/api/classes/<int:class_id>/students |
GET | 获取班级学生列表 | 无 | 学生数组(含段位) |
/api/classes/<int:class_id>/students |
POST | 添加单个学生 | {name, student_id} | 新学生详情 |
/api/classes/<int:class_id>/leaderboard |
GET | 获取班级排行榜 | 无 | 积分榜/硬币榜/段位统计 |
2.学生管理API
路由 | 方法 | 描述 | 参数 | 返回值 |
---|---|---|---|---|
/api/students/<int:student_id> |
DELETE | 删除学生 | 无 | 删除结果 |
/api/students/<int:student_id>/points |
POST | 更新学生积分 | {operation, [points_change], [description]} | 更新后学生数据 |
3.兑换物品API
路由 | 方法 | 描述 | 参数 | 返回值 |
---|---|---|---|---|
/api/exchange-items |
GET | 获取所有兑换物品 | 无 | 物品数组 |
/api/exchange-items |
POST | 创建兑换物品 | {name, coins_required} | 新物品详情 |
/api/exchange-items/<int:item_id> |
PUT | 更新兑换物品 | {[name], [description], [coins_required]} | 更新后物品 |
/api/exchange-items/<int:item_id> |
DELETE | 删除兑换物品 | 无 | 删除结果 |
4.积分规则API
路由 | 方法 | 描述 | 参数 | 返回值 |
---|---|---|---|---|
/api/point-rules |
GET | 获取所有积分规则 | 无 | 规则数组 |
/api/point-rules |
POST | 创建积分规则 | {name, points_change, rule_type} | 新规则详情 |
/api/point-rules/<int:rule_id> |
PUT | 更新积分规则 | {[name], [points_change], [rule_type]} | 更新后规则 |
/api/point-rules/<int:rule_id> |
DELETE | 删除积分规则 | 无 | 删除结果 |
5.段位管理API
路由 | 方法 | 描述 | 参数 | 返回值 |
---|---|---|---|---|
/api/ranks |
GET | 获取所有段位 | 无 | 段位数组(排序后) |
/api/ranks |
POST | 创建新段位 | {name, min_points, max_points} | 新段位详情 |
/api/ranks/<int:rank_id> |
PUT | 更新段位信息 | {[name], [min_points], [max_points], …} | 更新后段位 |
/api/ranks/<int:rank_id> |
DELETE | 删除段位 | 无 | 删除结果 |
前端项目结构
frontend/src/
├── components/ # 通用组件
│ └── Layout.tsx # 主布局组件
├── pages/ # 页面组件
│ ├── ClassManagement.tsx # 班级管理页面
│ ├── StudentManagement.tsx # 学生管理页面
│ ├── Leaderboard.tsx # 排行榜页面
│ ├── RandomCall.tsx # 随机点名页面
│ ├── ExchangeSettings.tsx # 兑换设置页面
│ ├── PointRules.tsx # 积分规则页面
│ └── RankManagement.tsx # 段位管理面
├── services/ # API服务
│ └── api.ts # API接口封装
├── App.tsx # 应用入口
├── App.css # 应用样式
├── index.tsx # 渲染入口
└── index.css # 全局样式
前端核心组件详解
1. Layout 布局组件
文件位置:components/Layout.tsx
描述:
- 提供应用的整体布局结构
- 支持菜单高亮显示当前页面
- 包含侧边导航栏和主内容区域
- 支持侧边栏折叠/展开功能
主要特性:
interface LayoutProps {
children: React.ReactNode;
}
const AppLayout: React.FC<LayoutProps> = ({ children }) => {
const [collapsed, setCollapsed] = useState(false);
// ...
}
2. ClassManagement 班级管理组件
文件位置:pages/ClassManagement.tsx
描述:
- 班级的增删改查操作(删除班级需要验证密钥)
- 班级导航(跳转到学生管理和排行榜)
- 学生名单的批量导入(Excel模板下载和文件上传)
状态管理:
const [classes, setClasses] = useState<Class[]>([]);
const [loading, setLoading] = useState(false);
const [modalVisible, setModalVisible] = useState(false);
const [className, setClassName] = useState('');
3. StudentManagement 学生管理组件
文件位置:pages/StudentManagement.tsx
描述:
- 单个学生信息的增删改查
- 积分操作(加分/扣分/兑换)
- 根据学生积分显示段位
状态管理:
const [students, setStudents] = useState<Student[]>([]);
const [exchangeItems, setExchangeItems] = useState<ExchangeItem[]>([]);
const [pointRules, setPointRules] = useState<PointRule[]>([]);
const [operationModalVisible, setOperationModalVisible] = useState(false);
4. RandomCall 随机点名组件
文件位置:pages/RandomCall.tsx
描述:
- 轮盘式随机选择学生
- 选中学生的积分操作
轮盘动画实现:
const spinWheel = () => {
const randomIndex = Math.floor(Math.random() * students.length);
const segmentAngle = 360 / students.length;
const targetAngle = randomIndex * segmentAngle + segmentAngle / 2;
const finalRotation = rotation + (360 * extraRotations) + (360 - targetAngle);
setRotation(finalRotation);
};
5. Leaderboard 排行榜组件
文件位置:pages/Leaderboard.tsx
描述:
- 积分排行榜展示
- 兑换币排行榜展示
- 前三名特殊图标显示
- 段位统计
数据展示:
interface LeaderboardData {
points_leaderboard: Student[];
coins_leaderboard: Student[];
rank_statistics: RankStatistic[];
}
API 服务层设计
文件位置:services/api.ts
描述:
- 统一的 API 基础配置
- 按功能模块分组 API 方法
API 分组:
// 班级相关API
export const classApi = {
getClasses: () => api.get('/classes'),
createClass: (name: string) => api.post('/classes', { name }),
// ...
};
// 学生相关API
export const studentApi = {
updatePoints: (studentId: number, operation: string, description?: string) =>
api.post(`/students/${studentId}/points`, { operation, description }),
};
// 兑换项目相关API
export const exchangeApi = {
getItems: () => api.get('/exchange-items'),
// ...
};