|
|
@@ -7,29 +7,30 @@
|
|
|
</div>
|
|
|
<div class="content-box">
|
|
|
<div class="left-max-big-box">
|
|
|
-
|
|
|
+ <coursewareComponent ref="coursewareComponent"></coursewareComponent>
|
|
|
</div>
|
|
|
<div class="right-max-big-box">
|
|
|
- <p class="title-p">{{learningData.data1}}</p>
|
|
|
- <div class="text-p" style="color:#666;">{{learningData.data2}}分钟丨{{learningData.data3}}学时丨{{learningData.data4}}积分</div>
|
|
|
- <div class="text-p">已学 {{learningData.data5}} / 总 {{learningData.data6}} 课件</div>
|
|
|
+ <p class="title-p">{{newData.coursewareName}}</p>
|
|
|
+ <div class="text-p" style="color:#666;">{{secondsToMinutes(newData.minLearningDuration)}}分钟丨{{newData.creditHours}}学时丨{{newData.points}}积分</div>
|
|
|
+ <!--<div class="text-p">已学 {{newData.learnedCoursewareCount}} / 总 {{newData.totalCoursewareCount}} 课件</div>-->
|
|
|
<div class="progress-box">
|
|
|
<p class="progress-title-box">学习进度</p>
|
|
|
<div class="progress-min-box">
|
|
|
- <el-progress :stroke-width="12" :percentage="learningData.data7"></el-progress>
|
|
|
+ <el-progress :stroke-width="12" :percentage="newData.progress?newData.progress:0"></el-progress>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="learning-for-max-big-box scrollbar-box">
|
|
|
<div class="for-max-big-box"
|
|
|
- v-for="(item,index) in learningData.dataList" :key="index">
|
|
|
- <div class="for-big-box" @click="checkLearningButton(index)"
|
|
|
+ v-for="(item,index) in newData.coursewares" :key="index">
|
|
|
+ <div class="for-big-box"
|
|
|
:class="checkLearningIndex == index ?'check-for-box':''">
|
|
|
- <p>{{item.listData1}}</p>
|
|
|
- <p>已学习:{{formatTime(item.listData3)}} / {{formatTime(item.listData4)}}</p>
|
|
|
- <p :class="item.listData5 ==1 ?'colorA':''">{{item.listData5==1?'已学完':'未学完'}}</p>
|
|
|
+ <!--<p>{{item.coursewareName}}</p>-->
|
|
|
+ <p></p>
|
|
|
+ <p>已学习:{{formatTime(item.learnedDuration)}} / {{formatTime(item.minLearningDuration)}}</p>
|
|
|
+ <p :class="item.learnStatus ==2 ?'colorA':(item.learnStatus ==1 ?'colorB':'')">{{item.learnStatus==2?'已学完':(item.learnStatus==1?'学习中':'未学完')}}</p>
|
|
|
</div>
|
|
|
<p class="for-button" @click="finishStudying(index)"
|
|
|
- v-if="item.listData5 == 0 && item.listData3 == item.listData4 && checkLearningIndex == index">
|
|
|
+ v-if="item.learnStatus != 2 && item.learnedDuration == item.minLearningDuration && checkLearningIndex == index">
|
|
|
若已完成学习,请点此确认
|
|
|
</p>
|
|
|
</div>
|
|
|
@@ -39,63 +40,145 @@
|
|
|
</div>
|
|
|
</template>
|
|
|
<script>
|
|
|
+ import StudyTimer from '@/utils/timerUtils/StudyTimer';
|
|
|
+ import { VerifySlider } from 'vue-verify-slider';
|
|
|
+ import coursewareComponent from "@/views/safetyEducationExaminationNew/components/coursewareComponent.vue";
|
|
|
+ import {
|
|
|
+ examUserCoursewareLearningDetail,examUserCoursewareLearningReportProgress,
|
|
|
+ examUserCoursewareLearningConfirmCompletion,examUserCoursewareLearningRestart
|
|
|
+ } from "@/api/safetyEducationExaminationNew/index";
|
|
|
export default {
|
|
|
name: 'index',
|
|
|
+ components: {
|
|
|
+ VerifySlider,
|
|
|
+ coursewareComponent,
|
|
|
+ },
|
|
|
data() {
|
|
|
return {
|
|
|
- learningData:{
|
|
|
- data1:"课程名称",
|
|
|
- data2:"20",
|
|
|
- data3:"1",
|
|
|
- data4:"3",
|
|
|
- data5:"0",
|
|
|
- data6:"2",
|
|
|
- data7:"20",
|
|
|
- dataList:[
|
|
|
- {
|
|
|
- listData1:'课件名称',
|
|
|
- listData2:1,
|
|
|
- listData3:320,
|
|
|
- listData4:600,
|
|
|
- listData5:0,
|
|
|
- },
|
|
|
- {
|
|
|
- listData1:'课件名称',
|
|
|
- listData2:1,
|
|
|
- listData3:600,
|
|
|
- listData4:600,
|
|
|
- listData5:0,
|
|
|
- },
|
|
|
- {
|
|
|
- listData1:'课件名称',
|
|
|
- listData2:1,
|
|
|
- listData3:600,
|
|
|
- listData4:600,
|
|
|
- listData5:1,
|
|
|
- },
|
|
|
+ coursewareId:null,
|
|
|
+ newData:{
|
|
|
+ coursewareName:"",
|
|
|
+ minLearningDuration:0,
|
|
|
+ creditHours:0,
|
|
|
+ points:0,
|
|
|
+ learnedCoursewareCount:0,
|
|
|
+ totalCoursewareCount:0,
|
|
|
+ progress:0,
|
|
|
+ coursewares:[
|
|
|
+ // {
|
|
|
+ // coursewareName:'视频课件名称',
|
|
|
+ // listData2:1,
|
|
|
+ // learnedDuration:590,
|
|
|
+ // minLearningDuration:600,
|
|
|
+ // learnStatus:2,
|
|
|
+ // attachmentPath:'http://192.168.1.8/statics/bigFile/20260801/0731dbcb-622b-4468-ade2-e20820b122eb.mp4',
|
|
|
+ // attachmentType:'mp4',
|
|
|
+ // materialType:'1',
|
|
|
+ // articleContent:'',
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // coursewareName:'docx课件名称',
|
|
|
+ // listData2:1,
|
|
|
+ // learnedDuration:600,
|
|
|
+ // minLearningDuration:600,
|
|
|
+ // learnStatus:0,
|
|
|
+ // attachmentPath:'http://192.168.1.8/statics/2026/08/01/b68f1b1d-99ea-44e0-94b5-4bad4ac3ff1f.docx',
|
|
|
+ // attachmentType:'.docx',
|
|
|
+ // materialType:'3',
|
|
|
+ // articleContent:'',
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // coursewareName:'xlsx课件名称',
|
|
|
+ // listData2:1,
|
|
|
+ // learnedDuration:600,
|
|
|
+ // minLearningDuration:600,
|
|
|
+ // learnStatus:1,
|
|
|
+ // attachmentPath:'http://192.168.1.8/statics/2026/08/01/270eb79e-627b-4fdf-9f1a-397bd9784d39.xlsx',
|
|
|
+ // attachmentType:'.xlsx',
|
|
|
+ // materialType:'3',
|
|
|
+ // articleContent:'',
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // coursewareName:'pdf课件名称',
|
|
|
+ // listData2:1,
|
|
|
+ // learnedDuration:600,
|
|
|
+ // minLearningDuration:600,
|
|
|
+ // learnStatus:1,
|
|
|
+ // attachmentPath:'http://192.168.1.8/statics/2026/08/01/b251bd69-120c-48d5-b662-c28e308cd61b.pdf',
|
|
|
+ // attachmentType:'.pdf',
|
|
|
+ // materialType:'3',
|
|
|
+ // articleContent:'',
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // coursewareName:'富文本课件名称',
|
|
|
+ // listData2:1,
|
|
|
+ // learnedDuration:600,
|
|
|
+ // minLearningDuration:600,
|
|
|
+ // learnStatus:1,
|
|
|
+ // attachmentPath:'',
|
|
|
+ // attachmentType:'',
|
|
|
+ // materialType:'4',
|
|
|
+ // articleContent:"<p><img style=\"max-width: 100%;\" src=\"../statics/2026/08/01/e2788e82-745c-4b49-82e0-ebb6f2a30713.jpeg\" alt=\"1.jpeg\"> </p>"
|
|
|
+ // },
|
|
|
+ // {
|
|
|
+ // coursewareName:'xlsx课件名称',
|
|
|
+ // listData2:1,
|
|
|
+ // learnedDuration:600,
|
|
|
+ // minLearningDuration:600,
|
|
|
+ // learnStatus:1,
|
|
|
+ // attachmentPath:'http://192.168.1.8/statics/2026/08/01/270eb79e-627b-4fdf-9f1a-397bd9784d39.xlsx',
|
|
|
+ // attachmentType:'.xlsx',
|
|
|
+ // materialType:'3',
|
|
|
+ // articleContent:'',
|
|
|
+ // },
|
|
|
],
|
|
|
},
|
|
|
+ //当前选中
|
|
|
checkLearningIndex:0,
|
|
|
-
|
|
|
+ //学习计时器
|
|
|
+ studyTimer: null,
|
|
|
+ //验证器弹窗状态
|
|
|
+ dialogVisible:false,
|
|
|
+ //验证器弹窗间隔时间
|
|
|
+ verificationTime:0,
|
|
|
+ //心跳回报时间
|
|
|
+ heartbeatValue:30,
|
|
|
}
|
|
|
},
|
|
|
created() {
|
|
|
|
|
|
},
|
|
|
mounted() {
|
|
|
-
|
|
|
+ this.initialization();
|
|
|
},
|
|
|
methods: {
|
|
|
- /*
|
|
|
- this.$router.push({
|
|
|
- name: 'Detail',
|
|
|
- params: {
|
|
|
- id: 1,
|
|
|
- title: '消息标题'
|
|
|
- }
|
|
|
- })
|
|
|
- this.$route.params.title
|
|
|
- */
|
|
|
+ //初始化
|
|
|
+ initialization(){
|
|
|
+ this.$set(this,'coursewareId',this.$route.params.coursewareId)
|
|
|
+ this.$nextTick(()=>{
|
|
|
+ this.examUserCoursewareLearningDetail();
|
|
|
+ })
|
|
|
+ },
|
|
|
+ //根据课件ID查询课件信息
|
|
|
+ examUserCoursewareLearningDetail(){
|
|
|
+ examUserCoursewareLearningDetail({ coursewareId:this.coursewareId }).then(response => {
|
|
|
+ response.data.coursewares=[
|
|
|
+ {
|
|
|
+ coursewareName:response.data.coursewareName,
|
|
|
+ learnedDuration:response.data.learnedDuration,
|
|
|
+ minLearningDuration:response.data.minLearningDuration,
|
|
|
+ learnStatus:response.data.learnStatus,
|
|
|
+ attachmentPath:response.data.attachmentPath,
|
|
|
+ attachmentType:response.data.attachmentType,
|
|
|
+ materialType:response.data.materialType,
|
|
|
+ articleContent:response.data.articleContent,
|
|
|
+ },
|
|
|
+ ]
|
|
|
+ this.$set(this, 'newData', response.data)
|
|
|
+ this.initTimer();//学习计时器
|
|
|
+ this.courseRendering(this.checkLearningIndex);//课件渲染
|
|
|
+ })
|
|
|
+ },
|
|
|
//返回
|
|
|
backPage() {
|
|
|
this.$router.back()
|
|
|
@@ -109,24 +192,62 @@
|
|
|
type: "warning"
|
|
|
}).then(function() {
|
|
|
}).then(() => {
|
|
|
-
|
|
|
+ self.examUserCoursewareLearningConfirmCompletion();
|
|
|
}).catch(() => {});
|
|
|
},
|
|
|
- //切换课件
|
|
|
- checkLearningButton(index){
|
|
|
+ //课件渲染
|
|
|
+ courseRendering(index){
|
|
|
+ let name = this.newData.coursewares[index].coursewareName;
|
|
|
+ let url = '';
|
|
|
+ let type = '';
|
|
|
+ if(this.newData.coursewares[index].materialType == 1){
|
|
|
+ //视频
|
|
|
+ type = 'video'
|
|
|
+ url = this.newData.coursewares[index].attachmentPath;
|
|
|
+ }else if(this.newData.coursewares[index].materialType == 3){
|
|
|
+ //文档
|
|
|
+ if(this.newData.coursewares[index].attachmentType == '.docx'){
|
|
|
+ type = 'docx'
|
|
|
+ }else if(this.newData.coursewares[index].attachmentType == '.xlsx'){
|
|
|
+ type = 'excel'
|
|
|
+ }else if(this.newData.coursewares[index].attachmentType == '.pdf'){
|
|
|
+ type = 'pdf'
|
|
|
+ }
|
|
|
+ url = this.newData.coursewares[index].attachmentPath;
|
|
|
+ }else if(this.newData.coursewares[index].materialType == 4){
|
|
|
+ //文章
|
|
|
+ type = 'text'
|
|
|
+ url = this.newData.coursewares[index].articleContent;
|
|
|
+ }
|
|
|
+ this.$refs['coursewareComponent'].initialize(name,url,type);
|
|
|
+ if(this.newData.coursewares[this.checkLearningIndex].learnStatus == 0){
|
|
|
+ this.$set(this.newData.coursewares[this.checkLearningIndex],'learnStatus',1);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //学习完成
|
|
|
+ examUserCoursewareLearningConfirmCompletion(){
|
|
|
let self = this;
|
|
|
- if(this.checkLearningIndex != index){
|
|
|
- this.$confirm('确认切换课件?', "警告", {
|
|
|
- confirmButtonText: "确认",
|
|
|
- cancelButtonText: "取消",
|
|
|
- type: "warning"
|
|
|
- }).then(function() {
|
|
|
- }).then(() => {
|
|
|
- self.$set(self,'checkLearningIndex',index);
|
|
|
- }).catch(() => {});
|
|
|
+ let obj = {
|
|
|
+ coursewareId:this.coursewareId,
|
|
|
+ courseId:0,
|
|
|
+ examId:0,
|
|
|
+ }
|
|
|
+ examUserCoursewareLearningConfirmCompletion(obj).then(response => {
|
|
|
+ this.$set(this.newData.coursewares[this.checkLearningIndex],'learnStatus',2);
|
|
|
+ this.msgSuccess(response.message)
|
|
|
+ })
|
|
|
+ },
|
|
|
+ //心跳接口
|
|
|
+ examUserCoursewareLearningReportProgress(){
|
|
|
+ let obj = {
|
|
|
+ coursewareId:this.coursewareId,
|
|
|
+ courseId:0,
|
|
|
+ examId:0,
|
|
|
+ duration:this.heartbeatValue,
|
|
|
}
|
|
|
+ examUserCoursewareLearningReportProgress(obj).then(response => {})
|
|
|
},
|
|
|
- //时间换算
|
|
|
+ //倒计时时间换算
|
|
|
formatTime(totalSeconds) {
|
|
|
if (typeof totalSeconds !== 'number' || totalSeconds <= 0) {
|
|
|
return '0秒';
|
|
|
@@ -140,8 +261,72 @@
|
|
|
} else {
|
|
|
return `${seconds}秒`;
|
|
|
}
|
|
|
+ },
|
|
|
+ //展示时间换算
|
|
|
+ secondsToMinutes(totalSeconds) {
|
|
|
+ if (typeof totalSeconds !== 'number' || totalSeconds <= 0) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ return Math.ceil(totalSeconds / 60);
|
|
|
+ },
|
|
|
+ /*=================================== 学习定时器 ===================================*/
|
|
|
+ // 初始化定时器
|
|
|
+ initTimer() {
|
|
|
+ let self = this;
|
|
|
+ if(this.newData.coursewares[this.checkLearningIndex].learnedDuration == this.newData.coursewares[this.checkLearningIndex].minLearningDuration){
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.studyTimer = new StudyTimer({
|
|
|
+ initialSeconds: self.newData.coursewares[self.checkLearningIndex].learnedDuration,
|
|
|
+ maxSeconds: self.newData.coursewares[self.checkLearningIndex].minLearningDuration,
|
|
|
+ onTick: (elapsedSeconds) => {
|
|
|
+ //每次计时
|
|
|
+ this.$set(self.newData.coursewares[self.checkLearningIndex],'learnedDuration',elapsedSeconds);
|
|
|
+ //心跳判断
|
|
|
+ if (elapsedSeconds % this.heartbeatValue === 0) {
|
|
|
+ //调用心跳方法
|
|
|
+ this.examUserCoursewareLearningReportProgress();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onMaxTimeReached: (elapsedSeconds) => {
|
|
|
+ //达到最大值
|
|
|
+ this.$set(self.newData.coursewares[self.checkLearningIndex],'learnedDuration',elapsedSeconds);
|
|
|
+ //调用心跳方法
|
|
|
+ this.examUserCoursewareLearningReportProgress();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ this.studyTimer.resume();
|
|
|
+ },
|
|
|
+ // 切换暂停/继续
|
|
|
+ handleToggle() {
|
|
|
+ if (!this.studyTimer) return;
|
|
|
+ if (this.studyTimer.isRunning) {
|
|
|
+ this.studyTimer.pause();
|
|
|
+ } else {
|
|
|
+ this.studyTimer.resume();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 清除定时器
|
|
|
+ clearTimer() {
|
|
|
+ if (this.studyTimer) {
|
|
|
+ this.studyTimer.clear();
|
|
|
+ this.studyTimer = null;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //乘法
|
|
|
+ accMul(arg1,arg2){
|
|
|
+ var m=0,s1=arg1.toString(),s2=arg2.toString();
|
|
|
+ try{m+=s1.split(".")[1].length}catch(e){}
|
|
|
+ try{m+=s2.split(".")[1].length}catch(e){}
|
|
|
+ return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m)
|
|
|
+ },
|
|
|
+ },
|
|
|
+ beforeDestroy() {
|
|
|
+ if (this.studyTimer) {
|
|
|
+ this.studyTimer.destroy();
|
|
|
+ this.studyTimer = null;
|
|
|
}
|
|
|
- }
|
|
|
+ },
|
|
|
}
|
|
|
</script>
|
|
|
<style scoped lang="scss">
|
|
|
@@ -155,23 +340,32 @@
|
|
|
padding:0;
|
|
|
box-shadow: 0 0 8px 1px rgba(0, 0, 0, 0.1);
|
|
|
margin:10px;
|
|
|
+ ::v-deep .el-progress .el-progress__text{
|
|
|
+ margin-left:10px;
|
|
|
+ margin-top:1px;
|
|
|
+ }
|
|
|
.content-box{
|
|
|
flex: 1;
|
|
|
display: flex;
|
|
|
overflow: hidden;
|
|
|
.left-max-big-box{
|
|
|
flex:1;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
background-color: #dedede;
|
|
|
- margin:40px 20px;
|
|
|
+ margin:20px 20px;
|
|
|
border-radius:10px;
|
|
|
overflow: hidden;
|
|
|
+ box-shadow: 0 0 15px rgba(0, 0, 0, 0.4);
|
|
|
+ border:1px solid #dedede;
|
|
|
}
|
|
|
.right-max-big-box{
|
|
|
- padding:40px 0;
|
|
|
+ padding:20px 0;
|
|
|
width:400px;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
overflow: hidden;
|
|
|
+ border-left: 1px solid #dedede;
|
|
|
.title-p{
|
|
|
font-size:16px;
|
|
|
font-weight:700;
|
|
|
@@ -235,7 +429,7 @@
|
|
|
position: absolute;
|
|
|
bottom: 16px;
|
|
|
right: 16px;
|
|
|
- color:#fff!important;
|
|
|
+ color:#fff;
|
|
|
background-color: #999;
|
|
|
border-radius:4px;
|
|
|
width:60px;
|
|
|
@@ -244,6 +438,12 @@
|
|
|
}
|
|
|
.colorA{
|
|
|
background-color: #0183fa!important;
|
|
|
+ color:#fff!important;
|
|
|
+ }
|
|
|
+ .colorB{
|
|
|
+ background-color: #fff!important;
|
|
|
+ border:1px solid #0183fa!important;
|
|
|
+ color:#0183fa!important;
|
|
|
}
|
|
|
}
|
|
|
.for-button{
|