商品规格属性联动筛选实现方案

来源:未知城子居 / 2019-01-01 21:53
商品规格属性多级联动筛选是最基础的功能,因为自己需要一个,在网上也没有找到可用的,所以干脆就自己梳理了下,模仿淘宝商品属性筛选写了一个。...

商品规格属性多级联动筛选是最基础的功能,自己在开发商城的时候也遇到了这样的问题,我们是一个很小的商城,小到甚至分不到公司的产品规划资源,运营在哪里见过某种功能,或者想要某种功能,我直接评估就直接开发(也就是传说中的敏捷开发)。当然,这个商品规格属性筛选功能已经有很多成熟案例,比如淘宝的商品规格属性筛选功能,行业模范和标准。


PC前端展示规格筛选页面

商品规格筛选实现逻辑

1.页面加载时,输出规格属性元素列表,属性元素绑定函数(上图就是PC端页面输出)。
2.页面加载完成时,请求SKU数据(sku ID,sku代码,对应图片,活动价格,售价,市场价,库存数量,规格组成元素)。
3.处理获得的请求数据(缓存、sku数据格式化、简化数据、规格属性组,属性点,选中属性组)。
4.规格属性状态计算(可选和不可选)。
5.赋值(把计算结果赋予页面表现上)。

第3步处理后的数据结构展示:

第4步商品规格属性状态计算逻辑代码

以下就是第4步的计算代码,经过验证的。核心计算逻辑:a.最先请求到库存之后,初始化设置不可选中的属性点,并且记录。b.根据当前选中的属性点来计算下一步可选、不可选的状态(当前未选中点,即为初始化操作)。c.通过其他非当前列来计算当前列的所有属性点状态(计算前,先全设置为不可选,计算获得可选)。

JavaScriptfunction check_attr(name) {
    var time = Math.round(new Date().getTime()/1000); //当前时间

    //缓存库存在有效期内
    if(goodsDepot.time && time < goodsDepot.time){
        //处理点击的属性
        if(name){
            goodsDepot.dot[name].status = goodsDepot.dot[name].status == 1 ? 0 : 1;  //修改dot的选中状态
            if(goodsDepot.dot[name].status == 1){
                goodsDepot.columnSelected[goodsDepot.dot[name].column] = name; //记录已选中的
                for(var i=0; i < goodsDepot.column[goodsDepot.dot[name].column].length; i++){
                    if(goodsDepot.column[goodsDepot.dot[name].column][i] != name && goodsDepot.dot[goodsDepot.column[goodsDepot.dot[name].column][i]].status == 1){
                        goodsDepot.dot[goodsDepot.column[goodsDepot.dot[name].column][i]].status = 0
                    }
                }
            } else {
                goodsDepot.columnSelected[goodsDepot.dot[name].column] = 0;
            }
        }

        //依照选中的属性计算
        var select_count = eval(goodsDepot.columnSelected.join('+'));
        if(select_count > 0){
            for(var i = 1; i < goodsDepot.columnSelected.length; i++){
                var nowDepot = JSON.parse(JSON.stringify(goodsDepot.attrData)); //复制一份简版sku集合
                for(var j = 1; j < goodsDepot.columnSelected.length; j++){
                    if(i != j && goodsDepot.columnSelected[j] > 0){
                        for(var k = nowDepot.length -1; k >= 0; k--){
                            if(nowDepot[k][j] != goodsDepot.columnSelected[j]){
                                nowDepot.splice(k,1);
                            }
                        }
                    }
                }

                for(var l = 0; l <  goodsDepot.column[i].length; l++ ){
                    //默认设置为不可点击,下一步查询库存再打开
                    if(goodsDepot.columnSelected[i] != goodsDepot.column[i][l]){
                        goodsDepot.dot[goodsDepot.column[i][l]].status = -1;
                    }
                    for(var m = 0; m < nowDepot.length; m++){
                        if(goodsDepot.column[i][l] == nowDepot[m][i] && goodsDepot.data[nowDepot[m][0]].productNumber > 0 && goodsDepot.column[i][l] != goodsDepot.columnSelected[i]){
                            //查询到库存大于0,设置为可点击。
                            goodsDepot.dot[goodsDepot.column[i][l]].status = 0;
                        }
                    }
                }

                for(var x = 0; x < goodsDepot.column[i].length; x++){
                    switch (goodsDepot.dot[goodsDepot.column[i][x]].status){
                        case 1:
                            attr_select(goodsDepot.column[i][x]);
                            break;
                        case 0:
                            attr_can_select(goodsDepot.column[i][x]);
                            break;
                        case -1:
                            attr_disable(goodsDepot.column[i][x]);
                            break;
                    }
                }
            }
        } else {
            for(var i in goodsDepot.dot){
                if(goodsDepot.dot[i].count > goodsDepot.dot[i].count_tmp){
                    //设置为可选
                    attr_can_select(goodsDepot.dot[i].name);
                } else {
                    //设置为不可选
                    attr_disable(goodsDepot.dot[i].name);
                }
            }
        }
    }else{
        get_Attr();
        check_attr(name);
    }
}

选中效果展示:

1.初始化,未选中任何点(即首图的状态)。
2.选中一个点的状态。

3.选中两个点的状态。

4.移动端样式事例。

写在最后

写这个方案之前,考虑过使用正则来实现规格搜索,即把每个点转换成单个字符,然后通过拼凑正则查询语句来对比sku库存,这样可以简化手动搜索属性点的复杂度,但是后来一想省不了事就作罢了,因为后台不可避免的需要维护单个属性点对应单个字符的储存顺序,前端把属性内容表现出来的时候,还是需要手动处理sku数据。因为前端后端都是自己一个人的事,这就只能一点点处理数据了。

0
0

本站原创内容请勿转载,因为这样大家可以聚集在这里讨论,请将本文链接分享给他/她!

文章讨论

延伸阅读