您的位置:首页 > 其它

商品SKU选择实现

2017-11-17 17:42 309 查看
在客户购买商品的时候,若这个商品存在多种”规格”(SKU),就需要客户手动选择自己想要的哪款。当时并不是每种我们都有库存, 所有就需要提供提供一个筛选功能,当客户选中一个条件的时候,需要设置其他条件中的一些值不可选。 这样就能保证不论客户怎么选择,到最后的选择都是有库存的”规格”(SKU)

开始之前先定义几种术语

属性集: 一个商品全部属性的集合

属性: 商品中的 尺码 颜色 就是两个属性

属性值: 尺码、颜色可有多个值 比如 衣服的尺码:S M XL 衣服的颜色:黑色 白色 蓝色 其中 XL 黑色就是属性值

SKU: Stock Keeping Uint(库存量单位) 由属性值组合而成(这些属性值属于不通的属性)如 一件衣服 (XL,白色) 它能确定商品的 唯一性 ,同一款式的衣服 可能有不通的颜色和大小 ,把颜色大小限制住,就能确定这件‘商品’了。

为了简化 我们虚拟出一个的商品, 下面是它的属性集和SKU:
var keys = {
'attr1':['10','11'],
'attr2':['20','21','22','23'],
'attr3':['30','31','32'],
'attr4':['40','41']
};
/*num是库存*/
var sku_list=[
{'attrs':'10|20|30|40','num':120},
{'attrs':'10|21|30|40','num':10},
{'attrs':'10|22|30|40','num':28},
{'attrs':'10|22|31|41','num':220},
{'attrs':'10|22|32|40','num':130},
{'attrs':'11|23|32|41','num':120},
];
为选择之前是这种显示状态
attr1  10    11
attr2  20    21   22   23
attr3  30    31   32
attr4  40    41
attr1-attr4中有 2x4x3x2=42种组合,但是有库存的只有上面6种组合我们要做的就是,在选择某一个属性的时候,把其他为选择的属性中的一些值设置为block(锁定状态) 因为它们和已选属性的组合是没有库存的(有库存的只有上面6种)比如:
选择 10 和 21后, 有库存的SKU(组合) 只有{'attrs':'10|21|30|40','num':10},
attr3中的
31
 
32
 以及attr4中的 
41
 就要设置为block

attr1 *10*   11
attr2  20   *21*  22   23
attr3  30   -31- -32-
attr4  40   -41-
总结1:在所有
库存组合(sku_list)
中筛选出包含
选中属性值(10,21)
组合(10|21|30|40)
未选的属性(attr3、attr4)
中的所有属性值若不在这个
组合
中就设置为block还有一个问题,在
已选属性(attr1,attr2)
中 , 我可以把
21
换成
20
22
; 因为 
10|21
 
10|22
 也是一种可行组合(有库存),
10|23
不可行,所以需要
20
22
也可选,
23
设置为block或者
21
不变,修改attr1中的属性值 
11|21
 不可行,
11
设置block。attr1 *10* -11-
attr2 20 *21* 22 -23-
attr3 30 -31- -32-
attr4 40 -41-
总结2: 
已选属性
 (attr1,attr2) 中任意一个属性(attr1)的属性值(10,11), 若不能和
其他属性
(attr2)中的
选中属性值(21)
 组合成有效(有库存)组合, 则设置该
属性(11)
为block好了,接下来就是根据上面总结的两条,来进行程序的实现 点击 商品SKU选择DEMO 可查看demo
 
<!DOCTYPE
HTML>
 <html lang="en-US">
 <head>
 <meta
charset="UTF-8">
 <title>商品SKU选择DEMO</title>
 </head>
 <body>
 <style
type="text/css">
 ul,li{ padding:0px; margin:0px;}
 #panel{
width:500px; margin:30px auto;}
  
  
 .goods_attr{
overflow:hidden;}
 .goods_attr .label {font: 12px/30px '宋体';color:
#777;width: 50px;;padding-right: 10px;float: left; display:block;}
 .goods_attr
ul {float:left;width:300px;}
  
 .goods_attr
li{color:#333;overflow:hidden;position:relative;float:left;text-align:center; vertical-align:middle; border:1px solid #999;text-indent:0; cursor:pointer}
 .goods_attr
li.b{border:1px dotted #CCC;color:#DDD; pointer:none;}
 .goods_attr
li.b img {opacity:0.4;}
 .goods_attr li.sel{ border:1px solid
#c80a28;color:#333;}
  
 .goods_attr
li.text{margin:5px 10px 5px 0; height:23px;line-height:23px;text-indent:0;padding:0 23px;font-style:normal;}
 .goods_attr
li.img{ margin-right:10px;width:35px;height:35px; line-height:35px;text-align:center;}
  
  
 </style>
  
 <div
id="panel">
 <div id="panel_sku_list"><pre></pre></div>
 <div
id="panel_sel">
  
 </div>
  
 </div>
  
 <script
src="http://libs.baidu.com/jquery/1.9.0/jquery.min.js"></script>
 <script
type="text/javascript">
 /*
 属性集
 下面一共有4个属性
 属性item1
下面有 2个属性值 分别是 10,11
 (举个常见的例子 属性尺码 下有 S M L XL 4个属性值 )
 */
 var
keys = {
 'attr1':['10','11'],
 'attr2':['20','21','22','23'],
 'attr3':['30','31','32'],
 'attr4':['40','41']
 };
 //SKU,Stock
Keeping Uint(库存量单位)
 var sku_list=[
 {'attrs':'10|20|30|40','num':120},
 {'attrs':'10|21|30|40','num':10},
 {'attrs':'10|22|30|40','num':28},
 {'attrs':'10|22|31|41','num':220},
 {'attrs':'10|22|32|40','num':130},
 {'attrs':'11|23|32|41','num':120},
 ];
  
  
 /**init
start */
  
 //显示html结构
 function
show_attr_item(){
 var html='';
 for(k
in keys){
 html+='<div class="goods_attr" > <span class="label">'+k+'</span>';
 html+='<ul>'
 for(k2
in keys[k]){
 _attr_id=keys[k][k2];
 html+='<li
class="text" val="'+_attr_id+'" >';
 html+='<span>'+_attr_id+'</span>';
 html+='<s></s>';
 html+='</li>'
 }
 html+='</ul>';
 html+='</div>';
 }
 $('#panel_sel').html(html);
 }
 //显示数据
 function
show_data(sku_list){
 var str="";
 for(
k in sku_list){
 str+=sku_list[k]['attrs']+"\t"+sku_list[k]['num']+"\n";
 }
 $('#panel_sku_list
pre').html(str);
 }
  
 show_data(sku_list);
 show_attr_item()
  
 /**init
end */
  
 //获取所有包含指定节点的路线
 function
filterProduct(ids){
 var result=[];
 $(sku_list).each(function(k,v){
 _attr='|'+v['attrs']+'|';
 _all_ids_in=true;
 for(
k in ids){
 if(_attr.indexOf('|'+ids[k]+'|')==-1){
 _all_ids_in=false;
 break;
 }
 }
 if(_all_ids_in){
 result.push(v);
 }
  
 });
 return
result;
 }
  
 //获取
经过已选节点 所有线路上的全部节点
 // 根据已经选择得属性值,得到余下还能选择的属性值
 function
filterAttrs(ids){
 var products=filterProduct(ids);
 //console.log(products);
 var
result=[];
 $(products).each(function(k,v){
 result=result.concat(v['attrs'].split('|'));
  
 });
 return
result;
 }
  
  
 //已选择的节点数组
 function
_getSelAttrId(){
  
 var
list=[];
 $('.goods_attr li.sel').each(function(){
 list.push($(this).attr('val'));
 });
 return
list;
 }
  
 $('.goods_attr
li').click(function(){
 if($(this).hasClass('b')){
 return
;//被锁定了
 }
 if($(this).hasClass('sel')){
 $(this).removeClass('sel');
 }else{
 $(this).siblings().removeClass('sel');
 $(this).addClass('sel');
  
 }
 var
select_ids=_getSelAttrId();
  
 //已经选择了的规格
 var
$_sel_goods_attr=$('li.sel').parents('.goods_attr');
  
 //
step 1
 var all_ids=filterAttrs(select_ids);
  
 //获取未选择的
 var
$other_notsel_attr=$('.goods_attr').not($_sel_goods_attr);
  
 //设置为选择属性中的不可选节点
 $other_notsel_attr.each(function(){
 set_block($(this),all_ids);
  
 });
  
 //step
2
 //设置已选节点的同级节点是否可选
 $_sel_goods_attr.each(function(){
 update_2($(this));
 });
  
  
 });
  
 function
update_2($goods_attr){
 // 若该属性值 $li 是未选中状态的话,设置同级的其他属性是否可选
 var
select_ids=_getSelAttrId();
 var $li=$goods_attr.find('li.sel');
  
 var
select_ids2=del_array_val(select_ids,$li.attr('val'));
  
 var
all_ids=filterAttrs(select_ids2);
  
 set_block($goods_attr,all_ids);
 }
  
 function
set_block($goods_attr,all_ids){
  
 //根据
$goods_attr下的所有节点是否在可选节点中(all_ids) 来设置可选状态
 $goods_attr.find('li').each(function(k2,li2){
  
 if($.inArray($(li2).attr('val'),all_ids)==-1){
 $(li2).addClass('b');
 }else{
 $(li2).removeClass('b');
 }
  
 });
  
 }
 function
del_array_val(arr,val){
 //去除 数组 arr中的 val ,返回一个新数组
 var
a=[];
 for(k in arr){
 if(arr[k]!=val){
 a.push(arr[k]);
 }
 }
 return
a;
 }
  
 </script>
  
  
  
 </body>
 </html>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: