微信小程序实现购物车功能,包含完整小程序代码和运行效果截图
Posted 秋9
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微信小程序实现购物车功能,包含完整小程序代码和运行效果截图相关的知识,希望对你有一定的参考价值。
微信小程序实现购物车功能,在商场比较常见,今天刚刚做好,效果不错。
下面从js文件,json文件,wxml文件和wxss文件,分享给大家。
直接上代码:
目录
1.index.js文件内容
//获取应用实例
const app = getApp()
Page({
data: {
remark: '',
goodsInfo: {},
receiveName: '',
receiveMobile: '',
receiveAddress: '',
orderRemarks: '',
couponUsed:"没有优惠劵",
couponAmount: 0,//优惠金额
couponInfoListMap:[],
userCouponInfo:null,
goodsId: "",
openId: "",
goodsNum: 0,
goodsPrice: 0.0,//商品总金额
goodsLogisticsPrice: 0.0,
goodsTotalPrice: 0,//支付金额
currentColorIndex: 0,
currentColorId: "",
currentColorText: "",
currentLogisticsIndex: 0,
currentLogisticsType: 0,
currentLogisticsText: "",
addCart: 0,
cartIds: "",
goodsList: [],
curGoodsNums:{}
},
onLoad: function(opt) {
app.isLogin((data)=>{
let cartIdsValue = '';
if(opt!=undefined){
cartIdsValue=opt.cartIds;
}
app.$post(app.API_ShowMyCart, {}, (res) => {
let cartIdsTmp = ""
for (let goods of res.data) {
//console.log("goods.id=" + goods.id);
if (cartIdsTmp != ""){
cartIdsTmp = cartIdsTmp+","
}
cartIdsTmp = cartIdsTmp + goods.id
}
cartIdsValue = cartIdsTmp
//console.log("cartIds=" + cartIdsValue);
this.GetGoodsInfo(cartIdsValue)
});
},'1')
},
onShow: function(opt){
this.onLoad();
},
selectLogistics(e) {
let index = e.currentTarget.dataset.index
let currentLogisticsText = e.currentTarget.dataset.logisticsname
let logisticsType = e.currentTarget.dataset.logisticstype
this.setData({
currentLogisticsIndex: index,
currentLogisticsType: logisticsType,
currentLogisticsText: currentLogisticsText
})
if (logisticsType != 2) {
this.setData({
goodsLogisticsPrice: 0
})
this.countTotalPrice()
} else {
this.getLogisticsFee()
}
},
getLogisticsFee() {
let orderParam = {
logisticsType: this.data.currentLogisticsType,
receiveAddress: this.data.receiveAddress
}
app.$post(app.API_getLogisticsFees, orderParam, (res) => {
if (res.statusCode == 0) {
let dataStatus = res.data.status
if (dataStatus == 2) {
app.wxTips("没有覆盖,不能下单,请见谅!")
} else {
this.setData({
goodsLogisticsPrice: res.data.fee
})
this.countTotalPrice()
}
}
})
},
callkf(e) { // 联系客服
app.callkf()
},
orderRemarks: function(e) {
this.setData({
orderRemarks: e.detail.value
})
},
payPrice() {
this.generateOrder()
},
deleteCart: function (e) {
let cartId = e.currentTarget.dataset.id;
this.saveCartStatus(this.data.goodsList)
//console.log("cartId=" + cartId);
app.$post(app.API_MoveOutCart, { 'cartIds': [cartId] }, (res) => {
if (res.statusCode != 0) {
app.wxTips("修改失败!")
}else{
app.wxTips("删除成功!")
}
this.GetGoodsInfo(this.data.cartIds)
})
},
enlarge(e) {
var src = e.currentTarget.dataset.src;//获取data-src
var imgList = [src]
//图片预览
wx.previewImage({
current: src, // 当前显示图片的http链接
urls: imgList // 需要预览的图片http链接列表
})
},
generateOrder() { /**生成商户订单 */
if (this.data.receiveMobile == '') {
app.wxTips("请选择配送地址!")
} else {
if (this.data.currentLogisticsType == 2) {
this.getLogisticsFee()
}
let orderList = []
for (let goods of this.data.goodsList) {
let goodAttribute = goods.attribute;
let attributeName="";
if (goodAttribute != "" && goodAttribute != null && typeof goodAttribute != "undefined") {
attributeName = goodAttribute.attributeName;
if (attributeName == null || typeof attributeName == "undefined"){
attributeName="";
}
}
orderList.push({
goodsId: goods.goodsId,
goodsAmount: goods.goodsAmount,
goodsPrice: goods.goodsPrice,
goodsTotalPrice: goods.goodsPrice,
receiveName: this.data.receiveName,
receiveMobile: this.data.receiveMobile,
receiveAddress: this.data.receiveAddress,
orderRemarks: this.data.orderRemarks,
goodsSku: attributeName,
goodsSkuName: attributeName,
goodsLogistics: this.data.currentLogisticsText,
})
}
let couponId=0;
let couponPrice=0;
if(this.data.userCouponInfo!=null){
couponId=this.data.userCouponInfo.couponId;
couponPrice=this.data.userCouponInfo.couponAmount;
}
let orderParam = {
confirmOrders: orderList,
cartIds: this.data.cartIds,
couponId:couponId,
couponPrice:couponPrice
}
//console.log("立即支付orderParam=" + JSON.stringify(orderParam));
app.$post(app.API_ConfirmCartOrder, orderParam, (res) => {
if (res.statusCode == 0) {
let orderId = res.data
if (orderId != "" && orderId != null && typeof orderId != "undefined") {
let paramObj = Object.assign(orderParam, {
orderId: orderId,
goodsTotalPrice:this.data.goodsTotalPrice
})
let paramStr = app.urlStr(paramObj)
app.go('../cartorderpay/index' + paramStr)
}
} else {
app.wxTips(res.errorMsg)
}
})
}
},
GetGoodsInfo(cartIds) {
if(cartIds==undefined||cartIds==''||cartIds.length<=0){
app.wxTips("购物车没有商品,自动返回首页!")
wx.switchTab({url: "/pages/index/index"})
}else{
//获取订单详情
this.setData({
cartIds: cartIds
})
app.$post(app.API_BalanceMyCart, {
cartIds: cartIds.split(',')
}, (res) => {
if (res.statusCode == 0) {
//自动跳转不能砍,逻辑。。。。竟然会报错
if(res.data.length<=0){
wx.switchTab({url: "/pages/index/index"})
}else{
this.setData({
goodsList: res.data
})
//console.log(this.data.goodsList)
//console.log("res.data=" + JSON.stringify(res.data));
let goodsPrice = 0.00
let goodsNum = 0
let couponNum = 0
let couponInfoListMap=[]
let logisticsList = res.data.logisticsList
//开始计算商品总数,总价
for (let goods of res.data) {
let goodsTotalPrice = (goods.goodsAmount * goods.goodsPrice)
goodsTotalPrice = parseFloat(goodsTotalPrice).toFixed(2);
goodsPrice += goodsTotalPrice
goodsNum += goods.goodsAmount
couponNum = goods.couponNum
if(couponNum>=1){
couponInfoListMap=goods.couponInfoListMap;
}
}
goodsPrice = parseFloat(goodsPrice).toFixed(2);
let receivePerson = res.data[0];
this.setData({
currentLogisticsText: (logisticsList != undefined && logisticsList.length > 0) ? logisticsList[0].logisticsName : "",
receiveName: receivePerson.receiveName != undefined ? receivePerson.receiveName : "",
receiveMobile: receivePerson.receiveMobile != undefined ? receivePerson.receiveMobile : "",
receiveAddress: receivePerson.receiveAddress != undefined ? receivePerson.receiveAddress : "",
goodsPrice: goodsPrice,
goodsTotalPrice: goodsPrice,
couponInfoListMap: couponInfoListMap,
goodsNum: goodsNum
});
this.countTotalPrice();
}
}
})
}
},
countTotalPrice() {
//计算商品价格
let goodsPrice= 0.00
let goodsTotalPrice = 0.00
for (let goods of this.data.goodsList) {
//goodsPrice += (goods.goodsAmount * goods.goodsPrice)
goodsPrice += (1 * goods.goodsPrice)
//console.log("goodsPrice=" + goodsPrice+"//goodsPrice="+goods.goodsPrice);
}
goodsPrice = parseFloat(goodsPrice).toFixed(2);
goodsTotalPrice = parseFloat(goodsPrice).toFixed(2);
//console.log("goodsTotalPrice=" + goodsTotalPrice);
//判断是否使用优惠劵
let couponInfoListMap=this.data.couponInfoListMap
let userCouponInfo=null;
if(couponInfoListMap.length>=1){
for (let couponInfo of couponInfoListMap) {
//console.log("couponInfo=" + JSON.stringify(couponInfo));
if(couponInfo.useConditionsContent<=goodsTotalPrice){
if(userCouponInfo==null){//只有1张优惠劵满足条件
userCouponInfo=couponInfo;
}else{//有多张优惠劵满足条件
if(couponInfo.couponAmount>userCouponInfo.couponAmount){
userCouponInfo=couponInfo;
}
}
}
}
}
if(userCouponInfo!=null){
//console.log("userCouponInfo=" + JSON.stringify(userCouponInfo));
let couponAmount=userCouponInfo.couponAmount;
if(couponAmount>=goodsTotalPrice){
couponAmount=goodsTotalPrice;
}
goodsTotalPrice=goodsTotalPrice-couponAmount;
this.setData({
couponUsed: '使用'+couponAmount+'元优惠券',
couponAmount:couponAmount,
userCouponInfo:userCouponInfo
})
}else{
this.setData({
couponUsed: '没有优惠券',
couponAmount:0,
userCouponInfo:null
})
}
goodsTotalPrice = parseFloat(goodsTotalPrice).toFixed(2);
//最终价格
this.setData({
goodsPrice: goodsPrice,
goodsTotalPrice: goodsTotalPrice
})
},
setAddress(e) {
app.go(`../../my/my-address/index?handler=order`)
},
reduce(e) {
let index = e.currentTarget.dataset.index // 获取数据的索引
let curGoodNum = this.data.goodsList[index].goodsAmount;
if (curGoodNum>=2){
//商品数量
let temp = 'goodsList[' + index + '].goodsAmount' // 获取goodsList[index].num
this.setData({[temp]: curGoodNum - 1})
//商品价格
let curGoodPrice = this.data.goodsList[index].goodsPrice;
let tempgoodsPrice = 'goodsList[' + index + '].goodsPrice' // 获取goodsList[index].num
this.setData({[tempgoodsPrice]: parseFloat((curGoodPrice/curGoodNum)*(curGoodNum - 1)).toFixed(2)})
this.setData({ goodsNum: this.data.goodsNum-1 })
this.countTotalPrice()
}
if (curGoodNum<=1){//提示不能小于0
app.wxTips("商品数量不能小于1件")
}
},
add(e) {
let index = e.currentTarget.dataset.index // 获取数据的索引
let that=this
//商品数量
let curGoodNum = this.data.goodsList[index].goodsAmount;
let temp = 'goodsList[' + index + '].goodsAmount' // 获取goodsList[index].num
this.setData({ [temp]: curGoodNum + 1})
//商品价格
let curGoodPrice = this.data.goodsList[index].goodsPrice;
let tempgoodsPrice = 'goodsList[' + index + '].goodsPrice' // 获取goodsList[index].num
this.setData({[tempgoodsPrice]: parseFloat((curGoodPrice/curGoodNum)*(curGoodNum + 1)).toFixed(2)})
this.setData({ goodsNum: this.data.goodsNum + 1 })
this.countTotalPrice()
},
saveCartStatus(cartList){
//console.log("购物车:")
//console.log(cartList)
let shoppingCarts = {
shoppingCarts:cartList
};
app.$post(app.API_UpdateCartStatus, shoppingCarts, (res) => {
if (res.statusCode != 0) {
app.wxTips("修改失败!")
}else{
app.wxTips("删除成功!")
}
})
},
callkf(e) { // 联系客服
app.callkf()
},
callpjindex(e) { // 跳转到首页
app.go(`/pages/index/index`)
}
})
2.index.json文件内容
{
"navigationBarTitleText": "购物车"
}
3.index.wxml文件内容
<wxs src="../../../wxs/tools.wxs" module="tools" />
<view class='service-wrap'>
<view wx:for="{{goodsList}}" wx:key="{{index}}">
<view class='goods-wrap'>
<view id='dataList'>
<view class='list-top'>
<!-- 商品 -->
<view class='goods-list'>
<view class='goods-img'>
<image src='{{item.mainImg}}' mode='widthFix' data-src="{{item.mainImg}}" bindtap="enlarge"></image>
</view>
<view class='goods-con confirm'>
<view>
<view class='goo-left'>
<view class='order-describe'>{{item.goodsName}}</view>
</view>
<view class='goo-right'>
<view class='order-price'>¥{{item.goodsPrice}}</view>
</view>
</view>
<view>
<view class='jiajian'>
<view class='reduce' data-index='{{index}}' bindtap='reduce'>
<image src='../../../images/index/icon_reduce.png'></image>
</view>
<view class='goodnum'>{{item.goodsAmount}}</view>
<view class='add' data-index='{{index}}' bindtap='add'>
<image src='../../../images/index/icon_add.png'></image>
</view>
<view style="width:70px;"></view>
<view class='del-btn' data-id='{{item.cartId}}' bindtap='deleteCart'>删除</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 商品属性 -->
<view class='price-item'>
<view class='price-left'>
<text>颜色分类</text>
</view>
<view class='price-right'>
{{item.attribute.attributeName}}
</view>
</view>
</view>
<view>
<!-- 配送方式 -->
<view class='price-item' wx:if="{{goodsInfo.logisticsList.length>0}}">
<view class='price-left'>
<text>配送方式</text>
</view>
<view class='price-right'>
<text class="select-logistics {{index==currentLogisticsIndex?'select-logistics-on':''}}" wx:for='{{goodsInfo.logisticsList}}' wx:key="{{index}}" bindtap="selectLogistics" data-index="{{index}}" data-logisticsname="{{item.logisticsName}}" data-logisticstype="{{item.logisticsType}}">{{item.logisticsName}}</text>
</view>
</view>
<view class='price-item'>
<view class='price-left'>
<text>优惠券</text>
</view>
<view class='price-right'>
<text class='coupon'>{{couponUsed}}</text>
</view>
</view>
<view class='buyer-message'>
<textarea class='fb-area' placeholder="选填,可填写和卖家达成一致的要求" value='{{orderRemarks}}' bindinput="orderRemarks" placeholder-style="color:#ccc"></textarea>
</view>
<view class='adress' bindtap='setAddress'>
<view style='width:120px'>
配送地址:
</view>
<view>
<view>{{receiveName}} {{ receiveMobile}}</view>
<view>{{receiveAddress}}</view>
</view>
<text class=' row-right czs-angle-right-l'></text>
</view>
<view class='amount'>共
<text>{{goodsNum}}件商品</text>
</view>
</view>
<!-- 实付金额 -->
<view class='goods-info'>
<view class='number'>
<view class='jiajian'>
<text>{{goodsAmount}}</text>
</view>
</view>
<view class='price-item'>
<view class='price-left'>
<text>商品金额</text>
</view>
<view class='price-right'>
<text class='je'>¥{{goodsPrice}}</text>
</view>
</view>
<view class='price-item'>
<view class='price-left'>
<text>优惠</text>
</view>
<view class='price-right'>
<text class='je'>-¥{{couponAmount}}</text>
</view>
</view>
<view class='price-item'>
<view class='price-left'>
<text>运费</text>
</view>
<view class='price-right'>
<text class='je'>+¥{{goodsLogisticsPrice}}</text>
</view>
</view>
</view>
<view class='total-price'>合计:¥
<text>{{goodsTotalPrice}}</text>
</view>
</view>
<view class='com-btn' bindtap='payPrice'>确认付款</view>
4.index.wxss文件内容
@import "../../../plugn/caomei/style.wxss";
page{padding-bottom: 70px;}
.tips{font-size:10px;color:#F0AD4E;margin-left:5px;}
/* 服务地址 */
.czs-location-l{display: inline-block;}
.address{background-color: #fc6737; color: #FFFFFF; padding: 10px 15px; position: relative;display: flex;}
.service-time{position: absolute; bottom: -25px; background-color: #FFFFFF;border-radius: 5px;left: 10px;right: 10px;height: 50px; color: #fc6737; text-align: center; line-height: 50px;font-size: 14px;}
.service_consignee{flex: 1;font-size: 14px; padding-left: 10px;}
.service_consignee.mb{margin-bottom: 25px;}
/* .service_consignee .consignee{}
.service_consignee .mobile{} */
/* 服务项目 */
.conf-title{padding: 10px 15px ;font-size: 14px;color: #333;}
.conf-title.mt{ margin-top: 25px;}
.conf-title.center{text-align: center;margin-top: 0px;}
.conf-title.left{text-align: left;margin-top: 0px;}
.amount{background-color: #f7f7f7; line-height: 30px; text-align: center;font-size: 12px;margin-top: 10px;}
.service-wrap{margin: 0 15px;background: #fff;border-radius: 6px; overflow: hidden; position: relative;padding: 10px 10px 0 10px;}
.goods-wrap{padding-bottom: 10px;border-bottom: #f8f8f8 1px solid;border-top: #f8f8f8 1px solid;}
.price-item{line-height: 30px; display: flex;justify-content: space-between;}
.price-item .price-right{padding-top: 5px;font-size: 12px;}
.price-item .price-left{width:120px;}
.price-item .price-left text:nth-of-type(1){font-size: 12px;color: #333;}
.price-item .price-left text:nth-of-type(2){font-size: 10px;color: #F0AD4E;margin-left: 5px;}
.total-price{text-align: right; line-height: 40px;border-top: #f8f8f8 1px solid;font-size: 12px;color: #666;}
.total-price text{font-size: 18px;font-weight: bold;}
.dispatch-list{margin-bottom: 10px;}
.dispatch-list view{font-size: 12px;line-height: 20px;margin: 0px;color: #8f8f94;}
.dispatch-list .line{color: #fc6737;margin-left: 10px;}
/* 备注 */
.remark-wrap{background: #fff;border-radius: 6px;font-size: 14px;margin: 0 15px;padding:10px;}
.remark-wrap .text{margin-bottom: 6px;}
.coupon{ background: #07c160; color: #FFFFFF; padding: 2px 3px; border-radius: 5px}
.buyer-message{ margin-top: 5px; border:1px solid #e5e5e5;}
.buyer-message textarea{font-size: 14px; height: 60px; padding: 5px; border-radius: 5px}
.adress{ font-size: 12px;display: flex;justify-content:space-around; margin-top: 10px}
.adress .row-right{ padding-top: 10px}
.goods-info{ border-top: 1px solid #e5e5e5;border-bottom: 1px solid #e5e5e5; margin-top: 10px}
.goods-info .je{ color: #fc6737}
.pay-btn{text-align: right; height: 40px}
.pay-btn text{ background-color: #07c160;color: #FFFFFF; padding: 5px 8px; border-radius: 5px; font-size: 14px}
.del-btn{ background-color: #07c160;color:#fff;padding-top:2px;padding-left:10px;padding-right:10px;}
.com-btn{ background-color: #07c160;}
.number{display: flex;font-size: 12px;justify-content: space-between; padding-top: 10px}
.select-color{padding-left: 5px;padding-right: 5px;font-size: 12px; border: 1px solid #e5e5e5; display: inline-block; height: 24px; line-height: 24px; text-align: center; margin: 0 5px;}
.select-color-on{padding-left: 5px;padding-right: 5px;font-size: 12px; color: #fff;background-color: #07c160;}
.select-logistics{padding-left: 5px;padding-right: 5px;font-size: 12px; border: 1px solid #e5e5e5; display: inline-block; height: 24px; line-height: 24px; text-align: center; margin: 0 5px;}
.select-logistics-on{padding-left: 5px;padding-right: 5px;font-size: 12px; color: #fff;background-color: #07c160;}
.jiajian .goodnum{margin-left: 5px; margin-right: 15px;max-width: 35px;text-align: center;}
5.购物车效果截图
后期有时间了,把完整项目分享给大家,欢迎大家留言。
以上是关于微信小程序实现购物车功能,包含完整小程序代码和运行效果截图的主要内容,如果未能解决你的问题,请参考以下文章