diff --git a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/pom.xml b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/pom.xml index 24006dd32..f1b0fd14f 100644 --- a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/pom.xml +++ b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/pom.xml @@ -142,5 +142,10 @@ ${project.version} test + + org.hswebframework.web + hsweb-tests + 3.0-SNAPSHOT + \ No newline at end of file diff --git a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/FlowableAutoConfiguration.java b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/FlowableAutoConfiguration.java index 9edc20720..0fb8a6c36 100644 --- a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/FlowableAutoConfiguration.java +++ b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/FlowableAutoConfiguration.java @@ -39,17 +39,8 @@ public class FlowableAutoConfiguration { configuration.setCustomSessionFactories(sessionFactories); } }; - -// ProcessEngineConfiguration processEngineConfiguration = new StandaloneProcessEngineConfiguration() -// .setAsyncExecutorActivate(false) -// .setJobExecutorActivate(false) -// .setActivityFontName("宋体") -// .setLabelFontName("宋体") -// .setAnnotationFontName("宋体"); -// return processEngineConfiguration; } - @ConditionalOnBean(UserService.class) @Configuration public static class CustomEntityManagerAutoConfiguration { diff --git a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/controller/BpmDeploymentController.java b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/controller/BpmDeploymentController.java index a3449dd29..1f9f4a7fb 100644 --- a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/controller/BpmDeploymentController.java +++ b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/controller/BpmDeploymentController.java @@ -7,7 +7,9 @@ import org.activiti.bpmn.converter.BpmnXMLConverter; import org.activiti.bpmn.model.BpmnModel; import org.activiti.editor.constants.ModelDataJsonConstants; import org.activiti.editor.language.json.converter.BpmnJsonConverter; +import org.activiti.engine.history.HistoricProcessInstance; import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; +import org.activiti.engine.impl.pvm.process.ActivityImpl; import org.activiti.engine.repository.DeploymentBuilder; import org.activiti.engine.repository.Model; import org.activiti.engine.repository.ProcessDefinition; @@ -19,7 +21,13 @@ import org.hsweb.ezorm.core.param.TermType; import org.hswebframework.web.commons.entity.PagerResult; import org.hswebframework.web.commons.entity.param.QueryParamEntity; import org.hswebframework.web.controller.message.ResponseMessage; +import org.hswebframework.web.workflow.flowable.service.BpmActivityService; +import org.hswebframework.web.workflow.flowable.service.BpmProcessService; +import org.hswebframework.web.workflow.flowable.service.BpmTaskService; import org.hswebframework.web.workflow.flowable.utils.FlowableAbstract; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -42,6 +50,16 @@ import java.util.zip.ZipInputStream; @RequestMapping("/workflow/definition") public class BpmDeploymentController extends FlowableAbstract { + protected Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + BpmTaskService bpmTaskService; + + @Autowired + BpmProcessService bpmProcessService; + @Autowired + BpmActivityService bpmActivityService; + /** * 流程定义列表 */ @@ -223,4 +241,49 @@ public class BpmDeploymentController extends FlowableAbstract { } return jsonObject; } + + /** + * 查看当前节点流程图 + * @param processInstanceId + * @return 当前节点 + * window.open('/showImage?processInstanceId=' + processInstanceId, 'newwindow', 'height=500, width=1000, top=100,left=200, toolbar=no, menubar=no, scrollbars=no, resizable=no,location=no, status=no'); + *
+ <#if message??> +

${message!}

+ <#else> + + +
+ +
+ */ + @GetMapping("/showImage/{processInstanceId}") + public Object showImage(@PathVariable String processInstanceId){ + JSONObject jsonObject = new JSONObject(); + HistoricProcessInstance processInstance = bpmTaskService.selectHisProInst(processInstanceId); + if(processInstance!=null){ + ActivityImpl activity = bpmActivityService.getActivityByProcInstId(processInstance.getProcessDefinitionId(),processInstance.getId()); + jsonObject.put("activity",activity); + jsonObject.put("procDefId",processInstance.getProcessDefinitionId()); + }else{ + jsonObject.put("message","获取流程图失败"); + logger.debug("获取流程节点,processInstanceId:"+processInstanceId); + } + return jsonObject; + } + + @GetMapping("/findPic/{procDefId}") + public void findPic(@PathVariable String procDefId,HttpServletResponse response){ + try{ + InputStream inputStream = bpmProcessService.findProcessPic(procDefId); + byte[] b = new byte[1024]; + int len = 0; + while ((len = inputStream.read(b,0,1024))!=-1){ + response.getOutputStream().write(b, 0, len); + } + }catch (Exception e){ + logger.debug("获取流程图失败,procDefId:"+procDefId); + } + } } diff --git a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/entity/TaskInfo.java b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/entity/TaskInfo.java new file mode 100644 index 000000000..003951d82 --- /dev/null +++ b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/entity/TaskInfo.java @@ -0,0 +1,126 @@ +package org.hswebframework.web.workflow.flowable.entity; + +import org.activiti.engine.repository.ProcessDefinition; +import org.activiti.engine.task.Task; +import org.hswebframework.web.commons.entity.SimpleGenericEntity; + +import java.util.Date; +import java.util.Map; + +/** + * @Author wangwei + * @Date 2017/8/4. + */ +public class TaskInfo extends SimpleGenericEntity { + + public static final String TYPE_TODO = "todo"; + + public static final String TYPE_CLAIM = "claim"; + + private String name; + + private Date createDate; + + private ProcessDefinition definition; + + private String formId; + + private String dataId; + + private Object mainFormData; + + private String pid; + + private String processInstanceId; + + private String type; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Date getCreateDate() { + return createDate; + } + + public void setCreateDate(Date createDate) { + this.createDate = createDate; + } + + public ProcessDefinition getDefinition() { + return definition; + } + + public void setDefinition(ProcessDefinition definition) { + this.definition = definition; + } + + public String getPid() { + return pid; + } + + public void setPid(String pid) { + this.pid = pid; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getProcessInstanceId() { + return processInstanceId; + } + + public void setProcessInstanceId(String processInstanceId) { + this.processInstanceId = processInstanceId; + } + + public TaskInfo initFromProtoType(Task task) { + this.setId(task.getId()); + this.setName(task.getName()); + this.setCreateDate(task.getCreateTime()); + this.setProcessInstanceId(task.getProcessInstanceId()); + this.setPid(task.getParentTaskId()); + Map var = task.getProcessVariables(); + this.setFormId((String) var.get("mainFormId")); + this.setDataId((String) var.get("mainFormDataId")); + return this; + } + + + public static TaskInfo buildFromProtoType(Task task) { + return new TaskInfo().initFromProtoType(task); + } + + public String getFormId() { + return formId; + } + + public void setFormId(String formId) { + this.formId = formId; + } + + public String getDataId() { + return dataId; + } + + public void setDataId(String dataId) { + this.dataId = dataId; + } + + public Object getMainFormData() { + return mainFormData; + } + + public void setMainFormData(Object mainFormData) { + this.mainFormData = mainFormData; + } +} diff --git a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/BpmActivityService.java b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/BpmActivityService.java new file mode 100644 index 000000000..2649771c1 --- /dev/null +++ b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/BpmActivityService.java @@ -0,0 +1,59 @@ +package org.hswebframework.web.workflow.flowable.service; + +import org.activiti.engine.impl.pvm.process.ActivityImpl; + +import java.util.List; + +/** + * 流程节点操作的接口 + * @Author wangwei + * @Date 2017/8/4. + */ +public interface BpmActivityService { + /** + * 获取指定节点 + * + * @param procDefId 流程定义ID + * @return ActivityImpl 指定的节点资源 + */ + ActivityImpl getActivityById(String procDefId, String activityId); + + /** + * 获取指定节点 + * + * @param procDefKey 流程定义Key + * @return ActivityImpl 指定的节点,未指定返回当前节点 + */ + ActivityImpl getActivityByKey(String procDefKey, String activityId); + + /** + * 获取所有节点 + * + * @param procDefId 流程定义ID + * @return List 当前流程的所有节点资源 + */ + List getActivitys(String procDefId); + + /** + * 获取所有userTask + * + * @param procDefId 流程定义ID + * @return List 当前流程的所有userTask资源 + */ + List getUserTasks(String procDefId); + + /** + * 获取结束节点 + * @param procDefId 流程定义ID + * @return ActivityImpl 当前流程的结束资源 + */ + ActivityImpl getEndActivityImpl(String procDefId); + + /*** + * 获取当前执行节点 + * @param procDefId 流程定义ID + * @param procInstId 流程实例ID + * @return + */ + ActivityImpl getActivityByProcInstId(String procDefId, String procInstId); +} diff --git a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/BpmProcessService.java b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/BpmProcessService.java new file mode 100644 index 000000000..0e14ec8fe --- /dev/null +++ b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/BpmProcessService.java @@ -0,0 +1,83 @@ +package org.hswebframework.web.workflow.flowable.service; + +import org.activiti.engine.repository.ProcessDefinition; +import org.activiti.engine.runtime.Job; +import org.activiti.engine.runtime.ProcessInstance; + +import java.io.InputStream; +import java.util.List; +import java.util.Map; + +/** + * 流程实例操作相关接口 + * @Author wangwei + * @Date 2017/8/4. + */ +public interface BpmProcessService{ + + /** + * 启动一个流程,并初始化自定义主表单数据 + * + * @param creator_id 流程创建人 + * @param procDefKey 流程定义key + * @param activity 下一环节id + * @param next_claim 下一步执行人 + * @param businessKey 业务数据ID + * @param variables 启动参数(流程变量,流程未结束前任意环节都可以使用) + * @return 启动后的流程实例 + * @throws Exception 异常信息 + */ + ProcessInstance startProcessInstance(String creator_id, String procDefKey, String activity, String next_claim, + String businessKey, + Map variables); + + /** + * 根据流程图key获取所有运行中流程分页 + * @param page + * @param num + * @param procDefKey + * @return + */ + List getProcessInstances(int page, int num, String procDefKey); + + /** + * 流程实例挂起 + * @param procInstId 流程实例ID + */ + void closeProcessInstance(String procInstId); + + /** + * 流程实例激活 + * @param procInstId 流程实例ID + */ + void openProcessInstance(String procInstId); + + /** + * 根据流程定义id获取流程定义实例
+ * 此方法使用了缓存,返回的{@link org.activiti.engine.repository.ProcessDefinition}实例不为activity默认的实例,而是{@link ProcessDefinitionCache},以保证缓存时正常序列化 + * + * @param procDefId 流程定义id + * @return 流程定义实例 + * @throws Exception 异常信息 + */ + ProcessDefinition getProcessDefinition(String procDefId); + + /*** + * 获取job事件 + * @param procInstId 执行ID + */ + Job getJob(String procInstId); + + /*** + * 强制删除job任务,该方法无 api 接口 + * @param jobId + */ + int deleteJob(String jobId); + + /*** + * 查看流程图 + * @param procDefId 流程定义id + * @return + */ + InputStream findProcessPic(String procDefId); +} diff --git a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/BpmTaskService.java b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/BpmTaskService.java new file mode 100644 index 000000000..90079a5ec --- /dev/null +++ b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/BpmTaskService.java @@ -0,0 +1,137 @@ +package org.hswebframework.web.workflow.flowable.service; + +import org.activiti.engine.history.HistoricProcessInstance; +import org.activiti.engine.task.Task; +import org.hswebframework.web.workflow.flowable.entity.TaskInfo; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * 流程任务操作相关接口 + * @Author wangwei + * @Date 2017/8/4. + */ +public interface BpmTaskService{ + + List selectNowTask(String procInstId); + + Task selectTaskByProcessId(String procInstId); + + Task selectTaskByTaskId(String taskId); + + String selectNowTaskName(String procInstId); + + String selectNowTaskId(String procInstId); + + HistoricProcessInstance selectHisProInst(String procInstId); + + /** + * 领取(签收)任务 + * + * @param taskId 任务id + * @param userId 用户id + * @throws Exception 异常信息 + */ + void claim(String taskId, String userId); + + + /** + * 预留等待签收的任务 + * + * @param userId 用户id + * @return 任务信息 + * @throws Exception + */ + List claimList(String userId); + + /** + * 已签收待办理的任务 + * + * @param userId 用户id + * @return 任务信息 + * @throws Exception + */ + List todoList(String userId); + + /** + * 完成任务(环节)并指定下一环节办理人 + * + * @param taskId 任务id + * @param userId 用户id + * @param activityId 人为指定下一执行环节(预留) + * @param next_claim 人为指定下一步执行人(预留) + * @throws Exception 异常信息 + */ + void complete(String taskId, String userId, String activityId, String next_claim); + + /** + * 流程任意跳转 + * @param procInstId 流程实例ID + * @param activity 流程环节ID + * @param next_claim 下一步执行人 + */ + void jumpTask(String procInstId, String activity, String next_claim); + + /** + * 设置办理人 + * + * @param taskId 当前环节ID + * @param userId 用户ID + */ + void setAssignee(String taskId, String userId); + /** + * 结束流程 + * @param procInstId 流程实例ID + */ + void endProcess(String procInstId); + + /** + * 删除历史环节信息 + * @param taskId 环节ID + */ + void removeHiTask(String taskId); + + /** + * 获取所有任务节点 + * @param procDefKey 流程定义Key,该参数获取最新流程 + */ + Map getUserTasksByProcDefKey(String procDefKey); + + /** + * 获取所有任务节点 + * @param procInstId 流程实例ID,该参数获取当前流程实例对应流程 + */ + Map getUserTasksByProcInstId(String procInstId); + + /** + * 设置流程变量 + * + * @param taskId 当前环节ID + * @param map key-value + */ + void setVariables(String taskId,Map map); + + /** + * 删除流程变量 + * + * @param taskId 当前环节ID + * @param var2 需要删除的 key + */ + void removeVariables(String taskId,Collection var2); + + /** + * 设置任务变量 + * + * @param taskId 当前环节ID + */ + void setVariablesLocal(String taskId, Map map); + + /*** + * 获取流程变量 + * @param procInstId 流程实例ID + */ + Map getVariables(String procInstId); + +} diff --git a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/imp/BpmActivityServiceImp.java b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/imp/BpmActivityServiceImp.java new file mode 100644 index 000000000..f37828a36 --- /dev/null +++ b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/imp/BpmActivityServiceImp.java @@ -0,0 +1,102 @@ +package org.hswebframework.web.workflow.flowable.service.imp; + +import org.activiti.engine.impl.RepositoryServiceImpl; +import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; +import org.activiti.engine.impl.pvm.process.ActivityImpl; +import org.activiti.engine.repository.ProcessDefinition; +import org.activiti.engine.runtime.ProcessInstance; +import org.hswebframework.web.workflow.flowable.service.BpmActivityService; +import org.hswebframework.web.workflow.flowable.utils.FlowableAbstract; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Author wangwei + * @Date 2017/8/7. + */ +@Service +public class BpmActivityServiceImp extends FlowableAbstract implements BpmActivityService { + + /** + * 获取指定节点 + * + * @param procDefId 流程定义ID + * @return ActivityImpl 指定的节点资源 + */ + @Override + public ActivityImpl getActivityById(String procDefId, String activityId){ + return getProcessDefinition(procDefId).findActivity(activityId); + } + + @Override + public ActivityImpl getActivityByKey(String procDefKey, String activityId) { + ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(procDefKey).orderByProcessDefinitionVersion().desc().list().get(0); + String procDefId = definition.getId(); + return getProcessDefinition(procDefId).findActivity(activityId); + } + + /** + * 获取所有节点 + * + * @param processDefId 流程定义ID + * @return List 当前流程的所有节点资源 + */ + @Override + public List getActivitys(String processDefId){ + ProcessDefinitionEntity pde = getProcessDefinition(processDefId); + return pde.getActivities(); + } + + /** + * 获取所有userTask + * + * @param procDefId 流程定义ID + * @return List 当前流程的所有userTask资源 + */ + @Override + public List getUserTasks(String procDefId){ + ProcessDefinitionEntity pde = getProcessDefinition(procDefId); + List activityList = new ArrayList<>(); + for(ActivityImpl activity : pde.getActivities()){ + if(activity.getProperty("type").equals("userTask")) + activityList.add(activity); + } + return activityList; + } + + /** + * 获取结束节点 + * @param procDefId 流程定义ID + * @return ActivityImpl 当前流程的结束资源 + */ + @Override + public ActivityImpl getEndActivityImpl(String procDefId){ + ProcessDefinitionEntity pde = getProcessDefinition(procDefId); + for(ActivityImpl activity : pde.getActivities()){ + if(activity.getProperty("type").equals("endEvent")) + return activity; + } + return null; + } + + /** + * 获取流程定义 + * + * @param procDefId 流程定义ID + * @return 流程定义资源 + */ + public ProcessDefinitionEntity getProcessDefinition(String procDefId){ + return (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(procDefId); + } + + @Override + public ActivityImpl getActivityByProcInstId(String procDefId, String procInstId) { + ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(procInstId) + .active().singleResult(); + String activityId = processInstance.getActivityId(); + + return getProcessDefinition(procDefId).findActivity(activityId); + } +} diff --git a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/imp/BpmProcessServiceImp.java b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/imp/BpmProcessServiceImp.java new file mode 100644 index 000000000..90e257484 --- /dev/null +++ b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/imp/BpmProcessServiceImp.java @@ -0,0 +1,113 @@ +package org.hswebframework.web.workflow.flowable.service.imp; + +import org.activiti.engine.impl.RepositoryServiceImpl; +import org.activiti.engine.impl.persistence.entity.ExecutionEntity; +import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; +import org.activiti.engine.impl.pvm.process.ActivityImpl; +import org.activiti.engine.impl.pvm.process.ProcessDefinitionImpl; +import org.activiti.engine.repository.ProcessDefinition; +import org.activiti.engine.runtime.Job; +import org.activiti.engine.runtime.ProcessInstance; +import org.activiti.engine.runtime.ProcessInstanceQuery; +import org.activiti.engine.task.Task; +import org.hswebframework.utils.StringUtils; +import org.hswebframework.web.workflow.flowable.service.BpmProcessService; +import org.hswebframework.web.workflow.flowable.service.BpmTaskService; +import org.hswebframework.web.workflow.flowable.utils.FlowableAbstract; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.io.InputStream; +import java.util.List; +import java.util.Map; + +/** + * @Author wangwei + * @Date 2017/8/7. + */ +@Service +public class BpmProcessServiceImp extends FlowableAbstract implements BpmProcessService { + protected Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Resource + BpmTaskService bpmTaskService; + + @Override + public ProcessInstance startProcessInstance(String creator_id,String procDefKey,String activity,String next_claim, + String businessKey, + Map variables){ + logger.debug("start flow :", procDefKey); + ProcessInstance processInstance = null; + try{ + // 用来设置启动流程的人员ID,引擎会自动把用户ID保存到activiti:initiator中 + identityService.setAuthenticatedUserId(creator_id); + logger.debug("流程启动,work_flow_key:{}", procDefKey); + logger.debug("表单ID,businessKey:{}",businessKey); + logger.debug("流程变量保存,variables:{}",variables); + //启动流程,返回流程实例 + processInstance = runtimeService.startProcessInstanceByKey(procDefKey, businessKey, variables); + //获取流程实例ID + String processInstanceId = processInstance.getId(); + logger.debug("流程启动成功,流程ID:{}",processInstanceId); + Task task = bpmTaskService.selectTaskByProcessId(processInstanceId); + //如果指定了下一步执行环节,则将流程跳转到指定环节,并删除当前未执行的环节历史信息 + if(!StringUtils.isNullOrEmpty(activity)){ + bpmTaskService.jumpTask(processInstanceId,activity,StringUtils.isNullOrEmpty(next_claim)?"":next_claim); + bpmTaskService.removeHiTask(task.getId()); + }else{ + //流程签收,签收人为指定办理人 + if(!StringUtils.isNullOrEmpty(next_claim)) + bpmTaskService.claim(task.getId(), next_claim); + } + + if (logger.isDebugEnabled()) + logger.debug("start process of {key={}, bkey={}, pid={}, variables={}}", new Object[]{procDefKey, businessKey, processInstanceId, variables}); + }catch (Exception e){ + logger.warn("工作流启动失败,请联系管理员!"); + }finally { + identityService.setAuthenticatedUserId(null); + } + return processInstance; + } + + @Override + public List getProcessInstances(int page, int num, String procDefKey) { + return runtimeService.createProcessInstanceQuery().processDefinitionKey(procDefKey).listPage(page, num); + } + + @Override + public void closeProcessInstance(String processInstanceId) { + runtimeService.suspendProcessInstanceById(processInstanceId); + } + + @Override + public void openProcessInstance(String processInstanceId) { + runtimeService.activateProcessInstanceById(processInstanceId); + } + + @Override + public ProcessDefinition getProcessDefinition(String processDefinitionId){ + return repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult(); + } + + @Override + public InputStream findProcessPic(String procDefId) { + ProcessDefinition definition = getProcessDefinition(procDefId); + String source = definition.getDiagramResourceName(); + InputStream inputStream = repositoryService.getResourceAsStream(definition.getDeploymentId(),source); + return inputStream; + } + + @Override + public Job getJob(String processInstanceId) { + return managementService.createJobQuery().processInstanceId(processInstanceId).singleResult(); + } + + @Override + public int deleteJob(String jobId) { + return 0; + } + +} diff --git a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/imp/BpmTaskServiceImp.java b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/imp/BpmTaskServiceImp.java new file mode 100644 index 000000000..3555f1d2f --- /dev/null +++ b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/imp/BpmTaskServiceImp.java @@ -0,0 +1,218 @@ +package org.hswebframework.web.workflow.flowable.service.imp; + +import org.activiti.engine.history.HistoricProcessInstance; +import org.activiti.engine.impl.TaskServiceImpl; +import org.activiti.engine.impl.pvm.process.ActivityImpl; +import org.activiti.engine.runtime.Execution; +import org.activiti.engine.runtime.ProcessInstance; +import org.activiti.engine.task.Task; +import org.hswebframework.utils.StringUtils; +import org.hswebframework.web.workflow.flowable.entity.TaskInfo; +import org.hswebframework.web.workflow.flowable.service.BpmTaskService; +import org.hswebframework.web.workflow.flowable.service.BpmActivityService; +import org.hswebframework.web.workflow.flowable.utils.FlowableAbstract; +import org.hswebframework.web.workflow.flowable.utils.JumpTaskCmd; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.*; + +/** + * @Author wangwei + * @Date 2017/8/7. + */ +@Service +public class BpmTaskServiceImp extends FlowableAbstract implements BpmTaskService { + + protected Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Resource + BpmActivityService bpmActivityService; + + @Override + public List selectNowTask(String procInstId) { + return taskService.createTaskQuery().processInstanceId(procInstId).list(); + } + + @Override + public Task selectTaskByProcessId(String procInstId){ + return taskService.createTaskQuery().processInstanceId(procInstId).singleResult(); + } + + @Override + public Task selectTaskByTaskId(String taskId){ + return taskService.createTaskQuery().taskId(taskId).singleResult(); + } + + @Override + public String selectNowTaskName(String procInstId) { + List tasks = selectNowTask(procInstId); + if (tasks.size() == 1) + return tasks.get(0).getName(); + else { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < tasks.size(); i++) { + if (i != 0) + builder.append(","); + builder.append(tasks.get(i).getName()); + } + return builder.toString(); + } + + } + + @Override + public String selectNowTaskId(String procInstId) { + List tasks = selectNowTask(procInstId); + if (tasks.size() == 1) + return tasks.get(0).getId(); + else { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < tasks.size(); i++) { + if (i != 0) + builder.append(","); + builder.append(tasks.get(i).getId()); + } + return builder.toString(); + } + } + + @Override + public void claim(String taskId, String userId){ + Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); + if (task == null) + logger.warn("获取任务失败!"); + if (!StringUtils.isNullOrEmpty(task.getAssignee())) { + logger.warn("该任务已被签收!"); + }else taskService.claim(taskId, userId); + } + + + @Override + public List claimList(String userId){ + List list = new ArrayList<>(); + // 等待签收的任务 + List todoList = taskService.createTaskQuery().taskCandidateUser(userId).includeProcessVariables().active().list(); + return list; + } + + @Override + public List todoList(String userId){ + List list = new ArrayList<>(); + // 已经签收的任务 + List todoList = taskService.createTaskQuery().taskAssignee(userId).includeProcessVariables().active().list(); + return list; + } + + @Override + public void complete(String workFlowId, String userId, String activityId, String next_claim){ + String taskId = selectNowTaskId(workFlowId); + Task task = taskService.createTaskQuery().taskId(taskId).includeProcessVariables().singleResult(); + if (task == null) + logger.warn("任务不存在!"); + String assignee = task.getAssignee(); + if (null == assignee) + logger.warn("请先签收任务!"); + if (!userId.equals(assignee)) { + logger.warn("只能完成自己的任务"); + } + //完成此任务 + if (activityId == null) { + taskService.complete(taskId); + }else{ + jumpTask(workFlowId,activityId,next_claim); + } + + //根据流程ID查找执行计划,存在则进行下一步,没有则结束工单 + List execution = runtimeService.createExecutionQuery().processInstanceId(workFlowId).list(); + if(execution.size()>0){ + String tasknow = selectNowTaskId(workFlowId); + // 自定义下一执行人 + if(!StringUtils.isNullOrEmpty(next_claim)) + claim(tasknow, next_claim); + } + } + + @Override + public void jumpTask(String procInstId, String activity, String next_claim){ + Task task = selectTaskByProcessId(procInstId); + TaskServiceImpl taskServiceImpl=(TaskServiceImpl)taskService; + taskServiceImpl.getCommandExecutor().execute(new JumpTaskCmd(task.getExecutionId(), activity)); + task = selectTaskByProcessId(procInstId); + if(null != task && !StringUtils.isNullOrEmpty(next_claim)) + claim(task.getId(), next_claim); + } + + @Override + public void setAssignee(String taskId,String userId){ + taskService.setAssignee(taskId,userId); + } + + @Override + public void endProcess(String procInstId){ + ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult(); + ActivityImpl activity = bpmActivityService.getEndActivityImpl(processInstance.getProcessDefinitionId()); + jumpTask(procInstId,activity.getId(),null); + } + + @Override + public void removeHiTask(String taskId){ + historyService.deleteHistoricTaskInstance(taskId); + } + + @Override + public HistoricProcessInstance selectHisProInst(String procInstId) { + return historyService.createHistoricProcessInstanceQuery().processInstanceId(procInstId).singleResult(); + } + + @Override + public Map getUserTasksByProcDefKey(String procDefKey){ + String definitionId = repositoryService.createProcessDefinitionQuery().processDefinitionKey(procDefKey).orderByProcessDefinitionVersion().desc().list().get(0).getId(); + List activitiList = bpmActivityService.getUserTasks(definitionId); + Map map = new HashMap<>(); + for(ActivityImpl activity:activitiList){ + map.put(activity.getId(),activity.getProperty("name")); + } + return map; + } + + @Override + public Map getUserTasksByProcInstId(String procInstId) { + String definitionId = runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult().getProcessDefinitionId(); + List activitiList = bpmActivityService.getUserTasks(definitionId); + Map map = new HashMap<>(); + for(ActivityImpl activity:activitiList){ + map.put(activity.getId(),activity.getProperty("name")); + } + return map; + } + + @Override + public void setVariables(String taskId, Map map) { + taskService.setVariables(taskId,map); + } + + @Override + public void removeVariables(String taskId, Collection var2) { + taskService.removeVariables(taskId,var2); + } + + @Override + public void setVariablesLocal(String taskId, Map map) { + taskService.setVariablesLocal(taskId,map); + } + + @Override + public Map getVariables(String procInstId) { + List executions = runtimeService.createExecutionQuery().processInstanceId(procInstId).list(); + String executionId = ""; + for(Execution execution : executions){ + if(StringUtils.isNullOrEmpty(execution.getParentId())){ + executionId = execution.getId(); + } + } + return runtimeService.getVariables(executionId); + } +} diff --git a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/java/org/hswebframework/web/workflow/flowable/ControllerTest.java b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/java/org/hswebframework/web/workflow/flowable/ControllerTest.java index 68a66d828..72ee5f224 100644 --- a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/java/org/hswebframework/web/workflow/flowable/ControllerTest.java +++ b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/java/org/hswebframework/web/workflow/flowable/ControllerTest.java @@ -1,17 +1,86 @@ package org.hswebframework.web.workflow.flowable; +import com.alibaba.fastjson.JSON; +import org.activiti.engine.*; +import org.activiti.engine.impl.RepositoryServiceImpl; +import org.activiti.engine.impl.interceptor.SessionFactory; +import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; +import org.activiti.engine.impl.pvm.process.ProcessDefinitionImpl; +import org.activiti.engine.repository.ProcessDefinition; +import org.activiti.engine.runtime.ProcessInstance; +import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer; +import org.hswebframework.web.tests.SimpleWebApplicationTests; +import org.hswebframework.web.workflow.flowable.service.BpmProcessService; +import org.hswebframework.web.workflow.flowable.utils.FlowableAbstract; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * @Author wangwei * @Date 2017/8/1. */ -@SpringBootApplication -public class ControllerTest { +public class ControllerTest extends SimpleWebApplicationTests { - public static void main(String[] args) { - SpringApplication.run(ControllerTest.class,args); + @Resource + protected RepositoryService repositoryService; + @Autowired + BpmProcessService bpmProcessService; + + public ProcessInstance start() throws Exception { + Map map = new HashMap<>(); + map.put("username", "admin"); + return bpmProcessService.startProcessInstance("1", "test", null, null, "流程名", map); } + @Test + public void test() { + ProcessInstance processInstance = null; + String aid = ""; + try { + processInstance = start(); + System.out.println("流程已启动:" + processInstance.toString()); + int i = bpmProcessService.getProcessInstances(0, 10, "test").size(); + System.out.println("当前活动流程数:" + i); + aid = processInstance.getActivityId(); + System.out.println("当前流程节点ID_" + aid); + } catch (Exception e) { + System.out.println("启动流程失败" + e); + } + ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(repositoryService.createProcessDefinitionQuery().processDefinitionKey("test").singleResult().getId()); + System.out.println("========="); + System.out.println(processDefinitionEntity.getActivities()); + System.out.println(processDefinitionEntity.findActivity(aid)); + System.out.println("========="); + } + + @Configuration + public static class config { + @Autowired(required = false) + private List sessionFactories; + + @Bean + public ProcessEngineConfigurationConfigurer processEngineConfigurationConfigurer() { + return configuration -> { + configuration + .setAsyncExecutorActivate(false) + .setJobExecutorActivate(false) + .setActivityFontName("宋体") + .setLabelFontName("宋体") + .setAnnotationFontName("宋体"); + + if (sessionFactories != null) { + configuration.setCustomSessionFactories(sessionFactories); + } + }; + } + } } diff --git a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/java/org/hswebframework/web/workflow/flowable/test/ServiceTest.java b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/java/org/hswebframework/web/workflow/flowable/test/ServiceTest.java index 2f0eb261a..5c277a780 100644 --- a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/java/org/hswebframework/web/workflow/flowable/test/ServiceTest.java +++ b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/java/org/hswebframework/web/workflow/flowable/test/ServiceTest.java @@ -1,5 +1,6 @@ package org.hswebframework.web.workflow.flowable.test; +import org.activiti.engine.repository.ProcessDefinition; import org.hswebframework.web.workflow.flowable.utils.FlowableAbstract; import org.junit.Test; import org.junit.runner.RunWith; @@ -15,7 +16,8 @@ public class ServiceTest extends FlowableAbstract { @Test public void getProcessDefinition(){ - + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("test").singleResult(); + System.out.println(processDefinition); } } \ No newline at end of file diff --git a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/resources/application.yml b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/resources/application.yml index 7a766e2e9..10ea18e60 100644 --- a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/resources/application.yml +++ b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/resources/application.yml @@ -1,4 +1,3 @@ - spring: aop: auto: true @@ -14,7 +13,6 @@ spring: logging: level: - org.hsweb: debug org.flowable: debug mybatis: dynamic-datasource: false diff --git a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/resources/processes/SimpleProcess.bpmn20.xml b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/resources/processes/SimpleProcess.bpmn20.xml index d3a91a7ba..6f1896bbf 100644 --- a/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/resources/processes/SimpleProcess.bpmn20.xml +++ b/hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/resources/processes/SimpleProcess.bpmn20.xml @@ -1,56 +1,75 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - + + + + - - + + - - + + - - - - - + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + +