Bladeren bron

视频交互

natasha 2 dagen geleden
bovenliggende
commit
989eb3db3c

+ 1 - 1
src/views/book/courseware/create/components/base/common/UploadFile.vue

@@ -252,7 +252,7 @@ export default {
       } else if (this.type === 'picture' || this.type === 'image_text' || this.type === 'drawing') {
         fileType = ['jpg', 'png', 'jpeg'];
         typeTip = '图片文件只能是 jpg、png、jpeg 格式!';
-      } else if (this.type === 'video') {
+      } else if (this.type === 'video' || this.type === 'video_interaction') {
         fileType = ['mp4'];
         typeTip = '视频文件只能是 mp4 格式!';
       } else if (this.type === 'upload_preview') {

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

@@ -0,0 +1,120 @@
+<template>
+  <ModuleBase :type="data.type">
+    <template #content>
+      <UploadFile
+        key="upload_image"
+        :courseware-id="courseware_id"
+        :component-id="id"
+        :type="data.type"
+        :total-size="data.total_size"
+        :file-list="data.video_list"
+        :file-id-list="data.video_info_list"
+        :file-info-list="data.video_id_list"
+        :label-text="labelText"
+        :accept-file-type="acceptFileType"
+        :icon-class="iconClass"
+        :upload-tip="uploadTip"
+        :limit="1"
+        :single-size="500"
+        @updateFileList="updateFileList"
+      />
+    </template>
+  </ModuleBase>
+</template>
+
+<script>
+import ModuleMixin from '../../common/ModuleMixin';
+import UploadFile from '../../base/common/UploadFile.vue';
+import { getVideoInteractionData } from '@/views/book/courseware/data/videoInteraction';
+import SelectUpload from '@/views/book/courseware/create/components/common/SelectUpload.vue';
+import { GetFileURLMap } from '@/api/app';
+
+export default {
+  name: 'VideoInteractionPage',
+  components: { UploadFile, SelectUpload },
+  mixins: [ModuleMixin],
+  data() {
+    return {
+      data: getVideoInteractionData(),
+      labelText: '视频',
+      acceptFileType: '.mp4',
+      uploadTip: '支持上传mp4格式视频文件,单个视频文件最大2GB,总文件体积不超10GB。',
+      iconClass: 'video',
+    };
+  },
+  watch: {
+    'data.video_list': {
+      handler(val) {
+        if (val.length > 0) {
+          this.handleData();
+        }
+      },
+      immediate: true,
+    },
+    'data.property.file_list': 'handleMindMap',
+  },
+  methods: {
+    updateFileList({ file_list, file_id_list, file_info_list }) {
+      this.data.video_list = file_list;
+      this.data.video_id_list = file_id_list;
+      this.data.video_id_list = file_info_list;
+    },
+
+    handleData() {
+      this.data.video_list.forEach((item) => {
+        GetFileURLMap({ file_id_list: [item.file_id] }).then(({ url_map }) => {
+          this.$set(item, 'file_url', url_map[item.file_id]);
+        });
+      });
+    },
+    handleMindMap() {
+      // 思维导图数据
+      let node_list = [];
+      this.data.file_list.forEach((item) => {
+        node_list.push({
+          name: item.file_name,
+          id: Math.random().toString(36).substring(2, 12),
+        });
+      });
+      this.data.mind_map.node_list = node_list;
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.upload-file {
+  display: flex;
+  column-gap: 12px;
+  align-items: center;
+  margin: 8px 0;
+
+  .file-name {
+    display: flex;
+    column-gap: 14px;
+    align-items: center;
+    justify-content: space-between;
+    max-width: 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;
+  }
+}
+
+.image-size {
+  display: flex;
+  gap: 10px;
+  align-items: center;
+  padding: 20px 0;
+}
+</style>

+ 32 - 0
src/views/book/courseware/create/components/question/video_interaction/VideoInteractionSetting.vue

@@ -0,0 +1,32 @@
+<template>
+  <div>
+    <el-form :model="property" label-width="72px" label-position="left">
+      <SerailNumber :property="property" />
+    </el-form>
+  </div>
+</template>
+
+<script>
+import SettingMixin from '@/views/book/courseware/create/components/common/SettingMixin';
+
+import { getVideoInteractionProperty } from '@/views/book/courseware/data/videoInteraction';
+
+export default {
+  name: 'VideoInteractionSetting',
+  mixins: [SettingMixin],
+  data() {
+    return {
+      property: getVideoInteractionProperty(),
+    };
+  },
+  methods: {},
+};
+</script>
+
+<style lang="scss" scoped>
+@use '@/styles/mixin.scss' as *;
+
+.el-form {
+  @include setting-base;
+}
+</style>

+ 11 - 0
src/views/book/courseware/data/bookType.js

@@ -61,6 +61,8 @@ import H5Games from '../create/components/base/h5_games/H5Games.vue';
 import H5GamesSetting from '../create/components/base/h5_games/H5GamesSetting.vue';
 import Drawing from '../create/components/question/drawing/Drawing.vue';
 import DrawingSetting from '../create/components/question/drawing/DrawingSetting.vue';
+import VideoInteraction from '../create/components/question/video_interaction/VideoInteraction.vue';
+import VideoInteractionSetting from '../create/components/question/video_interaction/VideoInteractionSetting.vue';
 
 // 预览组件页面列表
 import AudioPreview from '@/views/book/courseware/preview/components/audio/AudioPreview.vue';
@@ -95,6 +97,7 @@ import WriteBasePreview from '../preview/components/write_base/WriteBasePreview.
 import ImageTextPreview from '../preview/components/image_text/ImageTextPreview.vue';
 import H5GamesPreview from '../preview/components/h5_games/H5GamesPreview.vue';
 import DrawingPreview from '../preview/components/drawing/DrawingPreview.vue';
+import VideoInteractionPreview from '../preview/components/video_interaction/VideoInteractionPreview.vue';
 
 export const bookTypeOption = [
   {
@@ -349,6 +352,14 @@ export const bookTypeOption = [
         preview: PinyinBasePreview,
       },
       {
+        value: 'video_interaction',
+        label: '视频交互',
+        icon: '',
+        component: VideoInteraction,
+        set: VideoInteractionSetting,
+        preview: VideoInteractionPreview,
+      },
+      {
         value: 'drawing',
         label: '画板',
         icon: '',

+ 39 - 0
src/views/book/courseware/data/videoInteraction.js

@@ -0,0 +1,39 @@
+import {
+  displayList,
+  serialNumberTypeList,
+  serialNumberPositionList,
+  isEnable,
+} from '@/views/book/courseware/data/common';
+
+export { isEnable };
+
+export function getVideoInteractionProperty() {
+  return {
+    serial_number: 1,
+    sn_type: serialNumberTypeList[0].value,
+    sn_position: serialNumberPositionList[3].value,
+    sn_display_mode: displayList[0].value,   
+  };
+}
+
+export function getVideoInteractionData() {
+  return {
+    type: 'video_interaction',
+    title: '视频交互题',
+    property: getVideoInteractionProperty(),
+    total_size: 30000, // 单位MB
+    video_list: [], // 视频列表
+    video_info_list: [],
+    video_id_list: [], // 视频文件 id
+    file_list: [], // 文件列表
+    file_info_list: [],
+    file_id_list: [], // 视频文件 id
+    mind_map: {
+      node_list: [
+      ], // 思维导图数据
+    },
+    answer: {
+      answer_list: [],
+    },
+  };
+}

+ 1 - 3
src/views/book/courseware/preview/components/drawing/DrawingPreview.vue

@@ -73,9 +73,7 @@ export default {
   created() {
     this.initData();
   },
-  mounted() {
-    this.audio_width = document.getElementsByClassName('imageText-preview')[0].clientWidth - 150;
-  },
+  mounted() {},
   methods: {
     initData() {
       if (!this.isJudgingRightWrong) {

+ 87 - 0
src/views/book/courseware/preview/components/video_interaction/VideoInteractionPreview.vue

@@ -0,0 +1,87 @@
+<!-- eslint-disable vue/no-v-html -->
+<template>
+  <div class="imageText-preview" :style="getAreaStyle()">
+    <SerialNumberPosition v-if="isEnable(data.property.sn_display_mode)" :property="data.property" />
+  </div>
+</template>
+
+<script>
+import PreviewMixin from '../common/PreviewMixin';
+import { getVideoInteractionData } from '@/views/book/courseware/data/videoInteraction';
+import { GetFileURLMap } from '@/api/app';
+export default {
+  name: 'VideoInteractionPreview',
+
+  components: {},
+  mixins: [PreviewMixin],
+  data() {
+    return {
+      data: getVideoInteractionData(),
+      video_info: null,
+    };
+  },
+  created() {
+    this.initData();
+  },
+  mounted() {},
+  methods: {
+    initData() {
+      if (!this.isJudgingRightWrong) {
+        this.answer.answer_list = [];
+        let obj = {
+          answer: '',
+        };
+        this.answer.answer_list.push(obj);
+      }
+
+      this.data.video_list.forEach((item) => {
+        GetFileURLMap({ file_id_list: [item.file_id] }).then(({ url_map }) => {
+          this.video_info = url_map[item.file_id];
+        });
+      });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+@use '@/styles/mixin.scss' as *;
+
+.img-box {
+  position: relative;
+  margin: 20px auto;
+}
+
+.pen {
+  display: flex;
+  align-items: center;
+  justify-content: flex-end;
+
+  .save {
+    box-sizing: border-box;
+    width: 65px;
+    height: 32px;
+    margin-left: 16px;
+    font-size: 16px;
+    font-weight: 400;
+    line-height: 32px;
+    color: #000;
+    text-align: center;
+    cursor: pointer;
+    background: rgba(0, 0, 0, 5%);
+    border: 1px solid rgba(0, 0, 0, 10%);
+    border-radius: 6px;
+  }
+
+  .save:hover {
+    background: rgba(0, 0, 0, 25%);
+  }
+
+  > img {
+    width: 24px;
+    height: 24px;
+    margin: 0 8px;
+    cursor: pointer;
+  }
+}
+</style>