xw_admin/src/components/scCustomer/index.vue
2024-11-18 23:56:12 +08:00

361 lines
8.4 KiB
Vue

<template>
<div class="customerBox">
<el-image class="img" @click="openCustomer" src="/img/CustomerService.svg"></el-image>
<div class="customerView" v-if="customerShow">
<span class="arrow"></span>
<div class="viewBody">
<div class="title">智能客服
<el-icon class="close" size="18" @click="closeCustomer"><el-icon-Close/></el-icon>
</div>
<div class="bodyMain affix-container">
<el-scrollbar ref="scrollbar" height="100%" @scroll="scroll">
<div class="innerRefCom">
<div class="tagList" ref="tagList">
<div class="tagItem" v-for="(item,index) in tagList" :key="index" @click="typeActive(item)">{{item.label}}</div>
</div>
<div class="msgList">
<div class="msgItem" :class="user_id != item.to_user_id?'msgRightItem':''" v-for="(item,index) in msgList" :key="index">
<div class="avatar" v-if="user_id === item.to_user_id">
<el-avatar :size="36" :src="item.from_user.avatar" fit="cover">
<img src="https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png"/>
</el-avatar>
</div>
<div class="msgText">
<div class="msgTitle">
<span class="leftTime" v-if="user_id != item.to_user_id">{{item.created_at}}</span>
{{item.from_user && item.from_user.name?item.from_user.name:'匿名'}}
<span class="time" v-if="user_id === item.to_user_id">{{item.created_at}}</span>
</div>
<div class="textCom">
<div v-html="item.to_message"></div>
</div>
</div>
<div class="avatar" v-if="user_id != item.to_user_id">
<el-avatar :size="36" :src="item.from_user.avatar" fit="cover">
<img src="https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png"/>
</el-avatar>
</div>
</div>
</div>
</div>
</el-scrollbar>
</div>
<div class="footer">
<el-input class="customTextarea" v-model="params.to_message" @keydown="handleKeydown" resize="none" type="textarea" :row="2" placeholder="Shift+Enter换行 请简短描述您的问题"></el-input>
<div class="saveBtn" :class="params.to_message!==''?'saveActive':''" @click="sendCustomer">发 送</div>
</div>
</div>
</div>
</div>
</template>
<script>
import {eventBus} from "@/utils/eventBus";
export default {
name: "index",
data(){
return{
customerShow:false,
params:{
client:2,
type:"",
to_user_id:"",
to_message:"",
},
tagList:[],
msgList:[],
user_id:0,
}
},
mounted() {
let token = this.$TOOL.cookie.get('TOKEN');
if (token && token != null) {
// 登录成功连接ws
let global_callback = function () {};
this.$socketApi.createWebSocket(global_callback);
// 获取新消息
eventBus.$on('sockBack', this.getWsResult);
const userInfo = this.$TOOL.data.get("USER_INFO");
if(userInfo && userInfo.id){
this.user_id = userInfo.id;
}
}
},
unmounted() {
eventBus.$off('sockBack', this.getWsResult);
},
methods:{
getWsResult(res){
if(res.data && (res.data.type == 36 || res.data.type == 37)){
switch(res.data.type) {
case 36:
this.msgList = res.data.rows;
this.scrollDown();
break;
case 37:
this.params.to_user_id = res.data.user.uid;
this.msgList = [{
to_user_id:this.user_id,
from_user:{
name:res.data.user.user_info.name,
avatar:res.data.user.user_info.avatar
},
to_message:res.data.to_message
}]
break;
default:
break;
}
}
},
openCustomer(){
this.customerShow = !this.customerShow;
if(this.customerShow){
this.getAssign();
this.getRecordList();
this.customerType();
// 控制条控制在底部
this.scrollDown();
}
},
closeCustomer(){
this.customerShow = false;
},
async getAssign() {
await this.$API.customer.customer.post();
},
async getRecordList() {
await this.$API.customer.list.post();
},
async customerType() {
const res = await this.$API.customer.typeList.post();
if (res.code == 200) {
this.tagList = res.data;
}
},
typeActive(item){
this.params.type = item.value;
},
handleKeydown(event){
if(event.key === 'Enter' && !event.shiftKey){
event.preventDefault(); // 阻止输入框的默认行为
this.sendCustomer();
}else if(event.key === 'Enter' && event.shiftKey){
this.params.to_message += '';
}
},
async sendCustomer() {
if(this.params.to_message =="") return
const res = await this.$API.customer.send.post(this.params);
if(res.code == 200){
const userInfo = this.$TOOL.data.get("USER_INFO");
this.msgList.push({
to_user_id:-1,
from_user:{
name:userInfo.name,
avatar:userInfo.avatar
},
to_message:this.params.to_message
});
this.params.to_message = "";
this.scrollDown();
}
},
scroll({scrollTop}){
if(scrollTop>10){
this.$refs.tagList.style.position = "absolute";
this.$refs.tagList.style.background = "#fff";
}else{
this.$refs.tagList.style.position = "relative";
this.$refs.tagList.style.background = "";
}
},
scrollDown() {
this.$nextTick(() => {
const wrap = this.$refs.scrollbar;
if(wrap){
const e = wrap.$el.querySelector('.el-scrollbar__wrap')
e.scrollTop = e.scrollHeight;
}
})
},
}
}
</script>
<style scoped lang="scss">
.customerBox{
position: absolute;
right: 40px;
bottom: 80px;
z-index: 1000;
.img{
width: 56px;
height: 56px;
cursor: pointer;
}
.customerView{
width: 380px;
height: 580px;
position: absolute;
right: 0;
bottom: 70px;
background: #fff;
box-shadow: 0 4px 4px rgba(19,103,193,0.3);
border: 1px solid #B7D7F9;
border-radius: 8px;
.viewBody{
display: flex;
flex-direction: column;
height: 100%;
.title{
padding: 15px 10px;
border-bottom: 1px solid #F6F6F6;
font-size: 14px;
font-weight: 500;
display: flex;
align-items: center;
justify-content: space-between;
.close{
cursor: pointer;
}
}
.affix-container {
position: relative;
}
.bodyMain{
flex: 1;
overflow: hidden;
.tagList{
position: relative;
left: 0;
z-index: 0;
display: flex;
flex-wrap: wrap;
padding: 0 10px 10px 10px;
.tagItem{
background: #F4F4F4;
padding: 10px;
border-radius: 4px;
margin: 10px 10px 0 0;
color: #555;
cursor: pointer;
}
}
.msgList{
padding: 10px;
.msgItem{
display: flex;
margin-bottom: 12px;
.avatar{
padding-right: 10px;
}
.msgText{
.msgTitle{
padding: 0 0 8px 0;
color: #555;
.time{
margin-left: 8px;
font-size: 12px;
color: #888;
}
.leftTime{
margin-right: 8px;
font-size: 12px;
color: #888;
}
}
.textCom{
background: #f5f5f5;
border-radius: 4px;
padding: 10px;
display: inline-block;
text-align: left;
}
}
}
.msgRightItem{
justify-content: flex-end;
.avatar{
padding-left: 10px;
padding-right: 0;
}
.msgText{
text-align: right;
.msgTitle{
text-align: right;
}
.textCom{
background: var(--el-color-primary);
color: var(--el-color-white);
text-align: left;
}
}
}
}
}
.footer{
padding: 10px;
border-top: 1px solid #F6F6F6;
position: relative;
.customTextarea{
font-size:13px;
::v-deep .el-textarea__inner{
box-shadow: none;
border: 0;
padding-right: 60px;
}
::v-deep .el-textarea__inner::-webkit-scrollbar{
width: 0;
}
}
.saveBtn{
position: absolute;
bottom:22px;
right: 10px;
z-index: 10;
padding: 7px 15px;
background: #f4f4f5;
color: #A8ABB2;
border-radius: 3px;
cursor: not-allowed;
}
.saveActive{
cursor: pointer;
background: var(--el-color-primary);
color: var(--el-color-white);
}
}
}
}
.arrow{
position: absolute;
bottom: -5px;
right: 12px;
z-index: 1;
}
.arrow:before{
content: "";
position: absolute;
bottom: 0;
right: 12px;
z-index:1;
width: 8px;
height: 8px;
border: 1px solid #B7D7F9;
border-left-color:transparent;
border-top-color:transparent;
transform:rotate(45deg);
background: #fff;
}
}
</style>