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>
|