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>
|