220 lines
5.0 KiB
Vue
220 lines
5.0 KiB
Vue
<template>
|
|
<view class="community-selector">
|
|
<!-- 弹出层 -->
|
|
<wd-popup v-model="popupVisible" position="bottom" :safe-area-inset-bottom="true" @close="onCancel" custom-class="community-popup">
|
|
<view class="picker-container">
|
|
<!-- 头部操作区 -->
|
|
<view class="picker-header">
|
|
<text class="cancel-btn" @click="onCancel">取消</text>
|
|
<text class="title">选择小区</text>
|
|
<text class="confirm-btn" @click="onConfirm">确定</text>
|
|
</view>
|
|
|
|
<!-- 小区列表 -->
|
|
<scroll-view scroll-y class="community-list">
|
|
<view class="community-item"
|
|
v-for="(item, index) in communities"
|
|
:key="index"
|
|
:class="{'active': pickerIndex[0] === index}"
|
|
@click="selectCommunity(index)">
|
|
<text class="community-item-name">{{ item.label }}</text>
|
|
<text v-if="pickerIndex[0] === index" class="ri-check-line check-icon"></text>
|
|
</view>
|
|
|
|
<!-- 底部安全区域 -->
|
|
<view class="safe-area-padding"></view>
|
|
</scroll-view>
|
|
</view>
|
|
</wd-popup>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, computed, watch } from 'vue'
|
|
|
|
const props = defineProps({
|
|
// 小区列表数据
|
|
communities: {
|
|
type: Array,
|
|
default: () => []
|
|
},
|
|
// 当前选中的小区ID
|
|
modelValue: {
|
|
type: [String, Number],
|
|
default: ''
|
|
},
|
|
// 是否显示弹出层
|
|
visible: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
communityList: {
|
|
type: Array,
|
|
default: () => []
|
|
},
|
|
defaultId: {
|
|
type: String,
|
|
default: ''
|
|
}
|
|
})
|
|
|
|
const emit = defineEmits(['update:modelValue', 'update:visible', 'change', 'confirm', 'cancel'])
|
|
|
|
// 内部状态
|
|
const currentIndex = ref([0])
|
|
const pickerIndex = ref([0])
|
|
|
|
// 弹出层可见状态
|
|
const popupVisible = computed({
|
|
get() {
|
|
return props.visible
|
|
},
|
|
set(value) {
|
|
emit('update:visible', value)
|
|
}
|
|
})
|
|
|
|
// 设置默认选中的社区
|
|
const selectedCommunity = ref(null)
|
|
|
|
// 监听外部传入的值变化
|
|
watch(() => props.modelValue, (newVal) => {
|
|
if (newVal) {
|
|
const index = props.communities.findIndex(item => item.value === newVal)
|
|
if (index !== -1) {
|
|
currentIndex.value = [index]
|
|
pickerIndex.value = [index]
|
|
}
|
|
}
|
|
}, { immediate: true })
|
|
|
|
// 监听弹出层显示状态变化
|
|
watch(() => props.visible, (newVal) => {
|
|
if (newVal) {
|
|
// 弹出层显示时,重置选择器的值为当前选中值
|
|
const index = props.communities.findIndex(item => item.value === props.modelValue)
|
|
if (index !== -1) {
|
|
pickerIndex.value = [index]
|
|
} else if (props.communities.length > 0) {
|
|
pickerIndex.value = [0]
|
|
}
|
|
}
|
|
})
|
|
|
|
// 当社区列表变更时,自动选择第一个社区或默认社区
|
|
watch(() => props.communityList, (list) => {
|
|
if (list && list.length > 0) {
|
|
if (props.defaultId) {
|
|
selectedCommunity.value = list.find(item => item.id === props.defaultId) || list[0]
|
|
} else {
|
|
selectedCommunity.value = list[0]
|
|
}
|
|
}
|
|
}, { immediate: true })
|
|
|
|
// 选择小区
|
|
const selectCommunity = (index) => {
|
|
pickerIndex.value = [index]
|
|
}
|
|
|
|
// 取消选择
|
|
const onCancel = () => {
|
|
popupVisible.value = false
|
|
// 把选择器的值重置为当前已选的值
|
|
pickerIndex.value = currentIndex.value
|
|
emit('cancel')
|
|
}
|
|
|
|
// 确认选择
|
|
const onConfirm = () => {
|
|
const selectedIndex = pickerIndex.value[0]
|
|
if (selectedIndex >= 0 && selectedIndex < props.communities.length) {
|
|
const selectedItem = props.communities[selectedIndex]
|
|
currentIndex.value = pickerIndex.value
|
|
emit('update:modelValue', selectedItem.value)
|
|
emit('change', selectedItem)
|
|
emit('confirm', selectedItem)
|
|
}
|
|
popupVisible.value = false
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.community-selector {
|
|
display: inline-flex;
|
|
}
|
|
|
|
.community-popup {
|
|
border-radius: 24rpx 24rpx 0 0 !important;
|
|
}
|
|
|
|
.picker-container {
|
|
background-color: #fff;
|
|
border-radius: 24rpx 24rpx 0 0;
|
|
overflow: hidden;
|
|
display: flex;
|
|
flex-direction: column;
|
|
max-height: 70vh;
|
|
}
|
|
|
|
.picker-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
height: 110rpx;
|
|
padding: 0 30rpx;
|
|
border-bottom: 1px solid #f2f2f2;
|
|
box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.02);
|
|
position: relative;
|
|
|
|
.title {
|
|
font-size: 34rpx;
|
|
font-weight: 500;
|
|
color: #333;
|
|
}
|
|
|
|
.cancel-btn {
|
|
font-size: 30rpx;
|
|
color: #999;
|
|
padding: 15rpx 10rpx;
|
|
}
|
|
|
|
.confirm-btn {
|
|
font-size: 30rpx;
|
|
color: #3e9bff;
|
|
font-weight: 500;
|
|
padding: 15rpx 10rpx;
|
|
}
|
|
}
|
|
|
|
.community-list {
|
|
flex: 1;
|
|
height: calc(70vh - 110rpx);
|
|
}
|
|
|
|
.community-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 30rpx 40rpx;
|
|
border-bottom: 1px solid #f6f6f6;
|
|
|
|
&.active {
|
|
background-color: #f8f8f8;
|
|
}
|
|
|
|
.community-item-name {
|
|
font-size: 32rpx;
|
|
color: #333;
|
|
}
|
|
|
|
.check-icon {
|
|
font-size: 40rpx;
|
|
color: #3e9bff;
|
|
}
|
|
}
|
|
|
|
.safe-area-padding {
|
|
height: 80rpx;
|
|
}
|
|
</style> |