Merge branch 'develop' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into master-jdk17

This commit is contained in:
YunaiV
2025-07-30 18:59:32 +08:00
8 changed files with 107 additions and 16 deletions

View File

@@ -71,6 +71,9 @@ public class BpmSimpleModelNodeVO {
@Schema(description = "是否填写审批意见", example = "false")
private Boolean reasonRequire;
@Schema(description = "跳过表达式", example = "{true}")
private String skipExpression; // 用于审批节点
/**
* 审批节点拒绝处理
*/

View File

@@ -14,6 +14,7 @@ import lombok.Getter;
@AllArgsConstructor
public enum BpmTaskStatusEnum {
SKIP(-2, "跳过"),
NOT_START(-1, "未开始"),
RUNNING(1, "审批中"),
APPROVE(2, "审批通过"),

View File

@@ -800,9 +800,10 @@ public class BpmnModelUtils {
|| currentElement instanceof EndEvent
|| currentElement instanceof UserTask
|| currentElement instanceof ServiceTask) {
// 添加元素
// 添加节点
FlowNode flowNode = (FlowNode) currentElement;
resultElements.add(flowNode);
// 遍历子节点
flowNode.getOutgoingFlows().forEach(
nextElement -> simulateNextFlowElements(nextElement.getTargetFlowElement(), variables, resultElements, visitElements));
@@ -835,6 +836,31 @@ public class BpmnModelUtils {
}
}
/**
* 判断是否跳过此节点
*
* @param flowNode 节点
* @param variables 流程变量
*/
public static boolean isSkipNode(FlowElement flowNode, Map<String, Object> variables) {
// 1. 检查节点是否有跳过表达式(支持多种任务节点类型)
String skipExpression = null;
if (flowNode instanceof UserTask) {
skipExpression = ((UserTask) flowNode).getSkipExpression();
} else if (flowNode instanceof ServiceTask) {
skipExpression = ((ServiceTask) flowNode).getSkipExpression();
} else if (flowNode instanceof ScriptTask) {
skipExpression = ((ScriptTask) flowNode).getSkipExpression();
}
if (StrUtil.isEmpty(skipExpression)) {
return false;
}
// 2. 计算跳过表达式的值
return evalConditionExpress(variables, skipExpression);
}
/**
* 根据当前节点,获取下一个节点
*
@@ -997,7 +1023,7 @@ public class BpmnModelUtils {
* @return 是否满足条件
*/
public static boolean evalConditionExpress(Map<String, Object> variables, String expression) {
if (expression == null) {
if (StrUtil.isEmpty(expression)) {
return Boolean.FALSE;
}
// 如果 variables 为空,则创建一个的原因?可能 expression 的计算,不依赖于 variables

View File

@@ -464,6 +464,10 @@ public class SimpleModelUtils {
addReasonRequire(node.getReasonRequire(), userTask);
// 节点类型
addNodeType(node.getType(), userTask);
// 添加跳过表达式
if (StrUtil.isNotEmpty(node.getSkipExpression())) {
userTask.setSkipExpression(node.getSkipExpression());
}
return userTask;
}
@@ -968,7 +972,7 @@ public class SimpleModelUtils {
|| nodeType == BpmSimpleModelNodeTypeEnum.COPY_NODE
|| nodeType == BpmSimpleModelNodeTypeEnum.CHILD_PROCESS
|| nodeType == BpmSimpleModelNodeTypeEnum.END_NODE) {
// 添加元素
// 添加此节点
resultNodes.add(currentNode);
}
@@ -1014,6 +1018,16 @@ public class SimpleModelUtils {
simulateNextNode(currentNode.getChildNode(), variables, resultNodes);
}
/**
* 根据跳过表达式,判断是否跳过此节点
*/
public static boolean isSkipNode(BpmSimpleModelNodeVO currentNode, Map<String, Object> variables) {
if (StrUtil.isEmpty(currentNode.getSkipExpression())) {
return false;
}
return BpmnModelUtils.evalConditionExpress(variables, currentNode.getSkipExpression());
}
public static boolean evalConditionExpress(Map<String, Object> variables, BpmSimpleModelNodeVO.ConditionSetting conditionSetting) {
return BpmnModelUtils.evalConditionExpress(variables, buildConditionExpression(conditionSetting));
}

View File

@@ -398,7 +398,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
? BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType()
: ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”的识别
BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()))
.setStatus(FlowableUtils.getTaskStatus(task))
.setStatus(getEndActivityNodeStatus(task))
.setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode))
.setStartTime(DateUtils.of(task.getCreateTime())).setEndTime(DateUtils.of(task.getEndTime()))
.setTasks(singletonList(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task)));
@@ -462,6 +462,18 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
return approvalNodes;
}
/**
* 获取结束节点的状态
*/
private Integer getEndActivityNodeStatus(HistoricTaskInstance task) {
Integer status = FlowableUtils.getTaskStatus(task);
if (status != null) {
return status;
}
// 结束节点未获取到状态,为跳过状态。可见 bpmn 或者 simple 的 skipExpression
return BpmTaskStatusEnum.SKIP.getStatus();
}
/**
* 获得【进行中】的活动节点们
*/
@@ -565,10 +577,14 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
if (runActivityIds.contains(node.getId())) {
return null;
}
Integer status = BpmTaskStatusEnum.NOT_START.getStatus();
// 如果节点被跳过。设置状态为跳过
if (SimpleModelUtils.isSkipNode(node, processVariables)) {
status = BpmTaskStatusEnum.SKIP.getStatus();
}
ActivityNode activityNode = new ActivityNode().setId(node.getId()).setName(node.getName())
.setNodeType(node.getType()).setCandidateStrategy(node.getCandidateStrategy())
.setStatus(BpmTaskStatusEnum.NOT_START.getStatus());
.setStatus(status);
// 1. 开始节点/审批节点
if (ObjectUtils.equalsAny(node.getType(),
@@ -608,8 +624,13 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService
if (runActivityIds.contains(node.getId())) {
return null;
}
Integer status = BpmTaskStatusEnum.NOT_START.getStatus();
// 如果节点被跳过,状态设置为跳过
if(BpmnModelUtils.isSkipNode(node, processVariables)){
status = BpmTaskStatusEnum.SKIP.getStatus();
}
ActivityNode activityNode = new ActivityNode().setId(node.getId())
.setStatus(BpmTaskStatusEnum.NOT_START.getStatus());
.setStatus(status);
// 1. 开始节点
if (node instanceof StartEvent) {

View File

@@ -947,7 +947,10 @@ public class BpmTaskServiceImpl implements BpmTaskService {
BpmCommentTypeEnum.DELEGATE_START.formatComment(currentUser.getNickname(), delegateUser.getNickname(), reqVO.getReason()));
// 3.1 设置任务所有人 (owner) 为原任务的处理人 (assignee)
taskService.setOwner(taskId, task.getAssignee());
// 特殊如果已经被委派owner 非空),则不需要更新 ownerhttps://gitee.com/zhijiantianya/yudao-cloud/issues/ICJ153
if (StrUtil.isEmpty(task.getOwner())) {
taskService.setOwner(taskId, task.getAssignee());
}
// 3.2 执行委派,将任务委派给 delegateUser
taskService.delegateTask(taskId, reqVO.getDelegateUserId().toString());
// 补充说明:委托不单独设置状态。如果需要,可通过 Task 的 DelegationState 字段,判断是否为 DelegationState.PENDING 委托中
@@ -973,7 +976,10 @@ public class BpmTaskServiceImpl implements BpmTaskService {
BpmCommentTypeEnum.TRANSFER.formatComment(currentUser.getNickname(), assigneeUser.getNickname(), reqVO.getReason()));
// 3.1 设置任务所有人 (owner) 为原任务的处理人 (assignee)
taskService.setOwner(taskId, task.getAssignee());
// 特殊如果已经被转派owner 非空),则不需要更新 ownerhttps://gitee.com/zhijiantianya/yudao-cloud/issues/ICJ153
if (StrUtil.isEmpty(task.getOwner())) {
taskService.setOwner(taskId, task.getAssignee());
}
// 3.2 执行转派(审批人),将任务转派给 assigneeUser
// 委托( delegate和转派transfer的差别就在这块的调用
taskService.setAssignee(taskId, reqVO.getAssigneeUserId().toString());