!164 从vue版本迁移flowable到cloud版本

* update 按照vue版逻辑改造工作流
* update 去除泛化调用逻辑
* update 更改 工作流 测试用例接口路径
* fix 去除无用修改,还原demo,testLeave挪入工作流模块
* fix 清理无效代码,还原配置
* update 修改监听器属性名
* update 集成工作流
2.X
ZETA 10 months ago committed by 疯狂的狮子Li
parent 0bfc3efc3a
commit 992adc8589

Binary file not shown.

@ -13,6 +13,10 @@ datasource:
url: jdbc:mysql://localhost:3306/ry-job?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
password: password
workflow:
url: jdbc:mysql://localhost:3306/ry-workflow?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
username: root
password: password
# system-oracle:
# url: jdbc:oracle:thin:@//localhost:1521/XE
# username: ROOT

@ -5,6 +5,7 @@ security:
enabled: true
excludeUrls:
- /system/notice
- /workflow/model/editModelXml
# 不校验白名单
ignore:
whites:
@ -59,6 +60,11 @@ spring:
- Path=/resource/**
filters:
- StripPrefix=1
# workflow服务
- id: ruoyi-workflow
uri: lb://ruoyi-workflow
predicates:
- Path=/workflow/**
# 演示服务
- id: ruoyi-demo
uri: lb://ruoyi-demo

@ -0,0 +1,44 @@
spring:
datasource:
dynamic:
# 设置默认的数据源或者数据源组,默认值即为 master
primary: master
seata: false
datasource:
# 主库数据源
master:
type: ${spring.datasource.type}
driver-class-name: com.mysql.cj.jdbc.Driver
url: ${datasource.workflow.url}
username: ${datasource.workflow.username}
password: ${datasource.workflow.password}
# oracle:
# type: ${spring.datasource.type}
# driverClassName: oracle.jdbc.OracleDriver
# url: ${datasource.system-oracle.url}
# username: ${datasource.system-oracle.username}
# password: ${datasource.system-oracle.password}
# postgres:
# type: ${spring.datasource.type}
# driverClassName: org.postgresql.Driver
# url: ${datasource.system-postgres.url}
# username: ${datasource.system-postgres.username}
# password: ${datasource.system-postgres.password}
--- #flowable配置
flowable:
async-executor-activate: false #关闭定时任务JOB
# 将databaseSchemaUpdate设置为true。当Flowable发现库与数据库表结构不一致时会自动将数据库表结构升级至新版本。
database-schema-update: false
activity-font-name: 宋体
label-font-name: 宋体
annotation-font-name: 宋体
# 关闭各个模块生成表,目前只使用工作流基础表
idm:
enabled: false
cmmn:
enabled: false
dmn:
enabled: false
app:
enabled: false

@ -62,6 +62,11 @@
<maven-compiler-plugin.verison>3.11.0</maven-compiler-plugin.verison>
<maven-surefire-plugin.version>3.1.2</maven-surefire-plugin.version>
<flatten-maven-plugin.version>1.3.0</flatten-maven-plugin.version>
<!--工作流配置-->
<flowable.version>7.0.0</flowable.version>
<flowable-json-convertor.version>6.8.0</flowable-json-convertor.version>
<xmlgraphics.version>1.10</xmlgraphics.version>
</properties>
<profiles>
@ -161,6 +166,27 @@
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-bom</artifactId>
<version>${flowable.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-json-converter</artifactId>
<version>${flowable-json-convertor.version}</version>
</dependency>
<!-- svg转png图片工具-->
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-all</artifactId>
<version>${xmlgraphics.version}</version>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-core</artifactId>

@ -12,6 +12,7 @@
<module>ruoyi-api-bom</module>
<module>ruoyi-api-system</module>
<module>ruoyi-api-resource</module>
<module>ruoyi-api-workflow</module>
</modules>
<artifactId>ruoyi-api</artifactId>

@ -34,6 +34,13 @@
<version>${revision}</version>
</dependency>
<!-- workflow接口 -->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-api-workflow</artifactId>
<version>${revision}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

@ -3,6 +3,8 @@ package org.dromara.resource.api;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.resource.api.domain.RemoteFile;
import java.util.List;
/**
*
*
@ -26,4 +28,11 @@ public interface RemoteFileService {
*/
String selectUrlByIds(String ossIds);
/**
* ossId
*
* @param ossIds ossId
* @return
*/
List<RemoteFile> selectByIds(String ossIds);
}

@ -4,6 +4,8 @@ import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.resource.api.domain.RemoteFile;
import java.util.List;
/**
* ()
*
@ -34,4 +36,10 @@ public class RemoteFileServiceMock implements RemoteFileService {
return StringUtils.EMPTY;
}
@Override
public List<RemoteFile> selectByIds(String ossIds) {
log.warn("服务调用异常 -> 降级处理");
return List.of();
}
}

@ -31,4 +31,14 @@ public class RemoteFile implements Serializable {
*/
private String url;
/**
*
*/
private String originalName;
/**
*
*/
private String fileSuffix;
}

@ -3,9 +3,12 @@ package org.dromara.system.api;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.exception.user.UserException;
import org.dromara.system.api.domain.bo.RemoteUserBo;
import org.dromara.system.api.domain.dto.UserDTO;
import org.dromara.system.api.model.LoginUser;
import org.dromara.system.api.model.XcxLoginUser;
import java.util.List;
/**
*
*
@ -105,4 +108,19 @@ public interface RemoteUserService {
*/
void recordLoginInfo(Long userId, String ip);
/**
* ID
*
* @param userIds ids
* @return
*/
List<UserDTO> selectListByIds(List<Long> userIds);
/**
* IDID
*
* @param roleIds ids
* @return ids
*/
List<Long> selectUserIdsByRoleIds(List<Long> roleIds);
}

@ -0,0 +1,73 @@
package org.dromara.system.api.domain.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
*
*
* @author Michelle.Chung
*/
@Data
@NoArgsConstructor
public class UserDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
private Long userId;
/**
* ID
*/
private Long deptId;
/**
*
*/
private String userName;
/**
*
*/
private String nickName;
/**
* sys_user
*/
private String userType;
/**
*
*/
private String email;
/**
*
*/
private String phonenumber;
/**
* 0 1 2
*/
private String sex;
/**
* 0 1
*/
private String status;
/**
*
*/
private Date createTime;
}

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-api</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-api-workflow</artifactId>
<description>
ruoyi-api-resource 资源服务接口模块
</description>
<dependencies>
<!-- RuoYi Common Core-->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-core</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-translation</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,86 @@
package org.dromara.workflow.api.domain;
import org.dromara.workflow.api.domain.dto.BusinessInstanceDTO;
import java.util.List;
import java.util.Map;
/**
*
*
* @Author ZETA
* @Date 2024/6/3
*/
public interface RemoteWorkflowService {
/**
*
*
* @param businessKeys id
* @return
*/
boolean deleteRunAndHisInstance(List<String> businessKeys);
/**
*
*
* @param taskId id
*/
String getBusinessStatusByTaskId(String taskId);
/**
*
*
* @param businessKey id
*/
String getBusinessStatus(String businessKey);
/**
*
*
* @param businessKey id
*/
BusinessInstanceDTO getBusinessInstance(String businessKey);
/**
*
*
* @param businessKeys id
*/
List<BusinessInstanceDTO> getBusinessInstance(List<String> businessKeys);
/**
* ()
*
* @param taskId id
* @param variableName
* @param value
*/
void setVariable(String taskId, String variableName, Object value);
/**
* ()
*
* @param taskId id
* @param variables
*/
void setVariables(String taskId, Map<String, Object> variables);
/**
* (,)
*
* @param taskId id
* @param variableName
* @param value
*/
void setVariableLocal(String taskId, String variableName, Object value);
/**
* (,)
*
* @param taskId id
* @param variables
*/
void setVariablesLocal(String taskId, Map<String, Object> variables);
}

@ -0,0 +1,43 @@
package org.dromara.workflow.api.domain.bo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
*
*
* @author may
*/
@Data
public class ProcessInstanceBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
private String name;
/**
* key
*/
private String key;
/**
*
*/
private String startUserId;
/**
* id
*/
private String businessKey;
/**
*
*/
private String categoryCode;
}

@ -0,0 +1,31 @@
package org.dromara.workflow.api.domain.bo;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
import java.io.Serial;
import java.io.Serializable;
/**
*
*
* @author may
*/
@Data
public class ProcessInvalidBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@NotBlank(message = "业务id不能为空", groups = {AddGroup.class})
private String businessKey;
/**
*
*/
private String deleteReason;
}

@ -0,0 +1,34 @@
package org.dromara.workflow.api.domain.bo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
*
*
* @author may
*/
@Data
public class TaskUrgingBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
private String processInstanceId;
/**
*
*/
private List<String> messageType;
/**
*
*/
private String message;
}

@ -0,0 +1,72 @@
package org.dromara.workflow.api.domain.dto;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
*
*
* @Author ZETA
* @Date 2024/6/3
*/
@Data
@NoArgsConstructor
public class BusinessInstanceDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
private String id;
/**
* id
*/
private String processDefinitionId;
/**
*
*/
private String name;
/**
* id
*/
private String businessKey;
/**
* id
*/
private String tenantId;
/**
*
*/
private Date startTime;
/**
*
*/
private Date endTime;
/**
* id
*/
private String startUserId;
/**
*
*/
private String businessStatus;
/**
*
*/
private String businessStatusName;
}

@ -0,0 +1,47 @@
package org.dromara.workflow.api.domain.event;
import jakarta.servlet.http.HttpServletRequest;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
*
*
* @author may
*/
@Data
public class ProcessEvent implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* key
*/
private String key;
/**
* id
*/
private String businessKey;
/**
*
*/
private String status;
/**
* true
*/
private boolean submit;
/**
*
*/
private HttpServletRequest request;
}

@ -0,0 +1,41 @@
package org.dromara.workflow.api.domain.event;
import jakarta.servlet.http.HttpServletRequest;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
*
*
* @author may
*/
@Data
public class ProcessTaskEvent implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* key(key_)
*/
private String keyNode;
/**
* id
*/
private String taskId;
/**
* id
*/
private String businessKey;
/**
*
*/
private HttpServletRequest request;
}

@ -4,10 +4,11 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.sql.SqlUtil;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@ -21,6 +22,7 @@ import java.util.List;
*/
@Data
@NoArgsConstructor
public class PageQuery implements Serializable {
@Serial
@ -56,6 +58,13 @@ public class PageQuery implements Serializable {
*/
public static final int DEFAULT_PAGE_SIZE = Integer.MAX_VALUE;
public static final PageQuery DEFAULT_PAGE = new PageQuery(DEFAULT_PAGE_NUM, DEFAULT_PAGE_SIZE);
private PageQuery(Integer pageNum, Integer pageSize) {
this.pageSize = pageSize;
this.pageNum = pageNum;
}
public <T> Page<T> build() {
Integer pageNum = ObjectUtil.defaultIfNull(getPageNum(), DEFAULT_PAGE_NUM);
Integer pageSize = ObjectUtil.defaultIfNull(getPageSize(), DEFAULT_PAGE_SIZE);
@ -111,4 +120,8 @@ public class PageQuery implements Serializable {
return list;
}
public Integer getFirstNum() {
return (pageNum - 1) * pageSize;
}
}

@ -21,6 +21,6 @@ public class NicknameTranslationImpl implements TranslationInterface<String> {
@Override
public String translation(Object key, String other) {
return remoteUserService.selectNicknameById((Long) key);
return remoteUserService.selectNicknameById(Long.valueOf(String.valueOf(key)));
}
}

@ -108,6 +108,7 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>

@ -13,6 +13,7 @@
<module>ruoyi-gen</module>
<module>ruoyi-job</module>
<module>ruoyi-resource</module>
<module>ruoyi-workflow</module>
</modules>
<artifactId>ruoyi-modules</artifactId>

@ -1,20 +1,27 @@
package org.dromara.resource.dubbo;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.convert.Convert;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.oss.core.OssClient;
import org.dromara.common.oss.entity.UploadResult;
import org.dromara.common.oss.factory.OssFactory;
import org.dromara.resource.api.RemoteFileService;
import org.dromara.resource.api.domain.RemoteFile;
import org.dromara.resource.domain.bo.SysOssBo;
import org.dromara.resource.domain.vo.SysOssVo;
import org.dromara.resource.service.ISysOssService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.dromara.resource.api.domain.RemoteFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
/**
*
*
@ -68,4 +75,15 @@ public class RemoteFileServiceImpl implements RemoteFileService {
return sysOssService.selectUrlByIds(ossIds);
}
/**
* ossId
*
* @param ossIds ossId
* @return
*/
public List<RemoteFile> selectByIds(String ossIds){
List<SysOssVo> sysOssVos = sysOssService.listByIds(StringUtils.splitTo(ossIds, Convert::toLong));
return BeanUtil.copyToList(sysOssVos, RemoteFile.class,
CopyOptions.create().setFieldMapping(Map.of("fileName", "name")));
}
}

@ -14,6 +14,7 @@ import org.dromara.common.mybatis.helper.DataPermissionHelper;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.system.api.RemoteUserService;
import org.dromara.system.api.domain.bo.RemoteUserBo;
import org.dromara.system.api.domain.dto.UserDTO;
import org.dromara.system.api.model.LoginUser;
import org.dromara.system.api.model.RoleDTO;
import org.dromara.system.api.model.XcxLoginUser;
@ -234,4 +235,15 @@ public class RemoteUserServiceImpl implements RemoteUserService {
DataPermissionHelper.ignore(() -> userMapper.updateById(sysUser));
}
@Override
public List<UserDTO> selectListByIds(List<Long> userIds) {
List<SysUserVo> sysUserVos = userService.selectUserByIds(userIds, null);
return BeanUtil.copyToList(sysUserVos, UserDTO.class);
}
@Override
public List<Long> selectUserIdsByRoleIds(List<Long> roleIds) {
return userService.selectUserIdsByRoleIds(roleIds);
}
}

@ -252,4 +252,11 @@ public interface ISysUserService {
*/
List<SysUserVo> selectUserListByDept(Long deptId);
/**
* IDID
*
* @param roleIds ids
* @return ids
*/
List<Long> selectUserIdsByRoleIds(List<Long> roleIds);
}

@ -553,6 +553,13 @@ public class SysUserServiceImpl implements ISysUserService {
return baseMapper.selectVoList(lqw);
}
@Override
public List<Long> selectUserIdsByRoleIds(List<Long> roleIds) {
List<SysUserRole> userRoles = userRoleMapper.selectList(
new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getRoleId, roleIds));
return StreamUtils.toList(userRoles, SysUserRole::getUserId);
}
/**
* ID
*

@ -0,0 +1,138 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-modules</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-workflow</artifactId>
<description>
工作流模块
</description>
<dependencies>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-nacos</artifactId>
</dependency>
<!--引入flowable依赖-->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-autoconfigure</artifactId>
<exclusions>
<exclusion>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-security</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-configurator</artifactId>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 绘制flowable流程图 -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-image-generator</artifactId>
</dependency>
<!-- flowable json 转换 -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-json-converter</artifactId>
<version>6.8.0</version>
</dependency>
<!-- svg转png图片工具-->
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-all</artifactId>
<exclusions>
<exclusion>
<groupId>xalan</groupId>
<artifactId>xalan</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-mail</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-sms</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-mybatis</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-web</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-log</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-idempotent</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-excel</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-translation</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-tenant</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-tenant</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-security</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-api-workflow</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,22 @@
package org.dromara.workflow;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
/**
*
*
* @author ruoyi
*/
@EnableDubbo
@SpringBootApplication
public class RuoYiWorkflowApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(RuoYiWorkflowApplication.class);
application.setApplicationStartup(new BufferingApplicationStartup(2048));
application.run(args);
System.out.println("(♥◠‿◠)ノ゙ 工作流模块启动成功 ლ(´ڡ`ლ)゙ ");
}
}

@ -0,0 +1,137 @@
package org.dromara.workflow.common.constant;
/**
*
*
* @author may
*/
public interface FlowConstant {
String MESSAGE_CURRENT_TASK_IS_NULL = "当前任务不存在或你不是任务办理人!";
String MESSAGE_SUSPENDED = "当前任务已挂起不可审批!";
/**
* 线
*/
String SEQUENCE_FLOW = "sequenceFlow";
/**
*
*/
String PARALLEL_GATEWAY = "parallelGateway";
/**
*
*/
String EXCLUSIVE_GATEWAY = "exclusiveGateway";
/**
*
*/
String INCLUSIVE_GATEWAY = "inclusiveGateway";
/**
*
*/
String END_EVENT = "endEvent";
/**
*
*/
String PENDING = "PENDING";
/**
*
*/
String CANDIDATE = "candidate";
/**
*
*/
String NUMBER_OF_INSTANCES = "nrOfInstances";
/**
*
*/
String NUMBER_OF_ACTIVE_INSTANCES = "nrOfActiveInstances";
/**
*
*/
String NUMBER_OF_COMPLETED_INSTANCES = "nrOfCompletedInstances";
/**
* 使elementIndexVariableloopCounter
*/
String LOOP_COUNTER = "loopCounter";
String ZIP = "ZIP";
/**
*
*/
String BUSINESS_INSTANCE_DTO = "businessInstanceDTO";
/**
*
*/
String WF_DEFINITION_CONFIG_VO = "wfDefinitionConfigVo";
/**
*
*/
String WF_NODE_CONFIG_VO = "wfNodeConfigVo";
/**
*
*/
String INITIATOR = "initiator";
/**
* id
*/
String PROCESS_INSTANCE_ID = "processInstanceId";
/**
* id
*/
String BUSINESS_KEY = "businessKey";
/**
* id
*/
String PROCESS_DEFINITION_ID = "processDefinitionId";
/**
*
*/
String FLOWABLE_SKIP_EXPRESSION_ENABLED = "_FLOWABLE_SKIP_EXPRESSION_ENABLED";
/**
* key
*/
String MODEL_KEY_PATTERN = "^[a-zA-Z][a-zA-Z0-9_]{0,254}$";
/**
*
*/
String USER_TASK = "userTask";
/**
*
*/
String MULTI_INSTANCE = "multiInstance";
/**
*
*/
String TRUE = "0";
/**
*
*/
String FALSE = "1";
}

@ -0,0 +1,152 @@
package org.dromara.workflow.common.enums;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import java.util.Arrays;
/**
*
*
* @author may
*/
@Getter
@AllArgsConstructor
public enum BusinessStatusEnum {
/**
*
*/
CANCEL("cancel", "已撤销"),
/**
* 稿
*/
DRAFT("draft", "草稿"),
/**
*
*/
WAITING("waiting", "待审核"),
/**
*
*/
FINISH("finish", "已完成"),
/**
*
*/
INVALID("invalid", "已作废"),
/**
* 退
*/
BACK("back", "已退回"),
/**
*
*/
TERMINATION("termination", "已终止");
/**
*
*/
private final String status;
/**
*
*/
private final String desc;
/**
*
*
* @param status
*/
public static String findByStatus(String status) {
if (StringUtils.isBlank(status)) {
return StrUtil.EMPTY;
}
return Arrays.stream(BusinessStatusEnum.values())
.filter(statusEnum -> statusEnum.getStatus().equals(status))
.findFirst()
.map(BusinessStatusEnum::getDesc)
.orElse(StrUtil.EMPTY);
}
/**
*
*
* @param status
*/
public static void checkStartStatus(String status) {
if (WAITING.getStatus().equals(status)) {
throw new ServiceException("该单据已提交过申请,正在审批中!");
} else if (FINISH.getStatus().equals(status)) {
throw new ServiceException("该单据已完成申请!");
} else if (INVALID.getStatus().equals(status)) {
throw new ServiceException("该单据已作废!");
} else if (TERMINATION.getStatus().equals(status)) {
throw new ServiceException("该单据已终止!");
} else if (StringUtils.isBlank(status)) {
throw new ServiceException("流程状态为空!");
}
}
/**
*
*
* @param status
*/
public static void checkCancelStatus(String status) {
if (CANCEL.getStatus().equals(status)) {
throw new ServiceException("该单据已撤销!");
} else if (FINISH.getStatus().equals(status)) {
throw new ServiceException("该单据已完成申请!");
} else if (INVALID.getStatus().equals(status)) {
throw new ServiceException("该单据已作废!");
} else if (TERMINATION.getStatus().equals(status)) {
throw new ServiceException("该单据已终止!");
} else if (BACK.getStatus().equals(status)) {
throw new ServiceException("该单据已退回!");
} else if (StringUtils.isBlank(status)) {
throw new ServiceException("流程状态为空!");
}
}
/**
*
*
* @param status
*/
public static void checkBackStatus(String status) {
if (BACK.getStatus().equals(status)) {
throw new ServiceException("该单据已退回!");
} else if (FINISH.getStatus().equals(status)) {
throw new ServiceException("该单据已完成申请!");
} else if (INVALID.getStatus().equals(status)) {
throw new ServiceException("该单据已作废!");
} else if (TERMINATION.getStatus().equals(status)) {
throw new ServiceException("该单据已终止!");
} else if (CANCEL.getStatus().equals(status)) {
throw new ServiceException("该单据已撤销!");
} else if (StringUtils.isBlank(status)) {
throw new ServiceException("流程状态为空!");
}
}
/**
* ,
*
* @param status
*/
public static void checkInvalidStatus(String status) {
if (FINISH.getStatus().equals(status)) {
throw new ServiceException("该单据已完成申请!");
} else if (INVALID.getStatus().equals(status)) {
throw new ServiceException("该单据已作废!");
} else if (TERMINATION.getStatus().equals(status)) {
throw new ServiceException("该单据已终止!");
} else if (StringUtils.isBlank(status)) {
throw new ServiceException("流程状态为空!");
}
}
}

@ -0,0 +1,54 @@
package org.dromara.workflow.common.enums;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
/**
*
*
* @author may
*/
@Getter
@AllArgsConstructor
public enum FormTypeEnum {
/**
*
*/
STATIC("static", "自定义表单"),
/**
*
*/
DYNAMIC("dynamic", "动态表单");
/**
*
*/
private final String type;
/**
*
*/
private final String desc;
/**
*
*
* @param formType
*/
public static String findByType(String formType) {
if (StringUtils.isBlank(formType)) {
return StrUtil.EMPTY;
}
return Arrays.stream(FormTypeEnum.values())
.filter(statusEnum -> statusEnum.getType().equals(formType))
.findFirst()
.map(FormTypeEnum::getDesc)
.orElse(StrUtil.EMPTY);
}
}

@ -0,0 +1,51 @@
package org.dromara.workflow.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
*
*
* @author may
*/
@Getter
@AllArgsConstructor
public enum MessageTypeEnum {
/**
*
*/
SYSTEM_MESSAGE("1", "站内信"),
/**
*
*/
EMAIL_MESSAGE("2", "邮箱"),
/**
*
*/
SMS_MESSAGE("3", "短信");
private final String code;
private final String desc;
private final static Map<String, MessageTypeEnum> MESSAGE_TYPE_ENUM_MAP = new ConcurrentHashMap<>(MessageTypeEnum.values().length);
static {
for (MessageTypeEnum messageType : MessageTypeEnum.values()) {
MESSAGE_TYPE_ENUM_MAP.put(messageType.code, messageType);
}
}
/**
* code MessageTypeEnum
* @param code code
* @return MessageTypeEnum
*/
public static MessageTypeEnum getByCode(String code) {
return MESSAGE_TYPE_ENUM_MAP.get(code);
}
}

@ -0,0 +1,94 @@
package org.dromara.workflow.common.enums;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
/**
*
*
* @author may
*/
@Getter
@AllArgsConstructor
public enum TaskStatusEnum {
/**
*
*/
CANCEL("cancel", "撤销"),
/**
*
*/
PASS("pass", "通过"),
/**
*
*/
WAITING("waiting", "待审核"),
/**
*
*/
INVALID("invalid", "作废"),
/**
* 退
*/
BACK("back", "退回"),
/**
*
*/
TERMINATION("termination", "终止"),
/**
*
*/
TRANSFER("transfer", "转办"),
/**
*
*/
PENDING("pending", "委托"),
/**
*
*/
COPY("copy", "抄送"),
/**
*
*/
SIGN("sign", "加签"),
/**
*
*/
SIGN_OFF("sign_off", "减签"),
/**
*
*/
TIMEOUT("timeout", "超时");
/**
*
*/
private final String status;
/**
*
*/
private final String desc;
/**
*
*
* @param status
*/
public static String findByStatus(String status) {
if (StringUtils.isBlank(status)) {
return StrUtil.EMPTY;
}
return Arrays.stream(TaskStatusEnum.values())
.filter(statusEnum -> statusEnum.getStatus().equals(status))
.findFirst()
.map(TaskStatusEnum::getDesc)
.orElse(StrUtil.EMPTY);
}
}

@ -0,0 +1,154 @@
package org.dromara.workflow.controller;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.web.core.BaseController;
import org.dromara.resource.api.RemoteFileService;
import org.dromara.resource.api.domain.RemoteFile;
import org.dromara.system.api.model.LoginUser;
import org.dromara.workflow.domain.bo.ModelBo;
import org.dromara.workflow.domain.vo.ModelVo;
import org.dromara.workflow.service.IActModelService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Model;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
/**
*
*
* @author may
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/model")
public class ActModelController extends BaseController {
private final RepositoryService repositoryService;
private final IActModelService actModelService;
/**
*
*
* @param modelBo
*/
@GetMapping("/list")
public TableDataInfo<Model> page(ModelBo modelBo, PageQuery pageQuery) {
RemoteFileService bean = SpringUtils.getBean(RemoteFileService.class);
List<RemoteFile> remoteFiles = bean.selectByIds("1");
return actModelService.page(modelBo, pageQuery);
}
/**
*
*
* @param modelBo
*/
@Log(title = "模型管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/save")
public R<Void> saveNewModel(@Validated(AddGroup.class) @RequestBody ModelBo modelBo) {
return toAjax(actModelService.saveNewModel(modelBo));
}
/**
*
*
* @param id id
*/
@GetMapping("/getInfo/{id}")
public R<ModelVo> getInfo(@NotBlank(message = "模型id不能为空") @PathVariable String id) {
return R.ok(actModelService.getInfo(id));
}
/**
*
*
* @param modelBo
*/
@Log(title = "模型管理", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping(value = "/update")
public R<Void> update(@RequestBody ModelBo modelBo) {
return toAjax(actModelService.update(modelBo));
}
/**
* XMl
*
* @param modelBo
*/
@Log(title = "模型管理", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping(value = "/editModelXml")
public R<Void> editModel(@Validated(EditGroup.class) @RequestBody ModelBo modelBo) {
return toAjax(actModelService.editModelXml(modelBo));
}
/**
*
*
* @param ids id
*/
@Log(title = "模型管理", businessType = BusinessType.DELETE)
@RepeatSubmit()
@DeleteMapping("/{ids}")
@Transactional(rollbackFor = Exception.class)
public R<Void> delete(@NotEmpty(message = "主键不能为空") @PathVariable String[] ids) {
Arrays.stream(ids).parallel().forEachOrdered(repositoryService::deleteModel);
return R.ok();
}
/**
*
*
* @param id id
*/
@Log(title = "模型管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/modelDeploy/{id}")
public R<Void> deploy(@NotBlank(message = "模型id不能为空") @PathVariable("id") String id) {
return toAjax(actModelService.modelDeploy(id));
}
/**
* zip
*
* @param modelIds id
* @param response
*/
@GetMapping("/export/zip/{modelIds}")
public void exportZip(@NotEmpty(message = "模型id不能为空") @PathVariable List<String> modelIds,
HttpServletResponse response) {
actModelService.exportZip(modelIds, response);
}
/**
*
*
* @param modelBo
*/
@PostMapping("/copyModel")
public R<Void> copyModel(@RequestBody ModelBo modelBo) {
return toAjax(actModelService.copyModel(modelBo));
}
}

@ -0,0 +1,147 @@
package org.dromara.workflow.controller;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.workflow.domain.bo.ProcessDefinitionBo;
import org.dromara.workflow.domain.vo.ProcessDefinitionVo;
import org.dromara.workflow.service.IActProcessDefinitionService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
*
* @author may
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/processDefinition")
public class ActProcessDefinitionController extends BaseController {
private final IActProcessDefinitionService actProcessDefinitionService;
/**
*
*
* @param bo
*/
@GetMapping("/list")
public TableDataInfo<ProcessDefinitionVo> page(ProcessDefinitionBo bo, PageQuery pageQuery) {
return actProcessDefinitionService.page(bo, pageQuery);
}
/**
*
*
* @param key key
*/
@GetMapping("/getListByKey/{key}")
public R<List<ProcessDefinitionVo>> getListByKey(@NotEmpty(message = "流程定义key不能为空") @PathVariable String key) {
return R.ok("操作成功", actProcessDefinitionService.getListByKey(key));
}
/**
*
*
* @param processDefinitionId id
*/
@GetMapping("/definitionImage/{processDefinitionId}")
public R<String> definitionImage(@PathVariable String processDefinitionId) {
return R.ok("操作成功", actProcessDefinitionService.definitionImage(processDefinitionId));
}
/**
* xml
*
* @param processDefinitionId id
*/
@GetMapping("/definitionXml/{processDefinitionId}")
public R<Map<String, Object>> definitionXml(@NotBlank(message = "流程定义id不能为空") @PathVariable String processDefinitionId) {
Map<String, Object> map = new HashMap<>();
String xmlStr = actProcessDefinitionService.definitionXml(processDefinitionId);
map.put("xml", Arrays.asList(xmlStr.split("\n")));
map.put("xmlStr", xmlStr);
return R.ok(map);
}
/**
*
*
* @param deploymentIds id
* @param processDefinitionIds id
*/
@Log(title = "流程定义管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{deploymentIds}/{processDefinitionIds}")
public R<Void> deleteDeployment(@NotNull(message = "流程部署id不能为空") @PathVariable List<String> deploymentIds,
@NotNull(message = "流程定义id不能为空") @PathVariable List<String> processDefinitionIds) {
return toAjax(actProcessDefinitionService.deleteDeployment(deploymentIds, processDefinitionIds));
}
/**
*
*
* @param processDefinitionId id
*/
@Log(title = "流程定义管理", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/updateDefinitionState/{processDefinitionId}")
public R<Void> updateDefinitionState(@NotBlank(message = "流程定义id不能为空") @PathVariable String processDefinitionId) {
return toAjax(actProcessDefinitionService.updateDefinitionState(processDefinitionId));
}
/**
*
*
* @param currentProcessDefinitionId id
* @param fromProcessDefinitionId id
*/
@Log(title = "流程定义管理", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/migrationDefinition/{currentProcessDefinitionId}/{fromProcessDefinitionId}")
public R<Void> migrationDefinition(@NotBlank(message = "当前流程定义id") @PathVariable String currentProcessDefinitionId,
@NotBlank(message = "需要迁移到的流程定义id") @PathVariable String fromProcessDefinitionId) {
return toAjax(actProcessDefinitionService.migrationDefinition(currentProcessDefinitionId, fromProcessDefinitionId));
}
/**
*
*
* @param processDefinitionId id
*/
@Log(title = "流程定义管理", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/convertToModel/{processDefinitionId}")
public R<Void> convertToModel(@NotEmpty(message = "流程定义id不能为空") @PathVariable String processDefinitionId) {
return toAjax(actProcessDefinitionService.convertToModel(processDefinitionId));
}
/**
* zipxml
*
* @param file
* @param categoryCode
*/
@Log(title = "流程定义管理", businessType = BusinessType.INSERT)
@PostMapping("/deployByFile")
public void deployByFile(@RequestParam("file") MultipartFile file, @RequestParam("categoryCode") String categoryCode) {
actProcessDefinitionService.deployByFile(file, categoryCode);
}
}

@ -0,0 +1,160 @@
package org.dromara.workflow.controller;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.workflow.api.domain.bo.ProcessInstanceBo;
import org.dromara.workflow.api.domain.bo.ProcessInvalidBo;
import org.dromara.workflow.api.domain.bo.TaskUrgingBo;
import org.dromara.workflow.domain.vo.ActHistoryInfoVo;
import org.dromara.workflow.domain.vo.ProcessInstanceVo;
import org.dromara.workflow.service.IActProcessInstanceService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
*
*
* @author may
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/processInstance")
public class ActProcessInstanceController extends BaseController {
private final IActProcessInstanceService actProcessInstanceService;
/**
*
*
* @param bo
*/
@GetMapping("/getPageByRunning")
public TableDataInfo<ProcessInstanceVo> getPageByRunning(ProcessInstanceBo bo, PageQuery pageQuery) {
return actProcessInstanceService.getPageByRunning(bo, pageQuery);
}
/**
*
*
* @param bo
*/
@GetMapping("/getPageByFinish")
public TableDataInfo<ProcessInstanceVo> getPageByFinish(ProcessInstanceBo bo, PageQuery pageQuery) {
return actProcessInstanceService.getPageByFinish(bo, pageQuery);
}
/**
* id
*
* @param businessKey id
*/
@GetMapping("/getHistoryImage/{businessKey}")
public R<String> getHistoryImage(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) {
return R.ok("操作成功", actProcessInstanceService.getHistoryImage(businessKey));
}
/**
* id
*
* @param businessKey id
*/
@GetMapping("/getHistoryList/{businessKey}")
public R<Map<String, Object>> getHistoryList(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) {
return R.ok("操作成功", actProcessInstanceService.getHistoryList(businessKey));
}
/**
*
*
* @param businessKey id
*/
@GetMapping("/getHistoryRecord/{businessKey}")
public R<List<ActHistoryInfoVo>> getHistoryRecord(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) {
return R.ok(actProcessInstanceService.getHistoryRecord(businessKey));
}
/**
* ()
*
* @param processInvalidBo
*/
@Log(title = "流程实例管理", businessType = BusinessType.DELETE)
@RepeatSubmit()
@PostMapping("/deleteRunInstance")
public R<Void> deleteRunInstance(@Validated(AddGroup.class) @RequestBody ProcessInvalidBo processInvalidBo) {
return toAjax(actProcessInstanceService.deleteRunInstance(processInvalidBo));
}
/**
*
*
* @param businessKeys id
*/
@Log(title = "流程实例管理", businessType = BusinessType.DELETE)
@RepeatSubmit()
@DeleteMapping("/deleteRunAndHisInstance/{businessKeys}")
public R<Void> deleteRunAndHisInstance(@NotNull(message = "业务id不能为空") @PathVariable String[] businessKeys) {
return toAjax(actProcessInstanceService.deleteRunAndHisInstance(Arrays.asList(businessKeys)));
}
/**
*
*
* @param businessKeys id
*/
@Log(title = "流程实例管理", businessType = BusinessType.DELETE)
@RepeatSubmit()
@DeleteMapping("/deleteFinishAndHisInstance/{businessKeys}")
public R<Void> deleteFinishAndHisInstance(@NotNull(message = "业务id不能为空") @PathVariable String[] businessKeys) {
return toAjax(actProcessInstanceService.deleteFinishAndHisInstance(Arrays.asList(businessKeys)));
}
/**
*
*
* @param businessKey id
*/
@Log(title = "流程实例管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/cancelProcessApply/{businessKey}")
public R<Void> cancelProcessApply(@NotBlank(message = "业务id不能为空") @PathVariable String businessKey) {
return toAjax(actProcessInstanceService.cancelProcessApply(businessKey));
}
/**
*
*
* @param bo
*/
@GetMapping("/getPageByCurrent")
public TableDataInfo<ProcessInstanceVo> getPageByCurrent(ProcessInstanceBo bo, PageQuery pageQuery) {
return actProcessInstanceService.getPageByCurrent(bo, pageQuery);
}
/**
* ()
*
* @param taskUrgingBo
*/
@Log(title = "流程实例管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/taskUrging")
public R<Void> taskUrging(@RequestBody TaskUrgingBo taskUrgingBo) {
return toAjax(actProcessInstanceService.taskUrging(taskUrgingBo));
}
}

@ -0,0 +1,295 @@
package org.dromara.workflow.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import jakarta.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.web.core.BaseController;
import org.dromara.workflow.domain.WfTaskBackNode;
import org.dromara.workflow.domain.bo.*;
import org.dromara.workflow.domain.vo.TaskVo;
import org.dromara.workflow.domain.vo.VariableVo;
import org.dromara.workflow.service.IActTaskService;
import org.dromara.workflow.service.IWfTaskBackNodeService;
import org.dromara.workflow.utils.QueryUtils;
import org.flowable.engine.TaskService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
*
*
* @author may
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/task")
public class ActTaskController extends BaseController {
private final IActTaskService actTaskService;
private final TaskService taskService;
private final IWfTaskBackNodeService wfTaskBackNodeService;
/**
*
*
* @param startProcessBo
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/startWorkFlow")
public R<Map<String, Object>> startWorkFlow(@Validated(AddGroup.class) @RequestBody StartProcessBo startProcessBo) {
Map<String, Object> map = actTaskService.startWorkFlow(startProcessBo);
return R.ok("提交成功", map);
}
/**
*
*
* @param completeTaskBo
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/completeTask")
public R<Void> completeTask(@Validated(AddGroup.class) @RequestBody CompleteTaskBo completeTaskBo) {
return toAjax(actTaskService.completeTask(completeTaskBo));
}
/**
*
*
* @param taskBo
*/
@GetMapping("/getPageByTaskWait")
public TableDataInfo<TaskVo> getPageByTaskWait(TaskBo taskBo, PageQuery pageQuery) {
return actTaskService.getPageByTaskWait(taskBo, pageQuery);
}
/**
*
*
* @param taskBo
*/
@GetMapping("/getPageByAllTaskWait")
public TableDataInfo<TaskVo> getPageByAllTaskWait(TaskBo taskBo, PageQuery pageQuery) {
return actTaskService.getPageByAllTaskWait(taskBo, pageQuery);
}
/**
*
*
* @param taskBo
*/
@GetMapping("/getPageByTaskFinish")
public TableDataInfo<TaskVo> getPageByTaskFinish(TaskBo taskBo, PageQuery pageQuery) {
return actTaskService.getPageByTaskFinish(taskBo, pageQuery);
}
/**
*
*
* @param taskBo
*/
@GetMapping("/getPageByTaskCopy")
public TableDataInfo<TaskVo> getPageByTaskCopy(TaskBo taskBo, PageQuery pageQuery) {
return actTaskService.getPageByTaskCopy(taskBo, pageQuery);
}
/**
*
*
* @param taskBo
*/
@GetMapping("/getPageByAllTaskFinish")
public TableDataInfo<TaskVo> getPageByAllTaskFinish(TaskBo taskBo, PageQuery pageQuery) {
return actTaskService.getPageByAllTaskFinish(taskBo, pageQuery);
}
/**
*
*
* @param taskId id
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/claim/{taskId}")
public R<Void> claimTask(@NotBlank(message = "任务id不能为空") @PathVariable String taskId) {
try {
taskService.claim(taskId, Convert.toStr(LoginHelper.getUserId()));
return R.ok();
} catch (Exception e) {
e.printStackTrace();
return R.fail("签收任务失败:" + e.getMessage());
}
}
/**
*
*
* @param taskId id
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/returnTask/{taskId}")
public R<Void> returnTask(@NotBlank(message = "任务id不能为空") @PathVariable String taskId) {
try {
taskService.setAssignee(taskId, null);
return R.ok();
} catch (Exception e) {
e.printStackTrace();
return R.fail("归还任务失败:" + e.getMessage());
}
}
/**
*
*
* @param delegateBo
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/delegateTask")
public R<Void> delegateTask(@Validated({AddGroup.class}) @RequestBody DelegateBo delegateBo) {
return toAjax(actTaskService.delegateTask(delegateBo));
}
/**
*
*
* @param terminationBo
*/
@Log(title = "任务管理", businessType = BusinessType.DELETE)
@RepeatSubmit()
@PostMapping("/terminationTask")
public R<Void> terminationTask(@RequestBody TerminationBo terminationBo) {
return toAjax(actTaskService.terminationTask(terminationBo));
}
/**
*
*
* @param transmitBo
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/transferTask")
public R<Void> transferTask(@Validated({AddGroup.class}) @RequestBody TransmitBo transmitBo) {
return toAjax(actTaskService.transferTask(transmitBo));
}
/**
*
*
* @param addMultiBo
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/addMultiInstanceExecution")
public R<Void> addMultiInstanceExecution(@Validated({AddGroup.class}) @RequestBody AddMultiBo addMultiBo) {
return toAjax(actTaskService.addMultiInstanceExecution(addMultiBo));
}
/**
*
*
* @param deleteMultiBo
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/deleteMultiInstanceExecution")
public R<Void> deleteMultiInstanceExecution(@Validated({AddGroup.class}) @RequestBody DeleteMultiBo deleteMultiBo) {
return toAjax(actTaskService.deleteMultiInstanceExecution(deleteMultiBo));
}
/**
*
*
* @param backProcessBo
*/
@Log(title = "任务管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/backProcess")
public R<String> backProcess(@Validated({AddGroup.class}) @RequestBody BackProcessBo backProcessBo) {
return R.ok(actTaskService.backProcess(backProcessBo));
}
/**
*
*
* @param taskId id
*/
@GetMapping("/getTaskById/{taskId}")
public R<TaskVo> getTaskById(@PathVariable String taskId) {
return R.ok(QueryUtils.getTask(taskId));
}
/**
*
*
* @param taskIds id
* @param userId id
*/
@Log(title = "任务管理", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping("/updateAssignee/{taskIds}/{userId}")
public R<Void> updateAssignee(@PathVariable String[] taskIds, @PathVariable String userId) {
return toAjax(actTaskService.updateAssignee(taskIds, userId));
}
/**
*
*
* @param taskId id
*/
@GetMapping("/getInstanceVariable/{taskId}")
public R<List<VariableVo>> getProcessInstVariable(@PathVariable String taskId) {
return R.ok(actTaskService.getInstanceVariable(taskId));
}
/**
*
*
* @param processInstanceId id
*/
@GetMapping("/getTaskNodeList/{processInstanceId}")
public R<List<WfTaskBackNode>> getNodeList(@PathVariable String processInstanceId) {
return R.ok(CollUtil.reverse(wfTaskBackNodeService.getListByInstanceId(processInstanceId)));
}
/**
*
*
* @param taskId id
*/
@GetMapping("/getTaskUserIdsByAddMultiInstance/{taskId}")
public R<String> getTaskUserIdsByAddMultiInstance(@PathVariable String taskId) {
return R.ok(actTaskService.getTaskUserIdsByAddMultiInstance(taskId));
}
/**
*
*
* @param taskId id
*/
@GetMapping("/getListByDeleteMultiInstance/{taskId}")
public R<List<TaskVo>> getListByDeleteMultiInstance(@PathVariable String taskId) {
return R.ok(actTaskService.getListByDeleteMultiInstance(taskId));
}
}

@ -0,0 +1,106 @@
package org.dromara.workflow.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.web.core.BaseController;
import org.dromara.workflow.domain.bo.WfCategoryBo;
import org.dromara.workflow.domain.vo.WfCategoryVo;
import org.dromara.workflow.service.IWfCategoryService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
*
*
* @author may
* @date 2023-06-28
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/category")
public class WfCategoryController extends BaseController {
private final IWfCategoryService wfCategoryService;
/**
*
*/
@SaCheckPermission("workflow:category:list")
@GetMapping("/list")
public R<List<WfCategoryVo>> list(WfCategoryBo bo) {
List<WfCategoryVo> list = wfCategoryService.queryList(bo);
return R.ok(list);
}
/**
*
*/
@SaCheckPermission("workflow:category:export")
@Log(title = "流程分类", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(WfCategoryBo bo, HttpServletResponse response) {
List<WfCategoryVo> list = wfCategoryService.queryList(bo);
ExcelUtil.exportExcel(list, "流程分类", WfCategoryVo.class, response);
}
/**
*
*
* @param id
*/
@SaCheckPermission("workflow:category:query")
@GetMapping("/{id}")
public R<WfCategoryVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(wfCategoryService.queryById(id));
}
/**
*
*/
@SaCheckPermission("workflow:category:add")
@Log(title = "流程分类", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody WfCategoryBo bo) {
return toAjax(wfCategoryService.insertByBo(bo));
}
/**
*
*/
@SaCheckPermission("workflow:category:edit")
@Log(title = "流程分类", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody WfCategoryBo bo) {
return toAjax(wfCategoryService.updateByBo(bo));
}
/**
*
*
* @param ids
*/
@SaCheckPermission("workflow:category:remove")
@Log(title = "流程分类", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(wfCategoryService.deleteWithValidByIds(List.of(ids), true));
}
}

@ -0,0 +1,79 @@
package org.dromara.workflow.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.validation.constraints.*;
import org.dromara.workflow.domain.bo.WfDefinitionConfigBo;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.workflow.domain.vo.WfDefinitionConfigVo;
import org.dromara.workflow.service.IWfDefinitionConfigService;
/**
*
*
* @author may
* @date 2024-03-18
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/definitionConfig")
public class WfDefinitionConfigController extends BaseController {
private final IWfDefinitionConfigService wfDefinitionConfigService;
/**
*
*
* @param definitionId
*/
@GetMapping("/getByDefId/{definitionId}")
public R<WfDefinitionConfigVo> getByDefId(@NotBlank(message = "流程定义ID不能为空")
@PathVariable String definitionId) {
return R.ok(wfDefinitionConfigService.getByDefId(definitionId));
}
/**
*
*/
@Log(title = "流程定义配置", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/saveOrUpdate")
public R<Void> saveOrUpdate(@Validated(AddGroup.class) @RequestBody WfDefinitionConfigBo bo) {
return toAjax(wfDefinitionConfigService.saveOrUpdate(bo));
}
/**
*
*
* @param ids
*/
@Log(title = "流程定义配置", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(wfDefinitionConfigService.deleteByIds(List.of(ids)));
}
/**
*
*
* @param tableName
* @param definitionId id
*/
@GetMapping("/getByTableNameNotDefId/{tableName}/{definitionId}")
public R<List<WfDefinitionConfigVo>> getByTableNameNotDefId(@NotBlank(message = "表名不能为空") @PathVariable String tableName,
@NotBlank(message = "流程定义ID不能为空") @PathVariable String definitionId) {
return R.ok(wfDefinitionConfigService.getByTableNameNotDefId(tableName, definitionId));
}
}

@ -0,0 +1,114 @@
package org.dromara.workflow.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.workflow.domain.vo.WfFormManageVo;
import org.dromara.workflow.domain.bo.WfFormManageBo;
import org.dromara.workflow.service.IWfFormManageService;
import org.dromara.common.mybatis.core.page.TableDataInfo;
/**
*
*
* @author may
* @date 2024-03-29
*/
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/workflow/formManage")
public class WfFormManageController extends BaseController {
private final IWfFormManageService wfFormManageService;
/**
*
*/
@SaCheckPermission("workflow:formManage:list")
@GetMapping("/list")
public TableDataInfo<WfFormManageVo> list(WfFormManageBo bo, PageQuery pageQuery) {
return wfFormManageService.queryPageList(bo, pageQuery);
}
/**
*
*/
@SaCheckPermission("workflow:formManage:list")
@GetMapping("/list/selectList")
public R<List<WfFormManageVo>> selectList() {
return R.ok(wfFormManageService.selectList());
}
/**
*
*/
@SaCheckPermission("workflow:formManage:export")
@Log(title = "表单管理", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(WfFormManageBo bo, HttpServletResponse response) {
List<WfFormManageVo> list = wfFormManageService.queryList(bo);
ExcelUtil.exportExcel(list, "表单管理", WfFormManageVo.class, response);
}
/**
*
*
* @param id
*/
@SaCheckPermission("workflow:formManage:query")
@GetMapping("/{id}")
public R<WfFormManageVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(wfFormManageService.queryById(id));
}
/**
*
*/
@SaCheckPermission("workflow:formManage:add")
@Log(title = "表单管理", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody WfFormManageBo bo) {
return toAjax(wfFormManageService.insertByBo(bo));
}
/**
*
*/
@SaCheckPermission("workflow:formManage:edit")
@Log(title = "表单管理", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody WfFormManageBo bo) {
return toAjax(wfFormManageService.updateByBo(bo));
}
/**
*
*
* @param ids
*/
@SaCheckPermission("workflow:formManage:remove")
@Log(title = "表单管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(wfFormManageService.deleteByIds(List.of(ids)));
}
}

@ -0,0 +1,152 @@
package org.dromara.workflow.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* act_hi_procinst
*
* @author may
* @date 2023-07-22
*/
@Data
@TableName("act_hi_procinst")
public class ActHiProcinst implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId(value = "ID_")
private String id;
/**
*
*/
@TableField(value = "REV_")
private Long rev;
/**
*
*/
@TableField(value = "PROC_INST_ID_")
private String procInstId;
/**
*
*/
@TableField(value = "BUSINESS_KEY_")
private String businessKey;
/**
*
*/
@TableField(value = "PROC_DEF_ID_")
private String procDefId;
/**
*
*/
@TableField(value = "START_TIME_")
private Date startTime;
/**
*
*/
@TableField(value = "END_TIME_")
private Date endTime;
/**
*
*/
@TableField(value = "DURATION_")
private Long duration;
/**
*
*/
@TableField(value = "START_USER_ID_")
private String startUserId;
/**
*
*/
@TableField(value = "START_ACT_ID_")
private String startActId;
/**
*
*/
@TableField(value = "END_ACT_ID_")
private String endActId;
/**
*
*/
@TableField(value = "SUPER_PROCESS_INSTANCE_ID_")
private String superProcessInstanceId;
/**
*
*/
@TableField(value = "DELETE_REASON_")
private String deleteReason;
/**
*
*/
@TableField(value = "TENANT_ID_")
private String tenantId;
/**
*
*/
@TableField(value = "NAME_")
private String name;
/**
*
*/
@TableField(value = "CALLBACK_ID_")
private String callbackId;
/**
*
*/
@TableField(value = "CALLBACK_TYPE_")
private String callbackType;
/**
*
*/
@TableField(value = "REFERENCE_ID_")
private String referenceId;
/**
*
*/
@TableField(value = "REFERENCE_TYPE_")
private String referenceType;
/**
*
*/
@TableField(value = "PROPAGATED_STAGE_INST_ID_")
private String propagatedStageInstId;
/**
*
*/
@TableField(value = "BUSINESS_STATUS_")
private String businessStatus;
}

@ -0,0 +1,193 @@
package org.dromara.workflow.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
import java.io.Serial;
/**
* act_hi_taskinst
*
* @author may
* @date 2024-03-02
*/
@Data
@TableName("act_hi_taskinst")
public class ActHiTaskinst implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId(value = "ID_")
private String id;
/**
*
*/
@TableField(value = "REV_")
private Long rev;
/**
* id
*/
@TableField(value = "PROC_DEF_ID_")
private String procDefId;
/**
*
*/
@TableField(value = "TASK_DEF_ID_")
private String taskDefId;
/**
* id
*/
@TableField(value = "TASK_DEF_KEY_")
private String taskDefKey;
/**
* id
*/
@TableField(value = "PROC_INST_ID_")
private String procInstId;
/**
* id
*/
@TableField(value = "EXECUTION_ID")
private String executionId;
/**
*
*/
@TableField(value = "SCOPE_ID_")
private String scopeId;
/**
*
*/
@TableField(value = "SUB_SCOPE_ID_")
private String subScopeId;
/**
*
*/
@TableField(value = "SCOPE_TYPE_")
private String scopeType;
/**
*
*/
@TableField(value = "SCOPE_DEFINITION_ID_")
private String scopeDefinitionId;
/**
*
*/
@TableField(value = "PROPAGATED_STAGE_INST_ID_")
private String propagatedStageInstId;
/**
*
*/
@TableField(value = "NAME_")
private String name;
/**
* id
*/
@TableField(value = "PARENT_TASK_ID_")
private String parentTaskId;
/**
*
*/
@TableField(value = "DESCRIPTION_")
private String description;
/**
*
*/
@TableField(value = "OWNER_")
private String owner;
/**
*
*/
@TableField(value = "ASSIGNEE_")
private String assignee;
/**
*
*/
@TableField(value = "START_TIME_")
private Date startTime;
/**
*
*/
@TableField(value = "CLAIM_TIME_")
private Date claimTime;
/**
*
*/
@TableField(value = "END_TIME_")
private Date endTime;
/**
*
*/
@TableField(value = "DURATION_")
private Long duration;
/**
*
*/
@TableField(value = "DELETE_REASON_")
private String deleteReason;
/**
*
*/
@TableField(value = "PRIORITY_")
private Long priority;
/**
*
*/
@TableField(value = "DUE_DATE_")
private Date dueDate;
/**
*
*/
@TableField(value = "FORM_KEY_")
private String formKey;
/**
*
*/
@TableField(value = "CATEGORY_")
private String category;
/**
*
*/
@TableField(value = "LAST_UPDATED_TIME_")
private Date lastUpdatedTime;
/**
* id
*/
@TableField(value = "TENANT_ID_")
private String tenantId;
}

@ -0,0 +1,52 @@
package org.dromara.workflow.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.tenant.core.TenantEntity;
import java.io.Serial;
/**
* wf_category
*
* @author may
* @date 2023-06-27
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("wf_category")
public class WfCategory extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId(value = "id")
private Long id;
/**
*
*/
private String categoryName;
/**
*
*/
private String categoryCode;
/**
* id
*/
private Long parentId;
/**
*
*/
private Long sortNum;
}

@ -0,0 +1,56 @@
package org.dromara.workflow.domain;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* wf_definition_config
*
* @author may
* @date 2024-03-18
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("wf_definition_config")
public class WfDefinitionConfig extends BaseEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId(value = "id")
private Long id;
/**
*
*/
private String tableName;
/**
* ID
*/
private String definitionId;
/**
* KEY
*/
private String processKey;
/**
*
*/
private Integer version;
/**
*
*/
private String remark;
}

@ -0,0 +1,51 @@
package org.dromara.workflow.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* wf_form_manage
*
* @author may
* @date 2024-03-29
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("wf_form_manage")
public class WfFormManage extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId(value = "id")
private Long id;
/**
*
*/
private String formName;
/**
*
*/
private String formType;
/**
* /ID
*/
private String router;
/**
*
*/
private String remark;
}

@ -0,0 +1,61 @@
package org.dromara.workflow.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
/**
* wf_node_config
*
* @author may
* @date 2024-03-30
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("wf_node_config")
public class WfNodeConfig extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId(value = "id")
private Long id;
/**
* id
*/
private Long formId;
/**
*
*/
private String formType;
/**
*
*/
private String nodeName;
/**
* id
*/
private String nodeId;
/**
* id
*/
private String definitionId;
/**
* 0 1
*/
private String applyUserTask;
}

@ -0,0 +1,61 @@
package org.dromara.workflow.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.tenant.core.TenantEntity;
import java.io.Serial;
/**
* wf_task_back_node
*
* @author may
* @date 2024-03-13
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("wf_task_back_node")
public class WfTaskBackNode extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId(value = "id")
private Long id;
/**
* id
*/
private String instanceId;
/**
* id
*/
private String nodeId;
/**
*
*/
private String nodeName;
/**
*
*/
private Integer orderNo;
/**
*
*/
private String taskType;
/**
*
*/
private String assignee;
}

@ -0,0 +1,40 @@
package org.dromara.workflow.domain.bo;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
*
*
* @author may
*/
@Data
public class AddMultiBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@NotBlank(message = "任务ID不能为空", groups = AddGroup.class)
private String taskId;
/**
* id
*/
@NotEmpty(message = "加签人员不能为空", groups = AddGroup.class)
private List<Long> assignees;
/**
*
*/
@NotEmpty(message = "加签人员不能为空", groups = AddGroup.class)
private List<String> assigneeNames;
}

@ -0,0 +1,44 @@
package org.dromara.workflow.domain.bo;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
*
*
* @author may
*/
@Data
public class BackProcessBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@NotBlank(message = "任务ID不能为空", groups = AddGroup.class)
private String taskId;
/**
*
*/
private List<String> messageType;
/**
* id(使)
*/
@NotBlank(message = "驳回的节点不能为空", groups = AddGroup.class)
private String targetActivityId;
/**
*
*/
private String message;
}

@ -0,0 +1,65 @@
package org.dromara.workflow.domain.bo;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.workflow.domain.vo.WfCopy;
import java.io.Serial;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
*
*
* @author may
*/
@Data
public class CompleteTaskBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@NotBlank(message = "任务id不能为空", groups = {AddGroup.class})
private String taskId;
/**
* id
*/
private String fileId;
/**
*
*/
private List<WfCopy> wfCopyList;
/**
*
*/
private List<String> messageType;
/**
*
*/
private String message;
/**
*
*/
private Map<String, Object> variables;
public Map<String, Object> getVariables() {
if (variables == null) {
return new HashMap<>(16);
}
variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
return variables;
}
}

@ -0,0 +1,38 @@
package org.dromara.workflow.domain.bo;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
import java.io.Serial;
import java.io.Serializable;
/**
*
*
* @author may
*/
@Data
public class DelegateBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@NotBlank(message = "委派人id不能为空", groups = {AddGroup.class})
private String userId;
/**
*
*/
@NotBlank(message = "委派人名称不能为空", groups = {AddGroup.class})
private String nickName;
/**
* id
*/
@NotBlank(message = "任务id不能为空", groups = {AddGroup.class})
private String taskId;
}

@ -0,0 +1,52 @@
package org.dromara.workflow.domain.bo;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
*
*
* @author may
*/
@Data
public class DeleteMultiBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
@NotBlank(message = "任务ID不能为空", groups = AddGroup.class)
private String taskId;
/**
*
*/
@NotEmpty(message = "减签人员不能为空", groups = AddGroup.class)
private List<String> taskIds;
/**
* id
*/
@NotEmpty(message = "执行id不能为空", groups = AddGroup.class)
private List<String> executionIds;
/**
* id
*/
@NotEmpty(message = "减签人员id不能为空", groups = AddGroup.class)
private List<Long> assigneeIds;
/**
*
*/
@NotEmpty(message = "减签人员不能为空", groups = AddGroup.class)
private List<String> assigneeNames;
}

@ -0,0 +1,66 @@
package org.dromara.workflow.domain.bo;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.workflow.common.constant.FlowConstant;
import java.io.Serial;
import java.io.Serializable;
/**
*
*
* @author may
*/
@Data
public class ModelBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@NotBlank(message = "模型ID不能为空", groups = {EditGroup.class})
private String id;
/**
*
*/
@NotBlank(message = "模型名称不能为空", groups = {AddGroup.class})
private String name;
/**
* key
*/
@NotBlank(message = "模型标识key不能为空", groups = {AddGroup.class})
@Pattern(regexp = FlowConstant.MODEL_KEY_PATTERN, message = "模型标识key只能字符或者下划线开头", groups = {AddGroup.class})
private String key;
/**
*
*/
@NotBlank(message = "模型分类不能为空", groups = {AddGroup.class})
private String categoryCode;
/**
* XML
*/
@NotBlank(message = "模型XML不能为空", groups = {AddGroup.class})
private String xml;
/**
* SVG
*/
@NotBlank(message = "模型SVG不能为空", groups = {EditGroup.class})
private String svg;
/**
*
*/
private String description;
}

@ -0,0 +1,34 @@
package org.dromara.workflow.domain.bo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
*
*
* @author may
*/
@Data
public class ProcessDefinitionBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* key
*/
private String key;
/**
*
*/
private String name;
/**
*
*/
private String categoryCode;
}

@ -0,0 +1,49 @@
package org.dromara.workflow.domain.bo;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
import java.io.Serial;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
*
*
* @author may
*/
@Data
public class StartProcessBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@NotBlank(message = "业务ID不能为空", groups = {AddGroup.class})
private String businessKey;
/**
*
*/
@NotBlank(message = "表名不能为空", groups = {AddGroup.class})
private String tableName;
/**
* {'entity': {}}
*/
private Map<String, Object> variables;
public Map<String, Object> getVariables() {
if (variables == null) {
return new HashMap<>(16);
}
variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
return variables;
}
}

@ -0,0 +1,39 @@
package org.dromara.workflow.domain.bo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
*
*
* @author may
*/
@Data
public class SysUserMultiBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
private String userName;
/**
*
*/
private String nickName;
/**
* id
*/
private String deptId;
/**
* id
*/
private String taskId;
}

@ -0,0 +1,33 @@
package org.dromara.workflow.domain.bo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
*
*
* @author may
*/
@Data
public class TaskBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
private String name;
/**
*
*/
private String processDefinitionName;
/**
* key
*/
private String processDefinitionKey;
}

@ -0,0 +1,31 @@
package org.dromara.workflow.domain.bo;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
import java.io.Serial;
import java.io.Serializable;
/**
*
*
* @author may
*/
@Data
public class TerminationBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@NotBlank(message = "任务id为空", groups = AddGroup.class)
private String taskId;
/**
*
*/
private String comment;
}

@ -0,0 +1,37 @@
package org.dromara.workflow.domain.bo;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
import java.io.Serial;
import java.io.Serializable;
/**
*
*
* @author may
*/
@Data
public class TransmitBo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
@NotBlank(message = "任务id为空", groups = AddGroup.class)
private String taskId;
/**
* id
*/
@NotBlank(message = "转办人不能为空", groups = AddGroup.class)
private String userId;
/**
*
*/
private String comment;
}

@ -0,0 +1,54 @@
package org.dromara.workflow.domain.bo;
import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.workflow.domain.WfCategory;
/**
* wf_category
*
* @author may
* @date 2023-06-27
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = WfCategory.class, reverseConvertGenerate = false)
public class WfCategoryBo extends BaseEntity {
/**
*
*/
@NotNull(message = "主键不能为空", groups = {EditGroup.class})
private Long id;
/**
*
*/
@NotBlank(message = "分类名称不能为空", groups = {AddGroup.class, EditGroup.class})
private String categoryName;
/**
*
*/
@NotBlank(message = "分类编码不能为空", groups = {AddGroup.class, EditGroup.class})
private String categoryCode;
/**
* id
*/
@NotNull(message = "父级id不能为空", groups = {AddGroup.class, EditGroup.class})
private Long parentId;
/**
*
*/
private Long sortNum;
}

@ -0,0 +1,59 @@
package org.dromara.workflow.domain.bo;
import org.dromara.workflow.domain.WfDefinitionConfig;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
/**
* wf_form_definition
*
* @author may
* @date 2024-03-18
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = WfDefinitionConfig.class, reverseConvertGenerate = false)
public class WfDefinitionConfigBo extends BaseEntity {
/**
*
*/
@NotNull(message = "主键不能为空", groups = {EditGroup.class})
private Long id;
/**
*
*/
@NotBlank(message = "表名不能为空", groups = {AddGroup.class})
private String tableName;
/**
* ID
*/
@NotBlank(message = "流程定义ID不能为空", groups = {AddGroup.class})
private String definitionId;
/**
* KEY
*/
@NotBlank(message = "流程KEY不能为空", groups = {AddGroup.class})
private String processKey;
/**
*
*/
@NotNull(message = "流程版本不能为空", groups = {AddGroup.class})
private Integer version;
/**
*
*/
private String remark;
}

@ -0,0 +1,53 @@
package org.dromara.workflow.domain.bo;
import org.dromara.workflow.domain.WfFormManage;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
/**
* wf_form_manage
*
* @author may
* @date 2024-03-29
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = WfFormManage.class, reverseConvertGenerate = false)
public class WfFormManageBo extends BaseEntity {
/**
*
*/
@NotNull(message = "主键不能为空", groups = { EditGroup.class })
private Long id;
/**
*
*/
@NotBlank(message = "表单名称不能为空", groups = { AddGroup.class, EditGroup.class })
private String formName;
/**
*
*/
@NotBlank(message = "表单类型不能为空", groups = { AddGroup.class, EditGroup.class })
private String formType;
/**
* /ID
*/
@NotBlank(message = "路由地址/表单ID不能为空", groups = { AddGroup.class, EditGroup.class })
private String router;
/**
*
*/
private String remark;
}

@ -0,0 +1,63 @@
package org.dromara.workflow.domain.bo;
import org.dromara.workflow.domain.WfNodeConfig;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
/**
* wf_node_config
*
* @author may
* @date 2024-03-30
*/
@Data
@EqualsAndHashCode(callSuper = true)
@AutoMapper(target = WfNodeConfig.class, reverseConvertGenerate = false)
public class WfNodeConfigBo extends BaseEntity {
/**
*
*/
@NotNull(message = "主键不能为空", groups = {EditGroup.class})
private Long id;
/**
* id
*/
private Long formId;
/**
*
*/
private String formType;
/**
*
*/
@NotBlank(message = "节点名称不能为空", groups = {AddGroup.class, EditGroup.class})
private String nodeName;
/**
* id
*/
@NotBlank(message = "节点id不能为空", groups = {AddGroup.class, EditGroup.class})
private String nodeId;
/**
* id
*/
@NotBlank(message = "流程定义id不能为空", groups = {AddGroup.class, EditGroup.class})
private String definitionId;
/**
* 0 1
*/
@NotBlank(message = "是否为申请人节点不能为空", groups = {AddGroup.class, EditGroup.class})
private String applyUserTask;
}

@ -0,0 +1,89 @@
package org.dromara.workflow.domain.vo;
import lombok.Data;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import org.flowable.engine.task.Attachment;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
*
*
* @author may
*/
@Data
public class ActHistoryInfoVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
private String id;
/**
* id
*/
private String taskDefinitionKey;
/**
*
*/
private String name;
/**
* id
*/
private String processInstanceId;
/**
*
*/
private Date startTime;
/**
*
*/
private Date endTime;
/**
*
*/
private String runDuration;
/**
*
*/
private String status;
/**
*
*/
private String statusName;
/**
* id
*/
private String assignee;
/**
*
*/
@Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "assignee")
private String nickName;
/**
* id
*/
private String owner;
/**
* id
*/
private String commentId;
/**
*
*/
private String comment;
/**
*
*/
private List<Attachment> attachmentList;
}

@ -0,0 +1,47 @@
package org.dromara.workflow.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
*
*
* @author may
*/
@Data
public class GraphicInfoVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* x
*/
private double x;
/**
* y
*/
private double y;
/**
*
*/
private double height;
/**
*
*/
private double width;
/**
* id
*/
private String nodeId;
/**
*
*/
private String nodeName;
}

@ -0,0 +1,48 @@
package org.dromara.workflow.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
*
*
* @author may
*/
@Data
public class ModelVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
private String id;
/**
*
*/
private String name;
/**
* key
*/
private String key;
/**
*
*/
private String categoryCode;
/**
* XML
*/
private String xml;
/**
*
*/
private String description;
}

@ -0,0 +1,33 @@
package org.dromara.workflow.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
*
*
* @author may
*/
@Data
public class MultiInstanceVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
private Object type;
/**
* KEY
*/
private String assignee;
/**
* KEY
*/
private String assigneeList;
}

@ -0,0 +1,43 @@
package org.dromara.workflow.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
*
*
* @author may
*/
@Data
public class ParticipantVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* idid
*/
private List<Long> groupIds;
/**
* idid idcandidate
*/
private List<Long> candidate;
/**
* idcandidateName
*/
private List<String> candidateName;
/**
*
*
* true
* false
*/
private Boolean claim;
}

@ -0,0 +1,70 @@
package org.dromara.workflow.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
*
*
* @author may
*/
@Data
public class ProcessDefinitionVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
private String id;
/**
*
*/
private String name;
/**
* key
*/
private String key;
/**
*
*/
private int version;
/**
* 1 2
*/
private int suspensionState;
/**
* xml
*/
private String resourceName;
/**
*
*/
private String diagramResourceName;
/**
* id
*/
private String deploymentId;
/**
*
*/
private Date deploymentTime;
/**
*
*/
private WfDefinitionConfigVo wfDefinitionConfigVo;
}

@ -0,0 +1,100 @@
package org.dromara.workflow.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
*
*
* @author may
*/
@Data
public class ProcessInstanceVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
private String id;
/**
* id
*/
private String processDefinitionId;
/**
*
*/
private String processDefinitionName;
/**
* key
*/
private String processDefinitionKey;
/**
*
*/
private Integer processDefinitionVersion;
/**
* id
*/
private String deploymentId;
/**
* id
*/
private String businessKey;
/**
*
*/
private Boolean isSuspended;
/**
* id
*/
private String tenantId;
/**
*
*/
private Date startTime;
/**
*
*/
private Date endTime;
/**
* id
*/
private String startUserId;
/**
*
*/
private String businessStatus;
/**
*
*/
private String businessStatusName;
/**
*
*/
private List<TaskVo> taskVoList;
/**
*
*/
private WfNodeConfigVo wfNodeConfigVo;
}

@ -0,0 +1,173 @@
package org.dromara.workflow.domain.vo;
import lombok.Data;
import org.dromara.common.translation.annotation.Translation;
import org.dromara.common.translation.constant.TransConstant;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
*
*
* @author may
*/
@Data
public class TaskVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
private String id;
/**
*
*/
private String name;
/**
*
*/
private String description;
/**
*
*/
private Integer priority;
/**
* id
*/
private String owner;
/**
* id
*/
private Long assignee;
/**
*
*/
@Translation(type = TransConstant.USER_ID_TO_NICKNAME, mapper = "assignee")
private String assigneeName;
/**
* id
*/
private String processInstanceId;
/**
* id
*/
private String executionId;
/**
*
*/
private String taskDefinitionId;
/**
* id
*/
private String processDefinitionId;
/**
*
*/
private Date createTime;
/**
* -
*/
private Date startTime;
/**
*
*/
private Date endTime;
/**
* id
*/
private String taskDefinitionKey;
/**
*
*/
private Date dueDate;
/**
*
*/
private String category;
/**
* id
*/
private String parentTaskId;
/**
* id
*/
private String tenantId;
/**
*
*/
private Date claimTime;
/**
*
*/
private String businessStatus;
/**
*
*/
private String businessStatusName;
/**
*
*/
private String processDefinitionName;
/**
* key
*/
private String processDefinitionKey;
/**
*
*/
private Integer processDefinitionVersion;
/**
*
*/
private ParticipantVo participantVo;
/**
*
*/
private Boolean multiInstance;
/**
* id
*/
private String businessKey;
/**
*
*/
private WfDefinitionConfigVo wfDefinitionConfigVo;
/**
*
*/
private WfNodeConfigVo wfNodeConfigVo;
}

@ -0,0 +1,28 @@
package org.dromara.workflow.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
*
*
* @author may
*/
@Data
public class VariableVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* key
*/
private String key;
/**
*
*/
private String value;
}

@ -0,0 +1,58 @@
package org.dromara.workflow.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.workflow.domain.WfCategory;
import java.io.Serial;
import java.io.Serializable;
/**
* wf_category
*
* @author may
* @date 2023-06-27
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = WfCategory.class)
public class WfCategoryVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
@ExcelProperty(value = "主键")
private Long id;
/**
*
*/
@ExcelProperty(value = "分类名称")
private String categoryName;
/**
*
*/
@ExcelProperty(value = "分类编码")
private String categoryCode;
/**
* id
*/
@ExcelProperty(value = "父级id")
private Long parentId;
/**
*
*/
@ExcelProperty(value = "排序")
private Long sortNum;
}

@ -0,0 +1,29 @@
package org.dromara.workflow.domain.vo;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
*
*
* @author may
*/
@Data
public class WfCopy implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* id
*/
private Long userId;
/**
*
*/
private String userName;
}

@ -0,0 +1,70 @@
package org.dromara.workflow.domain.vo;
import org.dromara.workflow.domain.WfDefinitionConfig;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* wf_definition_config
*
* @author may
* @date 2024-03-18
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = WfDefinitionConfig.class)
public class WfDefinitionConfigVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
@ExcelProperty(value = "主键")
private Long id;
/**
*
*/
@ExcelProperty(value = "表名")
private String tableName;
/**
* ID
*/
@ExcelProperty(value = "流程定义ID")
private String definitionId;
/**
* KEY
*/
@ExcelProperty(value = "流程KEY")
private String processKey;
/**
*
*/
@ExcelProperty(value = "流程版本")
private Integer version;
/**
*
*/
@ExcelProperty(value = "备注")
private String remark;
/**
*
*/
private WfFormManageVo wfFormManageVo;
}

@ -0,0 +1,63 @@
package org.dromara.workflow.domain.vo;
import org.dromara.workflow.domain.WfFormManage;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* wf_form_manage
*
* @author may
* @date 2024-03-29
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = WfFormManage.class)
public class WfFormManageVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
@ExcelProperty(value = "主键")
private Long id;
/**
*
*/
@ExcelProperty(value = "表单名称")
private String formName;
/**
*
*/
@ExcelProperty(value = "表单类型")
private String formType;
/**
*
*/
private String formTypeName;
/**
* /ID
*/
@ExcelProperty(value = "路由地址/表单ID")
private String router;
/**
*
*/
@ExcelProperty(value = "备注")
private String remark;
}

@ -0,0 +1,75 @@
package org.dromara.workflow.domain.vo;
import org.dromara.workflow.domain.WfNodeConfig;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* wf_node_config
*
* @author may
* @date 2024-03-30
*/
@Data
@ExcelIgnoreUnannotated
@AutoMapper(target = WfNodeConfig.class)
public class WfNodeConfigVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
@ExcelProperty(value = "主键")
private Long id;
/**
* id
*/
@ExcelProperty(value = "表单id")
private Long formId;
/**
*
*/
@ExcelProperty(value = "表单类型")
private String formType;
/**
*
*/
@ExcelProperty(value = "节点名称")
private String nodeName;
/**
* id
*/
@ExcelProperty(value = "节点id")
private String nodeId;
/**
* id
*/
@ExcelProperty(value = "流程定义id")
private String definitionId;
/**
* 0 1
*/
@ExcelProperty(value = "是否为申请人节点 0是 1否")
private String applyUserTask;
/**
*
*/
private WfFormManageVo wfFormManageVo;
}

@ -0,0 +1,92 @@
package org.dromara.workflow.dubbo;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboService;
import org.dromara.workflow.api.domain.RemoteWorkflowService;
import org.dromara.workflow.api.domain.dto.BusinessInstanceDTO;
import org.dromara.workflow.common.enums.BusinessStatusEnum;
import org.dromara.workflow.domain.ActHiProcinst;
import org.dromara.workflow.service.IActHiProcinstService;
import org.dromara.workflow.service.WorkflowService;
import java.util.List;
import java.util.Map;
/**
* RemoteWorkflowServiceImpl
*
* @Author ZETA
* @Date 2024/6/3
*/
@DubboService
@RequiredArgsConstructor
public class RemoteWorkflowServiceImpl implements RemoteWorkflowService {
private final WorkflowService workflowService;
private final IActHiProcinstService actHiProcinstService;
@Override
public boolean deleteRunAndHisInstance(List<String> businessKeys) {
return workflowService.deleteRunAndHisInstance(businessKeys);
}
@Override
public String getBusinessStatusByTaskId(String taskId) {
return workflowService.getBusinessStatusByTaskId(taskId);
}
@Override
public String getBusinessStatus(String businessKey) {
return workflowService.getBusinessStatus(businessKey);
}
@Override
public BusinessInstanceDTO getBusinessInstance(String businessKey) {
ActHiProcinst actHiProcinst = actHiProcinstService.selectByBusinessKey(businessKey);
if (actHiProcinst == null) {
BusinessInstanceDTO businessInstanceDTO = new BusinessInstanceDTO();
businessInstanceDTO.setBusinessStatus(BusinessStatusEnum.DRAFT.getStatus());
return businessInstanceDTO;
}
BusinessInstanceDTO businessInstanceDTO = BeanUtil.toBean(actHiProcinst, BusinessInstanceDTO.class);
businessInstanceDTO.setBusinessStatusName(BusinessStatusEnum.findByStatus(businessInstanceDTO.getBusinessStatus()));
businessInstanceDTO.setProcessDefinitionId(actHiProcinst.getProcDefId());
return businessInstanceDTO;
}
@Override
public List<BusinessInstanceDTO> getBusinessInstance(List<String> businessKeys) {
List<ActHiProcinst> actHiProcinstList = actHiProcinstService.selectByBusinessKeyIn(businessKeys);
List<BusinessInstanceDTO> businessInstanceList = BeanUtil.copyToList(actHiProcinstList, BusinessInstanceDTO.class,
CopyOptions.create().setFieldMapping(Map.of("procDefId", "processDefinitionId")));
businessInstanceList.forEach(dto -> {
dto.setBusinessStatusName(BusinessStatusEnum.findByStatus(dto.getBusinessStatus()));
});
return businessInstanceList;
}
@Override
public void setVariable(String taskId, String variableName, Object value) {
workflowService.setVariable(taskId, variableName, value);
}
@Override
public void setVariables(String taskId, Map<String, Object> variables) {
workflowService.setVariables(taskId, variables);
}
@Override
public void setVariableLocal(String taskId, String variableName, Object value) {
workflowService.setVariableLocal(taskId, variableName, value);
}
@Override
public void setVariablesLocal(String taskId, Map<String, Object> variables) {
workflowService.setVariablesLocal(taskId, variables);
}
}

@ -0,0 +1,108 @@
package org.dromara.workflow.flowable;
import org.flowable.bpmn.model.AssociationDirection;
import org.flowable.image.impl.DefaultProcessDiagramCanvas;
import java.awt.*;
import java.awt.geom.Line2D;
import java.awt.geom.RoundRectangle2D;
public class CustomDefaultProcessDiagramCanvas extends DefaultProcessDiagramCanvas {
//设置高亮线的颜色 这里我设置成绿色
protected static Color HIGHLIGHT_SEQUENCEFLOW_COLOR = Color.GREEN;
public CustomDefaultProcessDiagramCanvas(int width, int height, int minX, int minY, String imageType, String activityFontName, String labelFontName, String annotationFontName, ClassLoader customClassLoader) {
super(width, height, minX, minY, imageType, activityFontName, labelFontName, annotationFontName, customClassLoader);
}
/**
* 线
*/
public void drawConnection(int[] xPoints, int[] yPoints, boolean conditional, boolean isDefault, String connectionType,
AssociationDirection associationDirection, boolean highLighted, double scaleFactor) {
Paint originalPaint = g.getPaint();
Stroke originalStroke = g.getStroke();
g.setPaint(CONNECTION_COLOR);
if (connectionType.equals("association")) {
g.setStroke(ASSOCIATION_STROKE);
} else if (highLighted) {
//设置线的颜色
g.setPaint(HIGHLIGHT_SEQUENCEFLOW_COLOR);
g.setStroke(HIGHLIGHT_FLOW_STROKE);
}
for (int i = 1; i < xPoints.length; i++) {
Integer sourceX = xPoints[i - 1];
Integer sourceY = yPoints[i - 1];
Integer targetX = xPoints[i];
Integer targetY = yPoints[i];
Line2D.Double line = new Line2D.Double(sourceX, sourceY, targetX, targetY);
g.draw(line);
}
if (isDefault) {
Line2D.Double line = new Line2D.Double(xPoints[0], yPoints[0], xPoints[1], yPoints[1]);
drawDefaultSequenceFlowIndicator(line, scaleFactor);
}
if (conditional) {
Line2D.Double line = new Line2D.Double(xPoints[0], yPoints[0], xPoints[1], yPoints[1]);
drawConditionalSequenceFlowIndicator(line, scaleFactor);
}
if (associationDirection == AssociationDirection.ONE || associationDirection == AssociationDirection.BOTH) {
Line2D.Double line = new Line2D.Double(xPoints[xPoints.length - 2], yPoints[xPoints.length - 2], xPoints[xPoints.length - 1], yPoints[xPoints.length - 1]);
drawArrowHead(line, scaleFactor);
}
if (associationDirection == AssociationDirection.BOTH) {
Line2D.Double line = new Line2D.Double(xPoints[1], yPoints[1], xPoints[0], yPoints[0]);
drawArrowHead(line, scaleFactor);
}
g.setPaint(originalPaint);
g.setStroke(originalStroke);
}
/**
*
*/
public void drawHighLight(int x, int y, int width, int height) {
Paint originalPaint = g.getPaint();
Stroke originalStroke = g.getStroke();
//设置高亮节点的颜色
g.setPaint(HIGHLIGHT_COLOR);
g.setStroke(THICK_TASK_BORDER_STROKE);
RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20);
g.draw(rect);
g.setPaint(originalPaint);
g.setStroke(originalStroke);
}
/**
* @description:
* @param: x
* @param: y
* @param: width
* @param: height
* @return: void
* @author: gssong
* @date: 2022/4/12
*/
public void drawHighLightRed(int x, int y, int width, int height) {
Paint originalPaint = g.getPaint();
Stroke originalStroke = g.getStroke();
//设置高亮节点的颜色
g.setPaint(Color.green);
g.setStroke(THICK_TASK_BORDER_STROKE);
RoundRectangle2D rect = new RoundRectangle2D.Double(x, y, width, height, 20, 20);
g.draw(rect);
g.setPaint(originalPaint);
g.setStroke(originalStroke);
}
}

@ -0,0 +1,61 @@
package org.dromara.workflow.flowable.cmd;
import cn.hutool.core.collection.CollUtil;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
import org.flowable.engine.impl.util.CommandContextUtil;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.dromara.workflow.common.constant.FlowConstant.NUMBER_OF_INSTANCES;
/**
*
*
* @author may
*/
public class AddSequenceMultiInstanceCmd implements Command<Void> {
/**
* id
*/
private final String executionId;
/**
* KEY
*/
private final String assigneeList;
/**
*
*/
private final List<Long> assignees;
public AddSequenceMultiInstanceCmd(String executionId, String assigneeList, List<Long> assignees) {
this.executionId = executionId;
this.assigneeList = assigneeList;
this.assignees = assignees;
}
@Override
public Void execute(CommandContext commandContext) {
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager();
ExecutionEntity entity = executionEntityManager.findById(executionId);
// 多实例任务总数加 assignees.size()
if (entity.getVariable(NUMBER_OF_INSTANCES) instanceof Integer nrOfInstances) {
entity.setVariable(NUMBER_OF_INSTANCES, nrOfInstances + assignees.size());
}
// 设置流程变量
if (entity.getVariable(assigneeList) instanceof List<?> userIds) {
CollUtil.addAll(userIds, assignees);
Map<String, Object> variables = new HashMap<>(16);
variables.put(assigneeList, userIds);
entity.setVariables(variables);
}
return null;
}
}

@ -0,0 +1,64 @@
package org.dromara.workflow.flowable.cmd;
import cn.hutool.core.collection.CollUtil;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.resource.api.RemoteFileService;
import org.dromara.resource.api.domain.RemoteFile;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.impl.persistence.entity.AttachmentEntity;
import org.flowable.engine.impl.persistence.entity.AttachmentEntityManager;
import org.flowable.engine.impl.util.CommandContextUtil;
import java.util.Date;
import java.util.List;
/**
*
*
* @author may
*/
public class AttachmentCmd implements Command<Boolean> {
private final String fileId;
private final String taskId;
private final String processInstanceId;
public AttachmentCmd(String fileId, String taskId, String processInstanceId) {
this.fileId = fileId;
this.taskId = taskId;
this.processInstanceId = processInstanceId;
}
@Override
public Boolean execute(CommandContext commandContext) {
try {
if (StringUtils.isNotBlank(fileId)) {
List<RemoteFile> ossList = SpringUtils.getBean(RemoteFileService.class).selectByIds(fileId);
if (CollUtil.isNotEmpty(ossList)) {
for (RemoteFile oss : ossList) {
AttachmentEntityManager attachmentEntityManager = CommandContextUtil.getAttachmentEntityManager();
AttachmentEntity attachmentEntity = attachmentEntityManager.create();
attachmentEntity.setRevision(1);
attachmentEntity.setUserId(LoginHelper.getUserId().toString());
attachmentEntity.setName(oss.getOriginalName());
attachmentEntity.setDescription(oss.getOriginalName());
attachmentEntity.setType(oss.getFileSuffix());
attachmentEntity.setTaskId(taskId);
attachmentEntity.setProcessInstanceId(processInstanceId);
attachmentEntity.setContentId(oss.getOssId().toString());
attachmentEntity.setTime(new Date());
attachmentEntityManager.insert(attachmentEntity);
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return true;
}
}

@ -0,0 +1,36 @@
package org.dromara.workflow.flowable.cmd;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
import org.flowable.engine.impl.util.CommandContextUtil;
import java.io.Serializable;
/**
*
*
* @author may
*/
public class DeleteExecutionCmd implements Command<Void>, Serializable {
/**
* id
*/
private final String executionId;
public DeleteExecutionCmd(String executionId) {
this.executionId = executionId;
}
@Override
public Void execute(CommandContext commandContext) {
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager();
ExecutionEntity entity = executionEntityManager.findById(executionId);
if (entity != null) {
executionEntityManager.deleteExecutionAndRelatedData(entity, "", false, false);
}
return null;
}
}

@ -0,0 +1,82 @@
package org.dromara.workflow.flowable.cmd;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
import org.flowable.engine.impl.util.CommandContextUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.dromara.workflow.common.constant.FlowConstant.LOOP_COUNTER;
import static org.dromara.workflow.common.constant.FlowConstant.NUMBER_OF_INSTANCES;
/**
*
*
* @author may
*/
@AllArgsConstructor
public class DeleteSequenceMultiInstanceCmd implements Command<Void> {
/**
* id
*/
private final String currentUserId;
/**
* id
*/
private final String executionId;
/**
* KEY
*/
private final String assigneeList;
/**
*
*/
private final List<Long> assignees;
@Override
@SuppressWarnings("unchecked")
public Void execute(CommandContext commandContext) {
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager();
ExecutionEntity entity = executionEntityManager.findById(executionId);
// 设置流程变量
List<Long> userIds = new ArrayList<>();
List<Object> variable = (List<Object>) entity.getVariable(assigneeList);
for (Object o : variable) {
userIds.add(Long.valueOf(o.toString()));
}
List<Long> userIdList = new ArrayList<>();
userIds.forEach(e -> {
Long userId = assignees.stream().filter(id -> ObjectUtil.equals(id, e)).findFirst().orElse(null);
if (userId == null) {
userIdList.add(e);
}
});
// 当前任务执行位置
int loopCounterIndex = -1;
for (int i = 0; i < userIdList.size(); i++) {
Long userId = userIdList.get(i);
if (currentUserId.equals(userId.toString())) {
loopCounterIndex = i;
}
}
Map<String, Object> variables = new HashMap<>(16);
variables.put(NUMBER_OF_INSTANCES, userIdList.size());
variables.put(assigneeList, userIdList);
variables.put(LOOP_COUNTER, loopCounterIndex);
entity.setVariables(variables);
return null;
}
}

@ -0,0 +1,39 @@
package org.dromara.workflow.flowable.cmd;
import org.dromara.common.core.utils.StreamUtils;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
import org.flowable.engine.impl.util.CommandContextUtil;
import java.io.Serializable;
import java.util.List;
/**
*
*
* @author may
*/
public class ExecutionChildByExecutionIdCmd implements Command<List<ExecutionEntity>>, Serializable {
/**
* id
*/
private final String executionId;
public ExecutionChildByExecutionIdCmd(String executionId) {
this.executionId = executionId;
}
@Override
public List<ExecutionEntity> execute(CommandContext commandContext) {
ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager();
// 获取当前执行数据
ExecutionEntity executionEntity = executionEntityManager.findById(executionId);
// 通过当前执行数据的父执行,查询所有子执行数据
List<ExecutionEntity> allChildrenExecution =
executionEntityManager.collectChildren(executionEntity.getParent());
return StreamUtils.filter(allChildrenExecution, e -> !e.isActive());
}
}

@ -0,0 +1,37 @@
package org.dromara.workflow.flowable.cmd;
import org.dromara.common.core.exception.ServiceException;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.impl.persistence.entity.HistoricProcessInstanceEntity;
import org.flowable.engine.impl.persistence.entity.HistoricProcessInstanceEntityManager;
import org.flowable.engine.impl.util.CommandContextUtil;
/**
*
*
* @author may
*/
public class UpdateBusinessStatusCmd implements Command<Boolean> {
private final String processInstanceId;
private final String status;
public UpdateBusinessStatusCmd(String processInstanceId, String status) {
this.processInstanceId = processInstanceId;
this.status = status;
}
@Override
public Boolean execute(CommandContext commandContext) {
try {
HistoricProcessInstanceEntityManager manager = CommandContextUtil.getHistoricProcessInstanceEntityManager();
HistoricProcessInstanceEntity processInstance = manager.findById(processInstanceId);
processInstance.setBusinessStatus(status);
manager.update(processInstance);
return true;
} catch (Exception e) {
throw new ServiceException(e.getMessage());
}
}
}

@ -0,0 +1,51 @@
package org.dromara.workflow.flowable.cmd;
import org.dromara.common.core.exception.ServiceException;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.task.service.HistoricTaskService;
import org.flowable.task.service.impl.persistence.entity.HistoricTaskInstanceEntity;
import java.util.Date;
import java.util.List;
/**
*
*
* @author may
*/
public class UpdateHiTaskInstCmd implements Command<Boolean> {
private final List<String> taskIds;
private final String processDefinitionId;
private final String processInstanceId;
public UpdateHiTaskInstCmd(List<String> taskIds, String processDefinitionId, String processInstanceId) {
this.taskIds = taskIds;
this.processDefinitionId = processDefinitionId;
this.processInstanceId = processInstanceId;
}
@Override
public Boolean execute(CommandContext commandContext) {
try {
HistoricTaskService historicTaskService = CommandContextUtil.getHistoricTaskService();
for (String taskId : taskIds) {
HistoricTaskInstanceEntity historicTask = historicTaskService.getHistoricTask(taskId);
if (historicTask != null) {
historicTask.setProcessDefinitionId(processDefinitionId);
historicTask.setProcessInstanceId(processInstanceId);
historicTask.setCreateTime(new Date());
CommandContextUtil.getHistoricTaskService().updateHistoricTask(historicTask, true);
}
}
return true;
} catch (Exception e) {
throw new ServiceException(e.getMessage());
}
}
}

@ -0,0 +1,32 @@
package org.dromara.workflow.flowable.config;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import org.dromara.workflow.flowable.handler.TaskTimeoutJobHandler;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.spring.boot.EngineConfigurationConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import java.util.Collections;
/**
* flowable
*
* @author may
*/
@Configuration
public class FlowableConfig implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration> {
@Autowired
private GlobalFlowableListener globalFlowableListener;
@Autowired
private IdentifierGenerator identifierGenerator;
@Override
public void configure(SpringProcessEngineConfiguration processEngineConfiguration) {
processEngineConfiguration.setIdGenerator(() -> identifierGenerator.nextId(null).toString());
processEngineConfiguration.setEventListeners(Collections.singletonList(globalFlowableListener));
processEngineConfiguration.addCustomJobHandler(new TaskTimeoutJobHandler());
}
}

@ -0,0 +1,139 @@
package org.dromara.workflow.flowable.config;
import cn.hutool.core.collection.CollUtil;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.workflow.common.enums.TaskStatusEnum;
import org.dromara.workflow.flowable.handler.TaskTimeoutJobHandler;
import org.dromara.workflow.utils.QueryUtils;
import org.flowable.bpmn.model.BoundaryEvent;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.common.engine.api.delegate.event.*;
import org.flowable.common.engine.impl.cfg.TransactionState;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.task.Comment;
import org.flowable.job.service.TimerJobService;
import org.flowable.job.service.impl.persistence.entity.JobEntity;
import org.flowable.job.service.impl.persistence.entity.TimerJobEntity;
import org.flowable.task.api.Task;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
/**
*
*
* @author may
*/
@Component
public class GlobalFlowableListener implements FlowableEventListener {
@Autowired
@Lazy
private TaskService taskService;
@Autowired
@Lazy
private RuntimeService runtimeService;
@Autowired
@Lazy
private RepositoryService repositoryService;
@Value("${flowable.async-executor-activate}")
private boolean asyncExecutorActivate;
@Override
public void onEvent(FlowableEvent flowableEvent) {
if (flowableEvent instanceof FlowableEngineEvent flowableEngineEvent) {
FlowableEngineEventType engineEventType = (FlowableEngineEventType) flowableEvent.getType();
switch (engineEventType) {
case JOB_EXECUTION_SUCCESS -> jobExecutionSuccess((FlowableEngineEntityEvent) flowableEngineEvent);
case TASK_DUEDATE_CHANGED, TASK_CREATED -> {
FlowableEntityEvent flowableEntityEvent = (FlowableEntityEvent) flowableEngineEvent;
Object entityObject = flowableEntityEvent.getEntity();
TaskEntity task = (TaskEntity) entityObject;
if (asyncExecutorActivate && task.getDueDate() != null && task.getDueDate().after(new Date())) {
//删除之前已经存在的定时任务
TimerJobService timerJobService = CommandContextUtil.getTimerJobService();
List<TimerJobEntity> timerJobEntityList = timerJobService.findTimerJobsByProcessInstanceId(task.getProcessInstanceId());
if (!CollUtil.isEmpty(timerJobEntityList)) {
for (TimerJobEntity timerJobEntity : timerJobEntityList) {
String taskId = timerJobEntity.getJobHandlerConfiguration();
if (task.getId().equals(taskId)) {
timerJobService.deleteTimerJob(timerJobEntity);
}
}
}
//创建job对象
TimerJobEntity timer = timerJobService.createTimerJob();
timer.setTenantId(TenantHelper.getTenantId());
//设置job类型
timer.setJobType(JobEntity.JOB_TYPE_TIMER);
timer.setJobHandlerType(TaskTimeoutJobHandler.TYPE);
timer.setDuedate(task.getDueDate());
timer.setProcessInstanceId(task.getProcessInstanceId());
//设置任务id
timer.setJobHandlerConfiguration(task.getId());
//保存并触发事件
timerJobService.scheduleTimerJob(timer);
}
}
}
}
}
@Override
public boolean isFailOnException() {
return true;
}
@Override
public boolean isFireOnTransactionLifecycleEvent() {
return false;
}
@Override
public String getOnTransaction() {
return TransactionState.COMMITTED.name();
}
/**
*
*
* @param event
*/
protected void jobExecutionSuccess(FlowableEngineEntityEvent event) {
if (event != null && StringUtils.isNotBlank(event.getExecutionId())) {
Execution execution = runtimeService.createExecutionQuery().executionId(event.getExecutionId()).singleResult();
if (execution != null) {
BpmnModel bpmnModel = repositoryService.getBpmnModel(event.getProcessDefinitionId());
FlowElement flowElement = bpmnModel.getFlowElement(execution.getActivityId());
if (flowElement instanceof BoundaryEvent) {
String attachedToRefId = ((BoundaryEvent) flowElement).getAttachedToRefId();
List<Execution> list = runtimeService.createExecutionQuery().activityId(attachedToRefId).list();
for (Execution ex : list) {
Task task = QueryUtils.taskQuery().executionId(ex.getId()).singleResult();
if (task != null) {
List<Comment> taskComments = taskService.getTaskComments(task.getId());
if (CollUtil.isEmpty(taskComments)) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.PASS.getStatus(), "超时自动审批!");
}
}
}
}
}
}
}
}

@ -0,0 +1,51 @@
package org.dromara.workflow.flowable.handler;
import org.dromara.common.core.utils.ServletUtils;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.workflow.api.domain.event.ProcessEvent;
import org.dromara.workflow.api.domain.event.ProcessTaskEvent;
import org.springframework.stereotype.Component;
/**
*
*
* @author may
* @date 2024-06-02
*/
@Component
public class FlowProcessEventHandler {
/**
* (: 退 )
*
* @param key key
* @param businessKey id
* @param status
* @param submit true
*/
public void processHandler(String key, String businessKey, String status, boolean submit) {
ProcessEvent processEvent = new ProcessEvent();
processEvent.setKey(key);
processEvent.setBusinessKey(businessKey);
processEvent.setStatus(status);
processEvent.setSubmit(submit);
processEvent.setRequest(ServletUtils.getRequest());
SpringUtils.context().publishEvent(processEvent);
}
/**
*
*
* @param keyNode key(key_)
* @param taskId id
* @param businessKey id
*/
public void processTaskHandler(String keyNode, String taskId, String businessKey) {
ProcessTaskEvent processTaskEvent = new ProcessTaskEvent();
processTaskEvent.setKeyNode(keyNode);
processTaskEvent.setTaskId(taskId);
processTaskEvent.setBusinessKey(businessKey);
processTaskEvent.setRequest(ServletUtils.getRequest());
SpringUtils.context().publishEvent(processTaskEvent);
}
}

@ -0,0 +1,38 @@
package org.dromara.workflow.flowable.handler;
import org.dromara.workflow.common.enums.TaskStatusEnum;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.TaskService;
import org.flowable.engine.impl.jobexecutor.TimerEventHandler;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.job.service.JobHandler;
import org.flowable.job.service.impl.persistence.entity.JobEntity;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.flowable.variable.api.delegate.VariableScope;
/**
* ()
*
* @author may
*/
public class TaskTimeoutJobHandler extends TimerEventHandler implements JobHandler {
public static final String TYPE = "taskTimeout";
@Override
public String getType() {
return TYPE;
}
@Override
public void execute(JobEntity job, String configuration, VariableScope variableScope, CommandContext commandContext) {
TaskService taskService = CommandContextUtil.getProcessEngineConfiguration(commandContext)
.getTaskService();
Task task = taskService.createTaskQuery().taskId(configuration).singleResult();
if (task != null) {
taskService.addComment(task.getId(), task.getProcessInstanceId(), TaskStatusEnum.TIMEOUT.getStatus(), "超时自动审批!");
taskService.complete(configuration);
}
}
}

@ -0,0 +1,16 @@
package org.dromara.workflow.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.workflow.domain.ActHiProcinst;
/**
* Mapper
*
* @author may
* @date 2023-07-22
*/
@InterceptorIgnore(tenantLine = "true")
public interface ActHiProcinstMapper extends BaseMapperPlus<ActHiProcinst, ActHiProcinst> {
}

@ -0,0 +1,16 @@
package org.dromara.workflow.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import org.dromara.workflow.domain.ActHiTaskinst;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* Mapper
*
* @author may
* @date 2024-03-02
*/
@InterceptorIgnore(tenantLine = "true")
public interface ActHiTaskinstMapper extends BaseMapperPlus<ActHiTaskinst, ActHiTaskinst> {
}

@ -0,0 +1,47 @@
package org.dromara.workflow.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.workflow.domain.vo.TaskVo;
/**
* Mapper
*
* @author may
* @date 2024-03-02
*/
@InterceptorIgnore(tenantLine = "true")
public interface ActTaskMapper extends BaseMapperPlus<TaskVo, TaskVo> {
/**
*
*
* @param page
* @param queryWrapper
* @return
*/
Page<TaskVo> getTaskWaitByPage(@Param("page") Page<TaskVo> page, @Param(Constants.WRAPPER) Wrapper<TaskVo> queryWrapper);
/**
*
*
* @param page
* @param queryWrapper
* @return
*/
Page<TaskVo> getTaskFinishByPage(@Param("page") Page<TaskVo> page, @Param(Constants.WRAPPER) Wrapper<TaskVo> queryWrapper);
/**
*
*
* @param page
* @param queryWrapper
* @return
*/
Page<TaskVo> getTaskCopyByPage(@Param("page") Page<TaskVo> page, @Param(Constants.WRAPPER) QueryWrapper<TaskVo> queryWrapper);
}

@ -0,0 +1,15 @@
package org.dromara.workflow.mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.workflow.domain.WfCategory;
import org.dromara.workflow.domain.vo.WfCategoryVo;
/**
* Mapper
*
* @author may
* @date 2023-06-27
*/
public interface WfCategoryMapper extends BaseMapperPlus<WfCategory, WfCategoryVo> {
}

@ -0,0 +1,15 @@
package org.dromara.workflow.mapper;
import org.dromara.workflow.domain.WfDefinitionConfig;
import org.dromara.workflow.domain.vo.WfDefinitionConfigVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* Mapper
*
* @author may
* @date 2024-03-18
*/
public interface WfDefinitionConfigMapper extends BaseMapperPlus<WfDefinitionConfig, WfDefinitionConfigVo> {
}

@ -0,0 +1,15 @@
package org.dromara.workflow.mapper;
import org.dromara.workflow.domain.WfFormManage;
import org.dromara.workflow.domain.vo.WfFormManageVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* Mapper
*
* @author may
* @date 2024-03-29
*/
public interface WfFormManageMapper extends BaseMapperPlus<WfFormManage, WfFormManageVo> {
}

@ -0,0 +1,15 @@
package org.dromara.workflow.mapper;
import org.dromara.workflow.domain.WfNodeConfig;
import org.dromara.workflow.domain.vo.WfNodeConfigVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
/**
* Mapper
*
* @author may
* @date 2024-03-30
*/
public interface WfNodeConfigMapper extends BaseMapperPlus<WfNodeConfig, WfNodeConfigVo> {
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save