vue + LogicFlow 实现流程图展示
1.背景
部门主要负责低代码平台,配置端负责配置流程图,引擎端负责流程执行,原引擎端只负责流程执行控制以及流程历史列表展示。现在提出个新的要求,认为仅历史记录不直观,需要在展示完整配置流程图的基础上显示执行历史路线。经过初步分析,决定在当前项目的基础上使用LogicFlow渲染从配置端获取的流程图
2.方案设计
- 配置端为流程设计器,引擎端通过配置端接口获取流程图所有的节点信息json
- 在引擎端根据json分析出各节点以及连线的信息并整合形成logicFlow适用的节点连线数据
- 根据节点连线数据渲染流程图,使显示与配置端配置流程图基本保持一致
- 引擎端获取流程执行历史,对执行过的节点以及节点之间的连线高亮从而显示完整的执行历史路线
3.准备工作
- 安装:
npm install @logicflow/core --save
- 引入:
import LogicFlow from '@logicflow/core';
- 版本:
^1.2.22
- 框架:
vue
4.运行问题排查
- 运行报错
ERROR in F:/app/node_modules/preact/src/jsx.d.ts(1462,3):1462:3 Cannot find name 'SubmitEvent'.
- 可能原因:在LogicFlow的package.json文件中
"dependencies": {"preact": "^10.4.8"}
,依赖的preact版本与当前项目的preact版本不一致导致ts校验报错 - 解决:
npm install preact@^10.4.8
,安装相应版本的preact
- 运行报错
ERROR in F:/app/node_modules/@logicflow/core/types/util/mobx.d.ts(1,106):1:106 Cannot find module 'mobx'
- 可能原因:在LogicFlow的package.json文件中
"devDependencies": {"mobx": "^5.15.7"}
,找不到依赖的第三方库 - 解决:
npm install mobx@^5.15.7
,安装相应版本的mobx(按道理来说devDependencies中依赖的库是不需要安装的,不清楚具体什么原因需要安装)
5.关键实现
1.挂载
// index.js
<div class="container" ref="lf_ref"></div>
import LogicFlow from '@logicflow/core'
this.lf = new LogicFlow({
container: this.$refs.lf_ref,
isSilentMode: true // 静默模式,仅用于展示
})
this.lf.render(this.lf_data)
2.自定义节点
基于某种类型节点改动可继承该类型节点类,若需要自定义整个节点则需继承htmlNode类去自定义构建html节点
// customRect.js
import { HtmlNodeModel, HtmlNode } from '@logicflow/core'
class CustomRectModel extends HtmlNodeModel {
setAttributes() {
const { properties } = this
this.width = properties.width
this.height = properties.height
}
}
class CustomRectNode extends HtmlNode {
setHtml(rootEl) {
const { properties } = this.props.model
const el = document.createElement('div')
el.className = 'custom-rect-contain'
const html = `
<div class="icon-side">
<div class="icon-type"><i class="new-web-icon icon-flow_sp"></i></div>
<div class="icon-status"><i class="new-web-icon icon-success"></i></div>
</div>
<div class="info-side">
<div class="name-text">${properties.af_actname || properties.value}</div>
<div class="member-text">${properties.af_assignee || ''}</div>
<div class="status-text">${properties.af_choice || ''}</div>
</div>
`
el.innerHTML = html
// 需要先把之前渲染的子节点清除掉
rootEl.innerHTML = ''
rootEl.appendChild(el)
}
}
export default {
type: 'custom-rect',
view: CustomRectNode,
model: CustomRectModel
}
// index.js
import customRect from './components/customRect'
this.lf.register(customRect)
3.自定义样式
自定义节点后需要搭配自定义样式,vue中会给节点样式增加唯一后缀以实现样式隔离,因此如果需要修改logicFlow生成的节点需要使用深层选择器;
我使用的是less,对应的深层选择器是::v-deep,sass应该是:deep()
<style lang="less" scoped>
.container {
width: 100%;
height: 100%;
overflow: hidden;
::v-deep {
// 此处定义各种自定义样式类的样式
}
}
</style>
4.流程json分析
原配置端的流程配置是基于Angular实现的流程设计器,流程协议与logicFlow并不通用,需要对配置端获取的流程协议的参数进行调整才可用于logicFlow的渲染;
json数据转换为logicFlow数据的具体逻辑实现在此不多做赘述,毕竟json格式不一定一致
{
// 节点属性:将当前节点作为起始节点的线的id,用于设置logicFlow中线的sourceNode
"outgoing": [
{
"resourceId": "sid-58F1C9BC-DEEE-4775-90FB-C3E55993E194"
}
],
// 节点/线属性:标志id
"resourceId": "sid-F73FFA42-61DD-4834-8A2D-1611588E1F6B",
// 节点/线属性:左上以及右下位置的坐标,需要根据两个坐标计算logicFlow中节点的x坐标、y坐标以及宽高
"bounds": {
"upperLeft": {
"x": 45,
"y": 270
},
"lowerRight": {
"x": 75,
"y": 300
}
},
// 节点/线属性:id对应不同类型,其他则均为普通节点
// StartNoneEvent:开始节点,EndNoneEvent:结束节点
// ExclusiveGateway:分支节点
// SequenceFlow:线
"stencil": {
"id": ""
},
// 线属性:dockers作为线连接节点的锚点,若仅两元素则为直线,若多于两元素则表示该连线为折线,超出的docker作为折线的中间点
// 节点的锚点在logicFlow中并不适用,计算折线pointsList时可根据节点方位选择节点边上任一坐标进行连接
"dockers": [
{
"x": 20.5,
"y": 20.5
},
{
"x": 50,
"y": 40
}
],
"properties": {},
// 线属性:线目标节点的id,用于设置logicFlow中线的targetNode
"target": {
"resourceId": "sid-0DA5B3EC-1E1F-4335-AA26-682E9C8D1DAC"
}
}