微信小程序购物车商品单选、多选、数量变化、结算等

1、本文只是提供一种思路,具体实现因原型各异;
2、首先是购物车中商品单选、全选、反选
(1)、假设后台提供的数据结构如下:

dataList: [
   {
      id: "01fedabc742d42938061b6599798651e",
      image: "https://jianyouquan.oss-cn-beijing.aliyuncs.com/timg (4).jpg",
      name: '[{id:"28d9bdb5c21e4a25b6066506b241e3aa",value:"烟台"},{"id":"4930e7aa3b424ceb92b49de9b5f3716b","value":"小号"}]',
      price: 6,
      qty: 11,
      skuid: "2a71da35c9ad4feaa02bb137971378fd",
      stock: 99,
      title: "西域美农 甘肃天水花牛苹果 非美国蛇果 新鲜水果宝宝辅"
    },
    {
      id: "01fedabc742d42938061b6599798651e",
      image: "https://jianyouquan.oss-cn-beijing.aliyuncs.com/timg (4).jpg",
      name: '[{"id":"28d9bdb5c21e4a25b6066506b241e3aa","value":"烟台"},{"id":"4930e7aa3b424ceb92b49de9b5f3716b","value":"小号"}]',
      price: 6,
      qty: 11,
      skuid: "2a71da35c9ad4feaa02bb137971378fd",
      stock: 99,
      title: "西域美农 甘肃天水花牛苹果 非美国蛇果 新鲜水果宝宝辅"
    }
  ]

(2)、首先为数据结构中增加方便计算价格、选中标识的键;

/**
 * 需要增加字段;
 * chooseFright: 0,  // 当前项的价格 数量 * 单价
 * isChooseGoods: false // 当前项是否选中
 * */ 

代码如下:

let carLists = [];
let dataList = res.data.dataList
 if (dataList) {
    dataList.map((i) => {
      let name = ''
      JSON.parse(i.name).map((item,index) => {
        // 属性名拼接
        name = name + ',' + item.value
      });
      // 去掉属性名拼接中第一个逗号
      let reg = new RegExp(",","");
      name = name.replace(reg,"");
      i.name = name;
      i = {...i , chooseFright: 0, isChooseGoods: false};
      carLists.push(i);
    })
    that.setData({
      carLists: carLists,
    })
  }

Dom结构如下:

<view class="container">
  <view class="order_box" wx:if="{{carLists && carLists.length>0}}">
    <view class="order_li cro_border_bottom" wx:for="{{carLists}}" wx:key="id" >
      <view class="goods_main" >
        <view class="selct_box">
        // 选中标识
          <image class="select_icon" wx:if="{{item.isChooseGoods}}" data-cars-id="{{item.id}}" catchtap="onChooseGoods" src="../../images/select-a.png" lazy-load="true" ></image>
          // 未选中
          <image class="select_icon" wx:else data-cars-id="{{item.id}}" catchtap="onChooseGoods" src="../../images/select-g.png"  lazy-load="true" ></image>
        </view>
        <view class="goods_info" catchtap="toSeeGoodsDetail" data-goods-id="{{item.productId}}">
          <image class="goods_img" src="{{item.image}}"  lazy-load="true" ></image>
          <view class="goods_detail" >
            <view class="goods_name">
              {{item.title}}
            </view>
            <view class="goods_modul"><view class="module_name">{{item.name}}</view>
            </view>
            <view class="goods_num_price">
              <view class="goods_price">{{item.price}}
              </view>
              <view class="goods_num">
                <!-- <text class="min" >-</text><text class="num" >15</text><text class="add" >+</text> -->
                x {{item.qty}}
              </view>
            </view>
          </view>
        </view>
        <view class="delete_box" data-cart-id="{{item.id}}" catchtap="onDelete">
          <image class="delect_icon" src="../../images/delete-icon.png" lazy-load="true" ></image>
        </view>
      </view>
    </view>
  </view>
  <view class="order_box" wx:if="{{carLists.length ==0}}">
    <view class="no_tip" >
      购物还没有商品!
    </view>
  </view>
</view>
<view class="h128"></view>
  
<view class="account_box">
  <view class="selct_box account_select" bindtap="onChooseAll">
    <view >
      <image class="select_icon" wx:if="{{!isChooseAll}}"  src="../../images/select-g.png" lazy-load="true" ></image>
      <image class="select_icon" wx:if="{{isChooseAll}}"  src="../../images/select-a.png" lazy-load="true" ></image>
      <view class="all_selected">
        全选
      </view>
    </view>
  </view>
  <view class="account_right">
    <!-- <text class="total_num" >合计:</text><text class="total_price" >{{totalPrice}}</text> -->
    <text class="total_num" >合计:</text><text class="total_price" >{{totalPrice}}</text>
    <view class="account_btn" bindtap="toSettleAccounts">
      去结算
    </view>
  </view>
</view>

(3)、单个商品选中与反选事件;

 onChooseGoods(event) {
  // 选中商商品
  let that = this;
  let eventData = event.currentTarget.dataset;
  let carsId = eventData.carsId;
  let { carLists } = that.data;
   // 逐个选择时;判断是不是所有的都选中了
  let choosedArr = [];
  carLists.map((i, ind) => {
    if (i.id === carsId) {
      if (i.isChooseGoods) {
        i['isChooseGoods'] = false;
      } else {
        i['isChooseGoods'] = true;
        // "status":"0",//是否下架 0否 1是 如果后台提供库存字段需要判断当前是否有库存
        // if(i.status === '0') {
          
        // } else {
        //   toastTip('该商品已经下架', 'none');
        // }
        
      }
    }
    if(i.isChooseGoods) {
      choosedArr.push(i.isChooseGoods)
    }
  })
  if (choosedArr.length === carLists.length) {
    that.setData({
      isChooseAll: true
    });
  } else {
    that.setData({
      isChooseAll: false
    });
  }
  that.setData({carLists});
  // 计算总费用
  that.sumTotalPrice();
},

(4)、选择、取消时计算选中商品的价钱;

sumTotalPrice() {
  let that = this;
  // 选中商品的总价,一定要先置 0;否则会导致重复计算
   that.setData({
     totalPrice: 0
   })
   let { totalPrice, carLists } = that.data;
     let totalFright = 0;
     carLists.map((i, ind) => {
       if (i.isChooseGoods) {
         i['chooseFright'] = i.price * i.qty;
         // 这里是自己写的工具,计算商品相加的总和,是为了避免 1+2 不等于3的这种情;
         // 很简单
         totalPrice = tool.getGoodsPayPriceSum(totalPrice, i.chooseFright);
       }
     })
   that.setData({totalPrice});
 },

(5)、全选操作;

onChooseAll(){
  // 全选,反选;
  let that = this;
  if (that.data.isChooseAll) {
    that.setData({
      isChooseAll: false
    });
  } else {
    that.setData({
      isChooseAll: true
    });
  }
  // 计算对应的最运费
  that.dataListsMap(that.data.isChooseAll);
},
dataListsMap(isChooseAll) {
   // 遍历 将所有的选中 并重新计算总费用;
   let that = this;
   let { carLists } = that.data;
   carLists.map((i) => {
     i['isChooseGoods'] = isChooseAll;
   })
   
   that.setData({carLists});
   that.sumTotalPrice();
 },

(6)、结算操作;

toSettleAccounts() {
    // 去结算购物车;
    let that = this;
    let { carLists, totalPrice } = that.data;
    let choosedDataLists = [];
    carLists.map((i, ind) => {
      if (i.isChooseGoods) {
        // 选中的商品
        choosedDataLists.push(i);
      }
    })
    // 将选中的商品存储起来,确认订单时使用;
    globalInfo.payCarLists = choosedDataLists;
    wx.navigateTo({
      url: '/pages/confirmOrderCar/confirmOrderCar?routerName=SHOPPING_CART',
      fail() {
        wx.redirectTo({
          url: '/pages/confirmOrderCar/confirmOrderCar?routerName=SHOPPING_CART',
        })
      }
    })
  },

效果如图所示:微信小程序购物车商品单选、多选、数量变化、结算等_第1张图片
微信小程序购物车商品单选、多选、数量变化、结算等_第2张图片
***至此,购物商品选择、全选已结束
重要的是:将自己计算,选择时所有需要的key,提前放入列表中;


3、本文提供的是在购物车中商品的数量是不能更改的,只有确认订单时候才能更改数量,等!
(1)、假设购物车结算时,选中的商品数据结构如下:

payCarLists: [
  {
    chooseFright: 24,
    id: "1480b5b90a4c4f8eb0a2fd5c982858b4",
    image: "https://jianyouquan.oss-cn-beijing.aliyuncs.com/timg (7).jpg",
    isChooseGoods: true,
    name: "灵宝,66,墨红",
    price: 12,
    qty: 2,
    skuid: "ff4b3857f9e54713bd68b850b3452082",
    stock: 104,
    title: "积分商品周大福(CHOW TAI FOOK)圣诞礼物 心心相守 足金黄金戒指",
  },
  {
    chooseFright: 84,
    id: "586c7d7008f242f590a3563fc8f38623",
    image: "https://jianyouquan.oss-cn-beijing.aliyuncs.com/2019070106.jpg",
    isChooseGoods: true,
    name: "灰色,XL,东郡",
    price: 12,
    qty: 7,
    skuid: "b9af776a66234b0a8bee5cf714b9721b",
    stock: 92,
    title: "T恤衫2"
  }
],

DOM结构如下所示:非常简单,看英文应该就能明白相关意思

<view class="container">
  <view class="container_li">
    <!-- 选择快递时才显示地址栏 -->
    <view class="order_address cro_border_bottom p_right30 p_left30"  bindtap="toChouseAddress">
    <!-- <view class="order_address cro_border_bottom p_right30 p_left30"  wx:if="{{sendVal === 'EXPRESS'}}" bindtap="toChouseAddress"> -->
      <!-- 地址信息 -->
      <!-- <view class="no_address" wx:if="{{!addressInfo.id}}"> -->
      <view class="no_address" wx:if="{{!addressInfo.id}}">
        <view class="no_left">
          <image class="address_icon v_m" src="../../images/position.png" ></image><text class="address_tip v_m" >选择您的收货地址</text>
        </view>
        <image class="next_icon v_m" src="../../images/next.png" ></image>
      </view>
      <!-- <view class="address" wx:elif="{{ addressInfo.id}}"> -->
      <view class="address" wx:elif="{{ addressInfo.id}}">
        <view class="no_left">
          <view class="left_flex">
            <image class="address_icon v_m" src="../../images/position.png" ></image>
            <view class="address_left v_m">
              <view class="address_detail">
                {{addressInfo.province_city_town}}{{addressInfo.address}}
              </view>
              <view class="user_info">
                {{addressInfo.name}}\t{{addressInfo.phone}}
              </view>
            </view>
          </view>
        </view>
        <image class="next_icon v_m" src="../../images/next.png" ></image>
      </view>
    </view>

    <view class="order_box">
      <view class="order_li">
        <view class="goods_info cro_border_bottom" wx:for="{{payCarLists}}" wx:key="id">
          <image class="goods_img" src="{{item.image}}"  lazy-load="true" alt="goodsImg" ></image>
          <view class="goods_detail">
            <view class="goods_name">
              {{item.title}}
            </view>
            <view class="goods_modul">
              {{itemname}}
            </view>
            <view class="goods_num_price">
              <view class="goods_price">{{item.price}}
              </view>
              <view class="goods_num">
                <text class="min" bindtap="onMin" data-cars-id="{{item.id}}">-</text><text class="num" >{{item.qty}}</text><text class="add" bindtap="onAdd" data-cars-id="{{item.id}}">+</text>
              </view>
            </view>
          </view>
        </view>
        <view class="distribution_type cro_border_bottom p_right30 p_left30">
          <!-- 快递-->
          <text class="left_name" >配送方式</text>
          <text class="left_name price_title" >快递</text>
        </view>
        <view class="distribution_type cro_border_bottom p_right30 p_left30" catchtap="toChooseDiscountCanUse">
          <!-- {{discountInfo.id}} -->
          <text class="left_name" wx:if="{{discountInfo.id }}">优惠券减免</text>
          <text class="left_name" wx:else>选择优惠券</text>
          <view class="distribution_right">
            <text class="discount_num" wx:if="{{discountInfo.id}}">-{{discountInfo.amount}}</text>
            <image class="next_icon f_r" src="../../images/next.png" ></image>
          </view>
            
          
        </view>
        <view class="lists p_right30 p_left30 cro_border_bottom">
          <view class="price_li">
            <!-- 选中规格价格 * 数量 -->
            <text class="left_name " >商品金额</text>
            <text class="left_name price_title" >{{goodsPrice}}</text>
          </view>
          <!-- <view class="price_li" wx:if="{{sendVal === 'EXPRESS'}}"> -->
          <view class="price_li" >
            <text class="left_name " >邮费</text>
            <text class="left_name price_title" >{{postage}}</text>
          </view>
          <!-- <view class="price_li" >
            <text class="left_name " >优惠券</text>
            <text class="left_name price_title" >-{{discountPrice}}</text>
          </view> -->
          <view class="price_li">
            <text class="left_name " >共计</text>
            <text class="left_name price_title" >{{totalPrice}}</text>
          </view>
        </view>

        <!-- <view class="remark_box">
          <text class="remark_title">留言(选填)</text>
          <input class="remark_inp" type="text" bindinput="remarkInput" value="{{remark}}"></input>
        </view>
           -->
      </view>
    </view>
  </view>
</view>
<view class="fixed_footer">
  <view class="total_price">{{totalPrice}}
  </view>
  <view class="submit_btn" bindtap="submitOrder">
    提交订单
  </view>
</view>

(2)、首先是确认订单中商品数量的变更;

onMin(event) {
  // 减少数量
  let that = this;
  // console.log('event:', event);
  let eventData = event.currentTarget.dataset;
  let carsId = eventData.carsId;
  let { payCarLists } = that.data;
  
  payCarLists.map((i, ind) => {
    if (i.id === carsId) {
      if (i.qty > 1) {
        i['qty'] = i.qty - 1;
        i['chooseFright'] = i.qty * i.price;
        // 更新购物车列表数据
        that.changeNumServe(carsId, i['qty']);
      } else {
        toastTip('购买数量不能小于1', 'none');
      }
    }
  })
  
  that.setData({payCarLists});
  that.sumTotalPrice();
},
  onAdd(event) {
 // 增加数量
  let that = this;
  let eventData = event.currentTarget.dataset;
  // console.log('event:', event);
  let carsId = eventData.carsId;
  let { payCarLists } = that.data;
  payCarLists.map((i, ind) => {
    if (i.id === carsId) {
      if (i.stock > i.qty) {
        // i['qty'] = tool.getGoodsPayPriceSum(i.qty, 1);
        i['qty'] = Number(i.qty) + 1;
        i['chooseFright'] = i.qty * i.price;
        // 更新购物车列表数据 请求了后台接口,为了当放弃购买时,购物中当前商品数量保持一致
        that.changeNumServe(carsId, i['qty']);
      } else {
        toastTip('库存不足!', 'none');
      }
    }
  });
   
  that.setData({payCarLists});
  // 计算费用
  that.sumTotalPrice();
},

(3)、费用随时更新变化;

sumTotalPrice() {
    // totalPrice 包含运费和价格 邮费、优惠券减免
     /**
	   * @param {Number} postage 邮费 不累加
	   * @param {Number} totalPrice 总费用
	   * @param {Array} payCarLists 确认订单的商品列表
	   * @param {Object} discountInfo 选中的优惠券信息
	   * @param {Number}} goodsPrice 所有商品价格 总和
	   * @param {Number} goodsAndPostage 所有商品价格  和 邮费总和
	  */
    let that = this;
    that.setData({
      totalPrice: 0,
      goodsPrice:0
    })
    let { totalPrice, payCarLists, postage, discountInfo, goodsPrice, goodsAndPostage } = that.data;
    
    payCarLists.map((item, index) => {
      // 所有商品价格
      goodsPrice = tool.getGoodsPayPriceSum(item.chooseFright, goodsPrice);
    })
    // 商品金额和邮费
    // let goodsAndPostage;
     goodsAndPostage = tool.getGoodsPayPriceSum(postage, goodsPrice);
    that.setData({goodsAndPostage});
    if (discountInfo && discountInfo.id) {
      // 有优惠券
      if (Number(goodsAndPostage) >= Number(discountInfo.price)) {
        // 优惠券可以使用
        totalPrice = tool.getGoodsMinPrice(goodsAndPostage, discountInfo.amount);
      } else {
        // 优惠券不能使用
        toastTip('优惠券不能使用,满'+ goodsAndPostage + '元,才能使用。');
        totalPrice = goodsAndPostage;
      }
    } else {
      totalPrice = goodsAndPostage;
    }
    that.setData({
      totalPrice:totalPrice
    });
  },

至此商品订单确认已结束:
效果如下:
微信小程序购物车商品单选、多选、数量变化、结算等_第3张图片
欢迎各位大佬批评指教;相关源码请移步github

你可能感兴趣的:(小程序,javascript,小程序)