231 lines
5.1 KiB
Vue
231 lines
5.1 KiB
Vue
<script setup>
|
|
import {
|
|
ref,
|
|
getCurrentInstance,
|
|
reactive,
|
|
computed,
|
|
defineEmits,
|
|
defineExpose,
|
|
} from 'vue'
|
|
// 工具
|
|
import util from '@/common/js/util.js';
|
|
import {
|
|
onLoad
|
|
} from '@dcloudio/uni-app'
|
|
// api
|
|
import api from '@/api/index.js';
|
|
|
|
// 代理
|
|
const {
|
|
proxy
|
|
} = getCurrentInstance()
|
|
const emit = defineEmits(['change'])
|
|
// 传参
|
|
const props = defineProps({
|
|
province: {
|
|
type: [String,Number],
|
|
},
|
|
city: {
|
|
type: [String,Number],
|
|
},
|
|
area: {
|
|
type: [String,Number],
|
|
},
|
|
})
|
|
// 地区
|
|
const region = reactive([])
|
|
// 地区下标
|
|
const regionIndex = reactive([0, 0, 0])
|
|
// 上次选择的地区下标
|
|
const regionIndexLast = reactive([0, 0, 0])
|
|
// 省份
|
|
const province = computed(() => {
|
|
return region[regionIndex[0]]
|
|
})
|
|
// 区县
|
|
const city = computed(() => {
|
|
return province.value && province.value.children[regionIndex[1]]
|
|
})
|
|
// 地区
|
|
const area = computed(() => {
|
|
return city.value && city.value.children[regionIndex[2]]
|
|
})
|
|
// 加载状态
|
|
const loading = ref(false);
|
|
|
|
onLoad(() => {
|
|
// 获取数据
|
|
getRegion()
|
|
})
|
|
|
|
// 初始化地区下标
|
|
function initRegionIndex() {
|
|
console.log('props', props)
|
|
if (props.province) {
|
|
const provinceIndex = region.findIndex(item => item.id == props.province);
|
|
regionIndex[0] = provinceIndex;
|
|
|
|
if (props.city) {
|
|
const cityIndex = region[provinceIndex].children.findIndex(item => item.id == props.city);
|
|
regionIndex[1] = cityIndex;
|
|
|
|
if (props.area) {
|
|
const areaIndex = region[provinceIndex].children[cityIndex].children.findIndex(item => item.id ==
|
|
props.area);
|
|
regionIndex[2] = areaIndex;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 获取数据
|
|
function getRegion() {
|
|
loading.value = true;
|
|
try {
|
|
//
|
|
api.getRegion().then(res => {
|
|
if (res.code === 200) {
|
|
region.length = 0
|
|
region.push(...res.data)
|
|
loading.value = false;
|
|
// 初始化下标
|
|
initRegionIndex()
|
|
return
|
|
}
|
|
util.alert({
|
|
content: res.msg,
|
|
showCancel: false,
|
|
})
|
|
loading.value = false;
|
|
})
|
|
} catch (error) {
|
|
console.error('Error occurred while fetching region data:', error);
|
|
loading.value = false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 切换
|
|
* @param {Object} value 具体的值
|
|
* @param {Object} index 下标
|
|
*/
|
|
function handleIndex(value, index) {
|
|
if (index >= 0 && index < regionIndex.length) {
|
|
regionIndex[index] = value;
|
|
}
|
|
}
|
|
|
|
// 开启弹窗
|
|
function open() {
|
|
console.log('open', proxy.$refs)
|
|
proxy.$refs.selection.open()
|
|
}
|
|
|
|
// 关闭弹窗
|
|
function close() {
|
|
proxy.$refs.selection.close()
|
|
setTimeout(() => {
|
|
// 恢复上一次选择的值
|
|
Object.assign(regionIndex, regionIndexLast.slice());
|
|
// 恢复上一次选择的值
|
|
regionIndexLast = regionIndex.slice();
|
|
}, 500)
|
|
}
|
|
|
|
// 取消
|
|
function handleCancel() {
|
|
close();
|
|
}
|
|
|
|
// 选择
|
|
function handleSubmit() {
|
|
Object.assign(regionIndexLast, regionIndex.slice());
|
|
if (province.value && city.value && area.value) {
|
|
emit('change', {
|
|
province: province.value,
|
|
city: city.value,
|
|
area: area.value,
|
|
});
|
|
}
|
|
proxy.$refs.selection.close()
|
|
}
|
|
|
|
//
|
|
defineExpose({
|
|
open,
|
|
close,
|
|
initRegionIndex,
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<template v-if="province">
|
|
<text>{{province.regionName}}</text>
|
|
<text>{{city.regionName}}</text>
|
|
<text>{{area.regionName}}</text>
|
|
</template>
|
|
<template v-else>
|
|
<text class="placeholderStyle">请选择产品所在地</text>
|
|
</template>
|
|
<uni-popup ref="selection" type="bottom">
|
|
<view class="selectionAlt popBot bfff">
|
|
<view class="header rows plr30">
|
|
<view class="option ptb30 f28" @click="handleCancel">取消</view>
|
|
<view class="title f32">选择省市区</view>
|
|
<view class="option ptb30 f28" @click="handleSubmit">确认</view>
|
|
</view>
|
|
<view class="main df plr10 plr10">
|
|
<scroll-view scroll-y="true" class="scroll province">
|
|
<view class="list">
|
|
<view class="item ptb20 tac" v-for="(item, index) in region" :key="index"
|
|
:class="{'active': index == regionIndex[0]}" @click="handleIndex(index,0)">
|
|
{{ item.regionName }}
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
<scroll-view scroll-y="true" class="scroll city" v-if="province">
|
|
<view class="list">
|
|
<view class="item ptb20 tac" v-for="(item, index) in province.children" :key="index"
|
|
:class="{'active': index == regionIndex[1]}" @click="handleIndex(index,1)">
|
|
{{ item.regionName }}
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
<scroll-view scroll-y="true" class="scroll area" v-if="city">
|
|
<view class="list">
|
|
<view class="item ptb20 tac" v-for="(item, index) in city.children" :key="index"
|
|
:class="{'active': index == regionIndex[2]}" @click="handleIndex(index,2)">
|
|
{{ item.regionName }}
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
<view v-if="loading" class="loading">Loading...</view>
|
|
</view>
|
|
</view>
|
|
</uni-popup>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
// 选择器弹窗
|
|
.selectionAlt {
|
|
|
|
//
|
|
.main {
|
|
height: 500rpx;
|
|
background-color: #f8f8f8;
|
|
|
|
.item {
|
|
color: #999;
|
|
|
|
&.active {
|
|
color: #333;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.loading {
|
|
text-align: center;
|
|
padding: 20rpx;
|
|
}
|
|
</style> |