Files
drl_2/xuexiao/AGENTS.md
user9994793890 3468394c6c feat: 实现单价分离、班级转课、消课筛选和手动录入功能
Coze-Commit-Type: user
Coze-User-ID: 3722323274763196
Coze-Conversation-ID: 5260473
2026-05-29 10:40:41 +08:00

264 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 学生课程管理系统 (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 | 计算退费金额(预览) |