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
d3b4063b
authored
Jul 01, 2024
by
puhui999
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
【新增】:mall 客服消息样式设计
parent
d3614cbb
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
249 additions
and
88 deletions
+249
-88
src/api/mall/promotion/kefu/conversation/index.ts
+1
-1
src/api/mall/promotion/kefu/message/index.ts
+70
-0
src/views/mall/promotion/kefu/components/KeFuChatBox.vue
+167
-0
src/views/mall/promotion/kefu/components/KeFuConversationBox.vue
+4
-4
src/views/mall/promotion/kefu/components/KefuChatBox.vue
+0
-77
src/views/mall/promotion/kefu/components/constants.ts
+0
-4
src/views/mall/promotion/kefu/components/index.ts
+1
-1
src/views/mall/promotion/kefu/index.vue
+6
-1
No files found.
src/api/mall/promotion/kefu/conversation/index.ts
View file @
d3b4063b
...
...
@@ -16,7 +16,7 @@ export interface KeFuConversationRespVO {
/**
* 会话所属用户昵称
*/
n
ickname
:
string
userN
ickname
:
string
/**
* 最后聊天时间
*/
...
...
src/api/mall/promotion/kefu/message/index.ts
0 → 100644
View file @
d3b4063b
import
request
from
'@/config/axios'
export
interface
KeFuMessageRespVO
{
/**
* 编号
*/
id
:
number
/**
* 会话编号
*/
conversationId
:
number
/**
* 发送人编号
*/
senderId
:
number
/**
* 发送人头像
*/
senderAvatar
:
string
/**
* 发送人类型
*/
senderType
:
number
/**
* 接收人编号
*/
receiverId
:
number
/**
* 接收人类型
*/
receiverType
:
number
/**
* 消息类型
*/
contentType
:
number
/**
* 消息
*/
content
:
string
/**
* 是否已读
*/
readStatus
:
boolean
/**
* 创建时间
*/
createTime
:
Date
}
// 客服会话 API
export
const
KeFuMessageApi
=
{
// 发送客服消息
sendKeFuMessage
:
async
(
data
:
any
)
=>
{
return
await
request
.
put
({
url
:
'/promotion/kefu-message/send'
,
data
})
},
// 更新客服消息已读状态
updateKeFuMessageReadStatus
:
async
(
data
:
any
)
=>
{
return
await
request
.
put
({
url
:
'/promotion/kefu-message/update-read-status'
,
data
})
},
// 获得消息分页数据
getKeFuMessagePage
:
async
(
params
:
any
)
=>
{
return
await
request
.
get
({
url
:
'/promotion/kefu-message/page'
,
params
})
}
}
src/views/mall/promotion/kefu/components/KeFuChatBox.vue
0 → 100644
View file @
d3b4063b
<
template
>
<el-container
class=
"kefu"
>
<el-header>
<div
class=
"kefu-title"
>
{{
keFuConversation
.
userNickname
}}
</div>
</el-header>
<el-main
class=
"kefu-content"
>
<div
v-for=
"item in messageList"
:key=
"item.id"
:class=
"[
item.senderType === UserTypeEnum.MEMBER
? `ss-row-left`
: item.senderType === UserTypeEnum.ADMIN
? `ss-row-right`
: ''
]"
class=
"flex mb-20px w-[100%]"
>
<el-avatar
v-show=
"item.senderType === UserTypeEnum.MEMBER"
:src=
"keFuConversation.userAvatar"
alt=
"avatar"
/>
<div
class=
"kefu-message flex items-center p-10px"
>
<!-- 文本消息 -->
<template
v-if=
"KeFuMessageContentTypeEnum.TEXT === item.contentType"
>
<div
v-dompurify-html=
"replaceEmoji(item.content)"
:class=
"[
item.senderType === UserTypeEnum.MEMBER
? `ml-10px`
: item.senderType === UserTypeEnum.ADMIN
? `mr-10px`
: ''
]"
></div>
</
template
>
<
template
v-else
>
{{
item
.
content
}}
</
template
>
</div>
<el-avatar
v-show=
"item.senderType === UserTypeEnum.ADMIN"
:src=
"item.senderAvatar"
alt=
"avatar"
/>
</div>
</el-main>
<el-footer
height=
"230px"
>
<div
class=
"h-[100%]"
>
<div
class=
"chat-tools"
>
<Icon
:size=
"30"
class=
"ml-10px"
icon=
"fa:frown-o"
/>
</div>
<el-input
v-model=
"message"
:rows=
"6"
type=
"textarea"
/>
<div
class=
"h-45px flex justify-end"
>
<el-button
class=
"mt-10px"
type=
"primary"
>
发送
</el-button>
</div>
</div>
</el-footer>
</el-container>
<!-- 没选择左侧会话时显示空界面 -->
</template>
<
script
lang=
"ts"
setup
>
import
{
KeFuMessageApi
,
KeFuMessageRespVO
}
from
'@/api/mall/promotion/kefu/message'
import
{
KeFuConversationRespVO
}
from
'@/api/mall/promotion/kefu/conversation'
import
{
UserTypeEnum
}
from
'@/utils/constants'
import
{
replaceEmoji
}
from
'@/views/mall/promotion/kefu/components/emoji'
import
{
KeFuMessageContentTypeEnum
}
from
'@/views/mall/promotion/kefu/components/constants'
defineOptions
({
name
:
'KeFuMessageBox'
})
const
message
=
ref
(
''
)
// 消息
const
messageList
=
ref
<
KeFuMessageRespVO
[]
>
([])
// 消息列表
const
keFuConversation
=
ref
<
KeFuConversationRespVO
>
({}
as
KeFuConversationRespVO
)
// 用户会话
// 获得消息
const
getMessageList
=
async
(
conversation
:
KeFuConversationRespVO
)
=>
{
keFuConversation
.
value
=
conversation
const
{
list
}
=
await
KeFuMessageApi
.
getKeFuMessagePage
({
pageNo
:
1
,
conversationId
:
conversation
.
id
})
messageList
.
value
=
list
}
defineExpose
({
getMessageList
})
</
script
>
<
style
lang=
"scss"
scoped
>
.kefu
{
&-title
{
border-bottom
:
#e4e0e0
solid
1px
;
height
:
60px
;
line-height
:
60px
;
}
&
-content
{
.ss-row-left
{
justify-content
:
flex-start
;
.kefu-message
{
margin-left
:
20px
;
position
:
relative
;
&::before
{
content
:
''
;
width
:
10px
;
height
:
10px
;
left
:
-19px
;
top
:
calc
(
50%
-
10px
);
position
:
absolute
;
border-left
:
5px
solid
transparent
;
border-bottom
:
5px
solid
transparent
;
border-top
:
5px
solid
transparent
;
border-right
:
5px
solid
#ffffff
;
}
}
}
.ss-row-right
{
justify-content
:
flex-end
;
.
kefu-message
::
after
{
content
:
''
;
width
:
10px
;
height
:
10px
;
right
:
-19px
;
top
:
calc
(
50%
-
10px
);
position
:
absolute
;
border-left
:
5px
solid
#ffffff
;
border-bottom
:
5px
solid
transparent
;
border-top
:
5px
solid
transparent
;
border-right
:
5px
solid
transparent
;
}
}
.kefu-message
{
color
:
#333
;
border-radius
:
5px
;
box-shadow
:
3px
5px
15px
rgba
(
0
,
0
,
0
,
0.2
);
padding
:
5px
10px
;
width
:
auto
;
max-width
:
50%
;
text-align
:
left
;
display
:
inline-block
!important
;
position
:
relative
;
word-break
:
break-all
;
background-color
:
#ffffff
;
transition
:
all
0.2s
;
&:hover
{
transform
:
scale
(
1.03
);
}
}
}
.chat-tools
{
width
:
100%
;
border
:
#e4e0e0
solid
1px
;
height
:
44px
;
display
:
flex
;
align-items
:
center
;
}
::v-deep
(
textarea
)
{
resize
:
none
;
}
}
</
style
>
src/views/mall/promotion/kefu/components/KeFuConversationBox.vue
View file @
d3b4063b
...
...
@@ -10,7 +10,7 @@
<div
class=
"kefu-conversation-left flex justify-center items-center"
>
<el-avatar
:src=
"item.userAvatar"
alt=
"avatar"
/>
<div
class=
"ml-10px"
>
<div
class=
"nickname"
>
{{
item
.
n
ickname
}}
</div>
<div
class=
"nickname"
>
{{
item
.
userN
ickname
}}
</div>
<div
v-dompurify-html=
"replaceEmoji(item.lastMessageContent)"
class=
"last-message flex items-center color-[#989EA6]"
...
...
@@ -41,7 +41,7 @@ const getConversationList = async () => {
userId
:
283
,
userAvatar
:
'https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKMezSxtOImrC9lbhwHiazYwck3xwrEcO7VJfG6WQo260whaeVNoByE5RreiaGsGfOMlIiaDhSaA991w/132'
,
n
ickname
:
'辉辉鸭'
+
i
,
userN
ickname
:
'辉辉鸭'
+
i
,
lastMessageTime
:
getNowDateTime
(),
lastMessageContent
:
'[爱心][爱心]你好哇'
,
lastMessageContentType
:
1
,
...
...
@@ -54,12 +54,12 @@ const getConversationList = async () => {
}
defineExpose
({
getConversationList
})
const
emits
=
defineEmits
<
{
(
e
:
'change'
,
v
:
number
):
void
(
e
:
'change'
,
v
:
KeFuConversationRespVO
):
void
}
>
()
// 打开右侧消息
const
openRightMessage
=
(
item
:
KeFuConversationRespVO
,
index
:
number
)
=>
{
activeConversationIndex
.
value
=
index
emits
(
'change'
,
item
.
id
)
emits
(
'change'
,
item
)
}
</
script
>
...
...
src/views/mall/promotion/kefu/components/KefuChatBox.vue
deleted
100644 → 0
View file @
d3614cbb
<
template
>
<el-container
class=
"kefu"
>
<el-header>
<div
class=
"kefu-title"
>
芋道
</div>
</el-header>
<el-main
class=
"kefu-content"
>
<div
v-for=
"item in 100"
:key=
"item"
:class=
"[item % 2 === 0 ? `ss-row-left` : `ss-row-right`]"
class=
"flex mb-20px w-[100%]"
>
<el-avatar
v-if=
"item % 2 === 0"
alt=
"avatar"
src=
"https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"
/>
<div
class=
"ml-10px"
>
Lorem Ipsum,也称乱数假文或者哑元文本
</div>
<el-avatar
v-if=
"item % 2 !== 0"
alt=
"avatar"
src=
"https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"
/>
</div>
</el-main>
<el-footer
height=
"230px"
>
<div
class=
"h-[100%]"
>
<div
class=
"chat-tools"
>
<Icon
:size=
"30"
class=
"ml-10px"
icon=
"fa:frown-o"
/>
</div>
<el-input
v-model=
"message"
:autosize=
"
{ minRows: 6, maxRows: 6 }" type="textarea" />
<div
class=
"h-45px flex justify-end"
>
<el-button
class=
"mt-10px"
type=
"primary"
>
发送
</el-button>
</div>
</div>
</el-footer>
</el-container>
<!-- 没选择左侧会话时显示空界面 -->
</
template
>
<
script
lang=
"ts"
setup
>
defineOptions
({
name
:
'KeFuMessageBox'
})
const
message
=
ref
(
''
)
</
script
>
<
style
lang=
"scss"
scoped
>
.kefu
{
&-title
{
border-bottom
:
#e4e0e0
solid
1px
;
height
:
60px
;
line-height
:
60px
;
}
&
-content
{
}
.chat-tools
{
width
:
100%
;
border
:
#e4e0e0
solid
1px
;
height
:
44px
;
display
:
flex
;
align-items
:
center
;
}
.ss-row-left
{
justify-content
:
flex-start
;
}
.ss-row-right
{
justify-content
:
flex-end
;
}
::v-deep
(
textarea
)
{
resize
:
none
;
}
}
</
style
>
src/views/mall/promotion/kefu/components/constants.ts
View file @
d3b4063b
...
...
@@ -8,7 +8,3 @@ export const KeFuMessageContentTypeEnum = {
PRODUCT
:
10
,
// 商品消息
ORDER
:
11
// 订单消息"
}
export
const
UserTypeEnum
=
{
MEMBER
:
1
,
// 会员 面向 c 端,普通用户
ADMIN
:
2
// 管理员 面向 b 端,管理后台
}
src/views/mall/promotion/kefu/components/index.ts
View file @
d3b4063b
import
KeFuConversationBox
from
'./KeFuConversationBox.vue'
import
KeFuChatBox
from
'./Ke
f
uChatBox.vue'
import
KeFuChatBox
from
'./Ke
F
uChatBox.vue'
import
*
as
Constants
from
'./constants'
export
{
KeFuConversationBox
,
KeFuChatBox
,
Constants
}
src/views/mall/promotion/kefu/index.vue
View file @
d3b4063b
...
...
@@ -15,12 +15,17 @@
<
script
lang=
"ts"
setup
>
import
{
KeFuChatBox
,
KeFuConversationBox
}
from
'./components'
import
{
KeFuConversationRespVO
}
from
'@/api/mall/promotion/kefu/conversation'
defineOptions
({
name
:
'KeFu'
})
// 加载消息
const
keFuChatBoxRef
=
ref
<
InstanceType
<
typeof
KeFuChatBox
>>
()
const
handleChange
=
()
=>
{}
const
handleChange
=
(
conversation
:
KeFuConversationRespVO
)
=>
{
keFuChatBoxRef
.
value
?.
getMessageList
(
conversation
)
}
// 加载会话
const
keFuConversationRef
=
ref
<
InstanceType
<
typeof
KeFuConversationBox
>>
()
onMounted
(()
=>
{
keFuConversationRef
.
value
?.
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