前台讲师显示
前台讲师列表显示
后端
controller提供分页接口
```java @RestController @CrossOrigin @RequestMapping(“/eduservice/front-teacher”) public class FrontTeacherController {@Autowired private EduTeacherService eduTeacherService;
@Autowired private EduCourseService eduCourseService;
@GetMapping(“pageTeacher/{currentPage}/{limit}”) public ResultEntity pageTeacher(@PathVariable long currentPage, @PathVariable long limit) {
// 此时没有使用element-ui提供的分页组件,返回的参数与后台不一致 Map<String, Object> map = eduTeacherService.getPageFrontTeacher(currentPage, limit); return ResultEntity.ok().data(map);
}
}
- service实现类,此时前端没有使用element的分页组件,返回的数据需要做修改
```java
// 前台返回讲师的分页,与后台系统有区别
@Override
public Map<String, Object> getPageFrontTeacher(long currentPage, long limit) {
Page<EduTeacher> eduTeacherPage = new Page<EduTeacher>(currentPage, limit);
baseMapper.selectPage(eduTeacherPage, null);
HashMap<String, Object> map = new HashMap<>();
map.put("pageTeacherInfo", eduTeacherPage);
map.put("hasNext", eduTeacherPage.hasNext());
map.put("hasPrevious", eduTeacherPage.hasPrevious());
return map;
}
前端
api定义接口地址
// 分页查询讲师 getPageTeacher(currentPage, limit) { return request({ url: `/eduservice/front-teacher/pageTeacher/${currentPage}/${limit}`, method: 'get' }) },
使用异步请求调用查询讲师方法,相当于created(),在页面渲染之前调用
```javascript- 讲师显示和页码显示 ```vue <!-- 讲师列表 开始 --> <section class="container"> <header class="comm-title all-teacher-title"> <h2 class="fl tac"> <span class="c-333">全部讲师</span> </h2> <section class="c-tab-title"> <a id="subjectAll" title="全部" href="#">全部</a> <!-- <c:forEach var="subject" items="${subjectList }"> <a id="${subject.subjectId}" title="${subject.subjectName }" href="javascript:void(0)" onclick="submitForm(${subject.subjectId})">${subject.subjectName }</a> </c:forEach>--> </section> </header> <section class="c-sort-box unBr"> <div> <!-- /无数据提示 开始--> <section class="no-data-wrap" v-if="data.pageTeacherInfo.total == 0"> <em class="icon30 no-data-ico"> </em> <span class="c-666 fsize14 ml10 vam" >没有相关数据,小编正在努力整理中...</span > </section> <!-- /无数据提示 结束--> <!-- /数据列表 开始--> <article v-if="data.pageTeacherInfo.total > 0" class="i-teacher-list"> <ul class="of"> <li v-for="item in data.pageTeacherInfo.records" :key="item.id"> <section class="i-teach-wrap"> <div class="i-teach-pic"> <a :href="'/teacher/' + item.id" :title="item.name"> <img :src="item.avatar" :alt="item.name" height="142" hright="142" /> </a> </div> <div class="mt10 hLh30 txtOf tac"> <a :href="'/teacher/' + item.id" :title="item.name" class="fsize18 c-666" >{{ item.name }}</a > </div> <div class="hLh30 txtOf tac"> <span class="fsize14 c-999">{{ item.career }}</span> </div> <div class="mt15 i-q-txt"> <p class="c-999 f-fA">{{ item.intro }}</p> </div> </section> </li> </ul> <div class="clear" /> </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.pageTeacherInfo.current - 1)" ><</a > <a v-for="page in data.pageTeacherInfo.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.pageTeacherInfo.current + 1)" >></a > <a :class="{ undisable: !data.hasNext }" href="#" title="末页" @click.prevent="gotoPage(data.pageTeacherInfo.pages)" >末</a > <div class="clear" /> </div> </div> <!-- 公共分页 结束 --> </section> </section> <!-- /讲师列表 结束 -->
讲师详情显示
后端
controller方法
@GetMapping("getTeacherInfoById/{teacherId}") public ResultEntity getTeacherInfoById(@PathVariable String teacherId) { // 根据讲师id查询讲师的基本信息 EduTeacher eduTeacher = eduTeacherService.getById(teacherId); // 根据讲师id查询课程的基本信息 List<EduCourse> eduCourseList = eduCourseService.getCourseByTeacherId(teacherId); return ResultEntity.ok().data("teacher", eduTeacher).data("courseList", eduCourseList); }
service实现查询课程的基本信息
@Override public List<EduCourse> getCourseByTeacherId(String teacherId) { QueryWrapper<EduCourse> eduCourseQueryWrapper = new QueryWrapper<>(); eduCourseQueryWrapper.eq("teacher_id" , teacherId); List<EduCourse> eduCourseList = baseMapper.selectList(eduCourseQueryWrapper); return eduCourseList; }
前端
api中定义接口地址
// 查询讲师详情 getTeacherInfoById(teacherId) { return request({ url: `/eduservice/front-teacher/getTeacherInfoById/${teacherId}`, method: 'get' }) }
动态路由页面_id中js调用方法
```javascript- 讲师介绍显示 ```vue <!-- 讲师介绍 开始 --> <section class="container"> <header class="comm-title"> <h2 class="fl tac"> <span class="c-333">讲师介绍</span> </h2> </header> <div class="t-infor-wrap"> <!-- 讲师基本信息 开始 --> <section class="fl t-infor-box c-desc-content"> <div class="mt20 ml20"> <section class="t-infor-pic"> <img :src="teacher.avatar" :alt="teacher.name" /> </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> </section> <!-- /讲师基本信息 结束 -->
- 讲师所讲课程信息显示
```vue<span class=”c-666 fsize14 ml10 vam” >没有相关数据,小编正在努力整理中...</span >
-
<a :href=”‘/course/‘ + course.id” title=”开始学习” target=”_blank” class=”comm-btn c-btn-1”
>开始学习</a > </div> </section> <h3 class="hLh30 txtOf mt10"> <a :href="'/course/' + course.id" :title="course.title" target="_blank" class="course-title fsize18 c-333" >{{ course.title }}</a > </h3> </div> </li> </ul> <div class="clear" />
<a name="785a2c60"></a> # 前台课程模块 <a name="212b47d9"></a> ## 前台课程列表显示 <a name="e778d61a-24"></a> ### 后端 - 定义VO对象,封装查询条件 ```java @ApiModel(value = "课程查询对象", description = "课程查询对象封装") @Data public class FrontCourseQueryVO 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; }
controller
@RestController @CrossOrigin @RequestMapping("/eduservice/front-course") public class FrontCourseController { @Autowired private EduCourseService eduCourseService; @Autowired private EduChapterService eduChapterService; @PostMapping("getPageCourseByCondition/{currentPage}/{limit}") public ResultEntity getPageCourseByCondition( @PathVariable long currentPage, @PathVariable long limit, @RequestBody(required = false) FrontCourseQueryVO courseQueryVO ) { Map<String, Object> map = eduCourseService.getPageCourseByCondition(currentPage, limit, courseQueryVO); return ResultEntity.ok().data(map); } }
service实现
// 前台条件查询 @Override public Map<String, Object> getPageCourseByCondition(long currentPage, long limit, FrontCourseQueryVO courseQueryVO) { Page<EduCourse> eduCoursePage = new Page<>(currentPage , limit); QueryWrapper<EduCourse> eduCourseQueryWrapper = new QueryWrapper<>(); // 获取条件 String subjectParentId = courseQueryVO.getSubjectParentId(); String subjectId = courseQueryVO.getSubjectId(); String buyCountSort = courseQueryVO.getBuyCountSort(); String gmtCreateSort = courseQueryVO.getGmtCreateSort(); String priceSort = courseQueryVO.getPriceSort(); // 判断条件中的值是否存在,在进行封装条件 if (!StringUtils.isEmpty(subjectParentId)) { // 一级分类 eduCourseQueryWrapper.eq("subject_parent_id", subjectParentId); } if (!StringUtils.isEmpty(subjectId)) { // 二级分类 eduCourseQueryWrapper.eq("subject_id", subjectId); } if (!StringUtils.isEmpty(buyCountSort)) { eduCourseQueryWrapper.orderByDesc("buy_count"); } if (!StringUtils.isEmpty(gmtCreateSort)) { eduCourseQueryWrapper.orderByDesc("gmt_create"); } if (!StringUtils.isEmpty(priceSort)) { eduCourseQueryWrapper.orderByDesc("price"); } eduCourseQueryWrapper.eq("status","Normal"); // 查询对象 baseMapper.selectPage(eduCoursePage, eduCourseQueryWrapper); List<EduCourse> records = eduCoursePage.getRecords(); long current = eduCoursePage.getCurrent(); long pages = eduCoursePage.getPages(); long size = eduCoursePage.getSize(); long total = eduCoursePage.getTotal(); boolean hasNext = eduCoursePage.hasNext(); boolean hasPrevious = eduCoursePage.hasPrevious(); // 封装在map中返回 HashMap<String, Object> map = new HashMap<>(); map.put("items", records); map.put("current", current); map.put("pages", pages); map.put("size", size); map.put("total", total); map.put("hasNext", hasNext); map.put("hasPrevious", hasPrevious); return map; }
前端
api中定义接口地址
// 条件分页查询讲师 getPageTeacher(currentPage, limit , courseVO) { return request({ url: `/eduservice/front-course/getPageCourseByCondition/${currentPage}/${limit}`, method: 'post', data: courseVO }) }, // 查询所有分类 getSubjectAll() { return request({ url: `/eduservice/edu-subject/listSubject`, method: 'get' }) },
js实现调用,通过点击事件封装条件
```javascript- 页面显示 ```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="/course" @click="searchOne('')" >全部</a > </li> <li v-for="(item, index) in subjectNestedList" v-bind:key="index" :class="{ active: oneIndex == index }" > <a :title="item.title" href="javascript:void(0);" @click="searchOne(item.id, index)" >{{ item.title }}</a > </li> </ul> </dd> </dl> <dl> <dt> <span class="c-999 fsize14" /> </dt> <dd class="c-s-dl-li"> <ul class="clearfix"> <li v-for="(item, index) in subSubjectList" v-bind:key="index" :class="{ active: twoIndex == index }" > <a :title="item.title" href="javascript:void(0);" @click="searchTwo(item.id, index)" >{{ item.title }}</a > </li> </ul> </dd> </dl> <div class="clear" /> </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 v-if="data.total > 0" class="comm-course-list"> <ul id="bna" class="of"> <li v-for="item in data.items" :key="item.id"> <div class="cc-l-wrap"> <section class="course-img"> <img :src="item.cover" class="img-responsive" alt="听力口语" width="170px" height="200px" /> <div class="cc-mask"> <a :href="'/course/' + item.id" title="开始学习" class="comm-btn c-btn-1" >开始学习</a > </div> </section> <h3 class="hLh30 txtOf mt10"> <a :href="'/course/' + item.id" :title="item.title" class="course-title fsize18 c-333" >{{ item.title }}</a > </h3> <section class="mt10 hLh20 of"> <span v-if="Number(item.price) === 0" class="fr jgTag bg-green" > <i class="c-fff fsize12 f-fA">免费</i> </span> <span class="fl jgAttr c-ccc f-fA"> <i class="c-999 f-fA">{{ item.viewCount }}人学习</i> | <i class="c-999 f-fA">9634评论</i> </span> </section> </div> </li> </ul> <div class="clear" /> </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>
前台课程详情
后端
在页面上显示的内容封装为一个VO对象
@ApiModel(value = "课程基本信息", description = "编辑课程基本信息的表单对象") @Data @AllArgsConstructor @NoArgsConstructor public class CourseInfoVO implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "课程ID") private String id; @ApiModelProperty(value = "课程讲师ID") private String teacherId; @ApiModelProperty(value = "课程二级分类ID") private String subjectId; @ApiModelProperty(value = "课程一级分类ID") private String subjectParentId; @ApiModelProperty(value = "课程标题") private String title; @ApiModelProperty(value = "课程销售价格,设置为0则可免费观看") private BigDecimal price; @ApiModelProperty(value = "总课时") private Integer lessonNum; @ApiModelProperty(value = "课程封面图片路径") private String cover; @ApiModelProperty(value = "课程简介") private String description; }
controller,查询章节后台管理已有方法,查询课程VO对象需要多表查询,使用sql语句实现
@GetMapping("getFrontBaseCourse/{courseId}") public ResultEntity getFrontBaseCourse(@PathVariable String courseId) { // 查询课程的VO对象(sql语句查询) FrontBaseCourseVO frontBaseCourseVO = eduCourseService.getFrontBaseCourse(courseId); // 根据课程id查询章节 List<ChapterVO> chapterVOList = eduChapterService.getChapterVO(courseId); return ResultEntity.ok().data("chapterList", chapterVOList).data("courseVO", frontBaseCourseVO); }
service实现
@Override public FrontBaseCourseVO getFrontBaseCourse(String courseId) { return baseMapper.getFrontCourseVO(courseId); }
接口和sql
sql语句FrontBaseCourseVO getFrontCourseVO(@Param("courseId") String courseId);
<select id="getFrontCourseVO" resultType="com.atguigu.eduservice.entity.vo.front.FrontBaseCourseVO"> select ec.id, ec.title, ec.price, ec.lesson_num lessonNum, ec.cover, ec.buy_count buyCount, ec.view_count viewCount, ecd.description, ec.teacher_id teacherId, et.`name` teacherName, et.intro, et.avatar, es1.id subjectLevelOneId, es1.title subjectLevelOne, es2.id subjectLevelTwoId, es2.title subjectLevelTwo from edu_course ec LEFT JOIN edu_teacher et ON ec.teacher_id = et.id LEFT JOIN edu_subject es1 ON ec.subject_parent_id = es1.id LEFT JOIN edu_subject es2 on ec.subject_id = es2.id LEFT JOIN edu_course_description ecd on ec.id = ecd.id where ec.id = #{courseId} </select>
前端
api定义接口地址
// 根据课程id查询课程的相关信息 getFrontBaseCourse(courseId) { return request({ url: `/eduservice/front-course/getFrontBaseCourse/${courseId}`, method: 'get' }) }
js实现方法调用
```java- 将数据显示在页面上 ```vue <template> <div id="aCoursesList" class="bg-fa of"> <!-- 课程详情 开始 --> <section class="container"> <!-- 课程所属分类 开始 --> <section class="path-wrap txtOf hLh30"> <a href="#" title class="c-999 fsize14">首页</a> \ <a href="/course" title class="c-999 fsize14">课程列表</a> \ <span class="c-333 fsize14">{{ course.subjectLevelOne }}</span> \ <span class="c-333 fsize14">{{ course.subjectLevelTwo }}</span> </section> <!-- /课程所属分类 结束 --> <!-- 课程基本信息 开始 --> <div> <article class="c-v-pic-wrap" style="height: 357px"> <section id="videoPlay" class="p-h-video-box"> <img :src="course.cover" :alt="course.title" class="dis c-v-pic" /> </section> </article> <aside class="c-attr-wrap"> <section class="ml20 mr15"> <h2 class="hLh30 txtOf mt15"> <span class="c-fff fsize24">{{ course.title }}</span> </h2> <section class="c-attr-jg"> <span class="c-fff">价格:</span> <b class="c-yellow" style="font-size: 24px" >¥{{ course.price }}</b > </section> <section class="c-attr-mt c-attr-undis"> <span class="c-fff fsize14" >主讲: {{ course.teacherName }} </span > </section> <section class="c-attr-mt of"> <span class="ml10 vam"> <em class="icon18 scIcon" /> <a class="c-fff vam" title="收藏" href="#">收藏</a> </span> </section> <section class="c-attr-mt"> <a href="#" title="立即观看" class="comm-btn c-btn-3">立即观看</a> </section> </section> </aside> <aside class="thr-attr-box"> <ol class="thr-attr-ol clearfix"> <li> <p> </p> <aside> <span class="c-fff f-fM">购买数</span> <br /> <h6 class="c-fff f-fM mt10">{{ course.buyCount }}</h6> </aside> </li> <li> <p> </p> <aside> <span class="c-fff f-fM">课时数</span> <br /> <h6 class="c-fff f-fM mt10">{{ course.lessonNum }}</h6> </aside> </li> <li> <p> </p> <aside> <span class="c-fff f-fM">浏览数</span> <br /> <h6 class="c-fff f-fM mt10">{{ course.viewCount }}</h6> </aside> </li> </ol> </aside> <div class="clear" /> </div> <!-- /课程基本信息 结束 --> <div class="mt20 c-infor-box"> <article class="fl col-7"> <section class="mr30"> <div class="i-box"> <div> <section id="c-i-tabTitle" class="c-infor-tabTitle c-tab-title"> <a name="c-i" class="current" title="课程详情">课程详情</a> </section> </div> <article class="ml10 mr10 pt20"> <!-- 课程详情介绍 开始 --> <div> <h6 class="c-i-content c-infor-title"> <span>课程介绍</span> </h6> <div class="course-txt-body-wrap"> <section class="course-txt-body"> <!-- 将内容中的html翻译过来 --> <p v-html="course.description"> {{ course.description }} </p> </section> </div> </div> <!-- /课程详情介绍 结束 --> <!-- 课程大纲 开始--> <div class="mt50"> <h6 class="c-g-content c-infor-title"> <span>课程大纲</span> </h6> <section class="mt20"> <div class="lh-menu-wrap"> <menu id="lh-menu" class="lh-menu mt10 mr10"> <ul> <!-- 课程章节目录 --> <li v-for="chapter in chapterList" :key="chapter.id" class="lh-menu-stair" > <a :title="chapter.title" href="javascript: void(0)" class="current-1" > <em class="lh-menu-i-1 icon18 mr10" />{{ chapter.title }} </a> <ol class="lh-menu-ol" style="display: block"> <li v-for="video in chapter.children" :key="video.id" class="lh-menu-second ml30" > <a href="#" title> <span v-if="video.free === true" class="fr"> <i class="free-icon vam mr10">免费试听</i> </span> <em class="lh-menu-i-2 icon16 mr5"> </em >{{ video.title }} </a> </li> </ol> </li> </ul> </menu> </div> </section> </div> <!-- /课程大纲 结束 --> </article> </div> </section> </article> <aside class="fl col-3"> <div class="i-box"> <!-- 主讲讲师 开始--> <div> <section class="c-infor-tabTitle c-tab-title"> <a title href="javascript:void(0)">主讲讲师</a> </section> <section class="stud-act-list"> <ul style="height: auto"> <li> <div class="u-face"> <a :href="'/teacher/' + course.teacherId" target="_blank"> <img :src="course.avatar" width="50px" height="50px" alt /> </a> </div> <section class="hLh30 txtOf"> <a :href="'/teacher/' + course.teacherId" class="c-333 fsize16 fl" target="_blank" >{{ course.teacherName }}</a > </section> <section class="hLh20 txtOf"> <span class="c-999">{{ course.intro }}</span> </section> </li> </ul> </section> </div> <!-- /主讲讲师 结束 --> </div> </aside> <div class="clear" /> </div> </section> <!-- /课程详情 结束 --> </div> </template>
- 讲师所讲课程信息显示