静态路由和动态路由:顶部栏固定的链接跳转时静态路由;点击心仪讲师实现具体信息页面显示是动态路由
名师列表
后端
后端接口controller
- 分页条件查,且每页显示8条讲师记录,且是热门讲师
此分页条件查区别于之前的课程页面,此处未使用element-ui组件
@Api(description = "讲师管理前端") @RestController @RequestMapping("/eduservice/teacherfront") @CrossOrigin public class TeacherFrontController { @Autowired private EduTeacherService teacherService; @Autowired private EduCourseService courseService; @ApiOperation(value = "分页查询所有讲师") @PostMapping("getTeacherFrontList/{page}/{limit}") public R getTeacherFrontList(@PathVariable long page,@PathVariable long limit) { Page<EduTeacher> pageTeacher = new Page<>(page, limit); Map<String,Object> map = teacherService.getTeacherFrontList(pageTeacher); //返回封装的数据 return R.ok().data(map); } }
实现接口中的方法
@Override public Map<String, Object> getTeacherFrontList(Page<EduTeacher> pageParam) { QueryWrapper<EduTeacher> wrapper = new QueryWrapper<>(); wrapper.orderByDesc("id"); baseMapper.selectPage(pageParam,wrapper); List<EduTeacher> records = pageParam.getRecords(); long current = pageParam.getCurrent(); long pages = pageParam.getPages(); long size = pageParam.getSize(); long total = pageParam.getTotal(); boolean hasNext = pageParam.hasNext();//下一页 boolean hasPrevious = pageParam.hasPrevious();//上一页 //把分页数据获取出来,放到map集合 Map<String,Object> map = new HashMap<>(); map.put("items",records); map.put("pages",pages); map.put("current",current); map.put("size",size); map.put("total",total); map.put("hasNext",hasNext); map.put("hasPrevious",hasPrevious); return map; }
前端
前端接口teacher.js ```javascript import request from ‘@/utils/request’
export default {
//查询讲师信息方法
getTeacherList(page,limit) {
return request({
url: /eduservice/teacherfront/getTeacherFrontList/${page}/${limit}
,
method: ‘post’
})
},
}
2. 讲师页面调用api获取数据
```javascript
<script>
import teacherApi from '@/api/teacher'
export default {
//异步调用,调用一次
//params: 相当于之前 this.$route.params.id 等价 params.id
asyncData({ params, error }) {
return teacherApi.getTeacherList(1,8).then(response => {
//this.data = response.data.data
return { data: response.data.data }
})
},
methods:{
//分页切换的方法
//参数是页码数
gotoPage(page) {
teacherApi.getTeacherList(page,8)
.then(response => {
this.data = response.data.data
})
}
}
};
</script>
分页展示和页面展示 ```java ========================页面展示=================
没有相关数据,小编正在努力整理中… -
{{teacher.intro}}
{{teacher.career}}
<a
:class="{undisable: !data.hasPrevious}" href="#" title="首页" @click.prevent="gotoPage(1)">首页</a>
<a
:class="{undisable: !data.hasPrevious}" href="#" title="前一页" @click.prevent="gotoPage(data.current-1)"><</a>
<a
v-for="page in data.pages" :key="page" :class="{current: data.current == page, undisable: data.current == page}" :title="'第'+page+'页'" href="#" @click.prevent="gotoPage(page)">{{ page }}</a>
<a
:class="{undisable: !data.hasNext}" href="#" title="后一页" @click.prevent="gotoPage(data.current+1)">></a>
<a
:class="{undisable: !data.hasNext}" href="#" title="末页" @click.prevent="gotoPage(data.pages)">末页</a>
-
<a name="Z21BI"></a>
# 名师详情
<a name="dfxfp"></a>
## 后端
```java
@ApiOperation(value = "讲师详情功能")
@GetMapping("getTeacherFrontInfo/{teacherId}")
public R getTeacherFrontInfo(@PathVariable String teacherId) {
//根据讲师id 查询讲师基本信息
EduTeacher teacher = teacherService.getById(teacherId);
//根据讲师id 查询课程基本信息
QueryWrapper<EduCourse> wrapper = new QueryWrapper<>();
wrapper.eq("teacher_id",teacherId);
List<EduCourse> courseList = courseService.list(wrapper);
return R.ok().data("teacher",teacher).data("courseList",courseList);
}
前端
前端api
//根据讲师id查询详情 getTeacherInfo(id) { return request({ url: `/eduservice/teacherfront/getTeacherFrontInfo/${id}`, method: 'get' }) }
讲师详情页调用数据: pages/teacher/_id.vue ```javascript
3. 讲师详情页面 ```vue <!-- 讲师基本信息 --> <section class="fl t-infor-box c-desc-content"> <div class="mt20 ml20"> <section class="t-infor-pic"> <img :src="teacher.avatar"> </section> <h3 class="hLh30"> <span class="fsize24 c-333">{{teacher.name}} {{ teacher.level===1?'高级讲师':'首席讲师' }} </span> </h3> <section class="mt10"> <span class="t-tag-bg">{{teacher.intro}}</span> </section> <section class="t-infor-txt"> <p class="mt20">{{teacher.career}}</p> </section> <div class="clear"></div> </div> </section> <!-- /无数据提示 开始--> <section class="no-data-wrap" v-if="courseList.length==0"> <em class="icon30 no-data-ico"> </em> <span class="c-666 fsize14 ml10 vam">没有相关数据,小编正在努力整理中...</span> </section> <!-- /无数据提示 结束--> <!-- 当前讲师课程列表--> <article class="comm-course-list"> <ul class="of"> <li v-for="course in courseList" :key="course.id"> <div class="cc-l-wrap"> <section class="course-img"> <img :src="course.cover" class="img-responsive" > <div class="cc-mask"> <a href="#" title="开始学习" target="_blank" class="comm-btn c-btn-1">开始学习</a> </div> </section> <h3 class="hLh30 txtOf mt10"> <a href="#" :title="course.title" target="_blank" class="course-title fsize18 c-333">{{course.title}}</a> </h3> </div> </li> </ul> <div class="clear"></div> </article>
课程列表
后端
后端vo类 ```java @Data public class CourseFrontVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = “课程名称”) private String title;
@ApiModelProperty(value = “讲师id”) private String teacherId;
@ApiModelProperty(value = “一级类别id”) private String subjectParentId;
@ApiModelProperty(value = “二级类别id”) private String subjectId;
@ApiModelProperty(value = “销量排序”) private String buyCountSort;
@ApiModelProperty(value = “最新时间排序”) private String gmtCreateSort;
@ApiModelProperty(value = “价格排序”) private String priceSort;
}
2. service接口及实现类 ```java public interface EduCourseService extends IService<EduCourse> { ...... //前台多条件分页查询 Map<String, Object> getCourseFrontInfo(Page<EduCourse> pageCourse, CourseFrontVo courseFrontVo); }
@Service public class EduCourseServiceImpl extends ServiceImpl<EduCourseMapper, EduCourse> implements EduCourseService { //前台多条件分页查询 @Override public Map<String, Object> getCourseFrontInfo(Page<EduCourse> pageCourse, CourseFrontVo courseFrontVo) { String title = null; String subjectId = null; String subjectParentId = null; String gmtCreateSort = null; String buyCountSort = null; String priceSort = null; String teacherId = null; if (!StringUtils.isEmpty(courseFrontVo)){ title = courseFrontVo.getTitle(); subjectId = courseFrontVo.getSubjectId(); subjectParentId = courseFrontVo.getSubjectParentId(); gmtCreateSort = courseFrontVo.getGmtCreateSort(); buyCountSort = courseFrontVo.getBuyCountSort(); priceSort = courseFrontVo.getPriceSort(); teacherId = courseFrontVo.getTeacherId(); } QueryWrapper<EduCourse> wrapper = new QueryWrapper<>(); //判断条件值是否为空,不为空拼接条件 if (!StringUtils.isEmpty(subjectParentId)){//一级分类 wrapper.eq("subject_parent_id",subjectParentId); } if (!StringUtils.isEmpty(subjectId)){//二级分类 wrapper.eq("subject_id",subjectId); } if (!StringUtils.isEmpty(buyCountSort)){//关注度 wrapper.orderByDesc("buy_count"); } if (!StringUtils.isEmpty(priceSort)){//价格 wrapper.orderByDesc("price"); } if (!StringUtils.isEmpty(gmtCreateSort)){//最新,创建时间 wrapper.orderByDesc("gmt_create"); } baseMapper.selectPage(pageCourse, wrapper); long total = pageCourse.getTotal();//总记录数 List<EduCourse> courseList = pageCourse.getRecords();//数据集合 long size = pageCourse.getSize();//每页记录数 long current = pageCourse.getCurrent();//当前页 long pages = pageCourse.getPages();//总页数 boolean hasPrevious = pageCourse.hasPrevious();//是否有上一页 boolean hasNext = pageCourse.hasNext();//是否有下一页 HashMap<String, Object> map = new HashMap<>(); map.put("total",total); map.put("list",courseList); map.put("size",size); map.put("current",current); map.put("pages",pages); map.put("hasPrevious",hasPrevious); map.put("hasNext",hasNext); return map; } }
前端
- 前端api api/course.js ```javascript import request from ‘@/utils/request’
export default{ //前台多条件分页查询 getConditionPage(page,limit,searchObj){ return request({ url:
/eduservice/courseFront/getConditionPage/${page}/${limit}
, method: ‘post’, data: searchObj }) }, //查询所有分类(一级分类、二级分类)的方法 getAllSubject(){ return request({ url:/eduservice/edu-subject/getAllSubject
, method: ‘get’ }) } }2. pages/course/index.vue ```javascript <script> import courseApi from "@/api/course"; export default { data() { return { page: 1, //当前页 data: {}, //课程列表 subjectNestedList: [], // 一级分类列表 subSubjectList: [], // 二级分类列表 searchObj: {}, // 查询表单对象 oneIndex: -1, twoIndex: -1, buyCountSort: "", gmtCreateSort: "", priceSort: "", }; }, methods: { //根据价格进行排序 searchPrice(){ //设置对应变量值,为了样式生效 this.buyCountSort='' this.gmtCreateSort='' this.priceSort='1' //把值赋值到searchObj中 this.searchObj.buyCountSort = this.buyCountSort this.searchObj.priceSort = this.priceSort this.searchObj.gmtCreateSort = this.gmtCreateSort //调用方法查询 this.gotoPage(1) }, //根据最新进行排序 searchGmtCreate(){ //设置对应变量值,为了样式生效 this.buyCountSort='' this.gmtCreateSort='1' this.priceSort='' //把值赋值到searchObj中 this.searchObj.buyCountSort = this.buyCountSort this.searchObj.priceSort = this.priceSort this.searchObj.gmtCreateSort = this.gmtCreateSort //调用方法查询 this.gotoPage(1) }, //根据销量排序 searchBuyCount(){ //设置对应变量值,为了样式生效 this.buyCountSort='1' this.gmtCreateSort='' this.priceSort='' //把值赋值到searchObj中 this.searchObj.buyCountSort = this.buyCountSort this.searchObj.priceSort = this.priceSort this.searchObj.gmtCreateSort = this.gmtCreateSort //调用方法查询 this.gotoPage(1) }, //课程第一次查询 initCourseFirst() { courseApi.getConditionPage(1, 8, this.searchObj).then((resp) => { this.data = resp.data.data; }); }, //查询所有一级分类 initSubject() { courseApi.getAllSubject().then((resp) => { this.subjectNestedList = resp.data.data.list; // this.subSubjectList = resp.data.data.list.children }); }, //分页切换方法 gotoPage(page) { courseApi.getConditionPage(page, 8, this.searchObj).then((resp) => { this.data = resp.data.data; }); }, //点击某个一级分类,查询对应的二级分类 seacherOne(subjectParentId, index) { //把传递来的index赋值给ondex,为了active样式生效 // this.oneIndex = index // this.twoIndex = -1 // this.searchObj.subjectId='' // this.subSubjectList=[] //把一级分类点击的id值,赋值给searchObj this.searchObj.subjectParentId = subjectParentId; //点击某个一级分类进行条件查询 this.gotoPage(1); //拿着点击的一级分类id 和 所有一级分类id进行比较 //如果id相同,从那个一级分类中获取他的二级分类 for (let i = 0; i < this.subjectNestedList.length; i++) { //获取每个一级分类 var oneSubject = this.subjectNestedList[i]; //比较id是否相同 if (oneSubject.id == subjectParentId) { this.subSubjectList = oneSubject.children; } } }, //点击某个二级分类实现查询 searchTwo(subjectId, index) { //把index赋值,为了样式生效 this.twoIndex = index; //把二级分类点击id值,赋给searchObj this.searchObj.subjectId = subjectId; //点击某个二级分类进行调节查询 this.gotoPage(1); }, }, created() { //课程第一次查询 this.initCourseFirst(); //一级分类显示 this.initSubject(); }, }; </script> <style scoped> .active { background: #bdbdbd; } .hide { display: none; } .show { display: block; } </style>
- index.vue页面
<template> <div id="aCoursesList" class="bg-fa of"> <!-- /课程列表 开始 --> <section class="container"> <header class="comm-title"> <h2 class="fl tac"> <span class="c-333">全部课程</span> </h2> </header> <section class="c-sort-box"> <section class="c-s-dl"> <dl> <dt> <span class="c-999 fsize14">课程类别</span> </dt> <dd class="c-s-dl-li"> <ul class="clearfix"> <li> <a title="全部" href="#">全部</a> </li> <li v-for="subjectNested in subjectNestedList" :key="subjectNested.id" > <a :title="subjectNested.title" @click="seacherOne(subjectNested.id, index)" href="#" >{{ subjectNested.title }}</a > </li> </ul> </dd> </dl> <dl> <dt> <span class="c-999 fsize14"></span> </dt> <dd class="c-s-dl-li"> <ul class="clearfix"> <li v-for="subject in subSubjectList" :key="subject.id"> <a :title="subject.title" @click="searchTwo(subject.id, index)" href="#" >{{ subject.title }}</a > </li> </ul> </dd> </dl> <div class="clear"></div> </section> <div class="js-wrap"> <section class="fr"> <span class="c-ccc"> <i class="c-master f-fM">1</i>/ <i class="c-666 f-fM">1</i> </span> </section> <section class="fl"> <ol class="js-tap clearfix"> <li :class="{ 'current bg-orange': buyCountSort != '' }"> <a title="销量" href="javascript:void(0);" @click="searchBuyCount()" >销量 <span :class="{ hide: buyCountSort == '' }">↓</span> </a> </li> <li :class="{ 'current bg-orange': gmtCreateSort != '' }"> <a title="最新" href="javascript:void(0);" @click="searchGmtCreate()" >最新 <span :class="{ hide: gmtCreateSort == '' }">↓</span> </a> </li> <li :class="{ 'current bg-orange': priceSort != '' }"> <a title="价格" href="javascript:void(0);" @click="searchPrice()" >价格 <span :class="{ hide: priceSort == '' }">↓</span> </a> </li> </ol> </section> </div> <div class="mt40"> <!-- /无数据提示 开始--> <section class="no-data-wrap" v-if="data.total == 0"> <em class="icon30 no-data-ico"> </em> <span class="c-666 fsize14 ml10 vam" >没有相关数据,小编正在努力整理 中...</span > </section> <!-- /无数据提示 结束--> <article class="comm-course-list" v-if="data.total > 0"> <ul class="of" id="bna"> <li v-for="item in data.list" :key="item.id"> <div class="cc-l-wrap"> <section class="course-img"> <img :src="item.cover" class="img-responsive" :alt="item.title" /> <div class="cc-mask"> <a href="/course/1" title="开始学习" class="comm-btn c- btn-1" >开始学习</a > </div> </section> <h3 class="hLh30 txtOf mt10"> <a href="/course/1" :title="item.title" class="course-title fsize18 c-333" >{{ item.title }}</a > </h3> <section class="mt10 hLh20 of"> <span class="fr jgTag bg-green" v-if="Number(item.price) === 0" > <i class="c-fff fsize12 f-fA">免费</i> </span> <span class="fl jgAttr c-ccc f-fA"> <i class="c-999 f-fA">9634人学习</i> | <i class="c-999 f-fA">9634评论</i> </span> </section> </div> </li> </ul> <div class="clear"></div> </article> </div> <!-- 公共分页 开始 --> <div> <div class="paging"> <!-- undisable这个class是否存在,取决于数据属性hasPrevious --> <a :class="{ undisable: !data.hasPrevious }" href="#" title="首页" @click.prevent="gotoPage(1)" >首</a > <a :class="{ undisable: !data.hasPrevious }" href="#" title="前一页" @click.prevent="gotoPage(data.current - 1)" ><</a > <a v-for="page in data.pages" :key="page" :class="{ current: data.current == page, undisable: data.current == page, }" :title="'第' + page + '页'" href="#" @click.prevent="gotoPage(page)" >{{ page }}</a > <a :class="{ undisable: !data.hasNext }" href="#" title="后一页" @click.prevent="gotoPage(data.current + 1)" >></a > <a :class="{ undisable: !data.hasNext }" href="#" title="末页" @click.prevent="gotoPage(data.pages)" >末</a > <div class="clear" /> </div> </div> <!-- 公共分页 结束 --> </section> </section> <!-- /课程列表 结束 --> </div> </template>