金山在线文档编辑器

news2024/9/20 10:55:13

官方文档地址:快速开始-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 null
  const instance = WebOfficeSDK.config({
    url,
    mount: el,
    commandBars: [
      {
        cmbId: 'HeaderMiddle', // 组件 ID
        attributes: {
          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-upload
      class="compare-uploader"
      ref="upload"
      :with-credentials="true"
      :show-file-list="false"
      withCredentials
      :http-request="httpRequest"
      :on-progress="onProgress"
      :multiple="false"
    >
      <!-- 文件上传-->
      <el-button
        type="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>
    <JSEditor
      v-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 = userTableMap
    export 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 = instance
          await instance.ready()
          if(this.mode === 'preview'){
            const app = instance.Application
            await 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.datas
              this.ksFileInfoCopy = res.data.datas
              this.getFileUrl(res.data.datas.id, res.data.datas.ext)
            })
            .catch(error => {
              console.log(error);
            });
        },
        getFileUrl(fileId, ext, isPreview) {
          this.showKS = false
          this.fileLoading = true
          axios({
            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 = false
              this.KSfile = res.data.datas
              this.KSurl = res.data.datas
              this.ksFileInfoCopy.url = isPreview ? this.ksFileInfo.url : res.data.datas
              this.ksFileInfo.url = res.data.datas
              this.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.Range
          const start = await range.Start
          let content = type + '书签'+ mark
          const 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 = false
            this.isShowTopArea = false
            this.isEditableFile = false
            let 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.id
            let 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.ksFileInfo
            this.isShowHeader = true
            this.isShowTopArea = true
            this.isEditableFile = true
            this.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.datas
            this.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)] = elmKey
              return {
                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).Range
              cell.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小时,在这时间内可以下载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2128568.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【HTML】HTML页面和常见标签

文章目录 什么是前端HTML 页面编写如何快速生成代码框架常见标签注释标签标题标签段落标签换行标签格式化标签 什么是前端 Web 前端&#xff0c;用来直接给以用户呈现的一个一个的网页。一个软件通常是由 后端前端 完成的 后端&#xff1a;通过 Java/C等语言&#xff0c;完成相…

机械厂选并联电容器的要求

在机械厂选择并联电容器时&#xff0c;需要考虑多个因素&#xff0c;以确保无功补偿设备能够有效提高功率因数、降低电网损耗、提升电能质量。以下是机械厂选用并联电容器时的一些关键要求&#xff1a; 1、容量选择 无功功率需求&#xff1a;根据机械厂的负载特性&#xff0c;…

Apple公众号,是如何玩转SVG擦出/刷新/填涂特效?|E2.COOL黑科技SVG编辑器

动画类型 width/height animation 通过擦出/刷新等效果&#xff0c;实现产品的多图轮播、细节对比、文字高亮——这是 Apple 公众号特别偏爱的一种 SVG 交互设计方式。那么它的技术本质是什么&#xff1f;Apple 的编辑又是如何持续创新应用在 SVG 图文内的&#xff1f;本期我…

【Python】谷歌浏览器总是自动更新,使用selenium跟chromedriver版本不匹配怎么办?

我发现&#xff0c;我的电脑对谷歌浏览器的禁止自动更新无效&#xff0c;哪怕是在任务计划程序里&#xff0c;禁止谷歌浏览器更新&#xff0c;也没有用。而且有时候点开右上角的三个点&#xff0c;也会自动更新版本。 但是往往chromedriver的更新版本更不上浏览器的版本哇&…

SQL Server数据库简单的事务日志备份恢复

模拟数据库备份恢复过程 1.基础操作 1.创建TestDB数据库&#xff0c;并添加数据 USE [master] GO CREATE DATABASE TestDB CONTAINMENT NONE ON PRIMARY ( NAME NTestDB, FILENAME ND:\TestDB.mdf , SIZE 8192KB , MAXSIZE UNLIMITED, FILEGROWTH 65536KB ) LOG ON ( …

前端开发人员都必须知道的 7 个 Vue3 组件库!

Vue.js 是一个流行的 JavaScript 框架&#xff0c;它以其易用性和灵活性吸引了大量开发人员。 随着 Vue 3 的发布&#xff0c;生态系统也迎来了新的变化和增强。 本文将介绍每个前端开发人员都必须知道的 7 个 Vue 3 组件库&#xff0c;并提供详细步骤、代码示例和相关图片链…

编译原理/软件工程核心概念-问题理解

目录 1.程序的编译执行过程 2.指针和引用的区别 3.堆和栈的区别 4.最熟悉的编程语言- Python&#xff1a;介绍PyTorch和TensorFlow框架 5.C与C的区别 6.软件工程是什么&#xff1f; 7.简述瀑布模型 8.敏捷开发方法是什么&#xff1f;它与瀑布模型相比有哪些优势和劣势 1…

Python 数学建模——高斯核密度估计

文章目录 前言原理代码实例scipy 实现seaborn 实现 前言 高斯核密度估计本是一种机器学习算法&#xff0c;在数学建模中也可以发挥作用。本文主要讨论用它来拟合变量的概率密度&#xff0c;获得概率密度函数 f ( x ) f(x) f(x)。 原理 已知一个连续型随机变量 X X X 的一系列…

实战千问2大模型第三天——Qwen2-VL-7B(多模态)视频检测和批处理代码测试

画面描述:这个视频中,一位穿着蓝色西装的女性站在室内,背景中可以看到一些装饰品和植物。她双手交叉放在身前,面带微笑,似乎在进行一场演讲或主持活动。她的服装整洁,显得非常专业和自信。 一、简介 阿里通义千问开源新一代视觉语言模型Qwen2-VL。其中,Qwen2-VL-72B在大…

Kubernetes部署(haproxy+keepalived)高可用环境和办公网络打通

HAProxy Keepalived 部署高可用性入口&#xff1a; 部署两台或多台节点运行 HAProxy 作为负载均衡器。使用 Keepalived 实现 VIP&#xff08;虚拟 IP&#xff09;&#xff0c;为 HAProxy 提供高可用性。Keepalived 会监控 HAProxy 的状态&#xff0c;如果主节点失效&#xff0…

再次进阶 舞台王者 第八季完美童模全球赛荣耀大使【殷淑窈】赛场秀场超燃合集!

7月20-23日&#xff0c;2024第八季完美童模全球总决赛在青岛圆满落幕。在盛大的颁奖典礼上&#xff0c;一位才能出众的少女——殷淑窈&#xff0c;迎来了她舞台生涯的璀璨时刻。 荣耀大使——殷淑窈&#xff0c;以璀璨童星之姿&#xff0c;优雅地踏上完美童模盛宴的绚丽舞台&am…

51单片机应用开发---二进制、十六进制与单片机寄存器之间的关系(跑马灯实例)

实现目标 1、掌握二进制与十六进制之间的转换 2、掌握单片机寄存器与二进制、十六进制之间的转换 一、二进制与十六进制之间的转换 1、二进制 二进制&#xff08;binary&#xff09;&#xff0c; 是在数学和数字电路中以2为基数的记数系统&#xff0c;是以2为基数代表系统…

Java面试篇基础部分-Java中的集合类

Java集合是面试中经常被问到的一块内容,很多人在这个地方被面试官吊打。Java集合类被定义在java.util包中,主要有四种集合,分别是List、Queue、Set和Map,每种集合分类如下图所示 List集合 List是一种在开发中比较常用的集合类,作为有序的Collection的典范,分别有如下的…

股指期货的指数一直贴水是什么意思?

在投资的世界里&#xff0c;股指期货是一个既复杂又充满机会的领域。而“股指期货贴水”这一现象&#xff0c;更是让不少投资者感到困惑。今天&#xff0c;我们就用大白话&#xff0c;来详细解释一下股指期货贴水到底是什么意思。 一、什么是股指期货&#xff1f; 首先&#…

ppt一键生成软件免费版有哪些?职场小白看这里

俗话说得好&#xff1a;时间就是金钱&#xff0c;一款好用且高效的工具无疑能让我们的工作事半功倍。 特别是经常需要制作ppt的朋友&#xff0c;拥有ppt一键生成软件免费工具可以帮你们更高效的完成工作&#xff0c;将精力投入到其他事项去。 因此&#xff0c;今天这篇文章找…

虚拟电厂高质量发展,大众氢能港引领能源管理新变革

在2024年这个充满希望的夏日&#xff0c;上海市政府正式印发了《上海市虚拟电厂高质量发展工作方案》&#xff0c;标志着上海在探索能源结构优化、促进绿色低碳发展的道路上迈出了坚实的一步。该方案不仅为虚拟电厂的未来发展绘制了清晰的蓝图&#xff0c;更通过一系列创新举措…

Github 2024-09-09 开源项目周报 Top15

根据Github Trendings的统计,本周(2024-09-09统计)共有15个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目6TypeScript项目4Jupyter Notebook项目2C++项目2JavaScript项目2Shell项目1Dockerfile项目1C#项目1Dart项目1Rust项目1Microsoft Pow…

大健康企业如何通过私域流量与积分增值模式实现业绩飞跃

在探讨大健康领域的一家创新企业时&#xff0c;我们发现其成功之路并非仅仅依赖传统电商的广撒网策略&#xff0c;如大规模广告投放和促销优惠&#xff0c;而是巧妙转型&#xff0c;深耕私域流量的构建与独特商业模式的应用。 这一转变不仅显著提升了月度销售业绩&#xff0c;更…

不小心把电脑格式化了怎么恢复?这些步骤帮你找回数据

在日常使用电脑的过程中&#xff0c;我们有时会因为各种原因不小心对电脑进行了格式化操作。一旦电脑被格式化&#xff0c;所有的数据都将被清除&#xff0c;这给用户带来了巨大的困扰和损失。 然而&#xff0c;不必过于绝望&#xff0c;因为有些方法可以帮助我们恢复被格式化…

作为负责招聘的HR,如何解决职位吸引力不足的问题

职位吸引力不足&#xff0c;很有可能是因为对职位描述的太过平淡无奇&#xff0c;没办法引起求职者足够的关心和了解。HR应当更加深入地挖掘企业特色&#xff0c;通过精心撰写职位描述&#xff0c;来凸显出企业的发展潜力和品牌文化等亮点&#xff0c;使用更加精确的描述&#…