From db9534073b0b05a46395c0532a43df00f879401c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=B1=E9=87=8E=E7=BE=A1=E6=B0=91?= Date: Thu, 20 Feb 2025 02:43:13 +0000 Subject: [PATCH 01/22] =?UTF-8?q?=E3=80=90bugfix=E3=80=91=E6=96=B0?= =?UTF-8?q?=E4=BA=BA=E5=88=B8=E5=B7=B2=E5=85=B3=E9=97=AD=E4=BD=86=E6=98=AF?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=E6=97=B6=E4=BB=8D=E7=84=B6=E5=8F=91=E6=94=BE?= =?UTF-8?q?=E4=BA=86update=20=20module/promotion/dal/mysql/coupon/CouponTe?= =?UTF-8?q?mplateMapper.java.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 山野羡民 --- .../module/promotion/dal/mysql/coupon/CouponTemplateMapper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java index 29b7711265..3096a49f3c 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java @@ -47,7 +47,7 @@ public interface CouponTemplateMapper extends BaseMapperX { } default List selectListByTakeType(Integer takeType) { - return selectList(CouponTemplateDO::getTakeType, takeType); + return selectList(CouponTemplateDO::getTakeType, takeType, CouponTemplateDO::getStatus, CommonStatusEnum.ENABLE.getStatus()); } default List selectList(List canTakeTypes, Integer productScope, Long productScopeValue, Integer count) { From 23844b930cdafa34edf5f45fd5b911cfb7b65eed Mon Sep 17 00:00:00 2001 From: smallNorthLee <18210040298@163.com> Date: Wed, 12 Mar 2025 22:42:32 +0800 Subject: [PATCH 02/22] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E5=AE=A1?= =?UTF-8?q?=E6=89=B9=E8=8A=82=E7=82=B9=E8=A1=A8=E5=8D=95=E6=97=A0=E5=8F=AF?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=AD=97=E6=AE=B5=E6=97=B6=EF=BC=8Cvariables?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=8F=98=E9=87=8F=E5=80=BC=E4=B8=BA=E7=A9=BA?= =?UTF-8?q?=EF=BC=8C=E6=B5=81=E7=A8=8B=E8=8A=82=E7=82=B9=E6=B5=81=E8=BD=AC?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flowable/core/util/BpmnModelUtils.java | 9 +-------- .../bpm/service/task/BpmTaskServiceImpl.java | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java index c471826306..1cccf18f04 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java @@ -907,16 +907,9 @@ public class BpmnModelUtils { * @return 符合条件的路径 */ private static SequenceFlow findMatchSequenceFlowByExclusiveGateway(Gateway gateway, Map variables) { - // TODO 表单无可编辑字段时variables为空,流程走向会出现问题,比如流程审批过程中无需要修改的字段值, - SequenceFlow matchSequenceFlow; - if (CollUtil.isNotEmpty(variables)){ - matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(), + SequenceFlow matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(), flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId()) && (evalConditionExpress(variables, flow.getConditionExpression()))); - }else { - matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(), - flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId())); - } if (matchSequenceFlow == null) { matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(), flow -> ObjUtil.equal(gateway.getDefaultFlow(), flow.getId())); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index eab70f921b..aeabde6f03 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -558,12 +558,21 @@ public class BpmTaskServiceImpl implements BpmTaskService { taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.APPROVE.getType(), BpmCommentTypeEnum.APPROVE.formatComment(reqVO.getReason())); // 2.3 调用 BPM complete 去完成任务 + // 如果流程变量前端传空,需要从历史实例中获取,原因:前端表单如果在当前节点无可编辑的字段时variables一定会为空 + // 场景一:A节点发起,B节点表单无可编辑字段,审批通过时,C节点需要流程变量获取下一个执行节点,但因为B节点无可编辑的字段,variables为空,流程可能出现问题 + // 场景二:A节点发起,B节点只有某一个字段可编辑(比如day),但C节点需要多个节点(比如workday,在发起时填写,因为B节点只有day的编辑权限,在审批后。variables会缺少work的值) + // 历史中的变量值 + Map variables = new HashMap<>(instance.getProcessVariables()); + // 如果变量值不为空,则覆盖历史变量 + if (CollUtil.isNotEmpty(reqVO.getVariables())) { + variables.putAll(reqVO.getVariables()); + } // 校验并处理 APPROVE_USER_SELECT 当前审批人,选择下一节点审批人的逻辑 - Map variables = validateAndSetNextAssignees(task.getTaskDefinitionKey(), reqVO.getVariables(), + Map resVariables = validateAndSetNextAssignees(task.getTaskDefinitionKey(), variables, bpmnModel, reqVO.getNextAssignees(), instance); // 完成任务 - runtimeService.setVariables(task.getProcessInstanceId(), variables); - taskService.complete(task.getId(), variables, true); + runtimeService.setVariables(task.getProcessInstanceId(), resVariables); + taskService.complete(task.getId(), resVariables, true); // 【加签专属】处理加签任务 handleParentTaskIfSign(task.getParentTaskId()); From c2789f628c2c053b50986d25de057cb2efcc6953 Mon Sep 17 00:00:00 2001 From: smallNorthLee <18210040298@163.com> Date: Wed, 12 Mar 2025 22:46:31 +0800 Subject: [PATCH 03/22] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E5=AE=A1?= =?UTF-8?q?=E6=89=B9=E8=8A=82=E7=82=B9=E8=A1=A8=E5=8D=95=E6=97=A0=E5=8F=AF?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=AD=97=E6=AE=B5=E6=97=B6=EF=BC=8Cvariables?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=8F=98=E9=87=8F=E5=80=BC=E4=B8=BA=E7=A9=BA?= =?UTF-8?q?=EF=BC=8C=E6=B5=81=E7=A8=8B=E8=8A=82=E7=82=B9=E6=B5=81=E8=BD=AC?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bpm/service/task/BpmTaskServiceImpl.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index aeabde6f03..60410d7769 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -557,22 +557,27 @@ public class BpmTaskServiceImpl implements BpmTaskService { // 2.2 添加评论 taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.APPROVE.getType(), BpmCommentTypeEnum.APPROVE.formatComment(reqVO.getReason())); - // 2.3 调用 BPM complete 去完成任务 + // 如果流程变量前端传空,需要从历史实例中获取,原因:前端表单如果在当前节点无可编辑的字段时variables一定会为空 // 场景一:A节点发起,B节点表单无可编辑字段,审批通过时,C节点需要流程变量获取下一个执行节点,但因为B节点无可编辑的字段,variables为空,流程可能出现问题 // 场景二:A节点发起,B节点只有某一个字段可编辑(比如day),但C节点需要多个节点(比如workday,在发起时填写,因为B节点只有day的编辑权限,在审批后。variables会缺少work的值) // 历史中的变量值 - Map variables = new HashMap<>(instance.getProcessVariables()); - // 如果变量值不为空,则覆盖历史变量 + // 3.1 设置流程变量 + Map processVariables = new HashMap<>(); + // 3.2 获取历史中流程变量 + if (CollUtil.isNotEmpty(instance.getProcessVariables())) { + processVariables.putAll(instance.getProcessVariables()); + } + // 3.3 合并前端传递的流程变量,以前端为准 if (CollUtil.isNotEmpty(reqVO.getVariables())) { - variables.putAll(reqVO.getVariables()); + processVariables.putAll(reqVO.getVariables()); } // 校验并处理 APPROVE_USER_SELECT 当前审批人,选择下一节点审批人的逻辑 - Map resVariables = validateAndSetNextAssignees(task.getTaskDefinitionKey(), variables, + Map variables = validateAndSetNextAssignees(task.getTaskDefinitionKey(), processVariables, bpmnModel, reqVO.getNextAssignees(), instance); - // 完成任务 - runtimeService.setVariables(task.getProcessInstanceId(), resVariables); - taskService.complete(task.getId(), resVariables, true); + // 3.4 调用 BPM complete 去完成任务 + runtimeService.setVariables(task.getProcessInstanceId(), variables); + taskService.complete(task.getId(), variables, true); // 【加签专属】处理加签任务 handleParentTaskIfSign(task.getParentTaskId()); From 575e7a38f37e32d28e0488c523cf55801f2a694f Mon Sep 17 00:00:00 2001 From: lizhixian <18210040298@163.com> Date: Thu, 13 Mar 2025 09:38:15 +0800 Subject: [PATCH 04/22] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E5=AE=A1?= =?UTF-8?q?=E6=89=B9=E8=8A=82=E7=82=B9=E8=A1=A8=E5=8D=95=E6=97=A0=E5=8F=AF?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=AD=97=E6=AE=B5=E6=97=B6=EF=BC=8Cvariables?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=8F=98=E9=87=8F=E5=80=BC=E4=B8=BA=E7=A9=BA?= =?UTF-8?q?=EF=BC=8C=E6=B5=81=E7=A8=8B=E8=8A=82=E7=82=B9=E6=B5=81=E8=BD=AC?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flowable/core/util/BpmnModelUtils.java | 10 +------ .../bpm/service/task/BpmTaskServiceImpl.java | 30 +++++++++++-------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java index 2ec26b407e..1cccf18f04 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java @@ -907,17 +907,9 @@ public class BpmnModelUtils { * @return 符合条件的路径 */ private static SequenceFlow findMatchSequenceFlowByExclusiveGateway(Gateway gateway, Map variables) { - // TODO 表单无可编辑字段时variables为空,流程走向会出现问题,比如流程审批过程中无需要修改的字段值, - // TODO @小北:是不是还是保证,编辑的时候,如果计算下一个节点,还是 variables 是完整体?而不是空的!!!(可以微信讨论下) - SequenceFlow matchSequenceFlow; - if (CollUtil.isNotEmpty(variables)) { - matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(), + SequenceFlow matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(), flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId()) && (evalConditionExpress(variables, flow.getConditionExpression()))); - } else { - matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(), - flow -> ObjUtil.notEqual(gateway.getDefaultFlow(), flow.getId())); - } if (matchSequenceFlow == null) { matchSequenceFlow = CollUtil.findOne(gateway.getOutgoingFlows(), flow -> ObjUtil.equal(gateway.getDefaultFlow(), flow.getId())); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index f96d0cb392..b15a59c540 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -557,11 +557,24 @@ public class BpmTaskServiceImpl implements BpmTaskService { // 2.2 添加评论 taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.APPROVE.getType(), BpmCommentTypeEnum.APPROVE.formatComment(reqVO.getReason())); - // 2.3 校验并处理 APPROVE_USER_SELECT 当前审批人,选择下一节点审批人的逻辑 - Map variables = validateAndSetNextAssignees(task.getTaskDefinitionKey(), reqVO.getVariables(), + // 如果流程变量前端传空,需要从历史实例中获取,原因:前端表单如果在当前节点无可编辑的字段时variables一定会为空 + // 场景一:A节点发起,B节点表单无可编辑字段,审批通过时,C节点需要流程变量获取下一个执行节点,但因为B节点无可编辑的字段,variables为空,流程可能出现问题 + // 场景二:A节点发起,B节点只有某一个字段可编辑(比如day),但C节点需要多个节点(比如workday,在发起时填写,因为B节点只有day的编辑权限,在审批后。variables会缺少work的值) + // 3.1 设置流程变量 + Map processVariables = new HashMap<>(); + // 3.2 获取历史中流程变量 + if (CollUtil.isNotEmpty(instance.getProcessVariables())) { + processVariables.putAll(instance.getProcessVariables()); + } + // 3.3 合并前端传递的流程变量,以前端为准 + if (CollUtil.isNotEmpty(reqVO.getVariables())) { + processVariables.putAll(reqVO.getVariables()); + } + // 3.4 校验并处理 APPROVE_USER_SELECT 当前审批人,选择下一节点审批人的逻辑 + Map variables = validateAndSetNextAssignees(task.getTaskDefinitionKey(), processVariables, bpmnModel, reqVO.getNextAssignees(), instance); runtimeService.setVariables(task.getProcessInstanceId(), variables); - // 2.4 调用 BPM complete 去完成任务 + // 4 调用 BPM complete 去完成任务 taskService.complete(task.getId(), variables, true); // 【加签专属】处理加签任务 @@ -600,9 +613,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { } processVariables = FlowableUtils.getStartUserSelectAssignees(processInstance.getProcessVariables()); // 特殊:如果当前节点已经存在审批人,则不允许覆盖 - // TODO @小北:【不用改】通过 if return,让逻辑更简洁一点;虽然会多判断一次 processVariables,但是 if else 层级更少。 - if (processVariables != null - && CollUtil.isNotEmpty(processVariables.get(nextFlowNode.getId()))) { + if (processVariables != null && CollUtil.isNotEmpty(processVariables.get(nextFlowNode.getId()))) { continue; } // 设置 PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES @@ -622,13 +633,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { processVariables = FlowableUtils.getApproveUserSelectAssignees(processInstance.getProcessVariables()); if (processVariables == null) { processVariables = new HashMap<>(); - } else { - List approveUserSelectAssignee = processVariables.get(nextFlowNode.getId()); - // 特殊:如果当前节点已经存在审批人,则不允许覆盖 - // TODO @小北:这种,应该可以覆盖呢。 - if (CollUtil.isNotEmpty(approveUserSelectAssignee)) { - continue; - } } // 设置 PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES processVariables.put(nextFlowNode.getId(), assignees); From c9690e144c05a753c258fe84bb5b507f605d9f7a Mon Sep 17 00:00:00 2001 From: lizhixian <18210040298@163.com> Date: Thu, 13 Mar 2025 16:05:13 +0800 Subject: [PATCH 05/22] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E5=AE=A1?= =?UTF-8?q?=E6=89=B9=E8=8A=82=E7=82=B9=E8=A1=A8=E5=8D=95=E6=97=A0=E5=8F=AF?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=AD=97=E6=AE=B5=E6=97=B6=EF=BC=8Cvariables?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=8F=98=E9=87=8F=E5=80=BC=E4=B8=BA=E7=A9=BA?= =?UTF-8?q?=EF=BC=8C=E6=B5=81=E7=A8=8B=E8=8A=82=E7=82=B9=E6=B5=81=E8=BD=AC?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bpm/framework/flowable/core/util/BpmnModelUtils.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java index 1cccf18f04..fdfb724442 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java @@ -21,6 +21,7 @@ import org.flowable.bpmn.converter.BpmnXMLConverter; import org.flowable.bpmn.model.Process; import org.flowable.bpmn.model.*; import org.flowable.common.engine.api.FlowableException; +import org.flowable.common.engine.impl.javax.el.PropertyNotFoundException; import org.flowable.common.engine.impl.util.io.BytesStreamSource; import org.flowable.engine.impl.el.FixedValue; @@ -1006,6 +1007,11 @@ public class BpmnModelUtils { Object result = FlowableUtils.getExpressionValue(variables, expression); return Boolean.TRUE.equals(result); } catch (FlowableException ex) { + // TODO @芋艿 临时方案解决流程变量中不包含条件表达式时报错问题,如果expression 的计算,可能不依赖于 variables,getExpressionValue方法应该需要重构 + if (ex.getCause() instanceof PropertyNotFoundException){ + log.error("[evalConditionExpress][条件表达式({}) 变量({}) 解析报错]", expression, variables, ex); + return Boolean.FALSE; + } // 为什么使用 info 日志?原因是,expression 如果从 variables 取不到值,会报错。实际这种情况下,可以忽略 log.info("[evalConditionExpress][条件表达式({}) 变量({}) 解析报错]", expression, variables, ex); return Boolean.FALSE; From be608b26e674ecaa0c79fc3ac239cb38fd1ba4f3 Mon Sep 17 00:00:00 2001 From: lizhixian <18210040298@163.com> Date: Thu, 13 Mar 2025 16:22:58 +0800 Subject: [PATCH 06/22] =?UTF-8?q?review:=20=E4=BB=A3=E7=A0=81=E9=87=8D?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bpm/service/definition/BpmModelServiceImpl.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java index 6f3162683f..a441803218 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java @@ -248,16 +248,11 @@ public class BpmModelServiceImpl implements BpmModelService { throw exception(MODEL_DEPLOY_FAIL_BPMN_USER_TASK_NAME_NOT_EXISTS, userTask.getId()); } }); - // TODO @小北:是不是可以 UserTask firUserTask = CollUtil.get(userTasks, BpmModelTypeEnum.BPMN.getType().equals(type) ? 0 : 1);然后,最好判空。。。极端情况下,没 usertask ,哈哈哈哈。 - // 3. 校验第一个用户任务节点的规则类型是否为“审批人自选” - Map userTaskMap = new HashMap<>(); - // BPMN 设计器,校验第一个用户任务节点 - userTaskMap.put(BpmModelTypeEnum.BPMN.getType(), userTasks.get(0)); - // SIMPLE 设计器,第一个节点固定为发起人所以校验第二个用户任务节点 - userTaskMap.put(BpmModelTypeEnum.SIMPLE.getType(), userTasks.get(1)); - Integer candidateStrategy = parseCandidateStrategy(userTaskMap.get(type)); + // 3. 校验第一个用户任务节点的规则类型是否为“审批人自选”,BPMN 设计器,校验第一个用户任务节点,SIMPLE 设计器,第一个节点固定为发起人所以校验第二个用户任务节点 + UserTask firUserTask = CollUtil.get(userTasks, BpmModelTypeEnum.BPMN.getType().equals(type) ? 0 : 1); + Integer candidateStrategy = parseCandidateStrategy(firUserTask); if (Objects.equals(candidateStrategy, BpmTaskCandidateStrategyEnum.APPROVE_USER_SELECT.getStrategy())) { - throw exception(MODEL_DEPLOY_FAIL_FIRST_USER_TASK_CANDIDATE_STRATEGY_ERROR, userTaskMap.get(type).getName()); + throw exception(MODEL_DEPLOY_FAIL_FIRST_USER_TASK_CANDIDATE_STRATEGY_ERROR, firUserTask.getName()); } } From d3db32b44e8814153586e73354fab739999ca5a5 Mon Sep 17 00:00:00 2001 From: lizhixian <18210040298@163.com> Date: Fri, 14 Mar 2025 16:58:12 +0800 Subject: [PATCH 07/22] =?UTF-8?q?fix=EF=BC=9A=E8=A7=A3=E5=86=B3=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=E6=B5=81=E7=A8=8B=E7=94=BB=E5=B8=83=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=EF=BC=8C=E6=9E=81=E7=AB=AF=E6=83=85=E5=86=B5=E4=B8=8B=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E4=BB=BB=E5=8A=A1=E8=8A=82=E7=82=B9=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E7=9A=84=E5=BC=82=E5=B8=B8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/bpm/service/definition/BpmModelServiceImpl.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java index a441803218..33614814d0 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java @@ -250,6 +250,10 @@ public class BpmModelServiceImpl implements BpmModelService { }); // 3. 校验第一个用户任务节点的规则类型是否为“审批人自选”,BPMN 设计器,校验第一个用户任务节点,SIMPLE 设计器,第一个节点固定为发起人所以校验第二个用户任务节点 UserTask firUserTask = CollUtil.get(userTasks, BpmModelTypeEnum.BPMN.getType().equals(type) ? 0 : 1); + // 4. 极端情况下无多个用户任务节点,比如发起人-抄送节点 + if (firUserTask == null){ + return; + } Integer candidateStrategy = parseCandidateStrategy(firUserTask); if (Objects.equals(candidateStrategy, BpmTaskCandidateStrategyEnum.APPROVE_USER_SELECT.getStrategy())) { throw exception(MODEL_DEPLOY_FAIL_FIRST_USER_TASK_CANDIDATE_STRATEGY_ERROR, firUserTask.getName()); From 25899d99885c68e40335e748f4b178e8ab613501 Mon Sep 17 00:00:00 2001 From: LesanOuO <1960681385@qq.com> Date: Sat, 15 Mar 2025 10:45:45 +0800 Subject: [PATCH 08/22] =?UTF-8?q?fix:=20=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vo/model/BpmModelMetaInfoVO.java | 6 +-- .../BpmProcessDefinitionInfoDO.java | 5 +- .../core/util/BpmHttpRequestUtils.java | 51 +++++++++---------- .../task/BpmProcessInstanceServiceImpl.java | 31 +++++------ .../task/listener/BpmUserTaskListener.java | 7 +-- .../trigger/http/BpmHttpCallbackTrigger.java | 7 +-- .../http/BpmSyncHttpRequestTrigger.java | 7 +-- 7 files changed, 44 insertions(+), 70 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java index 254a5178f0..cf9ca3e5fd 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/BpmModelMetaInfoVO.java @@ -82,13 +82,11 @@ public class BpmModelMetaInfoVO { @Schema(description = "摘要设置", example = "{}") private SummarySetting summarySetting; - // TODO @lesan:processBeforeTriggerSetting;要不叫这个?主要考虑,notify 留给后续的站内信、短信、邮件这种 notify 通知哈。 @Schema(description = "流程前置通知设置", example = "{}") - private HttpRequestSetting PreProcessNotifySetting; + private HttpRequestSetting processBeforeTriggerSetting; - // TODO @lesan:processAfterTriggerSetting @Schema(description = "流程后置通知设置", example = "{}") - private HttpRequestSetting PostProcessNotifySetting; + private HttpRequestSetting processAfterTriggerSetting; @Schema(description = "流程 ID 规则") @Data diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java index 549889e3aa..6a4c333ab2 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java @@ -188,16 +188,15 @@ public class BpmProcessDefinitionInfoDO extends BaseDO { @TableField(typeHandler = JacksonTypeHandler.class) private BpmModelMetaInfoVO.SummarySetting summarySetting; - // TODO @lesan:processBeforeTriggerSetting;要不叫这个?主要考虑,notify 留给后续的站内信、短信、邮件这种 notify 通知哈。 /** * 流程前置通知设置 */ @TableField(typeHandler = JacksonTypeHandler.class, exist = false) // TODO @芋艿:临时注释 exist,因为要合并 master-jdk17 - private BpmModelMetaInfoVO.HttpRequestSetting PreProcessNotifySetting; + private BpmModelMetaInfoVO.HttpRequestSetting processBeforeTriggerSetting; /** * 流程后置通知设置 */ @TableField(typeHandler = JacksonTypeHandler.class, exist = false) // TODO @芋艿:临时注释 exist,因为要合并 master-jdk17 - private BpmModelMetaInfoVO.HttpRequestSetting PostProcessNotifySetting; + private BpmModelMetaInfoVO.HttpRequestSetting processAfterTriggerSetting; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java index 7f4428aac3..2503c0fff9 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java @@ -5,6 +5,7 @@ import cn.hutool.core.util.StrUtil; 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.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; @@ -40,11 +41,9 @@ public class BpmHttpRequestUtils { List headerParams, List bodyParams, Boolean handleResponse, - List> response, - // TODO @lesan:RestTemplate 直接通过 springUtil 获取好咧; - RestTemplate restTemplate, - // TODO @lesan:processInstanceService 直接通过 springUtil 获取好咧; - BpmProcessInstanceService processInstanceService) { + List> response) { + RestTemplate restTemplate = SpringUtils.getBean(RestTemplate.class); + BpmProcessInstanceService processInstanceService = SpringUtils.getBean(BpmProcessInstanceService.class); // 1.1 设置请求头 MultiValueMap headers = buildHttpHeaders(processInstance, headerParams); @@ -55,27 +54,27 @@ public class BpmHttpRequestUtils { ResponseEntity responseEntity = sendHttpRequest(url, headers, body, restTemplate); // 3. 处理返回 - // TODO @lesan:可以用 if return,让括号小点 - if (Boolean.TRUE.equals(handleResponse)) { - // 3.1 判断是否需要解析返回值 - if (responseEntity == null - || StrUtil.isEmpty(responseEntity.getBody()) - || !responseEntity.getStatusCode().is2xxSuccessful() - || CollUtil.isEmpty(response)) { - return; - } - // 3.2 解析返回值, 返回值必须符合 CommonResult 规范。 - CommonResult> respResult = JsonUtils.parseObjectQuietly(responseEntity.getBody(), - new TypeReference<>() {}); - if (respResult == null || !respResult.isSuccess()) { - return; - } - // 3.3 获取需要更新的流程变量 - Map updateVariables = getNeedUpdatedVariablesFromResponse(respResult.getData(), response); - // 3.4 更新流程变量 - if (CollUtil.isNotEmpty(updateVariables)) { - processInstanceService.updateProcessInstanceVariables(processInstance.getId(), updateVariables); - } + if (Boolean.FALSE.equals(handleResponse)) { + return; + } + // 3.1 判断是否需要解析返回值 + if (responseEntity == null + || StrUtil.isEmpty(responseEntity.getBody()) + || !responseEntity.getStatusCode().is2xxSuccessful() + || CollUtil.isEmpty(response)) { + return; + } + // 3.2 解析返回值, 返回值必须符合 CommonResult 规范。 + CommonResult> respResult = JsonUtils.parseObjectQuietly(responseEntity.getBody(), + new TypeReference<>() {}); + if (respResult == null || !respResult.isSuccess()) { + return; + } + // 3.3 获取需要更新的流程变量 + Map updateVariables = getNeedUpdatedVariablesFromResponse(respResult.getData(), response); + // 3.4 更新流程变量 + if (CollUtil.isNotEmpty(updateVariables)) { + processInstanceService.updateProcessInstanceVariables(processInstance.getId(), updateVariables); } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 64abcef42e..58417d922b 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -122,9 +122,6 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @Resource private BpmProcessIdRedisDAO processIdRedisDAO; - @Resource - private RestTemplate restTemplate; - // ========== Query 查询相关方法 ========== @Override @@ -913,16 +910,14 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService. getProcessDefinitionInfo(instance.getProcessDefinitionId()); if (ObjUtil.isNotNull(processDefinitionInfo) && - ObjUtil.isNotNull(processDefinitionInfo.getPostProcessNotifySetting())) { - BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getPostProcessNotifySetting(); + ObjUtil.isNotNull(processDefinitionInfo.getProcessAfterTriggerSetting())) { + BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessAfterTriggerSetting(); BpmHttpRequestUtils.executeBpmHttpRequest(instance, setting.getUrl(), setting.getHeader(), setting.getBody(), - true, setting.getResponse(), - restTemplate, - this); + true, setting.getResponse()); } } }); @@ -935,18 +930,16 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService // 流程前置通知 BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService. getProcessDefinitionInfo(instance.getProcessDefinitionId()); - // TODO @lesan:if return 哈。减少括号。 - if (ObjUtil.isNotNull(processDefinitionInfo) && - ObjUtil.isNotNull(processDefinitionInfo.getPreProcessNotifySetting())) { - BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getPreProcessNotifySetting(); - BpmHttpRequestUtils.executeBpmHttpRequest(instance, - setting.getUrl(), - setting.getHeader(), - setting.getBody(), - true, setting.getResponse(), - restTemplate, - this); + if (ObjUtil.isNull(processDefinitionInfo) || + ObjUtil.isNull(processDefinitionInfo.getProcessBeforeTriggerSetting())) { + return; } + BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessBeforeTriggerSetting(); + BpmHttpRequestUtils.executeBpmHttpRequest(instance, + setting.getUrl(), + setting.getHeader(), + setting.getBody(), + true, setting.getResponse()); }); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmUserTaskListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmUserTaskListener.java index 6048423c91..e16fafa2d1 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmUserTaskListener.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmUserTaskListener.java @@ -32,9 +32,6 @@ public class BpmUserTaskListener implements TaskListener { @Resource private BpmProcessInstanceService processInstanceService; - @Resource - private RestTemplate restTemplate; - @Setter private FixedValue listenerConfig; @@ -58,9 +55,7 @@ public class BpmUserTaskListener implements TaskListener { listenerHandler.getPath(), listenerHandler.getHeader(), listenerHandler.getBody(), - false, null, - restTemplate, - processInstanceService); + false, null); // 3. 是否需要后续操作?TODO 芋艿:待定! } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmHttpCallbackTrigger.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmHttpCallbackTrigger.java index ab1f54abd4..351b57ddd4 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmHttpCallbackTrigger.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmHttpCallbackTrigger.java @@ -21,9 +21,6 @@ import org.springframework.web.client.RestTemplate; @Slf4j public class BpmHttpCallbackTrigger extends BpmAbstractHttpRequestTrigger { - @Resource - private RestTemplate restTemplate; - @Resource private BpmProcessInstanceService processInstanceService; @@ -51,9 +48,7 @@ public class BpmHttpCallbackTrigger extends BpmAbstractHttpRequestTrigger { setting.getUrl(), setting.getHeader(), setting.getBody(), - false, null, - restTemplate, - processInstanceService); + false, null); } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmSyncHttpRequestTrigger.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmSyncHttpRequestTrigger.java index 6c74b066f0..2ac04117e4 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmSyncHttpRequestTrigger.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmSyncHttpRequestTrigger.java @@ -20,9 +20,6 @@ import org.springframework.web.client.RestTemplate; @Slf4j public class BpmSyncHttpRequestTrigger extends BpmAbstractHttpRequestTrigger { - @Resource - private RestTemplate restTemplate; - @Resource private BpmProcessInstanceService processInstanceService; @@ -46,9 +43,7 @@ public class BpmSyncHttpRequestTrigger extends BpmAbstractHttpRequestTrigger { setting.getUrl(), setting.getHeader(), setting.getBody(), - true, setting.getResponse(), - restTemplate, - processInstanceService); + true, setting.getResponse()); } } From 0ab54a9fe42ddc72af31df119d5665fac3f6e2d8 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 15 Mar 2025 16:48:05 +0800 Subject: [PATCH 09/22] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91BPM=EF=BC=9Afix:=20=E8=A7=A3=E5=86=B3?= =?UTF-8?q?=E5=AE=A1=E6=89=B9=E8=8A=82=E7=82=B9=E8=A1=A8=E5=8D=95=E6=97=A0?= =?UTF-8?q?=E5=8F=AF=E7=BC=96=E8=BE=91=E5=AD=97=E6=AE=B5=E6=97=B6=EF=BC=8C?= =?UTF-8?q?variables=E6=B5=81=E7=A8=8B=E5=8F=98=E9=87=8F=E5=80=BC=E4=B8=BA?= =?UTF-8?q?=E7=A9=BA=EF=BC=8C=E6=B5=81=E7=A8=8B=E8=8A=82=E7=82=B9=E6=B5=81?= =?UTF-8?q?=E8=BD=AC=E5=BC=82=E5=B8=B8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BpmProcessDefinitionInfoDO.java | 4 ++-- .../flowable/core/util/BpmnModelUtils.java | 6 ----- .../definition/BpmModelServiceImpl.java | 3 +-- .../bpm/service/task/BpmTaskServiceImpl.java | 22 +++++++++---------- 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java index 6a4c333ab2..86c83ed611 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/definition/BpmProcessDefinitionInfoDO.java @@ -191,12 +191,12 @@ public class BpmProcessDefinitionInfoDO extends BaseDO { /** * 流程前置通知设置 */ - @TableField(typeHandler = JacksonTypeHandler.class, exist = false) // TODO @芋艿:临时注释 exist,因为要合并 master-jdk17 + @TableField(typeHandler = JacksonTypeHandler.class) private BpmModelMetaInfoVO.HttpRequestSetting processBeforeTriggerSetting; /** * 流程后置通知设置 */ - @TableField(typeHandler = JacksonTypeHandler.class, exist = false) // TODO @芋艿:临时注释 exist,因为要合并 master-jdk17 + @TableField(typeHandler = JacksonTypeHandler.class) private BpmModelMetaInfoVO.HttpRequestSetting processAfterTriggerSetting; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java index fdfb724442..1cccf18f04 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java @@ -21,7 +21,6 @@ import org.flowable.bpmn.converter.BpmnXMLConverter; import org.flowable.bpmn.model.Process; import org.flowable.bpmn.model.*; import org.flowable.common.engine.api.FlowableException; -import org.flowable.common.engine.impl.javax.el.PropertyNotFoundException; import org.flowable.common.engine.impl.util.io.BytesStreamSource; import org.flowable.engine.impl.el.FixedValue; @@ -1007,11 +1006,6 @@ public class BpmnModelUtils { Object result = FlowableUtils.getExpressionValue(variables, expression); return Boolean.TRUE.equals(result); } catch (FlowableException ex) { - // TODO @芋艿 临时方案解决流程变量中不包含条件表达式时报错问题,如果expression 的计算,可能不依赖于 variables,getExpressionValue方法应该需要重构 - if (ex.getCause() instanceof PropertyNotFoundException){ - log.error("[evalConditionExpress][条件表达式({}) 变量({}) 解析报错]", expression, variables, ex); - return Boolean.FALSE; - } // 为什么使用 info 日志?原因是,expression 如果从 variables 取不到值,会报错。实际这种情况下,可以忽略 log.info("[evalConditionExpress][条件表达式({}) 变量({}) 解析报错]", expression, variables, ex); return Boolean.FALSE; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java index 33614814d0..e8e90006f8 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java @@ -250,8 +250,7 @@ public class BpmModelServiceImpl implements BpmModelService { }); // 3. 校验第一个用户任务节点的规则类型是否为“审批人自选”,BPMN 设计器,校验第一个用户任务节点,SIMPLE 设计器,第一个节点固定为发起人所以校验第二个用户任务节点 UserTask firUserTask = CollUtil.get(userTasks, BpmModelTypeEnum.BPMN.getType().equals(type) ? 0 : 1); - // 4. 极端情况下无多个用户任务节点,比如发起人-抄送节点 - if (firUserTask == null){ + if (firUserTask == null) { return; } Integer candidateStrategy = parseCandidateStrategy(firUserTask); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index b15a59c540..67a0ddf7de 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -557,31 +557,31 @@ public class BpmTaskServiceImpl implements BpmTaskService { // 2.2 添加评论 taskService.addComment(task.getId(), task.getProcessInstanceId(), BpmCommentTypeEnum.APPROVE.getType(), BpmCommentTypeEnum.APPROVE.formatComment(reqVO.getReason())); - // 如果流程变量前端传空,需要从历史实例中获取,原因:前端表单如果在当前节点无可编辑的字段时variables一定会为空 - // 场景一:A节点发起,B节点表单无可编辑字段,审批通过时,C节点需要流程变量获取下一个执行节点,但因为B节点无可编辑的字段,variables为空,流程可能出现问题 - // 场景二:A节点发起,B节点只有某一个字段可编辑(比如day),但C节点需要多个节点(比如workday,在发起时填写,因为B节点只有day的编辑权限,在审批后。variables会缺少work的值) - // 3.1 设置流程变量 + + // 3. 设置流程变量。如果流程变量前端传空,需要从历史实例中获取,原因:前端表单如果在当前节点无可编辑的字段时 variables 一定会为空 + // 场景一:A 节点发起,B 节点表单无可编辑字段,审批通过时,C 节点需要流程变量获取下一个执行节点,但因为 B 节点无可编辑的字段,variables 为空,流程可能出现问题。 + // 场景二:A 节点发起,B 节点只有某一个字段可编辑(比如 day),但 C 节点需要多个节点。 + // (比如 work + day 变量,在发起时填写,因为 B 节点只有 day 的编辑权限,在审批后,variables 会缺少 work 的值) Map processVariables = new HashMap<>(); - // 3.2 获取历史中流程变量 - if (CollUtil.isNotEmpty(instance.getProcessVariables())) { + if (CollUtil.isNotEmpty(instance.getProcessVariables())) { // 获取历史中流程变量 processVariables.putAll(instance.getProcessVariables()); } - // 3.3 合并前端传递的流程变量,以前端为准 - if (CollUtil.isNotEmpty(reqVO.getVariables())) { + if (CollUtil.isNotEmpty(reqVO.getVariables())) { // 合并前端传递的流程变量,以前端为准 processVariables.putAll(reqVO.getVariables()); } - // 3.4 校验并处理 APPROVE_USER_SELECT 当前审批人,选择下一节点审批人的逻辑 + + // 4. 校验并处理 APPROVE_USER_SELECT 当前审批人,选择下一节点审批人的逻辑 Map variables = validateAndSetNextAssignees(task.getTaskDefinitionKey(), processVariables, bpmnModel, reqVO.getNextAssignees(), instance); runtimeService.setVariables(task.getProcessInstanceId(), variables); - // 4 调用 BPM complete 去完成任务 + + // 5. 调用 BPM complete 去完成任务 taskService.complete(task.getId(), variables, true); // 【加签专属】处理加签任务 handleParentTaskIfSign(task.getParentTaskId()); } - /** * 校验选择的下一个节点的审批人,是否合法 * From 5aacefc00e3b7c4071c018db5e52f2d5a57cec27 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 15 Mar 2025 21:07:34 +0800 Subject: [PATCH 10/22] =?UTF-8?q?=E3=80=90=E7=BC=BA=E9=99=B7=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=91AI=EF=BC=9A=E6=96=B0=E5=A2=9E=E5=AF=B9?= =?UTF-8?q?=E8=AF=9D=E8=BF=9B=E8=A1=8C=E9=97=AE=E7=AD=94=E6=97=B6=EF=BC=8C?= =?UTF-8?q?toolNames=20cannot=20be=20null=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java index becc54ee43..5f307cd645 100644 --- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java +++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.ai.core.util; +import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum; import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions; @@ -13,6 +14,7 @@ import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.qianfan.QianFanChatOptions; import org.springframework.ai.zhipuai.ZhiPuAiChatOptions; +import java.util.Collections; import java.util.Set; /** @@ -28,6 +30,7 @@ public class AiUtils { public static ChatOptions buildChatOptions(AiPlatformEnum platform, String model, Double temperature, Integer maxTokens, Set toolNames) { + toolNames = ObjUtil.defaultIfNull(toolNames, Collections.emptySet()); // noinspection EnhancedSwitchMigration switch (platform) { case TONG_YI: From a4815b30d07105dd2cf89ae99e325e687c5cfe09 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 15 Mar 2025 21:16:53 +0800 Subject: [PATCH 11/22] =?UTF-8?q?=E3=80=90=E7=BC=BA=E9=99=B7=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=91=E5=95=86=E5=9F=8E=EF=BC=9A=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=E5=95=86=E5=9F=8E=E4=B8=AD=E5=B0=86=E4=BC=9A=E5=91=98=E7=AD=89?= =?UTF-8?q?=E7=BA=A7=E5=85=B3=E9=97=AD=EF=BC=8C=E8=BF=98=E7=BB=A7=E7=BB=AD?= =?UTF-8?q?=E8=AE=A1=E7=AE=97=E6=8A=98=E6=89=A3=E4=BB=B7=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../calculator/TradeDiscountActivityPriceCalculator.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java index 801c7c0186..bf8651af5e 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.trade.service.price.calculator; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.module.member.api.level.MemberLevelApi; import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; @@ -141,7 +142,9 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato */ public Integer calculateVipPrice(MemberLevelRespDTO level, TradePriceCalculateRespBO.OrderItem orderItem) { - if (level == null || level.getDiscountPercent() == null) { + if (level == null + || CommonStatusEnum.isDisable(level.getStatus()) + || level.getDiscountPercent() == null) { return 0; } Integer newPrice = calculateRatePrice(orderItem.getPayPrice(), level.getDiscountPercent().doubleValue()); From 803da9ed9e6bedb209ac8426fff3ea32fa695d4a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 15 Mar 2025 21:37:18 +0800 Subject: [PATCH 12/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91System=EF=BC=9AcomponentName=20=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E6=A0=A1=E9=AA=8C=EF=BC=8C=E9=81=BF=E5=85=8D=20vue3?= =?UTF-8?q?=20router=20=E5=88=9D=E5=A7=8B=E5=8C=96=E6=9C=89=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/enums/ErrorCodeConstants.java | 1 + .../dal/mysql/permission/MenuMapper.java | 5 +++ .../service/permission/MenuServiceImpl.java | 33 +++++++++++++++++-- .../permission/MenuServiceImplTest.java | 8 ++--- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java index a3cc1cefa0..6db0e567c4 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java @@ -24,6 +24,7 @@ public interface ErrorCodeConstants { ErrorCode MENU_NOT_EXISTS = new ErrorCode(1_002_001_003, "菜单不存在"); ErrorCode MENU_EXISTS_CHILDREN = new ErrorCode(1_002_001_004, "存在子菜单,无法删除"); ErrorCode MENU_PARENT_NOT_DIR_OR_MENU = new ErrorCode(1_002_001_005, "父菜单的类型必须是目录或者菜单"); + ErrorCode MENU_COMPONENT_NAME_DUPLICATE = new ErrorCode(1_002_001_006, "已经存在该组件名的菜单"); // ========== 角色模块 1-002-002-000 ========== ErrorCode ROLE_NOT_EXISTS = new ErrorCode(1_002_002_000, "角色不存在"); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/MenuMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/MenuMapper.java index 8458faa67a..31eb117d26 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/MenuMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/MenuMapper.java @@ -28,4 +28,9 @@ public interface MenuMapper extends BaseMapperX { default List selectListByPermission(String permission) { return selectList(MenuDO::getPermission, permission); } + + default MenuDO selectByComponentName(String componentName) { + return selectOne(MenuDO::getComponentName, componentName); + } + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java index 98052eb650..5378108dd1 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.service.permission; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO; @@ -53,7 +54,8 @@ public class MenuServiceImpl implements MenuService { // 校验父菜单存在 validateParentMenu(createReqVO.getParentId(), null); // 校验菜单(自己) - validateMenu(createReqVO.getParentId(), createReqVO.getName(), null); + validateMenuName(createReqVO.getParentId(), createReqVO.getName(), null); + validateMenuComponentName(createReqVO.getComponentName(), null); // 插入数据库 MenuDO menu = BeanUtils.toBean(createReqVO, MenuDO.class); @@ -74,7 +76,8 @@ public class MenuServiceImpl implements MenuService { // 校验父菜单存在 validateParentMenu(updateReqVO.getParentId(), updateReqVO.getId()); // 校验菜单(自己) - validateMenu(updateReqVO.getParentId(), updateReqVO.getName(), updateReqVO.getId()); + validateMenuName(updateReqVO.getParentId(), updateReqVO.getName(), updateReqVO.getId()); + validateMenuComponentName(updateReqVO.getComponentName(), updateReqVO.getId()); // 更新到数据库 MenuDO updateObj = BeanUtils.toBean(updateReqVO, MenuDO.class); @@ -228,7 +231,7 @@ public class MenuServiceImpl implements MenuService { * @param id 菜单编号 */ @VisibleForTesting - void validateMenu(Long parentId, String name, Long id) { + void validateMenuName(Long parentId, String name, Long id) { MenuDO menu = menuMapper.selectByParentIdAndName(parentId, name); if (menu == null) { return; @@ -242,6 +245,30 @@ public class MenuServiceImpl implements MenuService { } } + /** + * 校验菜单组件名是否合法 + * + * @param componentName 组件名 + * @param id 菜单编号 + */ + @VisibleForTesting + void validateMenuComponentName(String componentName, Long id) { + if (StrUtil.isBlank(componentName)) { + return; + } + MenuDO menu = menuMapper.selectByComponentName(componentName); + if (menu == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的菜单 + if (id == null) { + return; + } + if (!menu.getId().equals(id)) { + throw exception(MENU_COMPONENT_NAME_DUPLICATE); + } + } + /** * 初始化菜单的通用属性。 *

diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImplTest.java index 27f1efb36c..cc393796cc 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImplTest.java @@ -275,7 +275,7 @@ public class MenuServiceImplTest extends BaseDbUnitTest { } @Test - public void testValidateMenu_success() { + public void testValidateMenu_Name_success() { // mock 父子菜单 MenuDO sonMenu = createParentAndSonMenu(); // 准备参数 @@ -284,11 +284,11 @@ public class MenuServiceImplTest extends BaseDbUnitTest { String otherSonMenuName = randomString(); // 调用,无需断言 - menuService.validateMenu(parentId, otherSonMenuName, otherSonMenuId); + menuService.validateMenuName(parentId, otherSonMenuName, otherSonMenuId); } @Test - public void testValidateMenu_sonMenuNameDuplicate() { + public void testValidateMenu_sonMenuNameNameDuplicate() { // mock 父子菜单 MenuDO sonMenu = createParentAndSonMenu(); // 准备参数 @@ -297,7 +297,7 @@ public class MenuServiceImplTest extends BaseDbUnitTest { String otherSonMenuName = sonMenu.getName(); //相同名称 // 调用,并断言异常 - assertServiceException(() -> menuService.validateMenu(parentId, otherSonMenuName, otherSonMenuId), + assertServiceException(() -> menuService.validateMenuName(parentId, otherSonMenuName, otherSonMenuId), MENU_NAME_DUPLICATE); } From 2511f2c55bb7b1455c7e783e92866624db5210be Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 15 Mar 2025 22:40:31 +0800 Subject: [PATCH 13/22] =?UTF-8?q?=E3=80=90=E7=BC=BA=E9=99=B7=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=91BPM=EF=BC=9A=E2=80=9C=E7=BB=93=E6=9D=9F?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E4=B8=8D=E8=83=BD=E6=9C=AA=E7=A9=BA=E2=80=9D?= =?UTF-8?q?=E6=96=87=E6=A1=88=E9=83=A8=E6=AD=A3=E7=A1=AE=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/bpm/service/task/BpmTaskServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index f96d0cb392..dd470d4999 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -966,7 +966,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(taskList.get(0).getProcessDefinitionId()); List activityIds = CollUtil.newArrayList(convertSet(taskList, Task::getTaskDefinitionKey)); EndEvent endEvent = BpmnModelUtils.getEndEvent(bpmnModel); - Assert.notNull(endEvent, "结束节点不能未空"); + Assert.notNull(endEvent, "结束节点不能为空"); runtimeService.createChangeActivityStateBuilder() .processInstanceId(processInstanceId) .moveActivityIdsToSingleActivityId(activityIds, endEvent.getId()) From bd93257a26a1bb49ab859365b1f0cec01e4789bd Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 16 Mar 2025 10:42:10 +0800 Subject: [PATCH 14/22] =?UTF-8?q?=E3=80=90=E7=BC=BA=E9=99=B7=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=91PAY=EF=BC=9AWxAppPayClient=20=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E7=BB=93=E6=9E=9C=E4=B8=8D=E8=AF=BBid=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/pay/core/client/impl/weixin/WxAppPayClient.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxAppPayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxAppPayClient.java index 396694a75b..ec88aa73a6 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxAppPayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxAppPayClient.java @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum; -import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult; +import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult; import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request; import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result; @@ -41,7 +41,7 @@ public class WxAppPayClient extends AbstractWxPayClient { // 构建 WxPayUnifiedOrderRequest 对象 WxPayUnifiedOrderRequest request = buildPayUnifiedOrderRequestV2(reqDTO); // 执行请求 - WxPayMpOrderResult response = client.createOrder(request); + WxPayAppOrderResult response = client.createOrder(request); // 转换结果 return PayOrderRespDTO.waitingOf(PayOrderDisplayModeEnum.APP.getMode(), toJsonString(response), From 75167383304c9f5c392af8553bc7e1e70736d043 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 16 Mar 2025 13:52:33 +0800 Subject: [PATCH 15/22] =?UTF-8?q?=E3=80=90=E7=BC=BA=E9=99=B7=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=91BPM=EF=BC=9A=E4=BF=AE=E5=A4=8D=20task=20?= =?UTF-8?q?=E7=9A=84=20category=20=E4=B8=8D=E6=AD=A3=E7=A1=AE=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/behavior/BpmUserTaskActivityBehavior.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java index cba5187b38..c4c8167c87 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmUserTaskActivityBehavior.java @@ -10,7 +10,10 @@ import org.flowable.common.engine.impl.el.ExpressionManager; import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.impl.bpmn.behavior.UserTaskActivityBehavior; import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.flowable.engine.impl.persistence.entity.ProcessDefinitionEntity; +import org.flowable.engine.impl.util.CommandContextUtil; import org.flowable.engine.impl.util.TaskHelper; +import org.flowable.engine.interceptor.CreateUserTaskBeforeContext; import org.flowable.task.service.TaskService; import org.flowable.task.service.impl.persistence.entity.TaskEntity; import org.springframework.transaction.annotation.Transactional; @@ -69,4 +72,15 @@ public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior { return CollUtil.get(candidateUserIds, index); } + @Override + protected void handleCategory(CreateUserTaskBeforeContext beforeContext, ExpressionManager expressionManager, + TaskEntity task, DelegateExecution execution) { + ProcessDefinitionEntity processDefinitionEntity = CommandContextUtil.getProcessDefinitionEntityManager().findById(execution.getProcessDefinitionId()); + if (processDefinitionEntity == null) { + log.warn("[handleCategory][任务编号({}) 找不到流程定义({})]", task.getId(), execution.getProcessDefinitionId()); + return; + } + task.setCategory(processDefinitionEntity.getCategory()); + } + } From fc8e4662bb6998df397950e6b7318e164b8d23f9 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 16 Mar 2025 14:45:09 +0800 Subject: [PATCH 16/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91=E9=99=90=E6=B5=81=E7=9A=84=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0=20expire=20=E8=BF=87=E6=9C=9F?= =?UTF-8?q?=EF=BC=8C=E5=8E=9F=E5=9B=A0=E5=8F=82=E8=A7=81=20https://t.zsxq.?= =?UTF-8?q?com/lcR0W=20=E5=9C=BA=E6=99=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ratelimiter/core/redis/RateLimiterRedisDAO.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/ratelimiter/core/redis/RateLimiterRedisDAO.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/ratelimiter/core/redis/RateLimiterRedisDAO.java index fc1378f3bd..18c30682e5 100644 --- a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/ratelimiter/core/redis/RateLimiterRedisDAO.java +++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/ratelimiter/core/redis/RateLimiterRedisDAO.java @@ -44,6 +44,7 @@ public class RateLimiterRedisDAO { RateLimiterConfig config = rateLimiter.getConfig(); if (config == null) { rateLimiter.trySetRate(RateType.OVERALL, count, rateInterval, RateIntervalUnit.SECONDS); + rateLimiter.expire(rateInterval, TimeUnit.SECONDS); // 原因参见 https://t.zsxq.com/lcR0W return rateLimiter; } // 2. 如果存在,并且配置相同,则直接返回 @@ -54,6 +55,7 @@ public class RateLimiterRedisDAO { } // 3. 如果存在,并且配置不同,则进行新建 rateLimiter.setRate(RateType.OVERALL, count, rateInterval, RateIntervalUnit.SECONDS); + rateLimiter.expire(rateInterval, TimeUnit.SECONDS); // 原因参见 https://t.zsxq.com/lcR0W return rateLimiter; } From 2ddf9d05e6d1cda118ebd66a497d94ae7c915e64 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 16 Mar 2025 15:24:56 +0800 Subject: [PATCH 17/22] =?UTF-8?q?=E3=80=90=E7=BC=BA=E9=99=B7=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=91BPM=EF=BC=9A=E4=BD=BF=E7=94=A8=20DataPermissi?= =?UTF-8?q?onUtils=20=E6=9B=BF=E4=BB=A3=20DataPermission=EF=BC=8C=E9=81=BF?= =?UTF-8?q?=E5=85=8D=20this=20=E8=B0=83=E7=94=A8=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E7=94=9F=E6=95=88=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/system/api/user/AdminUserApiImpl.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java index 6af7bcd422..4f7b4e4682 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.system.api.user; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; +import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; @@ -12,7 +12,10 @@ import cn.iocoder.yudao.module.system.service.user.AdminUserService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @@ -56,10 +59,11 @@ public class AdminUserApiImpl implements AdminUserApi { } @Override - @DataPermission(enable = false) // 禁用数据权限。原因是,一般基于指定 id 的 API 查询,都是数据拼接为主 public List getUserList(Collection ids) { - List users = userService.getUserList(ids); - return BeanUtils.toBean(users, AdminUserRespDTO.class); + return DataPermissionUtils.executeIgnore(() -> { // 禁用数据权限。原因是,一般基于指定 id 的 API 查询,都是数据拼接为主 + List users = userService.getUserList(ids); + return BeanUtils.toBean(users, AdminUserRespDTO.class); + }); } @Override From dc1c824749e6f714843fbe22053a13480183190b Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 16 Mar 2025 15:29:50 +0800 Subject: [PATCH 18/22] =?UTF-8?q?=E3=80=90=E7=BC=BA=E9=99=B7=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=91BPM=EF=BC=9AprocessTaskAssigned=20=E5=BF=BD?= =?UTF-8?q?=E7=95=A5=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90=EF=BC=8C=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E5=88=86=E9=85=8D=E7=BB=99=20leader=20=E7=9A=84?= =?UTF-8?q?=E6=97=B6=E5=80=99=EF=BC=8C=E5=9B=A0=E4=B8=BA=E6=B2=A1=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=9D=83=E9=99=90=EF=BC=8C=E5=AF=BC=E8=87=B4=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E4=B8=8D=E5=88=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/bpm/service/task/BpmTaskServiceImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index 67a0ddf7de..242ed77475 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -10,6 +10,7 @@ import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.framework.common.util.object.PageUtils; +import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert; @@ -1255,6 +1256,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { } @Override + @DataPermission(enable = false) // 忽略数据权限,避免因为过滤,导致找不到候选人 public void processTaskAssigned(Task task) { // 发送通知。在事务提交时,批量执行操作,所以直接查询会无法查询到 ProcessInstance,所以这里是通过监听事务的提交来实现。 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { From 2dc8071faa763f835c9b67e87bf570af38bd000f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 16 Mar 2025 16:31:36 +0800 Subject: [PATCH 19/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91=E5=85=A8=E5=B1=80=EF=BC=9A=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=20selectFirstOne=20=E6=96=B9=E6=B3=95=EF=BC=8C=E8=A7=A3?= =?UTF-8?q?=E5=86=B3=E5=AE=B9=E6=98=93=E5=87=BA=E7=8E=B0=E5=B9=B6=E5=8F=91?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E4=B8=8B=E7=9A=84=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mybatis/core/mapper/BaseMapperX.java | 30 +++++++++++++++++-- .../history/ProductBrowseHistoryMapper.java | 5 ++-- .../dal/mysql/social/SocialUserMapper.java | 13 ++++---- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java index 01f2142306..167a0fc4ea 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java @@ -92,10 +92,36 @@ public interface BaseMapperX extends MPJBaseMapper { default T selectOne(SFunction field1, Object value1, SFunction field2, Object value2, SFunction field3, Object value3) { - return selectOne(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2) - .eq(field3, value3)); + return selectOne(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2).eq(field3, value3)); } + /** + * 获取满足条件的第 1 条记录 + * + * 目的:解决并发场景下,插入多条记录后,使用 selectOne 会报错的问题 + * + * @param field 字段名 + * @param value 字段值 + * @return 实体 + */ + default T selectFirstOne(SFunction field, Object value) { + // 如果明确使用 MySQL 等场景,可以考虑使用 LIMIT 1 进行优化 + List list = selectList(new LambdaQueryWrapper().eq(field, value)); + return CollUtil.getFirst(list); + } + + default T selectFirstOne(SFunction field1, Object value1, SFunction field2, Object value2) { + List list = selectList(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2)); + return CollUtil.getFirst(list); + } + + default T selectFirstOne(SFunction field1, Object value1, SFunction field2, Object value2, + SFunction field3, Object value3) { + List list = selectList(new LambdaQueryWrapper().eq(field1, value1).eq(field2, value2).eq(field3, value3)); + return CollUtil.getFirst(list); + } + + default Long selectCount() { return selectCount(new QueryWrapper<>()); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/history/ProductBrowseHistoryMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/history/ProductBrowseHistoryMapper.java index 124357cacf..8ea2ca5105 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/history/ProductBrowseHistoryMapper.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/history/ProductBrowseHistoryMapper.java @@ -21,9 +21,8 @@ import java.util.Collection; public interface ProductBrowseHistoryMapper extends BaseMapperX { default ProductBrowseHistoryDO selectByUserIdAndSpuId(Long userId, Long spuId) { - return selectOne(new LambdaQueryWrapperX() - .eq(ProductBrowseHistoryDO::getUserId, userId) - .eq(ProductBrowseHistoryDO::getSpuId, spuId)); + return selectFirstOne(ProductBrowseHistoryDO::getUserId, userId, + ProductBrowseHistoryDO::getSpuId, spuId); } default PageResult selectPage(ProductBrowseHistoryPageReqVO reqVO) { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialUserMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialUserMapper.java index af30ecee29..a90e6ac2a1 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialUserMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialUserMapper.java @@ -5,23 +5,20 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; @Mapper public interface SocialUserMapper extends BaseMapperX { default SocialUserDO selectByTypeAndCodeAnState(Integer type, String code, String state) { - return selectOne(new LambdaQueryWrapper() - .eq(SocialUserDO::getType, type) - .eq(SocialUserDO::getCode, code) - .eq(SocialUserDO::getState, state)); + return selectOne(SocialUserDO::getType, type, + SocialUserDO::getCode, code, + SocialUserDO::getState, state); } default SocialUserDO selectByTypeAndOpenid(Integer type, String openid) { - return selectOne(new LambdaQueryWrapper() - .eq(SocialUserDO::getType, type) - .eq(SocialUserDO::getOpenid, openid)); + return selectFirstOne(SocialUserDO::getType, type, + SocialUserDO::getOpenid, openid); } default PageResult selectPage(SocialUserPageReqVO reqVO) { From 8ccc55d1aa2759e09e4f76305e84e67c55847f6d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 16 Mar 2025 16:45:48 +0800 Subject: [PATCH 20/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91=E5=95=86=E5=9F=8E=EF=BC=9AKdNiaoExpressClien?= =?UTF-8?q?t=20=E5=A2=9E=E5=8A=A0=20requestType=20=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=EF=BC=8C=E4=BD=BF=E7=94=A8=E5=85=8D=E8=B4=B9=E7=89=88=EF=BC=8C?= =?UTF-8?q?=E8=BF=98=E6=98=AF=E5=A2=9E=E5=80=BC=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../delivery/config/TradeExpressProperties.java | 9 +++++++++ .../core/client/impl/kdniao/KdNiaoExpressClient.java | 7 +------ yudao-server/src/main/resources/application.yaml | 3 ++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/config/TradeExpressProperties.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/config/TradeExpressProperties.java index 3d836bb176..9cd6ff7938 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/config/TradeExpressProperties.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/config/TradeExpressProperties.java @@ -56,6 +56,15 @@ public class TradeExpressProperties { @NotEmpty(message = "快递鸟 Api Key 配置项不能为空") private String apiKey; + /** + * 接口指令 + * + * 1. 1002:免费版(只能查询申通、圆通快递) + * 2. 8001:付费版 + */ + @NotEmpty(message = "RequestType 配置项不能为空") + private String requestType = "1002"; + } /** diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/impl/kdniao/KdNiaoExpressClient.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/impl/kdniao/KdNiaoExpressClient.java index 24cf8e6eda..5ecd1c3f01 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/impl/kdniao/KdNiaoExpressClient.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/impl/kdniao/KdNiaoExpressClient.java @@ -39,11 +39,6 @@ public class KdNiaoExpressClient implements ExpressClient { private static final String REAL_TIME_QUERY_URL = "https://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx"; - /** - * 快递鸟即时查询免费版 RequestType - */ - private static final String REAL_TIME_FREE_REQ_TYPE = "1002"; - private final RestTemplate restTemplate; private final TradeExpressProperties.KdNiaoConfig config; @@ -67,7 +62,7 @@ public class KdNiaoExpressClient implements ExpressClient { && StrUtil.length(reqDTO.getPhone()) >= 4) { requestDTO.setCustomerName(StrUtil.subSufByLength(reqDTO.getPhone(), 4)); } - KdNiaoExpressQueryRespDTO respDTO = httpRequest(REAL_TIME_QUERY_URL, REAL_TIME_FREE_REQ_TYPE, + KdNiaoExpressQueryRespDTO respDTO = httpRequest(REAL_TIME_QUERY_URL, config.getRequestType(), requestDTO, KdNiaoExpressQueryRespDTO.class); // 处理结果 diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 522c0845af..838d66b9d4 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -340,10 +340,11 @@ yudao: receive-expire-time: 14d # 收货的过期时间 comment-expire-time: 7d # 评论的过期时间 express: - client: kd_niao + client: KD_NIAO kd-niao: api-key: cb022f1e-48f1-4c4a-a723-9001ac9676b8 business-id: 1809751 + request-type: 1002 # 免费版 1002;付费版 8001 kd100: key: pLXUGAwK5305 customer: E77DF18BE109F454A5CD319E44BF5177 From c95f0c152dd6cca5a9fbe40b8b02d1c14fd6bc17 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 16 Mar 2025 16:58:13 +0800 Subject: [PATCH 21/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91=E5=85=A8=E5=B1=80=EF=BC=9A=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=20methodArgumentNotValidExceptionExceptionHandler=20=E5=AF=B9?= =?UTF-8?q?=E3=80=8C=E7=BB=84=E5=90=88=E6=A0=A1=E9=AA=8C=E3=80=8D=E5=9C=BA?= =?UTF-8?q?=E6=99=AF=E7=9A=84=E5=85=BC=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/handler/GlobalExceptionHandler.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java index 41c5cead6a..1f19b90186 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.web.core.handler; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjUtil; @@ -27,6 +28,7 @@ import org.springframework.security.access.AccessDeniedException; import org.springframework.util.Assert; import org.springframework.validation.BindException; import org.springframework.validation.FieldError; +import org.springframework.validation.ObjectError; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingServletRequestParameterException; @@ -37,6 +39,7 @@ import org.springframework.web.servlet.NoHandlerFoundException; import org.springframework.web.servlet.resource.NoResourceFoundException; import java.time.LocalDateTime; +import java.util.List; import java.util.Map; import java.util.Set; @@ -135,9 +138,23 @@ public class GlobalExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public CommonResult methodArgumentNotValidExceptionExceptionHandler(MethodArgumentNotValidException ex) { log.warn("[methodArgumentNotValidExceptionExceptionHandler]", ex); + // 获取 errorMessage + String errorMessage = null; FieldError fieldError = ex.getBindingResult().getFieldError(); - assert fieldError != null; // 断言,避免告警 - return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", fieldError.getDefaultMessage())); + if (fieldError == null) { + // 组合校验,参考自 https://t.zsxq.com/3HVTx + List allErrors = ex.getBindingResult().getAllErrors(); + if (CollUtil.isNotEmpty(allErrors)) { + errorMessage = allErrors.get(0).getDefaultMessage(); + } + } else { + errorMessage = fieldError.getDefaultMessage(); + } + // 转换 CommonResult + if (StrUtil.isEmpty(errorMessage)) { + return CommonResult.error(BAD_REQUEST); + } + return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", errorMessage)); } /** From d597d0057ee9d4e5e3ffbc89604bb324c3c5ca7e Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 16 Mar 2025 17:04:04 +0800 Subject: [PATCH 22/22] =?UTF-8?q?=E3=80=90=E7=BC=BA=E9=99=B7=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=91=E5=85=A8=E5=B1=80=EF=BC=9Aapplication-dev=20?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=EF=BC=8C=E5=A4=9A=E4=BA=86?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=20spring=20=E5=89=8D=E7=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-server/src/main/resources/application-dev.yaml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/yudao-server/src/main/resources/application-dev.yaml b/yudao-server/src/main/resources/application-dev.yaml index 9377af95cd..288078968d 100644 --- a/yudao-server/src/main/resources/application-dev.yaml +++ b/yudao-server/src/main/resources/application-dev.yaml @@ -4,11 +4,10 @@ server: --- #################### 数据库相关配置 #################### spring: - spring: - autoconfigure: - exclude: - - org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建 - - org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建 + autoconfigure: + exclude: + - org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建 + - org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建 # 数据源配置项 datasource: druid: # Druid 【监控】相关的全局配置