Files
learning-system-portal/src/views/study/coursenew.vue
2022-09-07 14:31:07 +08:00

1755 lines
55 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div>
<div class="coures-bg">
<portal-header current="course" :goSearch="1"></portal-header>
<el-breadcrumb style="margin-top:50px;margin-left:82px" separator-class="el-icon-arrow-right" class="breadcrumb-nav" >
<el-breadcrumb-item :to="{ path: '/course' }">课程列表</el-breadcrumb-item>
<el-breadcrumb-item class="hear-nav">课程详情</el-breadcrumb-item>
</el-breadcrumb>
<div class="coures-title">
<div>课程名称 标准化异常处理流程</div>
<span>课程简介通俗易懂的入门课程</span>
<h6>评分5.0</h6>
</div>
</div>
<div class="coures-content">
<div class="coures-play">
<div class="player" style="width: 100%;height: 100%;border: 1px solid #ffffff;background-color: #FFFFFF;overflow: auto;">
<div>
<div v-if="resType == null || resType == 0">
<!--先显示视频图片-->
<course-image v-if="courseInfo.id != ''" :course="courseInfo"></course-image>
</div>
<div v-if="resType == 10" style="position: relative;">
<videoPlayer id="myVideoPlayer" v-if="resType == 10"
:src="blobUrl"
@onPlayerPlaying="onPlayerPlaying"
:initTime="contentData.lastStudyTime"
@onPlayerPlay="onPlayerPlay"
:isDrag="curriculumData.isDrag"
@onFullscreen="onFullscreen"
@onPlayerPause="onPlayerPause"
@onPlayerEnded="onPlayerEnded"
></videoPlayer>
<div class="player-box" v-if="playerBoxShow">
<div class="player-praise" style="cursor: pointer;">
<div @click="praiseContent">
<img class="icon-small" v-if="isPraise" :src="require('@/assets/images/icon/praise-active.png')" />
<img class="icon-small" v-else :src="require('@/assets/images/icon/zhan.png')" />
<!-- {{ courseInfo.praises }} -->
<div style="color:#fff;cursor: pointer;"></div>
</div>
<div style="margin-left: 15px;cursor: pointer;" @click="treadContent">
<img class="icon-small" v-if="isTrample" :src="require('@/assets/images/icon/trample-active.png')" />
<img class="icon-small" v-else :src="require('@/assets/images/icon/cai.png')" />
<!-- {{ courseInfo.trampleCount }} -->
<div style="color:#fff;cursor: pointer;"></div>
</div>
</div>
<div v-if="!scoreInfo.has" class="player-rate">
<el-rate v-model="scoreInfo.score" text-color="#ff9900" score-template="{value}" void-color="#fff" @change="addScore"></el-rate>
</div>
<div v-if="scoreInfo.has" style="padding-top: 5px;display: flex;">
<div class="player-rate" style="padding-left: 35px;">
<el-rate disabled v-model="courseInfo.score" :allow-half="true" ></el-rate>
</div>
<span class="score-text" style="margin-top:35px">
<span style="color:#ffb30f;">{{ toScore(courseInfo.score) }}</span>
<span style="font-size: 12px;color: #fff"></span>
</span>
</div>
</div>
</div>
<div v-if="resType == 20">
<div class="con-audio">
<div class="con-audio-title">{{ contentData.contentName }}</div>
<div class="con-audio-player">
<audioPlayer
v-if="resType == 20"
:url="fileBaseUrl + curriculumData.url"
:name="contentData.contentName"
@onPlaying="audioPlaying"
:isDrag="curriculumData.isDrag"
@onPlay="audioPlay"
@onPause="audioPause"
@onPlayEnd="audioEnd"
></audioPlayer>
</div>
</div>
</div>
<div v-if="resType == 40">
<div style="padding: 10px;color: #ed0000; " v-if="curCFile.converStatus < 2 && !contentData.content">
<div>此课程内容无法预览请联系管理员</div>
</div>
<div style="padding: 10px;color: #ed0000;" v-if="curCFile.converStatus == 3 && !contentData.content">
此课程内容无法预览请联系管理员
</div>
<pdfPreview :autoScroll="true" v-if="resType == 40" :filePath="fileBaseUrl + contentData.content"></pdfPreview>
</div>
<div v-if="resType == 41"><div style="padding: 20px;" v-html="contentData.content"></div></div>
<div v-if="resType == 52">
<div v-if="contentData.content != ''">
<div class="hyper-link" v-if="conLink.openType == 2">
<div class="hyper-link-row">{{ contentData.contentName }}</div>
<div class="hyper-link-row">{{ conLink.url }}</div>
</div>
<div v-if="conLink.openType == 1"><iframe :src="conLink.url" style="width: 100%;border:0px;min-height: 473px;" frameborder="0"></iframe></div>
</div>
</div>
<div v-if="resType == 60"><homework v-if="resType == 60 && studyId != ''" :studyId="studyId" :content="contentData"></homework></div>
<div v-if="resType == 61"><exam v-if="resType == 61 && studyId != '' " :studyId="studyId" :content="contentData"></exam></div>
<div v-if="resType == 62" style="padding:5px">
<assess v-if="resType == 62 && studyId != '' && contentData.id" :studyId="studyId" :content="contentData"></assess>
</div>
</div>
</div>
<div style="padding-left:5px;margin: 14px 0px;background-color: #FFFFFF;" class="info">
<div class="coure-tab">
<div @click="coutab" :class="courestab == true? 'coureactive' : ''">课程评论<span class=""></span> </div>
<div @click="coutab" :class="courestab == false? 'coureactive' : ''">课程笔记<span class=""></span> </div>
</div>
<div v-if="courestab" class="coures-comments">
<comments v-if="courseInfo.id && courseInfo.id != ''" :obj-type="1" :obj-id="courseInfo.id" :toUsers="toUsers"></comments>
</div>
<div v-else class="coures-note">
<div class="note-tole">33条笔记</div>
<div class="note-info">
</div>
</div>
</div>
</div>
<div class="coures-infobox">
<div class="coures-info">
<div class="hear-tab">
<div @click="heartabone" :class="tab == 1 ? 'tab-active' : ' '"><i class="el-icon-reading" style="margin-right:9px;margin-left:9px"></i>课程单元</div>
<div @click="heartabtwo" :class="tab == 2 ? 'tab-active' : ' '"><i class="el-icon-edit" style="margin-right:9px;margin-left:9px"></i>我的笔记</div>
</div>
<div class="course-units" v-if="tab == 1">
<div class="units-info">
1. 任务工程师角色认知
</div>
<div class="units-info units-active">
<img src="../../../public/images/playicon.png" alt=""> 1. 任务工程师角色认知
</div>
<div class="units-info">
1. 任务工程师角色认知
</div>
<div class="units-info">
1. 任务工程师角色认知
</div>
<div class="units-info">
1. 任务工程师角色认知
</div>
<div class="units-info">
1. 任务工程师角色认知
</div>
<div class="units-info">
1. 任务工程师角色认知
</div>
<div class="units-info">
1. 任务工程师角色认知
</div>
<div class="units-info">
1. 任务工程师角色认知
</div>
<div class="units-info">
1. 任务工程师角色认知
</div>
</div>
<div class="mynote" v-if="tab == 2">
<div class="mynote-tab">
<div @click="notetab1" :class="notetab == 1 ? 'noteactive' : ' ' "> <a href="#">新增笔记</a> </div>
<div @click="notetab2" :class="notetab == 2 ? 'noteactive' : ' '"> <a href="#">我的笔记</a> </div>
</div>
<div class="newcote-content" v-if="notetab == 1">
<div class="newcote-time">
<img src="../../../public/images/coteplay.png" alt="">
8:40
<img src="../../../public/images/cotedetel.png" alt="">
</div>
<div class="newcote-text">
我见过的策划们不管是甲方企业的还是广告代理公司的还营销策划公司的在做策略写方案的时候都经常错误找一个营销理论做策略时直接向上套不管是什么行业企业处在什么发展阶段都要照着这个理论的要求来实施营销传播写PPT时也要照着这个理论的框架来写
我见过的策划们不管是甲方企业的还是广告代理公司的还营销策划公司的在做策略写方案的时候都经常错误找一个营销理论做策略时直接向上套不管是什么行业企业处在什么发展阶段都要照着这个理论的要求来实施营销传播写PPT时也要照着这个理论的框架来写
</div>
</div>
<div class="mycote-content" v-if="notetab == 2">
<div style="border-bottom:1px solid #4444;padding-bottom:25px;">
<span class="mycote-time">2022-06-21 21:35:12 <span class="sm">私密</span> <span class="more" icon="el-icon-more"></span> </span>
<div style="margin-top:20px" class="newcote-time">
<img src="../../../public/images/coteplay.png" alt="">
8:40
<img src="../../../public/images/cotedetel.png" alt="">
</div>
<div class="newcote-text">
在做策略写方案的时候都经常错套都要照着这个理论的要求来实施营销传播写PPT时也要照着这个理论的框架来写
我见划公司的在做策略写方案的时候都经常不管是什么行业企业处在什么来实施营销传播写PPT时也要照着这个理论的框架来写
</div>
</div>
<h6 class="mycote-dibu">已经到底啦</h6>
</div>
<div class="newcote-bottom" v-if="notetab == 1">
<span> <img src="../../../public/images/playtime.png" alt=""> 视频位置</span>
<el-radio v-model="radio" label="1">公开</el-radio>
<el-radio v-model="radio" label="2">私密</el-radio>
<el-button type="primary" size="small">保存</el-button>
</div>
</div>
</div>
<div class="coures-tearch">
<div class="tearch-top"><img src="../../../public/images/tearch-top.png" alt=""></div>
<el-card :body-style="{ padding: '0px' }" class="teachers">
<div class="top">
课程讲师
<el-button style="float :right;" type="primary" size="small">+ 关注</el-button>
</div>
<div>
<div class="teacher" v-for="(item, idx) in teachers" :key="idx">
<div class="teacher-avator">
<!-- <div class="teacher-text" v-if="item.authorInfo.avatar == ''">{{userAvatarText(item.teacherName)}}</div> -->
<el-avatar v-if="item.authorInfo.avatar !== ''" :src="fileBaseUrl + item.authorInfo.avatar" shape="circle" :size="50"></el-avatar>
<div v-else class="teacher-text">
<div v-if="item.authorInfo.sex === 1 "><img src="../../../public/images/Avatarman.png" alt=""></div>
<div v-else><img src="../../../public/images/Avatarwoman.png" alt=""></div>
</div>
</div>
<div class="teacher-info">
<div class="teacher-name">{{ item.teacherName }}</div>
<div class="teacher-remark" v-html="item.remark"></div>
</div>
</div>
</div>
</el-card>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import portalHeader from "@/components/PortalHeader.vue";
import portalFooter from "@/components/PortalFooter.vue";
import comments from "@/components/Portal/comments.vue";
import interactBar from "@/components/Portal/interactBar.vue";
import audioPlayer from '@/components/AudioPlayer/index.vue';
import videoPlayer from '@/components/VideoPlayer/index.vue';
import hyperLink from '@/components/Course/hyperLink.vue';
import studyUtil from '@/utils/study.js';
import {encrypt} from '@/utils/jsencrypt.js';
import cookies from 'vue-cookies';
import apiStudy from '@/api/modules/courseStudy.js';
import apiVideoStudy from "@/api/modules/videoStudy.js";
import apiCourseGrade from '@/api/modules/courseGrade.js';
import apiPraises from '@/api/modules/praises.js';
import apiTrample from '@/api/modules/trample.js';
import apiCoursePortal from '@/api/modules/coursePortal.js';
import apiCourse from '@/api/modules/course.js';
import apiUser from '@/api/system/user.js';
import apiCourseFile from '@/api/modules/courseFile.js';
import { resListMap, resOwnerListMap, courseType, getType, toScore,userAvatarText } from '@/utils/tools.js';
import pdfPreview from '@/components/PdfPreview/index.vue';
import courseImage from '@/components/Course/courseImage.vue';
import exam from '@/components/Course/exam';
import homework from '@/components/Course/homework';
import assess from '@/components/Course/assess';
export default {
name: "atticle",
components: {courseImage, portalHeader, portalFooter, hyperLink, comments, homework, exam, interactBar, assess, pdfPreview, audioPlayer, videoPlayer },
data(){
return{
courestab:true,
curCFile:{
converStatus:4,
},
interactRuning:false,
playerBoxShow:false,
userAvatarText,
publicPath: process.env.VUE_APP_PUBLIC_PATH,
showiframe: false,
toScore,
courseId: '',//当前课程的id
studyId: '', //当前学习的id
initContentId: '', //初始化当前学习的内容节
blobUrl:'',//播放的文件地址新添加采用blob方式
contentData: {
studyItemId:'',
status:1
}, //当前的显示的内容
conLink: { openType: 1, url: '' }, //对于超连接的内容
curriculumData:{url:'',isDrag:true,completeSetup:0,setupTage:0,second:0},// 课件内容
courseInfo: { id: '', name: '' }, //课程信息
totalContent: 0, //课程内容数量
pageCount: 0,
currentPage: 0,
fileBaseUrl: this.$Constants.fileBaseUrl,
contentList: [],
sectionList: [],
teachers: [],
toUsers: [], //对于@教师的处理
getType: getType,
ctabName: 'catalog',
resType: null,
activeNames: [0, 1, 2, 3, 4,5,6,7,8,9],
scoreInfo: {
dlgShow: false,
score: 5,
has: false
},
isPraise: false,
isTrample: false,
appendStartTime: null, //记录追加的开始时间
appendHandle:null,
isAppendTime:false,//是否追加学习时长
appentId:'',//当前追加的学习时长的id
appentInterval:30000,//追加学习时间的间隔 30秒加一次
handleTimeout:null,
completed:[],
tab:1,
notetab:1,
}
},
mounted() {
this.$watermark.set(this.userInfo.name + this.userInfo.loginName);
this.courseId = this.$route.query.id;
this.loadData();
},
computed: {
...mapGetters(['userInfo']),
catalogTree() {
let treeList = [];
this.completed = [];
let $this = this;
$this.sectionList.forEach(sec => {
let treeNode = { section: sec, children: [] };
sec.status = 1;
let finishCount = 0;
$this.contentList.forEach(c => {
if (c.csectionId == sec.id) {
if (c.status > 1) {
sec.status = 2;
if(c.status == 9){
finishCount++;
}
}
if(c.status == 9) {
$this.completed.push(c.id);
}
treeNode.children.push(c);
}
});
if (finishCount == treeNode.children.length) {
sec.status = 9;
}
treeList.push(treeNode);
});
return treeList;
}
},
methods: {
coutab(){
this.courestab = !this.courestab;
},
createPlayUrl(fid,u){
let nowDate=new Date();
let ctime=parseInt(nowDate.getTime()/1000);
let beforeUrl=parseInt(nowDate.getTime()/1000)+'/'+fid;
//console.log(beforeUrl,'beforeUrl');
let urlSign=encodeURIComponent(encrypt(beforeUrl));
//console.log(urlSign,'urlSign');
cookies.set('PLAYSIGN_TIME', ctime);//写客户端的cookie保存
//以下判断是为了区分本地环境和服务器环境
if(process.env.NODE_ENV == 'development'){
this.blobUrl=process.env.VUE_APP_FILE_BASE_URL+u;
}else{
this.blobUrl=process.env.VUE_APP_BASE_API+'/xboe/m/course/cware/resource?sign='+urlSign;
}
//console.log(this.blobUrl,'this.blobUrl');
},
widthOpen(url) {
window.open(url, '_blank');
},
showRes(r,i,index) { //i:子节下标index:章下标
if(i!=undefined && index!=undefined && r.status<9) {
if(this.courseInfo.orderStudy) {
//判断上个是否学完
if(i == 0) {
if(index > 0) { //第一章 第一节
let preCatalog=this.catalogTree[index-1];
let last=preCatalog.children[preCatalog.children.length-1];
if(last.status!=9){
this.$message.warning('请按顺序学习!');
return;
}
}
}else{
let pre=this.catalogTree[index].children[i-1];
if(pre.status!=9){
this.$message.warning('请按顺序学习!');
return;
}
}
//判断是否是第一个未学完的
let isAllow=false;
let has=this.catalogTree.some(treeNode=>{
let hasNo=treeNode.children.some(child=>{
if(child.status<9){
if(child.id==r.id){
isAllow=true;
}
return true;
}else{
return false;
}
});
return hasNo;
});
if(has){
if(!isAllow){
this.$message.warning('请按顺序学习');
return;
}
}
}
}
this.playerBoxShow=false;
//显示内容部分
let $this = this;
this.resType = r.contentType;
this.contentData = r;
this.saveStudyDuration();
if(r.contentType == 10 || r.contentType == 20) {
if (r.content.startsWith('\{')) {
this.curriculumData = JSON.parse(r.content);
} else {
this.curriculumData.url = r.content;
}
//let url=process.env.VUE_APP_BASE_API+'/xboe/m/course/file/show?cf='+this.curriculumData.url;
//let url=this.fileBaseUrl+this.curriculumData.url;
this.createPlayUrl(r.contentRefId,this.curriculumData.url);
} else if (r.contentType == 40) {
// if (r.content != '' && r.content.indexOf('.pdf') == -1) {
apiCourseFile.detail(r.contentRefId).then(cfrs => {
if (cfrs.status == 200) {
r.content = cfrs.result.previewFilePath;
this.curCFile = cfrs.result;
if(cfrs.result.previewFilePath == '' && cfrs.result.filePath.indexOf('pdf') > -1) {
r.content = cfrs.result.filePath;
this.curCFile.converStatus=2;
}
if(r.content && r.content.indexOf('.pdf')>-1){
this.curCFile.converStatus=2;
}
} else {
$this.$message.error('加载pdf课件文件失败');
}
});
// }
} else if (r.contentType == 52) {
this.isAppendTime=false;
if (r.content.startsWith('\{')) {
this.conLink = JSON.parse(r.content);
} else {
this.conLink.url = r.content;
this.conLink.openType = 1;
}
if (this.conLink.openType == 2) {
//直接设置完成状态
this.widthOpen(this.conLink.url);
}
//this.conLink=
} else if (r.contentType == 61) {
// 考试
} else if (r.contentType == 60) {
// 作业
} else if (r.contentType == 62) {
// 评估
//评估不需要查找因为内容就是content中
console.log('评估处理');
}
if(this.contentData.status<2){
this.contentData.status=2;//进行中
}
if(this.contentData.contentType>20){ //非视频类的
this.isAppendTime=true;
this.appendStudyTime();
this.handleTimeout= setTimeout(function() {$this.saveStudyInfo();}, 5000); //5秒后记录学习完成
}
},
handleChange(val) {
console.log(val);
},
loadScorePraiseAndTrample() {
//加载是否请过分
apiCourseGrade.has(this.courseId).then(rs => {
if (rs.status == 200 && rs.result) {
this.scoreInfo.has = true;
}
});
apiPraises.has(1, this.courseId).then(rs => {
if (rs.status == 200 && rs.result) {
this.isPraise = true;
}
});
apiTrample.has(this.courseId).then(rs => {
if (rs.status == 200 && rs.result) {
this.isTrample = true;
}
});
},
addScore() {
let that = this;
let postData = {
courseId: this.courseInfo.id,
studyId: this.studyId,
score: this.scoreInfo.score
};
if (this.scoreInfo.score > 0) {
apiCourseGrade.grade(postData).then(rs => {
if (rs.status == 200){
this.$message.success('打分成功,谢谢您的打分');
that.scoreInfo.has = true;
that.courseInfo.score = rs.result;
} else {
this.$message.error('打分处理失败,请稍后再试');
}
});
}
},
praiseContent() {
if (this.isTrample) {
this.$message.error('您已踩过了,不能再赞了');
return;
}
if(this.interactRuning){
return;
}
this.interactRuning=true;
let postData = {
objType: 1,
objId: this.courseId,
title: this.courseInfo.name
};
if (this.isPraise) {
apiPraises.remove(1, this.courseInfo.id).then(res => {
this.interactRuning=false;
if (res.status == 200) {
this.$message.info('已取消点赞');
this.isPraise = false;
this.courseInfo.praises--;
} else {
this.$message.error('取消点赞失败,请稍后再试');
}
});
} else {
apiPraises.save(postData).then(rs => {
this.interactRuning=false;
if (rs.status == 200) {
this.$message.success('点赞成功');
this.isPraise = true;
this.courseInfo.praises++;
} else {
this.$message.error('点赞失败,请稍后再试');
}
});
}
},
treadContent() {
if (this.isPraise) {
this.$message.error('您已赞过了,不能再踩了');
return;
}
if(this.interactRuning){
return;
}
this.interactRuning=true;
if (this.isTrample) {
apiTrample.remove(this.courseInfo.id).then(rs => {
this.interactRuning=false;
if (rs.status == 200) {
this.$message.info('已取消踩');
this.isTrample = false;
this.courseInfo.trampleCount--;
} else {
this.$message.error('取消失败,请稍后再试');
}
});
} else {
apiTrample.trample(this.courseInfo.id).then(rs => {
this.interactRuning=false;
if (rs.status == 200) {
this.$message.success('已踩');
this.isTrample = true;
this.courseInfo.trampleCount++;
} else {
this.$message.error('踩失败,请稍后再试');
}
});
}
},
statusToContent(status) {
let data = null;
switch (status) {
case 1: {
data = {
text: '未开始',
class: 'catalog-cell-state1'
};
break;
}
case 2: {
data = {
text: '进行中',
class: 'catalog-cell-state2'
};
break;
}
case 9: {
data = {
text: '已完成',
class: 'catalog-cell-state9'
};
break;
}
default:
{
data = {
text: '未开始',
class: 'catalog-cell-state1'
};
}
break;
}
return data;
},
loadAuthorInfo(list, ids) {
//加载作者信息,头像,机构信息
if (ids.length == 0) {
return;
}
apiUser.getByIds(ids).then(res => {
if (res.status == 200) {
list.forEach((item, index) => {
res.result.some(author => {
if (author.aid == item.teacherId) {
item.authorInfo = author;
return true;
} else {
return false;
}
});
});
} else {
//console.log('加载课程信息失败:'+res.error);
//this.$message.error(res.message);
}
});
},
ctabChange(e) {
//当前已经不再使用
//console.log(e);
},
onPlayerPause() {
//console.log("暂停");
},
onPlayerEnded() {
this.playerBoxShow = true;
if(this.contentData.status<9){
this.finishStudyItem();
}
},
onPlayerPlaying(itme) {
this.isAppendTime=false;
this.appendStartTime=null;
//console.log("当前播放"+itme);
//console.log("当前播放11"+itme);
if (this.contentData.contentType && this.contentData.contentType == 10){
let intTime = parseInt(itme);
//判断是否完成
let completeType=this.curriculumData.completeSetup;
let completeSecond=this.curriculumData.second;
if(!completeSecond || completeType==0){
completeSecond=5;//如果没有就采用默认的时间了
}
if(this.contentData.status<9){ //因为1按进度2按时长都是计算时间所以这里直接大于0处理
if(completeType==1){
let finishPercent=this.curriculumData.setupTage;
let videDuration=this.contentData.duration;
let percent =intTime*100/videDuration;
if(percent>=finishPercent){
this.finishStudyItem();
}
}else{
if(intTime>=completeSecond){
this.finishStudyItem();
}
}
}
//下面是每隔10秒记录一下次
let saveTime = Math.floor(intTime % 10);
if (intTime > 10 && intTime!=this.contentData.lastStudyTime && saveTime == 0 && this.contentData.studyItemId != '') {
this.contentData.lastStudyTime=intTime;
let postData = {
itemId: this.contentData.studyItemId,
videoTime: intTime
};
//console.log('记录播放时间')
apiStudy.studyVideoTime(postData).then(rs => {
if (rs.status != 200) {
console.log('记录播放时间错误');
}
});
}
}
},
audioPlaying(item,currentTime) {
//console.log("当前播放"+item);
let intTime = parseInt(currentTime);
//判断是否完成
let completeType=this.curriculumData.completeSetup;
let completeSecond=this.curriculumData.second;
if(!completeSecond || completeType==0){
completeSecond=5;//如果没有就采用默认的时间了
}
if(this.contentData.status<9){ //因为1按进度2按时长都是计算时间所以这里直接大于0处理
if(completeType==1){
let finishPercent=this.curriculumData.setupTage;
let videDuration=this.contentData.duration;
let percent =intTime*100/videDuration;
if(percent>=finishPercent){
this.finishStudyItem();
}
}else{
if(intTime>=completeSecond){
this.finishStudyItem();
}
}
}
//下面是每隔10秒记录一下次
let saveTime = Math.floor(intTime % 10);
if (intTime > 10 && intTime!=this.contentData.lastStudyTime && saveTime == 0 && this.contentData.studyItemId) {
this.contentData.lastStudyTime=intTime;
let postData = {
itemId: this.contentData.studyItemId,
videoTime: intTime
};
//console.log('记录播放时间')
apiStudy.studyVideoTime(postData).then(rs => {
if (rs.status != 200) {
console.log('记录播放时间错误');
}
});
}
},
audioPlay() {
//console.log("开始播放");
let $this=this;
// if(this.contentData.status!=9){
// let completeType=this.curriculumData.completeSetup;
// if(completeType==0){
// //默认5秒后学习完成.
// $this.handleTimeout= setTimeout(function() {$this.saveStudyInfo();}, 5000); //5秒后记录学习完成
// }else{
// //先记录进行中的学习内容
// this.saveStudyItem();
// }
// }
},
audioPause() {
//console.log("暂停");
},
audioEnd() {
//console.log("播放结束");
if(this.contentData.status<9){
this.finishStudyItem();
}
},
loadData() {
apiCoursePortal.detail(this.courseId,false).then(rs => {
if (rs.status == 200) {
//设置必须的字段
rs.result.sections.forEach(sec => {
sec.status = 0; //加入状态表未开始
rs.result.contents.forEach(c => {
c.status = 0; //初始化状态 ,未开始
c.studyItemId = ''; //初始化字段学习条目id
c.lastStudyTime = 0; //初始化上次一学习的时间,作用于视频插放
});
});
this.sectionList = rs.result.sections;
this.courseInfo = rs.result.course;
this.teachers = rs.result.teachers;
if (rs.result.teachers && rs.result.teachers.length > 0) {
let userIds = [];
let ctoUsers = [];
rs.result.teachers.forEach(item => {
item.authorInfo = { aid: '', name: '', orgInfo: '', avatar: '', code: '',sex:null, };
userIds.push(item.teacherId);
ctoUsers.push({ aid: item.teacherId, name: item.teacherName });
});
this.toUsers = ctoUsers;
this.loadAuthorInfo(rs.result.teachers, userIds);
}
this.contentList = rs.result.contents;
this.totalContent = rs.result.contents.length;
//加载学习的数据
this.loadStudyData();
} else {
this.$message.error(rs.message);
}
});
},
loadStudyData() {
let $this = this;
apiStudy.studyInfo(this.courseId).then(res => {
if (res.status == 200) {
if (res.result.signup){
this.loadScorePraiseAndTrample();
this.studyId = res.result.studyId;
//对已学习的内容进行比对,重要的字段, 学习内容id在后缀的
let playIndex = -1;
this.contentList.forEach((con, conIdx) => {
res.result.contents.forEach((scon, sconIdx) => {
if (scon.contentId == con.id) {
//定位显示的内容
if ($this.initContentId != '' && $this.initContentId == scon.contentId) {
//定位当前学习的内容,是上一次学习的内容
playIndex = conIdx;
} else {
if (sconIdx == 0 && con.contentType < 52){
playIndex = conIdx;
}
}
//console.log(scon.contentId,con.id);
con.lastStudyTime = scon.lastStudyTime;
//以下判断是为了兼容之前的问题,学习状态
if(scon.status){
con.status = scon.status;
}else{
con.status = 9;
}
con.studyItemId = scon.id; //这个就是学习内容条目的id
//console.log(scon.id,"scon.id");
//console.log(con,"scon.id");
}
});
});
//如果没有,就定位第一项内容
if (playIndex === -1) {
// this.showRes(this.contentList[0]);
this.showRes(this.catalogTree[0].children[0])
} else {
this.showRes(this.contentList[playIndex]);
}
} else {
this.$message.error('您还未报名');
if (this.courseInfo.type == 10) {
location.href = this.webBaseUrl + '/course/micro?id=' + this.courseId;
} else {
location.href = this.webBaseUrl + '/course/detail?id=' + this.courseId;
}
}
} else {
this.$message.error(res.message);
}
});
},
saveStudyInfo() {
//记录课件学习信息
if (this.contentData.contentType >= 60) {
//只有在课件页面停留超过5秒才会记录
return;
}
if (this.contentData.status == 9) {
//已学习完的,不用再添加
return;
}
let params = {
studyId: this.studyId, //学习id,
courseId: this.courseId, //课程id,
contentId: this.contentData.id, //内容id,
contentType:this.contentData.contentType,
contentName: this.contentData.contentName, //内容名称
progress: 100,
status:9,
contentTotal: this.totalContent
};
apiStudy.studyContent(params).then(res => {
if (res.status == 200) {
this.contentData.status = 9; //完成
this.contentData.studyItemId = res.result; //学习记录id
} else {
console.log('记录学习失败:' + res.message + '' + res.error);
}
});
},
saveStudyDuration(){ //保存本地存储的学习时长
let duration=studyUtil.getStudyDuration();
if(duration>0){
let postData = {
id:this.appentId,
studyId: this.studyId,
courseId: this.courseInfo.id,
contentId: this.contentData.id,
studyInfo:
this.courseInfo.name +
"-" +
this.contentData.contentName,
duration: duration
};
apiStudy.appendStudyTime(postData).then(rs => {
if (rs.status == 200){
this.appentId=rs.result;
studyUtil.clearStudyDuration();//清除本地存储
} else {
console.log(rs.message);
}
});
}
},
appendStudyTime(flag) {
if(this.studyId==''){
return;
}
if(!this.contentData.id){
return;
}
if(!this.isAppendTime){
this.appendStartTime =null;
return;
}
if(this.appendHandle!=null){
window.clearTimeout(this.appendHandle);
}
//首先从本地读取
let duration=studyUtil.getStudyDuration();
//追加学习时间
let $this = this;
if (this.appendStartTime == null) {
this.appendStartTime = new Date();
this.appendHandle=setTimeout(function() {$this.appendStudyTime();}, $this.appentInterval);
if(duration>0 && flag){
this.saveStudyDuration();
}
return;
}
let now = new Date();
let m = now.getTime() - this.appendStartTime.getTime(); //相差的毫秒数
let sen = parseInt(m / 1000); //计算秒数
duration=duration+sen;
if(flag) {
if(duration>0){
let postData = {
id:this.appentId,
studyId: this.studyId,
courseId: this.courseInfo.id,
contentId: this.contentData.id,
studyInfo:
this.courseInfo.name +
"-" +
this.contentData.contentName,
duration: duration
};
apiStudy.appendStudyTime(postData).then(rs => {
if (rs.status == 200){
$this.appentId=rs.result;
$this.appendStartTime = new Date(); //重置开始时间
studyUtil.clearStudyDuration();//清除本地存储
//this.appendHandle=setTimeout(function() {$this.appendStudyTime();}, $this.appentInterval);
} else {
console.log(rs.message);
}
});
}
} else {
$this.appendStartTime = new Date(); //重置开始时间
studyUtil.setStudyDuration(duration);//添加到本地存储中
}
this.appendHandle=setTimeout(function() {$this.appendStudyTime();},$this.appentInterval);
},
onPlayerPlay() {
//console.log("开始播放");
this.playerBoxShow = false;
let $this=this;
//console.log(this.contentData.status,'this.contentData.status');
// if(this.contentData.status<9){
// let completeType=this.curriculumData.completeSetup;
// //console.log(completeType,'completeType');
// if(completeType==0){
// //默认5秒后学习完成.
// $this.handleTimeout= setTimeout(function() {$this.saveStudyInfo();}, 5000); //5秒后记录学习完成
// }else{
// //先记录进行中的学习内容
// this.saveStudyItem();
// }
// }
},
onFullscreen(full){
let divId='videowatermark';
var div = document.getElementById('myVideoPlayer')
if(full){
var div3 = document.createElement("div");
div3.id =divId;
div3.setAttribute("class", "fullmark");
div3.innerHTML='';
//从父组件传过来的水印内容
//div3.innerText =this.userInfo.name+this.userInfo.code;
for(var i=0;i<8;i++){
div3.innerHTML+='<div style="color:#ffffff;width: 40%;height: 155px;padding-left:60px;padding-top:50px; display: flex;justify-content: center; transform: rotate(-36deg);font-size:20px;">'+this.userInfo.name+this.userInfo.loginName+'</div>';
}
div3.style.cssText = "position:absolute;pointer-events: none; width: 100%;height: 100%;top:0;left:0;bottom: 0;right: 0; display: flex;justify-content: center;flex-wrap: wrap;overflow: hidden; opacity:0.3;padding-top:10px";
div.appendChild(div3);
}else{
var markDiv=div.querySelector("#"+divId);
if(markDiv){
div.removeChild(markDiv);
}
}
},
finishStudyItem(){ //设置完成学习的内容,针对于音视频的内容
if(!this.contentData.studyItemId){
//这种可能没有不过这里也是为了万中那个1
this.saveStudyInfo();
}else{
let params={
itemId:this.contentData.studyItemId,
studyId:this.studyId,
courseId:this.courseId,
cnum:this.totalContent
}
apiVideoStudy.finishStudyItem(params).then(res=>{
if(res.status == 200){
this.contentData.status = 9;
this.contentData.progress = 100;
}else{
console.log("记录完成学习失败:" + res.message + "" + res.error);
}
});
}
},
saveStudyItem(){ //先保存学习的内容,针对于音视频的内容
if(this.contentData.studyItemId) {
return;//已经有记录的,不需要再保存了
}
let params = {
studyId: this.studyId, //学习id,
courseId: this.courseId, //课程id,
contentId: this.contentData.id, //内容id,
contentType:this.contentData.contentType, //内容id,
contentName: this.contentData.contentName, //内容名称
progress: 0,
lastStudyTime:0,
status:2,
studyDuration:0,
contentTotal: this.totalContent
};
apiVideoStudy.saveStudyItem(params).then(res=>{
if(res.status == 200){
this.contentData.studyItemId=res.result.id;
this.contentData.status = 2;//进行中状态
}else{
console.log("记录学习失败:" + res.message + "" + res.error);
}
});
},
formatTime(duration){
let min=0;
if(duration>0){
min=parseInt(duration/60);
}
return min;
},
heartabone(){
this.tab = 1
},
heartabtwo(){
this.tab = 2
},
notetab1(){
this.notetab = 1
},
notetab2(){
this.notetab = 2
}
},
}
</script>
<style lang="scss" scoped>
.tearch-top{
margin-top: 10px;
width: 100%;
height: 15px;
img{
width: 100%;
height: 100%;
}
}
.coures-note{
min-height: 500px;
padding-left: 50px;
padding-top: 25px;
.note-tole{
color: #333333;
font-size: 18px;
font-weight: 600;
}
.note-info{
}
}
.coure-tab{
display: flex;
width: 300px;
padding-top: 30px;
margin-left: 55px;
div{
flex: 1;
color: #666666;
font-size: 18px;
}
.coureactive{
color: #333333;
position: relative;
span{
display: inline-block;
width: 69px;
height: 4px;
background: #387DF7;
border-radius: 5px;
position: absolute;
left: 0;
top: 128%;
}
}
}
.mltit{
// width: 70%;
// width: ;
word-break:break-all;
// line-height: 25px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
}
.catalog-text{
width: 70%;
overflow: hidden;
word-break:break-all;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
height: 40px;
}
.player-box{
position: absolute;
// top: 62px;
// left: 184px;
width: 300px;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
height: 187px;
background: rgba(74, 74, 74,.5);
border-radius: 33px;
text-align: center;
padding: 20px;
box-sizing: border-box;
.player-praise{
margin-top: 25px;
display: flex;
// justify-items: center;
justify-content: center;
}
.player-rate{
margin-top: 35px;
}
}
.score {
display: flex;
justify-content: center;
align-items: center;
.el-rate {
display: inline-block;
}
.score-text {
font-size: 28px;
color: #ffb30f;
font-family: 'Arial';
margin-left: 23px;
// font-weight: 600;
}
// margin-bottom: 19px;
.score-no {
color: #ffb30f;
padding: 5px 0;
background: #efefef;
border-radius: 20px;
width: 65px;
font-size: 12px;
font-weight: 600;
text-align: center;
}
}
.portal-content-title {
font-weight: 600;
padding: 10px;
font-size: 22px;
line-height: 40px;
color: #333333;
word-break:break-all;
}
.type-kuang {
color: #666666;
border: 1px solid #666666;
}
.type-click {
color: #ffb30f !important;
border: 1px solid #ffb30f !important;
}
::v-deep .el-rate__icon {
font-size: 22px;
margin-right: 6px;
color: #ff8e00;
transition: 0.3s;
}
.ref-score {
// background: #e4e4e4;
// width: 64px;
// height: 32px;
// border-radius: 17px;
// line-height: 32px;
// // opacity: 0.24;
// color: #000;
// font-size: 14px;
// border: none;
}
.icon-small {
width: 20px;
height: 20px;
line-height: 20px;
vertical-align: middle;
}
.con-audio {
padding: 50px;
text-align: center;
.con-audio-title {
font-size: 16px;
font-weight: 700;
}
.con-audio-player {
padding: 20px 100px;
}
}
.hyper-link {
padding-left: 20px;
text-align: center;
padding-top: 100px;
.hyper-link-row {
padding: 20px;
}
}
.catalog-box {
background: #fff;
// padding: 15px 0px;
// box-shadow: 1px 1px 2px 2px #ededed;
.title {
font-size: 16px;
font-weight: 600;
color: #333333;
padding-left: 20px;
}
}
.collapse-title {
flex: 1 0 90%;
order: 1;
}
.el-collapse-item__header {
flex: 1 0 auto;
order: -1;
}
.course-interact {
height: 54px;
// padding-top: 10px;
// padding-right: 10px;
padding: 0 20px;
line-height: 54px;
background-color: #FFFFFF;
display: flex;
justify-content: space-between;
box-sizing: border-box;
}
.interact-btn {
margin-right: 10px;
}
.uc-badge {
margin-top: 10px;
margin-right: 40px;
}
.cres-list {
list-style-type: decimal;
margin: 0px;
li {
line-height: 30px;
}
.current {
color: #1ea0fa;
}
}
.uc-course {
display: flex;
justify-content: space-around;
border: 1px solid #f0f0f0;
padding: 10px;
.uc-course-img {
width: 200px;
img {
width: 200px;
border: 1px solid #f4f4f5;
}
}
.uc-course-info {
flex: 1;
line-height: 28px;
padding: 0px 10px;
.uc-course-name {
font-size: 18px;
font-weight: 700;
}
.uc-course-text {
color: #747474;
}
}
.uc-course-btns {
width: 150px;
}
}
.catalog-cell-state2 {
height: 24px;
width: 58px;
line-height: 20px;
border: 0px dotted #bed2f8;
padding: 3px 10px;
color: #ff8e00;
font-size: 12px;
border-radius: 6px;
margin-left: 2px;
background: #ffedd6;
}
.catalog-cell-state9 {
height: 24px;
width: 58px;
line-height: 20px;
border: 0px dotted #bed2f8;
padding: 3px 10px;
color: #3e7fff;
font-size: 12px;
border-radius: 6px;
margin-left: 2px;
background: #edf2fd;
// margin-left: 68%;
// background-color: #BED2F8;
}
.catalog-cell-state1 {
height: 24px;
width: 58px;
line-height: 20px;
border: 0px dotted #edf2fd;
border-radius: 6px;
padding: 3px 10px;
color: #ff3e3e;
font-size: 12px;
margin-left: 2px;
background: #fff0f0;
}
.catalog {
height: 500px;
max-width: 500px;
overflow: auto;
.catalog-row {
margin: 0px;
padding: 0px 10px 10px 10px;
.title-type {
width: 36px;
height: 24px;
padding: 2px 5px;
color: #666666;
border: 1px solid #666666;
margin-right: 8px;
}
ul {
padding: 0px;
margin: 0px;
li {
padding: 6px 0;
}
}
.catalog-cell {
line-height: 32px;
cursor: pointer;
list-style: none;
margin: 0px;
padding-left: 20px;
color: #5c5c5c;
}
}
}
.video-div {
position: absolute;
z-index: 999999999;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(101, 101, 101, 0.9);
.good {
display: flex;
justify-content: center;
align-items: center;
margin-top: 200px;
div {
line-height: 1;
margin: 0 15px;
.svg-icon {
width: 30px;
height: 30px;
}
}
div:nth-of-type(2) {
.svg-icon {
transform: scaleX(-1);
transform: rotate(180deg);
}
}
// margin-bottom: 50px;
// line-height: 20px;
// .el-link{
// font-size: 30px;
// color: #70a5f4;
// margin: 0 30px;
// }
}
// .score {
// display: flex;
// justify-content: center;
// align-items: center;
// padding-top: 20px
// }
}
::v-deep .el-tag {
background-color: #ecf5ff;
border-color: #409EFF;
display: inline-block;
height: 28px;
padding: 0 10px;
line-height: 28px;
font-size: 12px;
color: #3e7fff;
border-width: 1px;
border-style: solid;
border-radius: 0px;
box-sizing: border-box;
white-space: nowrap;
}
::v-deep .teacher .teacher-avator .teacher-text{
background: none;
border: none;
}
.teacher {
background-color: #ffffff;
display: flex;
border-top: none;
padding: 10px 0px;
.teacher-avator {
::v-deep .el-avatar {
width: 68px !important;
height: 68px !important;
border-radius: 0px;
}
.teacher-text {
width: 68px;
height: 68px;
div{
img{
width: 68px;
height: 68px;
}
}
// text-align: center;
// line-height: 68px;
// border-radius: 50%;
// color: #73adfe;
// border: 2px solid #73adfe;
// background: #d9e9ff;
}
}
.teacher-info {
flex: 1;
.teacher-name {
padding: 0px 5px 10px 10px;
}
.teacher-remark {
padding: 0px 5px 0 10px;
font-size: 14px;
color: #666666;
line-height: 20px;
}
}
}
.teachers {
background-color: #fff;
padding: 5px 15px 5px 10px;
margin-top: 0;
.top {
font-size: 16px;
font-weight: 600;
line-height: 50px;
}
}
.breadname {
margin-bottom: 15px;
}
//目录的样式更改
::v-deep .el-collapse-item{
.el-collapse-item__header{
// position: relative;
direction:rtl;
display: flex;
// justify-content;
justify-content: space-between;
// .el-collapse-item__arrow{
// float:right;
// }
// span{
// float:right;
// }
i{
display:none
}
}
}
.course-units{
.units-info{
padding: 0 30px;
height: 60px;
line-height: 60px;
font-size: 16px;
}
.units-active{
background: #F6F6F6;
color: #387DF7;
font-weight: 600;
img{
width: 18px;
height: 20px;
vertical-align: middle;
margin-right: 20px;
}
}
}
.more{
float: right;
}
.newcote-bottom{
span{
font-size: 14px;
color: #333333;
margin-right: 30px;
img{
width: 20px;
height: 24px;
vertical-align: middle;
}
}
}
.newcote-time{
width: 120px;
height: 30px;
border-radius: 4px;
border: 1px solid #3379FB;
font-size: 14px;
font-weight: 400;
color: #387DF7;;
text-align: center;
line-height: 30px;
img{
vertical-align: middle;
margin: 0 5px;
}
}
.newcote-text{
margin-top: 24px;
font-size: 14px;
color: #333333;
}
.mycote-content{
margin: 30px 0px;
box-sizing: border-box;
padding: 35px 30px;
height: 474px;
background-color: #fff;
.mycote-time{
color: #666;
font-size: 14px;
padding-bottom: 20px;
.sm{
width: 50px;
height: 22px;
border-radius: 10px;
border: 1px solid #3379FB;
color: #3379FB;
font-size: 12px;
line-height: 50px;
margin-left: 20px;
padding: 3px 10px;
}
}
.mycote-dibu{
margin: 50px 38%;
color: #999999;
font-size: 14px;
}
}
.newcote-content{
margin: 30px 0px;
box-sizing: border-box;
padding: 35px 30px;
height: 474px;
background-color: #F5F5F5 ;
}
.mynote{
// width: 100%;
margin: 35px 30px;
.mynote-tab{
width: 180px;
margin-top: 17px;
display: flex;
div{
font-size: 16px;
color: #666666;
flex: 1;
}
.noteactive a{
font-weight: 600;
color: #333333;
padding-bottom: 7px;
border-bottom: 4px solid #387DF7;
}
}
}
.coures-content{
height: 745px;
margin: 20px 80px;
background-color: #fff;
display: flex;
.coures-infobox{
width: 500px;
.coures-info{
height: 745px;
background-color: #fff;
box-sizing: border-box;
.hear-tab{
margin: 35px 30px;
width: 300px;
border-bottom: 1px solid #D8D8D8 ;
display: flex;
padding-bottom: 12px;
div{
flex: 1;
color: #666666;
}
.tab-active{
color: #333333;
font-weight: 600;
}
}
}
}
.coures-play{
flex: 1;
min-height: 745px;
}
}
.coures-title{
margin-left:82px;
font-size: 20px;
font-weight: 600;
color: #FFFFFF;
margin-top: 25px;
div{
float: left;
font-size: 20px;
font-weight: 600;
color: #FFFFFF;
line-height: 20px;
}
span{
float: left;
font-size: 16px;
font-weight: 400;
color: #FFFFFF;
margin-left: 27px;
}
h6{
float: left;
font-size: 16px;
font-weight: 600;
color: #FFFFFF;
margin: 0 20px;
}
}
::v-deep.el-breadcrumb__item:first-child .el-breadcrumb__inner a, .el-breadcrumb__inner .is-link {
color: #fff !important;
}
::v-deep.el-breadcrumb__item:last-child .el-breadcrumb__inner{
color: #fff !important;
}
::v-deep.hear-nav{
color: #fff !important;
}
.breadcrumb-nav{
color: #FFFFFF;
}
.coures-bg{
width: 100%;
height: 200px;
background: url('../../../public/images/couresdetail.png');
}
</style>