Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
848bc606
authored
Jul 08, 2024
by
puhui999
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
【新增】mall 客服消息下拉加载,有新消息提醒
parent
e9bb9403
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
110 additions
and
35 deletions
+110
-35
src/views/mall/promotion/kefu/components/KeFuChatBox.vue
+108
-14
src/views/mall/promotion/kefu/components/KeFuConversationBox.vue
+2
-21
No files found.
src/views/mall/promotion/kefu/components/KeFuChatBox.vue
View file @
848bc606
...
@@ -4,9 +4,16 @@
...
@@ -4,9 +4,16 @@
<div
class=
"kefu-title"
>
{{
keFuConversation
.
userNickname
}}
</div>
<div
class=
"kefu-title"
>
{{
keFuConversation
.
userNickname
}}
</div>
</el-header>
</el-header>
<el-main
class=
"kefu-content"
style=
"overflow: visible"
>
<el-main
class=
"kefu-content"
style=
"overflow: visible"
>
<el-scrollbar
ref=
"scrollbarRef"
always
height=
"calc(100vh - 495px)"
>
<div
v-show=
"loadingMore"
class=
"loadingMore flex justify-center items-center cursor-pointer"
@
click=
"handleOldMessage"
>
加载更多
</div>
<el-scrollbar
ref=
"scrollbarRef"
always
height=
"calc(100vh - 495px)"
@
scroll=
"handleScroll"
>
<div
ref=
"innerRef"
class=
"w-[100%] pb-3px"
>
<div
ref=
"innerRef"
class=
"w-[100%] pb-3px"
>
<div
v-for=
"(item, index) in
messageList
"
:key=
"item.id"
class=
"w-[100%]"
>
<div
v-for=
"(item, index) in
getMessageList0
"
:key=
"item.id"
class=
"w-[100%]"
>
<div
class=
"flex justify-center items-center mb-20px"
>
<div
class=
"flex justify-center items-center mb-20px"
>
<!-- 日期 -->
<!-- 日期 -->
<div
<div
...
@@ -58,6 +65,14 @@
...
@@ -58,6 +65,14 @@
</div>
</div>
</div>
</div>
</el-scrollbar>
</el-scrollbar>
<div
v-show=
"showNewMessageTip"
class=
"newMessageTip flex items-center cursor-pointer"
@
click=
"handleToNewMessage"
>
<span>
有新消息
</span>
<Icon
class=
"ml-5px"
icon=
"ep:bottom"
/>
</div>
</el-main>
</el-main>
<el-footer
height=
"230px"
>
<el-footer
height=
"230px"
>
<div
class=
"h-[100%]"
>
<div
class=
"h-[100%]"
>
...
@@ -101,23 +116,47 @@ const messageTool = useMessage()
...
@@ -101,23 +116,47 @@ const messageTool = useMessage()
const
message
=
ref
(
''
)
// 消息
const
message
=
ref
(
''
)
// 消息
const
messageList
=
ref
<
KeFuMessageRespVO
[]
>
([])
// 消息列表
const
messageList
=
ref
<
KeFuMessageRespVO
[]
>
([])
// 消息列表
const
keFuConversation
=
ref
<
KeFuConversationRespVO
>
({}
as
KeFuConversationRespVO
)
// 用户会话
const
keFuConversation
=
ref
<
KeFuConversationRespVO
>
({}
as
KeFuConversationRespVO
)
// 用户会话
// 获得消息 TODO puhui999: 先不考虑下拉加载历史消息
const
showNewMessageTip
=
ref
(
false
)
// 显示有新消息提示
const
queryParams
=
reactive
({
pageNo
:
1
,
conversationId
:
0
})
const
total
=
ref
(
0
)
// 消息总条数
// 获得消息
const
getMessageList
=
async
(
conversation
:
KeFuConversationRespVO
)
=>
{
const
getMessageList
=
async
(
conversation
:
KeFuConversationRespVO
)
=>
{
keFuConversation
.
value
=
conversation
keFuConversation
.
value
=
conversation
const
{
list
}
=
await
KeFuMessageApi
.
getKeFuMessagePage
({
queryParams
.
conversationId
=
conversation
.
id
pageNo
:
1
,
const
messageTotal
=
messageList
.
value
.
length
conversationId
:
conversation
.
id
if
(
total
.
value
>
0
&&
messageTotal
>
0
&&
messageTotal
===
total
.
value
)
{
})
return
messageList
.
value
=
list
.
reverse
()
}
// TODO puhui999: 首次加载时滚动到最新消息,如果加载的是历史消息则不滚动
const
res
=
await
KeFuMessageApi
.
getKeFuMessagePage
(
queryParams
)
total
.
value
=
res
.
total
for
(
const
item
of
res
.
list
)
{
if
(
messageList
.
value
.
some
((
val
)
=>
val
.
id
===
item
.
id
))
{
continue
}
messageList
.
value
.
push
(
item
)
}
await
scrollToBottom
()
await
scrollToBottom
()
}
}
const
getMessageList0
=
computed
(()
=>
{
messageList
.
value
.
sort
((
a
:
any
,
b
:
any
)
=>
a
.
createTime
-
b
.
createTime
)
return
messageList
.
value
})
// 刷新消息列表
// 刷新消息列表
const
refreshMessageList
=
()
=>
{
const
refreshMessageList
=
async
()
=>
{
if
(
!
keFuConversation
.
value
)
{
if
(
!
keFuConversation
.
value
)
{
return
return
}
}
getMessageList
(
keFuConversation
.
value
)
queryParams
.
pageNo
=
1
await
getMessageList
(
keFuConversation
.
value
)
if
(
loadHistory
.
value
)
{
// 有下角显示有新消息提示
showNewMessageTip
.
value
=
true
}
}
}
defineExpose
({
getMessageList
,
refreshMessageList
})
defineExpose
({
getMessageList
,
refreshMessageList
})
// 是否显示聊天区域
// 是否显示聊天区域
...
@@ -140,7 +179,7 @@ const handleSendPicture = async (picUrl: string) => {
...
@@ -140,7 +179,7 @@ const handleSendPicture = async (picUrl: string) => {
const
handleSendMessage
=
async
()
=>
{
const
handleSendMessage
=
async
()
=>
{
// 1. 校验消息是否为空
// 1. 校验消息是否为空
if
(
isEmpty
(
unref
(
message
.
value
)))
{
if
(
isEmpty
(
unref
(
message
.
value
)))
{
messageTool
.
w
arning
(
'请输入消息后再发送哦!'
)
messageTool
.
notifyW
arning
(
'请输入消息后再发送哦!'
)
return
return
}
}
// 2. 组织发送消息
// 2. 组织发送消息
...
@@ -167,12 +206,41 @@ const innerRef = ref<HTMLDivElement>()
...
@@ -167,12 +206,41 @@ const innerRef = ref<HTMLDivElement>()
const
scrollbarRef
=
ref
<
InstanceType
<
typeof
ElScrollbarType
>>
()
const
scrollbarRef
=
ref
<
InstanceType
<
typeof
ElScrollbarType
>>
()
// 滚动到底部
// 滚动到底部
const
scrollToBottom
=
async
()
=>
{
const
scrollToBottom
=
async
()
=>
{
// 1. 滚动到最新消息
// 1. 首次加载时滚动到最新消息,如果加载的是历史消息则不滚动
if
(
loadHistory
.
value
)
{
return
}
// 2.1 滚动到最新消息,关闭新消息提示
await
nextTick
()
await
nextTick
()
scrollbarRef
.
value
!
.
setScrollTop
(
innerRef
.
value
!
.
clientHeight
)
scrollbarRef
.
value
!
.
setScrollTop
(
innerRef
.
value
!
.
clientHeight
)
// 2. 消息已读
showNewMessageTip
.
value
=
false
// 2.2 消息已读
await
KeFuMessageApi
.
updateKeFuMessageReadStatus
(
keFuConversation
.
value
.
id
)
await
KeFuMessageApi
.
updateKeFuMessageReadStatus
(
keFuConversation
.
value
.
id
)
}
}
// 查看新消息
const
handleToNewMessage
=
async
()
=>
{
loadHistory
.
value
=
false
await
scrollToBottom
()
}
const
loadingMore
=
ref
(
false
)
// 滚动到顶部加载更多
const
loadHistory
=
ref
(
false
)
// 加载历史消息
const
handleScroll
=
async
({
scrollTop
})
=>
{
const
messageTotal
=
messageList
.
value
.
length
if
(
total
.
value
>
0
&&
messageTotal
>
0
&&
messageTotal
===
total
.
value
)
{
return
}
// 距顶 20 加载下一页数据
loadingMore
.
value
=
scrollTop
<
20
}
const
handleOldMessage
=
async
()
=>
{
loadHistory
.
value
=
true
// 加载消息列表
queryParams
.
pageNo
+=
1
await
getMessageList
(
keFuConversation
.
value
)
loadingMore
.
value
=
false
// TODO puhui999: 等页面加载完后,获得上一页最后一条消息的位置,控制滚动到它所在位置
}
/**
/**
* 是否显示时间
* 是否显示时间
* @param {*} item - 数据
* @param {*} item - 数据
...
@@ -196,6 +264,32 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
...
@@ -196,6 +264,32 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
}
}
&
-content
{
&
-content
{
position
:
relative
;
.loadingMore
{
position
:
absolute
;
top
:
0
;
left
:
0
;
width
:
100%
;
height
:
50px
;
background-color
:
#eee
;
color
:
#666
;
text-align
:
center
;
line-height
:
50px
;
transform
:
translateY
(
-100%
);
transition
:
transform
0.3s
ease-in-out
;
}
.newMessageTip
{
position
:
absolute
;
bottom
:
35px
;
right
:
35px
;
background-color
:
#fff
;
padding
:
10px
;
border-radius
:
30px
;
box-shadow
:
0
2px
4px
rgba
(
0
,
0
,
0
,
0.1
);
/* 阴影效果 */
}
.ss-row-left
{
.ss-row-left
{
justify-content
:
flex-start
;
justify-content
:
flex-start
;
...
...
src/views/mall/promotion/kefu/components/KeFuConversationBox.vue
View file @
848bc606
...
@@ -74,7 +74,7 @@
...
@@ -74,7 +74,7 @@
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
{
KeFuConversationApi
,
KeFuConversationRespVO
}
from
'@/api/mall/promotion/kefu/conversation'
import
{
KeFuConversationApi
,
KeFuConversationRespVO
}
from
'@/api/mall/promotion/kefu/conversation'
import
{
useEmoji
}
from
'./tools/emoji'
import
{
useEmoji
}
from
'./tools/emoji'
import
{
formatDate
,
getNowDateTime
}
from
'@/utils/formatTime'
import
{
formatDate
}
from
'@/utils/formatTime'
import
{
KeFuMessageContentTypeEnum
}
from
'./tools/constants'
import
{
KeFuMessageContentTypeEnum
}
from
'./tools/constants'
defineOptions
({
name
:
'KeFuConversationBox'
})
defineOptions
({
name
:
'KeFuConversationBox'
})
...
@@ -84,24 +84,6 @@ const activeConversationIndex = ref(-1) // 选中的会话
...
@@ -84,24 +84,6 @@ const activeConversationIndex = ref(-1) // 选中的会话
const
conversationList
=
ref
<
KeFuConversationRespVO
[]
>
([])
// 会话列表
const
conversationList
=
ref
<
KeFuConversationRespVO
[]
>
([])
// 会话列表
const
getConversationList
=
async
()
=>
{
const
getConversationList
=
async
()
=>
{
conversationList
.
value
=
await
KeFuConversationApi
.
getConversationList
()
conversationList
.
value
=
await
KeFuConversationApi
.
getConversationList
()
// 测试数据
for
(
let
i
=
0
;
i
<
5
;
i
++
)
{
conversationList
.
value
.
push
({
id
:
1
,
userId
:
283
,
userAvatar
:
'https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKMezSxtOImrC9lbhwHiazYwck3xwrEcO7VJfG6WQo260whaeVNoByE5RreiaGsGfOMlIiaDhSaA991w/132'
,
userNickname
:
'辉辉鸭'
+
i
,
lastMessageTime
:
getNowDateTime
(),
lastMessageContent
:
'[爱心][爱心]你好哇你好哇你好哇你好哇你好哇你好哇你好哇你好哇你好哇你好哇你好哇你好哇你好哇你好哇你好哇你好哇你好哇你好哇'
,
lastMessageContentType
:
1
,
adminPinned
:
false
,
userDeleted
:
false
,
adminDeleted
:
false
,
adminUnreadMessageCount
:
i
})
}
}
}
defineExpose
({
getConversationList
})
defineExpose
({
getConversationList
})
const
emits
=
defineEmits
<
{
const
emits
=
defineEmits
<
{
...
@@ -157,8 +139,7 @@ const updateConversationPinned = async (adminPinned: boolean) => {
...
@@ -157,8 +139,7 @@ const updateConversationPinned = async (adminPinned: boolean) => {
id
:
selectedConversation
.
value
.
id
,
id
:
selectedConversation
.
value
.
id
,
adminPinned
adminPinned
})
})
// TODO puhui999: 快速操作两次提示只会提示一次看看怎么优雅解决
message
.
notifySuccess
(
adminPinned
?
'置顶成功'
:
'取消置顶成功'
)
message
.
success
(
adminPinned
?
'置顶成功'
:
'取消置顶成功'
)
// 2. 关闭右键菜单,更新会话列表
// 2. 关闭右键菜单,更新会话列表
closeRightMenu
()
closeRightMenu
()
await
getConversationList
()
await
getConversationList
()
...
...
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