需求:用vue、xtrerm、sockJS实现一个终端;
实现效果如下:
在这里插入图片描述实现难点:主要是与服务端建立连接,后端用的sockJS前端保持一致,其实xterm中自带了websocket;视图展示用的xterm;
xterm.js官方文档
sockjs-client

主要代码逻辑:

<template>
  <div id="term" class="term"></div>
</template>
<script>
import 'xterm/css/xterm.css'
import { Terminal } from 'xterm'
import { FitAddon } from 'xterm-addon-fit'
import SockJS from 'sockjs-client'
 mounted() {
    this.initSocket()
  },
  methods: {
    initSocket() {
      //连接路径
      if (this.socketURL == '') {
        return
      }
      this.socket = new SockJS(this.socketURL)
      this.socketOnOpen()
      this.socketOnMessage()
      this.socketOnClose()
      this.socketOnError()
    },
    socketOnOpen() {
      this.socket.onopen = () => {
        console.log('web链接成功')
        //发送格式与后台保持一致要不发送也是失败的
        this.socket.send(
          JSON.stringify({
            Op: 'bind',
          })
        )
        this.initTerm()
      }
    },
    initTerm() {
      this.term = new Terminal({
        rendererType: 'canvas', //渲染类型
        disableStdin: false, //是否应禁用输入
        windowsMode: true, //根据窗口换行
        cursorBlink: true, //光标闪烁
        cursorStyle: 'underline', //光标样式
        theme: {
          foreground: '#ececec', //字体
          background: '#000', //背景色
          lineHeight: 16
        }
      })
      let element = document.getElementById('term')
      this.term.open(element)
      const fitAddon = new FitAddon() //全屏插件
      this.term.loadAddon(fitAddon)
      //自适应大小(使终端的尺寸和几何尺寸适合于终端容器的尺寸)
      this.fitAddon = fitAddon
      this.fitAddon.fit()
      this.term.focus()
      this.term.onData(data => {
        let dataMessage = data
        //将输入的命令通知给后台,后台返回数据
          if (data === '\r') {
            data = '\n'
          } else if (data === '\u0003') {
            // 输入ctrl+c
            data += '\n'
          }
          this.socket.send(
            JSON.stringify({
              Op: 'stdin',
              Data: dataMessage,
              Cols: this.term.cols || 30,
              Rows: this.term.rows || 20
            })
          )
      })
      //接受服务器返回的结果并将结果显示到term中
    socketOnMessage() {
      this.socket.onmessage = evt => {
        this.term.write(JSON.parse(evt.data).Data)
      }
    },
    socketOnClose() {
      this.socket.onclose = () => {
        this.socket.close()
        console.log('关闭 socket')
      }
    },
    socketOnError() {
      this.socket.onerror = () => {
        console.log('socket 链接失败')
      }
    },
  }
</script>

开发过程中遇到的痛点就是调试时很麻烦;后来后台将项目打包之后我本地起服务才能写单独的html页面去进行调试的但是和项目还是有出入;
这样比 打包到uat上去查问题方便一点 但是已经不是什么好的解决方案 调试的时候真的是有点烦躁~~
在这里插入图片描述

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐