shop_app/components/sku/tileSku.vue

312 lines
8.8 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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