p-honggang.li
5 天以前 ac918503bb5e8fad007348e7e39ba7275b75f334
src/main/java/com/webmanage/service/impl/CartServiceImpl.java
@@ -18,6 +18,7 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
@@ -55,7 +56,7 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addToCart(Long userId, Long unitId, CartItemDTO cartItemDTO) {
    public boolean addToCart(String userId, String unitId, CartItemDTO cartItemDTO) {
        try {
            // 验证商品定价是否存在
            ProductPricing pricing = productPricingMapper.selectById(cartItemDTO.getPricingId());
@@ -64,8 +65,8 @@
            }
            // 构建购物车key
            String cartKey = buildCartKey(userId, unitId);
            String cartItemKey = buildCartItemKey(userId, unitId, cartItemDTO.getPricingId());
            String cartKey = buildCartKey(userId,unitId, cartItemDTO.getProductId());
            String cartItemKey = buildCartItemKey(userId, unitId, cartItemDTO.getProductId(),cartItemDTO.getPricingId());
            // 检查商品是否已在购物车中
            CartItemVO existingItem = (CartItemVO) redisTemplate.opsForValue().get(cartItemKey);
@@ -90,7 +91,7 @@
            redisTemplate.opsForValue().set(cartItemKey, existingItem, (cartProperties.getExpireDays() != null ? cartProperties.getExpireDays() : CART_EXPIRE_DAYS), TimeUnit.DAYS);
            // 更新购物车商品列表
            updateCartItemList(userId, unitId, cartItemDTO.getPricingId(), true);
            updateCartItemList(userId, unitId, cartItemDTO.getProductId(), cartItemDTO.getPricingId(), true);
            // 设置购物车过期时间
            redisTemplate.expire(cartKey, (cartProperties.getExpireDays() != null ? cartProperties.getExpireDays() : CART_EXPIRE_DAYS), TimeUnit.DAYS);
@@ -110,19 +111,19 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeFromCart(Long userId, Long unitId, Long pricingId) {
    public boolean removeFromCart(String userId, String unitId, String productId, Long pricingId) {
        try {
            String cartItemKey = buildCartItemKey(userId, unitId, pricingId);
            String cartItemKey = buildCartItemKey(userId, unitId, productId, pricingId);
            // 从Redis中删除商品项
            Boolean removed = redisTemplate.delete(cartItemKey);
            if (Boolean.TRUE.equals(removed)) {
                // 更新购物车商品列表
                updateCartItemList(userId, unitId, pricingId, false);
                updateCartItemList(userId, unitId, productId, pricingId, false);
                // 异步从数据库中删除(根据配置)
                if (Boolean.TRUE.equals(cartProperties.getEnablePersistence()) && "realtime".equalsIgnoreCase(cartProperties.getSyncStrategy())) {
                    cartPersistenceService.remove(userId, unitId, pricingId);
                    cartPersistenceService.remove(userId, unitId, productId,pricingId);
                }
                log.info("用户{}成功从购物车移除商品{}", userId, pricingId);
@@ -137,13 +138,13 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCartItemQuantity(Long userId, Long unitId, Long pricingId, Integer quantity) {
    public boolean updateCartItemQuantity(String userId, String unitId, String productId, Long pricingId, Integer quantity) {
        try {
            if (quantity <= 0) {
                return removeFromCart(userId, unitId, pricingId);
                return removeFromCart(userId, unitId, productId, pricingId);
            }
            String cartItemKey = buildCartItemKey(userId, unitId, pricingId);
            String cartItemKey = buildCartItemKey(userId, unitId, productId, pricingId);
            CartItemVO cartItem = (CartItemVO) redisTemplate.opsForValue().get(cartItemKey);
            if (cartItem == null) {
                throw new BusinessException("购物车商品不存在");
@@ -169,16 +170,48 @@
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean clearCart(Long userId, Long unitId) {
    public boolean updateCartItemDuration(String userId, String unitId, String productId, Long pricingId, Integer duration) {
        try {
            String cartKey = buildCartKey(userId, unitId);
            List<Long> pricingIds = getCartItemPricingIds(userId, unitId);
            String cartItemKey = buildCartItemKey(userId, unitId, productId, pricingId);
            CartItemVO cartItem = (CartItemVO) redisTemplate.opsForValue().get(cartItemKey);
            if (cartItem == null) {
                throw new BusinessException("购物车商品不存在");
            }
            cartItem.setDuration(duration);
            cartItem.setUpdateTime(LocalDateTime.now());
            // 更新到Redis
            redisTemplate.opsForValue().set(cartItemKey, cartItem, (cartProperties.getExpireDays() != null ? cartProperties.getExpireDays() : CART_EXPIRE_DAYS), TimeUnit.DAYS);
            // 异步持久化到数据库(根据配置)
            if (Boolean.TRUE.equals(cartProperties.getEnablePersistence()) && "realtime".equalsIgnoreCase(cartProperties.getSyncStrategy())) {
                cartPersistenceService.saveOrUpdate(userId, unitId, cartItem);
            }
            log.info("用户{}成功更新购物车商品{}年限为{}", userId, pricingId, duration);
            return true;
        } catch (Exception e) {
            log.error("更新购物车商品数量失败", e);
            throw new BusinessException("更新购物车商品数量失败:" + e.getMessage());
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean clearCart(String userId, String unitId, String productId) {
        try {
            String cartKey = buildCartKey(userId, unitId, productId);
            List<Long> pricingIds = getCartItemPricingIds(userId, unitId, productId);
            // 删除所有商品项
            for (Long pricingId : pricingIds) {
                String cartItemKey = buildCartItemKey(userId, unitId, pricingId);
                String cartItemKey = buildCartItemKey(userId, unitId, productId,pricingId);
                redisTemplate.delete(cartItemKey);
            }
@@ -187,7 +220,7 @@
            // 异步清空数据库中的购物车数据(根据配置)
            if (Boolean.TRUE.equals(cartProperties.getEnablePersistence()) && "realtime".equalsIgnoreCase(cartProperties.getSyncStrategy())) {
                cartPersistenceService.clear(userId, unitId);
                cartPersistenceService.clear(userId, unitId, productId);
            }
            log.info("用户{}成功清空购物车", userId);
@@ -199,13 +232,14 @@
    }
    @Override
    public CartVO getCart(Long userId, Long unitId) {
    public CartVO getCart(String userId, String unitId, String productId) {
        try {
            CartVO cartVO = new CartVO();
            cartVO.setUserId(userId);
            cartVO.setUnitId(unitId);
            List<CartItemVO> items = getCartItems(userId, unitId);
            if (StringUtils.hasText(unitId)){
                cartVO.setUnitId(unitId);
            }
            List<CartItemVO> items = getCartItems(userId, unitId, productId);
            cartVO.setItems(items);
            // 计算总数量和总金额
@@ -226,40 +260,40 @@
    }
    @Override
    public List<CartItemVO> getCartItems(Long userId, Long unitId) {
    public List<CartItemVO> getCartItems(String userId, String unitId,String productId) {
        try {
            // 优先从Redis获取
            List<CartItemVO> items = getCartItemsFromRedis(userId, unitId);
            List<CartItemVO> items = getCartItemsFromRedis(userId, unitId,productId);
            if (items != null && !items.isEmpty()) {
                return items;
            }
            // Redis中没有数据,从数据库加载
            log.info("Redis中无购物车数据,从数据库加载用户{}的购物车", userId);
            return loadCartFromDatabase(userId, unitId) ? getCartItemsFromRedis(userId, unitId) : new ArrayList<>();
            return loadCartFromDatabase(userId, unitId, productId) ? getCartItemsFromRedis(userId, unitId, productId) : new ArrayList<>();
        } catch (Exception e) {
            log.error("获取购物车商品列表失败", e);
            // 降级到数据库查询
            return getCartItemsFromDatabase(userId, unitId);
            return getCartItemsFromDatabase(userId, unitId, productId);
        }
    }
    @Override
    public boolean checkCartItemStock(Long userId, Long unitId, Long pricingId) {
    public boolean checkCartItemStock(String userId, String unitId, Long pricingId) {
        // TODO: 实现库存检查逻辑
        return true;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchRemoveFromCart(Long userId, Long unitId, List<Long> pricingIds) {
    public boolean batchRemoveFromCart(String userId, String unitId, String productId,List<Long> pricingIds) {
        try {
            if (CollectionUtils.isEmpty(pricingIds)) {
                return true;
            }
            for (Long pricingId : pricingIds) {
                removeFromCart(userId, unitId, pricingId);
                removeFromCart(userId, unitId, productId,pricingId);
            }
            return true;
@@ -270,17 +304,17 @@
    }
    @Override
    public Integer getCartItemCount(Long userId, Long unitId) {
    public Integer getCartItemCount(String userId, String unitId, String productId) {
        try {
            // 优先从Redis获取
            String cartKey = buildCartKey(userId, unitId);
            String cartKey = buildCartKey(userId, unitId, productId);
            List<Long> pricingIds = (List<Long>) redisTemplate.opsForValue().get(cartKey);
            if (pricingIds != null) {
                return pricingIds.size();
            }
            // 从数据库获取
            return cartMapper.countByUserIdAndUnitId(userId, unitId);
            return cartMapper.countByUserIdAndUnitId(userId, unitId, productId);
        } catch (Exception e) {
            log.error("获取购物车商品数量失败", e);
            return 0;
@@ -288,19 +322,19 @@
    }
    @Override
    public boolean loadCartFromDatabase(Long userId, Long unitId) {
    public boolean loadCartFromDatabase(String userId, String unitId, String productId) {
        try {
            List<Cart> cartItems = cartMapper.selectByUserIdAndUnitId(userId, unitId);
            List<Cart> cartItems = cartMapper.selectByUserIdAndUnitId(userId, unitId, productId);
            if (CollectionUtils.isEmpty(cartItems)) {
                return false;
            }
            String cartKey = buildCartKey(userId, unitId);
            String cartKey = buildCartKey(userId, unitId, productId);
            List<Long> pricingIds = new ArrayList<>();
            for (Cart cartItem : cartItems) {
                CartItemVO itemVO = convertCartToCartItemVO(cartItem);
                String cartItemKey = buildCartItemKey(userId, unitId, cartItem.getPricingId());
                String cartItemKey = buildCartItemKey(userId, unitId,cartItem.getProductId(), cartItem.getPricingId());
                // 保存到Redis
                redisTemplate.opsForValue().set(cartItemKey, itemVO, CART_EXPIRE_DAYS, TimeUnit.DAYS);
@@ -319,19 +353,19 @@
    }
    @Override
    public boolean syncCartToDatabase(Long userId, Long unitId) {
    public boolean syncCartToDatabase(String userId, String unitId, String productId) {
        try {
            List<CartItemVO> redisItems = getCartItemsFromRedis(userId, unitId);
            List<CartItemVO> redisItems = getCartItemsFromRedis(userId, unitId, productId);
            if (CollectionUtils.isEmpty(redisItems)) {
                return true;
            }
            // 清空数据库中的购物车数据
            clearCartFromDatabase(userId, unitId);
            clearCartFromDatabase(userId, unitId, productId);
            // 同步Redis数据到数据库
            for (CartItemVO item : redisItems) {
                syncCartItemToDatabase(userId, unitId, item);
                syncCartItemToDatabase(userId, unitId,productId, item);
            }
            log.info("成功同步Redis购物车数据到数据库,用户{}", userId);
@@ -343,10 +377,10 @@
    }
    @Override
    public boolean checkCartConsistency(Long userId, Long unitId) {
    public boolean checkCartConsistency(String userId, String unitId, String productId) {
        try {
            List<CartItemVO> redisItems = getCartItemsFromRedis(userId, unitId);
            List<Cart> dbItems = cartMapper.selectByUserIdAndUnitId(userId, unitId);
            List<CartItemVO> redisItems = getCartItemsFromRedis(userId, unitId, productId);
            List<Cart> dbItems = cartMapper.selectByUserIdAndUnitId(userId, unitId, productId);
            if (redisItems.size() != dbItems.size()) {
                log.warn("购物车数据不一致:Redis数量{},数据库数量{}", redisItems.size(), dbItems.size());
@@ -378,16 +412,22 @@
    // ==================== 私有方法 ====================
    private String buildCartKey(Long userId, Long unitId) {
        return CART_KEY_PREFIX + userId + ":" + unitId;
    private String buildCartKey(String userId, String unitId,String productId) {
        if(StringUtils.hasText(unitId)){
            return CART_KEY_PREFIX + userId + ":" + unitId + ":" + productId;
        }
        return CART_KEY_PREFIX + userId + ":" + productId;
    }
    private String buildCartItemKey(Long userId, Long unitId, Long pricingId) {
        return CART_ITEM_KEY_PREFIX + userId + ":" + unitId + ":" + pricingId;
    private String buildCartItemKey(String userId, String unitId,String productId, Long pricingId) {
        if(StringUtils.hasText(unitId)){
            return CART_ITEM_KEY_PREFIX + userId + ":" + unitId + ":" + productId + ":" + pricingId;
        }
        return CART_ITEM_KEY_PREFIX + userId + ":" + productId + ":" + pricingId;
    }
    private void updateCartItemList(Long userId, Long unitId, Long pricingId, boolean add) {
        String cartKey = buildCartKey(userId, unitId);
    private void updateCartItemList(String userId, String unitId,String productId ,Long pricingId, boolean add) {
        String cartKey = buildCartKey(userId, unitId, productId);
        List<Long> pricingIds = (List<Long>) redisTemplate.opsForValue().get(cartKey);
        if (pricingIds == null) {
@@ -403,15 +443,15 @@
        redisTemplate.opsForValue().set(cartKey, pricingIds, CART_EXPIRE_DAYS, TimeUnit.DAYS);
    }
    private List<Long> getCartItemPricingIds(Long userId, Long unitId) {
        String cartKey = buildCartKey(userId, unitId);
    private List<Long> getCartItemPricingIds(String userId, String unitId, String productId) {
        String cartKey = buildCartKey(userId, unitId, productId);
        List<Long> pricingIds = (List<Long>) redisTemplate.opsForValue().get(cartKey);
        return pricingIds != null ? pricingIds : new ArrayList<>();
    }
    private List<CartItemVO> getCartItemsFromRedis(Long userId, Long unitId) {
    private List<CartItemVO> getCartItemsFromRedis(String userId, String unitId, String productId) {
        try {
            String cartKey = buildCartKey(userId, unitId);
            String cartKey = buildCartKey(userId, unitId, productId);
            List<Long> pricingIds = (List<Long>) redisTemplate.opsForValue().get(cartKey);
            if (CollectionUtils.isEmpty(pricingIds)) {
@@ -420,7 +460,7 @@
            List<CartItemVO> items = new ArrayList<>();
            for (Long pricingId : pricingIds) {
                String cartItemKey = buildCartItemKey(userId, unitId, pricingId);
                String cartItemKey = buildCartItemKey(userId, unitId, productId,pricingId);
                CartItemVO item = (CartItemVO) redisTemplate.opsForValue().get(cartItemKey);
                if (item != null) {
                    items.add(item);
@@ -434,9 +474,9 @@
        }
    }
    
    private List<CartItemVO> getCartItemsFromDatabase(Long userId, Long unitId) {
    private List<CartItemVO> getCartItemsFromDatabase(String userId, String unitId, String productId) {
        try {
            List<Cart> cartItems = cartMapper.selectByUserIdAndUnitId(userId, unitId);
            List<Cart> cartItems = cartMapper.selectByUserIdAndUnitId(userId, unitId, productId);
            List<CartItemVO> items = new ArrayList<>();
            
            for (Cart cartItem : cartItems) {
@@ -456,7 +496,7 @@
        return itemVO;
    }
    
    private void syncCartItemToDatabase(Long userId, Long unitId, CartItemVO item) {
    private void syncCartItemToDatabase(String userId, String unitId, String productId,CartItemVO item) {
        try {
            Cart cart = new Cart();
            BeanUtils.copyProperties(item, cart);
@@ -465,7 +505,7 @@
            cart.setUpdateTime(LocalDateTime.now());
            
            // 检查是否已存在
            Cart existingCart = cartMapper.selectByUserIdUnitIdAndPricingId(userId, unitId, item.getPricingId());
            Cart existingCart = cartMapper.selectByUserIdUnitIdAndPricingId(userId, unitId, productId,item.getPricingId());
            if (existingCart != null) {
                // 更新
                cart.setId(existingCart.getId());
@@ -480,9 +520,9 @@
        }
    }
    
    private void removeCartItemFromDatabase(Long userId, Long unitId, Long pricingId) {
    private void removeCartItemFromDatabase(String userId, String unitId, String productId, Long pricingId) {
        try {
            Cart existingCart = cartMapper.selectByUserIdUnitIdAndPricingId(userId, unitId, pricingId);
            Cart existingCart = cartMapper.selectByUserIdUnitIdAndPricingId(userId, unitId, productId,pricingId);
            if (existingCart != null) {
                cartMapper.deleteByCustomerCondition(existingCart.getId());
            }
@@ -491,10 +531,10 @@
        }
    }
    
    private void clearCartFromDatabase(Long userId, Long unitId) {
    private void clearCartFromDatabase(String userId, String unitId, String productId) {
        try {
            // 使用逻辑删除
            List<Cart> cartItems = cartMapper.selectByUserIdAndUnitId(userId, unitId);
            List<Cart> cartItems = cartMapper.selectByUserIdAndUnitId(userId, unitId, productId);
            for (Cart item : cartItems) {
                cartMapper.deleteById(item.getId());
            }