一、背景
公司项目是统一在公司自己的框架下实现的,然后现在在做的项目使用了flowable工作流。
昨儿忽然提了一个需求:在中心签领之前,企业可以撤回任务。比如企业上报了自己的信息,中心端需要签领后审核,但忽然企业发现自己上报的信息有些问题,这时可以点击【撤回】按钮,将该条上报信息撤回。(串行普通节点的回退)。
其中部分代码详细实现不可以粘贴出来,就主要记录一下大概思路~~
自己瞎实现,还请各位大佬可以指正错误~~~呜呜呜呜呜呜呜。
二、思路
1、获取当前任务节点
2、判断是否被签领
3、若被签领,则提示不能撤回。
4、若未被签领,则执行退回任务。
//核心
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(proInstanceId)
.moveActivityIdsToSingleActivityId(curTaskKeys, targetTaskKey)
.changeState();
5、自动签领任务。
6、返回要跳转的路径
三、代码
1、flowableEngineAPI.quash()实现!!
/**
* 撤回任务
*/
public DataObject quash(String piid, String taskid, String taskkey) throws AppException{
//存最终结果
DataObject result = DataObject.getInstance();
//判空
this.isEmpty(piid, "流程实例id不可为空");
//获取当前任务信息
Task task = taskService.createTaskQuery().taskId(taskid).singleResult();
//判断该任务是否被签领
String assignee = task.getAssignee();
if (null != assignee){
result.put("statu","0");
result.put("msg","任务已被签领,无法撤回!");
}else{
//获取历史任务节点
List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(task.getProcessInstanceId()).orderByHistoricTaskInstanceStartTime().asc().list();
Iterator<HistoricTaskInstance> it = historicTaskInstanceList.iterator();
//循环节点,获取当前节点的上一节点的key
String tkey = "";
while(it.hasNext()) {
HistoricTaskInstance his = it.next();
if (!taskkey.equals(his.getTaskDefinitionKey())){
tkey = his.getTaskDefinitionKey();
}
}
//回退(节点跳转)
runtimeService.createChangeActivityStateBuilder()
.processInstanceId(piid)
.moveActivityIdTo(taskkey, tkey)
.changeState();
//删除当前任务节点,不知道咋实现
//返回成功消息
result.put("statu","1");
result.put("msg","撤回成功!请尽快完成任务");
}
return result;
}
2、contrller层
/**
* 撤回任务,并进入相应页面
*
* @param para
* @return
* @author: tcy
* 时间:2021年12月07日
*/
@PostMapping("/quash")
@ResponseBody
public DataObject quash(@RequestBody DataObject para) {
String piid = para.getString("piid");
String pdkey = para.getString("pdkey");
//获取当前任务节点
DataObject rdo = DataObject.getInstance();
rdo.put("piid",piid);
DataObject active = flowableEngineAPI.getActiveTaskListByPiid(rdo);
DataStore rows = active.getDataStore("rows");
DataObject row = rows.getRow(0);
String taskid = row.getString("taskid");//任务id
String taskkey = row.getString("taskkey");//任务名称
//执行退回任务
DataObject result = flowableEngineAPI.quash(piid,taskid,taskkey);
//自动签领任务
String statu = result.getString("statu");
if ("1".equals(statu)){
active = flowableEngineAPI.getActiveTaskListByPiid(rdo);
rows = active.getDataStore("rows");
taskid = rows.getString(0, "taskid");
String curruser = SecurityUtils.getUser().getUserId();
rdo.clear();
rdo.put("userid", curruser);
rdo.put("taskid", taskid);
//签领任务
flowableEngineAPI.claim(rdo);
//返回需跳转的路径
rdo.clear();
rdo.put("pdkey", pdkey);
rdo.put("taskkey", active.getDataStore("rows").getString(0, "taskkey"));
DataObject path = flowableService.getTaskPath(rdo);
result.put("piid",piid);
result.put("task_path",path.getString("task_path"));
}
return result;
}
3、前端
layui.sight.ajaxRequest({
type: 'post',
async: true,
url: layui.sight.compileUrl('${rc.contextPath}/flowable/quash'),//调用方法路径
data: {//方法需要的参数
piid: '${piid}',
pdkey: '${pdkey}'
},
callback: function (data) {
//回调
var statu = data.statu;
layer.confirm(data.msg + '<br>', {
btn: ['确认']
}, function(){
//当可以执行撤回时,刷新页面
if ("1" == statu){
var url = layui.sight.compileUrl('${rc.contextPath}' + data.task_path + '?piid=' + data.piid);
window.open(url, target = "_self");
}else{
//不可以执行撤回时,直接关闭该弹窗
return;
}
}
);
},
failedCallback: function (data) { }
});
四、问题
造成的脏数据(撤回的节点)未删除。