onlyoffice集成
This commit is contained in:
parent
7d38fc745b
commit
7a5f1f359f
|
|
@ -1,6 +1,21 @@
|
|||
<template>
|
||||
<div class="onlyoffice-container">
|
||||
<div id="placeholder" class="editor-placeholder"></div>
|
||||
<!-- 加载状态 -->
|
||||
<div v-if="loading" class="loading-state">
|
||||
<div class="loading-spinner"></div>
|
||||
<p>正在加载文档...</p>
|
||||
</div>
|
||||
|
||||
<!-- 错误状态 -->
|
||||
<div v-if="error" class="error-state">
|
||||
<div class="error-icon">❌</div>
|
||||
<h3>加载失败</h3>
|
||||
<p>{{ error }}</p>
|
||||
<button @click="retry" class="retry-btn">重试</button>
|
||||
</div>
|
||||
|
||||
<!-- 编辑器容器(始终存在,通过样式控制显示) -->
|
||||
<div v-show="!loading && !error" id="placeholder" class="editor-placeholder"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -43,14 +58,26 @@ export default {
|
|||
return {
|
||||
docEditor: null,
|
||||
onlyOfficeScriptLoaded: false,
|
||||
editorConfig: {}
|
||||
editorConfig: null,
|
||||
configReady: false,
|
||||
loading: false,
|
||||
error: null
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getConfig();
|
||||
},
|
||||
mounted() {
|
||||
this.initOnlyOffice();
|
||||
async mounted() {
|
||||
try {
|
||||
this.loading = true;
|
||||
this.error = null;
|
||||
// 先加载配置
|
||||
await this.getConfig();
|
||||
// 再初始化 OnlyOffice(成功后会自动设置 loading = false)
|
||||
await this.initOnlyOffice();
|
||||
} catch (error) {
|
||||
console.error('初始化失败:', error);
|
||||
this.loading = false;
|
||||
this.error = error.message || '初始化失败';
|
||||
this.$emit('error', error);
|
||||
}
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
|
|
@ -61,33 +88,51 @@ export default {
|
|||
// 加载编辑器配置
|
||||
async getConfig() {
|
||||
try {
|
||||
console.log('开始获取编辑器配置...', {
|
||||
fileId: this.documentKey,
|
||||
fileName: this.fileName,
|
||||
mode: this.mode,
|
||||
type: this.type
|
||||
});
|
||||
|
||||
const res = await getConfigAPI({
|
||||
fileId: this.documentKey,
|
||||
fileName: this.fileName,
|
||||
mode: this.mode,
|
||||
type: this.type
|
||||
})
|
||||
});
|
||||
|
||||
console.log('获取配置响应:', res);
|
||||
|
||||
if (res.code !== 200) {
|
||||
throw new Error(res.msg || '获取编辑器配置失败');
|
||||
}
|
||||
if (!res.data) {
|
||||
throw new Error('配置数据为空');
|
||||
}
|
||||
|
||||
|
||||
this.editorConfig = res.data;
|
||||
this.$set(this.editorConfig, 'events', {
|
||||
onDocumentReady: this.onDocumentReady,
|
||||
onError: this.onEditorError,
|
||||
onAppReady: this.onAppReady
|
||||
});
|
||||
|
||||
console.log('编辑器配置', this.editorConfig);
|
||||
// 验证必要的配置字段
|
||||
if (!res.data.document || !res.data.document.url) {
|
||||
throw new Error('配置中缺少文档URL');
|
||||
}
|
||||
|
||||
}
|
||||
catch (error) {
|
||||
// 设置配置,添加事件回调
|
||||
this.editorConfig = {
|
||||
...res.data,
|
||||
events: {
|
||||
onDocumentReady: () => this.onDocumentReady(),
|
||||
onError: (error) => this.onEditorError(error),
|
||||
onAppReady: () => this.onAppReady()
|
||||
}
|
||||
};
|
||||
|
||||
this.configReady = true;
|
||||
console.log('编辑器配置准备完成:', this.editorConfig);
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取编辑器配置失败:', error);
|
||||
throw new Error('获取编辑器配置失败');
|
||||
this.error = error.message || '获取编辑器配置失败';
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -96,14 +141,26 @@ export default {
|
|||
*/
|
||||
async initOnlyOffice() {
|
||||
try {
|
||||
// 加载 OnlyOffice 脚本
|
||||
await this.loadOnlyOfficeScript();
|
||||
// 确保配置已准备好
|
||||
if (!this.configReady || !this.editorConfig) {
|
||||
throw new Error('编辑器配置未准备好,请先加载配置');
|
||||
}
|
||||
|
||||
// 加载 OnlyOffice 脚本
|
||||
console.log('开始加载 OnlyOffice 脚本...');
|
||||
await this.loadOnlyOfficeScript();
|
||||
console.log('OnlyOffice 脚本加载完成');
|
||||
|
||||
// 等待 DOM 准备好
|
||||
await this.$nextTick();
|
||||
|
||||
// 初始化编辑器
|
||||
this.initDocEditor();
|
||||
await this.initDocEditor();
|
||||
} catch (error) {
|
||||
console.error('初始化 OnlyOffice 失败:', error);
|
||||
this.error = error.message || '初始化 OnlyOffice 失败';
|
||||
this.$emit('error', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -133,8 +190,16 @@ export default {
|
|||
// 创建新的脚本元素
|
||||
const script = document.createElement('script');
|
||||
// onlyOfficeUrl 是 OnlyOffice 服务地址
|
||||
const onlyOfficeUrl = process.env.VUE_APP_ONLYOFFICE_URL;
|
||||
script.src = `${onlyOfficeUrl}/web-apps/apps/api/documents/api.js`;
|
||||
const onlyOfficeUrl = process.env.VUE_APP_ONLYOFFICE_URL || process.env.VUE_APP_BASE_API || '';
|
||||
|
||||
if (!onlyOfficeUrl) {
|
||||
reject(new Error('OnlyOffice 服务地址未配置,请检查环境变量 VUE_APP_ONLYOFFICE_URL'));
|
||||
return;
|
||||
}
|
||||
|
||||
const scriptUrl = `${onlyOfficeUrl}/web-apps/apps/api/documents/api.js`;
|
||||
console.log('加载 OnlyOffice 脚本,URL:', scriptUrl);
|
||||
script.src = scriptUrl;
|
||||
script.setAttribute('data-onlyoffice', 'true');
|
||||
|
||||
script.onload = () => {
|
||||
|
|
@ -160,18 +225,81 @@ export default {
|
|||
/**
|
||||
* 初始化文档编辑器
|
||||
*/
|
||||
initDocEditor() {
|
||||
if (!window.DocsAPI) {
|
||||
console.error('DocsAPI 未加载');
|
||||
return;
|
||||
async initDocEditor() {
|
||||
// 验证 DocsAPI
|
||||
if (!window.DocsAPI || !window.DocsAPI.DocEditor) {
|
||||
throw new Error('OnlyOffice DocsAPI 未正确加载,请检查脚本是否已加载');
|
||||
}
|
||||
|
||||
// 验证配置
|
||||
if (!this.editorConfig) {
|
||||
throw new Error('编辑器配置不存在');
|
||||
}
|
||||
|
||||
// 验证容器元素(容器可能被 v-show 隐藏,但 DOM 中应该存在)
|
||||
await this.$nextTick();
|
||||
let container = document.getElementById('placeholder');
|
||||
|
||||
// 如果容器不存在,等待一下再试
|
||||
if (!container) {
|
||||
console.warn('容器元素不存在,等待 DOM 渲染...');
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
await this.$nextTick();
|
||||
container = document.getElementById('placeholder');
|
||||
}
|
||||
|
||||
if (!container) {
|
||||
throw new Error('找不到编辑器容器元素 #placeholder,请确保容器已正确渲染');
|
||||
}
|
||||
|
||||
// 即使容器被 v-show 隐藏,也要强制显示以便创建编辑器
|
||||
container.style.display = 'block';
|
||||
container.style.visibility = 'visible';
|
||||
container.style.width = '100%';
|
||||
container.style.height = '100%';
|
||||
|
||||
console.log('容器元素:', container);
|
||||
console.log('容器尺寸:', {
|
||||
width: container.offsetWidth,
|
||||
height: container.offsetHeight,
|
||||
rect: container.getBoundingClientRect()
|
||||
});
|
||||
|
||||
// 确保容器有尺寸
|
||||
if (container.offsetWidth === 0 || container.offsetHeight === 0) {
|
||||
console.warn('容器尺寸为0,等待尺寸调整...');
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
|
||||
if (container.offsetWidth === 0 || container.offsetHeight === 0) {
|
||||
console.warn('容器尺寸仍为0,但继续尝试创建编辑器');
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
this.docEditor = new window.DocsAPI.DocEditor("placeholder", this.editorConfig);
|
||||
console.log('创建 OnlyOffice 编辑器,配置:', this.editorConfig);
|
||||
|
||||
// 清空容器
|
||||
container.innerHTML = '';
|
||||
|
||||
// 创建编辑器实例
|
||||
this.docEditor = new window.DocsAPI.DocEditor('placeholder', this.editorConfig);
|
||||
|
||||
console.log('编辑器实例创建成功:', this.docEditor);
|
||||
|
||||
// 编辑器创建成功,隐藏加载状态
|
||||
this.loading = false;
|
||||
this.$emit('initialized', this.docEditor);
|
||||
} catch (error) {
|
||||
console.error('创建 OnlyOffice 编辑器失败:', error);
|
||||
console.error('错误详情:', {
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
config: this.editorConfig
|
||||
});
|
||||
this.loading = false;
|
||||
this.error = error.message || '创建编辑器失败';
|
||||
this.$emit('error', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -216,8 +344,10 @@ export default {
|
|||
/**
|
||||
* 重新加载文档
|
||||
*/
|
||||
reloadDocument(newConfig = {}) {
|
||||
async reloadDocument(newConfig = {}) {
|
||||
this.destroyEditor();
|
||||
this.configReady = false;
|
||||
this.error = null;
|
||||
|
||||
// 可以在这里更新配置
|
||||
if (newConfig.documentUrl) {
|
||||
|
|
@ -230,10 +360,34 @@ export default {
|
|||
this.mode = newConfig.mode;
|
||||
}
|
||||
|
||||
// 等待 DOM 更新后重新初始化
|
||||
this.$nextTick(() => {
|
||||
this.initDocEditor();
|
||||
});
|
||||
// 重新加载配置并初始化
|
||||
try {
|
||||
this.loading = true;
|
||||
await this.getConfig();
|
||||
await this.initDocEditor();
|
||||
} catch (error) {
|
||||
console.error('重新加载文档失败:', error);
|
||||
this.error = error.message || '重新加载失败';
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 重试
|
||||
*/
|
||||
async retry() {
|
||||
this.error = null;
|
||||
this.loading = true;
|
||||
try {
|
||||
await this.getConfig();
|
||||
await this.initOnlyOffice();
|
||||
} catch (error) {
|
||||
console.error('重试失败:', error);
|
||||
this.error = error.message || '重试失败';
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -245,11 +399,79 @@ export default {
|
|||
height: 90vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.editor-placeholder {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
height: 100%;
|
||||
min-height: 600px;
|
||||
}
|
||||
|
||||
.loading-state,
|
||||
.error-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
min-height: 400px;
|
||||
text-align: center;
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 4px solid #f3f3f3;
|
||||
border-top: 4px solid #3498db;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.error-icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.error-state h3 {
|
||||
margin: 0 0 8px 0;
|
||||
color: #e74c3c;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.error-state p {
|
||||
margin: 0 0 16px 0;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.retry-btn {
|
||||
background: #3498db;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.retry-btn:hover {
|
||||
background: #2980b9;
|
||||
}
|
||||
|
||||
/* 确保 OnlyOffice iframe 正确显示 */
|
||||
.editor-placeholder ::v-deep iframe {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
border: none;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue