From 27235016ad9e70e92323b224cbc66ce4b43493e1 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Sun, 12 Oct 2025 16:20:37 +0800 Subject: [PATCH 01/10] =?UTF-8?q?perf:=20[BPM=20=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E6=B5=81]=20=E9=A9=B3=E5=9B=9E=E9=A2=84=E6=B5=8B=20review=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/enums/BpmnVariableConstants.java | 4 ++-- .../task/BpmProcessInstanceServiceImpl.java | 11 ++++------ .../bpm/service/task/BpmTaskServiceImpl.java | 20 +++++++++---------- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnVariableConstants.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnVariableConstants.java index b3ce946148..c1d9568365 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnVariableConstants.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/enums/BpmnVariableConstants.java @@ -54,11 +54,11 @@ public class BpmnVariableConstants { public static final String PROCESS_INSTANCE_VARIABLE_RETURN_FLAG = "RETURN_FLAG_%s"; /** - * 流程实例的变量前缀 - 用于退回操作,记录需要预测的节点:格式 NEED_SIMULATE_TASK_{节点定义 id} + * 流程实例的变量 - 用于退回操作,记录需要预测的节点 ids, 变量值类型为 Set * * 目的是:退回操作,预测节点会不准,在流程变量中记录需要预测的节点,来辅助预测 */ - public static final String PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_PREFIX = "NEED_SIMULATE_TASK_"; + public static final String PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS = "NEED_SIMULATE_TASK_IDS"; /** * 流程实例的变量 - 是否跳过表达式 diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index ffca8caea2..aaef5df875 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.convert.Convert; import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Assert; -import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.*; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; @@ -72,7 +72,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. import static cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO.ActivityNode; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.START_USER_NODE_ID; -import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_PREFIX; +import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseNodeType; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; @@ -223,11 +223,8 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService // 3.2 获取由于退回操作,需要预测的节点。从流程变量中获取,回退操作会设置这些变量 Set needSimulateTaskDefKeysByReturn = new HashSet<>(); if (StrUtil.isNotEmpty(reqVO.getProcessInstanceId())) { - Map variables = runtimeService.getVariables(reqVO.getProcessInstanceId()); - Map simulateTaskVariables = MapUtil.filter(variables, - item -> item.getKey().startsWith(PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_PREFIX)); - simulateTaskVariables.forEach((key, value) -> - needSimulateTaskDefKeysByReturn.add(StrUtil.removePrefix(key, PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_PREFIX))); + Object needSimulateTaskIds = runtimeService.getVariable(reqVO.getProcessInstanceId(), PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS); + needSimulateTaskDefKeysByReturn.addAll(Convert.toSet(String.class, needSimulateTaskIds)); } // 移除运行中的节点,运行中的节点无需预测 if (CollUtil.isNotEmpty(runActivityNodes)) { diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index 7be2d53d7b..a41cee6202 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -601,9 +601,13 @@ public class BpmTaskServiceImpl implements BpmTaskService { bpmnModel, reqVO.getNextAssignees(), instance); runtimeService.setVariables(task.getProcessInstanceId(), variables); - // 5. 移除辅助预测的流程变量,这些变量在回退操作中设置 - String simulateVariableName = StrUtil.concat(false, PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_PREFIX, task.getTaskDefinitionKey()); - runtimeService.removeVariable(task.getProcessInstanceId(), simulateVariableName); + // 5. 如果当前节点 Id 存在于需要预测的流程节点中,从中移除。 流程变量在回退操作中设置 + Object needSimulateTaskIds = runtimeService.getVariable(task.getProcessInstanceId(), PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS); + Set needSimulateTaskIdsByReturn = Convert.toSet(String.class, needSimulateTaskIds); + if (needSimulateTaskIdsByReturn.contains(task.getTaskDefinitionKey())) { + needSimulateTaskIdsByReturn.remove(task.getTaskDefinitionKey()); + runtimeService.setVariable(task.getProcessInstanceId(), PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS, needSimulateTaskIdsByReturn); + } // 6. 调用 BPM complete 去完成任务 taskService.complete(task.getId(), variables, true); @@ -932,11 +936,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { }); // 3. 构建需要预测的任务流程变量 - // TODO @jason:【驳回预测相关】是不是搞成一个变量,里面是 set 更简洁一点呀? Set needSimulateTaskDefinitionKeys = getNeedSimulateTaskDefinitionKeys(bpmnModel, currentTask, targetElement); - Map needSimulateVariables = convertMap(needSimulateTaskDefinitionKeys, - key -> StrUtil.concat(false, PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_PREFIX, key), item -> Boolean.TRUE); - // 4. 执行驳回 // 使用 moveExecutionsToSingleActivityId 替换 moveActivityIdsToSingleActivityId 原因: @@ -944,9 +944,9 @@ public class BpmTaskServiceImpl implements BpmTaskService { runtimeService.createChangeActivityStateBuilder() .processInstanceId(currentTask.getProcessInstanceId()) .moveExecutionsToSingleActivityId(runExecutionIds, reqVO.getTargetTaskDefinitionKey()) - // 设置需要预测的任务流程变量,用于辅助预测 - .processVariables(needSimulateVariables) - // 设置流程变量(local)节点退回标记, 用于退回到节点,不执行 BpmUserTaskAssignStartUserHandlerTypeEnum 策略,导致自动通过 + // 设置需要预测的任务 ids 的流程变量,用于辅助预测 + .processVariable(PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS, needSimulateTaskDefinitionKeys) + // 设置流程变量(local)节点退回标记, 用于退回到节点,不执行 BpmUserTaskAssignStartUserHandlerTypeEnum 策略,导致自动通过 .localVariable(reqVO.getTargetTaskDefinitionKey(), String.format(PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, reqVO.getTargetTaskDefinitionKey()), Boolean.TRUE) .changeState(); From dace9cfed56fe01db443d787e605ac4026c20235 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Sun, 12 Oct 2025 16:28:49 +0800 Subject: [PATCH 02/10] =?UTF-8?q?perf:=20[BPM=20=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E6=B5=81]=20=E9=A9=B3=E5=9B=9E=E9=A2=84=E6=B5=8B=20review=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/task/BpmProcessInstanceServiceImpl.java | 3 +-- .../module/bpm/service/task/BpmTaskServiceImpl.java | 13 ++++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index aaef5df875..af388fbd04 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -72,7 +72,6 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. import static cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO.ActivityNode; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.START_USER_NODE_ID; -import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.parseNodeType; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; @@ -223,7 +222,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService // 3.2 获取由于退回操作,需要预测的节点。从流程变量中获取,回退操作会设置这些变量 Set needSimulateTaskDefKeysByReturn = new HashSet<>(); if (StrUtil.isNotEmpty(reqVO.getProcessInstanceId())) { - Object needSimulateTaskIds = runtimeService.getVariable(reqVO.getProcessInstanceId(), PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS); + Object needSimulateTaskIds = runtimeService.getVariable(reqVO.getProcessInstanceId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS); needSimulateTaskDefKeysByReturn.addAll(Convert.toSet(String.class, needSimulateTaskIds)); } // 移除运行中的节点,运行中的节点无需预测 diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index a41cee6202..36cdcf31eb 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -69,7 +69,6 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.START_USER_NODE_ID; -import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants.*; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.*; /** @@ -602,11 +601,11 @@ public class BpmTaskServiceImpl implements BpmTaskService { runtimeService.setVariables(task.getProcessInstanceId(), variables); // 5. 如果当前节点 Id 存在于需要预测的流程节点中,从中移除。 流程变量在回退操作中设置 - Object needSimulateTaskIds = runtimeService.getVariable(task.getProcessInstanceId(), PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS); + Object needSimulateTaskIds = runtimeService.getVariable(task.getProcessInstanceId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS); Set needSimulateTaskIdsByReturn = Convert.toSet(String.class, needSimulateTaskIds); if (needSimulateTaskIdsByReturn.contains(task.getTaskDefinitionKey())) { needSimulateTaskIdsByReturn.remove(task.getTaskDefinitionKey()); - runtimeService.setVariable(task.getProcessInstanceId(), PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS, needSimulateTaskIdsByReturn); + runtimeService.setVariable(task.getProcessInstanceId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS, needSimulateTaskIdsByReturn); } // 6. 调用 BPM complete 去完成任务 @@ -945,10 +944,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { .processInstanceId(currentTask.getProcessInstanceId()) .moveExecutionsToSingleActivityId(runExecutionIds, reqVO.getTargetTaskDefinitionKey()) // 设置需要预测的任务 ids 的流程变量,用于辅助预测 - .processVariable(PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS, needSimulateTaskDefinitionKeys) + .processVariable(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS, needSimulateTaskDefinitionKeys) // 设置流程变量(local)节点退回标记, 用于退回到节点,不执行 BpmUserTaskAssignStartUserHandlerTypeEnum 策略,导致自动通过 .localVariable(reqVO.getTargetTaskDefinitionKey(), - String.format(PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, reqVO.getTargetTaskDefinitionKey()), Boolean.TRUE) + String.format(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, reqVO.getTargetTaskDefinitionKey()), Boolean.TRUE) .changeState(); } @@ -1492,9 +1491,9 @@ public class BpmTaskServiceImpl implements BpmTaskService { FlowElement userTaskElement = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); // 判断是否为退回或者驳回:如果是退回或者驳回不走这个策略(使用 local variable) Boolean returnTaskFlag = runtimeService.getVariableLocal(task.getExecutionId(), - String.format(PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, task.getTaskDefinitionKey()), Boolean.class); + String.format(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, task.getTaskDefinitionKey()), Boolean.class); Boolean skipStartUserNodeFlag = Convert.toBool(runtimeService.getVariable(processInstance.getProcessInstanceId(), - PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE, String.class)); + BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE, String.class)); if (userTaskElement.getId().equals(START_USER_NODE_ID) && (skipStartUserNodeFlag == null // 目的:一般是“主流程”,发起人节点,自动通过审核 || BooleanUtil.isTrue(skipStartUserNodeFlag)) // 目的:一般是“子流程”,发起人节点,按配置自动通过审核 From 243ec76df958f479fef9dd0f3ec03b554d25cd56 Mon Sep 17 00:00:00 2001 From: DevDengChao <2325690622@qq.com> Date: Thu, 6 Nov 2025 14:37:00 +0800 Subject: [PATCH 03/10] =?UTF-8?q?fix:=20=E9=87=8D=E7=BD=AE=20currentRow=20?= =?UTF-8?q?=E6=97=B6=E6=B2=A1=E6=9C=89=E5=AF=B9=E6=A8=A1=E6=9D=BF=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E8=BF=9B=E8=A1=8C=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/codegen/vue3/views/index.vue.vm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yudao-module-infra/src/main/resources/codegen/vue3/views/index.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3/views/index.vue.vm index fb7485d6d5..857972a85d 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3/views/index.vue.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3/views/index.vue.vm @@ -353,7 +353,9 @@ const handleDelete = async (id: number) => { // 发起删除 await ${simpleClassName}Api.delete${simpleClassName}(id) message.success(t('common.delSuccess')) +#if ( $table.templateType == 11 ) currentRow.value = {} +#end // 刷新列表 await getList() } catch {} From 07b03fab0df9d11d2d049ff9d535e1a23c62f605 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 14 Nov 2025 08:30:57 +0000 Subject: [PATCH 04/10] Initial plan From 4723b80785ca2f2d826d66fd795aeecb3961503c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 14 Nov 2025 08:34:40 +0000 Subject: [PATCH 05/10] Fix WeChat Pay V3 public key configuration bug Co-authored-by: YunaiV <2015545+YunaiV@users.noreply.github.com> --- .../pay/core/client/impl/weixin/AbstractWxPayClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java index 4ee904bbb1..3b54862a7d 100644 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java @@ -70,7 +70,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient Date: Wed, 19 Nov 2025 10:28:09 +0800 Subject: [PATCH 06/10] =?UTF-8?q?feat=EF=BC=9A=E3=80=90infra=E3=80=91?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=94=9F=E6=88=90=EF=BC=9Avben5=20+=20ele=20?= =?UTF-8?q?=E6=A8=A1=E7=89=88=E4=B8=AD=EF=BC=8CDatePicker=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20class:=20'!w-full'=20=E4=BF=9D=E8=AF=81=E5=AE=BD?= =?UTF-8?q?=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/codegen/vue3_vben5_ele/schema/views/data.ts.vm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/data.ts.vm b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/data.ts.vm index da9582448e..c0f5b8e973 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/data.ts.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/data.ts.vm @@ -114,6 +114,7 @@ export function useFormSchema(): VbenFormSchema[] { showTime: true, format: 'YYYY-MM-DD HH:mm:ss', valueFormat: 'x', + class: '!w-full', }, #elseif($column.htmlType == "textarea")## 文本域 component: 'Textarea', @@ -317,6 +318,7 @@ export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] { showTime: true, format: 'YYYY-MM-DD HH:mm:ss', valueFormat: 'x', + class: '!w-full', }, #elseif($column.htmlType == "textarea")## 文本域 component: 'Textarea', @@ -552,6 +554,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${api showTime: true, format: 'YYYY-MM-DD HH:mm:ss', valueFormat: 'x', + class: '!w-full', }, #elseif($column.htmlType == "textarea")## 文本域 component: 'Textarea', From 019d5fb473cea6dec6d35628678aa7a68a3265d4 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 21 Nov 2025 15:52:41 +0800 Subject: [PATCH 07/10] =?UTF-8?q?feat=EF=BC=9A=E3=80=90framework=E3=80=91?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AF=B9=20LocalDateTime=20=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E6=A0=BC=E5=BC=8F=E5=8C=96=E4=B8=8D=E7=94=9F=E6=95=88?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20#1019?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TimestampLocalDateTimeSerializer.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/databind/TimestampLocalDateTimeSerializer.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/databind/TimestampLocalDateTimeSerializer.java index ef767a5585..12354256e3 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/databind/TimestampLocalDateTimeSerializer.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/json/databind/TimestampLocalDateTimeSerializer.java @@ -1,12 +1,16 @@ package cn.iocoder.yudao.framework.common.util.json.databind; +import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; +import org.apache.commons.lang3.reflect.FieldUtils; import java.io.IOException; +import java.lang.reflect.Field; import java.time.LocalDateTime; import java.time.ZoneId; +import java.time.format.DateTimeFormatter; /** * 基于时间戳的 LocalDateTime 序列化器 @@ -19,7 +23,19 @@ public class TimestampLocalDateTimeSerializer extends JsonSerializer clazz = gen.getOutputContext().getCurrentValue().getClass(); + Field field = FieldUtils.getField(clazz, fieldName, true); + // 情况一:有 JsonFormat 自定义注解,则使用它。https://github.com/YunaiV/ruoyi-vue-pro/pull/1019 + JsonFormat[] jsonFormats = field.getAnnotationsByType(JsonFormat.class); + if (jsonFormats.length > 0) { + String pattern = jsonFormats[0].pattern(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); + gen.writeString(formatter.format(value)); + return; + } + + // 情况二:默认将 LocalDateTime 对象,转换为 Long 时间戳 gen.writeNumber(value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()); } From ed3edaf7552f86cb3c14dfe09fab356a98790c6f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 21 Nov 2025 16:47:10 +0800 Subject: [PATCH 08/10] =?UTF-8?q?fix=EF=BC=9A=E3=80=90framework=E3=80=91?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20CorsFilter=20=E5=9B=A0=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E9=A1=BA=E5=BA=8F=E5=BD=B1=E5=93=8D=E5=88=B0=E8=B7=A8=E5=9F=9F?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E4=B8=8D=E7=94=9F=E6=95=88=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/web/config/YudaoWebAutoConfiguration.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java index ed91a99f70..c0d1344392 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java @@ -9,7 +9,6 @@ import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import com.google.common.collect.Maps; -import jakarta.annotation.Resource; import jakarta.servlet.Filter; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfiguration; @@ -21,14 +20,13 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; +import org.springframework.core.annotation.Order; import org.springframework.util.AntPathMatcher; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; -import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import java.util.Map; @@ -106,6 +104,7 @@ public class YudaoWebAutoConfiguration { * 创建 CorsFilter Bean,解决跨域问题 */ @Bean + @Order(value = WebFilterOrderEnum.CORS_FILTER) // 特殊:修复因执行顺序影响到跨域配置不生效问题 public FilterRegistrationBean corsFilterBean() { // 创建 CorsConfiguration 对象 CorsConfiguration config = new CorsConfiguration(); From 24a88059fc0dc823abb9c08f39abe53244d45875 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 21 Nov 2025 16:56:52 +0800 Subject: [PATCH 09/10] =?UTF-8?q?fix=EF=BC=9A=E3=80=90framework=E3=80=91?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20easy-trans=20=E5=9B=A0=E4=B8=BA=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=97=A0?= =?UTF-8?q?=E6=B3=95=E8=AF=BB=E5=8F=96=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rule/DataPermissionRuleFactoryImpl.java | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/DataPermissionRuleFactoryImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/DataPermissionRuleFactoryImpl.java index eaa6e6aeda..8119c7d52b 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/DataPermissionRuleFactoryImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/DataPermissionRuleFactoryImpl.java @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ArrayUtil; import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; import cn.iocoder.yudao.framework.datapermission.core.aop.DataPermissionContextHolder; +import com.fhs.trans.service.impl.SimpleTransService; import lombok.RequiredArgsConstructor; import java.util.Collections; @@ -31,32 +32,53 @@ public class DataPermissionRuleFactoryImpl implements DataPermissionRuleFactory @Override // mappedStatementId 参数,暂时没有用。以后,可以基于 mappedStatementId + DataPermission 进行缓存 public List getDataPermissionRule(String mappedStatementId) { - // 1. 无数据权限 + // 1.1 无数据权限 if (CollUtil.isEmpty(rules)) { return Collections.emptyList(); } - // 2. 未配置,则默认开启 + // 1.2 未配置,则默认开启 DataPermission dataPermission = DataPermissionContextHolder.get(); if (dataPermission == null) { return rules; } - // 3. 已配置,但禁用 + // 1.3 已配置,但禁用 if (!dataPermission.enable()) { return Collections.emptyList(); } + // 1.4 特殊:数据翻译时,强制忽略数据权限 https://github.com/YunaiV/ruoyi-vue-pro/issues/1007 + if (isTranslateCall()) { + return Collections.emptyList(); + } - // 4. 已配置,只选择部分规则 + // 2.1 情况一:已配置,只选择部分规则 if (ArrayUtil.isNotEmpty(dataPermission.includeRules())) { return rules.stream().filter(rule -> ArrayUtil.contains(dataPermission.includeRules(), rule.getClass())) .collect(Collectors.toList()); // 一般规则不会太多,所以不采用 HashSet 查询 } - // 5. 已配置,只排除部分规则 + // 2.2 已配置,只排除部分规则 if (ArrayUtil.isNotEmpty(dataPermission.excludeRules())) { return rules.stream().filter(rule -> !ArrayUtil.contains(dataPermission.excludeRules(), rule.getClass())) .collect(Collectors.toList()); // 一般规则不会太多,所以不采用 HashSet 查询 } - // 6. 已配置,全部规则 + // 2.3 已配置,全部规则 return rules; } + /** + * 判断是否为数据翻译 {@link com.fhs.core.trans.anno.Trans} 的调用 + * + * 目前暂时只有这个办法,已经和 easy-trans 做过沟通 + * + * @return 是否 + */ + private boolean isTranslateCall() { + StackTraceElement[] stack = Thread.currentThread().getStackTrace(); + for (StackTraceElement e : stack) { + if (SimpleTransService.class.getName().equals(e.getClassName())) { + return true; + } + } + return false; + } + } From ec2bca7331ee24ba3315c97d02240eb0ebca8da4 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 21 Nov 2025 20:04:20 +0800 Subject: [PATCH 10/10] =?UTF-8?q?!1441=20=E3=80=90=E8=BD=BB=E9=87=8F?= =?UTF-8?q?=E7=BA=A7=20PR=E3=80=91=EF=BC=9Afix:=20=E3=80=90mall=E3=80=91?= =?UTF-8?q?=E6=89=BE=E4=B8=8D=E5=88=B0=E6=89=80=E5=9C=A8=E5=8C=BA=E5=9F=9F?= =?UTF-8?q?=E7=9A=84=E8=BF=90=E8=B4=B9=E6=94=B6=E8=B4=B9=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E5=92=8C=E8=BF=90=E8=B4=B9=E5=85=8D=E8=B4=B9=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E6=97=B6=EF=BC=88=E5=8D=B3=EF=BC=9A=E6=9C=AA=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=89=80=E5=9C=A8=E5=8C=BA=E5=9F=9F=E7=9A=84=E8=BF=90=E8=B4=B9?= =?UTF-8?q?=E6=A8=A1=E6=9D=BF=EF=BC=89=EF=BC=8C=E4=B8=8D=E6=8A=8A=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF=E5=AF=B9=E8=B1=A1put=E8=BF=9Bresult=E4=B8=AD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../convert/delivery/DeliveryExpressTemplateConvert.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java index b917d874bb..3c02e8917c 100644 --- a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java +++ b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java @@ -85,7 +85,9 @@ public interface DeliveryExpressTemplateConvert { .setChargeMode(template.getChargeMode()) .setCharge(convertTemplateCharge(findFirst(templateIdChargeMap.get(template.getId()), charge -> charge.getAreaIds().contains(areaId)))) .setFree(convertTemplateFree(findFirst(templateIdFreeMap.get(template.getId()), free -> free.getAreaIds().contains(areaId)))); - result.put(template.getId(), bo); + if (bo.getCharge() != null || bo.getFree() != null) { + result.put(template.getId(), bo); + } }); return result; }