|
@@ -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>
|