Vue中封装upload上传组件

109 阅读1分钟
<template>
  <div>
    <el-upload
      :file-list="fileArr ? fileArr : []"
      :action="action"
      :headers="userInfo"
      :disabled="!edit"
      list-type="picture-card"
      :class="!edit ? 'picture-disabled' : ''"
      :on-success="handleSuccess"
      :accept="accept"
    >
      <i class="el-icon-plus"></i>
      <div v-if="file.fileType === fileType" slot="file" slot-scope="{file}">
        <el-image :src="(file.materialUrlToBase || file.base64Url || file.imageToBase || file.materialUrl) | transformImageUrl" fit="cover" style="height: 80px;">
          <div slot="error" class="image-slot">
            <i class="el-icon-document" style="font-size: 63px;transform: translateX(35%);"></i>
          </div>
        </el-image>
        <!-- <img class="el-upload-list__item-thumbnail" :src="file.materialUrl" alt /> -->
        <label class="el-upload-list__item-status-label">
          <i class="el-icon-upload-success el-icon-check"></i>
        </label>
        <el-tooltip class="item" effect="dark" :content="file.materialFileName" placement="bottom">
          <span class="el-upload-list__item-actions">
            <span v-if="file.materialType === 'IMAGE'" class="el-upload-list__item-preview" @click="onPreview(file)">
              <i class="el-icon-zoom-in"></i>
            </span>
            <span class="el-upload-list__item-delete" @click="handleDownload(file)">
              <i class="el-icon-download"></i>
            </span>
            <!-- v-if="file.materialType !== 'IMAGE'" -->
            <span v-if="file.materialUrl && edit" class="el-upload-list__item-delete" @click="handleRemove(file)">
              <i class="el-icon-delete"></i>
            </span>
          </span>
        </el-tooltip>
        <p v-if="file.materialUrl" class="file-name">{{ file.materialFileName }}</p>
      </div>
    </el-upload>
    <!-- element预览组件 -->
    <el-image-viewer v-if="showViewer" :on-close="closeViewer" :url-list="srcList | transformImageUrl" />
    <!-- <el-dialog title="预览" :visible.sync="dialogVisible">
      <img width="100%" :src="dialogImageUrl" alt />
    </el-dialog>-->
  </div>
</template>

<script>
import db from '@/utils/localstorage'
import cookie from '@/utils/cookie'
import ElImageViewer from 'element-ui/packages/image/src/image-viewer'
import applyApi from '@/api/reportInstall/userApply.js'
import reportInstallCommon from '@/api/reportInstall/reportInstallCommon.js'
import AttachmentApi from '@/api/Attachment.js'
export default {
  name: 'uploadFile',
  components: { ElImageViewer },
  props: {
    fileApi: {
      type: String,
      default: '#',
    },
    fileArr: {
      type: Array,
      default: () => [],
    },
    fileType: {
      type: Number,
      default: -1,
    },
    edit: {
      type: Boolean,
      default: false,
    },
    taskNo: {
      type: String,
      default: '#',
    },
    taskNode: {
      type: Number,
      default: -1,
    },
    indexNumber: {
      //阶段渲染的Key
      type: Number,
      default: -1,
    },
    accept: {
      type: String,
    },
  },
  data() {
    return {
      action: '',
      dialogVisible: false,
      dialogImageUrl: '',
      disabled: false,
      srcList: [],
      showViewer: false,
    }
  },
  computed: {
    userInfo() {
      return {
        token: this.$store.state.account.token
          ? `Bearer ${this.$store.state.account.token}`
          : `Bearer ${cookie.get('gmis-ui_TOKEN')}`,
        tenant: this.$store.state.account.tenant || db.get('TENANT', ''),
        pt: 'zugmis',
      }
    },
  },
  mounted() {
    this.action = this.fileApi
  },
  methods: {
    closeViewer() {
      this.showViewer = false
    },
    onPreview(file) {
      this.srcList = [
        file.materialUrlToBase || file.base64Url || file.imageToBase || file.materialUrl,
      ]
      this.$nextTick(() => {
        this.showViewer = true
      })
    },
    // 图片放大预览
    // handlePictureCardPreview(file) {
    //   this.dialogImageUrl = file.materialUrl;
    //   this.dialogVisible = true;
    // },
    // 下载文件
    handleDownload(file) {
      reportInstallCommon.downLoadFromBase64({
        url: file.materialUrl,
        fileName: file.materialFileName,
      })
    },
    // 删除文件
    handleRemove(file) {
      const { id } = file
      this.$confirm('选中数据将被移除,是否继续?', this.$t('common.tips'), {
        confirmButtonText: this.$t('common.confirm'),
        cancelButtonText: this.$t('common.cancel'),
        type: 'warning',
      }).then(async () => {
        const {
          data: { isSuccess },
        } = await applyApi.delFiles(id)
        if (isSuccess) {
          this.$message({
            message: this.$t('tips.deleteSuccess'),
            type: 'success',
          })
          this.$emit('remove', file)
        }
      })
    },
    // 上传成功的回调
    handleSuccess(response, file, fileList) {
      const {
        data: {
          id,
          bizId,
          ext,
          submittedFileName,
          url,
          relativePath,
          dataType: { code },
        },
        isSuccess,
      } = response
      const reqData = {
        fileType: this.fileType,
        materialFileExtension: ext,
        materialFileName: submittedFileName,
        materialId: bizId,
        materialImageUrl: url,
        materialType: code,
        materialUrl: url,
        taskNo: this.taskNo,
        taskNode: this.taskNode,
        id,
        status: 1,
        base64Url: relativePath,
      }
      isSuccess ? this.$emit('success', reqData, response, file) : undefined
    },
  },
}
</script>

<style lang='scss' scoped>
::v-deep {
  /*解决element上传组件回显动画问题*/
  .el-upload-list__item {
    transition: none !important;
  }

  .disabled {
    cursor: not-allowed !important; //是禁用的样式 一个圆圈中间一个斜杠
  }

  .el-image {
    display: flex !important;
  }

  .el-upload-list__item-actions {
    height: 110px;
    width: 110px;
  }

  .el-upload-list__item {
    height: 110px;
    width: 110px;
  }

  .file-name {
    text-align: center;
    margin: 0 auto;
    max-width: 80px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .picture-disabled {
    .el-upload--picture-card {
      display: none;
    }
  }

  .el-upload--picture-card {
    width: 110px;
    height: 110px;
    position: relative;

    .el-icon-plus {
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
    }
  }
}
</style>