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

news2024/10/2 12:27:19

❤ 作者主页: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="前一页">&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>

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)"
                  >&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. 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)">&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>
      </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. 测试

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


视频播放测试

参考文档:https://help.aliyun.com/document_detail/61109.htmlspm=a2c4g.11186623.6.975.9ea624d8CwyqYN

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. 测试

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


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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/127888.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数字硬件建模SystemVerilog-组合逻辑建模(4)组合逻辑决策优先级

数字门级电路可分为两大类&#xff1a;组合逻辑和时序逻辑。锁存器是组合逻辑和时序逻辑的一个交叉点&#xff0c;在后面会作为单独的主题处理。组合逻辑描述了门级电路&#xff0c;其中逻辑块的输出直接反映到该块的输入值的组合&#xff0c;例如&#xff0c;双输入AND门的输出…

四点流程做好商机管理

企业想做好商机管理&#xff0c;仅凭员工是做不到的&#xff0c;借助CRM销售管理系统是比较明智的选择。接下来小编从客户信息管理、业务进程跟踪、设置提醒、销售漏斗等方面讲讲企业如何做好商机管理。 只有提高商机的转化率&#xff0c;企业的利润才会增长。想做好商机管理&…

MySQL 索引事务 · 讨论适合索引的数据结构 · N叉搜索树 · B+树 · 聚簇索引与非聚簇索引 · 事务的四个核心特性

一、索引1.1 概念1.2 作用1.3 讨论-如何提高查询的速度合适的数据结构&#xff1a;二叉搜索树AVL 树红黑树哈希表以上数据结构的问题&#xff1a;N 叉搜索树B 树B 树1.4 索引的使用场景1.5 索引的使用1.6 聚簇索引与非聚簇索引聚簇索引非聚簇索引1.7 索引 - 小结二、事务2.1 为…

小程序-会议OA项目-首页

目录 一&#xff0c;flex弹性布局 什么是flex布局&#xff1f; flex属性 flex-direction属性 学习地址&#xff1a; OA项目搭建以及flex布局演示 二&#xff0c;轮播图--组件的使用 1.先去官方文档中查看轮播图组件如何使 2.在开发工具中查看演示及修改代码 3. 使用mock…

异步通信技术AJAX | 基于JSON、XML的数据交换

目录 一&#xff1a;快速搞定AJAX&#xff08;第二篇&#xff09; 1、JS中如何创建和访问JSON对象 2、基于JSON的数据交换&#xff08;重点&#xff09; 3、基于XML的数据交换&#xff08;了解&#xff09; 一&#xff1a;快速搞定AJAX&#xff08;第二篇&#xff09; 1、…

-source1.5中不支持diamond运算符解决办法

写了几年代码了&#xff0c; 回到最初了遇到了bug了&#xff0c;没有仔细思考&#xff0c;以为很容易&#xff0c;起始走到了误区&#xff0c;有种打了一辈子鹰&#xff0c;最后被麻雀啄了眼 de 感觉 首先来看一下我们的错误信息&#xff0c;如下&#xff1a; [ERROR] Failed…

相机标定笔记(2) -- 标定实践

标定板 为什么需要标定板? 相机标定的第一篇笔记中提到了相机标定所使用的模型&#xff0c;标定算法中我们需要一些可靠的样本点&#xff0c;这些样本点由世界坐标系中的3D点和其在图像上的2D像点组成。用这些2D和3D点对来求解标定参数。为了构建更高精度的3D和2D点&#xff0…

对于系统架构来说,要么进化,要么死亡

在亚马逊云科技年度re:Invent&#xff0c;亚马逊首席技术官Dr. Werner Vogels的主题演讲历来涵盖大量科学和技术领域&#xff0c;今年的演讲也不例外&#xff0c;座无虚席。现在&#xff0c;亚马逊云科技 2022 re:Invent 中国区 recap 正式也开始了&#xff0c;欢迎大家积极参与…

单例模式之饿汉模式懒汉模式

前言 单例模式能保证某个类在程序中只存在唯一一份实例&#xff0c;而不会创建出多个实例&#xff0c;比如 JDBC 中的 DataSource 实例就只需要一个。单例模式具体的实现方式有"饿汉" 和 "懒汉" 两种。 1.饿汉模式&#xff08;类加载的同时创建实例&…

SOLIDWORKS装配体如何快速导出BOM丨慧德敏学

BOM作为产品数据的组成部分&#xff0c;它的重要性不言而喻。采购需要BOM、成本核算需要BOM、领料加工和装配需要BOM、录入ERP需要BOM……可以说&#xff0c;BOM与图纸同样重要&#xff0c;有些产品&#xff0c;可以没有图纸&#xff0c;但是不能没有BOM。借助SOLIDWORKS BOM插…

带你打开C语言的大门

最近有刚开始学习编程的同学问我&#xff1a;“C语言是什么&#xff1f;C语言是怎么来的&#xff1f;C语言用来干什么&#xff1f;”。对&#xff0c;在学习C语言之前&#xff0c;首先了解C语言的发展例程&#xff0c;这应该是每一个刚刚开始学习C语言的人应该了解的&#xff0…

什么是"文件表项"

从Linux的层次角度来说&#xff0c;在用户空间是存在这样的概念的&#xff0c;这个概念是存在内核空间的&#xff0c;而且是针对打开的文件的&#xff01; 内核用三种数据结构来描述一个打开的文件。 数据结构一: 文件描述符表(descriptor table): 每个进程都有它独立的描述符表…

【代码调试】《FSCE: Few-Shot Object Detection via Contrastive Proposal Encoding》

论文地址&#xff1a;https://arxiv.org/pdf/2103.05950.pdf 代码地址&#xff1a;https://github.com/megvii-research/FSCE 论文阅读&#xff1a;https://blog.csdn.net/qiankendeNMY/article/details/128390284 我的配置&#xff1a; Python &#xff1a;3.8(ubuntu18.04) …

小程序发布体验版流程

一、微信开发者工具操作 1. 点击 工具 -> 上传&#xff08;或 直接点击右上角“上传”按钮&#xff09; 【注意】 如果使用的测试 appid 则【上传】按钮不能点击&#xff0c;必须使用真实 appid 2. 如果之前有发布过体验版&#xff0c;会提示继续操作将会覆盖之前的体验版…

MyBatisPlus ---- 基本CRUD

MyBatisPlus ---- 基本CRUD1. BaseMapper2. 插入3. 删除a>通过id删除记录b>通过id批量删除记录c>通过map条件删除记录4. 修改5. 查询a>根据id查询用户信息b>根据多个id查询多个用户信息c>通过map条件查询用户信息d>查询所有数据6. 通用Servicea>IServi…

RK3588平台开发系列讲解(Display篇)开机视频的设置

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、开机视频功能介绍二、使用方法2.1、开启与关闭2.2、视频放置位置2.3、编译结果2.4、视频素材要求2.5、参数控制说明沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍RK3588平台开机视频的使用方法…

ARM64内存虚拟化分析(7)stage2异常处理

当虚拟机访问内存或虚拟机访问寄存器时&#xff0c;由于并没有分配真实的物理地址&#xff0c;并没有建立stage2映射&#xff0c;因此这两种情况会产生stage2异常处理&#xff0c;其中第一种情况为真实的stage2缺页&#xff0c;第二种情况为MMIO处理。同时如果在stage2产生外部…

零膨胀负二项回归案例分析

零膨胀负二项回归分析 计数研究模型中&#xff0c;常用泊松回归模型&#xff0c;但泊松回归模型理论上是要求平均值与标准差相等&#xff0c;如果不满足&#xff0c;则可使用负二项回归模型&#xff0c;负二项回归放宽了平均值标准差这一理论假定。 在实际研究中&#xff0c;…

网络协议类型

网络协议是一组规则、约定和数据结构&#xff0c;用于规定设备如何跨网络交换数据。换句话说&#xff0c;网络协议可以等同于两个设备必须理解的语言&#xff0c;以实现信息的无缝通信&#xff0c;无论其基础设施和设计差异如何。 OSI 模型&#xff1a;网络协议的工作原理 要…

Oracle数据库安装配置详细教程汇总(含11g、12c、18c、19c、21c)

不论你是数据库小白&#xff0c;还是久经沙场的技术专家&#xff0c;你接触和运维Oracle数据库的第一步可能都是安装配置。并且随着软硬件的升级、替换以及业务场景的变化&#xff0c;数据库安装也将是你常常会进行的操作之一。 这里先为大家附上Oracle各版本支持的生命周期及…