video.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <template>
  2. <view v-if="fullUrl && checked">
  3. <video id="myVideo" style="width: 100%;" :src="fullUrl"
  4. @error="videoErrorCallback"
  5. @timeupdate="videoUpdate"
  6. @loadedmetadata="videoLoad"
  7. @play="play = true"
  8. @pause="play = false"
  9. controls></video>
  10. <read-socket v-if="fileId && play && pageShow" v-model="fileId" :course-id="courseId" />
  11. <read-check v-if="fileId && play && pageShow && checkOn" :time-sec="checkSec" @break="checkBreak" />
  12. <face-check v-if="fileId && play && pageShow"
  13. :courseId="courseId"
  14. :fileId="fileId"
  15. @ok="pageShow=true"
  16. @no="pageShow=false"
  17. >
  18. </face-check>
  19. </view>
  20. <view v-else style="display: flex; align-items: center; height: 30vh; justify-content: center; color: #666;">
  21. 抱歉,该课件暂不支持查看!
  22. </view>
  23. </template>
  24. <script>
  25. import { apiCheckFile } from '@/api/course.js'
  26. import ReadSocket from './components/ReadSocket'
  27. import ReadCheck from './components/ReadCheck'
  28. import FaceCheck from './components/FaceCheck'
  29. export default {
  30. components: {
  31. ReadSocket, ReadCheck, FaceCheck
  32. },
  33. data() {
  34. return {
  35. checked: false,
  36. courseId: null,
  37. fileId: null,
  38. checkOn: false,
  39. checkSec: 0,
  40. // 完整预览路径
  41. fullUrl: null,
  42. extraProps: {
  43. src: this.fullUrl,
  44. controls: true
  45. },
  46. // 是否允许拖动
  47. play: false,
  48. videoContext: null,
  49. drag: true,
  50. pageShow: true,
  51. lastPlay: 0
  52. }
  53. },
  54. onLoad: function(option) {
  55. this.courseId = option.courseId
  56. this.fileId = option.fileId
  57. this.drag = option.drag
  58. if(option.checkOn && option.checkOn==='true'){
  59. this.checkOn = true
  60. }
  61. if(option.checkSec){
  62. this.checkSec = parseInt(option.checkSec)
  63. }
  64. apiCheckFile({courseId: this.courseId, fileId: this.fileId}).then(data=>{
  65. this.checked = data
  66. if(this.checked){
  67. const path = decodeURIComponent(option.path)
  68. this.fillData(path)
  69. console.log('文件地址:', this.fullUrl)
  70. }
  71. })
  72. },
  73. onHide: function(){
  74. // 程序隐藏
  75. this.pageShow = false
  76. this.videoContext.pause()
  77. },
  78. onShow:function(){
  79. this.pageShow = true
  80. },
  81. onReady: function (res) {
  82. this.videoContext = uni.createVideoContext('myVideo')
  83. },
  84. methods: {
  85. // 填充微信或APP地址
  86. fillData(path) {
  87. if (path.startsWith('https://') || path.startsWith('http://')) {
  88. this.fullUrl = path
  89. } else {
  90. this.fullUrl = `${this.$urls.api}${path}`;
  91. }
  92. },
  93. videoErrorCallback(e) {
  94. uni.showModal({
  95. content: '出现错误:' + e.target.errMsg,
  96. showCancel: false
  97. })
  98. console.log(e.target.errMsg)
  99. },
  100. videoLoad(e){
  101. // 视频总长度
  102. const lastTime = uni.getStorageSync(this.fileId);
  103. // 记忆上次播放,太短也没必要记忆
  104. if (lastTime != null && lastTime > 5) {
  105. this.lastPlay = lastTime
  106. this.videoContext.seek(lastTime)
  107. }
  108. },
  109. videoUpdate(e){
  110. const curTime = e.detail.currentTime
  111. const end = e.detail.duration - curTime
  112. // 播完了,直接跳到开始
  113. if (end < 1) {
  114. this.lastPlay = 0
  115. return
  116. }
  117. // 不能快进也不能后退
  118. if (this.drag && (curTime - this.lastPlay > 2 || this.lastPlay - curTime > 2)) {
  119. this.videoContext.seek(this.lastPlay)
  120. return
  121. }
  122. if (curTime > 0) {
  123. uni.setStorageSync(this.fileId, curTime);
  124. }
  125. this.lastPlay = curTime
  126. },
  127. // 验证
  128. checkBreak(){
  129. uni.switchTab({
  130. url: '/pages/index/index'
  131. })
  132. }
  133. }
  134. }
  135. </script>
  136. <style>
  137. .tips{
  138. width: 100%;
  139. text-align: center;
  140. margin-top: 50px;
  141. font-size: 12px;
  142. }
  143. </style>