361 lines
8.4 KiB
Vue
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>
|