0.3.8 • Published 1 year ago

askbot-ckeditor-plugin v0.3.8

Weekly downloads
-
License
ISC
Repository
-
Last release
1 year ago

ckeditor 在平台流程中扩展插件

富文本下述插件点击按钮之后均会向注册的监听函数发送事件,等待函数执行完成后回调 callback 编辑器将插入对应的内容.

/**
 * 定义监听函数
 */

const beforeButtonInsert = {
    event: 'BUTTON',
    process: function (event, callback) {
        let type = event.type; // 事件类型
        let param = event.param; // 各个事件param类型有所不同,参考下方实现
        console.log('beforeButtonInsert param:',event);
        let userinput = {
            "name": "按钮名",
            "event": "TO_NODE/TO_INTENT",
            "value": "xxx 节点ID/意图ID",
            "assignments":[
               {"webhookId":"1","key":"location[*].id","entity":"当前城市ID","_full_entity":[]},
               {"webhookId":"1","key":"location[*].name","entity":"当前城市名字","_full_entity":[]}
            ]
        }; // 根据type,param 进行 弹窗等方式获取用户输入,传递格式要求参考下方
        callback(userinput); // 回调用户输入
    }
};
const beforePlaceholderInsert = {
    event: 'PLACEHOLDER',
    process: function (event, callback) {

        console.log('beforePlaceholderInsert param:',event);
        // ...
        let userInput = {
            "name": "显示名称",
            "key": "性别"
        };
        callback(userInput);
    }
};
const beforeLoopBlockInsert = {
    event: 'LOOP',
    process: function (event, callback) {
        console.log('beforeLoopBlockInsert param:',event);
        // ...
        let userInput = {
            "name": "webhook数组类型返回值名称",
            "key": "webhook数组类型返回值key"
        };
        callback(userInput);
    }
};

Quick Start

文档待更新. 将插件打包至富文本编辑器中, 复文本编辑器代码地址 git@code.aliyun.com:guoran/ckeditor5.git 打包:

cd packages/ckeditor5-build-classic
cnpm install
./node_modules/.bin/webpack-cli  --mode production
// 实例富文本
ClassicEditor
    .create(document.querySelector('#editor'), {
        plugins: [Essentials, Paragraph, Heading, List, Bold,
            NotifyButton, NotifyList, NotifyPlaceholder  //引入插件
        ],
        toolbar: ['heading', '|', 'bold', 'italic', 'numberedList',
            'insertNotifyButton', 'insertNotifyList', 'insertNotifyPlaceholder'   // 注册工具栏
        ],
        askPluginListener: [beforeButtonInsert, beforePlaceholderInsert, beforeLoopBlockInsert]  // 注册监听
    })
    .then(editor => {
        console.log('Editor was initialized', editor);
        window.editor = editor;
    })
    .catch(error => {
        console.error(error.stack);
    });

Used In Vue

npm install --save @ckeditor/ckeditor5-vue @ckeditor/ckeditor5-build-classic
npm i askbot-ckeditor-plugin
import Vue from 'vue';
import CKEditor from '@ckeditor/ckeditor5-vue';

Vue.use( CKEditor );
<template>
    <div id="app">
        <ckeditor :editor="editor" :config="editorConfig"></ckeditor>
    </div>
</template>

<script>
    import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
    import NotifyList from './src/plugin-notify-list/notifylist';
    import NotifyPlaceholder from "./src/plugin-notify-placeholder/notifyplaceholder"
    import NotifyButton from "./src/plugin-notify-button/notifybutton";
    export default {
        name: 'app',
        data() {
            return {
                editor: ClassicEditor,
                editorConfig: {
                    toolbar: [ 'bold', 'italic', '|', 'link' ,
                            'insertNotifyButton', 'insertNotifyList', 'insertNotifyPlaceholder'   // 注册工具栏
                    ],
                    plugins: [ // 可以根据需要引入其他插件,如列表斜体插入图片等
                        NotifyButton, NotifyList, NotifyPlaceholder  //引入插件
                    ],
                    askPluginListener: [beforeButtonInsert, beforePlaceholderInsert, beforeLoopBlockInsert] // 注册监听
                    
                }
            };
        }
    }
</script>

按钮

listener event 参数:

{
  "type": "BUTTON"
}

回调传递数据,按钮名称name,事件类型event[TO_NODE,TO_INTENT],事件传递参数value :

{
"name": "按钮名",
"event": "TO_NODE/TO_INTENT",
"value": "xxx 节点ID/意图ID"
}

后端存储:

<button class="ask-ckeditor-button ck-widget ck-widget_selected" 
    __event="TO_NODE/TO_INTENT" 
    __value="xxx 节点ID/意图ID" __item_scope="location" 
    th:__assignments="'['+'{webhookId:1,entity:当前城市ID,key:'+${item.id}+'}'+','+'{webhookId:1,entity:当前城市名字,key:'+${item.name}+'}'+']'" 
    _name="按钮名" contenteditable="false">
    按钮名
</button>

最终渲染html:

<button class="ask-ckeditor-button ck-widget ck-widget_selected" 
    __event="TO_NODE/TO_INTENT" 
    __value="xxx 节点ID/意图ID" __item_scope="location" 
    __assignments="[{webhookId:1,entity:当前城市ID,key:001},{webhookId:1,entity:当前城市名字,key:北京}]" 
    _name="按钮名" contenteditable="false">
    按钮名
</button>

客户端 sdk 事件,需要开发客户端sdk对 class为 ask-ckeditor-button 的按钮注册事件:

// 伪代码
$("ask-ckeditor-button").onclick= function(dom) {

  // 发送设置变量请求
  sendAssignmentToSocket(dom.attr("__assignments"));

  // 向对话系统发送跳转请求
  sendGoToMessageToSocket(dom.attr("__event"),dom.attr("__value"),dom.attr("__model_key"),dom.attr("___index"));
};

占位符

listener event 参数:

{
  "type": "PLACEHOLDER",
  "param": {
     "source": "entity/webhook (占位符数据来源)",
     "model": {
        "webhook_id": "1",
        "list_key": "location"
     }
  }
}

Note: 当source为webhook时存在 model属性. 当在循环中插入占位符时,会将所属范围的 webhook_id和 list_key同时传递回去

回调传递数据,占位符显示名称name. 数据定位 key: source 为entity时为实体名字, 请求 source 为webhook时,值为 webhookId+返回值key(_2_name,下划线开头,下划线作为属性分割符):

{
    "name": "显示名称",
    "key": "性别"
}

model:

<placeholder type="entity" key="性别" name="显示名称">
</placeholder>

后端存储:

<!-- 实体类型 -->
<span class="ask-ckeditor-placeholder" __type="entity" __key="性别" th:text="性别">${显示名称}</span>

<!--webhook 类型-->
<span class="ask-ckeditor-placeholder" __type="webhook" __key="3.code" th:text="_3.code">${显示名称}</span>

<!--webhook 嵌套与循环中,属于所属域时 -->
<span class="ask-ckeditor-placeholder" __type="webhook" __key="3.location[*].name" th:text="item.name">${显示名称}</span>

渲染之后返回客户端:

<!-- 实体类型 -->
<span class="ask-ckeditor-placeholder" __type="entity" __key="性别" th:text="性别">渲染后名称</span>

<!--webhook 类型-->
<span class="ask-ckeditor-placeholder" __type="webhook" __key="3.code">渲染后名称</span>

<!--webhook 嵌套与循环中,属于所属域时 -->
<span class="ask-ckeditor-placeholder" __type="webhook" __key="3.location[*].name" th:text="_item.name">渲染后名称</span>

当前占位符无事件(20201013),不需要客户端sdk实现.

循环

listener event 参数:

{
  "type": "LOOP",
  "param": {
     "model": {
        "webhook_id": "1",
        "list_key": "location"
     }
  }
}

Note: 当在循环中插入循环时,会将所属范围的 webhook_id和 list_key同时传递回去

数据定位 key: webhookId+数组返回值key(2.location):

{
    "key": "2.location[*].alias",
    "name": "地址列表"
}

视图模型model:

<notifyList scope="1.location">
    <notifyListDescription name="地名"></notifyListDescription>
     <notifyListItem  foreach="1.location">
       
        <!-- 假设循环中放置了一个占位符    -->
        <placeholder type="webhook" key="1.location[*].name"/>
    </notifyListItem>
</notifyList>

后端存储:

<section class="ask-ckeditor-loop" __list_key="3.location">

  <span class="ask-ckeditor-desc">地名</span>
  <div class="ask-ckeditor-loop-item" __item_scope="3.location"  th:each="_item,_iterStat : ${_3.location}">
    <!--  假设存在一个占位符  -->
    <span class="ask-ckeditor-placeholder" __type="webhook" __key="3.location.name" th:text="_item.name">${显示名称}</span>
  </div>
</section>

渲染之后,假设 3.location存在三条数据 [{name:'北京'},name:'上海'},name:'广州'}]:

<section class="ask-ckeditor-loop" __list_key="3.location">

    <!-- 建议通过class设置样式隐藏作用域描述    -->
    <span class="ask-ckeditor-desc">地名</span>

    <div class="ask-ckeditor-loop-item" __item_scope="3.location">
        <span class="ask-ckeditor-placeholder" __type="webhook" __key="3.location.name" >北京</span>
    </div>
    <div class="ask-ckeditor-loop-item" __item_scope="3.location">
        <span class="ask-ckeditor-placeholder" __type="webhook" __key="3.location.name" >上海</span>
    </div>
    <div class="ask-ckeditor-loop-item" __item_scope="3.location">
        <span class="ask-ckeditor-placeholder" __type="webhook" __key="3.location.name" >广州</span>
    </div>
</section>