Explorar el Código

小程序样式

y595705120 hace 2 semanas
padre
commit
d1a6b1ba22

+ 3 - 5
src/containers/center/play/components/media.vue

@@ -167,12 +167,9 @@
       playerReadied(audio) {
         console.log("playerReadied", audio)
         let that = this;
-        // if (this.media.position) {
-        // this.setposition(this.media.position);
+
         if (this.media.position > 5 && this.media.position < this.media.duration) {
-          setTimeout(() => {
-            this.setposition(this.media.position)
-          }, 2000)
+          this.setposition(this.media.position+3)
         }
         this.isReady = true
         setTimeout(() => this.setMarks(), 600);
@@ -186,6 +183,7 @@
         }
       },
       setposition(position) {
+        console.log("setposition", position)
         if (position > this.media.duration) position = this.media.duration;
         let player = this.$refs.videoPlayer.player;
         player.currentTime(position);

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

@@ -240,7 +240,6 @@
       isStudyFinish(){
         let {getXs,totalXs} = this.info
         let {testXs, examXs} = this.tpl;
-        console.log(getXs, totalXs , testXs, examXs )
         return getXs>=totalXs -testXs - examXs
       },
       startExam( groupId ){

+ 114 - 0
src/containers/weixin/index.css

@@ -0,0 +1,114 @@
+
+.weixin-body {
+    background-size: 100% auto;
+    background-color:#fff;
+    margin:0;
+    font-family:"Arial";
+    /* padding-bottom: 20px; */
+}
+@media screen and  (min-width: 640px){
+    .weixin-body {
+        font-size: 85.4px;
+    }
+}
+
+@media screen and  (min-width: 414px) and (max-width: 639px){
+    .weixin-body {
+        font-size: 55.2px;
+    }
+}
+
+@media screen and (min-width:375px) and (max-width:413px){
+    .weixin-body {
+        font-size: 50px;
+    }
+}
+
+@media screen and (min-width:320px) and (max-width:374px){
+    .weixin-body {
+        font-size: 42.7px;
+    }
+}
+
+.weixin-title-2{
+  width: 100%;
+  font-size: 28px;
+  text-align: center;
+  /* margin: 30px auto; */
+  color: white;
+  padding-top: 30px;
+  padding-bottom: 30px;
+  display: block;
+  font-weight: bold;
+}
+
+.weixin-content-box {
+    width: 96%;
+    background-color: white;
+    border-radius: .6rem;
+    margin-left: auto;
+    margin-right: auto;
+/*    padding: .9rem;
+    margin-bottom: 1.2rem; */
+}
+
+.weixin-title {
+    font-weight: bold;
+    font-size: 20px;
+    color: #439fff;
+    padding-top: 0.5rem;
+    text-align: center;
+    margin: 0 auto;
+}
+
+.weixin-content {
+    width: 100%;
+    margin-top: .6rem;
+    border-top: 1px solid #e6e6e6;
+}
+
+.weixin-course-name {
+    font-size: 1.1rem;
+    font-weight: bold;
+    color: #333;
+    margin-top: .6rem;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+    -webkit-line-clamp: 2;
+    margin-bottom: -0.3rem;
+}
+
+.weixin-ul-info {
+    font-size: .9rem;
+    margin-top: .6rem;
+    color: #333;
+}
+
+.weixin-info {
+    margin-top: .15rem;
+}
+
+.weixin-info-2 {
+    width: 40%;
+    float: left;
+}
+.weixin-info-3 {
+    width: 60%;
+    float: left;
+}
+
+.weixin-con {
+    font-size: .72rem;
+}
+
+.weixin-tips {
+    margin-left: auto;
+    margin-right: auto;
+    font-size: .72rem;
+    font-weight: bold;
+    color: white;
+    width: 80%;
+    margin-bottom: 1.2rem;
+}

+ 316 - 0
src/containers/weixin/index.vue

@@ -0,0 +1,316 @@
+<template>
+  <div class="weixin-body">
+
+    <div class="weixin-content-box">
+      <div class="weixin-title">{{media.name|| tpl.name}}</div>
+      <div class="weixin-content">
+        <video-player
+          id="myVideo1"
+          ref="videoPlayer"
+          :playsinline="true"
+          @pause="onPlayerPause($event)"
+          @timeupdate="onPlayerTimeupdate($event)"
+          @play="onPlayerStart($event)"
+          @ready="playerReadied"
+          @canplay="canpay($event)"
+          @ended="onPlayerEnded($event)"
+          :globalOptions="{controls:true}"
+          :options="options">
+        </video-player>
+        <div style="font-size: 16px;; margin: 10px auto;text-align: center;">
+          <span>{{curTimes|useTime}}</span>
+          <strong>/</strong>
+          <span>{{media.duration|useTime}}</span>
+          <span v-if="media.isFinish==1" style="color: green;">已完成</span>
+        </div>
+
+      </div>
+    </div>
+
+    <!-- <div  style="width: 100%; margin: 0px auto;"> -->
+    <div class="weixin-content-box" style="padding: 4px;">
+      <div class="weixin-content" v-for="item in list"  v-if="item.isFinish==0">
+        <div class="weixin-course-name">
+          <el-button @click="loadMedia(item)" type="text">{{item.name}} </el-button>
+        </div>
+        <ul class="weixin-ul-info clear">
+          <li class="weixin-info">
+            <span>学时:</span>
+            <span>{{item.xs/10}}</span>
+          </li>
+          <li class="weixin-info">
+            <span>学习进度:</span>
+            <span>{{(item.position*100/item.duration).toFixed(2)}}%</span>
+          </li>
+        </ul>
+      </div>
+    </div>
+
+  </div>
+</template>
+<script>
+  import { mapGetters,mapActions } from "vuex";
+  import {getPercent} from '@/utils/index.js'
+  import {
+    videoPlayer
+  } from 'vue-video-player';
+  // import 'video.js/dist/video-js.css'
+  import {
+    httpServer
+  } from "@/components/httpServer/httpServer.js";
+  export default {
+    data() {
+      return {
+        id: '',
+        media:{},
+        options:{
+          controls:true,
+          autoplay: true, // 如果true,浏览器准备好时开始回放。
+          muted: true, // 默认情况下将会消除任何音频。
+          loop: false, // 导致视频一结束就重新开始。
+          preload: "auto", // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
+          language: 'zh-CN',
+          aspectRatio: '4:3', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
+          fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
+          sources: [],
+          poster: '', // 你的封面地址
+          notSupportedMessage: '无法播放媒体源', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
+          playtimes: '',
+          controlBar: {
+            timeDivider: true,
+            durationDisplay: true,
+            remainingTimeDisplay: false,
+            fullscreenToggle: true  //全屏按钮
+          }
+        },
+        curTimes:0,
+        tpl:{},
+        info: {},
+        list: [],
+        timer: false,
+        tickNum: 0,
+        prevTime: 0,
+        isReady: false,
+        onPlay: false
+      };
+    },
+    components: {
+      videoPlayer
+    },
+    filters:{
+      useTime(val) {
+        val = parseInt(val)||0
+        let timestr = ""
+        let hour = parseInt(val / 3600);
+        let min = parseInt(val / 60 % 60);
+        let sec = parseInt(val % 60);
+        if (hour < 10) hour = "0" + hour;
+        if (min < 10) min = "0" + min;
+        if (sec < 10) sec = "0" + sec;
+        return hour + ":" + min + ":" + sec
+      }
+    },
+    methods: {
+       ...mapActions("user", ["loadBaseInfo"]),
+      getCourse() {
+        let param = { courseId: this.courseId }
+        httpServer("course.getCourse", param).then(res => {
+          if (res.code == 200) {
+            let {info, extra, list, tpl, extraXs, examList} = res.data;
+            this.info =  Object.assign( info, extra||{});
+            this.tpl = tpl||{};
+            this.list = list.map( (item)=>{
+              item.percent = getPercent(item)||0;
+              return item;
+            })
+            for( let i in this,list){
+              if( this.list[i].mediaId == this.userInfo.mediaId){
+                this.loadMedia( this.list[i])
+              }
+            }
+          }
+        })
+      },
+      startTick() {
+        let tick = this.tryTick;
+        if (this.timer) clearInterval(this.timer);
+        this.timer = setInterval(tick, 5 * 1000);
+      },
+      stopTick() {
+        if (this.timer) clearInterval(this.timer);
+      },
+      tryTick() {
+        let that = this;
+        try {
+          that.tick()
+        } catch (err) {
+          that.reportErr("play", '' + err.message)
+        }
+      },
+      playerReadied(audio) {
+        this.isReady = true
+        let myPlayer = this.$refs.videoPlayer.player;
+        myPlayer && myPlayer.play()
+      },
+      onPlayerTimeupdate(player) {
+        let myPlayer = this.$refs.videoPlayer.player;
+        let curTimes = player.cache_.currentTime;
+        this.curTimes = curTimes || 0
+        if (this.media.isFinish) {
+          return;
+        }
+      },
+      canpay(player){
+        console.log("player", this.media.position )
+        if( this.media.position > this.curTimes){
+          player.currentTime(this.media.position+3);
+          setTimeout( ()=>{player.play()}, 100)
+
+        }
+      },
+      setposition(position) {
+        if (position > this.media.duration) position = this.media.duration;
+        let player = this.$refs.videoPlayer.player;
+        player.currentTime(position);
+        player.play()
+        if (this.media.isFinish) return;
+        if (this.media.position >= this.media.duration - 10 && !this.media.isFinish) {
+          this.tick(true)
+        }
+      },
+      onPlayerPause(event) {
+        this.reportErr("play", 'pause');
+        this.stopTick()
+        this.onPlay = false
+      },
+      onPlayerEnded(event) {
+        this.reportErr("play", 'end');
+        this.tick(true)
+      },
+      onClose() {
+        this.reportErr("play", 'close')
+        this.doPause()
+        this.$emit("close")
+      },
+      doPause() {
+        // console.log("doPause")
+        this.stopTick()
+        this.onPlay = false
+        let myPlayer = this.$refs.videoPlayer.player;
+        myPlayer && myPlayer.pause()
+      },
+      doPlay() {
+        console.log("doPlay")
+        this.onPlay = true
+        this.startTick();
+        if (!this.$refs.videoPlayer || !this.$refs.videoPlayer.player) return;
+        if (!this.dialog) return this.doPause();
+        let myPlayer = this.$refs.videoPlayer.player;
+        myPlayer && myPlayer.play()
+        this.tickNum = 0
+      },
+      onPlayerStart() {
+        console.log("onPlayerStart")
+        this.reportErr("play", 'start');
+        this.startTick();
+        this.onPlay = true
+      },
+      reportErr(action, msg) {
+        httpServer("course.report", {
+          action,
+          msg
+        })
+      },
+      tick(force = false) {
+        let media = this.media;
+        this.tickNum++
+        if (this.media.isFinish) {
+          console.log("finish")
+          return;
+        }
+        // 主动暂停
+        let myPlayer = this.$refs.videoPlayer.player;
+        let curTimes = parseInt(myPlayer.currentTime());
+        // 后退无心跳
+        if (this.media.position > curTimes && !force) return;
+        if (curTimes < 4) {
+          console.log("curTimes")
+          return;
+        }
+
+        let isFinish = force ? 1 : 0
+        if (curTimes >= media.duration) isFinish = 1;
+        //  拉到后面
+        if (!isFinish) {
+          if (!this.onPlay) return;
+        }
+        if(window.navigator.webdriver){
+          this.reportErr("play", 'webdriver');
+          this.doPause()
+          return
+        }
+        // 强制完成
+        let param = {
+          id: media.id,
+          position: curTimes,
+          isFinish
+        };
+        httpServer("course.tick", param, true).then(res => {
+          if (res.code == 200) {
+            let {
+              skip,
+              position,
+              pause,
+              closed
+            } = res.data
+            if (pause || closed) {
+              this.doPause();
+              this.$emit("close")
+              if (closed) {
+                this.$message.errorMsg("课程关闭学习", 5);
+              } else if (pause) {
+                this.$message.errorMsg("多处同时播放视频", 5);
+              }
+              return
+            }
+            if (!skip) this.setposition(position);
+            Object.assign(this.media, res.data)
+          }
+        })
+      },
+      loadMedia( item ) {
+        this.media = item;
+        httpServer('course.GetMedia', {id:item.id}).then( res => {
+          if( res.code != 200) return;
+          let {mediaUrl, id, position, marks,duration} = res.data||{};
+          this.mediaUrl = res.data.mediaUrl;
+          this.media.position = position;
+          this.media.duration = duration;
+          this.media.id = id;
+          this.options.sources = [{src:this.mediaUrl,type: "application/x-mpegURL"}];
+          this.options.playtimes = position||1;
+          this.options.autoplay  = position>0;
+          this.curTimes = 0
+          this.$refs.player && this.$refs.player.preload()
+        });
+      }
+    },
+    created() {
+      let {uid,token,courseId, mediaId} = this.$route.query;
+      this.userInfo = {uid, token, courseId, mediaId};
+      this.courseId = +courseId
+      if(uid) localStorage.uid = uid
+      if(token) localStorage.token = token
+      if (uid && token && courseId ) {
+        this.getCourse();
+      }
+      document.addEventListener('touchmove', function (event) {
+        console.log('touchmove')
+          event.preventDefault();
+      }, { passive: false });
+    }
+  }
+</script>
+<style>
+  @import url("./index.css");
+</style>

+ 6 - 0
src/router/index.js

@@ -32,6 +32,7 @@ import CenterMyOrder from '@/containers/center/myOrder/index'
 import CenterMessage from '@/containers/center/message/index'
 import CenterSign from '@/containers/center/sign/index'
 import PublicSign from '@/containers/sign/index'
+import PublicWeixin from '@/containers/weixin/index'
 
 import CenterMarket from '@/containers/center/market/index'
 import CenterTrainMarket from '@/containers/center/market/trainIndex'
@@ -63,6 +64,11 @@ export default new Router({
       name: 'sign',
       component: PublicSign,
     },
+    {
+      path: '/weixin',
+      name: 'weixin',
+      component: PublicWeixin,
+    },
     {
       path: '/news',
       name: 'news',