前端门户系统
经过上一章的后端开发后,接下来我们来操作前端开发,页面不需要我们自己开发,使用提供的页面即可
对应的前端初始项目地址:
链接:https://pan.baidu.com/s/1iFui2WbE1mfmHWnb9Z8oGg
提取码:alsk
运行项目 npm run serve
接下来进行开发
但要注意:这里只会给出部分代码,需要自己去进行对比修改(记得启动对应的后端,且没有的自然自己写)
由于是部分,对应的代码可能不是全的
可以使用ctrl+f进行查找,或者ctrl+d进行找到一样的(虽然从上到下,循环的,直到找到自己)
进入首页组件Index.vue
对应的js部分:
created() {
this.getCourseList()
},
getCourseList(){
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(){
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:
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")));
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"));
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,
isBuy:false,
user:null,
myCourseList:[],
};
},
created(){
this.course = this.$route.params.course
if(this.course==null){
this.$router.push("/");
}
this.user = JSON.parse(localStorage.getItem("user"))
if(this.user != null){
this.isLogin = true
if(this.course!=null){
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(status,index,courseMedia,lessonid) {
if(courseMedia == null){
this.$message.error("播放失败,暂无视频")
}else{
if(status == 1 && index<2){
this.$message.success("观看第【" + lessonid + "】节课程视频!" + courseMedia.fileEdk);
this.$router.push({
name: "videoDetail",
params: { course: this.course,lessonid: lessonid },
});
}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 },
});
}
}}
}
},
接下来我们操作播放执行:
到videoDetail.vue
data() {
return {
myvideo: null,
isplay: false,
nowTime: "00:00",
totalTime: "00:00",
course:null,
lessonid:0,
lessonName:null,
};
},
created() {
this.course = this.$route.params.course;
this.lessonid = this.$route.params.lessonid
},
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;
}
}
}
}
},
至此我们进行点击试看或者播放,点击视频中间进行播放,发现视频的确进行播放,那么操作成功
在这之前,也可以点击地址看看是否可以播放
接下来操作播放的页面:
<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,
lessonName:null,
isLogin:false,
isBuy:false,
};
},
我们从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)
}
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组件
<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;
this.myvideo.src = lesson.courseMedia.fileEdk
},
至此可以进行视频的切换了,虽然对应的按钮操作是特殊的,一般只能点击视频进行视频的观看
但是在观看切换时,可以点击按钮进行观看,而使得不会变化
这实际上并不是好的视频组件,因为并不是完全的根据按钮状态来执行,但这也并不需要操作,因为能看即可
实际上是因为每次的操作,都会进行取反(对应的播放,而切换时,并不会,所以使得出现上面的情况)
为了解决这样的问题,需要加上如下代码:
playLesson(lesson) {
this.lessonid = lesson.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;
this.myvideo.src = lesson.courseMedia.fileEdk
this.myvideo.play();
this.isplay = true
}else{
this.$message.warning("没有该视频")
}
},
但是虽然我们显示了状态,但是也要进行判断,使得对应状态真实起作用,代码如下:
最终的修改:
playLesson(status,index,lesson) {
if(lesson.courseMedia!=null){
if(status == 1 && index<2){
this.lessonid = lesson.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;
this.myvideo.src = lesson.courseMedia.fileEdk
this.myvideo.play();
this.isplay = true
}
}
}
}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;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class CourseCommentFavoriteRecord implements Serializable {
private static final long serialVersionUID = 159062001487532233L;
private Integer id;
private Integer userId;
private Integer commentId;
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;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class CourseComment implements Serializable {
private static final long serialVersionUID = -11641570368573216L;
private List<CourseCommentFavoriteRecord> favoriteRecords;
private Object id;
private Integer courseId;
private Integer sectionId;
private Integer lessonId;
private Integer userId;
private String userName;
private Integer parentId;
private Integer isTop;
private String comment;
private Integer likeCount;
private Integer isReply;
private Integer type;
private Integer status;
private Date createTime;
private Date updateTime;
private Integer isDel;
private Integer lastOperator;
private Integer isNotify;
private Integer markBelong;
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=="
}
}
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){
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,
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");
CourseComment courseComment = new CourseComment();
courseComment.setCourseId(courseid);
courseComment.setSectionId(0);
courseComment.setLessonId(0);
courseComment.setUserId(userid);
courseComment.setUserName(username);
courseComment.setParentId(0);
courseComment.setComment(comment);
courseComment.setType(0);
courseComment.setLastOperator(courseid);
Integer integer = commentService.saveComment(courseComment);
return integer;
}
这时我们进行发表留言,发现,的确有对应的数据了