hookehuyr

feat(scan-checkin-detail): 新增签到位置权限确认弹窗流程

为扫码签到功能新增位置权限确认弹窗流程,当活动开启位置验证时弹出弹窗请求用户授权,处理用户的同意或拒绝操作,拒绝时显示提示并终止签到流程。
...@@ -47,11 +47,39 @@ ...@@ -47,11 +47,39 @@
47 {{ actionButtonText }} 47 {{ actionButtonText }}
48 </nut-button> 48 </nut-button>
49 </view> 49 </view>
50 +
51 + <nut-dialog v-model:visible="showLocationConfirmDialog" title="位置权限申请">
52 + <template #default>
53 + <view class="text-gray-700 leading-loose text-sm text-left">
54 + {{ locationConfirmContent }}
55 + </view>
56 + </template>
57 + <template #footer>
58 + <nut-row :gutter="10">
59 + <nut-col :span="12">
60 + <nut-button @click="handleLocationConfirmCancel" type="default" size="normal" block>
61 + 暂不开启
62 + </nut-button>
63 + </nut-col>
64 + <nut-col :span="12">
65 + <nut-button
66 + @click="handleLocationConfirmAgree"
67 + type="primary"
68 + size="normal"
69 + color="#DF7750"
70 + block
71 + >
72 + 同意并继续
73 + </nut-button>
74 + </nut-col>
75 + </nut-row>
76 + </template>
77 + </nut-dialog>
50 </view> 78 </view>
51 </template> 79 </template>
52 80
53 <script setup> 81 <script setup>
54 -import { reactive, computed } from 'vue' 82 +import { reactive, computed, ref } from 'vue'
55 import Taro, { useLoad } from '@tarojs/taro' 83 import Taro, { useLoad } from '@tarojs/taro'
56 import './index.less' 84 import './index.less'
57 import RichTextRenderer from '@/components/RichTextRenderer.vue' 85 import RichTextRenderer from '@/components/RichTextRenderer.vue'
...@@ -99,6 +127,10 @@ const actionButtonText = computed(() => ...@@ -99,6 +127,10 @@ const actionButtonText = computed(() =>
99 detail.entryMode === 'direct_submit' ? '点击打卡' : '扫码打卡' 127 detail.entryMode === 'direct_submit' ? '点击打卡' : '扫码打卡'
100 ) 128 )
101 const isApiSuccess = code => Number(code) === 1 129 const isApiSuccess = code => Number(code) === 1
130 +const showLocationConfirmDialog = ref(false)
131 +const pendingLocationConfirmResolver = ref(null)
132 +const locationConfirmContent =
133 + '为了完成扫码打卡,我们需要获取您的位置信息,用于验证您是否在当前打卡点范围内。我们会严格保护您的位置隐私,仅用于本次扫码打卡。'
102 134
103 const normalizedRichTextContent = computed(() => { 135 const normalizedRichTextContent = computed(() => {
104 const content = detail.discountContentRaw 136 const content = detail.discountContentRaw
...@@ -195,6 +227,46 @@ const ensureOpenid = async () => { ...@@ -195,6 +227,46 @@ const ensureOpenid = async () => {
195 return openid 227 return openid
196 } 228 }
197 229
230 +const waitForLocationConfirm = async () => {
231 + if (detail.geoEnabled !== true) {
232 + return true
233 + }
234 +
235 + const authSetting = await Taro.getSetting()
236 + const hasLocationPermission = authSetting?.authSetting?.['scope.userLocation']
237 +
238 + if (hasLocationPermission === true) {
239 + return true
240 + }
241 +
242 + showLocationConfirmDialog.value = true
243 +
244 + return new Promise(resolve => {
245 + pendingLocationConfirmResolver.value = resolve
246 + })
247 +}
248 +
249 +const resolveLocationConfirm = confirmed => {
250 + showLocationConfirmDialog.value = false
251 +
252 + if (pendingLocationConfirmResolver.value) {
253 + pendingLocationConfirmResolver.value(confirmed)
254 + pendingLocationConfirmResolver.value = null
255 + }
256 +}
257 +
258 +const handleLocationConfirmCancel = () => {
259 + Taro.showToast({
260 + title: '需要位置权限才能参与活动',
261 + icon: 'none',
262 + })
263 + resolveLocationConfirm(false)
264 +}
265 +
266 +const handleLocationConfirmAgree = () => {
267 + resolveLocationConfirm(true)
268 +}
269 +
198 const handleScanCheckin = async () => { 270 const handleScanCheckin = async () => {
199 detail.scanSubmitting = true 271 detail.scanSubmitting = true
200 272
...@@ -208,6 +280,13 @@ const handleScanCheckin = async () => { ...@@ -208,6 +280,13 @@ const handleScanCheckin = async () => {
208 return 280 return
209 } 281 }
210 282
283 + const hasConfirmedLocation = await waitForLocationConfirm()
284 +
285 + if (!hasConfirmedLocation) {
286 + detail.scanSubmitting = false
287 + return
288 + }
289 +
211 // 点击扫码时重新静默拉一次当前位置,避免依赖进入页面时的旧定位缓存。 290 // 点击扫码时重新静默拉一次当前位置,避免依赖进入页面时的旧定位缓存。
212 const rangeCheck = await verifyCheckinRangeWithCurrentLocation({ 291 const rangeCheck = await verifyCheckinRangeWithCurrentLocation({
213 geoEnabled: detail.geoEnabled, 292 geoEnabled: detail.geoEnabled,
......