管理端客服
This commit is contained in:
@ -6,3 +6,26 @@ export function getUsers(params) {
|
|||||||
params
|
params
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 消息改为已读
|
||||||
|
export function readMsg(params) {
|
||||||
|
return request({
|
||||||
|
url: '/chat/readMsg',
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 获取和某个好友的聊天记录
|
||||||
|
export function getChatRecords(params) {
|
||||||
|
return request({
|
||||||
|
url: '/chat/getChatRecords',
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 给某人发送信息
|
||||||
|
export function sendMsg(data) {
|
||||||
|
return request({
|
||||||
|
url: '/chat/send',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -7,29 +7,33 @@
|
|||||||
class="user_item"
|
class="user_item"
|
||||||
v-for="item in userList"
|
v-for="item in userList"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
@click="active(item.id)"
|
@click="active(item)"
|
||||||
:class="activeId === item.id ? 'active' : ''"
|
:class="activeId === item.id ? 'active' : ''"
|
||||||
>
|
>
|
||||||
<div class="user_item_l">
|
<div class="user_item_l">
|
||||||
<div class="el-avatar">
|
<div class="el-avatar">
|
||||||
<span
|
|
||||||
:class="item.status ? 'el-avatar2' : ''"
|
|
||||||
v-if="item.msgNoReadCount != 0"
|
|
||||||
></span>
|
|
||||||
<img :src="item.icon" alt="" />
|
<img :src="item.icon" alt="" />
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<div class="phone">{{ item.username }}</div>
|
<div class="phone">
|
||||||
<div class="company">{{ num }}--msgNoReadCount:{{item.msgNoReadCount}}</div>
|
{{ item.username
|
||||||
|
}}<el-tag
|
||||||
|
style="margin-left: 15px"
|
||||||
|
size="mini"
|
||||||
|
v-if="item.msgNoReadCount != 0"
|
||||||
|
>{{ item.msgNoReadCount }}条未读</el-tag
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="company">{{ numTop }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="user_item_r">14:19</div>
|
<!-- <div class="user_item_r">14:19</div> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="18">
|
<el-col :span="18">
|
||||||
<div class="box_r">
|
<div class="box_r">
|
||||||
<!-- <div class="box" v-if="!activeId">
|
<div class="box" v-if="!activeId">
|
||||||
<div class="famous-box">
|
<div class="famous-box">
|
||||||
<img src="~@/assets/image/chat.png" width="300" />
|
<img src="~@/assets/image/chat.png" width="300" />
|
||||||
<p>
|
<p>
|
||||||
@ -38,34 +42,41 @@
|
|||||||
加油吧! ......
|
加油吧! ......
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div> -->
|
</div>
|
||||||
<div class="box">
|
<div class="box" v-else>
|
||||||
<div id="content" class="content" @scroll="scroll">
|
<div
|
||||||
|
v-loading="loading"
|
||||||
|
id="content"
|
||||||
|
class="content"
|
||||||
|
@scroll="scroll"
|
||||||
|
>
|
||||||
<div v-for="(item, index) in info" :key="index">
|
<div v-for="(item, index) in info" :key="index">
|
||||||
<div class="info_r info_default" v-if="item.type == 'leftinfo'">
|
<div class="info_r info_default" v-if="item.type == 'leftinfo'">
|
||||||
<span class="circle circle_r"></span>
|
<span class="circle circle_r el-avatar">
|
||||||
|
<img :src="icon" alt="" />
|
||||||
|
</span>
|
||||||
<div class="con_r con_text">
|
<div class="con_r con_text">
|
||||||
<div>{{ item.content }}</div>
|
<div>{{ item.sendText }}</div>
|
||||||
<div v-for="(item2, index) in item.question" :key="index">
|
<!-- <div v-for="(item2, index) in item.question" :key="index">
|
||||||
<div class="con_que">
|
<div class="con_que">
|
||||||
<div class="czkj-question-msg">
|
<div class="czkj-question-msg">
|
||||||
{{ item2.index }}
|
{{ item2.index }}
|
||||||
{{ item2.content }}
|
{{ item2.sendText }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="time_r">{{ item.time }}</div>
|
<div class="time_r">{{ item.msgTime }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="info_l" v-if="item.type == 'rightinfo'">
|
<div class="info_l" v-if="item.type == 'rightinfo'">
|
||||||
<div class="con_r con_text">
|
<div class="con_r con_text">
|
||||||
<span class="con_l">{{ item.content }}</span>
|
<span class="con_l">{{ item.sendText }}</span>
|
||||||
<span class="circle circle_l">
|
<span class="circle circle_l el-avatar">
|
||||||
<img src class="pic_l" />
|
<img :src="avatar" alt="" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="time_l">{{ item.time }}</div>
|
<div class="time_l">{{ item.msgTime }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -84,9 +95,9 @@
|
|||||||
"
|
"
|
||||||
id="text"
|
id="text"
|
||||||
v-model="customerText"
|
v-model="customerText"
|
||||||
@keyup.enter="sentMsg()"
|
@keyup.enter="sentMsg"
|
||||||
></textarea>
|
></textarea>
|
||||||
<button @click="sentMsg()" class="setproblems">
|
<button @click="sentMsg" class="setproblems">
|
||||||
<span style="vertical-align: 4px">发 送</span>
|
<span style="vertical-align: 4px">发 送</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -98,62 +109,53 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getUsers } from '@/api/service';
|
import { mapGetters } from 'vuex';
|
||||||
|
import { getUsers, readMsg, getChatRecords, sendMsg } from '@/api/service';
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
num: 0,
|
numTop: null,
|
||||||
queryParams: {
|
query: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
},
|
},
|
||||||
a: {},
|
userTotal: 0,
|
||||||
total: 0,
|
queryParams: {
|
||||||
|
userId: null,
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
},
|
||||||
|
msgTotal: 0,
|
||||||
|
loading: true,
|
||||||
|
info: [],
|
||||||
|
icon: '', // 用户头像
|
||||||
userList: [],
|
userList: [],
|
||||||
activeId: '1424606573631770624',
|
activeId: '', // 当前用户ID
|
||||||
customerText: '',
|
customerText: '',
|
||||||
info: [
|
|
||||||
// {
|
|
||||||
// type: 'leftinfo',
|
|
||||||
// time: this.getTodayTime(),
|
|
||||||
// name: 'robot',
|
|
||||||
// content: '',
|
|
||||||
// question: []
|
|
||||||
// }
|
|
||||||
],
|
|
||||||
timer: null,
|
|
||||||
robotQuestion: [
|
|
||||||
{ id: 1, content: '客户资料完善后是由谁来审批', index: 1 },
|
|
||||||
{ id: 2, content: '客户资料审批一直不通过', index: 2 },
|
|
||||||
{ id: 3, content: '客户资料审批需要多长时间', index: 3 },
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
content: '注册网站时需要一次填写完所有的客户资料吗',
|
|
||||||
index: 4,
|
|
||||||
},
|
|
||||||
{ id: 5, content: '注册时使用的手机号变更怎么办', index: 5 },
|
|
||||||
],
|
|
||||||
robotAnswer: [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
content:
|
|
||||||
'答案客户资料完善后是由谁来审批,答案客户资料完善后是由谁来审批,答案客户资料完善后是由谁来审批',
|
|
||||||
index: 1,
|
|
||||||
},
|
|
||||||
{ id: 2, content: '测试', index: 2 },
|
|
||||||
{ id: 3, content: '测试', index: 3 },
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
content: '3333333',
|
|
||||||
index: 4,
|
|
||||||
},
|
|
||||||
{ id: 5, content: '44444444', index: 5 },
|
|
||||||
],
|
|
||||||
textarea: '',
|
|
||||||
path: 'ws://192.168.0.125:1919/webStock/' + this.$store.state.user.userId,
|
path: 'ws://192.168.0.125:1919/webStock/' + this.$store.state.user.userId,
|
||||||
socket: '',
|
socket: '',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
activeId(newVal, oldVal) {
|
||||||
|
this.queryParams.pageNum = 1;
|
||||||
|
if (newVal == '' || newVal == null) return;
|
||||||
|
const info = this.userList.find((item) => {
|
||||||
|
return item.id == newVal;
|
||||||
|
});
|
||||||
|
if (info.msgNoReadCount != 0) {
|
||||||
|
// 消息改为已读
|
||||||
|
readMsg({ userId: newVal }).then((res) => {
|
||||||
|
info.msgNoReadCount = 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.queryParams.userId = newVal;
|
||||||
|
this.getMsgList();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['avatar']),
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// 初始化
|
// 初始化
|
||||||
this.init();
|
this.init();
|
||||||
@ -161,77 +163,78 @@ export default {
|
|||||||
// this.userList = data.list
|
// this.userList = data.list
|
||||||
// this.total = data.total
|
// this.total = data.total
|
||||||
// })
|
// })
|
||||||
|
},
|
||||||
|
created() {
|
||||||
this.getUserList();
|
this.getUserList();
|
||||||
},
|
},
|
||||||
created() {},
|
|
||||||
methods: {
|
methods: {
|
||||||
scroll(e) {
|
scroll(e) {
|
||||||
// console.log(e.srcElement.scrollTop);
|
// console.log(e.srcElement.scrollTop);
|
||||||
this.num = e.srcElement.scrollTop;
|
this.numTop = e.srcElement.scrollTop;
|
||||||
|
if (e.srcElement.scrollTop == 0) {
|
||||||
|
if (
|
||||||
|
this.queryParams.pageNum * this.queryParams.pageSize >=
|
||||||
|
this.msgTotal
|
||||||
|
)
|
||||||
|
return this.msgInfo('已经加载完成');
|
||||||
|
this.queryParams.pageNum++;
|
||||||
|
this.getMsgList();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
// 获取和某个好友的聊天记录
|
||||||
|
getMsgList() {
|
||||||
|
this.loading = true;
|
||||||
|
getChatRecords(this.queryParams).then(({ data }) => {
|
||||||
|
// 时间转时间戳
|
||||||
|
data.list.map((item) => {
|
||||||
|
item.sendTime = new Date(item.sendTime).getTime();
|
||||||
|
});
|
||||||
|
// 时间戳排序
|
||||||
|
data.list.sort(function (a, b) {
|
||||||
|
return a.sendTime > b.sendTime ? 1 : -1;
|
||||||
|
});
|
||||||
|
console.log(data.list);
|
||||||
|
this.info = [...data.list, ...this.info];
|
||||||
|
this.msgTotal = data.total;
|
||||||
|
this.loading = false;
|
||||||
|
if (this.queryParams.pageNum == 1) {
|
||||||
|
// 消息到底
|
||||||
|
this.$nextTick(() => {
|
||||||
|
var contentHeight = document.getElementById('content');
|
||||||
|
console.log(contentHeight.scrollHeight);
|
||||||
|
contentHeight.scrollTop = contentHeight.scrollHeight;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 获取用户列表
|
||||||
getUserList() {
|
getUserList() {
|
||||||
getUsers(this.queryParams).then(({ data }) => {
|
getUsers(this.query).then(({ data }) => {
|
||||||
this.userList = data.list;
|
this.userList = data.list;
|
||||||
this.total = data.total;
|
this.userTotal = data.total;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 用户发送消息
|
// 用户发送消息
|
||||||
sentMsg() {
|
sentMsg() {
|
||||||
clearTimeout(this.timer);
|
|
||||||
let text = this.customerText.trim();
|
let text = this.customerText.trim();
|
||||||
if (text != '') {
|
if (text != '') {
|
||||||
var obj = {
|
var obj = {
|
||||||
|
msgTime: this.getTodayTime(),
|
||||||
type: 'rightinfo',
|
type: 'rightinfo',
|
||||||
time: this.getTodayTime(),
|
sendText: text,
|
||||||
content: text,
|
receiverUserId: this.activeId,
|
||||||
};
|
};
|
||||||
this.info.push(obj);
|
sendMsg(obj).then((res) => {
|
||||||
this.appendRobotMsg(this.customerText);
|
this.info.push(obj);
|
||||||
this.customerText = '';
|
this.customerText = '';
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
var contentHeight = document.getElementById('content');
|
var contentHeight = document.getElementById('content');
|
||||||
contentHeight.scrollTop = contentHeight.scrollHeight;
|
console.log(contentHeight.scrollHeight);
|
||||||
|
contentHeight.scrollTop = contentHeight.scrollHeight;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 机器人回答消息
|
|
||||||
appendRobotMsg(text) {
|
|
||||||
clearTimeout(this.timer);
|
|
||||||
text = text.trim();
|
|
||||||
let answerText = '';
|
|
||||||
let flag;
|
|
||||||
for (let i = 0; i < this.robotAnswer.length; i++) {
|
|
||||||
if (this.robotAnswer[i].content.indexOf(text) != -1) {
|
|
||||||
flag = true;
|
|
||||||
answerText = this.robotAnswer[i].content;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if (flag) {
|
|
||||||
// let obj = {
|
|
||||||
// type: 'leftinfo',
|
|
||||||
// time: this.getTodayTime(),
|
|
||||||
// name: 'robot',
|
|
||||||
// content: answerText,
|
|
||||||
// question: []
|
|
||||||
// };
|
|
||||||
// this.info.push(obj);
|
|
||||||
// } else {
|
|
||||||
// answerText = '您可能想问:';
|
|
||||||
// let obj = {
|
|
||||||
// type: 'leftinfo',
|
|
||||||
// time: this.getTodayTime(),
|
|
||||||
// name: 'robot',
|
|
||||||
// content: answerText,
|
|
||||||
// question: this.robotQuestion
|
|
||||||
// };
|
|
||||||
// this.info.push(obj);
|
|
||||||
// }
|
|
||||||
this.$nextTick(() => {
|
|
||||||
var contentHeight = document.getElementById('content');
|
|
||||||
contentHeight.scrollTop = contentHeight.scrollHeight;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getTodayTime() {
|
getTodayTime() {
|
||||||
// 获取当前时间
|
// 获取当前时间
|
||||||
var day = new Date();
|
var day = new Date();
|
||||||
@ -261,8 +264,11 @@ export default {
|
|||||||
seconds;
|
seconds;
|
||||||
return time;
|
return time;
|
||||||
},
|
},
|
||||||
active(id) {
|
active(item) {
|
||||||
this.activeId = id;
|
this.customerText = '';
|
||||||
|
this.activeId = item.id;
|
||||||
|
this.info = [];
|
||||||
|
this.icon = item.icon;
|
||||||
},
|
},
|
||||||
init: function () {
|
init: function () {
|
||||||
if (typeof WebSocket === 'undefined') {
|
if (typeof WebSocket === 'undefined') {
|
||||||
@ -286,10 +292,25 @@ export default {
|
|||||||
console.log('连接错误');
|
console.log('连接错误');
|
||||||
},
|
},
|
||||||
getMessage(msg) {
|
getMessage(msg) {
|
||||||
console.log(msg.data);
|
const data = JSON.parse(msg.data);
|
||||||
console.log(JSON.parse(msg.data));
|
console.log(JSON.parse(msg.data));
|
||||||
this.a = JSON.parse(msg.data);
|
const msgInfo = JSON.parse(msg.data);
|
||||||
// sendUserId
|
// 遍历用户列表 新消息的用户未读数量加加
|
||||||
|
if (msgInfo.sendUserId === this.activeId) {
|
||||||
|
this.info.push(msgInfo);
|
||||||
|
// 消息已读
|
||||||
|
readMsg({ userId: msgInfo.sendUserId }).then((res) => {
|
||||||
|
const info = this.userList.find((item) => {
|
||||||
|
return item.id == msgInfo.sendUserId;
|
||||||
|
});
|
||||||
|
info.msgNoReadCount = 0;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const userInfo = this.userList.find((item) => {
|
||||||
|
return item.id == data.sendUserId;
|
||||||
|
});
|
||||||
|
userInfo.msgNoReadCount++;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
send: function (params) {
|
send: function (params) {
|
||||||
this.socket.send(params);
|
this.socket.send(params);
|
||||||
@ -330,15 +351,6 @@ export default {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
.el-avatar {
|
.el-avatar {
|
||||||
position: relative;
|
position: relative;
|
||||||
span {
|
|
||||||
width: 7px;
|
|
||||||
height: 7px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: red;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
img {
|
img {
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
Reference in New Issue
Block a user