SpringBoot在线教育项目(十四)

一、名师页面静态效果整合

一、列表页面

创建 pages/teacher/index.vue

<template>
  <div id="aCoursesList" class="bg-fa of">
    <!-- 讲师列表 开始 -->
    <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">
            <em class="icon30 no-data-ico">&nbsp;</em>
            <span class="c-666 fsize14 ml10 vam">没有相关数据,小编正在努力整理中...</span>
          </section>
          <!-- /无数据提示 结束-->
          <article class="i-teacher-list">
            <ul class="of">
              <li>
                <section class="i-teach-wrap">
                  <div class="i-teach-pic">
                    <a href="/teacher/1" title="姚晨" target="_blank">
                      <img src="~/assets/photo/teacher/1442297885942.jpg" alt>
                    </a>
                  </div>
                  <div class="mt10 hLh30 txtOf tac">
                    <a href="/teacher/1" title="姚晨" target="_blank" class="fsize18 c-666">姚晨</a>
                  </div>
                  <div class="hLh30 txtOf tac">
                    <span class="fsize14 c-999">北京师范大学法学院副教授、清华大学法学博士。自2004年至今已有9年的司法考试培训经验。长期从事司法考试辅导,深知命题规律,了解解题技巧。内容把握准确,授课重点明确,层次分明,调理清晰,将法条法理与案例有机融合,强调综合,深入浅出。</span>
                  </div>
                  <div class="mt15 i-q-txt">
                    <p class="c-999 f-fA">北京师范大学法学院副教授</p>
                  </div>
                </section>
              </li>
              <li>
                <section class="i-teach-wrap">
                  <div class="i-teach-pic">
                    <a href="/teacher/1" title="谢娜" target="_blank">
                      <img src="~/assets/photo/teacher/1442297919077.jpg" alt>
                    </a>
                  </div>
                  <div class="mt10 hLh30 txtOf tac">
                    <a href="/teacher/1" title="谢娜" target="_blank" class="fsize18 c-666">谢娜</a>
                  </div>
                  <div class="hLh30 txtOf tac">
                    <span class="fsize14 c-999">十年课程研发和培训咨询经验,曾任国企人力资源经理、大型外企培训经理,负责企业大学和培训体系搭建;曾任专业培训机构高级顾问、研发部总监,为包括广东移动、东莞移动、深圳移动、南方电网、工商银行、农业银行、民生银行、邮储银行、TCL集团、清华大学继续教育学院、中天路桥、广西扬翔股份等超过200家企业提供过培训与咨询服务,并担任近50个大型项目的总负责人。</span>
                  </div>
                  <div class="mt15 i-q-txt">
                    <p class="c-999 f-fA">资深课程设计专家,专注10年AACTP美国培训协会认证导师</p>
                  </div>
                </section>
              </li>
              <li>
                <section class="i-teach-wrap">
                  <div class="i-teach-pic">
                    <a href="/teacher/1" title="刘德华" target="_blank">
                      <img src="~/assets/photo/teacher/1442297927029.jpg" alt>
                    </a>
                  </div>
                  <div class="mt10 hLh30 txtOf tac">
                    <a href="/teacher/1" title="刘德华" target="_blank" class="fsize18 c-666">刘德华</a>
                  </div>
                  <div class="hLh30 txtOf tac">
                    <span class="fsize14 c-999">上海师范大学法学院副教授、清华大学法学博士。自2004年至今已有9年的司法考试培训经验。长期从事司法考试辅导,深知命题规律,了解解题技巧。内容把握准确,授课重点明确,层次分明,调理清晰,将法条法理与案例有机融合,强调综合,深入浅出。</span>
                  </div>
                  <div class="mt15 i-q-txt">
                    <p class="c-999 f-fA">上海师范大学法学院副教授</p>
                  </div>
                </section>
              </li>
              <li>
                <section class="i-teach-wrap">
                  <div class="i-teach-pic">
                    <a href="/teacher/1" title="周润发" target="_blank">
                      <img src="~/assets/photo/teacher/1442297935589.jpg" alt>
                    </a>
                  </div>
                  <div class="mt10 hLh30 txtOf tac">
                    <a href="/teacher/1" title="周润发" target="_blank" class="fsize18 c-666">周润发</a>
                  </div>
                  <div class="hLh30 txtOf tac">
                    <span class="fsize14 c-999">法学博士,北京师范大学马克思主义学院副教授,专攻毛泽东思想概论、邓小平理论,长期从事考研辅导。出版著作两部,发表学术论文30余篇,主持国家社会科学基金项目和教育部重大课题子课题各一项,参与中央实施马克思主义理论研究和建设工程项目。</span>
                  </div>
                  <div class="mt15 i-q-txt">
                    <p class="c-999 f-fA">考研政治辅导实战派专家,全国考研政治命题研究组核心成员。</p>
                  </div>
                </section>
              </li>
              <li>
                <section class="i-teach-wrap">
                  <div class="i-teach-pic">
                    <a href="/teacher/1" title="钟汉良" target="_blank">
                      <img src="~/assets/photo/teacher/1442298121626.jpg" alt>
                    </a>
                  </div>
                  <div class="mt10 hLh30 txtOf tac">
                    <a href="/teacher/1" title="钟汉良" target="_blank" class="fsize18 c-666">钟汉良</a>
                  </div>
                  <div class="hLh30 txtOf tac">
                    <span class="fsize14 c-999">具备深厚的数学思维功底、丰富的小学教育经验,授课风格生动活泼,擅长用形象生动的比喻帮助理解、简单易懂的语言讲解难题,深受学生喜欢</span>
                  </div>
                  <div class="mt15 i-q-txt">
                    <p class="c-999 f-fA">毕业于师范大学数学系,热爱教育事业,执教数学思维6年有余</p>
                  </div>
                </section>
              </li>
              <li>
                <section class="i-teach-wrap">
                  <div class="i-teach-pic">
                    <a href="/teacher/1" title="唐嫣" target="_blank">
                      <img src="~/assets/photo/teacher/1442297957332.jpg" alt>
                    </a>
                  </div>
                  <div class="mt10 hLh30 txtOf tac">
                    <a href="/teacher/1" title="唐嫣" target="_blank" class="fsize18 c-666">唐嫣</a>
                  </div>
                  <div class="hLh30 txtOf tac">
                    <span class="fsize14 c-999">中国科学院数学与系统科学研究院应用数学专业博士,研究方向为数字图像处理,中国工业与应用数学学会会员。参与全国教育科学“十五”规划重点课题“信息化进程中的教育技术发展研究”的子课题“基与课程改革的资源开发与应用”,以及全国“十五”科研规划全国重点项目“掌上型信息技术产品在教学中的运用和开发研究”的子课题“用技术学数学”。</span>
                  </div>
                  <div class="mt15 i-q-txt">
                    <p class="c-999 f-fA">中国人民大学附属中学数学一级教师</p>
                  </div>
                </section>
              </li>
              <li>
                <section class="i-teach-wrap">
                  <div class="i-teach-pic">
                    <a href="/teacher/1" title="周杰伦" target="_blank">
                      <img src="~/assets/photo/teacher/1442297969808.jpg" alt>
                    </a>
                  </div>
                  <div class="mt10 hLh30 txtOf tac">
                    <a href="/teacher/1" title="周杰伦" target="_blank" class="fsize18 c-666">周杰伦</a>
                  </div>
                  <div class="hLh30 txtOf tac">
                    <span class="fsize14 c-999">中教一级职称。讲课极具亲和力。</span>
                  </div>
                  <div class="mt15 i-q-txt">
                    <p class="c-999 f-fA">毕业于北京大学数学系</p>
                  </div>
                </section>
              </li>
              <li>
                <section class="i-teach-wrap">
                  <div class="i-teach-pic">
                    <a href="/teacher/1" title="陈伟霆" target="_blank">
                      <img src="~/assets/photo/teacher/1442297977255.jpg" alt>
                    </a>
                  </div>
                  <div class="mt10 hLh30 txtOf tac">
                    <a href="/teacher/1" title="陈伟霆" target="_blank" class="fsize18 c-666">陈伟霆</a>
                  </div>
                  <div class="hLh30 txtOf tac">
                    <span
                      class="fsize14 c-999"
                    >政治学博士、管理学博士后,北京师范大学马克思主义学院副教授。多年来总结出了一套行之有效的应试技巧与答题方法,针对性和实用性极强,能帮助考生在轻松中应考,在激励的竞争中取得高分,脱颖而出。</span>
                  </div>
                  <div class="mt15 i-q-txt">
                    <p class="c-999 f-fA">长期从事考研政治课讲授和考研命题趋势与应试对策研究。考研辅导新锐派的代表。</p>
                  </div>
                </section>
              </li>
            </ul>
            <div class="clear"></div>
          </article>
        </div>
        <!-- 公共分页 开始 -->
        <div>
          <div class="paging">
            <!-- undisable这个class是否存在,取决于数据属性hasPrevious -->
            <a href="#" title="首页">首</a>
            <a href="#" title="前一页">&lt;</a>
            <a href="#" title="第1页" class="current undisable">1</a>
            <a href="#" title="第2页">2</a>
            <a href="#" title="后一页">&gt;</a>
            <a href="#" title="末页">末</a>
            <div class="clear"></div>
          </div>
        </div>
        <!-- 公共分页 结束 -->
      </section>
    </section>
    <!-- /讲师列表 结束 -->
  </div>
</template>
<script>
export default {};
</script>

二、详情页面

创建 pages/teacher/_id.vue
修改资源路径为~/assets/

<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>
      <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="~/assets/photo/teacher/1442297885942.jpg">
            </section>
            <h3 class="hLh30">
              <span class="fsize24 c-333">姚晨&nbsp;高级讲师</span>
            </h3>
            <section class="mt10">
              <span class="t-tag-bg">北京师范大学法学院副教授</span>
            </section>
            <section class="t-infor-txt">
              <p
                class="mt20"
              >北京师范大学法学院副教授、清华大学法学博士。自2004年至今已有9年的司法考试培训经验。长期从事司法考试辅导,深知命题规律,了解解题技巧。内容把握准确,授课重点明确,层次分明,调理清晰,将法条法理与案例有机融合,强调综合,深入浅出。</p>
            </section>
            <div class="clear"></div>
          </div>
        </section>
        <div class="clear"></div>
      </div>
      <section class="mt30">
        <div>
          <header class="comm-title all-teacher-title c-course-content">
            <h2 class="fl tac">
              <span class="c-333">主讲课程</span>
            </h2>
            <section class="c-tab-title">
              <a href="javascript: void(0)">&nbsp;</a>
            </section>
          </header>
          <!-- /无数据提示 开始-->
          <section class="no-data-wrap">
            <em class="icon30 no-data-ico">&nbsp;</em>
            <span class="c-666 fsize14 ml10 vam">没有相关数据,小编正在努力整理中...</span>
          </section>
          <!-- /无数据提示 结束-->
          <article class="comm-course-list">
            <ul class="of">
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img src="~/assets/photo/course/1442295455437.jpg" 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="零基础入门学习Python课程学习" target="_blank" class="course-title fsize18 c-333">零基础入门学习Python课程学习</a>
                  </h3>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img src="~/assets/photo/course/1442295472860.jpg" 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="影想力摄影小课堂" target="_blank" class="course-title fsize18 c-333">影想力摄影小课堂</a>
                  </h3>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img src="~/assets/photo/course/1442302831779.jpg" 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="数学给宝宝带来的兴趣" target="_blank" class="course-title fsize18 c-333">数学给宝宝带来的兴趣</a>
                  </h3>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img src="~/assets/photo/course/1442295506745.jpg" 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="国家教师资格考试专用" target="_blank" class="course-title fsize18 c-333">国家教师资格考试专用</a>
                  </h3>
                </div>
              </li>
            </ul>
            <div class="clear"></div>
          </article>
        </div>
      </section>
    </section>
    <!-- /讲师介绍 结束 -->
  </div>
</template>
<script>
export default {};
</script>

二、讲师列表页

一、后端

1、TeacherService
接口

public Map<String, Object> pageListWeb(Page<Teacher> pageParam);

实现

@Override
public Map<String, Object> pageListWeb(Page<Teacher> pageParam) {
​
    QueryWrapper<Teacher> queryWrapper = new QueryWrapper<>();
    queryWrapper.orderByAsc("sort");
​
    baseMapper.selectPage(pageParam, queryWrapper);
​
    List<Teacher> 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<String, Object> map = new HashMap<String, Object>();
    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;
}

2、TeacherController

@ApiOperation(value = "分页讲师列表")
@GetMapping(value = "{page}/{limit}")
public R pageList(
    @ApiParam(name = "page", value = "当前页码", required = true)
    @PathVariable Long page,
​
    @ApiParam(name = "limit", value = "每页记录数", required = true)
    @PathVariable Long limit){
​
    Page<Teacher> pageParam = new Page<Teacher>(page, limit);
​
    Map<String, Object> map = teacherService.pageListWeb(pageParam);
​
    return  R.ok().data(map);
}

3、swagger测试

二、前端列表js

1、创建api
创建文件夹api,api下创建teacher.js,用于封装讲师模块的请求

import request from '@/utils/request'
const api_name = '/edu/teacher'
export default {
  getPageList(page, limit) {   
    return request({
      url: `${api_name}/${page}/${limit}`,
      method: 'get'
    })
  }
}

2、讲师列表组件中调用api
pages/teacher/index.vue

<script>
import teacher from "@/api/teacher"
export default {
  asyncData({ params, error }) {
    return teacher.getPageList(1, 8).then(response => {
      console.log(response.data.data);
      return { data: response.data.data }
    });
  },
};
</script>

三、页面渲染

1、页面模板

<template>
  <div id="aCoursesList" class="bg-fa of">
    <!-- 讲师列表 开始 -->
    <section class="container">
      <section class="c-sort-box unBr">
        <div>
          <!-- 无数据提示 开始-->
​
          <!-- /无数据提示 结束-->
​
          <!-- 数据列表 开始-->
​
          <!-- /数据列表 结束-->
        </div>
        <!-- 公共分页 开始 -->
​
        <!-- /公共分页 结束 -->
      </section>
    </section>
    <!-- /讲师列表 结束 -->
  </div>
</template>

2、无数据提示
添加:v-if=“data.total==0”

<!-- /无数据提示 开始-->
<section class="no-data-wrap" v-if="data.total==0">
    <em class="icon30 no-data-ico">&nbsp;</em>
    <span class="c-666 fsize14 ml10 vam">没有相关数据,小编正在努力整理中...</span>
</section>
<!-- /无数据提示 结束-->

3、列表

<!-- /数据列表 开始-->
<article v-if="data.total>0" class="i-teacher-list">
    <ul class="of">
        <li v-for="item in data.items" :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>
<!-- /数据列表 结束-->

4、测试

四、分页

1、分页方法

methods: {
    gotoPage(page){
        teacher.getPageList(page, 8).then(response => {
            this.data = response.data.data
        })
    }
}

2、分页页面渲染

<!-- 公共分页 开始 -->
<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)">&lt;</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)">&gt;</a>
    <a
      :class="{undisable: !data.hasNext}"
      href="#"
      title="末页"
      @click.prevent="gotoPage(data.pages)">末</a>
    <div class="clear"/>
  </div>
</div>
<!-- 公共分页 结束 -->

3、测试

三、讲师详情页

一、后端

1、CourseService
根据讲师id查询讲师所讲课程列表
接口

List<Course> selectByTeacherId(String teacherId);

实现

/**
     * 根据讲师id查询当前讲师的课程列表
     * @param teacherId
     * @return
     */
@Override
public List<Course> selectByTeacherId(String teacherId) {
​
    QueryWrapper<Course> queryWrapper = new QueryWrapper<Course>();
​
    queryWrapper.eq("teacher_id", teacherId);
    //按照最后更新时间倒序排列
    queryWrapper.orderByDesc("gmt_modified");
​
    List<Course> courses = baseMapper.selectList(queryWrapper);
    return courses;
}

2、TeacherController

@Autowired
private CourseService courseService;
修改getById方法:
@ApiOperation(value = "根据ID查询讲师")
@GetMapping(value = "{id}")
public R getById(
        @ApiParam(name = "id", value = "讲师ID", required = true)
        @PathVariable String id){
​
    //查询讲师信息
    Teacher teacher = teacherService.getById(id);
​
    //根据讲师id查询这个讲师的课程列表
    List<Course> courseList = courseService.selectByTeacherId(id);
​
    return R.ok().data("teacher", teacher).data("courseList", courseList);
}

3、swagger测试

二、前端详情js

1、teacher api
api/teacher.js

getById(teacherId) {
    return request({
        url: `${api_name}/${teacherId}`,
        method: 'get'
    })
}

2、讲师详情页中调用api
pages/teacher/_id.vue

<script>
import teacher from "@/api/teacher"
export default {
  asyncData({ params, error }) {
    return teacher.getById(params.id).then(response => {
      console.log(response);
      return { 
        teacher: response.data.data.teacher,
        courseList: response.data.data.courseList
      }
    })
  }
}
</script>

三、页面渲染

1、讲师基本信息模板

<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>
      <div class="t-infor-wrap">
        <!-- 讲师基本信息 开始 -->
​
        <!-- /讲师基本信息 结束 -->
        <div class="clear"/>
      </div>
      <section class="mt30">
        <div>
          <header class="comm-title all-teacher-title c-course-content">
            <h2 class="fl tac">
              <span class="c-333">主讲课程</span>
            </h2>
            <section class="c-tab-title">
              <a href="javascript: void(0)">&nbsp;</a>
            </section>
          </header>
          <!-- 无数据提示 开始-->
​
          <!-- /无数据提示 结束-->
​
          <!-- 课程列表 开始-->
​
          <!-- /课程列表 结束-->
        </div>
      </section>
    </section>
    <!-- /讲师介绍 结束 -->
  </div>
</template>

2、讲师详情显示

<!-- 讲师基本信息 开始 -->
<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 }}
                &nbsp;
                {{ 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>
<!-- /讲师基本信息 结束 -->

3、无数据提示

<!-- 无数据提示 开始-->
<section class="no-data-wrap" v-if="courseList.total==0">
    <em class="icon30 no-data-ico">&nbsp;</em>
    <span class="c-666 fsize14 ml10 vam">没有相关数据,小编正在努力整理中...</span>
</section>
<!-- /无数据提示 结束-->

4、当前讲师课程列表

<!-- 课程列表 开始-->
<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="'/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"/>
</article>
<!-- /课程列表 结束-->

5、测试

四、课程页面静态效果整合

一、列表页面

创建 pages/course/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>
                  <a title="数据库" href="#">数据库</a>
                </li>
                <li class="current">
                  <a title="外语考试" href="#">外语考试</a>
                </li>
                <li>
                  <a title="教师资格证" href="#">教师资格证</a>
                </li>
                <li>
                  <a title="公务员" href="#">公务员</a>
                </li>
                <li>
                  <a title="移动开发" href="#">移动开发</a>
                </li>
                <li>
                  <a title="操作系统" href="#">操作系统</a>
                </li>
              </ul>
            </dd>
          </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>
                  <a title="英语四级" href="#">英语四级</a>
                </li>
                <li>
                  <a title="英语六级" href="#">英语六级</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>
                <a title="关注度" href="#">关注度</a>
              </li>
              <li>
                <a title="最新" href="#">最新</a>
              </li>
              <li class="current bg-orange">
                <a title="价格" href="#">价格&nbsp;
                  <span>↓</span>
                </a>
              </li>
            </ol>
          </section>
        </div>
        <div class="mt40">
          <!-- /无数据提示 开始-->
          <section class="no-data-wrap">
            <em class="icon30 no-data-ico">&nbsp;</em>
            <span class="c-666 fsize14 ml10 vam">没有相关数据,小编正在努力整理中...</span>
          </section>
          <!-- /无数据提示 结束-->
          <article class="comm-course-list">
            <ul class="of" id="bna">
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img src="~/assets/photo/course/1442295592705.jpg" class="img-responsive" alt="听力口语">
                    <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="听力口语" class="course-title fsize18 c-333">听力口语</a>
                  </h3>
                  <section class="mt10 hLh20 of">
                    <span 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">9634人学习</i>
                      |
                      <i class="c-999 f-fA">9634评论</i>
                    </span>
                  </section>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img src="~/assets/photo/course/1442295581911.jpg" class="img-responsive" alt="Java精品课程">
                    <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="Java精品课程" class="course-title fsize18 c-333">Java精品课程</a>
                  </h3>
                  <section class="mt10 hLh20 of">
                    <span 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">501人学习</i>
                      |
                      <i class="c-999 f-fA">501评论</i>
                    </span>
                  </section>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img src="~/assets/photo/course/1442295604295.jpg" class="img-responsive" alt="C4D零基础">
                    <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="C4D零基础" class="course-title fsize18 c-333">C4D零基础</a>
                  </h3>
                  <section class="mt10 hLh20 of">
                    <span 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">300人学习</i>
                      |
                      <i class="c-999 f-fA">300评论</i>
                    </span>
                  </section>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img
                      src="~/assets/photo/course/1442302831779.jpg"
                      class="img-responsive"
                      alt="数学给宝宝带来的兴趣"
                    >
                    <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="数学给宝宝带来的兴趣" class="course-title fsize18 c-333">数学给宝宝带来的兴趣</a>
                  </h3>
                  <section class="mt10 hLh20 of">
                    <span 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">256人学习</i>
                      |
                      <i class="c-999 f-fA">256评论</i>
                    </span>
                  </section>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img
                      src="~/assets/photo/course/1442295455437.jpg"
                      class="img-responsive"
                      alt="零基础入门学习Python课程学习"
                    >
                    <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="零基础入门学习Python课程学习"
                      class="course-title fsize18 c-333"
                    >零基础入门学习Python课程学习</a>
                  </h3>
                  <section class="mt10 hLh20 of">
                    <span 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">137人学习</i>
                      |
                      <i class="c-999 f-fA">137评论</i>
                    </span>
                  </section>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img
                      src="~/assets/photo/course/1442295570359.jpg"
                      class="img-responsive"
                      alt="MySql从入门到精通"
                    >
                    <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="MySql从入门到精通" class="course-title fsize18 c-333">MySql从入门到精通</a>
                  </h3>
                  <section class="mt10 hLh20 of">
                    <span 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">125人学习</i>
                      |
                      <i class="c-999 f-fA">125评论</i>
                    </span>
                  </section>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img src="~/assets/photo/course/1442302852837.jpg" class="img-responsive" alt="搜索引擎优化技术">
                    <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="搜索引擎优化技术" class="course-title fsize18 c-333">搜索引擎优化技术</a>
                  </h3>
                  <section class="mt10 hLh20 of">
                    <span 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">123人学习</i>
                      |
                      <i class="c-999 f-fA">123评论</i>
                    </span>
                  </section>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img src="~/assets/photo/course/1442295379715.jpg" class="img-responsive" alt="20世纪西方音乐">
                    <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="20世纪西方音乐" class="course-title fsize18 c-333">20世纪西方音乐</a>
                  </h3>
                  <section class="mt10 hLh20 of">
                    <span 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">34人学习</i>
                      |
                      <i class="c-999 f-fA">34评论</i>
                    </span>
                  </section>
                </div>
              </li>
            </ul>
            <div class="clear"></div>
          </article>
        </div>
        <!-- 公共分页 开始 -->
        <div>
          <div class="paging">
            <a class="undisable" title>首</a>
            <a id="backpage" class="undisable" href="#" title>&lt;</a>
            <a href="#" title class="current undisable">1</a>
            <a href="#" title>2</a>
            <a id="nextpage" href="#" title>&gt;</a>
            <a href="#" title>末</a>
            <div class="clear"></div>
          </div>
        </div>
        <!-- 公共分页 结束 -->
      </section>
    </section>
    <!-- /课程列表 结束 -->
  </div>
</template>
<script>
export default {};
</script>

二、详情页面

创建 pages/course/_id.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="#" title class="c-999 fsize14">课程列表</a>
        \
        <span class="c-333 fsize14">Java精品课程</span>
      </section>
      <div>
        <article class="c-v-pic-wrap" style="height: 357px;">
          <section class="p-h-video-box" id="videoPlay">
            <img src="~/assets/photo/course/1442295581911.jpg" alt="Java精品课程" 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">Java精品课程</span>
            </h2>
            <section class="c-attr-jg">
              <span class="c-fff">价格:</span>
              <b class="c-yellow" style="font-size:24px;">¥0.00</b>
            </section>
            <section class="c-attr-mt c-attr-undis">
              <span class="c-fff fsize14">主讲: 唐嫣&nbsp;&nbsp;&nbsp;</span>
            </section>
            <section class="c-attr-mt of">
              <span class="ml10 vam">
                <em class="icon18 scIcon"></em>
                <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>&nbsp;</p>
              <aside>
                <span class="c-fff f-fM">购买数</span>
                <br>
                <h6 class="c-fff f-fM mt10">150</h6>
              </aside>
            </li>
            <li>
              <p>&nbsp;</p>
              <aside>
                <span class="c-fff f-fM">课时数</span>
                <br>
                <h6 class="c-fff f-fM mt10">20</h6>
              </aside>
            </li>
            <li>
              <p>&nbsp;</p>
              <aside>
                <span class="c-fff f-fM">浏览数</span>
                <br>
                <h6 class="c-fff f-fM mt10">501</h6>
              </aside>
            </li>
          </ol>
        </aside>
        <div class="clear"></div>
      </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">
                      <p>
                        Java的发展历史,可追溯到1990年。当时Sun&nbsp;Microsystem公司为了发展消费性电子产品而进行了一个名为Green的项目计划。该计划
                        负责人是James&nbsp;Gosling。起初他以C++来写一种内嵌式软件,可以放在烤面包机或PAD等小型电子消费设备里,使得机器更聪明,具有人工智
                        能。但他发现C++并不适合完成这类任务!因为C++常会有使系统失效的程序错误,尤其是内存管理,需要程序设计师记录并管理内存资源。这给设计师们造成
                        极大的负担,并可能产生许多bugs。&nbsp;
                        <br>为了解决所遇到的问题,Gosling决定要发展一种新的语言,来解决C++的潜在性危险问题,这个语言名叫Oak。Oak是一种可移植性语言,也就是一种平台独立语言,能够在各种芯片上运行。
                        <br>1994年,Oak技术日趋成熟,这时网络正开始蓬勃发展。Oak研发小组发现Oak很适合作为一种网络程序语言。因此发展了一个能与Oak配合的浏
                        览器--WebRunner,后更名为HotJava,它证明了Oak是一种能在网络上发展的程序语言。由于Oak商标已被注册,工程师们便想到以自己常
                        享用的咖啡(Java)来重新命名,并于Sun&nbsp;World&nbsp;95中被发表出来。
                      </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 class="lh-menu-stair">
                            <a href="javascript: void(0)" title="第一章" class="current-1">
                              <em class="lh-menu-i-1 icon18 mr10"></em>第一章
                            </a>
                            <ol class="lh-menu-ol" style="display: block;">
                              <li class="lh-menu-second ml30">
                                <a href="#" title>
                                  <span class="fr">
                                    <i class="free-icon vam mr10">免费试听</i>
                                  </span>
                                  <em class="lh-menu-i-2 icon16 mr5">&nbsp;</em>第一节
                                </a>
                              </li>
                              <li class="lh-menu-second ml30">
                                <a href="#" title class="current-2">
                                  <em class="lh-menu-i-2 icon16 mr5">&nbsp;</em>第二节
                                </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="#">
                        <img src="~/assets/photo/teacher/1442297969808.jpg" width="50" height="50" alt>
                      </a>
                    </div>
                    <section class="hLh30 txtOf">
                      <a class="c-333 fsize16 fl" href="#">周杰伦</a>
                    </section>
                    <section class="hLh20 txtOf">
                      <span class="c-999">毕业于北京大学数学系</span>
                    </section>
                  </li>
                </ul>
              </section>
            </div>
          </div>
        </aside>
        <div class="clear"></div>
      </div>
    </section>
    <!-- /课程详情 结束 -->
  </div>
</template>
​
<script>
export default {};
</script>

五、课程列表页面

一、课程后端接口

1、课程列表
(1)课程列表vo类

@ApiModel(value = "课程查询对象", description = "课程查询对象封装")
@Data
public class CourseQueryVo 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)课程列表controller

@ApiOperation(value = "分页课程列表")
@PostMapping(value = "{page}/{limit}")
public R pageList(
        @ApiParam(name = "page", value = "当前页码", required = true)
        @PathVariable Long page,
​
        @ApiParam(name = "limit", value = "每页记录数", required = true)
        @PathVariable Long limit,
​
        @ApiParam(name = "courseQuery", value = "查询对象", required = false)
                @RequestBody(required = false) CourseQueryVo courseQuery){
    Page<EduCourse> pageParam = new Page<EduCourse>(page, limit);
    Map<String, Object> map = courseService.pageListWeb(pageParam, courseQuery);
    return  R.ok().data(map);
}

(3)课程列表service

@Override
public Map<String, Object> pageListWeb(Page<EduCourse> pageParam, CourseQueryVo courseQuery) {
        QueryWrapper<EduCourse> queryWrapper = new QueryWrapper<>();
        if (!StringUtils.isEmpty(courseQuery.getSubjectParentId())) {
            queryWrapper.eq("subject_parent_id", courseQuery.getSubjectParentId());
        }
​
        if (!StringUtils.isEmpty(courseQuery.getSubjectId())) {
            queryWrapper.eq("subject_id", courseQuery.getSubjectId());
        }
​
        if (!StringUtils.isEmpty(courseQuery.getBuyCountSort())) {
            queryWrapper.orderByDesc("buy_count");
        }
​
        if (!StringUtils.isEmpty(courseQuery.getGmtCreateSort())) {
            queryWrapper.orderByDesc("gmt_create");
        }
​
        if (!StringUtils.isEmpty(courseQuery.getPriceSort())) {
            queryWrapper.orderByDesc("price");
        }
​
        baseMapper.selectPage(pageParam, queryWrapper);
​
        List<EduCourse> 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<String, Object> map = new HashMap<String, Object>();
        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;
}

二、课程列表前端

1、定义api
api/course.js

import request from '@/utils/request'
export default {
  getPageList(page, limit, searchObj) {
    return request({
      url: `/eduservice/edu/course/${page}/${limit}`,
      method: 'post',
      data: searchObj
    })
  },
  // 获取课程二级分类
  getNestedTreeList2() {
    return request({
      url: `/eduservice/edu/course/list2`,
      method: 'get'
    })
  }
}

2、页面调用接口
pages/course/index.vue

<script>
import course from '@/api/course'
​
export default {
​
  data () {
    return {
      page:1,
      data:{},
      subjectNestedList: [], // 一级分类列表
      subSubjectList: [], // 二级分类列表
      searchObj: {}, // 查询表单对象
      oneIndex:-1,
      twoIndex:-1,
      buyCountSort:"",
      gmtCreateSort:"",
      priceSort:""
    }
  },
​
  //加载完渲染时
  created () {
    //获取课程列表
    this.initCourse()
​
    //获取分类
    this.initSubject()
  },
​
  methods: {
    //查询课程列表
    initCourse(){
      course.getPageList(1, 8,this.searchObj).then(response => {
        this.data = response.data.data
      })
    },
    //查询所有一级分类
    initSubject(){
      //debugger
      course.getNestedTreeList2().then(response => {
        this.subjectNestedList = response.data.data.items
      })
    },
    
    //点击一级分类,显示对应的二级分类,查询数据
    searchOne(subjectParentId, index) {
      //debugger
      this.oneIndex = index
      this.twoIndex = -1
​
      this.searchObj.subjectId = "";
      this.subSubjectList = [];
​
      this.searchObj.subjectParentId = subjectParentId;
      this.gotoPage(this.page)
​
      for (let i = 0; i < this.subjectNestedList.length; i++) {
        if (this.subjectNestedList[i].id === subjectParentId) {
          this.subSubjectList = this.subjectNestedList[i].children
        }
      }
    },
​
    //点击二级分类,查询数据
    searchTwo(subjectId, index) {
      this.twoIndex = index
      this.searchObj.subjectId = subjectId;
      this.gotoPage(this.page)
    },
    //购买量查询
    searchBuyCount() {
      this.buyCountSort = "1";
      this.gmtCreateSort = "";
      this.priceSort = "";
      this.searchObj.buyCountSort = this.buyCountSort;
      this.searchObj.gmtCreateSort = this.gmtCreateSort;
      this.searchObj.priceSort = this.priceSort;
      this.gotoPage(this.page)
    },
    //更新时间查询
    searchGmtCreate() {
      debugger
      this.buyCountSort = "";
      this.gmtCreateSort = "1";
      this.priceSort = "";
      this.searchObj.buyCountSort = this.buyCountSort;
      this.searchObj.gmtCreateSort = this.gmtCreateSort;
      this.searchObj.priceSort = this.priceSort;
      this.gotoPage(this.page)
    },
    //价格查询
    searchPrice() {
      this.buyCountSort = "";
      this.gmtCreateSort = "";
      this.priceSort = "1";
      this.searchObj.buyCountSort = this.buyCountSort;
      this.searchObj.gmtCreateSort = this.gmtCreateSort;
      this.searchObj.priceSort = this.priceSort;
      this.gotoPage(this.page)
    },
    //分页查询
    gotoPage(page) {
      this.page = page
      course.getPageList(page, 8, this.searchObj).then(response => {
        this.data = response.data.data
      })
    }
  }
}
</script>
<style scoped>
  .active {
    background: #bdbdbd;
  }
  .hide {
    display: none;
  }
  .show {
    display: block;
  }
</style>
​```
## 三、课程列表渲染
**1、课程类别显示**
课程类别

4、列表

<!-- 数据列表 开始-->
<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="听力口语">
                    <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>
<!-- /数据列表 结束-->

5、分页页面渲染

<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)">&lt;</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)">&gt;</a>
    <a
      :class="{undisable: !data.hasNext}"
      href="#"
      title="末页"
      @click.prevent="gotoPage(data.pages)">末</a>
    <div class="clear"/>
  </div>
</div>

六、课程详情页

一、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>

四、页面模板

pages/course/_id.vue
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 }}&nbsp;&nbsp;&nbsp;</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>&nbsp;</p>
                <aside>
                    <span class="c-fff f-fM">购买数</span>
                    <br>
                    <h6 class="c-fff f-fM mt10">{{ course.buyCount }}</h6>
                </aside>
            </li>
            <li>
                <p>&nbsp;</p>
                <aside>
                    <span class="c-fff f-fM">课时数</span>
                    <br>
                    <h6 class="c-fff f-fM mt10">{{ course.lessonNum }}</h6>
                </aside>
            </li>
            <li>
                <p>&nbsp;</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">&nbsp;</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>
<!-- /主讲讲师 结束 -->

七、视频播放测试

一、获取播放地址播放

获取播放地址
参考文档:https://help.aliyun.com/document_detail/61064.html
前面的 03-使用服务端SDK 介绍了如何获取非加密视频的播放地址。直接使用03节的例子获取加密视频播放地址会返回如下错误信息

Currently only the AliyunVoDEncryption stream exists, you must use the Aliyun player to play or set the value of ResultType to Multiple.

目前只有AliyunVoDEncryption流存在,您必须使用Aliyun player来播放或将ResultType的值设置为Multiple。
因此在testGetPlayInfo测试方法中添加 ResultType 参数,并设置为true

privateParams.put("ResultType", "Multiple");

此种方式获取的视频文件不能直接播放,必须使用阿里云播放器播放

二、视频播放器

参考文档:https://help.aliyun.com/document_detail/61109.html
1、视频播放器介绍
阿里云播放器SDK(ApsaraVideo Player SDK)是阿里视频服务的重要一环,除了支持点播和直播的基础播放功能外,深度融合视频云业务,如支持视频的加密播放、安全下载、清晰度切换、直播答题等业务场景,为用户提供简单、快速、安全、稳定的视频播放服务。
2、集成视频播放器
参考文档:https://help.aliyun.com/document_detail/51991.html
参考 【播放器简单使用说明】一节
引入脚本文件和css文件

<link rel="stylesheet" href="https://g.alicdn.com/de/prismplayer/2.8.1/skins/default/aliplayer-min.css" />
<script charset="utf-8" type="text/javascript" src="https://g.alicdn.com/de/prismplayer/2.8.1/aliplayer-min.js"></script>

初始化视频播放器

<body>
    <div  class="prism-player" id="J_prismPlayer"></div>
    <script>
        var player = new Aliplayer({
            id: 'J_prismPlayer',
            width: '100%',
            autoplay: false,
            cover: 'http://liveroom-img.oss-cn-qingdao.aliyuncs.com/logo.png',  
            //播放配置
        },function(player){
            console.log('播放器创建好了。')
        });
    </script>
</body>

3、播放地址播放
在Aliplayer的配置参数中添加如下属性
//播放方式一:支持播放地址播放,此播放优先级最高,此种方式不能播放加密视频

source : '你的视频播放地址',
启动浏览器运行,测试视频的播放

4、播放凭证播放(推荐)
阿里云播放器支持通过播放凭证自动换取播放地址进行播放,接入方式更为简单,且安全性更高。播放凭证默认时效为100秒(最大为3000秒),只能用于获取指定视频的播放地址,不能混用或重复使用。如果凭证过期则无法获取播放地址,需要重新获取凭证。

encryptType:'1',//如果播放加密视频,则需设置encryptType=1,非加密视频无需设置此项
vid : '视频id',
playauth : '视频授权码',

注意:播放凭证有过期时间,默认值:100秒 。取值范围:100~3000。
设置播放凭证的有效期
在获取播放凭证的测试用例中添加如下代码

request.setAuthInfoTimeout(200L);

在线配置参考:https://player.alicdn.com/aliplayer/setting/setting.html

八、整合阿里云视频播放器

一、后端获取播放凭证

1、VideoController
service-vod微服务中创建 VideoController.java
controller中创建 getVideoPlayAuth 接口方法

package com.guli.vod.controller;
​
@Api(description="阿里云视频点播微服务")
@CrossOrigin //跨域
@RestController
@RequestMapping("/vod/video")
public class VideoController {
​
    @GetMapping("get-play-auth/{videoId}")
    public R getVideoPlayAuth(@PathVariable("videoId") String videoId) throws Exception {
​
        //获取阿里云存储相关常量
        String accessKeyId = ConstantPropertiesUtil.ACCESS_KEY_ID;
        String accessKeySecret = ConstantPropertiesUtil.ACCESS_KEY_SECRET;
​
        //初始化
        DefaultAcsClient client = AliyunVodSDKUtils.initVodClient(accessKeyId, accessKeySecret);
​
        //请求
        GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();
        request.setVideoId(videoId);
​
        //响应
        GetVideoPlayAuthResponse response = client.getAcsResponse(request);
​
        //得到播放凭证
        String playAuth = response.getPlayAuth();
​
        //返回结果
        return R.ok().message("获取凭证成功").data("playAuth", playAuth);
    }   
}

2、Swagger测试

二、前端播放器整合

1、点击播放超链接
course/_id.vue
修改课时目录超链接
在这里插入图片描述

<a
   :href="'/player/'+video.videoSourceId"
   :title="video.title"
   target="_blank">

2、layout
因为播放器的布局和其他页面的基本布局不一致,因此创建新的布局容器 layouts/video.vue

<template>
  <div class="guli-player">
    <div class="head">
      <a href="#" title="谷粒学院">
        <img class="logo" src="~/assets/img/logo.png" lt="谷粒学院">
    </a></div>
    <div class="body">
      <div class="content"><nuxt/></div>
    </div>
  </div>
</template>
<script>
export default {}
</script>
​
<style>
html,body{
  height:100%;
}
</style>
​
<style scoped>
.head {
  height: 50px;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
}
​
.head .logo{
  height: 50px;
  margin-left: 10px;
}
​
.body {
  position: absolute;
  top: 50px;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;
}
</style>

3、api
创建api模块 api/vod.js,从后端获取播放凭证

import request from '@/utils/request'
const api_name = '/vod/video'
​
export default {
​
  getPlayAuth(vid) {
    return request({
      url: `${api_name}/get-play-auth/${vid}`,
      method: 'get'
    })
  }
​
}

4、播放组件相关文档
集成文档:
https://help.aliyun.com/document_detail/51991.html?spm=a2c4g.11186623.2.39.478e192b8VSdEn
在线配置:
https://player.alicdn.com/aliplayer/setting/setting.html
功能展示:
https://player.alicdn.com/aliplayer/presentation/index.html

5、创建播放页面
创建 pages/player/_vid.vue
(1)引入播放器js库和css样式

<template>
  <div>
​
    <!-- 阿里云视频播放器样式 -->
    <link rel="stylesheet" href="https://g.alicdn.com/de/prismplayer/2.8.1/skins/default/aliplayer-min.css" >
    <!-- 阿里云视频播放器脚本 -->
    <script charset="utf-8" type="text/javascript" src="https://g.alicdn.com/de/prismplayer/2.8.1/aliplayer-min.js" />
​
    <!-- 定义播放器dom -->
    <div id="J_prismPlayer" class="prism-player" />
  </div>
</template>

(2)获取播放凭证

<script>
import vod from '@/api/vod'
export default {
    
  layout: 'video',//应用video布局
  asyncData({ params, error }) {
    return vod.getPlayAuth(params.vid).then(response => {
      // console.log(response.data.data)
      return {
        vid: params.vid,
        playAuth: response.data.data.playAuth
      }
    })
  }
}
</script>

(3)创建播放器

 /**
 * 页面渲染完成时:此时js脚本已加载,Aliplayer已定义,可以使用
 * 如果在created生命周期函数中使用,Aliplayer is not defined错误
 */
mounted() {
    
    new Aliplayer({
        id: 'J_prismPlayer',
        vid: this.vid, // 视频id
        playauth: this.playAuth, // 播放凭证
        encryptType: '1', // 如果播放加密视频,则需设置encryptType=1,非加密视频无需设置此项
        width: '100%',
        height: '500px'
    }, function(player) {
        console.log('播放器创建成功')
    })
}

(4)其他常见的可选配置

// 以下可选设置
cover: 'http://guli.shop/photo/banner/1525939573202.jpg', // 封面
qualitySort: 'asc', // 清晰度排序
​
mediaType: 'video', // 返回音频还是视频
autoplay: false, // 自动播放
isLive: false, // 直播
rePlay: false, // 循环播放
preload: true,
controlBarVisibility: 'hover', // 控制条的显示方式:鼠标悬停
useH5Prism: true, // 播放器类型:html5

6、加入播放组件
功能展示:https://player.alicdn.com/aliplayer/presentation/index.html

九、课程评论功能

一、数据库设计

1、数据库
edu_comment

2、数据表
guli_edu.sql

二、创建课程评论接口

1、在service-edu模块,生成课程评论代码
(1)使用mp代码生成器生成

2、在service-ucenter模块,创建接口
(1)实现用户id获取用户信息,返回用户信息对象

//根据token字符串获取用户信息
@PostMapping("getInfoUc/{id}")
public com.atguigu.commonutils.vo.UcenterMember getInfo(@PathVariable String id) {
        //根据用户id获取用户信息
        UcenterMember ucenterMember = memberService.getById(id);
        com.atguigu.commonutils.vo.UcenterMember memeber = new com.atguigu.commonutils.vo.UcenterMember();
        BeanUtils.copyProperties(ucenterMember,memeber);
        return memeber;
}

3、创建课程评论controller
(1)在service-edu模块创建client,实现微服务调用

@Component
@FeignClient(name="service-ucenter",fallback = UcenterClientImpl.class)
public interface UcenterClient {
​
    //根据用户id获取用户信息
    @GetMapping("/ucenterservice/member/getUcenterPay/{memberId}")
    public UcenterMemberPay getUcenterPay(@PathVariable("memberId") String memberId);
}
​
@Component
public class UcenterClientImpl implements UcenterClient {
    @Override
    public UcenterMemberPay getUcenterPay(String memberId) {
        return null;
    }
}

(2)创建评论列表和添加评论接口

@RestController
@RequestMapping("/eduservice/comment")
@CrossOrigin
public class CommentFrontController {
​
    @Autowired
    private CommentService commentService;
    @Autowired
    private UcenterClient ucenterClient;
​
    //根据课程id查询评论列表
    @ApiOperation(value = "评论分页列表")
    @GetMapping("{page}/{limit}")
    public R index(
            @ApiParam(name = "page", value = "当前页码", required = true)
            @PathVariable Long page,
​
            @ApiParam(name = "limit", value = "每页记录数", required = true)
            @PathVariable Long limit,
​
            @ApiParam(name = "courseQuery", value = "查询对象", required = false)
                    String courseId) {
        Page<Comment> pageParam = new Page<>(page, limit);
​
        QueryWrapper<Comment> wrapper = new QueryWrapper<>();
        wrapper.eq("course_id",courseId);
​
        commentService.page(pageParam,wrapper);
        List<Comment> commentList = pageParam.getRecords();
​
        Map<String, Object> map = new HashMap<>();
        map.put("items", commentList);
        map.put("current", pageParam.getCurrent());
        map.put("pages", pageParam.getPages());
        map.put("size", pageParam.getSize());
        map.put("total", pageParam.getTotal());
        map.put("hasNext", pageParam.hasNext());
        map.put("hasPrevious", pageParam.hasPrevious());
        return R.ok().data(map);
    }
​
    @ApiOperation(value = "添加评论")
    @PostMapping("auth/save")
    public R save(@RequestBody Comment comment, HttpServletRequest request) {
        String memberId = JwtUtils.getMemberIdByJwtToken(request);
        if(StringUtils.isEmpty(memberId)) {
            return R.error().code(28004).message("请登录");
        }
        comment.setMemberId(memberId);
​
        UcenterMemberPay ucenterInfo = ucenterClient.getUcenterPay(memberId);
​
        comment.setNickname(ucenterInfo.getNickname());
        comment.setAvatar(ucenterInfo.getAvatar());
​
        commentService.save(comment);
        return R.ok();
    }
}

三、课程评论前端整合

1、在api创建commonedu.js

import request from '@/utils/request'
​
export default {
​
  getPageList(page, limit, courseId) {
    return request({
      url: `/eduservice/comment/${page}/${limit}`,
      method: 'get',
      params: {courseId}
    })
  },
  addComment(comment) {
    return request({
      url: `/eduservice/comment/auth/save`,
      method: 'post',
      data: comment
    })
  }
}

2、在课程详情页面,调用方法 _id.vue

import comment from '@/api/commonedu'
    
<script>
import course from '@/api/course'
import comment from '@/api/commonedu'
export default {
​
     //和页面异步开始的
  asyncData({ params, error }) {
    return {courseId: params.id}
    
  },
  data() {
    return {
      data:{},
      page:1,
      limit:4,
      total:10,
      comment:{
        content:'',
        courseId:''
      },
      courseInfo:{},
      chapterVideoList:[],
      isbuyCourse:false
    }
  },
  created() {
    this.initCourseInfo()
    this.initComment()
  },
  methods:{
    //获取课程详情
    initCourseInfo() {
      course.getCourseInfo(this.courseId)
            .then(response => {
              this.courseInfo=response.data.data.courseFrontInfo
              this.chapterVideoList=response.data.data.chapterVideoList
              this.isbuyCourse=response.data.data.isbuyCourse
            })
    },
​
    initComment(){
       comment.getPageList(this.page, this.limit, this.courseId).then(response => {
           this.data = response.data.data
       })
    },
    addComment(){
        this.comment.courseId = this.courseId
        this.comment.teacherId = this.courseInfo.teacherId
        comment.addComment(this.comment).then(response => {
            if(response.data.success){
                this.comment.content = ''
                this.initComment()
            }
        })
    },
    gotoPage(page){
          comment.getPageList(page, this.limit,this.courseId).then(response => {
              this.data = response.data.data
          })
      }
  }
  
};
</script>

3、在课程详情页面 _id.vue显示评论

<div class="mt50 commentHtml"><div>
      <h6 class="c-c-content c-infor-title" id="i-art-comment">
        <span class="commentTitle">课程评论</span>
      </h6>
      <section class="lh-bj-list pr mt20 replyhtml">
        <ul>
          <li class="unBr">
            <aside class="noter-pic">
              <img width="50" height="50" class="picImg" src="~/assets/img/avatar-boy.gif">
              </aside>
            <div class="of">
              <section class="n-reply-wrap">
                <fieldset>
                  <textarea name="" v-model="comment.content" placeholder="输入您要评论的文字" id="commentContent"></textarea>
                </fieldset>
                <p class="of mt5 tar pl10 pr10">
                  <span class="fl "><tt class="c-red commentContentmeg" style="display: none;"></tt></span>
                  <input type="button" @click="addComment()" value="回复" class="lh-reply-btn">
                </p>
              </section>
            </div>
          </li>
        </ul>
      </section>
      <section class="">
          <section class="question-list lh-bj-list pr">
            <ul class="pr10">
              <li v-for="(comment,index) in data.items" v-bind:key="index">
                  <aside class="noter-pic">
                    <img width="50" height="50" class="picImg" :src="comment.avatar">
                    </aside>
                  <div class="of">
                    <span class="fl"> 
                    <font class="fsize12 c-blue"> 
                      {{comment.nickname}}</font>
                    <font class="fsize12 c-999 ml5">评论:</font></span>
                  </div>
                  <div class="noter-txt mt5">
                    <p>{{comment.content}}</p>
                  </div>
                  <div class="of mt5">
                    <span class="fr"><font class="fsize12 c-999 ml5">{{comment.gmtCreate}}</font></span>
                  </div>
                </li>
              
              </ul>
          </section>
        </section>
        
        <!-- 公共分页 开始 -->
        <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)">&lt;</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)">&gt;</a>
            <a
            :class="{undisable: !data.hasNext}"
            href="#"
            title="末页"
            @click.prevent="gotoPage(data.pages)">末</a>
            <div class="clear"/>
        </div>
        <!-- 公共分页 结束 -->
      </div>
    </div>
展开查看
 
     System.out.println("Hello");
       System.out.println("Hello");
       System.out.println("Hello");
       System.out.println("Hello");
       System.out.println("Hello");
       System.out.println("Hello");
  
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.项目概况 ​ 提到宿舍,现在无论是学校,还是工厂,都是在熟悉不过的了,学生宿舍楼,职工教员工,职工宿舍楼等等,每一栋楼房都有很多的房间,每个宿舍分配了多少个床位,住着什么人,那些床位是空的,那些房间是空的,这些都需要人员去维护,曾经的我们,通过纸张登记,查看房间信息,房间床位信息,房间少的情况下还好,我们可以一个个进行比对,看登记信息去查看房间信息,床位信息,但是房间多,登记信息多的情况下,或者有人员进行变动,退房,换房的情况下,可就麻烦了我们的宿舍管理员了,我们的宿舍管理员,需要慢慢的进行查找,浪费了时间成本不说,还容易出错,新来的学生或员工需要等待很长时间才能进去入住,在加上现在楼层在逐渐的向高层发展,人员手动管理已经不能满足社会的需要,因而,社会需要更好的工具去管理这些枯燥的的宿舍管理工作,从而宿舍管理系统应用而生。 ​ 宿舍管理系统,解决了当前人力成本,时间成本问题,可以快速的定位到房间号,宿舍床位号,通过宿舍管理系统,我们只要根据系统的要求去操作,就可以分分钟的时间解决某个宿舍是否满员,可以方便的把人员和宿舍,床位进行绑定,就像我们的身份号似的,都是唯一的,查询起来很方便,相比较起传统的宿舍纸张登记来说,现代化的宿舍管理系统更快捷,更高效,更适应人们快捷化的生活。 ​ 现在高校的发展和体制不断的进行了完善,所以学校的服务也逐渐有了变化,对于学校宿舍的管理有了新形势的管理模式。学校根据自身的实际情况,对于学生宿舍生活管理的服务进行改善。有些学校因为管理工作的错误,影响了学校里学生的现况,甚至给整个学校造成了负面的影响,而且现在学校管理问题普遍存在。所以现在学校也在建设信息化管理系统,这种管理系统,可以为学校的管理工作和宿舍管理工作带来很好的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值