/**
|
* CChinaArea - 表单项,中国地址三级联动
|
* @author Tevin
|
*/
|
|
<template>
|
<view class="c-china-area">
|
<picker
|
mode="multiSelector"
|
:range="range"
|
:value="current"
|
range-key="label"
|
@columnchange="evt=>updateColumns(evt.detail)"
|
@change="evt=>handleChange(evt.detail.value)"
|
>
|
<view @tap="evt=>handleOpen(evt)">
|
<AtInput
|
ref="input"
|
:name="itemRes.name"
|
:title="itemRes.label"
|
:required="itemRes.required"
|
:error="itemRes.error"
|
:placeholder="placeholder"
|
:value="selected"
|
>
|
<AtIcon :value="loading ? 'loading':'chevron-right'" />
|
</AtInput>
|
</view>
|
</picker>
|
</view>
|
</template>
|
|
<script>
|
import Taro from '@tarojs/taro';
|
import { AtInput, AtIcon } from 'taro-ui-vue';
|
import ChinaLocations from './ChinaLocations';
|
import './cChinaArea.scss';
|
|
const { onReady, getLocationTree, getRegionNames, getRegionCodes } = ChinaLocations;
|
|
export default {
|
name: 'CChinaArea',
|
components: {
|
AtInput,
|
AtIcon,
|
},
|
props: {
|
// 表单数据资源(表单组件内部机制专用)
|
itemRes: Object,
|
// 是否自动通过地理定位获取省市区
|
autoGeo: {
|
type: Boolean,
|
default: false,
|
},
|
// 占位提示
|
placeholder: String,
|
},
|
data() {
|
return {
|
loading: false,
|
range: [[], [], []],
|
current: [0, 0, 0],
|
};
|
},
|
computed: {
|
selected() {
|
const curVal = this.itemRes.formData[this.itemRes.name];
|
if (curVal && curVal.length === 3) {
|
return getRegionNames(curVal).join(' / ');
|
} else {
|
return '';
|
}
|
},
|
},
|
methods: {
|
handleOpen(evt) {
|
if (process.env.TARO_ENV === 'h5') {
|
if (evt && evt.target.className.indexOf('at-input__title') >= 0) {
|
evt.stopPropagation();
|
evt.preventDefault();
|
return;
|
}
|
}
|
const locationTree = getLocationTree();
|
const curVal = this.itemRes.formData[this.itemRes.name];
|
const range = [
|
locationTree,
|
locationTree[0].children,
|
locationTree[0].children[0].children,
|
];
|
const current = [0, 0, 0];
|
// 有值
|
if (curVal && curVal.length > 0) {
|
// 省
|
if (curVal[0]) {
|
const proviceIndex = locationTree.findIndex(
|
provice => provice.value === curVal[0]
|
);
|
if (proviceIndex >= 0) {
|
range[1] = locationTree[proviceIndex].children;
|
range[2] = locationTree[proviceIndex].children[0].children;
|
current[0] = proviceIndex;
|
// 市
|
if (curVal[1]) {
|
const cityIndex = range[1].findIndex(
|
city => city.value === curVal[1]
|
);
|
if (cityIndex >= 0) {
|
range[2] = range[1][cityIndex].children;
|
current[1] = cityIndex;
|
}
|
// 区
|
if (curVal[2]) {
|
const areaIndex = range[2].findIndex(
|
area => area.value === curVal[2]
|
);
|
if (areaIndex >= 0) {
|
current[2] = areaIndex;
|
}
|
}
|
}
|
}
|
}
|
}
|
this.range = range;
|
this.current = current;
|
},
|
updateColumns(roll) {
|
const locationTree = getLocationTree();
|
// 第一列滚动
|
if (roll.column === 0) {
|
const cities = locationTree[roll.value].children;
|
this.range = [this.range[0], cities, cities[0].children];
|
this.current = [roll.value, 0, 0];
|
}
|
// 第二列滚动
|
else if (roll.column === 1) {
|
const areas = locationTree[this.current[0]].children[roll.value].children;
|
this.range = [this.range[0], this.range[1], areas];
|
this.current = [this.current[0], roll.value, 0];
|
}
|
// 第三列滚动
|
else if (roll.column === 3) {
|
this.current.splice(2, 1, roll.value);
|
}
|
},
|
handleChange(detail) {
|
const locationTree = getLocationTree();
|
const codes = [];
|
const provice = locationTree[detail[0]];
|
codes[0] = provice.value;
|
const city = provice.children[detail[1]] || [];
|
codes[1] = city.value;
|
const area = city.children[detail[2]] || [];
|
codes[2] = area.value;
|
this.itemRes.onChange(codes);
|
},
|
_getGeoLocation() {
|
this.loading = true;
|
Taro.getLocation({
|
type: 'wgs84',
|
success: res => {
|
const latitude = res.latitude;
|
const longitude = res.longitude;
|
const myGeo = new BMap.Geocoder();
|
// 根据坐标得到地址描述
|
myGeo.getLocation(new BMap.Point(longitude, latitude), result => {
|
if (!result) {
|
this.locationLoading = false;
|
return;
|
}
|
const address = result.addressComponents;
|
const codes = getRegionCodes([
|
address.province.replace(/省|市|自治区|特别行政区/g, ''),
|
address.city,
|
address.district,
|
]);
|
if (codes && codes.length > 0) {
|
this.itemRes.onChange(codes);
|
}
|
this.loading = false;
|
});
|
},
|
cancel: res => (this.loading = false),
|
fail: err => (this.loading = false),
|
});
|
},
|
},
|
mounted() {
|
if (process.env.TARO_ENV === 'weapp') {
|
onReady(() => {
|
this.handleOpen();
|
});
|
}
|
// 开启自动定位时,延迟 0.1 秒后发起定位
|
if (this.autoGeo) {
|
if (process.env.TARO_ENV === 'weapp') {
|
setTimeout(() => {
|
// TODO:小程序中定位
|
}, 100);
|
} else if (process.env.TARO_ENV === 'h5') {
|
if (typeof wx === 'undefined') {
|
console.warn('无法进行地理位置定位,wx 不存在!');
|
return;
|
}
|
wx.ready(() => {
|
if (typeof BMap === 'undefined') {
|
console.warn('无法进行地理位置定位,BMap 不存在!');
|
return;
|
}
|
this._getGeoLocation();
|
});
|
}
|
}
|
},
|
};
|
</script>
|