• 技术文章 >微信小程序 >小程序开发

    小程序怎么导入sdk实现聊天功能

    GuanhuiGuanhui2020-05-11 15:38:35原创2469

    小程序怎么导入sdk实现聊天功能

    首先使用npm进行下载腾讯云的即时聊天sdk;然后在项目中进行引用并进行sdk初始化;再根据后台接口返回userID,userSig这两个参数判断当前登录人是谁;最后根据文档实现基础功能即可。

    示例代码

    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>
        <!-- 头像与内容文本 -->
        <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?'松开 结束':'按住说话'}}
        </view>
      </view>
      <view class="{{sendBtn==true?'send':'sendActive'}}" bindtap="sendMsg">发送</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">结束</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 应用的 SDKAppID
    };
    // 创建 SDK 实例,`TIM.create()`方法对于同一个 `SDKAppID` 只会返回同一份实例
    let tim = TIM.create(options); // SDK 实例通常用 tim 表示
    // 设置 SDK 日志输出级别,详细分级请参见 setLogLevel 接口的说明
    tim.setLogLevel(1); // 普通级别,日志量较多,接入时建议使用
    // tim.setLogLevel(1); // release 级别,SDK 输出关键信息,生产环境时建议使用
    // 注册 COS SDK 插件
    tim.registerPlugin({
      'cos-wx-sdk': COS
    });
    const app = getApp()
    let recorderManager = wx.getRecorderManager();
    // 录音部分参数 小程序文档
    const recordOptions = {
      duration: 60000, // 录音的时长,单位 ms,最大值 600000(10 分钟)
      sampleRate: 44100, // 采样率
      numberOfChannels: 1, // 录音通道数
      encodeBitRate: 192000, // 编码码率
      format: 'aac' // 音频格式,选择此格式创建的音频消息,可以在即时通信 IM 全平台(Android、iOS、微信小程序和Web)互通
    };
    Page({
      data: {
        friendId: '',
        friendName: '',
        friendAvatarUrl: '',
        messages: [], // 消息集合
        complete: 0, // 是否还有历史消息可以拉取,1 - 表示没有,0 - 表示有
        content: '', // 输入框的文本值
        lock: false, // 发送消息锁 true - 加锁状态 false - 解锁状态
        scroll_height: wx.getSystemInfoSync().windowHeight - 54,
        reply_height: 0,
        moreShow: true,
        userData: [],
        
        audioPng:"../image/audio-play.png",
        audioGif:"../image/audio-play.gif",
        audioState:true,
        /**
         * 历史消息消息集合(结构如下):
         * nextReqMessageID 用于续拉,分页续拉时需传入该字段。
         * isCompleted 表示是否已经拉完所有消息。
         */
        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;
        // 获取当前聊天的历史列表
        that.getMessageList();
        that.scrollToBottom();
        // 获取收到的单聊信息
        let onMessageReceived = function (event) {
          // event.data - 存储 Message 对象的数组 - [Message]
          let msgList = that.data.messages
          handlerHistoryMsgs(event.data, that)
          that.scrollToBottom();
        };
        tim.on(TIM.EVENT.MESSAGE_RECEIVED, onMessageReceived)
        // 监听录音结束
        recorderManager.onStop(function (res) {
          if (that.data.recording) {
            if (that.data.cancelRecord) {
              wx.hideToast()
              that.setData({
                cancelRecord: false
              })
            } else {
              // 创建消息实例,接口返回的实例可以上屏
              const message = tim.createAudioMessage({
                to: that.data.friendId,
                conversationType: TIM.TYPES.CONV_C2C,
                payload: {
                  file: res
                },
                onProgress: function (event) { }
              });
              //  发送消息
              let promise = tim.sendMessage(message);
              promise.then(function (imResponse) {
                // 发送成功
                that.addMessage(imResponse.data.message, that)
              }).catch(function (imError) {
                // 发送失败
              });
              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,//会话列表传递过来的参数
          count: 15
        })
        cb.then(function (imResponse) {
          const messageList = imResponse.data.messageList; // 消息列表。
          const nextReqMessageID = imResponse.data.nextReqMessageID; // 用于续拉,分页续拉时需传入该字段。
          const isCompleted = imResponse.data.isCompleted; // 表示是否已经拉完所有消息。
          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
        })
      },
      /**
       * 发送消息
       */
      sendMsg: function (e) {
        if(this.data.content ==""){
          wx.showToast({
            title: '请输入内容',
            duration: 1000,
            icon:'none'
          })
          return
        }
        var that = this
        // 发送文本消息,Web 端与小程序端相同
        // 1. 创建消息实例,接口返回的实例可以上屏
        let message = tim.createTextMessage({
          to: this.data.friendId,
          conversationType: TIM.TYPES.CONV_C2C,
          payload: {
            text: this.data.content
          }
        });
        // 2. 发送消息
        let promise = tim.sendMessage(message);
        promise.then(function (imResponse) {
          // 发送成功
          that.addMessage(imResponse.data.message, that)
          that.setData({sendBtn:true})
        }).catch(function (imError) {
          // 发送失败
        });
      },
      /**
       * 刷新文本消息
       */
      addMessage: function (msg, that) {
        var messages = that.data.messages;
        messages.push(msg);
        that.setData({
          messages: messages,
          content: '' // 清空输入框文本
        })
        that.scrollToBottom();
      },
      /**
       * 发送图片消息
       */
      sendImg() {
        let that = this;
        wx.chooseImage({
          sourceType: ['album'], // 从相册选择
          count: 1, // 只选一张,目前 SDK 不支持一次发送多张图片
          success: function (res) {
            // 2. 创建消息实例,接口返回的实例可以上屏
            let message = tim.createImageMessage({
              to: that.data.friendId,
              conversationType: TIM.TYPES.CONV_C2C,
              payload: {
                file: res
              },
              onProgress: function (event) {
              }
            });
            // 3. 发送图片
            let promise = tim.sendMessage(message);
            promise.then(function (imResponse) {
              // 发送成功
              that.addMessage(imResponse.data.message, that)
            }).catch(function (imError) {
              // 发送失败
            });
          }
        })
      },
      scrollToBottom: function () {
        this.setData({
          toView: 'row_' + (this.data.messages.length - 1)
        });
      },
      previewImage(e) {
        let src = '';
        wx.previewImage({
          current: e.currentTarget.dataset.src, // 当前显示图片的http链接
          urls: [e.currentTarget.dataset.src]
        })
      },
      // 录制语音
      startAudio: function () {
        wx.showToast({
          title: '上滑取消发送',
          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
        })
      },
      // 发送录音
      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("语音结束了")
        })
        this.data.audioContext.onError((res) => {
        })
      },
      // 上滑取消
      onTouchMove(e) {
        if (e.touches[0].clientY < 520) {
          // # 取消发送
          this.setData({
            cancelRecord: true
          });
          wx.showToast({
            title: '松开,取消发送',
            duration: 10000,
            image: '../image/cancel.png'
          })
        } else {
          // # 不取消
          wx.hideToast()
          wx.showToast({
            title: '上滑取消发送',
            duration: 10000,
            image: '../image/cancel.png'
          })
          this.setData({
            cancelRecord: false
          })
        }
      },
      // 下拉加载聊天记录
      refresh: function (e) {
        let that = this
        if (that.data.ScrollLoading == 1) { //防止多次触发
          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; // 用于续拉,分页续拉时需传入该字段。
              const isCompleted = imResponse.data.isCompleted; // 表示是否已经拉完所有消息。
              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为回复框高度,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;
    }
    /*回复框*/
    .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;
    }
    /*回复文本框*/
    .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;
    }
    /*图标*/
    .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;
    }

    推荐教程:《小程序开发

    以上就是小程序怎么导入sdk实现聊天功能的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:小程序 sdk 聊天
    上一篇:浅谈小程序中的生命周期 下一篇:微信小程序如何开发一款小游戏?(实战教程)
    千万级数据并发解决方案

    相关文章推荐

    • 小程序如何实现分页加载数据功能?• 如何开发小程序插件?• 小程序如何接入和维护微信登录态?• 小程序的21个新功能• 浅谈小程序中的生命周期
    1/1

    PHP中文网