From 08c54797b66a5c5c244915742d2130ee26c7810b Mon Sep 17 00:00:00 2001
From: Sun_sun <469361609@qq.com>
Date: Sun, 28 Sep 2025 17:30:20 +0800
Subject: [PATCH] =?UTF-8?q?2025-09-28=20=E8=81=8A=E5=A4=A9=E4=BF=AE?=
=?UTF-8?q?=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
App.vue | 21 +-
api/group.js | 6 +-
pages.json | 2 +-
pages/message/chat.vue | 535 ++++++++++++++++++++
pages/message/message.vue | 24 +-
pages/my/my.vue | 5 +-
pages/program/chat.vue | 171 -------
pages/program/programDetail.vue | 28 +-
static/icon/listen.png | Bin 0 -> 4944 bytes
uni_modules/colorful-uni-perm/changelog.md | 4 +
uni_modules/colorful-uni-perm/index.js | 262 ++++++++++
uni_modules/colorful-uni-perm/package.json | 87 ++++
uni_modules/colorful-uni-perm/permission.js | 55 ++
uni_modules/colorful-uni-perm/popup.js | 119 +++++
uni_modules/colorful-uni-perm/readme.md | 249 +++++++++
15 files changed, 1380 insertions(+), 188 deletions(-)
create mode 100644 pages/message/chat.vue
delete mode 100644 pages/program/chat.vue
create mode 100644 static/icon/listen.png
create mode 100644 uni_modules/colorful-uni-perm/changelog.md
create mode 100644 uni_modules/colorful-uni-perm/index.js
create mode 100644 uni_modules/colorful-uni-perm/package.json
create mode 100644 uni_modules/colorful-uni-perm/permission.js
create mode 100644 uni_modules/colorful-uni-perm/popup.js
create mode 100644 uni_modules/colorful-uni-perm/readme.md
diff --git a/App.vue b/App.vue
index 594993f..61fa317 100644
--- a/App.vue
+++ b/App.vue
@@ -1,6 +1,17 @@
diff --git a/api/group.js b/api/group.js
index 7ac92ff..f0e2965 100644
--- a/api/group.js
+++ b/api/group.js
@@ -2,6 +2,10 @@ import {
http
} from "../util/api";
+const baseURL = "http://192.168.0.15:3007"
+
export const groupAPI = {
- getList: (params) => http.get('/group/list', params)
+ getList: (params) => http.get(baseURL + '/group/list', params),
+ add: (data) => http.post(baseURL + '/group/', data),
+ getOne: (params) => http.get(baseURL + '/group/one', params),
}
\ No newline at end of file
diff --git a/pages.json b/pages.json
index 45c866d..9a051aa 100644
--- a/pages.json
+++ b/pages.json
@@ -65,7 +65,7 @@
}
},
{
- "path" : "pages/program/chat",
+ "path" : "pages/message/chat",
"style" :
{
"navigationBarTitleText" : "聊天页面",
diff --git a/pages/message/chat.vue b/pages/message/chat.vue
new file mode 100644
index 0000000..7848f9e
--- /dev/null
+++ b/pages/message/chat.vue
@@ -0,0 +1,535 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 点击说话
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.content}}
+
+
+
+
+
+
+
+
+ 点击播放
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.content}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{!showMaskBtn?'正在说话...点击结束': '点击播放录音'}}
+
+
+ 取消
+ 发送
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/message/message.vue b/pages/message/message.vue
index 97b7aca..1771616 100644
--- a/pages/message/message.vue
+++ b/pages/message/message.vue
@@ -48,6 +48,7 @@
} from '@dcloudio/uni-app';
import { onReady as onUniReady } from '@dcloudio/uni-app';
import { groupAPI } from '../../api/group';
+ import { getUserInfo } from '../../util/common';
const instance = getCurrentInstance();
const height = ref(0)
@@ -92,23 +93,23 @@
// 项目
const messageList = ref([])
-
- const mockData = () => {
- for (var i = 0; i < 20; i++) {
- messageList.value.push({
- messageName: "test" + i
- })
- }
- }
+ const user = ref()
+ const size = 10
+ const params = ref({
+ page: 1,
+ size: size,
+ userId: '',
+ customerId: '',
+ })
const handleChat = (item) => {
uni.navigateTo({
- url: '/pages/program/chat?groupId=' + item.groupId
+ url: '/pages/message/chat?groupId=' + item.groupId
})
}
const loadData = () => {
- groupAPI.getList().then((res) => {
+ groupAPI.getList(params.value).then((res) => {
messageList.value = res.data.list
})
}
@@ -120,7 +121,8 @@
onUniReady(() => {
loadHeight()
-
+ user.value = getUserInfo()
+ params.value.userId = user.value.id
loadData()
})
diff --git a/pages/my/my.vue b/pages/my/my.vue
index 4c68e4b..6e4c69f 100644
--- a/pages/my/my.vue
+++ b/pages/my/my.vue
@@ -1,7 +1,9 @@
- {{user.real_name}}
+
+ {{user.real_name}}
+
退出登录
@@ -16,7 +18,6 @@
onMounted(() => {
user.value = uni.getStorageSync("user")
-
})
const loginOut = () => {
diff --git a/pages/program/chat.vue b/pages/program/chat.vue
deleted file mode 100644
index c971394..0000000
--- a/pages/program/chat.vue
+++ /dev/null
@@ -1,171 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{item.content}}
-
-
- {{item.content}}
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/pages/program/programDetail.vue b/pages/program/programDetail.vue
index fda9c49..637789b 100644
--- a/pages/program/programDetail.vue
+++ b/pages/program/programDetail.vue
@@ -96,7 +96,8 @@
- {{isChat?"继续聊":"聊一聊"}}
+ {{isChat?"继续聊":"聊一聊"}}
立刻融
@@ -171,6 +172,7 @@
import { getUserInfo } from '../../util/common';
import { programAPI } from '../../api/program';
import { onLoad } from '@dcloudio/uni-app'
+ import { groupAPI } from '../../api/group';
const userId = ref()
const programId = ref()
@@ -213,6 +215,30 @@
loadData()
})
+ const handleChat = () => {
+ if (isChat.value) {
+ // 继续聊
+ groupAPI.getOne({programId: programId.value, userId: userId.value}).then(res=>{
+ if(res.code==200){
+ // 进入聊天
+ uni.redirectTo({
+ url: '/pages/message/chat?groupId=' + res.data.groupId
+ })
+ }
+ })
+ } else {
+ // 开启群组聊天
+ groupAPI.add({ programId: programId.value, userId: userId.value }).then(res => {
+ if(res.code==200){
+ // 创建成功,进入聊天
+ uni.redirectTo({
+ url: '/pages/message/chat?groupId=' + res.data.groupId
+ })
+ }
+ })
+ }
+ }
+
// 立刻融 弹窗
const showWarning = ref(false)
diff --git a/static/icon/listen.png b/static/icon/listen.png
new file mode 100644
index 0000000000000000000000000000000000000000..6dbabab451f3ee6b12a72c0ba52be1df3833df52
GIT binary patch
literal 4944
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
literal 0
HcmV?d00001
diff --git a/uni_modules/colorful-uni-perm/changelog.md b/uni_modules/colorful-uni-perm/changelog.md
new file mode 100644
index 0000000..999a06f
--- /dev/null
+++ b/uni_modules/colorful-uni-perm/changelog.md
@@ -0,0 +1,4 @@
+## 1.0.0(2025-06-09)
+- 两行代码完成全局监听权限申请
+- 自动化弹窗实现权限申请描述
+- 轻松通过华为应用商店审核
diff --git a/uni_modules/colorful-uni-perm/index.js b/uni_modules/colorful-uni-perm/index.js
new file mode 100644
index 0000000..ab9b007
--- /dev/null
+++ b/uni_modules/colorful-uni-perm/index.js
@@ -0,0 +1,262 @@
+import { popup } from './popup.js'
+import permissionUtil from './permission.js'
+
+let permissionListener = null
+
+const prefix = 'permissionStatus_'
+const { uniPlatform, platform } = uni.getSystemInfoSync()
+
+// 默认权限申请说明信息
+const defaultPermissionExplainMap = {
+ 'android.permission.BLUETOOTH_SCAN': {
+ title: '蓝牙扫描权限申请说明',
+ content: '应用需要扫描附近的蓝牙设备,以便进行连接或数据传输。'
+ },
+ 'android.permission.BLUETOOTH_CONNECT': {
+ title: '蓝牙连接权限申请说明',
+ content: '应用需要连接蓝牙设备,以便提供音频播放或数据通信功能。'
+ },
+ 'android.permission.READ_MEDIA_IMAGE': {
+ title: '读取图片权限申请说明',
+ content: '应用需要访问您的图片库,以便加载和选择照片。'
+ },
+ 'android.permission.READ_MEDIA_IMAGES': {
+ title: '读取图片权限申请说明',
+ content: '应用需要访问您的图片库,以便加载和选择照片。'
+ },
+ 'android.permission.READ_MEDIA_VIDEO': {
+ title: '读取视频权限申请说明',
+ content: '应用需要访问您的视频库,以便播放和选择视频文件。'
+ },
+ 'android.permission.READ_MEDIA_AUDIO': {
+ title: '读取音频权限申请说明',
+ content: '应用需要访问您的音频文件,以便播放音乐或录音。'
+ },
+ 'android.permission.CALL_PHONE': {
+ title: '拨打电话权限申请说明',
+ content: '应用需要拨打电话权限,以便直接拨打联系人或客服热线。'
+ },
+ 'android.permission.INTERNET': {
+ title: '网络权限申请说明',
+ content: '应用需要访问网络,以提供最新的内容和服务。'
+ },
+ 'android.permission.READ_EXTERNAL_STORAGE': {
+ title: '存储读取权限申请说明',
+ content: '应用需要读取您的存储,以便加载图片、视频等多媒体文件。'
+ },
+ 'android.permission.WRITE_EXTERNAL_STORAGE': {
+ title: '存储写入权限申请说明',
+ content: '应用需要写入您的存储,以便保存图片、视频等多媒体文件。'
+ },
+ 'android.permission.READ_PHONE_STATE': {
+ title: '设备信息权限申请说明',
+ content: '应用需要访问设备信息,以便提供更好的用户体验。'
+ },
+ 'android.permission.ACCESS_NETWORK_STATE': {
+ title: '网络状态权限申请说明',
+ content: '应用需要获取网络状态,以便优化网络请求。'
+ },
+ 'android.permission.ACCESS_WIFI_STATE': {
+ title: 'WiFi 状态权限申请说明',
+ content: '应用需要获取 WiFi 状态,以便优化网络连接。'
+ },
+ 'android.permission.CAMERA': {
+ title: '相机权限申请说明',
+ content: '应用需要访问您的相机,以便拍摄照片或扫描二维码。'
+ },
+ 'android.permission.ACCESS_COARSE_LOCATION': {
+ title: '定位权限申请说明',
+ content: '应用需要获取您的大致位置信息,以便提供基于位置的服务。'
+ },
+ 'android.permission.ACCESS_FINE_LOCATION': {
+ title: '精确定位权限申请说明',
+ content: '应用需要获取您的精确位置信息,以便提供导航等精准服务。'
+ },
+ 'android.permission.ACCESS_LOCATION_EXTRA_COMMANDS': {
+ title: '额外定位权限申请说明',
+ content: '应用需要使用额外的定位功能,以提升定位精度。'
+ },
+ 'android.permission.ACCESS_MOCK_LOCATION': {
+ title: '模拟定位权限申请说明',
+ content: '应用需要访问模拟位置,以便进行测试或特定功能。'
+ },
+ 'android.permission.READ_CONTACTS': {
+ title: '读取联系人权限申请说明',
+ content: '应用需要读取您的联系人信息,以便提供通讯录相关功能。'
+ },
+ 'android.permission.WRITE_CONTACTS': {
+ title: '写入联系人权限申请说明',
+ content: '应用需要写入您的联系人信息,以便管理通讯录。'
+ },
+ 'android.permission.BLUETOOTH': {
+ title: '蓝牙权限申请说明',
+ content: '应用需要访问蓝牙功能,以便连接设备或传输数据。'
+ },
+ 'android.permission.BLUETOOTH_ADMIN': {
+ title: '蓝牙管理权限申请说明',
+ content: '应用需要管理蓝牙功能,以便优化连接体验。'
+ },
+ 'android.permission.RECEIVE_SMS': {
+ title: '短信接收权限申请说明',
+ content: '应用需要读取短信,以便自动填充验证码或提供相关功能。'
+ },
+ 'android.permission.SEND_SMS': {
+ title: '短信发送权限申请说明',
+ content: '应用需要发送短信,以便提供短信验证等功能。'
+ },
+ 'android.permission.WRITE_SMS': {
+ title: '短信写入权限申请说明',
+ content: '应用需要写入短信,以便存储和管理您的短信信息。'
+ },
+ 'android.permission.READ_SMS': {
+ title: '短信读取权限申请说明',
+ content: '应用需要读取短信,以便自动填充验证码或提供相关功能。'
+ },
+ 'android.permission.INSTALL_PACKAGES': {
+ title: '安装应用权限申请说明',
+ content: '应用需要安装其他应用,以便提供扩展功能。'
+ },
+ 'android.permission.REQUEST_INSTALL_PACKAGES': {
+ title: '安装包权限申请说明',
+ content: '应用需要请求安装应用包权限,以便下载安装更新。'
+ },
+ 'com.android.launcher.permission.INSTALL_SHORTCUT': {
+ title: '创建快捷方式权限申请说明',
+ content: '应用需要创建桌面快捷方式,以便您快速访问应用。'
+ },
+ 'com.android.launcher.permission.UNINSTALL_SHORTCUT': {
+ title: '删除快捷方式权限申请说明',
+ content: '应用需要删除桌面快捷方式,以便管理您的快捷方式。'
+ },
+ 'android.permission.RECORD_AUDIO': {
+ title: '麦克风权限申请说明',
+ content: '应用需要访问麦克风,以便进行语音输入或语音通话。'
+ },
+ 'android.permission.MODIFY_AUDIO_SETTINGS': {
+ title: '音频设置修改权限申请说明',
+ content: '应用需要修改音频设置,以便优化音量或声音效果。'
+ },
+ 'android.permission.GET_ACCOUNTS': {
+ title: '账户权限申请说明',
+ content: '应用需要访问您的账户信息,以便提供个性化服务。'
+ },
+ 'android.permission.USE_FINGERPRINT': {
+ title: '指纹识别权限申请说明',
+ content: '应用需要使用指纹识别,以便进行身份验证。'
+ },
+ 'android.permission.USE_BIOMETRIC': {
+ title: '生物识别权限申请说明',
+ content: '应用需要使用生物识别功能(如面部识别),以便进行身份验证。'
+ },
+ 'android.permission.READ_CALENDAR': {
+ title: '读取日历权限申请说明',
+ content: '应用需要读取您的日历,以便提供日程管理功能。'
+ },
+ 'android.permission.WRITE_CALENDAR': {
+ title: '写入日历权限申请说明',
+ content: '应用需要写入您的日历,以便添加或修改日程。'
+ },
+ 'android.permission.READ_CALL_LOG': {
+ title: '读取通话记录权限申请说明',
+ content: '应用需要访问通话记录,以便提供通话管理或统计功能。'
+ },
+ 'android.permission.WRITE_CALL_LOG': {
+ title: '写入通话记录权限申请说明',
+ content: '应用需要写入通话记录,以便管理通话历史。'
+ },
+ 'android.permission.PROCESS_OUTGOING_CALLS': {
+ title: '处理拨出电话权限申请说明',
+ content: '应用需要访问拨出电话,以便提供通话拦截或号码识别功能。'
+ },
+ 'android.permission.BODY_SENSORS': {
+ title: '传感器权限申请说明',
+ content: '应用需要访问您的传感器数据,以便提供健康或运动相关功能。'
+ },
+ 'android.permission.ACTIVITY_RECOGNITION': {
+ title: '活动识别权限申请说明',
+ content: '应用需要访问您的活动状态,以便提供运动检测等功能。'
+ },
+ 'android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS': {
+ title: '电池优化忽略权限申请说明',
+ content: '应用需要忽略电池优化,以便在后台稳定运行。'
+ },
+ 'android.permission.FOREGROUND_SERVICE': {
+ title: '前台服务权限申请说明',
+ content: '应用需要运行前台服务,以便提供持续运行的功能,如音乐播放、导航等。'
+ },
+ 'android.permission.SYSTEM_ALERT_WINDOW': {
+ title: '悬浮窗权限申请说明',
+ content: '应用需要显示悬浮窗,以便提供浮动窗口功能,如聊天气泡、屏幕录制等。'
+ },
+ 'android.permission.WRITE_SETTINGS': {
+ title: '系统设置修改权限申请说明',
+ content: '应用需要修改系统设置,以便调整亮度、铃声等个性化配置。'
+ }
+}
+
+// 节流函数
+let previous = 0
+function throttle(func, wait = 500) {
+ let now = Date.now()
+ if (now - previous > wait) {
+ typeof func === 'function' && func()
+ previous = now
+ }
+}
+
+/**
+ * 创建请求权限的监听器
+ * 该函数用于在特定平台上创建和管理权限请求的监听器,并根据权限请求的结果做出相应处理
+ * @param {Object} permissionExplainMap - 包含权限名称和对应解释内容的映射对象,用于向用户展示权限请求的说明,默认为空对象
+ */
+const createRequestPermissionListener = (permissionExplainMap = {}) => {
+ if (uniPlatform != 'app' || platform != 'android') return
+
+ if (typeof permissionExplainMap != 'object') throw Error('permissionExplainMap 类型错误')
+
+ permissionListener = permissionListener || uni.createRequestPermissionListener()
+
+ permissionListener.onRequest(e => {
+ console.log('onRequest', e)
+ })
+
+ permissionListener.onConfirm(e => {
+ const [permissionName] = e
+
+ const status = uni.getStorageSync(prefix + permissionName)
+ console.log('onConfirm permissionName', permissionName, status)
+ const content = permissionExplainMap[permissionName] || defaultPermissionExplainMap[permissionName]
+
+ if (!status && content) {
+ throttle(() => popup.show(content))
+ }
+ })
+
+ permissionListener.onComplete(e => {
+ const [permissionName] = e
+
+ const status = uni.getStorageSync(prefix + permissionName)
+ console.log('onComplete permissionName', permissionName, status)
+ popup.close()
+
+ const content = permissionExplainMap[permissionName] || defaultPermissionExplainMap[permissionName]
+
+ if (status === -1 && content) {
+ throttle(() => showModal(content.content))
+ }
+ })
+}
+
+function showModal(content) {
+ uni.showModal({
+ title: '权限申请已被拒绝',
+ content: content + '请前往 APP 设置界面打开对应权限!',
+ showCancel: false
+ })
+}
+
+const stopRequestPermissionListener = () => {
+ permissionListener && permissionListener.stop()
+}
+
+export { permissionUtil, createRequestPermissionListener, stopRequestPermissionListener }
diff --git a/uni_modules/colorful-uni-perm/package.json b/uni_modules/colorful-uni-perm/package.json
new file mode 100644
index 0000000..54d0da5
--- /dev/null
+++ b/uni_modules/colorful-uni-perm/package.json
@@ -0,0 +1,87 @@
+{
+ "id": "colorful-uni-perm",
+ "displayName": "全局监听权限申请,安卓权限申请的使用目的说明弹窗,华为应用商店上架处理",
+ "version": "1.0.0",
+ "description": "解决华为、小米等应用商店上架审核时,未向用户告知权限申请的目的,导致应用审核被拒绝问题",
+ "keywords": [
+ "华为上架",
+ "监听权限申请",
+ "权限申请的使用目的",
+ "权限申请的使用目说明弹窗"
+],
+ "repository": "",
+ "engines": {
+ "HBuilderX": "^4.01"
+ },
+ "dcloudext": {
+ "type": "sdk-js",
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y",
+ "alipay": "y"
+ },
+ "client": {
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ },
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "u",
+ "app-uvue": "u",
+ "app-harmony": "u"
+ },
+ "H5-mobile": {
+ "Safari": "u",
+ "Android Browser": "u",
+ "微信浏览器(Android)": "u",
+ "QQ浏览器(Android)": "u"
+ },
+ "H5-pc": {
+ "Chrome": "u",
+ "IE": "u",
+ "Edge": "u",
+ "Firefox": "u",
+ "Safari": "u"
+ },
+ "小程序": {
+ "微信": "u",
+ "阿里": "u",
+ "百度": "u",
+ "字节跳动": "u",
+ "QQ": "u",
+ "钉钉": "u",
+ "快手": "u",
+ "飞书": "u",
+ "京东": "u"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
diff --git a/uni_modules/colorful-uni-perm/permission.js b/uni_modules/colorful-uni-perm/permission.js
new file mode 100644
index 0000000..4c34958
--- /dev/null
+++ b/uni_modules/colorful-uni-perm/permission.js
@@ -0,0 +1,55 @@
+/**
+ * 此文件来源于 https://ext.dcloud.net.cn/plugin?id=594 部分片段
+ *
+ * 获取权限状态
+ * @param {String} permissionID 权限ID
+ * @returns {Promise}
+ */
+const prefix = 'permissionStatus_';
+function requestAndroidPermission(permissionID) {
+ return new Promise((resolve, reject) => {
+ plus.android.requestPermissions(
+ // 理论上支持多个权限同时查询,但实际上本函数封装只处理了一个权限的情况。有需要的可自行扩展封装
+ [permissionID],
+ function (resultObj) {
+ var result = 0;
+ for (var i = 0; i < resultObj.granted.length; i++) {
+ var grantedPermission = resultObj.granted[i];
+ console.log('已获取的权限:' + grantedPermission);
+ result = 1;
+ }
+ for (var i = 0; i < resultObj.deniedPresent.length; i++) {
+ var deniedPresentPermission = resultObj.deniedPresent[i];
+ console.log('拒绝本次申请的权限:' + deniedPresentPermission);
+ result = 0;
+ }
+ for (var i = 0; i < resultObj.deniedAlways.length; i++) {
+ var deniedAlwaysPermission = resultObj.deniedAlways[i];
+ console.log('永久拒绝申请的权限:' + deniedAlwaysPermission);
+ result = -1;
+ }
+ uni.setStorageSync(prefix + permissionID, result);
+
+ resolve(result);
+ // 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限
+ if (result != 1) {
+ // uni.showModal({
+ // content: '权限已经被拒绝,请前往APP设置界面打开相应权限',
+ // showCancel: false,
+ // });
+ }
+ },
+ function (error) {
+ console.log('申请权限错误:' + error.code + ' = ' + error.message);
+ resolve({
+ code: error.code,
+ message: error.message,
+ });
+ },
+ );
+ });
+}
+
+export default {
+ requestAndroidPermission,
+};
diff --git a/uni_modules/colorful-uni-perm/popup.js b/uni_modules/colorful-uni-perm/popup.js
new file mode 100644
index 0000000..9c78d3f
--- /dev/null
+++ b/uni_modules/colorful-uni-perm/popup.js
@@ -0,0 +1,119 @@
+/**
+ * @description: 创建一个原生弹窗
+ * @param {*} options
+ * @return {*}
+ */
+export class NativePopup {
+ constructor(options = {}) {
+ this.sysInfo = uni.getSystemInfoSync();
+
+ const { bgColor = '#fff', titleColor = '#000', contentColor = '#272727' } = options;
+
+ this.bgColor = bgColor;
+ this.titleColor = titleColor;
+ this.contentColor = contentColor;
+ }
+
+ createPopup = () => {
+ const { statusBarHeight, screenWidth } = this.sysInfo;
+
+ const popupView = new plus.nativeObj.View('popupView', {
+ top: 0,
+ left: 0,
+ width: screenWidth,
+ height: 110 + statusBarHeight + 'px',
+ // backgroundColor: 'blue' // debug
+ });
+
+ popupView.addEventListener('click', this.close);
+
+ const bgPadding = 15;
+
+ popupView.drawRect(
+ {
+ color: 'rgba(0, 0, 0, 0.1)',
+ radius: '10px',
+ },
+ {
+ top: statusBarHeight + 7 + 'px',
+ left: bgPadding - 2 + 'px',
+ width: screenWidth - bgPadding * 2 + 4 + 'px',
+ height: '100px',
+ },
+ );
+
+ popupView.drawRect(
+ {
+ color: this.bgColor,
+ radius: '10px',
+ },
+ {
+ top: statusBarHeight + 5 + 'px',
+ left: bgPadding + 'px',
+ width: screenWidth - bgPadding * 2 + 'px',
+ height: '100px',
+ },
+ );
+
+ const padding = 10;
+
+ popupView.drawText(
+ this.title,
+ {
+ top: statusBarHeight + 10 + 'px',
+ left: padding + bgPadding + 'px',
+ height: '30px',
+ width: screenWidth - bgPadding * 2 - padding * 2 + 'px',
+ },
+ {
+ size: '16px',
+ weight: 'bold',
+ align: 'left',
+ color: this.titleColor,
+ },
+ {
+ onClick: function (e) {
+ console.log(e);
+ },
+ },
+ );
+
+ popupView.drawText(
+ this.content,
+ {
+ top: statusBarHeight + 40 + 'px',
+ height: '60px',
+ left: padding + bgPadding + 'px',
+ width: screenWidth - bgPadding * 2 - padding * 2 + 'px',
+ },
+ {
+ size: '14px',
+ align: 'left',
+ color: this.contentColor,
+ whiteSpace: 'normal',
+ },
+ );
+
+ this.popupView = popupView;
+
+ return popupView;
+ };
+
+ show = (options = {}) => {
+ this.close();
+
+ const { title = '权限申请说明', content = '' } = options;
+ this.title = title;
+ this.content = content;
+
+ this.createPopup();
+
+ this.popupView.show();
+ };
+
+ close = () => {
+ this.popupView && this.popupView.close();
+ };
+}
+
+export const popup = new NativePopup();
diff --git a/uni_modules/colorful-uni-perm/readme.md b/uni_modules/colorful-uni-perm/readme.md
new file mode 100644
index 0000000..8ef8dba
--- /dev/null
+++ b/uni_modules/colorful-uni-perm/readme.md
@@ -0,0 +1,249 @@
+### 用法说明
+
+**在 App.vue 生命周期内调用对应函数**
+
+```js
+import { createRequestPermissionListener, stopRequestPermissionListener } from '@/uni_modules/colorful-uni-perm';
+
+export default {
+ onLaunch: function (opt) {
+ // #ifdef APP-PLUS
+ if (plus.runtime.channel === 'huawei') {
+ // 创建权限申请监听
+ createRequestPermissionListener();
+ }
+ // #endif
+ },
+ onExit() {
+ // #ifdef APP-PLUS
+ if (plus.runtime.channel === 'huawei') {
+ // 清除权限申请监听
+ stopRequestPermissionListener();
+ }
+ // #endif
+ },
+};
+```
+
+### 已经支持以下安卓权限,对应的权限说明信息
+
+```js
+{
+ 'android.permission.BLUETOOTH_SCAN': {
+ title: '蓝牙扫描权限申请说明',
+ content: '应用需要扫描附近的蓝牙设备,以便进行连接或数据传输。'
+ },
+ 'android.permission.BLUETOOTH_CONNECT': {
+ title: '蓝牙连接权限申请说明',
+ content: '应用需要连接蓝牙设备,以便提供音频播放或数据通信功能。'
+ },
+ 'android.permission.READ_MEDIA_IMAGE': {
+ title: '读取图片权限申请说明',
+ content: '应用需要访问您的图片库,以便加载和选择照片。'
+ },
+ 'android.permission.READ_MEDIA_IMAGES': {
+ title: '读取图片权限申请说明',
+ content: '应用需要访问您的图片库,以便加载和选择照片。'
+ },
+ 'android.permission.READ_MEDIA_VIDEO': {
+ title: '读取视频权限申请说明',
+ content: '应用需要访问您的视频库,以便播放和选择视频文件。'
+ },
+ 'android.permission.READ_MEDIA_AUDIO': {
+ title: '读取音频权限申请说明',
+ content: '应用需要访问您的音频文件,以便播放音乐或录音。'
+ },
+ 'android.permission.CALL_PHONE': {
+ title: '拨打电话权限申请说明',
+ content: '应用需要拨打电话权限,以便直接拨打联系人或客服热线。'
+ },
+ 'android.permission.INTERNET': {
+ title: '网络权限申请说明',
+ content: '应用需要访问网络,以提供最新的内容和服务。'
+ },
+ 'android.permission.READ_EXTERNAL_STORAGE': {
+ title: '存储读取权限申请说明',
+ content: '应用需要读取您的存储,以便加载图片、视频等多媒体文件。'
+ },
+ 'android.permission.WRITE_EXTERNAL_STORAGE': {
+ title: '存储写入权限申请说明',
+ content: '应用需要写入您的存储,以便保存图片、视频等多媒体文件。'
+ },
+ 'android.permission.READ_PHONE_STATE': {
+ title: '设备信息权限申请说明',
+ content: '应用需要访问设备信息,以便提供更好的用户体验。'
+ },
+ 'android.permission.ACCESS_NETWORK_STATE': {
+ title: '网络状态权限申请说明',
+ content: '应用需要获取网络状态,以便优化网络请求。'
+ },
+ 'android.permission.ACCESS_WIFI_STATE': {
+ title: 'WiFi 状态权限申请说明',
+ content: '应用需要获取 WiFi 状态,以便优化网络连接。'
+ },
+ 'android.permission.CAMERA': {
+ title: '相机权限申请说明',
+ content: '应用需要访问您的相机,以便拍摄照片或扫描二维码。'
+ },
+ 'android.permission.ACCESS_COARSE_LOCATION': {
+ title: '定位权限申请说明',
+ content: '应用需要获取您的大致位置信息,以便提供基于位置的服务。'
+ },
+ 'android.permission.ACCESS_FINE_LOCATION': {
+ title: '精确定位权限申请说明',
+ content: '应用需要获取您的精确位置信息,以便提供导航等精准服务。'
+ },
+ 'android.permission.ACCESS_LOCATION_EXTRA_COMMANDS': {
+ title: '额外定位权限申请说明',
+ content: '应用需要使用额外的定位功能,以提升定位精度。'
+ },
+ 'android.permission.ACCESS_MOCK_LOCATION': {
+ title: '模拟定位权限申请说明',
+ content: '应用需要访问模拟位置,以便进行测试或特定功能。'
+ },
+ 'android.permission.READ_CONTACTS': {
+ title: '读取联系人权限申请说明',
+ content: '应用需要读取您的联系人信息,以便提供通讯录相关功能。'
+ },
+ 'android.permission.WRITE_CONTACTS': {
+ title: '写入联系人权限申请说明',
+ content: '应用需要写入您的联系人信息,以便管理通讯录。'
+ },
+ 'android.permission.BLUETOOTH': {
+ title: '蓝牙权限申请说明',
+ content: '应用需要访问蓝牙功能,以便连接设备或传输数据。'
+ },
+ 'android.permission.BLUETOOTH_ADMIN': {
+ title: '蓝牙管理权限申请说明',
+ content: '应用需要管理蓝牙功能,以便优化连接体验。'
+ },
+ 'android.permission.RECEIVE_SMS': {
+ title: '短信接收权限申请说明',
+ content: '应用需要读取短信,以便自动填充验证码或提供相关功能。'
+ },
+ 'android.permission.SEND_SMS': {
+ title: '短信发送权限申请说明',
+ content: '应用需要发送短信,以便提供短信验证等功能。'
+ },
+ 'android.permission.WRITE_SMS': {
+ title: '短信写入权限申请说明',
+ content: '应用需要写入短信,以便存储和管理您的短信信息。'
+ },
+ 'android.permission.READ_SMS': {
+ title: '短信读取权限申请说明',
+ content: '应用需要读取短信,以便自动填充验证码或提供相关功能。'
+ },
+ 'android.permission.INSTALL_PACKAGES': {
+ title: '安装应用权限申请说明',
+ content: '应用需要安装其他应用,以便提供扩展功能。'
+ },
+ 'android.permission.REQUEST_INSTALL_PACKAGES': {
+ title: '安装包权限申请说明',
+ content: '应用需要请求安装应用包权限,以便下载安装更新。'
+ },
+ 'com.android.launcher.permission.INSTALL_SHORTCUT': {
+ title: '创建快捷方式权限申请说明',
+ content: '应用需要创建桌面快捷方式,以便您快速访问应用。'
+ },
+ 'com.android.launcher.permission.UNINSTALL_SHORTCUT': {
+ title: '删除快捷方式权限申请说明',
+ content: '应用需要删除桌面快捷方式,以便管理您的快捷方式。'
+ },
+ 'android.permission.RECORD_AUDIO': {
+ title: '麦克风权限申请说明',
+ content: '应用需要访问麦克风,以便进行语音输入或语音通话。'
+ },
+ 'android.permission.MODIFY_AUDIO_SETTINGS': {
+ title: '音频设置修改权限申请说明',
+ content: '应用需要修改音频设置,以便优化音量或声音效果。'
+ },
+ 'android.permission.GET_ACCOUNTS': {
+ title: '账户权限申请说明',
+ content: '应用需要访问您的账户信息,以便提供个性化服务。'
+ },
+ 'android.permission.USE_FINGERPRINT': {
+ title: '指纹识别权限申请说明',
+ content: '应用需要使用指纹识别,以便进行身份验证。'
+ },
+ 'android.permission.USE_BIOMETRIC': {
+ title: '生物识别权限申请说明',
+ content: '应用需要使用生物识别功能(如面部识别),以便进行身份验证。'
+ },
+ 'android.permission.READ_CALENDAR': {
+ title: '读取日历权限申请说明',
+ content: '应用需要读取您的日历,以便提供日程管理功能。'
+ },
+ 'android.permission.WRITE_CALENDAR': {
+ title: '写入日历权限申请说明',
+ content: '应用需要写入您的日历,以便添加或修改日程。'
+ },
+ 'android.permission.READ_CALL_LOG': {
+ title: '读取通话记录权限申请说明',
+ content: '应用需要访问通话记录,以便提供通话管理或统计功能。'
+ },
+ 'android.permission.WRITE_CALL_LOG': {
+ title: '写入通话记录权限申请说明',
+ content: '应用需要写入通话记录,以便管理通话历史。'
+ },
+ 'android.permission.PROCESS_OUTGOING_CALLS': {
+ title: '处理拨出电话权限申请说明',
+ content: '应用需要访问拨出电话,以便提供通话拦截或号码识别功能。'
+ },
+ 'android.permission.BODY_SENSORS': {
+ title: '传感器权限申请说明',
+ content: '应用需要访问您的传感器数据,以便提供健康或运动相关功能。'
+ },
+ 'android.permission.ACTIVITY_RECOGNITION': {
+ title: '活动识别权限申请说明',
+ content: '应用需要访问您的活动状态,以便提供运动检测等功能。'
+ },
+ 'android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS': {
+ title: '电池优化忽略权限申请说明',
+ content: '应用需要忽略电池优化,以便在后台稳定运行。'
+ },
+ 'android.permission.FOREGROUND_SERVICE': {
+ title: '前台服务权限申请说明',
+ content: '应用需要运行前台服务,以便提供持续运行的功能,如音乐播放、导航等。'
+ },
+ 'android.permission.SYSTEM_ALERT_WINDOW': {
+ title: '悬浮窗权限申请说明',
+ content: '应用需要显示悬浮窗,以便提供浮动窗口功能,如聊天气泡、屏幕录制等。'
+ },
+ 'android.permission.WRITE_SETTINGS': {
+ title: '系统设置修改权限申请说明',
+ content: '应用需要修改系统设置,以便调整亮度、铃声等个性化配置。'
+ }
+}
+```
+
+**如果有不符合或缺少对应权限的提示信息,可以自己进行扩展**
+
+```js
+import { createRequestPermissionListener } from '@/uni_modules/colorful-uni-perm';
+
+createRequestPermissionListener({
+ 'android.permission.CAMERA': {
+ title: '相机权限申请说明',
+ content: '应用需要访问您的相机,以便拍摄照片或扫描二维码。',
+ },
+ 'android.permission.ACCESS_COARSE_LOCATION': {
+ title: '定位权限申请说明',
+ content: '应用需要获取您的大致位置信息,以便提供基于位置的服务。',
+ },
+});
+```
+
+### 注意
+
+只能监听通过 uniapp 或 plus 提供的权限申请时弹出提示,如果你使用原生的权限申请操作,无法监听到!
+
+所以,如果你是使用原生的权限申请操作,在使用权限前请主动使用以下方法请求权限
+
+```js
+import { permissionUtil } from '@/uni_modules/colorful-uni-perm';
+
+permissionUtil.requestAndroidPermission('android.permission.CAMERA').then((status) => {
+ // status 为 1 表示用户已授权,0 表示用户已拒绝, -1 表示用户永久拒绝
+ console.log('权限申请结果:', status);
+});
+```