408249787@qq.com пре 5 дана
родитељ
комит
c91ded32f4

+ 9 - 47
pages/catalog/detail.uvue

@@ -4,13 +4,6 @@ import Loading from '@/components/loading.uvue'
 import { ref, onMounted, watch, nextTick, onUnmounted } from 'vue'
 import { type SubjectCourseResult, fetchSubjectCourseApp, updateSubjectProgress, queryNextSubjectCourse } from '@/services/subject/course'
 import { router, user } from '@/.cool'
-import {
-  checkPermission,
-  requestPermissions,
-} from '@/uni_modules/m-permission-manager'
-import { useUi } from "@/uni_modules/cool-ui";
-
-const ui = useUi();
 const isLoading = ref(true)
 const showControls = ref(true)
 const showVideo = ref(true)
@@ -216,46 +209,15 @@ function handleTop() {
   progress2.value = 5
 }
 function startRecord() {
-  checkPermission({
-    permission: 'microphone',
-    success(res) {
-      console.log('microphone', res)
-      if (res.granted == true) {
-        console.log('开始录音');
-        timer.value = setInterval(function () {
-          timers.value--
-          if (timers.value <= 0) {
-            endRecord()
-          }
-        }, 1000)
-        recorderManager.value?.start({});
-      } else {
-        ui.showConfirm({
-          title: "获取麦克风权限",
-          message: "本应用仅在你主动触发录音操作时调用麦克风,仅用于临时实时录音,录音内容仅在当前页面本地播放,供你本人收听。你可随时在系统设置中关闭麦克风权限,关闭后将无法使用录音功能,不影响应用其他功能正常使用",
-          callback(action) {
-            if (action === "confirm") {
-              requestPermissions({
-                permissions: ['microphone'],
-                success(res) {
-                  console.log('microphone', res)
-                },
-                fail(err) {
-                  console.error(err.errCode, err.errMsg)
-                },
-              })
-              // 执行删除操作
-            } else {
-              console.log("用户取消操作");
-            }
-          },
-        });
-      }
-    },
-    fail(err) {
-      console.error(err.errCode, err.errMsg)
-    },
-  })
+  console.log('开始录音');
+  timer.value = setInterval(() => {
+    timers.value--
+    console.log(timers.value);
+    if (timers.value <= 0) {
+      endRecord()
+    }
+  }, 800)
+  recorderManager.value.start();
 }
 function endRecord() {
   clearInterval(timer.value)

+ 0 - 20
uni_modules/m-permission-manager/changelog.md

@@ -1,20 +0,0 @@
-## 1.0.3(2026-06-17)
-添加使用说明
-# 更新日志
-
-## 1.0.2(2026-06-17)
-- 修复 Android:相册/存储/蓝牙申请失败(`targetSdkVersion` 与 `READ_MEDIA_*` / `BLUETOOTH_*` 不匹配)
-- 权限映射同时校验设备 API 与宿主 `targetSdkVersion`,自定义基座 targetSdk < 33 时回退旧版权限
-## 1.0.1(2026-06-17)
-
-- 新增 `openPermissionSettings(permission)` 按权限类型跳转系统设置
-- 新增 `getPermissionSettingsGuide(permission, label)` 引导文案
-- Android:`overlay` / `writeSettings` 跳转对应系统设置页
-- 新增《发布指南.md》《使用规范.md》《权限配置说明.md》
-- readme 补充 iOS 蓝牙说明与 `NSBluetoothAlwaysUsageDescription`
-
-## 1.0.0(2026-05-29)
-
-- 初始版本
-- 支持 Android / iOS / Harmony 三端统一权限检查与申请
-- 提供同步 / 异步 API 及 `@/utils/permission-manager` Promise 封装

+ 0 - 113
uni_modules/m-permission-manager/index.d.ts

@@ -1,113 +0,0 @@
-/**
- * m-permission-manager UTS 插件 TypeScript 类型声明
- */
-
-export type PermissionKey =
-	| 'camera'
-	| 'photoLibrary'
-	| 'storage'
-	| 'readStorage'
-	| 'location'
-	| 'coarseLocation'
-	| 'microphone'
-	| 'contacts'
-	| 'writeContacts'
-	| 'bluetooth'
-	| 'phone'
-	| 'phoneState'
-	| 'sms'
-	| 'readSms'
-	| 'receiveSms'
-	| 'overlay'
-	| 'writeSettings'
-
-export type PermissionStatus =
-	| 'granted'
-	| 'denied'
-	| 'notDetermined'
-	| 'restricted'
-	| 'unsupported'
-
-export interface PermissionCheckResult {
-	permission: PermissionKey
-	status: PermissionStatus
-	granted: boolean
-}
-
-export interface PermissionGrantResult {
-	permission: PermissionKey
-	status: PermissionStatus
-	granted: boolean
-}
-
-export interface CheckPermissionsResult {
-	results: PermissionCheckResult[]
-	allGranted: boolean
-}
-
-export interface RequestPermissionsResult {
-	results: PermissionGrantResult[]
-	allGranted: boolean
-}
-
-export interface PermissionFail {
-	errCode: 9020001 | 9020002 | 9020003 | 9020004 | 9020005 | 9020006
-	errMsg: string
-}
-
-export interface CheckPermissionOptions {
-	permission: PermissionKey
-	success?: (res: PermissionCheckResult) => void
-	fail?: (res: PermissionFail) => void
-	complete?: (res: unknown) => void
-}
-
-export interface CheckPermissionsOptions {
-	permissions: PermissionKey[]
-	success?: (res: CheckPermissionsResult) => void
-	fail?: (res: PermissionFail) => void
-	complete?: (res: unknown) => void
-}
-
-export interface RequestPermissionOptions {
-	permission: PermissionKey
-	success?: (res: PermissionGrantResult) => void
-	fail?: (res: PermissionFail) => void
-	complete?: (res: unknown) => void
-}
-
-export interface RequestPermissionsOptions {
-	permissions: PermissionKey[]
-	success?: (res: RequestPermissionsResult) => void
-	fail?: (res: PermissionFail) => void
-	complete?: (res: unknown) => void
-}
-
-export interface OpenAppSettingsOptions {
-	/** 指定权限类型,各端将尽量跳转到对应设置页 */
-	permission?: PermissionKey
-	success?: (res: PermissionCheckResult) => void
-	fail?: (res: PermissionFail) => void
-	complete?: (res: unknown) => void
-}
-
-export interface GetSupportedPermissionsResult {
-	permissions: PermissionKey[]
-}
-
-export interface BluetoothDemoInfo {
-	available: boolean
-	enabled: boolean
-	stateText: string
-	stateCode: number
-}
-
-export function checkPermissionSync(permission: PermissionKey): PermissionCheckResult
-export function checkPermissionsSync(permissions: PermissionKey[]): CheckPermissionsResult
-export function checkPermission(options: CheckPermissionOptions): void
-export function checkPermissions(options: CheckPermissionsOptions): void
-export function requestPermission(options: RequestPermissionOptions): void
-export function requestPermissions(options: RequestPermissionsOptions): void
-export function openAppSettings(options?: OpenAppSettingsOptions): void
-export function getSupportedPermissionsSync(): GetSupportedPermissionsResult
-export function getBluetoothDemoInfoSync(): BluetoothDemoInfo

+ 0 - 44
uni_modules/m-permission-manager/index.ts

@@ -1,44 +0,0 @@
-/**
- * App 端编译时模块入口为 uts-proxy,Promise 封装请从 @/utils/permission-manager 引入。
- */
-// #ifdef APP-ANDROID
-export {
-	checkPermissionSync,
-	checkPermissionsSync,
-	checkPermission,
-	checkPermissions,
-	requestPermission,
-	requestPermissions,
-	openAppSettings,
-	getSupportedPermissionsSync,
-	getBluetoothDemoInfoSync,
-} from './utssdk/app-android/index.uts'
-// #endif
-
-// #ifdef APP-IOS
-export {
-	checkPermissionSync,
-	checkPermissionsSync,
-	checkPermission,
-	checkPermissions,
-	requestPermission,
-	requestPermissions,
-	openAppSettings,
-	getSupportedPermissionsSync,
-	getBluetoothDemoInfoSync,
-} from './utssdk/app-ios/index.uts'
-// #endif
-
-// #ifdef APP-HARMONY
-export {
-	checkPermissionSync,
-	checkPermissionsSync,
-	checkPermission,
-	checkPermissions,
-	requestPermission,
-	requestPermissions,
-	openAppSettings,
-	getSupportedPermissionsSync,
-	getBluetoothDemoInfoSync,
-} from './utssdk/app-harmony/index.uts'
-// #endif

+ 0 - 110
uni_modules/m-permission-manager/package.json

@@ -1,110 +0,0 @@
-{
-	"id": "m-permission-manager",
-	"displayName": "m-permission-manager 跨端权限管理",
-	"version": "1.0.3",
-	"description": "uni-app Vue3 跨端权限管理 UTS 插件,支持 Android / iOS / Harmony,统一 API 检查与申请运行时权限",
-	"keywords": [
-        "权限",
-        "permission",
-        "m-permission-manager",
-        "UTS"
-    ],
-	"repository": "",
-	"engines": {
-		"HBuilderX": "^4.24.0",
-		"uni-app": "^4.0",
-		"uni-app-x": "^4.0"
-	},
-	"dcloudext": {
-		"type": "uts",
-		"sale": {
-			"regular": {
-				"price": "0.00"
-			},
-			"sourcecode": {
-				"price": "0.00"
-			}
-		},
-		"contact": {
-			"qq": ""
-		},
-		"declaration": {
-			"ads": "无",
-			"data": "不上传任何用户数据,仅在本地检查与申请系统权限",
-			"permissions": "Android:宿主 manifest 声明对应 android.permission.*;iOS:宿主 manifest 声明 NSCameraUsageDescription 等 Info.plist 键;Harmony:插件 module.json5 声明 ohos.permission.*,运行时申请"
-		},
-		"npmurl": "",
-		"darkmode": "x",
-		"i18n": "x",
-		"widescreen": "x"
-	},
-	"uni_modules": {
-		"dependencies": [],
-		"encrypt": [],
-		"platforms": {
-			"cloud": {
-				"tcb": "x",
-				"aliyun": "x",
-				"alipay": "x"
-			},
-			"client": {
-				"uni-app": {
-					"vue": {
-						"vue2": "-",
-                        "vue3": "√"
-					},
-					"web": {
-						"safari": "x",
-						"chrome": "x"
-					},
-					"app": {
-						"vue": "-",
-						"nvue": "-",
-						"android": "-",
-						"ios": "-",
-						"harmony": "-"
-					},
-					"mp": {
-						"weixin": "x",
-						"alipay": "x",
-						"toutiao": "x",
-						"baidu": "x",
-						"kuaishou": "x",
-						"jd": "x",
-						"harmony": "x",
-						"qq": "x",
-						"lark": "x",
-						"xhs": "x"
-					},
-					"quickapp": {
-						"huawei": "x",
-						"union": "x"
-					}
-				},
-				"uni-app-x": {
-					"web": {
-						"safari": "x",
-						"chrome": "x"
-					},
-					"app": {
-						"android": {
-							"extVersion": "",
-							"minVersion": "23"
-						},
-						"ios": {
-							"extVersion": "",
-							"minVersion": "14"
-						},
-						"harmony": {
-							"extVersion": "",
-							"minVersion": "12"
-						}
-					},
-					"mp": {
-						"weixin": "x"
-					}
-				}
-			}
-		}
-	}
-}

+ 0 - 971
uni_modules/m-permission-manager/readme.md

@@ -1,971 +0,0 @@
-# m-permission-manager
-
-uni-app Vue3 跨端权限管理 UTS 插件,支持 **Android / iOS / Harmony** 三端,提供统一的权限检查与申请 API。
-
-## 功能
-
-- 统一权限标识,三端通用
-- 同步 / 异步检查权限状态
-- 单个 / 批量申请权限
-- 跳转系统应用设置页
-- 获取当前平台支持的权限列表
-
-## 安装
-
-插件位于 `src/uni_modules/m-permission-manager/`,随项目直接使用,无需额外安装。
-
-## 文档
-
-> 插件市场仅展示本 readme,下方链接为文内锚点,可直接跳转。
-
-| 文档 | 说明 |
-| --- | --- |
-| [使用规范](#使用规范) | 集成约束、推荐流程、审核注意事项 |
-| [权限配置说明](#权限配置说明) | Android / iOS / Harmony 三端权限文件配置详解 |
-| [发布指南](#发布指南) | DCloud 插件市场发布填写参考(插件作者) |
-| [更新日志](#更新日志) | 版本更新记录 |
-
-## 快速开始
-
-### 方式一:Promise 封装(推荐)
-
-```js
-import {
-  checkPermission,
-  requestPermission,
-  requestPermissions,
-  openAppSettings,
-  getSupportedPermissions,
-} from '@/utils/permission-manager'
-
-// 检查相机权限
-const result = await checkPermission('camera')
-console.log(result.granted, result.status)
-
-// 申请相机权限
-const granted = await requestPermission('camera')
-if (!granted) {
-  await openAppSettings()
-}
-
-// 批量申请
-const batch = await requestPermissions(['camera', 'microphone', 'location'])
-console.log(batch.allGranted, batch.results)
-```
-
-### 方式二:直接调用 UTS API(callback 风格)
-
-```js
-import { requestPermission } from '@/uni_modules/m-permission-manager'
-
-requestPermission({
-  permission: 'camera',
-  success(res) {
-    console.log(res.granted)
-  },
-  fail(err) {
-    console.error(err.errCode, err.errMsg)
-  },
-})
-```
-
-## 统一权限标识
-
-| 权限 Key | 说明 | Android | iOS | Harmony |
-| --- | --- | --- | --- | --- |
-| `camera` | 相机 | ✅ | ✅ | ✅ |
-| `photoLibrary` | 相册 | ✅ | ✅ | ✅ |
-| `storage` | 存储(写) | ✅ | ✅* | ✅ |
-| `readStorage` | 存储(读) | ✅ | ✅* | ✅ |
-| `location` | 精确定位 | ✅ | ✅ | ✅ |
-| `coarseLocation` | 大致定位 | ✅ | ✅* | ✅ |
-| `microphone` | 麦克风 | ✅ | ✅ | ✅ |
-| `contacts` | 通讯录(读) | ✅ | ✅ | ✅ |
-| `writeContacts` | 通讯录(写) | ✅ | ✅* | ✅ |
-| `bluetooth` | 蓝牙 | ✅ | ✅ | ✅ |
-| `phone` | 拨打电话 | ✅ | ❌ | ❌ |
-| `phoneState` | 电话状态 | ✅ | ❌ | ❌ |
-| `sms` | 发送短信 | ✅ | ❌ | ❌ |
-| `readSms` | 读取短信 | ✅ | ❌ | ❌ |
-| `receiveSms` | 接收短信 | ✅ | ❌ | ❌ |
-| `overlay` | 悬浮窗 | ✅ | ❌ | ❌ |
-| `writeSettings` | 系统设置 | ✅ | ❌ | ❌ |
-
-> *iOS 部分权限映射到相近的系统权限(如 storage → 相册)
-
-## 权限状态
-
-| status | 说明 |
-| --- | --- |
-| `granted` | 已授权 |
-| `denied` | 已拒绝 |
-| `notDetermined` | 尚未请求 |
-| `restricted` | 受限制(如家长控制) |
-| `unsupported` | 当前平台不支持 |
-
-## API
-
-| 方法 | 说明 |
-| --- | --- |
-| `checkPermissionSync(key)` | 同步检查单个权限 |
-| `checkPermissionsSync(keys[])` | 同步检查多个权限 |
-| `checkPermission(options)` | 异步检查单个权限 |
-| `checkPermissions(options)` | 异步检查多个权限 |
-| `requestPermission(options)` | 申请单个权限 |
-| `requestPermissions(options)` | 申请多个权限 |
-| `openAppSettings(options?)` | 打开系统应用设置 |
-| `openPermissionSettings(key)` | 按权限类型打开对应设置页(封装层) |
-| `getSupportedPermissionsSync()` | 获取当前平台支持的权限列表 |
-
-## 宿主配置
-
-> 完整配置说明见 [权限配置说明](#权限配置说明)。
-
-### Android
-
-在 `manifest.json` → `app-plus.distribute.android.permissions` 中声明所需权限,例如:
-
-```json
-"permissions": [
-  "<uses-permission android:name=\"android.permission.CAMERA\"/>",
-  "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
-  "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>"
-]
-```
-
-Android 13+ 读写媒体文件需使用 `READ_MEDIA_IMAGES` / `READ_MEDIA_VIDEO`;插件会同时校验**设备 API** 与宿主 **targetSdkVersion**,仅当 `targetSdkVersion >= 33` 时才申请新媒体权限,否则回退 `READ_EXTERNAL_STORAGE`(兼容未升级 targetSdk 的自定义基座)。
-
-### iOS
-
-在 `manifest.json` → `app-plus.distribute.ios.privacyDescription` 中配置权限说明,例如:
-
-```json
-"privacyDescription": {
-  "NSCameraUsageDescription": "需要使用相机进行拍照",
-  "NSMicrophoneUsageDescription": "需要使用麦克风进行录音",
-  "NSPhotoLibraryUsageDescription": "需要访问相册以选择图片",
-  "NSLocationWhenInUseUsageDescription": "需要获取位置信息",
-  "NSBluetoothAlwaysUsageDescription": "需要使用蓝牙连接周边设备"
-}
-```
-
-> **iOS 蓝牙说明**:蓝牙授权开关出现在「设置 → 本 App → 蓝牙」(需声明 `NSBluetoothAlwaysUsageDescription` 且 App 曾触发过蓝牙权限弹窗)。若 App 设置页无该项,请前往「设置 → 隐私与安全性 → 蓝牙」。系统蓝牙开关在「设置 → 蓝牙」,与应用授权无关。Apple 不提供跳转到「隐私 → 蓝牙」的公开深链,插件会打开 App 设置页并配合引导文案。
-
-### Harmony
-
-插件 `utssdk/app-harmony/module.json5` 已声明鸿蒙端**全部可映射**的 9 项权限:
-
-| 权限 Key | ohos.permission | APL 等级 | 说明 |
-| --- | --- | --- | --- |
-| `camera` | CAMERA | normal | 可直接安装使用 |
-| `microphone` | MICROPHONE | normal | 可直接安装使用 |
-| `location` | LOCATION | normal | 可直接安装使用 |
-| `coarseLocation` | APPROXIMATELY_LOCATION | normal | 可直接安装使用 |
-| `bluetooth` | ACCESS_BLUETOOTH | normal | 可直接安装使用 |
-| `photoLibrary` / `readStorage` | READ_IMAGEVIDEO | system_basic | 需 ACL 签名 |
-| `storage` | WRITE_IMAGEVIDEO | system_basic | 需 ACL 签名 |
-| `contacts` | READ_CONTACTS | system_basic | 需 ACL 签名 |
-| `writeContacts` | WRITE_CONTACTS | system_basic | 需 ACL 签名 |
-
-鸿蒙**不支持**(无系统 API):`phone`、`phoneState`、`sms`、`readSms`、`receiveSms`、`overlay`、`writeSettings`。
-
-#### 配置文件说明
-
-| 文件 | 权限数量 | 用途 |
-| --- | --- | --- |
-| `module.json5` | 5 项(normal) | **默认**,调试证书可直接安装 |
-| `module.normal.json5` | 5 项 | 与 `module.json5` 相同 |
-| `module.full.json5` | 9 项 | 含相册/通讯录等 system_basic 权限,需 ACL 后启用 |
-
-启用完整权限:将 `module.full.json5` 的内容覆盖 `module.json5`,并在 AppGallery Connect 配置 ACL 签名。
-
-#### 安装报 9568289 时
-
-说明当前 `module.json5` 中仍包含未签名的 system_basic 权限(如 `READ_CONTACTS`)。请确认使用的是默认的 5 项 normal 版本;若已手动合并 `module.full.json5`,需先完成 ACL 白名单与 Profile 签名配置。
-
-相册选图场景仍推荐使用系统 **PhotoViewPicker**(`uni.chooseImage`),无需申请媒体读写权限。
-
-#### 系统设置里找不到相册权限?
-
-默认 `module.json5` 为可安装调试包,**未声明** `READ_IMAGEVIDEO` / `WRITE_IMAGEVIDEO`,因此:
-
-- 系统「设置 → 应用 → 本应用 → 权限」中**不会出现**相册/媒体开关
-- 插件会将相册相关权限标记为 **未声明(restricted)**
-- 演示页可直接点 **「选图」** 试用,走系统相册选择器,不依赖该权限
-
-若业务必须申请媒体读写权限:用 `module.full.json5` 覆盖 `module.json5`,在 AppGallery Connect 配置 ACL 并重新签名安装后,系统设置中才会出现对应权限项。
-
-## 错误码
-
-| errCode | 说明 |
-| --- | --- |
-| 9020001 | 当前环境不支持 |
-| 9020002 | 用户拒绝授权 |
-| 9020003 | 权限不支持当前平台 |
-| 9020004 | 打开系统设置失败 |
-| 9020005 | 权限检查失败 |
-| 9020006 | 权限申请失败 |
-
-## 注意事项
-
-1. **H5 不支持**:本插件仅适用于 App(Android / iOS)与 Harmony 端。
-2. **需自定义基座**:UTS 插件修改后需在 HBuilderX 中重新制作自定义基座或云打包。
-3. **永久拒绝**:用户选择「不再询问」后,需引导用户通过 `openAppSettings()` 手动开启。
-4. **特殊权限**:Android 悬浮窗(`overlay`)和系统设置(`writeSettings`)需跳转系统设置页授权,申请结果可能为 `notDetermined`。
-
-
----
-
-## 使用规范
-
-本文档面向集成本插件的 App 开发者,说明 **必须遵守的约束**、**推荐做法** 和 **上架审核注意事项**。
-
----
-
-### 1. 基本约束(必须遵守)
-
-#### 1.1 用户主动触发
-
-`requestPermission` / `requestPermissions` **必须由真实用户手势触发**,例如按钮 `click` / `tap`。
-
-```vue
-<!-- ✅ 正确 -->
-<button @click="handleRequestCamera">申请相机权限</button>
-
-<!-- ❌ 错误:页面 onLoad / onShow 自动批量申请 -->
-<script setup>
-onMounted(async () => {
-  await requestPermissions(['camera', 'microphone', 'location']) // 体验差,可能被系统限制
-})
-</script>
-```
-
-原因:Android / iOS / Harmony 运行时权限弹窗均面向用户明确操作;冷启动批量申请易触发拒绝,且不符合各应用商店审核惯例。
-
-#### 1.2 先声明、后申请
-
-**仅安装插件不够**,必须在各端配置文件中声明所需权限,否则:
-
-| 平台 | 未声明后果 |
-| --- | --- |
-| Android | `SecurityException`、申请无弹窗或直接失败 |
-| iOS | 崩溃或无授权弹窗 |
-| Harmony | 系统设置无对应开关,插件返回 `restricted` 或 9020003 |
-
-详细配置见 [权限配置说明](#权限配置说明)。
-
-#### 1.3 按需申请
-
-只申请业务实际使用的权限。在功能入口处按需 `requestPermission`,不要一次性申请全部权限。
-
-```js
-// ✅ 审核页
-async function handleRequestCamera() {
-  const granted = await requestPermission('camera')
-  if (!granted) {
-    uni.showModal({
-      title: '需要相机权限',
-      content: getPermissionSettingsGuide('camera', '相机'),
-      confirmText: '去设置',
-      success: (res) => {
-        if (res.confirm) openPermissionSettings('camera')
-      },
-    })
-    return
-  }
-  // 继续业务逻辑
-}
-```
-
-#### 1.4 平台差异处理
-
-调用前可通过 `getSupportedPermissions()` 过滤当前平台不支持的 Key,避免向用户展示无效入口。
-
-```js
-const supported = getSupportedPermissions()
-const canUseOverlay = supported.includes('overlay') // 仅 Android 为 true
-```
-
----
-
-### 2. 推荐集成流程
-
-```
-进入功能页
-    ↓
-checkPermission(key) ──→ granted → 执行业务
-    ↓ notDetermined / denied
-用户点击「申请权限」
-    ↓
-requestPermission(key)
-    ↓
-系统弹窗 ──→ 拒绝 → getPermissionSettingsGuide + openPermissionSettings
-    ↓ 同意
-granted → 执行业务
-```
-
-#### 2.1 Promise 封装(推荐)
-
-项目可复用 `@/utils/permission-manager.js`:
-
-```js
-import {
-  checkPermission,
-  requestPermission,
-  requestPermissions,
-  openPermissionSettings,
-  getPermissionSettingsGuide,
-  ensurePermission,
-  getSupportedPermissions,
-} from '@/utils/permission-manager'
-```
-
-| 方法 | 用途 |
-| --- | --- |
-| `checkPermission(key)` | 检查状态,返回 `{ granted, status }` |
-| `requestPermission(key)` | 申请权限,返回 `boolean` |
-| `requestPermissions(keys[])` | 批量申请,返回 `{ allGranted, results }` |
-| `openPermissionSettings(key)` | 按权限类型跳转系统设置 |
-| `getPermissionSettingsGuide(key, label)` | 获取跳转前的引导文案 |
-| `ensurePermission(key, { openSettings })` | 检查 → 申请 → 可选跳转设置 |
-
-#### 2.2 直接调用 UTS API(callback 风格)
-
-```js
-import { requestPermission } from '@/uni_modules/m-permission-manager'
-
-requestPermission({
-  permission: 'camera',
-  success(res) {
-    if (res.granted) { /* ... */ }
-  },
-  fail(err) {
-    console.error(err.errCode, err.errMsg)
-  },
-})
-```
-
-#### 2.3 永久拒绝后的引导
-
-用户选择「不再询问」或多次拒绝后,应引导至系统设置:
-
-```js
-const granted = await requestPermission('bluetooth')
-if (!granted) {
-  uni.showModal({
-    title: '蓝牙权限未授予',
-    content: getPermissionSettingsGuide('bluetooth', '蓝牙'),
-    confirmText: '去设置',
-    success: (res) => {
-      if (res.confirm) openPermissionSettings('bluetooth')
-    },
-  })
-}
-```
-
-各端跳转行为:
-
-| 平台 | `openPermissionSettings` 行为 |
-| --- | --- |
-| Android 普通权限 | 应用详情 → 权限列表 |
-| Android `overlay` | 悬浮窗权限设置页 |
-| Android `writeSettings` | 修改系统设置权限页 |
-| iOS | 本 App 设置页(需 manifest 声明对应 UsageDescription) |
-| Harmony | 系统设置 → 应用详情 |
-
----
-
-### 3. 各端特别注意
-
-#### 3.1 Android
-
-- **Android 13+**:相册 / 存储自动映射 `READ_MEDIA_IMAGES` / `READ_MEDIA_VIDEO`
-- **Android 12+**:蓝牙自动映射 `BLUETOOTH_CONNECT` / `BLUETOOTH_SCAN`
-- **特殊权限**:`overlay`、`writeSettings` 需跳转系统设置页,申请结果可能为 `notDetermined`,返回后需再次 `checkPermission`
-
-#### 3.2 iOS
-
-- 必须在 `privacyDescription` 中配置对应 `NS*UsageDescription`,否则无弹窗
-- `storage` / `readStorage` 映射到相册权限(`PHPhotoLibrary`)
-- `coarseLocation` / `location` 均映射到定位授权
-- **蓝牙**:需 `NSBluetoothAlwaysUsageDescription`;系统蓝牙开关在「设置 → 蓝牙」,App 授权在 App 设置页或「隐私与安全性 → 蓝牙」
-
-#### 3.3 Harmony
-
-- 默认 `module.json5` 含 5 项 normal 权限,调试包可直接安装
-- 相册 / 通讯录为 `system_basic`,需 ACL 签名 + `module.full.json5`
-- 相册选图推荐 `uni.chooseImage`(系统 PhotoViewPicker),无需媒体读写权限
-- 未声明的 ACL 权限:检查返回 `restricted`,申请返回 9020003
-
----
-
-### 4. 错误码与用户提示
-
-| errCode | 含义 | 建议提示 |
-| --- | --- | --- |
-| 9020001 | 当前环境不支持 | 请在 App 端使用 |
-| 9020002 | 用户拒绝授权 | 您拒绝了授权,可在设置中重新开启 |
-| 9020003 | 权限不支持当前平台 | 当前平台不支持该权限 |
-| 9020004 | 打开系统设置失败 | 无法打开系统设置,请手动前往 |
-| 9020005 | 权限检查失败 | 权限检查失败,请重试 |
-| 9020006 | 权限申请失败 | 权限申请失败,请重试 |
-
----
-
-### 5. 上架审核注意事项
-
-| 市场 | 注意点 |
-| --- | --- |
-| App Store | 每个 `NS*UsageDescription` 文案需与真实功能一致;不要申请未使用的权限 |
-| Google Play | 需在 Data safety 中声明权限用途;Android 13+ 媒体权限需按类型声明 |
-| 华为 / 鸿蒙 | 说明 `ohos.permission.*` 用途;system_basic 权限需 ACL 白名单 |
-| 国内 Android 市场 | 隐私合规检测会扫描 manifest 权限列表,确保与隐私政策一致 |
-
----
-
-### 6. 自定义基座与发版
-
-1. 导入或更新插件后,**必须重新制作自定义基座**或云打包
-2. 修改 `manifest.json` 权限或鸿蒙 `module.json5` 后,需重新打包
-3. iOS 修改 `privacyDescription` 后需重新打包,必要时删除旧 App 重装以重新触发授权弹窗
-
----
-
-### 7. 参考文档
-
-- [readme](#m-permission-manager) — API 与快速开始
-- [权限配置说明](#权限配置说明) — 三端权限文件配置详解
-- [发布指南](#发布指南) — 插件市场发布填写参考
-
-## 权限配置说明
-
-本文档说明集成本插件时,**各端需要修改哪些文件**、**如何配置权限**,以及插件内置配置文件的作用。
-
----
-
-### 1. 配置总览
-
-| 平台 | 配置文件 | 配置方 | 说明 |
-| --- | --- | --- | --- |
-| **Android** | 宿主 `manifest.json` | 集成者 | 声明 `android.permission.*` |
-| **iOS** | 宿主 `manifest.json` | 集成者 | 声明 `NS*UsageDescription` |
-| **Harmony** | 插件 `utssdk/app-harmony/module.json5`(可选:`harmony-configs/entry/src/main/module.json5`) | 插件内置为主,集成者可切换 full 版或宿主覆盖 |
-
-> 插件负责**运行时检查与申请**;Android / iOS 的**静态声明**必须由宿主项目在 manifest 中完成。Harmony 权限由插件 module 合并进宿主包,集成者按需切换 normal / full 版本。
-
----
-
-### 2. Android 配置
-
-#### 2.1 配置文件
-
-**路径**:项目根目录 `manifest.json`  
-**节点**:`app-plus.distribute.android.permissions`
-
-```json
-{
-  "app-plus": {
-    "distribute": {
-      "android": {
-        "permissions": [
-          "<uses-permission android:name=\"android.permission.CAMERA\"/>",
-          "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
-          "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
-          "<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
-          "<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
-          "<uses-permission android:name=\"android.permission.BLUETOOTH_CONNECT\"/>",
-          "<uses-permission android:name=\"android.permission.BLUETOOTH_SCAN\"/>",
-          "<uses-permission android:name=\"android.permission.READ_MEDIA_IMAGES\"/>",
-          "<uses-permission android:name=\"android.permission.READ_MEDIA_VIDEO\"/>"
-        ]
-      }
-    }
-  }
-}
-```
-
-#### 2.2 统一 Key 与 Android 权限映射
-
-| 插件 Key | Android 权限 | 备注 |
-| --- | --- | --- |
-| `camera` | `CAMERA` | |
-| `photoLibrary` | `READ_MEDIA_IMAGES`(API 33+)或 `READ_EXTERNAL_STORAGE` | 插件按 SDK 自动选择 |
-| `storage` | `READ_MEDIA_IMAGES` + `READ_MEDIA_VIDEO`(API 33+)或 `WRITE/READ_EXTERNAL_STORAGE` | |
-| `readStorage` | 同 `photoLibrary` / 媒体读权限 | |
-| `location` | `ACCESS_FINE_LOCATION` | |
-| `coarseLocation` | `ACCESS_COARSE_LOCATION` | |
-| `microphone` | `RECORD_AUDIO` | |
-| `contacts` | `READ_CONTACTS` | |
-| `writeContacts` | `WRITE_CONTACTS` | |
-| `bluetooth` | `BLUETOOTH_CONNECT` + `BLUETOOTH_SCAN`(API 31+)或 `BLUETOOTH` + `BLUETOOTH_ADMIN` | |
-| `phone` | `CALL_PHONE` | |
-| `phoneState` | `READ_PHONE_STATE` | |
-| `sms` | `SEND_SMS` | |
-| `readSms` | `READ_SMS` | |
-| `receiveSms` | `RECEIVE_SMS` | |
-| `overlay` | 无 manifest 条目 | 通过 `Settings.canDrawOverlays` 检查 |
-| `writeSettings` | 无 manifest 条目 | 通过 `Settings.System.canWrite` 检查 |
-
-#### 2.3 注意
-
-- 只声明业务使用的权限,避免过度申请
-- Android 13+ 媒体权限使用 `READ_MEDIA_*`;插件仅在 **targetSdkVersion >= 33** 时动态申请新媒体权限,否则回退 `READ_EXTERNAL_STORAGE`(兼容 targetSdk 偏低的自定义基座)
-- `overlay`、`writeSettings` 需在 manifest 声明对应 capability 后,通过插件跳转系统设置页授权
-
----
-
-### 3. iOS 配置
-
-#### 3.1 配置文件
-
-**路径**:项目根目录 `manifest.json`  
-**节点**:`app-plus.distribute.ios.privacyDescription`
-
-```json
-{
-  "app-plus": {
-    "distribute": {
-      "ios": {
-        "privacyDescription": {
-          "NSCameraUsageDescription": "需要使用相机进行拍照",
-          "NSMicrophoneUsageDescription": "需要使用麦克风进行录音",
-          "NSPhotoLibraryUsageDescription": "需要访问相册以选择图片",
-          "NSPhotoLibraryAddUsageDescription": "需要保存图片到相册",
-          "NSLocationWhenInUseUsageDescription": "需要获取位置信息",
-          "NSContactsUsageDescription": "需要访问通讯录",
-          "NSBluetoothAlwaysUsageDescription": "需要使用蓝牙连接周边设备"
-        }
-      }
-    }
-  }
-}
-```
-
-#### 3.2 统一 Key 与 Info.plist 键映射
-
-| 插件 Key | Info.plist 键 | 备注 |
-| --- | --- | --- |
-| `camera` | `NSCameraUsageDescription` | |
-| `photoLibrary` | `NSPhotoLibraryUsageDescription` | |
-| `storage` | `NSPhotoLibraryUsageDescription` 或 `NSPhotoLibraryAddUsageDescription` | 映射到相册 |
-| `readStorage` | `NSPhotoLibraryUsageDescription` | 映射到相册 |
-| `location` | `NSLocationWhenInUseUsageDescription` | |
-| `coarseLocation` | `NSLocationWhenInUseUsageDescription` | 与精确定位共用 |
-| `microphone` | `NSMicrophoneUsageDescription` | |
-| `contacts` | `NSContactsUsageDescription` | |
-| `writeContacts` | `NSContactsUsageDescription` | 读写共用 |
-| `bluetooth` | `NSBluetoothAlwaysUsageDescription` | **必须配置**,否则 App 设置页无蓝牙开关 |
-
-#### 3.3 iOS 蓝牙特别说明
-
-iOS 蓝牙涉及两个独立概念:
-
-| 概念 | 设置路径 | 配置要求 |
-| --- | --- | --- |
-| 系统蓝牙开关 | 设置 → 蓝牙 | 无需 manifest,用户手动打开 |
-| App 蓝牙授权 | 设置 → 本 App → 蓝牙,或 设置 → 隐私与安全性 → 蓝牙 | 需 `NSBluetoothAlwaysUsageDescription` + 重新打包 + App 曾触发弹窗 |
-
-Apple 不提供跳转到「隐私 → 蓝牙」的公开深链;插件 `openPermissionSettings('bluetooth')` 会打开 App 设置页并配合引导文案。
-
----
-
-### 4. Harmony 配置
-
-#### 4.1 harmony-configs 要不要配?
-
-**使用 m-permission-manager 时,一般不需要在 `harmony-configs/` 里重复声明权限。**
-
-鸿蒙端权限有两种配置路径:
-
-| 方式 | 配置文件 | 适用场景 |
-| --- | --- | --- |
-| **UTS 插件声明(推荐)** | `uni_modules/m-permission-manager/utssdk/app-harmony/module.json5` | 插件打包为鸿蒙子模块(HAR),权限对整个 App 生效 |
-| **宿主工程覆盖** | `harmony-configs/entry/src/main/module.json5` | 插件未覆盖的权限、或希望在宿主侧集中管理 |
-
-鸿蒙官方规则:**已在子模块中声明的权限,主工程无需重复添加**,权限在整个应用中生效。  
-m-permission-manager 作为 UTS 插件,其 `module.json5` 会在编译时拷贝为插件子模块的 `src/main/module.json5`,因此**默认情况下宿主不必再配**。
-
-当前项目的 `harmony-configs/` 主要用于:
-
-| 文件 | 用途 |
-| --- | --- |
-| `AppScope/app.json5` | 包名、版本、图标(HX 4.31+ 也可在 `manifest.json` → `app-harmony` 图形界面配置) |
-| `build-profile.json5` | 签名证书(`.cer` / `.p12` / `.p7b`) |
-| `entry/build-profile.json5` | release 混淆等构建选项 |
-| `entry/obfuscation-rules.txt` | 混淆规则 |
-
-**若要在 harmony-configs 中配置权限**(可选,非必须):
-
-1. 先运行一次鸿蒙编译,从 `unpackage/dist/dev/app-harmony/entry/src/main/module.json5` 复制完整文件到 `harmony-configs/entry/src/main/module.json5`
-2. **仅修改** `module.requestPermissions` 节点,其他节点不要删(uni-app 是**文件级覆盖**,不是 JSON 节点合并)
-3. 不要与插件已声明的权限重复
-
-> 集成 m-permission-manager 时,优先改插件内的 `module.json5` / `module.full.json5`,而不是 harmony-configs。
-
-#### 4.2 插件内置文件
-
-**目录**:`uni_modules/m-permission-manager/utssdk/app-harmony/`
-
-| 文件 | 权限数量 | APL 等级 | 用途 |
-| --- | --- | --- | --- |
-| `module.json5` | 5 项 | normal | **默认生效**,调试证书可直接安装 |
-| `module.normal.json5` | 5 项 | normal | 与 `module.json5` 相同,备份参考 |
-| `module.full.json5` | 9 项 | normal + system_basic | 含相册 / 通讯录,需 ACL 签名 |
-
-**权限说明文案**:`resources/base/element/string.json`
-
-#### 4.3 默认 module.json5(5 项 normal)
-
-| 插件 Key | ohos.permission | 说明 |
-| --- | --- | --- |
-| `camera` | `CAMERA` | |
-| `microphone` | `MICROPHONE` | |
-| `location` | `LOCATION` | |
-| `coarseLocation` | `APPROXIMATELY_LOCATION` | |
-| `bluetooth` | `ACCESS_BLUETOOTH` | |
-
-#### 4.4 module.full.json5 额外 4 项(system_basic,需 ACL)
-
-| 插件 Key | ohos.permission | APL | 说明 |
-| --- | --- | --- | --- |
-| `photoLibrary` / `readStorage` | `READ_IMAGEVIDEO` | system_basic | 需 ACL |
-| `storage` | `WRITE_IMAGEVIDEO` | system_basic | 需 ACL |
-| `contacts` | `READ_CONTACTS` | system_basic | 需 ACL |
-| `writeContacts` | `WRITE_CONTACTS` | system_basic | 需 ACL |
-
-#### 4.5 如何切换 full 版本
-
-1. 将 `module.full.json5` 的内容**覆盖** `module.json5`
-2. 在 AppGallery Connect 配置 ACL 白名单
-3. 使用正式 Profile 重新签名打包
-4. 重新制作自定义基座或云打包
-
-#### 4.6 未声明 ACL 权限时的插件行为
-
-| 场景 | 检查 status | 申请结果 |
-| --- | --- | --- |
-| 相册 / 通讯录等未在 module.json5 声明 | `restricted` | 9020003,附未声明说明 |
-| 系统设置 | 无对应开关 | 引导使用 `uni.chooseImage` 或切换 full 版本 |
-
-#### 4.7 安装报 9568289
-
-说明 `module.json5` 中含有未签名的 system_basic 权限。请确认使用默认 5 项 normal 版本;若已合并 full 版本,需先完成 ACL 与 Profile 签名。
-
-#### 4.8 鸿蒙不支持的功能
-
-以下插件 Key 在鸿蒙返回 `unsupported`:`phone`、`phoneState`、`sms`、`readSms`、`receiveSms`、`overlay`、`writeSettings`。
-
----
-
-### 5. 配置示例(按业务场景)
-
-#### 5.1 仅需相机 + 麦克风
-
-**Android** manifest:
-
-```json
-"permissions": [
-  "<uses-permission android:name=\"android.permission.CAMERA\"/>",
-  "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>"
-]
-```
-
-**iOS** privacyDescription:
-
-```json
-"privacyDescription": {
-  "NSCameraUsageDescription": "需要使用相机",
-  "NSMicrophoneUsageDescription": "需要使用麦克风"
-}
-```
-
-**Harmony**:默认 `module.json5` 已包含,无需修改。
-
-#### 5.2 需要蓝牙
-
-**Android** manifest 增加:
-
-```json
-"<uses-permission android:name=\"android.permission.BLUETOOTH_CONNECT\"/>",
-"<uses-permission android:name=\"android.permission.BLUETOOTH_SCAN\"/>"
-```
-
-**iOS** privacyDescription 增加:
-
-```json
-"NSBluetoothAlwaysUsageDescription": "需要使用蓝牙连接周边设备"
-```
-
-**Harmony**:默认 `module.json5` 已包含 `ACCESS_BLUETOOTH`。
-
-#### 5.3 需要相册读写(Harmony 完整权限)
-
-1. 用 `module.full.json5` 覆盖 `module.json5`
-2. 配置 ACL 签名
-3. Android 增加 `READ_MEDIA_IMAGES` / `READ_MEDIA_VIDEO`
-4. iOS 增加 `NSPhotoLibraryUsageDescription`
-
-> 若仅需选图不上传,推荐使用 `uni.chooseImage`,三端均无需媒体读写权限。
-
----
-
-### 6. 配置后必做
-
-1. **重新制作自定义基座**或云打包(UTS 插件 + manifest 变更均须重新打包)
-2. iOS 修改 `privacyDescription` 后建议删除旧 App 重装,以重新触发授权弹窗
-3. Harmony 切换 `module.json5` 后需重新签名安装
-
----
-
-### 7. 相关文档
-
-- [readme](#m-permission-manager) — API 与权限 Key 对照表
-- [使用规范](#使用规范) — 集成流程与审核注意事项
-- [发布指南](#发布指南) — 插件市场发布填写参考
-
-## 发布指南
-
-面向插件作者,说明如何将本插件提交到 DCloud 插件市场,以及后台各字段的填写参考。
-
----
-
-### 发布前检查清单
-
-#### 代码与文档
-
-- [ ] `package.json` 中 `id`、`version`、`description`、`keywords` 已填写
-- [ ] `dcloudext.type` 为 `uts`
-- [ ] `dcloudext.declaration` 中 ads / data / permissions 已如实填写
-- [ ] `uni_modules.platforms` 中各端支持情况准确(vue3=y,H5/小程序=x)
-- [ ] `readme.md` 完整(安装、API、权限、FAQ)
-- [ ] `使用规范.md`、`权限配置说明.md`、`changelog.md` 已更新
-- [ ] `index.d.ts` 与 `index.js` 导出一致
-
-#### 功能验证
-
-- [ ] Android 真机:相机 / 麦克风 / 定位 / 蓝牙申请与检查
-- [ ] Android 12+ 真机:蓝牙 `BLUETOOTH_CONNECT` / `BLUETOOTH_SCAN`
-- [ ] Android 13+ 真机:相册 `READ_MEDIA_IMAGES` 自动映射
-- [ ] Android 真机:悬浮窗(`overlay`)、修改系统设置(`writeSettings`)跳转设置页
-- [ ] iOS 14+ 真机:相机 / 麦克风 / 定位 / 蓝牙 / 相册
-- [ ] iOS 真机:拒绝后 `openPermissionSettings('bluetooth')` 引导文案正确
-- [ ] Harmony API 12+ 真机:5 项 normal 权限申请(默认 `module.json5`)
-- [ ] Harmony 真机:相册 ACL 未声明时返回 `restricted` / 9020003
-- [ ] 拒绝授权时引导跳转系统设置
-- [ ] H5 环境明确不可用(9020001)
-
-#### 打包验证
-
-- [ ] 自定义基座可正常运行
-- [ ] 云打包 / 本地打包正式包可正常运行
-- [ ] 修改 UTS 代码后已重新制作基座
-
----
-
-### 提交到插件市场
-
-1. 登录 [DCloud 插件市场](https://ext.dcloud.net.cn/)
-2. 进入 **我的插件** → **发布插件**
-3. 插件类型选择 **UTS 插件**
-4. 上传 `uni_modules/m-permission-manager` 目录(或打包 zip)
-5. 按下方表格填写市场展示信息
-
----
-
-### 市场后台填写参考
-
-#### 基本信息
-
-| 字段 | 填写内容 |
-| --- | --- |
-| **插件名称** | m-permission-manager 跨端权限管理 |
-| **插件 ID** | m-permission-manager |
-| **插件类型** | UTS 插件 |
-| **价格** | 免费(或按实际定价) |
-| **版本号** | 与 `package.json` → `version` 一致,如 `1.0.0` |
-
-#### 标题(建议)
-
-```
-m-permission-manager - uni-app 跨端权限管理(Android/iOS/鸿蒙)
-```
-
-#### 一句话描述
-
-```
-UTS 权限插件,Android / iOS / Harmony 三端统一 API,检查与申请运行时权限,支持跳转系统设置。
-```
-
-#### 详细描述(可直接粘贴)
-
-```
-m-permission-manager 是 uni-app Vue3 跨端权限管理 UTS 插件,支持 Android、iOS、Harmony 三端。
-
-【核心能力】
-· 17 种统一权限 Key,三端通用命名
-· 同步 / 异步检查权限状态
-· 单个 / 批量申请权限
-· 按权限类型跳转系统设置页
-· 获取当前平台支持的权限列表
-
-【平台支持】
-· Android:17 项权限(含悬浮窗、短信、电话等 Android 专属)
-· iOS:10 项通用权限(相机、相册、定位、麦克风、蓝牙、通讯录等)
-· Harmony:10 项通用权限(默认 5 项 normal 可直接安装,相册/通讯录需 ACL)
-
-【集成方式】
-1. 导入 uni_modules 插件
-2. 在宿主 manifest.json(Android/iOS)及鸿蒙 module.json5 中声明所需权限
-3. 使用 @/utils/permission-manager Promise 封装或直接调用 UTS API
-
-详细权限配置见插件内[权限配置说明](#权限配置说明),集成规范见[使用规范](#使用规范)。
-```
-
-#### 标签 / 关键词
-
-```
-权限, permission, 运行时权限, 蓝牙, 相机, 定位, Android, iOS, Harmony, 鸿蒙, UTS
-```
-
-#### 使用说明(市场「使用说明」字段)
-
-可直接粘贴以下内容,或填写插件 readme 链接:
-
-```
-【快速开始】
-
-1. 从插件市场导入 m-permission-manager 到项目 uni_modules 目录
-
-2. 在 manifest.json 中声明宿主所需权限(Android permissions / iOS privacyDescription)
-   鸿蒙端见插件 utssdk/app-harmony/module.json5,详见[权限配置说明](#权限配置说明)
-
-3. 重新制作自定义基座或云打包(UTS 插件不支持标准基座)
-
-4. 在代码中调用:
-
-import {
-  checkPermission,
-  requestPermission,
-  openPermissionSettings,
-} from '@/utils/permission-manager'
-
-const result = await checkPermission('camera')
-const granted = await requestPermission('camera')
-if (!granted) {
-  await openPermissionSettings('camera')
-}
-
-【重要说明】
-· 仅支持 App 端(Android / iOS / Harmony),不支持 H5 与小程序
-· 插件负责运行时检查与申请,宿主仍需在 manifest 中声明静态权限
-· iOS 蓝牙需在 privacyDescription 中配置 NSBluetoothAlwaysUsageDescription
-· 鸿蒙相册/通讯录为 system_basic 权限,默认调试包未声明,需 ACL 签名后启用
-
-完整文档:
-· [readme](#m-permission-manager) — API 与快速开始
-· [使用规范](#使用规范) — 集成约束与推荐流程
-· [权限配置说明](#权限配置说明) — 三端权限文件配置详解
-```
-
-#### 权限与隐私声明(`dcloudext.declaration` 对应项)
-
-| 字段 | 填写内容 |
-| --- | --- |
-| **是否含广告** | 无 |
-| **是否采集数据** | 不上传任何用户数据,仅在本地检查与申请系统权限 |
-| **权限说明** | Android:宿主 manifest 声明对应 android.permission.*;iOS:宿主 manifest 声明 NSCameraUsageDescription 等 Info.plist 键;Harmony:插件 module.json5 声明 ohos.permission.*,运行时申请 |
-
-#### 平台支持(与 package.json 一致)
-
-| 平台 | 支持情况 |
-| --- | --- |
-| uni-app Vue3 | ✅ |
-| uni-app Vue2 | ❌ |
-| H5 | ❌ |
-| 小程序 | ❌ |
-| Android App | ✅(minSdk 23) |
-| iOS App | ✅(min iOS 14) |
-| Harmony App | ✅(API 12+) |
-
-#### 截图建议(4–6 张)
-
-1. 权限演示页截图(三端权限列表与状态)
-2. Promise 封装调用代码示例
-3. Android 系统权限弹窗(相机 / 蓝牙)
-4. iOS 隐私授权弹窗
-5. manifest.json 权限配置示例
-6. 三端权限支持对照表
-
----
-
-### 市场 FAQ 预填
-
-**Q:为什么必须自定义基座?**  
-A:本插件为 UTS 原生插件,标准基座不包含。需制作含本插件的自定义基座或云打包。
-
-**Q:H5 能用吗?**  
-A:不支持。仅 App 端(Android / iOS / Harmony)。
-
-**Q:安装插件后还需要配置权限吗?**  
-A:需要。Android / iOS 必须在宿主 `manifest.json` 中声明静态权限与隐私说明;鸿蒙由插件 `module.json5` 合并,但 ACL 权限需额外签名。详见[权限配置说明](#权限配置说明)。
-
-**Q:三端权限 Key 一样吗?**  
-A:统一使用 `camera`、`microphone`、`location`、`bluetooth` 等 Key,插件内部映射到各平台原生权限。部分 Key 仅 Android 支持(如 `overlay`、`sms`),调用时会返回 `unsupported`。
-
-**Q:iOS 蓝牙在 App 设置里找不到?**  
-A:需在 manifest 配置 `NSBluetoothAlwaysUsageDescription` 并重新打包,且 App 需曾触发蓝牙权限弹窗。若 App 设置页无该项,请前往「设置 → 隐私与安全性 → 蓝牙」。系统蓝牙开关在「设置 → 蓝牙」,与应用授权无关。
-
-**Q:鸿蒙相册权限申请失败?**  
-A:默认 `module.json5` 仅含 5 项 normal 权限,未声明相册读写。相册选图推荐 `uni.chooseImage`;若必须申请媒体权限,需用 `module.full.json5` 覆盖并配置 ACL 签名。
-
-**Q:用户永久拒绝后怎么办?**  
-A:调用 `openPermissionSettings(permissionKey)` 跳转对应系统设置页,配合 `getPermissionSettingsGuide()` 展示引导文案。
-
----
-
-### 版本号规范
-
-遵循 [语义化版本](https://semver.org/lang/zh-CN/):
-
-| 变更类型 | 版本 bump | 示例 |
-| --- | --- | --- |
-| 不兼容 API 变更 | major | 2.0.0 |
-| 新增功能(兼容) | minor | 1.1.0 |
-| Bug 修复 | patch | 1.0.1 |
-
-每次发版同步更新 `package.json` → `version` 和 `changelog.md`。
-
----
-
-### 联系方式
-
-发布前请在 `package.json` → `dcloudext.contact.qq` 填写维护者 QQ,或在插件市场后台配置联系方式。
-
----
-
-### 参考链接
-
-- [UTS 插件开发文档](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html)
-- [插件市场发布流程](https://uniapp.dcloud.net.cn/plugin/publish.html)
-- 插件内 [readme](#m-permission-manager)
-- 插件内 [使用规范](#使用规范)
-- 插件内 [权限配置说明](#权限配置说明)
-
-## 更新日志
-
-### 1.0.2(2026-06-17)
-- 修复 Android:相册/存储/蓝牙申请失败(`targetSdkVersion` 与 `READ_MEDIA_*` / `BLUETOOTH_*` 不匹配)
-- 权限映射同时校验设备 API 与宿主 `targetSdkVersion`,自定义基座 targetSdk < 33 时回退旧版权限
-### 1.0.1(2026-06-17)
-
-- 新增 `openPermissionSettings(permission)` 按权限类型跳转系统设置
-- 新增 `getPermissionSettingsGuide(permission, label)` 引导文案
-- Android:`overlay` / `writeSettings` 跳转对应系统设置页
-- 新增 [发布指南](#发布指南)、[使用规范](#使用规范)、[权限配置说明](#权限配置说明) 文档
-- readme 补充 iOS 蓝牙说明与 `NSBluetoothAlwaysUsageDescription`
-
-### 1.0.0(2026-05-29)
-
-- 初始版本
-- 支持 Android / iOS / Harmony 三端统一权限检查与申请
-- 提供同步 / 异步 API 及 `@/utils/permission-manager` Promise 封装

+ 0 - 4
uni_modules/m-permission-manager/utssdk/app-android/config.json

@@ -1,4 +0,0 @@
-{
-	"minSdkVersion": 23,
-	"dependencies": []
-}

+ 0 - 530
uni_modules/m-permission-manager/utssdk/app-android/index.uts

@@ -1,530 +0,0 @@
-import Build from 'android.os.Build'
-import Intent from 'android.content.Intent'
-import Settings from 'android.provider.Settings'
-import Uri from 'android.net.Uri'
-import ContextCompat from 'androidx.core.content.ContextCompat'
-import ActivityCompat from 'androidx.core.app.ActivityCompat'
-import PackageManager from 'android.content.pm.PackageManager'
-import BluetoothAdapter from 'android.bluetooth.BluetoothAdapter'
-import { UTSAndroid } from 'io.dcloud.uts'
-import {
-	BluetoothDemoInfo,
-	CheckPermission,
-	CheckPermissionOptions,
-	CheckPermissions,
-	CheckPermissionsOptions,
-	CheckPermissionsResult,
-	CheckPermissionsSync,
-	CheckPermissionSync,
-	GetSupportedPermissionsResult,
-	GetSupportedPermissionsSync,
-	GetBluetoothDemoInfoSync,
-	OpenAppSettings,
-	OpenAppSettingsOptions,
-	PermissionCheckResult,
-	PermissionFail,
-	PermissionKey,
-	PermissionGrantResult,
-	PermissionStatus,
-	RequestPermission,
-	RequestPermissionOptions,
-	RequestPermissions,
-	RequestPermissionsOptions,
-	RequestPermissionsResult,
-} from '../interface.uts'
-import { PermissionFailImpl } from '../unierror'
-
-const ANDROID_API_TIRAMISU : Int = 33
-const ANDROID_API_S : Int = 31
-
-function getAppTargetSdkVersion() : Int {
-	const activity = UTSAndroid.getUniActivity()
-	if (activity == null) {
-		return 0
-	}
-	return activity.getApplicationInfo().targetSdkVersion
-}
-
-/** 设备 API 与宿主 targetSdkVersion 均满足时才使用 READ_MEDIA_*(UTS 运行时强校验 targetSdk) */
-function shouldUseReadMediaPermissions() : boolean {
-	if (Build.VERSION.SDK_INT < ANDROID_API_TIRAMISU) {
-		return false
-	}
-	return getAppTargetSdkVersion() >= ANDROID_API_TIRAMISU
-}
-
-/** 设备 API 与宿主 targetSdkVersion 均满足时才使用 BLUETOOTH_CONNECT / BLUETOOTH_SCAN */
-function shouldUseBluetoothRuntimePermissions() : boolean {
-	if (Build.VERSION.SDK_INT < ANDROID_API_S) {
-		return false
-	}
-	return getAppTargetSdkVersion() >= ANDROID_API_S
-}
-
-const SUPPORTED_PERMISSIONS : PermissionKey[] = [
-	'camera',
-	'photoLibrary',
-	'storage',
-	'readStorage',
-	'location',
-	'coarseLocation',
-	'microphone',
-	'contacts',
-	'writeContacts',
-	'bluetooth',
-	'phone',
-	'phoneState',
-	'sms',
-	'readSms',
-	'receiveSms',
-	'overlay',
-	'writeSettings',
-]
-
-function createCheckResult(permission : PermissionKey, status : PermissionStatus) : PermissionCheckResult {
-	return {
-		permission: permission,
-		status: status,
-		granted: status == 'granted',
-	}
-}
-
-function createRequestResult(permission : PermissionKey, status : PermissionStatus) : PermissionGrantResult {
-	return {
-		permission: permission,
-		status: status,
-		granted: status == 'granted',
-	}
-}
-
-function resolveAndroidPermissions(permission : PermissionKey) : string[] | null {
-	switch (permission) {
-		case 'camera':
-			return ['android.permission.CAMERA']
-		case 'photoLibrary':
-			if (shouldUseReadMediaPermissions()) {
-				return ['android.permission.READ_MEDIA_IMAGES']
-			}
-			return ['android.permission.READ_EXTERNAL_STORAGE']
-		case 'storage':
-			if (shouldUseReadMediaPermissions()) {
-				return ['android.permission.READ_MEDIA_IMAGES', 'android.permission.READ_MEDIA_VIDEO']
-			}
-			return ['android.permission.WRITE_EXTERNAL_STORAGE', 'android.permission.READ_EXTERNAL_STORAGE']
-		case 'readStorage':
-			if (shouldUseReadMediaPermissions()) {
-				return ['android.permission.READ_MEDIA_IMAGES', 'android.permission.READ_MEDIA_VIDEO']
-			}
-			return ['android.permission.READ_EXTERNAL_STORAGE']
-		case 'location':
-			return ['android.permission.ACCESS_FINE_LOCATION']
-		case 'coarseLocation':
-			return ['android.permission.ACCESS_COARSE_LOCATION']
-		case 'microphone':
-			return ['android.permission.RECORD_AUDIO']
-		case 'contacts':
-			return ['android.permission.READ_CONTACTS']
-		case 'writeContacts':
-			return ['android.permission.WRITE_CONTACTS']
-		case 'bluetooth':
-			if (shouldUseBluetoothRuntimePermissions()) {
-				return ['android.permission.BLUETOOTH_CONNECT', 'android.permission.BLUETOOTH_SCAN']
-			}
-			return ['android.permission.BLUETOOTH', 'android.permission.BLUETOOTH_ADMIN']
-		case 'phone':
-			return ['android.permission.CALL_PHONE']
-		case 'phoneState':
-			return ['android.permission.READ_PHONE_STATE']
-		case 'sms':
-			return ['android.permission.SEND_SMS']
-		case 'readSms':
-			return ['android.permission.READ_SMS']
-		case 'receiveSms':
-			return ['android.permission.RECEIVE_SMS']
-		case 'overlay':
-		case 'writeSettings':
-			return []
-		default:
-			return null
-	}
-}
-
-function isPermissionGranted(permission : PermissionKey) : boolean {
-	const activity = UTSAndroid.getUniActivity()
-	if (activity == null) {
-		return false
-	}
-
-	if (permission == 'overlay') {
-		return Settings.canDrawOverlays(activity)
-	}
-	if (permission == 'writeSettings') {
-		return Settings.System.canWrite(activity)
-	}
-
-	const androidPermissions = resolveAndroidPermissions(permission)
-	if (androidPermissions == null) {
-		return false
-	}
-	if (androidPermissions.length == 0) {
-		return false
-	}
-	return UTSAndroid.checkSystemPermissionGranted(activity, androidPermissions)
-}
-
-function resolvePermissionStatus(permission : PermissionKey) : PermissionStatus {
-	const androidPermissions = resolveAndroidPermissions(permission)
-	if (androidPermissions == null) {
-		return 'unsupported'
-	}
-
-	if (permission == 'overlay' || permission == 'writeSettings') {
-		return isPermissionGranted(permission) ? 'granted' : 'notDetermined'
-	}
-
-	const activity = UTSAndroid.getUniActivity()
-	if (activity == null) {
-		return 'denied'
-	}
-
-	let allGranted = true
-	let hasDenied = false
-	for (let i = 0; i < androidPermissions.length; i++) {
-		const androidPermission = androidPermissions[i]
-		const granted = ContextCompat.checkSelfPermission(activity, androidPermission) == PackageManager.PERMISSION_GRANTED
-		if (granted) {
-			continue
-		}
-		allGranted = false
-		if (ActivityCompat.shouldShowRequestPermissionRationale(activity, androidPermission)) {
-			hasDenied = true
-		}
-	}
-	if (allGranted) {
-		return 'granted'
-	}
-	if (hasDenied) {
-		return 'denied'
-	}
-	return 'notDetermined'
-}
-
-function succeedCheckPermission(options : CheckPermissionOptions, res : PermissionCheckResult) {
-	const successCallback = options.success
-	if (successCallback != null) {
-		successCallback(res)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(res)
-	}
-}
-
-function succeedCheckPermissions(options : CheckPermissionsOptions, res : CheckPermissionsResult) {
-	const successCallback = options.success
-	if (successCallback != null) {
-		successCallback(res)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(res)
-	}
-}
-
-function succeedRequestPermission(options : RequestPermissionOptions, res : PermissionGrantResult) {
-	const successCallback = options.success
-	if (successCallback != null) {
-		successCallback(res)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(res)
-	}
-}
-
-function succeedRequestPermissions(options : RequestPermissionsOptions, res : RequestPermissionsResult) {
-	const successCallback = options.success
-	if (successCallback != null) {
-		successCallback(res)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(res)
-	}
-}
-
-function succeedOpenAppSettings(options : OpenAppSettingsOptions, res : PermissionCheckResult) {
-	const successCallback = options.success
-	if (successCallback != null) {
-		successCallback(res)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(res)
-	}
-}
-
-function failRequestPermission(options : RequestPermissionOptions, err : PermissionFail) {
-	const failCallback = options.fail
-	if (failCallback != null) {
-		failCallback(err)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(err)
-	}
-}
-
-function failRequestPermissions(options : RequestPermissionsOptions, err : PermissionFail) {
-	const failCallback = options.fail
-	if (failCallback != null) {
-		failCallback(err)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(err)
-	}
-}
-
-function failOpenAppSettings(options : OpenAppSettingsOptions, err : PermissionFail) {
-	const failCallback = options.fail
-	if (failCallback != null) {
-		failCallback(err)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(err)
-	}
-}
-
-function requestOverlayPermission(options : RequestPermissionOptions) {
-	const activity = UTSAndroid.getUniActivity()
-	if (activity == null) {
-		failRequestPermission(options, new PermissionFailImpl(9020006, 'Activity 不可用'))
-		return
-	}
-	if (Settings.canDrawOverlays(activity)) {
-		succeedRequestPermission(options, createRequestResult(options.permission, 'granted'))
-		return
-	}
-	const intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)
-	intent.setData(Uri.parse('package:' + activity.getPackageName()))
-	activity.startActivity(intent)
-	succeedRequestPermission(options, createRequestResult(options.permission, 'notDetermined'))
-}
-
-function requestWriteSettingsPermission(options : RequestPermissionOptions) {
-	const activity = UTSAndroid.getUniActivity()
-	if (activity == null) {
-		failRequestPermission(options, new PermissionFailImpl(9020006, 'Activity 不可用'))
-		return
-	}
-	if (Settings.System.canWrite(activity)) {
-		succeedRequestPermission(options, createRequestResult(options.permission, 'granted'))
-		return
-	}
-	const intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
-	intent.setData(Uri.parse('package:' + activity.getPackageName()))
-	activity.startActivity(intent)
-	succeedRequestPermission(options, createRequestResult(options.permission, 'notDetermined'))
-}
-
-function requestRuntimePermission(options : RequestPermissionOptions) {
-	const activity = UTSAndroid.getUniActivity()
-	const androidPermissions = resolveAndroidPermissions(options.permission)
-	if (activity == null) {
-		failRequestPermission(options, new PermissionFailImpl(9020006, 'Activity 不可用'))
-		return
-	}
-	if (androidPermissions == null) {
-		failRequestPermission(options, new PermissionFailImpl(9020003))
-		return
-	}
-	if (androidPermissions.length == 0) {
-		failRequestPermission(options, new PermissionFailImpl(9020003))
-		return
-	}
-
-	if (UTSAndroid.checkSystemPermissionGranted(activity, androidPermissions)) {
-		succeedRequestPermission(options, createRequestResult(options.permission, 'granted'))
-		return
-	}
-
-	try {
-		UTSAndroid.requestSystemPermission(
-			activity,
-			androidPermissions,
-			(allGranted : boolean, _ : string[]) => {
-				if (allGranted) {
-					succeedRequestPermission(options, createRequestResult(options.permission, 'granted'))
-					return
-				}
-				succeedRequestPermission(options, createRequestResult(options.permission, 'denied'))
-			},
-			(_ : boolean, _grantedList : string[]) => {
-				succeedRequestPermission(options, createRequestResult(options.permission, 'denied'))
-			},
-		)
-	} catch (ignored) {
-		failRequestPermission(options, new PermissionFailImpl(9020006, '权限申请失败,请确认 manifest 已声明对应权限且 targetSdkVersion 满足要求'))
-	}
-}
-
-export const checkPermissionSync : CheckPermissionSync = function (permission : PermissionKey) : PermissionCheckResult {
-	const status = resolvePermissionStatus(permission)
-	return createCheckResult(permission, status)
-}
-
-export const checkPermissionsSync : CheckPermissionsSync = function (permissions : PermissionKey[]) : CheckPermissionsResult {
-	const results : PermissionCheckResult[] = []
-	let allGranted = true
-	for (let i = 0; i < permissions.length; i++) {
-		const item = checkPermissionSync(permissions[i])
-		results.push(item)
-		if (!item.granted) {
-			allGranted = false
-		}
-	}
-	return {
-		results: results,
-		allGranted: allGranted,
-	}
-}
-
-export const checkPermission : CheckPermission = function (options : CheckPermissionOptions) {
-	const result = checkPermissionSync(options.permission)
-	succeedCheckPermission(options, result)
-}
-
-export const checkPermissions : CheckPermissions = function (options : CheckPermissionsOptions) {
-	const result = checkPermissionsSync(options.permissions)
-	succeedCheckPermissions(options, result)
-}
-
-export const requestPermission : RequestPermission = function (options : RequestPermissionOptions) {
-	if (options.permission == 'overlay') {
-		requestOverlayPermission(options)
-		return
-	}
-	if (options.permission == 'writeSettings') {
-		requestWriteSettingsPermission(options)
-		return
-	}
-	requestRuntimePermission(options)
-}
-
-export const requestPermissions : RequestPermissions = function (options : RequestPermissionsOptions) {
-	const permissions = options.permissions
-	if (permissions.length == 0) {
-		const emptyResult : RequestPermissionsResult = {
-			results: [],
-			allGranted: true,
-		}
-		succeedRequestPermissions(options, emptyResult)
-		return
-	}
-
-	let currentIndex = 0
-	const collectedResults : PermissionGrantResult[] = []
-
-	function requestNext() {
-		if (currentIndex >= permissions.length) {
-			let allGranted = true
-			for (let i = 0; i < collectedResults.length; i++) {
-				if (!collectedResults[i].granted) {
-					allGranted = false
-					break
-				}
-			}
-			const finalResult : RequestPermissionsResult = {
-				results: collectedResults,
-				allGranted: allGranted,
-			}
-			succeedRequestPermissions(options, finalResult)
-			return
-		}
-
-		const permission = permissions[currentIndex]
-		currentIndex += 1
-		requestPermission({
-			permission: permission,
-			success: (res : PermissionGrantResult) => {
-				collectedResults.push(res)
-				requestNext()
-			},
-			fail: (err : PermissionFail) => {
-				collectedResults.push(createRequestResult(permission, 'denied'))
-				failRequestPermissions(options, err)
-			},
-		})
-	}
-
-	requestNext()
-}
-
-export const openAppSettings : OpenAppSettings = function (options : OpenAppSettingsOptions) {
-	const activity = UTSAndroid.getUniActivity()
-	if (activity == null) {
-		failOpenAppSettings(options, new PermissionFailImpl(9020004, 'Activity 不可用'))
-		return
-	}
-	try {
-		const permission = options.permission
-		let intent : Intent
-		if (permission == 'overlay') {
-			intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)
-			intent.setData(Uri.parse('package:' + activity.getPackageName()))
-		} else if (permission == 'writeSettings') {
-			intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
-			intent.setData(Uri.parse('package:' + activity.getPackageName()))
-		} else {
-			intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
-			intent.setData(Uri.parse('package:' + activity.getPackageName()))
-		}
-		activity.startActivity(intent)
-		const resultPermission = permission != null ? permission : 'camera'
-		succeedOpenAppSettings(options, createCheckResult(resultPermission, 'granted'))
-	} catch (ignored) {
-		failOpenAppSettings(options, new PermissionFailImpl(9020004))
-	}
-}
-
-export const getSupportedPermissionsSync : GetSupportedPermissionsSync = function () : GetSupportedPermissionsResult {
-	return {
-		permissions: SUPPORTED_PERMISSIONS,
-	}
-}
-
-function mapAndroidBluetoothState(state : Int) : string {
-	switch (state) {
-		case BluetoothAdapter.STATE_OFF:
-			return '已关闭'
-		case BluetoothAdapter.STATE_TURNING_ON:
-			return '正在打开'
-		case BluetoothAdapter.STATE_ON:
-			return '已开启'
-		case BluetoothAdapter.STATE_TURNING_OFF:
-			return '正在关闭'
-		default:
-			return '未知'
-	}
-}
-
-export const getBluetoothDemoInfoSync : GetBluetoothDemoInfoSync = function () : BluetoothDemoInfo {
-	const adapter = BluetoothAdapter.getDefaultAdapter()
-	if (adapter == null) {
-		return {
-			available: false,
-			enabled: false,
-			stateText: '设备不支持蓝牙',
-			stateCode: -1,
-		}
-	}
-	const state = adapter.getState()
-	return {
-		available: true,
-		enabled: state == BluetoothAdapter.STATE_ON,
-		stateText: mapAndroidBluetoothState(state),
-		stateCode: state,
-	}
-}

+ 0 - 3
uni_modules/m-permission-manager/utssdk/app-harmony/config.json

@@ -1,3 +0,0 @@
-{
-	"dependencies": []
-}

+ 0 - 508
uni_modules/m-permission-manager/utssdk/app-harmony/index.uts

@@ -1,508 +0,0 @@
-import abilityAccessCtrl from '@ohos.abilityAccessCtrl'
-import { Permissions, PermissionRequestResult as AtManagerPermissionResult } from '@ohos.abilityAccessCtrl'
-import { BusinessError } from '@ohos.base'
-import common from '@ohos.app.ability.common'
-import Want from '@ohos.app.ability.Want'
-import access from '@ohos.bluetooth.access'
-import bundleManager from '@ohos.bundle.bundleManager'
-import {
-	BluetoothDemoInfo,
-	CheckPermission,
-	CheckPermissionOptions,
-	CheckPermissions,
-	CheckPermissionsOptions,
-	CheckPermissionsResult,
-	CheckPermissionsSync,
-	CheckPermissionSync,
-	GetSupportedPermissionsResult,
-	GetSupportedPermissionsSync,
-	GetBluetoothDemoInfoSync,
-	OpenAppSettings,
-	OpenAppSettingsOptions,
-	PermissionCheckResult,
-	PermissionGrantResult,
-	PermissionKey,
-	PermissionStatus,
-	RequestPermission,
-	RequestPermissionOptions,
-	RequestPermissions,
-	RequestPermissionsOptions,
-	RequestPermissionsResult,
-} from '../interface.uts'
-import { PermissionFailImpl } from '../unierror'
-
-const SUPPORTED_PERMISSIONS : PermissionKey[] = [
-	'camera',
-	'photoLibrary',
-	'storage',
-	'readStorage',
-	'location',
-	'coarseLocation',
-	'microphone',
-	'contacts',
-	'writeContacts',
-	'bluetooth',
-]
-
-/** 鸿蒙无对应系统能力的权限(Android 专属等) */
-const HARMONY_UNSUPPORTED : PermissionKey[] = [
-	'phone',
-	'phoneState',
-	'sms',
-	'readSms',
-	'receiveSms',
-	'overlay',
-	'writeSettings',
-]
-
-function createCheckResult(permission : PermissionKey, status : PermissionStatus) : PermissionCheckResult {
-	return {
-		permission: permission,
-		status: status,
-		granted: status == 'granted',
-	}
-}
-
-function createGrantResult(permission : PermissionKey, status : PermissionStatus) : PermissionGrantResult {
-	return {
-		permission: permission,
-		status: status,
-		granted: status == 'granted',
-	}
-}
-
-/** 需在 module.json5 声明且 ACL 签名的权限 */
-const HARMONY_ACL_PERMISSION_KEYS : PermissionKey[] = [
-	'photoLibrary',
-	'readStorage',
-	'storage',
-	'contacts',
-	'writeContacts',
-]
-
-function isHarmonyAclPermission(permission : PermissionKey) : boolean {
-	for (let i = 0; i < HARMONY_ACL_PERMISSION_KEYS.length; i++) {
-		if (HARMONY_ACL_PERMISSION_KEYS[i] == permission) {
-			return true
-		}
-	}
-	return false
-}
-
-function isHarmonyPermissionDeclared(harmonyPermission : Permissions) : boolean {
-	try {
-		const bundleInfo = bundleManager.getBundleInfoForSelfSync(
-			bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION,
-		)
-		const declared = bundleInfo.reqPermissionDetails
-		for (let i = 0; i < declared.length; i++) {
-			const item = declared[i]
-			if (item.name == harmonyPermission) {
-				return true
-			}
-		}
-		return false
-	} catch (ignored) {
-		return false
-	}
-}
-
-function createAclUndeclaredMessage(permission : PermissionKey) : string {
-	if (permission == 'photoLibrary' || permission == 'readStorage' || permission == 'storage') {
-		return '当前包未声明相册/媒体权限,系统设置无对应开关。选图请用系统相册选择器;完整权限需 module.full.json5 + ACL'
-	}
-	return '当前包未声明该权限,系统设置无对应开关。请使用 module.full.json5 并配置 ACL 后重签安装'
-}
-
-function isHarmonyAclUndeclared(permission : PermissionKey) : boolean {
-	if (!isHarmonyAclPermission(permission)) {
-		return false
-	}
-	const harmonyPermission = resolveHarmonyPermission(permission)
-	if (harmonyPermission == null) {
-		return false
-	}
-	return !isHarmonyPermissionDeclared(harmonyPermission)
-}
-
-function isHarmonyUnsupported(permission : PermissionKey) : boolean {
-	for (let i = 0; i < HARMONY_UNSUPPORTED.length; i++) {
-		if (HARMONY_UNSUPPORTED[i] == permission) {
-			return true
-		}
-	}
-	return false
-}
-
-function resolveHarmonyPermission(permission : PermissionKey) : Permissions | null {
-	switch (permission) {
-		case 'camera':
-			return 'ohos.permission.CAMERA'
-		case 'photoLibrary':
-		case 'readStorage':
-			return 'ohos.permission.READ_IMAGEVIDEO'
-		case 'storage':
-			return 'ohos.permission.WRITE_IMAGEVIDEO'
-		case 'location':
-			return 'ohos.permission.LOCATION'
-		case 'coarseLocation':
-			return 'ohos.permission.APPROXIMATELY_LOCATION'
-		case 'microphone':
-			return 'ohos.permission.MICROPHONE'
-		case 'contacts':
-			return 'ohos.permission.READ_CONTACTS'
-		case 'writeContacts':
-			return 'ohos.permission.WRITE_CONTACTS'
-		case 'bluetooth':
-			return 'ohos.permission.ACCESS_BLUETOOTH'
-		default:
-			return null
-	}
-}
-
-function getAbilityContext() : common.UIAbilityContext | null {
-	try {
-		return getContext() as common.UIAbilityContext
-	} catch (ignored) {
-		return null
-	}
-}
-
-function checkHarmonyPermissionStatus(permission : PermissionKey) : PermissionStatus {
-	if (isHarmonyUnsupported(permission)) {
-		return 'unsupported'
-	}
-
-	const harmonyPermission = resolveHarmonyPermission(permission)
-	if (harmonyPermission == null) {
-		return 'unsupported'
-	}
-
-	if (isHarmonyAclUndeclared(permission)) {
-		return 'restricted'
-	}
-
-	const context = getAbilityContext()
-	if (context == null) {
-		return 'denied'
-	}
-
-	const atManager = abilityAccessCtrl.createAtManager()
-	const tokenId = context.applicationInfo.accessTokenId
-	const status = atManager.checkAccessTokenSync(tokenId, harmonyPermission)
-	if (status == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
-		return 'granted'
-	}
-	return 'notDetermined'
-}
-
-function succeedCheckPermission(options : CheckPermissionOptions, res : PermissionCheckResult) {
-	const successCallback = options.success
-	if (successCallback != null) {
-		successCallback(res)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(res)
-	}
-}
-
-function succeedCheckPermissions(options : CheckPermissionsOptions, res : CheckPermissionsResult) {
-	const successCallback = options.success
-	if (successCallback != null) {
-		successCallback(res)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(res)
-	}
-}
-
-function succeedRequestPermission(options : RequestPermissionOptions, res : PermissionGrantResult) {
-	const successCallback = options.success
-	if (successCallback != null) {
-		successCallback(res)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(res)
-	}
-}
-
-function succeedRequestPermissions(options : RequestPermissionsOptions, res : RequestPermissionsResult) {
-	const successCallback = options.success
-	if (successCallback != null) {
-		successCallback(res)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(res)
-	}
-}
-
-function failRequestPermission(options : RequestPermissionOptions, err : PermissionFailImpl) {
-	const failCallback = options.fail
-	if (failCallback != null) {
-		failCallback(err)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(err)
-	}
-}
-
-function failRequestPermissions(options : RequestPermissionsOptions, err : PermissionFailImpl) {
-	const failCallback = options.fail
-	if (failCallback != null) {
-		failCallback(err)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(err)
-	}
-}
-
-function failOpenAppSettings(options : OpenAppSettingsOptions, err : PermissionFailImpl) {
-	const failCallback = options.fail
-	if (failCallback != null) {
-		failCallback(err)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(err)
-	}
-}
-
-function succeedOpenAppSettings(options : OpenAppSettingsOptions, res : PermissionCheckResult) {
-	const successCallback = options.success
-	if (successCallback != null) {
-		successCallback(res)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(res)
-	}
-}
-
-export const checkPermissionSync : CheckPermissionSync = function (permission : PermissionKey) : PermissionCheckResult {
-	return createCheckResult(permission, checkHarmonyPermissionStatus(permission))
-}
-
-export const checkPermissionsSync : CheckPermissionsSync = function (permissions : PermissionKey[]) : CheckPermissionsResult {
-	const results : PermissionCheckResult[] = []
-	let allGranted = true
-	for (let i = 0; i < permissions.length; i++) {
-		const item = checkPermissionSync(permissions[i])
-		results.push(item)
-		if (!item.granted) {
-			allGranted = false
-		}
-	}
-	return {
-		results: results,
-		allGranted: allGranted,
-	}
-}
-
-export const checkPermission : CheckPermission = function (options : CheckPermissionOptions) {
-	succeedCheckPermission(options, checkPermissionSync(options.permission))
-}
-
-export const checkPermissions : CheckPermissions = function (options : CheckPermissionsOptions) {
-	succeedCheckPermissions(options, checkPermissionsSync(options.permissions))
-}
-
-export const requestPermission : RequestPermission = function (options : RequestPermissionOptions) {
-	if (isHarmonyUnsupported(options.permission)) {
-		failRequestPermission(options, new PermissionFailImpl(9020003))
-		return
-	}
-
-	if (isHarmonyAclUndeclared(options.permission)) {
-		failRequestPermission(options, new PermissionFailImpl(9020003, createAclUndeclaredMessage(options.permission)))
-		return
-	}
-
-	const currentStatus = checkHarmonyPermissionStatus(options.permission)
-	if (currentStatus == 'granted') {
-		succeedRequestPermission(options, createGrantResult(options.permission, 'granted'))
-		return
-	}
-
-	const harmonyPermission = resolveHarmonyPermission(options.permission)
-	if (harmonyPermission == null) {
-		failRequestPermission(options, new PermissionFailImpl(9020003))
-		return
-	}
-
-	const context = getAbilityContext()
-	if (context == null) {
-		failRequestPermission(options, new PermissionFailImpl(9020006, 'UIAbilityContext 不可用'))
-		return
-	}
-
-	const atManager = abilityAccessCtrl.createAtManager()
-	const permissionList : Array<Permissions> = [harmonyPermission]
-	atManager.requestPermissionsFromUser(context, permissionList,
-		(err : BusinessError, result : AtManagerPermissionResult) => {
-			if (err != null) {
-				succeedRequestPermission(options, createGrantResult(options.permission, 'denied'))
-				return
-			}
-			if (result.authResults.length > 0
-				&& result.authResults[0] == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
-				succeedRequestPermission(options, createGrantResult(options.permission, 'granted'))
-				return
-			}
-			succeedRequestPermission(options, createGrantResult(options.permission, 'denied'))
-		})
-}
-
-export const requestPermissions : RequestPermissions = function (options : RequestPermissionsOptions) {
-	const permissions = options.permissions
-	if (permissions.length == 0) {
-		const emptyResult : RequestPermissionsResult = {
-			results: [],
-			allGranted: true,
-		}
-		succeedRequestPermissions(options, emptyResult)
-		return
-	}
-
-	const context = getAbilityContext()
-	if (context == null) {
-		failRequestPermissions(options, new PermissionFailImpl(9020006, 'UIAbilityContext 不可用'))
-		return
-	}
-
-	const harmonyPermissions : Array<Permissions> = []
-	const permissionKeys : PermissionKey[] = []
-	for (let i = 0; i < permissions.length; i++) {
-		const key = permissions[i]
-		if (isHarmonyUnsupported(key)) {
-			continue
-		}
-		const harmonyPermission = resolveHarmonyPermission(key)
-		if (harmonyPermission != null) {
-			harmonyPermissions.push(harmonyPermission)
-			permissionKeys.push(key)
-		}
-	}
-
-	if (harmonyPermissions.length == 0) {
-		failRequestPermissions(options, new PermissionFailImpl(9020003))
-		return
-	}
-
-	const atManager = abilityAccessCtrl.createAtManager()
-	atManager.requestPermissionsFromUser(context, harmonyPermissions,
-		(err : BusinessError, result : AtManagerPermissionResult) => {
-			const collectedResults : PermissionGrantResult[] = []
-			let allGranted = true
-
-			if (err != null) {
-				for (let i = 0; i < permissionKeys.length; i++) {
-					collectedResults.push(createGrantResult(permissionKeys[i], 'denied'))
-				}
-				allGranted = false
-			} else {
-				for (let i = 0; i < permissionKeys.length; i++) {
-					const granted = i < result.authResults.length
-						&& result.authResults[i] == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED
-					const status : PermissionStatus = granted ? 'granted' : 'denied'
-					collectedResults.push(createGrantResult(permissionKeys[i], status))
-					if (!granted) {
-						allGranted = false
-					}
-				}
-			}
-
-			const finalResult : RequestPermissionsResult = {
-				results: collectedResults,
-				allGranted: allGranted,
-			}
-			succeedRequestPermissions(options, finalResult)
-		})
-}
-
-export const openAppSettings : OpenAppSettings = function (options : OpenAppSettingsOptions) {
-	const context = getAbilityContext()
-	if (context == null) {
-		failOpenAppSettings(options, new PermissionFailImpl(9020004, 'UIAbilityContext 不可用'))
-		return
-	}
-
-	const wantInfo : Want = {
-		bundleName: 'com.huawei.hmos.settings',
-		abilityName: 'com.huawei.hmos.settings.MainAbility',
-		uri: 'application_info_entry',
-		parameters: {
-			pushParams: context.abilityInfo.bundleName,
-		},
-	}
-
-	context.startAbility(wantInfo).then(() => {
-		const resultPermission = options.permission != null ? options.permission! : 'camera'
-		succeedOpenAppSettings(options, createCheckResult(resultPermission, 'granted'))
-	}).catch((_err : BusinessError) => {
-		failOpenAppSettings(options, new PermissionFailImpl(9020004))
-	})
-}
-
-export const getSupportedPermissionsSync : GetSupportedPermissionsSync = function () : GetSupportedPermissionsResult {
-	return {
-		permissions: SUPPORTED_PERMISSIONS,
-	}
-}
-
-function mapHarmonyBluetoothState(state : access.BluetoothState) : string {
-	switch (state) {
-		case access.BluetoothState.STATE_OFF:
-			return '已关闭'
-		case access.BluetoothState.STATE_TURNING_ON:
-			return '正在打开'
-		case access.BluetoothState.STATE_ON:
-			return '已开启'
-		case access.BluetoothState.STATE_TURNING_OFF:
-			return '正在关闭'
-		case access.BluetoothState.STATE_BLE_TURNING_ON:
-			return 'BLE 正在打开'
-		case access.BluetoothState.STATE_BLE_ON:
-			return 'BLE 已开启'
-		case access.BluetoothState.STATE_BLE_TURNING_OFF:
-			return 'BLE 正在关闭'
-		default:
-			return '未知'
-	}
-}
-
-function isHarmonyBluetoothEnabled(state : access.BluetoothState) : boolean {
-	return state == access.BluetoothState.STATE_ON
-		|| state == access.BluetoothState.STATE_BLE_ON
-}
-
-export const getBluetoothDemoInfoSync : GetBluetoothDemoInfoSync = function () : BluetoothDemoInfo {
-	try {
-		const state = access.getState()
-		return {
-			available: true,
-			enabled: isHarmonyBluetoothEnabled(state),
-			stateText: mapHarmonyBluetoothState(state),
-			stateCode: state as number,
-		}
-	} catch (err) {
-		let message = '读取蓝牙状态失败'
-		if (err != null && typeof err === 'object') {
-			const errObj = err as BusinessError
-			if (errObj.message != null && errObj.message.length > 0) {
-				message = errObj.message
-			}
-		}
-		return {
-			available: false,
-			enabled: false,
-			stateText: message,
-			stateCode: -1,
-		}
-	}
-}

+ 0 - 78
uni_modules/m-permission-manager/utssdk/app-harmony/module.full.json5

@@ -1,78 +0,0 @@
-{
-	"module": {
-		"requestPermissions": [
-			{
-				"name": "ohos.permission.CAMERA",
-				"reason": "$string:permission_camera_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			},
-			{
-				"name": "ohos.permission.MICROPHONE",
-				"reason": "$string:permission_microphone_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			},
-			{
-				"name": "ohos.permission.LOCATION",
-				"reason": "$string:permission_location_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			},
-			{
-				"name": "ohos.permission.APPROXIMATELY_LOCATION",
-				"reason": "$string:permission_coarse_location_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			},
-			{
-				"name": "ohos.permission.ACCESS_BLUETOOTH",
-				"reason": "$string:permission_bluetooth_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			},
-			{
-				"name": "ohos.permission.READ_IMAGEVIDEO",
-				"reason": "$string:permission_read_storage_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			},
-			{
-				"name": "ohos.permission.WRITE_IMAGEVIDEO",
-				"reason": "$string:permission_write_storage_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			},
-			{
-				"name": "ohos.permission.READ_CONTACTS",
-				"reason": "$string:permission_contacts_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			},
-			{
-				"name": "ohos.permission.WRITE_CONTACTS",
-				"reason": "$string:permission_write_contacts_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			}
-		]
-	}
-}

+ 0 - 46
uni_modules/m-permission-manager/utssdk/app-harmony/module.json5

@@ -1,46 +0,0 @@
-{
-	"module": {
-		"requestPermissions": [
-			{
-				"name": "ohos.permission.CAMERA",
-				"reason": "$string:permission_camera_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			},
-			{
-				"name": "ohos.permission.MICROPHONE",
-				"reason": "$string:permission_microphone_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			},
-			{
-				"name": "ohos.permission.LOCATION",
-				"reason": "$string:permission_location_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			},
-			{
-				"name": "ohos.permission.APPROXIMATELY_LOCATION",
-				"reason": "$string:permission_coarse_location_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			},
-			{
-				"name": "ohos.permission.ACCESS_BLUETOOTH",
-				"reason": "$string:permission_bluetooth_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			}
-		]
-	}
-}

+ 0 - 46
uni_modules/m-permission-manager/utssdk/app-harmony/module.normal.json5

@@ -1,46 +0,0 @@
-{
-	"module": {
-		"requestPermissions": [
-			{
-				"name": "ohos.permission.CAMERA",
-				"reason": "$string:permission_camera_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			},
-			{
-				"name": "ohos.permission.MICROPHONE",
-				"reason": "$string:permission_microphone_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			},
-			{
-				"name": "ohos.permission.LOCATION",
-				"reason": "$string:permission_location_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			},
-			{
-				"name": "ohos.permission.APPROXIMATELY_LOCATION",
-				"reason": "$string:permission_coarse_location_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			},
-			{
-				"name": "ohos.permission.ACCESS_BLUETOOTH",
-				"reason": "$string:permission_bluetooth_reason",
-				"usedScene": {
-					"abilities": ["EntryAbility"],
-					"when": "inuse"
-				}
-			}
-		]
-	}
-}

+ 0 - 40
uni_modules/m-permission-manager/utssdk/app-harmony/resources/base/element/string.json

@@ -1,40 +0,0 @@
-{
-	"string": [
-		{
-			"name": "permission_camera_reason",
-			"value": "需要使用相机进行拍照或扫码"
-		},
-		{
-			"name": "permission_microphone_reason",
-			"value": "需要使用麦克风进行录音或语音输入"
-		},
-		{
-			"name": "permission_location_reason",
-			"value": "需要获取位置信息以提供定位相关服务"
-		},
-		{
-			"name": "permission_coarse_location_reason",
-			"value": "需要获取大致位置信息以提供定位相关服务"
-		},
-		{
-			"name": "permission_bluetooth_reason",
-			"value": "需要使用蓝牙连接周边设备"
-		},
-		{
-			"name": "permission_read_storage_reason",
-			"value": "需要读取相册或媒体文件"
-		},
-		{
-			"name": "permission_write_storage_reason",
-			"value": "需要保存文件到相册或媒体目录"
-		},
-		{
-			"name": "permission_contacts_reason",
-			"value": "需要读取通讯录以提供联系人相关功能"
-		},
-		{
-			"name": "permission_write_contacts_reason",
-			"value": "需要写入通讯录以保存联系人信息"
-		}
-	]
-}

+ 0 - 11
uni_modules/m-permission-manager/utssdk/app-ios/config.json

@@ -1,11 +0,0 @@
-{
-	"deploymentTarget": "14.0",
-	"frameworks": [
-		"AVFoundation.framework",
-		"Photos.framework",
-		"CoreLocation.framework",
-		"Contacts.framework",
-		"CoreBluetooth.framework"
-	],
-	"dependencies": []
-}

+ 0 - 535
uni_modules/m-permission-manager/utssdk/app-ios/index.uts

@@ -1,535 +0,0 @@
-import { AVCaptureDevice, AVMediaType, AVAuthorizationStatus } from 'AVFoundation'
-import { AVAudioSession } from 'AVFoundation'
-import { PHPhotoLibrary, PHAuthorizationStatus } from 'Photos'
-import { CLLocationManager, CLAuthorizationStatus } from 'CoreLocation'
-import { CNContactStore, CNAuthorizationStatus, CNEntityType } from 'Contacts'
-import { CBManager, CBManagerAuthorization, CBCentralManager, CBManagerState } from 'CoreBluetooth'
-import { UIApplication } from 'UIKit'
-import { DispatchQueue } from 'Dispatch'
-import { NSError, URL } from 'Foundation'
-import {
-	BluetoothDemoInfo,
-	CheckPermission,
-	CheckPermissionOptions,
-	CheckPermissions,
-	CheckPermissionsOptions,
-	CheckPermissionsResult,
-	CheckPermissionsSync,
-	CheckPermissionSync,
-	GetSupportedPermissionsResult,
-	GetSupportedPermissionsSync,
-	GetBluetoothDemoInfoSync,
-	OpenAppSettings,
-	OpenAppSettingsOptions,
-	PermissionCheckResult,
-	PermissionKey,
-	PermissionGrantResult,
-	PermissionStatus,
-	RequestPermission,
-	RequestPermissionOptions,
-	RequestPermissions,
-	RequestPermissionsOptions,
-	RequestPermissionsResult,
-} from '../interface.uts'
-import { PermissionFailImpl } from '../unierror'
-
-const SUPPORTED_PERMISSIONS : PermissionKey[] = [
-	'camera',
-	'photoLibrary',
-	'storage',
-	'readStorage',
-	'location',
-	'coarseLocation',
-	'microphone',
-	'contacts',
-	'writeContacts',
-	'bluetooth',
-]
-
-let locationManager : CLLocationManager | null = null
-let pendingLocationOptions : RequestPermissionOptions | null = null
-
-function createCheckResult(permission : PermissionKey, status : PermissionStatus) : PermissionCheckResult {
-	return {
-		permission: permission,
-		status: status,
-		granted: status == 'granted',
-	}
-}
-
-function createRequestResult(permission : PermissionKey, status : PermissionStatus) : PermissionGrantResult {
-	return {
-		permission: permission,
-		status: status,
-		granted: status == 'granted',
-	}
-}
-
-function isIosUnsupported(permission : PermissionKey) : boolean {
-	return permission == 'phone'
-		|| permission == 'phoneState'
-		|| permission == 'sms'
-		|| permission == 'readSms'
-		|| permission == 'receiveSms'
-		|| permission == 'overlay'
-		|| permission == 'writeSettings'
-}
-
-function mapPhotoStatus(status : PHAuthorizationStatus) : PermissionStatus {
-	if (status == PHAuthorizationStatus.authorized || status == PHAuthorizationStatus.limited) {
-		return 'granted'
-	}
-	if (status == PHAuthorizationStatus.notDetermined) {
-		return 'notDetermined'
-	}
-	if (status == PHAuthorizationStatus.restricted) {
-		return 'restricted'
-	}
-	return 'denied'
-}
-
-function mapLocationStatus(status : CLAuthorizationStatus) : PermissionStatus {
-	if (status == CLAuthorizationStatus.authorizedWhenInUse || status == CLAuthorizationStatus.authorizedAlways) {
-		return 'granted'
-	}
-	if (status == CLAuthorizationStatus.notDetermined) {
-		return 'notDetermined'
-	}
-	if (status == CLAuthorizationStatus.restricted) {
-		return 'restricted'
-	}
-	return 'denied'
-}
-
-function mapContactStatus(status : CNAuthorizationStatus) : PermissionStatus {
-	if (status == CNAuthorizationStatus.authorized) {
-		return 'granted'
-	}
-	if (status == CNAuthorizationStatus.notDetermined) {
-		return 'notDetermined'
-	}
-	if (status == CNAuthorizationStatus.restricted) {
-		return 'restricted'
-	}
-	return 'denied'
-}
-
-function mapBluetoothStatus(status : CBManagerAuthorization) : PermissionStatus {
-	if (status == CBManagerAuthorization.allowedAlways) {
-		return 'granted'
-	}
-	if (status == CBManagerAuthorization.notDetermined) {
-		return 'notDetermined'
-	}
-	if (status == CBManagerAuthorization.restricted) {
-		return 'restricted'
-	}
-	return 'denied'
-}
-
-function resolveCameraPermissionStatus() : PermissionStatus {
-	const status = AVCaptureDevice.authorizationStatus(for = AVMediaType.video)
-	if (status == AVAuthorizationStatus.authorized) {
-		return 'granted'
-	}
-	if (status == AVAuthorizationStatus.notDetermined) {
-		return 'notDetermined'
-	}
-	if (status == AVAuthorizationStatus.restricted) {
-		return 'restricted'
-	}
-	return 'denied'
-}
-
-function resolveMicrophonePermissionStatus() : PermissionStatus {
-	const recordPermission = AVAudioSession.sharedInstance().recordPermission
-	if (recordPermission == AVAudioSession.RecordPermission.granted) {
-		return 'granted'
-	}
-	if (recordPermission == AVAudioSession.RecordPermission.undetermined) {
-		return 'notDetermined'
-	}
-	return 'denied'
-}
-
-function resolvePermissionStatus(permission : PermissionKey) : PermissionStatus {
-	if (isIosUnsupported(permission)) {
-		return 'unsupported'
-	}
-	if (permission == 'camera') {
-		return resolveCameraPermissionStatus()
-	}
-	if (permission == 'photoLibrary' || permission == 'storage' || permission == 'readStorage') {
-		return mapPhotoStatus(PHPhotoLibrary.authorizationStatus())
-	}
-	if (permission == 'location' || permission == 'coarseLocation') {
-		return mapLocationStatus(CLLocationManager.authorizationStatus())
-	}
-	if (permission == 'microphone') {
-		return resolveMicrophonePermissionStatus()
-	}
-	if (permission == 'contacts' || permission == 'writeContacts') {
-		return mapContactStatus(CNContactStore.authorizationStatus(for = CNEntityType.contacts))
-	}
-	if (permission == 'bluetooth') {
-		return mapBluetoothStatus(CBManager.authorization)
-	}
-	return 'unsupported'
-}
-
-function succeedCheckPermission(options : CheckPermissionOptions, res : PermissionCheckResult) {
-	const successCallback = options.success
-	if (successCallback != null) {
-		successCallback(res)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(res)
-	}
-}
-
-function succeedCheckPermissions(options : CheckPermissionsOptions, res : CheckPermissionsResult) {
-	const successCallback = options.success
-	if (successCallback != null) {
-		successCallback(res)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(res)
-	}
-}
-
-function succeedRequestPermission(options : RequestPermissionOptions, res : PermissionGrantResult) {
-	const successCallback = options.success
-	if (successCallback != null) {
-		successCallback(res)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(res)
-	}
-}
-
-function succeedRequestPermissions(options : RequestPermissionsOptions, res : RequestPermissionsResult) {
-	const successCallback = options.success
-	if (successCallback != null) {
-		successCallback(res)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(res)
-	}
-}
-
-function succeedOpenAppSettings(options : OpenAppSettingsOptions, res : PermissionCheckResult) {
-	const successCallback = options.success
-	if (successCallback != null) {
-		successCallback(res)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(res)
-	}
-}
-
-function failRequestPermission(options : RequestPermissionOptions, err : PermissionFailImpl) {
-	const failCallback = options.fail
-	if (failCallback != null) {
-		failCallback(err)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(err)
-	}
-}
-
-function failRequestPermissions(options : RequestPermissionsOptions, err : PermissionFailImpl) {
-	const failCallback = options.fail
-	if (failCallback != null) {
-		failCallback(err)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(err)
-	}
-}
-
-function failOpenAppSettings(options : OpenAppSettingsOptions, err : PermissionFailImpl) {
-	const failCallback = options.fail
-	if (failCallback != null) {
-		failCallback(err)
-	}
-	const completeCallback = options.complete
-	if (completeCallback != null) {
-		completeCallback(err)
-	}
-}
-
-function requestCameraPermission(options : RequestPermissionOptions) {
-	AVCaptureDevice.requestAccess(for = AVMediaType.video, completionHandler = (granted : boolean) => {
-		DispatchQueue.main.async(execute = (): void => {
-			const status : PermissionStatus = granted ? 'granted' : 'denied'
-			succeedRequestPermission(options, createRequestResult(options.permission, status))
-		})
-	})
-}
-
-function requestPhotoPermission(options : RequestPermissionOptions) {
-	PHPhotoLibrary.requestAuthorization((status : PHAuthorizationStatus) => {
-		DispatchQueue.main.async(execute = (): void => {
-			succeedRequestPermission(options, createRequestResult(options.permission, mapPhotoStatus(status)))
-		})
-	})
-}
-
-function requestMicrophonePermission(options : RequestPermissionOptions) {
-	AVAudioSession.sharedInstance().requestRecordPermission((granted : boolean) => {
-		DispatchQueue.main.async(execute = (): void => {
-			const status : PermissionStatus = granted ? 'granted' : 'denied'
-			succeedRequestPermission(options, createRequestResult(options.permission, status))
-		})
-	})
-}
-
-function requestContactsPermission(options : RequestPermissionOptions) {
-	const store = new CNContactStore()
-	store.requestAccess(for = CNEntityType.contacts, completionHandler = (granted : boolean, _ : NSError | null) => {
-		DispatchQueue.main.async(execute = (): void => {
-			const status : PermissionStatus = granted ? 'granted' : 'denied'
-			succeedRequestPermission(options, createRequestResult(options.permission, status))
-		})
-	})
-}
-
-function ensureLocationManager() : CLLocationManager {
-	if (locationManager == null) {
-		locationManager = new CLLocationManager()
-	}
-	return locationManager!
-}
-
-function requestLocationPermission(options : RequestPermissionOptions) {
-	const currentStatus = CLLocationManager.authorizationStatus()
-	if (currentStatus != CLAuthorizationStatus.notDetermined) {
-		succeedRequestPermission(options, createRequestResult(options.permission, mapLocationStatus(currentStatus)))
-		return
-	}
-	pendingLocationOptions = options
-	const manager = ensureLocationManager()
-	manager.requestWhenInUseAuthorization()
-	scheduleLocationPermissionCheck(0)
-}
-
-function scheduleLocationPermissionCheck(attempt : Int) {
-	const maxAttempts : Int = 60
-	DispatchQueue.main.asyncAfter(deadline = DispatchTime.now() + 0.3, execute = (): void => {
-		const options = pendingLocationOptions
-		if (options == null) {
-			return
-		}
-		const authStatus = CLLocationManager.authorizationStatus()
-		if (authStatus == CLAuthorizationStatus.notDetermined) {
-			if (attempt >= maxAttempts) {
-				pendingLocationOptions = null
-				succeedRequestPermission(options, createRequestResult(options.permission, 'denied'))
-				return
-			}
-			scheduleLocationPermissionCheck(attempt + 1)
-			return
-		}
-		pendingLocationOptions = null
-		succeedRequestPermission(options, createRequestResult(options.permission, mapLocationStatus(authStatus)))
-	})
-}
-
-function requestBluetoothPermission(options : RequestPermissionOptions) {
-	const currentStatus = CBManager.authorization
-	if (currentStatus != CBManagerAuthorization.notDetermined) {
-		succeedRequestPermission(options, createRequestResult(options.permission, mapBluetoothStatus(currentStatus)))
-		return
-	}
-	// 创建 CBCentralManager 实例会触发系统蓝牙权限弹窗
-	const _centralManager = new CBCentralManager()
-	DispatchQueue.main.async(execute = (): void => {
-		succeedRequestPermission(options, createRequestResult(options.permission, mapBluetoothStatus(CBManager.authorization)))
-	})
-}
-
-export const checkPermissionSync : CheckPermissionSync = function (permission : PermissionKey) : PermissionCheckResult {
-	return createCheckResult(permission, resolvePermissionStatus(permission))
-}
-
-export const checkPermissionsSync : CheckPermissionsSync = function (permissions : PermissionKey[]) : CheckPermissionsResult {
-	const results : PermissionCheckResult[] = []
-	let allGranted = true
-	for (let i = 0; i < permissions.length; i++) {
-		const item = checkPermissionSync(permissions[i])
-		results.push(item)
-		if (!item.granted) {
-			allGranted = false
-		}
-	}
-	return {
-		results: results,
-		allGranted: allGranted,
-	}
-}
-
-export const checkPermission : CheckPermission = function (options : CheckPermissionOptions) {
-	succeedCheckPermission(options, checkPermissionSync(options.permission))
-}
-
-export const checkPermissions : CheckPermissions = function (options : CheckPermissionsOptions) {
-	succeedCheckPermissions(options, checkPermissionsSync(options.permissions))
-}
-
-export const requestPermission : RequestPermission = function (options : RequestPermissionOptions) {
-	if (isIosUnsupported(options.permission)) {
-		failRequestPermission(options, new PermissionFailImpl(9020003))
-		return
-	}
-
-	const currentStatus = resolvePermissionStatus(options.permission)
-	if (currentStatus == 'granted') {
-		succeedRequestPermission(options, createRequestResult(options.permission, 'granted'))
-		return
-	}
-	if (currentStatus == 'restricted') {
-		succeedRequestPermission(options, createRequestResult(options.permission, 'restricted'))
-		return
-	}
-
-	switch (options.permission) {
-		case 'camera':
-			requestCameraPermission(options)
-			break
-		case 'photoLibrary':
-		case 'storage':
-		case 'readStorage':
-			requestPhotoPermission(options)
-			break
-		case 'location':
-		case 'coarseLocation':
-			requestLocationPermission(options)
-			break
-		case 'microphone':
-			requestMicrophonePermission(options)
-			break
-		case 'contacts':
-		case 'writeContacts':
-			requestContactsPermission(options)
-			break
-		case 'bluetooth':
-			requestBluetoothPermission(options)
-			break
-		default:
-			failRequestPermission(options, new PermissionFailImpl(9020003))
-	}
-}
-
-export const requestPermissions : RequestPermissions = function (options : RequestPermissionsOptions) {
-	const permissions = options.permissions
-	if (permissions == null) {
-		const emptyResult : RequestPermissionsResult = {
-			results: [],
-			allGranted: true,
-		}
-		succeedRequestPermissions(options, emptyResult)
-		return
-	}
-	const permissionList = permissions!
-	if (permissionList.length == 0) {
-		const emptyResult : RequestPermissionsResult = {
-			results: [],
-			allGranted: true,
-		}
-		succeedRequestPermissions(options, emptyResult)
-		return
-	}
-
-	let currentIndex = 0
-	const collectedResults : PermissionGrantResult[] = []
-
-	function requestNext() {
-		if (currentIndex >= permissionList.length) {
-			let allGranted = true
-			for (let i = 0; i < collectedResults.length; i++) {
-				if (!collectedResults[i].granted) {
-					allGranted = false
-					break
-				}
-			}
-			const finalResult : RequestPermissionsResult = {
-				results: collectedResults,
-				allGranted: allGranted,
-			}
-			succeedRequestPermissions(options, finalResult)
-			return
-		}
-
-		const permission = permissionList[currentIndex]
-		currentIndex += 1
-		requestPermission({
-			permission: permission,
-			success: (res : PermissionGrantResult) => {
-				collectedResults.push(res)
-				requestNext()
-			},
-			fail: (err : PermissionFailImpl) => {
-				collectedResults.push(createRequestResult(permission, 'denied'))
-				failRequestPermissions(options, err)
-			},
-		})
-	}
-
-	requestNext()
-}
-
-export const openAppSettings : OpenAppSettings = function (options : OpenAppSettingsOptions) {
-	const settingsUrl = URL(string = UIApplication.openSettingsURLString)
-	if (settingsUrl == null) {
-		failOpenAppSettings(options, new PermissionFailImpl(9020004))
-		return
-	}
-	DispatchQueue.main.async(execute = (): void => {
-		UIApplication.shared.open(settingsUrl!)
-		const resultPermission = options.permission != null ? options.permission! : 'camera'
-		succeedOpenAppSettings(options, createCheckResult(resultPermission, 'granted'))
-	})
-}
-
-export const getSupportedPermissionsSync : GetSupportedPermissionsSync = function () : GetSupportedPermissionsResult {
-	return {
-		permissions: SUPPORTED_PERMISSIONS,
-	}
-}
-
-function mapIOSBluetoothState(state : CBManagerState) : string {
-	switch (state) {
-		case CBManagerState.poweredOn:
-			return '已开启'
-		case CBManagerState.poweredOff:
-			return '已关闭'
-		case CBManagerState.unsupported:
-			return '不支持'
-		case CBManagerState.unauthorized:
-			return '未授权'
-		case CBManagerState.resetting:
-			return '重置中'
-		case CBManagerState.unknown:
-			return '未知'
-		default:
-			return '未知'
-	}
-}
-
-export const getBluetoothDemoInfoSync : GetBluetoothDemoInfoSync = function () : BluetoothDemoInfo {
-	const manager = new CBCentralManager()
-	const state = manager.state
-	return {
-		available: state != CBManagerState.unsupported,
-		enabled: state == CBManagerState.poweredOn,
-		stateText: mapIOSBluetoothState(state),
-		stateCode: state as number,
-	}
-}

+ 0 - 125
uni_modules/m-permission-manager/utssdk/interface.uts

@@ -1,125 +0,0 @@
-/**
- * m-permission-manager 跨平台权限管理接口
- */
-
-/** 统一权限标识,三端通用 */
-export type PermissionKey =
-	| 'camera'
-	| 'photoLibrary'
-	| 'storage'
-	| 'readStorage'
-	| 'location'
-	| 'coarseLocation'
-	| 'microphone'
-	| 'contacts'
-	| 'writeContacts'
-	| 'bluetooth'
-	| 'phone'
-	| 'phoneState'
-	| 'sms'
-	| 'readSms'
-	| 'receiveSms'
-	| 'overlay'
-	| 'writeSettings'
-
-export type PermissionStatus =
-	| 'granted'
-	| 'denied'
-	| 'notDetermined'
-	| 'restricted'
-	| 'unsupported'
-
-export type PermissionCheckResult = {
-	permission : PermissionKey
-	status : PermissionStatus
-	granted : boolean
-}
-
-export type PermissionGrantResult = {
-	permission : PermissionKey
-	status : PermissionStatus
-	granted : boolean
-}
-
-export type CheckPermissionsResult = {
-	results : PermissionCheckResult[]
-	allGranted : boolean
-}
-
-export type RequestPermissionsResult = {
-	results : PermissionGrantResult[]
-	allGranted : boolean
-}
-
-export type CheckPermissionOptions = {
-	permission : PermissionKey
-	success ?: (res : PermissionCheckResult) => void
-	fail ?: (res : PermissionFail) => void
-	complete ?: (res : any) => void
-}
-
-export type CheckPermissionsOptions = {
-	permissions : PermissionKey[]
-	success ?: (res : CheckPermissionsResult) => void
-	fail ?: (res : PermissionFail) => void
-	complete ?: (res : any) => void
-}
-
-export type RequestPermissionOptions = {
-	permission : PermissionKey
-	success ?: (res : PermissionGrantResult) => void
-	fail ?: (res : PermissionFail) => void
-	complete ?: (res : any) => void
-}
-
-export type RequestPermissionsOptions = {
-	permissions : PermissionKey[]
-	success ?: (res : RequestPermissionsResult) => void
-	fail ?: (res : PermissionFail) => void
-	complete ?: (res : any) => void
-}
-
-export type OpenAppSettingsOptions = {
-	/** 指定权限类型,各端将尽量跳转到对应设置页 */
-	permission ?: PermissionKey
-	success ?: (res : PermissionCheckResult) => void
-	fail ?: (res : PermissionFail) => void
-	complete ?: (res : any) => void
-}
-
-export type GetSupportedPermissionsResult = {
-	permissions : PermissionKey[]
-}
-
-/**
- * 9020001 当前环境不支持
- * 9020002 用户拒绝授权
- * 9020003 权限不支持当前平台
- * 9020004 打开系统设置失败
- * 9020005 权限检查失败
- * 9020006 权限申请失败
- */
-export type PermissionErrorCode = 9020001 | 9020002 | 9020003 | 9020004 | 9020005 | 9020006
-
-export interface PermissionFail extends IUniError {
-	errCode : PermissionErrorCode
-}
-
-export type CheckPermissionSync = (permission : PermissionKey) => PermissionCheckResult
-export type CheckPermissionsSync = (permissions : PermissionKey[]) => CheckPermissionsResult
-export type CheckPermission = (options : CheckPermissionOptions) => void
-export type CheckPermissions = (options : CheckPermissionsOptions) => void
-export type RequestPermission = (options : RequestPermissionOptions) => void
-export type RequestPermissions = (options : RequestPermissionsOptions) => void
-export type OpenAppSettings = (options : OpenAppSettingsOptions) => void
-export type GetSupportedPermissionsSync = () => GetSupportedPermissionsResult
-
-/** 蓝牙演示信息(读取系统蓝牙开关状态) */
-export type BluetoothDemoInfo = {
-	available : boolean
-	enabled : boolean
-	stateText : string
-	stateCode : number
-}
-
-export type GetBluetoothDemoInfoSync = () => BluetoothDemoInfo

+ 0 - 23
uni_modules/m-permission-manager/utssdk/unierror.uts

@@ -1,23 +0,0 @@
-import { PermissionErrorCode, PermissionFail } from './interface.uts'
-
-export const UniErrorSubject = 'm-permission-manager'
-
-export const PermissionUniErrors : Map<PermissionErrorCode, string> = new Map([
-	[9020001, '当前环境不支持权限管理'],
-	[9020002, '用户拒绝授权'],
-	[9020003, '权限不支持当前平台'],
-	[9020004, '打开系统设置失败'],
-	[9020005, '权限检查失败'],
-	[9020006, '权限申请失败'],
-])
-
-export class PermissionFailImpl extends UniError implements PermissionFail {
-	override errCode : PermissionErrorCode
-
-	constructor(errCode : PermissionErrorCode, errMsg : string = '') {
-		super()
-		this.errSubject = UniErrorSubject
-		this.errCode = errCode
-		this.errMsg = errMsg.length > 0 ? errMsg : (PermissionUniErrors.get(errCode) ?? '')
-	}
-}

+ 0 - 220
uni_modules/m-permission-manager/使用规范.md

@@ -1,220 +0,0 @@
-# m-permission-manager 使用规范
-
-本文档面向集成本插件的 App 开发者,说明 **必须遵守的约束**、**推荐做法** 和 **上架审核注意事项**。
-
----
-
-## 1. 基本约束(必须遵守)
-
-### 1.1 用户主动触发
-
-`requestPermission` / `requestPermissions` **必须由真实用户手势触发**,例如按钮 `click` / `tap`。
-
-```vue
-<!-- ✅ 正确 -->
-<button @click="handleRequestCamera">申请相机权限</button>
-
-<!-- ❌ 错误:页面 onLoad / onShow 自动批量申请 -->
-<script setup>
-onMounted(async () => {
-  await requestPermissions(['camera', 'microphone', 'location']) // 体验差,可能被系统限制
-})
-</script>
-```
-
-原因:Android / iOS / Harmony 运行时权限弹窗均面向用户明确操作;冷启动批量申请易触发拒绝,且不符合各应用商店审核惯例。
-
-### 1.2 先声明、后申请
-
-**仅安装插件不够**,必须在各端配置文件中声明所需权限,否则:
-
-| 平台 | 未声明后果 |
-| --- | --- |
-| Android | `SecurityException`、申请无弹窗或直接失败 |
-| iOS | 崩溃或无授权弹窗 |
-| Harmony | 系统设置无对应开关,插件返回 `restricted` 或 9020003 |
-
-详细配置见 [权限配置说明.md](./权限配置说明.md)。
-
-### 1.3 按需申请
-
-只申请业务实际使用的权限。在功能入口处按需 `requestPermission`,不要一次性申请全部权限。
-
-```js
-// ✅ 审核页
-async function handleRequestCamera() {
-  const granted = await requestPermission('camera')
-  if (!granted) {
-    uni.showModal({
-      title: '需要相机权限',
-      content: getPermissionSettingsGuide('camera', '相机'),
-      confirmText: '去设置',
-      success: (res) => {
-        if (res.confirm) openPermissionSettings('camera')
-      },
-    })
-    return
-  }
-  // 继续业务逻辑
-}
-```
-
-### 1.4 平台差异处理
-
-调用前可通过 `getSupportedPermissions()` 过滤当前平台不支持的 Key,避免向用户展示无效入口。
-
-```js
-const supported = getSupportedPermissions()
-const canUseOverlay = supported.includes('overlay') // 仅 Android 为 true
-```
-
----
-
-## 2. 推荐集成流程
-
-```
-进入功能页
-    ↓
-checkPermission(key) ──→ granted → 执行业务
-    ↓ notDetermined / denied
-用户点击「申请权限」
-    ↓
-requestPermission(key)
-    ↓
-系统弹窗 ──→ 拒绝 → getPermissionSettingsGuide + openPermissionSettings
-    ↓ 同意
-granted → 执行业务
-```
-
-### 2.1 Promise 封装(推荐)
-
-项目可复用 `@/utils/permission-manager.js`:
-
-```js
-import {
-  checkPermission,
-  requestPermission,
-  requestPermissions,
-  openPermissionSettings,
-  getPermissionSettingsGuide,
-  ensurePermission,
-  getSupportedPermissions,
-} from '@/utils/permission-manager'
-```
-
-| 方法 | 用途 |
-| --- | --- |
-| `checkPermission(key)` | 检查状态,返回 `{ granted, status }` |
-| `requestPermission(key)` | 申请权限,返回 `boolean` |
-| `requestPermissions(keys[])` | 批量申请,返回 `{ allGranted, results }` |
-| `openPermissionSettings(key)` | 按权限类型跳转系统设置 |
-| `getPermissionSettingsGuide(key, label)` | 获取跳转前的引导文案 |
-| `ensurePermission(key, { openSettings })` | 检查 → 申请 → 可选跳转设置 |
-
-### 2.2 直接调用 UTS API(callback 风格)
-
-```js
-import { requestPermission } from '@/uni_modules/m-permission-manager'
-
-requestPermission({
-  permission: 'camera',
-  success(res) {
-    if (res.granted) { /* ... */ }
-  },
-  fail(err) {
-    console.error(err.errCode, err.errMsg)
-  },
-})
-```
-
-### 2.3 永久拒绝后的引导
-
-用户选择「不再询问」或多次拒绝后,应引导至系统设置:
-
-```js
-const granted = await requestPermission('bluetooth')
-if (!granted) {
-  uni.showModal({
-    title: '蓝牙权限未授予',
-    content: getPermissionSettingsGuide('bluetooth', '蓝牙'),
-    confirmText: '去设置',
-    success: (res) => {
-      if (res.confirm) openPermissionSettings('bluetooth')
-    },
-  })
-}
-```
-
-各端跳转行为:
-
-| 平台 | `openPermissionSettings` 行为 |
-| --- | --- |
-| Android 普通权限 | 应用详情 → 权限列表 |
-| Android `overlay` | 悬浮窗权限设置页 |
-| Android `writeSettings` | 修改系统设置权限页 |
-| iOS | 本 App 设置页(需 manifest 声明对应 UsageDescription) |
-| Harmony | 系统设置 → 应用详情 |
-
----
-
-## 3. 各端特别注意
-
-### 3.1 Android
-
-- **Android 13+**:相册 / 存储自动映射 `READ_MEDIA_IMAGES` / `READ_MEDIA_VIDEO`
-- **Android 12+**:蓝牙自动映射 `BLUETOOTH_CONNECT` / `BLUETOOTH_SCAN`
-- **特殊权限**:`overlay`、`writeSettings` 需跳转系统设置页,申请结果可能为 `notDetermined`,返回后需再次 `checkPermission`
-
-### 3.2 iOS
-
-- 必须在 `privacyDescription` 中配置对应 `NS*UsageDescription`,否则无弹窗
-- `storage` / `readStorage` 映射到相册权限(`PHPhotoLibrary`)
-- `coarseLocation` / `location` 均映射到定位授权
-- **蓝牙**:需 `NSBluetoothAlwaysUsageDescription`;系统蓝牙开关在「设置 → 蓝牙」,App 授权在 App 设置页或「隐私与安全性 → 蓝牙」
-
-### 3.3 Harmony
-
-- 默认 `module.json5` 含 5 项 normal 权限,调试包可直接安装
-- 相册 / 通讯录为 `system_basic`,需 ACL 签名 + `module.full.json5`
-- 相册选图推荐 `uni.chooseImage`(系统 PhotoViewPicker),无需媒体读写权限
-- 未声明的 ACL 权限:检查返回 `restricted`,申请返回 9020003
-
----
-
-## 4. 错误码与用户提示
-
-| errCode | 含义 | 建议提示 |
-| --- | --- | --- |
-| 9020001 | 当前环境不支持 | 请在 App 端使用 |
-| 9020002 | 用户拒绝授权 | 您拒绝了授权,可在设置中重新开启 |
-| 9020003 | 权限不支持当前平台 | 当前平台不支持该权限 |
-| 9020004 | 打开系统设置失败 | 无法打开系统设置,请手动前往 |
-| 9020005 | 权限检查失败 | 权限检查失败,请重试 |
-| 9020006 | 权限申请失败 | 权限申请失败,请重试 |
-
----
-
-## 5. 上架审核注意事项
-
-| 市场 | 注意点 |
-| --- | --- |
-| App Store | 每个 `NS*UsageDescription` 文案需与真实功能一致;不要申请未使用的权限 |
-| Google Play | 需在 Data safety 中声明权限用途;Android 13+ 媒体权限需按类型声明 |
-| 华为 / 鸿蒙 | 说明 `ohos.permission.*` 用途;system_basic 权限需 ACL 白名单 |
-| 国内 Android 市场 | 隐私合规检测会扫描 manifest 权限列表,确保与隐私政策一致 |
-
----
-
-## 6. 自定义基座与发版
-
-1. 导入或更新插件后,**必须重新制作自定义基座**或云打包
-2. 修改 `manifest.json` 权限或鸿蒙 `module.json5` 后,需重新打包
-3. iOS 修改 `privacyDescription` 后需重新打包,必要时删除旧 App 重装以重新触发授权弹窗
-
----
-
-## 7. 参考文档
-
-- [readme.md](./readme.md) — API 与快速开始
-- [权限配置说明.md](./权限配置说明.md) — 三端权限文件配置详解
-- [发布指南.md](./发布指南.md) — 插件市场发布填写参考

+ 0 - 227
uni_modules/m-permission-manager/发布指南.md

@@ -1,227 +0,0 @@
-# m-permission-manager 插件发布指南
-
-面向插件作者,说明如何将本插件提交到 DCloud 插件市场,以及后台各字段的填写参考。
-
----
-
-## 发布前检查清单
-
-### 代码与文档
-
-- [ ] `package.json` 中 `id`、`version`、`description`、`keywords` 已填写
-- [ ] `dcloudext.type` 为 `uts`
-- [ ] `dcloudext.declaration` 中 ads / data / permissions 已如实填写
-- [ ] `uni_modules.platforms` 中各端支持情况准确(vue3=y,H5/小程序=x)
-- [ ] `readme.md` 完整(安装、API、权限、FAQ)
-- [ ] `使用规范.md`、`权限配置说明.md`、`changelog.md` 已更新
-- [ ] `index.d.ts` 与 `index.js` 导出一致
-
-### 功能验证
-
-- [ ] Android 真机:相机 / 麦克风 / 定位 / 蓝牙申请与检查
-- [ ] Android 12+ 真机:蓝牙 `BLUETOOTH_CONNECT` / `BLUETOOTH_SCAN`
-- [ ] Android 13+ 真机:相册 `READ_MEDIA_IMAGES` 自动映射
-- [ ] Android 真机:悬浮窗(`overlay`)、修改系统设置(`writeSettings`)跳转设置页
-- [ ] iOS 14+ 真机:相机 / 麦克风 / 定位 / 蓝牙 / 相册
-- [ ] iOS 真机:拒绝后 `openPermissionSettings('bluetooth')` 引导文案正确
-- [ ] Harmony API 12+ 真机:5 项 normal 权限申请(默认 `module.json5`)
-- [ ] Harmony 真机:相册 ACL 未声明时返回 `restricted` / 9020003
-- [ ] 拒绝授权时引导跳转系统设置
-- [ ] H5 环境明确不可用(9020001)
-
-### 打包验证
-
-- [ ] 自定义基座可正常运行
-- [ ] 云打包 / 本地打包正式包可正常运行
-- [ ] 修改 UTS 代码后已重新制作基座
-
----
-
-## 提交到插件市场
-
-1. 登录 [DCloud 插件市场](https://ext.dcloud.net.cn/)
-2. 进入 **我的插件** → **发布插件**
-3. 插件类型选择 **UTS 插件**
-4. 上传 `uni_modules/m-permission-manager` 目录(或打包 zip)
-5. 按下方表格填写市场展示信息
-
----
-
-## 市场后台填写参考
-
-### 基本信息
-
-| 字段 | 填写内容 |
-| --- | --- |
-| **插件名称** | m-permission-manager 跨端权限管理 |
-| **插件 ID** | m-permission-manager |
-| **插件类型** | UTS 插件 |
-| **价格** | 免费(或按实际定价) |
-| **版本号** | 与 `package.json` → `version` 一致,如 `1.0.0` |
-
-### 标题(建议)
-
-```
-m-permission-manager - uni-app 跨端权限管理(Android/iOS/鸿蒙)
-```
-
-### 一句话描述
-
-```
-UTS 权限插件,Android / iOS / Harmony 三端统一 API,检查与申请运行时权限,支持跳转系统设置。
-```
-
-### 详细描述(可直接粘贴)
-
-```
-m-permission-manager 是 uni-app Vue3 跨端权限管理 UTS 插件,支持 Android、iOS、Harmony 三端。
-
-【核心能力】
-· 17 种统一权限 Key,三端通用命名
-· 同步 / 异步检查权限状态
-· 单个 / 批量申请权限
-· 按权限类型跳转系统设置页
-· 获取当前平台支持的权限列表
-
-【平台支持】
-· Android:17 项权限(含悬浮窗、短信、电话等 Android 专属)
-· iOS:10 项通用权限(相机、相册、定位、麦克风、蓝牙、通讯录等)
-· Harmony:10 项通用权限(默认 5 项 normal 可直接安装,相册/通讯录需 ACL)
-
-【集成方式】
-1. 导入 uni_modules 插件
-2. 在宿主 manifest.json(Android/iOS)及鸿蒙 module.json5 中声明所需权限
-3. 使用 @/utils/permission-manager Promise 封装或直接调用 UTS API
-
-详细权限配置见插件内《权限配置说明.md》,集成规范见《使用规范.md》。
-```
-
-### 标签 / 关键词
-
-```
-权限, permission, 运行时权限, 蓝牙, 相机, 定位, Android, iOS, Harmony, 鸿蒙, UTS
-```
-
-### 使用说明(市场「使用说明」字段)
-
-可直接粘贴以下内容,或填写插件 readme 链接:
-
-```
-【快速开始】
-
-1. 从插件市场导入 m-permission-manager 到项目 uni_modules 目录
-
-2. 在 manifest.json 中声明宿主所需权限(Android permissions / iOS privacyDescription)
-   鸿蒙端见插件 utssdk/app-harmony/module.json5,详见《权限配置说明.md》
-
-3. 重新制作自定义基座或云打包(UTS 插件不支持标准基座)
-
-4. 在代码中调用:
-
-import {
-  checkPermission,
-  requestPermission,
-  openPermissionSettings,
-} from '@/utils/permission-manager'
-
-const result = await checkPermission('camera')
-const granted = await requestPermission('camera')
-if (!granted) {
-  await openPermissionSettings('camera')
-}
-
-【重要说明】
-· 仅支持 App 端(Android / iOS / Harmony),不支持 H5 与小程序
-· 插件负责运行时检查与申请,宿主仍需在 manifest 中声明静态权限
-· iOS 蓝牙需在 privacyDescription 中配置 NSBluetoothAlwaysUsageDescription
-· 鸿蒙相册/通讯录为 system_basic 权限,默认调试包未声明,需 ACL 签名后启用
-
-完整文档:
-· readme.md — API 与快速开始
-· 使用规范.md — 集成约束与推荐流程
-· 权限配置说明.md — 三端权限文件配置详解
-```
-
-### 权限与隐私声明(`dcloudext.declaration` 对应项)
-
-| 字段 | 填写内容 |
-| --- | --- |
-| **是否含广告** | 无 |
-| **是否采集数据** | 不上传任何用户数据,仅在本地检查与申请系统权限 |
-| **权限说明** | Android:宿主 manifest 声明对应 android.permission.*;iOS:宿主 manifest 声明 NSCameraUsageDescription 等 Info.plist 键;Harmony:插件 module.json5 声明 ohos.permission.*,运行时申请 |
-
-### 平台支持(与 package.json 一致)
-
-| 平台 | 支持情况 |
-| --- | --- |
-| uni-app Vue3 | ✅ |
-| uni-app Vue2 | ❌ |
-| H5 | ❌ |
-| 小程序 | ❌ |
-| Android App | ✅(minSdk 23) |
-| iOS App | ✅(min iOS 14) |
-| Harmony App | ✅(API 12+) |
-
-### 截图建议(4–6 张)
-
-1. 权限演示页截图(三端权限列表与状态)
-2. Promise 封装调用代码示例
-3. Android 系统权限弹窗(相机 / 蓝牙)
-4. iOS 隐私授权弹窗
-5. manifest.json 权限配置示例
-6. 三端权限支持对照表
-
----
-
-## 市场 FAQ 预填
-
-**Q:为什么必须自定义基座?**  
-A:本插件为 UTS 原生插件,标准基座不包含。需制作含本插件的自定义基座或云打包。
-
-**Q:H5 能用吗?**  
-A:不支持。仅 App 端(Android / iOS / Harmony)。
-
-**Q:安装插件后还需要配置权限吗?**  
-A:需要。Android / iOS 必须在宿主 `manifest.json` 中声明静态权限与隐私说明;鸿蒙由插件 `module.json5` 合并,但 ACL 权限需额外签名。详见《权限配置说明.md》。
-
-**Q:三端权限 Key 一样吗?**  
-A:统一使用 `camera`、`microphone`、`location`、`bluetooth` 等 Key,插件内部映射到各平台原生权限。部分 Key 仅 Android 支持(如 `overlay`、`sms`),调用时会返回 `unsupported`。
-
-**Q:iOS 蓝牙在 App 设置里找不到?**  
-A:需在 manifest 配置 `NSBluetoothAlwaysUsageDescription` 并重新打包,且 App 需曾触发蓝牙权限弹窗。若 App 设置页无该项,请前往「设置 → 隐私与安全性 → 蓝牙」。系统蓝牙开关在「设置 → 蓝牙」,与应用授权无关。
-
-**Q:鸿蒙相册权限申请失败?**  
-A:默认 `module.json5` 仅含 5 项 normal 权限,未声明相册读写。相册选图推荐 `uni.chooseImage`;若必须申请媒体权限,需用 `module.full.json5` 覆盖并配置 ACL 签名。
-
-**Q:用户永久拒绝后怎么办?**  
-A:调用 `openPermissionSettings(permissionKey)` 跳转对应系统设置页,配合 `getPermissionSettingsGuide()` 展示引导文案。
-
----
-
-## 版本号规范
-
-遵循 [语义化版本](https://semver.org/lang/zh-CN/):
-
-| 变更类型 | 版本 bump | 示例 |
-| --- | --- | --- |
-| 不兼容 API 变更 | major | 2.0.0 |
-| 新增功能(兼容) | minor | 1.1.0 |
-| Bug 修复 | patch | 1.0.1 |
-
-每次发版同步更新 `package.json` → `version` 和 `changelog.md`。
-
----
-
-## 联系方式
-
-发布前请在 `package.json` → `dcloudext.contact.qq` 填写维护者 QQ,或在插件市场后台配置联系方式。
-
----
-
-## 参考链接
-
-- [UTS 插件开发文档](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html)
-- [插件市场发布流程](https://uniapp.dcloud.net.cn/plugin/publish.html)
-- 插件内 [readme.md](./readme.md)
-- 插件内 [使用规范.md](./使用规范.md)
-- 插件内 [权限配置说明.md](./权限配置说明.md)

+ 0 - 285
uni_modules/m-permission-manager/权限配置说明.md

@@ -1,285 +0,0 @@
-# m-permission-manager 权限配置说明
-
-本文档说明集成本插件时,**各端需要修改哪些文件**、**如何配置权限**,以及插件内置配置文件的作用。
-
----
-
-## 1. 配置总览
-
-| 平台 | 配置文件 | 配置方 | 说明 |
-| --- | --- | --- | --- |
-| **Android** | 宿主 `manifest.json` | 集成者 | 声明 `android.permission.*` |
-| **iOS** | 宿主 `manifest.json` | 集成者 | 声明 `NS*UsageDescription` |
-| **Harmony** | 插件 `utssdk/app-harmony/module.json5`(可选:`harmony-configs/entry/src/main/module.json5`) | 插件内置为主,集成者可切换 full 版或宿主覆盖 |
-
-> 插件负责**运行时检查与申请**;Android / iOS 的**静态声明**必须由宿主项目在 manifest 中完成。Harmony 权限由插件 module 合并进宿主包,集成者按需切换 normal / full 版本。
-
----
-
-## 2. Android 配置
-
-### 2.1 配置文件
-
-**路径**:项目根目录 `manifest.json`  
-**节点**:`app-plus.distribute.android.permissions`
-
-```json
-{
-  "app-plus": {
-    "distribute": {
-      "android": {
-        "permissions": [
-          "<uses-permission android:name=\"android.permission.CAMERA\"/>",
-          "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
-          "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
-          "<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
-          "<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
-          "<uses-permission android:name=\"android.permission.BLUETOOTH_CONNECT\"/>",
-          "<uses-permission android:name=\"android.permission.BLUETOOTH_SCAN\"/>",
-          "<uses-permission android:name=\"android.permission.READ_MEDIA_IMAGES\"/>",
-          "<uses-permission android:name=\"android.permission.READ_MEDIA_VIDEO\"/>"
-        ]
-      }
-    }
-  }
-}
-```
-
-### 2.2 统一 Key 与 Android 权限映射
-
-| 插件 Key | Android 权限 | 备注 |
-| --- | --- | --- |
-| `camera` | `CAMERA` | |
-| `photoLibrary` | `READ_MEDIA_IMAGES`(API 33+)或 `READ_EXTERNAL_STORAGE` | 插件按 SDK 自动选择 |
-| `storage` | `READ_MEDIA_IMAGES` + `READ_MEDIA_VIDEO`(API 33+)或 `WRITE/READ_EXTERNAL_STORAGE` | |
-| `readStorage` | 同 `photoLibrary` / 媒体读权限 | |
-| `location` | `ACCESS_FINE_LOCATION` | |
-| `coarseLocation` | `ACCESS_COARSE_LOCATION` | |
-| `microphone` | `RECORD_AUDIO` | |
-| `contacts` | `READ_CONTACTS` | |
-| `writeContacts` | `WRITE_CONTACTS` | |
-| `bluetooth` | `BLUETOOTH_CONNECT` + `BLUETOOTH_SCAN`(API 31+)或 `BLUETOOTH` + `BLUETOOTH_ADMIN` | |
-| `phone` | `CALL_PHONE` | |
-| `phoneState` | `READ_PHONE_STATE` | |
-| `sms` | `SEND_SMS` | |
-| `readSms` | `READ_SMS` | |
-| `receiveSms` | `RECEIVE_SMS` | |
-| `overlay` | 无 manifest 条目 | 通过 `Settings.canDrawOverlays` 检查 |
-| `writeSettings` | 无 manifest 条目 | 通过 `Settings.System.canWrite` 检查 |
-
-### 2.3 注意
-
-- 只声明业务使用的权限,避免过度申请
-- Android 13+ 媒体权限使用 `READ_MEDIA_*`;插件仅在 **targetSdkVersion >= 33** 时动态申请新媒体权限,否则回退 `READ_EXTERNAL_STORAGE`(兼容 targetSdk 偏低的自定义基座)
-- `overlay`、`writeSettings` 需在 manifest 声明对应 capability 后,通过插件跳转系统设置页授权
-
----
-
-## 3. iOS 配置
-
-### 3.1 配置文件
-
-**路径**:项目根目录 `manifest.json`  
-**节点**:`app-plus.distribute.ios.privacyDescription`
-
-```json
-{
-  "app-plus": {
-    "distribute": {
-      "ios": {
-        "privacyDescription": {
-          "NSCameraUsageDescription": "需要使用相机进行拍照",
-          "NSMicrophoneUsageDescription": "需要使用麦克风进行录音",
-          "NSPhotoLibraryUsageDescription": "需要访问相册以选择图片",
-          "NSPhotoLibraryAddUsageDescription": "需要保存图片到相册",
-          "NSLocationWhenInUseUsageDescription": "需要获取位置信息",
-          "NSContactsUsageDescription": "需要访问通讯录",
-          "NSBluetoothAlwaysUsageDescription": "需要使用蓝牙连接周边设备"
-        }
-      }
-    }
-  }
-}
-```
-
-### 3.2 统一 Key 与 Info.plist 键映射
-
-| 插件 Key | Info.plist 键 | 备注 |
-| --- | --- | --- |
-| `camera` | `NSCameraUsageDescription` | |
-| `photoLibrary` | `NSPhotoLibraryUsageDescription` | |
-| `storage` | `NSPhotoLibraryUsageDescription` 或 `NSPhotoLibraryAddUsageDescription` | 映射到相册 |
-| `readStorage` | `NSPhotoLibraryUsageDescription` | 映射到相册 |
-| `location` | `NSLocationWhenInUseUsageDescription` | |
-| `coarseLocation` | `NSLocationWhenInUseUsageDescription` | 与精确定位共用 |
-| `microphone` | `NSMicrophoneUsageDescription` | |
-| `contacts` | `NSContactsUsageDescription` | |
-| `writeContacts` | `NSContactsUsageDescription` | 读写共用 |
-| `bluetooth` | `NSBluetoothAlwaysUsageDescription` | **必须配置**,否则 App 设置页无蓝牙开关 |
-
-### 3.3 iOS 蓝牙特别说明
-
-iOS 蓝牙涉及两个独立概念:
-
-| 概念 | 设置路径 | 配置要求 |
-| --- | --- | --- |
-| 系统蓝牙开关 | 设置 → 蓝牙 | 无需 manifest,用户手动打开 |
-| App 蓝牙授权 | 设置 → 本 App → 蓝牙,或 设置 → 隐私与安全性 → 蓝牙 | 需 `NSBluetoothAlwaysUsageDescription` + 重新打包 + App 曾触发弹窗 |
-
-Apple 不提供跳转到「隐私 → 蓝牙」的公开深链;插件 `openPermissionSettings('bluetooth')` 会打开 App 设置页并配合引导文案。
-
----
-
-## 4. Harmony 配置
-
-### 4.1 harmony-configs 要不要配?
-
-**使用 m-permission-manager 时,一般不需要在 `harmony-configs/` 里重复声明权限。**
-
-鸿蒙端权限有两种配置路径:
-
-| 方式 | 配置文件 | 适用场景 |
-| --- | --- | --- |
-| **UTS 插件声明(推荐)** | `uni_modules/m-permission-manager/utssdk/app-harmony/module.json5` | 插件打包为鸿蒙子模块(HAR),权限对整个 App 生效 |
-| **宿主工程覆盖** | `harmony-configs/entry/src/main/module.json5` | 插件未覆盖的权限、或希望在宿主侧集中管理 |
-
-鸿蒙官方规则:**已在子模块中声明的权限,主工程无需重复添加**,权限在整个应用中生效。  
-m-permission-manager 作为 UTS 插件,其 `module.json5` 会在编译时拷贝为插件子模块的 `src/main/module.json5`,因此**默认情况下宿主不必再配**。
-
-当前项目的 `harmony-configs/` 主要用于:
-
-| 文件 | 用途 |
-| --- | --- |
-| `AppScope/app.json5` | 包名、版本、图标(HX 4.31+ 也可在 `manifest.json` → `app-harmony` 图形界面配置) |
-| `build-profile.json5` | 签名证书(`.cer` / `.p12` / `.p7b`) |
-| `entry/build-profile.json5` | release 混淆等构建选项 |
-| `entry/obfuscation-rules.txt` | 混淆规则 |
-
-**若要在 harmony-configs 中配置权限**(可选,非必须):
-
-1. 先运行一次鸿蒙编译,从 `unpackage/dist/dev/app-harmony/entry/src/main/module.json5` 复制完整文件到 `harmony-configs/entry/src/main/module.json5`
-2. **仅修改** `module.requestPermissions` 节点,其他节点不要删(uni-app 是**文件级覆盖**,不是 JSON 节点合并)
-3. 不要与插件已声明的权限重复
-
-> 集成 m-permission-manager 时,优先改插件内的 `module.json5` / `module.full.json5`,而不是 harmony-configs。
-
-### 4.2 插件内置文件
-
-**目录**:`uni_modules/m-permission-manager/utssdk/app-harmony/`
-
-| 文件 | 权限数量 | APL 等级 | 用途 |
-| --- | --- | --- | --- |
-| `module.json5` | 5 项 | normal | **默认生效**,调试证书可直接安装 |
-| `module.normal.json5` | 5 项 | normal | 与 `module.json5` 相同,备份参考 |
-| `module.full.json5` | 9 项 | normal + system_basic | 含相册 / 通讯录,需 ACL 签名 |
-
-**权限说明文案**:`resources/base/element/string.json`
-
-### 4.3 默认 module.json5(5 项 normal)
-
-| 插件 Key | ohos.permission | 说明 |
-| --- | --- | --- |
-| `camera` | `CAMERA` | |
-| `microphone` | `MICROPHONE` | |
-| `location` | `LOCATION` | |
-| `coarseLocation` | `APPROXIMATELY_LOCATION` | |
-| `bluetooth` | `ACCESS_BLUETOOTH` | |
-
-### 4.4 module.full.json5 额外 4 项(system_basic,需 ACL)
-
-| 插件 Key | ohos.permission | APL | 说明 |
-| --- | --- | --- | --- |
-| `photoLibrary` / `readStorage` | `READ_IMAGEVIDEO` | system_basic | 需 ACL |
-| `storage` | `WRITE_IMAGEVIDEO` | system_basic | 需 ACL |
-| `contacts` | `READ_CONTACTS` | system_basic | 需 ACL |
-| `writeContacts` | `WRITE_CONTACTS` | system_basic | 需 ACL |
-
-### 4.5 如何切换 full 版本
-
-1. 将 `module.full.json5` 的内容**覆盖** `module.json5`
-2. 在 AppGallery Connect 配置 ACL 白名单
-3. 使用正式 Profile 重新签名打包
-4. 重新制作自定义基座或云打包
-
-### 4.6 未声明 ACL 权限时的插件行为
-
-| 场景 | 检查 status | 申请结果 |
-| --- | --- | --- |
-| 相册 / 通讯录等未在 module.json5 声明 | `restricted` | 9020003,附未声明说明 |
-| 系统设置 | 无对应开关 | 引导使用 `uni.chooseImage` 或切换 full 版本 |
-
-### 4.7 安装报 9568289
-
-说明 `module.json5` 中含有未签名的 system_basic 权限。请确认使用默认 5 项 normal 版本;若已合并 full 版本,需先完成 ACL 与 Profile 签名。
-
-### 4.8 鸿蒙不支持的功能
-
-以下插件 Key 在鸿蒙返回 `unsupported`:`phone`、`phoneState`、`sms`、`readSms`、`receiveSms`、`overlay`、`writeSettings`。
-
----
-
-## 5. 配置示例(按业务场景)
-
-### 5.1 仅需相机 + 麦克风
-
-**Android** manifest:
-
-```json
-"permissions": [
-  "<uses-permission android:name=\"android.permission.CAMERA\"/>",
-  "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>"
-]
-```
-
-**iOS** privacyDescription:
-
-```json
-"privacyDescription": {
-  "NSCameraUsageDescription": "需要使用相机",
-  "NSMicrophoneUsageDescription": "需要使用麦克风"
-}
-```
-
-**Harmony**:默认 `module.json5` 已包含,无需修改。
-
-### 5.2 需要蓝牙
-
-**Android** manifest 增加:
-
-```json
-"<uses-permission android:name=\"android.permission.BLUETOOTH_CONNECT\"/>",
-"<uses-permission android:name=\"android.permission.BLUETOOTH_SCAN\"/>"
-```
-
-**iOS** privacyDescription 增加:
-
-```json
-"NSBluetoothAlwaysUsageDescription": "需要使用蓝牙连接周边设备"
-```
-
-**Harmony**:默认 `module.json5` 已包含 `ACCESS_BLUETOOTH`。
-
-### 5.3 需要相册读写(Harmony 完整权限)
-
-1. 用 `module.full.json5` 覆盖 `module.json5`
-2. 配置 ACL 签名
-3. Android 增加 `READ_MEDIA_IMAGES` / `READ_MEDIA_VIDEO`
-4. iOS 增加 `NSPhotoLibraryUsageDescription`
-
-> 若仅需选图不上传,推荐使用 `uni.chooseImage`,三端均无需媒体读写权限。
-
----
-
-## 6. 配置后必做
-
-1. **重新制作自定义基座**或云打包(UTS 插件 + manifest 变更均须重新打包)
-2. iOS 修改 `privacyDescription` 后建议删除旧 App 重装,以重新触发授权弹窗
-3. Harmony 切换 `module.json5` 后需重新签名安装
-
----
-
-## 7. 相关文档
-
-- [readme.md](./readme.md) — API 与权限 Key 对照表
-- [使用规范.md](./使用规范.md) — 集成流程与审核注意事项
-- [发布指南.md](./发布指南.md) — 插件市场发布填写参考