From 47d10945a6b91194e6dafdab30c5cb4b817a8129 Mon Sep 17 00:00:00 2001 From: cansnow Date: Mon, 9 Feb 2026 03:03:22 +0800 Subject: [PATCH] 26 --- common/config.js | 12 +- js_sdk/wa-permission/permission.js | 272 ++++++++++++++++++ manifest.json | 9 +- package.json | 4 +- .../MessageItem/PictureMessageRender.vue | 14 +- util/im.js | 183 ++++++++++++ 6 files changed, 478 insertions(+), 16 deletions(-) create mode 100644 js_sdk/wa-permission/permission.js create mode 100644 util/im.js diff --git a/common/config.js b/common/config.js index 801daab..d9d7e9d 100644 --- a/common/config.js +++ b/common/config.js @@ -4,15 +4,9 @@ // const WS_URL = `ws://${BASE_HOST}:10001` const BASE_DOMAIN = 'www.shun777.com' -// const CHAT_URL = `https://${BASE_DOMAIN}/chat` -// const API_URL = `https://${BASE_DOMAIN}/api` -// const WS_URL = `wss://${BASE_DOMAIN}/msg_gateway` -// const CHAT_URL = `http://${BASE_DOMAIN}/api` -// const API_URL = `http://${BASE_DOMAIN}/imapi` -// const WS_URL = `ws://${BASE_DOMAIN}/ws` -const CHAT_URL = `http://103.39.222.184:8585/api` -const API_URL = `http://103.39.222.184:10002` -const WS_URL = `ws://103.39.222.184:10001` +const CHAT_URL = `https://${BASE_DOMAIN}/api` +const API_URL = `https://${BASE_DOMAIN}/imapi` +const WS_URL = `wss://${BASE_DOMAIN}/msg_gateway` const version = '2.0.6' diff --git a/js_sdk/wa-permission/permission.js b/js_sdk/wa-permission/permission.js new file mode 100644 index 0000000..9981504 --- /dev/null +++ b/js_sdk/wa-permission/permission.js @@ -0,0 +1,272 @@ +/** + * 本模块封装了Android、iOS的应用权限判断、打开应用权限设置界面、以及位置系统服务是否开启 + */ + +var isIos +// #ifdef APP-PLUS +isIos = (plus.os.name == "iOS") +// #endif + +// 判断推送权限是否开启 +function judgeIosPermissionPush() { + var result = false; + var UIApplication = plus.ios.import("UIApplication"); + var app = UIApplication.sharedApplication(); + var enabledTypes = 0; + if (app.currentUserNotificationSettings) { + var settings = app.currentUserNotificationSettings(); + enabledTypes = settings.plusGetAttribute("types"); + console.log("enabledTypes1:" + enabledTypes); + if (enabledTypes == 0) { + console.log("推送权限没有开启"); + } else { + result = true; + console.log("已经开启推送功能!") + } + plus.ios.deleteObject(settings); + } else { + enabledTypes = app.enabledRemoteNotificationTypes(); + if (enabledTypes == 0) { + console.log("推送权限没有开启!"); + } else { + result = true; + console.log("已经开启推送功能!") + } + console.log("enabledTypes2:" + enabledTypes); + } + plus.ios.deleteObject(app); + plus.ios.deleteObject(UIApplication); + return result; +} + +// 判断定位权限是否开启 +function judgeIosPermissionLocation() { + var result = false; + var cllocationManger = plus.ios.import("CLLocationManager"); + var status = cllocationManger.authorizationStatus(); + result = (status != 2) + console.log("定位权限开启:" + result); + // 以下代码判断了手机设备的定位是否关闭,推荐另行使用方法 checkSystemEnableLocation + /* var enable = cllocationManger.locationServicesEnabled(); + var status = cllocationManger.authorizationStatus(); + console.log("enable:" + enable); + console.log("status:" + status); + if (enable && status != 2) { + result = true; + console.log("手机定位服务已开启且已授予定位权限"); + } else { + console.log("手机系统的定位没有打开或未给予定位权限"); + } */ + plus.ios.deleteObject(cllocationManger); + return result; +} + +// 判断麦克风权限是否开启 +function judgeIosPermissionRecord() { + var result = false; + var avaudiosession = plus.ios.import("AVAudioSession"); + var avaudio = avaudiosession.sharedInstance(); + var permissionStatus = avaudio.recordPermission(); + console.log("permissionStatus:" + permissionStatus); + if (permissionStatus == 1684369017 || permissionStatus == 1970168948) { + console.log("麦克风权限没有开启"); + } else { + result = true; + console.log("麦克风权限已经开启"); + } + plus.ios.deleteObject(avaudiosession); + return result; +} + +// 判断相机权限是否开启 +function judgeIosPermissionCamera() { + var result = false; + var AVCaptureDevice = plus.ios.import("AVCaptureDevice"); + var authStatus = AVCaptureDevice.authorizationStatusForMediaType('vide'); + console.log("authStatus:" + authStatus); + if (authStatus == 3) { + result = true; + console.log("相机权限已经开启"); + } else { + console.log("相机权限没有开启"); + } + plus.ios.deleteObject(AVCaptureDevice); + return result; +} + +// 判断相册权限是否开启 +function judgeIosPermissionPhotoLibrary() { + var result = false; + var PHPhotoLibrary = plus.ios.import("PHPhotoLibrary"); + var authStatus = PHPhotoLibrary.authorizationStatus(); + console.log("authStatus:" + authStatus); + if (authStatus == 3) { + result = true; + console.log("相册权限已经开启"); + } else { + console.log("相册权限没有开启"); + } + plus.ios.deleteObject(PHPhotoLibrary); + return result; +} + +// 判断通讯录权限是否开启 +function judgeIosPermissionContact() { + var result = false; + var CNContactStore = plus.ios.import("CNContactStore"); + var cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0); + if (cnAuthStatus == 3) { + result = true; + console.log("通讯录权限已经开启"); + } else { + console.log("通讯录权限没有开启"); + } + plus.ios.deleteObject(CNContactStore); + return result; +} + +// 判断日历权限是否开启 +function judgeIosPermissionCalendar() { + var result = false; + var EKEventStore = plus.ios.import("EKEventStore"); + var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0); + if (ekAuthStatus == 3) { + result = true; + console.log("日历权限已经开启"); + } else { + console.log("日历权限没有开启"); + } + plus.ios.deleteObject(EKEventStore); + return result; +} + +// 判断备忘录权限是否开启 +function judgeIosPermissionMemo() { + var result = false; + var EKEventStore = plus.ios.import("EKEventStore"); + var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1); + if (ekAuthStatus == 3) { + result = true; + console.log("备忘录权限已经开启"); + } else { + console.log("备忘录权限没有开启"); + } + plus.ios.deleteObject(EKEventStore); + return result; +} + +// Android权限查询 +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 + } + resolve(result); + // 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限 + // if (result != 1) { + // gotoAppPermissionSetting() + // } + }, + function(error) { + console.log('申请权限错误:' + error.code + " = " + error.message); + resolve({ + code: error.code, + message: error.message + }); + } + ); + }); +} + +// 使用一个方法,根据参数判断权限 +function judgeIosPermission(permissionID) { + if (permissionID == "location") { + return judgeIosPermissionLocation() + } else if (permissionID == "camera") { + return judgeIosPermissionCamera() + } else if (permissionID == "photoLibrary") { + return judgeIosPermissionPhotoLibrary() + } else if (permissionID == "record") { + return judgeIosPermissionRecord() + } else if (permissionID == "push") { + return judgeIosPermissionPush() + } else if (permissionID == "contact") { + return judgeIosPermissionContact() + } else if (permissionID == "calendar") { + return judgeIosPermissionCalendar() + } else if (permissionID == "memo") { + return judgeIosPermissionMemo() + } + return false; +} + +// 跳转到**应用**的权限页面 +function gotoAppPermissionSetting() { + if (isIos) { + var UIApplication = plus.ios.import("UIApplication"); + var application2 = UIApplication.sharedApplication(); + var NSURL2 = plus.ios.import("NSURL"); + // var setting2 = NSURL2.URLWithString("prefs:root=LOCATION_SERVICES"); + var setting2 = NSURL2.URLWithString("app-settings:"); + application2.openURL(setting2); + + plus.ios.deleteObject(setting2); + plus.ios.deleteObject(NSURL2); + plus.ios.deleteObject(application2); + } else { + // console.log(plus.device.vendor); + var Intent = plus.android.importClass("android.content.Intent"); + var Settings = plus.android.importClass("android.provider.Settings"); + var Uri = plus.android.importClass("android.net.Uri"); + var mainActivity = plus.android.runtimeMainActivity(); + var intent = new Intent(); + intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + var uri = Uri.fromParts("package", mainActivity.getPackageName(), null); + intent.setData(uri); + mainActivity.startActivity(intent); + } +} + +// 检查系统的设备服务是否开启 +// var checkSystemEnableLocation = async function () { +function checkSystemEnableLocation() { + if (isIos) { + var result = false; + var cllocationManger = plus.ios.import("CLLocationManager"); + var result = cllocationManger.locationServicesEnabled(); + console.log("系统定位开启:" + result); + plus.ios.deleteObject(cllocationManger); + return result; + } else { + var context = plus.android.importClass("android.content.Context"); + var locationManager = plus.android.importClass("android.location.LocationManager"); + var main = plus.android.runtimeMainActivity(); + var mainSvr = main.getSystemService(context.LOCATION_SERVICE); + var result = mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER); + console.log("系统定位开启:" + result); + return result + } +} + +module.exports = { + judgeIosPermission: judgeIosPermission, + requestAndroidPermission: requestAndroidPermission, + checkSystemEnableLocation: checkSystemEnableLocation, + gotoAppPermissionSetting: gotoAppPermissionSetting +} diff --git a/manifest.json b/manifest.json index dead263..e36313c 100644 --- a/manifest.json +++ b/manifest.json @@ -2,8 +2,8 @@ "name" : "瞬聊", "appid" : "__UNI__E41111F", "description" : "一款即时聊天软件", - "versionName" : "3.4.6", - "versionCode" : 346, + "versionName" : "3.4.8", + "versionCode" : 348, "transformPx" : false, "app-plus" : { "bounce" : "none", @@ -51,7 +51,10 @@ "", "", "", - "" + "", + "", + "", + "" ], "abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ], "minSdkVersion" : 21, diff --git a/package.json b/package.json index 217f025..23842d8 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "dependencies": { + "dependencies": { "@openim/client-sdk": "^0.0.11-ahpha.1", "crypto-js": "^4.2.0", "date-fns": "^2.30.0", @@ -14,4 +14,4 @@ "worker-loader": "^3.0.8", "worker-plugin": "^5.0.1" } -} +} \ No newline at end of file diff --git a/pages/conversation/chating/components/MessageItem/PictureMessageRender.vue b/pages/conversation/chating/components/MessageItem/PictureMessageRender.vue index c887372..d221455 100644 --- a/pages/conversation/chating/components/MessageItem/PictureMessageRender.vue +++ b/pages/conversation/chating/components/MessageItem/PictureMessageRender.vue @@ -49,7 +49,12 @@ const imageWidth = this.message.pictureElem.sourcePicture.width; const aspectRatio = imageHeight / imageWidth; return 120 * aspectRatio; - }, + } + }, + watch: { + src(newVal, oldVal) { + console.log(newVal,oldVal); + } }, created() { this.init(); @@ -59,7 +64,12 @@ const self = this; let url = ""; // 如果有远程 snapshotUrl,则下载到 coverCachePath - const snapshotUrl = (this.message.pictureElem.snapshotPicture?.url ?? this.message.pictureElem.sourcePath ); + //const snapshotUrl = (this.message.pictureElem.snapshotPicture?.url ?? this.message.pictureElem.sourcePath ); + const snapshotUrl = this.message.pictureElem.sourcePicture?.url; + if(!snapshotUrl){ + console.log(this.message); + return; + } //console.log(snapshotUrl); util.cacheFile(snapshotUrl,`${this.conversationID}`).then((fn)=>{ self.coverDownloading = false; diff --git a/util/im.js b/util/im.js new file mode 100644 index 0000000..573c1ea --- /dev/null +++ b/util/im.js @@ -0,0 +1,183 @@ + +import IMSDK,{IMMethods} from "openim-uniapp-polyfill"; +import {offlinePushInfo} from "@/util/imCommon"; +import {upload} from "@/api/login.js"; +import {getVideoInfo} from "@/util/common"; +export const imapi = (method,data)=>{ + return new Promise((resolve, reject) => { + IMSDK.asyncApi(method,IMSDK.uuid(),data) + .then(res=>{ + return resolve(res); + }) + .catch(e=>{ + return reject(e); + }) + }); +}; +export const copyFileToTempPath = (src) => { + //plus.io.PRIVATE_DOC; + console.log('src', src); + console.log('src', src.includes(plus.io.PRIVATE_DOC)); + return new Promise((resolve, reject) => { + plus.io.resolveLocalFileSystemURL(src, (entry) => { + console.log('entry name', entry.name); + console.log('dir', '_doc/uniapp_temp/'); + entry.copyTo('_doc/uniapp_temp/', entry.name, (newEntry) => { + console.log('newEntry', newEntry.fullPath); + resolve(newEntry.toLocalURL()); + }, reject); + }, reject); + }); +} +export const getPurePath = (path)=>{ + if(!path)return ""; + const prefix = "file://"; + const relativeRrefix = "_doc/"; + if (path.includes(prefix)) { + path = path.replace(prefix, ""); + } + if (path.includes(relativeRrefix)) { + path = plus.io.convertLocalFileSystemURL(path); + } + return path; +} +export const createVoiceMessage = async (path)=>{ +}; +export const createFileMessage = async (path)=>{ +}; +export const getVideoCover = async (path)=>{ + return new Promise((resolve, reject) => { + IMSDK.getVideoCover(path) + .then(res=>{ + console.log('res', res); + return resolve(res); + }) + .catch(e=>{ + console.log('e', e); + return reject(e); + }) + }); +}; +export const createVideoMessage = (path)=>{ + return new Promise(async(resolve, reject) => { + console.log('处理前的可用路径', path); + const realVideoPath = await copyFileToTempPath(path); + //const realVideoPath = await getPurePath(path); + console.log('处理后的可用路径', realVideoPath); + const info = await getVideoInfo(realVideoPath); + console.log('info', info); + const cover = await getVideoCover(realVideoPath); + console.log('cover', cover); + const coverresult = await upload(cover,{savePath: "msg"}); + console.log('coverresult', coverresult); + if(coverresult.code !=0){ + uni.$u.toast(coverresult.msg); + return reject(coverresult.msg); + } + const videoresult = await upload(realVideoPath,{savePath: "msg"},(res)=>{ + uni.showLoading({ + title: res.progress+"%", + }) + }); + console.log('videoresult', videoresult); + uni.hideLoading(); + + if(videoresult.code !=0){ + uni.$u.toast(videoresult.msg); + return reject(videoresult.msg); + } + imapi(IMMethods.CreateVideoMessageByURL,{ + videoPath: realVideoPath, + duration: info.duration, + videoType: info.type.split("/")[1], + snapshotPath: cover, + videoUUID: IMSDK.uuid(), + videoUrl: videoresult.data[0].file_url, + videoSize: videoresult.data[0].size, + snapshotUUID: IMSDK.uuid(), + snapshotSize: coverresult.data[0].size, + snapshotUrl: coverresult.data[0].file_url, + snapshotWidth: coverresult.data[0].file_width, + snapshotHeight: coverresult.data[0].file_height, + snapShotType: coverresult.data[0].extension, + }).then(res=>{ + console.log('res', res); + resolve(res); + }).catch(err=>{ + console.log('err', err); + reject(err); + }) + return ; + //const realVideoPath = await getPurePath(path); + //console.log('处理后的可用路径', realVideoPath); + //const info = await getVideoInfo(realVideoPath); + //const cover = await getVideoCover(path); + //const res1 = await IMSDK.getVideoCover(path); + //console.log(res1.path); + const videoParams = { + videoPath: realVideoPath, + videoType: "mp4", + duration: info.duration, + snapshotPath: getPurePath(res1.path), + //snapshotPath: getPurePath(cover), + }; + console.log('videoParams', videoParams); + message = await IMSDK.asyncApi( + IMMethods.CreateVideoMessageFromFullPath, + IMSDK.uuid(), + videoParams + ); + }); +}; +export const createImageMessage = async (path)=>{ + return new Promise(async (resolve, reject) => { + const result = await upload(path,{savePath: "msg"}); + if(result.code !=0){ + uni.$u.toast(result.msg); + return ; + } + const picBaseInfo = { + uuid: IMSDK.uuid(), + type: result.data[0].extension, + size: result.data[0].size, + width: result.data[0].file_width, + height: result.data[0].file_height, + url: result.data[0].file_url + }; + + const message = await IMSDK.asyncApi(IMMethods.CreateImageMessageByURL,IMSDK.uuid(),{ + sourcePicture: picBaseInfo, + bigPicture: picBaseInfo, + snapshotPicture: picBaseInfo, + sourcePath: result.data[0].file_url + }); + console.log('message', message); + return resolve(message); + const tempPath = await copyFileToTempPath(path); + console.log(tempPath); + imapi(IMMethods.CreateImageMessageFromFullPath,getPurePath(tempPath)).then(res=>{ + console.log(res); + resolve(res); + }).catch(err=>{ + console.log(err); + reject(err); + }) + }); +} +export const sendMessage = (message, user_id, group_id) => { + let method = IMMethods.SendMessage; + if([MessageType.PictureMessage,MessageType.VoiceMessage,MessageType.VideoMessage,MessageType.FileMessage].includes(message.contentType)){ + method = IMMethods.SendMessageNotOss; + } + return imapi(method,{recvID: user_id,groupID: group_id,message,offlinePushInfo,}); +}; +export default { + imapi, + sendMessage, + createVoiceMessage, + createVideoMessage, + createFileMessage, + createImageMessage, + getPurePath, + copyFileToTempPath, +} \ No newline at end of file