天天看點

vue背景管理系統富文本元件(一)tinymcevue背景管理系統富文本元件(一)tinymce

vue背景管理系統富文本元件(一)tinymce

簡介

富文本元件作為背景管理系統的最重要的基礎元件之一,一定要選擇坑比較少的富文本廠家。這裡使用的是好看又坑少的tinymce。

主要依賴說明 (先安裝,步驟略)

{
    "axios": "^0.18.0",
    "element-ui": "2.11.1",  
    "vue": "^2.6.10",    
    "vue-router": "^3.0.1"   
 }
           

tinymce:5.0.8 這裡直接采用下載下傳源碼的方式,npm下載下傳極大的影響打包速度,也可以使用cdn

tinymce官網下載下傳位址

正文

1.下載下傳tinymce源碼放在vue-cli 3生成的 public檔案夾下的static檔案夾下 ,如圖

vue背景管理系統富文本元件(一)tinymcevue背景管理系統富文本元件(一)tinymce

需要語言包的話,單獨下載下傳zh_CN.js檔案放在tinymce_5.0.8檔案夾下的lang檔案夾下

zh_CN.js官網下載下傳位址

2.在入口html檔案中導入

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="renderer" content="webkit" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
    />
    <meta name="description" content="<%= webpackConfig.name %>" />
    <meta name="robots" content="noindex,nofollow,noarchive" /> 
    <title>title</title>
  </head>
  <body>
    <script src="<%= BASE_URL %>static/tinymce_5.0.8/tinymce.min.js"></script>  
    <div id="app"></div> 
  </body>
</html>

           

3.元件Tinymce

檔案目錄

vue背景管理系統富文本元件(一)tinymcevue背景管理系統富文本元件(一)tinymce

src/components/Tinymce/index.vue

<template>
  <div class="tinymce-container editor-container" :class="{fullscreen:fullscreen}">
    <textarea :id="tinymceId" class="tinymce-textarea" />
    <div class="editor-custom-btn-container">
      <multiple-upload class="editor-upload-btn" @success="imageSuccess" />
    </div>
  </div>
</template>

<script>
import axios from 'axios'

 // MultipleUpload元件見 https://blog.csdn.net/qq_39953537/article/details/100039094

import MultipleUpload from '@/components/MultipleUpload'
import plugins from './plugins' // 見下文
import toolbar from './toolbar' // 見下文

// 上傳html片段接口根據自己項目更換
import { uploadHtml } from '@/api/upload'
export default {
  name: 'Tinymce',
  components: {
    MultipleUpload
  },
  props: {
    // 預設填充到富文本的html檔案
    html: {
      type: String,
      default: ''
    },
    toolbar: {
      type: Array,
      default() {
        return []
      }
    },
    menubar: {
      type: Boolean,
      default: false
    },
    height: {
      type: Number,
      default: 400
    }
  },
  data() {
    return {
      hasChange: false,
      hasInit: false,
      tinymceId: 'vue-tinymce-' + +new Date(),
      fullscreen: false,
      value: '',
      editorContent: ''
    }
  },
  watch: {
    value(val) {
      this.$nextTick(() =>
        window.tinymce.get(this.tinymceId).setContent(val || '')
      )
    },
    html(val) {
      if (this.isUrl) {
        this.loadUrl(val)
      }
    }
  },
  created() {
    if (this.html && this.html.startsWith('http')) {
      this.loadUrl(this.html)
    } else {
      this.value = this.html + ''
      this.editorContent = this.html + ''
    }
  },
  mounted() {
    this.initTinymce()
  },
  activated() {
    this.initTinymce()
  },
  deactivated() {
    this.destroyTinymce()
  },
  destroyed() {
    this.destroyTinymce()
  },
  methods: {
    initTinymce() {
      window.tinymce.init({
        fontsize_formats: '12px 14px 16px 18px 20px 24px 36px',
        language: 'zh_CN',
        language_url: '/static/tinymce_5.0.8/langs/zh_CN.js',
        selector: `#${this.tinymceId}`,
        height: this.height,
        body_class: 'panel-body ',
        object_resizing: true,
        toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
        menubar: this.menubar,
        plugins: plugins,
        end_container_on_empty_block: true,
        powerpaste_word_import: 'clean',
        code_dialog_height: 450,
        code_dialog_width: 1000,
        advlist_bullet_styles: 'square',
        advlist_number_styles: 'default',
        default_link_target: '_blank',
        link_title: false,
        init_instance_callback: editor => {
          if (this.value) {
            editor.setContent(this.value)
          }
          this.hasInit = true
          editor.on('NodeChange Change KeyUp SetContent', () => {
            this.hasChange = true
            this.$emit('input', editor.getContent())
            this.editorContent = editor.getContent()
          })
        },
        setup(editor) {
          editor.on('FullscreenStateChanged', e => {
            this.fullscreen = e.state
          })
        }
      })
    },
    destroyTinymce() {
      if (window.tinymce.get(this.tinymceId)) {
        window.tinymce.get(this.tinymceId).destroy()
      }
    },
    loadUrl(url) {
      if (url && url.length > 0) {
        axios
          .get(url)
          .then(response => {
            // 處理HTML顯示
            this.value = response.data
            this.editorContent = response.data
            this.$emit('subLoadUrlToHtml', response.data)
            this.$emit('input', response.data)
          })
          .catch(() => {
            this.value = '伺服器資料加載失敗,請重試!'
          })
      }
    },
    // 設定編輯器内容
    setContent(value) {
      window.tinymce.get(this.tinymceId).setContent(value)
    },
    // 擷取編輯器内容
    getContent() {
      window.tinymce.get(this.tinymceId).getContent()
    },
    // 圖檔上傳成功後填充到富文本編輯器
    async imageSuccess(urlList) {
      try {
        let imageTemplateList = ''
        urlList.forEach(item => {
          const image = `<img style="max-width:100%;" src="${item}">`
          imageTemplateList = imageTemplateList + image
        })
        window.tinymce.get(this.tinymceId).insertContent(imageTemplateList)
        this.$message({
          message: '上傳成功!',
          type: 'success'
        })
      } catch (error) {
        console.log(error)
        this.$message({
          message: error,
          type: 'error'
        })
      }
    },
    // 編輯器内容上傳到cos,調用傳回url
    async content2Url() {
      try {
        const res = await uploadHtml(this.editorContent)
        return res
      } catch (error) {
        this.$message({
          message: error.data.message,
          type: 'error'
        })
      }
    }
  }
}
</script>

<style lang='scss' >
#tinymce {
  background-color: blue;
  p {
    margin: 0;
  }
}
.tinymce-container {
  position: relative;
}
.tinymce-container >>> .mce-fullscreen {
  z-index: 10000;
}
.tinymce-textarea {
  visibility: hidden;
  z-index: -1;
}
.editor-custom-btn-container {
  position: absolute;
  right: 4px;
  top: 4px;
  /*z-index: 2005;*/
}
.fullscreen .editor-custom-btn-container {
  z-index: 10000;
  position: fixed;
}
.editor-upload-btn {
  display: inline-block;
}
// 隐藏底部logo欄
.mce-edit-area + .mce-statusbar {
  opacity: 0;
  height: 0;
}
</style>



           

src/components/Tinymce/plugins.js

const plugins = [
  'advlist anchor autolink autosave code codesample directionality emoticons fullscreen hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak  preview print save searchreplace spellchecker tabfocus table template  textpattern visualblocks visualchars wordcount paste'
]

export default plugins

           

src/components/Tinymce/toolbar.js

const toolbar = ['formatselect fontsizeselect forecolor backcolor bold italic underline strikethrough alignleft aligncenter alignright outdent indent    removeformat  hr undo redo']

export default toolbar

           

4.使用

<template>
    <div>
        <tinymce
        ref="tinymce"
        :height="500"
        :html="html"
        @input="getContent"
        />
    </div>
</template>

<script>
import AppCropper from '@/components/Cropper'
export default {
  name: 'GoodsForm',
  components: {
    AppCropper
  },
  data() {
    return {
      html: 'https://ebusiness-1255313385.cosbj.myqcloud.com/image/20190823/center2019082304054532.html',
      content:''
    }
  },
  methods: {
      // 擷取編輯器内容
    getContent(content) {
      this.content = content
    },
    // 編輯器内容轉換成線上url
    async getcontent2Url() {
      try {
        const htmlUrl =  await this.$refs.tinymce.content2Url()
        return htmlUrl
      } catch (error) {
        console.log(error)
      }
    }

  }
}
</script>
 
           

5.使用效果

vue背景管理系統富文本元件(一)tinymcevue背景管理系統富文本元件(一)tinymce

參考連結

1.https://github.com/PanJiaChen/vue-element-admin/blob/master/src/components/Tinymce/index.vue

2.tinymce中文文檔