樂優商城—購物車


1.實現未登錄狀態的購物車

2.實現登陸狀態下的購物車

購物車功能分析

需求

需求描述:

  • 用戶可以在登錄狀態下將商品添加到購物車
    • 放入數據庫
    • mongodb(建議)
    • 放入redis(被迫採用)
  • 用戶可以在未登錄狀態下將商品添加到購物車
    • 放入localstorage
    • cookie
    • webSQL
  • 用戶可以使用購物車一起結算下單
  • 用戶可以查詢自己的購物車
  • 用戶可以在購物車中修改購買商品的數量。
  • 用戶可以在購物車中刪除商品。
  • 在購物車中展示商品優惠信息
  • 提示購物車商品價格變化

流程圖

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-RngsiCLf-1586830021250)(assets/1527585343248.png)]

這幅圖主要描述了兩個功能:新增商品到購物車、查詢購物車。

新增商品:

  • 判斷是否登錄
    • 是:則添加商品到後臺Redis中
    • 否:則添加商品到本地的Localstorage

無論哪種新增,完成後都需要查詢購物車列表:

  • 判斷是否登錄
    • 否:直接查詢localstorage中數據並展示
    • 是:已登錄,則需要先看本地是否有數據,
      • 有:需要提交到後臺添加到redis,合併數據,而後查詢
      • 否:直接去後臺查詢redis,而後返回

未登錄購物車

web本地存儲主要有兩種方式:

  • LocalStorage:localStorage 方法存儲的數據沒有時間限制。第二天、第二週或下一年之後,數據依然可用。
  • SessionStorage:sessionStorage 方法針對一個 session 進行數據存儲。當用戶關閉瀏覽器窗口後,數據會被刪除。

LocalStorage的用法

語法非常簡單:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-2bhML4qx-1586830021251)(assets/1533739711101.png)]

localStorage.setItem("key","value"); // 存儲數據
localStorage.getItem("key"); // 獲取數據
localStorage.removeItem("key"); // 刪除數據

注意:localStorage和SessionStorage都只能保存字符串

不過,在我們的common.js中,已經對localStorage進行了簡單的封裝:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-dfMEWlJB-1586830021252)(assets/1533739810927.png)]
在這裏插入圖片描述

添加購物車

addCart(){
    ly.verifyUser().then(res=>{
        // 已登錄發送信息到後臺,保存到redis中

    }).catch(()=>{
        // 未登錄保存在瀏覽器本地的localStorage中
        // 1、查詢本地購物車
        let carts = ly.store.get("carts") || [];
        let cart = carts.find(c=>c.skuId===this.sku.id);
        // 2、判斷是否存在
        if (cart) {
            // 3、存在更新數量
            cart.num += this.num;
        } else {
            // 4、不存在,新增
            cart = {
                skuId: this.sku.id,
                title: this.sku.title,
                price: this.sku.price,
                image: this.sku.images,
                num: this.num,
                ownSpec: this.ownSpec
            }
            carts.push(cart);
        }
        // 把carts寫回localstorage
        ly.store.set("carts", carts);
        // 跳轉
        window.location.href = "http://www.leyou.com/cart.html";
    });
}

查詢購物車

頁面加載時,就應該去查詢購物車。

var cartVm = new Vue({
    el: "#cartApp",
    data: {
        ly,
        carts: [],// 購物車數據
    },
    created() {
        this.loadCarts();
    },
    methods: {
        loadCarts() {
            // 先判斷登錄狀態
            ly.verifyUser().then(() => {
                    // 已登錄

                }).catch(() => {
                    // 未登錄
                    this.carts = ly.store.get("carts") || [];
                    this.selected = this.carts;
                })
           }
    }
    components: {
        shortcut: () => import("/js/pages/shortcut.js")
    }
})

渲染carts的數據到頁面

修改數量

刪除商品

選中商品
在這裏插入圖片描述

已登錄購物車

添加登錄校驗

購物車系統只負責登錄狀態的購物車處理,因此需要添加登錄校驗,我們通過JWT鑑權即可實現。

  • 引入JWT相關依賴

我們引入之前寫的鑑權工具:leyou-auth-common

因爲很多接口都需要進行登錄,我們直接編寫SpringMVC攔截器,進行統一登錄校驗。同時,我們還要把解析得到的用戶信息保存起來,以便後續的接口可以使用。
在這裏插入圖片描述

後臺購物車設計

購物車是一個讀寫頻率很高的數據。因此我們這裏選擇讀寫效率比較高的Redis作爲購物車存儲。

  • 首先不同用戶應該有獨立的購物車,因此購物車應該以用戶的作爲key來存儲,Value是用戶的所有購物車信息。這樣看來基本的k-v結構就可以了。
  • 但是,我們對購物車中的商品進行增、刪、改操作,基本都需要根據商品id進行判斷,爲了方便後期處理,我們的購物車也應該是k-v結構,key是商品id,value纔是這個商品的購物車信息。

我們的購物車結構是一個雙層Map:Map<String,Map<String,String>>

  • 第一層Map,Key是用戶id
  • 第二層Map,Key是購物車中商品id,值是購物車數據

添加商品到購物車

這裏我們不訪問數據庫,而是直接操作Redis

  • 先查詢之前的購物車數據
  • 判斷要添加的商品是否存在
    • 存在:則直接修改數量後寫回Redis
    • 不存在:新建一條數據,然後寫入Redis
@Service
public class CartService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private GoodsClient goodsClient;

    static final String KEY_PREFIX = "leyou:cart:uid:";

    static final Logger logger = LoggerFactory.getLogger(CartService.class);

    public void addCart(Cart cart) {
        // 獲取登錄用戶
        UserInfo user = LoginInterceptor.getLoginUser();
        // Redis的key
        String key = KEY_PREFIX + user.getId();
        // 獲取hash操作對象
        BoundHashOperations<String, Object, Object> hashOps = this.redisTemplate.boundHashOps(key);
        // 查詢是否存在
        Long skuId = cart.getSkuId();
        Integer num = cart.getNum();
        Boolean boo = hashOps.hasKey(skuId.toString());
        if (boo) {
            // 存在,獲取購物車數據
            String json = hashOps.get(skuId.toString()).toString();
            cart = JsonUtils.parse(json, Cart.class);
            // 修改購物車數量
            cart.setNum(cart.getNum() + num);
        } else {
            // 不存在,新增購物車數據
            cart.setUserId(user.getId());
            // 其它商品信息,需要查詢商品服務
            Sku sku = this.goodsClient.querySkuById(skuId);
            cart.setImage(StringUtils.isBlank(sku.getImages()) ? "" : StringUtils.split(sku.getImages(), ",")[0]);
            cart.setPrice(sku.getPrice());
            cart.setTitle(sku.getTitle());
            cart.setOwnSpec(sku.getOwnSpec());
        }
        // 將購物車數據寫入redis
        hashOps.put(cart.getSkuId().toString(), JsonUtils.serialize(cart));
    }
}

查詢購物車

購物車頁面:cart.html

修改商品數量

刪除購物車商品

登錄後購物車合併

當跳轉到購物車頁面,查詢購物車列表前,需要判斷用戶登錄狀態,

  • 如果登錄:
    • 首先檢查用戶的LocalStorage中是否有購物車信息,
    • 如果有,則提交到後臺保存,
    • 清空LocalStorage
  • 如果未登錄,直接查詢即可

參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章