|
|
|
|
@ -23,15 +23,48 @@
|
|
|
|
|
<div class="item" @click="toService" style="cursor: pointer;">
|
|
|
|
|
<i class="el-icon-chat-dot-square" style="color:#fff;font-size: 20px"></i>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="item" @click="toTop" style="line-height: 20px">
|
|
|
|
|
<div class="item" @click="toTop" style="cursor: pointer;line-height: 20px">
|
|
|
|
|
<i class="el-icon-caret-top" style="color:#fff;font-size: 20px"></i>
|
|
|
|
|
<div style=" color: #fff">top</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="onlineConsultation" @click="consultation ">
|
|
|
|
|
<div class="btn">
|
|
|
|
|
<img :src="customerService" alt="" class="customerService">
|
|
|
|
|
<span class="text">在线咨询</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="chat" v-if="isChat" ref="dragDiv">
|
|
|
|
|
<div class="topDrag" @mousedown="onMouseDown">
|
|
|
|
|
<i class="el-icon-close close" @click="isChat = false"></i>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="content1" ref="chatContainer">
|
|
|
|
|
<template v-for="i in chatInfo">
|
|
|
|
|
<div v-if="i.type===0" class="message">
|
|
|
|
|
<div class="userInfo">{{ i.userName }} {{ formatTime(i.time) }}</div>
|
|
|
|
|
<div class="info">{{ i.content }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="i.type===1" class="message1">
|
|
|
|
|
<div class="userInfo">{{ i.userName }} {{ formatTime(i.time) }}</div>
|
|
|
|
|
<div class="info">{{ i.content }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="chatBox">
|
|
|
|
|
<el-input
|
|
|
|
|
type="textarea"
|
|
|
|
|
placeholder="请输入内容"
|
|
|
|
|
class="no-border-textarea"
|
|
|
|
|
v-model="textarea">
|
|
|
|
|
</el-input>
|
|
|
|
|
<el-button type="primary" size="mini" class="chatBtn" @click="sendChat">发送消息</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
import customerService from '@/assets/icon/customerService.png'
|
|
|
|
|
import qrcode from '@/assets/icon/QRCode.png'
|
|
|
|
|
import Menu from '@/components/menu/index'
|
|
|
|
|
import logo from '@/assets/logo.png'
|
|
|
|
|
@ -50,12 +83,141 @@ export default {
|
|
|
|
|
},
|
|
|
|
|
toService() {
|
|
|
|
|
this.$router.push('/serviceSupport')
|
|
|
|
|
},
|
|
|
|
|
consultation() {
|
|
|
|
|
this.isChat = true;
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
this.scrollToBottom()
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
onMouseDown(e) {
|
|
|
|
|
this.isDown = true;
|
|
|
|
|
const rect = this.$refs.dragDiv.getBoundingClientRect();
|
|
|
|
|
this.offsetX = e.clientX - rect.left;
|
|
|
|
|
this.offsetY = e.clientY - rect.top;
|
|
|
|
|
|
|
|
|
|
document.addEventListener("mousemove", this.onMouseMove);
|
|
|
|
|
document.addEventListener("mouseup", this.onMouseUp);
|
|
|
|
|
},
|
|
|
|
|
onMouseMove(e) {
|
|
|
|
|
if (!this.isDown) return;
|
|
|
|
|
|
|
|
|
|
const dragDiv = this.$refs.dragDiv;
|
|
|
|
|
|
|
|
|
|
// 鼠标相对窗口的 left/top
|
|
|
|
|
let left = e.clientX - this.offsetX;
|
|
|
|
|
let top = e.clientY - this.offsetY;
|
|
|
|
|
|
|
|
|
|
// ✅ 边界限制 (保证不出窗口)
|
|
|
|
|
if (left < 0) left = 0;
|
|
|
|
|
if (top < 0) top = 0;
|
|
|
|
|
if (left > window.innerWidth - dragDiv.offsetWidth) {
|
|
|
|
|
left = window.innerWidth - dragDiv.offsetWidth;
|
|
|
|
|
}
|
|
|
|
|
if (top > window.innerHeight - dragDiv.offsetHeight) {
|
|
|
|
|
top = window.innerHeight - dragDiv.offsetHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ✅ 转换为 right/bottom
|
|
|
|
|
let right = window.innerWidth - left - dragDiv.offsetWidth;
|
|
|
|
|
let bottom = window.innerHeight - top - dragDiv.offsetHeight;
|
|
|
|
|
|
|
|
|
|
dragDiv.style.right = right + "px";
|
|
|
|
|
dragDiv.style.bottom = bottom + "px";
|
|
|
|
|
},
|
|
|
|
|
onMouseUp() {
|
|
|
|
|
this.isDown = false;
|
|
|
|
|
document.removeEventListener("mousemove", this.onMouseMove);
|
|
|
|
|
document.removeEventListener("mouseup", this.onMouseUp);
|
|
|
|
|
},
|
|
|
|
|
formatTime(date) {
|
|
|
|
|
const now = new Date();
|
|
|
|
|
const input = new Date(date);
|
|
|
|
|
|
|
|
|
|
const diffTime = now - input;
|
|
|
|
|
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
|
|
|
|
|
|
|
|
|
|
const isToday = now.toDateString() === input.toDateString();
|
|
|
|
|
|
|
|
|
|
const yesterday = new Date();
|
|
|
|
|
yesterday.setDate(now.getDate() - 1);
|
|
|
|
|
const isYesterday = yesterday.toDateString() === input.toDateString();
|
|
|
|
|
const padZero = num => String(num).padStart(2, '0');
|
|
|
|
|
const timeStr = `${padZero(input.getHours())}:${padZero(input.getMinutes())}:${padZero(input.getSeconds())}`;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (isToday) {
|
|
|
|
|
return `今天 ${timeStr}`;
|
|
|
|
|
} else if (isYesterday) {
|
|
|
|
|
return `昨天 ${timeStr}`;
|
|
|
|
|
} else {
|
|
|
|
|
return `${diffDays}天前`;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
scrollToBottom() {
|
|
|
|
|
const container = this.$refs.chatContainer;
|
|
|
|
|
container.scrollTop = container.scrollHeight;
|
|
|
|
|
},
|
|
|
|
|
sendChat() {
|
|
|
|
|
if (this.textarea === '') {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
this.chatInfo.push({
|
|
|
|
|
type: 1,
|
|
|
|
|
content: this.textarea,
|
|
|
|
|
time: new Date().getTime(),
|
|
|
|
|
userName: '我',
|
|
|
|
|
})
|
|
|
|
|
this.textarea = ''
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
this.scrollToBottom()
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
mounted() {
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
this.isChat = true;
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
this.scrollToBottom()
|
|
|
|
|
})
|
|
|
|
|
}, 5 * 1000)
|
|
|
|
|
},
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
textarea: '',
|
|
|
|
|
logo,
|
|
|
|
|
qrcode
|
|
|
|
|
qrcode,
|
|
|
|
|
customerService,
|
|
|
|
|
isChat: false,
|
|
|
|
|
isDown: false,
|
|
|
|
|
offsetX: 0,
|
|
|
|
|
offsetY: 0,
|
|
|
|
|
chatInfo: [
|
|
|
|
|
{
|
|
|
|
|
type: 0,
|
|
|
|
|
content: '你好',
|
|
|
|
|
time: new Date().getTime(),
|
|
|
|
|
userName: '海威物联',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
type: 0,
|
|
|
|
|
content: '你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好',
|
|
|
|
|
time: new Date().getTime(),
|
|
|
|
|
userName: '海威物联',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
type: 1,
|
|
|
|
|
content: '测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试',
|
|
|
|
|
time: new Date().getTime(),
|
|
|
|
|
userName: '我',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
type: 0,
|
|
|
|
|
content: '你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好你好',
|
|
|
|
|
time: new Date().getTime(),
|
|
|
|
|
userName: '海威物联',
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -183,4 +345,137 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.onlineConsultation {
|
|
|
|
|
position: fixed;
|
|
|
|
|
right: 5vw;
|
|
|
|
|
bottom: 0;
|
|
|
|
|
width: 150px;
|
|
|
|
|
height: 50px;
|
|
|
|
|
background-color: #41B5EA;
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
z-index: 99;
|
|
|
|
|
|
|
|
|
|
.customerService {
|
|
|
|
|
position: absolute;
|
|
|
|
|
bottom: 0;
|
|
|
|
|
left: 0;
|
|
|
|
|
width: 70px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.text {
|
|
|
|
|
position: absolute;
|
|
|
|
|
bottom: 0;
|
|
|
|
|
left: 70px;
|
|
|
|
|
width: 80px;
|
|
|
|
|
line-height: 50px;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
color: #fff;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chat {
|
|
|
|
|
z-index: 999;
|
|
|
|
|
position: fixed;
|
|
|
|
|
bottom: 10vw;
|
|
|
|
|
right: 10vw;
|
|
|
|
|
width: 450px;
|
|
|
|
|
height: 450px;
|
|
|
|
|
border-top-left-radius: 5px;
|
|
|
|
|
border-top-right-radius: 5px;
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
box-shadow: -4px 4px 8px rgba(0, 0, 0, 0.1),
|
|
|
|
|
4px 4px 8px rgba(0, 0, 0, 0.1),
|
|
|
|
|
0 4px 8px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
|
|
|
|
.topDrag {
|
|
|
|
|
position: absolute;
|
|
|
|
|
top: 0;
|
|
|
|
|
left: 0;
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 50px;
|
|
|
|
|
background-color: #41B5EA;
|
|
|
|
|
cursor: move;
|
|
|
|
|
|
|
|
|
|
.close {
|
|
|
|
|
position: absolute;
|
|
|
|
|
top: 50%;
|
|
|
|
|
right: 20px;
|
|
|
|
|
transform: translateY(-50%);
|
|
|
|
|
color: #fff;
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.content1 {
|
|
|
|
|
position: absolute;
|
|
|
|
|
top: 50px;
|
|
|
|
|
height: 300px;
|
|
|
|
|
overflow: auto;
|
|
|
|
|
|
|
|
|
|
.message {
|
|
|
|
|
width: 80%;
|
|
|
|
|
margin: 5px 0 5px 5px;
|
|
|
|
|
text-align: left;
|
|
|
|
|
|
|
|
|
|
.userInfo {
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
color: #0008
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.info {
|
|
|
|
|
background-color: #EDEFF5;
|
|
|
|
|
padding: 5px;
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
border-top-left-radius: 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.message1 {
|
|
|
|
|
width: calc(100% - 20px);
|
|
|
|
|
margin: 5px 0 15px 5px;
|
|
|
|
|
text-align: right;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
|
|
|
|
.userInfo {
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
color: #0008
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.info {
|
|
|
|
|
text-align: left;
|
|
|
|
|
width: 80%;
|
|
|
|
|
float: right;
|
|
|
|
|
background-color: #EDEFF5;
|
|
|
|
|
padding: 5px;
|
|
|
|
|
border-radius: 5px 0px 5px 5px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chatBox {
|
|
|
|
|
position: absolute;
|
|
|
|
|
top: 350px;
|
|
|
|
|
height: 88px;
|
|
|
|
|
width: 100%;
|
|
|
|
|
margin-top: 12px;
|
|
|
|
|
|
|
|
|
|
.no-border-textarea /deep/ .el-textarea__inner {
|
|
|
|
|
border: none;
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
resize: none;
|
|
|
|
|
outline: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chatBtn {
|
|
|
|
|
position: absolute;
|
|
|
|
|
bottom: 5px;
|
|
|
|
|
right: 10px;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
|