npm install --save xterm-addon-fit
npm install --save xterm

<template>
  <div class="box">
    <div id="xterm"></div>
  </div>
</template>

<script>
import { Terminal } from "xterm";
import { FitAddon } from "xterm-addon-fit";
import "xterm/css/xterm.css";
import "xterm/lib/xterm.js";
export default {
  data() {
    return {
      term: null,
      socket: "",
      WebSocketUrl: "",//ws接口
      // 心跳
      lockReconnect: false, //是否真正建立连接
      timeout: 28 * 1000, //30秒一次心跳
      timeoutObj: null, //心跳心跳倒计时
      serverTimeoutObj: null, //心跳倒计时
      timeoutnum: null, //断开 重连倒计时
    };
  },
  mounted() {
    this.init(this.WebSocketUrl);
  },
  //跑路前清除定时器
  beforeDestroy() {
    this.close();
    clearTimeout(this.timeoutObj);
    clearTimeout(this.serverTimeoutObj);
    clearTimeout(this.timeoutnum);
  },
  methods: {
    // 心跳函数--------------
    reconnect() {
      //重新连接
      var that = this;
      if (that.lockReconnect) {
        return;
      }
      that.lockReconnect = true;
      //没连接上会一直重连,设置延迟避免请求过多
      that.timeoutnum && clearTimeout(that.timeoutnum);
      that.timeoutnum = setTimeout(function () {
        //新连接
        that.init(that.WebSocketUrl);
        that.lockReconnect = false;
      }, 2000);
    },
    reset() {
      //重置心跳
      var that = this;
      //清除时间
      clearTimeout(that.timeoutObj);
      clearTimeout(that.serverTimeoutObj);
      //重启心跳
      that.start();
    },
    start() {
      //开启心跳
      var self = this;
      self.timeoutObj && clearTimeout(self.timeoutObj);
      self.serverTimeoutObj && clearTimeout(self.serverTimeoutObj);
      self.timeoutObj = setTimeout(function () {
        //这里发送一个心跳,后端收到后,返回一个心跳消息,
        if (self.socket.readyState == 1) {
          //如果连接正常
          self.socket.send("ping");
        } else {
          //否则重连
          self.reconnect();
        }
        self.serverTimeoutObj = setTimeout(function () {
          //超时关闭
          self.close();
        }, self.timeout);
      }, self.timeout);
    },
    //-----------------

    initXterm() {
      if (this.term) {
        this.term.dispose();
      }

      this.term = new Terminal({
        rendererType: "canvas", //渲染类型
        rows: 35, //行数
        convertEol: true, //启用时,光标将设置为下一行的开头
        scrollback: 10, //终端中的回滚量
        disableStdin: false, //是否应禁用输入
        cursorStyle: "underline", //光标样式
        cursorBlink: true, //光标闪烁
        theme: {
          foreground: "yellow", //字体
          background: "#060101", //背景色
          cursor: "help", //设置光标
        },
      });
      this.term.open(document.getElementById("xterm"));
      const fitAddon = new FitAddon();
      this.term.loadAddon(fitAddon);
      // 支持输入与粘贴方法
      let _this = this; //一定要重新定义一个this,不然this指向会出问题
      this.term.onData(function (key) {
        //这里key值是你输入的值,数据格式order一定要找后端要!!!!
        let order = {
          data: key,
          operation: "stdin",
        };
        _this.socket.onsend(JSON.stringify(order)); //转换为字符串
      });
    },
    init(url) {
      // 实例化socket
      this.socket = new WebSocket(url);
      // 监听socket连接
      this.socket.onopen = this.open;
      // 监听socket错误信息
      this.socket.onerror = this.error;
      // 监听socket消息
      this.socket.onmessage = this.getMessage;
      // 发送socket消息
      this.socket.onsend = this.send;
    },
    open: function () {
      console.log("socket连接成功");
      this.initXterm();
      //开启心跳
      this.start();
    },
    error: function () {
      console.log("连接错误");
      //重连
      this.reconnect();
    },
    close: function () {
      this.socket.close();
      console.log("socket已经关闭");
      //重连
      this.reconnect();
    },
    getMessage: function (msg) {
      //msg是返回的数据
      msg = JSON.parse(msg.data);
      this.socket.send("ping");//有事没事ping一下,看看ws还活着没
      //switch用于处理返回的数据,根据返回数据的格式去判断
      switch (msg["operation"]) {
        case "stdout":
          this.term.write(msg["data"]);//这里write也许不是固定的,失败后找后端看一下该怎么往term里面write
          break;
        default:
          console.error("Unexpected message type:", msg);//但是错误是固定的。。。。
      }
      //收到服务器信息,心跳重置
      this.reset();
    },
    send: function (order) {
      this.socket.send(order);
    },
  },
};
</script>

<style lang="scss" scoped>
.box {
  width: 100%;
  height: 100%;
  #xterm {
    width: 100%;
    height: 100%;
  }
}
</style>

不多bb,上图片
不多比比,上图片
搁置情况下的ws心跳(不断刷ping,断开重连)
不断刷ping,断开重连

Logo

前往低代码交流专区

更多推荐