vue实现pdf在线预览业务

Posted 水香木鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue实现pdf在线预览业务相关的知识,希望对你有一定的参考价值。

一、博主介绍

💒首页:水香木鱼

🛫专栏:后台管理系统

简介: 博主:花名 “水香木鱼”,星座"水瓶座一枚"

🔰 格言: 生活是一面镜子。 你对它笑, 它就对你笑; 你对它哭, 它也对你哭。

🔋 充电:相信付出终将会得到回报!


二、笔芯文章

可直接粘贴走,拿去直接用即可。

注意:此方式 唯一不足,会出现双滚动条的问题。【如何解决双滚动条的问题呢,欢迎大家在页面底部评论区留言】👇

①安装vue-pdf

npm install -D vue-pdf

②局部使用

import pdf from "vue-pdf";

③源码

<template>
  <div id="container" v-if="ispdf">
    <!-- 右侧按钮区域 -->
    <div class="right-btn">
      <el-button @click="downloadPdf">下载</el-button>
      <!-- 输入页码 -->
      <div class="pageNum">
        <input
          v-model.number="currentPage"
          type="number"
          class="inputNumber"
          @input="inputEvent()"
        />
        <!-- 总页数 -->
        /  pageCount 
      </div>
      <el-button @click="changePdfPage('first')">首页</el-button>
      <!-- 在按钮不符合条件时禁用 -->
      <el-button
        @click="changePdfPage('pre')"
        :style="currentPage === 1 ? 'cursor: not-allowed;' : ''"
      >
        上一页
      </el-button>
      <el-button
        @click="changePdfPage('next')"
        :style="currentPage === pageCount ? 'cursor: not-allowed;' : ''"
      >
        下一页
      </el-button>
      <el-button @click="changePdfPage('last')">尾页</el-button>
    </div>

    <div class="pdfArea">
      <!-- :src:需要展示的pdf地址 
           :page:当前展示的pdf页码
           :num-pages:文件总页码
           :progress:加载时展示el-progress 
           :page-loaded:一开始加载的页面
           :loaded:加载事件
           :link-clicked:切换页面 -->
      <pdf
        :src="src"
        ref="pdf"
        v-show="loadedRatio === 1"
        :page="currentPage"
        @num-pages="pageCount = $event"
        @progress="loadedRatio = $event"
        @page-loaded="currentPage = $event"
        @loaded="loadPdfHandler"
        @link-clicked="currentPage = $event"
        style="display: inline-block; width: 100%"
        id="pdfID"
      ></pdf>
    </div>
    <!-- 加载未完成时,展示进度条组件并计算进度 -->
    <div class="progress" v-show="loadedRatio !== 1">
      <el-progress
        type="circle"
        :width="70"
        color="#53a7ff"
        :percentage="Math.floor(loadedRatio * 100)"
      ></el-progress>
      <br />
      <!-- 加载提示语 -->
      <span> remindShow </span>
    </div>
  </div>
</template>

<script>
import pdf from "vue-pdf";
export default 
  components: 
    pdf,
  ,
  computed: ,
  created() 
    // this.src = pdf.createLoadingTask(this.src);
  ,
  destroyed() 
    // 在页面销毁时记得清空 setInterval
    clearInterval(this.intervalID);
  ,
  mounted() 
    // 更改 loading 文字
    this.intervalID = setInterval(() => 
      this.remindShow === this.remindText.refresh
        ? (this.remindShow = this.remindText.loading)
        : (this.remindShow = this.remindText.refresh);
    , 4000);
  ,
  data() 
    return 
      // 需要展示的pdf的地址
      src: "./static/react.pdf",
      // 后端返回的真的需要预览的地址
      pdfUrl: "./static/react.pdf",
      Item: "",
      ispdf: true,
      // ----- loading -----
      remindText: 
        loading: "加载文件中,文件较大请耐心等待...",
        refresh: "若卡住不动,可刷新页面重新加载...",
      ,
      remindShow: "加载文件中,文件较大请耐心等待...",
      intervalID: "",
      // 当前页数
      currentPage: 0,
      // 总页数
      pageCount: 0,
      // 加载进度
      loadedRatio: 0,
    ;
  ,
  computed: ,
  methods: 
    // 页面回到顶部
    toTop() 
      document.getElementById("container").scrollTop = 0; //id.scrollTop而不是id.style.scrollTop
    ,
    // 输入页码时校验
    inputEvent() 
      if (this.currentPage > this.pageCount) 
        // 1. 大于max(总页数)
        this.currentPage = this.pageCount;
       else if (this.currentPage < 1) 
        // 2. 小于min(最小页数)
        this.currentPage = 1;
      
    ,
    // 切换页数
    changePdfPage(val) 
      // val的值分别为:first、pre、next、last,分别代表首页、上一页、下一页、尾页
      if (val === "pre" && this.currentPage > 1) 
        this.currentPage--;
        // 切换后页面回到顶部
        this.toTop();
       else if (val === "next" && this.currentPage < this.pageCount) 
        this.currentPage++;
        this.toTop();
       else if (val === "first") 
        this.currentPage = 1;
        this.toTop();
       else if (val === "last" && this.currentPage < this.pageCount) 
        this.currentPage = this.pageCount;
        this.toTop();
      
    ,
    // pdf加载时
    loadPdfHandler(e) 
      // 加载的时候先加载第一页
      this.currentPage = 1;
    ,
    // pdf下载
    downloadPdf() 
      var url = this.pdfUrl;
      var tempLink = document.createElement("a");
      tempLink.style.display = "none";
      tempLink.href = url;
      // tempLink.href = "#";
      // 获取文件名
      var numIndex = url.lastIndexOf("/") + 1;
      var pdfName = url.substring(numIndex);
      tempLink.setAttribute("download", `$pdfName.pdf`);
      if (typeof tempLink.download === "undefined") 
        tempLink.setAttribute("target", "_blank");
      
      document.body.appendChild(tempLink);
      tempLink.click();
      document.body.removeChild(tempLink);
    ,
  ,
  // props: ["src"],
;
</script>

<style lang="less" scoped>
@remvw:1920 /100vw;
#container 
  overflow: auto;
  height: 800 / @remvw;
  font-family: PingFang SC;
  width: 100%;
  height: 1080 / @remvw;
  display: flex;
  justify-content: center;
  position: relative;


/* 右侧功能按钮区 */
.right-btn 
  position: fixed;
  right: 2%;
  bottom: 35%;
  width: 120 / @remvw;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  z-index: 99;


.pdfArea 
  width: 85%;


//页码
.pageNum 
  margin: 10 / @remvw 0;
  font-size: 18 / @remvw;

/*在谷歌下移除input[number]的上下箭头*/
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button 
  -webkit-appearance: none !important;
  margin: 0;

/*在firefox下移除input[number]的上下箭头*/
input[type="number"] 
  -moz-appearance: textfield;


.inputNumber 
  border-radius: 8 / @remvw;
  border: 1 / @remvw solid #999999;
  height: 35 / @remvw;
  font-size: 18 / @remvw;
  width: 60 / @remvw;
  text-align: center;

.inputNumber:focus 
  border: 1 / @remvw solid #00aeff;
  background-color: rgba(18, 163, 230, 0.096);
  outline: none;
  transition: 0.2s;


::v-deep .el-button 
  width: 140 / @remvw;
  display: inline-block;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  background: #fff;
  border: 1px solid #dcdfe6;
  color: #606266;
  -webkit-appearance: none;
  text-align: center;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  outline: 0;
  margin: 0;
  -webkit-transition: 0.1s;
  transition: 0.1s;
  font-weight: 500;
  padding: 12px 20px;
  font-size: 14px;
  border-radius: 4px;

//hover效果
::v-deep .el-button:hover 
  width: 140 / @remvw;
  display: inline-block;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  background: #fff;
  border: 1px solid #1c57e0;
  color: #1c57e0;
  -webkit-appearance: none;
  text-align: center;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  outline: 0;
  margin: 0;
  -webkit-transition: 0.1s;
  transition: 0.1s;
  font-weight: 500;
  padding: 12px 20px;
  font-size: 14px;
  border-radius: 4px;


//进度条
.progress 
  position: absolute;
  right: 50%;
  top: 50%;
  text-align: center;

.progress > span 
  color: #199edb;
  font-size: 14 / @remvw;

</style>

三、博主致谢

感谢小伙伴们,耐心的阅读完本篇文章,关注👉 水香木鱼🔔 获取更多精彩文章!

⭐⭐⭐ 做为小可爱的你,别忘记一键三连呦!

以上是关于vue实现pdf在线预览业务的主要内容,如果未能解决你的问题,请参考以下文章

vue 使用 vue-pdf 实现pdf在线预览

vue-pdf.js 在线预览问题

vue前台 pdf.js瀑布流式加载大文件

vue-pdf 预览乱码问题

前端在线预览PDF文件

WEB在线预览PDF