图片复制上传,拖拽输入框上传,el-upload自定义上传方法(上传和备注框强关联)

1. 效果图:

2. 复制图片使用的方法:

  • 1.通过监听paste方法,获取复制内容
  • 2.获取复制内容中的clipboardData
  • 3.获取file文件进行上传


handlePaste(value){
   let files = value.clipboardData.files
   if(files){
     files=files[0]
   }else{
     files=value.clipboardData.items[0].getAsFile()
   }
   console.log(files)
}

3. 拖拽使用的方法:

  • 1.通过监听dragoverdropdragleave事件,进行判断拖拽
  • 2.drop释放鼠标时,获取对应文件的file并上传
 const e=Dom //节点

 // 挂载监听拖拽
 e.removeEventListener('dragover',this.handletDragover,false)
 e.addEventListener('dragover',this.handlePaste,false)

 // 挂载监听释放
 e.removeEventListener('drop',this.handletDrop,false)
 e.addEventListener('drop',this.handletDrop,false)

// 挂载监听离开
 e.removeEventListener('dragleave',this.handletDragleave,false)
 e.addEventListener('dragleave',this.handletDragleave,false)
 
 
 const handletDragover(e)=>{
        e.preventDefault();
        // 当拖拽到对应元素是设置样式
 }
const handletDragleave(e)=>{
      // 离开对应元素是设置样式
}
 const handletDrop(e)=>{
      const files = e.dataTransfer.files;
      // 获取对应的files,并进行上传
      e.preventDefault();
      e.stopPropagation();
   }

4. el-upload封装对应方法,并实现限制种类、大小等

  • 1.组件(copy-upload.vue):

    <template>
      <el-upload
                :action="sendUrl"
                :accept="acceptArray.length>0?acceptArray.map(n=>this.acceptType[n]).join(',') :'*'"
                class="upload-demo"
                :http-request="handleFileUpload"
                :headers="headers"
                :data="data"
                :on-preview="handlePreview"
                :on-remove="handleRemove"
                :before-upload="beforeUpload"
                :before-remove="beforeRemove"
                :on-success="handleSuccess"
                :on-erroe="handleError"
                :multiple="multiple"
                :limit="limit"
                :on-exceed="handleExceed"
                :file-list="fileList">
                <el-button size="small" type="primary">点击上传el-button>
                <div v-if="size>0" slot="tip" class="el-upload__tip">{{ acceptTitle!=''?acceptTitle :`只能上传${(acceptArray.map(n=>n=='image'?'图片':n).join('/'))}文件` }},且不超过{{ filterSize(size) }}div>
              el-upload>
    template>
    
    <script>
      export default {
        model:{
          prop:'parentFileList',
          event:'change-fileList'
        },
        props: {
            // 请求头
           headers:{
            type:Object,
            default:()=>{}
          },
            //   大小限制:10 * 1024 * 1024 = 10MB
          size:{
            type:Number,
            default:-1
          },
          //   展示的文字
          acceptTitle:{
            type:String,
            default:''
          },
          //   限制类型,按照acceptType数组里面来
          acceptArray:{
            type:Array,
            default(){
              return ['doc', 'docx', 'pdf', 'xls', 'xlsx','png','jpg','jpeg','gif']
            }
          },
          //  数量
          limit:{
            type:Number,
            default:null
          },
         //   是否可以多选
          multiple:{
            type:Boolean,
            default:false
          },
        //   额外数据
          data:{
            type:Object,
            default() {
                return {
                  uploadType: 'common',
                  security:'public',
                  module:'common',
              }
            }
          },
          // 存在的数据(v-model关联的)
          parentFileList:{
            type:Array,
            default(){
              return []
            }
          },
         //   请求头
          sendUrl:{
            type:String,
            default:''
          }
        },
        data() {
          return {
            acceptType:{
              'doc':'application/msword',
              'docx':'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
              'ppt':"application/vnd.ms-powerpoint",
              'pptx':'application/vnd.openxmlformats-officedocument.presentationml.presentation',
              'xls':'application/vnd.ms-excel',
              'xlsx':'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
              'pdf':'application/pdf',
              'csv':'.csv',
              'txt':'text/plain',
              'image':'image/*',
              'png':'image/png',
              'gif':'image/gif',
              'jpg':'image/jpg',
              'jpeg':'image/jpeg'
            },
            fileList:[],
            isClearTitle:true
          };
        },
        watch: {
          parentFileList:{
            handler(value){
              this.fileList=value
            },
            deep:true,
            immediate:true
          },
          fileList:{
            handler(value){
              this.$emit('change-fileList',value)
            },
            deep:true,
          }
        },
        created(){
          // 抛处监听请求
          this.$emit('inpuPaste',(e)=>{
            if(e){
              // 挂载监听复制
              e.removeEventListener('paste',this.handlePaste,false)
              e.addEventListener('paste',this.handlePaste,false)
            }
    
          })
    
          this.$emit('inpuDrag',(e)=>{
            if(e){
              // 挂载监听拖拽
              e.removeEventListener('dragover',this.handletDragover,false)
              e.addEventListener('dragover',this.handlePaste,false)
    
              // 挂载监听释放
              e.removeEventListener('drop',this.handletDrop,false)
              e.addEventListener('drop',this.handletDrop,false)
    
              // 挂载监听离开
              e.removeEventListener('dragleave',this.handletDragleave,false)
              e.addEventListener('dragleave',this.handletDragleave,false)
            }
    
          })
        },
        methods: {
          handletDragover(e){
            e.preventDefault();
          },
          handletDragleave(e){
          },
          handletDrop(e){
            const files = e.dataTransfer.files;
            this.copyUp(files)
            e.preventDefault();
            e.stopPropagation();
          },
          filterSize(size){
              const pow1024=(num)=>{
                  return Math.pow(1024, num)
              }
              if (!size) return ''
              if (size < pow1024(1)) return size + ' B'
              if (size < pow1024(2)) return (size / pow1024(1)).toFixed(0) + ' KB'
              if (size < pow1024(3)) return (size / pow1024(2)).toFixed(0) + ' MB'
              if (size < pow1024(4)) return (size / pow1024(3)).toFixed(0) + ' GB'
              return (size / pow1024(4)).toFixed(2) + ' TB'
          },
          // 判断
          judegFileSize(file){
            let retunBoolean=true
            let fileSize = file.size
            //判断文件类型
            const fileExtArray=file.name.split('.')
            const judegFn=()=>{
              if(this.acceptArray.indexOf(fileExtArray.at(-1))==-1){
                this.$message.error(`${file.name}上传失败,只能上传${this.acceptArray.join('、')}`)
                retunBoolean=false
              }
            }
            if(this.acceptArray.length>0){
              if(this.acceptArray.indexOf('image')!=-1){
                var pattern = /(\.jpg|\.jpeg|\.png|\.gif)$/i;
                // 判断文件名是否匹配图片格式的正则表达式
                if (!pattern.test(`.${fileExtArray.at(-1)}`)) {
                  judegFn()
                }
              }else{
                judegFn()
              }
    
            }
            if(retunBoolean){
              if (this.size>0 &&  fileSize > this.size) {
                this.$message.error(`最大上传${this.filterSize(this.size)}`)
                retunBoolean=false
              }
            }
            if(!retunBoolean){
              this.isClearTitle=false
            }
            return retunBoolean
          },
          postUpObject(file){
            return {
                action:this.sendUrl,
                data:this.data,
                file:file,
                headers:this.headers,
                onSuccess:this.handleSuccess,
                onError:this.handleError
              }
          },
          // 自定义上传
          handleFileUpload(data) {
            const formData = new FormData();
            formData.append("file", data.file);
            if(data.data){
              Object.keys(data.data).forEach(key => {
                formData.append(key, data.data[key]);
              })
            }
            fetch(data.action, {
                    method: "POST",
                    body: formData,
                    headers: data.headers,
                    'Content-type': 'multipart/form-data'
              })
              .then(respone => respone.json())
              .then(res=>{
                if (data.onSuccess) data.onSuccess(res, data.file, this.fileList)
              }).catch(error=>{
                if (data.onError) data.onError({message:'上传失败'}, data.file, this.fileList)
            })
          },
          // 上传之前,需要将数据追加到fileList,复制图片是存在复制
          beforeUpload(file){
            const isFile=this.judegFileSize(file)
            if(isFile){
              if(this.multiple){
                this.fileList.push(file)
              }else{
                this.fileList=[file]
              }
            }
            return isFile
          },
    
          // 点击(预览),需要在成功后将url放入file里面
          handlePreview(file) {
            if(file.status=="success" && file.url){
              const extArray=file.url.split('.')
              const extArrayAll=['doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx']
              if(extArrayAll.indexOf(extArray.at(-1))!=-1){
                window.open(`https://view.officeapps.live.com/op/view.aspx?src=${file.url}`)
              }else{
                window.open('http://www.pfile.com.cn/api/profile/onlinePreview?url='+encodeURIComponent(file.url));
              }
            }
          },
          // 超过限制
          handleExceed(files, fileList) {
            this.$message.warning(`当前限制选择 ${this.limit} 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
          },
           // 删除
          handleRemove(file, fileList) {
            const index=this.fileList.findIndex(n=>n.uid==file.uid)
            if(index!=-1){
              this.fileList.splice(index,1)
               this.isClearTitle=true
            }
          },
          // 删除之前
          beforeRemove(file, fileList) {
            if(this.isClearTitle){
              return this.$confirm(`确定移除 ${ file.name }`);
            }
    
          },
          // 成功&&插入对应的url
          handleSuccess(res,file,fileList){
            if(res.code && res.code==200){
              const resData=res.data
              const index=this.fileList.findIndex(n=>n.uid==file.uid)
              if(index!=-1){
                const fileData=this.fileList[index]
                this.fileList.splice(index,1,Object.assign(fileData,{url:resData.url}))
                // console.log(this.fileList,'---handleSuccess')
                console.log(res,'handleSuccess')
              }
            }else{
              this.handleError({message:'上传失败'},file,fileList)
            }
          },
          // 失败
          handleError(error,file,fileList){
            const index=this.fileList.findIndex(n=>n.uid==file.uid)
            if(index!=-1){
              this.fileList.splice(index,1)
              this.$message.error(`${file.name}上传失败`)
            }
            console.log(error,'handleError')
          },
          copyUp(files){
            if(files && files.length>0){
                if(!this.multiple){
                    const file=files[0]
                    if(this.judegFileSize(file)){
                        this.fileList=[file]
                        this.handleFileUpload(this.postUpObject(file))
                    }
                }else{
                    for(let x=0;x<files.length;x++){
                    const file=files[x]
                    if(this.fileList.length<this.limit || !this.limit){
                        if(this.judegFileSize(file)){
                            this.fileList.push(file)
                            this.handleFileUpload(this.postUpObject(file))
                        }
                    }else{
                        this.handleExceed(files,fileList)
                        break;
                    }
                    }
                }
              }
          },
          handlePaste(value){
            if(value.clipboardData){
              const fileList=[...this.fileList]
              let files = value.clipboardData.files
              if(!files){
                files=Array.from(value.clipboardData.items).map(n=>n.getAsFile()).filter(n=>n)
              }
              this.copyUp(files)
            }
    
          },
        },
      };
    script>
    
    <style  scoped>
    ::v-deep .el-upload-list__item:first-child{
      margin-left: 0 !important;
    }
    style>
    
    
  • 2.使用:

    • 1.引入copy-upload组件,并关联对应的v-model
    • 2.监听组件抛出的方法inpuDrag->拖拽相关方法,inpuPaste->复制相关方法
    • 3.对应的input定义ref,然后监听的方法使用,并传入对应的Dom节点, @inpuDrag="$event(input的Dom节点)",@inpuPaste="$event(input的Dom节点)"
    
    <div style='width:600px'>
          <el-input v-model='txt' ref="copyUploadRef" style='margin-bottom:10px' type="textarea" :rows="5">el-input>
          <copy-upload v-model="fileList" :size="10 * 1024 * 1024" acceptTitle="pdf或word或Excel或常见图片格式" :multiple="true" :headers='{}'  @inpuDrag="$event($refs.copyUploadRef.$el)"  @inpuPaste="$event($refs.copyUploadRef.$el)" sendUrl="/api/posts/" :data="{}">copy-upload>
    div>
    
    

你可能感兴趣的:(javascript,vue.js,elementui)