安装
yarn add easemob- websdk
在utils文件中写一个WebIMConfig.js (appkey换成自己的)
var config = {
socketServer : ( window. location. protocol === 'https:' ? 'https:' : 'http:' ) + '//im-api-v2-hsb.easemob.com/ws' ,
restServer : ( window. location. protocol === 'https:' ? 'https:' : 'http:' ) + '//a1-hsb.easemob.com' ,
appkey : '1100210506200509#single-structure' ,
Host : 'easemob.com' ,
https : true ,
isHttpDNS : true ,
isMultiLoginSessions : true ,
isSandBox : false ,
isDebug : true ,
autoReconnectNumMax : 10 ,
isWebRTC : window. RTCPeerConnection && / ^https\\:$ / . test ( window. location. protocol) ,
useOwnUploadFun : false ,
i18n : 'cn' ,
isAutoLogin : false ,
p2pMessageCacheSize : 500 ,
delivery : true ,
groupMessageCacheSize : 200 ,
loglevel : 'ERROR' ,
enableLocalStorage : true ,
deviceId : 'webim' ,
AgoraAppId : ''
}
export default config
在utils文件中写一个WebIM.js
import websdk from 'easemob-websdk'
import config from './WebIMConfig'
const rtc = {
client : null ,
localAudioTrack : null ,
localVideoTrack : null
}
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 : WebIM. config. isHttpDNS,
onOffline : ( ) => {
console. log ( 'onOffline' )
} ,
onOnline : ( ) => {
console. log ( 'onOnline' )
}
}
WebIM. conn = new websdk. connection ( options)
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' ,
'[<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'
}
}
聊天.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 : [
] ,
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
that. $webIM. conn. getGroup ( ) . then ( async ( res ) => {
console. log ( res, 'res' )
} )
that. $webIM. conn. getRoster ( ) . then ( ( res ) => {
console. log ( '获取好友列表' , res)
} )
} ,
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 . 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 ( )
var msg = new this. $webIM. message ( 'txt' , id)
var message = this . messageChat || data
console. log ( data === '' ? { } : { ACTION_INITIATE : 0 } , '确认进行专业问诊' )
var option = {
msg : message,
to : that. chatting. name,
chatType : 'singleChat' ,
ext : data === '' ? { } : { ACTION_INITIATE : 0 } ,
success : function ( ) {
console. log ( '发送成功:' , that. chatting. name, message)
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 = ''
}
}
msg. set ( option)
this . $webIM. conn. send ( msg. body)
}
} ,
customEmoji ( value ) {
return ` <img src="../../../static/faces/ ${ 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) )
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)
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 ( ) {
this . sendMessage ( '确认进行专业问诊?' )
} ,
endConsultation ( ) {
} ,
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 {
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 {
height : 230px;
. emoji {
border- top: 1px solid #E7ECF0 ;
border- bottom: 1px solid #E7ECF0 ;
padding : 15px 20px;
}
. el- textarea__inner {
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>
完善中。。。