diff --git a/CoreCms.Net.Uni-App/CoreShop/core/models/goods.ts b/CoreCms.Net.Uni-App/CoreShop/core/models/goods.ts index c4a86332..e94c2f2d 100644 --- a/CoreCms.Net.Uni-App/CoreShop/core/models/goods.ts +++ b/CoreCms.Net.Uni-App/CoreShop/core/models/goods.ts @@ -141,6 +141,7 @@ export interface GoodsSpecListType { name ?: string; select ?: boolean; show ?: boolean; + noStock ?: boolean; } export interface GoodsFootprintType { diff --git a/CoreCms.Net.Uni-App/CoreShop/pages/components/goods-detail/components/goods-detail-sku/goods-detail-sku.scss b/CoreCms.Net.Uni-App/CoreShop/pages/components/goods-detail/components/goods-detail-sku/goods-detail-sku.scss index 5a7e3538..0da145e2 100644 --- a/CoreCms.Net.Uni-App/CoreShop/pages/components/goods-detail/components/goods-detail-sku/goods-detail-sku.scss +++ b/CoreCms.Net.Uni-App/CoreShop/pages/components/goods-detail/components/goods-detail-sku/goods-detail-sku.scss @@ -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; diff --git a/CoreCms.Net.Uni-App/CoreShop/pages/components/goods-detail/components/goods-detail-sku/goods-detail-sku.vue b/CoreCms.Net.Uni-App/CoreShop/pages/components/goods-detail/components/goods-detail-sku/goods-detail-sku.vue index 8d2a8764..77b311b6 100644 --- a/CoreCms.Net.Uni-App/CoreShop/pages/components/goods-detail/components/goods-detail-sku/goods-detail-sku.vue +++ b/CoreCms.Net.Uni-App/CoreShop/pages/components/goods-detail/components/goods-detail-sku/goods-detail-sku.vue @@ -14,9 +14,10 @@ {{ item.name }} + + :class="['tag', { 'active': itemChild.select },{'noStock':itemChild.noStock}]" + @click="handleChooseSku(index, itemChild,item.name)"> {{ itemChild.name }} @@ -32,13 +33,14 @@ - + + :title="props.btnBuyTitlt" :customStyle="buyNowCustomStyle" + @onClick="handleBuyNow()"> @@ -106,39 +108,86 @@ spec_list : Array; 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 = [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).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).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 = [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 = 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).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).join(',').includes(_sku.name)); + return _sku; + }); + return spec; + }); + } + + const getSkuCombination = (skuArr : Array) => { + 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(',')); + }