前端门户系统
经过上一章的后端开发后,接下来我们来操作前端开发,页面不需要我们自己开发,使用提供的页面即可
对应的前端初始项目地址:
链接: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/no-login@2x.png"
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/yanzhi_activity_modal_gift@2x.png"
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" > 0</ span>
< span class = " message-edit-count-max" > /2000</ span>
</ 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;
}
这时我们进行发表留言,发现,的确有对应的数据了