mirror of
https://github.com/YunaiV/ruoyi-vue-pro.git
synced 2026-03-30 04:31:42 +00:00
Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro
# Conflicts: # yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -5,6 +5,9 @@ import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.servlet.JakartaServletUtil;
|
||||
import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiErrorLogCommonApi;
|
||||
import cn.iocoder.yudao.framework.common.biz.infra.logger.dto.ApiErrorLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
@@ -13,9 +16,11 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||
import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiErrorLogCommonApi;
|
||||
import cn.iocoder.yudao.framework.common.biz.infra.logger.dto.ApiErrorLogCreateReqDTO;
|
||||
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
import jakarta.validation.ValidationException;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
@@ -24,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;
|
||||
@@ -31,11 +37,8 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
|
||||
import org.springframework.web.servlet.NoHandlerFoundException;
|
||||
import org.springframework.web.servlet.resource.NoResourceFoundException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import javax.validation.ValidationException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -93,12 +96,15 @@ public class GlobalExceptionHandler {
|
||||
if (ex instanceof NoHandlerFoundException) {
|
||||
return noHandlerFoundExceptionHandler((NoHandlerFoundException) ex);
|
||||
}
|
||||
// if (ex instanceof NoResourceFoundException) {
|
||||
// return noResourceFoundExceptionHandler(request, (NoResourceFoundException) ex);
|
||||
// }
|
||||
if (ex instanceof NoResourceFoundException) {
|
||||
return noResourceFoundExceptionHandler(request, (NoResourceFoundException) ex);
|
||||
}
|
||||
if (ex instanceof HttpRequestMethodNotSupportedException) {
|
||||
return httpRequestMethodNotSupportedExceptionHandler((HttpRequestMethodNotSupportedException) ex);
|
||||
}
|
||||
if (ex instanceof HttpMediaTypeNotSupportedException) {
|
||||
return httpMediaTypeNotSupportedExceptionHandler((HttpMediaTypeNotSupportedException) ex);
|
||||
}
|
||||
if (ex instanceof ServiceException) {
|
||||
return serviceExceptionHandler((ServiceException) ex);
|
||||
}
|
||||
@@ -169,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,14 +223,14 @@ public class GlobalExceptionHandler {
|
||||
return CommonResult.error(NOT_FOUND.getCode(), String.format("请求地址不存在:%s", ex.getRequestURL()));
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 处理 SpringMVC 请求地址不存在
|
||||
// */
|
||||
// @ExceptionHandler(NoResourceFoundException.class)
|
||||
// private CommonResult<?> noResourceFoundExceptionHandler(HttpServletRequest req, NoResourceFoundException ex) {
|
||||
// log.warn("[noResourceFoundExceptionHandler]", ex);
|
||||
// return CommonResult.error(NOT_FOUND.getCode(), String.format("请求地址不存在:%s", ex.getResourcePath()));
|
||||
// }
|
||||
/**
|
||||
* 处理 SpringMVC 请求地址不存在
|
||||
*/
|
||||
@ExceptionHandler(NoResourceFoundException.class)
|
||||
private CommonResult<?> noResourceFoundExceptionHandler(HttpServletRequest req, NoResourceFoundException ex) {
|
||||
log.warn("[noResourceFoundExceptionHandler]", ex);
|
||||
return CommonResult.error(NOT_FOUND.getCode(), String.format("请求地址不存在:%s", ex.getResourcePath()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 SpringMVC 请求方法不正确
|
||||
@@ -235,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 权限不足的异常
|
||||
*
|
||||
@@ -325,12 +344,12 @@ public class GlobalExceptionHandler {
|
||||
errorLog.setApplicationName(applicationName);
|
||||
errorLog.setRequestUrl(request.getRequestURI());
|
||||
Map<String, Object> requestParams = MapUtil.<String, Object>builder()
|
||||
.put("query", ServletUtils.getParamMap(request))
|
||||
.put("body", ServletUtils.getBody(request)).build();
|
||||
.put("query", JakartaServletUtil.getParamMap(request))
|
||||
.put("body", JakartaServletUtil.getBody(request)).build();
|
||||
errorLog.setRequestParams(JsonUtils.toJsonString(requestParams));
|
||||
errorLog.setRequestMethod(request.getMethod());
|
||||
errorLog.setUserAgent(ServletUtils.getUserAgent(request));
|
||||
errorLog.setUserIp(ServletUtils.getClientIP(request));
|
||||
errorLog.setUserIp(JakartaServletUtil.getClientIP(request));
|
||||
errorLog.setExceptionTime(LocalDateTime.now());
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,9 @@ public class BpmSimpleModelNodeVO {
|
||||
@Schema(description = "是否填写审批意见", example = "false")
|
||||
private Boolean reasonRequire;
|
||||
|
||||
@Schema(description = "跳过表达式", example = "{true}")
|
||||
private String skipExpression; // 用于审批节点
|
||||
|
||||
/**
|
||||
* 审批节点拒绝处理
|
||||
*/
|
||||
|
||||
@@ -40,7 +40,7 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_EXISTS = new ErrorCode(1_009_004_004, "任务({})的候选人({})不存在");
|
||||
ErrorCode PROCESS_INSTANCE_START_USER_CAN_START = new ErrorCode(1_009_004_005, "发起流程失败,你没有权限发起该流程");
|
||||
ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_005, "流程取消失败,该流程不允许取消");
|
||||
ErrorCode PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR = new ErrorCode(1_009_004_006, "流程 Http 触发器请求调用失败");
|
||||
ErrorCode PROCESS_INSTANCE_HTTP_CALL_ERROR = new ErrorCode(1_009_004_006, "流程 Http 请求调用失败");
|
||||
ErrorCode PROCESS_INSTANCE_APPROVE_USER_SELECT_ASSIGNEES_NOT_CONFIG = new ErrorCode(1_009_004_007, "下一个任务({})的审批人未配置");
|
||||
ErrorCode PROCESS_INSTANCE_CANCEL_CHILD_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_008, "子流程取消失败,子流程不允许取消");
|
||||
|
||||
@@ -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, "审批通过"),
|
||||
|
||||
@@ -6,15 +6,15 @@ import cn.iocoder.yudao.framework.common.core.KeyValue;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.spring.SpringUtils;
|
||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||
import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
|
||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmHttpRequestParamTypeEnum;
|
||||
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
@@ -26,7 +26,7 @@ import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_HTTP_CALL_ERROR;
|
||||
|
||||
/**
|
||||
* 工作流发起 HTTP 请求工具类
|
||||
@@ -42,7 +42,6 @@ public class BpmHttpRequestUtils {
|
||||
List<BpmSimpleModelNodeVO.HttpRequestParam> bodyParams,
|
||||
Boolean handleResponse,
|
||||
List<KeyValue<String, String>> response) {
|
||||
RestTemplate restTemplate = SpringUtils.getBean(RestTemplate.class);
|
||||
BpmProcessInstanceService processInstanceService = SpringUtils.getBean(BpmProcessInstanceService.class);
|
||||
|
||||
// 1.1 设置请求头
|
||||
@@ -51,6 +50,7 @@ public class BpmHttpRequestUtils {
|
||||
MultiValueMap<String, String> body = buildHttpBody(processInstance, bodyParams);
|
||||
|
||||
// 2. 发起请求
|
||||
RestTemplate restTemplate = SpringUtils.getBean(RestTemplate.class);
|
||||
ResponseEntity<String> responseEntity = sendHttpRequest(url, headers, body, restTemplate);
|
||||
|
||||
// 3. 处理返回
|
||||
@@ -78,27 +78,55 @@ public class BpmHttpRequestUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void executeBpmHttpRequest(BpmProcessInstanceStatusEvent event,
|
||||
String url) {
|
||||
// 1.1 设置请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
if (TenantContextHolder.getTenantId() != null) {
|
||||
headers.add(HEADER_TENANT_ID, String.valueOf(TenantContextHolder.getTenantId()));
|
||||
} else {
|
||||
BpmProcessInstanceService processInstanceService = SpringUtils.getBean(BpmProcessInstanceService.class);
|
||||
ProcessInstance processInstance = processInstanceService.getProcessInstance(event.getId());
|
||||
if (processInstance != null) {
|
||||
headers.add(HEADER_TENANT_ID, String.valueOf(TenantContextHolder.getTenantId()));
|
||||
}
|
||||
}
|
||||
// 1.2 设置请求体
|
||||
// MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
|
||||
// body.add("id", event.getId());
|
||||
// body.add("processDefinitionKey", event.getProcessDefinitionKey());
|
||||
// body.add("status", event.getStatus().toString());
|
||||
// if (StrUtil.isNotEmpty(event.getBusinessKey())) {
|
||||
// body.add("businessKey", event.getBusinessKey());
|
||||
// }
|
||||
|
||||
// 2. 发起请求
|
||||
RestTemplate restTemplate = SpringUtils.getBean(RestTemplate.class);
|
||||
sendHttpRequest(url, headers, event, restTemplate);
|
||||
}
|
||||
|
||||
public static ResponseEntity<String> sendHttpRequest(String url,
|
||||
MultiValueMap<String, String> headers,
|
||||
MultiValueMap<String, String> body,
|
||||
Object body,
|
||||
RestTemplate restTemplate) {
|
||||
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers);
|
||||
HttpEntity<Object> requestEntity = new HttpEntity<>(body, headers);
|
||||
ResponseEntity<String> responseEntity;
|
||||
try {
|
||||
responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
|
||||
log.info("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity);
|
||||
log.info("[sendHttpRequest][HTTP 请求,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity);
|
||||
} catch (RestClientException e) {
|
||||
log.error("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage());
|
||||
throw exception(PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR);
|
||||
log.error("[sendHttpRequest][HTTP 请求,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage());
|
||||
throw exception(PROCESS_INSTANCE_HTTP_CALL_ERROR);
|
||||
}
|
||||
return responseEntity;
|
||||
}
|
||||
|
||||
public static MultiValueMap<String, String> buildHttpHeaders(ProcessInstance processInstance,
|
||||
List<BpmSimpleModelNodeVO.HttpRequestParam> headerSettings) {
|
||||
Map<String, Object> processVariables = processInstance.getProcessVariables();
|
||||
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
|
||||
headers.add(HEADER_TENANT_ID, processInstance.getTenantId());
|
||||
Map<String, Object> processVariables = processInstance.getProcessVariables();
|
||||
addHttpRequestParam(headers, headerSettings, processVariables);
|
||||
return headers;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -32,7 +32,7 @@ public class CrmPermissionUtils {
|
||||
* @return 是/否
|
||||
*/
|
||||
public static boolean isCrmAdmin() {
|
||||
PermissionApi permissionApi = SpringUtil.getBean(PermissionApi.class);
|
||||
PermissionCommonApi permissionApi = SpringUtil.getBean(PermissionCommonApi.class);
|
||||
return permissionApi.hasAnyRoles(getLoginUserId(), RoleCodeEnum.CRM_ADMIN.getCode());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user