<template> <div style="z-index: 1000; height: 75vh; overflow: auto;"> <img v-if="imgUrl" :src="imgUrl" alt="" style="width: 100%; height: 100%"/> <!-- pdf和txt使用iframe --> <pdf-view v-if="pdfUrl" v-model="pdfUrl" :fileName="fileName"></pdf-view> <!--<iframe v-if="pdfUrl" :src="pdfUrl" frameborder="0" style="width: 100%; height: 100%; min-height: 100vh"></iframe>--> <video v-if="videoUrl" :src="videoUrl" controls style="width: 100%; height: 100%; max-height: 800px"></video> <div v-if="docFile" ref="word" style="height:100%"> <iframe v-if="fileUrl" :src="fileUrl" width='100%' height='100%' frameborder='1'></iframe> </div> <div v-if="docxFile"> <div ref="file"></div> </div> <div v-if="xlsFile" class="excel-view-container"> <!-- Excel使用tab选项卡来模拟表格里的sheet业 --> <a-tabs type="card" v-if="sheetNames && sheetNames.length" @change="tabsClick"> <a-tab-pane v-for="(item, index) in sheetNames" :key="index" :tab="item"> <div id="excelView" v-html="excelView"></div> </a-tab-pane> </a-tabs> </div> </div> </template> <script> import axios from 'axios' import pdfView from '@/views/components/common/pdfView' import { getFileExtension } from '@/views/utils/common' //定义blob对应的type const fileTypeMap = { xls: 'application/vnd.ms-excel', xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', doc: 'application/msword', docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', pdf: 'application/pdf', ppt: 'application/pdf', pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation', png: 'image/png', gif: 'image/gif', jpeg: 'image/jpeg', jpg: 'image/jpeg', txt: 'text/plain', }; export default { name: 'previewFile', props: { value: { type: String, default() { return null }, }, fileName: { type: String, default() { return null } } }, components: { pdfView }, data() { return { fileType: '', //文件类型 data: '', //文件路径,blob 类型 imgUrl: '', //图片路径 pdfUrl: '', //pdf路径 videoUrl: '', //视频路径 excelView: '', //表格转换后的html数据 docFile: false, //是否是老版word文件(doc) docxFile: false, //是否是新版word文件(docx) xlsFile: false, //是否是Excel文件 execlArraybufferData: null, //Excelblob转换为arraybuff数据 sheetNames: null, //从数据中获取到的sheet页数组 imgType: [ 'bmp','jpg','jpeg','png','tif','gif','pcx','tga','exif','fpx','svg','psd','cdr','pcd','dxf','ufo','eps','ai','raw','WMF','webp','avif','apng' ], videoType: [ 'wmv','asf','asx','rm','rmvb','mp4','3gp','mov','m4v','avi','dat','mkv','flv','vob' ], wordType: [ 'text','pdf','doc','docx','xls','xlsx','ppt','pptx','rar','zip','7z','apz','ar','bz','car','dar','cpgz','f','ha','hbc','hbc2','hbe','hpk','hyp' ], fileUrl: '', previewAnnex: false, previewUrl: '', previewType: '', fileData: null } }, mounted() { this.coverUrl() }, methods: { // 预览文件 filePreviewPDF() { this.fileType = this.previewType if (this.imgType.includes(this.fileType)) { // 图片类型的 this.imgUrl = window.URL.createObjectURL(this.data) } else if (this.videoType.includes(this.fileType)) { // 视频类型的 this.videoUrl = window.URL.createObjectURL(this.data) } else if (this.fileType == 'pdf' || this.fileType == 'txt') { // pdf和文本类型的,用iframe打开 this.pdfUrl = this.previewUrl//window.URL.createObjectURL(this.data) } else if (this.fileType == 'doc') { this.docFile = true this.fileUrl = 'https://view.officeapps.live.com/op/view.aspx?src=' + location.origin + this.value } else if (this.fileType == 'docx') { // word类型的用docx-preview插件 this.docxFile = true axios.request({ method: 'GET', url: this.previewUrl, responseType: 'arraybuffer', }).then((res) => { if (res) { let docx = require('docx-preview') docx.renderAsync(res.data, this.$refs.file) } else { this.$message.error('数据接口请求失败!') } }) } else if (this.fileType == 'xls' || this.fileType == 'xlsx') { // 表格类型的用xlsx插件 this.xlsFile = true axios.request({ method: 'GET', url: this.previewUrl, responseType: 'blob', headers: { "Content-Type": "application/vnd.ms-excel;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", }, }).then((res) => { if (res) { let reader = new FileReader() reader.readAsArrayBuffer(res.data) // blob类型转换为ArrayBuffer类型 this.tabChange(0, reader) } else { this.$message.error('数据接口请求失败!') } }) } else { //this.handleClose(); this.$message.error('不支持此文件预览') } }, tabChange(index, reader) { this.excelView = '' let XLSX = require('xlsx') let _this = this // 如果第一次进来 if (!this.sheetNames) { // 文件转换加载完成后 reader.onload = function () { let arraybufferData = this.result this.execlArraybufferData = arraybufferData let data = new Uint8Array(arraybufferData) // es2017的方法 let workbook = XLSX.read(data, { type: 'array' }) // 得到表格的array数据 _this.workbooks = workbook // 赋值到此组件最外面,一会要用 let sheetNames = workbook.SheetNames // 得到execl工作表名称集合,结果类似这样['sheet1','sheet2'] _this.sheetNames = sheetNames // 赋值到此组件最外面,一会要用 let worksheet = workbook.Sheets[sheetNames[index]] // 获取第几个工作表0就是'sheet1',以此类推 _this['excelView'] = XLSX.utils.sheet_to_html(worksheet) // 把表格的array数据转换成html数据 _this.$nextTick(function () { // DOM加载完毕后执行,解决HTMLConnection有内容但是length为0问题。 _this.setStyle4ExcelHtml() }) } } else { // 已经有数据了的时候直接获取对应sheet里的内容 let worksheet = this.workbooks.Sheets[this.sheetNames[index]] this['excelView'] = XLSX.utils.sheet_to_html(worksheet) this.$nextTick(function () { // DOM加载完毕后执行,解决HTMLConnection有内容但是length为0问题。 this.setStyle4ExcelHtml() }) } }, // 设置Excel转成HTML后的样式 setStyle4ExcelHtml() { const excelViewDOM = document.getElementById('excelView') if (excelViewDOM) { const excelViewTDNodes = excelViewDOM.getElementsByTagName('td') // 获取的是HTMLConnection if (excelViewTDNodes) { const excelViewTDArr = Array.prototype.slice.call(excelViewTDNodes) for (const i in excelViewTDArr) { const id = excelViewTDArr[i].id // 默认生成的id格式为sjs-A1、sjs-A2...... if (id) { const idNum = id.replace(/[^0-9]/gi, '') // 提取id中的数字,即行号 if (idNum && (idNum === '1' || idNum === 1)) { // 第一行标题行 excelViewTDArr[i].classList.add('class4Title') } if (idNum && (idNum === '1' || idNum === 1)) { // 第二行表头行 excelViewTDArr[i].classList.add('class4TableTh') } } } } } }, tabsClick (key) { this.tabChange(key) }, //文件预览判断 coverUrl () { var type = getFileExtension(this.fileName) this.previewType = type this.previewUrl = this.value this.previewAnnex = true this.filePreviewPDF() return Promise.resolve() }, }, watch: { previewType: { handler(value) { this.fileType = value }, immediate: true, // 重点 deep: true, // 重点 }, previewUrl: { handler(value) { this.data = value }, immediate: true, // 重点 deep: true, // 重点 }, }, }; </script> <style lang="less" scoped=""> ::v-deep table { width: 100% !important; border-collapse: collapse !important; border-spacing: 0 !important; text-align: center !important; border: 0px !important; overflow-x: auto !important; } ::v-deep table tr td { border: 2px solid gray !important; width: 300px !important; height: 33px !important; } /**整体样式 */ ::v-deep .excel-view-container { background-color: #ffffff; } /**标题样式 */ ::v-deep .class4Title { font-size: 22px !important; font-weight: bold !important; padding: 10px !important; } /**表格表头样式 */ ::v-deep .class4TableTh { /* font-size: 14px !important; */ font-weight: bold !important; padding: 2px !important; background-color: #ccc !important; } </style>