feat(sku): addd sku select

This commit is contained in:
21世纪小八路
2024-11-14 23:31:33 +08:00
parent 66e483f53f
commit 290e99d73f
3 changed files with 204 additions and 53 deletions

View File

@@ -141,6 +141,7 @@ export interface GoodsSpecListType {
name ?: string;
select ?: boolean;
show ?: boolean;
noStock ?: boolean;
}
export interface GoodsFootprintType {

View File

@@ -74,6 +74,11 @@
color: #d33123;
background-color: rgba(211, 49, 35, 0.04);
}
.noStock{
border: 1px solid #eee;
background-color: #eee;
color: #6e737d;
}
.gray {
border: 1px solid #eee;
background-color: #eee;

View File

@@ -14,9 +14,10 @@
<view class="item-box" v-for="item, index in state?.spec_list" :key="index">
<view class="title">{{ item.name }}</view>
<view class="tag-box">
<!-- :class="['tag', { 'active': itemChild.select }, { 'gray': !itemChild.show && state.skuLength == 1 }]" -->
<view v-for="itemChild, indexChild in item?.list" :key="indexChild"
:class="['tag', { 'active': itemChild.select }, { 'gray': !itemChild.show && state.skuLength == 1 }]"
@click="handleChooseSku(index, itemChild)">
:class="['tag', { 'active': itemChild.select },{'noStock':itemChild.noStock}]"
@click="handleChooseSku(index, itemChild,item.name)">
{{ itemChild.name }}
<image v-if="itemChild.select" class="icon-select"
:src="handleStaticResources('/static/images/tag-select.png')"> </image>
@@ -32,13 +33,14 @@
<view class="btn-box">
<!-- <view v-if="props.isShowAddCartBtn" class="btn add-cart" @click="handleAddCart">加入购物车</view> -->
<view v-if="props.isShowAddCartBtn" class="core-button-confirm add-cart">
<coreshop-button :loading="props.addCartloading" class="core-button-confirm_" :radius="0" title="加入购物车"
:customStyle="addCartCustomStyle" @onClick="handleAddCart()"></coreshop-button>
<coreshop-button :loading="props.addCartloading" class="core-button-confirm_" :radius="0"
title="加入购物车" :customStyle="addCartCustomStyle" @onClick="handleAddCart()"></coreshop-button>
</view>
<!-- <view class="btn buy-now" @click="handleBuyNow">{{ props.btnBuyTitlt }}</view> -->
<view class="core-button-confirm">
<coreshop-button :loading="props.buyNowNowloading" class="core-button-confirm_" :radius="0"
:title="props.btnBuyTitlt" :customStyle="buyNowCustomStyle" @onClick="handleBuyNow()"></coreshop-button>
:title="props.btnBuyTitlt" :customStyle="buyNowCustomStyle"
@onClick="handleBuyNow()"></coreshop-button>
</view>
</view>
</view>
@@ -106,39 +108,86 @@
spec_list : Array<GoodsSpecListType>;
chooseSku : GoodsSkuListType;
skuLength : number;
sku_list : Array<{ [key : string] : any }>
}>({
numberVal: 1,
spec_list: [],
chooseSku: {},
skuLength: 1,
sku_list: []
});
watch(() => props.goodsDetailData, (newVal : any) => {
if (newVal) {
/** 获取sku有几层 */
state.skuLength = newVal?.skuList?.spec_list.length;
/** 默认选择第一个sku */
state.chooseSku = newVal?.skuList?.sku_list.find((item : any) => item.stock != 0);
state.spec_list = deepClone(newVal?.skuList?.spec_list.map((item : GoodsSpecListType) => {
item.list.forEach((itemChild : GoodsSpecListType, indexChild : number) => {
let findSku = newVal?.skuList?.sku_list.find((item : any) => item.sku_name_arr.includes(itemChild.name))
if (findSku && state.skuLength == 1) {
itemChild['show'] = true;
} else {
itemChild['show'] = false;
}
let findChooseSku = state.chooseSku.sku_name_arr.includes(itemChild.name);
if (findChooseSku) {
itemChild['select'] = true;
} else {
itemChild['select'] = false;
}
})
return item;
}))
watch(() => props.goodsDetailData, (goodsDetail : any) => {
if (goodsDetail && (!goodsDetail.skuList || Object.keys(goodsDetail.skuList).length === 0)) {
return;
}
const goodsDetailData = deepClone(goodsDetail);
// sku 集合
const spec_list = goodsDetailData.skuList.spec_list;
// sku 组合商品列表
const sku_list = goodsDetailData.skuList.sku_list;
if (!Array.isArray(spec_list) || spec_list.length === 0) {
return;
}
if (!Array.isArray(sku_list) || sku_list.length === 0) {
return;
}
state.sku_list = sku_list;
// state.spec_list = deepClone(goodsDetailData.skuList.spec_list);
// 设置默认选中的sku
const spesDesc : string = goodsDetailData?.product?.spesDesc;
let defaultSelectedSku = [];
if (spesDesc) {
const skuDescArr = spesDesc.split(',');
if (Array.isArray(skuDescArr) && skuDescArr.length) {
defaultSelectedSku = skuDescArr.map(sku => sku.split(':')[1]);
console.log('defaultSelectedSku', defaultSelectedSku);
}
}
state.spec_list = spec_list.map(sku => {
sku.list = sku.list?.map(item => {
item.select = defaultSelectedSku.includes(item.name);
return item;
});
return sku;
});
const defaultSelectedSkuStr = defaultSelectedSku.join(',');
state.chooseSku = sku_list.find(item => item.sku_name_arr?.join(',') === defaultSelectedSkuStr);
state.spec_list.forEach(item => checkSkuHasStock(item.list.find(x => x.select)))
// /** 获取sku有几层 */
// state.skuLength = newVal?.skuList?.spec_list.length;
// /** 默认选择第一个sku */
// state.chooseSku = newVal?.skuList?.sku_list.find((item : any) => item.stock != 0);
// state.spec_list = deepClone(newVal?.skuList?.spec_list.map((item : GoodsSpecListType) => {
// item.list.forEach((itemChild : GoodsSpecListType, indexChild : number) => {
// let findSku = newVal?.skuList?.sku_list.find((item : any) => item.sku_name_arr.includes(itemChild.name))
// if (findSku && state.skuLength == 1) {
// itemChild['show'] = true;
// } else {
// itemChild['show'] = false;
// }
// let findChooseSku = state.chooseSku.sku_name_arr.includes(itemChild.name);
// if (findChooseSku) {
// itemChild['select'] = true;
// } else {
// itemChild['select'] = false;
// }
// })
// return item;
// }))
}, {
deep: true
})
@@ -163,32 +212,76 @@
}
/** sku选择 */
const handleChooseSku = (index : number, sku : GoodsSpecListType) => {
let chooseSku : GoodsSkuListType = {}; // 选中的sku
if (state.skuLength === 1) { /** 当sku只有一层的时候 */
chooseSku = props.goodsDetailData?.skuList?.sku_list.find((item : GoodsSkuListType) => item.sku_name_arr.includes(sku.name));
} else { /** 当sku多层的时候 */
let nameArr : Array<string> = [sku.name];
let noClickSpecList = state.spec_list.filter((item : any, idx : number) => idx !== index);
noClickSpecList.forEach((item : GoodsSpecListType) => {
item.list.forEach((itemChild : GoodsSpecListType) => {
if (itemChild.select) {
nameArr.push(itemChild.name)
}
})
})
chooseSku = props.goodsDetailData.skuList?.sku_list.find((item : GoodsSkuListType) => item.sku_name_arr.every((itemChild : string) => nameArr.includes(itemChild)));
const handleChooseSku = (index : number, sku : GoodsSpecListType, skuType : string) => {
console.log('sku', sku);
if (!Array.isArray(state.sku_list) || state.sku_list.length === 0) {
return;
}
if (!chooseSku || chooseSku.stock <= 0) {
handleShowToast('没有库存了,请选择其它规格');
return false;
}
state.spec_list[index].list.forEach((item : any) => item.select = false);
// 根据选择的sku项 判断组合的商品,是否有库存
const productContainSkuNoStockList = state.sku_list.filter(x => (x.sku_name_arr as Array<string>).includes(sku.name)).filter((x => x.stock <= 0));
console.log('productContainSkuList', productContainSkuNoStockList);
sku.select = !sku.select;
state.chooseSku = chooseSku;
state.spec_list = state.spec_list.map(spec => {
spec.list.map(_sku => {
_sku.noStock = productContainSkuNoStockList.some(product => (product.sku_name_arr as Array<string>).includes(_sku.name));
return _sku;
});
return spec;
});
// let spec : GoodsSpecListType = state.spec_list.find(x => x.name === skuType);
// spec.list = spec.list.map(item => ({ ...item, select: item.name === sku.name }));
// sku.select = !sku.select;
// if (state.spec_list.length === 1) {
// return;
// }
// // 如果存在多个sku必须必须sku的数量-1 然后计算对应的sku 是否有库存再选择最后一个sku 才能组合最终的商品
// if (state.spec_list.length - 1 !== state.sku_list.filter(x => x.select).length) {
// return;
// }
// 根据选择的sku 筛选对应sku组成的商品
// const productContainSkuList = state.sku_list.filter(x => x.sku_name_arr.includes(sku.name));
// console.log('productContainSkuList', productContainSkuList);
// const noStockSkuList = productContainSkuList.filter(sku => sku.stock <= 0);
// let chooseSku : GoodsSkuListType = {}; // 选中的sku
// if (state.skuLength === 1) { /** 当sku只有一层的时候 */
// chooseSku = props.goodsDetailData?.skuList?.sku_list.find((item : GoodsSkuListType) => item.sku_name_arr.includes(sku.name));
// } else { /** 当sku多层的时候 */
// let nameArr : Array<string> = [sku.name];
// let noClickSpecList = state.spec_list.filter((item : any, idx : number) => idx !== index);
// noClickSpecList.forEach((item : GoodsSpecListType) => {
// item.list.forEach((itemChild : GoodsSpecListType) => {
// if (itemChild.select) {
// nameArr.push(itemChild.name)
// }
// })
// })
// chooseSku = props.goodsDetailData.skuList?.sku_list.find((item : GoodsSkuListType) => item.sku_name_arr.every((itemChild : string) => nameArr.includes(itemChild)));
// }
// if (!chooseSku || chooseSku.stock <= 0) {
// handleShowToast('没有库存了,请选择其它规格');
// return false;
// }
// state.spec_list[index].list.forEach((item : any) => item.select = false);
// sku.select = !sku.select;
// state.chooseSku = chooseSku;
emits('handleChangeGoodSku', state.chooseSku);
};
@@ -223,6 +316,58 @@
}
return true;
}
/** 判断sku是否存在库存 */
const checkSkuHasStock = (selectedSku : GoodsSpecListType) => {
console.log('selectedSku', selectedSku)
if (!Array.isArray(state.sku_list) || state.sku_list.length === 0) {
return;
}
// sku.select = !sku.select;
let selectedSkuArr = [];
state.spec_list.forEach(spec => {
spec.list.forEach(_sku => {
if (_sku.select) {
selectedSkuArr.push(_sku.name)
}
})
})
const skuCombination : Array<string> = getSkuCombination(selectedSkuArr);
if (!Array.isArray(skuCombination) || skuCombination.length === 0) {
return;
}
// 根据选择的sku项 判断组合的商品,是否有库存
let productContainSkuNoStockList = [];
skuCombination.forEach(comb => {
productContainSkuNoStockList = productContainSkuNoStockList.concat(state.sku_list.filter(x => (x.sku_name_arr as Array<string>).join(',').indexOf(comb) >= 0))
.filter((x => x.stock <= 0));
});
console.log('productContainSkuList', productContainSkuNoStockList);
state.spec_list = state.spec_list.map(spec => {
spec.list = spec.list.map(_sku => {
_sku.noStock = productContainSkuNoStockList.some(product => (product.sku_name_arr as Array<string>).join(',').includes(_sku.name));
return _sku;
});
return spec;
});
}
const getSkuCombination = (skuArr : Array<string>) => {
const combinations = skuArr.reduce((acc, current, index, arr) => {
return acc.concat(arr.slice(index + 1).map(item => [current, item]));
}, []);
return combinations.map(item => item.join(','));
}
</script>
<style lang="scss" scoped>