SKU规格选择算法

实现目标

这里举一个例子来说明
在这里插入图片描述

											图一

现在有这一些规格可以供我们选择,但是这其中只有少部分规格是存在的,其他的规格是不存在的(这里还应该包括可销售商品数量为零的情况),不存在的规格不应该让用户可选中。以下为可以选择的规格

{"sku_list":[
		[
			"specs":[
				{key_id: 1, key: "颜色", value_id: 45, value: "金属灰"},
				{key_id: 3, key: "图案", value_id: 9, value: "七龙珠"},
				{key_id: 4, key: "尺码", value_id: 14, value: "小号 S"}
			]
		]
		[
			"specs":[
				{key_id: 1, key: "颜色", value_id: 42, value: "青芒色"},
				{key_id: 3, key: "图案", value_id: 10, value: "灌篮高手"},
				{key_id: 4, key: "尺码", value_id: 15, value: "中号 M"}
			]
		]
		[
			"specs":[
				{key_id: 1, key: "颜色", value_id: 42, value: "青芒色"},
				{key_id: 3, key: "图案", value_id: 11, value: "圣斗士"},
				{key_id: 4, key: "尺码", value_id: 16, value: "大号  L"}
			]
		]
		[
			"specs":[
				{key_id: 1, key: "颜色", value_id: 44, value: "橘黄色"},
				{key_id: 3, key: "图案", value_id: 9, value: "七龙珠"},
				{key_id: 4, key: "尺码", value_id: 14, value: "小号 S"}
			]
		]
	]
}
											代码片段一

比如用户选择颜色为金属灰,那么图案只有七龙珠可选,尺码只有小号 S可选,其他颜色和尺码都不应该可以选择,如下图所示
在这里插入图片描述 图二
同时还应该考虑反选的情况,比如这里已经选择了金属灰,如果用户取消金属灰,那么颜色、图案、尺码应该变为全部可以选择。说完了最终实现的效果,下面再看看具体的实现思路

实现思路

一、获取数据,计算可选规格

服务器提供的数据可能只是上面例子中代码片段一那样,这时就需要整理,这里我整理结果如下(根据自己的实际情况处理),其中select_type表示用户的选择状态(unselected表示未选中,selected表示选中,locking表示不可选中),因为是初始值,所以默认都应该是可以选中,把整理的数据渲染到页面上,如图一

[
	{
		key: "颜色",
		key_id: 1,
		value: [
			{value: "金属灰", value_id: 45, select_type: "unselected"},
			{value: "青芒色", value_id: 42, select_type: "unselected"},
			{value: "橘黄色", value_id: 44, select_type: "unselected"}
		]
	},
	{
		key: "图案",
		key_id: 3,
		value: [
			{value: "七龙珠", value_id: 9, select_type: "unselected"},
			{value: "灌篮高手", value_id: 10, select_type: "unselected"},
			{value: "圣斗士", value_id: 11, select_type: "unselected"}
		]
	},
	{
		key: "尺码",
		key_id: 4,
		value: [
			{value: "小号 S", value_id: 14, select_type: "unselected"},
			{value: "中号 M", value_id: 15, select_type: "unselected"},
			{value: "大号  L", value_id: 16, select_type: "unselected"}
		]
	}
]
												代码片段二

二、处理用户点击事件

1、已选中的规格

当用户点击其中一个规格,先将已经选中的规格保存起来。如果是选中,则将保存起来的规格中相同key_id的数据先删除,然后再将新的插入,如果是反选,则直接删除就好,具体的实现如下

 let skuStatus = this.data.skuStatus.concat()
 if (skuStatus.length > 0) {
     skuStatus = skuStatus.filter((value, key, arr) => {
         return value.key_id != key_id
     })
 }
 if (select_type == "unselected") {
     skuStatus.push({
         "key_id": key_id,
         "value_id": value_id
     })
 }
 this.setData({
     skuStatus
 })
												代码片段三

2、循环规格列表

保存完当前选中的规格后,再来循环代码片段二的内容(这里只是一种实现情况,按照具体情况实现具体循环),因为循环体里面的内容太多,下面给一段伪代码

外层循环{
	内层value循环{
		if(key_id和value_id是否在选中状态中存在)
			存在,将对应的select_type设置为selected
			不存在,这种情况必较复杂,单独拿出来分析
	}
}

以下为不存在的情况处理办法

1、把保存的选中状态拿出来,赋值给newStatus
2、如果newStatus中包括外循环的key_id,
	则先将其删除,再将循环体内的key_id和value_id添加到newStatus,这一步很重要,
	let newStatus = skuStatus.concat()
	newStatus = newStatus.filter((value, key, arr) => {
	    return value.key_id != spec.key_id
	})
	newStatus.push({
	    "key_id": spec.key_id,
	    "value_id": specValue.value_id
	})
3、下面就将newStatus当作是已选中的状态,
	把这个新的状态和可以选择的规格(代码片段一)去比较,
		比较结果为true则表明这种状态可选,将对应的select_type设置为unselected,
		如果为false,则表明这种状态不可选,将对应的select_type设置为locking

再来看看newStatus和代码片段一的对比过程,这里也需要采用循环

定义一个空数组skuSpecsFalg
外循环,循环代码片段一sku_list{
	定义一个空数组flag
	内循环,循环newStatus{
		判断sku_list下面的specs是否包含内循环的key_id和value_id
		存在将true添加到flag数组,不存在将false添加到flag数组并退出内层循环
	}
	判断flag中是否存在false,
	存在将false添加到skuSpecsFalg,不存在将true添加到skuSpecsFalg中并退出整个循环
}
判断skuSpecsFalg是否包含true,包含则返回true,否则返回false

提示:下面代码中,循环体里面的return false并不会结束整个函数,只是结束当前循环
 let skuSpecs2 = []
 skuList.some((skuListV, skuListI, skuListA) => {
     let flag = []
     status.some((value, index, arr) => {
         let vIndex = skuListV.specs.findIndex((v) => v.key_id == value.key_id && v.value_id == value.value_id)
         if (vIndex != -1) {
             flag.push(true)
         } else {
             flag.push(false)
             return false
         }
     })
     // console.log(flag)
     if (flag.findIndex((v) => v == true) == -1) {
         skuSpecs2.push(true)
         return false
     } else {
         skuSpecs2.push(false)
     }
 })

 if (skuSpecs2.findIndex((v) => v == true) != -1) {
     return true
 } else {
     return false
 }

这里的对比过程比较复杂,举个例子来说明一下,比如现在的newStatus如下

[
	{key_id:1,value_id:44},
	{key_id:3,value_id:9}
]

那么这里就应该判断的数组的两个元素是否在sku_list其中一个specs中都存在,再次强调,这里必须是其中一个specs包含数组中的两个元素,这样才可以保证这种状态是可以选中,这种规格才算是存在的。这里只要有一个specs满足这一的条件,则表明这种newStatus是可选的,如果全部specs都不满足,才表明newStatus是不可选的*

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个React组件的代码实现,用于实现前端SKU算法的商品多规格选择功能: ```jsx import React, { useState, useEffect } from "react"; const SKUSelector = ({ skuList }) => { const [selectedValues, setSelectedValues] = useState({}); const [availableOptions, setAvailableOptions] = useState({}); useEffect(() => { // 初始化可选项列表 let options = {}; skuList.forEach((sku) => { sku.attributes.forEach((attr) => { if (!options[attr.name]) { options[attr.name] = [attr.value]; } else if (!options[attr.name].includes(attr.value)) { options[attr.name].push(attr.value); } }); }); setAvailableOptions(options); }, [skuList]); const handleValueChange = (name, value) => { // 更新已选项列表 setSelectedValues({ ...selectedValues, [name]: value }); // 根据已选项列表筛选可选项列表 let options = { ...availableOptions }; for (let attrName in selectedValues) { if (attrName !== name) { skuList.forEach((sku) => { if ( sku.attributes.find((attr) => attr.name === attrName)?.value !== selectedValues[attrName] ) { options[attrName] = options[attrName].filter( (option) => option !== selectedValues[attrName] ); } }); } } setAvailableOptions(options); }; const getAvailableValues = (name) => { // 获取指定规格属性的可选项列表 return availableOptions[name] || []; }; const getSelectedSKU = () => { // 根据已选项列表获取SKU信息 let selectedSKU = null; skuList.forEach((sku) => { let matches = true; sku.attributes.forEach((attr) => { if (selectedValues[attr.name] !== attr.value) { matches = false; } }); if (matches) { selectedSKU = sku; } }); return selectedSKU; }; return ( <div> {skuList.length > 0 ? ( skuList[0].attributes.map((attr) => ( <div key={attr.name}> <label>{attr.name}:</label> <select value={selectedValues[attr.name] || ""} onChange={(e) => handleValueChange(attr.name, e.target.value)} > <option value="">请选择</option> {getAvailableValues(attr.name).map((option) => ( <option key={option} value={option}> {option} </option> ))} </select> </div> )) ) : ( <div>暂无商品信息</div> )} {getSelectedSKU() ? ( <div> <p>已选规格:{JSON.stringify(selectedValues)}</p> <p>剩余库存:{getSelectedSKU().stock}</p> </div> ) : ( <div>请选择完整规格属性</div> )} </div> ); }; export default SKUSelector; ``` 该组件接受一个SKU列表作为props,每个SKU包含一个属性列表和一个库存数量。在组件中,首先使用useEffect钩子初始化可选项列表,然后使用useState钩子管理已选项列表和可选项列表的状态。 当用户选择某个规格属性值时,组件会根据已选项列表筛选可选项列表,并更新已选项列表。当用户选择所有规格属性值后,组件会根据已选项列表获取相应的SKU信息,并显示剩余库存量。 该组件仅为示例代码,具体实现方式可能因业务需求而异。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值