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)导致请…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...

AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...

uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...