Merge branch 'featrue/micro_service' into dev

# Conflicts:
#	workflow-engine-core/src/main/java/cn/axzo/workflow/core/deletage/BpmTaskCalculateDTO.java
#	workflow-engine-core/src/main/java/cn/axzo/workflow/core/listener/BpmActivityEventListener.java
#	workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/BpmProcessInstanceService.java
#	workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/dto/request/bpmn/process/CustomProcInstSearchDTO.java
#	workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/engine/EngineActivityEventListener.java
#	workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmProcessInstanceServiceImpl.java
#	workflow-engine-server/src/main/java/cn/axzo/server/controller/web/BpmProcessInstanceController.java
This commit is contained in:
wangli 2023-07-31 10:24:29 +08:00
commit 29a2bed129
176 changed files with 6616 additions and 4126 deletions

24
pom.xml
View File

@ -11,7 +11,7 @@
<groupId>cn.axzo.workflow</groupId>
<artifactId>workflow-engine</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<version>1.0.1-SNAPSHOT</version>
<name>workflow-engine</name>
<properties>
@ -41,28 +41,6 @@
</dependencies>
</dependencyManagement>
<dependencies>
<!-- lombok -->
<!-- <dependency>-->
<!-- <groupId>org.projectlombok</groupId>-->
<!-- <artifactId>lombok</artifactId>-->
<!-- </dependency>-->
<!-- for test -->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-test</artifactId>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>junit</groupId>-->
<!-- <artifactId>junit</artifactId>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
</dependencies>
<build>
<plugins>
<!-- maven-compiler-plugin 插件,解决 Lombok + MapStruct 组合 -->

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>workflow-engine</artifactId>
<groupId>cn.axzo.workflow</groupId>
<version>1.0-SNAPSHOT</version>
<version>1.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -18,16 +18,25 @@
<groupId>cn.axzo.framework</groupId>
<artifactId>axzo-consumer-spring-cloud-starter</artifactId>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>cn.axzo.framework</groupId>
<artifactId>axzo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<scope>provided</scope>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- for test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<!-- for test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

View File

@ -1,15 +1,15 @@
package cn.axzo.client;
package cn.axzo.workflow.client;
import cn.axzo.framework.domain.page.PageQO;
import cn.axzo.framework.domain.page.PageResp;
import cn.axzo.framework.domain.web.ApiException;
import cn.axzo.framework.domain.web.result.ApiPageResult;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.client.feign.MicroArchetypeApi;
import cn.axzo.client.model.NewUserReq;
import cn.axzo.client.model.QueryUserReq;
import cn.axzo.client.model.UpdateUserReq;
import cn.axzo.client.model.UserRes;
import cn.axzo.workflow.client.feign.MicroArchetypeApi;
import cn.axzo.workflow.client.model.NewUserReq;
import cn.axzo.workflow.client.model.QueryUserReq;
import cn.axzo.workflow.client.model.UpdateUserReq;
import cn.axzo.workflow.client.model.UserRes;
import cn.azxo.framework.common.model.CommonResponse;
import lombok.RequiredArgsConstructor;

View File

@ -1,8 +1,9 @@
package cn.axzo.client.config;
package cn.axzo.workflow.client.config;
import cn.axzo.client.feign.MicroArchetypeApi;
import cn.axzo.client.MicroArchetypeClient;
import cn.axzo.client.feign.MicroArchetypeFallbackFactory;
import cn.axzo.workflow.client.MicroArchetypeClient;
import cn.axzo.workflow.client.feign.MicroArchetypeApi;
import cn.axzo.workflow.client.feign.MicroArchetypeFallbackFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -12,10 +13,11 @@ import org.springframework.context.annotation.Configuration;
* @Date: 2022/9/17
* @Description:
*/
@EnableFeignClients(basePackages = {"cn.axzo.client"})
@EnableFeignClients(basePackages = {"cn.axzo.workflow.client"})
@Configuration
public class MicroArchetypeClientAutoConfiguration {
public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@Bean
public MicroArchetypeFallbackFactory microArchetypeFallbackFactory() {
return new MicroArchetypeFallbackFactory();

View File

@ -0,0 +1,56 @@
package cn.axzo.workflow.client.consumer;
import org.springframework.core.Ordered;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
/**
* @author: wangli
* @date: 2022/6/9 14:41
*/
public abstract class AbstractFlowableEngineEventMQListener implements
FlowableEngineEventMQListener {
protected final List<FlowableEngineEventProcessor> listeners = new ArrayList<>();
private Set<TaskListener> taskListeners;
private Set<ProcessInstanceListener> processInstanceListeners;
@Override
public Set<TaskListener> getTaskListeners() {
return taskListeners;
}
@Override
public void setTaskListeners(Set<TaskListener> taskListeners) {
this.taskListeners = taskListeners;
}
@Override
public Set<ProcessInstanceListener> getProcessInstanceListeners() {
return processInstanceListeners;
}
@Override
public void setProcessInstanceListeners(
Set<ProcessInstanceListener> processInstanceListeners) {
this.processInstanceListeners = processInstanceListeners;
}
@Override
public final List<FlowableEngineEventProcessor> getAllListeners() {
if (CollectionUtils.isEmpty(listeners)) {
synchronized (listeners) {
if (CollectionUtils.isEmpty(listeners)) {
listeners.addAll(getTaskListeners());
listeners.addAll(getProcessInstanceListeners());
}
}
}
listeners.sort(Comparator.comparing(Ordered::getOrder));
return listeners;
}
}

View File

@ -0,0 +1,129 @@
package cn.axzo.workflow.client.consumer;
import com.rabbitmq.client.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.core.Ordered;
import java.io.IOException;
import java.util.Objects;
import static cn.axzo.workflow.client.config.MicroArchetypeClientAutoConfiguration.OBJECT_MAPPER;
/**
* @author: wangli
* @date: 2022/6/9 15:08
*/
public abstract class AbstractListener implements FlowableEngineEventProcessor {
private final Logger log = LoggerFactory.getLogger(AbstractListener.class);
public static final ThreadLocal<Channel> TL_CHANNEL = new ThreadLocal<>();
public static final ThreadLocal<Message> TL_MESSAGE = new ThreadLocal<>();
@Override
public final void process(Message message, Channel channel) {
TL_CHANNEL.set(channel);
invoke(message);
}
/**
* 判断是否能支持当前的事件
* <p>
* Note that: 如果该方法内部实现抛出异常, 此条消息不会自动 ack, 将会引起消息一直"退回 -> 消费"路径循环.
*
* @param flag
* @return 返回 true ,将执行 Listener 中覆写的事件方法, 否则该消息将自动 ACK,不可再消费该条消息
*/
@Override
public abstract boolean supportEvent(String flag);
/**
* 解析监听的到工作流引擎消息未指定的 Entity 对象
*
* @param msgBytes 消息原信息
* @param type 被转成的类型
* @param <T>
* @return
*/
protected final <T> T parseEntity(byte[] msgBytes, Class<T> type) {
String msg = new String(msgBytes);
if (log.isDebugEnabled()) {
log.debug("接收的消息内容为: {}", msg);
}
try {
String[] split = msg.split("");
return OBJECT_MAPPER.readValue(split[1], type);
} catch (Exception e) {
e.printStackTrace();
if (log.isDebugEnabled()) {
log.debug("接收的消息无法转换为正常的 Entity 模型, 将直接丢弃该消息! 当前信息为: {}", new String(msgBytes));
}
autoAck();
return null;
}
}
/**
* 判断配置是否开启手动 ACK, 如果开启还需要判断 Channel 对象是否为空, 否则 ACK 动作会直接抛出异常
*/
protected final void ack() throws IOException {
if (Objects.isNull(TL_CHANNEL.get())) {
throw new IllegalArgumentException("线程本地变量表已不存在 Channel, 无法进行 ACK 确认!");
}
TL_CHANNEL.get().basicAck(TL_MESSAGE.get().getMessageProperties().getDeliveryTag(), false);
clearThreadLocal();
}
protected final void nack(boolean requeue) throws IOException {
if (Objects.isNull(TL_CHANNEL.get())) {
throw new IllegalArgumentException("线程本地变量表已不存在 Channel, 无法进行 NACK 确认!");
}
TL_CHANNEL.get()
.basicNack(TL_MESSAGE.get().getMessageProperties().getDeliveryTag(), false, requeue);
clearThreadLocal();
}
/**
* 考虑是否将 Channel Message 本身直接暴露给使用者
*
* @return
*/
private final Channel getChannel() {
return TL_CHANNEL.get();
}
private final Message getMessage() {
return TL_MESSAGE.get();
}
/**
* 清理线程变量中的无用的 Message Channel
*/
@Override
public final void clearThreadLocal() {
TL_MESSAGE.remove();
TL_CHANNEL.remove();
}
protected final void autoAck() {
//TODO ACK 处理问题
// WorkflowUtils.getRabbitProperties().ifPresent(r -> {
// if (Objects.nonNull(r.getListener().getSimple().getAcknowledgeMode()) && r.getListener()
// .getSimple().getAcknowledgeMode().isManual()) {
// try {
// ack();
// } catch (IOException e) {
// e.printStackTrace();
// log.error("RabbitMQ 消息自动 ACK 发生异常");
// }
// }
// });
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
}

View File

@ -0,0 +1,80 @@
package cn.axzo.workflow.client.consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
/**
* 流程实例自身状态变更事件
*
* @author: wangli
* @date: 2022/6/9 14:13
*/
public abstract class AbstractProcessInstanceListener extends AbstractListener implements
ProcessInstanceListener {
private Logger log = LoggerFactory.getLogger(AbstractProcessInstanceListener.class);
private static final String PROCESS_INSTANCE_STR = "pi";
@Override
public final boolean supportEvent(String flag) {
return PROCESS_INSTANCE_STR.equals(flag);
}
@Override
public final void invoke(Message message) {
TL_MESSAGE.set(message);
// ProcessInstanceEntity entity = parseEntity(message.getBody(),
// ProcessInstanceEntity.class);
// if (Objects.isNull(entity) || !support(entity)) {
// if (log.isDebugEnabled()) {
// log.debug("无需处理该消息,将自动确认消息");
// }
// autoAck();
// return;
// }
// switch (entity.getType()) {
// case PROCESS_CREATED:
// created(entity);
// break;
// case PROCESS_STARTED:
// started(entity);
// break;
// case PROCESS_CANCELLED:
// cancelled(entity);
// break;
// case PROCESS_COMPLETED:
// completed(entity);
// break;
// default:
// autoAck();
// throw new IllegalArgumentException("不支持的流程实例事件类型!");
// }
}
/**
* @param entity
* @return true 才会真实回调 {@link ProcessInstanceListener} 接口相关方法
*/
protected abstract Boolean support();
@Override
public void created() {
autoAck();
}
@Override
public void started() {
autoAck();
}
@Override
public void cancelled() {
autoAck();
}
@Override
public void completed() {
autoAck();
}
}

View File

@ -0,0 +1,74 @@
package cn.axzo.workflow.client.consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
/**
* 流程实例内的审批任务节点自身的状态变更事件
*
* @author: wangli
* @date: 2022/6/7 15:35
*/
public abstract class AbstractTaskListener extends AbstractListener implements TaskListener {
private Logger log = LoggerFactory.getLogger(AbstractTaskListener.class);
private static final String TASK_STR = "ts";
@Override
public final boolean supportEvent(String flag) {
return TASK_STR.equals(flag);
}
@Override
public final void invoke(Message message) {
// TL_MESSAGE.set(message);
// TaskEntity entity = parseEntity(message.getBody(), TaskEntity.class);
// if (Objects.isNull(entity) || !support(entity)) {
// if (log.isDebugEnabled()) {
// log.debug("无需处理该消息,将自动确认消息");
// }
// autoAck();
// return;
// }
// switch (entity.getType()) {
// case TASK_CREATED:
// created(entity);
// break;
// case TASK_ASSIGNED:
// assigned(entity);
// break;
// case TASK_COMPLETED:
// completed(entity);
// break;
// default:
// autoAck();
// throw new IllegalArgumentException("不支持的活动事件类型!");
// }
}
/**
* 判断是否需要处理该流程实例的信息
* <p>
* Note That: 请杜绝该方法中抛出异常.
*
* @return true 才会真实回调 {@link TaskListener} 接口相关方法
*/
protected abstract Boolean support();
@Override
public void created() {
autoAck();
}
@Override
public void assigned() {
autoAck();
}
@Override
public void completed() {
autoAck();
}
}

View File

@ -0,0 +1,44 @@
package cn.axzo.workflow.client.consumer;
import com.rabbitmq.client.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.util.StringUtils;
/**
* @author: wangli
* @date: 2022/6/9 14:20
*/
public class DefaultFlowableEngineEventRabbitMQListener extends
AbstractFlowableEngineEventMQListener {
private Logger log = LoggerFactory.getLogger(DefaultFlowableEngineEventRabbitMQListener.class);
/**
* 判断事件类型是 Process 还是 Activity,调用不同的 Listener
*/
@Override
public void onMessage(Message message, Channel channel) {
String body = new String(message.getBody());
log.info("[onMessage][线程编号:{} 消息内容:{}], Message: {}", Thread.currentThread().getId(),
body, message);
//这里是有简易的协议标识
String[] split = body.split("");
if (split.length == 2 && StringUtils.hasLength(split[1])) {
listeners.forEach(listener -> {
try {
if (listener.supportEvent(split[0])) {
listener.process(message, channel);
listener.clearThreadLocal();
}
} catch (Exception e) {
e.printStackTrace();
}
});
}
}
}

View File

@ -0,0 +1,42 @@
package cn.axzo.workflow.client.consumer;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import java.io.IOException;
import java.util.List;
import java.util.Set;
/**
* 接收全量 MQ 中关于 Flowable Engine Event 事件
*
* @author: wangli
* @date: 2022/6/9 14:04
*/
public interface FlowableEngineEventMQListener {
/**
* 接收全量工作流引擎的状态变更事件
*/
void onMessage(Message message, Channel channel) throws IOException;
/**
* 获取 {@link TaskListener} 对象
*
* @return
*/
Set<TaskListener> getTaskListeners();
/**
* 获取 {@link ProcessInstanceListener} 对象
*
* @return
*/
Set<ProcessInstanceListener> getProcessInstanceListeners();
void setTaskListeners(Set<TaskListener> taskListeners);
void setProcessInstanceListeners(Set<ProcessInstanceListener> processInstanceListeners);
List<FlowableEngineEventProcessor> getAllListeners();
}

View File

@ -0,0 +1,36 @@
package cn.axzo.workflow.client.consumer;
import java.util.Objects;
/**
* 工作流事件消息列队消费者的工厂类
*
* @author wangli
* @date 2022/6/9 14:17
*/
public class FlowableEngineEventMqListenerFactory {
private volatile FlowableEngineEventMQListener flowableEngineEventMqListener;
protected void createFlowableEngineEventMqListener() {
if (Objects.isNull(flowableEngineEventMqListener)) {
synchronized (this) {
if (Objects.isNull(flowableEngineEventMqListener)) {
flowableEngineEventMqListener = new DefaultFlowableEngineEventRabbitMQListener();
}
}
}
}
public FlowableEngineEventMQListener getFlowableEngineEventMqListener() {
if (Objects.isNull(flowableEngineEventMqListener)) {
createFlowableEngineEventMqListener();
}
return flowableEngineEventMqListener;
}
public void setFlowableEngineEventMqListener(
FlowableEngineEventMQListener flowableEngineEventMqListener) {
this.flowableEngineEventMqListener = flowableEngineEventMqListener;
}
}

View File

@ -0,0 +1,23 @@
package cn.axzo.workflow.client.consumer;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.core.Ordered;
/**
* Processor
*
* @author: wangli
* @date: 2022/6/9 14:01
*/
public interface FlowableEngineEventProcessor extends Ordered {
boolean supportEvent(String flag);
void process(Message message, Channel channel);
void invoke(Message message);
void clearThreadLocal();
}

View File

@ -0,0 +1,32 @@
package cn.axzo.workflow.client.consumer;
/**
* 实例状态变更通知
*
* @author: wangli
* @date: 2022/6/7 14:30
*/
public interface ProcessInstanceListener extends FlowableEngineEventProcessor {
/**
* 实例已创建
*/
void created();
/**
* 实例已启动
*/
void started();
/**
* 实例已取消
*/
void cancelled();
/**
* 实例已完成
*/
void completed();
}

View File

@ -0,0 +1,32 @@
package cn.axzo.workflow.client.consumer;
/**
* 用户任务节点状态变更时触发的回调
* <p>
* 实际上对应 Flowable Engine Activity 的相关事件, 但为了保证业务的正常理解,更名为 Task
*
* @author: wangli
* @date: 2022/6/7 10:43
*/
public interface TaskListener extends FlowableEngineEventProcessor {
/**
* 用户任务已创建,未指派审核人
*/
void created();
/**
* 用户任务已指派审核人
*/
void assigned();
/**
* 用户任务已处理完成
* <p>
* 仅审核通过一个用户任务时触发, 如果任务是拒绝了, 则直接走实例取消事件
*/
void completed();
}

View File

@ -1,12 +1,11 @@
package cn.axzo.client.feign;
package cn.axzo.workflow.client.feign;
import cn.axzo.framework.context.client.QueryMap;
import cn.axzo.framework.domain.page.PageQO;
import cn.axzo.framework.domain.web.result.ApiPageResult;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.client.model.NewUserReq;
import cn.axzo.client.model.UpdateUserReq;
import cn.axzo.client.model.UserRes;
import cn.axzo.workflow.client.model.NewUserReq;
import cn.axzo.workflow.client.model.UpdateUserReq;
import cn.axzo.workflow.client.model.UserRes;
import cn.azxo.framework.common.model.CommonResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

View File

@ -1,13 +1,12 @@
package cn.axzo.client.feign;
package cn.axzo.workflow.client.feign;
import cn.axzo.framework.client.feign.FeignFallback;
import cn.axzo.framework.domain.page.PageQO;
import cn.axzo.framework.domain.web.result.ApiPageResult;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.framework.jackson.utility.JSON;
import cn.axzo.client.model.NewUserReq;
import cn.axzo.client.model.UpdateUserReq;
import cn.axzo.client.model.UserRes;
import cn.axzo.workflow.client.model.NewUserReq;
import cn.axzo.workflow.client.model.UpdateUserReq;
import cn.axzo.workflow.client.model.UserRes;
import cn.azxo.framework.common.model.CommonResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

View File

@ -1,4 +1,4 @@
package cn.axzo.client.feign;
package cn.axzo.workflow.client.feign;
import cn.axzo.framework.client.feign.FeignFallback;
import cn.axzo.framework.domain.web.code.IRespCode;

View File

@ -1,4 +1,4 @@
package cn.axzo.client.model;
package cn.axzo.workflow.client.model;
import lombok.Data;

View File

@ -1,4 +1,4 @@
package cn.axzo.client.model;
package cn.axzo.workflow.client.model;
import cn.axzo.framework.context.client.IQueryMap;
import cn.axzo.framework.context.client.QueryMap;

View File

@ -1,4 +1,4 @@
package cn.axzo.client.model;
package cn.axzo.workflow.client.model;
import lombok.Data;

View File

@ -1,4 +1,4 @@
package cn.axzo.client.model;
package cn.axzo.workflow.client.model;
import lombok.Data;

View File

@ -3,11 +3,11 @@
<parent>
<artifactId>workflow-engine</artifactId>
<groupId>cn.axzo.workflow</groupId>
<version>1.0-SNAPSHOT</version>
<version>1.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<version>1.0-SNAPSHOT</version>
<version>1.0.1-SNAPSHOT</version>
<artifactId>workflow-engine-core</artifactId>
<packaging>jar</packaging>
@ -36,40 +36,26 @@
<artifactId>hutool-all</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-bpmn-model</artifactId>
<version>${flowable.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-json-converter</artifactId>
<version>${flowable.version}</version>
<scope>compile</scope>
</dependency>
<!-- 引入 BPMN 引擎 -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter-basic</artifactId>
<version>${flowable.version}</version>
</dependency>
<!-- 引入 Form 引擎(基于 Flowable) -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-form-spring-configurator</artifactId>
<version>${flowable.version}</version>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter-actuator</artifactId>
<version>${flowable.version}</version>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-bpmn-converter</artifactId>
<version>${flowable.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-engine</artifactId>
<version>6.7.2</version>
</dependency>
</dependencies>
</project>

View File

@ -1,6 +1,9 @@
package cn.axzo.workflow.core.common;
public interface BpmConstants {
String BPMN_FILE_SUFFIX = ".bpmn";
String FORM_FILE_SUFFIX = ".form";
String SERVER_APP_ID = "server-app-id";
/**
* 引擎自己隐藏指令
@ -21,5 +24,19 @@ public interface BpmConstants {
String START_EVENT_ID = "startEventNode";
String END_EVENT_ID = "endEventNode";
String BPM_MODEL_CATEGORY = "bpm_model_category";
String MODEL_META_INFO_PROCESS = "MODEL_PROCESS";
String MODEL_META_INFO_FORM = "MODEL_FORM";
String BPM_ALLOW_SKIP_USER_TASK = "_INTERNAL_SKIP_USER_TASK";
/**
* 用于国内审批节点填写审批建议
* <p>
* 其他类型 @see org.flowable.engine.impl.persistence.entity.CommentEntity
*/
String COMMENT_TYPE_ADVICE = "advice";
String INITIATOR_REVOKE_THE_APPROVAL = "发起人主动撤销审批";
String APPROVAL_ENDS_AUTOMATICALLY = "审批拒绝自动结束";
String NUMBER_OF_INSTANCES = "nrOfInstances";
String MULTI_INSTANCE_LOOP_COUNTER = "loopCounter";
}

View File

@ -4,21 +4,45 @@ import cn.axzo.framework.domain.web.code.IProjectRespCode;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
/**
* @Author: liyong.tian
* @Date: 2022/9/5
* @Description: 响应码规范一共8位取值范围0~93位项目编号(首位不能为0)+2位模块编号+3位自定义编号
*/
@Getter
@AllArgsConstructor
public enum BpmErrorCode implements IProjectRespCode {
* @Date: 2022/9/5
* @Description: 响应码规范一共8位取值范围0~93位项目编号(首位不能为0)+2位模块编号+3位自定义编号
*/
@Getter
@AllArgsConstructor
public enum BpmErrorCode implements IProjectRespCode {
// ========== category 01-001 ==========
CATEGORY_VALUE_EXISTS("01001", "分类值【{}】已经存在"),
CATEGORY_NOT_EXISTS("01002", "指定分类不存在"),
// ========== convertor 02-001 ==========
CONVERTOR_UNKNOW_NODE_TYPE("02001", "节点类型【{}】暂不支持"),
CONVERTOR_META_DATA_FORMAT_ERROR("02002", "JSON 数据格式有误"),
// ========== model 03-001 ==========
MODEL_KEY_EXISTS("03001", "已经存在流程标识为【{}】的流程"),
MODEL_ID_NOT_EXISTS("03002", "流程模型ID【{}】不存在"),
MODEL_KEY_NOT_EXISTS("03003", "流程模型KEY【{}】不存在"),
// ========== processDefinition 04-001 ==========
PROCESS_DEFINITION_BPMN_NOT_EXISTS("04001", "模型ID【{}】的定义内容不存在"),
PROCESS_DEFINITION_ID_NOT_EXISTS("04002", "流程定义ID【{}】不存在"),
PROCESS_DEFINITION_DEPLOY_ID_NOT_EXISTS("04003", "流程定义部署ID【{}】不存在"),
PROCESS_DEFINITION_KEY_NOT_EXISTS("04004", "流程定义KEY【{}】不存在"),
PROCESS_DEFINITION_RESULT_TOO_MANY("04005", "租户【{}】中存在多条分类为【{}】的流程定义,不允许直接变更状态"),
PROCESS_DEFINITION_IS_SUSPENDED("04006", "流程定义KEY【{}】处于挂起状态"),
// "数据出现异常,同一个工作台下,同一个所属分类,只能有一个流程定义"),
// ========== processInstance 05-001 ==========
PROCESS_INSTANCE_CREATE_ERROR("05001", ""),
// ========== task 06-001 ==========
// ========== formDefinition 07-001 ==========
// ========== formInstance 08-001 ==========
// ========== flowableEngin 09-001 ==========
// ========== 流程模型 1-009-002-000 ==========
MODEL_KEY_EXISTS("9002000", "已经存在流程标识为【{}】的流程"),
MODEL_KEY_EXISTS2("9002000", "已经存在流程标识为【{}】的流程"),
MODEL_NOT_EXISTS("9002001", "流程模型不存在"),
MODEL_KEY_VALID("9002002",
// ========== 流程模型 01-001 ==========
MODEL_KEY_VALID("9002002",
"流程标识格式不正确,需要以字母或下划线开头,后接任意字母、数字、中划线、下划线、句点!"),
MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG("9002003",
"部署流程失败,原因:流程表单未配置,请点击【修改流程】按钮进行配置"),
@ -32,8 +56,8 @@ public enum BpmErrorCode implements IProjectRespCode {
PROCESS_DEFINITION_NAME_NOT_MATCH("9003001",
"流程定义的名字期望是({}),当前是({}),请修改 BPMN 流程图"),
PROCESS_DEFINITION_NOT_EXISTS("9003002", "流程定义不存在"),
PROCESS_DEFINITION_IS_SUSPENDED("9003003", "流程定义处于挂起状态"),
PROCESS_DEFINITION_BPMN_MODEL_NOT_EXISTS("9003004", "流程定义的模型不存在"),
PROCESS_DEFINITION_BPMN_MODEL_NOT_EXISTS("9003004", "流程定义的模型不存在"),
// ========== 流程实例 1-009-004-000 ==========
PROCESS_INSTANCE_NOT_EXISTS("9004000", "流程实例不存在"),
@ -96,10 +120,9 @@ public enum BpmErrorCode implements IProjectRespCode {
"流程模型模板不存在,或者模型未配置 BPMN 流程"),
BPM_PROCESS_DEFINITION_NOT_EXISTS("9012014",
"未查询到可以用于发起工作流的流程定义ID, 请确认工作台与所属分类是否匹配"),
BPM_PROCESS_DEFINITION_RESULT_TOO_MANY("9012015",
"数据出现异常,同一个工作台下,同一个所属分类,只能有一个流程定义"),
FORM_NOT_ENABLE("9012016", "表单已经不可用"),
FORM_NOT_ENABLE("9012016", "表单已经不可用"),
ILLEGAL_FORM_DATA("9012017", "表单类型数据异常, 非法数据"),
BPMN_XML_NOT_EXISTS("9012018", "BPMN 文件内容不存在,将终止发布"),
BPMN_XML_NOT_VALID("9012019", "BPMN 文件内容不合法,将终止发布"),
@ -116,9 +139,9 @@ public enum BpmErrorCode implements IProjectRespCode {
MODEL_POOL_CANT_DEPLOY("9012028", "模型已不部署,无需重复发布"),
PROCESS_DEFINITION_IS_SUSPENDED_CANT_DEPLOY("9012029",
"模型处于挂起状态,无法发布"),
BPM_META_DATA_FORMAT_ERROR("9012029", "BpmJson数据格式有误"),
FLOWABLE_GENERAL_ERROR("9013000", "流程引擎一般错误"),
FLOWABLE_GENERAL_ERROR("9013000", "流程引擎一般错误"),
FLOWABLE_ENGINE_OBJECT_NOT_FOUND("9013001", "流程引擎内部错误:流程定义未找到"),
FLOWABLE_WRONG_DB("9013002", "数据库版本与流程引擎版本不匹配"),
FLOWABLE_DB_OPTIMISTIC_LOCKING("9013003", "引擎内部数据乐观锁死锁"),

View File

@ -1,4 +0,0 @@
package cn.axzo.workflow.core.common.enums;
public class BpmErrorCodeConstants {
}

View File

@ -1,63 +0,0 @@
package cn.axzo.workflow.core.common.enums;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 流程实例的删除原因
*
* @author 芋道源码
*/
@Getter
@AllArgsConstructor
public enum BpmProcessInstanceDeleteReasonEnum {
/** 修改文案时,需要注意 isRejectReason 方法 */
REJECT_TASK("不通过任务,原因:{}"),
/** */
CANCEL_TASK("主动取消任务,原因:{}"),
// ========== 流程任务的独有原因 ==========
/** 多实例满足 condition 而结束时,其它任务实例任务会被取消,对应的删除原因是 MI_END*/
MULTI_TASK_END(
"该任务审核已被处理,无需审核");
/**
* 理由
*/
private final String reason;
/**
* 格式化理由
*
* @param args 参数
* @return 理由
*/
public String format(Object... args) {
return StrUtil.format(reason, args);
}
// ========== 逻辑 ==========
public static boolean isRejectReason(String reason) {
return StrUtil.startWith(reason, "不通过任务,原因:");
}
/**
* Flowable 的删除原因翻译成对应的中文原因
*
* @param reason 原始原因
* @return 原因
*/
public static String translateReason(String reason) {
if (StrUtil.isEmpty(reason)) {
return reason;
}
switch (reason) {
case "MI_END":
return MULTI_TASK_END.getReason();
default:
return reason;
}
}
}

View File

@ -3,31 +3,29 @@ package cn.axzo.workflow.core.common.enums;
import java.util.Arrays;
public enum BpmProcessInstanceResultEnum {
PROCESS(1, "审核中"),
APPROVE(2, "已通过"),
REJECT(3, "已驳回"),
CANCEL(4, "已撤销"),
// ========== 流程任务独有的状态 ==========
BACK(5, "退回/驳回");
PROCESSING("PROCESSING", "审批中"),
APPROVED("APPROVED", "已通过"),
REJECTED("REJECTED", "已驳回"),
CANCELLED("CANCELLED", "已撤销"),
SKIP("SKIP", "自动跳过"),
BACKED("BACKED", "退回/驳回");
/**
* 结果
*/
private final Integer result;
private final String status;
/**
* 描述
*/
private final String desc;
BpmProcessInstanceResultEnum(Integer result, String desc) {
this.result = result;
BpmProcessInstanceResultEnum(String status, String desc) {
this.status = status;
this.desc = desc;
}
public Integer getResult() {
return result;
public String getStatus() {
return status;
}
public String getDesc() {
@ -43,12 +41,12 @@ public enum BpmProcessInstanceResultEnum {
* @return 是否
*/
public static boolean isEndResult(Integer result) {
return Arrays.asList(APPROVE.getResult(), REJECT.getResult(),
CANCEL.getResult(), BACK.getResult()).contains(result);
return Arrays.asList(PROCESSING.getStatus(), APPROVED.getStatus(), REJECTED.getStatus(),
CANCELLED.getStatus(), BACKED.getStatus()).contains(result);
}
public static BpmProcessInstanceResultEnum valueOf(Integer result) {
return Arrays.stream(values()).filter(it -> it.getResult().equals(result)).findFirst()
public static BpmProcessInstanceResultEnum valueOfStatus(String status) {
return Arrays.stream(values()).filter(it -> it.getStatus().equals(status)).findFirst()
.orElse(null);
}
}

View File

@ -1,23 +1,21 @@
package cn.axzo.workflow.core.common.exception;
import cn.axzo.framework.domain.ServiceException;
import cn.axzo.framework.domain.web.code.BaseCode;
import cn.axzo.framework.domain.web.code.IRespCode;
import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j;
public class WorkflowEngineException extends ServiceException {
@Slf4j
public class WorkflowEngineException extends ServiceException {
private String code;
public WorkflowEngineException() {
this((IRespCode)BaseCode.SERVICE_UNAVAILABLE);
}
public WorkflowEngineException(IRespCode code) {
super(code.getMessage());
this.code = code.getRespCode();
}
public WorkflowEngineException(IRespCode code, String message) {
super(message);
public WorkflowEngineException(IRespCode code, String... params) {
super(doFormat(code.getCode(), code.getMessage(), params));
this.code = code.getRespCode();
}
@ -25,16 +23,45 @@ public class WorkflowEngineException extends ServiceException {
super(message);
}
public WorkflowEngineException(String message, Throwable cause) {
super(message, cause);
}
public WorkflowEngineException(Throwable cause) {
super(cause);
}
@Override
public String getCode() {
return this.code;
}
/**
* 将错误编号对应的消息使用 params 进行格式化
*
* @param code 错误编号
* @param messagePattern 消息模版
* @param params 参数
* @return 格式化后的提示
*/
@VisibleForTesting
private static String doFormat(String code, String messagePattern, Object... params) {
StringBuilder sbuf = new StringBuilder(messagePattern.length() + 50);
int i = 0;
int j;
int l;
for (l = 0; l < params.length; l++) {
j = messagePattern.indexOf("{}", i);
if (j == -1) {
log.error("[doFormat][参数过多:错误码({})|错误内容({})|参数({})", code, messagePattern, params);
if (i == 0) {
return messagePattern;
} else {
sbuf.append(messagePattern.substring(i));
return sbuf.toString();
}
} else {
sbuf.append(messagePattern, i, j);
sbuf.append(params[l]);
i = j + 2;
}
}
if (messagePattern.indexOf("{}", i) != -1) {
log.error("[doFormat][参数过少:错误码({})|错误内容({})|参数({})", code, messagePattern, params);
}
sbuf.append(messagePattern.substring(i));
return sbuf.toString();
}
}

View File

@ -3,8 +3,8 @@ package cn.axzo.workflow.core.common.utils;
import cn.axzo.workflow.core.common.enums.BpmFlowMultiMode;
import cn.axzo.workflow.core.common.enums.BpmFlowNodeType;
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
import cn.axzo.workflow.core.service.dto.BpmJsonNode;
import cn.axzo.workflow.core.service.dto.request.BpmJsonNodeProperty;
import cn.axzo.workflow.core.service.dto.request.bpmn.BpmnJsonNode;
import cn.axzo.workflow.core.service.dto.request.bpmn.BpmnJsonNodeProperty;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
@ -13,7 +13,6 @@ import org.flowable.bpmn.BpmnAutoLayout;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.engine.delegate.ExecutionListener;
import org.flowable.engine.delegate.TaskListener;
import org.flowable.engine.repository.Model;
@ -23,15 +22,16 @@ import java.util.stream.Collectors;
import static cn.axzo.workflow.core.common.BpmConstants.BPM_ALLOW_SKIP_USER_TASK;
import static cn.axzo.workflow.core.common.BpmConstants.END_EVENT_ID;
import static cn.axzo.workflow.core.common.enums.BpmErrorCode.BPM_META_DATA_FORMAT_ERROR;
import static cn.axzo.workflow.core.common.enums.BpmErrorCode.CONVERTOR_META_DATA_FORMAT_ERROR;
import static cn.axzo.workflow.core.common.enums.BpmErrorCode.CONVERTOR_UNKNOW_NODE_TYPE;
import static org.flowable.bpmn.model.ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION;
import static org.flowable.engine.delegate.BaseExecutionListener.EVENTNAME_END;
import static org.flowable.engine.delegate.BaseExecutionListener.EVENTNAME_START;
@Slf4j
public class BpmTransformUtil {
public static byte[] transformBpmnJsonToXml(BpmJsonNode bpmnJson, Model model) {
// JSONObject bpmnJson = (JSONObject) updateReqVO.getBpmnJson();
public static byte[] transformBpmnJsonToXml(BpmnJsonNode bpmnJson, Model model) {
BpmnModel bpmnModel = new BpmnModel();
Process process = new Process();
@ -41,26 +41,21 @@ public class BpmTransformUtil {
process.setName(model.getName());
if (BpmFlowNodeType.NODE_STARTER.getType().equals(bpmnJson.getType())) {
process.addFlowElement(createStartEvent(bpmnJson.getId()));
process.addFlowElement(createStartEvent(bpmnJson.getId(), Objects.nonNull(bpmnJson.getProperty()) ?
bpmnJson.getProperty().getFormKey() : ""));
}
List<SequenceFlow> sequenceFlows = Lists.newArrayList();
Map<String, BpmJsonNode> childNodeMap = new HashMap<>();
// JSONObject jsonObject = (JSONObject) JSONObject.toJSON(bpmnJson);
// ExtensionAttribute extensionAttribute=new ExtensionAttribute();
// extensionAttribute.setName("TestName");
// extensionAttribute.setNamespace("http://flowable.org/bpmn");
// extensionAttribute.setValue(bpmnJson.toJSONString());
//// process.addAttribute(extensionAttribute);
// JSONObject processNodes = bpmnJson.getJSONObject("nodeConfig");
Map<String, BpmnJsonNode> childNodeMap = new HashMap<>();
String lastNode = null;
try {
lastNode = create(bpmnJson.getId(), bpmnJson.getChildren(), process, bpmnModel, sequenceFlows,
childNodeMap);
} catch (WorkflowEngineException e) {
throw e;
} catch (Exception e) {
e.printStackTrace();
throw new WorkflowEngineException(BPM_META_DATA_FORMAT_ERROR);
throw new WorkflowEngineException(CONVERTOR_META_DATA_FORMAT_ERROR);
}
EndEvent endEvent = createEndEvent();
process.addFlowElement(endEvent);
@ -85,15 +80,15 @@ public class BpmTransformUtil {
}
public static SequenceFlow sequenceFlow(String from, String to, List<SequenceFlow> sequenceFlows, Map<String,
BpmJsonNode> childNodeMap, Process process) {
BpmnJsonNode> childNodeMap, Process process) {
SequenceFlow flow = new SequenceFlow();
String sequenceFlowId = id("sequenceFlow");
if (process.getFlowElement(from) != null && process.getFlowElement(from) instanceof ExclusiveGateway) {
BpmJsonNode childNode = childNodeMap.get(to);
BpmnJsonNode childNode = childNodeMap.get(to);
if (childNode != null) {
String parentId = childNode.getParentId();
if (StringUtils.isNotBlank(parentId)) {
BpmJsonNode parentNode = childNodeMap.get(parentId);
BpmnJsonNode parentNode = childNodeMap.get(parentId);
if (parentNode != null) {
if (BpmFlowNodeType.NODE_CONDITION.getType().equals(parentNode.getType())) {
sequenceFlowId = parentNode.getId();
@ -119,10 +114,13 @@ public class BpmTransformUtil {
return flow;
}
public static StartEvent createStartEvent(String id) {
public static StartEvent createStartEvent(String id, String formKey) {
StartEvent startEvent = new StartEvent();
startEvent.setId(id);
startEvent.setInitiator("applyUserId");
if (Objects.nonNull(formKey) && !formKey.trim().isEmpty()) {
startEvent.setFormKey(formKey);
}
return startEvent;
}
@ -133,8 +131,8 @@ public class BpmTransformUtil {
}
public static String create(String fromId, BpmJsonNode flowNode, Process process, BpmnModel bpmnModel,
List<SequenceFlow> sequenceFlows, Map<String, BpmJsonNode> childNodeMap) throws InvocationTargetException, IllegalAccessException {
public static String create(String fromId, BpmnJsonNode flowNode, Process process, BpmnModel bpmnModel,
List<SequenceFlow> sequenceFlows, Map<String, BpmnJsonNode> childNodeMap) throws InvocationTargetException, IllegalAccessException {
String nodeType = flowNode.getType();
if (BpmFlowNodeType.NODE_ROUTER.isEqual(nodeType)) {
return createExclusiveGatewayBuilder(fromId, flowNode, process, bpmnModel, sequenceFlows, childNodeMap);
@ -144,7 +142,7 @@ public class BpmTransformUtil {
incoming.put("incoming", Collections.singletonList(fromId));
String id = createTask(process, flowNode, sequenceFlows, childNodeMap);
// 如果当前任务还有后续任务则遍历创建后续任务
BpmJsonNode children = flowNode.getChildren();
BpmnJsonNode children = flowNode.getChildren();
if (Objects.nonNull(children) && StringUtils.isNotBlank(children.getId())) {
return create(id, children, process, bpmnModel, sequenceFlows, childNodeMap);
} else {
@ -156,14 +154,14 @@ public class BpmTransformUtil {
incoming.put("incoming", Collections.singletonList(fromId));
String id = createTask(process, flowNode, sequenceFlows, childNodeMap);
// 如果当前任务还有后续任务则遍历创建后续任务
BpmJsonNode children = flowNode.getChildren();
BpmnJsonNode children = flowNode.getChildren();
if (Objects.nonNull(children) && StringUtils.isNotBlank(children.getId())) {
return create(id, children, process, bpmnModel, sequenceFlows, childNodeMap);
} else {
return id;
}
} else {
throw new RuntimeException("未知节点类型: nodeType=" + nodeType);
throw new WorkflowEngineException(CONVERTOR_UNKNOW_NODE_TYPE, nodeType);
}
}
@ -174,9 +172,9 @@ public class BpmTransformUtil {
}
private static String createExclusiveGatewayBuilder(String formId, BpmJsonNode flowNode, Process process,
private static String createExclusiveGatewayBuilder(String formId, BpmnJsonNode flowNode, Process process,
BpmnModel bpmnModel, List<SequenceFlow> sequenceFlows,
Map<String, BpmJsonNode> childNodeMap) throws InvocationTargetException, IllegalAccessException {
Map<String, BpmnJsonNode> childNodeMap) throws InvocationTargetException, IllegalAccessException {
childNodeMap.put(flowNode.getId(), flowNode);
String name = flowNode.getName();
String exclusiveGatewayId = flowNode.getId();
@ -189,10 +187,10 @@ public class BpmTransformUtil {
if (Objects.isNull(flowNode.getBranches()) && Objects.isNull(flowNode.getChildren())) {
return exclusiveGatewayId;
}
List<BpmJsonNode> branches = flowNode.getBranches();
List<BpmnJsonNode> branches = flowNode.getBranches();
List<String> incoming = Lists.newArrayListWithCapacity(branches.size());
List<Map> conditions = Lists.newCopyOnWriteArrayList();
for (BpmJsonNode element : branches) {
for (BpmnJsonNode element : branches) {
if (!ObjectUtils.isEmpty(element.getProperty())) {
Boolean typeElse = element.getProperty().getDefaultCondition();
if (Boolean.TRUE.equals(typeElse)) {
@ -201,7 +199,7 @@ public class BpmTransformUtil {
}
childNodeMap.put(element.getId(), element);
BpmJsonNode children = element.getChildren();
BpmnJsonNode children = element.getChildren();
String nodeName = element.getName();
if (!ObjectUtils.isEmpty(element.getProperty()) && (Objects.isNull(children) || StringUtils.isBlank(children.getId()))) {
@ -246,11 +244,11 @@ public class BpmTransformUtil {
}
BpmJsonNode childNode = flowNode.getChildren();
BpmnJsonNode childNode = flowNode.getChildren();
if (Objects.nonNull(childNode) && StringUtils.isNotBlank(childNode.getId())) {
String parentId = childNode.getParentId();
BpmJsonNode parentChildNode = childNodeMap.get(parentId);
BpmnJsonNode parentChildNode = childNodeMap.get(parentId);
if (BpmFlowNodeType.NODE_ROUTER.getType().equals(parentChildNode.getType())) {
String endExId = parentChildNode.getId() + "end";
process.addFlowElement(createExclusiveGateWayEnd(endExId));
@ -263,7 +261,7 @@ public class BpmTransformUtil {
incomingObj.put("incoming", incoming);
FlowElement flowElement = bpmnModel.getFlowElement(incoming.get(0));
// 1.0 先进行边连接, 暂存 nextNode
BpmJsonNode nextNode = childNode.getChildren();
BpmnJsonNode nextNode = childNode.getChildren();
childNode.setChildren(null);
String identifier = endExId;
for (int i = 0; i < incoming.size(); i++) {
@ -315,8 +313,8 @@ public class BpmTransformUtil {
}
private static String createTask(Process process, BpmJsonNode flowNode, List<SequenceFlow> sequenceFlows,
Map<String, BpmJsonNode> childNodeMap) {
private static String createTask(Process process, BpmnJsonNode flowNode, List<SequenceFlow> sequenceFlows,
Map<String, BpmnJsonNode> childNodeMap) {
Map incomingJson = flowNode.getIncoming();
List<String> incoming = (List<String>) incomingJson.get("incoming");
// 自动生成id
@ -334,20 +332,19 @@ public class BpmTransformUtil {
createTaskListener.setImplementationType(IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
// FIXME 如果监听器想设置多个,这里还需要额外处理
createTaskListener.setImplementation("${engineTaskEventListener}");
userTask.setTaskListeners(Arrays.asList(createTaskListener));
List<FlowableListener> taskListeners = new ArrayList<>();
taskListeners.add(createTaskListener);
userTask.setTaskListeners(taskListeners);
if ("root".equalsIgnoreCase(id)) {
} else {
ArrayList<FlowableListener> listeners = new ArrayList<>();
FlowableListener activitiListener = new FlowableListener();
activitiListener.setEvent(ExecutionListener.EVENTNAME_START);
activitiListener.setImplementationType(IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
activitiListener.setImplementation("${engineExecutionStartListener}");
List<FlowableListener> executionListeners = new ArrayList<>();
createExecutionListener(EVENTNAME_START, executionListeners);
// End 事件,主要想用于多实例节点保留一条历史的任务信息, 后续研究过程中, 发现通过更优的解决方案, 所以注释掉下面一行
// createExecutionListener(EVENTNAME_END, executionListeners);
listeners.add(activitiListener);
userTask.setExecutionListeners(listeners);
if (!ObjectUtils.isEmpty(flowNode.getProperty()) && Boolean.TRUE.equals(flowNode.getProperty().getIsMultiTask())) {
BpmJsonNodeProperty property = flowNode.getProperty();
BpmnJsonNodeProperty property = flowNode.getProperty();
BpmFlowMultiMode mode = property.getMultiMode();
MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics =
@ -362,8 +359,7 @@ public class BpmTransformUtil {
// 设置多实例属性
userTask.setLoopCharacteristics(multiInstanceLoopCharacteristics);
if (BpmFlowMultiMode.OR.getType().equals(mode.getType())) {
multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfCompletedInstances" +
"/nrOfInstances > 0}");
multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfCompletedInstances > 0}");
} else if (BpmFlowMultiMode.AND.getType().equals(mode.getType())) {
multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfInstances == " +
"nrOfCompletedInstances}");
@ -373,8 +369,36 @@ public class BpmTransformUtil {
if (!ObjectUtils.isEmpty(flowNode.getProperty()) && flowNode.getProperty().getAllowSkip()) {
userTask.setSkipExpression("${" + BPM_ALLOW_SKIP_USER_TASK + "}");
}
if (!ObjectUtils.isEmpty(flowNode.getProperty()) && StringUtils.isNotBlank(flowNode.getProperty().getFormKey())) {
userTask.setFormKey(flowNode.getProperty().getFormKey());
}
}
}
return id;
}
/**
* 根据 Execution 事件类型, 创建 Execution 监听器
*
* @param eventName @see ExecutionListener
* @return
*/
private static void createExecutionListener(String eventName, List<FlowableListener> listeners) {
FlowableListener executionListener = new FlowableListener();
executionListener.setImplementationType(IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
executionListener.setEvent(eventName);
switch (eventName) {
case EVENTNAME_START:
executionListener.setImplementation("${engineExecutionStartListener}");
break;
case EVENTNAME_END:
executionListener.setImplementation("${engineExecutionEndListener}");
break;
default:
return;
}
listeners.add(executionListener);
}
}

View File

@ -1,5 +1,6 @@
package cn.axzo.workflow.core.conf;
import cn.axzo.workflow.core.service.engine.behavior.CustomActivityBehaviorFactory;
import com.google.common.collect.Lists;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.spring.SpringProcessEngineConfiguration;
@ -19,9 +20,16 @@ public class FlowableConfiguration {
@Bean
public EngineConfigurationConfigurer<SpringProcessEngineConfiguration> processEngineConfigurer(
ObjectProvider<FlowableEventListener> listeners) {
ObjectProvider<FlowableEventListener> listeners,
CustomActivityBehaviorFactory customActivityBehaviorFactory) {
return configuration -> {
configuration.setEventListeners(Lists.newArrayList(listeners));
configuration.setActivityBehaviorFactory(customActivityBehaviorFactory);
};
}
@Bean
public CustomActivityBehaviorFactory customActivityBehaviorFactory() {
return new CustomActivityBehaviorFactory();
}
}

View File

@ -37,7 +37,7 @@ public class BpmTaskCalculateDTO {
private String tenantId;
/**
* 流程运行实例
* 流程实例变量信息
*/
private Map<String, Object> variables;
}

View File

@ -32,5 +32,4 @@ public interface BpmActivityEventListener {
* @param event {@link FlowableActivityEventImpl}
*/
void onEvent(FlowableEvent event);
}

View File

@ -1,107 +0,0 @@
package cn.axzo.workflow.core.repository.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.Data;
import lombok.ToString;
import java.util.Date;
import java.util.Map;
@TableName(value = "bpm_process_instance_ext", autoResultMap = true)
@Data
@ToString(callSuper = true)
public class BpmProcessInstanceExtDO {
/**
* 编号自增
*/
@TableId
private Long id;
/**
* 流程实例的名字
* <p>
* 冗余 ProcessInstance name 属性用于筛选
*/
private String name;
/**
* 自定义的流程实例的编号
*/
private String customProInstId;
/**
* 流程实例的编号
* <p>
* 关联 ProcessInstance id 属性
*/
private String processInstanceId;
/**
* 流程定义的编号
* <p>
* 关联 ProcessDefinition id 属性
*/
private String processDefinitionId;
/**
* 流程分类
* <p>
* 冗余 ProcessDefinition category 属性 数据字典 bpm_model_category
*/
private String category;
/**
* 流程实例的状态
* <p>
* 枚举 {@link cn.axzo.workflow.core.common.enums.BpmProcessInstanceStatusEnum}
*/
private Integer status;
/**
* 流程实例的结果
* <p>
* 枚举 {@link cn.axzo.workflow.core.common.enums.BpmProcessInstanceResultEnum}
*/
private Integer result;
/**
* 创建时间
*/
private Date createAt;
/**
* 结束时间
* <p>
* 冗余 HistoricProcessInstance endTime 属性
*/
private Date endTime;
/**
* 提交的表单值
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private Map<String, Object> formVariables;
/**
* 发起人所在的工作台ID(企业/项目)
* <p>
* 使用租户字段隔离
*/
private String tenantId;
/**
* 发起人的身份ID
*/
private String startUserId;
/**
* 发起人的姓名
*/
private String startUserName;
/**
* 拓展字段业务自定义数据
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private Object ext;
}

View File

@ -8,10 +8,10 @@ import lombok.EqualsAndHashCode;
import lombok.ToString;
@EqualsAndHashCode(callSuper = true)
@TableName(value = "bpm_dict_data", autoResultMap = true)
@TableName(value = "ext_ax_dict", autoResultMap = true)
@Data
@ToString(callSuper = true)
public class BpmDictDataDO extends BaseOwnEntity<BpmDictDataDO> {
public class ExtAxDictDO extends BaseOwnEntity<ExtAxDictDO> {
/**
* 编号自增
*/
@ -19,9 +19,9 @@ public class BpmDictDataDO extends BaseOwnEntity<BpmDictDataDO> {
private Long id;
/**
* 字典排序
* 字典类型
*/
private Long sort;
private String type;
/**
* 字典标签
@ -33,27 +33,23 @@ public class BpmDictDataDO extends BaseOwnEntity<BpmDictDataDO> {
*/
private String value;
/**
* 字典类型
*/
private String dictType;
/**
* 颜色类型
*/
private String colorType;
/**
* css 样式
*/
private String cssClass;
/**
* 备注
*/
private String remark;
/**
* 字典排序
*/
private Long sort;
/**
* 状态0正常 1停用
*/
private Integer status;
/**
* 租户 ID
*/
private String tenantId;
}

View File

@ -1,98 +0,0 @@
package cn.axzo.workflow.core.repository.entity;
import cn.axzo.framework.data.mybatisplus.model.BaseOwnEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.*;
import org.flowable.engine.repository.ProcessDefinition;
import java.util.List;
import java.util.Map;
/**
* Bpm 流程定义的拓展表
* 主要解决 Activiti {@link ProcessDefinition} 不支持拓展字段所以新建拓展表
*
* @author 芋道源码
*/
@TableName(value = "bpm_process_definition_ext", autoResultMap = true)
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
// TODO 该表是否有用有待确定
public class ProcessDefinitionExtDO extends BaseOwnEntity<ProcessDefinitionExtDO> {
/**
* 编号
*/
@TableId
private Long id;
/**
* 流程定义的编号
*
* 关联 ProcessDefinition id 属性
*/
private String processDefinitionId;
/**
* 流程模型的编号
*
* 关联 Model id 属性
*/
private String modelId;
/**
* 描述
*/
private String description;
/**
* 表单类型
*
* 关联 {@link BpmModelFormTypeEnum}
*/
private Integer formType;
/**
* 动态表单编号
* 在表单类型为 {@link BpmModelFormTypeEnum#NORMAL}
*
* 关联 {@link BpmFormDO#getId()}
*/
private Long formId;
/**
* 表单的配置
* 在表单类型为 {@link BpmModelFormTypeEnum#NORMAL}
*
* 冗余 {@link BpmFormDO#getConf()}
*/
private String formConf;
/**
* 表单项的数组
* 在表单类型为 {@link BpmModelFormTypeEnum#NORMAL}
*
* 冗余 {@link BpmFormDO#getFields()} ()}
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private List<String> formFields;
/**
* 自定义表单的提交路径使用 Vue 的路由地址
* 在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM}
*/
private String formCustomCreatePath;
/**
* 自定义表单的查看路径使用 Vue 的路由地址
* 在表单类型为 {@link BpmModelFormTypeEnum#CUSTOM}
*/
private String formCustomViewPath;
private String tenantId;
/**
* 拓展字段业务自定义数据
* */
@TableField(typeHandler = JacksonTypeHandler.class)
private Map<String, Object> ext;
}

View File

@ -1,106 +0,0 @@
package cn.axzo.workflow.core.repository.entity;
import cn.axzo.framework.data.mybatisplus.model.BaseOwnEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
import java.util.Map;
@EqualsAndHashCode(callSuper = true)
@TableName(value = "bpm_task_ext", autoResultMap = true)
@Data
@ToString(callSuper = true)
public class TaskExtDO extends BaseOwnEntity<TaskExtDO> {
/**
* 编号自增
*/
@TableId
private Long id;
/**
* 任务的审批人
* <p>
* 冗余 Task assignee 属性
*/
private Long assigneeUserId;
/**
* 任务的名字
* <p>
* 冗余 Task name 属性为了筛选
*/
private String name;
/**
* 任务的编号
* <p>
* 关联 Task id 属性
*/
private String taskId;
/**
* 任务的结果
* <p>
* 枚举 {@link cn.axzo.workflow.core.common.enums.BpmProcessInstanceResultEnum}
*/
private Integer result;
/**
* 审批建议
*/
private String comment;
/**
* 任务的结束时间
* <p>
* 冗余 HistoricTaskInstance endTime 属性
*/
private Date endTime;
/**
* 流程实例的编号
* <p>
* 关联 ProcessInstance id 属性
*/
private String processInstanceId;
/**
* 流程定义的编号
* <p>
* 关联 ProcessDefinition id 属性
*/
private String processDefinitionId;
/**
* 租户ID
* <p>
* 企业或项目工作台ID
*/
private String tenantId;
/**
* 审批人的安心筑用户身份id
*/
private String userId;
/**
* 参与单位下的具体公司ID
*/
private Long companyId;
/**
* 审批人的姓名
*/
private String userName;
/**
* 审批人的组织架构信息, 施工使用
*/
private String organizationalStructureInfo;
/**
* 拓展字段业务自定义数据
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private Map<String, Object> ext;
}

View File

@ -1,18 +0,0 @@
package cn.axzo.workflow.core.repository.mapper;
import cn.axzo.workflow.core.repository.entity.ProcessDefinitionExtDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.List;
@Mapper
public interface BpmProcessDefinitionExtMapper extends BaseMapperX<ProcessDefinitionExtDO> {
default List<ProcessDefinitionExtDO> selectListByProcessDefinitionIds(Collection<String> processDefinitionIds) {
return selectList("process_definition_id", processDefinitionIds);
}
default ProcessDefinitionExtDO selectByProcessDefinitionId(String processDefinitionId) {
return selectOne("process_definition_id", processDefinitionId);
}
}

View File

@ -1,46 +0,0 @@
package cn.axzo.workflow.core.repository.mapper;
import cn.axzo.workflow.core.repository.entity.BpmProcessInstanceExtDO;
import cn.axzo.workflow.core.service.dto.request.process.BpmProcessInstanceMyPageReqVO;
import cn.axzo.workflow.core.service.dto.response.BpmPageResult;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.util.StringUtils;
@Mapper
public interface BpmProcessInstanceExtMapper extends BaseMapperX<BpmProcessInstanceExtDO> {
default BpmPageResult<BpmProcessInstanceExtDO> selectPage(BpmProcessInstanceMyPageReqVO reqVO) {
return selectPage(reqVO, new BpmLambdaQueryWrapperX<BpmProcessInstanceExtDO>()
.likeIfPresent(BpmProcessInstanceExtDO::getName, reqVO.getName())
.eqIfPresent(BpmProcessInstanceExtDO::getCustomProInstId, reqVO.getCustomProInstId())
.eqIfPresent(BpmProcessInstanceExtDO::getProcessInstanceId, reqVO.getProcessDefinitionId())
.eqIfPresent(BpmProcessInstanceExtDO::getCategory, reqVO.getCategory())
.eqIfPresent(BpmProcessInstanceExtDO::getStatus, reqVO.getStatus())
.eqIfPresent(BpmProcessInstanceExtDO::getResult, reqVO.getResult())
.eqIfPresent(BpmProcessInstanceExtDO::getTenantId, reqVO.getTenantId())
.eqIfPresent(BpmProcessInstanceExtDO::getStartUserId, reqVO.getUserId())
.eqIfPresent(BpmProcessInstanceExtDO::getResult, reqVO.getResult())
.betweenIfPresent(BpmProcessInstanceExtDO::getCreateAt, reqVO.getBeginCreateTime(),
reqVO.getEndCreateTime())
.orderByAsc(BpmProcessInstanceExtDO::getStatus)
.orderByDesc(BpmProcessInstanceExtDO::getCreateAt));
}
default BpmProcessInstanceExtDO selectByProcessInstanceId(String processInstanceId,
String tenantId) {
if (StringUtils.hasLength(tenantId)) {
return selectOne(BpmProcessInstanceExtDO::getProcessInstanceId, processInstanceId,
BpmProcessInstanceExtDO::getTenantId, tenantId);
} else {
return selectOne(BpmProcessInstanceExtDO::getProcessInstanceId, processInstanceId);
}
}
default void updateByProcessInstanceId(BpmProcessInstanceExtDO updateObj) {
update(updateObj, new QueryWrapper<BpmProcessInstanceExtDO>()
.eq("process_instance_id", updateObj.getProcessInstanceId()));
}
}

View File

@ -1,28 +0,0 @@
package cn.axzo.workflow.core.repository.mapper;
import cn.axzo.workflow.core.repository.entity.TaskExtDO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.List;
@Mapper
public interface BpmTaskExtMapper extends BaseMapperX<TaskExtDO> {
default void updateByTaskId(TaskExtDO entity) {
update(entity,
new LambdaQueryWrapper<TaskExtDO>().eq(TaskExtDO::getTaskId, entity.getTaskId()));
}
default List<TaskExtDO> selectListByTaskIds(Collection<String> taskIds) {
return selectList(TaskExtDO::getTaskId, taskIds);
}
default List<TaskExtDO> selectListByProcessInstanceId(String processInstanceId) {
return selectList("process_instance_id", processInstanceId);
}
default TaskExtDO selectByTaskId(String taskId) {
return selectOne(TaskExtDO::getTaskId, taskId);
}
}

View File

@ -1,10 +1,10 @@
package cn.axzo.workflow.core.repository.mapper;
import cn.axzo.workflow.core.repository.entity.BpmDictDataDO;
import cn.axzo.workflow.core.repository.entity.ExtAxDictDO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BpmDictDataMapper extends BaseMapper<BpmDictDataDO> {
public interface ExtAxDictMapper extends BaseMapper<ExtAxDictDO> {
}

View File

@ -0,0 +1,14 @@
package cn.axzo.workflow.core.repository.mapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
/**
* TODO
*
* @author wangli
* @since 2023/7/27 11:38
*/
public interface InfoMapper {
ArrayNode map(Object element);
}

View File

@ -1,46 +0,0 @@
package cn.axzo.workflow.core.service;
import cn.axzo.workflow.core.service.dto.request.model.BpmCategoryCreateDTO;
import cn.axzo.workflow.core.service.dto.request.model.BpmCategoryDTO;
import cn.axzo.workflow.core.service.dto.request.model.BpmCategoryUpdateDTO;
import cn.axzo.workflow.core.service.dto.response.model.BpmCategoryItemVo;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
/**
* Category的增删改查
*/
public interface BpmCategoryService {
/**
* 创建
*
* @param createDTO {@link #createBpmCategory(BpmCategoryCreateDTO)}
* @return insert record count
*/
int createBpmCategory(BpmCategoryCreateDTO createDTO);
/**
* 修改
*
* @param updateDTO {@link #updateBpmCategory(BpmCategoryUpdateDTO)}
* @return update record count
*/
int updateBpmCategory(BpmCategoryUpdateDTO updateDTO);
/**
* 删除
*
* @param id {@link #deleteBpmCategory(Long)}
* @return this row primary key
*/
int deleteBpmCategory(Long id);
/**
* 查询
*
* @param findDTO {@link #findBpmCategory(BpmCategoryDTO)}
* @return {@link BpmCategoryItemVo}
*/
Page<BpmCategoryItemVo> findBpmCategory(BpmCategoryDTO findDTO);
}

View File

@ -1,57 +0,0 @@
package cn.axzo.workflow.core.service;
import cn.axzo.workflow.core.service.dto.request.model.BpmModelCreateDTO;
import cn.axzo.workflow.core.service.dto.request.model.BpmModelBpmPageDTO;
import cn.axzo.workflow.core.service.dto.request.model.BpmModelUpdateDTO;
import cn.axzo.workflow.core.service.dto.response.BpmPageResult;
import cn.axzo.workflow.core.service.dto.response.model.BpmModelDetailVO;
import cn.axzo.workflow.core.service.dto.response.model.BpmModelPageItemVO;
import io.swagger.annotations.ApiOperation;
@ApiOperation("流程模型 - 部署流程")
public interface BpmModelService {
/**
* 获取流程模型的查询结果
* */
BpmPageResult<BpmModelPageItemVO> getModelPage(BpmModelBpmPageDTO modelPageDTO);
/**
* 创建流程,
* return modelId的主键
* */
String createBpmModel(BpmModelCreateDTO createDTO);
/**
* 获取模型
* */
BpmModelDetailVO getModelDetailById(String modelId);
/**
* 获取模型
* */
BpmModelDetailVO getModelDetailByKey(String modelKey);
/**
* 修改流程信息
* */
void updateBpmModel(BpmModelUpdateDTO updateDTO);
/**
* 部署模型
* return 部署完成的流程定义Id
* */
String deployBpmModelById(String modelId);
/**
* 部署模型
* return 部署完成的流程定义Id
* */
String deployBpmModelByKey(String modelKey);
/**
* 删除模型
* */
void deleteBpmModel(String id);
}

View File

@ -1,112 +0,0 @@
package cn.axzo.workflow.core.service;
import cn.axzo.workflow.core.service.dto.request.process.BpmProcessInstanceCancelDTO;
import cn.axzo.workflow.core.service.dto.request.process.BpmProcessInstanceCreateDTO;
import cn.axzo.workflow.core.service.dto.request.process.BpmProcessInstanceMyPageReqVO;
import cn.axzo.workflow.core.service.dto.request.process.CustomProcInstSearchDTO;
import cn.axzo.workflow.core.service.dto.response.BpmPageResult;
import cn.axzo.workflow.core.service.dto.response.process.BpmProcessInstancePageItemVO;
import cn.axzo.workflow.core.service.dto.response.process.BpmProcessInstanceVO;
import cn.axzo.workflow.core.service.dto.response.process.CustomProcInstVO;
import org.flowable.engine.delegate.event.FlowableCancelledEvent;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import javax.annotation.Nullable;
import javax.validation.Valid;
import java.util.List;
public interface BpmProcessInstanceService {
/**
* 发起审核
*/
String createProcessInstance(BpmProcessInstanceCreateDTO processInstanceCreateDTO);
/**
* 取消流程实例
*
* @return true or false, true mean's cancelled
*/
Boolean cancelProcessInstance(BpmProcessInstanceCancelDTO processInstanceCancelDTO);
/**
* 获得流程实例的分页 / 我发起的审批列表
*
* @param pageReqVO 分页请求
* @return 流程实例的分页
*/
BpmPageResult<BpmProcessInstancePageItemVO> getMyProcessInstancePage(@Valid BpmProcessInstanceMyPageReqVO pageReqVO);
BpmPageResult<List<CustomProcInstVO>> historicProcessInstancePage(CustomProcInstSearchDTO dto);
/**
* 获得流程实例
*
* @param businessKey 创建工作流实例时,业务传入的 businessKey
* @param tenantId 租户 ID,非必传
* @return 流程实例
*/
ProcessInstance getProcessInstanceByBusinessKey(String businessKey, @Nullable String tenantId,
@Nullable Boolean hasVariables);
/**
* 获得流程实例
*
* @param id 流程实例的编号
* @param tenantId 租户Id
* @param hasVariable 查询结果是否包含流程参数
* @return 流程实例, 租户Id不必传
*/
ProcessInstance getProcessInstance(String id, @Nullable String tenantId, @Nullable Boolean hasVariable);
/**
* 获得流程实例
*
* @param processInstanceId 流程实例的编号
* @param status 状态
* @link SuspensionState.ACTIVE.getStateCode()
*/
Boolean updateProcessStatus(String processInstanceId, String status);
/**
* 获得历史的流程实例
*
* @param id 流程实例的编号
* @return 历史的流程实例
*/
HistoricProcessInstance getHistoricProcessInstance(String id, String tenantId);
/**
* 获得流程实例 VO 信息
*
* @param processInstanceId 流程实例的编号
* @param businessKey 业务key
* @param tenantId 租户 ID
* @return 流程实例
*/
BpmProcessInstanceVO getProcessInstanceVO(String processInstanceId, String businessKey, String tenantId);
/**
* 创还能 ProcessInstance 扩展记录
*
* @param instance
*/
void createProcessInstanceExt(ProcessInstance instance);
/**
* 更新 ProcessInstance 扩展记录为取消
*
* @param instance
*/
void updateProcessInstanceExtComplete(ProcessInstance instance);
/**
* 更新 ProcessInstance 扩展记录为完成
*
* @param event
*/
void updateProcessInstanceExtCancel(FlowableCancelledEvent event);
}

View File

@ -1,56 +0,0 @@
package cn.axzo.workflow.core.service;
import cn.axzo.workflow.core.service.dto.request.task.BpmTaskAuditDTO;
import cn.axzo.workflow.core.service.dto.request.task.BpmTaskTodoBpmPageDTO;
import cn.axzo.workflow.core.service.dto.response.BpmPageResult;
import cn.axzo.workflow.core.service.dto.response.task.BpmTaskTodoPageItemRespVO;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import java.util.List;
public interface BpmTaskService {
/**
* 待审核列表
* */
BpmPageResult<BpmTaskTodoPageItemRespVO> getTodoTaskPage(BpmTaskTodoBpmPageDTO taskTodoPageDTO);
/**
* 已完成的审批列表
*
* @return*/
BpmPageResult<BpmTaskTodoPageItemRespVO> getDoneTaskPage(BpmTaskTodoBpmPageDTO taskDonePageD);
/**
* 同意
* */
void approveTask(BpmTaskAuditDTO taskAuditDTO);
/**
* 拒绝
* */
void rejectTask(BpmTaskAuditDTO taskAuditDTO);
/**
* 获取历史已审批的列表详情
*/
List<HistoricTaskInstance> getTaskListByProcessInstanceId(String processInstanceId);
/**
* 获取实例正在审核的人列表
*
* FIXME 该接口 web 不能正常响应
* */
List<Task> getActiveTasksByProcessInstanceId(String processInstanceId);
/**
* 获得流程任务列表
* FIXME 该接口 web 不能正常响应
* @param processInstanceIds 流程实例的编号数组
* @return 流程任务列表
*/
List<Task> getTasksByProcessInstanceIds(List<String> processInstanceIds);
}

View File

@ -1,13 +1,14 @@
package cn.axzo.workflow.core.service;
import cn.axzo.workflow.core.service.dto.request.process.BpmProcessDefinitionPageDTO;
import cn.axzo.workflow.core.service.dto.request.bpmn.definition.BpmnProcessDefinitionUpdateDTO;
import cn.axzo.workflow.core.service.dto.request.bpmn.process.BpmnProcessDefinitionPageDTO;
import cn.axzo.workflow.core.service.dto.response.BpmPageResult;
import cn.axzo.workflow.core.service.dto.response.process.BpmProcessDefinitionPageItemRespVO;
import cn.axzo.workflow.core.service.dto.response.bpmn.process.BpmnProcessDefinitionVO;
import org.flowable.common.engine.impl.db.SuspensionState;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ProcessDefinition;
public interface BpmProcessDefinitionService {
public interface BpmnProcessDefinitionService {
/**
@ -16,11 +17,15 @@ public interface BpmProcessDefinitionService {
*/
String createProcessDefinition(Model model, byte[] bpmnBytes);
void updateProcessDefinition(String processModelId, byte[] bpmnBytes);
void updateProcessDefinition(String processModelId, String bpmnXml);
/**
* 获取活跃的流程定义分页
* */
BpmPageResult<BpmProcessDefinitionPageItemRespVO> getProcessDefinitionPage(BpmProcessDefinitionPageDTO request);
*/
BpmPageResult<BpmnProcessDefinitionVO> getProcessDefinitionPage(BpmnProcessDefinitionPageDTO request);
/**
* 获得编号对应的 ProcessDefinition
@ -28,7 +33,7 @@ public interface BpmProcessDefinitionService {
* @param id 编号
* @return 流程定义
*/
ProcessDefinition getProcessDefinition(String id);
BpmnProcessDefinitionVO getProcessDefinition(String id);
/**
* 获得 deploymentId 对应的 ProcessDefinition
@ -44,7 +49,7 @@ public interface BpmProcessDefinitionService {
* @param key 流程定义的标识
* @return 流程定义
*/
ProcessDefinition getActiveProcessDefinitionByKey(String key);
BpmnProcessDefinitionVO getActiveProcessDefinitionByKey(String key);
/**
* 挂起/激活流程
@ -60,4 +65,5 @@ public interface BpmProcessDefinitionService {
*/
String getActiveProcessDefinitionId(String tenantId, String category);
void updateProcessDefinition(BpmnProcessDefinitionUpdateDTO dto);
}

View File

@ -0,0 +1,94 @@
package cn.axzo.workflow.core.service;
import cn.axzo.workflow.core.service.dto.request.bpmn.process.*;
import cn.axzo.workflow.core.service.dto.response.BpmPageResult;
import cn.axzo.workflow.core.service.dto.response.bpmn.process.BpmnProcessInstancePageItemVO;
import cn.axzo.workflow.core.service.dto.response.bpmn.process.BpmnProcessInstanceVO;
import cn.axzo.workflow.core.service.dto.response.bpmn.process.HistoricProcessInstanceVO;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.form.api.FormInfo;
import javax.annotation.Nullable;
import javax.validation.Valid;
import java.util.List;
public interface BpmnProcessInstanceService {
/**
* 发起审核
*/
String createProcessInstance(BpmnProcessInstanceCreateDTO processInstanceCreateDTO);
String createProcessInstanceWithForm(BpmnProcessInstanceCreateWithFormDTO createWithFormDTO);
FormInfo getStartFormModel(String processDefinitionId, String processInstanceId);
/**
* 取消流程实例
*
* @return true or false, true mean's cancelled
*/
Boolean cancelProcessInstance(BpmnProcessInstanceCancelDTO processInstanceCancelDTO);
/**
* 获得流程实例的分页 / 我发起的审批列表
*
* @param pageReqVO 分页请求
* @return 流程实例的分页
*/
BpmPageResult<BpmnProcessInstancePageItemVO> getMyProcessInstancePage(@Valid BpmnProcessInstanceMyPageReqVO pageReqVO);
/**
* 获得流程实例
*
* @param businessKey 创建工作流实例时,业务传入的 businessKey
* @param tenantId 租户 ID,非必传
* @return 流程实例
*/
HistoricProcessInstance getProcessInstanceByBusinessKey(String businessKey, @Nullable String tenantId,
@Nullable Boolean hasVariables);
/**
* 获得流程实例
*
* @param id 流程实例的编号
* @param tenantId 租户Id
* @param hasVariable 查询结果是否包含流程参数
* @return 流程实例, 租户Id不必传
*/
HistoricProcessInstance getProcessInstance(String id, @Nullable String tenantId, @Nullable Boolean hasVariable);
/**
* 获得流程实例
*
* @param processInstanceId 流程实例的编号
* @param status 状态
* @link SuspensionState.ACTIVE.getStateCode()
*/
Boolean updateProcessStatus(String processDefinitionId, Integer status);
/**
* 获得历史的流程实例
*
* @param id 流程实例的编号
* @return 历史的流程实例
*/
HistoricProcessInstance getHistoricProcessInstance(String id, String tenantId);
/**
* 获得流程实例 VO 信息
*
* @param processInstanceId 流程实例的编号
* @param businessKey 业务key
* @param tenantId 租户 ID
* @return 流程实例
*/
BpmnProcessInstanceVO getProcessInstanceVO(BpmnProcessInstanceQueryDTO dto);
void deleteProcessInstance(String id, String reason);
ObjectNode getProcessInstanceGraphical(String processInstanceId, @Nullable String tenantId);
BpmPageResult<List<HistoricProcessInstanceVO>> historicProcessInstancePage(HistoricProcessInstanceSearchDTO dto);
}

View File

@ -0,0 +1,63 @@
package cn.axzo.workflow.core.service;
import cn.axzo.workflow.core.service.dto.request.bpmn.model.BpmnModelCreateDTO;
import cn.axzo.workflow.core.service.dto.request.bpmn.model.BpmnModelSearchDTO;
import cn.axzo.workflow.core.service.dto.request.bpmn.model.BpmnModelUpdateDTO;
import cn.axzo.workflow.core.service.dto.response.BpmPageResult;
import cn.axzo.workflow.core.service.dto.response.bpmn.model.BpmnModelDetailVO;
import cn.axzo.workflow.core.service.dto.response.form.model.FormModelBaseVO;
import io.swagger.annotations.ApiOperation;
import javax.annotation.Nullable;
@ApiOperation("流程模型 - 部署流程")
public interface BpmnProcessModelService {
/**
* 获取流程模型的查询结果
*/
BpmPageResult<FormModelBaseVO> getModelPage(BpmnModelSearchDTO dto);
/**
* 创建流程,
* return modelId的主键
*/
String createBpmModel(BpmnModelCreateDTO dto);
String createBpmModelWithXml(String fileUrl);
/**
* 获取模型
*/
BpmnModelDetailVO getById(String processModelId, @Nullable String tenantId);
/**
* 获取模型
*/
BpmnModelDetailVO getByKey(String processModelKey, @Nullable String tenantId);
/**
* 修改流程信息
*/
void updateBpmModel(BpmnModelUpdateDTO dto);
/**
* 部署模型
* return 部署完成的流程定义Id
*/
String deployBpmModelById(String processModelId, @Nullable String tenantId);
/**
* 部署模型
* return 部署完成的流程定义Id
*/
String deployBpmModelByKey(String processModelKey, @Nullable String tenantId);
/**
* 删除模型
*/
void deleteBpmModelById(String processModelId, @Nullable String tenantId);
void deleteBpmModelByKey(String processModelKey, @Nullable String tenantId);
}

View File

@ -0,0 +1,77 @@
package cn.axzo.workflow.core.service;
import cn.axzo.workflow.core.service.dto.request.bpmn.task.BpmnTaskAssigneeDTO;
import cn.axzo.workflow.core.service.dto.request.bpmn.task.BpmnTaskAuditDTO;
import cn.axzo.workflow.core.service.dto.request.bpmn.task.BpmnTaskCommentDTO;
import cn.axzo.workflow.core.service.dto.request.bpmn.task.BpmnTaskTodoPageSearchDTO;
import cn.axzo.workflow.core.service.dto.response.BpmPageResult;
import cn.axzo.workflow.core.service.dto.response.bpmn.task.*;
import org.flowable.form.api.FormInfo;
import java.util.List;
public interface BpmnTaskService {
/**
* 待审核列表
*/
BpmPageResult<BpmnTaskTodoPageItemVO> getTodoTaskPage(BpmnTaskTodoPageSearchDTO dto);
/**
* 已完成的审批列表
*
* @return
*/
BpmPageResult<BpmnTaskDonePageItemVO> getDoneTaskPage(BpmnTaskTodoPageSearchDTO dto);
/**
* 同意
*/
void approveTask(BpmnTaskAuditDTO taskAuditDTO);
/**
* 拒绝
*/
void rejectTask(BpmnTaskAuditDTO taskAuditDTO);
/**
* 获取历史已审批的列表详情
* <p>
* 扁平的任务列表
*/
List<BpmnHistoricTaskInstanceVO> getHistoricTaskListByProcessInstanceId(String processInstanceId, String tenantId);
/**
* 获取历史已审批的列表详情
* <p>
* 任务根据定义 ID 分组
*
* @param processInstanceId
* @param tenantId
* @return
*/
List<BpmnHistoricTaskInstanceGroupVO> getHistoricTaskListGroupByProcessInstanceId(String processInstanceId,
String tenantId);
/**
* 获取实例正在审核的人列表
* <p>
*/
List<BpmnTaskInstanceVO> getActiveTasksByProcessInstanceId(String processInstanceId, String tenantId);
FormInfo getTaskFormModel(String taskId);
/**
* 修改审批任务审批人
* <p>
* 注意:不是委派给其他人
*
* @param dto
*/
void assigneeTask(BpmnTaskAssigneeDTO dto);
void commentTask(BpmnTaskCommentDTO dto);
}

View File

@ -0,0 +1,55 @@
package cn.axzo.workflow.core.service;
import cn.axzo.workflow.core.service.dto.request.category.CategoryCreateDTO;
import cn.axzo.workflow.core.service.dto.request.category.CategorySearchDTO;
import cn.axzo.workflow.core.service.dto.request.category.CategoryUpdateDTO;
import cn.axzo.workflow.core.service.dto.response.category.CategoryItemVO;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
/**
* Category的增删改查
*/
public interface CategoryService {
/**
* 创建
*
* @param createDTO {@link #createCategory(CategoryCreateDTO)}
* @return insert record count
*/
int createCategory(CategoryCreateDTO createDTO);
/**
* 修改
*
* @param updateDTO {@link #updateCategory(CategoryUpdateDTO)}
* @return update record count
*/
int updateCategory(CategoryUpdateDTO updateDTO);
/**
* 删除
*
* @param id {@link #deleteCategory(Long)}
* @return this row primary key
*/
int deleteCategory(Long id);
/**
* 查询
*
* @param findDTO {@link #findCategory(CategorySearchDTO)}
* @return {@link CategoryItemVO}
*/
Page<CategoryItemVO> findCategory(CategorySearchDTO findDTO);
/**
* 更新字典状态
*
* @param id 字典 ID
* @param state
* @return
*/
Boolean updateState(Long id, Boolean state);
}

View File

@ -0,0 +1,20 @@
package cn.axzo.workflow.core.service;
import cn.axzo.workflow.core.service.dto.request.form.definition.FormDefinitionUpdateDTO;
import cn.axzo.workflow.core.service.dto.response.form.definition.FormDefinitionVO;
import javax.annotation.Nullable;
/**
* 表单定义相关服务接口
*
* @author wangli
* @since 2023/7/19 16:46
*/
public interface FormDefinitionService {
FormDefinitionVO get(String formModeId, @Nullable String tenantId);
void updateFormDefinition(FormDefinitionUpdateDTO dto);
}

View File

@ -0,0 +1,19 @@
package cn.axzo.workflow.core.service;
import cn.axzo.workflow.core.service.dto.request.form.instance.FormContentUpdateDTO;
/**
* 表单实例相关接口
*
* @author wangli
* @since 2023/7/21 15:19
*/
public interface FormInstanceService {
/**
* 更新表单填写的数据
*
* @param dto
*/
void updateFormContent(FormContentUpdateDTO dto);
}

View File

@ -0,0 +1,36 @@
package cn.axzo.workflow.core.service;
import cn.axzo.workflow.core.service.dto.request.bpmn.model.BpmnModelSearchDTO;
import cn.axzo.workflow.core.service.dto.request.form.model.FormModelCreateDTO;
import cn.axzo.workflow.core.service.dto.request.form.model.FormModelUpdateDTO;
import cn.axzo.workflow.core.service.dto.response.BpmPageResult;
import cn.axzo.workflow.core.service.dto.response.form.model.FormModelBaseVO;
import javax.annotation.Nullable;
/**
* TODO
*
* @author wangli
* @since 2023/7/24 23:47
*/
public interface FormModelService {
String createFormModel(FormModelCreateDTO dto);
void updateFormModel(FormModelUpdateDTO dto);
BpmPageResult<FormModelBaseVO> getModelPage(BpmnModelSearchDTO dto);
FormModelBaseVO getById(String formModelId, @Nullable String tenantId);
FormModelBaseVO getByKey(String formModelKey, @Nullable String tenantId);
String deployFormModelById(String formModelId, @Nullable String tenantId);
String deployFormModelByKey(String formModelKey, @Nullable String tenantId);
void deleteFormModelById(String formModelId, @Nullable String tenantId);
void deleteFormModelByKey(String formModelKey, @Nullable String tenantId);
}

View File

@ -1,24 +0,0 @@
package cn.axzo.workflow.core.service.converter;
import cn.axzo.workflow.core.repository.entity.BpmDictDataDO;
import cn.axzo.workflow.core.service.dto.response.model.BpmCategoryItemVo;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import java.util.Arrays;
import static org.mapstruct.NullValueCheckStrategy.ALWAYS;
@Mapper(
componentModel = "spring",
nullValueCheckStrategy = ALWAYS,
imports = Arrays.class
)
public interface BpmCategoryConverter extends EntityConverter<BpmCategoryItemVo, BpmDictDataDO>{
@Mapping(target = "id", source = "category.id")
@Mapping(target = "dictType", source = "category.dictType")
@Mapping(target = "label", source = "category.label")
@Mapping(target = "value", source = "category.value")
BpmCategoryItemVo toVo(BpmDictDataDO category);
}

View File

@ -1,27 +0,0 @@
package cn.axzo.workflow.core.service.converter;
import cn.axzo.workflow.core.service.dto.response.model.BpmModelDetailVO;
import org.flowable.engine.repository.Model;
import org.springframework.util.ObjectUtils;
public class BpmModelConverter {
public static BpmModelDetailVO convert(Model model) {
if (ObjectUtils.isEmpty(model)) {
return null;
}
BpmModelDetailVO detailVO = new BpmModelDetailVO();
detailVO.setCreateTime(model.getCreateTime());
detailVO.setKey(model.getKey());
detailVO.setLastUpdateTime(model.getLastUpdateTime());
detailVO.setCreateTime(model.getCreateTime());
detailVO.setLastUpdateTime(model.getLastUpdateTime());
detailVO.setCategory(model.getCategory());
detailVO.setTenantId(model.getTenantId());
detailVO.setVersion(model.getVersion());
detailVO.setName(model.getName());
return detailVO;
}
}

View File

@ -1,59 +0,0 @@
package cn.axzo.workflow.core.service.converter;
import cn.axzo.workflow.core.common.utils.BpmCollectionUtils;
import cn.axzo.workflow.core.repository.entity.ProcessDefinitionExtDO;
import cn.axzo.workflow.core.service.dto.response.process.BpmProcessDefinitionPageItemRespVO;
import org.flowable.common.engine.impl.db.SuspensionState;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.springframework.beans.BeanUtils;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class BpmProcessDefinitionConvert {
public static List<BpmProcessDefinitionPageItemRespVO> convertList(List<ProcessDefinition> list,
Map<String, Deployment> deploymentMap,
Map<String, ProcessDefinitionExtDO> processDefinitionDOMap,
Integer version) {
return BpmCollectionUtils.convertList(list, definition -> {
Deployment deployment =
definition.getDeploymentId() != null ? deploymentMap.get(definition.getDeploymentId())
: null;
ProcessDefinitionExtDO definitionDO = processDefinitionDOMap.get(definition.getId());
return convert(definition, deployment, definitionDO, version);
});
}
public static BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean, Deployment deployment,
ProcessDefinitionExtDO processDefinitionExtDO, Integer version) {
BpmProcessDefinitionPageItemRespVO respVO = convert(bean);
respVO.setSyncModelPool(!Objects.nonNull(version) || bean.getVersion() <= version);
respVO.setSuspensionState(bean.isSuspended() ? SuspensionState.SUSPENDED.getStateCode()
: SuspensionState.ACTIVE.getStateCode());
if (deployment != null) {
respVO.setDeploymentTime(deployment.getDeploymentTime());
}
BeanUtils.copyProperties(processDefinitionExtDO, respVO);
return respVO;
}
public static BpmProcessDefinitionPageItemRespVO convert(ProcessDefinition bean) {
if ( bean == null ) {
return null;
}
BpmProcessDefinitionPageItemRespVO bpmProcessDefinitionPageItemRespVO = new BpmProcessDefinitionPageItemRespVO();
bpmProcessDefinitionPageItemRespVO.setId( bean.getId() );
bpmProcessDefinitionPageItemRespVO.setVersion( bean.getVersion() );
bpmProcessDefinitionPageItemRespVO.setName( bean.getName() );
bpmProcessDefinitionPageItemRespVO.setDescription( bean.getDescription() );
bpmProcessDefinitionPageItemRespVO.setCategory( bean.getCategory() );
return bpmProcessDefinitionPageItemRespVO;
}
}

View File

@ -1,133 +0,0 @@
package cn.axzo.workflow.core.service.converter;
import cn.axzo.workflow.core.repository.entity.BpmProcessInstanceExtDO;
import cn.axzo.workflow.core.service.dto.response.BpmPageResult;
import cn.axzo.workflow.core.service.dto.response.process.BpmProcessInstancePageItemVO;
import org.flowable.task.api.Task;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class BpmProcessInstanceConvert {
public static BpmPageResult<BpmProcessInstancePageItemVO> convertPage(BpmPageResult<BpmProcessInstanceExtDO> page,
Map<String, List<Task>> taskMap) {
List<BpmProcessInstancePageItemVO> list = convertList(page.getList());
list.forEach(respVO -> respVO.setTasks(convertList2(taskMap.get(respVO.getId()))));
return new BpmPageResult<>(list, page.getTotal());
}
public static List<BpmProcessInstancePageItemVO> convertList(List<BpmProcessInstanceExtDO> list){
if ( list == null ) {
return null;
}
List<BpmProcessInstancePageItemVO> list1 = new ArrayList<BpmProcessInstancePageItemVO>( list.size() );
for ( BpmProcessInstanceExtDO bpmProcessInstanceExtDO : list ) {
list1.add( convert( bpmProcessInstanceExtDO ) );
}
return list1;
}
public static BpmProcessInstancePageItemVO convert(BpmProcessInstanceExtDO bean){
if ( bean == null ) {
return null;
}
BpmProcessInstancePageItemVO bpmProcessInstancePageItemRespVO = new BpmProcessInstancePageItemVO();
bpmProcessInstancePageItemRespVO.setId( bean.getProcessInstanceId() );
bpmProcessInstancePageItemRespVO.setCustomProInstId( bean.getCustomProInstId() );
bpmProcessInstancePageItemRespVO.setName( bean.getName() );
bpmProcessInstancePageItemRespVO.setProcessDefinitionId( bean.getProcessDefinitionId() );
bpmProcessInstancePageItemRespVO.setCategory( bean.getCategory() );
bpmProcessInstancePageItemRespVO.setStatus( bean.getStatus() );
bpmProcessInstancePageItemRespVO.setResult(bean.getResult());
bpmProcessInstancePageItemRespVO.setCreateTime(bean.getCreateAt());
bpmProcessInstancePageItemRespVO.setEndTime(bean.getEndTime());
bpmProcessInstancePageItemRespVO.setStartUserName( bean.getStartUserName() );
return bpmProcessInstancePageItemRespVO;
}
public static List<BpmProcessInstancePageItemVO.Task> convertList2(List<Task> tasks){
if ( tasks == null ) {
return null;
}
List<BpmProcessInstancePageItemVO.Task> list = new ArrayList<BpmProcessInstancePageItemVO.Task>( tasks.size() );
for ( Task task : tasks ) {
list.add( taskToTask( task ) );
}
return list;
}
// default BpmProcessInstanceVO convert2(HistoricProcessInstance processInstance, BpmProcessInstanceExtDO processInstanceExt,
// ProcessDefinition processDefinition, BpmProcessDefinitionExtDO processDefinitionExt,
// String bpmnXml, AdminUserRespDTO startUser, DeptRespDTO dept) {
// BpmProcessInstanceRespVO respVO = convert2(processInstance);
// copyTo(processInstanceExt, respVO);
// // definition
// respVO.setProcessDefinition(convert2(processDefinition));
// copyTo(processDefinitionExt, respVO.getProcessDefinition());
// respVO.getProcessDefinition().setBpmnXml(bpmnXml);
// // user
//// if (startUser != null) {
//// respVO.setStartUser(convert2(startUser));
//// if (dept != null) {
//// respVO.getStartUser().setDeptName(dept.getName());
//// }
//// }
//
// String startUserId = processInstance.getStartUserId();
// String[] s = startUserId.split("_");
// Long startWorkspaceId = Long.valueOf(s[0]);
// Long startIdentityId = Long.valueOf(s[1]);
//
// BpmProcessInstanceRespVO.User startUser1 = new BpmProcessInstanceRespVO.User();
// startUser1.setWorkspaceId(startWorkspaceId);
// startUser1.setIdentityId(startIdentityId);
// respVO.setStartUser(startUser1);
//
// return respVO;
// }
//
// BpmProcessInstanceRespVO convert2(HistoricProcessInstance bean);
//
// @Mapping(source = "from.id", target = "to.id", ignore = true)
// void copyTo(BpmProcessInstanceExtDO from, @MappingTarget BpmProcessInstanceRespVO to);
//
// BpmProcessInstanceRespVO.ProcessDefinition convert2(ProcessDefinition bean);
//
// @Mapping(source = "from.id", target = "to.id", ignore = true)
// void copyTo(BpmProcessDefinitionExtDO from, @MappingTarget BpmProcessInstanceRespVO.ProcessDefinition to);
//
// BpmProcessInstanceRespVO.User convert2(AdminUserRespDTO bean);
//
// default BpmProcessInstanceResultEvent convert(Object source, HistoricProcessInstance instance, Integer result) {
// BpmProcessInstanceResultEvent event = new BpmProcessInstanceResultEvent(source);
// event.setId(instance.getId());
// event.setProcessDefinitionKey(instance.getProcessDefinitionKey());
// event.setBusinessKey(instance.getBusinessKey());
// event.setResult(result);
// return event;
// }
public static BpmProcessInstancePageItemVO.Task taskToTask(Task task) {
if ( task == null ) {
return null;
}
BpmProcessInstancePageItemVO.Task task1 = new BpmProcessInstancePageItemVO.Task();
task1.setId( task.getId() );
task1.setName( task.getName() );
return task1;
}
}

View File

@ -1,119 +0,0 @@
package cn.axzo.workflow.core.service.converter;
import cn.axzo.workflow.core.common.utils.BpmCollectionUtils;
import cn.axzo.workflow.core.repository.entity.TaskExtDO;
import cn.axzo.workflow.core.service.dto.response.task.BpmTaskDonePageItemRespVO;
import cn.axzo.workflow.core.service.dto.response.task.BpmTaskTodoPageItemRespVO;
import cn.hutool.core.util.StrUtil;
import org.flowable.common.engine.impl.db.SuspensionState;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.service.delegate.DelegateTask;
import org.mapstruct.factory.Mappers;
import org.springframework.beans.BeanUtils;
import java.util.List;
import java.util.Map;
public class BpmTaskConvert {
public static TaskExtDO convertTaskExt(DelegateTask task) {
String assignee = task.getAssignee();
TaskExtDO taskExtDO = new TaskExtDO();
taskExtDO.setTaskId(task.getId());
taskExtDO.setTenantId(task.getTenantId());
taskExtDO.setUserId(assignee);
taskExtDO.setProcessDefinitionId(task.getProcessDefinitionId());
taskExtDO.setProcessInstanceId(task.getProcessInstanceId());
taskExtDO.setName(task.getName());
taskExtDO.setCreateAt(task.getCreateTime());
taskExtDO.setUserName(task.getOwner());
return taskExtDO;
}
public static List<BpmTaskDonePageItemRespVO> convertList2(List<HistoricTaskInstance> tasks,
Map<String, TaskExtDO> bpmTaskExtDOMap,
Map<String, HistoricProcessInstance> historicProcessInstanceMap) {
return BpmCollectionUtils.convertList(tasks, task -> {
BpmTaskDonePageItemRespVO respVO = convert2(task);
TaskExtDO taskExtDO = bpmTaskExtDOMap.get(task.getId());
BeanUtils.copyProperties(taskExtDO, respVO);
HistoricProcessInstance processInstance = historicProcessInstanceMap.get(
task.getProcessInstanceId());
if (processInstance != null) {
String startUserId = processInstance.getStartUserId();
//convert
BpmTaskTodoPageItemRespVO.ProcessInstance processInstance1 = new BpmTaskTodoPageItemRespVO.ProcessInstance();
processInstance1.setId(processInstance.getId());
processInstance1.setName(processInstance.getName());
processInstance1.setProcessDefinitionId(processInstance.getProcessDefinitionId());
processInstance1.setStartUserId(startUserId);
respVO.setProcessInstance(processInstance1);
}
return respVO;
});
}
public static BpmTaskDonePageItemRespVO convert2(HistoricTaskInstance bean) {
if ( bean == null ) {
return null;
}
BpmTaskDonePageItemRespVO bpmTaskDonePageItemRespVO = new BpmTaskDonePageItemRespVO();
bpmTaskDonePageItemRespVO.setId( bean.getId() );
bpmTaskDonePageItemRespVO.setName( bean.getName() );
bpmTaskDonePageItemRespVO.setClaimTime( bean.getClaimTime() );
bpmTaskDonePageItemRespVO.setCreateTime( bean.getCreateTime() );
bpmTaskDonePageItemRespVO.setEndTime( bean.getEndTime() );
bpmTaskDonePageItemRespVO.setDurationInMillis( bean.getDurationInMillis() );
return bpmTaskDonePageItemRespVO;
}
BpmTaskConvert INSTANCE = Mappers.getMapper(BpmTaskConvert.class);
public static List<BpmTaskTodoPageItemRespVO> convertList1(List<Task> tasks,
Map<String, ProcessInstance> processInstanceMap) {
return BpmCollectionUtils.convertList(tasks, task -> {
BpmTaskTodoPageItemRespVO respVO = convert1(task);
ProcessInstance processInstance = processInstanceMap.get(task.getProcessInstanceId());
if (processInstance != null) {
//convert
BpmTaskTodoPageItemRespVO.ProcessInstance processInstance1 = new BpmTaskTodoPageItemRespVO.ProcessInstance();
processInstance1.setId(processInstance.getId());
processInstance1.setName(
StrUtil.isBlank(processInstance.getName()) ? processInstance.getProcessDefinitionName()
: processInstance.getName());
processInstance1.setProcessDefinitionId(processInstance.getProcessDefinitionId());
processInstance1.setStartUserId(processInstance.getStartUserId());
respVO.setProcessInstance(processInstance1);
}
return respVO;
});
}
public static BpmTaskTodoPageItemRespVO convert1(Task bean) {
if ( bean == null ) {
return null;
}
BpmTaskTodoPageItemRespVO bpmTaskTodoPageItemRespVO = new BpmTaskTodoPageItemRespVO();
bpmTaskTodoPageItemRespVO.setSuspensionState( convertSuspendedToSuspensionState( bean.isSuspended() ) );
bpmTaskTodoPageItemRespVO.setId( bean.getId() );
bpmTaskTodoPageItemRespVO.setName( bean.getName() );
bpmTaskTodoPageItemRespVO.setClaimTime( bean.getClaimTime() );
bpmTaskTodoPageItemRespVO.setCreateTime( bean.getCreateTime() );
return bpmTaskTodoPageItemRespVO;
}
public static Integer convertSuspendedToSuspensionState(boolean suspended) {
return suspended ? SuspensionState.SUSPENDED.getStateCode() :
SuspensionState.ACTIVE.getStateCode();
}
}

View File

@ -0,0 +1,34 @@
package cn.axzo.workflow.core.service.converter;
import cn.axzo.workflow.core.service.dto.response.bpmn.task.BpmnHistoricCommentVO;
import org.flowable.engine.task.Comment;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import java.util.Arrays;
import static org.mapstruct.NullValueCheckStrategy.ALWAYS;
/**
* 任务评论 MapStruts 转换器
*
* @author wangli
* @since 2023/7/30 13:30
*/
@Mapper(
componentModel = "spring",
nullValueCheckStrategy = ALWAYS,
imports = Arrays.class
)
public interface BpmnHistoricCommentConverter extends EntityConverter<BpmnHistoricCommentVO, Comment> {
@Mapping(target = "id", source = "id")
@Mapping(target = "type", source = "type")
@Mapping(target = "userId", source = "userId")
@Mapping(target = "taskId", source = "taskId")
@Mapping(target = "createTime", source = "time")
@Mapping(target = "processInstanceId", source = "processInstanceId")
@Mapping(target = "message", source = "fullMessage")
@Override
BpmnHistoricCommentVO toVo(Comment entity);
}

View File

@ -0,0 +1,44 @@
package cn.axzo.workflow.core.service.converter;
import cn.axzo.workflow.core.service.dto.response.bpmn.process.BpmnProcessDefinitionVO;
import cn.axzo.workflow.core.service.dto.response.bpmn.process.BpmnProcessInstanceVO;
import org.flowable.engine.history.HistoricProcessInstance;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import java.util.Arrays;
import static org.mapstruct.NullValueCheckStrategy.ALWAYS;
/**
* 历史流程实例的 MapStruts 转换器
*
* @author wangli
* @since 2023/7/26 16:01
*/
@Mapper(
componentModel = "spring",
nullValueCheckStrategy = ALWAYS,
imports = Arrays.class
)
public interface BpmnHistoricProcessInstanceConverter extends EntityConverter<BpmnProcessInstanceVO,
HistoricProcessInstance> {
@Mapping(target = "id", source = "id")
@Mapping(target = "name", source = "name")
@Mapping(target = "result", source = "businessStatus")
@Mapping(target = "createAt", source = "startTime")
@Mapping(target = "endTime", source = "endTime")
@Mapping(target = "businessKey", source = "businessKey")
@Mapping(target = "variables", source = "processVariables")
@Mapping(target = "startUserId", source = "startUserId")
@Override
BpmnProcessInstanceVO toVo(HistoricProcessInstance entity);
default BpmnProcessInstanceVO toVo(HistoricProcessInstance processInstance,
BpmnProcessDefinitionVO processDefinition) {
BpmnProcessInstanceVO vo = toVo(processInstance);
vo.setCategory(processDefinition.getCategory());
return vo;
}
}

View File

@ -0,0 +1,58 @@
package cn.axzo.workflow.core.service.converter;
import cn.axzo.workflow.core.service.dto.response.bpmn.task.BpmnHistoricTaskInstanceVO;
import org.flowable.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.springframework.util.CollectionUtils;
import java.util.*;
import static org.mapstruct.NullValueCheckStrategy.ALWAYS;
/**
* 历史任务实例的 MapStruts 转换器
*
* @author wangli
* @since 2023/7/29 17:50
*/
@Mapper(
componentModel = "spring",
nullValueCheckStrategy = ALWAYS,
imports = Arrays.class
)
public interface BpmnHistoricTaskInstanceConverter extends EntityConverter<BpmnHistoricTaskInstanceVO,
HistoricTaskInstance> {
/**
* @see MultiInstanceActivityBehavior#DELETE_REASON_END
*/
String DELETE_REASON_END = "MI_END";
@Override
@Mapping(target = "taskId", source = "id")
@Mapping(target = "taskDefinitionKey", source = "taskDefinitionKey")
@Mapping(target = "name", source = "name")
@Mapping(target = "processInstanceId", source = "processInstanceId")
@Mapping(target = "processDefinitionId", source = "processDefinitionId")
@Mapping(target = "assignee", source = "assignee")
@Mapping(target = "createTime", source = "createTime")
@Mapping(target = "endTime", source = "endTime")
@Mapping(target = "durationInMillis", source = "durationInMillis")
@Mapping(target = "tenantId", source = "tenantId")
@Mapping(target = "deleteReason", source = "deleteReason")
BpmnHistoricTaskInstanceVO toVo(HistoricTaskInstance entity);
default List<BpmnHistoricTaskInstanceVO> toVosSkipMiEnd(List<HistoricTaskInstance> entities) {
if (CollectionUtils.isEmpty(entities)) {
return Collections.emptyList();
}
List<BpmnHistoricTaskInstanceVO> vos = new ArrayList<>();
entities.stream()
.filter(i -> !Objects.equals(DELETE_REASON_END, i.getDeleteReason()))
.forEach(i -> vos.add(toVo(i)));
return vos;
}
}

View File

@ -0,0 +1,33 @@
package cn.axzo.workflow.core.service.converter;
import cn.axzo.workflow.core.service.dto.response.bpmn.model.BpmnModelDetailVO;
import org.flowable.engine.repository.Model;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import java.util.Arrays;
import static org.mapstruct.NullValueCheckStrategy.ALWAYS;
/**
* 流程模型的 MapStruts 转换器
*/
@Mapper(
componentModel = "spring",
nullValueCheckStrategy = ALWAYS,
imports = Arrays.class
)
public interface BpmnModelConverter extends EntityConverter<BpmnModelDetailVO, Model> {
@Override
@Mapping(target = "id", source = "id")
@Mapping(target = "key", source = "key")
@Mapping(target = "name", source = "name")
@Mapping(target = "category", source = "category")
@Mapping(target = "createAt", source = "createTime")
@Mapping(target = "updateAt", source = "lastUpdateTime")
@Mapping(target = "version", source = "version")
@Mapping(target = "tenantId", source = "tenantId")
BpmnModelDetailVO toVo(Model entity);
}

View File

@ -0,0 +1,58 @@
package cn.axzo.workflow.core.service.converter;
import cn.axzo.workflow.core.service.dto.response.bpmn.process.BpmnProcessDefinitionVO;
import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.flowable.engine.repository.ProcessDefinition;
import org.mapstruct.Mapper;
import java.util.Arrays;
import static org.mapstruct.NullValueCheckStrategy.ALWAYS;
/**
* 流程定义的 MapStruts 转换器
*
* @author wangli
* @since 2023/7/25 22:44
*/
@Mapper(
componentModel = "spring",
nullValueCheckStrategy = ALWAYS,
imports = Arrays.class
)
public interface BpmnProcessDefinitionConverter extends EntityConverter<BpmnProcessDefinitionVO, ProcessDefinition> {
@Override
default BpmnProcessDefinitionVO toVo(ProcessDefinition entity) {
if (entity == null) {
return null;
}
BpmnProcessDefinitionVO bpmnProcessDefinitionVO = new BpmnProcessDefinitionVO();
if (entity.getId() != null) {
bpmnProcessDefinitionVO.setId(entity.getId());
}
if (entity.getName() != null) {
bpmnProcessDefinitionVO.setName(entity.getName());
}
if (entity.getKey() != null) {
bpmnProcessDefinitionVO.setKey(entity.getKey());
}
if (entity.getDescription() != null) {
bpmnProcessDefinitionVO.setDescription(entity.getDescription());
}
if (entity.getCategory() != null) {
bpmnProcessDefinitionVO.setCategory(entity.getCategory());
}
if (entity.getTenantId() != null) {
bpmnProcessDefinitionVO.setTenantId(entity.getTenantId());
}
bpmnProcessDefinitionVO.setVersion(entity.getVersion());
ProcessDefinitionEntity entitySource = (ProcessDefinitionEntity) entity;
bpmnProcessDefinitionVO.setSuspensionState(entitySource.getSuspensionState());
return bpmnProcessDefinitionVO;
}
}

View File

@ -0,0 +1,34 @@
package cn.axzo.workflow.core.service.converter;
import cn.axzo.workflow.core.service.dto.response.bpmn.process.BpmnProcessInstancePageItemVO;
import org.flowable.engine.history.HistoricProcessInstance;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import java.util.Arrays;
import static org.mapstruct.NullValueCheckStrategy.ALWAYS;
/**
* 流程实例分页模型的 MapStruts 转换器
*
* @author wangli
* @since 2023/7/26 14:31
*/
@Mapper(
componentModel = "spring",
nullValueCheckStrategy = ALWAYS,
imports = Arrays.class
)
public interface BpmnProcessInstancePageItemConverter extends EntityConverter<BpmnProcessInstancePageItemVO,
HistoricProcessInstance> {
@Mapping(target = "id", source = "id")
@Mapping(target = "name", source = "name")
@Mapping(target = "processDefinitionId", source = "processDefinitionId")
@Mapping(target = "result", source = "businessStatus")
@Mapping(target = "startTime", source = "startTime")
@Mapping(target = "endTime", source = "endTime")
@Override
BpmnProcessInstancePageItemVO toVo(HistoricProcessInstance entity);
}

View File

@ -0,0 +1,37 @@
package cn.axzo.workflow.core.service.converter;
import cn.axzo.workflow.core.service.dto.response.bpmn.task.BpmnTaskInstanceVO;
import org.flowable.task.api.Task;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import java.util.Arrays;
import static org.mapstruct.NullValueCheckStrategy.ALWAYS;
/**
* 运行中的审批任务的 MapStruts 转换器
*
* @author wangli
* @since 2023/7/29 23:23
*/
@Mapper(
componentModel = "spring",
nullValueCheckStrategy = ALWAYS,
imports = Arrays.class
)
public interface BpmnTaskConverter extends EntityConverter<BpmnTaskInstanceVO, Task> {
@Mapping(target = "processInstanceId", source = "processInstanceId")
@Mapping(target = "processDefinitionId", source = "processDefinitionId")
@Mapping(target = "taskId", source = "id")
@Mapping(target = "taskDefinitionKey", source = "taskDefinitionKey")
@Mapping(target = "name", source = "name")
@Mapping(target = "owner", source = "owner")
@Mapping(target = "assignee", source = "assignee")
@Mapping(target = "createTime", source = "createTime")
@Mapping(target = "tenantId", source = "tenantId")
@Mapping(target = "formKey", source = "formKey")
@Mapping(target = "category", source = "category")
@Override
BpmnTaskInstanceVO toVo(Task entity);
}

View File

@ -0,0 +1,65 @@
package cn.axzo.workflow.core.service.converter;
import cn.axzo.workflow.core.service.dto.response.bpmn.task.BpmnTaskDonePageItemVO;
import cn.axzo.workflow.core.service.dto.response.bpmn.task.BpmnTaskTodoPageItemVO;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import org.springframework.beans.BeanUtils;
import java.util.*;
import static org.mapstruct.NullValueCheckStrategy.ALWAYS;
/**
* 流程已完成的审批任务分页的 MapStruts 转换器
*
* @author wangli
* @since 2023/7/26 23:37
*/
@Mapper(
componentModel = "spring",
nullValueCheckStrategy = ALWAYS,
imports = Arrays.class
)
public interface BpmnTaskDonePageItemConverter extends EntityConverter<BpmnTaskDonePageItemVO, HistoricTaskInstance> {
BpmnTaskTodoPageItemConverter todoConverter = Mappers.getMapper(BpmnTaskTodoPageItemConverter.class);
@Override
default BpmnTaskDonePageItemVO toVo(HistoricTaskInstance entity) {
BpmnTaskTodoPageItemVO todo = todoConverter.toVo(entity);
BpmnTaskDonePageItemVO vo = new BpmnTaskDonePageItemVO();
BeanUtils.copyProperties(todo, vo);
vo.setEndTime(entity.getEndTime());
vo.setDurationInMillis(entity.getDurationInMillis());
vo.setComment(entity.getDeleteReason());
return vo;
}
default List<BpmnTaskDonePageItemVO> toVos(List<HistoricTaskInstance> tasks,
Map<String, HistoricProcessInstance> historicProcessInstanceMap) {
if (tasks.isEmpty()) {
return Collections.emptyList();
}
List<BpmnTaskDonePageItemVO> vos = new ArrayList<>();
tasks.forEach(i -> {
BpmnTaskDonePageItemVO vo = toVo(i);
HistoricProcessInstance instance = historicProcessInstanceMap.getOrDefault(i.getProcessInstanceId(), null);
if (Objects.nonNull(instance)) {
vo.setProcessInstanceId(instance.getId());
vo.setProcessInstanceName(instance.getName());
vo.setBusinessKey(instance.getBusinessKey());
vo.setStartUserId(instance.getStartUserId());
vo.setStartTime(instance.getStartTime());
vo.setProcessInstanceEndTime(instance.getEndTime());
vos.add(vo);
}
});
return vos;
}
}

View File

@ -0,0 +1,56 @@
package cn.axzo.workflow.core.service.converter;
import cn.axzo.workflow.core.service.dto.response.bpmn.task.BpmnTaskTodoPageItemVO;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import java.util.*;
import static org.mapstruct.NullValueCheckStrategy.ALWAYS;
/**
* 流程实例待审批任务的 MapStruts 转换器
*
* @author wangli
* @since 2023/7/26 23:00
*/
@Mapper(
componentModel = "spring",
nullValueCheckStrategy = ALWAYS,
imports = Arrays.class
)
public interface BpmnTaskTodoPageItemConverter extends EntityConverter<BpmnTaskTodoPageItemVO, HistoricTaskInstance> {
@Mapping(target = "id", source = "id")
@Mapping(target = "taskName", source = "name")
@Mapping(target = "category", source = "category")
@Mapping(target = "claimTime", source = "createTime")
@Mapping(target = "owner", source = "owner")
@Mapping(target = "assignee", source = "assignee")
@Mapping(target = "formKey", source = "formKey")
@Override
BpmnTaskTodoPageItemVO toVo(HistoricTaskInstance entity);
default List<BpmnTaskTodoPageItemVO> toVos(List<HistoricTaskInstance> tasks,
Map<String, ProcessInstance> processInstanceMap) {
if (tasks.isEmpty()) {
return Collections.emptyList();
}
List<BpmnTaskTodoPageItemVO> vos = new ArrayList<>();
tasks.forEach(i -> {
BpmnTaskTodoPageItemVO vo = toVo(i);
ProcessInstance instance = processInstanceMap.getOrDefault(i.getProcessInstanceId(), null);
if (Objects.nonNull(instance)) {
vo.setProcessInstanceId(instance.getProcessInstanceId());
vo.setProcessInstanceName(instance.getName());
vo.setBusinessKey(instance.getBusinessKey());
vo.setStartUserId(instance.getStartUserId());
vo.setStartTime(instance.getStartTime());
vos.add(vo);
}
});
return vos;
}
}

View File

@ -0,0 +1,29 @@
package cn.axzo.workflow.core.service.converter;
import cn.axzo.workflow.core.repository.entity.ExtAxDictDO;
import cn.axzo.workflow.core.service.dto.response.category.CategoryItemVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import java.util.Arrays;
import static org.mapstruct.NullValueCheckStrategy.ALWAYS;
/**
* 分类的 MapStruts 转换器
*/
@Mapper(
componentModel = "spring",
nullValueCheckStrategy = ALWAYS,
imports = Arrays.class
)
public interface CategoryConverter extends EntityConverter<CategoryItemVO, ExtAxDictDO> {
@Mapping(target = "id", source = "category.id")
@Mapping(target = "type", source = "category.type")
@Mapping(target = "label", source = "category.label")
@Mapping(target = "value", source = "category.value")
@Mapping(target = "remark", source = "category.remark")
@Mapping(target = "status", source = "category.status")
CategoryItemVO toVo(ExtAxDictDO category);
}

View File

@ -1,10 +1,21 @@
package cn.axzo.workflow.core.service.converter;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public interface EntityConverter<V, E>{
public interface EntityConverter<V, E> {
V toVo(E var);
V toVo(E entity);
List<V> toVo(List<E> var);
default List<V> toVos(List<E> entities) {
if (CollectionUtils.isEmpty(entities)) {
return Collections.emptyList();
}
List<V> vos = new ArrayList<>();
entities.forEach(i -> vos.add(toVo(i)));
return vos;
}
}

View File

@ -0,0 +1,35 @@
package cn.axzo.workflow.core.service.converter;
import cn.axzo.workflow.core.service.dto.response.form.model.FormModelBaseVO;
import org.flowable.engine.repository.Model;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import java.util.Arrays;
import static org.mapstruct.NullValueCheckStrategy.ALWAYS;
/**
* 表单模型的 MapStruts 转换器
*
* @author wangli
* @since 2023/7/25 13:33
*/
@Mapper(
componentModel = "spring",
nullValueCheckStrategy = ALWAYS,
imports = Arrays.class
)
public interface FormModelConverter extends EntityConverter<FormModelBaseVO, Model> {
@Mapping(target = "id", source = "entity.id")
@Mapping(target = "name", source = "entity.name")
@Mapping(target = "key", source = "entity.key")
@Mapping(target = "category", source = "entity.category")
@Mapping(target = "tenantId", source = "entity.tenantId")
@Mapping(target = "version", source = "entity.version")
@Mapping(target = "createAt", source = "entity.createTime")
@Mapping(target = "updateAt", source = "entity.lastUpdateTime")
FormModelBaseVO toVo(Model entity);
}

View File

@ -1,38 +0,0 @@
package cn.axzo.workflow.core.service.dto.request;
import cn.axzo.workflow.core.common.enums.BpmFlowMultiMode;
import lombok.Data;
@Data
public class BpmJsonNodeProperty {
/**
* 是否是多实例Task节点
*/
private Boolean isMultiTask;
/**
* Task 多实例模式OR"或签"AND"会签"
*/
private BpmFlowMultiMode multiMode;
/**
* 审批人为空是否允许自动跳过
*/
private Boolean allowSkip = false;
/**
* 条件节点中是否是默认分支可以都不传;
*/
private Boolean defaultCondition;
/**
* 条件分支的Key
*/
private String conditionBranchKey;
/**
* 条件节点当ConditionKey的值是多少走该分支
* */
private Integer conditionBranchValue;
}

View File

@ -1,7 +1,7 @@
package cn.axzo.workflow.core.service.dto;
package cn.axzo.workflow.core.service.dto.request.bpmn;
import cn.axzo.workflow.core.common.enums.BpmFlowNodeType;
import cn.axzo.workflow.core.service.dto.request.BpmJsonNodeProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ -9,8 +9,12 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* JSON 版本的 BPMN 协议模型
*/
@ApiModel("JSON 版本的 BPMN 协议模型")
@Data
public class BpmJsonNode {
public class BpmnJsonNode {
@ApiModelProperty(value = "节点ID", required = true)
private String id;
@ -18,23 +22,24 @@ public class BpmJsonNode {
private String parentId;
/**
* {@link BpmFlowNodeType}
* */
*/
@ApiModelProperty(value = "节点类型task/branch", required = true)
private String type; // task, branch,
@ApiModelProperty(value = "节点名称", required = true)
private String name;
// private Map<> properties; //ext : Object; 会签/或签
// private Map<> properties; //ext : Object; 会签/或签
@ApiModelProperty(value = "子节点信息", required = true)
private BpmJsonNode children;
private BpmnJsonNode children;
@ApiModelProperty(value = "分支节点信息", required = true)
private List<BpmJsonNode> branches;
private BpmJsonNodeProperty property;
private List<BpmnJsonNode> branches;
private BpmnJsonNodeProperty property;
/* 内部使用,不需要外界传 */
private transient Map incoming = new HashMap();
public BpmJsonNode() {
public BpmnJsonNode() {
}
public String getId() {
@ -69,27 +74,27 @@ public class BpmJsonNode {
this.name = name;
}
public BpmJsonNode getChildren() {
public BpmnJsonNode getChildren() {
return children;
}
public void setChildren(BpmJsonNode children) {
public void setChildren(BpmnJsonNode children) {
this.children = children;
}
public List<BpmJsonNode> getBranches() {
public List<BpmnJsonNode> getBranches() {
return branches;
}
public void setBranches(List<BpmJsonNode> branches) {
public void setBranches(List<BpmnJsonNode> branches) {
this.branches = branches;
}
public BpmJsonNodeProperty getProperty() {
public BpmnJsonNodeProperty getProperty() {
return property;
}
public void setProperty(BpmJsonNodeProperty property) {
public void setProperty(BpmnJsonNodeProperty property) {
this.property = property;
}

View File

@ -0,0 +1,56 @@
package cn.axzo.workflow.core.service.dto.request.bpmn;
import cn.axzo.workflow.core.common.enums.BpmFlowMultiMode;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* JSON 版本的 BPMN 协议中 UserTask 节点的属性扩展模型
*/
@ApiModel("JSON 版本的 BPMN 协议中 UserTask 节点的属性扩展模型")
@Data
public class BpmnJsonNodeProperty {
/**
* 是否是多实例Task节点
*/
@ApiModelProperty("是否是多实例Task节点")
private Boolean isMultiTask;
/**
* Task 多实例模式OR"或签"AND"会签"
*/
@ApiModelProperty(value = "Task 多实例模式OR或签AND会签")
private BpmFlowMultiMode multiMode;
/**
* 审批人为空是否允许自动跳过
*/
@ApiModelProperty(value = "审批人为空是否允许自动跳过")
private Boolean allowSkip = false;
/**
* 条件节点中是否是默认分支可以都不传;
*/
@ApiModelProperty(value = "条件节点中是否是默认分支,可以都不传")
private Boolean defaultCondition;
/**
* 条件分支的Key
*/
@ApiModelProperty(value = "条件分支的Key")
private String conditionBranchKey;
/**
* 条件节点当ConditionKey的值是多少走该分支
*/
@ApiModelProperty(value = "条件节点当ConditionKey的值是多少走该分支")
private Integer conditionBranchValue;
/**
* 发起时使用的表单 key
*/
@ApiModelProperty(value = "发起时使用的表单 key")
private String formKey;
}

View File

@ -0,0 +1,27 @@
package cn.axzo.workflow.core.service.dto.request.bpmn.definition;
import cn.axzo.workflow.core.service.dto.request.bpmn.BpmnJsonNode;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
/**
* 用于更新流程定义的入参模型
*
* @author wangli
* @since 2023/7/26 10:07
*/
@ApiModel("用于更新流程定义的入参模型")
@Data
public class BpmnProcessDefinitionUpdateDTO {
@ApiModelProperty(value = "流程模型 ID")
private String processModelId;
@ApiModelProperty(value = "JSON 转义的流程定义内容", notes = "枢智业务线在用")
@Valid
@NotNull(message = "模型定义内容不能为空")
private BpmnJsonNode bpmJson;
}

View File

@ -1,16 +1,21 @@
package cn.axzo.workflow.core.service.dto.request.model;
package cn.axzo.workflow.core.service.dto.request.bpmn.model;
import cn.axzo.workflow.core.service.dto.BpmJsonNode;
import cn.axzo.workflow.core.service.dto.request.bpmn.BpmnJsonNode;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank;
/**
* 创建流程模型的入参模型
*/
@ApiModel("创建流程模型的入参模型")
@Data
public class BpmModelCreateDTO {
public class BpmnModelCreateDTO {
@ApiModelProperty(value = "流程模型标识", notes = "前端不用填写", example = "process_yudao", hidden = true)
@ApiModelProperty(value = "流程模型标识", example = "process_key", hidden = true)
@Length(max = 255, message = "流程标识最长只支持255个字符")
@NotBlank(message = "流程模型表示不能为空")
private String key;
@ -20,34 +25,25 @@ public class BpmModelCreateDTO {
*/
@ApiModelProperty(value = "流程名称", required = true, example = "模板流程名称")
@NotBlank(message = "流程名称不能为空")
@Length(max = 20, message = "流程名称最长只支持255个字符")
@Length(max = 255, message = "流程名称最长只支持255个字符")
private String name;
/**
* 所属业务
* 默认 1
* OA 2
* 自定义分类
*/
@ApiModelProperty(value = "所属业务", notes = "由业务自定义", example = "1")
@NotBlank(message = "所属业务不能为空")
@ApiModelProperty(value = "自定义分类", notes = "由业务自定义", example = "1")
private String category;
/**
* MetaInfo 自定义数据可以放icon等任何
* */
@ApiModelProperty(value = "MetaInfo 自定义数据可以放icon等任何", example = "1")
private Object metaInfo;
/**
* 流程的Json 结构
*
* */
*/
@ApiModelProperty(value = "流程的Json 结构", example = "1")
private BpmJsonNode node;
private BpmnJsonNode node;
/**
* 租户Id
* */
*/
@ApiModelProperty(value = "租户Id", example = "1")
@NotBlank(message = "租户 ID 不能为空")
private String tenantId;
}

View File

@ -0,0 +1,41 @@
package cn.axzo.workflow.core.service.dto.request.bpmn.model;
import cn.axzo.workflow.core.service.dto.request.BpmPageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 流程模型搜索入参模型
*/
@EqualsAndHashCode(callSuper = true)
@ApiModel("流程模型搜索入参模型")
@Data
public class BpmnModelSearchDTO extends BpmPageParam {
/**
* 标识
*/
@ApiModelProperty(value = "流程模型标识", example = "process1641042089407", notes = "精准匹配")
private String key;
/**
* 名称
*/
@ApiModelProperty(value = "流程模型名字", example = "流程模型名称", notes = "模糊匹配")
private String name;
/**
* 流程分类
*/
@ApiModelProperty(value = "流程模型分类", example = "1")
private String category;
/**
* 工作台ID
*/
@ApiModelProperty(value = "租户 ID", example = "1")
private String tenantId;
}

View File

@ -0,0 +1,20 @@
package cn.axzo.workflow.core.service.dto.request.bpmn.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 修改流程模型入参模型
*/
@EqualsAndHashCode(callSuper = true)
@ApiModel("修改流程模型入参模型")
@Data
public class BpmnModelUpdateDTO extends BpmnModelCreateDTO {
@ApiModelProperty(value = "流程模型 ID", required = true)
private String processModelId;
}

View File

@ -1,18 +1,20 @@
package cn.axzo.workflow.core.service.dto.request.process;
package cn.axzo.workflow.core.service.dto.request.bpmn.process;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* TODO
* 最基础的流程实例查询入参模型
*
* @author wangli
* @since 2023/7/14 13:48
*/
@ApiModel("最基础的流程实例查询入参模型")
@Data
public class BpmBasicProcessInstanceQueryDTO {
public class BpmnBasicProcessInstanceQueryDTO {
/**
* 流程实例 ID
*/

View File

@ -0,0 +1,26 @@
package cn.axzo.workflow.core.service.dto.request.bpmn.process;
import cn.axzo.workflow.core.service.dto.request.BpmPageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
/**
* 流程定义分页查询入参模型
*/
@EqualsAndHashCode(callSuper = true)
@ApiModel("流程定义分页查询入参模型")
@Data
public class BpmnProcessDefinitionPageDTO extends BpmPageParam {
@ApiModelProperty(value = "流程标识,传了精准匹配")
@NotBlank(message = "流程标识不能为空")
private String key;
@ApiModelProperty(value = "租户Id", example = "1")
private String tenantId;
}

View File

@ -1,5 +1,6 @@
package cn.axzo.workflow.core.service.dto.request.process;
package cn.axzo.workflow.core.service.dto.request.bpmn.process;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ -11,8 +12,9 @@ import javax.validation.constraints.NotBlank;
* @author wangli
* @since 2023/7/17 09:34
*/
@ApiModel("取消流程实例的入参模型")
@Data
public class BpmProcessInstanceCancelDTO {
public class BpmnProcessInstanceCancelDTO {
/**
* 流程实例的编号
@ -43,7 +45,7 @@ public class BpmProcessInstanceCancelDTO {
* 用户 ID
*/
@NotBlank(message = "用户编号不能为空")
@ApiModelProperty(value = "操作人编号")
@ApiModelProperty(value = "操作人标识")
private String userId;
/**

View File

@ -1,13 +1,20 @@
package cn.axzo.workflow.core.service.dto.request.process;
package cn.axzo.workflow.core.service.dto.request.bpmn.process;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import java.util.HashMap;
import java.util.Map;
/**
* 创建流程实例的入参模型
*/
@ApiModel("创建流程实例的入参模型")
@Data
public class BpmProcessInstanceCreateDTO {
public class BpmnProcessInstanceCreateDTO {
/**
* 流程定义的 id
@ -21,7 +28,7 @@ public class BpmProcessInstanceCreateDTO {
/**
* 变量实例
*/
private Map<String, Object> variables;
private Map<String, Object> variables = new HashMap<>();
/**
* 业务的唯一标识
@ -34,12 +41,13 @@ public class BpmProcessInstanceCreateDTO {
/**
* 发起人所在的(企业/项目)租户ID
*/
@NotBlank(message = "租户不能为空")
@NotBlank(message = "租户ID不能为空")
private String tenantId;
/**
* 发起人的身份ID
*/
@ApiModelProperty(value = "操作人标识")
@NotBlank(message = "用户Id不能为空")
private String userId;
@ -52,10 +60,7 @@ public class BpmProcessInstanceCreateDTO {
/**
* 自定义的流程实例名称
*/
@ApiModelProperty(value = "自定义的流程实例名称")
private String customProcessInstanceName;
/**
* 拓展业务字段
*/
private Object ext;
}

View File

@ -0,0 +1,38 @@
package cn.axzo.workflow.core.service.dto.request.bpmn.process;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
/**
* 创建工作流实例同时携带表单的入参模型
*
* @author wangli
* @since 2023/7/20 15:49
*/
@ApiModel("创建工作流实例同时携带表单的入参模型")
@EqualsAndHashCode(callSuper = true)
@Data
public class BpmnProcessInstanceCreateWithFormDTO extends BpmnProcessInstanceCreateDTO {
/**
* 表单的定义 ID
* <p>
* 参考:ACT_FO_FORM_DEFINITION 表的主键
*/
@ApiModelProperty(value = "表单定义 ID", example = "ssss")
@NotBlank(message = "表单不能为空")
private String formDefinitionId;
/**
* 工作流实例集成表单后,可以通过表单 key 组装成的变量存入该变量的值,可用于后续流程的流转
* <p>
* 一般不用设置
*/
@ApiModelProperty(value = "用于接入外部传入的信息", hidden = true)
private String outcome;
}

View File

@ -0,0 +1,60 @@
package cn.axzo.workflow.core.service.dto.request.bpmn.process;
import cn.axzo.workflow.core.common.enums.BpmProcessInstanceResultEnum;
import cn.axzo.workflow.core.service.dto.request.BpmPageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotBlank;
import java.util.Date;
/**
* 用于查询我的发起的流程实例入参模型
*/
@ApiModel("用于查询我的发起的流程实例入参模型")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BpmnProcessInstanceMyPageReqVO extends BpmPageParam {
@ApiModelProperty(value = "流程名称")
private String name;
@ApiModelProperty(value = "流程定义的编号", hidden = true)
private String processDefinitionId;
@ApiModelProperty(value = "业务KEY")
private String businessKey;
@ApiModelProperty(value = "审核状态(PROCESSING:审核中,APPROVED:已通过,REJECTED:已拒绝,CANCELLED:已取消)", example = "APPROVED")
private BpmProcessInstanceResultEnum result;
@ApiModelProperty(value = "自定义分类")
private String category;
@ApiModelProperty(value = "发起时间")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date beginCreateTime;
@ApiModelProperty(value = "结束时间")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endCreateTime;
/**
* 发起人所在的(企业/项目)工作台ID
*/
@ApiModelProperty(value = "租户Id", required = true)
@NotBlank(message = "租户不能为空")
private String tenantId;
/**
* 发起人的身份ID
*/
@ApiModelProperty(value = "操作人标识", required = true)
@NotBlank(message = "用户编号不能为空")
private String userId;
}

View File

@ -1,4 +1,4 @@
package cn.axzo.workflow.core.service.dto.request.process;
package cn.axzo.workflow.core.service.dto.request.bpmn.process;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ -12,12 +12,12 @@ import lombok.Data;
*/
@Data
@ApiModel("查询流程实例的入参模型")
public class BpmProcessInstanceQueryDTO extends BpmBasicProcessInstanceQueryDTO {
public class BpmnProcessInstanceQueryDTO extends BpmnBasicProcessInstanceQueryDTO {
/**
* 是否包含参数
*/
@ApiModelProperty("是否包含实例运行参数")
private Boolean hasVariable;
private Boolean hasVariable = false;
}

View File

@ -1,20 +1,24 @@
package cn.axzo.workflow.core.service.dto.request.process;
package cn.axzo.workflow.core.service.dto.request.bpmn.process;
import cn.axzo.workflow.core.service.dto.request.BpmPageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* TODO
* 全量历史流程实例搜索入参模型
*
* @author wangli
* @since 2023/7/26 17:58
* @since 2023/7/30 22:01
*/
@ApiModel("全量历史流程实例搜索入参模型")
@Data
public class CustomProcInstSearchDTO extends BpmPageParam {
public class HistoricProcessInstanceSearchDTO extends BpmPageParam {
@ApiModelProperty(value = "businessKey OR Name")
private String searchKey;
private String category;
@ -33,3 +37,4 @@ public class CustomProcInstSearchDTO extends BpmPageParam {
private String tenantId;
}

View File

@ -0,0 +1,32 @@
package cn.axzo.workflow.core.service.dto.request.bpmn.task;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* 转交审批任务的入参模型
*
* @author wangli
* @since 2023/7/27 11:50
*/
@ApiModel("转交审批任务的入参模型")
@Data
public class BpmnTaskAssigneeDTO {
@ApiModelProperty(value = "审批任务 ID")
@NotBlank(message = "任务 ID 不能为空")
private String taskId;
@ApiModelProperty(value = "审批任务原审批人", notes = "可以为空,意义在于可以将没有指派给任何人的任务转交给其他人")
private String originUserId;
@ApiModelProperty(value = "审批任务转发给谁", notes = "可以为空,意义在于如果分配给某离职的人,可能需要置为空")
private String newUserId;
@ApiModelProperty(value = "租户 ID")
@NotBlank(message = "租户不能为空")
private String tenantId;
}

View File

@ -0,0 +1,47 @@
package cn.axzo.workflow.core.service.dto.request.bpmn.task;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
/**
* 审批任务节点的入参模型
*/
@ApiModel("审批任务节点的入参模型")
@Data
public class BpmnTaskAuditDTO {
@ApiModelProperty(value = "任务编号", required = true, example = "1024")
@NotEmpty(message = "任务编号不能为空")
private String taskId;
/**
* 审核人Id
*/
@ApiModelProperty(value = "操作人标识")
@NotBlank(message = "操作人编号不能为空")
private String userId;
/**
* 审核人名称
* */
@ApiModelProperty(value = "操作人姓名")
@NotBlank(message = "操作人姓名不能为空")
private String userName;
/**
* 租户Id
* */
@ApiModelProperty(value = "租户")
@NotBlank(message = "租户不能为空")
private String tenantId;
/**
* 评论信息
*/
@ApiModelProperty(value = "审批意见")
private String advice;
}

View File

@ -0,0 +1,33 @@
package cn.axzo.workflow.core.service.dto.request.bpmn.task;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* 对审批任务添加评论的入参模型
*
* @author wangli
* @since 2023/7/29 17:25
*/
@ApiModel("对审批任务添加评论的入参模型")
@Data
public class BpmnTaskCommentDTO {
@ApiModelProperty(value = "审批任务 ID")
@NotBlank(message = "任务 ID 不能为空")
private String taskId;
@ApiModelProperty(value = "流程实例 ID")
@NotBlank(message = "流程实例 ID 不能为空")
private String processInstanceId;
@ApiModelProperty(value = "租户 ID")
@NotBlank(message = "tenantId")
private String tenantId;
@ApiModelProperty(value = "评论内容")
private String comment;
}

View File

@ -1,6 +1,7 @@
package cn.axzo.workflow.core.service.dto.request.task;
package cn.axzo.workflow.core.service.dto.request.bpmn.task;
import cn.axzo.workflow.core.service.dto.request.BpmPageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -9,19 +10,26 @@ import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* "待我审核"的审批任务列表查询入参模型
*/
@ApiModel("'待我审核'的审批任务列表查询入参模型")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BpmTaskTodoBpmPageDTO extends BpmPageParam {
public class BpmnTaskTodoPageSearchDTO extends BpmPageParam {
@ApiModelProperty(value = "用户ID唯一标识", example = "1")
@ApiModelProperty(value = "操作人标识")
private String userId;
@ApiModelProperty(value = "租户Id", example = "1")
private String tenantId;
@ApiModelProperty(value = "审核单类型,多选就'逗号'分隔", example = "1")
private String category;
private String categories;
@ApiModelProperty(value = "业务 KEY")
private String businessKey;
@ApiModelProperty(value = "流程任务名", example = "芋道")
private String name;
@ -34,6 +42,4 @@ public class BpmTaskTodoBpmPageDTO extends BpmPageParam {
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endCreateTime;
@ApiModelProperty(value = "自定义审核单号", example = "20220622143500001")
private String customProInstId;
}

View File

@ -1,4 +1,4 @@
package cn.axzo.workflow.core.service.dto.request.model;
package cn.axzo.workflow.core.service.dto.request.category;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ -7,7 +7,7 @@ import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank;
@Data
public class BpmCategoryCreateDTO {
public class CategoryCreateDTO {
@ApiModelProperty(value = "字典标签", example = "新业务")
@Length(max = 50, message = "字典标签最长只支持255个字符")
@ -20,22 +20,20 @@ public class BpmCategoryCreateDTO {
private String value;
@ApiModelProperty(value = "字典类型", example = "字典类型(用于字典分组)")
private String dictType;
private String type;
@ApiModelProperty(value = "备注", example = "remark")
@Length(max = 250, message = "备注最长只支持250个字符")
private String remark;
@ApiModelProperty(value = "字典排序", example = "1", hidden = true)
private Integer sort;
@ApiModelProperty(value = "字典排序", example = "1")
private Long sort;
@ApiModelProperty(value = "状态", example = "true or false", hidden = true)
@ApiModelProperty(value = "状态", example = "true or false")
private Boolean status;
@ApiModelProperty(value = "颜色类型", example = "对应到 element-ui 为 default、primary、success、info、warning、danger", hidden = true)
private String colorType;
@ApiModelProperty(value = "CSS样式", example = "color: red", hidden = true)
private String cssClass;
@ApiModelProperty(value = "租户", example = "1")
@NotBlank(message = "租户不能为空")
private String tenantId;
}

View File

@ -0,0 +1,33 @@
package cn.axzo.workflow.core.service.dto.request.category;
import cn.axzo.workflow.core.service.dto.request.BpmPageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotBlank;
/**
* 自定义分类的查询入参模型
*/
@ApiModel("自定义分类的查询入参模型")
@EqualsAndHashCode(callSuper = true)
@Data
public class CategorySearchDTO extends BpmPageParam {
@ApiModelProperty(value = "字典类型", example = "dict_group", notes = "精准匹配")
private String dictType;
@ApiModelProperty(value = "字典标签", example = "新业务")
private String label;
@ApiModelProperty(value = "字典值", example = "new_business")
private String value;
@ApiModelProperty(value = "状态", example = "0 or 1")
private Integer status;
@ApiModelProperty(value = "租户 ID", example = "1")
@NotBlank(message = "租户不能为空")
private String tenantId;
}

View File

@ -1,14 +1,19 @@
package cn.axzo.workflow.core.service.dto.request.model;
package cn.axzo.workflow.core.service.dto.request.category;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
/**
* 自定义分类更新模型
*/
@ApiModel("自定义分类更新模型")
@EqualsAndHashCode(callSuper = true)
@Data
public class BpmCategoryUpdateDTO extends BpmCategoryCreateDTO{
public class CategoryUpdateDTO extends CategoryCreateDTO {
@ApiModelProperty(value = "ID", example = "1")
@NotNull(message = "字典标签表示不能为空")

View File

@ -0,0 +1,29 @@
package cn.axzo.workflow.core.service.dto.request.form.definition;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.flowable.form.model.SimpleFormModel;
import java.util.List;
/**
* 特殊的模型,对应 Flowable Engine 中的 {@link SimpleFormModel}
*
* @author wangli
* @since 2023/7/24 22:36
*/
@Data
public class FormDefinitionDTO {
@ApiModelProperty(value = "表单定义的key", hidden = true)
private String key;
@ApiModelProperty(value = "表单定义的名称", hidden = true)
private String name;
@ApiModelProperty(value = "表单定义的版本", hidden = true)
private Integer version;
@ApiModelProperty(value = "表单定义的具体字段项", example = "[{'': '''}]")
private List<FormFieldsDTO> fields;
}

View File

@ -0,0 +1,26 @@
package cn.axzo.workflow.core.service.dto.request.form.definition;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* 表单定义的更新入参模型
*
* @author wangli
* @since 2023/7/25 14:21
*/
@ApiModel("表单定义的更新入参模型")
@Data
public class FormDefinitionUpdateDTO {
@ApiModelProperty("表单模型ID")
@NotBlank(message = "表单模型 ID 不能为空")
public String formModelId;
@ApiModelProperty(value = "表单定义内容")
private FormDefinitionDTO formDefinition;
}

View File

@ -0,0 +1,51 @@
package cn.axzo.workflow.core.service.dto.request.form.definition;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.util.Map;
/**
* 表单定义中的字段相关属性入参模型
*
* @author wangli
* @since 2023/7/20 10:39
*/
@ApiModel("表单定义中的字段相关属性入参模型")
@Data
public class FormFieldsDTO {
@ApiModelProperty(value = "表单字段类型", hidden = true)
@NotBlank(message = "字段类型不能为空")
private transient String fieldType = "FormField";
@ApiModelProperty(value = "前端的组件类型")
private String type;
@ApiModelProperty(value = "表单字段组件ID", example = "account")
@NotBlank(message = "表单字段组件 ID 不能为空")
private String id;
@ApiModelProperty(value = "表单字段名称", example = "账号")
private String name;
@ApiModelProperty(value = "表单字段默认值", example = "account")
private String value;
@ApiModelProperty(value = "表单字段是否必填,默认 false", example = "true or false")
private Boolean required = false;
@ApiModelProperty(value = "表单字段是否只读,默认 false", example = "true or false")
private Boolean readOnly = false;
@ApiModelProperty(value = "表单字段占位提示")
private String placeholder;
@ApiModelProperty(value = "该表单字段的其他扩展属性,期望 JSON 格式")
private Map<String, Object> params;
}

View File

@ -0,0 +1,34 @@
package cn.axzo.workflow.core.service.dto.request.form.instance;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.util.Map;
/**
* 表单实例填写内容更新入参模型
*
* @author wangli
* @since 2023/7/20 17:51
*/
@ApiModel("表单实例填写内容更新入参模型")
@Data
public class FormContentUpdateDTO {
@ApiModelProperty(value = "任务 ID", example = "sss-ss")
@NotBlank(message = "任务 ID 不能为空")
private String taskId;
@ApiModelProperty(value = "使用的表单定义 ID")
@NotBlank(message = "表单定义 ID 不能为空")
private String formDefinitionId;
@ApiModelProperty(value = "表单字段值", example = "{'field1': '1', 'field2': 2}")
private Map<String, Object> formVariables;
@ApiModelProperty(value = "任务归属人标识", example = "1")
@NotBlank(message = "任务归属人不能为空")
private String userId;
}

View File

@ -0,0 +1,37 @@
package cn.axzo.workflow.core.service.dto.request.form.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank;
/**
* 表单模型创建入参模型
*
* @author wangli
* @since 2023/7/20 09:52
*/
@ApiModel("表单模型创建入参模型")
@Data
public class FormModelCreateDTO {
@ApiModelProperty(value = "表单标识", example = "form_key", hidden = true)
@Length(max = 255, message = "表单标识最长只支持255个字符")
@NotBlank(message = "流程表单 key 不能为空")
private String key;
@ApiModelProperty(value = "表单名称", example = "第一个表单")
@NotBlank(message = "表单名称不能为空")
@Length(max = 255, message = "表单名称最长只支持255个字符")
private String name;
@ApiModelProperty(value = "表单分类", example = "business_form_key")
private String category;
@ApiModelProperty(value = "租户 ID", example = "1")
@NotBlank(message = "租户 ID 不能为空")
private String tenantId;
}

View File

@ -0,0 +1,26 @@
package cn.axzo.workflow.core.service.dto.request.form.model;
import cn.axzo.workflow.core.service.dto.request.BpmPageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 表单模型查询的入参模型
*
* @author wangli
* @since 2023/7/20 14:39
*/
@ApiModel("表单模型查询的入参模型")
@Data
public class FormModelSearchDTO extends BpmPageParam {
@ApiModelProperty(value = "表单名称", example = "第一个表单")
private String name;
@ApiModelProperty(value = "表单分类", example = "new_category")
private String category;
@ApiModelProperty(value = "租户 ID", example = "11")
private String tenantId;
}

View File

@ -0,0 +1,23 @@
package cn.axzo.workflow.core.service.dto.request.form.model;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* 表单模型更新的入参模型
*
* @author wangli
* @since 2023/7/20 13:44
*/
@ApiModel("表单模型更新的入参模型")
@Data
public class FormModelUpdateDTO extends FormModelCreateDTO {
@ApiModelProperty("表单ID")
@NotBlank(message = "表单 ID 不能为空")
public String formModelId;
}

View File

@ -1,19 +0,0 @@
package cn.axzo.workflow.core.service.dto.request.model;
import cn.axzo.framework.domain.page.PageQO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class BpmCategoryDTO extends PageQO {
@ApiModelProperty(value = "字典类型", example = "dict_group", notes = "精准匹配")
private String dictType;
@ApiModelProperty(value = "字典标签", example = "新业务")
private String label;
@ApiModelProperty(value = "字典值", example = "new_business")
private String value;
}

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