tinymce 富文本限制字数 超出不显示

(function () {
    'use strict';

    let Tools = tinymce.util.Tools.resolve('tinymce.util.Tools');
    let global = tinymce.util.Tools.resolve('tinymce.PluginManager');

    let defaults = {
        // max: 0, // 最多可以输入多少字
        spaces: !1, // 是否含空格
        isInput: !1, // 是否在超出后还可以输入
        toast: null, // 自定义的提示方法, 默认用编辑器自带
    };

    class WordLimit {
        constructor(editor, options) {
            this.editor = editor;
            this.options = Tools.extend(defaults, options);

            var _this = this,
                oldContent = editor.getContent(),
                WordCount = editor.plugins.wordcount,
                preCount = 0,
                _wordCount = 0;

            editor.on('input paste undo redo Keyup ', function (e) {

                var content = editor.getContent() || e.content || '';

                if (!_this.options.spaces) { // 字数
                    _wordCount = WordCount.body.getCharacterCount();

                } else { // 不含空格字数
                    _wordCount = WordCount.body.getCharacterCountWithoutSpaces();
                }

                if (_wordCount > _this.options.max) {
                    preCount = _wordCount;
                    // 禁止再输入
                    if (_this.options.isInput == !1) {
                        // 内容超出还原
                        editor.setContent(oldContent);

                        // 还原后重新统计
                        if (!_this.options.spaces) {
                            _wordCount = WordCount.body.getCharacterCount();
                        } else {
                            _wordCount = WordCount.body.getCharacterCountWithoutSpaces();
                        }
                    }

                    editor.getBody().blur();
                    editor.fire('wordlimit', {
                        maxCount: _this.options.max,
                        wordCount: _wordCount,
                        preCount: preCount,
                        isPaste: (e.type === 'paste' || e.paste) || false
                    });
                }

                oldContent = editor.getContent();
            });
        }
    };

    function Plugin() {
        global.add('wordlimit', function (editor) {

            var options = editor.getParam('wordlimit', {}, 'object');

            if (!options && !options.max) {
                return !1;
            }

            if (typeof options.toast !== 'function') {
                options.toast = function (message) {
                    editor.notificationManager.open({
                        text: message,
                        type: 'error',
                        timeout: 3000,
                    });
                }
            }

            if (!editor.plugins.wordcount) {
                options.toast('请先在tinymce的plugins配置wordlimit之前加入wordcount插件');
                return !1;
            }

            editor.on('init', function (e) {
                new WordLimit(editor, options);
            });
        });
    }

    Plugin();

}());

1. 创建 WordLimit 文件  

2. 要在wordcount  字数统计插件下引入

3.配置 WordLimit     记得在 plugins 配置中引入

 wordlimit: {
    max: 10, // 最多可以输入多少字
    spaces: !1, // 是否含空格
    isInput: !1, // 是否在超出后还可以输入
    // 自定义的提示方法, 默认用编辑器自带
    toast: function (message: any) {
    }
  },
  init_instance_callback: (editor: any) => {
    
    editor.on('wordlimit', function (e: any) {
      var beyond = 0;
      if (e.wordCount > e.maxCount) {
        beyond = e.wordCount - e.maxCount;
      }
      // 可以吧alert换成自己的提示组件
      warnMsg('最多只能输入' + e.maxCount + '个字' + (beyond > 0 ? ',已超出' + beyond + '个字,超出部分请删除' : '。'));
    });
  },

完整代码

<template>
  <editor v-model="myValue" :init="init" :disabled="disabled" :id="tinymceId" ref="editorRef"></editor>
</template>

<script setup lang="ts">
import { warnMsg } from "@/utils/msg";
//JS部分
//在js中引入所需的主题和组件
import tinymce from "tinymce/tinymce";
import "tinymce/skins/content/default/content.css";
import Editor from "@tinymce/tinymce-vue";
import "tinymce/themes/silver";
import "tinymce/themes/silver/theme";
import "tinymce/icons/default"; //引入编辑器图标icon,不引入则不显示对应图标
//   import 'tinymce/models/dom' // 这里是个坑 一定要引入

//在TinyMce.vue中接着引入相关插件
import "tinymce/icons/default/icons";
import "tinymce/plugins/image"; // 插入上传图片插件
import "tinymce/plugins/media"; // 插入视频插件
import "tinymce/plugins/table"; // 插入表格插件
import "tinymce/plugins/lists"; // 列表插件
import "tinymce/plugins/link";
import "tinymce/plugins/wordcount"; // 字数统计插件
import "tinymce/plugins/code"; // 源码
import "tinymce/plugins/fullscreen"; //全屏
import "tinymce/plugins/searchreplace";
import "tinymce/plugins/preview";
import '@/utils/letterspacing'  // 间距插件
import '@/utils/wordlimit' // 字数插件
import { uploadImg } from "@/api/understand";
const emits = defineEmits(["getContent",]);
//这里我选择将数据定义在props里面,方便在不同的页面也可以配置出不同的编辑器,当然也可以直接在组件中直接定义
const props = defineProps({
  value: {
    type: String,
    default: () => {
      return "";
    },
  },
  baseUrl: {
    type: String,
    default: "",
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  plugins: {
    type: [String, Array],
    default:
      "link lists image code table wordcount preview fullscreen media searchreplace letterspacing wordlimit",
    // default:
    //   'print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template code codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount imagetools textpattern help emoticons autosave bdmap indent2em autoresize formatpainter axupimgs',
  }, //必填
  toolbar: {
    type: [String, Array],
    default:
      "undo redo  | bold italic underline | fontselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bdmap indent2em lineheight formatpainter axupimgs  image letterspacing| media| searchreplace  | bullist numlist | code",
    // default:
    //   ' cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | \
    // styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | \
    // table image media charmap emoticons hr pagebreak insertdatetime print preview | fullscreen | bdmap indent2em lineheight formatpainter axupimgs',
  }, //必填
});
//用于接收外部传递进来的富文本
let win: any = window;
const editorRef = ref(null);
const myValue = ref(props.value);
const tinymceId = ref(
  "vue-tinymce-" + +new Date() + ((Math.random() * 1000).toFixed(0) + "")
);
//定义一个对象 init初始化
const init = reactive({
  selector: "#" + tinymceId.value, //富文本编辑器的id,
  // icons_url: '/web-official-website-manage/icons/custom/icons.js', //自定义图标
  // icons: 'custom',
  language_url: "/web-official-website-manage/langs/zh-Hans.js",
  language: "zh-Hans",
  skin_url: "/web-official-website-manage/skins/ui/oxide",
  height: 500, //编辑器高度
  branding: false, //是否禁用“Powered by TinyMCE”
  menubar: true, //顶部菜单栏显示
  image_dimensions: true, //去除宽高属性
  plugins: props.plugins, //这里的数据是在props里面就定义好了的
  toolbar: props.toolbar, //这里的数据是在props里面就定义好了的
  toolbar_mode: 'sliding',
  font_formats:
    "Arial=arial,helvetica,sans-serif; 宋体=SimSun; 微软雅黑=Microsoft Yahei; Impact=impact,chicago;", //字体
  fontsize_formats: "11px 12px 14px 16px 18px 24px 30px 36px 48px 64px 72px", //文字大小
  // paste_convert_word_fake_lists: false, // 插入word文档需要该属性
  paste_webkit_styles: "all",
  paste_merge_formats: true,
  nonbreaking_force_tab: false,
  paste_auto_cleanup_on_paste: false,
  file_picker_types: "media",
  setup: function (editor: any) {
    editor.ui.registry.addIcon(
      "image",
      `<svg t="1664002320321" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4420" width="24" height="24"><path d="M125.9 185h772.2v653.9H125.9z" fill="#1F53CC" p-id="4421"></path><path d="M164.7 217.2h694.6v516.7H164.7z" fill="#FECD44" p-id="4422"></path><path d="M458.9 734l-8.6-43.8-101.5-102.8-135 146.6z" fill="#FC355D" p-id="4423"></path><path d="M306.9 348.7m-66.7 0a66.7 66.7 0 1 0 133.4 0 66.7 66.7 0 1 0-133.4 0Z" fill="#FFFFFF" p-id="4424"></path><path d="M384.6 734h474.7V608.8L687.8 400.1z" fill="#FC355D" p-id="4425"></path><path d="M422.5 662l-37.9 72 52.1-57.5z" fill="#BF2847" p-id="4426"></path><path d="M302.5 778.9h418.9v16.7H302.5z" fill="#00F0D4" p-id="4427"></path></svg>`
    );
  },
  content_css: "/web-official-website-manage/skins/content/default/content.css", //以css文件方式自定义可编辑区域的css样式,css文件需自己创建并引入
  wordlimit: {
    max: 10, // 最多可以输入多少字
    spaces: !1, // 是否含空格
    isInput: !1, // 是否在超出后还可以输入
    // 自定义的提示方法, 默认用编辑器自带
    toast: function (message: any) {
    }
  },
  init_instance_callback: (editor: any) => {
    
    editor.on('wordlimit', function (e: any) {
      var beyond = 0;
      if (e.wordCount > e.maxCount) {
        beyond = e.wordCount - e.maxCount;
      }
      // 可以吧alert换成自己的提示组件
      warnMsg('最多只能输入' + e.maxCount + '个字' + (beyond > 0 ? ',已超出' + beyond + '个字,超出部分请删除' : '。'));
    });
  },
  //图片上传
  // images_upload_url: "/localFile/uploadFile",
  images_upload_handler: (blobInfo: any, progress: any, failure: any, success: any) =>
    new Promise(async (resolve, reject) => {
      if (blobInfo.blob().size / 1024 / 1024 > 2) {
        // reject({ message: "上传失败,图片大小请控制在 2M 以内", remove: true });
        failure('上传失败,图片大小请控制在 2M 以内')
        return;
      } else {
        const ph = win.configs.IMG_URL;
        let params = new FormData();
        params.append("file", blobInfo.blob());
        const res: any = await uploadImg(params);
        if (res.code == 200) {
          progress(ph + res.data); //上传成功,在成功函数里填入图片路径
        } else {
          reject("HTTP Error: 上传失败" + res.data.code);
          return;
        }
      }
    }),

  // 文件上传  需要的话添加
  // 上传视频
  file_picker_callback: (callback: any, value: any, meta: any) => {
    if (meta.filetype == 'media') {
      // callback('movie.mp4', { source2: 'alt.ogg', poster: 'image.jpg' });
      let input = document.createElement('input');
      input.setAttribute('type', 'file');
      input.setAttribute('accept', '.mp3, .mp4');
      input.click();
      input.onchange = function (v: any) {
        // console.log(v.target.files[0]); //视频文件信息   上传即可    规定视频格式大小需重写逻辑  获取视频时长
      }
    }
  }
});
//监听外部传递进来的的数据变化
watch(
  () => props.value,
  () => {
    myValue.value = props.value;
    emits("getContent", myValue.value);
  }
);
//监听富文本中的数据变化
watch(
  () => myValue.value,
  () => {
    emits("getContent", myValue.value);
  }
);

//在onMounted中初始化编辑器
onMounted(() => {
  tinymce.init({});
});
</script>
<style>
.tox-tinymce {
  width: 100%;
  touch-action: none !important;
}
</style>

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值