美文网首页
vue2 tinymce实现导入word功能

vue2 tinymce实现导入word功能

作者: ClownD | 来源:发表于2022-08-12 11:45 被阅读0次

前言

VUE后台管理有使用富文本编辑器导入word 文档进行编辑的需求
在使用 tinymce-plugin 库中的importword插件,总有各种报错,现在重新通过Mammoth获取word内容,实现导入word编辑的需求。底部有完整代码。

安装

现在TinMCE已经推到了v6版本,兼容Vue3.0X版本,现在我们要说的是Vue2.0X版本和我们的TinyMEC

npm install tinymce@6.1.2 -S
npm install @tinymce/tinymce-vue@2.0.0 -S

安装好后在node_modules里找到这个文件


image.png

将里面你所需要的文件拉到我们本地文件中,Vue2的版本是public,很多的博客的写法是将 node_modules 里面的skins文件夹复制到public/tinymce目录下,经过尝试是不完善的,需要将整个目录倒入进public里。

image.png
tinymce 默认是英文界面,所以还需要下载一个中文包,复制到 public/tinymce/langs目录下

导入tinymcejs

<div id="app"></div>
<script src="/tinymce/tinymce.js"></script>

封装组件

自己封装一个组件

<template>
  <div id="textAreaTemplate">
    <!-- //富文本插件 -->

    <div class="tinymcebox">
      <editor v-model="content" :init="init" :disabled="disabled"></editor>
    </div>
  </div>
</template>

<!--

                       _ooOoo_
                      o8888888o
                      88" . "88
                      (| -_- |)
                      O\  =  /O
                   ____/`---'\____
                 .'  \\|     |//  `.
                /  \\|||  :  |||//  \
               /  _||||| -:- |||||-  \
               |   | \\\  -  /// |   |
               | \_|  ''\-/''  |   |
               \  .-\__  `-`  ___/-. /
             ___`. .'  /-.-\  `. . __
          ."" '<  `.___\_<|>_/___.'  >'"".
         | | :  `- \`.;`\ _ /`;.`/ - ` : | |
         \  \ `-.   \_ __\ /__ _/   .-` /  /
    ======`-.____`-.___\_____/___.-`____.-'======
                       `=-='

-->


<script>
import tinymce from "tinymce/tinymce";
import Editor from "@tinymce/tinymce-vue";
import "tinymce/icons/default/icons";
import "tinymce/themes/silver";
import "tinymce/plugins/image";
import "tinymce/plugins/media";
import "tinymce/plugins/table";
import "tinymce/plugins/lists";
import "tinymce/plugins/wordcount";
import "tinymce/plugins/preview";
import "tinymce/plugins/code";
import "tinymce/plugins/link";
import "tinymce/plugins/advlist";
import "tinymce/plugins/codesample";
import "tinymce/plugins/fullscreen";
import "tinymce/plugins/searchreplace";
import "tinymce/plugins/autolink";
import "tinymce/plugins/directionality";
import "tinymce/plugins/visualblocks";
import "tinymce/plugins/visualchars";
import "tinymce/plugins/template";
import "tinymce/plugins/charmap";
import "tinymce/plugins/nonbreaking";
import "tinymce/plugins/insertdatetime";
import "tinymce/plugins/autosave";
import "tinymce/plugins/autoresize";
export default {
  components: {
    Editor,
  },
  props:{
    value:{
      type:String,
      default:''
    }
  },
  watch:{
    value(newValue){
      this.content = newValue
    },
    content(newValue){
      this.$emit("input",newValue)
    }
  },
  data() {
    return {
      disabled: false,
      content:'',
      //初始化配置
      init: {
        _target: () => this,
        //menubar: true, // 菜单栏显隐
        language_url: "/tinymce/langs/zh_CN.js",
        //language_url: '../../static/tinymce/langs/zh_CN.js', // vue-cli2.x
        language: "zh_CN",
        skin_url: "/tinymce/skins/ui/oxide",
        //skin_url: '../../static/tinymce/skins/ui/oxide', // vue-cli2.x
        //content_css: '../../static/tinymce/skins/content/default/content.css',// vue-cli2.x
        height: 770,
        min_height: 770,
        max_height: 770,
        toolbar_mode: "wrap",
        plugins:
          "preview searchreplace autolink directionality visualblocks visualchars fullscreen image link template code codesample table charmap  nonbreaking insertdatetime advlist lists wordcount autosave autoresize",
        toolbar:
          "code undo redo restoredraft | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link codesample | alignleft aligncenter alignright alignjustify outdent indent formatpainter | \
    styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | \
    table image charmap  pagebreak insertdatetime | fullscreen preview|",
        content_style: "p {margin: 5px 0;}",
        fontsize_formats: "12px 14px 16px 18px 24px 36px 48px 56px 72px",
        font_formats:
          "微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;",
        branding: false,
        paste_data_images: true,
        // 图片上传转码,图片作为base64代码使用,不使用上传接口,如果需要使用上传,请根据文档中的图片上传进行修改
        images_upload_handler: (blobInfo, progress) =>
          new Promise((resolve, reject) => {
            resolve(
              "data:" + blobInfo.blob().type + ";base64," + blobInfo.base64()
            );
          }),
      },
      content: this.value,
    };
  },
  mounted() {
  },
  methods: {

  },
};
</script>
<style lang="scss" scoped>

</style>

页面使用

<MyTinymce v-model="formData.content" ref="tinymce" />

到这一步已经完成可以用富文本的功能,接下来实现导入word的功能
首先下载依赖

npm install --save mammoth

在富文本的组件中,创建一个上传的组件,

<div style="text-align: right; margin-bottom: 20px">
      <el-upload
        class="uploadBtn"
        style="display:none"
        ref="fileRefs"
        action=""
        :before-upload="beforeUpload"
        :show-file-list="false"
        :disabled="disabled"
      >
        <el-button :disabled="disabled">导入</el-button>
      </el-upload>
    </div>

引入依赖

import "mammoth/mammoth.browser.js";
import Mammoth from "mammoth";

文件上传完之后,转化为html,并把内容传入编辑器中

beforeUpload(file, fileList) {
      const self = this;
      var reader = new FileReader();
      reader.onloadend = function (event) {
        let arrayBuffer = reader.result;
        //将word 转换成html
        const loading = self.$loading({
          lock: true,
          text: '文件解析中....',
          spinner: 'el-icon-loading',
          background: 'rgba(0, 0, 0, 0.3)'
        });
        Mammoth.convertToHtml({ arrayBuffer: arrayBuffer }).then(function (
          resultObject
        ) {
          // 重要!不适用setTimeout,无法使用
          setTimeout(() => {
            //获取原来编辑器的内容
            let content = tinymce.activeEditor.getContent()+resultObject.value
            tinymce.activeEditor.setContent(content);
            loading.close();
          }, 100);
        });
      };
      reader.readAsArrayBuffer(file);
      return false;
    },

将导入word按钮加入到tinymce的工具栏中,

将以下代码加入到tinymce的init配置信息中


image.png
setup: (editor)=> {
          let _this = this
          editor.ui.registry.addButton("importbtn", {
            text: "导入word",
            // icon:'', // 目前使用文字按钮,如果需要图标展示,根据文档中自定义图标中的内容进行配置
            onAction: function () {
              //触发上传组件
              _this.$refs['fileRefs'].$refs['upload-inner'].handleClick()
            },
          });
        },

效果展示

image.png
image.png

完整代码

组件代码

<template>
  <div id="textAreaTemplate">
    <div style="text-align: right; margin-bottom: 20px">
      <el-upload
        class="uploadBtn"
        style="display:none"
        ref="fileRefs"
        action=""
        :before-upload="beforeUpload"
        :show-file-list="false"
        :disabled="disabled"
      >
        <el-button :disabled="disabled">导入</el-button>
      </el-upload>
    </div>
    <!-- //富文本插件 -->

    <div class="tinymcebox">
      <editor v-model="content" :init="init" :disabled="disabled"></editor>
    </div>
  </div>
</template>

<!--

                       _ooOoo_
                      o8888888o
                      88" . "88
                      (| -_- |)
                      O\  =  /O
                   ____/`---'\____
                 .'  \\|     |//  `.
                /  \\|||  :  |||//  \
               /  _||||| -:- |||||-  \
               |   | \\\  -  /// |   |
               | \_|  ''\-/''  |   |
               \  .-\__  `-`  ___/-. /
             ___`. .'  /-.-\  `. . __
          ."" '<  `.___\_<|>_/___.'  >'"".
         | | :  `- \`.;`\ _ /`;.`/ - ` : | |
         \  \ `-.   \_ __\ /__ _/   .-` /  /
    ======`-.____`-.___\_____/___.-`____.-'======
                       `=-='

-->


<script>
import "mammoth/mammoth.browser.js";
import Mammoth from "mammoth";
import tinymce from "tinymce/tinymce";
import Editor from "@tinymce/tinymce-vue";
import "tinymce/icons/default/icons";
import "tinymce/themes/silver";
import "tinymce/plugins/image";
import "tinymce/plugins/media";
import "tinymce/plugins/table";
import "tinymce/plugins/lists";
import "tinymce/plugins/wordcount";
import "tinymce/plugins/preview";
import "tinymce/plugins/code";
import "tinymce/plugins/link";
import "tinymce/plugins/advlist";
import "tinymce/plugins/codesample";
import "tinymce/plugins/fullscreen";
import "tinymce/plugins/searchreplace";
import "tinymce/plugins/autolink";
import "tinymce/plugins/directionality";
import "tinymce/plugins/visualblocks";
import "tinymce/plugins/visualchars";
import "tinymce/plugins/template";
import "tinymce/plugins/charmap";
import "tinymce/plugins/nonbreaking";
import "tinymce/plugins/insertdatetime";
import "tinymce/plugins/autosave";
import "tinymce/plugins/autoresize";
export default {
  components: {
    Editor,
  },
  props:{
    value:{
      type:String,
      default:''
    }
  },
  watch:{
    value(newValue){
      this.content = newValue
    },
    content(newValue){
      this.$emit("input",newValue)
    }
  },
  data() {
    return {
      disabled: false,
      content:'',
      //初始化配置
      init: {
        _target: () => this,
        //menubar: true, // 菜单栏显隐
        language_url: "/tinymce/langs/zh_CN.js",
        //language_url: '../../static/tinymce/langs/zh_CN.js', // vue-cli2.x
        language: "zh_CN",
        skin_url: "/tinymce/skins/ui/oxide",
        //skin_url: '../../static/tinymce/skins/ui/oxide', // vue-cli2.x
        //content_css: '../../static/tinymce/skins/content/default/content.css',// vue-cli2.x
        height: 770,
        min_height: 770,
        max_height: 770,
        toolbar_mode: "wrap",
        plugins:
          "preview searchreplace autolink directionality visualblocks visualchars fullscreen image link template code codesample table charmap  nonbreaking insertdatetime advlist lists wordcount autosave autoresize",
        toolbar:
          "code undo redo restoredraft | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link codesample | alignleft aligncenter alignright alignjustify outdent indent formatpainter | \
    styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | \
    table image charmap  pagebreak insertdatetime | fullscreen preview| importbtn",
        content_style: "p {margin: 5px 0;}",
        fontsize_formats: "12px 14px 16px 18px 24px 36px 48px 56px 72px",
        font_formats:
          "微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;",
        branding: false,
        setup: (editor)=> {
          let _this = this
          editor.ui.registry.addButton("importbtn", {
            text: "导入word",
            // icon:'material',
            onAction: function () {
              _this.$refs['fileRefs'].$refs['upload-inner'].handleClick()
            },
          });
        },
        paste_data_images: true,
        // 图片上传转码
        images_upload_handler: (blobInfo, progress) =>
          new Promise((resolve, reject) => {
            resolve(
              "data:" + blobInfo.blob().type + ";base64," + blobInfo.base64()
            );
          }),
      },
      content: this.value,
    };
  },
  mounted() {
  },
  methods: {
    beforeUpload(file, fileList) {
      const self = this;
      var reader = new FileReader();
      reader.onloadend = function (event) {
        let arrayBuffer = reader.result;
        //将word 转换成html
        const loading = self.$loading({
          lock: true,
          text: '文件解析中....',
          spinner: 'el-icon-loading',
          background: 'rgba(0, 0, 0, 0.3)'
        });
        Mammoth.convertToHtml({ arrayBuffer: arrayBuffer }).then(function (
          resultObject
        ) {
          
          setTimeout(() => {
            let content = tinymce.activeEditor.getContent()+resultObject.value
            tinymce.activeEditor.setContent(content);
            loading.close();
          }, 100);
        });
      };
      reader.readAsArrayBuffer(file);
      return false;
    }
  },
};
</script>
<style lang="scss" scoped>
#textAreaTemplate {
  .uploadBtn {
    display: inline-block;
    margin: 0 10px;
  }
  .tabTiyle {
    border-left: 8px solid rgba(36, 145, 255, 1);
    padding-left: 15px;
    font-size: 21px;
    text-align: left;
    font-family: PingFangSC-Medium, PingFang SC;
    font-weight: 500;
    color: rgba(0, 0, 0, 0.87);
  }
}
</style>
<style>
.dialog {
  text-align: left;
}
</style>

页面使用

<MyTinymce v-model="formData.content" ref="tinymce" />

相关文章

网友评论

      本文标题:vue2 tinymce实现导入word功能

      本文链接:https://www.haomeiwen.com/subject/lhpxgrtx.html