diff options
Diffstat (limited to 'src/views/rangeNodeManage/detail/console/module')
5 files changed, 0 insertions, 1677 deletions
diff --git a/src/views/rangeNodeManage/detail/console/module/ControlConsole.vue b/src/views/rangeNodeManage/detail/console/module/ControlConsole.vue deleted file mode 100644 index 3971e08..0000000 --- a/src/views/rangeNodeManage/detail/console/module/ControlConsole.vue +++ /dev/null @@ -1,389 +0,0 @@ -<template> - <div - style="height: 100%; - background: #002833;" - > - <div class="indexContainer" id="terminal" ref="terminal" v-resize="onResize"></div> - </div> -</template> - -<script> - // 引入xterm,请注意这里和3.x版本的引入路径不一样 - import { Terminal } from "xterm"; - import "xterm/css/xterm.css"; - import "xterm/lib/xterm.js"; - import { FitAddon } from "xterm-addon-fit"; - - import resize from 'vue-resize-directive'; - - export default { - name: "Shell", - directives: { resize }, - data() { - return { - nodeId: '', - showOrder: "", // 保存服务端返回的命令 - inputList: [], - shellWs: "", - term: "", // 保存terminal实例 - rows: 40, - cols: 100, - urlParam: { - Tag: 'tag', - name: 'name', - pod: 'pod' - }, - commandPrefix: 'target' - }; - }, - watch: { - '$store.state.range.nodeId': { - handler(newVal, oldVal) { - this.nodeId = newVal - }, - immediate: true - } - }, - created() { - this.getWebsocketUrl() - }, - - mounted() { - let _this = this; - localStorage.setItem('commands', '') - // 获取容器宽高/字号大小,定义行数和列数 - this.rows = document.querySelector(".indexContainer").offsetHeight / 16 - 6; - this.cols = document.querySelector(".indexContainer").offsetWidth / 14; - - let term = new Terminal({ - rendererType: "canvas", //渲染类型 - rows: parseInt(_this.rows), //行数 - cols: parseInt(_this.cols), // 不指定行数,自动回车后光标从下一行开始 - convertEol: true, //启用时,光标将设置为下一行的开头 - fontSize: 16, //字体大小 - // scrollback: 50, //终端中的回滚量 - disableStdin: false, //是否应禁用输入。 - cursorStyle: "underline", //光标样式 - cursorBlink: true, //光标闪烁 - // theme: { - // foreground: "#7e9192", //字体 - // background: "#002833", //背景色 - // cursor: "help", //设置光标 - // lineHeight: 16 - // } - theme: { - foreground: "yellow", //字体 - background: "#060101", //背景色 - cursor: "help", //设置光标 - lineHeight: 16 - } - }); - - // 创建terminal实例 - term.open(this.$refs["terminal"]); - - // 换行并输入起始符“$” - term.prompt = () => { - term.write("\r\n$ "); - }; - term.prompt(); - - // // canvas背景全屏 - var fitAddon = new FitAddon(); - term.loadAddon(fitAddon); - fitAddon.fit(); - - window.addEventListener("resize", resizeScreen); - // document.querySelector(".indexContainer").addEventListener('resize', resizeScreen) - - // 内容全屏显示 - function resizeScreen() { - // 不传size - try { - fitAddon.fit(); - // 窗口大小改变时触发xterm的resize方法,向后端发送行列数,格式由后端决定 - // 这里不使用size默认参数,因为改变窗口大小只会改变size中的列数而不能改变行数,所以这里不使用size.clos,而直接使用获取我们根据窗口大小计算出来的行列数 - term.onResize(() => { - _this.onSend({ Op: "resize", Cols: term.cols, Rows: term.rows }); - }); - } catch (e) { - console.log("e", e.message); - } - } - - function runFakeTerminal(_this) { - if (term._initialized) { - return; - } - - term._initialized = true; - - term.prompt = () => { - term.write("\r\n "); - }; - - // term.writeln("Welcome to xterm.js"); - // term.writeln( - // "This is a local terminal emulation, without a real terminal in the back-end." - // ); - // term.writeln("Type some keys and commands to play around."); - - // term.writeln("root@target:/#"); - // term.prompt(); - - // 监控键盘输入事件 - // / ** - // *添加事件监听器,用于按下键时的事件。事件值包含 - // *将在data事件以及DOM事件中发送的字符串 - // *触发了它。 - // * @返回一个IDisposable停止监听。 - // * / - let last = 0; - - term.onKey(function(event) { - // 可打印状态,即不是alt键ctrl等功能健时 - // console.log(event, '输入的key======') - const printable = !event.domEvent.altKey && !event.domEvent.altGraphKey && !event.domEvent.ctrlKey && !event.domEvent.metaKey - - // !key.charCodeAt(0).altKey && !key.charCodeAt(0).altGraphKey && !key.charCodeAt(0).ctrlKey && !key.charCodeAt(0).metaKey; - - // 因服务端返回命令包含乱码,但使用write方法输出时并不显示,故将真实显示内容截取出来 - let show = '' - if (_this.showOrder) { - let index = _this.showOrder.indexOf("sh"); - show = _this.showOrder.substr(index, _this.showOrder.length - 1); - } - - // 当输入回车时 - if (event.domEvent.keyCode === 13) { - if (_this.order == "cls" || _this.order == "clear") { - _this.order = ""; - return false; - } - //先将数据发送 - term.prompt(); - // 判断如果不是英文给出提醒 - let reg = /[a-zA-Z]/; - // let order = { - // Data: _this.order, - // Op: "stdin" - // }; - let order = _this.order - - if (!reg.test(_this.order)) { - term.writeln("请输入有效指令~"); - } else { - // 发送数据 - _this.inputList.push(_this.order); - last = _this.inputList.length - 1; - _this.onSend(order); - // 清空输入内容变量 - } - } else if (event.domEvent.keyCode === 8) { - // 当输入退 - // 当前行字符长度如果等于后端返回字符就不进行删除 - if(_this.order.length > 0) { - _this.order = _this.order.substr(0, _this.order.length - 1); - term.write('\b \b') - } - // if (term._core.buffer.x > _this.showOrder.length) { - // term.write("\b \b"); // 输出退格 - // } - - // // 将输入内容变量删除 - - // if (_this.trim(_this.order) == _this.trim(_this.showOrder)) { - // return false; - // } else { - // _this.order = _this.order.substr(0, _this.order.length - 1); - // term.write('\b \b') - // } - } else if (event.domEvent.keyCode === 127) { - if (term._core.buffer.x > (_this.showOrder.length + 2)) { - term.write('\b \b') - _this.order = _this.order.substr(0, _this.order.length - 1) - } - } else if (event.domEvent.keyCode === 38 || event.domEvent.keyCode === 40) { - let len = _this.inputList.length; - let code = event.domEvent.keyCode; - - if (code === 38 && last <= len && last >= 0) { - // 直接取出字符串数组最后一个元素 - let inputVal = _this.inputList[last]; - term.write(inputVal); - if (last > 0) { - last--; - } - } - if (code === 40 && last < len) { - // last现在为当前元素 - if (last == len - 1) { - return; - } - if (last < len - 1) { - last++; - } - - let inputVal = _this.inputList[last]; - term.write(inputVal); - } - } else if (event.domEvent.keyCode === 9) { - // 如果按tab键前输入了之前后端返回字符串的第一个字符,就显示此命令 - if (_this.order !== "" && show.indexOf(_this.order) == 0) { - term.write(_this.showOrder); - } - } else if (event.key == '\x16') { - navigator.clipboard.readText().then(clipText => { - term.write(clipText); - }) - //ctrol+ c copy - } else if (event.key == '\x03' && term.hasSelection()) { - navigator.clipboard.writeText(term.getSelection()) - } else if (printable) { - let key = event.key - // // 当为可打印内容时 - // if (/[a-zA-Z]/.test(key)) { - // key = key.toLowerCase(); - // } - // 存入输入内容变量 - _this.order = _this.order + key; - // 将变量写入终端内 - term.write(key); - } - }); - - _this.term = term; - } - runFakeTerminal(_this); - }, - - methods: { - - /** - * **wsShell 创建页面级别的websocket,加载页面数据 - * ws 接口:/xxx/xxx/xxx - * 参数:无 - * ws参数: - * @deployId 任务id - * @tagString 当前节点 - * 返回:无 - * **/ - wsShell(url) { - const _this = this; - let tag = this.urlParam.Tag; - let name= this.urlParam.name; - let pod= this.urlParam.pod; - - // let query = `?tag=${tag}&name=${name}&pod=${pod}`; - // let url = `xxxx/xxxx${query}`;// websocket连接接口 - // let url = 'ws://172.16.0.120:30598/ws/target-19-austria-80-110-35-0-24/target-19-relay-127-54b5df76f4-8958g/relay-127' - - this.shellWs = this.websoketLib.WS({ - url, - isInit: true, - openFn(e) { - console.log('连接websocket成功===', e) - // _this.term.resize({ rows: _this.rows, cols: 100 }); //终端窗口重新设置大小 并触发term.on("resize") - }, - messageFn(e) { - console.log("message", e); - if (e) { - // let data = JSON.parse(e.data); - // if (data.Data == "\n" || data.Data == "\r\nexit\r\n") { - // _this.$message("连接已关闭"); - // } - // 打印后端返回数据 - // _this.term.write(data.Data); - - let backData = '' - // 创建一个包含文本内容的Blob对象 - var blob = e.data; - // 创建一个新的FileReader对象 - var reader = new FileReader(); - // 读取Blob并将其转换为字符串 - reader.onloadend = function () { - backData = reader.result; // 获得转换后的字符串 - console.log(backData, '服务端websockt返回结果===='); // 输出结果到控制台 - let index = _this.order?.length; - backData = backData.substring(index, backData.length); - // 如果返回字符包含这些字符显示close提示 - if (backData == "\n" || backData == "\r\nexit\r\n") { - alert("closed"); - } - if (backData.trim() === 'Connected!') { - _this.term.write(backData) - _this.term.write(`root@${_this.commandPrefix}:/#`); - } else { - _this.term.write(backData) - } - _this.showOrder = backData; - _this.order = ""; - }; - - // 开始读取Blob - reader.readAsText(blob); - } - }, - errorFn(e) { - //出现错误关闭当前ws,并且提示 - console.log("error", e); - _this.$message.error({ - message: "ws 请求失败,请刷新重试~", - duration: 5000 - }); - } - }); - }, - - onSend(data) { - // data = this.websoketLib.isObject(data) ? JSON.stringify(data) : data; - // data = this.websoketLib.isArray(data) ? data.toString() : data; - // data = data.replace(/\\\\/, "\\"); - this.shellWs.onSend(data); - }, - - //删除左右两端的空格 - trim(str) { - return str.replace(/(^\s*)|(\s*$)/g, ""); - }, - // 获取websocket地址 - getWebsocketUrl() { - const reqParams = { node_id: this.nodeId } - this.$axios.get(this.$http.api.getWebsocketUrl, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - const wsUrl = 'ws://' + window.g.baseURL + res.result - this.wsShell(wsUrl) - this.commandPrefix = res.result.split('/')[3] - } - }).catch(err => { - console.log(err) - }) - }, - // 全屏时重新设置控制台行高 - onResize() { - this.rows = document.querySelector(".indexContainer").offsetHeight / 16 - 6; - this.cols = document.querySelector(".indexContainer").offsetWidth / 14; - this.term.resize(parseInt(this.rows), parseInt(this.cols)) - // canvas背景全屏 - var fitAddon = new FitAddon(); - this.term.loadAddon(fitAddon); - try { - fitAddon.fit(); - // 窗口大小改变时触发xterm的resize方法,向后端发送行列数,格式由后端决定 - // 这里不使用size默认参数,因为改变窗口大小只会改变size中的列数而不能改变行数,所以这里不使用size.clos,而直接使用获取我们根据窗口大小计算出来的行列数 - term.onResize(() => { - this.onSend({ Op: "resize", Cols: term.cols, Rows: term.rows }); - }); - } catch (e) { - console.log("e", e.message); - } - }, - } - }; -</script> -<style lang="less" scoped> -.indexContainer { - height: calc(100% - 0px); -} -</style> -
\ No newline at end of file diff --git a/src/views/rangeNodeManage/detail/console/module/ControlConsole2.vue b/src/views/rangeNodeManage/detail/console/module/ControlConsole2.vue deleted file mode 100644 index a1851c9..0000000 --- a/src/views/rangeNodeManage/detail/console/module/ControlConsole2.vue +++ /dev/null @@ -1,306 +0,0 @@ -<template> - <!-- <div class="content"> --> - <!-- <div id="xterm" class="xterm"/> --> - <div id="log" style="margin:10px auto;"> - <div class="console" id="terminal"></div> - </div> - <!-- </div> --> -</template> - -<script> -import "xterm/css/xterm.css"; -import { Terminal } from "xterm"; -import { FitAddon } from "xterm-addon-fit"; -import { AttachAddon } from "xterm-addon-attach"; -export default { - name: "Xterm", - props: { - // socketURI: { - // type: String, - // default: '' - // }, - }, - data() { - return { - term: null, //terminal 黑窗口容器 - socket: null, - rows: 32, - cols: 20, - SetOut: false, - isKey: false, - prefix: "[root@serverip ~]# "//前缀 - // inputText: "",//输入内容,每次回车后进行ws通信然后清空此数据 - }; - }, - watch: {}, - mounted() { - this.initSocket() - }, - beforeDestroy() { - this.socket.close() - // this.term.dispose() - }, - methods: { - //初始化黑窗口 - async initTerm() { - const term = new Terminal({ - rendererType: "canvas", //渲染类型 - rows: this.rows, //行数 - // cols: this.cols,// 设置之后会输入多行之后覆盖现象 - convertEol: true, //启用时,光标将设置为下一行的开头 - // scrollback: 10,//终端中的回滚量 - fontSize: 14, //字体大小 - disableStdin: false, //是否应禁用输入。 - cursorStyle: "block", //光标样式 - // cursorBlink: true, //光标闪烁 - scrollback: 30, - tabStopWidth: 4, - theme: { - foreground: "yellow", //字体 - background: "#060101", //背景色 - cursor: "help" //设置光标 - } - }); - - const attachAddon = new AttachAddon(this.socket); - const fitAddon = new FitAddon(); - term.loadAddon(attachAddon); - term.loadAddon(fitAddon); - //开启Xterm终端 - term.open(document.getElementById("terminal")); - - term.write('Hello from \x1B[1;3;31mxterm.js\x1B[0m $ '); - term.focus(); - this.term = term; - // if (term._initialized) { - // return - // } - // term._initialized = true - // term.prompt = () => { - // term.write('\r\n$ ') - // } - - // term.writeln('Welcome to xterm.js') - // term.writeln('This is a local terminal emulation, Type some keys and commands to play around') - // term.writeln('') - // term.prompt() - - // // xterm.4.x 输入 - // term.onKey(e => { - // const ev = e.domEvent - // const printable = !ev.altKey && !ev.altGraphKey && !ev.ctrlKey && !ev.metaKey - // if (ev.keyCode === 13) { - // term.prompt() - // } else if (ev.keyCode === 8) { - // // Do not delete the prompt - // if (term._core.buffer.x > 2) { - // term.write('\b \b') - // } - // } else if (printable) { - // term.write(e.key); - // this.socket.send(e.key); - // } - // }) - // this.term = term - }, - // //事件 - // 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")); - }, - initSocket() { - const wsurl = 'ws://172.16.0.120:30598/ws/target-19-austria-80-110-35-0-24/target-19-relay-127-54b5df76f4-8958g/relay-127' - this.socket = new WebSocket(wsurl); - this.socketOnClose(); - this.socketOnOpen(); - this.socketOnError(); - }, - socketOnOpen() { - this.socket.onopen = () => { - console.log('socket 连接成功') - // 链接成功后 - this.initTerm() - } - // this.socket.onmessage = function(evt) { - // // let str = new TextDecoder().decode(evt.data); - // // console.log('onmessage=====', evt) - // this.term.write(evt.data); - // }; - // //返回 - // this.socket.onmessage = function(evt) { - // // let str = new TextDecoder().decode(evt.data); - // console.log('onmessage=====', evt) - // this.term.write(evt.data); - // }; - }, - socketOnClose() { - this.socket.onclose = (e) => { - console.log('socket 关闭:' + '错误码==' + e.code + ';错误原因==' + e.reason + ';wasClean==' + e.wasClean) - } - }, - socketOnError() { - this.socket.onerror = () => { - console.log('socket 连接失败') - } - } - }, -}; -</script> - -<style lang='less' scoped="scoped"> -// .content { -// ::v-deep .el-textarea__inner { -// background-color: #1A2648; -// } -// } -.xterm-screen{ - min-height: calc(100vh); -} -</style> -<style scoped> - h1, h2 { - font-weight: normal; -} -ul { - list-style-type: none; - padding: 0; -} -li { - display: inline-block; - margin: 0 10px; -} -a { - color: #42b983; -} - -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/detail/console/module/ControlConsole4.vue b/src/views/rangeNodeManage/detail/console/module/ControlConsole4.vue deleted file mode 100644 index 778bea4..0000000 --- a/src/views/rangeNodeManage/detail/console/module/ControlConsole4.vue +++ /dev/null @@ -1,349 +0,0 @@ -<template> - <div - style="height: 100%; - background: #002833;" - > - <div class="indexContainer" id="terminal" ref="terminal"></div> - </div> - </template> - - <script> - // 引入xterm,请注意这里和3.x版本的引入路径不一样 - import { Terminal } from "xterm"; - import "xterm/css/xterm.css"; - import "xterm/lib/xterm.js"; - import { FitAddon } from "xterm-addon-fit"; - - export default { - name: "Shell", - data() { - return { - nodeId: '', - shellWs: "", - term: "", // 保存terminal实例 - rows: 40, - cols: 100, - urlParam: { - Tag: 'tag', - name: 'name', - pod: 'pod' - } - }; - }, - watch: { - '$store.state.range.nodeId': { - handler(newVal, oldVal) { - this.nodeId = newVal - }, - immediate: true - } - }, - created() { - this.getWebsocketUrl() - }, - - mounted() { - let _this = this; - localStorage.setItem('commands', '') - // 获取容器宽高/字号大小,定义行数和列数 - // this.rows = document.querySelector(".indexContainer").offsetHeight / 16 - 6; - // this.cols = document.querySelector(".indexContainer").offsetWidth / 14; - - let term = new Terminal({ - rendererType: "canvas", //渲染类型 - // rows: parseInt(_this.rows), //行数 - // cols: parseInt(_this.cols), // 不指定行数,自动回车后光标从下一行开始 - convertEol: true, //启用时,光标将设置为下一行的开头 - // scrollback: 50, //终端中的回滚量 - disableStdin: false, //是否应禁用输入。 - cursorStyle: "underline", //光标样式 - cursorBlink: true, //光标闪烁 - theme: { - foreground: "#7e9192", //字体 - background: "#002833", //背景色 - cursor: "help", //设置光标 - lineHeight: 16 - } - }); - - // 创建terminal实例 - term.open(this.$refs["terminal"]); - - // 换行并输入起始符“$” - term.prompt = () => { - term.write("\r\n$ "); - }; - term.prompt(); - - // // canvas背景全屏 - var fitAddon = new FitAddon(); - term.loadAddon(fitAddon); - fitAddon.fit(); - - window.addEventListener("resize", resizeScreen); - - // 内容全屏显示 - function resizeScreen() { - // 不传size - - try { - fitAddon.fit(); - - // 窗口大小改变时触发xterm的resize方法,向后端发送行列数,格式由后端决定 - // 这里不使用size默认参数,因为改变窗口大小只会改变size中的列数而不能改变行数,所以这里不使用size.clos,而直接使用获取我们根据窗口大小计算出来的行列数 - term.onResize(() => { - _this.onSend({ Op: "resize", Cols: term.cols, Rows: term.rows }); - }); - } catch (e) { - console.log("e", e.message); - } - } - - // function runFakeTerminal(_this) { - // if (term._initialized) { - // return; - // } - // // 初始化 - // term._initialized = true; - - // term.writeln("Welcome to use Superman. "); - // term.writeln( - // `This is Web Terminal of pod\x1B[1;3;31m ${ - // _this.urlParam.podName - // }\x1B[0m in namespace\x1B[1;3;31m ${_this.urlParam.namespace}\x1B[0m` - // ); - - // term.prompt(); - - // // / ** - // // *添加事件监听器,用于按下键时的事件。事件值包含 - // // *将在data事件以及DOM事件中发送的字符串 - // // *触发了它。 - // // * @返回一个IDisposable停止监听。 - // // * / - // // / ** 更新:xterm 4.x(新增) - // // *为数据事件触发时添加事件侦听器。发生这种情况 - // // *用户输入或粘贴到终端时的示例。事件值 - // // *是`string`结果的结果,在典型的设置中,应该通过 - // // *到支持pty。 - // // * @返回一个IDisposable停止监听。 - // // * / - // // 支持输入与粘贴方法 - // term.onData(function(key) { - // let order = { - // Data: key, - // Op: "stdin" - // }; - // _this.onSend(key); - // // 为解决窗体resize方法才会向后端发送列数和行数,所以页面加载时也要触发此方法 - // _this.onSend({ - // Op: "resize", - // Cols: parseInt(term.cols), - // Rows: parseInt(term.rows) - // }); - // }); - - // _this.term = term; - // } - // runFakeTerminal(_this); - function runFakeTerminal(_this) { - if (term._initialized) { - return; - } - - term._initialized = true; - - term.prompt = () => { - term.write("\r\n "); - }; - - term.writeln("Welcome to xterm.js"); - term.writeln( - "This is a local terminal emulation, without a real terminal in the back-end." - ); - term.writeln("Type some keys and commands to play around."); - term.writeln(""); - term.prompt(); - - // 监控键盘输入事件 - // / ** - // *添加事件监听器,用于按下键时的事件。事件值包含 - // *将在data事件以及DOM事件中发送的字符串 - // *触发了它。 - // * @返回一个IDisposable停止监听。 - // * / - // 添加事件监听器,支持输入方法 - term.onData( function (key) { - if (key.charCodeAt(0) == 13) { // 回车 - if(_this.command === 'clear') { - term.clear() - } - if (_this.command.trim().length === 0) { - term.prompt() - } else { - // 保存命令 - let commands = localStorage.getItem('commands') ? JSON.parse(localStorage.getItem('commands')) : [] - commands.push(_this.command) - localStorage.setItem('commands', JSON.stringify(commands)) - localStorage.setItem('index', commands.length) - // _this.sendData(0) - _this.onSend(localStorage.getItem('commands')) - } - _this.command = '' - } else if (key === '\u001b[A') { // 向上方向 - let commands = localStorage.getItem('commands') ? JSON.parse(localStorage.getItem('commands')) : [] - // console.log(commands) - let index = localStorage.getItem('index') ? localStorage.getItem('index') : commands.length - index = parseInt(index) - if (commands.length && index < commands.length + 1 && index > 0) { - // 删除现有命令 - for (let i = 0; i < _this.command.length; i++) { - if (term._core.buffer.x > (_this.sshPrompt.length + 2)) { - term.write('\b \b') - } - } - _this.command = commands[index - 1] - term.write(_this.command) - localStorage.setItem('index', index - 1) - } - } else if (key === '\u001b[B') { // 向下方向 - let commands = localStorage.getItem('commands') ? JSON.parse(localStorage.getItem('commands')) : [] - let index = localStorage.getItem('index') ? localStorage.getItem('index') : commands.length - index = parseInt(index) - if (commands.length && index < commands.length - 1 && index > -1) { - // 删除现有命令 - for (let i = 0; i < _this.command.length; i++) { - if (term._core.buffer.x > (_this.sshPrompt.length + 2)) { - term.write('\b \b') - } - } - _this.command = commands[index + 1] - term.write(_this.command) - localStorage.setItem('index', index + 1) - } - } else if (key.charCodeAt(0) === 9) { // tab键 - let params = { - consoleUUID: _this.activeMsf, - cmd: _this.command - } - // tab补全 - _this.$apis.readTabsComplete(params).then((res) => { - if (res.code === 200) { - if (res.data.length) { - for (let i = 0; i < _this.command.length; i++) { - term.write('\b \b') - } - let data = res.data.join('\r\n') - _this.command = res.data[res.data.length - 1] - if (res.data.length > 1) { - term.write('\r\n') - term.write(data) - term.prompt() - term.write(res.data[res.data.length - 1]) - } else { - term.write(_this.command) - } - } - } else { - _this.$message.error(res.message()) - } - }) - } else if (key.charCodeAt(0) === 127) { - if (term._core.buffer.x > (_this.sshPrompt.length + 2)) { - term.write('\b \b') - _this.command = _this.command.substr(0, _this.command.length - 1) - } - } else{ - _this.command += key - term.write(key) - } - }) - - _this.term = term; - - // 粘贴事件 - term.onData(function(data) { - _this.order = data; - term.write(data); - }); - } - runFakeTerminal(_this); - }, - - methods: { - - /** - * **wsShell 创建页面级别的websocket,加载页面数据 - * ws 接口:/xxx/xxx/xxx - * 参数:无 - * ws参数: - * @deployId 任务id - * @tagString 当前节点 - * 返回:无 - * **/ - wsShell(url) { - const _this = this; - let tag = this.urlParam.Tag; - let name= this.urlParam.name; - let pod= this.urlParam.pod; - - // let query = `?tag=${tag}&name=${name}&pod=${pod}`; - // let url = `xxxx/xxxx${query}`;// websocket连接接口 - // let url = 'ws://172.16.0.120:30598/ws/target-19-austria-80-110-35-0-24/target-19-relay-127-54b5df76f4-8958g/relay-127' - - this.shellWs = this.websoketLib.WS({ - url, - isInit: true, - openFn(e) { - console.log('连接websocket成功===', e) - // _this.term.resize({ rows: _this.rows, cols: 100 }); //终端窗口重新设置大小 并触发term.on("resize") - }, - messageFn(e) { - console.log("message", e); - if (e) { - _this.term.write(e.data); - // let data = JSON.parse(e.data); - // if (data.Data == "\n" || data.Data == "\r\nexit\r\n") { - // _this.$message("连接已关闭"); - // } - // 打印后端返回数据 - // _this.term.write(data.Data); - } - }, - errorFn(e) { - //出现错误关闭当前ws,并且提示 - console.log("error", e); - _this.$message.error({ - message: "ws 请求失败,请刷新重试~", - duration: 5000 - }); - } - }); - }, - - onSend(data) { - // data = this.websoketLib.isObject(data) ? JSON.stringify(data) : data; - // data = this.websoketLib.isArray(data) ? data.toString() : data; - // data = data.replace(/\\\\/, "\\"); - this.shellWs.onSend(data); - }, - - //删除左右两端的空格 - trim(str) { - return str.replace(/(^\s*)|(\s*$)/g, ""); - }, - // 获取websocket地址 - getWebsocketUrl() { - const reqParams = { node_id: this.nodeId } - this.$axios.get(this.$http.api.getWebsocketUrl, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.wsShell(res.result) - } - }).catch(err => { - console.log(err) - }) - } - } - }; - </script> -
\ No newline at end of file diff --git a/src/views/rangeNodeManage/detail/console/module/DirNameForm.vue b/src/views/rangeNodeManage/detail/console/module/DirNameForm.vue deleted file mode 100644 index 55ac4ca..0000000 --- a/src/views/rangeNodeManage/detail/console/module/DirNameForm.vue +++ /dev/null @@ -1,95 +0,0 @@ -<template> -<div class="role-dialog" v-if="visible"> - <i class="el-icon-close" style="float: right; padding-right: 7%;padding-top: 2.8%" @click="close"></i> - <div class="fbs"> - <span style="margin-right: 3%">文件名</span> - <el-input - size="mini" - :value="value" - placeholder="请输入内容" - style="width: 50%" - v-bind="$attrs" - v-on="$listeners"> - </el-input> - </div> - <div class="anDiv"> - <div> - <el-button class="glBut" type="primary" @click="submit">确认</el-button> - </div> - </div> -</div> -</template> - -<script> -export default { - name: 'RoleForm', - props: { - value: { - typeof: String, - require: true, - default: '' - } - }, - data() { - return { - visible: false - } - }, - watch: { - value: { - handler(val) { - this.$emit('input', val) - } - } - }, - methods: { - close() { - // document.querySelector('.mask').style.display = 'none' - this.visible = false - }, - submit() { - // document.querySelector('.mask').style.display = 'none' - this.visible = false - this.$emit('makeDirSubmit') - } - } - -} -</script> - -<style lang="less" scoped> -.role-dialog{ - z-index: 998; - width: 300px; - height: 120px; - position: absolute; /* 绝对定位 */ - top: 100px; /* 向下偏移50% */ - left: 150px; /* 向右偏移50% */ - transform: translate(-50%, -50%); /* 回移50% */ - background-image:url('../../../../../img/jbpzxybqr.png'); - background-repeat: no-repeat; /* 可选,防止图像重复 */ - background-size: 100% 100%; /* 宽度为100%,高度自适应保持宽高比 */ - .fbs{ - width: 100%; - float: left; - margin-top: 3%; - text-align: center; - } - .anDiv{ - width: 100%; - float: left; - margin-top: 5%; - text-align: center; - .glBut{ - width: 50px; - height: 18px; - display: inline-flex; - align-items: center; - justify-content: center; - margin-left: 5%; - background-color: rgba(24, 133, 234, 0.2); - color: #1b7cc4; - } - } -} -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/detail/console/module/FileManage.vue b/src/views/rangeNodeManage/detail/console/module/FileManage.vue deleted file mode 100644 index df28f48..0000000 --- a/src/views/rangeNodeManage/detail/console/module/FileManage.vue +++ /dev/null @@ -1,538 +0,0 @@ -<template> -<div class="content"> - <el-tree - ref="tree" - class="tree-section" - lazy - node-key="id" - :data="treeData" - :props="defaultProps" - :load="loadNode" - @node-click="handleNodeClick" - @node-contextmenu="openTreeMenu" - v-dragresize="dragConfig" - > - </el-tree> - <div class="tree-content"> - <div style="text-align:left; width: 100%; padding: 10px;border: 1px solid #BAD0F11A;"> - <span> - {{ dirTitle }} - </span> - </div> - <div style="clear:both;text-align:left; padding: 10px;border-bottom: 1px solid #BAD0F11A;"> - <img src="../../../../../img/icon/file-icon.svg" alt="" style="width: 18px; height: 18px;"> - {{ currentFileName }} - </div> - <ul style="clear:both;" class="tree-content-ul"> - <li v-for="fileItem in fileList" :key="fileItem.name" @contextmenu.prevent="openMenu(fileItem, $event)"> - <i class="el-icon-document file-info" style="font-size: 20px"></i> - <span class="file-info">{{ fileItem.name }}</span> - <span class="file-info">{{ fileItem.size }}</span> - <span class="file-info">{{ fileItem.time }}</span> - </li> - </ul> - <div class="empty-box" @contextmenu.prevent="openUploadMenu($event)"></div> - </div> - <ul - v-show="visible" - :style="{left:left+'px',top:top+'px'}" - class="contextmenu" - > - <li> - <label - class="button" - for="file-input" - > - <span>上传</span> - <input - type="file" - class="file-input" - id="file-input" - @change="upload" - /> - </label> - </li> - <li @click="download">下载</li> - <li @click="del">删除</li> - </ul> - <ul - v-show="uploadVisible" - :style="{left:left+'px',top:top+'px'}" - class="contextmenu" - > - <li> - <label - class="button" - for="file-input" - > - <span>上传</span> - <input - type="file" - class="file-input" - id="file-input" - @change="upload" - /> - </label> - </li> - </ul> - <div v-show="showTreeMenu" class="treeMenu"> - <div @click="makeDir">新建文件夹</div> - <div @click="delDir">删除文件夹</div> - </div> - <DirNameForm - ref="dirNameForm" - v-model="dirName" - @makeDirSubmit="makeDirSubmit"> - </DirNameForm> -</div> -</template> - -<script> -import DirNameForm from './DirNameForm.vue' -export default { -components: { DirNameForm }, -props: ['isFullscreen'], -data() { - return{ - visible: false, - uploadVisible: false, - top: 0, - left: 0, - nodeId: '', - dirTitle: '>', - currentFileName: '', - fileList: [], - selectFile: {}, - selectNode: {path: '/'}, - rightClickNode: {}, - defaultProps: { - children: 'children', - label: 'name', - }, - showTreeMenu: false, // 文件夹数据 - contextNode: {}, // 文件夹数据 - dirName: '', // 新建文件名 - treeData: [] - } -}, -computed: { - dragConfig() { - return [ - { - dragBorder: "right", - setCssProperty: "width", - }, - ]; - }, -}, -watch: { - '$store.state.range.nodeId': { - handler(newVal, oldVal) { - this.nodeId = newVal - // this.getCurrentDirFile('/') - }, - immediate: true - }, - visible(value) { - if (value) { - document.body.addEventListener('click', this.closeMenu) - } else { - document.body.removeEventListener('click', this.closeMenu) - } - }, - uploadVisible(value) { - if (value) { - document.body.addEventListener('click', this.closeUploadMenu) - } else { - document.body.removeEventListener('click', this.closeUploadMenu) - } - }, -}, -methods: { - upload(e) { - const params = { - node_id : this.nodeId, - current_dir: this.selectNode.path, - file: e.target.files[0] - } - const submitForm = new FormData() - for(const key in params) { - submitForm.append(key, params[key]) - } - this.$axios.postFormData(this.$http.api.uploadFile, submitForm).then(res => { - if (res.code == 200 || res.code == "OK") { - this.$notify({ - title: '上传文件成功', - type: 'success', - duration: 2500 - }) - // this.$refs.tree.remove(item.id); - // this.setCurrentHighlight(null); - // console.log('选中了节点id===', this.selectNode.$treeNodeId) - // 更新当前路径下的文件信息 - this.handleNodeClick(this.selectNode) - this.setCurrentHighlight(this.selectNode.$treeNodeId); - // this.init() - } - }).catch(err => { - console.log(err) - }) - }, - download() { - // this.downLoading = true - const reqParams = { - node_id : this.nodeId, - current_dir: this.selectNode.path, - filename: this.selectFile.name - } - this.$axios.getFile(this.$http.api.downloadFile, reqParams).then(res => { - if (res.status == 200 || res.statusText == "OK") { - const { data, headers } = res - const fileName = headers['content-disposition'].replace(/\w+;filename=(.*)/, '$1') - // 此处当返回json文件时需要先对data进行JSON.stringify处理,其他类型文件不用做处理 - //const blob = new Blob([JSON.stringify(data)], ...) - const blob = new Blob([data], {type: headers['content-type']}) - let dom = document.createElement('a') - let url = window.URL.createObjectURL(blob) - dom.href = url - dom.download = decodeURI(fileName) - dom.style.display = 'none' - document.body.appendChild(dom) - dom.click() - dom.parentNode.removeChild(dom) - window.URL.revokeObjectURL(url) - this.$notify({ - title: '下载文件成功', - type: 'success', - duration: 2500 - }) - } else { - this.$notify({ - title: '下载文件失败', - type: 'success', - duration: 2500 - }) - } - }).catch(err => { - console.log(err) - }).finally(() => { - // this.downLoading = false - }) - }, - del() { - const params = { - node_id : this.nodeId, - current_dir: this.selectNode.path, - filename: this.selectFile.name - } - this.$axios.delete(this.$http.api.delFile, params).then(res => { - if (res.code == 200 || res.code == "OK") { - this.$notify({ - title: '删除文件成功', - type: 'success', - duration: 2500 - }) - // 更新当前路径下的文件信息 - this.handleNodeClick(this.selectNode) - // console.log('选中了节点id===', this.selectNode.$treeNodeId) - this.setCurrentHighlight(this.selectNode.$treeNodeId); - // this.init() - } - }).catch(err => { - console.log(err) - }) - }, - // 设置当前选中高亮 - setCurrentHighlight (id) { - this.$nextTick(() => { - this.$refs.tree.setCurrentKey(id) - }) - }, - openMenu(fileItem, e) { - const menuMinWidth = 105 - const offsetLeft = this.$el.getBoundingClientRect().left // container margin left - const offsetWidth = this.$el.offsetWidth // container width - const maxLeft = offsetWidth - menuMinWidth // left boundary - const left = e.clientX - offsetLeft + 60 // 15: margin right - - if (left > maxLeft) { - this.left = maxLeft - } else { - this.left = left - } - - if (this.isFullscreen) { - this.top = e.clientY - 180 // fix 位置bug - } else { - this.top = e.clientY - 600 // fix 位置bug - } - this.uploadVisible = false - this.visible = true - this.selectFile = fileItem - }, - closeMenu() { - this.visible = false - }, - openUploadMenu(e) { - const menuMinWidth = 105 - const offsetLeft = this.$el.getBoundingClientRect().left // container margin left - const offsetWidth = this.$el.offsetWidth // container width - const maxLeft = offsetWidth - menuMinWidth // left boundary - const left = e.clientX - offsetLeft + 60 // 15: margin right - - if (left > maxLeft) { - this.left = maxLeft - } else { - this.left = left - } - - if (this.isFullscreen) { - this.top = e.clientY - 120 // fix 位置bug - } else { - this.top = e.clientY - 600 // fix 位置bug - } - this.visible = false - this.uploadVisible = true - }, - closeUploadMenu() { - this.uploadVisible = false - }, - // 获取当前路径下文件 - getCurrentDirFile(currentDir) { - const reqParams = { node_id: this.nodeId, current_dir: currentDir } - return this.$axios.get(this.$http.api.getCurrentDir, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - const dirs = res?.result?.object?.dir || [] - this.fileList = res?.result?.object?.file || [] - // console.log('请求回来files===', files) - const nodeData = dirs.map(dir => { - return { - name: dir.name, - path: currentDir === '/' ? currentDir + dir.name : `${currentDir}/${dir.name}`, - fileList: [] - } - }) - // console.log('请求回来nodeData====', nodeData) - return nodeData - } - }).catch(err => { - console.log(err) - }) - }, - // 点击加载子节点 - async loadNode(node, reslove) { - // console.log('执行了loadNode', node) - if (node.level == 0) { - let nodeData = await this.getCurrentDirFile('/') - // console.log('初始化数据===', nodeData) - // this.selectNode = nodeData.fileList - return reslove(nodeData) - } else { - let nodeData = await this.getCurrentDirFile(node.data.path) - // 判断是否为最底层节点 根据自己接口返回的数据判断即可 - nodeData.forEach(item => { - item.hasChildren == false ? item.lastNode = ture : null - }); - // this.selectNode = nodeData.fileList - return reslove(nodeData) - } - }, - handleNodeClick(node) { - // this.fileList = [] - // console.log('选中了节点===', node) - // console.log('选中了节点id===', node.$treeNodeId) - this.selectNode = node - this.dirTitle = node.path.split('/').join('>') - this.currentFileName = node.name - // this.fileList = node.fileList - const reqParams = { node_id: this.nodeId, current_dir: node.path } - this.$axios.get(this.$http.api.getCurrentDir, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.fileList = res?.result?.object?.file || [] - } - }).catch(err => { - console.log(err) - }) - }, - openTreeMenu(event, data, node, target) { - // console.log(event, data, node, target) - this.showTreeMenu = true // 显示菜单 - this.contextNode = data // 存储数据 - // console.log(this.contextNode, 'contextNode') - // console.log(node, 'rightClickNode=======') - // console.log(target, 'target') - this.rightClickNode = node - document.querySelector('.treeMenu').setAttribute('style',`top:${event.clientY + 30}px;left:${event.clientX + 30}px;`) - document.addEventListener('click', this.closeTreeMenu) - document.addEventListener('contextmenu', this.closeTreeMenu) - }, - closeTreeMenu() { - this.showTreeMenu = false // 关闭菜单 - document.removeEventListener('click', this.closeTreeMenu) - document.removeEventListener('contextmenu', this.closeTreeMenu) - }, - // 当新建文件夹时,先填写名字 - openDirNameForm() { - this.$refs.dirNameForm.visible = true - }, - // 新建文件夹 - makeDir() { - this.openDirNameForm() - }, - // 新建文件夹接口提交 - makeDirSubmit() { - const reqParams = { node_id: this.nodeId, current_dir: this.contextNode.path, new_dir_name: this.dirName } - this.$axios.get(this.$http.api.makeDir, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.$notify({ - title: '新建文件夹成功', - type: 'success', - duration: 2500 - }) - // 页面增加子节点 - let id = Math.ceil(Math.random() * 1000000) - var addNode = { - path: this.contextNode.path + '/' + this.dirName, - name: this.dirName, - fileList: [] - // id: id, - // name: this.dirName, - // data: { - // path: this.contextNode.path, - // name: this.dirName, - // fileList: [] - // } - } - // console.log(addNode, 'addNode======') - this.$refs.tree.append(addNode, this.rightClickNode) - } - }).catch(err => { - console.log(err) - }) - }, - // 删除文件夹 - delDir() { - const index = this.contextNode.path.lastIndexOf('/') - const path = this.contextNode.path.substring(0, index); - const params = { - node_id : this.nodeId, - current_dir: path, - dir_name: this.contextNode.name - } - this.$axios.delete(this.$http.api.delDir, params).then(res => { - if (res.code == 200 || res.code == "OK") { - this.$notify({ - title: '删除文件成功', - type: 'success', - duration: 2500 - }) - // 页面删除子节点 - this.$refs.tree.remove(this.rightClickNode) - } - }).catch(err => { - console.log(err) - }) - } -} -} -</script> - -<style lang='less' scoped="scoped"> -.content { - width: 100%; - height: 100%; - display: flex; - flex-direction: row; - color: #ffffff; - .tree-section { - width: 25%; - height: 100%; - // background-color: #1A2648; - background: transparent; - border: 1px solid #BAD0F11A; - color: #06F7FF; - overflow-y: auto; - ::v-deep .el-tree-node__content:hover { - background-color: rgba(14, 61, 138, 0.3) !important; - } - ::v-deep .el-tree-node.is-current > .el-tree-node__content { - background-color: rgba(14, 61, 138, 0.3) !important; - } - } - .tree-content { - width: 75%; - height: 100%; - display: flex; - flex-direction: column; - .tree-content-ul { - width: 100%; - background-color: rgba(25, 33, 61, 0.4); - overflow-y: auto; - li { - display: flex; - flex-direction: row; - justify-content: space-around; - border-bottom: 1px solid #BAD0F11A; - padding: 5px; - .file-info { - flex: 1 1 100px; - } - } - } - .empty-box { - flex: 1; - } - } -} -.contextmenu { - margin: 0; - border-radius: 6px; - border: 0.5px solid rgba(6, 247, 255, 0.20); - background: #0E3D8A; - z-index: 3000; - position: absolute; - list-style-type: none; - padding: 5px 0; - font-size: 12px; - font-weight: 400; - color: #06F7FF; - // box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3); - box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.10), 0px 8px 10px 1px rgba(0, 0, 0, 0.06), 0px 3px 14px 2px rgba(0, 0, 0, 0.05); - li { - margin: 0; - padding: 7px 30px; - cursor: pointer; - &:hover { - border-radius: 3px; - background: rgba(6, 247, 255, 0.10); - } - } - .file-input { - display: none; - } - } - -.treeMenu { - position: fixed; - z-index: 99999; - top: 50%; - left: 50%; - color: #06F7FF; - background-color: #0E3D8A; - overflow: hidden; - border-radius: 5px; - border: 0.5px solid rgba(6, 247, 255, 0.20); - box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.10), 0px 8px 10px 1px rgba(0, 0, 0, 0.06), 0px 3px 14px 2px rgba(0, 0, 0, 0.05); - div{ - padding: 7px 30px; - box-sizing: border-box; - //width: 50px; - text-align: center; - } - div:hover{ - border-radius: 3px; - background: rgba(6, 247, 255, 0.10); - cursor: pointer; - } -} -</style>
\ No newline at end of file |
