前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【畅购商城】购物车模块之添加购物车

【畅购商城】购物车模块之添加购物车

作者头像
陶然同学
发布2023-02-24 13:30:11
2.2K0
发布2023-02-24 13:30:11
举报
文章被收录于专栏:陶然同学博客

购物车数据2种形态:

        登录态:保存到服务器端的redis中

        没登录:保存在浏览器端 localStorage 中

搭建购物车服务:8095

步骤一:创建changgou4-service-cart 项目

步骤二:修改pom.xml文件,添加坐标

代码语言:javascript
复制
<dependencies>
    <!--自定义项目-->
    <dependency>
        <groupId>com.czxy.changgou</groupId>
        <artifactId>changgou4-common-auth</artifactId>
    </dependency>
    <dependency>
        <groupId>com.czxy.changgou</groupId>
        <artifactId>changgou4-pojo</artifactId>
    </dependency>
    <!--web起步依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--redis-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
    </dependency>
    <!-- nacos 客户端 -->
    <dependency>
        <groupId>com.alibaba.nacos</groupId>
        <artifactId>nacos-client</artifactId>
    </dependency>

    <!-- nacos 服务发现 -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>

    <!-- openfeign 远程调用 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

    <!--swagger2-->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
    </dependency>

    <!--fastjson-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
    </dependency>

</dependencies>

步骤三:创建yml文件,

代码语言:javascript
复制
#端口号
server:
  port: 8095
spring:
  application:
    name: cart-service
  redis:
    host: 127.0.0.1
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848   #nacos服务地址
#自定义内容
sc:
  jwt:
    secret: sc@Login(Auth}*^31)&czxy% # 登录校验的密钥
    pubKeyPath: D:/rsa/rsa.pub # 公钥地址
    priKeyPath: D:/rsa/rsa.pri # 私钥地址
    expire: 360 # 过期时间,单位分钟

步骤四:拷贝JWT配合类 + Swagger + Redis

步骤五:启动类

代码语言:javascript
复制
package com.czxy.changgou4;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class CGCartServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(CGCartServiceApplication.class, args);
    }
}

添加到购物车

整体分析

接口

代码语言:javascript
复制
POST http://localhost:10010/cart-service/carts
{
    "skuid": 2600242,
    "count": 5,
    "checked": true
}

后端实现:JavaBean

购物车列表项对象:CartItem (某一件商品的购买情况:商品、购买数量 等)

代码语言:javascript
复制
package com.czxy.changgou4.cart;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Data
public class CartItem {
    private Integer skuid;
    private Integer spuid;
    @JsonProperty("goods_name")
    private String goodsName;
    private Double price;
    private Integer count;//购买数量
    private Boolean checked;
    private String midlogo;
    @JsonProperty("spec_info")
    private String specInfo;

}

购物车对象:Cart

代码语言:javascript
复制
package com.czxy.changgou4.cart;

import lombok.Data;

import java.util.HashMap;
import java.util.Map;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Data
public class Cart {

    private Map<Integer , CartItem > data = new HashMap<>();
    private Double total;

    public Double getTotal() {
        double sum = 0.0;
        for (CartItem cartItem : data.values()) {
            //只统计勾选的价格
            if(cartItem.getChecked()){
                sum += ( cartItem.getPrice() * cartItem.getCount());
            }
        }
        return sum;
    }

    public void addCart(CartItem cartItem) {
        CartItem temp = data.get(cartItem.getSkuid());
        if(temp == null) {
            data.put( cartItem.getSkuid() , cartItem);
        } else {
            temp.setCount( cartItem.getCount() + temp.getCount() );
        }
    }


    public void updateCart(Integer skuid, Integer count , Boolean checked) {
        CartItem temp = data.get(skuid);
        if(temp != null) {
            temp.setCount( count );
            temp.setChecked(checked);
        }
    }

    public void deleteCart(Integer skuid) {
        data.remove( skuid );
    }

}

购物车专门定制的对象

CartCategory

代码语言:javascript
复制
package com.czxy.changgou4.vo;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Data
public class CartCategory {

    private Integer id;

    @JsonProperty("cat_name")
    private String catName;

    @JsonProperty("parent_id")
    private Integer parentId;

    @JsonProperty("is_parent")
    private Boolean isParent;

    //当前分类具有的所有孩子
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    private List<CartCategory> children = new ArrayList<>();

}

CartSpecificationOption

代码语言:javascript
复制
package com.czxy.changgou4.vo;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Data
public class CartSpecificationOption {

    private Integer id;

    @JsonProperty("spec_id")
    private Integer specId;                //外键,规格ID

    private CartSpecification specification; //外键对应对象

    @JsonProperty("option_name")
    private String optionName;             //选项名称

}

CartSpecification

代码语言:javascript
复制
package com.czxy.changgou4.vo;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

import java.util.List;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Data
public class CartSpecification {

    private Integer id;

    @JsonProperty("spec_name")
    private String specName;                    //规格名称

    private Integer categoryId;                     //分类外键
    private CartCategory category;                      //分类外键对应对象


    private List<CartSpecificationOption> options;      //一个规格,具有多个规格选项

}

CartOneSkuResult

代码语言:javascript
复制
package com.czxy.changgou4.vo;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Data
public class CartOneSkuResult {

    private Integer skuid;
    private Integer spuid;
    @JsonProperty("goods_name")
    private String goodsName;
    private Double price;
    @JsonProperty("on_sale_date")
    private Date onSaleDate;
    @JsonProperty("comment_count")
    private Integer commentCount;
    @JsonProperty("comment_level")
    private Integer commentLevel;
    @JsonProperty("cat1_info")
    private CartCategory cat1Info;
    @JsonProperty("cat2_info")
    private CartCategory cat2Info;
    @JsonProperty("cat3_info")
    private CartCategory cat3Info;
    private Map<String, String> logo;
    private List<Map> photos;
    private String description;
    private String aftersale;
    private Integer stock;
    @JsonProperty("spec_list")
    private List<CartSpecification> specList;
    // id_list:'规格ID:选项ID|规格ID:选项ID|...',
    // id_txt:'规格名称:选项名称|规格名称:选项名称|...'
    @JsonProperty("spec_info")
    private Map<String, String> specInfo;
    @JsonProperty("sku_list")
    private List<Map<String, String>> skuList;

}

​​​​​​​后端实现

步骤一:创建CartVo,用于封装请求参数

代码语言:javascript
复制
package com.czxy.changgou4.vo;

import lombok.Data;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Data
public class CartVo {

    private Integer skuid ;     //"SKUID",
    private Integer count;      //"购买数量"
    private Boolean checked;    //"是否选中"

}

步骤二:创建SkuClient,用于查询详情

代码语言:javascript
复制
package com.czxy.changgou4.feign;

import com.czxy.changgou4.vo.BaseResult;
import com.czxy.changgou4.vo.OneSkuResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@FeignClient(value="web-service",path = "/sku")
public interface SkuClient {

    @GetMapping("/goods/{skuid}")
    public BaseResult<OneSkuResult> findSkuById(@PathVariable("skuid") Integer skuid);

}

步骤三:创建CartService接口,用于完成添加业务逻辑

代码语言:javascript
复制
package com.czxy.changgou4.service;

import com.czxy.changgou4.pojo.User;
import com.czxy.changgou4.vo.CartVo;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
public interface CartService {

    /**
     * 给指定用户添加商品
     * @param user
     * @param cartVo
     */
    public void addCart(User user , CartVo cartVo);
}

步骤四:创建CartService实现类

代码语言:javascript
复制
package com.czxy.changgou4.service.impl;

import com.alibaba.fastjson.JSON;
import com.czxy.changgou4.cart.Cart;
import com.czxy.changgou4.cart.CartItem;
import com.czxy.changgou4.feign.SkuClient;
import com.czxy.changgou4.pojo.User;
import com.czxy.changgou4.service.CartService;
import com.czxy.changgou4.vo.BaseResult;
import com.czxy.changgou4.vo.CartOneSkuResult;
import com.czxy.changgou4.vo.CartVo;
import com.czxy.changgou4.vo.OneSkuResult;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Service
@Transactional
public class CartServiceImpl implements CartService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private SkuClient skuClient;


    @Override
    public void addCart(User user, CartVo cartVo) {
        //1 获得购物车
        Cart cart;
        String key = "cart" + user.getId();
        String cartStr = stringRedisTemplate.opsForValue().get(key);
        // 处理是否有购物车,没有创建,有转换(jsonStr --> java对象 )
        if(cartStr != null){
            //如果有,将json字符串转换购物车对象
            cart = JSON.parseObject( cartStr , Cart.class);

        } else {
            //如果没有创建一个
            cart = new Cart();
        }

        //2 保存商品
        // 2.1 确定购物买商品
        BaseResult<CartOneSkuResult> entity = skuClient.findSkuById(cartVo.getSkuid());
        CartOneSkuResult oneSkuResult = entity.getData();

        // * 将OneSkuResult 转换成 CartItem
        CartItem cartItem = new CartItem();
        cartItem.setSkuid( oneSkuResult.getSkuid() );
        cartItem.setSpuid( oneSkuResult.getSpuid() );
        cartItem.setGoodsName( oneSkuResult.getGoodsName() );
        cartItem.setPrice( oneSkuResult.getPrice() );
        cartItem.setCount( cartVo.getCount() );        //购买数量,用户传递的
        cartItem.setChecked(true);
        cartItem.setMidlogo( oneSkuResult.getLogo().get("biglogo"));
        cartItem.setSpecInfo( JSON.toJSONString( oneSkuResult.getSpecInfo() ) );   //将对象转换json字符串

        // 2.2 添加到购物车
        cart.addCart( cartItem );

        System.out.println(JSON.toJSONString(cart) );
        //3 保存购物车
        stringRedisTemplate.opsForValue().set( key , JSON.toJSONString(cart) );

    }
}

步骤五:创建CartController

代码语言:javascript
复制
package com.czxy.changgou4.controller;

import com.czxy.changgou4.config.JwtProperties;
import com.czxy.changgou4.pojo.User;
import com.czxy.changgou4.service.CartService;
import com.czxy.changgou4.utils.JwtUtils;
import com.czxy.changgou4.vo.BaseResult;
import com.czxy.changgou4.vo.CartVo;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@RestController
@RequestMapping("/carts")
public class CartController {

    @Resource
    private CartService cartService;

    @Resource
    private HttpServletRequest request;

    @Resource
    private JwtProperties jwtProperties;

    @PostMapping
    public BaseResult addCart(@RequestBody CartVo cartVo){

        //1 获得用户信息
        // 1.1 获得token
        String token = request.getHeader("Authorization");
        // 1.2 解析token
        User loginUser = null;
        try {
            loginUser = JwtUtils.getObjectFromToken(token, jwtProperties.getPublicKey(),User.class);
        } catch (Exception e) {
            return BaseResult.error("token失效或未登录");
        }

        //2 添加操作
        cartService.addCart( loginUser , cartVo );

        //3 提示
        return BaseResult.ok("添加成功");


    }

}

步骤六:测试

​​​​​​​前端实现:购买数量

步骤一:修改Goods.vue ,为文本框添加键盘事件,用于校验输入的数据

代码语言:javascript
复制
<input type="text" name="amount" v-model="buyCount" @keyup.prevent="updateCount($event)" value="1" class="amount"/>

步骤二:修改Goods.vue ,完成updateCount函数

代码语言:javascript
复制
 updateCount : function(e){
      // e.target.value 获得用户输入的数据
      //使用正则处理数字
      if( /^\d+$/.test(e.target.value) ){
        //如果是数字,小于1,默认为1
        if( e.target.value < 1) {
          this.buyCount = 1;
        }
      } else {
        //默认为1
        this.buyCount = 1;
      }
    },

步骤三:检查+和-已完成功能

前端实现

步骤一:修改 api.js ,完成“添加到购物车”方法

代码语言:javascript
复制
  //添加到购物车
  addToCart : ( params ) => {
    return axios.post("/cart-service/carts", params )
  },

步骤二:修改Goods.vue,给“加入购物车”绑定点击事件 addToCartFn

代码语言:javascript
复制
<input type="submit" value="" class="add_btn" @click.prevent="addToCartFn"  />

步骤三:修改Goods.vue,完成addToCartFn功能

未登录:保存到sessionStorage

登录:保存到redis

待完善功能:用户登录时,将sessionStorage保存的商品信息合并到redis中

代码语言:javascript
复制
async addToCartFn(){
      //获得登录标识
      let token = sessionStorage.getItem("token");
      if(token != null){
        //登录:发送ajax进行添加
        let newGoods = {
          skuid: this.$route.query.id,
          count:this.buyCount
        };
        //登录状态下的添加商品到购物车操作
        let {data} = await this.$request.addToCart(newGoods)
        if(data.code == 20000){
          //location.href = "flow1"
          this.$router.push('flow1')
        } else {
          alert(data.data.errmsg);
        }
        return;
      }

      //未登录:在浏览器保存
      //1 准备添加物品数据
      var newGoods = {
        skuid: this.goodsInfo.skuid,
        goods_name:this.goodsInfo.goods_name,
        price:this.goodsInfo.price,
        count:this.buyCount,
        checked:true,
        midlogo:this.goodsInfo.logo.smlogo,
        spec_info: JSON.stringify(this.goodsInfo.spec_info)
      };
      //2 维护数据:本地已经存储信息 和 新添加信息 合并
      var cartStr = localStorage.getItem("cart");
      var cart;
      if(cartStr == null) {
        // 2.1 第一次添加,直接已数组方式添加
        cart = [newGoods];
      } else {
        //判断是否存在(将字符串转换数组、依次遍历)
        cart = JSON.parse(cartStr);
        //是否为新物品,默认为新的
        let isNew = true;

        cart.forEach( g => {
          //已有数据的id 和 新物品id 是否一样
          if(g.skuid == newGoods.skuid){
            //不是新物品
            isNew = false;
            // 2.3 已有,重复,先获得对应,修改数量
            g.count += parseInt(newGoods.count);
          }
        });

        if(isNew == true){
          // 2.2 已有,不重复,先获得数组,后追加
          cart.push(newGoods);
        }

      }
      //3 存放到浏览器
      var cartStr = JSON.stringify(cart);
      localStorage.setItem("cart" , cartStr );
      //4 跳转页面
      location.href = "flow1"
    }

步骤四:编写flow1页面

代码语言:javascript
复制
<template>
  <div>
    购物车
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-11-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 搭建购物车服务:8095
  • 添加到购物车
    • 整体分析
      • 接口
        • 后端实现:JavaBean
          • ​​​​​​​后端实现
            • ​​​​​​​前端实现:购买数量
              • 前端实现
              相关产品与服务
              云数据库 Redis
              腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档