项目初始化

This commit is contained in:
2025-07-17 18:07:48 +08:00
parent c74ce366c7
commit 6550a64884
1179 changed files with 3407 additions and 3447 deletions

View File

@@ -0,0 +1,373 @@
package com.klp.flowable.utils;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.impl.util.io.StringStreamSource;
import java.util.*;
/**
* @author KonBAI
* @createTime 2022/3/26 19:04
*/
public class ModelUtils {
private static final BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();
/**
* xml转bpmnModel对象
*
* @param xml xml
* @return bpmnModel对象
*/
public static BpmnModel getBpmnModel(String xml) {
return bpmnXMLConverter.convertToBpmnModel(new StringStreamSource(xml), false, false);
}
/**
* bpmnModel转xml字符串
*
* @deprecated 存在会丢失 bpmn 连线问题
* @param bpmnModel bpmnModel对象
* @return xml字符串
*/
@Deprecated
public static String getBpmnXmlStr(BpmnModel bpmnModel) {
return StrUtil.utf8Str(getBpmnXml(bpmnModel));
}
/**
* bpmnModel转xml对象
*
* @deprecated 存在丢失 bpmn 连线问题
* @param bpmnModel bpmnModel对象
* @return xml
*/
@Deprecated
public static byte[] getBpmnXml(BpmnModel bpmnModel) {
return bpmnXMLConverter.convertToXML(bpmnModel);
}
/**
* 根据节点,获取入口连线
*
* @param source 起始节点
* @return 入口连线列表
*/
public static List<SequenceFlow> getElementIncomingFlows(FlowElement source) {
List<SequenceFlow> sequenceFlows = new ArrayList<>();
if (source instanceof FlowNode) {
sequenceFlows = ((FlowNode) source).getIncomingFlows();
}
return sequenceFlows;
}
/**
* 根据节点,获取出口连线
*
* @param source 起始节点
* @return 出口连线列表
*/
public static List<SequenceFlow> getElementOutgoingFlows(FlowElement source) {
List<SequenceFlow> sequenceFlows = new ArrayList<>();
if (source instanceof FlowNode) {
sequenceFlows = ((FlowNode) source).getOutgoingFlows();
}
return sequenceFlows;
}
/**
* 获取开始节点
*
* @param model bpmnModel对象
* @return 开始节点未找到开始节点返回null
*/
public static StartEvent getStartEvent(BpmnModel model) {
Process process = model.getMainProcess();
FlowElement startElement = process.getInitialFlowElement();
if (startElement instanceof StartEvent) {
return (StartEvent) startElement;
}
return getStartEvent(process.getFlowElements());
}
/**
* 获取开始节点
*
* @param flowElements 流程元素集合
* @return 开始节点未找到开始节点返回null
*/
public static StartEvent getStartEvent(Collection<FlowElement> flowElements) {
for (FlowElement flowElement : flowElements) {
if (flowElement instanceof StartEvent) {
return (StartEvent) flowElement;
}
}
return null;
}
/**
* 获取结束节点
*
* @param model bpmnModel对象
* @return 结束节点未找到开始节点返回null
*/
public static EndEvent getEndEvent(BpmnModel model) {
Process process = model.getMainProcess();
return getEndEvent(process.getFlowElements());
}
/**
* 获取结束节点
*
* @param flowElements 流程元素集合
* @return 结束节点未找到开始节点返回null
*/
public static EndEvent getEndEvent(Collection<FlowElement> flowElements) {
for (FlowElement flowElement : flowElements) {
if (flowElement instanceof EndEvent) {
return (EndEvent) flowElement;
}
}
return null;
}
public static UserTask getUserTaskByKey(BpmnModel model, String taskKey) {
Process process = model.getMainProcess();
FlowElement flowElement = process.getFlowElement(taskKey);
if (flowElement instanceof UserTask) {
return (UserTask) flowElement;
}
return null;
}
/**
* 获取流程元素信息
*
* @param model bpmnModel对象
* @param flowElementId 元素ID
* @return 元素信息
*/
public static FlowElement getFlowElementById(BpmnModel model, String flowElementId) {
Process process = model.getMainProcess();
return process.getFlowElement(flowElementId);
}
/**
* 获取元素表单Key限开始节点和用户节点可用
*
* @param flowElement 元素
* @return 表单Key
*/
public static String getFormKey(FlowElement flowElement) {
if (flowElement != null) {
if (flowElement instanceof StartEvent) {
return ((StartEvent) flowElement).getFormKey();
} else if (flowElement instanceof UserTask) {
return ((UserTask) flowElement).getFormKey();
}
}
return null;
}
/**
* 获取开始节点属性值
* @param model bpmnModel对象
* @param name 属性名
* @return 属性值
*/
public static String getStartEventAttributeValue(BpmnModel model, String name) {
StartEvent startEvent = getStartEvent(model);
return getElementAttributeValue(startEvent, name);
}
/**
* 获取结束节点属性值
* @param model bpmnModel对象
* @param name 属性名
* @return 属性值
*/
public static String getEndEventAttributeValue(BpmnModel model, String name) {
EndEvent endEvent = getEndEvent(model);
return getElementAttributeValue(endEvent, name);
}
/**
* 获取用户任务节点属性值
* @param model bpmnModel对象
* @param taskKey 任务Key
* @param name 属性名
* @return 属性值
*/
public static String getUserTaskAttributeValue(BpmnModel model, String taskKey, String name) {
UserTask userTask = getUserTaskByKey(model, taskKey);
return getElementAttributeValue(userTask, name);
}
/**
* 获取元素属性值
* @param baseElement 流程元素
* @param name 属性名
* @return 属性值
*/
public static String getElementAttributeValue(BaseElement baseElement, String name) {
if (baseElement != null) {
List<ExtensionAttribute> attributes = baseElement.getAttributes().get(name);
if (attributes != null && !attributes.isEmpty()) {
attributes.iterator().next().getValue();
Iterator<ExtensionAttribute> attrIterator = attributes.iterator();
if(attrIterator.hasNext()) {
ExtensionAttribute attribute = attrIterator.next();
return attribute.getValue();
}
}
}
return null;
}
public static boolean isMultiInstance(BpmnModel model, String taskKey) {
UserTask userTask = getUserTaskByKey(model, taskKey);
if (ObjectUtil.isNotNull(userTask)) {
return userTask.hasMultiInstanceLoopCharacteristics();
}
return false;
}
/**
* 获取所有用户任务节点
*
* @param model bpmnModel对象
* @return 用户任务节点列表
*/
public static Collection<UserTask> getAllUserTaskEvent(BpmnModel model) {
Process process = model.getMainProcess();
Collection<FlowElement> flowElements = process.getFlowElements();
return getAllUserTaskEvent(flowElements, null);
}
/**
* 获取所有用户任务节点
* @param flowElements 流程元素集合
* @param allElements 所有流程元素集合
* @return 用户任务节点列表
*/
public static Collection<UserTask> getAllUserTaskEvent(Collection<FlowElement> flowElements, Collection<UserTask> allElements) {
allElements = allElements == null ? new ArrayList<>() : allElements;
for (FlowElement flowElement : flowElements) {
if (flowElement instanceof UserTask) {
allElements.add((UserTask) flowElement);
}
if (flowElement instanceof SubProcess) {
// 继续深入子流程,进一步获取子流程
allElements = getAllUserTaskEvent(((SubProcess) flowElement).getFlowElements(), allElements);
}
}
return allElements;
}
/**
* 查找起始节点下一个用户任务列表列表
* @param source 起始节点
* @return 结果
*/
public static List<UserTask> findNextUserTasks(FlowElement source) {
return findNextUserTasks(source, null, null);
}
/**
* 查找起始节点下一个用户任务列表列表
* @param source 起始节点
* @param hasSequenceFlow 已经经过的连线的 ID用于判断线路是否重复
* @param userTaskList 用户任务列表
* @return 结果
*/
public static List<UserTask> findNextUserTasks(FlowElement source, Set<String> hasSequenceFlow, List<UserTask> userTaskList) {
hasSequenceFlow = Optional.ofNullable(hasSequenceFlow).orElse(new HashSet<>());
userTaskList = Optional.ofNullable(userTaskList).orElse(new ArrayList<>());
// 获取出口连线
List<SequenceFlow> sequenceFlows = getElementOutgoingFlows(source);
if (!sequenceFlows.isEmpty()) {
for (SequenceFlow sequenceFlow : sequenceFlows) {
// 如果发现连线重复,说明循环了,跳过这个循环
if (hasSequenceFlow.contains(sequenceFlow.getId())) {
continue;
}
// 添加已经走过的连线
hasSequenceFlow.add(sequenceFlow.getId());
FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
if (targetFlowElement instanceof UserTask) {
// 若节点为用户任务,加入到结果列表中
userTaskList.add((UserTask) targetFlowElement);
} else {
// 若节点非用户任务,继续递归查找下一个节点
findNextUserTasks(targetFlowElement, hasSequenceFlow, userTaskList);
}
}
}
return userTaskList;
}
/**
* 迭代从后向前扫描,判断目标节点相对于当前节点是否是串行
* 不存在直接回退到子流程中的情况,但存在从子流程出去到父流程情况
* @param source 起始节点
* @param target 目标节点
* @param visitedElements 已经经过的连线的 ID用于判断线路是否重复
* @return 结果
*/
public static boolean isSequentialReachable(FlowElement source, FlowElement target, Set<String> visitedElements) {
visitedElements = visitedElements == null ? new HashSet<>() : visitedElements;
if (source instanceof StartEvent && isInEventSubprocess(source)) {
return false;
}
// 根据类型,获取入口连线
List<SequenceFlow> sequenceFlows = getElementIncomingFlows(source);
if (sequenceFlows != null && sequenceFlows.size() > 0) {
// 循环找到目标元素
for (SequenceFlow sequenceFlow: sequenceFlows) {
// 如果发现连线重复,说明循环了,跳过这个循环
if (visitedElements.contains(sequenceFlow.getId())) {
continue;
}
// 添加已经走过的连线
visitedElements.add(sequenceFlow.getId());
FlowElement sourceFlowElement = sequenceFlow.getSourceFlowElement();
// 这条线路存在目标节点,这条线路完成,进入下个线路
if (target.getId().equals(sourceFlowElement.getId())) {
continue;
}
// 如果目标节点为并行网关,则不继续
if (sourceFlowElement instanceof ParallelGateway) {
return false;
}
// 否则就继续迭代
boolean isSequential = isSequentialReachable(sourceFlowElement, target, visitedElements);
if (!isSequential) {
return false;
}
}
}
return true;
}
protected static boolean isInEventSubprocess(FlowElement flowElement) {
FlowElementsContainer flowElementsContainer = flowElement.getParentContainer();
while (flowElementsContainer != null) {
if (flowElementsContainer instanceof EventSubProcess) {
return true;
}
if (flowElementsContainer instanceof FlowElement) {
flowElementsContainer = ((FlowElement) flowElementsContainer).getParentContainer();
} else {
flowElementsContainer = null;
}
}
return false;
}
}

View File

@@ -0,0 +1,50 @@
package com.klp.flowable.utils;
import cn.hutool.core.convert.Convert;
import com.klp.flowable.core.FormConf;
import java.util.List;
import java.util.Map;
/**
* 流程表单工具类
*
* @author KonBAI
* @createTime 2022/8/7 17:09
*/
public class ProcessFormUtils {
private static final String CONFIG = "__config__";
private static final String MODEL = "__vModel__";
/**
* 填充表单项内容
*
* @param formConf 表单配置信息
* @param data 表单内容
*/
public static void fillFormData(FormConf formConf, Map<String, Object> data) {
for (Map<String, Object> field : formConf.getFields()) {
recursiveFillField(field, data);
}
}
@SuppressWarnings("unchecked")
private static void recursiveFillField(final Map<String, Object> field, final Map<String, Object> data) {
if (!field.containsKey(CONFIG)) {
return;
}
Map<String, Object> configMap = (Map<String, Object>) field.get(CONFIG);
if (configMap.containsKey("children")) {
List<Map<String, Object>> childrens = (List<Map<String, Object>>) configMap.get("children");
for (Map<String, Object> children : childrens) {
recursiveFillField(children, data);
}
}
String modelKey = Convert.toStr(field.get(MODEL));
Object value = data.get(modelKey);
if (value != null) {
configMap.put("defaultValue", value);
}
}
}

View File

@@ -0,0 +1,115 @@
package com.klp.flowable.utils;
import com.klp.common.utils.DateUtils;
import com.klp.common.utils.StringUtils;
import com.klp.flowable.core.domain.ProcessQuery;
import org.flowable.common.engine.api.query.Query;
import org.flowable.common.engine.impl.db.SuspensionState;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
import java.util.Map;
/**
* 流程工具类
*
* @author konbai
* @since 2022/12/11 03:35
*/
public class ProcessUtils {
public static void buildProcessSearch(Query<?, ?> query, ProcessQuery process) {
if (query instanceof ProcessDefinitionQuery) {
buildProcessDefinitionSearch((ProcessDefinitionQuery) query, process);
} else if (query instanceof TaskQuery) {
buildTaskSearch((TaskQuery) query, process);
} else if (query instanceof HistoricTaskInstanceQuery) {
buildHistoricTaskInstanceSearch((HistoricTaskInstanceQuery) query, process);
} else if (query instanceof HistoricProcessInstanceQuery) {
buildHistoricProcessInstanceSearch((HistoricProcessInstanceQuery) query, process);
}
}
/**
* 构建流程定义搜索
*/
public static void buildProcessDefinitionSearch(ProcessDefinitionQuery query, ProcessQuery process) {
// 流程标识
if (StringUtils.isNotBlank(process.getProcessKey())) {
query.processDefinitionKeyLike("%" + process.getProcessKey() + "%");
}
// 流程名称
if (StringUtils.isNotBlank(process.getProcessName())) {
query.processDefinitionNameLike("%" + process.getProcessName() + "%");
}
// 流程分类
if (StringUtils.isNotBlank(process.getCategory())) {
query.processDefinitionCategory(process.getCategory());
}
// 流程状态
if (StringUtils.isNotBlank(process.getState())) {
if (SuspensionState.ACTIVE.toString().equals(process.getState())) {
query.active();
} else if (SuspensionState.SUSPENDED.toString().equals(process.getState())) {
query.suspended();
}
}
}
/**
* 构建任务搜索
*/
public static void buildTaskSearch(TaskQuery query, ProcessQuery process) {
Map<String, Object> params = process.getParams();
if (StringUtils.isNotBlank(process.getProcessKey())) {
query.processDefinitionKeyLike("%" + process.getProcessKey() + "%");
}
if (StringUtils.isNotBlank(process.getProcessName())) {
query.processDefinitionNameLike("%" + process.getProcessName() + "%");
}
if (params.get("beginTime") != null && params.get("endTime") != null) {
query.taskCreatedAfter(DateUtils.parseDate(params.get("beginTime")));
query.taskCreatedBefore(DateUtils.parseDate(params.get("endTime")));
}
}
private static void buildHistoricTaskInstanceSearch(HistoricTaskInstanceQuery query, ProcessQuery process) {
Map<String, Object> params = process.getParams();
if (StringUtils.isNotBlank(process.getProcessKey())) {
query.processDefinitionKeyLike("%" + process.getProcessKey() + "%");
}
if (StringUtils.isNotBlank(process.getProcessName())) {
query.processDefinitionNameLike("%" + process.getProcessName() + "%");
}
if (params.get("beginTime") != null && params.get("endTime") != null) {
query.taskCompletedAfter(DateUtils.parseDate(params.get("beginTime")));
query.taskCompletedBefore(DateUtils.parseDate(params.get("endTime")));
}
}
/**
* 构建历史流程实例搜索
*/
public static void buildHistoricProcessInstanceSearch(HistoricProcessInstanceQuery query, ProcessQuery process) {
Map<String, Object> params = process.getParams();
// 流程标识
if (StringUtils.isNotBlank(process.getProcessKey())) {
query.processDefinitionKey(process.getProcessKey());
}
// 流程名称
if (StringUtils.isNotBlank(process.getProcessName())) {
query.processDefinitionName(process.getProcessName());
}
// 流程名称
if (StringUtils.isNotBlank(process.getCategory())) {
query.processDefinitionCategory(process.getCategory());
}
if (params.get("beginTime") != null && params.get("endTime") != null) {
query.startedAfter(DateUtils.parseDate(params.get("beginTime")));
query.startedBefore(DateUtils.parseDate(params.get("endTime")));
}
}
}

View File

@@ -0,0 +1,41 @@
package com.klp.flowable.utils;
import cn.hutool.core.util.ObjectUtil;
import com.klp.common.core.domain.model.LoginUser;
import com.klp.common.helper.LoginHelper;
import com.klp.flowable.common.constant.TaskConstants;
import java.util.ArrayList;
import java.util.List;
/**
* 工作流任务工具类
*
* @author konbai
* @createTime 2022/4/24 12:42
*/
public class TaskUtils {
public static String getUserId() {
return String.valueOf(LoginHelper.getUserId());
}
/**
* 获取用户组信息
*
* @return candidateGroup
*/
public static List<String> getCandidateGroup() {
List<String> list = new ArrayList<>();
LoginUser user = LoginHelper.getLoginUser();
if (ObjectUtil.isNotNull(user)) {
if (ObjectUtil.isNotEmpty(user.getRoles())) {
user.getRoles().forEach(role -> list.add(TaskConstants.ROLE_GROUP_PREFIX + role.getRoleId()));
}
if (ObjectUtil.isNotNull(user.getDeptId())) {
list.add(TaskConstants.DEPT_GROUP_PREFIX + user.getDeptId());
}
}
return list;
}
}