浏览代码

fix(region-cascader): 修复初始值为字符串时解析失败的问题

yz 1 月之前
父节点
当前提交
6480332a1f
共有 1 个文件被更改,包括 200 次插入192 次删除
  1. 200 192
      src/components/region-cascader/index.vue

+ 200 - 192
src/components/region-cascader/index.vue

@@ -1,213 +1,221 @@
 <template>
-  <el-cascader
-    ref="cascader"
-    v-model="selectedValues"
-    :options="options"
-    :props="cascaderProps"
-    :placeholder="placeholder"
-    :clearable="clearable"
-    :disabled="disabled"
-    :size="size"
-    @change="handleChange"
-    @expand-change="handleExpandChange"
-    filterable
-  />
+    <el-cascader ref="cascader" v-model="selectedValues" :options="options" :props="cascaderProps"
+        :placeholder="placeholder" :clearable="clearable" :disabled="disabled" :size="size" @change="handleChange"
+        @expand-change="handleExpandChange" filterable />
 </template>
 
 <script>
 import { getLazyTree } from '@/api/base/region'
 
 export default {
-  name: 'RegionCascader',
-  props: {
-    value: {
-      type: [String, Array],
-      default: ''
-    },
-    placeholder: {
-      type: String,
-      default: '请选择省/市/区'
-    },
-    clearable: {
-      type: Boolean,
-      default: true
-    },
-    disabled: {
-      type: Boolean,
-      default: false
+    name: 'RegionCascader',
+    props: {
+        value: {
+            type: [String, Array],
+            default: ''
+        },
+        placeholder: {
+            type: String,
+            default: '请选择省/市/区'
+        },
+        clearable: {
+            type: Boolean,
+            default: true
+        },
+        disabled: {
+            type: Boolean,
+            default: false
+        },
+        size: {
+            type: String,
+            default: 'small'
+        }
     },
-    size: {
-      type: String,
-      default: 'small'
-    }
-  },
-  data() {
-    return {
-      options: [],
-      selectedValues: [],
-      cascaderProps: {
-        value: 'value',
-        label: 'title',
-        children: 'children',
-        lazy: true,
-        lazyLoad: this.lazyLoad,
-        checkStrictly: false
-      }
-    }
-  },
-  watch: {
-    value: {
-      handler(newVal) {
-        if (typeof newVal === 'string' && newVal) {
-          // 如果传入的是regionName字符串(如:"广东省 深圳市 南山区"),需要解析
-          this.parseRegionName(newVal)
-        } else if (Array.isArray(newVal)) {
-          this.selectedValues = [...newVal]
-        } else {
-          this.selectedValues = []
+    data() {
+        return {
+            options: [],
+            selectedValues: [],
+            initialValue: null, // 保存初始值
+            cascaderProps: {
+                value: 'value',
+                label: 'title',
+                children: 'children',
+                lazy: true,
+                lazyLoad: this.lazyLoad,
+                checkStrictly: false
+            }
         }
-      },
-      immediate: true
-    }
-  },
-  async mounted() {
-    await this.loadProvinces()
-  },
-  methods: {
-    async loadProvinces() {
-      try {
-        const res = await getLazyTree('00')
-        if (res.data.success) {
-          this.options = res.data.data.map(item => ({
-            ...item,
-            leaf: false
-          }))
+    },
+    watch: {
+        value: {
+            handler(newVal) {
+                if (typeof newVal === 'string' && newVal) {
+                    // 如果省份数据还没加载,先保存初始值
+                    if (this.options.length === 0) {
+                        this.initialValue = newVal
+                    } else {
+                        this.parseRegionName(newVal)
+                    }
+                } else if (Array.isArray(newVal)) {
+                    this.selectedValues = [...newVal]
+                } else {
+                    this.selectedValues = []
+                }
+            },
+            immediate: true
         }
-      } catch (error) {
-        console.error('加载省级数据失败:', error)
-        this.$message.error('加载省级数据失败')
-      }
     },
+    mounted() {
+        this.loadProvinces().then(() => {
+            // 省份数据加载完成后,处理初始值
+            if (this.initialValue) {
+                this.parseRegionName(this.initialValue).then(() => {
+                    this.initialValue = null
+                })
+            }
+        })
+    },
+    methods: {
+        /**
+         * 解析regionName字符串,查找对应的代码路径
+         * @param {string} regionName - 省市区名称,用空格分割
+         */
+        async parseRegionName(regionName) {
+            if (!regionName) {
+                this.selectedValues = []
+                return
+            }
 
-    async lazyLoad(node, resolve) {
-      const { level, value } = node
-      
-      try {
-        // 如果是第三级(区级),直接返回空数组,不再加载子级
-        if (level >= 3) {
-          resolve([])
-          return
-        }
+            const regions = regionName.split(' ').filter(item => item.trim())
+            if (regions.length === 0) {
+                this.selectedValues = []
+                return
+            }
 
-        const res = await getLazyTree(value)
-        if (res.data.success) {
-          const children = res.data.data.map(item => ({
-            ...item,
-            leaf: level >= 2 // 市级的子级(区级)设为叶子节点
-          }))
-          resolve(children)
-        } else {
-          resolve([])
-        }
-      } catch (error) {
-        console.error('加载子级数据失败:', error)
-        resolve([])
-      }
-    },
+            try {
+                // 确保省份数据已加载
+                if (this.options.length === 0) {
+                    await this.loadProvinces()
+                }
 
-    /**
-     * 选择改变事件
-     * @param {Array} values - 选中的值数组
-     */
-    handleChange(values) {
-      this.selectedValues = values || []
-      
-      // 获取选中的节点信息
-    //   const selectedNodes = this.$refs.cascader?.getCheckedNodes() || []
-      const selectedNodes = this.$refs.cascader ? this.$refs.cascader.getCheckedNodes() : []
-
-      let regionName = ''
-      
-      if (values && values.length > 0) {
-        // 获取选中的节点信息
-        const selectedNodes = this.$refs.cascader.getCheckedNodes()
-        if (selectedNodes.length > 0) {
-          const node = selectedNodes[0]
-          regionName = node.pathLabels.join(' ')
-        }
-      }
-
-      // 直接返回regionName作为组件的值,这样avue-crud可以正确验证
-      this.$emit('input', regionName)
-      this.$emit('change', {
-        values,
-        regionName,
-      })
-    },
+                const codes = []
+
+                // 查找省级
+                if (regions[0]) {
+                    const province = this.options.find(item => item.title === regions[0])
+                    if (province) {
+                        codes.push(province.value)
+
+                        // 查找市级
+                        if (regions[1]) {
+                            const cityRes = await getLazyTree(province.value)
+                            if (cityRes.data.success) {
+                                const city = cityRes.data.data.find(item => item.title === regions[1])
+                                if (city) {
+                                    codes.push(city.value)
 
-    /**
-     * 展开改变事件
-     * @param {Array} activeValues - 当前展开的值
-     */
-    handleExpandChange(activeValues) {
-      this.$emit('expand-change', activeValues)
-    }
-  },
-  
-  /**
-   * 解析regionName字符串,查找对应的代码路径
-   * @param {string} regionName - 省市区名称,用空格分割
-   */
-  async parseRegionName(regionName) {
-    if (!regionName) {
-      this.selectedValues = []
-      return
-    }
-    
-    const regions = regionName.split(' ').filter(item => item.trim())
-    if (regions.length === 0) {
-      this.selectedValues = []
-      return
-    }
-    
-    try {
-      const codes = []
-      
-      // 查找省级
-      if (regions[0]) {
-        const province = this.options.find(item => item.title === regions[0])
-        if (province) {
-          codes.push(province.value)
-          
-          // 查找市级
-          if (regions[1]) {
-            const cityRes = await getLazyTree(province.value)
-            if (cityRes.data.success) {
-              const city = cityRes.data.data.find(item => item.title === regions[1])
-              if (city) {
-                codes.push(city.value)
-                
-                // 查找区级
-                if (regions[2]) {
-                  const districtRes = await getLazyTree(city.value)
-                  if (districtRes.data.success) {
-                    const district = districtRes.data.data.find(item => item.title === regions[2])
-                    if (district) {
-                      codes.push(district.value)
+                                    // 查找区级
+                                    if (regions[2]) {
+                                        const districtRes = await getLazyTree(city.value)
+                                        if (districtRes.data.success) {
+                                            const district = districtRes.data.data.find(item => item.title === regions[2])
+                                            if (district) {
+                                                codes.push(district.value)
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
                     }
-                  }
                 }
-              }
+
+                this.selectedValues = codes
+            } catch (error) {
+                console.error('解析regionName失败:', error)
+                this.selectedValues = []
+            }
+        },
+        async loadProvinces() {
+            try {
+                const res = await getLazyTree('00')
+                if (res.data.success) {
+                    this.options = res.data.data.map(item => ({
+                        ...item,
+                        leaf: false
+                    }))
+                }
+            } catch (error) {
+                console.error('加载省级数据失败:', error)
+                this.$message.error('加载省级数据失败')
+            }
+        },
+
+        async lazyLoad(node, resolve) {
+            const { level, value } = node
+
+            try {
+                // 如果是第三级(区级),直接返回空数组,不再加载子级
+                if (level >= 3) {
+                    resolve([])
+                    return
+                }
+
+                const res = await getLazyTree(value)
+                if (res.data.success) {
+                    const children = res.data.data.map(item => ({
+                        ...item,
+                        leaf: level >= 2 // 市级的子级(区级)设为叶子节点
+                    }))
+                    resolve(children)
+                } else {
+                    resolve([])
+                }
+            } catch (error) {
+                console.error('加载子级数据失败:', error)
+                resolve([])
+            }
+        },
+
+        /**
+         * 选择改变事件
+         * @param {Array} values - 选中的值数组
+         */
+        handleChange(values) {
+            this.selectedValues = values || []
+
+            // 获取选中的节点信息
+            //   const selectedNodes = this.$refs.cascader?.getCheckedNodes() || []
+            const selectedNodes = this.$refs.cascader ? this.$refs.cascader.getCheckedNodes() : []
+
+            let regionName = ''
+
+            if (values && values.length > 0) {
+                // 获取选中的节点信息
+                const selectedNodes = this.$refs.cascader.getCheckedNodes()
+                if (selectedNodes.length > 0) {
+                    const node = selectedNodes[0]
+                    regionName = node.pathLabels.join(' ')
+                }
             }
-          }
+
+            // 直接返回regionName作为组件的值,这样avue-crud可以正确验证
+            this.$emit('input', regionName)
+            this.$emit('change', {
+                values,
+                regionName,
+            })
+        },
+
+        /**
+         * 展开改变事件
+         * @param {Array} activeValues - 当前展开的值
+         */
+        handleExpandChange(activeValues) {
+            this.$emit('expand-change', activeValues)
         }
-      }
-      
-      this.selectedValues = codes
-    } catch (error) {
-      console.error('解析regionName失败:', error)
-      this.selectedValues = []
-    }
-  },
+    },
+
+
 }
 </script>