<template>
<div style="height: 100%; width: 100%; background-color: #fff">
<div class="wrap">
<!-- 头部 -->
<div class="titleBox">
<img
src="@/assets/image/avatar.png"
style="argin: 10px 20px 10px 20px;width: 40px;height: 40px;"
class="head_portrait"
/>
<span style="color: #fff;font-size: 15px;">官方客服</span>
</div>
<!-- 底部 -->
<div class="infoBox">
<!-- 左边用户列表 -->
<div class="userList">
<div class="searchBox">
<el-input placeholder="请输入内容" v-model="search" class="input-with-select" size="mini" @input="inquire">
<i class="el-icon-search el-input__icon" slot="suffix" @click="handleIconClick" />
</el-input>
<!-- <el-button-->
<!-- icon="el-icon-plus"-->
<!-- size="mini"-->
<!-- type="primary"-->
<!-- @click="dialogVisible = true"-->
<!-- ></el-button>-->
</div>
<div class="userListBox" ref="scrollUserBox" id="userBox">
<div v-if="list!=null && list.length > 0" v-for="(item, index) in list" :key="index"
@click="getAct(item, index)" :class="item.opposUserId == act ? 'userFlexAct' : 'userFlex'" >
<el-badge :hidden="item.unreadCount ==0" :value="item.unreadCount" :max="99" class="item">
<div>
<img :src="item.avatar" class="head_portrait2" style="margin-left: 20px ; " />
</div>
</el-badge>
<div style="margin-right: 10px;"></div>
<div style="margin-right: 40px">
<div style="color: #565656" class="nickName">
{
{ item.nickName }}
</div>
<div class="userInfo" v-if="item.messageType==1" >{
{item.message}}</div>
<div class="userInfo" v-if="item.messageType==2" >[商品]</div>
<div class="userInfo" v-if="item.messageType==3" >[图片]</div>
<div class="userInfo" v-if="item.messageType==4" >[订单]</div>
</div>
<div style="margin-right: 10px; font-size: 14px; color: #ccc">
{
{ formatDate(item.createTime) }}
</div>
</div>
</div>
</div>
<!-- 右边输入框和信息展示 -->
<div class="infoList">
<!-- 信息 -->
<div class="infoTop" ref="scrollBox" id="box">
<div v-for="(item, index) in info" :key="index">
<!-- 显示时间信息 -->
<div class="chatInfoRight1 " v-if="shouldShowTime(index)">
{
{ formatDate1(item.createTime) }}
</div>
<div :class="(item.fromUserId == item.userId && item.fromUserType != 1) ? 'chatInfoRight' :'chatInfoLeft' ">
<!-- <img :src="item.avatar" alt="头像" class="head_portrait2" />-->
<img :src="(item.fromUserId == item.userId && item.fromUserType != 1) ? require('@/assets/image/avatar.png') : item.avatar" class="head_portrait2" style="margin-left: 20px;" />
<div :class="(item.fromUserId == item.userId && item.fromUserType != 1) ? 'chatRight' : 'chatLeft'">
<!-- 文字 -->
<div class="text" v-if="item.messageType==1" >{
{item.message}}</div>
<!-- 商品 -->
<div v-if="item.messageType==2" class="text">
<!-- @click="openUrl(`/pages/goodsDetail?id=${parseMessage(item.message).productId}`)"-->
<div class="goods1"
style="width: 200px;height: 70px;margin: 0 auto;background-color: #FFF;display: flex; ">
<image-preview :src="item.message" :width="60" :height="60"/>
<div class="right1"
style="flex: 1;margin: auto 0;height: 60px;margin-left: 10px;">
<div style="color: #333;height: 30px;line-height: 30px; font-size: 14px; " class="right_title">
{
{parseMessage(item.message).productName}}
</div>
<div style="height: 30px;color: #ff0000;line-height: 30px; font-size: 12px;">
¥{
{parseMessage(item.message).merchantPrice}}</div>
</div>
</div>
</div>
<!-- 图片 -->
<div v-if="item.messageType==3" class="text">
<image-preview :src="item.message" :width="70" :height="70"/>
</div>
</div>
</div>
</div>
</div>
<!-- 输入框 -->
<div class="infoBottom">
<div class="infoIcon">
<mesImg v-if='isshow==1?true:false' v-model="imgUrl"/>
<!-- <i @click="extend('发送商品')" class="el-icon-sell"></i>-->
<!-- <i @click="extend('设置')" class="el-icon-setting"></i>-->
<!-- <i @click="extend('聊天记录')" class="el-icon-chat-dot-round"></i>-->
<!-- <i @click="extend('更多选项')" class="el-icon-more-outline"></i>-->
</div>
<textarea maxlength="255"
show-word-limit
type="textarea"
class="infoInput"
v-model="textarea"
@keydown.enter.exact="handlePushKeyword($event)"
@keyup.ctrl.enter="lineFeed"
:disabled='isshow==1?false:true'
/>
<div class="fasong" @click="setUp(1)" v-show="isshow==1?true:false">发送</div>
</div>
</div>
</div>
</div>
<!-- 搜索框边 + 号弹框 -->
<el-dialog
title="选择需要添加的联系人"
:visible.sync="dialogVisible"
width="30%"
:modal="false"
>
<span>自定义页面,还没想好写什么功能</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false"
>确 定</el-button
>
</span>
</el-dialog>
</div>
</template>
<script>
import {getMesList,getMesInfo} from "@/api/ums/umsUser";
import axios from 'axios'
export default {
watch: {
imgUrl(newVal, oldVal) {
if (newVal) {
this.textarea =this.$constants.baseURL + this.imgUrl;
this.setUp(3);
}
},
},
data() {
return {
socket: null,
imgUrl: "",
queryParams:{
pageNum: 1,
pageSize: 10,
userId:this.$store.getters.userId,
userType:2,
},
queryParamsUser:{
pageNum: 1,
pageSize: 10,
userId:this.$store.getters.userId,
userType:2,
},
// 在线状态
state: 1,
//搜索用户
search: "",
user: "",
info: [],
list:[],
total:0,
userIdserTotal:0,
//用户点击选中变色
act: Number,
// 加号弹框
dialogVisible: false,
//历史信息
userInfoList: [],
//输入框
textarea: "",
//滚动条距离顶部距离
scrollTop: 0,
//滚动条距离顶部距离
scrollUserTop: 0,
//发送和输入显隐
isshow:0
};
},
created() {
this.socket = new WebSocket('ws://192.168.1.140:9092/front/websocket/2:'+this.$store.getters.userId); // 替换成你的WebSocket服务器地址
this.socket.onmessage = this.handleMessage;
this.handleMesList()
// this.setUserPageScrollTo()
},
methods: {
// 计算是否显示时间信息的函数
shouldShowTime(index) {
if (index === 0) {
return true; // 第一条消息肯定要显示时间信息
}
const currentItem = this.info[index];
const prevItem = this.info[index - 1];
const currentTime = new Date(currentItem.createTime);
const prevTime = new Date(prevItem.createTime);
const timeDiff = currentTime - prevTime; // 计算时间差,单位为毫秒
const minutesDiff = Math.floor(timeDiff / 1000 / 60); // 转换为分钟
return minutesDiff >= 3; // 如果时间差大于等于3分钟,则显示时间信息
},
// 解析消息字符串为对象
parseMessage(message) {
try {
return JSON.parse(message);
} catch (error) {
console.error("Error parsing message:", error);
return {}; // 返回空对象以避免渲染错误
}
},
handleMessage(event) {
try {
const message = JSON.parse(event.data);
// 判断发的信息是不是当前会话
if (this.user.opposUserId == message.userId){
this.getAct(this.user);
}else {
this.queryParams.pageNum = 1
this.handleMesList();
}
// 处理收到的消息
// 例如,将消息添加到相应的聊天记录中
} catch (error) {
// console.error('Received message is not in JSON format:', event.data);
}
},
// 左侧列表
handleMesList(){
getMesList(this.queryParams).then(response => {
this.list = response.rows
this.total = response.total
});
// 直接调用不生效:因为你历史数据刚给,渲染的时候盒子高度还没有成型,所以直接调用拿不到,用个定时器让他在下一轮循环中调用,盒子就已经生成了
this.$nextTick(() => { // 一定要用nextTick
this.setUserPageScrollTo();
//页面滚动条距离顶部高度等于这个盒子的高度
this.$refs.scrollUserBox.scrollUserTop = this.$refs.scrollUserBox.scrollHeight;
})
},
//切换客服状态
uploadState(state) {
if (state !== 4) {
this.state = state;
} else {
this.$confirm("是否退出登录?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
this.$message({
type: "success",
message: "退出成功!",
});
})
.catch(() => {
this.$message({
type: "info",
message: "已取消退出",
});
});
}
},
//搜索icon
handleIconClick() {
alert("搜索");
console.log(1);
},
//点击用户
getAct(val) {
console.log(val,11)
this.isshow=1
// 点击用户切换数据时先清除监听滚动事件,防止出现没有历史数据的用户,滚动条为0,会触发滚动事件
this.$refs.scrollBox.removeEventListener("scroll", this.srTop);
//点击变色
this.act = val.opposUserId;
//清空消息数组
// this.info = [];
this.queryParamsUser.toUserId = val.opposUserId
this.queryParamsUser.pageNum = 1
getMesInfo(this.queryParamsUser).then(response => {
this.info = response.rows
this.userTotal = response.total
this.queryParams.pageNum = 1
this.handleMesList()
// 直接调用不生效:因为你历史数据刚给,渲染的时候盒子高度还没有成型,所以直接调用拿不到,用个定时器让他在下一轮循环中调用,盒子就已经生成了
this.$nextTick(() => { // 一定要用nextTick
this.setPageScrollTo();
//页面滚动条距离顶部高度等于这个盒子的高度
this.$refs.scrollBox.scrollTop = this.$refs.scrollBox.s