LikeShop 知识付费系统章节试学与打卡解锁功能的二开方案

简介: 本文针对LikeShop知识付费系统,提出轻量级二开方案:通过扩展章节权限字段、新建学习进度与打卡表、统一播放校验入口,在不破坏原生架构前提下,低成本实现“免费试学”提升转化、“打卡解锁”增强留存两大核心能力,兼顾安全、兼容与可扩展性。

知识付费产品的核心增长矛盾,往往集中在转化与留存两端。

LikeShop 知识付费系统原生已具备完整的专栏课程、音频视频交付、会员订阅、支付结算能力,但在实际运营中,两类需求尤为突出:一是转化侧,用户付费决策门槛高,需要免费试学降低决策成本;二是留存侧,用户购买后容易半途弃课,需要打卡解锁等游戏化机制提升完课率。如果直接在原有章节播放逻辑里硬加判断,很容易导致权限混乱、播放地址泄露、学习进度不同步等问题。

这类需求属于典型的业务扩展型二开,最佳实践是扩展章节权限字段 + 独立学习进度体系 + 统一播放权限校验入口,不推翻原生课程与订单架构,以最小侵入成本实现试学转化与打卡激励能力。

本文基于 LikeShop 知识付费 Java 版技术底座,从设计思路、表结构改造、核心权限逻辑、打卡解锁实现、上下游联动五个维度,给出完整的二开落地方案。

一、二开背景与核心目标

1.1 原生能力的局限

原生系统以「购买后解锁全部内容」为核心模型,能够满足基础交付需求,但在精细化运营场景下存在短板:

  • 转化手段单一:用户只能看到课程简介,无法体验内容质量,付费转化率低;
  • 学习激励缺失:用户购买后缺乏持续学习的动力,完课率低,复购意愿弱;
  • 进度颗粒度粗:缺少章节级别的学习进度记录,无法做精细化的学习提醒;
  • 权限控制简单:仅区分「已购买/未购买」,无法实现部分章节免费、部分付费的分级体验。

1.2 二开核心目标

  1. 章节试学能力:支持单章节设置免费试学,未付费用户可观看试学章节,付费后解锁全部内容,降低决策门槛;
  2. 打卡解锁机制:支持「学习完前一章 → 打卡 → 解锁下一章」的递进式学习,提升完课率与用户留存;
  3. 统一权限校验:所有播放请求走统一权限入口,防止绕过页面直接访问视频地址;
  4. 最小侵入原则:通过扩展字段与新增表实现,复用原生订单、会员、课程体系,不破坏原有主流程;
  5. 向下兼容:历史课程与订单不受影响,可平滑升级。

二、核心设计思路

2.1 章节权限模型

采用「三级权限」控制,优先级从高到低:

  1. 全局免费:课程整体免费,所有章节无需购买即可观看;
  2. 试学章节:课程整体付费,但指定章节设置为免费试学,未购买用户仅可观看试学章节;
  3. 付费解锁:购买课程或开通会员后,解锁全部章节内容。

核心原则:视频/音频的真实播放地址,必须经过后端权限校验后再返回,绝不能直接暴露在前端页面中,防止被抓包下载。

2.2 打卡解锁模型

两种主流解锁模式,可配置切换:

模式 规则说明 适用场景
顺序解锁 必须学完前一章并打卡,才能解锁下一章 体系化课程、训练营、进阶教程
每日解锁 每天固定解锁 N 章,打卡后获得当日学习权限 轻量专栏、每日听书、打卡营

核心规则:

  • 每章设置「学习完成条件」,如观看时长达到 80%、完成课后习题;
  • 满足条件后用户点击打卡,系统记录打卡时间,解锁下一章节;
  • 支持补卡机制,可通过分享、积分等方式补解锁历史章节。

2.3 与原生体系的关系

  • 复用原生课程表、章节表、订单表、会员表;
  • 试学标记通过章节表扩展字段实现;
  • 学习进度、打卡记录独立建表,不侵入原生业务表;
  • 购买、会员开通等事件通过监听原生事件,同步更新用户课程权限。

三、数据库设计

遵循「扩展字段 + 新增表」的原则,尽量不修改原生表结构,降低升级冲突。

3.1 章节表扩展字段

在原生章节表上增加试学与解锁配置字段,不改变原有字段语义。

ALTER TABLE ls_course_chapter 
ADD COLUMN is_free_trial TINYINT DEFAULT 0 COMMENT '是否免费试学:0否 1是' AFTER chapter_title,
ADD COLUMN unlock_type TINYINT DEFAULT 0 COMMENT '解锁方式:0直接解锁 1打卡解锁' AFTER is_free_trial,
ADD COLUMN study_duration_require INT DEFAULT 0 COMMENT '要求学习时长(秒),达到才算完成' AFTER unlock_type,
ADD INDEX idx_free_trial(is_free_trial);

3.2 用户课程权限表 ls_user_course_auth

记录用户对某门课程的权限状态,避免每次都关联订单表查询。

CREATE TABLE ls_user_course_auth (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  user_id BIGINT NOT NULL,
  course_id BIGINT NOT NULL,

  auth_type TINYINT NOT NULL COMMENT '权限类型:1试学 2购买 3会员',
  expire_time DATETIME DEFAULT NULL COMMENT '权限过期时间,会员模式使用',

  total_progress DECIMAL(5,2) DEFAULT 0.00 COMMENT '课程总进度百分比',
  last_study_chapter_id BIGINT DEFAULT NULL COMMENT '上次学习章节',
  last_study_time DATETIME DEFAULT NULL,

  create_time DATETIME NOT NULL,
  update_time DATETIME NOT NULL,

  UNIQUE KEY uk_user_course(user_id, course_id),
  INDEX idx_user_id(user_id),
  INDEX idx_course_id(course_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户课程权限表';

3.3 章节学习进度表 ls_user_chapter_study

章节级别的学习记录,是打卡解锁的判断依据。

CREATE TABLE ls_user_chapter_study (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  user_id BIGINT NOT NULL,
  course_id BIGINT NOT NULL,
  chapter_id BIGINT NOT NULL,

  study_duration INT NOT NULL DEFAULT 0 COMMENT '已学习时长(秒)',
  is_completed TINYINT NOT NULL DEFAULT 0 COMMENT '是否完成学习:0否 1是',
  is_checked_in TINYINT NOT NULL DEFAULT 0 COMMENT '是否已打卡:0否 1是',
  checkin_time DATETIME DEFAULT NULL COMMENT '打卡时间',

  is_unlocked TINYINT NOT NULL DEFAULT 0 COMMENT '是否已解锁:0否 1是',
  unlock_time DATETIME DEFAULT NULL,

  create_time DATETIME NOT NULL,
  update_time DATETIME NOT NULL,

  UNIQUE KEY uk_user_chapter(user_id, chapter_id),
  INDEX idx_user_course(user_id, course_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='章节学习进度表';

3.4 打卡规则配置表 ls_course_checkin_rule

每门课程可配置独立的打卡解锁规则。

CREATE TABLE ls_course_checkin_rule (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  course_id BIGINT NOT NULL UNIQUE,

  enable_checkin TINYINT NOT NULL DEFAULT 0 COMMENT '是否开启打卡解锁:0否 1是',
  unlock_mode TINYINT NOT NULL DEFAULT 1 COMMENT '解锁模式:1顺序解锁 2每日解锁',
  daily_unlock_count INT DEFAULT 1 COMMENT '每日解锁章节数',
  enable_retroactive TINYINT DEFAULT 0 COMMENT '是否允许补卡:0否 1是',
  retroactive_cost INT DEFAULT 0 COMMENT '补卡消耗积分',

  create_time DATETIME NOT NULL,
  update_time DATETIME NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='课程打卡规则表';

四、核心业务代码实现

4.1 统一章节权限校验

这是整个模块的第一道防线,所有获取播放地址的请求必须经过此校验。

@Service
public class ChapterAuthService {
   

    @Autowired
    private UserCourseAuthMapper authMapper;
    @Autowired
    private CourseChapterMapper chapterMapper;
    @Autowired
    private CheckinRuleMapper ruleMapper;

    /**
     * 校验用户是否有权限观看该章节
     */
    public boolean hasPermission(Long userId, Long chapterId) {
   
        CourseChapter chapter = chapterMapper.selectById(chapterId);
        if (chapter == null) return false;

        // 1. 全局免费章节,直接放行
        if (chapter.getIsFreeTrial() == 1) {
   
            return true;
        }

        if (userId == null) {
   
            return false; // 未登录且非试学章节,无权限
        }

        // 2. 查询用户课程权限
        UserCourseAuth auth = authMapper.selectOne(userId, chapter.getCourseId());
        if (auth == null) {
   
            return false; // 无购买/会员权限
        }

        // 3. 已购买或会员,再校验打卡解锁规则
        CourseCheckinRule rule = ruleMapper.selectByCourseId(chapter.getCourseId());
        if (rule != null && rule.getEnableCheckin() == 1) {
   
            UserChapterStudy study = studyMapper.selectOne(userId, chapterId);
            return study != null && study.getIsUnlocked() == 1;
        }

        // 4. 无打卡限制,直接有权限
        return true;
    }

    /**
     * 获取可播放的视频地址(有权限才返回真实地址)
     */
    public String getPlayUrl(Long userId, Long chapterId) {
   
        if (!hasPermission(userId, chapterId)) {
   
            throw new BizException("无权限观看该章节,请先购买课程");
        }
        CourseChapter chapter = chapterMapper.selectById(chapterId);
        // 可增加签名、时效token,防止地址外泄
        return buildSignedPlayUrl(chapter.getVideoUrl());
    }
}

4.2 学习进度同步

用户播放过程中定时上报学习时长,达到阈值自动标记为完成。

@Service
public class ChapterStudyService {
   

    @Transactional(rollbackFor = Exception.class)
    public void syncStudyProgress(Long userId, Long chapterId, int duration) {
   
        CourseChapter chapter = chapterMapper.selectById(chapterId);
        Long courseId = chapter.getCourseId();

        // 1. 更新章节学习时长
        UserChapterStudy study = studyMapper.selectOne(userId, chapterId);
        if (study == null) {
   
            study = initStudyRecord(userId, courseId, chapterId);
        }

        int newDuration = study.getStudyDuration() + duration;
        study.setStudyDuration(newDuration);

        // 2. 达到要求时长,标记为完成
        if (newDuration >= chapter.getStudyDurationRequire() 
                && study.getIsCompleted() == 0) {
   
            study.setIsCompleted(1);
        }

        studyMapper.updateById(study);

        // 3. 更新课程总进度
        updateCourseTotalProgress(userId, courseId);
    }
}

4.3 打卡解锁核心逻辑

用户完成学习后打卡,解锁下一章节。

@Service
public class CheckinService {
   

    @Transactional(rollbackFor = Exception.class)
    public CheckinResultVO checkin(Long userId, Long chapterId) {
   
        UserChapterStudy study = studyMapper.selectOne(userId, chapterId);
        if (study == null || study.getIsCompleted() == 0) {
   
            throw new BizException("请先完成本章学习后再打卡");
        }
        if (study.getIsCheckedIn() == 1) {
   
            throw new BizException("今日已打卡");
        }

        CourseChapter chapter = chapterMapper.selectById(chapterId);
        Long courseId = chapter.getCourseId();
        CourseCheckinRule rule = ruleMapper.selectByCourseId(courseId);

        // 1. 标记当前章节已打卡
        study.setIsCheckedIn(1);
        study.setCheckinTime(new Date());
        studyMapper.updateById(study);

        // 2. 解锁下一章节
        CourseChapter nextChapter = getNextChapter(courseId, chapter.getSort());
        if (nextChapter != null) {
   
            unlockChapter(userId, nextChapter.getId());
        }

        // 3. 打卡奖励(可选:积分、成长值)
        rewardService.giveCheckinReward(userId, courseId);

        CheckinResultVO vo = new CheckinResultVO();
        vo.setCheckedIn(true);
        vo.setNextChapterId(nextChapter != null ? nextChapter.getId() : null);
        vo.setRewardInfo(getRewardInfo(courseId));
        return vo;
    }

    private void unlockChapter(Long userId, Long chapterId) {
   
        UserChapterStudy study = studyMapper.selectOne(userId, chapterId);
        if (study == null) {
   
            study = initStudyRecord(userId, getCourseId(chapterId), chapterId);
        }
        if (study.getIsUnlocked() == 0) {
   
            study.setIsUnlocked(1);
            study.setUnlockTime(new Date());
            studyMapper.updateById(study);
        }
    }
}

4.4 购买后初始化权限

监听订单支付成功事件,自动为用户开通课程权限并解锁第一章。

@Component
public class CourseOrderListener {
   

    @Autowired
    private UserCourseAuthMapper authMapper;
    @Autowired
    private CheckinService checkinService;

    @EventListener
    @Transactional(rollbackFor = Exception.class)
    public void onOrderPaid(CourseOrderPaidEvent event) {
   
        Long userId = event.getUserId();
        Long courseId = event.getCourseId();

        // 1. 创建或更新课程权限
        UserCourseAuth auth = authMapper.selectOne(userId, courseId);
        if (auth == null) {
   
            auth = new UserCourseAuth();
            auth.setUserId(userId);
            auth.setCourseId(courseId);
            auth.setAuthType(2); // 购买
            authMapper.insert(auth);
        }

        // 2. 如果是打卡解锁模式,默认解锁第一章
        CourseCheckinRule rule = ruleMapper.selectByCourseId(courseId);
        if (rule != null && rule.getEnableCheckin() == 1) {
   
            CourseChapter firstChapter = getFirstChapter(courseId);
            if (firstChapter != null) {
   
                checkinService.unlockChapter(userId, firstChapter.getId());
            }
        }
    }
}

五、上下游模块联动

试学与打卡不是孤立功能,必须联动订单、会员、统计等模块,才能形成完整运营闭环。

5.1 订单与会员模块

  • 购买课程、开通会员后,自动初始化用户课程权限;
  • 会员过期时,同步更新权限有效期,过期后收回非试学章节的观看权限;
  • 退款时,根据退款比例处理课程权限,支持关闭或保留。

5.2 内容播放模块

  • 播放地址统一走权限校验接口,返回带时效签名的播放链接,防止外泄;
  • 播放页根据权限状态,展示「试看结束,购买解锁」「打卡解锁下一章」等引导文案;
  • 学习进度断点续播,下次进入自动回到上次观看位置。

5.3 营销与激励模块

  • 打卡可配置积分、成长值奖励,提升用户动力;
  • 支持分享补卡,利用社交裂变带来新用户;
  • 学习排行榜、连续打卡天数展示,增强竞争感与成就感。

5.4 数据统计模块

  • 课程维度:试学转化率、购买转化率、完课率、平均打卡天数;
  • 用户维度:累计学习时长、连续打卡天数、已完成课程数;
  • 运营后台看板直观展示,辅助优化课程内容与运营策略。

六、平滑升级与兼容方案

6.1 升级步骤

  1. 执行扩展字段与新增表 SQL,全部为增量操作,不修改原生核心数据;
  2. 部署权限校验、学习进度、打卡模块代码,原生播放与订单逻辑保持不变;
  3. 后台先灰度开启部分课程的试学与打卡功能,验证权限与解锁逻辑;
  4. 全量上线后,同步更新运营端配置指引。

6.2 历史数据兼容

  • 历史已购买课程的用户,通过定时任务批量初始化课程权限记录;
  • 历史章节默认关闭试学、关闭打卡解锁,不影响原有内容的观看;
  • 学习进度数据从无到有,不追溯历史播放行为,新产生的学习行为正常记录。

6.3 官方版本升级兼容

  • 核心改造以新增表、扩展字段为主,极少修改原生核心文件;
  • 官方版本迭代时,重点核对章节表、订单支付事件是否有变动,同步适配即可;
  • 独立的权限校验层将扩展逻辑与原生业务解耦,升级冲突成本极低。

七、常见坑与避坑建议

1. 播放地址泄露

坑:视频地址直接写在前端页面,用户通过抓包就能获取全部课程链接,付费体系形同虚设。
避坑:播放地址统一由后端接口返回,校验通过后生成带时效与签名的临时地址;重要课程配合视频加密、防盗链。

2. 打卡作弊刷进度

坑:用户通过脚本快速上报学习时长,瞬间完成所有章节打卡。
避坑:服务端校验时长合理性,单次上报时长不超过实际时间间隔;增加防刷机制,异常时长人工审核。

3. 权限判断不一致

坑:列表页显示可观看,点进去却提示无权限,体验割裂。
避坑:列表查询与详情播放共用同一套权限校验方法,保证判断口径一致。

4. 打卡解锁顺序错乱

坑:章节排序变动后,解锁逻辑出现跳章或死锁。
避坑:解锁严格依赖章节排序字段,排序变更后重新校验用户已解锁章节的连续性。

5. 会员过期权限不回收

坑:会员到期后,用户依然能观看所有付费章节。
避坑:权限校验时实时判断有效期,不依赖静态标记;定时任务扫描过期权限,同步更新状态。

结语

知识付费的试学与打卡,表面看是两个运营功能,本质是「转化漏斗」与「留存激励」两套体系的落地。

LikeShop 知识付费系统原生已经有扎实的课程交付与支付结算底座,二开时不用推翻重构,沿着「扩展权限字段 + 统一校验入口 + 事件联动上下游」的思路,就能以很低的侵入成本实现完整的试学与打卡能力,同时保留后续官方版本的平滑升级空间。

对知识付费类二开项目来说,核心原则永远是:权限收口、进度独立、事件联动。底层链路做扎实了,后续再加直播、作业、社群等更多玩法,也都是在这套骨架上做增量。

目录
相关文章
|
1天前
|
SQL 存储 Java
LikeShop 多商户高级版商城满减满赠活动的自定义规则二开实现
本文针对LikeShop多商户高级版,提出轻量、可配置的满减满赠二开方案:通过独立活动体系、统一计算入口与事件联动分账,支持平台/商家双层级、多档阶梯规则、智能分摊及精准退款回退,最小侵入实现灵活营销,保障账务准确。
22 0
|
1天前
|
SQL 前端开发 Java
LikeShop 连锁点餐系统套餐组合与加料功能的二开改造
本文基于LikeShop连锁点餐系统,提出轻量级二开方案:通过新增扩展表(套餐/加料模型)、复用原生订单与库存底座,实现固定/自选套餐、分组加料(支持库存联动与价格配置),保障全链路库存扣减、后厨明细打印及平滑升级,侵入极小、落地高效。
21 0
|
2天前
|
SQL 前端开发 PHP
LikeShop 多商户标准版订单拆分与合并功能的二开改造方案
本文针对LikeShop多商户标准版订单体系痛点,提出轻量级二开方案:通过新增主子单架构(主单统一支付/展示,子单独立履约/分账),实现跨店拆单与同店合并,兼容原库存、支付、分账、售后全链路,零破坏、易升级。
23 0
|
2天前
|
SQL 存储 Java
LikeShop 多商户高级版商城满减满赠活动的自定义规则二开实现
本文针对LikeShop多商户平台满减满赠二开需求,提出“独立活动体系+统一计算入口+事件联动分账”架构方案。涵盖双层级活动模型、多档阶梯规则、精准分摊与退款回退、审核流程及平滑升级,全程低侵入、高兼容,确保账务准确与运营灵活。
19 0
|
2天前
|
监控 Java 关系型数据库
LikeShop 多商户高级版商城系统日志采集与监控告警体系搭建
本文针对多商户平台资金链路复杂、故障影响面广等特性,基于LikeShop高级版实践,从日志规范、采集方案、监控分层、告警体系四方面,提出轻量可落地的可观测性建设方案,覆盖入门到生产级演进路径。
34 0
|
5天前
|
缓存 安全 应用服务中间件
LikeShop 全版本部署优化:Nginx 反向代理、静态资源缓存与 HTTPS 配置
本文详解LikeShop(PHP/Java全版本)生产级Nginx部署优化方案:通过反向代理、动静分离、静态资源强缓存(JS/CSS 30天、图片90天)、Gzip/Brotli压缩、规范HTTPS(TLS1.2+、HSTS、完整证书链)及安全加固,低成本显著提升H5加载速度、小程序首屏体验与并发能力,助你一次部署达标过审。
52 0
|
6天前
|
SQL 前端开发 Java
LikeShop 二开代码规范:目录结构、钩子使用与版本升级兼容方案
本文为电商系统二开团队提供可落地的代码规范指南,聚焦目录隔离、钩子扩展与升级兼容三大维度。强调“最小侵入、物理隔离、扩展优先、兼容升级”原则,覆盖PHP(ThinkPHP)与Java(SpringBoot)双技术栈,助团队告别升级冲突,实现平滑迭代。
49 0
|
6天前
|
缓存 小程序 UED
LikeShop 连锁点餐系统后厨打印:订单下发、打印状态反馈与出餐标记
LikeShop连锁点餐系统将后厨打印升维为订单生产核心链路:支持多门店/多打印机智能路由、持久化任务+指数重试、云打印实时状态回调、出餐一键标记及前厅/用户/取餐屏三端同步,彻底解决丢单、重复打、状态不同步等连锁经营痛点。
49 0
|
6天前
|
移动开发 小程序 前端开发
LikeShop 单商户标准版 UniApp 端二开:页面组件复用与自定义主题适配
本文详解LikeShop单商户版UniApp二开的正确姿势:避免直接改页面,善用已有的三层组件化体系(基础/业务/页面区块)与SCSS主题变量机制。从目录结构梳理、组件复用实践到主题适配技巧,附核心代码示例,助团队降本增效、提升可维护性。
49 0
|
6天前
|
存储 定位技术 数据安全/隐私保护
LikeShop 社区团购系统自提点管理:库存核销、团长佣金与提现对账
本文详解社区团购中自提点的三大核心管理模块:库存核销(四状态流转+幂等设计)、团长佣金(分层配置+下单快照)、提现对账(周期结算+明细留痕),结合LikeShop实战代码与六大避坑指南,助力系统稳健落地。
65 0

热门文章

最新文章