mirror of
https://gitee.com/hhyykk/ipms-sjy-ui.git
synced 2025-06-19 23:02:00 +08:00
【功能完善】商城客服: 客服布局样式调整
This commit is contained in:
parent
1d01955b8b
commit
34fe09e2db
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="kefu">
|
<el-aside class="kefu-conversation-aside p-10px h-100%" width="260px">
|
||||||
|
<div class="color-[#999] font-bold my-10px">会话记录({{ conversationList.length }})</div>
|
||||||
<div
|
<div
|
||||||
v-for="item in conversationList"
|
v-for="item in conversationList"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
@ -22,7 +23,7 @@
|
|||||||
<div class="ml-10px w-100%">
|
<div class="ml-10px w-100%">
|
||||||
<div class="flex justify-between items-center w-100%">
|
<div class="flex justify-between items-center w-100%">
|
||||||
<span class="username">{{ item.userNickname }}</span>
|
<span class="username">{{ item.userNickname }}</span>
|
||||||
<span class="color-[var(--left-menu-text-color)]" style="font-size: 13px">
|
<span class="color-[#999]" style="font-size: 13px">
|
||||||
{{ formatPast(item.lastMessageTime, 'YYYY-MM-DD') }}
|
{{ formatPast(item.lastMessageTime, 'YYYY-MM-DD') }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@ -31,7 +32,7 @@
|
|||||||
v-dompurify-html="
|
v-dompurify-html="
|
||||||
getConversationDisplayText(item.lastMessageContentType, item.lastMessageContent)
|
getConversationDisplayText(item.lastMessageContentType, item.lastMessageContent)
|
||||||
"
|
"
|
||||||
class="last-message flex items-center color-[var(--left-menu-text-color)]"
|
class="last-message flex items-center color-[#999]"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -65,7 +66,7 @@
|
|||||||
取消
|
取消
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</el-aside>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@ -179,7 +180,9 @@ watch(showRightMenu, (val) => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.kefu {
|
.kefu-conversation-aside {
|
||||||
|
background-color: #fff;
|
||||||
|
|
||||||
&-conversation {
|
&-conversation {
|
||||||
height: 60px;
|
height: 60px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
@ -206,12 +209,13 @@ watch(showRightMenu, (val) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.active {
|
.active {
|
||||||
border-left: 5px #3271ff solid;
|
//border-left: 5px #96afea solid;
|
||||||
background-color: var(--login-bg-color);
|
background-color: rgba(128, 128, 128, 0.5); // 透明色,暗黑模式下也能体现
|
||||||
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pinned {
|
.pinned {
|
||||||
background-color: var(--left-menu-bg-active-color);
|
background-color: rgba(128, 128, 128, 0.5); // 透明色,暗黑模式下也能体现
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-menu-ul {
|
.right-menu-ul {
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-container v-if="showKeFuMessageList" class="kefu">
|
<el-container v-if="showKeFuMessageList" class="kefu">
|
||||||
<el-header>
|
<el-header class="kefu-header">
|
||||||
<div class="kefu-title">{{ conversation.userNickname }}</div>
|
<div class="kefu-title">{{ conversation.userNickname }}</div>
|
||||||
</el-header>
|
</el-header>
|
||||||
<el-main class="kefu-content overflow-visible">
|
<el-main class="kefu-content overflow-visible">
|
||||||
<el-scrollbar ref="scrollbarRef" always height="calc(100vh - 495px)" @scroll="handleScroll">
|
<el-scrollbar ref="scrollbarRef" always @scroll="handleScroll">
|
||||||
<div v-if="refreshContent" ref="innerRef" class="w-[100%] pb-3px">
|
<div v-if="refreshContent" ref="innerRef" class="w-[100%] px-10px">
|
||||||
<!-- 消息列表 -->
|
<!-- 消息列表 -->
|
||||||
<div v-for="(item, index) in getMessageList0" :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">
|
||||||
@ -43,7 +43,9 @@
|
|||||||
class="w-60px h-60px"
|
class="w-60px h-60px"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
:class="{ 'kefu-message': KeFuMessageContentTypeEnum.TEXT === item.contentType }"
|
:class="{
|
||||||
|
'kefu-message': KeFuMessageContentTypeEnum.TEXT === item.contentType
|
||||||
|
}"
|
||||||
class="p-10px"
|
class="p-10px"
|
||||||
>
|
>
|
||||||
<!-- 文本消息 -->
|
<!-- 文本消息 -->
|
||||||
@ -71,10 +73,10 @@
|
|||||||
<MessageItem :message="item">
|
<MessageItem :message="item">
|
||||||
<ProductItem
|
<ProductItem
|
||||||
v-if="KeFuMessageContentTypeEnum.PRODUCT === item.contentType"
|
v-if="KeFuMessageContentTypeEnum.PRODUCT === item.contentType"
|
||||||
:spuId="getMessageContent(item).spuId"
|
|
||||||
:picUrl="getMessageContent(item).picUrl"
|
:picUrl="getMessageContent(item).picUrl"
|
||||||
:price="getMessageContent(item).price"
|
:price="getMessageContent(item).price"
|
||||||
:skuText="getMessageContent(item).introduction"
|
:skuText="getMessageContent(item).introduction"
|
||||||
|
:spuId="getMessageContent(item).spuId"
|
||||||
:title="getMessageContent(item).spuName"
|
:title="getMessageContent(item).spuName"
|
||||||
:titleWidth="400"
|
:titleWidth="400"
|
||||||
class="max-w-70%"
|
class="max-w-70%"
|
||||||
@ -108,8 +110,7 @@
|
|||||||
<Icon class="ml-5px" icon="ep:bottom" />
|
<Icon class="ml-5px" icon="ep:bottom" />
|
||||||
</div>
|
</div>
|
||||||
</el-main>
|
</el-main>
|
||||||
<el-footer height="230px">
|
<el-footer class="kefu-footer">
|
||||||
<div class="h-[100%]">
|
|
||||||
<div class="chat-tools flex items-center">
|
<div class="chat-tools flex items-center">
|
||||||
<EmojiSelectPopover @select-emoji="handleEmojiSelect" />
|
<EmojiSelectPopover @select-emoji="handleEmojiSelect" />
|
||||||
<PictureSelectUpload
|
<PictureSelectUpload
|
||||||
@ -117,14 +118,21 @@
|
|||||||
@send-picture="handleSendPicture"
|
@send-picture="handleSendPicture"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<el-input v-model="message" :rows="6" style="border-style: none" type="textarea" />
|
<el-input
|
||||||
<div class="h-45px flex justify-end">
|
v-model="message"
|
||||||
<el-button class="mt-10px" type="primary" @click="handleSendMessage">发送</el-button>
|
:rows="6"
|
||||||
</div>
|
placeholder="输入消息,Enter发送,Shift+Enter换行"
|
||||||
</div>
|
style="border-style: none"
|
||||||
|
type="textarea"
|
||||||
|
@keyup.enter.prevent="handleSendMessage"
|
||||||
|
/>
|
||||||
</el-footer>
|
</el-footer>
|
||||||
</el-container>
|
</el-container>
|
||||||
<el-empty v-else description="请选择左侧的一个会话后开始" />
|
<el-container v-else class="kefu">
|
||||||
|
<el-main>
|
||||||
|
<el-empty description="请选择左侧的一个会话后开始" />
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@ -262,7 +270,11 @@ const handleSendPicture = async (picUrl: string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 发送文本消息 */
|
/** 发送文本消息 */
|
||||||
const handleSendMessage = async () => {
|
const handleSendMessage = async (event: any) => {
|
||||||
|
// shift 不发送
|
||||||
|
if (event.shiftKey) {
|
||||||
|
return
|
||||||
|
}
|
||||||
// 1. 校验消息是否为空
|
// 1. 校验消息是否为空
|
||||||
if (isEmpty(unref(message.value))) {
|
if (isEmpty(unref(message.value))) {
|
||||||
messageTool.notifyWarning('请输入消息后再发送哦!')
|
messageTool.notifyWarning('请输入消息后再发送哦!')
|
||||||
@ -357,14 +369,29 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.kefu {
|
.kefu {
|
||||||
|
background-color: #fff;
|
||||||
|
width: calc(100% - 300px - 260px);
|
||||||
|
border-left: var(--el-border-color) solid 1px;
|
||||||
|
|
||||||
|
.kefu-header {
|
||||||
|
background: #fbfbfb;
|
||||||
|
box-shadow: 0 0 0 0 #dcdfe6;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
&-title {
|
&-title {
|
||||||
border-bottom: #e4e0e0 solid 1px;
|
font-size: 18px;
|
||||||
height: 60px;
|
font-weight: bold;
|
||||||
line-height: 60px;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-content {
|
&-content {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
.newMessageTip {
|
.newMessageTip {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -447,21 +474,36 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
|
|||||||
border-radius: 12rpx;
|
border-radius: 12rpx;
|
||||||
padding: 8rpx 16rpx;
|
padding: 8rpx 16rpx;
|
||||||
margin-bottom: 16rpx;
|
margin-bottom: 16rpx;
|
||||||
//background-color: #e8e8e8;
|
|
||||||
color: #999;
|
color: #999;
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.kefu-footer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: auto;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border-top: var(--el-border-color) solid 1px;
|
||||||
|
|
||||||
.chat-tools {
|
.chat-tools {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: var(--el-border-color) solid 1px;
|
|
||||||
border-radius: 10px;
|
|
||||||
height: 44px;
|
height: 44px;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
::v-deep(textarea) {
|
::v-deep(textarea) {
|
||||||
resize: none;
|
resize: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.el-input__wrapper) {
|
||||||
|
box-shadow: none !important;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep(.el-textarea__inner) {
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import KeFuConversationList from './KeFuConversationList.vue'
|
import KeFuConversationList from './KeFuConversationList.vue'
|
||||||
import KeFuMessageList from './KeFuMessageList.vue'
|
import KeFuMessageList from './KeFuMessageList.vue'
|
||||||
import MemberBrowsingHistory from './history/MemberBrowsingHistory.vue'
|
import MemberInfo from './member/MemberInfo.vue'
|
||||||
|
|
||||||
export { KeFuConversationList, KeFuMessageList, MemberBrowsingHistory }
|
export { KeFuConversationList, KeFuMessageList, MemberInfo }
|
||||||
|
@ -1,21 +1,24 @@
|
|||||||
<!-- 目录是不是叫 member 好点。然后这个组件是 MemberInfo,里面有浏览足迹 -->
|
<!-- 目录是不是叫 member 好点。然后这个组件是 MemberInfo,里面有浏览足迹 -->
|
||||||
<template>
|
<template>
|
||||||
<div v-show="!isEmpty(conversation)" class="kefu">
|
<el-container class="kefu">
|
||||||
<div class="header-title h-60px flex justify-center items-center">他的足迹</div>
|
<el-header class="kefu-header">
|
||||||
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
|
<el-tabs v-model="activeName" class="kefu-tabs" @tab-click="handleClick">
|
||||||
<el-tab-pane label="最近浏览" name="a" />
|
<el-tab-pane label="最近浏览" name="a" />
|
||||||
<el-tab-pane label="订单列表" name="b" />
|
<el-tab-pane label="订单列表" name="b" />
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
<div>
|
</el-header>
|
||||||
<el-scrollbar ref="scrollbarRef" always height="calc(115vh - 400px)" @scroll="handleScroll">
|
<el-main class="kefu-content">
|
||||||
|
<div v-show="!isEmpty(conversation)">
|
||||||
|
<el-scrollbar ref="scrollbarRef" always @scroll="handleScroll">
|
||||||
<!-- 最近浏览 -->
|
<!-- 最近浏览 -->
|
||||||
<ProductBrowsingHistory v-if="activeName === 'a'" ref="productBrowsingHistoryRef" />
|
<ProductBrowsingHistory v-if="activeName === 'a'" ref="productBrowsingHistoryRef" />
|
||||||
<!-- 订单列表 -->
|
<!-- 订单列表 -->
|
||||||
<OrderBrowsingHistory v-if="activeName === 'b'" ref="orderBrowsingHistoryRef" />
|
<OrderBrowsingHistory v-if="activeName === 'b'" ref="orderBrowsingHistoryRef" />
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<el-empty v-show="isEmpty(conversation)" description="请选择左侧的一个会话后开始" />
|
<el-empty v-show="isEmpty(conversation)" description="请选择左侧的一个会话后开始" />
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@ -91,6 +94,41 @@ const handleScroll = debounce(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.kefu {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 300px !important;
|
||||||
|
background-color: #fff;
|
||||||
|
border-left: var(--el-border-color) solid 1px;
|
||||||
|
|
||||||
|
&-header {
|
||||||
|
background: #fbfbfb;
|
||||||
|
box-shadow: 0 0 0 0 #dcdfe6;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-content {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-tabs {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.header-title {
|
.header-title {
|
||||||
border-bottom: #e4e0e0 solid 1px;
|
border-bottom: #e4e0e0 solid 1px;
|
||||||
}
|
}
|
@ -1,28 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-row :gutter="10">
|
<el-container class="kefu-layout">
|
||||||
<!-- 会话列表 -->
|
<!-- 会话列表 -->
|
||||||
<el-col :span="6">
|
|
||||||
<ContentWrap>
|
|
||||||
<KeFuConversationList ref="keFuConversationRef" @change="handleChange" />
|
<KeFuConversationList ref="keFuConversationRef" @change="handleChange" />
|
||||||
</ContentWrap>
|
|
||||||
</el-col>
|
|
||||||
<!-- 会话详情(选中会话的消息列表) -->
|
<!-- 会话详情(选中会话的消息列表) -->
|
||||||
<el-col :span="12">
|
|
||||||
<ContentWrap>
|
|
||||||
<KeFuMessageList ref="keFuChatBoxRef" @change="getConversationList" />
|
<KeFuMessageList ref="keFuChatBoxRef" @change="getConversationList" />
|
||||||
</ContentWrap>
|
|
||||||
</el-col>
|
|
||||||
<!-- 会员足迹(选中会话的会员足迹) -->
|
<!-- 会员足迹(选中会话的会员足迹) -->
|
||||||
<el-col :span="6">
|
<MemberInfo ref="memberInfoRef" />
|
||||||
<ContentWrap>
|
</el-container>
|
||||||
<MemberBrowsingHistory ref="memberBrowsingHistoryRef" />
|
|
||||||
</ContentWrap>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { KeFuConversationList, KeFuMessageList, MemberBrowsingHistory } from './components'
|
import { KeFuConversationList, KeFuMessageList, MemberInfo } from './components'
|
||||||
import { WebSocketMessageTypeConstants } from './components/tools/constants'
|
import { WebSocketMessageTypeConstants } from './components/tools/constants'
|
||||||
import { KeFuConversationRespVO } from '@/api/mall/promotion/kefu/conversation'
|
import { KeFuConversationRespVO } from '@/api/mall/promotion/kefu/conversation'
|
||||||
import { getRefreshToken } from '@/utils/auth'
|
import { getRefreshToken } from '@/utils/auth'
|
||||||
@ -91,10 +79,10 @@ const getConversationList = () => {
|
|||||||
|
|
||||||
/** 加载指定会话的消息列表 */
|
/** 加载指定会话的消息列表 */
|
||||||
const keFuChatBoxRef = ref<InstanceType<typeof KeFuMessageList>>()
|
const keFuChatBoxRef = ref<InstanceType<typeof KeFuMessageList>>()
|
||||||
const memberBrowsingHistoryRef = ref<InstanceType<typeof MemberBrowsingHistory>>()
|
const memberInfoRef = ref<InstanceType<typeof MemberInfo>>()
|
||||||
const handleChange = (conversation: KeFuConversationRespVO) => {
|
const handleChange = (conversation: KeFuConversationRespVO) => {
|
||||||
keFuChatBoxRef.value?.getNewMessageList(conversation)
|
keFuChatBoxRef.value?.getNewMessageList(conversation)
|
||||||
memberBrowsingHistoryRef.value?.initHistory(conversation)
|
memberInfoRef.value?.initHistory(conversation)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 初始化 */
|
/** 初始化 */
|
||||||
@ -112,9 +100,13 @@ onBeforeUnmount(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.kefu {
|
.kefu-layout {
|
||||||
height: calc(100vh - 165px);
|
position: absolute;
|
||||||
overflow: auto; /* 确保内容可滚动 */
|
flex: 1;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 定义滚动条样式 */
|
/* 定义滚动条样式 */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user