¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <u-popup :show="modelValue" mode="bottom" :popup="false" :mask="true" :closeable="true" |
| | | :safe-area-inset-bottom="true" close-icon-color="#ffffff" :z-index="uZIndex" :maskCloseAble="maskCloseAble" |
| | | @close="close"> |
| | | <u-tabs v-if="modelValue" :list="genTabsList" :scrollable="true" :current="tabsIndex" @change="tabsChange" |
| | | ref="tabs" /> |
| | | <view class="area-box"> |
| | | <view class="u-flex" :class="{ 'change': isChange }"> |
| | | <view class="area-item"> |
| | | <view class="u-padding-10 u-bg-gray" style="height: 100%;"> |
| | | <scroll-view :scroll-y="true" style="height: 100%"> |
| | | <u-cell-group> |
| | | <u-cell v-for="(item, index) in provinces" :title="item.label" :arrow="false" |
| | | :index="index" :key="index" @click="provinceChange(index)"> |
| | | <template v-slot:right-icon> |
| | | <u-icon v-if="isChooseP && province === index" size="17" |
| | | name="checkbox-mark"></u-icon> |
| | | </template> |
| | | </u-cell> |
| | | </u-cell-group> |
| | | </scroll-view> |
| | | </view> |
| | | </view> |
| | | <view class="area-item"> |
| | | <view class="u-padding-10 u-bg-gray" style="height: 100%;"> |
| | | <scroll-view :scroll-y="true" style="height: 100%"> |
| | | <u-cell-group v-if="isChooseP"> |
| | | <u-cell v-for="(item, index) in citys" :title="item.label" :arrow="false" :index="index" |
| | | :key="index" @click="cityChange(index)"> |
| | | <template v-slot:right-icon> |
| | | <u-icon v-if="isChooseC && city === index" size="17" |
| | | name="checkbox-mark"></u-icon> |
| | | </template> |
| | | </u-cell> |
| | | </u-cell-group> |
| | | </scroll-view> |
| | | </view> |
| | | </view> |
| | | <view class="area-item"> |
| | | <view class="u-padding-10 u-bg-gray" style="height: 100%;"> |
| | | <scroll-view :scroll-y="true" style="height: 100%"> |
| | | <u-cell-group v-if="isChooseC"> |
| | | <u-cell v-for="(item, index) in areas" :title="item.label" :arrow="false" :index="index" |
| | | :key="index" @click="areaChange(index)"> |
| | | <template v-slot:right-icon> |
| | | <u-icon v-if="isChooseA && area === index" size="17" |
| | | name="checkbox-mark"></u-icon> |
| | | </template> |
| | | </u-cell> |
| | | </u-cell-group> |
| | | </scroll-view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </u-popup> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { ref, computed, onMounted, PropType } from 'vue'; |
| | | import provincesSource from "./province.js"; |
| | | import citysSource from "./city.js"; |
| | | import areasSource from "./area.js"; |
| | | |
| | | // å®ä¹æ¥å£ |
| | | interface Region { |
| | | label: string; |
| | | value: string; |
| | | } |
| | | |
| | | interface CitySelectResult { |
| | | province: Region; |
| | | city: Region; |
| | | area: Region; |
| | | } |
| | | |
| | | interface TabItem { |
| | | name: string; |
| | | } |
| | | |
| | | // Props å®ä¹ |
| | | const props = defineProps({ |
| | | // éè¿ååç»å®æ§å¶ç»ä»¶çå¼¹åºä¸æ¶èµ· |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | // é»è®¤æ¾ç¤ºçå°åºï¼å¯ä¼ 类似["æ²³åç", "秦çå²å¸", "åæ´æ²³åº"] |
| | | defaultRegion: { |
| | | type: Array as PropType<string[]>, |
| | | default: () => [] |
| | | }, |
| | | // é»è®¤æ¾ç¤ºå°åºçç¼ç ï¼defaultRegionåareaCodeåæ¶åå¨ï¼areaCodeä¼å
ï¼å¯ä¼ 类似["13", "1303", "130304"] |
| | | areaCode: { |
| | | type: Array as PropType<string[]>, |
| | | default: () => [] |
| | | }, |
| | | // æ¯å¦å
许éè¿ç¹å»é®ç½©å
³éPicker |
| | | maskCloseAble: { |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | // å¼¹åºçz-indexå¼ |
| | | zIndex: { |
| | | type: [String, Number], |
| | | default: 0 |
| | | } |
| | | }); |
| | | |
| | | // äºä»¶å®ä¹ |
| | | const emit = defineEmits<{ |
| | | (e: 'update:modelValue', value: boolean): void; |
| | | (e: 'close'): void; |
| | | (e: 'city-change', result: CitySelectResult): void; |
| | | }>(); |
| | | |
| | | const cityValue = ref(""); |
| | | const isChooseP = ref(false); // æ¯å¦å·²ç»éæ©äºç |
| | | const province = ref(0); // ççº§ä¸æ |
| | | const provinces = ref<Region[]>(provincesSource); |
| | | const isChooseC = ref(false); // æ¯å¦å·²ç»éæ©äºå¸ |
| | | const city = ref(0); // å¸çº§ä¸æ |
| | | const citys = ref<Region[]>(citysSource[0]); |
| | | const isChooseA = ref(false); // æ¯å¦å·²ç»éæ©äºåº |
| | | const area = ref(0); // åºçº§ä¸æ |
| | | const areas = ref<Region[]>(areasSource[0][0]); |
| | | const tabsIndex = ref(0); |
| | | const tabs = ref(); |
| | | |
| | | // 计ç®å±æ§ |
| | | const isChange = computed(() => { |
| | | return tabsIndex.value > 1; |
| | | }); |
| | | |
| | | const genTabsList = computed((): TabItem[] => { |
| | | let tabsList: TabItem[] = [{ |
| | | name: "è¯·éæ©" |
| | | }]; |
| | | |
| | | if (isChooseP.value) { |
| | | tabsList[0].name = provinces.value[province.value].label; |
| | | tabsList[1] = { |
| | | name: "è¯·éæ©" |
| | | }; |
| | | } |
| | | |
| | | if (isChooseC.value) { |
| | | tabsList[1].name = citys.value[city.value].label; |
| | | tabsList[2] = { |
| | | name: "è¯·éæ©" |
| | | }; |
| | | } |
| | | |
| | | if (isChooseA.value) { |
| | | tabsList[2].name = areas.value[area.value].label; |
| | | } |
| | | |
| | | return tabsList; |
| | | }); |
| | | |
| | | const uZIndex = computed(() => { |
| | | // å¦æç¨æ·æä¼ éz-indexå¼ï¼ä¼å
ä½¿ç¨ |
| | | return props.zIndex ? props.zIndex : 1075; // å设$u.zIndex.popup为1075 |
| | | }); |
| | | |
| | | // æ¹æ³ |
| | | const setProvince = (label = "", value = "") => { |
| | | provinces.value.map((v, k) => { |
| | | if (value ? v.value == value : v.label == label) { |
| | | provinceChange(k); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const setCity = (label = "", value = "") => { |
| | | citys.value.map((v, k) => { |
| | | if (value ? v.value == value : v.label == label) { |
| | | cityChange(k); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const setArea = (label = "", value = "") => { |
| | | areas.value.map((v, k) => { |
| | | if (value ? v.value == value : v.label == label) { |
| | | isChooseA.value = true; |
| | | area.value = k; |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const close = () => { |
| | | emit('update:modelValue', false); |
| | | emit('close'); |
| | | }; |
| | | |
| | | const tabsChange = (value: { index: number }) => { |
| | | tabsIndex.value = value.index; |
| | | }; |
| | | |
| | | const provinceChange = (index: number) => { |
| | | isChooseP.value = true; |
| | | isChooseC.value = false; |
| | | isChooseA.value = false; |
| | | province.value = index; |
| | | citys.value = citysSource[index]; |
| | | tabsIndex.value = 1; |
| | | }; |
| | | |
| | | const cityChange = (index: number) => { |
| | | isChooseC.value = true; |
| | | isChooseA.value = false; |
| | | city.value = index; |
| | | areas.value = areasSource[province.value][index]; |
| | | tabsIndex.value = 2; |
| | | }; |
| | | |
| | | const areaChange = (index: number) => { |
| | | isChooseA.value = true; |
| | | area.value = index; |
| | | const result: CitySelectResult = { |
| | | province: provinces.value[province.value], |
| | | city: citys.value[city.value], |
| | | area: areas.value[area.value] |
| | | }; |
| | | emit('city-change', result); |
| | | close(); |
| | | }; |
| | | |
| | | // çå½å¨æé©å |
| | | onMounted(() => { |
| | | if (props.areaCode.length == 3) { |
| | | setProvince("", props.areaCode[0]); |
| | | setCity("", props.areaCode[1]); |
| | | setArea("", props.areaCode[2]); |
| | | } else if (props.defaultRegion.length == 3) { |
| | | setProvince(props.defaultRegion[0], ""); |
| | | setCity(props.defaultRegion[1], ""); |
| | | setArea(props.defaultRegion[2], ""); |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .area-box { |
| | | width: 100%; |
| | | overflow: hidden; |
| | | height: 800rpx; |
| | | |
| | | >view { |
| | | width: 150%; |
| | | transition: transform 0.3s ease-in-out 0s; |
| | | transform: translateX(0); |
| | | |
| | | &.change { |
| | | transform: translateX(-33.3333333%); |
| | | } |
| | | } |
| | | |
| | | .area-item { |
| | | width: 33.3333333%; |
| | | height: 800rpx; |
| | | } |
| | | } |
| | | </style> |