一、课程后端接口

1、课程列表

(1)课程列表vo类

  1. @ApiModel(value = "课程查询对象", description = "课程查询对象封装")
  2. @Data
  3. public class CourseQueryVo implements Serializable {
  4. private static final long serialVersionUID = 1L;
  5. @ApiModelProperty(value = "课程名称")
  6. private String title;
  7. @ApiModelProperty(value = "讲师id")
  8. private String teacherId;
  9. @ApiModelProperty(value = "一级类别id")
  10. private String subjectParentId;
  11. @ApiModelProperty(value = "二级类别id")
  12. private String subjectId;
  13. @ApiModelProperty(value = "销量排序")
  14. private String buyCountSort;
  15. @ApiModelProperty(value = "最新时间排序")
  16. private String gmtCreateSort;
  17. @ApiModelProperty(value = "价格排序")
  18. private String priceSort;
  19. }

(2)课程列表controller

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

(3)课程列表service

  1. @Override
  2. public Map<String, Object> pageListWeb(Page<EduCourse> pageParam, CourseQueryVo courseQuery) {
  3. QueryWrapper<EduCourse> queryWrapper = new QueryWrapper<>();
  4. if (!StringUtils.isEmpty(courseQuery.getSubjectParentId())) {
  5. queryWrapper.eq("subject_parent_id", courseQuery.getSubjectParentId());
  6. }
  7. if (!StringUtils.isEmpty(courseQuery.getSubjectId())) {
  8. queryWrapper.eq("subject_id", courseQuery.getSubjectId());
  9. }
  10. if (!StringUtils.isEmpty(courseQuery.getBuyCountSort())) {
  11. queryWrapper.orderByDesc("buy_count");
  12. }
  13. if (!StringUtils.isEmpty(courseQuery.getGmtCreateSort())) {
  14. queryWrapper.orderByDesc("gmt_create");
  15. }
  16. if (!StringUtils.isEmpty(courseQuery.getPriceSort())) {
  17. queryWrapper.orderByDesc("price");
  18. }
  19. baseMapper.selectPage(pageParam, queryWrapper);
  20. List<EduCourse> records = pageParam.getRecords();
  21. long current = pageParam.getCurrent();
  22. long pages = pageParam.getPages();
  23. long size = pageParam.getSize();
  24. long total = pageParam.getTotal();
  25. boolean hasNext = pageParam.hasNext();
  26. boolean hasPrevious = pageParam.hasPrevious();
  27. Map<String, Object> map = new HashMap<String, Object>();
  28. map.put("items", records);
  29. map.put("current", current);
  30. map.put("pages", pages);
  31. map.put("size", size);
  32. map.put("total", total);
  33. map.put("hasNext", hasNext);
  34. map.put("hasPrevious", hasPrevious);
  35. return map;
  36. }

**

、课程列表前端

1、定义api

api/course.js

  1. import request from '@/utils/request'
  2. export default {
  3. getPageList(page, limit, searchObj) {
  4. return request({
  5. url: `/eduservice/edu/course/${page}/${limit}`,
  6. method: 'post',
  7. data: searchObj
  8. })
  9. },
  10. // 获取课程二级分类
  11. getNestedTreeList2() {
  12. return request({
  13. url: `/eduservice/edu/course/list2`,
  14. method: 'get'
  15. })
  16. }
  17. }

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>