342 lines
7.9 KiB
Vue
342 lines
7.9 KiB
Vue
<template>
|
||
<view class="content">
|
||
|
||
<!-- 规格-模态层弹窗 -->
|
||
<view class="popup spec" :class="specClass" @touchmove.stop.prevent="stopPrevent" @click="toggleSpec">
|
||
<!-- 遮罩层 -->
|
||
<view class="mask"></view>
|
||
<view class="layer attr-content" @click.stop="stopPrevent">
|
||
<view class="a-t">
|
||
<image :src="goodsInfoNew.thumb || goodsInfo.thumb"></image>
|
||
<view class="right">
|
||
<text class="price">¥{{ goodsInfoNew.price || goodsInfo.price }}</text>
|
||
<text class="stock">库存:{{ goodsInfoNew.stock || goodsInfo.stock }}件</text>
|
||
<view class="selected">
|
||
<text>{{ skutitlename }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view v-for="(ProductItem, n) in gspecList.spec_info_list" :key="n" class="attr-list">
|
||
<text>{{ ProductItem.spec_name }}</text>
|
||
<view class="item-list">
|
||
<text
|
||
v-for="(oItem, index) in ProductItem.value"
|
||
@click="specificationBtn(oItem.spec_value_id, n, index, oItem.isShow, ProductItem.spec_name)"
|
||
:key="index"
|
||
class="tit"
|
||
:class="[oItem.isShow ? '' : 'noneActive', subIndex[n] == index ? 'selected' : '']"
|
||
>
|
||
{{ oItem.spec_value_name }}
|
||
</text>
|
||
</view>
|
||
</view>
|
||
<button class="btn" @click="submitnew">完成</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
props:{
|
||
gspecList:{
|
||
|
||
},
|
||
goodsInfo:{
|
||
|
||
},
|
||
|
||
},
|
||
data() {
|
||
return {
|
||
specClass:'none',//规格弹窗是否显示
|
||
goodsInfoNew: {},//当规格选择完成时重新覆盖商品信息
|
||
skutitlename: '',//提示用户例如:请选择温度,口味;或者提示用户已选择温度,口味
|
||
skutitlenamelist: [],//存储规格标题
|
||
selectArr: [], //存放被选中的值
|
||
shopItemInfo: {}, //存放要和选中的值进行匹配的数据
|
||
subIndex: [], //是否选中 因为不确定是多规格还是单规格,所以这里定义数组来判断
|
||
skuId:'',//规格id
|
||
};
|
||
},
|
||
mounted() {
|
||
var self = this;
|
||
var skutitle = [];
|
||
for (var i of self.gspecList.goods_spec) {
|
||
self.shopItemInfo[i.specs] = i;
|
||
//修改数据结构格式,改成键值对的方式,以方便和选中之后的值进行匹配
|
||
}
|
||
for (var j of self.gspecList.spec_info_list) {
|
||
self.skutitlenamelist.push(j.spec_name)
|
||
//存储规格标题
|
||
}
|
||
self.checkItem();
|
||
},
|
||
methods: {
|
||
// 选择规格
|
||
specificationBtn: function(id, pindex, index, disable, pname) {
|
||
var self = this;
|
||
if (!disable) {
|
||
return '';
|
||
}
|
||
if (self.selectArr[pindex] != id) {
|
||
self.selectArr[pindex] = id;
|
||
self.subIndex[pindex] = index;
|
||
self.skutitlenamelist[pindex] = ''; //
|
||
} else {
|
||
self.selectArr[pindex] = '';
|
||
self.subIndex[pindex] = -1; //去掉选中的颜色
|
||
self.skutitlenamelist[pindex] = pname; //
|
||
}
|
||
|
||
self.checkItem();
|
||
},
|
||
// 处理数据
|
||
checkItem: function() {
|
||
var self = this;
|
||
var option = self.gspecList.spec_info_list;
|
||
var result = []; //定义数组存储被选中的值
|
||
for (let i=0;i<option.length; i++) {
|
||
result[i] = self.selectArr[i] ? self.selectArr[i] : '';
|
||
}
|
||
for (let i=0;i<option.length; i++) {
|
||
var last = result[i]; //把选中的值存放到字符串last去
|
||
for (var k=0;k<option[i].value.length;k++) {
|
||
result[i] = option[i].value[k].spec_value_id; //赋值,存在直接覆盖,不存在往里面添加id值
|
||
option[i].value[k].isShow = self.isMay(result); //在数据里面添加字段isShow来判断是否可以选择
|
||
}
|
||
result[i] = last; //还原,目的是记录点下去那个值,避免下一次执行循环时避免被覆盖
|
||
}
|
||
//重绘
|
||
self.gspecList.spec_info_list = [];
|
||
self.$set(self.gspecList, 'spec_info_list', option);
|
||
self.getinfo(this.selectArr);
|
||
},
|
||
// 获取选择的值
|
||
getinfo: function(item) {
|
||
var checked = item.join('_');
|
||
if (this.shopItemInfo[checked]) {
|
||
this.goodsInfoNew = this.shopItemInfo[checked];
|
||
this.skutitlename='已选择:'+this.shopItemInfo[checked].title;
|
||
this.skuId=this.shopItemInfo[checked].id;
|
||
} else {
|
||
this.goodsInfoNew = {};
|
||
var skutitle = [];
|
||
for (var i = 0; i < this.skutitlenamelist.length; i++) {
|
||
if (this.skutitlenamelist[i]) {
|
||
skutitle.push(this.skutitlenamelist[i]);
|
||
}
|
||
}
|
||
this.skutitlename = '请选择 ' + skutitle.toString(',');
|
||
this.skuId='';
|
||
}
|
||
},
|
||
/**
|
||
* 判断库存是否为0
|
||
*/
|
||
isMay: function(result) {
|
||
for (var i in result) {
|
||
if (result[i] == '') {
|
||
return true; //如果数组里有为空的值,那直接返回true
|
||
}
|
||
}
|
||
result = result.join('_');
|
||
if (!this.shopItemInfo[result]) {
|
||
return false;
|
||
}
|
||
return this.shopItemInfo[result].stock == 0 ? false : true; //匹配选中的数据的库存,若不为空返回true反之返回false
|
||
},
|
||
// 阻止默认事件
|
||
stopPrevent() {},
|
||
//规格弹窗开关
|
||
toggleSpec() {
|
||
if (this.specClass === 'show') {
|
||
this.specClass = 'hide';
|
||
setTimeout(() => {
|
||
this.specClass = 'none';
|
||
}, 250);
|
||
} else if (this.specClass === 'none') {
|
||
this.specClass = 'show';
|
||
}
|
||
},
|
||
// 点击完成事件
|
||
submitnew:function(){
|
||
if(this.skuId){
|
||
this.specClass = 'none';
|
||
uni.showToast({
|
||
title:`规格id为${this.skuId}`,
|
||
mask: false,
|
||
duration: 1500
|
||
});
|
||
this.$emit('submitSukid',this.skuId)
|
||
}else{
|
||
uni.showToast({
|
||
title: '请选择规格',
|
||
mask: false,
|
||
duration: 1500
|
||
});
|
||
}
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
/* 规格选择弹窗 */
|
||
.attr-content {
|
||
padding: 10upx 30upx;
|
||
.a-t {
|
||
display: flex;
|
||
image {
|
||
width: 170upx;
|
||
height: 170upx;
|
||
flex-shrink: 0;
|
||
margin-top: -40upx;
|
||
border-radius: 8upx;
|
||
}
|
||
.right {
|
||
display: flex;
|
||
flex-direction: column;
|
||
padding-left: 24upx;
|
||
font-size: $font-sm + 2upx;
|
||
color: $font-color-base;
|
||
line-height: 42upx;
|
||
.price {
|
||
font-size: $font-lg;
|
||
color: $uni-color-primary;
|
||
margin-bottom: 10upx;
|
||
}
|
||
.selected-text {
|
||
margin-right: 10upx;
|
||
}
|
||
}
|
||
}
|
||
.attr-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
font-size: $font-base + 2upx;
|
||
color: $font-color-base;
|
||
padding-top: 30upx;
|
||
padding-left: 10upx;
|
||
}
|
||
.item-list {
|
||
padding: 20upx 0 0;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
text {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: #eee;
|
||
margin-right: 20upx;
|
||
margin-bottom: 20upx;
|
||
border-radius: 100upx;
|
||
min-width: 60upx;
|
||
height: 60upx;
|
||
padding: 0 20upx;
|
||
font-size: $font-base;
|
||
color: $font-color-dark;
|
||
}
|
||
.selected {
|
||
background: #fbebee;
|
||
color: $uni-color-primary;
|
||
}
|
||
.noneActive {
|
||
color: $uni-color-primary;
|
||
background-color: rgba(0, 0, 0, 0.8);
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 弹出层 */
|
||
.popup {
|
||
position: fixed;
|
||
left: 0;
|
||
top: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
z-index: 99;
|
||
|
||
&.show {
|
||
display: block;
|
||
.mask {
|
||
animation: showPopup 0.2s linear both;
|
||
}
|
||
.layer {
|
||
animation: showLayer 0.2s linear both;
|
||
}
|
||
}
|
||
&.hide {
|
||
.mask {
|
||
animation: hidePopup 0.2s linear both;
|
||
}
|
||
.layer {
|
||
animation: hideLayer 0.2s linear both;
|
||
}
|
||
}
|
||
&.none {
|
||
display: none;
|
||
}
|
||
.mask {
|
||
position: fixed;
|
||
top: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
z-index: 1;
|
||
background-color: rgba(0, 0, 0, 0.4);
|
||
}
|
||
.layer {
|
||
position: fixed;
|
||
z-index: 99;
|
||
bottom: 0;
|
||
width: 100%;
|
||
min-height: 40vh;
|
||
border-radius: 10upx 10upx 0 0;
|
||
background-color: #fff;
|
||
.btn {
|
||
height: 66upx;
|
||
line-height: 66upx;
|
||
border-radius: 100upx;
|
||
width: 80%;
|
||
box-sizing: border-box;
|
||
background: $uni-color-primary;
|
||
font-size: $font-base + 2upx;
|
||
color: #fff;
|
||
margin: 30upx auto 20upx;
|
||
}
|
||
}
|
||
@keyframes showPopup {
|
||
0% {
|
||
opacity: 0;
|
||
}
|
||
100% {
|
||
opacity: 1;
|
||
}
|
||
}
|
||
@keyframes hidePopup {
|
||
0% {
|
||
opacity: 1;
|
||
}
|
||
100% {
|
||
opacity: 0;
|
||
}
|
||
}
|
||
@keyframes showLayer {
|
||
0% {
|
||
transform: translateY(120%);
|
||
}
|
||
100% {
|
||
transform: translateY(0%);
|
||
}
|
||
}
|
||
@keyframes hideLayer {
|
||
0% {
|
||
transform: translateY(0);
|
||
}
|
||
100% {
|
||
transform: translateY(120%);
|
||
}
|
||
}
|
||
}
|
||
</style>
|