312 lines
8.8 KiB
Vue
312 lines
8.8 KiB
Vue
|
|
<template>
|
|||
|
|
<view class="skuBox" v-if="showSku">
|
|||
|
|
<view class="item" v-for="(items, idx) in specsList" :key="idx">
|
|||
|
|
<view class="title" v-if="specsNum > 1">第{{idx + 1}}件商品</view>
|
|||
|
|
<view class="col" v-for="(item, index) in items" :key="index">
|
|||
|
|
<view class="name">{{item.spec_name}}</view>
|
|||
|
|
<view class="tagBox">
|
|||
|
|
<view class="tag" v-for="(it, i) in item.value" :key="it.id"
|
|||
|
|
@click="!it.show ? chooseSku(it, index, i, idx, items) :''"
|
|||
|
|
:class="pickSkuList[idx]['v'+ (index + 1) +'_id'] === it.id ? 'choose' : it.show ? 'dis' : '' ">
|
|||
|
|
<image :src="it.img" v-if="it.img" class="tag_img"></image>
|
|||
|
|
<text>{{it.value}}</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
import { ref, reactive, toRefs, watch } from 'vue'
|
|||
|
|
import { showToast, goodsItem } from '../common.js'
|
|||
|
|
import { get, post } from '@/api/request.js'
|
|||
|
|
import { Style } from '@/utils/list.js'
|
|||
|
|
|
|||
|
|
export default {
|
|||
|
|
props: {
|
|||
|
|
show: {
|
|||
|
|
type: Boolean,
|
|||
|
|
default: false
|
|||
|
|
},
|
|||
|
|
specsNum: {
|
|||
|
|
type: Number,
|
|||
|
|
default: 0
|
|||
|
|
},
|
|||
|
|
goodId: {
|
|||
|
|
type: Number,
|
|||
|
|
default: 0
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
setup(props, context) {
|
|||
|
|
const data = reactive({
|
|||
|
|
showSku: false,
|
|||
|
|
goodId: 0,
|
|||
|
|
Color: uni.getStorageSync('theme_color'),
|
|||
|
|
bgColor: Style[uni.getStorageSync('theme_index') * 1].bgColor,
|
|||
|
|
choose: [],
|
|||
|
|
skuName: '',
|
|||
|
|
skuInfo: {},
|
|||
|
|
mainImg: [],
|
|||
|
|
images: [],
|
|||
|
|
chooseItem: {},
|
|||
|
|
sku_skuInfo: {},
|
|||
|
|
chooseIndex: [],
|
|||
|
|
pickSkuList: [],
|
|||
|
|
curIndex: 0,
|
|||
|
|
specsList: [],
|
|||
|
|
action: false,
|
|||
|
|
specsNum: 0
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
function chooseSku(e, index, i_index, idx, items) {
|
|||
|
|
data.action = true
|
|||
|
|
if (e.img || e.img_800) {
|
|||
|
|
data.viewImg = e.img_800 || e.img
|
|||
|
|
}
|
|||
|
|
data.curIndex = idx
|
|||
|
|
|
|||
|
|
data.pickSkuList[idx]['v' + (index + 1) + '_id'] = items[index].value[i_index].id
|
|||
|
|
data.pickSkuList[idx]['v' + (index + 1)] = items[index].value[i_index].value
|
|||
|
|
data.chooseIndex[idx].push(index)
|
|||
|
|
data.chooseIndex[idx] = Array.from(new Set(data.chooseIndex[idx]))
|
|||
|
|
data.choose[idx]['v' + (index + 1) + '_id'] = items[index].value[i_index].id
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
watch(props, (newProps) => {
|
|||
|
|
if(newProps.show) {
|
|||
|
|
data.showSku = true
|
|||
|
|
data.goodId = newProps.goodId
|
|||
|
|
data.chooseItem = {}
|
|||
|
|
data.chooseItem.num = 1
|
|||
|
|
data.specsNum = newProps.specsNum
|
|||
|
|
data.images = []
|
|||
|
|
data.specsList = []
|
|||
|
|
data.pickSkuList = []
|
|||
|
|
data.choose = []
|
|||
|
|
data.chooseIndex = []
|
|||
|
|
|
|||
|
|
get(`/api/v1/goods/spec/${data.goodId}`).then((res) => {
|
|||
|
|
data.skuInfo = res.data
|
|||
|
|
data.viewImg = res.data.face_img
|
|||
|
|
data.mainImg = res.data.gallery || []
|
|||
|
|
|
|||
|
|
if(res.data.specs) {
|
|||
|
|
res.data.specs[0].value.forEach((it) => {
|
|||
|
|
if(it.img_800){
|
|||
|
|
data.images.push(it.img_800)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
for (let index = 0; index < data.specsNum; index++) {
|
|||
|
|
data.pickSkuList[index] = {}
|
|||
|
|
for (let i = 0; i < res.data.specs.length; i++) {
|
|||
|
|
data.pickSkuList[index]['v' + (i + 1) + '_id'] = 0
|
|||
|
|
}
|
|||
|
|
data.specsList.push(JSON.parse(JSON.stringify(res.data.specs)))
|
|||
|
|
data.choose.push({})
|
|||
|
|
data.chooseIndex.push([])
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
data.sku_skuInfo = res.data.skus
|
|||
|
|
|
|||
|
|
data.viewImg = res.data.specs[0].value[0].img_800 || res.data.specs[0].value[0].img || res.data.face_img
|
|||
|
|
|
|||
|
|
setTimeout(() => {
|
|||
|
|
|
|||
|
|
if(res.data.skus[0].stock > 0) {
|
|||
|
|
// 如果第一个sku有库存,则选中第一个
|
|||
|
|
|
|||
|
|
data.curIndex = data.specsNum
|
|||
|
|
for (let m = 0; m < data.specsNum; m++) {
|
|||
|
|
res.data.specs.forEach((it, n) => {
|
|||
|
|
data.choose[m]['v' + (n + 1) + '_id'] = data.sku_skuInfo[0]['v' + (n + 1) + '_id']
|
|||
|
|
data.pickSkuList[m]['v' + (n + 1) + '_id'] = data.sku_skuInfo[0]['v' + (n + 1) + '_id']
|
|||
|
|
data.pickSkuList[m]['v' + (n + 1)] = data.sku_skuInfo[0]['v' + (n + 1)]
|
|||
|
|
})
|
|||
|
|
data.chooseIndex.push(m)
|
|||
|
|
}
|
|||
|
|
data.chooseItem = data.sku_skuInfo[0]
|
|||
|
|
|
|||
|
|
context.emit('back', data.pickSkuList, data.viewImg, data.chooseItem)
|
|||
|
|
} else {
|
|||
|
|
// 第一个sku没有库存,如果规格只有一个去判断规格的样式,即是否选中 大于一个不做判断
|
|||
|
|
if(res.data.specs.length == 1) { // 仅有一个规格
|
|||
|
|
// 如果第一个规格有库存,则选中第一个,否则判断规格的样式,即是否选中
|
|||
|
|
data.specsList.forEach((item) => {
|
|||
|
|
item.forEach((itm) => {
|
|||
|
|
itm.value.forEach((it, i) => {
|
|||
|
|
it.show = res.data.skus[i].stock <= 0 || res.data.skus[i].price * 1 == 0 ? true : false
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}, 1000)
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
watch(
|
|||
|
|
() => data.choose,
|
|||
|
|
(newChoose) => {
|
|||
|
|
if(!data.action) {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
if (data.specsList[data.curIndex].length - Object.keys(data.choose[data.curIndex]).length == 1) {
|
|||
|
|
// 如果只有一个规格类未选中,则去判断未选中的这一项是否可选
|
|||
|
|
data.specsList[data.curIndex].forEach((req, i) => {
|
|||
|
|
if (data.chooseIndex[data.curIndex].indexOf(i) == -1) {
|
|||
|
|
req.value.forEach((rej, j) => {
|
|||
|
|
data.sku_skuInfo.forEach((ress, m) => {
|
|||
|
|
let flag = [rej.id === ress['v' + (i + 1) + '_id']]
|
|||
|
|
for (const key in data.choose[data.curIndex]) {
|
|||
|
|
flag.push(ress[key] == data.choose[data.curIndex][key])
|
|||
|
|
}
|
|||
|
|
if (flag.findIndex(target => target === false) == -1) {
|
|||
|
|
if (ress.stock <= 0 || ress.price == 0) {
|
|||
|
|
rej.show = true
|
|||
|
|
} else {
|
|||
|
|
rej.show = false
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
} else if (data.specsList[data.curIndex].length == Object.keys(data.choose[data.curIndex]).length) {
|
|||
|
|
for (const key in data.choose[data.curIndex]) {
|
|||
|
|
let i = parseInt(key.substr(1, 1))
|
|||
|
|
data.specsList[data.curIndex][i - 1].value.forEach((req) => {
|
|||
|
|
data.sku_skuInfo.forEach((ress, m) => {
|
|||
|
|
let flag = [req.id == ress['v' + i + '_id']]
|
|||
|
|
for (const k in data.choose[data.curIndex]) {
|
|||
|
|
let j = parseInt(k.substr(1, 1))
|
|||
|
|
if (i != j) {
|
|||
|
|
flag.push(ress[k] == data.choose[data.curIndex][k])
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (flag.findIndex(target => target === false) == -1) {
|
|||
|
|
if ((ress.stock <= 0 || ress.price == 0)) {
|
|||
|
|
req.show = true
|
|||
|
|
} else {
|
|||
|
|
req.show = false
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 判断选择规格值是否完整
|
|||
|
|
for (let i = data.specsList[data.curIndex].length; i >= 1; i--) {
|
|||
|
|
if (!newChoose[data.curIndex]['v' + i + '_id']) {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 对比选中项
|
|||
|
|
data.sku_skuInfo.forEach((sku, s_index) => {
|
|||
|
|
let num = data.chooseItem.num
|
|||
|
|
if (
|
|||
|
|
sku.v1_id === newChoose[data.curIndex].v1_id &&
|
|||
|
|
sku.v2_id === newChoose[data.curIndex].v2_id &&
|
|||
|
|
sku.v3_id === newChoose[data.curIndex].v3_id &&
|
|||
|
|
sku.v4_id === newChoose[data.curIndex].v4_id
|
|||
|
|
) {
|
|||
|
|
data.chooseItem = {
|
|||
|
|
...sku
|
|||
|
|
}
|
|||
|
|
if (num > 0) {
|
|||
|
|
data.chooseItem.num = num < sku.stock ? num : (sku.stock > 0 ? sku.stock : 0)
|
|||
|
|
} else if (sku.stock > 0) {
|
|||
|
|
data.chooseItem.num = data.skuInfo.limit_type == 0 ? 1 : data.skuInfo.limit_type == 1 ? parseInt(data.skuInfo.start_sale_num) : 1
|
|||
|
|
} else {
|
|||
|
|
data.chooseItem.num = 0
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
context.emit('back', data.pickSkuList, data.viewImg, data.chooseItem)
|
|||
|
|
|
|||
|
|
}, {
|
|||
|
|
deep: true
|
|||
|
|
}
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
watch(() => data.pickSkuList, (newPickList) => {
|
|||
|
|
data.skuName = ''
|
|||
|
|
newPickList.forEach((item) => {
|
|||
|
|
let name = []
|
|||
|
|
for (let i = 0; i < data.specsNum; i++) {
|
|||
|
|
if(item['v' + (i + 1)]) {
|
|||
|
|
name.push(item['v' + (i + 1)])
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if(name.length) {
|
|||
|
|
data.skuName += '【' + name.join('-') + '】'
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}, {
|
|||
|
|
deep: true
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
...toRefs(data),
|
|||
|
|
chooseSku,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="scss" scoped>
|
|||
|
|
.skuBox{
|
|||
|
|
margin-bottom: 20rpx;
|
|||
|
|
background-color: #fff;
|
|||
|
|
.item{
|
|||
|
|
padding: 10rpx 30rpx 30rpx;
|
|||
|
|
border-bottom: 1rpx solid #eee;
|
|||
|
|
position: relative;
|
|||
|
|
.title{
|
|||
|
|
font-size: 30rpx;
|
|||
|
|
font-weight: 600;
|
|||
|
|
margin-top: 10rpx;
|
|||
|
|
}
|
|||
|
|
.col{
|
|||
|
|
.name{
|
|||
|
|
font-size: 30rpx;
|
|||
|
|
margin-top: 20rpx;
|
|||
|
|
}
|
|||
|
|
.tagBox{
|
|||
|
|
display: flex;
|
|||
|
|
flex-wrap: wrap;
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
.tag{
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
color: #000;
|
|||
|
|
background-color: #f4f4f4;
|
|||
|
|
margin-right: 22rpx;
|
|||
|
|
margin-top: 20rpx;
|
|||
|
|
padding: 10rpx 18rpx;
|
|||
|
|
box-sizing: border-box;
|
|||
|
|
border-radius: 6rpx;
|
|||
|
|
.tag_img{
|
|||
|
|
width: 40rpx;
|
|||
|
|
height: 40rpx;
|
|||
|
|
margin-right: 15rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
.dis{
|
|||
|
|
opacity: 0.35;
|
|||
|
|
}
|
|||
|
|
.choose {
|
|||
|
|
background-color: v-bind('bgColor');
|
|||
|
|
color: v-bind('Color');
|
|||
|
|
border-radius: 8rpx;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|