uniapp 实现腾讯云IM @成员功能

UniApp 集成腾讯云IM实现@功能的实战指南

一、技术选型与实现目标

在社交类应用开发中,群聊@功能是提升沟通效率的核心交互。本文将基于腾讯云IM SDK,在UniApp框架下实现以下功能:

  1. 消息输入时智能提示@对象
  2. 发送消息时携带@成员信息
  3. 接收端精准识别@内容并高亮显示
  4. 被@用户接收实时通知提醒

二、环境准备与SDK初始化

2.1 安装依赖包

npm install tim-js-sdk tim-upload-plugin --save

2.2 全局SDK配置

// main.js
import TIM from 'tim-js-sdk';
import TIMUploadPlugin from 'tim-upload-plugin';

// 创建SDK实例
export const tim = TIM.create({
  SDKAppID: xxxxxxxxxxx // 必填项
});

// 注册上传插件
tim.registerPlugin({ 'tim-upload-plugin': TIMUploadPlugin });

// 初始化配置
tim.setLogLevel(0); // 调试阶段建议开启日志

三、核心功能实现流程

3.1 消息构造器封装

// utils/message-builder.js
export const buildAtMessage = (content, atUserList = []) => {
  return {
    type: 'TIMTextElem',
    content: {
      text: content,
      mentionInfo: {
        mentionedType: atUserList.length ? 'PART' : 'ALL',
        mentionedUserList: atUserList.map(user => ({
          userID: user.userID,
          nickName: user.nickName || ''
        }))
      }
    }
  };
};

3.2 发送带@的消息

// pages/chat/chat.vue
async function handleSendMessage() {
  if (!this.messageContent.trim()) return;

  try {
    const message = tim.createTextMessage({
      to: this.currentConversation.groupId,
      conversationType: 'GROUP',
      payload: buildAtMessage(
        this.messageContent,
        this.selectedAtUsers // 存储已选@用户的数组
      )
    });

    const { data: messageID } = await tim.sendMessage(message);
    console.log('消息发送成功', messageID);
  } catch (err) {
    console.error('发送失败:', err);
    uni.showToast({ title: '发送失败', icon: 'none' });
  }
}

3.3 消息接收与解析

// 消息监听逻辑
tim.on(TIM.EVENT.MESSAGE_RECEIVED, (event) => {
  event.data.forEach(message => {
    if (message.type === 'TIMTextElem') {
      handleTextMessage(message);
    }
  });
});

function handleTextMessage(message) {
  const { mentionInfo } = message.payload;
  if (!mentionInfo) return;

  // 判断是否包含当前用户
  const isMentioned = mentionInfo.mentionedUserList.some(user => 
    user.userID === tim.getUserProfile().userID
  );

  if (isMentioned) {
    // 触发本地通知(需实现具体逻辑)
    showLocalNotification(message);
  }
}

3.4 前端UI高亮渲染

<template>
  <view class="message-container">
    <rich-text :nodes="parseMessageContent(message.payload.text)"></rich-text>
  </view>
</template>

<script>
export default {
  methods: {
    parseMessageContent(text) {
      const atPattern = /@(\S+?)\b/g;
      const segments = [];
      let lastIndex = 0;

      text.replace(atPattern, (match, p1, offset) => {
        // 添加普通文本
        if (offset > lastIndex) {
          segments.push({ type: 'text', text: text.slice(lastIndex, offset) });
        }

        // 添加@标记
        segments.push({
          type: 'span',
          attrs: {
            class: 'at-mention',
            '@click': `handleAtClick('${p1}')`
          },
          children: [{ type: 'text', text: match }]
        });

        lastIndex = offset + match.length;
        return '';
      });

      // 处理剩余文本
      if (lastIndex < text.length) {
        segments.push({ type: 'text', text: text.slice(lastIndex) });
      }

      return segments;
    }
  }
}
</script>

<style>
.at-mention {
  color: #007AFF;
  font-weight: 500;
  padding: 2rpx 4rpx;
  border-radius: 4rpx;
  background-color: rgba(0,122,255,0.1);
}
</style>

四、关键优化策略

4.1 输入框@联想优化

<!--使用uni-popup实现选择器-->
<uni-popup ref="atSelector" type="bottom">
  <scroll-view scroll-y style="max-height: 60vh">
    <view 
      v-for="user in filteredUsers" 
      :key="user.userID"
      class="at-item"
      @click="selectAtUser(user)"
    >
      {{ user.nickName }}
    </view>
  </scroll-view>
</uni-popup>

<script>
export default {
  methods: {
    handleInput(e) {
      const content = e.detail.value;
      const lastWord = content.split(/[\s@]/).pop();

      if (lastWord.startsWith('@')) {
        const keyword = lastWord.slice(1);
        this.searchUsers(keyword);
      }
    }
  }
}
</script>

4.2 消息防抖处理

// 使用lodash防抖优化输入体验
import _ from 'lodash';

export default {
  methods: {
    handleInput: _.debounce(function(e) {
      // 原始处理逻辑
    }, 300)
  }
}

五、生产环境注意事项

  1. 安全校验

    • 后端应校验@用户是否属于当前群组
    • 限制单条消息@人数(建议不超过50人)
  2. 性能优化

    // 消息内容长度限制
    const MAX_MESSAGE_LENGTH = 2000;
    if (text.length > MAX_MESSAGE_LENGTH) {
      uni.showToast({ title: '消息内容过长', icon: 'none' });
      return;
    }
    
  3. 平台适配

    • 小程序端需处理rich-text组件对span标签的支持
    • App端建议使用原生富文本组件提升渲染性能
  4. 扩展功能建议

    // @所有人特殊处理
    if (atUsers.includes('ALL')) {
      // 显示红色醒目标记
      // 触发强制推送通知
    }
    

六、总结

通过腾讯云IM的自定义消息机制,结合UniApp的跨平台能力,可以高效实现完整的@功能体系。实际开发中需重点关注:

  1. 消息协议的规范设计(推荐使用JSON Schema校验)
  2. 前后端数据校验的闭环机制
  3. 输入体验的持续优化(建议接入Fuse.js实现模糊搜索)
  4. 性能监控(重点关注消息渲染时的DOM节点数量)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

^Rocky

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值