2024-03-25 19:16:41 +08:00
|
|
|
|
<template>
|
|
|
|
|
<view>
|
|
|
|
|
<!-- <cu-custom bgColor="bg-gradual-blueness" :isBack="true">-->
|
|
|
|
|
<!-- <block slot="backText">返回</block>-->
|
|
|
|
|
<!-- <block slot="content">学习详情</block>-->
|
|
|
|
|
<!-- </cu-custom>-->
|
|
|
|
|
<view id="fixed">
|
|
|
|
|
<view v-if="videoSrc">
|
|
|
|
|
<video
|
|
|
|
|
id="video"
|
|
|
|
|
:src="videoSrc"
|
|
|
|
|
:poster="videoPoster"
|
|
|
|
|
autoplay
|
|
|
|
|
controls
|
|
|
|
|
style="width: 100vw"
|
|
|
|
|
:show-progress="false"
|
|
|
|
|
:enable-progress-gesture="false"
|
|
|
|
|
@play="fnPlay"
|
|
|
|
|
@pause="fnPause"
|
|
|
|
|
@ended="fnEnded"
|
|
|
|
|
@timeupdate="fnTimeUpdate"
|
|
|
|
|
/>
|
|
|
|
|
</view>
|
|
|
|
|
<image
|
|
|
|
|
v-if="!videoSrc"
|
|
|
|
|
:src="baseImgPath+info.COVERPATH"
|
|
|
|
|
class="video_bg"
|
|
|
|
|
/>
|
|
|
|
|
<view class="title">
|
|
|
|
|
<text>{{ info.CURRICULUMNAME }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="tabs">
|
|
|
|
|
<uv-tabs :list="[{name:'视频目录'},{name:'详情'}]" @change="tabsCurrent=$event.index" :scrollable="false"/>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="show_container" v-show="tabsCurrent === 1">
|
|
|
|
|
<scroll-view scroll-y :style="{ height: `calc(100vh - ${scrollHeight})` }">
|
|
|
|
|
<view class="introduce">{{ info.CURRICULUMINTRODUCE }}</view>
|
|
|
|
|
<view class="image">
|
|
|
|
|
<image :src="baseImgPath+info.COVERPATH" alt=""/>
|
|
|
|
|
</view>
|
|
|
|
|
</scroll-view>
|
|
|
|
|
</view>
|
|
|
|
|
<view v-show="tabsCurrent === 0">
|
|
|
|
|
<scroll-view scroll-y :style="{ height: `calc(100vh - ${scrollHeight})` }">
|
|
|
|
|
<view class="video_container">
|
|
|
|
|
<view
|
|
|
|
|
class="video_list"
|
|
|
|
|
v-for="(item, index) in videoList"
|
|
|
|
|
:key="index"
|
|
|
|
|
>
|
|
|
|
|
<view class="video_list_title">
|
|
|
|
|
<image src="/static/study/copy-one.png"/>
|
|
|
|
|
<view>{{ item.NAME }}</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="video_list_main">
|
|
|
|
|
<view v-if="item.nodes && item.nodes.length > 0">
|
|
|
|
|
<view
|
|
|
|
|
class="video_list_main_wrap"
|
|
|
|
|
v-for="(item1, index1) in item.nodes"
|
|
|
|
|
:key="index1"
|
|
|
|
|
@click="fnVideoSwitching(item1, 1, index, index1)"
|
|
|
|
|
>
|
|
|
|
|
<view class="video_list_main_wrap_tit line-1">
|
|
|
|
|
{{ item1.COURSEWARENAME }}
|
|
|
|
|
</view>
|
|
|
|
|
<view class="video_list_main_wrap_info">
|
|
|
|
|
<text class="fcb">进度:{{ item1.percent }}%</text>
|
|
|
|
|
<text>{{ secondsCount(item1.VIDEOTIME) }}</text>
|
|
|
|
|
<image src="/static/study/play.png"/>
|
|
|
|
|
<button
|
|
|
|
|
class="cu-btn round bg-blue sm"
|
|
|
|
|
@click.stop="
|
|
|
|
|
fnNavigationExercises(item1.VIDEOCOURSEWARE_ID)
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
课后练习
|
|
|
|
|
</button>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view v-else>
|
|
|
|
|
<view
|
|
|
|
|
class="video_list_main_wrap"
|
|
|
|
|
@click="fnVideoSwitching(item, 0, index, 0)"
|
|
|
|
|
>
|
|
|
|
|
<view class="video_list_main_wrap_tit line-1">
|
|
|
|
|
{{ item.COURSEWARENAME }}
|
|
|
|
|
</view>
|
|
|
|
|
<view class="video_list_main_wrap_info">
|
|
|
|
|
<text class="fcb">进度:{{ item.percent }}%</text>
|
|
|
|
|
<text>{{ secondsCount(item.VIDEOTIME) }}</text>
|
|
|
|
|
<image src="/static/study/play.png"/>
|
|
|
|
|
<button
|
|
|
|
|
class="cu-btn round bg-blue sm"
|
|
|
|
|
@click.stop="fnNavigationExercises(item.VIDEOCOURSEWARE_ID)"
|
|
|
|
|
>
|
|
|
|
|
课后练习
|
|
|
|
|
</button>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</scroll-view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
import {basePath, loginUser, baseImgPath} from "@/common/tool";
|
|
|
|
|
|
|
|
|
|
let faceAuthTimer; // 人脸认证计时器
|
|
|
|
|
let throttleTimer;
|
|
|
|
|
let throttleFlag;
|
2024-05-20 18:03:21 +08:00
|
|
|
|
let videoContext;
|
2024-03-25 19:16:41 +08:00
|
|
|
|
export default {
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
baseImgPath,
|
|
|
|
|
CLASSCURRICULUM_ID: '',
|
|
|
|
|
CLASS_ID: '',
|
|
|
|
|
STUDENT_ID: '',
|
|
|
|
|
ISFACE: '',
|
|
|
|
|
info: {}, // 课程信息
|
|
|
|
|
videoList: [], // 视频列表
|
|
|
|
|
tabsCurrent: 0, // 当前tabs
|
|
|
|
|
randomTime: 0, // 随机人脸识别认证时间
|
|
|
|
|
// randomTime: new Date().getTime() + 60 * 1000, // 1分钟 随机人脸识别认证时间 测试
|
|
|
|
|
videoData: {
|
|
|
|
|
CURRICULUM_ID: '',
|
|
|
|
|
VIDEOCOURSEWARE_ID: '',
|
|
|
|
|
CHAPTER_ID: '',
|
|
|
|
|
VIDEOTIME: '',
|
|
|
|
|
}, // 当前播放视频的对象
|
|
|
|
|
index: 0, // 一级目录index
|
|
|
|
|
nodeIndex: 0, // 二级目录index
|
|
|
|
|
hasNodes: '0', // 是否存在二级目录(1是 0否)
|
|
|
|
|
changeVideoPlayTime: 0, // 当前视频播放进度
|
|
|
|
|
serverVideoPlayTime: 0, // 服务器的当前视频播放进度
|
|
|
|
|
videoSrc: "", // 视频地址
|
|
|
|
|
videoPoster: "", // 视频封面图
|
|
|
|
|
scrollHeight: '0px', // scroll-view减去的高度
|
2024-05-20 18:03:21 +08:00
|
|
|
|
// videoContext: null, // 视频上下文
|
|
|
|
|
submitTimeWaitForCount: 0, // 提交时间等待次数
|
2024-03-25 19:16:41 +08:00
|
|
|
|
verification:false,// 是否人脸认证
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onLoad(options) {
|
|
|
|
|
this.CLASSCURRICULUM_ID = options.CLASSCURRICULUM_ID;
|
|
|
|
|
this.CLASS_ID = options.CLASS_ID;
|
|
|
|
|
this.STUDENT_ID = options.STUDENT_ID;
|
|
|
|
|
this.ISFACE = options.ISFACE;
|
|
|
|
|
this.fnInit();
|
|
|
|
|
},
|
|
|
|
|
onReady() {
|
|
|
|
|
uni.createSelectorQuery()
|
|
|
|
|
.select("#fixed")
|
|
|
|
|
.boundingClientRect((data) => {
|
|
|
|
|
this.scrollHeight = data.height + 'px';
|
|
|
|
|
})
|
|
|
|
|
.exec();
|
|
|
|
|
},
|
|
|
|
|
mounted() {
|
|
|
|
|
uni.$on('verification', () => {
|
|
|
|
|
this.verification = true
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
beforeDestroy() {
|
|
|
|
|
uni.$off('verification')
|
|
|
|
|
},
|
|
|
|
|
watch: {
|
|
|
|
|
verification() {
|
|
|
|
|
if (this.verification) {
|
|
|
|
|
this.fnInit();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
post(url, data) {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
if (data && data.loading !== false) {
|
|
|
|
|
uni.showLoading({
|
|
|
|
|
title: "加载中",
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
uni.request({
|
|
|
|
|
url: basePath + url,
|
|
|
|
|
data: {
|
|
|
|
|
CORPINFO_ID: loginUser.CORPINFO_ID,
|
|
|
|
|
USER_ID: loginUser.USER_ID,
|
|
|
|
|
...data,
|
|
|
|
|
},
|
|
|
|
|
method: "POST",
|
|
|
|
|
header: {
|
|
|
|
|
"Content-type": "application/x-www-form-urlencoded",
|
|
|
|
|
},
|
|
|
|
|
success: (res) => {
|
|
|
|
|
if (res.statusCode !== 200) {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "网络错误请重试," + res.statusCode,
|
|
|
|
|
icon: "error",
|
|
|
|
|
duration: 2000,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
if (data && data.loading !== false) {
|
|
|
|
|
uni.hideLoading();
|
|
|
|
|
}
|
|
|
|
|
if (res.data.result === "success") {
|
|
|
|
|
resolve(res.data);
|
|
|
|
|
} else {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: res.data.msg || "系统开小差了",
|
|
|
|
|
icon: "none",
|
|
|
|
|
duration: 2000,
|
|
|
|
|
});
|
|
|
|
|
reject(res.data);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
if (data && data.loading !== false) {
|
|
|
|
|
uni.hideLoading();
|
|
|
|
|
}
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "网络错误请重试",
|
|
|
|
|
icon: "none",
|
|
|
|
|
duration: 2000,
|
|
|
|
|
});
|
|
|
|
|
reject(err);
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
throttle(func, wait = 500, immediate = true) {
|
|
|
|
|
if (immediate) {
|
|
|
|
|
if (!throttleFlag) {
|
|
|
|
|
throttleFlag = true
|
|
|
|
|
// 如果是立即执行,则在wait毫秒内开始时执行
|
|
|
|
|
typeof func === 'function' && func()
|
|
|
|
|
throttleTimer = setTimeout(() => {
|
|
|
|
|
throttleFlag = false
|
|
|
|
|
}, wait)
|
|
|
|
|
}
|
|
|
|
|
} else if (!throttleFlag) {
|
|
|
|
|
throttleFlag = true
|
|
|
|
|
// 如果是非立即执行,则在wait毫秒内的结束处执行
|
|
|
|
|
throttleTimer = setTimeout(() => {
|
|
|
|
|
throttleFlag = false
|
|
|
|
|
typeof func === 'function' && func()
|
|
|
|
|
}, wait)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
secondsCount(second) {
|
|
|
|
|
if (!second) return 0;
|
|
|
|
|
const h = parseInt((second / 60 / 60) % 24, 10);
|
|
|
|
|
const m = parseInt((second / 60) % 60, 10);
|
|
|
|
|
const s = parseInt(second % 60, 10);
|
|
|
|
|
return (
|
|
|
|
|
(h < 10 ? "0" + h : h) +
|
|
|
|
|
":" +
|
|
|
|
|
(m < 10 ? "0" + m : m) +
|
|
|
|
|
":" +
|
|
|
|
|
(s < 10 ? "0" + s : s)
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
async fnInit() {
|
|
|
|
|
await this.fnGetData();
|
|
|
|
|
if (this.ISFACE === "1") {
|
|
|
|
|
if (this.verification) {
|
|
|
|
|
await this.fnGetVideoPlayInfo();
|
|
|
|
|
} else {
|
|
|
|
|
uni.showModal({
|
|
|
|
|
title: "温馨提示",
|
|
|
|
|
confirmText: "同意并继续",
|
|
|
|
|
content:
|
|
|
|
|
"重要提醒:尊敬的用户,根据规定我们会在您学习过程中多次进行人脸识别认证,为了保护您的隐私请您在摄像设备视野内确保衣冠整齐。",
|
|
|
|
|
success: (res) => {
|
|
|
|
|
if (res.cancel) {
|
|
|
|
|
uni.navigateBack();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
async fnGetData() {
|
|
|
|
|
const resData = await this.post('/app/stagestudentrelation/getMyTask',{
|
|
|
|
|
CLASSCURRICULUM_ID: this.CLASSCURRICULUM_ID,
|
|
|
|
|
CLASS_ID: this.CLASS_ID,
|
|
|
|
|
STUDENT_ID: this.STUDENT_ID,
|
|
|
|
|
});
|
|
|
|
|
if (resData.pd.VIDEOLIST && resData.pd.VIDEOLIST.length > 0) {
|
|
|
|
|
resData.pd.VIDEOLIST.forEach((item) => {
|
|
|
|
|
if (item.nodes && item.nodes.length > 0) {
|
|
|
|
|
item.nodes.forEach((nodeItem) => {
|
|
|
|
|
let percent;
|
|
|
|
|
if (nodeItem.PLAYCOUNT > 0) {
|
|
|
|
|
percent = 100;
|
|
|
|
|
} else {
|
|
|
|
|
const resourceTime = parseFloat(nodeItem.RESOURCETIME || 0);
|
|
|
|
|
const videoTime = parseFloat(nodeItem.VIDEOTIME || 0);
|
|
|
|
|
const temp = Math.floor(
|
|
|
|
|
(resourceTime / videoTime) * 10000,
|
|
|
|
|
).toString();
|
|
|
|
|
percent = temp.substring(0, temp.length) / 100;
|
|
|
|
|
}
|
|
|
|
|
nodeItem.percent = percent;
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
let percent;
|
|
|
|
|
if (item.PLAYCOUNT > 0) {
|
|
|
|
|
percent = 100;
|
|
|
|
|
} else {
|
|
|
|
|
const resourceTime = parseFloat(item.RESOURCETIME || 0);
|
|
|
|
|
const videoTime = parseFloat(item.VIDEOTIME || 0);
|
|
|
|
|
const temp = Math.floor(
|
|
|
|
|
(resourceTime / videoTime) * 10000,
|
|
|
|
|
).toString();
|
|
|
|
|
percent = temp.substring(0, temp.length) / 100;
|
|
|
|
|
}
|
|
|
|
|
item.percent = percent;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
this.info = resData.pd;
|
|
|
|
|
this.videoList = resData.pd.VIDEOLIST;
|
|
|
|
|
},
|
|
|
|
|
async fnVideoSwitching(videoData, hasNodes, index, index1) {
|
2024-05-20 18:03:21 +08:00
|
|
|
|
videoContext && videoContext.pause();
|
|
|
|
|
this.submitTimeWaitForCount = 0;
|
2024-03-25 19:16:41 +08:00
|
|
|
|
if (this.changeVideoPlayTime !== 0) {
|
|
|
|
|
await this.fnSubmitPlayTime("0", this.changeVideoPlayTime);
|
|
|
|
|
this.changeVideoPlayTime = 0;
|
|
|
|
|
}
|
|
|
|
|
this.videoData = videoData;
|
|
|
|
|
this.firstIndex = index;
|
|
|
|
|
this.nodeIndex = index1;
|
|
|
|
|
this.hasNodes = hasNodes.toString();
|
|
|
|
|
if (this.ISFACE === "1") {
|
|
|
|
|
await this.fnNavigationFaceAuth();
|
|
|
|
|
} else {
|
|
|
|
|
this.videoSrc = "";
|
|
|
|
|
this.videoPoster = "";
|
|
|
|
|
await this.fnGetVideoPlayInfo();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
async fnGetVideoPlayInfo() {
|
|
|
|
|
const resData = await this.post('/app/audioOrVideo/getPlayInfo',{
|
|
|
|
|
VIDEOCOURSEWARE_ID: this.videoData.VIDEOCOURSEWARE_ID,
|
|
|
|
|
CURRICULUM_ID: this.videoData.CURRICULUM_ID,
|
|
|
|
|
});
|
|
|
|
|
this.videoSrc = resData.PLAYURLMP4 || resData.PLAYURL;
|
|
|
|
|
this.videoPoster = resData.COVERURL;
|
|
|
|
|
await this.fnGetVideoPlayProgress();
|
|
|
|
|
},
|
|
|
|
|
async fnGetVideoPlayProgress() {
|
|
|
|
|
const resData = await this.post('/app/coursestudyvideorecord/getVideoProgress',{
|
|
|
|
|
VIDEOCOURSEWARE_ID: this.videoData.VIDEOCOURSEWARE_ID,
|
|
|
|
|
CURRICULUM_ID: this.videoData.CURRICULUM_ID,
|
|
|
|
|
CLASS_ID: this.CLASS_ID,
|
|
|
|
|
STUDENT_ID: this.STUDENT_ID,
|
|
|
|
|
});
|
|
|
|
|
if (!resData.pd.RESOURCETIME) {
|
|
|
|
|
await this.fnSubmitPlayTime("0", 0);
|
|
|
|
|
}
|
2024-05-20 18:03:21 +08:00
|
|
|
|
console.log('resData.pd.RESOURCETIME:'+resData.pd.RESOURCETIME)
|
|
|
|
|
this.serverVideoPlayTime = Math.floor(resData.pd.RESOURCETIME) || 0
|
|
|
|
|
console.log('this.serverVideoPlayTime:'+this.serverVideoPlayTime)
|
2024-03-25 19:16:41 +08:00
|
|
|
|
if (this.ISFACE === "1") {
|
|
|
|
|
if (this.verification) {
|
|
|
|
|
this.fnCreateVideo();
|
|
|
|
|
} else {
|
|
|
|
|
this.fnCreateVideo();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
this.fnCreateVideo();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
fnCreateVideo() {
|
2024-05-20 18:03:21 +08:00
|
|
|
|
videoContext = null;
|
|
|
|
|
videoContext = uni.createVideoContext("video");
|
|
|
|
|
videoContext.play();
|
|
|
|
|
console.log('fnCreateVideo:'+this.serverVideoPlayTime)
|
|
|
|
|
this.serverVideoPlayTime !== 0 && videoContext.seek(this.serverVideoPlayTime);
|
2024-03-25 19:16:41 +08:00
|
|
|
|
},
|
2024-05-20 18:03:21 +08:00
|
|
|
|
async fnTimeUpdate(event) {
|
2024-03-25 19:16:41 +08:00
|
|
|
|
const currentTime = event.detail.currentTime;
|
|
|
|
|
if (currentTime - this.serverVideoPlayTime >= 10) {
|
|
|
|
|
uni.navigateBack();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-05-20 18:03:21 +08:00
|
|
|
|
//app视频自带bug,判断当前视频进度与服务器进度差,如果小于10秒,则退出重新进
|
|
|
|
|
if(currentTime !== 0 && Math.abs(currentTime - this.serverVideoPlayTime) > 10) {
|
|
|
|
|
videoContext.pause();
|
|
|
|
|
uni.showModal({
|
|
|
|
|
title: "提示",
|
|
|
|
|
content: "app开发环境问题,偶现当前视频进度获取不准确,为了防止进度被覆盖,请退出重新进入!",
|
|
|
|
|
showCancel:false,
|
|
|
|
|
success: (res) => {
|
|
|
|
|
uni.navigateBack();
|
|
|
|
|
return;
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
2024-03-25 19:16:41 +08:00
|
|
|
|
this.changeVideoPlayTime = currentTime;
|
|
|
|
|
if (currentTime - this.serverVideoPlayTime >= 5) {
|
2024-05-20 18:03:21 +08:00
|
|
|
|
this.serverVideoPlayTime = currentTime;
|
|
|
|
|
this.submitTimeWaitForCount = ++this.submitTimeWaitForCount;
|
|
|
|
|
}
|
|
|
|
|
if (this.submitTimeWaitForCount === 6) {
|
|
|
|
|
this.submitTimeWaitForCount = 0;
|
2024-03-25 19:16:41 +08:00
|
|
|
|
await this.fnSubmitPlayTime("0", currentTime);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
async fnSubmitPlayTime(IS_END, RESOURCETIME) {
|
2024-05-20 18:03:21 +08:00
|
|
|
|
if(!this.videoData.VIDEOCOURSEWARE_ID) {
|
|
|
|
|
return
|
|
|
|
|
}
|
2024-03-25 19:16:41 +08:00
|
|
|
|
const resData = await this.post('/app/coursestudyvideorecord/save',{
|
|
|
|
|
USERNAME: loginUser.NAME,
|
|
|
|
|
VIDEOCOURSEWARE_ID: this.videoData.VIDEOCOURSEWARE_ID,
|
|
|
|
|
CURRICULUM_ID: this.videoData.CURRICULUM_ID,
|
|
|
|
|
CHAPTER_ID: this.videoData.CHAPTER_ID,
|
|
|
|
|
RESOURCETIME,
|
|
|
|
|
IS_END,
|
|
|
|
|
CLASS_ID: this.CLASS_ID,
|
|
|
|
|
CLASSCURRICULUM_ID: this.CLASSCURRICULUM_ID,
|
|
|
|
|
STUDENT_ID: this.STUDENT_ID,
|
|
|
|
|
loading: false,
|
|
|
|
|
});
|
|
|
|
|
this.serverVideoPlayTime = RESOURCETIME;
|
|
|
|
|
if (this.hasNodes === "1") {
|
|
|
|
|
let percent = 0;
|
|
|
|
|
if (resData.pd.PLAYCOUNT > 0) {
|
|
|
|
|
percent = 100;
|
|
|
|
|
} else {
|
|
|
|
|
const resourceTime = parseFloat(resData.pd.RESOURCETIME || 0);
|
|
|
|
|
const videoTime = parseFloat(
|
|
|
|
|
this.videoList[this.firstIndex].nodes[this.nodeIndex].VIDEOTIME ||
|
|
|
|
|
0,
|
|
|
|
|
);
|
|
|
|
|
const temp = Math.floor(
|
|
|
|
|
(resourceTime / videoTime) * 10000,
|
|
|
|
|
).toString();
|
|
|
|
|
percent = temp.substring(0, temp.length) / 100;
|
|
|
|
|
}
|
|
|
|
|
this.videoList[this.firstIndex].nodes[this.nodeIndex].percent = percent;
|
|
|
|
|
} else {
|
|
|
|
|
let percent = 0;
|
|
|
|
|
if (resData.pd.PLAYCOUNT > 0) {
|
|
|
|
|
percent = 100;
|
|
|
|
|
} else {
|
|
|
|
|
const resourceTime = parseFloat(resData.pd.RESOURCETIME || 0);
|
|
|
|
|
const videoTime = parseFloat(
|
|
|
|
|
this.videoList[this.firstIndex].VIDEOTIME || 0,
|
|
|
|
|
);
|
|
|
|
|
const temp = Math.floor(
|
|
|
|
|
(resourceTime / videoTime) * 10000,
|
|
|
|
|
).toString();
|
|
|
|
|
percent = temp.substring(0, temp.length) / 100;
|
|
|
|
|
}
|
|
|
|
|
this.videoList[this.firstIndex].percent = percent;
|
|
|
|
|
}
|
|
|
|
|
if (resData.pd.CANEXAM === "1") {
|
2024-05-20 18:03:21 +08:00
|
|
|
|
videoContext.pause();
|
2024-03-25 19:16:41 +08:00
|
|
|
|
uni.showModal({
|
|
|
|
|
title: "提示",
|
|
|
|
|
content: "当前班级内所有课程均已学完,是否直接参加考试?",
|
|
|
|
|
confirmButtonText: "是",
|
|
|
|
|
cancelButtonText: "否",
|
|
|
|
|
success: (res) => {
|
|
|
|
|
if (res.confirm) {
|
2024-05-23 11:13:48 +08:00
|
|
|
|
videoContext && videoContext.exitFullScreen()
|
2024-03-25 19:16:41 +08:00
|
|
|
|
uni.navigateTo({
|
|
|
|
|
url: '/pages/application/onlinexxks/course_exam?STAGEEXAMPAPERINPUT_ID=' + resData.paper.STAGEEXAMPAPERINPUT_ID + '&STAGEEXAMPAPER_ID=' + resData.paper.STAGEEXAMPAPERINPUT_ID + '&CLASS_ID=' + this.CLASS_ID + '&POST_ID=' + resData.pd.POST_ID + '&STUDENT_ID=' + this.STUDENT_ID + '&NUMBEROFEXAMS=' + resData.pd.NUMBEROFEXAMS + '&entrySite=video_study'
|
|
|
|
|
})
|
|
|
|
|
} else if (res.cancel) {
|
2024-05-20 18:03:21 +08:00
|
|
|
|
videoContext.play();
|
2024-03-25 19:16:41 +08:00
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
fnEnded() {
|
2024-05-20 18:03:21 +08:00
|
|
|
|
if (this.changeVideoPlayTime - this.serverVideoPlayTime >= 10) {
|
|
|
|
|
uni.navigateBack();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-03-25 19:16:41 +08:00
|
|
|
|
this.changeVideoPlayTime = 0;
|
|
|
|
|
this.fnSubmitPlayTime("1", 0);
|
2024-05-20 18:03:21 +08:00
|
|
|
|
videoContext.pause();
|
2024-03-25 19:16:41 +08:00
|
|
|
|
this.fnClearInterval();
|
|
|
|
|
},
|
|
|
|
|
fnPlay() {
|
|
|
|
|
if (this.ISFACE === "1") {
|
|
|
|
|
this.fnClearInterval();
|
|
|
|
|
if (this.randomTime === 0) {
|
|
|
|
|
this.randomTime = new Date().getTime() + 60 * 1000 * 10;
|
|
|
|
|
}
|
|
|
|
|
faceAuthTimer = setInterval(async () => {
|
|
|
|
|
if (new Date().getTime() >= this.randomTime) {
|
2024-05-20 18:03:21 +08:00
|
|
|
|
this.randomTime = 0;
|
2024-03-25 19:16:41 +08:00
|
|
|
|
await this.fnSubmitPlayTime("0", this.changeVideoPlayTime);
|
|
|
|
|
await this.fnNavigationFaceAuth();
|
|
|
|
|
}
|
|
|
|
|
}, 1000);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
fnPause() {
|
|
|
|
|
this.fnClearInterval();
|
|
|
|
|
},
|
|
|
|
|
fnClearInterval() {
|
|
|
|
|
faceAuthTimer && clearInterval(faceAuthTimer);
|
|
|
|
|
faceAuthTimer = null;
|
|
|
|
|
},
|
|
|
|
|
async fnNavigationFaceAuth() {
|
|
|
|
|
this.verification = false
|
|
|
|
|
const params = JSON.stringify({
|
|
|
|
|
CLASS_ID: this.CLASS_ID,
|
|
|
|
|
STUDENT_ID: this.STUDENT_ID,
|
|
|
|
|
CURRICULUM_ID: this.videoData.CURRICULUM_ID,
|
|
|
|
|
CHAPTER_ID: this.videoData.CHAPTER_ID,
|
|
|
|
|
VIDEOCOURSEWARE_ID: this.videoData.VIDEOCOURSEWARE_ID,
|
|
|
|
|
})
|
2024-05-20 18:03:21 +08:00
|
|
|
|
if (videoContext && videoContext.fullScreen) {
|
|
|
|
|
videoContext.exitFullScreen()
|
|
|
|
|
}
|
2024-05-15 14:16:58 +08:00
|
|
|
|
const resData = await this.post('/app/user/getUserFace', {
|
|
|
|
|
USERNAME: loginUser.NAME,
|
|
|
|
|
USER_ID: loginUser.USER_ID,
|
|
|
|
|
});
|
|
|
|
|
if (!resData.pd.PORTRAIT) {
|
|
|
|
|
uni.showModal({
|
|
|
|
|
title: "温馨提示",
|
|
|
|
|
confirmText: "确定",
|
|
|
|
|
content: "您当前还未进行人脸认证,请先进行认证",
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
uni.navigateTo({
|
|
|
|
|
url: '/pages/application/onlinexxks/face/index?params=' + params
|
|
|
|
|
})
|
|
|
|
|
}
|
2024-03-25 19:16:41 +08:00
|
|
|
|
},
|
|
|
|
|
fnNavigationExercises(VIDEOCOURSEWARE_ID) {
|
|
|
|
|
uni.navigateTo({
|
|
|
|
|
url: '/pages/application/onlinexxks/exercises?VIDEOCOURSEWARE_ID=' + VIDEOCOURSEWARE_ID
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
.video_bg, #video {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 450upx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.title {
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
padding: 20upx;
|
|
|
|
|
font-size: 34upx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tabs {
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
padding: 0 40upx;
|
|
|
|
|
margin-top: 20upx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.video_container {
|
|
|
|
|
width: 100%;
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
padding: 40upx;
|
|
|
|
|
margin-top: 20upx;
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
|
|
|
|
.video_list_title {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-left: -10upx;
|
|
|
|
|
|
|
|
|
|
image {
|
|
|
|
|
width: 48upx;
|
|
|
|
|
height: 48upx;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.video_list_main {
|
|
|
|
|
margin-top: 20upx;
|
|
|
|
|
|
|
|
|
|
.video_list_main_wrap {
|
|
|
|
|
width: 100%;
|
|
|
|
|
background: #fafafa;
|
|
|
|
|
padding: 20upx;
|
|
|
|
|
border-radius: 10upx;
|
|
|
|
|
font-size: 26upx;
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
color: #666666;
|
|
|
|
|
margin-bottom: 20upx;
|
|
|
|
|
|
|
|
|
|
.video_list_main_wrap_tit {
|
|
|
|
|
width: 100%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.video_list_main_wrap_info {
|
|
|
|
|
flex: 1;
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-top: 10upx;
|
|
|
|
|
|
|
|
|
|
image {
|
|
|
|
|
width: 28upx;
|
|
|
|
|
height: 28upx;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.fcb {
|
|
|
|
|
color: #3c9cff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.show_container {
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
padding: 40upx;
|
|
|
|
|
|
|
|
|
|
.introduce {
|
|
|
|
|
word-break: break-all;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.image {
|
|
|
|
|
margin-top: 20upx;
|
|
|
|
|
|
|
|
|
|
image {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 400upx;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|