溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

小程序如何導(dǎo)入sdk實現(xiàn)聊天功能

發(fā)布時間:2021-01-20 10:24:50 來源:億速云 閱讀:180 作者:小新 欄目:移動開發(fā)

這篇文章主要介紹小程序如何導(dǎo)入sdk實現(xiàn)聊天功能,文中介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們一定要看完!

小程序怎么導(dǎo)入sdk實現(xiàn)聊天功能

首先使用npm進行下載騰訊云的即時聊天sdk;然后在項目中進行引用并進行sdk初始化;再根據(jù)后臺接口返回userID,userSig這兩個參數(shù)判斷當(dāng)前登錄人是誰;最后根據(jù)文檔實現(xiàn)基礎(chǔ)功能即可。

示例代碼

wxml:

<scroll-view  bindscroll="refresh" scroll-into-view="{{toView}}" style="height: {{scroll_height}}px;" upper-threshold="100" scroll-y="true" enable-back-to-top="true" class="message-list">
  <!-- 每一行 -->
  <view class="row" wx:for="{{messages}}" wx:key="{{index}}" id="row_{{index}}">
    <!-- 日期 -->
    <view class="datetime" wx:if="{{item.msgTime != ''}}">{{item.msgTime}}</view>
    <!-- 頭像與內(nèi)容文本 -->
    <view class="body" style="flex-flow: {{item.flow == 'in' ? 'row' : 'row-reverse'}}">
      <view class="avatar-container">
        <image wx:if="{{item.flow=='in'}}" class="avatar" src="{{friendAvatarUrl}}" />
        <image wx:else class="avatar" src="{{userData.avatarUrl}}" />
      </view>
      <!-- 畫對話框 -->
      <view class="triangle" style="{{item.flow == 'out' ? 'right: 140rpx; background: #7ECB4B' : 'left: 140rpx;'}}"></view>
      <view class="content" style="{{item.flow == 'out' ? 'background: #7ECB4B' : ''}}">
        <view wx:if="{{item.type === 'TIMTextElem'}}">{{item.payload.text}}</view>
        <image class="image-message" wx:elif="{{item.type === 'TIMImageElem'}}" src="{{item.payload.imageInfoArray[1].url}}" bindtap="previewImage" data-src="{{item.payload.imageInfoArray[1].url}}"></image>
        <view wx:elif="{{item.type === 'TIMSoundElem'}}" url="{{item.payload.url}}">
          <view class="box" bindtap="openAudio" data-eventid="{{'13_'+index}}"  data-time="{{item.payload.second}}" data-comkey="{{item.payload.url}}">
            <image  src="{{'13_'+index==audioIndex?audioGif:audioPng}}" style="height:22px;width:22px" class="_image"></image>
            <view style="padding-left: 4px;" class="_div data-v-afeb3abc">
              {{item.payload.second<1?1:item.payload.second}}s
            </view>
          </view>
        </view>
      </view>
    </view>
  </view>
</scroll-view>
<view class="reply" style="bottom:{{reply_height}}px;">
  <view class="Audio">
    <image wx:if="{{opration==true}}" bindtap="Audio" src="../image/Audio.png"></image>
    <image wx:else bindtap="keyboard" src="../image/keyboard.png"></image>
  </view>
  <view class="opration-area">
    <input bindfocus="bindfocus" wx:if="{{opration==true}}" type="text" bindinput="getContent" value="{{content}}" />
    <view wx:else class="voice-button {{touchBtn?'hoverBtn':''}}" bind:touchstart="startAudio" bind:touchend="onTouchEnd" bind:longpress="onLongpress" bind:touchmove="onTouchMove">
      {{touchBtn?'松開 結(jié)束':'按住說話'}}
    </view>
  </view>
  <view class="{{sendBtn==true?'send':'sendActive'}}" bindtap="sendMsg">發(fā)送</view>
  <view class="add" bind:tap="moreClick">
    <image class="more" src="../image/more.png"></image>
  </view>
  <!-- <view class="send" bindtap="sendImg">相冊</view>
  <view class="send" bindtap="startAudio">開始</view>
  <view class="send" bindtap="endAudio">結(jié)束</view> -->
</view>
<view class="more_box" hidden="{{moreShow}}"> 
  <view class="more_item" bindtap="sendImg">
    <view class="img_box">
      <image src="../image/picture.png"></image>
    </view>
    <view style="margin-top:10rpx;">
      <text>相冊</text>
    </view>
  </view>
</view>

js:

import TIM from 'tim-wx-sdk';
import COS from "cos-wx-sdk-v5";
let options = {
  SDKAppID: 0 // 接入時需要將0替換為您的即時通信 IM 應(yīng)用的 SDKAppID
};
// 創(chuàng)建 SDK 實例,`TIM.create()`方法對于同一個 `SDKAppID` 只會返回同一份實例
let tim = TIM.create(options); // SDK 實例通常用 tim 表示
// 設(shè)置 SDK 日志輸出級別,詳細(xì)分級請參見 setLogLevel 接口的說明
tim.setLogLevel(1); // 普通級別,日志量較多,接入時建議使用
// tim.setLogLevel(1); // release 級別,SDK 輸出關(guān)鍵信息,生產(chǎn)環(huán)境時建議使用
// 注冊 COS SDK 插件
tim.registerPlugin({
  'cos-wx-sdk': COS
});
const app = getApp()
let recorderManager = wx.getRecorderManager();
// 錄音部分參數(shù) 小程序文檔
const recordOptions = {
  duration: 60000, // 錄音的時長,單位 ms,最大值 600000(10 分鐘)
  sampleRate: 44100, // 采樣率
  numberOfChannels: 1, // 錄音通道數(shù)
  encodeBitRate: 192000, // 編碼碼率
  format: 'aac' // 音頻格式,選擇此格式創(chuàng)建的音頻消息,可以在即時通信 IM 全平臺(Android、iOS、微信小程序和Web)互通
};
Page({
  data: {
    friendId: '',
    friendName: '',
    friendAvatarUrl: '',
    messages: [], // 消息集合
    complete: 0, // 是否還有歷史消息可以拉取,1 - 表示沒有,0 - 表示有
    content: '', // 輸入框的文本值
    lock: false, // 發(fā)送消息鎖 true - 加鎖狀態(tài) false - 解鎖狀態(tài)
    scroll_height: wx.getSystemInfoSync().windowHeight - 54,
    reply_height: 0,
    moreShow: true,
    userData: [],
    
    audioPng:"../image/audio-play.png",
    audioGif:"../image/audio-play.gif",
    audioState:true,
    /**
     * 歷史消息消息集合(結(jié)構(gòu)如下):
     * nextReqMessageID 用于續(xù)拉,分頁續(xù)拉時需傳入該字段。
     * isCompleted 表示是否已經(jīng)拉完所有消息。
     */
    nextReqMessageID: "",
    isCompleted: "",
    isFirstGetList: true,
    audioContext: null,
    opration: true,
    touchBtn: false,
    recording: false,
    stopflag: false,
    cancelRecord: false,
    refreshTime: '',
    ScrollLoading: 0,
    audioIndex:null,
    sendBtn:true
  },
  onLoad: function (options) {
    // 
    this.setData({
      friendId: options.friendId,
      friendName: options.friendName,
      friendAvatarUrl: options.friendAvatarUrl,
      conversationID: options.conversationID
    })
    wx.setNavigationBarTitle({
      title: options.friendName
    })
    var that = this
    var userData = JSON.parse(wx.getStorageSync('userData'))
    that.data.messages = [] // 清空歷史消息
    let audioContext = wx.createInnerAudioContext()
    this.setData({
      userData,
      audioContext
    })
    // 將某會話下所有未讀消息已讀上報
    let promise = tim.setMessageRead({ conversationID: options.conversationID });
    promise.then(function (imResponse) {
      // 已讀上報成功
    }).catch(function (imError) {
      // 已讀上報失敗
    });
  },
  onShow: function () {
    let that = this;
    // 獲取當(dāng)前聊天的歷史列表
    that.getMessageList();
    that.scrollToBottom();
    // 獲取收到的單聊信息
    let onMessageReceived = function (event) {
      // event.data - 存儲 Message 對象的數(shù)組 - [Message]
      let msgList = that.data.messages
      handlerHistoryMsgs(event.data, that)
      that.scrollToBottom();
    };
    tim.on(TIM.EVENT.MESSAGE_RECEIVED, onMessageReceived)
    // 監(jiān)聽錄音結(jié)束
    recorderManager.onStop(function (res) {
      if (that.data.recording) {
        if (that.data.cancelRecord) {
          wx.hideToast()
          that.setData({
            cancelRecord: false
          })
        } else {
          // 創(chuàng)建消息實例,接口返回的實例可以上屏
          const message = tim.createAudioMessage({
            to: that.data.friendId,
            conversationType: TIM.TYPES.CONV_C2C,
            payload: {
              file: res
            },
            onProgress: function (event) { }
          });
          //  發(fā)送消息
          let promise = tim.sendMessage(message);
          promise.then(function (imResponse) {
            // 發(fā)送成功
            that.addMessage(imResponse.data.message, that)
          }).catch(function (imError) {
            // 發(fā)送失敗
          });
          that.setData({
            recording: false
          })
        }
      } else {
        wx.showToast({
          title: '說話時間太短',
          duration: 1000,
          image: '../image/err.png'
        })
      }
    });
  },
  onUnload: function () {
  },
  /**
   * 獲取消息列表
   */
  getMessageList() {
    let that = this;
    let cb = tim.getMessageList({
      conversationID: conversationID,//會話列表傳遞過來的參數(shù)
      count: 15
    })
    cb.then(function (imResponse) {
      const messageList = imResponse.data.messageList; // 消息列表。
      const nextReqMessageID = imResponse.data.nextReqMessageID; // 用于續(xù)拉,分頁續(xù)拉時需傳入該字段。
      const isCompleted = imResponse.data.isCompleted; // 表示是否已經(jīng)拉完所有消息。
      that.setData({
        nextReqMessageID: nextReqMessageID,
        isCompleted: isCompleted
      })
      handlerHistoryMsgs(messageList, that);
      that.scrollToBottom();
    });
  },
  /**
   * 獲取文本的消息
   */
  getContent: function (e) {
    if(e.detail.value ==""){
      this.setData({sendBtn:true})
    }else{
      this.setData({sendBtn:false})
    }
    console.log(e)
    var that = this;
    that.setData({
      content: e.detail.value
    })
  },
  /**
   * 發(fā)送消息
   */
  sendMsg: function (e) {
    if(this.data.content ==""){
      wx.showToast({
        title: '請輸入內(nèi)容',
        duration: 1000,
        icon:'none'
      })
      return
    }
    var that = this
    // 發(fā)送文本消息,Web 端與小程序端相同
    // 1. 創(chuàng)建消息實例,接口返回的實例可以上屏
    let message = tim.createTextMessage({
      to: this.data.friendId,
      conversationType: TIM.TYPES.CONV_C2C,
      payload: {
        text: this.data.content
      }
    });
    // 2. 發(fā)送消息
    let promise = tim.sendMessage(message);
    promise.then(function (imResponse) {
      // 發(fā)送成功
      that.addMessage(imResponse.data.message, that)
      that.setData({sendBtn:true})
    }).catch(function (imError) {
      // 發(fā)送失敗
    });
  },
  /**
   * 刷新文本消息
   */
  addMessage: function (msg, that) {
    var messages = that.data.messages;
    messages.push(msg);
    that.setData({
      messages: messages,
      content: '' // 清空輸入框文本
    })
    that.scrollToBottom();
  },
  /**
   * 發(fā)送圖片消息
   */
  sendImg() {
    let that = this;
    wx.chooseImage({
      sourceType: ['album'], // 從相冊選擇
      count: 1, // 只選一張,目前 SDK 不支持一次發(fā)送多張圖片
      success: function (res) {
        // 2. 創(chuàng)建消息實例,接口返回的實例可以上屏
        let message = tim.createImageMessage({
          to: that.data.friendId,
          conversationType: TIM.TYPES.CONV_C2C,
          payload: {
            file: res
          },
          onProgress: function (event) {
          }
        });
        // 3. 發(fā)送圖片
        let promise = tim.sendMessage(message);
        promise.then(function (imResponse) {
          // 發(fā)送成功
          that.addMessage(imResponse.data.message, that)
        }).catch(function (imError) {
          // 發(fā)送失敗
        });
      }
    })
  },
  scrollToBottom: function () {
    this.setData({
      toView: 'row_' + (this.data.messages.length - 1)
    });
  },
  previewImage(e) {
    let src = '';
    wx.previewImage({
      current: e.currentTarget.dataset.src, // 當(dāng)前顯示圖片的http鏈接
      urls: [e.currentTarget.dataset.src]
    })
  },
  // 錄制語音
  startAudio: function () {
    wx.showToast({
      title: '上滑取消發(fā)送',
      duration: 10000,
      image: '../image/cancel.png'
    })
    this.setData({
      touchBtn: true
    })
    if (this.data.stopFlag) {
      return;
    }
    recorderManager.start(recordOptions);
    recorderManager.onError(function (errMsg) {
    });
  },
  // # 利用長按判斷錄音是否太短
  onLongpress() {
    this.setData({
      recording: true
    })
  },
  // 發(fā)送錄音
  onTouchEnd: function () {
    wx.hideToast()
    let that = this;
    that.setData({
      touchBtn: false
    })
    if (that.data.stopFlag) {
      return;
    }
    if (that.data.recording) {
      recorderManager.stop();
    } else {
      that.setData({
        stopFlag: true
      })
      setTimeout(() => {
        recorderManager.stop();
        that.setData({
          stopFlag: false
        })
      }, 400);
    }
  },
  // 播放語音
  openAudio(audio) {
    console.log(audio)
    let index = audio.currentTarget.dataset.eventid
    this.setData({
      audioIndex:index
      // audioState:false
    })
    this.data.audioContext.src = audio.currentTarget.dataset.comkey
    this.data.audioContext.autoplay = true;
    this.data.audioContext.play()
    this.data.audioContext.onPlay((res) => {
    })
    this.data.audioContext.onEnded(() => {
      wx.hideToast()
      this.setData({
        audioIndex:null
      })
      console.log("語音結(jié)束了")
    })
    this.data.audioContext.onError((res) => {
    })
  },
  // 上滑取消
  onTouchMove(e) {
    if (e.touches[0].clientY < 520) {
      // # 取消發(fā)送
      this.setData({
        cancelRecord: true
      });
      wx.showToast({
        title: '松開,取消發(fā)送',
        duration: 10000,
        image: '../image/cancel.png'
      })
    } else {
      // # 不取消
      wx.hideToast()
      wx.showToast({
        title: '上滑取消發(fā)送',
        duration: 10000,
        image: '../image/cancel.png'
      })
      this.setData({
        cancelRecord: false
      })
    }
  },
  // 下拉加載聊天記錄
  refresh: function (e) {
    let that = this
    if (that.data.ScrollLoading == 1) { //防止多次觸發(fā)
      return false
    }
    if (e.detail.scrollTop < 1) {
      that.setData({ ScrollLoading: 1 })
      wx.showLoading({
        title: '加載中',
      })
      setTimeout(() => {
        let promise = tim.getMessageList({ conversationID: that.data.conversationID, nextReqMessageID: that.data.nextReqMessageID, count: 15 });
        promise.then(function (imResponse) {
          const newMessageList = imResponse.data.messageList; // 消息列表。
          const nextReqMessageID = imResponse.data.nextReqMessageID; // 用于續(xù)拉,分頁續(xù)拉時需傳入該字段。
          const isCompleted = imResponse.data.isCompleted; // 表示是否已經(jīng)拉完所有消息。
          that.setData({
            nextReqMessageID: nextReqMessageID,
            isCompleted: isCompleted,
            messages: newMessageList.concat(that.data.messages)
          })
          wx.hideLoading()
          that.setData({ ScrollLoading: 0 })
          // handlerHistoryMsgs(messageList, that);
        });
      }, 800);
    }
    // setTimeout(function(){
    //   var date = new Date();
    // },300);
  },
  // 切換
  Audio() {
    this.setData({
      opration: false
    })
  },
  keyboard() {
    this.setData({
      opration: true
    })
  },
  moreClick() {
    if (this.data.moreShow) {
      this.setData({
        moreShow: false,
        reply_height: 92,
        scroll_height: this.data.scroll_height - 92
      })
    }
  },
  bindfocus() {
    this.setData({
      moreShow: true,
      reply_height: 0,
      scroll_height: wx.getSystemInfoSync().windowHeight - 54
    })
  }
})
/**
 * 處理歷史消息 
 */
function handlerHistoryMsgs(result, that) {
  var historyMsgs = that.data.messages;
  result.forEach(item => {
    historyMsgs.push(item)
  })
  // historyMsgs.push(result[0])
  that.setData({
    messages: historyMsgs,
  })
    // 將某會話下所有未讀消息已讀上報
    let promise = tim.setMessageRead({ conversationID: that.data.conversationID });
    promise.then(function (imResponse) {
      // 已讀上報成功
    }).catch(function (imError) {
      // 已讀上報失敗
    });
}

wxss:

/** 聊天窗口樣式
 * 54px為回復(fù)框高度,js同
 */
/*聊天記錄*/
page{
  background: rgb(245, 245, 245);
}
.message-list {
  /*margin-bottom: 54px;*/
  background: rgb(235, 235, 235);
}
/*單元行*/
.row {
  display: flex;
  flex-direction: column;
  margin: 0 30rpx;
}
/*日期*/
.datetime {
  font-size: 10px;
  padding: 10px 0;
  color: #999;
  text-align: center;
}
.send {
  font-size: 15px;
  /* padding-right: 10px; */
  color: #999;
  text-align: center;
  height: 70%;
  border: 1px solid #e4dfdf;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 90rpx;
  border-radius: 10rpx;
}
.sendActive {
  font-size: 15px;
  /* padding-right: 10px; */
  color: #fff;
  text-align: center;
  height: 70%;
  border: 1px solid #05c15f;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 90rpx;
  border-radius: 10rpx;
  background-color: #05c15f;
}
.Audio {
  font-size: 15px;
  color: #999;
  text-align: center;
  padding-left: 10rpx;
}
.Audio image {
  width: 50rpx;
  height: 50rpx;
}
.add {
  height: 70%;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 90rpx;
}
.more {
  width: 50rpx;
  height: 50rpx;
}
/*主體*/
.body {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  justify-content: flex-start;
  width: 100%;
  margin-top: 10px;
}
/*頭像容器*/
.body.avatar-container {
  width: 20%;
}
/*頭像*/
.body .avatar {
  width: 80rpx;
  height: 80rpx;
  border-radius: 50%;
  margin: 0 20rpx;
}
/*文本消息*/
.body .content {
  font-size: 16px;
  background: #fff;
  border-radius: 5px;
  padding: 10px;
  line-height: 22px;
  margin-bottom: 10px;
  word-wrap: break-word;
  max-width: 300rpx;
}
/* 三角箭頭 */
.body .triangle {
  background: white;
  width: 20rpx;
  height: 20rpx;
  margin-top: 26rpx;
  transform: rotate(45deg);
  position: absolute;
}
/*圖片消息*/
.picture {
  width: 160px;
}
/*回復(fù)框*/
.reply {
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
  position: fixed;
  /* bottom: 0; */
  width: 100%;
  height: 54px;
  border-top: 1px solid rgb(215, 215, 215);
  background: rgb(245, 245, 245);
}
.reply .voice-image {
  width: 25px;
  height: 25px;
  margin-left: 3%;
}
/*文本輸入或語音錄入*/
.reply .opration-area {
  flex: 1;
  padding: 8px;
}
/*回復(fù)文本框*/
.reply input {
  background: rgb(252, 252, 252);
  height: 36px;
  border: 1px solid rgb(221, 221, 221);
  border-radius: 6px;
  padding-left: 3px;
}
/*選取圖片*/
.reply .choose-image {
  width: 25px;
  height: 25px;
  margin-right: 3%;
}
/*按住說話button*/
.voice-button {
  height: 36px;
  color: #818181;
  font-size: 14px;
  line-height: 36px;
  text-align: center;
  border: 1px solid #e4dfdf;
  border-radius: 10rpx;
}
/*懸浮提示框*/
.hud-container {
  position: fixed;
  width: 150px;
  height: 150px;
  left: 50%;
  top: 50%;
  margin-left: -75px;
  margin-top: -75px;
}
/*背景層*/
.hud-background {
  position: absolute;
  width: 100%;
  height: 100%;
  background: #999;
  opacity: 0.8;
  z-index: 11;
  border-radius: 10px;
}
/*懸浮框主體*/
.hud-body {
  position: relative;
  width: 100%;
  height: 100%;
  z-index: 19;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
}
/*圖標(biāo)*/
.hud-body image {
  margin-top: 20px;
  width: 80px;
  height: 80px;
}
/*文字*/
.hud-body .tip {
  color: #fff;
  text-align: center;
  width: 90%;
  line-height: 34px;
  margin: 0 auto;
  margin-bottom: 10px;
  width: 90%;
}
.hud-body .warning {
  background: #c33;
  border-radius: 5px;
}
.image-message {
  max-width: 100%;
  border-radius: 4rpx;
}
.box {
  display: flex;
  height: 40rpx;
  line-height: 40rpx;
}
.hoverBtn {
  background-color: rgb(226, 220, 220);
  color: #fff;
  border-radius: 10rpx;
}
.more_box {
height: 138rpx;
width: 100%;
padding: 15rpx;
display: flex;
background: rgb(245, 245, 245);
position: fixed;
bottom: 0;
}
.more_item {
  text-align: center;
  height: 150rpx;
  font-size: 24rpx;
  margin-left: 26rpx
}
.img_box {
  width: 80rpx;
  height: 84rpx;
  background-color: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 10rpx;
}
.img_box image {
  width: 40rpx;
  height: 40rpx;
}

以上是“小程序如何導(dǎo)入sdk實現(xiàn)聊天功能”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI