
主要是使用vue-office来实现docx和excel、pdf插件来实现预览
插件下载插件
javascript
npm i @vue-office/docx
npm i @vue-office/excel
npm i @vue-office/pdf
javascript
<script setup lang="ts">
//引入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'
//引入VueOfficePdf组件
import VueOfficePdf from '@vue-office/pdf'
import * as FileApi from '@/api/system/file'
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const dialogVisible = ref(false) // 弹窗的是否展示
const formLoading = ref(false)
const src = ref('')
const docx = ref('')
const excel = ref('')
const pdf = ref('')
const txt = ref('')
const fileObj = ref<{ fileFormat: string; fileName: string }>({
fileFormat: '',
fileName: ''
})
let fileInfo
let fileUrl
const renderedHandler = () => {
formLoading.value = false
}
const errorHandler = () => {
formLoading.value = false
}
const open = async (data: any, url: string) => {
src.value = ''
docx.value = ''
excel.value = ''
pdf.value = ''
txt.value = ''
fileInfo = data
dialogVisible.value = true
formLoading.value = true
fileObj.value = await FileApi.getuploadInfo(url)
fileUrl = await FileApi.getDownloadUrl(url)
if (fileUrl) {
try {
if (
fileObj.value.fileFormat === 'jpeg' ||
fileObj.value.fileFormat === 'jpg' ||
fileObj.value.fileFormat === 'png'
) {
src.value = fileUrl
formLoading.value = false
} else {
if (fileObj.value.fileFormat === 'xlsx' || fileObj.value.fileFormat === 'xls') {
excel.value = fileUrl
} else if (fileObj.value.fileFormat === 'docx') {
docx.value = fileUrl
} else if (fileObj.value.fileFormat === 'pdf') {
pdf.value = fileUrl
} else if (fileObj.value.fileFormat === 'txt') {
try {
const response = await fetch(fileUrl)
txt.value = await response.text()
formLoading.value = false
} catch (e) {
console.log(e)
formLoading.value = false
}
} else {
formLoading.value = false
}
console.log('fileObj.value.fileFormat', fileObj.value.fileFormat)
}
} finally {
// formLoading.value = false
}
}
}
const close = () => {
dialogVisible.value = false
}
const handleDownload = async () => {
if (!fileUrl) {
return
}
const response = await fetch(fileUrl)
if (!response.ok) {
message.success(t('common.downloadFail'))
}
const blob = await response.blob()
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = fileInfo.fileName || fileObj.value.fileName + '.' + fileObj.value.fileFormat
a.click()
}
defineExpose({
open
})
</script>
<template>
<Dialog v-model="dialogVisible" @close="close" width="900px" :destroy-on-close="true">
<div class="preview-content" v-loading="formLoading">
<img
:src="src"
alt=""
style="width: 100%"
v-if="
fileObj.fileFormat === 'jpeg' ||
fileObj.fileFormat === 'jpg' ||
fileObj.fileFormat === 'png'
"
/>
<template v-else>
<vue-office-docx
:src="docx"
v-if="docx"
style="width: 100%; height: 100%"
@rendered="renderedHandler"
@error="errorHandler"
/>
<vue-office-excel
:src="excel"
v-if="excel"
style="width: 100%; height: 100%"
@rendered="renderedHandler"
@error="errorHandler"
/>
<vue-office-pdf
:src="pdf"
v-if="pdf"
style="width: 100%; height: 100%"
@rendered="renderedHandler"
@error="errorHandler"
/>
<div v-if="txt">{{ txt }}</div>
<span v-if="!docx && !excel && !pdf && !txt">文件类型暂不支持预览</span>
</template>
</div>
<template #icon>
<Icon class="is-hover mr-10px cursor-pointer" icon="ep:download" @click="handleDownload" />
</template>
</Dialog>
</template>
<style scoped lang="scss">
.preview-content {
position: relative;
width: 100%;
height: 600px;
overflow: hidden;
}
</style>