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',
})
}
})
},
效果如图所示:
***至此,购物商品选择、全选已结束
重要的是:将自己计算,选择时所有需要的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
});
},