业务场景
uni-app中需要使用扫码的功能
遇到的问题
1.camera自动调用授权功能,弹出授权框,但第一次拒绝后,再次打开该页面,自动默认为拒绝授权,但实际上需要手动提醒用户进行授权
2.扫码过程中,扫码成功事件触发多次,会出现扫一次码支付出现多笔消费记录的情况,所以需要手动拦截
具体实现代码
<template>
<view class="out">
<nav-bar :type="3" title="扫码核销"></nav-bar>
<camera v-if="isShow" device-position="back" mode="scanCode" @scancode="scan" @error="error" class="camera">
<view class="line"></view>
</camera>
<view class="bottom">
<view class="tip">将二维码/条形码放入框内,即可自动扫描</view>
<view class="text">收款</view>
<view class="num">¥{{ account }}</view>
</view>
</view>
</template>
<script setup>
import {
ref,
onMounted
} from 'vue'
import {
scanbiz
} from '../../apis/scancode'
import navBar from '@/components/navBar.vue'
const account = ref()
const userInfo = {}
let flag = false
const isShow = ref(false)
const scan = async (e) => {
//成功后将flag置为true防止多次扫码
if (flag) {
return;
}
flag = true
if (e) {
if (!e.target.result) {
uni.showModal({
content: '二维码无效',
showCancel: false
});
flag = false
return
}
try {
//e 扫码的结果
//该处进行接口调用等操作
} catch (e) {
//失败后能再次扫码
flag = false
}
}
}
const error = (e) => {
if (e) {
uni.showModal({
content: '授权扫码失败',
showCancel: false
});
}
}
onMounted(() => {
//需要获得现在的授权信息
uni.getSetting({
success(res){
//如果相机访问权限没有授权
if (!res.authSetting['scope.camera']) {
//访问授权
uni.authorize({
scope: 'scope.camera',
success(){
uni.showToast({
title:'授权成功',
})
isShow.value = true
},
//拒绝后第二次访问授权默认进入fail,询问用户“检测到您没打开获取相机功能权限,是否去设置打开”
fail(){
uni.showModal({
content: '检测到您没打开获取相机功能权限,是否去设置打开?',
confirmText: "确认",
cancelText: '取消',
success: (res)=>{
if (res.confirm) {
//打开设置页面,让用户授权
uni.openSetting({
success: ()=>{
uni.showModal({
title: '授权后请重新打开此页面',
icon: 'none',
success: function(){
// 刷新
uni.redirectTo({
url: '/pages/scancode/setAccount',
});
}
})
}
})
}
}
})
}
})
}else{
isShow.value = true
}
}
})
})
</script>
<style lang="scss" scoped>
.out {
position: relative;
z-index: 0;
height: 100vh;
background-color: #343434;
padding-top: 32rpx;
.camera {
position: absolute;
top: calc(40% - 240rpx);
left: calc(50% - 240rpx);
width: 480rpx;
height: 480rpx;
border: 2px solid #fff;
.line {
position: absolute;
top: 32rpx;
left: 14rpx;
width: 452rpx;
height: 6rpx;
background: linear-gradient(225deg, rgba(102, 102, 102, 0.00), #666666 49%, rgba(102, 102, 102, 0.00) 99%);
border-radius: 50%;
}
}
.bottom {
position: absolute;
top: calc(40% + 288rpx);
left: calc(50% - 278rpx);
display: flex;
flex-direction: column;
align-items: center;
.tip {
font-size: 30rpx;
font-weight: 400;
color: #cccccc;
line-height: 42rpx;
}
.text {
font-size: 30rpx;
font-weight: 400;
color: #ffffff;
line-height: 42rpx;
margin-top: 65rpx;
}
.num {
font-size: 80rpx;
font-weight: 500;
color: #ffffff;
line-height: 112rpx;
}
}
}
</style>