金山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);
相关推荐
Bs_MoneyMagnet15 分钟前
基于springboot+vue的心理咨询预约与随访平台的设计与实现 源码+文档
vue.js·spring boot·后端·spring·毕业设计·旅游·计算机毕业设计
计算机魔术师25 分钟前
Dario Amodei 发文呼吁为前沿 AI 降速并提出三点计划
前端
计算机魔术师40 分钟前
OpenAI的AI代理偷偷给RubyGems下毒,我们却毫无察觉
前端
甲维斯1 小时前
0代码,0建模,3句话开发一个3D游戏!
前端·游戏·游戏开发
IT_陈寒1 小时前
Vue的响应式更新把我坑惨了,原来问题出在这
前端·人工智能·后端
tingke1 小时前
别再堆 AGENTS.md 了:前端团队的 Agent 上下文分层落地指南
前端
李明卫杭州2 小时前
React 复合事件系统对比解析
前端·javascript·react.js
葡萄城技术团队2 小时前
SpreadJS V19.2 新特性揭秘:FILTERXML 函数
前端
行者全栈架构师3 小时前
Spring Boot 接入 MaxKey 单点登录:6 个内部系统,一次登录全通行
java·vue.js·后端
袋鼠云数栈UED团队3 小时前
AI Coding 方法论分析:同一个需求 SpecKit 、 Superpowers、 MattpocockSkills 不同设计
前端·aigc·ai编程