即时通讯小程序
1.网易云信SDK
1)先申请注册云信账号
2)下载SDK
npm install @nertc/wechat-miniprogram --save
3)配置manifest.json
{"mp-weixin": {"permission": {"scope.userLocation": {"desc": "您的位置信息将用于小程序位置接口的效果展示"}},"requiredBackgroundModes": ["audio"],"plugins": {"live-player-plugin": {"version": "1.0.0","provider": "wx2b03c6e691cd7370"}}}
}
4)初始化SDK
// utils/nim.js
import SDK from '@/utils/nim-weapp-sdk'class NIMService {constructor() {this.nim = null}// 初始化SDKinit(options) {this.nim = SDK.NIM.getInstance({appKey: 'your_app_key',account: options.account,token: options.token,onconnect: this.onConnect.bind(this),onwillreconnect: this.onWillReconnect.bind(this),ondisconnect: this.onDisconnect.bind(this),onerror: this.onError.bind(this),onroamingmsgs: this.onRoamingMsgs.bind(this),onofflinemsgs: this.onOfflineMsgs.bind(this),onmsg: this.onMsg.bind(this),onsessions: this.onSessions.bind(this),onupdatesession: this.onUpdateSession.bind(this)})}// 连接成功onConnect() {console.log('连接成功')uni.$emit('nim-connect-success')}// 收到消息onMsg(msg) {console.log('收到消息:', msg)uni.$emit('nim-receive-msg', msg)}// 发送消息sendTextMsg(sessionId, text) {return this.nim.sendText({scene: 'p2p',to: sessionId,text: text})}// 发送图片sendImageMsg(sessionId, imagePath) {return this.nim.sendFile({scene: 'p2p',to: sessionId,type: 'image',file: imagePath})}
}export default new NIMService()
5)具体代码
<!-- components/chat/index.vue -->
<template><view class="chat-container"><!-- 消息列表 --><scroll-view class="message-list" scroll-y :scroll-top="scrollTop"@scrolltoupper="loadMore"><view v-for="(msg, index) in messageList" :key="index"class="message-item":class="{'self': msg.from === currentUser}"><view class="message-content"><text>{{ msg.text }}</text></view><text class="message-time">{{ formatTime(msg.time) }}</text></view></scroll-view><!-- 输入框 --><view class="input-area"><input v-model="inputText" placeholder="输入消息..."@confirm="sendMessage"class="text-input"/><button @click="sendMessage" class="send-btn">发送</button></view></view>
</template><script>
import nimService from '@/utils/nim.js'export default {data() {return {messageList: [],inputText: '',scrollTop: 0,currentUser: '',sessionId: ''}},onLoad(options) {this.sessionId = options.sessionIdthis.currentUser = uni.getStorageSync('userInfo').accountthis.initChat()},methods: {// 初始化聊天initChat() {// 监听消息uni.$on('nim-receive-msg', this.handleReceiveMsg)// 获取历史消息this.loadHistoryMessages()},// 发送消息sendMessage() {if (!this.inputText.trim()) returnnimService.sendTextMsg(this.sessionId, this.inputText).then(() => {this.inputText = ''this.scrollToBottom()}).catch(err => {console.error('发送失败:', err)})},// 处理接收消息handleReceiveMsg(msg) {if (msg.scene === 'p2p' && msg.from === this.sessionId) {this.messageList.push({from: msg.from,text: msg.text,time: msg.time})this.scrollToBottom()}},// 滚动到底部scrollToBottom() {this.$nextTick(() => {this.scrollTop = this.messageList.length * 100})}}
}
</script>
2.腾讯云IM
1)申请注册腾讯云申请权限
2)下载SDK
npm install tim-wx-sdk --save
npm install tim-upload-plugin --save
3)配置 manifest.json,添加腾讯云域名
{"mp-weixin": {"appid": "你的小程序appid","setting": {"urlCheck": false},"networkTimeout": {"request": 10000,"connectSocket": 10000},"domain": {"requestDomain": ["https://webim.tim.qq.com", "https://yun.tim.qq.com"],"socketDomain": ["wss://wss.im.qcloud.com"]}}
}
4)初始化SDK
import TIM from 'tim-wx-sdk';
import TIMUploadPlugin from 'tim-upload-plugin';let tim = null;
let isInitialized = false;// 初始化IM
export function initLiveIM(SDKAppID) {if (isInitialized) return tim;// 创建实例tim = TIM.create({ SDKAppID });// 注册上传插件tim.registerPlugin({ 'tim-upload-plugin': TIMUploadPlugin });// 监听核心事件tim.on(TIM.EVENT.SDK_READY, handleSDKReady);tim.on(TIM.EVENT.MESSAGE_RECEIVED, handleMessageReceived);tim.on(TIM.EVENT.ERROR, handleError);isInitialized = true;return tim;
}// 登录IM
export function loginIM(userID, userSig) {return tim.login({ userID, userSig });
}// 加入直播群
export function joinLiveRoom(roomID) {return tim.joinGroup({groupID: roomID,type: TIM.TYPES.GRP_AVCHATROOM // 直播群类型});
}// 发送文本消息(弹幕)
export function sendDanmaku(roomID, text) {const message = tim.createTextMessage({to: roomID,conversationType: TIM.TYPES.CONV_AVCHATROOM,payload: { text }});return tim.sendMessage(message);
}// 发送礼物消息(自定义消息)
export function sendGift(roomID, giftInfo) {const message = tim.createCustomMessage({to: roomID,conversationType: TIM.TYPES.CONV_AVCHATROOM,payload: {data: JSON.stringify(giftInfo),description: 'gift', // 用于区分消息类型extension: ''}});return tim.sendMessage(message);
}// 事件处理函数
function handleSDKReady() {console.log('IM SDK 就绪');// 可以在这里获取历史消息
}function handleMessageReceived(event) {const { messageList } = event;messageList.forEach(msg => {// 区分消息类型并触发对应事件if (msg.type === TIM.TYPES.MSG_TEXT) {// 普通文本消息(弹幕)wx.$emit('liveDanmaku', {user: msg.from,content: msg.payload.text,time: msg.time});} else if (msg.type === TIM.TYPES.MSG_CUSTOM && msg.payload.description === 'gift') {// 礼物消息wx.$emit('liveGift', {user: msg.from,gift: JSON.parse(msg.payload.data),time: msg.time});}});
}function handleError(error) {console.error('IM 错误:', error);if (error.data.type === TIM.TYPES.ERROR_TOKEN_EXPIRED) {// 处理token过期,需要重新登录wx.$emit('imTokenExpired');}
}// 退出登录
export function logoutIM() {return tim.logout();
}export default {initLiveIM,loginIM,joinLiveRoom,sendDanmaku,sendGift,logoutIM
};
5)具体代码
<!-- 直播播放器 -->
<live-player src="{{ liveUrl }}" mode="live" autoplay class="live-player"
></live-player><!-- 弹幕显示区域 -->
<view class="danmaku-container"><view class="danmaku" wx:for="{{ danmakus }}" wx:key="index"style="top: {{ item.top }}px; left: {{ item.left }}px;"><text class="danmaku-user">{{ item.user }}:</text><text class="danmaku-content">{{ item.content }}</text></view>
</view><!-- 礼物特效区域 -->
<view class="gift-container" wx:if="{{ currentGift }}"><image src="{{ currentGift.gift.icon }}" class="gift-icon"></image><text class="gift-text">{{ currentGift.user }} 送出了 {{ currentGift.gift.name }}</text>
</view><!-- 聊天输入区域 -->
<view class="chat-area"><input type="text" value="{{ inputText }}" placeholder="发送弹幕..." bindinput="onInputChange"bindconfirm="sendDanmaku"class="chat-input"/><button bindtap="sendDanmaku" class="send-btn">发送</button>
</view><!-- 礼物选择区 -->
<view class="gift-selector"><view class="gift-item" wx:for="{{ gifts }}" wx:key="id"bindtap="sendGift"data-gift="{{ item }}"><image src="{{ item.icon }}" class="gift-img"></image><text class="gift-name">{{ item.name }}</text></view>
</view>