├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── src ├── main │ ├── java │ │ └── com │ │ │ └── activiti6 │ │ │ └── demo │ │ │ ├── vo │ │ │ ├── BaseVo.java │ │ │ ├── IsFinishProcessReq.java │ │ │ ├── DeleteTaskReq.java │ │ │ ├── QueryWaitTaskReq.java │ │ │ ├── QueryTaskHistoryReq.java │ │ │ ├── QueryProcessInstanceReq.java │ │ │ ├── GroupReq.java │ │ │ ├── ClaimTaskReq.java │ │ │ ├── MembershipReq.java │ │ │ ├── ViewProcessInstanceImageReq.java │ │ │ ├── QueryTaskReq.java │ │ │ ├── StartProcessInstanceReq.java │ │ │ ├── UserReq.java │ │ │ ├── CompleteTaskReq.java │ │ │ ├── ProcessDefinitionVo.java │ │ │ ├── HistoricTaskInstanceVo.java │ │ │ └── TaskVo.java │ │ │ ├── Activiti6DemoApplication.java │ │ │ ├── util │ │ │ ├── ResponseEnum.java │ │ │ └── R.java │ │ │ ├── service │ │ │ ├── ActivitiService.java │ │ │ └── impl │ │ │ │ └── ActivitiServiceImpl.java │ │ │ └── controller │ │ │ ├── FlowTaskProvider.java │ │ │ ├── FlowUserProvider.java │ │ │ └── ProcessDefinitionProvider.java │ └── resources │ │ ├── application.yml │ │ └── processes │ │ └── mymodel1.bpmn20.xml └── test │ └── java │ └── com │ └── activiti6 │ └── demo │ └── Activiti6DemoApplicationTests.java ├── .gitignore ├── mvnw.cmd ├── pom.xml ├── mvnw └── README.md /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/allengrit2211/Activiti6Demo/HEAD/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.3/apache-maven-3.5.3-bin.zip 2 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/vo/BaseVo.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.vo; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * @Auther: Allen 7 | * @Date: 2018/7/27 11:25 8 | * @Description: 9 | */ 10 | public class BaseVo implements Serializable { 11 | } 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /src/test/java/com/activiti6/demo/Activiti6DemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class Activiti6DemoApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/vo/IsFinishProcessReq.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.vo; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | 9 | 10 | @Data 11 | @ApiModel 12 | public class IsFinishProcessReq { 13 | 14 | @ApiModelProperty(value = "实例ID", notes = "实例ID", required = true, dataType = "String") 15 | @NotBlank(message = "实例ID不能为空") 16 | private String processInstanceId; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/Activiti6DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo; 2 | 3 | import org.activiti.spring.boot.SecurityAutoConfiguration; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | @SpringBootApplication(exclude = SecurityAutoConfiguration.class) 8 | 9 | public class Activiti6DemoApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(Activiti6DemoApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/vo/DeleteTaskReq.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.vo; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | 9 | /** 10 | * @Auther: Allen 11 | * @Date: 2018/7/27 13:38 12 | * @Description: 13 | */ 14 | @Data 15 | @ApiModel 16 | public class DeleteTaskReq { 17 | 18 | @ApiModelProperty(value = "任务ID", notes = "任务ID", required = true, dataType = "String") 19 | @NotBlank(message = "任务ID不能为空") 20 | private String taskId; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/vo/QueryWaitTaskReq.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.vo; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | /** 8 | * @Auther: Allen 9 | * @Date: 2018/7/27 11:22 10 | * @Description: 11 | */ 12 | @Data 13 | @ApiModel 14 | public class QueryWaitTaskReq{ 15 | 16 | @ApiModelProperty(value = "开始记录数", notes = "开始记录数", dataType = "int") 17 | private int firstResult = 0; 18 | 19 | @ApiModelProperty(value = "每页记录数", notes = "每页记录数", dataType = "int" ) 20 | private int maxResults = 100; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/vo/QueryTaskHistoryReq.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.vo; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | 9 | /** 10 | * @Auther: Allen 11 | * @Date: 2018/7/27 13:46 12 | * @Description: 13 | */ 14 | @Data 15 | @ApiModel 16 | public class QueryTaskHistoryReq { 17 | 18 | @ApiModelProperty(value = "实例ID", notes = "实例ID", required = true, dataType = "String") 19 | @NotBlank(message = "实例ID不能为空") 20 | private String processInstanceId; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/vo/QueryProcessInstanceReq.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.vo; 2 | 3 | 4 | import io.swagger.annotations.ApiModel; 5 | import io.swagger.annotations.ApiModelProperty; 6 | import lombok.Data; 7 | 8 | import javax.validation.constraints.NotBlank; 9 | 10 | 11 | /** 12 | * @author Allen 13 | * @Date: 2018/7/27 10:10 14 | * @Description: 开始流程实例请求类 15 | */ 16 | @Data 17 | @ApiModel 18 | public class QueryProcessInstanceReq { 19 | 20 | @ApiModelProperty(value = "实例名称", notes = "实例名称", dataType = "String") 21 | @NotBlank(message = "实例名称不能为空") 22 | private String instanceKey; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/vo/GroupReq.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.vo; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | 9 | /** 10 | * @Auther: Allen 11 | * @Date: 2018/7/30 14:51 12 | * @Description: 13 | */ 14 | @Data 15 | @ApiModel 16 | public class GroupReq { 17 | 18 | @ApiModelProperty(value = "用户组ID", notes = "用户组ID", required = true, dataType = "String") 19 | @NotBlank(message = "用户组ID不能为空") 20 | private String id; 21 | 22 | @ApiModelProperty(value = "用户组名称", notes = "用户组名称", required = true, dataType = "String") 23 | private String name; 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/util/ResponseEnum.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.util; 2 | 3 | public enum ResponseEnum { 4 | SUCCESS(0, "success"), 5 | FAIL(1, "未知异常,请联系管理员"), 6 | NO_LOGIN(-1, "登录失效,请重新登录"), 7 | NO_PERMISSION(2, "没有权限禁止访问"); 8 | 9 | private int code; 10 | private String msg; 11 | 12 | public int getCode() { 13 | return this.code; 14 | } 15 | 16 | public void setCode(int code) { 17 | this.code = code; 18 | } 19 | 20 | public String getMsg() { 21 | return this.msg; 22 | } 23 | 24 | public void setMsg(String msg) { 25 | this.msg = msg; 26 | } 27 | 28 | private ResponseEnum(int code, String msg) { 29 | this.code = code; 30 | this.msg = msg; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/vo/ClaimTaskReq.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.vo; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | 9 | /** 10 | * @Auther: Allen 11 | * @Date: 2018/7/27 13:41 12 | * @Description: 指派任务请求对象 13 | */ 14 | @Data 15 | @ApiModel 16 | public class ClaimTaskReq { 17 | 18 | @ApiModelProperty(value = "任务ID", notes = "任务ID", required = true, dataType = "String") 19 | @NotBlank(message = "任务ID不能为空") 20 | private String taskId; 21 | 22 | 23 | @ApiModelProperty(value = "审批人", notes = "审批人", required = true, dataType = "String") 24 | @NotBlank(message = "审批人不能为空") 25 | private String assignee; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/vo/MembershipReq.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.vo; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | 9 | /** 10 | * @Auther: Allen 11 | * @Date: 2018/7/30 15:41 12 | * @Description: 用户与组关联请求对象 13 | */ 14 | @Data 15 | @ApiModel 16 | public class MembershipReq{ 17 | 18 | @ApiModelProperty(value = "用户ID", notes = "用户ID", required = true, dataType = "String") 19 | @NotBlank(message = "用户ID不能为空") 20 | private String userId; 21 | 22 | @ApiModelProperty(value = "用户组ID", notes = "用户组ID", required = true, dataType = "String") 23 | @NotBlank(message = "用户组ID不能为空") 24 | private String groupId; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/vo/ViewProcessInstanceImageReq.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.vo; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | 9 | 10 | /** 11 | * @author Allen 12 | * @Date: 2018/7/27 10:10 13 | * @Description: 流程实例处理状态请求对象 14 | */ 15 | @Data 16 | @ApiModel 17 | public class ViewProcessInstanceImageReq { 18 | 19 | 20 | @ApiModelProperty(value = "实例名称", notes = "实例名称", dataType = "String") 21 | @NotBlank(message = "实例名称不能为空") 22 | private String instanceKey; 23 | 24 | @ApiModelProperty(value = "实例ID", notes = "实例ID", required = true, dataType = "String") 25 | @NotBlank(message = "实例ID不能为空") 26 | private String processInstanceId; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/vo/QueryTaskReq.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.vo; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | /** 8 | * @Auther: Allen 9 | * @Date: 2018/7/27 10:53 10 | * @Description: 查询待办请求对象 11 | */ 12 | @Data 13 | @ApiModel 14 | public class QueryTaskReq { 15 | 16 | 17 | @ApiModelProperty(value = "开始记录数", notes = "开始记录数", dataType = "int") 18 | private int firstResult = 0; 19 | 20 | @ApiModelProperty(value = "每页记录数", notes = "每页记录数", dataType = "int" ) 21 | private int maxResults = 100; 22 | 23 | @ApiModelProperty(value = "处理人", notes = "处理人", dataType = "String" ) 24 | private String assignee; 25 | 26 | @ApiModelProperty(value = "候选用户", notes = "候选用户", dataType = "String" ) 27 | private String candidateUser; 28 | 29 | @ApiModelProperty(value = "候选用户组", notes = "候选用户组", dataType = "String" ) 30 | private String candidateGroup; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/vo/StartProcessInstanceReq.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.vo; 2 | 3 | 4 | import io.swagger.annotations.ApiModel; 5 | import io.swagger.annotations.ApiModelProperty; 6 | import lombok.Data; 7 | 8 | import javax.validation.constraints.NotBlank; 9 | import java.util.Map; 10 | 11 | /** 12 | * @author Allen 13 | * @Date: 2018/7/27 10:10 14 | * @Description: 开始流程实例请求类 15 | */ 16 | @Data 17 | @ApiModel 18 | public class StartProcessInstanceReq { 19 | 20 | 21 | @ApiModelProperty(value = "实例名称", notes = "实例名称", required = true, dataType = "String") 22 | @NotBlank(message = "实例名称不能为空") 23 | private String instanceKey; 24 | 25 | 26 | @ApiModelProperty(value = "流程发起人", notes = "流程发起人", required = true, dataType = "String") 27 | @NotBlank(message = "流程发起人不能为空") 28 | private String applyUserId; 29 | 30 | 31 | @ApiModelProperty(value = "自定义参数", notes = "自定义参数", required = true, dataType = "Map") 32 | private Map variables; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/vo/UserReq.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.vo; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | 9 | /** 10 | * @Auther: Allen 11 | * @Date: 2018/7/30 15:26 12 | * @Description: 13 | */ 14 | @Data 15 | @ApiModel 16 | public class UserReq { 17 | 18 | @ApiModelProperty(value = "用户ID", notes = "用户ID", required = true, dataType = "String") 19 | @NotBlank(message = "用户ID不能为空") 20 | private String id; 21 | 22 | @ApiModelProperty(value = "Email", notes = "Email", required = true, dataType = "String") 23 | private String email; 24 | 25 | @ApiModelProperty(value = "名字", notes = "名字", required = true, dataType = "String") 26 | private String firstName; 27 | 28 | @ApiModelProperty(value = "姓", notes = "姓", required = true, dataType = "String") 29 | private String lastName; 30 | 31 | @ApiModelProperty(value = "密码", notes = "密码", required = true, dataType = "String") 32 | private String password; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/vo/CompleteTaskReq.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.vo; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | import lombok.Data; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | import java.util.Map; 9 | 10 | /** 11 | * @Auther: Allen 12 | * @Date: 2018/7/27 13:25 13 | * @Description: 14 | */ 15 | 16 | @Data 17 | @ApiModel 18 | public class CompleteTaskReq { 19 | 20 | 21 | @ApiModelProperty(value = "任务ID", notes = "任务ID", required = true, dataType = "String") 22 | @NotBlank(message = "任务ID不能为空") 23 | private String taskId; 24 | 25 | @ApiModelProperty(value = "审批人", notes = "审批人", required = true, dataType = "String") 26 | @NotBlank(message = "审批人不能为空") 27 | private String assignee; 28 | 29 | /*** 30 | * 是否通过审核 0 未通过 1 通过 默认值 1 通过 31 | */ 32 | @ApiModelProperty(value = "是否通过审核", notes = "是否通过审核", required = true, dataType = "String") 33 | private int isReviewPass = 1; 34 | 35 | /*** 36 | * 是否返回到开始节点 0 否 1 是 默认0 回退到上一个节点 37 | */ 38 | @ApiModelProperty(value = "是否返回到开始节点", notes = "是否返回到开始节点", required = true, dataType = "String") 39 | private int returnStart = 0; 40 | 41 | @ApiModelProperty(value = "自定义参数", notes = "自定义参数", required = true, dataType = "Map") 42 | private Map variables; 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 1855 3 | 4 | spring: 5 | datasource: 6 | type: com.alibaba.druid.pool.DruidDataSource 7 | driverClassName: com.mysql.jdbc.Driver 8 | url: jdbc:mysql://localhost:3306/activiti?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8 9 | username: root 10 | password: 123123 11 | initial-size: 10 12 | max-active: 100 13 | min-idle: 10 14 | max-wait: 60000 15 | pool-prepared-statements: true 16 | max-pool-prepared-statement-per-connection-size: 20 17 | time-between-eviction-runs-millis: 60000 18 | min-evictable-idle-time-millis: 300000 19 | validation-query: SELECT 1 FROM DUAL 20 | test-while-idle: true 21 | test-on-borrow: false 22 | test-on-return: false 23 | stat-view-servlet: 24 | enabled: true 25 | url-pattern: /druid/* 26 | #login-username: admin 27 | #login-password: admin 28 | filter: 29 | stat: 30 | log-slow-sql: true 31 | slow-sql-millis: 1000 32 | merge-sql: true 33 | wall: 34 | config: 35 | multi-statement-allow: true 36 | jpa: 37 | hibernate: 38 | ddl-auto: update 39 | properties: 40 | hibernate: 41 | dialect: org.hibernate.dialect.MySQL5Dialect 42 | format_sql: true 43 | use_sql_comments: true 44 | show-sql: true 45 | activiti: 46 | database-schema-update: true 47 | check-process-definitions: false 48 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/util/R.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.util; 2 | 3 | import org.springframework.http.HttpStatus; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | public class R extends HashMap { 9 | private static final long serialVersionUID = 1L; 10 | 11 | public R() { 12 | this.put((String)"code", ResponseEnum.SUCCESS.getCode()); 13 | this.put((String)"msg", ResponseEnum.SUCCESS.getMsg()); 14 | } 15 | 16 | public R(ResponseEnum response) { 17 | this.put((String)"code", response.getCode()); 18 | this.put((String)"msg", response.getMsg()); 19 | } 20 | 21 | public static R error() { 22 | return error(ResponseEnum.FAIL.getCode(), ResponseEnum.FAIL.getMsg()); 23 | } 24 | 25 | public static R error(String msg) { 26 | return error(ResponseEnum.FAIL.getCode(), msg); 27 | } 28 | 29 | public static R error(HttpStatus code, String msg) { 30 | R r = new R(); 31 | r.put((String)"code", code); 32 | r.put((String)"msg", msg); 33 | return r; 34 | } 35 | 36 | public static R error(int code, String msg) { 37 | R r = new R(); 38 | r.put((String)"code", code); 39 | r.put((String)"msg", msg); 40 | return r; 41 | } 42 | 43 | public static R ok(String msg) { 44 | R r = new R(); 45 | r.put((String)"msg", msg); 46 | return r; 47 | } 48 | 49 | public static R ok(Map map) { 50 | R r = new R(); 51 | r.putAll(map); 52 | return r; 53 | } 54 | 55 | public static R ok() { 56 | return new R(); 57 | } 58 | 59 | public R put(String key, Object value) { 60 | super.put(key, value); 61 | return this; 62 | } 63 | } -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/service/ActivitiService.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.service; 2 | 3 | import org.activiti.engine.runtime.ProcessInstance; 4 | 5 | import java.io.InputStream; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /**** 10 | * 工作流服务接口 11 | */ 12 | public interface ActivitiService { 13 | 14 | /*** 15 | * 发布规则 16 | * @param bpmnName 17 | */ 18 | public void deploy(String bpmnName); 19 | 20 | 21 | /*** 22 | * 发布规则 23 | * @param fileInputStream 文件流 24 | * @param fileName 文件名称 25 | */ 26 | public void deploy(InputStream fileInputStream, String fileName); 27 | 28 | /*** 29 | * 开始流程 30 | * @param instanceKey 流程实例key 31 | * @param variables 参数 32 | */ 33 | public ProcessInstance startProcessInstance(String instanceKey, Map variables); 34 | 35 | /*** 36 | * 通过key获取流程定义明细列表 37 | * @param instanceKey 38 | * @return 39 | */ 40 | public List processDefinitionQuery(String instanceKey); 41 | 42 | /*** 43 | * 查询用户任务列表 44 | * @param assignee 任务执行人 45 | * @param candidateUser 候选用户 46 | * @param candidateGroup 候选用户组 47 | * @return 48 | */ 49 | public List queryTask(String assignee, String candidateUser, String candidateGroup, int firstResult, int maxResults); 50 | 51 | 52 | /*** 53 | * 查询任务参数 54 | * @param taskId 55 | * @return 56 | */ 57 | public Map queryVariables(String taskId); 58 | 59 | 60 | /*** 61 | * 根据实例ID查询任务审核历史 62 | * @param processInstanceId 实例ID 63 | * @return 64 | */ 65 | public List queryTaskHistory(String processInstanceId); 66 | 67 | /*** 68 | * 完成任务 69 | * @param taskId 任务id 70 | * @param assignee 分配到任务的人 71 | * @param variables 表单参数信息 72 | * @param param 返回值 73 | */ 74 | public void completeTask(String taskId, String assignee, Map variables, Map param); 75 | 76 | /**** 77 | * 任务指派 78 | * @param taskId 79 | * @param assignee 80 | */ 81 | public void claimTask(String taskId, String assignee); 82 | 83 | public void deleteTask(String taskId); 84 | 85 | 86 | /**** 87 | * 流程是否完成 88 | * @param processInstanceId 89 | * @return 90 | */ 91 | public boolean isFinishProcess(String processInstanceId); 92 | 93 | 94 | /*** 95 | * 查询待办任务 96 | * @param firstResult 开始位置 97 | * @param maxResults 最大记录数 98 | * @return 99 | */ 100 | public List queryWaitTask(int firstResult, int maxResults); 101 | 102 | /*** 103 | * 驳回任务 104 | * @param taskId 当前节点 105 | * @param returnStart 是否返回到起点 106 | */ 107 | public void rejectTask(String taskId, String assignee, boolean returnStart); 108 | 109 | 110 | } -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/vo/ProcessDefinitionVo.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.vo; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * @author Allen 7 | * @Date: 2018/6/27 19:38 8 | * @Description: 9 | */ 10 | public class ProcessDefinitionVo extends BaseVo { 11 | 12 | protected String id; 13 | protected String name; 14 | protected String description; 15 | protected String key; 16 | protected int version; 17 | protected String category; 18 | protected String deploymentId; 19 | protected String resourceName; 20 | protected String tenantId = ""; 21 | protected Integer historyLevel; 22 | protected String diagramResourceName; 23 | protected boolean isGraphicalNotationDefined; 24 | protected Map variables; 25 | protected boolean hasStartFormKey; 26 | protected int suspensionState; 27 | protected boolean isIdentityLinksInitialized; 28 | protected String engineVersion; 29 | 30 | public String getId() { 31 | return id; 32 | } 33 | 34 | public void setId(String id) { 35 | this.id = id; 36 | } 37 | 38 | public String getName() { 39 | return name; 40 | } 41 | 42 | public void setName(String name) { 43 | this.name = name; 44 | } 45 | 46 | public String getDescription() { 47 | return description; 48 | } 49 | 50 | public void setDescription(String description) { 51 | this.description = description; 52 | } 53 | 54 | public String getKey() { 55 | return key; 56 | } 57 | 58 | public void setKey(String key) { 59 | this.key = key; 60 | } 61 | 62 | public int getVersion() { 63 | return version; 64 | } 65 | 66 | public void setVersion(int version) { 67 | this.version = version; 68 | } 69 | 70 | public String getCategory() { 71 | return category; 72 | } 73 | 74 | public void setCategory(String category) { 75 | this.category = category; 76 | } 77 | 78 | public String getDeploymentId() { 79 | return deploymentId; 80 | } 81 | 82 | public void setDeploymentId(String deploymentId) { 83 | this.deploymentId = deploymentId; 84 | } 85 | 86 | public String getResourceName() { 87 | return resourceName; 88 | } 89 | 90 | public void setResourceName(String resourceName) { 91 | this.resourceName = resourceName; 92 | } 93 | 94 | public String getTenantId() { 95 | return tenantId; 96 | } 97 | 98 | public void setTenantId(String tenantId) { 99 | this.tenantId = tenantId; 100 | } 101 | 102 | public Integer getHistoryLevel() { 103 | return historyLevel; 104 | } 105 | 106 | public void setHistoryLevel(Integer historyLevel) { 107 | this.historyLevel = historyLevel; 108 | } 109 | 110 | public String getDiagramResourceName() { 111 | return diagramResourceName; 112 | } 113 | 114 | public void setDiagramResourceName(String diagramResourceName) { 115 | this.diagramResourceName = diagramResourceName; 116 | } 117 | 118 | public boolean isGraphicalNotationDefined() { 119 | return isGraphicalNotationDefined; 120 | } 121 | 122 | public void setGraphicalNotationDefined(boolean graphicalNotationDefined) { 123 | isGraphicalNotationDefined = graphicalNotationDefined; 124 | } 125 | 126 | public Map getVariables() { 127 | return variables; 128 | } 129 | 130 | public void setVariables(Map variables) { 131 | this.variables = variables; 132 | } 133 | 134 | public boolean isHasStartFormKey() { 135 | return hasStartFormKey; 136 | } 137 | 138 | public void setHasStartFormKey(boolean hasStartFormKey) { 139 | this.hasStartFormKey = hasStartFormKey; 140 | } 141 | 142 | public int getSuspensionState() { 143 | return suspensionState; 144 | } 145 | 146 | public void setSuspensionState(int suspensionState) { 147 | this.suspensionState = suspensionState; 148 | } 149 | 150 | public boolean isIdentityLinksInitialized() { 151 | return isIdentityLinksInitialized; 152 | } 153 | 154 | public void setIdentityLinksInitialized(boolean identityLinksInitialized) { 155 | isIdentityLinksInitialized = identityLinksInitialized; 156 | } 157 | 158 | public String getEngineVersion() { 159 | return engineVersion; 160 | } 161 | 162 | public void setEngineVersion(String engineVersion) { 163 | this.engineVersion = engineVersion; 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/controller/FlowTaskProvider.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.controller; 2 | 3 | import com.activiti6.demo.service.ActivitiService; 4 | import com.activiti6.demo.util.R; 5 | import com.activiti6.demo.vo.*; 6 | import io.swagger.annotations.Api; 7 | import io.swagger.annotations.ApiOperation; 8 | import io.swagger.annotations.ApiParam; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.apache.commons.lang.StringUtils; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.web.bind.annotation.PostMapping; 13 | import org.springframework.web.bind.annotation.RequestBody; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.bind.annotation.RestController; 16 | 17 | import javax.validation.Valid; 18 | import java.util.HashMap; 19 | import java.util.List; 20 | import java.util.Map; 21 | 22 | /** 23 | * @author Allen 24 | * @Date: 2018/6/25 13:52 25 | * @Description: 任务相关 26 | */ 27 | @RestController 28 | @Slf4j 29 | @Api(value = "任务控制类") 30 | @RequestMapping({"/flowTask"}) 31 | public class FlowTaskProvider{ 32 | 33 | 34 | @Autowired 35 | ActivitiService activitiService; 36 | 37 | /*** 38 | * 查询待办任务 39 | * @param queryWaitTaskReq 40 | * @return 41 | */ 42 | 43 | @PostMapping(value = "/queryWaitTask") 44 | @ApiOperation(value = "查询待办任务", notes = "查询待办任务") 45 | public R queryWaitTask(@RequestBody @ApiParam(value = "查询任务请求对象") @Valid QueryWaitTaskReq queryWaitTaskReq) { 46 | List list = activitiService.queryWaitTask(queryWaitTaskReq.getFirstResult(), queryWaitTaskReq.getMaxResults()); 47 | return R.ok().put("list", list); 48 | } 49 | 50 | 51 | /*** 52 | * 查询用户任务列表 53 | * @return 54 | */ 55 | 56 | @PostMapping(value = "/queryTask") 57 | @ApiOperation(value = "查询任务", notes = "查询任务") 58 | public R queryTask(@RequestBody @ApiParam(value = "查询任务请求对象") @Valid QueryTaskReq queryTaskReq) { 59 | try { 60 | List list = activitiService.queryTask(queryTaskReq.getAssignee(), queryTaskReq.getCandidateUser(), queryTaskReq.getCandidateGroup(), queryTaskReq.getFirstResult(), queryTaskReq.getMaxResults()); 61 | return R.ok().put("list", list); 62 | } catch (Exception e) { 63 | return R.error(-1, e.getMessage()); 64 | } 65 | } 66 | 67 | 68 | /*** 69 | * 审核任务 70 | * @param completeTaskReq 71 | * @return 72 | */ 73 | @PostMapping(value = "/completeTask") 74 | @ApiOperation(value = "审核任务", notes = "审核任务") 75 | public R completeTask(@RequestBody @ApiParam(value = "审核任务请求对象") @Valid CompleteTaskReq completeTaskReq) { 76 | try { 77 | if (StringUtils.isBlank(completeTaskReq.getAssignee())) {//审核人不能为空 78 | return R.error(-1, "审核人不能为空"); 79 | } 80 | 81 | Map param = new HashMap<>(); 82 | param.put("isFinish", false);//流程是否完成 83 | 84 | if (completeTaskReq.getIsReviewPass() == 1) { 85 | activitiService.completeTask(completeTaskReq.getTaskId(), completeTaskReq.getAssignee(), completeTaskReq.getVariables(), param); 86 | } 87 | 88 | if (completeTaskReq.getIsReviewPass() == 0) {//驳回 89 | activitiService.rejectTask(completeTaskReq.getTaskId(), completeTaskReq.getAssignee(), completeTaskReq.getReturnStart() == 1); 90 | } 91 | 92 | //流程是否结束 93 | return R.ok().put("isFinish", param.get("isFinish")); 94 | } catch (Exception e) { 95 | return R.error(-1, e.getMessage()); 96 | } 97 | } 98 | 99 | /**** 100 | * 删除任务 101 | * @param deleteTaskReq 102 | * @return 103 | */ 104 | 105 | @PostMapping(value = "/deleteTask") 106 | @ApiOperation(value = "删除任务", notes = "删除任务") 107 | public R deleteTask(@RequestBody @ApiParam(value = "删除任务求对象") @Valid DeleteTaskReq deleteTaskReq) { 108 | try { 109 | activitiService.deleteTask(deleteTaskReq.getTaskId()); 110 | return R.ok(); 111 | } catch (Exception e) { 112 | return R.error(-1, e.getMessage()); 113 | } 114 | } 115 | 116 | /*** 117 | * 任务指派 118 | * @param claimTaskReq 119 | * @return 120 | */ 121 | @ApiOperation(value = "任务指派", notes = "任务指派") 122 | @PostMapping(value = "/claimTask") 123 | public R claimTask(@RequestBody @ApiParam(value = "指派任务求对象") @Valid ClaimTaskReq claimTaskReq) { 124 | try { 125 | activitiService.claimTask(claimTaskReq.getTaskId(), claimTaskReq.getAssignee()); 126 | return R.ok(); 127 | } catch (Exception e) { 128 | return R.error(-1, e.getMessage()); 129 | } 130 | } 131 | 132 | 133 | /**** 134 | * 查询任务历史记录 135 | * @param queryTaskHistoryReq 136 | * @return 137 | */ 138 | @ApiOperation(value = "查询任务历史记录", notes = "查询任务历史记录") 139 | @PostMapping(value = "/queryTaskHistory") 140 | public R queryTaskHistory(@RequestBody @ApiParam(value = "查询任务历史记录对象") QueryTaskHistoryReq queryTaskHistoryReq) { 141 | try { 142 | List list = activitiService.queryTaskHistory(queryTaskHistoryReq.getProcessInstanceId()); 143 | return R.ok().put("list", list); 144 | } catch (Exception e) { 145 | return R.error(-1, e.getMessage()); 146 | } 147 | } 148 | 149 | } 150 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/vo/HistoricTaskInstanceVo.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.vo; 2 | 3 | import java.util.Date; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author Allen 8 | * @Date: 2018/6/28 20:28 9 | * @Description: 10 | */ 11 | public class HistoricTaskInstanceVo extends BaseVo{ 12 | 13 | protected String executionId; 14 | protected String name; 15 | protected String localizedName; 16 | protected String parentTaskId; 17 | protected String description; 18 | protected String localizedDescription; 19 | protected String owner; 20 | protected String assignee; 21 | protected String taskDefinitionKey; 22 | protected String formKey; 23 | protected int priority; 24 | protected Date dueDate; 25 | protected Date claimTime; 26 | protected String category; 27 | protected String tenantId = ""; 28 | protected String processInstanceId; 29 | protected String processDefinitionId; 30 | protected Date startTime; 31 | protected Date endTime; 32 | protected Long durationInMillis; 33 | protected String deleteReason; 34 | 35 | /*** 36 | * 参数 37 | */ 38 | protected Map variables; 39 | 40 | public String getExecutionId() { 41 | return executionId; 42 | } 43 | 44 | public void setExecutionId(String executionId) { 45 | this.executionId = executionId; 46 | } 47 | 48 | public String getName() { 49 | return name; 50 | } 51 | 52 | public void setName(String name) { 53 | this.name = name; 54 | } 55 | 56 | public String getLocalizedName() { 57 | return localizedName; 58 | } 59 | 60 | public void setLocalizedName(String localizedName) { 61 | this.localizedName = localizedName; 62 | } 63 | 64 | public String getParentTaskId() { 65 | return parentTaskId; 66 | } 67 | 68 | public void setParentTaskId(String parentTaskId) { 69 | this.parentTaskId = parentTaskId; 70 | } 71 | 72 | public String getDescription() { 73 | return description; 74 | } 75 | 76 | public void setDescription(String description) { 77 | this.description = description; 78 | } 79 | 80 | public String getLocalizedDescription() { 81 | return localizedDescription; 82 | } 83 | 84 | public void setLocalizedDescription(String localizedDescription) { 85 | this.localizedDescription = localizedDescription; 86 | } 87 | 88 | public String getOwner() { 89 | return owner; 90 | } 91 | 92 | public void setOwner(String owner) { 93 | this.owner = owner; 94 | } 95 | 96 | public String getAssignee() { 97 | return assignee; 98 | } 99 | 100 | public void setAssignee(String assignee) { 101 | this.assignee = assignee; 102 | } 103 | 104 | public String getTaskDefinitionKey() { 105 | return taskDefinitionKey; 106 | } 107 | 108 | public void setTaskDefinitionKey(String taskDefinitionKey) { 109 | this.taskDefinitionKey = taskDefinitionKey; 110 | } 111 | 112 | public String getFormKey() { 113 | return formKey; 114 | } 115 | 116 | public void setFormKey(String formKey) { 117 | this.formKey = formKey; 118 | } 119 | 120 | public int getPriority() { 121 | return priority; 122 | } 123 | 124 | public void setPriority(int priority) { 125 | this.priority = priority; 126 | } 127 | 128 | public Date getDueDate() { 129 | return dueDate; 130 | } 131 | 132 | public void setDueDate(Date dueDate) { 133 | this.dueDate = dueDate; 134 | } 135 | 136 | public Date getClaimTime() { 137 | return claimTime; 138 | } 139 | 140 | public void setClaimTime(Date claimTime) { 141 | this.claimTime = claimTime; 142 | } 143 | 144 | public String getCategory() { 145 | return category; 146 | } 147 | 148 | public void setCategory(String category) { 149 | this.category = category; 150 | } 151 | 152 | public String getTenantId() { 153 | return tenantId; 154 | } 155 | 156 | public void setTenantId(String tenantId) { 157 | this.tenantId = tenantId; 158 | } 159 | 160 | public String getProcessInstanceId() { 161 | return processInstanceId; 162 | } 163 | 164 | public void setProcessInstanceId(String processInstanceId) { 165 | this.processInstanceId = processInstanceId; 166 | } 167 | 168 | public String getProcessDefinitionId() { 169 | return processDefinitionId; 170 | } 171 | 172 | public void setProcessDefinitionId(String processDefinitionId) { 173 | this.processDefinitionId = processDefinitionId; 174 | } 175 | 176 | public Date getStartTime() { 177 | return startTime; 178 | } 179 | 180 | public void setStartTime(Date startTime) { 181 | this.startTime = startTime; 182 | } 183 | 184 | public Date getEndTime() { 185 | return endTime; 186 | } 187 | 188 | public void setEndTime(Date endTime) { 189 | this.endTime = endTime; 190 | } 191 | 192 | public Long getDurationInMillis() { 193 | return durationInMillis; 194 | } 195 | 196 | public void setDurationInMillis(Long durationInMillis) { 197 | this.durationInMillis = durationInMillis; 198 | } 199 | 200 | public String getDeleteReason() { 201 | return deleteReason; 202 | } 203 | 204 | public void setDeleteReason(String deleteReason) { 205 | this.deleteReason = deleteReason; 206 | } 207 | 208 | public Map getVariables() { 209 | return variables; 210 | } 211 | 212 | public void setVariables(Map variables) { 213 | this.variables = variables; 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/controller/FlowUserProvider.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.controller; 2 | 3 | import com.activiti6.demo.service.ActivitiService; 4 | import com.activiti6.demo.util.R; 5 | import com.activiti6.demo.vo.GroupReq; 6 | import com.activiti6.demo.vo.MembershipReq; 7 | import com.activiti6.demo.vo.UserReq; 8 | import io.swagger.annotations.Api; 9 | import io.swagger.annotations.ApiOperation; 10 | import io.swagger.annotations.ApiParam; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.activiti.engine.IdentityService; 13 | import org.activiti.engine.identity.Group; 14 | import org.activiti.engine.identity.User; 15 | import org.apache.commons.lang.StringUtils; 16 | import org.springframework.beans.factory.annotation.Autowired; 17 | import org.springframework.web.bind.annotation.PostMapping; 18 | import org.springframework.web.bind.annotation.RequestBody; 19 | import org.springframework.web.bind.annotation.RequestMapping; 20 | import org.springframework.web.bind.annotation.RestController; 21 | 22 | import javax.validation.Valid; 23 | 24 | /** 25 | * @Auther: Allen 26 | * @Date: 2018/7/30 14:33 27 | * @Description: 用户接口定义 28 | */ 29 | @RestController 30 | @Slf4j 31 | @Api(value = "用户相关控制类") 32 | @RequestMapping({"/flowUser"}) 33 | public class FlowUserProvider{ 34 | 35 | @Autowired 36 | ActivitiService activitiService; 37 | 38 | @Autowired 39 | IdentityService identityService; 40 | 41 | 42 | /*** 43 | * 新增组 44 | * @param groupReq 45 | */ 46 | @PostMapping(value = "/newGroup") 47 | @ApiOperation(value = "新增用户组", notes = "新增用户组") 48 | public R newGroup(@RequestBody @ApiParam(value = "新增用户组请求") @Valid GroupReq groupReq) { 49 | try { 50 | 51 | if (StringUtils.isBlank(groupReq.getName())) { 52 | return R.error(-1, "用户组名称不能为空"); 53 | } 54 | 55 | //验证是否保存成功 56 | Group groupInDb = identityService.createGroupQuery().groupId(groupReq.getId()).singleResult(); 57 | if (groupInDb != null) { 58 | return R.error(-2, "ID已存在"); 59 | } 60 | 61 | 62 | Group group = identityService.newGroup(groupReq.getId()); 63 | group.setName(groupReq.getName()); 64 | group.setType("assignment"); 65 | //保存用户组 66 | identityService.saveGroup(group); 67 | 68 | return R.ok(); 69 | } catch (Exception e) { 70 | return R.error(-1, e.getMessage()); 71 | } 72 | } 73 | 74 | @PostMapping(value = "/deleteGroup") 75 | @ApiOperation(value = "删除用户组", notes = "删除用户组") 76 | public R deleteGroup(@RequestBody @ApiParam(value = "新增用户组ID") @Valid GroupReq groupReq) { 77 | try { 78 | identityService.deleteGroup(groupReq.getId()); 79 | return R.ok(); 80 | } catch (Exception e) { 81 | return R.error(-1, e.getMessage()); 82 | } 83 | } 84 | 85 | @PostMapping(value = "/newUser") 86 | @ApiOperation(value = "新增用户", notes = "新增用户") 87 | public R newUser(@RequestBody @ApiParam(value = "新增用户请求对象") @Valid UserReq userReq) { 88 | try { 89 | 90 | 91 | //验证是否保存成功 92 | User userInDb = identityService.createUserQuery().userId(userReq.getId()).singleResult(); 93 | if (userInDb != null) { 94 | return R.error(-2, "用户ID已存在"); 95 | } 96 | 97 | User user = identityService.newUser(userReq.getId()); 98 | user.setEmail(userReq.getEmail()); 99 | user.setFirstName(userReq.getFirstName()); 100 | user.setLastName(userReq.getLastName()); 101 | user.setPassword(userReq.getPassword()); 102 | identityService.saveUser(user); 103 | 104 | return R.ok(); 105 | } catch (Exception e) { 106 | return R.error(-1, e.getMessage()); 107 | } 108 | } 109 | 110 | 111 | @PostMapping(value = "/deleteUser") 112 | @ApiOperation(value = "删除用户", notes = "删除用户") 113 | public R deleteUser(@RequestBody @ApiParam(value = "删除用户请求对象") @Valid UserReq userReq) { 114 | try { 115 | identityService.deleteUser(userReq.getId()); 116 | return R.ok(); 117 | } catch (Exception e) { 118 | return R.error(-1, e.getMessage()); 119 | } 120 | } 121 | 122 | @PostMapping(value = "/createMembership") 123 | @ApiOperation(value = "新增用户与组关联", notes = "新增用户与组关联") 124 | public R createMembership(@RequestBody @ApiParam(value = "用户与组关联请求对象") @Valid MembershipReq membershipReq) { 125 | try { 126 | 127 | User userInDb = identityService.createUserQuery().userId(membershipReq.getUserId()).singleResult(); 128 | if (userInDb == null) { 129 | return R.error(-2, "用户ID不存在"); 130 | } 131 | 132 | //验证是否保存成功 133 | Group groupInDb = identityService.createGroupQuery().groupId(membershipReq.getGroupId()).singleResult(); 134 | if (groupInDb == null) { 135 | return R.error(-2, "用户组ID不存在"); 136 | } 137 | 138 | long count = identityService.createUserQuery().userId(membershipReq.getUserId()).memberOfGroup(membershipReq.getGroupId()).count(); 139 | if (count > 0) { 140 | return R.error(-2, "用户与组关联ID已存在"); 141 | } 142 | 143 | identityService.createMembership(membershipReq.getUserId(), membershipReq.getGroupId()); 144 | return R.ok(); 145 | } catch (Exception e) { 146 | return R.error(-1, e.getMessage()); 147 | } 148 | } 149 | 150 | 151 | @PostMapping(value = "/deleteMembership") 152 | @ApiOperation(value = "删除用户与组关联", notes = "删除用户与组关联") 153 | public R deleteMembership(@RequestBody @ApiParam(value = "用户与组关联请求对象") @Valid MembershipReq membershipReq) { 154 | try { 155 | identityService.deleteMembership(membershipReq.getUserId(), membershipReq.getGroupId()); 156 | return R.ok(); 157 | } catch (Exception e) { 158 | return R.error(-1, e.getMessage()); 159 | } 160 | } 161 | 162 | 163 | } 164 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.activiti6 7 | demo 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | activiti6 demo 12 | activiti6 Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.4.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 6.0.0 26 | 1.2.45 27 | 1.1.9 28 | 5.1.45 29 | 1.16.20 30 | 2.8.0 31 | 2.6 32 | 33 | 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter 38 | 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-test 43 | test 44 | 45 | 46 | 47 | 48 | 49 | org.activiti 50 | activiti-spring-boot-starter-basic 51 | ${activiti.version} 52 | 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-starter-web 57 | 58 | 59 | 60 | 61 | 62 | org.springframework.boot 63 | spring-boot-starter-data-jpa 64 | 65 | 66 | 67 | 68 | mysql 69 | mysql-connector-java 70 | runtime 71 | ${mysql.version} 72 | 73 | 74 | 75 | org.projectlombok 76 | lombok 77 | ${lombok.version} 78 | 79 | 80 | 81 | commons-lang 82 | commons-lang 83 | ${commons.lang.version} 84 | 85 | 86 | 87 | 88 | 89 | org.springframework.boot 90 | spring-boot-test 91 | 2.0.2.RELEASE 92 | test 93 | 94 | 95 | 96 | io.springfox 97 | springfox-swagger2 98 | ${swagger.version} 99 | 100 | 101 | io.springfox 102 | springfox-swagger-ui 103 | ${swagger.version} 104 | 105 | 106 | 107 | 108 | 109 | com.fasterxml.jackson.core 110 | jackson-databind 111 | 2.9.6 112 | 113 | 114 | 115 | 116 | 117 | org.springframework.boot 118 | spring-boot-devtools 119 | true 120 | 121 | 122 | com.alibaba 123 | fastjson 124 | ${fastjson.version} 125 | 126 | 127 | 128 | com.alibaba 129 | druid-spring-boot-starter 130 | ${druid.version} 131 | 132 | 133 | 134 | org.apache.xmlgraphics 135 | batik-awt-util 136 | 1.7 137 | 138 | 139 | org.apache.xmlgraphics 140 | batik-dom 141 | 1.7 142 | 143 | 144 | org.apache.xmlgraphics 145 | batik-svggen 146 | 1.7 147 | 148 | 149 | junit 150 | junit 151 | 4.12 152 | test 153 | 154 | 155 | org.springframework 156 | spring-test 157 | 5.0.6.RELEASE 158 | test 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | org.springframework.boot 171 | spring-boot-maven-plugin 172 | 173 | 174 | 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/vo/TaskVo.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.vo; 2 | 3 | 4 | 5 | import java.util.Date; 6 | import java.util.Map; 7 | 8 | /** 9 | * @author Allen 10 | * @Date: 2018/6/27 20:18 11 | * @Description: 12 | */ 13 | public class TaskVo extends BaseVo{ 14 | 15 | protected String id; 16 | protected String owner; 17 | protected int assigneeUpdatedCount; 18 | protected String originalAssignee; 19 | protected String assignee; 20 | protected String parentTaskId; 21 | protected String name; 22 | protected String localizedName; 23 | protected String description; 24 | protected String localizedDescription; 25 | protected int priority = 50; 26 | protected Date createTime; 27 | protected Date dueDate; 28 | protected int suspensionState; 29 | protected String category; 30 | protected boolean isIdentityLinksInitialized; 31 | protected String executionId; 32 | protected String processInstanceId; 33 | protected String processDefinitionId; 34 | protected String taskDefinitionKey; 35 | protected String formKey; 36 | protected boolean isDeleted; 37 | protected boolean isCanceled; 38 | protected String eventName; 39 | protected String tenantId; 40 | protected boolean forcedUpdate; 41 | protected Date claimTime; 42 | protected Map variables; 43 | 44 | public String getId() { 45 | return id; 46 | } 47 | 48 | public void setId(String id) { 49 | this.id = id; 50 | } 51 | 52 | public String getOwner() { 53 | return owner; 54 | } 55 | 56 | public void setOwner(String owner) { 57 | this.owner = owner; 58 | } 59 | 60 | public int getAssigneeUpdatedCount() { 61 | return assigneeUpdatedCount; 62 | } 63 | 64 | public void setAssigneeUpdatedCount(int assigneeUpdatedCount) { 65 | this.assigneeUpdatedCount = assigneeUpdatedCount; 66 | } 67 | 68 | public String getOriginalAssignee() { 69 | return originalAssignee; 70 | } 71 | 72 | public void setOriginalAssignee(String originalAssignee) { 73 | this.originalAssignee = originalAssignee; 74 | } 75 | 76 | public String getAssignee() { 77 | return assignee; 78 | } 79 | 80 | public void setAssignee(String assignee) { 81 | this.assignee = assignee; 82 | } 83 | 84 | 85 | public String getParentTaskId() { 86 | return parentTaskId; 87 | } 88 | 89 | public void setParentTaskId(String parentTaskId) { 90 | this.parentTaskId = parentTaskId; 91 | } 92 | 93 | public String getName() { 94 | return name; 95 | } 96 | 97 | public void setName(String name) { 98 | this.name = name; 99 | } 100 | 101 | public String getLocalizedName() { 102 | return localizedName; 103 | } 104 | 105 | public void setLocalizedName(String localizedName) { 106 | this.localizedName = localizedName; 107 | } 108 | 109 | public String getDescription() { 110 | return description; 111 | } 112 | 113 | public void setDescription(String description) { 114 | this.description = description; 115 | } 116 | 117 | public String getLocalizedDescription() { 118 | return localizedDescription; 119 | } 120 | 121 | public void setLocalizedDescription(String localizedDescription) { 122 | this.localizedDescription = localizedDescription; 123 | } 124 | 125 | public int getPriority() { 126 | return priority; 127 | } 128 | 129 | public void setPriority(int priority) { 130 | this.priority = priority; 131 | } 132 | 133 | public Date getCreateTime() { 134 | return createTime; 135 | } 136 | 137 | public void setCreateTime(Date createTime) { 138 | this.createTime = createTime; 139 | } 140 | 141 | public Date getDueDate() { 142 | return dueDate; 143 | } 144 | 145 | public void setDueDate(Date dueDate) { 146 | this.dueDate = dueDate; 147 | } 148 | 149 | public int getSuspensionState() { 150 | return suspensionState; 151 | } 152 | 153 | public void setSuspensionState(int suspensionState) { 154 | this.suspensionState = suspensionState; 155 | } 156 | 157 | public String getCategory() { 158 | return category; 159 | } 160 | 161 | public void setCategory(String category) { 162 | this.category = category; 163 | } 164 | 165 | public boolean isIdentityLinksInitialized() { 166 | return isIdentityLinksInitialized; 167 | } 168 | 169 | public void setIdentityLinksInitialized(boolean identityLinksInitialized) { 170 | isIdentityLinksInitialized = identityLinksInitialized; 171 | } 172 | 173 | public String getExecutionId() { 174 | return executionId; 175 | } 176 | 177 | public void setExecutionId(String executionId) { 178 | this.executionId = executionId; 179 | } 180 | 181 | public String getProcessInstanceId() { 182 | return processInstanceId; 183 | } 184 | 185 | public void setProcessInstanceId(String processInstanceId) { 186 | this.processInstanceId = processInstanceId; 187 | } 188 | 189 | 190 | public String getProcessDefinitionId() { 191 | return processDefinitionId; 192 | } 193 | 194 | public void setProcessDefinitionId(String processDefinitionId) { 195 | this.processDefinitionId = processDefinitionId; 196 | } 197 | 198 | public String getTaskDefinitionKey() { 199 | return taskDefinitionKey; 200 | } 201 | 202 | public void setTaskDefinitionKey(String taskDefinitionKey) { 203 | this.taskDefinitionKey = taskDefinitionKey; 204 | } 205 | 206 | public String getFormKey() { 207 | return formKey; 208 | } 209 | 210 | public void setFormKey(String formKey) { 211 | this.formKey = formKey; 212 | } 213 | 214 | public boolean isDeleted() { 215 | return isDeleted; 216 | } 217 | 218 | public void setDeleted(boolean deleted) { 219 | isDeleted = deleted; 220 | } 221 | 222 | public boolean isCanceled() { 223 | return isCanceled; 224 | } 225 | 226 | public void setCanceled(boolean canceled) { 227 | isCanceled = canceled; 228 | } 229 | 230 | public String getEventName() { 231 | return eventName; 232 | } 233 | 234 | public void setEventName(String eventName) { 235 | this.eventName = eventName; 236 | } 237 | 238 | 239 | public String getTenantId() { 240 | return tenantId; 241 | } 242 | 243 | public void setTenantId(String tenantId) { 244 | this.tenantId = tenantId; 245 | } 246 | 247 | 248 | public boolean isForcedUpdate() { 249 | return forcedUpdate; 250 | } 251 | 252 | public void setForcedUpdate(boolean forcedUpdate) { 253 | this.forcedUpdate = forcedUpdate; 254 | } 255 | 256 | public Date getClaimTime() { 257 | return claimTime; 258 | } 259 | 260 | public void setClaimTime(Date claimTime) { 261 | this.claimTime = claimTime; 262 | } 263 | 264 | public Map getVariables() { 265 | return variables; 266 | } 267 | 268 | public void setVariables(Map variables) { 269 | this.variables = variables; 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /src/main/resources/processes/mymodel1.bpmn20.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | mymodel1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/controller/ProcessDefinitionProvider.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.controller; 2 | 3 | import com.activiti6.demo.service.ActivitiService; 4 | import com.activiti6.demo.util.R; 5 | import com.activiti6.demo.vo.IsFinishProcessReq; 6 | import com.activiti6.demo.vo.QueryProcessInstanceReq; 7 | import com.activiti6.demo.vo.StartProcessInstanceReq; 8 | import com.activiti6.demo.vo.ViewProcessInstanceImageReq; 9 | import io.swagger.annotations.Api; 10 | import io.swagger.annotations.ApiOperation; 11 | import io.swagger.annotations.ApiParam; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.activiti.bpmn.model.BpmnModel; 14 | import org.activiti.bpmn.model.FlowNode; 15 | import org.activiti.bpmn.model.SequenceFlow; 16 | import org.activiti.engine.HistoryService; 17 | import org.activiti.engine.ProcessEngine; 18 | import org.activiti.engine.RepositoryService; 19 | import org.activiti.engine.history.HistoricActivityInstance; 20 | import org.activiti.engine.history.HistoricProcessInstance; 21 | import org.activiti.engine.impl.RepositoryServiceImpl; 22 | import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; 23 | import org.activiti.engine.repository.ProcessDefinition; 24 | import org.activiti.engine.runtime.ProcessInstance; 25 | import org.activiti.image.ProcessDiagramGenerator; 26 | import org.apache.commons.lang.StringUtils; 27 | import org.springframework.beans.factory.annotation.Autowired; 28 | import org.springframework.validation.annotation.Validated; 29 | import org.springframework.web.bind.annotation.*; 30 | import org.springframework.web.multipart.MultipartFile; 31 | 32 | import javax.servlet.http.HttpServletRequest; 33 | import javax.servlet.http.HttpServletResponse; 34 | import javax.validation.Valid; 35 | import java.io.IOException; 36 | import java.io.InputStream; 37 | import java.io.OutputStream; 38 | import java.text.SimpleDateFormat; 39 | import java.util.ArrayList; 40 | import java.util.List; 41 | import java.util.Map; 42 | 43 | /** 44 | * @author Allen 45 | * @Date: 2018/6/25 13:52 46 | * @Description: 流程定义相关 47 | */ 48 | @RestController 49 | @Slf4j 50 | @Api(value = "流程定义控制类") 51 | @RequestMapping({"/processDefinition"}) 52 | public class ProcessDefinitionProvider { 53 | 54 | 55 | @Autowired 56 | ProcessEngine processEngine; 57 | 58 | @Autowired 59 | ActivitiService activitiService; 60 | 61 | @Autowired 62 | HistoryService historyService; 63 | 64 | @Autowired 65 | RepositoryService repositoryService; 66 | 67 | 68 | /*** 69 | * 部署工作流规则文件 70 | * @param file BPMN 流程文件zip压缩包 71 | * @param bpmnName bpmn文件名称 包含.png 文件 72 | * @return 73 | */ 74 | @PostMapping(value = "/deploy") 75 | @ApiOperation(value = "部署工作流规则文件", notes = "部署工作流规则文件") 76 | public R deploy(@ApiParam(value = "BPMN 流程文件zip压缩包") @RequestParam(value = "file", required = false) MultipartFile file, 77 | @ApiParam(value = "bpmn文件名称 包含.png 文件") @RequestParam(value = "bpmnName", required = false) String bpmnName) { 78 | try { 79 | 80 | if (file == null && StringUtils.isBlank(bpmnName)) { 81 | return R.error(-1, "Please select a file to upload or input BPMN file name."); 82 | } 83 | 84 | 85 | if (file != null && !file.isEmpty()) {//发布zip 文件 86 | 87 | String fileName = file.getOriginalFilename(); 88 | if (StringUtils.isBlank(fileName)) 89 | return R.error(-2, "bpmn 文件名称不能为空"); 90 | 91 | 92 | InputStream fileInputStream = file.getInputStream(); 93 | 94 | activitiService.deploy(fileInputStream, fileName); 95 | } else { 96 | activitiService.deploy(bpmnName); 97 | } 98 | 99 | return R.ok(); 100 | } catch (Exception e) { 101 | return R.error(-100, "error:" + e.getMessage()); 102 | } 103 | } 104 | 105 | /*** 106 | * 开始流程 107 | */ 108 | @PostMapping(value = "/startProcessInstance") 109 | @ApiOperation(value = "开始流程", notes = "开始流程") 110 | public R startProcessInstance(@RequestBody @Validated @ApiParam(value = "开始流程请求对象") @Valid StartProcessInstanceReq startProcessInstanceReq) { 111 | try { 112 | Map variables = startProcessInstanceReq.getVariables();//流程配置参数 113 | variables.put("applyUserId", startProcessInstanceReq.getApplyUserId());//流程发起人 114 | ProcessInstance processInstance = activitiService.startProcessInstance(startProcessInstanceReq.getInstanceKey(), variables); 115 | log.debug("processInstance:" + processInstance.getProcessDefinitionId()); 116 | return R.ok().put("processInstanceId", processInstance.getId()); 117 | } catch (Exception e) { 118 | return R.error(-1, e.getMessage()); 119 | } 120 | } 121 | 122 | /**** 123 | * 通过key获取流程定义明细列表 124 | * @return 125 | */ 126 | @PostMapping(value = "/queryProcessInstance") 127 | @ApiOperation(value = "通过key获取流程定义明细列表", notes = "通过key获取流程定义明细列表") 128 | public R processDefinitionQuery(@RequestBody @ApiParam(value = "获取流程定义明细请求对象") @Valid QueryProcessInstanceReq queryProcessInstanceReq) { 129 | try { 130 | List list = activitiService.processDefinitionQuery(queryProcessInstanceReq.getInstanceKey()); 131 | return R.ok().put("list", list); 132 | } catch (Exception e) { 133 | return R.error(-1, "error:" + e.getMessage()); 134 | } 135 | } 136 | 137 | 138 | @PostMapping(value = "/isFinishProcess") 139 | @ApiOperation(value = "流程是否结束", notes = "流程是否结束") 140 | public R isFinishProcess(@RequestBody @ApiParam(value = "流程是否结束请求对象") @Valid IsFinishProcessReq isFinishProcessReq) { 141 | boolean flag = activitiService.isFinishProcess(isFinishProcessReq.getProcessInstanceId()); 142 | return R.ok().put("isFinish", flag); 143 | } 144 | 145 | /**** 146 | * 显示流程实例处理状态图片 147 | * @param request 148 | * @param response 149 | * @param viewProcessInstanceImageReq 150 | * @throws IOException 151 | */ 152 | @PostMapping(value = "/viewProcessInstanceImage") 153 | @ApiOperation(value = "显示流程实例处理状态图片", notes = "显示流程实例处理状态图片") 154 | public void viewProcessInstanceImage(HttpServletRequest request, HttpServletResponse response, @RequestBody @ApiParam(value = "流程实例处理状态请求对象") @Valid ViewProcessInstanceImageReq viewProcessInstanceImageReq) { 155 | //logger.info("[开始]-获取流程图图像"); 156 | try { 157 | // 获取历史流程实例 158 | HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() 159 | .processInstanceId(viewProcessInstanceImageReq.getProcessInstanceId()).singleResult(); 160 | 161 | if (historicProcessInstance == null) { 162 | //throw new BusinessException("获取流程实例ID[" + pProcessInstanceId + "]对应的历史流程实例失败!"); 163 | } else { 164 | // 获取流程定义 165 | ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService) 166 | .getDeployedProcessDefinition(historicProcessInstance.getProcessDefinitionId()); 167 | 168 | // 获取流程历史中已执行节点,并按照节点在流程中执行先后顺序排序 169 | List historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery() 170 | .processInstanceId(viewProcessInstanceImageReq.getProcessInstanceId()).orderByHistoricActivityInstanceId().asc().list(); 171 | 172 | // 已执行的节点ID集合 173 | List executedActivityIdList = new ArrayList(); 174 | int index = 1; 175 | //logger.info("获取已经执行的节点ID"); 176 | for (HistoricActivityInstance activityInstance : historicActivityInstanceList) { 177 | executedActivityIdList.add(activityInstance.getActivityId()); 178 | 179 | //logger.info("第[" + index + "]个已执行节点=" + activityInstance.getActivityId() + " : " +activityInstance.getActivityName()); 180 | index++; 181 | } 182 | 183 | BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId()); 184 | 185 | 186 | // 获取流程走过的线 (getHighLightedFlows是下面的方法) 187 | List flowIds = getHighLightedFlows(bpmnModel, processDefinition, historicActivityInstanceList); 188 | 189 | 190 | // 获取流程图图像字符流 191 | ProcessDiagramGenerator pec = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator(); 192 | //配置字体 193 | InputStream imageStream = pec.generateDiagram(bpmnModel, "png", executedActivityIdList, flowIds, "宋体", "微软雅黑", "黑体", null, 2.0); 194 | 195 | response.setContentType("image/png"); 196 | OutputStream os = response.getOutputStream(); 197 | int bytesRead = 0; 198 | byte[] buffer = new byte[8192]; 199 | while ((bytesRead = imageStream.read(buffer, 0, 8192)) != -1) { 200 | os.write(buffer, 0, bytesRead); 201 | } 202 | os.close(); 203 | imageStream.close(); 204 | } 205 | //logger.info("[完成]-获取流程图图像"); 206 | } catch (Exception e) { 207 | System.out.println(e.getMessage()); 208 | //logger.error("【异常】-获取流程图失败!" + e.getMessage()); 209 | //throw new BusinessException("获取流程图失败!" + e.getMessage()); 210 | } 211 | } 212 | 213 | 214 | /**** 215 | * 216 | * @param bpmnModel 217 | * @param processDefinitionEntity 218 | * @param historicActivityInstances 219 | * @return 220 | */ 221 | public List getHighLightedFlows(BpmnModel bpmnModel, ProcessDefinitionEntity processDefinitionEntity, List historicActivityInstances) { 222 | SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //24小时制 223 | List highFlows = new ArrayList();// 用以保存高亮的线flowId 224 | 225 | for (int i = 0; i < historicActivityInstances.size() - 1; i++) { 226 | // 对历史流程节点进行遍历 227 | // 得到节点定义的详细信息 228 | FlowNode activityImpl = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(i).getActivityId()); 229 | 230 | 231 | List sameStartTimeNodes = new ArrayList();// 用以保存后续开始时间相同的节点 232 | FlowNode sameActivityImpl1 = null; 233 | 234 | HistoricActivityInstance activityImpl_ = historicActivityInstances.get(i);// 第一个节点 235 | HistoricActivityInstance activityImp2_; 236 | 237 | for (int k = i + 1; k <= historicActivityInstances.size() - 1; k++) { 238 | activityImp2_ = historicActivityInstances.get(k);// 后续第1个节点 239 | 240 | if (activityImpl_.getActivityType().equals("userTask") && activityImp2_.getActivityType().equals("userTask") && 241 | df.format(activityImpl_.getStartTime()).equals(df.format(activityImp2_.getStartTime()))) //都是usertask,且主节点与后续节点的开始时间相同,说明不是真实的后继节点 242 | { 243 | 244 | } else { 245 | sameActivityImpl1 = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstances.get(k).getActivityId());//找到紧跟在后面的一个节点 246 | break; 247 | } 248 | 249 | } 250 | sameStartTimeNodes.add(sameActivityImpl1); // 将后面第一个节点放在时间相同节点的集合里 251 | for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) { 252 | HistoricActivityInstance activityImpl1 = historicActivityInstances.get(j);// 后续第一个节点 253 | HistoricActivityInstance activityImpl2 = historicActivityInstances.get(j + 1);// 后续第二个节点 254 | 255 | if (df.format(activityImpl1.getStartTime()).equals(df.format(activityImpl2.getStartTime()))) {// 如果第一个节点和第二个节点开始时间相同保存 256 | FlowNode sameActivityImpl2 = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityImpl2.getActivityId()); 257 | sameStartTimeNodes.add(sameActivityImpl2); 258 | } else {// 有不相同跳出循环 259 | break; 260 | } 261 | } 262 | List pvmTransitions = activityImpl.getOutgoingFlows(); // 取出节点的所有出去的线 263 | 264 | for (SequenceFlow pvmTransition : pvmTransitions) {// 对所有的线进行遍历 265 | FlowNode pvmActivityImpl = (FlowNode) bpmnModel.getMainProcess().getFlowElement(pvmTransition.getTargetRef());// 如果取出的线的目标节点存在时间相同的节点里,保存该线的id,进行高亮显示 266 | if (sameStartTimeNodes.contains(pvmActivityImpl)) { 267 | highFlows.add(pvmTransition.getId()); 268 | } 269 | } 270 | 271 | } 272 | return highFlows; 273 | 274 | } 275 | 276 | } 277 | -------------------------------------------------------------------------------- /src/main/java/com/activiti6/demo/service/impl/ActivitiServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.activiti6.demo.service.impl; 2 | 3 | import com.activiti6.demo.service.ActivitiService; 4 | import com.activiti6.demo.vo.HistoricTaskInstanceVo; 5 | import com.activiti6.demo.vo.ProcessDefinitionVo; 6 | import com.activiti6.demo.vo.TaskVo; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.activiti.bpmn.model.BpmnModel; 9 | import org.activiti.bpmn.model.FlowNode; 10 | import org.activiti.bpmn.model.SequenceFlow; 11 | import org.activiti.engine.*; 12 | import org.activiti.engine.history.HistoricActivityInstance; 13 | import org.activiti.engine.history.HistoricTaskInstance; 14 | import org.activiti.engine.history.HistoricVariableInstance; 15 | import org.activiti.engine.impl.cmd.NeedsActiveTaskCmd; 16 | import org.activiti.engine.impl.interceptor.Command; 17 | import org.activiti.engine.impl.interceptor.CommandContext; 18 | import org.activiti.engine.impl.persistence.entity.ExecutionEntity; 19 | import org.activiti.engine.impl.persistence.entity.TaskEntity; 20 | import org.activiti.engine.impl.persistence.entity.TaskEntityManagerImpl; 21 | import org.activiti.engine.repository.ProcessDefinition; 22 | import org.activiti.engine.repository.ProcessDefinitionQuery; 23 | import org.activiti.engine.runtime.ProcessInstance; 24 | import org.activiti.engine.task.Task; 25 | import org.activiti.engine.task.TaskQuery; 26 | import org.apache.commons.lang.StringUtils; 27 | import org.springframework.beans.BeanUtils; 28 | import org.springframework.beans.factory.annotation.Autowired; 29 | import org.springframework.stereotype.Service; 30 | 31 | import java.io.InputStream; 32 | import java.util.ArrayList; 33 | import java.util.HashMap; 34 | import java.util.List; 35 | import java.util.Map; 36 | import java.util.zip.ZipInputStream; 37 | 38 | 39 | @Service 40 | @Slf4j 41 | public class ActivitiServiceImpl implements ActivitiService { 42 | 43 | @Autowired 44 | ProcessEngine processEngine; 45 | 46 | @Autowired 47 | RepositoryService repositoryService; 48 | 49 | 50 | @Autowired 51 | RuntimeService runtimeService; 52 | 53 | @Autowired 54 | TaskService taskService; 55 | 56 | @Autowired 57 | HistoryService historyService; 58 | 59 | @Autowired 60 | IdentityService identityService; 61 | 62 | @Autowired 63 | ManagementService managementService; 64 | 65 | 66 | /** 67 | * 发布规则文件 68 | * 69 | * @param bpmnName 70 | */ 71 | public void deploy(String bpmnName) { 72 | 73 | String bpmn = "processes/" + bpmnName + ".xml"; 74 | String png = "processes/" + bpmnName + ".png"; 75 | 76 | 77 | log.debug(String.format("xml:%s,png", bpmn, png)); 78 | repositoryService.createDeployment()//创建一个部署对象 79 | .name(bpmnName)//添加部署的名称 80 | .addInputStream(bpmn, this.getClass().getClassLoader().getResourceAsStream(bpmn)) 81 | // .addInputStream(png, this.getClass().getClassLoader().getResourceAsStream(png)) 82 | .deploy();//完成部署 83 | } 84 | 85 | 86 | /** 87 | * 发布规则文件 88 | * 89 | * @param fileName 90 | */ 91 | public void deploy(InputStream fileInputStream, String fileName) { 92 | 93 | ZipInputStream zipInputStream = new ZipInputStream(fileInputStream); 94 | //使用deploy方法发布流程 95 | repositoryService.createDeployment() 96 | .addZipInputStream(zipInputStream) 97 | .name(fileName) 98 | .deploy(); 99 | } 100 | 101 | 102 | @Override 103 | public ProcessInstance startProcessInstance(String instanceKey, Map variables) { 104 | /** 105 | * 启动请假单流程 并获取流程实例 106 | * 因为该请假单流程可以会启动多个所以每启动一个请假单流程都会在数据库中插入一条新版本的流程数据 107 | * 通过key启动的流程就是当前key下最新版本的流程 108 | * 109 | */ 110 | ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(instanceKey, variables); 111 | log.debug(String.format("id:%s,activitiId:%s", processInstance.getId(), processInstance.getActivityId())); 112 | return processInstance; 113 | } 114 | 115 | @Override 116 | public List processDefinitionQuery(String instanceKey) { 117 | 118 | //创建查询对象 119 | ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery(); 120 | 121 | ProcessDefinitionQuery processDefinitionQuery = query.latestVersion(); 122 | if (StringUtils.isBlank(instanceKey)) { 123 | processDefinitionQuery.list(); 124 | } else { 125 | query.processDefinitionKey(instanceKey); 126 | } 127 | 128 | //添加查询条件 129 | // .processDefinitionName("My process")//通过name获取 130 | // .orderByProcessDefinitionId()//根据ID排序 131 | //执行查询获取流程定义明细 132 | List pds = query.list(); 133 | log.debug("queryProcdef query list:" + pds); 134 | if (pds != null && pds.size() > 0) { 135 | for (ProcessDefinition pd : pds) { 136 | log.debug("ID:" + pd.getId() + ",NAME:" + pd.getName() + ",KEY:" + pd.getKey() + ",VERSION:" + pd.getVersion() + ",RESOURCE_NAME:" + pd.getResourceName() + ",DGRM_RESOURCE_NAME:" + pd.getDiagramResourceName()); 137 | } 138 | } 139 | 140 | 141 | return listToBeanVo(pds, ProcessDefinitionVo.class); 142 | } 143 | 144 | @Override 145 | public List queryTask(String assignee, String candidateUser, String candidateGroup, int firstResult, int maxResults) { 146 | 147 | //获取任务服务对象 148 | //根据接受人获取该用户的任务 149 | 150 | TaskQuery taskQuery = taskService.createTaskQuery(); 151 | 152 | if (!StringUtils.isBlank(assignee)) { 153 | taskQuery.taskAssignee(assignee); 154 | } 155 | 156 | if (!StringUtils.isBlank(candidateUser)) { 157 | taskQuery.taskCandidateUser(candidateUser); 158 | } 159 | if (!StringUtils.isBlank(candidateGroup)) { 160 | taskQuery.taskCandidateGroup(candidateGroup); 161 | } 162 | 163 | List tasks = taskQuery.listPage(firstResult, maxResults); 164 | 165 | 166 | List list1 = null; 167 | if (tasks != null && tasks.size() > 0) { 168 | 169 | list1 = listToBeanVo(tasks, TaskVo.class, "variables"); 170 | 171 | for (TaskVo task : list1) { 172 | 173 | Map variables = taskService.getVariables(task.getId()); 174 | task.setVariables(variables); 175 | 176 | log.debug("ID:" + task.getId() + ",姓名:" + task.getName() + ",接收人:" + task.getAssignee() + ",开始时间:" + task.getCreateTime()); 177 | } 178 | } 179 | 180 | 181 | return list1; 182 | } 183 | 184 | 185 | @Override 186 | public Map queryVariables(String taskId) { 187 | return taskService.getVariables(taskId); 188 | } 189 | 190 | @Override 191 | public List queryTaskHistory(String processInstanceId) { 192 | 193 | List list = historyService 194 | .createHistoricTaskInstanceQuery()//创建历史任务实例查询 195 | .processInstanceId(processInstanceId)// 196 | .orderByHistoricTaskInstanceStartTime().asc() 197 | .list(); 198 | 199 | 200 | List list1 = null; 201 | if (list != null && list.size() > 0) { 202 | list1 = new ArrayList<>(); 203 | for (HistoricTaskInstance hti : list) { 204 | log.debug(hti.getId() + " " + hti.getName() + " " + hti.getProcessInstanceId() + " " + hti.getStartTime() + " " + hti.getEndTime() + " " + hti.getDurationInMillis()); 205 | log.debug("################################"); 206 | 207 | HistoricTaskInstanceVo historicTaskInstanceVo = objToBeanVo(hti, HistoricTaskInstanceVo.class); 208 | if (historicTaskInstanceVo != null) { 209 | 210 | List list2 = historyService.createHistoricVariableInstanceQuery().taskId(hti.getId()).list(); 211 | if (list2 != null && list2.size() > 0) { 212 | 213 | Map variables = new HashMap<>(); 214 | for (HistoricVariableInstance historicVariableInstance : list2) { 215 | variables.put(historicVariableInstance.getVariableName(), historicVariableInstance.getValue()); 216 | } 217 | historicTaskInstanceVo.setVariables(variables); 218 | } 219 | 220 | 221 | list1.add(historicTaskInstanceVo); 222 | } 223 | 224 | } 225 | } 226 | 227 | return list1; 228 | } 229 | 230 | @Override 231 | public void completeTask(String taskId, String assignee, Map variables, Map param) { 232 | 233 | Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); 234 | 235 | //完成请假申请任务 236 | taskService.setVariablesLocal(taskId, variables); 237 | if (!StringUtils.isBlank(assignee)) { 238 | taskService.setAssignee(taskId, assignee); 239 | } 240 | taskService.complete(taskId, variables); 241 | 242 | if (task != null) { 243 | param.put("isFinish", isFinishProcess(task.getProcessInstanceId())); 244 | } 245 | 246 | } 247 | 248 | @Override 249 | public void claimTask(String taskId, String assignee) { 250 | taskService.claim(taskId, assignee); 251 | } 252 | 253 | @Override 254 | public void deleteTask(String taskId) { 255 | taskService.deleteTask(taskId); 256 | } 257 | 258 | 259 | @Override 260 | public boolean isFinishProcess(String processInstanceId) { 261 | 262 | /**判断流程是否结束,查询正在执行的执行对象表*/ 263 | ProcessInstance rpi = processEngine.getRuntimeService()// 264 | .createProcessInstanceQuery()//创建流程实例查询对象 265 | .processInstanceId(processInstanceId) 266 | .singleResult(); 267 | 268 | return rpi == null; 269 | } 270 | 271 | @Override 272 | public List queryWaitTask(int firstResult, int maxResults) { 273 | List list = taskService.createTaskQuery().listPage(firstResult, maxResults); 274 | return listToBeanVo(list, TaskVo.class, "variables"); 275 | } 276 | 277 | 278 | @Override 279 | public void rejectTask(String taskId, String assignee, boolean returnStart) { 280 | jump(this, taskId, assignee, returnStart); 281 | } 282 | 283 | //跳转方法 284 | public void jump(ActivitiServiceImpl activitiService, String taskId, String assignee, boolean returnStart) { 285 | //当前任务 286 | Task currentTask = activitiService.taskService.createTaskQuery().taskId(taskId).singleResult(); 287 | //获取流程定义 288 | // Process process = activitiService.repositoryService.getBpmnModel(currentTask.getProcessDefinitionId()).getMainProcess(); 289 | BpmnModel bpmnModel = repositoryService.getBpmnModel(currentTask.getProcessDefinitionId()); 290 | 291 | 292 | List list = historyService.createHistoricActivityInstanceQuery().processInstanceId(currentTask.getProcessInstanceId()).activityType("userTask").finished().orderByHistoricActivityInstanceEndTime().asc().list(); 293 | if (list == null || list.size() == 0) { 294 | throw new ActivitiException("操作历史流程不存在"); 295 | } 296 | 297 | //获取目标节点定义 298 | FlowNode targetNode = null; 299 | 300 | if (returnStart) {//驳回到发起点 301 | 302 | targetNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(list.get(0).getActivityId()); 303 | } else {//驳回到上一个节点 304 | 305 | FlowNode currNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentTask.getTaskDefinitionKey()); 306 | 307 | for (int i = 0; i < list.size(); i++) {//倒序审核任务列表,最后一个不与当前节点相同的节点设置为目标节点 308 | FlowNode lastNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(list.get(i).getActivityId()); 309 | if (list.size() > 0 && currNode.getId().equals(lastNode.getId())) { 310 | targetNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(list.get(i - 1).getActivityId()); 311 | break; 312 | } 313 | } 314 | 315 | if (targetNode == null && list.size() > 0) { 316 | targetNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(list.get(list.size() - 1).getActivityId()); 317 | } 318 | 319 | 320 | // Map flowElementMap = new TreeMap<>(); 321 | // Collection flowElements = bpmnModel.getMainProcess().getFlowElements(); 322 | // for (FlowElement flowElement : flowElements) { 323 | // 324 | // flowElementMap.put(flowElement.getId(), flowElement); 325 | // } 326 | // 327 | // 328 | // 329 | // targetNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(tmplist.get(tmplist.size() - 1).getActivityId()); 330 | 331 | } 332 | 333 | if (targetNode == null) { 334 | throw new ActivitiException("开始节点不存在"); 335 | } 336 | 337 | 338 | //删除当前运行任务 339 | String executionEntityId = activitiService.managementService.executeCommand(activitiService.new DeleteTaskCmd(currentTask.getId())); 340 | //流程执行到来源节点 341 | activitiService.managementService.executeCommand(activitiService.new SetFLowNodeAndGoCmd(targetNode, executionEntityId)); 342 | } 343 | 344 | 345 | //删除当前运行时任务命令,并返回当前任务的执行对象id 346 | //这里继承了NeedsActiveTaskCmd,主要时很多跳转业务场景下,要求不能时挂起任务。可以直接继承Command即可 347 | public class DeleteTaskCmd extends NeedsActiveTaskCmd { 348 | public DeleteTaskCmd(String taskId) { 349 | super(taskId); 350 | } 351 | 352 | public String execute(CommandContext commandContext, TaskEntity currentTask) { 353 | //获取所需服务 354 | TaskEntityManagerImpl taskEntityManager = (TaskEntityManagerImpl) commandContext.getTaskEntityManager(); 355 | //获取当前任务的来源任务及来源节点信息 356 | ExecutionEntity executionEntity = currentTask.getExecution(); 357 | //删除当前任务,来源任务 358 | taskEntityManager.deleteTask(currentTask, "jumpReason", false, false); 359 | return executionEntity.getId(); 360 | } 361 | 362 | public String getSuspendedTaskException() { 363 | return "挂起的任务不能跳转"; 364 | } 365 | } 366 | 367 | //根据提供节点和执行对象id,进行跳转命令 368 | public class SetFLowNodeAndGoCmd implements Command { 369 | private FlowNode flowElement; 370 | private String executionId; 371 | 372 | public SetFLowNodeAndGoCmd(FlowNode flowElement, String executionId) { 373 | this.flowElement = flowElement; 374 | this.executionId = executionId; 375 | } 376 | 377 | public Void execute(CommandContext commandContext) { 378 | 379 | ExecutionEntity executionEntity = commandContext.getExecutionEntityManager().findById(executionId); 380 | 381 | //获取目标节点的来源连线 382 | List flows = flowElement.getIncomingFlows(); 383 | if (flows == null || flows.size() < 1) { 384 | 385 | executionEntity.setCurrentFlowElement(flowElement); 386 | commandContext.getAgenda().planTakeOutgoingSequenceFlowsOperation(executionEntity, true); 387 | 388 | } else { 389 | //随便选一条连线来执行,时当前执行计划为,从连线流转到目标节点,实现跳转 390 | executionEntity.setCurrentFlowElement(flows.get(0)); 391 | } 392 | 393 | commandContext.getAgenda().planTakeOutgoingSequenceFlowsOperation(executionEntity, true); 394 | 395 | return null; 396 | } 397 | } 398 | 399 | 400 | /*** 401 | * 转化显示Bean 402 | * @param list 待转化列表 403 | * @param clazz 显示类 404 | * @param 405 | * @return 406 | * @throws Exception 407 | */ 408 | private List listToBeanVo(List list, Class clazz, String... ignoreProperties) { 409 | if (list == null) 410 | return null; 411 | 412 | List rlist = new ArrayList<>(); 413 | try { 414 | for (Object obj : list) { 415 | T t = objToBeanVo(obj, clazz, ignoreProperties); 416 | rlist.add(t); 417 | } 418 | } catch (Exception e) { 419 | log.error("listToBeanVo error:" + e.getMessage()); 420 | e.printStackTrace(); 421 | } 422 | return rlist; 423 | } 424 | 425 | /** 426 | * 复制源对象属性到目标对象 427 | * 428 | * @param obj 429 | * @param clazz 430 | * @param ignoreProperties 431 | * @param 432 | * @return 433 | * @throws Exception 434 | */ 435 | private T objToBeanVo(Object obj, Class clazz, String... ignoreProperties) { 436 | try { 437 | T t = (T) Class.forName(clazz.getName()).newInstance(); 438 | BeanUtils.copyProperties(obj, t, ignoreProperties); 439 | return t; 440 | } catch (Exception e) { 441 | log.error("objToBeanVo error:" + e.getMessage()); 442 | e.printStackTrace(); 443 | } 444 | return null; 445 | } 446 | 447 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Activiti6 SpringBoot Demo 2 | 3 | > 版本: v1.0.0
4 | > 日期: 2018-07-06
5 | > 编辑: Allen
6 | 7 | 8 | 9 | ## 一、工作流文件 10 | 11 | 目录:/resources/processes 12 | + 测试例子:mymodel1.bpmn20.xml 13 | 14 | 15 | 16 | 17 | ### 18 | 19 | 20 | ## 二、接口 21 | 22 | ### 1. 部署工作流规则文件 23 | 描述: 发布工作流文件BPMN
24 | 功能:
25 | 26 | API:
27 | 方法: POST
28 | 请求地址: /processDefinition/deploy
29 | 参数说明:
30 | 31 | 32 | | 参数明|类型|说明|是否必填|示例| 33 | |:--------:|:-----:|:-----:|:----:|:-----| 34 | |file|file|.zip 扩展的BPMN 文件压缩包|可选必填|process_core_ent_credit.zip| 35 | |bpmnName|string|bpmn文件名称 包含.png 文件|可选必填|myLeave.bpmn20| 36 | 37 | 请求示例: 38 | 39 | 40 | 41 | 42 | 返回值说明: 43 | 44 | 45 | + code 返回代码 46 | + msg 消息提示 47 | 48 | 返回数据样例: 49 | 50 | { 51 | "code": "1", 52 | "msg": "ok", 53 | } 54 | 55 | 56 | ### 2. 开始流程 57 | 描述: 发布BPMN文件后开启流程实例
58 | 功能:
59 | 60 | API:
61 | 方法: POST
62 | 请求地址: /processDefinition/startProcessInstance
63 | 参数说明:
64 | 65 | | 参数明|类型|说明|是否必填|示例| 66 | |:--------:|:-----:|:-----:|:----:|:-----| 67 | |instanceKey|string|BPMN文件实例名称|是|process_core_ent_credit| 68 | |applyUserId|string|启动者ID流程发起人|是| 资产经理|| 69 | |params|object|表单参数|是|{"flowId":"2","param1":"内容1","param2":"内容2","param3":"内容3","param4":"内容4","param5":"内容5","applyUserId":"资产经理","assignee":"资产经理"}| 70 | |+assignee|string|审核人|是| 资产经理| 71 | 72 | 73 | 74 | 请求示例: 75 | 76 | { 77 | "instanceKey": "process_core_ent_credit", 78 | "params": { 79 | "flowId": "2", 80 | "param1": "内容1", 81 | "param2": "内容2", 82 | "param3": "内容3", 83 | "param4": "内容4", 84 | "param5": "内容5", 85 | "applyUserId": "资产经理", 86 | "assignee": "资产经理" 87 | } 88 | } 89 | 90 | 返回值说明: 91 | 92 | 93 | + code 返回代码 94 | + msg 消息提示 95 | + processInstanceId 实例ID 96 | 97 | 返回数据样例: 98 | 99 | { 100 | "msg": "ok", 101 | "processInstanceId": "5001", 102 | "code": 1 103 | } 104 | 105 | 106 | 107 | 108 | 109 | ### 3. 流程定义明细列表 110 | 描述: 通过key获取流程定义明细列表
111 | 功能:
112 | 113 | API:
114 | 方法: POST
115 | 请求地址: /processDefinition/queryProcessInstance
116 | 参数说明:
117 | 118 | | 参数明|类型|说明|是否必填|示例| 119 | |:--------:|:-----:|:-----:|:----:|:-----| 120 | |instanceKey|string|BPMN文件实例名称|否|process_core_ent_credit| 121 | 122 | 123 | 124 | 请求示例: 125 | 126 | { 127 | "instanceKey": "" 128 | } 129 | 130 | 131 | 返回值说明: 132 | 133 | 134 | + code 返回代码 135 | + msg 消息提示 136 | + list 流程定义列表 137 | 138 | 返回数据样例: 139 | 140 | { 141 | "msg": "ok", 142 | "code": 1, 143 | "list": [ 144 | { 145 | "id": "process_core_ent_credit:3:2508", 146 | "name": "XXXX", 147 | "description": "XXXX", 148 | "key": "process_core_ent_credit", 149 | "version": 3, 150 | "category": "http://www.activiti.org/processdef", 151 | "deploymentId": "2505", 152 | "resourceName": "processes/process_core_ent_credit.bpmn20.xml", 153 | "tenantId": "", 154 | "historyLevel": null, 155 | "diagramResourceName": null, 156 | "variables": null, 157 | "hasStartFormKey": false, 158 | "suspensionState": 1, 159 | "engineVersion": null, 160 | "identityLinksInitialized": false, 161 | "graphicalNotationDefined": true 162 | }, 163 | { 164 | "id": "process_core_ent_project:1:5020", 165 | "name": "XXX", 166 | "description": null, 167 | "key": "process_core_ent_project", 168 | "version": 1, 169 | "category": "http://www.activiti.org/processdef", 170 | "deploymentId": "5017", 171 | "resourceName": "processes/process_core_ent_project.bpmn20.xml", 172 | "tenantId": "", 173 | "historyLevel": null, 174 | "diagramResourceName": null, 175 | "variables": null, 176 | "hasStartFormKey": false, 177 | "suspensionState": 1, 178 | "engineVersion": null, 179 | "identityLinksInitialized": false, 180 | "graphicalNotationDefined": true 181 | } 182 | ] 183 | } 184 | 185 | 186 | 187 | ### 4. 查询用户任务列表 188 | 描述: 查询用户任务列表
189 | 功能:
190 | 191 | API:
192 | 方法: POST
193 | 请求地址: /flowUser/queryTask
194 | 参数说明:
195 | 196 | | 参数明|类型|说明|是否必填|示例| 197 | |:--------:|:-----:|:-----:|:----:|:-----| 198 | |assignee|string|审核人|否|Allen| 199 | |candidateUser|string|审核候选人|否|Allen| 200 | |candidateGroup|string|审核候选组|否|风控部门组| 201 | 202 | 请求示例: 203 | 204 | { 205 | "assignee": "", 206 | "candidateUser": "deptLeader", 207 | "candidateGroup": "hrGroups" 208 | } 209 | 210 | 211 | 返回值说明: 212 | 213 | 214 | + code 返回代码 215 | + msg 消息提示 216 | + list 任务列表 217 | 218 | 返回数据样例: 219 | 220 | { 221 | "msg": "ok", 222 | "code": 1, 223 | "list": [ 224 | { 225 | "id": "5013", 226 | "owner": null, 227 | "assigneeUpdatedCount": 0, 228 | "originalAssignee": null, 229 | "assignee": null, 230 | "parentTaskId": null, 231 | "name": "XXX", 232 | "localizedName": null, 233 | "description": null, 234 | "localizedDescription": null, 235 | "priority": 50, 236 | "createTime": "2018-07-06 03:04:47", 237 | "dueDate": null, 238 | "suspensionState": 1, 239 | "category": null, 240 | "executionId": "5010", 241 | "processInstanceId": "5001", 242 | "processDefinitionId": "process_core_ent_credit:3:2508", 243 | "taskDefinitionKey": "sid-1E9202D7-134D-44D0-A8C7-17C21D867102", 244 | "formKey": null, 245 | "eventName": null, 246 | "tenantId": "", 247 | "forcedUpdate": false, 248 | "claimTime": null, 249 | "variables": { 250 | "param5": "内容5", 251 | "assignee": "资产经理", 252 | "param3": "内容3", 253 | "flowId": "2", 254 | "param4": "内容4", 255 | "applyUserId": "资产经理", 256 | "param1": "内容1", 257 | "param2": "内容2" 258 | }, 259 | "deleted": false, 260 | "canceled": false, 261 | "identityLinksInitialized": false 262 | } 263 | ] 264 | } 265 | 266 | 267 | 268 | ### 5. 查询待办任务 269 | 描述: 查询待办任务
270 | 功能:
271 | 272 | API:
273 | 方法: POST
274 | 请求地址: /flowUser/queryWaitTask
275 | 参数说明:
276 | 277 | | 参数明|类型|说明|是否必填|示例| 278 | |:--------:|:-----:|:-----:|:----:|:-----| 279 | |tmp|string|随便参数名|是|xxx| 280 | 281 | 请求示例: 282 | 283 | {"tmp":""} 284 | 285 | 286 | 返回值说明: 287 | 288 | 289 | + code 返回代码 290 | + msg 消息提示 291 | + list 任务列表 292 | 293 | 返回数据样例: 294 | 295 | { 296 | "msg": "ok", 297 | "code": 1, 298 | "list": [ 299 | { 300 | "id": "5013", 301 | "owner": null, 302 | "assigneeUpdatedCount": 0, 303 | "originalAssignee": null, 304 | "assignee": null, 305 | "parentTaskId": null, 306 | "name": "XXX", 307 | "localizedName": null, 308 | "description": null, 309 | "localizedDescription": null, 310 | "priority": 50, 311 | "createTime": "2018-07-06 03:04:47", 312 | "dueDate": null, 313 | "suspensionState": 1, 314 | "category": null, 315 | "executionId": "5010", 316 | "processInstanceId": "5001", 317 | "processDefinitionId": "process_core_ent_credit:3:2508", 318 | "taskDefinitionKey": "sid-1E9202D7-134D-44D0-A8C7-17C21D867102", 319 | "formKey": null, 320 | "eventName": null, 321 | "tenantId": "", 322 | "forcedUpdate": false, 323 | "claimTime": null, 324 | "variables": null, 325 | "deleted": false, 326 | "canceled": false, 327 | "identityLinksInitialized": false 328 | } 329 | ] 330 | } 331 | 332 | 333 | ### 6. 完成任务 334 | 描述: 用户完成任务操作
335 | 功能:
336 | 337 | API:
338 | 方法: POST
339 | 请求地址: /flowUser/completeTask
340 | 参数说明:
341 | 342 | | 参数明|类型|说明|是否必填|示例| 343 | |:--------:|:-----:|:-----:|:----:|:-----| 344 | |taskId|string|任务ID|是|1212| 345 | |assignee|string|审批人|否|1212| 346 | |isReviewPass|int|是否通过审核 [0:未通过,1:通过] 默认值 1|否|1| 347 | |returnStart|int|是否返回到开始节点 [0:返回上一个节点,1:返回到起始节点] 默认值 0|否|1| 348 | |variables|map|表单参数|是|{"param1":"232","param2":"23"}| 349 | 350 | 请求示例: 351 | 352 | { 353 | "taskId": "5013", 354 | "assignee": "资产总经理", 355 | "isReviewPass": 1, 356 | "returnStart": 0, 357 | "params": { 358 | "param1": "内容1", 359 | "param2": "内容2", 360 | "param3": "内容3", 361 | "param4": "内容4", 362 | "param5": "内容5", 363 | "review": true, 364 | "reviewConteng": "没问题" 365 | } 366 | } 367 | 368 | 369 | 返回值说明: 370 | 371 | 372 | + code 返回代码 373 | + msg 消息提示 374 | + isFinish 流程是否结束 375 | 376 | 返回数据样例: 377 | 378 | { 379 | "msg": "ok", 380 | "code": 1, 381 | "isFinish": false 382 | } 383 | 384 | 385 | 386 | ### 7. 任务指派 387 | 描述: 任务指派
388 | 功能:
389 | 390 | API:
391 | 方法: POST
392 | 请求地址: /flowUser/claimTask
393 | 参数说明:
394 | 395 | | 参数明|类型|说明|是否必填|示例| 396 | |:--------:|:-----:|:-----:|:----:|:-----| 397 | |taskId|string|任务ID|是|1212| 398 | |userId|string|被指派人用户ID|否|1212| 399 | 400 | 请求示例: 401 | 402 | { 403 | "taskId": "112522", 404 | "userId": "hr1" 405 | } 406 | 407 | 返回值说明: 408 | 409 | 410 | + code 返回代码 411 | + msg 消息提示 412 | + isFinish 流程是否结束 413 | 414 | 返回数据样例: 415 | 416 | { 417 | "msg": "ok", 418 | "code": 1 419 | } 420 | 421 | 422 | 423 | ### 8. 查询审核历史 424 | 描述: 任务指派
425 | 功能:
426 | 427 | API:
428 | 方法: POST
429 | 请求地址: /flowUser/queryTaskHistory
430 | 参数说明:
431 | 432 | | 参数明|类型|说明|是否必填|示例| 433 | |:--------:|:-----:|:-----:|:----:|:-----| 434 | |processInstanceId|string|任务实例ID|是|1212| 435 | 436 | 请求示例: 437 | 438 | { 439 | "processInstanceId": "5" 440 | } 441 | 442 | 返回值说明: 443 | 444 | 445 | + code 返回代码 446 | + msg 消息提示 447 | + list 流程实例列表 448 | 449 | 返回数据样例: 450 | 451 | { 452 | "msg": "ok", 453 | "code": 1, 454 | "list": [ 455 | { 456 | "executionId": "14", 457 | "name": "XXXX", 458 | "localizedName": null, 459 | "parentTaskId": null, 460 | "description": null, 461 | "localizedDescription": null, 462 | "owner": null, 463 | "assignee": "XX", 464 | "taskDefinitionKey": "sid-1E9202D7-134D-44D0-A8C7-17C21D867102", 465 | "formKey": null, 466 | "priority": 50, 467 | "dueDate": null, 468 | "claimTime": "2018-07-05 09:22:05", 469 | "category": null, 470 | "tenantId": "", 471 | "processInstanceId": "5", 472 | "processDefinitionId": "process_core_ent_credit:1:4", 473 | "startTime": "2018-07-05 09:21:50", 474 | "endTime": "2018-07-05 09:22:05", 475 | "durationInMillis": 15379, 476 | "deleteReason": null, 477 | "variables": { 478 | "reviewConteng": "没问题", 479 | "param5": "内容5", 480 | "review": true, 481 | "param3": "内容3", 482 | "param4": "内容4", 483 | "param1": "内容1", 484 | "param2": "内容2" 485 | } 486 | }, 487 | { 488 | "executionId": "14", 489 | "name": "XX", 490 | "localizedName": null, 491 | "parentTaskId": null, 492 | "description": null, 493 | "localizedDescription": null, 494 | "owner": null, 495 | "assignee": "XX", 496 | "taskDefinitionKey": "sid-B26EAAEE-C2BE-4A9D-8FE4-7AF1A629ACFC", 497 | "formKey": null, 498 | "priority": 50, 499 | "dueDate": null, 500 | "claimTime": null, 501 | "category": null, 502 | "tenantId": "", 503 | "processInstanceId": "5", 504 | "processDefinitionId": "process_core_ent_credit:1:4", 505 | "startTime": "2018-07-05 09:22:05", 506 | "endTime": "2018-07-05 09:22:44", 507 | "durationInMillis": 38517, 508 | "deleteReason": null, 509 | "variables": { 510 | "reviewConteng": "没风险,同意", 511 | "param5": "内容5", 512 | "review": true, 513 | "param3": "内容3", 514 | "param4": "内容4", 515 | "param1": "内容1", 516 | "param2": "内容2" 517 | } 518 | }, 519 | { 520 | "executionId": "14", 521 | "name": "XX XX", 522 | "localizedName": null, 523 | "parentTaskId": null, 524 | "description": null, 525 | "localizedDescription": null, 526 | "owner": null, 527 | "assignee": "XX", 528 | "taskDefinitionKey": "sid-E39E699C-B70E-488F-82F1-718517ECF215", 529 | "formKey": null, 530 | "priority": 50, 531 | "dueDate": null, 532 | "claimTime": "2018-07-05 09:23:41", 533 | "category": null, 534 | "tenantId": "", 535 | "processInstanceId": "5", 536 | "processDefinitionId": "process_core_ent_credit:1:4", 537 | "startTime": "2018-07-05 09:22:44", 538 | "endTime": "2018-07-05 09:23:42", 539 | "durationInMillis": 57850, 540 | "deleteReason": null, 541 | "variables": { 542 | "reviewConteng": "同意,没问题", 543 | "param5": "内容5", 544 | "review": true, 545 | "param3": "内容3", 546 | "param4": "内容4", 547 | "param1": "内容1", 548 | "param2": "内容2" 549 | } 550 | }, 551 | { 552 | "executionId": "14", 553 | "name": "法务经理审核", 554 | "localizedName": null, 555 | "parentTaskId": null, 556 | "description": null, 557 | "localizedDescription": null, 558 | "owner": null, 559 | "assignee": "法务经理", 560 | "taskDefinitionKey": "sid-D2260A87-C8DD-4837-BBB7-0DB2B9CC4D90", 561 | "formKey": null, 562 | "priority": 50, 563 | "dueDate": null, 564 | "claimTime": null, 565 | "category": null, 566 | "tenantId": "", 567 | "processInstanceId": "5", 568 | "processDefinitionId": "process_core_ent_credit:1:4", 569 | "startTime": "2018-07-05 09:23:42", 570 | "endTime": "2018-07-05 09:24:00", 571 | "durationInMillis": 18366, 572 | "deleteReason": null, 573 | "variables": { 574 | "reviewConteng": "同意,没问题", 575 | "param5": "内容5", 576 | "review": true, 577 | "param3": "内容3", 578 | "param4": "内容4", 579 | "param1": "内容1", 580 | "param2": "内容2" 581 | } 582 | }, 583 | { 584 | "executionId": "14", 585 | "name": "XX 理审核", 586 | "localizedName": null, 587 | "parentTaskId": null, 588 | "description": null, 589 | "localizedDescription": null, 590 | "owner": null, 591 | "assignee": "XXX", 592 | "taskDefinitionKey": "sid-D257D11D-C44B-4F83-9B55-AC2E1088785F", 593 | "formKey": null, 594 | "priority": 50, 595 | "dueDate": null, 596 | "claimTime": "2018-07-05 09:24:19", 597 | "category": null, 598 | "tenantId": "", 599 | "processInstanceId": "5", 600 | "processDefinitionId": "process_core_ent_credit:1:4", 601 | "startTime": "2018-07-05 09:24:00", 602 | "endTime": "2018-07-05 09:24:19", 603 | "durationInMillis": 19077, 604 | "deleteReason": null, 605 | "variables": { 606 | "reviewConteng": "同意,没问题", 607 | "param5": "内容5", 608 | "review": true, 609 | "param3": "内容3", 610 | "param4": "内容4", 611 | "param1": "内容1", 612 | "param2": "内容2" 613 | } 614 | }, 615 | { 616 | "executionId": "14", 617 | "name": "XXXX", 618 | "localizedName": null, 619 | "parentTaskId": null, 620 | "description": null, 621 | "localizedDescription": null, 622 | "owner": null, 623 | "assignee": "秘书", 624 | "taskDefinitionKey": "sid-EF4E6C58-6FAA-4A8A-8B98-792B0F3B3BA7", 625 | "formKey": null, 626 | "priority": 50, 627 | "dueDate": null, 628 | "claimTime": null, 629 | "category": null, 630 | "tenantId": "", 631 | "processInstanceId": "5", 632 | "processDefinitionId": "process_core_ent_credit:1:4", 633 | "startTime": "2018-07-05 09:24:19", 634 | "endTime": "2018-07-05 09:25:23", 635 | "durationInMillis": 63528, 636 | "deleteReason": null, 637 | "variables": { 638 | "param5": "内容5", 639 | "assigneeList": [ 640 | "zhangsan", 641 | "lisi", 642 | "wangwu", 643 | "zhaoliu" 644 | ], 645 | "param3": "内容3", 646 | "param4": "内容4", 647 | "param1": "内容1", 648 | "param2": "内容2" 649 | } 650 | }, 651 | { 652 | "executionId": "105", 653 | "name": "委员投票", 654 | "localizedName": null, 655 | "parentTaskId": null, 656 | "description": null, 657 | "localizedDescription": null, 658 | "owner": null, 659 | "assignee": null, 660 | "taskDefinitionKey": "sid-DA97B90B-B68C-4F82-841E-9401F52A06C8", 661 | "formKey": null, 662 | "priority": 50, 663 | "dueDate": null, 664 | "claimTime": null, 665 | "category": null, 666 | "tenantId": "", 667 | "processInstanceId": "5", 668 | "processDefinitionId": "process_core_ent_credit:1:4", 669 | "startTime": "2018-07-05 09:25:23", 670 | "endTime": "2018-07-05 09:26:43", 671 | "durationInMillis": 80225, 672 | "deleteReason": null, 673 | "variables": { 674 | "param5": "内容5", 675 | "multi_vote_pass": true, 676 | "param3": "内容3", 677 | "param4": "内容4", 678 | "param1": "内容1", 679 | "param2": "内容2" 680 | } 681 | }, 682 | { 683 | "executionId": "106", 684 | "name": "委员投票", 685 | "localizedName": null, 686 | "parentTaskId": null, 687 | "description": null, 688 | "localizedDescription": null, 689 | "owner": null, 690 | "assignee": null, 691 | "taskDefinitionKey": "sid-DA97B90B-B68C-4F82-841E-9401F52A06C8", 692 | "formKey": null, 693 | "priority": 50, 694 | "dueDate": null, 695 | "claimTime": null, 696 | "category": null, 697 | "tenantId": "", 698 | "processInstanceId": "5", 699 | "processDefinitionId": "process_core_ent_credit:1:4", 700 | "startTime": "2018-07-05 09:25:23", 701 | "endTime": "2018-07-05 09:27:33", 702 | "durationInMillis": 130008, 703 | "deleteReason": null, 704 | "variables": { 705 | "reviewConteng": "同意1", 706 | "param5": "内容5", 707 | "multi_vote_pass": true, 708 | "review": true, 709 | "param3": "内容3", 710 | "param4": "内容4", 711 | "param1": "内容1", 712 | "param2": "内容2" 713 | } 714 | }, 715 | { 716 | "executionId": "107", 717 | "name": "委员投票", 718 | "localizedName": null, 719 | "parentTaskId": null, 720 | "description": null, 721 | "localizedDescription": null, 722 | "owner": null, 723 | "assignee": null, 724 | "taskDefinitionKey": "sid-DA97B90B-B68C-4F82-841E-9401F52A06C8", 725 | "formKey": null, 726 | "priority": 50, 727 | "dueDate": null, 728 | "claimTime": null, 729 | "category": null, 730 | "tenantId": "", 731 | "processInstanceId": "5", 732 | "processDefinitionId": "process_core_ent_credit:1:4", 733 | "startTime": "2018-07-05 09:25:23", 734 | "endTime": "2018-07-05 09:29:17", 735 | "durationInMillis": 234197, 736 | "deleteReason": null, 737 | "variables": { 738 | "reviewConteng": "不同意", 739 | "param5": "内容5", 740 | "multi_vote_pass": false, 741 | "param3": "内容3", 742 | "param4": "内容4", 743 | "param1": "内容1", 744 | "param2": "内容2" 745 | } 746 | }, 747 | { 748 | "executionId": "108", 749 | "name": "委员投票", 750 | "localizedName": null, 751 | "parentTaskId": null, 752 | "description": null, 753 | "localizedDescription": null, 754 | "owner": null, 755 | "assignee": null, 756 | "taskDefinitionKey": "sid-DA97B90B-B68C-4F82-841E-9401F52A06C8", 757 | "formKey": null, 758 | "priority": 50, 759 | "dueDate": null, 760 | "claimTime": null, 761 | "category": null, 762 | "tenantId": "", 763 | "processInstanceId": "5", 764 | "processDefinitionId": "process_core_ent_credit:1:4", 765 | "startTime": "2018-07-05 09:25:23", 766 | "endTime": "2018-07-05 09:33:51", 767 | "durationInMillis": 508181, 768 | "deleteReason": null, 769 | "variables": { 770 | "reviewConteng": "同意", 771 | "param5": "内容5", 772 | "multi_vote_pass": true, 773 | "param3": "内容3", 774 | "param4": "内容4", 775 | "param1": "内容1", 776 | "param2": "内容2" 777 | } 778 | }, 779 | { 780 | "executionId": "14", 781 | "name": "XXXX", 782 | "localizedName": null, 783 | "parentTaskId": null, 784 | "description": null, 785 | "localizedDescription": null, 786 | "owner": null, 787 | "assignee": null, 788 | "taskDefinitionKey": "sid-0BAC4ED4-8C81-4632-8209-5B9A02928D77", 789 | "formKey": null, 790 | "priority": 50, 791 | "dueDate": null, 792 | "claimTime": null, 793 | "category": null, 794 | "tenantId": "", 795 | "processInstanceId": "5", 796 | "processDefinitionId": "process_core_ent_credit:1:4", 797 | "startTime": "2018-07-05 09:33:51", 798 | "endTime": "2018-07-05 09:34:33", 799 | "durationInMillis": 41353, 800 | "deleteReason": null, 801 | "variables": { 802 | "multi_vote_count": 3, 803 | "param1": "XXX" 804 | } 805 | }, 806 | { 807 | "executionId": "14", 808 | "name": "主任委员签发", 809 | "localizedName": null, 810 | "parentTaskId": null, 811 | "description": null, 812 | "localizedDescription": null, 813 | "owner": null, 814 | "assignee": null, 815 | "taskDefinitionKey": "sid-55586A2F-4682-4C24-B6C4-7402F40459F9", 816 | "formKey": null, 817 | "priority": 50, 818 | "dueDate": null, 819 | "claimTime": null, 820 | "category": null, 821 | "tenantId": "", 822 | "processInstanceId": "5", 823 | "processDefinitionId": "process_core_ent_credit:1:4", 824 | "startTime": "2018-07-05 09:34:33", 825 | "endTime": "2018-07-05 09:35:30", 826 | "durationInMillis": 57257, 827 | "deleteReason": null, 828 | "variables": { 829 | "reviewConteng": "同意2", 830 | "param5": "内容5", 831 | "review": true, 832 | "param3": "内容3", 833 | "param4": "内容4", 834 | "param1": "内容1", 835 | "param2": "内容2" 836 | } 837 | } 838 | ] 839 | } 840 | 841 | 842 | 843 | 844 | ### 9. 展示流程图 845 | 描述: 流程中的节点状态展示
846 | 功能:
847 | 848 | API:
849 | 方法: POST
850 | 请求地址: /processDefinition/viewProcessInstanceImage
851 | 参数说明:
852 | 853 | | 参数明|类型|说明|是否必填|示例| 854 | |:--------:|:-----:|:-----:|:----:|:-----| 855 | |instanceKey|string|任务实例KEY|是|process_core_ent_project| 856 | |processInstanceId|string|任务实例ID|是|5| 857 | 858 | 请求示例: 859 | 860 | /processDefinition/viewImage?instanceKey=process_core_ent_project&processInstanceId=5 861 | 862 | 863 | ### 10. 流程是否结束 864 | 描述: 流程是否结束
865 | 功能:
866 | 867 | API:
868 | 方法: POST
869 | 请求地址: /processDefinition/isFinishProcess
870 | 参数说明:
871 | 872 | | 参数明|类型|说明|是否必填|示例| 873 | |:--------:|:-----:|:-----:|:----:|:-----| 874 | |processInstanceId|string|任务实例ID|是|5| 875 | 876 | 请求示例: 877 | 878 | { 879 | "processInstanceId": "5" 880 | } 881 | 882 | 返回值说明: 883 | 884 | 885 | + code 返回代码 886 | + msg 消息提示 887 | + isFinish 流程是否结束 888 | 889 | 返回数据样例: 890 | 891 | { 892 | "msg": "ok", 893 | "code": 1, 894 | "isFinish":true 895 | } 896 | --------------------------------------------------------------------------------