diff options
| author | ll <[email protected]> | 2024-07-11 20:41:37 +0800 |
|---|---|---|
| committer | ll <[email protected]> | 2024-07-11 20:41:37 +0800 |
| commit | bafa736c04845e103d7e3747a8152b410d1628fb (patch) | |
| tree | 032d00938963b7cb21ff5c57e4f08723b521ae41 /src/views/rangeNodeManage | |
| parent | ac8bc7f895baa346cdb498e1b8be41ce66130afd (diff) | |
Diffstat (limited to 'src/views/rangeNodeManage')
41 files changed, 0 insertions, 8597 deletions
diff --git a/src/views/rangeNodeManage/detail/console/index.vue b/src/views/rangeNodeManage/detail/console/index.vue deleted file mode 100644 index 7ab20ca..0000000 --- a/src/views/rangeNodeManage/detail/console/index.vue +++ /dev/null @@ -1,220 +0,0 @@ -<template> -<div :class="['tabs', {'is--maximize': isFullscreen}]"> - <el-tabs - v-model="activeName" - @tab-click="handleClick" - > - <el-tab-pane label="控制台" name="first"> - <ControlConsole ref="controlConsole"></ControlConsole> - </el-tab-pane> - <el-tab-pane label="文件管理" name="second"> - <FileManage :is-fullscreen="isFullscreen"></FileManage> - </el-tab-pane> - </el-tabs> - <el-button class="console-btn" v-if="activeName === 'first'" :loading="consoleLoading" type="primary" @click="openConsoleTab">打开控制台</el-button> - <span class="icon-span" slot="label"> - <i v-if="closeIcon" class="el-icon-close icon-zoom" @click="backNodeList"></i> - <svg-icon v-else class="icon-zoom" :icon-class="fullscreenIcon" @click="zoomEvent"></svg-icon> - </span> -</div> -</template> - -<script> -import ControlConsole from './module/ControlConsole' -import FileManage from './module/FileManage' -export default { - components: { ControlConsole, FileManage }, - data() { - return { - activeName: 'first', - nodeId: '', - // consoleUrl: '', - fullscreenIcon: 'fullscreen', - isFullscreen: false, - closeIcon: false, - consoleLoading: false - }; - }, - watch: { - '$store.state.range.nodeId': { - handler(newVal, oldVal) { - this.nodeId = newVal - // this.init() - }, - immediate: true - } - }, - mounted() { - this.closeIcon = this.$route.params.closeIcon - }, - methods: { - backNodeList() { - this.$router.push({ name: 'rangeNodeManage' }) - }, - handleClick(tab, event) { - console.log(tab, event); - }, - openConsoleTab() { - // 获取webshell地址,用浏览器打开 - const reqParams = { node_id: this.nodeId } - this.consoleLoading = true - this.$axios.get(this.$http.api.getWebshell, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - const consoleUrl = 'http://' + window.g.baseURL + '/' + res?.result - window.open(consoleUrl, '_blank') - // var newWindow = window.open(consoleUrl , '_blank'); - // // 等待新页面加载完成 - // newWindow.onload = function() { - // console.log('1111111111111111') - // // 选择用户名输入框 - // var usernameInput = newWindow.document.querySelector('input[name="username"]'); - // // 选择密码输入框 - // var passwordInput = newWindow.document.querySelector('input[name="password"]'); - // // 选择登录按钮 - // var loginButton = newWindow.document.querySelector('button[type="submit"]'); - // console.log(usernameInput, 'usernameInput====') - - // // 如果输入框存在,则自动输入用户名和密码 - // if (usernameInput && passwordInput && loginButton) { - // usernameInput.value = 'admin'; - // passwordInput.value = 'Bjhit@2020'; - - // // 触发登录按钮的点击事件 - // loginButton.click(); - // } - // }; - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.consoleLoading = false - }) - }, - zoomEvent() { - if (this.activeName === 'first') { - - this.isFullscreen = !this.isFullscreen - this.fullscreenIcon = this.isFullscreen ? 'narrow' : 'fullscreen' - // this.$refs.controlConsole.resize() - } else { - this.isFullscreen = !this.isFullscreen - this.fullscreenIcon = this.isFullscreen ? 'narrow' : 'fullscreen' - } - }, - findNthOccurrence(str, char, n) { - let index = str.indexOf(char) - while (--n > 0 && index !== -1) { - index = str.indexOf(char, index + 1) - } - return index - } - } -} -</script> - -<style lang='less' scoped="scoped"> -.is--maximize { - position: fixed !important; - top: 9%; - left: 10%; - width: 90% !important; - height: 91% !important; - padding: 0.5em 1em; - // background-color: #17234e; - background: url(../../../../img/background/bgMain.svg); - background-repeat: no-repeat; /* 可选,防止图像重复 */ - background-position: center; /* 居中显示 */ - background-size: cover; /* 宽度为100%,高度自适应保持宽高比 */ - z-index: 1000; -} -// ::v-deep #tab-zoom { -// border: none; -// background-color: #1b202e !important; -// position: absolute; -// top: 1px; -// right: 0; -// font-weight: 500; -// font-size: 15px; -// color: #fff !important; -// } -.tabs { - width: 100%; - height: calc(100% - 15px); - text-align: center; - position: relative; - padding: 0 0; - // display: flex; - // .detail-title { - // position:absolute; - // margin: 10px; - // } -} -::v-deep .el-tabs{ - color: #000; - left: 0px; - top: 0px; - padding: 0 0; - width: 100%; - height: 100%; - position: relative; - .el-tabs__header { - margin: 15px 30px; - } - .el-tabs__content { - width: 100%; - height: calc(100% - 50px); - .el-tab-pane { - width: 100%; - height: 100%; - } - } -} -/* 去除灰色横条 */ -::v-deep .el-tabs__nav-wrap::after { - position: static !important; -} -/* 设置滑块颜色 */ -::v-deep .el-tabs__active-bar{ - background-color: #0E3D8A !important; -} -/* 设置滑块停止位置 */ -::v-deep .el-tabs__active-bar.is-top{ - height: 37px; - width: 104px ! important; - border-radius: 17px; - top: 0px !important; - left: -18px !important; - position: absolute !important; - z-index: 1; -} -/* 设置当前选中样式 */ -::v-deep .el-tabs__item.is-active{ - color:#02DDEA !important; - z-index: 2; -} -/* 设置未被选中样式 */ -::v-deep .el-tabs__item{ - padding: 0 20px !important; - width: 104px; - box-sizing: border-box; - display: inline-block; - position: relative !important; - color:#02DDEA !important; - z-index: 2; -} -.console-btn { - position: absolute; - top: 5px; - right: 100px; -} -.icon-span { - position: absolute; - top: 10px; - right: 30px; - .icon-zoom { - font-size: 30px; - color: #02DDEA; - margin: 0 15px; - } -} -</style>
\ No newline at end of file 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 diff --git a/src/views/rangeNodeManage/detail/detail/index.vue b/src/views/rangeNodeManage/detail/detail/index.vue deleted file mode 100644 index 0a254c1..0000000 --- a/src/views/rangeNodeManage/detail/detail/index.vue +++ /dev/null @@ -1,107 +0,0 @@ -<template> -<div class="tabs"> - <i class="el-icon-back back-btn" @click="backNodeList"></i> - <el-tabs v-model="activeName" @tab-click="handleClick"> - <el-tab-pane label="详细信息" name="second"> - <DetailInfo></DetailInfo> - </el-tab-pane> - <el-tab-pane label="资源监控" name="third"> - <ResourceMonitor v-if="activeName==='third'"></ResourceMonitor> - </el-tab-pane> - </el-tabs> -</div> -</template> - -<script> -import DetailInfo from './module/DetailInfo' -import ResourceMonitor from './module/ResourceMonitor' -export default { - components: { DetailInfo, ResourceMonitor }, - data() { - return { - activeName: 'second' - }; - }, - methods: { - handleClick(tab, event) { - }, - backNodeList() { - this.$router.push({ name: 'rangeNodeManage' }) - } - } -} -</script> - -<style lang='less' scoped="scoped"> -.tabs { - width: 100%; - height: 100%; - text-align: center; - position: relative; - padding: 8px 0 0; - display: flex; - .detail-title { - position:absolute; - margin: 10px; - } - .back-btn { - position: absolute; - cursor: pointer; - font-size: 30px; - color: #02DDEA; - margin: 5px; - z-index: 10; - } -} -::v-deep .el-tabs{ - color: #000; - left: 0px; - top: 0px; - width: 100%; - height: 100%; - position: relative; - .el-tabs__header { - margin-left: 100px; - } - .el-tabs__content{ - height: calc(100% - 48px); - // height: 100%; - .el-tab-pane{ - height: 100%; - } - } -} -/* 去除灰色横条 */ -::v-deep .el-tabs__nav-wrap::after { - position: static !important; -} -/* 设置滑块颜色 */ -::v-deep .el-tabs__active-bar{ - background-color: #0E3D8A !important; -} -/* 设置滑块停止位置 */ -::v-deep .el-tabs__active-bar.is-top{ - height: 37px; - width: 104px ! important; - border-radius: 17px; - top: 0px !important; - left: -18px !important; - position: absolute !important; - z-index: 1; -} -/* 设置当前选中样式 */ -::v-deep .el-tabs__item.is-active{ - color:#02DDEA !important; - z-index: 2; -} -/* 设置未被选中样式 */ -::v-deep .el-tabs__item{ - padding: 0 20px !important; - width: 104px; - box-sizing: border-box; - display: inline-block; - position: relative !important; - color:#02DDEA !important; - z-index: 2; -} -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/detail/detail/module/DetailInfo.vue b/src/views/rangeNodeManage/detail/detail/module/DetailInfo.vue deleted file mode 100644 index cec66d8..0000000 --- a/src/views/rangeNodeManage/detail/detail/module/DetailInfo.vue +++ /dev/null @@ -1,82 +0,0 @@ -<template> - <div class="detail-info" v-loading="loading"> - <el-descriptions :column="2"> - <el-descriptions-item label="Tor版本">{{nodeDetail.owner_setting && nodeDetail.owner_setting.tor_version}}</el-descriptions-item> - <el-descriptions-item label="状态">{{nodeDetail.status}}</el-descriptions-item> - <el-descriptions-item label="角色">{{nodeDetail.owner_setting && nodeDetail.owner_setting.role}}</el-descriptions-item> - <el-descriptions-item label="创建开始时间">{{formatTime(nodeDetail.create_time)}}</el-descriptions-item> - <el-descriptions-item label="宽带">{{nodeDetail.owner_setting && nodeDetail.owner_setting.bandwidth + ' M'}}</el-descriptions-item> - <el-descriptions-item label="创建完成时间">{{formatTime(nodeDetail.complete_time)}}</el-descriptions-item> - <el-descriptions-item label="内存">{{nodeDetail.owner_setting && nodeDetail.owner_setting.memory + ' Mi'}}</el-descriptions-item> - <el-descriptions-item label="ip">{{nodeDetail.ip}}</el-descriptions-item> - <el-descriptions-item label="sockport">{{nodeDetail.owner_setting && nodeDetail.owner_setting.socks_port}}</el-descriptions-item> - <el-descriptions-item label="pod名">{{nodeDetail.pod_name}}</el-descriptions-item> - <el-descriptions-item label="网络">{{nodeDetail.owner_setting && nodeDetail.owner_setting.use_network.cidr}}</el-descriptions-item> - <el-descriptions-item label="节点昵称">{{nodeDetail.nick_name}}</el-descriptions-item> - <el-descriptions-item v-if="nodeDetail.owner_setting && nodeDetail.owner_setting.role==='onion'" label="onion">{{nodeDetail.onion}}</el-descriptions-item> - </el-descriptions> - </div> - </template> - - <script> - import { formatTime } from '../../../../../utils' - export default { - name: 'DetailInfo', - data() { - return { - loading: false, - nodeId: '', - nodeDetail: {} - } - }, - watch: { - '$store.state.range.nodeId': { - handler(newVal, oldVal) { - this.nodeId = newVal - this.init() - }, - immediate: true - } - }, - methods: { - formatTime, - init() { - // this.nodeDetail = getTargetsResponse?.result - this.loading = true - const reqParams = { node_id: this.nodeId } - this.$axios.get(this.$http.api.getNodeDetail, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.nodeDetail = res?.result - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.loading = false - }) - } - } - } - </script> - - <style lang='less' scoped="scoped"> - .detail-info { - width: 100%; - height: 100%; - background-color: rgba(25, 33, 61, 0.4); - border: 1px solid rgba(186, 208, 241, 0.1); - border-radius: 8px; - } -.el-descriptions{ - ::v-deep .el-descriptions__body { - background-color: transparent; - .el-descriptions__table .el-descriptions-item__cell { - font-size: 16px; - font-weight: 500; - line-height: 20px; - padding-top: 20px; - padding-left: 25px; - color: rgba(255, 255, 255, 0.6); - } - } -} - </style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/detail/detail/module/ResourceMonitor.vue b/src/views/rangeNodeManage/detail/detail/module/ResourceMonitor.vue deleted file mode 100644 index 37ff85c..0000000 --- a/src/views/rangeNodeManage/detail/detail/module/ResourceMonitor.vue +++ /dev/null @@ -1,199 +0,0 @@ -<template> - <div class="dresource-monitor"> - <div class="cpu"> - <div style="width:100%;height: 100%;" id="cpu"></div> - </div> - <div class="memory"> - <div style="width:100%;height: 100%;" id="memory"></div> - </div> - </div> - </template> - - <script> - import * as echarts from 'echarts'; - import dayjs from 'dayjs' - import { getCpuResponse } from './cpuMock.js' - import { getMemoryResponse } from './memoryMock.js' - export default { - data() { - return { - nodeId: '', - cpuData: [], - cpuDataX: [], - cpuDataY: [], - memoryData: [], - memoryDataX: [], - memoryDataY: [] - } - }, - watch: { - '$store.state.range.nodeId': { - handler(newVal, oldVal) { - this.nodeId = newVal - // this.init() - }, - immediate: true - } - }, - created() { - }, - mounted() { - this.init() - }, - methods: { - init() { - // this.cpuData = getCpuResponse.result - // this.cpuData.forEach(item => { - // this.cpuDataX.push(item[0]) - // this.cpuDataY.push(item[1]) - // }) - // this.memoryData = getMemoryResponse.result - // this.memoryData.forEach(item => { - // this.memoryDataX.push(item[0]) - // this.memoryDataY.push(item[1]) - // }) - // this.setCpuEcharts() - // this.setMemoryEcharts() - - const reqParams = { - node_id: this.nodeId, - } - this.$axios.get(this.$http.api.getCpu, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.cpuData = res?.result - this.cpuData.forEach(item => { - this.cpuDataX.push(dayjs(item[0]).format('HH:mm:ss')) - this.cpuDataY.push(item[1]) - }) - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.setCpuEcharts() - }) - this.$axios.get(this.$http.api.getMemory, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.memoryData = res?.result - this.memoryData.forEach(item => { - this.memoryDataX.push(dayjs(item[0]).format('HH:mm:ss')) - this.memoryDataY.push(item[1]) - }) - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.setMemoryEcharts() - }) - }, - setCpuEcharts() { - var chartDom = document.getElementById('cpu'); - var myChart = echarts.init(chartDom); - var option; - - option = { - // color: ['rgba(61, 255, 220, 0.2)'], - grid: { - // top: '8%', - height: '55%' // 设置折线图的高度为容器高度的百分之四十 - }, - xAxis: { - type: 'category', - data: this.cpuDataX, - axisLabel: { - color: '#ffffff' - } - }, - yAxis: { - type: 'value', - name: 'cpu (mcore)', - nameTextStyle: { - color: '#ffffff' - }, - axisLine: { - show: true // 将此处改为 true 则显示 Y 轴刻度线 - // symbol: ['none', 'arrow'] - }, - splitLine: { - show: false - }, - axisLabel: { - color: '#ffffff' - } - }, - series: [ - { - data: this.cpuDataY, - type: 'line', - smooth: true - } - ] - } - option && myChart.setOption(option) - }, - - setMemoryEcharts() { - var chartDom = document.getElementById('memory'); - var myChart = echarts.init(chartDom); - var option; - - option = { - grid: { - top: '18%', - height: '55%' // 设置折线图的高度为容器高度的百分之四十 - }, - xAxis: { - type: 'category', - data: this.memoryDataX, - axisLabel: { - color: '#ffffff' - } - }, - yAxis: { - type: 'value', - name: '内存 (Mi)', - nameTextStyle: { - color: '#ffffff' - }, - axisLine: { - show: true // 将此处改为 true 则显示 Y 轴刻度线 - // symbol: ['none', 'arrow'] - }, - splitLine: { - show: false - }, - axisLabel: { - color: '#ffffff' - } - }, - series: [ - { - data: this.memoryDataY, - type: 'line', - smooth: true - } - ] - } - option && myChart.setOption(option) - } - } - - } - </script> - -<style lang='less' scoped="scoped"> -.dresource-monitor { - width: 100%; - height: 100%; - background-color: rgba(25, 33, 61, 0.4); - border: 1px solid rgba(186, 208, 241, 0.1); - border-radius: 8px; -} -.cpu { - width: 100%; - height: 50%; -} -.memory { - width: 100%; - height: 50%; -} -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/detail/detail/module/cpuMock.js b/src/views/rangeNodeManage/detail/detail/module/cpuMock.js deleted file mode 100644 index f7220e0..0000000 --- a/src/views/rangeNodeManage/detail/detail/module/cpuMock.js +++ /dev/null @@ -1,91 +0,0 @@ -const getCpuResponse = { - "code": 200, - "message": "success", - "result": [ - [ - "2024-01-06 09:33:14", - 1.757 - ], - [ - "2024-01-06 09:34:14", - 1.694 - ], - [ - "2024-01-06 09:35:14", - 1.573 - ], - [ - "2024-01-06 09:36:14", - 0.877 - ], - [ - "2024-01-06 09:37:14", - 0.774 - ], - [ - "2024-01-06 09:38:14", - 0.855 - ], - [ - "2024-01-06 09:39:14", - 0.903 - ], - [ - "2024-01-06 09:40:14", - 0.929 - ], - [ - "2024-01-06 09:41:14", - 1.135 - ], - [ - "2024-01-06 09:42:14", - 1.154 - ], - [ - "2024-01-06 09:43:14", - 0.963 - ], - [ - "2024-01-06 09:44:14", - 1.195 - ], - [ - "2024-01-06 09:45:14", - 1.128 - ], - [ - "2024-01-06 09:46:14", - 1.294 - ], - [ - "2024-01-06 09:47:14", - 1.698 - ], - [ - "2024-01-06 09:48:14", - 1.136 - ], - [ - "2024-01-06 09:49:14", - 1.554 - ], - [ - "2024-01-06 09:50:14", - 1.721 - ], - [ - "2024-01-06 09:51:14", - 1.941 - ], - [ - "2024-01-06 09:52:14", - 1.594 - ], - [ - "2024-01-06 09:53:14", - 1.955 - ] - ] - } - export { getCpuResponse }
\ No newline at end of file diff --git a/src/views/rangeNodeManage/detail/detail/module/memoryMock.js b/src/views/rangeNodeManage/detail/detail/module/memoryMock.js deleted file mode 100644 index 4197939..0000000 --- a/src/views/rangeNodeManage/detail/detail/module/memoryMock.js +++ /dev/null @@ -1,91 +0,0 @@ -const getMemoryResponse = { - "code": 200, - "message": "success", - "result": [ - [ - "2024-01-07 01:08:27", - 42.371 - ], - [ - "2024-01-07 01:09:27", - 42.371 - ], - [ - "2024-01-07 01:10:27", - 42.371 - ], - [ - "2024-01-07 01:11:27", - 42.371 - ], - [ - "2024-01-07 01:12:27", - 42.371 - ], - [ - "2024-01-07 01:13:27", - 42.371 - ], - [ - "2024-01-07 01:14:27", - 42.371 - ], - [ - "2024-01-07 01:15:27", - 42.383 - ], - [ - "2024-01-07 01:16:27", - 42.383 - ], - [ - "2024-01-07 01:17:27", - 42.383 - ], - [ - "2024-01-07 01:18:27", - 42.383 - ], - [ - "2024-01-07 01:19:27", - 42.383 - ], - [ - "2024-01-07 01:20:27", - 42.383 - ], - [ - "2024-01-07 01:21:27", - 42.383 - ], - [ - "2024-01-07 01:22:27", - 42.383 - ], - [ - "2024-01-07 01:23:27", - 42.383 - ], - [ - "2024-01-07 01:24:27", - 42.383 - ], - [ - "2024-01-07 01:25:27", - 42.395 - ], - [ - "2024-01-07 01:26:27", - 42.402 - ], - [ - "2024-01-07 01:27:27", - 42.41 - ], - [ - "2024-01-07 01:28:27", - 42.422 - ] - ] - } - export { getMemoryResponse }
\ No newline at end of file diff --git a/src/views/rangeNodeManage/detail/file/index.vue b/src/views/rangeNodeManage/detail/file/index.vue deleted file mode 100644 index d94fffc..0000000 --- a/src/views/rangeNodeManage/detail/file/index.vue +++ /dev/null @@ -1,304 +0,0 @@ -<template> -<div class="range-config-manage" ref="appRef"> - <Header - :down-loading="downLoading" - :start-loading="startLoading" - :stop-loading="stopLoading" - @download="download" - @start="start" - @end="end" - ></Header> - <div class="list" > - <el-table - class="custom-table" - ref="multipleTable" - v-loading="loading" - height="100%" - style="width: 100%;" - :data="tableData" - tooltip-effect="dark" - highlight-current-row - @selection-change="handleSelectionChange" - > - <el-table-column - align="center" - type="selection" - width="80"/> - <el-table-column - align="center" - prop="bucket_name" - label="桶名称" - min-width="100"/> - <el-table-column - align="center" - prop="file_name" - label="文件名" - min-width="250"/> - <el-table-column - align="center" - prop="size" - label="文件大小" - min-width="80"/> - <el-table-column - align="center" - prop="last_modified" - label="更新时间" - min-width="100" - > - <template slot-scope="scope"> - {{ scope.row.last_modified | formatTime }} - </template> - </el-table-column> - </el-table> - </div> - <!-- <el-pagination - background - :current-page="page" - :page-sizes="[10, 20, 30, 40]" - :page-size="10" - :total="total" - layout="total, sizes, prev, pager, next, jumper" - @size-change="handleSizeChange" - @current-change="handleCurrentChange" - > - </el-pagination> --> -</div> -</template> -<script> -import Header from './module/Header.vue' -import { getTargetsResponse } from './mock.js' -export default { - name: "File", - components:{ Header}, - data(){ - return{ - target_id: '', - nodeId: '', - tableData: [], - selectFileNameList: [], - selectTableData: [], - loading: false, - downLoading: false, - startLoading: false, - stopLoading: false - } - }, - mounted() { - - }, - watch: { - '$store.state.range.nodeId': { - handler(newVal, oldVal) { - this.nodeId = newVal - this.init() - }, - immediate: true - }, - '$store.state.node.startTraffic': { - handler(newVal, oldVal) { - this.startLoading = newVal - }, - immediate: true - }, - '$store.state.node.endTraffic': { - handler(newVal, oldVal) { - this.stopLoading = newVal - }, - immediate: true - } - }, - created() { - }, - methods:{ - init() { - // this.tableData = getTargetsResponse?.result - const reqParams = { node_id: this.nodeId } - this.loading = true - this.$axios.get(this.$http.api.getNodeFile, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.tableData = res?.result - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.loading = false - }) - }, - // 当选择其它角色时,弹窗填写角色窗 - openRoleForm() { - this.$refs.roleForm.visible = true - }, - // 下载 - download() { - if (this.selectFileNameList.length <= 0) { - this.$notify({ - title: '请勾选要下载的文件', - type: 'warning', - duration: 2500 - }) - return - } - const reqParams = { - node_id: this.nodeId, - object_file_name_list: JSON.stringify(this.selectFileNameList) - } - this.downLoading = true - this.$axios.getFile(this.$http.api.downloadNodeFile, 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 - }) - }, - // 开始 - start() { - const reqParams = { - node_id: this.nodeId, - command: 'start' - } - // this.startLoading = true - this.$store.commit('node/setStartTraffic', true) - this.$axios.get(this.$http.api.flowStartStop, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.$notify({ - title: '开始统计流量', - type: 'success', - duration: 2500 - }) - } - }).catch(err => { - console.log(err) - this.$store.commit('node/setStartTraffic', false) - }).finally(() => { - // this.startLoading = false - }) - }, - // 结束 - end() { - const reqParams = { - node_id: this.nodeId, - command: 'stop' - } - // this.stopLoading = true - this.$store.commit('node/setEndTraffic', true) - this.$axios.get(this.$http.api.flowStartStop, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.$store.commit('node/setStartTraffic', false) - this.$notify({ - title: '结束统计流量', - type: 'success', - duration: 2500 - }) - } - }).catch(err => { - console.log(err) - }).finally(() => { - setTimeout(() => { - // this.stopLoading = false - this.$store.commit('node/setEndTraffic', false) - this.init() - }, 5 * 1000); - }) - }, - // 处理选中的数据 - handleSelectionChange(selectData) { - this.selectTableData = selectData - this.selectFileNameList = selectData.map(item => { - return item.file_name - }) - }, - // // 修改每页数据条数 - // handleSizeChange(val) { - // console.log(`每页 ${val} 条`) - // this.page=1 - // this.size=val - // this.query() - // }, - // // 修改页数 - // handleCurrentChange(val) { - // console.log(`当前页: ${val}`) - // this.page=val - // this.query() - // } - } -} - -</script> - -<style lang='less' scoped="scoped"> -.el-pagination { - padding: 15px 55px 0 0 !important; -} -.custom-table { - width: 100%; - height: 100%; -} -.range-config-manage{ - width: 100%; - height: 100%; - // display: flex; - // flex-direction: column; - // justify-content: flex-start; - .list{ - width: 100%; - height: 87%; - background-color: rgba(25, 33, 61, 0.4); - border: 1px solid rgba(186, 208, 241, 0.1); - border-radius: 8px; - // margin-left: 2.5%; - // overflow-y: auto; - // overflow-y: scroll; - // overflow-x: hidden; - // border: none; - } - .list::-webkit-scrollbar { - width: 0px; /* 隐藏滚动条 */ - height: 0px; - background-color: transparent; /* 让背景透明 */ - - } - /* 隐藏火狐浏览器滚动条 */ - @-moz-document url-prefix() { - .trackSource { - scrollbar-width: none; - } - } - // 遮罩层 - .mask{ - position: fixed; /*将元素设置为固定定位*/ - top: 0; - right: 0; - bottom: 0; - left: 0; - background-color: rgba(0,0,0,0.5); /*通过rgba函数来控制遮罩层的透明度*/ - display: none; /*将元素隐藏*/ - } - } -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/detail/file/mock.js b/src/views/rangeNodeManage/detail/file/mock.js deleted file mode 100644 index c51e523..0000000 --- a/src/views/rangeNodeManage/detail/file/mock.js +++ /dev/null @@ -1,26 +0,0 @@ -const getTargetsResponse = { - "code": 200, - "message": "success", - "result": [ - { - "bucket_name": "target-1-da-15", - "file_name": "target_1_da_15_2023_07_31_23_58_04.pcap", - "last_modified": "2023-07-31T15:58:40.158000+00:00", - "size": "3.80KiB" - }, - { - "bucket_name": "target-1-da-15", - "file_name": "target_1_da_15_2023_08_01_00_04_07.pcap", - "last_modified": "2023-07-31T16:07:09.377000+00:00", - "size": "21.7KiB" - }, - { - "bucket_name": "target-1-da-15", - "file_name": "target_1_da_15_2023_08_01_00_13_41.pcap", - "last_modified": "2023-07-31T16:16:08.605000+00:00", - "size": "20.6KiB" - } - ] -} - -export { getTargetsResponse }
\ No newline at end of file diff --git a/src/views/rangeNodeManage/detail/file/module/Header.vue b/src/views/rangeNodeManage/detail/file/module/Header.vue deleted file mode 100644 index 6dc6599..0000000 --- a/src/views/rangeNodeManage/detail/file/module/Header.vue +++ /dev/null @@ -1,74 +0,0 @@ -<template> -<div class="head"> - <span class="title">节点流量采集文件</span> - <el-button :loading="downLoading" type="primary" @click="download">下载</el-button> - <el-button :loading="startLoading" type="primary" @click="start">开始</el-button> - <el-button :loading="stopLoading" type="primary" @click="end">结束</el-button> -</div> -</template> - -<script> -export default { - name: 'Header', - props: ['startLoading', 'stopLoading', 'downLoading'], - data() { - return { - role: '', - has_deployed: '' - } - }, - methods: { - // 下载 - download() { - this.$emit('download') - }, - // 开始 - start() { - this.$emit('start') - }, - // 结束 - end() { - this.$emit('end') - } - } -} -</script> - -<style lang="less" scoped> -.head{ - width: 100%; - height: 12%; - margin-top: 1%; - text-align: right; - - /*background-color: #5daf34;*/ - .block{ - display: inline-block; - margin-left: 2%; - - } - .input{ - display: inline-block; - height: 60%; - width: 10%; - margin-left: 0.5%; - .el-input::placeholder { - width: auto; - } - .icon-group { - display: flex; /* 设置容器为 Flexbox 容器 */ - align-items: center; /* 垂直居中图片 */ - gap: 5px; /* 图片和文字之间的间距,可以根据需要进行调整 */ - - } - .icon-group img { - transform: scale(1); - margin-right: 15px; - margin-top: 6px; - } - } - .title { - margin-right: 60%; - } -} -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/detail/index.vue b/src/views/rangeNodeManage/detail/index.vue deleted file mode 100644 index 3435d74..0000000 --- a/src/views/rangeNodeManage/detail/index.vue +++ /dev/null @@ -1,80 +0,0 @@ -<template> - <div class="container"> - <div class="card-detail"> - <Detail></Detail> - </div> - <div class="card-file"> - <File></File> - </div> - <div class="card"> - <Log></Log> - </div> - <div class="card"> - <Console></Console> - </div> - </div> -</template> - -<script> -import Detail from './detail/index.vue' -import File from './file/index.vue' -import Log from './log/index.vue' -import Console from './console/index.vue' -import { getTargetsResponse } from './mock.js' -export default { - name: "NodeDetail", - components: { Detail, File, Log, Console}, - data(){ - return{ - nodeId: '', - nodeDetail: {} - } - }, - mounted() { - }, - // watch: { - // '$store.state.range.nodeId': { - // handler(newVal, oldVal) { - // this.nodeId = newVal - // this.init() - // }, - // immediate: true - // } - // }, - created() { - }, - methods:{ - // init() {} - } -} -</script> - -<style lang='less' scoped="scoped"> -.container{ - width: 100%; - height: 100%; - display: flex; - flex-wrap: wrap; - flex-direction: row; - justify-content: space-around; - align-content: space-around; - background-image:url('../../../img/background/backgroundFourCorner.svg'); - background-repeat: no-repeat; /* 可选,防止图像重复 */ - background-size: 100% auto; /* 宽度为100%,高度自适应保持宽高比 */ - .card{ - width: 48%; - height: 46%; - background-image:url('../../../img/backgroundFourCorner.png'); - background-repeat: no-repeat; /* 可选,防止图像重复 */ - background-size: 100% 100%; /* 宽度为100%,高度自适应保持宽高比 */ - } - .card-detail{ - width: 48%; - height: 46%; - } - .card-file{ - width: 48%; - height: 46%; - } -} -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/detail/log/index.vue b/src/views/rangeNodeManage/detail/log/index.vue deleted file mode 100644 index b7a0638..0000000 --- a/src/views/rangeNodeManage/detail/log/index.vue +++ /dev/null @@ -1,227 +0,0 @@ -<template> - <div :class="['range-config-manage', {'is--maximize': isFullscreen}]" ref="appRef"> - <Header - :is-fullscreen="isFullscreen" - :fullscreen-icon="fullscreenIcon" - :down-loading="downLoading" - :close-icon="closeIcon" - @query="query" - @download="download" - @zoomEvent="zoomEvent" - ></Header> - <div class="list"> - <el-table - class="custom-table" - ref="multipleTable" - v-loading="loading" - height="100%" - style="width: 100%;" - :data="tableData" - tooltip-effect="dark" - highlight-current-row - > - <el-table-column - align="center" - prop="id" - label="id" - min-width="50"/> - <el-table-column - align="left" - prop="content" - label="日志内容" - min-width="500" - show-overflow-tooltip/> - </el-table> - </div> - </div> -</template> -<script> -import Header from './module/Header.vue' -import { getTargetsResponse } from './mock.js' -export default { - name: "File", - components:{ Header}, - data(){ - return{ - fullscreenIcon: 'fullscreen', - isFullscreen: false, - target_id: '', - nodeId: '', - downLoading: false, - tableData: [], - inverterMonTimer: null, - loading: false, - closeIcon: false - } - }, - mounted() { - this.closeIcon = this.$route.params.closeIcon - }, - watch: { - '$store.state.range.nodeId': { - handler(newVal, oldVal) { - this.nodeId = newVal - this.init() - }, - immediate: true - } - }, - created() { - this.inverterMonTimer = setInterval(() => { - this.init() - }, 5 * 1000) - }, - beforeDestroy() { - if (this.inverterMonTimer) { - clearInterval(this.inverterMonTimer); - this.inverterMonTimer = null; - } - }, - - methods:{ - zoomEvent() { - this.isFullscreen = !this.isFullscreen - this.fullscreenIcon = this.isFullscreen ? 'narrow' : 'fullscreen' - }, - init(params={}) { - // const responseData = getTargetsResponse?.result - // this.tableData = responseData.map((item, index) => { - // return { - // id: index, - // content: item - // } - // }) - // TODO: 暂时注释接口 - const reqParams = { - node_id: this.nodeId, - ...params - } - this.loading = true - this.$axios.get(this.$http.api.getLog, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - const responseData = res?.result - this.tableData = responseData.map((item, index) => { - return { - id: index, - content: item - } - }) - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.loading = false - }) - }, - query(params) { - // 清除日志轮询器 - if (this.inverterMonTimer) { - clearInterval(this.inverterMonTimer); - this.inverterMonTimer = null; - } - // 立即查询一次 - this.init(params) - // 开启新的日志轮询器 - this.inverterMonTimer = setInterval(() => { - this.init(params) - }, 5 * 1000) - }, - // 下载 - download() { - this.downLoading = true - const reqParams = { node_id: this.nodeId } - this.$axios.getFile(this.$http.api.downloadLog, 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 - }) - }, - // // 修改每页数据条数 - // handleSizeChange(val) { - // console.log(`每页 ${val} 条`) - // this.page=1 - // this.size=val - // this.query() - // }, - // // 修改页数 - // handleCurrentChange(val) { - // console.log(`当前页: ${val}`) - // this.page=val - // this.query() - // } - } -} - -</script> - -<style lang='less' scoped="scoped"> -.is--maximize { - position: fixed; - top: 9%; - left: 10%; - width: 90% !important; - height: 91% !important; - padding: 0.5em 1em; - // background-color: #17234e; - background: url(../../../../img/background/bgMain.svg); - background-repeat: no-repeat; /* 可选,防止图像重复 */ - background-position: center; /* 居中显示 */ - background-size: cover; /* 宽度为100%,高度自适应保持宽高比 */ - z-index: 1000; -} -.el-pagination { - padding: 15px 55px 0 0 !important; -} -.custom-table { - width: 100%; - height: 100%; - border-radius: 0px; - background-color: transparent !important; -} -.range-config-manage{ - width: 100%; - height: 100%; - .list{ - width: 100%; - height: calc(100% - 85px); - } - // 遮罩层 - .mask{ - position: fixed; /*将元素设置为固定定位*/ - top: 0; - right: 0; - bottom: 0; - left: 0; - background-color: rgba(0,0,0,0.5); /*通过rgba函数来控制遮罩层的透明度*/ - display: none; /*将元素隐藏*/ - } - } -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/detail/log/mock.js b/src/views/rangeNodeManage/detail/log/mock.js deleted file mode 100644 index 40b73cf..0000000 --- a/src/views/rangeNodeManage/detail/log/mock.js +++ /dev/null @@ -1,12 +0,0 @@ -const getTargetsResponse ={ - "code": 200, - "message": "success", - "result": [ - "Jan 02 18:36:44.000 [notice] Tor 0.4.8.10 opening new log file.\n", - "Jan 02 18:36:44.000 [info] Tor 0.4.8.10 opening new log file.\n", - "Jan 02 18:36:44.000 [warn] Tor 0.4.8.10 opening new log file.\n", - "Jan 02 18:36:44.000 [warn] Tor 0.4.8.10 opening new log file.\n", - ] - } - -export { getTargetsResponse }
\ No newline at end of file diff --git a/src/views/rangeNodeManage/detail/log/module/Header.vue b/src/views/rangeNodeManage/detail/log/module/Header.vue deleted file mode 100644 index bee079f..0000000 --- a/src/views/rangeNodeManage/detail/log/module/Header.vue +++ /dev/null @@ -1,122 +0,0 @@ -<template> -<div class="head"> - <span class="title">日志流展示</span> - <div class="role-select"> - <el-select v-model="level" clearable placeholder="全部" @change="query"> - <el-option - v-for="item in levelDict" - :key="item.value" - :label="item.label" - :value="item.value"> - </el-option> - </el-select> - </div> - <el-button :loading="downLoading" class="role-select" type="primary" @click="download">下载</el-button> - <span class="icon-span" slot="label"> - <i v-if="closeIcon" class="el-icon-close icon-zoom" @click="backNodeList"></i> - <svg-icon v-else class="icon-zoom" :icon-class="fullscreenIcon" @click="zoomEvent"></svg-icon> - </span> -</div> -</template> - -<script> -export default { - name: 'Header', - props: { - isFullscreen: { - typeof: Boolean - }, - fullscreenIcon: { - typeof: String - }, - downLoading: { - typeof: Boolean - }, - closeIcon: { - typeof:Boolean - } - }, - data() { - return { - level: '', - levelDict:[ - {label: 'info', value: 'info'}, - {label: 'notice', value: 'notice'}, - {label: 'warn', value: 'warn'} - ], - } - }, - methods: { - zoomEvent() { - this.$emit('zoomEvent') - // this.fullscreenIcon = this.isFullscreen ? 'el-icon-full-screen' : 'el-icon-rank' - }, - // 查询 - query() { - let params = {} - if (this.level) { - params.level = this.level - } - this.$emit('query', params) - }, - // 下载 - download() { - this.$emit('download') - }, - backNodeList() { - this.$router.push({ name: 'rangeNodeManage' }) - } - } -} -</script> - -<style lang="less" scoped> -.head{ - width: 100%; - height: 50px; - margin-top: 20px; - text-align: right; - - /*background-color: #5daf34;*/ - .block{ - display: inline-block; - margin-left: 2%; - - } - .input{ - display: inline-block; - height: 60%; - width: 10%; - margin-left: 0.5%; - .el-input::placeholder { - width: auto; - } - .icon-group { - display: flex; /* 设置容器为 Flexbox 容器 */ - align-items: center; /* 垂直居中图片 */ - gap: 5px; /* 图片和文字之间的间距,可以根据需要进行调整 */ - - } - .icon-group img { - transform: scale(1); - margin-right: 15px; - margin-top: 6px; - } - } - .title { - margin-right: 45%; - } - ::v-deep .role-select{ - display: inline-block; - margin-right: 15px; - } - .icon-span { - padding: 12px 20px; - .icon-zoom { - font-size: 30px; - color: #02DDEA; - margin: 0 15px; - } - } -} -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/detail/mock.js b/src/views/rangeNodeManage/detail/mock.js deleted file mode 100644 index 0566abd..0000000 --- a/src/views/rangeNodeManage/detail/mock.js +++ /dev/null @@ -1,38 +0,0 @@ -const getTargetsResponse = { - "code": 200, - "message": "success", - "result": { - "setting_id": 70, - "traffic_collect_task_id": null, - "id": 90, - "ip": "148.113.2.0", - "pod_name": "target-11-relay-90-568f44566f-rvbl8", - "nick_name": "relaykmuhkwkdjy", - "status": "complete", - "onion": null, - "create_time": "2024-01-02T18:36:37", - "complete_time": "2024-01-02T18:48:20", - "role": null, - "owner_setting": { - "role": "relay", - "image_id": 34, - "replicas": "1", - "bandwidth": 10, - "memory": 100, - "service": null, - "tor_version": "4.8.9", - "create_time": null, - "update_time": null, - "out_port": null, - "socks_port": 19001, - "control_port": 19002, - "or_port": 7000, - "dir_port": 9030, - "use_network": { - "cidr": "148.113.2.0/24" - } - } - } -} - -export { getTargetsResponse }
\ No newline at end of file diff --git a/src/views/rangeNodeManage/index.vue b/src/views/rangeNodeManage/index.vue deleted file mode 100644 index 27f2086..0000000 --- a/src/views/rangeNodeManage/index.vue +++ /dev/null @@ -1,146 +0,0 @@ -<template> - <div class="range-node-manage"> - <div class="container"> - <div class="header"> - <el-select class="range-select" v-model="target_id" placeholder="全部靶场" @change="changeRange"> - <el-option - v-for="item in rangeDict" - :key="item.value" - :label="item.label" - :value="item.value"> - </el-option> - </el-select> - </div> - <div class="map-container"> - <WorldMap></WorldMap> - <TopologyMap></TopologyMap> - </div> - <div class="list-container"> - <NodeList></NodeList> - </div> - </div> - </div> -</template> - -<script> -import WorldMap from './worldMap' -import TopologyMap from './topologyMap' -import NodeList from './nodeList' -export default { - name: 'rangeNodeManage', - components: { - NodeList, - WorldMap, - TopologyMap - }, - data() { - return { - target_id: '', - rangeDict: [] - } - }, - watch: { - '$store.state.range.targetId': { - handler(newVal, oldVal) { - this.target_id = newVal - }, - immediate: true - } - }, - created() { - this.getRangeDict() - }, - methods: { - // 改变靶场 - changeRange() { - this.$store.commit('range/setTargetId', this.target_id) - }, - // 获取靶场列表字典 - getRangeDict() { - const reqParams = { - page: 1, - size: 99, - } - this.$axios.get(this.$http.api.getTargets, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.rangeDict = res?.result?.items.map(item => { - return { - label: item.target_name, - value: item.id - } - }) - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.rangeDict.unshift({label: '全部靶场', value: ''}) - }) - }, - } - -} -</script> - -<style lang='less' scoped> -.range-node-manage { - width: 100%; - height: 100%; - position: relative; - .container { - width: 95%; - height: 95%; - position: absolute; /* 绝对定位 */ - top: 50%; /* 向下偏移50% */ - left: 50%; /* 向右偏移50% */ - transform: translate(-50%, -50%); /* 回移50% */ - background-image:url('../../img/backgroundFourCorner.png'); - background-repeat: no-repeat; /* 可选,防止图像重复 */ - background-size: 100% 100%; /* 宽度为100%,高度自适应保持宽高比 */ - padding: 1.5%; - } -} -.header { - height: 7%; - width: 100%; - text-align: left; - .range-select { - // position: absolute; - // top: 12px; - // right: 140px; - ::v-deep .el-input { - width: 60%; - .el-input__inner { - background-color: transparent !important; - border-color: transparent; - border-radius: 0; - color: #FFFFFF; - } - /* select去除竖线 */ - .el-input__suffix::before { - content: ""; - width: 0; - height: 0; - margin: 0; - position: absolute; - } - /*select的上下箭头图标样式*/ - .el-select__caret { - color: rgba(2, 221, 234, 0.9); - } - } -} -} -.map-container{ - height: 43%; - width: 100%; - display: flex; - flex-direction: row; - justify-content: space-between; - -} -.list-container{ - height: 50%; - width: 100%; -} - -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/nodeList/components/DirNameForm.vue b/src/views/rangeNodeManage/nodeList/components/DirNameForm.vue deleted file mode 100644 index 7939629..0000000 --- a/src/views/rangeNodeManage/nodeList/components/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/nodeList/components/DownloadFileManager.vue b/src/views/rangeNodeManage/nodeList/components/DownloadFileManager.vue deleted file mode 100644 index 9c77da3..0000000 --- a/src/views/rangeNodeManage/nodeList/components/DownloadFileManager.vue +++ /dev/null @@ -1,536 +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" - 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"> - <el-radio v-model="filename" :label="fileItem.name" class="file-info">{{ '' }}</el-radio> - <span class="file-info">{{ fileItem.name }}</span> - <i class="el-icon-document file-info" style="font-size: 20px"></i> - <span class="file-info">{{ fileItem.size }}</span> - <span class="file-info">{{ fileItem.time }}</span> - </li> - </ul> - <div class="empty-box"></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: [], - filename: '' - } -}, -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) { - // this.$emit('selectUploadFile', {path: this.selectNode.path, file: e.target.files[0]}) - // 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.handleNodeClick(this.selectNode) - // this.setCurrentHighlight(this.selectNode.$treeNodeId); - // } - // }).catch(err => { - // console.log(err) - // }) - // }, - // download() { - // // this.downLoading = true - // const reqParams = { - // master_node_id : this.nodeId, - // current_dir: this.selectNode.path, - // filename: this.selectFile.name - // } - // this.$axios.getFile(this.$http.api.batchDownload, 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 - 160 // 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 - 160 // 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> diff --git a/src/views/rangeNodeManage/nodeList/components/MainNode.vue b/src/views/rangeNodeManage/nodeList/components/MainNode.vue deleted file mode 100644 index 5219549..0000000 --- a/src/views/rangeNodeManage/nodeList/components/MainNode.vue +++ /dev/null @@ -1,98 +0,0 @@ -<template> -<el-table - class="main-table styleTable" - ref="mainTable" - height="500px" - style="width: 100%;" - :data="nodeList" - tooltip-effect="dark" - highlight-current-row -> - <el-table-column label="" width="80" align="center"> - <template slot-scope="scope"> - <el-radio v-model="master_node_id" :label="scope.row.id" @input="handleSelectionMain(scope.row)">{{ "" }}</el-radio> - </template> - </el-table-column> - <el-table-column - align="center" - prop="id" - label="id" - width="80"/> - <el-table-column - align="center" - prop="nick_name" - label="节点昵称" - min-width="100"/> - <el-table-column - align="center" - prop="role" - label="角色" - min-width="100"> - <template slot-scope="scope"> - <svg-icon :icon-class="scope.row.role"></svg-icon> - </template> - </el-table-column> - <el-table-column - align="center" - prop="ip" - label="ip" - min-width="150"/> - <el-table-column - align="center" - prop="status" - label="部署状态" - min-width="100" - > - <!-- <template slot-scope="scope"> - {{ scope.row.has_deployed ? '已部署' : '未部署' }} - </template> --> - </el-table-column> - <el-table-column - align="center" - prop="create_time" - label="创建开始时间" - min-width="100" - > - <template slot-scope="scope"> - {{ scope.row.create_time | formatTime }} - </template> - </el-table-column> - <el-table-column - align="center" - prop="complete_time" - label="创建完成时间" - min-width="100" - > - <template slot-scope="scope"> - {{ scope.row.complete_time | formatTime }} - </template> - </el-table-column> -</el-table> -</template> - -<script> -export default { - name: 'MainNode', - props: { - nodeList: { - typeof: Array, - require: true - } - }, - data() { - return { - master_node_id: '' - } - }, - methods: { - // 选择主节点 - handleSelectionMain(row) { - this.$emit('selectMainNode', row) - }, - } -} -</script> - -<style lang="less" scoped> - -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/nodeList/components/OperateNode.vue b/src/views/rangeNodeManage/nodeList/components/OperateNode.vue deleted file mode 100644 index 30e5881..0000000 --- a/src/views/rangeNodeManage/nodeList/components/OperateNode.vue +++ /dev/null @@ -1,98 +0,0 @@ -<template> -<el-table - class="main-table styleTable" - ref="operateTable" - height="500px" - style="width: 100%;" - :data="nodeList" - tooltip-effect="dark" - highlight-current-row - @selection-change="handleSelectionOperateNode" -> - <el-table-column - align="center" - type="selection" - width="80"/> - <el-table-column - align="center" - prop="id" - label="id" - width="80"/> - <el-table-column - align="center" - prop="nick_name" - label="节点昵称" - min-width="100"/> - <el-table-column - align="center" - prop="role" - label="角色" - min-width="100"> - <template slot-scope="scope"> - <svg-icon :icon-class="scope.row.role"></svg-icon> - </template> - </el-table-column> - <el-table-column - align="center" - prop="ip" - label="ip" - min-width="150"/> - <el-table-column - align="center" - prop="status" - label="部署状态" - min-width="100" - > - <!-- <template slot-scope="scope"> - {{ scope.row.has_deployed ? '已部署' : '未部署' }} - </template> --> - </el-table-column> - <el-table-column - align="center" - prop="create_time" - label="创建开始时间" - min-width="100" - > - <template slot-scope="scope"> - {{ scope.row.create_time | formatTime }} - </template> - </el-table-column> - <el-table-column - align="center" - prop="complete_time" - label="创建完成时间" - min-width="100" - > - <template slot-scope="scope"> - {{ scope.row.complete_time | formatTime }} - </template> - </el-table-column> -</el-table> -</template> - -<script> -export default { - name: 'OperateNode', - props: { - nodeList: { - typeof: Array, - require: true - } - }, - data() { - return { - - } - }, - methods: { - // 选择被操作节点 - handleSelectionOperateNode(selectRows) { - this.$emit('selectOperateNode', selectRows) - }, - } -} -</script> - -<style lang="less" scoped> - -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/nodeList/components/UploadFileManager.vue b/src/views/rangeNodeManage/nodeList/components/UploadFileManager.vue deleted file mode 100644 index d62dfdf..0000000 --- a/src/views/rangeNodeManage/nodeList/components/UploadFileManager.vue +++ /dev/null @@ -1,520 +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" - 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"> - <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) { - // this.$emit('selectUploadFile', {path: this.selectNode.path, file: e.target.files[0]}) - // const params = { - // node_id : this.nodeId, - // current_dir: this.selectNode.path, - // file: e.target.files[0] - // } - // }, - updateCurrentPath() { - this.handleNodeClick(this.selectNode) - this.setCurrentHighlight(this.selectNode.$treeNodeId); - }, - 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 - 160 // 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 - 160 // 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> diff --git a/src/views/rangeNodeManage/nodeList/index.vue b/src/views/rangeNodeManage/nodeList/index.vue deleted file mode 100644 index 7a0e2fd..0000000 --- a/src/views/rangeNodeManage/nodeList/index.vue +++ /dev/null @@ -1,445 +0,0 @@ -<template> -<div class="range-config-manage" ref="appRef"> - <Header - :range-dict="rangeDict" - @query="query" - @batchConsole="batchConsole" - @batchDownload="batchDownload" - @batchUpload="batchUpload" - @batchCollectTraffic="batchCollectTraffic" - ></Header> - <div class="list" > - <el-table - class="custom-table" - ref="multipleTable" - v-loading="loading" - element-loading-text="加载中..." - height="100%" - style="width: 100%;" - :data="tableData" - tooltip-effect="dark" - highlight-current-row - > - <el-table-column - align="center" - prop="id" - label="id" - width="80"/> - <el-table-column - align="center" - prop="nick_name" - label="节点昵称" - min-width="100"/> - <el-table-column - align="center" - prop="role" - label="角色" - min-width="100"> - <template slot-scope="scope"> - <svg-icon :icon-class="scope.row.role"></svg-icon> - <span style="padding-left: 5px;">{{ roleDict[scope.row.role] || scope.row.role }}</span> - </template> - </el-table-column> - <el-table-column - align="center" - prop="ip" - label="ip" - min-width="150"/> - <el-table-column - align="center" - prop="status" - label="部署状态" - min-width="100" - > - <template slot-scope="scope"> - <div class="deploy-status"> - <svg-icon :icon-class="getStatus(scope.row.status).class"></svg-icon> - <span :class="getStatus(scope.row.status).class">{{ getStatus(scope.row.status).label }}</span> - </div> - </template> - </el-table-column> - <el-table-column - align="center" - prop="collecting" - label="正在采集流量" - min-width="100" - > - <template slot-scope="scope"> - {{ scope.row.collecting ? '是' : '否' }} - </template> - </el-table-column> - <el-table-column - align="center" - prop="create_time" - label="创建开始时间" - min-width="150" - > - <template slot-scope="scope"> - {{ scope.row.create_time | formatTime }} - </template> - </el-table-column> - <el-table-column - align="center" - prop="complete_time" - label="创建完成时间" - min-width="150" - > - <template slot-scope="scope"> - {{ scope.row.complete_time | formatTime }} - </template> - </el-table-column> - <el-table-column - align="center" - label="操作" - min-width="200" - > - <template slot-scope="scope"> - <el-button type="text" size="medium" :disabled="scope.row.status==='pending' || !roleDict[scope.row.role]" @click="console(scope.row)">控制台</el-button> - <el-button type="text" size="medium" :disabled="!roleDict[scope.row.role]" @click="log(scope.row)">日志</el-button> - <el-button type="text" size="medium" :disabled="!roleDict[scope.row.role]" @click="detail(scope.row)">详情</el-button> - </template> - </el-table-column> - </el-table> - </div> - <el-pagination - background - :current-page="page" - :page-sizes="[10, 20, 30, 40]" - :page-size="10" - :total="total" - layout="total, sizes, prev, pager, next, jumper" - @size-change="handleSizeChange" - @current-change="handleCurrentChange" - > - </el-pagination> - <div class="mask"></div> - <Console - ref="batchConsole" - :target_id="target_id" - @refresh="init"> - </Console> - <Download - ref="batchDownload" - :target_id="target_id" - @refresh="init"> - </Download> - <Upload - ref="batchUpload" - :target_id="target_id" - @refresh="init"> - </Upload> - <CollectTraffic - ref="batchCollectTraffic" - :target_id="target_id" - @refresh="init"> - </CollectTraffic> -</div> -</template> -<script> -import Header from './module/Header.vue' -import Console from './module/Console.vue' -import Download from './module/Download.vue' -import Upload from './module/Upload.vue' -import CollectTraffic from './module/CollectTraffic' - -export default { - name: "RangeConfigManage", - components:{ Header, Console, Download, Upload, CollectTraffic }, - - data(){ - return{ - page: 1, - size: 10, - total: 0, - target_id: '', - tableData: [], - selectConfigIds: [], - rangeDict: [], - loading: false, - pendingTimer: null, - roleDict:{ - da: '权威目录节点', - client: '客户端节点', - guard: '入口节点', - relay: '路由节点', - exit: '出口节点', - onion: '洋葱服务节点', - } - } - }, - mounted() { - - }, - watch: { - '$store.state.range.targetId': { - handler(newVal, oldVal) { - this.target_id = newVal - this.init() - }, - immediate: true - } - }, - created() {}, - beforeDestroy() { - if (this.pendingTimer) { - clearInterval(this.pendingTimer) - this.pendingTimer = null - } -}, - methods:{ - init(params={}) { - // this.tableData = getTargetsResponse?.result?.items - // this.total = getTargetsResponse?.result?.total - - // const checkedData = JSON.parse(JSON.stringify(this.selectTableData)) - const reqParams = { - page: this.page, - size: this.size, - ...params - } - if (this.target_id && this.target_id !== '') { - reqParams.target_id = this.target_id - } - this.loading = true - this.$axios.get(this.$http.api.getNodeList, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.tableData = res?.result?.items - this.total = res?.result?.total - // this.$nextTick(()=>{ - // checkedData.forEach((item) => { - // this.$refs?.multipleTable?.toggleRowSelection(this.tableData.find(val => val.id === item.id), true) - // }) - // }) - let index = this.tableData?.findIndex(item => { - return item.status === 'pending' - }) - if (index !== -1) { - if (!this.pendingTimer) { - this.pendingTimer = setInterval(() => { - this.init() - }, 10 * 1000) - } - } - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.loading = false - }) - }, - query(params) { - this.init(params) - }, - // 批量控制台 - batchConsole() { - document.querySelector('.mask').style.display = 'block' - this.$refs.batchConsole.visible = true - }, - // 批量下载文件 - batchDownload() { - this.$refs.batchDownload.getNodeList() - document.querySelector('.mask').style.display = 'block' - this.$refs.batchDownload.visible = true - }, - // 批量上传 - batchUpload() { - // this.$store.commit('range/setNodeId', '') - this.$refs.batchUpload.getNodeList() - document.querySelector('.mask').style.display = 'block' - this.$refs.batchUpload.visible = true - }, - // 批量运行流水线 - batchCollectTraffic() { - this.$refs.batchCollectTraffic.getNodeList() - document.querySelector('.mask').style.display = 'block' - this.$refs.batchCollectTraffic.visible = true - }, - // 控制台 - console(row) { - this.$store.commit('range/setNodeId', row.id) - this.$router.push({ - name: 'console', - params: { - closeIcon : true - } - }) - }, - // 日志 - log(row) { - this.$store.commit('range/setNodeId', row.id) - this.$router.push({ - name: 'log', - params: { - closeIcon : true - } - }) - }, - // 详情 - detail(row) { - this.$store.commit('range/setNodeId', row.id) - //保存是否正在采集流量 - this.$store.commit('node/setStartTraffic', row.collecting) - //保存是否正在结束采集流量 - this.$store.commit('node/setEndTraffic', row.analysing) - this.$router.push({ name: 'nodeDetail'}) - }, - getStatus(status) { - let statusInfo = { - label: '', - class: '' - } - switch (status) { - case 'true': - case 'pending': - statusInfo.label = '正在部署' - statusInfo.class = 'deployNormal' - break; - case 'false': - statusInfo.label = '部署失败' - statusInfo.class = 'deployFail' - break; - case 'complete': - statusInfo.label = '部署完成' - statusInfo.class = 'deploySuccess' - break; - default: - break; - } - return statusInfo - }, - // 获取靶场列表字典 - getRangeDict() { - const reqParams = { - page: 1, - size: 99, - } - this.$axios.get(this.$http.api.getTargets, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.rangeDict = res?.result?.items.map(item => { - return { - label: item.target_name, - value: item.id - } - }) - } - }).catch(err => { - console.log(err) - }) - }, - // // 处理选中的数据 - // handleSelectionChange(selectData) { - // this.selectTableData = selectData - // this.selectConfigIds = selectData.map(item => { - // return item.id - // }) - // }, - // 修改每页数据条数 - handleSizeChange(val) { - console.log(`每页 ${val} 条`) - this.page=1 - this.size=val - this.query() - }, - // 修改页数 - handleCurrentChange(val) { - console.log(`当前页: ${val}`) - this.page=val - this.query() - } - } -} - -</script> - -<style lang='less' scoped="scoped"> -.el-pagination { - padding: 15px 55px 0 0 !important; -} -.custom-table { - width: 100%; - height: 100%; - .deploy-status { - display: inline-block; - width: 103px; - height: 28px; - color:#FFFFFF; - border-radius: 3px; - padding: 5px, 12px, 5px, 12px; - background: rgba(227, 249, 233, 0.2); - } - .deployFail { - color: #E9473E; - width: 56px; - height: 28px; - margin-left: 10px; - font-family: PingFang SC; - font-size: 14px; - font-weight: 400; - line-height: 28px; - letter-spacing: 0em; - text-align: left; - } - .deployNormal { - color: #02DDEA; - width: 56px; - height: 28px; - margin-left: 10px; - font-family: PingFang SC; - font-size: 14px; - font-weight: 400; - line-height: 28px; - letter-spacing: 0em; - text-align: left; - } - .deploySuccess { - color: #0CCB64; - width: 56px; - height: 28px; - margin-left: 10px; - font-family: PingFang SC; - font-size: 14px; - font-weight: 400; - line-height: 28px; - letter-spacing: 0em; - text-align: left; - } -} -.range-config-manage { - width: 100%; - height: 100%; - // display: flex; - // flex-direction: column; - // justify-content: flex-start; - .list{ - width: 100%; - height: 73%; - // margin-left: 2.5%; - // overflow-y: auto; - // overflow-y: scroll; - // overflow-x: hidden; - // border: none; - } - .list::-webkit-scrollbar { - width: 0px; /* 隐藏滚动条 */ - height: 0px; - background-color: transparent; /* 让背景透明 */ - - } - /* 隐藏火狐浏览器滚动条 */ - @-moz-document url-prefix() { - .trackSource { - scrollbar-width: none; - } - } - // 遮罩层 - .mask{ - position: fixed; /*将元素设置为固定定位*/ - top: 0; - right: 0; - bottom: 0; - left: 0; - background-color: rgba(0,0,0,0.5); /*通过rgba函数来控制遮罩层的透明度*/ - display: none; /*将元素隐藏*/ - } - } -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/nodeList/mock.js b/src/views/rangeNodeManage/nodeList/mock.js deleted file mode 100644 index 49bc588..0000000 --- a/src/views/rangeNodeManage/nodeList/mock.js +++ /dev/null @@ -1,38 +0,0 @@ -const getTargetsResponse ={ - "code": 200, - "message": "success", - "result": { - "items": [ - { - "setting_id": 1, - "traffic_collect_task_id": 1, - "id": 1, - "ip": "1.1.1.1", - "pod_name": "pod_name1", - "nick_name": "第一节点", - "status": "未部署", - "onion": "onion1", - "create_time": "2023-12-26T10:51:15.363Z", - "complete_time": "2023-12-26T10:51:15.363Z" - }, - { - "setting_id": 2, - "traffic_collect_task_id": 2, - "id": 2, - "ip": "2.2.2.2", - "pod_name": "pod_name2", - "nick_name": "第二节点", - "status": "已部署", - "onion": "onion2", - "create_time": "2023-12-26T10:51:15.363Z", - "complete_time": "2023-12-26T10:51:15.363Z" - } - ], - "total": 0, - "page": 1, - "size": 50, - "pages": 0 - } - } - -export { getTargetsResponse }
\ No newline at end of file diff --git a/src/views/rangeNodeManage/nodeList/module/CollectTraffic/RuleList.vue b/src/views/rangeNodeManage/nodeList/module/CollectTraffic/RuleList.vue deleted file mode 100644 index fac918e..0000000 --- a/src/views/rangeNodeManage/nodeList/module/CollectTraffic/RuleList.vue +++ /dev/null @@ -1,207 +0,0 @@ -<template> - <div class="rule-section"> - <div class="task-box"> - <div class="header"> - <span>规则列表</span> - <img @click="addRule" src="../../../../../img/icon/addTrafficBtn.png" alt="" style="width: 194px; height: 40px;"> - </div> - <div class="content"> - <el-table - class="main-table styleTable" - ref="multipleTable" - height="230px" - style="width: 100%;" - :data="tableData" - tooltip-effect="dark" - highlight-current-row - > - <el-table-column - align="center" - prop="id" - label="id" - width="100"/> - <el-table-column - align="center" - prop="rule_name" - label="规则名称" - min-width="130"/> - <el-table-column - align="center" - prop="rule" - label="具体规则" - min-width="130" - > - </el-table-column> - <el-table-column - align="center" - prop="update_time" - label="添加时间" - min-width="130" - > - <template slot-scope="scope"> - {{ scope.row.update_time | formatDate }} - </template> - </el-table-column> - <el-table-column - align="center" - prop="use_count" - label="使用次数" - min-width="130"/> - <el-table-column - align="center" - label="操作" - min-width="300" - > - <template slot-scope="scope"> - <el-button type="text" size="medium" @click="editRule(scope.row)">修改</el-button> - <el-button type="text" size="medium" :loading="scope.row.delLoading" @click="delRule(scope.row)">删除</el-button> - </template> - </el-table-column> - </el-table> - </div> - </div> - <div class="mask"></div> - <RuleForm ref="ruleForm" :is-add="isAdd" @refresh="init"/> - </div> - </template> - - <script> - import RuleForm from './module/RuleForm' - export default { - name: 'RuleList', - components: { RuleForm }, - props: {}, - data() { - return { - tableData: [], - isAdd: true, - visible:false, - loading: false - } - }, - created() { - this.init() - }, - methods: { - init() { - const reqParams = { - page: 1, - size: 99, - } - this.loading = true - this.$axios.get(this.$http.api.getRuleList, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.tableData = res?.result?.items - this.tableData.map(item => { - this.$set(item, 'delLoading', false) - return item - }) - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.loading = false - }) - }, - // 添加流量采集规则 - addRule() { - this.isAdd = true - this.$refs.ruleForm.visible = true - }, - // 编辑规则 - editRule(row) { - this.isAdd = false - this.$refs.ruleForm.rule_id = row.id - this.$refs.ruleForm.form.rule_name = row.rule_name - this.$refs.ruleForm.form.rule = row.rule - this.$refs.ruleForm.visible = true - }, - // 删除规则 - delRule(row) { - this.$confirm('此操作将永久删除该规则, 是否继续?', '确认删除', { - confirmButtonText: '确定', - cancelButtonText: '取消', - type: 'warning' - }).then(() => { - this.del(row) - }).catch(() => { - this.$notify({ - title: '已取消删除', - type: 'success', - duration: 2500 - }) - }); - }, - del(row) { - const url = this.$http.api.rule + '/' + row.id - row.delLoading = true - this.$axios.delete(url, {}).then(res => { - if (res.code == 200 || res.code == "OK") { - this.$notify({ - title: '删除成功', - type: 'success', - duration: 2500 - }) - this.init() - } - }).catch(err => { - console.log(err) - }).finally(() => { - row.delLoading = false - }) - }, - // 关闭 - close() { - document.querySelector('.mask').style.display = 'none' - this.visible = false - this.resetForm() - } - } - } - </script> - - <style lang="less" scoped> - .rule-section{ - // height: 100%; - .styleTable { - background-color: transparent !important; - } - .base-input { - width: 100%; - float: left; - margin-top: 2%; - text-align: center; - } - .label-span { - margin-right: 3%; - display: inline-block; - width: 60px; - text-align: right; - } - .but-color { - background-color: #02DDEA !important; - } - .task-box{ - width: 100%; - min-height: 45%; - display: flex; - flex-direction: column; - padding: 2%; - .header{ - display: flex; - flex-direction: row; - justify-content: space-between; - width: 100%; - height: 50px; - line-height: 50px; - margin-bottom: 1%; - } - .content { - flex: 1; - ::v-deep .el-textarea__inner { - background-color: #1A2648; - } - } - } - } - </style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/nodeList/module/CollectTraffic/TaskList.vue b/src/views/rangeNodeManage/nodeList/module/CollectTraffic/TaskList.vue deleted file mode 100644 index 616ad6d..0000000 --- a/src/views/rangeNodeManage/nodeList/module/CollectTraffic/TaskList.vue +++ /dev/null @@ -1,391 +0,0 @@ -<template> - <div class="task-section"> - <div class="task-box"> - <div class="header"> - <span>任务列表</span> - <img @click="addTask" src="../../../../../img/icon/batchCollectBtn.png" alt="" style="width: 194px; height: 40px;"> - </div> - <div class="content"> - <el-table - class="main-table styleTable" - ref="multipleTable" - v-loading="loading" - height="230px" - style="width: 100%;" - :data="tableData" - tooltip-effect="dark" - highlight-current-row - @expand-change="handleExpandChange" - > - <el-table-column type="expand"> - <template slot-scope="props"> - <el-table - class="main-table styleTable" - ref="multipleTable" - v-loading="loading" - height="100%" - style="width: 100%; margin: 5px 20px;" - :data="taskNodeList" - tooltip-effect="dark" - highlight-current-row - > - <el-table-column - align="center" - prop="id" - label="id" - width="80"/> - <el-table-column - align="center" - prop="nick_name" - label="节点昵称" - min-width="100"/> - <el-table-column - align="center" - prop="role" - label="角色" - min-width="100"/> - <el-table-column - align="center" - prop="ip" - label="ip" - min-width="150"/> - <el-table-column - align="center" - prop="status" - label="部署状态" - min-width="100" - > - </el-table-column> - <el-table-column - align="center" - prop="create_time" - label="创建开始时间" - min-width="100" - > - <template slot-scope="scope"> - {{ scope.row.create_time | formatDate }} - </template> - </el-table-column> - <el-table-column - align="center" - prop="complete_time" - label="创建完成时间" - min-width="100" - > - <template slot-scope="scope"> - {{ scope.row.complete_time | formatDate }} - </template> - </el-table-column> - </el-table> - </template> - </el-table-column> - <el-table-column - align="center" - prop="id" - label="id" - width="60"/> - <el-table-column - align="center" - prop="task_name" - label="任务名称" - min-width="100"/> - <el-table-column - align="center" - prop="traffic_collect_rule_id" - label="采集规则" - min-width="100"/> - <el-table-column - align="center" - prop="collecting" - label="任务状态" - min-width="80" - > - <template slot-scope="scope"> - {{ scope.row.collecting ? (scope.row.collecting === true ? '正在采集' : '采集失败') : '采集完成' }} - </template> - </el-table-column> - <el-table-column - align="center" - prop="start_collect_time" - label="开始时间" - min-width="110" - > - <template slot-scope="scope"> - {{ scope.row.start_collect_time | formatTime }} - </template> - </el-table-column> - <el-table-column - align="center" - prop="end_collect_time" - label="结束时间" - min-width="110" - > - <template slot-scope="scope"> - {{ scope.row.end_collect_time | formatTime }} - </template> - </el-table-column> - <el-table-column - align="center" - label="操作" - min-width="300" - > - <template slot-scope="scope"> - <el-button type="text" size="medium" :loading="startLoading" @click="startTask(scope.row)">开始</el-button> - <el-button type="text" size="medium" :loading="stopLoading" @click="endTask(scope.row)">结束</el-button> - <el-button type="text" size="medium" @click="editTask(scope.row)">修改</el-button> - <el-button type="text" size="medium" @click="delTask(scope.row)">删除</el-button> - <!-- <el-button type="text" size="medium" @click="viewNode(scope.row)">查看节点</el-button> --> - <el-button type="text" size="medium" @click="downloadPack(scope.row)">下载pcap包</el-button> - </template> - </el-table-column> - </el-table> - </div> - </div> - <div class="mask"></div> - <TaskForm - ref="taskForm" - :node-list="nodeList" - :is-add="isAdd" - :target_id="target_id" - @refresh="init"> - </TaskForm> - <DownloadPack - ref="downloadPack" - @refresh="init"> - </DownloadPack> - </div> - </template> - - <script> - import TaskForm from './module/TaskForm' - import DownloadPack from './module/DownloadPack' - export default { - name: 'Console', - components: { TaskForm, DownloadPack }, - props: { - target_id: { - typeof: String, - default: 0 - }, - nodeList: { - typeof: Array, - require: true - }, - }, - data() { - return { - tableData: [], - taskNodeList: [], - isAdd: true, - visible:false, - loading: false, - startLoading: false, - stopLoading: false - } - }, - created() { - this.init() - }, - methods: { - init() { - const reqParams = { - page: 1, - size: 99, - } - this.loading = true - this.$axios.get(this.$http.api.getTaskList, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - // this.total = res?.result?.total - this.tableData = res?.result?.items - this.tableData.map(item => { - this.$set(item, 'delLoading', false) - return item - }) - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.loading = false - }) - }, - // 创建批量采集流量任务 - addTask() { - this.isAdd = true - document.querySelector('.mask').style.display = 'block' - this.$refs.taskForm.visible = true - }, - // 编辑任务 - editTask(row) { - this.isAdd = false - this.$refs.taskForm.task_id = row.id ?? '' - this.$refs.taskForm.form.task_name = row.task_name ?? '' - this.$refs.taskForm.form.task_description = row.task_description ?? '' - this.$refs.taskForm.form.node_list = row.node_list ?? [] - this.$refs.taskForm.form.traffic_collect_rule_id = row.traffic_collect_rule_id - this.$refs.taskForm.form.filter_noise = row.filter_noise ?? '' - this.$refs.taskForm.visible = true - }, - // 开始 - startTask(row) { - const reqParams = { - task_id: row.id, - command: 'start' - } - this.startLoading = true - this.$axios.get(this.$http.api.taskStartStop, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.$notify({ - title: '开始统计流量', - type: 'success', - duration: 2500 - }) - } - }).catch(err => { - console.log(err) - this.startLoading = false - }).finally(() => { - }) - }, - // 结束 - endTask(row) { - const reqParams = { - task_id: row.id, - command: 'stop' - } - this.stopLoading = true - this.$axios.get(this.$http.api.taskStartStop, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.startLoading = false - this.$notify({ - title: '结束统计流量', - type: 'success', - duration: 2500 - }) - } - }).catch(err => { - console.log(err) - }).finally(() => { - setTimeout(() => { - this.stopLoading = false - this.init() - }, 5 * 1000) - }) - }, - - // 删除任务 - delTask(row) { - this.$confirm('此操作将永久删除该任务, 是否继续?', '确认删除', { - confirmButtonText: '确定', - cancelButtonText: '取消', - type: 'warning' - }).then(() => { - this.del(row) - }).catch(() => { - this.$notify({ - title: '已取消删除', - type: 'success', - duration: 2500 - }) - }); - }, - del(row) { - const url = this.$http.api.trafficTask + '/' + row.id - row.delLoading = true - this.$axios.delete(url, {delete_minio: true}).then(res => { - if (res.code == 200 || res.code == "OK") { - this.$notify({ - title: '删除任务成功', - type: 'success', - duration: 2500 - }) - this.init() - } - }).catch(err => { - console.log(err) - }).finally(() => { - row.delLoading = false - }) - }, - // 展开行查看节点 - handleExpandChange(row, expandedRows) { - this.getTaskNodeList(row) - }, - // // 查看节点 - // viewNode(row) { - // this.getTaskNodeList(row) - // }, - // 获取节点列表 - getTaskNodeList(row) { - const params = { - page:1, - size: 99, - task_id: row.id - } - this.$axios.get(this.$http.api.getTrafficNodes, params).then(res => { - if (res.code == 200 || res.code == "OK") { - this.taskNodeList = res?.result?.items - } - }).catch(err => { - console.log(err) - }) - }, - // 下载pcap包 - downloadPack(row) { - this.$refs.downloadPack.task_id = row.id - this.$refs.downloadPack.init() - document.querySelector('.mask').style.display = 'block' - this.$refs.downloadPack.visible = true - } - } - } - </script> - - <style lang="less" scoped> - .task-section{ - // height: 100%; - .styleTable { - background-color: transparent !important; - } - .base-input { - width: 100%; - float: left; - margin-top: 2%; - text-align: center; - } - .label-span { - margin-right: 3%; - display: inline-block; - width: 60px; - text-align: right; - } - .but-color { - background-color: #02DDEA !important; - } - .task-box{ - width: 100%; - min-height: 45%; - display: flex; - flex-direction: column; - padding: 2%; - .header{ - display: flex; - flex-direction: row; - justify-content: space-between; - width: 100%; - height: 50px; - line-height: 50px; - margin-bottom: 1%; - } - .content { - flex: 1; - ::v-deep .el-textarea__inner { - background-color: #1A2648; - } - } - } - ::v-deep .el-table tbody tr>td { - // background: rgba(25, 33, 61, 0.5) !important; - background-color: #0A162C !important; - } - } - </style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/nodeList/module/CollectTraffic/index.vue b/src/views/rangeNodeManage/nodeList/module/CollectTraffic/index.vue deleted file mode 100644 index fe93dd2..0000000 --- a/src/views/rangeNodeManage/nodeList/module/CollectTraffic/index.vue +++ /dev/null @@ -1,110 +0,0 @@ -<template> -<div class="console-dialog" v-if="visible"> - <!-- 在此处指定弹窗的样式和内容 --> - <i class="el-icon-close" @click="close"></i> - <div class="tag"> - <el-tag class="tags" style="color:#f8fdff">批量采集流量</el-tag> - </div> - <TaskList style="height: 42%;" :node-list="nodeList"></TaskList> - <RuleList style="height: 42%;"></RuleList> - <footer class="anDiv"> - <el-button class="glBut but-color" type="primary" @click="close">确定</el-button> - </footer> -</div> -</template> - -<script> -import TaskList from './TaskList' -import RuleList from './RuleList' -export default { - name: 'Console', - components: { TaskList, RuleList }, - props: { - target_id: { - typeof: String, - required: true, - default: 0 - } - }, - data() { - return { - visible:false, - nodeList: [] - } - }, - methods: { - getNodeList() { - const reqParams = { - page: 1, - size: 99 - } - if (this.target_id && this.target_id !== '') { - reqParams.target_id = this.target_id - } - this.$axios.get(this.$http.api.getNodeList, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.nodeList = res?.result?.items - } - }).catch(err => { - console.log(err) - }).finally(() => {}) - }, - // 关闭 - close() { - document.querySelector('.mask').style.display = 'none' - this.$emit('refresh') - this.visible = false - } - } -} -</script> - -<style lang="less" scoped> -.console-dialog{ - z-index: 997; - width: 1331px; - height: 800px; - position: absolute; /* 绝对定位 */ - top: 50%; /* 向下偏移50% */ - left: 50%; /* 向右偏移50% */ - transform: translate(-50%, -50%); /* 回移50% */ - background-image:url('../../../../../img/background/NodeListDialog.svg'); - background-repeat: no-repeat; /* 可选,防止图像重复 */ - background-size: cover; /* 宽度为100%,高度自适应保持宽高比 */ - .el-icon-close{ - float: right; - padding-right: 8%; - padding-top: 1.8% - } - .tag{ - text-align: left; - margin-left: 2%; - .tags{ - margin-top: 1%; - font-size: 23px; - border: none; - background-color: transparent !important; - color: #565e6e; - } - } - .but-color { - background-color: #02DDEA !important; - } - .anDiv{ - width: 100%; - float: left; - text-align: center; - .glBut{ - width: 90px; - height: 30px; - display: inline-flex; - align-items: center; - justify-content: center; - margin-left: 5%; - margin-right: 5%; - background-color: rgba(24, 133, 234, 0.2); - color: #1b7cc4; - } - } -} -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/nodeList/module/CollectTraffic/module/DownloadPack.vue b/src/views/rangeNodeManage/nodeList/module/CollectTraffic/module/DownloadPack.vue deleted file mode 100644 index c9d7080..0000000 --- a/src/views/rangeNodeManage/nodeList/module/CollectTraffic/module/DownloadPack.vue +++ /dev/null @@ -1,223 +0,0 @@ -<template> - <div - class="custom-dialog" - v-if="visible" - > - <span class="dialog-title">pcap包下载</span> - <!-- 在此处指定弹窗的样式和内容 --> - <i class="el-icon-close" style="float: right; padding-right: 10%;padding-top: 2.5%" @click="close"></i> - <div class="basic-box"> - <div class="content"> - <el-table - class="main-table styleTable" - ref="multipleTable" - v-loading="loading" - height="420px" - style="width: 100%;" - :data="tableData" - tooltip-effect="dark" - highlight-current-row - @selection-change="handleSelectionChange" - > - <el-table-column - align="center" - type="selection" - width="80"/> - <el-table-column - align="center" - prop="bucket_name" - label="桶名称" - width="80"/> - <el-table-column - align="center" - prop="file_name" - label="文件名称" - min-width="100"/> - <el-table-column - align="center" - prop="size" - label="文件大小" - min-width="100" - > - </el-table-column> - <el-table-column - align="center" - prop="last_modified" - label="生成时间" - min-width="100" - > - <template slot-scope="scope"> - {{ scope.row.last_modified | formatTime }} - </template> - </el-table-column> - </el-table> - </div> - <div class="anDiv"> - <div> - <el-button class="glBut but-color" type="primary" @click="download" :loading="downLoading">下载</el-button> - </div> - </div> - </div> - </div> -</template> - -<script> -export default { - name: 'RuleForm', - // props: ['task_id'], - data() { - return { - visible: false, - loading: false, - downLoading: false, - task_id: '', - tableData: [], - selectFileNameList: [] - } - }, - created() { - }, - methods: { - init() { - const reqParams = { - page: 1, - size: 99, - task_id: this.task_id - } - this.loading = true - this.$axios.get(this.$http.api.getPackList, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.tableData = res?.result?.items - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.loading = false - }) - }, - handleSelectionChange(selectData) { - this.selectFileNameList = selectData.map(item => { - return { - bucket_name: item.bucket_name, - file_name: item.file_name - } - }) - }, - close() { - this.resetForm() - document.querySelector('.mask').style.display = 'none' - this.visible = false - }, - resetForm() { - }, - // 下载 - download() { - if (this.selectFileNameList.length <= 0) { - this.$notify({ - title: '请勾选要下载的文件', - type: 'warning', - duration: 2500 - }) - return - } - const reqParams = { - task_id: this.task_id, - object_info_list: JSON.stringify(this.selectFileNameList) - } - this.downLoading = true - this.$axios.getFile(this.$http.api.downloadPacp, 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 - this.close() - }) - } - } -} -</script> - -<style lang="less" scoped> - .custom-dialog{ - z-index: 998; - width: 620px; - height: 555px; - position: absolute; /* 绝对定位 */ - top: 50%; /* 向下偏移50% */ - left: 50%; /* 向右偏移50% */ - transform: translate(-50%, -50%); /* 回移50% */ - background-image:url('../../../../../../img/background/dialog660-553.svg'); - background-repeat: no-repeat; /* 可选,防止图像重复 */ - // background-size: 100% 100%; /* 宽度为100%,高度自适应保持宽高比 */ - .dialog-title { - font-size: 20px; - float: left; - margin: 11px 0 11px 20px; - } - .basic-box { - width: 100%; - min-height: 100%; - padding: 2%; - display: flex; - flex-direction: column; - .content { - flex: 1; - .bcmcDiv{ - width: 100%; - float: left; - margin-top: 5%; - text-align: center; - .bcmc { - width: 60%; - } - } - } - } - .anDiv{ - width: 100%; - float: left; - margin-bottom: 10%; - text-align: center; - .glBut{ - width: 90px; - height: 30px; - display: inline-flex; - align-items: center; - justify-content: center; - margin-left: 2%; - background-color: rgba(24, 133, 234, 0.2); - color: #1b7cc4; - } - .but-color { - background-color: #02DDEA; - } - } - } -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/nodeList/module/CollectTraffic/module/RuleForm.vue b/src/views/rangeNodeManage/nodeList/module/CollectTraffic/module/RuleForm.vue deleted file mode 100644 index f280b5a..0000000 --- a/src/views/rangeNodeManage/nodeList/module/CollectTraffic/module/RuleForm.vue +++ /dev/null @@ -1,164 +0,0 @@ -<template> - <div - class="rule-dialog" - v-if="visible" - > - <!-- 在此处指定弹窗的样式和内容 --> - <i class="el-icon-close" style="float: right; padding-right: 8%;padding-top: 3%" @click="close"></i> - <el-form - ref="ruleForm" - :model="form" - :rules="rules" - label-width="150px" - class="rule-form" - > - <el-row> - <el-col :span="20"> - <el-form-item label="规则名称" prop="rule_name"> - <el-input v-model="form.rule_name" placeholder="请输入规则名称"></el-input> - </el-form-item> - </el-col> - </el-row> - <el-row> - <el-col :span="20"> - <el-form-item label="规则" prop="rule"> - <el-input type="textarea" v-model="form.rule" placeholder="请输入规则"></el-input> - </el-form-item> - </el-col> - </el-row> - </el-form> - <div class="submit-footer"> - <div> - <el-button class="glBut but-color" type="primary" @click="submit" :loading="loading">确定</el-button> - </div> - </div> - <div class="mask"></div> - </div> -</template> - -<script> -export default { - name: 'RuleForm', - props: ['isAdd'], - data() { - return { - visible: false, - loading: false, - form: { - rule_name: '', // 规则名称 - rule: '' // 规则 - }, - rule_id: '', - rules: { - rule_name: [ - { required: true, message: '请输入规则名称', trigger: 'blur' } - ], - rule: [ - { required: true, message: '请输入规则', trigger: 'blur' } - ] - } - } - }, - methods: { - close() { - this.resetForm() - // document.querySelector('.mask').style.display = 'none' - this.visible = false - }, - submit() { - this.$refs.ruleForm.validate((valid) => { - if (valid) { - if (this.isAdd) { - this.add() - } else { - this.edit() - } - } - }) - }, - add () { - this.loading = true - const url = this.$http.api.rule - this.$axios.post(url, this.form).then(res => { - if (res.code == 200 || res.code == "OK") { - this.resetForm() - this.close() - this.$emit('refresh') - this.$notify({ - title: '创建规则成功', - type: 'success', - duration: 2500 - }) - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.loading = false - }) - }, - edit() { - this.loading = true - const url = this.$http.api.rule + `/${this.rule_id}` - this.$axios.put(url, this.form).then(res => { - if (res.code == 200 || res.code == "OK") { - this.resetForm() - this.close() - this.$emit('refresh') - this.$notify({ - title: '编辑规则成功', - type: 'success', - duration: 2500 - }) - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.loading = false - }) - }, - resetForm() { - this.form = { - rule_name: '', // 规则名称 - rule: '' // 规则 - } - } - } -} -</script> - -<style lang="less" scoped> - .rule-dialog{ - width: 620px; - height: 555px; - position: absolute; /* 绝对定位 */ - top: 50%; /* 向下偏移50% */ - left: 50%; /* 向右偏移50% */ - transform: translate(-50%, -50%); /* 回移50% */ - background-image:url('../../../../../../img/background/addRuleBg.svg'); - background-repeat: no-repeat; /* 可选,防止图像重复 */ - background-size: 100% 100%; /* 宽度为100%,高度自适应保持宽高比 */ - .rule-form { - margin-top: 70px; - text-align: left; - } - .submit-footer{ - width: 100%; - float: left; - margin-top: 200px; - text-align: center; - .glBut{ - width: 90px; - height: 30px; - display: inline-flex; - align-items: center; - justify-content: center; - margin-left: 2%; - background-color: rgba(24, 133, 234, 0.2); - color: #1b7cc4; - } - .but-color { - background-color: #02DDEA; - } - } - } -</style> diff --git a/src/views/rangeNodeManage/nodeList/module/CollectTraffic/module/TaskForm.vue b/src/views/rangeNodeManage/nodeList/module/CollectTraffic/module/TaskForm.vue deleted file mode 100644 index a7d2cc0..0000000 --- a/src/views/rangeNodeManage/nodeList/module/CollectTraffic/module/TaskForm.vue +++ /dev/null @@ -1,522 +0,0 @@ -<template> -<div class="console-dialog" v-if="visible"> - <!-- 在此处指定弹窗的样式和内容 --> - <i class="el-icon-close" @click="close"></i> - <div class="tag"> - <el-tag class="tags" :style="{'color': (tag==='添加任务') ? '#f8fdff': '#565e6e'}">添加任务</el-tag> - <el-tag class="tags" :style="{'color': (tag==='被操作节点') ? '#f8fdff': '#565e6e'}">被操作节点</el-tag> - <el-tag class="tags" :style="{'color': (tag==='操作') ? '#f8fdff': '#565e6e'}">操作</el-tag> - </div> - <div class="basic-box" v-if="tag==='添加任务'"> - <el-form - ref="addTaskForm" - :model="form" - :rules="taskRules" - label-width="150px" - class="basic-form" - size="small" - > - <el-row> - <el-col :span="12" :offset="6"> - <el-form-item label="任务名称" prop="task_name"> - <el-input v-model="form.task_name" placeholder="请输入任务名称"></el-input> - </el-form-item> - </el-col> - </el-row> - <el-row> - <el-col :span="12" :offset="6"> - <el-form-item label="任务描述" prop="task_description"> - <el-input v-model="form.task_description" placeholder="请输入任务描述"> - </el-input> - </el-form-item> - </el-col> - </el-row> - </el-form> - <footer class="anDiv"> - <el-button class="glBut" type="primary" @click="close">取消</el-button> - <el-button class="glBut but-color" type="primary" @click="updateTag('被操作节点', true)">下一步</el-button> - </footer> - </div> - <div class="table-box" v-if="tag==='被操作节点'"> - <div class="tip-message">请勾选多个节点</div> - <div class="content"> - <el-table - class="main-table styleTable" - ref="multipleTable" - height="100%" - style="width: 100%;" - :data="nodeList" - tooltip-effect="dark" - highlight-current-row - @selection-change="handleSelectionNode" - > - <el-table-column - align="center" - type="selection" - width="80"/> - <el-table-column - align="center" - prop="id" - label="id" - width="80"/> - <el-table-column - align="center" - prop="nick_name" - label="节点昵称" - min-width="100"/> - <el-table-column - align="center" - prop="role" - label="角色" - min-width="100"> - <template slot-scope="scope"> - <svg-icon :icon-class="scope.row.role"></svg-icon> - </template> - </el-table-column> - <el-table-column - align="center" - prop="ip" - label="ip" - min-width="150"/> - <el-table-column - align="center" - prop="status" - label="部署状态" - min-width="100" - > - <template slot-scope="scope"> - <div class="deploy-status"> - <svg-icon :icon-class="getStatus(scope.row.status).class"></svg-icon> - <span :class="getStatus(scope.row.status).class">{{ getStatus(scope.row.status).label }}</span> - </div> - </template> - </el-table-column> - <el-table-column - align="center" - prop="create_time" - label="创建开始时间" - min-width="100" - > - <template slot-scope="scope"> - {{ scope.row.create_time | formatDate }} - </template> - </el-table-column> - <el-table-column - align="center" - prop="complete_time" - label="创建完成时间" - min-width="100" - > - <template slot-scope="scope"> - {{ scope.row.complete_time | formatDate }} - </template> - </el-table-column> - </el-table> - </div> - <div class="anDiv"> - <div> - <el-button class="glBut" type="primary" @click="close">取消</el-button> - <el-button class="glBut but-color" type="primary" @click="updateTag('添加任务')">上一步</el-button> - <el-button class="glBut but-color" type="primary" @click="updateTag('操作', true)">下一步</el-button> - </div> - </div> - - </div> - <div class="basic-box" v-if="tag==='操作'"> - <el-form - ref="operateForm" - :model="form" - :rules="oprateRules" - label-width="150px" - class="basic-form" - size="small" - > - <el-row> - <el-col :span="12" :offset="6"> - <el-form-item label="选择规则" prop="traffic_collect_rule_id"> - <el-select v-model="form.traffic_collect_rule_id" placeholder="请选择规则" @focus="getRuleList"> - <el-option - v-for="item in ruleDict" - :key="item.value" - :label="item.label" - :value="item.value"> - </el-option> - </el-select> - </el-form-item> - </el-col> - </el-row> - <el-row> - <el-col :span="12" :offset="6"> - <el-form-item label="是否过滤噪音流量" prop="filter_noise"> - <el-radio-group v-model="form.filter_noise"> - <el-radio :label="true">是</el-radio> - <el-radio :label="false">否</el-radio> - </el-radio-group> - </el-form-item> - </el-col> - </el-row> - </el-form> - <div class="anDiv"> - <div> - <el-button class="glBut" type="primary" @click="close">取消</el-button> - <el-button class="glBut but-color" type="primary" @click="updateTag('被操作节点')">上一步</el-button> - <el-button class="glBut but-color" type="primary" @click="submit" :loading="loading">确认</el-button> - </div> - </div> - </div> -</div> -</template> - -<script> -export default { - name: 'TaskForm', - props: { - isAdd: { - typeof: Boolean, - required: true - }, - nodeList: { - typeof: Array, - require: true - }, - target_id: { - typeof: String, - required: true - } - }, - data() { - return { - visible:false, - loading: false, - tag:"添加任务", - task_id: '', - ruleDict: [], - form: { - task_name: '', // 任务名称 - task_description: '', // 任务描述 - node_list: [], // 节点列表 - traffic_collect_rule_id: null, // 选择规则 - filter_noise: true, // 是否过滤噪音流量 - }, - taskRules: { - task_name:[ - { required: true, message: '请输入任务名称', trigger: 'blur' } - ], - task_description: [ - { required: true, message: '请输入任务描述', trigger: 'blur' } - ] - }, - oprateRules: { - traffic_collect_rule_id: [ - { required: true, message: '请选择规则', trigger: 'blur' } - ], - filter_noise: [ - { required: true, message: '请选择是否过滤噪音流量', trigger: 'blur' } - ] - }, - setting_id: '', - torDict: [], - networkDict: [], - imageDict: [] - } - }, - created() { - // 获取规则字典 - this.getRuleList() - }, - methods: { - // 选择添加任务 - handleSelectionNode(selectRows) { - this.form.node_list = selectRows.map(row => { - return row.id - }) - }, - // 关闭 - close() { - document.querySelector('.mask').style.display = 'none' - this.visible = false - this.tag = '添加任务' - this.resetForm() - }, - // 重置 - resetForm() { - this.form = { - task_name: '', // 任务名称 - task_description: '', // 任务描述 - node_list: [], // 节点列表 - traffic_collect_rule_id: null, // 选择规则 - filter_noise: true, // 是否过滤噪音流量 - } - }, - // 选择哪个页面 - updateTag(val, isValid){ - if (val === '被操作节点' && isValid) { - this.$refs.addTaskForm.validate((valid) => { - if (valid) { - this.tag=val - } - }) - } else if(val === '操作' && isValid) { - if (this.form.node_list.length > 0) { - this.tag=val - } else { - this.$notify({ - title: '请勾选要被操作的节点!', - type: 'success', - duration: 2500 - }) - return - } - } else { - this.tag=val - } - }, - // 获取规则列表 - getRuleList() { - const reqParams = { - page: 1, - size: 99, - } - this.loading = true - this.$axios.get(this.$http.api.getRuleList, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.ruleDict = res?.result?.items.map(item => { - return { - label: item.rule_name, - value: item.id - } - }) - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.loading = false - }) - }, - // 提交数据 - submit() { - this.$refs.operateForm.validate((valid) => { - if (valid) { - if (this.isAdd) { - this.add() - } else { - this.edit() - } - } - }) - }, - add () { - this.loading = true - const url = this.$http.api.trafficTask - this.$axios.post(url, this.form).then(res => { - if (res.code == 200 || res.code == "OK") { - this.resetForm() - this.close() - this.$emit('refresh') - this.$notify({ - title: '创建任务成功', - type: 'success', - duration: 2500 - }) - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.loading = false - }) - }, - edit() { - this.loading = true - const url = this.$http.api.trafficTask + `/${this.task_id}` - this.$axios.put(url, this.form).then(res => { - if (res.code == 200 || res.code == "OK") { - this.resetForm() - this.close() - this.$emit('refresh') - this.$notify({ - title: '编辑任务成功', - type: 'success', - duration: 2500 - }) - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.loading = false - }) - }, - getStatus(status) { - let statusInfo = { - label: '', - class: '' - } - switch (status) { - case 'true': - case 'pending': - statusInfo.label = '正在部署' - statusInfo.class = 'deployNormal' - break; - case 'false': - statusInfo.label = '部署失败' - statusInfo.class = 'deployFail' - break; - case 'complete': - statusInfo.label = '部署完成' - statusInfo.class = 'deploySuccess' - break; - default: - break; - } - return statusInfo - } - } -} -</script> - -<style lang="less" scoped> -.console-dialog{ - z-index: 997; - width: 1171px; - height: 705px; - position: absolute; /* 绝对定位 */ - top: 50%; /* 向下偏移50% */ - left: 50%; /* 向右偏移50% */ - transform: translate(-50%, -50%); /* 回移50% */ - background-image:url('../../../../../../img/background/NodeListDialog.svg'); - background-repeat: no-repeat; /* 可选,防止图像重复 */ - background-size: cover; /* 宽度为100%,高度自适应保持宽高比 */ - - .el-icon-close{ - float: right; - padding-right: 7%; - padding-top: 1.8% - } - .tag{ - margin-left: 9%; - .tags{ - margin-right: 5%; - margin-top: 1%; - font-size: 23px; - border: none; - background-color: transparent !important; - color: #565e6e; - } - } - .basic-form { - margin-top: 50px; - text-align: left; - ::v-deep .el-select { - width: 100%; - } - } - .but-color { - background-color: #02DDEA !important; - } - - .basic-box{ - .anDiv{ - width: 100%; - float: left; - margin-top: 450px; - text-align: center; - .glBut{ - width: 90px; - height: 30px; - display: inline-flex; - align-items: center; - justify-content: center; - margin-left: 5%; - margin-right: 5%; - background-color: rgba(24, 133, 234, 0.2); - color: #1b7cc4; - } - - } - } - - .table-box{ - width: 100%; - min-height: 100%; - display: flex; - flex-direction: column; - padding: 2%; - .tip-message{ - width: 100%; - height: 50px; - text-align: left; - padding: 11px 0 12px 20px; - font-size: 20px; - background-color: #1A2648; - border-radius: 4px; - margin-bottom: 2%; - } - .content { - flex: 1; - display: flex; - flex-direction: row; - .deploy-status { - display: inline-block; - width: 103px; - height: 28px; - color:#FFFFFF; - border-radius: 3px; - padding: 5px, 12px, 5px, 12px; - background: rgba(227, 249, 233, 0.2); - } - .deployFail { - color: #E9473E; - width: 56px; - height: 28px; - margin-left: 10px; - font-family: PingFang SC; - font-size: 14px; - font-weight: 400; - line-height: 28px; - letter-spacing: 0em; - text-align: left; - } - .deployNormal { - color: #02DDEA; - width: 56px; - height: 28px; - margin-left: 10px; - font-family: PingFang SC; - font-size: 14px; - font-weight: 400; - line-height: 28px; - letter-spacing: 0em; - text-align: left; - } - .deploySuccess { - color: #0CCB64; - width: 56px; - height: 28px; - margin-left: 10px; - font-family: PingFang SC; - font-size: 14px; - font-weight: 400; - line-height: 28px; - letter-spacing: 0em; - text-align: left; - } - } - .anDiv{ - width: 100%; - float: left; - margin-bottom: 7%; - text-align: center; - .glBut{ - width: 90px; - height: 30px; - display: inline-flex; - align-items: center; - justify-content: center; - margin-left: 5%; - margin-right: 5%; - background-color: rgba(24, 133, 234, 0.2); - color: #1b7cc4; - } - } - } -} -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/nodeList/module/Console.vue b/src/views/rangeNodeManage/nodeList/module/Console.vue deleted file mode 100644 index fec6b03..0000000 --- a/src/views/rangeNodeManage/nodeList/module/Console.vue +++ /dev/null @@ -1,521 +0,0 @@ -<template> -<div class="console-dialog" v-if="visible"> - <!-- 在此处指定弹窗的样式和内容 --> - <i class="el-icon-close" @click="close"></i> - <div class="tag"> - <el-tag class="tags" :style="{'color': (tag==='主节点') ? '#f8fdff': '#565e6e'}" @click="updateTag('主节点')">主节点</el-tag> - <el-tag class="tags" :style="{'color': (tag==='被操作节点') ? '#f8fdff': '#565e6e'}" @click="updateTag('被操作节点')">被操作节点</el-tag> - <el-tag class="tags" :style="{'color': (tag==='控制台') ? '#f8fdff': '#565e6e'}" @click="updateTag('控制台')">控制台</el-tag> - </div> - <div class="basic-box" v-if="tag==='主节点'"> - <div class="tip-message">请选择主节点作为打开文件系统的依据</div> - <div class="content"> - <el-table - class="main-table styleTable" - ref="multipleTable" - height="100%" - style="width: 100%;" - :data="tableData" - tooltip-effect="dark" - highlight-current-row - @selection-change="handleSelectionMain" - > - <el-table-column - align="center" - type="selection" - width="80"/> - <el-table-column - align="center" - prop="id" - label="id" - width="80"/> - <el-table-column - align="center" - prop="nick_name" - label="节点昵称" - min-width="100"/> - <el-table-column - align="center" - prop="role" - label="角色" - min-width="100"> - <template slot-scope="scope"> - <svg-icon :icon-class="scope.row.role"></svg-icon> - </template> - </el-table-column> - <el-table-column - align="center" - prop="ip" - label="ip" - min-width="150"/> - <el-table-column - align="center" - prop="status" - label="部署状态" - min-width="100" - > - <!-- <template slot-scope="scope"> - {{ scope.row.has_deployed ? '已部署' : '未部署' }} - </template> --> - </el-table-column> - <el-table-column - align="center" - prop="create_time" - label="创建开始时间" - min-width="100" - > - <template slot-scope="scope"> - {{ scope.row.create_time | formatDate }} - </template> - </el-table-column> - <el-table-column - align="center" - prop="complete_time" - label="创建完成时间" - min-width="100" - > - <template slot-scope="scope"> - {{ scope.row.complete_time | formatDate }} - </template> - </el-table-column> - </el-table> - </div> - <footer class="anDiv"> - <el-button class="glBut" type="primary" @click="close">取消</el-button> - <el-button class="glBut but-color" type="primary" @click="updateTag('被操作节点')">下一步</el-button> - </footer> - </div> - <div class="basic-box" v-if="tag==='被操作节点'"> - <div class="tip-message">请勾选多个节点</div> - <div class="content"> - <el-table - class="main-table styleTable" - ref="multipleTable" - height="100%" - style="width: 100%;" - :data="tableData" - tooltip-effect="dark" - highlight-current-row - @selection-change="handleSelectionMain" - > - <el-table-column - align="center" - type="selection" - width="80"/> - <el-table-column - align="center" - prop="id" - label="id" - width="80"/> - <el-table-column - align="center" - prop="nick_name" - label="节点昵称" - min-width="100"/> - <el-table-column - align="center" - prop="role" - label="角色" - min-width="100"> - <template slot-scope="scope"> - <svg-icon :icon-class="scope.row.role"></svg-icon> - </template> - </el-table-column> - <el-table-column - align="center" - prop="ip" - label="ip" - min-width="150"/> - <el-table-column - align="center" - prop="status" - label="部署状态" - min-width="100" - > - <!-- <template slot-scope="scope"> - {{ scope.row.has_deployed ? '已部署' : '未部署' }} - </template> --> - </el-table-column> - <el-table-column - align="center" - prop="create_time" - label="创建开始时间" - min-width="100" - > - <template slot-scope="scope"> - {{ scope.row.create_time | formatDate }} - </template> - </el-table-column> - <el-table-column - align="center" - prop="complete_time" - label="创建完成时间" - min-width="100" - > - <template slot-scope="scope"> - {{ scope.row.complete_time | formatDate }} - </template> - </el-table-column> - </el-table> - </div> - <div class="anDiv"> - <div> - <el-button class="glBut" type="primary" @click="close">取消</el-button> - <el-button class="glBut but-color" type="primary" @click="updateTag('主节点')">上一步</el-button> - <el-button class="glBut but-color" type="primary" @click="updateTag('控制台')">下一步</el-button> - </div> - </div> - - </div> - <div class="basic-box" v-if="tag==='控制台'"> - <div class="tip-message">主节点名称:10-relaytwlgthavry -已勾选的节点名称列表:11-relayyqbgcxuewy、12-relayztitnmkgfl…</div> - <div class="content"> - <el-input - type="textarea" - :rows="25" - placeholder="请输入命令" - v-model="textarea"> - </el-input> - </div> - <div class="anDiv"> - <div> - <el-button class="glBut" type="primary" @click="close">取消</el-button> - <el-button class="glBut but-color" type="primary" @click="updateTag('被操作节点')">上一步</el-button> - <el-button class="glBut but-color" type="primary" @click="submit" :loading="loading">确认</el-button> - </div> - </div> - </div> -</div> -</template> - -<script> -export default { - name: 'Console', - props: { - tableData: { - typeof: Array, - require: true - }, - target_id: { - typeof: String, - required: true - } - }, - data() { - return { - visible:false, - loading: false, - tag:"主节点", - setting_id: '', - form: { - role: '', // 角色选择 - tor_version: '', // tor版本 - image_id: '', // 选择镜像 - replicas: '', // 复本数 - bandwidth: '', // 宽带限制 - memory: '', // 内存限制 - service: '', // 服务器地址 - out_port: '', // 代理端口 - or_port: '', // or端口 - dir_port: '', // dir端口 - socks_port: '', // 客户端监听端口 - control_port: '', // 客户端控制端口 - - country_id: '', // 国家 - network_id: '', // 网络 - - deployType: '', // 部署方式 - direct: false, // 直接部署true 仅添加配置false - start_tcpdump: false // 启动采集程序并部署 true - }, - roleDict:[ - {label: '权威目录节点', value: 'da'}, - {label: '路由节点', value: 'relay'}, - {label: '出口节点', value: 'exit'}, - {label: '洋葱服务节点', value: 'onion'}, - {label: '客户端节点', value: 'client'}, - {label: '入口节点', value: 'guard'}, - {label: '其他节点', value: 'other'} - ], - torDict: [], - networkDict: [], - imageDict: [] - } - }, - methods: { - // 选择主节点 - handleSelectionMain() {}, - // 关闭 - close() { - document.querySelector('.mask').style.display = 'none' - this.visible = false - this.tag = '主节点' - this.resetForm() - }, - // 重置 - resetForm() { - this.form = { - role: '', // 角色选择 - tor_version: '', // tor版本 - image_id: '', // 选择镜像 - replicas: '', // 复本数 - bandwidth: '', // 宽带限制 - memory: '', // 内存限制 - service: '', // 服务器地址 - out_port: '', // 代理端口 - or_port: '', // or端口 - dir_port: '', // dir端口 - socks_port: '', // 客户端监听端口 - control_port: '', // 客户端控制端口 - - country_id: '', // 国家 - network_id: '', // 网络 - - deployType: '', // 部署方式 - direct: false, // 直接部署true 仅添加配置false - start_tcpdump: false // 启动采集程序并部署 true - } - }, - // 选择哪个页面 - updateTag(val){ - this.tag=val - }, - // 角色选择 - selectRole(node) { - if (node === 'other') { - this.$emit('openRoleForm') - } - // 获取torDict - this.$axios.get(this.$http.api.getTorDict, {role: this.form.role}).then(res => { - if (res.code == 200 || res.code == "OK") { - this.torDict = res?.result - } - }).catch(err => { - console.log(err) - }) - // 获取镜像字典 - this.getImageDict() - - }, - // tor选择 - selectTor(tor){ - // 获取镜像字典 - this.getImageDict() - }, - // 获取imageDict - getImageDict(){ - const params = { - page:1, - size: 99, - image_name: this.form.role, - image_version: this.form.tor_version - } - this.$axios.get(this.$http.api.getImageDict, params).then(res => { - if (res.code == 200 || res.code == "OK") { - this.imageDict = res?.result?.items.map(item => { - return { - label: item.image_name + '-' + item.image_version, - value: item.id - } - }) - } - }).catch(err => { - console.log(err) - }) - }, - // 获取网络 - getNetworkDict(){ - const params = { - page:1, - size: 99, - country_id: this.form.country_id, - } - this.$axios.get(this.$http.api.getNetworkDict, params).then(res => { - if (res.code == 200 || res.code == "OK") { - this.networkDict = res?.result?.items.map(item => { - return { - label: item.cidr, - value: item.id - } - }) - } - }).catch(err => { - console.log(err) - }) - }, - selectDeploy(deployType) { - switch (deployType) { - case 'direct': - this.form.direct = true - break - case 'only': - this.form.direct = false - break - case 'start': - this.form.start_tcpdump = true - break - default: - this.form.direct = true - break - } - }, - // 提交数据 - submit() { - // const submitForm = this.setSubmitForm() - // if (this.isAdd) { - // this.add(submitForm) - // } else { - // this.edit(submitForm) - // } - }, - setSubmitForm() { - const {role, image_id, replicas, bandwidth, memory } = this.form - let submitForm = {role, image_id, replicas, bandwidth, memory } - if (this.form.role === 'other') { - submitForm.role = this.otherRole - } else if (this.form.role==='da'||this.form.role==='relay'||this.form.role ==='guard'||this.form.role ==='exit') { - submitForm.tor_version = this.form.tor_version - submitForm.or_port = this.form.or_port - submitForm.dir_port = this.form.dir_port - } else if (this.form.role==='onion') { - submitForm.tor_version = this.form.tor_version - submitForm.service = this.form.service - submitForm.socks_port = this.form.socks_port - submitForm.control_port = this.form.control_port - } else if (this.form.role==='client') { - submitForm.tor_version = this.form.tor_version - submitForm.out_port = this.form.out_port - submitForm.socks_port = this.form.socks_port - submitForm.control_port = this.form.control_port - } - return submitForm - }, - add(submitForm) { - this.loading = true - const url = this.$http.api.setting + `/?target_id=${this.target_id}&network_id=${this.form.network_id}&direct=${this.form.direct}&start_tcpdump=${this.form.start_tcpdump}` - this.$axios.post(url, submitForm).then(res => { - if (res.code == 200 || res.code == "OK") { - this.close() - this.$emit('refresh') - this.$notify({ - title: '添加靶场配置成功', - type: 'success', - duration: 2500 - }) - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.loading = false - }) - }, - edit(submitForm) { - this.loading = true - const url = this.$http.api.setting + `/?target_id=${this.target_id}&setting_id=${this.setting_id}&network_id=${this.form.network_id}&direct=${this.form.direct}&start_tcpdump=${this.form.start_tcpdump}` - this.$axios.put(url, submitForm).then(res => { - if (res.code == 200 || res.code == "OK") { - this.close() - this.$emit('refresh') - this.$notify({ - title: '添加靶场配置成功', - type: 'success', - duration: 2500 - }) - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.loading = false - }) - } - } -} -</script> - -<style lang="less" scoped> -.console-dialog{ - z-index: 997; - width: 1331px; - height: 800px; - position: absolute; /* 绝对定位 */ - top: 50%; /* 向下偏移50% */ - left: 50%; /* 向右偏移50% */ - transform: translate(-50%, -50%); /* 回移50% */ - background-image:url('../../../../img/background/NodeListDialog.svg'); - background-repeat: no-repeat; /* 可选,防止图像重复 */ - background-size: cover; /* 宽度为100%,高度自适应保持宽高比 */ - .el-icon-close{ - float: right; - padding-right: 8%; - padding-top: 1.8% - } - .tag{ - margin-left: 15%; - .tags{ - margin-right: 5%; - margin-top: 1%; - font-size: 23px; - border: none; - background-color: transparent !important; - color: #565e6e; - } - } - - .base-input { - width: 100%; - float: left; - margin-top: 2%; - text-align: center; - } - .label-span { - margin-right: 3%; - display: inline-block; - width: 60px; - text-align: right; - } - .but-color { - background-color: #02DDEA !important; - } - .basic-box{ - width: 100%; - min-height: 100%; - display: flex; - flex-direction: column; - padding: 2%; - .tip-message{ - width: 100%; - height: 50px; - line-height: 50px; - font-size: 20px; - background-color: #1A2648; - border-radius: 4px; - margin-bottom: 2%; - } - .content { - flex: 1; - ::v-deep .el-textarea__inner { - background-color: #1A2648; - } - } - .anDiv{ - width: 100%; - float: left; - margin-bottom: 7%; - text-align: center; - .glBut{ - width: 90px; - height: 30px; - display: inline-flex; - align-items: center; - justify-content: center; - margin-left: 5%; - margin-right: 5%; - background-color: rgba(24, 133, 234, 0.2); - color: #1b7cc4; - } - - } - } -} -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/nodeList/module/Download.vue b/src/views/rangeNodeManage/nodeList/module/Download.vue deleted file mode 100644 index b76a9e5..0000000 --- a/src/views/rangeNodeManage/nodeList/module/Download.vue +++ /dev/null @@ -1,274 +0,0 @@ -<template> -<div class="console-dialog" v-if="visible"> - <i class="el-icon-close" @click="close"></i> - <div class="tag"> - <el-tag class="tags" :style="{'color': (tag==='主节点') ? '#f8fdff': '#565e6e'}" @click="updateTag('主节点')">主节点</el-tag> - <el-tag class="tags" :style="{'color': (tag==='被操作节点') ? '#f8fdff': '#565e6e'}" @click="updateTag('被操作节点')">被操作节点</el-tag> - <el-tag class="tags" :style="{'color': (tag==='文件管理') ? '#f8fdff': '#565e6e'}" @click="updateTag('文件管理')">文件管理</el-tag> - </div> - <div class="basic-box" v-show="tag==='主节点'"> - <div class="tip-message">请选择主节点作为打开文件系统的依据</div> - <div class="content"> - <!-- 主节点 --> - <MainNode - :node-list="nodeList" - @selectMainNode="selectMainNode" - ></MainNode> - </div> - <footer class="anDiv"> - <el-button class="glBut" type="primary" @click="close">取消</el-button> - <el-button class="glBut but-color" type="primary" @click="updateTag('被操作节点')">下一步</el-button> - </footer> - </div> - <div class="basic-box" v-show="tag==='被操作节点'"> - <div class="tip-message">请勾选多个节点</div> - <div class="content"> - <!-- 被操作节点 --> - <OperateNode - :node-list="nodeList" - @selectOperateNode="selectOperateNode" - ></OperateNode> - </div> - <div class="anDiv"> - <div> - <el-button class="glBut" type="primary" @click="close">取消</el-button> - <el-button class="glBut but-color" type="primary" @click="updateTag('主节点')">上一步</el-button> - <el-button class="glBut but-color" type="primary" @click="updateTag('文件管理')">下一步</el-button> - </div> - </div> - - </div> - <div class="basic-box" v-if="tag==='文件管理'"> - <div class="tip-message" style="height: 76px;"> - <span>{{`主节点名称:${master_node_name}`}}<br/>{{`已勾选的节点名称列表:${batch_node_name_list.join('、')}`}}</span> - </div> - <!-- 文件管理 --> - <FileManager - ref="fileManager" - ></FileManager> - <div class="anDiv"> - <div> - <el-button class="glBut" type="primary" @click="close">取消</el-button> - <el-button class="glBut but-color" type="primary" @click="updateTag('被操作节点')">上一步</el-button> - <el-button class="glBut but-color" type="primary" @click="download" :loading="loading">下载</el-button> - </div> - </div> - </div> -</div> -</template> - -<script> -import MainNode from '../components/MainNode.vue' -import OperateNode from '../components/OperateNode.vue' -import FileManager from '../components/DownloadFileManager.vue' -import qs from 'qs' -export default { - name: 'Download', - components:{ - MainNode, - OperateNode, - FileManager - }, - props: { - target_id: { - typeof: String, - required: true - } - }, - data() { - return { - nodeList: [], - downloadForm: { - master_node_id: '', - batch_node_id_list: [], - current_dir: '', - filename: '' - }, - master_node_name: '', - batch_node_name_list: [], - visible:false, - loading: false, - tag:"主节点", - form: {} - } - }, - methods: { - // 获取节点列表 - getNodeList() { - const reqParams = { - page: 1, - size: 99 - } - if (this.target_id && this.target_id !== '') { - reqParams.target_id = this.target_id - } - this.$axios.get(this.$http.api.getNodeList, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.nodeList = res?.result?.items - } - }).catch(err => { - console.log(err) - }).finally(() => {}) - }, - // 选择主节点 - selectMainNode({ id, nick_name }) { - this.$store.commit('range/setNodeId', id) - this.downloadForm.master_node_id = id - this.master_node_name = nick_name - }, - // 选择被操作节点 - selectOperateNode(selectRows) { - this.batch_node_name_list = [] - this.downloadForm.batch_node_id_list = selectRows.map(row => { - this.batch_node_name_list.push(row.nick_name) - return row.id - }) - }, - // 选择上传文件 - selectUploadFile({path, file}) { - this.downloadForm.current_dir = path - this.downloadForm.file = file - }, - // 关闭 - close() { - document.querySelector('.mask').style.display = 'none' - this.visible = false - this.tag = '主节点' - this.resetForm() - }, - // 重置 - resetForm() { - this.form = {} - }, - // 选择哪个页面 - updateTag(val){ - this.tag=val - }, - // 提交数据 - download() { - this.downloadForm.current_dir = this.$refs.fileManager.selectNode.path - this.downloadForm.filename = this.$refs.fileManager.filename - const reqParams = qs.stringify(this.downloadForm, { arrayFormat: 'repeat' }) - const url = this.$http.api.batchDownload + '?' + reqParams - this.$axios.getFile(url).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.close() - }) - } - } -} -</script> - -<style lang="less" scoped> -.console-dialog{ - z-index: 997; - width: 1331px; - height: 800px; - position: absolute; /* 绝对定位 */ - top: 50%; /* 向下偏移50% */ - left: 50%; /* 向右偏移50% */ - transform: translate(-50%, -50%); /* 回移50% */ - background-image:url('../../../../img/background/NodeListDialog.svg'); - background-repeat: no-repeat; /* 可选,防止图像重复 */ - background-size: cover; /* 宽度为100%,高度自适应保持宽高比 */ - .el-icon-close{ - float: right; - padding-right: 8%; - padding-top: 1.8% - } - .tag{ - margin-left: 15%; - .tags{ - margin-right: 5%; - margin-top: 1%; - font-size: 23px; - border: none; - background-color: transparent !important; - color: #565e6e; - } - } - .base-input { - width: 100%; - float: left; - margin-top: 2%; - text-align: center; - } - .label-span { - margin-right: 3%; - display: inline-block; - width: 60px; - text-align: right; - } - .but-color { - background-color: #02DDEA !important; - } - .basic-box{ - width: 100%; - min-height: 100%; - display: flex; - flex-direction: column; - padding: 2%; - .tip-message{ - width: 100%; - height: 50px; - text-align: left; - padding: 11px 0 12px 20px; - font-size: 20px; - background-color: #1A2648; - border-radius: 4px; - margin-bottom: 2%; - } - .content { - flex: 1; - display: flex; - flex-direction: row; - } - .anDiv{ - width: 100%; - float: left; - margin-bottom: 7%; - text-align: center; - .glBut{ - width: 90px; - height: 30px; - display: inline-flex; - align-items: center; - justify-content: center; - margin-left: 5%; - margin-right: 5%; - background-color: rgba(24, 133, 234, 0.2); - color: #1b7cc4; - } - } - } -} -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/nodeList/module/Header.vue b/src/views/rangeNodeManage/nodeList/module/Header.vue deleted file mode 100644 index f4c97c7..0000000 --- a/src/views/rangeNodeManage/nodeList/module/Header.vue +++ /dev/null @@ -1,146 +0,0 @@ -<template> -<div class="head"> - <div class="role-select"> - <el-select v-model="role" clearable placeholder="节点角色" @change="query"> - <el-option - v-for="item in roleDict" - :key="item.value" - :label="item.label" - :value="item.value"> - <svg-icon :icon-class="item.value ? item.value : 'other'"></svg-icon> - <span style="margin-left: 10px;">{{ item.label }}</span> - </el-option> - </el-select> - </div> - <div class="deploy-select"> - <el-select v-model="status" clearable placeholder="节点部署状态" @change="query"> - <el-option - v-for="item in statusDict" - :key="item.value" - :label="item.label" - :value="item.value"> - </el-option> - </el-select> - </div> - <el-button v-if="false" type="primary" @click="batchConsole">批量控制台</el-button> - <el-button v-if="true" type="primary" @click="batchDownload">批量下载文件</el-button> - <el-button v-if="true" type="primary" @click="batchUpload">批量上传文件</el-button> - <el-button v-if="true" type="primary" @click="batchCollectTraffic">批量采集流量</el-button> -</div> -</template> - -<script> -export default { - name: 'Header', - data() { - return { - role: '', - status: '', - roleDict:[ - {label: '全部节点', value: ''}, - {label: '权威目录节点', value: 'da'}, - {label: '路由节点', value: 'relay'}, - {label: '出口节点', value: 'exit'}, - {label: '洋葱服务节点', value: 'onion'}, - {label: '客户端节点', value: 'client'}, - {label: '入口节点', value: 'guard'} - ], - statusDict: [ - {value: 'pending', label: '正在部署'}, - {value: 'false', label: '部署失败'}, - {value: 'complete',label: '部署完成'} - ] - } - }, - methods: { - // 查询 - query() { - let params = {} - if (this.role !== '') { - params.role = this.role - } - if (this.status !== '') { - params.status = this.status - } - this.$emit('query', params) - }, - // 批量控制台 - batchConsole() { - this.$emit('batchConsole') - }, - // 批量下载文件 - batchDownload() { - this.$emit('batchDownload') - }, - // 批量上传文件 - batchUpload() { - this.$emit('batchUpload') - }, - // 批量采集流量 - batchCollectTraffic() { - this.$emit('batchCollectTraffic') - } - } -} -</script> - -<style lang="less" scoped> -.head{ - width: 100%; - height: 15%; - margin-top: 1%; - text-align: right; - - /*background-color: #5daf34;*/ - .block{ - display: inline-block; - margin-left: 2%; - - } - .input{ - display: inline-block; - height: 60%; - width: 10%; - margin-left: 0.5%; - .el-input::placeholder { - width: auto; - } - .icon-group { - display: flex; /* 设置容器为 Flexbox 容器 */ - align-items: center; /* 垂直居中图片 */ - gap: 5px; /* 图片和文字之间的间距,可以根据需要进行调整 */ - - } - .icon-group img { - transform: scale(1); - margin-right: 15px; - margin-top: 6px; - } - - } - .deploy-select{ - display: inline-block; - height: 60%; - width: 10%; - margin-top: 0.5%; - margin-left: 0.5%; - margin-right: 1%; - .el-input::placeholder { - width: auto; - } - .icon-group { - display: flex; /* 设置容器为 Flexbox 容器 */ - align-items: center; /* 垂直居中图片 */ - gap: 5px; /* 图片和文字之间的间距,可以根据需要进行调整 */ - } - .icon-group img { - transform: scale(1); - margin-right: 15px; - margin-top: 6px; - } - } - ::v-deep .role-select{ - display: inline-block; - } -} -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/nodeList/module/Upload.vue b/src/views/rangeNodeManage/nodeList/module/Upload.vue deleted file mode 100644 index 987749c..0000000 --- a/src/views/rangeNodeManage/nodeList/module/Upload.vue +++ /dev/null @@ -1,285 +0,0 @@ -<template> -<div class="console-dialog" v-if="visible"> - <i class="el-icon-close" @click="close"></i> - <div class="tag"> - <el-tag class="tags" :style="{'color': (tag==='主节点') ? '#f8fdff': '#565e6e'}" @click="updateTag('主节点')">主节点</el-tag> - <el-tag class="tags" :style="{'color': (tag==='被操作节点') ? '#f8fdff': '#565e6e'}" @click="updateTag('被操作节点')">被操作节点</el-tag> - <el-tag class="tags" :style="{'color': (tag==='文件管理') ? '#f8fdff': '#565e6e'}" @click="updateTag('文件管理')">文件管理</el-tag> - </div> - <div class="basic-box" v-show="tag==='主节点'"> - <div class="tip-message">请选择主节点作为打开文件系统的依据</div> - <div class="content"> - <!-- 主节点 --> - <MainNode - :node-list="nodeList" - @selectMainNode="selectMainNode" - ></MainNode> - </div> - <footer class="anDiv"> - <el-button class="glBut" type="primary" @click="close">取消</el-button> - <el-button class="glBut but-color" type="primary" @click="updateTag('被操作节点')">下一步</el-button> - </footer> - </div> - <div class="basic-box" v-show="tag==='被操作节点'"> - <div class="tip-message">请勾选多个节点</div> - <div class="content"> - <!-- 被操作节点 --> - <OperateNode - :node-list="nodeList" - @selectOperateNode="selectOperateNode" - ></OperateNode> - </div> - <div class="anDiv"> - <div> - <el-button class="glBut" type="primary" @click="close">取消</el-button> - <el-button class="glBut but-color" type="primary" @click="updateTag('主节点')">上一步</el-button> - <el-button class="glBut but-color" type="primary" @click="updateTag('文件管理')">下一步</el-button> - </div> - </div> - - </div> - <div class="basic-box" v-if="tag==='文件管理'"> - <div class="tip-message" style="height: 76px;"> - <span>{{`主节点名称:${master_node_name}`}}<br/>{{`已勾选的节点名称列表:${batch_node_name_list.join('、')}`}}</span> - </div> - <!-- 文件管理 --> - <FileManager - ref="fileManager" - ></FileManager> - <div class="anDiv"> - <div> - <el-button class="glBut" type="primary" @click="close">取消</el-button> - <el-button class="glBut but-color" type="primary" @click="updateTag('被操作节点')">上一步</el-button> - <label - class="file-upload-button" - for="file-input-upload" - > - <span>上传</span> - <input - type="file" - id="file-input-upload" - @change="submit" - style="display: none;" - /> - </label> - </div> - </div> - </div> -</div> -</template> - -<script> -import MainNode from '../components/MainNode.vue' -import OperateNode from '../components/OperateNode.vue' -import FileManager from '../components/UploadFileManager.vue' -import qs from 'qs' -export default { - name: 'Upload', - components:{ - MainNode, - OperateNode, - FileManager - }, - props: { - target_id: { - typeof: String, - required: true - } - }, - data() { - return { - nodeList: [], - uploadForm: { - master_node_id: '', - batch_node_id_list: [], - current_dir: '' - }, - file: '', - master_node_name: '', - batch_node_name_list: [], - visible:false, - loading: false, - tag:"主节点", - form: {} - } - }, - methods: { - // 获取节点列表 - getNodeList() { - const reqParams = { - page: 1, - size: 99 - } - if (this.target_id && this.target_id !== '') { - reqParams.target_id = this.target_id - } - this.$axios.get(this.$http.api.getNodeList, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.nodeList = res?.result?.items - } - }).catch(err => { - console.log(err) - }).finally(() => {}) - }, - // 选择主节点 - selectMainNode({ id, nick_name }) { - this.$store.commit('range/setNodeId', id) - this.uploadForm.master_node_id = id - this.master_node_name = nick_name - }, - // 选择被操作节点 - selectOperateNode(selectRows) { - this.batch_node_name_list = [] - this.uploadForm.batch_node_id_list = selectRows.map(row => { - this.batch_node_name_list.push(row.nick_name) - return row.id - }) - }, - // // 选择上传文件 - // selectUploadFile({path}) { - // this.uploadForm.current_dir = path - // // this.file = file - // }, - // 关闭 - close() { - document.querySelector('.mask').style.display = 'none' - this.visible = false - this.tag = '主节点' - this.resetForm() - }, - // 重置 - resetForm() { - this.form = {} - }, - // 选择哪个页面 - updateTag(val){ - this.tag=val - }, - // 提交数据 - submit(e) { - this.uploadForm.current_dir = this.$refs.fileManager.selectNode.path - this.file = e.target.files[0] - const params = qs.stringify(this.uploadForm, { arrayFormat: 'repeat' }) - const url = this.$http.api.batchUpload + '?' + params - const submitForm = new FormData() - submitForm.append('file', this.file) - this.loading = true - this.$axios.postFormData(url, submitForm).then(res => { - if (res.code == 200 || res.code == "OK") { - this.$notify({ - title: '批量上传成功', - type: 'success', - duration: 2500 - }) - // 更新当前路径下的文件信息 - this.$refs.fileManager.updateCurrentPath() - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.loading = false - }) - } - } -} -</script> - -<style lang="less" scoped> -.console-dialog{ - z-index: 997; - width: 1331px; - height: 800px; - position: absolute; /* 绝对定位 */ - top: 50%; /* 向下偏移50% */ - left: 50%; /* 向右偏移50% */ - transform: translate(-50%, -50%); /* 回移50% */ - background-image:url('../../../../img/background/NodeListDialog.svg'); - background-repeat: no-repeat; /* 可选,防止图像重复 */ - background-size: cover; /* 宽度为100%,高度自适应保持宽高比 */ - .el-icon-close{ - float: right; - padding-right: 8%; - padding-top: 1.8% - } - .tag{ - margin-left: 15%; - .tags{ - margin-right: 5%; - margin-top: 1%; - font-size: 23px; - border: none; - background-color: transparent !important; - color: #565e6e; - } - } - .base-input { - width: 100%; - float: left; - margin-top: 2%; - text-align: center; - } - .label-span { - margin-right: 3%; - display: inline-block; - width: 60px; - text-align: right; - } - .but-color { - background-color: #02DDEA !important; - } - - .file-upload-button { - display: inline-block; - padding: 5px 33px; - background-color: #02DDEA; - color: #1b7cc4; - border: none; - border-radius: 0; - cursor: pointer; - font-size: 14px; - } - .file-upload-button:hover { - background-color: #02DDEA; - } - - .basic-box{ - width: 100%; - min-height: 100%; - display: flex; - flex-direction: column; - padding: 2%; - .tip-message{ - width: 100%; - height: 50px; - text-align: left; - padding: 11px 0 12px 20px; - font-size: 20px; - background-color: #1A2648; - border-radius: 4px; - margin-bottom: 2%; - } - .content { - flex: 1; - display: flex; - flex-direction: row; - } - .anDiv{ - width: 100%; - float: left; - margin-bottom: 7%; - text-align: center; - .glBut{ - width: 90px; - height: 30px; - display: inline-flex; - align-items: center; - justify-content: center; - margin-left: 5%; - margin-right: 5%; - background-color: rgba(24, 133, 234, 0.2); - color: #1b7cc4; - } - } - } -} -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/topologyMap/index.vue b/src/views/rangeNodeManage/topologyMap/index.vue deleted file mode 100644 index 5b225f6..0000000 --- a/src/views/rangeNodeManage/topologyMap/index.vue +++ /dev/null @@ -1,30 +0,0 @@ -<template> - <div class="topology-map"> - <!-- <img class="img-topology" src="../../../img/background/topology.svg"> --> - <div class="img-topology"></div> - </div> -</template> - -<script> -export default { - name: 'TopologyMap', -} -</script> - -<style lang='less' scoped> - .topology-map { - width: 49%; - height: 100%; - background-image:url('../../../img/backgroundFourCorner.png'); - background-repeat: no-repeat; - background-size: 100% 100%; - } - .img-topology { - width: 100%; - height: 100%; - background-image:url('../../../img/background/topology.svg'); - background-position: center center; - background-repeat: no-repeat; - background-size: contain; - } -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/worldMap/Map.vue b/src/views/rangeNodeManage/worldMap/Map.vue deleted file mode 100644 index 1a8e0d2..0000000 --- a/src/views/rangeNodeManage/worldMap/Map.vue +++ /dev/null @@ -1,217 +0,0 @@ -<template> -<div class='wrapper' v-loading="loading"> - <div class='chart' id='chart' style="width: 100%; height: 100%;"></div> -</div> -</template> - -<script> -import { getTargetsResponse } from './mock.js' -export default { - data () { - return { - loading: false, - worldChart: {}, - target_id: '', - NodeList: [], - namemap: {}, - geoCoordMap: {} - } - }, - props:{ - }, - watch: { - '$store.state.range.targetId': { - handler(newVal, oldVal) { - this.target_id = newVal - this.init() - }, - immediate: true - } - }, - created() { - }, - mounted () { - }, - methods: { - init() { - this.initData() - }, - initData() { - // 获取world.json里面国家数据和坐标数据 - var json = require('/src/api/world.json') - this.geoCoordMap = json.trapeze - this.namemap = json.namemap - // 获取接口节点数据 - // this.NodeList = getTargetsResponse?.result - - const reqParams = {} - if (this.target_id && this.target_id !== '') { - reqParams.target_id = this.target_id - } - this.loading = true - this.$axios.get(this.$http.api.worldMap, reqParams).then(res => { - if (res.code == 200 || res.code == "OK") { - this.NodeList = res?.result - } - }).catch(err => { - console.log(err) - }).finally(() => { - this.loading = false - this.initWorldMap(this.namemap, this.geoCoordMap) - }) - }, - initWorldMap(namemap, geoCoordMap) { - // var that = this - // 获取echarts的容器 - this.worldChart = this.$echarts.init(document.getElementById("chart")); - var pointData = this.NodeList - var series = []; - [[, pointData]].forEach(function (item, i) { - series.push({ - type: "effectScatter", - coordinateSystem: "geo", - zlevel: 2, - rippleEffect: { - //涟漪特效 - period: 4, //动画时间,值越小速度越快 - brushType: "stroke", //波纹绘制方式 stroke, fill - scale: 4 - //波纹圆环最大限制,值越大波纹越大 - }, - label: { - normal: { - show: true, - position: "right", //显示位置 - offset: [5, 0], //偏移设置 - formatter: "{b}" //圆环显示文字 - }, - emphasis: { - show: true - } - }, - symbol: "circle", - symbolSize: function (val) { - return 5; //圆环大小 - }, - data: item[1].map(dataItem => { - let countryName = '' - for (let key in namemap) { - if(key.toLowerCase() === dataItem.country.replace('-', ' ').toLowerCase()) { - countryName = namemap[key] - } - } - const location = [Number(dataItem.location_info.longitude), Number(dataItem.location_info.latitude), dataItem.id] - return { - name: dataItem.nick_name, - value: location, - nodeInfo: dataItem - } - }) - }); - }); - - let option = { - // backgroundColor: '#000', - // 图表主标题 - title: { - text: '世界地图展示各节点位置', // 主标题文本,支持使用 \n 换行 - top: 5, // 定位 值: 'top', 'middle', 'bottom' 也可以是具体的值或者百分比 - left: 'left', // 值: 'left', 'center', 'right' 同上 - textStyle: { // 文本样式 - fontSize: 14, - fontWeight: 400, - color: '#ffffff' - } - }, - //悬浮提示 - tooltip: { - trigger: "item", - // backgroundColor: "#1540a1", - borderColor: "#FFFFFF", - showDelay: 0, - hideDelay: 0, - // enterable: true, - transitionDuration: 0, - // extraCssText: "z-index:100",formatter - formatter: function (params, ticket, callback) { - // console.log(params) - //根据业务自己拓展要显示的内容 - var res = ""; - const { name, value, nodeInfo } = params.data - res = "<span style='display:inline-block; text-align:left;'>id:" + value[2] - + "<br/>昵称:" + name.toString() - + "<br/>国家:" + nodeInfo.location_info.country - + "<br/>ip:" + nodeInfo.ip - + "<br/>经纬度:" + value[0] + ',' + value[1] - + "</span>"; - return res; - } - }, - visualMap: { - //图例值控制 - show: false, - min: 0, - max: 1000, - text:['max','min'], - realtime: false, - calculable: true, - color: ['orangered'] - // color: ['#0064d0','#c3e0ff'], - }, - geo: { - map: "world", - label: { - emphasis: { - show: false - } - }, - roam: true, //是否允许缩放 - layoutCenter: ["50%", "50%"], //地图位置 - layoutSize: "180%", - itemStyle: { - normal: { - areaColor: '#0064d0', //地图背景色 - // color: ["#04284e"], //地图背景色 - borderColor: "#5bc1c9" //省市边界线 - }, - emphasis: { - color: "rgba(37, 43, 61, .5)" //选中区域的颜色 - // areaColor: '#3742ff' // 选中区域的颜色 - } - }, - nameMap: this.namemap - }, - series: series, - loading: true // 开启Loading效果 - }; - this.worldChart.setOption(option); - //点击事件,根据点击某个节点跳转到节点详情页 - this.worldChart.on("click", params => { - if (params.value) { - this.$store.commit('range/setNodeId', params.value[2]) - //保存是否正在采集流量 - this.$store.commit('node/setStartTraffic', params?.data?.nodeInfo?.collecting) - //保存是否正在结束采集流量 - this.$store.commit('node/setEndTraffic', params?.data?.nodeInfo?.analysing) - this.$router.push({ name: 'nodeDetail'}) - } - }); - } - // drawChart () { - // this.initWorldMap(this.namemap, this.geoCoordMap) - // } - } -} -</script> -<style lang="less" scoped> -.wrapper { - width: 100%; - height: 100%; -} -.wrapper .chart { - width: 100%; - margin:0 auto; - height: 100%; - background-size: 100% 100%; -} -</style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/worldMap/index.vue b/src/views/rangeNodeManage/worldMap/index.vue deleted file mode 100644 index d4da6c0..0000000 --- a/src/views/rangeNodeManage/worldMap/index.vue +++ /dev/null @@ -1,68 +0,0 @@ -<template> - <div :class="['world-map', {'is--maximize': isFullscreen}]"> - <Map ref="worldMap"></Map> - <span class="icon-span" slot="label"> - <svg-icon class="icon-zoom" :icon-class="fullscreenIcon" @click="zoomEvent"></svg-icon> - </span> - </div> - </template> - - <script> - import Map from './Map' - export default { - name: 'WorldMap', - components: { Map }, - data() { - return { - isFullscreen: false, - fullscreenIcon: 'fullscreen' - } - }, - methods: { - zoomEvent() { - this.isFullscreen = !this.isFullscreen - this.fullscreenIcon = this.isFullscreen ? 'narrow' : 'fullscreen' - this.$nextTick(() => { - this.$refs.worldMap.worldChart.resize() - }) - }, - } - - } - </script> - - <style lang='less' scoped> - .world-map { - position: relative; - width: 49%; - height: 100%; - background-image:url('../../../img/backgroundFourCorner.png'); - background-repeat: no-repeat; - background-size: 100% 100%; - .icon-span { - position: absolute; - top: 10px; - right: -10px; - padding: 12px 20px; - .icon-zoom { - font-size: 30px; - color: #02DDEA; - margin: 0 15px; - } - } - } - .is--maximize { - position: fixed; - top: 0; - left: 0; - width: 100% !important; - height: 100% !important; - padding: 0.5em 1em; - // background-color: #17234e; - background: url(../../../img/background/bgMain.svg); - background-repeat: no-repeat; /* 可选,防止图像重复 */ - background-position: center; /* 居中显示 */ - background-size: cover; /* 宽度为100%,高度自适应保持宽高比 */ - z-index: 1000; - } - </style>
\ No newline at end of file diff --git a/src/views/rangeNodeManage/worldMap/mock.js b/src/views/rangeNodeManage/worldMap/mock.js deleted file mode 100644 index 0ba865a..0000000 --- a/src/views/rangeNodeManage/worldMap/mock.js +++ /dev/null @@ -1,113 +0,0 @@ -const getTargetsResponse = { - "code": 200, - "message": "success", - "result": [ - { - "setting_id": 1, - "traffic_collect_task_id": null, - "id": 1, - "ip": "171.25.193.64", - "pod_name": "target-1-da-1-6cddf4649d-mfpx7", - "nick_name": "daoranjcqlil", - "status": "complete", - "onion": null, - "create_time": "2023-12-29T18:50:32", - "complete_time": "2023-12-29T19:00:17", - "role": "da", - "country": "sweden", - "cidr": "171.25.193.0/24" - }, - { - "setting_id": 2, - "traffic_collect_task_id": null, - "id": 2, - "ip": "193.31.27.64", - "pod_name": "target-1-relay-2-8df66cb66-slhnv", - "nick_name": "relayjknwkekrof", - "status": "complete", - "onion": null, - "create_time": "2023-12-29T18:50:34", - "complete_time": "2023-12-29T19:05:01", - "role": "relay", - "country": "germany", - "cidr": "193.31.27.0/24" - }, - { - "setting_id": 3, - "traffic_collect_task_id": null, - "id": 3, - "ip": "80.228.207.64", - "pod_name": "target-1-relay-3-6f57bf5448-snwgk", - "nick_name": "relayuyunnharjw", - "status": "complete", - "onion": null, - "create_time": "2023-12-29T18:50:36", - "complete_time": "2023-12-29T19:05:00", - "role": "relay", - "country": "germany", - "cidr": "80.228.207.0/24" - }, - { - "setting_id": 4, - "traffic_collect_task_id": null, - "id": 4, - "ip": "116.202.169.64", - "pod_name": "target-1-relay-4-557dcdfbd7-4lx5p", - "nick_name": "relayslwwaewlzs", - "status": "complete", - "onion": null, - "create_time": "2023-12-29T18:50:38", - "complete_time": "2023-12-29T19:04:00", - "role": "relay", - "country": "germany", - "cidr": "116.202.169.0/24" - }, - { - "setting_id": 6, - "traffic_collect_task_id": null, - "id": 6, - "ip": "84.19.188.64", - "pod_name": "target-1-relay-6-8559fc5858-j2v5m", - "nick_name": "relayzvrsfipwmd", - "status": "complete", - "onion": null, - "create_time": "2023-12-29T18:50:46", - "complete_time": "2023-12-29T19:08:06", - "role": "relay", - "country": "germany", - "cidr": "84.19.188.0/24" - }, - { - "setting_id": 7, - "traffic_collect_task_id": null, - "id": 7, - "ip": "45.138.16.0", - "pod_name": "target-1-exit-7-78984bf859-2hmnc", - "nick_name": "exitpzidrsshzi", - "status": "complete", - "onion": null, - "create_time": "2023-12-29T18:50:48", - "complete_time": "2023-12-29T19:07:12", - "role": "exit", - "country": "netherlands", - "cidr": "45.138.16.0/24" - }, - { - "setting_id": 8, - "traffic_collect_task_id": null, - "id": 8, - "ip": "77.91.68.64", - "pod_name": "target-1-exit-8-865cf99948-gw7br", - "nick_name": "exitgqnnvqsoux", - "status": "complete", - "onion": null, - "create_time": "2023-12-29T18:50:49", - "complete_time": "2023-12-29T19:04:56", - "role": "exit", - "country": "russia", - "cidr": "77.91.68.0/24" - } - ] -} - -export { getTargetsResponse }
\ No newline at end of file |
