目录
1.背景... 1
2.Onlyoffice介绍... 2
3.Onlyoffice核心api介绍... 2
3.1 ApiDocument 2
3.2 ApiParagraph. 2
3.3 ApiTable. 2
3.4. ApiRange. 3
4.Onlyoffice插件介绍... 3
4.1 插件定义... 3
4.2 插件对象... 3
4.3 插件结构... 4
4.4 插件内嵌使用方式... 4
4.5 插件外挂使用方式... 5
5.集成方案介绍... 6
5.1 开发vue-onlyoffice文档组件... 6
5.2 基于插件实现文档切换和段落/表格内容选中... 8
6.集成问题分享... 9
6.1如何隐藏插件... 9
6.2避免onlyoffice跨域... 10
7.参考链接... 10
1.背景
基于文档审核项目,需要对审核的结果在office word里面进行高亮,并能自动跳转到指定页的对应文字处,基于这样的需求背景下,通过vue进行onlyoffice文档方案集成。
2.Onlyoffice介绍
3.Onlyoffice核心api介绍
3.1 ApiDocument
英文名称 | 中文说明 |
AddComment | 添加批注 |
AddElement | 添加文档元素(注:元素常见类型Paragraph\Table) |
GetAllParagraphs | 获取所有段落 |
GetAllTables | 获取所有表格 |
GetElement | 获取文档元素 |
GetCommentById | 获取批注 |
GetPageCount | 获取页数 |
GetRange | 根据字坐标获取对应文档部分 |
Search | 根据文字内容获取对应文档部分 |
3.2 ApiParagraph
英文名称 | 中文说明 |
AddText | 添加段落文本 |
AddElement | 添加段落要素 |
AddPageBreak | 添加分页符 |
GetElement | 获取段落元素 |
GetText | 获取段落文本 |
GetRange | 根据字坐标获取对应段落部分 |
Search | 根据文字内容获取对应段落部分 |
Select | 段落文本选中 |
SetBold | 设置段落文本字体粗细 |
3.3 ApiTable
英文名称 | 中文说明 |
AddColumn | 添加表格列 |
AddRow | 添加表格行 |
AddElement | 添加表格元素 |
GetElement | 获取段落元素 |
GetText | 获取段落文本 |
GetRange | 根据字坐标获取对应表格部分 |
Search | 根据文字内容获取对应表格部分 |
GetColumn | 获取表格列 |
GetRow | 获取表格行 |
Select | 选中指定单元格 |
3.4. ApiRange
英文名称 | 中文说明 |
AddComment | 指定位置添加批注 |
AddText | 指定位置添加文本 |
GetParagraph | 获取指定位置段落 |
GetRange | 根据字坐标获取对应部分 |
GetText | 获取指定位置文本 |
GetRange | 根据字坐标获取对应表格部分 |
Select | 选中指定位置内容 |
SetHighlight | 高亮指定位置内容 |
SetPosition | 截取指定位置内容 |
4.Onlyoffice插件介绍
4.1 插件定义
ONLYOFFICE offer support for plugins allowing developers to add specific features to the editors that are not directly related to the OOXML format.
4.2 插件对象
Asc 对象
用于操作onlyoffice文档的对象
Asc.plugin对象
任何插件都有window.Asc.plugin对象,该对象又具有几种方法,用于与ONLYOFFICE文档、电子表格和演示文稿编辑器进行交互
方法名称 | 方法作用 |
callCommand | 定义用于将数据发送回编辑器的方法。它允许插件发送结构化数据,这些数据可以插入到生成的文档文件中(格式化的段落、表格、文本部分和单独的单词等) |
executeMethod | 定义使用插件执行某些编辑器方法的方法 |
Asc.scope对象
用于将任何附加数据(对象、参数、变量等)传递给 window.Asc.plugin.callCommand 方法,该方法在其独立的上下文中执行
4.3 插件结构
Develop a plugin. Follow the plugin structure described here. The plugin folder must contain three files required for the plugin to work: config.json, index.html, pluginCode.js.
4.4 插件内嵌使用方式
参考4.3方式自定义插件页面,即需按规范编写相关html、js逻辑,此时插件页面和onlyoffice展示页面会绑定在一起,如下图如下:
此时可以直接在js文件操作插件对象Asc
4.5 插件外挂使用方式
参考4.3方式自定义插件页面,此时赋予一个默认的index.html,js相关逻辑不用处理,通过这样处理,隐藏内嵌插件页面的同时,获取onlyoffice的插件对象Asc,从而可以独立于onlyoffice之外,用vue编写操作页面的逻辑,相对于4.4方式更灵活,并支持多文档切换,如下图所示:
#待分享(即通过外挂右侧操作页面,控制左侧word页面的元素)
由于此时不依赖js文件操作插件对象Asc,此时需要通过iframe机制即window对象,间接获取Asc对象,onlyoffice iframe视图如下:
此时获取获取Asc对象方法为
document.getElementsByTagName("iframe")[0]. .contentWindow[0].Asc
5.集成方案介绍
5.1 开发vue-onlyoffice文档组件
代码示例1:
<!-- word展示 --> <view-word v-if="docType === 'word'" :editorConfig="viewWordCfg" ref="onlyofficeEditor" |
代码示例2:
<template> <div id="officeWord"></div> </template> <script> import loadScript from "@/utils/loadScript"; // import "../js/api.js"; export default { name: "onlyofficeEditor", props: ["editorConfig"], mounted() { // 文档服务地址,依据环境更改 const docApiUrl = `/office/web-apps/apps/api/documents/api.js`; loadScript(docApiUrl, "onlyoffice-api-script") .then(() => this.onLoad()) .catch(() => { this.onError(-2); }); // Promise.all([this.onLoad()]).catch(() => { // this.onError(-2); // }); // this.onReady(); }, beforeDestroy() { const id = "officeWord"; if (window?.DocEditor?.instances[id]) { window.DocEditor.instances[id].destroyEditor(); window.DocEditor.instances[id] = undefined; } }, methods: { onLoad() { try { const id = "officeWord"; if (!window.DocsAPI) this.onError(-3); if (window?.DocEditor?.instances[id]) { console.log("Skip loading. Instance already exists", id); return; } if (!window?.DocEditor?.instances) { window.DocEditor = { instances: {} }; } const editor = window.DocsAPI.DocEditor( id, Object.assign( { events: { onAppReady: this.onAppReady, }, }, this.editorConfig ) ); window.DocEditor.instances[id] = editor; } catch (err) { console.error(err); this.onError(-1); } }, onAppReady() { const id = "officeWord"; window.DocEditor.instances[id]; }, onError(errorCode) { let message; switch (errorCode) { case -2: message = "Error load DocsAPI from " + this.documentServerUrl; break; case -3: message = "DocsAPI is not defined"; break; default: message = "Unknown error loading component"; errorCode = -1; } if (typeof this.onLoadComponentError == "undefined") { console.error(message); } else { this.onLoadComponentError(errorCode, message); } }, }, }; </script> <style scoped></style> |
5.2 基于插件实现文档切换和段落/表格内容选中
const oIframe = document.getElementsByTagName("iframe")[0]; if (!oIframe) { return; } let Asc = oIframe.contentWindow[0].Asc; const { tableId, startIndex, endIndex } = ele; Asc.scope.start = startIndex; Asc.scope.end = endIndex; Asc.scope.tableId = tableId; sessionStorage.setItem("ascScope-word", JSON.stringify(Asc.scope)); console.log(Asc); // this.viewWordCfg Asc.plugin.callCommand( function () { // eslint-disable-next-line no-undef var oDocument = Api.GetDocument(); var ascScope = JSON.parse(sessionStorage.getItem("ascScope-word")); var start_index = ascScope ? Number(ascScope.start) : 0; var end_index = ascScope ? Number(ascScope.end) : 0; var oTableArr = []; for (var i = 0; i < oDocument.GetElementsCount(); i++) { var oElement = oDocument.GetElement(i); var sClassType = oElement.GetClassType(); if (sClassType == "table") { oTableArr.push(oElement); } } // 区分表格还是文字 进行提示 // if (ascScope && ascScope.tableId !== null) { // 表格 var oTable = oTableArr[0]; //表格是按字数来的,不包括空格 var oTableRange = oTable.GetRange(start_index, end_index); oTableRange.SetHighlight(20, 37, 220); oTableRange.Select(); } else { // 文字 var oRange = oDocument.GetRange(start_index, end_index); oRange.SetHighlight(20, 37, 220); oRange.Select(); } }, false, true ); |
6.集成问题分享
6.1如何隐藏插件
需修改插件目录下的config.json文件,即配置isVisual 为false 实现插件隐藏
6.2避免onlyoffice跨域
由于涉及iframe操作和第三方服务,需保证onlyoffice服务和前端服务在同一个nginx下,从而避免跨域
7.参考链接
文档相关: https://api.onlyoffice.com/docbuilder/basic
插件相关:https://api.onlyoffice.com/plugin/basic