currentData;
+
+}
diff --git a/nla-common/src/test/java/tools/MyBatisPlusGenerator.java b/nla-common/src/test/java/tools/MyBatisPlusGenerator.java
index 30f3ce6..2674bc3 100644
--- a/nla-common/src/test/java/tools/MyBatisPlusGenerator.java
+++ b/nla-common/src/test/java/tools/MyBatisPlusGenerator.java
@@ -22,7 +22,7 @@ public class MyBatisPlusGenerator {
// 作者
.setAuthor("YJs")
// ⽣成路径,最好使⽤绝对路径,window路径是不⼀样的
- .setOutputDir("D:\\workspace\\2024\\nla-shop\\nla-coupon-service\\src\\main\\java")
+ .setOutputDir("D:\\workspace\\2024\\nla-shop\\nla-product-service\\src\\main\\java")
// ⽂件覆盖
.setFileOverride(true)
// 主键策略
@@ -43,7 +43,7 @@ public class MyBatisPlusGenerator {
// 设置数据库类型
dsConfig.setDbType(DbType.MYSQL)
.setDriverName("com.mysql.cj.jdbc.Driver")
- .setUrl("jdbc:mysql://117.72.43.105:3306/p_nla_coupon?useSSL=false")
+ .setUrl("jdbc:mysql://117.72.43.105:3306/p_nla_product?useSSL=false")
.setUsername("root")
.setPassword("Yuan625621105.");
@@ -58,11 +58,11 @@ public class MyBatisPlusGenerator {
//使⽤restcontroller注解
.setRestControllerStyle(true)
// ⽣成的表, ⽀持多表⼀起⽣成,以数组形式填写
- .setInclude("coupon","coupon_record");
+ .setInclude("product","banner");
//4. 包名策略配置
PackageConfig pkConfig = new PackageConfig();
- pkConfig.setParent("cn.nla.coupon")
+ pkConfig.setParent("cn.nla.product")
.setMapper("mapper")
.setService("service")
.setController("controller")
diff --git a/nla-coupon-service/src/main/java/cn/nla/coupon/controller/CouponController.java b/nla-coupon-service/src/main/java/cn/nla/coupon/controller/CouponController.java
index 961e385..adce067 100644
--- a/nla-coupon-service/src/main/java/cn/nla/coupon/controller/CouponController.java
+++ b/nla-coupon-service/src/main/java/cn/nla/coupon/controller/CouponController.java
@@ -2,6 +2,7 @@ package cn.nla.coupon.controller;
import cn.nla.common.enums.CouponCategoryEnum;
import cn.nla.common.util.JsonData;
+import cn.nla.coupon.model.request.NewUserCouponRequest;
import cn.nla.coupon.service.CouponService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -41,4 +42,13 @@ public class CouponController {
public JsonData addPromotionCoupon(@ApiParam(value = "优惠券id", required = true) @PathVariable("coupon_id") long couponId) {
return couponService.addCoupon(couponId, CouponCategoryEnum.PROMOTION);
}
+ /**
+ * 新用户注册发放优惠券接口
+ */
+ @ApiOperation("RPC-新用户注册接口")
+ @PostMapping("/new_user_coupon")
+ public JsonData addNewUserCoupon( @ApiParam("用户对象") @RequestBody NewUserCouponRequest newUserCouponRequest ){
+ return couponService.initNewUserCoupon(newUserCouponRequest);
+ }
+
}
diff --git a/nla-coupon-service/src/main/java/cn/nla/coupon/controller/CouponRecordController.java b/nla-coupon-service/src/main/java/cn/nla/coupon/controller/CouponRecordController.java
index 16f929c..3e83b76 100644
--- a/nla-coupon-service/src/main/java/cn/nla/coupon/controller/CouponRecordController.java
+++ b/nla-coupon-service/src/main/java/cn/nla/coupon/controller/CouponRecordController.java
@@ -1,9 +1,15 @@
package cn.nla.coupon.controller;
+import cn.nla.common.enums.BizCodeEnum;
+import cn.nla.common.util.JsonData;
+import cn.nla.coupon.model.VO.CouponRecordVO;
+import cn.nla.coupon.service.CouponRecordService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import org.springframework.web.bind.annotation.*;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import org.springframework.web.bind.annotation.RestController;
+import javax.annotation.Resource;
/**
*
@@ -13,9 +19,26 @@ import org.springframework.web.bind.annotation.RestController;
* @author YJs
* @since 2024-08-08
*/
+@Api(tags = "优惠券领劵记录控制器")
@RestController
-@RequestMapping("/couponRecordEntity")
+@RequestMapping("/cop/couponRecord/v1")
public class CouponRecordController {
+ @Resource
+ private CouponRecordService couponRecordService;
+
+ @ApiOperation("分页查询个人优惠券")
+ @GetMapping("page")
+ public JsonData page(@ApiParam(value = "当前页") @RequestParam(value = "page", defaultValue = "1") int page,
+ @ApiParam(value = "每页显示多少条") @RequestParam(value = "size", defaultValue = "10") int size) {
+ return JsonData.buildSuccess(couponRecordService.page(page, size));
+ }
+
+ @ApiOperation("查询优惠券记录详情")
+ @GetMapping("detail/{record_id}")
+ public JsonData getCouponRecordDetail(@ApiParam(value = "记录id") @PathVariable("record_id") long recordId) {
+ CouponRecordVO couponRecordVO = couponRecordService.findById(recordId);
+ return couponRecordVO == null ? JsonData.buildResult(BizCodeEnum.COUPON_NO_EXITS) : JsonData.buildSuccess(couponRecordVO);
+ }
}
diff --git a/nla-coupon-service/src/main/java/cn/nla/coupon/model/VO/CouponRecordVO.java b/nla-coupon-service/src/main/java/cn/nla/coupon/model/VO/CouponRecordVO.java
new file mode 100644
index 0000000..941dac0
--- /dev/null
+++ b/nla-coupon-service/src/main/java/cn/nla/coupon/model/VO/CouponRecordVO.java
@@ -0,0 +1,67 @@
+package cn.nla.coupon.model.VO;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 个人领劵信息
+ */
+@Data
+public class CouponRecordVO {
+ private Long id;
+ /**
+ * 优惠券id
+ */
+ @JsonProperty("coupon_id")
+ private Long couponId;
+ /**
+ * 使用状态 可用 NEW,已使用USED,过期 EXPIRED;
+ */
+ @JsonProperty("use_state")
+ private String useState;
+ /**
+ * 用户id
+ */
+ @JsonProperty("user_id")
+ private Long userId;
+ /**
+ * 用户昵称
+ */
+ @JsonProperty("user_name")
+ private String userName;
+ /**
+ * 优惠券标题
+ */
+ @JsonProperty("coupon_title")
+ private String couponTitle;
+ /**
+ * 开始时间
+ */
+ @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss", locale = "zh", timezone = "GMT+8")
+ @JsonProperty("start_time")
+ private Date startTime;
+ /**
+ * 结束时间
+ */
+ @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss", locale = "zh", timezone = "GMT+8")
+ @JsonProperty("end_time")
+ private Date endTime;
+ /**
+ * 订单id
+ */
+ @JsonProperty("order_id")
+ private Long orderId;
+ /**
+ * 抵扣价格
+ */
+ private BigDecimal price;
+ /**
+ * 满多少才可以使用
+ */
+ @JsonProperty("condition_price")
+ private BigDecimal conditionPrice;
+}
diff --git a/nla-coupon-service/src/main/java/cn/nla/coupon/model/request/NewUserCouponRequest.java b/nla-coupon-service/src/main/java/cn/nla/coupon/model/request/NewUserCouponRequest.java
new file mode 100644
index 0000000..1c19cca
--- /dev/null
+++ b/nla-coupon-service/src/main/java/cn/nla/coupon/model/request/NewUserCouponRequest.java
@@ -0,0 +1,20 @@
+package cn.nla.coupon.model.request;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 新用户注册发放优惠卷
+ */
+@ApiModel(value = "新用户注册发放优惠卷对象", description = "新用户注册发放优惠卷请求对象")
+@Data
+public class NewUserCouponRequest {
+ @ApiModelProperty(value = "用户Id", example = "19")
+ @JsonProperty("user_id")
+ private long userId;
+ @ApiModelProperty(value = "名称", example = "二当家")
+ @JsonProperty("name")
+ private String name;
+}
diff --git a/nla-coupon-service/src/main/java/cn/nla/coupon/service/CouponRecordService.java b/nla-coupon-service/src/main/java/cn/nla/coupon/service/CouponRecordService.java
index 595258d..1716277 100644
--- a/nla-coupon-service/src/main/java/cn/nla/coupon/service/CouponRecordService.java
+++ b/nla-coupon-service/src/main/java/cn/nla/coupon/service/CouponRecordService.java
@@ -1,5 +1,7 @@
package cn.nla.coupon.service;
+import cn.nla.common.model.PageResult;
+import cn.nla.coupon.model.VO.CouponRecordVO;
import cn.nla.coupon.model.entity.CouponRecordEntity;
import com.baomidou.mybatisplus.extension.service.IService;
@@ -13,4 +15,10 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/
public interface CouponRecordService extends IService {
+ /**
+ * 分页查询个人优惠券
+ */
+ PageResult page(int page, int size);
+
+ CouponRecordVO findById(long recordId);
}
diff --git a/nla-coupon-service/src/main/java/cn/nla/coupon/service/CouponService.java b/nla-coupon-service/src/main/java/cn/nla/coupon/service/CouponService.java
index 749f79d..14f8da7 100644
--- a/nla-coupon-service/src/main/java/cn/nla/coupon/service/CouponService.java
+++ b/nla-coupon-service/src/main/java/cn/nla/coupon/service/CouponService.java
@@ -3,6 +3,7 @@ package cn.nla.coupon.service;
import cn.nla.common.enums.CouponCategoryEnum;
import cn.nla.common.util.JsonData;
import cn.nla.coupon.model.entity.CouponEntity;
+import cn.nla.coupon.model.request.NewUserCouponRequest;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.Map;
@@ -27,4 +28,12 @@ public interface CouponService extends IService {
* 4、保存领劵记录
*/
JsonData addCoupon(Long couponId, CouponCategoryEnum category);
+
+ /**
+ * 用户微服务调用的时候,没传递token
+ *
+ * 本地直接调用发放优惠券的方法,需要构造一个登录用户存储在threadlocal
+ *
+ */
+ JsonData initNewUserCoupon(NewUserCouponRequest newUserCouponRequest);
}
diff --git a/nla-coupon-service/src/main/java/cn/nla/coupon/service/impl/CouponRecordServiceImpl.java b/nla-coupon-service/src/main/java/cn/nla/coupon/service/impl/CouponRecordServiceImpl.java
index 4c1e467..940d47d 100644
--- a/nla-coupon-service/src/main/java/cn/nla/coupon/service/impl/CouponRecordServiceImpl.java
+++ b/nla-coupon-service/src/main/java/cn/nla/coupon/service/impl/CouponRecordServiceImpl.java
@@ -1,11 +1,21 @@
package cn.nla.coupon.service.impl;
+import cn.nla.common.interceptor.LoginInterceptor;
+import cn.nla.common.model.LoginUser;
+import cn.nla.common.model.PageResult;
+import cn.nla.coupon.model.VO.CouponRecordVO;
import cn.nla.coupon.model.entity.CouponRecordEntity;
import cn.nla.coupon.mapper.CouponRecordMapper;
import cn.nla.coupon.service.CouponRecordService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
+import java.util.stream.Collectors;
+
/**
*
* 优惠券领劵记录 服务实现类
@@ -17,4 +27,34 @@ import org.springframework.stereotype.Service;
@Service
public class CouponRecordServiceImpl extends ServiceImpl implements CouponRecordService {
+ @Override
+ public PageResult page(int page, int size) {
+ LoginUser loginUser = LoginInterceptor.threadLocal.get();
+ //封装分页信息
+ Page pageInfo = new Page<>(page, size);
+ IPage recordPage = baseMapper.selectPage(pageInfo,
+ Wrappers.lambdaQuery().eq(CouponRecordEntity::getUserId, loginUser.getId())
+ .orderByDesc(CouponRecordEntity::getCreateTime));
+ return new PageResult<>(recordPage.getTotal(), recordPage.getPages(),
+ recordPage.getRecords().stream().map(item -> {
+ CouponRecordVO result = new CouponRecordVO();
+ BeanUtils.copyProperties(item, result);
+ return result;
+ }).collect(Collectors.toList()));
+ }
+
+ @Override
+ public CouponRecordVO findById(long recordId) {
+ LoginUser loginUser = LoginInterceptor.threadLocal.get();
+ CouponRecordEntity couponRecord = baseMapper.selectOne(
+ Wrappers.lambdaQuery().
+ eq(CouponRecordEntity::getUserId, loginUser.getId())
+ .eq(CouponRecordEntity::getId, recordId));
+ if (couponRecord == null) {
+ return null;
+ }
+ CouponRecordVO result = new CouponRecordVO();
+ BeanUtils.copyProperties(couponRecord, result);
+ return result;
+ }
}
diff --git a/nla-coupon-service/src/main/java/cn/nla/coupon/service/impl/CouponServiceImpl.java b/nla-coupon-service/src/main/java/cn/nla/coupon/service/impl/CouponServiceImpl.java
index 7f9a178..089d98c 100644
--- a/nla-coupon-service/src/main/java/cn/nla/coupon/service/impl/CouponServiceImpl.java
+++ b/nla-coupon-service/src/main/java/cn/nla/coupon/service/impl/CouponServiceImpl.java
@@ -14,6 +14,7 @@ import cn.nla.coupon.model.VO.CouponVO;
import cn.nla.coupon.model.entity.CouponEntity;
import cn.nla.coupon.mapper.CouponMapper;
import cn.nla.coupon.model.entity.CouponRecordEntity;
+import cn.nla.coupon.model.request.NewUserCouponRequest;
import cn.nla.coupon.service.CouponService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -32,10 +33,7 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.Duration;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -64,7 +62,7 @@ public class CouponServiceImpl extends ServiceImpl i
Page pageInfo = new Page<>(page, size);
IPage couponDOIPage = baseMapper.selectPage(pageInfo,
Wrappers.lambdaQuery().eq(CouponEntity::getPublish, CouponPublishEnum.PUBLISH)
- .eq(CouponEntity::getCategory, CouponCategoryEnum.PROMOTION)
+ .eq(CouponEntity::getCategory, CouponCategoryEnum.PROMOTION.name())
.orderByDesc(CouponEntity::getCreateTime));
Map pageMap = new HashMap<>(3);
//总条数
@@ -75,7 +73,6 @@ public class CouponServiceImpl extends ServiceImpl i
return pageMap;
}
-
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
@Override
public JsonData addCoupon(Long couponId, CouponCategoryEnum category) {
@@ -179,6 +176,23 @@ public class CouponServiceImpl extends ServiceImpl i
return JsonData.buildSuccess();
}
+ @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
+ @Override
+ public JsonData initNewUserCoupon(NewUserCouponRequest newUserCouponRequest) {
+ LoginUser loginUser = new LoginUser();
+ loginUser.setId(newUserCouponRequest.getUserId());
+ loginUser.setName(newUserCouponRequest.getName());
+ LoginInterceptor.threadLocal.set(loginUser);
+ //查询新用户有哪些优惠券
+ List couponList = baseMapper.selectList(
+ Wrappers.lambdaQuery().eq(CouponEntity::getCategory, CouponCategoryEnum.NEW_USER.name()));
+ for (CouponEntity coupon : couponList) {
+ //幂等操作,调用需要加锁
+ this.addCoupon(coupon.getId(), CouponCategoryEnum.NEW_USER);
+ }
+ return JsonData.buildSuccess();
+ }
+
private CouponVO beanProcess(CouponEntity entity) {
CouponVO couponVO = new CouponVO();
BeanUtils.copyProperties(entity, couponVO);
diff --git a/nla-product-service/pom.xml b/nla-product-service/pom.xml
new file mode 100644
index 0000000..bbd98ab
--- /dev/null
+++ b/nla-product-service/pom.xml
@@ -0,0 +1,28 @@
+
+
+
+ nla-shop
+ cn.nla
+ 1.0-SNAPSHOT
+
+ 4.0.0
+ nla-product-service
+ 商品服务模块
+
+ 11
+ 11
+
+
+
+ cn.nla
+ nla-common
+ 1.0-SNAPSHOT
+
+
+ org.projectlombok
+ lombok
+
+
+
diff --git a/nla-product-service/src/main/java/cn/nla/product/ProductApplication.java b/nla-product-service/src/main/java/cn/nla/product/ProductApplication.java
new file mode 100644
index 0000000..dbaf423
--- /dev/null
+++ b/nla-product-service/src/main/java/cn/nla/product/ProductApplication.java
@@ -0,0 +1,15 @@
+package cn.nla.product;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.ComponentScan;
+
+@SpringBootApplication
+@MapperScan("cn.nla.*.mapper")
+@ComponentScan(basePackages = {"cn.nla.*"})
+public class ProductApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(ProductApplication.class, args);
+ }
+}
diff --git a/nla-product-service/src/main/java/cn/nla/product/controller/BannerController.java b/nla-product-service/src/main/java/cn/nla/product/controller/BannerController.java
new file mode 100644
index 0000000..d1cd6b5
--- /dev/null
+++ b/nla-product-service/src/main/java/cn/nla/product/controller/BannerController.java
@@ -0,0 +1,38 @@
+package cn.nla.product.controller;
+
+
+import cn.nla.common.util.JsonData;
+import cn.nla.product.service.BannerService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+/**
+ *
+ * banner表 前端控制器
+ *
+ *
+ * @author YJs
+ * @since 2024-08-09
+ */
+@Api(tags = "轮播图控制器")
+@RestController
+@RequestMapping("/pdt/banner/v1")
+public class BannerController {
+
+ @Resource
+ private BannerService bannerService;
+
+ @ApiOperation("轮播图列表接口")
+ @GetMapping("list")
+ public JsonData list() {
+ return JsonData.buildSuccess(bannerService.list());
+ }
+}
+
diff --git a/nla-product-service/src/main/java/cn/nla/product/controller/CartController.java b/nla-product-service/src/main/java/cn/nla/product/controller/CartController.java
new file mode 100644
index 0000000..214f4c3
--- /dev/null
+++ b/nla-product-service/src/main/java/cn/nla/product/controller/CartController.java
@@ -0,0 +1,56 @@
+package cn.nla.product.controller;
+
+import cn.nla.common.util.JsonData;
+import cn.nla.product.model.request.CartItemRequest;
+import cn.nla.product.service.CartService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+
+/**
+ * 购物车前端控制器
+ */
+@Api(tags = "购物车控制器")
+@RestController
+@RequestMapping("/pdt/cart/v1")
+public class CartController {
+ @Resource
+ private CartService cartService;
+
+ @ApiOperation("添加到购物车")
+ @PostMapping("add")
+ public JsonData addToCart(@ApiParam("购物项") @RequestBody CartItemRequest cartItemRequest) {
+ cartService.addToCart(cartItemRequest);
+ return JsonData.buildSuccess();
+ }
+
+ @ApiOperation("清空购物车")
+ @DeleteMapping("/clear")
+ public JsonData cleanMyCart() {
+ cartService.clear();
+ return JsonData.buildSuccess();
+ }
+
+ @ApiOperation("查看我的购物车")
+ @GetMapping("/my-cart")
+ public JsonData findMyCart() {
+ return JsonData.buildSuccess(cartService.getMyCart());
+ }
+
+ @ApiOperation("修改购物车数量")
+ @PostMapping("change")
+ public JsonData changeItemNum(@ApiParam("购物项") @RequestBody CartItemRequest cartItemRequest) {
+ cartService.changeItemNum(cartItemRequest);
+ return JsonData.buildSuccess();
+ }
+
+ @ApiOperation("删除购物项")
+ @DeleteMapping("/delete/{product_id}")
+ public JsonData deleteItem(@ApiParam(value = "商品id", required = true) @PathVariable("product_id") long productId) {
+ cartService.deleteItem(productId);
+ return JsonData.buildSuccess();
+ }
+}
diff --git a/nla-product-service/src/main/java/cn/nla/product/controller/ProductController.java b/nla-product-service/src/main/java/cn/nla/product/controller/ProductController.java
new file mode 100644
index 0000000..dc7ff13
--- /dev/null
+++ b/nla-product-service/src/main/java/cn/nla/product/controller/ProductController.java
@@ -0,0 +1,49 @@
+package cn.nla.product.controller;
+
+
+import cn.nla.common.util.JsonData;
+import cn.nla.product.model.VO.ProductVO;
+import cn.nla.product.service.ProductService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.Map;
+
+/**
+ *
+ * 商品表 前端控制器
+ *
+ *
+ * @author YJs
+ * @since 2024-08-09
+ */
+@Api(tags = "商品控制器")
+@RestController
+@RequestMapping("//pdt/product/v1")
+public class ProductController {
+
+ @Resource
+ private ProductService productService;
+
+ @ApiOperation("分页查询商品列表")
+ @GetMapping("page")
+ public JsonData pageProductList(
+ @ApiParam(value = "当前页") @RequestParam(value = "page", defaultValue = "1") int page,
+ @ApiParam(value = "每页显示多少条") @RequestParam(value = "size", defaultValue = "10") int size) {
+
+ return JsonData.buildSuccess(productService.page(page, size));
+ }
+
+
+ @ApiOperation("商品详情")
+ @GetMapping("/detail/{product_id}")
+ public JsonData detail(@ApiParam(value = "商品id", required = true) @PathVariable("product_id") long productId) {
+ return JsonData.buildSuccess(productService.findDetailById(productId));
+ }
+
+}
+
diff --git a/nla-product-service/src/main/java/cn/nla/product/mapper/BannerMapper.java b/nla-product-service/src/main/java/cn/nla/product/mapper/BannerMapper.java
new file mode 100644
index 0000000..d9a829d
--- /dev/null
+++ b/nla-product-service/src/main/java/cn/nla/product/mapper/BannerMapper.java
@@ -0,0 +1,16 @@
+package cn.nla.product.mapper;
+
+import cn.nla.product.model.entity.BannerEntity;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ *
+ * banner表 Mapper 接口
+ *
+ *
+ * @author YJs
+ * @since 2024-08-09
+ */
+public interface BannerMapper extends BaseMapper {
+
+}
diff --git a/nla-product-service/src/main/java/cn/nla/product/mapper/ProductMapper.java b/nla-product-service/src/main/java/cn/nla/product/mapper/ProductMapper.java
new file mode 100644
index 0000000..3bec40d
--- /dev/null
+++ b/nla-product-service/src/main/java/cn/nla/product/mapper/ProductMapper.java
@@ -0,0 +1,16 @@
+package cn.nla.product.mapper;
+
+import cn.nla.product.model.entity.ProductEntity;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ *
+ * 商品表 Mapper 接口
+ *
+ *
+ * @author YJs
+ * @since 2024-08-09
+ */
+public interface ProductMapper extends BaseMapper {
+
+}
diff --git a/nla-product-service/src/main/java/cn/nla/product/model/VO/CartItemVO.java b/nla-product-service/src/main/java/cn/nla/product/model/VO/CartItemVO.java
new file mode 100644
index 0000000..78796e8
--- /dev/null
+++ b/nla-product-service/src/main/java/cn/nla/product/model/VO/CartItemVO.java
@@ -0,0 +1,42 @@
+package cn.nla.product.model.VO;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 购物项
+ */
+@Data
+public class CartItemVO {
+ /**
+ * 商品id
+ */
+ @JsonProperty("product_id")
+ private Long productId;
+ /**
+ * 购买数量
+ */
+ @JsonProperty("buy_num")
+ private Integer buyNum;
+ /**
+ * 商品标题
+ */
+ @JsonProperty("product_title")
+ private String productTitle;
+ /**
+ * 图片
+ */
+ @JsonProperty("product_img")
+ private String productImg;
+ /**
+ * 商品单价
+ */
+ private BigDecimal amount;
+ /**
+ * 总价格,单价+数量
+ */
+ @JsonProperty("total_amount")
+ private BigDecimal totalAmount;
+}
diff --git a/nla-product-service/src/main/java/cn/nla/product/model/VO/CartVO.java b/nla-product-service/src/main/java/cn/nla/product/model/VO/CartVO.java
new file mode 100644
index 0000000..8f2ab06
--- /dev/null
+++ b/nla-product-service/src/main/java/cn/nla/product/model/VO/CartVO.java
@@ -0,0 +1,72 @@
+package cn.nla.product.model.VO;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 购物车
+ */
+@Data
+public class CartVO {
+ /**
+ * 购物项
+ */
+ @JsonProperty("cart_items")
+ private List cartItems;
+ /**
+ * 购买总件数
+ */
+ @JsonProperty("total_num")
+ private Integer totalNum;
+ /**
+ * 购物车总价格
+ */
+ @JsonProperty("total_price")
+ private BigDecimal totalPrice;
+ /**
+ * 购物车实际支付价格
+ */
+ @JsonProperty("real_pay_price")
+ private BigDecimal realPayPrice;
+
+ /**
+ * 总件数
+ */
+ public Integer getTotalNum() {
+ if (this.cartItems != null) {
+ return cartItems.stream().mapToInt(CartItemVO::getBuyNum).sum();
+ }
+ return 0;
+ }
+
+ /**
+ * 总价格
+ */
+ public BigDecimal getTotalPrice() {
+ BigDecimal amount = new BigDecimal("0");
+ if (this.cartItems != null) {
+ for (CartItemVO cartItemVO : cartItems) {
+ BigDecimal itemTotalAmount = cartItemVO.getTotalAmount();
+ amount = amount.add(itemTotalAmount);
+ }
+ }
+ return amount;
+ }
+
+ /**
+ * 购物车里面实际支付的价格
+ */
+ public BigDecimal getRealPayPrice() {
+ BigDecimal amount = new BigDecimal("0");
+ if (this.cartItems != null) {
+ for (CartItemVO cartItemVO : cartItems) {
+ BigDecimal itemTotalAmount = cartItemVO.getTotalAmount();
+ amount = amount.add(itemTotalAmount);
+ }
+ }
+ return amount;
+ }
+}
diff --git a/nla-product-service/src/main/java/cn/nla/product/model/VO/ProductVO.java b/nla-product-service/src/main/java/cn/nla/product/model/VO/ProductVO.java
new file mode 100644
index 0000000..4e7cb57
--- /dev/null
+++ b/nla-product-service/src/main/java/cn/nla/product/model/VO/ProductVO.java
@@ -0,0 +1,37 @@
+package cn.nla.product.model.VO;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class ProductVO {
+ private Long id;
+ /**
+ * 标题
+ */
+ private String title;
+ /**
+ * 封面图
+ */
+ @JsonProperty("cover_img")
+ private String coverImg;
+ /**
+ * 详情
+ */
+ private String detail;
+ /**
+ * 老价格
+ */
+ @JsonProperty("old_amount")
+ private BigDecimal oldAmount;
+ /**
+ * 新价格
+ */
+ private BigDecimal amount;
+ /**
+ * 库存
+ */
+ private Integer stock;
+}
diff --git a/nla-product-service/src/main/java/cn/nla/product/model/entity/BannerEntity.java b/nla-product-service/src/main/java/cn/nla/product/model/entity/BannerEntity.java
new file mode 100644
index 0000000..858ab7f
--- /dev/null
+++ b/nla-product-service/src/main/java/cn/nla/product/model/entity/BannerEntity.java
@@ -0,0 +1,44 @@
+package cn.nla.product.model.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ *
+ * banner表
+ *
+ *
+ * @author YJs
+ * @since 2024-08-09
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("banner")
+public class BannerEntity implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Integer id;
+
+ /**
+ * 图片
+ */
+ private String img;
+
+ /**
+ * 跳转地址
+ */
+ private String url;
+
+ /**
+ * 权重
+ */
+ private Integer weight;
+
+
+}
diff --git a/nla-product-service/src/main/java/cn/nla/product/model/entity/ProductEntity.java b/nla-product-service/src/main/java/cn/nla/product/model/entity/ProductEntity.java
new file mode 100644
index 0000000..aaf6f3f
--- /dev/null
+++ b/nla-product-service/src/main/java/cn/nla/product/model/entity/ProductEntity.java
@@ -0,0 +1,71 @@
+package cn.nla.product.model.entity;
+
+import java.math.BigDecimal;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.IdType;
+import java.util.Date;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ *
+ * 商品表
+ *
+ *
+ * @author YJs
+ * @since 2024-08-09
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("product")
+public class ProductEntity implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 标题
+ */
+ private String title;
+
+ /**
+ * 封面图
+ */
+ private String coverImg;
+
+ /**
+ * 详情
+ */
+ private String detail;
+
+ /**
+ * 老价格
+ */
+ private BigDecimal oldPrice;
+
+ /**
+ * 新价格
+ */
+ private BigDecimal price;
+
+ /**
+ * 库存
+ */
+ private Integer stock;
+
+ /**
+ * 创建时间
+ */
+ private Date createTime;
+
+ /**
+ * 锁定库存
+ */
+ private Integer lockStock;
+
+
+}
diff --git a/nla-product-service/src/main/java/cn/nla/product/model/request/CartItemRequest.java b/nla-product-service/src/main/java/cn/nla/product/model/request/CartItemRequest.java
new file mode 100644
index 0000000..3d0a91b
--- /dev/null
+++ b/nla-product-service/src/main/java/cn/nla/product/model/request/CartItemRequest.java
@@ -0,0 +1,20 @@
+package cn.nla.product.model.request;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 添加购物车对象
+ */
+@ApiModel(value = "添加购物车对象", description = "添加购物车请求对象")
+@Data
+public class CartItemRequest {
+ @ApiModelProperty(value = "商品id", example = "11")
+ @JsonProperty("product_id")
+ private long productId;
+ @ApiModelProperty(value = "购买数量", example = "1")
+ @JsonProperty("buy_num")
+ private int buyNum;
+}
diff --git a/nla-product-service/src/main/java/cn/nla/product/service/BannerService.java b/nla-product-service/src/main/java/cn/nla/product/service/BannerService.java
new file mode 100644
index 0000000..e141aca
--- /dev/null
+++ b/nla-product-service/src/main/java/cn/nla/product/service/BannerService.java
@@ -0,0 +1,16 @@
+package cn.nla.product.service;
+
+import cn.nla.product.model.entity.BannerEntity;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ *
+ * banner表 服务类
+ *
+ *
+ * @author YJs
+ * @since 2024-08-09
+ */
+public interface BannerService extends IService {
+
+}
diff --git a/nla-product-service/src/main/java/cn/nla/product/service/CartService.java b/nla-product-service/src/main/java/cn/nla/product/service/CartService.java
new file mode 100644
index 0000000..17938fc
--- /dev/null
+++ b/nla-product-service/src/main/java/cn/nla/product/service/CartService.java
@@ -0,0 +1,32 @@
+package cn.nla.product.service;
+
+
+import cn.nla.product.model.VO.CartVO;
+import cn.nla.product.model.request.CartItemRequest;
+
+public interface CartService {
+ /**
+ * 添加到购物车(一直缓存到redis中,没有创建购物车数据表)
+ */
+ void addToCart(CartItemRequest cartItemRequest);
+
+ /**
+ * 清空购物车
+ */
+ void clear();
+
+ /**
+ * 查询
+ */
+ CartVO getMyCart();
+
+ /**
+ * 修改
+ */
+ void changeItemNum(CartItemRequest cartItemRequest);
+
+ /**
+ * 删除
+ */
+ void deleteItem(long productId);
+}
diff --git a/nla-product-service/src/main/java/cn/nla/product/service/ProductService.java b/nla-product-service/src/main/java/cn/nla/product/service/ProductService.java
new file mode 100644
index 0000000..5fb7ac9
--- /dev/null
+++ b/nla-product-service/src/main/java/cn/nla/product/service/ProductService.java
@@ -0,0 +1,33 @@
+package cn.nla.product.service;
+
+import cn.nla.common.model.PageResult;
+import cn.nla.product.model.VO.ProductVO;
+import cn.nla.product.model.entity.ProductEntity;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+/**
+ *
+ * 商品表 服务类
+ *
+ *
+ * @author YJs
+ * @since 2024-08-09
+ */
+public interface ProductService extends IService {
+ /**
+ * 根据id找商品详情
+ **/
+ ProductVO findDetailById(Long productId);
+
+ /**
+ * 分页查询商品列表
+ **/
+ PageResult page(int page, int size);
+
+ /**
+ * 批量查询
+ */
+ List findProductsByIdBatch(List productIdList);
+}
diff --git a/nla-product-service/src/main/java/cn/nla/product/service/impl/BannerServiceImpl.java b/nla-product-service/src/main/java/cn/nla/product/service/impl/BannerServiceImpl.java
new file mode 100644
index 0000000..608d77c
--- /dev/null
+++ b/nla-product-service/src/main/java/cn/nla/product/service/impl/BannerServiceImpl.java
@@ -0,0 +1,20 @@
+package cn.nla.product.service.impl;
+
+import cn.nla.product.model.entity.BannerEntity;
+import cn.nla.product.mapper.BannerMapper;
+import cn.nla.product.service.BannerService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ *
+ * banner表 服务实现类
+ *
+ *
+ * @author YJs
+ * @since 2024-08-09
+ */
+@Service
+public class BannerServiceImpl extends ServiceImpl implements BannerService {
+
+}
diff --git a/nla-product-service/src/main/java/cn/nla/product/service/impl/CartServiceImpl.java b/nla-product-service/src/main/java/cn/nla/product/service/impl/CartServiceImpl.java
new file mode 100644
index 0000000..07c08f7
--- /dev/null
+++ b/nla-product-service/src/main/java/cn/nla/product/service/impl/CartServiceImpl.java
@@ -0,0 +1,163 @@
+package cn.nla.product.service.impl;
+
+import cn.nla.common.constant.CacheKey;
+import cn.nla.common.enums.BizCodeEnum;
+import cn.nla.common.exception.BizException;
+import cn.nla.common.interceptor.LoginInterceptor;
+import cn.nla.common.model.LoginUser;
+import cn.nla.product.model.VO.CartItemVO;
+import cn.nla.product.model.VO.CartVO;
+import cn.nla.product.model.VO.ProductVO;
+import cn.nla.product.model.request.CartItemRequest;
+import cn.nla.product.service.CartService;
+import cn.nla.product.service.ProductService;
+import com.alibaba.fastjson.JSON;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.data.redis.core.BoundHashOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * 购物车
+ */
+@Service
+public class CartServiceImpl implements CartService {
+ @Resource
+ private ProductService productService;
+ @Resource
+ private RedisTemplate redisTemplate;
+
+ @Override
+ public void addToCart(CartItemRequest cartItemRequest) {
+ long productId = cartItemRequest.getProductId();
+ int buyNum = cartItemRequest.getBuyNum();
+ //获取购物车
+ BoundHashOperations myCart = getMyCartOps();
+ Object cacheObj = myCart.get(String.valueOf(productId));
+ String result = "";
+ if (cacheObj != null) {
+ result = (String) cacheObj;
+ }
+ if (StringUtils.isBlank(result)) {
+ //不存在则新建一个商品
+ CartItemVO cartItemVO = new CartItemVO();
+ ProductVO product = productService.findDetailById(productId);
+ if (product == null) {
+ throw new BizException(BizCodeEnum.CART_FAIL);
+ }
+ cartItemVO.setAmount(product.getAmount());
+ cartItemVO.setBuyNum(buyNum);
+ cartItemVO.setProductId(productId);
+ cartItemVO.setProductImg(product.getCoverImg());
+ cartItemVO.setProductTitle(product.getTitle());
+ cartItemVO.setTotalAmount(product.getAmount().multiply(new BigDecimal(buyNum)));
+ myCart.put(String.valueOf(productId), JSON.toJSONString(cartItemVO));
+ } else {
+ //存在商品,修改数量
+ CartItemVO cartItem = JSON.parseObject(result, CartItemVO.class);
+ cartItem.setBuyNum(cartItem.getBuyNum() + buyNum);
+ myCart.put(String.valueOf(productId), JSON.toJSONString(cartItem));
+ }
+ }
+
+ @Override
+ public void clear() {
+ redisTemplate.delete(getCartKey());
+
+ }
+
+ /**
+ * 删除购物项
+ */
+ @Override
+ public void deleteItem(long productId) {
+ getMyCartOps().delete(String.valueOf(productId));
+ }
+
+ @Override
+ public void changeItemNum(CartItemRequest cartItemRequest) {
+ BoundHashOperations mycart = getMyCartOps();
+ Object cacheObj = mycart.get(String.valueOf(cartItemRequest.getProductId()));
+ if (cacheObj == null) {
+ throw new BizException(BizCodeEnum.CART_FAIL);
+ }
+ String obj = (String) cacheObj;
+ CartItemVO cartItemVO = JSON.parseObject(obj, CartItemVO.class);
+ cartItemVO.setBuyNum(cartItemRequest.getBuyNum());
+ cartItemVO.setTotalAmount(cartItemVO.getAmount().multiply(new BigDecimal(cartItemVO.getBuyNum())));
+ mycart.put(String.valueOf(cartItemRequest.getProductId()), JSON.toJSONString(cartItemVO));
+ }
+
+ @Override
+ public CartVO getMyCart() {
+ //获取全部购物项
+ List cartItemVOList = buildCartItem(false);
+ CartVO cartVO = new CartVO();
+ cartVO.setCartItems(cartItemVOList);
+ return cartVO;
+ }
+
+ /**
+ * 获取最新的购物项,
+ *
+ * @param latestPrice 是否获取最新价格
+ */
+ private List buildCartItem(boolean latestPrice) {
+ BoundHashOperations myCart = getMyCartOps();
+ List