This commit is contained in:
bobobobo
2026-02-04 23:01:03 +08:00
parent f59e09f4ee
commit 737d8e9a69
25 changed files with 12456 additions and 106 deletions

View File

@@ -1,11 +1,14 @@
<script setup lang="ts">
import * as CallLib from '@/uni_modules/RongCloud-CallWrapper/lib/index.esm'
import ToolbarItemContainer from '../toolbar-item-container/index.vue'
import custom from '../../../../assets/icon/telephone-icon.svg'
import videoIcon from '../../../../assets/icon/video-icon.svg'
import { isUniFrameWork } from '../../../../utils/env'
import { computed } from 'vue'
import { computed, ref } from 'vue'
import { type IConversationModel } from '@tencentcloud/chat-uikit-engine-lite'
CallLib.init({});
const props = withDefaults(
defineProps<{
/** 通话状态: 0 语音 1 视频 */
@@ -26,28 +29,97 @@
const emits = defineEmits(['onDialogPopupShowOrHide'])
const container = ref()
const closeDialog = () => {
container?.value?.toggleDialogDisplay(false)
}
const onDialogShow = () => {
console.log('弹出窗口')
console.log(props.currentConversation)
// emits('onDialogPopupShowOrHide', true)
emits('onDialogPopupShowOrHide', true)
}
const onDialogClose = () => {
console.log('关闭窗口')
// emits('onDialogPopupShowOrHide', false)
emits('onDialogPopupShowOrHide', false)
}
CallLib.onCallReceived(res => {
console.log(res)
console.log(
'Engine:OnCallReceived=>' + '监听通话呼入, 目标id=>',
res.data.targetId
)
})
CallLib.onCallConnected(res => {
console.log(res)
console.log(
'Engine:OnCallConnected=>' +
'已建立通话通话接通时,通过回调 onCallConnected 通知当前 call 的详细信息',
res
)
})
CallLib.onRemoteUserJoined(res => {
console.log(
'Engine:OnRemoteUserJoined=>' +
'主叫端拨出电话被叫端收到请求后加入通话被叫端Id为=>',
res.data.userId
)
})
CallLib.onCallDisconnected(res => {
console.log(
'Engine:OnCallDisconnected=>' + '挂断成功, 挂断原因=>',
res.data.reason
)
})
const onDial = () => {
const data = props.currentConversation.userProfile
// data.userID
CallLib.enableMicrophone(true)
CallLib.startSingleCall(data.userID, 0, '邀请您进行语音通话')
}
</script>
<template>
<ToolbarItemContainer
ref="container"
needBottomPopup
:iconFile="evaluateIcon"
:iconWidth="isUniFrameWork ? '34px' : '20px'"
:iconHeight="isUniFrameWork ? '34px' : '20px'"
:title="isType ? '语音通话' : '视频通话'"
@onDialogShow="onDialogShow"
@onDialogClose="onDialogClose"
></ToolbarItemContainer>
>
<view class="box-index">
<view class="top-icon">
<uni-icons
type="back"
color="#ffffff"
size="42rpx"
@click.stop="closeDialog"
></uni-icons>
</view>
<button @click.stop="onDial">拨打</button>
<button
@click.stop="
() => {
CallLib.enableMicrophone(true)
CallLib.accept()
}
"
>
接听
</button>
</view>
</ToolbarItemContainer>
</template>
<style scoped lang="scss" src="./style/index.scss"></style>

View File

@@ -0,0 +1,13 @@
.box-index {
height: 100vh;
background: #161616;
.top-icon {
padding-top: var(--status-bar-height);
padding-left: 20rpx;
width: 100%;
display: flex;
align-items: center;
height: 100rpx;
}
}

View File

@@ -4,13 +4,15 @@ import TUIChatEngine, {
StoreName,
TUITranslateService,
IConversationModel,
SendMessageParams,
} from '@tencentcloud/chat-uikit-engine-lite';
import { Toast, TOAST_TYPE } from '../../common/Toast/index';
import { isEnabledMessageReadReceiptGlobal } from '../utils/utils';
import { ITipTapEditorContent } from '../../../interface';
import { enableSampleTaskStatus } from '../../../utils/enableSampleTaskStatus';
import OfflinePushInfoManager, { IOfflinePushInfoCreateParams } from '../offlinePushInfoManager/index';
SendMessageParams
} from '@tencentcloud/chat-uikit-engine-lite'
import { Toast, TOAST_TYPE } from '../../common/Toast/index'
import { isEnabledMessageReadReceiptGlobal } from '../utils/utils'
import { ITipTapEditorContent } from '../../../interface'
import { enableSampleTaskStatus } from '../../../utils/enableSampleTaskStatus'
import OfflinePushInfoManager, {
IOfflinePushInfoCreateParams
} from '../offlinePushInfoManager/index'
export const sendMessageErrorCodeMap: Map<number, string> = new Map([
[3123, '文本包含本地审核拦截词'],
@@ -21,26 +23,32 @@ export const sendMessageErrorCodeMap: Map<number, string> = new Map([
[8001, '消息长度超出限制,消息长度不要超过12K'],
[80001, '消息或者资料中文本存在敏感内容,发送失败'],
[80004, '消息中图片存在敏感内容,发送失败'],
[10017, '您已被禁止聊天'],
]);
[10017, '您已被禁止聊天']
])
export const createOfflinePushInfo = (conversation: IConversationModel) => {
const androidInfo = {};
const apnsInfo = {};
const userInfo = TUIStore.getData(StoreName.USER, 'userProfile');
export const createOfflinePushInfo = (
conversation: IConversationModel
) => {
const androidInfo = {}
const apnsInfo = {}
const userInfo = TUIStore.getData(StoreName.USER, 'userProfile')
const entity = {
sender: conversation.type === TUIChatEngine.TYPES.CONV_GROUP ? conversation.groupProfile?.groupID : userInfo.userID,
sender:
conversation.type === TUIChatEngine.TYPES.CONV_GROUP
? conversation.groupProfile?.groupID
: userInfo.userID,
nickName: userInfo.nick,
chatType: conversation.type === TUIChatEngine.TYPES.CONV_GROUP ? 2 : 1,
chatType:
conversation.type === TUIChatEngine.TYPES.CONV_GROUP ? 2 : 1,
version: 1,
action: 1,
};
action: 1
}
return {
extension: JSON.stringify({ entity }),
androidInfo,
apnsInfo,
};
};
apnsInfo
}
}
/**
* This function only processes five message types: Text/TextAt/Image/Video/File
@@ -49,112 +57,143 @@ export const createOfflinePushInfo = (conversation: IConversationModel) => {
*/
export const sendMessages = async (
messageList: ITipTapEditorContent[],
currentConversation: IConversationModel,
currentConversation: IConversationModel
) => {
// In case of messageJumping, the sent message is automatically cleared and returns to the bottom
if (TUIStore.getData(StoreName.CHAT, 'messageSource')) {
TUIStore.update(StoreName.CHAT, 'messageSource', undefined);
TUIStore.update(StoreName.CHAT, 'messageSource', undefined)
}
messageList?.forEach(async (content: ITipTapEditorContent) => {
try {
const options: SendMessageParams = {
to: currentConversation?.groupProfile?.groupID || currentConversation?.userProfile?.userID,
to:
currentConversation?.groupProfile?.groupID ||
currentConversation?.userProfile?.userID,
conversationType: currentConversation?.type as any,
payload: {},
needReadReceipt: isEnabledMessageReadReceiptGlobal(),
};
needReadReceipt: isEnabledMessageReadReceiptGlobal()
}
// handle message typing
let textMessageContent;
let textMessageContent
const sendMessageOptions = {
offlinePushInfo: {},
};
offlinePushInfo: {}
}
const offlinePushInfoCreateParams: IOfflinePushInfoCreateParams = {
conversation: currentConversation,
payload: content.payload,
messageType: '',
};
messageType: ''
}
switch (content?.type) {
case 'text':
textMessageContent = JSON.parse(JSON.stringify(content.payload?.text));
textMessageContent = JSON.parse(
JSON.stringify(content.payload?.text)
)
// Do not send empty messages
if (!textMessageContent) {
break;
break
}
options.payload = {
text: textMessageContent,
};
offlinePushInfoCreateParams.messageType = TUIChatEngine.TYPES.MSG_TEXT;
sendMessageOptions.offlinePushInfo = OfflinePushInfoManager.create(offlinePushInfoCreateParams);
text: textMessageContent
}
offlinePushInfoCreateParams.messageType =
TUIChatEngine.TYPES.MSG_TEXT
sendMessageOptions.offlinePushInfo =
OfflinePushInfoManager.create(offlinePushInfoCreateParams)
if (content.payload?.atUserList) {
options.payload.atUserList = content.payload.atUserList;
await TUIChatService.sendTextAtMessage(options, sendMessageOptions);
options.payload.atUserList = content.payload.atUserList
await TUIChatService.sendTextAtMessage(
options,
sendMessageOptions
)
} else {
try {
console.log('发送成功')
await TUIChatService.sendTextMessage(options, sendMessageOptions);
} catch (err) {
console.log('发送失败,对方不是你的好友')
}
}
break;
break
case 'image':
options.payload = {
file: content.payload?.file,
};
offlinePushInfoCreateParams.messageType = TUIChatEngine.TYPES.MSG_IMAGE;
sendMessageOptions.offlinePushInfo = OfflinePushInfoManager.create(offlinePushInfoCreateParams);
await TUIChatService.sendImageMessage(options, sendMessageOptions);
break;
file: content.payload?.file
}
offlinePushInfoCreateParams.messageType =
TUIChatEngine.TYPES.MSG_IMAGE
sendMessageOptions.offlinePushInfo =
OfflinePushInfoManager.create(offlinePushInfoCreateParams)
await TUIChatService.sendImageMessage(
options,
sendMessageOptions
)
break
case 'video':
options.payload = {
file: content.payload?.file,
};
offlinePushInfoCreateParams.messageType = TUIChatEngine.TYPES.MSG_VIDEO;
sendMessageOptions.offlinePushInfo = OfflinePushInfoManager.create(offlinePushInfoCreateParams);
await TUIChatService.sendVideoMessage(options, sendMessageOptions);
break;
file: content.payload?.file
}
offlinePushInfoCreateParams.messageType =
TUIChatEngine.TYPES.MSG_VIDEO
sendMessageOptions.offlinePushInfo =
OfflinePushInfoManager.create(offlinePushInfoCreateParams)
await TUIChatService.sendVideoMessage(
options,
sendMessageOptions
)
break
case 'file':
options.payload = {
file: content.payload?.file,
};
offlinePushInfoCreateParams.messageType = TUIChatEngine.TYPES.MSG_FILE;
sendMessageOptions.offlinePushInfo = OfflinePushInfoManager.create(offlinePushInfoCreateParams);
await TUIChatService.sendFileMessage(options, sendMessageOptions);
break;
file: content.payload?.file
}
offlinePushInfoCreateParams.messageType =
TUIChatEngine.TYPES.MSG_FILE
sendMessageOptions.offlinePushInfo =
OfflinePushInfoManager.create(offlinePushInfoCreateParams)
await TUIChatService.sendFileMessage(
options,
sendMessageOptions
)
break
default:
break;
break
}
enableSampleTaskStatus('sendMessage');
enableSampleTaskStatus('sendMessage')
} catch (error: any) {
Toast({
message: sendMessageErrorCodeMap.get(error?.code)
? TUITranslateService.t(`TUIChat.${sendMessageErrorCodeMap.get(error.code) as string}`)
? TUITranslateService.t(
`TUIChat.${
sendMessageErrorCodeMap.get(error.code) as string
}`
)
: error?.message,
type: TOAST_TYPE.ERROR,
});
type: TOAST_TYPE.ERROR
})
// If the message fails to be sent and the message is a reference message, clear the reference message information
if (TUIStore.getData(StoreName.CHAT, 'quoteMessage')) {
TUIStore.update(StoreName.CHAT, 'quoteMessage', {});
TUIStore.update(StoreName.CHAT, 'quoteMessage', {})
}
}
});
};
})
}
export const handleMessageWithTyping = (cloudCustomData: any) => {
if (!cloudCustomData) {
cloudCustomData = {};
cloudCustomData = {}
}
cloudCustomData.messageFeature = {
needTyping: 1,
version: 1,
};
return cloudCustomData;
};
export const sendTyping = (inputContentEmpty: boolean, inputBlur: boolean) => {
if (!inputContentEmpty && !inputBlur) {
TUIChatService.enterTypingState();
} else {
TUIChatService.leaveTypingState();
version: 1
}
};
return cloudCustomData
}
export const sendTyping = (
inputContentEmpty: boolean,
inputBlur: boolean
) => {
if (!inputContentEmpty && !inputBlur) {
TUIChatService.enterTypingState()
} else {
TUIChatService.leaveTypingState()
}
}