ZhiYeJianKang_PeiXun/Song.Site/Templates/Web/_Public/Scripts/CourseStudy.js

562 lines
24 KiB
JavaScript
Raw Normal View History

2025-02-20 15:41:53 +08:00
var couid = $api.querystring("couid");
var vdata = new Vue({
data: {
//数据实体
account: {}, //当前账号信息
course: {}, //当前课程
outline: {}, //当前课程章节
subject: {}, //当前专业
outlines: [], //当前课程的章节列表(树形)
access: [], //附件列表
events: [], //视频事件
messages: [], //咨询留言
//当前章节的视频信息
video: {
url: '', //视频路径
total: 0, //总时长
playTime: 0, //当前播放时间,单位:毫秒
playhistime: 0, //历史播放时间
studytime: 0, //累计学习时间
percent: 0 //完成度(百分比)
},
playtime: 0, //当前播放时间,单位:秒
playpercent: 0, //当前播放完成度百分比
//状态
state: {}, //课程状态
couid: $api.querystring("couid"),
olid: $api.querystring("olid"),
median: false, //分隔线折叠状态
titState: 'loading', //左侧选项卡的状态
rightState: 'outline', //右侧选项卡状态章节outline,交流chat
outlineLoaded: false, //右侧章节列表加载中
studylogUpdate: false, //学习记录是否在递交中
studylogState: 0, //学习记录提交状态1为成功-1为失败
switchSubtitle: $api.cookie("switchSubtitle_" + $api.querystring("couid")) == "true" ? true : false, //弹幕开关
//控件
player: null //播放器
},
watch: {
//课程状态
state: function (val) {
if (vdata.state.isNull) vdata.titState = 'isNull';
if (vdata.state.isAccess) vdata.titState = 'isAccess';
if (vdata.state.isQues) vdata.titState = 'isQues';
if (vdata.state.isContext) vdata.titState = 'isContext';
if (vdata.state.isLive) vdata.titState = 'isLive';
if (vdata.state.existVideo) vdata.titState = 'existVideo';
//if (!vdata.state.canStudy) vdata.titState = 'isNull';
if (vdata.state.DeskAllow) return;
//视频播放
if (vdata.state.canStudy && (vdata.state.existVideo || vdata.state.isLive))
vdata.videoPlay(vdata.state);
},
//左侧选项卡切换
titState: function (val) {
if (vdata.playready()) {
vdata.titState == 'existVideo' ? vdata.player.play() : vdata.player.pause();
}
},
//弹幕开关
'switchSubtitle': function (val, old) {
if (val != old)
$api.cookie("switchSubtitle_" + vdata.couid, val);
},
//播放进度时间变化
playtime: function (val) {
vdata.video.studytime++;
//当前视频播放进度百分比
var per = Math.floor(vdata.video.studytime <= 0 ? 0 : vdata.video.studytime / vdata.video.total * 100);
vdata.playpercent = per;
//触发视频事件
vdata.videoEvent(vdata.playtime);
},
//播放进度百分比变化,
playpercent: function (val, oldval) {
//console.log('当前播放进度百分比:'+val);
//学习记录提交
if (val <= 100) vdata.videoLog(val);
}
},
methods: {
//知识库的点击事件
knlClick: function () {
new top.PageBox('课程知识库', 'Knowledges.ashx?couid=' + vdata.couid, 100, 100, null, window.name).Open();
},
//章节列表的点击事件
outlineClick: function (olid, event) {
var url = $api.setpara("olid", olid);
history.pushState({}, null, url);
vdata.olid = olid;
vdata.titState = 'loading';
if (event != null) event.preventDefault();
//获取当前章节状态,和专业信息
$api.bat(
$api.get("Outline/ForID", {
id: olid
}),
$api.get("Outline/state", {
olid: olid
})
).then(axios.spread(function (ol, state) {
if (ol.data.success && state.data.success) {
vdata.outline = ol.data.result;
vdata.state = state.data.result;
if (!vdata.state.isLive && vdata.state.PlayTime / 1000 > 0) {
/*
vdata.$confirm('是否从上次进度播放?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(function() {
vdata.videoSeek(vdata.state.PlayTime / 1000);
window.setTimeout(function() {
if (vdata.playready()) vdata.player.play();
}, 500);
}).catch(function() {
});*/
}
//视频播放记录
var result = state.data.result;
vdata.video.studytime = isNaN(result.StudyTime) ? 0 : result.StudyTime;
vdata.video.playhistime = isNaN(result.PlayTime) ? 0 : result.PlayTime / 1000;
window.setTimeout(function () {
vdata.outlineLoaded = true;
}, 100);
//获取视频事件
if (state.data.result.existVideo && vdata.outline) {
$api.get("Outline/VideoEvents", {
olid: vdata.outline.Ol_ID
}).then(function (req) {
if (req.data.success) {
vdata.events = req.data.result;
} else {
alert("视频事件加载失败!详情:\r" + req.data.message);
}
});
}
} else {
if (!ol.data.success) alert("章节信息加载异常!详情:\r" + ol.data.message);
if (!state.data.success) alert("章节状态加载异常!详情:\r" + state.data.message);
}
}));
//获取留言列表
vdata.msgGet();
},
//播放器是否准备好
playready: function () {
if (vdata.player != null) {
return vdata.player._isReady && vdata.player.engine;
}
return false;
},
//视频开始播放
videoPlay: function (state) {
if (vdata.player != null) {
vdata.player.destroy();
vdata.player = null;
}
if (!vdata.state.isLive) { //点播
vdata.player = new QPlayer({
url: state.urlVideo,
container: document.getElementById("videoplayer"),
autoplay: true,
});
} else { //直播
vdata.player = new QPlayer({
url: state.urlVideo,
container: document.getElementById("livebox"),
isLive: true,
autoplay: true
});
}
if (vdata.player != null) {
vdata.player.on("loading", vdata.videoready);
vdata.player.on("ready", vdata.videoready);
vdata.player.on("timeupdate", function (currentTime, totalTime) {
vdata.video.total = parseInt(totalTime);
vdata.video.playTime = currentTime; //详细时间,精确到毫秒
vdata.playtime = parseInt(currentTime);
//学习完成度,最大为百分百
vdata.video.percent = Math.floor(vdata.video.studytime <= 0 ? 0 : vdata.video.studytime / vdata.video.total * 1000) / 10;
vdata.video.percent = vdata.video.percent > 100 ? 100 : vdata.video.percent;
});
vdata.player.on("seeked", function () {
vdata.playtime = vdata.playready() ? vdata.player.currentTime : 0;
window.setTimeout(function () {
if (vdata.playready()) vdata.player.pause();
}, 50);
});
vdata.player.on("play", function (e) {
if (window.videoFixed) vdata.player.pause();
});
}
},
//播放器加载后的事件
videoready: function () {
//隐藏全屏按钮
var fullbtn = document.getElementsByClassName("qplayer-fullscreen");
for (var i = 0; i < fullbtn.length; i++) {
fullbtn[i].style.display = "none";
}
//隐藏设置按钮(播放倍速也禁用了)
var setbtn = document.getElementsByClassName("qplayer-settings-btn");
for (var i = 0; i < setbtn.length; i++) {
//setbtn[i].style.display = "none";
}
//给video对象增加属性
var video = document.querySelector("video");
video.setAttribute("x5-playsinline", "");
video.setAttribute("playsinline", true);
video.setAttribute("webkit-playsinline", true);
video.setAttribute("x-webkit-airplay", true);
video.setAttribute("x5-video-player-type", "h5");
video.setAttribute("x5-video-player-fullscreen", "");
video.setAttribute("x5-video-orientation", "portraint");
},
//视频播放跳转
videoSeek: function (second) {
if (vdata.playready()) {
vdata.player.seek(second);
}
},
//学习记录记录
videoLog: function (per) {
if (vdata.studylogUpdate) return;
var interval = 1; //间隔百分比多少递交一次记录
if (vdata.video.total <= 5 * 60) interval = 10; //5分钟内的视频
else if (vdata.video.total <= 10 * 60) interval = 5; //10分钟的视频5%递交一次
else if (vdata.video.total <= 30 * 60) interval = 2; //30分钟的视频2%递交一次
if (per > 0 && per < (100 + interval) && per % interval == 0) {
if (!vdata.outline) return;
$api.post("Course/StudyLog", {
couid: vdata.course.Cou_ID,
olid: vdata.outline.Ol_ID,
playTime: vdata.playtime,
studyTime: vdata.video.studytime,
totalTime: vdata.video.total
}, function () {
vdata.studylogUpdate = true;
}, function () {
vdata.studylogUpdate = false;
}).then(function (req) {
if (!req.data.success) {
if (vdata.playready()) {
vdata.player.pause();
vdata.player.destroy();
vdata.player = null;
}
alert(req.data.message);
return;
}
vdata.studylogState = 1;
window.setTimeout(function () {
vdata.studylogState = 0;
}, 2000);
}).catch(function (err) {
vdata.studylogState = -1;
//alert(err);
window.setTimeout(function () {
vdata.studylogState = 0;
}, 2000);
});
}
},
//视频事件的触发
videoEvent: function (playtime) {
if (vdata.events.length < 1) return;
var curr = null;
for (var ev in vdata.events) {
if (vdata.events[ev].Oe_TriggerPoint == playtime) {
curr = vdata.events[ev];
break;
}
}
if (curr == null) return;
//视频暂停
if (vdata.playready()) vdata.player.pause();
var box = new MsgBox();
box.OverEvent = function () {
if (vdata.playready()) vdata.player.play();
}
if (curr.Oe_EventType == 1)
box.Init("提示:" + curr.Oe_Title, curr.Oe_Context, curr.Oe_Width, curr.Oe_Height, "alert").Open();
if (curr.Oe_EventType == 2)
box.Init("知识点:" + curr.Oe_Title, curr.Oe_Context, curr.Oe_Width, curr.Oe_Height, "alert").Open();
if (curr.Oe_EventType == 3) {
var items = eval(curr.Oe_Datatable);
var context = curr.Oe_Context + "<div class='quesBox'>";
for (var i in items) {
if (items[i].item == "") continue;
context += "<div onclick='vdata.videoEventClick(" + items[i].iscorrect + ",-1)'>" +
(Number(i) + 1) + "、" + items[i].item + "</div>";
}
context += "</div>";
context += "<div id='event_error'>回答错误</div>";
box.Init("提问" + curr.Oe_Title, context, curr.Oe_Width, curr.Oe_Height, "null").Open();
}
if (curr.Oe_EventType == 4) {
var items = eval(curr.Oe_Datatable);
var context = curr.Oe_Context + "<div class='quesBox'>";
for (var i in items) {
if (items[i].item == "") continue;
context += "<div onclick='vdata.videoEventClick(null," + items[i].point + ")'>" +
(Number(i) + 1) + "、" + items[i].item + " - (跳转到:" + items[i].point + "秒)</div>";
}
context += "</div>";
box.Init("反馈:" + curr.Oe_Title, context, curr.Oe_Width, curr.Oe_Height, "alert").Open();
}
},
//视频事件的点击操作
videoEventClick: function (iscorrect, seek) {
//视频事件的问题
if (iscorrect != null) {
if (iscorrect) MsgBox.Close();
if (!iscorrect) {
var err = document.getElementById("event_error");
err.style.height = 20 + 'px';
err.style.opacity = 1;
window.setTimeout(function () {
var err = document.getElementById("event_error");
err.style.height = 0 + 'px';
err.style.opacity = 0;
}, 1000);
}
}
//视频跳转
if (iscorrect == null && seek > 0) {
if (!vdata.playready()) return;
vdata.player.seek(seek);
MsgBox.Close();
}
},
//发送消息
msgSend: function () {
var msg = document.getElementById("messageinput").value;
if ($api.trim(msg) == '') return;
var span = Date.now() - Number($api.cookie("msgtime"));
if (span / 1000 < 10) {
vdata.$notify({
message: '不要频繁发消息!',
position: 'bottom-right'
});
return;
}
$api.cookie("msgtime", Date.now());
$api.post("message/add", {
acc: '',
msg: msg,
playtime: vdata.playtime,
couid: vdata.couid,
olid: vdata.olid
}).then(function (req) {
var d = req.data;
if (d.success) {
document.getElementById("messageinput").value = '';
vdata.msgGet();
} else {
alert("信息添加发生异常!详情:\r" + d.message);
}
});
},
//获取当前章节的留言信息
msgGet: function () {
if (!vdata.olid || vdata.olid < 1) return;
$api.post("message/count", {
olid: vdata.olid,
order: 'asc',
count: 100
}).then(function (req) {
var d = req.data;
if (d.success) {
vdata.messages = d.result;
window.setTimeout(function () {
var dl = document.getElementById("chatlistdl");
document.getElementById("chatlist").scrollTop = dl.offsetHeight;
}, 1000);
} else {
alert("留言信息加载异常!详情:\r" + d.message);
}
}).catch(function (err) {
//alert("msgGet方法存在错误"+err);
});
},
init: function () {
}
},
created: function () {
var couid = $api.querystring("couid");
$api.bat(
$api.get("Outline/tree", {
couid: couid
}),
$api.get("Course/ForID", {
id: couid
})).then(axios.spread(function (ol, cur) {
if (ol.data.success && cur.data.success) {
if (ol.data.result.length < 1) throw "没有课程章节";
vdata.outlines = ol.data.result;
if (vdata.olid == '') vdata.olid = ol.data.result[0].Ol_ID;
vdata.outlineClick(vdata.olid, null);
vdata.course = cur.data.result;
document.title = vdata.course.Cou_Name;
$api.get("Subject/ForID", {
id: vdata.course.Sbj_ID
}).then(function (subject) {
if (subject.data.success) {
vdata.subject = subject.data.result;
} else {
if (!subject.data.success) throw "课程所属专业加载异常!详情:\r" + subject.data.message;
}
}).catch(function (err) {
alert(err);
});
vdata.msgGet();
} else {
if (!ol.data.success) throw "章节列表加载异常!详情:\r" + ol.data.message;
if (!cur.data.success) throw "课程信息加载异常!详情:\r" + cur.data.message;
}
})).catch(function (err) {
alert(err);
});
//当前登录学员
$api.get("Account/Current", {}, null, null).then(function (req) {
if (req.data.success) {
vdata.account = req.data.result;
}
});
//定时刷新(加载)咨询留言
window.setInterval('vdata.msgGet()', 1000 * 10);
},
mounted: function () {
//视频上面的漂浮信息(学员姓名和电话),防录屏
window.setInterval(function () {
var acc = document.getElementById("accinfo");
if (acc == null) return;
if (acc.parentNode.offsetHeight == 0 || acc.parentNode.offsetWidth == 0) return;
//移动速度
window.acctop = window.acctop ? window.acctop : Math.ceil(Math.random() * 100) / 10;
window.accleft = window.accleft ? window.accleft : Math.ceil(Math.random() * 100) / 10;
//获取当前坐标
var top = Number(acc.style.top.replace('px', ''));
var left = Number(acc.style.left.replace('px', ''));
//转向
if (top < 0 || top > acc.parentNode.offsetHeight - acc.offsetHeight) window.acctop = -window.acctop;
if (left < 0 || left > acc.parentNode.offsetWidth - acc.offsetWidth) window.accleft = -window.accleft;
//移动
acc.style.top = (top < 0 ? 0 : (top > acc.parentNode.offsetHeight - acc.offsetHeight ? acc.parentNode.offsetHeight - acc.offsetHeight : top + window.acctop)) + "px";
acc.style.left = (left < 0 ? 0 : (left > acc.parentNode.offsetWidth - acc.offsetWidth ? acc.parentNode.offsetWidth - acc.offsetWidth : left + window.accleft)) + "px";
}, 200);
},
});
vdata.$mount('#body');
window.onload = function () {
this.vdata.init();
}
window.onblur = function () {
if (vdata.playready()) {
//if (vdata.state.isLive || vdata.state.existVideo)
if (!vdata.state.SwitchPlay)
vdata.player.pause();
}
}
window.onfocus = function () {
//如果有视频事件弹出,则窗体获取焦点时,视频并不播放
if ($("div[type=MsgBox]").size() > 0) return;
if (vdata.playready()) {
//vdata.titState == 'existVideo' && vdata.state.isLive ? vdata.player.play() : vdata.player.pause();
//只有当处于视频状态时才播放
if (vdata.titState == 'existVideo' || vdata.titState == 'isLive')
vdata.player.play();
}
}
window.onresize = function () {
window.setTimeout(function () {
var str = '';
[22, 9, 4, 5, 15].forEach(x => str += String.fromCharCode(0x60 + x));
var v = document.querySelector(str);
if (!v) return;
var styles = document.defaultView.getComputedStyle(v.parentNode, null);
var posi = styles.getPropertyValue('position');
window.videoFixed = posi == 'fixed';
v.style.display = window.videoFixed ? 'none' : '';
!window.videoFixed && $("div[type=MsgBox]").size() < 1 ? v.play() : v.pause();
}, 100);
}
//全局过滤器,日期格式化
Vue.filter('date', function (value, fmt) {
if ($api.getType(value) != 'Date') return value;
var o = {
"M+": value.getMonth() + 1,
"d+": value.getDate(),
"h+": value.getHours(),
"m+": value.getMinutes(),
"s+": value.getSeconds()
};
if (/(y+)/.test(fmt))
fmt = fmt.replace(RegExp.$1, (value.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(fmt))
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return fmt;
});
//******* 附件列表
Vue.component('accessory', {
props: ['uid', 'isbuy'],
data: function () {
return {
datas: [], //附件列表
msg: '' //提示信息
}
},
watch: {
'uid': function (val, old) {
var th = this;
th.msg = '';
$api.get("Outline/Accessory", { uid: val }).then(function (acc) {
if (acc.data.success) {
th.datas = acc.data.result;
} else {
th.msg = "附件信息加载异常!详情:\r" + acc.data.message;
}
}).catch(function (err) {
th.msg = err;
});
},
'isbuy': function (val, old) {
}
},
methods: {
//附件的点击事件
accessClick: function (file, tit, event) {
var exist = file.substring(file.lastIndexOf(".") + 1).toLowerCase();
if (exist == "pdf") {
event.preventDefault();
var box = new PageBox(tit, $api.pdfViewer(file), 100, 100, null, window.name);
box.Open();
}
return false;
}
},
template: '<div id="accessory">\
<div v-if="!isbuy" style="color:red;">课程未购买资料不提供下载或预览</div>\
<a v-if="isbuy" v-for="(item,index) in datas" target="_blank":href="item.As_FileName"\
v-on:click="accessClick(item.As_FileName,item.As_Name,$event)"\
:download="item.As_Name">{{index+1}}{{item.As_Name}}\
</a>\
<div v-if="!isbuy" v-for="(item,index) in datas" >\
{{index+1}}{{item.As_Name}}\
</div>\
<div class="noInfo">{{msg}}</div>\
</div>'
});