在社交类应用开发中,群聊@功能是提升沟通效率的核心交互。本文将基于腾讯云IM SDK,在UniApp框架下实现以下功能:
npm install tim-js-sdk tim-upload-plugin --save
// 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); // 调试阶段建议开启日志
// 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 || ''
}))
}
}
};
};
// 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' });
}
}
// 消息监听逻辑
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);
}
}
<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>
<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>
// 使用lodash防抖优化输入体验
import _ from 'lodash';
export default {
methods: {
handleInput: _.debounce(function(e) {
// 原始处理逻辑
}, 300)
}
}
安全校验:
性能优化:
// 消息内容长度限制
const MAX_MESSAGE_LENGTH = 2000;
if (text.length > MAX_MESSAGE_LENGTH) {
uni.showToast({ title: '消息内容过长', icon: 'none' });
return;
}
平台适配:
扩展功能建议:
// @所有人特殊处理
if (atUsers.includes('ALL')) {
// 显示红色醒目标记
// 触发强制推送通知
}
通过腾讯云IM的自定义消息机制,结合UniApp的跨平台能力,可以高效实现完整的@功能体系。实际开发中需重点关注: