Vue3+TS实现将html或富文本编辑器转为Word并下载

说明:我用的富文本编辑器是wangEditor:
wangEditor官网

  • 安装

yarn add @wangeditor/editor
# 或者 npm install @wangeditor/editor --save
yarn add @wangeditor/editor-for-vue@next
# 或者 npm install @wangeditor/editor-for-vue@next --save
yarn add html-docx-js-typescript
# 或者  npm install html-docx-js-typescript --save-dev

利用Button按钮进行导出

  • 在所需页面中引入资源

    import '@wangeditor/editor/dist/css/style.css' // 引入 富文本编辑器css
    import { Editor, Toolbar } from '@wangeditor/editor-for-vue'//富文本编辑器
    import { asBlob } from 'html-docx-js-typescript';//将html转为word
    
  • HTML部分

<el-button type="primary" plain @click="exportDoc">
  导出文档
</el-button>
<div style="border: 1px solid #ccc">
  <Toolbar
    style="border-bottom: 1px solid #ccc"
    :editor="editorRef"
    :default-config="toolbarConfig"
    :mode="mode"
  />
  <Editor
    v-model="valueHtml"
    style="height: 500px; overflow-y: hidden;"
    :default-config="editorConfig"
    :mode="mode"
    @on-created="handleCreated"
  />
</div>
  • JavaScript部分

<script setup lang="ts">
 // 编辑器实例,必须用 shallowRef
 const editorRef = shallowRef()
 const mode = ref('default')
 // 内容 HTML
 const valueHtml = ref('')
 // 工具栏配置项
 const toolbarConfig: Partial<IToolbarConfig> = {}
 const editorConfig = { placeholder: '请输入内容...', MENU_CONF: {} }
 // 组件销毁时,也及时销毁编辑器
 onBeforeUnmount(() => {
   const editor = editorRef.value
   if (editor == null)
     return
   editor.destroy()
 })
 function handleCreated(editor: any) {
   editorRef.value = editor // 记录 editor 实例,重要!
 }
 // 导出文档
 async function exportDoc() {
   const editor = editorRef.value
   // 将富文本内容拼接为一个完整的html
   const html = editor.getHtml()
   const value =  `<!DOCTYPE html>
   <html lang="en">
      <head>
        <meta charset="UTF-8">
        <title>Document</title>
      </head>
      <body>
         ${html}
      </body>
    </html>`
   // landscape就是横着的,portrait是竖着的,默认是竖屏portrait。
   const data = await asBlob(value, { orientation: 'portrait' }) as Blob
   const a = document.createElement('a')
   a.href = window.URL.createObjectURL(data)
   a.setAttribute('download', 'document.docx')
   a.click()
   // 下载后将标签移除
   a.remove()
  }
 </script>

在操作栏导出添加导出word功能

  • 在所需页面中引入资源
    import '@wangeditor/editor/dist/css/style.css' // 引入 富文本编辑器css
    import { Editor, Toolbar } from '@wangeditor/editor-for-vue'//富文本编辑器
    import type { IToolbarConfig } from '@wangeditor/editor'
    import MyButtonMenu from '@/views/home/button'
    
  • HTML部分

<div class="home-page">
    <div style="border: 1px solid #ccc">
      <Toolbar
        style="border-bottom: 1px solid #ccc"
        :editor="editorRef"
        :default-config="toolbarConfig"
        :mode="mode"
      />
      <Editor
        v-model="valueHtml"
        style="height: 500px; overflow-y: hidden;"
        :default-config="editorConfig"
        :mode="mode"
        @on-created="handleCreated"
      />
    </div>
  </div>
  • JavaScript部分

<script setup lang="ts" name="Home">
// 编辑器实例,必须用 shallowRef
const editorRef = shallowRef()
const mode = ref('default')

// 内容 HTML
const valueHtml = ref('')

const toolbarConfig: Partial<IToolbarConfig> = {
  insertKeys: {
    index: 1, // 插入的位置,基于当前的 toolbarKeys
    keys: ['button'],
  },
}
const editorConfig = { placeholder: '请输入内容...', MENU_CONF: {} }
// 组件销毁时,也及时销毁编辑器
onBeforeUnmount(() => {
  const editor = editorRef.value
  if (editor == null)
    return
  editor.destroy()
})
onMounted(() => {
  setTimeout(() => {
    const editor = editorRef.value
    editor.insertText('HelloWorld')
    editor.dangerouslyInsertHtml('<h1>标题</h1><p>文本 <b>加粗</b></p>')
    console.log(editor.getHtml(), 'editor.getHtml()')
  }, 1500)
})
const menu1Conf: any = {
  key: 'button', // 定义 menu key :要保证唯一、不重复(重要)
  factory() {
    return new MyButtonMenu() // 把 `YourMenuClass` 替换为你菜单的 class
  },
}
Boot.registerMenu(menu1Conf)
function handleCreated(editor: any) {
  editorRef.value = editor // 记录 editor 实例,重要!
}
</script>
  • button.ts

import type { IButtonMenu, IDomEditor } from '@wangeditor/editor'
import { asBlob } from 'html-docx-js-typescript'

class MyButtonMenu implements IButtonMenu { // TS 语法
  constructor() {
    this.title = '导出为word' // 自定义菜单标题
    // this.iconSvg = '<svg>...</svg>' // 可选
    this.tag = 'button'
  }

  // 获取菜单执行时的 value ,用不到则返回空 字符串或 false
  getValue(editor: IDomEditor): string | boolean { // TS 语法
    console.log(editor, '====')
    return false
  }

  // 菜单是否需要激活(如选中加粗文本,“加粗”菜单会激活),用不到则返回 false

  isActive(editor: IDomEditor): boolean { // TS 语法
    console.log(editor, '====')
    return false
  }

  // 菜单是否需要禁用(如选中 H1 ,“引用”菜单被禁用),用不到则返回 false

  isDisabled(editor: IDomEditor): boolean { // TS 语法
    console.log(editor, '====')
    return false
  }

  // 点击菜单时触发的函数
  async exec(editor: IDomEditor, value: string | boolean) { // TS 语法
    // 将富文本内容拼接为一个完整的html
    const html = editor.getHtml()
    const val = `<!DOCTYPE html>
  <html lang="en">
     <head>
        <meta charset="UTF-8">
           <title>Document</title>
        </head>
        <body>
           ${html}
        </body>
  </html>`
    // 1、将html转为word的blob  2、 landscape就是横着的,portrait是竖着的,默认是竖屏portrait。
    const data = await asBlob(val, { orientation: 'portrait' }) as Blob
    const a = document.createElement('a')
    a.href = window.URL.createObjectURL(data)
    a.setAttribute('download', 'document.docx')
    a.click()
    // 下载后将标签移除
    a.remove()
    if (this.isDisabled(editor))
      return
    editor.insertText(value as any) // value 即 this.value(editor) 的返回值
  }
}
export default MyButtonMenu
  • 效果图

    • Web 富文本编辑器富文本

      image.png
      image.png

    • word文档
      image.png
      image.png


标题:Vue3+TS实现将html或富文本编辑器转为Word并下载
作者:mcwu
地址:http://mcongblog.com/articles/2024/05/14/1715657293905.html

    评论
    0 评论
avatar

取消