实现自定义消息收发

更新时间: 2024/05/10 11:40:02

本文介绍 IM UIKit 默认支持的基本消息类型,以及如何实现自定义消息收发。

基本消息类型

IM UIKit 内置了几种基本消息类型(见下表),如果基本消息类型无法满足您的业务需求,您可自定义消息类型。

消息类型
显示效果
文本消息
图片消息
文件消息
表情

前提条件

实现自定义消息收发前,请确保已集成会话消息界面

实现方法

发送自定义消息

发送方可以在会话界面的消息发送按钮上绑定发送消息的函数。

以“发送一条评价消息”为例:

发送时,可将“是否为评价消息”标记在附件信息 attach 字段或者其他字段中(可联系技术支持获取最贴近您业务的字段),然后在消息接收时进行判断。

  • 如果是评价消息,则使用自定义渲染。
  • 如果不是评价消息,则返回 null,使用默认的消息渲染逻辑。

评价消息.png

您可以根据业务需要,决定调用 store 层的 sendCustomMsgActive 或 SDK 原生方法 sendCustomMsg(可以传递更丰富的参数) 发送函数实现自定义消息的发送。

Vue
import { compile } from "jsx-web-compiler";
 // 发送评价消息
    const sendEvaluationMessage = () => {
      // 这里通过 uikit 实例获取 store,store 文档参考 https://doc.yunxin.163.com/docs/interface/messaging/web/typedoc/UIKit/Latest/zh/modules.html
      const { store, nim } = window.__xkit_store__
      const [scene, to] = store.uiStore.selectedSession.split('-')
      const from = store.userStore.myUserInfo.account
      //用户自定义参数
      const attach = {
        isEvaluation: true
      }
      // sence代表发送场景 form 发送方 to接收方
      store.msgStore.sendCustomMsgActive({
        scene,
        from,
        to,
        attach: JSON.stringify(attach)
      }).then((res) => {
        console.log('=======发送成功======', res)
        // 让消息滚动到可视区域
        document.getElementById(res.idClient).scrollIntoView()
      }).catch((err) => {
        console.log('发送失败', err)
      })
    }

// 此部分代码为右侧发送按钮新增一个发送评价信息按钮,并绑定消息发送函数
 window.$uikit.render(
      ChatContainer,
      {
        actions: [
            //...,
            {
              action: 'evaluation',
              visible: true,
              render: (props) => {
                   return compile(`
                    <button onClick={context.sendEvaluationMessage}>
                      评价
                    </button>
                  `, {
                    sendEvaluationMessage
                  });
                },
            },
        ]
      },
          this.$refs.chat
    );
React
// IMUIKit store实例, store 文档参考 https://doc.yunxin.163.com/docs/interface/messaging/web/typedoc/UIKit/Latest/zh/modules.html
  const { store } = useStateContext()
   // 发送评价消息
   const sendEvaluationMessage = () => {
    const [scene, to] = store.uiStore.selectedSession.split('-')
    const from = store.userStore.myUserInfo.account
    //用户自定义参数
    const attach = {
      isEvaluation: true
    }
    // sence代表发送场景 form 发送方 to接收方
    store.msgStore.sendCustomMsgActive({
      scene,
      from,
      to,
      attach: JSON.stringify(attach)
    }).then((res) => {
      console.log('=======发送成功======', res)
      // 让消息滚动到可视区域
      document.getElementById(res.idClient).scrollIntoView()
    }).catch((err) => {
      console.log('发送失败', err)
    })
  }
  
  const actions = [
      //...,
      {
        action: 'evaluation',
        visible: true,
        render: (props) => {
             return (
              <button onClick={sendEvaluationMessageBySdk}>
                评价
              </button>
             )
          },
      },  
  ]
  
  
  <ChatContainer
      //...
      actions={actions}
   />
  • 通过调用SDK 原生方法 sendCustomMsg 实现的示例代码(IM 1为例):
Vue
const sendEvaluationMessageBySdk = () => {
      // 这里通过 uikit 实例获取 store,store 文档参考 https://doc.yunxin.163.com/docs/interface/messaging/web/typedoc/UIKit/Latest/zh/modules.html
      const { store, nim } = window.__xkit_store__
      const [scene, to] = store.uiStore.selectedSession.split('-')
      const from = store.userStore.myUserInfo.account
      //用户自定义参数
      const attach = {
        isEvaluation: true
      }
      nim.nim.sendCustomMsg({
        scene,
        to,
        //接收方通过onMsg接收消息
        //然后如果msg.type === 'custom',接收方通过读取msg.content,然后调用业务代码
        content: JSON.stringify(attach),
        done: function(err, msg) {
          if (err) {
              console.log('发送失败', err)
          } else {
              console.log('=======发送消息成功,消息为======: ', msg)
              // 将自定义消息插入到消息列表中, 这里将消息的attach中添加一个canRecall字段,用于标识是否可以撤回
              if (msg && msg.sessionId) {
                const canRecallMsg = {
                  ...msg,
                  attach: {
                    ...JSON.parse(msg.content),
                    canRecall: true,
                    reCallTimer: setTimeout(() => {
                      const _msg = store.msgStore.getMsg(msg.sessionId, [msg.idClient])[0]
                      if (_msg) {
                        const _attach = _msg.attach
                        if (_attach) {
                          delete _attach.canRecall
                          delete _attach.reCallTimer
                        }
                        _msg.attach = _attach
                        store.msgStore.addMsg(msg.sessionId, [_msg])
                      }
                    }, 2 * 60 * 1000),
                  },
                }
                store.msgStore.addMsg(msg.sessionId, [canRecallMsg])
                // 让消息滚动到可视区域
                document.getElementById(msg.idClient).scrollIntoView()
              }

          }
        }
      })
    }
    
    window.$uikit.render(
      ChatContainer,
      {
        actions: [
            //...,
            {
              action: 'evaluation',
              visible: true,
              render: (props) => {
               return compile(`
                <button onClick={context.sendEvaluationMessageBySdk}>
                  评价
                </button>
              `, {
                sendEvaluationMessageBySdk
              });
            },
            },
        ]
      },
          this.$refs.chat
    );
React
// IMUIKit store实例, store 文档参考 https://doc.yunxin.163.com/docs/interface/messaging/web/typedoc/UIKit/Latest/zh/modules.html
  const { store, nim } = useStateContext()
  const sendEvaluationMessageBySdk = () => {
    // 这里通过 uikit 实例获取 store,store 文档参考 https://doc.yunxin.163.com/docs/interface/messaging/web/typedoc/UIKit/Latest/zh/modules.html
    const [scene, to] = store.uiStore.selectedSession.split('-')
    const from = store.userStore.myUserInfo.account
    //用户自定义参数
    const attach = {
      isEvaluation: true
    }
    nim.nim.sendCustomMsg({
      scene,
      to,
      //接收方通过onMsg接收消息
      //然后如果msg.type === 'custom',接收方通过读取msg.content,然后调用业务代码
      content: JSON.stringify(attach),
      done: function(err, msg) {
        if (err) {
            console.log('发送失败', err)
        } else {
            console.log('=======发送消息成功,消息为======: ', msg)
            // 将自定义消息插入到消息列表中, 这里将消息的attach中添加一个canRecall字段,用于标识是否可以撤回
            if (msg && msg.sessionId) {
              const canRecallMsg = {
                ...msg,
                attach: {
                  ...JSON.parse(msg.content),
                  canRecall: true,
                  reCallTimer: setTimeout(() => {
                    const _msg = store.msgStore.getMsg(msg.sessionId, [msg.idClient])[0]
                    if (_msg) {
                      const _attach = _msg.attach
                      if (_attach) {
                        delete _attach.canRecall
                        delete _attach.reCallTimer
                      }
                      _msg.attach = _attach
                      store.msgStore.addMsg(msg.sessionId, [_msg])
                    }
                  }, 2 * 60 * 1000),
                },
              }
              store.msgStore.addMsg(msg.sessionId, [canRecallMsg])
              // 让消息滚动到可视区域
              document.getElementById(msg.idClient).scrollIntoView()
            }

        }
      }
    })
  }
  
  const actions = [
      //...,
      {
        action: 'evaluation',
        visible: true,
        render: (props) => {
             return (
              <button onClick={sendEvaluationMessageBySdk}>
                评价
              </button>
             )
          },
      },  
  ]
  
  
  <ChatContainer
      //...
      actions={actions}
   />  

接收自定义消息并渲染

同样以“接收评价消息”为例,接收方可从如下回调函数中获取 IM UIKit 渲染一条消息的所有参数,从而自行实现任意的 UI 展示。

如果需要针对特定类型(type)的消息进行单独的渲染处理,可以根据type判断并返回自定义的内容,如果返回null则使用默认渲染方式。

回调
类型
说明
renderP2pCustomMessage ((options: RenderP2pCustomMessageOptions) => Element | null) 渲染单聊中的自定义消息
注:RenderP2pCustomMessageOptions.msg 的类型请参考IMMessage
renderTeamCustomMessage ((options: RenderTeamCustomMessageOptions) => Element | null) 渲染群聊中的自定义消息
注:RenderTeamCustomMessageOptions.msg 的类型请参考IMMessage
renderMessageOuterContent ((msg: IMMessage) => JSX.Element | null | undefined) 自定义渲染会话消息,气泡样式也需要自定义
注:msg 的类型请参考IMMessage
renderMessageInnerContent ((msg: IMMessage) => JSX.Element | null | undefined) 自定义渲染会话消息,不需要自定义气泡样式
注:msg 的类型请参考IMMessage

您可以根据你业务需要,决定调用以上自定义消息的任意一种。

示例代码:

Vue
this.$uikit.render(
      ChatContainer,
      {
        renderMessageInnerContent:(options) => {
          console.log('===========options==========', options);
          let isEvaluation
          if(options.attach){
            isEvaluation = options.attach.isEvaluation
          }
          return isEvaluation ?
            compile(`<div className='wrapper'>
         <div className='msg-wrapper'>
          <div className='text'>欢迎您进行评价</div>
          <img className='star' src="https://yx-web-nosdn.netease.im/common/57dea86c692f76efdfecff37ee7e1059/星星.png"/>
          <img className='star' src="https://yx-web-nosdn.netease.im/common/57dea86c692f76efdfecff37ee7e1059/星星.png"/>
          <img className='star' src="https://yx-web-nosdn.netease.im/common/57dea86c692f76efdfecff37ee7e1059/星星.png"/>
          <img className='star' src="https://yx-web-nosdn.netease.im/common/57dea86c692f76efdfecff37ee7e1059/星星.png"/>
          <img className='star' src="https://yx-web-nosdn.netease.im/common/57dea86c692f76efdfecff37ee7e1059/星星.png"/>
          </div>
        </div> `, {
              options,
            }) : null},
        actions: [
            {
              action: 'emoji',
              visible: true,
            },
            {
              action: 'sendImg',
              visible: true,
            },
            {
              action: 'sendFile',
              visible: true,
            },
            {
              action: 'evaluation',
              visible: true,
              render: (props) => {
               return compile(`
                <context.Button onClick={context.sendEvaluationMessage} size="small" disabled={context.props.mute}>
                  <i className="iconfont icon-message_fill_light" />
                </context.Button>
              `, {
                props,
                CommonIcon,
                Button,
                sendEvaluationMessage
              });
            },
            },
        ]
      },
      this.$refs.chat
    );
React
<ChatContainer
      actions={actions}
      // renderP2pCustomMessage={renderP2pCustomMessage}
      renderMessageInnerContent={(options) => {
          console.log('===========options==========', options);
          let isEvaluation
          if(options.attach){
            isEvaluation = options.attach.isEvaluation
          }
          return isEvaluation ?
          (<div className='wrapper'>
         <div className='msg-wrapper'>
          <div className='text'>欢迎您进行评价</div>
          <img className='star' src="https://yx-web-nosdn.netease.im/common/57dea86c692f76efdfecff37ee7e1059/星星.png"/>
          <img className='star' src="https://yx-web-nosdn.netease.im/common/57dea86c692f76efdfecff37ee7e1059/星星.png"/>
          <img className='star' src="https://yx-web-nosdn.netease.im/common/57dea86c692f76efdfecff37ee7e1059/星星.png"/>
          <img className='star' src="https://yx-web-nosdn.netease.im/common/57dea86c692f76efdfecff37ee7e1059/星星.png"/>
          <img className='star' src="https://yx-web-nosdn.netease.im/common/57dea86c692f76efdfecff37ee7e1059/星星.png"/>
          </div>
        </div> ) : null}}
    />

查看在线示例

查看在线示例

IMAppProps 传入正确的 appkeyaccounttoken 即可在线预览效果。

最终实现的效果参见如下 gif 动图:

评价消息收发.gif

常见问题

可通过哪些参数/回调自定义渲染消息的样式?

支持通过如下参数/回调自定义渲染单聊和群聊的自定义消息。

参数/回调
类型 说明
renderP2pCustomMessage ((options: RenderP2pCustomMessageOptions) => Element | null) 渲染单聊中的自定义消息
renderTeamCustomMessage ((options: RenderTeamCustomMessageOptions) => Element | null) 渲染群聊中的自定义消息
renderMessageAvatar (msg: IMMessage) => JSX.Element | null | undefined 自定义渲染消息头像
renderMessageOuterContent ((msg: IMMessage) => JSX.Element | null | undefined) 自定义渲染会话消息,气泡样式也需要自定义
renderMessageInnerContent ((msg: IMMessage) => JSX.Element | null | undefined) 自定义渲染会话消息,不需要自定义气泡样式
renderMessageName (msg: IMMessage) => JSX.Element | null | undefined 自定义渲染消息昵称
此文档是否对你有帮助?
有帮助
去反馈
  • 基本消息类型
  • 前提条件
  • 实现方法
  • 发送自定义消息
  • 接收自定义消息并渲染
  • 查看在线示例
  • 常见问题
  • 可通过哪些参数/回调自定义渲染消息的样式?