vue項目使用elementUI的el-upload組件實現圖片上傳和文件上傳的公共組件封裝


 

圖片上傳:

<template>
  <div class="upload-pic">
    <el-upload
      class="upload-demo"
      :action="uploadFdfsFileUrl"
      :headers="requestHeader"
      list-type="picture-card"
      name="file"
      :before-upload="beforeAvatarUpload"
      :on-preview="handlePictureCardPreview"
      :on-remove="handleRemove"
      :before-remove="beforeRemove"
      :on-success="handleSuccess"
      :on-error="handleError"
      :multiple="multiple"
      :limit="limitNum"
      :on-exceed="handleExceed"
      :file-list.sync="picWebUrlList"
    >
      <i class="el-icon-plus"></i>
    </el-upload>
    <el-dialog :visible.sync="dialogVisible">
      <img width="100%" :src="dialogImageUrl" alt="">
    </el-dialog>
  </div>
</template>
  import { mapGetters, mapActions } from 'vuex'
  import { getToken } from '@/utils/auth'
  export default {
    name: 'UploadPic',
    props: {
      isEdit: {
        type: Boolean,
        default: false
      },
      // 是否多選
      multiple: {
        type: Boolean,
        default: true
      },
      // 文件列表
      fileList: {
        type: Array,
        default: () => []
      },
      // 限制上傳個數
      limitNum: {
        type: Number,
        default: null
      }
    },
    data() {
      return {
        // 附件上傳請求頭
        requestHeader: '',
        // 圖片上傳路徑
        picUploadList: [],
        // 圖片回顯路徑
        picWebUrlList: [],
        // 預覽路徑
        dialogImageUrl: '',
        // 預覽彈框
        dialogVisible: false,
        // 刪除圖片下標
        delIndex: null
      }
    },
    computed: {
      ...mapGetters([
        'uploadFdfsFileUrl'
      ])
    },
    watch: {},
    /**
     * 生命周期函數--el 被新創建的 vm.$el 替換,並掛載到實例上去之后調用該鈎子
     */
    mounted: function() {},
    created() {
      // 設置文件按上傳請求頭
      this.requestHeader = { 'Authorization': 'Bearer ' + getToken('token') }
    },
    methods: {
      ...mapActions([
        'download'
      ]),
      refreshPicData(value) {
        this.picUploadList = value
        this.getWebUrlList()
      },
      // 圖片回顯數組
      getWebUrlList() {
        let webUrlList = []
        if (this.picUploadList.length > 0) {
          this.picUploadList.forEach((item, index) => {
            // 獲取圖片 web 地址
            this.$store.dispatch('dictionary/getWebFileUrl', item.url).then(response => {
              const fileObj = {
                index: index,
                name: '',
                url: response.data
              }
              webUrlList.push(fileObj)
            })
          })
          this.picWebUrlList = webUrlList
        }
      },
      // 圖片格式及大小限制
      beforeAvatarUpload(file) {
        const isJPG = file.type === 'image/jpg'
        const isJPEG = file.type === 'image/jpeg'
        const isGIF = file.type === 'image/gif'
        const isPNG = file.type === 'image/png'
        const isBMP = file.type === 'image/bmp'
        const isLt2M = file.size / 1024 / 1024 < 2
        if (!isJPG && !isJPEG && !isGIF && !isPNG && !isBMP) {
          this.$message.error('上傳圖片必須是JPG/JPEG/GIF/PNG/BMP 格式!')
        }
        if (!isLt2M) {
          this.$message.error('上傳圖片大小不能超過 2MB!')
        }
        return (isJPG || isJPEG || isBMP || isGIF || isPNG) && isLt2M
      },
      // 點擊預覽圖標,預覽圖片
      handlePictureCardPreview(file) {
        this.dialogImageUrl = file.url
        this.dialogVisible = true
      },
      // 文件列表移除文件時的鈎子
      handleRemove(file, fileList) {
        if (this.isEdit) {
          this.picUploadList.splice(this.delIndex, 1)
          this.$emit('update:fileList', this.picUploadList)
        } else {
          const fileArr = []
          fileList.forEach(item => {
            if (item.response) {
              const fileObj = {
                name: item.name,
                url: item.response.data
              }
              fileArr.push(fileObj)
            } else {
              fileArr.push(item)
            }
          })
          this.$emit('update:fileList', fileArr)
        }
      },
      // 刪除文件之前的鈎子
      beforeRemove(file, fileList) {
        fileList.forEach((item, index) => {
          if (file.url === item.url) {
            this.delIndex = index
          }
        })
        return this.$confirm('', `確定移除 ${file.name}?`, { customClass: 'del-dialog' })
      },
      // 文件上傳成功時的鈎子
      handleSuccess(response, file, fileList) {
        if (response.code === '1') {
          if (this.isEdit) {
            const fileObj = {
              index: this.picUploadList.length,
              name: file.name,
              url: response.data
            }
            this.picUploadList.push(fileObj)
            this.$emit('update:fileList', this.picUploadList)
          } else {
            const fileArr = []
            fileList.forEach(item => {
              if (item.response) {
                const fileObj = {
                  name: item.name,
                  url: item.response.data
                }
                fileArr.push(fileObj)
              } else {
                fileArr.push(item)
              }
            })
            this.$emit('update:fileList', fileArr)
          }
        } else {
          this.$message({
            message: `${file.name} 上傳失敗,請重新再試`,
            type: 'error',
            duration: 2000
          })
        }
      },
      // 文件上傳失敗時的鈎子
      handleError(err, file, fileList) {
        console.log(err)
        this.$message({
          message: `${file.name} 上傳失敗,請重新再試`,
          type: 'error',
          duration: 2000
        })
      },
      // 文件超出個數限制時的鈎子
      handleExceed(files, fileList) {
        this.$message.warning(`當前限制選擇 ${this.limitNum} 個文件,本次選擇了 ${files.length} 個文件,共選擇了 ${files.length + fileList.length} 個文件`)
      }
    }
  }

父組件引用:<upload-pic ref="refreshData" :file-list.sync="formData.picList" :limit="1" :is-edit="isEdit"></upload-pic>

在編輯圖片時,將編輯圖片的數組傳遞給圖片上傳組件,否則不能回顯父組件拿到圖片數據后,通過調用圖片上傳組件內的 refreshPicData 方法,傳遞圖片數據。

 

 


 


文件上傳:

<template>
  <div class="upload-file">
    <el-upload
      class="upload-demo"
      :action="uploadFdfsFileUrl"
      :headers="requestHeader"
      name="file"
      :on-preview="handlePreview"
      :on-remove="handleRemove"
      :before-remove="beforeRemove"
      :on-success="handleSuccess"
      :on-error="handleError"
      :multiple="multiple"
      :limit="limitNum"
      :on-exceed="handleExceed"
      :file-list.sync="fileList"
    >
      <el-button class="dashed-btn" icon="el-icon-upload" size="small">{{ btnTxt }}</el-button>
      <div slot="tip" class="el-upload__tip">{{ tipTxt }}</div>
    </el-upload>
  </div>
</template>
  import { mapGetters, mapActions } from 'vuex'
  import { getToken } from '@/utils/auth'
  export default {
    name: 'UploadFile',
    props: {
      // 是否多選
      multiple: {
        type: Boolean,
        default: true
      },
      // 文件列表
      fileList: {
        type: Array,
        default: () => []
      },
      // 限制上傳個數
      limitNum: {
        type: Number,
        default: null
      },
      // 按鈕文字
      btnTxt: {
        type: String,
        default: '上傳附件'
      },
      // tip 提示
      tipTxt: {
        type: String,
        default: ''
      }
    },
    data() {
      return {
        // 附件上傳請求頭
        requestHeader: ''
        // 限制文件數量
        // limitNum: ''
        // 文件列表
        // fileList: []
      }
    },
    computed: {
      ...mapGetters([
        'uploadFdfsFileUrl'
      ])
    },
    watch: {},
    /**
     * 生命周期函數--el 被新創建的 vm.$el 替換,並掛載到實例上去之后調用該鈎子
     */
    mounted: function() {},
    created() {
      // 設置文件按上傳請求頭
      this.requestHeader = { 'Authorization': 'Bearer ' + getToken('token') }
    },
    methods: {
      ...mapActions([
        'download'
      ]),
      // 點擊文件列表中已上傳的文件時的鈎子,下載文件
      handlePreview(file) {
        console.log(file)
        // const param = {
        //   fileUrl: file.url
        // }
        // this.$store.dispatch('dictionary/downLoad', param).then(response => {
        //   console.log(response)
        //   let fileName = localStorage.fileName
        //   fileName = decodeURI(fileName.substr(fileName.indexOf('=') + 1))
        //   const paramData = {
        //     data: response,
        //     title: '天津園區電梯監控.xlsx'
        //   }
        //   this.download(paramData)
        // })
      },
      // 文件列表移除文件時的鈎子
      handleRemove(file, fileList) {
        const fileArr = []
        fileList.forEach(item => {
          if (item.response) {
            const fileObj = {
              name: item.name,
              url: item.response.data
            }
            fileArr.push(fileObj)
          } else {
            fileArr.push(item)
          }
        })
        this.$emit('update:fileList', fileArr)
      },
      // 刪除文件之前的鈎子
      beforeRemove(file, fileList) {
        return this.$confirm('', `確定移除 ${file.name}?`, { customClass: 'del-dialog' })
      },
      // 文件上傳成功時的鈎子
      handleSuccess(response, file, fileList) {
        if (response.code === '1') {
          const fileArr = []
          fileList.forEach(item => {
            if (item.response) {
              const fileObj = {
                name: item.name,
                url: item.response.data
              }
              fileArr.push(fileObj)
            } else {
              fileArr.push(item)
            }
          })
          this.$emit('update:fileList', fileArr)
        } else {
          this.$message({
            message: `${file.name} 上傳失敗,請重新再試`,
            type: 'error',
            duration: 2000
          })
        }
      },
      // 文件上傳失敗時的鈎子
      handleError(err, file, fileList) {
        console.log(err)
        this.$message({
          message: `${file.name} 上傳失敗,請重新再試`,
          type: 'error',
          duration: 2000
        })
      },
      // 文件超出個數限制時的鈎子
      handleExceed(files, fileList) {
        this.$message.warning(`當前限制選擇 ${this.limitNum} 個文件,本次選擇了 ${files.length} 個文件,共選擇了 ${files.length + fileList.length} 個文件`)
      }
    }
  }

父組件引用:<upload-file :file-list.sync="formData.fileList" ></upload-file>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM