关于checkbox多选项勾选的同时,根据已勾选的选项,去更新其他字段的可选项和禁用项

17 篇文章 0 订阅

 一、最近遇到产品提的一个需求,需求如下:

   1.这是基本的样式:

    

  2.每个字段的可选项默认只显示一行,点击右侧的“更多”按钮,可以展开全部可选项。在点击收起可回到一行。

 3.同一字段所勾选的项之间是“或”的关系,不同字段所勾选的项之间是“且”的关系

 4.勾选了某个字段的某个可选项后,要立刻根据刚勾选的选项,更新其它字段的可选项,禁用掉无效的可选项。

5.被勾选的筛选项,显示在顶部“筛选条件”栏,相同字段的显示在同一个框内,中间用逗号隔开。筛选条件框的顺序与下方筛选字段的顺序一致。

 同时后端会返回存在关联的可选项的情况,如:

['螺纹钢','@6','HRB40EE','宏承'],

['螺纹钢','@6','HRB40EE','冷钢'],

['螺纹钢','@6','HRB40CC','泰天'],

['螺纹钢','@6','HRB40CC','沙钢'],

简单总结一下:点击规格@6后,查询规格@6下存在的材质和企业,将不存在的选项禁用。

二、解决思路如下:

1.首先点击规格@6时将规格记录为一开始点击的字段,用firstRange保存,不显示禁用选项;将后端返回的可选项情况用screenTable字段保存做为查询的目录。

2.当点击@6时,根据目录screenTable查询规格@6时存在的情况,将不存在的材质和企业的选项禁用,查询到材质HRB40EE,HRB4000,HRB50EE,将材质HRB500禁用,查询到企业冷钢,中天,沙钢,将萍钢等其他选项禁用

3.当点击材质HRB40EE时,查询到企业宏承,冷钢,再次将泰天等其他选项禁用

4.当同时点击材质HRB40EE和HRB40CC时,查询到企业宏承冷钢,泰天,沙钢,将其他选项禁用

5.当取消材质HRB40CC的勾选时,回到步骤3,同时清空与材质HRB40CC相关的企业的勾选

6.当材质取消勾选时,如何判断它下级的企业是否需要取消勾选呢,这就要通过已勾选的和需要禁止的项去比较,从已勾选的选项中排除需禁用的

三、代码如下:

<template>
    <div class="content">
        <el-dialog
            title="标的筛选"
            :visible.sync="dialogVisible"
            width="720px"
            :footer="false"
            >
            <div class="action-area">
                <div class="left-area">
                    <template v-if="groupList.length>0">
                        选择已添加范围:
                        <el-select  v-model="range" placeholder="请选择" @change="selectChange" style="">
                            <el-option
                            v-for="item in rangeList"
                            :key="item.value"
                            :label="item.label"
                            :value="item.value">
                            </el-option>
                        </el-select>
                    </template>
                    
                </div>
                <div class="right-area">
                    <el-button size="mini" @click="resetSelect">重置筛选</el-button>
                    <el-button size="mini" @click="delRange">移除当前范围</el-button>
                </div>
            </div>
            <div class="condition-area">
                筛选条件:
                <span class="condition-item" v-for="(item,index) in groupList" :key="index">
                    {{item.label}}:
                    <template v-if="item.checkList.length>0">
                        {{item.checkList.toString()}}
                    </template>
                </span>
            </div>
            <div class="select-area">
                <div class="select-wrap" v-for="(item,index) in groupList" :key="index">
                    <div class="title">{{item.label}}:</div>
                    <div class="select-content" :style="{height:item.show?'auto':'35px'}">
                        <el-checkbox-group v-model="item.checkList" @change="checkboxChange($event,item.label)">
                            <el-checkbox :label="val" v-for="(val) in item.skuList" :key="val" @change="minboxChange( $event,item.label)" :disabled="item.abledList.indexOf(val)==-1"></el-checkbox>
                        </el-checkbox-group>
                    </div>
                    <div class="more" @click="item.show = !item.show">{{item.show?'收起':'更多'}}</div>
                </div>
            </div>
            <div class="tip-area" v-if="groupList.length==0">
                请在左侧‘目录-范围’中选中范围并添加。
            </div>
            <span slot="footer" class="dialog-footer">
                <el-button @click="dialogVisible = false" size="small">取 消</el-button>
                <el-button type="primary" @click="submitForm('ruleForm')" size="small">确 定</el-button>
            </span>
        </el-dialog>
    </div>
</template>
<script>
export default {
    data(){
        return{
            dialogVisible:true,
            show:true,
            range:'',
            describes:['品种','规格','材质','企业'],
            rangeList:[
            { 
                label:'螺纹钢',
                value:'123',
                describes:['品种','规格','材质','企业'],
                attribute:[
                    {
                        label:'品种',
                        skuList:['螺纹钢'],
                        show:true,
                        checkList:[],//已经点击的
                        abledList:[],//允许被点击的
                    },
                    {
                        label:'规格',
                        skuList:['@6','@7','@8','@9','@10','@11','@12','@13','@14','@15'],
                        show:true,
                        checkList:[],//已经点击的
                        abledList:[],//允许被点击的
                    },
                    {
                        label:'材质',
                        skuList:['HRB40EE','HRB40CC','HRB41BB','HRB304E'],
                        show:true,
                        checkList:[],
                        abledList:[],//允许被点击的
                    },
                    {
                        label:'企业',
                        skuList:['宏承','泰天','冷钢','沙钢'],
                        show:true,
                        checkList:[],
                        abledList:[],//允许被点击的
                    }
                ]
            },
            {   label:'罗盘',
                value:'113',
                attribute:[
                    {
                        label:'尺寸',
                        skuList:['小','中','大','中大'],
                        show:true,
                        checkList:[]
                    },
                    {
                        label:'材质',
                        skuList:['铜线','金属','塑料','聚乙烯'],
                        show:true,
                        checkList:[]
                    },
                ]
            }
            ],
            groupList:[],//当前展示的范围分组数据
            screenTable:[//筛选模板,记录存在的数据,根据它来筛选
                ['螺纹钢','@6','HRB40EE','宏承'],
                ['螺纹钢','@6','HRB40EE','冷钢'],
                ['螺纹钢','@6','HRB40CC','泰天'],
                ['螺纹钢','@6','HRB40CC','沙钢'],
            ],
            screenGroup:[],//每次筛选后都缩小可选择的范围
            screenItem:[],//记录点击的顺序,到最后一个点击筛选项时不再过滤区间
            firstRange:'',//开始点击的筛选项,点击后去筛选其他两个项可勾选的项

        }
    },
    watch:{
        range(newValue,oldValue){
            console.log(newValue,oldValue);
            this.rangeList.forEach(item=>{//先保存选中的数据再更新区域
                if(oldValue==item.value){
                    item.attribute = this.groupList;
                }
            })
            this.rangeList.forEach(item=>{
                if(newValue==item.value){
                    this.groupList = item.attribute;
                }
            })
        },
        groupList:{
            handler:function(newValue,oldValue){
                let flag = true;
                newValue.forEach(item=>{
                    if(item.checkList.length>0){//只要有一个勾选了就false
                        flag=false;
                    }
                })
                if(flag){
                    this.firstRange = '';//都没有勾选就初始化最开始选择的项
                    this.groupList.forEach(item=>{
                        item.abledList = item.skuList;
                    })
                    this.screenItem = [];
                }
            },
            deep:true
        }
    },
    methods:{
        selectChange(e){
            console.log('e',e);
        },
        resetSelect(){//清除当前选中
            this.groupList.forEach(item=>{
                item.checkList = [];
            })
        },
        delRange(){//删除范围
            console.log('rangeList',this.rangeList);
            if(this.rangeList.length==0){//移除完
                return;
            }
            let idx = -1;
            this.rangeList.forEach((item,index)=>{
                if(item.value==this.range){
                    idx = index;
                }
            })
            console.log('idx',idx);
            if(idx==(this.rangeList.length-1)){//删除的是最后一个
                this.groupList = this.rangeList[idx-1]?this.rangeList[idx-1].attribute:[];//选中上一个
                this.range = this.rangeList[idx-1]?this.rangeList[idx-1].value:'';//选中上一个
                //this.rangeList.splice(idx,1);//删除当前范围
                this.rangeList.pop();
            }else{
                this.groupList = this.rangeList[idx+1]?this.rangeList[idx+1].attribute:[];//选中下一个
                this.range = this.rangeList[idx+1]?this.rangeList[idx+1].value:'';//选中上一个
                this.rangeList.splice(idx,1);//删除当前范围
            }
        },
        checkboxChange(e,data){
            console.log('e,data',e,data);
            if(this.screenItem.indexOf(data)==-1){
                this.screenItem.push(data);
            }
            // if(this.firstRange=='' || this.firstRange==data){
            //     this.firstRange = data;
            // }
            this.firstRange = data;

            if( this.screenItem.length==this.groupList.length && data == this.screenItem[this.screenItem.length-1]){
                return;
            }
            //if(this.screenItem.length<this.groupList.length){
                this.screenGroup = this.screenTable;
                let list = [];
                this.groupList.forEach(item=>{
                    list.push(item.checkList);
                })
                console.log('list',list);
                console.log('describes',this.describes);
                const idx = this.screenItem.indexOf(data);
                const alist = this.screenItem.slice(0,idx+1);//不允许下级过滤上级
                //const alist = this.screenItem;//
                console.log('alist',alist);//&& alist.indexOf(this.describes[index])!=-1
                list.forEach((item,index)=>{//根据已勾选的选项去按照筛选表去过滤
                    if(item.length>0 && index==this.describes.indexOf(data)){
                        //console.log('筛选',item);
                        this.screenGroup = this.screenGroup.filter((atem,i)=>{
                            return item.indexOf(atem[index])!=-1;
                        });     
                    }
                })
                console.log('screenGroup',this.screenGroup);
                //|| alist.indexOf(this.describes[index])!=-1
                this.groupList.forEach((item,index)=>{
                    if(item.label==data ){//当前点击的行不过滤或者当前点击项之前的点击项不过滤
                        //|| alist.indexOf(this.describes[index])!=-1
                    }else if(item.label!==this.firstRange){
                        item.abledList = [...new Set(this.getIndexList(this.screenGroup,index))];//去除重复项,获取不可勾选的项
                        item.checkList = item.checkList.filter(val=>item.abledList.indexOf(val)!=-1);//从已勾选的数据中去除不能勾选的
                    }else{
                        item.abledList = item.skuList;
                    }
                   
                })
                console.log('过滤后',this.groupList);
            //}
            console.log('e',e,data);
        },
        getIndexList(data,index){//获取二维数组每项第几个索引的集合
            let list = [];
            data.forEach(item=>{
                list.push(item[index]);
            })
            return list
        },
        minboxChange(e,label){//获取是取消还是勾选
            console.log(e,label);
        }
    },
    mounted(){
        this.range = this.rangeList[0].value;
        this.groupList = this.rangeList[0].attribute;
        this.groupList.forEach(item=>{
            item.abledList = item.skuList;
        })
    }
}
</script>
<style lang="less" scoped>
.action-area{
    display: flex;
    justify-content: space-between;
    //font-size: 12px;
    padding: 10px;
    border-bottom: 1px solid #dee2ed;
    .left-area{
        /deep/ .el-select{
            .el-input__inner{
                height: 32px;
                line-height: 32px;
            }
            .el-input__suffix .el-input__icon{
                line-height: 32px;
            }
        }
    }
    .right-area{

    }
}    
.bar{
    border: 1px solid #dee2ed;
    width: 350px;
    height: 400px;
    white-space: pre-line;
    font-size: 12px;
}
/deep/ .el-dialog__header {
    background-color: #f2f2f2;
    border-bottom: 1px solid #dee2ed;
    .el-dialog__title{
        font-size: 14px;
    }
}
/deep/ .el-dialog__body{
    padding: 0;
    margin-bottom: 80px;
}
/deep/ .el-dialog__footer{
   padding-left:0 ;
   padding-right: 0;
}
.dialog-footer{
    border-top: 1px solid #dee2ed;
    display: block;
    padding: 10px;
    bttton{

    }
}
.select-area{
    margin: 0 auto;
    .select-wrap{
        display: flex;
        font-size: 12px;
        border-bottom: 1px solid #dee2ed;
        padding: 20px 20px 20px 20px;
        //align-items: ;
        .title{
            width: 36px;
            line-height: 30px;
        }
        .select-content{
            flex: 1;
            line-height: 30px;
            overflow: hidden;
            /deep/ .el-checkbox-group .el-checkbox{
                margin-right: 18px;
            }
        }
        .more{
            width: 40px;
            line-height: 24px;
            height: 24px;
            border-radius: 4px;
            background-color: #409eff;
            color: #fff;
            text-align: center;
            cursor: pointer;

        }
    }
}
.condition-area{
    display: flex;
    flex-wrap: wrap;
    border-bottom: 1px solid #dee2ed;
    padding: 10px 20px 10px 20px;
    .condition-item{
        font-size: 12px;
        margin-right: 6px;
        padding: 2px 16px;
        border: 1px solid #409eff;
        border-radius: 2px;
        color: #409eff;
    }
}
.tip-area{
    padding: 120px 0;
    text-align: center;
}
</style>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值