WebApp【公共组件库】@前端(For Git Submodule)
Tevin
2023-07-31 f0adae265c4a40159c665fb424305a27b1afcece
forms/chinaArea/CChinaArea.vue
@@ -1,11 +1,12 @@
/**
 * CChinaArea
 * CChinaArea - 表单项,中国地址三级联动
 * @author Tevin
 */
<template>
    <view class="c-china-area">
        <picker
            class="c-china-area-picker"
            mode="multiSelector"
            :range="range"
            :value="current"
@@ -31,11 +32,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 +44,33 @@
        AtIcon,
    },
    props: {
        loading: {
        // 表单数据资源(表单组件内部机制专用)
        itemRes: Object,
        // 是否自动通过地理定位获取省市区
        autoGeo: {
            type: Boolean,
            default: false,
        },
        // 联动级别
        level: {
            type: Number,
            default: 3,
        },
        // 占位提示
        placeholder: String,
        itemRes: Object,
    },
    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 '';
            }
@@ -69,76 +78,196 @@
    },
    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]);
                            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;
                this.current = current;
            });
        },
        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,
                            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>