自学内容网 自学内容网

点击文本将内容填入tinymce-vue 富文本编辑器的光标处

富文本编辑器组件

<template>
  <div ref="tinymceBox" class="tinymce-box">
    <Editor id="myEditor" v-model="contentValue" :init="init" :disabled="disabled" @blur="inputBlur" @click="onClick" />
  </div>
</template>

<script>
const api = import.meta.env.VITE_APP_API_FILE
import { post } from '@/services/http'

// 引入tinymce编辑器
import Editor from '@tinymce/tinymce-vue'

// 引入node_modules里的tinymce相关文件文件
import tinymce from 'tinymce/tinymce' // tinymce默认hidden,不引入则不显示编辑器
import 'tinymce/themes/silver' // 编辑器主题,不引入则报错
import 'tinymce/icons/default' // 引入编辑器图标icon,不引入则不显示对应图标

// 引入编辑器插件(基本免费插件都在这儿了)
// import 'tinymce/plugins' //高级列表
// import 'tinymce/plugins/anchor' //锚点
// import 'tinymce/plugins/autolink' //自动链接
// import 'tinymce/plugins/autoresize' //编辑器高度自适应,注:plugins里引入此插件时,Init里设置的height将失效
// import 'tinymce/plugins/autosave' //自动存稿
// import 'tinymce/plugins/charmap' //特殊字符
import 'tinymce/plugins/code' // 编辑源码
import 'tinymce/plugins/codesample' // 代码示例
import 'tinymce/plugins/directionality' // 文字方向
// import 'tinymce/plugins/emoticons' //表情
// import 'tinymce/plugins/fullpage' //文档属性
import 'tinymce/plugins/fullscreen' // 全屏
// import 'tinymce/plugins/help' //帮助
import 'tinymce/plugins/hr' // 水平分割线
import 'tinymce/plugins/image' // 插入编辑图片
// import 'tinymce/plugins/importcss' //引入css
// import 'tinymce/plugins/insertdatetime' //插入日期时间
import 'tinymce/plugins/link' // 超链接
import 'tinymce/plugins/lists' // 列表插件
import 'tinymce/plugins/media' // 插入编辑媒体
// import 'tinymce/plugins/nonbreaking' //插入不间断空格
// import 'tinymce/plugins/pagebreak' //插入分页符
// import 'tinymce/plugins/paste' //粘贴插件

import 'tinymce/plugins/preview' // 预览
import 'tinymce/plugins/print' // 打印
// import 'tinymce/plugins/quickbars' //快速工具栏
// import 'tinymce/plugins/save' //保存
// import 'tinymce/plugins/searchreplace' //查找替换
// import 'tinymce/plugins/spellchecker'  //拼写检查,暂未加入汉化,不建议使用
// import 'tinymce/plugins/tabfocus' //切入切出,按tab键切出编辑器,切入页面其他输入框中
import 'tinymce/plugins/table' // 表格
// import 'tinymce/plugins/template' //内容模板
// import 'tinymce/plugins/textcolor' //文字颜色
// import 'tinymce/plugins/textpattern' //快速排版
// import 'tinymce/plugins/toc' //目录生成器
import 'tinymce/plugins/visualblocks' // 显示元素范围
// import 'tinymce/plugins/visualchars' //显示不可见字符
import 'tinymce/plugins/wordcount' // 字数统计
export default {
  name: 'TEditor',
  components: {
    Editor
  },
  props: {
    value: {
      type: String,
      default: ''
    },
    disabled: {
      type: Boolean,
      default: false
    },
    plugins: {
      type: [String, Array],
      // powerpaste
      default:
        'print code codesample preview directionality visualblocks fullscreen image link media table hr lists wordcount indent2em wordlimit'
    },
    toolbar: {
      type: [String, Array],
      // undo redo media visualblocks fontselect 隐藏工具
      default:
        'fullscreen code codesample restoredraft forecolor backcolor bold italic underline strikethrough link | formatselect fontsizeselect lineheight | alignleft aligncenter alignright alignjustify | indent2em outdent indent | bullist numlist | blockquote removeformat | table image charmap hr print preview | '
    },
    fileType: {
      type: String,
      default: ''
    },
    supportBase64: {
      type: Boolean,
      default: true
    },
    maxLimit: {
      type: Number,
      default: 500
    },
    placeholder: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      dom: null,
      init: {
        language_url: '/tinymce/langs/zh_CN.js', // 引入语言包文件
        language: 'zh_CN', // 语言类型
        skin_url: '/tinymce/skins/ui/oxide', // 皮肤:浅色
        // skin_url: '/tinymce/skins/ui/oxide-dark',//皮肤:暗色

        plugins: this.plugins, // 插件配置
        toolbar: this.toolbar, // 工具栏配置,设为false则隐藏
        menubar: false, // 菜单栏配置,设为false则隐藏
        external_plugins: {
          // powerpaste: `/tinymce/powerpaste/plugin.min.js`,
          indent2em: `/tinymce/indent2em/plugin.min.js`,
          wordlimit: `/tinymce/wordlimit/plugin.min.js`
        },

        fontsize_formats: '12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 48px 56px 72px', // 字体大小
        font_formats: `思源宋体='思源宋体';微软雅黑='微软雅黑';宋体='宋体';黑体='黑体';仿宋='仿宋';楷体='楷体';隶书='隶书';幼圆='幼圆';Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings`, // 字体样式
        lineheight_formats: '0.5 0.8 1 1.2 1.5 1.75 2 2.5 3 4 5', // 行高配置,也可配置成"12px 14px 16px 20px"这种形式

        // height: 400, //注:引入autoresize插件时,此属性失效
        min_height: 300,
        max_height: 500,
        toolbar_mode: 'sliding',
        placeholder: this.placeholder || '在这里输入描述',
        branding: false, // tiny技术支持信息是否显示
        resize: true, // 编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可,注意引号
        // statusbar: false,  //最下方的元素路径和字数统计那一栏是否显示
        elementpath: false, // 元素路径是否显示

        content_style: 'img {max-width:100%;} .mce-item-anchor {display:none !important}', // 直接自定义可编辑区域的css样式
        content_css: 'tinymce/skins/content/default/content.css', // 以css文件方式自定义可编辑区域的css样式,css文件需自己创建并引入

        // images_upload_url: '/apib/api-upload/uploadimg',  //后端处理程序的url,建议直接自定义上传函数image_upload_handler,这个就可以不用了
        // images_upload_base_path: '/demo',  //相对基本路径--关于图片上传建议查看--http://tinymce.ax-z.cn/general/upload-images.php
        wordlimit: {
          max: this.maxLimit, // 最多可以输入多少字
          spaces: false, // 是否含空格
          isInput: false, // 是否在超出后还可以输入
          maxMessage: `超出最大输入字符数量,最多允许${this.maxLimit}个字符!`
        },
        setup(editor) {
          // 设置默认字体样式
          editor.on('init', function (e) {
            this.getBody().style.lineHeight = '2'
            this.getBody().style.fontFamily = '微软雅黑'
          })
        },
        urlconverter_callback: (url, node, onSave, name) => {
          if (node === 'img' && url.startsWith('blob:')) {
            tinymce.activeEditor && tinymce.activeEditor.uploadImages()
          }
          return url
        },
        // paste_preprocess: (editor, args) => {
        //     if (this.disabled) {
        //         args.content = ''
        //     }
        // },
        end_container_on_empty_block: true,
        powerpaste_html_import: 'merge',
        powerpaste_word_import: 'merge',
        powerpaste_allow_local_images: true,
        paste_data_images: true, // 图片是否可粘贴
        images_upload_handler: (blobInfo, success, failure) => {
          let file = null
          const fileSize = 3
          const fileType = ['jpg', 'png']
          if (blobInfo.blob() instanceof Blob) {
            file = new File([blobInfo.blob()], blobInfo.blob().name || 'image.png', { type: 'image/png' })
          } else {
            file = blobInfo.blob()
          }
          const suffix = file.name.substring(file.name.lastIndexOf('.') + 1).toLocaleLowerCase()
          const allowType = fileType.map(v => v.toLocaleLowerCase()).includes(suffix)
          const allowSize = file.size / 1024 / 1024 < fileSize
          if (!allowType) {
            failure('上传失败,仅支持上传JPG、PNG格式的图片')
          } else if (!allowSize) {
            failure(`上传失败,图片大小请控制在 ${fileSize}M 以内`)
          } else {
            const params = new FormData()
            params.append('file', file)
            params.append('type', this.fileType || 'product')

            const config = {
              headers: {
                'Content-Type': 'multipart/form-data',
                'Client-Type': 0
              }
            }

            const AuthorizationInfo = localStorage.getItem('AuthorizationInfo')
            if (AuthorizationInfo) {
              const { tokenHeader, tokenHead, token } = JSON.parse(AuthorizationInfo)
              config.headers[tokenHeader] = `${tokenHead} ${token}`
            }

            post(api, params, config, '/')
              .then(res => {
                success(res.url) // 上传成功,在成功函数里填入图片路径
              })
              .catch(() => {
                // 是否支持上传图片为base64格式
                if (!this.supportBase64) {
                  const imgReg = /<img.*?(?:>|\/>)/gi // 匹配图片中的img标签
                  this.contentValue = this.contentValue.replace(imgReg, (match, capture) => (match.indexOf('base64') == -1 ? match : ''))
                }
                failure('上传出错,服务器开小差了呢')
              })
          }
        }
      },
      contentValue: this.value
    }
  },
  watch: {
    value(newValue) {
      this.contentValue = newValue
    },
    contentValue(newValue) {
      this.$emit('input', newValue)
    }
  },
  mounted() {
    tinymce.init({})
  },
  methods: {
    // 添加相关的事件,可用的事件参照文档=> https://github.com/tinymce/tinymce-vue => All available events
    onClick(e) {
      this.$emit('onClick', e, tinymce)
    },
    // 清空内容
    clear() {
      this.contentValue = ''
    },
    // 失去焦点
    inputBlur() {
      this.$emit('blur')
    }
  }
}
</script>

<style lang="less" scoped>
.tinymce-box {
  min-height: 300px;
}
</style>

项目中引用
注意:要给组件加上id

  <TEditor
     id="myEditor"
     ref="tEditorRef"
     fileType="supply/hr/report"
     v-model:value="formState.emailContent"
     @input="e => (formState.emailContent = e)"
     :maxLimit="10000"
     placeholder="请输入邮件内容"
   />

// 点击标签
const changeLabel = item => {
  const editor = tinymce.get('myEditor')
  if (editor) {
    editor.focus()
    editor.selection.setContent(`<div>【${item}】</div>`)
  }
  state.labelCount++
  if (state.labelCount <= 2) {
    formState.emailSubject += `${item}`
  }
}

在这里插入图片描述


原文地址:https://blog.csdn.net/weixin_46060121/article/details/143629078

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!