一、vo对象的定义
在项目中很多时候需要把model转换成dto用于网站信息的展示,按前端的需要传递对象的数据,保证model对外是隐私的,例如密码之类的属性能很好地避免暴露在外,同时也会减小数据传输的体积。
CourseWebVo.java
package com.guli.edu.vo;
@ApiModel(value="课程信息", description="网站课程详情页需要的相关字段")
@Data
public class CourseWebVo implements Serializable {
private static final long serialVersionUID = 1L;
private String id;
@ApiModelProperty(value = "课程标题")
private String title;
@ApiModelProperty(value = "课程销售价格,设置为0则可免费观看")
private BigDecimal price;
@ApiModelProperty(value = "总课时")
private Integer lessonNum;
@ApiModelProperty(value = "课程封面图片路径")
private String cover;
@ApiModelProperty(value = "销售数量")
private Long buyCount;
@ApiModelProperty(value = "浏览数量")
private Long viewCount;
@ApiModelProperty(value = "课程简介")
private String description;
@ApiModelProperty(value = "讲师ID")
private String teacherId;
@ApiModelProperty(value = "讲师姓名")
private String teacherName;
@ApiModelProperty(value = "讲师资历,一句话说明讲师")
private String intro;
@ApiModelProperty(value = "讲师头像")
private String avatar;
@ApiModelProperty(value = "课程类别ID")
private String subjectLevelOneId;
@ApiModelProperty(value = "类别名称")
private String subjectLevelOne;
@ApiModelProperty(value = "课程类别ID")
private String subjectLevelTwoId;
@ApiModelProperty(value = "类别名称")
private String subjectLevelTwo;
}
二、课程和讲师信息的获取
1、Mapper中关联查询课程和讲师信息
CourseMapper.java
CourseWebVo selectInfoWebById(String courseId);
CourseMapper.xml
<select id="selectInfoWebById" resultType="com.guli.edu.vo.CourseWebVo">
SELECT
c.id,
c.title,
c.cover,
CONVERT(c.price, DECIMAL(8,2)) AS price,
c.lesson_num AS lessonNum,
c.cover,
c.buy_count AS buyCount,
c.view_count AS viewCount,
cd.description,
t.id AS teacherId,
t.name AS teacherName,
t.intro,
t.avatar,
s1.id AS subjectLevelOneId,
s1.title AS subjectLevelOne,
s2.id AS subjectLevelTwoId,
s2.title AS subjectLevelTwo
FROM
edu_course c
LEFT JOIN edu_course_description cd ON c.id = cd.id
LEFT JOIN edu_teacher t ON c.teacher_id = t.id
LEFT JOIN edu_subject s1 ON c.subject_parent_id = s1.id
LEFT JOIN edu_subject s2 ON c.subject_id = s2.id
WHERE
c.id = #{id}
</select>
2、业务层获取数据并更新浏览量
CourseService
接口
/**
* 获取课程信息
* @param id
* @return
*/
CourseWebVo selectInfoWebById(String id);
/**
* 更新课程浏览数
* @param id
*/
void updatePageViewCount(String id);
实现
@Override
public CourseWebVo selectInfoWebById(String id) {
this.updatePageViewCount(id);
return baseMapper.selectInfoWebById(id);
}
@Override
public void updatePageViewCount(String id) {
Course course = baseMapper.selectById(id);
course.setViewCount(course.getViewCount() + 1);
baseMapper.updateById(course);
}
3、接口层
CourseController
@Autowired
private ChapterService chapterService;
@ApiOperation(value = "根据ID查询课程")
@GetMapping(value = "{courseId}")
public R getById(
@ApiParam(name = "courseId", value = "课程ID", required = true)
@PathVariable String courseId){
//查询课程信息和讲师信息
CourseWebVo courseWebVo = courseService.selectInfoWebById(courseId);
//查询当前课程的章节信息
List<ChapterVo> chapterVoList = chapterService.nestedList(courseId);
return R.ok().data("course", courseWebVo).data("chapterVoList", chapterVoList);
}
4、swagger测试
三、前端js
1、api/course.js
getById(courseId) {
return request({
url: `${api_name}/${courseId}`,
method: 'get'
})
}
2、pages/course/_id.vue
<script>
import course from "@/api/course"
export default {
asyncData({ params, error }) {
return course.getById(params.id).then(response => {
console.log(response);
return {
course: response.data.data.course,
chapterList: response.data.data.chapterVoList
}
})
}
}
</script>
四、页面模板
1、template
<template>
<div id="aCoursesList" class="bg-fa of">
<!-- 课程详情 开始 -->
<section class="container">
<!-- 课程所属分类 开始 -->
<!-- /课程所属分类 结束 -->
<!-- 课程基本信息 开始 -->
<!-- /课程基本信息 结束 -->
<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">
<!-- 课程详情介绍 开始 -->
<!-- /课程详情介绍 结束 -->
<!-- 课程大纲 开始-->
<!-- /课程大纲 结束 -->
</article>
</div>
</section>
</article>
<aside class="fl col-3">
<div class="i-box">
<!-- 主讲讲师 开始-->
<!-- /主讲讲师 结束 -->
</div>
</aside>
<div class="clear"/>
</div>
</section>
<!-- /课程详情 结束 -->
</div>
</template>
2、课程所属分类
<!-- 课程所属分类 开始 -->
<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>
<!-- /课程所属分类 结束 -->
3、课程基本信息
<!-- 课程基本信息 开始 -->
<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>
<!-- /课程基本信息 结束 -->
4、课程详情介绍
<!-- 课程详情介绍 开始 -->
<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>
<!-- /课程详情介绍 结束 -->
5、课程大纲
<!-- 课程大纲 开始-->
<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>
<!-- /课程大纲 结束 -->
6、主讲讲师
<!-- 主讲讲师 开始-->
<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="50" height="50" 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>
<!-- /主讲讲师 结束 -->