vue+element在线浏览文件轮播组件(支持pdf/doc/

2020-03-11  本文已影响0人  七號7777

看自己用的框架选择,vue+iview查看器可以参考这篇文章https://www.jianshu.com/p/32cd865a8b34

效果图


微信截图_20200310161707.png

首先PDF为了提高兼容性,我们可以加载一个原生的PDF插件(pdf.js)
插件下载地址:http://mozilla.github.io/pdf.js/getting_started/
点击蓝色按钮的下载就行

image.png
在vue项目下的static添加一个pdf文件夹,放入以下得到的两个文件夹,
image.png
在vue项目下的static添加一个jpgView文件夹,放入这两个文件
viewer.js 和 viewer.css(下载路径:https://www.jianshu.com/p/8ffdbe48859e

安装base64转换插件:
npm install js-base64 --save

写个组件页面(el-carousel自己找文档看参数,还有doc文档查看的话只能查看外网的,内网的文件看不了(一般现在分内外网开发,想测试效果的话,可以在正式服务器扔一份文件看效果))

<template>
<div>
  <el-carousel
    :id="viewerId"
    :autoplay='false'
    v-if="fileUrls !== undefined && fileUrls.length>0"
    @change="changeIndex">
    <el-carousel-item v-for="(item) in PTFurls" :key="item.id">
      <div style="text-align: center;height: 100%;">
        <iframe
          scrolling="auto"
          :src="item.url"
          class="scrollStyle table_120_list"
          frameborder="0"
          width="100%"
          height="100%"
          :id="item.id"
          @load="cardFinish($event,item.id,'pdf')"
        >
          该浏览器暂不支持PDF浏览,您可以下载该文件进行查看:
          <a :src="item.url" rel="external nofollow">下载PDF文件</a>
        </iframe>
        <Spin size="large" fix v-if="item.loading"></Spin>
      </div>
    </el-carousel-item>
    <el-carousel-item v-for="(item,index) in DOCurls" :key="index+100">
      <div style="text-align: center;height: 100%;">
        <iframe
          scrolling="auto"
          :src="'http://view.officeapps.live.com/op/view.aspx?src='+item.url"
          class="scrollStyle table_120_list"
          frameborder="0"
          width="100%"
          height="100%"
        >
          该浏览器暂不支持文档浏览,您可以下载该文件进行查看:
          <a :src="item.url" rel="external nofollow">下载文档文件</a>
        </iframe>
      </div>
    </el-carousel-item>
    <el-carousel-item v-for="(item) in Imgurls" :key="item.id">
      <div style="text-align: center;height: 100%;">
        <img
          :src="item.url"
          style="height:85%;cursor: pointer;width: 100%"
          alt="点击查看"
          title="点击查看"
          @click="imgShow(viewerId)"
        />
        <div style="margin-top: 10px;text-align: center;">
          <el-button type="primary" @click="plaintiffDown(item.url)" plain>下载到电脑</el-button>
        </div>
      </div>
    </el-carousel-item>
  </el-carousel>
  <div v-else style="height:500px;text-align: center;margin-top: 50px;width: 100%">暂无数据</div>
</div>
</template>
<script>
import '@static/viewer/viewer.css'
import Viewer from '@static/viewer/viewer'
import { urlRedirect } from '@/libs/address'
export default {
  name: 'ZhViewer',
  props: {
    fileUrls: {
      type: Array,
      default: function () {
        return []
      }
    },
    viewerId: {
      type: String
    }
  },
  data () {
    return {
      setting: {
        dots: 'outside',
        radiusDot: true
      },
      nowIndex: 0, // 当前显示第几张
      allHost: urlRedirect(), // 域名
      PTFurls: [], // PTF文件
      Imgurls: [], // IMG文件
      DOCurls: [] // DOC文件
    }
  },
  methods: {
    changeIndex (index) {
      this.nowIndex = index
    },
    imgShow (name) {
      // 放在模态框的有时候会出现第一次图片放大显示在模态框下面,所以加个层级
      let gallery = new Viewer(document.getElementById(name), {
        show: function () {
          gallery.update()
        },
        hide: function() {
          gallery.destroy() // 图片点击放大后关闭图片时销毁
        },
        zIndex: 9999
      })
      gallery.show()
    },
    init () {
      // console.log(this.fileUrls)
    },
    plaintiffDown (item) {
      // 必须同源才能下载
      // var alink = document.createElement('a')
      // alink.href = item
      // let type = item.split('.')[1]
      // let name = item.split('.')[0]
      // alink.download = name + '.' + type // 图片名
      // alink.click()
      // 以上注释掉的部分,是会在同个页面上替换链接打开图片,我们的需求是开新页面,所以我用了window.open()
      window.open(item)
    },
    cardFinish (e, id, type) {
      // 判断iframe是否加载完毕
      switch (type) {
        case 'pdf':
          this.PTFurls.forEach((item, index) => {
            if (item.id === id) {
              item.loading = false
              this.$set(item, 'loading', false)
            }
          })
          break
      }
      setTimeout(() => {
        this.nowIndex = 0
      }, 2000)
    },
    spinShow () {
      return false
    }
  },
  mounted () {
    // console.log(this.fileUrls)
  },
  watch: {
    fileUrls: {
      immediate: true,
      handler (val) {
        // 当前域名
        this.allHost = `${urlRedirect()}/`  --------------------------自己的域名自己配
        this.PTFurls = []
        this.DOCurls = []
        this.Imgurls = []
        // console.log('fileUrls', this.fileUrls)
        // 筛选文件分别显示
        this.fileUrls.forEach((item, index) => {
          let fileType = item.path.split('.')[item.path.split('.').length - 1] // 获取文件类型
          let url = item.path.indexOf('http://') >= 0 ? item.path : this.allHost + item.path // 过滤文件路径
          let time = Date.parse(new Date())
          switch (fileType) {
            case 'pdf':
              this.PTFurls.push({
                url: url + '?' + time,
                loading: false,
                id: item.id
              })
              break
            case 'xlsx':
            case 'docx':
              this.DOCurls.push({
                url: url + '?' + time,
                loading: true,
                id: Math.random()
                  .toString(36)
                  .substr(2)
              })
              break
            case 'jpg':
            case 'png':
            case 'jpeg':
              this.Imgurls.push({
                url: url + '?' + time,
                loading: true,
                id: item.id
              })
              break
          }
        })
        // this.nowIndex = this.fileUrls.length - 1
        this.nowIndex = 0
      }
    },
    // 当前轮播的下标 ------------外部删除或者添加操作的时候会用到
    nowIndex: {
      immediate: true,
      handler (newVal, oldVal) {
        this.$emit('emitNowIndex', newVal)
      }
    }
  }
}
</script>

引入组件,注册组件,引用组件

import moreFileViewer from '@/components/fileViewer/moreFileViewer.vue'// 路径自己放,这里只是例子
components: { moreFileViewer }
// v-if = 'modal'  ---是因为我放在模态框里面,一个页面上有多个数据有引入该插件,然后切换的时候根据外部标签的显示隐藏,不然第一份打开正常后,第二份点击图片放大的时候图片不显示,具体看自己的效果,有遇到的话可以根据外部标签的显示隐藏做改变
// fileUrls 绑定的数组,里面的对象是{path: '链接'},记住是path字段,只要传的数组里面的对象包含path就行,或者不想叫path,上面组件代码自己改
 // viewerId 大家都知道,id是唯一的,所以这个加随机数,或者你们加下标什么都没问题,只要确保不重复就行
// emitNowIndex 获取当前展示的轮播图的下标
<more-file-viewer v-if='modal' :fileUrls='viewArr' :viewerId="'one'+Math.floor(Math.random() * 10000)" @emitNowIndex="emitNowIndex"></more-file-viewer>

// 当前展示的文件
emitNowIndex (index) {
     this.nowIndex = index
},
上一篇下一篇

猜你喜欢

热点阅读