Vue 封装el-upload通用组件, 实现pdf、img混排,支持预览

  1. 使用vue-pdf加载pdf文件
    npm install --save vue-pdf
  2. el-upload设置上传文件格式,自定义排版,通过过slot实现
     

      <el-upload
            ref="elUpload"
            :action="baseUrl"
            list-type="picture-card"
            :limit="limit"
            :class="{ hide: disabled }"
            :disabled="disabled"
            :before-upload="beforeAvatarUpload"
            accept=".jpg, .png, .gif, .jpeg, .pdf"
            :file-list="fileList"
          >
            <i class="el-icon-plus"></i>
            <div
              slot="file"
              slot-scope="{ file }"
              v-loading="file.status == 'uploading'"
              style="height: 100%"
            >
              <pdf
                v-if="file.name.endsWith('.pdf')"
                :src="file.url"
                :page="1"
              ></pdf>
    
              <img
                v-else
                class="el-upload-list__item-thumbnail"
                style="object-fit: cover"
                :src="file.url"
                alt=""
              />
    
              <spa class="el-upload-list__item-actions">
                <span
                  class="el-upload-list__item-preview"
                  @click="handlePictureCardPreview(file)"
                >
                  <i class="el-icon-zoom-in"></i>
                </span>
    
                <span
                  v-if="!disabled"
                  class="el-upload-list__item-delete"
                  @click="handleRemove(file)"
                >
                  <i class="el-icon-delete"></i>
                </span>
              </spa>
            </div>
          </el-upload>
    

  3. pdf预览,通过el-dialog 实现
     

       <el-dialog
          title="查看PDF"
          :visible.sync="dialogVisible"
          width="80%"
          :modal="false"
        >
          <pdf
            ref="pdf"
            v-for="i in pdfPageNumber"
            :key="i"
            :src="pdfSrc"
            :page="i"
          ></pdf>
        </el-dialog>

  4. 图片预览,为了和项目图片预览保持统一,这里使用el-image自带的图片预览,不过需要自己手动调用
     

       //设置一个1像素的,为了使用预览功能
        <el-image
            ref="elImage"
            :src="previewImageUrl"
            style="width: 1px; height: 1px"
            :preview-src-list="[previewImageUrl]"
          ></el-image>
    
    
       //获取elImage元素,手动调用预览
       let image = this.$refs.elImage;
       image.showViewer = true;

  5. 效果图

  6. 完整代码

     

<template>
  <div>
    <div style="display: flex; flex-direction: column">
      <el-upload
        ref="elUpload"
        :action="baseUrl"
        list-type="picture-card"
        :limit="limit"
        :class="{ hide: disabled }"
        :disabled="disabled"
        :before-upload="beforeAvatarUpload"
        accept=".jpg, .png, .gif, .jpeg, .pdf"
        :file-list="fileList"
      >
        <i class="el-icon-plus"></i>
        <div
          slot="file"
          slot-scope="{ file }"
          v-loading="file.status == 'uploading'"
          style="height: 100%"
        >
          <pdf
            v-if="file.name.endsWith('.pdf')"
            :src="file.url"
            :page="1"
          ></pdf>

          <img
            v-else
            class="el-upload-list__item-thumbnail"
            style="object-fit: cover"
            :src="file.url"
            alt=""
          />

          <spa class="el-upload-list__item-actions">
            <span
              class="el-upload-list__item-preview"
              @click="handlePictureCardPreview(file)"
            >
              <i class="el-icon-zoom-in"></i>
            </span>

            <span
              v-if="!disabled"
              class="el-upload-list__item-delete"
              @click="handleRemove(file)"
            >
              <i class="el-icon-delete"></i>
            </span>
          </spa>
        </div>
      </el-upload>

      <p v-if="!disabled">
        支持jpg、gif、png、pdf格式,最多上传10个,单个文件不超过20M。
      </p>
      <el-image
        ref="elImage"
        :src="previewImageUrl"
        style="width: 1px; height: 1px"
        :preview-src-list="[previewImageUrl]"
      ></el-image>
    </div>
    <el-image
      ref="elImage"
      :src="previewImageUrl"
      style="width: 1px; height: 1px"
      :preview-src-list="[previewImageUrl]"
    ></el-image>

    <el-dialog
      title="查看PDF"
      :visible.sync="dialogVisible"
      width="80%"
      :modal="false"
    >
      <pdf
        ref="pdf"
        v-for="i in pdfPageNumber"
        :key="i"
        :src="pdfSrc"
        :page="i"
      ></pdf>
    </el-dialog>
  </div>
</template>

<script>
import pdf from "vue-pdf";
export default {
  name: "",
  components: {
    pdf,
  },
  props: {
    ///当前列表选中条目
    selectRow: {
      type: Object,
      default: {},
    },
    //需要回显的文件
    fileList: {
      type: Array,
      default: [],
    },
    //最大上传数
    limit: {
      type: Number,
      default: 10,
    },
    ///是否禁用上传,只支持放大预览
    disabled: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      pdfPageNumber: 0,///pdf最页数
      pdfSrc: "",///pdf地址
      loadingBtn: false,
      dialogVisible: false,
      previewImageUrl: "",///预览图片都中
      baseUrl: "",
    };
  },


  mounted() {
    this.getBaseUrl();
  },

  methods: {
    ///获取上传文件地址
    getBaseUrl() {
      if (process.env.NODE_ENV === "development") {
        this.baseUrl =
          "java/" +
          this.$store.state.user.urlConfig["java"] +
          "api/v1/app/aliyun/uploadFile";
      } else {
        this.baseUrl =
          this.$store.state.user.urlConfig["java"] +
          "api/v1/app/aliyun/uploadFile";
      }
    },
    ///判断文件大小
    beforeAvatarUpload(file) {
      const isLt20M = file.size / 1024 / 1024 < 20;
      if (!isLt20M) {
        this.$message.error("上传头像图片大小不能超过 20MB!");
      }
      return isLt20M;
    },
    ///点击删除
    handleRemove(file) {
      let uploadFiles = this.$refs.elUpload.uploadFiles;
      let index = uploadFiles.findIndex((item) => {
        return item == file;
      });
      uploadFiles.splice(index, 1);
    },
    ///预览
    handlePictureCardPreview(file) {
      if (file.name.endsWith(".pdf")) {
        if (file.response) {
          this.pdfSrc = file.response.data;
        } else {
          this.pdfSrc = file.name;
        }
        this.getPDFnums(this.pdfSrc);
      } else {
        let image = this.$refs.elImage;
        if (file.response) {
          this.previewImageUrl = file.response.data;
        } else {
          this.previewImageUrl = file.name;
        }
        image.showViewer = true;
      }
    },
    //计算pdf页码总数
    getPDFnums(url) {
      let loadURL = pdf.createLoadingTask({
        url: url, //你的pdf地址
      });
      loadURL.promise.then((pdf) => {
        this.pdfPageNumber = pdf.numPages;
        this.dialogVisible = true;
      });
    },

    getFileUrls() {
      let fileNames = "";
      const uploadFiles = this.$refs.elUpload.uploadFiles;
      debugger
      let uploading = uploadFiles.some((item) => {
        return item.status == "uploading";
      });
      if (uploading) {
        this.$message.warning("文件上传中,请稍后再试!");
        return false;
      }
      uploadFiles.forEach((item) => {
        const response = item.response;
        if (response) {
          if (response.code == 0) {
            fileNames += response.data + ",";
          }
        } else {
          fileNames += item.name + ",";
        }
      });
      if (fileNames.endsWith(",")) {
        fileNames = fileNames.replace(/,$/gi, "");
      }
      return fileNames;
    },
  },
};
</script>
<style lang='less' scoped>

/deep/ .hide .el-upload--picture-card {///deep 穿透隐藏上传图片入口
  display: none;
}
</style>

PS:pdf有些发票信息显示不全,一些字体显示不出来,解决办法如下

    //url 是当前pdf的链接地址
    getPdfUrl(url) {
      let src = pdf.createLoadingTask({
        url: url,
        //引入pdf.js字体,templ
        cMapUrl: "https://cdn.jsdelivr.net/npm/pdfjs-dist@2.5.207/cmaps/",
        cMapPacked: true,
      });
      return src;
    },

  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值