162 lines
3.5 KiB
Vue
162 lines
3.5 KiB
Vue
![]() |
<template>
|
|||
|
<view class="region-picker">
|
|||
|
<view class="picker-header">
|
|||
|
<text class="title">选择地区</text>
|
|||
|
<text class="close" @click="close">×</text>
|
|||
|
</view>
|
|||
|
<view class="picker-content">
|
|||
|
<scroll-view
|
|||
|
v-for="(list, index) in regionLists"
|
|||
|
:key="index"
|
|||
|
class="region-list"
|
|||
|
scroll-y
|
|||
|
>
|
|||
|
<view
|
|||
|
v-for="item in list"
|
|||
|
:key="item.id"
|
|||
|
class="region-item"
|
|||
|
:class="{ active: selectedIds[index] === item.id }"
|
|||
|
@click="selectRegion(item, index)"
|
|||
|
>
|
|||
|
{{ item.name }}
|
|||
|
</view>
|
|||
|
</scroll-view>
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
</template>
|
|||
|
|
|||
|
<script>
|
|||
|
export default {
|
|||
|
name: 'RegionPicker',
|
|||
|
props: {
|
|||
|
value: {
|
|||
|
type: Array,
|
|||
|
default: () => []
|
|||
|
},
|
|||
|
regionData: {
|
|||
|
type: Array,
|
|||
|
default: () => []
|
|||
|
}
|
|||
|
},
|
|||
|
data() {
|
|||
|
return {
|
|||
|
regionLists: [],
|
|||
|
selectedIds: [],
|
|||
|
selectedNames: []
|
|||
|
}
|
|||
|
},
|
|||
|
watch: {
|
|||
|
regionData: {
|
|||
|
immediate: true,
|
|||
|
handler(val) {
|
|||
|
if (val.length) {
|
|||
|
this.regionLists = [val.filter(item => item.pid === '0')]
|
|||
|
if (this.value.length) {
|
|||
|
this.initSelected(this.value)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
methods: {
|
|||
|
initSelected(ids) {
|
|||
|
this.selectedIds = [...ids]
|
|||
|
this.selectedNames = []
|
|||
|
this.regionLists = [this.regionData.filter(item => item.pid === '0')]
|
|||
|
|
|||
|
let currentId = ids[0]
|
|||
|
for (let i = 0; i < ids.length; i++) {
|
|||
|
const item = this.regionData.find(item => item.id === currentId)
|
|||
|
if (item) {
|
|||
|
this.selectedNames.push(item.name)
|
|||
|
const nextLevel = this.regionData.filter(item => item.pid === currentId)
|
|||
|
if (nextLevel.length) {
|
|||
|
this.regionLists.push(nextLevel)
|
|||
|
currentId = ids[i + 1]
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
selectRegion(item, index) {
|
|||
|
this.selectedIds = this.selectedIds.slice(0, index)
|
|||
|
this.selectedNames = this.selectedNames.slice(0, index)
|
|||
|
|
|||
|
this.selectedIds.push(item.id)
|
|||
|
this.selectedNames.push(item.name)
|
|||
|
|
|||
|
const nextLevel = this.regionData.filter(item => item.pid === this.selectedIds[index])
|
|||
|
if (nextLevel.length) {
|
|||
|
this.regionLists = this.regionLists.slice(0, index + 1)
|
|||
|
this.regionLists.push(nextLevel)
|
|||
|
} else {
|
|||
|
this.regionLists = this.regionLists.slice(0, index + 1)
|
|||
|
this.$emit('change', {
|
|||
|
ids: this.selectedIds,
|
|||
|
names: this.selectedNames
|
|||
|
})
|
|||
|
}
|
|||
|
},
|
|||
|
close() {
|
|||
|
this.$emit('close')
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
</script>
|
|||
|
|
|||
|
<style lang="scss" scoped>
|
|||
|
.region-picker {
|
|||
|
width: 100%;
|
|||
|
background: #fff;
|
|||
|
border-radius: 24rpx 24rpx 0 0;
|
|||
|
|
|||
|
.picker-header {
|
|||
|
display: flex;
|
|||
|
justify-content: space-between;
|
|||
|
align-items: center;
|
|||
|
padding: 30rpx;
|
|||
|
border-bottom: 1rpx solid #eee;
|
|||
|
|
|||
|
.title {
|
|||
|
font-size: 32rpx;
|
|||
|
font-weight: 500;
|
|||
|
color: #333;
|
|||
|
}
|
|||
|
|
|||
|
.close {
|
|||
|
font-size: 40rpx;
|
|||
|
color: #999;
|
|||
|
padding: 0 20rpx;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
.picker-content {
|
|||
|
display: flex;
|
|||
|
height: 600rpx;
|
|||
|
|
|||
|
.region-list {
|
|||
|
flex: 1;
|
|||
|
min-width: 33.33%;
|
|||
|
height: 100%;
|
|||
|
border-right: 1rpx solid #eee;
|
|||
|
|
|||
|
&:last-child {
|
|||
|
border-right: none;
|
|||
|
}
|
|||
|
|
|||
|
.region-item {
|
|||
|
padding: 20rpx 30rpx;
|
|||
|
font-size: 28rpx;
|
|||
|
color: #333;
|
|||
|
white-space: nowrap;
|
|||
|
overflow: hidden;
|
|||
|
text-overflow: ellipsis;
|
|||
|
|
|||
|
&.active {
|
|||
|
color: #6a8cff;
|
|||
|
background: #f7f8fa;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
</style>
|