2025-10-21 22:58:47 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<uni-popup
|
|
|
|
|
|
ref="popup"
|
|
|
|
|
|
type="bottom"
|
|
|
|
|
|
borderRadius="10px 10px 0 0"
|
|
|
|
|
|
background-color="#FFFFFF"
|
|
|
|
|
|
:mask-click="maskClick"
|
|
|
|
|
|
>
|
|
|
|
|
|
<view class="popup-content">
|
|
|
|
|
|
<view class="popup-header">
|
|
|
|
|
|
<view class="btn-cancel" @click="cancel">取消</view>
|
|
|
|
|
|
<view class="title">{{ title }}</view>
|
|
|
|
|
|
<view class="btn-confirm" @click="confirm">确认</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="popup-list">
|
|
|
|
|
|
<picker-view
|
|
|
|
|
|
indicator-style="height: 84rpx;"
|
|
|
|
|
|
:value="selectedIndex"
|
|
|
|
|
|
@change="bindChange"
|
|
|
|
|
|
class="picker-view"
|
|
|
|
|
|
>
|
|
|
|
|
|
<!-- 省 -->
|
|
|
|
|
|
<picker-view-column>
|
|
|
|
|
|
<view
|
|
|
|
|
|
v-for="(item, index) in provinceList"
|
|
|
|
|
|
:key="item.code"
|
|
|
|
|
|
class="item"
|
|
|
|
|
|
:class="{ 'item-active': selectedIndex[0] === index }"
|
|
|
|
|
|
>
|
|
|
|
|
|
<text>{{ item.name }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</picker-view-column>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 市 -->
|
|
|
|
|
|
<picker-view-column>
|
|
|
|
|
|
<view
|
|
|
|
|
|
v-for="(item, index) in cityList"
|
|
|
|
|
|
:key="item.code"
|
|
|
|
|
|
class="item"
|
|
|
|
|
|
:class="{ 'item-active': selectedIndex[1] === index }"
|
|
|
|
|
|
>
|
|
|
|
|
|
<text>{{ item.name }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</picker-view-column>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 区县 -->
|
|
|
|
|
|
<picker-view-column>
|
|
|
|
|
|
<view
|
|
|
|
|
|
v-for="(item, index) in districtList"
|
|
|
|
|
|
:key="item.code"
|
|
|
|
|
|
class="item"
|
|
|
|
|
|
:class="{ 'item-active': selectedIndex[2] === index }"
|
|
|
|
|
|
>
|
|
|
|
|
|
<text>{{ item.name }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</picker-view-column>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 街道 -->
|
|
|
|
|
|
<picker-view-column>
|
|
|
|
|
|
<view
|
|
|
|
|
|
v-for="(item, index) in streetList"
|
|
|
|
|
|
:key="item.code"
|
|
|
|
|
|
class="item"
|
|
|
|
|
|
:class="{ 'item-active': selectedIndex[3] === index }"
|
|
|
|
|
|
>
|
|
|
|
|
|
<text>{{ item.name }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</picker-view-column>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 社区/居委会 -->
|
|
|
|
|
|
<picker-view-column>
|
|
|
|
|
|
<view
|
|
|
|
|
|
v-for="(item, index) in communityList"
|
|
|
|
|
|
:key="item.code"
|
|
|
|
|
|
class="item"
|
|
|
|
|
|
:class="{ 'item-active': selectedIndex[4] === index }"
|
|
|
|
|
|
>
|
|
|
|
|
|
<text>{{ item.name }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</picker-view-column>
|
|
|
|
|
|
</picker-view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</uni-popup>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
2025-11-10 19:21:34 +08:00
|
|
|
|
import { createRequest } from '@/utils/request';
|
2025-10-21 22:58:47 +08:00
|
|
|
|
export default {
|
|
|
|
|
|
name: 'AreaCascadePicker',
|
|
|
|
|
|
data() {
|
2025-11-10 19:21:34 +08:00
|
|
|
|
return {
|
|
|
|
|
|
maskClick: false,
|
|
|
|
|
|
title: '选择地址',
|
|
|
|
|
|
confirmCallback: null,
|
|
|
|
|
|
cancelCallback: null,
|
|
|
|
|
|
changeCallback: null,
|
|
|
|
|
|
selectedIndex: [0, 0, 0, 0, 0],
|
|
|
|
|
|
// 原始数据(懒加载模式下,只存储省份列表)
|
|
|
|
|
|
areaData: [],
|
|
|
|
|
|
// 各级列表
|
|
|
|
|
|
provinceList: [],
|
|
|
|
|
|
cityList: [],
|
|
|
|
|
|
districtList: [],
|
|
|
|
|
|
streetList: [],
|
|
|
|
|
|
communityList: [],
|
|
|
|
|
|
// 当前选中的项
|
|
|
|
|
|
selectedProvince: null,
|
|
|
|
|
|
selectedCity: null,
|
|
|
|
|
|
selectedDistrict: null,
|
|
|
|
|
|
selectedStreet: null,
|
|
|
|
|
|
selectedCommunity: null,
|
|
|
|
|
|
// 加载状态
|
|
|
|
|
|
isLoading: false,
|
|
|
|
|
|
};
|
|
|
|
|
|
},
|
2025-10-21 22:58:47 +08:00
|
|
|
|
methods: {
|
|
|
|
|
|
async open(newConfig = {}) {
|
|
|
|
|
|
const {
|
|
|
|
|
|
title,
|
|
|
|
|
|
success,
|
|
|
|
|
|
cancel,
|
|
|
|
|
|
change,
|
|
|
|
|
|
maskClick = false,
|
|
|
|
|
|
defaultValue = null,
|
2025-11-10 15:27:34 +08:00
|
|
|
|
forceRefresh = false, // 是否强制刷新数据
|
2025-10-21 22:58:47 +08:00
|
|
|
|
} = newConfig;
|
|
|
|
|
|
|
|
|
|
|
|
this.reset();
|
|
|
|
|
|
if (title) this.title = title;
|
|
|
|
|
|
if (typeof success === 'function') this.confirmCallback = success;
|
|
|
|
|
|
if (typeof cancel === 'function') this.cancelCallback = cancel;
|
|
|
|
|
|
if (typeof change === 'function') this.changeCallback = change;
|
|
|
|
|
|
this.maskClick = maskClick;
|
|
|
|
|
|
|
|
|
|
|
|
// 加载地区数据
|
2025-11-10 15:27:34 +08:00
|
|
|
|
this.isLoading = true;
|
|
|
|
|
|
try {
|
2025-11-10 19:21:34 +08:00
|
|
|
|
// 先显示弹窗,避免长时间等待
|
2025-11-10 15:27:34 +08:00
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
|
this.$refs.popup.open();
|
|
|
|
|
|
});
|
2025-11-10 19:21:34 +08:00
|
|
|
|
|
|
|
|
|
|
// 加载省份数据
|
|
|
|
|
|
await this.loadAreaData(forceRefresh);
|
|
|
|
|
|
|
|
|
|
|
|
// 只有当provinceList有数据时才初始化后续列表
|
|
|
|
|
|
if (this.areaData && this.areaData.length > 0) {
|
|
|
|
|
|
await this.initLists();
|
|
|
|
|
|
console.log('地址选择器初始化完成');
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.warn('没有加载到省份数据');
|
|
|
|
|
|
// 即使没有数据,也保持弹窗打开,让用户可以关闭它
|
|
|
|
|
|
}
|
2025-11-10 15:27:34 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('打开地址选择器失败:', error);
|
2025-11-10 19:21:34 +08:00
|
|
|
|
// 注意:由于loadAreaData已经处理了错误,这里不应该会被触发
|
|
|
|
|
|
// 但保留作为额外的安全措施
|
2025-11-10 15:27:34 +08:00
|
|
|
|
} finally {
|
|
|
|
|
|
this.isLoading = false;
|
|
|
|
|
|
}
|
2025-10-21 22:58:47 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-10 15:27:34 +08:00
|
|
|
|
async loadAreaData(forceRefresh = false) {
|
2025-10-21 22:58:47 +08:00
|
|
|
|
try {
|
2025-11-10 19:21:34 +08:00
|
|
|
|
console.log('正在加载省份列表...');
|
|
|
|
|
|
const resp = await createRequest('/cms/dict/sysarea/list', { parentCode: '' }, 'GET', false);
|
|
|
|
|
|
console.log('省份列表接口响应:', resp);
|
2025-10-21 22:58:47 +08:00
|
|
|
|
|
2025-11-10 19:21:34 +08:00
|
|
|
|
// 处理正确的数据格式
|
|
|
|
|
|
if (resp && resp.code === 200 && resp.data) {
|
|
|
|
|
|
// 数据在data字段中
|
|
|
|
|
|
this.areaData = resp.data.map(item => ({
|
|
|
|
|
|
code: item.code,
|
|
|
|
|
|
name: item.name
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
console.log('省份列表加载成功:', this.areaData);
|
|
|
|
|
|
if (this.areaData.length === 0) {
|
|
|
|
|
|
console.warn('省份列表为空');
|
|
|
|
|
|
}
|
2025-11-10 15:27:34 +08:00
|
|
|
|
} else {
|
2025-11-10 19:21:34 +08:00
|
|
|
|
console.error('获取省份列表失败:', resp);
|
|
|
|
|
|
throw new Error(`获取省份列表失败: ${resp?.msg || '未知错误'}`);
|
2025-11-10 15:27:34 +08:00
|
|
|
|
}
|
2025-10-21 22:58:47 +08:00
|
|
|
|
} catch (error) {
|
2025-11-10 15:27:34 +08:00
|
|
|
|
console.error('加载省份列表失败:', error);
|
2025-11-10 19:21:34 +08:00
|
|
|
|
// 不抛出错误,避免阻止页面打开
|
|
|
|
|
|
// 而是使用默认空数据,让用户可以继续操作
|
2025-11-10 15:27:34 +08:00
|
|
|
|
this.areaData = [];
|
2025-11-10 19:21:34 +08:00
|
|
|
|
// 显示更友好的错误提示
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: error.message || '加载地址数据失败,请检查网络连接',
|
|
|
|
|
|
icon: 'none',
|
|
|
|
|
|
duration: 3000
|
|
|
|
|
|
});
|
2025-10-21 22:58:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-10 19:21:34 +08:00
|
|
|
|
async initLists() {
|
2025-10-21 22:58:47 +08:00
|
|
|
|
// 初始化省列表
|
2025-11-10 19:21:34 +08:00
|
|
|
|
this.provinceList = this.areaData || [];
|
2025-10-21 22:58:47 +08:00
|
|
|
|
|
|
|
|
|
|
if (this.provinceList.length > 0) {
|
|
|
|
|
|
this.selectedProvince = this.provinceList[0];
|
2025-11-10 15:27:34 +08:00
|
|
|
|
// 懒加载:首次选择第一个省份时,加载其详情
|
2025-11-10 19:21:34 +08:00
|
|
|
|
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];
|
2025-10-21 22:58:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-10 15:27:34 +08:00
|
|
|
|
async updateCityList() {
|
|
|
|
|
|
if (!this.selectedProvince) {
|
|
|
|
|
|
this.cityList = [];
|
|
|
|
|
|
this.districtList = [];
|
|
|
|
|
|
this.streetList = [];
|
|
|
|
|
|
this.communityList = [];
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-10 19:21:34 +08:00
|
|
|
|
try {
|
|
|
|
|
|
console.log(`正在加载城市列表,父级编码: ${this.selectedProvince.code}`);
|
|
|
|
|
|
|
|
|
|
|
|
// 使用createRequest工具调用接口
|
|
|
|
|
|
const resp = await createRequest('/cms/dict/sysarea/list', { parentCode: this.selectedProvince.code }, 'GET', false);
|
|
|
|
|
|
|
|
|
|
|
|
console.log('城市列表接口响应:', resp);
|
|
|
|
|
|
|
|
|
|
|
|
// 处理正确的数据格式
|
|
|
|
|
|
let cityData = [];
|
|
|
|
|
|
if (resp && resp.code === 200 && resp.data) {
|
|
|
|
|
|
cityData = resp.data;
|
2025-11-10 15:27:34 +08:00
|
|
|
|
|
2025-11-10 19:21:34 +08:00
|
|
|
|
this.cityList = cityData.map(item => ({
|
|
|
|
|
|
code: item.code,
|
|
|
|
|
|
name: item.name
|
|
|
|
|
|
}));
|
|
|
|
|
|
console.log('城市列表加载成功:', this.cityList);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.error('获取城市列表失败:', resp);
|
2025-11-10 15:27:34 +08:00
|
|
|
|
this.cityList = [];
|
|
|
|
|
|
}
|
2025-11-10 19:21:34 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('加载城市列表失败:', error);
|
2025-10-21 22:58:47 +08:00
|
|
|
|
this.cityList = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.selectedIndex[1] = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (this.cityList.length > 0) {
|
|
|
|
|
|
this.selectedCity = this.cityList[0];
|
2025-11-10 19:21:34 +08:00
|
|
|
|
await this.updateDistrictList();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.districtList = [];
|
|
|
|
|
|
this.streetList = [];
|
|
|
|
|
|
this.communityList = [];
|
2025-10-21 22:58:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-10 19:21:34 +08:00
|
|
|
|
async updateDistrictList() {
|
|
|
|
|
|
if (!this.selectedCity) {
|
2025-10-21 22:58:47 +08:00
|
|
|
|
this.districtList = [];
|
|
|
|
|
|
this.streetList = [];
|
|
|
|
|
|
this.communityList = [];
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-10 19:21:34 +08:00
|
|
|
|
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 = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-21 22:58:47 +08:00
|
|
|
|
this.selectedIndex[2] = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (this.districtList.length > 0) {
|
|
|
|
|
|
this.selectedDistrict = this.districtList[0];
|
2025-11-10 19:21:34 +08:00
|
|
|
|
await this.updateStreetList();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.streetList = [];
|
|
|
|
|
|
this.communityList = [];
|
2025-10-21 22:58:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-10 19:21:34 +08:00
|
|
|
|
async updateStreetList() {
|
|
|
|
|
|
if (!this.selectedDistrict) {
|
2025-10-21 22:58:47 +08:00
|
|
|
|
this.streetList = [];
|
|
|
|
|
|
this.communityList = [];
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-10 19:21:34 +08:00
|
|
|
|
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 = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-21 22:58:47 +08:00
|
|
|
|
this.selectedIndex[3] = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (this.streetList.length > 0) {
|
|
|
|
|
|
this.selectedStreet = this.streetList[0];
|
2025-11-10 19:21:34 +08:00
|
|
|
|
await this.updateCommunityList();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.communityList = [];
|
2025-10-21 22:58:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-10 19:21:34 +08:00
|
|
|
|
async updateCommunityList() {
|
|
|
|
|
|
if (!this.selectedStreet) {
|
2025-10-21 22:58:47 +08:00
|
|
|
|
this.communityList = [];
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-10 19:21:34 +08:00
|
|
|
|
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 = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-21 22:58:47 +08:00
|
|
|
|
this.selectedIndex[4] = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (this.communityList.length > 0) {
|
|
|
|
|
|
this.selectedCommunity = this.communityList[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-10 15:27:34 +08:00
|
|
|
|
async bindChange(e) {
|
2025-10-21 22:58:47 +08:00
|
|
|
|
const newIndex = e.detail.value;
|
|
|
|
|
|
|
|
|
|
|
|
// 检查哪一列发生了变化
|
|
|
|
|
|
for (let i = 0; i < 5; i++) {
|
|
|
|
|
|
if (newIndex[i] !== this.selectedIndex[i]) {
|
|
|
|
|
|
this.selectedIndex[i] = newIndex[i];
|
|
|
|
|
|
|
|
|
|
|
|
// 根据变化的列更新后续列
|
|
|
|
|
|
if (i === 0) {
|
2025-11-10 19:21:34 +08:00
|
|
|
|
// 省变化 - 需要加载新省份的城市
|
2025-10-21 22:58:47 +08:00
|
|
|
|
this.selectedProvince = this.provinceList[newIndex[0]];
|
2025-11-10 19:21:34 +08:00
|
|
|
|
await this.updateCityList();
|
2025-10-21 22:58:47 +08:00
|
|
|
|
} else if (i === 1) {
|
|
|
|
|
|
// 市变化
|
|
|
|
|
|
this.selectedCity = this.cityList[newIndex[1]];
|
2025-11-10 19:21:34 +08:00
|
|
|
|
await this.updateDistrictList();
|
2025-10-21 22:58:47 +08:00
|
|
|
|
} else if (i === 2) {
|
|
|
|
|
|
// 区县变化
|
|
|
|
|
|
this.selectedDistrict = this.districtList[newIndex[2]];
|
2025-11-10 19:21:34 +08:00
|
|
|
|
await this.updateStreetList();
|
2025-10-21 22:58:47 +08:00
|
|
|
|
} else if (i === 3) {
|
|
|
|
|
|
// 街道变化
|
|
|
|
|
|
this.selectedStreet = this.streetList[newIndex[3]];
|
2025-11-10 19:21:34 +08:00
|
|
|
|
await this.updateCommunityList();
|
2025-10-21 22:58:47 +08:00
|
|
|
|
} else if (i === 4) {
|
|
|
|
|
|
// 社区变化
|
|
|
|
|
|
this.selectedCommunity = this.communityList[newIndex[4]];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (this.changeCallback) {
|
|
|
|
|
|
this.changeCallback(this.getSelectedAddress());
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
getSelectedAddress() {
|
|
|
|
|
|
const parts = [];
|
|
|
|
|
|
if (this.selectedProvince) parts.push(this.selectedProvince.name);
|
|
|
|
|
|
if (this.selectedCity) parts.push(this.selectedCity.name);
|
|
|
|
|
|
if (this.selectedDistrict) parts.push(this.selectedDistrict.name);
|
|
|
|
|
|
if (this.selectedStreet) parts.push(this.selectedStreet.name);
|
|
|
|
|
|
if (this.selectedCommunity) parts.push(this.selectedCommunity.name);
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
address: parts.join('/'),
|
|
|
|
|
|
province: this.selectedProvince,
|
|
|
|
|
|
city: this.selectedCity,
|
|
|
|
|
|
district: this.selectedDistrict,
|
|
|
|
|
|
street: this.selectedStreet,
|
|
|
|
|
|
community: this.selectedCommunity,
|
|
|
|
|
|
};
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
close() {
|
|
|
|
|
|
this.$refs.popup.close();
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
cancel() {
|
|
|
|
|
|
this.clickCallback(this.cancelCallback);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
confirm() {
|
|
|
|
|
|
this.clickCallback(this.confirmCallback);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
async clickCallback(callback) {
|
|
|
|
|
|
if (typeof callback !== 'function') {
|
|
|
|
|
|
this.$refs.popup.close();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const result = await callback(this.getSelectedAddress());
|
|
|
|
|
|
if (result !== false) {
|
|
|
|
|
|
this.$refs.popup.close();
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('callback 执行出错:', error);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-10 19:21:34 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 重置所有状态(内部使用)
|
|
|
|
|
|
*/
|
2025-10-21 22:58:47 +08:00
|
|
|
|
reset() {
|
|
|
|
|
|
this.maskClick = false;
|
|
|
|
|
|
this.confirmCallback = null;
|
|
|
|
|
|
this.cancelCallback = null;
|
|
|
|
|
|
this.changeCallback = null;
|
|
|
|
|
|
this.selectedIndex = [0, 0, 0, 0, 0];
|
2025-11-10 19:21:34 +08:00
|
|
|
|
this.selectedProvince = null;
|
|
|
|
|
|
this.selectedCity = null;
|
|
|
|
|
|
this.selectedDistrict = null;
|
|
|
|
|
|
this.selectedStreet = null;
|
|
|
|
|
|
this.selectedCommunity = null;
|
2025-10-21 22:58:47 +08:00
|
|
|
|
this.provinceList = [];
|
|
|
|
|
|
this.cityList = [];
|
|
|
|
|
|
this.districtList = [];
|
|
|
|
|
|
this.streetList = [];
|
|
|
|
|
|
this.communityList = [];
|
2025-11-10 19:21:34 +08:00
|
|
|
|
this.areaData = [];
|
2025-10-21 22:58:47 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-10 15:27:34 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 清除地址数据缓存(供外部调用)
|
|
|
|
|
|
*/
|
|
|
|
|
|
async clearCache() {
|
|
|
|
|
|
try {
|
2025-11-10 19:21:34 +08:00
|
|
|
|
// 清除内存缓存
|
|
|
|
|
|
this.reset();
|
2025-11-10 15:27:34 +08:00
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '缓存已清除',
|
|
|
|
|
|
icon: 'success',
|
|
|
|
|
|
duration: 2000
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('清除缓存失败:', error);
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '清除缓存失败',
|
|
|
|
|
|
icon: 'none',
|
|
|
|
|
|
duration: 2000
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-10-21 22:58:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
};
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
.popup-content {
|
|
|
|
|
|
color: #000000;
|
|
|
|
|
|
height: 60vh;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.popup-list {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
|
flex-wrap: nowrap;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: space-evenly;
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
|
|
|
|
|
|
.picker-view {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: calc(60vh - 100rpx);
|
|
|
|
|
|
margin-top: 20rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.uni-picker-view-mask {
|
|
|
|
|
|
background: rgba(0, 0, 0, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.item {
|
|
|
|
|
|
line-height: 84rpx;
|
|
|
|
|
|
height: 84rpx;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
color: #cccccc;
|
|
|
|
|
|
padding: 0 4rpx;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.item-active {
|
|
|
|
|
|
color: #333333;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.uni-picker-view-indicator:after {
|
|
|
|
|
|
border-color: #e3e3e3;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.uni-picker-view-indicator:before {
|
|
|
|
|
|
border-color: #e3e3e3;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.popup-header {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 40rpx 40rpx 10rpx 40rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.title {
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
font-size: 36rpx;
|
|
|
|
|
|
color: #333333;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.btn-cancel {
|
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
|
color: #666d7f;
|
|
|
|
|
|
line-height: 38rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.btn-confirm {
|
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
|
color: #256bfa;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|
|
|
|
|
|
|