hookehuyr

refactor(地址选择): 替换element-china-area-data为@vant/area-data并优化地区数据处理

重构地址选择组件和相关逻辑,使用@vant/area-data替代element-china-area-data
优化地区数据转换逻辑,直接从扁平化数据结构获取地区信息
移除不再需要的findNodeByCode函数,简化代码结构
......@@ -55,8 +55,8 @@
"@tarojs/runtime": "4.1.2",
"@tarojs/shared": "4.1.2",
"@tarojs/taro": "4.1.2",
"@vant/area-data": "^2.0.0",
"axios-miniprogram": "^2.7.2",
"element-china-area-data": "^6.1.0",
"pinia": "^3.0.3",
"taro-plugin-pinia": "^1.0.0",
"vue": "^3.3.0"
......
......@@ -65,6 +65,9 @@ importers:
'@tarojs/taro':
specifier: 4.1.2
version: 4.1.2(@tarojs/components@4.1.2(@tarojs/helper@4.1.2)(html-webpack-plugin@5.6.3(webpack@5.78.0(@swc/core@1.3.96)))(postcss@8.5.6)(react@19.1.1)(rollup@3.29.5)(vue@3.5.18(typescript@5.9.2))(webpack-chain@6.5.1)(webpack-dev-server@4.15.2(webpack@5.78.0(@swc/core@1.3.96)))(webpack@5.78.0(@swc/core@1.3.96)))(@tarojs/helper@4.1.2)(@tarojs/shared@4.1.2)(html-webpack-plugin@5.6.3(webpack@5.78.0(@swc/core@1.3.96)))(postcss@8.5.6)(rollup@3.29.5)(vue@3.5.18(typescript@5.9.2))(webpack-chain@6.5.1)(webpack-dev-server@4.15.2(webpack@5.78.0(@swc/core@1.3.96)))(webpack@5.78.0(@swc/core@1.3.96))
'@vant/area-data':
specifier: ^2.0.0
version: 2.0.0
axios-miniprogram:
specifier: ^2.7.2
version: 2.7.2
......@@ -2172,6 +2175,9 @@ packages:
'@ungap/structured-clone@1.3.0':
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
'@vant/area-data@2.0.0':
resolution: {integrity: sha512-zgP4AA8z09S9QTNgVCCHo9cHjcybrv22RJDYPjuCkecn4SB98T5EoPQh2TwqbQXmUhbaOGgiZGy3OUaUxnY7qg==}
'@vue/babel-helper-vue-transform-on@1.5.0':
resolution: {integrity: sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==}
......@@ -9041,6 +9047,8 @@ snapshots:
'@ungap/structured-clone@1.3.0': {}
'@vant/area-data@2.0.0': {}
'@vue/babel-helper-vue-transform-on@1.5.0': {}
'@vue/babel-plugin-jsx@1.5.0(@babel/core@7.28.0)':
......
......@@ -70,19 +70,46 @@
<script setup>
import { ref, computed, watch } from 'vue'
import { RectRight, ArrowRight } from '@nutui/icons-vue-taro'
import { regionData } from 'element-china-area-data'
import { areaList } from '@vant/area-data'
/**
* 转换地区数据格式以适配NutUI Cascader组件
* @param {Array} data - element-china-area-data的原始数据
* @returns {Array} - 转换后的数据格式
* 转换@vant/area-data的扁平化数据为NutUI Cascader组件需要的树形结构
* @param {Object} areaList - @vant/area-data的原始数据
* @returns {Array} - 转换后的树形数据格式
*/
const transformAreaData = (data) => {
return data.map(item => ({
value: item.value,
text: item.label,
children: item.children ? transformAreaData(item.children) : undefined
}))
const transformAreaData = (areaList) => {
const { province_list, city_list, county_list } = areaList
return Object.keys(province_list).map(provinceCode => {
const provinceName = province_list[provinceCode]
// 获取该省份下的所有城市
const cities = Object.keys(city_list)
.filter(cityCode => cityCode.startsWith(provinceCode.substring(0, 2)))
.map(cityCode => {
const cityName = city_list[cityCode]
// 获取该城市下的所有区县
const counties = Object.keys(county_list)
.filter(countyCode => countyCode.startsWith(cityCode.substring(0, 4)))
.map(countyCode => ({
value: countyCode,
text: county_list[countyCode]
}))
return {
value: cityCode,
text: cityName,
children: counties.length > 0 ? counties : undefined
}
})
return {
value: provinceCode,
text: provinceName,
children: cities.length > 0 ? cities : undefined
}
})
}
/**
......@@ -127,7 +154,7 @@ const showAreaPicker = ref(false)
const selectedAreaCodes = ref([])
const selectedAreaText = ref('')
const detailAddress = ref('')
const areaData = ref(transformAreaData(regionData))
const areaData = ref(transformAreaData(areaList))
/**
* 计算完整地址
......@@ -154,13 +181,14 @@ const initAddressData = (addressData) => {
addressData.city_code,
addressData.county_code
]
// 根据code值查找对应的文本
const provinceNode = findNodeByCode(areaData.value, addressData.province_code)
const cityNode = provinceNode?.children ? findNodeByCode(provinceNode.children, addressData.city_code) : null
const countyNode = cityNode?.children ? findNodeByCode(cityNode.children, addressData.county_code) : null
if (provinceNode && cityNode && countyNode) {
selectedAreaText.value = `${provinceNode.text}${cityNode.text}${countyNode.text}`
// 根据code值直接从扁平化数据中获取对应的文本
const { province_list, city_list, county_list } = areaList
const provinceName = province_list[addressData.province_code] || ''
const cityName = city_list[addressData.city_code] || ''
const countyName = county_list[addressData.county_code] || ''
if (provinceName && cityName && countyName) {
selectedAreaText.value = `${provinceName}${cityName}${countyName}`
}
} else if (addressData.province && addressData.city && addressData.county) {
// 兼容旧的文本格式
......@@ -250,41 +278,25 @@ const confirmAddress = () => {
*/
const getAreaTextFromCodes = () => {
const codes = selectedAreaCodes.value
const { province_list, city_list, county_list } = areaList
const result = { province: '', city: '', county: '' }
if (codes.length >= 1) {
const provinceNode = findNodeByCode(areaData.value, codes[0])
if (provinceNode) {
result.province = provinceNode.text
if (codes.length >= 2 && provinceNode.children) {
const cityNode = findNodeByCode(provinceNode.children, codes[1])
if (cityNode) {
result.city = cityNode.text
if (codes.length >= 3 && cityNode.children) {
const countyNode = findNodeByCode(cityNode.children, codes[2])
if (countyNode) {
result.county = countyNode.text
}
}
}
}
}
if (codes.length >= 1 && province_list[codes[0]]) {
result.province = province_list[codes[0]]
}
if (codes.length >= 2 && city_list[codes[1]]) {
result.city = city_list[codes[1]]
}
if (codes.length >= 3 && county_list[codes[2]]) {
result.county = county_list[codes[2]]
}
return result
}
/**
* 根据编码查找节点
* @param {Array} nodes - 节点数组
* @param {String} code - 编码
* @returns {Object|null} - 找到的节点或null
*/
const findNodeByCode = (nodes, code) => {
return nodes.find(node => node.value === code) || null
}
// findNodeByCode 函数已移除,现在直接从 @vant/area-data 的扁平化数据中获取地区名称
</script>
<style lang="less">
......
......@@ -271,7 +271,7 @@ import { useUserStore } from '@/stores/user'
// 导入地址选择组件
import AddressSelector from '@/components/AddressSelector.vue'
import { regionData } from 'element-china-area-data'
import { areaList } from '@vant/area-data'
// 获取页面参数
const instance = Taro.getCurrentInstance()
......@@ -1150,30 +1150,49 @@ const addressData = ref({
})
/**
* 转换地区数据格式以适配NutUI Cascader组件
* @param {Array} data - element-china-area-data的原始数据
* @returns {Array} - 转换后的数据格式
* 转换@vant/area-data的扁平化数据为NutUI Cascader组件需要的树形结构
* @param {Object} areaList - @vant/area-data的原始数据
* @returns {Array} - 转换后的树形数据格式
*/
const transformAreaData = (data) => {
return data.map(item => ({
value: item.value,
text: item.label,
children: item.children ? transformAreaData(item.children) : undefined
}))
const transformAreaData = (areaList) => {
const { province_list, city_list, county_list } = areaList
return Object.keys(province_list).map(provinceCode => {
const provinceName = province_list[provinceCode]
// 获取该省份下的所有城市
const cities = Object.keys(city_list)
.filter(cityCode => cityCode.startsWith(provinceCode.substring(0, 2)))
.map(cityCode => {
const cityName = city_list[cityCode]
// 获取该城市下的所有区县
const counties = Object.keys(county_list)
.filter(countyCode => countyCode.startsWith(cityCode.substring(0, 4)))
.map(countyCode => ({
value: countyCode,
text: county_list[countyCode]
}))
return {
value: cityCode,
text: cityName,
children: counties.length > 0 ? counties : undefined
}
})
return {
value: provinceCode,
text: provinceName,
children: cities.length > 0 ? cities : undefined
}
})
}
// 转换后的地区数据
const areaData = ref(transformAreaData(regionData))
const areaData = ref(transformAreaData(areaList))
/**
* 根据编码查找节点
* @param {Array} nodes - 节点数组
* @param {String} code - 编码
* @returns {Object|null} - 找到的节点或null
*/
const findNodeByCode = (nodes, code) => {
return nodes.find(node => node.value === code) || null
}
// findNodeByCode 函数已移除,现在直接从 @vant/area-data 的扁平化数据中获取地区名称
/**
* 根据省市县code值获取对应的文字
......@@ -1183,27 +1202,19 @@ const findNodeByCode = (nodes, code) => {
* @returns {Object} - 包含省市县文字的对象
*/
const getAreaTextFromCodes = (provinceCode, cityCode, countyCode) => {
const { province_list, city_list, county_list } = areaList
const result = { province: '', city: '', county: '' }
if (provinceCode) {
const provinceNode = findNodeByCode(areaData.value, provinceCode)
if (provinceNode) {
result.province = provinceNode.text
if (cityCode && provinceNode.children) {
const cityNode = findNodeByCode(provinceNode.children, cityCode)
if (cityNode) {
result.city = cityNode.text
if (countyCode && cityNode.children) {
const countyNode = findNodeByCode(cityNode.children, countyCode)
if (countyNode) {
result.county = countyNode.text
}
}
}
}
}
if (provinceCode && province_list[provinceCode]) {
result.province = province_list[provinceCode]
}
if (cityCode && city_list[cityCode]) {
result.city = city_list[cityCode]
}
if (countyCode && county_list[countyCode]) {
result.county = county_list[countyCode]
}
return result
......