mrr.sj.front/utils/per.js

309 lines
8.5 KiB
JavaScript
Raw Normal View History

2026-03-24 11:45:13 +08:00
// permissionUtils.js
/**
* 统一权限检测工具
* 支持平台APP(Android/iOS)微信小程序H5
*/
export default {
/**
* 检查权限状态
* @param {String} permission 权限类型
* @param {String} description 权限描述(仅APP端需要)
* @returns {Promise<Object>}
* - granted: 是否已授权
* - firstRequest: 是否第一次请求
* - canRequest: 是否可以请求(用户未永久拒绝)
*/
async checkPermission(permission, description = '') {
// #ifdef APP-PLUS
return await this._checkAppPermission(permission, description);
// #endif
// #ifdef MP-WEIXIN
return await this._checkMpPermission(permission);
// #endif
// #ifdef H5
// H5默认返回已授权实际权限由浏览器控制
return { granted: true, firstRequest: false, canRequest: false };
// #endif
},
/**
* APP端权限检查
*/
async _checkAppPermission(permission, description) {
// Android和iOS通用权限映射
const permissionMap = {
'camera': {
android: 'android.permission.CAMERA',
ios: 'camera'
},
'location': {
android: 'android.permission.ACCESS_FINE_LOCATION',
ios: 'location'
},
'phone': {
android: 'android.permission.CALL_PHONE',
ios: 'phone'
},
'photo_library': {
android: [
'android.permission.READ_EXTERNAL_STORAGE',
'android.permission.WRITE_EXTERNAL_STORAGE'
],
ios: 'photo_library',
}
// 添加其他需要的权限...
};
const platformPerm = permissionMap[permission];
if (!platformPerm) {
console.error('不支持的权限类型:', permission);
return { granted: false, firstRequest: false, canRequest: false };
}
// #ifdef APP-PLUS
if (plus.os.name === 'Android') {
return this._checkAndroidPermission(platformPerm.android);
}else {
return this._checkIosPermission(platformPerm.ios, description);
}
// #endif
return { granted: false, firstRequest: false, canRequest: false };
},
/**
* Android权限检查
*/
async _checkAndroidPermission(permission) {
return new Promise((resolve) => {
plus.android.requestPermissions(
Array.isArray(permission) ? permission : [permission],
(e) => {
console.log(`perm_${permission}`,e)
// 第一次请求标记
const firstRequest = !plus.storage.getItem(`perm_${permission}`);
if (firstRequest) {
plus.storage.setItem(`perm_${permission}`, '1');
}
if(e.deniedPresent.length !== 0) {
plus.storage.setItem(`perm_${permission}_no`, '2');
}
if(e.granted.length !== 0) {
plus.storage.removeItem(`perm_${permission}_no`, '2');
}
resolve({
granted: e.granted.length !== 0,
firstRequest,
canRequest: true // Android可以重复请求
});
},
(e) => {
resolve({
granted: false,
firstRequest: false,
canRequest: true
});
}
);
});
},
/**
* iOS权限检查
*/
async _checkIosPermission(permission, description) {
try {
let status;
switch (permission) {
case 'camera':
status = plus.ios.invoke('AVCaptureDevice', 'authorizationStatusForMediaType:', 'vide');
break;
case 'location':
const locationManager = plus.ios.newObject('CLLocationManager');
status = plus.ios.invoke(locationManager, 'authorizationStatus');
plus.ios.deleteObject(locationManager);
break;
// 其他权限处理...
default:
return { granted: false, firstRequest: false, canRequest: false };
}
// iOS授权状态
// 0: 未决定(第一次)
// 1: 受限
// 2: 已拒绝
// 3: 已授权
return {
granted: status === 3,
firstRequest: status === 0,
canRequest: status !== 2 // 不是永久拒绝
};
} catch (e) {
console.error('iOS权限检查错误:', e);
return { granted: false, firstRequest: false, canRequest: false };
}
},
/**
* 小程序权限检查
*/
async _checkMpPermission(permission) {
// 小程序scope映射
const scopeMap = {
'camera': 'scope.camera',
'location': 'scope.userLocation',
'record': 'scope.record',
// 其他小程序权限...
};
const scope = scopeMap[permission];
if (!scope) {
return { granted: false, firstRequest: false, canRequest: false };
}
return new Promise((resolve) => {
uni.getSetting({
success(res) {
const authSetting = res.authSetting;
resolve({
granted: authSetting[scope] === true,
firstRequest: authSetting[scope] === undefined,
canRequest: authSetting[scope] !== false // 不是拒绝状态
});
},
fail() {
resolve({ granted: false, firstRequest: false, canRequest: false });
}
});
});
},
/**
* 请求权限
*/
async requestPermission(permission, description = '') {
const { granted, firstRequest, canRequest } = await this.checkPermission(permission, description);
if (granted) return true;
if (!canRequest) return false;
// #ifdef APP-PLUS
return this._requestAppPermission(permission, description);
// #endif
// #ifdef MP-WEIXIN
return this._requestMpPermission(permission);
// #endif
// #ifdef H5
return false; // H5无法主动请求权限
// #endif
},
/**
* APP端请求权限
*/
async _requestAppPermission(permission, description) {
// #ifdef APP-PLUS && ANDROID
return new Promise((resolve) => {
plus.android.requestPermissions(
[permission],
(e) => resolve(e.denied.length === 0),
() => resolve(false)
);
});
// #endif
// #ifdef APP-PLUS && IOS
return new Promise((resolve) => {
switch (permission) {
case 'camera':
plus.ios.invoke('AVCaptureDevice', 'requestAccessForMediaType:completionHandler:', 'vide', (granted) => {
resolve(granted);
});
break;
case 'location':
const locationManager = plus.ios.newObject('CLLocationManager');
plus.ios.invoke(locationManager, 'requestWhenInUseAuthorization');
// iOS定位权限需要监听变化
setTimeout(() => {
const status = plus.ios.invoke(locationManager, 'authorizationStatus');
plus.ios.deleteObject(locationManager);
resolve(status === 3 || status === 4);
}, 300);
break;
default:
resolve(false);
}
});
// #endif
return false;
},
/**
* 小程序请求权限
*/
async _requestMpPermission(permission) {
const scopeMap = {
'camera': 'scope.camera',
'location': 'scope.userLocation',
'record': 'scope.record',
};
const scope = scopeMap[permission];
if (!scope) return false;
return new Promise((resolve) => {
uni.authorize({
scope,
success: () => resolve(true),
fail: () => resolve(false)
});
});
},
/**
* 打开系统设置页
*/
openSystemSettings() {
// #ifdef APP-PLUS
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);
} else {
const UIApplication = plus.ios.import('UIApplication');
const NSURL = plus.ios.import('NSURL');
const url = NSURL.URLWithString('app-settings:');
const application = UIApplication.sharedApplication();
if (plus.ios.invoke(application, 'canOpenURL:', url)) {
plus.ios.invoke(application, 'openURL:', url);
}
plus.ios.deleteObject(url);
plus.ios.deleteObject(application);
}
// #endif
// #ifdef MP-WEIXIN
uni.openSetting();
// #endif
// #ifdef H5
console.log('H5无法打开系统设置');
// #endif
}
};