Tinymce富文本编辑器添加自定义toolbar,二级菜单,自定义表单,签名

概要

Tinymce富文本编辑器插件,开发的自由表单、病历插件,文本的编辑和删除,自定义电子签名的插件

插件准备

“tinymce”: “^5.10.7”
项目时基于 Vue3.0、Vite、 Ant-Design-Vue、TypeScript

实现自定义插件步骤

一.自定义插件
1.基础配置
toolbar设置 control SignBtn 是自定义的
export const toolbar = [
‘control SignBtn fontsizeselect lineheight searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample’,
‘hr bullist numlist link preview anchor pagebreak insertdatetime media forecolor backcolor fullscreen’,
];
工具栏设置 control 是自定义的
export const plugins = [
‘control advlist anchor autolink autosave code codesample directionality fullscreen hr insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textpattern visualblocks visualchars wordcount’,
];
const publicPath = import.meta.env.VITE_PUBLIC_PATH || ‘/’;
富文本文本显示的标签ID

中英文切换 const langName = computed(() => { const lang = useLocale().getLocale.value; return ['zh_CN', 'en'].includes(lang) ? lang : 'zh_CN'; }); options设置 ```javascript return { selector: `#${unref(tinymceId)}`, height, toolbar, menubar: 'file edit insert view format table', plugins, language_url: publicPath + 'resource/tinymce/langs/' + langName.value + '.js', // 引入public中的js文件 language: langName.value, branding: false, default_link_target: '_blank', link_title: false, object_resizing: false, auto_focus: true, skin: skinName.value, skin_url: publicPath + 'resource/tinymce/skins/ui/' + skinName.value, content_css: publicPath + 'resource/tinymce/skins/ui/' + skinName.value + '/content.min.css', // 引入public中的css文件 ...options, setup: (editor: Editor) => { editorRef.value = editor }, }; ```

2:注册自定义插件为自定义插件 注册按钮和注册菜单项

	// 注册自定义插件 control
	tinymce.PluginManager.add('control', function (editor) {
        // 为插件注册一个按钮
		  editor.ui.registry.addButton("control", {
		    icon: "non-breaking",
		    tooltip: "插入control",
		    onAction: function () {
		    // 点击按钮,需要执行的方法 dialogOpener()是封装的打开自由表单的方法
            dialogOpener();
		    },
		  })
		
		  // 为插件注册一菜单项
		  editor.ui.registry.addMenuItem("control", {
		    icon: "non-breaking",
		    text: "插入control",
		    onAction: function () {
		    },
		  })
		// 返回插件的元数据
        return {
          getMetadata: function () {
            return {
              name: 'control',
              url: 'https://www.cinea.cc/',
            };
          },
        };
      });

效果如下
在这里插入图片描述

3.点击按钮弹出自由表单,

	// 注册自定义插件 control
	tinymce.PluginManager.add('control', function (editor) {
        dialogConfig.value = Dialog(editor);
        const dialogOpener = () => {
        // 打开弹窗
          return editor.windowManager.open(dialogConfig.value);
        };
      })
  // 弹框配置 表单内容配置
    let Dialog = (editor) => {
      return {
        title: '添加表单', // The dialog's title - displayed in the dialog header
        body: {
          type: 'panel', // The root body type - a Panel or TabPanel
          items: [
            // A list of panel components
            {
              type: 'selectbox',
              name: 'select',
              label: '控件',
              items: [
                { value: 'input', text: 'input' },
                { value: 'date', text: 'date' },
                { value: 'radio', text: 'radio' },
                { value: 'checkbox', text: 'checkbox' },
                { value: 'select', text: 'select' },
                // { value: 'textarea', text: 'textarea' },
              ],
            },
            {
              type: 'input', //类型可以是 checkbox, input, selectbox, textarea and urlinput
              name: 'name',
              label: '字段名称',
            },
          ],
        },
        //初始值
        // initialData: {
        //   name: '2'
        // },
        buttons: [
          // A list of footer buttons
          {
            type: 'cancel',
            name: 'closeButton',
            text: '取消',
          },
          {
            type: 'submit',
            primary: true,
            text: '确认',
          },
        ],
        // radio select checkbox 添加子项 设置key和value
        onAction: dialogFn.onAction(editor),
        // 切换表单控件
        onChange: dialogFn.onChange(editor),
        // 表单提交方法
        onSubmit: dialogFn.onSubmit(editor),
      };
    };
图片如下

在这里插入图片描述

4.填完表单,点击保存,在文本上下文中插入设置的HTML标签
①:根据选择标签类型,显示不一样的设置内容
表单change事件

	②:点击上图的确认按钮,将标签展示在上下文中

在这里插入图片描述
表单提交时间
5. 点击文本上下文显示编辑和删除的tooltip文字提示,并且点击编辑按钮弹出表单,返显HTML标签设置的属性,进行编辑

	// 添加悬浮 上下文工具栏
      editor.ui.registry.addContextToolbar('editcontrol', {
        //浮层的触发条件
        predicate: function (node) {
          return node.className === 'control';
          // return node.nodeName.toLowerCase() === 'p'
        },
        items: 'changecontrol removecontrol', //显示的工具列表
        position: 'selection', //工具栏放置位置  selection node line
        // scope: 'node',
      });
      // 浮层注册编辑和删除按钮
      editor.ui.registry.addButton('changecontrol', {
        icon: 'edit-block',
        tooltip: '编辑控件',
        onAction: () => {
        	// 打开弹窗并返显表单数据
          let data = editor.selection.getNode().getAttribute('data-control');
          data = JSON.parse(data);
          dialogConfig.value = Dialog(editor);
          dialogConfig.value.body = data.body;
          dialogConfig.value.title = '编辑控件';
          dialogConfig.value.initialData = data.initialData;
          editor.windowManager.open(dialogConfig.value);
        },
      });
      editor.ui.registry.addButton('removecontrol', {
        icon: 'remove',
        tooltip: '删除控件',
        onAction: (editor) => {
          editor.selection.setContent('');
          editor.dispatch('contexttoolbar-hide', { toolbarKey: 'editcontrol' });
          console.log(arguments);
        },
      });

效果如下
在这里插入图片描述

实现自定义插件步骤

  1. 注册工具栏按钮及图标 在options的setup中设置
  // 注册图标
  editor.ui.registry.addIcon(
   'shopping-cart',
            `<svg viewBox="0 0 1024 1024" data-icon="shopping-cart" width="1.5em" height="1.5em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M922.9 701.9H327.4l29.9-60.9 496.8-.9c16.8 0 31.2-12 34.2-28.6l68.8-385.1c1.8-10.1-.9-20.5-7.5-28.4a34.99 34.99 0 0 0-26.6-12.5l-632-2.1-5.4-25.4c-3.4-16.2-18-28-34.6-28H96.5a35.3 35.3 0 1 0 0 70.6h125.9L246 312.8l58.1 281.3-74.8 122.1a34.96 34.96 0 0 0-3 36.8c6 11.9 18.1 19.4 31.5 19.4h62.8a102.43 102.43 0 0 0-20.6 61.7c0 56.6 46 102.6 102.6 102.6s102.6-46 102.6-102.6c0-22.3-7.4-44-20.6-61.7h161.1a102.43 102.43 0 0 0-20.6 61.7c0 56.6 46 102.6 102.6 102.6s102.6-46 102.6-102.6c0-22.3-7.4-44-20.6-61.7H923c19.4 0 35.3-15.8 35.3-35.3a35.42 35.42 0 0 0-35.4-35.2zM305.7 253l575.8 1.9-56.4 315.8-452.3.8L305.7 253zm96.9 612.7c-17.4 0-31.6-14.2-31.6-31.6 0-17.4 14.2-31.6 31.6-31.6s31.6 14.2 31.6 31.6a31.6 31.6 0 0 1-31.6 31.6zm325.1 0c-17.4 0-31.6-14.2-31.6-31.6 0-17.4 14.2-31.6 31.6-31.6s31.6 14.2 31.6 31.6a31.6 31.6 0 0 1-31.6 31.6z"></path></svg>`,
          );
          // 注册一个自定义的按钮
          editor.ui.registry.addButton('CardBtn', {
            icon: `shopping-cart`,
            onAction: function (_) {
            // 点击按钮,插入上下文的签名按钮 
              let str = `<div class='goodsBox'><div class='goodsBtn' οnclick='goodClick('11111111')'>签名 </div></div>&nbsp;`;
              editor.insertContent(str);
            },
          });
        },
  1. 引入签名插件
    点击签名按钮弹出引入的组件
    1:import signModal from ‘/@/components/Signature/components/signModal/index.vue’;
    2:在components中注册组件components: { signModal }
    3:在中引入
    4:在editor.ui.registry.addContextToolbar(‘editcontrol’, {})方法中设置签名弹窗的显示与隐藏
    在这里插入图片描述

技术细节

  • 表单提交的时候,表单控件总是复位。
  • 表单控件可以添加对表单样式的设置。
    踩坑①:签名按钮,点击事件失效 过查询资料后发现标签中支持的属性还需要去配置
 extended_valid_elements: 'a[class|target|href|onclick],div[class|onclick|id|style],link[rel|href]',

踩坑②:菜单栏显示二级项

//添加菜单改为 addMenuItem改为 addNestedMenuItem
editor.ui.registry.addNestedMenuItem('emoticons', {
  icon: 'emoticons',
   text: '插入control12',
   getSubmenuItems: function () {
     return [
     	// 子项设置
       {
         type: 'menuitem',
         text: 'My submenu item',
         onAction: function () {
           //子项设置点击事件
           alert('Submenu item clicked');
         },
       },
     ];
   },

参考资料

tinymce对外接口文档, api很全,有示例: (https://www.tiny.cloud/docs/ui-components/menuitems/)

小结

在开发电子病历需求过程中,调研了很多编辑器,决定在tinymce富文本编辑器的基础上进行二次开单
https://www.x-emr.cn/ 是成熟的电子病历,但是需要key,需要花钱
SoDiaoEditor电子病历编辑器更新至V3版本 index.js文件进行了加密打包,不能进行二次开发

  • 21
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值