3 次代碼提交 87688fe51d ... d028fa0daa

作者 SHA1 備註 提交日期
  natasha d028fa0daa Merge branch 'lhd' 2 周之前
  natasha 33a32fa697 视频交互题增加提示点 2 周之前
  lhd 0093fab05d 1 3 周之前

+ 3 - 1
package.json

@@ -20,8 +20,8 @@
     "builder:mac": "electron-builder --mac"
   },
   "dependencies": {
-    "@tinymce/tinymce-vue": "^3.2.8",
     "7zip-bin": "^5.2.0",
+    "@tinymce/tinymce-vue": "^3.2.8",
     "axios": "^1.7.2",
     "cnchar": "^3.2.6",
     "core-js": "^3.47.0",
@@ -38,6 +38,8 @@
     "three": "^0.181.2",
     "tinymce": "^5.10.9",
     "v-fit-columns": "^0.2.0",
+    "video.js": "^8.23.7",
+    "videojs-markers": "^1.0.1",
     "vis-data": "^8.0.3",
     "vis-network": "^10.0.2",
     "vue": "^2.6.14",

+ 544 - 0
src/components/UploadFile.vue

@@ -0,0 +1,544 @@
+<template>
+  <div class="upload-file">
+    <div class="file-area">
+      <span class="label-text">{{ labelText }}</span>
+      <div class="upload-box">
+        <el-upload
+          ref="upload"
+          class="file-uploader"
+          action="no"
+          :accept="acceptFileType"
+          :multiple="limit === null || limit > 1"
+          :show-file-list="false"
+          :auto-upload="false"
+          :file-list="fileList"
+          :on-change="onFileChange"
+          :on-exceed="handleExceed"
+          :limit="limit"
+        >
+          <el-button>{{ type === 'h5_games' ? '选择Zip压缩包或单个html文件' : '选取' + labelText + '文件' }}</el-button>
+        </el-upload>
+        <el-button size="small" type="primary" @click="uploadFiles"> 上传 </el-button>
+        <el-button size="small" type="primary" @click="useResource"> 使用资源 </el-button>
+      </div>
+    </div>
+    <el-divider v-if="showDivider" />
+    <div class="upload-tip">{{ uploadTip }}</div>
+    <ul v-if="fileList.length > 0" slot="file-list" class="file-list">
+      <li v-for="(file, i) in fileList" :key="i">
+        <div class="file-name">
+          <span>
+            <SvgIcon v-if="iconClass" :icon-class="iconClass" size="12" />
+            <!-- 编辑序号和名称 -->
+            <template v-if="content.file_info[file.file_id] && content.file_info[file.file_id].isEdit">
+              <el-input v-model="content.file_info[file.file_id].xuhao" placeholder="序号" style="width: 80px" />
+              <el-input v-model="content.file_info[file.file_id].file_name" placeholder="名称" />
+            </template>
+            <!-- 可以编辑序号名称状态下显示序号 -->
+            <span v-else>{{
+              canEditName && file.file_id
+                ? content.file_info[file.file_id].xuhao + content.file_info[file.file_id].file_name
+                : (file.file_name ?? file.name)
+            }}</span>
+            <!-- <span>({{ file.size }})</span> -->
+          </span>
+          <el-progress
+            v-if="file.progress > 0 && file.progress < 100"
+            type="circle"
+            :percentage="file.progress"
+            :width="20"
+            color="#2A5AF6"
+            stroke-linecap="butt"
+            :show-text="false"
+          />
+          <span v-else-if="file.file_id"> 完成</span>
+        </div>
+        <SvgIcon icon-class="delete-black" size="12" @click="removeFile(file, i)" />
+        <SvgIcon
+          v-show="type === 'picture' && file.file_id"
+          icon-class="mark"
+          size="12"
+          @click="viewDialog(file.file_id)"
+        />
+        <!-- 编辑名称和序号 -->
+        <template v-if="canEditName && file.file_id">
+          <SvgIcon
+            v-if="content.file_info[file.file_id].isEdit"
+            icon-class="icon-save"
+            size="12"
+            @click="changeIsEdit(content.file_info[file.file_id])"
+          />
+          <SvgIcon v-else icon-class="icon-edit" size="12" @click="changeIsEdit(content.file_info[file.file_id])" />
+        </template>
+      </li>
+    </ul>
+
+    <SelectResource
+      :visible.sync="visibleResource"
+      :project-id="projectId"
+      :accept="accept"
+      :courseware-id="coursewareId"
+      @selectResource="selectResource"
+    />
+  </div>
+</template>
+
+<script>
+import { fileUpload } from '@/api/app';
+import { conversionSize } from '@/utils/common';
+import { isEnable } from '@/views/book/courseware/data/common';
+import { getConfig, getToken } from '@/utils/auth';
+
+import SelectResource from '@/views/book/courseware/create/components/base/common/SelectResource.vue';
+import { SubmitFileToResourceStore } from '@/api/book';
+export default {
+  name: 'UploadFile',
+  components: {
+    SelectResource,
+  },
+  props: {
+    // 项目id
+    projectId: {
+      type: String,
+      default: '',
+    },
+    // 课件id
+    coursewareId: {
+      type: String,
+      default: '',
+    },
+    // 组件id
+    componentId: {
+      type: String,
+      default: '',
+    },
+    // 组件标签
+    labelText: {
+      type: String,
+      default: '',
+    },
+    // 上传支持的文件格式
+    acceptFileType: {
+      type: String,
+      default: '*',
+    },
+    // 提示语
+    uploadTip: {
+      type: String,
+      default: '',
+    },
+    // 图标
+    iconClass: {
+      type: String,
+      default: '',
+    },
+    fileList: {
+      type: Array,
+      default: () => [],
+    },
+    fileIdList: {
+      type: Array,
+      default: () => [],
+    },
+    fileInfoList: {
+      type: Array,
+      default: () => [],
+    },
+    type: {
+      type: String,
+      default: '',
+    },
+    singleSize: {
+      type: Number,
+      default: 100,
+    },
+    totalSize: {
+      type: Number,
+      default: 1024,
+    },
+    limit: {
+      type: Number,
+      default: null,
+    },
+    canEditName: {
+      type: Boolean,
+      default: false,
+    },
+    fileInfo: {
+      type: Object,
+      default: () => ({}),
+    },
+    index: {
+      // 如果是二维数组里循环上传 一维索引
+      type: Number,
+      default: null,
+    },
+    indexs: {
+      // 如果是二维数组里循环上传 二维索引
+      type: Number,
+      default: null,
+    },
+    // 是否显示分割线
+    showDivider: {
+      type: Boolean,
+      default: true,
+    },
+  },
+  data() {
+    return {
+      curFile: null,
+      conversionSize,
+      visible: false,
+      content: {
+        file_list: this.fileList,
+        file_id_list: this.fileIdList,
+        file_info_list: this.fileInfoList,
+        file_info: this.fileInfo,
+      },
+      visibleResource: false,
+      isEnable,
+    };
+  },
+  computed: {
+    accept() {
+      let accept = '*';
+      if (this.acceptFileType.includes('.mp3')) {
+        accept = 'audio';
+      } else if (this.acceptFileType.includes('.mp4')) {
+        accept = 'video';
+      } else if (this.acceptFileType.includes('.jpg')) {
+        accept = 'image';
+      } else if (this.acceptFileType.includes('.zip')) {
+        accept = 'h5_game';
+      } else if (this.acceptFileType.includes('.txt')) {
+        accept = 'text';
+      }
+      return accept;
+    },
+  },
+  watch: {
+    content: {
+      handler(val) {
+        this.$emit('updateFileList', val, this.index, this.indexs);
+      },
+      deep: true,
+    },
+  },
+  methods: {
+    // 显示自定义样式文件列表
+    onFileChange(file, fileList) {
+      this.afterSelectFile(file);
+      fileList.forEach((file) => {
+        if (!file.progress || file.progress <= 0) file.progress = 0;
+      });
+      const lists = this.$refs.upload.uploadFiles;
+      if (lists.length === 0) return;
+      const files = lists.filter((item) => {
+        let find = this.content.file_list.findIndex((p) => p.uid === item.uid);
+        return find === -1;
+      });
+      if (this.limit !== null && this.content.file_list.length + files.length > this.limit) {
+        this.$message.warning(
+          `当前限制选择 ${this.limit} 个文件,本次选择了 ${files.length} 个文件,共选择了 ${
+            files.length + this.content.file_list.length
+          } 个文件`,
+        );
+        return;
+      }
+      this.content.file_list = [...this.content.file_list, ...files];
+    },
+
+    handleExceed(files, fileList) {
+      this.$message.warning(
+        `当前限制选择 ${this.limit} 个文件,本次选择了 ${files.length} 个文件,共选择了 ${
+          files.length + fileList.length
+        } 个文件`,
+      );
+    },
+
+    // 删除文件
+    removeFile(file, i) {
+      this.$confirm('是否删除当前文件?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning',
+      })
+        .then(() => {
+          this.$refs.upload.handleRemove(file);
+          this.content.file_list.splice(i, 1);
+          this.content.file_id_list.splice(i, 1);
+        })
+        .catch(() => {});
+    },
+
+    // 文件校验
+    afterSelectFile(file) {
+      const fileName = file.name;
+      let singleSizeTip = `文件[${fileName}]大小超过${conversionSize(this.singleSize * 1024 * 1024)},被移除!`;
+      if (file.size > this.singleSize * 1024 * 1024) {
+        this.$message.error(singleSizeTip);
+        this.$refs.upload.handleRemove(file);
+        return false;
+      }
+
+      const suffix = fileName.slice(fileName.lastIndexOf('.') + 1, fileName.length).toLowerCase();
+      let fileType = [];
+      let typeTip = '';
+
+      if (this.type === 'audio') {
+        fileType = ['mp3', 'acc', 'wma', 'wav'];
+        typeTip = '音频文件只能是 mp3、acc、wma、wav格式!';
+      } else if (
+        this.type === 'picture' ||
+        this.type === 'image_text' ||
+        this.type === 'drawing' ||
+        this.type === 'character_structure' ||
+        this.type === 'newWord_template' ||
+        this.type === 'character'
+      ) {
+        fileType = ['jpg', 'png', 'jpeg'];
+        typeTip = '图片文件只能是 jpg、png、jpeg 格式!';
+      } else if (this.type === 'video' || this.type === 'video_interaction') {
+        fileType = ['mp4'];
+        typeTip = '视频文件只能是 mp4 格式!';
+      } else if (this.type === 'upload_preview' || this.type === 'video_interaction_file') {
+        fileType = [
+          'png',
+          'jpg',
+          'jpeg',
+          'txt',
+          'pdf',
+          'doc',
+          'docx',
+          'xls',
+          'xlsx',
+          'ppt',
+          'pptx',
+          'mp3',
+          'wma',
+          'mp4',
+          'mov',
+          'zip',
+          'rar',
+        ];
+        typeTip = '文件不支持';
+      } else if (this.type === 'h5_games') {
+        fileType = ['zip', 'html'];
+        typeTip = 'H5游戏文件只能是 zip、html 格式!';
+      } else if (this.type === '3DModel') {
+        fileType = ['fbx', 'zip', 'gltf', 'glb'];
+        typeTip = '3D模型文件只能是 fbx、gltf、glb、zip 格式!';
+      }
+      const isNeedType = fileType.includes(suffix);
+      if (!isNeedType) {
+        typeTip += `,[${fileName}]被移除!`;
+        this.$message.error(typeTip);
+        this.$refs.upload.handleRemove(file);
+        return false;
+      }
+    },
+
+    // 上传文件
+    uploadFiles() {
+      const files = (this.content.file_list || []).filter((file) => file.uid && file.status !== 'success');
+      if (files.length <= 0) {
+        this.$message.error('没有需要上传的文件!');
+        return false;
+      }
+      const totalSize = files.reduce((sum, cur) => sum + Number(cur.size || 0), 0);
+      if (totalSize > this.totalSize * 1024 * 1024) {
+        this.$message.error(`文件总大小不能超过${conversionSize(this.totalSize * 1024 * 1024)}!`);
+        return false;
+      }
+
+      files
+        .filter((p) => {
+          let pro = p.progress || -1;
+          return pro <= 0;
+        })
+        .forEach((file) => {
+          // 添加验证
+          if (!file.raw || !(file.raw instanceof Blob)) {
+            this.$message.error(`文件 ${file.name} 无效,请删除后重新选择!`);
+            return;
+          }
+          let form = new FormData();
+          form.append(file.name, file.raw, file.name);
+          fileUpload('Mid', form, {
+            handleUploadProgress: (progressEvent) => {
+              // 进度到99等服务器返回文件信息后才算实际完成
+              let per = Number((progressEvent.progress * 99).toFixed(2) || 0);
+              let en = this.content.file_list.find((p) => p.uid === file.uid);
+              if (en) {
+                en.progress = per;
+                this.$forceUpdate();
+              }
+            },
+          }).then(({ file_info_list }) => {
+            let file_index = this.content.file_list.findIndex((p) => p.uid === file.uid);
+            if (file_index > -1) {
+              if (this.type === 'picture') {
+                this.content.file_info_list[file_index] = {
+                  file_id: file_info_list[0].file_id,
+                  file_name: file_info_list[0].file_name,
+                  title: '',
+                  intro: '',
+                };
+              }
+              this.content.file_list[file_index] = {
+                file_id: file_info_list[0].file_id,
+                file_name: file_info_list[0].file_name,
+                file_url: file_info_list[0].file_url,
+              };
+              if (this.canEditName) {
+                let obj = {
+                  xuhao: '',
+                  isEdit: false,
+                  file_name: file_info_list[0].file_name,
+                };
+                this.$set(this.content.file_info, file_info_list[0].file_id, obj);
+              }
+              this.content.file_id_list.push(file_info_list[0].file_id);
+              this.$refs.upload.uploadFiles = [];
+              this.$forceUpdate();
+            }
+          });
+        });
+    },
+
+    // 显示弹窗
+    viewDialog(file_id) {
+      if (file_id) this.visible = true;
+      this.curFile = this.content.file_info_list.find((file) => file.file_id === file_id);
+    },
+
+    // 给文件加介绍
+    fillDescribeToFile(file) {
+      let en = this.content.file_info_list.find((p) => p.file_id === file.file_id);
+      if (en) {
+        Object.assign(en, file);
+      }
+    },
+    // 使用资源
+    useResource() {
+      this.visibleResource = true;
+    },
+    selectResource({ file_id, file_name, file_url, intro }) {
+      this.content.file_list.push({ file_id, file_name, file_url });
+      this.content.file_id_list.push(file_id);
+      this.content.file_info_list.push({ file_id, file_name, title: '', intro });
+      if (this.canEditName) {
+        let obj = {
+          xuhao: '',
+          isEdit: false,
+          file_name,
+        };
+        this.$set(this.content.file_info, file_id, obj);
+      }
+      this.visibleResource = false;
+    },
+    // 编辑文件名及序号
+    changeIsEdit(file) {
+      file.isEdit = !file.isEdit;
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.module-content {
+  .file-area {
+    display: flex;
+    column-gap: 16px;
+    align-items: center;
+
+    .label-text {
+      font-size: 14px;
+      color: $font-light-color;
+    }
+
+    div {
+      flex: 1;
+    }
+  }
+
+  .el-divider {
+    margin: 16px 0;
+  }
+
+  .upload-tip {
+    margin-bottom: 16px;
+    font-size: 12px;
+    color: #86909c;
+  }
+
+  .upload-box {
+    display: flex;
+    justify-content: space-between;
+
+    .el-button + .el-button {
+      margin-left: 2px;
+    }
+
+    .file-uploader {
+      flex: 1;
+
+      :deep .el-upload {
+        &--text {
+          width: 100%;
+          background-color: $fill-color;
+          border-radius: 2px 0 0 2px;
+
+          .el-button {
+            width: 100%;
+            color: #86909c;
+            text-align: left;
+          }
+        }
+      }
+    }
+
+    .el-button {
+      border-radius: 0 2px 2px 0;
+    }
+  }
+
+  .old_file_list {
+    margin-top: 16px;
+  }
+
+  .file-list {
+    display: flex;
+    flex-direction: column;
+    row-gap: 16px;
+
+    li {
+      display: flex;
+      column-gap: 12px;
+      align-items: center;
+
+      .file-name {
+        display: flex;
+        column-gap: 14px;
+        align-items: center;
+        justify-content: space-between;
+        max-width: 500px; // 360px有点窄
+        padding: 8px 12px;
+        font-size: 14px;
+        color: #1d2129;
+        background-color: #f7f8fa;
+
+        span {
+          display: flex;
+          column-gap: 14px;
+          align-items: center;
+        }
+      }
+
+      .svg-icon {
+        cursor: pointer;
+      }
+    }
+  }
+}
+</style>

+ 120 - 9
src/views/book/courseware/create/components/question/video_interaction/VideoInteraction.vue

@@ -17,8 +17,18 @@
         @updateFileList="updateFileList"
       />
       <div v-if="data.video_list.length > 0" class="interaction-box">
-        <video id="interaction-video" :src="data.video_list[0].file_url" width="100%" height="400" controls></video>
-        <el-button type="primary" size="small" @click="handlePause">暂停视频编辑题目</el-button>
+        <video
+          ref="videoPlayer"
+          id="interaction-video"
+          :src="data.video_list[0].file_url"
+          width="100%"
+          height="400"
+          controls
+          class="video-js vjs-default-skin vjs-big-play-centered"
+        ></video>
+        <!-- <video ref="videoPlayer" class="video-js vjs-default-skin vjs-big-play-centered"></video> -->
+
+        <el-button type="primary" size="small" @click="handlePause" style="margin-top: 5px">暂停视频编辑题目</el-button>
         <!-- <el-button @click="handleMultilingual">多语言</el-button> -->
         <ul v-if="data.file_info_list.length > 0" class="file-list">
           <li v-for="(file, i) in data.file_info_list" :key="i">
@@ -74,6 +84,11 @@ import { getVideoInteractionData } from '@/views/book/courseware/data/videoInter
 import { GetCoursewareExercise } from '@/api/book';
 import { getSelectData } from '@/views/book/courseware/data/select';
 
+import 'videojs-markers/dist/videojs.markers.min.css';
+import videojs from 'video.js';
+import 'video.js/dist/video-js.css';
+import 'videojs-markers';
+
 export default {
   name: 'VideoInteractionPage',
   components: { UploadFile, ExerciseAdd },
@@ -91,15 +106,21 @@ export default {
       file_id_list: [],
       loading: false,
       currentTime: 0,
+      duration: 0,
       multilingualText: '',
       exerciseContent: null,
+      playTime: 0,
+      player: null,
     };
   },
   watch: {
     'data.video_list': {
       handler(val) {
         if (val.length > 0) {
-          this.handleData();
+          let _this = this;
+          this.$nextTick(() => {
+            _this.handleCreatPlayer();
+          });
         }
       },
       immediate: true,
@@ -107,6 +128,83 @@ export default {
     'data.property.file_list': 'handleMindMap',
   },
   methods: {
+    // 初始化player
+    handleCreatPlayer(time) {
+      let _this = this;
+      let options = {
+        autoplay: false, //自动播放
+        height: 500,
+        width: 918,
+        controls: true, //用户可以与之交互的控件
+        loop: true, //视频一结束就重新开始
+        muted: false, //默认情况下将使所有音频静音
+        playsinline: true,
+        webkitPlaysinline: true,
+        // aspectRatio:"16:9",//显示比率
+        playbackRates: [0.5, 1, 1.5, 2],
+        fullscreen: {
+          options: { navigationUI: 'hide' },
+        },
+        sources: [
+          {
+            src: this.data.video_list[0].file_url,
+            type: 'video/mp4',
+          },
+        ],
+      };
+      this.player = videojs(this.$refs.videoPlayer, options, function onPlayerReady() {
+        // console.log('onPlayerReady');
+      });
+      // 设置标点
+      _this.handleMarkers();
+      // 获取当前播放时间
+      this.player.on('timeupdate', function (event) {
+        _this.currentTime = this.currentTime().toFixed(3);
+        // console.log(this.currentTime());
+      });
+    },
+    // 设置标点
+    handleMarkers() {
+      let markers = [];
+      this.data.file_info_list.forEach((item) => {
+        markers.push({
+          time: item.currentTime,
+        });
+      });
+      this.player.markers({
+        // 不显示鼠标悬浮标记提示文字
+        markerTip: {
+          display: true,
+        },
+        markerStyle: {
+          width: '4px',
+          'background-color': 'red',
+          'border-radius': '50%',
+        },
+        markers: markers,
+        // markers: [
+        //   {
+        //     time: 0.694313,
+        //     class: 'custom-marker-class',
+        //     text: '标记1',
+        //   },
+        //   {
+        //     time: 5.694313,
+        //     class: 'custom-marker-class',
+        //     text: '标记2',
+        //   },
+        //   {
+        //     time: 10.694313,
+        //     class: 'custom-marker-class',
+        //     text: '标记3',
+        //   },
+        //   {
+        //     time: 15.694313,
+        //     class: 'custom-marker-class',
+        //   },
+        // ],
+      });
+    },
     updateFileList({ file_list, file_id_list, file_info_list }) {
       this.data.video_list = file_list;
       this.data.video_id_list = file_id_list;
@@ -114,6 +212,8 @@ export default {
       this.data.video_info_list = file_info_list;
       if (file_list.length === 0) {
         this.data.file_info_list = [];
+      } else {
+        this.duration = file_list[0].media_duration;
       }
     },
 
@@ -142,15 +242,16 @@ export default {
       if (file_list.length > 0 && file_list[0].file_id) {
         let obj = file_list[0];
         obj.currentTime = this.currentTime;
+        obj.position = (this.currentTime / this.duration) * 100;
         this.data.file_info_list.push(obj);
         this.sourceAddFlag = false;
-        document.getElementById('interaction-video').play();
+        this.player.play();
       }
     },
     handleCancle() {
       // this.sourceAddFlag = false;
       this.exerciseFlag = false;
-      document.getElementById('interaction-video').play();
+      this.player.play();
     },
     // 确定新增资源
     submitAdd(id, type, isAdd) {
@@ -159,6 +260,7 @@ export default {
           currentTime: this.currentTime,
           file_name: type,
           id,
+          position: (this.currentTime / this.duration) * 100,
         });
         this.file_id_list.push(id);
       } else {
@@ -167,13 +269,16 @@ export default {
       }
 
       this.exerciseFlag = false;
-      document.getElementById('interaction-video').play();
+      // document.getElementById('interaction-video').play();
+      this.player.play();
     },
     // 暂停视频上传资源
     handlePause() {
-      const video = document.getElementById('interaction-video');
-      video.pause();
-      this.currentTime = video.currentTime.toFixed(3);
+      // const video = document.getElementById('interaction-video');
+      // video.pause();
+      // this.currentTime = video.currentTime.toFixed(3);
+      this.playTime = JSON.parse(JSON.stringify(this.currentTime));
+      this.player.pause();
       this.file_list = [];
       this.file_id_list = [];
       // this.sourceAddFlag = true;
@@ -223,6 +328,12 @@ export default {
         });
     },
   },
+  mounted() {},
+  beforeDestroy() {
+    if (this.player) {
+      this.player.dispose();
+    }
+  },
 };
 </script>
 <style lang="scss" scoped>

+ 93 - 12
src/views/book/courseware/preview/components/video_interaction/VideoInteractionPreview.vue

@@ -3,7 +3,7 @@
   <div class="imageText-preview" :style="[getAreaStyle(), getComponentStyle()]">
     <SerialNumberPosition v-if="isEnable(data.property.sn_display_mode)" :property="data.property" />
     <div v-if="data.video_list.length > 0" class="interaction-box">
-      <video
+      <!-- <video
         id="interaction-preview-video"
         :src="data.video_list[0].file_url"
         width="100%"
@@ -11,6 +11,15 @@
         controls
         controlsList="nodownload"
         @timeupdate="handleTimeUpdate"
+      ></video> -->
+      <video
+        ref="videoPlayer"
+        id="interaction-preview-video"
+        :src="data.video_list[0].file_url"
+        width="100%"
+        height="400"
+        controls
+        class="video-js vjs-default-skin vjs-big-play-centered"
       ></video>
     </div>
     <!-- v-if="Object.keys(this.userAnswer).length === data.file_info_list.length" -->
@@ -21,6 +30,7 @@
           data.unified_attrib && data.unified_attrib.topic_color ? data.unified_attrib.topic_color : '#165dff',
         borderColor:
           data.unified_attrib && data.unified_attrib.topic_color ? data.unified_attrib.topic_color : '#165dff',
+        marginTop: '5px',
       }"
       @click="lookReport"
       >{{ convertText('查看答题报告') }}</el-button
@@ -77,6 +87,10 @@ import Report from './Report.vue';
 import PreviewMixin from '../common/PreviewMixin';
 import { getVideoInteractionData } from '@/views/book/courseware/data/videoInteraction';
 import { getConfig } from '@/utils/auth';
+import 'videojs-markers/dist/videojs.markers.min.css';
+import videojs from 'video.js';
+import 'video.js/dist/video-js.css';
+import 'videojs-markers';
 export default {
   name: 'VideoInteractionPreview',
 
@@ -107,6 +121,7 @@ export default {
         error: 0,
         rightRate: 0,
       },
+      player: null,
     };
   },
   watch: {
@@ -125,18 +140,79 @@ export default {
       if (!this.isJudgingRightWrong) {
         this.answer.answer_list[0] = this.userAnswer;
       }
+      if (this.data.video_list.length > 0) {
+        let _this = this;
+        this.$nextTick(() => {
+          _this.handleCreatPlayer();
+        });
+      }
     },
-    handleTimeUpdate(event) {
-      let currentTime = event.target.currentTime;
-
+    // 初始化player
+    handleCreatPlayer() {
+      let _this = this;
+      let options = {
+        autoplay: false, //自动播放
+        height: 500,
+        width: 918,
+        controls: true, //用户可以与之交互的控件
+        loop: true, //视频一结束就重新开始
+        muted: false, //默认情况下将使所有音频静音
+        playsinline: true,
+        webkitPlaysinline: true,
+        // aspectRatio:"16:9",//显示比率
+        playbackRates: [0.5, 1, 1.5, 2],
+        fullscreen: {
+          options: { navigationUI: 'hide' },
+        },
+        sources: [
+          {
+            src: this.data.video_list[0].file_url,
+            type: 'video/mp4',
+          },
+        ],
+      };
+      this.player = videojs(this.$refs.videoPlayer, options, function onPlayerReady() {
+        // console.log('onPlayerReady');
+      });
+      // 设置标点
+      _this.handleMarkers();
+      // 获取当前播放时间
+      this.player.on('timeupdate', function (event) {
+        _this.handleTimeUpdate(this.currentTime());
+        // console.log(this.currentTime());
+      });
+    },
+    // 设置标点
+    handleMarkers() {
+      let markers = [];
+      this.data.file_info_list.forEach((item) => {
+        markers.push({
+          time: item.currentTime,
+          text: '',
+        });
+      });
+      this.player.markers({
+        // 不显示鼠标悬浮标记提示文字
+        markerTip: {
+          display: true,
+        },
+        markerStyle: {
+          width: '4px',
+          'background-color': 'red',
+          'border-radius': '50%',
+        },
+        markers: markers,
+      });
+    },
+    handleTimeUpdate(currentTime) {
       this.data.file_info_list.forEach((item) => {
         if (
-          Number(item.currentTime) > Math.floor(currentTime) &&
-          Number(item.currentTime) < Math.floor(currentTime) + 1 &&
+          Number(item.currentTime) > Math.floor(currentTime) - 0.3 &&
+          Number(item.currentTime) < Math.floor(currentTime) + 0.3 &&
           item.id !== this.first
         ) {
           this.first = item.id;
-          document.getElementById('interaction-preview-video').pause();
+          this.player.pause();
           this.exercise_id = item.id;
           this.visible = true;
           // GetFileURLMap({ file_id_list: [item.file_id] }).then(({ url_map }) => {
@@ -148,22 +224,22 @@ export default {
     },
     handleClose() {
       this.reportFlag = false;
-      document.getElementById('interaction-preview-video').play();
+      this.player.play();
       // setTimeout(() => {
       //   this.first = '';
       // }, 1000);
     },
     submitAdd(id, answer, content) {
       this.visible = false;
-      document.getElementById('interaction-preview-video').play();
+      this.player.play();
       setTimeout(() => {
-        this.first = '';
-      }, 1000);
+        // this.first = '';
+      }, 2000);
       this.$set(this.userAnswer, id, answer);
       this.$set(this.exerciseList, id, content);
     },
     lookReport() {
-      document.getElementById('interaction-preview-video').pause();
+      this.player.pause();
       let num = 0;
       let total = this.data.file_info_list.length;
       Object.keys(this.userAnswer).forEach((key) => {
@@ -180,6 +256,11 @@ export default {
       this.reportFlag = true;
     },
   },
+  beforeDestroy() {
+    if (this.player) {
+      this.player.dispose();
+    }
+  },
 };
 </script>