From fdeb869c386da95150a087bc22bcebc4e57d0f76 Mon Sep 17 00:00:00 2001 From: Tevin <tingquanren@163.com> Date: Tue, 18 Mar 2025 18:16:32 +0800 Subject: [PATCH] 更新所有表单组件文档和头注释 --- forms/chinaArea/CChinaArea.vue | 286 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 211 insertions(+), 75 deletions(-) diff --git a/forms/chinaArea/CChinaArea.vue b/forms/chinaArea/CChinaArea.vue index 6a6d577..faadcf5 100644 --- a/forms/chinaArea/CChinaArea.vue +++ b/forms/chinaArea/CChinaArea.vue @@ -1,11 +1,15 @@ /** - * CChinaArea + * CChinaArea - 表单项,中国地址三级联动 + * 中国地区选择器组件,用于在表单中选择省市区地址 + * 内置完整的中国行政区划数据,支持多级联动选择 + * 支持自动通过地理定位获取省市区 * @author Tevin */ <template> <view class="c-china-area"> <picker + class="c-china-area-picker" mode="multiSelector" :range="range" :value="current" @@ -16,10 +20,10 @@ <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" > @@ -31,11 +35,10 @@ </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', @@ -44,24 +47,33 @@ AtIcon, }, props: { - loading: { + // 表单数据资源(表单组件内部机制专用) + itemRes: Object, + // 是否自动通过地理定位获取省市区 + autoGeo: { type: Boolean, default: false, }, + // 联动级别 + level: { + type: Number, + default: 3, + }, + // 占位提示 placeholder: String, - itemData: Object, }, data() { return { - range: [[], [], []], - current: [0, 0, 0], + loading: true, + range: [], + current: [], }; }, computed: { selected() { - const curVal = this.itemData.formData[this.itemData.name]; - if (curVal && curVal.length === 3) { - return getRegionNames(curVal).join(' / '); + const curVal = this.itemRes.formData[this.itemRes.name]; + if (curVal && (curVal.length === 3 || curVal.length === 4)) { + return curVal.join(' / '); } else { return ''; } @@ -69,76 +81,200 @@ }, 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 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]); - 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; + $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; + 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.itemData.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> \ No newline at end of file -- Gitblit v1.9.1