vue ckeditor5 富文本使用及自定义阿里上传

1、npm 包安装 

npm i -s @ckeditor/ckeditor5-build-decoupled-document @ckeditor/ckeditor5-vue2

2、引入

在vue main.js或者nuxt plugins文件夹下的文件中

import Vue from 'vue'
import '@ckeditor/ckeditor5-build-decoupled-document/build/translations/zh-cn'
import CKEditor from '@ckeditor/ckeditor5-vue2'

Vue.use(CKEditor)

3、富文本组件定义

<template>
  <div
    ref="editorContent"
    style="height: calc(100% - 2.5rem)"
    class="overflow-hidden z-50"
  >
    <div id="toolbar-container"></div>
    <ckeditor
      ref="editor"
      v-model="editorStr"
      style="height: calc(100% - 3rem)"
      :editor="editor"
      placeholder="请编辑消息内容"
      :config="config"
      @ready="onEditorReady"
    />
  </div>
</template>

<script>
import DecoupledEditor from '@ckeditor/ckeditor5-build-decoupled-document'
import UploadAdapter from '@/components/UploadAdapter' // 自定义上传
import { mapActions } from 'vuex'
export default {
  name: 'Editor',
  model: {
    prop: 'content',
    event: 'change',
  },
  props: {
    content: {
      type: String,
      default: '',
    },
  },
  data() {
    return {
      editor: DecoupledEditor,
      showPreview: false,
      previewMsg: {},
      config: {
        // removeDialogTabs: 'image:advanced;image:Link',
        language: 'zh-cn',
        previewText: '',
        // removePlugins: ['Table', 'BlockQuote', 'indent'],
        extraPlugins: [],
        toolbar: {
          items: [
            'undo',
            'redo',
            '|',
            'heading',
            '|',
            'fontfamily',
            'fontsize',
            'fontColor',
            'fontBackgroundColor',
            '|',
            'bold',
            'italic',
            'underline',
            'strikethrough',
            '|',
            'alignment',
            'uploadImage',
            '|',
            'numberedList',
            'bulletedList',
            '|',
            'outdent',
            'indent',
            '|',
            'link',
            'blockquote',
            'insertTable',
            'mediaEmbed',
          ],
        },
      },
      editorStr: '',
      el: '',
    }
  },
  watch: {
    content(val) {
      this.editorStr = val
    },
    editorStr(val) {
      this.$emit('change', val)
    },
  },
  mounted() {},
  methods: {
    ...mapActions(['upload']),
    onEditorReady(editor) {
      const that = this
      document
        .querySelector('#toolbar-container')
        .appendChild(editor.ui.view.toolbar.element)
      window.editor = editor
      that.editorStr = that.content
      // console.log(
      //   editor,
      //   '》》》》',
      //   Array.from(editor.ui.componentFactory.names())
      // )
      editor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
        // 将当前vue对象挂载到loader,使得自定义上传可以访问vue对象中的上传方法及其他属性
        loader.that = that
        return new UploadAdapter(loader)
      }
    },
  },
}
</script>
<style>
.ck.ck-editor__main {
  height: calc(100% - 2.5rem);
}
.ck.ck-editor {
  height: 100%;
}
.ck-editor__editable {
  height: 100%;
  overflow-x: auto;
}
.ck.ck-editor__editable_inline {
  border: #e2e3e5 solid 1px;
  border-top: 0;
}
.ck ck-balloon-rotator {
  z-index: 199999;
}
</style>

在components自定义上传UploadAdapter.js

/**
 * 自定义上传图片插件
 */
class UploadAdapter {
  constructor(loader) {
    this.loader = loader
  }

  async upload() {
    const file = await this.loader.file
    const { that } = this.loader
    const date = that.$moment().format('YYYY-MM-DD')// vue全局属性
    const path = `/images/notice/${date}/${file.name}`
    // 方法返回数据格式: {default: "url"}
    // eslint-disable-next-line no-async-promise-executor
    return new Promise(async (resolve, reject) => {
      try {
         // 阿里云oss上传封装的upload方法
        const { code, url, msg } = await that.upload({ file, path })
        if (code === 0) resolve({ default: url })
        else reject(msg)
      } catch (e) {
        reject(e)
      }
    })
  }
}

export default UploadAdapter

在 store.js actions 中定义upload上传

import crypto from 'crypto'
import OSS from 'ali-oss'

export const actions = {
  md5(ctx, val) {
    const md5 = crypto.createHash('md5')
    md5.update(val)
    return md5.digest('hex')
  },
  // 获取oss上传信息
  async ossToken({ dispatch, state, commit }) {
    const format = 'YYYY-MM-DD HH:mm'
    const now = this.$moment().format(format)
    const { Expiration = '' } = state.sts
    const expire = this.$moment(Expiration).format(format)
    if (Expiration && expire > now) return { code: 0, result: state.sts }
    const data = await dispatch('get', { url: '/api/oss/sts' })
    commit('setSts', data.result || {})
    return data
  },
  // oss 上传文件
  async upload({ dispatch }, { path, file }) {
    const data = await dispatch('ossToken')
    if (data.code > 0) return data
    else {
      const {
        AccessKeyId: accessKeyId,
        AccessKeySecret: accessKeySecret,
        SecurityToken: stsToken,
        region,
        bucket,
      } = data.result
      const client = new OSS({
        region,
        accessKeyId,
        accessKeySecret,
        stsToken,
        bucket,
      })
      try {
        const { name } = await client.put(path, file)
        return {
          code: 0,
          url: `http://${bucket}.${region}.aliyuncs.com/${name}`,
        }
      } catch (e) {
        return { code: 201, msg: e }
      }
    }
  },
  async get(ctx, { url, params = {} }) {
    //在vue main.js 中 store.$axios = axios,nuxt项目中不用处理
    const { data } = await this.$axios.get(url, { params })
    return data
  }
}

vue ckeditor5 富文本使用及自定义阿里上传

上一篇:所遇bug


下一篇:webpack学习---优化--多线程打包js(多用于babel中)