<template>
|
<el-dialog v-model="dialogVisible" title="预览" width="100%" fullscreen align-center :before-close="handleClose" append-to-body>
|
<div>
|
<!-- 图片预览 -->
|
<div v-if="isImage">
|
<img :src="imgUrl" alt="Image Preview" />
|
</div>
|
|
<!-- PDF预览 -->
|
<div v-if="isPdf" class="pdf-preview-wrapper">
|
<iframe :src="fileUrl" class="pdf-preview-frame" frameborder="0"></iframe>
|
</div>
|
|
<!-- Word文档预览 -->
|
<div v-if="isDoc">
|
<p v-if="!isDocShow">文档无法直接预览,请下载查看。</p>
|
<a :href="fileUrl" v-if="!isDocShow">下载文件</a>
|
<vue-office-docx
|
v-else
|
:src="fileUrl"
|
style="height: 100vh;"
|
@rendered="renderedHandler"
|
@error="errorHandler"
|
/>
|
</div>
|
|
<!-- Excel文档预览 -->
|
<div v-if="isXls">
|
<p v-if="!isDocShow">文档无法直接预览,请下载查看。</p>
|
<a :href="fileUrl" v-if="!isDocShow">下载文件</a>
|
<vue-office-excel
|
v-else
|
:src="fileUrl"
|
:options="options"
|
style="height: 100vh;"
|
@rendered="renderedHandler"
|
@error="errorHandler"
|
/>
|
</div>
|
|
<!-- 压缩文件处理 -->
|
<div v-if="isZipOrRar">
|
<p>压缩文件无法直接预览,请下载查看。</p>
|
<a :href="fileUrl">下载文件</a>
|
</div>
|
|
<!-- 不支持的格式 -->
|
<div v-if="!isSupported">
|
<p>不支持的文件格式</p>
|
</div>
|
</div>
|
</el-dialog>
|
</template>
|
|
<script setup>
|
import { ref, computed, getCurrentInstance } from 'vue';
|
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';
|
|
// 响应式变量
|
const fileUrl = ref('')
|
const dialogVisible = ref(false)
|
const { proxy } = getCurrentInstance();
|
const javaApi = proxy.javaApi;
|
|
// 文档预览状态
|
const isDocShow = ref(true);
|
const imgUrl = ref('');
|
const options = ref({
|
xls: false,
|
minColLength: 0,
|
minRowLength: 0,
|
widthOffset: 10,
|
heightOffset: 10,
|
beforeTransformData: (workbookData) => workbookData,
|
transformData: (workbookData) => workbookData,
|
});
|
|
// 计算属性 - 判断文件类型
|
const isImage = computed(() => {
|
const state = /\.(jpg|jpeg|png|gif)$/i.test(fileUrl.value);
|
if (state) {
|
imgUrl.value = fileUrl.value.replaceAll('word', 'img');
|
}
|
return state;
|
});
|
|
const isPdf = computed(() => {
|
console.log(fileUrl.value)
|
return /\.pdf$/i.test(fileUrl.value);
|
});
|
|
const isDoc = computed(() => {
|
return /\.(doc|docx)$/i.test(fileUrl.value);
|
});
|
|
const isXls = computed(() => {
|
const state = /\.(xls|xlsx)$/i.test(fileUrl.value);
|
if (state) {
|
options.value.xls = /\.(xls)$/i.test(fileUrl.value);
|
}
|
return state;
|
});
|
|
const isZipOrRar = computed(() => {
|
return /\.(zip|rar)$/i.test(fileUrl.value);
|
});
|
|
const isSupported = computed(() => {
|
return isImage.value || isPdf.value || isDoc.value || isXls.value || isZipOrRar.value;
|
});
|
|
// 方法定义
|
const renderedHandler = () => {
|
console.log("渲染完成");
|
isDocShow.value = true;
|
resetStyle();
|
};
|
|
const errorHandler = () => {
|
console.log("渲染失败");
|
isDocShow.value = false;
|
};
|
|
const open = (url) => {
|
fileUrl.value = window.location.protocol+'//'+window.location.host+ url;
|
dialogVisible.value = true;
|
};
|
const handleClose = () => {
|
dialogVisible.value = false;
|
};
|
|
const resetStyle = () => {
|
const elements = document.querySelectorAll('[style*="pt"]');
|
for (const element of elements) {
|
const style = element.getAttribute('style');
|
if (style) {
|
element.setAttribute('style', style.replace(/pt/g, 'px'));
|
}
|
}
|
};
|
|
// 暴露open方法供外部调用
|
defineExpose({
|
open
|
})
|
</script>
|
|
<style scoped>
|
img {
|
max-width: 100%;
|
display: block;
|
margin: 0 auto;
|
}
|
|
.pdf-preview-wrapper {
|
height: 100vh;
|
}
|
|
.pdf-preview-frame {
|
width: 100%;
|
height: 100%;
|
}
|
|
.oneLine {
|
overflow: hidden;
|
white-space: nowrap;
|
text-overflow: ellipsis;
|
}
|
</style>
|