<template> <view> <text class="uni-input" @tap="open">{{ value }}</text> <uni-popup ref="popup" type="bottom"> <view class="cityselect"> <view class="cityselect-header"> <view class="cityselect-title"> <text>请选择地址</text> </view> <view class="cityselect-nav"> <view class="item" v-if="provinceActive" @tap="changeNav(0)"> <text>{{ provinceActive.n }}</text> </view> <view class="item" v-if="cityActive" @tap="changeNav(1)"> <text>{{ cityActive.n }}</text> </view> <view class="item" v-if="districtActive" @tap="changeNav(2)"> <text>{{ districtActive.n }}</text> </view> <view class="item active" v-else> <text>请选择</text> </view> </view> </view> <view class="cityselect-content"> <swiper class="swiper" disable-touch="true" touchable="false" :current="current"> <swiper-item> <scroll-view scroll-y class="cityScroll"> <view> <view class="cityselect-item" v-for="(item, index) in province" :key="index" @tap="selectProvince(index)"> <view class="cityselect-item-box" :class="{ active: isProvinceActive(item) }"> <text>{{ item.n }}</text> </view> </view> </view> </scroll-view> </swiper-item> <swiper-item> <scroll-view scroll-y class="cityScroll"> <view> <view class="cityselect-item" v-for="(item, index) in city" :key="index" @tap="selectCity(index)"> <view class="cityselect-item-box" :class="{ active: isCityActive(item)}"> <text>{{ item.n }}</text> </view> </view> </view> </scroll-view> </swiper-item> <swiper-item> <scroll-view scroll-y class="cityScroll"> <view> <view class="cityselect-item" v-for="(item, index) in district" :key="index" @tap="selectDistrict(index)"> <view class="cityselect-item-box" :class="{ active: isDistrictActive(item) }"> <text>{{ item.n }}</text> </view> </view> </view> </scroll-view> </swiper-item> </swiper> </view> </view> </uni-popup> </view> </template> <script type="text/babel"> import uniPopup from './uni-popup/uni-popup.vue' import uniPopupMessage from './uni-popup/uni-popup-message.vue' import uniPopupDialog from './uni-popup/uni-popup-dialog.vue' export default { name: 'CitySelect', components: { uniPopup, uniPopupMessage, uniPopupDialog, }, props: ['callback', 'items', 'defaultValue'], data() { return { value: '请选择', show: this.value, province: [], provinceActive: null, city: [], cityActive: null, district: [], districtActive: null, current: 0, } }, watch: { items(next) { this.province = next }, defaultValue(next) { this.value = `${next.province.n} ${next.city.n} ${next.district.n}` this.setDefaultValue(this.items, next) }, }, mounted() { console.log(this) if (this.value) { this.value = this.value } this.province = this.items }, methods: { isProvinceActive(item) { return this.provinceActive && item.v == this.provinceActive.v }, isCityActive(item) { return this.cityActive && item.v == this.cityActive.v }, isDistrictActive(item) { return this.districtActive && item.v == this.districtActive.v }, setDefaultValue(items, value) { if (!items || !value) { return } this.province = items items.map(province => { if (province.n == value.province.n) { this.city = province.c this.provinceActive = { v: province.v, n: value.province.n, } province.c.map(city => { if (city.n == value.city.n) { this.district = city.c this.cityActive = { v: city.v, n: value.city.n, } city.c.map(district => { if (district.n == value.district.n) { this.districtActive = { v: city.v, n: value.district.n, } } }) } }) } }) console.log(this.provinceActive, this.cityActive, this.districtActive) console.log(this) }, open() { this.province = this.items this.provinceActive = null this.cityActive = null this.districtActive = null this.city = [] this.district = [] this.current = 0 this.$refs.popup.open() this.setDefaultValue(this.items, this.defaultValue) }, changeNav(index) { if (index == 0) { this.provinceActive = null } if (index == 1) { this.cityActive = null this.districtActive = null } if (index == 2) { this.districtActive = null } this.current = index }, selectProvince(index) { this.provinceActive = this.province[index] this.city = this.province[index].c this.current = 1 }, selectCity(index) { this.cityActive = this.city[index] this.district = this.city[index].c this.current = 2 }, selectDistrict(index) { this.districtActive = this.district[index] this.value = `${this.provinceActive.n} ${this.cityActive.n} ${this.districtActive.n}` // this.callback({ // province: { // id: this.provinceActive.v, // name: this.provinceActive.n // }, // city: { // id: this.cityActive.v, // name: this.cityActive.n // }, // district: { // id: this.districtActive.v, // name: this.districtActive.n // } // }); this.$emit('callback', { province: { id: this.provinceActive.v, name: this.provinceActive.n, }, city: { id: this.cityActive.v, name: this.cityActive.n, }, district: { id: this.districtActive.v, name: this.districtActive.n, }, }) this.$refs.popup.close() }, }, } </script> <style lang="less"> .cityselect { width: 100%; height: 75%; background-color: #fff; z-index: 1502; position: relative; padding-bottom: 0; padding-bottom: constant(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom); .cityScroll { height: 100%; } .swiper { height: 800rpx; } } .cityselect-header { width: 100%; z-index: 1; } .cityselect-title { width: 100%; font-size: 30rpx; text-align: center; height: 95rpx; line-height: 95rpx; position: relative; &:cityselect-title:after { height: 1px; position: absolute; z-index: 0; bottom: 0; left: 0; content: ''; width: 100%; background-image: linear-gradient(0deg, #ececec 50%, transparent 0); } } .cityselect-nav { width: 100%; padding-left: 20rpx; overflow: hidden; display: flex; align-items: center; justify-content: flex-start; .item { font-size: 26rpx; color: #222; display: block; height: 80rpx; line-height: 92rpx; padding: 0 16rpx; position: relative; margin-right: 30rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 40%; &.active { color: #f23030 !important; border-bottom: 1rpx solid #f23030; } } } .cityselect-content { height: 100%; width: 100%; } .cityselect-item { .cityselect-item-box { display: block; padding: 0 40rpx; position: relative; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; word-break: break-all; text-overflow: ellipsis; line-height: 64rpx; max-height: 65rpx; font-size: 26rpx; color: #333; &.active{ color:#f23030 !important; } &:after { content: ''; height: 1rpx; position: absolute; z-index: 0; bottom: 0; left: 0; width: 100%; background-image: linear-gradient(0deg, #ececec 50%, transparent 0); } } } </style>