基于vue-onlyoffice实现企业office web在线应用

embedded/2024/9/25 14:20:40/

目录

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-office>onlyoffice文档组件... 6

5.2 基于插件实现文档切换和段落/表格内容选中... 8

6.集成问题分享... 9

6.1如何隐藏插件... 9

6.2避免office>onlyoffice跨域... 10

7.参考链接... 10

1.背景

基于文档审核项目,需要对审核的结果在office word里面进行高亮,并能自动跳转到指定页的对应文字处,基于这样的需求背景下,通过vue进行office>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 对象

用于操作office>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.jsonindex.htmlpluginCode.js.

4.4 插件内嵌使用方式

参考4.3方式自定义插件页面,即需按规范编写相关html、js逻辑,此时插件页面和office>onlyoffice展示页面会绑定在一起,如下图如下:

此时可以直接在js文件操作插件对象Asc

4.5 插件外挂使用方式

参考4.3方式自定义插件页面,此时赋予一个默认的index.html,js相关逻辑不用处理,通过这样处理,隐藏内嵌插件页面的同时,获取office>onlyoffice的插件对象Asc,从而可以独立于office>onlyoffice之外,用vue编写操作页面的逻辑,相对于4.4方式更灵活,并支持多文档切换,如下图所示:

#待分享(即通过外挂右侧操作页面,控制左侧word页面的元素)

由于此时不依赖js文件操作插件对象Asc,此时需要通过iframe机制即window对象,间接获取Asc对象,office>onlyoffice iframe视图如下:

此时获取获取Asc对象方法为

document.getElementsByTagName("iframe")[0]. .contentWindow[0].Asc

5.集成方案介绍

5.1 开发vue-office>onlyoffice文档组件

代码示例1:

<!-- word展示 -->

         <view-word

          v-if="docType === 'word'"

          :editorConfig="viewWordCfg"

            ref="office>onlyofficeEditor"

代码示例2:

<template>

  <div id="officeWord"></div>

</template>

<script>

import loadScript from "@/utils/loadScript";

// import "../js/api.js";

export default {

  name: "office>onlyofficeEditor",

  props: ["editorConfig"],

  mounted() {

    // 文档服务地址,依据环境更改

    const docApiUrl = `/office/web-apps/apps/api/documents/api.js`;

    loadScript(docApiUrl, "office>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避免office>onlyoffice跨域

由于涉及iframe操作和第三方服务,需保证office>onlyoffice服务和前端服务在同一个nginx下,从而避免跨域

7.参考链接

文档相关: https://api.office>onlyoffice.com/docbuilder/basic

插件相关:https://api.office>onlyoffice.com/plugin/basic


http://www.ppmy.cn/embedded/87958.html

相关文章

前端常见场景、JS计算精度丢失问题(Decimal.js 介绍)

目录 一. Decimal.js 介绍 二. 常用方法 1. 创建 Decimal 实例 2.加法 add 或 plus 3.减法 sub 或 minus 4.乘法 times 或 mul 5.除法 div 或 dividedBy 6.取模 7.幂运算 8.平方根 9.保留小数位 toFixed方法(四舍五入) 三.项目应用 前端精度丢失问题通常由以下原因…

替换后端国外身份目录服务,宁盾身份域管接管FileNet助力国产化升级

IBM FileNet 是一款优秀的企业内容管理解决方案&#xff0c;为客户提供了领先的文档管理和流程管理集成环境&#xff0c;被大量企业所采用。FileNet 需要使用企业级的目录服务器&#xff08;LDAP&#xff09;作为其用户管理系统&#xff0c;满足其认证和授权的需求。对于 LDAP …

【React】详解样式控制:从基础到进阶应用的全面指南

文章目录 一、内联样式1. 什么是内联样式&#xff1f;2. 内联样式的定义3. 基本示例4. 动态内联样式 二、CSS模块1. 什么是CSS模块&#xff1f;2. CSS模块的定义3. 基本示例4. 动态应用样式 三、CSS-in-JS1. 什么是CSS-in-JS&#xff1f;2. styled-components的定义3. 基本示例…

数据结构-C语言-排序(4)

代码位置&#xff1a; test-c-2024: 对C语言习题代码的练习 (gitee.com) 一、前言&#xff1a; 1.1-排序定义&#xff1a; 排序就是将一组杂乱无章的数据按照一定的规律&#xff08;升序或降序&#xff09;组织起来。(注&#xff1a;我们这里的排序采用的都为升序) 1.2-排…

typescript 数据类型

// 基础类型规定 let num: number 123; // 规定num必须是数字类型 let str: string "123"; // 规定str必须是字符串类型 let bl: boolean false; // 规定bl必须是布尔值类型 let nl: null null; // 规定nl必须是null类…

Laravel Eloquent资源更新全解析:优雅地处理数据更新

Laravel Eloquent资源更新全解析&#xff1a;优雅地处理数据更新 Laravel的Eloquent ORM不仅是一个对象关系映射工具&#xff0c;它还提供了一种优雅的方式来更新数据库资源。Eloquent的资源更新机制&#xff0c;以其简洁的API和强大的功能&#xff0c;让数据库操作变得简单而…

MySQL练手 --- 1141. 查询近30天活跃用户数

题目链接&#xff1a;1141. 查询近30天活跃用户数 思路&#xff1a; 题目要求&#xff1a;统计截至 2019-07-27&#xff08;包含2019-07-27&#xff09;&#xff0c;近 30 天的每日活跃用户数&#xff08;当天只要有一条活动记录&#xff0c;即为活跃用户&#xff09; 要计算…

gRPC常见面试题目

1. gRPC服务端启动流程 答&#xff1a;定义服务接口->实现服务->创建服务器->启动服务器 定义服务接口&#xff1a;实现proto文件&#xff0c;这个文件服务端和接收端共用&#xff0c;通过protoc命令进行编译生成c代码 实现服务&#xff1a;实现接口方法 创建服务&…