优化客服消息
This commit is contained in:
parent
2e332c8986
commit
8e660fd657
@ -7,26 +7,30 @@
|
|||||||
<div class="title">智能客服
|
<div class="title">智能客服
|
||||||
<el-icon class="close" size="18" @click="closeCustomer"><el-icon-Close/></el-icon>
|
<el-icon class="close" size="18" @click="closeCustomer"><el-icon-Close/></el-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="bodyMain">
|
<div class="bodyMain affix-container">
|
||||||
<el-scrollbar>
|
<el-scrollbar ref="scrollbar" height="100%" @scroll="scroll">
|
||||||
<div class="tagList">
|
<div class="innerRefCom">
|
||||||
<div class="tagItem" v-for="(item,index) in tagList" :key="index" @click="typeActive(item)">{{item.label}}</div>
|
<div class="tagList" ref="tagList">
|
||||||
</div>
|
<div class="tagItem" v-for="(item,index) in tagList" :key="index" @click="typeActive(item)">{{item.label}}</div>
|
||||||
<div class="msgList">
|
</div>
|
||||||
<div class="msgItem" :class="user_id != item.to_user_id?'msgRightItem':''" v-for="(item,index) in msgList" :key="index">
|
<div class="msgList">
|
||||||
<div class="avatar" v-if="user_id === item.to_user_id">
|
<div class="msgItem" :class="user_id != item.to_user_id?'msgRightItem':''" v-for="(item,index) in msgList" :key="index">
|
||||||
<el-avatar :size="36" :src="item.from_user.avatar" fit="contain">
|
<div class="avatar" v-if="user_id === item.to_user_id">
|
||||||
<img src="https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png"/>
|
<el-avatar :size="36" :src="item.from_user.avatar" fit="cover">
|
||||||
</el-avatar>
|
<img src="https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png"/>
|
||||||
</div>
|
</el-avatar>
|
||||||
<div class="msgText">
|
</div>
|
||||||
<div class="msgTitle">{{item.from_user && item.from_user.name?item.from_user.name:'匿名'}}</div>
|
<div class="msgText">
|
||||||
<div class="textCom">{{item.to_message}}</div>
|
<div class="msgTitle">{{item.from_user && item.from_user.name?item.from_user.name:'匿名'}}</div>
|
||||||
</div>
|
<div class="textCom">
|
||||||
<div class="avatar" v-if="user_id != item.to_user_id">
|
<div v-html="item.to_message"></div>
|
||||||
<el-avatar :size="36" :src="item.avatar" fit="contain">
|
</div>
|
||||||
<img src="https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png"/>
|
</div>
|
||||||
</el-avatar>
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -53,7 +57,6 @@ export default {
|
|||||||
type:"",
|
type:"",
|
||||||
to_user_id:"",
|
to_user_id:"",
|
||||||
to_message:"",
|
to_message:"",
|
||||||
|
|
||||||
},
|
},
|
||||||
tagList:[],
|
tagList:[],
|
||||||
msgList:[],
|
msgList:[],
|
||||||
@ -79,22 +82,32 @@ export default {
|
|||||||
switch(res.data.type) {
|
switch(res.data.type) {
|
||||||
case 36:
|
case 36:
|
||||||
this.msgList = res.data.rows;
|
this.msgList = res.data.rows;
|
||||||
|
this.scrollDown();
|
||||||
break;
|
break;
|
||||||
case 37:
|
case 37:
|
||||||
this.params.to_user_id = res.data.user.uid;
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
openCustomer(){
|
openCustomer(){
|
||||||
this.customerShow = !this.customerShow;
|
this.customerShow = !this.customerShow;
|
||||||
if(this.customerShow){
|
if(this.customerShow){
|
||||||
this.getAssign();
|
this.getAssign();
|
||||||
this.getRecordList();
|
this.getRecordList();
|
||||||
this.customerType();
|
this.customerType();
|
||||||
|
// 控制条控制在底部
|
||||||
|
this.scrollDown();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
closeCustomer(){
|
closeCustomer(){
|
||||||
@ -107,14 +120,6 @@ export default {
|
|||||||
async getRecordList() {
|
async getRecordList() {
|
||||||
await this.$API.customer.list.post();
|
await this.$API.customer.list.post();
|
||||||
},
|
},
|
||||||
async sendCustomer() {
|
|
||||||
if(this.params.to_message =="") return
|
|
||||||
const res = await this.$API.customer.send.post(this.params);
|
|
||||||
if(res.code == 200){
|
|
||||||
this.tagList.push({});
|
|
||||||
this.params.to_message = "";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async customerType() {
|
async customerType() {
|
||||||
const res = await this.$API.customer.typeList.post();
|
const res = await this.$API.customer.typeList.post();
|
||||||
if (res.code == 200) {
|
if (res.code == 200) {
|
||||||
@ -123,20 +128,57 @@ export default {
|
|||||||
},
|
},
|
||||||
typeActive(item){
|
typeActive(item){
|
||||||
this.params.type = item.value;
|
this.params.type = item.value;
|
||||||
}
|
},
|
||||||
|
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>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.customerBox{
|
.customerBox{
|
||||||
position: fixed;
|
position: absolute;
|
||||||
right: 40px;
|
right: 40px;
|
||||||
bottom: 80px;
|
bottom: 40px;
|
||||||
z-index: 10;
|
z-index: 1000;
|
||||||
.img{
|
.img{
|
||||||
width: 56px;
|
width: 56px;
|
||||||
height: 56px;
|
height: 56px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.customerView{
|
.customerView{
|
||||||
width: 380px;
|
width: 380px;
|
||||||
@ -165,19 +207,26 @@ export default {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.affix-container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
.bodyMain{
|
.bodyMain{
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
.tagList{
|
.tagList{
|
||||||
|
position: relative;
|
||||||
|
left: 0;
|
||||||
|
z-index: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
padding: 0 10px;
|
padding: 0 10px 10px 10px;
|
||||||
.tagItem{
|
.tagItem{
|
||||||
background: #F4F4F4;
|
background: #F4F4F4;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
margin: 10px 10px 0 0;
|
margin: 10px 10px 0 0;
|
||||||
color: #555;
|
color: #555;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.msgList{
|
.msgList{
|
||||||
@ -190,7 +239,7 @@ export default {
|
|||||||
}
|
}
|
||||||
.msgText{
|
.msgText{
|
||||||
.msgTitle{
|
.msgTitle{
|
||||||
padding: 6px 0;
|
padding: 0 0 8px 0;
|
||||||
color: #555;
|
color: #555;
|
||||||
}
|
}
|
||||||
.textCom{
|
.textCom{
|
||||||
|
|||||||
39
src/directives/draggable.js
Normal file
39
src/directives/draggable.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// 自定义拖拉指令
|
||||||
|
export default{
|
||||||
|
mounted(el) {
|
||||||
|
let startX, startY, initialMouseX, initialMouseY;
|
||||||
|
const parent = el.parentElement;
|
||||||
|
|
||||||
|
function onMouseMove(event) {
|
||||||
|
const dx = event.clientX - initialMouseX;
|
||||||
|
const dy = event.clientY - initialMouseY;
|
||||||
|
|
||||||
|
let newLeft = startX + dx;
|
||||||
|
let newTop = startY + dy;
|
||||||
|
|
||||||
|
// 确保拖拽元素不会超出父级容器的范围
|
||||||
|
const maxX = parent.clientWidth - el.offsetWidth;
|
||||||
|
const maxY = parent.clientHeight - el.offsetHeight;
|
||||||
|
|
||||||
|
newLeft = Math.max(0, Math.min(newLeft, maxX));
|
||||||
|
newTop = Math.max(0, Math.min(newTop, maxY));
|
||||||
|
|
||||||
|
el.style.left = newLeft + 'px';
|
||||||
|
el.style.top = newTop + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMouseUp() {
|
||||||
|
document.removeEventListener('mousemove', onMouseMove);
|
||||||
|
document.removeEventListener('mouseup', onMouseUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
el.addEventListener('mousedown', (event) => {
|
||||||
|
startX = el.offsetLeft;
|
||||||
|
startY = el.offsetTop;
|
||||||
|
initialMouseX = event.clientX;
|
||||||
|
initialMouseY = event.clientY;
|
||||||
|
document.addEventListener('mousemove', onMouseMove);
|
||||||
|
document.addEventListener('mouseup', onMouseUp);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -43,6 +43,7 @@ import time from './directives/time'
|
|||||||
import copy from './directives/copy'
|
import copy from './directives/copy'
|
||||||
import number from './directives/number'
|
import number from './directives/number'
|
||||||
import focus from './directives/focus'
|
import focus from './directives/focus'
|
||||||
|
import draggable from './directives/draggable'
|
||||||
import errorHandler from './utils/errorHandler'
|
import errorHandler from './utils/errorHandler'
|
||||||
|
|
||||||
import * as elIcons from '@element-plus/icons-vue'
|
import * as elIcons from '@element-plus/icons-vue'
|
||||||
@ -100,6 +101,7 @@ export default {
|
|||||||
app.directive('copy', copy)
|
app.directive('copy', copy)
|
||||||
app.directive('number', number)
|
app.directive('number', number)
|
||||||
app.directive('focus', focus)
|
app.directive('focus', focus)
|
||||||
|
app.directive('draggable', draggable)
|
||||||
|
|
||||||
//统一注册el-icon图标
|
//统一注册el-icon图标
|
||||||
for(let icon in elIcons){
|
for(let icon in elIcons){
|
||||||
|
|||||||
@ -140,6 +140,7 @@ export default {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
position: relative;
|
||||||
.pageBody{
|
.pageBody{
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -273,4 +274,11 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.customerBoxView{
|
||||||
|
position: absolute;
|
||||||
|
right: 15px;
|
||||||
|
top: 80%;
|
||||||
|
z-index: 2000;
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -26,7 +26,7 @@
|
|||||||
<div class="mainBody">
|
<div class="mainBody">
|
||||||
<div class="mainTitle">龙隆</div>
|
<div class="mainTitle">龙隆</div>
|
||||||
<div class="mainView">
|
<div class="mainView">
|
||||||
<el-scrollbar>
|
<el-scrollbar ref="scrollbar">
|
||||||
<div class="msgList">
|
<div class="msgList">
|
||||||
<div class="msgItem" :class="user_id === item.to_user_id?'msgRightItem':''" v-for="(item,index) in msgList" :key="index">
|
<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">
|
<div class="avatar" v-if="user_id != item.to_user_id">
|
||||||
@ -36,7 +36,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="msgText">
|
<div class="msgText">
|
||||||
<div class="msgTitle">{{item.from_user && item.from_user.name?item.from_user.name:'匿名'}}</div>
|
<div class="msgTitle">{{item.from_user && item.from_user.name?item.from_user.name:'匿名'}}</div>
|
||||||
<div class="textCom">{{item.to_message}}</div>
|
<div class="textCom">
|
||||||
|
<div v-html="item.to_message"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="avatar" v-if="user_id === item.to_user_id">
|
<div class="avatar" v-if="user_id === item.to_user_id">
|
||||||
<el-avatar :size="36" :src="item.from_user.avatar" fit="contain">
|
<el-avatar :size="36" :src="item.from_user.avatar" fit="contain">
|
||||||
@ -102,7 +104,7 @@ export default {
|
|||||||
contactsList:[
|
contactsList:[
|
||||||
{name:"龙隆",msg:"嘻嘻"},
|
{name:"龙隆",msg:"嘻嘻"},
|
||||||
{name:"骁骁",msg:"测试信息"},
|
{name:"骁骁",msg:"测试信息"},
|
||||||
{name:"",msg:"怎么能快速挣够一百万"},
|
{name:"管理员",msg:"怎么能快速挣够一百万"},
|
||||||
{name:"",msg:"真机运行不需要检查更新,真机运行时appid固定为'HBuilder'"},
|
{name:"",msg:"真机运行不需要检查更新,真机运行时appid固定为'HBuilder'"},
|
||||||
{name:"",msg:"真机运行不需要检查更新,真机运行时appid固定为'HBuilder'"},
|
{name:"",msg:"真机运行不需要检查更新,真机运行时appid固定为'HBuilder'"},
|
||||||
],
|
],
|
||||||
@ -129,6 +131,7 @@ export default {
|
|||||||
switch(res.data.type) {
|
switch(res.data.type) {
|
||||||
case 36:
|
case 36:
|
||||||
this.msgList = res.data.rows;
|
this.msgList = res.data.rows;
|
||||||
|
this.scrollDown();
|
||||||
break;
|
break;
|
||||||
case 37:
|
case 37:
|
||||||
this.params.to_user_id = res.data.user.uid;
|
this.params.to_user_id = res.data.user.uid;
|
||||||
@ -143,9 +146,29 @@ export default {
|
|||||||
if(this.params.to_message =="") return
|
if(this.params.to_message =="") return
|
||||||
const res = await this.$API.customer.send.post(this.params);
|
const res = await this.$API.customer.send.post(this.params);
|
||||||
if(res.code == 200){
|
if(res.code == 200){
|
||||||
|
const userInfo = this.$TOOL.data.get("USER_INFO");
|
||||||
|
this.msgList.push({
|
||||||
|
to_user_id:userInfo.id,
|
||||||
|
from_user:{
|
||||||
|
name:userInfo.name,
|
||||||
|
avatar:userInfo.avatar
|
||||||
|
},
|
||||||
|
to_message:this.params.to_message
|
||||||
|
});
|
||||||
this.params.to_message = "";
|
this.params.to_message = "";
|
||||||
|
this.scrollDown();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
scrollDown() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
const wrap = this.$refs.scrollbar;
|
||||||
|
if(wrap){
|
||||||
|
const e = wrap.$el.querySelector('.el-scrollbar__wrap')
|
||||||
|
e.scrollTop = e.scrollHeight;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -247,7 +270,7 @@ export default {
|
|||||||
}
|
}
|
||||||
.msgText{
|
.msgText{
|
||||||
.msgTitle{
|
.msgTitle{
|
||||||
padding: 6px 0;
|
padding:0 0 8px 0;
|
||||||
color: #555;
|
color: #555;
|
||||||
}
|
}
|
||||||
.textCom{
|
.textCom{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user