官方文档地址:快速开始-WebOffice 知识库
首先按照文档写的方式将包引入项目了
util.js
import WebOfficeSDK from "../../public/JSEditor/open-jssdk-v0.0.13.umd"
export function WordSDK(url, isEdit, mountDom, isShowTopArea, isShowHeader) {const el = document.querySelector(mountDom)if (!el) return nullconst instance = WebOfficeSDK.config({url,mount: el,commandBars: [{cmbId: 'HeaderMiddle', // 组件 IDattributes: {enable: isEdit, // 禁用组件(组件显示但不响应点击事件)},},],wordOptions: {enableReadOnlyComment: isEdit,isBestScale: false, // 打开文档时,默认以最佳比例显示},commonOptions: {isShowTopArea, // 隐藏顶部区域(头部和工具栏)isShowHeader, // 隐藏头部区域// isBrowserViewFullscreen: false, // 是否在浏览器区域全屏// isIframeViewFullscreen: false, // 是否在 iframe 区域内全屏// acceptVisualViewportResizeEvent: true, // 控制 WebOffice 是否接受外部的 VisualViewport},});instance.setToken({// token: `bearer ${getToken('token')}`,token: '',timeout: 10 * 60 * 1000,});return instance;
}
封装编辑器组件:KSEditor.vue
<template><div ref="editorContainer" class="editor-container"></div>
</template><script>import {WordSDK} from "@/utils/util"export default {name: 'JsEditorComponent',props: {KSfile: {type: String,default: ''},isShowHeader: {type: Boolean,default: true},isShowTopArea: {type: Boolean,default: true},isEditable: {type: Boolean,default: true}},data() {return {editorInstance: null,ksConfig: {// 在这里配置金山在线文档编辑器的初始化参数// 比如 token、文档ID 等}};},mounted() {// 在组件加载完成后初始化编辑器this.initEditor()},methods: {initEditor() {let KSInstance = WordSDK(this.KSfile,this.isEditable,'.editor-container',this.isShowTopArea,this.isShowHeader,)this.$emit('setInstance', KSInstance)},createDocument() {// 在点击按钮时触发新建文档操作// 假设SDK提供了相应的方法来新建文档if (this.editor) {this.editor.createDocument(); // 假设SDK方法名为createDocument} else {console.error('编辑器尚未初始化');}}}};
</script><style scoped>/* 可能需要一些样式来控制编辑器容器的宽度和高度 */.editor-container {width: 100%;height: 600px;}
</style>
页面testKSEditor.vue
<template><div style="width: 100%"><el-uploadclass="compare-uploader"ref="upload":with-credentials="true":show-file-list="false"withCredentials:http-request="httpRequest":on-progress="onProgress":multiple="false"><!-- 文件上传--><el-buttontype="ghost"slot="trigger"size="mini">导入文件</el-button></el-upload>id:<el-input v-model="ksFileInfoCopy.id"/><br/>文件类型:<el-input v-model="ksFileInfoCopy.ext"/><br/>文件名称:<el-input v-model="ksFileInfoCopy.name"/><br/><el-button@click="()=>getFileUrl(this.ksFileInfoCopy.id, this.ksFileInfoCopy.ext)">刷新</el-button><el-button@click="()=>destroyKS()">销毁</el-button><el-button@click="()=>insertBookmark('TEXT')">插入书签</el-button><el-button@click="()=>insertBookmark('TABLE')">插入表格类型书签</el-button><el-button@click="() => this.bookmarks = []">清空</el-button><el-button@click="()=>changeMode()">{{mode === 'edit'?'预览':'编辑'}}</el-button><el-button@click="()=>replaceBookmarkValue()">替换书签值</el-button><JSEditorv-if="showKS"@setInstance="setInstance":KSfile="KSfile":isShowTopArea="isShowTopArea":isShowHeader="isShowHeader":isEditable="isEditableFile"/></div>
</template><script>import axios from "axios";import JSEditor from 'lib@/components/KSEditor'import {userTableMap} from "@/modules/testKSeditor/fieldMap";const userTable = userTableMapexport default {name: "index",components: {JSEditor},data () {// supplementRules:return {userId: this.$store.getters.userId,fileLoading: false,app: null,bookmark: null,KSfile: '',KSurl: '',showKS: false,isShowHeader: true,isShowTopArea: true,isEditableFile: true,ksFileInfo: {ext: 'docx',id: '0af2cc2e1da145f48667a6bd09d30e77',// id: '6170f21b9fe94db78bc2e56d8f543c1e',name: '工治具报修管理.docx',url: ''},ksFileInfoCopy: {ext: 'docx',id: '0af2cc2e1da145f48667a6bd09d30e77',// id: '6170f21b9fe94db78bc2e56d8f543c1e',name: '工治具报修管理.docx',url: ''},tableData: [{number: '1',name: 'yy',sex: 'b',age: '11'},{number: '2',name: 'ee',sex: 'g',age: '22'},{number: '3',name: 'ss',sex: 'b',age: '33'},{index: '4',name: 'ff',sex: 'g',age: '44'},],mode: 'edit',bookmarks: [],KSInstance: null}},methods: {async setInstance(instance){// console.log(instance, '1111')this.KSInstance = instanceawait instance.ready()if(this.mode === 'preview'){const app = instance.Applicationawait app.ActiveDocument.SetReadOnly({Value: true})}// console.log(app, 'this.KSInstance.Application')},httpRequest(fileObj) {const formData = new FormData();formData.append("file", fileObj.file);axios({url: 'https://sdap-dev.sunwoda.com/api/platform-oss/public/upload?bucket=sdap',method: "post",data: formData,}).then(res => {this.ksFileInfo = res.data.datasthis.ksFileInfoCopy = res.data.datasthis.getFileUrl(res.data.datas.id, res.data.datas.ext)}).catch(error => {console.log(error);});},getFileUrl(fileId, ext, isPreview) {this.showKS = falsethis.fileLoading = trueaxios({url: 'https://sdap-dev.sunwoda.com/api/platform-system/public/wps-api/edit-url',method: "get",params: { fileId, ext, previewMode: 'high_definition' }}).then(res => {this.fileLoading = falsethis.KSfile = res.data.datasthis.KSurl = res.data.datasthis.ksFileInfoCopy.url = isPreview ? this.ksFileInfo.url : res.data.datasthis.ksFileInfo.url = res.data.datasthis.showKS = true}).catch(error => {console.log(error);});},destroyKS(){this.KSInstance.destroy()},async insertBookmark(type){const bookmark = await this.KSInstance.Application.ActiveDocument.Bookmarks;const selection = await this.KSInstance.Application.ActiveDocument.ActiveWindow.Selection// 区域对象let mark = 'mark' + Date.now()const range = await selection.Rangeconst start = await range.Startlet content = type + '书签'+ markconst end = start + content.length// 在选区后面插入内容await selection.InsertAfter(content)await bookmark.Add({Name: mark,Range: {Start: start,End: end}})this.bookmarks.push({markName: mark,type: type,value: mark + '的值'})},changeMode(){if(this.mode === 'edit'){this.mode = 'preview'this.isShowHeader = falsethis.isShowTopArea = falsethis.isEditableFile = falselet replaceData = []let modelLines = this.bookmarks // 合同元素相关信息// let allMarks = await this.KSInstance.Application.ActiveDocument.Bookmarks.Json()for (const i of modelLines) {replaceData.push({bookmark: i.markName,type: i.type,text: i.value})}let template_url = 'https://sdap-dev.sunwoda.com/api/platform-oss/public/download/' + this.ksFileInfo.idlet data = {task_id: this.userId,template_url: template_url,template_filename: this.ksFileInfo.name,use_template_section_property:true,flatten_source_style: true,sample_list: replaceData}axios({url: 'https://sdap-dev.sunwoda.com/api/platform-system/public/wps-api/wrap-header',method: 'post',data}).then(res => {if(res.data.resp_code === 200){this.getReviewFile(res.data.datas.download_id)}})} else {this.mode = 'edit'this.ksFileInfoCopy = this.ksFileInfothis.isShowHeader = truethis.isShowTopArea = truethis.isEditableFile = truethis.getFileUrl(this.ksFileInfo.id, this.ksFileInfo.ext)}},getReviewFile(id){let data = {bucket: 'sdap',downloadId: id,fileName: id + '测试文档.docx'}axios({url: ' https://sdap-dev.sunwoda.com/api/platform-system/public/wps-api/upload-file',method: 'post',params: data}).then(res => {this.ksFileInfoCopy = res.data.datasthis.getFileUrl(res.data.datas.id, res.data.datas.ext, true)})},async replaceBookmarkValue(){let modelLines = this.bookmarks // 合同元素相关信息let allMarks = await this.KSInstance.Application.ActiveDocument.Bookmarks.Json()let replaceData = []for (const i of modelLines) {if (i.type === 'TABLE') {let tableData = JSON.parse(JSON.stringify(this.tableData))let header = ["序号", "姓名", "性别", "年龄"]await this.insertTable(header, tableData, userTable, i)} else {replaceData.push({name: i.markName,type: 'text',value: i.value})}}this.KSInstance.Application.ActiveDocument.Bookmarks.ReplaceBookmark(replaceData)},async insertTable(tableHead, tableBodyData, fieldMap, eleInfo){const tables = await this.KSInstance.Application.ActiveDocument.Tables // 编辑器的表格对象let tableData = JSON.parse(JSON.stringify(tableBodyData))tableData.map((i, ind) => {i.number = ind + 1 + ''})let headerData = {}let fields = tableHead.map((elmKey, index) => {if (!!elmKey) {headerData[fieldMap.get(elmKey)] = elmKeyreturn {name: elmKey,field: fieldMap.get(elmKey)}}})tableData.unshift(headerData)let rowCount = tableData.length, colCount = tableHead.length// 插入表格await tables.Add(this.KSInstance.Application.ActiveDocument.Bookmarks.Item(eleInfo.markName).Range, // 位置信息rowCount, // 新增表格的行数colCount, // 新增表格的列数1, // 启用自动调整功能1 // 根据表格中包含的内容自动调整表格的大小)const count = await tables.Count // 表格数量const curTable = await tables.Item(count)console.log(count, 'count')// console.log(tableData, 'tableData')// console.log(headerData, 'headerData')// console.log(fields, 'fields')for (let j = 1; j < rowCount + 1; j++) { // 遍历行let row = tableData[j-1]for (let f = 1; f < colCount + 1; f++) { // 遍历列let fieldsInfo = fields[f-1]// console.log(fieldsInfo, 'fieldsInfo')let field = row[fieldsInfo.field] || ''const cell = await curTable.Rows.Item(j).Cells.Item(f).Rangecell.Text = field + ''}}this.KSInstance.Application.ActiveDocument.ReplaceText([ // 将书签的内容替换成空字符串{key: 'TABLE书签' + eleInfo.markName,value: ''}])}}}
</script><style scoped></style>
fieldMap.js
export const userTableMap = new Map();
userTableMap.set('序号', "number");
userTableMap.set('姓名', "name");
userTableMap.set("性别", "sex");
userTableMap.set("年龄", "age");
前端代码实现书签替换页面效果:
两张截图是分开截的,效果差不多是这样。是有bug的,给表格赋值不太稳定。书签替换也不稳定,没截到连续的图就是因为这个,老有问题,不想截了,不稳定的原因不明。
还可以调用在线编辑的接口实现书签替换,这种方式不支持替换成表格,但支持替换成在线文档,就是可以建一个在线文档,里面加表格,然后将这个在线文档引入进来。我用的接口是我们的后端封装过的,具体的找金山的询问,毕竟要用这个肯定得买,他们肯定会派人支持。
调用接口的方式,可以在“编辑”“预览”之前多次跳转,因为这个方法替换书签不是在原文档上修改,是后台会新建一个文件来替换书签,并且这个新文档会缓存24小时,在这时间内可以下载。