vue2 集成 Onlyoffice
缘起于进行了一次在线 Office 解决方案的调研,对比了 Office365、可道云、WPS Office、PageOffice 等厂商,最终敲定了使用 Onlyoffice,故整理了一份 Onlyoffice 从零开始系列教程,这是第一篇。
一、Onlyoffice 是什么?
Onlyoffice 是一个多端协同的 Office 办公套件,相当于微软的 Office365 全家桶。
二、Onlyoffice 平台功能
功能强大到什么程度呢?我列了一下 Onlyoffice 对我们需求的支持程度:
| 需求 | 支持程度 |
|---|---|
| 终端支持 | 全端支持,包含桌面端、PC 网页端、移动端等 |
| 客户端操作系统 | Windows、Mac、Linux |
| 服务端操作系统 | Linux、Ubuntu、CentOS、Debian、Alibaba Cloud Image 等 Docker 镜像包 |
| 基础功能 | 具备 Word 基础的字体设置、字体大小、加粗、对齐、颜色、背景颜色等功能,同时还有等同于 Office 的各个高级功能 |
| 插件支持 | 支持自定义插件,官方提供了完整的插件开发文档 |
| 二次开发 | 官方开放了 1000+ API,支持根据业务二次开发、功能定制,甚至扩展或增强基础功能 |
| 深度定制 | 支持 |
| 使用体验 | 安装成本低,编辑体验与本地 Word 高度一致 |
| 开发者社区 | 官方维护了一个开发者社区,内容丰富,也比较活跃 |
| 安全与稳定性 | 文档加密保存、传输支持标准的 JWT 加密,多种场景测试未出现崩溃、卡死等情况 |
| 协同 | 支持多人协同编辑、历史记录查看,文档回滚等功能 |
| 分布式部署 | 支持 |
三、服务宗旨
社区版免费,企业版收费,10w 起步。
四、适用场景
预算、私有云、需要二次开发、需要文档协同等。
正文
本文使用docker进行安装,故:
五、安装docker
a、windows安装:Windows10 Docker 安装教程-CSDN博客
b、mac安装:【云原生丶Docker】MacOS系统安装Docker【保姆级教程】_mac安装docker-CSDN博客
六、通过docker安装Onlyoffice
1、使用JWT验证
sudo docker run -i -t -d -p 8701:80 onlyoffice/documentserver
2、不使用JWT验证
sudo docker run -i -t -d -p 8701:80 --restart=always -e JWT_ENABLED=false onlyoffice/documentserver
从7.2版本起,默认使用了JWT功能,安装Onlyoffice时,可以通过不同的命令参数启动服务,默认不使用JWT验证!如果是第 1 次执行这个命令,会先去下载 Onlyoffice,比较慢,约等待 3~10 分钟,网络畅通一点的会快一些。如果是已经安装过则直接进行启动。待其安装完成:

安装完成后:

七、启动服务
1、等上述安装完成后执行命令 ,查看 Onlyoffice 容器 ID:
docker ps

2、执行以下命令进入容器,这里将获取到的 ID 替换为上个步骤你得到的自己的ID!
sudo docker exec -it ID /bin/bash

3、接着执行下面的这两个命令
# 启动所有的内置服务
supervisorctl restart all
# 退出容器
exit
命令输出如下:

4、最后访问 http://IP:8701/welcome 页面(网上其他人说IP 不能是 localhost 或 127.0.0.1,一定要用你自己本地真实 IP 来访问。但是我经过测试完全可以),看到下面的这个效果说明 Onlyoffice 启动成功。
此页面提供了在线文档新增、编辑等功能,你可以点击生成一个文档,后续开发测试功能时会用到。



八、在 Vue 中接入 Onlyoffice
1、子组件准备,在你的项目的合适目录下新建如下两个文件,将下方的代码复制粘贴进去到你对应的文件中。

index.vue页面代码:
<template><div :class="s.view"><div :id="id"></div></div>
</template><script>import loadScript from './loadScript.js';export default {name: 'DocumentEditor',props: {id: {type: String,default: '',},documentServerUrl: {type: String,default: '',},config: {type: Object,default: () => { },},document_fileType: {type: String,default: '',},document_title: {type: String,default: '',},documentType: {type: String,default: '',},editorConfig_lang: {type: String,default: '',},height: {type: String,default: '',},type: {type: String,default: '',},width: {type: String,default: '',},events_onAppReady: {type: Function,default: () => { },},events_onDocumentStateChange: {type: Function,default: () => { },},events_onMetaChange: {type: Function,default: () => { },},events_onDocumentReady: {type: Function,default: () => { },},events_onInfo: {type: Function,default: () => { },},events_onWarning: {type: Function,default: () => { },},events_onError: {type: Function,default: () => { },},events_onRequestSharingSettings: {type: Function,default: () => { },},events_onRequestRename: {type: Function,default: () => { },},events_onMakeActionLink: {type: Function,default: () => { },},events_onRequestInsertImage: {type: Function,default: () => { },},events_onRequestSaveAs: {type: Function,default: () => { },},events_onRequestMailMergeRecipients: {type: Function,default: () => { },},events_onRequestCompareFile: {type: Function,default: () => { },},events_onRequestEditRights: {type: Function,default: () => { },},events_onRequestHistory: {type: Function,default: () => { },},events_onRequestHistoryClose: {type: Function,default: () => { },},events_onRequestHistoryData: {type: Function,default: () => { },},events_onRequestRestore: {type: Function,default: () => { },},},data() {return {};},watch: {config: {handler() {this.onChangeProps();},deep: true,},document_fileType() {this.onChangeProps();},document_title() {this.onChangeProps();},documentType() {this.onChangeProps();},editorConfig_lang() {this.onChangeProps();},height() {this.onChangeProps();},type() {this.onChangeProps();},width() {this.onChangeProps();},},mounted() {let url = this.documentServerUrl;if (!url.endsWith('/')) {url += '/';}const docApiUrl = `${url}web-apps/apps/api/documents/api.js`;loadScript(docApiUrl, 'onlyoffice-api-script').then(() => this.onLoad()).catch((err) => console.error(err));},beforeDestroy() {const id = this.id || '';if (window?.DocEditor?.instances[id]) {window.DocEditor.instances[id].destroyEditor();window.DocEditor.instances[id] = undefined;}},methods: {onLoad() {try {const id = this.id || '';if (!window.DocsAPI) throw new Error('DocsAPI is not defined');if (window?.DocEditor?.instances[id]) {console.log('Skip loading. Instance already exists', id);return;}if (!window?.DocEditor?.instances) {window.DocEditor = { instances: {} };}const initConfig = {document: {fileType: this.document_fileType,title: this.document_title,},documentType: this.documentType,editorConfig: {lang: this.editorConfig_lang,},events: {onAppReady: this.onAppReady,onDocumentStateChange: this.events_onDocumentStateChange,onMetaChange: this.events_onMetaChange,onDocumentReady: this.events_onDocumentReady,onInfo: this.events_onInfo,onWarning: this.events_onWarning,onError: this.events_onError,onRequestSharingSettings: this.events_onRequestSharingSettings,onRequestRename: this.events_onRequestRename,onMakeActionLink: this.events_onMakeActionLink,onRequestInsertImage: this.events_onRequestInsertImage,onRequestSaveAs: this.events_onRequestSaveAs,onRequestMailMergeRecipients: this.events_onRequestMailMergeRecipients,onRequestCompareFile: this.events_onRequestCompareFile,onRequestEditRights: this.events_onRequestEditRights,onRequestHistory: this.events_onRequestHistory,onRequestHistoryClose: this.events_onRequestHistoryClose,onRequestHistoryData: this.events_onRequestHistoryData,onRequestRestore: this.events_onRequestRestore,},height: this.height,type: this.type,width: this.width,...(this.config || {}),};const editor = window.DocsAPI.DocEditor(id, initConfig);window.DocEditor.instances[id] = editor;} catch (err) {console.error(err);this.events_onError(err);}},onAppReady() {const id = this.id || '';this.events_onAppReady(window.DocEditor.instances[id]);},onChangeProps() {const id = this.id || '';if (window?.DocEditor?.instances[id]) {window.DocEditor.instances[id].destroyEditor();window.DocEditor.instances[id] = undefined;console.log('Important props have been changed. Load new Editor.');this.onLoad();}},},};
</script><style lang="scss" module="s">.view {width: 100%;height: 100%;iframe {width: 100%;height: 100%;}}</style>
loadScript.js文件:
const loadScript = async (url, id) =>new Promise((resolve, reject) => {try {if (document.getElementById(id)) {if (window.DocsAPI) return resolve(null);const intervalHandler = setInterval(() => {if (!window.DocsAPI) return;clearInterval(intervalHandler);return resolve(null);}, 500);} else {const script = document.createElement("script");script.setAttribute("type", "text/javascript");script.setAttribute("id", id);script.onload = resolve;script.onerror = reject;script.src = url;script.async = true;document.body.appendChild(script);}} catch (e) {console.error(e);}});export default loadScript;
2、在页面中使用。在合适的位置创建如下页面,将代码复制粘贴进去。

docPreview.vue代码
<template><!-- onlyoffice展示 --><div class='qualityManual-container'><div class='qualityManual-container-office'><vab-only-office id="office-preview" :documentServerUrl='documentServerUrl' :config="config" /></div></div></template>
<script>import vabOnlyOffice from '@/components/docPreview/index.vue'export default {components: { vabOnlyOffice },data() {return {documentServerUrl: "http://192.168.0.15:8701/",config: {document: {fileType: "docx",key: "Khirz6zTPdfd7",title: "Example Document Title.docx",url: "http://192.168.0.15:8701/example/editor?fileName=new.docx"},documentType: "word",editorConfig: {callbackUrl: "https://example.com/url-to-callback.ashx"}}}},methods: {//这里的val是传递的参数loadOnlyOffice(val) {this.option.key = // key 默认置空则不走缓存this.option.title = '' // 该文件名在下载文档时也将用作文件名this.option.url = // 定义存储原始查看或编辑的文档的绝对URLthis.option.fileType = 'docx' // 文件类型this.option.callbackUrl = '' // 回调地址this.show = true // 打开onlyOffice窗口console.log(val, '编辑word默认配置参数')},}}
</script><style rel="stylesheet/scss" lang="scss">.qualityManual-container {padding: 0 !important;width: 100%;height: calc(100vh - 180px);}.qualityManual-container-office {width: 100%;height: calc(100% - 55px);}</style>
下来则是重点功能分析及使用:
data() {return {//本地onlyoffice安装成功后的服务documentServerUrl: "http://192.168.0.15:8701/",config: {document: {fileType: "docx",key: "Khirz6zTPdfd7",title: "Example Document Title.docx",//你要打开的文档绝对路径,这里可以使用7.4页面左侧去生成文档并复制其文档地址进行开发测试!url: "http://192.168.0.15:8701/example/editor?fileName=new.docx"},documentType: "word",editorConfig: {callbackUrl: "https://example.com/url-to-callback.ashx"}}}
},
运行项目查看!祝你成功。
相关文章:
vue2 集成 Onlyoffice
缘起于进行了一次在线 Office 解决方案的调研,对比了 Office365、可道云、WPS Office、PageOffice 等厂商,最终敲定了使用 Onlyoffice,故整理了一份 Onlyoffice 从零开始系列教程,这是第一篇。 一、Onlyoffice 是什么?…...
天锐绿盾透明加密、半透明加密、智能加密这三种不同加密模式的区别和适用场景——@德人合科技-公司内部核心文件数据、资料防止外泄系统
由于企事业单位海量的内部数据存储情况复杂,且不同公司、不同部门对于文件加密的需求各不相同,单一的加密系统无法满足多样化的加密需求。天锐绿盾企业加密系统提供多种不同的加密模式,包括透明加密、半透明加密和智能加密,用户可…...
六、DHCP实验
拓扑图: DHCP协议,给定一个ip范围使其自动给终端分配IP,提高了IP分配的效率 首先对PC设备选择DHCP分配ip 首先先对路由器的下端配置网关的ip 创建地址池,通过globle的方式实现DHCP ip pool 地址池名称 之后设置地址池的网关地址…...
N沟道场效应管 FDA69N25深度图解 工作原理应用
深力科推荐一款 FDA69N25是高压 MOSFET产品,基于平面条形和 DMOS 技术。 该 MOSFET 产品专用于降低通态电阻,并提供更好的开关性能和更高的雪崩能量强度。 该器件系列适用于开关电源转换器应用,如功率因数校正(PFC)、…...
Python爬虫入门教程
文章目录: 一:Python基础 二:爬虫须知 1.流程 2.遵守规则 三:HTTP请求和响应 1.相关定义 2.HTTP请求响应 2.1 完整的HTTP请求 2.2 完整的HTTP响应 3.Requests库 四:HTML 1.HTML网页结构 2.常用标 参考&…...
使用正则前瞻检查密码强度
使用正则前瞻检查密码强度 题目要求 要求密码必须包含大小写字母,并且至少包含 $,_. 中的一个特殊字符。 在这道题中,我们可以使用正则表达式的前瞻运算来实现。 const reg /^(?.*\d)(?.*[a-z])(?.*[A-Z])(?.*[$,_.])[\da-zA-Z$,_.]{6,12}/;con…...
react+ts手写cron表达式转换组件
前言 最近在写的一个分布式调度系统,后端同学需要让我传入cron表达式,给调度接口传参。我去了学习了解了cron表达式的用法,发现有3个通用的表达式刚好符合我们的需求: 需求 每天 xx 的时间: 0 11 20 * * ? 上面是…...
民安智库(第三方市民健康素养调研)居民健康素养调查的重要性及实施步骤
一、背景和意义 健康素养是衡量一个社区或国家居民对健康知识的理解,以及他们如何将这些知识应用于日常生活中的能力的重要指标。它不仅包括了基本的医学知识,如疾病预防和治疗,也包括了生活方式的改善,如合理饮食和适当运动。因…...
Linux | vim的入门手册
目录 前言 一、什么是vim 二、vim编辑器的模式 1、插入模式 (1)用vim打开文件 (2)进入插入模式 2、默认模式 (1)光标移动 (2)复制、粘贴与剪切操作 (3&#x…...
B053 项目部署
目录 Linux简介虚拟机软件安装安装centos步骤备份系统网络设置 远程访问Linux步骤永久关闭CentOS防火墙 linux命令linux文件系统linux常用命令目录相关命令文件相关命令 安装JDK先卸载自带的JDK安装JDK复制压缩包到linux解压配置环境变量 安装MySql清理旧文件安装mysqlMysql编码…...
视觉Slam面试题(不定时更新)
文章目录 0 引言1 单目、双目、深度相机和RGBD相机的区别2 特征点法与直接法的优缺点3 等距变换、相似变换、仿射变换、射影变换的区别4 单应矩阵、本质矩阵和基础矩阵的区别5 Slam中为什么用李群李代数6 解释Slam中的绑架问题7 ORB、SIFT和SURF特征点检测算法的区别8 什么是对…...
从入门到进阶 之 ElasticSearch 节点配置 集群篇
🌹 以上分享 ElasticSearch 安装部署,如有问题请指教写。🌹🌹 如你对技术也感兴趣,欢迎交流。🌹🌹🌹 如有需要,请👍点赞💖收藏🐱&a…...
UE4中无法保存项目问题
系列文章目录 文章目录 系列文章目录前言一、解决方法 前言 取消:停止保存所有资产并返回编辑器。 重试:尝试再次保存资产。 继续:仅跳过保存该资产。 当我点击继续时,关闭项目,然后重新打开项目,发现之前…...
解剖—顺序表相关OJ练习题
目录 一、删除有序数组中的重复项,返回出现一次元素的个数。 二、原地移除数组中所有数值等于val的元素 三、合并两个有序数组 四、旋转数组 五、数组形式的整数加法 一、删除有序数组中的重复项,返回出现一次元素的个数。 26. 删除有序数组中的重…...
NAT网关在阿里云的应用
NAT网关(Network Address Translation Gateway)是一种网络地址转换服务,提供NAT代理(SNAT和DNAT)能力。NAT是用于在本地网络中使用私有地址,在连接互联网时转而使用全局 IP 地址的技术。NAT实际上是为解决I…...
操作系统体系结构和OS
1.冯诺依曼计算机体系 关于冯诺伊曼系统,在这里我只是简单讲一讲,更加详细的内容可以看我的计算机组成系列。 常见的笔记本、台式机,不常见的服务器、工作站,大部分都遵守“冯诺依曼体系”,因此该计算机体系就是现代…...
Flutter ☞ 常量
常量 只能被定义一次,并且不可修改的值叫做常量。 在 Flutter 中有两种常量修饰方法 finalconst 相同点 类型声明可以省略 final String a 123; final a 123;const String a 123; const a 123;初始化后不能再赋值 final a 123; a abc; // 错误const a …...
C++ 配置VSCode开发环境
C配置VSCode开发环境 简介 Visual Studio Code (VSCode) 是一款开源的轻量级代码编辑器。它支持许多编程语言,包括C。本文档将详细介绍如何在Windows环境下配置VSCode的C开发环境。 安装步骤 1. 安装Visual Studio Code 首先,你需要下载并安装Visua…...
Arduino_STM32整理贴
Arduion-STM32 stm32duino 让stm32 在arduino中使用 源代码:https://github.com/stm32duino/Arduino_Core_STM32 busybox文件位置 stm32duino 下有个stm32tool 项目,内含有busybox.exe 使用usb转TTL烧写 使用 PA9 PA10 端口 PA9接 RX ,PA10接 TX …...
MoeCTF 2023 Web+Jail wp
----------签到---------- hello CTFer 给了一个URL,是赛博厨子解码base64的flag,flag直接给了。 远程端口转发: 这次比赛估计好多大师傅都没参加,题目环境是在本机内网上的(比如localhost:52005)导致请…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
