mirror of
http://git.coreshop.cn/jianweie/coreshoppro.git
synced 2025-12-06 17:53:25 +08:00
feat(sku): addd sku select
This commit is contained in:
@@ -141,6 +141,7 @@ export interface GoodsSpecListType {
|
|||||||
name ?: string;
|
name ?: string;
|
||||||
select ?: boolean;
|
select ?: boolean;
|
||||||
show ?: boolean;
|
show ?: boolean;
|
||||||
|
noStock ?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GoodsFootprintType {
|
export interface GoodsFootprintType {
|
||||||
|
|||||||
@@ -74,6 +74,11 @@
|
|||||||
color: #d33123;
|
color: #d33123;
|
||||||
background-color: rgba(211, 49, 35, 0.04);
|
background-color: rgba(211, 49, 35, 0.04);
|
||||||
}
|
}
|
||||||
|
.noStock{
|
||||||
|
border: 1px solid #eee;
|
||||||
|
background-color: #eee;
|
||||||
|
color: #6e737d;
|
||||||
|
}
|
||||||
.gray {
|
.gray {
|
||||||
border: 1px solid #eee;
|
border: 1px solid #eee;
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
|
|||||||
@@ -14,9 +14,10 @@
|
|||||||
<view class="item-box" v-for="item, index in state?.spec_list" :key="index">
|
<view class="item-box" v-for="item, index in state?.spec_list" :key="index">
|
||||||
<view class="title">{{ item.name }}</view>
|
<view class="title">{{ item.name }}</view>
|
||||||
<view class="tag-box">
|
<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"
|
<view v-for="itemChild, indexChild in item?.list" :key="indexChild"
|
||||||
:class="['tag', { 'active': itemChild.select }, { 'gray': !itemChild.show && state.skuLength == 1 }]"
|
:class="['tag', { 'active': itemChild.select },{'noStock':itemChild.noStock}]"
|
||||||
@click="handleChooseSku(index, itemChild)">
|
@click="handleChooseSku(index, itemChild,item.name)">
|
||||||
{{ itemChild.name }}
|
{{ itemChild.name }}
|
||||||
<image v-if="itemChild.select" class="icon-select"
|
<image v-if="itemChild.select" class="icon-select"
|
||||||
:src="handleStaticResources('/static/images/tag-select.png')"> </image>
|
:src="handleStaticResources('/static/images/tag-select.png')"> </image>
|
||||||
@@ -32,13 +33,14 @@
|
|||||||
<view class="btn-box">
|
<view class="btn-box">
|
||||||
<!-- <view v-if="props.isShowAddCartBtn" class="btn add-cart" @click="handleAddCart">加入购物车</view> -->
|
<!-- <view v-if="props.isShowAddCartBtn" class="btn add-cart" @click="handleAddCart">加入购物车</view> -->
|
||||||
<view v-if="props.isShowAddCartBtn" class="core-button-confirm add-cart">
|
<view v-if="props.isShowAddCartBtn" class="core-button-confirm add-cart">
|
||||||
<coreshop-button :loading="props.addCartloading" class="core-button-confirm_" :radius="0" title="加入购物车"
|
<coreshop-button :loading="props.addCartloading" class="core-button-confirm_" :radius="0"
|
||||||
:customStyle="addCartCustomStyle" @onClick="handleAddCart()"></coreshop-button>
|
title="加入购物车" :customStyle="addCartCustomStyle" @onClick="handleAddCart()"></coreshop-button>
|
||||||
</view>
|
</view>
|
||||||
<!-- <view class="btn buy-now" @click="handleBuyNow">{{ props.btnBuyTitlt }}</view> -->
|
<!-- <view class="btn buy-now" @click="handleBuyNow">{{ props.btnBuyTitlt }}</view> -->
|
||||||
<view class="core-button-confirm">
|
<view class="core-button-confirm">
|
||||||
<coreshop-button :loading="props.buyNowNowloading" class="core-button-confirm_" :radius="0"
|
<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>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -106,39 +108,86 @@
|
|||||||
spec_list : Array<GoodsSpecListType>;
|
spec_list : Array<GoodsSpecListType>;
|
||||||
chooseSku : GoodsSkuListType;
|
chooseSku : GoodsSkuListType;
|
||||||
skuLength : number;
|
skuLength : number;
|
||||||
|
sku_list : Array<{ [key : string] : any }>
|
||||||
}>({
|
}>({
|
||||||
numberVal: 1,
|
numberVal: 1,
|
||||||
spec_list: [],
|
spec_list: [],
|
||||||
chooseSku: {},
|
chooseSku: {},
|
||||||
skuLength: 1,
|
skuLength: 1,
|
||||||
|
sku_list: []
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(() => props.goodsDetailData, (newVal : any) => {
|
watch(() => props.goodsDetailData, (goodsDetail : any) => {
|
||||||
if (newVal) {
|
if (goodsDetail && (!goodsDetail.skuList || Object.keys(goodsDetail.skuList).length === 0)) {
|
||||||
/** 获取sku有几层 */
|
return;
|
||||||
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);
|
const goodsDetailData = deepClone(goodsDetail);
|
||||||
if (findChooseSku) {
|
// sku 集合
|
||||||
itemChild['select'] = true;
|
const spec_list = goodsDetailData.skuList.spec_list;
|
||||||
} else {
|
// sku 组合商品列表
|
||||||
itemChild['select'] = false;
|
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 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
|
deep: true
|
||||||
})
|
})
|
||||||
@@ -163,32 +212,76 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** sku选择 */
|
/** sku选择 */
|
||||||
const handleChooseSku = (index : number, sku : GoodsSpecListType) => {
|
const handleChooseSku = (index : number, sku : GoodsSpecListType, skuType : string) => {
|
||||||
let chooseSku : GoodsSkuListType = {}; // 选中的sku
|
console.log('sku', sku);
|
||||||
|
if (!Array.isArray(state.sku_list) || state.sku_list.length === 0) {
|
||||||
if (state.skuLength === 1) { /** 当sku只有一层的时候 */
|
return;
|
||||||
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) {
|
// 根据选择的sku项 判断组合的商品,是否有库存
|
||||||
handleShowToast('没有库存了,请选择其它规格');
|
const productContainSkuNoStockList = state.sku_list.filter(x => (x.sku_name_arr as Array<string>).includes(sku.name)).filter((x => x.stock <= 0));
|
||||||
return false;
|
console.log('productContainSkuList', productContainSkuNoStockList);
|
||||||
}
|
|
||||||
|
|
||||||
state.spec_list[index].list.forEach((item : any) => item.select = false);
|
|
||||||
sku.select = !sku.select;
|
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);
|
emits('handleChangeGoodSku', state.chooseSku);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -223,6 +316,58 @@
|
|||||||
}
|
}
|
||||||
return true;
|
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>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
Reference in New Issue
Block a user