From eb57bfb6b460772c5f98ed5b661a30d9385777ac Mon Sep 17 00:00:00 2001
From: bobobobo <1055026847@qq.com>
Date: Mon, 9 Feb 2026 02:10:27 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=9F=B3=E8=A7=86=E9=A2=91?=
=?UTF-8?q?=E5=8F=91=E9=80=81=E4=BF=A1=E6=81=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../message-input-toolbar/call-view/index.vue | 184 ++--
.../message-elements/message-custom.vue | 58 +-
.../conversation-list/index.vue | 14 +
TUIKit/constant.ts | 6 +-
composables/useAuthUser.js | 6 +
pages/room/incom.vue | 903 ++++++++++--------
stores/user.js | 818 ++++++++--------
utils/call-user.js | 59 ++
8 files changed, 1147 insertions(+), 901 deletions(-)
create mode 100644 utils/call-user.js
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 027abd6..37f1736 100644
--- a/TUIKit/components/TUIChat/message-input-toolbar/call-view/index.vue
+++ b/TUIKit/components/TUIChat/message-input-toolbar/call-view/index.vue
@@ -1,102 +1,112 @@
-
-
-
+
+
-
+
-
\ No newline at end of file
+
diff --git a/TUIKit/components/TUIChat/message-list/message-elements/message-custom.vue b/TUIKit/components/TUIChat/message-list/message-elements/message-custom.vue
index bc1c412..bc22c1b 100644
--- a/TUIKit/components/TUIChat/message-list/message-elements/message-custom.vue
+++ b/TUIKit/components/TUIChat/message-list/message-elements/message-custom.vue
@@ -151,6 +151,25 @@
+
+
+
+ {{ goodsData.title }}
+
+
+
@@ -165,7 +184,7 @@
computed,
reactive
} from '../../../../adapter-vue'
- import {
+ import TUIChatEngine, {
TUITranslateService,
IMessageModel
} from '@tencentcloud/chat-uikit-engine-lite'
@@ -177,6 +196,7 @@
import unopenedEnvelope from '../../../../assets/icon/unopened-envelope.svg'
import kaiEnvelope from '../../../../assets/icon/kai-unopened-envelope.svg'
import { navigateTo } from '../../../../../utils/router'
+ import { useUserStore } from '../../../../../stores/user'
interface Props {
messageItem: IMessageModel
@@ -187,6 +207,8 @@
(key: 'claim'): void
}
+ const { updateCallMode } = useUserStore()
+
const emits = defineEmits()
const props = withDefaults(defineProps(), {
@@ -230,6 +252,32 @@
return JSON.parse(props.messageItem.payload.data)
})
+ /** 点击拨打音视频电话 */
+ const onCall = () => {
+ if (props.messageItem.flow === 'out') {
+ if (
+ goodsData.value.businessID === CHAT_MSG_CUSTOM_TYPE.VOICE_CALL
+ ) {
+ updateCallMode('0')
+ navigateTo('/pages/room/incom', {
+ type: 'call',
+ userID: goodsData.value.userID,
+ mediaType: 'audio',
+ callType: 'out'
+ })
+ } else {
+ uni.setStorageSync('room-parameters', {
+ callType: 'out',
+ mediaType: 'video',
+ targetId: goodsData.value.userID,
+ callSelect: 'single'
+ })
+ updateCallMode('1')
+ navigateTo('/pages/room/room')
+ }
+ }
+ }
+
/** 点击商品详情 */
const onGoods = () => {
navigateTo('/pages/mall/detail', { productId: goodsData.value.id })
@@ -467,4 +515,12 @@
}
}
}
+
+ .call-box {
+ display: flex;
+ align-items: center;
+ .call-text {
+ margin-right: 10rpx;
+ }
+ }
diff --git a/TUIKit/components/TUIConversation/conversation-list/index.vue b/TUIKit/components/TUIConversation/conversation-list/index.vue
index 5cc06bf..0b74f68 100644
--- a/TUIKit/components/TUIConversation/conversation-list/index.vue
+++ b/TUIKit/components/TUIConversation/conversation-list/index.vue
@@ -404,6 +404,20 @@
return `[直播信息]:${data.title}`
}
}
+ if (data.businessID === CHAT_MSG_CUSTOM_TYPE.VOICE_CALL) {
+ if (isText) {
+ return `${text[0]}:[语音通话]`
+ } else {
+ return `[语音通话]`
+ }
+ }
+ if (data.businessID === CHAT_MSG_CUSTOM_TYPE.VIDEO_CALL) {
+ if (isText) {
+ return `${text[0]}:[视频通话]`
+ } else {
+ return `[视频通话]`
+ }
+ }
if (data.content === 'Create Group' && item.type === 'GROUP') {
return `${item.getLastMessage('text')?.split(':')[0]}:创建群聊`
}
diff --git a/TUIKit/constant.ts b/TUIKit/constant.ts
index 3ce9379..3afe941 100644
--- a/TUIKit/constant.ts
+++ b/TUIKit/constant.ts
@@ -23,7 +23,11 @@ export const CHAT_MSG_CUSTOM_TYPE = {
/** 商品详情 */
GOODS: "goods",
/** 直播 */
- LIVE: "live"
+ LIVE: "live",
+ /** 语音通话 */
+ VOICE_CALL: "voiceCall",
+ /** 视频通话 */
+ VIDEO_CALL: "videoCall",
};
export const DIALOG_CONTENT = {
diff --git a/composables/useAuthUser.js b/composables/useAuthUser.js
index 49421c1..51d803f 100644
--- a/composables/useAuthUser.js
+++ b/composables/useAuthUser.js
@@ -11,6 +11,9 @@ export const useAuthUser = () => {
// 响应式状态(state & getters)
const {
+ callMode,
+ callUserId,
+ callDuration,
imEngine,
userInfo,
tencentUserSig,
@@ -20,6 +23,9 @@ export const useAuthUser = () => {
const { token } = storeToRefs(tokenStore)
return {
+ callMode,
+ callUserId,
+ callDuration,
imEngine,
integralData,
userInfo,
diff --git a/pages/room/incom.vue b/pages/room/incom.vue
index 0c88030..faa3631 100644
--- a/pages/room/incom.vue
+++ b/pages/room/incom.vue
@@ -1,472 +1,527 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ formattedTime }}
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ callerInfo?.nick || callerInfo?.userID }}
-
-
- {{ callState === 'call' ? '呼叫中,等待对方接受邀请...' : callState === 'answer' ? '等待接听...' : '对话中...' }}
-
- {{ mediaType === 'audio' ? "语音通话" : "视频通话" }}
-
-
-
-
-
-
-
-
-
-
- {{ isMicMuted ? '开启' : '静音' }}
-
-
-
-
-
-
-
- {{ callState === 'call' || callState == 'dialogue' ? "挂断" : "拒绝" }}
-
-
-
-
-
-
-
- 接听
-
-
-
-
-
-
-
-
- 扬声器
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formattedTime }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ callerInfo?.nick || callerInfo?.userID }}
+
+
+ {{
+ callState === 'call'
+ ? '呼叫中,等待对方接受邀请...'
+ : callState === 'answer'
+ ? '等待接听...'
+ : '对话中...'
+ }}
+
+
+ {{ mediaType === 'audio' ? '语音通话' : '视频通话' }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ isMicMuted ? '开启' : '静音' }}
+
+
+
+
+
+
+
+
+ {{
+ callState === 'call' || callState == 'dialogue'
+ ? '挂断'
+ : '拒绝'
+ }}
+
+
+
+
+
+
+
+
+ 接听
+
+
+
+
+
+
+
+
+ 扬声器
+
+
+
+
+
\ No newline at end of file
+ /* 响应式调整 */
+ @media (max-height: 600px) {
+ .incoming-controls {
+ padding: 40rpx 30rpx 80rpx !important;
+ }
+ }
+
diff --git a/stores/user.js b/stores/user.js
index 3055200..57cb170 100644
--- a/stores/user.js
+++ b/stores/user.js
@@ -1,419 +1,461 @@
+import { defineStore } from 'pinia'
import {
- defineStore
-} from 'pinia'
-import {
- getToken,
- getUserInfoData,
- setUserInfoData,
- removeUserInfoData,
- getSig,
- setSig,
- removeSig,
- getFontSize,
- setFontSize,
- removeFontSize
+ 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 permision from "@/js_sdk/wa-permission/permission.js"
+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'
import { navigateTo } from '@/utils/router'
+import { sendCallMsg } from '../utils/call-user'
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)
+ /** 发起通话用户id */
+ const callUserId = ref('')
+ /** 通话时长(秒) */
+ const callDuration = ref(0)
+ /** 通话模式 0:语音通话 1:视频通话 */
+ const callMode = ref('0')
+ /** 通话计时器 */
+ const timer = ref(null)
- /**
- * 获取用户信息(可从缓存或接口)
- */
- const fetchUserInfo = async () => {
- // 尝试从本地缓存读取
- const cachedToken = getToken()
- const cachedUserInfo = getUserInfoData()
- const cachedSig = getSig()
+ /** 开始通话计时 */
+ const startTimer = () => {
+ stopTimer() // 先停止之前的计时器
+ timer.value = setInterval(() => {
+ callDuration.value++
+ }, 1000)
+ }
- 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 stopTimer = () => {
+ if (timer.value) {
+ clearInterval(timer.value)
+ timer.value = null
+ }
+ }
- /**
- * 设置用户信息
- */
- 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 resetTime = () => {
+ callDuration.value = 0
+ }
+ /** 通话模式更新 */
+ const updateCallMode = mode => {
+ callMode.value = mode
+ }
- /** 获取用户积分 */
- const getIntegral = async () => {
- const res = await getUserIntegral()
- integralData.value = res.data.availablePoints
- }
+ /**
+ * 获取用户信息(可从缓存或接口)
+ */
+ const fetchUserInfo = async () => {
+ // 尝试从本地缓存读取
+ const cachedToken = getToken()
+ const cachedUserInfo = getUserInfoData()
+ const cachedSig = getSig()
- /**
- * 登录腾讯 IM
- */
- const loginTencentIM = async () => {
- await refreshUserInfo()
- await TUILogin.login({
- SDKAppID: tencentUserSig.value.sdkappID,
- userID: tencentUserSig.value.userId,
- userSig: tencentUserSig.value.userSig,
- framework: `vue3`
- })
+ 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
+ }
- 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
+ /**
+ * 设置用户信息
+ */
+ 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)
+ }
- // #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
- }
+ /** 获取用户积分 */
+ const getIntegral = async () => {
+ const res = await getUserIntegral()
+ integralData.value = res.data.availablePoints
+ }
- //连接融云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
- });
- if (uni.getSystemInfoSync().platform === 'android') {
- permision.requestAndroidPermission('android.permission.CAMERA');
- permision.requestAndroidPermission('android.permission.RECORD_AUDIO');
- }
- onAllListeners()
- });
- let code = await imEngine.value.connect(tencentUserSig.value.ryToken, 10)
- if (code != 0) {
- uni.hideLoading();
- uni.showToast({
- title: 'connect:' + code,
- icon: 'error'
- })
- }
- }
-
- function onAllListeners () {
- CallLib.onCallReceived( (res)=> {
- console.log(res)
- console.log("Engine:OnCallReceived=>"+"监听通话呼入, 目标id=>", res.data.targetId);
- 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'
- });
- uni.showToast({
- title:"有通话呼入该跳转了"+res.data.targetId,
- duration:3000
- })
- 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(res)
- console.log("Engine:OnCallDisconnected=>"+"通话挂断/拒绝, 挂断原因=>", res.data.reason);
- // 重新渲染视频视图
- // uni.$emit('OnCallDisconnected');
- uni.showToast({
- title:reasonDeal(res.data.reason),
- error:"error",
- icon:'none',
- duration:2000
- })
- goback()
- });
- CallLib.onCallConnected((res)=>{
- console.log(res)
- console.log("Engine:OnCallConnected=>"+"已建立通话通话接通时,通过回调 onCallConnected 通知当前 call 的详细信息", res);
- });
- CallLib.onRemoteUserInvited((res)=>{
- console.log("Engine:OnRemoteUserInvited=>"+"通话中的某一个参与者,邀请好友加入通话 ,远端Id为=>", res.data.userId);
- uni.$emit('OnCallConnected');
- })
- CallLib.onRemoteUserJoined((res)=>{
- console.log("Engine:OnRemoteUserJoined=>"+"主叫端拨出电话,被叫端收到请求后,加入通话,对端Id为=>", res.data.userId);
- uni.$emit('OnCallConnected');
- })
- CallLib.onRemoteUserLeft((res)=>{
- console.log("Engine:OnRemoteUserLeft=>"+"远端用户挂断(群聊触发),远端Id为=>", res.data.reason);
- uni.$emit('OnCallConnected');
- uni.showToast({
- title:reasonDeal(res.data.reason),
- error:"error",
- icon:'none',
- duration:2000
- })
- })
- CallLib.onCallOutgoing((res)=>{
- console.log('电话已拨出 主叫端拨出电话后,通过回调 onCallOutgoing 通知当前 call 的详细信息')
- })
- CallLib.onRemoteUserRinging((res)=>{
- console.log('被叫端正在振铃,主叫端拨出电话,被叫端收到请求,发出振铃响应时,回调 onRemoteUserRingin,对端Id为=>', res.data.userId)
- })
- CallLib.onError((res)=>{
- console.log('通话过程中,发生异常')
- uni.showToast({
- title:errorDeal(res.data.reason),
- error:"error",
- icon:'none',
- duration:2000
- });
- goback()
- })
- CallLib.onRemoteUserMediaTypeChanged((res)=>{
- console.log('当通话中的某一个参与者切换通话类型,例如由 audio 切换至 video,回调 onMediaTypeChanged,切换媒体类型的Id为=>',res.data.user.userId);
- })
- }
-
- function goback () {
- const pages = getCurrentPages()
- console.log('pages: ',pages);
- if (pages.length > 1) {
- console.log("走返回");
- uni.showToast({
- title:"走返回",
- duration:3000
- })
- uni.navigateBack({
- delta: 1
- })
- const currentPage = pages[pages.length - 1]
- const prevPage = pages[pages.length - 2]
-
- // 判断上一页是否是 tabBar 页面
- // const isPrevPageTabBar = isTabBarPage(currentPage.route)
- // if(!isPrevPageTabBar){
-
- // }
- }
- }
-
- // 判断页面是否是 tabBar 页面
- function isTabBarPage(route) {
- // 这里根据你的 pages.json 配置来判断
- const tabBarPages = [
- 'TUIKit/components/TUIConversation/index',
- 'TUIKit/components/TUIContact/index',
- 'pages/discover/discover',
- 'pages/my-index/my-index'
- ]
-
- // 判断路由是否在 tabBar 页面列表中
- return tabBarPages.includes(route)
- }
+ /**
+ * 登录腾讯 IM
+ */
+ const loginTencentIM = async () => {
+ await refreshUserInfo()
+ await TUILogin.login({
+ SDKAppID: tencentUserSig.value.sdkappID,
+ userID: tencentUserSig.value.userId,
+ userSig: tencentUserSig.value.userSig,
+ framework: `vue3`
+ })
- /**
- * 清除用户信息(退出登录)
- */
- const clearUserInfo = async () => {
- const show = await showDialog('提示', '确定要退出登录吗?')
- if (show) {
- await logout()
- }
- }
+ 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
- /**
- * 退出登录(不带提示)
- */
- const logout = async () => {
- if (!userInfo.value) return
- try {
- userInfo.value = null
+ // #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
+ }
- 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')
- }
- }
+ //连接融云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
+ // })
+ console.log('登录成功')
+ if (uni.getSystemInfoSync().platform === 'android') {
+ permision.requestAndroidPermission('android.permission.CAMERA')
+ permision.requestAndroidPermission(
+ 'android.permission.RECORD_AUDIO'
+ )
+ }
+ onAllListeners()
+ })
+ let code = await imEngine.value.connect(
+ tencentUserSig.value.ryToken,
+ 10
+ )
+ if (code != 0) {
+ uni.hideLoading()
+ uni.showToast({
+ title: 'connect:' + code,
+ icon: 'error'
+ })
+ }
+ }
- /** 清空所有用户缓存 */
- const clearAllUserInfo = async () => {
- userInfo.value = null
- tencentUserSig.value = null
- fontSizeData.value = 26
- clearToken()
- removeUserInfoData()
- removeSig()
- removeFontSize()
- }
+ function onAllListeners() {
+ CallLib.onCallReceived(res => {
+ console.log(res)
+ console.log(
+ 'Engine:OnCallReceived=>' + '监听通话呼入, 目标id=>',
+ res.data.targetId
+ )
+ 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'
+ })
+ uni.showToast({
+ title: '有通话呼入该跳转了' + res.data.targetId,
+ duration: 3000
+ })
+ 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(res)
+ console.log(
+ 'Engine:OnCallDisconnected=>' + '通话挂断/拒绝, 挂断原因=>',
+ res.data.reason
+ )
+ console.log('=====通话用户id', callUserId.value)
+ sendCallMsg(res.data.reason)
+ // 重新渲染视频视图
+ // uni.$emit('OnCallDisconnected');
+ uni.showToast({
+ title: reasonDeal(res.data.reason),
+ error: 'error',
+ icon: 'none',
+ duration: 2000
+ })
+ goback()
+ })
+ CallLib.onCallConnected(res => {
+ console.log(res)
+ console.log(
+ 'Engine:OnCallConnected=>' +
+ '已建立通话通话接通时,通过回调 onCallConnected 通知当前 call 的详细信息',
+ res
+ )
+ })
+ CallLib.onRemoteUserInvited(res => {
+ console.log(
+ 'Engine:OnRemoteUserInvited=>' +
+ '通话中的某一个参与者,邀请好友加入通话 ,远端Id为=>',
+ res.data.userId
+ )
+ uni.$emit('OnCallConnected')
+ })
+ CallLib.onRemoteUserJoined(res => {
+ console.log(
+ 'Engine:OnRemoteUserJoined=>' +
+ '主叫端拨出电话,被叫端收到请求后,加入通话,对端Id为=>',
+ res.data.userId
+ )
+ uni.$emit('OnCallConnected')
+ })
+ CallLib.onRemoteUserLeft(res => {
+ console.log(
+ 'Engine:OnRemoteUserLeft=>' +
+ '远端用户挂断(群聊触发),远端Id为=>',
+ res.data.reason
+ )
+ uni.$emit('OnCallConnected')
+ uni.showToast({
+ title: reasonDeal(res.data.reason),
+ error: 'error',
+ icon: 'none',
+ duration: 2000
+ })
+ })
+ CallLib.onCallOutgoing(res => {
+ console.log(
+ '电话已拨出 主叫端拨出电话后,通过回调 onCallOutgoing 通知当前 call 的详细信息'
+ )
+ })
+ CallLib.onRemoteUserRinging(res => {
+ console.log(
+ '被叫端正在振铃,主叫端拨出电话,被叫端收到请求,发出振铃响应时,回调 onRemoteUserRingin,对端Id为=>',
+ res.data.userId
+ )
+ })
+ CallLib.onError(res => {
+ console.log('通话过程中,发生异常')
+ uni.showToast({
+ title: errorDeal(res.data.reason),
+ error: 'error',
+ icon: 'none',
+ duration: 2000
+ })
+ goback()
+ })
+ CallLib.onRemoteUserMediaTypeChanged(res => {
+ console.log(
+ '当通话中的某一个参与者切换通话类型,例如由 audio 切换至 video,回调 onMediaTypeChanged,切换媒体类型的Id为=>',
+ res.data.user.userId
+ )
+ })
+ }
- /** 刷新用户信息(如用户信息被修改) */
- const refreshUserInfo = async () => {
- const res = await getUserData()
- await getIntegral()
- await setUserInfoData(res.data)
- userInfo.value = res.data
- }
+ function goback() {
+ const pages = getCurrentPages()
+ console.log('pages: ', pages)
+ if (pages.length > 1) {
+ console.log('走返回')
+ uni.showToast({
+ title: '走返回',
+ duration: 3000
+ })
+ uni.navigateBack({
+ delta: 1
+ })
+ const currentPage = pages[pages.length - 1]
+ const prevPage = pages[pages.length - 2]
- /**
- * 更新部分用户信息(例如昵称、头像)
- */
- const updateUserInfo = async partialData => {
- if (!userInfo.value) return
- await updateUserData(partialData)
- await refreshUserInfo()
- }
+ // 判断上一页是否是 tabBar 页面
+ // const isPrevPageTabBar = isTabBarPage(currentPage.route)
+ // if(!isPrevPageTabBar){
- /** 更新字体大小 */
- 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
- }
-})
\ No newline at end of file
+ // 判断页面是否是 tabBar 页面
+ function isTabBarPage(route) {
+ // 这里根据你的 pages.json 配置来判断
+ const tabBarPages = [
+ 'TUIKit/components/TUIConversation/index',
+ 'TUIKit/components/TUIContact/index',
+ 'pages/discover/discover',
+ 'pages/my-index/my-index'
+ ]
+
+ // 判断路由是否在 tabBar 页面列表中
+ return tabBarPages.includes(route)
+ }
+
+ /**
+ * 清除用户信息(退出登录)
+ */
+ const clearUserInfo = async () => {
+ const show = await showDialog('提示', '确定要退出登录吗?')
+ if (show) {
+ await logout()
+ }
+ }
+
+ /**
+ * 退出登录(不带提示)
+ */
+ 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')
+ }
+ }
+
+ /** 清空所有用户缓存 */
+ 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 updateUserInfo = async partialData => {
+ if (!userInfo.value) return
+ await updateUserData(partialData)
+ await refreshUserInfo()
+ }
+
+ /** 更新字体大小 */
+ const updateFontSize = async fontSize => {
+ fontSizeData.value = fontSize
+ setFontSize(fontSize)
+ }
+
+ return {
+ callUserId,
+ callDuration,
+ imEngine,
+ userInfo,
+ integralData,
+ tencentUserSig,
+ fontSizeData,
+ callMode,
+ startTimer,
+ stopTimer,
+ updateCallMode,
+ resetTime,
+ getIntegral,
+ clearAllUserInfo,
+ updateFontSize,
+ logout,
+ refreshUserInfo,
+ fetchUserInfo,
+ loginTencentIM,
+ setUserInfo,
+ clearUserInfo,
+ updateUserInfo
+ }
+})
diff --git a/utils/call-user.js b/utils/call-user.js
new file mode 100644
index 0000000..d7105de
--- /dev/null
+++ b/utils/call-user.js
@@ -0,0 +1,59 @@
+import TUIChatEngine, {
+ TUIChatService
+} from '@tencentcloud/chat-uikit-engine-lite'
+import { CHAT_MSG_CUSTOM_TYPE } from '../TUIKit/constant'
+import { useAuthUser } from '../composables/useAuthUser'
+import { useUserStore } from '../stores/user'
+
+/** 格式化时间显示 */
+const formatTime = date => {
+ const minutes = Math.floor(date / 60)
+ const seconds = date % 60
+ return `${minutes.toString().padStart(2, '0')}:${seconds
+ .toString()
+ .padStart(2, '0')}`
+}
+
+/** 通话消息发送 */
+export const sendCallMsg = async state => {
+ const { resetTime, stopTimer } = useUserStore()
+ const { callUserId, callMode, callDuration, tencentUserSig } =
+ useAuthUser()
+ const to = callUserId.value
+ const userID = tencentUserSig.value.userId
+ if (to !== userID) {
+ let title = ''
+ if ([0, 11].includes(state)) {
+ title = { 0: '已挂断', 11: '对方已拒绝' }[state]
+ } else {
+ title = `通话时长 ${formatTime(callDuration.value)}`
+ }
+
+ const payload = {
+ data: JSON.stringify({
+ businessID:
+ callMode.value == 0
+ ? CHAT_MSG_CUSTOM_TYPE.VOICE_CALL
+ : CHAT_MSG_CUSTOM_TYPE.VIDEO_CALL,
+ title,
+ userID: to
+ }),
+ description: title,
+ extension: title
+ }
+ const options = {
+ to,
+ payload,
+ conversationType: TUIChatEngine.TYPES.CONV_C2C,
+ needReadReceipt: false
+ }
+ resetTime()
+ await TUIChatService.sendCustomMessage(options)
+ } else {
+ resetTime()
+ }
+
+ if (callMode.value == 1) {
+ stopTimer()
+ }
+}