You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
4.0 KiB
Vue
166 lines
4.0 KiB
Vue
4 months ago
|
<template>
|
||
|
<view class="container">
|
||
|
<view v-if="isLoading" class="loading">
|
||
|
<u-loading mode="circle"></u-loading>
|
||
|
</view>
|
||
|
<view v-else class="field-body" @click="handleSelect()">
|
||
|
<view class="field-value onelist-hidden">{{ valueText ? valueText: placeholder }}</view>
|
||
|
</view>
|
||
|
<u-select v-model="show" mode="mutil-column-auto" :list="options" :default-value="defaultValue" @confirm="onConfirm"></u-select>
|
||
|
</view>
|
||
|
</template>
|
||
|
|
||
|
<script>
|
||
|
import Emitter from '@/uview-ui/libs/util/emitter'
|
||
|
import { isEmpty } from '@/utils/util'
|
||
|
import RegionModel from '@/common/model/Region'
|
||
|
|
||
|
// 根据选中的value集获取索引集keys
|
||
|
// 用于设置默认选中
|
||
|
const findOptionsKey = (data, searchValue, deep = 1, keys = []) => {
|
||
|
const index = data.findIndex(item => item.value === searchValue[deep - 1])
|
||
|
if (index > -1) {
|
||
|
keys.push(index)
|
||
|
if (data[index].children) {
|
||
|
findOptionsKey(data[index].children, searchValue, ++deep, keys)
|
||
|
}
|
||
|
}
|
||
|
return keys
|
||
|
}
|
||
|
|
||
|
export default {
|
||
|
name: 'SelectRegion',
|
||
|
mixins: [Emitter],
|
||
|
model: {
|
||
|
prop: 'value',
|
||
|
event: 'change'
|
||
|
},
|
||
|
props: {
|
||
|
// v-model 指定选中项
|
||
|
value: {
|
||
|
type: Array,
|
||
|
default: () => {
|
||
|
return []
|
||
|
}
|
||
|
},
|
||
|
// 未选中时的提示文字
|
||
|
placeholder: {
|
||
|
type: String,
|
||
|
default: '请选择省/市/区'
|
||
|
}
|
||
|
},
|
||
|
data() {
|
||
|
return {
|
||
|
// 正在加载
|
||
|
isLoading: true,
|
||
|
// 是否显示
|
||
|
show: false,
|
||
|
// 默认选中的值
|
||
|
defaultValue: [],
|
||
|
// 选中项内容(文本展示)
|
||
|
valueText: '',
|
||
|
// 级联选择器数据
|
||
|
options: []
|
||
|
}
|
||
|
},
|
||
|
watch: {
|
||
|
// 监听v-model
|
||
|
value(val) {
|
||
|
// 设置默认选中的值
|
||
|
this.valueText = val.map(item => item.label).join('/')
|
||
|
this.setDefaultValue(val)
|
||
|
// 将当前的值发送到 u-form-item 进行校验
|
||
|
this.dispatch('u-form-item', 'on-form-change', val)
|
||
|
},
|
||
|
},
|
||
|
created() {
|
||
|
// 获取地区数据
|
||
|
this.getTreeData()
|
||
|
},
|
||
|
|
||
|
methods: {
|
||
|
|
||
|
// 打开选择器
|
||
|
handleSelect() {
|
||
|
this.show = true
|
||
|
},
|
||
|
|
||
|
// 获取地区数据
|
||
|
getTreeData() {
|
||
|
const app = this
|
||
|
app.isLoading = true
|
||
|
RegionModel.getTreeData()
|
||
|
.then(regions => {
|
||
|
// 格式化级联选择器数据
|
||
|
this.options = this.getOptions(regions)
|
||
|
})
|
||
|
.finally(() => app.isLoading = false)
|
||
|
},
|
||
|
|
||
|
// 确认选择后的回调
|
||
|
onConfirm(value) {
|
||
|
// 绑定到v-model执行的值
|
||
|
this.$emit('input', value)
|
||
|
this.$emit('change', value)
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 设置默认选中的值
|
||
|
* 该操作是为了每次打开选择器时聚焦到上次选择
|
||
|
* @param {Object} value
|
||
|
*/
|
||
|
setDefaultValue(value) {
|
||
|
const values = value.map(item => item.value)
|
||
|
const options = this.options
|
||
|
this.defaultValue = findOptionsKey(options, values)
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* 格式化级联选择器数据
|
||
|
* @param {*} regions 地区数据
|
||
|
*/
|
||
|
getOptions(regions) {
|
||
|
const { getOptions, getChildren } = this
|
||
|
const options = []
|
||
|
for (const index in regions) {
|
||
|
const item = regions[index]
|
||
|
const children = getChildren(item)
|
||
|
const optionItem = {
|
||
|
value: item.id,
|
||
|
label: item.name
|
||
|
}
|
||
|
if (children !== false) {
|
||
|
optionItem.children = getOptions(children)
|
||
|
}
|
||
|
options.push(optionItem)
|
||
|
}
|
||
|
|
||
|
return options
|
||
|
},
|
||
|
|
||
|
// 获取子集地区
|
||
|
getChildren(item) {
|
||
|
if (item.city) {
|
||
|
return item.city
|
||
|
}
|
||
|
if (item.region) {
|
||
|
return item.region
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
</script>
|
||
|
|
||
|
<style lang="scss" scoped>
|
||
|
.container {
|
||
|
width: 100%;
|
||
|
}
|
||
|
|
||
|
.loading {
|
||
|
padding-left: 10rpx;
|
||
|
// text-align: center;
|
||
|
}
|
||
|
</style>
|