微信小程序实现购物车功能

 在我的GitHub上有校园二手交易微信小程序的源码,这里面包含了购物车的功能,GitHub地址:https://github.com/zhuyuzhu/Secondhand-goods-on-campus,该项目的pages文件夹下的shoppingCart文件夹就是购物车的代码。

购物车功能实现的逻辑:

(1)从服务器拿到的物品数据data里面,只有物品的信息,我们需要给每个物品数据中加入一个是否选中的属性

这样当我们在点击选择按钮的时候,就可以选中该物品,当再次点击的时候,就可以取消选择。

其中几个主要的功能:

(1)物品请求数据,使用微信小程序request请求,POST方式得到服务器传来的物品数据。

每次请求要想后端传入用户id和物品id(物品id根据后端要求进行处理,我每次传入请求到的物品中最后一个物品的id,后端会把这个id之后的5个值再传给前端)才得到的物品数据,每一次请求要判断还有没有数据,有数据则请求成功,没有数据就不请求。

(2)选中和取消选中单个物品

(3)选中或取消选中物品时,总价格要进行加减

每次触发选择事件,都会触发计算总价的方法

(4)全选按钮,实现物品的全选

当用户通过单选选择了所有物品时,“全选按钮”会自动改变为选中样式;当用户通过“全选按钮”选择所有商品的时候,每个商品都应该是选中状态。

(5)计算总价

任何一次触发该函数,都会重新计算价格,将总价变为0,再进行选中项的价格累加,而不是在原总价上累加或减某一个商品的价格

wxml代码: 

<!--pages/shoppingCart/shoppingCart.wxml-->
<view class='box'>
  <view class='wrapper'>
    <view class="tab-content {{selectBook? 'select': 'noSelect'}}" bindtap='chooseBookCart'>书本</view>
    <view class="tab-content {{selectThing? 'select': 'noSelect'}}" bindtap='chooseThingCart'>物品</view>

  </view>
</view>
<!-- 书本 -->
<view class="cart-box" wx:if="{{selectBook}}">
  <!-- wx:for 渲染购物车列表 -->
  <view wx:for="{{carts}}" wx:key="{{carts}}" class='cart-goods'>
    <!-- wx:if 是否选择显示不同图标 -->
 <view class='icon-wrapper' bindtap="selectList" data-index="{{index}}">
    <icon wx:if="{{item.selected}}" class='cart-icon' type="success" color="red"  />
    <icon wx:else type="circle" class='cart-icon'  />
    </view>
    <view  class='cart-img'>
      <image class="cart-thumb" src="{{item.picture}}"></image>
      <view class='cart-message'>
        <text class='name'>书名:{{item.bname}}</text>
        <text class='author'>作者:{{item.author}}</text>
        <text class='press'>出版社:{{item.press}}</text>
        <text class='price'>价格:¥{{item.bprice}}</text>
      </view>
    </view>
    <!-- 点击商品图片可跳转到商品详情 -->
    
    <!-- 删除按钮 -->
    <text bindtap="deleteList" data-index="{{index}}" class='delete'> × </text>
  </view>
  <view wx:if="{{isMyCartShow}}" class='bottom'>没有书本啦~_~</view>
</view>
<!-- 物品 -->
<view class="cart-box" wx:if="{{selectThing}}">
  <!-- wx:for 渲染购物车列表 -->
  <view wx:for="{{thingCarts}}" wx:key="{{thingCarts}}" class='cart-goods'>
    <!-- wx:if 是否选择显示不同图标 -->
     <view class='icon-wrapper' bindtap="selectListThing" data-index="{{index}}">
    <icon wx:if="{{item.selected}}" class='cart-icon' type="success" color="red"  />
    <icon wx:else type="circle" class='cart-icon'  />
    </view>

    <view  class='cart-img'>
      <image class="cart-thumb" src="{{item.gpicture}}"></image>
      <view class='cart-message'>
        <text class="name">{{item.gname}}</text>
        <text class="author">校区:{{item.gcollege}}</text>
        <text class='author'>成色:{{item.gstatus}}</text>
        <text class='author'>发布者:{{item.usersname}}</text>
        <text class='price'>¥{{item.gprice}}</text>
      </view>
    </view>
    <!-- 点击商品图片可跳转到商品详情 -->
    
    <!-- 删除按钮 -->
    <text bindtap="deleteListThing" data-index="{{index}}" class='delete'> × </text>
  </view>
  <view wx:if="{{isThingCartShow}}" class='bottom'>没有物品啦~_~</view>
</view>
<!-- 底部操作栏 -->
<view class='cart-bottom'>
  <!-- wx:if 是否全选显示不同图标 -->
  <icon wx:if="{{selectAllStatus}}" class='cart-iconAll' type="success_circle" color="red" bindtap="selectAll" />
  <icon wx:else type="circle" class='cart-iconAll' color="#ff7100" bindtap="selectAll" />
  <text class='cart-allSelect' bindtap="selectAll">全选</text>
  <!-- 总价 -->
  <text class='cart-allPrice'>合计:</text>
  <text class='allPrice'>¥{{totalPrice}}</text>
  <button class='btn-red' bindtap='toBuy' form-type='submit'>去结算</button>
</view>

 wxss代码:

/* pages/shoppingCart/shoppingCart.wxss */
.wrapper {
  position: fixed;
  top: 0rpx;
  display: flex;
  width: 100%;
  height: 50rpx;
  justify-content: space-around;
  background-color: #fff;
  z-index: 9999;
}
.select {
 
  text-align: center;
  width: 50%;
  background-color: green;
  color: #fff;
}
.noSelect {
  width: 50%;
  text-align: center;
}
.cart-box {
   margin-top: 50rpx;
  margin-bottom: 100rpx;
}
.cart-goods {
  display: flex;
  flex-direction: row;
  padding: 30rpx;
  border-bottom: 3rpx solid #e6e6e6;
}
.icon-wrapper {
  line-height: 260rpx;
}
 .cart-icon {
    display: inline-block;
    margin: auto 10rpx;
    margin-left: -10rpx;
  }
 .cart-img {
   display: flex;
  width: 580rpx;
  height: 260rpx;
}
.cart-img image{
  margin: auto 0rpx;
  width: 165rpx;
  height: 225rpx;
}
 .cart-goods .cart-message {
  width: 380rpx;
  display: flex;
  flex-direction: column;
  margin: 0 20rpx;
  justify-content: space-around;
  
}
 .name{
  font-weight: 600;
  color: #4a4a4a;
  font-size: 32rpx;
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}
 .author,
 .press{
    font-size: 28rpx;
    color: #9e9e9e;
    font-weight: 300;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden; 
  }
  .price {
    font-size: 28rpx;
    color: #f40;
    font-weight: 300;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden; 
  }
  .delete {
    position: absolute;
    right: 40rpx;
    margin-top: -10rpx;
  }
  .cart-bottom {
    position: fixed;
    width: 100%;
    height: 100rpx;
    background-color: white;
    bottom: 0rpx;
  }
  .cart-allPrice {
  float:left;
   padding: 0.5rem;
    font-weight: 100;
    margin-left: 70rpx;
  }
  .allPrice {
     float:left;
    padding: 0.5rem;
    font-weight: 100;
   margin-left: -30rpx;
   color: #f40;
  }
  .cart-allSelect {
    float:left;
    padding: 0.5rem;
    margin-left: -23rpx;
     font-weight: 100
  }
  .cart-iconAll {
    float:left;
    padding: 0.5rem;
   margin-top: 7rpx;
  }
  .btn-red {
  background-color: #f44336; /* 红色 */
  font-size: 40rpx;
}
button {
  position: fixed;
  right: 0;
  color: white;
  text-align: center;
  display: inline-block;
  font-size: 30rpx;
  border-radius: 0rpx;
  width: 30%;
  height: 100rpx;
  line-height: 100rpx;
}
.cart-list {
  display: flex;
  flex-direction: column;
}
.bottom {
 
  color: #666;
  text-align: center;
  font-size: 30rpx;

}

微信js代码:

// pages/shoppingCart/shoppingCart.js
var app = getApp();
const orginalPrice = 0; //由于0.00在赋值时是0,用toFixed()取余
Page({

  /**
   * 页面的初始数据
   */
  data: {
    selectTab: true,
    selectBook: true,
    selectThing: false, 

    carts: [], // 购物车列表
    hasList: false, // 列表是否有数据
    totalPrice: orginalPrice.toFixed(2), // 总价,初始为0
    selectAllStatus: false, // 全选状态,默认全选
    bookId: '',
    isMyCartShow: false,
    studentId: '', 
    myCartBookLength: '5',
    bookPrice: 0,

    thingId: '',
    thingCarts: [], // 物品列表
    isThingCartShow: false,
    myCartThingLength: '5',
    thingPrice: 0,
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {

    
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
    var that = this;
    var studentId = that.data.studentId;
    var hasList = that.data.hasList;
    try {
      var value = wx.getStorageSync('studentIdSync')
      if (value) {
        console.log(value); //同步得到studentId的值
        that.setData({
          studentId: value
        })
      }
    } catch (e) {
      console.log(0);
    }
    this.getBookCartList()
  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {
    // 动态设置导航条标题
    wx.setNavigationBarTitle({
      title: '购物车'
    });
    wx.showNavigationBarLoading(); //在标题栏中显示加载图标
    setTimeout(function(){
      wx.stopPullDownRefresh(); //停止加载
      wx.hideNavigationBarLoading(); //隐藏加载icon
    },2000)
  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {
    if (this.data.selectBook){
      this.getBookCartList()
    }else {
      this.getThingCartList()
    }
    
  },
getBookCartList(){
  console.log(1);
  var that = this;
  var url = app.globalData.huanbaoBase + 'getbooksbystudentid.php'
  var ismyCartShow = that.data.ismyCartShow;
  var carts = that.data.carts;
  var bookId = that.data.bookId;
  var myCartBookLength = that.data.myCartBookLength;
  var studentId = that.data.studentId;
  console.log(bookId, myCartBookLength);
  // if (myCartBookLength < 5) {
  //   that.setData({
  //     isMyCartShow: true
  //   })
  //   return
  // }
  wx.showToast({
    title: '加载中',
    icon: 'loading',
    duration: 1000,
  })
  
  wx.request({
    url,
    method: 'POST',
    header: { 'content-type': 'application/x-www-form-urlencoded ' },
    data: { //此处设置,一定要与后台一一对应,属性名和属性的先后位置。
      studentId: studentId,
      lastId: bookId,
    },
    success: res => {
      var carts = that.data.carts || [];
      var data = res.data.data;  
      console.log(data);
      if(data === undefined) {
        wx.hideToast()
        that.setData({
          isMyCartShow: true
        })
        return 
      }
      that.setData({
        myCartBookLength: data.length  //每次获取5组值
      })
      myCartBookLength = data.length; 
      that.setData({
        bookId: res.data.data[myCartBookLength - 1].bookid
      })
      console.log(myCartBookLength);
      data.forEach(item => {
          let messege = {
          selected: false,
          ...item
        }
        carts.push(messege); //实现购物车的最近添加的物品,展现在最前面
      })

      that.setData({
        carts:  carts ,
      })
     
    },
    fail: err => {
      console.log(err);
    }
  })
},
  getThingCartList() {
    console.log(1);
    var that = this;
    var url = app.globalData.huanbaoBase + 'getthingsbystudentid.php'
    var isThingCartShow = that.data.isThingCartShow;
    var thingCarts = that.data.thingCarts;
    var thingId = that.data.thingId;
    var myCartThingLength = that.data.myCartThingLength;
    var studentId = that.data.studentId;
    var selectBook = that.data.selectBook;
    var selectThing = that.data.selectThing;
    
    console.log(thingId, myCartThingLength);
    // if (myCartThingLength < 5) {
    //   that.setData({
    //     isThingCartShow: true
    //   })
    //   return
    // }
    wx.showToast({
      title: '加载中',
      icon: 'loading',
      duration: 1000,
    })

    wx.request({
      url,
      method: 'POST',
      header: { 'content-type': 'application/x-www-form-urlencoded ' },
      data: { //此处设置,一定要与后台一一对应,属性名和属性的先后位置。
        studentId: studentId,
        lastId: thingId,
       },
      success: res => {
        var thingCarts = that.data.thingCarts || [];
        var data = res.data.data;
        console.log(data);
        if (data === undefined) {
          wx.hideToast()
          that.setData({
            isThingCartShow: true
          })
          return
        }
        that.setData({
          myCartThingLength: data.length  //每次获取5组值
        })
        myCartThingLength = data.length;
        that.setData({
          thingId: res.data.data[myCartThingLength - 1].goodid
        })
        console.log(myCartThingLength);
        data.forEach(item => {
          let messege = {
            selected: false,
            ...item
          }
          thingCarts.push(messege); //实现购物车的最近添加的物品,展现在最前面
        })

        that.setData({
          thingCarts: thingCarts,
        })

      },
      fail: err => {
        console.log(err);
      }
    })
  },
  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {

  },
  //计量总价
  getTotalPrice() {
    let carts = this.data.carts; // 获取购物车列表
    let thingPrice = parseFloat(this.data.thingPrice);
    let bookPrice = parseFloat(this.data.bookPrice);
    let total = 0.00;
    for (let i = 0; i < carts.length; i++) { // 循环列表得到每个数据
      if (carts[i].selected) { // 判断选中才会计算价格
       
        total += parseFloat(carts[i].bprice); // 所有价格加起来
      }
    }
    this.setData({
      bookPrice: total.toFixed(2)
    })
    total += thingPrice;
    this.setData({ // 最后赋值到data中渲染到页面
      carts: carts, 
      totalPrice: total.toFixed(2) //保留小数后面2两位
    });
  },
  //选择事件
  selectList(e) {
    let that = this;
    const index = e.currentTarget.dataset.index;    // 获取data- 传进来的index
    console.log(index);
  
    let selectAllStatus = that.data.selectAllStatus; //是否已经全选
    let str = true;  //用str与每一项进行状态判断
    let carts = that.data.carts;                    // 获取购物车列表
    const selected = carts[index].selected;         // 获取当前商品的选中状态
    carts[index].selected = !selected;              // 改变状态
    that.setData({
      carts: carts
    });
    that.getTotalPrice();                           // 重新获取总价
    for (var i = 0; i < carts.length; i++) {
      str = str && carts[i].selected;           //用str与每一项进行状态判断
    }
  
    if (str === true) {
      that.setData({
        selectAllStatus: true
      })
    } else {
      that.setData({
        selectAllStatus: false
      })
    }
  },
  //全选事件
  selectAll(e) {
    var that = this;
    let selectAllStatus = that.data.selectAllStatus;    // 是否全选状态
    let carts = that.data.carts;
    let thingCarts = that.data.thingCarts;
    var selectThing = that.data.selectThing;
    var selectBook = that.data.selectBook;
  if(selectBook) {
    selectAllStatus = !selectAllStatus;
    for (let i = 0; i < carts.length; i++) {
      carts[i].selected = selectAllStatus;            // 改变所有商品状态
    }
    that.setData({
      selectAllStatus: selectAllStatus,
      carts: carts
    });
    that.getTotalPrice();                               // 重新获取总价
    if (carts.length === 0) { //当没有物品时,不能再点“全选”
      wx.showModal({
        title: '提示',
        content: '购物车空空如也~',
        success: function (res) {   //模糊层成功出来后
          if (res.confirm) {
            console.log('用户点击确定')
            that.setData({
              selectAllStatus: false
            })
          } else {
            console.log('用户点击取消')
            that.setData({
              selectAllStatus: false
            })
          }
        },
      })
    }
  }else {
    selectAllStatus = !selectAllStatus;
    for (let i = 0; i < thingCarts.length; i++) {
      thingCarts[i].selected = selectAllStatus;            // 改变所有商品状态
    }
    that.setData({
      selectAllStatus: selectAllStatus,
      thingCarts: thingCarts
    });
    that.getTotalPriceThing();                               // 重新获取总价
    if (thingCarts.length === 0) { //当没有物品时,不能再点“全选”
      wx.showModal({
        title: '提示',
        content: '购物车空空如也~',
        success: function (res) {   //模糊层成功出来后
          if (res.confirm) {
            console.log('用户点击确定')
            that.setData({
              selectAllStatus: false
            })
          } else {
            console.log('用户点击取消')
            that.setData({
              selectAllStatus: false
            })
          }
        },

      })

    }
  }
  },

  //删除商品
  deleteList(e) {
    const index = e.currentTarget.dataset.index;
    var selectAllStatus = this.data.selectAllStatus;
    let carts = this.data.carts;
    let totalPrice = this.data.totalPrice;
    wx.showModal({
      title: '提示',
      content: '将此产品移除购物车?',
      success: res=> {
        if (res.confirm) {
          console.log('用户点击确定')
          carts.splice(index, 1);              // 删除购物车列表里这个商品
          this.setData({
            carts: carts
          });
          if (carts.length == 0) {                  // 如果购物车为空
            this.setData({
              hasList: false,             // 修改标识为false,显示购物车为空页面
              selectAllStatus: false,
              totalPrice: orginalPrice.toFixed(2)              //此时价格为0
            });
          } else {                              // 如果不为空
            this.getTotalPrice();           // 重新计算总价格
          }
        } else if (res.cancel) {
          console.log('用户点击取消')
        }
      }
    })
  },

// 物品
  //计量总价
  getTotalPriceThing() {
    let thingCarts = this.data.thingCarts; // 获取购物车列表
    let total = 0; //注意后台返回的是字符串数字。
    let thingPrice = parseFloat(this.data.thingPrice);
    let bookPrice = parseFloat(this.data.bookPrice);
    for (let i = 0; i < thingCarts.length; i++) { // 循环列表得到每个数据
      if (thingCarts[i].selected) { // 判断选中才会计算价格  
        total += parseFloat(thingCarts[i].gprice); // 所有价格加起来  
      }
    }
    this.setData({
      thingPrice: total
    })
    total += bookPrice;
    this.setData({ // 最后赋值到data中渲染到页面
      thingCarts: thingCarts,
      totalPrice: total.toFixed(2) //保留小数后面2两位
    });
  },
  //选择事件
  selectListThing(e) {
    let that = this;
    const index = e.currentTarget.dataset.index;    // 获取data- 传进来的index
    console.log(index);

    let selectAllStatus = that.data.selectAllStatus; //是否已经全选
    let str = true;  //用str与每一项进行状态判断
    let thingCarts = that.data.thingCarts;                    // 获取购物车列表
    const selected = thingCarts[index].selected;         // 获取当前商品的选中状态
    thingCarts[index].selected = !selected;              // 改变状态
    that.setData({
      thingCarts: thingCarts
    });
    that.getTotalPriceThing();                           // 重新获取总价
    for (var i = 0; i < thingCarts.length; i++) {
      str = str && thingCarts[i].selected;           //用str与每一项进行状态判断
    }
    console.log(str);
    if (str === true) {
      that.setData({
        selectAllStatus: true
      })
    } else {
      that.setData({
        selectAllStatus: false
      })
    }
  },


  //删除商品
  deleteListThing(e) {
    const index = e.currentTarget.dataset.index;
    var selectAllStatus = this.data.selectAllStatus
    let thingCarts = this.data.thingCarts;
    let totalPrice = this.data.totalPrice;
    wx.showModal({
      title: '提示',
      content: '将此产品移除购物车?',
      success: res=> {
        if(res.confirm){
          console.log("用户点了确定")
          thingCarts.splice(index, 1);              // 删除购物车列表里这个商品
          this.setData({
            thingCarts: thingCarts
          });
          if (thingCarts.length == 0) {                  // 如果购物车为空
            this.setData({
              hasList: false,             // 修改标识为false,显示购物车为空页面
              selectAllStatus: false,
              totalPrice: orginalPrice.toFixed(2)              //此时价格为0
            });
          } else {                              // 如果不为空
            this.getTotalPrice();           // 重新计算总价格
          }
        }else if(res.cancel) {
          console.log("用户点了取消")
        }
      }
    })
  },
  chooseBookCart() {
    var that = this;
    var selectBook = that.data.selectBook;
    var selectThing = that.data.selectThing;
    let selectAllStatus = that.data.selectAllStatus; //是否已经全选
    let str = true;  //用str与每一项进行状态判断
    let carts = that.data.carts;  
    for (var i = 0; i < carts.length; i++) {
      str = str && carts[i].selected;           //用str与每一项进行状态判断
    }
    console.log(str);
    that.setData({
      selectBook: true,
      selectThing: false, 
    })
   
  },
  chooseThingCart() {
    var that = this;
    var selectThing = that.data.selectThing;
    var selectBook = that.data.selectBook;
    var selectAllStatus = that.data.selectAllStatus;
    
    that.setData({
      selectBook: false,
      selectThing: true,
      
    })
    // 此时data中的数据改变,但是此时的属性值还未改变
    
    that.getThingCartList()
    
  },
  toBuy(){
    var totalPrice = this.data.totalPrice;
    var thingCarts = this.data.thingCarts;
    var bookCarts = this.data.carts;
    var bookId = this.data.bookId;
    var bookCart = [], thingCart = [];
    bookCarts.forEach(item=>{
      if (item.selected){
        bookCart.push(item);
      }
    })
    thingCarts.forEach(item=>{
      if (item.selected){
        thingCart.push(item);
      }
    })
    let shoppingCartList = {thingCart, bookCart};
    
    console.log(bookCart);
    if(totalPrice === '0.00'){
     console.log(totalPrice);

    }else {
      console.log(shoppingCartList);
      wx.navigateTo({
        url: '../settlement/settlement?bookCart='+bookCart,
      })
    }

  }
})

后端代码和数据库有时间再写吧。。。 

猜你喜欢

转载自blog.csdn.net/zyz00000000/article/details/82532998