diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleMapper.java index 24d1722..d60b7a9 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleMapper.java @@ -7,8 +7,9 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleDO; -import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; +import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeBizSceneEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; @@ -36,6 +37,7 @@ public interface AfterSaleMapper extends BaseMapperX { /** * 售后按关联订单做商城/售货机拆分 + 设备绑定过滤 + *

使用 EXISTS,避免 IN/NOT IN 大子查询导致超时。 */ static void appendBizSceneAndDeviceFilter(LambdaQueryWrapperX wrapper, String bizScene, @@ -48,11 +50,18 @@ public interface AfterSaleMapper extends BaseMapperX { "SELECT order_id FROM trade_order_item WHERE deleted = 0 AND device_id IN (" + inValues + ")"); return; } - String machineOrderSql = TradeOrderMapper.buildMachineOrderIdSql(); + int machineType = TradeOrderTypeEnum.MACHINE.getType(); + int doorType = DeliveryTypeEnum.DOOR.getType(); + String machineExistsSql = "(" + + "EXISTS (SELECT 1 FROM trade_order o WHERE o.id = trade_after_sale.order_id AND o.deleted = 0" + + " AND (o.type = " + machineType + " OR o.delivery_type = " + doorType + "))" + + " OR EXISTS (SELECT 1 FROM trade_order_item i WHERE i.order_id = trade_after_sale.order_id" + + " AND i.deleted = 0 AND i.device_id IS NOT NULL AND i.device_id != '')" + + ")"; if (TradeBizSceneEnum.isMachine(bizScene)) { - wrapper.inSql(AfterSaleDO::getOrderId, machineOrderSql); + wrapper.apply(machineExistsSql); } else { - wrapper.notInSql(AfterSaleDO::getOrderId, machineOrderSql); + wrapper.apply("NOT " + machineExistsSql); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java index ce030f2..4edc3a7 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java @@ -93,7 +93,9 @@ public interface TradeOrderItemMapper extends BaseMapperX { .inIfPresent(TradeOrderItemDO::getDeviceId, salesStatisticsReqVO.getBindDeviceImeis()) .eqIfPresent(TradeOrderItemDO::getBarCode, salesStatisticsReqVO.getBarCode()) .likeIfPresent(TradeOrderItemDO::getSpuName, salesStatisticsReqVO.getSpuName()) - .betweenIfPresent(TradeOrderItemDO::getCreateTime, salesStatisticsReqVO.getCreateTime()); + .betweenIfPresent(TradeOrderItemDO::getCreateTime, salesStatisticsReqVO.getCreateTime()) + .orderByDesc(TradeOrderItemDO::getCreateTime) + .orderByDesc(TradeOrderItemDO::getId); appendSalesBizSceneFilter(query, salesStatisticsReqVO.getBizScene(), CollUtil.isNotEmpty(salesStatisticsReqVO.getBindDeviceImeis()) || StrUtil.isNotEmpty(salesStatisticsReqVO.getDeviceId())); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java index c797255..cd41f6b 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderMapper.java @@ -81,6 +81,7 @@ public interface TradeOrderMapper extends BaseMapperX { *

  • machine:售货机订单(type/delivery/item.device_id)
  • *
  • mall(默认):排除售货机订单
  • * + *

    使用 EXISTS / 字段条件,避免 IN (大表 DISTINCT JOIN) 导致分页超时。 */ static void appendBizSceneAndDeviceFilter(LambdaQueryWrapperX wrapper, String bizScene, @@ -89,11 +90,7 @@ public interface TradeOrderMapper extends BaseMapperX { wrapper.inSql(TradeOrderDO::getId, buildOrderIdInSqlByDeviceImeis(bindDeviceImeis)); return; } - if (TradeBizSceneEnum.isMachine(bizScene)) { - wrapper.inSql(TradeOrderDO::getId, buildMachineOrderIdSql()); - } else { - wrapper.notInSql(TradeOrderDO::getId, buildMachineOrderIdSql()); - } + applyMachineSceneCondition(wrapper, TradeBizSceneEnum.isMachine(bizScene)); } static void appendBizSceneAndDeviceFilter(MPJLambdaWrapperX wrapper, @@ -103,11 +100,7 @@ public interface TradeOrderMapper extends BaseMapperX { wrapper.inSql(TradeOrderDO::getId, buildOrderIdInSqlByDeviceImeis(bindDeviceImeis)); return; } - if (TradeBizSceneEnum.isMachine(bizScene)) { - wrapper.inSql(TradeOrderDO::getId, buildMachineOrderIdSql()); - } else { - wrapper.notInSql(TradeOrderDO::getId, buildMachineOrderIdSql()); - } + applyMachineSceneCondition(wrapper, TradeBizSceneEnum.isMachine(bizScene)); } static String buildOrderIdInSqlByDeviceImeis(List bindDeviceImeis) { @@ -118,18 +111,54 @@ public interface TradeOrderMapper extends BaseMapperX { } /** - * 售货机订单:type=MACHINE 或 delivery_type=DOOR 或订单项有 device_id + * 订单项是否绑定了设备 IMEI(关联当前 trade_order 行) + */ + private static final String MACHINE_ITEM_EXISTS_SQL = + "EXISTS (SELECT 1 FROM trade_order_item i WHERE i.order_id = trade_order.id" + + " AND i.deleted = 0 AND i.device_id IS NOT NULL AND i.device_id != '')"; + + /** + * 售货机订单条件:type=MACHINE 或 delivery_type=DOOR 或订单项有 device_id + */ + static void applyMachineSceneCondition(LambdaQueryWrapperX wrapper, boolean machine) { + int machineType = TradeOrderTypeEnum.MACHINE.getType(); + int doorType = DeliveryTypeEnum.DOOR.getType(); + if (machine) { + wrapper.and(w -> w.eq(TradeOrderDO::getType, machineType) + .or().eq(TradeOrderDO::getDeliveryType, doorType) + .or().apply(MACHINE_ITEM_EXISTS_SQL)); + } else { + // 排除售货机:type/delivery 允许 NULL(与原 NOT IN 语义一致) + wrapper.and(w -> w.isNull(TradeOrderDO::getType).or().ne(TradeOrderDO::getType, machineType)) + .and(w -> w.isNull(TradeOrderDO::getDeliveryType).or().ne(TradeOrderDO::getDeliveryType, doorType)) + .apply("NOT " + MACHINE_ITEM_EXISTS_SQL); + } + } + + static void applyMachineSceneCondition(MPJLambdaWrapperX wrapper, boolean machine) { + int machineType = TradeOrderTypeEnum.MACHINE.getType(); + int doorType = DeliveryTypeEnum.DOOR.getType(); + if (machine) { + wrapper.and(w -> w.eq(TradeOrderDO::getType, machineType) + .or().eq(TradeOrderDO::getDeliveryType, doorType) + .or().apply(MACHINE_ITEM_EXISTS_SQL)); + } else { + wrapper.and(w -> w.isNull(TradeOrderDO::getType).or().ne(TradeOrderDO::getType, machineType)) + .and(w -> w.isNull(TradeOrderDO::getDeliveryType).or().ne(TradeOrderDO::getDeliveryType, doorType)) + .apply("NOT " + MACHINE_ITEM_EXISTS_SQL); + } + } + + /** + * 售货机订单 ID 子查询(售后等场景复用)。UNION 分段查询,避免 LEFT JOIN DISTINCT 全表扫描。 */ static String buildMachineOrderIdSql() { int machineType = TradeOrderTypeEnum.MACHINE.getType(); int doorType = DeliveryTypeEnum.DOOR.getType(); - return "SELECT DISTINCT o.id FROM trade_order o" - + " LEFT JOIN trade_order_item i ON i.order_id = o.id AND i.deleted = 0" - + " WHERE o.deleted = 0 AND (" - + " o.type = " + machineType - + " OR o.delivery_type = " + doorType - + " OR (i.device_id IS NOT NULL AND i.device_id != '')" - + ")"; + return "SELECT id FROM trade_order WHERE deleted = 0 AND type = " + machineType + + " UNION SELECT id FROM trade_order WHERE deleted = 0 AND delivery_type = " + doorType + + " UNION SELECT order_id FROM trade_order_item WHERE deleted = 0" + + " AND device_id IS NOT NULL AND device_id != ''"; } /** 判断订单是否为售货机订单(详情权限等复用) */