本示例使用springboot2+activiti7+bpmn-js(vue+elementUI)环境;
官网:https://www.activiti.org/
<properties>
<java.version>1.8</java.version>
<activiti.version>7.1.0.M6</activiti.version>
</properties>
<dependencies>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-image-generator</artifactId>
<version>${activiti.version}</version>
</dependency>
</dependencies>
application.properties
# activiti配置
# 自动部署验证设置:true-开启(默认)、false-关闭
spring.activiti.check-process-definitions=false
# 自动创建表
# spring.activiti.database-schema-update=drop-create
spring.activiti.database-schema-update=false
# 使用历史表
spring.activiti.db-history-used=true
spring.activiti.history-level=full
# 关闭自动部署
spring.activiti.deployment-mode=never-fail
# 自动部署文件路径前后缀
# spring.activiti.process-definition-location-prefix=classpath:/process/
# spring.activiti.process-definition-location-suffixes=**.bpmn,**.bpmn20.xml
@SpringBootApplication
注解加一下参数(关闭activiti自带的权限)@SpringBootApplication(exclude = {
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class,
org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration.class
})
activiti工作流总共包含25张表,都已act_开头(activiti7与老版本的activiti表结构还是有些小变化的);其中:
ACT_GE_
:通用,用在各种情况下,2张;ACT_HI_
:历史,8张,默认提供了4种历史级别:
none
:不保存历史记录,性能最好;activity
:保存流程实例、任务、活动信息;audit
:默认,保存实例、任务、活动、表单属性;full
:保存完整的历史记录;ACT_RE_
:仓库,3张,保存一些静态信息,如流程定义、资源(图片,规则等);ACT_RU_
:运行,10张,保存流程实例、任务、变量等运行时数据,流程结束后会立即移除数据;ACT_EVT_LOG
:存储事件处理日志;ACT_PROCDEF_INFO
:流程定义信息;(老版本的activiti少了4张ACT_RU_
,多了4张ACT_ID_
的表(用于管理用户和用户组,作用不大))
常用的流程服务组件有:
RepositoryService
:提供管理流程定义和部署的API;RuntimeService
:在流程运行时对流程实例进行管理与控制;TaskService
:对流程任务进行管理,如:任务提醒、任务完成和创建;ManagementService
:提供对流程引擎进行管理和维护的服务;HistoryService
:对流程历史数据进行操作;DynamicBpmnService
:实现在不重新部署流程的情况下对流程模型进行部分修改;yarn add bpmn-js bpmn-js-properties-panel
(注意bpmn-js的版本不能太高,不然整合activiti可能会报错,我这里使用的这个版本)"bpmn-js": "~7.5.0",
"bpmn-js-properties-panel": "~0.43.1",
bpmn-js整合activiti需要下面这个json
{
"name": "Activiti",
"uri": "http://activiti.org/bpmn",
"prefix": "activiti",
"xml": {
"tagAlias": "lowerCase"
},
"associations": [],
"types": [
{
"name": "Definitions",
"isAbstract": true,
"extends": [
"bpmn:Definitions"
],
"properties": [
{
"name": "diagramRelationId",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "InOutBinding",
"superClass": [
"Element"
],
"isAbstract": true,
"properties": [
{
"name": "source",
"isAttr": true,
"type": "String"
},
{
"name": "sourceExpression",
"isAttr": true,
"type": "String"
},
{
"name": "target",
"isAttr": true,
"type": "String"
},
{
"name": "businessKey",
"isAttr": true,
"type": "String"
},
{
"name": "local",
"isAttr": true,
"type": "Boolean",
"default": false
},
{
"name": "variables",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "In",
"superClass": [
"InOutBinding"
],
"meta": {
"allowedIn": [
"bpmn:CallActivity"
]
}
},
{
"name": "Out",
"superClass": [
"InOutBinding"
],
"meta": {
"allowedIn": [
"bpmn:CallActivity"
]
}
},
{
"name": "AsyncCapable",
"isAbstract": true,
"extends": [
"bpmn:Activity",
"bpmn:Gateway",
"bpmn:Event"
],
"properties": [
{
"name": "async",
"isAttr": true,
"type": "Boolean",
"default": false
},
{
"name": "asyncBefore",
"isAttr": true,
"type": "Boolean",
"default": false
},
{
"name": "asyncAfter",
"isAttr": true,
"type": "Boolean",
"default": false
},
{
"name": "exclusive",
"isAttr": true,
"type": "Boolean",
"default": true
}
]
},
{
"name": "JobPriorized",
"isAbstract": true,
"extends": [
"bpmn:Process",
"activiti:AsyncCapable"
],
"properties": [
{
"name": "jobPriority",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "SignalEventDefinition",
"isAbstract": true,
"extends": [
"bpmn:SignalEventDefinition"
],
"properties": [
{
"name": "async",
"isAttr": true,
"type": "Boolean",
"default": false
}
]
},
{
"name": "ErrorEventDefinition",
"isAbstract": true,
"extends": [
"bpmn:ErrorEventDefinition"
],
"properties": [
{
"name": "errorCodeVariable",
"isAttr": true,
"type": "String"
},
{
"name": "errorMessageVariable",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "Error",
"isAbstract": true,
"extends": [
"bpmn:Error"
],
"properties": [
{
"name": "activiti:errorMessage",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "PotentialStarter",
"superClass": [
"Element"
],
"properties": [
{
"name": "resourceAssignmentExpression",
"type": "bpmn:ResourceAssignmentExpression"
}
]
},
{
"name": "FormSupported",
"isAbstract": true,
"extends": [
"bpmn:StartEvent",
"bpmn:UserTask"
],
"properties": [
{
"name": "formHandlerClass",
"isAttr": true,
"type": "String"
},
{
"name": "formKey",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "TemplateSupported",
"isAbstract": true,
"extends": [
"bpmn:Process",
"bpmn:FlowElement"
],
"properties": [
{
"name": "modelerTemplate",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "Initiator",
"isAbstract": true,
"extends": [
"bpmn:StartEvent"
],
"properties": [
{
"name": "initiator",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "ScriptTask",
"isAbstract": true,
"extends": [
"bpmn:ScriptTask"
],
"properties": [
{
"name": "resultVariable",
"isAttr": true,
"type": "String"
},
{
"name": "resource",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "Process",
"isAbstract": true,
"extends": [
"bpmn:Process"
],
"properties": [
{
"name": "candidateStarterGroups",
"isAttr": true,
"type": "String"
},
{
"name": "candidateStarterUsers",
"isAttr": true,
"type": "String"
},
{
"name": "versionTag",
"isAttr": true,
"type": "String"
},
{
"name": "historyTimeToLive",
"isAttr": true,
"type": "String"
},
{
"name": "isStartableInTasklist",
"isAttr": true,
"type": "Boolean",
"default": true
},
{
"name": "executionListener",
"isAbstract": true,
"type": "Expression"
}
]
},
{
"name": "EscalationEventDefinition",
"isAbstract": true,
"extends": [
"bpmn:EscalationEventDefinition"
],
"properties": [
{
"name": "escalationCodeVariable",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "FormalExpression",
"isAbstract": true,
"extends": [
"bpmn:FormalExpression"
],
"properties": [
{
"name": "resource",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "multiinstance_type",
"superClass": [
"Element"
]
},
{
"name": "multiinstance_condition",
"superClass": [
"Element"
]
},
{
"name": "Assignable",
"extends": [
"bpmn:UserTask"
],
"properties": [
{
"name": "assignee",
"isAttr": true,
"type": "String"
},
{
"name": "candidateUsers",
"isAttr": true,
"type": "String"
},
{
"name": "candidateGroups",
"isAttr": true,
"type": "String"
},
{
"name": "dueDate",
"isAttr": true,
"type": "String"
},
{
"name": "followUpDate",
"isAttr": true,
"type": "String"
},
{
"name": "priority",
"isAttr": true,
"type": "String"
},
{
"name": "multiinstance_condition",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "CallActivity",
"extends": [
"bpmn:CallActivity"
],
"properties": [
{
"name": "calledElementBinding",
"isAttr": true,
"type": "String",
"default": "latest"
},
{
"name": "calledElementVersion",
"isAttr": true,
"type": "String"
},
{
"name": "calledElementVersionTag",
"isAttr": true,
"type": "String"
},
{
"name": "calledElementTenantId",
"isAttr": true,
"type": "String"
},
{
"name": "caseRef",
"isAttr": true,
"type": "String"
},
{
"name": "caseBinding",
"isAttr": true,
"type": "String",
"default": "latest"
},
{
"name": "caseVersion",
"isAttr": true,
"type": "String"
},
{
"name": "caseTenantId",
"isAttr": true,
"type": "String"
},
{
"name": "variableMappingClass",
"isAttr": true,
"type": "String"
},
{
"name": "variableMappingDelegateExpression",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "ServiceTaskLike",
"extends": [
"bpmn:ServiceTask",
"bpmn:BusinessRuleTask",
"bpmn:SendTask",
"bpmn:MessageEventDefinition"
],
"properties": [
{
"name": "expression",
"isAttr": true,
"type": "String"
},
{
"name": "class",
"isAttr": true,
"type": "String"
},
{
"name": "delegateExpression",
"isAttr": true,
"type": "String"
},
{
"name": "resultVariable",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "DmnCapable",
"extends": [
"bpmn:BusinessRuleTask"
],
"properties": [
{
"name": "decisionRef",
"isAttr": true,
"type": "String"
},
{
"name": "decisionRefBinding",
"isAttr": true,
"type": "String",
"default": "latest"
},
{
"name": "decisionRefVersion",
"isAttr": true,
"type": "String"
},
{
"name": "mapDecisionResult",
"isAttr": true,
"type": "String",
"default": "resultList"
},
{
"name": "decisionRefTenantId",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "ExternalCapable",
"extends": [
"activiti:ServiceTaskLike"
],
"properties": [
{
"name": "type",
"isAttr": true,
"type": "String"
},
{
"name": "topic",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "TaskPriorized",
"extends": [
"bpmn:Process",
"activiti:ExternalCapable"
],
"properties": [
{
"name": "taskPriority",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "Properties",
"superClass": [
"Element"
],
"meta": {
"allowedIn": [
"*"
]
},
"properties": [
{
"name": "values",
"type": "Property",
"isMany": true
}
]
},
{
"name": "Property",
"superClass": [
"Element"
],
"properties": [
{
"name": "id",
"type": "String",
"isAttr": true
},
{
"name": "name",
"type": "String",
"isAttr": true
},
{
"name": "value",
"type": "String",
"isAttr": true
}
]
},
{
"name": "Connector",
"superClass": [
"Element"
],
"meta": {
"allowedIn": [
"activiti:ServiceTaskLike"
]
},
"properties": [
{
"name": "inputOutput",
"type": "InputOutput"
},
{
"name": "connectorId",
"type": "String"
}
]
},
{
"name": "InputOutput",
"superClass": [
"Element"
],
"meta": {
"allowedIn": [
"bpmn:FlowNode",
"activiti:Connector"
]
},
"properties": [
{
"name": "inputOutput",
"type": "InputOutput"
},
{
"name": "connectorId",
"type": "String"
},
{
"name": "inputParameters",
"isMany": true,
"type": "InputParameter"
},
{
"name": "outputParameters",
"isMany": true,
"type": "OutputParameter"
}
]
},
{
"name": "InputOutputParameter",
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "value",
"isBody": true,
"type": "String"
},
{
"name": "definition",
"type": "InputOutputParameterDefinition"
}
]
},
{
"name": "InputOutputParameterDefinition",
"isAbstract": true
},
{
"name": "List",
"superClass": [
"InputOutputParameterDefinition"
],
"properties": [
{
"name": "items",
"isMany": true,
"type": "InputOutputParameterDefinition"
}
]
},
{
"name": "Map",
"superClass": [
"InputOutputParameterDefinition"
],
"properties": [
{
"name": "entries",
"isMany": true,
"type": "Entry"
}
]
},
{
"name": "Entry",
"properties": [
{
"name": "key",
"isAttr": true,
"type": "String"
},
{
"name": "value",
"isBody": true,
"type": "String"
},
{
"name": "definition",
"type": "InputOutputParameterDefinition"
}
]
},
{
"name": "Value",
"superClass": [
"InputOutputParameterDefinition"
],
"properties": [
{
"name": "id",
"isAttr": true,
"type": "String"
},
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "value",
"isBody": true,
"type": "String"
}
]
},
{
"name": "Script",
"superClass": [
"InputOutputParameterDefinition"
],
"properties": [
{
"name": "scriptFormat",
"isAttr": true,
"type": "String"
},
{
"name": "resource",
"isAttr": true,
"type": "String"
},
{
"name": "value",
"isBody": true,
"type": "String"
}
]
},
{
"name": "Field",
"superClass": [
"Element"
],
"meta": {
"allowedIn": [
"activiti:ServiceTaskLike",
"activiti:ExecutionListener",
"activiti:TaskListener"
]
},
"properties": [
{
"name": "name",
"isAttr": true,
"type": "String"
},
{
"name": "expression",
"type": "String"
},
{
"name": "stringValue",
"isAttr": true,
"type": "String"
},
{
"name": "string",
"type": "String"
}
]
},
{
"name": "InputParameter",
"superClass": [
"InputOutputParameter"
]
},
{
"name": "OutputParameter",
"superClass": [
"InputOutputParameter"
]
},
{
"name": "Collectable",
"isAbstract": true,
"extends": [
"bpmn:MultiInstanceLoopCharacteristics"
],
"superClass": [
"activiti:AsyncCapable"
],
"properties": [
{
"name": "collection",
"isAttr": true,
"type": "String"
},
{
"name": "elementVariable",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "FailedJobRetryTimeCycle",
"superClass": [
"Element"
],
"meta": {
"allowedIn": [
"activiti:AsyncCapable",
"bpmn:MultiInstanceLoopCharacteristics"
]
},
"properties": [
{
"name": "body",
"isBody": true,
"type": "String"
}
]
},
{
"name": "ExecutionListener",
"superClass": [
"Element"
],
"meta": {
"allowedIn": [
"bpmn:Task",
"bpmn:ServiceTask",
"bpmn:UserTask",
"bpmn:BusinessRuleTask",
"bpmn:ScriptTask",
"bpmn:ReceiveTask",
"bpmn:ManualTask",
"bpmn:ExclusiveGateway",
"bpmn:SequenceFlow",
"bpmn:ParallelGateway",
"bpmn:InclusiveGateway",
"bpmn:EventBasedGateway",
"bpmn:StartEvent",
"bpmn:IntermediateCatchEvent",
"bpmn:IntermediateThrowEvent",
"bpmn:EndEvent",
"bpmn:BoundaryEvent",
"bpmn:CallActivity",
"bpmn:SubProcess",
"bpmn:Process"
]
},
"properties": [
{
"name": "expression",
"isAttr": true,
"type": "String"
},
{
"name": "class",
"isAttr": true,
"type": "String"
},
{
"name": "delegateExpression",
"isAttr": true,
"type": "String"
},
{
"name": "event",
"isAttr": true,
"type": "String"
},
{
"name": "script",
"type": "Script"
},
{
"name": "fields",
"type": "Field",
"isMany": true
}
]
},
{
"name": "TaskListener",
"superClass": [
"Element"
],
"meta": {
"allowedIn": [
"bpmn:UserTask"
]
},
"properties": [
{
"name": "expression",
"isAttr": true,
"type": "String"
},
{
"name": "class",
"isAttr": true,
"type": "String"
},
{
"name": "delegateExpression",
"isAttr": true,
"type": "String"
},
{
"name": "event",
"isAttr": true,
"type": "String"
},
{
"name": "script",
"type": "Script"
},
{
"name": "fields",
"type": "Field",
"isMany": true
}
]
},
{
"name": "FormProperty",
"superClass": [
"Element"
],
"meta": {
"allowedIn": [
"bpmn:StartEvent",
"bpmn:UserTask"
]
},
"properties": [
{
"name": "id",
"type": "String",
"isAttr": true
},
{
"name": "name",
"type": "String",
"isAttr": true
},
{
"name": "type",
"type": "String",
"isAttr": true
},
{
"name": "required",
"type": "String",
"isAttr": true
},
{
"name": "readable",
"type": "String",
"isAttr": true
},
{
"name": "writable",
"type": "String",
"isAttr": true
},
{
"name": "variable",
"type": "String",
"isAttr": true
},
{
"name": "expression",
"type": "String",
"isAttr": true
},
{
"name": "datePattern",
"type": "String",
"isAttr": true
},
{
"name": "default",
"type": "String",
"isAttr": true
},
{
"name": "values",
"type": "Value",
"isMany": true
}
]
},
{
"name": "FormProperty",
"superClass": [
"Element"
],
"properties": [
{
"name": "id",
"type": "String",
"isAttr": true
},
{
"name": "label",
"type": "String",
"isAttr": true
},
{
"name": "type",
"type": "String",
"isAttr": true
},
{
"name": "datePattern",
"type": "String",
"isAttr": true
},
{
"name": "defaultValue",
"type": "String",
"isAttr": true
},
{
"name": "properties",
"type": "Properties"
},
{
"name": "validation",
"type": "Validation"
},
{
"name": "values",
"type": "Value",
"isMany": true
}
]
},
{
"name": "Validation",
"superClass": [
"Element"
],
"properties": [
{
"name": "constraints",
"type": "Constraint",
"isMany": true
}
]
},
{
"name": "Constraint",
"superClass": [
"Element"
],
"properties": [
{
"name": "name",
"type": "String",
"isAttr": true
},
{
"name": "config",
"type": "String",
"isAttr": true
}
]
},
{
"name": "ConditionalEventDefinition",
"isAbstract": true,
"extends": [
"bpmn:ConditionalEventDefinition"
],
"properties": [
{
"name": "variableName",
"isAttr": true,
"type": "String"
},
{
"name": "variableEvent",
"isAttr": true,
"type": "String"
}
]
}
],
"emumerations": []
}
<template>
<div style="width: 100%; height: 100%">
<div ref="bpmn" style="width: 100%; height: 100%;"></div>
<div ref="panel" class="panel"></div>
<button @click="showSave = true" class="saveBtn" style="margin-left: -50px;">保存</button>
<button @click="loadData" class="saveBtn" style="margin-left: 50px;">重置</button>
<el-dialog title="保存流程图" :visible.sync="showSave">
<el-form :model="model">
<el-form-item label="key">
<el-input v-model="model.key" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="name">
<el-input v-model="model.name" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="showSave = false">取 消</el-button>
<el-button type="primary" @click="save">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
// 这个只能预览
// import BpmnViewer from 'bpmn-js/lib/Viewer'
import Modeler from 'bpmn-js/lib/Modeler'
// 面板
import propertiesPanelModule from 'bpmn-js-properties-panel'
import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/bpmn'
// 适应activiti
import activiti from '@/components/activiti/activiti.json'
// 汉化
/// import customTranslate from '@/components/activiti/customTranslate.js'
export default {
data() {
return {
showSave: false, model: {id: '', key: '', name: '', xml: ''}, modeler: null
}
},
mounted() {
this.modeler = new Modeler({
container: this.$refs.bpmn, propertiesPanel: {parent: this.$refs.panel},
additionalModules: [
propertiesPanelModule, propertiesProviderModule,
/// {translate: ['value', customTranslate]}
],
moddleExtensions: {
activiti: activiti
}
})
this.loadData()
},
methods: {
loadData() {
this.model.id = this.$route.query.id
new Promise(resolve => {
if (this.model.id) {
this.$apis.act.act.getModel.req({id: this.model.id}).then(res => {
if (res.data && res.data.metaInfo) {
this.model = res.data
}
resolve(this.model.metaInfo)
})
} else {
resolve()
}
}).then(xml => {
xml ? this.modeler.importXML(xml) : this.modeler.createDiagram()
})
},
save() {
this.modeler.saveXML().then(xml => {
this.model.xml = xml.xml
this.$apis.act.act.saveModel.req(this.model).then(res => {
this.$message({type: 'success', message: '成功'})
this.$router.push({path: '/bpmn/modelEdit', query: {id: res.data.id}})
this.loadData()
})
})
/*this.modeler.saveSVG().then(b => {
console.log(b)
})*/
},
}
}
</script>
<style scoped>
/* 基础样式 */
@import '~bpmn-js/dist/assets/diagram-js.css';
@import '~bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
@import '~bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css';
@import '~bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
/* 右侧面板样式 */
@import '~bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css';
.saveBtn {
position: absolute;
top: 80%;
left: 50%;
padding: 12px 16px;
border-radius: 10px;
font-size: 18px;
cursor: pointer;
}
.panel {
position: absolute;
box-sizing: border-box;
width: 400px;
height: 100%;
padding: 10px 15px;
top: 80px;
right: 15px;
overflow: auto;
}
</style>
activiti的每一个服务组件都有一个query对象,可以通过服务组件的createXxxQuery方法得到;可用于查询流程数据(可以查询model、部署的流程、流程实例、流程历史等信息),这里就不细说了;
@PostMapping("/saveModel")
@ApiOperation("保存流程")
public R<String> saveModel(String id, String name, String xml) {
Model model = repositoryService.getModel(id);
if (model == null) {
model = repositoryService.newModel();
}
model.setMetaInfo(xml);
model.setName(name);
model.setKey("testKey");
//保存模型
repositoryService.saveModel(model);
return R.success(model.getId());
}
流程部署可以根据model、xml、zip等不同的数据源来部署,这里是根据流程设计器保存的提供的xml来部署流程,部署成功后会在ACT_RE_
的部分表中有体现。
@GetMapping("/deploy")
@ApiOperation("部署流程")
public R<String> deploy(String modelId) {
Model model = repositoryService.getModel(modelId);
String deploymentId = model.getDeploymentId();
if (StringUtils.hasText(deploymentId)) {
return R.error("流程已部署" + deploymentId);
}
// 部署流程
Deployment deployment = repositoryService.createDeployment().name(model.getName()).key(model.getKey())
.addString(model.getName() + ".bpmn20.xml", model.getMetaInfo()).deploy();
model.setDeploymentId(deployment.getId());
repositoryService.saveModel(model);
return R.success(deployment.getId());
}
@GetMapping("/start")
@ApiOperation("启动流程")
public R<String> start(String deploymentId, String businessKey) {
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
.deploymentId(deploymentId).active().latestVersion().singleResult();
List<ProcessInstance> list = runtimeService.createProcessInstanceQuery()
.processDefinitionId(processDefinition.getId()).processInstanceBusinessKey(businessKey).list();
if (list != null && !list.isEmpty()) {
return R.error("businessKey重复");
}
// 启动流程
ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId(), businessKey);
return R.success(processInstance.getId());
}
@GetMapping("/audit")
@ApiOperation("审核流程")
public R audit(String processInstanceId) {
Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
if (task == null) {
return R.error("任务不存在");
}
// 通过
taskService.complete(task.getId());
// 驳回
/// taskService.resolveTask(task.getId());
return R.success();
}
这里返回的是svg图片
@GetMapping("/img")
@ApiOperation("流程图")
public R<String> img(String defId, String businessKey) throws IOException {
BpmnModel bpmnModel = repositoryService.getBpmnModel(defId);
List<String> activityIds = new ArrayList<>();
HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(businessKey).singleResult();
List<HistoricActivityInstance> list1 = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstance.getId()).list();
for (HistoricActivityInstance instance : list1) {
activityIds.add(instance.getActivityId());
}
ProcessDiagramGenerator imageGenerator = new DefaultProcessDiagramGenerator();
String activityFontName = "宋体";
String labelFontName = "宋体";
String annotationFontName = "宋体";
Process process = bpmnModel.getMainProcess();
List<String> flows = new ArrayList<>();
for (FlowElement flowElement : process.getFlowElements()) {
boolean isExecute = (flowElement instanceof Activity || flowElement instanceof Event) && activityIds.contains(flowElement.getId());
if (isExecute) {
flows.addAll(((FlowNode) flowElement).getIncomingFlows().stream().map(BaseElement::getId).collect(Collectors.toList()));
}
}
InputStream is = imageGenerator.generateDiagram(bpmnModel, activityIds, flows,
activityFontName, labelFontName, annotationFontName, true);
byte[] bytes = new byte[is.available()];
int len = is.read(bytes);
is.close();
String svgImg = new String(bytes, 0, len);
return R.success(svgImg);
}
到此,一个简单的流程就可以使用上面的api来操作了。