hookehuyr

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

替换原生的位置权限申请弹窗为自定义样式弹窗,提升用户体验
<!--
* @Date: 2022-09-19 14:11:06
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-09-06 00:32:56
* @LastEditTime: 2025-09-06 13:18:25
* @FilePath: /lls_program/src/pages/ActivitiesCover/index.vue
* @Description: 活动海报页面 - 展示活动信息并处理定位授权
-->
......@@ -89,6 +89,43 @@
@cancel="onCancelSave"
cancel-txt="取消"
/>
<!-- 位置权限申请弹窗 -->
<nut-dialog
v-model:visible="showLocationDialog"
title="位置权限申请"
>
<template #default>
<view class=" text-gray-700 leading-loose text-sm text-left">
{{ locationContent }}
</view>
</template>
<template #footer>
<nut-row :gutter="10">
<nut-col :span="12">
<nut-button
@click="onLocationCancel"
type="default"
size="normal"
block
>
暂不授权
</nut-button>
</nut-col>
<nut-col :span="12">
<nut-button
@click="onLocationConfirm"
type="primary"
size="normal"
color="#007AFF"
block
>
同意授权
</nut-button>
</nut-col>
</nut-row>
</template>
</nut-dialog>
</view>
</template>
......@@ -118,6 +155,13 @@ const userLocation = ref({ lng: null, lat: null }) // 用户位置信息
const hasJoinedFamily = ref(false);
const showLocationPrompt = ref(false) // 是否显示定位权限提示
// Dialog 相关状态
const showLocationDialog = ref(false) // 是否显示位置权限申请弹窗
const pendingLocationCallback = ref(null) // 待执行的位置获取回调
// 位置权限申请说明内容
const locationContent = '为了提供更好的活动体验,我们需要获取您的位置信息:1. 验证您是否在活动区域内 2. 为您推荐附近的打卡点 3. 记录活动轨迹和完成情况 4. 提供基于位置的个性化服务, 我们承诺严格保护您的位置隐私,仅用于活动相关功能。'
// 海报生成相关状态
const show_post = ref(false) // 显示海报预览
const show_save = ref(false) // 显示保存弹窗
......@@ -185,20 +229,10 @@ const getUserLocation = async (skipAuthCheck = false) => {
// 如果没有授权,先显示数据用途说明
if (hasLocationAuth !== true) {
const modalRes = await Taro.showModal({
title: '位置权限申请',
content: '为了提供更好的活动体验,我们需要获取您的位置信息:1. 验证您是否在活动区域内 2. 为您推荐附近的打卡点 3. 记录活动轨迹和完成情况 4. 提供基于位置的个性化服务, 我们承诺严格保护您的位置隐私,仅用于活动相关功能。',
confirmText: '同意授权',
cancelText: '暂不授权'
return new Promise((resolve) => {
pendingLocationCallback.value = resolve
showLocationDialog.value = true
})
if (!modalRes.confirm) {
Taro.showToast({
title: '需要位置权限才能参与活动',
icon: 'none'
})
return false
}
}
}
......@@ -311,6 +345,57 @@ const retryGetLocation = async () => {
}
/**
* 位置权限申请弹窗 - 取消操作
*/
const onLocationCancel = () => {
showLocationDialog.value = false
if (pendingLocationCallback.value) {
Taro.showToast({
title: '需要位置权限才能参与活动',
icon: 'none'
})
pendingLocationCallback.value(false)
pendingLocationCallback.value = null
}
}
/**
* 位置权限申请弹窗 - 同意授权
*/
const onLocationConfirm = async () => {
showLocationDialog.value = false
try {
const location = await Taro.getLocation({
type: 'gcj02',
altitude: false,
isHighAccuracy: true,
highAccuracyExpireTime: 4000
})
userLocation.value = {
lng: location.longitude,
lat: location.latitude
}
console.log('获取到用户位置:', userLocation.value)
showLocationPrompt.value = false
hasLocationAuth.value = true
if (pendingLocationCallback.value) {
pendingLocationCallback.value(true)
pendingLocationCallback.value = null
}
} catch (error) {
console.error('获取位置失败:', error)
if (pendingLocationCallback.value) {
pendingLocationCallback.value(false)
pendingLocationCallback.value = null
}
}
}
/**
* 处理参加活动按钮点击
*/
const handleJoinActivity = async () => {
......