Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Q
qk_admin
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
quanku
qk_admin
Commits
618cc34e
Commit
618cc34e
authored
Nov 03, 2023
by
yaya
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 添加聊天功能
parent
3c7b83f2
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
566 additions
and
43 deletions
+566
-43
package.json
package.json
+5
-2
src/api/business/chat.js
src/api/business/chat.js
+17
-0
src/utils/chat.js
src/utils/chat.js
+18
-0
src/utils/index.js
src/utils/index.js
+48
-8
src/views/customerService/chatDetail.vue
src/views/customerService/chatDetail.vue
+399
-33
src/views/customerService/components/chatMessageItem.vue
src/views/customerService/components/chatMessageItem.vue
+79
-0
No files found.
package.json
View file @
618cc34e
...
@@ -22,6 +22,7 @@
...
@@ -22,6 +22,7 @@
},
},
"dependencies"
:
{
"dependencies"
:
{
"
@riophae/vue-treeselect
"
:
"
0.0.37
"
,
"
@riophae/vue-treeselect
"
:
"
0.0.37
"
,
"
@tencentcloud/chat
"
:
"
^3.2.1
"
,
"
@tinymce/tinymce-vue
"
:
"
1.1.0
"
,
"
@tinymce/tinymce-vue
"
:
"
1.1.0
"
,
"
axios
"
:
"
0.18.0
"
,
"
axios
"
:
"
0.18.0
"
,
"
clipboard
"
:
"
1.7.1
"
,
"
clipboard
"
:
"
1.7.1
"
,
...
@@ -36,6 +37,8 @@
...
@@ -36,6 +37,8 @@
"
normalize.css
"
:
"
7.0.0
"
,
"
normalize.css
"
:
"
7.0.0
"
,
"
nprogress
"
:
"
0.2.0
"
,
"
nprogress
"
:
"
0.2.0
"
,
"
screenfull
"
:
"
3.3.3
"
,
"
screenfull
"
:
"
3.3.3
"
,
"
tim-profanity-filter-plugin
"
:
"
^1.0.0
"
,
"
tim-upload-plugin
"
:
"
^1.3.0
"
,
"
tree-table-vue
"
:
"
^1.1.0
"
,
"
tree-table-vue
"
:
"
^1.1.0
"
,
"
v-charts
"
:
"
1.19.0
"
,
"
v-charts
"
:
"
1.19.0
"
,
"
vue
"
:
"
2.5.17
"
,
"
vue
"
:
"
2.5.17
"
,
...
@@ -46,9 +49,9 @@
...
@@ -46,9 +49,9 @@
"
vue-router
"
:
"
3.0.1
"
,
"
vue-router
"
:
"
3.0.1
"
,
"
vue2-org-tree
"
:
"
^1.3.6
"
,
"
vue2-org-tree
"
:
"
^1.3.6
"
,
"
vued3tree
"
:
"
^5.1.0
"
,
"
vued3tree
"
:
"
^5.1.0
"
,
"
vuedraggable
"
:
"
^2.23.2
"
,
"
vuex
"
:
"
3.0.1
"
,
"
vuex
"
:
"
3.0.1
"
,
"
xlsx
"
:
"
^0.11.16
"
,
"
xlsx
"
:
"
^0.11.16
"
"
vuedraggable
"
:
"
^2.23.2
"
},
},
"devDependencies"
:
{
"devDependencies"
:
{
"
autoprefixer
"
:
"
8.5.0
"
,
"
autoprefixer
"
:
"
8.5.0
"
,
...
...
src/api/business/chat.js
0 → 100644
View file @
618cc34e
import
request
from
'
@/utils/request
'
export
function
getUserSig
(
params
)
{
return
request
({
url
:
'
/sysIM/getUserSig
'
,
method
:
'
post
'
,
data
:
params
})
}
export
function
getUserList
(
params
)
{
return
request
({
url
:
'
/sysAiAssistant/find
'
,
method
:
'
post
'
,
data
:
params
})
}
src/utils/chat.js
0 → 100644
View file @
618cc34e
import
TencentCloudChat
from
'
@tencentcloud/chat
'
import
TIMUploadPlugin
from
'
tim-upload-plugin
'
import
TIMProfanityFilterPlugin
from
'
tim-profanity-filter-plugin
'
// 初始化 SDK 实例
const
options
=
{
SDKAppID
:
1400489950
// 接入时需要将0替换为您的即时通信 IM 应用的 SDKAppID
}
// 创建 SDK 实例,`TencentCloudChat.create()`方法对于同一个 `SDKAppID` 只会返回同一份实例
const
chat
=
TencentCloudChat
.
create
(
options
)
// SDK 实例通常用 chat 表示
chat
.
setLogLevel
(
0
)
// 普通级别,日志量较多,接入时建议使用
// chat.setLogLevel(1); // release 级别,SDK 输出关键信息,生产环境时建议使用
// 注册腾讯云即时通信 IM 上传插件
chat
.
registerPlugin
({
'
tim-upload-plugin
'
:
TIMUploadPlugin
})
// 注册腾讯云即时通信 IM 本地审核插件
chat
.
registerPlugin
({
'
tim-profanity-filter-plugin
'
:
TIMProfanityFilterPlugin
})
export
default
chat
src/utils/index.js
View file @
618cc34e
...
@@ -51,21 +51,61 @@ export function formatTime(time, option) {
...
@@ -51,21 +51,61 @@ export function formatTime(time, option) {
return
Math
.
ceil
(
diff
/
3600
)
+
'
小时前
'
return
Math
.
ceil
(
diff
/
3600
)
+
'
小时前
'
}
else
if
(
diff
<
3600
*
24
*
2
)
{
}
else
if
(
diff
<
3600
*
24
*
2
)
{
return
'
1天前
'
return
'
1天前
'
}
else
if
(
diff
<
3600
*
24
*
2
*
7
)
{
return
(
d
.
getMonth
()
+
1
+
'
-
'
+
d
.
getDate
()
+
'
'
+
d
.
getHours
()
+
'
:
'
+
d
.
getMinutes
()
)
}
else
if
(
isYear
(
time
))
{
return
(
d
.
getMonth
()
+
1
+
'
-
'
+
d
.
getDate
()
)
}
else
{
return
(
d
.
getFullYear
()
+
'
-
'
+
d
.
getMonth
()
+
'
-
'
+
d
.
getDate
()
+
'
'
+
d
.
getHours
()
+
'
:
'
+
d
.
getMinutes
()
)
}
}
if
(
option
)
{
/*
if (option) {
return parseTime(time, option)
return parseTime(time, option)
} else {
} else {
return (
return (
d
.
getMonth
()
+
d.getMonth()
1
+
+
'
月
'
+
'
-
' +
d.getDate() +
d.getDate() +
'
日
'
+
'
' +
d.getHours() +
d.getHours() +
'
时
'
+
':' +
d
.
getMinutes
()
+
d.getMinutes()
'
分
'
)
)
}*/
}
function
isYear
(
timeValue
)
{
// 是否为今年
const
dateyear
=
new
Date
(
timeValue
).
getFullYear
()
const
toyear
=
new
Date
().
getFullYear
()
// console.log(dateyear, toyear)
if
(
dateyear
===
toyear
)
{
return
true
}
else
{
return
false
}
}
}
}
...
...
src/views/customerService/chatDetail.vue
View file @
618cc34e
...
@@ -5,12 +5,31 @@
...
@@ -5,12 +5,31 @@
<span
slot=
"title"
>
{{
item
.
title
}}
</span>
<span
slot=
"title"
>
{{
item
.
title
}}
</span>
</el-menu-item>
</el-menu-item>
</el-menu>
-->
</el-menu>
-->
<el-container
style=
"width: 100%;height: 100%; border: 1px solid #eee"
>
<el-container
v-loading=
"loading"
style=
"width: 100%;height: 100%; border: 1px solid #eee"
>
<el-aside
style=
"width: 25%;background-color: white;padding: 0"
>
<el-aside
style=
"background-color: white;padding: 10px"
>
<el-tabs
style=
"width: 100%; padding: 10px 10px 0"
@
tab-click=
"handleClick"
>
<el-tabs
:tab-position=
"top"
style=
"height: 100%;width: 100%;"
@
tab-click=
"handleClick"
>
<el-tab-pane
v-for=
"item in chatList"
:key=
"item.code"
:label=
"item.name"
/>
<el-tab-pane
v-for=
"item in chatList"
:key=
"item.userId"
:label=
"item.title"
>
{{
item
.
title
}}
</el-tab-pane>
</el-tabs>
</el-tabs>
<div
class=
"conversation"
>
<div
v-for=
"item in conversationList"
:key=
"item.conversationID"
:class=
"
{'conversation-item-active': currentChatItem.conversationID === item.conversationID}"
class="conversation-item flex f-ai-c"
@click="handleSelectChat(item)">
<div
class=
"conversation-item-image"
>
<img
:src=
"item.avatar"
class=
"conversation-item-image__avatar"
>
<div
class=
"conversation-item-image__num"
>
2
</div>
</div>
<div
class=
"conversation-item-info"
>
<div
class=
"conversation-item-info__nick"
>
{{
item
.
nick
}}
</div>
<div
class=
"conversation-item-info__message flex f-jc-sb"
>
<div
class=
"conversation-item-info__message__profile"
>
{{
item
.
messageForShow
}}
</div>
<div
class=
"conversation-item-info__message__time"
>
{{
item
.
lastTime
}}
</div>
</div>
</div>
</div>
</div>
</el-aside>
</el-aside>
<el-main
style=
"background-color: rgb(238, 241, 246); padding: 0; border: 1px solid #eee"
>
<el-main
style=
"background-color: rgb(238, 241, 246); padding: 0; border: 1px solid #eee"
>
<div
class=
"chat-message"
>
<div
class=
"chat-message"
>
...
@@ -18,6 +37,22 @@
...
@@ -18,6 +37,22 @@
<div
class=
"chat-message-top__title"
>
账号昵称
</div>
<div
class=
"chat-message-top__title"
>
账号昵称
</div>
<el-button
type=
"text"
>
人工介入
</el-button>
<el-button
type=
"text"
>
人工介入
</el-button>
</div>
</div>
<div
class=
"chat-message-list"
style=
"overflow:auto"
>
<ul
class=
"chat-message-list__content"
infinite-scroll-disabled=
"disabled"
style=
"margin: 0; padding: 0"
>
<div
v-for=
"messageItem in messageList"
:key=
"messageItem.id"
class=
"chat-message-list__content__item"
>
<ChatMessageItem
:chat-message-item=
"messageItem"
/>
</div>
</ul>
</div>
<div
class=
"chat-message-input"
>
<el-input
v-model=
"messageContent"
:rows=
"4"
type=
"textarea"
placeholder=
"请输入聊天内容"
style=
"border: none"
/>
<div
class=
"chat-message-input__send"
>
<el-button
:disabled=
"sendDisabled"
type=
"primary"
>
发送
</el-button>
</div>
</div>
</div>
</div>
</el-main>
</el-main>
<el-aside
style=
"width: 20%;background-color: white;padding: 10px"
>
<el-aside
style=
"width: 20%;background-color: white;padding: 10px"
>
...
@@ -31,45 +66,266 @@
...
@@ -31,45 +66,266 @@
</
template
>
</
template
>
<
script
>
<
script
>
import
{
getUserSig
,
getUserList
}
from
'
@/api/business/chat
'
import
chat
from
'
@/utils/chat
'
import
{
formatTime
}
from
'
@/utils/index
'
import
TencentCloudChat
from
'
@tencentcloud/chat
'
import
ChatMessageItem
from
'
./components/chatMessageItem
'
export
default
{
export
default
{
name
:
'
ChatDetail
'
,
name
:
'
ChatDetail
'
,
components
:
{
ChatMessageItem
},
data
()
{
data
()
{
return
{
return
{
activeIndex
:
'
1233
'
,
currentChatItem
:
{},
// 当前聊天
chatList
:
[
chatList
:
[],
{
loading
:
true
,
title
:
'
老猫
'
,
conversationList
:
[],
userId
:
'
1233
'
messageContent
:
''
,
count
:
10
,
currentChatIndex
:
-
1
,
// 当前聊天
nextReqMessageID
:
''
,
// 历史消息下一页
isCompleted
:
false
,
envText
:
'
cjxc-applet-dev_
'
,
messageList
:
[]
// 历史消息
}
},
},
{
computed
:
{
title
:
'
葛若
'
,
sendDisabled
()
{
userId
:
'
1323
'
return
!
this
.
messageContent
||
this
.
messageContent
.
length
===
0
}
},
},
{
created
()
{
title
:
'
斑胡
'
,
chat
.
on
(
TencentCloudChat
.
EVENT
.
SDK_READY
,
this
.
onSdkReady
)
userId
:
'
1133
'
this
.
handleGetChatList
()
},
},
{
methods
:
{
title
:
'
测试1
'
,
handleSelect
(
key
,
keyPath
)
{
userId
:
'
1143
'
console
.
log
(
key
,
keyPath
)
},
},
{
/**
title
:
'
测试2
'
,
* 选择客服
userId
:
'
1633
'
**/
handleClick
(
tab
,
event
)
{
console
.
log
(
'
====tab=
'
,
tab
.
index
,
event
)
if
(
this
.
currentChatIndex
===
tab
.
index
)
{
return
}
this
.
currentChatIndex
=
tab
.
index
this
.
handleBeforeLogin
()
},
},
{
/**
title
:
'
测试3
'
,
* 获取客服列表
userId
:
'
1933
'
**/
handleGetChatList
()
{
const
params
=
{}
getUserList
(
params
).
then
(
response
=>
{
if
(
response
&&
response
.
data
&&
response
.
data
.
data
)
{
this
.
chatList
=
response
.
data
.
data
}
}
]
if
(
this
.
chatList
.
length
>
0
)
{
this
.
handleBeforeLogin
()
}
}
console
.
log
(
'
===list ===
'
,
response
.
data
.
data
)
}).
catch
(
response
=>
{
this
.
$notify
.
error
({
title
:
'
失败
'
,
message
:
response
.
data
.
errmsg
||
'
请求失败
'
})
})
},
},
methods
:
{
handleBeforeLogin
()
{
handleSelect
(
key
,
keyPath
)
{
this
.
showLoading
()
console
.
log
(
key
,
keyPath
)
if
(
this
.
currentChatIndex
===
-
1
)
{
const
chatItem
=
this
.
chatList
[
0
]
this
.
currentChatIndex
=
0
this
.
handleGetUserSign
(
chatItem
.
code
)
}
else
{
const
promise
=
chat
.
logout
()
promise
.
then
((
imResponse
)
=>
{
// console.log('==登出成功=', imResponse.data, this.chatList) // 登出成功
const
chatItem
=
this
.
chatList
[
this
.
currentChatIndex
]
this
.
handleGetUserSign
(
chatItem
.
code
)
}).
catch
(
function
(
imError
)
{
console
.
warn
(
'
====登出失败:
'
,
imError
)
// 登录失败的相关信息
})
}
},
},
handleClick
(
tab
,
event
)
{
/**
console
.
log
(
tab
,
event
)
* 获取UserSign
*/
handleGetUserSign
(
userId
)
{
const
params
=
{
userId
:
userId
}
getUserSig
(
params
).
then
(
response
=>
{
this
.
handleImLoin
(
userId
,
response
.
data
.
data
.
userSig
)
}).
catch
(
response
=>
{
this
.
closeLoading
()
console
.
log
(
'
====获取userSign失败,
'
,
response
)
this
.
$notify
.
error
({
title
:
'
失败
'
,
message
:
response
.
data
.
errmsg
||
'
请求失败
'
})
})
},
/**
* IM 登录
*/
handleImLoin
(
userId
,
userSign
)
{
console
.
log
(
'
====用户信息===
'
,
userId
,
userSign
)
// 登录成功
const
promise
=
chat
.
login
({
userID
:
this
.
envText
+
userId
,
userSig
:
userSign
})
promise
.
then
((
imResponse
)
=>
{
this
.
closeLoading
()
console
.
log
(
'
====登录成功===
'
,
imResponse
.
data
)
// 登录成功
chat
.
on
(
TencentCloudChat
.
EVENT
.
CONVERSATION_LIST_UPDATED
,
this
.
onConversationListUpdated
)
chat
.
on
(
TencentCloudChat
.
EVENT
.
MESSAGE_RECEIVED
,
this
.
onMessageReceived
)
this
.
handleGetConversationList
()
if
(
imResponse
.
data
.
repeatLogin
===
true
)
{
// 标识账号已登录,本次登录操作为重复登录。
console
.
log
(
imResponse
.
data
.
errorInfo
)
}
}).
catch
((
imError
)
=>
{
this
.
closeLoading
()
console
.
warn
(
'
====登录失败:
'
,
imError
)
// 登录失败的相关信息
})
},
onSdkReady
(
event
)
{
this
.
handleGetConversationList
()
},
onMessageReceived
(
event
)
{
const
receivedList
=
event
.
data
receivedList
.
forEach
((
message
)
=>
{
if
(
message
.
type
===
TencentCloudChat
.
TYPES
.
MSG_TEXT
)
{
console
.
log
(
'
=====新消息=
'
,
message
)
// 文本消息 - https://web.sdk.qcloud.com/im/doc/v3/zh-cn/Message.html#.TextPayload
}
/* else if (message.type === TencentCloudChat.TYPES.MSG_IMAGE) {
// 图片消息 - https://web.sdk.qcloud.com/im/doc/v3/zh-cn/Message.html#.ImagePayload
} else if (message.type === TencentCloudChat.TYPES.MSG_SOUND) {
// 音频消息 - https://web.sdk.qcloud.com/im/doc/v3/zh-cn/Message.html#.AudioPayload
} else if (message.type === TencentCloudChat.TYPES.MSG_VIDEO) {
// 视频消息 - https://web.sdk.qcloud.com/im/doc/v3/zh-cn/Message.html#.VideoPayload
} else if (message.type === TencentCloudChat.TYPES.MSG_FILE) {
// 文件消息 - https://web.sdk.qcloud.com/im/doc/v3/zh-cn/Message.html#.FilePayload
} else if (message.type === TencentCloudChat.TYPES.MSG_CUSTOM) {
// 自定义消息 - https://web.sdk.qcloud.com/im/doc/v3/zh-cn/Message.html#.CustomPayload
} else if (message.type === TencentCloudChat.TYPES.MSG_MERGER) {
// 合并消息 - https://web.sdk.qcloud.com/im/doc/v3/zh-cn/Message.html#.MergerPayload
} else if (message.type === TencentCloudChat.TYPES.MSG_LOCATION) {
// 地理位置消息 - https://web.sdk.qcloud.com/im/doc/v3/zh-cn/Message.html#.LocationPayload
} else if (message.type === TencentCloudChat.TYPES.MSG_GRP_TIP) {
// 群提示消息 - https://web.sdk.qcloud.com/im/doc/v3/zh-cn/Message.html#.GroupTipPayload
} else if (message.type === TencentCloudChat.TYPES.MSG_GRP_SYS_NOTICE) {
// 群系统通知 - https://web.sdk.qcloud.com/im/doc/v3/zh-cn/Message.html#.GroupSystemNoticePayload
}*/
})
},
handleGetConversationList
()
{
const
promise
=
chat
.
getConversationList
()
promise
.
then
((
imResponse
)
=>
{
// 全量的会话列表,用该列表覆盖原有的会话列表
const
conversationList
=
imResponse
.
data
.
conversationList
this
.
setConversationList
(
conversationList
)
}).
catch
((
imError
)
=>
{
// 获取会话列表失败的相关信息
console
.
warn
(
'
getConversationList error:
'
,
imError
)
})
},
/**
* 会话列表更改监听
* */
onConversationListUpdated
(
event
)
{
console
.
log
(
'
====会话列表更新--
'
,
event
.
data
)
// 包含 Conversation 实例的数组
this
.
setConversationList
(
event
.
data
)
},
setConversationList
(
list
)
{
if
(
!
list
||
list
.
length
===
0
)
{
this
.
conversationList
=
[]
}
else
{
const
newList
=
[]
list
.
map
((
item
)
=>
{
const
object
=
{
conversationID
:
item
.
conversationID
||
''
,
messageForShow
:
item
.
lastMessage
.
messageForShow
,
lastTime
:
formatTime
(
item
.
lastMessage
.
lastTime
),
avatar
:
item
.
userProfile
.
avatar
,
nick
:
item
.
userProfile
.
nick
,
fromAccount
:
item
.
userProfile
.
userID
,
isPinned
:
item
.
isPinned
,
unreadCount
:
item
.
unreadCount
||
0
}
newList
.
push
(
object
)
})
this
.
conversationList
=
newList
}
},
/**
* 选择聊天
* */
handleSelectChat
(
item
)
{
this
.
messageList
=
[]
if
(
this
.
currentChatItem
!==
item
)
{
this
.
currentChatItem
=
item
this
.
nextReqMessageID
=
''
this
.
handleGetHistory
()
}
},
handleGetHistory
()
{
const
userID
=
this
.
chatList
[
this
.
currentChatIndex
].
code
if
(
this
.
currentChatItem
)
{
const
promise
=
chat
.
getMessageList
({
conversationID
:
this
.
currentChatItem
.
conversationID
,
nextReqMessageID
:
this
.
nextReqMessageID
})
promise
.
then
((
imResponse
)
=>
{
if
(
!
imResponse
||
!
imResponse
.
data
)
{
return
}
const
list
=
imResponse
.
data
.
messageList
||
[]
// 消息列表。
this
.
nextReqMessageID
=
imResponse
.
data
.
nextReqMessageID
||
''
// 用于续拉,分页续拉时需传入该字段。
this
.
isCompleted
=
imResponse
.
data
.
isCompleted
||
false
// 表示是否已经拉完所有消息。
console
.
log
(
'
====历史消息===
'
,
list
)
const
topList
=
[]
if
(
list
&&
list
.
length
>
0
)
{
imResponse
.
data
.
messageList
.
map
((
item
)
=>
{
const
object
=
{
id
:
item
.
ID
,
messageContent
:
item
.
payload
.
text
,
fromUserId
:
item
.
from
,
toAccount
:
item
.
to
,
avatar
:
item
.
avatar
,
msgType
:
item
.
from
===
this
.
envText
+
userID
?
1
:
2
}
topList
.
push
(
object
)
})
}
console
.
log
(
'
====messageList
'
,
this
.
messageList
,
topList
)
this
.
messageList
=
topList
.
concat
(
this
.
messageList
)
console
.
log
(
'
====历史消息
'
,
this
.
messageList
)
}).
catch
((
err
)
=>
{
console
.
log
(
'
====err--历史消息
'
,
err
)
})
}
},
/**
* 打开加载
*/
showLoading
()
{
this
.
loading
=
true
},
/**
* 关闭加载
*/
closeLoading
()
{
this
.
loading
=
false
}
}
}
}
}
}
...
@@ -79,6 +335,12 @@ export default {
...
@@ -79,6 +335,12 @@ export default {
/deep/ .main {
/deep/ .main {
padding: 0;
padding: 0;
}
}
/deep/ .el-textarea__inner {
border: none;
}
/deep/ .ul {
padding-inline-start: 0;
}
.page-chatDetail {
.page-chatDetail {
height: calc(100vh - 84px);
height: calc(100vh - 84px);
...
@@ -87,14 +349,118 @@ export default {
...
@@ -87,14 +349,118 @@ export default {
width: 30%;
width: 30%;
}
}
.conversation {
height: 100%;
.conversation-item {
border-bottom: 1px solid #e7eaec;
height: 50px;
background: white;
padding: 0 12px;
.conversation-item-image {
position: relative;
width: 30px;
height: 30px;
margin-right: 8px;
.conversation-item-image__avatar {
width: 30px;
height: 30px;
border-radius: 15px;
}
.conversation-item-image__num {
position: absolute;
right: 0;
top: 0;
height: 12px;
background-color: red;
color: white;
font-size: 12px;
font-weight: bold;
padding: 3px 6px;
border-radius: 50%;
display: none;
}
}
.conversation-item-info {
width: 100%;
.conversation-item-info__nick {
height: 20px;
font-size: 13px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #17191C;
line-height: 20px;
}
.conversation-item-info__message {
width: 100%;
.conversation-item-info__message__profile {
flex: 1;
height: 16px;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #989CA8;
line-height: 16px;
white-space: normal;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
margin-right: 10px
}
.conversation-item-info__message__time {
height: 16px;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #989CA8;
line-height: 16px;
}
}
}
}
.conversation-item-active {
background: rgb(238, 241, 246);
}
}
.chat-message {
.chat-message {
display: flex;
display: flex;
flex-direction: column;
flex-direction: column;
height:100%;
.chat-message-top {
.chat-message-top {
background: white;
background: white;
padding: 8px;
padding: 8px;
}
}
.chat-message-list {
width: 100%;
flex: 1;
.chat-message-list__content {
width: 100%;
.chat-message-list__content__item {
width: 100%;
margin-bottom: 20px;
}
}
}
.chat-message-input {
border: 1px solid #DCDFE6;
border-radius: 4px;
background-color: #FFFFFF;
padding: 12px 0;
.chat-message-input__send {
text-align: end;
margin: 12px 12px 0 0;
}
}
}
}
}
}
...
...
src/views/customerService/components/chatMessageItem.vue
0 → 100644
View file @
618cc34e
<
template
>
<div
class=
"message_components"
>
<div
v-if=
"chatMessageItem.msgType === 1"
class=
"message-self"
>
<div
class=
"message-self_content"
>
{{
chatMessageItem
.
messageContent
}}
</div>
<img
:src=
"chatMessageItem.avatar"
class=
"message-self__avatar"
>
</div>
<div
v-if=
"chatMessageItem.msgType === 2"
class=
"message-other"
>
<img
:src=
"chatMessageItem.avatar"
class=
"message-other__avatar"
>
<div
class=
"message-other_content"
>
{{
chatMessageItem
.
messageContent
}}
</div>
</div>
</div>
</
template
>
<
script
>
export
default
{
name
:
'
ChatMessageItem
'
,
props
:
{
chatMessageItem
:
{
type
:
Object
,
required
:
true
}
}
}
</
script
>
<
style
lang=
"less"
scoped
>
.message_components {
width: 100%;
display: flex;
flex-direction: column;
.message-self {
display: flex;
flex-direction: row;
.message-self_content {
width: fit-content;
max-width: 60%;
background: #95EC69;
border-radius: 11px 11px 0px 11px;
padding: 10px 12px;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
color: #000000;
line-height: 20px;
margin-left:auto;
}
.message-self__avatar {
width: 30px;
height: 30px;
border-radius: 15px;
margin: 0 10px;
}
}
.message-other {
display: flex;
flex-direction: row;
.message-other_content {
width: fit-content;
max-width: 60%;
background: #FFFFFF;
border-radius: 11px 11px 0px 11px;
padding: 10px 12px;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
color: #000000;
line-height: 20px;
}
.message-other__avatar {
width: 30px;
height: 30px;
border-radius: 15px;
margin: 0 10px;
}
}
}
</
style
>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment