前言
在上一章内容中,介绍了工作流的启动和执行,只要掌握了这两个驱动工作流引擎的方法,那么对于工作流就等于掌握了60%,因此上章内容的对于工作流的启动和执行的基本用法十分重要!
在这一章内容中,主要介绍:
1.正在运行中实例和历史流程查看
2.工作流实例的挂起与激活
以上这两类功能,在本质上分别两两相对应,即分别成对存在,难舍难分。因此在本章进行介绍。废话不多说,下面就让我们进入正题吧~
系列四内容
1.正在运行中实例和历史流程查看
2.工作流实例的挂起与激活
主界面总览
说明:为了简单方便,进入正在运行实例和历史实例,我只用了最简单的超链接。若各位觉得过菜,请使用vue的路由跳转等其他方式实现,在此不再赘述。
功能详细说明
说明
首先,先说说第一对兄弟,在实际项目运用中,很少会将这两块内容放入到实际开发项目的前台页面中,大多都是通过查询数据库的方式对某个实例(正在运行:act_ru_task或历史:act_hi_taskinst)进行追踪,但是本系统为了想要对全部实例有一个整体的把控,决定把这一对幕后英雄请上前台。各位可根据项目实际需要进行查阅。
注:获取列表的查询参数为defId(processDefineKey),即流程定义KEY。方案不止此一种,各位看官可以根据实际项目需求进行斟酌选用
页面
正在运行实例
前端代码
ActiveProcess.vue
展示正在运行实例列表(含查看历史功能)
<template>
<div class="div-class">
<Card style="height: 750px">
<p slot="title">
<Icon type="ios-film-outline"></Icon>
活动实例列表({{this.$route.params.defId}})
</p>
<Button type="primary" class="btn-class" @click="returnPage">返回</Button>
<ul>
<Table height="550" border ref="selection" :columns="columns12" :data="data6" style="margin-top: 50px">
<template slot-scope="{ row, index }" slot="action">
<div class="slot_class">
<Button type="success" size="small" v-show="row.suspended==false" @click="suspendTask(row)">挂起</Button>
<Button type="error" size="small" v-show="row.suspended==true" @click="activateTask(row)">激活</Button>
<Button type="info" size="small" @click="showHistory(row)">查看历史</Button>
</div>
</template>
</Table>
</ul>
</Card>
<Modal width="850px" :closable="false" :mask-closable="false" v-model="historyDetailModal">
<Card>
<HistoryDetail ref="historyDetail"></HistoryDetail>
</Card>
<div slot="footer" style="text-align: center">
<Button type="primary" @click="historyDetailModal=false">确定</Button>
</div>
</Modal>
</div>
</template>
<script>
import {
getHistoryActivitiIds, getTaskListByDefId
} from '../../api/activityManagement'
export default {
name: 'ActiveProcess',
data () {
return {
flowId:'',
processInstanceId:'',
historyDetailModal:false,
columns12: [
{
type: 'selection',
width: 60,
align: 'center'
},
{ title: '序号', align:'center', type: 'index', key:'index', width:'80px'},
{ title: '工作项', align:'center', key:'id', width:'80px'},
{ title: '任务名称', align:'center', key: 'name', width:'140px'},
{ title: '任务KEY', align:'center', key: 'taskDefinitionKey', width:'140px'},
{ title: '处理人', align:'center', key: 'assignee', width:'100px'},
{ title: '创建时间', align:'center', key: 'createTime',
render: (h, params) => {
// 这里要求h中的第一个参数是注册成功的组件
if(params.row.createTime !== null){
return h('div',getDate(new Date(params.row.createTime),'day')
)
}
}
},
{ title: '流程实例ID', align:'center', key: 'processInstanceId', width:'120px'},
{ title: '部署定义ID', align:'center', key: 'processDefinitionId'},
{
title: '操作项',
slot: 'action',
width: 350,
align: 'center'
}
],
data6: []
}
},
mounted(){
this.getTableData() ;
},
methods: {
openCallBack(row){
const processInstanceId = row.processInstanceId ;
getHistoryActivitiIds({
processInstanceId: processInstanceId
}).then(res => {
if(res.data.responseCode === 1){
const list = res.data.responseData.list ;
this.selectData = list;
this.workFlowCallBackModal = true ;
//②这里赋值回退的流程实例ID
this.processInstanceId = processInstanceId ;
}
})
},
showHistory(row){
this.$refs.historyDetail.detailData = row.historyList ;
this.historyDetailModal = true
},
getTableData(){
const defId = this.$route.params.defId ;
getTaskListByDefId({
defId:defId
}).then(res =>{
if(res.data.responseCode === 1){
this.data6 = res.data.responseData.list
}
})
},
returnPage(){
//返回这个路由对应的组件
this.$router.push('/homePage');
}
}
}
</script>
activityManagement.js
/**defId(processDefineId)获取task**/
export const getTaskListByDefId = params => {
return axios.request({
url: 'workflow/getTaskListByDefId',
params: params,
method: 'post'
})
}
/**根据defId(processDefineId)获取历史实例列表**/
export const getHistoryListByDefId = params => {
return axios.request({
url: 'workflow/getHistoryListByDefId',
params: params,
method: 'post'
})
}
后端代码
WorkflowController
展示正在运行实例列表
@RequestMapping("/getTaskListByDefId")
public JsonResult getTaskListByDefId(String defId){
JsonResult jr = new JsonResult() ;
resultMap = new HashMap<String,Object>() ;
List<ActivitiTaskVO> voList = new ArrayList<ActivitiTaskVO>();
try {
//获取正在运行实例的列表
List<Task> list = taskService.createTaskQuery().processDefinitionId(defId).orderByProcessInstanceId().asc().list();
if(list != null){
for(Task task : list){
//遍历查询出来的所有实例
ActivitiTaskVO vo = new ActivitiTaskVO() ;
//使用API将实例对象copy为自己的非持久化类方便展示和后续拓展
BeanUtils.copyProperties(task, vo);
String processInstanceId = vo.getProcessInstanceId() ;
List<HistoricTaskInstance> historicTaskInstanceList = historyService
.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId)
.orderByExecutionId().asc().list();
//如果有历史记录(原则上必须有),则将其转化为自定义VO,然后赋值给历史记录的HistoryList属性,放到前台进行展示
if(historicTaskInstanceList != null && historicTaskInstanceList.size()>0){
List<HistoryDetailVO> historyDetailVOS = new ArrayList<HistoryDetailVO>() ;
for(HistoricTaskInstance historicTaskInstance:historicTaskInstanceList){
//使用同样的方式获取该实例的所有历史环节进行前台展示
HistoryDetailVO historyDetailVO = new HistoryDetailVO() ;
BeanUtils.copyProperties(historicTaskInstance, historyDetailVO);
historyDetailVOS.add(historyDetailVO) ;
}
vo.setHistoryList(historyDetailVOS);
}
voList.add(vo) ;
}
}
resultMap.put("list",voList) ;
jr.setResponseData(resultMap);
jr.setResponseCode(1);
jr.setResponseMessage(ResultEnum.SUCCESS);
}catch (Exception e){
e.printStackTrace();
jr.setResponseCode(0);
jr.setResponseMessage(ResultEnum.EXCEPTION);
}
return jr ;
}
历史实例
说明
由于历史实例和正在运行实例两个功能的前端页面和后端处理思路完全相同,仅在后台获取历史实例列表的API选择上与正在运行实例功能不同,因此为节约篇幅,仅把后台不同代码段进行展示。
后台代码
WorkflowController
/**
* 根据defId(processDefineKey)查询历史记录
* @param defId
* @return
*/
@RequestMapping("/getHistoryListByDefId")
public JsonResult getHistoryListByDefId(String defId){
JsonResult jr = new JsonResult() ;
resultMap = new HashMap<String,Object>() ;
List<HistoryListVO> voList = new ArrayList<HistoryListVO>();
try {
//此list直接转到前台接收即可,getTaskListByFlowKey同
List<HistoricProcessInstance> list = historyService
.createHistoricProcessInstanceQuery()
.processDefinitionId(defId).finished().list() ;
if(list != null){
for(HistoricProcessInstance historicProcessInstance : list){
HistoryListVO vo = new HistoryListVO() ;
BeanUtils.copyProperties(historicProcessInstance, vo);
//获取所有的历史活动
String processInstanceId = vo.getProcessInstanceId() ;
List<HistoricTaskInstance> historicTaskInstanceList = historyService
.createHistoricTaskInstanceQuery()
.processInstanceId(processInstanceId).orderByExecutionId().asc()
.list();
//如果有历史记录(原则上必须有),则将其转化为自定义VO,然后赋值给历史记录的HistoryList属性,放到前台进行展示
if(historicTaskInstanceList != null && historicTaskInstanceList.size()>0){
List<HistoryDetailVO> historyDetailVOS = new ArrayList<HistoryDetailVO>() ;
for(HistoricTaskInstance historicTaskInstance:historicTaskInstanceList){
HistoryDetailVO historyDetailVO = new HistoryDetailVO() ;
BeanUtils.copyProperties(historicTaskInstance, historyDetailVO);
historyDetailVOS.add(historyDetailVO) ;
}
vo.setHistoryList(historyDetailVOS);
}
voList.add(vo) ;
}
}
resultMap.put("list",voList) ;
jr.setResponseData(resultMap);
jr.setResponseCode(1);
jr.setResponseMessage(ResultEnum.SUCCESS);
}catch (Exception e){
e.printStackTrace();
jr.setResponseCode(0);
jr.setResponseMessage(ResultEnum.EXCEPTION);
}
return jr ;
}
流程实例的挂起与激活
说明
顾名思义,流程实例的挂起与激活标志着该实例的一种当前状态,若实例被挂起,则代表该实例不能被用户所执行,被称为挂起态,反之则允许用户执行该实例,为激活态。
本功能点在代码上实现十分简单,仅需调用官方API即可实现(参数为流程实例ID:processInstanceId)
页面
后台代码
WorkflowController
//挂起流程
runtimeService.suspendProcessInstanceById(processInstanceId);
//激活流程
runtimeService.activateProcessInstanceById(processInstanceId);
补充说明
-
流程实例的状态表示字段在act_ru_task表的SUSPENSION_STATE_字段,
其中 1为激活状态;2为挂起状态,如下图所示:
-
当流程实例被挂起时,若执行该实例,后台则会抛出ActivitiException异常(Cannot complete a suspended task),如下图所示:
总结
至此,有关于运行实例和历史实例的展示功能和流程的激活挂起功能开发完成。其中对于运行实例和历史实例列表查询的方式并不唯一,本文使用的查询参数为processDefineKey,还可用部署ID,流程实例ID等参数进行查询实现,各位可以根据实际项目需求进行取舍。
好了,以上就是本文的全部内容,各位若对代码有任何不同的意见或建议欢迎下方留言,大家共同进步!
下篇预告
流程图的查看
敬请期待~~~
第四篇完结~