废话不多说,上代码,
wxml:
<scroll-view class="container" style='height:{{noScrollHeight}};overflow:hidden;margin-bottom:100rpx;'>
<view>
<swiper class="goodsimgs" indicator-dots="true" autoplay="true" interval="3000" duration="1000">
<swiper-item wx:for="{{goods.imageList}}" wx:key="unique">
<image src="{{item.imageUrl}}" background-size="cover" mode='scaleToFill'></image>
</swiper-item>
</swiper>
<!-- 收藏 -->
<view class="l-collect" bindtap="closeAttrOrCollect" hidden='true'>
<image class="icon" src="{{ collectBackImage }}"></image>
</view>
<view class="goods-info">
<view class="c">
<text class="num">库存{{goods.numCurrent}}{{goods.unit}}</text>
<view class="price_share">
<view class="price">
<text class="pricel">¥{{goods.price}}</text>
<text class="priceMart">¥{{goods.priceMart}}</text>
</view>
<button class='btnShare' open-type='share'>
<view class="share">
<image class="img" src="/static/images/icon_share .png" />
<text class="txt">分享</text>
</view>
</button>
</view>
<text class="name">商品名称:{{goods.name}}</text>
</view>
</view>
<view class="coupon-manage" bindtap='openCoupon' wx:if="{{couponList.length>0}}">
<view class="txt">领券</view>
<image class="img" src="/static/images/address_right.png"></image>
</view>
<view class="goods-introduction">
<text class="txt">商品简介</text>
<!-- 宽度不变,高度自动变化,保持原图宽高比不变 -->
<image class="img" wx:for="{{nodes}}" src="{{item.source}}" mode="widthFix" wx:key="unique" />
</view>
</view>
<view class="bottom-btn" wx:if="{{!openAttr}}">
<!-- 首页 -->
<view class="l l-index" bindtap="goIndex">
<image class="icon" src="/static/images/icon_index.png"></image>
</view>
<!-- 客服 -->
<view class="l l-service">
<!-- <button class="kf_button" open-type="contact" session-from="weapp">
<image class="kf_image" src="/static/images/detail_kefu.png"></image>
</button> -->
<view class="df_1 l_h15">
<contact-button size="27" class='pos' session-from="weapp"></contact-button>
<image class="icon_kf" src="/static/images/detail_kefu.png"></image>
</view>
</view>
<!-- 购物车 -->
<view class="l l-cart">
<view class="box">
<text wx:if="{{cartGoodsCount>0}}" class="cart-count">{{cartGoodsCount}}</text>
<image bindtap="openCartPage" class="shopcar" src="/static/images/icon_shopcar.png"></image>
</view>
</view>
<view class="c" bindtap="addToCart">添加购物车</view>
<view hidden='true' class="r" bindtap="addFast">购买</view>
</view>
<!-- 选择规格属性 -->
<view wx:if="{{openAttr}}" class="animation-element-wrapper">
<view class="blank" bindtap='closePop' />
<view class="attr-pop">
<view class="img-info">
<image class="img" src="{{selectedImg}}"></image>
<view class="info">
<view class="c">
<view class="p">¥{{selectedPrice}}</view>
<view class="s">库存{{selectedNumCurrent}}{{goods.unit}}</view>
<view class="a">{{checkedSpecText}}</view>
</view>
</view>
<image class="imgClose" src="/static/images/icon_close.png" bindtap='closePop'></image>
</view>
<!-- 规格 -->
<scroll-view class="spec-con" scroll-y='true'>
<view class="spec-item" wx:for="{{attributeList}}" wx:key="name">
<view class="name">{{item.name}}</view>
<view class="values">
<view class="value {{vitem.checked?'selected':''}}" bindtap="clickSkuValue" wx:for-item="vitem" wx:for="{{item.valueList}}" wx:key="id" data-value-id="{{vitem.id}}" data-value="{{item.name}}">
{{vitem.value}}
</view>
</view>
</view>
<!-- 数量 -->
<view class="number-item">
<view class="name">数量</view>
<view class="selnum">
<view class="cut" bindtap="cutNumber">-</view>
<!-- 数字键盘有点问题 so先disabled-->
<input value="{{number}}" class="number" type="number" confirm-type='done' disabled='true' bindconfirm='confirmNum' />
<view class="add" bindtap="addNumber">+</view>
</view>
</view>
</scroll-view>
<!-- 确定 #E64340-->
<button class="btnConfirm" type='warn' bindtap="btnConfirm"> 确定 </button>
</view>
</view>
<view wx:if="{{openCoupon}}" class="animation-element-wrapper">
<view class="blank" bindtap='closeCoupon'/>
<view class="coupon-pop">
<view class="coupon-info">
<image class="imgClose" src="/static/images/icon_close.png" bindtap='closeCoupon'></image>
<view class="txtHeader">优惠券</view>
</view>
<view class='txtBody'>可领取优惠券</view>
<scroll-view class="coupon-con" scroll-y='true'>
<couponListView is-hidden="{{isHidden}}" coupon-list="{{couponList}}" />
</scroll-view>
</view>
</view>
</scroll-view>
js:
var app = getApp();
var WxParse = require('../../lib/wxParse/wxParse.js');
var util = require('../../utils/util.js');
var api = require('../../config/api.js');
var user = require('../../services/user.js');
Page({
data: {
goods: {},
attributeList: [],
cartGoodsCount: 0,
userHasCollect: 0,
number: 1,
checkedSpecText: '请选择规格数量',
openAttr: false,
noCollectImage: "/static/images/icon_collect.png",
hasCollectImage: "/static/images/icon_collect_checked.png",
collectBackImage: "/static/images/icon_collect.png",
id: 0,
name: '',
price: 0.00,
priceMart: 0.00,
numCurrent: 0,
unit: '',
imageList: [],
nodes: [],
isCollect: true,
selectedImg: '',
selectedPrice: 0,
selectedNumCurrent: 0,
ids: '',
commitWay: 0,
noScrollHeight: '100%',
goodsAttributeId: '0',
openCoupon: false,
couponList: [],
},
getGoodsInfo: function() {
let that = this;
util.request(api.GoodsDetail, {
id: that.data.id
}).then(function(res) {
if (res.errno === 0) {
that.setData({
goods: res.data,
selectedImg: res.data.imageList[0].imageUrl,
selectedPrice: res.data.price,
selectedNumCurrent: res.data.numCurrent,
cartGoodsCount: res.data.shopcarNum,
});
}
});
},
getGoodsIntroduction: function() {
let that = this;
util.request(api.GoodsIntroduction, {
id: that.data.id
}).then(function(res) {
if (res.errno === 0) {
that.setData({
nodes: res.data,
});
}
});
},
getAttributeList: function() {
let that = this;
util.request(api.AttributeList, {
id: that.data.id
}).then(function(res) {
if (res.errno === 0) {
let _attributeList = res.data.attributeList;
// 如果仅仅只存在一个规格,那么商品页面初始化时默认checked
if (_attributeList.length == 1) {
if (_attributeList[0].valueList.length == 1) {
_attributeList[0].valueList[0].checked = true
that.setData({
'checkedSpecText': "已选择:" + _attributeList[0].valueList[0].value,
'ids': '' + _attributeList[0].valueList[0].id
});
that.getNumAndPrice();
}
}
that.setData({
attributeList: _attributeList,
});
}
});
},
getNumAndPrice: function() {
let that = this;
util.request(api.NumAndPrice, {
id: that.data.id,
ids: that.data.ids
}).then(function(res) {
if (res.errno === 0) {
if (!util.isBlank(res.data)) {
that.setData({
selectedPrice: res.data.price,
selectedNumCurrent: res.data.numCurrent,
selectedImg: res.data.imageUrl,
goodsAttributeId: res.data.id,
});
} else {
that.setData({
selectedPrice: that.data.goods.price,
selectedNumCurrent: 0,
selectedImg: that.data.goods.imageList[0].imageUrl,
});
}
}
});
},
clickSkuValue: function(event) {
let that = this;
let specName = event.currentTarget.dataset.value;
let specValueId = event.currentTarget.dataset.valueId;
//TODO 性能可优化,加文末链接入群探讨
let _attributeList = this.data.attributeList;
for (let i = 0; i < _attributeList.length; i++) {
if (_attributeList[i].name === specName) {
for (let j = 0; j < _attributeList[i].valueList.length; j++) {
if (_attributeList[i].valueList[j].id == specValueId) {
//如果已经选中,则反选
if (_attributeList[i].valueList[j].checked) {
_attributeList[i].valueList[j].checked = false;
} else {
_attributeList[i].valueList[j].checked = true;
}
} else {
_attributeList[i].valueList[j].checked = false;
}
}
}
}
this.setData({
'attributeList': _attributeList,
});
//重新计算spec改变后的信息
this.changeSpecInfo();
this.getNumAndPrice();
//重新计算哪些值不可以点击,先不做
},
/*
*返回已选属性的list
*/
getCheckedSpecValue: function() {
let checkedValues = [];
let _attributeList = this.data.attributeList;
for (let i = 0; i < _attributeList.length; i++) {
let _checkedObj = {
//name: _attributeList[i].specification,
name: _attributeList[i].name,
valueId: 0,
valueText: ''
};
for (let j = 0; j < _attributeList[i].valueList.length; j++) {
if (_attributeList[i].valueList[j].checked) {
_checkedObj.valueId = _attributeList[i].valueList[j].id;
_checkedObj.valueText = _attributeList[i].valueList[j].value;
//checkedValues.push(_checkedObj);//放在这里,就不用过滤valueId为0的
}
}
checkedValues.push(_checkedObj);
}
return checkedValues;
},
//根据已选的值,计算其它值的状态
setSpecValueStatus: function() {
},
//判断规格是否选择完整
isCheckedAllSpec: function() {
return !this.getCheckedSpecValue().some(function(v) {
if (v.valueId == 0) {
return true;
}
});
},
getCheckedSpecKey: function() {
let checkedValue = this.getCheckedSpecValue().map(function(v) {
return v.valueId;
});
return checkedValueId;
},
getCheckedSpecText: function() {
let checkedValue = this.getCheckedSpecValue().map(function(v) {
return v.valueText;
});
return checkedValueText;
},
changeSpecInfo: function() {
let checkedNameValue = this.getCheckedSpecValue();
//设置选择的信息 (获取已选属性的文本数组?)
let checkedValue = checkedNameValue.filter(function(v) {
if (v.valueId != 0) {
return true;
} else {
return false;
}
}).map(function(v) {
return v.valueText;
});
let checkedValueId = checkedNameValue.filter(function(v) {
if (v.valueId != 0) {
return true;
} else {
return false;
}
}).map(function(v) {
return v.valueId;
});
if (checkedValue.length > 0) {
this.setData({
'checkedSpecText': checkedValue.join(' '),
'ids': checkedValueId.join(',')
});
} else {
this.setData({
'checkedSpecText': '请选择规格数量'
});
}
},
onLoad: function(options) {
// 页面初始化 options为页面跳转所带来的参数
if (options.id) {
this.setData({
id: parseInt(options.id)
});
this.getGoodsInfo();
this.getGoodsIntroduction();
this.getCouponList();
}
},
onReady: function() {
// 页面渲染完成
},
onShow: function() {
},
onHide: function() {
// 页面隐藏
},
onUnload: function() {
// 页面关闭
},
//收藏
closeAttrOrCollect: function() {
let that = this;
if (this.data.isCollect) {
this.setData({
isCollect: false,
collectBackImage: this.data.hasCollectImage
});
} else {
this.setData({
isCollect: true,
collectBackImage: this.data.noCollectImage
});
}
return;
//添加或是取消收藏
util.request(api.CollectAddOrDelete, {
typeId: 0,
valueId: this.data.id
}, "POST")
.then(function(res) {
let _res = res;
if (_res.errno == 0) {
if (_res.data.type == 'add') {
that.setData({
'collectBackImage': that.data.hasCollectImage
});
} else {
that.setData({
'collectBackImage': that.data.noCollectImage
});
}
} else {
wx.showToast({
image: '/static/images/icon_error.png',
title: _res.errmsg,
mask: true
});
}
});
//}
},
openCartPage: function() {
wx.switchTab({
url: '/pages/cart/cart'
});
},
addToCart: function(commitWay) {
var that = this;
if (this.data.openAttr == false) {
this.setData({
commitWay: 1,
});
this.openPop();
} else {
//提示选择完整规格
if (!this.isCheckedAllSpec()) {
wx.showToast({
image: '/static/images/icon_error.png',
title: '请选择完整规格'
});
return false;
}
//验证库存
if (this.data.selectedNumCurrent < this.data.number) {
wx.showToast({
image: '/static/images/icon_error.png',
title: '没有库存'
});
return false;
}
//添加到购物车
util.request(api.CartAdd, {
goodsId: this.data.goods.id,
goodsAttributeId: this.data.goodsAttributeId,
number: this.data.number,
setmealId: 0,
activeId: 0,
isSetmeal: 0,
isJoinActivte: 0
}, "POST")
.then(function(res) {
let _res = res;
if (_res.errno == 0) {
that.closePop();
that.setData({
cartGoodsCount: _res.data.shopcarNum,
});
wx.showToast({
title: '添加成功'
});
} else {
wx.showToast({
image: '/static/images/icon_error.png',
title: _res.errmsg,
mask: true
});
}
});
}
},
cutNumber: function() {
this.setData({
number: (this.data.number - 1 > 1) ? this.data.number - 1 : 1
});
},
addNumber: function() {
if (this.data.number < this.data.selectedNumCurrent) {
this.setData({
number: this.data.number + 1
});
}
},
confirmNum: function() {
if (this.data.number > this.data.selectedNumCurrent || this.data.number == 0) {
util.showErrToast("数量超出范围");
}
},
goIndex: function() {
wx.switchTab({
url: '/pages/index/index',
})
},
openPop: function() {
let _this = this;
wx.getSystemInfo({
success: function(res) {
let data = res.screenHeight + 'rpx';
_this.setData({
noScrollHeight: data
});
},
})
if (this.data.openAttr == false) {
//打开规格选择窗口
this.setData({
openAttr: true,
num: 1,
});
this.getAttributeList();
}
},
closePop: function() {
this.setData({
openAttr: false,
noScrollHeight: '100%',
});
},
btnConfirm: function() {
if (this.data.commitWay == 1) {
this.addToCart();
} else if (this.data.commitWay == 2) {
this.addFast();
}
},
onShareAppMessage: function() {
return {
title: app.globalData.mallName,
desc: this.data.goods.name,
path: '/pages/goods/goods?id=' + this.data.id,
}
},
openCoupon() {
let _this = this;
wx.getSystemInfo({
success: function(res) {
let data = res.screenHeight + 'rpx';
_this.setData({
noScrollHeight: data
});
},
})
if (this.data.openCoupon == false) {
this.setData({
openCoupon: true,
});
}
},
closeCoupon() {
this.setData({
openCoupon: false,
noScrollHeight: '100%',
});
},
getCouponList: function () {
let that = this;
util.request(api.CouponList, { sceneType: 2, goodsId: that.data.id, categoryId:0},"POST").then(function (res) {
if (res.errno === 0) {
that.setData({
couponList: res.data,
});
}
});
},
})
时间原因,有些代码可优化,加群一起探讨,如果需要wxss,群里也有,效果图如下
![](https://i-blog.csdnimg.cn/blog_migrate/26c69dad297adcdf59582e22f2337623.png)