- 开发中...
+
+
+
+
+
+
+
+
+
+ 修改
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 关闭
+ {{ isModify ? '修改' : '添加' }}
+
+
+
-
+.host_count {
+ display: block;
+ width: 100px;
+ text-align: center;
+ font-size: 15px;
+ color: #87cf63;
+ cursor: pointer;
+}
+
\ No newline at end of file
diff --git a/web/src/views/server/components/host-form.vue b/web/src/views/server/components/host-form.vue
index 982bb60..f09ace7 100644
--- a/web/src/views/server/components/host-form.vue
+++ b/web/src/views/server/components/host-form.vue
@@ -288,7 +288,7 @@ const visible = computed({
set: (newVal) => emit('update:show', newVal)
})
-const title = computed(() => props.defaultData ? '修改实例' : '新增实例')
+const title = computed(() => props.defaultData ? '修改实例' : '添加实例')
let groupList = computed(() => $store.groupList)
let sshList = computed(() => $store.sshList)
diff --git a/web/src/views/terminal/components/info-side.vue b/web/src/views/terminal/components/info-side.vue
index 0083dcc..df46c86 100644
--- a/web/src/views/terminal/components/info-side.vue
+++ b/web/src/views/terminal/components/info-side.vue
@@ -190,7 +190,7 @@
-->
命令输入框
diff --git a/web/src/views/terminal/components/terminal-tab.vue b/web/src/views/terminal/components/terminal-tab.vue
index 2afde4a..2f6b693 100644
--- a/web/src/views/terminal/components/terminal-tab.vue
+++ b/web/src/views/terminal/components/terminal-tab.vue
@@ -26,7 +26,7 @@ const props = defineProps({
}
})
-const emit = defineEmits(['input',])
+const emit = defineEmits(['inputCommand',])
const socket = ref(null)
const term = ref(null)
@@ -206,8 +206,7 @@ const onData = () => {
let acsiiCode = key.codePointAt()
if (acsiiCode === 22) return handlePaste()
if (acsiiCode === 6) return searchBar.value.show()
- emit('input', { idx: props.index, key })
- // console.log('input:', key)
+ emit('inputCommand', key)
socket.value.emit('input', key)
})
}
@@ -218,8 +217,7 @@ const handleClear = () => {
const handlePaste = async () => {
let key = await navigator.clipboard.readText()
- emit('input', { idx: props.index, key })
- // console.log('input:', key)
+ emit('inputCommand', key)
socket.value.emit('input', key)
term.value.focus()
}
@@ -231,7 +229,7 @@ const focusTab = () => {
}, 200)
}
-const handleInputCommand = (command) => {
+const inputCommand = (command) => {
socket.value.emit('input', command)
}
@@ -250,7 +248,7 @@ onBeforeUnmount(() => {
defineExpose({
focusTab,
handleResize,
- handleInputCommand,
+ inputCommand,
handleClear
})
diff --git a/web/src/views/terminal/components/terminal.vue b/web/src/views/terminal/components/terminal.vue
index 1534bac..591120d 100644
--- a/web/src/views/terminal/components/terminal.vue
+++ b/web/src/views/terminal/components/terminal.vue
@@ -1,34 +1,99 @@
-
- 新建连接
-
-
-
- {{ item.name }} {{ item.host }}
-
-
-
-
-
- 会话同步
-
-
-
-
- 同步键盘输入到所有会话
-
-
-
-
-
-
-
-
-
+
+
-
+
@@ -98,9 +163,10 @@ const emit = defineEmits(['closed', 'removeTab', 'add-host',])
const showInputCommand = ref(false)
const infoSideRef = ref(null)
-const terminalTabRefs = ref([])
+const terminalRefs = ref([])
let activeTabIndex = ref(0)
let visible = ref(true)
+let showSftp = ref(false)
let mainHeight = ref('')
let isSyncAllSession = ref(false)
let hostFormVisible = ref(false)
@@ -110,6 +176,7 @@ const terminalTabs = computed(() => props.terminalTabs)
const terminalTabsLen = computed(() => props.terminalTabs.length)
const curHost = computed(() => terminalTabs.value[activeTabIndex.value])
let hostList = computed(() => $store.hostList)
+let scriptList = computed(() => $store.scriptList)
// const closable = computed(() => terminalTabs.length > 1)
@@ -135,7 +202,7 @@ const handleUpdateList = async ({ isConfig, host }) => {
}
}
-function handleResizeTerminalSftp() {
+const handleResizeTerminalSftp = () => {
$nextTick(() => {
mainHeight.value = document.querySelector('.terminals_sftp_wrap').offsetHeight - 45 // 45 is tab-header height+15
})
@@ -157,25 +224,33 @@ const handleSyncSession = () => {
else $message.info('已关闭键盘输入到所有会话')
}
-const terminalInput = ({ idx, key }) => {
- if (!isSyncAllSession.value) return
- let filterHostList = terminalTabRefs.value.filter((host, index) => {
- return index !== idx
+const handleExecScript = (scriptObj) => {
+ // console.log(scriptObj.content)
+ if (!isSyncAllSession.value) return handleInputCommand(scriptObj.content)
+ terminalRefs.value.forEach(terminalRef => {
+ terminalRef.inputCommand(scriptObj.content)
})
- filterHostList.forEach(item => {
- item.handleInputCommand(key)
+}
+
+const terminalInput = (command) => {
+ if (!isSyncAllSession.value) return
+ let filterTerminalRefs = terminalRefs.value.filter((host, index) => {
+ return index !== activeTabIndex.value
+ })
+ filterTerminalRefs.forEach(hostRef => {
+ hostRef.inputCommand(command)
})
}
const tabChange = async (index) => {
await $nextTick()
- const curTabTerminal = terminalTabRefs.value[index]
- curTabTerminal?.focusTab()
+ const curTerminalRef = terminalRefs.value[index]
+ curTerminalRef?.focusTab()
}
watch(terminalTabsLen, () => {
let len = terminalTabsLen.value
- console.log('add tab:', len)
+ // console.log('add tab:', len)
if (len > 0) {
activeTabIndex.value = len - 1
// registryDbClick()
@@ -222,23 +297,23 @@ const handleFullScreen = () => {
// removeTab(key)
// }
-const handleVisibleSidebar = () => {
- visible.value = !visible.value
- resizeTerminal()
-}
+// const handleVisibleSidebar = () => {
+// visible.value = !visible.value
+// resizeTerminal()
+// }
const resizeTerminal = () => {
- for (let terminalTabRef of terminalTabRefs.value) {
+ for (let terminalTabRef of terminalRefs.value) {
const { handleResize } = terminalTabRef || {}
handleResize && handleResize()
}
}
const handleInputCommand = async (command) => {
- const curTabTerminal = terminalTabRefs.value[activeTabIndex.value]
+ const curTerminalRef = terminalRefs.value[activeTabIndex.value]
await $nextTick()
- curTabTerminal?.focusTab()
- curTabTerminal.handleInputCommand(`${ command }\n`)
+ curTerminalRef?.focusTab()
+ curTerminalRef.inputCommand(`${ command }\n`)
showInputCommand.value = false
}
@@ -265,34 +340,68 @@ const handleInputCommand = async (command) => {
}
$terminalTopHeight: 30px;
+
.terminal_top {
width: 100%;
height: $terminalTopHeight;
display: flex;
align-items: center;
+ justify-content: space-between;
padding: 0 15px;
- border-bottom: 1px solid var(--el-color-primary);
position: sticky;
top: 0;
- background-color: #fff;
+ border-bottom: 1px solid #fff;
+ // background-color: #fff;
+ background: var(--el-fill-color-light);
+ color: var(--el-text-color-regular);
z-index: 3;
- :deep(.el-dropdown) {
- margin-top: -2px;
+ user-select: none;
+
+ // :deep(.el-dropdown) {
+ // margin-top: -2px;
+ // }
+ .scripts_menu {
+ :deep(.el-dropdown-menu) {
+ min-width: 100px;
+ max-width: 300px;
+ }
}
+
.link_text {
font-size: var(--el-font-size-base);
- color: var(--el-color-primary);
+ color: var(--el-text-color-regular);
+ // color: var(--el-color-primary);
cursor: pointer;
margin-right: 15px;
+
+ .hidden_icon {
+ opacity: 0;
+ }
}
- .full_icon {
- cursor: pointer;
- margin-left: auto;
- &:hover .icon {
- color: var(--el-color-primary);
+
+ .left_menu {
+ display: flex;
+ align-items: center;
+ }
+
+ .right_overview {
+ display: flex;
+ align-items: center;
+ .switch_wrap {
+ display: flex;
+ align-items: center;
+ margin-right: 5px;
+ }
+ .full_icon {
+ cursor: pointer;
+
+ &:hover .icon {
+ color: var(--el-color-primary);
+ }
}
}
}
+
.info_box {
height: calc(100% - $terminalTopHeight);
overflow: auto;