vue2项目对接wps实现在线编辑、预览文档

对接文档:WebOffice 知识库

项目场景:

本项目需要实现在线编辑、预览文档功能,包括对文档进行修订、留痕以及进行套红操作等。


实现步骤:

JSSDK 提供了非模块化以及 AMDCommonJSES6 等多种模块化规范的包,项目中使用非模块化引入方式。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>WPS WebOffice</title>
</head>
<body>
  <script src="./web-office-sdk.umd.js"></script>
  <script>
    console.log('引入后可以开始使用 JSSDK 了~');
    console.log(WebOfficeSDK);
  </script>
</body>
</html>

关于引用的其他方式,请参考:引用 

  • 初始化

引用 JSSDK 之后,就可以通过WebOfficeSDK.config方法在指定的挂载节点下创建一个文档应用。

创建wpsUtils.js文件,根据项目需求配置wps在线编辑页面。

 wpsUtils.js

// 新建编辑文档
export const editWpsDoc = function (fileInfo, controlBtns) {
  this.fileInfo = fileInfo
  this.controlBtns = controlBtns
  this.editUrl = ''
  this.wpsDocObject = {}
  this.wpsAppObject = {}
}
// 创建在线编辑对象
editWpsDoc.prototype.builder = async function () {
  const editRes = await getWPSEditUrl(this.fileInfo)
  if (editRes.code == 200) {
    this.editUrl = editRes.data.link
    this.wpsDocObject = WebOfficeSDK.config({
      url: this.editUrl, // 该地址需要对接方服务端提供,形如 https://wwo.wps.cn/office/p/xxx
      mount: document.getElementById('wpsIframeDoc'),
    })

    // 需要等待 jssdk ready 之后再调用高级 API
    await this.wpsDocObject.ready()
    this.wpsAppObject = await this.wpsDocObject.Application
 
    return this.wpsDocObject
  }else{
    return null
  }
}

配置如下:

  1. 是否接受修订由修订参数控制

在页面定制-可定制列表模块,列出了页面上相关组件的CommandBarId,通过CommandBarId可以配置相关组件的显示隐藏或是否禁用。只支持列表里的CommandBarId。

I. 由于wps不支持对下拉列表的选项设置隐藏或禁用 ,为了满足需求,只能将修订设置按钮隐藏,再单独对其下拉列表的内容进行设置。

// 配置审阅-修订设置选项

editWpsDoc.prototype.RevisionSettingDisplay = async function (flag) {
  // 隐藏修订设置选项  flag值为 false
  const RevisionSettingChanges = await this.wpsAppObject.CommandBars('RevisionSetting');
  RevisionSettingChanges.Visible  = flag
}

II. 隐藏修订记录框右上角的接受/拒绝修订图标

// 显示/隐藏 接受修订/拒绝修订的按钮
editWpsDoc.prototype.SwitchRevisionBtnDisplay = async function (flag) {
  // 获取修订对象
  const revisions = await this.wpsAppObject.ActiveDocument.Revisions;
  // 隐藏接受/拒绝修订的按钮 false-隐藏, true-显示
  await revisions.SwitchRevisionBtn(flag);
}

以上两个配置,禁止了用户选择拒绝修订的动作,在开启修订的状态下,默认接受所有修订。


        2. 启用或禁用修订按钮

// 配置审阅-修订选项
editWpsDoc.prototype.ReviewTrackEnabled = async function (flag) {
  // 页面定制对象:启用 true/禁用 false 审阅-修订按钮
  const ReviewTrackChanges = await this.wpsAppObject.CommandBars('ReviewTrackChanges');
  
  ReviewTrackChanges.Enabled  = flag
}

        3.是否默认开启修订模式,默认显示修订状态为最终状态,不带修订标记,不显示修订记录框

// 是否开启修订
editWpsDoc.prototype.RevisionsAuthority = async function (flag) {
  // 获取修订对象
  const revisions = await this.wpsAppObject.ActiveDocument.Revisions;
  // 获取节对象
  const View = await this.wpsAppObject.ActiveDocument.ActiveWindow.View;

  // flag值为true时,将当前文档的编辑状态切换成修订模式
  this.wpsAppObject.ActiveDocument.TrackRevisions = flag
  // 设置修订状态 0-最终状态  1-原始状态
  View.RevisionsFilter.View = 0;
  // 设置修订状态 true-显示标记的最终状态  false-最终状态
  View.ShowRevisionsAndComments = false;         // 默认显示最终状态
  // 隐藏修订框
  revisions.ShowRevisionsFrame = false;
}

        4.查看文档的最终状态,不带显示标记(清样稿)

在wps在线编辑的默认页面,要查看文档的不同状态时,可以在审阅-修订设置-修订状态模块进行查看,但上面的配置进行了隐藏,因此需要自定义按钮,实现查看文档的最终状态。

// 自定义清样稿按钮
editWpsDoc.prototype.clearMark = async function () {
  // 在【审阅】栏新增定制元素  清样稿
  const View = await this.wpsAppObject.ActiveDocument.ActiveWindow.View;
  const TabReviewWordControls = await this.wpsAppObject.CommandBars('ReviewTab').Controls;
  const revisionControl = await TabReviewWordControls.Add(1);
  revisionControl.Caption = '清样稿';
  revisionControl.Picture = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAYAAACOEfKtAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIzLTA3LTIwVDE3OjUxOjQ1KzA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMy0wNy0yMFQxNzo1Mjo1NSswODowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMy0wNy0yMFQxNzo1Mjo1NSswODowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDplOWI1MDJhOC03MzhmLTE5NDAtYjJhOS0zNTY0MTIyMGE3NTciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ZTliNTAyYTgtNzM4Zi0xOTQwLWIyYTktMzU2NDEyMjBhNzU3IiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6ZTliNTAyYTgtNzM4Zi0xOTQwLWIyYTktMzU2NDEyMjBhNzU3Ij4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDplOWI1MDJhOC03MzhmLTE5NDAtYjJhOS0zNTY0MTIyMGE3NTciIHN0RXZ0OndoZW49IjIwMjMtMDctMjBUMTc6NTE6NDUrMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE4IChXaW5kb3dzKSIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5dMi+lAAACGElEQVR42u3dv0scQRjG8QEhCArR2s6/QsE/4v2Otf+BnW0wEEiTLp1lhIiniGBjo62YIoWlfYKVJCYxTQKeRVYQufhjZ+Zmz/cpHq6eDw97u+/OzYV+vx8Gxcxu8gq4BH4DFx3JL+A7cAosxxhDqQDBzML/nMI9gAvAJtDvemKMb7oI+AG4GgXABnG1U4DAyajglWyiK8ASTXQHmLuJpQCPgXVgZ4hZB74Ou4mlABeBUCE7w26ia8AcTXQPmNpEASY20QvgeYzxqEQTvQB+iTHOAIe5m+gF8AJ40Sz6IGcTPQG+bBY9AXzK1URXgMDNwidzNdErYLYmugO8g5jcRO+AyU10CZizia4Bc1wT3QPewXxyEwU4oJHAx8c20QvgH2AP6D0wlN0F1oD9x05xNI1JzwowLcD2uQTeCzAtn58L4NtKgCedAby156ZNZoAz14CpiMBs8y36F/iZabPSt2bzlAvAAIw1931TzWdqArA0MoApiAWvr4sC9ATYFlGAAsx7HyhAAdZ/EhGgAOs/CwtQgPWnMQIUYP15oAAFWH8iLUAB1n8nIsBCiAJMhBRgIqQAuxsBClCAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFKEABCrBbgDWOAC19vOjxMAG9RYACHEHAnuD+xcy22pylPwdsC5ANM5tv08AAjAOv6d7fYZTMj+aX8Gdm9s7Mxu47N+YaQ80SRrRuEyUAAAAASUVORK5CYII='
  revisionControl.OnAction = () =>{
    // 设置修订状态为最终状态
    View.RevisionsFilter.View = 0;

    // 设置修订状态为 最终状态
    View.ShowRevisionsAndComments = false;
  }
}

      5.查看文档带显示标记的最终状态(留痕稿)

同上面第四个配置一样,需要自定义按钮,实现查看文档带显示标记的最终状态。

// 自定义留痕稿按钮
editWpsDoc.prototype.displayMark = async function () {
  // 在【审阅】栏新增定制元素  留痕稿
  const revisions = await this.wpsAppObject.ActiveDocument.Revisions;   // 获取修订对象
  const View = await this.wpsAppObject.ActiveDocument.ActiveWindow.View;
  const TabReviewWordControls = await this.wpsAppObject.CommandBars('ReviewTab').Controls;
  const revisionControl = await TabReviewWordControls.Add(1);
  revisionControl.Caption = '留痕稿';
  revisionControl.Picture = 'data:image/png;base64,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'
    revisionControl.OnAction = () =>{
    // 设置修订状态为最终状态
    View.RevisionsFilter.View = 0;

    // 设置修订状态为 显示标记的最终状态
    View.ShowRevisionsAndComments = true;
    // 显示修订框
    revisions.ShowRevisionsFrame = true;
  }
}

     6. 自定义套红按钮

// 自定义套红按钮
editWpsDoc.prototype.redHeadDoc = async function () {
  // 在【插入】栏新增定制元素
  const InsertControls = await this.wpsAppObject.CommandBars('InsertTab').Controls;
  // 添加 1 个定制元素:套红按钮
  const redHeaderControl = await InsertControls.Add(1);
  redHeaderControl.Caption = '套红';
  redHeaderControl.Picture = 'data:image/png;base64,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'
  return redHeaderControl
}

返回套红按钮,根据需要在套红按钮的点击事件编写业务代码


问题列表:

问题一

  • 问题描述:

套红后,服务器上的文件已经套红,但是获取到的文件还是未修改的文件

  • 解决方法:

后台在套红完成后,调用强刷接口


 问题二

  • 问题描述:

套红完成,后台进行强刷文件后,在线编辑页面显示为wps的默认编辑页面,导致自定义的配置失效

  • 解决方法

在后台完成强刷之后,重新开档


 问题三

  • 问题描述:

套红后,原来的修订记录不显示

  • 解决方法

暂无


  • 22
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值