diff --git a/App.vue b/App.vue index 7722c59..c14e36f 100644 --- a/App.vue +++ b/App.vue @@ -1,72 +1,219 @@ + /* common css for page */ + // uni-page-body, + // html, + // body, + // page { + // width: 100% !important; + // height: 100% !important; + // overflow: hidden; + // } + \ No newline at end of file diff --git a/TUIKit/components/TUIChat/message-input-toolbar/call-view/index.vue b/TUIKit/components/TUIChat/message-input-toolbar/call-view/index.vue index 3379516..027abd6 100644 --- a/TUIKit/components/TUIChat/message-input-toolbar/call-view/index.vue +++ b/TUIKit/components/TUIChat/message-input-toolbar/call-view/index.vue @@ -1,106 +1,102 @@ - + \ No newline at end of file diff --git a/manifest.json b/manifest.json index 47bb6d0..7acf74e 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { "name" : "密谈IM", - "appid" : "__UNI__D40A151", + "appid" : "__UNI__BE00EFC", "description" : "", "versionName" : "1.1.3", "versionCode" : 112, @@ -112,27 +112,13 @@ } }, "nativePlugins" : { - "RongCloud-Beauty" : { - "__plugin_info__" : { - "name" : "RCUniBeauty", - "description" : "融云基础版美颜插件,服务于 RCUniRtc 或 RCUniCall", - "platforms" : "Android,iOS", - "url" : "https://ext.dcloud.net.cn/plugin?id=7982", - "android_package_name" : "", - "ios_bundle_id" : "", - "isCloud" : true, - "bought" : 1, - "pid" : "7982", - "parameters" : {} - } - }, "RongCloud-Call" : { "__plugin_info__" : { "name" : "RCUniCall", "description" : "融云实时音视频 SDK uni 原生插件", "platforms" : "Android,iOS", "url" : "https://ext.dcloud.net.cn/plugin?id=6372", - "android_package_name" : "uni.app.UNI9EFDC69WWCC", + "android_package_name" : "uni.app.UNI9EFDC69", "ios_bundle_id" : "", "isCloud" : true, "bought" : 1, @@ -146,7 +132,7 @@ "description" : "融云即时通讯 SDK uni 原生插件V2", "platforms" : "Android,iOS", "url" : "https://ext.dcloud.net.cn/plugin?id=9227", - "android_package_name" : "uni.app.UNI9EFDC69WWCC", + "android_package_name" : "uni.app.UNI9EFDC69", "ios_bundle_id" : "", "isCloud" : true, "bought" : 1, diff --git a/pages.json b/pages.json index d201486..0d0d889 100644 --- a/pages.json +++ b/pages.json @@ -444,14 +444,14 @@ { "path": "pages/room/room", "style": { - "navigationBarTitleText": "拨打电话", + "navigationBarTitleText": "拨打视频", "navigationStyle": "custom" } }, { "path": "pages/room/incom", "style": { - "navigationBarTitleText": "拨打视频", + "navigationBarTitleText": "拨打电话", "navigationStyle": "custom" } }, diff --git a/pages/room/incom.vue b/pages/room/incom.vue index 73a14fb..fc2668c 100644 --- a/pages/room/incom.vue +++ b/pages/room/incom.vue @@ -1,395 +1,379 @@ diff --git a/pages/room/room.nvue b/pages/room/room.nvue index f010f5e..c939d28 100644 --- a/pages/room/room.nvue +++ b/pages/room/room.nvue @@ -150,24 +150,16 @@ }, onUnload() { call.hangup() - // this.removeAllListeners() }, onHide() { const session = call.getCurrentCallSession() if (session) { call.hangup() } - // this.removeAllListeners() + uni.$off('OnCallDisconnected') + uni.$off('OnCallConnected') }, methods: { - removeAllListeners(){ - //移除监听-接收到通话呼入 - call.removeRemoteUserJoinedListener(); - // 移除监听-通话已结束 - call.removeCallDisconnectedListener(); - // 移除监听-通话出现错误的回调 - call.removeErrorListener(); - }, changeMediaType() { if (this.mediaTypeCur == 'video') { this.mediaTypeCur = 'audio' @@ -284,9 +276,9 @@ hangup() { this.isSelf = true call.hangup() - uni.navigateBack({ - delta: 1 - }) + // uni.navigateBack({ + // delta: 1 + // }) }, accept() { call.accept() @@ -324,12 +316,61 @@ ) } }, - onCallConnected() { let context = this console.log('oncallconnected接收了') + console.log('call: ',call); + // 使用 Promise 确保 call 对象完全初始化 + this.initializeCall(call) + .then(() => { + this.processCallSession() + }) + .catch(error => { + console.error('初始化通话失败:', error) + }) + }, + async initializeCall(callObj) { + // 等待 call 对象就绪 + await this.waitForCallReady(callObj) + + // 设置扬声器 + if (callObj.enableSpeaker && typeof callObj.enableSpeaker === 'function') { + try { + callObj.enableSpeaker(true) + } catch (error) { + console.warn('设置扬声器失败:', error) + } + } + + return callObj + }, + + waitForCallReady(callObj, timeout = 2000) { + return new Promise((resolve, reject) => { + const startTime = Date.now() + + const check = () => { + const now = Date.now() + + if (callObj && + callObj.enableSpeaker && + callObj.getCurrentCallSession && + typeof callObj.getCurrentCallSession === 'function') { + resolve(callObj) + } else if (now - startTime > timeout) { + reject(new Error('call 对象初始化超时')) + } else { + setTimeout(check, 50) + } + } + + check() + }) + }, + + processCallSession(){ + // call.enableSpeaker(true) this.mediaTypeCur = this.mediaType - call.enableSpeaker(true) this.currentCallSession = call.getCurrentCallSession() this.callWay = this.currentCallSession.callType this.users = this.currentCallSession.users @@ -347,6 +388,7 @@ ) { //视频是两个的时候 if (this.currentCallSession.users.length <= 2) { + console.log("视频是两个的时候"); setTimeout(() => { this.systemInfoSync( this.currentCallSession.mine.userId, @@ -397,6 +439,7 @@ } } }, + systemInfoSync(userId, ref, isZOrderOnTop) { switch (uni.getSystemInfoSync().platform) { case 'android': diff --git a/stores/user.js b/stores/user.js index 2d4296b..b08c09d 100644 --- a/stores/user.js +++ b/stores/user.js @@ -1,326 +1,302 @@ -import { defineStore } from 'pinia' import { - getToken, - getUserInfoData, - setUserInfoData, - removeUserInfoData, - getSig, - setSig, - removeSig, - getFontSize, - setFontSize, - removeFontSize + defineStore +} from 'pinia' +import { + getToken, + getUserInfoData, + setUserInfoData, + removeUserInfoData, + getSig, + setSig, + removeSig, + getFontSize, + setFontSize, + removeFontSize } from '@/utils/storage' // #ifdef APP-PLUS -import { useLoginState } from '@/uni_modules/tuikit-atomic-x/state/LoginState' +import { + useLoginState +} from '@/uni_modules/tuikit-atomic-x/state/LoginState' import * as CallLib from '@/uni_modules/RongCloud-CallWrapper/lib/index' import RCIMIWEngine from '@/uni_modules/RongCloud-IMWrapper-V2/js_sdk/RCIMEngine' -import { reasonDeal, errorDeal, imCode } from '@/utils/code.js' +import { + reasonDeal, + errorDeal, + imCode +} from '@/utils/code.js' // #endif // #ifdef H5 -import { useLoginState } from 'tuikit-atomicx-vue3' +import { + useLoginState +} from 'tuikit-atomicx-vue3' // #endif -import { useTokenStore } from './token' -import { getUserData, userLogout, updateUserData } from '@/api' -import { ref } from 'vue' -import { useUI } from '@/utils/use-ui' -import { reLaunch } from '@/utils/router' -import { getTencentUserSig } from '@/api' -import { TUILogin } from '@tencentcloud/tui-core-lite' -import { TUIChatEngine } from '@tencentcloud/chat-uikit-engine-lite' -import { getUserIntegral } from '@/api/my-index' -import { removeFriendList, removeGroupList } from '../utils/storage' -import { getRongYunLoginInfo } from '../api' +import { + useTokenStore +} from './token' +import { + getUserData, + userLogout, + updateUserData +} from '@/api' +import { + ref +} from 'vue' +import { + useUI +} from '@/utils/use-ui' +import { + reLaunch +} from '@/utils/router' +import { + getTencentUserSig +} from '@/api' +import { + TUILogin +} from '@tencentcloud/tui-core-lite' +import { + TUIChatEngine +} from '@tencentcloud/chat-uikit-engine-lite' +import { + getUserIntegral +} from '@/api/my-index' +import { + removeFriendList, + removeGroupList +} from '../utils/storage' +import { + getRongYunLoginInfo +} from '../api' +import permision from "@/js_sdk/wa-permission/permission.js" export const useUserStore = defineStore('user', () => { - const { clearToken } = useTokenStore() - const { showDialog, showToast } = useUI() + const { + clearToken + } = useTokenStore() + const { + showDialog, + showToast + } = useUI() - const userInfo = ref( - getUserInfoData() ? JSON?.parse(getUserInfoData()) : {} - ) - /** 用户字体大小 */ - const fontSizeData = ref(getFontSize()) + const userInfo = ref( + getUserInfoData() ? JSON?.parse(getUserInfoData()) : {} + ) + /** 用户字体大小 */ + const fontSizeData = ref(getFontSize()) - /** 腾讯 IM 存储数据 */ - const tencentUserSig = ref(getSig() ? JSON?.parse(getSig()) : {}) + /** 腾讯 IM 存储数据 */ + const tencentUserSig = ref(getSig() ? JSON?.parse(getSig()) : {}) - /** 用户积分数 */ - const integralData = ref(0) - /** 融云 IM 引擎 */ - const imEngine = ref(null) + /** 用户积分数 */ + const integralData = ref(0) + /** 融云 IM 引擎 */ + const imEngine = ref(null) - /** - * 获取用户信息(可从缓存或接口) - */ - const fetchUserInfo = async () => { - // 尝试从本地缓存读取 - const cachedToken = getToken() - const cachedUserInfo = getUserInfoData() - const cachedSig = getSig() + /** + * 获取用户信息(可从缓存或接口) + */ + const fetchUserInfo = async () => { + // 尝试从本地缓存读取 + const cachedToken = getToken() + const cachedUserInfo = getUserInfoData() + const cachedSig = getSig() - if (cachedToken && cachedUserInfo) { - userInfo.value = JSON.parse(cachedUserInfo) - tencentUserSig.value = JSON.parse(cachedSig) - loginTencentIM() - return - } - await getIntegral() - const res = await getUserData() - await setUserInfo(res.data) - loginTencentIM() - return - } + if (cachedToken && cachedUserInfo) { + userInfo.value = JSON.parse(cachedUserInfo) + tencentUserSig.value = JSON.parse(cachedSig) + loginTencentIM() + return + } + await getIntegral() + const res = await getUserData() + await setUserInfo(res.data) + loginTencentIM() + return + } - /** - * 设置用户信息 - */ - const setUserInfo = async data => { - const res = await getTencentUserSig() - const ryData = await getRongYunLoginInfo() - const IM_DATA = { - ...res.data, - ...ryData.data - } - tencentUserSig.value = IM_DATA - userInfo.value = data - setUserInfoData(data) - setSig(IM_DATA) - } + /** + * 设置用户信息 + */ + const setUserInfo = async data => { + const res = await getTencentUserSig() + const ryData = await getRongYunLoginInfo() + const IM_DATA = { + ...res.data, + ...ryData.data + } + tencentUserSig.value = IM_DATA + userInfo.value = data + setUserInfoData(data) + setSig(IM_DATA) + } - /** 获取用户积分 */ - const getIntegral = async () => { - const res = await getUserIntegral() - integralData.value = res.data.availablePoints - } + /** 获取用户积分 */ + const getIntegral = async () => { + const res = await getUserIntegral() + integralData.value = res.data.availablePoints + } - /** - * 登录腾讯 IM - */ - const loginTencentIM = async () => { - await refreshUserInfo() - await TUILogin.login({ - SDKAppID: tencentUserSig.value.sdkappID, - userID: tencentUserSig.value.userId, - userSig: tencentUserSig.value.userSig, - framework: `vue3` - }) + /** + * 登录腾讯 IM + */ + const loginTencentIM = async () => { + await refreshUserInfo() + await TUILogin.login({ + SDKAppID: tencentUserSig.value.sdkappID, + userID: tencentUserSig.value.userId, + userSig: tencentUserSig.value.userSig, + framework: `vue3` + }) - await TUIChatEngine.login({ - SDKAppID: tencentUserSig.value.sdkappID, - userID: tencentUserSig.value.userId, - userSig: tencentUserSig.value.userSig, - useUploadPlugin: true // 使用文件上传插件 - }) - // #ifdef H5 - await useLoginState().login({ - SDKAppID: tencentUserSig.value.sdkappID, - userID: tencentUserSig.value.userId, - userSig: tencentUserSig.value.userSig - }) - // #endif + await TUIChatEngine.login({ + SDKAppID: tencentUserSig.value.sdkappID, + userID: tencentUserSig.value.userId, + userSig: tencentUserSig.value.userSig, + useUploadPlugin: true // 使用文件上传插件 + }) + // #ifdef H5 + await useLoginState().login({ + SDKAppID: tencentUserSig.value.sdkappID, + userID: tencentUserSig.value.userId, + userSig: tencentUserSig.value.userSig + }) + // #endif - // #ifdef APP-PLUS - await useLoginState().login({ - sdkAppID: tencentUserSig.value.sdkappID, - userID: tencentUserSig.value.userId, - userSig: tencentUserSig.value.userSig - }) - console.log(tencentUserSig.value.appKey, '====') - await connectIM() - // #endif - // #ifdef APP-PLUS - // CallLib.init({}) - CallLib.onCallReceived(res => { - console.log( - 'Engine:OnCallReceived=>' + '监听通话呼入, 目标id=>', - res.data - ) - console.log('res: ',res.data); - if (res.data.targetId) { - // let url = res.data.mediaType == 0 ? "" : "/pages/room/room" - uni.setStorageSync('room-parameters', { - callType: 'in', - mediaType: res.data.mediaType === 0 ? 'audio' : 'video' + // #ifdef APP-PLUS + await useLoginState().login({ + sdkAppID: tencentUserSig.value.sdkappID, + userID: tencentUserSig.value.userId, + userSig: tencentUserSig.value.userSig + }) + console.log(tencentUserSig.value.appKey, '====') + await connectIM() + // #endif + } + + //连接融云IM + const connectIM = async () => { + let options = {} + imEngine.value = await RCIMIWEngine.create(tencentUserSig.value.appKey, options) + imEngine.value.setOnConnectedListener((res) => { + if (res.code != 0) { + uni.hideLoading(); + // uni.showToast({ + // title: 'OnCon:' + res.code, + // icon: 'error' + // }) + console.log("连接已存在"); + // return + } + //连接成功 + CallLib.init({}); + console.log('call.init') + uni.hideLoading(); + uni.showToast({ + title: res.userId }); - uni.navigateTo("/pages/room/incom", { - type: res.data.extra, - callType: 'in', - mediaType: res.data.mediaType == 0 ? "audio" : "video", - userID: res.data.mine.userId // 对方的用户id - }) - } - }) - - /** 挂断电话 */ - CallLib.onCallDisconnected(res => { - console.log( - 'Engine:OnCallDisconnected=>' + '挂断成功, 挂断原因=>', - res.data.reason - ) - uni.navigateBack() - }) - - CallLib.onError(res => { - console.log('通话过程中,发生异常,异常原因=>', res.data.reason) - uni.navigateBack() - }) - - - // #endif - } + if (uni.getSystemInfoSync().platform === 'android') { + permision.requestAndroidPermission('android.permission.CAMERA'); + permision.requestAndroidPermission('android.permission.RECORD_AUDIO'); + } + }); + let code = await imEngine.value.connect(tencentUserSig.value.ryToken, 10) + if (code != 0) { + uni.hideLoading(); + uni.showToast({ + title: 'connect:' + code, + icon: 'error' + }) + } + } - //连接融云IM - const connectIM = async () => { - const options = { - naviServer: '' - } - imEngine.value = await RCIMIWEngine.create( - tencentUserSig.value.appKey, - options - ) - imEngine.value.setOnConnectedListener(res => { - if (res.code != 0) { - uni.hideLoading() - uni.showToast({ - title: 'OnCon:' + res.code, - icon: 'error' - }) - return - } - //连接成功 - CallLib.init({}) - console.log('call.init') - // this.libPage = true; - // this.loginUserId = res.userId; - uni.hideLoading() - console.log('登录成功') - }) - const callback = { - onDatabaseOpened: res => { - console.log('数据库打开') - }, - onConnected: res => { - console.log(res) - if (res.code === 0) { - // uni.showToast({ - // title: '连接成功', - // icon: 'none' - // }) - console.log('连接成功') - } else if (res.code === 34001) { - // uni.showToast({ - // title: '连接已存在,不需要再连接', - // icon: 'none' - // }) - console.log('连接已存在,不需要再连接') - } - - } - } - let code = await imEngine.value.connect( - tencentUserSig.value.ryToken, - 10, - callback - ) - if (code != 0) { - uni.hideLoading() - uni.showToast({ - title: 'connect:' + code, - icon: 'error' - }) - } - } + /** + * 清除用户信息(退出登录) + */ + const clearUserInfo = async () => { + const show = await showDialog('提示', '确定要退出登录吗?') + if (show) { + await logout() + } + } - /** - * 清除用户信息(退出登录) - */ - const clearUserInfo = async () => { - const show = await showDialog('提示', '确定要退出登录吗?') - if (show) { - await logout() - } - } + /** + * 退出登录(不带提示) + */ + const logout = async () => { + if (!userInfo.value) return + try { + userInfo.value = null - /** - * 退出登录(不带提示) - */ - const logout = async () => { - if (!userInfo.value) return - try { - userInfo.value = null + await userLogout() + await TUILogin.logout() + await TUIChatEngine.logout() + // #ifdef APP-PLUS + removeFriendList() + removeGroupList() + await useLoginState().logout() + // #endif + // #ifdef H5 + await useLoginState().logout() + // #endif + clearAllUserInfo() + await showToast('退出登录成功', 'success') + reLaunch('/pages/login/login') + } catch (error) { + clearAllUserInfo() + await showToast('退出登录成功', 'success') + reLaunch('/pages/login/login') + } + } - await userLogout() - await TUILogin.logout() - await TUIChatEngine.logout() - // #ifdef APP-PLUS - removeFriendList() - removeGroupList() - await useLoginState().logout() - // #endif - // #ifdef H5 - await useLoginState().logout() - // #endif - clearAllUserInfo() - await showToast('退出登录成功', 'success') - reLaunch('/pages/login/login') - } catch (error) { - clearAllUserInfo() - await showToast('退出登录成功', 'success') - reLaunch('/pages/login/login') - } - } + /** 清空所有用户缓存 */ + const clearAllUserInfo = async () => { + userInfo.value = null + tencentUserSig.value = null + fontSizeData.value = 26 + clearToken() + removeUserInfoData() + removeSig() + removeFontSize() + } - /** 清空所有用户缓存 */ - const clearAllUserInfo = async () => { - userInfo.value = null - tencentUserSig.value = null - fontSizeData.value = 26 - clearToken() - removeUserInfoData() - removeSig() - removeFontSize() - } + /** 刷新用户信息(如用户信息被修改) */ + const refreshUserInfo = async () => { + const res = await getUserData() + await getIntegral() + await setUserInfoData(res.data) + userInfo.value = res.data + } - /** 刷新用户信息(如用户信息被修改) */ - const refreshUserInfo = async () => { - const res = await getUserData() - await getIntegral() - await setUserInfoData(res.data) - userInfo.value = res.data - } + /** + * 更新部分用户信息(例如昵称、头像) + */ + const updateUserInfo = async partialData => { + if (!userInfo.value) return + await updateUserData(partialData) + await refreshUserInfo() + } - /** - * 更新部分用户信息(例如昵称、头像) - */ - const updateUserInfo = async partialData => { - if (!userInfo.value) return - await updateUserData(partialData) - await refreshUserInfo() - } + /** 更新字体大小 */ + const updateFontSize = async fontSize => { + fontSizeData.value = fontSize + setFontSize(fontSize) + } - /** 更新字体大小 */ - const updateFontSize = async fontSize => { - fontSizeData.value = fontSize - setFontSize(fontSize) - } - - return { - imEngine, - userInfo, - integralData, - tencentUserSig, - fontSizeData, - getIntegral, - clearAllUserInfo, - updateFontSize, - logout, - refreshUserInfo, - fetchUserInfo, - loginTencentIM, - setUserInfo, - clearUserInfo, - updateUserInfo - } -}) + return { + imEngine, + userInfo, + integralData, + tencentUserSig, + fontSizeData, + getIntegral, + clearAllUserInfo, + updateFontSize, + logout, + refreshUserInfo, + fetchUserInfo, + loginTencentIM, + setUserInfo, + clearUserInfo, + updateUserInfo + } +}) \ No newline at end of file