IM环信聊天

安装

yarn add easemob-websdk

在utils文件中写一个WebIMConfig.js (appkey换成自己的)

/**
 * git do not control webim.config.js
 * everyone should copy webim.config.js.demo to webim.config.js
 * and have their own configs.
 * In this way , others won't be influenced by this config while git pull.
 */

// for react native
// var location = {
//     protocol: 'https'
// }

var config = {
  /*
     * websocket server
     * im-api-v2.easemob.com/ws 线上环境
     * im-api-v2-hsb.easemob.com/ws 沙箱环境
     */
  socketServer: (window.location.protocol === 'https:' ? 'https:' : 'http:') + '//im-api-v2-hsb.easemob.com/ws',
  /*
     * Backend REST API URL
     * a1.easemob.com 线上环境
     * a1-hsb.easemob.com 沙箱环境
     */
  restServer: (window.location.protocol === 'https:' ? 'https:' : 'http:') + '//a1-hsb.easemob.com',
  /*
     * Application AppKey
     */
  appkey: '1100210506200509#single-structure',
  /*
     * Application Host
     */
  Host: 'easemob.com',
  /*
     * Whether to use HTTPS
     * @parameter {Boolean} true or false
     */
  https: true,

  /*
    * 公有云配置默认为 true,
    * 私有云配置请设置 isHttpDNS = false , 详细文档:http://docs-im.easemob.com/im/web/other/privatedeploy
    */
  isHttpDNS: true,
  /*
     * isMultiLoginSessions
     * true: A visitor can sign in to multiple webpages and receive messages at all the webpages.
     * false: A visitor can sign in to only one webpage and receive messages at the webpage.
     */
  isMultiLoginSessions: true,
  /**
     * isSandBox=true:  socketURL: 'im-api.sandbox.easemob.com',  apiURL: '//a1.sdb.easemob.com',
     * isSandBox=false: socketURL: 'im-api.easemob.com',          apiURL: '//a1.easemob.com',
     * @parameter {Boolean} true or false
     */
  isSandBox: false, // 内部测试环境,集成时设为false
  /**
     * Whether to console.log
     * @parameter {Boolean} true or false
     */
  isDebug: true,
  /**
     * will auto connect the websocket server autoReconnectNumMax times in background when client is offline.
     * won't auto connect if autoReconnectNumMax=0.
     */
  autoReconnectNumMax: 10,
  /**
     * webrtc supports WebKit and https only
     */
  isWebRTC: window.RTCPeerConnection && /^https\\:$/.test(window.location.protocol),
  /*
     * Upload pictures or file to your own server and send message with url
     * @parameter {Boolean} true or false
     * true: Using the API provided by SDK to upload file to huanxin server
     * false: Using your method to upload file to your own server
     */
  useOwnUploadFun: false,
  /**
     *  cn: chinese
     *  us: english
     */
  i18n: 'cn',
  /*
     * Set to auto sign-in
     */
  isAutoLogin: false,
  /**
     * Size of message cache for person to person
     */
  p2pMessageCacheSize: 500,
  /**
     * When a message arrived, the receiver send an ack message to the
     * sender, in order to tell the sender the message has delivered.
     * See call back function onReceivedMessage
     */
  delivery: true,
  /**
     * Size of message cache for group chating like group, chatroom etc. For use in this demo
     */
  groupMessageCacheSize: 200,
  /**
     * 5 actual logging methods, ordered and available:
     * 'TRACE', 'DEBUG', 'INFO', 'WARN', 'ERROR'
     */
  loglevel: 'ERROR',

  /**
     * enable localstorage for history messages. For use in this demo
     */
  enableLocalStorage: true,

  deviceId: 'webim',

  AgoraAppId: '' // 需要替换成自己的声网 appId,此 appId 有限量,仅供参考使用,同时获取声网 token 的接口仅能供此 appId 使用,换成自己的 appId 后需要自己去实现 app server 获取声网token。
}
export default config

在utils文件中写一个WebIM.js

/* eslint-disable */
//import 'script-loader!easemob-websdk/dist/strophe-1.2.8.js'
/* eslint-enable */

// add dataReport sdk
// import websdk from './Easemob-chat-3.6.3'
// import websdk from './Easemob-chat-4.0.1'

import websdk from 'easemob-websdk'
// import webrtc from 'easemob-webrtc'
// import emedia from './EMedia_sdk-dev'
import config from './WebIMConfig'

const rtc = {
  // 用来放置本地客户端。
  client: null,
  // 用来放置本地音视频频轨道对象。
  localAudioTrack: null,
  localVideoTrack: null
}

// init DOMParser / document for strophe and sdk
const WebIM = (window.WebIM = {})
WebIM.config = config
WebIM.message = websdk.message
WebIM.statusCode = websdk.statusCode
WebIM.utils = websdk.utils
WebIM.logger = websdk.logger
const options = {
  isMultiLoginSessions: WebIM.config.isMultiLoginSessions,
  isDebug: WebIM.config.isDebug,
  https: WebIM.config.https,
  isAutoLogin: false,
  heartBeatWait: WebIM.config.heartBeatWait,
  autoReconnectNumMax: WebIM.config.autoReconnectNumMax,
  delivery: WebIM.config.delivery,
  appKey: WebIM.config.appkey,
  useOwnUploadFun: WebIM.config.useOwnUploadFun,
  deviceId: WebIM.config.deviceId,
  // 公有云 isHttpDNS 默认配置为true
  isHttpDNS: WebIM.config.isHttpDNS,
  onOffline: () => {
    console.log('onOffline')
  },
  onOnline: () => {
    console.log('onOnline')
  }
}
// eslint-disable-next-line new-cap
WebIM.conn = new websdk.connection(options)

// websdk.debug(true)

WebIM.rtc = rtc
export default WebIM

main.js

import WebIM from './utils/WebIM'
Vue.prototype.$webIM = WebIM

表情组件

<template>
  <div style="display: flex;justify-content: space-between">
    <el-popover v-model="showPopover" placement="top" title="" trigger="click">
      <div class="emoji-box">
        <img v-for="(v,i) in emojiList" :key="i" :src="require(`../../../assets/faces/${v}`)" class="img-style"
             @click="selectEmoji(i)"/>
      </div>
      <img slot="reference" :src="require('@/assets/happyemoji.png')" alt="" height="16" width="16">
    </el-popover>
    <div style="display: flex">
      <div style="cursor:pointer;color:#fff;border-radius: 4px;padding:5px 16px;background:#86C895;margin-right: 8px" @click="launchConsultation">发起专业问诊</div>
      <div style="cursor:pointer;color:#fff;border-radius: 4px;padding:5px 16px;background:#EA5D56;" @click="endConsultation">结束专业问诊</div>
    </div>
  </div>
</template>

<script>
import emoji from '@/utils/emoji'

export default {
  data () {
    return {
      emojiList: emoji.obj,
      showPopover: false
    }
  },
  methods: {
    selectEmoji (e) {
      const value = (this.inpMessage || '') + e
      this.showPopover = false
      this.$emit('selectEmoji', value)
    },
    launchConsultation () {
      this.$emit('launchConsultation')
    },
    endConsultation () {
      this.$emit('endConsultation')
    }
  },
  props: {
    inpMessage: String
  }
}
</script>
<style scoped>
.emoji-box {
  width: 360px;
}

.img-style {
  width: 22px;
  margin: 5px;
  cursor: pointer;
}

.img-style:hover {
  background-color: aquamarine;
}
</style>

@/utils/emoji (记得assest中准备好图片)

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',
    '[: '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'
  }
}

聊天.vue

<template>
  <div class="onlineService">
    <div style="height: 100%;">
      <div class="chat">
        <div class="chat_l">
          <div class="inConversation" @click="showChatList=!showChatList">
            <span style="font-size: 14px;">会话中</span>
            <i :style="{transform: showChatList? '':'rotate(180deg)'}" class="el-icon-arrow-up"></i>
          </div>
          <div style="max-height: 248px;overflow-y: auto">
            <el-collapse-transition>
              <div v-show="showChatList">
                <div v-for="(item, i) in chatList" :key="i"
                     :style="{cursor:'pointer', background: item.name===chatting.name?'#eff2f7': ''}"
                     class="chatList"
                     @click="chatWithHim(item)">
                  <img :src="require('@/assets/headPortrait.jpg')" alt="" height="40" width="40">
                  <div>
                    <div class="flex">
                      <div class="chatName">{{ item.name }}</div>
                      <div v-show="item.unread_num!==0" :class="['badge']"
                           :style="{padding: item.unread_num>10?'2px 6px':''}">
                        {{ item.unread_num }}
                      </div>
                    </div>
                    <div class="chatTime">{{ timestampConversion(item.time) }}</div>
                  </div>
                </div>
              </div>
            </el-collapse-transition>
          </div>
          <div class="newSession" @click="showNewChatList=!showNewChatList">
            <span style="font-size: 14px;">新会话</span>
            <i :style="{transform: showNewChatList? '':'rotate(180deg)'}" class="el-icon-arrow-up"></i>
          </div>
          <el-collapse-transition>
            <div v-show="showNewChatList" style="max-height: 248px;overflow-y: auto">
              <div v-for="(item, i) in newChatList" :key="i" class="chatList" style="cursor:pointer;"
                   @click="startConversation(item)">
                <img :src="VUE_APP_BASE_API + '/api/v1/Files/GetAttachments?fileName=' + item.headPortrait" alt=""
                     height="40" width="40">
                <div>
                  <div class="flex">
                    <div class="chatName">{{ item.name }}</div>
                    <div :class="['badge']" :style="{padding: item.unread_num>10?'2px 6px':''}">{{
                        item.unread_num
                      }}
                    </div>
                  </div>
                  <div style="display: flex;justify-content: space-between">
                    <div class="chatTime">{{ item.createDate }}</div>
                    <div
                      style="font-size:12px;cursor:pointer;color:#fff;border-radius: 15px;padding:2px 8px;background:#86C895;margin-right: 8px;display: inline-block"
                      @click="startSession(item)">
                      开始会话
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </el-collapse-transition>
        </div>
        <div class="chat_m">
          <div class="chat_m_top flex">
            <div class="name">{{ chatting.name }}</div>
            <div class="ending" @click="endConversation">结束交谈</div>
          </div>
          <div id="messgaeContent" class="chat_m_m">
            <div v-for="(item,i) in message" :key="i">
              <div v-if="!item.host">
                <div class="flex">
                  <i class="el-icon-user photo"></i>
                  <div class="phone">{{ item.name }}</div>
                  <div class="time">{{ timestampConversion(item.time) }}</div>
                </div>
                <div :key="timer" class="chatContent" v-html="renderTxt(item.chatContent)">
                </div>
              </div>
              <div v-else class="host">
                <div class="flex">
                  <div></div>
                  <div class="time">{{ timestampConversion(item.time) }}</div>
                </div>
                <div class="chatContent">
                  <div v-html="renderTxt(item.chatContent)"></div>
                  <div v-show="item.chatContent==='确认进行专业问诊?'"
                       style="color:#fff;border-radius: 4px;padding:5px 16px;background:#86C895;display: inline-block;margin-top: 14px">
                    待确认
                  </div>
                </div>
              </div>
              <!-- <img class="photo" :src="require('@/assets/user-ico.png')" alt="" width="30" height="30"> -->
            </div>
          </div>
          <div class="chat_m_bottom">
            <!-- 表情组件 -->
            <div class="emoji">
              <ChatEmoji :inpMessage="messageChat" @endConsultation="endConsultation"
                         @launchConsultation="launchConsultation"
                         @selectEmoji="selectEmoji"/>
            </div>
            <div style="padding: 20px">
              <el-input ref="txtDom" v-model="messageChat" rows="6" type="textarea"></el-input>
              <el-button type="success" @click="sendMessage('')">发送</el-button>
            </div>
          </div>
        </div>
        <div class="chat_r">
          <div class="chatTitle">用户信息</div>
          <div><span style="width: 80px;display: inline-block">账号</span>15234561897</div>
          <div><span style="width: 80px;display: inline-block">姓名</span>Barbara Hudson</div>
          <div><span style="width: 80px;display: inline-block">管理周期</span>健康减脂餐-冲刺7日餐</div>
          <div><span style="width: 80px;display: inline-block">专业问诊</span>7</div>
          <el-button type="text">查看详情</el-button>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import ChatEmoji from './chatEmoji/index.vue'
import emoji from '@/utils/emoji'
import dayjs from 'dayjs'
import api from '@/api/api'

export default {
  components: {
    ChatEmoji
  },
  watch: {
    $route (to, from) {
      console.log('route', to, from)
      if (to.path !== '/' && to.path !== '/login') {
        console.log('进入IM')
        var that = this
        if (!this.isOpened) {
          this.$webIM.conn.listen({
            // 连接成功回调
            onOpened: function () {
              console.log('登录成功')
              that.isOpened = true
            },
            // 连接关闭回调
            onClosed: function () {
              that.isOpened = false
            },
            // 收到文本消息
            onTextMessage: function (message) {
              console.log('收到文本消息:', message)
              that.receiveMessage(message)
            },
            // 当前用户收到透传消息。
            onCmdMessage: function (message) {
              console.log('当前用户收到透传消息: ', message)
            },
            // 收到图片消息
            onPictureMessage: function (message) {
              console.log(message)
              that.receiveMessage(message)
            },
            // 收到音频消息
            onAudioMessage: function (message) {
              console.log(message)
            },
            // 处理“广播”或“发布-订阅”消息,如联系人订阅请求、处理群组、聊天室被踢解散等消息
            onPresence: function (message) {
              switch (message.type) {
                case 'direct_joined':
                  break
              }
            }
          })
          const options = {
            user: 'zrymishu',
            pwd: '123456',
            appKey: this.$WebIM.config.appkey
          }
          this.$webIM.conn.open(options)
        }
      }
    }
  },
  data () {
    return {
      VUE_APP_BASE_API: process.env.VUE_APP_BASE_API,
      timer: Date.parse(new Date()),
      isMessage: false,
      showChatList: true,
      showNewChatList: true,
      selectCustomer: {},
      defaultselectedkeys: ['1'],
      desc: '',
      chatList: this.$store.state.chatList,
      newChatList: [],
      messageChat: '',
      isOpened: false,
      group: null,
      message: [
        // {
        //   phone: '15234561897',
        //   time: '今天 14:23',
        //   chatContent: '请问老人最近的身体情况怎么样?' + '',
        //   host: false
        // }, {
        //   phone: '15234561897',
        //   time: '今天 14:23',
        //   chatContent: '非常配合工作人员',
        //   host: true
        // }, {
        //   phone: '15234561897',
        //   time: '今天 14:23',
        //   chatContent: '请问老人最近的身体情况怎么样?',
        //   host: false
        // }, {
        //   phone: '15234561897',
        //   time: '今天 14:23',
        //   chatContent: '非常配合工作人员',
        //   host: true
        // }
      ],
      chatting: {
        name: ''
      },
      conversationalist: [] // 会话的所有人
    }
  },
  beforeMount () {
    const options = {
      user: 'zrymishu',
      pwd: '123456',
      appKey: this.$webIM.config.appkey
    }
    this.$webIM.conn.open(options)
    var that = this
    this.$webIM.conn.listen({
      // 连接成功回调
      onOpened: function (message) {
        console.log('登录成功', message)
        that.isOpened = true
        // todo 调接口
        that.$webIM.conn.getGroup().then(async (res) => {
          console.log(res, 'res')
        })
        // that.getConversation()
        // 获取好友列表
        // that.$webIM.conn.getContacts().then((res) => {
        //   console.log('获取好友列表', res) // res.data > ['user1', 'user2']
        // })
        that.$webIM.conn.getRoster().then((res) => {
          console.log('获取好友列表', res) // res.data > ['user1', 'user2']
        })
      },
      // 连接关闭回调
      onClosed: function () {
        that.isOpened = false
      },
      // 收到文本消息
      onTextMessage: function (message) {
        console.log(message)
        that.receiveMessage(message)
      },
      // 当前用户收到透传消息。
      onCmdMessage: function (message) {
        console.log('当前用户收到透传消息: ', message)
      },
      // 收到表情消息
      onEmojiMessage: function (message) {
        console.log('onEmojiMessage', message)
        const { type } = message
        type === 'chat' && this.ack(message)
      },
      // 收到图片消息
      onPictureMessage: function (message) {
        console.log(message)
        that.receiveMessage(message)
      },
      // 收到音频消息
      onAudioMessage: function (message) {
        console.log(message)
      },
      // 处理“广播”或“发布-订阅”消息,如联系人订阅请求、处理群组、聊天室被踢解散等消息
      onPresence: function (message) {
        switch (message.type) {
          case 'direct_joined':
            break
        }
      }
    })
  },
  mounted () {
    this.$nextTick(() => {
      // this.getConversation()
    })
    this.getUserSendLists()
  },
  methods: {
    async getUserSendLists () {
      const res = await api.getUserSendList()
      if (!res.state) return false
      this.newChatList = res.data
    },
    getConversation () {
      const that = this
      this.$webIM.conn.getConversationlist().then(res => {
        console.log('res.data.channel_infos', res.data.channel_infos)
        let newList = []
        console.log('chatList.length', that.chatList.length)
        if (!that.chatList.length) {
          res.data.channel_infos.map(item => {
            newList.push({
              ...item,
              chatting: false
            })
          })
          console.log('没有有正在谈话', newList)
          that.getConversationalist(newList)
          return false
        } else {
          // 比较两个数组对象的不同
          newList = res.data.channel_infos.filter(
            (x) => !that.chatList.some((i) => i.id === x.lastMessage.from)
          )
          console.log('有正在谈话', newList)
          that.getConversationalist(newList)
        }
      })
    },
    getConversationalist (data) {
      this.newChatList = []
      this.conversationalist = [] // 用户的数组
      console.log('datadatadatadatadata', data)
      data.map(ele => {
        if (!ele.chatting) {
          if (this.conversationalist.indexOf(ele.lastMessage.from) !== -1) { // 是否已存在此人
            const index = this.newChatList.findIndex(item => {
              return item.name === ele.lastMessage.from
            })
            this.newChatList[index].unread_num += 1
          } else {
            this.conversationalist.push(ele.lastMessage.from)
            this.newChatList.push({
              id: ele.lastMessage.from,
              name: ele.lastMessage.from,
              time: ele.lastMessage.time,
              unread_num: 1
            })
          }
        }
      })
      this.chatWithHim(this.chatList[0])
    },
    startTalk (value) {
      this.statistics = '1'
      const that = this
      that.isMessage = value.state
      if (that.isMessage) {
        that.group.forEach(item => {
          if (item.customerID === value.customerId) {
            that.selectCustomer = item
          }
        })
        that.defaultselectedkeys[0] = that.selectCustomer.name
        that.selectCustomer.unread = 0
        that.$nextTick(() => {
          var div = document.getElementById('messgaeContent')
          div.scrollTop = div.scrollHeight
        })
      } else {
        that.selectCustomer = {}
      }
    },
    sendMessage (data) {
      console.log('发给:', this.chatting.name)
      if (this.messageChat !== '' || data !== '') {
        var that = this
        var id = this.$webIM.conn.getUniqueId()
        // eslint-disable-next-line new-cap
        var msg = new this.$webIM.message('txt', id)
        var message = this.messageChat || data
        // var groupid = this.selectCustomer.groupid
        console.log(data === '' ? {} : { ACTION_INITIATE: 0 }, '确认进行专业问诊')
        var option = {
          msg: message,
          to: that.chatting.name, // this.selectCustomer.groupid 群组id
          chatType: 'singleChat', // groupChat
          ext: data === '' ? {} : { ACTION_INITIATE: 0 },
          success: function () {
            console.log('发送成功:', that.chatting.name, message)
            // chatType chat单聊 chartroom聊天室
            that.send({
              from: 'zrymishu',
              to: that.chatting.name,
              chatType: 'chat',
              payload: JSON.stringify({
                msg: message,
                type: 'txt'
              })
            })
            that.message.push({
              name: 'zrymishu',
              time: new Date(),
              chatContent: message,
              host: true
            })
            that.$nextTick(() => {
              const div = document.getElementById('messgaeContent')
              div.scrollTop = div.scrollHeight
            })
            that.messageChat = ''
            // that.group.forEach(item => {
            //   if (groupid === item.groupid) {
            //     item.message.push({
            //       messageID: id,
            //       userID: that.userInfo.phone,
            //       data: message,
            //       dataType: 'TEXT',
            //       time: ''
            //     })
            //     var data = {
            //       groupId: groupid,
            //       messageId: id,
            //       dataType: 'TEXT',
            //       data: message
            //     }
            //     updateChatMessage(data)
            // }
            // })
            //     if (groupid === that.selectCustomer.groupid) {
            // that.$nextTick(() => {
            //   var div = document.getElementById('messgaeContent')
            //   div.scrollTop = div.scrollHeight
            // })
          }
        }
        msg.set(option)
        this.$webIM.conn.send(msg.body)
      }
    },
    customEmoji (value) {
      return `${value}" style="width:20px; height: 20px;"/>`
    },
    renderTxt (txt = '') {
      const 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))
      // console.log(rnTxt.toString().replace(/,/g, ''), '表情')
      this.timer = Date.parse(new Date())
      return rnTxt.toString().replace(/,/g, '')
    },
    selectEmoji (v) {
      this.$data.messageChat = v
      this.$refs.txtDom.focus()
    },
    receiveMessage (message) {
      console.log('收到文本消息', message)
      if (this.chatting.name === message.from) {
        this.message.push({
          name: message.from,
          time: message.time,
          chatContent: message.data,
          host: false
        })
      }
      console.log('who来的消息', this.conversationalist, message.from)
      console.log('this.chatList', this.newChatList)
      const isChatList = this.chatList.some(ele => {
        return ele.name === message.from
      })
      if (isChatList) {
        console.log('正在会话的人来了一条消息')
        if (this.chatting.name === message.from) {
          this.chatList.map((ele, i) => {
            if (ele.name === message.from) {
              this.chatList[i].unread_num = 0
            }
          })
        } else {
          this.chatList.map((ele, i) => {
            if (ele.name === message.from) {
              this.chatList[i].unread_num += 1
            }
          })
        }
      } else {
        if (this.conversationalist.indexOf(message.from) !== -1) {
          const index = this.newChatList.findIndex(item => {
            return item.name === message.from
          })
          console.log('存在', index)
          this.newChatList[index].unread_num += 1
        } else {
          console.log('nono存在')
          this.conversationalist.push(message.from)
          this.newChatList.push({
            name: message.from,
            time: message.time,
            unread_num: 1
          })
        }
      }
      this.$nextTick(() => {
        var div = document.getElementById('messgaeContent')
        div.scrollTop = div.scrollHeight
      })
    },
    chatWithHim (row) {
      this.chatting.name = row.name
      row.unread_num = 0
    },
    // 开始交谈,放到会话中
    startConversation (item) {
      item.unread_num = 0
      this.$store.commit('chatList', item)
      // this.newChatList = this.newChatList.filter(ele => {
      //   return ele.id !== item.id
      // })
      console.log(this.chatList, 'this.chatListthis.chatList')
      this.chatWithHim(item)
    },
    timestampConversion (val) {
      return dayjs(Number(val)).format('YYYY-MM-DD HH:mm:ss')
    },
    // 结束交谈
    async endConversation () {
      const res = await api.endSession({
        imUserId: this.chatting.name,
        secretaryId: this.$store.state.user_info.userId
      })
      if (!res.state) return false
      this.chatList = this.chatList.filter(ele => {
        return ele.name !== this.chatting.name
      })
    },
    // 发起专业问诊
    launchConsultation () {
      // todo
      this.sendMessage('确认进行专业问诊?')
    },
    // 结束专业问诊
    endConsultation () {
      // todo
    },
    // 开始会话
    async startSession (item) {
      const res = await api.receiveUser({
        id: item.id,
        secretaryId: this.$store.state.user_info.userId,
        personId: item.personId
      })
      if (!res.state) return false
      this.getUserSendLists()
      this.startConversation(item)
    },
    async send (data) {
      const res = await api.send(data)
      if (!res.state) return false
    }
  }
}
</script>

<style lang='less'>
.onlineService {
  background-color: #fff;
  height: 100%;
  overflow: hidden;

  .scroll {
    overflow: auto;
    height: calc(100% - 80px);

    .box {
      display: flex;
      margin: 30px 0 0 40px;

      .box_l {
        width: 40px;
        height: 40px;
        background: #bac2cb;
        border-radius: 50%;
        margin-right: 10px;
      }

      .box_r {
        width: 100%;
        position: relative;

        .userName {
          font-weight: bold;
        }

        .time {
          margin-top: 4px;
          color: #69747e;
        }

        .ques {
          margin: 10px 0;
          font-size: 14px;
        }

        .el-input {
        }

        img {
          margin: 10px 10px 10px 0;
        }

        .el-button.is-round {
          position: absolute;
          top: 8px;
          right: 40px;
          padding: 6px 14px;
        }
      }
    }
  }

  .chat {
    display: flex;
    width: 100%;
    height: 100%;

    .chat_l {
      width: 280px;
      padding: 0 16px;
      box-sizing: border-box;
      border-right: 1px solid #E7ECF0;

      .inConversation {
        margin: 24px 0 16px;
        background-color: #F2F3F5;
        padding: 6px 8px;
        display: flex;
        justify-content: space-between;
        cursor: pointer;
      }

      .newSession {
        margin: 16px 0;
        background-color: #F2F3F5;
        padding: 6px 8px;
        display: flex;
        justify-content: space-between;
        cursor: pointer;
      }

      .chatList {
        display: flex;
        padding: 10px 20px;

        .flex {
          width: 155px;
          justify-content: space-between;
        }

        img {
          width: 40px;
          height: 40px;
          margin-right: 8px;
          border-radius: 25px;
        }

        .chatName {
          font-size: 14px;
          margin-bottom: 6px;
        }

        .badge {
          color: #fff;
          height: 20px;
          line-height: 20px;
          background: #ea5d56;
          border-radius: 25px;
          min-width: 20px;
          text-align: center;
          font-size: 12px;
        }

        .chatTime {
          font-size: 12px;
          color: #69747E;
        }
      }
    }

    .chat_m {
      //background-color: #f8f9fe;
      width: calc(100% - 560px);

      .chat_m_top {
        border-bottom: 2px solid #E7ECF0;
        box-shadow: 0px 6px 10px -5px rgb(178 178 178 / 40%);
        justify-content: space-between;
        align-items: center;
        box-sizing: border-box;
        padding: 19px;

        .name {
          font-weight: bold;
          font-size: 16px;
        }

        .ending {
          color: #fff;
          padding: 6px 14px;
          background: linear-gradient(to right, #ff6e00, #ea5d56);
          border-radius: 15px;
          cursor: pointer;
        }
      }

      .chat_m_m {
        padding: 20px;
        box-sizing: border-box;
        height: calc(100% - 390px);
        overflow: auto;

        .photo {
          background-color: #afb9c6;
          border-radius: 50%;
          width: 30px;
          height: 30px;
          text-align: center;
          line-height: 30px;
        }

        .el-icon-user {
          color: #fff;
          font-size: 16px;
        }

        .flex {
          align-items: center;
          margin-bottom: 12px;

          .phone {
            margin: 0 10px;
            font-size: 14px;
            color: #69747E;
          }

          .time {
            font-size: 14px;
            color: #69747E;
          }
        }

        .chatContent {
          margin-bottom: 25px;
          display: inline-block;
          margin-left: 40px;
          border: 1px solid #D7DDE5;
          background-color: #EFF2F7;
          color: #171d25;
          padding: 11px 20px;
          border-radius: 0px 8px 8px 8px;
        }

        .host {
          display: flex;
          flex-direction: column;
          align-items: flex-end;

          .phone {
            margin: 0 10px;
            font-size: 14px;
            color: #171D25;
          }

          .time {
            margin-left: 10px;
            color: #171D25;
          }

          .chatContent {
            background-color: #fff;
            border-radius: 8px 0px 8px 8px;
          }
        }
      }

      .chat_m_bottom {
        //box-shadow: 0px -4px 3.68px 0.32px rgba(178, 178, 178, 0.22);
        //border-top: 1px solid #E7ECF0;
        //padding: 20px 0;
        height: 230px;

        .emoji {
          border-top: 1px solid #E7ECF0;
          border-bottom: 1px solid #E7ECF0;
          padding: 15px 20px;
        }

        .el-textarea__inner {
          //background-color: #f8f9fe;
          border: none;
          padding: 0;
          font-size: 14px;
          resize: none;
        }

        .el-button--success {
          border-radius: 3px;
          float: right;
        }
      }
    }

    .chat_r {
      width: 280px;
      padding-left: 20px;
      border-left: 1px solid #EFF2F5;

      div {
        margin-top: 20px;
      }

      div:first-child {
        font-weight: bold;
      }

      .el-button {
        padding-top: 20px;
      }
    }
  }

  .el-tabs {
    padding-top: 10px;
  }

  .el-tabs__header {
    margin: 0;
  }

  .el-tabs__nav-wrap::after {
    background-color: #eff2f5;
  }

  .el-tabs--top .el-tabs__item.is-top:nth-child(2) {
    padding-left: 20px !important;
  }

  .flex {
    display: flex;
  }
}
</style>

完善中。。。

你可能感兴趣的:(javascript,vue.js)