import { 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 * 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' // #endif // #ifdef H5 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 { navigateTo } from '@/utils/router' import { sendCallMsg } from '../utils/call-user' export const useUserStore = defineStore('user', () => { const { clearToken } = useTokenStore() const { showDialog, showToast } = useUI() const userInfo = ref( getUserInfoData() ? JSON?.parse(getUserInfoData()) : {} ) /** 用户字体大小 */ const fontSizeData = ref(getFontSize()) /** 腾讯 IM 存储数据 */ const tencentUserSig = ref(getSig() ? JSON?.parse(getSig()) : {}) /** 用户积分数 */ 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 startTimer = () => { stopTimer() // 先停止之前的计时器 timer.value = setInterval(() => { callDuration.value++ }, 1000) } /** 停止通话计时 */ const stopTimer = () => { if (timer.value) { clearInterval(timer.value) timer.value = null } } /** 重置时间 */ const resetTime = () => { callDuration.value = 0 } /** 通话模式更新 */ const updateCallMode = mode => { callMode.value = mode } /** * 获取用户信息(可从缓存或接口) */ 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 } /** * 设置用户信息 */ 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 (loading = true) => { const res = await getUserIntegral(loading) 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` }) 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 } //连接融云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' }) } } 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 ) }) } 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) } /** * 清除用户信息(退出登录) */ 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 } })