hookehuyr

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

重构地址选择组件和相关逻辑,使用@vant/area-data替代element-china-area-data
优化地区数据转换逻辑,直接从扁平化数据结构获取地区信息
移除不再需要的findNodeByCode函数,简化代码结构
...@@ -55,8 +55,8 @@ ...@@ -55,8 +55,8 @@
55 "@tarojs/runtime": "4.1.2", 55 "@tarojs/runtime": "4.1.2",
56 "@tarojs/shared": "4.1.2", 56 "@tarojs/shared": "4.1.2",
57 "@tarojs/taro": "4.1.2", 57 "@tarojs/taro": "4.1.2",
58 + "@vant/area-data": "^2.0.0",
58 "axios-miniprogram": "^2.7.2", 59 "axios-miniprogram": "^2.7.2",
59 - "element-china-area-data": "^6.1.0",
60 "pinia": "^3.0.3", 60 "pinia": "^3.0.3",
61 "taro-plugin-pinia": "^1.0.0", 61 "taro-plugin-pinia": "^1.0.0",
62 "vue": "^3.3.0" 62 "vue": "^3.3.0"
......
...@@ -65,6 +65,9 @@ importers: ...@@ -65,6 +65,9 @@ importers:
65 '@tarojs/taro': 65 '@tarojs/taro':
66 specifier: 4.1.2 66 specifier: 4.1.2
67 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)) 67 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))
68 + '@vant/area-data':
69 + specifier: ^2.0.0
70 + version: 2.0.0
68 axios-miniprogram: 71 axios-miniprogram:
69 specifier: ^2.7.2 72 specifier: ^2.7.2
70 version: 2.7.2 73 version: 2.7.2
...@@ -2172,6 +2175,9 @@ packages: ...@@ -2172,6 +2175,9 @@ packages:
2172 '@ungap/structured-clone@1.3.0': 2175 '@ungap/structured-clone@1.3.0':
2173 resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} 2176 resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
2174 2177
2178 + '@vant/area-data@2.0.0':
2179 + resolution: {integrity: sha512-zgP4AA8z09S9QTNgVCCHo9cHjcybrv22RJDYPjuCkecn4SB98T5EoPQh2TwqbQXmUhbaOGgiZGy3OUaUxnY7qg==}
2180 +
2175 '@vue/babel-helper-vue-transform-on@1.5.0': 2181 '@vue/babel-helper-vue-transform-on@1.5.0':
2176 resolution: {integrity: sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==} 2182 resolution: {integrity: sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==}
2177 2183
...@@ -9041,6 +9047,8 @@ snapshots: ...@@ -9041,6 +9047,8 @@ snapshots:
9041 9047
9042 '@ungap/structured-clone@1.3.0': {} 9048 '@ungap/structured-clone@1.3.0': {}
9043 9049
9050 + '@vant/area-data@2.0.0': {}
9051 +
9044 '@vue/babel-helper-vue-transform-on@1.5.0': {} 9052 '@vue/babel-helper-vue-transform-on@1.5.0': {}
9045 9053
9046 '@vue/babel-plugin-jsx@1.5.0(@babel/core@7.28.0)': 9054 '@vue/babel-plugin-jsx@1.5.0(@babel/core@7.28.0)':
......
...@@ -70,19 +70,46 @@ ...@@ -70,19 +70,46 @@
70 <script setup> 70 <script setup>
71 import { ref, computed, watch } from 'vue' 71 import { ref, computed, watch } from 'vue'
72 import { RectRight, ArrowRight } from '@nutui/icons-vue-taro' 72 import { RectRight, ArrowRight } from '@nutui/icons-vue-taro'
73 -import { regionData } from 'element-china-area-data' 73 +import { areaList } from '@vant/area-data'
74 74
75 /** 75 /**
76 - * 转换地区数据格式以适配NutUI Cascader组件 76 + * 转换@vant/area-data的扁平化数据为NutUI Cascader组件需要的树形结构
77 - * @param {Array} data - element-china-area-data的原始数据 77 + * @param {Object} areaList - @vant/area-data的原始数据
78 - * @returns {Array} - 转换后的数据格式 78 + * @returns {Array} - 转换后的树形数据格式
79 */ 79 */
80 -const transformAreaData = (data) => { 80 +const transformAreaData = (areaList) => {
81 - return data.map(item => ({ 81 + const { province_list, city_list, county_list } = areaList
82 - value: item.value, 82 +
83 - text: item.label, 83 + return Object.keys(province_list).map(provinceCode => {
84 - children: item.children ? transformAreaData(item.children) : undefined 84 + const provinceName = province_list[provinceCode]
85 - })) 85 +
86 + // 获取该省份下的所有城市
87 + const cities = Object.keys(city_list)
88 + .filter(cityCode => cityCode.startsWith(provinceCode.substring(0, 2)))
89 + .map(cityCode => {
90 + const cityName = city_list[cityCode]
91 +
92 + // 获取该城市下的所有区县
93 + const counties = Object.keys(county_list)
94 + .filter(countyCode => countyCode.startsWith(cityCode.substring(0, 4)))
95 + .map(countyCode => ({
96 + value: countyCode,
97 + text: county_list[countyCode]
98 + }))
99 +
100 + return {
101 + value: cityCode,
102 + text: cityName,
103 + children: counties.length > 0 ? counties : undefined
104 + }
105 + })
106 +
107 + return {
108 + value: provinceCode,
109 + text: provinceName,
110 + children: cities.length > 0 ? cities : undefined
111 + }
112 + })
86 } 113 }
87 114
88 /** 115 /**
...@@ -127,7 +154,7 @@ const showAreaPicker = ref(false) ...@@ -127,7 +154,7 @@ const showAreaPicker = ref(false)
127 const selectedAreaCodes = ref([]) 154 const selectedAreaCodes = ref([])
128 const selectedAreaText = ref('') 155 const selectedAreaText = ref('')
129 const detailAddress = ref('') 156 const detailAddress = ref('')
130 -const areaData = ref(transformAreaData(regionData)) 157 +const areaData = ref(transformAreaData(areaList))
131 158
132 /** 159 /**
133 * 计算完整地址 160 * 计算完整地址
...@@ -154,13 +181,14 @@ const initAddressData = (addressData) => { ...@@ -154,13 +181,14 @@ const initAddressData = (addressData) => {
154 addressData.city_code, 181 addressData.city_code,
155 addressData.county_code 182 addressData.county_code
156 ] 183 ]
157 - // 根据code值查找对应的文本 184 + // 根据code值直接从扁平化数据中获取对应的文本
158 - const provinceNode = findNodeByCode(areaData.value, addressData.province_code) 185 + const { province_list, city_list, county_list } = areaList
159 - const cityNode = provinceNode?.children ? findNodeByCode(provinceNode.children, addressData.city_code) : null 186 + const provinceName = province_list[addressData.province_code] || ''
160 - const countyNode = cityNode?.children ? findNodeByCode(cityNode.children, addressData.county_code) : null 187 + const cityName = city_list[addressData.city_code] || ''
161 - 188 + const countyName = county_list[addressData.county_code] || ''
162 - if (provinceNode && cityNode && countyNode) { 189 +
163 - selectedAreaText.value = `${provinceNode.text}${cityNode.text}${countyNode.text}` 190 + if (provinceName && cityName && countyName) {
191 + selectedAreaText.value = `${provinceName}${cityName}${countyName}`
164 } 192 }
165 } else if (addressData.province && addressData.city && addressData.county) { 193 } else if (addressData.province && addressData.city && addressData.county) {
166 // 兼容旧的文本格式 194 // 兼容旧的文本格式
...@@ -250,41 +278,25 @@ const confirmAddress = () => { ...@@ -250,41 +278,25 @@ const confirmAddress = () => {
250 */ 278 */
251 const getAreaTextFromCodes = () => { 279 const getAreaTextFromCodes = () => {
252 const codes = selectedAreaCodes.value 280 const codes = selectedAreaCodes.value
281 + const { province_list, city_list, county_list } = areaList
253 const result = { province: '', city: '', county: '' } 282 const result = { province: '', city: '', county: '' }
254 283
255 - if (codes.length >= 1) { 284 + if (codes.length >= 1 && province_list[codes[0]]) {
256 - const provinceNode = findNodeByCode(areaData.value, codes[0]) 285 + result.province = province_list[codes[0]]
257 - if (provinceNode) { 286 + }
258 - result.province = provinceNode.text 287 +
259 - 288 + if (codes.length >= 2 && city_list[codes[1]]) {
260 - if (codes.length >= 2 && provinceNode.children) { 289 + result.city = city_list[codes[1]]
261 - const cityNode = findNodeByCode(provinceNode.children, codes[1]) 290 + }
262 - if (cityNode) { 291 +
263 - result.city = cityNode.text 292 + if (codes.length >= 3 && county_list[codes[2]]) {
264 - 293 + result.county = county_list[codes[2]]
265 - if (codes.length >= 3 && cityNode.children) {
266 - const countyNode = findNodeByCode(cityNode.children, codes[2])
267 - if (countyNode) {
268 - result.county = countyNode.text
269 - }
270 - }
271 - }
272 - }
273 - }
274 } 294 }
275 295
276 return result 296 return result
277 } 297 }
278 298
279 -/** 299 +// findNodeByCode 函数已移除,现在直接从 @vant/area-data 的扁平化数据中获取地区名称
280 - * 根据编码查找节点
281 - * @param {Array} nodes - 节点数组
282 - * @param {String} code - 编码
283 - * @returns {Object|null} - 找到的节点或null
284 - */
285 -const findNodeByCode = (nodes, code) => {
286 - return nodes.find(node => node.value === code) || null
287 -}
288 </script> 300 </script>
289 301
290 <style lang="less"> 302 <style lang="less">
......
...@@ -271,7 +271,7 @@ import { useUserStore } from '@/stores/user' ...@@ -271,7 +271,7 @@ import { useUserStore } from '@/stores/user'
271 271
272 // 导入地址选择组件 272 // 导入地址选择组件
273 import AddressSelector from '@/components/AddressSelector.vue' 273 import AddressSelector from '@/components/AddressSelector.vue'
274 -import { regionData } from 'element-china-area-data' 274 +import { areaList } from '@vant/area-data'
275 275
276 // 获取页面参数 276 // 获取页面参数
277 const instance = Taro.getCurrentInstance() 277 const instance = Taro.getCurrentInstance()
...@@ -1150,30 +1150,49 @@ const addressData = ref({ ...@@ -1150,30 +1150,49 @@ const addressData = ref({
1150 }) 1150 })
1151 1151
1152 /** 1152 /**
1153 - * 转换地区数据格式以适配NutUI Cascader组件 1153 + * 转换@vant/area-data的扁平化数据为NutUI Cascader组件需要的树形结构
1154 - * @param {Array} data - element-china-area-data的原始数据 1154 + * @param {Object} areaList - @vant/area-data的原始数据
1155 - * @returns {Array} - 转换后的数据格式 1155 + * @returns {Array} - 转换后的树形数据格式
1156 */ 1156 */
1157 -const transformAreaData = (data) => { 1157 +const transformAreaData = (areaList) => {
1158 - return data.map(item => ({ 1158 + const { province_list, city_list, county_list } = areaList
1159 - value: item.value, 1159 +
1160 - text: item.label, 1160 + return Object.keys(province_list).map(provinceCode => {
1161 - children: item.children ? transformAreaData(item.children) : undefined 1161 + const provinceName = province_list[provinceCode]
1162 - })) 1162 +
1163 + // 获取该省份下的所有城市
1164 + const cities = Object.keys(city_list)
1165 + .filter(cityCode => cityCode.startsWith(provinceCode.substring(0, 2)))
1166 + .map(cityCode => {
1167 + const cityName = city_list[cityCode]
1168 +
1169 + // 获取该城市下的所有区县
1170 + const counties = Object.keys(county_list)
1171 + .filter(countyCode => countyCode.startsWith(cityCode.substring(0, 4)))
1172 + .map(countyCode => ({
1173 + value: countyCode,
1174 + text: county_list[countyCode]
1175 + }))
1176 +
1177 + return {
1178 + value: cityCode,
1179 + text: cityName,
1180 + children: counties.length > 0 ? counties : undefined
1181 + }
1182 + })
1183 +
1184 + return {
1185 + value: provinceCode,
1186 + text: provinceName,
1187 + children: cities.length > 0 ? cities : undefined
1188 + }
1189 + })
1163 } 1190 }
1164 1191
1165 // 转换后的地区数据 1192 // 转换后的地区数据
1166 -const areaData = ref(transformAreaData(regionData)) 1193 +const areaData = ref(transformAreaData(areaList))
1167 1194
1168 -/** 1195 +// findNodeByCode 函数已移除,现在直接从 @vant/area-data 的扁平化数据中获取地区名称
1169 - * 根据编码查找节点
1170 - * @param {Array} nodes - 节点数组
1171 - * @param {String} code - 编码
1172 - * @returns {Object|null} - 找到的节点或null
1173 - */
1174 -const findNodeByCode = (nodes, code) => {
1175 - return nodes.find(node => node.value === code) || null
1176 -}
1177 1196
1178 /** 1197 /**
1179 * 根据省市县code值获取对应的文字 1198 * 根据省市县code值获取对应的文字
...@@ -1183,27 +1202,19 @@ const findNodeByCode = (nodes, code) => { ...@@ -1183,27 +1202,19 @@ const findNodeByCode = (nodes, code) => {
1183 * @returns {Object} - 包含省市县文字的对象 1202 * @returns {Object} - 包含省市县文字的对象
1184 */ 1203 */
1185 const getAreaTextFromCodes = (provinceCode, cityCode, countyCode) => { 1204 const getAreaTextFromCodes = (provinceCode, cityCode, countyCode) => {
1205 + const { province_list, city_list, county_list } = areaList
1186 const result = { province: '', city: '', county: '' } 1206 const result = { province: '', city: '', county: '' }
1187 1207
1188 - if (provinceCode) { 1208 + if (provinceCode && province_list[provinceCode]) {
1189 - const provinceNode = findNodeByCode(areaData.value, provinceCode) 1209 + result.province = province_list[provinceCode]
1190 - if (provinceNode) { 1210 + }
1191 - result.province = provinceNode.text 1211 +
1192 - 1212 + if (cityCode && city_list[cityCode]) {
1193 - if (cityCode && provinceNode.children) { 1213 + result.city = city_list[cityCode]
1194 - const cityNode = findNodeByCode(provinceNode.children, cityCode) 1214 + }
1195 - if (cityNode) { 1215 +
1196 - result.city = cityNode.text 1216 + if (countyCode && county_list[countyCode]) {
1197 - 1217 + result.county = county_list[countyCode]
1198 - if (countyCode && cityNode.children) {
1199 - const countyNode = findNodeByCode(cityNode.children, countyCode)
1200 - if (countyNode) {
1201 - result.county = countyNode.text
1202 - }
1203 - }
1204 - }
1205 - }
1206 - }
1207 } 1218 }
1208 1219
1209 return result 1220 return result
......