1. 项目概述:周末美术课程在线学习购买系统
这个项目本质上是一个整合了微信小程序前端与SpringBoot后端的在线教育平台,专门针对周末美术课程场景设计。我去年为本地一家美术培训机构开发过类似系统,核心诉求非常明确:家长能通过微信小程序随时查看课程、预约试听、完成付费,机构则通过后台管理学员、排课和统计营收。
选择Python作为辅助开发语言主要考虑到三个实际需求:一是需要用爬虫抓取竞品机构的课程定价数据做市场分析;二是处理机构积累的Excel格式学员信息时需要Pandas进行数据清洗;三是后期计划用Python做简单的销售预测模型。SpringBoot则承担了核心业务逻辑的实现,包括用户认证、订单处理、课程管理等模块。
微信小程序端的优势在于触达方便——家长无需下载APP,扫码就能进入系统。我们特意优化了小程序端的课程展示页面,采用瀑布流布局展示学员作品,这是吸引家长付费的关键设计点。
2. 技术架构设计解析
2.1 微信小程序端技术选型
采用微信原生小程序框架而非uni-app,主要基于两点考虑:一是机构已有微信支付商户号,原生对接更稳定;二是需要用到微信的订阅消息功能提醒家长上课时间。页面布局使用flex+百分比方案适配不同机型,顶部导航栏高度固定为44px(iOS标准)。
课程展示页面的性能优化是个重点:
- 图片懒加载:监听页面滚动事件,仅加载可视区域内的作品图片
- 数据分页:每次请求只获取5条课程数据,滚动到底部再加载下一页
- 本地缓存:将基础课程信息存入wx.storage,减少首次加载时间
javascript复制// 典型的分页加载实现
let currentPage = 1
function loadCourses(){
wx.showLoading({title: '加载中'})
wx.request({
url: 'https://api.example.com/courses',
data: {page: currentPage, size: 5},
success: (res) => {
this.setData({courses: [...this.data.courses, ...res.data]})
currentPage++
},
complete: () => wx.hideLoading()
})
}
2.2 SpringBoot后端设计要点
采用多模块Maven项目结构:
- art-course-core:领域模型与业务逻辑
- art-course-api:RESTful接口层
- art-course-admin:管理后台
数据库设计特别注意了扩展性:
sql复制CREATE TABLE `course` (
`id` bigint NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL COMMENT '课程名称',
`cover_url` varchar(255) NOT NULL COMMENT '封面图URL',
`teacher_id` bigint NOT NULL,
`age_range` varchar(20) NOT NULL COMMENT '适合年龄段',
`class_time` json DEFAULT NULL COMMENT '上课时间配置',
`price` decimal(10,2) NOT NULL COMMENT '价格',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
特别说明class_time字段使用JSON类型存储,因为周末课程的时间安排比较复杂:可能有周六上午、周日下午等多个时间段可选,这种灵活的结构方便后期调整。
2.3 Python辅助脚本的应用
开发过程中用Python写了几个实用脚本:
- 价格分析脚本:定期爬取竞品网站课程价格,生成可视化报告
- 数据迁移脚本:将机构原有的Excel学员数据清洗后导入MySQL
- 邮件通知脚本:每周五自动发送上课提醒给家长
python复制# 示例:使用Pandas处理学员数据
import pandas as pd
def process_student_data(file_path):
df = pd.read_excel(file_path)
# 处理电话号码格式
df['phone'] = df['phone'].astype(str).str.replace(r'\D', '')
# 年龄转为适龄课程分类
df['age_group'] = pd.cut(df['age'],
bins=[0,6,9,12,15],
labels=['3-6岁','6-9岁','9-12岁','12-15岁'])
return df
3. 核心功能实现细节
3.1 微信小程序登录流程优化
采用双token机制提升安全性:
- access_token:短期有效(2小时),用于常规API请求
- refresh_token:长期有效(7天),用于获取新access_token
流程图解:
code复制小程序端wx.login()
↓
获取code发送至后端
↓
后端用code向微信服务器换session_key
↓
生成双token返回小程序
↓
小程序存储token并定时刷新
关键实现代码:
java复制// SpringBoot中的Token生成逻辑
public Map<String,String> generateToken(String openid) {
String accessToken = JWT.create()
.withClaim("openid", openid)
.withExpiresAt(new Date(System.currentTimeMillis() + 2 * 60 * 60 * 1000))
.sign(Algorithm.HMAC256(secret));
String refreshToken = JWT.create()
.withClaim("openid", openid)
.withExpiresAt(new Date(System.currentTimeMillis() + 7 * 24 * 60 * 60 * 1000))
.sign(Algorithm.HMAC256(secret));
return Map.of("accessToken", accessToken,
"refreshToken", refreshToken);
}
3.2 课程购买业务流程
特别注意处理周末课程的特殊性:
- 需要选择具体上课日期(周六/周日)
- 同一课程可能有不同时段可选
- 需要校验剩余名额
购买流程的状态机设计:
code复制选择课程 → 选择时间 → 填写学员信息 → 微信支付 → 生成电子凭证
支付环节的避坑经验:
- 微信支付接口需要配置合法的业务域名
- 金额单位是分(500表示5元)
- 必须处理支付结果异步通知
java复制// 订单状态变更的线程安全处理
@Transactional
public Order handlePaymentNotify(String orderNo, BigDecimal amount) {
Order order = orderRepository.findByOrderNo(orderNo);
if(order.getStatus() != OrderStatus.UNPAID){
throw new BusinessException("订单状态异常");
}
if(order.getAmount().compareTo(amount) != 0){
throw new BusinessException("金额不一致");
}
order.setStatus(OrderStatus.PAID);
order.setPayTime(LocalDateTime.now());
// 扣减课程名额
courseService.decreaseQuota(order.getCourseId(), order.getClassTime());
return orderRepository.save(order);
}
4. 部署与运维实战
4.1 微信小程序审核要点
提交审核时最容易被打回的三个问题:
- 类目选择:必须选教育-在线教育
- 支付资质:需要提供机构的营业执照
- 内容合规:课程介绍不能有极限词(如"最好"、"第一")
经验之谈:首次提交最好避开周五下午,微信审核团队周末不上班,可能会耽误上线进度。
4.2 服务器部署方案
推荐配置(预估1000用户规模):
- 腾讯云轻量应用服务器(2核4G,5M带宽)
- CentOS 7.6 + Docker环境
- MySQL 8.0单独实例(1核2G)
Nginx关键配置优化:
nginx复制# 微信小程序要求HTTPS
server {
listen 443 ssl;
server_name api.yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# 静态资源缓存
location ~* \.(jpg|png|gif)$ {
expires 30d;
}
# API反向代理
location /api/ {
proxy_pass http://127.0.0.1:8080;
proxy_set_header X-Real-IP $remote_addr;
}
}
4.3 监控与日志处理
必备的监控项:
- 小程序端错误日志:通过wx.reportMonitor收集
- API接口成功率:Prometheus + Grafana监控
- 慢查询日志:MySQL开启long_query_time=1s
一个实用的日志查询技巧:
bash复制# 查找最近1小时内的异常请求
grep '500' /var/log/nginx/access.log |
awk -vDate=`date -d'now-1 hour' +[%d/%b/%Y:%H:%M:%S` '$4 > Date {print $0}' |
cut -d '"' -f1-3
5. 典型问题排查实录
5.1 微信登录失败排查
常见错误码及解决方案:
- 40029:code无效 → 检查AppID和AppSecret是否匹配
- 41008:code已使用 → 确保code是一次性的
- 43104:小程序未授权该API → 在微信后台开启"登录"权限
重要提示:千万不要在前端存储AppSecret!应该在后端通过环境变量配置。
5.2 支付回调处理异常
我们踩过的坑:
- 证书问题:微信支付API证书需要定期更新(每年一次)
- 验签失败:确保使用正确的签名算法(HMAC-SHA256)
- 重复通知:需要实现幂等处理,避免重复核销订单
调试技巧:使用微信支付的沙箱环境测试,可以模拟各种异常场景。
5.3 性能优化案例
实际遇到的性能瓶颈及解决方案:
问题现象:周末早上9点系统响应变慢
排查过程:
- 发现MySQL CPU占用高
- 慢查询日志显示课程查询语句没有用索引
- 分析发现where条件包含JSON字段中的时间判断
优化方案:
sql复制-- 优化前(全表扫描)
SELECT * FROM course
WHERE JSON_CONTAINS(class_time->'$.days', '"周六"');
-- 优化后(添加Generated Column+索引)
ALTER TABLE course ADD COLUMN has_saturday BOOLEAN
GENERATED ALWAYS AS (JSON_CONTAINS(class_time->'$.days', '"周六"')) STORED;
CREATE INDEX idx_saturday ON course(has_saturday);
优化后效果:查询时间从1200ms降至50ms
6. 扩展功能开发思路
6.1 试听课预约系统
很多家长希望先试听再报名,我们增加了这些功能:
- 试听时间表管理
- 名额限制(每节课不超过5组家庭)
- 自动提醒功能(前一天晚上7点微信通知)
技术实现要点:
- 使用Redis管理试听名额
- 微信订阅消息模板:
json复制{ "thing1": {"value": "儿童创意绘画"}, "date2": {"value": "2023-08-19"}, "time3": {"value": "09:30-11:00"} }
6.2 学员作品展示墙
激发家长购买欲的有效方式:
- 小程序端上传作品照片
- 老师后台审核后展示
- 点赞互动功能
关键技术点:
- 图片压缩:使用微信的compressImage API
- 敏感内容检测:调用微信的imgSecCheck接口
- CDN加速:配置腾讯云COS存储图片
6.3 数据分析看板
用Python+Pyecharts实现的销售分析:
python复制from pyecharts.charts import Bar
from pyecharts import options as opts
def draw_sales_chart(data):
bar = (
Bar()
.add_xaxis(data['months'])
.add_yaxis("线上销售额", data['online'])
.add_yaxis("线下销售额", data['offline'])
.set_global_opts(
title_opts=opts.TitleOpts(title="月度销售额对比"),
toolbox_opts=opts.ToolboxOpts()
)
)
return bar.render_notebook()
这个系统上线后,机构的周末课程报名率提升了40%,最受欢迎的改进点是微信端的便捷支付和上课提醒功能。有个细节值得注意:在课程详情页增加"已报名的朋友"展示模块后,转化率显著提高——这验证了社交推荐在教育培训领域的重要性。
