这段代码 ios app上面运行后 没有打印 是因为弹出来一次之后 就没发再弹出来的原因吗 怎么处理这个方法
// iOS 请求权限
requestIOSPermission() {
return new Promise((resolve) => {
// iOS 直接使用系统API请求授权
uni.authorize({
scope: this.getIOSScope(),
success: () => {
console.log(111);
this.$emit('changeAuth');
resolve(true);
},
fail: () => {
console.log(222);
this.showSettingGuide();
resolve(false);
}
});
});
},
// 获取 iOS 对应的 scope
getIOSScope() {
const mapping = {
'ACCESS_FINE_LOCATION': 'scope.userLocation',
'WRITE_EXTERNAL_STORAGE': 'scope.writePhotosAlbum',
'CAMERA': 'scope.camera',
'RECORD_AUDIO': 'scope.record',
'READ_PHONE_STATE': 'scope.notification',
'CALL_PHONE': 'scope.addressBook'
};
return mapping[this.permissionID] || '';
},
然后这是全部代码 情节和我的全部逻辑 优化完整:
<template>
<!-- 权限申请弹窗组件 -->
<view v-if="showPopup" class="uni-popup" :style="{top:isNativeHead?'':StatusBar}">
<view :class="[type, ani, animation ? 'ani' : '']" class="uni-custom uni-popup__wrapper" @click.stop="close(true)">
<view class="uni-popup__wrapper-box">
<view class="title">{{currentPermissionData.title}}</view>
<view class="content">{{currentPermissionData.content}}</view>
<!-- 操作按钮区域 -->
<view class="action-buttons">
<button class="btn cancel" @click.stop="handleLater">稍后再说</button>
<button class="btn confirm" @click.stop="handleAuthorize">立即授权</button>
</view>
</view>
</view>
</view>
</template>
<script>
// 权限信息配置 - 集中管理
const PERMISSION_DATA = {
// 'WRITE_EXTERNAL_STORAGE': {
// title: "霍小帮对存储空间/照片权限申请说明",
// content: "便于您使用该功能上传您的照片/图片/视频及用于更换头像、意见反馈、保存相册、发布商品/分享、下载与客服沟通等场景中读取和写入相册和文件内容。"
// },
// 'ACCESS_FINE_LOCATION': {
// title: "霍小帮对地理位置权限申请说明",
// content: "便于应用程序可以提供基于位置的服务、定位导航、附近搜索等功能。APP收集WIFI扫描结果的目的为提供定位服务,仅在首页获取定位的城市的时候需要使用到,只收集周围可用WIFI网络的名称和信号强度等信息,不收集WIFI密码等敏感信息!为同城配送功能会获取骑手当前位置,不储存任何隐私信息!" },
// 'CAMERA':{
// title: "霍小帮对相机/摄像头权限申请说明",
// content: "便于您使用该功能拍照上传您的照片/视频及用于更换头像、意见反馈、保存相册、发布商品/动态、下载与客服沟通等场景中使用"
// },
// 'RECORD_AUDIO':{
// title: "霍小帮对麦克风权限申请说明",
// content: "便于您使用该功能进行录音、语音通话、发布语音、与客服语音沟通等场景中使用"
// },
// 'READ_PHONE_STATE':{
// title: "霍小帮对获取设备信息申请说明",
// content: "首次或切换设备请允许此权限,便于您收到APP的系统通知或APP内平台公告/好友消息通知的场景中使用,不会泄露任何个人信息,我们只保存您的设备ID用于发送消息通知"
// },
// 'CALL_PHONE': {
// title: "霍小帮对拨打/管理电话权限申请说明",
// content: "便于您使用该功能联系买家、骑手或者客服、业务经理与联系等场景下使用"
// }
WRITE_EXTERNAL_STORAGE: {
title: "存储空间/照片权限说明",
content: "用于上传照片/图片/视频、更换头像、意见反馈、保存相册等功能",
iosPermission: "PHPhotoLibrary" // iOS 对应的权限类
},
ACCESS_FINE_LOCATION: {
title: "地理位置权限说明",
content: "用于提供定位服务、附近搜索等功能,保护您的隐私安全",
iosPermission: "CLLocationManager"
},
CAMERA: {
title: "相机/摄像头权限说明",
content: "用于拍照上传照片/视频、更换头像、发布商品等功能",
iosPermission: "AVCaptureDevice"
},
RECORD_AUDIO: {
title: "麦克风权限说明",
content: "用于语音通话、语音消息、客服沟通等功能",
iosPermission: "AVAudioSession"
},
READ_PHONE_STATE: {
title: "设备信息权限说明",
content: "用于系统通知、消息推送功能,保护您的个人信息安全",
iosPermission: "CNContactStore"
},
CALL_PHONE: {
title: "电话权限说明",
content: "用于联系买家、骑手或客服等功能",
iosPermission: "CNContactStore"
}
};
export default {
name: 'YkAuthPopup',
props: {
animation: {
type: Boolean,
default: true
},
type: {
type: String,
default: 'top'
},
show: {
type: Boolean,
default: true
},
isNativeHead: {
type: Boolean,
default: false
},
permissionID: {
type: [String, Number],
required: true
}
},
data() {
return {
ani: '',
showPopup: false,
StatusBar: '',
refuseNum: 0, // 拒绝次数
currentPermissionData: {}, // 当前权限数据
authList: PERMISSION_DATA // 权限配置映射
}
},
watch: {
permissionID: {
immediate: true,
handler(newVal) {
// 更新当前权限数据
this.currentPermissionData = this.authList[newVal] || {};
}
}
},
created() {
// #ifdef APP-PLUS
this.getSystemInfo();
// #endif
},
methods: {
// 获取状态栏高度
getSystemInfo() {
uni.getSystemInfo({
success: (e) => {
this.StatusBar = e.statusBarHeight + 'px';
}
})
},
open() {
this.showPopup = true;
this.$nextTick(() => {
setTimeout(() => {
this.ani = 'uni-' + this.type;
// 延迟后自动检查权限
setTimeout(() => {
this.checkPermissions();
}, 300);
}, 30);
});
},
close() {
this.ani = '';
this.$nextTick(() => {
setTimeout(() => {
this.showPopup = false;
}, 300);
});
},
// 稍后再说处理
handleLater() {
this.close();
this.refuseNum++;
// 如果拒绝超过3次,显示引导提示
if (this.refuseNum >= 3) {
this.$emit('permission-denied', this.permissionID);
}
},
// 立即授权处理
handleAuthorize() {
this.close();
this.requestPermissions();
},
// 统一权限检查方法
async checkPermissions() {
var _this = this
const platform = plus.os.name;
// Android 权限检查
if (platform === 'Android') {
try {
const permissionStr = 'android.permission.' + this.permissionID;
const result = await new Promise((resolve) => {
plus.android.checkPermission(permissionStr, resolve);
});
if (result?.checkResult === -1) {
// 未授权:显示弹窗(已显示)
return;
}
// 已授权,通知父组件
this.$emit('changeAuth');
} catch (error) {
console.error('权限检查失败:', error);
}
}
// iOS 权限检查
else if (platform === 'iOS') {
// try {
// const granted = await this.checkIOSPermission();
// if (granted) {
// // 已授权,通知父组件
// this.$emit('changeAuth');
// }
// } catch (error) {
// console.error('iOS权限检查失败:', error);
// }
//IOS不需要添加自定义弹框来描述权限目的,因为在配置文件的隐私信息访问的许可描述里可添加
//正常可以直接调用uni的API调起权限询问弹框使用各种权限,下面的判断使用场景主要是在IOS禁用某权限后,这个可以判断有无权限,进而引导用户跳转设置开启,仅列出了位置、相册、通讯录、相机、录音等权限,其他IOS权限可具体参考 https://ext.dcloud.net.cn/plugin?id=15787
let result = 0;
console.log(permissionID,'permissionID');
if (permissionID == 'ACCESS_FINE_LOCATION') {
//IOS检测位置权限
let cLLocationManager = plus.ios.importClass("CLLocationManager"),
authStatus = cLLocationManager.authorizationStatus(),
enable = cLLocationManager.locationServicesEnabled();
if (enable && authStatus != 2) {
result = 1;
} else {
result = 0;
}
plus.ios.deleteObject(cLLocationManager);
} else if (permissionID == 'WRITE_EXTERNAL_STORAGE') {
//IOS检测相册权限
let PHPhotoLibrary = plus.ios.importClass("PHPhotoLibrary"),
authStatus = PHPhotoLibrary.authorizationStatus();
if (authStatus === 3) {
result = 1;
} else {
result = 0;
}
plus.ios.deleteObject(PHPhotoLibrary);
} else if (permissionID == 'CAMERA') {
//IOS检测相机/摄像头权限
let avCaptureDevice = plus.ios.importClass("AVCaptureDevice"),
authStatus = avCaptureDevice.authorizationStatusForMediaType("vide");
if (authStatus === 3) {
result = 1;
} else {
result = 0;
}
plus.ios.deleteObject(avCaptureDevice);
} else if (permissionID == 'CALL_PHONE') {
//IOS检测通讯录权限
let contactStore = plus.ios.importClass("CNContactStore"),
authStatus = contactStore.authorizationStatusForEntityType(0);
// console.log(authStatus,'authStatus');
if (authStatus === 3) {
result = 1;
} else {
result = 0;
}
plus.ios.deleteObject(contactStore);
}else if(permissionID == 'RECORD_AUDIO'){
//IOS检测麦克风权限
let aVAudioSession = plus.ios.importClass("AVAudioSession"),
aVAudio = aVAudioSession.sharedInstance(),
authStatus = aVAudio.recordPermission();
if ([1684369017, 1970168948].includes(authStatus)) {
result = 0;
} else {
result = 1;
}
plus.ios.deleteObject(aVAudioSession);
}
if (result) {
//当前查询权限已授权,此时可以通知页面执行接下来的操作
_this.$emit('changeAuth')
} else {
//当前查询的权限已禁用,引导用户跳转手机系统设置去开启
if(permissionID == 'READ_PHONE_STATE'){
}else{
console.log(this.currentPermissionData,'this.currentPermissionData');
this.$util.showModal({
title: '温馨提示【'+permissionID+'】',
content: '请再设置打开此权限,更好使用此页面功能~',//是否立刻前往?'
// cancelText: "取消",
confirmText: "我知道了",
showCancel: true,
confirmColor: '#000',
cancelColor: '#666',
success: (res) => {
if (res.confirm) {
// _this.goSetting();
}
}
})
}
}
}
},
// 修复后的 iOS 权限检查方法
async checkIOSPermission() {
try {
// 特殊处理不需要权限检查的情况
if (this.permissionID === 'READ_PHONE_STATE') {
// iOS 设备信息不需要额外权限
return true;
}
// 获取对应的权限类名
const permissionClass = this.currentPermissionData?.iosPermission;
if (!permissionClass) {
console.error(`未配置权限类: ${this.permissionID}`);
return false;
}
// 安全导入 iOS 类
let manager;
try {
manager = plus.ios.importClass(permissionClass);
if (!manager) {
console.warn(`无法导入iOS类: ${permissionClass}`);
return false;
}
} catch (importError) {
console.error(`导入iOS类失败: ${permissionClass}`, importError);
return false;
}
// 统一权限状态检查
let granted = false;
switch (this.permissionID) {
case 'ACCESS_FINE_LOCATION':
// 位置权限检查
const authStatus = manager.authorizationStatus?.();
const enabled = manager.locationServicesEnabled?.();
granted = !!enabled && authStatus !== 2;
break;
case 'WRITE_EXTERNAL_STORAGE':
// 存储权限检查
granted = manager.authorizationStatus?.() === 3;
break;
case 'CAMERA':
// 相机权限检查
granted = manager.authorizationStatusForMediaType?.("vide") === 3;
break;
case 'CALL_PHONE':
case 'READ_PHONE_STATE':
// 电话权限检查
// iOS 14+ 需要使用 CNContactStore 检查通讯录权限
const authStatusPhone = manager.authorizationStatusForEntityType?.(0);
granted = authStatusPhone === 3;
break;
case 'RECORD_AUDIO':
// 麦克风权限检查
const session = manager.sharedInstance?.();
const status = session?.recordPermission?.();
// 使用更安全的状态检查方式
const deniedStatuses = [1684369017, 1970168948];
granted = !deniedStatuses.includes(status);
break;
default:
console.warn(`未处理的权限类型: ${this.permissionID}`);
granted = false;
}
return granted;
} catch (error) {
console.error(`iOS权限检查失败: ${this.permissionID}`, error);
return false;
} finally {
// 确保释放原生对象
if (manager) {
try {
plus.ios.deleteObject(manager);
} catch (deleteError) {
console.warn(`释放iOS对象失败:`, deleteError);
}
}
}
},
// 请求权限的统一方法
async requestPermissions() {
const platform = plus.os.name;
if (platform === 'Android') {
await this.requestAndroidPermission();
} else if (platform === 'iOS') {
await this.requestIOSPermission();
}
},
// Android 请求权限
requestAndroidPermission() {
return new Promise((resolve) => {
const permissionStr = 'android.permission.' + this.permissionID;
plus.android.requestPermissions([permissionStr], (e) => {
if (e.granted.length > 0) {
this.$emit('changeAuth');
} else if (e.deniedAlways.length > 0) {
this.showSettingGuide();
}
resolve();
});
});
},
// iOS 请求权限
requestIOSPermission() {
return new Promise((resolve) => {
// iOS 直接使用系统API请求授权
uni.authorize({
scope: this.getIOSScope(),
success: () => {
console.log(111);
this.$emit('changeAuth');
resolve(true);
},
fail: () => {
console.log(222);
this.showSettingGuide();
resolve(false);
}
});
});
},
// 获取 iOS 对应的 scope
getIOSScope() {
const mapping = {
'ACCESS_FINE_LOCATION': 'scope.userLocation',
'WRITE_EXTERNAL_STORAGE': 'scope.writePhotosAlbum',
'CAMERA': 'scope.camera',
'RECORD_AUDIO': 'scope.record',
'READ_PHONE_STATE': 'scope.notification',
'CALL_PHONE': 'scope.addressBook'
};
return mapping[this.permissionID] || '';
},
// 显示设置引导
showSettingGuide() {
this.$util.showModal({
title: '温馨提示',
content: '请前往系统设置开启权限,以获得完整功能体验',
cancelText: "取消",
confirmText: "前往设置",
showCancel: true,
confirmColor: '#000',
cancelColor: '#666',
success: (res) => {
if (res.confirm) {
this.goSetting();
}
}
});
},
// 跳转系统设置
goSetting() {
// Android
if (plus.os.name === "Android") {
const Intent = plus.android.importClass("android.content.Intent");
const Settings = plus.android.importClass("android.provider.Settings");
const Uri = plus.android.importClass("android.net.Uri");
const mainActivity = plus.android.runtimeMainActivity();
const intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
const uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
intent.setData(uri);
mainActivity.startActivity(intent);
}
// iOS
else {
const UIApplication = plus.ios.import("UIApplication");
const application = UIApplication.sharedApplication();
const NSURL = plus.ios.import("NSURL");
try {
// 优先使用官方设置URL
const settingsURL = NSURL.URLWithString(UIApplicationOpenSettingsURLString);
if (application.canOpenURL(settingsURL)) {
const iosVersion = parseFloat(plus.os.version);
if (iosVersion >= 10.0) {
application.openURLOptionsCompletionHandler(settingsURL, {}, null);
} else {
application.openURL(settingsURL);
}
return;
}
} catch (e) {
console.warn("使用官方设置URL失败,尝试备选方案");
}
// 备选方案
const settingsURL = NSURL.URLWithString("app-settings:");
application.openURL(settingsURL);
}
}
}
}
</script>
<style lang="scss">
.uni-popup {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 99999;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: flex-start;
justify-content: center;
&__wrapper {
position: relative;
margin-top: 100rpx;
&.ani {
transition: all 0.3s ease-out;
}
&.top {
animation: slideDown 0.3s forwards;
}
&-box {
width: 650rpx;
background: #fff;
border-radius: 20rpx;
overflow: hidden;
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.15);
.title {
padding: 30rpx 30rpx 10rpx;
font-size: 34rpx;
font-weight: bold;
color: #333;
text-align: center;
}
.content {
padding: 20rpx 40rpx;
font-size: 28rpx;
color: #666;
line-height: 1.6;
text-align: center;
}
}
}
}
.action-buttons {
display: flex;
border-top: 1rpx solid #eee;
margin-top: 20rpx;
.btn {
flex: 1;
height: 90rpx;
line-height: 90rpx;
font-size: 32rpx;
border-radius: 0;
background: none;
position: relative;
margin: 0;
&::after {
border: none;
}
&.cancel {
color: #999;
border-right: 1rpx solid #eee;
}
&.confirm {
color: #007AFF;
font-weight: 500;
}
}
}
@keyframes slideDown {
from {
transform: translateY(-100px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
</style>
最新发布