hookehuyr

feat(定位授权): 添加位置权限申请自定义弹窗组件

替换原生的位置权限申请弹窗为自定义样式弹窗,提升用户体验
1 <!-- 1 <!--
2 * @Date: 2022-09-19 14:11:06 2 * @Date: 2022-09-19 14:11:06
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-09-06 00:32:56 4 + * @LastEditTime: 2025-09-06 13:18:25
5 * @FilePath: /lls_program/src/pages/ActivitiesCover/index.vue 5 * @FilePath: /lls_program/src/pages/ActivitiesCover/index.vue
6 * @Description: 活动海报页面 - 展示活动信息并处理定位授权 6 * @Description: 活动海报页面 - 展示活动信息并处理定位授权
7 --> 7 -->
...@@ -89,6 +89,43 @@ ...@@ -89,6 +89,43 @@
89 @cancel="onCancelSave" 89 @cancel="onCancelSave"
90 cancel-txt="取消" 90 cancel-txt="取消"
91 /> 91 />
92 +
93 + <!-- 位置权限申请弹窗 -->
94 + <nut-dialog
95 + v-model:visible="showLocationDialog"
96 + title="位置权限申请"
97 + >
98 + <template #default>
99 + <view class=" text-gray-700 leading-loose text-sm text-left">
100 + {{ locationContent }}
101 + </view>
102 + </template>
103 + <template #footer>
104 + <nut-row :gutter="10">
105 + <nut-col :span="12">
106 + <nut-button
107 + @click="onLocationCancel"
108 + type="default"
109 + size="normal"
110 + block
111 + >
112 + 暂不授权
113 + </nut-button>
114 + </nut-col>
115 + <nut-col :span="12">
116 + <nut-button
117 + @click="onLocationConfirm"
118 + type="primary"
119 + size="normal"
120 + color="#007AFF"
121 + block
122 + >
123 + 同意授权
124 + </nut-button>
125 + </nut-col>
126 + </nut-row>
127 + </template>
128 + </nut-dialog>
92 </view> 129 </view>
93 </template> 130 </template>
94 131
...@@ -118,6 +155,13 @@ const userLocation = ref({ lng: null, lat: null }) // 用户位置信息 ...@@ -118,6 +155,13 @@ const userLocation = ref({ lng: null, lat: null }) // 用户位置信息
118 const hasJoinedFamily = ref(false); 155 const hasJoinedFamily = ref(false);
119 const showLocationPrompt = ref(false) // 是否显示定位权限提示 156 const showLocationPrompt = ref(false) // 是否显示定位权限提示
120 157
158 +// Dialog 相关状态
159 +const showLocationDialog = ref(false) // 是否显示位置权限申请弹窗
160 +const pendingLocationCallback = ref(null) // 待执行的位置获取回调
161 +
162 +// 位置权限申请说明内容
163 +const locationContent = '为了提供更好的活动体验,我们需要获取您的位置信息:1. 验证您是否在活动区域内 2. 为您推荐附近的打卡点 3. 记录活动轨迹和完成情况 4. 提供基于位置的个性化服务, 我们承诺严格保护您的位置隐私,仅用于活动相关功能。'
164 +
121 // 海报生成相关状态 165 // 海报生成相关状态
122 const show_post = ref(false) // 显示海报预览 166 const show_post = ref(false) // 显示海报预览
123 const show_save = ref(false) // 显示保存弹窗 167 const show_save = ref(false) // 显示保存弹窗
...@@ -185,20 +229,10 @@ const getUserLocation = async (skipAuthCheck = false) => { ...@@ -185,20 +229,10 @@ const getUserLocation = async (skipAuthCheck = false) => {
185 229
186 // 如果没有授权,先显示数据用途说明 230 // 如果没有授权,先显示数据用途说明
187 if (hasLocationAuth !== true) { 231 if (hasLocationAuth !== true) {
188 - const modalRes = await Taro.showModal({ 232 + return new Promise((resolve) => {
189 - title: '位置权限申请', 233 + pendingLocationCallback.value = resolve
190 - content: '为了提供更好的活动体验,我们需要获取您的位置信息:1. 验证您是否在活动区域内 2. 为您推荐附近的打卡点 3. 记录活动轨迹和完成情况 4. 提供基于位置的个性化服务, 我们承诺严格保护您的位置隐私,仅用于活动相关功能。', 234 + showLocationDialog.value = true
191 - confirmText: '同意授权',
192 - cancelText: '暂不授权'
193 - })
194 -
195 - if (!modalRes.confirm) {
196 - Taro.showToast({
197 - title: '需要位置权限才能参与活动',
198 - icon: 'none'
199 }) 235 })
200 - return false
201 - }
202 } 236 }
203 } 237 }
204 238
...@@ -311,6 +345,57 @@ const retryGetLocation = async () => { ...@@ -311,6 +345,57 @@ const retryGetLocation = async () => {
311 } 345 }
312 346
313 /** 347 /**
348 + * 位置权限申请弹窗 - 取消操作
349 + */
350 +const onLocationCancel = () => {
351 + showLocationDialog.value = false
352 + if (pendingLocationCallback.value) {
353 + Taro.showToast({
354 + title: '需要位置权限才能参与活动',
355 + icon: 'none'
356 + })
357 + pendingLocationCallback.value(false)
358 + pendingLocationCallback.value = null
359 + }
360 +}
361 +
362 +/**
363 + * 位置权限申请弹窗 - 同意授权
364 + */
365 +const onLocationConfirm = async () => {
366 + showLocationDialog.value = false
367 +
368 + try {
369 + const location = await Taro.getLocation({
370 + type: 'gcj02',
371 + altitude: false,
372 + isHighAccuracy: true,
373 + highAccuracyExpireTime: 4000
374 + })
375 +
376 + userLocation.value = {
377 + lng: location.longitude,
378 + lat: location.latitude
379 + }
380 +
381 + console.log('获取到用户位置:', userLocation.value)
382 + showLocationPrompt.value = false
383 + hasLocationAuth.value = true
384 +
385 + if (pendingLocationCallback.value) {
386 + pendingLocationCallback.value(true)
387 + pendingLocationCallback.value = null
388 + }
389 + } catch (error) {
390 + console.error('获取位置失败:', error)
391 + if (pendingLocationCallback.value) {
392 + pendingLocationCallback.value(false)
393 + pendingLocationCallback.value = null
394 + }
395 + }
396 +}
397 +
398 +/**
314 * 处理参加活动按钮点击 399 * 处理参加活动按钮点击
315 */ 400 */
316 const handleJoinActivity = async () => { 401 const handleJoinActivity = async () => {
......