From 1ef56b68318629e24f8e42406822059262d392b9 Mon Sep 17 00:00:00 2001
From: coder77 <2293444075@qq.com>
Date: Thu, 10 Apr 2025 11:03:25 +0800
Subject: [PATCH] Merge branch 'master_dev' of ssh://dev.zhiheiot.com:29418/mob-components into master_dev

---
 plugins/baiduMap/CBaiduMap.weapp.vue |  442 +++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 284 insertions(+), 158 deletions(-)

diff --git a/plugins/baiduMap/CBaiduMap.weapp.vue b/plugins/baiduMap/CBaiduMap.weapp.vue
index c7f6728..2491458 100644
--- a/plugins/baiduMap/CBaiduMap.weapp.vue
+++ b/plugins/baiduMap/CBaiduMap.weapp.vue
@@ -28,7 +28,7 @@
                     type="primary"
                     size="small"
                     :onClick="evt => handleChooseLocation(evt)"
-                >选择位置</AtButton>
+                >选择地点</AtButton>
                 <AtButton
                     type="primary"
                     size="small"
@@ -41,7 +41,7 @@
                     size="small"
                     class="btn-info"
                     :onClick="evt => handleSaveLocation(evt)"
-                >保存</AtButton>
+                >确认</AtButton>
             </view>
         </view>
     </view>
@@ -51,6 +51,7 @@
 import Taro from '@tarojs/taro';
 import { AtButton } from 'taro-ui-vue';
 import { BAIDU_MAP, BMapWX } from './index';
+import './cBaiduMap.scss';
 
 export default {
     name: 'CBaiduMap',
@@ -69,68 +70,82 @@
     },
     data() {
         return {
+            // 地图上下文
             mapCtx: null,
+            // 地图是否准备就绪
             isMapReady: false,
+            // 当前位置
             currentLocation: null,
+            // 标记点id
             selectedMarkerId: 0,
+            // 标记点列表
             markers: [],
+            // 本地维护的坐标
+            localLatitude: this.latitude,
+            localLongitude: this.longitude,
+            // 地图坐标
             mapLatitude: this.latitude,
             mapLongitude: this.longitude,
+            // 地图缩放级别
             mapScale: 14,
+            // 是否由chooseLocation触发移动
+            isFromChooseLocation: false,
         };
     },
     watch: {
         latitude: {
             handler(newVal) {
-                console.log(newVal, '纬度');
                 if (newVal && this.longitude && this.isValidLatitude(newVal)) {
-                    this.mapLatitude = newVal;
+                    // 只在回显时更新本地坐标
+                    this.localLatitude = newVal;
                     this.moveToLocation(newVal, this.longitude);
-                    this.initLocation();
                 }
             },
-            immediate: true,
+            immediate: false,
         },
         longitude: {
             handler(newVal) {
-                console.log(newVal, '经度');
                 if (newVal && this.latitude && this.isValidLongitude(newVal)) {
-                    this.mapLongitude = newVal;
+                    // 只在回显时更新本地坐标
+                    this.localLongitude = newVal;
                     this.moveToLocation(this.latitude, newVal);
-                    this.initLocation();
                 }
             },
-            immediate: true,
+            immediate: false,
         },
     },
     mounted() {
         // 初始化地图
         this.initMap();
-        // 如果有初始经纬度,添加标记点
-        if (
-            this.latitude &&
-            this.longitude &&
-            this.isValidLatitude(this.latitude) &&
-            this.isValidLongitude(this.longitude)
-        ) {
-            this.initLocation();
-        }
+        // 设置一个延时,确保地图组件已完全加载
+        setTimeout(() => {
+            // 使用默认值处理可能的undefined或null
+            const latitude = this.latitude || 39.90886;
+            const longitude = this.longitude || 116.39739;
+            // 确保坐标有效
+            if (this.isValidLatitude(latitude) && this.isValidLongitude(longitude)) {
+                this.localLatitude = latitude;
+                this.localLongitude = longitude;
+                this.initLocation();
+            }
+        }, 800);
     },
     methods: {
         // 验证纬度是否有效
         isValidLatitude(lat) {
             return lat >= -90 && lat <= 90;
         },
+
         // 验证经度是否有效
         isValidLongitude(lng) {
             return lng >= -180 && lng <= 180;
         },
+
         // 初始化地图
         initMap() {
             try {
                 // 初始化地图上下文
                 this.mapCtx = Taro.createMapContext('map', this);
-
                 // 检查地图是否准备就绪
                 this.checkMapReady();
             } catch (error) {
@@ -154,26 +169,34 @@
 
         // 地图区域改变事件
         async handleRegionChange(evt) {
+            // 如果是由chooseLocation触发的移动,则不处理
+            if (this.isFromChooseLocation) {
+                return;
+            }
             if (!evt.detail || !evt.detail.centerLocation) {
                 return;
             }
-
             const { latitude, longitude } = evt.detail.centerLocation;
             if (!latitude || !longitude) {
                 return;
             }
-
             try {
+                // 将 GCJ-02 坐标转换为百度坐标用于获取地址
+                const baiduCoords = this.gcj02ToBaidu(latitude, longitude);
                 // 获取地址信息
-                const address = await this.getAddressFromLocation(latitude, longitude);
+                const address = await this.getAddressFromLocation(
+                    baiduCoords.lat,
+                    baiduCoords.lng,
+                );
                 if (!address || !address.address) {
                     return;
                 }
-
                 // 更新当前位置信息
                 this.currentLocation = {
-                    latitude,
-                    longitude,
+                    latitude: baiduCoords.lat,
+                    longitude: baiduCoords.lng,
+                    gcjLatitude: latitude,
+                    gcjLongitude: longitude,
                     address: address.address,
                     province: address.province,
                     city: address.city,
@@ -181,7 +204,6 @@
                     street: address.street,
                     streetNumber: address.streetNumber,
                 };
-
                 // 添加标记点并显示地址信息
                 this.addMarker(latitude, longitude, address.address);
                 // 通知父组件位置已更新
@@ -204,7 +226,7 @@
                 width: 20,
                 height: 20,
                 callout: {
-                    content: title,
+                    content: title || '未知位置',
                     color: '#000000',
                     fontSize: 14,
                     borderRadius: 4,
@@ -224,16 +246,21 @@
             if (!e || !e.detail) {
                 return;
             }
-
             const { latitude, longitude } = e.detail;
             if (!latitude || !longitude) {
                 return;
             }
-
             try {
+                // 更新本地坐标
+                this.localLatitude = latitude;
+                this.localLongitude = longitude;
+                // 将 GCJ-02 坐标转换为百度坐标用于获取地址
+                const baiduCoords = this.gcj02ToBaidu(latitude, longitude);
                 // 获取地址信息
-                const address = await this.getAddressFromLocation(latitude, longitude);
-
+                const address = await this.getAddressFromLocation(
+                    baiduCoords.lat,
+                    baiduCoords.lng,
+                );
                 if (!address || !address.address) {
                     Taro.showToast({
                         title: '获取地址失败',
@@ -241,10 +268,11 @@
                     });
                     return;
                 }
-
                 this.currentLocation = {
-                    latitude,
-                    longitude,
+                    latitude: baiduCoords.lat,
+                    longitude: baiduCoords.lng,
+                    gcjLatitude: latitude,
+                    gcjLongitude: longitude,
                     address: address.address,
                     province: address.province,
                     city: address.city,
@@ -252,7 +280,6 @@
                     street: address.street,
                     streetNumber: address.streetNumber,
                 };
-
                 // 添加标记点
                 this.addMarker(latitude, longitude, address.address);
                 this.$emit('locationSelected', this.currentLocation);
@@ -270,14 +297,18 @@
             const { markerId } = e.detail;
             const marker = this.markers.find(m => m.id === markerId);
             if (marker) {
+                // 转换为百度坐标
+                const baiduCoords = this.gcj02ToBaidu(marker.latitude, marker.longitude);
                 // 获取地址信息
                 const address = await this.getAddressFromLocation(
-                    marker.latitude,
-                    marker.longitude,
+                    baiduCoords.lat,
+                    baiduCoords.lng,
                 );
                 this.currentLocation = {
-                    latitude: marker.latitude,
-                    longitude: marker.longitude,
+                    latitude: baiduCoords.lat,
+                    longitude: baiduCoords.lng,
+                    gcjLatitude: marker.latitude,
+                    gcjLongitude: marker.longitude,
                     address: address.address,
                     province: address.province,
                     city: address.city,
@@ -291,36 +322,72 @@
 
         // 移动到指定位置
         moveToLocation(latitude, longitude) {
-            // 更新地图位置
+            // 更新地图位置数据
             this.mapLatitude = latitude;
             this.mapLongitude = longitude;
             this.mapScale = 16; // 设置合适的缩放级别
-
-            // 更新标记点位置
-            if (this.currentLocation) {
-                this.addMarker(latitude, longitude, this.currentLocation.address);
+            // 使用地图上下文移动到指定位置
+            if (this.mapCtx) {
+                this.mapCtx.moveToLocation({
+                    latitude: latitude,
+                    longitude: longitude,
+                    success: () => {
+                        // 更新标记点位置
+                        if (this.currentLocation) {
+                            this.addMarker(
+                                latitude,
+                                longitude,
+                                this.currentLocation.address,
+                            );
+                        }
+                    },
+                    fail: err => {
+                        console.error('移动失败:', err);
+                        // 失败时也要尝试更新标记点
+                        if (this.currentLocation) {
+                            this.addMarker(
+                                latitude,
+                                longitude,
+                                this.currentLocation.address,
+                            );
+                        }
+                    },
+                });
+            } else {
+                // 地图上下文不可用时,直接更新标记点
+                if (this.currentLocation) {
+                    this.addMarker(latitude, longitude, this.currentLocation.address);
+                }
             }
         },
 
         // 获取当前位置按钮点击事件
         async handleGetLocation(e) {
             try {
+                // 显示加载中提示
+                Taro.showLoading({
+                    title: '获取位置中...',
+                });
                 const res = await Taro.getLocation({
                     type: 'gcj02',
                 });
-
-                // 将GCJ-02坐标转换为百度坐标
-                const baiduLocation = this.gcj02ToBaidu(res.latitude, res.longitude);
-
+                // 更新本地坐标
+                this.localLatitude = res.latitude;
+                this.localLongitude = res.longitude;
+                // 设置标志,防止handleRegionChange触发时覆盖地址
+                this.isFromChooseLocation = true;
+                // 将 GCJ-02 坐标转换为百度坐标用于获取地址
+                const baiduCoords = this.gcj02ToBaidu(res.latitude, res.longitude);
                 // 获取地址信息
                 const address = await this.getAddressFromLocation(
-                    baiduLocation.lat,
-                    baiduLocation.lng,
+                    baiduCoords.lat,
+                    baiduCoords.lng,
                 );
-
                 this.currentLocation = {
-                    latitude: baiduLocation.lat,
-                    longitude: baiduLocation.lng,
+                    latitude: baiduCoords.lat,
+                    longitude: baiduCoords.lng,
+                    gcjLatitude: res.latitude,
+                    gcjLongitude: res.longitude,
                     address: address.address,
                     province: address.province,
                     city: address.city,
@@ -328,12 +395,24 @@
                     street: address.street,
                     streetNumber: address.streetNumber,
                 };
-
-                // 移动到当前位置(使用原始GCJ-02坐标)
-                this.moveToLocation(res.latitude, res.longitude);
+                // 直接更新地图位置
+                this.mapLatitude = res.latitude;
+                this.mapLongitude = res.longitude;
+                this.mapScale = 16;
+                // 添加标记点
+                this.addMarker(res.latitude, res.longitude, address.address);
+                // 通知父组件位置已更新
                 this.$emit('locationSelected', this.currentLocation);
+                // 完成后隐藏加载提示
+                Taro.hideLoading();
+                // 使用延时恢复标志
+                setTimeout(() => {
+                    this.isFromChooseLocation = false;
+                }, 800);
             } catch (error) {
                 console.error('获取位置失败:', error);
+                Taro.hideLoading();
+                this.isFromChooseLocation = false;
                 Taro.showToast({
                     title: '获取位置失败',
                     icon: 'none',
@@ -345,26 +424,56 @@
         async handleChooseLocation(e) {
             try {
                 const res = await Taro.chooseLocation();
-
-                // 将GCJ-02坐标转换为百度坐标
-                const baiduLocation = this.gcj02ToBaidu(res.latitude, res.longitude);
-
+                // 设置标志,防止handleRegionChange触发时覆盖地址
+                this.isFromChooseLocation = true;
+                // 更新本地坐标
+                this.localLatitude = res.latitude;
+                this.localLongitude = res.longitude;
+                // 转换为百度坐标
+                const baiduCoords = this.gcj02ToBaidu(res.latitude, res.longitude);
                 this.currentLocation = {
-                    latitude: baiduLocation.lat,
-                    longitude: baiduLocation.lng,
+                    latitude: baiduCoords.lat,
+                    longitude: baiduCoords.lng,
+                    gcjLatitude: res.latitude,
+                    gcjLongitude: res.longitude,
                     address: res.address,
+                    name: res.name || '',
                     province: '',
                     city: '',
                     district: '',
                     street: '',
                     streetNumber: '',
                 };
-
-                // 移动到选择的位置(使用原始GCJ-02坐标)
-                this.moveToLocation(res.latitude, res.longitude);
+                // 直接更新地图位置和添加标记点
+                this.mapLatitude = res.latitude;
+                this.mapLongitude = res.longitude;
+                this.mapScale = 16;
+                // 添加标记点
+                this.addMarker(res.latitude, res.longitude, res.address);
+                // 使用地图上下文移动到选择的位置
+                if (this.mapCtx) {
+                    this.mapCtx.moveToLocation({
+                        latitude: res.latitude,
+                        longitude: res.longitude,
+                        success: () => {
+                            // 再次确保标记点显示
+                            setTimeout(() => {
+                                // 重置标志
+                                this.isFromChooseLocation = false;
+                            }, 800);
+                        },
+                        fail: err => {
+                            console.error('移动失败:', err);
+                            // 重置标志
+                            this.isFromChooseLocation = false;
+                        },
+                    });
+                }
                 this.$emit('locationSelected', this.currentLocation);
             } catch (error) {
                 console.error('选择位置失败:', error);
+                // 重置标志
+                this.isFromChooseLocation = false;
                 Taro.showToast({
                     title: '选择位置失败',
                     icon: 'none',
@@ -397,11 +506,9 @@
                     },
                     timeout: 10000,
                 });
-
                 if (!res.data) {
                     throw new Error('百度地图API返回数据为空');
                 }
-
                 if (res.data.status === 0) {
                     const result = res.data.result;
                     return {
@@ -430,116 +537,135 @@
 
         // GCJ-02坐标转百度坐标
         gcj02ToBaidu(lat, lng) {
-            const x_pi = (3.14159265358979324 * 3000.0) / 180.0;
-            const x = lng;
-            const y = lat;
-            const z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
-            const theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
-            const lngs = z * Math.cos(theta);
-            const lats = z * Math.sin(theta);
+            const PI = 3.14159265358979324;
+            const x_pi = (PI * 3000.0) / 180.0;
+            const z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_pi);
+            const theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_pi);
+            const bd_lng = z * Math.cos(theta) + 0.0065;
+            const bd_lat = z * Math.sin(theta) + 0.006;
             return {
-                lat: lats,
-                lng: lngs,
+                lat: bd_lat,
+                lng: bd_lng,
             };
         },
 
         // 百度坐标转腾讯坐标
         baiduToGcj02(lat, lng) {
-            const x_pi = (3.14159265358979324 * 3000.0) / 180.0;
+            const PI = 3.14159265358979324;
+            const x_pi = (PI * 3000.0) / 180.0;
             const x = lng - 0.0065;
             const y = lat - 0.006;
             const z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
             const theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
-            const lngs = z * Math.cos(theta);
-            const lats = z * Math.sin(theta);
+            const gg_lng = z * Math.cos(theta);
+            const gg_lat = z * Math.sin(theta);
             return {
-                lat: lats,
-                lng: lngs,
+                lat: gg_lat,
+                lng: gg_lng,
             };
         },
 
         // 初始化位置信息
         async initLocation() {
             try {
-                // 获取地址信息
-                const address = await this.getAddressFromLocation(
-                    this.latitude,
-                    this.longitude,
-                );
-                if (!address || !address.address) {
-                    return;
+                // 设置标志,防止handleRegionChange触发时覆盖地址
+                this.isFromChooseLocation = true;
+                // 显示加载提示
+                Taro.showLoading({
+                    title: '加载位置信息...',
+                });
+                try {
+                    // 使用本地坐标(初始默认值或props传入值)获取地址信息
+                    const address = await this.getAddressFromLocation(
+                        this.localLatitude,
+                        this.localLongitude,
+                    );
+                    if (!address || !address.address) {
+                        console.warn('获取地址信息失败');
+                        Taro.hideLoading();
+                        this.isFromChooseLocation = false;
+                        return;
+                    }
+                    // 将百度坐标转换为腾讯坐标
+                    const gcjCoords = this.baiduToGcj02(
+                        this.localLatitude,
+                        this.localLongitude,
+                    );
+                    // 更新当前位置信息
+                    this.currentLocation = {
+                        latitude: this.localLatitude,
+                        longitude: this.localLongitude,
+                        gcjLatitude: gcjCoords.lat,
+                        gcjLongitude: gcjCoords.lng,
+                        address: address.address,
+                        province: address.province,
+                        city: address.city,
+                        district: address.district,
+                        street: address.street,
+                        streetNumber: address.streetNumber,
+                    };
+                    // 使用腾讯坐标更新地图位置
+                    this.mapLatitude = gcjCoords.lat;
+                    this.mapLongitude = gcjCoords.lng;
+                    this.mapScale = 16;
+                    // 添加标记点
+                    this.markers = [
+                        {
+                            id: this.selectedMarkerId++,
+                            latitude: gcjCoords.lat,
+                            longitude: gcjCoords.lng,
+                            title: address.address,
+                            width: 30,
+                            height: 30,
+                            callout: {
+                                content: address.address || '未知位置',
+                                color: '#000000',
+                                fontSize: 14,
+                                borderRadius: 4,
+                                padding: 8,
+                                display: 'ALWAYS',
+                                bgColor: '#ffffff',
+                                borderWidth: 1,
+                                borderColor: '#cccccc',
+                                textAlign: 'center',
+                                anchorY: -10,
+                            },
+                        },
+                    ];
+                    // 通知父组件位置已更新
+                    this.$emit('locationSelected', this.currentLocation);
+                    // 隐藏加载提示
+                    Taro.hideLoading();
+                    // 使用地图上下文移动到位置中心
+                    if (this.mapCtx) {
+                        this.mapCtx.moveToLocation({
+                            latitude: gcjCoords.lat,
+                            longitude: gcjCoords.lng,
+                            success: () => {
+                                // 延迟重置标志
+                                setTimeout(() => {
+                                    this.isFromChooseLocation = false;
+                                }, 800);
+                            },
+                            fail: err => {
+                                console.error('地图移动失败:', err);
+                                this.isFromChooseLocation = false;
+                            },
+                        });
+                    } else {
+                        this.isFromChooseLocation = false;
+                    }
+                } catch (error) {
+                    console.error('处理位置信息失败:', error);
+                    Taro.hideLoading();
+                    this.isFromChooseLocation = false;
                 }
-
-                // 更新当前位置信息
-                this.currentLocation = {
-                    latitude: this.latitude,
-                    longitude: this.longitude,
-                    address: address.address,
-                    province: address.province,
-                    city: address.city,
-                    district: address.district,
-                    street: address.street,
-                    streetNumber: address.streetNumber,
-                };
-
-                // 添加标记点
-                this.addMarker(this.latitude, this.longitude, address.address);
-                // 通知父组件位置已更新
-                this.$emit('locationSelected', this.currentLocation);
             } catch (error) {
-                console.error('初始化位置信息失败:', error);
+                console.error('初始化位置信息失败:', error);
+                Taro.hideLoading();
+                this.isFromChooseLocation = false;
             }
         },
     },
 };
-</script>
-
-<style lang="scss">
-.c-baidu-map {
-    width: 100%;
-    height: 100%;
-    position: relative;
-    display: block;
-
-    .map {
-        width: 100%;
-        height: 100%;
-        display: block;
-    }
-
-    .map-controls {
-        position: absolute;
-        bottom: 0;
-        left: 0;
-        right: 0;
-        background: rgba(255, 255, 255, 0.9);
-        z-index: 100;
-
-        .map-controls-top {
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-            height: 100px;
-            padding: 0 20px;
-            .at-button {
-                width: 45%;
-                height: 76px !important;
-                line-height: 72px;
-                font-size: 40px;
-            }
-        }
-        .map-controls-bottom {
-            display: flex;
-            align-items: center;
-            height: 100px;
-            padding: 0 20px;
-            .at-button {
-                width: 95%;
-                height: 76px !important;
-                line-height: 72px;
-                font-size: 40px;
-            }
-        }
-    }
-}
-</style>
\ No newline at end of file
+</script>
\ No newline at end of file

--
Gitblit v1.9.1