/**
|
* CChinaArea - 表单项,中国地址三级联动
|
* @author Tevin
|
*/
|
|
<template>
|
<view class="c-china-area">
|
<picker
|
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 { $locations } from '@components/forms/chinaArea/ChinaLocations';
|
import './cChinaArea.scss';
|
|
export default {
|
name: 'CChinaArea',
|
components: {
|
AtInput,
|
AtIcon,
|
},
|
props: {
|
// 表单数据资源(表单组件内部机制专用)
|
itemRes: Object,
|
// 是否自动通过地理定位获取省市区
|
autoGeo: {
|
type: Boolean,
|
default: false,
|
},
|
// 联动级别
|
level: {
|
type: Number,
|
default: 3,
|
},
|
// 占位提示
|
placeholder: String,
|
},
|
data() {
|
return {
|
loading: true,
|
range: [],
|
current: [],
|
};
|
},
|
computed: {
|
selected() {
|
const curVal = this.itemRes.formData[this.itemRes.name];
|
if (curVal && (curVal.length === 3 || curVal.length === 4)) {
|
return 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;
|
}
|
}
|
$locations.getLocationTree(this.level, locationTree => {
|
const curVal = this.itemRes.formData[this.itemRes.name];
|
const range2 = (locationTree[0] || {}).children || [];
|
const range3 = (range2[0] || {}).children || [];
|
const range = [locationTree, range2, range3];
|
const current = [0, 0, 0];
|
if (this.level === 4) {
|
const range4 = (range3[0] || {}).children || [];
|
range[3] = range4;
|
current[3] = '';
|
}
|
// 有值
|
if (curVal && curVal.length > 0) {
|
$locations.getRegionCodes(curVal, codes => {
|
// 省
|
if (codes[0]) {
|
const proviceIndex = locationTree.findIndex(
|
provice => provice.value === codes[0]
|
);
|
if (proviceIndex >= 0) {
|
range[1] = locationTree[proviceIndex].children;
|
range[2] =
|
locationTree[proviceIndex].children[0].children;
|
current[0] = proviceIndex;
|
// 市
|
if (codes[1]) {
|
const cityIndex = range[1].findIndex(
|
city => city.value === codes[1]
|
);
|
if (cityIndex >= 0) {
|
range[2] = range[1][cityIndex].children;
|
current[1] = cityIndex;
|
}
|
// 区
|
if (codes[2]) {
|
const distIndex = range[2].findIndex(
|
dist => dist.value === codes[2]
|
);
|
if (distIndex >= 0) {
|
current[2] = distIndex;
|
}
|
// 街
|
if (this.level === 4) {
|
range[3] =
|
range[2][current[2]].children || [];
|
const streetIndex = range[3].findIndex(
|
street => street.value === codes[3]
|
);
|
if (streetIndex >= 0) {
|
current[3] = streetIndex;
|
}
|
}
|
}
|
}
|
}
|
}
|
});
|
}
|
this.range = range;
|
this.current = current;
|
});
|
},
|
updateColumns(roll) {
|
$locations.getLocationTree(this.level, locationTree => {
|
// 第一列滚动
|
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];
|
if (this.level === 4) {
|
const range3 = (cities[0].children[0] || {}).children || [];
|
this.range.splice(3, 1, range3);
|
this.current.splice(3, 1, '');
|
}
|
}
|
// 第二列滚动
|
else if (roll.column === 1) {
|
const dists =
|
locationTree[this.current[0]].children[roll.value].children;
|
this.range = [this.range[0], this.range[1], dists];
|
this.current = [this.current[0], roll.value, 0];
|
if (this.level === 4) {
|
const range3 = dists[0].children || [];
|
this.range.splice(3, 1, range3);
|
this.current.splice(3, 1, '');
|
}
|
}
|
// 第三列滚动
|
else if (roll.column === 2) {
|
this.current.splice(2, 1, roll.value);
|
if (this.level === 4) {
|
const streets =
|
locationTree[this.current[0]].children[this.current[1]]
|
.children[roll.value].children || [];
|
this.range.splice(3, 1, streets);
|
this.current.splice(3, 1, '');
|
}
|
}
|
// 第四列滚动
|
else if (roll.column === 3) {
|
this.current.splice(3, 1, roll.value);
|
}
|
});
|
},
|
handleChange(detail) {
|
$locations.getLocationTree(this.level, locationTree => {
|
const names = [];
|
const provice = locationTree[detail[0]];
|
names[0] = provice.label;
|
const city = provice.children[detail[1]] || {};
|
names[1] = city.label;
|
const dist = city.children[detail[2]] || {};
|
names[2] = dist.label;
|
if (this.level === 4) {
|
const street = (dist.children || [])[detail[3]] || {};
|
if (street.value) {
|
names[3] = street.label;
|
}
|
}
|
this.itemRes.onChange(names);
|
});
|
},
|
_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 regions = [
|
address.province.replace(/省|市|自治区|特别行政区/g, ''),
|
address.city,
|
address.district,
|
address.street,
|
];
|
$locations.getRegionCodes(regions, codes => {
|
if (codes && codes.length > 0) {
|
$locations.getRegionNames(codes, names => {
|
this.itemRes.onChange(names);
|
});
|
}
|
});
|
this.loading = false;
|
});
|
},
|
cancel: res => (this.loading = false),
|
fail: err => (this.loading = false),
|
});
|
},
|
},
|
mounted() {
|
$locations.onReady(() => {
|
this.loading = false;
|
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>
|