vue(版本2.xx) + 环信web sdk(版本1.8.3)

Posted 小白&小菜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue(版本2.xx) + 环信web sdk(版本1.8.3)相关的知识,希望对你有一定的参考价值。

实现方案:

环信没有临时聊天人员历史记录接口,所以实现的方案是:

1.监听消息接收;2.将受到的消息存到缓存中,同时判断此用户是否之前聊天过,如果没聊过的话,把他的用户信息也存到缓存中;3.展示的东西都是从缓存中获取;4.新消息提醒是在监听到消息后,给用户信息里设置一个状态值,当点击刚用户查看历史记录时,再改变这个状态值

实现效果:

 

 

1.准备工作

npm引入sdk及 strophe.js坑:刚开始下载的最新版的sdk,但是下载下来总是少文件src,挣扎半天,换了1.8.3版本的sdk好了,可能跟我项目的哪些东西的版本有不兼容的吧

(1)cnpm i easemob-websdk@1.8.3 --save

(2)cnpm i strophe.js@1.2.16 --save

(3)下载webim.config.js:   https://gitee.com/weimingye/web-im/blob/master/demo/javascript/dist/webim.config.js#

2.修改sdk的connection.js文件(注意新增代码的位置,放在11行声明变量的后边

 

 代码:

//新增代码***********start
var Strophe = require(\'../../strophe.js/dist/strophe.js\').Strophe;
var meStrophe = require(\'../../strophe.js/dist/strophe.js\');
$iq = meStrophe.$iq;
$build = meStrophe.$build;
$msg = meStrophe.$msg;
$pres = meStrophe.$pres;
//新增代码***********end

3.修改strophe.js

 

 代码:

//新增代码***********start
  setJid: function (jid) {
    this.jid = jid;
    this.authzid = Strophe.getBareJidFromJid(this.jid);
    this.authcid = Strophe.getNodeFromJid(this.jid);
  },

  getJid: function () {
    return this.jid;
  },
  //新增代码***********end

4.修改webim.config.js(首行、最后一行,把自己公司的appkey换上去)

 

 

 5.main.js新增配置

//环信start
require(\'./assets/webim.config.js\')
let WebIM = require(\'easemob-websdk\')
Vue.prototype.$webim = WebIM

const conn = new WebIM.connection({
  isMultiLoginSessions: WebIM.config.isMultiLoginSessions,
  https: typeof WebIM.config.https === \'boolean\' ? WebIM.config.https : location.protocol === \'https:\',
  url: WebIM.config.xmppURL,
  heartBeatWait: WebIM.config.heartBeatWait,
  autoReconnectNumMax: WebIM.config.autoReconnectNumMax,
  autoReconnectInterval: WebIM.config.autoReconnectInterval,
  apiUrl: WebIM.config.apiURL,
  isAutoLogin: true
})

const options = {
  apiUrl: WebIM.config.apiURL,
  user: \'\',//用户名
  pwd: \'\',//密码
  appKey: WebIM.config.appkey,
  success:function (res) {
    console.log(\'链接服务器正常\')
  },
  error:function (err) {
    alert(err)
  }
}
Vue.prototype.$imconn = conn
Vue.prototype.$imoption = options
//环信end

 

6.聊天中的表情编码对应文件

 

 emoji.js

module.exports = {
    path: "../../static/faces",
    obj: {
        "[):]": "ee_1.png",
        "[:D]": "ee_2.png",
        "[;)]": "ee_3.png",
        "[:-o]": "ee_4.png",
        "[:p]": "ee_5.png",
        "[(H)]": "ee_6.png",
        "[:@]": "ee_7.png",
        "[:s]": "ee_8.png",
        "[:$]": "ee_9.png",
        "[:(]": "ee_10.png",
        "[:\'(]": "ee_11.png",
        "[:|]": "ee_18.png",
        "[(a)]": "ee_13.png",
        "[8o|]": "ee_14.png",
        "[8-|]": "ee_15.png",
        "[+o(]": "ee_16.png",
        "[<o)]": "ee_12.png",
        "[|-)]": "ee_17.png",
        "[*-)]": "ee_19.png",
        "[:-#]": "ee_20.png",
        "[:-*]": "ee_22.png",
        "[^o)]": "ee_21.png",
        "[8-)]": "ee_23.png",
        "[(|)]": "ee_24.png",
        "[(u)]": "ee_25.png",
        "[(S)]": "ee_26.png",
        "[(*)]": "ee_27.png",
        "[(#)]": "ee_28.png",
        "[(R)]": "ee_29.png",
        "[({)]": "ee_30.png",
        "[(})]": "ee_31.png",
        "[(k)]": "ee_32.png",
        "[(F)]": "ee_33.png",
        "[(W)]": "ee_34.png",
        "[(D)]": "ee_35.png"
    }
};
emoji.js

index.js(暂时未用到)

const _WIDTH = window.screen.availWidth > 350 ? 350 : window.screen.availWidth;
export default {
    // whether auto check media query and dispatch by redux or not ?
    reduxMatchMedia: true,
    // map of media query breakpoints
    dimensionMap: {
        xs: "480px",
        sm: "768px",
        md: "992px",
        lg: "1200px",
        xl: "1600px"
    },
    name: "Web IM",
    logo: "",
    SIDER_COL_BREAK: "sm", // md
    SIDER_COL_WIDTH: 80,
    SIDER_WIDTH: 350,
    RIGHT_SIDER_WIDTH: _WIDTH,
    // imgType: {
    //     gif: 1,
    //     bmp: 1,
    //     jpg: 1,
    //     png: 1,
        
    // },
    PAGE_NUM: 20
};
index.js

 

7.图片文件存放在static文件夹下,图片大致都差不多,网上应该可以查到

 

 

8.表情组件

 

 

<template>
  <span>
    <el-popover ref="popover5" placement="top-start" width="360" v-model="showModal">
      <img
        v-for="(v,i) in emojiList"
        :src="require(`../../../static/faces/${v}`)"
        :key="i"
        @click="selectEmoji(i)"
        class="img-style"
      />
    </el-popover>
    <i class="icon iconfont icon-face" @click="showModal = !showModal"></i>

  </span>
</template>

<script>
import emoji from "../../config/emoji";

export default {
  data() {
    return {
      emojiList: emoji.obj,
      currentEmoji: "",
      showModal: false
    };
  },
  methods: {
    selectEmoji(e) {
      let value = (this.inpMessage || "") + e;
      this.$data.showModal = false;
      this.$emit("selectEmoji", value);
    }
  },
  props: {
    inpMessage: String
  }
};
</script>
<style scoped>
  /deep/ .el-popover.el-popper {
    width: 360px;
    position: absolute;
    bottom: 20%;
    left: 260px;
    transform-origin: center bottom;
    z-index: 2001;
  }
.img-style {
  width: 22px;
  margin: 5px;
  cursor: pointer;
}
.img-style:hover {
  background-color: aquamarine;
}
</style>

 

8.页面中使用

 

 

<template>
    <div>
      <div class="headerTitle">{{title}}</div>
      <div class="chatBox">
<!--        临时聊天用户列表-->
        <div class="chatList" ref="chatList">
          <div class="chatList_title">近期联系人</div>
          <div>
            <div v-if="chatList && chatList.length>0" v-for="(item,index) in chatList" :key="index" class="chatList_item" :class="{\'active\':index == currentIndex}" @click="selectFriend(item.userPhone,index)">
              <img :src="item.userPic" :onerror="defaultImgs" style="min-width: 40px;"/>
              <div>{{item.userPhone}} {{item.userName}}</div>
              <span v-if="item.active"></span>
            </div>
          </div>
        </div>
<!--        聊天内容-->
        <div class="content" ref="chatContent">
<!--          聊天历史记录-->
          <div class="historyList" id="historyList">
            <div v-for="(item,index) in historyMessage" :key="index">
              <div class="item_time">{{item.time}}</div>
              <div class="item_message" :class="{\'currentUser\':item.from == username_from}">
<!--                展示图片-->
                <img v-if="item.type == \'img\'" :src="item.message" style="max-width: 30%"/>
<!--解析文本或表情-->
                <p
                  v-if="item.type ==\'txt\'"
                  style="user-select: text"
                  v-html="renderTxt(item.message)"
                />
              </div>

            </div>
          </div>

<!--发送聊天-->

          <div class="chatInput">

            <div style="padding: 4px 10px;">
              <!-- 表情组件 -->
              <ChatEmoji v-on:selectEmoji="selectEmoji" :inpMessage="message" />
              <!-- 上传图片 -->
              <div class="upImgBox">
                <i class="icon iconfont icon-tupian"></i>
                <input type="file" class="sendImg" ref="sendImg" @change="sendPrivateUrlImg">
              </div>

            </div>


<!--            输入框-->
            <el-input
              ref="txtDom"
              type="textarea"
              :autosize="{ minRows: 4, maxRows: 8}"
              placeholder="请输入内容"
              resize="none"
              v-model="message"
              @keyup.enter.native="sendPrivateText">
            </el-input>
            <el-button type="primary" size="small" @click="sendPrivateText" style="float: right;margin-right: 20px;">提交</el-button>

          </div>
        </div>
      </div>


    </div>
</template>

<script>
  import ChatEmoji from "../../components/chatEmoji/index.vue";//表情组件
  import emoji from "../../config/emoji";

    export default {
      name: "index",
      components: {
        ChatEmoji
      },
      data(){
          return {
            title: \'互动消息\',
            type: \'contact\',
            currentUserpwd: \'123456\',
            username_from: \'15263819410\',//当前登录的用户(发送人手机号)
            username_to: \'\',//当前聊天的用户名(接收人手机号)
            message:\'\',//当前发送的信息
            historyMessage: [],//聊天历史记录
            showEmoji: false,//是否展示表情组件
            chatList:[],//临时聊天用户列表
            currentIndex: undefined,//左侧当前激活index
            defaultImgs: \'this.src = "\' + require(\'../../assets/img/userLogo.png\') + \'"\',
          }
      },
      created() {
          this.login();
          this.updateChatList();//获取临时聊天用户列表
      },
      mounted(){
          this.$refs.chatContent.style.height = this.getClientHeight() - 50 + \'px\';
          this.$refs.chatList.style.height = this.getClientHeight() - 50 + \'px\';
      },
      methods: {
        //登录环信账户
        login(){
          var _this = this;
          this.$imoption.user = this.username_from;
          this.$imoption.pwd = this.currentUserpwd;
          this.$imoption.success = (res)=>{
            // console.log(\'登录成功回调\',res);

          }
          this.$imconn.open(this.$imoption);
          this.$imconn.listen({
            onOpened: function (message) {
              // console.log(\'用户已上线\');
            },
            onClosed: function (message) {
              this.$message.info(\'用户已下线\')
            },
            //收到表情消息
            onEmojiMessage: function (message) {

              // //把聊天对象名message.from存储到storage中
              _this.updateChatList(message);
              //把新接收的信息更新存储到storage中
              _this.updateStorage(message);
              //_this.selectFriend(message.from);
            },

            //收到图片消息
            onPictureMessage: (message) => {
              //把聊天对象名message.from存储到storage中
              _this.updateChatList(message);
              //把新接收的信息更新存储到storage中
              _this.updateStorage(message);
              //_this.selectFriend(message.from);

            },
            //收到文本消息
            onTextMessage: function (message) {
              //把聊天对象名message.from存储到storage中
              _this.updateChatList(message);
              //把新接收的信息更新存储到storage中
              _this.updateStorage(message);
            //  更新历史记录到页面
             // _this.selectFriend(message.from);

            },
            //收到音频消息
            onAudioMessage: function ( message ) {
              var options = { url: message.url };

              options.onFileDownloadComplete = function ( response ) {
                //音频下载成功,需要将response转换成blob,使用objectURL作为audio标签的src即可播放。
                var objectURL = WebIM.utils.parseDownloadResponse.call(Demo.conn, response);
                // console.log(\'音频\',objectURL)
              };

              options.onFileDownloadError = function () {
                //音频下载失败
              };

              //通知服务器将音频转为mp3
              options.headers = {
                \'Accept\': \'audio/mp3\'
              };

              WebIM.utils.download.call(conn, options);
            },
            //收到视频消息
            onVideoMessage: function (message) {
              var node = document.getElementById(\'privateVideo\');
              var option = {
                url: message.url,
                headers: {
                  \'Accept\': \'audio/mp4\'
                },
                onFileDownloadComplete: function (response) {
                  var objectURL = WebIM.utils.parseDownloadResponse.call(conn, response);
                  // console.log(\'视频消息\',objectURL);
                  node.src = objectURL;
                },
                onFileDownloadError: function () {
                  // console.log(\'File down load error.\')
                }
              };
              WebIM.utils.download.call(conn, option);
            },
          })

        },


      //  获取好友列表(项目没用到)
      //   getFriends(){
      //     var newarry = [];
      //     this.friends = newarry;
      //     this.$imconn.getRoster({
      //       success: function (roster) {
      //         console.log(\'获取好友列表1\',roster)
      //         roster.forEach((item,index)=>{
      //           if(item.subscription === \'both\' || item.subscription === \'to\'){
      //             newarry.push(item);
      //             console.log(\'好友列表\',newarry, item.name);
      //           }
      //         });
      //       },
      //       error: function (error) {
      //         console.log(\'error\',error)
      //       }
      //     })
      //   },

      //发送文本消息
环信 flutter sdk集成IM离线推送及点击推送获取推送信息(iOS版)

环信 flutter sdk集成IM离线推送及点击推送获取推送信息(iOS版)

vue脚手架(vue-cli)老版本(2.xx版)的使用

RTC月度小报5月 |教育aPaaS灵动课堂升级抢先体验VUE版 Agora Web SDK声网Agora与HTC达成合作

Vue3+TypeScript 如何以 Plugins 形式引入环信 WebSDK?

vue h5页面 使用第三方聊天(环信集成web端)