refactor(地址选择): 替换element-china-area-data为@vant/area-data并优化地区数据处理
重构地址选择组件和相关逻辑,使用@vant/area-data替代element-china-area-data 优化地区数据转换逻辑,直接从扁平化数据结构获取地区信息 移除不再需要的findNodeByCode函数,简化代码结构
Showing
4 changed files
with
110 additions
and
79 deletions
| ... | @@ -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 | + | ||
| 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] | ||
| 85 | })) | 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] || '' |
| 188 | + const countyName = county_list[addressData.county_code] || '' | ||
| 161 | 189 | ||
| 162 | - if (provinceNode && cityNode && countyNode) { | 190 | + if (provinceName && cityName && countyName) { |
| 163 | - selectedAreaText.value = `${provinceNode.text}${cityNode.text}${countyNode.text}` | 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) { | ||
| 258 | - result.province = provinceNode.text | ||
| 259 | - | ||
| 260 | - if (codes.length >= 2 && provinceNode.children) { | ||
| 261 | - const cityNode = findNodeByCode(provinceNode.children, codes[1]) | ||
| 262 | - if (cityNode) { | ||
| 263 | - result.city = cityNode.text | ||
| 264 | - | ||
| 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 | } | 286 | } |
| 287 | + | ||
| 288 | + if (codes.length >= 2 && city_list[codes[1]]) { | ||
| 289 | + result.city = city_list[codes[1]] | ||
| 273 | } | 290 | } |
| 291 | + | ||
| 292 | + if (codes.length >= 3 && county_list[codes[2]]) { | ||
| 293 | + result.county = county_list[codes[2]] | ||
| 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 | + | ||
| 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] | ||
| 1162 | })) | 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) { | ||
| 1191 | - result.province = provinceNode.text | ||
| 1192 | - | ||
| 1193 | - if (cityCode && provinceNode.children) { | ||
| 1194 | - const cityNode = findNodeByCode(provinceNode.children, cityCode) | ||
| 1195 | - if (cityNode) { | ||
| 1196 | - result.city = cityNode.text | ||
| 1197 | - | ||
| 1198 | - if (countyCode && cityNode.children) { | ||
| 1199 | - const countyNode = findNodeByCode(cityNode.children, countyCode) | ||
| 1200 | - if (countyNode) { | ||
| 1201 | - result.county = countyNode.text | ||
| 1202 | - } | ||
| 1203 | - } | ||
| 1204 | - } | ||
| 1205 | } | 1210 | } |
| 1211 | + | ||
| 1212 | + if (cityCode && city_list[cityCode]) { | ||
| 1213 | + result.city = city_list[cityCode] | ||
| 1206 | } | 1214 | } |
| 1215 | + | ||
| 1216 | + if (countyCode && county_list[countyCode]) { | ||
| 1217 | + result.county = county_list[countyCode] | ||
| 1207 | } | 1218 | } |
| 1208 | 1219 | ||
| 1209 | return result | 1220 | return result | ... | ... |
-
Please register or login to post a comment