即时通讯小程序

发布于:2025-09-11 ⋅ 阅读:(18) ⋅ 点赞:(0)

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
  }
  
  // 初始化SDK
  init(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.sessionId
    this.currentUser = uni.getStorageSync('userInfo').account
    this.initChat()
  },
  
  methods: {
    // 初始化聊天
    initChat() {
      // 监听消息
      uni.$on('nim-receive-msg', this.handleReceiveMsg)
      
      // 获取历史消息
      this.loadHistoryMessages()
    },
    
    // 发送消息
    sendMessage() {
      if (!this.inputText.trim()) return
      
      nimService.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>
    


网站公告

今日签到

点亮在社区的每一天
去签到