wangwei 7 년 전
부모
커밋
0ab98e613d
14개의 변경된 파일1049개의 추가작업 그리고 64개의 파일을 삭제
  1. 5 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/pom.xml
  2. 0 9
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/FlowableAutoConfiguration.java
  3. 63 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/controller/BpmDeploymentController.java
  4. 126 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/entity/TaskInfo.java
  5. 59 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/BpmActivityService.java
  6. 83 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/BpmProcessService.java
  7. 137 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/BpmTaskService.java
  8. 102 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/imp/BpmActivityServiceImp.java
  9. 113 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/imp/BpmProcessServiceImp.java
  10. 218 0
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/main/java/org/hswebframework/web/workflow/flowable/service/imp/BpmTaskServiceImp.java
  11. 73 4
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/java/org/hswebframework/web/workflow/flowable/ControllerTest.java
  12. 3 1
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/java/org/hswebframework/web/workflow/flowable/test/ServiceTest.java
  13. 0 2
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/resources/application.yml
  14. 67 48
      hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/resources/processes/SimpleProcess.bpmn20.xml

+ 5 - 0
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/pom.xml

@@ -142,5 +142,10 @@
             <version>${project.version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.hswebframework.web</groupId>
+            <artifactId>hsweb-tests</artifactId>
+            <version>3.0-SNAPSHOT</version>
+        </dependency>
     </dependencies>
 </project>

+ 0 - 9
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 {

+ 63 - 0
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');
+     *      <div>
+                <#if message??>
+                    <h1>${message!}</h1>
+                <#else>
+                    <img src="${application.getContextPath()}/workflow/document/alldoc/findPic/${procDefId!}">
+                    <!-- 给执行的节点加框 -->
+                    <div style="position:absolute; border:2px solid red;left:${activity.x+6 }px;
+                    top:${activity.y+6 }px;width:${activity.width }px;height:${activity.height }px;"></div>
+                </#if>
+            </div>
+     */
+    @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);
+        }
+    }
 }

+ 126 - 0
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<String> {
+
+    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<String, Object> 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;
+    }
+}

+ 59 - 0
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<ActivityImpl>  当前流程的所有节点资源
+     */
+    List<ActivityImpl> getActivitys(String procDefId);
+
+    /**
+     * 获取所有userTask
+     *
+     * @param procDefId        流程定义ID
+     * @return List<ActivityImpl>  当前流程的所有userTask资源
+     */
+    List<ActivityImpl> 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);
+}

+ 83 - 0
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<String, Object> variables);
+
+    /**
+     * 根据流程图key获取所有运行中流程分页
+     * @param page
+     * @param num
+     * @param procDefKey
+     * @return
+     */
+    List<ProcessInstance> getProcessInstances(int page, int num, String procDefKey);
+
+    /**
+     * 流程实例挂起
+     * @param procInstId 流程实例ID
+     */
+    void closeProcessInstance(String procInstId);
+
+    /**
+     * 流程实例激活
+     * @param procInstId 流程实例ID
+     */
+    void openProcessInstance(String procInstId);
+
+    /**
+     * 根据流程定义id获取流程定义实例<br/>
+     * 此方法使用了缓存,返回的{@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);
+}

+ 137 - 0
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<Task> 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<TaskInfo> claimList(String userId);
+
+    /**
+     * 已签收待办理的任务
+     *
+     * @param userId 用户id
+     * @return 任务信息
+     * @throws Exception
+     */
+    List<TaskInfo> 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<String,Object> getUserTasksByProcDefKey(String procDefKey);
+
+    /**
+     * 获取所有任务节点
+     * @param procInstId            流程实例ID,该参数获取当前流程实例对应流程
+     */
+    Map<String,Object> getUserTasksByProcInstId(String procInstId);
+
+    /**
+     * 设置流程变量
+     *
+     * @param taskId   当前环节ID
+     * @param map   key-value
+     */
+    void setVariables(String taskId,Map<String ,Object> map);
+
+    /**
+     * 删除流程变量
+     *
+     * @param taskId   当前环节ID
+     * @param var2   需要删除的 key
+     */
+    void removeVariables(String taskId,Collection<String> var2);
+
+    /**
+     * 设置任务变量
+     *
+     * @param taskId   当前环节ID
+     */
+    void setVariablesLocal(String taskId, Map<String, Object> map);
+
+    /***
+     * 获取流程变量
+     * @param procInstId  流程实例ID
+     */
+    Map<String,Object> getVariables(String procInstId);
+
+}

+ 102 - 0
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<ActivityImpl>  当前流程的所有节点资源
+     */
+    @Override
+    public List<ActivityImpl> getActivitys(String processDefId){
+        ProcessDefinitionEntity pde = getProcessDefinition(processDefId);
+        return pde.getActivities();
+    }
+
+    /**
+     * 获取所有userTask
+     *
+     * @param procDefId        流程定义ID
+     * @return List<ActivityImpl>  当前流程的所有userTask资源
+     */
+    @Override
+    public List<ActivityImpl> getUserTasks(String procDefId){
+        ProcessDefinitionEntity pde = getProcessDefinition(procDefId);
+        List<ActivityImpl> 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);
+    }
+}

+ 113 - 0
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<String, Object> 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<ProcessInstance> 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;
+    }
+
+}

+ 218 - 0
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<Task> 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<Task> 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<Task> 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<TaskInfo> claimList(String userId){
+        List<TaskInfo> list = new ArrayList<>();
+        // 等待签收的任务
+        List<Task> todoList = taskService.createTaskQuery().taskCandidateUser(userId).includeProcessVariables().active().list();
+        return list;
+    }
+
+    @Override
+    public List<TaskInfo> todoList(String userId){
+        List<TaskInfo> list = new ArrayList<>();
+        // 已经签收的任务
+        List<Task> 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> 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<String,Object> getUserTasksByProcDefKey(String procDefKey){
+        String definitionId = repositoryService.createProcessDefinitionQuery().processDefinitionKey(procDefKey).orderByProcessDefinitionVersion().desc().list().get(0).getId();
+        List<ActivityImpl> activitiList = bpmActivityService.getUserTasks(definitionId);
+        Map<String,Object> map = new HashMap<>();
+        for(ActivityImpl activity:activitiList){
+            map.put(activity.getId(),activity.getProperty("name"));
+        }
+        return map;
+    }
+
+    @Override
+    public Map<String, Object> getUserTasksByProcInstId(String procInstId) {
+        String definitionId = runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult().getProcessDefinitionId();
+        List<ActivityImpl> activitiList = bpmActivityService.getUserTasks(definitionId);
+        Map<String,Object> map = new HashMap<>();
+        for(ActivityImpl activity:activitiList){
+            map.put(activity.getId(),activity.getProperty("name"));
+        }
+        return map;
+    }
+
+    @Override
+    public void setVariables(String taskId, Map<String, Object> map) {
+        taskService.setVariables(taskId,map);
+    }
+
+    @Override
+    public void removeVariables(String taskId, Collection<String> var2) {
+        taskService.removeVariables(taskId,var2);
+    }
+
+    @Override
+    public void setVariablesLocal(String taskId, Map<String, Object> map) {
+        taskService.setVariablesLocal(taskId,map);
+    }
+
+    @Override
+    public Map<String, Object> getVariables(String procInstId) {
+        List<Execution> executions = runtimeService.createExecutionQuery().processInstanceId(procInstId).list();
+        String executionId = "";
+        for(Execution execution : executions){
+            if(StringUtils.isNullOrEmpty(execution.getParentId())){
+                executionId = execution.getId();
+            }
+        }
+        return runtimeService.getVariables(executionId);
+    }
+}

+ 73 - 4
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 {
+
+    @Resource
+    protected RepositoryService repositoryService;
+    @Autowired
+    BpmProcessService bpmProcessService;
+
+    public ProcessInstance start() throws Exception {
+        Map<String, Object> map = new HashMap<>();
+        map.put("username", "admin");
+        return bpmProcessService.startProcessInstance("1", "test", null, null, "流程名", map);
+    }
 
-    public static void main(String[] args) {
-        SpringApplication.run(ControllerTest.class,args);
+    @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<SessionFactory> sessionFactories;
+
+        @Bean
+        public ProcessEngineConfigurationConfigurer processEngineConfigurationConfigurer() {
+            return configuration -> {
+                configuration
+                        .setAsyncExecutorActivate(false)
+                        .setJobExecutorActivate(false)
+                        .setActivityFontName("宋体")
+                        .setLabelFontName("宋体")
+                        .setAnnotationFontName("宋体");
+
+                if (sessionFactories != null) {
+                    configuration.setCustomSessionFactories(sessionFactories);
+                }
+            };
+        }
+    }
 }

+ 3 - 1
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);
     }
 
 }

+ 0 - 2
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

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 67 - 48
hsweb-system/hsweb-system-workflow/hsweb-system-workflow-flowable/src/test/resources/processes/SimpleProcess.bpmn20.xml