docx、pdf、xlsx文件的预览
package.json里面引入依赖,进行安装
"dependencies": {
"@vue-office/docx": "^1.3.1",
"@vue-office/excel": "^1.4.6",
"@vue-office/pdf": "^1.5.5",
"@vue/composition-api": "^1.7.2",
}
组件代码
<template>
<div class="office">
<vue-office-docx
class="flex1"
v-if="preview.fileType == 'docx'"
:src="preview.url"
:style="{height:height + 'px'}"
@rendered="rendered"
/>
<vue-office-pdf
class="flex1"
v-else-if="preview.fileType == 'pdf'"
:src="preview.url"
:style="{height:height + 'px'}"
@rendered="rendered"
/>
<vue-office-excel
class="flex1"
v-else-if="preview.fileType == 'xlsx'"
:src="preview.url"
:style="{height:height + 'px'}"
@rendered="rendered"
/>
<div
v-else
class="flex1"
:style="{height:height + 'px'}">
<slot name="nopreview" :data="preview">
<el-empty :description="`${preview.name}暂时无法预览`">
<!-- <el-button type="primary">下载</el-button> -->
</el-empty>
</slot>
</div>
<div class="download" v-if="hasDownload">
<el-link icon="el-icon-download" type="primary"
:href="`${preview.url}`"
:underline="false"
target="_blank"
class="mr5 mt5 mb5"
></el-link>
</div>
</div>
</template>
<script>
//引入VueOfficeDocx组件
import VueOfficeDocx from '@vue-office/docx'
//引入相关样式
import '@vue-office/docx/lib/index.css'
//引入VueOfficeExcel组件
import VueOfficeExcel from '@vue-office/excel'
//引入相关样式
import '@vue-office/excel/lib/index.css'
import VueOfficePdf from '@vue-office/pdf'
export default {
name:"FilePreview",
data(){
return{
}
},
props:{
/**
* fileType 文件类型 docx pdf xlsx
* name 文件名称 暂时没有用到
* title 标题 暂时没有用到
* url 文件的地址
*/
preview:{
fileType:'',
name:'',
title:'',
url:'',
},
// 预览框的高度
height:{
type:Number,
default:720
},
// 是否有下载功能
hasDownload:{
type:Boolean,
default:false
}
},
components: {
VueOfficeDocx,
VueOfficeExcel,
VueOfficePdf
},
methods:{
// 渲染完成函数
rendered(){
this.$emit('rendered')
}
}
}
</script>
<style scoped>
.office{
width: 100%;
position: relative;
}
.download{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: fit-content;
background: #e8eaed;
display: flex;
justify-content: flex-end;
/* border-radius: 10px; */
}
/* 自动宽度 */
.flex1{
flex:1
}
</style>
正常引入组件的方式使用
import FilePreview from '@/components/FilePreview/index.vue' //引入预览组件
我个人的preview数据
goView(item){
this.dialogVisible = true
let fileString = item.file
if(fileString.includes('.docx')){
this.preview.fileType = 'docx'
}else if(fileString.includes('.pdf')){
this.preview.fileType = 'pdf'
}else if(fileString.includes('.xlsx')){
this.preview.fileType = 'xlsx'
}else{
this.preview.fileType = ''
}
this.preview.title = item.title + '附件预览'
this.preview.url = this.preview.fileType != '' ? this.baseUrl + item.file : ''
}
如果有更多场景使用欢迎评论改进
进一步完善功能,传入多个对象,切换
<template>
<div class="office">
<vue-office-docx
class="flex1"
v-if="previews.fileType == 'docx'"
:src="previews.url"
:style="{height:height + 'px'}"
@rendered="rendered"
/>
<vue-office-pdf
class="flex1"
v-else-if="previews.fileType == 'pdf'"
:src="previews.url"
:style="{height:height + 'px'}"
@rendered="rendered"
/>
<vue-office-excel
class="flex1"
v-else-if="previews.fileType == 'xlsx'"
:src="previews.url"
:style="{height:height + 'px'}"
@rendered="rendered"
/>
<div v-else-if="['png','jpg','jpeg'].includes(previews.fileType)">
<slot name="image" :data="previews"></slot>
</div>
<div
v-else
class="flex1"
:style="{height:height + 'px'}">
<slot name="nopreview" :data="previews">
<el-empty :description="`${previews.name}暂时无法预览`">
<!-- <el-button type="primary">下载</el-button> -->
</el-empty>
</slot>
</div>
<div class="download" v-if="hasDownload">
<el-link icon="el-icon-download" type="primary"
:href="`${previews.url}`"
:underline="false"
target="_blank"
class="mr5 mt5 mb5"
></el-link>
</div>
<div v-if="fileResources.length>1">
<el-button type="success" icon="el-icon-arrow-left" class="pre" :disabled="cutIndex == 0" circle @click="pre()"></el-button>
<el-button type="success" icon="el-icon-arrow-right" class="next" :disabled="cutIndex == fileResources.length-1" circle @click="next()"></el-button>
</div>
</div>
</template>
<script>
//引入VueOfficeDocx组件
import VueOfficeDocx from '@vue-office/docx'
//引入相关样式
import '@vue-office/docx/lib/index.css'
//引入VueOfficeExcel组件
import VueOfficeExcel from '@vue-office/excel'
//引入相关样式
import '@vue-office/excel/lib/index.css'
import VueOfficePdf from '@vue-office/pdf'
export default {
name:"FilePreview",
data(){
return{
previews:{
fileType:'',
name:'',
title:'',
url:'',
},
fileResources:[],
cutIndex:null
}
},
props:{
/**
* fileType 文件类型 docx pdf xlsx
* name 文件名称 暂时没有用到
* title 标题 暂时没有用到
* url 文件的地址
*/
preview:{
fileType:'',
name:'',
title:'',
url:'',
},
// 预览框的高度
height:{
type:Number,
default:720
},
// 是否有下载功能
hasDownload:{
type:Boolean,
default:false
},
// 多文件预览数据源
fileResource:{
type:Array,
default:()=>{return[]}
},
// 请求的前缀
baseUrl:{
type:String,
default:process.env.VUE_APP_BASE_API
}
},
components: {
VueOfficeDocx,
VueOfficeExcel,
VueOfficePdf
},
watch:{
fileResource:{
handler(newVal, oldVal) {
if(this.fileResource.length != 0){
this.splitRequestPath()
}
},
deep: true, // 加这个属性,深度监听
},
preview:{
handler(newVal, oldVal) {
console.log("preview🚀 ~ handler ~ newVal:", newVal,oldVal)
this.previews = this.preview
},
deep: true, // 加这个属性,深度监听
}
},
mounted(){
console.log("🚀 ~ mounted ~ mounted:")
this.previews = this.preview
console.log("🚀 ~ mounted ~ this.previews:", this.previews)
if(this.fileResource.length != 0){
this.splitRequestPath()
}
},
destroyed(){
this.previews = {}
this.preview = {}
this.fileResources = []
this.fileResource = []
},
methods:{
// 渲染完成函数
rendered(){
this.$emit('rendered')
},
// 拼接请求路径
splitRequestPath(){
this.fileResources = []
if(this.baseUrl){
this.fileResource.forEach((element,index) => {
if(this.preview.url.includes(element)){
this.cutIndex = index
}
let info = this.returnFileInfo(element)
this.fileResources.push({
...info,
url:this.baseUrl + info.url
})
});
}
},
// 根据路径分解出文件类型,名称,标题,url等等
returnFileInfo(path){
console.log("🚀 ~ returnFileInfo ~ path:", path)
let o = {
fileType:'',
name:'',
title:'',
url:path,
}
if (path.lastIndexOf("/") > -1) {
o.name = path.slice(path.lastIndexOf("/") + 1);
let index = path.slice(path.lastIndexOf("/") + 1).lastIndexOf(".")
o.fileType = o.name.slice(index + 1)
} else {
o.name = "";
}
return o;
},
next(){
this.previews = this.fileResources[++this.cutIndex]
this.$forceUpdate()
},
pre(){
this.previews = this.fileResources[--this.cutIndex]
this.$forceUpdate()
}
}
}
</script>
<style scoped>
.office{
width: 100%;
position: relative;
}
.download{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: fit-content;
background: #e8eaed;
display: flex;
justify-content: flex-end;
/* border-radius: 10px; */
}
/* 自动宽度 */
.flex1{
flex:1
}
.pre{
position: absolute;
top:50%;
}
.next{
position: absolute;
top:50%;
right: 10px;
}
</style>