y595705120 2 年 前
コミット
7a6468535a

+ 6 - 3
src/assets/css/main.css

@@ -63,7 +63,7 @@ form {
 }
 
 .p-wrap-full {
-    width: 1200px;
+    width: 1360px;
     margin-left: auto;
     margin-right: auto;
 }
@@ -206,7 +206,7 @@ input:focus{
   position: relative;
   height: 110px;
   width: 100%;
-  
+
   bottom: 0;
   /* padding-top:30px; */
   position: relative;
@@ -225,11 +225,14 @@ a, span {
 }
 
 .m-right-block {
-  width: 1009px;
+  width: 1160px;
   min-height: 700px;
   background: #fff;
   border-left: 1px solid #e8e8e8;
 }
+.m-right-big {
+  width: 1200px !important;
+}
 
 .m-right-block .right-block-bd {
   padding: 13px 20px;

+ 115 - 16
src/containers/center/play/components/iMedia.vue

@@ -5,19 +5,70 @@
       <strong>/</strong>
       <span>{{media.duration|useTime}}</span>
     </h2>
-    <el-row style="width: 900px;">
-      <el-col :span="8" style="width: 250px;" v-show="!closeFace">
-        <video ref="video" v-show="isnotbtn" width="240" height="180" autoplay></video>
-        <canvas ref="canvas" v-show="ontakebtn" width="240" height="180"></canvas>
-      </el-col>
-
-      <el-col :span="16" style="width: 640px;">
+    <el-row style="width: 1100px;">
+      <el-col :span="18" style="width: 700px;">
         <video-player id="myVideo" class="video-player-box" ref="videoPlayer" :playsinline="true" @pause="onPlayerPause($event)"
           @play="onPlayerStart($event)" @ready="playerReadied" @timeupdate="onPlayerTimeupdate($event)" @ended="onPlayerEnded($event)"
           :globalOptions="{controls:true}" :options="options">
         </video-player>
       </el-col>
+
+      <el-col :span="6" style="width: 400px;float:right;">
+        <div class="account-tit" style="align-items: center;width: 360px;margin-left: 30px">
+          <a :class="{'current':required===1}"  @click="required=1" class="">必修课程</a>
+          <a :class="{'current':required===0}"  @click="required=0" class="">选修课程</a>
+        </div>
+
+
+        <el-menu v-if="required==1" style="width: 400px;font-size: 10px;">
+          <ul class="m-chapter-list">
+            <li v-for="(item, index) in chapter.required" :key="index"  :class="{'current':item.name==activeChapter}">
+              <a href="javascript:void(0)" style="text-decoration: none" @click="goState(item)"
+                class="ng-binding"> {{parseInt(item.xs/10)}}学时 {{item.name}}</a>
+
+              <div class="sub-list" v-if="item.name==activeChapter" >
+                <a v-for="(subItem,index)  in list" :key="subItem.id" v-if="subItem.chapterName == activeChapter"
+                  @click="goSubState(subItem, index)" :class="{'current':subItem.name==activeName}">
+                  <span style="width: 8px;height: 8px;">
+                    <el-progress :percentage="subItem.percent" type="circle" :width="16" :height="16"  :format="()=>{return ''}" v-if="subItem.percent>=100" color="green"></el-progress>
+                    <el-progress :percentage="subItem.percent" type="circle" :width="16" :height="16" :format="()=>{return ''}" v-else-if="subItem.percent>=50" color="cyan"></el-progress>
+                    <el-progress :percentage="subItem.percent" type="circle" :width="16" :height="16" :format="()=>{return ''}" v-else></el-progress>
+                  </span>
+                  <span style="margin-left: 16px;"> {{subItem.name}} </span>
+                  </a>
+              </div>
+            </li>
+          </ul>
+        </el-menu>
+
+        <el-menu v-if="required==0">
+          <ul class="m-chapter-list" style="width: 400px;font-size: 10px;">
+            <li v-for="(item, index) in chapter.normal" :key="index"  :class="{'current':item.name==activeChapter}">
+              <a href="javascript:void(0)" style="text-decoration: none" @click="goState(item)"
+                class="ng-binding">{{parseInt(item.xs/10)}}学时 {{item.name}}</a>
+
+              <div class="sub-list pt10" v-if="item.name==activeChapter" >
+                <a v-for="(subItem,index) in list" :key="subItem.id" v-if="subItem.chapterName == activeChapter"
+                  @click="goSubState(subItem, index)" :class="{'current':subItem.name==activeName}">
+                    <span style="width: 8px;height: 8px;">
+                      <el-progress :percentage="subItem.percent" type="circle" :width="16" :height="16"  :format="()=>{return ''}" v-if="subItem.percent>=100" color="green"></el-progress>
+                      <el-progress :percentage="subItem.percent" type="circle" :width="16" :height="16" :format="()=>{return ''}" v-else-if="subItem.percent>=50" color="cyan"></el-progress>
+                      <el-progress :percentage="subItem.percent" type="circle" :width="16" :height="16" :format="()=>{return ''}" v-else></el-progress>
+                    </span>
+                    <span style="margin-left: 16px;"> {{subItem.name}} </span>
+                  </a>
+                </a>
+              </div>
+            </li>
+          </ul>
+            <!-- <el-menu-item v-for="item in chapter.normal" :key="item">{{item}}</el-menu-item> -->
+        </el-menu>
+      </el-col>
     </el-row>
+    <div class="left-float" v-if="!closeFace" v-drag>
+        <video ref="video" v-show="isnotbtn" width="240" height="180" autoplay></video>
+        <canvas ref="canvas" v-show="ontakebtn" width="240" height="180"></canvas>
+    </div>
 
   </div>
 </template>
@@ -42,11 +93,14 @@
     data() {
       return {
         timer: false,
+        required:1,
         tickNum: 0,
         prevTime: 0,
         isReady: false,
         isnotbtn: false,
         ontakebtn: false,
+        activeChapter:'',
+        activeName:'',
         curTimes: 0,
         errMsg: '',
         errCount: 0,
@@ -56,7 +110,7 @@
     components: {
       videoPlayer
     },
-    props: [ 'media', 'options', 'heartbeat', 'maxErrorCount', 'collectBeat','closeFace'],
+    props: [ 'media', 'options', 'heartbeat', 'maxErrorCount', 'collectBeat','closeFace', 'chapter', 'list'],
     filters: {
       useTime(val) {
         let timestr = ""
@@ -73,6 +127,21 @@
       this.stopTick()
       this.reportErr("play", 'destroy');
     },
+    directives: {
+      drag(el, bindings) {
+        el.onmousedown = function(e) {
+          var disx = e.pageX - el.offsetLeft
+          var disy = e.pageY - el.offsetTop
+          document.onmousemove = function (e) {
+            el.style.left = e.pageX - disx + 'px'
+            el.style.top = e.pageY - disy + 'px'
+          }
+          document.onmouseup = function() {
+            document.onmousemove = document.onmouseup = null
+          }
+        }
+      }
+    },
     computed: {
       player() {
         return this.$refs.videoPlayer.player
@@ -85,6 +154,15 @@
     created() {
       this.startTick()
       this.startMonitor();
+      this.activeChapter = this.media.chapterName;
+      this.activeName = this.media.name
+    },
+    watch:{
+      "media.name"(){
+        console.log("media.name")
+         this.activeChapter = this.media.chapterName;
+         this.activeName = this.media.name
+      }
     },
     methods: {
       photograph() {
@@ -120,6 +198,16 @@
       destroyTimer() {
         if (this.timer) clearInterval(this.timer);
       },
+      goState(item){
+        if( item.name == this.activeChapter){
+          this.activeChapter = ""
+        }else{
+          this.activeChapter = item.name;
+        }
+      },
+      goSubState(item, index){
+        this.$emit('loadMedia', item, index)
+      },
       callCamera() {
         // H5调用电脑摄像头API
         if( this.closeFace){
@@ -177,7 +265,6 @@
         this.timer = setTimeout(this.tryTick, 1 * 1000);
       },
       playerReadied(audio) {
-        console.log("playerReadied", audio)
         let that = this;
         let {
           position,
@@ -193,9 +280,9 @@
       },
       onPlayerTimeupdate(player) {
         let curTimes = player.cache_.currentTime;
-        if (curTimes > 30 && curTimes > this.media.position + 10) {
+        if (curTimes > 30 && curTimes > this.curTimes + 2) {
           console.log("return", curTimes, this.media.position)
-          player.currentTime(this.media.position);
+          player.currentTime(this.curTimes);
           return;
         }
         this.curTimes = curTimes
@@ -203,7 +290,9 @@
       setposition(position) {
         if (position > this.media.duration) position = this.media.duration;
         let player = this.$refs.videoPlayer.player;
+        console.log("setposition", position)
         player.currentTime(position);
+        this.curTimes = position;
         if (this.media.isFinish) return;
         if (this.media.position >= this.media.duration - 10 && !this.media.isFinish) {
           this.tick(true)
@@ -244,7 +333,7 @@
         this.reportErr("play", 'start');
         this.startTick();
         this.onPlay = true
-        this.tickNum = 0 
+        this.tickNum = 0
       },
       reportErr(action, msg) {
         httpServer("course.report", {
@@ -273,8 +362,6 @@
           console.log("finish")
           return;
         }
-        console.log(this.heartbeat, this.collectBeat, this.closeFace)
-
         if (!this.isnotbtn && !this.media.isFinish && this.onPlay && !this.closeFace) {
           this.$message.errorMsg("需要安装摄像头才能学习", 2);
           this.doPause()
@@ -304,7 +391,7 @@
         let curTimes = parseInt(myPlayer.currentTime());
         // 后退无心跳
         if (this.media.position > curTimes && !force) return;
-        if (curTimes < 4) {
+        if (curTimes < this.heartbeat) {
           console.log("curTimes")
           return;
         }
@@ -350,6 +437,7 @@
 </script>
 
 <style>
+   @import url("./imedia.css");
   .video-js {
     .vjs-control-bar {
       .vjs-icon-custombutton {
@@ -365,7 +453,18 @@
       }
     }
   }
-
+  .left-float {
+      width: 240px;
+      height: 180px;
+      background-color: #8bbdf5;
+      position: fixed;
+      transition: bottom ease .9s;
+      z-index: 0;
+      left: 60px;
+      top: 120px;
+      text-align: center;
+      border-radius: 5px;
+  }
   .p-process {
     width: 100%;
     margin: 20px auto;

+ 55 - 0
src/containers/center/play/components/imedia.css

@@ -0,0 +1,55 @@
+.m-chapter-list {
+  position: relative;
+  margin-top: 20px;
+  margin-left: 20px;
+  min-height: 600px;
+  border-top: 1px solid #f8f8f8;
+}
+.m-chapter-list a {
+  width: 100%;
+  height: 50px;
+  line-height: 50px;
+  border-bottom: 1px solid #f8f8f8;
+  font-size: 15px;
+  display: block;
+  box-sizing: border-box;
+  padding-left: 6px;
+  position: relative;
+}
+.m-chapter-list .current {
+  border-left: 5px solid #3290d4;
+  background-color: #fff;
+}
+.m-chapter-list .current a {
+  color: #3290d4;
+  width: 400px;
+  background-color: #fff;
+  border-right: 2px solid #fff;
+}
+
+.m-chapter-list .current .sub-list {
+  display: block;
+}
+.m-chapter-list .current .sub-list a {
+  color: #666;
+  font-size: 14px;
+  line-height: 30px;
+}
+.m-chapter-list .current .sub-list a:before {
+  content: "";
+  border: 1px solid;
+  width: 8px;
+  border-color: transparent transparent #ddd #ddd;
+  display: inline-block;
+  margin-right: 5px;
+  position: relative;
+  top: -3px;
+}
+.m-chapter-list .current .sub-list a:hover,
+.m-chapter-list .current .sub-list a.current {
+  color: #3290d4;
+  border-left: 0;
+}
+.m-chapter-list .sub-list {
+  display: none;
+}

+ 34 - 1
src/containers/center/play/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="m-right-block fr mh576">
+  <div class="m-right-block  fr mh576">
     <div v-if="show!=4">
       <ICourseInfoTest  v-if="tpl.type=='检测试验人员'" :info="info" :tpl="tpl" @printCert="printCert" @startExam="startExam"></ICourseInfoTest>
       <ICourseInfoXsExtra v-else-if="tpl.testXs>0"
@@ -87,7 +87,10 @@
               :dialog="mediaDialog"
               :media="media"
               :duration="info.duration"
+              :list = "list"
+              :chapter = "chapter"
               @close="closeMedia"
+              @loadMedia="loadMedia"
               :mediaType="mediaType"
               :heartbeat="heartbeat"
               :max-error-count="maxErrorCount"
@@ -151,6 +154,7 @@
         tpl:{},
         media:{},
         extraXs:{},
+        chapter:{required:[],normal:[]},
         page:1,
         size:5,
         mediaId:0,
@@ -296,6 +300,34 @@
       formatString(val){
         return ()=> val;
       },
+      calcChapter( list ){
+        let required = {};
+        let normal = {};
+        let chapter = {required: [],normal: []}
+        for( let i in list){
+          let item = list[i];
+          if( item.required){
+            if( required[ item.chapterName] ){
+              required[ item.chapterName] = required[ item.chapterName]+item.xs
+            }else{
+              required[ item.chapterName ] = item.xs
+            }
+          }else{
+            if( normal[ item.chapterName] ){
+              normal[ item.chapterName] = normal[ item.chapterName]+item.xs
+            }else{
+              normal[ item.chapterName ] = item.xs
+            }
+          }
+        }
+        for( let name in required){
+          chapter.required.push({name: name, active: false, xs:required[name]})
+        }
+        for( let name in normal){
+          chapter.normal.push({name: name, active: false, xs:normal[name]})
+        }
+        this.chapter = chapter;
+      },
       getData() {
         let param = { courseId: this.courseId }
         httpServer("course.getCourse", param).then(res => {
@@ -312,6 +344,7 @@
               item.percent = getPercent(item)||0;
               return item;
             })
+            this.calcChapter( this.list );
             this.updateShowList()
           }
         })