Commit ff70aaa6a9dea2ede66eaa8b57d1a343045af2e6
Merge branch 'develop' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into master-jdk17
Showing
8 changed files
with
107 additions
and
16 deletions
sql/tools/convertor.py
| @@ -17,6 +17,7 @@ uv run --with simple-ddl-parser convertor.py dm8 > ../dm/ruoyi-vue-pro-dm8.sql | @@ -17,6 +17,7 @@ uv run --with simple-ddl-parser convertor.py dm8 > ../dm/ruoyi-vue-pro-dm8.sql | ||
| 17 | import argparse | 17 | import argparse |
| 18 | import pathlib | 18 | import pathlib |
| 19 | import re | 19 | import re |
| 20 | +import sys | ||
| 20 | import time | 21 | import time |
| 21 | from abc import ABC, abstractmethod | 22 | from abc import ABC, abstractmethod |
| 22 | from typing import Dict, Generator, Optional, Tuple, Union | 23 | from typing import Dict, Generator, Optional, Tuple, Union |
| @@ -293,8 +294,10 @@ class Convertor(ABC): | @@ -293,8 +294,10 @@ class Convertor(ABC): | ||
| 293 | 294 | ||
| 294 | # 将parse失败的脚本打印出来 | 295 | # 将parse失败的脚本打印出来 |
| 295 | if error_scripts: | 296 | if error_scripts: |
| 297 | + print("!!! 以下内容无法正常解析", file=sys.stderr) | ||
| 296 | for script in error_scripts: | 298 | for script in error_scripts: |
| 297 | - print(script) | 299 | + # print to stderr |
| 300 | + print(script, file=sys.stderr) | ||
| 298 | 301 | ||
| 299 | 302 | ||
| 300 | class PostgreSQLConvertor(Convertor): | 303 | class PostgreSQLConvertor(Convertor): |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java
| @@ -6,6 +6,8 @@ import cn.hutool.core.map.MapUtil; | @@ -6,6 +6,8 @@ import cn.hutool.core.map.MapUtil; | ||
| 6 | import cn.hutool.core.util.ObjUtil; | 6 | import cn.hutool.core.util.ObjUtil; |
| 7 | import cn.hutool.core.util.StrUtil; | 7 | import cn.hutool.core.util.StrUtil; |
| 8 | import cn.hutool.extra.servlet.JakartaServletUtil; | 8 | import cn.hutool.extra.servlet.JakartaServletUtil; |
| 9 | +import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiErrorLogCommonApi; | ||
| 10 | +import cn.iocoder.yudao.framework.common.biz.infra.logger.dto.ApiErrorLogCreateReqDTO; | ||
| 9 | import cn.iocoder.yudao.framework.common.exception.ServiceException; | 11 | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| 10 | import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; | 12 | import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; |
| 11 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 13 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| @@ -14,8 +16,6 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | @@ -14,8 +16,6 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||
| 14 | import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; | 16 | import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; |
| 15 | import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; | 17 | import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; |
| 16 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; | 18 | import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; |
| 17 | -import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiErrorLogCommonApi; | ||
| 18 | -import cn.iocoder.yudao.framework.common.biz.infra.logger.dto.ApiErrorLogCreateReqDTO; | ||
| 19 | import com.fasterxml.jackson.databind.exc.InvalidFormatException; | 19 | import com.fasterxml.jackson.databind.exc.InvalidFormatException; |
| 20 | import jakarta.servlet.http.HttpServletRequest; | 20 | import jakarta.servlet.http.HttpServletRequest; |
| 21 | import jakarta.validation.ConstraintViolation; | 21 | import jakarta.validation.ConstraintViolation; |
| @@ -29,6 +29,7 @@ import org.springframework.util.Assert; | @@ -29,6 +29,7 @@ import org.springframework.util.Assert; | ||
| 29 | import org.springframework.validation.BindException; | 29 | import org.springframework.validation.BindException; |
| 30 | import org.springframework.validation.FieldError; | 30 | import org.springframework.validation.FieldError; |
| 31 | import org.springframework.validation.ObjectError; | 31 | import org.springframework.validation.ObjectError; |
| 32 | +import org.springframework.web.HttpMediaTypeNotSupportedException; | ||
| 32 | import org.springframework.web.HttpRequestMethodNotSupportedException; | 33 | import org.springframework.web.HttpRequestMethodNotSupportedException; |
| 33 | import org.springframework.web.bind.MethodArgumentNotValidException; | 34 | import org.springframework.web.bind.MethodArgumentNotValidException; |
| 34 | import org.springframework.web.bind.MissingServletRequestParameterException; | 35 | import org.springframework.web.bind.MissingServletRequestParameterException; |
| @@ -101,6 +102,9 @@ public class GlobalExceptionHandler { | @@ -101,6 +102,9 @@ public class GlobalExceptionHandler { | ||
| 101 | if (ex instanceof HttpRequestMethodNotSupportedException) { | 102 | if (ex instanceof HttpRequestMethodNotSupportedException) { |
| 102 | return httpRequestMethodNotSupportedExceptionHandler((HttpRequestMethodNotSupportedException) ex); | 103 | return httpRequestMethodNotSupportedExceptionHandler((HttpRequestMethodNotSupportedException) ex); |
| 103 | } | 104 | } |
| 105 | + if (ex instanceof HttpMediaTypeNotSupportedException) { | ||
| 106 | + return httpMediaTypeNotSupportedExceptionHandler((HttpMediaTypeNotSupportedException) ex); | ||
| 107 | + } | ||
| 104 | if (ex instanceof ServiceException) { | 108 | if (ex instanceof ServiceException) { |
| 105 | return serviceExceptionHandler((ServiceException) ex); | 109 | return serviceExceptionHandler((ServiceException) ex); |
| 106 | } | 110 | } |
| @@ -171,17 +175,19 @@ public class GlobalExceptionHandler { | @@ -171,17 +175,19 @@ public class GlobalExceptionHandler { | ||
| 171 | /** | 175 | /** |
| 172 | * 处理 SpringMVC 请求参数类型错误 | 176 | * 处理 SpringMVC 请求参数类型错误 |
| 173 | * | 177 | * |
| 174 | - * 例如说,接口上设置了 @RequestBody实体中 xx 属性类型为 Integer,结果传递 xx 参数类型为 String | 178 | + * 例如说,接口上设置了 @RequestBody 实体中 xx 属性类型为 Integer,结果传递 xx 参数类型为 String |
| 175 | */ | 179 | */ |
| 176 | @ExceptionHandler(HttpMessageNotReadableException.class) | 180 | @ExceptionHandler(HttpMessageNotReadableException.class) |
| 177 | public CommonResult<?> methodArgumentTypeInvalidFormatExceptionHandler(HttpMessageNotReadableException ex) { | 181 | public CommonResult<?> methodArgumentTypeInvalidFormatExceptionHandler(HttpMessageNotReadableException ex) { |
| 178 | log.warn("[methodArgumentTypeInvalidFormatExceptionHandler]", ex); | 182 | log.warn("[methodArgumentTypeInvalidFormatExceptionHandler]", ex); |
| 179 | - if(ex.getCause() instanceof InvalidFormatException) { | 183 | + if (ex.getCause() instanceof InvalidFormatException) { |
| 180 | InvalidFormatException invalidFormatException = (InvalidFormatException) ex.getCause(); | 184 | InvalidFormatException invalidFormatException = (InvalidFormatException) ex.getCause(); |
| 181 | return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", invalidFormatException.getValue())); | 185 | return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", invalidFormatException.getValue())); |
| 182 | - }else { | ||
| 183 | - return defaultExceptionHandler(ServletUtils.getRequest(), ex); | ||
| 184 | } | 186 | } |
| 187 | + if (StrUtil.startWith(ex.getMessage(), "Required request body is missing")) { | ||
| 188 | + return CommonResult.error(BAD_REQUEST.getCode(), "请求参数类型错误: request body 缺失"); | ||
| 189 | + } | ||
| 190 | + return defaultExceptionHandler(ServletUtils.getRequest(), ex); | ||
| 185 | } | 191 | } |
| 186 | 192 | ||
| 187 | /** | 193 | /** |
| @@ -238,6 +244,17 @@ public class GlobalExceptionHandler { | @@ -238,6 +244,17 @@ public class GlobalExceptionHandler { | ||
| 238 | } | 244 | } |
| 239 | 245 | ||
| 240 | /** | 246 | /** |
| 247 | + * 处理 SpringMVC 请求的 Content-Type 不正确 | ||
| 248 | + * | ||
| 249 | + * 例如说,A 接口的 Content-Type 为 application/json,结果请求的 Content-Type 为 application/octet-stream,导致不匹配 | ||
| 250 | + */ | ||
| 251 | + @ExceptionHandler(HttpMediaTypeNotSupportedException.class) | ||
| 252 | + public CommonResult<?> httpMediaTypeNotSupportedExceptionHandler(HttpMediaTypeNotSupportedException ex) { | ||
| 253 | + log.warn("[httpMediaTypeNotSupportedExceptionHandler]", ex); | ||
| 254 | + return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求类型不正确:%s", ex.getMessage())); | ||
| 255 | + } | ||
| 256 | + | ||
| 257 | + /** | ||
| 241 | * 处理 Spring Security 权限不足的异常 | 258 | * 处理 Spring Security 权限不足的异常 |
| 242 | * | 259 | * |
| 243 | * 来源是,使用 @PreAuthorize 注解,AOP 进行权限拦截 | 260 | * 来源是,使用 @PreAuthorize 注解,AOP 进行权限拦截 |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java
| @@ -71,6 +71,9 @@ public class BpmSimpleModelNodeVO { | @@ -71,6 +71,9 @@ public class BpmSimpleModelNodeVO { | ||
| 71 | @Schema(description = "是否填写审批意见", example = "false") | 71 | @Schema(description = "是否填写审批意见", example = "false") |
| 72 | private Boolean reasonRequire; | 72 | private Boolean reasonRequire; |
| 73 | 73 | ||
| 74 | + @Schema(description = "跳过表达式", example = "{true}") | ||
| 75 | + private String skipExpression; // 用于审批节点 | ||
| 76 | + | ||
| 74 | /** | 77 | /** |
| 75 | * 审批节点拒绝处理 | 78 | * 审批节点拒绝处理 |
| 76 | */ | 79 | */ |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatusEnum.java
| @@ -14,6 +14,7 @@ import lombok.Getter; | @@ -14,6 +14,7 @@ import lombok.Getter; | ||
| 14 | @AllArgsConstructor | 14 | @AllArgsConstructor |
| 15 | public enum BpmTaskStatusEnum { | 15 | public enum BpmTaskStatusEnum { |
| 16 | 16 | ||
| 17 | + SKIP(-2, "跳过"), | ||
| 17 | NOT_START(-1, "未开始"), | 18 | NOT_START(-1, "未开始"), |
| 18 | RUNNING(1, "审批中"), | 19 | RUNNING(1, "审批中"), |
| 19 | APPROVE(2, "审批通过"), | 20 | APPROVE(2, "审批通过"), |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java
| @@ -800,9 +800,10 @@ public class BpmnModelUtils { | @@ -800,9 +800,10 @@ public class BpmnModelUtils { | ||
| 800 | || currentElement instanceof EndEvent | 800 | || currentElement instanceof EndEvent |
| 801 | || currentElement instanceof UserTask | 801 | || currentElement instanceof UserTask |
| 802 | || currentElement instanceof ServiceTask) { | 802 | || currentElement instanceof ServiceTask) { |
| 803 | - // 添加元素 | 803 | + // 添加节点 |
| 804 | FlowNode flowNode = (FlowNode) currentElement; | 804 | FlowNode flowNode = (FlowNode) currentElement; |
| 805 | resultElements.add(flowNode); | 805 | resultElements.add(flowNode); |
| 806 | + | ||
| 806 | // 遍历子节点 | 807 | // 遍历子节点 |
| 807 | flowNode.getOutgoingFlows().forEach( | 808 | flowNode.getOutgoingFlows().forEach( |
| 808 | nextElement -> simulateNextFlowElements(nextElement.getTargetFlowElement(), variables, resultElements, visitElements)); | 809 | nextElement -> simulateNextFlowElements(nextElement.getTargetFlowElement(), variables, resultElements, visitElements)); |
| @@ -836,6 +837,31 @@ public class BpmnModelUtils { | @@ -836,6 +837,31 @@ public class BpmnModelUtils { | ||
| 836 | } | 837 | } |
| 837 | 838 | ||
| 838 | /** | 839 | /** |
| 840 | + * 判断是否跳过此节点 | ||
| 841 | + * | ||
| 842 | + * @param flowNode 节点 | ||
| 843 | + * @param variables 流程变量 | ||
| 844 | + */ | ||
| 845 | + public static boolean isSkipNode(FlowElement flowNode, Map<String, Object> variables) { | ||
| 846 | + // 1. 检查节点是否有跳过表达式(支持多种任务节点类型) | ||
| 847 | + String skipExpression = null; | ||
| 848 | + if (flowNode instanceof UserTask) { | ||
| 849 | + skipExpression = ((UserTask) flowNode).getSkipExpression(); | ||
| 850 | + } else if (flowNode instanceof ServiceTask) { | ||
| 851 | + skipExpression = ((ServiceTask) flowNode).getSkipExpression(); | ||
| 852 | + } else if (flowNode instanceof ScriptTask) { | ||
| 853 | + skipExpression = ((ScriptTask) flowNode).getSkipExpression(); | ||
| 854 | + } | ||
| 855 | + | ||
| 856 | + if (StrUtil.isEmpty(skipExpression)) { | ||
| 857 | + return false; | ||
| 858 | + } | ||
| 859 | + | ||
| 860 | + // 2. 计算跳过表达式的值 | ||
| 861 | + return evalConditionExpress(variables, skipExpression); | ||
| 862 | + } | ||
| 863 | + | ||
| 864 | + /** | ||
| 839 | * 根据当前节点,获取下一个节点 | 865 | * 根据当前节点,获取下一个节点 |
| 840 | * | 866 | * |
| 841 | * @param currentElement 当前节点 | 867 | * @param currentElement 当前节点 |
| @@ -997,7 +1023,7 @@ public class BpmnModelUtils { | @@ -997,7 +1023,7 @@ public class BpmnModelUtils { | ||
| 997 | * @return 是否满足条件 | 1023 | * @return 是否满足条件 |
| 998 | */ | 1024 | */ |
| 999 | public static boolean evalConditionExpress(Map<String, Object> variables, String expression) { | 1025 | public static boolean evalConditionExpress(Map<String, Object> variables, String expression) { |
| 1000 | - if (expression == null) { | 1026 | + if (StrUtil.isEmpty(expression)) { |
| 1001 | return Boolean.FALSE; | 1027 | return Boolean.FALSE; |
| 1002 | } | 1028 | } |
| 1003 | // 如果 variables 为空,则创建一个的原因?可能 expression 的计算,不依赖于 variables | 1029 | // 如果 variables 为空,则创建一个的原因?可能 expression 的计算,不依赖于 variables |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
| @@ -464,6 +464,10 @@ public class SimpleModelUtils { | @@ -464,6 +464,10 @@ public class SimpleModelUtils { | ||
| 464 | addReasonRequire(node.getReasonRequire(), userTask); | 464 | addReasonRequire(node.getReasonRequire(), userTask); |
| 465 | // 节点类型 | 465 | // 节点类型 |
| 466 | addNodeType(node.getType(), userTask); | 466 | addNodeType(node.getType(), userTask); |
| 467 | + // 添加跳过表达式 | ||
| 468 | + if (StrUtil.isNotEmpty(node.getSkipExpression())) { | ||
| 469 | + userTask.setSkipExpression(node.getSkipExpression()); | ||
| 470 | + } | ||
| 467 | return userTask; | 471 | return userTask; |
| 468 | } | 472 | } |
| 469 | 473 | ||
| @@ -968,7 +972,7 @@ public class SimpleModelUtils { | @@ -968,7 +972,7 @@ public class SimpleModelUtils { | ||
| 968 | || nodeType == BpmSimpleModelNodeTypeEnum.COPY_NODE | 972 | || nodeType == BpmSimpleModelNodeTypeEnum.COPY_NODE |
| 969 | || nodeType == BpmSimpleModelNodeTypeEnum.CHILD_PROCESS | 973 | || nodeType == BpmSimpleModelNodeTypeEnum.CHILD_PROCESS |
| 970 | || nodeType == BpmSimpleModelNodeTypeEnum.END_NODE) { | 974 | || nodeType == BpmSimpleModelNodeTypeEnum.END_NODE) { |
| 971 | - // 添加元素 | 975 | + // 添加此节点 |
| 972 | resultNodes.add(currentNode); | 976 | resultNodes.add(currentNode); |
| 973 | } | 977 | } |
| 974 | 978 | ||
| @@ -1014,6 +1018,16 @@ public class SimpleModelUtils { | @@ -1014,6 +1018,16 @@ public class SimpleModelUtils { | ||
| 1014 | simulateNextNode(currentNode.getChildNode(), variables, resultNodes); | 1018 | simulateNextNode(currentNode.getChildNode(), variables, resultNodes); |
| 1015 | } | 1019 | } |
| 1016 | 1020 | ||
| 1021 | + /** | ||
| 1022 | + * 根据跳过表达式,判断是否跳过此节点 | ||
| 1023 | + */ | ||
| 1024 | + public static boolean isSkipNode(BpmSimpleModelNodeVO currentNode, Map<String, Object> variables) { | ||
| 1025 | + if (StrUtil.isEmpty(currentNode.getSkipExpression())) { | ||
| 1026 | + return false; | ||
| 1027 | + } | ||
| 1028 | + return BpmnModelUtils.evalConditionExpress(variables, currentNode.getSkipExpression()); | ||
| 1029 | + } | ||
| 1030 | + | ||
| 1017 | public static boolean evalConditionExpress(Map<String, Object> variables, BpmSimpleModelNodeVO.ConditionSetting conditionSetting) { | 1031 | public static boolean evalConditionExpress(Map<String, Object> variables, BpmSimpleModelNodeVO.ConditionSetting conditionSetting) { |
| 1018 | return BpmnModelUtils.evalConditionExpress(variables, buildConditionExpression(conditionSetting)); | 1032 | return BpmnModelUtils.evalConditionExpress(variables, buildConditionExpression(conditionSetting)); |
| 1019 | } | 1033 | } |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
| @@ -398,7 +398,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -398,7 +398,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 398 | ? BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType() | 398 | ? BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType() |
| 399 | : ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”的识别 | 399 | : ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”的识别 |
| 400 | BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType())) | 400 | BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType())) |
| 401 | - .setStatus(FlowableUtils.getTaskStatus(task)) | 401 | + .setStatus(getEndActivityNodeStatus(task)) |
| 402 | .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode)) | 402 | .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode)) |
| 403 | .setStartTime(DateUtils.of(task.getCreateTime())).setEndTime(DateUtils.of(task.getEndTime())) | 403 | .setStartTime(DateUtils.of(task.getCreateTime())).setEndTime(DateUtils.of(task.getEndTime())) |
| 404 | .setTasks(singletonList(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task))); | 404 | .setTasks(singletonList(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task))); |
| @@ -463,6 +463,18 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -463,6 +463,18 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 463 | } | 463 | } |
| 464 | 464 | ||
| 465 | /** | 465 | /** |
| 466 | + * 获取结束节点的状态 | ||
| 467 | + */ | ||
| 468 | + private Integer getEndActivityNodeStatus(HistoricTaskInstance task) { | ||
| 469 | + Integer status = FlowableUtils.getTaskStatus(task); | ||
| 470 | + if (status != null) { | ||
| 471 | + return status; | ||
| 472 | + } | ||
| 473 | + // 结束节点未获取到状态,为跳过状态。可见 bpmn 或者 simple 的 skipExpression | ||
| 474 | + return BpmTaskStatusEnum.SKIP.getStatus(); | ||
| 475 | + } | ||
| 476 | + | ||
| 477 | + /** | ||
| 466 | * 获得【进行中】的活动节点们 | 478 | * 获得【进行中】的活动节点们 |
| 467 | */ | 479 | */ |
| 468 | private List<ActivityNode> getRunApproveNodeList(Long startUserId, | 480 | private List<ActivityNode> getRunApproveNodeList(Long startUserId, |
| @@ -565,10 +577,14 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -565,10 +577,14 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 565 | if (runActivityIds.contains(node.getId())) { | 577 | if (runActivityIds.contains(node.getId())) { |
| 566 | return null; | 578 | return null; |
| 567 | } | 579 | } |
| 568 | - | 580 | + Integer status = BpmTaskStatusEnum.NOT_START.getStatus(); |
| 581 | + // 如果节点被跳过。设置状态为跳过 | ||
| 582 | + if (SimpleModelUtils.isSkipNode(node, processVariables)) { | ||
| 583 | + status = BpmTaskStatusEnum.SKIP.getStatus(); | ||
| 584 | + } | ||
| 569 | ActivityNode activityNode = new ActivityNode().setId(node.getId()).setName(node.getName()) | 585 | ActivityNode activityNode = new ActivityNode().setId(node.getId()).setName(node.getName()) |
| 570 | .setNodeType(node.getType()).setCandidateStrategy(node.getCandidateStrategy()) | 586 | .setNodeType(node.getType()).setCandidateStrategy(node.getCandidateStrategy()) |
| 571 | - .setStatus(BpmTaskStatusEnum.NOT_START.getStatus()); | 587 | + .setStatus(status); |
| 572 | 588 | ||
| 573 | // 1. 开始节点/审批节点 | 589 | // 1. 开始节点/审批节点 |
| 574 | if (ObjectUtils.equalsAny(node.getType(), | 590 | if (ObjectUtils.equalsAny(node.getType(), |
| @@ -608,8 +624,13 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | @@ -608,8 +624,13 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService | ||
| 608 | if (runActivityIds.contains(node.getId())) { | 624 | if (runActivityIds.contains(node.getId())) { |
| 609 | return null; | 625 | return null; |
| 610 | } | 626 | } |
| 627 | + Integer status = BpmTaskStatusEnum.NOT_START.getStatus(); | ||
| 628 | + // 如果节点被跳过,状态设置为跳过 | ||
| 629 | + if(BpmnModelUtils.isSkipNode(node, processVariables)){ | ||
| 630 | + status = BpmTaskStatusEnum.SKIP.getStatus(); | ||
| 631 | + } | ||
| 611 | ActivityNode activityNode = new ActivityNode().setId(node.getId()) | 632 | ActivityNode activityNode = new ActivityNode().setId(node.getId()) |
| 612 | - .setStatus(BpmTaskStatusEnum.NOT_START.getStatus()); | 633 | + .setStatus(status); |
| 613 | 634 | ||
| 614 | // 1. 开始节点 | 635 | // 1. 开始节点 |
| 615 | if (node instanceof StartEvent) { | 636 | if (node instanceof StartEvent) { |
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
| @@ -947,7 +947,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -947,7 +947,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 947 | BpmCommentTypeEnum.DELEGATE_START.formatComment(currentUser.getNickname(), delegateUser.getNickname(), reqVO.getReason())); | 947 | BpmCommentTypeEnum.DELEGATE_START.formatComment(currentUser.getNickname(), delegateUser.getNickname(), reqVO.getReason())); |
| 948 | 948 | ||
| 949 | // 3.1 设置任务所有人 (owner) 为原任务的处理人 (assignee) | 949 | // 3.1 设置任务所有人 (owner) 为原任务的处理人 (assignee) |
| 950 | - taskService.setOwner(taskId, task.getAssignee()); | 950 | + // 特殊:如果已经被委派(owner 非空),则不需要更新 owner:https://gitee.com/zhijiantianya/yudao-cloud/issues/ICJ153 |
| 951 | + if (StrUtil.isEmpty(task.getOwner())) { | ||
| 952 | + taskService.setOwner(taskId, task.getAssignee()); | ||
| 953 | + } | ||
| 951 | // 3.2 执行委派,将任务委派给 delegateUser | 954 | // 3.2 执行委派,将任务委派给 delegateUser |
| 952 | taskService.delegateTask(taskId, reqVO.getDelegateUserId().toString()); | 955 | taskService.delegateTask(taskId, reqVO.getDelegateUserId().toString()); |
| 953 | // 补充说明:委托不单独设置状态。如果需要,可通过 Task 的 DelegationState 字段,判断是否为 DelegationState.PENDING 委托中 | 956 | // 补充说明:委托不单独设置状态。如果需要,可通过 Task 的 DelegationState 字段,判断是否为 DelegationState.PENDING 委托中 |
| @@ -973,7 +976,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { | @@ -973,7 +976,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { | ||
| 973 | BpmCommentTypeEnum.TRANSFER.formatComment(currentUser.getNickname(), assigneeUser.getNickname(), reqVO.getReason())); | 976 | BpmCommentTypeEnum.TRANSFER.formatComment(currentUser.getNickname(), assigneeUser.getNickname(), reqVO.getReason())); |
| 974 | 977 | ||
| 975 | // 3.1 设置任务所有人 (owner) 为原任务的处理人 (assignee) | 978 | // 3.1 设置任务所有人 (owner) 为原任务的处理人 (assignee) |
| 976 | - taskService.setOwner(taskId, task.getAssignee()); | 979 | + // 特殊:如果已经被转派(owner 非空),则不需要更新 owner:https://gitee.com/zhijiantianya/yudao-cloud/issues/ICJ153 |
| 980 | + if (StrUtil.isEmpty(task.getOwner())) { | ||
| 981 | + taskService.setOwner(taskId, task.getAssignee()); | ||
| 982 | + } | ||
| 977 | // 3.2 执行转派(审批人),将任务转派给 assigneeUser | 983 | // 3.2 执行转派(审批人),将任务转派给 assigneeUser |
| 978 | // 委托( delegate)和转派(transfer)的差别,就在这块的调用!!!! | 984 | // 委托( delegate)和转派(transfer)的差别,就在这块的调用!!!! |
| 979 | taskService.setAssignee(taskId, reqVO.getAssigneeUserId().toString()); | 985 | taskService.setAssignee(taskId, reqVO.getAssigneeUserId().toString()); |