
<template>
<el-dialog :class="[curFileType === 'img' ? 'file-preview-dialog-img' : 'file-preview-dialog']" v-model="showDialog"
:width="curFileType === 'img' ? '600' : '60%'" title="文件预览" append-to-body
@close="handlerClose">
<div v-loading="loading" style="width: 100%;height: 100%">
<vue-office-docx v-if="curFileType === 'word' && isRenderSuccess" class="office" :src="fileUrl"
@rendered="renderedHandler" @error="errorHandler" />
<vue-office-excel v-else-if="curFileType === 'execl' && isRenderSuccess" class="office" :src="fileUrl"
@rendered="renderedHandler" @error="errorHandler" />
<VuePdfEmbed v-else-if="curFileType === 'pdf' && isRenderSuccess" class="office" :source="fileUrl"
@rendered="renderedHandler" @rendering-failed="errorHandler" />
<el-image v-else-if="curFileType === 'img' && isRenderSuccess" class="image" :src="fileUrl"
@load="renderedHandler" @error="errorHandler" />
<video v-else-if="curFileType === 'video' && isRenderSuccess" class="video" :src='fileUrl' autoplay loop
muted></video>
<el-empty v-else-if="curFileType && !isRenderSuccess" :image="loadError" description="加载失败" />
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="download">下载</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import {ref} from "vue";
const { proxy } = getCurrentInstance();
const loadError = new URL(`@/assets/images/load-error.png`, import.meta.url).href;
import VueOfficeDocx from '@vue-office/docx'
import '@vue-office/docx/lib/index.css';
import VueOfficeExcel from '@vue-office/excel'
import '@vue-office/excel/lib/index.css'
import VuePdfEmbed from 'vue-pdf-embed';
import { getCurrentInstance, onMounted} from 'vue';
const imgTypeList = ['jpg', 'png', 'jpeg', 'ofd']
const videoTypeList = ['mp4', 'avi', 'wmv', 'rmvb', 'flv', 'mkv']
const wordTypeList = ['docx','doc']
const execlTypeList = ['xlsx','xls']
const pdfTypeList = ['pdf']
const curFileType = ref('')
const loading = ref(false)
const fileUrl = ref('')
let fileType
const handlerFileType = () => {
let targetType
if (imgTypeList.includes(fileType)) {
targetType = 'img'
} else if (videoTypeList.includes(fileType)) {
targetType = 'video'
} else if (wordTypeList.includes(fileType)) {
targetType = 'word'
} else if (execlTypeList.includes(fileType)) {
targetType = 'execl'
} else if (pdfTypeList.includes(fileType)) {
targetType = 'pdf'
}
return targetType
}
function show(url,type){
loading.value = true
fileUrl.value = url
fileType = type
curFileType.value = handlerFileType()
showDialog.value = true
}
const isRenderSuccess = ref(true)
const renderedHandler = () => {
loading.value = false
}
const errorHandler = (err) => {
isRenderSuccess.value = false
loading.value = false
}
const showDialog = ref(false)
const handlerClose = () => {
fileType = ''
fileUrl.value = ''
showDialog.value = false
}
function download(){
window.open(fileUrl.value)
}
defineExpose({
show
})
</script>
<style scoped lang='scss'>
.office {
width: 100%;
height: 60vh;
overflow-y: auto;
:deep(.docx-wrapper) {
background-color: #fff !important;
}
:deep(.vue-office-pdf-wrapper) {
background-color: #fff !important;
}
}
.image {
width: 500px;
// height: 420px;
// object-fit: fill;
}
.video {
width: 100%;
max-height: 80vh;
}
.dialog-footer{
width: 100%;
display: flex;
flex-direction: row;
justify-content: center;
}
</style>
<style lang="scss">
.file-preview-dialog {
.el-dialog__body {
display: flex;
justify-content: center;
}
}
.file-preview-dialog-img {
.el-dialog__body {
height: calc(85vh - 72px);
overflow: auto;
text-align: center;
}
}
</style>