From 696757da2160c79687e4403bacb7a48a1907bbee Mon Sep 17 00:00:00 2001 From: puzvv <1@> Date: Thu, 18 Dec 2025 17:37:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=BA=86=E8=B4=AD=E7=89=A9?= =?UTF-8?q?=E8=BD=A6=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 5 + .../Common/Constant/MessageConstant.java | 5 + .../Controllers/ShoppingCartController.java | 72 +++++++ .../Mapper/ShoppingCartMapper.java | 11 ++ .../Service/Impl/ShoppingCartServiceImpl.java | 179 ++++++++++++++++++ .../Service/ShoppingCartService.java | 44 +++++ .../pojo/Dto/ShoppingCartDTO.java | 42 ++++ .../pojo/Vo/ShoppingCartVO.java | 20 ++ 8 files changed, 378 insertions(+) create mode 100644 src/main/java/icu/sunway/ai_spring_example/Controllers/ShoppingCartController.java create mode 100644 src/main/java/icu/sunway/ai_spring_example/Mapper/ShoppingCartMapper.java create mode 100644 src/main/java/icu/sunway/ai_spring_example/Service/Impl/ShoppingCartServiceImpl.java create mode 100644 src/main/java/icu/sunway/ai_spring_example/Service/ShoppingCartService.java create mode 100644 src/main/java/icu/sunway/ai_spring_example/pojo/Dto/ShoppingCartDTO.java create mode 100644 src/main/java/icu/sunway/ai_spring_example/pojo/Vo/ShoppingCartVO.java diff --git a/pom.xml b/pom.xml index e5900c9..a6fb3a7 100644 --- a/pom.xml +++ b/pom.xml @@ -84,6 +84,11 @@ io.jsonwebtoken jjwt-jackson 0.11.5 + + + + org.springframework.boot + spring-boot-starter-validation diff --git a/src/main/java/icu/sunway/ai_spring_example/Common/Constant/MessageConstant.java b/src/main/java/icu/sunway/ai_spring_example/Common/Constant/MessageConstant.java index 8fded17..2f34a9e 100644 --- a/src/main/java/icu/sunway/ai_spring_example/Common/Constant/MessageConstant.java +++ b/src/main/java/icu/sunway/ai_spring_example/Common/Constant/MessageConstant.java @@ -19,4 +19,9 @@ public class MessageConstant { public static final String ORDER_NOT_FOUND = "订单不存在"; public static final String PRODUCT_NOT_FOUND = "商品不存在"; public static final String PRODUCT_HAS_CHILDREN = "商品有子商品,不能删除"; + public static final String SKU_NOT_FOUND = "商品没有对应规格"; + public static final String PARAM_ERROR = "参数错误"; + public static final String CART_ITEM_NOT_FOUND = "购物车记录不存在"; + public static final String STOCK_INSUFFICIENT = "库存不足,无法添加"; + public static final String NO_PERMISSION = "没有权限"; } diff --git a/src/main/java/icu/sunway/ai_spring_example/Controllers/ShoppingCartController.java b/src/main/java/icu/sunway/ai_spring_example/Controllers/ShoppingCartController.java new file mode 100644 index 0000000..31320b6 --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Controllers/ShoppingCartController.java @@ -0,0 +1,72 @@ +// ShoppingCartController.java +package icu.sunway.ai_spring_example.Controllers; + +import icu.sunway.ai_spring_example.Common.Response.ResponseEntity; +import icu.sunway.ai_spring_example.Service.ShoppingCartService; +import icu.sunway.ai_spring_example.pojo.Dto.ShoppingCartDTO; +import icu.sunway.ai_spring_example.pojo.Vo.ShoppingCartVO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/cart") +@Slf4j +public class ShoppingCartController { + + @Autowired + private ShoppingCartService shoppingCartService; + + /** + * 添加商品到购物车 + */ + @PostMapping + public ResponseEntity addCart(@Validated @RequestBody ShoppingCartDTO cartDTO) { + log.info("添加商品到购物车: {}", cartDTO); + shoppingCartService.addCart(cartDTO); + return ResponseEntity.success("添加购物车成功"); + } + + /** + * 修改购物车商品数量 + */ + @PutMapping("/count") + public ResponseEntity updateCount(@Validated @RequestBody ShoppingCartDTO cartDTO) { + log.info("修改购物车商品数量: {}", cartDTO); + shoppingCartService.updateCount(cartDTO); + return ResponseEntity.success("数量更新成功"); + } + + /** + * 删除购物车商品 + */ + @DeleteMapping("/{id}") + public ResponseEntity deleteCart(@PathVariable Long id, @RequestParam Long userId) { + log.info("删除购物车商品: id={}, userId={}", id, userId); + shoppingCartService.deleteCart(id, userId); + return ResponseEntity.success("删除成功"); + } + + /** + * 修改购物车商品勾选状态 + */ + @PutMapping("/checked") + public ResponseEntity updateChecked(@Validated @RequestBody ShoppingCartDTO cartDTO) { + log.info("修改购物车商品勾选状态: {}", cartDTO); + shoppingCartService.updateChecked(cartDTO); + return ResponseEntity.success("勾选状态更新成功"); + } + + /** + * 查询用户购物车列表 + */ + @GetMapping + public ResponseEntity> getUserCartList(@RequestParam Long userId) { + log.info("查询用户购物车列表: userId={}", userId); + List cartList = shoppingCartService.getUserCartList(userId); + return ResponseEntity.success(cartList); + } +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/Mapper/ShoppingCartMapper.java b/src/main/java/icu/sunway/ai_spring_example/Mapper/ShoppingCartMapper.java new file mode 100644 index 0000000..80cd810 --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Mapper/ShoppingCartMapper.java @@ -0,0 +1,11 @@ +// ShoppingCartMapper.java +package icu.sunway.ai_spring_example.Mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import icu.sunway.ai_spring_example.pojo.Entity.ShoppingCart; +import org.apache.ibatis.annotations.Mapper; + + +@Mapper +public interface ShoppingCartMapper extends BaseMapper { +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/Service/Impl/ShoppingCartServiceImpl.java b/src/main/java/icu/sunway/ai_spring_example/Service/Impl/ShoppingCartServiceImpl.java new file mode 100644 index 0000000..a63348f --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Service/Impl/ShoppingCartServiceImpl.java @@ -0,0 +1,179 @@ +// ShoppingCartServiceImpl.java +package icu.sunway.ai_spring_example.Service.Impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import icu.sunway.ai_spring_example.Common.Exception.BusinessException; +import icu.sunway.ai_spring_example.Common.Constant.MessageConstant; +import icu.sunway.ai_spring_example.Mapper.ProductMapper; +import icu.sunway.ai_spring_example.Mapper.ShoppingCartMapper; +import icu.sunway.ai_spring_example.Mapper.ProductSkuMapper; +import icu.sunway.ai_spring_example.Service.ShoppingCartService; +import icu.sunway.ai_spring_example.pojo.Dto.ShoppingCartDTO; +import icu.sunway.ai_spring_example.pojo.Entity.Product; +import icu.sunway.ai_spring_example.pojo.Entity.ShoppingCart; +import icu.sunway.ai_spring_example.pojo.Entity.ProductSku; +import icu.sunway.ai_spring_example.pojo.Vo.ShoppingCartVO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +@Service +@Slf4j +public class ShoppingCartServiceImpl extends ServiceImpl implements ShoppingCartService { + + @Autowired + private ShoppingCartMapper shoppingCartMapper; + + @Autowired + private ProductSkuMapper productSkuMapper; + + @Autowired + private ProductMapper productMapper; + + @Override + @Transactional + public void addCart(ShoppingCartDTO cartDTO) { + // 检查SKU是否存在 + ProductSku sku = productSkuMapper.selectById(cartDTO.getSkuId()); + if (sku == null) { + throw new BusinessException(MessageConstant.SKU_NOT_FOUND); + } + + // 检查购物车中是否已有该商品 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(ShoppingCart::getUserId, cartDTO.getUserId()) + .eq(ShoppingCart::getProductId, cartDTO.getProductId()) + .eq(ShoppingCart::getSkuId, cartDTO.getSkuId()) + .eq(ShoppingCart::getIsDeleted, 0); + + ShoppingCart existingCart = shoppingCartMapper.selectOne(queryWrapper); + + if (existingCart != null) { + // 已存在则更新数量 + existingCart.setCount(existingCart.getCount() + cartDTO.getCount()); + existingCart.setUpdateTime(LocalDateTime.now()); + shoppingCartMapper.updateById(existingCart); + } else { + // 不存在则新增 + ShoppingCart shoppingCart = new ShoppingCart(); + BeanUtils.copyProperties(cartDTO, shoppingCart); + // 设置默认勾选状态 + if (shoppingCart.getChecked() == null) { + shoppingCart.setChecked(1); // 默认勾选 + } + shoppingCartMapper.insert(shoppingCart); + } + } + + @Override + @Transactional + public void updateCount(ShoppingCartDTO cartDTO) { + // 验证参数 + if (cartDTO.getId() == null || cartDTO.getCount() == null || cartDTO.getCount() <= 0) { + throw new BusinessException(MessageConstant.PARAM_ERROR); + } + + // 检查购物车记录是否存在 + ShoppingCart cart = shoppingCartMapper.selectById(cartDTO.getId()); + if (cart == null || cart.getIsDeleted() == 1) { + throw new BusinessException(MessageConstant.CART_ITEM_NOT_FOUND); + } + + // 检查数量是否超过库存 + ProductSku sku = productSkuMapper.selectById(cart.getSkuId()); + if (cartDTO.getCount() > sku.getStock()) { + throw new BusinessException(MessageConstant.STOCK_INSUFFICIENT); + } + + // 更新数量 + cart.setCount(cartDTO.getCount()); + cart.setUpdateTime(LocalDateTime.now()); + shoppingCartMapper.updateById(cart); + } + + @Override + @Transactional + public void deleteCart(Long id, Long userId) { + // 验证参数 + if (id == null || userId == null) { + throw new BusinessException(MessageConstant.PARAM_ERROR); + } + + // 检查购物车记录是否属于当前用户 + ShoppingCart cart = shoppingCartMapper.selectById(id); + if (cart == null || cart.getIsDeleted() == 1) { + throw new BusinessException(MessageConstant.CART_ITEM_NOT_FOUND); + } + if (!cart.getUserId().equals(userId)) { + throw new BusinessException(MessageConstant.NO_PERMISSION); + } + + // 逻辑删除 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("id", id); + shoppingCartMapper.delete(queryWrapper); + } + + @Override + @Transactional + public void updateChecked(ShoppingCartDTO cartDTO) { + // 验证参数 + if (cartDTO.getId() == null || cartDTO.getChecked() == null) { + throw new BusinessException(MessageConstant.PARAM_ERROR); + } + + // 检查购物车记录是否存在 + ShoppingCart cart = shoppingCartMapper.selectById(cartDTO.getId()); + if (cart == null || cart.getIsDeleted() == 1) { + throw new BusinessException(MessageConstant.CART_ITEM_NOT_FOUND); + } + + // 更新勾选状态 + cart.setChecked(cartDTO.getChecked()); + cart.setUpdateTime(LocalDateTime.now()); + shoppingCartMapper.updateById(cart); + } + + @Override + public List getUserCartList(Long userId) { + if (userId == null) { + throw new BusinessException(MessageConstant.PARAM_ERROR); + } + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("user_id", userId); + List ShoppingCartList = shoppingCartMapper.selectList(queryWrapper); + // 将 ShoppingCart 转换为 ShoppingCartVO + List cartVOList = new ArrayList<>(); + for (ShoppingCart cart : ShoppingCartList) { + ShoppingCartVO cartVO = new ShoppingCartVO(); + // 复制相同属性 + BeanUtils.copyProperties(cart, cartVO); + + //设置productName、productImage、price属性 + QueryWrapper productQueryWrapper = new QueryWrapper<>(); + productQueryWrapper.eq("id", cart.getProductId()); + Product product = productMapper.selectOne(productQueryWrapper); + cartVO.setProductName(product.getName()); + cartVO.setProductImage(product.getMainImage()); + cartVO.setPrice(product.getPrice()); + + //设置skuName、specJson属性 + QueryWrapper skuQueryWrapper = new QueryWrapper<>(); + skuQueryWrapper.eq("id", cart.getSkuId()); + ProductSku sku = productSkuMapper.selectOne(skuQueryWrapper); + cartVO.setSkuName(sku.getSkuName()); + cartVO.setSpecJson(sku.getSpecJson()); + + cartVOList.add(cartVO); + } + return cartVOList; + } +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/Service/ShoppingCartService.java b/src/main/java/icu/sunway/ai_spring_example/Service/ShoppingCartService.java new file mode 100644 index 0000000..a726b82 --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/Service/ShoppingCartService.java @@ -0,0 +1,44 @@ +// ShoppingCartService.java +package icu.sunway.ai_spring_example.Service; + +import com.baomidou.mybatisplus.extension.service.IService; +import icu.sunway.ai_spring_example.pojo.Dto.ShoppingCartDTO; +import icu.sunway.ai_spring_example.pojo.Entity.ShoppingCart; +import icu.sunway.ai_spring_example.pojo.Vo.ShoppingCartVO; + +import java.util.List; + +public interface ShoppingCartService extends IService { + + /** + * 添加商品到购物车 + * @param cartDTO 购物车信息 + */ + void addCart(ShoppingCartDTO cartDTO); + + /** + * 修改购物车商品数量 + * @param cartDTO 购物车信息 + */ + void updateCount(ShoppingCartDTO cartDTO); + + /** + * 删除购物车商品 + * @param id 购物车ID + * @param userId 用户ID + */ + void deleteCart(Long id, Long userId); + + /** + * 修改购物车商品勾选状态 + * @param cartDTO 购物车信息 + */ + void updateChecked(ShoppingCartDTO cartDTO); + + /** + * 查询用户购物车列表 + * @param userId 用户ID + * @return 购物车列表 + */ + List getUserCartList(Long userId); +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/pojo/Dto/ShoppingCartDTO.java b/src/main/java/icu/sunway/ai_spring_example/pojo/Dto/ShoppingCartDTO.java new file mode 100644 index 0000000..075f07e --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/pojo/Dto/ShoppingCartDTO.java @@ -0,0 +1,42 @@ +// ShoppingCartDTO.java +package icu.sunway.ai_spring_example.pojo.Dto; + +import lombok.Data; + +import jakarta.validation.constraints.NotNull; + +@Data +public class ShoppingCartDTO { + /** + * 购物车ID(修改/删除时使用) + */ + private Long id; + + /** + * 用户ID + */ + @NotNull(message = "用户ID不能为空") + private Long userId; + + /** + * 商品ID + */ + @NotNull(message = "商品ID不能为空") + private Long productId; + + /** + * SKU ID + */ + @NotNull(message = "SKU ID不能为空") + private Long skuId; + + /** + * 数量 + */ + private Integer count; + + /** + * 勾选状态 0-未勾选 1-已勾选 + */ + private Integer checked; +} \ No newline at end of file diff --git a/src/main/java/icu/sunway/ai_spring_example/pojo/Vo/ShoppingCartVO.java b/src/main/java/icu/sunway/ai_spring_example/pojo/Vo/ShoppingCartVO.java new file mode 100644 index 0000000..6784a2c --- /dev/null +++ b/src/main/java/icu/sunway/ai_spring_example/pojo/Vo/ShoppingCartVO.java @@ -0,0 +1,20 @@ +// ShoppingCartVO.java +package icu.sunway.ai_spring_example.pojo.Vo; + +import lombok.Data; +import java.math.BigDecimal; + +@Data +public class ShoppingCartVO { + private Long id; + private Long userId; + private Long productId; + private Long skuId; + private Integer count; + private Integer checked; + private String productName; + private String productImage; + private String skuName; + private BigDecimal price; + private String specJson; +} \ No newline at end of file