Componente de texto enriquecido del sistema de gestión de fondo Vue (1) tinymce

Componente de texto enriquecido del sistema de gestión de fondo Vue (1) tinymce

Introducción

Como uno de los componentes básicos más importantes del sistema de gestión en segundo plano, los componentes de texto enriquecido deben seleccionarse de fabricantes de texto enriquecido con menos pits. El tinymce que se usa aquí es hermoso y menos picado.

Confíe principalmente en las instrucciones (instale primero, se omiten los pasos)

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

tinymce: 5.0.8 El método para descargar el código fuente se usa directamente aquí. La descarga de Npm afecta en gran medida la velocidad de empaquetado, y también puede usar cdn

Dirección de descarga del sitio web oficial de Tinymce

texto

1. Descargue el código fuente de tinymce y colóquelo en la carpeta estática debajo de la carpeta pública generada por vue-cli 3, como se muestra en la figura
Inserte la descripción de la imagen aquí

Si necesita un paquete de idioma, descargue el archivo zh_CN.js por separado y colóquelo en la carpeta lang debajo de la carpeta tinymce_5.0.8

Dirección de descarga del sitio web oficial de zh_CN.js

2. Importar en el archivo html de entrada


<!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. Componentes Tinymce

Directorio de archivos

Inserte la descripción de la imagen aquí

src / componentes / 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 / componentes / 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 / componentes / 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. Utilice

<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. Efecto de uso
Inserte la descripción de la imagen aquí

Link de referencia

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

2. Documento chino de Tinymce

Supongo que te gusta

Origin blog.csdn.net/qq_39953537/article/details/100041453
Recomendado
Clasificación