从一个特殊的需求开始
我们的项目使用流程图的形式配置用户进线流程。什么是用户进线流程呢?用一个比较好理解的例子来讲,我们打10010联通热线的时候,首先会有一段语音播报(播放语音),然后我们会语音告诉它要选择“按键”服务还是“语音”服务(语音识别、用户选择判断),如果选择按键,那么会一步步提示你可以按哪些按键,每个按键对应的含义是什么(用户菜单),然后我们会一步步地进行按键选择,直到流程结束(系统挂断)或者转接到人工坐席(流程跳转),在挂断后我们也可能会收到评价短信(满意度问卷下发)。
随着场景越来越复杂,运营画的流程图也越来越大,整个流程图已经越来越难看了。所以产品提出了要增加一个手动分组的功能。主要的效果就是鼠标框选流程图上的一部分区域,把区域内的节点放到一个新建的分组里面,分组要支持收缩展开操作:收缩状态下隐藏分组内部节点,但是保留分组内节点与分组外节点间的连线关系;展开状态下要将隐藏的内部节点展示出来。大致效果如下图:
我们项目的流程图用的bpmn.js,虽然我们是把bpmn.js源码引入到项目中来,但是bpmn.js代码太难懂了,而且被之前接手的人魔改的乱七八糟的。所以接到需求的时候理直气壮的说“这个实现不了,bpmn.js不支持,除非你给我几个月把它换了”。然后老大真就给了我几个月~
调研目前流程图相关开源项目
目前市面上有很多流程图开源项目,例如draw.io、flowchart.js,但是这些项目都是直接提供一个完整的流程图作图工具,而我们的项目有各种产品特殊的自定义需求,像“标注”,“路径”,“实时统计”等,所以我们需要更灵活的流程图设计器。又看了d3,g6感觉他们又太过灵活,实现我们项目成本太高。最后发现阿里的x6和滴滴的LogicFlow比较合适,既满足了兼容我们后端activiti引擎的需求,又有足够的自定义能力。我最后选择了LogicFlow是因为LogicFlow的架构足够清晰,而且源码非常易懂,后续有什么新功能的开发也可以自己直接上手搞。关于LogicFlow架构设计大家可以看LogicFlow官方文章:http://logic-flow.org/article/article01.html
用LogicFlow实现绘制区域再收起
LogicFlow本身支持分组和选区,但是与我们自己需要的交互和样式还有一点差异,所以我们需要在上面做一定的改造。我们的需求可以拆分为下面几步:
- 自定义分组,分组外观需要是UI给出的外观,大小受到创建分组传入的宽高控制。
- 通过鼠标在画布上绘制一块区域,获取区域内所有的节点。
- 创建一个和绘制区域同样大小的分组,然后将选区内的节点放入分组。
在LogicFlow中分组也是一种节点,大多数自定义节点的方法分组也可以用。所以我们只需要在自定义分组的时候,基于分组的展开和收起状态,定义分组这个节点的样式就好。
定义group的model
class SelectGroupModel extends GroupNode.model {
// 初始化节点数据
initNodeData(data) {
super.initNodeData(data);
// 支持创建分组的时候传入自定义宽高
this.width = data.width || 300;
this.height = data.height || 200;
// 支持收缩
this.foldable = true;
// 收缩后的节点宽高
this.foldedWidth = 175;
this.foldedHeight = 40;
const forbidConnect = {
message: "不允许直接连接到分组",
validate: () => {
return false;
}
};