需求
功能布局如下图,实现根据一级选项的code去查询二级选项,并且其他二级选择框无法再次选中已经被选的二级选项。
代码实现
HTML
一级选择框:
<div style="margin-top: 20px;" v-for="(item, index) in questions" :key="index">
<span><span style="color: red;">*</span>问题类别:</span>
<a-select style="width: 240px;" :value="item.primaryIndicators.itemCode"
@change="handleChangetypes(index,$event)">
<a-select-option v-for="itemone,ccindex in problemTypeoptions" :key="itemone.itemCode+ccindex"
:value="itemone.itemCode">{{ itemone.itemName }}
</a-select-option>
</a-select>
二级选择框:
<a-select :showSearch="false" style="width: 240px;margin-left: 40px;" mode="multiple"
@change="handlechildtypes(index, item.secondaryIndicatorkeys)"
v-model:value="item.secondaryIndicatorkeys">
<a-select-option v-for="citem, cindex in item.CategoryDetails" :key="cindex"
:value="citem.itemCode">{{ citem.itemName }}
</a-select-option>
</a-select>
</div>
数据结构
questions:({
primaryIndicators: {
itemCode: "",
itemName: "",
parentItemCode: "",
changed: true
},
CategoryDetails: [
],
secondaryIndicatorkeys: [],
secondaryIndicators: [{
itemCode: "",
itemName: "",
parentItemCode: "",
changed: true
}]
})
我们看到二级选择框的选择项并没有像一级一样直接双向绑定选项的code,因为一级选项虽然能多选,但是数据结构是对象,而二级是数组,如果直接item.secondaryIndicators[index].itemCode就有问题,故用一个secondaryIndicatorkeys来单独存储二级选项的code。
JS
改变一级选项:
将primaryIndicators的值更改为现在对应选项的code,使用getProblemTypeInfo接口用一级选项的code查询二级选项,将查询回来的二级选项存于questions中的CategoryDetails数组:
const handleChangetypes = async (index, code) => {
questions.value[index].primaryIndicators = problemTypeoptions.value.find(item => {
return item.itemCode == code
})
questions.value[index].CategoryDetails = []
questions.value[index].secondaryIndicatorkeys = [],
questions.value[index].secondaryIndicators = [],
spinning.value = true
let cdatas = await useStore.getproblemTypeinfo(1, code)
questions.value[index].CategoryDetails = cdatas
spinning.value = false
}
因为二级绑定的不是secondaryIndicators,故选择二级后需要把数据传递给真正要穿回后端的questions的secondaryIndicators:
const handlechildtypes = (index, slects) => {
questions.value[index].secondaryIndicators = []
slects?.map(item => {
let cdataobjs = questions.value[index].CategoryDetails.find(citem => {
return citem.itemCode == item
})
questions.value[index].secondaryIndicators.push(cdataobjs)
})
}
上面就实现了基本的级联功能,但是没用实现二级选项的互斥,下面我们来实现二级选项互斥。
使用了a-select组件API中的select和deselect来监听选中的二级选项增减:
<div v-for="fitem, findex in Questionitems" :key="findex" v-if="allquestions"
style="margin-bottom: 10px;">
<a-select placeholder="请选择" @select="selectmytype($event, findex)"
v-model:value="fitem.primaryIndicators" style="width: 150px">
<template v-for="item, index in allquestions">
<a-select-option :value="item?.primaryIndicators?.itemCode">
{{ item?.primaryIndicators?.itemName }}
</a-select-option>
</template>
</a-select>
<a-select @select="selecttype($event, fitem.primaryIndicators, true)"
@deselect="selecttype($event, fitem.primaryIndicators, false)" mode="multiple"
:disabled="!fitem.primaryIndicators.length" placeholder="请选择"
v-model:value="fitem.secondaryIndicators" style="width: 150px;margin-left: 10px;">
<template v-for="citem, cindex in getChileds(fitem.primaryIndicators)" :key="cindex">
<a-select-option
:disabled="getchildrendis(citem.disabled, fitem.secondaryIndicators.includes(citem?.itemCode))"
:value="citem?.itemCode">
<span :title="citem?.itemName">
{{ citem?.itemName }}
</span>
</a-select-option>
</template>
</a-select>
</div>
选项映射到返回表单中:
const selectmytype = (itemcode, index) => {
Questionitems.value[index].myprimaryIndicators = allquestions.value.find(item => {
return item.primaryIndicators.itemCode == itemcode
})?.primaryIndicators
}
将后端查询到的数据回显到页面,并将选中的二级选项选项标识符置为真,这样修改表单只能从后端返回的二级中选(而非全部二级选项),如果不需要限制则不需加这个标识符:
const selecttype = (event, fitemcode, newtype) => {
allquestions.value = allquestions.value.map(item => {
if (item.primaryIndicators.itemCode == fitemcode) {
item.secondaryIndicators = item.secondaryIndicators.map(citem => {
if (citem.itemCode == event) {
citem.disabled = newtype
}
return citem;
})
}
return item;
})
}
获得二级选项:
const getChileds = (code) => {
let chiledtypes = allquestions.value.find(item => {
return item.primaryIndicators.itemCode == code
})
return chiledtypes ? chiledtypes.secondaryIndicators : []
}
判断二级选项被选中没有:
const getchildrendis = (boll1, bool2) => {
return boll1 && !bool2;
}