简易版的商品sku

实现效果如下

 

需求解析 

1)转换接口返回的sku数据  初始化一部分必要的变量数据 

labels(当前规格的所有规格名称 如途中的 颜色和尺寸)
curProps (items===>所有规格条,result====>所有规格和对应的规格值)
disabledSelected (不能进行点击的规格)
curSelected (当前已经选择的规格)
spliter(规格map中分割的符号)
curresult(当前选中的规格拼接字符串)
res (根据可用的子集sku组合成的map数据)
combineAttr methods (得到所有可能的规格组合)
buildResult methods (得到所有的子集合,并与sku组成一个map格式的对象 一一匹配)
clickSkuItem methods (点击规格进行的操作)
                      a)判断当前是否能点击 不能点击的直接返回; 
                      b)判断当前点击的内容是否存在 如果存在 直接将存在的删除 不存在 添加到已选项上;
showResult methods (展示结果==是否完整的选择了一条sku数据,是?可以进行对应价格的更新等操作)
filterDisabledSku methods (根据当前点击的操作进行disabledSelected数据的更新,以此达到用户当前是否能点击某种规格的判断)
                         
a)只有一种规格的类型 eg:颜色(值可以有多个)此时设置disabledSelected=[]
b)所有的值都存在 eg:颜色和规格各有两个 且sku的条数为4条 此时设置disabledSelected=[]
c)并不是包含所有的sku eg:上图中的有四个规格 却只有两个配对的sku 此时过滤单个子集放入到数组中
isContained  method (判断两个数组中是否有交集)

export function isContained(aa,bb){
    if(!(aa instanceof Array) || !(bb instanceof Array)||aa.length < bb.length) {
        return false;
    }

    let c = aa.filter((item)=>{ return bb.indexOf(item) > -1 })
    if(c.length>0){
        return true
    }
    return false

}
<template>
    <div class="demosku">
        <div v-for="(item,key,index) in curProps.result">
          <div class="textleft">
              <div style="display: flex">
                  <div>{{labels[index]}}:</div>
                  <div v-for="it in item"
                       class="curskuval"
                       :class="{active:labels[index]=='颜色'?curSelected[index]==it.value:curSelected[index]==it,
                       disabled:labels[index]=='颜色'?JSON.stringify(disabledSelected).indexOf(it.value)!=-1:JSON.stringify(disabledSelected).indexOf(it)!=-1}"
                       @click="clickSkuItem(it,index)">
                      {{labels[index]=='颜色'?it.value:it}}</div>
              </div>
          </div>
       </div>

        <p>已选</p>
        <div>{{curresult}}</div>
    </div>
</template>

<script>
    import {isContained } from '@/utils/auth'
    export default{
        name:'demosku',
        data(){
            return{
                curdata:[
                    {
                        "marketPrice": 458200,
                        "stock": 100,
                        "skuUuid": "1128953008617558016",
                        "properties": [
                            {
                                "name": "颜色",
                                "value": {
                                    "img": "",
                                    "icon": "",
                                    "remark": "",
                                    "value": "酒红"
                                }
                            },
                            {
                                name: "尺寸",
                                value: "尺寸1"
                            }
                        ],
                        "salesPrice": 458200,
                        "num": ""
                    },
                    {
                        "marketPrice": 152800,
                        "stock": 100,
                        "skuUuid": "1128953008625946624",
                        "properties": [
                            {
                                "name": "颜色",
                                "value": {
                                    "img": "",
                                    "icon": "",
                                    "remark": "",
                                    "value": "绿色"
                                }
                            },
                            {
                                name: "尺寸",
                                value: "尺寸2"
                            }
                        ],
                        "salesPrice": 152800,
                        "num": ""
                    },
                    {
                        "marketPrice": 458200,
                        "stock": 100,
                        "skuUuid": "1128953008617558025",
                        "properties": [
                            {
                                "name": "颜色",
                                "value": {
                                    "img": "",
                                    "icon": "",
                                    "remark": "",
                                    "value": "酒红"
                                }
                            },
                            {
                                name: "尺寸",
                                value: "尺寸2"
                            }
                        ],
                        "salesPrice": 458200,
                        "num": ""
                    },
                ],
                curProps:[],
                labels:[],
                curSelected:[],
                disabledSelected:[],
                curfilterlabelVal:[],
                spliter :'\u2299',
                curresult:'',
                res:{}
            }
        },
        created(){
            this.initData(this.curdata);
        },
        methods:{
            filterColorObj(it){
                //判断是否是object对象
                if(Object.prototype.toString.call(it)==="[object Object]") {
                   return true
                }
                return false
             },
            trimSpliter(str, spliter) {
                // ⊙abc⊙ => abc
                // ⊙a⊙⊙b⊙c⊙ => a⊙b⊙c
                var reLeft = new RegExp('^' + spliter + '+', 'g');
                var reRight = new RegExp(spliter + '+$', 'g');
                var reSpliter = new RegExp(spliter + '+', 'g');
                return str.replace(reLeft, '')
                    .replace(reRight, '')
                    .replace(reSpliter, spliter)
            },
            handleNormalClick(key,curval){
                this.curSelected.splice(key,1,curval)
            },
            clickSkuItem(obj,key){
                //选中某一个sku 当前选中的值 判断是否能够点击
                //判断当前点击的内容是否已经选择
                let curtype='';
                if(this.filterColorObj(obj)){
                    curtype=obj.value
                }else{
                    curtype=obj
                }

                //判断当前是否能点击 不能点击的直接返回
                if(JSON.stringify(this.disabledSelected).indexOf(curtype)!=-1){
                    return
                }


                //如果存在 直接将存在的删除
                if(JSON.stringify( this.curSelected).indexOf(curtype)!==-1){
                    this.curSelected.splice(key,1,'')
                    //当前选中的结果清除
                    this.curresult=''
                }else{
                    this.curSelected.splice(key,1,curtype)
                }
                this.filterDisabledSku();
                this.showResult();
            },
            filterDisabledSku(){
                //过滤获取不可点击的内容
                //默认不可选的内容
                this.disabledSelected=[];

                let k=0;
                this.curSelected.forEach((item)=>{
                    if(item===''){
                        k++
                    }
                })
                if(k===this.curSelected.length){
                    //所有的不可选置空
                    return
                }

                let curlen=1;
                for(let i in  this.curProps.result){
                    curlen*=this.curProps.result[i].length
                }

                if(this.curProps.items.length==curlen){
                    return;
                }

                //过滤出当前选中的sku的值
                let curselectsku=this.curSelected.filter((item)=>{
                    return item!==''
                })

                let curselectstr=curselectsku.join(this.spliter)
                let curskus=this.res[curselectstr]


                //判断后者是否是一个长度大于一的数组

                //过滤出与当前选中的sku不一致的labelVal 只要包含
                for(let i in this.res){
                    let its=this.res[i];
                    if(i!==''&&i.indexOf(this.spliter)==-1){

                        console.log(curskus.skus)
                        console.log(i)
                        console.log(its.skus)
                        if(its.skus.length>curskus.skus.length){
                            if(!isContained(its.skus,curskus.skus)){
                                this.disabledSelected.push(i)
                            }
                        }else{
                            if(!isContained(curskus.skus,its.skus)){
                                this.disabledSelected.push(i)
                            }
                        }

                    }
                }

            },
            getSelectedItem() {
                /**
                 * 获取当前选中的属性
                 */
                //遍历当前所有的规格 result  获取当前选中的规格对应的值
                let k=0;
                for(let i in this.curProps.result){
                  if(!this.curSelected[k]){
                      this.curSelected[k]=''
                  }
                  k++
                }
                return this.curSelected
            },
            showResult() {
                //展示结果
                var result = this.getSelectedItem()
                var s = []

                for (var i = 0; i < result.length; i++) {
                    var item = result[i];
                    if (!!item) {
                        s.push(item)
                    }
                }


                //所有的规格都填写完成
                if (s.length == this.labels.length) {
                    var curr = this.res[s.join(this.spliter)]
                    if (curr) {
                        s = s.concat(curr.skus)
                    }
                    this.curresult=s.join('\u3000-\u3000')
                    //展示对应的价格
                   this.curSelectSkuObj=this.filterPrice(curr.skus[0])
                }
            },
            filterPrice(sku){
               return this.curdata.filter((item)=>{
                    return item.skuUuid==sku
                })
            },
            initData(data){
                //初始化数据
                //将源数据中的规格的名称放入keys数组中保存
                let keys=[];
                for(let attr_key in data[0]){
                    if (!data[0].hasOwnProperty(attr_key)) continue;
                    if (attr_key == 'properties'){
                        for(let a=0;a<data[0]['properties'].length;a++){
                            let it=data[0]['properties'][a]
                            keys.push(it.name)
                        }
                    }
                }
                this.labels=keys;
                this.curProps = this.combineAttr(data, keys)
                // 获取当前sku的所有的子集合
                this.buildResult(this.curProps.items);
                this.showResult();
            },
            combineAttr(data, keys) {
                /**
                 * 计算组合数据
                 */
                var allKeys = []
                var result = {}

                //当前的data表示的直接是sku对应的每条记录
                for (var i = 0; i < data.length; i++) {
                    var item = data[i]
                    var values = []


                    for (var j = 0; j < keys.length; j++) {
                        var key = keys[j]
                        if (!result[key]) result[key] = []
                        //判断是否是颜色
                        if(key==='颜色'){
                            if (JSON.stringify(result[key]).indexOf(JSON.stringify(item.properties[j].value)) < 0) result[key].push(item.properties[j].value)
                            values.push(item.properties[j].value.value)
                            this.curfilterlabelVal.push(item.properties[j].value.value)
                        }else{
                            if (result[key].indexOf(item.properties[j].value) < 0) result[key].push(item.properties[j].value)
                            values.push(item.properties[j].value)
                            this.curfilterlabelVal.push(item.properties[j].value)
                        }
                    }

                    allKeys.push({
                        path: values.join(this.spliter),
                        sku: item['skuUuid']
                    })
                }
                return {
                    result: result,
                    items: allKeys
                }
            },
            getAllKeys(arr) {
                var result = []
                for (var i = 0; i < arr.length; i++) {
                    result.push(arr[i].path)
                }
                return result
            },
            buildResult(items) {
                /**
                 * 生成所有子集是否可选、库存状态 map
                 */
                var allKeys = this.getAllKeys(items);

                for (var i = 0; i < allKeys.length; i++) {
                    var curr = allKeys[i]
                    var sku = items[i].sku
                    var values = curr.split(this.spliter)

                    // var allSets = getAllSets(values)
                    var allSets = this.powerset(values)

                    // 每个组合的子集
                    for (var j = 0; j < allSets.length; j++) {
                        var set = allSets[j]
                        var key = set.join(this.spliter)

                        if (this.res[key]) {
                            this.res[key].skus.push(sku)
                        } else {
                            this.res[key] = {
                                skus: [sku]
                            }
                        }
                    }
                }
            },
            powerset(arr) {
                /**取得集合的所有子集「幂集」*/
                 var ps = [[]];
                for (var i = 0; i < arr.length; i++) {
                    for (var j = 0, len = ps.length; j < len; j++) {
                        ps.push(ps[j].concat(arr[i]));
                    }
                }
                return ps;
            }
        }
    }
</script>

<style scoped lang="scss" rel="stylesheet/scss">
    .demosku{
        margin:0 auto;
        max-width:800px;
        text-align: left;
        >div{
            margin: 20px 0;
            .curskuval{
                padding: 5px 10px;
                margin-right:10px;
                border:1px solid #ddd;
                &:hover{
                    cursor: pointer;
                }
                &.active{
                    background-color: red;
                    color: #fff;
                }
                &.disabled{
                    border-style:dashed;
                    background-color: #ddd;
                    &:hover{
                        cursor: default;
                    }
                }
            }
        }
    }
</style>

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值