import { courseProcess, courseTypes, courseTypeTexts, htmlTypes, logicStatus, liveStatus, liveSources } from "../../model/enum"; import Api from "../../model/api"; import { getDataSet, getEventParam, showLoading, toast } from "../../utils/utils"; import Route from "../../model/route"; import { wxToPromise } from "../../utils/wx"; Page({ data: { id: '', type: '', item: {}, obj: {}, plan: {}, fileList: [], videoList: [], videoIndex: 0, courseTypeTexts: courseTypeTexts, courseTypesEnum: courseTypes, coverDefaultVal: '/images/kc.jpg', looseSecondTime: 3, //学习时长和视频总时长差3s就算学完 videoItem: {}, scanTime: 0, //从数据库中查询到的视频学习时长 oldNodeTime: -1, //已被记录的视频播放时长 nodeTime: 0, //课程状态 logicStatus.NO: 未学完 logicStatus.YES: 已学完 lessStatus: logicStatus.NO, show: false, //视频实时播放时长(拖拽进度条,currentTime为拖拽位置的时长) currentTime: 0, scanOkTime: 0, videoContext: null, tempFilePath: '', //10s 本地缓存一次视频时长 localRecordInterval: 10, //是否是从往期培训来的 isPre: logicStatus.NO, updatingStudyRecord: false, }, async onLoad(options) { let { id, detail, plan, type, isPre } = options; let obj = JSON.parse(detail); plan = JSON.parse(plan); wx.setNavigationBarTitle({ title: courseTypeTexts[type] }); const videoContext = wx.createVideoContext('myVideo3'); this.setData({ id, plan, obj, type, videoContext, isPre: Number(isPre) }, async () => { showLoading(); await this.getData(); wx.hideLoading() this.data.videoContext.seek(this.data.nodeTime) }) }, async getData() { //查询课程详细信息 const res = await Api.getCourseDetail(this.data.id, this.data.obj.eduStuId); if (this.data.obj.isOnline) { res.data.isQuestion = res.data.suitangUpper; } else { res.data.isQuestion = res.data.suitangLower; } let fileList = []; let videoItem = {}; if (res.data.enclosureUrl) { if (this.data.type == courseTypes.RECORD) { //videoItem 附加信息 videoItem = JSON.parse(res.data.enclosureUrl)[0]; if (this.data.isPre == logicStatus.YES) { // 如果是往期培训来的 this.setData({ nodeTime: 0, lessStatus: logicStatus.NO, videoItem }); return; } if (videoItem.verifyInterval) { //如果有人脸识别,设置人脸识别次数 let scanTime = videoItem.verifyInterval; this.setData({ scanTime }) } //获取学员本节课的学习记录 const less = await Api.getRecordedLesson({ stuId: this.data.obj.eduStuId, scheduleId: this.data.id }) if (less.data) { //课程学习状态 0:为学完 1:已学完 let lessStatus = less.data.status; //课程是否已经完成 let hasFulfilled = lessStatus == logicStatus.YES; //查询本地缓存里面记录的学习时长 let localRecordTime = this.getLessonRecordByLocal(); //数据库里面记录的学习时长 let serviceRecordTime = less.data.nodeTime || 0; console.log('course - localRecordTime -->', localRecordTime); // localRecordTime = hasFulfilled && localRecordTime >= videoItem.duration ? 0 : localRecordTime; //课程已学习的时长(秒), 取本地和数据中记录时长的最大值 let nodeTime = hasFulfilled ? 0 : Math.max(localRecordTime, serviceRecordTime); this.setData({ oldNodeTime: serviceRecordTime, nodeTime, lessStatus, videoItem }); if (!hasFulfilled && localRecordTime > serviceRecordTime) { //如果未完成课程学习 并且 本地记录的时长 > 数据库记录的时长(异常退出) ,更新数据库学习记录 this.changeProgress(); } //如果已经学完了 删除本地的学习时长缓存 hasFulfilled && this.removeLessonRecordByLocal(); // let lessStatus = less.data.status; // let nodeTime = lessStatus == logicStatus.YES ? 0 : less.data.nodeTime || 0; // this.setData({nodeTime, lessStatus, videoItem}) } else { //如果数据库里面未取到学习记录(学员本节课未学过) this.setData({ oldNodeTime: -1, nodeTime: 0, lessStatus: logicStatus.NO, videoItem }) } } else { fileList = JSON.parse(res.data.enclosureUrl); } } let videoList = []; if (this.data.type == courseTypes.PLAYBACK && res.data.videoPlaybackUrl) { videoList = res.data.videoPlaybackUrl.split(","); } this.compare(res.data, this.data.plan); this.setData({ item: res.data, fileList, videoList }) }, compare(newData, oldData) { if (!oldData) { return; } if (newData.courseProcess != oldData.courseProcess || newData.courseStatus != oldData.courseStatus || newData.liveStatus != oldData.liveStatus ) { const eventChannel = this.getOpenerEventChannel() eventChannel.emit('refresh'); } }, async downloadFile(e) { let url = getDataSet(e, "url"); let end = url.substr(url.lastIndexOf(".") + 1); showLoading('下载中...') let filePath = ""; if (this.data.tempFilePath) { filePath = this.data.tempFilePath; } else { const res = await wxToPromise("downloadFile", { url }); if (res.statusCode === 200) { filePath = res.tempFilePath this.setData({ tempFilePath: filePath }) } else { toast(`下载文档失败,请稍后重试${res.statusCode}:${res.errMsg}`) } } try { await wx.openDocument({ filePath }) } catch (e) { console.log(e) toast(`打开文档失败,请稍后重试${e.msg}`) } wx.hideLoading(); }, toTeacher(e) { let id = getDataSet(e, "id"); Route.toTeacher(id); }, clickImg(e) { let id = this.data.item.id; let eId = this.data.obj.eduStuId; Route.toNews(htmlTypes.SEAT, id, "座位图", eId); }, refresh(e) { return new Promise(async (resolve, reject) => { await this.getData(); const eventChannel = this.getOpenerEventChannel() eventChannel.emit('refresh'); resolve(true); }); }, changeVideo(e) { let index = getDataSet(e, "index"); this.setData({ videoIndex: index, }) }, // 以下是录播课的逻辑算法 待分离 async onUnload() { await this.changeProgress(); }, async onHide() { await this.changeProgress(); }, async changeProgress() { if (this.data.isPre == logicStatus.YES) { //如果是往期培训,不执行更新学习记录 return; } if (this.data.lessStatus == logicStatus.YES) { //如果已经学完了 不更新学习记录 return; } if (this.data.nodeTime === 0 && this.data.oldNodeTime === -1 && !this.data.videoItem.duration) { //如果课程还没查询到数据就退出当前页面,不更新学习记录 return; } if(this.data.updatingStudyRecord) { //如果正在更新学习记录,不继续调用接口(解决短时间内重复调用更新学习记录接口问题) return; } //只有是录播课的时候才会更新学习记录 if (this.data.type == courseTypes.RECORD) { this.data.updatingStudyRecord = true; const res = await Api.changeVideoProgress({ stuId: this.data.obj.eduStuId, scheduleId: this.data.id, nodeTime: this.data.nodeTime, oldNodeTime: this.data.oldNodeTime, status: this.data.lessStatus, duration: this.data.videoItem.duration }); // console.log('res -> ', res); if (res.data) { //如果学完了 // await this.getData(); //上面这句是否要删除????????????/ let { status, nodeTime } = res.data; this.setData({ nodeTime, lessStatus: status }); if (status == logicStatus.YES) { this.setData({ [`item.courseProcess`]: courseProcess.END }); //设定学习状态 const eventChannel = this.getOpenerEventChannel(); eventChannel.emit('refresh'); wx.showModal({ title: "恭喜你,视频已学完!", showCancel: false }); } } else { // 学习时长记录到本地缓存 start // 如果未完成视频学习 将学习记录缓存到本地 this.recordLessonByLocal(this.data.nodeTime); // 学习时长记录到本地缓存 end } this.data.updatingStudyRecord = false; } }, async timeUpdate(e) { if (this.data.isPre == logicStatus.YES) { //往期培训不记录播放时长 return; } let currentTime = parseInt(getEventParam(e, "currentTime")); let lessStatus = this.data.lessStatus; let unFulfilledFlag = lessStatus == logicStatus.NO; console.log("timeUpdate", currentTime, this.data.scanTime) // if (this.data.scanTime && unFulfilledFlag) { //需要处理验证人脸情况 // let flag = currentTime % this.data.scanTime; // if (flag == 0 && currentTime != this.data.scanOkTime && // currentTime >= this.data.nodeTime && currentTime != this.data.videoItem.duration) { // console.log("暂停,弹出人脸识别") // this.data.videoContext.exitFullScreen(); // this.data.videoContext.pause(); // this.setData({ // show: true, // currentTime // }); // } // } if (currentTime - this.data.nodeTime <= 1) { // 播放时长和被记录的时长的时间差<=1秒 说明没有快进视频 if (currentTime - this.data.nodeTime >= 0) { //给学员的学习时长重新赋值 👇 this.data.nodeTime = currentTime; // 如果学习时间和视频总时长相差在 this.data.looseSecondTime 秒内(现在设置是3s),就算完成 if ((this.data.nodeTime >= (this.data.videoItem.duration - this.data.looseSecondTime)) && unFulfilledFlag) { await this.changeProgress(); // //设定学习状态 // this.setData({ // lessStatus: logicStatus.YES // }); // //提示用户 // await wx.showModal({ // title: "恭喜你,视频已学完!", // showCancel: false // }); } // 原来的逻辑 👇 // if (this.data.nodeTime == this.data.videoItem.duration) { // if (unFulfilledFlag) { // await this.changeProgress(); // this.setData({ // lessStatus: logicStatus.YES // }); // await wx.showModal({ // title: "恭喜你,视频已学完!", // showCancel: false // }); // } // } } // 学习时长记录到本地缓存 start if (unFulfilledFlag && currentTime % this.data.localRecordInterval === 0) { //未学完课程时 才将学习时长记录到本地 this.recordLessonByLocal(currentTime); } // 学习时长记录到本地缓存 end this.setData({ currentTime }); } else { // 不可以快进的情况(课程未学完) if (unFulfilledFlag) { wx.showToast({ title: '视频未学完,不可以快进!', icon: 'none' }); this.data.videoContext.seek(this.data.nodeTime); } } }, recordLessonByLocal(time) { console.log('缓存视频学习时长', time); wx.setStorageSync(`stu${this.data.obj.eduStuId}-course${this.data.id}`, time); }, getLessonRecordByLocal() { return wx.getStorageSync(`stu${this.data.obj.eduStuId}-course${this.data.id}`) || 0; }, removeLessonRecordByLocal() { //如果课程已学完,移除本地学习时长的记录 wx.removeStorageSync(`stu${this.data.obj.eduStuId}-course${this.data.id}`); }, scanOk(e) { this.data.scanOkTime = getEventParam(e, "currentTime"); this.setData({ show: false, }); setTimeout(() => { this.data.videoContext.play(); }, 500) }, async toLive() { // if (this.data.item.liveStatus != liveStatus.LIVEEND) { // //如果直播课程的课程状态不为已结束,则点击按钮时先重新查询课程信息 // await this.refresh(); // } await this.refresh(); let item = this.data.item; let obj = this.data.obj; let courseLiveStatus = item.liveStatus; if (courseLiveStatus == liveStatus.LIVING) { Route.toLive(liveSources.DEFAULT, item.courseName || item.ceremonyName, item.id, obj.eduStuId, obj.eduStuName, item.courseThumbnailUrl); } else if (courseLiveStatus == liveStatus.LIVEEND) { toast('直播已结束!'); } else { toast('直播未开始!'); } } });