首页 > 其他分享 >vue 视频上传组件

vue 视频上传组件

时间:2023-11-28 11:04:17浏览次数:23  
标签:vue return data height width video 组件 上传

组件:

<template>
  <div class="upload-box">
    <div class="avatar-uploader-box">
      <!-- 图片预览 -->
      <div :key="index" class="video-preview" v-for="(item, index) in videoList">
        <video v-if="item.videoLink" :src="`${videoBaseUrl}${item.videoLink}`" @mouseover.stop="item.isShowPopup = true" class="avatar">
          您的浏览器不支持视频播放
        </video>
        <video v-else :src="item.url" @mouseover.stop="item.isShowPopup = true" class="avatar">
          您的浏览器不支持视频播放
        </video>
        <!-- 显示查看和删除的按钮弹窗 -->
        <div
          @mouseleave="item.isShowPopup = false"
          class="avatar-uploader-popup"
          v-show="(item.videoLink || item.url) && item.isShowPopup"
        >
          <i @click="previewVideo(item)" class="el-icon-zoom-in"></i>
          <i @click="deleteVideo(index)" class="el-icon-delete"></i>
        </div>
      </div>      <!-- 方框样式 -->
      <el-upload
        :action="actionUrl"
        :auto-upload="false"
        :on-change="handleAvatarChange"
        :show-file-list="false"
        class="avatar-uploader"
        ref="avatarUploader"
        v-show="uploadShow"
      >
        <span
          element-loading-background="rgba(0, 0, 0, 0.8)"
          element-loading-spinner="el-icon-loading"
          element-loading-text="上传中"
          style="display:block;"
          v-loading="loading"
        >
          <i class="el-icon-plus avatar-uploader-icon"></i>
        </span>
      </el-upload>      <!-- 上传提示文字样式 -->
      <div class="upload-tip">
        <slot></slot>
      </div>
    </div>    <!-- 查看大图 -->
    <el-dialog :visible.sync="dialogVisible" append-to-body center title="视频查看" :before-close="handleClose">
      <video :src="videoSrc" ref="video" controls alt width="100%">您的浏览器不支持视频播放</video>
    </el-dialog>
  </div>
</template><script>
export default {
  name: 'UploadVideo',
  components: {},
  props: {
    videos: {
      type: Array,
      default: function() {
        return []
      }
    },
    numLimit: {
      // 最大允许上传个数
      type: Number,
      default: 1
    },
    sizeLimit: {
      // 最大单文件大小
      type: Number,
      default: 50
    },
    videoBaseUrl: {
      // 已上传图片服务器路径
      type: String,
      required: true
    }
  },
  data() {
    return {
      loading: false,
      dialogVisible: false,
      videoList: [],
      videoSrc: '',
      actionUrl: ''
    }
  },
  computed: {
    uploadShow() {
      return this.videos.length < this.numLimit
    }
  },
  watch: {
    videos: {
      handler() {
        const isArray = Array.isArray(this.videos)
        if (isArray && this.videos.length > 0) {
          this.videos.map(item => {
            item.isShowPopup = false
          })
          this.videoList = JSON.parse(JSON.stringify(this.videos))
        } else {
          this.videoList = []
        }
      },
      deep: true,
      immediate: true
    }
  },
  created() {},
  methods: {
    // 上传之前
    beforeAvatarUpload(file) {
      return new Promise((resolve, reject) => {
        if (['video/mp4', 'video/ogg', 'video/flv', 'video/avi', 'video/wmv', 'video/rmvb', 'video/mov'].indexOf(file.raw.type) == -1) {
          // eslint-disable-next-line prefer-promise-reject-errors
          return reject('请上传正确的视频格式!')
        }        if (file.size / 1024 / 1024 > this.sizeLimit) {
          // eslint-disable-next-line prefer-promise-reject-errors
          return reject(`视频大小不能超过${this.sizeLimit}M!`)
        }        if (this.videoList.length === this.numLimit) {
          // eslint-disable-next-line prefer-promise-reject-errors
          return reject(`最多上传${this.numLimit}个视频`)
        }        resolve('符合表單規則')
      })
    },
    // 上传改变
    async handleAvatarChange(file, fileList) {
      try {
        await this.beforeAvatarUpload(file)
        this.uploadImgApi(file)
      } catch (e) {
        this.$message.warning(JSON.stringify(e))
      }
    },
    // 上传视频准备
    uploadImgApi(data) {
      console.log(data, 'upload**')
      const videoSrc = URL.createObjectURL(data.raw)
      this.videoList.push({
        videoFile: data,
        url: videoSrc,
        isShowPopup: false
      })
      this.$emit('change', this.videoList)
    },
    // 预览视频
    previewVideo(data) {
      if (data.videoLink) {
        this.videoSrc = `${this.videoBaseUrl}${data.videoLink}`
      } else {
        this.videoSrc = data.url
      }
      this.dialogVisible = true
    },
    // 删除视频
    deleteVideo(index) {
      this.$emit('delete', index)
    },
    handleClose() {
      const video = document.getElementsByTagName('video')[1]
      if (!video.paused) {
        video.currentTime = 0
        video.pause()
      }
      this.dialogVisible = false
    }
  }
}
</script><style lang="scss">
$width: 90px;
$height: 90px;.upload-box {
  .avatar-uploader-box {
    position: relative;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    padding-bottom: 20px;
    min-width: 350px;
    .avatar-uploader {
      .el-upload {
        width: $width;
        height: $height;
        border: 1px dashed #d9d9d9;
        border-radius: 6px;
        cursor: pointer;
        position: relative;
        overflow: hidden;
        &:hover {
          border-color: #409eff;
        }
        .el-loading-spinner {
          width: $width;
          height: $height;
          position: relative;
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          margin-top: 0;
          top: 0;
          .el-loading-text {
            margin: 0;
          }
        }
      }
      .avatar-uploader-icon {
        font-size: 28px;
        color: #8c939d;
        width: $width;
        height: $height;
        line-height: $height;
        text-align: center;
      }
    }
    .video-preview {
      position: relative;
      padding-right: 20px;
      .avatar {
        width: $width;
        height: $height;
        display: block;
        border-radius: 6px;
      }
      .avatar-uploader-popup {
        position: absolute;
        top: 0;
        left: 0;
        z-index: 2;
        width: $width;
        height: $height;
        background: rgba($color: #000000, $alpha: 0.5);
        display: flex;
        justify-content: center;
        align-items: center;
        color: #fff;
        font-size: 20px;
        border-radius: 6px;
        i {
          width: 30%;
          text-align: center;
          padding: 0 5%;
          font-size: 24px;
        }
      }
    }
    .upload-tip {
      position: absolute;
      bottom: 0;
      left: 0;
      font-size: 12px;
      color: #606266;
      max-width: 350px;
      line-height: 20px;
    }
  }
}
</style>页面引入:
import UploadVideo from '@c/UploadVideo'

components: { UploadVideo }

<upload-video
  :videos="videoInfo.allVideo"
  :videoBaseUrl="IMAGEURL"
  @delete="deleteVideo"
  @change="getVideo" >
</upload-video>
data数据:videoInfo: {
   allVideo: [],
   deleteVideo: []
}
视频上传:(此处只是上传到暂存区,真正上传是在提交表单时)getVideo(event) {
  this.videoInfo.allVideo = event
}
视频删除:deleteVideo(index) {
  const video = this.videoInfo.allVideo[index]
  if (video.videoLink) {
  this.videoInfo.deleteVideo.push(video)
  }
  this.videoInfo.allVideo.splice(index, 1)
}
在提交表单时上传:uploadFiles() {
  const uploadList = []
  this.videoInfo.allVideo.map(item => {
        console.log(item, 'video')
        const videoFile = new FormData()
        if (!item.videoLink) {
          videoFile.append('file', item.videoFile.raw)
          videoFile.append('fileTag', 'video')
          uploadList.push(
            new Promise((resolve, reject) => {
              return ImgServe.uploadSingleFile(videoFile).then(res => {
                if (res.data.code === 200) {
                  resolve(res.data.data)
                } else {
                  this.$message('上传视频失败!')
                }
              })
            })
          )
        }
      })
      return Promise.all(uploadList)
}*:分开上传是为了杜绝服务器脏数据
ImgServe.uploadSingleFile(videoFile)这儿是上传到服务器的接口,替换为自己的写法即可

 

参考文章:http://blog.ncmem.com/wordpress/2023/11/03/vue-视频上传组件/


 

标签:vue,return,data,height,width,video,组件,上传
From: https://blog.51cto.com/u_14023400/8597135

相关文章

  • vue图片上传视频
    图片上传是现在Web开发中常见的需求之一。而使用Vue框架可以使得这一过程更加方便和有效。在Vue中使用预先开发好的组件,可以快速地实现图片上传功能。//在Vue组件中引用插件importVueUploadComponentfrom'vue-upload-component'//在模板中引用组件上面的代码使用VueUpload......
  • vue上传视频框架
    在Web应用程序中经常需要用户上传视频,以便内容分享,教程和其他目的。Vue.js是一种流行的JavaScript框架,它提供了一种方便的方式来设计交互式和动态的用户界面,因此Vue上传视频框架是一种非常受欢迎的技术。Vue.js框架提供了各种插件和工具,它们可以帮助开发人员轻松地实现视频上传功能......
  • 使用 CKEditor 上传图片, 粘贴屏幕截图
    之前写过wangEditor,那真是好用,文档也清晰,半天就搞定了,无奈没有对应license,只好选择别的。外语一般,阅读理解都靠蒙。CKEditor官方文档看的我云里雾里,国内的博客比较少,经过一天的调试,终于成功了。记录下,欢迎交流。1.下载CKEditor包。 打开samples文件夹下的index.html,确认ckedi......
  • PHP大文件分割上传详解
    这篇文章主要为大家详细介绍了PHP大文件分割上传,PHP分片上传,具有一定的参考价值,感兴趣的小伙伴们可以参考一下服务端为什么不能直接传大文件?跟php.ini里面的几个配置有关upload_max_filesize=2M//PHP最大能接受的文件大小post_max_size=8M//PHP能收到的最大POST值'memory_l......
  • CKEDITOR图片上传实现详细步骤
    CKEditor的编辑器工具栏中有一项“图片域”,该工具可以贴上图片地址来在文本编辑器中加入图片,但是没有图片上传。  “预览”中有一大堆鸟语,看得很不爽。可以打开ckeditor/plugins/image/dialogs/image.js文件,搜索“b.config.image_previewText”就能找到这段鸟语了,(b.config.image......
  • Vue3 + [email protected] + UploadPictureCard
    <template><a-uploadname="file"v-model:file-list="showFileList"list-type="picture-card":multiple="multiple":max-count="maxCount":before-up......
  • 界面控件DevExpress WPF流程图组件,完美复制Visio UI!(二)
    DevExpressWPFDiagram(流程图)控件帮助用户完美复制MicrosoftVisioUI,并将信息丰富且组织良好的图表、流程图和组织图轻松合并到您的下一个WPF项目中。在上文中(点击这里回顾>>),我们为大家介绍了DevExpressWPFDiagram(流程图)组件性能优异切信息丰富的流程图功能、轻松地从数据源......
  • vue引入外部样式只在当前文件生效
    引入外部文件时,想要只在当前组件使用,但是我们使用如下方式时,会在全局使用。因为在scoped起作用的时候,import还没有引入这个文件<stylescoped>@import"../../xx.css"</style>使用以下方式即可<stylescopedsrc="../../xx.css"></style> ......
  • 【源码系列#02】Vue3响应式原理(Effect)
    专栏分享:vue2源码专栏,vue3源码专栏,vuerouter源码专栏,玩具项目专栏,硬核......
  • 弄明白文件上传
    先从一个例子开始,看一下掘金上传头像接口。请求头:注意看图片中的content-type,后面会解释:content-type:multipart/form-data;boundary=----WebKitFormBoundarycA7SgHXGF2nIiW3S再看一下请求携带的参数(接口中还带了一大串查询参数,这不是重点,重点是form-data参数):从上图中......