最近在使用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"}
加载更多
{include file="public/store_menu"}
{/block}
{block name="foot"}
{/block}
大致分析
分析代码是个体力活,所以最好还是要紧跟时代,结合AI分析,事半功倍,所以先请DeepSeek分析一波
大概deepsekk也不想分析.............
回归正题,分析大致意思如下:
页面部分:
头部引入了某些东西,标题还有写好的html头部分,然后内嵌了css样式,可能是外联优先级不够或者是引入css太多有冲突,所以对某一个界面进行特殊设置或独立设置样式,一般都是对于页面整体性的修饰.
然后在头部就引入了两个js,一般js都在页面底部引入,提升页面加载的速度,但这里在头部就引入了而且是单独引入,并没有在style.html中集中引入,所以判断是只有这个页面应用了这两个js,其它页面没有使用,基于这个判断结合下面的代码可以知道,大概率这两个js是用来操控导航栏的,从js文件的命名上也不难看出这一点。
再就是html+vue的页面排版,显示搜索,然后是一级导航输出,二级导航输出,内容输出,然后是两个其它代码,第一个看图片名称是没有数据,所以初步判断就是一张暂无数据的图片类似这种的,然后是加载更多,这个通常都是被控制的,动态显示文字内容,根据数据加载情况来显示。
最后是js部分,请求,挂载,初始化数据,当created()完了以后先调this.getCateList(); 意思是先拿到导航,通过查看Network可以知道,这里接口返回了一级和二级导航的数据
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分析如下:
search
变量,点击搜索触发 goSearch
方法。javascript
data: {
gradeCate: [], // 一级分类数据(如:全部、小学、初中)
subjectCate: [], // 二级分类数据(如:语文、数学)
specialList: [], // 当前展示的课程列表
gradeId: -1, // 当前选中的一级分类ID
subjectId: -1, // 当前选中的二级分类ID
search: '', // 搜索关键词
page: 1, // 当前页码
limit: 10, // 每页数据量
loading: false, // 是否正在加载数据
loadend: false // 是否已加载全部数据
}
getCateList
){:url('special/get_grade_cate')}
。{id: 0, name: '全部'}
。navbarscroll
插件实现横向滚动导航,设置点击回调 endClickScroll
。gradeId
。gradeId !== 0
),调用 getSubject
加载二级分类。getSubject
)gradeCate
找到当前一级分类的子分类。{id: 0, name: '全部', pic: '...'}
。navbarscroll
初始化二级导航,点击时更新 subjectId
并重新加载课程。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
。goSearch
)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"}