| | |
| | | <template> |
| | | <view class="c-china-area"> |
| | | <picker |
| | | class="c-china-area-picker" |
| | | mode="multiSelector" |
| | | :range="range" |
| | | :value="current" |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import Taro from '@tarojs/taro'; |
| | | import { AtInput, AtIcon } from 'taro-ui-vue'; |
| | | import ChinaLocations from './ChinaLocations'; |
| | | import { $locations } from '@components/forms/chinaArea/ChinaLocations'; |
| | | import './cChinaArea.scss'; |
| | | |
| | | const { locationTree, getRegionNames } = ChinaLocations; |
| | | |
| | | export default { |
| | | name: 'CChinaArea', |
| | |
| | | props: { |
| | | // 表单数据资源(表单组件内部机制专用) |
| | | itemRes: Object, |
| | | // 当地址获取经纬度时,设置加载中显示状态 |
| | | loading: { |
| | | // 是否自动通过地理定位获取省市区 |
| | | autoGeo: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | // 联动级别 |
| | | level: { |
| | | type: Number, |
| | | default: 3, |
| | | }, |
| | | // 占位提示 |
| | | placeholder: String, |
| | | }, |
| | | data() { |
| | | return { |
| | | range: [[], [], []], |
| | | current: [0, 0, 0], |
| | | loading: true, |
| | | range: [], |
| | | current: [], |
| | | }; |
| | | }, |
| | | computed: { |
| | | selected() { |
| | | const curVal = this.itemRes.formData[this.itemRes.name]; |
| | | if (curVal && curVal.length === 3) { |
| | | return getRegionNames(curVal).join(' / '); |
| | | if (curVal && (curVal.length === 3 || curVal.length === 4)) { |
| | | return curVal.join(' / '); |
| | | } else { |
| | | return ''; |
| | | } |
| | |
| | | }, |
| | | methods: { |
| | | handleOpen(evt) { |
| | | if (evt.target.className.indexOf('at-input__title') >= 0) { |
| | | evt.stopPropagation(); |
| | | evt.preventDefault(); |
| | | return; |
| | | if (process.env.TARO_ENV === 'h5') { |
| | | if (evt && evt.target.className.indexOf('at-input__title') >= 0) { |
| | | evt.stopPropagation(); |
| | | evt.preventDefault(); |
| | | return; |
| | | } |
| | | } |
| | | 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.code === 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.code === curVal[1] |
| | | $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 (cityIndex >= 0) { |
| | | range[2] = range[1].children[cityIndex].children; |
| | | current[1] = cityIndex; |
| | | } |
| | | // 区 |
| | | if (curVal[2]) { |
| | | const areaIndex = range[2].findIndex( |
| | | area => area.code === curVal[2] |
| | | ); |
| | | if (areaIndex >= 0) { |
| | | current[2] === areaIndex; |
| | | 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; |
| | | this.range = range; |
| | | setTimeout(() => { |
| | | this.current = current; |
| | | }, 100); |
| | | }); |
| | | }, |
| | | updateColumns(roll) { |
| | | if (roll.column === 0) { |
| | | const cities = locationTree[roll.value].children; |
| | | this.range.splice(1, 2, 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.splice(2, 1, areas); |
| | | this.current = [this.current[0], roll.value, 0]; |
| | | } else if (roll.column === 3) { |
| | | this.current.splice(2, 1, roll.value); |
| | | } |
| | | $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) { |
| | | 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); |
| | | $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, |
| | | ]; |
| | | if (this.level === 4) { |
| | | regions.push(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() {}, |
| | | 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> |