谷粒学院——Day14【首页课程和名师功能】

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 谷粒学院——Day14【首页课程和名师功能】
❤ 作者主页:Java技术一点通的博客
❀ 个人介绍:大家好,我是Java技术一点通!( ̄▽ ̄)~*
🍊 记得关注、点赞、收藏、评论⭐️⭐️⭐️
📣 认真学习,共同进步!!!🎉🎉

首页名师功能

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

1. 列表页面

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)"
            οnclick="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="前一页"><</a>
            <a href="#" title="第1页" class="current undisable">1</a>
            <a href="#" title="第2页">2</a>
            <a href="#" title="后一页">></a>
            <a href="#" title="末页">末</a>
            <div class="clear"></div>
          </div>
        </div>
        <!-- 公共分页 结束 -->
      </section>
    </section>
    <!-- /讲师列表 结束 -->
  </div>
</template>
<script>
export default {};
</script>

2. 详情页面

pages/teacher/_id.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>
      <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. controller层

TeacherFrontController

@RestController
@CrossOrigin
@RequestMapping("/eduservice/teacherfront")
public class TeacherFrontController {

    @Autowired
    private EduTeacherService teacherService;

    // 分页查询讲师的方法
    @PostMapping("getTeahcerFrontList/{page}/{limit}")
    public R getTeacherFrontList(@PathVariable long page, @PathVariable long limit) {
        Page<EduTeacher> pageTeacher = new Page<>(page,limit);
        Map<String, Object> map = teacherService.getTeacherFrontList(pageTeacher);

        // 返回分页所有数据
        return R.ok().data(map);

    }
}

2. service层

  • EduTeacherService

      // 分页查询讲师的方法
        Map<String, Object> getTeacherFrontList(Page<EduTeacher> pageTeacher);
  • EduTeacherServiceImpl

    // 分页查询讲师的方法
        @Override
        public Map<String, Object> getTeacherFrontList(Page<EduTeacher> pageTeacher) {
    
            QueryWrapper<EduTeacher> wrapper = new QueryWrapper<>();
            wrapper.orderByDesc("id");
            //把分页数据封装到pageTeacher对象
            baseMapper.selectPage(pageTeacher, wrapper);
    
            // 把分页数据获取出来,放到map集合
            Map<String, Object> map = new HashMap<>();
    
            //总记录数
            long total = pageTeacher.getTotal();
            //当前页
            long current = pageTeacher.getCurrent();
            //每页记录数
            long size = pageTeacher.getSize();
            //查询到的对象
            List<EduTeacher> teacherList = pageTeacher.getRecords();
            //总页数
            long pages = pageTeacher.getPages();
            //是否有上一页
            boolean hasPrevious = pageTeacher.hasPrevious();
            //是否有下一页
            boolean hasNext = pageTeacher.hasNext();
    
            //将数据封装到map中返回
            map.put("total", total);
            map.put("current", current);
            map.put("size", size);
            map.put("list", teacherList);
            map.put("hasPrevious", hasPrevious);
            map.put("hasNext", hasNext);
            map.put("pages", pages);
    
            return map;
        }

3. swagger测试

在这里插入图片描述
 
在这里插入图片描述
 


二、前端列表js

1. 创建api

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

import request from '@/utils/request'

export default{

    // 分页讲师查询的方法
    getTeacherList(page, limit) {
        return request({
            url: `/eduservice/teacherfront/getTeahcerFrontList/${page}/${limit}`,
            method: 'post'
        })
    }

}

2. 讲师列表组件中调用api

<script>
import teacherAPI from "@/api/teacher";

export default {
       //异步调用,进页面调用,且只会调一次
      //params:相当于之前的 this.$route.params.id 等价 params.id
      //error:错误信息
      asyncData({ params, error }) {
        return teacherApi.getTeacherList(1, 8)
          .then(response => {
              //this.data = 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 class="i-teacher-list" v-if="data.total > 0">
              <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/1" :title="item.name" target="_blank">
                                  <img :src="item.avatar" :alt="item.name" />
                              </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.career}}</p>
                          </div>
                      </section>
                  </li>
              </ul>
              <div class="clear"></div>
          </article>

4. 测试

在这里插入图片描述
 


四、分页

1. 分页方法

methods: {
        // 分页切换的方法
        //参数是页码数
        gotoPage(page) {
          teacherApi.getTeacherList(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)"
                  ><</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>
        <!-- 公共分页 结束 -->

3. 测试

在这里插入图片描述
 
在这里插入图片描述
 


三、讲师详情页

一、后端开发

1. controller层

TeacherFrontController

@RestController
@CrossOrigin
@RequestMapping("/eduservice/teacherfront")
public class TeacherFrontController {

    @Autowired
    private EduTeacherService teacherService;

    @Autowired
    private EduCourseService courseService;

    // 根据id查询讲师信息(讲师本身信息 + 讲师所讲课程信息)
    @GetMapping("/getTeacherFrontInfo/{teacherId}")
    public R getTeacherFrontInfo(@PathVariable String teacherId) {
        //1.根据讲师id查询讲师基本信息
        EduTeacher eduTeacher = teacherService.getById(teacherId);

        //2.根据讲师id查询所讲课程
        QueryWrapper<EduCourse> wrapper = new QueryWrapper<>();
        wrapper.eq("teacher_id", teacherId);
        List<EduCourse> courseList = courseService.list(wrapper);

        return R.ok().data("teacher", eduTeacher).data("courseList", courseList);
        
    }

}

2. Swagger测试

在这里插入图片描述
 
在这里插入图片描述
 


二、前端开发

1. 定义api

api/teacher.js:

// 讲师详情的方法
    getTeacherInfo(id) {
        return request({
            url: `/eduservice/teacherfront/getTeacherFrontInfo/${id}`,
            method: 'get'
        })
    }

2. 讲师详情页中调用api

pages/teacher/_id.vue:

import teacherApi from '@/api/teacher'

export default {

   asyncData({ params, error }) {
    return teacherApi.getTeacherInfo(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">
        <!-- 讲师基本信息 -->
        <section class="fl t-infor-box c-desc-content">
          <div class="mt20 ml20">
            <section class="t-infor-pic">
              <img :src="teacher.avatar" />
            </section>
            <h3 class="hLh30">
              <span class="fsize24 c-333">{{teacher.name}}&nbsp;
                {{teacher.level ===1?'高级讲师':'首席讲师'}}
              </span>
            </h3>
            <section class="mt10">
              <span class="t-tag-bg">{{teacher.career}}</span>
            </section>
            <section class="t-infor-txt">
              <p class="mt20">
                {{teacher.intro}}
              </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" v-if="courseList.length==0">
            <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 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"></div>
          </article>
        </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" />
            </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.career}}</span>
            </section>
            <section class="t-infor-txt">
              <p class="mt20">
                {{teacher.intro}}
              </p>
            </section>

3. 无数据提示

 <!-- /无数据提示 开始-->
          <section class="no-data-wrap" v-if="courseList.length==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"></div>
          </article>

5. 测试

  • 讲师列表

在这里插入图片描述

  • 有课程

在这里插入图片描述

  • 没有课程

在这里插入图片描述
 


首页课程功能

课程列表页面

一、后端接口开发

1. 实体类

创建 frontvo 包,在改包下创建 CourseFrontVo 实体类:

@Data
public class CourseFrontVo {
    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层

CourseFrontController

@RestController
@CrossOrigin
@RequestMapping("/eduservice/coursefront")
public class CourseFrontController {
    
    @Autowired
    private EduCourseService courseService;

    // 条件查询带分页查询课程
    @PostMapping("getFrontCourseList/{page}/{limit}")
    public R getFrontCourseList(@PathVariable long page, @PathVariable long limit,
                                @RequestBody(required = false) CourseFrontVo courseFrontVo) {
        Page<EduCourse> pageCourse = new Page<>(page, limit);
        Map<String, Object> map = courseService.getCourseFrontList(pageCourse, courseFrontVo);

        // 返回分页所有数据
        return R.ok().data(map);
    }

}

3. service层

EduCourseService:

// 条件查询带分页查询课程
    Map<String, Object> getCourseFrontList(Page<EduCourse> pageCourse, CourseFrontVo courseFrontVo);

EduCourseServiceImpl:

 // 条件查询带分页查询课程
    @Override
    public Map<String, Object> getCourseFrontList(Page<EduCourse> pageParam, CourseFrontVo courseFrontVo) {
        QueryWrapper<EduCourse> wrapper = new QueryWrapper<>();
        // 判断条件值是否为空,不为空则拼接
        if (!StringUtils.isEmpty(courseFrontVo.getSubjectParentId())) { //一级分类
            wrapper.eq("subject_parent_id", courseFrontVo.getSubjectId());
        }

        if (!StringUtils.isEmpty(courseFrontVo.getSubjectId())) { //二级分类
            wrapper.eq("subject_id", courseFrontVo.getSubjectId());
        }

        if (!StringUtils.isEmpty(courseFrontVo.getBuyCountSort())) { //关注度
            wrapper.orderByDesc("buy_count");
        }

        if (!StringUtils.isEmpty(courseFrontVo.getGmtCreateSort())) { //最新,创建时间
            wrapper.orderByDesc("gmt_create");
        }

        if (!StringUtils.isEmpty(courseFrontVo.getPriceSort())) { //价格
            wrapper.orderByDesc("price");
        }

        baseMapper.selectPage(pageParam, wrapper);

        // 把分页数据获取出来,放到map集合
        Map<String, Object> map = new HashMap<>();

        //总记录数
        long total = pageParam.getTotal();
        //当前页
        long current = pageParam.getCurrent();
        //每页记录数
        long size = pageParam.getSize();
        //查询到的对象
        List<EduCourse> records = pageParam.getRecords();
        //总页数
        long pages = pageParam.getPages();
        //是否有上一页
        boolean hasPrevious = pageParam.hasPrevious();
        //是否有下一页
        boolean hasNext = pageParam.hasNext();

        //将数据封装到map中返回
        map.put("total", total);
        map.put("current", current);
        map.put("size", size);
        map.put("items", records);
        map.put("hasPrevious", hasPrevious);
        map.put("hasNext", hasNext);
        map.put("pages", pages);

        return map;

    }

 


二、课程列表前端

1. 定义api

api/course.js

import request from '@/utils/request'

export default{

   // 条件分页课程查询的方法
   getCourseList(page, limit, searchObj) {
       return request({
           url: `/eduservice/coursefront/getFrontCourseList/${page}/${limit}`,
           method: 'post',
           data: searchObj
       })
   },

   // 查询所有分类的方法
   getAllSubject() {
       return request({
           url: `/eduservice/subject/getAllSubject`,
           method: 'get'
       })
   }
}

2. 页面调用接口

pages/course/index.vue

<script>
import courseApi from '@/api/course'

export default {
  data() {
    return {
      page:1, //当前页
      data:{},  //课程列表
      subjectNestedList: [], // 一级分类列表
      subSubjectList: [], // 二级分类列表

      searchObj: {}, // 查询表单对象

      oneIndex:-1,
      twoIndex:-1,
      buyCountSort:"",
      gmtCreateSort:"",
      priceSort:""
    }
  },

  created() {
    //课程第一次查询
    this.initCourseFirst()
    //一级分类显示
    this.initSubject()
  },
  methods:{
    //1 查询第一页数据
    initCourseFirst() {
      courseApi.getCourseList(1,8,this.searchObj).then(response => {
        this.data = response.data.data
      })
    },

    //2 查询所有一级分类
    initSubject() {
      courseApi.getAllSubject()
        .then(response => {
          this.subjectNestedList = response.data.data.list
        })
    },

    //3 分页切换的方法
    gotoPage(page) {
      courseApi.getCourseList(page,8,this.searchObj).then(response => {
        this.data = response.data.data
      })
    },

    //4 点击某个一级分类,查询对应二级分类
    searchOne(subjectParentId,index) {
      //把传递index值赋值给oneIndex,为了active样式生效
      this.oneIndex = index

      this.twoIndex = -1
      this.searchObj.subjectId = ""
      this.subSubjectList = []

      //把一级分类点击id值,赋值给searchObj
      this.searchObj.subjectParentId = subjectParentId
      //点击某个一级分类进行条件查询
      this.gotoPage(1)

      //拿着点击一级分类id 和 所有一级分类id进行比较,
      //如果id相同,从一级分类里面获取对应的二级分类
      for(let i=0;i<this.subjectNestedList.length;i++) {
        //获取每个一级分类
        var oneSubject = this.subjectNestedList[i]
        //比较id是否相同
        if(subjectParentId == oneSubject.id) {
          //从一级分类里面获取对应的二级分类
          this.subSubjectList = oneSubject.children
        }
      }
    },

    //5 点击某个二级分类实现查询
    searchTwo(subjectId, index) {
      //把index赋值,为了样式生效
      this.twoIndex = index
      //把二级分类点击id值,赋值给searchObj
      this.searchObj.subjectId = subjectId
      //点击某个二级分类进行条件查询
      this.gotoPage(1)
    },

    //6 根据销量排序
    searchBuyCount() {
      //设置对应变量值,为了样式生效
      this.buyCountSort = "1"
      this.gmtCreateSort = ""
      this.priceSort = ""

      //把值赋值到searchObj
      this.searchObj.buyCountSort = this.buyCountSort
      this.searchObj.gmtCreateSort = this.gmtCreateSort
      this.searchObj.priceSort = this.priceSort

      //调用方法查询
      this.gotoPage(1)
    },

    //7 最新排序
    searchGmtCreate() {
      //设置对应变量值,为了样式生效
      this.buyCountSort = ""
      this.gmtCreateSort = "1"
      this.priceSort = ""

      //把值赋值到searchObj
      this.searchObj.buyCountSort = this.buyCountSort
      this.searchObj.gmtCreateSort = this.gmtCreateSort;
      this.searchObj.priceSort = this.priceSort;

      //调用方法查询
      this.gotoPage(1)
    },

    //8 价格排序
    searchPrice() {
      //设置对应变量值,为了样式生效
      this.buyCountSort = ""
      this.gmtCreateSort = ""
      this.priceSort = "1"

      //把值赋值到searchObj
      this.searchObj.buyCountSort = this.buyCountSort
      this.searchObj.gmtCreateSort = this.gmtCreateSort;
      this.searchObj.priceSort = this.priceSort;

      //调用方法查询
      this.gotoPage(1)
    },


  }
};
</script>
<style scoped>
  .active {
    background: #bdbdbd;
  }
  .hide {
    display: none;
  }
  .show {
    display: block;
  }
</style>

3. 前端页面

<template>
  <div id="aCoursesList" class="bg-fa of">
    <!-- /课程列表 开始 -->
    <section class="container">
      <header class="comm-title">
        <h2 class="fl tac">
          <span class="c-333">全部课程</span>
        </h2>
      </header>
      <section class="c-sort-box">
        <section class="c-s-dl">
          <dl>
            <dt>
              <span class="c-999 fsize14">课程类别</span>
            </dt>
            <dd class="c-s-dl-li">
              <ul class="clearfix">
                <li>
                  <a title="全部" href="#" >全部</a>
                </li>
                
                <li v-for="(item,index) in subjectNestedList" :key="index" :class="{active:oneIndex==index}">
                  <a :title="item.title" href="#" @click="searchOne(item.id,index)">{{item.title}}</a>
                </li>
               
              </ul>
            </dd>
          </dl>
          <dl>
            <dt>
              <span class="c-999 fsize14"></span>
            </dt>
            <dd class="c-s-dl-li">
              <ul class="clearfix">
                <li v-for="(item,index) in subSubjectList" :key="index" :class="{active:twoIndex==index}">
                  <a :title="item.title" href="#" @click="searchTwo(item.id,index)">{{item.title}}</a>
                </li>
               
              </ul>
            </dd>
          </dl>
          <div class="clear"></div>
        </section>
        <div class="js-wrap">
          <section class="fr">
            <span class="c-ccc">
              <i class="c-master f-fM">1</i>/
              <i class="c-666 f-fM">1</i>
            </span>
          </section>
          <section class="fl">
            <ol class="js-tap clearfix">
             <li :class="{'current bg-orange':buyCountSort!=''}">
                <a title="销量" href="javascript:void(0);" @click="searchBuyCount()">销量
                <span :class="{hide:buyCountSort==''}">↓</span>
                </a>
              </li>
              <li :class="{'current bg-orange':gmtCreateSort!=''}">
                <a title="最新" href="javascript:void(0);" @click="searchGmtCreate()">最新
                <span :class="{hide:gmtCreateSort==''}">↓</span>
                </a>
              </li>
              <li :class="{'current bg-orange':priceSort!=''}">
                <a title="价格" href="javascript:void(0);" @click="searchPrice()">价格&nbsp;
                  <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">&nbsp;</em>
            <span class="c-666 fsize14 ml10 vam">没有相关数据,小编正在努力整理中...</span>
          </section>
          <!-- /无数据提示 结束-->
          <article  v-if="data.total>0" class="comm-course-list">
            <ul class="of" id="bna">
              <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="item.title">
                    <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">9634人学习</i>
                      |
                      <i class="c-999 f-fA">9634评论</i>
                    </span>
                  </section>
                </div>
              </li>
              
            </ul>
            <div class="clear"></div>
          </article>
        </div>
        <!-- 公共分页 开始 -->
        <div>
      <div class="paging">
        <!-- undisable这个class是否存在,取决于数据属性hasPrevious -->
        <a
          :class="{undisable: !data.hasPrevious}"
          href="#"
          title="首页"
          @click.prevent="gotoPage(1)">首</a>
        <a
          :class="{undisable: !data.hasPrevious}"
          href="#"
          title="前一页"
          @click.prevent="gotoPage(data.current-1)"><</a>
        <a
          v-for="page in data.pages"
          :key="page"
          :class="{current: data.current == page, undisable: data.current == page}"
          :title="'第'+page+'页'"
          href="#"
          @click.prevent="gotoPage(page)">{{ page }}</a>
        <a
          :class="{undisable: !data.hasNext}"
          href="#"
          title="后一页"
          @click.prevent="gotoPage(data.current+1)">></a>
        <a
          :class="{undisable: !data.hasNext}"
          href="#"
          title="末页"
          @click.prevent="gotoPage(data.pages)">末</a>
        <div class="clear"/>
      </div>
    </div>
      </section>
    </section>
    <!-- /课程列表 结束 -->
  </div>
</template>

4. 测试

在这里插入图片描述
 
在这里插入图片描述
 


课程详情页

一、后端开发

1. 实体类

CourseWebVo

@Data
public class CourseWebVo {
    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;
}

#### 2. controller层
CourseFrontController

 //课程详情的方法
    @GetMapping("getFrontCourseInfo/{courseId}")
    public R getFrontCourseInfo(@PathVariable String courseId) {
        //根据课程id,编写sql语句查询课程信息
        CourseWebVo courseWebVo = courseService.getBaseCourseInfo(courseId);

        //根据课程id查询章节和小节
        List<ChapterVo> chapterVoList = chapterService.getChapterVideoByCourseId(courseId);

        return R.ok().data("courseWebVo",courseWebVo).data("chapterVoList",chapterVoList);
    }

3. service层

  • EduCourseService

     //根据课程id,编写sql语句查询课程信息
        CourseWebVo getBaseCourseInfo(String courseId);
  • EduCourseServiceImpl

    //根据课程id,编写sql语句查询课程信息
        @Override
        public CourseWebVo getBaseCourseInfo(String courseId) {
            return baseMapper.getBaseCourseInfo(courseId);
        }

4. dao层

@Mapper
public interface EduCourseMapper extends BaseMapper<EduCourse> {

    public CoursePublishVo getPublishCourseInfo(String courseId);

    //根据课程id,编写sql语句查询课程信息
    CourseWebVo getBaseCourseInfo(String courseId);
}

EduCourseMapper.xml:

  <!--前台根据课程id,查询课程基础信息-->
    <select id="getBaseCourseInfo" resultType="com.atguigu.eduservice.entity.frontvo.CourseWebVo">
        SELECT
            ec.id,
            ec.title,
            ec.cover,
            ec.lesson_num AS lessonNum,
            ec.price,
            ec.cover,
            ec.buy_count as buyCount,
            ec.view_count as viewCount,
            esd.description,
            s1.title AS subjectLevelOne,
            s1.id as subjectLevelOneId,
            s2.id as subjectLevelTwoId,
            s2.title AS subjectLevelTwo,
            t.name AS teacherName,
            t.id as teacherId,
            t.avatar,
            t.intro
        FROM
            edu_course ec
                LEFT JOIN edu_teacher t ON ec.teacher_id = t.id
                LEFT JOIN edu_subject s1 ON ec.subject_parent_id = s1.id
                LEFT JOIN edu_subject s2 ON ec.id = s2.id
                left join edu_course_description esd on ec.id = esd.id
        WHERE
            ec.id = #{id}
    </select>

5. 测试

在这里插入图片描述
 
在这里插入图片描述
 


二、前端开发

1. 定义api

api/course.js

 //课程详情的方法
    getCourseInfo(courseId) {
        return request({
            url: `/eduservice/coursefront/getFrontCourseInfo/${courseId}`,
            method: 'get'
        })
    }

2. 页面调用接口

pages/course/_id.vue

<script>
import courseApi from "@/api/course"

export default {
    asyncData({ params, error }) {
    return courseApi.getCourseInfo(params.id).then(response => {
      return { 
        courseWebVo: response.data.data.courseWebVo,
        chapterVideoList: response.data.data.chapterVideoList
      }
    })
  }
};
</script>

3. 前端页面

<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">{{courseWebVo.subjectLevelOne}}</a>
        \
        <span class="c-333 fsize14">{{ courseWebVo.subjectLevelTwo}}</span>
      </section>
      <div>
        <article class="c-v-pic-wrap" style="height: 357px">
          <section class="p-h-video-box" id="videoPlay">
            <img
              :src="courseWebVo.cover"
              :alt="courseWebVo.title"
              class="dis c-v-pic"
              height="355px"
              width="630px"
              />
          </section>
        </article>
        <aside class="c-attr-wrap">
          <section class="ml20 mr15">
            <h2 class="hLh30 txtOf mt15">
              <span class="c-fff fsize24">{{ courseWebVo.title }}</span>
            </h2>
            <section class="c-attr-jg">
              <span class="c-fff">价格:</span>
              <b class="c-yellow" style="font-size: 24px">¥{{ courseWebVo.price }}</b>
            </section>
            <section class="c-attr-mt c-attr-undis">
              <span class="c-fff fsize14">主讲: {{ courseWebVo.teacherName }}&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">{{ courseWebVo.buyCount }}</h6>
              </aside>
            </li>
            <li>
              <p>&nbsp;</p>
              <aside>
                <span class="c-fff f-fM">课时数</span>
                <br />
                <h6 class="c-fff f-fM mt10">{{ courseWebVo.lessonNum }}</h6>
              </aside>
            </li>
            <li>
              <p>&nbsp;</p>
              <aside>
                <span class="c-fff f-fM">浏览数</span>
                <br />
                <h6 class="c-fff f-fM mt10">{{ courseWebVo.viewCount }}</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">
                     <!-- 将内容中的html翻译过来 -->
                      <p v-html="courseWebVo.description">{{ courseWebVo.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 chapterVideoList" :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>
                </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="courseWebVo.avatar"
                          width="50"
                          height="50"
                          alt
                        />
                      </a>
                    </div>
                    <section class="hLh30 txtOf">
                      <a class="c-333 fsize16 fl" href="#">{{courseWebVo.teacherName}}</a>
                    </section>
                    <section class="hLh20 txtOf">
                      <span class="c-999">{{courseWebVo.intro}}</span>
                    </section>
                  </li>
                </ul>
              </section>
            </div>
          </div>
        </aside>
        <div class="clear"></div>
      </div>
    </section>
    <!-- /课程详情 结束 -->
  </div>
</template>

4. 测试

在这里插入图片描述
 
在这里插入图片描述
 


视频播放测试

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.htmlspm=a2c4g.11186623.2.16.242c6782Kdc4Za
 


整合阿里云视频播放器

一、后端获取播放凭证

1. controller层

VodController

//根据视频id获取视频凭证
    @GetMapping("/getPlayAuth/{id}")
    public R getPlayAuth(@PathVariable String id){
        try {
            //初始化
            DefaultAcsClient client = InitVodClient.initVodClient(ConstantVodUtils.ACCESS_KEY_ID, ConstantVodUtils.ACCESS_KEY_SECRET);

            //请求
            GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();
            request.setVideoId(id);

            //响应
            GetVideoPlayAuthResponse response = client.getAcsResponse(request);

            //得到播放凭证
            String playAuth = response.getPlayAuth();

            return R.ok().data("playAuth", playAuth);
            
        } catch (Exception e) {
            throw new GuliException(20001,"获取视频凭证失败");
        }
    }

2. Swagger测试

在这里插入图片描述
 
在这里插入图片描述
 


二、前端播放器整合

1. 点击播放超链接

course/_id.vue

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

2. 定义api

api/vod.js

import request from '@/utils/request'

export default{
    //根据视频id,获取视频凭证
    getPlayAuthById(id){
        return request({
            url:`/eduvod/video/getPlayAuth/${id}`,
            method: 'get'
        })
    }
}

3. 页面

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

<script>
import vod from "@/api/vod"

export default {
    layout: "video", //应用video布局
    asyncData({ params, error }) {
    return vod.getPlayAuthById(params.vid).then((response) => {
      return {
        playAuth: response.data.data.playAuth,
        vid: params.vid
      }
    })
  },

   mounted() {
    //页面渲染之后  created
    new Aliplayer(
      {
        id: "J_prismPlayer",
        vid: this.vid, // 视频id
        playauth: this.playAuth, // 播放凭证
        encryptType: "1", // 如果播放加密视频,则需设置encryptType=1,非加密视频无需设置此项
        width: "100%",
        height: "500px",
        // 以下可选设置
        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
      },function (player) {
        console.log("播放器创建成功");
      }
    )
  }

}
</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>

4. 测试

在这里插入图片描述
 
在这里插入图片描述


创作不易,如果有帮助到你,请给文章==点个赞和收藏==,让更多的人看到!!!
==关注博主==不迷路,内容持续更新中。

目录
相关文章
|
5月前
|
前端开发 JavaScript NoSQL
杨校老师项目之基于SpringBoot的驾校预约课程管理系统
杨校老师项目之基于SpringBoot的驾校预约课程管理系统
54 0
|
JavaScript 前端开发 Java
谷粒学院——Day07【课程发布-添加课程信息】
谷粒学院——Day07【课程发布-添加课程信息】
94 0
谷粒学院——Day07【课程发布-添加课程信息】
|
XML 存储 前端开发
谷粒学院——Day08【课程发布-课程大纲和课程发布】
谷粒学院——Day08【课程发布-课程大纲和课程发布】
158 0
谷粒学院——Day08【课程发布-课程大纲和课程发布】
|
存储 JSON 前端开发
谷粒学院——Day02【环境搭建和讲师管理接口开发】
谷粒学院——Day02【环境搭建和讲师管理接口开发】
334 0
谷粒学院——Day02【环境搭建和讲师管理接口开发】
|
JSON 前端开发 easyexcel
谷粒学苑项目实战(十二):课程分类管理模块搭建
谷粒学苑项目实战(十二):课程分类管理模块搭建
191 0
谷粒学苑项目实战(十二):课程分类管理模块搭建
|
存储 JavaScript 前端开发
谷粒学院——Day03【项目前端相关基础知识一】
谷粒学院——Day03【项目前端相关基础知识一】
98 0
谷粒学院——Day03【项目前端相关基础知识一】
|
编解码 JavaScript 前端开发
谷粒学院——Day04【项目前端相关基础知识二】
谷粒学院——Day04【项目前端相关基础知识二】
104 0
谷粒学院——Day04【项目前端相关基础知识二】
|
JSON 数据库 数据格式
谷粒学苑项目实战(二):讲师管理模块搭建(下)
谷粒学苑项目实战(二):讲师管理模块搭建
158 0
谷粒学苑项目实战(二):讲师管理模块搭建(下)
|
Java 测试技术 数据库
谷粒学苑项目实战(二):讲师管理模块搭建(上)
谷粒学苑项目实战(二):讲师管理模块搭建
227 0
谷粒学苑项目实战(二):讲师管理模块搭建(上)
|
SQL Java 程序员
谷粒学苑项目实战(十三):课程管理模块搭建
谷粒学苑项目实战(十三):课程管理模块搭建
177 0
谷粒学苑项目实战(十三):课程管理模块搭建