<!-- @format --> <template> <div> <div v-show="false">{{ getDetail }}</div> <a-input placeholder="请选择" readonly="readonly" style="cursor: pointer" v-model:value="choiceCity" @click.stop="showCard"> <template #suffix> <ns-icon name="drow" size="12" @click.stop="showCard" /></template> </a-input> <div v-show="visible" class="selectCard"> <header class="card_header"> <div :style="{ background: regionLevel === 1 ? '#fff' : '' }" @click.stop="check(1)" >省</div > <div :style="{ background: regionLevel === 2 ? '#fff' : '' }" @click.stop="check(2)" >市</div > <div :style="{ background: regionLevel === 3 ? '#fff' : '' }" @click.stop="check(3)" >区</div > </header> <ul> <li :class="choiceCity.split('/')[regionLevel - 1] === item.name ? 'isChoice' : ''" @click.stop="choiceItem(item)" v-for="item in data[regionLevel]" :key="item.code" >{{ item.name }}</li > </ul> </div> </div> </template> <script lang="ts"> import { defineComponent, ref, watch, computed } from 'vue'; import { http } from '/nerv-lib/util/http'; export default defineComponent({ name: 'NsInputCity', props: { value: {}, defaultHomeAddress: { type: String, default: '', }, defaultProvinceCode: { type: String, default: '', }, defaultCityCode: { type: String, default: '', }, defaultAreaCode: { type: String, default: '', }, api: { type: String, default: '', }, isSeparate: { type: Boolean, default: false, }, }, emits: ['change'], setup(props, context) { const visible = ref(false); let choiceCity = ref(''); let province = ref([]); //省 let city = ref([]); //市 let area = ref([]); //区 let provinceCode = ref(''); let cityCode = ref(''); let areaCode = ref(''); let addre = props.defaultHomeAddress.split('/'); if (props.defaultHomeAddress) { context.emit('change', [ addre[0], addre[1], addre[2], props.defaultProvinceCode, props.defaultCityCode, props.defaultAreaCode, props.defaultHomeAddress, ]); } choiceCity.value = props.defaultHomeAddress || ''; // province.value = addRe[0] || ''; // city.value = addRe[1] || ''; // area.value = addRe[2] || ''; provinceCode.value = props.defaultProvinceCode || ''; cityCode.value = props.defaultCityCode || ''; areaCode.value = props.defaultAreaCode || ''; const data = ref([]); data.value[1] = province.value; const regionLevel = ref(1); const showCard = () => { visible.value = true; }; const closeCard = () => { visible.value = false; }; const check = (e) => { regionLevel.value = e; }; const initData = (regionLevel: Number, code?: Number) => { switch (regionLevel) { case 1: province.value = []; break; case 2: city.value = []; data.value[3] = []; break; case 3: area.value = []; break; } async function getDate() { try { let date = {}; date.regionLevel = regionLevel; code ? (date.parentCode = code) : ''; const res = await http.get(props.api || '/api/pension/pension/objs/BaseArea', date); if (res.success) { switch (regionLevel) { case 1: province.value = res.data; break; case 2: city.value = res.data; break; case 3: area.value = res.data; break; } data.value[regionLevel] = res.data; } } catch (err) { console.log(err); } } getDate(); }; watch( () => [ props.defaultHomeAddress, props.defaultProvinceCode, props.defaultCityCode, props.defaultAreaCode, ], ([defaultHomeAddress, defaultProvinceCode, defaultCityCode, defaultAreaCode]) => { if (defaultHomeAddress) { choiceCity.value = defaultHomeAddress; } if (defaultProvinceCode) { regionLevel.value = 1; provinceCode.value = defaultProvinceCode; regionLevel.value = 2; initData(regionLevel.value, provinceCode.value); } if (defaultCityCode) { regionLevel.value = 2; cityCode.value = defaultCityCode; initData(regionLevel.value, provinceCode.value); regionLevel.value = 3; initData(regionLevel.value, cityCode.value); } if (defaultAreaCode) { areaCode.value = defaultAreaCode; regionLevel.value = 3; initData(regionLevel.value, cityCode.value); } }, ); const getDetail = computed(() => { const { value } = props; if (!value) { regionLevel.value = 1; choiceCity.value = ''; provinceCode.value = ''; cityCode.value = ''; areaCode.value = ''; //test.value = []; } else { } // choiceCity.value = value; return value; }); watch( () => props.value, (value) => { if (!value) { data.value[2] = []; data.value[3] = []; } }, { deep: true }, ); return { getDetail, choiceCity, showCard, closeCard, regionLevel, check, visible, initData, province, city, area, provinceCode, cityCode, areaCode, data, }; }, watch: { visible(val) { val ? document.body.addEventListener('click', this.closeCard) : document.body.removeEventListener('click', this.closeCard); }, choiceCity(val) { let info = { label: '', provinceCode: '', cityCode: '', areaCode: '' }; let addressArr = this.defaultHomeAddress.split('/'); info.provinceCode = this.provinceCode; info.cityCode = this.cityCode; info.areaCode = this.areaCode; if (this.isSeparate) { info.label = val.split('/'); this.$emit('change', [ info.label[0], info.label[1], info.label[2], info.provinceCode, info.cityCode, info.areaCode, val, ]); } else { info.label = val; this.$emit('change', [info.label, info.provinceCode, info.cityCode, info.areaCode, val]); } }, // regionLevel(val) { // switch (val) { // case 1: // this.data = this.province; // break; // case 2: // this.data = this.city; // // this.area = []; // break; // case 3: // this.data = this.area; // break; // } // }, }, created() { this.initData(this.regionLevel); }, methods: { // initData(regionLevel: Number, code?: Number) { // const that = this; // switch (regionLevel) { // case 1: // that.province = []; // break; // case 2: // that.city = []; // break; // case 3: // that.area = []; // break; // } // async function getDate() { // try { // let date = {}; // date.regionLevel = regionLevel; // code ? (date.parentCode = code) : ''; // const res = await http.get('/api/pension/pension/objs/BaseArea', date); // if (res.success) { // switch (that.regionLevel) { // case 1: // that.province = res.data; // break; // case 2: // that.city = res.data; // break; // case 3: // that.area = res.data; // break; // } // that.data = res.data; // } // } catch (err) { // console.log(err); // } // } // getDate(); // }, choiceItem(e: any) { switch (this.regionLevel) { case 1: this.choiceCity = e.name; this.provinceCode = e.code; this.cityCode = ''; this.areaCode = ''; this.initData(2, e.code); this.regionLevel = 2; break; case 2: this.choiceCity = this.choiceCity.split('/')[0] + `/${e.name}`; this.cityCode = e.code; this.areaCode = ''; this.initData(3, e.code); this.regionLevel = 3; break; case 3: this.choiceCity = this.choiceCity.split('/')[0] + '/' + this.choiceCity.split('/')[1] + `/${e.name}`; this.areaCode = e.code; this.closeCard(); break; } }, }, }); </script> <style lang="less" scoped> .selectCard { position: absolute; z-index: 4; width: 300px; height: 180px; transform: translateY(5px); box-shadow: 0 2px 8px rgb(0 0 0 / 15%); animation: move-down 0.5s; background: #fff; border: 1px solid #ccc; .card_header { width: 100%; height: 26px; background: rgb(238, 238, 238); display: flex; justify-content: space-between; border-bottom: 1px solid #ccc; div { text-align: center; width: 34%; cursor: pointer; } } ul { width: 100%; height: 150px; overflow: auto; list-style: none; padding: 10px; li { line-height: 30px; cursor: pointer; padding-left: 10px; &:hover { background-color: rgba(3, 141, 218, 0.1); } } } } .isChoice { color: rgb(3, 141, 218); } @keyframes move-down { 0% { transform: scale(0); height: 0px; opacity: 0; } 100% { transform: scale(1); height: 180px; opacity: 1; } } </style>