首先,按需拉取,依賴和項(xiàng)目對(duì)應(yīng)的版本 ,引入方法,和調(diào)用方法,根據(jù)版本來(lái)
- npm install @vue-office/docx
- npm install @vue-office/pdf
- npm install @vue-office/excel
- npm install @vue-office/pptx
- 根據(jù)版本,有的需要 npm install @vue/composition-api

image.png
如果pdf不需要修改樣式,可以使用iframe
<template>
<div id="docx-demo">
<div class="file-info">
<h3>正在預(yù)覽: {{ selectedFile.name }}</h3>
<p>文件大小: {{ formatFileSize(selectedFile.size) }}</p>
</div>
<div class="loading" v-if="loading">
<div class="spinner"></div>
<p>加載中,請(qǐng)稍候...</p>
</div>
<el-upload
:limit="1"
:file-list="fileList"
:beforeUpload="beforeUpload"
action=""
>
<el-button size="small" type="warning">點(diǎn)擊上傳</el-button>
</el-upload>
<vue-office-docx
v-if="fileType === 'docx' || fileType === 'doc'"
:src="src"
@rendered="onRendered"
@error="onError"
/>
<vue-office-excel
:src="excel"
v-if="fileType === 'xlsx' || fileType === 'xls'"
:options="options"
style="height: 500px"
@rendered="onRendered"
@error="onError"
/>
<vue-office-pdf
v-if="fileType === 'pdf'"
:src="pdf"
style="height: 100vh"
@rendered="onRendered"
@error="onError"
/>
<div
class="custom-ppt-viewer"
v-if="fileType === 'pptx' || fileType === 'ppt'"
>
<vue-office-pptx :src="ppt" @rendered="onRendered" @error="onError" />
</div>
<iframe
:src="previewUrl"
frameborder="0"
class="pdf-iframe"
@load="handleIframeLoad"
@error="handleIframeError"
></iframe>
</div>
</template>
<script>
import VueOfficeDocx from "@vue-office/docx";
import "@vue-office/docx/lib/index.css";
//引入VueOfficeExcel組件
import VueOfficeExcel from "@vue-office/excel";
//引入相關(guān)樣式
import "@vue-office/excel/lib/index.css";
import VueOfficePdf from "@vue-office/pdf";
import VueOfficePptx from "@vue-office/pptx";
export default {
components: {
VueOfficeDocx,
VueOfficeExcel,
VueOfficePdf,
VueOfficePptx,
},
data() {
return {
ppt: "",
previewUrl: "",
acceptTypes: ".docx,.xlsx,.pptx,.pdf",
loading: false,
fileType: "",
selectedFile: { name: "", size: 0 },
pdf: "",
excel: "",
src: "",
fileList: [],
options: {
xls: false, //預(yù)覽xlsx文件設(shè)為false;預(yù)覽xls文件設(shè)為true
// minColLength: 0, // excel最少渲染多少列,如果想實(shí)現(xiàn)xlsx文件內(nèi)容有幾列,就渲染幾列,可以將此值設(shè)置為0.
// minRowLength: 0, // excel最少渲染多少行,如果想實(shí)現(xiàn)根據(jù)xlsx實(shí)際函數(shù)渲染,可以將此值設(shè)置為0.
widthOffset: 10, //如果渲染出來(lái)的結(jié)果感覺(jué)單元格寬度不夠,可以在默認(rèn)渲染的列表寬度上再加 Npx寬
heightOffset: 10, //在默認(rèn)渲染的列表高度上再加 Npx高
beforeTransformData: (workbookData) => {
return workbookData;
}, //底層通過(guò)exceljs獲取excel文件內(nèi)容,通過(guò)該鉤子函數(shù),可以對(duì)獲取的excel文件內(nèi)容進(jìn)行修改,比如某個(gè)單元格的數(shù)據(jù)顯示不正確,可以在此自行修改每個(gè)單元格的value值。
transformData: (workbookData) => {
return workbookData;
}, //將獲取到的excel數(shù)據(jù)進(jìn)行處理之后且渲染到頁(yè)面之前,可通過(guò)transformData對(duì)即將渲染的數(shù)據(jù)及樣式進(jìn)行修改,此時(shí)每個(gè)單元格的text值就是即將渲染到頁(yè)面上的內(nèi)容
},
};
},
methods: {
// 檢查文件大小 (這里限制為10MB)
// const maxSize = 10 * 1024 * 1024; // 10MB
// if (file.size > maxSize) {
// this.errorMessage = '文件大小不能超過(guò)10MB';
// return;
// }
// 處理iframe加載完成
handleIframeLoad() {
console.log("PDF預(yù)覽加載完成");
},
// 處理iframe加載錯(cuò)誤
handleIframeError() {
this.errorMessage = "PDF預(yù)覽失敗,請(qǐng)嘗試重新上傳";
},
formatFileSize(bytes) {
if (bytes === 0) return "0 Bytes";
const k = 1024;
const sizes = ["Bytes", "KB", "MB", "GB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
},
onRendered() {
this.loading = false;
console.log("文檔渲染完成");
},
onError(err) {
this.loading = false;
this.error = "文檔預(yù)覽失敗: " + err.message;
console.error("預(yù)覽錯(cuò)誤:", err);
},
//在beforeUpload中讀取文件內(nèi)容
beforeUpload(file) {
if (!file) return;
this.selectedFile = file;
this.error = "";
this.loading = true;
// 獲取文件類型
const fileName = file.name.toLowerCase();
if (fileName.endsWith(".docx")) {
this.fileType = "docx";
} else if (fileName.endsWith(".doc")) {
this.fileType = "doc";
} else if (fileName.endsWith(".ppt")) {
this.fileType = "ppt";
} else if (fileName.endsWith(".xlsx")) {
this.fileType = "xlsx";
} else if (fileName.endsWith(".xls")) {
this.fileType = "xls";
} else if (fileName.endsWith(".pptx")) {
this.fileType = "pptx";
} else if (fileName.endsWith(".pdf")) {
this.fileType = "pdf";
} else if (fileName.endsWith(".txt")) {
this.fileType = "txt";
} else {
this.error = "不支持的文件格式";
this.loading = false;
return;
}
let reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = (loadEvent) => {
let arrayBuffer = loadEvent.target.result;
if (this.fileType == "xlsx" || this.fileType == "xls") {
this.excel = arrayBuffer;
} else if (this.fileType == "docx" || this.fileType == "doc") {
this.src = arrayBuffer;
} else if (this.fileType == "pptx" || this.fileType == "ppt") {
this.ppt = arrayBuffer;
}
if (this.fileType == "pdf" || this.fileType == "txt") {
this.pdf = arrayBuffer;
this.previewFile(file);
}
};
return false;
},
// 預(yù)覽PDF文件
previewFile(file) {
// 模擬上傳進(jìn)度
this.uploadProgress = 0;
const interval = setInterval(() => {
this.uploadProgress += 10;
if (this.uploadProgress >= 100) {
clearInterval(interval);
// 創(chuàng)建文件的臨時(shí)URL用于預(yù)覽
this.previewUrl = URL.createObjectURL(file);
}
}, 200);
},
},
};
</script>
<style scoped>
.pdf-iframe {
width: 100%;
height: 400px;
}
.custom-ppt-viewer {
width: 100%;
max-width: 900px;
margin: 0 auto;
height: 700px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.custom-ppt-viewer .slide-container {
background-color: #f9f9f9;
margin-bottom: 20px;
border-radius: 8px;
overflow: hidden;
}
</style>