教培机构在线招生系统设计——课程套餐、微页面与多端架构
引言教培机构面临的招生压力在近几年持续加剧地推成本飙升、传统广告转化率下降、获客渠道越来越贵。核心原因是学员的注意力已经迁移到移动端而很多机构的招生方式仍停留在等学员上门阶段。本文从系统设计的角度讨论教培机构在线招生场景下的几个关键技术模块课程套餐的数据建模与权限授予、可视化微页面的组件化架构、多端页面生成策略以及订单数据的统计查询实现。一、课程套餐设计数据模型与权限授予1.1 单课销售的局限单课销售模式下存在两个结构性问题客单价低学员学完即走难以形成持续付费学习碎片化学员各买各的无法形成系统性学习路径。套餐将相关课程按学习路径打包销售可以同时解决客单价和学习路径问题。1.2 套餐数据模型// 课程套餐实体publicclassCoursePackage{privateLongpackageId;privateStringname;// 套餐名称privateStringcoverUrl;// 套餐封面privateStringdescription;// 套餐介绍privateBigDecimaloriginalPrice;// 累计原价展示用用于体现优惠privateBigDecimalsalePrice;// 套餐售价privateListLongcourseIds;// 包含的课程列表privateIntegervalidDays;// 购买后有效期天privateBooleanhasCert;// 完成后是否颁发证书privateLocalDateTimesaleEndAt;// 限时优惠截止时间可选}关键字段说明originalPrice与salePrice分离前端展示折扣信息时直接取两个字段计算避免每次请求都重新累加单课价格。validDays控制套餐有效期与单课有效期独立支持套餐到期后单课权限仍保留的场景。saleEndAt为可选字段支持限时促销到期后自动恢复原价。1.3 套餐购买后的权限授予套餐购买成功后需要为套餐内每门课程分别授权。这里涉及事务一致性如果中途某门课程授权失败已授权的需要回滚。// 套餐购买后的权限授予TransactionalpublicvoidgrantPackageAccess(LonguserId,LongpackageId,LongorderId){CoursePackagepkgpackageRepo.findById(packageId).orElseThrow();LocalDateTimeexpireAtLocalDateTime.now().plusDays(pkg.getValidDays());// 为套餐内每门课程分别授权pkg.getCourseIds().forEach(courseId-{UserCourseAccessaccessnewUserCourseAccess();access.setUserId(userId);access.setCourseId(courseId);access.setOrderId(orderId);access.setExpireAt(expireAt);accessRepo.save(access);});}一个需要注意的边界情况学员可能已经单独购买过套餐内的某门课程。此时需要判断已有权限的到期时间取较晚者避免覆盖更长的有效期。// 处理已有权限的合并逻辑pkg.getCourseIds().forEach(courseId-{OptionalUserCourseAccessexistingaccessRepo.findByUserIdAndCourseId(userId,courseId);if(existing.isPresent()){// 取较晚的到期时间LocalDateTimenewExpireAtexisting.get().getExpireAt().isAfter(expireAt)?existing.get().getExpireAt():expireAt;existing.get().setExpireAt(newExpireAt);}else{UserCourseAccessaccessnewUserCourseAccess();access.setUserId(userId);access.setCourseId(courseId);access.setOrderId(orderId);access.setExpireAt(expireAt);accessRepo.save(access);}});二、可视化微页面组件化架构设计2.1 设计动机教培机构的页面需求是高频且多样的新课上架介绍页、节日促销落地页、招生活动报名页、讲师简介页等。如果每种页面都由开发单独编码周期长且灵活性差。微页面的核心思路是将页面拆解为可复用的组件通过 JSON 配置组合生成页面前端渲染引擎根据 JSON 动态渲染无需为每个页面单独写代码。2.2 组件体系系统定义以下基础组件类型组件类型标识用途Banner 图banner顶部主视觉图片支持跳转链接课程卡片course-card课程封面、标题、价格展示套餐卡片package-card套餐内容、原价/现价、倒计时讲师介绍lecturer讲师头像、简介、擅长方向报名表单form姓名、手机号收集倒计时模块countdown限时活动倒计时图文区块richtext富文本内容展示视频预览video嵌入课程试看视频2.3 数据结构设计微页面以 JSON 格式存储核心是页面配置与组件配置的分离// 微页面数据结构interfaceMicroPage{pageId:stringtitle:stringcoverUrl:string// 分享时的封面图shareTitle:string// 分享标题shareDesc:string// 分享描述backgroundColor:stringcomponents:PageComponent[]}interfacePageComponent{componentId:stringtype:banner|course-card|package-card|lecturer|form|countdown|richtext|videoorder:number// 排序config:Recordstring,any// 各组件的配置项}// 示例课程卡片组件配置interfaceCourseCardConfig{courseId:numbershowPrice:booleanshowOriginalPrice:booleanbuttonText:string// 按钮文案buttonAction:buy|preview|enroll}config字段使用Recordstring, any是一个权衡不同组件的配置差异大用强类型会导致接口膨胀。实际实现中可以通过 JSON Schema 对每种组件的 config 做校验保证数据合法性。2.4 多端渲染策略同一份 JSON 配置需要适配多端渲染PC 端双栏布局内容区 侧边栏引导使用 CSS Grid 实现H5/移动端单栏全幅布局底部固定操作栏小程序端映射到小程序原生组件如rich-text、swiper等前端渲染引擎的核心逻辑是遍历components数组根据type字段选择对应的渲染组件将config作为 props 传入。新增组件类型时只需注册新的渲染组件无需修改引擎逻辑。三、订单数据统计查询3.1 统计查询设计运营需要按课程或套餐维度查看销量和收入数据。这个查询的特点是聚合维度灵活、数据量大时需要分页。// 订单统计查询按课程/套餐汇总Query( SELECT o.item_type, o.item_id, o.item_name, COUNT(*) AS order_count, SUM(o.amount) AS total_revenue, AVG(o.amount) AS avg_order_value FROM orders o WHERE o.status PAID AND o.paid_at BETWEEN :startAt AND :endAt GROUP BY o.item_type, o.item_id, o.item_name ORDER BY total_revenue DESC )ListOrderStatsVOgetOrderStatsByItem(Param(startAt)LocalDateTimestartAt,Param(endAt)LocalDateTimeendAt);当订单量达到百万级时这个聚合查询需要优化paid_at字段建索引避免全表扫描时间范围查询走索引覆盖避免回表如果数据量继续增长考虑将统计结果预计算并缓存用定时任务每小时刷新3.2 核心统计指标指标计算方式销售额SUM(amount) WHERE status PAID付费学员数COUNT(DISTINCT user_id) WHERE status PAID课程销量排行按item_id分组COUNT(*) DESC订单转化率详情页 UV / 支付成功数退款率退款数 / 已支付数按课程维度统计转化率的分母详情页 UV来自前端埋点上报需要单独的访问日志表存储不能与订单表直接 JOIN。实际实现中通常通过定时任务离线计算写入统计结果表。四、总结本文讨论了教培机构在线招生系统中几个关键模块的设计思路套餐权限授予需要处理事务一致性和已有权限合并两个边界情况微页面组件化通过 JSON 配置驱动渲染新增页面类型无需开发介入订单统计查询在大数据量下需要索引优化和预计算策略这几个模块的共同特点是业务逻辑看似简单但边界情况处理和数据一致性保障才是实现中的难点。在实际项目中权限授予的事务边界、微页面 JSON 的 Schema 校验、统计查询的性能优化都需要根据具体业务规模做针对性设计。