FilePreviewTs
<template>
<!-- doc -->
<el-dialog v-model="dialogDocxValue" :title="dialogTitle" width="80%" @close="dialogDocxClose">
<div ref="docxRef" class="word-div"></div>
</el-dialog>
<!-- xlsx -->
<el-dialog v-model="dialogXlsxValue" :title="dialogTitle" width="80%" @close="dialogXlsxClose">
<div ref="xlsxRef" class="xlsx-div">
<el-tabs v-model="activeName" type="border-card">
<el-tab-pane v-for="(item, index) in excelSheet" :key="index" :label="item.name" :name="item.name">
<div class="table" v-html="item.html"></div>
</el-tab-pane>
</el-tabs>
</div>
</el-dialog>
<!-- 图片 -->
<el-dialog v-model="dialogImgValue" :title="dialogTitle" width="80%" @close="dialogImgClose">
<div class="img-div">
<el-image :src="fileData.src" :alt="fileData.fileOldName" />
</div>
</el-dialog>
<!-- pdf -->
<el-dialog v-model="dialogPdfValue" :title="dialogTitle" width="80%" @close="dialogPdfClose">
<div class="pdf-div">
<iframe id="pdfRef" :src="iframeUrl" frameborder="0" style="width: 100%; height: 99%"></iframe>
</div>
</el-dialog>
</template>
<script setup lang="ts">
import axios from 'axios';
import { defineProps, ref, reactive, computed, nextTick } from 'vue';
import { renderAsync } from 'docx-preview';
import * as XLSX from 'xlsx';
interface Props {
dialogDocx?: boolean;
dialogXlsx?: boolean;
dialogTitle?: string;
}
const props: any = withDefaults(defineProps<Props>(), {
dialogDocx: false,
dialogTitle: '',
dialogXlsx: false,
});
const dialogDocxValue: any = ref(false);
let dialogTitle = computed(() => {
return props.dialogTitle;
});
const fileHtml = ref('');
const docxRef = ref<any>();
// doc 文档预览
const viewDocx = (data: any) => {
docxRef.value = '';
dialogDocxValue.value = true;
console.log(data);
if (data.src) {
// 已上传的文件
axios({
url: data.src,
method: 'get',
responseType: 'blob',
}).then((res) => {
console.log(res);
if (res.status == 200) {
const content = res.data;
const blob = new Blob([content]);
nextTick(() => {
dialogDocxValue.value = true;
renderAsync(blob, docxRef.value);
dialogTitle = data.fileOldName || data.name;
});
}
});
} else {
// 本地文件
const blob = new Blob([data.raw]);
nextTick(() => {
dialogDocxValue.value = true;
renderAsync(blob, docxRef.value);
dialogTitle = data.fileOldName || data.name;
});
}
};
const dialogXlsxValue: any = ref(false);
const excelSheet: any = ref([]);
const activeName = ref('');
const dialogDocxClose = () => {
dialogDocxValue.value = false;
docxRef.value = '';
};
// xlsx 预览
const viewXlsx = (data: any) => {
dialogXlsxValue.value = true;
console.log(data);
if (data.src) {
axios({
url: data.src,
method: 'get',
responseType: 'blob',
}).then((res) => {
console.log(res);
if (res.status == 200) {
const content = res.data;
// const blob = new Blob(content);
const reader = new FileReader();
reader.readAsArrayBuffer(content);
reader.onload = function (loadEvent: any) {
const arrayBuffer = loadEvent.target['result'];
const workbook = XLSX.read(new Uint8Array(arrayBuffer), {
type: 'array',
});
const list = [];
const sheetNames = workbook.SheetNames;
activeName.value = sheetNames[0];
for (const p of sheetNames) {
let html = '';
try {
html = XLSX.utils.sheet_to_html(workbook.Sheets[p]);
} catch (e) {
html = '';
}
const map = {
name: p,
html: html,
};
list.push(map);
}
excelSheet.value = list;
dialogTitle = data.fileName || data.name;
};
}
});
} else {
const blob = new Blob([data.raw]);
const reader = new FileReader();
reader.readAsArrayBuffer(blob);
reader.onload = function (loadEvent: any) {
const arrayBuffer = loadEvent.target['result'];
const workbook = XLSX.read(new Uint8Array(arrayBuffer), {
type: 'array',
});
const list = [];
const sheetNames = workbook.SheetNames;
activeName.value = sheetNames[0];
for (const p of sheetNames) {
let html = '';
try {
html = XLSX.utils.sheet_to_html(workbook.Sheets[p]);
} catch (e) {
html = '';
}
const map = {
name: p,
html: html,
};
list.push(map);
}
excelSheet.value = list;
dialogTitle = data.fileName || data.name;
};
}
};
const dialogXlsxClose = () => {
dialogXlsxValue.value = false;
excelSheet.value = '';
activeName.value = '';
};
const fileData: any = ref({});
const dialogImgValue: any = ref(false);
// 图片预览
const viewImg = (data: any) => {
if (data.src) {
// 已上传的图片
fileData.value = data;
} else {
// 本地图片
const freader = new FileReader();
freader.readAsDataURL(data.raw);
freader.onload = (e: any) => {
fileData.value = {
src: e.target.result,
id: new Date(),
fileName: data.fileOldName || data.name,
};
};
}
dialogTitle = data.fileOldName || data.name;
dialogImgValue.value = true;
};
const dialogImgClose = () => {
dialogImgValue.value = false;
};
const dialogPdfValue: any = ref(false);
const iframeUrl: any = ref('');
const pdfRef = ref<any>();
const viewPdf = (data: any) => {
if (data.src) {
axios({
url: data.src,
method: 'get',
responseType: 'blob',
}).then((res) => {
if (res.status == 200) {
// 把文件流转化为url
iframeUrl.value = URL.createObjectURL(res.data);
dialogPdfValue.value = true;
}
});
} else {
iframeUrl.value = URL.createObjectURL(data.raw);
dialogPdfValue.value = true;
}
};
const dialogPdfClose = () => {
dialogPdfValue.value = false;
};
defineExpose({
viewDocx,
viewXlsx,
viewImg,
viewPdf,
});
</script>
<style scoped lang="scss">
.word-div {
height: calc(70vh);
overflow: auto;
}
.xlsx-div {
height: calc(70vh);
overflow: auto;
}
.img-div {
height: calc(70vh);
overflow: auto;
img {
width: 100%;
height: 100%;
}
}
.pdf-div {
height: calc(70vh);
overflow: auto;
}
</style>
<style lang="scss">
.xlsx-div {
.table-html-wrap table {
border-right: 1px solid #fff;
border-bottom: 1px solid #e8eaec;
border-collapse: collapse;
// margin: auto;
}
.table-html-wrap table td {
border-left: 1px solid #e8eaec;
border-top: 1px solid #e8eaec;
white-space: wrap;
text-align: left;
min-width: 100px;
padding: 4px;
}
table {
border-top: 1px solid #ebeef5;
border-left: 1px solid #ebeef5;
width: 100%;
// overflow: auto;
tr {
height: 44px;
}
td {
min-width: 200px;
max-width: 400px;
padding: 4px 8px;
border-right: 1px solid #ebeef5;
border-bottom: 1px solid #ebeef5;
}
}
.el-tabs--border-card > .el-tabs__content {
overflow-x: auto;
}
}
</style>