| | |
| | | /** |
| | | * CChinaArea |
| | | * CChinaArea - 表单项,中国地址三级联动 |
| | | * @author Tevin |
| | | */ |
| | | |
| | |
| | | <view @tap="evt=>handleOpen(evt)"> |
| | | <AtInput |
| | | ref="input" |
| | | :name="itemData.name" |
| | | :title="itemData.label" |
| | | :required="itemData.required" |
| | | :error="itemData.error" |
| | | :name="itemRes.name" |
| | | :title="itemRes.label" |
| | | :required="itemRes.required" |
| | | :error="itemRes.error" |
| | | :placeholder="placeholder" |
| | | :value="selected" |
| | | > |
| | | <view class="at-icon at-icon-chevron-right" /> |
| | | <AtIcon :value="loading ? 'loading':'chevron-right'" /> |
| | | </AtInput> |
| | | </view> |
| | | </picker> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import { AtInput } from 'taro-ui-vue'; |
| | | import Taro from '@tarojs/taro'; |
| | | import { AtInput, AtIcon } from 'taro-ui-vue'; |
| | | import ChinaLocations from './ChinaLocations'; |
| | | import './cChinaArea.scss'; |
| | | |
| | | const { locationTree, getRegionNames } = ChinaLocations; |
| | | const { onReady, getLocationTree, getRegionNames, getRegionCodes } = ChinaLocations; |
| | | |
| | | export default { |
| | | name: 'CChinaArea', |
| | | components: { |
| | | AtInput, |
| | | AtIcon, |
| | | }, |
| | | props: { |
| | | // 表单数据资源(表单组件内部机制专用) |
| | | itemRes: Object, |
| | | // 是否自动通过地理定位获取省市区 |
| | | autoGeo: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | // 占位提示 |
| | | placeholder: String, |
| | | itemData: Object, |
| | | }, |
| | | data() { |
| | | return { |
| | | loading: false, |
| | | range: [[], [], []], |
| | | current: [0, 0, 0], |
| | | }; |
| | | }, |
| | | computed: { |
| | | selected() { |
| | | const curVal = this.itemData.formData[this.itemData.name]; |
| | | const curVal = this.itemRes.formData[this.itemRes.name]; |
| | | if (curVal && curVal.length === 3) { |
| | | return getRegionNames(curVal).join(' / '); |
| | | } else { |
| | |
| | | }, |
| | | 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.itemData.formData[this.itemData.name]; |
| | | const locationTree = getLocationTree(); |
| | | const curVal = this.itemRes.formData[this.itemRes.name]; |
| | | const range = [ |
| | | locationTree, |
| | | locationTree[0].children, |
| | |
| | | // 省 |
| | | if (curVal[0]) { |
| | | const proviceIndex = locationTree.findIndex( |
| | | (provice) => provice.code === curVal[0] |
| | | provice => provice.value === curVal[0] |
| | | ); |
| | | if (proviceIndex >= 0) { |
| | | range[1] = locationTree[proviceIndex].children; |
| | |
| | | current[0] = proviceIndex; |
| | | // 市 |
| | | if (curVal[1]) { |
| | | const cityIndex = range[1].findIndex((city) => city.code === curVal[1]); |
| | | const cityIndex = range[1].findIndex( |
| | | city => city.value === curVal[1] |
| | | ); |
| | | if (cityIndex >= 0) { |
| | | range[2] = range[1].children[cityIndex].children; |
| | | range[2] = range[1][cityIndex].children; |
| | | current[1] = cityIndex; |
| | | } |
| | | // 区 |
| | | if (curVal[2]) { |
| | | const areaIndex = range[2].findIndex( |
| | | (area) => area.code === curVal[2] |
| | | area => area.value === curVal[2] |
| | | ); |
| | | if (areaIndex >= 0) { |
| | | current[2] === areaIndex; |
| | | current[2] = areaIndex; |
| | | } |
| | | } |
| | | } |
| | |
| | | this.current = current; |
| | | }, |
| | | updateColumns(roll) { |
| | | const locationTree = getLocationTree(); |
| | | // 第一列滚动 |
| | | if (roll.column === 0) { |
| | | const cities = locationTree[roll.value].children; |
| | | this.range.splice(1, 2, cities, cities[0].children); |
| | | this.range = [this.range[0], cities, cities[0].children]; |
| | | this.current = [roll.value, 0, 0]; |
| | | } else if (roll.column === 1) { |
| | | } |
| | | // 第二列滚动 |
| | | else if (roll.column === 1) { |
| | | const areas = locationTree[this.current[0]].children[roll.value].children; |
| | | this.range.splice(2, 1, areas); |
| | | this.range = [this.range[0], this.range[1], areas]; |
| | | this.current = [this.current[0], roll.value, 0]; |
| | | } else if (roll.column === 3) { |
| | | } |
| | | // 第三列滚动 |
| | | 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]]; |
| | | const city = provice.children[detail[1]] || []; |
| | | codes[1] = city.value; |
| | | const area = city.children[detail[2]]; |
| | | const area = city.children[detail[2]] || []; |
| | | codes[2] = area.value; |
| | | this.itemData.onChange(codes); |
| | | 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() {}, |
| | | 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> |