86-分布式前端开发

前端门户系统

经过上一章的后端开发后,接下来我们来操作前端开发,页面不需要我们自己开发,使用提供的页面即可
对应的前端初始项目地址:
链接:https://pan.baidu.com/s/1iFui2WbE1mfmHWnb9Z8oGg
提取码:alsk
运行项目 npm run serve
接下来进行开发
但要注意:这里只会给出部分代码,需要自己去进行对比修改(记得启动对应的后端,且没有的自然自己写)
由于是部分,对应的代码可能不是全的
可以使用ctrl+f进行查找,或者ctrl+d进行找到一样的(虽然从上到下,循环的,直到找到自己)
进入首页组件Index.vue

对应的js部分:
 created() {
    this.getCourseList() //组件使用时,就调用获取课程信息的方法
  },
  getCourseList(){ //去dubbo服务获取全部课程的数据
    return this.axios.get("http://localhost:8002/course/getAllCourse").then(res => {
      console.log(res)
    }).catch(err =>{
      this.$message.error("获取课程信息失败")
    })
    }
进行访问后,查询浏览器的检查,是否有对应数据,一般对应的data根据对应编码值来显示先后
实际上是因为对应的json操作返回的(后台的操作)
测试后,若有数据,那么接下来则编写具体代码,代码部分:
 data() {
    return {
      activeName: "allLesson",
      courseList:[] //课程集合
    };
  },
 getCourseList(){ //去dubbo服务获取全部课程的数据
    return this.axios.get("http://localhost:8002/course/getAllCourse").then(res => {
      console.log(res)
      this.courseList = res.data; //添加该代码
    }).catch(err =>{
      this.$message.error("获取课程信息失败")
    })
    }

            <li class="course-li" v-for="(item,index) in courseList" :key="index"> 
                
                
                
		 <img
                :src="item.courseImgUrl"
                class="teacher-portrait hover-pointer"
              />


		<div
                    class="p-title"
                    style="text-align:left;"
                    @click="gotoDetail"
                  >
                    <span>
                      {{item.courseName}}
                        
                    span>
                  div>
 
                  <p class="p-title-buy text-overflow">
                    <span class="p-author-span">
                      {{item.teacher.teacherName}}
                    span>
                    <span class="p-author-line" />
                    <span class="p-author-span">
                       {{item.teacher.position}}
                    span>
                  p>
 
                  <p class="p-describe" style="text-align:left;">
                    {{item.brief}}
                  p>
 <span class="content-price-orange-sm">span>
                    <span class="content-price-orange">{{item.discounts}}span> 

                    <span class="current-price">
                      <span class="current-price-unite">span>
                      {{item.price}} 
                    span>
<span class="content-price-buy">{{item.sales}}人购买span>

删掉对应的章节2的li标签,因为我们直接遍历即可
 <ul class="content-course" style="text-align:left;">
                  
                   <li
                    class="content-course-lesson text-overflow"
                    style="width:300px" 
       v-for="(lesson,index) in item.courseSectionList[0].courseLessonList.slice(0,2)" :key="index"
                  >
                       
                      
                    
                    <img
                      src="@/assets/course-list/free-course.png"
                      class="free-label hover-pointer"
                    />
                    <span class="theme-span hover-pointer">
                        {{lesson.theme}} 
                      span>
                  li>
                  
                 
                ul>
现在对应的显示已经完成,现在我们操作登录
找到Header.vue:
//methods里面的  
login(){ //前去登录
      return this.axios.get("http://localhost:8002/user/login",{
        params:{
          phone:this.phone,
          password:this.password
        }
      }).then(res =>{
        
        console.log(res);
        this.userDTO = res.data;
          if(this.userDTO.content!=null){
        this.isLogin = true //更新登录状态,一般写在上面的设置后面,虽然写在前面也可(因为执行速度够快)
        //将登录成功的信息进行保存(本地),使得刷新界面时,可以继续得到信息,基本只与浏览器有关
        localStorage.setItem("user",JSON.stringify(this.userDTO)) //将字符串数据变过去
          }
          //初始化
        this.phone = "";
        this.password="";
      
        this.dialogFormVisible = false; // 不显示登录框
           this.$router.push("/" ); //防止其他界面路径操作时,出现问题,直接跳转到根目录,且刷新
        
          window.location.reload() //进行刷新,使得操作后面的已购,因为在当前相同的路径下
          //并不会有刷新,那么已购也就不会动态的出现了
      }).catch(err =>{
        this.$message.error("登录失败")
      })
    }
created(){
    
    //当刷新页面,组件创建成功之后,立刻检测本地储存中是否存在用户对象
    console.log(JSON.parse(localStorage.getItem("user")));
    //将得到的字符串变成对应的对象,也可以说是JSON对象,使得可以操作,即"对象.key"的获取值
     this.userDTO =JSON.parse(localStorage.getItem("user")); 
     console.log(this.userDTO)
     if( this.userDTO != null){
         this.isLogin = true //更新登录状态,表示已登录
     }
  },
操作完成后,就可以进行登录了,刷新也是一样
登出操作:
  logout(){ //登出
localStorage.setItem("user",null)
 this.isLogin = false
       this.$router.push("/" ); //防止其他界面路径操作时,出现问题,直接跳转到根目录,且刷新
      window.location.reload() //进行刷新,使得操作后面的已购,最好加上(),不加可能不会起作用
 alert("已登出")
    }
回到Index.vue:
 data() {
    return {
      activeName: "allLesson",
      courseList:[], //课程集合
        myCourseList:[], //我购买过的课程列表
      isLogin:false, //登录状态
      user:null //登录的用户对象信息
    };
  },
created() {

this.user = JSON.parse(localStorage.getItem("user"));   
//不为null代表登录了,因为登录了才会设置对应的值,没有登录会设置为null
//而JSON.parse操作null,返回的也是null
if(this.user != null){ 
  this.isLogin = true
     this.getMyCourseList(); //获得自己的课程,也就是购买过的课程
}

    this.getCourseList() //组件使用时,就调用获取课程信息的方法

  

  },
  getMyCourseList(){
      return this.axios.get("http://localhost:8002/course/getCourseByUserId/" + this.user.content.id).then(res =>{
 console.log(res)
      this.myCourseList = res.data;
      }).catch(err => {
 this.$message.error("获取课程信息失败")
      })
    }
<el-tab-pane label="已购" name="hasPay">
          <div v-if="!isLogin">
          <img
            src="@/assets/course-list/[email protected]"
            class="no-data-icon"
          />
          <div class="no-data-title">您还没有登录div>
          <div class="no-data-title">登录后即可查看已购课程div>
          <div class="btn btn-yellow btn-center">立即登录div>
          div>
          <div v-if="isLogin">
            <ul class="course-ul-pc">
            
            <li class="course-li" v-for="(item,index) in myCourseList" :key="index">
              
              <img
                :src="item.courseImgUrl"
                class="teacher-portrait hover-pointer"
              />
              
              <div class="content-main">
                
                <div class="content-title hover-pointer">
                  <div
                    class="p-title"
                    style="text-align:left;"
                    @click="gotoDetail"
                  >
                    <span>
                      {{item.courseName}}
                    span>
                  div>
                  
                  <p class="p-title-buy text-overflow">
                    <span class="p-author-span">
                      {{item.teacher.teacherName}}
                    span>
                    <span class="p-author-line" />
                    <span class="p-author-span">
                       {{item.teacher.position}}
                    span>
                  p>
                  <p>p>
                  
                  <p class="p-describe" style="text-align:left;">
                    {{item.brief}}
                  p>
                div>
                
                <ul class="content-course" style="text-align:left;">
                  
                  <li
                    class="content-course-lesson text-overflow"
                    style="width:300px" 
    v-for="(lesson,index) in item.courseSectionList[0].courseLessonList.slice(0,2)" :key="index"
                  >
                    
                    <img
                       src="@/assets/course-list/[email protected]"
                      class="free-label hover-pointer"
                    />
                    <span class="theme-span hover-pointer">
                      {{lesson.theme}}
                      span>
                  li>
                  
                 
                ul>
                
                <div class="content-price" style="text-align:left;">
                  <p class="content-price-p">
                    <span class="content-price-orange-sm">span>
                    <span class="content-price-orange">{{item.discounts}}span>
                    <span class="current-price">
                      <span class="current-price-unite">span>
                      {{item.price}}
                    span>
                    <span class="activity-name">成就自己span>
                    <span class="content-price-buy">{{item.sales}}人购买span>
                  p>
                  <div class="btn btn-yellow btn-offset">开始学习div> 
                
                div>
              div>
            li>
            
            
          ul>
          div>
        el-tab-pane>
课程的显示已经完成,接下来我们来显示课程里面的信息
  <div
                    class="p-title"
                    style="text-align:left;"
                    @click="gotoDetail(item)"
                  >
                        
gotoDetail(item) {
      this.$router.push({ name: "Course", params: { course: item } });
    },
到Course.vue组件:
 data() {
    return {
      activeName: "intro",
      course:null,
      totalLessons:0, //本门课程的总节数
    };
  },
//没有自然自己写
 created(){
    
this.course = this.$route.params.course //从路由中获得参数对象,赋值给本组件的参数
console.log(1)
console.log(this.course)
let x = 0;
for(let i = 0;i<this.course.courseSectionList.length;i++){
  let section = this.course.courseSectionList[i] //每一章
  for(let j = 0;j<section.courseLessonList.length;j++){
    x++;
  }
}
this.totalLessons = x; //得到对应所有的讲(也就是所有的课时)
  },
  
      <div class="nav-wrap">
        <p class="nav-p-pc" style="margin-top:-25px;text-align:left;">
          <a href="#">课程列表a>
          <span class="sharp-content">>span>
          <span class="nav-sec">{{course.courseName}}span>
        p>
      div>
<img
                      class="course-img"
                      :src="course.courseImgUrl"
                      alt="课程图片"
                    />
<div class="conent-wrap">
                      <div class="name" style="text-align:left;">
                        {{course.courseName}}
                      div>
                      <div class="des text-omit" style="text-align:left;">
                        {{course.brief}}
                      div>
                      <div class="title">
                        <div class="teacher-name text-omit">
                          讲师:{{course.teacher.teacherName}}
                          <span class="line">span>
                          {{course.teacher.position}}
                        div>
                      div>
                      <div class="lesson-info">
                        <div class="boook-icon backgroun-img-set">div>
                        <div class="time">{{totalLessons}}讲 / {{course.totalDuration}}课时div>
                        
                        <div class="person-icon backgroun-img-set">div>
                        <div class="person">{{course.sales}}人已购买div>
                      div>
                    div>
 <el-tab-pane label="课程信息" name="intro">
                   <div v-html="course.courseDescription" class="content-p pc-background">
                      
                    div>
                  el-tab-pane>
.content-p {
  font-size: 0.373rem;
  color: #666;
  letter-spacing: 0;
  text-align: justify;
  line-height: 1.1rem;
}
 <div
      class="class-menu-contaniner list-page-container more-sections more-sections-padding"
                    v-for="(section,index) in course.courseSectionList" :key="index"
                 
                    >
.class-menu-contaniner.list-page-container {
  padding: 0px 15px;
  background: #fff;
}
   <div>
                        <div class="section-name single-line">
                         {{section.sectionName}}
                        div>
                        <div class="class-menu-block">
                          <div
                            class="class-level-one over-ellipsis"
                            @click="watchCourse(1)"
                             v-for="(lesson,index) in section.courseLessonList" :key="index"
                          >
                            <div class="text-wrap">
                              <div class="content">{{lesson.theme}}div>
                              <div
                                class="item-status-wrap item-status-wrap-list"
                              >
                                <div class="item-status test-watch">试看div>
                              div>
                            div>
                          div>
                       
                        div>
                      div>
 <span class="current-price" style="font-size:28px">
            <span class="current-price-unite" style="font-size:.347rem">span
            >{{course.discounts}}
          span>
          <span class="current-price price">
            <span class="current-price-unite">span>
            {{course.price}}
          span>
接下来我们操作留言(任然是Course.vue):
 created(){
    
this.course = this.$route.params.course //从路由中获得参数对象,赋值给本组件的参数
console.log(1)
console.log(this.course)
let x = 0;
for(let i = 0;i<this.course.courseSectionList.length;i++){
  let section = this.course.courseSectionList[i] //每一章
  for(let j = 0;j<section.courseLessonList.length;j++){
    x++;
  }
}
this.totalLessons = x; //得到对应所有的讲(也就是所有的课时)
this.getComment(); //这里是新加的
  },
 data() {
    return {
      activeName: "intro",
      course:null,
      totalLessons:0, //本门课程的总节数
      commentList:null //所有留言
    };
  },
  getComment(){
 return this.axios
     .get("http://localhost:8002/course/comment/getCourseCommentList/"+this.course.id+"/1/20")
     .then(res => {
      console.log(res)
      this.commentList = res.data;
    }).catch(err =>{
      this.$message.error("获取留言信息失败")
    })
    },
 
    <div class="message-list" v-for="(comment , index) in commentList" :key="index">
                        <div class="message-list-title">
                          <div class="message-list-title-left">
                            <div class="message-list-title-left-name">{{comment.userName}}div>
                            <div class="message-list-title-left-tag">div>
                          div>
                         <div @click="cancelzan(comment)"
                              v-if="JSON.stringify(comment.favoriteRecords)
                                    .indexOf( user.content.id ) >= 0" 
                              class="message-list-title-right">
                            <img class="message-list-title-right-icon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADgAAAA4BAMAAABaqCYtAAAAJFBMVEVHcEwAuI4AtIsAtIsAtIoAtYwAtIsAtYwAtowAx5kAtIsAs4qd4c1kAAAAC3RSTlMAGMfz3VGnbTYIhXtDq8EAAAETSURBVDjLldWhb8JAFAbwg8CGhGSGzNQtULNkWUioWbJkpmYKAQaBITPLLKZysmLz+xfolUL6/XM72msh9N2X8ImaX17vrq+vVeqU39XTuK/kdEMA01jGDY4ZyYWFIRPxp0S8u+8KeBJ+WDxIGFrMJbQm7qhVYSJgr8JUwNsKtYDtCiHgPavcsDVDstsuyDk7NeYDk6G8pM3bWXNawQUijWq8QyPPpQy+50ET9bF09go5pus3cMV0feFEc2DfieZRBU7Up7fjSkwZZgz3DA8MHxl6DP8YRgxjgokimDHcMdwyfGG4ZPjJMCKoY4KJIpgz3DHcMvQYFuPpk/005t1mffHlOs/ETvxXAA0Ul3oQHsp/xD93wxfHcC4VkwAAAABJRU5ErkJggg==" alt="">
                            <div class="message-list-title-right-praise">{{comment.likeCount}}div>
                          div>
                          
                          <div @click="zan(comment)" v-else class="message-list-title-right">
                            <img class="message-list-title-right-icon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADgAAAA4BAMAAABaqCYtAAAAKlBMVEVHcExnZ2dzc3NmZmZqampmZmZmZmZnZ2dnZ2dnZ2dmZmZoaGhmZmZmZmZl+8SAAAAADXRSTlMA/AbsFtilbj5YwSqJPyESoQAAAZxJREFUOMt1lTtLA1EQha8xRhPTBEmhuKCCoNgoIlYLMcRKBG0sxIUgCDaBSDohEO0FEbQyIBZaBazERvAPWCwxPnP+i3tnrlGTmVPswn73NXNm7hrzq9m9kZ2ckTUUABifkOEBrK7liR7BMRFOA/uFc+BUgnV8mFisEW5IsIFi9FzBuwR91KJnAm8S9EIbxSBeBRZHk86MrBQJWjymJUC3nlugSyk+SQyhANfxos+s4krfM0DZvmbw2cuSCHNGi3PAfUygXYiU79ryyw1ibf0xZ9intBsz6SBadx24iiZXz8kPxCiTtYdLPzKTVFkkLQAZO/VikwYW/x/wHohcT/MiPQE8W9frxJrlbpiw4xvA0vbNmWyhj2Nrhmy+B7nEyTsN0rIaJAc0SDWqwX7rhAYfMa/Dui0bDZbwZAwUGNjWUWActnUUyN2hwDTaOkxRaSiwj6pRhjHKgTazSkWlwBK1jgIpBwrkHCgwyZ0oQ86BAjkHCjziG0KE8YBvCA/5KacOm6sgrHFAotouT6J23bkkLbsNDjM9yt7yP+IbQYga5De+eBMAAAAASUVORK5CYII=" alt="">
                            <div class="message-list-title-right-praise">{{comment.likeCount}}div>
                          div>
                        div>
                        <div class="message-list-content">
                          {{comment.comment}}
                        div>
                      
                      
                      div>
                      
在这之前,我们需要讲样式进行改变,删除原来的样式,复制如下地址的样式进行使用
链接:https://pan.baidu.com/s/16u-vPVF_tmokXNOKzZUjxQ
提取码:alsk
接下来我们了操作试看的状态:
任然是Course.vue:
  data() {
    return {
      activeName: "intro",
      course:null,
      totalLessons:0, //本门课程的总节数
      commentList:null, //所有留言
      isLogin:false, //false,未登录
      isBuy:false,//未购买
      user:null, //当前用户,可以","结尾
      myCourseList:[], //当前用户购买过的所有课程
    };
  },
created(){
    
this.course = this.$route.params.course //从路由中获得参数对象,赋值给本组件的参数
  if(this.course==null){ //防止自己刷新或者其他页面跳转出现错误,因为这时候的this.course是undefined
  //undefined==null返回的是true,因为他们操作==时,一般会变成false
      //因为只会比较这时候在判断的值(可以说看成了false)
//若要进行完全比较,则需要===,那么返回false
  this.$router.push("/"); //回到首页
}
//检测是否登录
this.user = JSON.parse(localStorage.getItem("user"))
if(this.user != null){
  this.isLogin = true //已登陆
  if(this.course!=null){  //防止出现没有值(这里是undefined),导致axios中then错误,那么catch也会错误
  this.getMyCourseList() //查询登录用户购买的所有课程
}
}

console.log(1)
console.log(this.course)
let x = 0;
for(let i = 0;i<this.course.courseSectionList.length;i++){
  let section = this.course.courseSectionList[i] //每一章
  for(let j = 0;j<section.courseLessonList.length;j++){
    x++;
  }
}
this.totalLessons = x; //得到对应所有的讲(也就是所有的课时)
this.getComment();
  },
getMyCourseList(){  查询登录用户购买的所有课程
  return this.axios.get("http://localhost:8002/course/getCourseByUserId/" + 
                        this.user.content.id).then(res =>{
 console.log(res)
      this.myCourseList = res.data;

    //检测当前的课程是否购买过
    for(let i = 0;i<this.myCourseList.length;i++){
      if(this.myCourseList[i].id == this.course.id){
        this.isBuy = true //这样就代表购买过该课程,自然其中的课程(如章节的课时的视频)都可以进行播放
        break;
      }
    }

      }).catch(err => {
 this.$message.error("获取课程信息失败")
      })
    },
   <div
                                class="item-status-wrap item-status-wrap-list"
                              >
                              
                              <div v-if="index<2">
                                
                                <div class="item-status test-watch" v-if="!isLogin">试看div>
                                
                         <div class="item-status test-watch" v-else-if="isLogin && !isBuy">试看div>
                                
                                <div class="item-status test-watch"  v-else>播放div>
                              div>
                              
                                
                                <div v-if="index>1"> 
                                
                                <div class="item-status lock" v-if="!isLogin">div>
                                
                                <div class="item-status lock" v-else-if="isLogin && !isBuy">div>
                                
                                <div class="item-status test-watch"  v-else>播放div>
                              div>
                              div>
修改对应的html(注意找到具体位置):
   <div
         class="class-menu-contaniner list-page-container more-sections more-sections-padding"
                   
                 
                    >
                    
          <div  v-for="(section,index) in course.courseSectionList.slice(0,1)" :key="index">
                        <div class="section-name single-line">
                         {{section.sectionName}}
                        div>
                        <div class="class-menu-block">
                          <div
                            class="class-level-one over-ellipsis"
                            @click="watchCourse(1,index,lesson.courseMedia,lesson.id)"
                             v-for="(lesson,index) in section.courseLessonList" :key="index"
                          >
                            <div class="text-wrap">
                              <div class="content">{{lesson.theme}}div>
                              <div
                                class="item-status-wrap item-status-wrap-list"
                              >
                              
                              <div v-if="index<2">
                                
                                <div class="item-status test-watch" v-if="!isLogin">试看div>
                                
                       <div class="item-status test-watch" v-else-if="isLogin && !isBuy">试看div>
                                
                                <div class="item-status test-watch"  v-else>播放div>
                              div>
                              
                                
                                <div v-if="index>1"> 
                                
                                <div class="item-status lock" v-if="!isLogin">div>
                                
                                <div class="item-status lock" v-else-if="isLogin && !isBuy">div>
                                
                                <div class="item-status test-watch"  v-else>播放div>
                              div>
                              div>
                            div>
                          div>
                       
                        div>
                      div>
                       

                        
<div  v-for="(section,index) in course.courseSectionList.slice(1,course.courseSectionList.length)" 
     :key="index">
                        <div class="section-name single-line">
                         {{section.sectionName}}
                        div>
                        <div class="class-menu-block">
                          <div
                            class="class-level-one over-ellipsis"
                            @click="watchCourse(2,index,lesson.courseMedia,lesson.id)"
                             v-for="(lesson,index) in section.courseLessonList" :key="index"
                          >
                            <div class="text-wrap">
                              <div class="content">{{lesson.theme}}div>
                              <div
                                class="item-status-wrap item-status-wrap-list"
                              >
                                                 
                                
                                <div class="item-status lock" v-if="!isLogin">div>
                                
                                <div class="item-status lock" v-else-if="isLogin && !isBuy">div>
                                
                                <div class="item-status test-watch"  v-else>播放div>
                           
                              div>
                            div>
                          div>
                       
                        div>
                      div>
                      
                      
                      div>
操作播放(任然是Course.vue):
//前面的
//watchCourse(1,index,lesson.courseMedia,lesson.id)
//watchCourse(2,index,lesson.courseMedia,lesson.id)
//已经写好了

   //播放视频
    //参数1:代表是否是第一章(1表示是第一章,2表示其他章)
    //参数2:对应的下标,也就是index的值,比如可以知道是否是前两节(对第一章来说)
    //参数3:代表视频地址
    watchCourse(status,index,courseMedia,lessonid) { 
//判断对应的视频是否有值
if(courseMedia == null){
  this.$message.error("播放失败,暂无视频")
}else{
 
    //试看的可以跳转播放页面,这里判断第一章的前两节,其余的没有试看
    //之所以可以这样一起判断,是因为这里是总数据status,index,courseMedia
    //直接操作课时的数据,而不是章节
    if(status == 1 && index<2){
this.$message.success("观看第【" + lessonid + "】节课程视频!" + courseMedia.fileEdk);
//lessonid代表课时对应的编号,一般也当成第几节,虽然可能在数据库里并不是从最小开始
//所以若为了好的正确观看,就可以不用lessonid而用index+1了,但是不好查看是哪个视频
  this.$router.push({
        name: "videoDetail",
        params: { course: this.course,lessonid: lessonid },
      });
        //params: { course: this.course,lessonid: lessonid ,a: courseMedia.fileEdk},
    }else{
    //锁上的先验证是否登录
    if(!this.isLogin){
      this.$message.success("请先登录")
    }else{
      //登录的,再验证是否购买过
      if(!this.isBuy){
this.$message.warning("请先购买后,进行解锁")
      }else{
        this.$message.success("观看第【" + lessonid + "】节课程视频!"+ courseMedia.fileEdk);
         this.$router.push({
        name: "videoDetail",
          params: { course: this.course,lessonid: lessonid },
      });
          //params: { course: this.course,lessonid: lessonid ,a: courseMedia.fileEdk},
      }

    }}
}

  
    },
接下来我们操作播放执行:
到videoDetail.vue
 data() {
    return {
      myvideo: null, // 播放器对象
      isplay: false, //是否在播放
      nowTime: "00:00", //当前播放时间
      totalTime: "00:00", //总时长
      course:null, //课程
      lessonid:0, //当前播放视频的课时id
        lessonName:null,//当前播放的视频名称
      //a:null
    };
  },
 created() {
    //从路由中得到对应的课程和课时id
    this.course = this.$route.params.course;
    this.lessonid = this.$route.params.lessonid
    //this.a=this.$route.params.a
  },
mounted() {
    this.myvideo = document.getElementById("myvideo");
    this.initplay() //初始化播放的视频,即当我到达这个页面,要播放的是对应的那个视频,基本不会是其他的视频
  },
 //初始化时播放的视频
    initplay(){
        //在课程信息中查找即将播放的小节视频的编号
      for(let i = 0 ;i<this.course.courseSectionList.length;i++){
        let section = this.course.courseSectionList[i]
        for(let j = 0;j<section.courseLessonList.length;j++){
          let lesson = section.courseLessonList[j]
          if(lesson.courseMedia!=null){
              if(this.lessonid==lesson.courseMedia.lessonId){
                  this.lessonName = lesson.theme
            console.log("视频地址:" + lesson.courseMedia.fileEdk)
            //将小节视频的地址赋值给播放器进行播放
            this.myvideo.src = lesson.courseMedia.fileEdk
            return;
            }
          }
        }
      }
       
      //上面的确可以进行操作,但实际上我们并不需要这么麻烦
      //因为在跳转到这个路由之前,我们就已经有对应的地址参数了,即并不需要进行循环判断使得相同id得到地址参数
        //因为之前就是同一个lesson
      //this.myvideo.src = this.a
        //但可能点击其他视频时,需要循环,所以为了后面的会出现的问题出发,加上循环并没有坏处
        //当然好像并没有什么作用
        
    },
至此我们进行点击试看或者播放,点击视频中间进行播放,发现视频的确进行播放,那么操作成功
在这之前,也可以点击地址看看是否可以播放
接下来操作播放的页面:
<span style="position:absolute;left:80px;">
            {{course.courseName}} > {{lessonName}}</span
          >
 <span class="progress-label">--span>
 data() {
    return {
      myvideo: null, // 播放器对象
      isplay: false, //是否在播放
      nowTime: "00:00", //当前播放时间
      totalTime: "00:00", //总时长
      course:null, //课程
      lessonid:0, //当前播放视频的课时id
      lessonName:null,//当前播放的视频名称
       isLogin:false, //false,未登录
      isBuy:false,//未购买
      //a:null
    };
  },
我们从Course.vue里修改对应的如下代码:
//有两个
this.$router.push({
        name: "videoDetail",
        params: { course: this.course,lessonid: lessonid,isBuy:this.isBuy},
      });
回到videoDetail.vue:
created() {

//检测是否登录
this.user = JSON.parse(localStorage.getItem("user"))
if(this.user != null){
  this.isLogin = true //已登陆
  console.log(1)
}

    //从路由中得到对应的课程和课时id
    this.course = this.$route.params.course;
    this.lessonid = this.$route.params.lessonid
    this.isBuy = this.$route.params.isBuy
  },
   <div class="content-container">
              
              <div v-for="(section,index) in course.courseSectionList.slice(0,1)" :key="index">
                
                <div class="content-label">
                  <div class="content-label-title single-line">{{section.sectionName}}div>
                  <img
                    class="arrow-icon"
                    src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkBAMAAAATLoWrAAAAGFBMVEVHcEz///8dS1W+AAAAB3RSTlMAgwWyMeGgBsFrrQAAAFVJREFUKM9jYBiugMUBQ0i8EF2EsbxcAF1ReXkhuqJiczRl4uVGyqjKgIoUmFCVARUxMKAoAyliYEBRBlaEqiwcpAikrBShKglCqyFUMcEYCgwjBAAAeaoQrHtg6QoAAAAASUVORK5CYII="
                    alt=""
                  />
                div>


                
                <div class="content-sections">
                  
      
                  <div :class="{
                    'content-section':lesson.id != lessonid,
                  'content-section content-section-choose':lesson.id == lessonid
                  }" 
                  v-for="(lesson,index) in section.courseLessonList" :key="index">
                  
                    
                    
                    <div v-if="index<2">
                    <div class="section-item clearfix">
                       
                      <span :class="{
                    'kw-icon-video section-type-icon':lesson.id != lessonid,
                  'kw-icon-video section-type-icon lv':lesson.id == lessonid
                  }"
                        ><i class="el-icon-video-play">i
                      >span>
                       
                       <span :class="{
                    'section-dec':lesson.id != lessonid,
                  'section-dec  lv':lesson.id == lessonid
                  }">
                     {{lesson.theme}}span>
                      
                      <div v-if="lesson.id != lessonid">
                    
                      <span v-if="!isLogin" class="section-status-icon pause-play">试看span>
                        
       <span v-else-if="isLogin && !isBuy" class="section-status-icon pause-play">试看span>
                        
                          <span v-else class="section-status-icon pause-play">播放span>
                      div>
                       <div v-if="lesson.id == lessonid">
                    
                      <span v-if="!isLogin" class="section-status-icon pause-play">span>
                        
       <span v-else-if="isLogin && !isBuy" class="section-status-icon pause-play">span>
                        
                          <span v-else class="section-status-icon pause-play">span>
                      div>
                    div>
                    <div class="section-duration">
   <span v-if="lesson.courseMedia != null">时长:{{lesson.courseMedia.duration}}span>
                            <span v-else>时长:无媒体文件span>
                    div>
                    div>

            
              <div v-if="index>1">
                    <div class="section-item clearfix">
                      <span :class="{
                    'kw-icon-video section-type-icon':lesson.id != lessonid,
                  'kw-icon-video section-type-icon lv':lesson.id == lessonid
                  }"
                        ><i class="el-icon-video-play">i
                      >span>
                      <span :class="{
                    'section-dec':lesson.id != lessonid,
                  'section-dec  lv':lesson.id == lessonid
                  }">{{lesson.theme}}span>
                        
                      <span v-if="!isLogin" class="section-status-icon pause-play">未解锁span>
                        
        <span v-else-if="isLogin && !isBuy" class="section-status-icon pause-play">未解锁span>
                        
       <span v-else-if="lesson.id != lessonid" class="section-status-icon pause-play">播放span>
                          <span v-else class="section-status-icon pause-play">span>
                    div>
                    <div class="section-duration">
         <span v-if="lesson.courseMedia != null">时长:{{lesson.courseMedia.duration}}span>
                            <span v-else>时长:无媒体文件span>
                    div>
                    div>


                  div>
                div>
              div>
              
                
<div v-for="(section,index) in course.courseSectionList.slice(1,course.courseSectionList.length)" 
     :key="index">
                
                <div class="content-label">
                  <div class="content-label-title single-line">{{section.sectionName}}div>
                  <img
                    class="arrow-icon"
                    src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkBAMAAAATLoWrAAAAGFBMVEVHcEz///8dS1W+AAAAB3RSTlMAgwWyMeGgBsFrrQAAAFVJREFUKM9jYBiugMUBQ0i8EF2EsbxcAF1ReXkhuqJiczRl4uVGyqjKgIoUmFCVARUxMKAoAyliYEBRBlaEqiwcpAikrBShKglCqyFUMcEYCgwjBAAAeaoQrHtg6QoAAAAASUVORK5CYII="
                    alt=""
                  />
                div>

                <div class="content-sections">
                  
                
                     <div :class="{
                    'content-section':lesson.id != lessonid,
                  'content-section content-section-choose':lesson.id == lessonid
                  }" 
                  v-for="(lesson,index) in section.courseLessonList" :key="index">
                  <div>
        
                    <div class="section-item clearfix">
                       <span :class="{
                    'kw-icon-video section-type-icon':lesson.id != lessonid,
                  'kw-icon-video section-type-icon lv':lesson.id == lessonid
                  }"
                        ><i class="el-icon-video-play">i
                      >span>
                      <span :class="{
                    'section-dec':lesson.id != lessonid,
                  'section-dec  lv':lesson.id == lessonid
                  }">{{lesson.theme}}span>
                        
                      <span v-if="!isLogin" class="section-status-icon pause-play">未解锁span>
                        
      <span v-else-if="isLogin && !isBuy" class="section-status-icon pause-play">未解锁span>
                        
                    
        <span v-else-if="lesson.id != lessonid" class="section-status-icon pause-play">播放span>
                          <span v-else class="section-status-icon pause-play">span>
                    div>
                    <div class="section-duration">
          <span v-if="lesson.courseMedia != null">时长:{{lesson.courseMedia.duration}}span>
                            <span v-else>时长:无媒体文件span>
                    div>

                  div>

                  div>
                div>
              div>
              
            div>
对应的样式地址,记得进行替换(是videoDetail.vue组件):
链接:https://pan.baidu.com/s/1AD141qyMnHyv3veJ06kwJw
提取码:alsk
至此对应的状态也操作完毕,自己运行看看吧
接下来操作点击跳转视频:
任然是videoDetail.vue组件
//所以章里面的的都加上@click="playlesson"进行操作(无论是第一章还是其他章),进行视频的切换
  <div :class="{
                    'content-section':lesson.id != lessonid,
                  'content-section content-section-choose':lesson.id == lessonid
                  }" 
                  v-for="(lesson,index) in section.courseLessonList" :key="index"
                  @click="playLesson(lesson)"
                  >
 //播放课程
    playLesson(lesson) {
      //将对应的播放视频变成我点击的视频
      this.lessonid = lesson.id; //修改对应的id,一般用来操作前面的样式
      this.myvideo.src = lesson.courseMedia.fileEdk //将地址进行改变,使得视频也改变
      //这里并不需要循环,就如循环里说的,使用现成的即可

    },
至此可以进行视频的切换了,虽然对应的按钮操作是特殊的,一般只能点击视频进行视频的观看
但是在观看切换时,可以点击按钮进行观看,而使得不会变化
这实际上并不是好的视频组件,因为并不是完全的根据按钮状态来执行,但这也并不需要操作,因为能看即可
实际上是因为每次的操作,都会进行取反(对应的播放,而切换时,并不会,所以使得出现上面的情况)
为了解决这样的问题,需要加上如下代码:
 //播放课程
    playLesson(lesson) {
      //将对应的播放视频变成我点击的视频
      this.lessonid = lesson.id; //修改对应的id,一般用来操作前面的样式
      this.myvideo.src = lesson.courseMedia.fileEdk //将地址进行改变,使得视频也改变
      //这里并不需要循环,就如循环里说的,使用现成的即可
      this.myvideo.play();
      this.isplay = true //呈现播放状态
        //使得重置为执行视频(只是对应的状态,即显示样式的确定),因为上面的就是需要执行视频
        //这一就可以操作了,具体可以看对应的代码
        

    },
对应的我们的显示控制面板可能是有问题的(位置与点击不同,如播放按钮)
若不使用这个面板,可以使得自带的控制面板,代码如下:
 mounted() {
    this.myvideo = document.getElementById("myvideo");
    this.myvideo.controls = true //显示对应的控制面板
    this.initplay() //初始化播放的视频,即当我到达这个页面,要播放的是对应的那个视频,基本不会是其他的视频
  },
接下来删除对应的面板:
找到对应的div,其他的代码删除掉即可,这一就使用对应的控制面板了(video自带的),而不是使用我们自己操作的
 <div
     id="player-video-vontainer"
        class="player-container video-container"
   >
              
                <video
                  style="width: 100%; height: 100%;"
                  id="myvideo"
  src="https://video.pearvideo.com/mp4/adshort/20200901/cont-1693694-15359233_adpkg-ad_hd.mp4"
                  @canplay="getInit"
                  @timeupdate="handlerNowTime"
      />
               
     div>
可能对应的视频是没有的,所以需要判断:
 //播放课程
    playLesson(lesson) {
      if(lesson.courseMedia!=null){ //只要没有对应的视频,那么就不会有任何操作,并给出提示
          //之所以还需要判断,是因为虽然从课程那里过来时,不可点击
          //但可以点击其他的进入,所以需要判断,除非你进行验证删除,但是这时非常麻烦的
          //所以基本不做考虑,且不符合实际(因为我已经买了课,需要显示出来)
      //将对应的播放视频变成我点击的视频
      this.lessonid = lesson.id; //修改对应的id,一般用来操作前面的样式
      
      this.myvideo.src = lesson.courseMedia.fileEdk //将地址进行改变,使得视频也改变
      //这里并不需要循环,就如循环里说的,使用现成的即可
      this.myvideo.play();
      this.isplay = true
      }else{
        this.$message.warning("没有该视频")
    
      }
    },
但是虽然我们显示了状态,但是也要进行判断,使得对应状态真实起作用,代码如下:
//先修改对应的方法
//第一章的@click="playLesson(1,index,lesson)"
//第二章的@click="playLesson(2,index,lesson)"
最终的修改:
   //播放课程
    playLesson(status,index,lesson) {
      if(lesson.courseMedia!=null){

  //试看的可以跳转播放页面
  if(status == 1 && index<2){

      //将对应的播放视频变成我点击的视频
      this.lessonid = lesson.id; //修改对应的id,一般用来操作前面的样式
      
      this.myvideo.src = lesson.courseMedia.fileEdk //将地址进行改变,使得视频也改变
      //这里并不需要循环,就如循环里说的,使用现成的即可
      this.myvideo.play();
      this.isplay = true
  }else{
    //锁上的先验证是否登录
    if(!this.isLogin){
      this.$message.success("请先登录")
    }else{
      //登录的,再验证是否购买过
      if(!this.isBuy){
        this.$message.warning("请先购买后,进行解锁")
      }else{
         //将对应的播放视频变成我点击的视频
      this.lessonid = lesson.id; //修改对应的id,一般用来操作前面的样式
      
      this.myvideo.src = lesson.courseMedia.fileEdk //将地址进行改变,使得视频也改变
      //这里并不需要循环,就如循环里说的,使用现成的即可
      this.myvideo.play();
      this.isplay = true
          //可以将这个else里面的代码用一个方法包括起来,也可以不用,看你自己如何操作
      }
  }
  }
      }else{
        this.$message.error("播放失败,暂无视频")
    
      }
    },
至此播放的操作基本全部编写完毕
接下来我们继续操作留言:
但在这之前,我们需要操作一下后端
因为虽然前面编写后端时,操作了点赞以及点赞总数的操作,但并不能知道对应的赞是谁点的,所以我们需要联查
新增对应的entity项目的entity包下的类:
package com.lagou.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.Date;
import java.io.Serializable;

/**
 * 课程留言点赞表(CourseCommentFavoriteRecord)实体类
 *
 * @author makejava
 * @since 2022-07-23 20:26:35
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class CourseCommentFavoriteRecord implements Serializable {
    private static final long serialVersionUID = 159062001487532233L;
    /**
     * 用户评论点赞j记录ID
     */
    private Integer id;
    /**
     * 用户ID
     */
    private Integer userId;
    /**
     * 用户评论ID
     */
    private Integer commentId;
    /**
     * 是否删除,0:未删除(已赞),1:已删除(取消赞状态)
     */
    private Integer isDel;
    /**
     * 创建时间
     */
    private Date createTime;
    /**
     * 更新时间
     */
    private Date updateTime;

}
修改对应的CourseComment类:
package com.lagou.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.Date;
import java.io.Serializable;

/**
 * 课程留言表(CourseComment)实体类
 *
 * @author makejava
 * @since 2022-07-15 19:48:04
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class CourseComment implements Serializable {
    private static final long serialVersionUID = -11641570368573216L;
    
     //一条留言对应多个点赞
    private List<CourseCommentFavoriteRecord> favoriteRecords;
    
    /**
     * 主键
     */
    private Object id;
    /**
     * 课程id
     */
    private Integer courseId;
    /**
     * 章节id
     */
    private Integer sectionId;
    /**
     * 课时id
     */
    private Integer lessonId;
    /**
     * 用户id
     */
    private Integer userId;
    /**
     * 运营设置用户昵称
     */
    private String userName;
    /**
     * 父级评论id
     */
    private Integer parentId;
    /**
     * 是否置顶:0不置顶,1置顶
     */
    private Integer isTop;
    /**
     * 评论
     */
    private String comment;
    /**
     * 点赞数
     */
    private Integer likeCount;
    /**
     * 是否回复留言:0普通留言,1回复留言
     */
    private Integer isReply;
    /**
     * 留言类型:0用户留言,1讲师留言,2运营马甲 3讲师回复 4小编回复 5官方客服回复
     */
    private Integer type;
    /**
     * 留言状态:0待审核,1审核通过,2审核不通过,3已删除
     */
    private Integer status;
    /**
     * 创建时间
     */
    private Date createTime;
    /**
     * 更新时间
     */
    private Date updateTime;
    /**
     * 是否删除
     */
    private Integer isDel;
    /**
     * 最后操作者id
     */
    private Integer lastOperator;
    /**
     * 是否发送了通知,1表示未发出,0表示已发出
     */
    private Integer isNotify;
    /**
     * 标记归属
     */
    private Integer markBelong;
    /**
     * 回复状态 0 未回复 1 已回复
     */
    private Integer replied;


}


修改对应的dao层项目的接口(CourseCommentDao)对应的配置文件:

    <resultMap type="com.lagou.entity.CourseComment" id="CourseCommentMap">
        <result property="id" column="id"/>
        <result property="courseId" column="course_id"/>
        <result property="sectionId" column="section_id"/>
        <result property="lessonId" column="lesson_id"/>
        <result property="userId" column="user_id"/>
        <result property="userName" column="user_name"/>
        <result property="parentId" column="parent_id"/>
        <result property="isTop" column="is_top"/>
        <result property="comment" column="comment"/>
        <result property="likeCount" column="like_count"/>
        <result property="isReply" column="is_reply"/>
        <result property="type" column="type"/>
        <result property="status" column="status"/>
        <result property="createTime" column="create_time"/>
        <result property="updateTime" column="update_time"/>
        <result property="isDel" column="is_del"/>
        <result property="lastOperator" column="last_operator"/>
        <result property="isNotify" column="is_notify"/>
        <result property="markBelong" column="mark_belong"/>
        <result property="replied" column="replied"/>

         <collection property="favoriteRecords" 
                     ofType="com.lagou.entity.CourseCommentFavoriteRecord">
            <result property="id" column="ccfr_id"/>
            <result property="userId" column="ccfr_user_id"/>
            <result property="commentId" column="comment_id"/>
            <result property="isDel" column="ccfr_is_del"/>
            <result property="createTime" column="ccfr_create_time"/>
            <result property="updateTime" column="ccfr_update_time"/>
        collection>
    resultMap>

  <select id="getCommentsByCourseId" resultMap="CourseCommentMap">
      
        SELECT
            cc.*,
            ccfr.id ccfr_id,ccfr.user_id ccfr_user_id,comment_id,
       ccfr.is_del ccfr_is_del,ccfr.create_time ccfr_create_time,
       ccfr.update_time ccfr_update_time
        FROM course_comment cc LEFT JOIN course_comment_favorite_record ccfr 
       ON cc.id = ccfr.`comment_id`
        WHERE cc.is_del = 0
          AND course_id = #{courseId}
        ORDER BY is_top DESC,like_count DESC,cc.create_time DESC
            LIMIT #{offset},#{pagesize}
    select>


添加对应dao层项目的TestCourse类里添加测试方法:
   @Test
    public void getCoument(){
        List<CourseComment> commentsByCourseId = courseCommentDao.getCommentsByCourseId(1, 0, 20);
        System.out.println(commentsByCourseId);
        for(CourseComment courseComment: commentsByCourseId ){
            System.out.println("\n"+courseComment.getUserName() +"=>留言:" + 
                               courseComment.getComment());
            for(CourseCommentFavoriteRecord favoriteRecord : courseComment.getFavoriteRecords()){
                System.out.println("-------------->" + favoriteRecord.getUserId() + "点过赞");
            }
        }
    }
进行测试,查看是否有对应的点赞数据,若有,且对应,那么操作完成
接下来我们操作赞:
回到Course.vue:
 <div class="message-list-title">
                          <div class="message-list-title-left">
                            <div class="message-list-title-left-name">{{comment.userName}}div>
                            <div class="message-list-title-left-tag">div>
                          div>
                          
                        
                         
     <div v-if='JSON.stringify(comment.favoriteRecords).indexOf("\"userId\":"+user.content.id) >=0 
                && JSON.stringify(comment.favoriteRecords).indexOf("\"isDel\":0") >=0  ' 
          class="message-list-title-right">
                          
                            <img class="message-list-title-right-icon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADgAAAA4BAMAAABaqCYtAAAAJFBMVEVHcEwAuI4AtIsAtIsAtIoAtYwAtIsAtYwAtowAx5kAtIsAs4qd4c1kAAAAC3RSTlMAGMfz3VGnbTYIhXtDq8EAAAETSURBVDjLldWhb8JAFAbwg8CGhGSGzNQtULNkWUioWbJkpmYKAQaBITPLLKZysmLz+xfolUL6/XM72msh9N2X8ImaX17vrq+vVeqU39XTuK/kdEMA01jGDY4ZyYWFIRPxp0S8u+8KeBJ+WDxIGFrMJbQm7qhVYSJgr8JUwNsKtYDtCiHgPavcsDVDstsuyDk7NeYDk6G8pM3bWXNawQUijWq8QyPPpQy+50ET9bF09go5pus3cMV0feFEc2DfieZRBU7Up7fjSkwZZgz3DA8MHxl6DP8YRgxjgokimDHcMdwyfGG4ZPjJMCKoY4KJIpgz3DHcMvQYFuPpk/005t1mffHlOs/ETvxXAA0Ul3oQHsp/xD93wxfHcC4VkwAAAABJRU5ErkJggg==" alt="">
                            <div class="message-list-title-right-praise">{{comment.likeCount}}div>
                          div>
                          
        <div v-else class="message-list-title-right">
                            <img class="message-list-title-right-icon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADgAAAA4BAMAAABaqCYtAAAAKlBMVEVHcExnZ2dzc3NmZmZqampmZmZmZmZnZ2dnZ2dnZ2dmZmZoaGhmZmZmZmZl+8SAAAAADXRSTlMA/AbsFtilbj5YwSqJPyESoQAAAZxJREFUOMt1lTtLA1EQha8xRhPTBEmhuKCCoNgoIlYLMcRKBG0sxIUgCDaBSDohEO0FEbQyIBZaBazERvAPWCwxPnP+i3tnrlGTmVPswn73NXNm7hrzq9m9kZ2ckTUUABifkOEBrK7liR7BMRFOA/uFc+BUgnV8mFisEW5IsIFi9FzBuwR91KJnAm8S9EIbxSBeBRZHk86MrBQJWjymJUC3nlugSyk+SQyhANfxos+s4krfM0DZvmbw2cuSCHNGi3PAfUygXYiU79ryyw1ibf0xZ9intBsz6SBadx24iiZXz8kPxCiTtYdLPzKTVFkkLQAZO/VikwYW/x/wHohcT/MiPQE8W9frxJrlbpiw4xvA0vbNmWyhj2Nrhmy+B7nEyTsN0rIaJAc0SDWqwX7rhAYfMa/Dui0bDZbwZAwUGNjWUWActnUUyN2hwDTaOkxRaSiwj6pRhjHKgTazSkWlwBK1jgIpBwrkHCgwyZ0oQ86BAjkHCjziG0KE8YBvCA/5KacOm6sgrHFAotouT6J23bkkLbsNDjM9yt7yP+IbQYga5De+eBMAAAAASUVORK5CYII=" alt="">
                            <div class="message-list-title-right-praise">{{comment.likeCount}}div>
                          div>
                        div>
至此通过对应的关联查询,就解决了对应的用户是否点赞的问题
接下来进行点赞和取消赞的操作:
 <div @click="zan(comment,$event)"
      v-if='JSON.stringify(comment.favoriteRecords).indexOf("\"userId\":"+user.content.id) >=0 
                && JSON.stringify(comment.favoriteRecords).indexOf("\"isDel\":0") >=0  ' 
          class="message-list-title-right">
 <div @click="zan(comment,$event)" v-else class="message-list-title-right">
 //取消赞和点赞一起的操作(取反)
    zan(comment,th){ 

let a = th.currentTarget.childNodes[0]
for(let i =0;i<comment.favoriteRecords.length;i++){
  let o = comment.favoriteRecords[i];
  if(o.userId == this.user.content.id && o.isDel == 0){

a.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADgAAAA4BAMAAABaqCYtAAAAKlBMVEVHcExnZ2dzc3NmZmZqampmZmZmZmZnZ2dnZ2dnZ2dmZmZoaGhmZmZmZmZl+8SAAAAADXRSTlMA/AbsFtilbj5YwSqJPyESoQAAAZxJREFUOMt1lTtLA1EQha8xRhPTBEmhuKCCoNgoIlYLMcRKBG0sxIUgCDaBSDohEO0FEbQyIBZaBazERvAPWCwxPnP+i3tnrlGTmVPswn73NXNm7hrzq9m9kZ2ckTUUABifkOEBrK7liR7BMRFOA/uFc+BUgnV8mFisEW5IsIFi9FzBuwR91KJnAm8S9EIbxSBeBRZHk86MrBQJWjymJUC3nlugSyk+SQyhANfxos+s4krfM0DZvmbw2cuSCHNGi3PAfUygXYiU79ryyw1ibf0xZ9intBsz6SBadx24iiZXz8kPxCiTtYdLPzKTVFkkLQAZO/VikwYW/x/wHohcT/MiPQE8W9frxJrlbpiw4xvA0vbNmWyhj2Nrhmy+B7nEyTsN0rIaJAc0SDWqwX7rhAYfMa/Dui0bDZbwZAwUGNjWUWActnUUyN2hwDTaOkxRaSiwj6pRhjHKgTazSkWlwBK1jgIpBwrkHCgwyZ0oQ86BAjkHCjziG0KE8YBvCA/5KacOm6sgrHFAotouT6J23bkkLbsNDjM9yt7yP+IbQYga5De+eBMAAAAASUVORK5CYII="
   break;
  }else{

    a.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADgAAAA4BAMAAABaqCYtAAAAJFBMVEVHcEwAuI4AtIsAtIsAtIoAtYwAtIsAtYwAtowAx5kAtIsAs4qd4c1kAAAAC3RSTlMAGMfz3VGnbTYIhXtDq8EAAAETSURBVDjLldWhb8JAFAbwg8CGhGSGzNQtULNkWUioWbJkpmYKAQaBITPLLKZysmLz+xfolUL6/XM72msh9N2X8ImaX17vrq+vVeqU39XTuK/kdEMA01jGDY4ZyYWFIRPxp0S8u+8KeBJ+WDxIGFrMJbQm7qhVYSJgr8JUwNsKtYDtCiHgPavcsDVDstsuyDk7NeYDk6G8pM3bWXNawQUijWq8QyPPpQy+50ET9bF09go5pus3cMV0feFEc2DfieZRBU7Up7fjSkwZZgz3DA8MHxl6DP8YRgxjgokimDHcMdwyfGG4ZPjJMCKoY4KJIpgz3DHcMvQYFuPpk/005t1mffHlOs/ETvxXAA0Ul3oQHsp/xD93wxfHcC4VkwAAAABJRU5ErkJggg=="
  }
 
}
        
        //前面在标签里的判断是为了初始化的显示,这里是为了点击赞或者取消赞时
        //进一步进行解决,因为初始化的判断后面的isDel是代表全部
        //实际上可以通过修改sql语句来进行改变,那样就更加方便了

        //alert("赞和取消赞")
         return this.axios.get("http://localhost:8002/course/comment/Favorite/"+comment.id+
                               "/"+this.user.content.id).then(res => {
        
           //重新获取本课程的全部留言,使得更新数据
     this.getComment()
    }).catch(err =>{
      this.$message.error("点赞失败")
    })
    },
至此可以通过点击赞进行操作了
对应的sql方式:
<select id="getCommentsByCourseId" resultMap="CourseCommentMap">
        SELECT
            cc.*,
            ccfr.id ccfr_id,ccfr.user_id ccfr_user_id,comment_id,
    ccfr.is_del ccfr_is_del,ccfr.create_time ccfr_create_time,ccfr.update_time ccfr_update_time
        FROM course_comment cc LEFT JOIN 
    (select * from course_comment_favorite_record where is_del =0) ccfr ON cc.id = ccfr.`comment_id`
        WHERE cc.is_del = 0
          AND course_id = #{courseId}
        ORDER BY is_top DESC,like_count DESC,cc.create_time DESC
            LIMIT #{offset},#{pagesize}
    
    
    select>
对应的html:
  <div @click="zan(comment)" 
       v-if='JSON.stringify(comment.favoriteRecords).indexOf("\"userId\":"+user.content.id) >=0'  
       class="message-list-title-right">
   <div @click="zan(comment)" v-else class="message-list-title-right">
 zan(comment){ 

        //alert("赞和取消赞")
         return this.axios.get("http://localhost:8002/course/comment/Favorite/"+comment.id+
                               "/"+this.user.content.id).then(res => {
        
           //重新获取本课程的全部留言,使得更新数据
     this.getComment()
    }).catch(err =>{
      this.$message.error("点赞失败")
    })
    },
发现,只需要改变一下sql,那么代码就省略了很多,实际上sql对数据的操作更加接近,而程序一般会通过很多逻辑进行改变
所以若可以使用sql进行优化的,最好考虑sql,即在优化前,sql最好优先考虑
点赞操作完成了,接下来我们操作留言的发表
<button class="message-edit-btn disableBg" @click="saveComment">发表留言button>
 <div class="message-edit">
              
               <textarea rows="20" style="border:none;resize: none;" 
                contenteditable="true"
                placeholder="分享学习心得、思考感悟或者给自己一个小鼓励吧!"
                class="edit-div pcStyle"
                          v-model="comment"
              >textarea>
              <div class="message-edit-count">
                <span class="message-edit-count-cur">0span>
                <span class="message-edit-count-max">/2000span>
              div>
            div>
data() {
    return {
      comment:null, //待发表的留言内容
      activeName: "intro",
      course:null,
      totalLessons:0, //本门课程的总节数
      commentList:null, //所有留言
      isLogin:false, //false,未登录
      isBuy:false,//未购买
      user:null, //当前用户,{}对象可以","结尾
      myCourseList:[], //当前用户购买过的所有课程
    };
  },
 //发表留言
    saveComment(){
 return this.axios.get("http://localhost:8002/course/comment/saveCourseComment",{
   params:{
     courseid:this.course.id,
     userid:this.user.content.id,
     username:this.user.content.name,
     comment:this.comment,
  


   }
 }).then(res => {     
      //重新获取本课程的全部留言,使得更新数据
     this.getComment()
    }).catch(err =>{
      this.$message.error("发表留言失败")
    })
    }
我们需要修改后端的代码:
 @GetMapping("comment/saveCourseComment")
    public Object saveCourseComment(Integer courseid,Integer userid,String username,String comment) 
        throws UnsupportedEncodingException {
        System.out.println(new String(username.getBytes("ISO-8859-1")));
     System.out.println(new String(comment.getBytes("ISO-8859-1")));

        username = new String(username.getBytes("ISO-8859-1"),"UTF-8");
        comment = new String(comment.getBytes("ISO-8859-1"),"UTF-8");
        //解决get情况中,传递过来的乱码问题,因为get默认是ISO-8859-1的操作
        //一般来说,get请求会设置成识别中文,而post不会
        //假设若由于版本,服务器或者框架的影响,使得不能识别(一般是服务器问题,即版本问题)
        //也就是默认使用ISO-8859-1编码
        //一般tomcat8及其以后就不需要了
        //那时get会设置成对应的中文识别,也可以说,设置了UTF-8,但低版本的还是默认ISO-8859-1
        //这里好像使用的是tomcat7,所以是默认操作ISO-8859-1
        //即这时,我们需要使用ISO-8859-1进行变成对应的中文
        //然后设置操作UTF-8,虽然并不需要设置,好像的默认的,但也要防止默认识别不了中文
        //这里之所以会这样,与当前的框架或则版本,以及前端可能都有关系,因为一般的get不会出现乱码
        //而乱码主要是对应的编码方式不一致的缘故,无论是什么情况,只要编码一致即可


        CourseComment courseComment = new CourseComment();
        courseComment.setCourseId(courseid); //课程编号
        //这里写为0,因为我们的留言只操作对应的课程,章节和小节并没有操作
        //所以这样的操作,我们称为预留字段
        //即在后面的版本中(如更新版本)进行执行,现在默认写为0,虽然写其他的也可
        courseComment.setSectionId(0); //章节编号,预留字段
        courseComment.setLessonId(0); //小节编号,预留字段
        courseComment.setUserId(userid); //用户编号
        courseComment.setUserName(username); //用户昵称
        courseComment.setParentId(0); //没有父id,预留字段
        courseComment.setComment(comment); //留言内容
        courseComment.setType(0); //0:用户留言,预留字段
        courseComment.setLastOperator(courseid); //最后操作的用户编号
        Integer integer = commentService.saveComment(courseComment);
        return integer;



    }
这时我们进行发表留言,发现,的确有对应的数据了

你可能感兴趣的:(笔记,分布式,前端,javascript,vue)