原生聊天会话详情组件,支持Android和iOS双端,仅限App端nvue页面可用
,不支持H5、小程序等。
在uni-app
上,常规使用 vue 或使用 nvue 去实现聊天页面,发送消息等视图,体验性差,性能低下。包括不限于键盘与表情面板等切换流畅度差,列表滑动卡顿,页面加载消息慢。
解决了在 uni-app 上实现聊天详情页面的痛点,高性能聊天记录列表,无感知聊天记录置底,动画平滑切换键盘及面板,仿 Wechat 动画,支持发送消息、在离线状态展示。文字、语音、视频、图片、位置、文件等消息展示,支持下拉加载历史记录,表情,更多功能等...
组件覆盖整个 nvue 页面,一组件即一页面,此组件仅为UI,通过传入参数(消息列表,会话信息,相关功能参数等)进行展示视图,不涉及具体聊天逻辑,具体聊天逻辑仍需uni-app JS端实现,
使用请仔细阅读以下文档及注意事项。
目前仅提供 Android App 演示,进入 App 点击某会话选择->原生会话页面查看
由于编译型语言特性,原生插件无法过于可自定义化,所以客户虽然满意此插件的用户体验,但可能因自身项目原因对 UI 方面需要一定的改变。所以基于各种原因,此插件可支持付费定制需求,包括不限于 UI 的改变、消息结构的支持,多消息自定义类型的 UI 定制等。
费用包含:离线打包基础费用 + 需求定制费用
原生插件离线打包基础费用为:3000 元。每个客户仅需支付一次,如有客户自身的其他项目也需要定制另一种 UI,则不再收取此费用。
需求定制费用包含不限于会话页面的 UI 改变费用(根据具体需求定价)、多消息类型费用(单个类型的消息 UI,价格 500 起。此插件本身支持的消息类型不收费:文本图片视频语音等)、消息结构费用(一般根据你的 IMSDK 和消息类型数量定,价格 200-1000 间)。
举例说明:如果客户对 uniapp vue 做的聊天页面不满意,体验太差。此时需要一个原始聊天会话页面,刚好此原生插件的用户体验能够让你满意,但是消息支持度和页面的 UI 不太符合你当前项目的需求,需要进行一定的改变,那么你可以进行付费定制。如果主要需求是多消息类型支持,比如需要一个红包消息和一个订单消息,那么根据具体的 UI 定,这两个消息分别 500 起的价格。如果对页面整体 UI 没有太大的改变,那么总费用大约为:3000+500+500 = 4000 元。
不要发票:淘宝、闲鱼、微信、支付宝
要发票:企业对公转账
消息数据结构支持度:
支持以下接口消息数据:
支持以下接口消息数据:
支持以下接口消息数据:
注:融云消息结构内必须添加 userInfo 字段,无 userInfo 字段消息无法显示
userInfo 字段对象结构:{"portrait":"https://img1.baidu.com/it/u=440202259,2734237708&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500","userId":"1","alias":"","name":"融云用户 1","extra":""}
点击查看 融云即时通信 IM(uni-app SDK) 文档
目前支持腾讯云IM (uni-app SDK)
、YeIM-Uni-SDK
、融云即时通信IM(uni-app SDK)
的消息结构数据,如需紧急支持其他类型,可参照上述已适配的消息结构 json 字符串去修改为类似的消息结构,再传入参数 messages
。
初始化参数
说明:组件初始化时有必传的一部分参数,均为组件渲染所需,请务必注意。
参数名 | 类型 | 默认值 | 是否必填 | 说明 | 平台差异 |
---|---|---|---|---|---|
structure | String | tim | 否 | 消息结构平台,请根据实际情况准确填写,可选值:tim、yeim、rongcloud | 无 |
userInfo | Object | 无 | 是 | 当前用户信息,见下表详情 | 无 |
conversation | Object | 无 | 是 | 会话信息,见下表详情 | 无 |
badge | Number | 0 | 否 | 导航栏未读角标 | 无 |
badgeTextColor | String | #ffffff | 否 | 导航栏角标文字颜色 | 1.0.1 |
badgeBackgroundColor | String | #faab38 | 否 | 导航栏角标背景色 | 1.0.1 |
showOnlineStatus | Boolean | false | 否 | 是否显示在、离线视图 | 无 |
onlineStatus | Boolean | false | 否 | 在、离线状态(showOnlineStatus 为 true 时有效) | 无 |
showName | Boolean | false | 否 | 是否显示对端用户名称 | 无 |
amapWebKey | String | null | 否 | 高德地图 Web Key,作为位置消息静态地图使用,如无位置消息,可不传 | 无 |
tools | Array<Object> | 无 | 是 | 更多功能,见下表详情 | 无 |
faceList | Array<String> | 无 | 否 | 自定义收藏表情 URL 数组,见下表详情 | 1.0.6 |
popMenuList | Array<Object> | 无 | 否 | 自定义消息长按气泡功能,见下表详情 | 1.0.4 |
rightTextBackgroundColor | String | #ffc166 | 否 | 列表右侧消息框背景色 | 1.0.1 |
rightTextColor | String | #000000 | 否 | 列表右侧消息框文字颜色 | 1.0.1 |
leftTextBackgroundColor | String | #ffffff | 否 | 列表左侧消息框背景色 | 1.0.1 |
leftTextColor | String | #ffffff | 否 | 列表左侧消息框文字颜色 | 1.0.1 |
sendButtonBackgroundColor | String | #ffffff | 否 | 发送按钮背景色 | 1.0.1,iOS 端表现为表情面板按钮 |
sendButtonTextColor | String | #ffffff | 否 | 发送按钮文字颜色 | 1.0.1,iOS 端表现为表情面板按钮 |
当前用户信息
说明:用于区别聊天列表消息所属,消息发送者为 userInfo
中 id
,则列表那一行的消息显示为右侧,否则为左侧
参数名 | 类型 | 默认值 | 是否必填 | 说明 | 平台差异 |
---|---|---|---|---|---|
id | String | 无 | 是 | 当前用户 ID,字符串类型 | 无 |
name | String | 无 | 否 | 当前用户名称,字符串类型。属于占位,此字段暂未使用 | 无 |
会话信息
参数名 | 类型 | 默认值 | 是否必填 | 说明 | 平台差异 |
---|---|---|---|---|---|
id | String | 无 | 否 | 会话 ID,属于占位,此字段暂未使用 | 无 |
name | String | 无 | 是 | 会话名称,字符串类型。组件导航栏视图使用此字段作为标题 | 无 |
更多视图功能列表数据,下表为单个对象结构
参数名 | 类型 | 默认值 | 是否必填 | 说明 | 示例 | 平台差异 |
---|---|---|---|---|---|---|
name | String | 无 | 是 | 功能名称 | 相册 | 无 |
icon | String | 无 | 是 | 功能图标,支持static 目录下的图片 | /static/album.png | 无 |
action | String | 无 | 是 | 点击事件名称,通过@tools-action 事件回调到 JS 端,见下表详情 | album | 无 |
自定义收藏表情 URL 数组
faceList: ['url1', 'url2'];
消息长按气泡菜单,此处为新增功能。下表为单个对象结构
参数名 | 类型 | 默认值 | 是否必填 | 说明 | 示例 | 平台差异 |
---|---|---|---|---|---|---|
name | String | 无 | 是 | 功能名称 | 转发 | 无 |
icon | String | 无 | 是 | 功能图标,支持static 目录下的图片 | /static/album.png | 无 |
action | String | 无 | 是 | 点击事件名称,通过@action 事件回调到 JS 端 | forward | 无 |
messages
接收一个消息对象数组
。
腾讯云即时通信 IM 消息对象
点下方链接查看
腾讯云即时通信 IM(Web & 小程序 & uni-app SDK)Message
参数名 | 类型 | 默认值 | 是否必填 | 说明 | 平台差异 |
---|---|---|---|---|---|
ID | String | 无 | 是 | 消息 ID | 无 |
type | String | 无 | 是 | 消息类型 | 无 |
conversationType | String | 无 | 是 | 消息所属会话的类型 | 无 |
nick | String | 无 | 是 | 消息发送者的昵称 | 无 |
avatar | String | 无 | 是 | 消息发送者的头像地址 | 无 |
from | String | 无 | 是 | 发送方的 userID | 无 |
to | String | 无 | 是 | 接收方的 userID | 无 |
isPeerRead | Boolean | 无 | 是 | C2C 消息对端是否已读 | 无 |
time | Number | 无 | 是 | 消息时间戳。单位:秒 | 无 |
status | String | 无 | 是 | 消息状态 | 无 |
payload | Object | 无 | 是 | 消息的内容,点此查看 | 无 |
以下代码解释:给组件的 messages 属性赋值一个 messages 数组,messages 数组中包含了一个腾讯云 IM 文字消息对象
<template><view><!-- 此处仅为演示初始化时消息数组结构传入,未给options等赋值,请勿直接复制使用 --><yeim-chat-page :messages="messages" /></view></template><script>export default {data() {return {messages: [{ID: '144115242122962694-1666581007-32219913',conversationID: 'C2C2',conversationType: 'C2C',time: 1666581008,sequence: 1109260003,clientSequence: 1109260003,random: 32219913,priority: 'Normal',nick: '妖精不会飞',avatar:'https://img1.baidu.com/it/u=440202259,2734237708&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',isPeerRead: true,nameCard: '',_elements: [{type: 'TIMTextElem',content: {text: '你好',},},],isPlaceMessage: 0,isRevoked: false,from: '1',to: '2',flow: 'out',isSystemMessage: false,protocol: 'JSON',isResend: false,isRead: true,status: 'success',_onlineOnlyFlag: false,_groupAtInfoList: [],_relayFlag: false,atUserList: [],cloudCustomData: '',isDeleted: false,isModified: false,_isExcludedFromUnreadCount: false,_isExcludedFromLastMessage: false,clientTime: 1666581007,senderTinyID: '144115242122962694',readReceiptInfo: {},needReadReceipt: false,version: 0,isBroadcastMessage: false,payload: {text: '你好',},type: 'TIMTextElem',},],};},};</script>
插件版本 1.0.8 开始,支持腾讯云即时通信IM(Web & 小程序 & uni-app SDK)
、YeIM-Uni-SDK
这两个 SDK 使用createCustomMessage
创建自定义 Tips 消息,类似对方撤回了一条消息
和群主邀请了xxx进入了群聊
这种 Tips 提示性的消息类型,需要根据指定的结构传入,方可显示如下 UI:
腾讯云的自定义消息 Tips 消息类型消息结构显示:
[{"ID": "144115242311226482-1686049232-82482770","conversationID": "C2Cuser2","conversationType": "C2C","time": 1686049232,"sequence": 1900320001,"clientSequence": 1900320001,"random": 82482770,"priority": "Normal","nick": "妖精不会飞","avatar": "https://img1.baidu.com/it/u=440202259,2734237708&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500","isPeerRead": false,"nameCard": "","_elements": [{"type": "TIMCustomElem","content": {"data": "tips","description": "群主邀请了xxx、lll、zzz进入了群聊","extension": ""}}],"isPlaceMessage": 0,"isRevoked": false,"from": "1","to": "user2","flow": "out","isSystemMessage": false,"protocol": "JSON","isResend": false,"isRead": true,"status": "success","_onlineOnlyFlag": false,"_groupAtInfoList": [],"_relayFlag": false,"atUserList": [],"cloudCustomData": "","isDeleted": false,"isModified": false,"_isExcludedFromUnreadCount": false,"_isExcludedFromLastMessage": false,"clientTime": 1686049232,"senderTinyID": "144115242311226482","readReceiptInfo": {},"needReadReceipt": false,"version": 0,"isBroadcastMessage": false,"payload": {"data": "tips","description": "啊实打实大大是的","extension": ""},"type": "TIMCustomElem"}]
YeIM-Uni-SDK 的自定义消息 Tips 消息类型消息结构显示:
[{"sequence": 5740984,"messageId": "405076915945541-1681032133432-1","userId": "user1","conversationId": "user2","conversationType": "private","direction": "out","from": "user1","fromUserInfo": {"nickname": "没有毛病","avatarUrl": "https://api.multiavatar.com/99521.png"},"to": "user2","type": "custom","body": {"custom": {"type": "tips","data": "群主邀请了xxx、lll、zzz进入了群聊"}},"extra": "","isRead": 0,"isRevoke": 0,"isDeleted": 0,"status": "success","receive": 0,"time": 1681032133432}]
事件名 | 参数 | 说明 | 平台差异 |
---|---|---|---|
@navigate-back | 无 | 导航栏左侧返回图标点击事件 | 无 |
@navigate-more | 无 | 导航栏右侧更多图标点击事件 | 无 |
@load-more | 无 | 聊天列表下拉加载事件,配合finishLoadMore() 使用 | 无 |
@avatar-action | Object | 聊天列表头像点击事件 | 无 |
@send | Object | 发送按钮点击事件 | 无 |
@voice-end | Object | 语音完毕回调 | 无 |
@tools-action | Object | 功能点击事件回调,回调参数为初始化参数 中tools 内传入的action | 无 |
@open-file | Object | 文件消息点击事件 | 无 |
@open-map | Object | 位置消息点击事件 | 无 |
@revoke-message | Object | 消息菜单->撤回消息点击事件 | 无 |
@delete-message | Object | 消息菜单->删除消息点击事件 | 无 |
@add-custom-emoji-action | Object | 自定义收藏表情面板点击添加事件 | 1.0.4 |
@custom-emoji-action | Object | 自定义收藏表情点击事件 | 1.0.6 |
@custom-emoji-long-action | Object | 自定义收藏表情长按事件 | 1.0.6 |
@error-message-action | Object | 错误消息红色感叹号图标点击事件 | 1.0.8 |
<template><view><!-- 此处仅为演示事件,未初始化参数,请勿直接复制使用 --><yeim-chat-page @avatar-action="@avatarAction" /></view></template><script>export default {data() {return {};},methods: {avatarAction(e) {console.log(e);/*当用户点击消息列表的头像后,此处回调结果:{"type":"avatarAction","timeStamp":1666691669115,"target":{"id":"","dataset":{},"offsetLeft":0,"offsetTop":0},"currentTarget":{"id":"","dataset":{},"offsetLeft":0,"offsetTop":0},"detail":{"messageId":"144115242122962694-1666684242-36090699"},"stopPropagation":"function() { [native code] }"}*/},},};</script>
设置导航栏未读角标,直接传入数字,0则不显示角标
<template><view><!-- 此处仅为演示方法,未初始化参数,请勿直接复制使用 --><yeim-chat-page ref="chatpage" /></view></template><script>export default {data() {return {};},onReady() {this.$refs.chatpage.setBadge(5);},};</script>
设置在、离线状态,直接传入布尔值。调用此方法需确认组件参数
showOnlineStatus
为true
,否则无效
<template><view><!-- 此处仅为演示方法,未初始化参数,请勿直接复制使用 --><yeim-chat-page ref="chatpage" /></view></template><script>export default {data() {return {};},onReady() {this.$refs.chatpage.setOnlineStatus(true);},};</script>
完成加载历史记录,传入消息数组。没有记录则传入[],不管有无数据,回调
@load-more
事件后,均需调用此方法
<template><view><!-- 此处仅为演示方法,未初始化参数,请勿直接复制使用 --><yeim-chat-page ref="chatpage" @load-more="loadMore" /></view></template><script>export default {data() {return {};},method: {loadMore() {setTimeout(() => {// 模拟加载历史记录let messages = getHistoryList();// 完成加载历史记录this.$refs.chatpage.finishLoadMore(messages);// TODO// 如果没有更多历史记录// this.$refs.chatpage.finishLoadMore([]);}, 2000);},},};</script>
将消息加入到聊天列表,参数为消息对象
<template><view><!-- 此处仅为演示方法,未初始化参数,请勿直接复制使用 --><yeim-chat-page ref="chatpage" @send="send" /></view></template><script>export default {data() {return {};},onLoad() {//当收到新消息时候,调用链:onMessage->insertMessageTIM.on(TIM.EVENT.MESSAGE_RECEIVED, this.onMessage);},method: {onMessage(e) {let list = e.data;for (let i = 0; i < list.length; i++) {//TODO 此处应做去重处理let message = list[i];this.$refs.chatpage.insertMessage(message);}},send(e) {let detail = e.detail;let text = detail.text;let message = TIM.createTextMessage({to: '对方ID',conversationType: TIM.TYPES.CONV_C2C,payload: {text: text,},});this.$refs.chatpage.insertMessage(message);let promise = TIM.sendMessage(message);promise.then((imResponse) => {//发送消息一般需要耗时,但若等待发送完成后再将消息插入到消息列表,那么用户是有感知的,明显会感觉到按下发送按钮后,等了一下消息才弹出来。//基于这种情况,我们可以在创建消息后直接调用insertMessage,此时消息结构中,消息状态一般为`发送中`,那么我们在调用发送接口发送完成后,再调用updateMessageStatus,就可以刷新当前消息状态this.$refs.chatpage.updateMessageStatus(imResponse.data.message);}).catch((imError) => {message.status = 'fail';this.$refs.chatpage.updateMessageStatus(imResponse.data.message);});},},};</script>
从消息列表中删除某一条消息,参数为消息对象
在消息列表里刷新某一条消息,参数为消息对象
在消息列表中刷新某一条消息的状态,参数为消息对象
在自定义收藏表情面板中添加一个表情,参数为图片 URL
在自定义收藏表情面板中删除一个表情,参数为图片 URL
恢复部分设置,退出聊天页面时调用,可恢复因组件需要而改变的全局设置。
<template><view><!-- 此处仅为演示方法,未初始化参数,请勿直接复制使用 --><yeim-chat-page ref="chatpage" /></view></template><script>export default {data() {return {};},onBackPress() {this.$refs.chatpage.restore();},};</script>
此样例使用腾讯云即时通信 IM SDK演示,SDK 名称:tim-wx-sdk、tim-upload-plugin,文档地址:https://web.sdk.qcloud.com/im/doc/zh-cn/SDK.html#getMessageList
YeIM-Uni-SDK 样例可查看代码:https://ext.dcloud.net.cn/plugin?id=10266
融云 IM uni-app sdk 使用样例可查看代码:https://gitee.com/wzJun1/yeim-chat-page_rongyuncloud_demo
<template><view><button class="button" @click="open">打开某个用户的聊天会话页面</button></view></template><script>export default {data() {return {};},methods: {open() {//由于腾讯IM获取历史聊天记录无缓存情况下会请求网络,导致进入会话详情页面,组件无法第一时间给messages赋值,从而影响用户体验//所以此处建议在进入页面之前获取聊天记录,使用全局变量或者Vuex的方式给会话页面传值。//Tips:如果可以保证在会话页面里拉取聊天记录的速度,或者可以保证直接从本地缓存里拉取,也可以不在此处获取,直接在会话详情页面onLoad里getMessageListlet promise = TIM.getMessageList({conversationID: '此处填会话ID',count: 15,});promise.then((imResponse) => {console.log(imResponse);//TODO//此处按上述原因,全局变量赋值imResponse//可使用globalData或者Vuex实现//我在此处未写具体实现逻辑,这里应自行实现// eg: getApp().globalData.imResponse = imResponse;// preloadPage 预加载nvue页面,保证了渲染效率// `/pages/index/chat` 为demo中组件所在页面,也即是下方代码块所显示内容// 会话ID和会话名称也需自行替换// 此处的url可自行修改,如果有其他方式去给会话详情页面传递会话信息,也可以直接去掉id、namelet url ='/pages/index/chat?id=' +会话ID +'&name=' +会话名称 +'&time=' +new Date().getTime();uni.preloadPage({url: url,complete: () => {setTimeout(() => {uni.navigateTo({url: url,});}, 100);},fail: (e) => {console.log('页面预加载失败:' + e);},});}).catch(function (imError) {console.warn('getMessageList error:', imError);});},},};</script>
{"path": "pages/index/chat","style": {"enablePullDownRefresh": false,"disableScroll": true,"navigationStyle": "custom","navigationBarTextStyle": "black"}}
<template><view><yeim-chat-pageref="chatpage":style="style":options="options":messages="messages"@navigate-back="navigateBack"@navigate-more="navigateMore"@load-more="loadMore"@avatar-action="avatarAction"@send="sendTextMessage"@voice-end="voiceEnd"@tools-action="toolsAction"@revoke-message="revokeMessage"@delete-message="deleteMessage"></yeim-chat-page></view></template><script>export default {data() {return {time: 0,style: {width: uni.getSystemInfoSync().screenWidth + 'px',height: uni.getSystemInfoSync().screenHeight + 'px',},options: {},conversation: {},messages: [],nextReqMessageID: '',isCompleted: false,};},onLoad(option) {//接收url参数,转会话信息this.conversation.id = option.id;this.conversation.name = option.name;//url random,用于解除预加载this.time = option.time;//组件初始化参数this.options = {structure: 'tim', //消息结构类型: timuserInfo: {id: 'userid1',name: '用户本人',}, // 当前登录用户conversation: this.conversation, // 会话用户信息(群信息):namebadge: 10, // 未读角标showOnlineStatus: true, //是否显示在线状态onlineStatus: true, // 是否在线showName: false, //是否显示列表内除自己外,别人的名称amapWebKey: '高德web key', // 如需要位置消息,则需填写高德地图 Web Key用作显示位置消息的静态地图//更多功能tools: [{name: '相册',icon: '/static/ic_more_item_image.png',action: 'album',},{name: '视频',icon: '/static/ic_more_item_cap.png',action: 'photograph',},{name: '视频通话',icon: '/static/ic_more_item_video_call.png',action: 'videoCall',},{name: '语音通话',icon: '/static/ic_more_item_voice_call.png',action: 'voiceCall',},{name: '文件',icon: '/static/ic_more_item_files.png',action: 'files',},{name: '位置',icon: '/static/ic_more_item_location.png',action: 'location',},],};//此处承接上个页面的:imResponse(全局变量或者Vuex赋值)//这里假设我已经拿到了imResponse// eg: const imResponse = getApp().globalData.imResponse;const messageList = imResponse.data.messageList;this.nextReqMessageID = imResponse.data.nextReqMessageID;this.isCompleted = imResponse.data.isCompleted;//给组件 messages 赋值this.messages = messageList;},onShow() {//监听腾讯IM MESSAGE_RECEIVED时间,收到消息后调用onMessageTIM.on(TIM.EVENT.MESSAGE_RECEIVED, this.onMessage, this);},onUnload() {//解除预加载let url ='/pages/index/chat?id=' +this.conversation.id +'&name=' +this.conversation.name +'&time=' +this.time;uni.unPreloadPage({url: url,});//取消监听MESSAGE_RECEIVEDTIM.off(TIM.EVENT.MESSAGE_RECEIVED, this.onMessage);},onBackPress() {//执行恢复设置,防止UI错位this.$refs.chatpage.restore();//解除预加载let url ='/pages/index/chat?id=' +this.conversation.id +'&name=' +this.conversation.name +'&time=' +this.time;uni.unPreloadPage({url: url,});//取消监听MESSAGE_RECEIVEDTIM.off(TIM.EVENT.MESSAGE_RECEIVED, this.onMessage);},methods: {onMessage: function (e) {//收到消息,插入到消息列表中try {let list = e.data;if (list) {for (let i = 0; i < list.length; i++) {let message = list[i];//去重、防乱入if (message.from === this.conversation.id) {let index = this.messages.findIndex((item) => item.ID === message.ID);if (index === -1) {//messages可加,也可不加,此处push进去,是可能后续需要用到messages//组件的messages属性,仅在第一次赋值时生效,以后修改messages不影响组件内部消息列表this.messages.push(message);//插入到消息列表this.$refs.chatpage.insertMessage(message);}}}}} catch (e) {console.log(e);}},navigateBack() {//左侧导航栏返回图标点击事件},navigateMore() {//右侧导航栏更多图标点击事件},avatarAction(e) {//头像点击事件console.log(e);},loadMore() {//下拉加载历史记录回调if (this.nextReqMessageID != '' && !this.isCompleted) {let promise = TIM.getMessageList({conversationID: 'C2C' + this.conversation.id,nextReqMessageID: this.nextReqMessageID,count: 15,});promise.then((imResponse) => {const messageList = imResponse.data.messageList; // 消息列表。this.nextReqMessageID = imResponse.data.nextReqMessageID; // 用于续拉,分页续拉时需传入该字段。this.isCompleted = imResponse.data.isCompleted;this.$refs.chatpage.finishLoadMore(messageList);});} else {this.$refs.chatpage.finishLoadMore([]);}},sendTextMessage(e) {//发送按钮点击事件let detail = e.detail;let text = detail.text;if (text != '') {let message = TIM.createTextMessage({to: this.conversation.id,conversationType: TIM.TYPES.CONV_C2C,payload: {text: text,},});this.messages.push(message);this.$refs.chatpage.insertMessage(message);let promise = TIM.sendMessage(message);promise.then((imResponse) => {this.$refs.chatpage.updateMessageStatus(imResponse.data.message);}).catch((imError) => {console.warn('sendMessage error:', imError);message.status = 'fail';this.$refs.chatpage.updateMessageStatus(imResponse.data.message);});}},voiceEnd(e) {//组件内,用户语音完毕事件,只有用户确认发送语音后,才会回调此方法const message = TIM.createAudioMessage({to: this.conversation.id,conversationType: TIM.TYPES.CONV_C2C,payload: {file: e.detail,},});this.messages.push(message);this.$refs.chatpage.insertMessage(message);let promise = TIM.sendMessage(message);promise.then((imResponse) => {this.$refs.chatpage.updateMessageStatus(imResponse.data.message);}).catch(function (imError) {console.warn('sendMessage error:', imError);message.status = 'fail';this.$refs.chatpage.updateMessageStatus(imResponse.data.message);});},revokeMessage(e) {//撤回消息回调let messageId = e.detail.messageId;let message = this.messages.find((item) => item.ID == messageId);uni.showLoading({title: '撤回中...',});let promise = TIM.revokeMessage(message);promise.then((imResponse) => {// 消息撤回成功uni.hideLoading();this.$refs.chatpage.updateMessage(imResponse.data.message);}).catch(function (imError) {uni.hideLoading();if (imError.code == 20016) {//消息撤回超过了时间限制(默认2分钟)uni.showModal({title: '提示',content: '消息撤回超过了时间限制2分钟',});}// 消息撤回失败console.warn('revokeMessage error:', imError);});},deleteMessage(e) {//删除消息回调let messageId = e.detail.messageId;let message = this.messages.find((item) => item.ID == messageId);uni.showLoading({title: '删除中...',});let promise = TIM.deleteMessage([message]);promise.then((imResponse) => {// 删除消息成功uni.hideLoading();this.$refs.chatpage.removeMessage(message);}).catch(function (imError) {uni.hideLoading();// 删除消息失败console.warn('deleteMessage error:', imError);uni.showToast({icon: 'error',title: '删除失败',});});},toolsAction(e) {//更多功能点击事件if (e.detail) {let detail = e.detail;let action = detail.action;if (action == 'album') {uni.chooseImage({count: 1,sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有success: (res) => {let message = TIM.createImageMessage({to: this.conversation.id,conversationType: TIM.TYPES.CONV_C2C,payload: {file: res,},onProgress: function (event) {console.log('file uploading:', event);},});this.messages.push(message);this.$refs.chatpage.insertMessage(message);let promise = TIM.sendMessage(message);promise.then((imResponse) => {this.$refs.chatpage.updateMessageStatus(imResponse.data.message);}).catch(function (imError) {console.warn('sendMessage error:', imError);message.status = 'fail';this.$refs.chatpage.updateMessageStatus(imResponse.data.message);});},});} else if (action == 'photograph') {uni.chooseVideo({count: 1,maxDuration: 60, // 设置最长时间60scamera: 'back', // 后置摄像头success: (res) => {let message = TIM.createVideoMessage({to: this.conversation.id,conversationType: TIM.TYPES.CONV_C2C,payload: {file: res,},onProgress: function (event) {console.log('file uploading:', event);},});this.messages.push(message);this.$refs.chatpage.insertMessage(message);let promise = TIM.sendMessage(message);promise.then((imResponse) => {this.$refs.chatpage.updateMessageStatus(imResponse.data.message);}).catch(function (imError) {console.warn('sendMessage error:', imError);message.status = 'fail';this.$refs.chatpage.updateMessageStatus(imResponse.data.message);});},});} else if (action == 'files') {} else if (action == 'location') {uni.chooseLocation({success: (res) => {let message = TIM.createLocationMessage({to: this.conversation.id,conversationType: TIM.TYPES.CONV_C2C,payload: {description: res.name + '|' + res.address,longitude: res.longitude, // 经度latitude: res.latitude, // 纬度},});let promise = TIM.sendMessage(message);promise.then((imResponse) => {this.messages.push(imResponse.data.message);this.$refs.chatpage.insertMessage(imResponse.data.message);}).catch(function (imError) {// 发送失败console.warn('sendMessage error:', imError);});},});}}},},};</script>
https://gitee.com/wzJun1/ye-im-chat-page-demo-tim
1.1.0 - 2023-10-08
1.0.9 - 2023-07-28
1.0.8 - 2023-06-06
errorMessageAction
(消息状态为错误时,红色感叹号的点击事件)对方撤回了一条消息
的Tips 类型消息 (看文档传入指定消息结构可正常显示)1.0.7 - 2023-04-02
1.0.6 - 2023-03-22
1.0.5 - 2023-03-14
1.0.4 - 2023-02-19
转发
、收藏
@input
1.0.3 - 2023-02-15
1.0.2 - 2023-01-27
YeIM-Uni-SDK
消息结构。YeIM-Uni-SDK
是可以私有化部署的全开源即时通讯 UniAPP JSSDK,详情可查看文档。1.0.1 - 2022-11-14
1.0.0 - 2022-11-06