【同步】BOOT 和 CLOUD 的功能
parent
3c5c3ddc87
commit
7d9de01556
|
@ -17,6 +17,7 @@ uv run --with simple-ddl-parser convertor.py dm8 > ../dm/ruoyi-vue-pro-dm8.sql
|
|||
import argparse
|
||||
import pathlib
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Dict, Generator, Optional, Tuple, Union
|
||||
|
@ -293,8 +294,10 @@ class Convertor(ABC):
|
|||
|
||||
# 将parse失败的脚本打印出来
|
||||
if error_scripts:
|
||||
print("!!! 以下内容无法正常解析", file=sys.stderr)
|
||||
for script in error_scripts:
|
||||
print(script)
|
||||
# print to stderr
|
||||
print(script, file=sys.stderr)
|
||||
|
||||
|
||||
class PostgreSQLConvertor(Convertor):
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.springframework.util.Assert;
|
|||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.validation.ObjectError;
|
||||
import org.springframework.web.HttpMediaTypeNotSupportedException;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.MissingServletRequestParameterException;
|
||||
|
@ -101,6 +102,9 @@ public class GlobalExceptionHandler {
|
|||
if (ex instanceof HttpRequestMethodNotSupportedException) {
|
||||
return httpRequestMethodNotSupportedExceptionHandler((HttpRequestMethodNotSupportedException) ex);
|
||||
}
|
||||
if (ex instanceof HttpMediaTypeNotSupportedException) {
|
||||
return httpMediaTypeNotSupportedExceptionHandler((HttpMediaTypeNotSupportedException) ex);
|
||||
}
|
||||
if (ex instanceof ServiceException) {
|
||||
return serviceExceptionHandler((ServiceException) ex);
|
||||
}
|
||||
|
@ -171,17 +175,19 @@ public class GlobalExceptionHandler {
|
|||
/**
|
||||
* 处理 SpringMVC 请求参数类型错误
|
||||
*
|
||||
* 例如说,接口上设置了 @RequestBody实体中 xx 属性类型为 Integer,结果传递 xx 参数类型为 String
|
||||
* 例如说,接口上设置了 @RequestBody 实体中 xx 属性类型为 Integer,结果传递 xx 参数类型为 String
|
||||
*/
|
||||
@ExceptionHandler(HttpMessageNotReadableException.class)
|
||||
public CommonResult<?> methodArgumentTypeInvalidFormatExceptionHandler(HttpMessageNotReadableException ex) {
|
||||
log.warn("[methodArgumentTypeInvalidFormatExceptionHandler]", ex);
|
||||
if(ex.getCause() instanceof InvalidFormatException) {
|
||||
if (ex.getCause() instanceof InvalidFormatException) {
|
||||
InvalidFormatException invalidFormatException = (InvalidFormatException) ex.getCause();
|
||||
return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", invalidFormatException.getValue()));
|
||||
}else {
|
||||
return defaultExceptionHandler(ServletUtils.getRequest(), ex);
|
||||
}
|
||||
if (StrUtil.startWith(ex.getMessage(), "Required request body is missing")) {
|
||||
return CommonResult.error(BAD_REQUEST.getCode(), "请求参数类型错误: request body 缺失");
|
||||
}
|
||||
return defaultExceptionHandler(ServletUtils.getRequest(), ex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -237,6 +243,17 @@ public class GlobalExceptionHandler {
|
|||
return CommonResult.error(METHOD_NOT_ALLOWED.getCode(), String.format("请求方法不正确:%s", ex.getMessage()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 SpringMVC 请求的 Content-Type 不正确
|
||||
*
|
||||
* 例如说,A 接口的 Content-Type 为 application/json,结果请求的 Content-Type 为 application/octet-stream,导致不匹配
|
||||
*/
|
||||
@ExceptionHandler(HttpMediaTypeNotSupportedException.class)
|
||||
public CommonResult<?> httpMediaTypeNotSupportedExceptionHandler(HttpMediaTypeNotSupportedException ex) {
|
||||
log.warn("[httpMediaTypeNotSupportedExceptionHandler]", ex);
|
||||
return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求类型不正确:%s", ex.getMessage()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 Spring Security 权限不足的异常
|
||||
*
|
||||
|
@ -395,7 +412,7 @@ public class GlobalExceptionHandler {
|
|||
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
|
||||
"[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]");
|
||||
}
|
||||
// 9. IOT 物联网
|
||||
// 9. IoT 物联网
|
||||
if (message.contains("iot_")) {
|
||||
log.error("[IoT 物联网 yudao-module-iot - 表结构未导入][参考 https://doc.iocoder.cn/iot/build/ 开启]");
|
||||
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
|
||||
|
|
|
@ -58,7 +58,6 @@ public interface ErrorCodeConstants {
|
|||
ErrorCode TASK_SIGN_DELETE_NO_PARENT = new ErrorCode(1_009_005_012, "任务减签失败,被减签的任务必须是通过加签生成的任务");
|
||||
ErrorCode TASK_TRANSFER_FAIL_USER_REPEAT = new ErrorCode(1_009_005_013, "任务转办失败,转办人和当前审批人为同一人");
|
||||
ErrorCode TASK_TRANSFER_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_014, "任务转办失败,转办人不存在");
|
||||
ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!");
|
||||
ErrorCode TASK_SIGNATURE_NOT_EXISTS = new ErrorCode(1_009_005_015, "签名不能为空!");
|
||||
ErrorCode TASK_REASON_REQUIRE = new ErrorCode(1_009_005_016, "审批意见不能为空!");
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import lombok.Getter;
|
|||
@AllArgsConstructor
|
||||
public enum BpmTaskStatusEnum {
|
||||
|
||||
SKIP(-2, "跳过"),
|
||||
NOT_START(-1, "未开始"),
|
||||
RUNNING(1, "审批中"),
|
||||
APPROVE(2, "审批通过"),
|
||||
|
|
|
@ -71,6 +71,9 @@ public class BpmSimpleModelNodeVO {
|
|||
@Schema(description = "是否填写审批意见", example = "false")
|
||||
private Boolean reasonRequire;
|
||||
|
||||
@Schema(description = "跳过表达式", example = "{true}")
|
||||
private String skipExpression; // 用于审批节点
|
||||
|
||||
/**
|
||||
* 审批节点拒绝处理
|
||||
*/
|
||||
|
|
|
@ -797,12 +797,13 @@ public class BpmnModelUtils {
|
|||
|
||||
// 情况:StartEvent/EndEvent/UserTask/ServiceTask
|
||||
if (currentElement instanceof StartEvent
|
||||
|| currentElement instanceof EndEvent
|
||||
|| currentElement instanceof UserTask
|
||||
|| currentElement instanceof ServiceTask) {
|
||||
// 添加元素
|
||||
|| 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据当前节点,获取下一个节点
|
||||
*
|
||||
|
@ -912,8 +938,8 @@ public class BpmnModelUtils {
|
|||
*/
|
||||
private static SequenceFlow findMatchSequenceFlowByExclusiveGateway(Gateway gateway, Map<String, Object> variables) {
|
||||
SequenceFlow matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(),
|
||||
flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId())
|
||||
&& (evalConditionExpress(variables, flow.getConditionExpression())));
|
||||
flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId())
|
||||
&& (evalConditionExpress(variables, flow.getConditionExpression())));
|
||||
if (matchSequenceFlow == null) {
|
||||
matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(),
|
||||
flow -> ObjUtil.equal(gateway.getDefaultFlow(), flow.getId()));
|
||||
|
@ -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
|
||||
|
|
|
@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
|
|||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.*;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.ConditionGroups;
|
||||
|
@ -17,13 +16,14 @@ import cn.iocoder.yudao.module.bpm.service.task.listener.BpmCallActivityListener
|
|||
import cn.iocoder.yudao.module.bpm.service.task.listener.BpmUserTaskListener;
|
||||
import org.flowable.bpmn.BpmnAutoLayout;
|
||||
import org.flowable.bpmn.constants.BpmnXMLConstants;
|
||||
import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.bpmn.model.*;
|
||||
import org.flowable.bpmn.model.Process;
|
||||
import org.flowable.engine.delegate.ExecutionListener;
|
||||
import org.flowable.engine.delegate.TaskListener;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*;
|
||||
import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.*;
|
||||
import static java.util.Arrays.asList;
|
||||
|
@ -239,13 +239,13 @@ public class SimpleModelUtils {
|
|||
// 3.1 分支有后续节点。即分支 1: A->B->C->D 的情况
|
||||
if (isValidNode(conditionChildNode)) {
|
||||
// 3.1.1 建立与后续的节点的连线。例如说,建立 A->B 的连线
|
||||
SequenceFlow sequenceFlow = ConditionNodeConvert.buildSequenceFlow(node.getId(), conditionChildNode.getId(), item);
|
||||
SequenceFlow sequenceFlow = ConditionNodeConvert.buildSequenceFlow(node.getId(), conditionChildNode.getId(), nodeType, item);
|
||||
process.addFlowElement(sequenceFlow);
|
||||
// 3.1.2 递归调用后续节点连线。例如说,建立 B->C->D 的连线
|
||||
traverseNodeToBuildSequenceFlow(process, conditionChildNode, branchEndNodeId);
|
||||
} else {
|
||||
// 3.2 分支没有后续节点。例如说,建立 A->D 的连线
|
||||
SequenceFlow sequenceFlow = ConditionNodeConvert.buildSequenceFlow(node.getId(), branchEndNodeId, item);
|
||||
SequenceFlow sequenceFlow = ConditionNodeConvert.buildSequenceFlow(node.getId(), branchEndNodeId, nodeType, item);
|
||||
process.addFlowElement(sequenceFlow);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -591,17 +595,23 @@ public class SimpleModelUtils {
|
|||
|
||||
private static class ParallelBranchNodeConvert implements NodeConvert {
|
||||
|
||||
/**
|
||||
* 并行分支使用包容网关。需要设置所有出口条件表达式的值为 true 。原因是,解决 https://t.zsxq.com/m6GXh 反馈问题
|
||||
*
|
||||
* @see {@link ConditionNodeConvert#buildSequenceFlow}
|
||||
*/
|
||||
@Override
|
||||
public List<ParallelGateway> convertList(BpmSimpleModelNodeVO node) {
|
||||
ParallelGateway parallelGateway = new ParallelGateway();
|
||||
parallelGateway.setId(node.getId());
|
||||
public List<InclusiveGateway> convertList(BpmSimpleModelNodeVO node) {
|
||||
|
||||
InclusiveGateway inclusiveGateway = new InclusiveGateway();
|
||||
inclusiveGateway.setId(node.getId());
|
||||
// TODO @jason:setName
|
||||
|
||||
// 并行聚合网关由程序创建,前端不需要传入
|
||||
ParallelGateway joinParallelGateway = new ParallelGateway();
|
||||
// 合并网关 由程序创建,前端不需要传入
|
||||
InclusiveGateway joinParallelGateway = new InclusiveGateway();
|
||||
joinParallelGateway.setId(buildGatewayJoinId(node.getId()));
|
||||
// TODO @jason:setName
|
||||
return CollUtil.newArrayList(parallelGateway, joinParallelGateway);
|
||||
return CollUtil.newArrayList(inclusiveGateway, joinParallelGateway);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -652,8 +662,14 @@ public class SimpleModelUtils {
|
|||
}
|
||||
|
||||
public static SequenceFlow buildSequenceFlow(String sourceId, String targetId,
|
||||
BpmSimpleModelNodeVO node) {
|
||||
String conditionExpression = buildConditionExpression(node.getConditionSetting());
|
||||
BpmSimpleModelNodeTypeEnum nodeType, BpmSimpleModelNodeVO node) {
|
||||
String conditionExpression;
|
||||
// 并行分支,使用包容网关实现,强制设置条件表达式为 true
|
||||
if (BpmSimpleModelNodeTypeEnum.PARALLEL_BRANCH_NODE == nodeType) {
|
||||
conditionExpression ="${true}";
|
||||
} else {
|
||||
conditionExpression = buildConditionExpression(node.getConditionSetting());
|
||||
}
|
||||
return buildBpmnSequenceFlow(sourceId, targetId, node.getId(), node.getName(), conditionExpression);
|
||||
}
|
||||
}
|
||||
|
@ -662,7 +678,6 @@ public class SimpleModelUtils {
|
|||
* 构造条件表达式
|
||||
*/
|
||||
public static String buildConditionExpression(BpmSimpleModelNodeVO.ConditionSetting conditionSetting) {
|
||||
// 并行网关不需要设置条件
|
||||
if (conditionSetting == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -684,15 +699,18 @@ public class SimpleModelUtils {
|
|||
if (conditionGroups == null || CollUtil.isEmpty(conditionGroups.getConditions())) {
|
||||
return null;
|
||||
}
|
||||
List<String> strConditionGroups = CollectionUtils.convertList(conditionGroups.getConditions(), item -> {
|
||||
List<String> strConditionGroups = convertList(conditionGroups.getConditions(), item -> {
|
||||
if (CollUtil.isEmpty(item.getRules())) {
|
||||
return "";
|
||||
}
|
||||
// 构造规则表达式
|
||||
List<String> list = CollectionUtils.convertList(item.getRules(), (rule) -> {
|
||||
List<String> list = convertList(item.getRules(), (rule) -> {
|
||||
String rightSide = NumberUtil.isNumber(rule.getRightSide()) ? rule.getRightSide()
|
||||
: "\"" + rule.getRightSide() + "\""; // 如果非数值类型加引号
|
||||
return String.format(" %s %s var:convertByType(%s,%s)", rule.getLeftSide(), rule.getOpCode(), rule.getLeftSide(), rightSide);
|
||||
return String.format(" vars:getOrDefault(%s, null) %s var:convertByType(%s,%s) ",
|
||||
rule.getLeftSide(), // 左侧:读取变量
|
||||
rule.getOpCode(), // 中间:操作符,比较
|
||||
rule.getLeftSide(), rightSide); // 右侧:转换变量,VariableConvertByTypeExpressionFunction
|
||||
});
|
||||
// 构造条件组的表达式
|
||||
Boolean and = item.getAnd();
|
||||
|
@ -954,7 +972,7 @@ public class SimpleModelUtils {
|
|||
|| nodeType == BpmSimpleModelNodeTypeEnum.COPY_NODE
|
||||
|| nodeType == BpmSimpleModelNodeTypeEnum.CHILD_PROCESS
|
||||
|| nodeType == BpmSimpleModelNodeTypeEnum.END_NODE) {
|
||||
// 添加元素
|
||||
// 添加此节点
|
||||
resultNodes.add(currentNode);
|
||||
}
|
||||
|
||||
|
@ -1000,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));
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 非空),则不需要更新 owner:https://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 非空),则不需要更新 owner:https://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());
|
||||
|
|
Loading…
Reference in New Issue