<!--onlyoffice 编辑器-->
|
<template>
|
<div class="document-preview">
|
<iframe
|
v-if="isPdf"
|
:key="option.url"
|
:src="option.url"
|
class="native-pdf-preview"
|
title="PDF预览"
|
></iframe>
|
<div v-else id="vabOnlyOffice"></div>
|
</div>
|
</template>
|
|
<script>
|
// OnlyOffice 文档服务地址,按环境配置;脚本在真正需要预览时才加载
|
const OFFICE_API_BASE = import.meta.env.VITE_APP_ONLYOFFICE_API || "http://192.168.21.53:9001";
|
|
// 多个页面共用编辑器,api.js 只加载一次
|
let docsApiPromise = null;
|
function loadDocsApi() {
|
if (window.DocsAPI) {
|
return Promise.resolve(window.DocsAPI);
|
}
|
if (!docsApiPromise) {
|
docsApiPromise = new Promise((resolve, reject) => {
|
const script = document.createElement("script");
|
script.src = OFFICE_API_BASE.replace(/\/$/, "") + "/web-apps/apps/api/documents/api.js";
|
script.onload = () => {
|
if (window.DocsAPI) {
|
resolve(window.DocsAPI);
|
} else {
|
reject(new Error("api.js 加载完成但未注册 DocsAPI"));
|
}
|
};
|
script.onerror = () => reject(new Error("OnlyOffice 文档服务脚本加载失败:" + script.src));
|
document.head.appendChild(script);
|
});
|
// 加载失败后允许下次重试
|
docsApiPromise.catch(() => {
|
docsApiPromise = null;
|
});
|
}
|
return docsApiPromise;
|
}
|
|
export default {
|
name: "VabOnlyOffice",
|
props: ['options'],
|
data() {
|
return {
|
doctype: "",
|
docEditor: null,
|
//参考vabOnlyOffice组件参数配置
|
option: {
|
url: "",
|
isEdit: false,
|
fileType: "",
|
title: "",
|
lang: "zh-CN",
|
isPrint: true,
|
user: {},
|
editUrl: ""
|
}
|
};
|
},
|
computed: {
|
isPdf() {
|
return this.isPdfFile(this.option);
|
}
|
},
|
created() {
|
if(this.options){
|
const option = this.options
|
this.option.url = option.url
|
this.option.isEdit = option.isEdit === "true" ? true : false
|
this.option.fileType = option.fileType
|
this.option.title = option.title
|
this.option.lang = option.lang
|
this.option.isPrint = option.isPrint
|
this.option.user.id = option.user_id
|
this.option.user.name = option.user_name
|
this.option.editUrl = option.editUrl
|
}else{
|
const option = this.$route.query
|
this.option.url = option.url
|
this.option.isEdit = option.isEdit === "true" ? true : false
|
this.option.fileType = option.fileType
|
this.option.title = option.title
|
this.option.lang = option.lang
|
this.option.isPrint = option.isPrint
|
this.option.user.id = option.user_id
|
this.option.user.name = option.user_name
|
this.option.editUrl = option.editUrl
|
}
|
},
|
beforeUnmount() {
|
this.destroyEditor();
|
},
|
watch: {
|
option: {
|
handler: function(n) {
|
this.setEditor(n);
|
this.doctype = this.getFileType(n.fileType);
|
},
|
deep: true
|
}
|
},
|
mounted() {
|
if (this.option.url) {
|
this.setEditor(this.option);
|
}
|
},
|
methods: {
|
destroyEditor() {
|
if (this.docEditor !== null) {
|
this.docEditor.destroyEditor();
|
this.docEditor = null;
|
}
|
},
|
async setEditor(option) {
|
this.destroyEditor();
|
// PDF 使用浏览器原生预览;其他文档才初始化 OnlyOffice。
|
if (!option || !option.url || this.isPdfFile(option)) {
|
return;
|
}
|
// 等待 v-else 中的 OnlyOffice 容器完成渲染。
|
await this.$nextTick();
|
this.doctype = this.getFileType(option.fileType);
|
let config = {
|
document: {
|
//后缀
|
fileType: option.fileType,
|
key: option.key || "",
|
title: option.title,
|
permissions: {
|
edit: option.isEdit, //是否可以编辑: 只能查看,传false
|
print: option.isPrint,
|
download: false
|
// "fillForms": true,//是否可以填写表格,如果将mode参数设置为edit,则填写表单仅对文档编辑器可用。 默认值与edit或review参数的值一致。
|
// "review": true //跟踪变化
|
},
|
url: option.url
|
},
|
documentType: this.doctype,
|
editorConfig: {
|
callbackUrl: option.editUrl, //"编辑word后保存时回调的地址,这个api需要自己写了,将编辑后的文件通过这个api保存到自己想要的位置
|
lang: option.lang, //语言设置
|
//定制
|
customization: {
|
autosave: true, //是否自动保存
|
chat: true,
|
comments: false,
|
help: false,
|
"hideRightMenu": false,//定义在第一次加载时是显示还是隐藏右侧菜单。 默认值为false
|
//是否显示插件
|
plugins: false
|
},
|
user: {
|
id: option.user.id,
|
name: option.user.name
|
},
|
mode: option.model ? option.model : "edit"
|
},
|
width: "100%",
|
height: "100%",
|
token: option.token || ""
|
};
|
|
try {
|
await loadDocsApi();
|
} catch (error) {
|
console.error(error);
|
this.$message.error("文档服务暂时不可用,无法预览");
|
return;
|
}
|
if (this._isDestroyed) {
|
return;
|
}
|
this.docEditor = new window.DocsAPI.DocEditor("vabOnlyOffice", config);
|
},
|
isPdfFile(option) {
|
if (!option) {
|
return false;
|
}
|
const fileType = String(option.fileType || "").toLowerCase();
|
const url = String(option.url || "").split(/[?#]/)[0].toLowerCase();
|
return fileType === "pdf" || url.endsWith(".pdf");
|
},
|
getFileType(fileType) {
|
let docType = "";
|
let fileTypesDoc = [
|
"doc",
|
"docm",
|
"docx",
|
"dot",
|
"dotm",
|
"dotx",
|
"epub",
|
"fodt",
|
"htm",
|
"html",
|
"mht",
|
"odt",
|
"ott",
|
"pdf",
|
"rtf",
|
"txt",
|
"djvu",
|
"xps"
|
];
|
let fileTypesCsv = [
|
"csv",
|
"fods",
|
"ods",
|
"ots",
|
"xls",
|
"xlsm",
|
"xlsx",
|
"xlt",
|
"xltm",
|
"xltx"
|
];
|
let fileTypesPPt = [
|
"fodp",
|
"odp",
|
"otp",
|
"pot",
|
"potm",
|
"potx",
|
"pps",
|
"ppsm",
|
"ppsx",
|
"ppt",
|
"pptm",
|
"pptx"
|
];
|
if (fileTypesDoc.includes(fileType)) {
|
docType = "text";
|
}
|
if (fileTypesCsv.includes(fileType)) {
|
docType = "spreadsheet";
|
}
|
if (fileTypesPPt.includes(fileType)) {
|
docType = "presentation";
|
}
|
return docType;
|
}
|
}
|
};
|
</script>
|
|
<style scoped>
|
.document-preview,
|
.native-pdf-preview,
|
#vabOnlyOffice {
|
width: 100%;
|
height: 100%;
|
}
|
.native-pdf-preview {
|
display: block;
|
border: 0;
|
}
|
html,
|
body {
|
height: 100%;
|
}
|
#app {
|
font-family: Avenir, Helvetica, Arial, sans-serif;
|
-webkit-font-smoothing: antialiased;
|
-moz-osx-font-smoothing: grayscale;
|
text-align: center;
|
color: #2c3e50;
|
height: 100%;
|
}
|
.qualityManual-container {
|
padding: 0 !important;
|
height: 100%;
|
}
|
.qualityManual-container-office {
|
width: 100%;
|
height: calc(100% - 55px);
|
}
|
</style>
|