今天分享一个用Vue写的网页端终端插件,可以在web页面模拟原生命令行终端实现一些高级的操作。

插件地址:https://github.com/tzfun/vue-web-terminal
npm地址:https://www.npmjs.com/package/vue-web-terminal

下面是演示图:
vue-web-terminal

使用

npm安装插件

npm install vue-web-terminal --save

在入口函数中载入

import Vue from 'vue'
import App from './App.vue'
import Terminal from 'vue-web-terminal'

Vue.config.productionTip = false
Vue.use(Terminal)

new Vue({
  render: h => h(App),
}).$mount('#app')

在App.vue中使用,当你在Terminal中输入命令并回车时会触发 execCmd方法,这个方法有四个参数:

  1. key 是命令行的关键字,比如平时使用的 cd /home/user/data命令key就是cd;
  2. 第二个参数command是完整的命令行,交给你自己解析
  3. successfailed是成功和失败的回调,无论处理成功还是失败都必须调用其中一回调,否则你敲完回车后就没有回显了
<template>
  <div id="app">
    <terminal name="my-terminal" @execCmd="onExecCmd"></terminal>
  </div>
</template>

<script>

export default {
  name: 'App',
  methods: {
    onExecCmd(key, command, success, failed) {
      success({
        type: 'normal',
        class: 'success',
        tag: '成功',
        content: command
      })
    },
  }
}
</script>

<style>
body,html{
  margin: 0;
  padding: 0;
}
</style>

到这你就成功使用这个插件了,不过想更溜的使用它还得去看官方的插件文档,下面介绍一此插件支持的几种消息类型。

多种类型消息

这个插件支持了四种消息类型:普通文本、表格、json、代码(多行文本),下面分别介绍使用方法

普通文本

普通文本支持显示时间、标签等,普通文本的消息 type 为 normal,class为消息级别,tag为自定义的消息标签,如果不传tag默认以class作为tag

onExecCmd(key, command, success, failed) {
 if(key === 'success') {
   success({
     type: 'normal',
     class: 'success',
     content: '这是一条 success 级别的消息'
   })
 } else if (key === 'system') {
   success({
     type: 'normal',
     class: 'system',
     content: '这是一条 system 级别的消息'
   })
 } else if (key === 'info') {
   success({
     type: 'normal',
     class: 'info',
     content: '这是一条 info 级别的消息'
   })
 } else if (key === 'warning') {
   success({
     type: 'normal',
     class: 'warning',
     content: '这是一条 warning 级别的消息'
   })
 } else if (key === 'error') {
   success({
     type: 'normal',
     class: 'error',
     content: '这是一条 error 级别的消息'
   })
 } else if (key === 'setTag') {
   success({
     type: 'normal',
     class: 'success',
     tag: command.split(' ')[1],
     content: '这是一条 success 级别的消息,并自定义了tag内容'
   })
 } else {
   failed('无法解析的命令!')
 }
}

普通文本示例
插件默认会显示时间的,如果你不想显示时间可以这样关闭:

<terminal name="my-terminal" @execCmd="onExecCmd" :show-log-time="false"></terminal>

表格

当消息显示类型为表格时,type 为 table,content定义表格内容,示例代码:

onExecCmd(key, command, success, failed) {
  if (key === 'table') {
    success({
      type: 'table',
      content: {
        head: ['列1', '列2', '列3', '列4', '列5'],
        rows: [
          ['h', 'e', 'l', 'l', 'o'],
          ['w', 'o', 'r', 'l', 'd']
        ]
      }
    })
  } else {
    failed('无法解析的命令!')
  }
}

表格示例

Json

插件也支持json显示,并可选择层级,type为json,content为你想要展示的json即可

onExecCmd(key, command, success, failed) {
  if (key === 'json') {
    success({
      type: 'json',
      content: {
        k1: 'welcome to vue-web-terminal',
        k2: 120,
        k3: ['h', 'e', 'l', 'l', 'o'],
        k4: {k41: 2, k42: '200'}
      }
    })
  } else {
    failed('无法解析的命令!')
  }
}

Json示例

显示代码 / 多行文本

插件也支持代码显示,type为code,content为你要显示的代码内容即可,上代码:

onExecCmd(key, command, success, failed) {
  if (key === 'code') {
    success({
      type: 'code',
      content: 'export function _screenType(width) {\n' +
          '    let result = {}\n' +
          '    if (width < 600) {\n' +
          '        result.xs = true\n' +
          '    } else if (width >= 600 && width < 960) {\n' +
          '        result.sm = true\n' +
          '    } else if (width >= 960 && width < 1264) {\n' +
          '        result.md = true\n' +
          '    } else if (width >= 1264 && width < 1904) {\n' +
          '        result.lg = true\n' +
          '    } else {\n' +
          '        result.xl = true\n' +
          '    }\n' +
          '    return result\n' +
          '}'
    })
  } else {
    failed('无法解析的命令!')
  }
}

代码显示示例

Highlight代码高亮

如果你想你的代码高亮显示,可以接入Highlight,Terminal插件支持Highlight!

首先你需要定义解析规则,创建一个Highlight.js文件

import Hljs from 'highlight.js';
import 'highlight.js/styles/tomorrow-night-bright.css';

let Highlight = {};
Highlight.install = function (Vue) {
    Vue.directive('highlight', {
        inserted: function (el) {
            let blocks = el.querySelectorAll('pre code');
            blocks.forEach(block => {
                let ul = document.createElement("ul");
                let rowCount = block.outerHTML.split('\n').length;
                for (let i = 1; i <= rowCount; i++) {
                    let li = document.createElement("li")
                    let text = document.createTextNode(i)
                    li.appendChild(text)
                    ul.appendChild(li)
                }
                ul.className = 'pre-numbering'
                block.parentNode.appendChild(ul)
                Hljs.highlightBlock(block)
            })
        },
        componentUpdated: function (el) {
            let blocks = el.querySelectorAll('pre code');
            for (let i = 0; i < blocks.length; i++) {
                Hljs.highlightBlock(blocks[i]);
            }
        }
    })
};

export default Highlight;

然后再在载入Terminal处添加参数 { highlight: true }

import Vue from 'vue'
import App from './App.vue'
import Terminal from 'vue-web-terminal'
import Highlight from '@/Highlight'

Vue.config.productionTip = false

Vue.use(Highlight)
Vue.use(Terminal, { highlight: true})

new Vue({
  render: h => h(App),
}).$mount('#app')

结果:
代码高亮显示

Js API

插件提供了两个API:主动推送消息和修改上下文

主动推送消息

当某一个命令需要显示多个提示时可以使用以下方式:

onExecCmd(key, command, success, failed) {
  if(key === 'multiMsg') {
    let count = parseInt(command.split(' ')[1])
    for (let i = 0; i < count; i++) {
      this.$terminal.pushMessage('my-terminal', {
        type: 'normal',
        class: 'system',
        content: `push message ${i + 1}`
      })
    }
    success({
      type: 'normal',
      class: 'success',
      content: `成功推送${count}条消息`
    })
  } else {
    failed('无法解析的命令!')
  }
}

主动推送消息示例

修改上下文

默认上下文为插件名,一般我们都需要自定义插件上下文,比如模拟服务器连接切换路径

<template>
  <div id="app">
    <terminal :name="terminalName" @execCmd="onExecCmd" :context.sync="context"></terminal>
  </div>
</template>

<script>

export default {
  name: 'App',
  data() {
    return {
      terminalName: 'my-terminal',
      context: '/home/user'
    }
  },
  methods: {
    onExecCmd(key, command, success, failed) {
      if (key === 'cd') {
        let newCtx = command.split(' ')[1]
        this.$terminal.updateContext(this.terminalName, newCtx)
        success()
      } else {
        failed('无法解析的命令!')
      }
    },
  }
}
</script>

修改上下文示例

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐