287 lines
6.9 KiB
Vue
287 lines
6.9 KiB
Vue
<template>
|
||
<div class="chat">
|
||
<div class="chat-title">
|
||
欢迎您,在这里可查看城市的重点隐患信息!
|
||
</div>
|
||
|
||
<div class="content">
|
||
<div class="item item-right">
|
||
<div class="bubble bubble-right">
|
||
刚刚不在,不好意思
|
||
</div>
|
||
<div class="avatar">
|
||
<img src="https://tse1-mm.cn.bing.net/th/id/OIP-C.4XP3SrYigaDrlkbG_uFkzQAAAA?rs=1&pid=ImgDetMain">
|
||
</div>
|
||
</div>
|
||
<div class="item item-left">
|
||
<div class="avatar">
|
||
<img src="https://tse4-mm.cn.bing.net/th/id/OIP-C.-byzt1F3AA9UcVgO_DOIwQAAAA?rs=1&pid=ImgDetMain">
|
||
</div>
|
||
<div class="bubble bubble-left">
|
||
没事
|
||
<br>
|
||
你继续!
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 服务端向客户端推送的消息队列 -->
|
||
<div v-for="(item, index) in receiveMessageList" :key="index" :class="item.className">
|
||
<div style="display: flex;" v-html="item.content" />
|
||
</div>
|
||
|
||
<!-- 客户端向服务端主动发送的消息队列 -->
|
||
<div v-for="(item, index) in sendMessageList" :key="index" :class="item.className">
|
||
<div style="display: flex;" v-html="item.content" />
|
||
</div>
|
||
</div>
|
||
|
||
<div class="input-area">
|
||
<textarea id="textarea" v-model="inputTextValue" class="input-text-area" name="text" />
|
||
<div class="button-area">
|
||
<button class="btnSend" @click="handleSendMessage"> 发送(S) </button>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
|
||
let socketIOInstance
|
||
|
||
export default {
|
||
name: 'Chat',
|
||
data() {
|
||
return {
|
||
websocketonline: '',
|
||
inputTextValue: '',
|
||
/** 发送消息列表 */
|
||
sendMessageList: [],
|
||
/** 接收消息列表 */
|
||
receiveMessageList: []
|
||
}
|
||
},
|
||
created() {
|
||
this.getWebsocketController()
|
||
},
|
||
beforeDestroy() {
|
||
socketIOInstance.close()
|
||
},
|
||
methods: {
|
||
// 启动 websocket 连接控制器
|
||
getWebsocketController() {
|
||
if (window.WebSocket) {
|
||
socketIOInstance = new WebSocket(encodeURI('ws://192.168.0.35:8089/getMapData/1'))
|
||
socketIOInstance.onopen = () => {
|
||
console.log('socket 连接成功!')
|
||
}
|
||
socketIOInstance.onerror = () => {
|
||
console.log('socket 连接失败!')
|
||
}
|
||
socketIOInstance.onclose = () => {
|
||
console.log('socket 连接断开!')
|
||
}
|
||
socketIOInstance.onmessage = (message) => {
|
||
this.handleReceiveMessage(message)
|
||
}
|
||
}
|
||
},
|
||
/** 处理服务端向客户端推送的消息并展示到消息列表内 */
|
||
handleReceiveMessage(val) {
|
||
this.sendMessageList.push({
|
||
className: 'item item-left',
|
||
content: `<div class="avatar"><img src="https://tse4-mm.cn.bing.net/th/id/OIP-C.-byzt1F3AA9UcVgO_DOIwQAAAA?rs=1&pid=ImgDetMain"></div><div class="bubble bubble-left">${val.data}</div>`
|
||
})
|
||
},
|
||
// 处理客户端向服务端发送消息
|
||
handleSendMessage() {
|
||
if (this.inputTextValue === '') {
|
||
this.$message('消息不能为空!')
|
||
return
|
||
}
|
||
socketIOInstance.send(this.inputTextValue) // 向 websocket 服务发送消息
|
||
|
||
this.sendMessageList.push({
|
||
className: 'item item-right',
|
||
content: `<div class="bubble bubble-left">${this.inputTextValue}</div><div class="avatar"><img src="https://tse1-mm.cn.bing.net/th/id/OIP-C.4XP3SrYigaDrlkbG_uFkzQAAAA?rs=1&pid=ImgDetMain" /></div>`
|
||
})
|
||
|
||
this.inputTextValue = ''
|
||
this.$nextTick(() => {
|
||
// 滚动条置底
|
||
const height = document.querySelector('.content').scrollHeight
|
||
document.querySelector('.content').scrollTop = height
|
||
})
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
* {
|
||
padding: 0;
|
||
margin: 0;
|
||
font-size: 15px;
|
||
font-family: '微软雅黑', "宋体", "Arial Narrow", Helvetica, sans-serif;
|
||
}
|
||
|
||
.chat {
|
||
box-sizing: border-box;
|
||
width: 100%;
|
||
height: 100%;
|
||
|
||
.chat-title {
|
||
font-size: 20px;
|
||
text-align: center;
|
||
color: #fff;
|
||
height: 35px;
|
||
border-bottom: 1px solid white
|
||
}
|
||
|
||
.content {
|
||
overflow-y: auto;
|
||
overflow-x: hidden;
|
||
height: 648px;
|
||
|
||
&::-webkit-scrollbar {
|
||
width: 7px;
|
||
}
|
||
|
||
// 滚动条的滚动区域(轨道)
|
||
&::-webkit-scrollbar-track {
|
||
width: 8px;
|
||
border-radius: 18px;
|
||
background: transparent;
|
||
}
|
||
|
||
// 滚动条的可拖拽部分(滑块)
|
||
&::-webkit-scrollbar-thumb {
|
||
width: 8px;
|
||
border-radius: 18px;
|
||
background: rgba(20, 31, 168, .8);
|
||
}
|
||
|
||
.bubble {
|
||
max-width: 300px;
|
||
padding: 10px;
|
||
border-radius: 5px;
|
||
position: relative;
|
||
color: #000;
|
||
word-wrap: break-word;
|
||
word-break: normal;
|
||
}
|
||
|
||
.item-left .bubble {
|
||
margin-left: 15px;
|
||
background-color: #fff;
|
||
}
|
||
|
||
.item-left .bubble:before {
|
||
content: "";
|
||
position: absolute;
|
||
width: 0;
|
||
height: 0;
|
||
border-left: 10px solid transparent;
|
||
border-top: 10px solid transparent;
|
||
border-right: 10px solid #fff;
|
||
border-bottom: 10px solid transparent;
|
||
left: -20px;
|
||
}
|
||
|
||
.item-right .bubble {
|
||
margin-right: 15px;
|
||
background-color: #9eea6a;
|
||
}
|
||
|
||
.item-right .bubble:before {
|
||
content: "";
|
||
position: absolute;
|
||
width: 0;
|
||
height: 0;
|
||
border-left: 10px solid #9eea6a;
|
||
border-top: 10px solid transparent;
|
||
border-right: 10px solid transparent;
|
||
border-bottom: 10px solid transparent;
|
||
right: -20px;
|
||
}
|
||
|
||
.item {
|
||
margin-top: 15px;
|
||
display: flex;
|
||
width: 100%;
|
||
}
|
||
|
||
.item.item-right {
|
||
justify-content: flex-end;
|
||
}
|
||
|
||
.avatar img {
|
||
width: 42px;
|
||
height: 42px;
|
||
border-radius: 50%;
|
||
}
|
||
}
|
||
|
||
.input-area {
|
||
position: relative;
|
||
width: 100%;
|
||
height: 100px;
|
||
|
||
.input-text-area {
|
||
// 去除选中后的边框
|
||
outline: none;
|
||
resize: none;
|
||
background: none;
|
||
caret-color: #fff;
|
||
border: 1px solid #fff;
|
||
color: #fff;
|
||
width: 100%;
|
||
height: 100%;
|
||
border-radius: 6px;
|
||
padding: 10px;
|
||
overflow: auto;
|
||
line-height: 20px;
|
||
|
||
&::-webkit-scrollbar {
|
||
width: 7px;
|
||
}
|
||
|
||
// 滚动条的滚动区域(轨道)
|
||
&::-webkit-scrollbar-track {
|
||
width: 8px;
|
||
border-radius: 18px;
|
||
background: transparent;
|
||
}
|
||
|
||
// 滚动条的可拖拽部分(滑块)
|
||
&::-webkit-scrollbar-thumb {
|
||
width: 8px;
|
||
border-radius: 18px;
|
||
background: rgba(20, 31, 168, .8);
|
||
}
|
||
}
|
||
|
||
.button-area {
|
||
margin-top: 5px;
|
||
text-align: right;
|
||
|
||
.btnSend {
|
||
width: 85px;
|
||
height: 37px;
|
||
background: none;
|
||
border: 1px solid #fff;
|
||
border-radius: 6px;
|
||
color: #fff;
|
||
cursor: pointer;
|
||
font-weight: 800;
|
||
transition: transform ease-in-out .2s;
|
||
|
||
&:active {
|
||
transform: scale(0.9);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|