2025-11-04 13:22:28 +08:00
|
|
|
<template>
|
2025-11-07 13:34:04 +08:00
|
|
|
<div class="onlyoffice-container">
|
|
|
|
|
<div id="placeholder" class="editor-placeholder"></div>
|
2025-11-04 13:22:28 +08:00
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
2025-11-07 13:34:04 +08:00
|
|
|
import { getConfigAPI, generateCallbackTokenAPI } from '@/api/common/onlyOfficeViewer'
|
2025-11-04 13:22:28 +08:00
|
|
|
export default {
|
|
|
|
|
name: 'OnlyOfficeViewer',
|
|
|
|
|
props: {
|
2025-11-07 13:34:04 +08:00
|
|
|
// 可以添加 props 来动态配置
|
|
|
|
|
documentUrl: {
|
2025-11-04 13:22:28 +08:00
|
|
|
type: String,
|
2025-11-07 13:34:04 +08:00
|
|
|
default: 'http://192.168.0.14:9090/smart-bid/technicalSolutionDatabase/2025/11/03/716d9f3d89434c56bc49296dbbccc226.docx'
|
2025-11-04 13:22:28 +08:00
|
|
|
},
|
2025-11-07 13:34:04 +08:00
|
|
|
documentTitle: {
|
2025-11-04 13:22:28 +08:00
|
|
|
type: String,
|
2025-11-07 13:34:04 +08:00
|
|
|
default: '716d9f3d89434c56bc49296dbbccc226.docx'
|
2025-11-04 13:22:28 +08:00
|
|
|
},
|
2025-11-07 13:34:04 +08:00
|
|
|
documentKey: {
|
2025-11-04 13:22:28 +08:00
|
|
|
type: String,
|
2025-11-07 13:34:04 +08:00
|
|
|
default: '1'
|
2025-11-04 13:22:28 +08:00
|
|
|
},
|
2025-11-07 13:34:04 +08:00
|
|
|
fileName: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: 'technicalSolutionDatabase/2025/11/03/716d9f3d89434c56bc49296dbbccc226.docx'
|
2025-11-04 13:22:28 +08:00
|
|
|
},
|
|
|
|
|
mode: {
|
|
|
|
|
type: String,
|
2025-11-07 13:34:04 +08:00
|
|
|
default: 'view', // 'view' 或 'edit'
|
2025-11-04 13:22:28 +08:00
|
|
|
validator: (value) => ['view', 'edit'].includes(value)
|
|
|
|
|
},
|
2025-11-07 13:34:04 +08:00
|
|
|
type: {
|
2025-11-04 13:22:28 +08:00
|
|
|
type: String,
|
2025-11-07 13:34:04 +08:00
|
|
|
default: 'desktop', // 'desktop', 'mobile', 'embedded'
|
|
|
|
|
validator: (value) => ['desktop', 'mobile', 'embedded'].includes(value)
|
2025-11-04 13:22:28 +08:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2025-11-07 13:34:04 +08:00
|
|
|
|
2025-11-04 13:22:28 +08:00
|
|
|
data() {
|
|
|
|
|
return {
|
2025-11-07 13:34:04 +08:00
|
|
|
docEditor: null,
|
|
|
|
|
onlyOfficeScriptLoaded: false,
|
|
|
|
|
editorConfig: {}
|
2025-11-04 13:22:28 +08:00
|
|
|
};
|
|
|
|
|
},
|
2025-11-07 13:34:04 +08:00
|
|
|
created() {
|
|
|
|
|
this.getConfig();
|
2025-11-04 13:22:28 +08:00
|
|
|
},
|
|
|
|
|
mounted() {
|
2025-11-07 13:34:04 +08:00
|
|
|
this.initOnlyOffice();
|
2025-11-04 13:22:28 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
beforeDestroy() {
|
2025-11-07 13:34:04 +08:00
|
|
|
this.destroyEditor();
|
2025-11-04 13:22:28 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
methods: {
|
2025-11-07 13:34:04 +08:00
|
|
|
// 加载编辑器配置
|
|
|
|
|
async getConfig() {
|
2025-11-04 13:22:28 +08:00
|
|
|
try {
|
2025-11-07 13:34:04 +08:00
|
|
|
const res = await getConfigAPI({
|
|
|
|
|
fileId: this.documentKey,
|
|
|
|
|
fileName: this.fileName,
|
|
|
|
|
mode: this.mode,
|
|
|
|
|
type: this.type
|
|
|
|
|
})
|
|
|
|
|
if (res.code !== 200) {
|
|
|
|
|
throw new Error(res.msg || '获取编辑器配置失败');
|
2025-11-05 09:47:20 +08:00
|
|
|
}
|
2025-11-07 13:34:04 +08:00
|
|
|
if (!res.data) {
|
|
|
|
|
throw new Error('配置数据为空');
|
2025-11-04 13:22:28 +08:00
|
|
|
}
|
2025-11-07 13:34:04 +08:00
|
|
|
|
2025-11-04 13:22:28 +08:00
|
|
|
|
2025-11-07 13:34:04 +08:00
|
|
|
this.editorConfig = res.data;
|
|
|
|
|
this.$set(this.editorConfig, 'events', {
|
|
|
|
|
onDocumentReady: this.onDocumentReady,
|
|
|
|
|
onError: this.onEditorError,
|
|
|
|
|
onAppReady: this.onAppReady
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
console.log('编辑器配置', this.editorConfig);
|
2025-11-05 09:47:20 +08:00
|
|
|
|
2025-11-07 13:34:04 +08:00
|
|
|
}
|
|
|
|
|
catch (error) {
|
|
|
|
|
console.error('获取编辑器配置失败:', error);
|
|
|
|
|
throw new Error('获取编辑器配置失败');
|
|
|
|
|
}
|
|
|
|
|
},
|
2025-11-05 09:47:20 +08:00
|
|
|
|
2025-11-07 13:34:04 +08:00
|
|
|
/**
|
|
|
|
|
* 初始化 OnlyOffice
|
|
|
|
|
*/
|
|
|
|
|
async initOnlyOffice() {
|
|
|
|
|
try {
|
|
|
|
|
// 加载 OnlyOffice 脚本
|
|
|
|
|
await this.loadOnlyOfficeScript();
|
2025-11-05 09:47:20 +08:00
|
|
|
|
2025-11-07 13:34:04 +08:00
|
|
|
// 初始化编辑器
|
|
|
|
|
this.initDocEditor();
|
2025-11-04 13:22:28 +08:00
|
|
|
} catch (error) {
|
2025-11-07 13:34:04 +08:00
|
|
|
console.error('初始化 OnlyOffice 失败:', error);
|
|
|
|
|
this.$emit('error', error);
|
2025-11-04 13:22:28 +08:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 加载 OnlyOffice 脚本
|
|
|
|
|
*/
|
|
|
|
|
loadOnlyOfficeScript() {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
// 如果已经加载,直接返回
|
|
|
|
|
if (window.DocsAPI) {
|
2025-11-07 13:34:04 +08:00
|
|
|
this.onlyOfficeScriptLoaded = true;
|
2025-11-04 13:22:28 +08:00
|
|
|
resolve();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查是否正在加载
|
2025-11-07 13:34:04 +08:00
|
|
|
const existingScript = document.querySelector('script[data-onlyoffice]');
|
2025-11-04 13:22:28 +08:00
|
|
|
if (existingScript) {
|
2025-11-07 13:34:04 +08:00
|
|
|
existingScript.addEventListener('load', () => {
|
|
|
|
|
this.onlyOfficeScriptLoaded = true;
|
|
|
|
|
resolve();
|
2025-11-04 13:22:28 +08:00
|
|
|
});
|
2025-11-07 13:34:04 +08:00
|
|
|
existingScript.addEventListener('error', reject);
|
2025-11-04 13:22:28 +08:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-07 13:34:04 +08:00
|
|
|
// 创建新的脚本元素
|
2025-11-04 13:22:28 +08:00
|
|
|
const script = document.createElement('script');
|
2025-11-07 13:34:04 +08:00
|
|
|
// onlyOfficeUrl 是 OnlyOffice 服务地址
|
|
|
|
|
const onlyOfficeUrl = process.env.VUE_APP_ONLYOFFICE_URL;
|
|
|
|
|
script.src = `${onlyOfficeUrl}/web-apps/apps/api/documents/api.js`;
|
|
|
|
|
script.setAttribute('data-onlyoffice', 'true');
|
2025-11-04 13:22:28 +08:00
|
|
|
|
|
|
|
|
script.onload = () => {
|
2025-11-07 13:34:04 +08:00
|
|
|
this.onlyOfficeScriptLoaded = true;
|
|
|
|
|
// 等待 API 完全初始化
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
if (window.DocsAPI) {
|
|
|
|
|
resolve();
|
|
|
|
|
} else {
|
|
|
|
|
reject(new Error('OnlyOffice API 未正确加载'));
|
|
|
|
|
}
|
|
|
|
|
}, 100);
|
2025-11-04 13:22:28 +08:00
|
|
|
};
|
2025-11-07 13:34:04 +08:00
|
|
|
|
2025-11-04 13:22:28 +08:00
|
|
|
script.onerror = () => {
|
2025-11-07 13:34:04 +08:00
|
|
|
reject(new Error('加载 OnlyOffice 脚本失败'));
|
2025-11-04 13:22:28 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
document.head.appendChild(script);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
2025-11-07 13:34:04 +08:00
|
|
|
* 初始化文档编辑器
|
2025-11-04 13:22:28 +08:00
|
|
|
*/
|
2025-11-07 13:34:04 +08:00
|
|
|
initDocEditor() {
|
|
|
|
|
if (!window.DocsAPI) {
|
|
|
|
|
console.error('DocsAPI 未加载');
|
2025-11-04 13:22:28 +08:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
2025-11-07 13:34:04 +08:00
|
|
|
this.docEditor = new window.DocsAPI.DocEditor("placeholder", this.editorConfig);
|
|
|
|
|
this.$emit('initialized', this.docEditor);
|
2025-11-04 13:22:28 +08:00
|
|
|
} catch (error) {
|
2025-11-07 13:34:04 +08:00
|
|
|
console.error('创建 OnlyOffice 编辑器失败:', error);
|
|
|
|
|
this.$emit('error', error);
|
2025-11-04 13:22:28 +08:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
2025-11-07 13:34:04 +08:00
|
|
|
* 文档准备就绪回调
|
2025-11-04 13:22:28 +08:00
|
|
|
*/
|
2025-11-07 13:34:04 +08:00
|
|
|
onDocumentReady() {
|
|
|
|
|
console.log("文档准备好了");
|
|
|
|
|
this.$emit('document-ready');
|
2025-11-04 13:22:28 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
2025-11-07 13:34:04 +08:00
|
|
|
* 应用准备就绪回调
|
2025-11-04 13:22:28 +08:00
|
|
|
*/
|
2025-11-07 13:34:04 +08:00
|
|
|
onAppReady() {
|
|
|
|
|
console.log("OnlyOffice 应用准备就绪");
|
|
|
|
|
this.$emit('app-ready');
|
2025-11-04 13:22:28 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
2025-11-07 13:34:04 +08:00
|
|
|
* 编辑器错误回调
|
2025-11-04 13:22:28 +08:00
|
|
|
*/
|
2025-11-07 13:34:04 +08:00
|
|
|
onEditorError(error) {
|
|
|
|
|
console.error("OnlyOffice 错误:", error);
|
|
|
|
|
this.$emit('error', error);
|
2025-11-04 13:22:28 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 销毁编辑器
|
|
|
|
|
*/
|
|
|
|
|
destroyEditor() {
|
2025-11-07 13:34:04 +08:00
|
|
|
if (this.docEditor && typeof this.docEditor.destroy === 'function') {
|
|
|
|
|
try {
|
|
|
|
|
this.docEditor.destroy();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.warn('销毁编辑器时出错:', error);
|
2025-11-04 13:22:28 +08:00
|
|
|
}
|
|
|
|
|
}
|
2025-11-07 13:34:04 +08:00
|
|
|
this.docEditor = null;
|
2025-11-04 13:22:28 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
2025-11-07 13:34:04 +08:00
|
|
|
* 重新加载文档
|
2025-11-04 13:22:28 +08:00
|
|
|
*/
|
2025-11-07 13:34:04 +08:00
|
|
|
reloadDocument(newConfig = {}) {
|
|
|
|
|
this.destroyEditor();
|
2025-11-04 13:22:28 +08:00
|
|
|
|
2025-11-07 13:34:04 +08:00
|
|
|
// 可以在这里更新配置
|
|
|
|
|
if (newConfig.documentUrl) {
|
|
|
|
|
this.documentUrl = newConfig.documentUrl;
|
2025-11-04 13:22:28 +08:00
|
|
|
}
|
2025-11-07 13:34:04 +08:00
|
|
|
if (newConfig.documentTitle) {
|
|
|
|
|
this.documentTitle = newConfig.documentTitle;
|
|
|
|
|
}
|
|
|
|
|
if (newConfig.mode) {
|
|
|
|
|
this.mode = newConfig.mode;
|
2025-11-04 13:22:28 +08:00
|
|
|
}
|
|
|
|
|
|
2025-11-07 13:34:04 +08:00
|
|
|
// 等待 DOM 更新后重新初始化
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
this.initDocEditor();
|
|
|
|
|
});
|
2025-11-04 13:22:28 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
|
2025-11-07 13:34:04 +08:00
|
|
|
<style scoped>
|
|
|
|
|
.onlyoffice-container {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 90vh;
|
2025-11-04 13:22:28 +08:00
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-07 13:34:04 +08:00
|
|
|
.editor-placeholder {
|
2025-11-04 13:22:28 +08:00
|
|
|
width: 100%;
|
|
|
|
|
height: 100vh;
|
2025-11-07 13:34:04 +08:00
|
|
|
min-height: 600px;
|
2025-11-04 13:22:28 +08:00
|
|
|
}
|
|
|
|
|
</style>
|