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