308 lines
9.4 KiB
Vue
308 lines
9.4 KiB
Vue
|
|
<template>
|
||
|
|
<div class="form-item-box zj-addressSelect-wrap" :style="{ width: width }">
|
||
|
|
<el-select :placeholder="placeholder" :clearable="true" v-model="value" popper-class="adderss-select"
|
||
|
|
@clear="handleClear">
|
||
|
|
<el-option value="1" style="display: none"></el-option>
|
||
|
|
<el-input v-if="filterable" v-model="filterText" style="margin-bottom: 5px; font-size: 12px"
|
||
|
|
:prefix-icon="Search" />
|
||
|
|
<el-tabs v-model="activeName" type="card" @tab-click="handleClick">
|
||
|
|
<el-tab-pane name="province" :label="province ? province : '请选择'">
|
||
|
|
<div class="citylist">
|
||
|
|
<ul>
|
||
|
|
<li @click="chooseProvince(item)" v-for="item in provinceList" :key="item.code"
|
||
|
|
:class="{ selected: provinceId == item.code }">
|
||
|
|
{{ item.name }}
|
||
|
|
</li>
|
||
|
|
</ul>
|
||
|
|
</div>
|
||
|
|
</el-tab-pane>
|
||
|
|
<el-tab-pane name="city" v-if="cityList.length > 0" :label="city ? city : '请选择'">
|
||
|
|
<div class="citylist">
|
||
|
|
<ul>
|
||
|
|
<li @click="chooseCity(item)" v-for="item in cityList" :class="{ selected: cityId == item.code }"
|
||
|
|
:key="item.code">
|
||
|
|
{{ item.name }}
|
||
|
|
</li>
|
||
|
|
</ul>
|
||
|
|
</div>
|
||
|
|
</el-tab-pane>
|
||
|
|
<el-tab-pane name="area" v-if="areaList.length > 0" :label="area ? area : '请选择'">
|
||
|
|
<div class="citylist">
|
||
|
|
<ul>
|
||
|
|
<li @click="chooseArea(item)" v-for="item in areaList" :key="item.code"
|
||
|
|
:class="{ selected: areaId == item.code }">
|
||
|
|
{{ item.name }}
|
||
|
|
</li>
|
||
|
|
</ul>
|
||
|
|
</div>
|
||
|
|
</el-tab-pane>
|
||
|
|
<el-tab-pane name="street" v-if="streetList.length > 0" :label="street ? street : '请选择'">
|
||
|
|
<div class="citylist">
|
||
|
|
<ul>
|
||
|
|
<li @click="chooseStreet(item)" v-for="item in streetList" :key="item.code"
|
||
|
|
:class="{ selected: streetId == item.code }">
|
||
|
|
{{ item.name }}
|
||
|
|
</li>
|
||
|
|
</ul>
|
||
|
|
</div>
|
||
|
|
</el-tab-pane>
|
||
|
|
</el-tabs>
|
||
|
|
</el-select>
|
||
|
|
<!-- <el-icon class="errorIcon">
|
||
|
|
<circle-close-filled />
|
||
|
|
</el-icon>
|
||
|
|
<el-icon class="checkIcon">
|
||
|
|
<circle-check-filled />
|
||
|
|
</el-icon> -->
|
||
|
|
</div>
|
||
|
|
</template>
|
||
|
|
<script setup>
|
||
|
|
import { COMPONENT_WIDTH } from '@/constant';
|
||
|
|
import { nextTick, ref, watch } from "vue";
|
||
|
|
import { Search } from "@element-plus/icons-vue";
|
||
|
|
const emits = defineEmits(["handleChange"]); //子组件向父组件事件传递
|
||
|
|
const props = defineProps({
|
||
|
|
placeholder: {
|
||
|
|
default: "选择地址",
|
||
|
|
type: String
|
||
|
|
},
|
||
|
|
filterable: {
|
||
|
|
default: false,
|
||
|
|
type: Boolean
|
||
|
|
},
|
||
|
|
address: {
|
||
|
|
default: () => [],
|
||
|
|
type: Array
|
||
|
|
},
|
||
|
|
defaultConf: {
|
||
|
|
type: Object,
|
||
|
|
default: () => ({
|
||
|
|
children: "",
|
||
|
|
label: "",
|
||
|
|
id: ""
|
||
|
|
})
|
||
|
|
},
|
||
|
|
width: {
|
||
|
|
default: COMPONENT_WIDTH,
|
||
|
|
type: String
|
||
|
|
}
|
||
|
|
});
|
||
|
|
const filterText = ref("");
|
||
|
|
const activeName = ref("province");
|
||
|
|
const value = ref("");
|
||
|
|
const valueId = ref([]);
|
||
|
|
const province = ref("");
|
||
|
|
const provinceId = ref("");
|
||
|
|
const provinceList = ref([]);
|
||
|
|
provinceList.value = require("@/constant/pca-code.json");
|
||
|
|
const city = ref("");
|
||
|
|
const cityId = ref("");
|
||
|
|
const cityList = ref([]);
|
||
|
|
const area = ref("");
|
||
|
|
const areaId = ref("");
|
||
|
|
const areaList = ref([]);
|
||
|
|
const street = ref("");
|
||
|
|
const streetId = ref("");
|
||
|
|
const streetList = ref([]);
|
||
|
|
const provinceListFilter = ref([]);
|
||
|
|
provinceListFilter.value = require("@/constant/pca-code.json");
|
||
|
|
const cityListFilter = ref([]);
|
||
|
|
const areaListFilter = ref([]);
|
||
|
|
const streetListFilter = ref([]);
|
||
|
|
nextTick(() => {
|
||
|
|
if (props.address.length > 0) {
|
||
|
|
init(props.address);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
watch(filterText, (val) => {
|
||
|
|
filterNode(val);
|
||
|
|
});
|
||
|
|
const handleClick = () => {
|
||
|
|
filterText.value = "";
|
||
|
|
filterNode("");
|
||
|
|
};
|
||
|
|
const filterNode = (val) => {
|
||
|
|
if (activeName.value === "province") {
|
||
|
|
if (val !== "") {
|
||
|
|
provinceList.value = provinceListFilter.value.filter(
|
||
|
|
(item) => item[props.defaultConf.label].indexOf(val) !== -1
|
||
|
|
);
|
||
|
|
} else {
|
||
|
|
provinceList.value = provinceListFilter.value;
|
||
|
|
}
|
||
|
|
} else if (activeName.value === "city") {
|
||
|
|
if (val !== "") {
|
||
|
|
cityList.value = cityListFilter.value.filter(
|
||
|
|
(item) => item[props.defaultConf.label].indexOf(val) !== -1
|
||
|
|
);
|
||
|
|
} else {
|
||
|
|
cityList.value = cityListFilter.value;
|
||
|
|
}
|
||
|
|
} else if (activeName.value === "area") {
|
||
|
|
if (val !== "") {
|
||
|
|
areaList.value = areaListFilter.value.filter(
|
||
|
|
(item) => item[props.defaultConf.label].indexOf(val) !== -1
|
||
|
|
);
|
||
|
|
} else {
|
||
|
|
areaList.value = areaListFilter.value;
|
||
|
|
}
|
||
|
|
} else if (activeName.value === "street") {
|
||
|
|
if (val !== "") {
|
||
|
|
streetList.value = streetListFilter.value.filter(
|
||
|
|
(item) => item[props.defaultConf.label].indexOf(val) !== -1
|
||
|
|
);
|
||
|
|
} else {
|
||
|
|
streetList.value = streetListFilter.value;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
const chooseProvince = (e) => {
|
||
|
|
province.value = e[props.defaultConf.label];
|
||
|
|
provinceId.value = e[props.defaultConf.id];
|
||
|
|
value.value = province.value;
|
||
|
|
valueId.value = [provinceId.value];
|
||
|
|
emits("handleChange", valueId.value);
|
||
|
|
city.value = "";
|
||
|
|
cityId.value = "";
|
||
|
|
cityList.value = [];
|
||
|
|
areaList.value = [];
|
||
|
|
streetList.value = [];
|
||
|
|
filterText.value = "";
|
||
|
|
provinceList.value.forEach((el) => {
|
||
|
|
if (el[props.defaultConf.id] === e[props.defaultConf.id]) {
|
||
|
|
if (el[props.defaultConf.children]) {
|
||
|
|
activeName.value = "city";
|
||
|
|
cityList.value = el[props.defaultConf.children];
|
||
|
|
cityListFilter.value = el[props.defaultConf.children];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
};
|
||
|
|
const chooseCity = (e) => {
|
||
|
|
city.value = e[props.defaultConf.label];
|
||
|
|
cityId.value = e[props.defaultConf.id];
|
||
|
|
area.value = "";
|
||
|
|
areaId.value = "";
|
||
|
|
areaList.value = [];
|
||
|
|
streetList.value = [];
|
||
|
|
filterText.value = "";
|
||
|
|
value.value = province.value + "/" + city.value;
|
||
|
|
valueId.value = [provinceId.value, cityId.value];
|
||
|
|
emits("handleChange", valueId.value);
|
||
|
|
cityList.value.forEach((el) => {
|
||
|
|
if (el[props.defaultConf.id] === e[props.defaultConf.id]) {
|
||
|
|
if (el[props.defaultConf.children]) {
|
||
|
|
activeName.value = "area";
|
||
|
|
areaList.value = el[props.defaultConf.children];
|
||
|
|
areaListFilter.value = el[props.defaultConf.children];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
};
|
||
|
|
const chooseArea = (e) => {
|
||
|
|
area.value = e[props.defaultConf.label];
|
||
|
|
areaId.value = e[props.defaultConf.id];
|
||
|
|
street.value = "";
|
||
|
|
streetId.value = "";
|
||
|
|
streetList.value = [];
|
||
|
|
filterText.value = "";
|
||
|
|
value.value = province.value + "/" + city.value + "/" + area.value;
|
||
|
|
valueId.value = [provinceId.value, cityId.value, areaId.value];
|
||
|
|
emits("handleChange", valueId.value);
|
||
|
|
areaList.value.forEach((el) => {
|
||
|
|
if (el[props.defaultConf.id] === e[props.defaultConf.id]) {
|
||
|
|
if (el[props.defaultConf.children]) {
|
||
|
|
streetList.value = el[props.defaultConf.children];
|
||
|
|
activeName.value = "street";
|
||
|
|
streetListFilter.value = el[props.defaultConf.children];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
};
|
||
|
|
const chooseStreet = (e) => {
|
||
|
|
street.value = e[props.defaultConf.label];
|
||
|
|
streetId.value = e[props.defaultConf.id];
|
||
|
|
value.value =
|
||
|
|
province.value + "/" + city.value + "/" + area.value + "/" + street.value;
|
||
|
|
valueId.value = [
|
||
|
|
provinceId.value,
|
||
|
|
cityId.value,
|
||
|
|
areaId.value,
|
||
|
|
streetId.value
|
||
|
|
];
|
||
|
|
emits("handleChange", valueId.value);
|
||
|
|
};
|
||
|
|
const handleClear = () => {
|
||
|
|
activeName.value = "province";
|
||
|
|
value.value = "";
|
||
|
|
valueId.value = [];
|
||
|
|
province.value = "";
|
||
|
|
provinceId.value = "";
|
||
|
|
city.value = "";
|
||
|
|
cityId.value = "";
|
||
|
|
cityList.value = [];
|
||
|
|
area.value = "";
|
||
|
|
areaId.value = "";
|
||
|
|
areaList.value = [];
|
||
|
|
street.value = "";
|
||
|
|
streetId.value = "";
|
||
|
|
streetList.value = [];
|
||
|
|
cityListFilter.value = [];
|
||
|
|
areaListFilter.value = [];
|
||
|
|
streetListFilter.value = [];
|
||
|
|
filterText.value = "";
|
||
|
|
filterNode("");
|
||
|
|
emits("handleChange", []);
|
||
|
|
};
|
||
|
|
const treeValueFind = (tree, arr, newArr = []) => {
|
||
|
|
tree.forEach((el) => {
|
||
|
|
if (el[props.defaultConf.id] === arr) {
|
||
|
|
newArr.push(el);
|
||
|
|
}
|
||
|
|
if (el[props.defaultConf.children]) {
|
||
|
|
treeValueFind(el[props.defaultConf.children], arr, newArr);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
return newArr;
|
||
|
|
};
|
||
|
|
const init = (data) => {
|
||
|
|
let obj1 = treeValueFind(provinceList.value, data[0])[0];
|
||
|
|
province.value = obj1[props.defaultConf.label];
|
||
|
|
provinceId.value = obj1[props.defaultConf.id];
|
||
|
|
cityList.value = obj1[props.defaultConf.children];
|
||
|
|
cityListFilter.value = obj1[props.defaultConf.children];
|
||
|
|
value.value = province.value;
|
||
|
|
if (data[1]) {
|
||
|
|
let obj2 = treeValueFind(provinceList.value, data[1])[0];
|
||
|
|
city.value = obj2[props.defaultConf.label];
|
||
|
|
cityId.value = obj2[props.defaultConf.id];
|
||
|
|
areaList.value = obj2[props.defaultConf.children];
|
||
|
|
areaListFilter.value = obj2[props.defaultConf.children];
|
||
|
|
value.value = province.value + "/" + city.value;
|
||
|
|
}
|
||
|
|
if (data[2]) {
|
||
|
|
let obj3 = treeValueFind(provinceList.value, data[2])[0];
|
||
|
|
area.value = obj3[props.defaultConf.label];
|
||
|
|
areaId.value = obj3[props.defaultConf.id];
|
||
|
|
streetList.value = obj3[props.defaultConf.children];
|
||
|
|
streetListFilter.value = obj3[props.defaultConf.children];
|
||
|
|
value.value = province.value + "/" + city.value + "/" + area.value;
|
||
|
|
}
|
||
|
|
if (data[3]) {
|
||
|
|
let obj4 = treeValueFind(provinceList.value, data[3])[0];
|
||
|
|
street.value = obj4[props.defaultConf.label];
|
||
|
|
streetId.value = obj4[props.defaultConf.id];
|
||
|
|
value.value =
|
||
|
|
province.value + "/" + city.value + "/" + area.value + "/" + street.value;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style lang="scss" scoped>
|
||
|
|
.zj-addressSelect-wrap {
|
||
|
|
::v-deep .el-select {
|
||
|
|
width: 100%;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</style>
|