先看效果图

第一步
// 安装以下依赖 yarn add @logicflow/core yarn add @logicflow/extension yarn add vue-json-pretty
主要页面业务源码参考
<template>
<div class="logic-flow-view">
<!-- 辅助工具栏 -->
<Control
class="demo-control"
v-if="lf"
:lf="lf"
:catTurboData="true"
@catData="$_catData"
@catTurboData="$_catTurboData"
></Control>
<!-- 节点面板 -->
<NodePanel :lf="lf" :nodeList="nodeList"></NodePanel>
<!-- 画布 -->
<div id="LF-Turbo"></div>
<!-- 数据查看面板 -->
<el-dialog title="数据" :visible.sync="dataVisible" width="50%">
<DataDialog :graphData="graphData"></DataDialog>
</el-dialog>
<!-- 编辑节点信息 -->
<el-dialog title="属性" :visible.sync="nodeInfo" width="70%">
<div :key="nodeKey">
<div class="node-content">
<el-form label-width="86px" :model="nodeObjProperties" class="demo-form-inline">
<el-row :gutter="40">
<el-col :span="12">
<el-form-item label="编号">
<el-input v-model="nodeObjProperties.overrideid" disabled placeholder="请输入"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="名称">
<el-input v-model="nodeObjProperties.name" placeholder="请输入"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="40" v-if="isNode">
<el-col :span="12">
<el-form-item label="分配角色">
<el-select v-model="nodeObjProperties.taskroleids" placeholder="请选择">
<el-option
v-for="item in assignRole"
:key="item.roleId"
:label="item.roleName"
:value="item.roleId"
>
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="阶段策略">
<!-- <el-input readonly placeholder="点击设置" @click="stageStrategyFun"></el-input> -->
<el-button @click="stageStrategyFun">点击设置</el-button>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="40">
<el-col :span="12" v-if="isNode">
<el-form-item label="多实例类型">
<el-select v-model="nodeObjProperties.multiinstance_type" placeholder="请选择">
<el-option
v-for="item in multiinstanceTypeList"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" v-if="!isNode">
<el-form-item label="流转策略">
<el-button @click="sequenseflowStrategyFun">点击设置</el-button>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="说明">
<el-input v-model="nodeObjProperties.des" placeholder="请输入"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="nodeInfo = false">取 消</el-button>
<el-button type="primary" @click="editNodeFun">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script lang="ts">
import { Vue, Component, Ref, Watch, Inject, Provide, Prop } from ‘vue-property-decorator‘
import LogicFlow from ‘@logicflow/core‘
// BpmnXmlAdapter
import { Menu, Snapshot, BpmnElement, InsertNodeInPolyline } from ‘@logicflow/extension‘
import ‘@logicflow/core/dist/style/index.css‘
import ‘@logicflow/extension/lib/style/index.css‘
import NodePanel from ‘./LFComponents/NodePanel.vue‘
import Control from ‘./LFComponents/Control.vue‘
import DataDialog from ‘./LFComponents/DataDialog.vue‘
import { toTurboData, toLogicflowData } from ‘./AdpterForTurbo‘
import { BpmnNode } from ‘./config‘
import qs from ‘qs‘
import demoDataNew from ‘./zdata‘
@Component({
name: ‘LF‘,
components: {
NodePanel,
Control,
DataDialog
}
})
export default class LF extends Vue {
@Prop() private flowData!: any
@Prop() private flowModelInit!: any
@Prop() private assignRole!: any[]
nodeObj: any = {}
lf: any = {}
graphData: any = null
dataVisible = false
// 画布样式
config: any = {
background: {
// color: ‘#f7f9ff‘
},
grid: {
size: 10,
visible: true,
type: ‘mesh‘,
config: {
color: ‘#dcdcdc‘, // 设置网格的颜色
thickness: ‘2‘ // 设置网格线的宽度
}
},
keyboard: {
enabled: true
},
style: {
rect: {
radius: 16
},
edgeText: {
background: {
fill: ‘#fff‘
}
}
},
// adjustEdge: true,
textEdit: true,
isSilentMode: false,
// edgeType: ‘bezier‘,
snapline: true,
edgeTextDraggable: true,
guards: {
beforeClone(data: object) {
console.log(‘beforeClone‘, data)
return true
},
beforeDelete(data: object) {
// 可以根据data数据判断是否允许删除,允许返回true,不允许返回false
// 文档: http://logic-flow.org/guide/basic/keyboard.html#%E5%A6%82%E4%BD%95%E9%98%BB%E6%AD%A2%E5%88%A0%E9%99%A4%E6%88%96%E8%80%85%E6%8B%B7%E8%B4%9D%E8%A1%8C%E4%B8%BA
console.log(‘beforeDelete‘, data)
// _this.$message(‘不允许删除‘, ‘error‘)
return true
}
}
}
nodeList = BpmnNode
nodeInfo = false
nodeKey = 0
taskroleidsList = []
multiinstanceTypeList = [
{
id: 1,
label: ‘None‘,
value: ‘None‘
},
{
id: 2,
label: ‘Parallel‘,
value: ‘Parallel‘
},
{
id: 3,
label: ‘Sequential‘,
value: ‘Sequential‘
}
]
nodeData = []
nodeObjProperties: any = {}
isNode = true
graphDataBefore: any = {}
mounted() {
this.$_initLf()
}
/**
* 流程初始化
*/
$_initLf() {
const _this = this
LogicFlow.use(Menu)
LogicFlow.use(Snapshot)
// 支持在连接线上插入节点
LogicFlow.use(InsertNodeInPolyline)
// 支持转bpmnXml格式
// LogicFlow.use(BpmnXmlAdapter)
// 使用bpmn插件,引入bpmn元素,这些元素可以在turbo中转换后使用
LogicFlow.use(BpmnElement)
const lf = new LogicFlow({ ...this.config, container: document.querySelector(‘#LF-Turbo‘) as HTMLElement })
this.lf = lf || {}
// 添加属性菜单
lf.addMenuConfig({
nodeMenu: [
{
text: ‘属性‘,
callback(node: any) {
_this.showInfoDialog(node, true)
}
}
],
edgeMenu: [
{
text: ‘属性‘,
callback(edge: any) {
_this.showInfoDialog(edge, false)
}
}
]
})
// 设置主题
lf.setTheme({
circle: {
r: 15,
stroke: ‘#000000‘,
outlineColor: ‘#88f‘,
strokeWidth: 2
},
rect: {
outlineColor: ‘#88f‘,
strokeWidth: 2,
width: 100,
height: 80,
radius: 6,
color: ‘#1890ff‘,
opcity: 0.6
},
polygon: {
strokeWidth: 2,
points: ‘20, 0, 40, 20, 20, 40, 0, 20‘
},
polyline: {
stroke: ‘#000000‘,
hoverStroke: ‘#000000‘,
selectedStroke: ‘#000000‘,
outlineColor: ‘#88f‘,
strokeWidth: 1
},
nodeText: {
color: ‘#000000‘
},
edgeText: {
color: ‘#000000‘,
background: {
fill: ‘#f7f9ff‘
}
}
})
this.$_registerNode()
// 设置边类型bpmn:sequenceFlow为默认类型
// lf.setDefaultEdgeType(‘bpmn:sequenceFlow‘)
this.$_render()
}
/**
* 自定义节点注册
*/
$_registerNode() {
// registerStart(this.lf)
// registerUser(this.lf)
// registerEnd(this.lf)
// registerDownload(this.lf)
// registerPolyline(this.lf)
// registerTask(this.lf)
// registerConnect(this.lf)
this.$_render()
}
/**
* 事件初始化
*/
$_LfEvent() {
this.lf.on(‘node:click‘, (res: any) => {})
this.lf.on(‘edge:click‘, (res: any) => {})
// this.lf.on(‘blank:click‘, () => {
// this.nodeInfo = false
// })
}
/**
* 属性展示弹窗
* @param item 属性对象
* @param isNodeType 是否节点类型
*/
showInfoDialog(item: any, isNodeType: boolean) {
const data = item
data.properties.name = data.text && data.text.value
data.properties.id = data.id
if (!data.text) {
data.text = {}
}
this.isNode = isNodeType
// this.lf.setNodeData(data)
this.nodeObjProperties = JSON.parse(JSON.stringify(data.properties))
this.nodeObj = data
this.nodeInfo = true
this.nodeKey += 1
}
/**
* render初始化
*/
$_render() {
console.log(this.flowData, ‘flowData‘)
// 调用toLogicflowData将数据转换为LogicFlow内部识别的数据结构
// const lFData = toLogicflowData(this.flowData || {})
const lFData = toLogicflowData(demoDataNew)
console.log(lFData, ‘lFData‘)
// 兼容老数据 对折现拉直处理
// lFData.edges.forEach((j: any) => {
// // const pointsListArr = (j.pointsList && j.pointsList.slice(0)) || []
// // j.pointsList = [pointsListArr[0], pointsListArr[pointsListArr.length - 1]]
// j.pointsList =
// j.pointsList &&
// j.pointsList.filter((q: any) => {
// return q.x === j.startPoint.x || q.y === j.startPoint.y || q.x === j.endPoint.x || q.y === j.endPoint.y
// })
// })
this.lf.render(lFData)
this.$_LfEvent()
}
/**
* 查看数据
*/
$_catData() {
this.$data.graphData = this.$data.lf.getGraphData()
this.$data.dataVisible = true
}
/**
* 生成随机数
*/
randNum() {
let rand = ‘‘
for (let i = 0; i < 19; i++) {
rand += Math.floor(Math.random() * 10)
}
return rand
}
/**
* 保存
*/
$_catTurboData() {
this.graphDataBefore = this.$data.lf.getGraphData()
this.reNodeData()
this.reEdgeData()
// json重组为借口需要格式
this.graphData = toTurboData(this.graphDataBefore)
// this.graphData = this.graphDataBefore
console.log(this.graphData, ‘graphData--2‘)
localStorage.setItem(‘submitData‘, JSON.stringify(this.graphData))
this.reFormData()
}
/**
* 节点属性添加
*/
reNodeData() {
this.graphDataBefore.nodes = this.graphDataBefore.nodes.map((q: any) => {
const overrideidVal = `${q.type.substring(5, q.type.length)}_${this.randNum()}`
const propertiesVal = {
overrideid: overrideidVal,
usertaskassignment: {
assignment: {
type: ‘static‘,
assignee: `assignee_variable_${overrideidVal}`
}
},
multiinstance_collection: `assignee_${overrideidVal}`,
multiinstance_variable: `assignee_variable_${overrideidVal}`
}
q.properties = Object.assign(q.properties, propertiesVal)
// 添加节点ourgoing
let outgoingArr: any = []
this.graphDataBefore.edges.forEach((j: any) => {
if (q.id === j.sourceNodeId && j.targetNodeId) {
outgoingArr.push({ resourceId: j.targetNodeId })
}
})
q.outgoing = outgoingArr
return q
})
}
/**
* 连接线属性添加
*/
reEdgeData() {
this.graphDataBefore.edges = this.graphDataBefore.edges.map((q: any) => {
const overrideidVal = `${q.type.substring(5, q.type.length)}_${this.randNum()}`
const propertiesVal = {
overrideid: overrideidVal,
usertaskassignment: {
assignment: {
type: ‘static‘,
assignee: ‘${assignee_variable_‘ + ‘overrideidVal‘ + ‘}‘
}
},
multiinstance_collection: `assignee_${overrideidVal}`,
multiinstance_variable: `assignee_variable_${overrideidVal}`
}
q.properties = Object.assign(q.properties, propertiesVal)
return q
})
}
/**
* 重组参数为接口需要
*/
reFormData() {
const { name, description, key, lastUpdated, lastUpdatedBy, modelId, version } = this.flowModelInit
const xmlJson = {
modelId: this.flowData.modelId || ‘0‘,
properties: this.flowData.properties,
...this.graphData
}
const formData = {
modeltype: ‘model‘,
json_xml: JSON.stringify(xmlJson),
name: name,
description: description,
key: key,
lastUpdated: lastUpdated,
newversion: true,
common: ‘‘
}
this.$emit(‘saveFlow‘, qs.stringify(formData))
this.$data.dataVisible = true
}
/**
* 编辑节点属性
*/
editNodeFun() {
this.nodeObj.text.value = this.nodeObjProperties.name
this.nodeObj.properties = this.nodeObjProperties
if (this.isNode) {
this.lf.setNodeData(this.nodeObj)
} else {
this.lf.setEdgeData(this.nodeObj)
}
console.log(this.nodeObj, ‘this.nodeObj‘)
this.nodeInfo = false
}
/**
* 阶段策略
*/
stageStrategyFun() {
this.$emit(‘stageStrategy‘)
}
/**
* 流转策略
*/
sequenseflowStrategyFun() {
this.$emit(‘sequenseflowStrategy‘)
}
}
</script>
<style scoped lang="scss">
.logic-flow-view {
height: 100%;
position: relative;
}
.demo-title {
text-align: center;
margin: 20px;
}
.demo-control {
position: absolute;
top: 10px;
right: 10px;
z-index: 2;
}
#LF-Turbo {
width: 100%;
height: 100%;
outline: none;
}
.time-plus {
cursor: pointer;
}
.add-panel {
position: absolute;
z-index: 11;
background-color: white;
padding: 10px 5px;
}
.el-drawer__body {
height: 80%;
overflow: auto;
margin-top: -30px;
z-index: 3;
}
::v-deep .node-item-icon {
margin: auto;
}
.node-panel {
margin-left: 8px;
left: 6px !important;
}
.node-content {
margin-top: 14px;
}
::v-deep .el-form--inline .el-form-item__content,
.el-select {
width: 100%;
}
::v-deep .el-dialog {
width: 700px !important;
}
</style>
具体根据业务需求
demo见我的仓库 https://gitee.com/zh888/logicflow-vue-bpm-demo-ing (注意:这个demo不是上面我写的业务源码参考,仅仅是我用过的参考demo)
【前端开发】基于logicFlow可视化流程库改造的流程引擎教程
原文:https://www.cnblogs.com/xiaohuizhang/p/15307837.html