| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- <!-- components/AreaPicker.vue -->
- <template>
- <view>
- <!-- 地区选择器 -->
- <u-picker
- :show="show"
- :columns="areaColumns"
- keyName="label"
- @confirm="handleConfirm"
- @cancel="handleCancel"
- @change="handleChange"
- ref="pickerRef"
- ></u-picker>
- </view>
- </template>
- <script setup>
- import { ref, watch, nextTick, onMounted, reactive, defineProps, defineEmits } from 'vue';
- import { getProvinces, getCities, getDistricts } from '@/utils/area-data.js';
- // 定义props
- const props = defineProps({
- show: {
- type: Boolean,
- default: false
- }
- });
- // 定义emits
- const emit = defineEmits(['update:show', 'confirm']);
- // 响应式数据
- const areaColumns = reactive([[], [], []]);
- const pickerRef = ref(null);
- const isUpdating = ref(false); // 防止重复更新
- // 初始化数据
- const initAreaData = () => {
- // 获取省份数据
- const provinces = getProvinces();
- areaColumns[0] = provinces;
-
- // 获取第一个省份的城市
- if (provinces.length > 0) {
- const cities = getCities(provinces[0].value);
- areaColumns[1] = cities;
-
- // 获取第一个城市的区县
- if (cities.length > 0) {
- const districts = getDistricts(cities[0].value);
- areaColumns[2] = districts;
- }
- }
- };
- // 处理选择器变化
- const handleChange = (e) => {
- if (isUpdating.value) return; // 防止重复更新
-
- const valueIndex = e.indexs; // 获取索引数组
-
- console.log('选择器变化 - 索引:', valueIndex);
-
- // 省份变化 (第一列)
- if (valueIndex[0] !== undefined) {
- isUpdating.value = true;
-
- // 通过索引获取省份对象
- const province = areaColumns[0][valueIndex[0]];
- console.log('选择了省份:', province);
-
- if (province) {
- // 获取城市数据
- const cities = getCities(province.value);
- areaColumns[1] = cities;
-
- // 检查城市索引是否超出范围
- let cityIndex = valueIndex[1] || 0;
- if (cityIndex >= cities.length) {
- cityIndex = 0; // 超出范围则重置为0
- }
-
- // 获取区县数据
- let districts = [];
- if (cities.length > 0) {
- // 使用调整后的城市索引获取区县数据
- const selectedCity = cities[cityIndex];
- if (selectedCity) {
- districts = getDistricts(selectedCity.value);
- } else if (cities.length > 0) {
- // 如果选中的城市不存在,使用第一个城市
- districts = getDistricts(cities[0].value);
- }
- } else {
- // 直辖市情况:直接使用省份code获取区县
- districts = getDistricts(province.value);
- }
- areaColumns[2] = districts;
-
- // 检查区县索引是否超出范围
- let districtIndex = valueIndex[2] || 0;
- if (districtIndex >= districts.length) {
- districtIndex = 0; // 超出范围则重置为0
- }
-
- // 更新选择器位置
- nextTick(() => {
- if (pickerRef.value && pickerRef.value.setIndexes) {
- // 重置城市和区县索引(市超出则重置为0,区超出也重置为0)
- pickerRef.value.setIndexes([valueIndex[0], cityIndex, districtIndex]);
- }
- isUpdating.value = false;
- });
- } else {
- isUpdating.value = false;
- }
- return; // 省份变化处理后直接返回,避免城市变化逻辑执行
- }
-
- // 城市变化 (第二列)
- if (valueIndex[1] !== undefined && areaColumns[1].length > 0) {
- isUpdating.value = true;
-
- // 检查城市索引是否超出范围
- let cityIndex = valueIndex[1];
- if (cityIndex >= areaColumns[1].length) {
- cityIndex = 0; // 超出范围则重置为0
- }
-
- // 通过索引获取城市对象
- const city = areaColumns[1][cityIndex];
- if (city) {
- // 获取区县数据
- const districts = getDistricts(city.value);
- areaColumns[2] = districts;
-
- // 检查区县索引是否超出范围
- let districtIndex = valueIndex[2] || 0;
- if (districtIndex >= districts.length) {
- districtIndex = 0; // 超出范围则重置为0
- }
-
- // 更新选择器位置
- nextTick(() => {
- if (pickerRef.value && pickerRef.value.setIndexes) {
- // 获取当前的省份索引
- const currentIndexes = pickerRef.value.getIndexes ? pickerRef.value.getIndexes() : [0, 0, 0];
- const provinceIndex = currentIndexes[0];
-
- // 设置索引:省份保持当前,城市使用调整后的索引,区县使用调整后的索引
- pickerRef.value.setIndexes([provinceIndex, cityIndex, districtIndex]);
- }
- isUpdating.value = false;
- });
- } else {
- isUpdating.value = false;
- }
- }
- };
- // 确认选择
- const handleConfirm = (e) => {
- const areaData = e.value;
-
- // 根据选中的对象获取值
- const province = areaData[0];
- const city = areaData[1] !== undefined ? areaData[1] : { label: '', value: '' };
- const district = areaData[2] !== undefined ? areaData[2] : { label: '', value: '' };
-
- const result = {
- province: {
- name: province.label,
- code: province.value
- },
- city: city.label ? {
- name: city.label,
- code: city.value
- } : null,
- district: district.label ? {
- name: district.label,
- code: district.value
- } : null,
- fullAddress: province.label + (city.label ? ' ' + city.label : '') + (district.label ? ' ' + district.label : '')
- };
-
- console.log('确认选择:', result);
- emit('confirm', result);
- emit('update:show', false);
- };
- // 取消选择
- const handleCancel = () => {
- emit('update:show', false);
- };
- // 组件挂载时初始化数据
- onMounted(() => {
- console.log('AreaPicker 组件已挂载');
- initAreaData();
- });
- // 监听显示状态
- watch(() => props.show, (newVal) => {
- console.log('show 状态变化:', newVal);
- if (newVal) {
- // 每次显示时重新初始化数据
- initAreaData();
-
- // 延迟设置选择器位置,确保DOM已更新
- setTimeout(() => {
- if (pickerRef.value && pickerRef.value.setIndexes) {
- pickerRef.value.setIndexes([0, 0, 0]);
- }
- }, 100);
- }
- });
- </script>
|