vue移动端实现pdf、excel、图片在线预览

vue移动端实现pdf、excel、图片在线预览

一、首先预览pdf安装vue-pdf,预览excel安装xlsx,预览图片是用的vant

npm install --save vue-pdf 
npm install xlsx --save
npm install vant --save

二、父页面代码

<template>
   <button @click="seeFile">
   </button>
</template>
//引入子页面,也就是预览的界面
import Views from './previewFile'
export default {
  name: 'FileList',
  components: { Views },
  data() {
    return {
      url:'',//要预览的文件地址
      src: '', // 传参
      type: '', // 附件类型
    }
  },
  methods: {
      //item参数为文件地址
      seeFile(this.url) {
      //文件预览 
      if (item.fileName.toLowerCase().includes('jpg') || item.fileName.toLowerCase().includes('png')|| item.fileName.toLowerCase().includes('jpeg')) {
        this.src = fileAbsPath
        this.type = 'img'
      } else if (item.fileName.toLowerCase().includes('pdf')) {
        this.src = fileAbsPath
        this.type = 'pdf'
        this.$refs.vViews.pageNum = 1
      } else if (item.fileName.toLowerCase().includes('xls') || item.fileName.toLowerCase().includes('xlsx')) {
        this.src = fileAbsPath
        this.type = 'excel'
      }
      this.$nextTick(() => {
        this.$refs.Views.isShow = true
        this.$refs.Views.showFile(this.src)
      })
    },
  }
  }

三,子页面previewFile(预览页面)代码

<template>
  <div class="viewBox" v-if="isShow">
    <!-- pdf预览 -->
    <div class="wrap-pdf" v-if="type === 'pdf'">
      <div class="pdf">
	  <div class="pdf-tab">
	    <div
	      class="btn-def"
	      @click.stop="prePage"><span>上一页</span>
	    </div>
	    <div
	      class="btn-def"
	      @click.stop="nextPage"><span>下一页</span>
	    </div>
	  </div>
	  <div style="text-align: center;">{{pageNum}}/{{pageTotalNum}}</div>
	  <div class="any-scroll-view">
	    <div ref="body">
	      <pdf
	        id="pdfPreview"
	        ref="pdf"
	        :src="pdfSrc"
	        :page="pageNum"
	        :rotate="pageRotate"
	        @password="password"
	        @progress="loadedRatio = $event"
	        @page-loaded="pageLoaded($event)"
	        @num-pages="pageTotalNum=$event"
	        @error="pdfError($event)"
	        @link-clicked="page = $event">
	      </pdf>
	    </div>
	  </div>
	</div>
      <!-- <pdf v-for="item in numPages" :key="item" :src="pdfSrc" :page="item"/> -->
    </div>
    <!-- 表格组件 -->
    <div class="table-box" v-if="type === 'excel'">
      <van-tabs
          class="table-tab"
          v-if="sheetNames.length"
          title-active-color="#07AC7F"
          color="#07AC7F"
          @click="clickTab">
          <van-tab
              v-for="(item, index) in sheetNames"
              :key="index"
              :name="item"
              :title="item"></van-tab>
      </van-tabs>
      <div class="tableBox" ref="excPreview"></div>
    </div>
		<!-- 关闭按钮 -->
      <van-icon class="closeBtn" name="cross" @click="isShow = false" />
	</div>
</template>

<script>
import { ImagePreview } from 'vant'
import pdf from 'vue-pdf' 
import XLSX from 'xlsx'
export default {
  name: 'PreviewFile',
  components: {
    pdf
  },
  props: {
    datas: {},
    type: {}
  },
  data() {
    return {
      isShow: false,
      numPages: 1,
      pdfSrc: '',
      sheetNames: [],
      pageNum: 1,
      wsObj: {},
        pageTotalNum:1,
        pageRotate:0,
        // 加载进度
        loadedRatio:0,
        curPageNum:0,
    }
  },
  
  methods: {
    showFile(newVal) {
      console.log('----', newVal)
      if (this.type === 'img') {
        const that = this
        ImagePreview({
          images: [newVal],
          onClose() {
            that.isShow = false
          }
        })
      } else if (this.type === 'pdf') {
        this.pdfSrc = pdf.createLoadingTask(newVal)
      } else if (this.type === 'excel') {
        var xhr = new XMLHttpRequest()
        xhr.open('get', newVal, true)
        xhr.responseType = 'arraybuffer'
        let _this = this
        xhr.onload = function (e) {
          let that=this;
          var binary = "";
          if (xhr.status === 200) {
            var bytes  = new Uint8Array(xhr.response)
            var length = bytes.byteLength;
            for (var i = 0; i < length; i++) {
              binary += String.fromCharCode(bytes[i]);
            }
            var wb = XLSX.read(binary, { type: "binary" });
            var wsname = wb.SheetNames[0];
            var ws = wb.Sheets[wsname];
             _this.sheetNames = [...wb.SheetNames] // 数组
        _this.wsObj = { ...wb.Sheets }
        _this.changeExcel(_this.sheetNames[0])
          }
        }
        xhr.send()
      }
    },
    clickTab(name) {
      this.changeExcel(name)
    },
    prePage(){
        var p = this.pageNum
        p = p>1?p-1:this.pageTotalNum
        this.pageNum = p
      },
      nextPage(){
        var p = this.pageNum
        p = p<this.pageTotalNum?p+1:1
        this.pageNum = p
      },
      password(updatePassword, reason) {
        updatePassword(prompt('password is "123456"'))
      },
      pageLoaded(e){
        this.curPageNum = e
      },
      pdfError(error){
        console.error(error)
      },
    changeExcel(item) {
      // 获取当前选中表格对象
      const ws = this.wsObj[item]
      console.log(ws);
      const keyArr = Object.keys(ws) || []
      const HTML = keyArr.length > 1 ? XLSX.utils.sheet_to_html(ws)
        : '' +
                    'SheetJS Table Export
暂无数据
'
+ '' this.$nextTick(() => { this.$refs.excPreview.innerHTML = HTML // 获取表格dom元素 const tables = this.$refs.excPreview.children[2] // 添加完毕后 通过空格将数组组装为字符串 tables.className = 'myTable' }) } } } </script> <style lang="scss" scoped> .excel-container { width: 100%; } table { display: table; border-collapse: collapse; box-sizing: border-box; border: 1px solid #929292; width: auto;height: auto;color: #333333;// 合并边框 th,tr{ white-space: nowrap;overflow: hidden;text-overflow: ellipsis;background: #ffffff;padding: 10px;border:1px solid #929292; td{ font-weight: normal; text-align: center; border:1px solid #929292; } } } .tableBox {width: 100vw;height: calc(100vh - 44px);overflow: auto; }// 表格边框 .pdf-tab { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; padding: 0 .4rem; -ms-flex-pack: justify; justify-content: space-between; } .pdf-tab .btn-def { border-radius: .2rem; font-size: 0.5rem; // height: 40px; margin-top: 40px; // width: 6.4rem; text-align: center; // line-height: 1.93333rem; background: #409eff; color: #fff; // margin-bottom: 1.26667rem; } .pdf-total { text-align: center; font-size: 1.45333rem; } .pdf-process, .pdf-total { text-align: center; font-size: 1.45333rem; } .pdf-num { margin-bottom: 1.2rem; } .pdf-box, .word-box, .table-box, .txt-box { width: 100vw; height: 100vh; } .viewBox { width: 100%; height: 100%; overflow: hidden; background: #ffffff; position: fixed; top: 0; left: 0; z-index: 2000; .closeBtn { position: absolute; top: 10px; right: 10px; z-index: 10; font-size: 24px; } } </style>

缺点:excel预览显示不了边框,word预览还没有找到好的解决方案!!!有找到word移动端预览和解决了excel预览边框显示的小伙伴可以私聊我。
效果图如下:
vue移动端实现pdf、excel、图片在线预览_第1张图片
vue移动端实现pdf、excel、图片在线预览_第2张图片

你可能感兴趣的:(excel,vue.js,pdf)