优化地区选择下拉

This commit is contained in:
冯辉
2025-11-10 19:21:34 +08:00
parent 07f6d0e93f
commit 89529eb0f1

View File

@@ -85,8 +85,7 @@
</template> </template>
<script> <script>
import addressDataLoaderLazy from '@/utils/addressDataLoaderLazy.js'; import { createRequest } from '@/utils/request';
export default { export default {
name: 'AreaCascadePicker', name: 'AreaCascadePicker',
data() { data() {
@@ -113,8 +112,6 @@ export default {
selectedCommunity: null, selectedCommunity: null,
// 加载状态 // 加载状态
isLoading: false, isLoading: false,
// 懒加载模式:已加载的省份详情缓存
loadedProvinceDetails: new Map(),
}; };
}, },
methods: { methods: {
@@ -139,20 +136,26 @@ export default {
// 加载地区数据 // 加载地区数据
this.isLoading = true; this.isLoading = true;
try { try {
await this.loadAreaData(forceRefresh); // 先显示弹窗,避免长时间等待
// 初始化列表
this.initLists();
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.popup.open(); this.$refs.popup.open();
}); });
// 加载省份数据
await this.loadAreaData(forceRefresh);
// 只有当provinceList有数据时才初始化后续列表
if (this.areaData && this.areaData.length > 0) {
await this.initLists();
console.log('地址选择器初始化完成');
} else {
console.warn('没有加载到省份数据');
// 即使没有数据,也保持弹窗打开,让用户可以关闭它
}
} catch (error) { } catch (error) {
console.error('打开地址选择器失败:', error); console.error('打开地址选择器失败:', error);
uni.showToast({ // 注意由于loadAreaData已经处理了错误这里不应该会被触发
title: '加载地址数据失败', // 但保留作为额外的安全措施
icon: 'none',
duration: 2000
});
} finally { } finally {
this.isLoading = false; this.isLoading = false;
} }
@@ -160,42 +163,69 @@ export default {
async loadAreaData(forceRefresh = false) { async loadAreaData(forceRefresh = false) {
try { try {
console.log('正在加载省份列表(懒加载模式)...'); console.log('正在加载省份列表...');
const resp = await createRequest('/cms/dict/sysarea/list', { parentCode: '' }, 'GET', false);
console.log('省份列表接口响应:', resp);
// 优先尝试调用后端API获取省份列表 // 处理正确的数据格式
// const resp = await uni.request({ if (resp && resp.code === 200 && resp.data) {
// url: '/app/common/area/provinces', // 数据在data字段中
// method: 'GET' this.areaData = resp.data.map(item => ({
// }); code: item.code,
// if (resp.statusCode === 200 && resp.data && resp.data.data) { name: item.name
// this.areaData = resp.data.data; }));
// return;
// }
// 使用懒加载器:只加载省份列表(数据量很小,< 1MB console.log('省份列表加载成功:', this.areaData);
const provinceList = await addressDataLoaderLazy.loadProvinceList(forceRefresh); if (this.areaData.length === 0) {
console.warn('省份列表为空');
if (provinceList && Array.isArray(provinceList)) { }
this.areaData = provinceList;
} else { } else {
console.warn('省份列表格式不正确,使用空数据'); console.error('获取省份列表失败:', resp);
this.areaData = []; throw new Error(`获取省份列表失败: ${resp?.msg || '未知错误'}`);
} }
} catch (error) { } catch (error) {
console.error('加载省份列表失败:', error); console.error('加载省份列表失败:', error);
// 不抛出错误,避免阻止页面打开
// 而是使用默认空数据,让用户可以继续操作
this.areaData = []; this.areaData = [];
throw error; // 显示更友好的错误提示
uni.showToast({
title: error.message || '加载地址数据失败,请检查网络连接',
icon: 'none',
duration: 3000
});
} }
}, },
initLists() { async initLists() {
// 初始化省列表 // 初始化省列表
this.provinceList = this.areaData; this.provinceList = this.areaData || [];
if (this.provinceList.length > 0) { if (this.provinceList.length > 0) {
this.selectedProvince = this.provinceList[0]; this.selectedProvince = this.provinceList[0];
// 懒加载:首次选择第一个省份时,加载其详情 // 懒加载:首次选择第一个省份时,加载其详情
this.updateCityList(); await this.updateCityList();
// 如果有城市数据,初始化第一个城市的区县数据
if (this.cityList.length > 0) {
this.selectedCity = this.cityList[0];
await this.updateDistrictList();
// 如果有区县数据,初始化第一个区县的街道数据
if (this.districtList.length > 0) {
this.selectedDistrict = this.districtList[0];
await this.updateStreetList();
// 如果有街道数据,初始化第一个街道的社区数据
if (this.streetList.length > 0) {
this.selectedStreet = this.streetList[0];
await this.updateCommunityList();
}
}
}
// 更新选中索引
this.selectedIndex = [0, 0, 0, 0, 0];
} }
}, },
@@ -208,107 +238,168 @@ export default {
return; return;
} }
// 检查是否已加载该省份的详情
let provinceDetail = this.loadedProvinceDetails.get(this.selectedProvince.code);
// 如果未加载,则懒加载该省份的详情
if (!provinceDetail) {
try { try {
console.log(`📥 懒加载省份详情: ${this.selectedProvince.name} (${this.selectedProvince.code})`); console.log(`正在加载城市列表,父级编码: ${this.selectedProvince.code}`);
provinceDetail = await addressDataLoaderLazy.loadProvinceDetail(
this.selectedProvince.code,
false
);
if (provinceDetail) { // 使用createRequest工具调用接口
// 缓存已加载的省份详情 const resp = await createRequest('/cms/dict/sysarea/list', { parentCode: this.selectedProvince.code }, 'GET', false);
this.loadedProvinceDetails.set(this.selectedProvince.code, provinceDetail);
// 更新省份对象添加children console.log('城市列表接口响应:', resp);
Object.assign(this.selectedProvince, {
children: provinceDetail.children || [] // 处理正确的数据格式
}); let cityData = [];
if (resp && resp.code === 200 && resp.data) {
cityData = resp.data;
this.cityList = cityData.map(item => ({
code: item.code,
name: item.name
}));
console.log('城市列表加载成功:', this.cityList);
} else {
console.error('获取城市列表失败:', resp);
this.cityList = [];
} }
} catch (error) { } catch (error) {
console.error('加载省份详情失败:', error); console.error('加载城市列表失败:', error);
// 如果加载失败,检查是否有 _hasChildren 标记
if (this.selectedProvince._hasChildren) {
uni.showToast({
title: '加载城市数据失败,请重试',
icon: 'none',
duration: 2000
});
}
this.cityList = []; this.cityList = [];
this.districtList = [];
this.streetList = [];
this.communityList = [];
return;
}
} else {
// 如果已加载,直接使用缓存的详情
Object.assign(this.selectedProvince, {
children: provinceDetail.children || []
});
} }
// 更新城市列表
if (!this.selectedProvince.children || this.selectedProvince.children.length === 0) {
this.cityList = [];
this.districtList = [];
this.streetList = [];
this.communityList = [];
return;
}
this.cityList = this.selectedProvince.children;
this.selectedIndex[1] = 0; this.selectedIndex[1] = 0;
if (this.cityList.length > 0) { if (this.cityList.length > 0) {
this.selectedCity = this.cityList[0]; this.selectedCity = this.cityList[0];
this.updateDistrictList(); await this.updateDistrictList();
} else {
this.districtList = [];
this.streetList = [];
this.communityList = [];
} }
}, },
updateDistrictList() { async updateDistrictList() {
if (!this.selectedCity || !this.selectedCity.children) { if (!this.selectedCity) {
this.districtList = []; this.districtList = [];
this.streetList = []; this.streetList = [];
this.communityList = []; this.communityList = [];
return; return;
} }
this.districtList = this.selectedCity.children; try {
console.log(`正在加载区县列表,父级编码: ${this.selectedCity.code}`);
// 使用createRequest工具调用接口
const resp = await createRequest('/cms/dict/sysarea/list', { parentCode: this.selectedCity.code }, 'GET', false);
console.log('区县列表接口响应:', resp);
// 处理正确的数据格式
let districtData = [];
if (resp && resp.code === 200 && resp.data) {
districtData = resp.data;
this.districtList = districtData.map(item => ({
code: item.code,
name: item.name
}));
console.log('区县列表加载成功:', this.districtList);
} else {
console.error('获取区县列表失败:', resp);
this.districtList = [];
}
} catch (error) {
console.error('加载区县列表失败:', error);
this.districtList = [];
}
this.selectedIndex[2] = 0; this.selectedIndex[2] = 0;
if (this.districtList.length > 0) { if (this.districtList.length > 0) {
this.selectedDistrict = this.districtList[0]; this.selectedDistrict = this.districtList[0];
this.updateStreetList(); await this.updateStreetList();
} else {
this.streetList = [];
this.communityList = [];
} }
}, },
updateStreetList() { async updateStreetList() {
if (!this.selectedDistrict || !this.selectedDistrict.children) { if (!this.selectedDistrict) {
this.streetList = []; this.streetList = [];
this.communityList = []; this.communityList = [];
return; return;
} }
this.streetList = this.selectedDistrict.children; try {
console.log(`正在加载街道列表,父级编码: ${this.selectedDistrict.code}`);
// 使用createRequest工具调用接口
const resp = await createRequest('/cms/dict/sysarea/list', { parentCode: this.selectedDistrict.code }, 'GET', false);
console.log('街道列表接口响应:', resp);
// 处理正确的数据格式
let streetData = [];
if (resp && resp.code === 200 && resp.data) {
streetData = resp.data;
this.streetList = streetData.map(item => ({
code: item.code,
name: item.name
}));
console.log('街道列表加载成功:', this.streetList);
} else {
console.error('获取街道列表失败:', resp);
this.streetList = [];
}
} catch (error) {
console.error('加载街道列表失败:', error);
this.streetList = [];
}
this.selectedIndex[3] = 0; this.selectedIndex[3] = 0;
if (this.streetList.length > 0) { if (this.streetList.length > 0) {
this.selectedStreet = this.streetList[0]; this.selectedStreet = this.streetList[0];
this.updateCommunityList(); await this.updateCommunityList();
} else {
this.communityList = [];
} }
}, },
updateCommunityList() { async updateCommunityList() {
if (!this.selectedStreet || !this.selectedStreet.children) { if (!this.selectedStreet) {
this.communityList = []; this.communityList = [];
return; return;
} }
this.communityList = this.selectedStreet.children; try {
console.log(`正在加载社区列表,父级编码: ${this.selectedStreet.code}`);
// 使用createRequest工具调用接口
const resp = await createRequest('/cms/dict/sysarea/list', { parentCode: this.selectedStreet.code }, 'GET', false);
console.log('社区列表接口响应:', resp);
// 处理正确的数据格式
let communityData = [];
if (resp && resp.code === 200 && resp.data) {
communityData = resp.data;
this.communityList = communityData.map(item => ({
code: item.code,
name: item.name
}));
console.log('社区列表加载成功:', this.communityList);
} else {
console.error('获取社区列表失败:', resp);
this.communityList = [];
}
} catch (error) {
console.error('加载社区列表失败:', error);
this.communityList = [];
}
this.selectedIndex[4] = 0; this.selectedIndex[4] = 0;
if (this.communityList.length > 0) { if (this.communityList.length > 0) {
@@ -326,21 +417,21 @@ export default {
// 根据变化的列更新后续列 // 根据变化的列更新后续列
if (i === 0) { if (i === 0) {
// 省变化 - 需要加载新省份的详情 // 省变化 - 需要加载新省份的城市
this.selectedProvince = this.provinceList[newIndex[0]]; this.selectedProvince = this.provinceList[newIndex[0]];
await this.updateCityList(); // 改为异步 await this.updateCityList();
} else if (i === 1) { } else if (i === 1) {
// 市变化 // 市变化
this.selectedCity = this.cityList[newIndex[1]]; this.selectedCity = this.cityList[newIndex[1]];
this.updateDistrictList(); await this.updateDistrictList();
} else if (i === 2) { } else if (i === 2) {
// 区县变化 // 区县变化
this.selectedDistrict = this.districtList[newIndex[2]]; this.selectedDistrict = this.districtList[newIndex[2]];
this.updateStreetList(); await this.updateStreetList();
} else if (i === 3) { } else if (i === 3) {
// 街道变化 // 街道变化
this.selectedStreet = this.streetList[newIndex[3]]; this.selectedStreet = this.streetList[newIndex[3]];
this.updateCommunityList(); await this.updateCommunityList();
} else if (i === 4) { } else if (i === 4) {
// 社区变化 // 社区变化
this.selectedCommunity = this.communityList[newIndex[4]]; this.selectedCommunity = this.communityList[newIndex[4]];
@@ -401,17 +492,26 @@ export default {
} }
}, },
/**
* 重置所有状态(内部使用)
*/
reset() { reset() {
this.maskClick = false; this.maskClick = false;
this.confirmCallback = null; this.confirmCallback = null;
this.cancelCallback = null; this.cancelCallback = null;
this.changeCallback = null; this.changeCallback = null;
this.selectedIndex = [0, 0, 0, 0, 0]; this.selectedIndex = [0, 0, 0, 0, 0];
this.selectedProvince = null;
this.selectedCity = null;
this.selectedDistrict = null;
this.selectedStreet = null;
this.selectedCommunity = null;
this.provinceList = []; this.provinceList = [];
this.cityList = []; this.cityList = [];
this.districtList = []; this.districtList = [];
this.streetList = []; this.streetList = [];
this.communityList = []; this.communityList = [];
this.areaData = [];
}, },
/** /**
@@ -419,9 +519,8 @@ export default {
*/ */
async clearCache() { async clearCache() {
try { try {
await addressDataLoaderLazy.clearCache(); // 清除内存缓存
// 同时清除内存缓存 this.reset();
this.loadedProvinceDetails.clear();
uni.showToast({ uni.showToast({
title: '缓存已清除', title: '缓存已清除',
icon: 'success', icon: 'success',