264 lines
11 KiB
Markdown
264 lines
11 KiB
Markdown
# 学生课程管理系统 (Student Course Management System)
|
||
|
||
## 项目概览
|
||
|
||
基于 Flask + HTML + MySQL/SQLite 的学生课程管理系统,涵盖学员管理、课程管理、班级管理、充值优惠、消课、退费、转课转赠、停课保号、考勤、统计报表、Excel导出、系统权限等全量功能模块。
|
||
|
||
## 技术栈
|
||
|
||
- **后端**: Python 3.12 + Flask + Flask-SQLAlchemy
|
||
- **前端**: Bootstrap 5.3 + Bootstrap Icons + 自定义 CSS/JS
|
||
- **数据库**: 默认 SQLite (开发), 支持 MySQL (通过环境变量切换)
|
||
- **Excel导出**: openpyxl
|
||
- **端口**: 5000
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
/workspace/projects/
|
||
├── app.py # Flask主应用入口(create_app工厂模式)
|
||
├── config.py # 配置文件(数据库连接等)
|
||
├── models.py # SQLAlchemy数据模型(17张表)
|
||
├── utils.py # 工具函数(权限体系/导出/迁移/初始化)
|
||
├── requirements.txt # Python依赖
|
||
├── .coze # Coze配置文件
|
||
├── sql/
|
||
│ └── mysql_tables.sql # MySQL建表脚本(含初始化数据)
|
||
├── routes/ # 模块化路由(Blueprint风格)
|
||
│ ├── __init__.py # 路由注册入口
|
||
│ ├── auth.py # 登录/登出
|
||
│ ├── dashboard.py # 仪表盘首页
|
||
│ ├── student.py # 学员管理+导出
|
||
│ ├── course.py # 课程管理+导出
|
||
│ ├── teacher.py # 老师管理+导出
|
||
│ ├── class_.py # 班级管理+考勤+导出
|
||
│ ├── recharge.py # 充值+优惠活动+API+导出
|
||
│ ├── consumption.py # 消课+导出
|
||
│ ├── refund.py # 退费+API+导出
|
||
│ ├── transfer.py # 转课转赠+导出
|
||
│ ├── stop.py # 停课保号+导出
|
||
│ ├── statistics.py # 统计报表+导出
|
||
│ └── system.py # 用户/角色/日志/课程安排+导出
|
||
├── static/
|
||
│ ├── css/style.css # 自定义样式
|
||
│ └── js/main.js # 自定义JS(Toast/确认框/导出等)
|
||
└── templates/ # Jinja2 HTML模板(30+页面)
|
||
├── base.html # 侧边栏布局基模板(权限过滤)
|
||
├── login.html # 登录页
|
||
├── dashboard.html # 仪表盘首页
|
||
├── student_*.html # 学员管理(列表/表单/详情)
|
||
├── course_*.html # 课程管理
|
||
├── teacher_*.html # 老师管理
|
||
├── class_*.html # 班级管理(列表/表单/详情)
|
||
├── recharge_activity_*.html # 充值优惠活动
|
||
├── recharge_*.html # 充值记录
|
||
├── consumption_*.html # 消课管理(单人/批量)
|
||
├── refund_*.html # 退费管理
|
||
├── transfer_*.html # 转课/转赠
|
||
├── stop_*.html # 停课保号
|
||
├── attendance_*.html # 考勤
|
||
├── statistics.html # 统计报表
|
||
├── schedule_*.html # 课程安排
|
||
├── user_*.html # 用户管理
|
||
├── role_*.html # 角色管理(含权限checkbox分组)
|
||
└── log_list.html # 操作日志
|
||
```
|
||
|
||
## 核心业务规则
|
||
|
||
### 单价计算
|
||
- 新签和续费分开计算,不混在一起
|
||
- 均不含赠课,只核算正课
|
||
- 单价记录在 StudentAccount.unit_price 和 original_price_per_lesson 字段
|
||
|
||
### 学员归属
|
||
- 学员按班级分配,关联授课老师
|
||
- 班级—学员—老师一一对应关系
|
||
- 通过 ClassStudent 表维护班级与学员关系
|
||
- StudentAccount 记录学员所属班级(from_class_id)和授课老师(from_teacher_id)
|
||
|
||
### 消课记录表
|
||
- 表格格式展示消课记录
|
||
- 支持按日期、班级、老师、学员姓名筛选
|
||
- 课时汇总数量手动录入
|
||
- API: /api/class_students/<class_id> 获取班级学员列表
|
||
|
||
### 转课管理
|
||
支持两种转课类型:
|
||
|
||
**1. 班级转课**
|
||
- 无单价变更转课:仅调整学员所属班级与授课老师,原缴费单价、剩余课时保持不变
|
||
- 有单价变更转课:调整班级与老师的同时,同步更新对应计费单价,需备注变更原因及生效时间
|
||
|
||
**2. 课程转课**
|
||
- 转赠:学员之间课时转移(仅正课)
|
||
- 升阶:课程升级,100%正课全额结转
|
||
- 换课:不同课程间的课时转换
|
||
|
||
## 数据模型 (17+张表)
|
||
|
||
| 表名 | 说明 |
|
||
|------|------|
|
||
| roles | 角色表(含permissions字段) |
|
||
| users | 用户表(管理员/老师) |
|
||
| teachers | 老师表 |
|
||
| students | 学员表 |
|
||
| courses | 课程表(含total_hours/material_fee/type/remark) |
|
||
| classes | 班级表 |
|
||
| class_students | 班级学员关联表 |
|
||
| student_accounts | 学员课时账户表(含from_class_id/from_teacher_id关联) |
|
||
| recharge_activities | 充值优惠活动表(累计/期限/团报/老带新) |
|
||
| recharge_records | 充值记录表 |
|
||
| consumption_records | 消课记录表(普通/混合/试听) |
|
||
| refund_records | 退费记录表(材料费/已消核算) |
|
||
| transfer_records | 转课/转赠记录表(含班级转课/单价变更字段) |
|
||
| stop_records | 停课保号记录表 |
|
||
| attendance_records | 考勤记录表 |
|
||
| operation_logs | 操作日志表 |
|
||
| schedules | 课程安排表 |
|
||
|
||
## 构建和运行
|
||
|
||
```bash
|
||
# 安装依赖
|
||
pip3 install -r requirements.txt
|
||
|
||
# 开发环境启动(端口5000)
|
||
python3 app.py
|
||
|
||
# MySQL建表(可选,程序启动时也会自动创建)
|
||
mysql -u root -p < sql/mysql_tables.sql
|
||
```
|
||
|
||
### 自动迁移机制
|
||
|
||
程序启动时会自动执行 `auto_migrate()`,检测 models.py 中定义但数据库中缺失的列,并自动执行 `ALTER TABLE ADD COLUMN`。这意味着:
|
||
- 用 `mysql_tables.sql` 建表后,如果 models.py 新增了字段,**无需手动改表**,重启程序即可自动补齐
|
||
- 对于 MySQL NOT NULL 列,会自动添加合理的默认值
|
||
|
||
## 默认账号
|
||
|
||
- 用户名: `admin`
|
||
- 密码: `admin123`
|
||
|
||
## 数据库切换
|
||
|
||
默认使用SQLite。支持三种数据库模式,通过环境变量 `DB_TYPE` 切换:
|
||
|
||
### 方式1 - 自建MySQL
|
||
|
||
```
|
||
DB_TYPE=mysql
|
||
MYSQL_HOST=127.0.0.1
|
||
MYSQL_PORT=3306
|
||
MYSQL_USER=root
|
||
MYSQL_PASSWORD=your_password
|
||
MYSQL_DB=student_course
|
||
```
|
||
|
||
### 方式2 - 阿里云RDS MySQL
|
||
|
||
```
|
||
DB_TYPE=aliyun_mysql
|
||
ALIYUN_MYSQL_HOST=rm-xxxxx.mysql.rds.aliyuncs.com # RDS内网/外网地址
|
||
ALIYUN_MYSQL_PORT=3306
|
||
ALIYUN_MYSQL_USER=root
|
||
ALIYUN_MYSQL_PASSWORD=your_password
|
||
ALIYUN_MYSQL_DB=student_course
|
||
ALIYUN_MYSQL_SSL=1 # 可选,设为1启用SSL加密连接
|
||
```
|
||
|
||
阿里云RDS连接池已针对RDS特性优化:
|
||
- `pool_recycle=1800` — 低于RDS默认wait_timeout,避免连接被服务端主动断开
|
||
- `pool_pre_ping=True` — 每次取连接前探测存活,防止断连报错
|
||
- `connect_timeout=10` — 建立连接超时10秒
|
||
- SSL连接: 设置 `ALIYUN_MYSQL_SSL=1` 启用,适用于要求加密传输的场景
|
||
|
||
### MySQL兼容性说明
|
||
|
||
- **日期函数**: 代码已兼容SQLite和MySQL,避免使用`strftime`(仅SQLite),改用`>=`范围查询
|
||
- **GROUP BY**: MySQL严格模式下GROUP BY列必须与SELECT列一致,已按`id`分组
|
||
- **db.case**: 使用`db.case((condition, value), else_=0)`兼容SQLAlchemy 2.x
|
||
- **连接池**: MySQL配置了pool_size=10, max_overflow=20, pool_recycle=3600
|
||
- **字符集**: MySQL连接使用charset=utf8mb4
|
||
|
||
## 权限体系
|
||
|
||
### 权限定义 (utils.py - PERMISSIONS字典)
|
||
|
||
共54个权限项,按16个模块分组:
|
||
|
||
| 模块 | 权限项 |
|
||
|------|--------|
|
||
| 学员管理 | student_view, student_add, student_edit, student_delete, student_export |
|
||
| 课程管理 | course_view, course_add, course_edit, course_delete, course_export |
|
||
| 老师管理 | teacher_view, teacher_add, teacher_edit, teacher_delete, teacher_export |
|
||
| 班级管理 | class_view, class_add, class_edit, class_delete, class_export |
|
||
| 充值管理 | recharge_view, recharge_add, recharge_export |
|
||
| 优惠活动 | recharge_activity_view, recharge_activity_add, recharge_activity_edit |
|
||
| 消课管理 | consumption_view, consumption_add, consumption_export |
|
||
| 退费管理 | refund_view, refund_add, refund_export |
|
||
| 转课转赠 | transfer_view, transfer_add, transfer_export |
|
||
| 停课保号 | stop_view, stop_add, stop_export |
|
||
| 考勤管理 | attendance_view, attendance_add, attendance_export |
|
||
| 统计报表 | statistics_view, statistics_export |
|
||
| 课程安排 | schedule_view, schedule_add, schedule_export |
|
||
| 用户管理 | user_view, user_add, user_edit |
|
||
| 角色管理 | role_view, role_add, role_edit |
|
||
| 操作日志 | log_view, log_export |
|
||
|
||
### 权限控制机制
|
||
|
||
1. **角色绑定**: 每个角色(Role)的`permissions`字段存储逗号分隔的权限键(如`student_view,student_export`)
|
||
2. **超级管理员**: 角色名为"超级管理员"或permissions为"all"时,自动拥有所有权限
|
||
3. **User.has_permission()**: 用户对象的权限检查方法,用于模板中`current_user.has_permission('xxx')`
|
||
4. **permission_required装饰器**: 后端路由权限检查,无权限时重定向到dashboard
|
||
5. **侧边栏过滤**: base.html中根据`current_user.has_permission()`控制菜单显示
|
||
6. **导出按钮**: 列表页根据`current_user.has_permission('xxx_export')`控制显示
|
||
|
||
### 角色管理
|
||
|
||
- 在角色编辑页面,权限按模块分组显示为checkbox
|
||
- 支持全选/取消/仅选查看快捷操作
|
||
- 超级管理员角色不可编辑/删除
|
||
|
||
## Excel导出功能
|
||
|
||
所有模块均支持导出Excel,使用openpyxl生成:
|
||
|
||
| 导出路由 | 端点 | 所需权限 |
|
||
|----------|------|----------|
|
||
| /students/export | student_export | student_export |
|
||
| /courses/export | course_export | course_export |
|
||
| /teachers/export | teacher_export | teacher_export |
|
||
| /classes/export | class_export | class_export |
|
||
| /recharge_activities/export | recharge_activity_export | recharge_activity_export |
|
||
| /recharges/export | recharge_export | recharge_export |
|
||
| /consumptions/export | consumption_export | consumption_export |
|
||
| /refunds/export | refund_export | refund_export |
|
||
| /transfers/export | transfer_export | transfer_export |
|
||
| /stops/export | stop_export | stop_export |
|
||
| /statistics/export | statistics_export | statistics_export |
|
||
| /schedules/export | schedule_export | schedule_export |
|
||
| /operation_logs/export | log_export | log_export |
|
||
|
||
导出文件格式: xlsx, 含标题行、表头样式、自动列宽调整。
|
||
|
||
## 核心业务逻辑
|
||
|
||
- **消课规则**: 先扣正课,再扣赠课;试听课不扣课;停课保号期间不可消课
|
||
- **退费规则**: 退费=充值总额-已消课时金额(按原价)-材料费(250元/季度);需扣回赠课
|
||
- **转课规则**: 按剩余金额换算转入课程课时(剩余课时×转出单价÷转入单价)
|
||
- **转赠规则**: 同课程下课时转赠给其他学员
|
||
- **充值优惠**: 自动匹配优惠活动(触发金额/有效期/参与人群/累计充值)
|
||
- **停课保号**: 最长3年,停课期间不可消课,复课后恢复
|
||
|
||
## API接口
|
||
|
||
| 路径 | 方法 | 说明 |
|
||
|------|------|------|
|
||
| /api/student_account/<student_id>/<course_id> | GET | 获取学员课时账户 |
|
||
| /api/student_accounts/<student_id> | GET | 获取学员所有账户 |
|
||
| /api/calculate_recharge | POST | 计算充值优惠(预览) |
|
||
| /api/calculate_refund | POST | 计算退费金额(预览) |
|