Sfoglia il codice sorgente

feat(order): 添加直接下单功能支持

- 新增下单方式字段,区分购物车下单和直接下单
- 实现直接下单的商品信息传递逻辑
- 修改订单创建流程以支持两种下单方式
- 调整购物车删除逻辑仅在购物车下单时执行
- 新增商品编号搜索功能
- 修复商品基础表字段映射问题
- 完善特价商品链接页面的数据展示功能
肖路 1 mese fa
parent
commit
cc27aa671d

+ 32 - 18
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/pc/PcOrderController.java

@@ -32,6 +32,7 @@ import jakarta.validation.constraints.NotNull;
 
 import java.math.BigDecimal;
 import java.time.LocalDate;
+import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -246,25 +247,38 @@ public class PcOrderController extends BaseController {
 
             // 设置订单商品列表
             // mainBo.setOrderProductBos(bo.getOrderProductBos());
+            Map<Long, Long> productNumMap;
             // 1. 获取购物车项
-            Set<Long> productShoppingCartIds = bo.getProductShoppingCartId();
-            if (productShoppingCartIds == null || productShoppingCartIds.isEmpty()) {
-                throw new IllegalArgumentException("购物车项ID不能为空");
+            if(bo.getPlaceOrderType() == 1){
+                productNumMap = Map.of();
+                Set<Long> productShoppingCartIds = bo.getProductShoppingCartId();
+                if (productShoppingCartIds == null || productShoppingCartIds.isEmpty()) {
+                    throw new IllegalArgumentException("购物车项ID不能为空");
+                }
+
+                List<RemoteProductShoppingCartVo> shoppingCartList = remoteProductShoppingCartService.getShoppingCartList(productShoppingCartIds);
+                if (shoppingCartList.isEmpty()) {
+                    throw new IllegalStateException("购物车数据不存在");
+                }
+
+                // 2. 构建 productId -> productNum 映射(防御性:过滤 null key)
+                shoppingCartList.stream()
+                    .filter(item -> item.getProductId() != null && item.getProductNum() != null)
+                    .collect(Collectors.toMap(
+                        RemoteProductShoppingCartVo::getProductId,
+                        RemoteProductShoppingCartVo::getProductNum,
+                        (existing, replacement) -> existing // 防止重复 key 冲突(理论上不应发生)
+                    ));
+            }else {
+                productNumMap = bo.getProductInfo().stream()
+                    .filter(item -> item.getProductId() != null && item.getProductNum() != null)
+                    .collect(Collectors.toMap(
+                        PcSubmitOrderBo.PcOrderProduct::getProductId,
+                        PcSubmitOrderBo.PcOrderProduct::getProductNum,
+                        (existing, replacement) -> existing // 防止重复 key 冲突(理论上不应发生)
+                    ));
             }
 
-            List<RemoteProductShoppingCartVo> shoppingCartList = remoteProductShoppingCartService.getShoppingCartList(productShoppingCartIds);
-            if (shoppingCartList.isEmpty()) {
-                throw new IllegalStateException("购物车数据不存在");
-            }
-
-            // 2. 构建 productId -> productNum 映射(防御性:过滤 null key)
-            Map<Long, Long> productNumMap = shoppingCartList.stream()
-                .filter(item -> item.getProductId() != null && item.getProductNum() != null)
-                .collect(Collectors.toMap(
-                    RemoteProductShoppingCartVo::getProductId,
-                    RemoteProductShoppingCartVo::getProductNum,
-                    (existing, replacement) -> existing // 防止重复 key 冲突(理论上不应发生)
-                ));
 
             // 3. 提取所有商品 ID(使用 List/Collection,而非拼接字符串!)
             List<Long> productIds = new ArrayList<>(productNumMap.keySet());
@@ -308,9 +322,9 @@ public class PcOrderController extends BaseController {
 
             // 5. 保存订单(关键:成功后再删除购物车)
             Long orderId = orderMainService.insertByBo(mainBo);
-            if (orderId != null && orderId > 0) {
+            if (orderId != null && orderId > 0 && bo.getPlaceOrderType() == 1) {
                 // 成功下单后,删除对应的购物车项
-                remoteProductShoppingCartService.deleteWithValidByIds(productShoppingCartIds);
+                remoteProductShoppingCartService.deleteWithValidByIds(bo.getProductShoppingCartId());
             } else {
                 throw new RuntimeException("订单创建失败");
             }

+ 29 - 0
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/domain/bo/PcSubmitOrderBo.java

@@ -4,6 +4,7 @@ import jakarta.validation.constraints.NotNull;
 import lombok.Data;
 
 import java.math.BigDecimal;
+import java.util.List;
 import java.util.Set;
 
 @Data
@@ -44,8 +45,36 @@ public class PcSubmitOrderBo {
      */
     private BigDecimal shippingFee;
 
+    /**
+    * 下单方式  1为购物车下单  2为直接下单
+    * */
+    private Integer placeOrderType;
+
     /**
      * 购物车项id
      */
     private Set<Long> productShoppingCartId;
+
+    /**
+    * 商品信息
+    * */
+    private List<PcOrderProduct> productInfo;
+
+
+    @Data
+    public class PcOrderProduct {
+        /**
+         * 商品ID
+         */
+        @NotNull(message = "商品ID不能为空")
+        private Long productId;
+
+        /**
+         * 商品数量
+         */
+        @NotNull(message = "商品数量不能为空")
+        private Long productNum;
+     }
 }
+
+

+ 4 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/PcProductBo.java

@@ -15,6 +15,10 @@ public class PcProductBo {
      * */
     private String searchKeyword;
     /**
+    * 商品编号
+    * */
+    private String productNo;
+    /**
     * 客户id
     * */
     private Long customerId;

+ 30 - 1
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductSpecialLinkVo.java

@@ -10,6 +10,7 @@ import lombok.Data;
 
 import java.io.Serial;
 import java.io.Serializable;
+import java.math.BigDecimal;
 import java.util.Date;
 
 
@@ -29,7 +30,7 @@ public class ProductSpecialLinkVo implements Serializable {
     private static final long serialVersionUID = 1L;
 
     /**
-     * 
+     *
      */
     @ExcelProperty(value = "")
     private Long id;
@@ -59,5 +60,33 @@ public class ProductSpecialLinkVo implements Serializable {
     @ExcelProperty(value = "备注")
     private String remark;
 
+    /**
+     * 产品图片URL
+     */
+    private String productImage;
+
+    /**
+     * 产品名称
+     */
+    private String itemName;
+
+    /**
+     * 市场价
+     * */
+    @ExcelProperty(value = "市场价")
+    private BigDecimal marketPrice;
+
+    /**
+     * 平台价
+     */
+    private BigDecimal minSellingPrice;
+
+    /**
+     * 总库存
+     * */
+    private Long totalInventory;
+
+
+
 
 }

+ 4 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductBaseServiceImpl.java

@@ -490,6 +490,9 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
         LambdaEsQueryWrapper<ProductBaseVo> wrapper = new LambdaEsQueryWrapper<ProductBaseVo>()
             .eq(ProductBaseVo::getProductStatus, 1);
 
+        if(ObjectUtil.isNotEmpty(bo.getProductNo())){
+            wrapper.eq(ProductBaseVo::getProductNo, bo.getProductNo());
+        }
         if (ObjectUtil.isNotEmpty(bo.getBrandId())) {
             wrapper.eq(ProductBaseVo::getBrandId, bo.getBrandId());
         }
@@ -1443,6 +1446,7 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
                 .or().like("br.brand_name", bo.getSearchKeyword())
             )
         );
+        lqw.like(StringUtils.isNotBlank(bo.getProductNo()), "b.product_no", bo.getProductNo());
         lqw.eq(ObjectUtil.isNotEmpty(bo.getBrandId()), "b.brand_id", bo.getBrandId());
         lqw.eq(ObjectUtil.isNotEmpty(bo.getTopCategoryId()), "b.top_category_id", bo.getTopCategoryId());
         lqw.eq(ObjectUtil.isNotEmpty(bo.getMiddleCategoryId()), "b.middle_category_id", bo.getMiddleCategoryId());

+ 22 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductSpecialLinkServiceImpl.java

@@ -10,6 +10,11 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.dromara.product.domain.ProductBase;
+import org.dromara.product.domain.ProductPriceInventory;
+import org.dromara.product.domain.vo.ProductBaseVo;
+import org.dromara.product.mapper.ProductBaseMapper;
+import org.dromara.product.mapper.ProductPriceInventoryMapper;
 import org.springframework.stereotype.Service;
 import org.dromara.product.domain.bo.ProductSpecialLinkBo;
 import org.dromara.product.domain.vo.ProductSpecialLinkVo;
@@ -34,6 +39,10 @@ public class ProductSpecialLinkServiceImpl  extends ServiceImpl<ProductSpecialLi
 
     private final ProductSpecialLinkMapper baseMapper;
 
+    private final ProductBaseMapper productBaseMapper;
+
+    private final ProductPriceInventoryMapper priceInventoryMapper;
+
     /**
      * 查询特价商品
      *
@@ -56,6 +65,19 @@ public class ProductSpecialLinkServiceImpl  extends ServiceImpl<ProductSpecialLi
     public TableDataInfo<ProductSpecialLinkVo> queryPageList(ProductSpecialLinkBo bo, PageQuery pageQuery) {
         LambdaQueryWrapper<ProductSpecialLink> lqw = buildQueryWrapper(bo);
         Page<ProductSpecialLinkVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        result.getRecords().forEach(item -> {
+            ProductBase productBase = productBaseMapper.selectById(item.getProductId());
+            ProductPriceInventory productPriceInventory = priceInventoryMapper.selectById(item.getProductId());
+            if (productPriceInventory != null){
+                item.setMarketPrice(productPriceInventory.getMarketPrice());
+                item.setTotalInventory(productPriceInventory.getTotalInventory());
+                item.setMinSellingPrice(productPriceInventory.getMinSellingPrice());
+            }
+            if (productBase != null){
+                item.setProductImage(productBase.getProductImage());
+                item.setItemName(productBase.getItemName());
+            }
+        });
         return TableDataInfo.build(result);
     }
 

+ 1 - 1
ruoyi-modules/ruoyi-product/src/main/resources/mapper/product/ProductBaseMapper.xml

@@ -272,8 +272,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             b.product_status AS productStatus,
             b.data_source AS dataSource,
             b.remark,
-            b.is_customize AS isCustomize,
             -- 扩展表字段
+            e.is_customize AS isCustomize,
             e.invoice_name AS invoiceName,
             e.invoice_specs AS invoiceSpec,
             e.bar_coding AS upcBarcode,