Browse Source

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

YunaiV 10 months ago
parent
commit
3e3bcc963d

+ 2 - 1
yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java

@@ -21,7 +21,8 @@ import org.springframework.context.annotation.Bean;
 @AutoConfiguration
 @ConditionalOnClass(name = {
         "org.apache.skywalking.apm.toolkit.opentracing.SkywalkingTracer",
-        "io.opentracing.Tracer"
+        "io.opentracing.Tracer",
+        "jakarta.servlet.Filter"
 })
 @EnableConfigurationProperties(TracerProperties.class)
 @ConditionalOnProperty(prefix = "yudao.tracer", value = "enable", matchIfMissing = true)

+ 26 - 5
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java

@@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.common.pojo.SortingField;
 import cn.iocoder.yudao.framework.mybatis.core.enums.DbTypeEnum;
 import com.baomidou.mybatisplus.annotation.DbType;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.OrderItem;
 import com.baomidou.mybatisplus.core.toolkit.StringPool;
@@ -47,16 +48,36 @@ public class MyBatisUtils {
         return page;
     }
 
+    @SuppressWarnings("PatternVariableCanBeUsed")
     public static <T> void addOrder(Wrapper<T> wrapper, Collection<SortingField> sortingFields) {
         if (CollUtil.isEmpty(sortingFields)) {
             return;
         }
-        QueryWrapper<T> query = (QueryWrapper<T>) wrapper;
-        for (SortingField sortingField : sortingFields) {
-            query.orderBy(true,
-                    SortingField.ORDER_ASC.equals(sortingField.getOrder()),
-                    StrUtil.toUnderlineCase(sortingField.getField()));
+        if (wrapper instanceof QueryWrapper<T>) {
+            QueryWrapper<T> query = (QueryWrapper<T>) wrapper;
+            for (SortingField sortingField : sortingFields) {
+                query.orderBy(true,
+                        SortingField.ORDER_ASC.equals(sortingField.getOrder()),
+                        StrUtil.toUnderlineCase(sortingField.getField()));
+            }
+        } else if (wrapper instanceof LambdaQueryWrapper<T>) {
+            // LambdaQueryWrapper 不直接支持字符串字段排序,使用 last 方法拼接 ORDER BY
+            LambdaQueryWrapper<T> lambdaQuery = (LambdaQueryWrapper<T>) wrapper;
+            StringBuilder orderBy = new StringBuilder();
+            for (SortingField sortingField : sortingFields) {
+                if (StrUtil.isNotEmpty(orderBy)) {
+                    orderBy.append(", ");
+                }
+                orderBy.append(StrUtil.toUnderlineCase(sortingField.getField()))
+                       .append(" ")
+                       .append(SortingField.ORDER_ASC.equals(sortingField.getOrder()) ? "ASC" : "DESC");
+            }
+            lambdaQuery.last("ORDER BY " + orderBy);
+            // 另外个思路:https://blog.csdn.net/m0_59084856/article/details/138450913
+        } else {
+            throw new IllegalArgumentException("Unsupported wrapper type: " + wrapper.getClass().getName());
         }
+
     }
 
     /**

+ 3 - 1
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/encrypt/core/filter/ApiEncryptFilter.java

@@ -128,6 +128,7 @@ public class ApiEncryptFilter extends ApiRequestFilter {
      *
      * @param request 请求
      */
+    @SuppressWarnings("PatternVariableCanBeUsed")
     private ApiEncrypt getApiEncrypt(HttpServletRequest request) {
         try {
             HandlerExecutionChain mappingHandler = requestMappingHandlerMapping.getHandler(request);
@@ -135,7 +136,8 @@ public class ApiEncryptFilter extends ApiRequestFilter {
                 return null;
             }
             Object handler = mappingHandler.getHandler();
-            if (handler instanceof HandlerMethod handlerMethod) {
+            if (handler instanceof HandlerMethod) {
+                HandlerMethod handlerMethod = (HandlerMethod) handler;
                 ApiEncrypt annotation = handlerMethod.getMethodAnnotation(ApiEncrypt.class);
                 if (annotation == null) {
                     annotation = handlerMethod.getBeanType().getAnnotation(ApiEncrypt.class);

+ 18 - 3
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java

@@ -36,6 +36,7 @@ import org.springframework.web.bind.MissingServletRequestParameterException;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.RestControllerAdvice;
 import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
+import org.springframework.web.multipart.MaxUploadSizeExceededException;
 import org.springframework.web.servlet.NoHandlerFoundException;
 import org.springframework.web.servlet.resource.NoResourceFoundException;
 
@@ -93,6 +94,9 @@ public class GlobalExceptionHandler {
         if (ex instanceof ValidationException) {
             return validationException((ValidationException) ex);
         }
+        if (ex instanceof MaxUploadSizeExceededException) {
+            return maxUploadSizeExceededExceptionHandler((MaxUploadSizeExceededException) ex);
+        }
         if (ex instanceof NoHandlerFoundException) {
             return noHandlerFoundExceptionHandler((NoHandlerFoundException) ex);
         }
@@ -111,9 +115,6 @@ public class GlobalExceptionHandler {
         if (ex instanceof AccessDeniedException) {
             return accessDeniedExceptionHandler(request, (AccessDeniedException) ex);
         }
-        if (ex instanceof UncheckedExecutionException && ex.getCause() != ex) {
-            return allExceptionHandler(request, ex.getCause());
-        }
         return defaultExceptionHandler(request, ex);
     }
 
@@ -213,6 +214,14 @@ public class GlobalExceptionHandler {
         return CommonResult.error(BAD_REQUEST);
     }
 
+    /**
+     * 处理上传文件过大异常
+     */
+    @ExceptionHandler(MaxUploadSizeExceededException.class)
+    public CommonResult<?> maxUploadSizeExceededExceptionHandler(MaxUploadSizeExceededException ex) {
+        return CommonResult.error(BAD_REQUEST.getCode(), "上传文件过大,请调整后重试");
+    }
+
     /**
      * 处理 SpringMVC 请求地址不存在
      *
@@ -309,6 +318,12 @@ public class GlobalExceptionHandler {
      */
     @ExceptionHandler(value = Exception.class)
     public CommonResult<?> defaultExceptionHandler(HttpServletRequest req, Throwable ex) {
+        // 特殊:如果是 ServiceException 的异常,则直接返回
+        // 例如说:https://gitee.com/zhijiantianya/yudao-cloud/issues/ICSSRM、https://gitee.com/zhijiantianya/yudao-cloud/issues/ICT6FM
+        if (ex.getCause() != null && ex.getCause() instanceof ServiceException) {
+            return serviceExceptionHandler((ServiceException) ex.getCause());
+        }
+
         // 情况一:处理表不存在的异常
         CommonResult<?> tableNotExistsResult = handleTableNotExists(ex);
         if (tableNotExistsResult != null) {

+ 6 - 6
yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java

@@ -30,7 +30,7 @@ public interface CouponConvert {
     CouponRespDTO convert(CouponDO bean);
 
     default CouponDO convert(CouponTemplateDO template, Long userId) {
-        CouponDO couponDO = new CouponDO()
+        CouponDO coupon = new CouponDO()
                 .setTemplateId(template.getId())
                 .setName(template.getName())
                 .setTakeType(template.getTakeType())
@@ -44,13 +44,13 @@ public interface CouponConvert {
                 .setStatus(CouponStatusEnum.UNUSED.getStatus())
                 .setUserId(userId);
         if (CouponTemplateValidityTypeEnum.DATE.getType().equals(template.getValidityType())) {
-            couponDO.setValidStartTime(template.getValidStartTime());
-            couponDO.setValidEndTime(template.getValidEndTime());
+            coupon.setValidStartTime(template.getValidStartTime());
+            coupon.setValidEndTime(template.getValidEndTime());
         } else if (CouponTemplateValidityTypeEnum.TERM.getType().equals(template.getValidityType())) {
-            couponDO.setValidStartTime(LocalDateTime.now().plusDays(template.getFixedStartTerm()));
-            couponDO.setValidEndTime(LocalDateTime.now().plusDays(template.getFixedEndTerm()));
+            coupon.setValidStartTime(LocalDateTime.now().plusDays(template.getFixedStartTerm()));
+            coupon.setValidEndTime(coupon.getValidStartTime().plusDays(template.getFixedEndTerm()));
         }
-        return couponDO;
+        return coupon;
     }
 
     CouponPageReqVO convert(AppCouponPageReqVO pageReqVO, Collection<Long> userIds);

+ 34 - 17
yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeStatusSyncToWxaOrderHandler.java

@@ -42,6 +42,40 @@ public class TradeStatusSyncToWxaOrderHandler implements TradeOrderHandler {
         if (ObjUtil.notEqual(order.getPayChannelCode(), PayChannelEnum.WX_LITE.getCode())) {
             return;
         }
+
+        // 上传订单物流信息到微信小程序
+        uploadWxaOrderShippingInfo(order);
+    }
+
+    @Override
+    public void afterReceiveOrder(TradeOrderDO order) {
+        // 注意:只有微信小程序支付的订单,才需要同步
+        if (ObjUtil.notEqual(order.getPayChannelCode(), PayChannelEnum.WX_LITE.getCode())) {
+            return;
+        }
+        PayOrderRespDTO payOrder = payOrderApi.getOrder(order.getPayOrderId());
+        SocialWxaOrderNotifyConfirmReceiveReqDTO reqDTO = new SocialWxaOrderNotifyConfirmReceiveReqDTO()
+                .setTransactionId(payOrder.getChannelOrderNo())
+                .setReceivedTime(order.getReceiveTime());
+        try {
+            socialClientApi.notifyWxaOrderConfirmReceive(UserTypeEnum.MEMBER.getValue(), reqDTO);
+        } catch (Exception ex) {
+            log.error("[afterReceiveOrder][订单({}) 通知订单收货到微信小程序失败]", order, ex);
+        }
+
+        // 如果是门店自提订单,上传订单物流信息到微信小程序
+        // 原因是,门店自提订单没有 “afterDeliveryOrder” 阶段。可见 https://t.zsxq.com/KWD3u 反馈
+        if (DeliveryTypeEnum.PICK_UP.getType().equals(order.getDeliveryType())) {
+            uploadWxaOrderShippingInfo(order);
+        }
+    }
+
+    /**
+     * 上传订单物流信息到微信小程序
+     *
+     * @param order 订单
+     */
+    private void uploadWxaOrderShippingInfo(TradeOrderDO order) {
         PayOrderRespDTO payOrder = payOrderApi.getOrder(order.getPayOrderId());
         SocialWxaOrderUploadShippingInfoReqDTO reqDTO = new SocialWxaOrderUploadShippingInfoReqDTO()
                 .setTransactionId(payOrder.getChannelOrderNo())
@@ -64,23 +98,6 @@ public class TradeStatusSyncToWxaOrderHandler implements TradeOrderHandler {
         }
     }
 
-    @Override
-    public void afterReceiveOrder(TradeOrderDO order) {
-        // 注意:只有微信小程序支付的订单,才需要同步
-        if (ObjUtil.notEqual(order.getPayChannelCode(), PayChannelEnum.WX_LITE.getCode())) {
-            return;
-        }
-        PayOrderRespDTO payOrder = payOrderApi.getOrder(order.getPayOrderId());
-        SocialWxaOrderNotifyConfirmReceiveReqDTO reqDTO = new SocialWxaOrderNotifyConfirmReceiveReqDTO()
-                .setTransactionId(payOrder.getChannelOrderNo())
-                .setReceivedTime(order.getReceiveTime());
-        try {
-            socialClientApi.notifyWxaOrderConfirmReceive(UserTypeEnum.MEMBER.getValue(), reqDTO);
-        } catch (Exception ex) {
-            log.error("[afterReceiveOrder][订单({}) 通知订单收货到微信小程序失败]", order, ex);
-        }
-    }
-
     // TODO @芋艿:【设置路径】 https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/business-capabilities/order-shipping/order-shipping.html#%E5%85%AD%E3%80%81%E6%B6%88%E6%81%AF%E8%B7%B3%E8%BD%AC%E8%B7%AF%E5%BE%84%E8%AE%BE%E7%BD%AE%E6%8E%A5%E5%8F%A3
 
 }