✅P244_商城业务-购物车-获取并合并购物车
大约 4 分钟
一、开篇
购物车列表展示逻辑
- 若用户未登录,则使用user-key获取Redis中购物车数据
- 若用户登录,则使用userId获取Redis中购物车数据,并将user-key 对应的临时购物车数据与用户购物车数据合并且删除临时购物车
二、业务实现
2.1 Controller
cfmall-cart/src/main/java/com/gyz/cfmall/controller/CartController.java
/**
* 去购物车页面的请求
* 浏览器有一个cookie:user-key 标识用户的身份,一个月过期
* 如果第一次使用jd的购物车功能,都会给一个临时的用户身份:
* 浏览器以后保存,每次访问都会带上这个cookie;
* <p>
* 登录:session有
* 没登录:按照cookie里面带来user-key来做
* 第一次,如果没有临时用户,自动创建一个临时用户
*
* @return
*/
@GetMapping(value = "/cart.html")
public String cartListPage(Model model) throws ExecutionException, InterruptedException {
//快速得到用户信息:id,user-key
// UserInfoTo userInfoTo = CartInterceptor.toThreadLocal.get();
CartVo cartVo = cartService.getCart();
model.addAttribute("cart", cartVo);
return "cartList";
}
2.2 Service
@Override
public CartVo getCart() throws ExecutionException, InterruptedException {
CartVo cartVo = new CartVo();
UserInfoTo userInfoTo = CartInterceptor.threadLocal.get();
if (userInfoTo.getUserId() != null) {
//1、登录
String cartKey = CART_PREFIX + userInfoTo.getUserId();
//临时购物车的键
String temptCartKey = CART_PREFIX + userInfoTo.getUserKey();
//2、如果临时购物车的数据还未进行合并
List<CartItemVo> tempCartItems = getCartItemList(temptCartKey);
if (tempCartItems != null) {
//临时购物车有数据需要进行合并操作
for (CartItemVo item : tempCartItems) {
this.addCartItem(item.getSkuId(), item.getCount());
}
//清除临时购物车的数据
this.clearCartInfo(temptCartKey);
}
//3、获取登录后的购物车数据【包含合并过来的临时购物车的数据和登录后购物车的数据】
List<CartItemVo> cartItems = this.getCartItemList(cartKey);
cartVo.setItems(cartItems);
} else {
//没登录
String cartKey = CART_PREFIX + userInfoTo.getUserKey();
//获取临时购物车里面的所有购物项
List<CartItemVo> cartItems = this.getCartItemList(cartKey);
cartVo.setItems(cartItems);
}
return cartVo;
}
/**
* 获取购物车里所有商品数据
*
* @param tempUserKey
* @return
*/
public List<CartItemVo> getCartItemList(String tempUserKey) {
BoundHashOperations<String, Object, Object> ops = stringRedisTemplate.boundHashOps(tempUserKey);
List<Object> values = ops.values();
if (values != null && values.size() > 0) {
List<CartItemVo> cartItemList = values.stream().map(item -> {
CartItemVo cartItemVo = JSON.parseObject((String) item, CartItemVo.class);
return cartItemVo;
}).collect(Collectors.toList());
return cartItemList;
}
return null;
}
/**
* 清空购物车的数据
*
* @param cartKey
*/
@Override
public void clearCartInfo(String cartKey) {
stringRedisTemplate.delete(cartKey);
}
三、前端页面
3.1 登录回显
cfmall-cart/src/main/resources/templates/success.html
<ul class="hd_wrap_right">
<li class="forel">
<li>
<a th:if="${session.loginUser == null}" href="http://auth.cfmall.com/login.html" class="li_2">请登录</a>
<a th:if="${session.loginUser != null}">欢迎, [[${session.loginUser.nickname}]]</a>
</li>
<li>
<a th:if="${session.loginUser == null}" href="http://auth.cfmall.com/reg.html" style="color: red;">免费注册</a>
</li>
<li>
<a href="/javascript:;">我的订单</a>
</li>
</ul>
3.2 购物车页面
cfmall-cart/src/main/resources/templates/cartList.html
3.2.1 常规内容显示
<div class="One_ShopCon">
<h1 th:if="${cart.items==null}">购物车还没有商品,<a href="http://cfmall.com/">去购物</a></h1>
<ul th:if="${cart.items!=null}">
<li th:each="item:${cart.items}">
<div></div>
<div>
<ol>
<li><input type="checkbox" th:attr="skuId=${item.skuId}" class="itemCheck" th:checked="${item.check}"/></li>
<li>
<dt><img th:src="${item.image}" alt=""></dt>
<dd style="width: 150px;">
<p>
<span th:text="${item.title}">TCL 55A950C 55英寸32核</span><br/>
<span th:each="attr:${item.skuAttrValues}"
th:text="${attr}+''"></span>
</p>
</dd>
</li>
<li>
<!-- #numbers.formatDecimal(变量, 整数位位数(不足前面补0), 保留小数位的数量) -->
<p class="dj" th:text="'¥'+${#numbers.formatDecimal(item.price,3,2)}">4599.00</p>
</li>
<li>
<p>
<span>-</span>
<span th:text="${item.count}">5</span>
<span>+</span>
</p>
</li>
<li style="font-weight:bold">
<p class="zj">¥[[${#numbers.formatDecimal(item.totalPrice,3,2)}]]</p>
</li>
<li>
<p class="deleteItemBtn" th:attr="skuId=${item.skuId}">删除</p>
</li>
</ol>
</div>
</li>
</ul>
</div>
3.2.2 购物车总价&优惠价格显示
<div>
<ol>
<li>总价:<span style="color:#e64346;font-weight:bold;font-size:16px;" class="fnt">¥[[${#numbers.formatDecimal(cart.totalAmount, 3, 2)}]]</span></li>
<li>优惠:¥[[${#numbers.formatDecimal(cart.reduce,1,2)}]]</li>
</ol>
</div>
3.2.3 页面优化
cfmall-cart/src/main/resources/templates/cartList.html
<div class="one_search_load" th:if="${session.loginUser==null}">
<img src="/static/cart/img/shop_07.jpg" class="one_load_wraing">
<span>您还没有登录!登录后购物车的商品将保存到您账号中</span>
<a href="#"><input type="button" onclick="login()" value="立即登录" class="one_load_btn"></a>
</div>
function login(){
location.href = "http://auth.cfmall.com/login.html";
}
3.3 商城首页-我的购物车
实现:点击商城首页-“我的购物车”展示购物车列表数据,
修改获取购物车数据接口,
cfmall-product/src/main/resources/templates/index.html