文件areaData中北京 一小块
[{"parentCode":"CN","regionCode":"110000","regionName":"北京市","regionLevel":1,"children":[{"parentCode":"110000","regionCode":"110100000000","regionName":"北京市","regionLevel":2,"children":[{"parentCode":"110100000000","regionCode":"110101000000","regionName":"东城区","regionLevel":3,"children":null},{"parentCode":"110100000000","regionCode":"110102000000","regionName":"西城区","regionLevel":3,"children":null},{"parentCode":"110100000000","regionCode":"110105000000","regionName":"朝阳区","regionLevel":3,"children":null},{"parentCode":"110100000000","regionCode":"110106000000","regionName":"丰台区","regionLevel":3,"children":null},{"parentCode":"110100000000","regionCode":"110107000000","regionName":"石景山区","regionLevel":3,"children":null},{"parentCode":"110100000000","regionCode":"110108000000","regionName":"海淀区","regionLevel":3,"children":null},{"parentCode":"110100000000","regionCode":"110109000000","regionName":"门头沟区","regionLevel":3,"children":null},{"parentCode":"110100000000","regionCode":"110111000000","regionName":"房山区","regionLevel":3,"children":null},{"parentCode":"110100000000","regionCode":"110112000000","regionName":"通州区","regionLevel":3,"children":null},{"parentCode":"110100000000","regionCode":"110113000000","regionName":"顺义区","regionLevel":3,"children":null},{"parentCode":"110100000000","regionCode":"110114000000","regionName":"昌平区","regionLevel":3,"children":null},{"parentCode":"110100000000","regionCode":"110115000000","regionName":"大兴区","regionLevel":3,"children":null},{"parentCode":"110100000000","regionCode":"110116000000","regionName":"怀柔区","regionLevel":3,"children":null},{"parentCode":"110100000000","regionCode":"110117000000","regionName":"平谷区","regionLevel":3,"children":null},{"parentCode":"110100000000","regionCode":"110118000000","regionName":"密云区","regionLevel":3,"children":null},{"parentCode":"110100000000","regionCode":"110119000000","regionName":"延庆区","regionLevel":3,"children":null}]}]}]
组件 duoxuan.vue
<script setup lang="ts">
import {ref, onMounted, defineEmits,defineProps} from "vue";
import areaData from '@/assets/json/area.json';
// areaData 数据格式
// {
// regionCode,
// regionName,
// children:[]
// ... 无用数据
// }
import { Modal } from 'ant-design-vue';
import Zhongxuan from "./zhongxuan.vue";
const value = ref([])
const data = ref([])
const a = ref([])
const visible=ref(true)
const props=defineProps(['curForm_data'])
const emit = defineEmits(['confirmEvent']);
onMounted(() => {
a.value = shaixuan(areaData)
huixian()
})
//回显 遍历省市区编号开头 对应再深入遍历
const huixian=()=>{
console.log(props.curForm_data[0].sele_area_id_array)
props.curForm_data[0].sele_area_id_array.forEach(item=>{
a.value.forEach((i)=>{
if(i.regionCode.slice(0,3)===item.slice(0,3)) {
i.children.forEach((it)=>{
if(it.regionCode.slice(3,5)==item.slice(3,5)) {
it.children.forEach((ite)=>{
if(item===ite.regionCode){
if(!it.huixian){
it.huixian=[]
}
it.huixian.push(ite.regionCode)
console.log(it.huixian)
}
})
}
})
}
})
})
}
const handleOk = (e: MouseEvent) => {
queren()
visible.value = false;
};
//将数据格式筛选
const shaixuan = (v) => {
let box1 = []
v.forEach((item, index) => {
const box2 = []
if (item.children) {
const box3 = shaixuan(item.children)
box1.push({
regionCode: item.regionCode,
regionName: item.regionName,
children: box3
})
return
}
box1.push({
regionCode: item.regionCode,
regionName: item.regionName
})
})
return box1
}
const itemContent = (obj) => {
let box = data.value.filter((i) => {
return i.regionName === obj.regionName
})
if (box.length === 0) {
data.value.push(obj)
} else {
data.value.forEach((ite, ind) => {
if (ite.regionName === obj.regionName) {
data.value.splice(ind, 1, obj)
}
})
}
}
const queren = () => {
let deliver_areas = []
let sele_area_id_array = []
data.value.forEach((item) => {
item.value.length > 0 && item.value.forEach((it) => {
sele_area_id_array.push(it.regionCode)
deliver_areas.push(it.regionName)
})
})
emit('confirmEvent', {
deliver_areas: deliver_areas.toString(),
sele_area_id_array
})
}
</script>
<template>
<!-- {{a}}-->
<div @click="visible=true">xianshi</div>
<Modal width="1000px" style="top: 20px" v-model:visible="visible" title="选择地址" @ok="handleOk">
<div style="max-height: 600px;overflow-y: auto;padding: 20px" >
<div v-for="item in a">
<zhongxuan @itemContent="itemContent" :content="item" />
<div style="border-bottom: 1px solid #e7e7e7"></div>
</div>
</div>
</Modal>
</template>
组件 zhongxuan.vue
<script setup lang="ts">
import {Checkbox} from "ant-design-vue";
import Xuanze from "./xuanze.vue";
import {defineEmits, defineProps, reactive, ref, watch} from "vue";
const props = defineProps(['content'])
const data = ref([])
const value = reactive({
value: [],
checkAll: false,
})
const xuan = ref(null)
const indeterminate = ref(false)
const emit = defineEmits(['itemContent']);
const shuju = (obj) => {
let box = data.value.filter((i) => {
return i.regionName === obj.regionName
})
if (box.length === 0) {
data.value.push(obj)
} else {
data.value.forEach((ite, ind) => {
if (ite.regionName === obj.regionName) {
data.value.splice(ind, 1, obj)
}
})
}
emit('itemContent', {regionName: props.content.regionName, value: obj.value})
}
const zhuangt = (v, val) => {
if (v == 0) {
//取消 删除
value.value.forEach((item, index) => {
if (item.regionName == val.regionName) {
value.value.splice(index, 1)
}
})
} else if (v == 1) {
let ind = null
let x
value.value.forEach((item, index) => {
console.log(item.regionName, val.regionName)
if (item.regionName == val.regionName) {
ind = index
}
})
if (ind === null) {
value.value.push(val)
ind = value.value.length - 1
} else {
value.value.forEach((item, index) => {
if (item.regionName == val.regionName) {
console.log(index)
value.value.splice(index, 1, val)
ind = index
}
})
}
// value.value.forEach((item, index) => {
// if (item.regionName == val.regionName) {
// value.value[index]=val
// // value.value.splice(index, 1)
// }
// })
if (value.value[ind].children.length !== 0 && (value.value[ind].children.length !== val.children.length)) {
indeterminate.value = true
}
// value.value.length>0&&(indeterminate.value = true)
// indeterminate.value = true
} else if (v == 2) {
let x = null
value.value.forEach((item, index) => {
if (item.regionName == val.regionName) {
value.value.splice(index, 1, val)
x = true
}
})
if (x == null) {
value.value.push(val)
}
}
}
const onCheckAllChange = (e: any) => {
Object.assign(value, {
value: e.target.checked ? [...props.content.children] : [],
indeterminate: false,
});
if (e.target.checked) {
//省全选 控制子全选
xuan.value.forEach((item, index) => {
xuan.value[index].xuan()
})
} else {
//省取消 控制子取消
xuan.value.forEach((item, index) => {
xuan.value[index].qing()
})
}
};
watch(() => value.value, (v) => {
if (value.value.length === props.content.children.length) {
// 判断每个的数组是不是一样长 半选或全选
let num = 0
value.value.forEach((item, index) => {
props.content.children.forEach((it, ind) => {
console.log(item.regionName, props.content.children[ind].regionName)
if (item.regionName === props.content.children[ind].regionName) {
if (item.children.length === props.content.children[ind].children.length) {
num++
}
}
})
})
if (num === props.content.children.length) {
//全选
indeterminate.value = false
value.checkAll = true
} else {
// 半选
indeterminate.value = true
value.checkAll = false
}
} else if (value.value.length === 0) {
indeterminate.value = false
value.checkAll = false
} else {
indeterminate.value = true
value.checkAll = false
}
}, {deep: true})
</script>
<template>
<Checkbox :indeterminate="indeterminate" @change="onCheckAllChange" :checked="value.checkAll">
{{ content.regionName }}
</Checkbox>
<div v-for="it in content.children" style="margin-left: 20px">
回显数据: {{it.huixian}}
<Xuanze ref="xuan" @shuju="shuju" @zhuangt="zhuangt" :content="it" :huixian="it.huixian"/>
</div>
</template>
组件 xuanze.vue
<script setup lang="ts">
import {ref, defineProps, watch, reactive, onMounted, defineEmits, defineExpose} from "vue";
import {Checkbox, CheckboxGroup} from 'ant-design-vue'
const props = defineProps(['content','huixian'])
const emit = defineEmits(['zhuangt', 'shuju']);
let a = ref(false)
const state = reactive({
indeterminate: false,
checkAll: false,
checkedList: [],
});
onMounted(()=>{
console.log(props.huixian,props.content)
if(props.huixian?.length>0){
props.content.children.forEach(item=>{
if(props.huixian.includes(item.regionCode)){
state.checkedList.push(item)
}
})
}
})
const onCheckAllChange = (e: any) => {
Object.assign(state, {
checkedList: e.target.checked ? [...props.content.children] : [],
indeterminate: false,
});
};
watch(
() => state.checkedList,
val => {
state.indeterminate = !!val.length && val.length < props.content.children.length;
state.checkAll = val.length === props.content.children?.length;
if (val.length === props.content.children?.length) {
emit('zhuangt', 2, props.content) //全取消 删除
} else if (val.length && val.length < props.content.children?.length) {
emit('zhuangt', 1, {regionCode:props.content.regionCode,regionName:props.content.regionName,children:state.checkedList}) //半选 现在选的
} else {
emit('zhuangt', 0, props.content) //全选 添加
}
//给父级最新选择数据
emit('shuju', {regionName: props.content.regionName, value: state.checkedList})
},
{immediate: true,deep:true}
);
const xuan = () => {
state.checkAll = true
state.checkedList = [...props.content.children]
}
const qing = () => {
state.checkedList.length = 0
state.checkAll = false
}
defineExpose({
qing,
xuan
})
</script>
<template>
选中数据:{{state.checkedList}}
<div>
<div style="display: flex">
<Checkbox :indeterminate="state.indeterminate"
@change="onCheckAllChange" :checked="state.checkAll">{{ content.regionName }}
</Checkbox>
<div @click="a=!a" style="cursor:pointer;color: #0b79ee">展开授权</div>
</div>
<CheckboxGroup style="margin-left: 20px" v-if="a" v-model:value="state.checkedList">
<Checkbox v-for="i in content.children" :value="i">{{ i.regionName }}</Checkbox>
</CheckboxGroup>
</div>
</template>
<style scoped lang="less">
/deep/ .ant-checkbox-wrapper+.ant-checkbox-wrapper{
margin-left: 10px;
}
/deep/ .ant-checkbox-wrapper{
margin-left: 10px;
}
</style>
使用 @confirm-event为回调事件 一个参数为收集的数据 回显数据传入curForm_data 格式为
[ { "key": 0, "deliver_areas": "东城区,西城区,朝阳区,丰台区,石景山区,海淀区,门头沟区,武清区,宝坻区,桥西区,高邑县", "trans_weight": 1, "trans_fee": 1, "trans_add_weight": 1, "trans_add_fee": 1, "sele_area_id_array": [ "110101000000", "110102000000", "110105000000", "110106000000", "110107000000", "110108000000", "110109000000", "120114000000", "120115000000", "130104000000", "130127000000" ], "freightExtendId": 50 } ]
<duoxuan @confirm-event="sldHandleConfirmPer" :curForm_data="curForm_data?.data_table"/>