# 学生课程管理系统 (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/ 获取班级学员列表 ### 转课管理 支持两种转课类型: **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// | GET | 获取学员课时账户 | | /api/student_accounts/ | GET | 获取学员所有账户 | | /api/calculate_recharge | POST | 计算充值优惠(预览) | | /api/calculate_refund | POST | 计算退费金额(预览) |