[CRMEB知识付费系统]移动端课程列表一级分类模式实现

写在前面

最近在使用crmeb知识付费下系统的时候,发现默认是二级分类模式,但需求需要一级直接展示内容所以只能重构一下了,重构只改动了前端,非必要不去改动后端,会很麻烦.....

目录

写在前面

实施准备

代码结构与功能说明

​1. 页面结构

​2. 数据与状态管理

​3. 核心方法解析

​3.1 获取一级分类 (getCateList)

​3.2 获取二级分类 (getSubject)

​3.3 加载课程列表 (getSpecialList)

​3.4 搜索功能 (goSearch)

​4. 计算属性

具体修改

完整代码


实施准备

具体实施准备,首先肯定是要先分析默认的代码,了解了默认代码的逻辑再在基础上修改实现自己的逻辑

默认代码

{extend name="public/container"}
{block name="title"}课程分类{/block}
{block name="head_top"}



{/block}
{block name="content"}

{/block}
{block name="foot"}

{/block}

大致分析

分析代码是个体力活,所以最好还是要紧跟时代,结合AI分析,事半功倍,所以先请DeepSeek分析一波

[CRMEB知识付费系统]移动端课程列表一级分类模式实现_第1张图片

大概deepsekk也不想分析.............

回归正题,分析大致意思如下:

页面部分:

头部引入了某些东西,标题还有写好的html头部分,然后内嵌了css样式,可能是外联优先级不够或者是引入css太多有冲突,所以对某一个界面进行特殊设置或独立设置样式,一般都是对于页面整体性的修饰.

然后在头部就引入了两个js,一般js都在页面底部引入,提升页面加载的速度,但这里在头部就引入了而且是单独引入,并没有在style.html中集中引入,所以判断是只有这个页面应用了这两个js,其它页面没有使用,基于这个判断结合下面的代码可以知道,大概率这两个js是用来操控导航栏的,从js文件的命名上也不难看出这一点。


再就是html+vue的页面排版,显示搜索,然后是一级导航输出,二级导航输出,内容输出,然后是两个其它代码,第一个看图片名称是没有数据,所以初步判断就是一张暂无数据的图片类似这种的,然后是加载更多,这个通常都是被控制的,动态显示文字内容,根据数据加载情况来显示。

最后是js部分,请求,挂载,初始化数据,当created()完了以后先调this.getCateList(); 意思是先拿到导航,通过查看Network可以知道,这里接口返回了一级和二级导航的数据

[CRMEB知识付费系统]移动端课程列表一级分类模式实现_第2张图片

mounted()方法看不懂,貌似是当.....监听什么东西然后就调用获取课程的方法

methods()方法,getCateList()方法大概是说:通过get请求special/get_grade_cate接口,然后设置vm.loading = false; 应该是页面状态之类的,然后判断是否成功200,成功后就给gradeCate,这个可能是存储一级分类的,通过上下文一看确定是,然后循环了gradeCate判断应该是给第一个值,可能是设置动态样式用,从下文可以看出,从下面的代码不难看出,重构的重点就在这里,取决于我们是否走二级也在这里。

 vm.$nextTick(function () {
                                $('#wrapper').navbarscroll({
                                    defaultSelect: defaultSelect,
                                    scrollerWidth: 5,
                                    fingerClick: 1,
                                    endClickScroll: function (elem) {
                                        var id = $(elem).data('id');
                                        vm.count++;
                                        if (vm.gradeId === id) {
                                            return;
                                        }
                                        vm.gradeId = id;
                                        if (vm.gradeId) {
                                            vm.getSubject();
                                        } else {
                                            vm.subjectCate = [];
                                            vm.specialList = [];
                                            vm.subjectId = 0;
                                            vm.loading = false;
                                            vm.loadend = false;
                                            vm.page = 1;
                                            vm.getSpecialList();
                                        }
                                    }
                                });
                            });

重点是endClickScroll()方法,然后再下面是二级导航的逻辑,二级导航同样也有一段相同的代码,

 this.$nextTick(function () {
                        $('#nav').navbarscroll({
                            defaultSelect: defaultSelect,
                            scrollerWidth: 5,
                            fingerClick: 1,
                            endClickScroll: function (elem) {
                                var id = $(elem).data('id');
                                if (vm.subjectId === id) {
                                    return;
                                }
                                vm.subjectId = id;
                                vm.specialList = [];
                                vm.loadend = false;
                                vm.page = 1;
                                vm.getSpecialList();
                            }
                        });
                    });

正常二级分类流程是到这里,二级导航调getSpecialList()同时设置 vm.loadend = false;这个未知作用的状态,然后展示数据,但现在是去除二级导航,直接就不用看二级这一块了,后面直接注释这段

最后的课程方法就不用仔细分析了,就是请求接口返回传参,返回如果有错就抛

以上为个人分析

AI分析如下:

代码结构与功能说明


1. 页面结构
  • 搜索栏:提供关键词搜索功能,输入内容绑定到 search 变量,点击搜索触发 goSearch 方法。
  • 一级分类导航:横向滚动列表,展示从后台获取的课程分类(如"全部"、"小学"、"初中"等)。
  • 二级分类导航:当一级分类非"全部"时展示,显示该分类下的子分类(如"语文"、"数学")。
  • 课程列表:卡片式布局,展示课程封面、标题、价格、学习人数等信息。
  • 加载提示:列表底部显示加载状态(加载中/已加载完毕/无数据)。

2. 数据与状态管理

javascript

data: {
  gradeCate: [],       // 一级分类数据(如:全部、小学、初中)
  subjectCate: [],      // 二级分类数据(如:语文、数学)
  specialList: [],      // 当前展示的课程列表
  gradeId: -1,          // 当前选中的一级分类ID
  subjectId: -1,        // 当前选中的二级分类ID
  search: '',           // 搜索关键词
  page: 1,              // 当前页码
  limit: 10,            // 每页数据量
  loading: false,       // 是否正在加载数据
  loadend: false        // 是否已加载全部数据
}

3. 核心方法解析
3.1 获取一级分类 (getCateList)
  • 功能:从后端API获取所有一级分类数据,插入"全部"选项,并初始化导航滚动插件。
  • 关键流程
    1. 发送GET请求到 {:url('special/get_grade_cate')}
    2. 在数据开头插入 {id: 0, name: '全部'}
    3. 使用 navbarscroll 插件实现横向滚动导航,设置点击回调 endClickScroll
  • 点击回调逻辑
    • 更新 gradeId
    • 若选中非"全部"分类 (gradeId !== 0),调用 getSubject 加载二级分类。
    • 若选中"全部"分类,清空二级分类并直接加载课程。
3.2 获取二级分类 (getSubject)
  • 触发条件:当一级分类非"全部"时调用。
  • 功能:生成二级分类数据(含"全部"选项),并初始化二级导航滚动插件。
  • 关键流程
    1. 遍历 gradeCate 找到当前一级分类的子分类。
    2. 在子分类数组开头插入 {id: 0, name: '全部', pic: '...'}
    3. 使用 navbarscroll 初始化二级导航,点击时更新 subjectId 并重新加载课程。
3.3 加载课程列表 (getSpecialList)
  • 功能:根据当前选中的分类和搜索词分页加载课程数据。
  • 参数

    javascript

    params: {
      grade_id: this.gradeId,   // 一级分类ID
      subject_id: this.subjectId, // 二级分类ID
      search: this.search,       // 搜索关键词
      page: this.page,           // 页码
      limit: this.limit          // 每页数据量
    }
  • 分页逻辑
    • 滚动到底部时自动加载下一页(通过 listenTouchDirection 监听滚动事件)。
    • 每次加载后递增 page,直到返回数据少于 limit 时标记 loadend = true
3.4 搜索功能 (goSearch)
  • 触发方式:点击搜索按钮或按回车键。
  • 逻辑:重置页码和课程列表,重新加载数据。

4. 计算属性

javascript

computed: {
  updateSpecialList() {
    return this.specialList.map(item => ({
      ...item,
      special_type: specialType[item.type] // 将课程类型编码转为文字(如1→"视频课程")
    }));
  }
}
  • 作用:将课程的类型字段 type 转换为可读文本(依赖外部 specialType 映射表)。

具体修改

具体修改就是结合以上分析,删除不需要的部分,但要保证数据和流程正确

从上到下,一步步对照替换就可以了

头部其它的不需要动,内嵌的

然后页面部分,也对照原版的进行替换,去掉我们不需要二级部分,按照自己的页面结构,把默认页面的vue输出拿过来就可以,然后对应输出内容,最后的两个判断输出“暂无数据”图片和加载状态的代码不要删除,保留就可以,基本没什么影响,如果页面错乱可以调一下css,页面底部的引入也不需要动

    

加载更多

{include file="public/store_menu"}

最重要和麻烦的是js部分

js部分的大框架都不需要改动,data{}的初始化,用不到的可以先注释,created()方法的调用

this.getCateList(); 也无需改动,mounted()中的可以根据情况修改,这里主要控制的就是导航栏滚动相关的然后根据这个去调this.getSpecialList();

methods()方法中,getCateList()获取分类数据,这里通过接口返回了数据之后,处理之后,直接调取课程就可以了,不需要再进行判断然后再调二级的方法去二级里面

getCateList() {
                    this.loading = true;
                    axios.get("{:url('special/get_grade_cate')}")
                        .then(res => {
                            const data = res.data.data || [];
                            this.gradeCate = [{ id: 0, name: '全部' }, ...data];
                            // 默认加载第一个分类数据
                            this.getSpecialList();
                        })
                        .finally(() => this.loading = false);
                }

把二级导航部分的代码,直接注释

之后写了一个切换分类的方法switchCategory()切换栏目、调取课程方法,同时处理页面状态和处理其它的数据

// 切换分类
                switchCategory(id) {
                    if (this.gradeId === id) return;
                    this.gradeId = id;
                    this.page = 1;
                    this.specialList = [];
                    this.loadend = false;
                    this.getSpecialList();
                }

最后是getSpecialList()方法,getSpecialList()方法几乎不需要改动,确保返回数据正确就可以

getSpecialList() {
                    if (this.loading || this.loadend) return;

                    this.loading = true;
                    this.loadTitle = '加载中...';

                    axios.get("{:url('special/get_special_list')}", {
                        params: {
                            grade_id: this.gradeId !== 0 ? this.gradeId : null,
                            search: this.search.trim(),
                            page: this.page,
                            limit: this.limit
                        }
                    }).then(res => {
                        console.log('接口响应', res.data);
                        const data = res.data.data || [];
                        if (this.page === 1) {
                            this.specialList = data;
                        } else {
                            this.specialList.push(...data);
                        }
                        // this.specialList.push(...data);
                        this.loadend = data.length < this.limit;
                        this.page++;
                    }).catch(error => {
                        console.error('请求失败:', error);
                        this.loading = false;
                        this.loadTitle = '加载失败';
                    }).
                        finally(() => {
                            this.loading = false;
                            this.loadTitle = this.loadend ? '已全部加载' : '上拉加载更多';
                        });
                }

搜索功能无需改动

// 搜索功能
                goSearch() {
                    this.page = 1;
                    this.specialList = [];
                    this.loadend = false;
                    this.getSpecialList();
                }

目前存在的bug:

页面初始化时,全部栏目内没有数据,必须切换导航栏才有数据,现在还不知道具体为什么,处理之后会更新,如果有大佬理清楚了欢迎大佬私信教导

调整下来基本就是 去除二级分类的相关操作就可以了,课程数据正常获取,在一级分类的地方,调用getSpecialList()方法拿到数据,结合自己写的分类方法进行切换、调取等操作.

完整代码

{extend name="public/container"}
{block name="title"}课程分类{/block}
{block name="head_top"}


{/block}
{block name="content"}

{include file="public/store_menu"}
{/block} {block name="foot"} {/block}

你可能感兴趣的:(CRMEB,vue,html5,css)