websocket简单运用

406 阅读4分钟

<template>  
<div ref="centerContainer1" class="bottom-wrapper">   
 <vue-draggable-resizable     
 :draggable="false"   
   :handles="['tm']"    
  :min-height="50"    
  :max-height="300"  
    :h="50"   
   :w="stretch.width"    
  :x="stretch.left"   
   :parent="false"   
   class="bottom-container"   
 >     
 <el-tabs v-model="activeName" type="card">
        <el-tab-pane label="全部" name="1">
          <div v-if="logs.log1.length !== 0" class="log-content">
            <div
              v-for="(item, index) in logs.log1"
              :key="index"
              class="log-warpper"
            >
              <div class="info-time">
                {{ filterTime(item.time) }}
              </div>
              <div
               class="info-type"
                :class="[
                  { blue: item.type === 1 },
                  { yellow: item.type === 2 },
                  { green: item.type === 3 }
                ]"
              >
                {{ item.type | filterType }}
              </div>
              <div class="log-info">
                {{ item.info }}
              </div>
              <div v-if="item.type === 2" class="view-info">
                <el-button type="text">查看详情</el-button>
              </div>
            </div>
          </div>
          <no-data v-if="logs.log1.length === 0"></no-data>
        </el-tab-pane>
        <el-tab-pane label="操作" name="2">
          <div v-if="logs.log2.length !== 0" class="log-content">
            <div
              v-for="(item1, index1) in logs.log2"
              :key="index1"
              class="log-warpper"
            >
              <div class="info-time">
                {{ filterTime(item1.time) }}
              </div>
              <div class="info-type blue">
                {{ item1.type | filterType }}
              </div>
              <div class="log-info">
                {{ item1.info }}
              </div>
            </div>
          </div>
          <no-data v-if="logs.log2.length === 0"></no-data>
        </el-tab-pane>
        <el-tab-pane label="试运行" name="3">
          <div v-if="logs.log3.length !== 0" class="log-content">
            <div
              v-for="(item2, index2) in logs.log3"
              :key="index2"
              class="log-warpper"
            >
              <div class="info-time">
                {{ filterTime(item2.time) }}
              </div>
              <div class="info-type yellow">
                {{ item2.type | filterType }}
              </div>
              <div class="log-info">
                {{ item2.info }}
              </div>      
        <div class="view-info">      
          <el-button type="text">查看详情</el-button>      
        </div>       
     </div>     
     </div>      
    <no-data v-if="logs.log3.length === 0"></no-data>   
     </el-tab-pane>     
   <el-tab-pane label="审批" name="4">     
     <div v-if="logs.log4 !== 0" class="log-content">    
        <div         
     v-for="(item3, index3) in logs.log4"      
        :key="index3"      
        class="log-warpper"     
       >            
  <div class="info-time">   
             {{ filterTime(item3.time) }} 
             </div>         
     <div class="info-type green">    
            {{ item3.type | filterType }}     
         </div>          
    <div class="log-info">       
         {{ item3.info }}       
       </div>       
     </div>      
    </div>      
   <no-data v-if="logs.log4.length === 0"></no-data>   
     </el-tab-pane>  
    </el-tabs> 
   </vue-draggable-resizable> 
 </div>
</template>
<script>
import { Base64 } from "js-base64";
import Cookies from "js-cookie";
import VueDraggableResizable from "vue-draggable-resizable";
import NoData from "@/components/NoData"; 
// 表单无数据时显示
import "vue-draggable-resizable/dist/VueDraggableResizable.css";
import { filterTime } from "@/filters";
export default { 
 components: {  
  VueDraggableResizable,  
  NoData  
},  
filters: {   
 filterType(type) {     
 const lists = {      
  1: "操作",      
  2: "试运行",     
   3: "审批"    
  };     
 return lists[type];   
 }  
},  
props: {   
 stretch: {    
  type: Object,   
   default: () => {    
    return {       
   width: 800,        
  left: 100    
    };    
  }   
} 
 },  
data() { 
  return {  
    activeName: "1",  
    webSock: null, //webScoket    
  logs: {     
   log1: [], //全部  
      log2: [], //操作   
     log3: [], //试运行     
   log4: [] //审批  
    },   
  filterTime   
 }; 
 }, 
 watch: { 
  activeName(nv, ov) { 
     if (nv !== ov) {  
      let params = {      
    modelId: Number(Base64.decode(this.$route.query.id)),      
    type: Number(nv) //1全部日志2操作日志3试运行日志4审批日志    
    };    
    this.websocketSend(params);  
    }   
 }  
},  
created() {  
  this.initWebSocket(); 
 }, 
 mounted() {}, 
 beforeDestroy() {
   this.wbReset(); //取消心跳时间   
 this.webSock.close();
 }, 
 methods: {  
  //初始化websocket 
   initWebSocket() {
      let token = Cookies.get("token"); 
    let id = Base64.decode(this.$route.query.id);  
    let localHost = window.location.host;    
  const url =     
    "ws://" + localHost + "/ws/modelLog/" + id + "/" + token; //与对应url建立连接   
   this.webSock = new WebSocket(url);     
 this.webSock.onopen = this.websocketOnOpen;    
  this.webSock.onmessage = this.websocketOnMessage;  
    this.webSock.onerror = this.websocketOnError;  
    this.webSock.onclose = this.websocketClose;    }, 
   //连接建立之后执行send方法发送数据   
 websocketOnOpen() {  
    // console.log("open");    
  // this.wbReset().wbstart(); //消息建立成功后重置心跳时间   
   let token = Cookies.get("token");    
  let params = {      
  modelId: Number(Base64.decode(this.$route.query.id)),   
     type: Number(this.activeName), //1全部日志2操作日志3试运行日志4审批日志   
     token: token    
  };     
 this.websocketSend(params);  
  },  
  websocketOnError() { 
     //连接建立失败重连    
  this.$message.error("websocket连接失败");   
   // this.initWebSocket();  
  },  
  //连接成功后,后端返回的数据   
 websocketOnMessage(event) {    
  if (event.data === "连接成功") return;  
    const res = JSON.parse(event.data);  
    if (res.log) {    
    let { type, log } = res; 
       this.logs["log" + type].unshift(log);    
  } else {      
  let { type, logs } = res;    
    let endLogs = logs.sort((a, b) => {    
      return b.time - a.time;     
   });     
   this.logs["log" + type] = endLogs;     
   this.wbReset().wbstart(); //消息接收成功后重置心跳时间   
   }   
 },   
 //主动向后端发送参数的方法--   
 websocketSend(params) {     
 //数据发送     
 this.webSock.send(JSON.stringify(params));   
 },   
 /**     * 心跳检测, 每隔一段时间检测连接状态, 
    * 如果处于连接中,就向server端主动发送消息,
来重置server端与客户端的最大连接时间,  
   * 如果已经断开了,发起重连。    
 */   
 wbReset() { 
     //心跳时间重置   
   clearInterval(this.wsHeartCheckTimeoutObj);  
    return this; 
   },    
//其实就是类似一个节流函数,在固定时间长度下,给后端发信息,保持通道处于连接状态  
  wbstart() {     
 //心跳启动    
  this.wsHeartCheckTimeoutObj = setInterval(() => {      
  if (this.webSock.readyState == 1) {   
       // console.log("当前为连接状态,开始发送消息保持连接");    
      let token = Cookies.get("token");  
        let modelId = Number(Base64.decode(this.$route.query.id)) 
         let params = {   
         modelId: modelId,   
         type: 0,        
    token: token    
      };       
   this.webSock.send(JSON.stringify(params));   
       this.wbReset().wbstart(); // 如果获取到消息,说明连接是正常的,重置心跳检测     
   } else {        
  // console.log("当前为断开状态,开始尝试重连");     
     this.initWebSocket();  
      }      
}, 1000 * 30);
    },  
  //连接断开时   
 websocketClose() {}   
 //切换  
}};
</script>
<style lang="scss" scoped>
.bottom-wrapper { 
 height: 50px; 
 width: 100%; 
 position: fixed;
  z-index: 0; 
 bottom: 0; 
.bottom-container {
    width: 1000px; 
   height: 100%; 
   background-color: rgba(250, 250, 250, 1);   
 border: 0px solid rgba(232, 232, 232, 1); 
   box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.16); 
 }
}
.log-content {  
width: 100%;
  height: 100%; 
 font-size: 13px; 
 overflow-y: scroll;
  .log-warpper {   
 display: flex;    
justify-content: flex-start; 
   margin-bottom: 20px;   
 .info-time {    
  color: #666666;   
   width: 150px;   
   margin-left: 24px;  
  }    .info-type {   
   width: 60px;   
   margin-left: 15px;   
 }  
  .log-info {
     color: #666666; 
     overflow: hidden;    
  text-overflow: ellipsis;    
  white-space: nowrap;   
   width: 400px;   
 }   
 .view-info {  
    width: 80px;   
   /deep/.el-button.el-button--text.el-button--small {    
    padding: 0;   
   }   
 }  
}
}
</style>