别被“培训机构课程报名选课管理系统”这个标题吓到,拆开看其实就是三件事:课程、选课、报名。但真正动手做的时候会发现,难点根本不在功能多少,而在业务角色怎么分、数据怎么串、以及微信小程序生态里那些绕不开的坑。我前后做了两版,第一版是典型的毕设思维,课程表、订单表、用户表一建就开写,结果一到排课冲突和老师端权限就崩。第二版才想明白,这种系统本质上是“排课 + 报名 + 管理”的三角闭环,小程序只是入口,真正的主战场在后台。
这篇文章就把我第二版的完整思路和实现过程拆开讲,从业务角色设计到数据库表结构,再到小程序端和后台管理端的核心代码,最后是微信支付、订阅消息、部署上线这些容易被忽略的环节。你如果是拿来做毕业设计,可以直接照抄这套架构;如果是机构真实要用,我也会把权限控制、课时统计、退课审核这些生产环境才需要的细节一并说清楚。
1. 项目整体设计与思路拆解
1.1 核心需求从哪里开始拆
培训机构业务,不管是少儿编程、成人职场技能还是艺考培训,日常运转都绕不开这几个人:来咨询报名的学员(或者学员家长)、负责卖课和排课的运营/教务老师、真正讲课的授课老师、以及偶尔要看一下数据报表的机构老板。
大多数人设计这类系统时容易犯一个错误——默认只有“管理员”和“用户”两种角色,把所有管理功能都堆在后台。但真实场景里,前端小程序的使用者不仅有学员,还有授课老师。老师需要用手机查看自己的课表、确认上课、标记学员出勤,这些操作如果都要跑回后台操作,教务老师的日常工作会被频繁打断。
于是我在角色设计上做了一个关键拆分:系统分三个端,学员/家长用微信小程序端完成浏览课程、提交报名、在线支付、查看课表;教务管理用后台管理端完成课程上下架、排课、审核报名、退课处理;授课老师有一个简化版的小程序端入口,只看自己的课表和学生名单,做签到确认。
这个拆分的直接好处是权限边界清晰。一位老师登录后台去改课程价格或者调整另一个老师的排课,这类越权操作从产品设计层面就被杜绝了,代码层面只需要按角色校验接口权限就行。
1.2 为什么选了“课程 + 排课 + 订单”三角模型
我第一版失败的原因,是把“课程”和“排课”当成了一张表。课程基础信息确实相对稳定,比如课程名称、适合年龄段、总课时数,但它一旦绑定到具体的上课时间、上课老师、上课教室,就变成了一条独立的业务记录。
举个例子,一套“Python 入门班”课程标准价是 2999 元,每周六上午两个课时,教务老师安排李老师带这个班,教室是 A03。一周后招生火爆,又开了一个周六下午的新班,还是李老师带,但换成了 A05 教室。如果课程和排课是一张表,数据会冗余得没法维护;分开了就清爽得多:课程表只存课程本身的信息,排课表每条记录 = 课程 + 具体时间段 + 老师 + 教室 + 剩余名额。
订单表则是连接学员和排课记录的桥梁。一个学员可以一次性报一个学期的课,也可以单次报名某一节体验课,订单明细里记录的是“哪个排课班级”,这样退课、转班、补课才有据可依。
这个模型想清楚之后,后面所有接口的设计都顺了。学员端看到课程详情页时,其实展示的是某个排课班级的信息,包括剩余名额、上课时间、授课老师介绍,不再是笼统的课程介绍。
1.3 技术选型没有用“最热”的,而是用“最顺”的
朋友圈里不少人做小程序后端喜欢直接用微信云开发,确实省事,数据库、存储、云函数一步到位。但我建议对这个项目谨慎一点,原因有二:数据模型复杂之后,云开发的数据库查询能力和索引机制在联表查询和统计报表场景下会比较别扭;另外你以后想把系统迁移到自己的服务器,或者接入第三方的教务硬件(比如人脸识别考勤机),云开发迁移成本会很高。
我更推荐常规方案:后端用 Python 写,小程序端用原生微信小程序(或者 uni-app 也可以),数据存储用 MySQL,后端框架用 Django REST Framework 或者 Flask + SQLAlchemy 都可以。我这次用的是 Django REST Framework,理由很实在:Django 自带的 Admin 后台可以直接当教务管理端用,省去一大块后台前端开发工作量;它的 ORM 做课程、排课这类复杂关系查询很顺手;用户认证和权限体系成熟,不需要自己造轮子。
当然,如果你后台管理端想做得更灵活、界面更好看,可以用 Vue + Element Plus 单独搭一个管理后台,Django 只作为 API 服务。我在第二版就是这么做的,后面会讲原因。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心细节解析与实操要点
2.1 数据库表结构设计是这整套系统的地基
先给出一份我反复调整后的核心表结构设计,比直接列建表 SQL 更有参考价值。
学员用户表(StudentProfile)除了微信用户的 openid、昵称、头像外,关键字段有:学员姓名、年龄、家长手机号、剩余课时数、报名来源。这个“剩余课时数”是冗余字段,从订单和退课记录里理论上可以算出来,但真实场景里课时数被查询的频率太高,每次实时计算会对数据库造成很大压力,所以我在每次报名成功、退课成功、老师标记出勤时都会同步维护这个字段。
课程表(Course):课程名称、课程分类(编程/美术/舞蹈等)、适合年龄段、课程简介、封面图、总课时数、标准价格、状态。状态字段我习惯命名 status,有两种值,上架和下架。
排课班级表(CourseSchedule):这表是排课管理的核心。外键关联课程 ID,字段包括班级名称(如“Python 入门周六上午班”)、上课星期、开始时间、结束时间、开课日期、结课日期、授课老师 ID、教室、人数上限、已报名人数、当前状态。注意,上课星期、时间段、教室这些字段不能做成分散表——一个排课班级一周只上一次课,这是绝大多数培训机构的基本设定,不用过度设计成每周多天的复杂模式。
订单表(Order):订单号、学员用户 ID、关联的排课班级 ID、支付金额、支付状态、支付时间、订单类型(新报名/续费/退课)、退课状态、退课原因、审核人、审核时间。订单号我建议用“日期 + 随机数”的方式生成,别用数据库自增 ID,因为自增 ID 容易被猜到,产生无关的数据暴露风险,而且微信支付回调对订单号也有要求。
选课记录表(Enrollment):这个表容易被人忽略但它非常关键,记录学员和排课班级之间的状态变化。字段包括学员、排课班级、报名时间、课时数变动、状态(在学/结课/退课)。很多需求里要查“一个学员报过哪些班”“一个班有多少学员在学”,都要靠这张关联表,比直接查订单表语义更清晰。
课时/出勤表(Attendance):授课老师标记出勤的记录。一个班级的某节课,有哪些学员出勤,谁请假了,谁旷课了。老师在手机端确认这节课上完之后,系统会按出勤情况扣减学员剩余课时。
2.2 微信登录的 code 换 session 流程别踩坑
小程序端登录是几乎所有微信小程序开发的第一步,也是初次接触时最常见的一个“看起来简单但很啰嗦”的环节。流程是固定的:小程序端调用 wx.login 获取一个临时 code,然后把 code 发给后端
