首頁課程和名師功能

01-名師頁面靜態效果整合

一、列表頁面

​ 創建 pages/teacher/index.vue

<template>
  <div id="aCoursesList" class="bg-fa of">
    <!-- 講師列表 開始 -->
    <section class="container">
      <header class="comm-title all-teacher-title">
        <h2 class="fl tac">
          <span class="c-333">全部講師</span>
        </h2>
        <section class="c-tab-title">
          <a id="subjectAll" title="全部" href="#">全部</a>
          <!-- <c:forEach var="subject" items="${subjectList }">
                            <a id="${subject.subjectId}" title="${subject.subjectName }" href="javascript:void(0)" onclick="submitForm(${subject.subjectId})">${subject.subjectName }</a>
          </c:forEach>-->
        </section>
      </header>
      <section class="c-sort-box unBr">
        <div>
          <!-- /無數據提示 開始-->
          <section class="no-data-wrap">
            <em class="icon30 no-data-ico">&nbsp;</em>
            <span class="c-666 fsize14 ml10 vam">沒有相關數據,小編正在努力整理中...</span>
          </section>
          <!-- /無數據提示 結束-->
          <article class="i-teacher-list">
            <ul class="of">
              <li>
                <section class="i-teach-wrap">
                  <div class="i-teach-pic">
                    <a href="/teacher/1" title="姚晨" target="_blank">
                      <img src="~/assets/photo/teacher/1442297885942.jpg" alt>
                    </a>
                  </div>
                  <div class="mt10 hLh30 txtOf tac">
                    <a href="/teacher/1" title="姚晨" target="_blank" class="fsize18 c-666">姚晨</a>
                  </div>
                  <div class="hLh30 txtOf tac">
                    <span class="fsize14 c-999">北京師範大學法學院副教授、清華大學法學博士。自2004年至今已有9年的司法考試培訓經驗。長期從事司法考試輔導,深知命題規律,瞭解解題技巧。內容把握準確,授課重點明確,層次分明,調理清晰,將法條法理與案例有機融合,強調綜合,深入淺出。</span>
                  </div>
                  <div class="mt15 i-q-txt">
                    <p class="c-999 f-fA">北京師範大學法學院副教授</p>
                  </div>
                </section>
              </li>
              <li>
                <section class="i-teach-wrap">
                  <div class="i-teach-pic">
                    <a href="/teacher/1" title="謝娜" target="_blank">
                      <img src="~/assets/photo/teacher/1442297919077.jpg" alt>
                    </a>
                  </div>
                  <div class="mt10 hLh30 txtOf tac">
                    <a href="/teacher/1" title="謝娜" target="_blank" class="fsize18 c-666">謝娜</a>
                  </div>
                  <div class="hLh30 txtOf tac">
                    <span class="fsize14 c-999">十年課程研發和培訓諮詢經驗,曾任國企人力資源經理、大型外企培訓經理,負責企業大學和培訓體系搭建;曾任專業培訓機構高級顧問、研發部總監,爲包括廣東移動、東莞移動、深圳移動、南方電網、工商銀行、農業銀行、民生銀行、郵儲銀行、TCL集團、清華大學繼續教育學院、中天路橋、廣西揚翔股份等超過200家企業提供過培訓與諮詢服務,並擔任近50個大型項目的總負責人。</span>
                  </div>
                  <div class="mt15 i-q-txt">
                    <p class="c-999 f-fA">資深課程設計專家,專注10年AACTP美國培訓協會認證導師</p>
                  </div>
                </section>
              </li>
              <li>
                <section class="i-teach-wrap">
                  <div class="i-teach-pic">
                    <a href="/teacher/1" title="劉德華" target="_blank">
                      <img src="~/assets/photo/teacher/1442297927029.jpg" alt>
                    </a>
                  </div>
                  <div class="mt10 hLh30 txtOf tac">
                    <a href="/teacher/1" title="劉德華" target="_blank" class="fsize18 c-666">劉德華</a>
                  </div>
                  <div class="hLh30 txtOf tac">
                    <span class="fsize14 c-999">上海師範大學法學院副教授、清華大學法學博士。自2004年至今已有9年的司法考試培訓經驗。長期從事司法考試輔導,深知命題規律,瞭解解題技巧。內容把握準確,授課重點明確,層次分明,調理清晰,將法條法理與案例有機融合,強調綜合,深入淺出。</span>
                  </div>
                  <div class="mt15 i-q-txt">
                    <p class="c-999 f-fA">上海師範大學法學院副教授</p>
                  </div>
                </section>
              </li>
              <li>
                <section class="i-teach-wrap">
                  <div class="i-teach-pic">
                    <a href="/teacher/1" title="周潤發" target="_blank">
                      <img src="~/assets/photo/teacher/1442297935589.jpg" alt>
                    </a>
                  </div>
                  <div class="mt10 hLh30 txtOf tac">
                    <a href="/teacher/1" title="周潤發" target="_blank" class="fsize18 c-666">周潤發</a>
                  </div>
                  <div class="hLh30 txtOf tac">
                    <span class="fsize14 c-999">法學博士,長期從事考研輔導。出版著作兩部,發表學術論文30餘篇,主持國家社會科學基金項目和教育部重大課題子課題各一項。</span>
                  </div>
                  <div class="mt15 i-q-txt">
                    <p class="c-999 f-fA">考研政治輔導實戰派專家,全國考研政治命題研究組核心成員。</p>
                  </div>
                </section>
              </li>
              <li>
                <section class="i-teach-wrap">
                  <div class="i-teach-pic">
                    <a href="/teacher/1" title="鍾漢良" target="_blank">
                      <img src="~/assets/photo/teacher/1442298121626.jpg" alt>
                    </a>
                  </div>
                  <div class="mt10 hLh30 txtOf tac">
                    <a href="/teacher/1" title="鍾漢良" target="_blank" class="fsize18 c-666">鍾漢良</a>
                  </div>
                  <div class="hLh30 txtOf tac">
                    <span class="fsize14 c-999">具備深厚的數學思維功底、豐富的小學教育經驗,授課風格生動活潑,擅長用形象生動的比喻幫助理解、簡單易懂的語言講解難題,深受學生喜歡</span>
                  </div>
                  <div class="mt15 i-q-txt">
                    <p class="c-999 f-fA">畢業於師範大學數學系,熱愛教育事業,執教數學思維6年有餘</p>
                  </div>
                </section>
              </li>
              <li>
                <section class="i-teach-wrap">
                  <div class="i-teach-pic">
                    <a href="/teacher/1" title="唐嫣" target="_blank">
                      <img src="~/assets/photo/teacher/1442297957332.jpg" alt>
                    </a>
                  </div>
                  <div class="mt10 hLh30 txtOf tac">
                    <a href="/teacher/1" title="唐嫣" target="_blank" class="fsize18 c-666">唐嫣</a>
                  </div>
                  <div class="hLh30 txtOf tac">
                    <span class="fsize14 c-999">中國科學院數學與系統科學研究院應用數學專業博士,研究方向爲數字圖像處理,中國工業與應用數學學會會員。參與全國教育科學“十五”規劃重點課題“信息化進程中的教育技術發展研究”的子課題“基與課程改革的資源開發與應用”,以及全國“十五”科研規劃全國重點項目“掌上型信息技術產品在教學中的運用和開發研究”的子課題“用技術學數學”。</span>
                  </div>
                  <div class="mt15 i-q-txt">
                    <p class="c-999 f-fA">中國人民大學附屬中學數學一級教師</p>
                  </div>
                </section>
              </li>
              <li>
                <section class="i-teach-wrap">
                  <div class="i-teach-pic">
                    <a href="/teacher/1" title="周杰倫" target="_blank">
                      <img src="~/assets/photo/teacher/1442297969808.jpg" alt>
                    </a>
                  </div>
                  <div class="mt10 hLh30 txtOf tac">
                    <a href="/teacher/1" title="周杰倫" target="_blank" class="fsize18 c-666">周杰倫</a>
                  </div>
                  <div class="hLh30 txtOf tac">
                    <span class="fsize14 c-999">中教一級職稱。講課極具親和力。</span>
                  </div>
                  <div class="mt15 i-q-txt">
                    <p class="c-999 f-fA">畢業於北京大學數學系</p>
                  </div>
                </section>
              </li>
              <li>
                <section class="i-teach-wrap">
                  <div class="i-teach-pic">
                    <a href="/teacher/1" title="陳偉霆" target="_blank">
                      <img src="~/assets/photo/teacher/1442297977255.jpg" alt>
                    </a>
                  </div>
                  <div class="mt10 hLh30 txtOf tac">
                    <a href="/teacher/1" title="陳偉霆" target="_blank" class="fsize18 c-666">陳偉霆</a>
                  </div>
                  <div class="hLh30 txtOf tac">
                    <span
                      class="fsize14 c-999"
                    >政治學博士、管理學博士後,。多年來總結出了一套行之有效的應試技巧與答題方法,針對性和實用性極強,能幫助考生在輕鬆中應考,在激勵的競爭中取得高分,脫穎而出。</span>
                  </div>
                  <div class="mt15 i-q-txt">
                    <p class="c-999 f-fA">長期從事考研政治課講授和考研命題趨勢與應試對策研究。考研輔導新銳派的代表。</p>
                  </div>
                </section>
              </li>
            </ul>
            <div class="clear"></div>
          </article>
        </div>
        <!-- 公共分頁 開始 -->
        <div>
          <div class="paging">
            <!-- undisable這個class是否存在,取決於數據屬性hasPrevious -->
            <a href="#" title="首頁">首</a>
            <a href="#" title="前一頁">&lt;</a>
            <a href="#" title="第1頁" class="current undisable">1</a>
            <a href="#" title="第2頁">2</a>
            <a href="#" title="後一頁">&gt;</a>
            <a href="#" title="末頁">末</a>
            <div class="clear"></div>
          </div>
        </div>
        <!-- 公共分頁 結束 -->
      </section>
    </section>
    <!-- /講師列表 結束 -->
  </div>
</template>
<script>
export default {};
</script>

二、詳情頁面

創建 pages/teacher/_id.vue

修改資源路徑爲~/assets/

<template>
  <div id="aCoursesList" class="bg-fa of">
    <!-- 講師介紹 開始 -->
    <section class="container">
      <header class="comm-title">
        <h2 class="fl tac">
          <span class="c-333">講師介紹</span>
        </h2>
      </header>
      <div class="t-infor-wrap">
        <!-- 講師基本信息 -->
        <section class="fl t-infor-box c-desc-content">
          <div class="mt20 ml20">
            <section class="t-infor-pic">
              <img src="~/assets/photo/teacher/1442297885942.jpg">
            </section>
            <h3 class="hLh30">
              <span class="fsize24 c-333">姚晨&nbsp;高級講師</span>
            </h3>
            <section class="mt10">
              <span class="t-tag-bg">北京師範大學法學院副教授</span>
            </section>
            <section class="t-infor-txt">
              <p
                class="mt20"
              >北京師範大學法學院副教授、清華大學法學博士。自2004年至今已有9年的司法考試培訓經驗。長期從事司法考試輔導,深知命題規律,瞭解解題技巧。內容把握準確,授課重點明確,層次分明,調理清晰,將法條法理與案例有機融合,強調綜合,深入淺出。</p>
            </section>
            <div class="clear"></div>
          </div>
        </section>
        <div class="clear"></div>
      </div>
      <section class="mt30">
        <div>
          <header class="comm-title all-teacher-title c-course-content">
            <h2 class="fl tac">
              <span class="c-333">主講課程</span>
            </h2>
            <section class="c-tab-title">
              <a href="javascript: void(0)">&nbsp;</a>
            </section>
          </header>
          <!-- /無數據提示 開始-->
          <section class="no-data-wrap">
            <em class="icon30 no-data-ico">&nbsp;</em>
            <span class="c-666 fsize14 ml10 vam">沒有相關數據,小編正在努力整理中...</span>
          </section>
          <!-- /無數據提示 結束-->
          <article class="comm-course-list">
            <ul class="of">
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img src="~/assets/photo/course/1442295455437.jpg" class="img-responsive" >
                    <div class="cc-mask">
                      <a href="#" title="開始學習" target="_blank" class="comm-btn c-btn-1">開始學習</a>
                    </div>
                  </section>
                  <h3 class="hLh30 txtOf mt10">
                    <a href="#" title="零基礎入門學習Python課程學習" target="_blank" class="course-title fsize18 c-333">零基礎入門學習Python課程學習</a>
                  </h3>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img src="~/assets/photo/course/1442295472860.jpg" class="img-responsive" >
                    <div class="cc-mask">
                      <a href="#" title="開始學習" target="_blank" class="comm-btn c-btn-1">開始學習</a>
                    </div>
                  </section>
                  <h3 class="hLh30 txtOf mt10">
                    <a href="#" title="影想力攝影小課堂" target="_blank" class="course-title fsize18 c-333">影想力攝影小課堂</a>
                  </h3>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img src="~/assets/photo/course/1442302831779.jpg" class="img-responsive" >
                    <div class="cc-mask">
                      <a href="#" title="開始學習" target="_blank" class="comm-btn c-btn-1">開始學習</a>
                    </div>
                  </section>
                  <h3 class="hLh30 txtOf mt10">
                    <a href="#" title="數學給寶寶帶來的興趣" target="_blank" class="course-title fsize18 c-333">數學給寶寶帶來的興趣</a>
                  </h3>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img src="~/assets/photo/course/1442295506745.jpg" class="img-responsive" >
                    <div class="cc-mask">
                      <a href="#" title="開始學習" target="_blank" class="comm-btn c-btn-1">開始學習</a>
                    </div>
                  </section>
                  <h3 class="hLh30 txtOf mt10">
                    <a href="#" title="國家教師資格考試專用" target="_blank" class="course-title fsize18 c-333">國家教師資格考試專用</a>
                  </h3>
                </div>
              </li>
            </ul>
            <div class="clear"></div>
          </article>
        </div>
      </section>
    </section>
    <!-- /講師介紹 結束 -->
  </div>
</template>
<script>
export default {};
</script>

02-講師列表頁

一、後端

1、TeacherService

接口

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

實現

@Override
public Map<String, Object> pageListWeb(Page<Teacher> pageParam) {

    QueryWrapper<Teacher> queryWrapper = new QueryWrapper<>();
    queryWrapper.orderByAsc("sort");

    baseMapper.selectPage(pageParam, queryWrapper);

    List<Teacher> records = pageParam.getRecords();
    long current = pageParam.getCurrent();
    long pages = pageParam.getPages();
    long size = pageParam.getSize();
    long total = pageParam.getTotal();
    boolean hasNext = pageParam.hasNext();
    boolean hasPrevious = pageParam.hasPrevious();

    Map<String, Object> map = new HashMap<String, Object>();
    map.put("items", records);
    map.put("current", current);
    map.put("pages", pages);
    map.put("size", size);
    map.put("total", total);
    map.put("hasNext", hasNext);
    map.put("hasPrevious", hasPrevious);

    return map;
}

2、TeacherController

@ApiOperation(value = "分頁講師列表")
@GetMapping(value = "{page}/{limit}")
public R pageList(
    @ApiParam(name = "page", value = "當前頁碼", required = true)
    @PathVariable Long page,

    @ApiParam(name = "limit", value = "每頁記錄數", required = true)
    @PathVariable Long limit){

    Page<Teacher> pageParam = new Page<Teacher>(page, limit);

    Map<String, Object> map = teacherService.pageListWeb(pageParam);

    return  R.ok().data(map);
}

3、swagger測試

二、前端列表js

1、創建api

創建文件夾api,api下創建teacher.js,用於封裝講師模塊的請求

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

2、講師列表組件中調用api

pages/teacher/index.vue

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

三、頁面渲染

1、頁面模板

<template>
  <div id="aCoursesList" class="bg-fa of">
    <!-- 講師列表 開始 -->
    <section class="container">
      <section class="c-sort-box unBr">
        <div>
          <!-- 無數據提示 開始-->

          <!-- /無數據提示 結束-->

          <!-- 數據列表 開始-->

          <!-- /數據列表 結束-->
        </div>
        <!-- 公共分頁 開始 -->

        <!-- /公共分頁 結束 -->
      </section>
    </section>
    <!-- /講師列表 結束 -->
  </div>
</template>

2、無數據提示

添加:v-if=“data.total==0”

<!-- /無數據提示 開始-->
<section class="no-data-wrap" v-if="data.total==0">
    <em class="icon30 no-data-ico">&nbsp;</em>
    <span class="c-666 fsize14 ml10 vam">沒有相關數據,小編正在努力整理中...</span>
</section>
<!-- /無數據提示 結束-->

3、列表

<!-- /數據列表 開始-->
<article v-if="data.total>0" class="i-teacher-list">
    <ul class="of">
        <li v-for="item in data.items" :key="item.id">
            <section class="i-teach-wrap">
                <div class="i-teach-pic">
                    <a :href="'/teacher/'+item.id" :title="item.name">
                        <img :src="item.avatar" :alt="item.name" height="142" hright="142">
                    </a>
                </div>
                <div class="mt10 hLh30 txtOf tac">
                    <a :href="'/teacher/'+item.id" :title="item.name" class="fsize18 c-666">{{ item.name }}</a>
                </div>
                <div class="hLh30 txtOf tac">
                    <span class="fsize14 c-999" >{{ item.career }}</span>
                </div>
                <div class="mt15 i-q-txt">
                    <p class="c-999 f-fA">{{ item.intro }}</p>
                </div>
            </section>
        </li>
    </ul>
    <div class="clear"/>
</article>
<!-- /數據列表 結束-->

4、測試

四、分頁

1、分頁方法

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

2、分頁頁面渲染

<!-- 公共分頁 開始 -->
<div>
  <div class="paging">
    <!-- undisable這個class是否存在,取決於數據屬性hasPrevious -->
    <a
      :class="{undisable: !data.hasPrevious}"
      href="#"
      title="首頁"
      @click.prevent="gotoPage(1)">首</a>
    <a
      :class="{undisable: !data.hasPrevious}"
      href="#"
      title="前一頁"
      @click.prevent="gotoPage(data.current-1)">&lt;</a>
    <a
      v-for="page in data.pages"
      :key="page"
      :class="{current: data.current == page, undisable: data.current == page}"
      :title="'第'+page+'頁'"
      href="#"
      @click.prevent="gotoPage(page)">{{ page }}</a>
    <a
      :class="{undisable: !data.hasNext}"
      href="#"
      title="後一頁"
      @click.prevent="gotoPage(data.current+1)">&gt;</a>
    <a
      :class="{undisable: !data.hasNext}"
      href="#"
      title="末頁"
      @click.prevent="gotoPage(data.pages)">末</a>
    <div class="clear"/>
  </div>
</div>
<!-- 公共分頁 結束 -->

3、測試

03-講師詳情頁

一、後端

1、CourseService

根據講師id查詢講師所講課程列表

接口

List<Course> selectByTeacherId(String teacherId);

實現

/**
     * 根據講師id查詢當前講師的課程列表
     * @param teacherId
     * @return
     */
@Override
public List<Course> selectByTeacherId(String teacherId) {

    QueryWrapper<Course> queryWrapper = new QueryWrapper<Course>();

    queryWrapper.eq("teacher_id", teacherId);
    //按照最後更新時間倒序排列
    queryWrapper.orderByDesc("gmt_modified");

    List<Course> courses = baseMapper.selectList(queryWrapper);
    return courses;
}

2、TeacherController

@Autowired
private CourseService courseService;

修改getById方法:

@ApiOperation(value = "根據ID查詢講師")
@GetMapping(value = "{id}")
public R getById(
        @ApiParam(name = "id", value = "講師ID", required = true)
        @PathVariable String id){

    //查詢講師信息
    Teacher teacher = teacherService.getById(id);

    //根據講師id查詢這個講師的課程列表
    List<Course> courseList = courseService.selectByTeacherId(id);

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

3、swagger測試

二、前端詳情js

1、teacher api

api/teacher.js

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

2、講師詳情頁中調用api

pages/teacher/_id.vue

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

三、頁面渲染

1、講師基本信息模板

<template>
  <div id="aCoursesList" class="bg-fa of">
    <!-- 講師介紹 開始 -->
    <section class="container">
      <header class="comm-title">
        <h2 class="fl tac">
          <span class="c-333">講師介紹</span>
        </h2>
      </header>
      <div class="t-infor-wrap">
        <!-- 講師基本信息 開始 -->

        <!-- /講師基本信息 結束 -->
        <div class="clear"/>
      </div>
      <section class="mt30">
        <div>
          <header class="comm-title all-teacher-title c-course-content">
            <h2 class="fl tac">
              <span class="c-333">主講課程</span>
            </h2>
            <section class="c-tab-title">
              <a href="javascript: void(0)">&nbsp;</a>
            </section>
          </header>
          <!-- 無數據提示 開始-->

          <!-- /無數據提示 結束-->

          <!-- 課程列表 開始-->

          <!-- /課程列表 結束-->
        </div>
      </section>
    </section>
    <!-- /講師介紹 結束 -->
  </div>
</template>

2、講師詳情顯示

<!-- 講師基本信息 開始 -->
<section class="fl t-infor-box c-desc-content">
    <div class="mt20 ml20">
        <section class="t-infor-pic">
            <img :src="teacher.avatar" :alt="teacher.name">
        </section>
        <h3 class="hLh30">
            <span class="fsize24 c-333">{{ teacher.name }}
                &nbsp;
                {{ teacher.level===1?'高級講師':'首席講師' }}
            </span>
        </h3>
        <section class="mt10">
            <span class="t-tag-bg">{{ teacher.intro }}</span>
        </section>
        <section class="t-infor-txt">
            <p class="mt20">{{ teacher.career }}</p>
        </section>
        <div class="clear"/>
    </div>
</section>
<!-- /講師基本信息 結束 -->

3、無數據提示

<!-- 無數據提示 開始-->
<section class="no-data-wrap" v-if="courseList.total==0">
    <em class="icon30 no-data-ico">&nbsp;</em>
    <span class="c-666 fsize14 ml10 vam">沒有相關數據,小編正在努力整理中...</span>
</section>
<!-- /無數據提示 結束-->

4、當前講師課程列表

<!-- 課程列表 開始-->
<article class="comm-course-list">
  <ul class="of">
    <li v-for="course in courseList" :key="course.id">
      <div class="cc-l-wrap">
        <section class="course-img">
          <img :src="course.cover" class="img-responsive">
          <div class="cc-mask">
            <a :href="'/course/'+course.id" title="開始學習" target="_blank" class="comm-btn c-btn-1">開始學習</a>
          </div>
        </section>
        <h3 class="hLh30 txtOf mt10">
          <a
            :href="'/course/'+course.id"
            :title="course.title"
            target="_blank"
            class="course-title fsize18 c-333">{{ course.title }}</a>
        </h3>
      </div>
    </li>
  </ul>
  <div class="clear"/>
</article>
<!-- /課程列表 結束-->

5、測試

04-課程頁面靜態效果整合

一、列表頁面

創建 pages/course/index.vue

<template>
  <div id="aCoursesList" class="bg-fa of">
    <!-- /課程列表 開始 -->
    <section class="container">
      <header class="comm-title">
        <h2 class="fl tac">
          <span class="c-333">全部課程</span>
        </h2>
      </header>
      <section class="c-sort-box">
        <section class="c-s-dl">
          <dl>
            <dt>
              <span class="c-999 fsize14">課程類別</span>
            </dt>
            <dd class="c-s-dl-li">
              <ul class="clearfix">
                <li>
                  <a title="全部" href="#">全部</a>
                </li>
                <li>
                  <a title="數據庫" href="#">數據庫</a>
                </li>
                <li class="current">
                  <a title="外語考試" href="#">外語考試</a>
                </li>
                <li>
                  <a title="教師資格證" href="#">教師資格證</a>
                </li>
                <li>
                  <a title="公務員" href="#">公務員</a>
                </li>
                <li>
                  <a title="移動開發" href="#">移動開發</a>
                </li>
                <li>
                  <a title="操作系統" href="#">操作系統</a>
                </li>
              </ul>
            </dd>
          </dl>
          <dl>
            <dt>
              <span class="c-999 fsize14"></span>
            </dt>
            <dd class="c-s-dl-li">
              <ul class="clearfix">
                <li>
                  <a title="職稱英語" href="#">職稱英語</a>
                </li>
                <li>
                  <a title="英語四級" href="#">英語四級</a>
                </li>
                <li>
                  <a title="英語六級" href="#">英語六級</a>
                </li>
              </ul>
            </dd>
          </dl>
          <div class="clear"></div>
        </section>
        <div class="js-wrap">
          <section class="fr">
            <span class="c-ccc">
              <i class="c-master f-fM">1</i>/
              <i class="c-666 f-fM">1</i>
            </span>
          </section>
          <section class="fl">
            <ol class="js-tap clearfix">
              <li>
                <a title="關注度" href="#">關注度</a>
              </li>
              <li>
                <a title="最新" href="#">最新</a>
              </li>
              <li class="current bg-orange">
                <a title="價格" href="#">價格&nbsp;
                  <span>↓</span>
                </a>
              </li>
            </ol>
          </section>
        </div>
        <div class="mt40">
          <!-- /無數據提示 開始-->
          <section class="no-data-wrap">
            <em class="icon30 no-data-ico">&nbsp;</em>
            <span class="c-666 fsize14 ml10 vam">沒有相關數據,小編正在努力整理中...</span>
          </section>
          <!-- /無數據提示 結束-->
          <article class="comm-course-list">
            <ul class="of" id="bna">
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img src="~/assets/photo/course/1442295592705.jpg" class="img-responsive" alt="聽力口語">
                    <div class="cc-mask">
                      <a href="/course/1" title="開始學習" class="comm-btn c-btn-1">開始學習</a>
                    </div>
                  </section>
                  <h3 class="hLh30 txtOf mt10">
                    <a href="/course/1" title="聽力口語" class="course-title fsize18 c-333">聽力口語</a>
                  </h3>
                  <section class="mt10 hLh20 of">
                    <span class="fr jgTag bg-green">
                      <i class="c-fff fsize12 f-fA">免費</i>
                    </span>
                    <span class="fl jgAttr c-ccc f-fA">
                      <i class="c-999 f-fA">9634人學習</i>
                      |
                      <i class="c-999 f-fA">9634評論</i>
                    </span>
                  </section>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img src="~/assets/photo/course/1442295581911.jpg" class="img-responsive" alt="Java精品課程">
                    <div class="cc-mask">
                      <a href="/course/1" title="開始學習" class="comm-btn c-btn-1">開始學習</a>
                    </div>
                  </section>
                  <h3 class="hLh30 txtOf mt10">
                    <a href="/course/1" title="Java精品課程" class="course-title fsize18 c-333">Java精品課程</a>
                  </h3>
                  <section class="mt10 hLh20 of">
                    <span class="fr jgTag bg-green">
                      <i class="c-fff fsize12 f-fA">免費</i>
                    </span>
                    <span class="fl jgAttr c-ccc f-fA">
                      <i class="c-999 f-fA">501人學習</i>
                      |
                      <i class="c-999 f-fA">501評論</i>
                    </span>
                  </section>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img src="~/assets/photo/course/1442295604295.jpg" class="img-responsive" alt="C4D零基礎">
                    <div class="cc-mask">
                      <a href="/course/1" title="開始學習" class="comm-btn c-btn-1">開始學習</a>
                    </div>
                  </section>
                  <h3 class="hLh30 txtOf mt10">
                    <a href="/course/1" title="C4D零基礎" class="course-title fsize18 c-333">C4D零基礎</a>
                  </h3>
                  <section class="mt10 hLh20 of">
                    <span class="fr jgTag bg-green">
                      <i class="c-fff fsize12 f-fA">免費</i>
                    </span>
                    <span class="fl jgAttr c-ccc f-fA">
                      <i class="c-999 f-fA">300人學習</i>
                      |
                      <i class="c-999 f-fA">300評論</i>
                    </span>
                  </section>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img
                      src="~/assets/photo/course/1442302831779.jpg"
                      class="img-responsive"
                      alt="數學給寶寶帶來的興趣"
                    >
                    <div class="cc-mask">
                      <a href="/course/1" title="開始學習" class="comm-btn c-btn-1">開始學習</a>
                    </div>
                  </section>
                  <h3 class="hLh30 txtOf mt10">
                    <a href="/course/1" title="數學給寶寶帶來的興趣" class="course-title fsize18 c-333">數學給寶寶帶來的興趣</a>
                  </h3>
                  <section class="mt10 hLh20 of">
                    <span class="fr jgTag bg-green">
                      <i class="c-fff fsize12 f-fA">免費</i>
                    </span>
                    <span class="fl jgAttr c-ccc f-fA">
                      <i class="c-999 f-fA">256人學習</i>
                      |
                      <i class="c-999 f-fA">256評論</i>
                    </span>
                  </section>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img
                      src="~/assets/photo/course/1442295455437.jpg"
                      class="img-responsive"
                      alt="零基礎入門學習Python課程學習"
                    >
                    <div class="cc-mask">
                      <a href="/course/1" title="開始學習" class="comm-btn c-btn-1">開始學習</a>
                    </div>
                  </section>
                  <h3 class="hLh30 txtOf mt10">
                    <a
                      href="/course/1"
                      title="零基礎入門學習Python課程學習"
                      class="course-title fsize18 c-333"
                    >零基礎入門學習Python課程學習</a>
                  </h3>
                  <section class="mt10 hLh20 of">
                    <span class="fr jgTag bg-green">
                      <i class="c-fff fsize12 f-fA">免費</i>
                    </span>
                    <span class="fl jgAttr c-ccc f-fA">
                      <i class="c-999 f-fA">137人學習</i>
                      |
                      <i class="c-999 f-fA">137評論</i>
                    </span>
                  </section>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img
                      src="~/assets/photo/course/1442295570359.jpg"
                      class="img-responsive"
                      alt="MySql從入門到精通"
                    >
                    <div class="cc-mask">
                      <a href="/course/1" title="開始學習" class="comm-btn c-btn-1">開始學習</a>
                    </div>
                  </section>
                  <h3 class="hLh30 txtOf mt10">
                    <a href="/course/1" title="MySql從入門到精通" class="course-title fsize18 c-333">MySql從入門到精通</a>
                  </h3>
                  <section class="mt10 hLh20 of">
                    <span class="fr jgTag bg-green">
                      <i class="c-fff fsize12 f-fA">免費</i>
                    </span>
                    <span class="fl jgAttr c-ccc f-fA">
                      <i class="c-999 f-fA">125人學習</i>
                      |
                      <i class="c-999 f-fA">125評論</i>
                    </span>
                  </section>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img src="~/assets/photo/course/1442302852837.jpg" class="img-responsive" alt="搜索引擎優化技術">
                    <div class="cc-mask">
                      <a href="/course/1" title="開始學習" class="comm-btn c-btn-1">開始學習</a>
                    </div>
                  </section>
                  <h3 class="hLh30 txtOf mt10">
                    <a href="/course/1" title="搜索引擎優化技術" class="course-title fsize18 c-333">搜索引擎優化技術</a>
                  </h3>
                  <section class="mt10 hLh20 of">
                    <span class="fr jgTag bg-green">
                      <i class="c-fff fsize12 f-fA">免費</i>
                    </span>
                    <span class="fl jgAttr c-ccc f-fA">
                      <i class="c-999 f-fA">123人學習</i>
                      |
                      <i class="c-999 f-fA">123評論</i>
                    </span>
                  </section>
                </div>
              </li>
              <li>
                <div class="cc-l-wrap">
                  <section class="course-img">
                    <img src="~/assets/photo/course/1442295379715.jpg" class="img-responsive" alt="20世紀西方音樂">
                    <div class="cc-mask">
                      <a href="/course/1" title="開始學習" class="comm-btn c-btn-1">開始學習</a>
                    </div>
                  </section>
                  <h3 class="hLh30 txtOf mt10">
                    <a href="/course/1" title="20世紀西方音樂" class="course-title fsize18 c-333">20世紀西方音樂</a>
                  </h3>
                  <section class="mt10 hLh20 of">
                    <span class="fr jgTag bg-green">
                      <i class="c-fff fsize12 f-fA">免費</i>
                    </span>
                    <span class="fl jgAttr c-ccc f-fA">
                      <i class="c-999 f-fA">34人學習</i>
                      |
                      <i class="c-999 f-fA">34評論</i>
                    </span>
                  </section>
                </div>
              </li>
            </ul>
            <div class="clear"></div>
          </article>
        </div>
        <!-- 公共分頁 開始 -->
        <div>
          <div class="paging">
            <a class="undisable" title>首</a>
            <a id="backpage" class="undisable" href="#" title>&lt;</a>
            <a href="#" title class="current undisable">1</a>
            <a href="#" title>2</a>
            <a id="nextpage" href="#" title>&gt;</a>
            <a href="#" title>末</a>
            <div class="clear"></div>
          </div>
        </div>
        <!-- 公共分頁 結束 -->
      </section>
    </section>
    <!-- /課程列表 結束 -->
  </div>
</template>
<script>
export default {};
</script>

二、詳情頁面

創建 pages/course/_id.vue

<template>
  <div id="aCoursesList" class="bg-fa of">
    <!-- /課程詳情 開始 -->
    <section class="container">
      <section class="path-wrap txtOf hLh30">
        <a href="#" title class="c-999 fsize14">首頁</a>
        \
        <a href="#" title class="c-999 fsize14">課程列表</a>
        \
        <span class="c-333 fsize14">Java精品課程</span>
      </section>
      <div>
        <article class="c-v-pic-wrap" style="height: 357px;">
          <section class="p-h-video-box" id="videoPlay">
            <img src="~/assets/photo/course/1442295581911.jpg" alt="Java精品課程" class="dis c-v-pic">
          </section>
        </article>
        <aside class="c-attr-wrap">
          <section class="ml20 mr15">
            <h2 class="hLh30 txtOf mt15">
              <span class="c-fff fsize24">Java精品課程</span>
            </h2>
            <section class="c-attr-jg">
              <span class="c-fff">價格:</span>
              <b class="c-yellow" style="font-size:24px;">¥0.00</b>
            </section>
            <section class="c-attr-mt c-attr-undis">
              <span class="c-fff fsize14">主講: 唐嫣&nbsp;&nbsp;&nbsp;</span>
            </section>
            <section class="c-attr-mt of">
              <span class="ml10 vam">
                <em class="icon18 scIcon"></em>
                <a class="c-fff vam" title="收藏" href="#" >收藏</a>
              </span>
            </section>
            <section class="c-attr-mt">
              <a href="#" title="立即觀看" class="comm-btn c-btn-3">立即觀看</a>
            </section>
          </section>
        </aside>
        <aside class="thr-attr-box">
          <ol class="thr-attr-ol clearfix">
            <li>
              <p>&nbsp;</p>
              <aside>
                <span class="c-fff f-fM">購買數</span>
                <br>
                <h6 class="c-fff f-fM mt10">150</h6>
              </aside>
            </li>
            <li>
              <p>&nbsp;</p>
              <aside>
                <span class="c-fff f-fM">課時數</span>
                <br>
                <h6 class="c-fff f-fM mt10">20</h6>
              </aside>
            </li>
            <li>
              <p>&nbsp;</p>
              <aside>
                <span class="c-fff f-fM">瀏覽數</span>
                <br>
                <h6 class="c-fff f-fM mt10">501</h6>
              </aside>
            </li>
          </ol>
        </aside>
        <div class="clear"></div>
      </div>
      <!-- /課程封面介紹 -->
      <div class="mt20 c-infor-box">
        <article class="fl col-7">
          <section class="mr30">
            <div class="i-box">
              <div>
                <section id="c-i-tabTitle" class="c-infor-tabTitle c-tab-title">
                  <a name="c-i" class="current" title="課程詳情">課程詳情</a>
                </section>
              </div>
              <article class="ml10 mr10 pt20">
                <div>
                  <h6 class="c-i-content c-infor-title">
                    <span>課程介紹</span>
                  </h6>
                  <div class="course-txt-body-wrap">
                    <section class="course-txt-body">
                      <p>
                        Java的發展歷史,可追溯到1990年。當時Sun&nbsp;Microsystem公司爲了發展消費性電子產品而進行了一個名爲Green的項目計劃。該計劃
                        負責人是James&nbsp;Gosling。起初他以C++來寫一種內嵌式軟件,可以放在烤麪包機或PAD等小型電子消費設備裏,使得機器更聰明,具有人工智
                        能。但他發現C++並不適合完成這類任務!因爲C++常會有使系統失效的程序錯誤,尤其是內存管理,需要程序設計師記錄並管理內存資源。這給設計師們造成
                        極大的負擔,並可能產生許多bugs。&nbsp;
                        <br>爲了解決所遇到的問題,Gosling決定要發展一種新的語言,來解決C++的潛在性危險問題,這個語言名叫Oak。Oak是一種可移植性語言,也就是一種平臺獨立語言,能夠在各種芯片上運行。
                        <br>1994年,Oak技術日趨成熟,這時網絡正開始蓬勃發展。Oak研發小組發現Oak很適合作爲一種網絡程序語言。因此發展了一個能與Oak配合的瀏
                        覽器--WebRunner,後更名爲HotJava,它證明了Oak是一種能在網絡上發展的程序語言。由於Oak商標已被註冊,工程師們便想到以自己常
                        享用的咖啡(Java)來重新命名,並於Sun&nbsp;World&nbsp;95中被發表出來。
                      </p>
                    </section>
                  </div>
                </div>
                <!-- /課程介紹 -->
                <div class="mt50">
                  <h6 class="c-g-content c-infor-title">
                    <span>課程大綱</span>
                  </h6>
                  <section class="mt20">
                    <div class="lh-menu-wrap">
                      <menu id="lh-menu" class="lh-menu mt10 mr10">
                        <ul>
                          <!-- 文件目錄 -->
                          <li class="lh-menu-stair">
                            <a href="javascript: void(0)" title="第一章" class="current-1">
                              <em class="lh-menu-i-1 icon18 mr10"></em>第一章
                            </a>
                            <ol class="lh-menu-ol" style="display: block;">
                              <li class="lh-menu-second ml30">
                                <a href="#" title>
                                  <span class="fr">
                                    <i class="free-icon vam mr10">免費試聽</i>
                                  </span>
                                  <em class="lh-menu-i-2 icon16 mr5">&nbsp;</em>第一節
                                </a>
                              </li>
                              <li class="lh-menu-second ml30">
                                <a href="#" title class="current-2">
                                  <em class="lh-menu-i-2 icon16 mr5">&nbsp;</em>第二節
                                </a>
                              </li>
                            </ol>
                          </li>
                        </ul>
                      </menu>
                    </div>
                  </section>
                </div>
                <!-- /課程大綱 -->
              </article>
            </div>
          </section>
        </article>
        <aside class="fl col-3">
          <div class="i-box">
            <div>
              <section class="c-infor-tabTitle c-tab-title">
                <a title href="javascript:void(0)">主講講師</a>
              </section>
              <section class="stud-act-list">
                <ul style="height: auto;">
                  <li>
                    <div class="u-face">
                      <a href="#">
                        <img src="~/assets/photo/teacher/1442297969808.jpg" width="50" height="50" alt>
                      </a>
                    </div>
                    <section class="hLh30 txtOf">
                      <a class="c-333 fsize16 fl" href="#">周杰倫</a>
                    </section>
                    <section class="hLh20 txtOf">
                      <span class="c-999">畢業於北京大學數學系</span>
                    </section>
                  </li>
                </ul>
              </section>
            </div>
          </div>
        </aside>
        <div class="clear"></div>
      </div>
    </section>
    <!-- /課程詳情 結束 -->
  </div>
</template>

<script>
export default {};
</script>

05-課程列表頁面

一、課程後端接口

1、課程列表

(1)課程列表vo類

@ApiModel(value = "課程查詢對象", description = "課程查詢對象封裝")
@Data
public class CourseQueryVo implements Serializable {
    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "課程名稱")
    private String title;

    @ApiModelProperty(value = "講師id")
    private String teacherId;

    @ApiModelProperty(value = "一級類別id")
    private String subjectParentId;

    @ApiModelProperty(value = "二級類別id")
    private String subjectId;

    @ApiModelProperty(value = "銷量排序")
    private String buyCountSort;

    @ApiModelProperty(value = "最新時間排序")
    private String gmtCreateSort;

    @ApiModelProperty(value = "價格排序")
    private String priceSort;
}

(2)課程列表controller

@ApiOperation(value = "分頁課程列表")
@PostMapping(value = "{page}/{limit}")
public R pageList(
        @ApiParam(name = "page", value = "當前頁碼", required = true)
        @PathVariable Long page,

        @ApiParam(name = "limit", value = "每頁記錄數", required = true)
        @PathVariable Long limit,

        @ApiParam(name = "courseQuery", value = "查詢對象", required = false)
                @RequestBody(required = false) CourseQueryVo courseQuery){
    Page<EduCourse> pageParam = new Page<EduCourse>(page, limit);
    Map<String, Object> map = courseService.pageListWeb(pageParam, courseQuery);
    return  R.ok().data(map);
}

(3)課程列表service

@Override
public Map<String, Object> pageListWeb(Page<EduCourse> pageParam, CourseQueryVo courseQuery) {
        QueryWrapper<EduCourse> queryWrapper = new QueryWrapper<>();
        if (!StringUtils.isEmpty(courseQuery.getSubjectParentId())) {
            queryWrapper.eq("subject_parent_id", courseQuery.getSubjectParentId());
        }

        if (!StringUtils.isEmpty(courseQuery.getSubjectId())) {
            queryWrapper.eq("subject_id", courseQuery.getSubjectId());
        }

        if (!StringUtils.isEmpty(courseQuery.getBuyCountSort())) {
            queryWrapper.orderByDesc("buy_count");
        }

        if (!StringUtils.isEmpty(courseQuery.getGmtCreateSort())) {
            queryWrapper.orderByDesc("gmt_create");
        }

        if (!StringUtils.isEmpty(courseQuery.getPriceSort())) {
            queryWrapper.orderByDesc("price");
        }

        baseMapper.selectPage(pageParam, queryWrapper);

        List<EduCourse> records = pageParam.getRecords();
        long current = pageParam.getCurrent();
        long pages = pageParam.getPages();
        long size = pageParam.getSize();
        long total = pageParam.getTotal();
        boolean hasNext = pageParam.hasNext();
        boolean hasPrevious = pageParam.hasPrevious();

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("items", records);
        map.put("current", current);
        map.put("pages", pages);
        map.put("size", size);
        map.put("total", total);
        map.put("hasNext", hasNext);
        map.put("hasPrevious", hasPrevious);

        return map;
}

二**、課程列表前端**

1、定義api

api/course.js

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

2、頁面調用接口

pages/course/index.vue

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

export default {

  data () {
    return {
      page:1,
      data:{},
      subjectNestedList: [], // 一級分類列表
      subSubjectList: [], // 二級分類列表
      searchObj: {}, // 查詢表單對象
      oneIndex:-1,
      twoIndex:-1,
      buyCountSort:"",
      gmtCreateSort:"",
      priceSort:""
    }
  },

  //加載完渲染時
  created () {
    //獲取課程列表
    this.initCourse()

    //獲取分類
    this.initSubject()
  },

  methods: {
    //查詢課程列表
    initCourse(){
      course.getPageList(1, 8,this.searchObj).then(response => {
        this.data = response.data.data
      })
    },
    //查詢所有一級分類
    initSubject(){
      //debugger
      course.getNestedTreeList2().then(response => {
        this.subjectNestedList = response.data.data.items
      })
    },
    
    //點擊一級分類,顯示對應的二級分類,查詢數據
    searchOne(subjectParentId, index) {
      //debugger
      this.oneIndex = index
      this.twoIndex = -1

      this.searchObj.subjectId = "";
      this.subSubjectList = [];

      this.searchObj.subjectParentId = subjectParentId;
      this.gotoPage(this.page)

      for (let i = 0; i < this.subjectNestedList.length; i++) {
        if (this.subjectNestedList[i].id === subjectParentId) {
          this.subSubjectList = this.subjectNestedList[i].children
        }
      }
    },

    //點擊二級分類,查詢數據
    searchTwo(subjectId, index) {
      this.twoIndex = index
      this.searchObj.subjectId = subjectId;
      this.gotoPage(this.page)
    },
    //購買量查詢
    searchBuyCount() {
      this.buyCountSort = "1";
      this.gmtCreateSort = "";
      this.priceSort = "";
      this.searchObj.buyCountSort = this.buyCountSort;
      this.searchObj.gmtCreateSort = this.gmtCreateSort;
      this.searchObj.priceSort = this.priceSort;
      this.gotoPage(this.page)
    },
    //更新時間查詢
    searchGmtCreate() {
      debugger
      this.buyCountSort = "";
      this.gmtCreateSort = "1";
      this.priceSort = "";
      this.searchObj.buyCountSort = this.buyCountSort;
      this.searchObj.gmtCreateSort = this.gmtCreateSort;
      this.searchObj.priceSort = this.priceSort;
      this.gotoPage(this.page)
    },
    //價格查詢
    searchPrice() {
      this.buyCountSort = "";
      this.gmtCreateSort = "";
      this.priceSort = "1";
      this.searchObj.buyCountSort = this.buyCountSort;
      this.searchObj.gmtCreateSort = this.gmtCreateSort;
      this.searchObj.priceSort = this.priceSort;
      this.gotoPage(this.page)
    },
    //分頁查詢
    gotoPage(page) {
      this.page = page
      course.getPageList(page, 8, this.searchObj).then(response => {
        this.data = response.data.data
      })
    }
  }
}
</script>
<style scoped>
  .active {
    background: #bdbdbd;
  }
  .hide {
    display: none;
  }
  .show {
    display: block;
  }
</style>

三、課程列表渲染

1、課程類別顯示

<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="javascript:void(0);" @click="searchOne('')">全部</a>
        </li>
        <li v-for="(item,index) in subjectNestedList" v-bind:key="index" :class="{active:oneIndex==index}">
          <a :title="item.title" href="javascript:void(0);" @click="searchOne(item.id, index)">{{item.title}}</a>
        </li>
      </ul>
    </dd>
  </dl>
  <dl>
    <dt>
      <span class="c-999 fsize14"/>
    </dt>
    <dd class="c-s-dl-li">
      <ul class="clearfix">
        <li v-for="(item,index) in subSubjectList" v-bind:key="index" :class="{active:twoIndex==index}">
          <a :title="item.title" href="javascript:void(0);" @click="searchTwo(item.id, index)">{{item.title}}</a>
        </li>
      </ul>
    </dd>
  </dl>
  <div class="clear"/>
</section>

2、排序方式顯示

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

3、無數據提示

添加: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>
<!-- /無數據提示 結束-->

4、列表

<!-- 數據列表 開始-->
<article v-if="data.total>0" class="comm-course-list">
    <ul id="bna" class="of">
        <li v-for="item in data.items" :key="item.id">
            <div class="cc-l-wrap">
                <section class="course-img">
                    <img :src="item.cover" class="img-responsive" alt="聽力口語">
                    <div class="cc-mask">
                        <a :href="'/course/'+item.id" title="開始學習" class="comm-btn c-btn-1">開始學習</a>
                    </div>
                </section>
                <h3 class="hLh30 txtOf mt10">
                    <a :href="'/course/'+item.id" :title="item.title" class="course-title fsize18 c-333">{{ item.title }}</a>
                </h3>
                <section class="mt10 hLh20 of">
                    <span v-if="Number(item.price) === 0" class="fr jgTag bg-green">
                        <i class="c-fff fsize12 f-fA">免費</i>
                    </span>
                    <span class="fl jgAttr c-ccc f-fA">
                        <i class="c-999 f-fA">{{ item.viewCount }}人學習</i>
                        |
                        <i class="c-999 f-fA">9634評論</i>
                    </span>
                </section>
            </div>
        </li>
    </ul>
    <div class="clear"/>
</article>
<!-- /數據列表 結束-->

5、分頁頁面渲染

<div>
  <div class="paging">
    <!-- undisable這個class是否存在,取決於數據屬性hasPrevious -->
    <a
      :class="{undisable: !data.hasPrevious}"
      href="#"
      title="首頁"
      @click.prevent="gotoPage(1)">首</a>
    <a
      :class="{undisable: !data.hasPrevious}"
      href="#"
      title="前一頁"
      @click.prevent="gotoPage(data.current-1)">&lt;</a>
    <a
      v-for="page in data.pages"
      :key="page"
      :class="{current: data.current == page, undisable: data.current == page}"
      :title="'第'+page+'頁'"
      href="#"
      @click.prevent="gotoPage(page)">{{ page }}</a>
    <a
      :class="{undisable: !data.hasNext}"
      href="#"
      title="後一頁"
      @click.prevent="gotoPage(data.current+1)">&gt;</a>
    <a
      :class="{undisable: !data.hasNext}"
      href="#"
      title="末頁"
      @click.prevent="gotoPage(data.pages)">末</a>
    <div class="clear"/>
  </div>
</div>

06-課程詳情頁

一、vo對象的定義

在項目中很多時候需要把model轉換成dto用於網站信息的展示,按前端的需要傳遞對象的數據,保證model對外是隱私的,例如密碼之類的屬性能很好地避免暴露在外,同時也會減小數據傳輸的體積。

CourseWebVo.java
package com.guli.edu.vo;

@ApiModel(value="課程信息", description="網站課程詳情頁需要的相關字段")
@Data
public class CourseWebVo implements Serializable {

    private static final long serialVersionUID = 1L;

    private String id;

    @ApiModelProperty(value = "課程標題")
    private String title;

    @ApiModelProperty(value = "課程銷售價格,設置爲0則可免費觀看")
    private BigDecimal price;

    @ApiModelProperty(value = "總課時")
    private Integer lessonNum;

    @ApiModelProperty(value = "課程封面圖片路徑")
    private String cover;

    @ApiModelProperty(value = "銷售數量")
    private Long buyCount;

    @ApiModelProperty(value = "瀏覽數量")
    private Long viewCount;

    @ApiModelProperty(value = "課程簡介")
    private String description;

    @ApiModelProperty(value = "講師ID")
    private String teacherId;

    @ApiModelProperty(value = "講師姓名")
    private String teacherName;
    
    @ApiModelProperty(value = "講師資歷,一句話說明講師")
    private String intro;

    @ApiModelProperty(value = "講師頭像")
    private String avatar;

    @ApiModelProperty(value = "課程類別ID")
    private String subjectLevelOneId;

    @ApiModelProperty(value = "類別名稱")
    private String subjectLevelOne;

    @ApiModelProperty(value = "課程類別ID")
    private String subjectLevelTwoId;

    @ApiModelProperty(value = "類別名稱")
    private String subjectLevelTwo;
    
}

二、課程和講師信息的獲取

1、Mapper中關聯查詢課程和講師信息

CourseMapper.java

CourseWebVo selectInfoWebById(String courseId);

CourseMapper.xml

<select id="selectInfoWebById" resultType="com.guli.edu.vo.CourseWebVo">
  SELECT
    c.id,
    c.title,
    c.cover,
    CONVERT(c.price, DECIMAL(8,2)) AS price,
    c.lesson_num AS lessonNum,
    c.cover,
    c.buy_count AS buyCount,
    c.view_count AS viewCount,
    cd.description,

    t.id AS teacherId,
    t.name AS teacherName,
    t.intro,
    t.avatar,
    
    s1.id AS subjectLevelOneId,
    s1.title AS subjectLevelOne,
    s2.id AS subjectLevelTwoId,
    s2.title AS subjectLevelTwo

  FROM
    edu_course c
    LEFT JOIN edu_course_description cd ON c.id = cd.id
    LEFT JOIN edu_teacher t ON c.teacher_id = t.id
    LEFT JOIN edu_subject s1 ON c.subject_parent_id = s1.id
    LEFT JOIN edu_subject s2 ON c.subject_id = s2.id
  WHERE
    c.id = #{id}
</select>

2、業務層獲取數據並更新瀏覽量

CourseService

接口

/**
     * 獲取課程信息
     * @param id
     * @return
     */
CourseWebVo selectInfoWebById(String id);

/**
     * 更新課程瀏覽數
     * @param id
     */
void updatePageViewCount(String id);

實現

@Override
public CourseWebVo selectInfoWebById(String id) {
    this.updatePageViewCount(id);
    return baseMapper.selectInfoWebById(id);
}

@Override
public void updatePageViewCount(String id) {
    Course course = baseMapper.selectById(id);
    course.setViewCount(course.getViewCount() + 1);
    baseMapper.updateById(course);
}

3、接口層

CourseController

@Autowired
private ChapterService chapterService;

@ApiOperation(value = "根據ID查詢課程")
@GetMapping(value = "{courseId}")
public R getById(
    @ApiParam(name = "courseId", value = "課程ID", required = true)
    @PathVariable String courseId){

    //查詢課程信息和講師信息
    CourseWebVo courseWebVo = courseService.selectInfoWebById(courseId);

    //查詢當前課程的章節信息
    List<ChapterVo> chapterVoList = chapterService.nestedList(courseId);

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

4、swagger測試

三、前端js

1、api/course.js

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

2、pages/course/_id.vue

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

四、頁面模板

pages/course/_id.vue

1、template

<template>
  <div id="aCoursesList" class="bg-fa of">
    <!-- 課程詳情 開始 -->
    <section class="container">

      <!-- 課程所屬分類 開始 -->

      <!-- /課程所屬分類 結束 -->

      <!-- 課程基本信息 開始 -->

      <!-- /課程基本信息 結束 -->

      <div class="mt20 c-infor-box">
        <article class="fl col-7">
          <section class="mr30">
            <div class="i-box">
              <div>
                <section id="c-i-tabTitle" class="c-infor-tabTitle c-tab-title">
                  <a name="c-i" class="current" title="課程詳情">課程詳情</a>
                </section>
              </div>
              <article class="ml10 mr10 pt20">

                <!-- 課程詳情介紹 開始 -->

                <!-- /課程詳情介紹 結束 -->

                <!-- 課程大綱 開始-->

                <!-- /課程大綱 結束 -->
              </article>
            </div>
          </section>
        </article>
        <aside class="fl col-3">
          <div class="i-box">
            <!-- 主講講師 開始-->

            <!-- /主講講師 結束 -->
          </div>
        </aside>
        <div class="clear"/>
      </div>
    </section>
    <!-- /課程詳情 結束 -->
  </div>
</template>

2、課程所屬分類

<!-- 課程所屬分類 開始 -->
<section class="path-wrap txtOf hLh30">
    <a href="#" title class="c-999 fsize14">首頁</a>
    \
    <a href="/course" title class="c-999 fsize14">課程列表</a>
    \
    <span class="c-333 fsize14">{{ course.subjectLevelOne }}</span>
    \
    <span class="c-333 fsize14">{{ course.subjectLevelTwo }}</span>
</section>
<!-- /課程所屬分類 結束 -->

3、課程基本信息

<!-- 課程基本信息 開始 -->
<div>
    <article class="c-v-pic-wrap" style="height: 357px;">
        <section id="videoPlay" class="p-h-video-box">
            <img :src="course.cover" :alt="course.title" class="dis c-v-pic">
        </section>
    </article>
    <aside class="c-attr-wrap">
        <section class="ml20 mr15">
            <h2 class="hLh30 txtOf mt15">
                <span class="c-fff fsize24">{{ course.title }}</span>
            </h2>
            <section class="c-attr-jg">
                <span class="c-fff">價格:</span>
                <b class="c-yellow" style="font-size:24px;">¥{{ course.price }}</b>
            </section>
            <section class="c-attr-mt c-attr-undis">
                <span class="c-fff fsize14">主講: {{ course.teacherName }}&nbsp;&nbsp;&nbsp;</span>
            </section>
            <section class="c-attr-mt of">
                <span class="ml10 vam">
                    <em class="icon18 scIcon"/>
                    <a class="c-fff vam" title="收藏" href="#" >收藏</a>
                </span>
            </section>
            <section class="c-attr-mt">
                <a href="#" title="立即觀看" class="comm-btn c-btn-3">立即觀看</a>
            </section>
        </section>
    </aside>
    <aside class="thr-attr-box">
        <ol class="thr-attr-ol clearfix">
            <li>
                <p>&nbsp;</p>
                <aside>
                    <span class="c-fff f-fM">購買數</span>
                    <br>
                    <h6 class="c-fff f-fM mt10">{{ course.buyCount }}</h6>
                </aside>
            </li>
            <li>
                <p>&nbsp;</p>
                <aside>
                    <span class="c-fff f-fM">課時數</span>
                    <br>
                    <h6 class="c-fff f-fM mt10">{{ course.lessonNum }}</h6>
                </aside>
            </li>
            <li>
                <p>&nbsp;</p>
                <aside>
                    <span class="c-fff f-fM">瀏覽數</span>
                    <br>
                    <h6 class="c-fff f-fM mt10">{{ course.viewCount }}</h6>
                </aside>
            </li>
        </ol>
    </aside>
    <div class="clear"/>
</div>
<!-- /課程基本信息 結束 -->

4、課程詳情介紹

<!-- 課程詳情介紹 開始 -->
<div>
    <h6 class="c-i-content c-infor-title">
        <span>課程介紹</span>
    </h6>
    <div class="course-txt-body-wrap">
        <section class="course-txt-body">
            <!-- 將內容中的html翻譯過來 -->
            <p v-html="course.description">{{ course.description }}</p>
        </section>
    </div>
</div>
<!-- /課程詳情介紹 結束 -->

5、課程大綱

<!-- 課程大綱 開始-->
<div class="mt50">
    <h6 class="c-g-content c-infor-title">
        <span>課程大綱</span>
    </h6>
    <section class="mt20">
        <div class="lh-menu-wrap">
            <menu id="lh-menu" class="lh-menu mt10 mr10">
                <ul>
                    <!-- 課程章節目錄 -->
                    <li v-for="chapter in chapterList" :key="chapter.id" class="lh-menu-stair">
                        <a :title="chapter.title" href="javascript: void(0)" class="current-1">
                            <em class="lh-menu-i-1 icon18 mr10"/>{{ chapter.title }}
                        </a>
                        <ol class="lh-menu-ol" style="display: block;">
                            <li v-for="video in chapter.children" :key="video.id" class="lh-menu-second ml30">
                                <a href="#" title>
                                    <span v-if="video.free === true" class="fr">
                                        <i class="free-icon vam mr10">免費試聽</i>
                                    </span>
                                    <em class="lh-menu-i-2 icon16 mr5">&nbsp;</em>{{ video.title }}
                                </a>
                            </li>
                        </ol>
                    </li>
                </ul>
            </menu>
        </div>
    </section>
    <!-- /課程大綱 結束 -->

6、主講講師

<!-- 主講講師 開始-->
<div>
    <section class="c-infor-tabTitle c-tab-title">
        <a title href="javascript:void(0)">主講講師</a>
    </section>
    <section class="stud-act-list">
        <ul style="height: auto;">
            <li>
                <div class="u-face">
                    <a :href="'/teacher/'+course.teacherId" target="_blank">
                        <img :src="course.avatar" width="50" height="50" alt>
                    </a>
                </div>
                <section class="hLh30 txtOf">
                    <a :href="'/teacher/'+course.teacherId" class="c-333 fsize16 fl" target="_blank">{{ course.teacherName }}</a>
                </section>
                <section class="hLh20 txtOf">
                    <span class="c-999">{{ course.intro }}</span>
                </section>
            </li>
        </ul>
    </section>
</div>
<!-- /主講講師 結束 -->

07-視頻播放測試

一、獲取播放地址播放

獲取播放地址

參考文檔:https://help.aliyun.com/document_detail/61064.html

前面的 03-使用服務端SDK 介紹瞭如何獲取非加密視頻的播放地址。直接使用03節的例子獲取加密視頻播放地址會返回如下錯誤信息

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

目前只有AliyunVoDEncryption流存在,您必須使用Aliyun player來播放或將ResultType的值設置爲Multiple。

因此在testGetPlayInfo測試方法中添加 ResultType 參數,並設置爲true

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

此種方式獲取的視頻文件不能直接播放,必須使用阿里雲播放器播放

二、視頻播放器

參考文檔:https://help.aliyun.com/document_detail/61109.html

1、視頻播放器介紹

阿里雲播放器SDK(ApsaraVideo Player SDK)是阿里視頻服務的重要一環,除了支持點播和直播的基礎播放功能外,深度融合視頻雲業務,如支持視頻的加密播放、安全下載、清晰度切換、直播答題等業務場景,爲用戶提供簡單、快速、安全、穩定的視頻播放服務。

2、集成視頻播放器

參考文檔:https://help.aliyun.com/document_detail/51991.html

參考 【 播放器簡單使用說明】一節

引入腳本文件和css文件

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

初始化視頻播放器

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

3、播放地址播放

在Aliplayer的配置參數中添加如下屬性

//播放方式一:支持播放地址播放,此播放優先級最高,此種方式不能播放加密視頻
source : '你的視頻播放地址',

啓動瀏覽器運行,測試視頻的播放

4、播放憑證播放(推薦)

阿里雲播放器支持通過播放憑證自動換取播放地址進行播放,接入方式更爲簡單,且安全性更高。播放憑證默認時效爲100秒(最大爲3000秒),只能用於獲取指定視頻的播放地址,不能混用或重複使用。如果憑證過期則無法獲取播放地址,需要重新獲取憑證。

encryptType:'1',//如果播放加密視頻,則需設置encryptType=1,非加密視頻無需設置此項
vid : '視頻id',
playauth : '視頻授權碼',

注意:播放憑證有過期時間,默認值:100秒 。取值範圍:100~3000

設置播放憑證的有效期

在獲取播放憑證的測試用例中添加如下代碼

request.setAuthInfoTimeout(200L);

在線配置參考:https://player.alicdn.com/aliplayer/setting/setting.html

08-整合阿里雲視頻播放器

一、後端獲取播放憑證

1、VideoController

service-vod微服務中創建 VideoController.java

controller中創建 getVideoPlayAuth 接口方法

package com.guli.vod.controller;

@Api(description="阿里雲視頻點播微服務")
@CrossOrigin //跨域
@RestController
@RequestMapping("/vod/video")
public class VideoController {

    @GetMapping("get-play-auth/{videoId}")
    public R getVideoPlayAuth(@PathVariable("videoId") String videoId) throws Exception {

        //獲取阿里雲存儲相關常量
        String accessKeyId = ConstantPropertiesUtil.ACCESS_KEY_ID;
        String accessKeySecret = ConstantPropertiesUtil.ACCESS_KEY_SECRET;

        //初始化
        DefaultAcsClient client = AliyunVodSDKUtils.initVodClient(accessKeyId, accessKeySecret);

        //請求
        GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();
        request.setVideoId(videoId);

        //響應
        GetVideoPlayAuthResponse response = client.getAcsResponse(request);

        //得到播放憑證
        String playAuth = response.getPlayAuth();

        //返回結果
        return R.ok().message("獲取憑證成功").data("playAuth", playAuth);
    }   
}

2、Swagger測試

二、前端播放器整合

1、點擊播放超鏈接

course/_id.vue

修改課時目錄超鏈接

在這裏插入圖片描述

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

2、layout

因爲播放器的佈局和其他頁面的基本佈局不一致,因此創建新的佈局容器 layouts/video.vue

<template>
  <div class="guli-player">
    <div class="head">
      <a href="#" title="穀粒學院">
        <img class="logo" src="~/assets/img/logo.png" lt="穀粒學院">
    </a></div>
    <div class="body">
      <div class="content"><nuxt/></div>
    </div>
  </div>
</template>
<script>
export default {}
</script>

<style>
html,body{
  height:100%;
}
</style>

<style scoped>
.head {
  height: 50px;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
}

.head .logo{
  height: 50px;
  margin-left: 10px;
}

.body {
  position: absolute;
  top: 50px;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;
}
</style>

3、api

創建api模塊 api/vod.js,從後端獲取播放憑證

import request from '@/utils/request'
const api_name = '/vod/video'

export default {

  getPlayAuth(vid) {
    return request({
      url: `${api_name}/get-play-auth/${vid}`,
      method: 'get'
    })
  }

}

4、播放組件相關文檔

集成文檔: https://help.aliyun.com/document_detail/51991.html?spm=a2c4g.11186623.2.39.478e192b8VSdEn

在線配置: https://player.alicdn.com/aliplayer/setting/setting.html

功能展示: https://player.alicdn.com/aliplayer/presentation/index.html

5、創建播放頁面

創建 pages/player/_vid.vue

(1)引入播放器js庫和css樣式

<template>
  <div>

    <!-- 阿里雲視頻播放器樣式 -->
    <link rel="stylesheet" href="https://g.alicdn.com/de/prismplayer/2.8.1/skins/default/aliplayer-min.css" >
    <!-- 阿里雲視頻播放器腳本 -->
    <script charset="utf-8" type="text/javascript" src="https://g.alicdn.com/de/prismplayer/2.8.1/aliplayer-min.js" />

    <!-- 定義播放器dom -->
    <div id="J_prismPlayer" class="prism-player" />
  </div>
</template>

(2)獲取播放憑證

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

(3)創建播放器

 /**
 * 頁面渲染完成時:此時js腳本已加載,Aliplayer已定義,可以使用
 * 如果在created生命週期函數中使用,Aliplayer is not defined錯誤
 */
mounted() {
    
    new Aliplayer({
        id: 'J_prismPlayer',
        vid: this.vid, // 視頻id
        playauth: this.playAuth, // 播放憑證
        encryptType: '1', // 如果播放加密視頻,則需設置encryptType=1,非加密視頻無需設置此項
        width: '100%',
        height: '500px'
    }, function(player) {
        console.log('播放器創建成功')
    })
}

(4)其他常見的可選配置

// 以下可選設置
cover: 'http://guli.shop/photo/banner/1525939573202.jpg', // 封面
qualitySort: 'asc', // 清晰度排序

mediaType: 'video', // 返回音頻還是視頻
autoplay: false, // 自動播放
isLive: false, // 直播
rePlay: false, // 循環播放
preload: true,
controlBarVisibility: 'hover', // 控制條的顯示方式:鼠標懸停
useH5Prism: true, // 播放器類型:html5

6、加入播放組件

功能展示: https://player.alicdn.com/aliplayer/presentation/index.html

09-課程評論功能

一、數據庫設計

1、數據庫

edu_comment

2、數據表

guli_edu.sql

二、創建課程評論接口

1、在service-edu模塊,生成課程評論代碼

(1)使用mp代碼生成器生成

2、在service-ucenter模塊,創建接口(1)***實現用戶id獲取用戶信息,返回用戶信息對象***

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

3、創建課程評論controller

(1)在service-edu模塊創建client,實現微服務調用

@Component
@FeignClient(name="service-ucenter",fallback = UcenterClientImpl.class)
public interface UcenterClient {

    //根據用戶id獲取用戶信息
    @GetMapping("/ucenterservice/member/getUcenterPay/{memberId}")
    public UcenterMemberPay getUcenterPay(@PathVariable("memberId") String memberId);
}

@Component
public class UcenterClientImpl implements UcenterClient {
    @Override
    public UcenterMemberPay getUcenterPay(String memberId) {
        return null;
    }
}

(2)創建評論列表和添加評論接口

@RestController
@RequestMapping("/eduservice/comment")
@CrossOrigin
public class CommentFrontController {

    @Autowired
    private CommentService commentService;
    @Autowired
    private UcenterClient ucenterClient;

    //根據課程id查詢評論列表
    @ApiOperation(value = "評論分頁列表")
    @GetMapping("{page}/{limit}")
    public R index(
            @ApiParam(name = "page", value = "當前頁碼", required = true)
            @PathVariable Long page,

            @ApiParam(name = "limit", value = "每頁記錄數", required = true)
            @PathVariable Long limit,

            @ApiParam(name = "courseQuery", value = "查詢對象", required = false)
                    String courseId) {
        Page<Comment> pageParam = new Page<>(page, limit);

        QueryWrapper<Comment> wrapper = new QueryWrapper<>();
        wrapper.eq("course_id",courseId);

        commentService.page(pageParam,wrapper);
        List<Comment> commentList = pageParam.getRecords();

        Map<String, Object> map = new HashMap<>();
        map.put("items", commentList);
        map.put("current", pageParam.getCurrent());
        map.put("pages", pageParam.getPages());
        map.put("size", pageParam.getSize());
        map.put("total", pageParam.getTotal());
        map.put("hasNext", pageParam.hasNext());
        map.put("hasPrevious", pageParam.hasPrevious());
        return R.ok().data(map);
    }

    @ApiOperation(value = "添加評論")
    @PostMapping("auth/save")
    public R save(@RequestBody Comment comment, HttpServletRequest request) {
        String memberId = JwtUtils.getMemberIdByJwtToken(request);
        if(StringUtils.isEmpty(memberId)) {
            return R.error().code(28004).message("請登錄");
        }
        comment.setMemberId(memberId);

        UcenterMemberPay ucenterInfo = ucenterClient.getUcenterPay(memberId);

        comment.setNickname(ucenterInfo.getNickname());
        comment.setAvatar(ucenterInfo.getAvatar());

        commentService.save(comment);
        return R.ok();
    }
}

三、課程評論前端整合

1、在api創建commonedu.js

import request from '@/utils/request'

export default {

  getPageList(page, limit, courseId) {
    return request({
      url: `/eduservice/comment/${page}/${limit}`,
      method: 'get',
      params: {courseId}
    })
  },
  addComment(comment) {
    return request({
      url: `/eduservice/comment/auth/save`,
      method: 'post',
      data: comment
    })
  }
}

2、在課程詳情頁面,調用方法 _id.vue

import comment from '@/api/commonedu'
    
<script>
import course from '@/api/course'
import comment from '@/api/commonedu'
export default {

     //和頁面異步開始的
  asyncData({ params, error }) {
    return {courseId: params.id}
    
  },
  data() {
    return {
      data:{},
      page:1,
      limit:4,
      total:10,
      comment:{
        content:'',
        courseId:''
      },
      courseInfo:{},
      chapterVideoList:[],
      isbuyCourse:false
    }
  },
  created() {
    this.initCourseInfo()
    this.initComment()
  },
  methods:{
    //獲取課程詳情
    initCourseInfo() {
      course.getCourseInfo(this.courseId)
            .then(response => {
              this.courseInfo=response.data.data.courseFrontInfo
              this.chapterVideoList=response.data.data.chapterVideoList
              this.isbuyCourse=response.data.data.isbuyCourse
            })
    },

    initComment(){
       comment.getPageList(this.page, this.limit, this.courseId).then(response => {
           this.data = response.data.data
       })
    },
    addComment(){
        this.comment.courseId = this.courseId
        this.comment.teacherId = this.courseInfo.teacherId
        comment.addComment(this.comment).then(response => {
            if(response.data.success){
                this.comment.content = ''
                this.initComment()
            }
        })
    },
    gotoPage(page){
          comment.getPageList(page, this.limit,this.courseId).then(response => {
              this.data = response.data.data
          })
      }
  }
  
};
</script>

3、在課程詳情頁面 _id.vue顯示評論

<div class="mt50 commentHtml"><div>
      <h6 class="c-c-content c-infor-title" id="i-art-comment">
        <span class="commentTitle">課程評論</span>
      </h6>
      <section class="lh-bj-list pr mt20 replyhtml">
        <ul>
          <li class="unBr">
            <aside class="noter-pic">
              <img width="50" height="50" class="picImg" src="~/assets/img/avatar-boy.gif">
              </aside>
            <div class="of">
              <section class="n-reply-wrap">
                <fieldset>
                  <textarea name="" v-model="comment.content" placeholder="輸入您要評論的文字" id="commentContent"></textarea>
                </fieldset>
                <p class="of mt5 tar pl10 pr10">
                  <span class="fl "><tt class="c-red commentContentmeg" style="display: none;"></tt></span>
                  <input type="button" @click="addComment()" value="回覆" class="lh-reply-btn">
                </p>
              </section>
            </div>
          </li>
        </ul>
      </section>
      <section class="">
          <section class="question-list lh-bj-list pr">
            <ul class="pr10">
              <li v-for="(comment,index) in data.items" v-bind:key="index">
                  <aside class="noter-pic">
                    <img width="50" height="50" class="picImg" :src="comment.avatar">
                    </aside>
                  <div class="of">
                    <span class="fl"> 
                    <font class="fsize12 c-blue"> 
                      {{comment.nickname}}</font>
                    <font class="fsize12 c-999 ml5">評論:</font></span>
                  </div>
                  <div class="noter-txt mt5">
                    <p>{{comment.content}}</p>
                  </div>
                  <div class="of mt5">
                    <span class="fr"><font class="fsize12 c-999 ml5">{{comment.gmtCreate}}</font></span>
                  </div>
                </li>
              
              </ul>
          </section>
        </section>
        
        <!-- 公共分頁 開始 -->
        <div class="paging">
            <!-- undisable這個class是否存在,取決於數據屬性hasPrevious -->
            <a
            :class="{undisable: !data.hasPrevious}"
            href="#"
            title="首頁"
            @click.prevent="gotoPage(1)">首</a>
            <a
            :class="{undisable: !data.hasPrevious}"
            href="#"
            title="前一頁"
            @click.prevent="gotoPage(data.current-1)">&lt;</a>
            <a
            v-for="page in data.pages"
            :key="page"
            :class="{current: data.current == page, undisable: data.current == page}"
            :title="'第'+page+'頁'"
            href="#"
            @click.prevent="gotoPage(page)">{{ page }}</a>
            <a
            :class="{undisable: !data.hasNext}"
            href="#"
            title="後一頁"
            @click.prevent="gotoPage(data.current+1)">&gt;</a>
            <a
            :class="{undisable: !data.hasNext}"
            href="#"
            title="末頁"
            @click.prevent="gotoPage(data.pages)">末</a>
            <div class="clear"/>
        </div>
        <!-- 公共分頁 結束 -->
      </div>
    </div>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章