You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Odoo 14 eLearning模块如何实现章节顺序解锁功能

Odoo 14 eLearning模块章节顺序锁定实现方案

现有实现的核心问题

  • 你定义的previous_category_complete是普通存储字段,默认值固定为True,不会根据当前登录用户的幻灯片完成进度动态计算,完全起不到校验作用
  • 模板里的判断逻辑写反了:前序章节没完成的时候应该锁,你现在写的previous_category_complete is False反而给未完成状态的内容放行了
  • 只做前端链接隐藏没用,用户直接拼接幻灯片URL就能直接访问锁定内容,没有后端权限校验等于锁了个寂寞

完整实现步骤

这套方案不需要写自定义JavaScript,所有逻辑都在Odoo后端层处理,兼容性远好于纯前端实现,不会因为前端缓存、JS加载失败出现锁失效问题。

第一步:修正模型层逻辑,用计算字段动态返回当前用户的解锁状态

不要用固定存储的布尔字段,加基于当前登录用户、关联幻灯片完成记录的实时计算字段即可:

from odoo import models, fields
from odoo.http import request

class SlideSlide(models.Model):
    _inherit = 'slide.slide'

    is_locked = fields.Boolean(
        string='是否锁定',
        compute='_compute_is_locked',
        compute_sudo=False
    )

    def _compute_is_locked(self):
        current_user = request.env.user
        for slide in self:
            # 课程管理员/发布者、标记为预览的幻灯片、未归类的幻灯片永远不锁
            if slide.channel_id.can_publish or slide.is_preview or not slide.category_id:
                slide.is_locked = False
                continue
            # 按章节排序序号定位前序章节
            current_section_seq = slide.category_id.sequence
            previous_section = request.env['slide.slide.category'].search([
                ('channel_id', '=', slide.channel_id.id),
                ('sequence', '<', current_section_seq)
            ], order='sequence desc', limit=1)
            # 没有前序章节即为第一个章节,直接开放
            if not previous_section:
                slide.is_locked = False
                continue
            # 校验前序章节下所有幻灯片当前用户是否全部完成
            previous_slides = self.env['slide.slide'].search([
                ('channel_id', '=', slide.channel_id.id),
                ('category_id', '=', previous_section.id)
            ])
            completed_count = request.env['slide.slide.partner'].search_count([
                ('partner_id', '=', current_user.partner_id.id),
                ('slide_id', 'in', previous_slides.ids),
                ('completed', '=', True)
            ])
            slide.is_locked = completed_count != len(previous_slides)

第二步:修正QWeb模板逻辑

替换原有错误的判断规则,锁定状态下不渲染跳转链接,增加明确的锁定标识:

<odoo>
    <data>
        <template id="section_lock" inherit_id='website_slides.course_slides_list_slide'>
            <xpath expr="//div[@class='text-truncate mr-auto']" position="replace">
                <div class="text-truncate mr-auto d-flex align-items-center">
                    <a t-if="not slide.is_locked"
                       class="o_wslides_js_slides_list_slide_link" 
                       t-attf-href="/slides/slide/#{slug(slide)}">
                        <span t-field="slide.name"/>
                    </a>
                    <t t-else="">
                        <i class="fa fa-lock text-muted mr-2" title="完成前序章节后解锁"></i>
                        <span class="text-muted" t-esc="slide.name"/>
                    </t>
                </div>
            </xpath>
        </template>
    </data>
</odoo>

第三步:增加后端路由拦截,防止URL绕过

继承幻灯片详情的原生路由,访问前先校验锁定状态,直接拦截非法访问:

from odoo.addons.website_slides.controllers.main import WebsiteSlides
from odoo.http import request, route

class SectionLockSlides(WebsiteSlides):

    @route()
    def slide_view(self, slide, **kwargs):
        if slide.is_locked and not slide.channel_id.can_publish:
            return request.render('website.403', status=403)
        return super().slide_view(slide, **kwargs)

补充说明

  • 章节排序直接复用eLearning模块自带的slide.slide.category的sequence字段,你在后台拖拽调整章节顺序,解锁逻辑会自动适配,不需要额外修改配置
  • 计算字段为实时计算,用户完成前序章节最后一张幻灯片后,刷新页面下一章就会自动解锁,不需要配置定时任务
  • 完成状态读取的是Odoo原生的slide.slide.partner表,这张表本来就用来存储每个用户的幻灯片完成记录,不需要额外新建存储表

内容的提问来源于stack exchange,提问作者Francesco Garzillo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 15:39:15