微光集市-登陆后用户对购物车的操作(版本4.0)


登陆后用户对购物车的操作

1 获得登录用户购买商品数量,及将固定用户修改为当前用户

1.1 客户端

1.1.1 ui界面的改变

<el-badge :value="carCount" class="item">
    <el-button type="success" 
               icon="el-icon-shopping-cart-full"  
               @click="$router.push('/showCar')">
        购物车
    </el-button>
</el-badge>

1.1.2 得到后端数据,并做出处理

data(){
    
    
        return{
    
    
            curUserInfo:null,//用户信息
            carCount:0,//当前用户购物车中商品数量 
        }
    },
    methods: {
    
    
      getCurUserInfo(){
    
    
        this.curUserInfo= JSON.parse(window.sessionStorage.getItem("curUserInfo"));
        if(this.curUserInfo!=null){
    
    
          //获得当前用户商品数量
          this.getCarCount();
        }
      },
      getCarCount(){
    
    
        this.$axios
                .get("car/getCarCount")
                .then(response=>{
    
    
                    this.carCount =response.data;
                })
                .catch(err=>{
    
    
                    console.log(err)
                })
      },
    }

1.2 服务端

1.2.1 Controller添加获得商品数量方法

  @GetMapping("/getCarCount")
    public Integer getCarCount(HttpSession session){
    
    
       CurUserInfo curUserInfo = (CurUserInfo) session.getAttribute("curUserInfo");
       return carService.getCarCount(curUserInfo.getUser_id());
   }

1.2.2 Service层进行对应修改

  • CarService
Integer getCarCount(Integer user_id);
  • CarServiceImpl
@Override
public Integer getCarCount(Integer user_id) {
    
    
    //redis获取当前购物车
    Map<Integer, Car> carMap = (Map<Integer, Car>) hashOperations.get("cars", "user:" + user_id);
	return carMap.size();
}

1.2.3 将原本设置的固定用户修改为当前用户

  • Controller层
@RestController
@RequestMapping("/car")
public class CarController {
    
    
    @Resource
    private CarService carService;
    //注入session
    @Resource
    private HttpSession session;

    @PostMapping("/addCar")
    public Result addCar(@RequestBody Car car) {
    
    
        try {
    
    
            //session获得当前用户信息
            CurUserInfo curUserInfo = (CurUserInfo) session.getAttribute("curUserInfo");
            car.setUser_id(curUserInfo.getUser_id());
            carService.addCar(car);
            return Result.success();
        } catch (Exception e) {
    
    
            e.printStackTrace();
            return Result.fail(500, "商品添加失败!!!");
        }
    }

    @GetMapping("/queryCarInfo")
    public List<Car> queryCarInfo() {
    
    
        CurUserInfo curUserInfo = (CurUserInfo) session.getAttribute("curUserInfo");
        return carService.queryCarInfo(curUserInfo.getUser_id());
    }

   @PutMapping("/updateCarCount")
    public Result updateCarCount(@RequestBody Car car){
    
    
       try {
    
    
           CurUserInfo curUserInfo = (CurUserInfo) session.getAttribute("curUserInfo");
           car.setUser_id(curUserInfo.getUser_id());
           carService.updateCarCount(car);
           return Result.success();
       } catch (Exception e) {
    
    
           e.printStackTrace();
           return Result.fail(500, "数字不能为0");
       }
   }

   @DeleteMapping("/delCarByBookId")
   public Result delCarByBookId(Integer book_id){
    
    
       try {
    
    
           CurUserInfo curUserInfo = (CurUserInfo) session.getAttribute("curUserInfo");
           carService.delCarByBookId(curUserInfo.getUser_id(),book_id);
           return Result.success();
       } catch (Exception e) {
    
    
           e.printStackTrace();
           return Result.fail(500, "删除失败!!");
       }
   }

   @GetMapping("/getCarCount")
    public Integer getCarCount(){
    
    
       CurUserInfo curUserInfo = (CurUserInfo) session.getAttribute("curUserInfo");
       return carService.getCarCount(curUserInfo.getUser_id());
   }
}

2 购物车实现-计算要购买商品的总价格

2.1 客户端

2.1.1 购物车页面添加总价UI

<el-table
:data="carList"
border 
style="width: 100%"
empty-text="暂无商品"
@selection-change="getSum"><!--添加获得总价事件-->

<div class="down">
    <div class="carSum">
    <label style="color: black">合计:</label>
    <label style="color: red; margin-top: 20px; font-size: 10px ;"></label>
    <label style="color: red;">0</label>
    <el-button type="warning" size="small" round="true" style="margin-right: 80px; margin-left: 10px;font-size: 15px;" >&nbsp;结算&nbsp;</el-button>
    </div>
</div>

<style scoped>
.down{
      
      
        position:fixed;
        bottom:0px;
        width:100%;
        height: 50px;
        background-color:rgba(0, 0, 0, 0.3);
        /* opacity: 0.3; */
        text-align: right;
        
}
.carSum{
      
      
    margin: 10px auto;
}
</style>

2.1.2 选择商品后得到所需商品总价处理

data(){
    
    
	return{
    
    
   		sum:0,
	}
}
getSum(selection){
    
    
  this.sum=0;
  //遍历选择的项并计算价格
  for(let row of selection){
    
    
      this.sum= this.sum+row.book_price*row.car_count;
  }
}

2.1.3 修改购物车里更新数量

此时出现问题,当我们修改数量时,由于以前所做是修改数量,让数据重新查询,会页面刷新,导致本来选择的商品不选择,下面我们对以前功能做出修改

  • 我们让改变事件的方法传递数据改为row

    <template slot-scope="scope">
        <el-input-number size="small" v-model="scope.row.car_count" :min="1" @change="updateCarCount(scope.row)"></el-input-number>
    </template>
    
  • 对应方法做出改变

    updateCarCount(row){
          
          
                this.$axios
                    .put('car/updateCarCount',
                    {
          
          "book_id":row.book_id,
                    "car_count": row.car_count})
                    .then(response => {
          
          
                        let result=response.data;
                        if(result.success){
          
          
                            // this.queryCars();
                            row.total=row.book_price*row.car_count;
                        }else{
          
          
                             this.$notify.error({
          
          
                                title: '错误',
                                message: '请输入有效数字'
                            });
                        }
                    })
                    .catch(error => {
          
          
                        console.log(error)
                    })
              }
    

此时问题,页面不刷新了,但是改变数量,下面总价不随之改变

  • 设置一数组,存储选中商品
 data(){
    
    
        return{
    
    
            sum:0,
            salBooks:[],//要购买商品的数组
        }
 }
  • 向选择的商品赋给数组
getSum(selection){
    
    
                //将选择商品赋给数组
                this.salBooks=selection;
                this.sum=0;
                //遍历选择的项并计算价格
                for(let row of selection){
    
    
                    this.sum= this.sum+row.book_price*row.car_count;
                }
          }
  • 点击修改数量,计算总价格
updateCarCount(row){
    
    
   this.$axios
       .put('car/updateCarCount',
       {
    
    "book_id":row.book_id,
       "car_count": row.car_count})
       .then(response => {
    
    
           let result=response.data;
           if(result.success){
    
    
               // this.queryCars();
               row.total=row.book_price*row.car_count;
               //清空原来总价
               this.sum =0;
               //改变总价格,如果修改数量商品时被修改的才修改总价格
               for(let salBook of this.salBooks){
    
    
                   //改变价格
                   this.sum =this.sum +salBook.book_price*salBook.car_count; 
               }
           }else{
    
    
                this.$notify.error({
    
    
                   title: '错误',
                   message: '请输入有效数字'
               });
           }
       })
       .catch(error => {
    
    
           console.log(error)
       })
}

3 从购物车到购买确认购买页面的处理

3.1 客户端

3.1.1 点击进入确认购买页面

 <el-button type="warning" size="small" round 
 style="margin-right: 80px; margin-left: 10px;font-size: 15px;" 
 :disabled="sum == 0 ? true : false" 
 s@click="$router.push({path:'/ConfirmSal',query:{
     
     'salBooks':salBooks}})">
 &nbsp;结算&nbsp;
 </el-button>

3.1.2 确认购买页面及配置路由

  • ConfirmSal页面
<template>
    <div class="showCar-Container"> 
        <div class="car_list">
            <el-table
                :data="salBooks"
                border
                style="width: 100%"
                empty-text="暂无商品"
                @selection-change="getSum"><!--添加获得总价事件-->

                <el-table-column
                align="center"
                type="selection">
                </el-table-column>

                <el-table-column
                    align="center"
                    type="index"
                    label="序号">
                </el-table-column> 

                <el-table-column
                    align="center"
                    prop="book_name"
                    label="商品名称">
                </el-table-column>

                <el-table-column
                    align="center"
                    label="商品照片">
                    <template slot-scope="scope">
                        <img :src="require('@/assets/images/books/'+scope.row.book_image)" class="image">
                    </template>    
                </el-table-column>

                <el-table-column
                    align="center"
                    prop="book_price"
                    label="单价">
                </el-table-column>
                
                <el-table-column
                    align="center"
                    prop="car_count"
                    label="购买数量">
                   
                </el-table-column>            

                <el-table-column
                    align="center" 
                    label="总计">
                    <template slot-scope="scope">
                        {
   
   { scope.row.car_count* scope.row.book_price }}
                    </template>
                </el-table-column>  
                
            </el-table>
        </div>
        <div class="down">
            <div class="carSum">
            <label style="color: black">合计:</label>
            <label style="color: red; margin-top: 20px; font-size: 10px ;"></label>
            <label style="color: red;">{
   
   { sum }}</label>
            <el-button 
                type="warning" 
                size="small" 
                round 
                style="margin-right: 80px; margin-left: 10px;font-size: 15px;" 
                :disabled="sum == 0 ? true : false">
                &nbsp;结算&nbsp;
            </el-button>
            <el-button 
             type="info" 
             size="small" 
             round 
             style="margin-right: 80px; margin-left: 10px;font-size: 15px;" 
             @click="$router.push('/showCar')">
             &nbsp;返回购物车&nbsp;   
            </el-button>    
            </div>
        </div>
    </div>
</template>

<script>
export default {
      
      
}
</script>

<style scoped>
.showCar-Container{
      
      
     margin:0;padding:0;height:100%;width:100%;
    
}
.down{
      
      
        position:fixed;
        bottom:0px;
        width:100%;
        height: 50px;
        background-color:rgba(0, 0, 0, 0.3);
        /* opacity: 0.3; */
        text-align: right;
        
}
.carSum{
      
      
    margin: 10px auto;
}
 .image{
      
      
    width: 80px;
    height: 80px;
 }
</style>
  • 配置路由
import ConfirmSal from "../views/ConfirmSal.vue"

const routes = [
  {
    
    
    path: "/confirmSal",
    name: "confirmSal",
    component: ConfirmSal,
  },
];

3.1.3 处理购物车传来的数据

export default {
    
    
    data(){
    
    
        return{
    
    
            sum:0,
            salBooks:[],//要购买商品的数组
        }
    },methods:{
    
    
          getSum(){
    
    
                    this.sum=0;
                for(let salBook of this.salBooks){
    
    
                    this.sum=this.sum+salBook.book_price*salBook.car_count;
                }          
          },                
    },created(){
    
    
           this.salBooks=this.$route.query.salBooks;
           this.getSum();
    }
}

4 添加订单

4.1 客户端

4.1.1 点击结算进入添加订单UI

<el-button 
                type="warning" 
                size="small" 
                round 
                style=" margin-left: 10px;font-size: 15px;" 
                :disabled="sum == 0 ? true : false"
                @click="drawer = true">
                &nbsp;结算&nbsp;
</el-button>


<div>
  <el-drawer
       title="添加联系人信息"
       :visible.sync="drawer"
       :direction="direction">
       <el-form ref="form" :model="order" label-width="120px">
          <el-form-item label="收货人姓名">
               <el-input v-model="order.order_to_name"></el-input>
          </el-form-item>
          <el-form-item label="收货人联系方式">
              <el-input v-model="order.order_to_phone"></el-input>
          </el-form-item>
           <el-form-item label="收货人联系地址">
               <el-input v-model="order.order_to_address"></el-input>
           </el-form-item>                
           <el-button type="warning" style="width:100%" @click="sale">确认购买</el-button>
       </el-form>    
   </el-drawer>
</div>


data(){
            drawer: false,//是否显示抽屉
            direction: 'rtl',//设置抽屉的方向
}

4.1.2 向服务端传递数据并做出成功处理

地址,联系方式,姓名,要购买的订单

data(){
    
    
 return{
    
    
       salBooks:[],//要购买商品的数组
       order: {
    
    },//订单对象
       }
}
/**
 * 确认购买按钮
 */
sale(){
    
    
    //要购买的商品编号
    let book_ids=[];
    for(let salBook of this.salBooks){
    
    
         book_ids.push(salBook.book_id)
    }    
    //订单参数
    let orderParam={
    
    "order":this.order,"book_ids":book_ids}
        this.$axios.post("/order/addOrder", orderParam)
         .then(response=>{
    
    
                 let result=response.data; 
                 if(result.success){
    
                   
                     //弹出提示框
                     this.$swal.fire({
    
    
                         icon: 'success',
                         title: result.message,
                         showConfirmButton: false,
                         timer:1000,
                         didClose:()=>{
    
    
                             this.$router.push("/ShowCar")
                         }
                     });
                 }else{
    
    
                     this.$swal.fire({
    
    
                         icon: 'error',
                         title: result.message,
                         showConfirmButton: false,
                         timer: 1000,
                     });
                 }
         })
         .catch(error=>{
    
    
             console.log(error)
         })
},

4.2 服务端

4.2.1 创建公共类-OrderParam

@Data
@AllArgsConstructor
@NoArgsConstructor
public class OrderParam implements Serializable {
    
    
         private Integer[]  book_ids;
         private Orders order;//订单
}

4.2.2 创建model-Orders

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Orders implements Serializable {
    
    
    private String order_id;
    private Integer user_id;
    private String order_to_name;
    private String order_to_address;
    private String order_to_phone;
    private Date order_time;
    private Integer order_status;
    private Double order_total_price;
}

4.2.3 创建model-OrderDesc

@AllArgsConstructor
@NoArgsConstructor
@Data
public class OrderDesc implements Serializable {
    
    
    private Integer desc_id;
    private String order_id;
    private Integer book_id;
    private Integer count;
}

4.2.4 创建Controller-OrderController

@RestController
@RequestMapping("/order")
public class OrderController {
    
    
    @Resource
    private OrderService orderService;
    @Resource
    private HttpSession session;
    @PostMapping("/addOrder")
    public Result addOrder(@RequestBody OrderParam orderParam ){
    
    
        try {
    
    
            CurUserInfo curUserInfo = (CurUserInfo) session.getAttribute("curUserInfo");
            Orders order=orderParam.getOrder();
            //设置订单用户id
            order.setUser_id(curUserInfo.getUser_id());
            List<OrderDesc> orderDescList =new ArrayList<>();
            //将book_id封装到订单明细集合中
            for (int book_id :orderParam.getBook_ids()){
    
    
                OrderDesc orderDesc =new OrderDesc();
                orderDesc.setBook_id(book_id);
                orderDescList.add(orderDesc);
            }
            orderService.addOrder(order,orderDescList);
            return Result.success("订单添加成功");
        } catch (Exception e) {
    
    
            e.printStackTrace();
            return Result.fail(500,"订单添加失败");
        }
        
    }
}

4.2.3 创建Service层

  • OrderService
public interface OrderService {
    
    
    void addOrder(Orders orders, List<OrderDesc> orderDescList) throws Exception;
}

4.2.4 OrderServiceImpl实现具体功能

具体思路:

  • 1.补全订单及其相关属性
  • 2.向数据库添加订单和订单明细
  • 3.从redis中删除已购买商品
4.2.4.1 添加生成订单编号工具类

设置订单编号

/**
 * 生成订单编号工具类
 */
public class GenerateOrderId {
    
    
    private static int num=0;
    private static final int MIN_NUM=0;
    private static final int MAX_NUM=10000000;
    public static synchronized String getOrderId(){
    
    
        String timeStr =new SimpleDateFormat("yyyyMMddHHmmssSS").format(new Date());
        if (num>=MAX_NUM){
    
    
            num=MIN_NUM;
        }
        String orderId =timeStr+num;

        try {
    
    
            TimeUnit.MILLISECONDS.sleep(10);
        } catch (InterruptedException e) {
    
    
        }
        num++;
        return orderId;
    }
}
4.2.4.2 在carServcie添加根据用户id和图书id查询购物车信息

设置订单数量,需要从redis中读取(需要购买商品id)的信息里面有订单数量

  • carServcie
Car getCarInfoById(int user_id,int book_id);
  • carServiceImpl
    @Override
    public Car getCarInfoById(int user_id, int book_id) {
    
    
        //得到对应用户的购物车
        Map<Integer, Car> carMap = (Map<Integer, Car>) hashOperations.get("cars", "user:" + user_id);
        return carMap.get(book_id);
    }
4.2.4.3 向数据库添加订单和订单明细
  • OrderMapper
@Repository
public interface OrderMapper {
    
    
    //添加订单
    @Insert("insert into myshopping.tbl_order values (#{order_id},#{user_id},#{order_to_name},#{order_to_address},#{order_to_phone},now(),default,#{order_total_price})")
    void addOrder(Orders orders);
}
  • OrderDescMapper
@Repository
public interface OrderDescMapper {
    
    

     public void addOrderDesc(List<OrderDesc> descList);
}
  • OrderDescMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.shopping.mapper.OrderDescMapper">
    <insert id="addOrderDesc">
            INSERT INTO myshopping.tbl_order_desc values
            <foreach collection="descList"   item="desc" separator=",">
                (default,#{desc.order_id},#{desc.book_id},#{desc.count})
            </foreach>
    </insert>
</mapper>
4.2.4.4 OrderServiceImpl实现具体功能

此处会出现当订单添加成功或者但是订单信息没添加成功,不具有原子性

因此此处使用事务,使添加订单和添加订单信息,要么都添加成功,要么都添加失败

@Service
@Transactional //声明式事务,使用该注解,当前类中所有方法,都属于一个独立的事务
public class OrderServiceImpl implements OrderService {
    
    

    @Resource
    private CarService carService;
    @Resource
    private OrderDescMapper orderDescMapper;
    @Resource
    private OrderMapper orderMapper;
    /**
     * 添加订单
     *  1.补全订单及其相关属性
     *  2.向数据库添加订单和订单明细
     *  3.从redis中删除已购买商品
     * @param orders
     * @param orderDescList
     * @throws Exception
     */
    @Override
    public void addOrder(Orders orders, List<OrderDesc> orderDescList) throws Exception {
    
    
        orders.setOrder_id(GenerateOrderId.getOrderId());//订单编号
        double total = 0;
        //遍历orderDescList并添加订单明细相关属性数据
        for (OrderDesc orderDesc:orderDescList){
    
    
            //设置订单编号
            orderDesc.setOrder_id(orders.getOrder_id());
            //从redis中读取购物车数据
            Car car = carService.getCarInfoById(orders.getUser_id(), orderDesc.getBook_id());
            //设置购买数量
            orderDesc.setCount(car.getCar_count());
            total=total+car.getCar_count()*car.getBook_price();
        }
        //设置订单总价格
        orders.setOrder_total_price(total);

        //向数据库添加数据
        orderMapper.addOrder(orders);
        orderDescMapper.addOrderDesc(orderDescList);

        //从redis中删除购买商品
        for (OrderDesc orderDesc:orderDescList){
    
    
            carService.delCarByBookId(orders.getUser_id(),orderDesc.getBook_id());
        }
    }
}

猜你喜欢

转载自blog.csdn.net/woschengxuyuan/article/details/129326807