金山WPS文档在线编辑

背景:vue项目,同一个页面存在多个编辑器场景。

按照往常一样,将编辑器封装成组件然后在页面引入,只能显示最后渲染的一个编辑器,前面渲染的都会消失。尝试过直接用iframe指向文档地址,不用金山提供的jdk还是有一样的问题。

下面是金山的开发给的解决方案:

​​

以下是我根据自己的情况实现的:这个html和需要用到的jdk放在public文件夹中

html 复制代码
// KSIframe.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>www</title>
</head>
<body>
</body>
<script src="./open-jssdk-v0.0.13.umd.js"></script>
<script>
  window.onload = () => {
    const params = new URLSearchParams(window.location.search);
    console.log(params.get('url'), 'url')
    // console.log(params.get('editorId'), 'editorId')
    // console.log(params.get('isShowTopArea'), 'isShowTopArea')
    // console.log(params.get('isShowHeader'), 'isShowHeader')
    // console.log(params.get('isEditable'), 'isEditable')
    const param1 = params.get('url')
    const param2 = params.get('editorId')
    const isEdit = params.get('isEditable') === 'true';
    const isShowTopArea = params.get('isShowTopArea') === 'true';
    const isShowHeader = params.get('isShowHeader') === 'true';
    const url = param1
    let div = document.createElement('div');

    div.setAttribute('id', param2); // 设置iframe的ID
    div.style.height = '520px'
// 将div添加到DOM中
    document.body.appendChild(div); // 添加到body的末尾
    const KSInstance = OpenSDK.config({
      url,
      mount: document.querySelector("#"+param2), // 挂载 iframe 节点
      commandBars: [
        {
          cmbId: 'HeaderMiddle', // 组件 ID
          attributes: {
            enable: isEdit, // 禁用组件(组件显示但不响应点击事件)
          },
        },
      ],
 wordOptions: {
        enableReadOnlyComment: isEdit,
        isBestScale: false, // 打开文档时,默认以最佳比例显示
      },
      commonOptions: {
        isShowTopArea, // 隐藏顶部区域(头部和工具栏)
        isShowHeader, // 隐藏头部区域
        // isBrowserViewFullscreen: false, // 是否在浏览器区域全屏
        // isIframeViewFullscreen: false, // 是否在 iframe 区域内全屏
        // acceptVisualViewportResizeEvent: true, // 控制 WebOffice 是否接受外部的 VisualViewport
      },
    });
 window.addEventListener('message', function(event) {
      // console.log(event.origin, '------>', window.location.origin);
      if (event.origin !== window.location.origin) {
        return; // 只接受来自特定源的消息
      }
      // console.log('Received message:', event.data);
      let getData = event.data
      switch (getData.type) {
        case 'insertEle':
          insertEle(getData.content, getData.markName)
              break;
        case 'setMode':
          setMode(getData.mode);
          break;
        case 'deleteEle':
          deleteEle(getData.key);
          break;
        default:
          console.log('没这个方法')
      }
 // 可以回复消息
      // event.source.postMessage('Hi there!', event.origin);
    }, false);
    async function insertEle(content, markName) {
      await KSInstance.ready();

      const selection = await KSInstance.Application.ActiveDocument.ActiveWindow.Selection

      // 区域对象
      const range = await selection.Range
      const start = await range.Start
      const end = start + content.length
  // 在选区后面插入内容
      await selection.InsertAfter(content)
      // const end = await range.End
      // console.log(range, 'range')
      // console.log(start, 'start1')
      // console.log(end, 'end1')
      await KSInstance.Application.ActiveDocument.Bookmarks.Add({
        Name: markName,
        Range: {
          Start: start,
          End: end
        }
      })
 const marks1 = await KSInstance.Application.ActiveDocument.Bookmarks.Json()
    }
    async function setMode(mode){
      await KSInstance.ready();
      const app = KSInstance.Application
      await app.ActiveDocument.SetReadOnly({
        Value: mode === 'preview'
      })
    }
 async function deleteEle(ceebElemPlaceHolder) {
      await KSInstance.ready();
      const app = KSInstance.Application
      app.ActiveDocument.ReplaceText([
        {
          key: ceebElemPlaceHolder,
          value: ''
        }
      ])
    }

  };
</script>
</html>

文档地址

等初始化需要用到的参数,放在父页面iframe的src中,通过路由参数传递。其它对文档的操作,用iframe通信的方式实现。

javascript 复制代码
 let urlEncoded = encodeURIComponent(fileUrl),
     src = `/KSIframe.html?url=${urlEncoded}&editorId=${this.editorId}&isShowTopArea=${this.isShowTopArea}&isShowHeader=${this.isShowHeader}&isEditable=${this.isEditableFile}`
 this.$nextTick(()=>{
       let box = document.getElementById(this.editorBoxId) // 插入iframe的父元素
       // 移除所有子元素
       box.replaceChildren();
            
       let iframe = document.createElement('iframe')
       iframe.setAttribute('src', src)
       iframe.setAttribute('id', this.editorIframeId)
       iframe.style.height = '500px'
       iframe.style.width = '100%'
       function handleLoaded(){
           let postData = {
               type: 'setMode',
               mode: isPreview ? 'preview' : 'edit'
           }
           iframe.contentWindow.postMessage(postData, window.location.origin);
           this.removeEventListener('load', handleLoaded, false);
       }
       iframe.addEventListener('load', handleLoaded, false);
       box.appendChild(iframe)
 })
      

iframe通信操作文档内容:

javascript 复制代码
let iframe = document.getElementById(this.editorIframeId)
let postData = {
   type: 'deleteEle',
   key: yourKey
}
iframe.contentWindow.postMessage(postData, window.location.origin);


let iframe = document.getElementById(this.editorIframeId)
let postData = {
    type: 'insertEle',
    content,
    markName,
}
iframe.contentWindow.postMessage(postData, window.location.origin);
相关推荐
崔庆才丨静觅5 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60616 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了6 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅6 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅6 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅6 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment7 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅7 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊7 小时前
jwt介绍
前端
爱敲代码的小鱼7 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax