cdn形式html页面实现
在进行开发这个功能的时候,进行了百度,最后参考此博主的文章中的自定义版本,进行修改:https://blog.csdn.net/qq_25252769/article/details/127791918
开发过程中,由于后台数据返回的格式需要进行处理,根据自身需求,代码进行了少许修改
主要修改1:
根据后台返回的数据,需要传入一个对象,里边key值为message,并对这个对象进行序列化
主要修改2:
// this.ws.send("\n");//这边原来是放开状态,但由于后台数据返回原因会报错,就直接注释了
主要修改3:
接收信息时,
let message = "\n" + JSON.parse(event.data).message; //根据后台返回数据进行处理成对象形式,获取到message,进行显示到页面 const blob = new Blob([message], { type: "text/plain", });
原内容是:
//将字符串转换成 Blob对象 const blob = new Blob([event.data], { type: 'text/plain' })
,最终修改后的代码如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>前端终端,操作后端的docker容器</title> <!-- 引入样式 --> <link rel="stylesheet" href="https://unpkg.com/xterm@4.18.0/css/xterm.css"> </head> <body class="bodyCss"> <div id="app"> <div id="terminal" ></div> </div> </body> <script src="https://unpkg.com/xterm@4.18.0/lib/xterm.js"></script> <script src="https://lib.baomitu.com/vue/2.6.14/vue.js"></script> <script src="https://unpkg.com/xterm-addon-fit@0.6.0/lib/xterm-addon-fit.js"></script>
<script>
let wsTime = null;
new Vue({
el: "#app",
data() {
return {
// 终端
term: {},
// websocket
ws: {},
// 用户输入
command: "",
};
},
created() {
// 初始化终端
this.initTerminal();
},
mounted() {
// 建立websocket连接
this.websocket();
},
beforeDestroy() {
this.ws.close();
this.term.dispose();
},
methods: {
// 初始化终端配置
initTerminal() {
this.term = new Terminal({
rendererType: "canvas", //渲染类型
// rows: 40, //行数,影响最小高度
cols: 100, // 列数,影响最小宽度
convertEol: true, //启用时,光标将设置为下一行的开头
// scrollback: 50, //终端中的滚动条回滚量
disableStdin: false, //是否应禁用输入。
cursorStyle: "underline", //光标样式
cursorBlink: true, //光标闪烁
theme: {
foreground: "#F8F8F8",
background: "#2D2E2C",
cursor: "help", //设置光标
lineHeight: 16,
},
fontFamily: '"Cascadia Code", Menlo, monospace',
});
},
// 自定义终端默认展示内容
writeDefaultInfo() {
let defaultInfo = [
"┌\x1b[1m terminals \x1b[0m─────────────────────────────────────────────────────────────────┐ ",
"│ │ ",
"│ \x1b[1;34m 欢迎使用Web Docker SSH \x1b[0m │ ",
"│ │ ",
"└────────────────────────────────────────────────────────────────────────────┘ ",
];
// 测试颜色区间
// let arr = Array.from({length:100},(v,i)=>v = i)
// console.log(arr)
// arr.map((item,i) => {
// defaultInfo.push(`Hello from \x1B[1;3;${i}m ${i} \x1B[0m \u2764\ufe0f ${i}`)
// })
this.term.write(defaultInfo.join("\n\r"));
this.writeOfColor("我是加粗斜体红色的字呀", "1;3;", "31m");
// this.term.write('\n\r$ ')
},
//
writeOfColor(txt, fontCss = "", bgColor = "") {
// 在Linux脚本中以 \x1B[ 开始,中间前部分是样式+内容,以 \x1B[0m 结尾
// 示例 \x1B[1;3;31m 内容 \x1B[0m
// fontCss
// 0;-4;字体样式(0;正常 1;加粗 2;变细 3;斜体 4;下划线)
// bgColor
// 30m-37m字体颜色(30m:黑色 31m:红色 32m:绿色 33m:棕色字 34m:蓝色 35m:洋红色/紫色 36m:蓝绿色/浅蓝色 37m:白色)
// 40m-47m背景颜色(40m:黑色 41m:红色 42m:绿色 43m:棕色字 44m:蓝色 45m:洋红色/紫色 46m:蓝绿色/浅蓝色 47m:白色)
this.term.write(`\x1B[${fontCss}${bgColor}${txt}\x1B[0m`);
},
// 监听输入
userWrite() {
this.term.onData((e) => {
switch (e) {
case "\u0003": // Ctrl+C
this.term.write("^C ");
this.term.write("\r\n$ ");
break;
case "\r": // Enter
this.ws.send(JSON.stringify({ message: this.command }));//根据后台返回的数据,需要传入一个对象,里边key值为message,并对这个对象进行序列化
// this.ws.send("\n");//这边原来是放开状态,但由于后台数据返回原因会报错,就直接注释了
this.command = "";
// this.term.write('\r\n$ ')
break;
case "\u007F": // Backspace (DEL)
// Do not delete the prompt
if (this.term._core.buffer.x > 2) {
this.term.write("\b \b");
if (this.command.length > 0) {
this.command = this.command.substr(
0,
this.command.length - 1
);
}
}
break;
default: // Print all other characters for demo
if (
(e >= String.fromCharCode(0x20) &&
e <= String.fromCharCode(0x7e)) ||
e >= "\u00a0"
) {
this.command += e;
this.writeOfColor(e, "2;3;", "33m");
console.log("用户输入command", this.command);
}
}
});
},
// 建立websocket连接
websocket() {
// WebSocket start
if ("WebSocket" in window) {
//需要修改ip和id
//例如:const url = `ws://192.168.111.222:2375/v1.41/containers/0eb8aafb4e6e/attach/ws?logs=0&stream=1&stdin=1&stdout=1&stderr=1`
const url = `ws:172.16.188.58:5000/ws/chat/?host=172.16.188.58&username=root&password=admin`;
const ws = new WebSocket(url);
this.ws = ws;
this.$nextTick(() => {
this.userWrite();
});
ws.onopen = (event) => {
console.log("已建立连接:", event);
// 输入换行符可让终端显示当前用户的工作路径
// ws.send("\n");//这边原来是放开状态,但由于后台数据返回原因会报错,就直接注释了
// 窗口自适应插件
const fitAddon = new FitAddon.FitAddon();
// 窗口尺寸变化时,终端尺寸自适应
window.onresize = () => {
fitAddon.fit();
};
this.term.loadAddon(fitAddon);
this.term.open(document.getElementById("terminal"));
this.term.focus();
// 自定义终端默认展示内容
this.writeDefaultInfo();
};
ws.onmessage = (event) => {
console.log("接收信息:", event.data);
let message = "\n" + JSON.parse(event.data).message; //根据后台返回数据进行处理成对象形式进行显示到页面,如果不需要处理,需要直接
//将字符串转换成 Blob对象
const blob = new Blob([message], {
type: "text/plain",
});
//将Blob 对象转换成字符串
const reader = new FileReader();
reader.readAsText(blob, "utf-8");
reader.onload = (e) => {
// 可以根据返回值判断使用何种颜色或者字体,不过返回值自带了一些字体颜色
this.writeOfColor(reader.result, "0;", "37m");
};
};
ws.onerror = (event) => {
console.log("错误信息:", event);
if (wsTime) {
window.clearTimeout(wsTime);
wsTime = null;
}
wsTime = window.setTimeout(() => {
this.websocket();
}, 3000);
};
ws.onclose = (event) => {
console.log("已关闭连接:", event);
// if (wsTime) {
// window.clearTimeout(wsTime)
// wsTime = null
// }
// wsTime = window.setTimeout(() => {
// this.websocket()
// }, 3000)
};
} else {
console.log("浏览器不支持 WebSocket..");
}
// WebSocket end
},
},
});
</script>
</html>