Vue xtermjs 终端
2023-12-14 14:37:27
Vue xtermjs 终端
安装步骤如下
安装xtermjs所需要的插件
npm install --save xterm
npm install --save xterm-addon-fit
npm install --save xterm-addon-attach
HTML代码片段
<template>
<div>
<a-drawer
title="终端"
placement="right"
:closable="false"
:visible="visible"
:width="1000"
@close="onClose"
>
<div id="xterm" class="xterm" style="height:800px" />
</a-drawer>
</div>
</template>
<script>
import "xterm/css/xterm.css";
import { Terminal } from "xterm";
import { FitAddon } from "xterm-addon-fit";
export default {
data() {
return {
visible: false,
term: "",//terminal 黑窗口容器
prefix: "[root@serverip ~]# ",//前缀
inputText: "",//输入内容,每次回车后进行ws通信然后清空此数据
};
},
methods: {
//初始化黑窗口
async initTerm() {
const fitAddon = new FitAddon();
this.term = new Terminal({
fontSize: 14,
cursorBlink: true,
allowProposedApi: true,
disableStdin: false,
LogLevel: "debug",
});
this.term.loadAddon(fitAddon);
//开启Xterm终端
this.term.open(document.getElementById("xterm"));
this.term.writeln("\x1b[1;1;32mwellcom to web terminal!\x1b[0m");
this.term.write(this.prefix); //黑窗口 前缀
await this.termPromt(); //term.promt
await this.termKeyCode(); //事件
fitAddon.fit(); //黑窗口适应实际div宽高
this.term.focus(); //自动聚焦
},
//事件
termKeyCode() {
const TERMINAL_INPUT_KEY = {
BACK: 8, // 退格删除键
ENTER: 13, // 回车键
UP: 38, // 方向盘上键
DOWN: 40, // 方向盘键
LEFT: 37, // 方向盘左键
RIGHT: 39, // 方向盘右键
};
// const { eqpCode, server } = this.selectObj;
let inputText = "";
let currentIndex = 0;
let inputTextList = [];
this.term.onKey((e) => {
const { key, domEvent } = e;
const { keyCode, altKey, altGraphKey, ctrlKey, metaKey } = domEvent;
const printAble = !(altKey || altGraphKey || ctrlKey || metaKey); // 禁止相关按键
const totalOffsetLength = inputText.length + this.prefix.length; // 总偏移量
const currentOffsetLength = this.term._core.buffer.x; // 当前x偏移量
switch (keyCode) {
//删除
case TERMINAL_INPUT_KEY.BACK:
if (currentOffsetLength > this.prefix.length) {
const cursorOffSetLength = this.getCursorOffsetLength(totalOffsetLength - currentOffsetLength, "\x1b[D"); // 保留原来光标位置
this.term._core.buffer.x = currentOffsetLength - 1;
this.term.write("\x1b[?K" + inputText.slice(currentOffsetLength - this.prefix.length));
this.term.write(cursorOffSetLength);
inputText = `${inputText.slice(0, currentOffsetLength - this.prefix.length - 1)}${inputText.slice(
currentOffsetLength - this.prefix.length
)}`;
}
break;
//回车
case TERMINAL_INPUT_KEY.ENTER: {
this.term.write("\r\n");
console.log("inputText", inputText);
//ws 通信参数
// let wsParams = { EqpCode: eqpCode, Action: "terminal", Data: inputText };
// this.$emit("websocketSend", wsParams, server);
if (!inputText.trim()) {
this.term.prompt();
return;
}
if (inputTextList.indexOf(inputText) === -1) {
inputTextList.push(inputText);
currentIndex = inputTextList.length;
}
this.term.prompt();
inputText = "";
break;
}
case TERMINAL_INPUT_KEY.UP: {
if (!inputTextList[currentIndex - 1]) break;
const offsetLength = this.getCursorOffsetLength(inputText.length, "\x1b[D");
inputText = inputTextList[currentIndex - 1];
this.term.write(offsetLength + "\x1b[?K");
this.term.write(inputTextList[currentIndex - 1]);
this.term._core.buffer.x = totalOffsetLength;
currentIndex--;
break;
}
case TERMINAL_INPUT_KEY.LEFT:
if (currentOffsetLength > this.prefix.length) {
this.term.write(key); // '\x1b[D'
}
break;
case TERMINAL_INPUT_KEY.RIGHT:
if (currentOffsetLength < totalOffsetLength) {
this.term.write(key); // '\x1b[C'
}
break;
default: {
// 在当前的坐标写上 key 和坐标后面的字符
// 移动停留在当前位置的光标
if (!printAble) break;
if (totalOffsetLength >= this.term.cols) break;
if (currentOffsetLength >= totalOffsetLength) {
this.term.write(key);
inputText += key;
break;
}
let cursorOffSetLength = this.getCursorOffsetLength(totalOffsetLength - currentOffsetLength, "\x1b[D");
this.term.write("\x1b[?K" + `${key}${inputText.slice(currentOffsetLength - this.prefix.length)}`);
this.term.write(cursorOffSetLength);
inputText = inputText.slice(0, currentOffsetLength) + key + inputText.slice(totalOffsetLength - currentOffsetLength);
break;
}
}
});
},
//限制和后端交互,只有输入回车键才显示结果
termPromt() {
this.term.prompt = () => {
this.term.write(this.prefix);
};
},
//获取光标当前位置
getCursorOffsetLength(offsetLength, subString) {
let cursorOffsetLength = "";
for (let offset = 0; offset < offsetLength; offset++) {
cursorOffsetLength += subString;
}
return cursorOffsetLength;
},
//写入黑窗口
wirteTerm(data) {
console.log("写入黑窗口", data);
this.term.writeln(data);
this.term.prompt();
},
//加载基础数据
pageLoad(data) {
this.selectObj = data;
this.drawerFlag = true;
this.$nextTick(() => {
this.initTerm();
});
},
cancelClick() {
this.drawerFlag = false;
//关闭弹框
this.term.dispose(document.getElementById("xterm"));
},
showDrawer() {
this.visible = true;
this.$nextTick(()=>{
this.initTerm()
})
},
onClose() {
this.visible = false;
},
},
};
</script>
<style>
#terminal{
width:100%;
height:800px;
}
</style>
文章来源:https://blog.csdn.net/weixin_47000834/article/details/134994104
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!