quanwei
2025-11-03 ef5d748e3e3331bd20d4065c33e7867c2637d1db
mobile/pages/branch/activity/detail/detail.vue
@@ -78,11 +78,12 @@
               </view>
            </view>
            <!-- 活动介绍 -->
            <view class="wrapper bg-white radius24" v-if="activityData.content">
            <view class="wrapper bg-white radius24" v-if="activityData.content || activityData.describe">
               <view class="info-title-box tc pt30 fb f30">
                  <view class="info-title">活动介绍</view>
               </view>
               <view class="activity-desc p30" v-html="activityData.content"></view>
               <view class="activity-desc p30" v-html="activityData.content||activityData.describe"></view>
               <!-- <view class="activity-desc p30" v-else>{{ activityData.describe }}</view> -->
            </view>
         </view>
         <view class="detail-footer">
@@ -214,45 +215,26 @@
            longitude: 0,
            isVerify: false, // 签到成功弹窗
            in_radius: false, // 用户是否在活动地点限定范围内
            user_verify: 0, // 核销标识,只有扫核销码进来值才是1
         }
      },
      onLoad(e) {
         /*活动id*/
         let scene = utils.getSceneData(e);
         this.activity_id = e.activity_id ? e.activity_id : scene.activity_id;
         if (scene && typeof scene === 'object' && Object.keys(scene).length > 0) {
            this.activity_id = scene.activity_id;
            this.user_verify = scene.user_verify;
         } else {
            this.activity_id = e.activity_id;
         }
      },
      onShow() {
         this.getUserLocation();
         this.getData();
      },
      onUnload() {
         this.stopWatchingLocation();
      },
      methods: {
         // 获取用户坐标并判断在不在活动范围内
         getUserLocation() {
            let self = this;
            uni.getLocation({
               type: 'gcj02',
               success: (res) => {
                  self.latitude = res.latitude;
                  self.longitude = res.longitude;
                  // 计算距离
                  const distance = this.calculateDistance(
                     res.latitude, res.longitude,
                     parseFloat(self.activityData.latitude), parseFloat(self.activityData.longitude)
                  );
                  if (distance <= self.activityData.radius) {
                     self.in_radius = true;
                  }
               },
               fail: (err) => {
                  console.error('获取位置失败:', err);
                  uni.showToast({
                     title:'获取位置失败' + err,
                     icon: 'none'
                  });
               }
            });
         },
         /*获取数据*/
         getData() {
            let self = this;
@@ -267,18 +249,212 @@
               function(res) {
                  self.activityData = res.data.detail;
                  self.userList = res.data.userList;
                  if (self.activityData.radius > 0) {
                     self.getUserLocation();
                  // 当活动设置了签到范围并且是扫核销码进来的
                  if (self.activityData.radius > 0 && self.user_verify) {
                     self.initializeWithLocation();
                  }
                  self.loadding = false;
                  uni.hideLoading();
               }
            );
         },
         // 初始化并等待位置信息
         async initializeWithLocation() {
            try {
               // 等待获取第一个有效位置
               const location = await this.startWatchingLocation();
               console.log('获得初始位置:', location);
               // 检查用户是否在活动范围
               this.updateInRadius();
            } catch (error) {
               console.error('初始化失败:', error);
               uni.showToast({
                  title: '位置获取失败,请重新扫码试试',
                  icon: 'none'
               });
            }
         },
         // 修改后的开始监听位置方法,返回 Promise
         startWatchingLocation() {
            return new Promise(async (resolve, reject) => {
               try {
                  // 存储 resolve 和 reject 以便在位置回调中使用
                  this.locationResolve = resolve;
                  this.locationReject = reject;
                  // 申请定位权限
                  await this.authorizeLocation();
                  // 开始位置更新
                  await this.startLocationUpdate();
                  // 监听位置变化
                  this.watchLocationChange();
                  // 设置超时处理
                  setTimeout(() => {
                     if (this.locationReject) {
                        this.locationReject(new Error('位置获取超时'));
                        this.locationResolve = null;
                        this.locationReject = null;
                     }
                  }, 10000); // 10秒超时
               } catch (error) {
                  reject(error);
               }
            });
         },
         // 授权定位
         authorizeLocation() {
            return new Promise((resolve, reject) => {
               uni.authorize({
                  scope: 'scope.userLocation',
                  success: resolve,
                  fail: (err) => {
                     uni.showModal({
                        title: '提示',
                        content: '需要您授权位置信息,请前往设置页开启权限',
                        success: (modalRes) => {
                           if (modalRes.confirm) {
                              uni.openSetting({
                                 success: (openRes) => {
                                    if (openRes.authSetting[
                                          'scope.userLocation'
                                          ]) {
                                       resolve();
                                    } else {
                                       reject(new Error(
                                          '用户未授权位置权限'));
                                    }
                                 }
                              });
                           } else {
                              reject(new Error('用户取消授权'));
                           }
                        }
                     });
                  }
               });
            });
         },
         // 开启位置更新
         startLocationUpdate() {
            return new Promise((resolve, reject) => {
               uni.startLocationUpdate({
                  success: resolve,
                  fail: reject
               });
            });
         },
         // 监听位置变化
         watchLocationChange() {
            if (this._locationChangeCallback) {
               uni.offLocationChange(this._locationChangeCallback);
            }
            this._locationChangeCallback = (res) => {
               console.log('位置变化:', res);
               this.latitude = res.latitude;
               this.longitude = res.longitude;
               // 如果是第一次获取位置,解析 Promise
               if (this.locationResolve) {
                  this.locationResolve({
                     latitude: res.latitude,
                     longitude: res.longitude,
                     accuracy: res.accuracy
                  });
                  this.locationResolve = null;
                  this.locationReject = null;
               }
               // 位置更新后处理
               this.updateInRadius();
            };
            uni.onLocationChange(this._locationChangeCallback);
         },
         // 检查是否在签到范围
         updateInRadius() {
            let self = this;
            // 如果不是扫码进来的或者没有设置活动范围
            if (!self.user_verify || !self.activityData.radius) {
               return;
            }
            // 计算距离
            const distance = this.calculateDistance(
               parseFloat(self.latitude),
               parseFloat(self.longitude),
               parseFloat(self.activityData.latitude),
               parseFloat(self.activityData.longitude)
            );
            if (distance <= self.activityData.radius) {
               self.in_radius = true;
            }
         },
         // 停止监听位置
         stopWatchingLocation() {
            if (this._locationChangeCallback) {
               uni.offLocationChange(this._locationChangeCallback);
               this._locationChangeCallback = null;
            }
            // 清理 Promise 相关状态
            if (this.locationReject) {
               this.locationReject(new Error('位置监听已停止'));
               this.locationResolve = null;
               this.locationReject = null;
            }
            uni.stopLocationUpdate();
         },
         // 获取用户坐标并判断在不在活动范围内(弃用)
         // getUserLocation() {
         //    let self = this;
         //    uni.getLocation({
         //       type: 'gcj02',
         //       success: (res) => {
         //          self.latitude = res.latitude;
         //          self.longitude = res.longitude;
         //          // 计算距离
         //          const distance = this.calculateDistance(
         //             res.latitude, res.longitude,
         //             parseFloat(self.activityData.latitude), parseFloat(self.activityData.longitude)
         //          );
         //          if (distance <= self.activityData.radius) {
         //             self.in_radius = true;
         //          }
         //       },
         //       fail: (err) => {
         //          console.error('获取位置失败:', err);
         //          uni.showToast({
         //             title: '获取位置失败' + err,
         //             icon: 'none'
         //          });
         //       }
         //    });
         // },
         onReg() {
            this.isOpenReg = true;
            this.$refs.regForm.activityData = this.activityData;
            if (this.activityData.fee > 0) {
               this.isOpenReg = true;
            } else {
               this.$refs.regForm.onSubmit();
            }
         },
         closeRegFunc(e) {
@@ -302,16 +478,16 @@
            let self = this;
            if (!self.in_radius && self.activityData.radius > 0) {
               uni.showModal({
                 title: '签到失败',
                 content: `您距离活动地点太远,无法签到`,
                 showCancel: false
                  title: '签到失败',
                  content: `您距离活动地点太远,无法签到`,
                  showCancel: false
               });
               return false;
            } else {
               self.doVierfy();
            }
         },
         // 执行签到
         doVierfy() {
            let self = this;
@@ -329,24 +505,24 @@
               }
            );
         },
         // 计算坐标距离
         calculateDistance(lat1, lng1, lat2, lng2) {
           const R = 6371000; // 地球半径(米)
           const toRadians = (degree) => degree * (Math.PI / 180);
           const φ1 = toRadians(lat1);
           const φ2 = toRadians(lat2);
           const Δφ = toRadians(lat2 - lat1);
           const Δλ = toRadians(lng2 - lng1);
           const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
                     Math.cos(φ1) * Math.cos(φ2) *
                     Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
           const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
           const distance = R * c;
           return Math.round(distance * 100) / 100; // 保留两位小数
            const R = 6371000; // 地球半径(米)
            const toRadians = (degree) => degree * (Math.PI / 180);
            const φ1 = toRadians(lat1);
            const φ2 = toRadians(lat2);
            const Δφ = toRadians(lat2 - lat1);
            const Δλ = toRadians(lng2 - lng1);
            const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
               Math.cos(φ1) * Math.cos(φ2) *
               Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
            const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
            const distance = R * c;
            return Math.round(distance * 100) / 100; // 保留两位小数
         },
         // 打开相册
@@ -449,10 +625,11 @@
               }
            });
         },
         gotoSupplier() {
            this.gotoPage('pages/shop/shop?shop_supplier_id=' + this.activityData.visit_supplier_id);
         },
      }
   }
</script>
@@ -560,7 +737,7 @@
            height: 120rpx;
         }
      }
      .status-verify {
         position: absolute;
         bottom: 200rpx;
@@ -569,7 +746,7 @@
         border-radius: 60rpx 0 0 60rpx;
         font-size: 28rpx;
         padding: 6rpx 20rpx;
         .iconfont {
            margin-right: 10rpx;
         }