Bootstrap

wangeditor二次封装

RichEditor.vue

<template>
  <div class="root" style="border: 1px solid #ccc margin-top: 10px">
    <!-- 工具栏 -->
    <Toolbar :defaultConfig="toolbarConfig" :editor="editor" style="border-bottom: 1px solid #ccc" />
    <!-- 编辑器 -->
    <div class="editor-area">
      <div class="area">编辑区</div>
      <Editor :defaultConfig="editorConfig" :value="value" @onCreated="onCreated" class="editor" v-on="$listeners" />
      <div class="area">预览区</div>
      <!-- <div class="editor preview" v-html="$richTextAddOssToken(value)"></div> -->
      <div class="editor preview" v-html="value"></div>
      <div class="area">[注:小程序端不同手机屏幕像素不同,显示略有差异]</div>
    </div>
  </div>
</template>

<script>
import { Editor, Toolbar } from "@wangeditor/editor-for-vue"
import { imageUpload, imageDelete } from '@/api/basic/system'

export default {
  name: "RichEditor",
  components: { Editor, Toolbar },
  props: {
    value: ''
  },
  data () {
    return {
      editor: null,
      toolbarConfig: {
        // toolbarKeys: [ /* 显示哪些菜单,如何排序、分组 */ ],
        // excludeKeys: [ /* 隐藏哪些菜单 */ ],
        excludeKeys: ['fontFamily', 'group-video', 'fullScreen', 'insertLink', 'blockquote']
      },
      editorConfig: {
        placeholder: "请输入内容...",
        // autoFocus: false,

        // 所有的菜单配置,都要在 MENU_CONF 属性下
        MENU_CONF: {
          uploadImage: {
            // 单个文件的最大体积限制,默认为 2M
            maxFileSize: 10 * 1024 * 1024, // 10M
            // 最多可上传几个文件,默认为 100
            maxNumberOfFiles: 100,
            // 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 []
            allowedFileTypes: ['image/png', 'image/jpeg', 'image/jpg', 'image/bmp'],
            // 超时时间,默认为 10 秒
            timeout: 30000 // 30 秒
          }
        }
      },
      originalImgs: [], // 初始图片
      insertedImgs: [] // 数据库新增图片
    }
  },
  methods: {
    onCreated (editor) {
      this.editor = Object.seal(editor) // 【注意】一定要用 Object.seal() 否则会报错
    },
    setOriginalImgs (html) { // 父组件mounted时调用
      this.originalImgs = html.match(/evo-oss[0-9a-z/.-]*\?/g).map(item => item.replace('evo-oss/', '').replace('?', ''))
    },
    updateImgs () { // 父组件保存时调用
      let finalImgs = this.editor.getElemsByType('image').map(item => item.src.match(/evo-oss[0-9a-z/.-]*\?/g)[0].replace('evo-oss/', '').replace('?', ''))
      let allServerImgs = this.originalImgs.concat(this.insertedImgs)
      let wastedImgs = allServerImgs.filter(i => finalImgs.indexOf(i) === -1)
      this.originalImgs = [].concat(finalImgs)
      this.insertedImgs = []
      wastedImgs.length && imageDelete(wastedImgs)
      // 清空编辑历史,防止撤销被删除的图片
      this.editor.history.redos = []
      this.editor.history.undos = []
    },
    deleteWastedImgs () { // 父组件beforeDestroy时调用
      this.insertedImgs.length && imageDelete(this.insertedImgs)
    }
  },
  created () {
    this.editorConfig.MENU_CONF.uploadImage.customUpload = async (image, insertFn) => {
      // image 即选中的文件
      // 自己实现上传,并得到图片 url alt href
      const form = new FormData()
      form.append('image', image)
      let res = await imageUpload(form)
      if (res.success) {
        console.log('上传了', res.data)
        this.insertedImgs.push(res.data)
        insertFn(`/evo-apigw/evo-oss/${res.data}?token=${localStorage.getItem('accessToken')}`, '加载失败')
      }
    }
  },
  beforeDestroy () {
    console.log('RichEditor beforeDestroy')
    const editor = this.editor
    if (editor == null) return
    editor.destroy() // 组件销毁时,及时销毁 editor ,重要!!!
  }
}
</script>

<style src="@wangeditor/editor/dist/css/style.css"></style>
<style lang="less" scoped>
.root {
  position: relative;
}
.area {
  display: inline-block;
  vertical-align: top;
  max-width: 135px;
  text-align: justify;
  color: rgb(140, 140, 140);
}
.editor {
  display: inline-block;
  // width: 1300px;
  width: 330px;
  height: 700px;
  overflow-y: scroll;
  border: 1px solid rgb(204, 204, 204);
  border-radius: 5px;
}
.preview {
  width: 330px;
  vertical-align: top;
  padding: 16px;
}
.editor-area {
  margin: 0 auto;
  // width: fit-content;
  margin-top: 10px;
  display: flex;
  justify-content: space-between;
}
</style>

;