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

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行声明变量的后边

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

 

 代码:

//新增代码***********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

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

 

 代码:

//新增代码***********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换上去)

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

 

 

 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.聊天中的表情编码对应文件

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

 

 emoji.js

vue(版本2.xx) + 环信web sdk(版本1.8.3)
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(暂时未用到)

vue(版本2.xx) + 环信web sdk(版本1.8.3)
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文件夹下,图片大致都差不多,网上应该可以查到

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

 

 

8.表情组件

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

 

 

<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.页面中使用

 

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

 

 

vue(版本2.xx) + 环信web sdk(版本1.8.3)
<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)
      //       }
      //     })
      //   },

      //发送文本消息
        sendPrivateText(){

          if(this.message == ‘‘){
            this.$message.error(‘不能发送空白信息‘);
            return false;
          }
          if(this.username_to == ‘‘){
            this.$message.error(‘请选择发送的好友‘);
            return false;
          }
          var id = this.$imconn.getUniqueId();// 生成本地消息id
          var msg = new WebIM.message(‘txt‘,id);
          var sendTime = this.getNowTime();
          var username_from = this.username_from;
          var message = this.message;
          var _this = this;
          msg.set({
            msg: message,                  // 消息内容
            to: _this.username_to,                          // 接收消息对象(用户id)
            roomType: false,
            success: function (id, serverMsgId) {
              _this.historyMessage.push({
                from: username_from,
                message: message,
                time:sendTime,
                type:‘txt‘
              })
              window.localStorage.setItem(_this.username_to,JSON.stringify(_this.historyMessage));
              var lusername = window.localStorage.getItem(_this.username_to);
              lusername = JSON.parse(lusername);
              _this.message = ‘‘;
              _this.setScroll();
            },
            fail: function(e){
              // console.log("Send private text error");
            }
          });
          this.$imconn.send(msg.body);
        },

        // 发送图片消息
        sendPrivateUrlImg(context, payload) {
          let _this = this;
          if(_this.username_to == ‘‘){
            _this.$message.error(‘请选择发送的好友‘);
            return false;
          }
          let file =  WebIM.utils.getFileUrl(_this.$refs.sendImg); // 将图片转化为二进制文件
          var id = this.$imconn.getUniqueId();                   // 生成本地消息id
          var msg = new WebIM.message(‘img‘, id);        // 创建图片消息
          // console.log(‘图片消息‘,msg);
          msg.set({
            apiUrl: WebIM.config.apiURL,
            file: file,
            to: this.username_to,// 接收消息对象
            roomType: false,
            chatType: ‘singleChat‘,
            timestamp:new Date().getTime(),
            onFileUploadError: function(error){
              // console.log("图片上传失败", error);
            },
            onFileUploadComplete: function(file){
              //更新发送的图片到缓存中
              _this.historyMessage.push({
                from: _this.username_from,
                message: `${file.uri}/${file.entities[0].uuid}`,
                time:_this.getNowTime(),
                type:‘img‘
              })
              window.localStorage.setItem(_this.username_to,JSON.stringify(_this.historyMessage));
              var lusername = window.localStorage.getItem(_this.username_to);
              lusername = JSON.parse(lusername);
              this.setScroll();
            },
            success: function(){
              // console.log("图片发送成功");

            }
          });

          this.$imconn.send(msg.body);
        },


        //  选择表情
        selectEmoji (code) {
          this.showEmoji = false
          this.message = code;
          this.$refs.txtDom.focus();
        },


        //返回表情
        customEmoji(value) {
          return `<img src="http://39.100.159.29/faces/${value}" style="width:20px"/>`;
          // return ‘<img src="http://localhost:9527/static/img/logo.063d13ac.png"/>‘ 本地图片访问不到,原因未知
        },

        //解析接收的消息
        renderTxt(txt = "") {
          let rnTxt = [];
          let match = null;
          const regex = /(\[.*?\])/g;
          let start = 0;
          let index = 0;
          while ((match = regex.exec(txt))) {
            index = match.index;
            if (index > start) {
              rnTxt.push(txt.substring(start, index));
            }
            if (match[1] in emoji.obj) {
              const v = emoji.obj[match[1]];
              rnTxt.push(this.customEmoji(v));
            } else {
              rnTxt.push(match[1]);
            }
            start = index + match[1].length;
          }
          rnTxt.push(txt.substring(start, txt.length));
          return rnTxt.toString().replace(/,/g, "");
        },


        //  获取发送和接收消息的时间
        getNowTime(){
          let now = new Date();
          return now.getFullYear() + ‘-‘ + now.getMonth()+1 + ‘-‘ + now.getDate() + ‘ ‘ + (now.getHours()<10 ? ‘0‘ + now.getHours() : now.getHours()) + ‘:‘ + (now.getMinutes()<10 ? ‘0‘ + now.getMinutes() : now.getMinutes()) + ‘:‘ + (now.getSeconds()<10 ? ‘0‘ + now.getSeconds() : now.getSeconds());
        },

      //  选择好友发送消息
        selectFriend(item,index){
          if(index != undefined){this.currentIndex = index};
          var chatList = JSON.parse(window.localStorage.getItem(‘chatList‘));
          this.username_to = item;
          //获取当前聊天对象历史记录
          var historyMessage = window.localStorage.getItem(item);
          historyMessage = historyMessage ? JSON.parse(historyMessage) : [];
          var emojiArr = [];
          for(var i=0;i<historyMessage.length;i++){
            var item = historyMessage[i].message;
            if(typeof(item) === ‘object‘){
              if(item[0].type == ‘emoji‘){
                var emojiItem = {};
                var url = item[0].data;
                item.data = url;
              }
            }
          }
          this.historyMessage = historyMessage;

          //清除消息提示
          console.log(‘chatList‘,window.localStorage.getItem(‘chatList‘));

          for(var i=0;i<chatList.length;i++){
            console.log(‘username‘,this.username_to)
            if(this.username_to == chatList[i].userPhone){
              chatList[i].active = false;
            }
          }

          window.localStorage.setItem(‘chatList‘,JSON.stringify(chatList));
          this.chatList = chatList;

          this.setScroll();
        },

      //  更新聊天历史记录缓存数据
        updateStorage(message){
          let sendTimeWZ = message.time ? new Date(message.time) : new Date();
          let sendTime = sendTimeWZ.getFullYear() + ‘-‘ + sendTimeWZ.getMonth()+1 + ‘-‘ + sendTimeWZ.getDate() + ‘ ‘ + (sendTimeWZ.getHours()<10 ? ‘0‘ + sendTimeWZ.getHours() : sendTimeWZ.getHours()) + ‘:‘ + (sendTimeWZ.getMinutes()<10 ? ‘0‘ + sendTimeWZ.getMinutes() : sendTimeWZ.getMinutes()) + ‘:‘ + (sendTimeWZ.getSeconds()<10 ? ‘0‘ + sendTimeWZ.getSeconds() : sendTimeWZ.getSeconds());

          //判断接收的消息是什么类型
          let type = ‘‘;
          if(message.url){
            type = ‘img‘;
          }else{
            type = ‘txt‘;
          }
          //定义新接收到的信息
          let message_new = {
            from: message.from,
            message: message.url ? message.url :message.data,
            time: sendTime,
            type: type
          }

          var historyMessage = window.localStorage.getItem(message.from);
          historyMessage = historyMessage ? JSON.parse(historyMessage) : [];
          historyMessage.push(message_new);
          window.localStorage.removeItem(message.from);
          window.localStorage.setItem(message.from,JSON.stringify(historyMessage));

          this.setScroll();

        },

      //  判断数组对象中是否有某个属性值
        findElem(chatList,userPhone,formId){
          for(var i=0;i<chatList.length;i++){
            if(chatList[i].userPhone == formId){
              return i
            }
          }
          return -1;
        },
        //获取可视区域高度
        getClientHeight(){
          var clientHeight=0;
          if(document.body.clientHeight&&document.documentElement.clientHeight)
          {
            var clientHeight = (document.body.clientHeight<document.documentElement.clientHeight)?document.body.clientHeight:document.documentElement.clientHeight;
          }
          else
          {
            var clientHeight = (document.body.clientHeight>document.documentElement.clientHeight)?document.body.clientHeight:document.documentElement.clientHeight;
          }
          return clientHeight;
        },


  //  更新临时聊天用户列表
        updateChatList(message){
          var chatList_str = window.localStorage.getItem(‘chatList‘);
          var chatList = chatList_str ? JSON.parse(chatList_str) : [];

          if(message){
            //用户信息之前不存在
            if(this.findElem(chatList,‘userPhone‘,message.from) == (-1)){
              var chatUser_new = {
                userName: message.ext.userName,
                userPic: message.ext.userPic,
                userPhone: message.from,
                active: false
              }
              chatList.push(chatUser_new);
            }
        //  新消息提示
            for(var i=0;i<chatList.length;i++){
              if(message.from == chatList[i].userPhone){
                chatList[i].active = true;
              }
            }
          }

          window.localStorage.setItem(‘chatList‘,JSON.stringify(chatList));
          this.chatList = chatList;
        },

        //  设置默认滚动到页面最底部
        setScroll(){
          let msg = document.getElementById(‘historyList‘) // 获取对象
          if(msg){
            this.$nextTick(() => {
              msg.scrollTop = msg.scrollHeight // 滚动高度
            })
          }
        }



      }
    }
</script>

<style scoped lang="scss">
  .headerTitle{
    color: #757373;
    width: 100%;
    height: 50px;
    line-height: 50px;
    padding-left: 10px;
    border-bottom: 1px solid #ddd;
    position: fixed;
    top: 50px;
    left: 210px;
    z-index: 100;
    background-color: #f9fafa;
  }
  #app .hideSidebar  {
    .headerTitle {
      left: 54px;
    }
  }
  #app .mobile.hideSidebar {
    .headerTitle {
      left: 0;
    }
  }
  .chatBox {
    display: flex;
    justify-content: flex-start;
    align-items: flex-start;
  }

  .chatList {
    width: 20%;
    height: 100%;
    border-right: 1px solid #ddd;
    display: inline-block;
    font-size: 14px;
    padding-top: 50px;
    .chatList_title {
      width: 100%;
      height: 40px;
      line-height: 40px;
      padding: 0 20px;
      font-weight: 600;
      border-bottom: 1px solid #ddd;
      background-color: #f9fafa;
    }
    .chatList_item {
      width: 100%;
      height: 60px;
      padding: 0 20px;
      border-bottom: 1px solid #ddd;
      display: flex;
      justify-content: flex-start;
      align-items: center;
      cursor: pointer;
      position: relative;
      span {
        width: 10px;
        height: 10px;
        border-radius: 50%;
        background-color: red;
        position: absolute;
        right: 14px;
        top: 10px;
      }
      &.active {
        background-color: #0178EF;
        color: #fff;
      }
      img {
        width: 40px;
        height: 40px;
        border-radius: 50%;
        margin-right: 10px;
      }
    }
  }
  .content {
    width: 80%;
    display: inline-block;
    padding: 44px 0 20px;
    .historyList {
      width: 100%;
      height: 80%;
      padding: 20px 20px 0;
      overflow-y: scroll;
      .item_time {
        text-align: center;
        margin: 10px 0;
      }
      .item_message {
        text-align: left;
        margin-bottom: 20px;
        &.currentUser {
          text-align: right;
          p {
            display: inline-block;
            background-color: #00b7ee;
            border: 1px solid #00b7ee;
            color: #fff;
          }
        }
        p {
          display: inline-block;
          border: 1px solid #ddd;
          border-radius: 4px;
          padding: 4px 8px;
        }
      }
    }
  }



  /*表情聊天对话框*/
  .chatInput {
    border-top: 1px solid #ddd;
    /deep/ .el-textarea__inner:hover {
      border: none;
    }
    /deep/ .el-textarea__inner {
      border: none;
    }
    /deep/ .icon {
      cursor: pointer;
    }
    /*发送图片*/
    .upImgBox {
      display: inline-block;
      position: relative;
      width: 16px;
      height: 17px;
      margin: 0 4px;
      cursor: pointer;
      /deep/ .iconfont {
        position: absolute;
        left: 0;
        top: 0;
        cursor: pointer;
      }
      .sendImg {
        position: absolute;
        left: 0;
        top: 0;
        width: 16px;
        height: 17px;
        opacity: 0;
      }
    }

  }

</style>
使用环信的页面代码

 

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

上一篇:(四)Kubernetes 资源清单定义


下一篇:(六)Kubernetes Pod控制器-ReplicaSet和Deployment和DaemonSet