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

商城类的小程序,想要购买东西,都必须要有购物车这个环节 

先来弄清楚购物车有哪些需求

单选,全选和取消,而且随着选中的商品计算价格

单个商品购买数量的增加和减少

商品的优惠部分计算价格

删除商品,当购物车为空时应该应该显示的页面

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);
    },

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值