diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 3bf41dcc8..1bac18123 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -64,6 +64,7 @@ 0.1.55 2.4.1 1.3.0 + 4.1.75.Final 8.2.2 4.6.0 @@ -563,6 +564,12 @@ ${jsch.version} + + io.netty + netty-all + ${netty-all.version} + + cn.iocoder.cloud diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java index e338e2c73..e9ec9772c 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantAutoConfiguration.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.tenant.core.db.TenantDatabaseInterceptor; import cn.iocoder.yudao.framework.tenant.core.job.TenantJobAspect; import cn.iocoder.yudao.framework.tenant.core.mq.TenantChannelInterceptor; import cn.iocoder.yudao.framework.tenant.core.mq.TenantFunctionAroundWrapper; +import cn.iocoder.yudao.framework.tenant.core.redis.TenantRedisCacheManager; import cn.iocoder.yudao.framework.tenant.core.security.TenantSecurityWebFilter; import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService; import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkServiceImpl; @@ -25,8 +26,16 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.cloud.function.context.catalog.FunctionAroundWrapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.integration.config.GlobalChannelInterceptor; +import java.util.Objects; + @Configuration @ConditionalOnProperty(prefix = "yudao.tenant", value = "enable", matchIfMissing = true) // 允许使用 yudao.tenant.enable=false 禁用多租户 @EnableConfigurationProperties(TenantProperties.class) @@ -122,4 +131,17 @@ public class YudaoTenantAutoConfiguration { return new TenantJobAspect(tenantFrameworkService); } + // ========== Redis ========== + + @Bean + @Primary // 引入租户时,tenantRedisCacheManager 为主 Bean + public RedisCacheManager tenantRedisCacheManager(RedisTemplate redisTemplate, + RedisCacheConfiguration redisCacheConfiguration) { + // 创建 RedisCacheWriter 对象 + RedisConnectionFactory connectionFactory = Objects.requireNonNull(redisTemplate.getConnectionFactory()); + RedisCacheWriter cacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory); + // 创建 TenantRedisCacheManager 对象 + return new TenantRedisCacheManager(cacheWriter, redisCacheConfiguration); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/redis/TenantRedisCacheManager.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/redis/TenantRedisCacheManager.java new file mode 100644 index 000000000..8058b2f54 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/redis/TenantRedisCacheManager.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.framework.tenant.core.redis; + +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.Cache; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; + +/** + * 多租户的 {@link RedisCacheManager} 实现类 + * + * 操作指定 name 的 {@link Cache} 时,自动拼接租户后缀,格式为 name + ":" + tenantId + 后缀 + * + * @author airhead + */ +@Slf4j +public class TenantRedisCacheManager extends RedisCacheManager { + + public TenantRedisCacheManager(RedisCacheWriter cacheWriter, + RedisCacheConfiguration defaultCacheConfiguration) { + super(cacheWriter, defaultCacheConfiguration); + } + + @Override + public Cache getCache(String name) { + // 如果开启多租户,则 name 拼接租户后缀 + if (!TenantContextHolder.isIgnore() + && TenantContextHolder.getTenantId() != null) { + name = name + ":" + TenantContextHolder.getTenantId(); + } + + // 继续基于父方法 + return super.getCache(name); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-redis/pom.xml b/yudao-framework/yudao-spring-boot-starter-redis/pom.xml index f1d66e776..06ce85bd3 100644 --- a/yudao-framework/yudao-spring-boot-starter-redis/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-redis/pom.xml @@ -32,6 +32,11 @@ spring-boot-starter-cache + + io.netty + netty-all + 4.1.75.Final + diff --git a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java index e8c716203..6a8f92efc 100644 --- a/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-redis/src/main/java/cn/iocoder/yudao/framework/redis/config/YudaoCacheAutoConfiguration.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.framework.redis.config; import org.springframework.boot.autoconfigure.cache.CacheProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -13,6 +14,7 @@ import org.springframework.data.redis.serializer.RedisSerializer; * Cache 配置类,基于 Redis 实现 */ @Configuration +@EnableConfigurationProperties({CacheProperties.class}) @EnableCaching public class YudaoCacheAutoConfiguration { diff --git a/归档/moved/product/product-start/src/main/java/cn/iocoder/mall/product/application/convert/ProductAttrConvert.java b/归档/moved/product/product-start/src/main/java/cn/iocoder/mall/product/application/convert/ProductAttrConvert.java deleted file mode 100644 index 2d9a9f9e2..000000000 --- a/归档/moved/product/product-start/src/main/java/cn/iocoder/mall/product/application/convert/ProductAttrConvert.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.mall.product.application.convert; - -import cn.iocoder.mall.product.api.bo.ProductAttrBO; -import cn.iocoder.mall.product.api.bo.ProductAttrPageBO; -import cn.iocoder.mall.product.api.bo.ProductAttrSimpleBO; -import cn.iocoder.mall.product.api.bo.ProductAttrValueBO; -import cn.iocoder.mall.product.application.vo.admins.AdminsProductAttrPageVO; -import cn.iocoder.mall.product.application.vo.admins.AdminsProductAttrSimpleVO; -import cn.iocoder.mall.product.application.vo.admins.AdminsProductAttrVO; -import cn.iocoder.mall.product.application.vo.admins.AdminsProductAttrValueVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mappings; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface ProductAttrConvert { - - ProductAttrConvert INSTANCE = Mappers.getMapper(ProductAttrConvert.class); - - @Mappings({}) - AdminsProductAttrPageVO convert2(ProductAttrPageBO result); - - @Mappings({}) - List convert(List result); - - @Mappings({}) - AdminsProductAttrVO convert3(ProductAttrBO productAttrBO); - - @Mappings({}) - AdminsProductAttrValueVO convert4(ProductAttrValueBO productAttrValueBO); - -} diff --git a/归档/moved/product/product-start/src/main/java/cn/iocoder/mall/product/application/convert/ProductSpuConvert.java b/归档/moved/product/product-start/src/main/java/cn/iocoder/mall/product/application/convert/ProductSpuConvert.java deleted file mode 100644 index ce6b00d03..000000000 --- a/归档/moved/product/product-start/src/main/java/cn/iocoder/mall/product/application/convert/ProductSpuConvert.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.iocoder.mall.product.application.convert; - -import cn.iocoder.mall.product.api.bo.ProductSpuBO; -import cn.iocoder.mall.product.api.bo.ProductSpuDetailBO; -import cn.iocoder.mall.product.api.bo.ProductSpuPageBO; -import cn.iocoder.mall.product.application.vo.admins.AdminsProductSpuDetailVO; -import cn.iocoder.mall.product.application.vo.admins.AdminsProductSpuPageVO; -import cn.iocoder.mall.product.application.vo.admins.AdminsProductSpuVO; -import cn.iocoder.mall.product.application.vo.users.UsersProductSpuDetailVO; -import cn.iocoder.mall.product.application.vo.users.UsersProductSpuPageVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mappings; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface ProductSpuConvert { - - ProductSpuConvert INSTANCE = Mappers.getMapper(ProductSpuConvert.class); - - @Mappings({}) - AdminsProductSpuDetailVO convert(ProductSpuDetailBO productSpuDetailBO); - -// @Mappings({}) -// CommonResult convert(CommonResult result); - - @Mappings({}) - AdminsProductSpuPageVO convert2(ProductSpuPageBO result); - - @Mappings({}) - List convert3(List result); - - @Mappings({}) - UsersProductSpuPageVO convert3(ProductSpuPageBO result); - - @Mappings({}) - UsersProductSpuDetailVO convert4(ProductSpuDetailBO result); - -} diff --git a/归档/promotion-service-project/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/enums/activity/PromotionActivityStatusEnum.java b/归档/promotion-service-project/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/enums/activity/PromotionActivityStatusEnum.java deleted file mode 100644 index 885d9d8c5..000000000 --- a/归档/promotion-service-project/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/enums/activity/PromotionActivityStatusEnum.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.mall.promotion.api.enums.activity; - -/** - * 促销活动状态枚举 - */ -public enum PromotionActivityStatusEnum { - - WAIT(10, "未开始"), - RUN(20, "进行中"), - END(30, "已结束"), - /** - * 1. WAIT、RUN、END 可以转换成 INVALID 状态。 - * 2. INVALID 只可以转换成 DELETED 状态。 - */ - INVALID(40, "已撤销"), - DELETED(50, "已删除"), - ; - - /** - * 状态值 - */ - private final Integer value; - /** - * 状态名 - */ - private final String name; - - PromotionActivityStatusEnum(Integer value, String name) { - this.value = value; - this.name = name; - } - - public Integer getValue() { - return value; - } - - public String getName() { - return name; - } - -} diff --git a/归档/promotion-service-project/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/enums/activity/PromotionActivityTypeEnum.java b/归档/promotion-service-project/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/enums/activity/PromotionActivityTypeEnum.java deleted file mode 100644 index a4cbe9fd2..000000000 --- a/归档/promotion-service-project/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/enums/activity/PromotionActivityTypeEnum.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.mall.promotion.api.enums.activity; - -/** - * 促销活动类型枚举 - */ -public enum PromotionActivityTypeEnum { - - TIME_LIMITED_DISCOUNT(1, "限时折扣"), - FULL_PRIVILEGE(2, "满减送"), - ; - - /** - * 类型值 - */ - private final Integer value; - /** - * 类型名 - */ - private final String name; - - PromotionActivityTypeEnum(Integer value, String name) { - this.value = value; - this.name = name; - } - - public Integer getValue() { - return value; - } - - public String getName() { - return name; - } - -} diff --git a/归档/promotion-service-project/promotion-service-app/src/main/java/cn/iocoder/mall/promotionservice/config/AsyncConfiguration.java b/归档/promotion-service-project/promotion-service-app/src/main/java/cn/iocoder/mall/promotionservice/config/AsyncConfiguration.java deleted file mode 100644 index 84ca8a91f..000000000 --- a/归档/promotion-service-project/promotion-service-app/src/main/java/cn/iocoder/mall/promotionservice/config/AsyncConfiguration.java +++ /dev/null @@ -1,9 +0,0 @@ -package cn.iocoder.mall.promotionservice.config; - -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.annotation.EnableAsync; - -@Configuration -@EnableAsync(proxyTargetClass = true) // 开启 Spring Async 异步的功能 -public class AsyncConfiguration { -} diff --git a/归档/promotion-service-project/promotion-service-app/src/main/java/cn/iocoder/mall/promotionservice/config/DatabaseConfiguration.java b/归档/promotion-service-project/promotion-service-app/src/main/java/cn/iocoder/mall/promotionservice/config/DatabaseConfiguration.java deleted file mode 100644 index efded6dc4..000000000 --- a/归档/promotion-service-project/promotion-service-app/src/main/java/cn/iocoder/mall/promotionservice/config/DatabaseConfiguration.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.mall.promotionservice.config; - -import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; -import com.baomidou.mybatisplus.core.injector.ISqlInjector; -import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.transaction.annotation.EnableTransactionManagement; - -@Configuration -@MapperScan("cn.iocoder.mall.promotionservice.dal.mysql.mapper") // 扫描对应的 Mapper 接口 -@EnableTransactionManagement(proxyTargetClass = true) // 启动事务管理。 -public class DatabaseConfiguration { - - // 数据库连接池 Druid - - @Bean - public ISqlInjector sqlInjector() { - return new DefaultSqlInjector(); // MyBatis Plus 逻辑删除 - } - - @Bean - public PaginationInterceptor paginationInterceptor() { - return new PaginationInterceptor(); // MyBatis Plus 分页插件 - } - -} diff --git a/归档/promotion-service-project/promotion-service-app/src/main/java/cn/iocoder/mall/promotionservice/dal/mysql/dataobject/banner/BannerDO.java b/归档/promotion-service-project/promotion-service-app/src/main/java/cn/iocoder/mall/promotionservice/dal/mysql/dataobject/banner/BannerDO.java deleted file mode 100644 index 58da17412..000000000 --- a/归档/promotion-service-project/promotion-service-app/src/main/java/cn/iocoder/mall/promotionservice/dal/mysql/dataobject/banner/BannerDO.java +++ /dev/null @@ -1,51 +0,0 @@ -package cn.iocoder.mall.promotionservice.dal.mysql.dataobject.banner; - -import cn.iocoder.mall.mybatis.core.dataobject.DeletableDO; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; - -/** - * Banner 广告页 - */ -@TableName("banner") -@Data -@EqualsAndHashCode(callSuper = true) -@Accessors(chain = true) -public class BannerDO extends DeletableDO { - - /** - * 编号 - */ - private Integer id; - /** - * 标题 - */ - private String title; - /** - * 跳转链接 - */ - private String url; - /** - * 图片链接 - */ - private String picUrl; - /** - * 排序 - */ - private Integer sort; - /** - * 状态 - * - * {@link cn.iocoder.common.framework.enums.CommonStatusEnum} - */ - private Integer status; - /** - * 备注 - */ - private String memo; - - // TODO 芋艿 点击次数。&& 其他数据相关 - -} diff --git a/归档/promotion-service-project/promotion-service-app/src/main/java/cn/iocoder/mall/promotionservice/dal/mysql/mapper/banner/BannerMapper.java b/归档/promotion-service-project/promotion-service-app/src/main/java/cn/iocoder/mall/promotionservice/dal/mysql/mapper/banner/BannerMapper.java deleted file mode 100644 index 95e1e0465..000000000 --- a/归档/promotion-service-project/promotion-service-app/src/main/java/cn/iocoder/mall/promotionservice/dal/mysql/mapper/banner/BannerMapper.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.mall.promotionservice.dal.mysql.mapper.banner; - -import cn.iocoder.mall.mybatis.core.query.QueryWrapperX; -import cn.iocoder.mall.promotion.api.rpc.banner.dto.BannerListReqDTO; -import cn.iocoder.mall.promotion.api.rpc.banner.dto.BannerPageReqDTO; -import cn.iocoder.mall.promotionservice.dal.mysql.dataobject.banner.BannerDO; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import org.springframework.stereotype.Repository; - -import java.util.List; - -@Repository -public interface BannerMapper extends BaseMapper { - - default List selectList(BannerListReqDTO listReqDTO) { - return selectList(new QueryWrapperX().eqIfPresent("status", listReqDTO.getStatus())); - } - - default IPage selectPage(BannerPageReqDTO pageReqDTO) { - return selectPage(new Page<>(pageReqDTO.getPageNo(), pageReqDTO.getPageSize()), - new QueryWrapperX().likeIfPresent("title", pageReqDTO.getTitle())); - } - -} diff --git a/归档/promotion-service-project/promotion-service-app/src/main/java/cn/iocoder/mall/promotionservice/manager/price/PriceManager.java b/归档/promotion-service-project/promotion-service-app/src/main/java/cn/iocoder/mall/promotionservice/manager/price/PriceManager.java index 00b259777..807c5ff01 100644 --- a/归档/promotion-service-project/promotion-service-app/src/main/java/cn/iocoder/mall/promotionservice/manager/price/PriceManager.java +++ b/归档/promotion-service-project/promotion-service-app/src/main/java/cn/iocoder/mall/promotionservice/manager/price/PriceManager.java @@ -48,26 +48,12 @@ public class PriceManager { private CouponTemplateService couponTemplateService; public PriceProductCalcRespDTO calcProductPrice(PriceProductCalcReqDTO calcReqDTO) { - // TODO 芋艿,补充一些表单校验。例如说,需要传入用户编号。 - // 校验商品都存在 - Map calcProductItemDTOMap = CollectionUtils.convertMap( - calcReqDTO.getItems(), PriceProductCalcReqDTO.Item::getSkuId); - CommonResult> listProductSkusResult = productSkuFeign.listProductSkus( - new ProductSkuListQueryReqDTO().setProductSkuIds(calcProductItemDTOMap.keySet())); - listProductSkusResult.checkError(); - if (calcReqDTO.getItems().size() != listProductSkusResult.getData().size()) { - throw ServiceExceptionUtil.exception(PRICE_PRODUCT_SKU_NOT_EXISTS); - } - // TODO 库存相关 - // 查询促销活动 + // 拼装结果(主要是计算价格) + PriceProductCalcRespDTO calcRespDTO = new PriceProductCalcRespDTO(); + List activityRespDTOs = promotionActivityService.listPromotionActivitiesBySpuIds( CollectionUtils.convertSet(listProductSkusResult.getData(), ProductSkuRespDTO::getSpuId), Collections.singleton(PromotionActivityStatusEnum.RUN.getValue())); - // 拼装结果(主要是计算价格) - PriceProductCalcRespDTO calcRespDTO = new PriceProductCalcRespDTO(); - // 1. 创建初始的每一项的数组 - List calcItemRespDTOs = this.initCalcOrderPriceItems( - listProductSkusResult.getData(), calcProductItemDTOMap); // 2. 计算【限时折扣】促销 this.modifyPriceByTimeLimitDiscount(calcItemRespDTOs, activityRespDTOs); // 3. 计算【满减送】促销 @@ -93,35 +79,6 @@ public class PriceManager { return calcRespDTO; } - private List initCalcOrderPriceItems(List skus, - Map calcProductItemDTOMap) { - // 获得商品分类 Map - CommonResult> listProductSpusResult = productSpuFeign.listProductSpus(CollectionUtils.convertSet(skus, ProductSkuRespDTO::getSpuId)); - listProductSpusResult.checkError(); - Map spuIdCategoryIdMap = CollectionUtils.convertMap(listProductSpusResult.getData(), // SPU 编号与 Category 编号的映射 - ProductSpuRespDTO::getId, ProductSpuRespDTO::getCid); - // 生成商品列表 - List items = new ArrayList<>(); - for (ProductSkuRespDTO sku : skus) { - PriceProductCalcRespDTO.Item item = new PriceProductCalcRespDTO.Item(); - items.add(item); - // 将基本信息,复制到 item 中 - PriceProductCalcReqDTO.Item calcOrderItem = calcProductItemDTOMap.get(sku.getId()); - item.setSpuId(sku.getSpuId()).setSkuId(sku.getId()); - item.setCid(spuIdCategoryIdMap.get(sku.getSpuId())); - item.setSelected(calcOrderItem.getSelected()); - item.setBuyQuantity(calcOrderItem.getQuantity()); - // 计算初始价格 - item.setOriginPrice(sku.getPrice()); - item.setBuyPrice(sku.getPrice()); - item.setPresentPrice(sku.getPrice()); - item.setBuyTotal(sku.getPrice() * calcOrderItem.getQuantity()); - item.setDiscountTotal(0); - item.setPresentTotal(item.getBuyTotal()); - } - return items; - } - private void modifyPriceByTimeLimitDiscount(List items, List activityList) { for (PriceProductCalcRespDTO.Item item : items) { // 获得符合条件的限时折扣 diff --git a/归档/shop-web-app/src/main/java/cn/iocoder/mall/shopweb/service/trade/CartManager.java b/归档/shop-web-app/src/main/java/cn/iocoder/mall/shopweb/service/trade/CartManager.java index 4d1180458..0b62c71b7 100644 --- a/归档/shop-web-app/src/main/java/cn/iocoder/mall/shopweb/service/trade/CartManager.java +++ b/归档/shop-web-app/src/main/java/cn/iocoder/mall/shopweb/service/trade/CartManager.java @@ -34,16 +34,7 @@ public class CartManager { * @return 商品列表 */ public CartDetailVO getCartDetail(Integer userId) { - // 获得购物车的商品 - CommonResult> listCartItemsResult = cartFeign.listCartItems(new CartItemListReqDTO().setUserId(userId)); - listCartItemsResult.checkError(); - // 购物车为空时,构造空的 UsersOrderConfirmCreateVO 返回 - if (CollectionUtils.isEmpty(listCartItemsResult.getData())) { - CartDetailVO result = new CartDetailVO(); - result.setItemGroups(Collections.emptyList()); - result.setFee(new CartDetailVO.Fee(0, 0, 0, 0)); - return result; - } + // 计算商品价格 CommonResult calcProductPriceResult = priceFeign.calcProductPrice(new PriceProductCalcReqDTO().setUserId(userId) .setItems(listCartItemsResult.getData().stream()