背景:vue项目,同一个页面存在多个编辑器场景。
按照往常一样,将编辑器封装成组件然后在页面引入,只能显示最后渲染的一个编辑器,前面渲染的都会消失。尝试过直接用iframe指向文档地址,不用金山提供的jdk还是有一样的问题。
下面是金山的开发给的解决方案:
以下是我根据自己的情况实现的:这个html和需要用到的jdk放在public文件夹中
// 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通信的方式实现。
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通信操作文档内容:
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);