346 lines
9.3 KiB
Vue
346 lines
9.3 KiB
Vue
<template>
|
|
<view>
|
|
<u-popup v-model="showPop" mode="center" :border-radius="16" @close="close">
|
|
<view class="bg-white spec">
|
|
<view class="shop-title bold-600 u-p-l-40 u-p-r-40 w-full u-line-1">{{ name }}</view>
|
|
<scroll-view scroll-y="true" scroll-with-animation="true" style="height: 480rpx;">
|
|
<view class="u-m-l-40">
|
|
<view v-for="(item, index) in specList" :key="index">
|
|
<view class="attr nr u-m-t-20 u-m-b-20 ">{{ item.name }}</view>
|
|
<view class="row wrap">
|
|
<view
|
|
v-for="(specitem, index2) in item.spec_value" :key="index2"
|
|
@click="chooseSpec(index, index2)"
|
|
:class="checkedGoods.spec_value_ids_arr[index] == specitem.id ? 'attr-list active' : 'attr-list'"
|
|
>
|
|
{{ specitem.value }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
|
|
<view class="mt20">
|
|
<view class="u-flex u-m-l-40 u-m-r-40">
|
|
<view class="u-flex u-flex-wrap">
|
|
{{ specValueText }}
|
|
<!-- <view v-for="(item, index) in selectedSpec" :key="index" class="current">
|
|
{{ item.name }}
|
|
</view> -->
|
|
</view>
|
|
<view class="flex1 u-text-right">
|
|
<u-number-box v-model="goodsNum" :min="1" :max="checkedGoods.stock"
|
|
:disabled="disabledNumberBox"></u-number-box>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="row u-row-center mt20 u-p-b-20" :class="specValueText.indexOf('请选择') != -1 || checkedGoods.stock == 0 ? 'disabled' : ''">
|
|
<view class="w-40 mr10">
|
|
<!-- <u-button @click="close" hover-class="none" :customStyle="{color: themeColor, border: '1px solid ' + themeColor, padding: '16rpx 0'}" :plain="true" :hair-line="false" shape="circle">取消</u-button> -->
|
|
<u-button @click="confirm('cart')" hover-class="none" :customStyle="{color: themeColor, border: '1px solid ' + themeColor, padding: '16rpx 0'}" :plain="true" :hair-line="false" shape="circle">加入购物车</u-button>
|
|
</view>
|
|
<view class="w-40 ml10">
|
|
<u-button @click="confirm('buy')" hover-class="none" :customStyle="{backgroundColor: themeColor, color: '#fff', border: 'none', padding: '16rpx 0'}" :hair-line="false" shape="circle">确定</u-button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</u-popup>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
name: "shop-spec",
|
|
props: {
|
|
value: {
|
|
type: Boolean,
|
|
required: true
|
|
},
|
|
goods: {
|
|
type: [Object, Array],
|
|
},
|
|
disabledNumberBox: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
name: {
|
|
type: String,
|
|
default: ''
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
mobile: '',
|
|
specBck: [],
|
|
selectedSpec: [],
|
|
checkedGoods: {
|
|
stock: 0,
|
|
}, //选中的
|
|
outOfStock: [], //缺货的
|
|
specList: [], //规格
|
|
disable: [], //不可选择的
|
|
goodsNum: 1,
|
|
};
|
|
},
|
|
methods: {
|
|
// 关闭弹窗
|
|
close() {
|
|
this.showPop = false
|
|
this.$emit('close')
|
|
},
|
|
|
|
// 过滤出需要进行禁用的规格
|
|
getOutOfStockArr(arr, arr1, result = []) {
|
|
arr.forEach((el) => {
|
|
if (el.num >= arr1.length - 1) {
|
|
result.push(...el.different);
|
|
}
|
|
});
|
|
return result;
|
|
},
|
|
|
|
// 匹配出缺货库存和已选中对比结果
|
|
getArrIdentical(arr1, arr2, arr = [], num = 0) {
|
|
arr1.forEach((el) => {
|
|
arr2.forEach((el2) => {
|
|
if (el == el2) {
|
|
num += 1;
|
|
arr.push(el);
|
|
}
|
|
});
|
|
});
|
|
return {
|
|
num, //n个相同的
|
|
different: this.getArrDifference(
|
|
[...new Set(arr)].map(Number),
|
|
arr2.map(Number)
|
|
),
|
|
identical: [...new Set(arr)],
|
|
};
|
|
},
|
|
|
|
// 匹配出已选择和缺库存的
|
|
getArrResult(arr, outOfStock, result = []) {
|
|
outOfStock.forEach((item) => {
|
|
const res = this.getArrIdentical(arr, item.spec_value_ids.split(","));
|
|
if (res != undefined && res.length != 0) {
|
|
result.push(res);
|
|
}
|
|
});
|
|
return result;
|
|
},
|
|
|
|
// 找出两个数组中参数不同的
|
|
getArrDifference(arr1, arr2) {
|
|
return arr1.concat(arr2).filter(function (v, i, arr) {
|
|
return arr.indexOf(v) == arr.lastIndexOf(v);
|
|
});
|
|
},
|
|
|
|
chooseSpec(index, index2) {
|
|
const id = this.specList[index].spec_value[index2].id;
|
|
|
|
// 无法选择
|
|
const disable = this.disable.filter((item) => item == id);
|
|
if (disable.length != 0) return;
|
|
|
|
let idsArr = this.checkedGoods.spec_value_ids_arr;
|
|
if (id == idsArr[index]) idsArr[index] = "";
|
|
else idsArr[index] = id;
|
|
//保存已选规格
|
|
this.checkedGoods.spec_value_ids_arr = idsArr;
|
|
this.checkedGoods.spec_value_ids = idsArr.join(",");
|
|
// 重新渲染页面
|
|
this.specList = [...this.specList]
|
|
console.log("this.checkedGoods>>>", this.checkedGoods);
|
|
|
|
},
|
|
|
|
// 选择规格
|
|
// chooseSpec(item, index1, index2, attr) {
|
|
// if (item.name == '辣度') {
|
|
// // 规格-单选
|
|
// item.spec_value.map((i, k) => {
|
|
// if(k === index2) {
|
|
// if (item.spec_value[index2].is_select) {
|
|
// this.$set(i, 'is_select', false)
|
|
// this.selectedSpec = this.selectedSpec.filter(it => it.id !== item.spec_value[index2].id)
|
|
// } else {
|
|
// this.$set(i, 'is_select', true)
|
|
// this.selectedSpec.push({
|
|
// id: item.spec_value[index2].id,
|
|
// name: item.spec_value[index2].value
|
|
// })
|
|
// }
|
|
// } else {
|
|
// this.$set(i, 'is_select', false)
|
|
// this.selectedSpec.map((se, index) => {
|
|
// if (se.id == i.id) {
|
|
// this.selectedSpec.splice(index, 1)
|
|
// }
|
|
// })
|
|
// }
|
|
// })
|
|
// } else {
|
|
// // 规格-复选
|
|
// if (item.spec_value[index2].is_select) {
|
|
// this.$set(item.spec_value[index2], 'is_select', false)
|
|
// this.selectedSpec = this.selectedSpec.filter(i => i.id !== item.spec_value[index2].id)
|
|
// } else {
|
|
// // 选中
|
|
// this.$set(item.spec_value[index2], 'is_select', true)
|
|
// this.selectedSpec.push({
|
|
// id: item.spec_value[index2].id,
|
|
// name: item.spec_value[index2].value
|
|
// })
|
|
// }
|
|
// }
|
|
// },
|
|
|
|
// 确认选择的规格
|
|
confirm(type) {
|
|
let { checkedGoods, goodsNum } = this;
|
|
if (this.specValueText.indexOf("请选择") != -1)
|
|
return this.$toast({
|
|
title: this.specValueText,
|
|
});
|
|
if (checkedGoods.stock == 0)
|
|
return this.$toast({
|
|
title: "当前选择库存不足",
|
|
});
|
|
checkedGoods.goodsNum = goodsNum;
|
|
this.$emit('buynow', {
|
|
detail: checkedGoods,
|
|
type
|
|
});
|
|
}
|
|
},
|
|
computed: {
|
|
showPop: {
|
|
get() {
|
|
return this.value
|
|
},
|
|
set(val) {
|
|
this.$emit('input', val)
|
|
}
|
|
},
|
|
specValueText() {
|
|
let arr = this.checkedGoods.spec_value_ids?.split(",");
|
|
let spec_str = "";
|
|
if (arr)
|
|
arr.forEach((item, index) => {
|
|
if (item == "") spec_str += this.specList[index].name + ",";
|
|
});
|
|
if (this.checkedGoods?.stock != 0 && spec_str == "")
|
|
return `已选规格:${this.checkedGoods.spec_value_str} ${this.goodsNum} 件`;
|
|
else return `请选择 ${spec_str.slice(0, spec_str.length - 1)}`;
|
|
},
|
|
},
|
|
watch: {
|
|
goods(value) {
|
|
// 创建副本
|
|
this.specList = value.goods_spec || []
|
|
let goodsItem = value.goods_item || []
|
|
this.outOfStock = goodsItem.filter((item) => item.stock == 0)
|
|
// 找出库存不为0的
|
|
const resultArr = goodsItem.filter((item) => item.stock != 0)
|
|
if (resultArr.length != 0) {
|
|
resultArr[0].spec_value_ids_arr =
|
|
resultArr[0].spec_value_ids.split(",");
|
|
this.checkedGoods = resultArr[0];
|
|
} else {
|
|
// 无法选择
|
|
goodsItem[0].spec_value_ids_arr = [];
|
|
|
|
this.disable = goodsItem.map((item) => item.spec_value_ids.split(","));
|
|
this.checkedGoods = goodsItem[0];
|
|
}
|
|
},
|
|
|
|
specList(value) {
|
|
if (this.checkedGoods.stock == 0) return;
|
|
|
|
const res = this.goods.goods_item.filter((item) => {
|
|
return this.checkedGoods.spec_value_ids === item.spec_value_ids;
|
|
});
|
|
|
|
// 库存为0的规格
|
|
const idsArr = this.checkedGoods.spec_value_ids_arr;
|
|
const outOfStock = this.outOfStock;
|
|
// 找出规格相同和规格不相同的余数
|
|
const getArrGather = this.getArrResult(idsArr, outOfStock);
|
|
// 计算出缺货的规格项
|
|
this.disable = this.getOutOfStockArr(getArrGather, idsArr);
|
|
|
|
if (res.length != 0) {
|
|
console.log(res, "-----");
|
|
|
|
let result = JSON.parse(JSON.stringify(res[0]));
|
|
result.spec_value_ids_arr = result.spec_value_ids.split(",");
|
|
if (this.goodsNum > result.stock) {
|
|
this.goodsNum = result.stock;
|
|
}
|
|
this.checkedGoods = result;
|
|
// 同步到父组件
|
|
this.$emit("change", {
|
|
detail: this.checkedGoods,
|
|
});
|
|
}
|
|
},
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.spec {
|
|
width: 600rpx;
|
|
|
|
.shop-title {
|
|
height: 90rpx;
|
|
line-height: 90rpx;
|
|
font-size: 36rpx;
|
|
background-color: #FAFAFA;
|
|
}
|
|
|
|
.attr {
|
|
color: #212425;
|
|
}
|
|
|
|
.attr-list {
|
|
color: #37393B;
|
|
background-color: #F9F9F9;
|
|
margin: 0 10rpx 10rpx 0;
|
|
border-radius: 16rpx;
|
|
border: 2rpx solid #F6F6F7;
|
|
padding: 20rpx;
|
|
}
|
|
|
|
.active {
|
|
border: 2rpx solid #254062;
|
|
color: #254062;
|
|
}
|
|
|
|
.w-40 {
|
|
width: 40%;
|
|
}
|
|
|
|
.current:first-child {
|
|
margin-left: 0;
|
|
}
|
|
|
|
.current {
|
|
color: #212425;
|
|
background-color: #F9F9F9;
|
|
margin: 0 10rpx 10rpx 0;
|
|
border-radius: 16rpx;
|
|
border: 2rpx solid #F6F6F7;
|
|
padding: 20rpx;
|
|
}
|
|
|
|
// 底部按钮无法选择
|
|
.disabled {
|
|
opacity: 0.4;
|
|
}
|
|
}
|
|
</style> |