Pārlūkot izejas kodu

Merge branch 'master-jdk17' of https://gitee.com/zhijiantianya/ruoyi-vue-pro

YunaiV 5 mēneši atpakaļ
vecāks
revīzija
f3b897ea5d
11 mainītis faili ar 94 papildinājumiem un 61 dzēšanām
  1. 57 21
      yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/MPJLambdaWrapperX.java
  2. 0 1
      yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java
  3. 2 1
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
  4. 10 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmSequentialMultiInstanceBehavior.java
  5. 6 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
  6. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java
  7. 7 17
      yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/general/views/index.vue.vm
  8. 2 2
      yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/general/views/modules/form_sub_normal.vue.vm
  9. 7 17
      yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/general/views/modules/list_sub_erp.vue.vm
  10. 1 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageServiceImpl.java
  11. 1 1
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java

+ 57 - 21
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/MPJLambdaWrapperX.java

@@ -4,7 +4,6 @@ import cn.hutool.core.util.ArrayUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
 import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
-import com.github.yulichang.toolkit.MPJWrappers;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
 import org.springframework.util.StringUtils;
 
@@ -15,93 +14,93 @@ import java.util.function.Consumer;
  * 拓展 MyBatis Plus Join QueryWrapper 类,主要增加如下功能:
  * <p>
  * 1. 拼接条件的方法,增加 xxxIfPresent 方法,用于判断值不存在的时候,不要拼接到条件中。
- *
+ * 2. SFunction<S, ?> column + <S> 泛型:支持任意类字段(主表、子表、三表),推荐写法, 让编译器自动推断 S 类型
  * @param <T> 数据类型
  */
 public class MPJLambdaWrapperX<T> extends MPJLambdaWrapper<T> {
 
-    public <R> MPJLambdaWrapperX<T> likeIfPresent(SFunction<R, ?> column, String val) {
-        MPJWrappers.lambdaJoin().like(column, val);
+    public <S> MPJLambdaWrapperX<T> likeIfPresent(SFunction<S, ?> column, String val) {
         if (StringUtils.hasText(val)) {
             return (MPJLambdaWrapperX<T>) super.like(column, val);
         }
         return this;
     }
 
-    public <R> MPJLambdaWrapperX<T> inIfPresent(SFunction<R, ?> column, Collection<?> values) {
+    public <S> MPJLambdaWrapperX<T> inIfPresent(SFunction<S, ?> column, Collection<?> values) {
         if (ObjectUtil.isAllNotEmpty(values) && !ArrayUtil.isEmpty(values)) {
             return (MPJLambdaWrapperX<T>) super.in(column, values);
         }
         return this;
     }
 
-    public <R> MPJLambdaWrapperX<T> inIfPresent(SFunction<R, ?> column, Object... values) {
+    public <S> MPJLambdaWrapperX<T> inIfPresent(SFunction<S, ?> column, Object... values) {
         if (ObjectUtil.isAllNotEmpty(values) && !ArrayUtil.isEmpty(values)) {
             return (MPJLambdaWrapperX<T>) super.in(column, values);
         }
         return this;
     }
 
-    public <R> MPJLambdaWrapperX<T> eqIfPresent(SFunction<R, ?> column, Object val) {
+    public <S> MPJLambdaWrapperX<T> eqIfPresent(SFunction<S, ?> column, Object val) {
         if (ObjectUtil.isNotEmpty(val)) {
             return (MPJLambdaWrapperX<T>) super.eq(column, val);
         }
         return this;
     }
 
-    public <R> MPJLambdaWrapperX<T> neIfPresent(SFunction<R, ?> column, Object val) {
+    public <S> MPJLambdaWrapperX<T> neIfPresent(SFunction<S, ?> column, Object val) {
         if (ObjectUtil.isNotEmpty(val)) {
             return (MPJLambdaWrapperX<T>) super.ne(column, val);
         }
         return this;
     }
 
-    public <R> MPJLambdaWrapperX<T> gtIfPresent(SFunction<R, ?> column, Object val) {
+    public <S> MPJLambdaWrapperX<T> gtIfPresent(SFunction<S, ?> column, Object val) {
         if (val != null) {
             return (MPJLambdaWrapperX<T>) super.gt(column, val);
         }
         return this;
     }
 
-    public <R> MPJLambdaWrapperX<T> geIfPresent(SFunction<R, ?> column, Object val) {
+    public <S> MPJLambdaWrapperX<T> geIfPresent(SFunction<S, ?> column, Object val) {
         if (val != null) {
             return (MPJLambdaWrapperX<T>) super.ge(column, val);
         }
         return this;
     }
 
-    public <R> MPJLambdaWrapperX<T> ltIfPresent(SFunction<R, ?> column, Object val) {
+    public <S> MPJLambdaWrapperX<T> ltIfPresent(SFunction<S, ?> column, Object val) {
         if (val != null) {
             return (MPJLambdaWrapperX<T>) super.lt(column, val);
         }
         return this;
     }
 
-    public <R> MPJLambdaWrapperX<T> leIfPresent(SFunction<R, ?> column, Object val) {
+    public <S> MPJLambdaWrapperX<T> leIfPresent(SFunction<S, ?> column, Object val) {
         if (val != null) {
             return (MPJLambdaWrapperX<T>) super.le(column, val);
         }
         return this;
     }
 
-    public <R> MPJLambdaWrapperX<T> betweenIfPresent(SFunction<R, ?> column, Object val1, Object val2) {
+    public <S> MPJLambdaWrapperX<T> betweenIfPresent(SFunction<S, ?> column, Object[] values) {
+        Object val1 = ArrayUtils.get(values, 0);
+        Object val2 = ArrayUtils.get(values, 1);
+        return betweenIfPresent(column, val1, val2);
+    }
+
+    public <S> MPJLambdaWrapperX<T> betweenIfPresent(SFunction<S, ?> column, Object val1, Object val2) {
         if (val1 != null && val2 != null) {
             return (MPJLambdaWrapperX<T>) super.between(column, val1, val2);
         }
         if (val1 != null) {
-            return (MPJLambdaWrapperX<T>) ge(column, val1);
+            return (MPJLambdaWrapperX<T>) super.ge(column, val1);
         }
         if (val2 != null) {
-            return (MPJLambdaWrapperX<T>) le(column, val2);
+            return (MPJLambdaWrapperX<T>) super.le(column, val2);
         }
         return this;
     }
 
-    public <R> MPJLambdaWrapperX<T> betweenIfPresent(SFunction<R, ?> column, Object[] values) {
-        Object val1 = ArrayUtils.get(values, 0);
-        Object val2 = ArrayUtils.get(values, 1);
-        return betweenIfPresent(column, val1, val2);
-    }
 
     // ========== 重写父类方法,方便链式调用 ==========
 
@@ -310,4 +309,41 @@ public class MPJLambdaWrapperX<T> extends MPJLambdaWrapper<T> {
         return this;
     }
 
-}
+    // ========== 关键重写:使 leftJoin 返回当前类型 this ==========
+    @Override
+    public <A, B> MPJLambdaWrapperX<T> leftJoin(Class<A> clazz, SFunction<A, ?> left, SFunction<B, ?> right) {
+        super.leftJoin(clazz, left, right);
+        return this;
+    }
+
+    @Override
+    public <A, B> MPJLambdaWrapperX<T> rightJoin(Class<A> clazz, SFunction<A, ?> left, SFunction<B, ?> right) {
+        super.rightJoin(clazz, left, right);
+        return this;
+    }
+
+    @Override
+    public <A, B> MPJLambdaWrapperX<T> innerJoin(Class<A> clazz, SFunction<A, ?> left, SFunction<B, ?> right) {
+        super.innerJoin(clazz, left, right);
+        return this;
+    }
+
+    // ========== 添加扩展 Join 支持 ext 函数式参数 ==========
+    public <A, B> MPJLambdaWrapperX<T> leftJoin(Class<A> clazz, SFunction<A, ?> left, SFunction<B, ?> right, Consumer<MPJLambdaWrapperX<T>> ext) {
+        super.leftJoin(clazz, left, right);
+        if (ext != null) ext.accept(this);
+        return this;
+    }
+
+    public <A, B> MPJLambdaWrapperX<T> rightJoin(Class<A> clazz, SFunction<A, ?> left, SFunction<B, ?> right, Consumer<MPJLambdaWrapperX<T>> ext) {
+        super.rightJoin(clazz, left, right);
+        if (ext != null) ext.accept(this);
+        return this;
+    }
+
+    public <A, B> MPJLambdaWrapperX<T> innerJoin(Class<A> clazz, SFunction<A, ?> left, SFunction<B, ?> right, Consumer<MPJLambdaWrapperX<T>> ext) {
+        super.innerJoin(clazz, left, right);
+        if (ext != null) ext.accept(this);
+        return this;
+    }
+}

+ 0 - 1
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java

@@ -64,7 +64,6 @@ public class AiUtils {
                 return OpenAiChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens)
                         .toolNames(toolNames).toolContext(toolContext).build();
             case AZURE_OPENAI:
-                // TODO 芋艿:貌似没 model 字段???!
                 return AzureOpenAiChatOptions.builder().deploymentName(model).temperature(temperature).maxTokens(maxTokens)
                         .toolNames(toolNames).toolContext(toolContext).build();
             case OLLAMA:

+ 2 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java

@@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.bpm.convert.task;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.map.MapUtil;
-import cn.iocoder.yudao.framework.common.core.KeyValue;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+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.BeanUtils;
 import cn.iocoder.yudao.module.bpm.controller.admin.base.user.UserSimpleBaseVO;
@@ -53,6 +53,7 @@ public interface BpmTaskConvert {
             taskVO.setProcessInstance(BeanUtils.toBean(processInstance, BpmTaskRespVO.ProcessInstance.class));
             AdminUserRespDTO startUser = userMap.get(NumberUtils.parseLong(processInstance.getStartUserId()));
             taskVO.getProcessInstance().setStartUser(BeanUtils.toBean(startUser, UserSimpleBaseVO.class));
+            taskVO.getProcessInstance().setCreateTime(DateUtils.of(processInstance.getStartTime()));
             // 摘要
             taskVO.getProcessInstance().setSummary(FlowableUtils.getSummary(processDefinitionInfoMap.get(processInstance.getProcessDefinitionId()),
                     processInstance.getProcessVariables()));

+ 10 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmSequentialMultiInstanceBehavior.java

@@ -14,6 +14,7 @@ import org.flowable.bpmn.model.UserTask;
 import org.flowable.engine.delegate.DelegateExecution;
 import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior;
 import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
+import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
 
 import java.util.List;
 import java.util.Set;
@@ -82,4 +83,13 @@ public class BpmSequentialMultiInstanceBehavior extends SequentialMultiInstanceB
         return super.resolveNrOfInstances(execution);
     }
 
+    @Override
+    protected void executeOriginalBehavior(DelegateExecution execution, ExecutionEntity multiInstanceRootExecution, int loopCounter) {
+        // 参见 https://gitee.com/zhijiantianya/yudao-cloud/issues/IC239F
+        super.collectionExpression = null;
+        super.collectionVariable = FlowableUtils.formatExecutionCollectionVariable(execution.getCurrentActivityId());
+        super.collectionElementVariable = FlowableUtils.formatExecutionCollectionElementVariable(execution.getCurrentActivityId());
+        super.executeOriginalBehavior(execution, multiInstanceRootExecution, loopCounter);
+    }
+
 }

+ 6 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java

@@ -597,6 +597,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
      * @param nextAssignees 下一个节点审批人集合(参数)
      * @param processInstance 流程实例
      */
+    @SuppressWarnings("unchecked")
     private Map<String, Object> validateAndSetNextAssignees(String taskDefinitionKey, Map<String, Object> variables, BpmnModel bpmnModel,
                                                             Map<String, List<Long>> nextAssignees, ProcessInstance processInstance) {
         // simple 设计器第一个节点默认为发起人节点,不校验是否存在审批人
@@ -646,6 +647,11 @@ public class BpmTaskServiceImpl implements BpmTaskService {
                     approveUserSelectAssignees = new HashMap<>();
                 }
                 approveUserSelectAssignees.put(nextFlowNode.getId(), assignees);
+                Map<String,List<Long>> existingApproveUserSelectAssignees = (Map<String,List<Long>>) variables.get(
+                        BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES);
+                if (CollUtil.isNotEmpty(existingApproveUserSelectAssignees)) {
+                    approveUserSelectAssignees.putAll(existingApproveUserSelectAssignees);
+                }
                 variables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_APPROVE_USER_SELECT_ASSIGNEES, approveUserSelectAssignees);
             }
         }

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java

@@ -214,7 +214,7 @@ public class CrmContactServiceImpl implements CrmContactService {
         }
     }
 
-    @LogRecord(type = CRM_CONTACT_TYPE, subType = CRM_CONTACT_UPDATE_OWNER_USER_SUB_TYPE, bizNo = "{{#contact.id}",
+    @LogRecord(type = CRM_CONTACT_TYPE, subType = CRM_CONTACT_UPDATE_OWNER_USER_SUB_TYPE, bizNo = "{{#contact.id}}",
             success = CRM_CONTACT_UPDATE_OWNER_USER_SUCCESS)
     public void receiveContactLog(CrmContactDO contact, Long ownerUserId) {
         // 记录操作日志上下文

+ 7 - 17
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/general/views/index.vue.vm

@@ -1,6 +1,6 @@
 <script lang="ts" setup>
 import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
-import type { VxeTableInstance } from 'vxe-table';
+import type { VxeTableInstance } from '#/adapter/vxe-table';
 
 import { Page, useVbenModal } from '@vben/common-ui';
 import { cloneDeep, formatDateTime } from '@vben/utils';
@@ -9,9 +9,10 @@ import { DictTag } from '#/components/dict-tag';
 import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
 import ${simpleClassName}Form from './modules/form.vue';
 import { Download, Plus, RefreshCw, Search } from '@vben/icons';
-import { ContentWrap } from "#/components/content-wrap";
-import { VxeColumn, VxeTable } from 'vxe-table';
+import { ContentWrap } from '#/components/content-wrap';
+import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
 import { TableToolbar } from '#/components/table-toolbar';
+import { useTableToolbar } from '#/hooks';
 
 ## 特殊:主子表专属逻辑
 #if ( $table.templateType == 11 || $table.templateType == 12 )
@@ -167,11 +168,6 @@ try {
 }
 }
 
-/** 隐藏搜索栏 */
-const hiddenSearchBar = ref(false);
-const tableToolbarRef = ref<InstanceType<typeof TableToolbar>>();
-const tableRef = ref<VxeTableInstance>();
-
 #if (${table.templateType} == 2)
 /** 切换树形展开/收缩状态 */
 const isExpanded = ref(true);
@@ -182,15 +178,9 @@ function toggleExpand() {
 #end
 
 /** 初始化 */
-onMounted(async () => {
-  await getList();
-  await nextTick();
-  // 挂载 toolbar 工具栏
-  const table = tableRef.value;
-  const tableToolbar = tableToolbarRef.value;
-  if (table && tableToolbar) {
-    await table.connect(tableToolbar.getToolbarRef()!);
-  }
+const { hiddenSearchBar, tableToolbarRef, tableRef } = useTableToolbar();
+onMounted(() => {
+  getList();
 });
 </script>
 

+ 2 - 2
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/general/views/modules/form_sub_normal.vue.vm

@@ -13,9 +13,9 @@
   import { DICT_TYPE, getDictOptions } from '#/utils';
 
 #if ($subTable.subJoinMany) ## 一对多
-import type { VxeTableInstance } from 'vxe-table';
+import type { VxeTableInstance } from '#/adapter/vxe-table';
 import { Plus } from "@vben/icons";
-import { VxeColumn, VxeTable } from 'vxe-table';
+import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
 import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
 #else
 import type { Rule } from 'ant-design-vue/es/form';

+ 7 - 17
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben5_antd/general/views/modules/list_sub_erp.vue.vm

@@ -7,14 +7,14 @@
 #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
 <script lang="ts" setup>
   import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
-  import type { VxeTableInstance } from 'vxe-table';
+  import type { VxeTableInstance } from '#/adapter/vxe-table';
 
   import { DictTag } from '#/components/dict-tag';
   import { DICT_TYPE, getDictOptions } from '#/utils';
-  import { VxeColumn, VxeTable } from 'vxe-table';
+  import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
   import { reactive,ref, h, nextTick,watch,onMounted } from 'vue';
   import { cloneDeep, formatDateTime } from '@vben/utils';
-  import { ContentWrap } from "#/components/content-wrap";
+  import { ContentWrap } from '#/components/content-wrap';
 
 #if ($table.templateType == 11) ## erp
     import { useVbenModal } from '@vben/common-ui';
@@ -26,6 +26,7 @@
     import { Plus } from '@vben/icons';
     import { $t } from '#/locales';
     import { TableToolbar } from '#/components/table-toolbar';
+    import { useTableToolbar } from '#/hooks';
 #end
 
 #if ($table.templateType == 11) ## erp
@@ -165,21 +166,10 @@ const resetQuery = () => {
   );
 
 #if ($table.templateType == 11) ## erp
-/** 隐藏搜索栏 */
-const hiddenSearchBar = ref(false);
-const tableToolbarRef = ref<InstanceType<typeof TableToolbar>>();
-const tableRef = ref<VxeTableInstance>();
-
 /** 初始化 */
-onMounted(async () => {
-  await getList();
-  await nextTick();
-  // 挂载 toolbar 工具栏
-  const table = tableRef.value;
-  const tableToolbar = tableToolbarRef.value;
-  if (table && tableToolbar) {
-    await table.connect(tableToolbar.getToolbarRef()!);
-  }
+const { hiddenSearchBar, tableToolbarRef, tableRef } = useTableToolbar();
+onMounted(() => {
+  getList();
 });
 #end
 </script>

+ 1 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageServiceImpl.java

@@ -92,6 +92,7 @@ public class KeFuMessageServiceImpl implements KeFuMessageService {
         MemberUserRespDTO user = memberUserApi.getUser(kefuMessage.getSenderId());
         KeFuMessageRespVO message = BeanUtils.toBean(kefuMessage, KeFuMessageRespVO.class).setSenderAvatar(user.getAvatar());
         getSelf().sendAsyncMessageToAdmin(KEFU_MESSAGE_TYPE, message);
+        getSelf().sendAsyncMessageToMember(conversation.getUserId(), KEFU_MESSAGE_TYPE, message);
         return kefuMessage.getId();
     }
 

+ 1 - 1
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java

@@ -395,7 +395,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
 
         // 3. 记录订单日志
         TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.DELIVERED.getStatus(),
-                MapUtil.<String, Object>builder().put("deliveryName", express != null ? express.getName() : "")
+                MapUtil.<String, Object>builder().put("expressName", express != null ? express.getName() : "")
                         .put("logisticsNo", express != null ? deliveryReqVO.getLogisticsNo() : "").build());
 
         // 4.1 发送站内信