1988 lines
55 KiB
Vue
1988 lines
55 KiB
Vue
<template>
|
||
<div class="customer-service-page row" style="padding: 35px">
|
||
<fln-table
|
||
:config="state.tableConfig"
|
||
tableType=""
|
||
:hideDataTable="state.hideDataTable"
|
||
@customerServiceSearch="searchCustomer"
|
||
>
|
||
<template #search-header>
|
||
<div
|
||
class="col-12 row font-18"
|
||
style="
|
||
color: #764cf6;
|
||
border-bottom: 1px solid #c1b2e5;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
"
|
||
>
|
||
<div
|
||
class="fl-py-sm font-bold"
|
||
style="border-bottom: 4px solid #764cf6"
|
||
>
|
||
客服
|
||
</div>
|
||
<div
|
||
style="
|
||
font-size: 14px;
|
||
font-weight: 400;
|
||
line-height: 20px;
|
||
color: #46299d;
|
||
cursor: pointer;
|
||
"
|
||
@click="showCreateDialog"
|
||
>
|
||
<span>创建会话</span>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
<template #table-header-box>
|
||
<div
|
||
class="customer-service"
|
||
:style="'height:' + state.serviceAreaHeight + 'px'"
|
||
>
|
||
<div class="customer-list-area">
|
||
<div
|
||
class="customer-list"
|
||
ref="scrollCustomerList"
|
||
:style="
|
||
state.customerList.length == 0 ? 'padding: 13px 21px;' : ''
|
||
"
|
||
>
|
||
<div
|
||
class="customer-list-each"
|
||
v-for="(item, index) in state.customerList"
|
||
:key="index"
|
||
@click="changeCustomer(item, index)"
|
||
v-if="state.customerList.length > 0"
|
||
>
|
||
<div
|
||
class="customer-list-each-leftLine"
|
||
:style="
|
||
item.isActive
|
||
? 'background-color: #46299D;'
|
||
: 'background-color: #C2C2C2;'
|
||
"
|
||
></div>
|
||
<span class="font-14">{{ item.name }}</span>
|
||
<div
|
||
class="customer-list-each-unread-msg-count"
|
||
:style="item.total ? '' : 'background-color:#fff;'"
|
||
>
|
||
<span>{{ item.total }}</span>
|
||
</div>
|
||
<img
|
||
src="@/assets/image/icon/close-circle-grey.png"
|
||
@click.stop="closeChatCustomer(index)"
|
||
/>
|
||
</div>
|
||
<div class="chat-no-data" v-if="state.customerList.length == 0">
|
||
<img src="@/assets/image/customerService/chat-nodata.png" />
|
||
<span>暂时没有消息哦~</span>
|
||
</div>
|
||
</div>
|
||
<div
|
||
v-if="state.customerList.length > 0"
|
||
class="customer-list-back-to-top-btn"
|
||
@click="scrollCustomerListToTop"
|
||
>
|
||
<img src="@/assets/image/customerService/back-to-top.png" />
|
||
<span>顶部</span>
|
||
</div>
|
||
</div>
|
||
<div
|
||
class="chat-service"
|
||
:style="'height:' + state.serviceAreaHeight + 'px'"
|
||
v-if="state.customerList.length > 0"
|
||
>
|
||
<div class="chat-service-userInfo">
|
||
<div class="chat-service-userInfo-detail">
|
||
<div
|
||
class="chat-service-userInfo-detail-each"
|
||
:style="index > 2 ? 'margin: 28px 0 0;' : ''"
|
||
v-for="(item, index) in state.customerInfoList"
|
||
:key="index"
|
||
>
|
||
<span class="font-14">{{ item.label }}:</span>
|
||
<span class="font-14">{{
|
||
item.value ? item.value : "--"
|
||
}}</span>
|
||
</div>
|
||
</div>
|
||
<div class="chat-service-userInfo-photo">
|
||
<span class="font-14">近照:</span>
|
||
<a-image
|
||
style="
|
||
width: 119px;
|
||
height: 59px;
|
||
flex-shrink: 0;
|
||
object-fit: cover;
|
||
"
|
||
:src="state.artistInfo.recentPhoto"
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div
|
||
class="chat-list"
|
||
ref="scrollChatList"
|
||
:style="'height:' + state.chatListHeight + 'px'"
|
||
>
|
||
<div
|
||
class="chat-list-getHistoryRecord-btn"
|
||
@click="getHistoryRecord"
|
||
>
|
||
<img
|
||
class="getHistoryRecord-loading"
|
||
src="@/assets/image/customerService/chat-loading.png"
|
||
v-if="state.loadPrevChat"
|
||
/>
|
||
<img
|
||
class="getHistoryRecord-arrow"
|
||
src="@/assets/image/customerService/arrow-up-purple.png"
|
||
v-if="!state.loadPrevChat && !state.hasNomoreChat"
|
||
/>
|
||
<span class="font-14">{{
|
||
state.loadPrevChat
|
||
? "正在加载中..."
|
||
: state.hasNomoreChat
|
||
? "没有更多啦~"
|
||
: "点击此处唤起聊天记录"
|
||
}}</span>
|
||
</div>
|
||
<div
|
||
class="chat-list-each"
|
||
v-for="(item, index) in state.chatList"
|
||
:key="index"
|
||
:id="'chatEach' + item.ID"
|
||
:class="
|
||
item.eventType == 'send' ? 'chat-list-each-rightAlign' : ''
|
||
"
|
||
>
|
||
<div
|
||
class="chat-tool-tip"
|
||
v-if="item.showToolTip"
|
||
@touchstart.stop
|
||
@click.stop
|
||
:style="
|
||
item.eventType == 'send' ? 'right: 54px;' : 'left: 54px;'
|
||
"
|
||
>
|
||
<div
|
||
class="chat-tool-tip-each"
|
||
@click="handleToolTipClick(item, $event)"
|
||
>
|
||
<n-button
|
||
color="#505050"
|
||
:focusable="false"
|
||
text-color="#fff"
|
||
>转文字</n-button
|
||
>
|
||
</div>
|
||
</div>
|
||
<div
|
||
@click="handleCustomerHeadImgClick(item)"
|
||
class="chat-each-headImg"
|
||
style="cursor: pointer"
|
||
v-if="item.eventType == 'receive'"
|
||
>
|
||
<span
|
||
class="font-14 font-bolder"
|
||
:style="item.name.length > 3 ? 'width:30px;' : ''"
|
||
>{{ item.name }}</span
|
||
>
|
||
</div>
|
||
<div class="chat-each-content">
|
||
<div
|
||
class="chat-each-details"
|
||
@click="handleChatEachClick(item)"
|
||
@mousedown="handleMouseDownChatItem($event, item)"
|
||
@mouseup="handleMouseUpChatItem($event)"
|
||
@mouseout="handleMouseOutChatItem($event)"
|
||
:class="
|
||
item?.message?.msgType == 3
|
||
? item.eventType == 'receive'
|
||
? 'chat-each-details-leftAlign'
|
||
: 'chat-each-details-rightAlign'
|
||
: ''
|
||
"
|
||
>
|
||
<span
|
||
class="font-14 font-regular"
|
||
v-if="item?.message?.msgType == 1"
|
||
>{{
|
||
item.message && item.message.text
|
||
? item.message.text
|
||
: ""
|
||
}}</span
|
||
>
|
||
<a-image
|
||
style="width: 216px; height: 125px; object-fit: cover"
|
||
v-if="item?.message?.msgType == 2"
|
||
:src="
|
||
item.message &&
|
||
item.message.media &&
|
||
item.message.media.length > 0 &&
|
||
item.message.media[0].url
|
||
? item.message.media[0].url
|
||
: ''
|
||
"
|
||
/>
|
||
<aTrumpet
|
||
:isPlay="item.isPlay"
|
||
v-if="
|
||
item.message.msgType == 3 && item.eventType == 'receive'
|
||
"
|
||
color="#fff"
|
||
:size="30"
|
||
></aTrumpet>
|
||
<span
|
||
class="font-14 font-regular"
|
||
v-if="item?.message?.msgType == 3"
|
||
>{{
|
||
item.message &&
|
||
item.message.media &&
|
||
item.message.media.length > 0 &&
|
||
item.message.media[0].duration
|
||
? item.message.media[0].durationText
|
||
: 0
|
||
}}</span
|
||
>
|
||
<aTrumpet
|
||
:isPlay="item.isPlay"
|
||
v-if="
|
||
item?.message?.msgType == 3 && item.eventType == 'send'
|
||
"
|
||
color="#C1C1C1"
|
||
:size="30"
|
||
direction="left"
|
||
></aTrumpet>
|
||
<audio
|
||
v-if="item?.message?.msgType == 3"
|
||
:id="'voiceAudio' + item.ID"
|
||
>
|
||
<source :src="state.voiceSrc" type="audio/mpeg" />
|
||
</audio>
|
||
</div>
|
||
<div
|
||
class="chat-each-details"
|
||
v-if="item?.message?.msgType == 3 && item.voiceToText"
|
||
>
|
||
<span class="font-14 font-regular">{{
|
||
item.voiceToText
|
||
}}</span>
|
||
</div>
|
||
<div class="chat-each-dateTime">
|
||
<span class="font-14 font-regular">{{
|
||
item.createdAt
|
||
}}</span>
|
||
</div>
|
||
</div>
|
||
<div
|
||
class="chat-each-headImg"
|
||
v-if="item.eventType == 'send'"
|
||
style="background-color: #fff"
|
||
>
|
||
<!-- <span class="font-14 font-bolder">{{ item.name }}</span> -->
|
||
<img
|
||
class=""
|
||
src="@/assets/image/customerService/customerServiceStaffHeadImg.png"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="chat-input-area">
|
||
<Upload
|
||
slotType="iconOnly"
|
||
@UploadChange="(e) => uploadImageChange(e)"
|
||
uploadUrl="api/aschat/media/upload"
|
||
>
|
||
</Upload>
|
||
<!-- <img src="@/assets/image/icon/upload-img-grey.png" /> -->
|
||
<n-input
|
||
placeholder="请输入文字"
|
||
v-model:value="state.megSendData.sendMessageText"
|
||
@focus="() => inputMsgOnFocus()"
|
||
@blur="() => inputMsgOnBlur()"
|
||
></n-input>
|
||
<n-button
|
||
color="#46299D"
|
||
class="chat-input-area-send-btn"
|
||
@click="sendMessage(1)"
|
||
:loading="state.sendLoading"
|
||
>发送</n-button
|
||
>
|
||
</div>
|
||
</div>
|
||
<div class="chat-no-data" v-if="state.customerList.length == 0">
|
||
<img src="@/assets/image/customerService/chat-nodata.png" />
|
||
<span>暂时没有消息哦~</span>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</fln-table>
|
||
</div>
|
||
<n-modal
|
||
v-model:show="state.dialogInitiate"
|
||
style="width: 1200px"
|
||
:mask-closable="false"
|
||
preset="card"
|
||
>
|
||
<template #header>
|
||
<div
|
||
class="col-12 row justify-center relative"
|
||
style="border-bottom: 1px solid #dfd7f2"
|
||
>
|
||
<div
|
||
style="
|
||
font-size: 20px;
|
||
font-weight: bold;
|
||
color: #1f2225ff;
|
||
margin: 0 0 15px;
|
||
"
|
||
>
|
||
资料查看
|
||
</div>
|
||
</div>
|
||
</template>
|
||
<div class="customer-service-modal-body">
|
||
<n-button
|
||
color="#46299D"
|
||
class="modal-body-btns view-artist-btn"
|
||
@click="viewArtistInfo"
|
||
>查看画家信息</n-button
|
||
>
|
||
<n-button
|
||
color="#EEE9F8"
|
||
class="modal-body-btns view-artwork-btn"
|
||
text-color="#46299D"
|
||
@click="viewArtworkInfo"
|
||
>查看画作信息</n-button
|
||
>
|
||
</div>
|
||
</n-modal>
|
||
<n-modal
|
||
v-model:show="state.isShowCreateDialog"
|
||
style="width: 1385px"
|
||
:mask-closable="false"
|
||
preset="card"
|
||
:z-index="999"
|
||
>
|
||
<template #header>
|
||
<div
|
||
class="col-12 row justify-center relative"
|
||
style="border-bottom: 1px solid #e9e9e9"
|
||
>
|
||
<div
|
||
style="
|
||
font-size: 20px;
|
||
font-weight: bold;
|
||
color: #1f2225;
|
||
margin: 0 0 15px;
|
||
"
|
||
>
|
||
创建会话
|
||
</div>
|
||
</div>
|
||
</template>
|
||
<div class="artist-search-area">
|
||
<fln-search
|
||
:config="state.artistSearchConfig"
|
||
:btnLoading="state.artistSearchBtnLoading"
|
||
@triggerSearchChange="handleArtistSearchChange"
|
||
></fln-search>
|
||
<div style="margin: 26px 0 0">
|
||
<span>画家选择</span>
|
||
</div>
|
||
<div
|
||
class="artist-list"
|
||
v-if="
|
||
state.artistList.length > 0 &&
|
||
(state.searchObj.ArtistName || state.searchObj.Tnum)
|
||
"
|
||
>
|
||
<div class="artist-list-loading" v-if="state.artistSearchBtnLoading">
|
||
<img
|
||
class="artist-list-loading-image"
|
||
src="@/assets/image/customerService/chat-loading.png"
|
||
/>
|
||
</div>
|
||
<div
|
||
class="artist-list-each"
|
||
v-for="(artistItem, artistIndex) in state.artistList"
|
||
:key="artistIndex"
|
||
>
|
||
<div class="artist-info-detail">
|
||
<div
|
||
class="artist-info-detail-each"
|
||
:style="index > 2 ? 'margin: 28px 0 0;' : ''"
|
||
v-for="(item, index) in artistItem.artistInfoList"
|
||
:key="index"
|
||
>
|
||
<span class="font-14">{{ item.label }}:</span>
|
||
<span class="font-14">{{ item.value ? item.value : "--" }}</span>
|
||
</div>
|
||
</div>
|
||
<div class="artist-info-photo">
|
||
<span class="font-14">近照:</span>
|
||
<a-image
|
||
v-if="artistItem.photo"
|
||
width="119px"
|
||
height="59px"
|
||
:src="artistItem.photo"
|
||
/>
|
||
<span v-if="!artistItem.photo" style="width: 119px; margin: 0"
|
||
>--</span
|
||
>
|
||
</div>
|
||
<div
|
||
class="artist-start-dialog-btn"
|
||
@click="createDialog(artistItem)"
|
||
>
|
||
<span>开始会话</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="artist-list-pagination">
|
||
<n-pagination
|
||
v-if="
|
||
state.artistList.length > 0 &&
|
||
(state.searchObj.ArtistName || state.searchObj.Tnum)
|
||
"
|
||
v-model:page="state.pagination.current"
|
||
v-model:page-size="state.pagination.pageSize"
|
||
:show-size-picker="state.pagination.showSizePicker"
|
||
:show-quick-jumper="state.pagination.showQuickJumper"
|
||
:item-count="state.pagination.total"
|
||
:page-sizes="state.pagination.pageSizeOptions"
|
||
:on-update:page="handlePagination"
|
||
:on-update:page-size="handlePaginationSize"
|
||
/>
|
||
</div>
|
||
<div
|
||
class="no-artist"
|
||
v-if="
|
||
state.artistList.length === 0 ||
|
||
(!state.searchObj.ArtistName && !state.searchObj.Tnum)
|
||
"
|
||
>
|
||
<img src="@/assets/image/customerService/no-artist.png" />
|
||
<text>无相关匹配画家</text>
|
||
</div>
|
||
</div>
|
||
</n-modal>
|
||
<!-- <Tabs
|
||
v-model:showModal="state.showModal"
|
||
:detailInfo="detailInfo"
|
||
@closeFn="closeFn"
|
||
/> -->
|
||
<!-- <a-modal
|
||
v-if="state.artworkModalVisible"
|
||
v-model:visible="state.artworkModalVisible"
|
||
width="1400px"
|
||
class="fl-modal-artwork"
|
||
:bodyStyle="{ height: '90vh' }"
|
||
style="top: 60px"
|
||
:closable="false"
|
||
:maskClosable="false"
|
||
:keyboard="false"
|
||
:footer="null"
|
||
:getContainer="() => $refs.modalView"
|
||
>
|
||
<fl-artwork-modal
|
||
:pageType="state.pageType"
|
||
:fatherData="state.rowData"
|
||
@triggerCloseModal="handleCloseModal"
|
||
></fl-artwork-modal>
|
||
</a-modal> -->
|
||
<div ref="modalView"></div>
|
||
</template>
|
||
<script setup>
|
||
import flnTable from "@/components/flnlayout/table/flntable.vue";
|
||
import aTrumpet from "./components/a-trumpet/a-trumpet.vue";
|
||
// import Tabs from "../../artist/components/tabs.vue";
|
||
// import flArtworkModal from "../../artwork/artworkmodal.vue";
|
||
import {
|
||
reactive,
|
||
onMounted,
|
||
onBeforeUnmount,
|
||
ref,
|
||
getCurrentInstance,
|
||
} from "vue";
|
||
import useWebSocket from "@/utils/webSocket";
|
||
import { Local } from "@/utils/storage";
|
||
import customerServiceApi from "@/api-norm/customerService/index.js";
|
||
import Upload from "@/components/upload";
|
||
import utils from "@/utils/commonUtils";
|
||
import flnSearch from "@/components/flnlayout/search/flnsearch.vue";
|
||
const currentInstance = getCurrentInstance();
|
||
const { $request } = currentInstance.appContext.config.globalProperties;
|
||
const state = reactive({
|
||
btnLoading: false,
|
||
listUrl: {
|
||
resDataField: "data",
|
||
url: "",
|
||
params: [],
|
||
},
|
||
tableConfig: {
|
||
searchConfig: [
|
||
{
|
||
type: "text",
|
||
label: "画家姓名",
|
||
field: "telNum",
|
||
},
|
||
],
|
||
columns: [],
|
||
},
|
||
customerList: [], //客户列表
|
||
hideDataTable: true, //是否隐藏表格
|
||
chatList: [], //聊天列表
|
||
windowHeight: 0, //窗口高度
|
||
serviceAreaHeight: 0, //客服区域高度
|
||
chatListHeight: 0, //聊天区域高度
|
||
dialogInitiate: false, //是否显示模态弹框
|
||
showModal: false, //画家详情模态框
|
||
artworkModalVisible: false, //画作详情模态框显示
|
||
pageType: "view",
|
||
rowData: {},
|
||
megSendData: {
|
||
sendMessageText: "", //输入的文字内容
|
||
}, //要发送的聊天信息
|
||
latestChatId: "", //最早的聊天记录
|
||
newestChatId: "", //最新的聊天记录
|
||
userSessionId: "", //用户会话ID
|
||
userId: "", //用户Id
|
||
hasMoreData: true, //是否还有更多
|
||
pageSize: 10, //每页数据量
|
||
artistInfo: {}, //画家信息
|
||
sessionId: "", //当前用户会话Id
|
||
direction: 2, //查询聊天记录的方向:1=向后查最新,即上拉加载;2=向前查最旧,即下拉刷新
|
||
focusOn: "", //当前聚焦
|
||
sendLoading: false, //发送消息loading
|
||
originalCustomerList: [], //存储快照,以用于筛选时恢复
|
||
loadPrevChat: false, //是否正在加载之前的聊天内容
|
||
hasNomoreChat: false, //是否还有更多聊天记录
|
||
chatLongPressTimeout: null, //聊天内容长按延时事件
|
||
voiceSrc: "", //语音文件地址
|
||
isLongPress: false, // 长按标记
|
||
preventDocumentClick: false, // 防止长按松手时关闭弹窗标记
|
||
autoGetNewMsg: null, // 自动获取新消息
|
||
isShowCreateDialog: false, //是否显示创建会话弹窗
|
||
artistSearchConfig: [
|
||
{
|
||
type: "text",
|
||
label: "画家姓名",
|
||
field: "ArtistName",
|
||
class: "col-4",
|
||
placeholder: "",
|
||
},
|
||
{
|
||
type: "text",
|
||
label: "画家编号",
|
||
field: "Tnum",
|
||
class: "col-4",
|
||
placeholder: "",
|
||
},
|
||
], //画家搜索框配置
|
||
artistSearchBtnLoading: false, //按钮加载中状态
|
||
artistList: [], //的画家列表
|
||
pagination: {
|
||
current: 1,
|
||
pageSize: 5,
|
||
total: 0,
|
||
showSizePicker: true,
|
||
showQuickJumper: true,
|
||
pageSizeOptions: [5],
|
||
}, //分页配置
|
||
searchObj: {
|
||
ArtistName: "",
|
||
Tnum: "",
|
||
}, //搜索内容对象
|
||
});
|
||
let socket = ref(null);
|
||
// 详情数据
|
||
let detailInfo = ref(null);
|
||
const handleResize = () => {
|
||
// console.log("窗口大小已改变:" + window.innerHeight);
|
||
state.windowHeight = window.innerHeight;
|
||
let serviceAreaHeight =
|
||
window.innerHeight -
|
||
document.querySelector(".fixed-nav-bar").getBoundingClientRect().height -
|
||
70 -
|
||
document.querySelector(".fl-mb-xs").getBoundingClientRect().height -
|
||
16 -
|
||
13;
|
||
if (serviceAreaHeight < 300) {
|
||
serviceAreaHeight = 300;
|
||
}
|
||
state.serviceAreaHeight = serviceAreaHeight;
|
||
if (state.customerList.length > 0) {
|
||
let chatListHeight =
|
||
serviceAreaHeight -
|
||
document.querySelector(".chat-service-userInfo").getBoundingClientRect()
|
||
.height -
|
||
document.querySelector(".chat-input-area").getBoundingClientRect()
|
||
.height -
|
||
35 -
|
||
40;
|
||
state.chatListHeight = chatListHeight;
|
||
} else {
|
||
state.chatListHeight = serviceAreaHeight;
|
||
}
|
||
// console.log(serviceAreaHeight, chatListHeight);
|
||
};
|
||
const handleKeyDownEnter = (event) => {
|
||
if (event.key === "Enter") {
|
||
if (state.focusOn == "msgInput" && !state.sendLoading) {
|
||
sendMessage(1);
|
||
}
|
||
}
|
||
};
|
||
const scrollChatList = ref(false);
|
||
onMounted(() => {
|
||
initWebSocket();
|
||
handleResize();
|
||
window.addEventListener("resize", handleResize);
|
||
document.addEventListener("keydown", handleKeyDownEnter);
|
||
document.addEventListener("click", handleDocumentClick);
|
||
customScrollToBottom();
|
||
});
|
||
|
||
onBeforeUnmount(() => {
|
||
if (state.autoGetNewMsg) {
|
||
clearTimeout(state.autoGetNewMsg);
|
||
state.autoGetNewMsg = null;
|
||
}
|
||
window.removeEventListener("resize", handleResize);
|
||
document.removeEventListener("keydown", handleKeyDownEnter);
|
||
document.removeEventListener("click", handleDocumentClick);
|
||
if (socket && socket.value) {
|
||
socket.value.close = () => {
|
||
console.log("WebSocket连接已关闭");
|
||
};
|
||
}
|
||
});
|
||
//点击聊天内容
|
||
const handleChatEachClick = (chatItem) => {
|
||
if (state.isLongPress) {
|
||
state.isLongPress = false;
|
||
return;
|
||
}
|
||
if (chatItem.message.msgType == 3) {
|
||
let audio = document.querySelector("#voiceAudio" + chatItem.ID);
|
||
state.voiceSrc = chatItem.message.media[0].url;
|
||
audio.load();
|
||
if (chatItem.isPlay) {
|
||
audio.pause();
|
||
chatItem.isPlay = false;
|
||
} else {
|
||
audio.play();
|
||
chatItem.isPlay = true;
|
||
setTimeout(() => {
|
||
chatItem.isPlay = false;
|
||
}, chatItem.message.media[0].duration);
|
||
}
|
||
}
|
||
};
|
||
const scrollCustomerList = ref(false);
|
||
const scrollCustomerListToTop = () => {
|
||
if (scrollCustomerList.value) {
|
||
scrollCustomerList.value.scrollTop = 0;
|
||
}
|
||
};
|
||
//点击用户头像
|
||
const handleCustomerHeadImgClick = (chatItem) => {
|
||
console.log(chatItem);
|
||
// state.dialogInitiate = true;
|
||
};
|
||
//点击显示查看画家信息模态框
|
||
const viewArtistInfo = () => {
|
||
state.dialogInitiate = false;
|
||
state.showModal = true;
|
||
};
|
||
//点击隐藏查看画家信息模态框
|
||
const closeFn = () => {
|
||
state.showModal = false;
|
||
state.dialogInitiate = true;
|
||
};
|
||
//点击显示画作详情模态框
|
||
const viewArtworkInfo = () => {
|
||
state.dialogInitiate = false;
|
||
state.artworkModalVisible = true;
|
||
};
|
||
//点击隐藏画作详情模态框
|
||
const handleCloseModal = () => {
|
||
state.artworkModalVisible = false;
|
||
state.dialogInitiate = true;
|
||
};
|
||
//点击发送消息
|
||
const sendMessage = async (msgType, mediaInfo) => {
|
||
state.sendLoading = true;
|
||
let params = {
|
||
sessionId: state.userSessionId, //会话id
|
||
msgType: msgType, //消息类型:1=文本 2=图片 3=音频 4=视频
|
||
text: msgType == 1 ? state.megSendData.sendMessageText : "", //文本内容
|
||
};
|
||
if (msgType != 1) {
|
||
params.media = [
|
||
{
|
||
mediaId: mediaInfo.ID,
|
||
},
|
||
]; //媒体文件列表
|
||
} else {
|
||
if (!state.megSendData.sendMessageText.trim()) {
|
||
state.sendLoading = false;
|
||
return;
|
||
}
|
||
}
|
||
console.log(params);
|
||
const res = await customerServiceApi.sendNewMessage(params);
|
||
if (res.status === 0) {
|
||
state.sendLoading = false;
|
||
console.log(res);
|
||
if (msgType == 1) {
|
||
state.megSendData.sendMessageText = "";
|
||
}
|
||
state.direction = 1;
|
||
getMessageList(2);
|
||
} else {
|
||
state.sendLoading = false;
|
||
message.error('res.message || "操作失败",');
|
||
}
|
||
};
|
||
const getUserMessage = async (newMsg) => {
|
||
const res = await customerServiceApi.getUserMsgStat({});
|
||
if (res && res.status === 0) {
|
||
console.log(res);
|
||
if (res.data && res.data.length > 0) {
|
||
if (Local.get("clearUserList")) {
|
||
let clearUserList = Local.get("clearUserList");
|
||
if (clearUserList.length > 0) {
|
||
res.data.forEach((resItem, resIndex) => {
|
||
clearUserList.forEach((item, index) => {
|
||
if (item.userId == resItem.userId) {
|
||
if (resItem.total > 0) {
|
||
clearUserList.splice(index, 1);
|
||
console.log(clearUserList);
|
||
Local.set("clearUserList", clearUserList);
|
||
} else {
|
||
resItem.hide = true;
|
||
}
|
||
}
|
||
});
|
||
});
|
||
res.data = res.data.filter((item) => {
|
||
return !item.hide;
|
||
});
|
||
}
|
||
}
|
||
res.data.forEach((item, index) => {
|
||
item.isActive = false;
|
||
});
|
||
state.customerList = res.data;
|
||
state.originalCustomerList = [...state.customerList];
|
||
nextTick(() => {
|
||
handleResize();
|
||
});
|
||
if (state.customerList.length > 0) {
|
||
let selectedCustomerIndex = 0;
|
||
if (Local.get("selectedCustomerId")) {
|
||
let selectedCustomerId = Local.get("selectedCustomerId");
|
||
state.customerList.forEach((item, index) => {
|
||
if (item.userId == selectedCustomerId) {
|
||
selectedCustomerIndex = index;
|
||
}
|
||
});
|
||
}
|
||
if (newMsg) {
|
||
state.customerList[selectedCustomerIndex].isActive = true;
|
||
Local.set(
|
||
"selectedCustomerId",
|
||
state.customerList[selectedCustomerIndex].userId
|
||
);
|
||
if (state.customerList[selectedCustomerIndex].total > 0) {
|
||
if (!state.userSessionId) {
|
||
state.userSessionId =
|
||
state.customerList[selectedCustomerIndex].sessionId;
|
||
state.userId = state.customerList[selectedCustomerIndex].userId;
|
||
getArtistInfo();
|
||
}
|
||
state.direction = 1;
|
||
getMessageList(2);
|
||
} else {
|
||
if (state.autoGetNewMsg) {
|
||
clearTimeout(state.autoGetNewMsg);
|
||
state.autoGetNewMsg = null;
|
||
}
|
||
state.autoGetNewMsg = setTimeout(() => {
|
||
getUserMessage(true);
|
||
}, 1000 * 60 * 5);
|
||
}
|
||
} else {
|
||
changeCustomer(
|
||
state.customerList[selectedCustomerIndex],
|
||
selectedCustomerIndex
|
||
);
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
message.error('res.message || "操作失败",');
|
||
}
|
||
};
|
||
//初始化websocket
|
||
const initWebSocket = () => {
|
||
let socketUrl = "wss://artist.fontree.cn/api/aschat/ws";
|
||
if (import.meta.env.VITE_API_URL === "http://114.218.158.24:9020/") {
|
||
socketUrl = "wss://artisttest.fontree.cn/api/aschat/ws";
|
||
}
|
||
socket.value = new WebSocket(socketUrl);
|
||
socket.value.onopen = () => {
|
||
console.log("WebSocket连接已建立");
|
||
const token = Local.get("token");
|
||
console.log(token);
|
||
socket.value.send(
|
||
JSON.stringify({
|
||
type: 5,
|
||
content: {
|
||
auth: token,
|
||
domain: "fontree",
|
||
},
|
||
})
|
||
);
|
||
};
|
||
socket.value.onmessage = socketMessage;
|
||
socket.value.onclose = () => {
|
||
console.log("WebSocket连接已关闭");
|
||
setTimeout(() => {
|
||
socket.value = new WebSocket(socketUrl);
|
||
}, 1000);
|
||
};
|
||
socket.value.onerror = (error) => {
|
||
console.error("WebSocket error:", error);
|
||
socket.value.close();
|
||
setTimeout(() => {
|
||
socket.value = new WebSocket(socketUrl);
|
||
}, 1000);
|
||
};
|
||
};
|
||
const socketMessage = (event) => {
|
||
if (event.data) {
|
||
console.log(event);
|
||
let result = JSON.parse(event.data);
|
||
if (result.type == 0) {
|
||
//连接成功
|
||
state.sessionId = result.content.sessionId;
|
||
getUserMessage();
|
||
} else if (result.type == 4) {
|
||
//收到新消息
|
||
getUserMessage(true);
|
||
}
|
||
}
|
||
};
|
||
//点击切换用户
|
||
const changeCustomer = (customerItem, customerIndex) => {
|
||
state.hasNomoreChat = false;
|
||
Local.set("selectedCustomerId", customerItem.userId);
|
||
state.customerList.forEach((item, index) => {
|
||
item.isActive = false;
|
||
});
|
||
state.customerList[customerIndex].isActive = true;
|
||
state.chatList = [];
|
||
state.userSessionId = customerItem.sessionId;
|
||
state.userId = customerItem.userId;
|
||
getMessageList(1);
|
||
getArtistInfo();
|
||
// getDetail();
|
||
};
|
||
//观察新消息是否已读
|
||
const observeElementsVisibility = (element, selectedCustomerIndex) => {
|
||
const observer = new IntersectionObserver((entries, observer) => {
|
||
entries.forEach((entry) => {
|
||
if (entry.isIntersecting) {
|
||
console.log(`Element ${entry.target.id} is visible in the viewport.`);
|
||
state.customerList[selectedCustomerIndex].total =
|
||
state.customerList[selectedCustomerIndex].total - 1;
|
||
observer.unobserve(element);
|
||
} else {
|
||
console.log(
|
||
`Element ${entry.target.id} is not visible in the viewport.`
|
||
);
|
||
}
|
||
});
|
||
});
|
||
observer.observe(element);
|
||
};
|
||
//获取聊天信息
|
||
const getMessageList = async (flag) => {
|
||
let params = {
|
||
sessionId: state.userSessionId,
|
||
pageSize: state.pageSize,
|
||
};
|
||
if (state.chatList.length == 0) {
|
||
params.recent = true;
|
||
} else {
|
||
if (flag == 1) {
|
||
//查最近10条
|
||
params.recent = true;
|
||
} else if (flag == 2) {
|
||
//上拉加载——获取当前最后消息往后的所有新消息
|
||
params.direction = state.direction;
|
||
params.currentId = state.newestChatId;
|
||
} else if (flag == 3) {
|
||
//下拉刷新——获取当前最前消息往前的所有旧消息
|
||
params.direction = state.direction;
|
||
params.currentId = state.latestChatId;
|
||
}
|
||
}
|
||
const res = await customerServiceApi.getMessageList(params);
|
||
if (res && res.status === 0) {
|
||
console.log(res);
|
||
if (res.data.length > 0) {
|
||
res.data.forEach((item, index) => {
|
||
if (item.userId == state.userId) {
|
||
item.eventType = "receive";
|
||
} else {
|
||
item.eventType = "send";
|
||
}
|
||
if (item?.message?.media[0]?.duration) {
|
||
let durationFormat = utils.division(
|
||
item.message.media[0].duration,
|
||
1000,
|
||
0
|
||
);
|
||
if (durationFormat <= 60) {
|
||
durationFormat = durationFormat + "s";
|
||
} else if (durationFormat > 60 && durationFormat <= 3600) {
|
||
durationFormat =
|
||
Math.floor(utils.division(durationFormat, 60)) +
|
||
"min" +
|
||
(durationFormat % 60) +
|
||
"s";
|
||
} else if (durationFormat > 3600) {
|
||
durationFormat =
|
||
Math.floor(utils.division(durationFormat, 3600)) +
|
||
"h" +
|
||
Math.floor(utils.division(durationFormat % 3600, 60)) +
|
||
"min" +
|
||
((durationFormat % 3600) % 60) +
|
||
"s";
|
||
}
|
||
item.message.media[0].durationText = durationFormat;
|
||
}
|
||
});
|
||
}
|
||
if (res.data.length < state.pageSize) {
|
||
state.hasMoreData = false;
|
||
} else {
|
||
state.hasMoreData = true;
|
||
}
|
||
if (state.chatList.length == 0) {
|
||
state.chatList = res.data;
|
||
} else {
|
||
if (flag == 1) {
|
||
state.chatList = res.data;
|
||
} else if (flag == 2) {
|
||
state.chatList = state.chatList.concat(res.data);
|
||
} else if (flag == 3) {
|
||
state.chatList.unshift(...res.data);
|
||
}
|
||
}
|
||
if (state.chatList.length > 0) {
|
||
state.latestChatId = state.chatList[0].ID;
|
||
state.newestChatId = state.chatList[state.chatList.length - 1].ID;
|
||
}
|
||
let selectedCustomerIndex = 0;
|
||
if (Local.get("selectedCustomerId")) {
|
||
let selectedCustomerId = Local.get("selectedCustomerId");
|
||
state.customerList.forEach((item, index) => {
|
||
if (item.userId == selectedCustomerId) {
|
||
selectedCustomerIndex = index;
|
||
}
|
||
});
|
||
}
|
||
// if (flag == 2) {
|
||
// console.log(res.data);
|
||
// if (res.data.length > 0) {
|
||
// res.data.forEach((item, index) => {
|
||
// nextTick(() => {
|
||
// console.log(item.ID);
|
||
// let eachChatItem = document.querySelector("#chatEach" + item.ID);
|
||
// console.log(eachChatItem);
|
||
// const unobserve = observeElementsVisibility(
|
||
// eachChatItem,
|
||
// selectedCustomerIndex
|
||
// );
|
||
// });
|
||
// });
|
||
// }
|
||
// } else {
|
||
state.customerList[selectedCustomerIndex].total = 0;
|
||
// }
|
||
if (flag == 3) {
|
||
nextTick(() => {
|
||
let currentChat = document.querySelector(
|
||
"#chatEach" + params.currentId
|
||
);
|
||
let getHistoryRecordBtn = document.querySelector(
|
||
".chat-list-getHistoryRecord-btn"
|
||
);
|
||
if (scrollChatList.value) {
|
||
// console.log(scrollChatList.value.scrollHeight);
|
||
if (currentChat) {
|
||
scrollChatList.value.scrollTop =
|
||
currentChat.offsetTop - getHistoryRecordBtn.offsetHeight;
|
||
}
|
||
state.loadPrevChat = false;
|
||
} else {
|
||
state.loadPrevChat = false;
|
||
}
|
||
if (res.data.length == 0) {
|
||
state.hasNomoreChat = true;
|
||
} else {
|
||
state.hasNomoreChat = false;
|
||
}
|
||
});
|
||
return;
|
||
}
|
||
customScrollToBottom();
|
||
} else {
|
||
state.loadPrevChat = false;
|
||
message.error('res.message || "操作失败",');
|
||
}
|
||
|
||
if (state.autoGetNewMsg) {
|
||
clearTimeout(state.autoGetNewMsg);
|
||
state.autoGetNewMsg = null;
|
||
}
|
||
if (state.customerList.length > 0) {
|
||
state.autoGetNewMsg = setTimeout(() => {
|
||
getUserMessage(true);
|
||
}, 1000 * 60 * 5);
|
||
}
|
||
|
||
if (state.autoGetNewMsg) {
|
||
clearTimeout(state.autoGetNewMsg);
|
||
state.autoGetNewMsg = null;
|
||
}
|
||
if (state.customerList.length > 0) {
|
||
state.autoGetNewMsg = setTimeout(() => {
|
||
getUserMessage(true);
|
||
}, 1000 * 60 * 5);
|
||
}
|
||
};
|
||
//点击关闭与对应用户聊天框
|
||
const closeChatCustomer = (index) => {
|
||
let clearUserList = [];
|
||
let update = true;
|
||
if (Local.get("clearUserList")) {
|
||
clearUserList = Local.get("clearUserList");
|
||
clearUserList.forEach((item) => {
|
||
if (state.customerList[index].userId == item.userId) {
|
||
update = false;
|
||
}
|
||
});
|
||
}
|
||
if (update) {
|
||
clearUserList.push(state.customerList[index]);
|
||
}
|
||
Local.set("clearUserList", clearUserList);
|
||
state.customerList.splice(index, 1);
|
||
if (state.customerList.length > 0) {
|
||
changeCustomer(state.customerList[0], 0);
|
||
} else {
|
||
state.chatList = [];
|
||
state.userSessionId = "";
|
||
state.userId = "";
|
||
Local.set("selectedCustomerId", "");
|
||
}
|
||
};
|
||
//上传图片
|
||
const uploadImageChange = (event) => {
|
||
// console.log(event)
|
||
sendMessage(2, event.data);
|
||
};
|
||
//滑动到底部
|
||
const customScrollToBottom = () => {
|
||
setTimeout(() => {
|
||
if (scrollChatList.value) {
|
||
// console.log(scrollChatList.value.scrollHeight);
|
||
scrollChatList.value.scrollTop = scrollChatList.value.scrollHeight;
|
||
}
|
||
}, 100);
|
||
};
|
||
//获取画家简要信息
|
||
const getArtistInfo = async () => {
|
||
let params = {
|
||
userId: state.userId,
|
||
};
|
||
const res = await customerServiceApi.getArtistInfo(params);
|
||
if (res && res.status === 0) {
|
||
console.log(res);
|
||
state.artistInfo = res.data;
|
||
state.customerInfoList = [];
|
||
Object.keys(state.artistInfo).forEach((item, index) => {
|
||
let label;
|
||
if (item == "tnum") {
|
||
label = "画家编号";
|
||
} else if (item == "artistName") {
|
||
label = "画家姓名";
|
||
} else if (item == "age") {
|
||
label = "年龄";
|
||
} else if (item == "sex") {
|
||
label = "性别";
|
||
} else if (item == "nativePlace") {
|
||
label = "籍贯";
|
||
} else if (item == "telNum") {
|
||
label = "电话";
|
||
}
|
||
if (label) {
|
||
state.customerInfoList.push({
|
||
label: label,
|
||
value: state.artistInfo[item],
|
||
});
|
||
}
|
||
});
|
||
} else {
|
||
message.error('res.message || "操作失败",');
|
||
}
|
||
};
|
||
//发送消息输入框获得焦点
|
||
const inputMsgOnFocus = () => {
|
||
state.focusOn = "msgInput";
|
||
};
|
||
//发送消息输入框失去焦点
|
||
const inputMsgOnBlur = () => {
|
||
state.focusOn = "";
|
||
};
|
||
//获取之前的数据
|
||
const getHistoryRecord = () => {
|
||
if (state.hasNomoreChat || state.loadPrevChat) {
|
||
return;
|
||
}
|
||
state.loadPrevChat = true;
|
||
state.direction = 2;
|
||
getMessageList(3);
|
||
};
|
||
//获取画家详细信息
|
||
const getDetail = async () => {
|
||
await $request.HTTP.artist
|
||
.artistDetail({ Uid: String(state.userId) })
|
||
.then((res) => {
|
||
if (res.status == 0) {
|
||
detailInfo.value = res.data;
|
||
} else {
|
||
message.error(res.msg);
|
||
}
|
||
})
|
||
.catch((e) => {
|
||
message.error(e.response.data.msg || "操作失败,请稍后再试");
|
||
});
|
||
};
|
||
//搜索用户
|
||
const searchCustomer = (searchText) => {
|
||
state.customerList = [...state.originalCustomerList];
|
||
if (!searchText.trim()) {
|
||
return;
|
||
}
|
||
if (state.customerList.length > 0) {
|
||
state.customerList = state.customerList.filter((item, index) => {
|
||
item.isMatch = false;
|
||
if (item.name.indexOf(searchText) > -1) {
|
||
item.isMatch = true;
|
||
}
|
||
return item.isMatch;
|
||
});
|
||
}
|
||
};
|
||
//长按聊天内容展示上方弹窗
|
||
const showChatToolTip = (chatItem) => {
|
||
if (chatItem.message.msgType == 3) {
|
||
chatItem.showToolTip = true;
|
||
}
|
||
};
|
||
//处理鼠标按下聊天内容事件
|
||
const handleMouseDownChatItem = (e, chatItem) => {
|
||
// e.stopPropagation();
|
||
// e.preventDefault();
|
||
state.chatLongPressTimeout = setTimeout(() => {
|
||
state.isLongPress = true;
|
||
state.preventDocumentClick = true;
|
||
showChatToolTip(chatItem);
|
||
}, 500);
|
||
};
|
||
//处理鼠标抬起聊天内容事件
|
||
const handleMouseUpChatItem = (e) => {
|
||
if (state.chatLongPressTimeout) {
|
||
clearTimeout(state.chatLongPressTimeout);
|
||
state.chatLongPressTimeout = null;
|
||
}
|
||
setTimeout(() => {
|
||
state.preventDocumentClick = false;
|
||
}, 0);
|
||
};
|
||
//处理鼠标离开聊天内容事件
|
||
const handleMouseOutChatItem = (e) => {
|
||
if (state.chatLongPressTimeout) {
|
||
clearTimeout(state.chatLongPressTimeout);
|
||
state.chatLongPressTimeout = null;
|
||
}
|
||
state.isLongPress = false;
|
||
};
|
||
//点击聊天上方弹窗按钮
|
||
const handleToolTipClick = async (chatItem, event) => {
|
||
event.stopPropagation();
|
||
if (chatItem?.message?.media[0]?.convText) {
|
||
chatItem.voiceToText = chatItem.message.media[0].convText;
|
||
chatItem.showToolTip = false;
|
||
} else {
|
||
let params = {
|
||
mediaId: chatItem.message.media[0].mediaId,
|
||
};
|
||
// console.log(params);
|
||
const res = await customerServiceApi.voiceToText(params);
|
||
if (res?.status === 0) {
|
||
chatItem.voiceToText = res.data.convText;
|
||
chatItem.showToolTip = false;
|
||
}
|
||
}
|
||
};
|
||
// 处理document点击事件
|
||
const handleDocumentClick = () => {
|
||
if (state.preventDocumentClick) {
|
||
return;
|
||
}
|
||
if (state.chatList && state.chatList.length > 0) {
|
||
state.chatList.forEach((item) => {
|
||
if (item.showToolTip) {
|
||
item.showToolTip = false;
|
||
}
|
||
});
|
||
}
|
||
};
|
||
|
||
//点击显示创建会话弹窗
|
||
const showCreateDialog = () => {
|
||
state.isShowCreateDialog = true;
|
||
};
|
||
|
||
//处理搜索
|
||
const handleArtistSearchChange = ({ obj }) => {
|
||
console.log(obj);
|
||
state.searchObj = obj;
|
||
state.pagination.current = 1;
|
||
getArtistSearchResultList();
|
||
};
|
||
|
||
const handlePagination = (page) => {
|
||
state.pagination.current = page;
|
||
getArtistSearchResultList();
|
||
};
|
||
const handlePaginationSize = (pageSize) => {
|
||
state.pagination.pageSize = pageSize;
|
||
getArtistSearchResultList();
|
||
};
|
||
|
||
//获取画家搜索结果列表
|
||
const getArtistSearchResultList = async () => {
|
||
state.artistSearchBtnLoading = true;
|
||
let params = {
|
||
artistName: state.searchObj.ArtistName, //画家姓名
|
||
tnum: state.searchObj.Tnum, //画家编号
|
||
page: state.pagination.current,
|
||
pageSize: state.pagination.pageSize,
|
||
isRealName: 1,
|
||
idname: true,
|
||
};
|
||
const res = await customerServiceApi.getArtistSearchResultList(params);
|
||
if (res && res.status === 0) {
|
||
state.artistSearchBtnLoading = false;
|
||
console.log(res);
|
||
state.artistList = res.data.Data;
|
||
state.pagination.total = res.data.Total;
|
||
if (state?.artistList?.length > 0) {
|
||
state.artistList.forEach((artistItem) => {
|
||
const artistInfoList = [];
|
||
const fieldOrder = [
|
||
{
|
||
key: "realName",
|
||
label: "画家姓名",
|
||
process: (v) => v.replace(/#/g, ""),
|
||
},
|
||
{ key: "sex", label: "性别" },
|
||
{ key: "tnum", label: "画家编号" },
|
||
{ key: "age", label: "年龄" },
|
||
{ key: "telNum", label: "手机号" },
|
||
{ key: "nativePlace", label: "籍贯" },
|
||
];
|
||
fieldOrder.forEach(({ key, label, process }) => {
|
||
if (artistItem.hasOwnProperty(key)) {
|
||
let value = artistItem[key];
|
||
if (process) value = process(value);
|
||
artistInfoList.push({ label, value });
|
||
}
|
||
});
|
||
artistItem.artistInfoList = artistInfoList;
|
||
});
|
||
}
|
||
} else {
|
||
state.artistSearchBtnLoading = false;
|
||
message.error('res.message || "操作失败",');
|
||
}
|
||
};
|
||
|
||
//点击开始会话
|
||
const createDialog = (artistInfo) => {
|
||
state.isShowCreateDialog = false;
|
||
let hadChat = false;
|
||
if (state?.customerList?.length > 0) {
|
||
state.customerList.forEach((item, index) => {
|
||
if (item.userId === artistInfo.userId) {
|
||
// console.log(state.customerList[index],index)
|
||
hadChat = true;
|
||
changeCustomer(state.customerList[index], index);
|
||
}
|
||
});
|
||
}
|
||
if (!hadChat) {
|
||
state.customerList.unshift({
|
||
artistUid: artistInfo.artistUid,
|
||
name: artistInfo.realName.replace(/#/g, ""),
|
||
sessionId: artistInfo.userId.toString(),
|
||
total: 0,
|
||
userId: artistInfo.userId,
|
||
});
|
||
changeCustomer(state.customerList[0], 0);
|
||
}
|
||
if (Local.get("clearUserList")) {
|
||
let clearUserList = Local.get("clearUserList");
|
||
if (clearUserList.length > 0) {
|
||
clearUserList.forEach((item, index) => {
|
||
if (item.userId == artistInfo.userId) {
|
||
clearUserList.splice(index, 1);
|
||
console.log(clearUserList);
|
||
Local.set("clearUserList", clearUserList);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
state.searchObj = {
|
||
ArtistName: "",
|
||
Tnum: "",
|
||
};
|
||
};
|
||
</script>
|
||
<style scoped lang="scss">
|
||
.customer-service-page {
|
||
:deep(.fl-px-md) {
|
||
width: unset !important;
|
||
text-align: left !important;
|
||
padding: 0 !important;
|
||
margin: 0 40px 0 0;
|
||
}
|
||
|
||
:deep(.fl-mt-md) {
|
||
padding: 0 !important;
|
||
}
|
||
|
||
:deep(.fl-mt-sm) {
|
||
width: 368px !important;
|
||
}
|
||
|
||
.customer-service {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: flex-start;
|
||
justify-content: flex-start;
|
||
width: 100%;
|
||
|
||
.customer-list-area {
|
||
height: 100%;
|
||
position: relative;
|
||
box-sizing: border-box;
|
||
|
||
.customer-list::-webkit-scrollbar {
|
||
width: 0;
|
||
}
|
||
|
||
.customer-list::-webkit-scrollbar {
|
||
height: 0;
|
||
}
|
||
|
||
.customer-list {
|
||
padding: 13px 21px 76px;
|
||
border-right: 1px solid #e0e0e5;
|
||
height: 100%;
|
||
overflow: scroll;
|
||
box-sizing: border-box;
|
||
width: 238px;
|
||
|
||
.customer-list-each {
|
||
width: 186px;
|
||
height: 42px;
|
||
border: 1px solid #e0e0e5;
|
||
border-radius: 3px;
|
||
margin: 0 0 10px;
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: relative;
|
||
cursor: pointer;
|
||
|
||
.customer-list-each-leftLine {
|
||
width: 5px;
|
||
height: 100%;
|
||
position: absolute;
|
||
left: 0;
|
||
top: 0;
|
||
}
|
||
|
||
span {
|
||
color: #343639;
|
||
line-height: 1;
|
||
}
|
||
|
||
.customer-list-each-unread-msg-count {
|
||
width: 14px;
|
||
height: 14px;
|
||
border-radius: 50%;
|
||
background-color: #cf3050;
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin: 0 0 0 4px;
|
||
|
||
span {
|
||
color: #fff;
|
||
font-size: 10px;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
|
||
img {
|
||
position: absolute;
|
||
right: 10px;
|
||
top: 50%;
|
||
margin-top: -8px;
|
||
width: 16px;
|
||
height: 16px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.customer-list-back-to-top-btn {
|
||
position: absolute;
|
||
right: 23px;
|
||
bottom: 23px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
box-shadow: 0px 3px 6px 1px rgba(0, 0, 0, 0.12);
|
||
width: 48px;
|
||
height: 48px;
|
||
border-radius: 50%;
|
||
background-color: #fff;
|
||
cursor: pointer;
|
||
|
||
img {
|
||
width: 16px;
|
||
height: 16px;
|
||
margin: 4px 0 0;
|
||
}
|
||
|
||
span {
|
||
font-size: 10px;
|
||
color: #46299d;
|
||
margin: 2px 0 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
.chat-service {
|
||
position: relative;
|
||
width: 100%;
|
||
padding: 13px 22px 22px 22px;
|
||
|
||
.chat-service-userInfo {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: flex-start;
|
||
justify-content: flex-start;
|
||
background-color: #f9f9fd;
|
||
width: 100%;
|
||
|
||
.chat-service-userInfo-detail {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: flex-start;
|
||
flex-wrap: wrap;
|
||
flex: 1;
|
||
padding: 18px 22px;
|
||
|
||
.chat-service-userInfo-detail-each {
|
||
width: calc(100% / 3);
|
||
display: flex;
|
||
flex-direction: row;
|
||
min-width: 132px;
|
||
|
||
span {
|
||
line-height: 1;
|
||
}
|
||
}
|
||
|
||
.chat-service-userInfo-detail-each span:nth-child(1) {
|
||
margin: 0 10px 0 0;
|
||
min-width: 70px;
|
||
display: inline-block;
|
||
}
|
||
}
|
||
|
||
.chat-service-userInfo-photo {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: flex-start;
|
||
justify-content: flex-start;
|
||
padding: 18px 22px;
|
||
flex-shrink: 0;
|
||
|
||
span {
|
||
margin: 0 10px 0 0;
|
||
min-width: 70px;
|
||
display: inline-block;
|
||
}
|
||
}
|
||
}
|
||
|
||
.chat-list::-webkit-scrollbar {
|
||
width: 0;
|
||
}
|
||
|
||
.chat-list::-webkit-scrollbar {
|
||
height: 0;
|
||
}
|
||
|
||
.chat-list {
|
||
position: relative;
|
||
overflow: scroll;
|
||
margin: 20px 0;
|
||
|
||
.chat-list-getHistoryRecord-btn {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 0 0 20px;
|
||
cursor: pointer;
|
||
|
||
@keyframes chatLoading {
|
||
0% {
|
||
transform: rotate(0deg);
|
||
}
|
||
50% {
|
||
transform: rotate(180deg);
|
||
}
|
||
100% {
|
||
transform: rotate(360deg);
|
||
}
|
||
}
|
||
|
||
.getHistoryRecord-loading {
|
||
width: 19px;
|
||
height: 19px;
|
||
margin: 0 0 7px;
|
||
animation-name: chatLoading;
|
||
animation-iteration-count: infinite;
|
||
animation-timing-function: linear;
|
||
animation-duration: 2s;
|
||
}
|
||
|
||
.getHistoryRecord-arrow {
|
||
width: 19px;
|
||
height: 11px;
|
||
margin: 0 0 7px;
|
||
}
|
||
|
||
span {
|
||
color: #46299d;
|
||
}
|
||
}
|
||
|
||
.chat-tool-tip {
|
||
position: absolute;
|
||
top: -50px;
|
||
background-color: #0000;
|
||
z-index: 10036;
|
||
background-color: #505050;
|
||
border-radius: 10px;
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: flex-start;
|
||
|
||
.chat-tool-tip-each {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
:deep(.n-button .n-button__border) {
|
||
border: 0 !important;
|
||
}
|
||
|
||
span {
|
||
color: #e0e0e0;
|
||
line-height: 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
.chat-tool-tip::after {
|
||
content: "";
|
||
position: absolute;
|
||
background-color: #505050;
|
||
width: 14px;
|
||
height: 14px;
|
||
bottom: -4px;
|
||
left: 50%;
|
||
margin-left: -7px;
|
||
-webkit-transform: rotate(45deg);
|
||
transform: rotate(45deg);
|
||
border-radius: 2px;
|
||
z-index: -1;
|
||
}
|
||
|
||
.chat-list-each {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: flex-start;
|
||
justify-content: flex-start;
|
||
margin: 0 0 38px;
|
||
position: relative;
|
||
|
||
.chat-each-headImg {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 44px;
|
||
height: 44px;
|
||
border-radius: 50%;
|
||
flex-shrink: 0;
|
||
background-color: #46299d;
|
||
|
||
span {
|
||
color: #fff;
|
||
line-height: 1;
|
||
}
|
||
}
|
||
|
||
.chat-each-content {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
justify-content: flex-start;
|
||
margin: 0 10px;
|
||
|
||
.chat-each-details {
|
||
box-shadow: 0 3px 6px 1px rgba(0, 0, 0, 0.08);
|
||
max-width: 452px;
|
||
padding: 14px 10px;
|
||
border-radius: 0 8px 8px 8px;
|
||
margin: 0 0 6px;
|
||
background-color: #b5a9d9;
|
||
box-sizing: border-box;
|
||
|
||
span {
|
||
color: #fff;
|
||
line-height: 1;
|
||
}
|
||
|
||
.chat-voice-icon {
|
||
width: 14px;
|
||
height: 20px;
|
||
margin: 0 0 0 10px;
|
||
}
|
||
|
||
.chat-voice-icon-leftAlign {
|
||
transform: rotateZ(180deg);
|
||
margin: 0 10px 0 0;
|
||
}
|
||
}
|
||
|
||
.chat-each-details-leftAlign {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: flex-start;
|
||
max-width: 304px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.chat-each-dateTime {
|
||
span {
|
||
color: #bababa;
|
||
line-height: 27px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.chat-list-each-rightAlign {
|
||
justify-content: flex-end;
|
||
|
||
.chat-each-headImg {
|
||
}
|
||
|
||
.chat-each-content {
|
||
align-items: flex-end;
|
||
|
||
.chat-each-details {
|
||
background-color: #fff;
|
||
border-radius: 8px 0 8px 8px;
|
||
|
||
span {
|
||
color: #1a1a1a;
|
||
}
|
||
}
|
||
|
||
.chat-each-details-rightAlign {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
max-width: 304px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.chat-each-dateTime {
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.chat-input-area {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
position: absolute;
|
||
left: 22px;
|
||
bottom: 22px;
|
||
width: calc(100% - 44px);
|
||
box-sizing: border-box;
|
||
|
||
:deep(.ant-upload-select-picture-card) {
|
||
border: 0;
|
||
width: 37px;
|
||
height: 34px;
|
||
margin: 0 20px 0 0;
|
||
}
|
||
|
||
img {
|
||
width: 37px;
|
||
height: 34px;
|
||
margin: 0 20px 0 0;
|
||
}
|
||
|
||
.chat-input-area-send-btn {
|
||
margin: 0 0 0 20px;
|
||
width: 161px;
|
||
height: 34px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.customer-service-modal-body {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 42px 0 65px;
|
||
|
||
.modal-body-btns {
|
||
width: 332px;
|
||
height: 42px;
|
||
}
|
||
|
||
.view-artist-btn {
|
||
}
|
||
|
||
.view-artwork-btn {
|
||
margin: 36px 0 0;
|
||
}
|
||
}
|
||
|
||
.chat-no-data {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
img {
|
||
margin: 0 0 20px 0;
|
||
max-width: 190px;
|
||
max-height: 190px;
|
||
}
|
||
span {
|
||
font-size: 16px;
|
||
font-weight: 500;
|
||
color: #cdcdcd;
|
||
}
|
||
}
|
||
|
||
.artist-search-area {
|
||
:deep(.fl-px-md) {
|
||
width: 94px !important;
|
||
text-align: left !important;
|
||
padding: 0 !important;
|
||
}
|
||
:deep(.fl-mt-sm) {
|
||
width: calc(100% / 3 - 20px) !important;
|
||
margin: 0 20px 0 0;
|
||
}
|
||
:deep(.fl-mt-sm:nth-last-child(1)) {
|
||
margin: 0;
|
||
}
|
||
.artist-list {
|
||
height: 517px;
|
||
position: relative;
|
||
.artist-list-loading {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background-color: rgba(224, 224, 224, 0.4);
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
@keyframes chatLoading {
|
||
0% {
|
||
transform: rotate(0deg);
|
||
}
|
||
50% {
|
||
transform: rotate(180deg);
|
||
}
|
||
100% {
|
||
transform: rotate(360deg);
|
||
}
|
||
}
|
||
|
||
.artist-list-loading-image {
|
||
width: 19px;
|
||
height: 19px;
|
||
margin: 0 0 7px;
|
||
animation-name: chatLoading;
|
||
animation-iteration-count: infinite;
|
||
animation-timing-function: linear;
|
||
animation-duration: 2s;
|
||
}
|
||
}
|
||
.artist-list-each {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: flex-start;
|
||
background-color: #f9f9fd;
|
||
width: 100%;
|
||
margin: 10px 0 0;
|
||
|
||
.artist-info-detail {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: flex-start;
|
||
flex-wrap: wrap;
|
||
flex: 1;
|
||
padding: 18px 22px;
|
||
|
||
.artist-info-detail-each {
|
||
width: calc(100% / 3);
|
||
display: flex;
|
||
flex-direction: row;
|
||
min-width: 132px;
|
||
|
||
span {
|
||
line-height: 1;
|
||
}
|
||
}
|
||
|
||
.artist-info-detail-each span:nth-child(1) {
|
||
margin: 0 10px 0 0;
|
||
min-width: 70px;
|
||
display: inline-block;
|
||
}
|
||
}
|
||
|
||
.artist-info-photo {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: flex-start;
|
||
justify-content: flex-start;
|
||
padding: 18px 22px;
|
||
flex-shrink: 0;
|
||
|
||
span {
|
||
margin: 0 10px 0 0;
|
||
min-width: 70px;
|
||
display: inline-block;
|
||
}
|
||
|
||
:deep(.ant-image-img) {
|
||
object-fit: cover;
|
||
}
|
||
}
|
||
|
||
.artist-start-dialog-btn {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
margin: 0 90px;
|
||
span {
|
||
font-size: 14rpx;
|
||
font-weight: 400;
|
||
line-height: 20px;
|
||
color: #46299d;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.artist-list-pagination {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
padding: 8px 0 0;
|
||
}
|
||
.no-artist {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 208px 0 236px;
|
||
img {
|
||
width: 83px;
|
||
height: 83px;
|
||
}
|
||
text {
|
||
font-size: 14px;
|
||
font-weight: 400;
|
||
line-height: 20px;
|
||
color: #c2c2c2;
|
||
margin: 8px 0 0;
|
||
}
|
||
}
|
||
}
|
||
</style>
|