259 lines
6.4 KiB
Vue
259 lines
6.4 KiB
Vue
<template>
|
|
<view class="selectArea">
|
|
<uni-popup ref="popup" type="bottom">
|
|
<view class="header">
|
|
<view class="header-title">选择省市区</view>
|
|
<view class="close" @click="handleCancel"></view>
|
|
</view>
|
|
<!-- 搜索框 -->
|
|
<!-- <view class="seachBox">
|
|
<uni-search-bar placeholder="请输入城市/区县/街道名称搜索" cancelButton="none" @confirm="search" :focus="true"
|
|
v-model="searchValue" @blur="blur" @focus="focus" @input="input">
|
|
<template v-slot:searchIcon>
|
|
<view class="search-icon"></view>
|
|
</template>
|
|
</uni-search-bar>
|
|
</view> -->
|
|
<!-- 热门城市 -->
|
|
<view class="hot-city">
|
|
<view class="title">热门城市</view>
|
|
<view class="city-box">
|
|
<view class="city-item" :class="index===hotCityIndex?'active':''" v-for="(item,index) in cityList" :key="index"
|
|
@click="handleHotCityClick(item,index)">
|
|
{{item.label}}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<!-- 省市区三级联动 -->
|
|
<view class="province-city-area">
|
|
<view class="label-box">
|
|
<view class="label">省份</view>
|
|
<view class="label">城市</view>
|
|
<view class="label">区县</view>
|
|
</view>
|
|
<picker-view :value="areaIndex.data" :indicator-style="`height: 50px;`" @change="bindChange"
|
|
@pickstart="handlePickStart" class="picker-view">
|
|
<picker-view-column>
|
|
<view class="item" v-for="(item,index) in province.data" :key="index">{{item.name}}</view>
|
|
</picker-view-column>
|
|
<picker-view-column>
|
|
<view class="item" v-for="(item,index) in city.data" :key="index">{{item.name}}</view>
|
|
</picker-view-column>
|
|
<picker-view-column>
|
|
<view class="item" v-for="(item,index) in area.data" :key="index">{{item.name}}</view>
|
|
</picker-view-column>
|
|
</picker-view>
|
|
</view>
|
|
<!-- 底部 -->
|
|
<view class="footer">
|
|
<view class="btn" @click="confirm">确定</view>
|
|
</view>
|
|
</uni-popup>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import {
|
|
ref,
|
|
reactive,
|
|
onMounted,
|
|
nextTick,
|
|
computed,
|
|
watch
|
|
} from 'vue';
|
|
import {
|
|
getArea
|
|
} from '@/pages/api/order.js'
|
|
import {
|
|
onLoad,
|
|
onShow
|
|
} from '@dcloudio/uni-app';
|
|
const emits = defineEmits(["@getAreaData"]);
|
|
const popup = ref()
|
|
let props = defineProps({
|
|
provinceId: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
cityId: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
countyId: {
|
|
type: String,
|
|
default: '',
|
|
}
|
|
})
|
|
//省数据
|
|
let province = reactive({
|
|
data: []
|
|
})
|
|
let selectedProvince = reactive({
|
|
data: {
|
|
name: '北京市',
|
|
id: '1'
|
|
}
|
|
})
|
|
//市数据
|
|
const city = reactive({
|
|
data: []
|
|
})
|
|
let selectedCity = reactive({
|
|
data: {
|
|
name: '直辖市',
|
|
id: '2'
|
|
}
|
|
})
|
|
//区域数据
|
|
const area = reactive({
|
|
data: []
|
|
})
|
|
let selectedArea = reactive({
|
|
data: {
|
|
name: '东城区',
|
|
id: '3'
|
|
}
|
|
})
|
|
//记录三级联动每项的index以及默认展示
|
|
let areaIndex = reactive({
|
|
data: [0, 0, 0]
|
|
})
|
|
|
|
//记录热门城市选中的索引
|
|
let hotCityIndex = ref('')
|
|
|
|
const cityList = reactive([{
|
|
label: '北京',
|
|
provinceId: "1",
|
|
cityId: "2",
|
|
countyId: "3"
|
|
},
|
|
{
|
|
label: '上海',
|
|
provinceId: "161792",
|
|
cityId: "161793",
|
|
countyId: "161794"
|
|
},
|
|
{
|
|
label: '广州',
|
|
provinceId: "483250",
|
|
cityId: "483251",
|
|
countyId: "483252"
|
|
},
|
|
{
|
|
label: '深圳',
|
|
provinceId: "483250",
|
|
cityId: "487721",
|
|
countyId: "487722"
|
|
}
|
|
])
|
|
//负责记录组件中选中的三级对应的id
|
|
let placeIdItem = reactive({
|
|
provinceId: '',
|
|
cityId: '',
|
|
countyId: ''
|
|
})
|
|
//区分热门城市点击还是滑动三级组件
|
|
let chooseType = ref('select')
|
|
|
|
// 监听后台获取的详情
|
|
watch(props, (newValue, oldValue) => {
|
|
placeIdItem.provinceId = newValue.provinceId
|
|
placeIdItem.cityId = newValue.cityId
|
|
placeIdItem.countyId = newValue.countyId
|
|
})
|
|
|
|
const handleHotCityClick = (item,index) => {
|
|
placeIdItem.provinceId = item.provinceId
|
|
placeIdItem.cityId = item.cityId
|
|
placeIdItem.countyId = item.countyId
|
|
getAreaInfo('', province)
|
|
getAreaInfo(placeIdItem.provinceId, city)
|
|
getAreaInfo(placeIdItem.cityId, area)
|
|
chooseType.value = 'click'
|
|
hotCityIndex.value = index
|
|
}
|
|
|
|
const getList = () => {
|
|
getAreaInfo('', province)
|
|
getAreaInfo(placeIdItem.provinceId || 1, city)
|
|
getAreaInfo(placeIdItem.cityId || 2, area)
|
|
}
|
|
|
|
//获取省市区
|
|
const getAreaInfo = (parentId, type) => {
|
|
getArea({
|
|
parentId
|
|
}).then((res) => {
|
|
type.data = res.data
|
|
if (type === province) {
|
|
//用于解决响应式状态变更但是dom不更新的问题
|
|
nextTick(() => {
|
|
selectedProvince.data = res.data.filter(item => item.id == placeIdItem.provinceId)[0]|| res.data[0]
|
|
areaIndex.data[0] = res.data.findIndex(item => item.id == placeIdItem.provinceId)
|
|
})
|
|
} else if (type === city) {
|
|
nextTick(() => {
|
|
selectedCity.data = res.data.filter(item => item.id == placeIdItem.cityId)[0]|| res.data[0]
|
|
areaIndex.data[1] = res.data.findIndex(item => item.id == placeIdItem.cityId)
|
|
})
|
|
} else if (type === area) {
|
|
nextTick(() => {
|
|
selectedArea.data = res.data.filter(item => item.id == placeIdItem.countyId)[0]|| res.data[0]
|
|
areaIndex.data[2] = res.data.findIndex(item => item.id == placeIdItem.countyId)
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
const handlePickStart = () => {
|
|
chooseType.value = 'select'
|
|
}
|
|
|
|
//选择省市区
|
|
const bindChange = (event) => {
|
|
|
|
if(chooseType.value ==='click') return
|
|
//二级地址获取
|
|
if (areaIndex.data[0] !== event.detail.value[0]) {
|
|
getAreaInfo(province.data[event.detail.value[0]].id, city)
|
|
getAreaInfo(Number(province.data[event.detail.value[0]].id) + 1, area)
|
|
selectedProvince.data = province.data[event.detail.value[0]]
|
|
} else if (areaIndex.data[1] !== event.detail.value[1]) {
|
|
//三级地址获取
|
|
getAreaInfo(city.data[event.detail.value[1]].id, area)
|
|
selectedCity.data = city.data[event.detail.value[1]]
|
|
} else {
|
|
selectedArea.data = area.data[event.detail.value[2]]
|
|
}
|
|
areaIndex.data = event.detail.value
|
|
hotCityIndex.value = ''
|
|
}
|
|
|
|
// 打开弹层
|
|
const handleOpen = () => {
|
|
popup.value.open('bottom');
|
|
};
|
|
// 关闭弹层
|
|
const handleCancel = () => {
|
|
popup.value.close('bottom');
|
|
}
|
|
|
|
//确认选择省市区
|
|
const confirm = () => {
|
|
handleCancel()
|
|
emits("getAreaData", {
|
|
province: selectedProvince.data,
|
|
city: selectedCity.data,
|
|
area: selectedArea.data
|
|
})
|
|
}
|
|
// 暴漏给父组件
|
|
defineExpose({
|
|
handleOpen,
|
|
getList
|
|
});
|
|
</script>
|
|
|
|
<style src="./selectArea.scss" lang="scss" scoped></style>
|