vue2项目封装一个表格里的上传组件

122 阅读1分钟

子组件:TableUpload.vue

<template>
  <div class="uploadBox">
    <!-- 图片 -->
    <div class="imagesBox">
      <div v-for="(item, index) in fileList" :key="index" style="position: relative; display: inline-block">
        <img
          v-if="item.type === 'png' || item.type === 'jpeg' || item.type === 'jpg'"
          class="images"
          :src="item.openUrl"
          alt=""
          @click="previewFile(item.openUrl)"
        />
        <img v-else class="images" src="../../assets/file.png" alt="" @click="previewFile(item.openUrl)" />
        <a-icon class="icon-del" :size="16" theme="filled" type="close-circle" @click="deleteImg(index)" />
      </div>
    </div>
    <!--  -->
    <a-upload
      action="#"
      :accept="accept"
      :show-upload-list="false"
      :multiple="multipleOption"
      :beforeUpload="beforeUpload"
      :file-list="list"
      :customRequest="customRequest"
    >
      <div v-if="!limit || fileList.length < limit" class="upload-btn">
        <a-icon type="plus" style="font-size: 32px; color: #999" />
      </div>
    </a-upload>
  </div>
</template>

<script>
import { uploadFileNew, getBatchFilePathsNew } from '@/api/financialBillSystem/uploadApi'
export default {
  name: 'TableUpload',
  props: [
    'value',
    'onChange',
    'limit',
    'selected',
    'size',
    'myDisabled',
    'isHasOther',
    'listType',
    'multiple',
    'isHasPdf',
    'isNeedName',
    'isHasOfd',
    'uploadFile',
    'accept'
  ],
  data() {
    return {
      list: [],
      fileList: [],
      mySize: 10,
      multipleOption: this.multiple != false, // 是否可以一次选多个
      keys: '',
      addList: []
    }
  },
  watch: {
    selected: {
      async handler(val, oldVal) {
        console.log('selected', val)
        if (!val) {
          this.fileList = []
          return
        }
        let keysList = val.replace(/\,/g, '|')
        let files = keysList.split('|')
        console.log(files, '===========')
        for (var i = 0; i < files.length; i++) {
          var src = files[i]
          if (!src) {
            return
          }
          // 判断触发这个监听事件的是进入组件还是离开组件
          //如果之前有的则不请求
          var existImg = false
          for (var j = 0; j < this.fileList.length; j++) {
            var oldFile = this.fileList[j]
            if (oldFile.resourceId == src) {
              existImg = true
            }
          }
          // 如果是进入时触发,需要请求图片
          if (!existImg) {
            console.log('src====', src)
            await this.getImgUrl(src)
          }
        }
        this.fileList = this.addList
      },
      immediate: true,
      deep: true
    }
  },
  mounted() {
    if (this.size) {
      this.mySize = this.size
    }
  },
  methods: {
    //删除
    deleteImg(index) {
      this.fileList.splice(index, 1)
      let res = ''
      for (let i = 0; i < this.fileList.length; i++) {
        if (i == 0) {
          res = this.fileList[i].resourceId
        } else {
          res = res + '|' + this.fileList[i].resourceId
        }
      }
      this.onChange(res)
    },
    beforeUpload(file, fileList) {
      let files = this.selected ? this.selected.split('|') : ''
      console.log('beforeUpload', file, files.length)

      if (this.limit < this.fileList.length) {
        this.$message.warning(`当前限制选择 ${this.limit}个文件,共选择了 ${files.length} 个文件`)
        return false
      }
      var testmsg = file.name.substring(file.name.lastIndexOf('.') + 1)
      testmsg = testmsg.toLowerCase()
      const extension = testmsg === 'jpg'
      const extension2 = testmsg === 'png'
      const extension3 = testmsg === 'pdf'
      const extension4 = testmsg === 'jpeg'
      const extension5 = testmsg === 'docx'
      const extension6 = testmsg === 'ofd'
      const isLt2M = file.size / 1024 / 1024 < this.size || this.mySize
      if (this.isHasOther) {
        if (!extension && !extension2 && !extension4 && !extension3 && !extension5) {
          this.$message.warning('上传文件只能是 jpg、png、jpeg、pdf、docx格式!')
          return false
        }
      } else if (this.isHasPdf) {
        if (!extension && !extension2 && !extension4 && !extension3) {
          this.$message.warning('上传文件只能是 jpg、png、jpeg、pdf格式!')
          return false
        }
      } else if (this.isHasOfd) {
        if (!extension && !extension2 && !extension4 && !extension3 && !extension6) {
          this.$message.warning('上传文件只能是 jpg、png、jpeg、pdf、ofd格式!')

          return false
        }
      } else {
        if (!extension && !extension2 && !extension4) {
          this.$message.warning('上传文件只能是 jpg、png、jpeg格式!')
          return false
        }
        if (!isLt2M) {
          this.$message.warning(`上传文件大小不能超过 ${this.mySize}MB!`)
          return isLt2M
        }
      }
    },
    async customRequest(fileItem, fileList) {
      console.log('自定义上传', fileItem, fileList)
      const formData = new FormData()
      formData.append('file', fileItem.file)
      try {
        const data = await uploadFileNew(formData)
        console.log('请求结果:', data)
        // await this.getImgUrl(data.resourceId)
        let res = ''
        for (let i = 0; i < this.fileList.length; i++) {
          if (i == 0) {
            res = this.fileList[i].resourceId
          } else {
            res = res + '|' + this.fileList[i].resourceId
          }
        }
        if (this.fileList.length > 1) {
          res = res + '|' + data.resourceId
        } else {
          res = data.resourceId
        }
        // let keyList = []
        // let keys
        // this.fileList.forEach((item) => {
        //   keyList.push(item.resourceId)
        // })
        // this.keys = keyList.join('|')
        // console.log('上传结果:', data, this.fileList, this.keys)

        this.onChange(res)
        console.log(res)
      } catch (err) {
        console.log(err)
        // createMessage.error(err);
        // uploadLoading.value = false;
      } finally {
      }
    },
    async getImgUrl(resourceId) {
      const path = await getBatchFilePathsNew({
        ids: [resourceId]
      })
      let openUrl = this.isInternet() ? path.data[resourceId].internetUrl : path.data[resourceId].innerUrl

      const fileName = path.data[resourceId].originalFilename
      console.log('fileName', fileName)
      let lastIndex = fileName.lastIndexOf('.')
      let str = fileName.slice(lastIndex + 1)
      this.addList.push({
        resourceId: resourceId,
        fileName: fileName,
        openUrl: openUrl,
        type: str
      })
      console.log('获取url', this.addList)
    },
    previewFile(openUrl) {
      window.open(openUrl, '_blank')
    },
    isInternet() {
      return location.protocol === 'https:'
    }
  }
}
</script>

<style lang="less" scoped>
.ant-upload-select-picture-card i {
  font-size: 32px;
  color: #999;
}

.ant-upload-select-picture-card .ant-upload-text {
  margin-top: 8px;
  color: #666;
}
.upload-btn {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  width: 55px;
  height: 55px;
  background-color: #fafafa;
  border: 1px dashed #d9d9d9;
  border-radius: 4px;
  cursor: pointer;
  transition: border-color 0.3s ease;
}

.uploadBox {
  margin-left: 10px;
  display: flex;
  justify-content: start;
  .imagesBox {
    // width: 575px;
    .images {
      display: inline-block;
      margin-right: 15px;
      margin-bottom: 15px;
      width: 55px;
      height: 55px;
      padding: 3px;
      border: 1px solid #ccc;
      border-radius: 2px;
    }

    .icon-del {
      position: absolute;
      right: -10px;
      left: 40%;
      top: -4px;
    }
  }
}
</style>


父组件:

  <a-table
        :bordered="true"
        class="title-table"
        :pagination="false"
        :row-key="(record, index) => index"
        :columns="titleColumns"
        :dataSource="list"
      >
        <template slot="opration" slot-scope="text, record">
          <div class="editable-row-operations">
            <!-- <span>
              <a class="action-btn" @click="goDetail(record)">上传</a>
            </span> -->
            <TableUpload
              :limit="5"
              :isHasOther="true"
              :on-change="
                (data) => {
                  record.file = data
                }
              "
              :selected="record.file"
              :size="10"
              :accept="'.png, .jpg, .pdf,.doc,.docx,.dot,jpeg'"
            />
          </div>
        </templa