tinymce 自定义插件

2,574 阅读2分钟

需求一 :是在题目中选中内容需要关联一个知识点,知识点是请求后台获取的数据,由于tinymce不支持搜索下拉列表,所以做了一个输入框,一个展示列表的下拉框,输入框输入值以后结果在下拉列表里面展示

需求二:点击a标签需要跳到相应知识点的链接内容

需求三:选中的知识点要在外面的知识点列表里面展示

注意: 由于selectbox数据更新但是页面不会更新(这个暂时没有找到解决方案),所以使用的是listbox这个也有一个小缺点,就是搜索出来是没有结果的,此时数据是空,但是页面上依然会展示第一条(这个也不知道怎么解决),页面也没有selectbox样式好看,但是解决了数据更新页面不更新的问题

生成一个插件

let choosedTery = ""
let editKnowledgeList = [];
let majorId = "";
let timer = null
function uuid() {
    var s = [];
    var hexDigits = "0123456789abcdef";
    for (var i = 0; i < 36; i++) {
        s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
    }
    s[14] = "4";  // bits 12-15 of the time_hi_and_version field to 0010
    s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);  // bits 6-7 of the clock_seq_hi_and_reserved to 01
    s[8] = s[13] = s[18] = s[23] = "-";

    var uuid = s.join("");
    return uuid;
}
tinymce.PluginManager.add('example', function (editor) {
    var openDialog = function () {
        return editor.windowManager.open({
            title: '绑定知识点',
            body: {
                type: 'panel',
                items: [
                    {
                        type: 'input',
                        name: 'catdata',
                        label: '搜索',
                        placeholder: '请输入搜索内容',
                    },
                    {
                        type: 'listbox',
                        name: 'choosydata',
                        label: '知识点',
                        placeholder: '请选择Theroy',
                        items: editKnowledgeList||[]
                    }
                ]
            },
            buttons: [
                {
                    type: 'cancel',
                    text: '取消',
                },
                {
                    type: 'submit',
                    text: '确定',
                    primary: true
                }
            ],
            onSubmit: function (api, details) {
                var data = api.getData();
                //点击确定的时候给当前选中内容绑定知识点
                if(editKnowledgeList && editKnowledgeList.length){
                    let choosedValue = ""
                    editKnowledgeList.forEach(item => {
                        if (item.value === data.choosydata) {
                            choosedValue = item.text
                        }
                    })
                    editor.insertContent(`<a onclick="clickBlank();return false" data-theroyid="${data.choosydata}" data-id="${choosedValue}" target="_blank" href="后台要跳转的链接?keyWord=${tinymce.activeEditor.selection.getContent({
                        format:
                            'text'
                    })}&knowledgeId=${data.choosydata}&keyWordId=${new Date().getTime()}${uuid()}">${tinymce.activeEditor.selection.getContent({
                        format:
                            'text'
                    })}</a>`);
                    choosedTery = data.choosydata
                }
                api.close();
                /*
                当前选中的内容
                ${tinymce.activeEditor.selection.getContent({
                        format:
                            'text'
                    })}
                */
            },
            onChange: async function (dialogApi, details) {
                var data = dialogApi.getData();
                //根据输入框的内容触发搜索知识点列表
                clearTimeout(timer)
                timer = setTimeout(async () => {
                    let res = await getMajorByUser({ majorId, keyword: data.catdata });
                    if (res.status === 200) {
                        if(res.body && res.body.length){
                        editKnowledgeList = res.body
                        this.body.items[1].items = res.body
                        }else{
                            editKnowledgeList = []
                            this.body.items[1].items = []
                        }
                    }
                }, 300)
            },
        });
    };
    /* Add a button that opens a window */
    editor.ui.registry.addButton('example', {
        text: '绑定知识点',
        // icon: 'link',
        onAction: function () {
            /* Open window */
            openDialog();
        }
    });
    /* Adds a menu item, which can then be included in any menu via the menu/menubar configuration */
    editor.ui.registry.addMenuItem('example', {
        text: 'Example plugin',
        onAction: function () {
            /* Open window */
            openDialog();
        }
    });
    /* Return the metadata for the help plugin */
    return {
        getMetadata: function () {
            return {
                name: 'Example plugin',
                url: 'http://exampleplugindocsurl.com'
            };
        }
    };
});


注册插件

//在plugins注册插件,在toolbar注册按钮,由于我们使用的是悬浮工具栏quickbars_selection_toolbar,这个需要注册插件

import tinymce from "tinymce/tinymce";
import "tinymce/plugins/quickbars";//悬浮工具栏

mounted() { 
    tinymce.init({}); 
}, 
computed: { 
    init() { 
        return { 
             quickbars_selection_toolbar:
                    "example",
          plugins:['quickbars','example'],
          setup: (editor) => {
                    editor.ui.registry.addButton('customInsertButton', {
                        text: '',
                        icon: "horizontal-rule",
                        onAction: function (_) {
                            let a = `<img class="imgred" src="横线图片地址"></img>`

                            editor.insertContent(a);
                        },
                    });
                },
        }  
    } 
 }

效果

image.png

查看当前绑定的知识点

image.png

点击a标签跳到相应知识点链接

   <div
      class="editors id"
      @click="changeStem"
      v-html="stemValue"
      tabIndex="0"
    ></div>
    
    
    //根据后台返回的链接跳转
   async changeStem(e){
        if(e.target.localName === 'a'){

         let obj = this.urlArgs(e.target.href)
           if(this.link === ''||this.link===undefined){
              e.returnValue=false;

           }
           let res = await getTheroyLink(obj.knowledgeId)
           if(res.status === 200){
             this.link = res.body.msg
           }
           if(this.link){
               e.target.href = this.link+'&knowledgeId='+obj.knowledgeId
           }else{
               e.returnValue=false;
           }
        }
     },
   urlArgs(href){
         var args = {};
         var query = href.substring(1);//查找到查询串,去掉?
         var pairs = query.split('&');//根据“&”符合将查询字符部分分隔开
         for(var i=0;i<pairs.length;i++){
         var pos = pairs[i].indexOf('=');//"查找name=value"
         if(pos == -1) continue;//如果没有找到的话就跳过
         var name = pairs[i].substring(0,pos);//提取name
         var value = pairs[i].substring(pos+1);//提取value
         args[name] = value;
         }
         return args;
     },

选中的知识点要在外面的知识点列表里面展示

  watch: {
  //showStem是一个Boolean,判断编译器显示不显示,true不显示编译器
     showStem(value) {
        if (value) {
            if (!choosedTery) return
            let arr = [...this.topic.knowledge, choosedTery]
            this.topic.knowledge = [...new Set(arr)]
            //this.topic.knowledge外面知识点列表绑定的值
            this.realTimeSave()
        } else {
            // choosedTery = ""
        }
    },
}