在上一篇的文章中,我给大家分享了Activiti工作流引擎的API的封装代码,通过我们自己封装的代码,在实际的项目中我们就可以进行工作流相关的开发了。以下内容我们分三个部分:提交审批,审批列表查询,审批处理。
一、提交审批
提交审批之前,我们需要做好相关的准备工作。在上文中,我提到过:
1.首先,我们要画工作流程图,并且需要在流程图中设置相关的参数,比如:流程ID、审批人节点,审批条件的判断等,然后我们把生成的.bpmn20.xml放入到我们的项目中,以下展示的是xml里面的内容,主要是看下参数节点的设置。
2.其次,我们需要根据具体的工作流业务需求选择相应的工作流,主要是需要逻辑判断获取流程ID,这个我们在工作流提交审批的时候会用到。
public static final String ACTIVITY_AUDIT_PROCESS_DEFINITION_12359 = "workflow001";
public static final String ACTIVITY_AUDIT_PROCESS_DEFINITION_34579 = "workflow002";
public static final String ACTIVITY_AUDIT_PROCESS_DEFINITION_6789 = "workflow003";
public static final String ACTIVITY_AUDIT_PROCESS_DEFINITION_8910 = "workflow004";
public static final String ACTIVITY_AUDIT_PROCESS_DEFINITION_10 = "workflow005";
3.然后,我们需要把用到的业务参数也需要放入到工作流里面,比如主键ID、查询待审批的业务查询条件。
Map variables = new HashMap<>();
// 活动主题
variables.put(WFVariablesEnum.activityName.name(), record.getActivityName());
// 活动类型
variables.put(WFVariablesEnum.activityType.name(), record.getActivityType());
// 活动组织机构
variables.put(WFVariablesEnum.orgName.name(), record.getOrgName());
// 提报类型
variables.put(WFVariablesEnum.reportType.name(), record.getReportType());
// 提交审批人用户ID
variables.put(WFVariablesEnum.submitter.name(),userId);
好了,现在我们展示一下提交审批的相关代码:
// 1、获取流程定义ID 此处根据前台传的审批人节点来查找工作流
StringBuffer sb = new StringBuffer();
for (TbActivityAuditor tbAuditor : auditorList) {
sb.append(tbAuditor.getAuditNode());
}
String nodeSqu = sb.toString();
// 2、判断选的工作流是否存在
ProjectApproveEnum pEnum = ProjectApproveEnum.getByStrSeq(nodeSqu);
if (pEnum == null ) {
resultMap.put("status",false);
resultMap.put("message","未找到该审批流程的配置,提交审批失败!");
return resultMap;
}
String processDefinitonKey = pEnum.getProcessDefinitionKey();
String businessKey = String.valueOf(record.getId());
Map variables = new HashMap<>();
// 活动主题
variables.put(WFVariablesEnum.activityName.name(), record.getActivityName());
// 活动类型
variables.put(WFVariablesEnum.activityType.name(), record.getActivityType());
// 活动组织机构
variables.put(WFVariablesEnum.orgName.name(), record.getOrgName());
// 提报类型
variables.put(WFVariablesEnum.reportType.name(), record.getReportType());
variables.put(WFVariablesEnum.submitter.name(),userId);
// 设置实体相关所需变量
for (TbActivityAuditor tbAct : auditorList) {
if (ReportAuditNodeEnum.getByAuditNode(tbAct.getAuditNode()) != null) {
ReportAuditNodeEnum auditorEnum = ReportAuditNodeEnum.getByAuditNode(tbAct.getAuditNode());
variables.put(auditorEnum.getAuditorVar(), tbAct.getAuditor());
}
}
String processInstanceId = "";
// 流程发起人设置
workFlowHandler.setAuthenticatedUserId(String.valueOf(userId));
ProcessInstance processInstance = workFlowHandler.startProcessInstanceByKey(processDefinitonKey, businessKey, variables);
//
processInstanceId = processInstance.getId();
然后把获取到的processInstanceId值设置到相应的主键ID对应的数据库表记录上。说到这里,我再提一下数据库表这块的内容,
`process_instance_id` varchar(64) COLLATE utf8_bin DEFAULT '' COMMENT '流程实例ID',
业务表需要添加这个字段,记录工作流流程实例ID,方便我们进行工作流待处理任务的查找。
经过上面的处理,我们已经开启了一个工作流,并且可以进行任务的查找与处理了。 第一部分的内容我们已经完成了。
二、审批列表查询
审批列表查询需要根据我们提交审批部分设置的参数进行查询任务,直接上示例代码:
Map params = new HashMap();
if (StringUtils.isNotBlank(orgName)) {
params.put(WFVariablesEnum.orgName.toString(), orgName);
}
if (StringUtils.isNotBlank(activityName)) {
params.put(WFVariablesEnum.activityName.toString(), activityName);
}
if (StringUtils.isNotBlank(activityType) && !"0".equals(activityType)) {
params.put(WFVariablesEnum.activityType.toString(), Integer.parseInt(activityType));
}
params.put(WFVariablesEnum.reportType1.toString(), new Integer(0));
count = activityReportAuditService.countTaskListByVariables(userId, params);
if (count > 0) {
page = PageUtils.buildPage(new Page(), (int) count, pageNum, Constant.DefaultPageSize);
List tskList = activityReportAuditService.findTaskListByVariables(userId, params, page.getPageStartNumber(), Constant.DefaultPageSize);
for (Task task : tskList) {
String taskId = task.getId();
String taskName = task.getName();
String taskAssignee = task.getAssignee();
String businessKey = workFlowTaskQuery.findBusinessKeyByTaskId(taskId);
... ...
}
}
需要说明一下,首先查询参数的数据类型一定要和提交审批时候的一致,否则查询不出来,其次是需要往工作流传入审批人的用户ID,也就是我们提交审批时候设置的审批人的ID是对应的。 查询列表的时候,我们先去统计记录数,如果记录数为0,我们就不用去查询列表了,减少操作。如果有记录数,那我们就进行分页查询。遍历每一个任务,获取到taskId、taskName、taskAssignee、businessKey,然后去关联业务表的相关数据进行展示。
/**
* 待审批记录统计
* @param userId
* @param vars
* @return
* @throws Exception
*/
public long countTaskListByVariables(String userId, Map vars) throws Exception {
TaskQuery tq = workFlowTaskQuery.createTaskQuery();
if (vars != null && vars.size() >0) {
for(Entry entry : vars.entrySet()){
if (WFVariablesEnum.activityName.toString().equals(entry.getKey()) ||
WFVariablesEnum.orgName.toString().equals(entry.getKey())) {
tq.processVariableValueLike(entry.getKey(),"%" +String.valueOf(entry.getValue())+ "%");
}if (WFVariablesEnum.reportType1.toString().equals(entry.getKey())) {
tq.processVariableValueLessThanOrEqual(WFVariablesEnum.reportType.toString(), ReportTypeEnum.ACTIVITY_OFFSET.getCode());
}else {
tq.processVariableValueEquals(entry.getKey(),entry.getValue());
}
}
}
return workFlowTaskQuery.countTaskAssigneeByTaskQuery(userId, tq);
}
有些项目的待审批的任务查询条件有些需要特殊处理,比如模糊查询。我们就需要包装一层去处理。
/**
* 待审批记录列表
* @param userId
* @param vars
* @param start
* @param limit
* @return
* @throws Exception
*/
public List findTaskListByVariables(String userId, Map vars, int start, int limit)
throws Exception {
TaskQuery tq = workFlowTaskQuery.createTaskQuery();
if (vars != null && vars.size() >0) {
for(Entry entry : vars.entrySet()){
if (WFVariablesEnum.activityName.toString().equals(entry.getKey()) ||
WFVariablesEnum.orgName.toString().equals(entry.getKey())) {
tq.processVariableValueLike(entry.getKey(), "%" +String.valueOf(entry.getValue())+ "%");
}if (WFVariablesEnum.reportType1.toString().equals(entry.getKey())) {
tq.processVariableValueLessThanOrEqual(WFVariablesEnum.reportType.toString(), ReportTypeEnum.ACTIVITY_OFFSET.getCode());
}else {
tq.processVariableValueEquals(entry.getKey(),entry.getValue());
}
}
}
return workFlowTaskQuery.taskAssigneeByTaskQuery(userId, tq, start, limit);
}
三、审批处理
审批处理比较复杂,会分很多情况,比如审批通过,审批退回,审批驳回等,那处理方式也是不一样的,我大致说说从控制器controller接收审批处理的开始说起,这里,我只说单笔任务处理的方式,批量的只是要循环处理。
/**
* 单笔审批
*
* @param taskId 任务ID
* @param auditOpr //审批结果
* @param comment 审批意见
* @return
*/
@RequestMapping(value = "/singleAudit", method = RequestMethod.POST)
@ResponseBody
public Map singleAudit(@RequestParam(value = "taskId") String taskId,
@RequestParam(value = "auditOpr") String auditOpr,
@RequestParam(value = "comment", required = false) String comment) {
Map responseMap = new HashMap();
String userId = String.valueOf(UserAuthorizingUtils.getUserId());
try {
if (StringUtils.isBlank(taskId) || StringUtils.isBlank(auditOpr)) {
throw new ValidationException("参数为空");
}
activityReportAuditService.singleAudit(userId, taskId, auditOpr, comment);
responseMap.put("respCode", RespCodeEnum.R0000.getRespCode());
responseMap.put("respMsg", RespCodeEnum.R0000.getRespDesc());
} catch (ValidateException e) {
logger.info("校验检查", e);
responseMap.put("respCode", RespCodeEnum.R0001.getRespCode());
responseMap.put("respMsg", RespCodeEnum.R0001.getRespDesc());
} catch (Exception e) {
e.printStackTrace();
logger.info("系统处理异常", e);
responseMap.put("respCode", RespCodeEnum.R9999.getRespCode());
responseMap.put("respMsg", RespCodeEnum.R9999.getRespDesc());
}
return responseMap;
}
@Transactional("transactionManager")
@Override
public void singleAudit(String userId, String taskId,String auditOpr,String comment) throws Exception{
try {
Map variables = new HashMap();
// 审批通过
if (AuditOperationEnum.OPER_PASS.getCode().equals(auditOpr)) {
variables.put(WFVariablesEnum.approveOpr.toString(), AuditOperationEnum.OPER_PASS.getCode());
this.auditPass(userId,taskId, variables);
// 审批退回
}else if (AuditOperationEnum.OPER_TOBACK.getCode().equals(auditOpr)) {
variables.put(WFVariablesEnum.approveOpr.toString(), AuditOperationEnum.OPER_TOBACK.getCode());
this.auditBackToInitiator(userId,taskId, comment, variables);
// 审批驳回
}else if (AuditOperationEnum.OPER_REFUSED.getCode().equals(auditOpr)) {
variables.put(WFVariablesEnum.approveOpr.toString(), AuditOperationEnum.OPER_REFUSED.getCode());
this.auditRefuse(userId,taskId, comment, variables);
}
} catch (BusinessException e) {
throw e;
} catch (Exception e) {
throw new BusinessException(e);
}
}
@Override
public void auditPass(String userId,String taskId, Map variables) throws Exception {
try {
// 1、获取业务主键ID值
String id = workFlowTaskQuery.findBusinessKeyByTaskId(taskId);
int recordId = Integer.parseInt(id);
String taskName = workFlowTaskQuery.taskId(taskId).getName();
// 2、完成工作流任务任务
workFlowTask.complete(taskId, variables);
// 3、根据recordId查询业务数据
// 4、插入审批记录
// 5、处理暂无负责人
String processId = record.getProcessInstanceId();
Task autoTask = null;
while ( (autoTask = workFlowTaskQuery.processInstanceId(processId)) != null) {
if (Constant.NO_AUDITOR_CODE.equals(autoTask.getAssignee())) {
workFlowTask.complete(autoTask.getId(), variables);
} else {
break;
}
}
ProcessInstance pi = workFlowQuery.processInstanceId(processId);
// 6、审批流程走完处理逻辑
if (pi == null) {
logger.info("-----------------审批流程已走完.--------------",record.getReportNo());
}else{
// 7、流程未走完处理逻辑
}
} catch (Exception e) {
e.printStackTrace();
throw new BusinessException("活动立项审批处理异常");
}
}
@Override
public void auditRefuse(String userId,String taskId,String comment, Map variables) throws Exception {
try {
String id = workFlowTaskQuery.findBusinessKeyByTaskId(taskId);
int recordId = Integer.parseInt(id);
String taskName = workFlowTaskQuery.taskId(taskId).getName();
// 1、删除流程实例,结束审批流程
ProcessInstance pi = workFlowQuery.taskId(taskId);
String processInstId = pi.getProcessInstanceId();
workFlow.deleteProcessInstance(processInstId, comment);
// 2、根据recordId更新业务状态
// 3、添加审批记录
} catch (Exception e) {
e.printStackTrace();
throw new BusinessException("驳回处理异常");
}
}
@Override
public void auditBackToInitiator(String userId,String taskId, String comment,Map variables) throws Exception {
try {
String id = workFlowTaskQuery.findBusinessKeyByTaskId(taskId);
int recordId = Integer.parseInt(id);
String taskName = workFlowTaskQuery.taskId(taskId).getName();
// 1、完成任务
ProcessInstance pi = workFlowQuery.taskId(taskId);
String processInstId = pi.getProcessInstanceId();
workFlow.deleteProcessInstance(processInstId, comment);
// 2、根据recordId更新业务数据
// 3、添加审批记录
} catch (Exception e) {
e.printStackTrace();
throw new BusinessException("退回处理异常");
}
}
到现在,我们已经把相关的审批任务的相关内容介绍完了,对需要的朋友应该会有一些帮助, 在当前的技术行业,我们每个人的学习的水平、广度深入都是不一样的,那我们可以把我们所学的东西分享出来,来帮助需要帮助的人。我也希望能够认识更多的朋友,我们一起进步。