商城类的小程序,想要购买东西,都必须要有购物车这个环节
先来弄清楚购物车有哪些需求
单选,全选和取消,而且随着选中的商品计算价格
单个商品购买数量的增加和减少
商品的优惠部分计算价格
删除商品,当购物车为空时应该应该显示的页面
wxml部分:
<block wx:if="{{list.length>0}}">
<!--购物车列表-->
<view class="list-group-area">
<view class="edit-area">
<view class="edit-clear">
<view>共{{totalInfo.kindCount}}种商品</view>
</view>
<view bindtap="changeEdit">{{isEdit?'完成':'编辑'}}</view>
</view>
<!--列表-->
<view class="shop-goods-group " wx:for="{{list}}" wx:key="unique" wx:for-item="cartListItem"
wx:for-index="cartIndex">
<view class="shop-area">
<!--选中状态-->
<image class="cart-select-icon" mode="widthFix"
src="{{iconUrl}}{{cartListItem.checked?'img/comm/icon_xz_radio_h.png':'img/comm/icon_xz_radio_n.png'}}"
catchtap="changeCartStatus" data-cart-index="{{cartIndex}}" wx:if="{{!isEdit}}"></image>
<image wx:else class="cart-select-icon" mode="widthFix"
src="{{iconUrl}}{{cartListItem.manageChecked?'img/comm/icon_xz_radio_h.png':'img/comm/icon_xz_radio_n.png'}}"
catchtap="changeCartStatus" data-cart-index="{{cartIndex}}"></image>
<view class="shop-coupon">
<view class="shop">
<view catchtap="redirect" data-params="{{pageKeys.ONLINESHOP_BRAND_DETAIL}}"
data-args="brandId={{cartListItem.shopId}}">
<image class="shop-comm-icon" mode="widthFix"
src="{{iconUrl}}img/order/icon_shop.png"></image>
{{cartListItem.shopName}}
<image class="direction" mode="widthFix" src="{{iconUrl}}img/comm/right_jt.png"></image>
</view>
<view class="shop-tip" wx:if="{{cartListItem.onlineCouponInfoList.length>0&&!isEdit}}"
catchtap="showCouponModal" data-cart-index="{{cartIndex}}">领券
</view>
</view>
<!--优惠信息-->
<view class="coupon-area" wx:if="{{cartListItem.onlineCouponInfoList.length>0}}">
<text style="background: {{baseColor}}">优惠</text>
<view class="coupon-list">
<swiper vertical="true" autoplay="true">
<block wx:for="{{cartListItem.onlineCouponInfoList}}" wx:key="unique"
wx:for-item="couponItem">
<swiper-item>
{{couponItem.name}}
</swiper-item>
</block>
</swiper>
</view>
</view>
</view>
</view>
<!--商户下的商品-->
<view class="goods-area potive" wx:for="{{cartListItem.cartItemList}}" wx:for-item="cartItem"
wx:key="{{cartItem.id}}">
<!--<block wx:if="{{cartItem.onlineCartSkuInfoResp.skuCheckStatus==13}}">-->
<image class="cart-select-icon" mode="widthFix" wx:if="{{!isEdit}}"
catchtap="{{cartItem.onlineCartSkuInfoResp.skuCheckStatus==13 ? 'updateData' :''}}"
data-cart-index="{{cartIndex}}" data-type="{{updateType.updateChecked}}"
data-goods-index="{{index}}" data-checked="{{cartItem.checked}}"
src="{{iconUrl}}{{cartItem.checked?'img/comm/icon_xz_radio_h.png':'img/comm/icon_xz_radio_n.png'}}"></image>
<image class="cart-select-icon" mode="widthFix" wx:else
catchtap="{{cartItem.onlineCartSkuInfoResp.skuCheckStatus==13 ? 'updateData' :''}}"
data-cart-index="{{cartIndex}}" data-type="{{updateType.updateChecked}}"
data-goods-index="{{index}}" data-checked="{{cartItem.manageChecked}}"
src="{{iconUrl}}{{cartItem.manageChecked?'img/comm/icon_xz_radio_h.png':'img/comm/icon_xz_radio_n.png'}}"></image>
<!--</block>-->
<view class="goods-info {{(cartItem.onlineCartSkuInfoResp.skuCheckStatus!=13||cartItem.onlineCartSkuInfoResp.stockNum==0)?'filter-gray':''}}"
catchtap="redirect" data-params="{{pageKeys.ONLINESHOP_GOODS_DETAIL}}"
data-args="goodsId={{cartItem.onlineCartSkuInfoResp.goodsId}}">
<image class="icon" mode="aspectFill" src="{{cartItem.onlineCartSkuInfoResp.image}}"></image>
<view class="info-wrapper">
<view class="name">
<text class="house" wx:if="{{cartItem.onlineCartSkuInfoResp.isHouse == 1}}">自营</text>
{{cartItem.onlineCartSkuInfoResp.name}}
</view>
<block wx:for="{{cartItem.onlineCartSkuInfoResp.skuSpecList}}" wx:key="unique"
wx:for-item="specItem" wx:for-index="specIndex">
<text class="spec" wx:if="{{specItem.value > 0}}">{{specItem.value}}{{specItem.name}}
</text>
<text class="spec" wx:else>
<text wx:if="{{cartItem.onlineCartSkuInfoResp.skuSpecList.length > 1}}">
{{specItem.name}}:
</text>
{{specItem.value}}
</text>
</block>
<view class="price-count">
<view class="price-area">
¥{{cartItem.onlineCartSkuInfoResp.activityPriceStr?cartItem.onlineCartSkuInfoResp.activityPriceStr:cartItem.onlineCartSkuInfoResp.sellPriceStr}}
<!--原始价格,需要跟活动价或者销售价做比较-->
<view class="original-price"
wx:if="{{(cartItem.onlineCartSkuInfoResp.activityPriceStr&&cartItem.onlineCartSkuInfoResp.originPriceStr!=cartItem.onlineCartSkuInfoResp.activityPriceStr)||(cartItem.onlineCartSkuInfoResp.sellPriceStr&&cartItem.onlineCartSkuInfoResp.sellPriceStr!=cartItem.onlineCartSkuInfoResp.originPriceStr)}}">
¥{{cartItem.onlineCartSkuInfoResp.originPriceStr}}
</view>
<!--<block class="delme" wx:if="{{cartItem.onlineCartSkuInfoResp.skuCheckStatus != 13}}" bindtap="deleteme">删除</block>-->
</view>
<!--加减操作-->
<view class="count-area"
wx:if="{{cartItem.onlineCartSkuInfoResp.skuCheckStatus==13&&cartItem.onlineCartSkuInfoResp.stockNum!=0}}">
<block wx:if="{{!isEdit}}">
<button class="btn add-btn" catchtap="updateData" data-goods-index="{{index}}"
data-isadd="{{false}}" data-cart-index="{{cartIndex}}"
data-type="{{updateType.updateCount}}" data-count="{{cartItem.count}}">-
</button>
<text>{{cartItem.count}}</text>
<button class="btn sub-btn" catchtap="updateData" data-goods-index="{{index}}"
data-isadd="{{true}}" data-count="{{cartItem.count}}"
data-cart-index="{{cartIndex}}" data-type="{{updateType.updateCount}}">+
</button>
</block>
<block wx:else>
x{{cartItem.count}}
</block>
</view>
</view>
</view>
<!--商品状态-->
<image class="status-img" wx:if="{{cartItem.onlineCartSkuInfoResp.skuCheckStatus!=13}}"
src="{{iconUrl}}img/goods/Screening_Icon_ygq.png"></image>
<image class="status-img" wx:elif="{{cartItem.onlineCartSkuInfoResp.stockNum==0}}"
src="{{iconUrl}}img/goods/sell_out_icon.png"></image>
</view>
<view class="delme" data-cart-index="{{cartIndex}}" data-type="{{updateType.updateChecked}}"
data-goods-index="{{index}}" data-checked="{{cartItem.checked}}"
wx:if="{{cartItem.onlineCartSkuInfoResp.skuCheckStatus != 13}}" bindtap="deleteme">删除
</view>
</view>
</view>
</view>
<!--底部-->
<view class="navbar-fixed-bottom total-btn-area {{isPhoneX?'fix-iphonex':''}}" wx:if="{{totalInfo}}">
<view class="select-area" bindtap="changeCartStatus">
<image class="cart-select-icon" mode="widthFix" wx:if="{{!isEdit}}"
src="{{iconUrl}}{{totalInfo.checked?'img/comm/icon_xz_radio_h.png':'img/comm/icon_xz_radio_n.png'}}"></image>
<image class="cart-select-icon" mode="widthFix" wx:else
src="{{iconUrl}}{{totalInfo.manageChecked?'img/comm/icon_xz_radio_h.png':'img/comm/icon_xz_radio_n.png'}}"></image>
全选
</view>
<!--编辑模式-->
<block wx:if="{{isEdit}}">
<button class="btn btn-sm" style="background: {{baseColor}}" bindtap="delete">删除</button>
</block>
<!--非编辑模式-->
<block wx:else>
<view class="display-flex">
<view class="total-num">合计:
<text>¥{{totalInfo.priceStr||0}}</text>
</view>
<view class="addressprice">不含运费</view>
<button class="btn btn-sm {{totalInfo.count<=0?'btn-disabled':''}}" bindtap="redirectFillOrder"
style="background: {{baseColor}}" data-params="{{pageKeys.ONLINESHOP_FILLING_ORDER}}"
data-args="buyType=4">
结算({{totalInfo.count||0}})
</button>
</view>
</block>
</view>
</block>
<dataStatus wx:if="{{dataStatus.type}}" type="{{dataStatus.type}}" module="{{dataStatus.module}}"/>
<block wx:if="{{list.length>0 && cartAdBottom}}">
<image class="bottom-service-image" mode="aspectFill" src="{{cartAdBottom}}"></image>
</block>
js部分:
Page({
/**
* 页面的初始数据
*/
data: {
iconUrl: app.globalData.iconUrl,
baseColor: '',
baseColorSub: '',
dataStatus: {
module: appPush.pageKeys.ONLINESHOP_CART,
type: ''
},
isPhoneX: app.globalData.isPhoneX,
pageKeys: appPush.pageKeys,
scrollTop: 0, //页面在垂直方向已滚动的距离
list: [],
listParams: { //购物车列表参数
page: 0,
pagesize: 1000
},
isAll: false, //是否全选
isEdit: false, //是否是编辑模式
shopCouponList: [], //店铺优惠券列表
showCouponModal: false, //是否展示优惠券模态框
totalInfo: null, //合计信息
uid: '', //用户ID
updateType: updateType //数据更新类型
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
wx.hideShareMenu();
app.notRefreshPrePage();
let that = this;
if (!app.globalData.multiMallChecked) {
app.checkMultiMallFinished(options).then(res => {});
}
that.setData({
iconUrl: app.globalData.iconUrl,
baseColor: app.globalData.baseColor,
baseColorSub: app.globalData.baseColorSub,
mallInfo: app.globalData.currentMallInfo
});
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
let that = this;
if (userCommService.isLogin()) {
let uid = userCommService.getUid();
that.setData({
uid: uid,
list: [],
totalInfo: null,
isEdit: false,
['listParams.page']: 0
});
that.getList(that.data.listParams);
}
this.setData({
cartAdBottom: app.globalData.cartAdBottom
});
//如果购物车图片素材已加载 则不在加载
if (!app.globalData.cartAdBottom) {
this.getCartAdBottom();
}
},
deleteme(e) {
let that = this;
that.setData({
isEdit: true
})
that.updateData(e)
that.delete(e)
that.setData({
isEdit: false
})
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
this.setData({
showCouponModal: false
})
},
/**
* 页面滚动触发事件的处理函数
* @param e
*/
onPageScroll: function (e) {
this.setData({
scrollTop: e.scrollTop || 0,
opacity: (e.scrollTop >= 120) ? 0 : ((e.scrollTop / 240) || 1)
});
},
/**
* 阻断事件向下传递
*/
preventTouchMove() {
return false;
},
/**
* 改变全选/反选,购物车项和全部的购物车列表
* @param e
*/
changeCartStatus(e) {
let that = this,
totalInfo = that.data.totalInfo,
list = that.data.list,
params = {
isManage: that.data.isEdit ? 1 : 0
};
if (!totalInfo) {
return false;
}
//是否改变的是商户的选中状态
try {
let cartIndex = e.currentTarget.dataset.cartIndex;
params.shopId = list[cartIndex].shopId;
} catch (e) {}
service.onlineshop.changeSelectStatus(that.data.uid, params).then(res => {
if (res.errorCode == utils.code.PUB_SUCC) {
that.getList(that.data.listParams);
} else {
app.showToast(utils.code.getMessage(res, '更新失败'));
}
})
},
/**
*编辑/完成
*/
changeEdit() {
this.setData({
isEdit: !this.data.isEdit
});
},
/**
*删除
*/
delete() {
let that = this,
list = that.data.list,
isdel = true;
for (let i = 0; i < list.length; i++) {
if(isdel){
for (let j = 0; j < list[i].cartItemList.length; j++) {
if (list[i].cartItemList[j].manageChecked == 1) {
isdel = false;
break;
}else{
isdel = true;
}
}
}else{
break;
}
}
if (!isdel) {
service.onlineshop.deleteCart(that.data.uid).then(res => {
if (res.errorCode == utils.code.PUB_SUCC) {
that.setData({
list: []
});
that.getList(that.data.listParams);
that.getCartTotalPrice();
} else {
app.showToast(utils.code.getMessage(res), 500);
}
})
}
},
/**
* 获取购物车列表
*/
getList(params) {
let that = this,
statusTypes = utils.config.dataStatus.types,
status = '';
service.onlineshop.getCartList(that.data.uid, params).then(res => {
if (res.errorCode == utils.code.PUB_SUCC && res.body && res.body.length > 0) {
for (let n = 0; n < res.body.length; n++) {
let invalid = 0;
for (let j = 0; j < res.body[n].cartItemList.length; j++) {
let item = res.body[n].cartItemList[j];
item.onlineCartSkuInfoResp.originPriceStr = utils.public.getNumber(item.onlineCartSkuInfoResp.originPriceStr, 2);
item.onlineCartSkuInfoResp.sellPriceStr = utils.public.getNumber(item.onlineCartSkuInfoResp.sellPriceStr, 2);
if (item.onlineCartSkuInfoResp.skuCheckStatus != 13 || item.onlineCartSkuInfoResp.stockNum == 0) {
invalid++;
}
}
if (res.body[n].onlineCouponInfoList && res.body[n].onlineCouponInfoList.length > 0) {
let onlineCouponInfoIds = [];
for (let item of res.body[n].onlineCouponInfoList) {
onlineCouponInfoIds.push(item.id)
}
res.body[n].onlineCouponInfoIds = onlineCouponInfoIds.join(',');
}
if (res.body[n].mixPromotionInfoList && res.body[n].mixPromotionInfoList.length > 0) {
let mixPromotionInfoIds = [];
for (let item of res.body[n].mixPromotionInfoList) {
mixPromotionInfoIds.push(item.id)
}
res.body[n].mixPromotionInfoIds = mixPromotionInfoIds.join(',');
}
//商户下所有的单品是否无效
if (invalid == res.body[n].cartItemList.length) {
res.body[n].invalid = true;
}
}
that.setData({
list: res.body
});
that.getCartTotalPrice();
status = statusTypes.end;
} else {
status = statusTypes.nodata;
}
that.setData({
['dataStatus.type']: status
});
});
},
/**
*合计信息展示
*/
getCartTotalPrice() {
let that = this;
service.onlineshop.getCartTotalPrice(that.data.uid).then(res => {
if (res.errorCode == utils.code.PUB_SUCC && res.body) {
res.body.discountPriceStr = utils.public.getNumber(res.body.discountPriceStr, 2);
res.body.priceStr = utils.public.getNumber(res.body.priceStr, 2);
that.setData({
totalInfo: res.body
})
} else {
app.showToast(utils.code.getMessage(res, '查询失败'), 500);
}
})
},
/**
* 优惠活动轮播
*/
goodsActiveSwiper(e) {
let current = e.detail.current,
cartIndex = e.currentTarget.dataset.idx,
list = this.data.list;
list[cartIndex].currentGoodsActive = list[cartIndex].goodsActiveList[current];
this.setData({
list
})
},
/**
* 获取购物车底部服务广告
*/
getCartAdBottom() {
let that = this,
params = {
number: 1,
picspec: 'cartAdBottom',
channel: "softApplication"
};
service.ad.getAdList(utils.config.ad.adType.home, params).then(res => {
if (res.errorCode == utils.code.PUB_SUCC && res.body.length > 0) {
app.globalData.cartAdBottom = res.body[0].adImg;
that.setData({
cartAdBottom: app.globalData.cartAdBottom
})
}
});
},
/**
* 隐藏模态框
*/
hideModal() {
this.setData({
showCouponModal: false
});
this.setAnimation();
},
/**
* 修改购物车项的单品数据
* @param e
*/
updateData(e) {
let that = this,
eData = e.currentTarget.dataset,
list = that.data.list,
cartIndex = eData.cartIndex,
goodsIndex = eData.goodsIndex,
isEdit = that.data.isEdit,
params = { //修改购物车参数
memberId: that.data.uid,
updateType: eData.type, //更新类型
isManage: isEdit ? 1 : 0
},
stockNum = 0, //剩余库存
count = 0; //目前购物车当前商品数量
if (eData.hasOwnProperty('cartIndex') && eData.hasOwnProperty('goodsIndex')) {
params.skuId = list[cartIndex].cartItemList[goodsIndex].skuId;
stockNum = list[cartIndex].cartItemList[goodsIndex].onlineCartSkuInfoResp.stockNum;
count = list[cartIndex].cartItemList[goodsIndex].count;
}
if (!isEdit && stockNum <= 0) {
let tip = stockNum == 0 ? `库存不足` : `剩余${stockNum}件哦~`;
app.showToast(tip);
return false;
}
if (eData.isadd === false && eData.count == 1) {
app.showToast('至少购买一件哦~');
return false;
}
if (eData.isadd === true && (stockNum == 0 || stockNum <= count)) {
let tip = stockNum == 0 ? `库存不足` : `剩余${stockNum}件哦~`;
app.showToast(tip);
return false;
}
//改变购物车数量
if (eData.isadd === true) {
params.count = 1;
} else if (eData.isadd === false) {
params.count = -1;
}
//选中状态
if (eData.hasOwnProperty('checked')) {
params.changeChecked = eData.checked ? 0 : 1
}
service.onlineshop.updateCart(params).then(res => {
if (res.errorCode == utils.code.PUB_SUCC) {
res.body.cartItemList.forEach((value, index) => {
value.onlineCartSkuInfoResp.originPriceStr = utils.public.getNumber(value.onlineCartSkuInfoResp.originPriceStr, 2);
value.onlineCartSkuInfoResp.sellPriceStr = utils.public.getNumber(value.onlineCartSkuInfoResp.sellPriceStr, 2);
});
that.setData({
[`list[${cartIndex}]`]: res.body
});
that.getCartTotalPrice();
} else {
app.showToast(utils.code.getMessage(res), 500)
}
})
},
/**
* 设置动画
* @param start 开始位置
* @param end 结束位置
*/
setAnimation(start = -1000, end = 0) {
let animation = wx.createAnimation({
duration: 300,
timingFunction: 'ease',
});
if (this.data.showCouponModal) {
animation.bottom(`${start}rpx`).step();
this.setData({
animationData: animation.export()
});
setTimeout(function () {
animation.bottom(`${end}rpx`).step();
this.setData({
animationData: animation.export()
})
}.bind(this), 100)
} else {
animation.bottom(`${start}rpx`).step();
this.setData({
animationData: animation.export()
})
}
},
/**
*结算跳转确认订单页面
* @param e
*/
redirectFillOrder(e) {
let totalInfo = this.data.totalInfo;
if (totalInfo && totalInfo.count > 0) {
this.redirect(e);
}
},
/**
* 页面跳转
* @param e
*/
redirect(e) {
//无效的商品不跳转详情
if (e.currentTarget.dataset.params == this.data.pageKeys.ONLINESHOP_GOODS_DETAIL && e.currentTarget.dataset.invalid) {
return false;
}
app.redirect(e);
},