🆕 重构监控数据结构
This commit is contained in:
parent
5b2b776155
commit
655e9bc8af
@ -1,7 +1,10 @@
|
||||
const { readGroupList, writeGroupList, readHostList, writeHostList, randomStr } = require('../utils')
|
||||
|
||||
async function getGroupList({ res }) {
|
||||
const data = await readGroupList()
|
||||
let data = await readGroupList()
|
||||
data = data.map(item => {
|
||||
return { ...item, id: item._id }
|
||||
})
|
||||
data?.sort((a, b) => Number(b.index || 0) - Number(a.index || 0))
|
||||
res.success({ data })
|
||||
}
|
||||
|
@ -5,9 +5,11 @@ async function getHostList({ res }) {
|
||||
let data = await readHostList()
|
||||
data?.sort((a, b) => Number(b.index || 0) - Number(a.index || 0))
|
||||
data = data.map((item) => {
|
||||
const isConfig = Boolean(item.username && item.port && (item[item.authType]))
|
||||
const { username, port, authType, _id: id } = item
|
||||
const isConfig = Boolean(username && port && (item[authType]))
|
||||
return {
|
||||
...item,
|
||||
id,
|
||||
isConfig,
|
||||
password: '',
|
||||
privateKey: ''
|
||||
|
@ -25,6 +25,7 @@ app.config.globalProperties.$store = useStore()
|
||||
const serviceURI = import.meta.env.DEV ? process.env.serviceURI : location.origin
|
||||
app.config.globalProperties.$serviceURI = serviceURI
|
||||
app.config.globalProperties.$clientPort = process.env.clientPort || 22022
|
||||
app.config.globalProperties.$store.$patch({ serviceURI })
|
||||
console.warn('ISDEV: ', import.meta.env.DEV)
|
||||
console.warn('serviceURI: ', serviceURI)
|
||||
|
||||
|
@ -5,8 +5,6 @@ import { createRouter, createWebHistory } from 'vue-router'
|
||||
// import terminal from '@views/terminal/index.vue'
|
||||
// import test from '@views/test/index.vue'
|
||||
|
||||
const HostList = () => import('@views/list/index.vue')
|
||||
|
||||
const Login = () => import('@views/login/index.vue')
|
||||
const Container = () => import('@views/index.vue')
|
||||
const Server = () => import('@views/server/index.vue')
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { io } from 'socket.io-client'
|
||||
import { defineStore, acceptHMRUpdate } from 'pinia'
|
||||
import $api from '@/api'
|
||||
import ping from '@/utils/ping'
|
||||
@ -5,9 +6,11 @@ import ping from '@/utils/ping'
|
||||
const useStore = defineStore({
|
||||
id: 'global',
|
||||
state: () => ({
|
||||
serviceURI: null,
|
||||
hostList: [],
|
||||
groupList: [],
|
||||
sshList: [],
|
||||
HostStatusSocket: null,
|
||||
user: localStorage.getItem('user') || null,
|
||||
token: sessionStorage.getItem('token') || localStorage.getItem('token') || null,
|
||||
title: ''
|
||||
@ -31,18 +34,15 @@ const useStore = defineStore({
|
||||
this.$patch({ token: null })
|
||||
},
|
||||
async getMainData() {
|
||||
const { data: groupList } = await $api.getGroupList()
|
||||
const { data: hostList } = await $api.getHostList()
|
||||
const { data: sshList } = await $api.getSSHList()
|
||||
// console.log('hostList:', hostList)
|
||||
// console.log('groupList:', groupList)
|
||||
// console.log('sshList:', sshList)
|
||||
this.$patch({ groupList, hostList, sshList })
|
||||
await this.getGroupList()
|
||||
await this.getHostList()
|
||||
await this.getSSHList()
|
||||
},
|
||||
async getHostList() {
|
||||
const { data: hostList } = await $api.getHostList()
|
||||
// console.log('hostList:', hostList)
|
||||
this.$patch({ hostList })
|
||||
this.wsHostStatus()
|
||||
},
|
||||
async getGroupList() {
|
||||
const { data: groupList } = await $api.getGroupList()
|
||||
@ -67,11 +67,39 @@ const useStore = defineStore({
|
||||
// console.warn('Please tick \'Preserve Log\'')
|
||||
}, 1500)
|
||||
},
|
||||
async sortHostList(list) {
|
||||
let hostList = list.map(({ host }) => {
|
||||
return this.hostList.find(item => item.host === host)
|
||||
async wsHostStatus() {
|
||||
if (this.HostStatusSocket) this.HostStatusSocket.close()
|
||||
let socketInstance = io(this.serviceURI, {
|
||||
path: '/clients',
|
||||
forceNew: true,
|
||||
reconnectionDelay: 5000,
|
||||
reconnectionAttempts: 2
|
||||
})
|
||||
this.HostStatusSocket = socketInstance
|
||||
socketInstance.on('connect', () => {
|
||||
let flag = 5
|
||||
console.log('clients websocket 已连接: ', socketInstance.id)
|
||||
let token = this.token
|
||||
socketInstance.emit('init_clients_data', { token })
|
||||
socketInstance.on('clients_data', (data) => {
|
||||
if ((flag++ % 5) === 0) this.getHostPing()
|
||||
this.hostList.forEach(item => {
|
||||
const { host } = item
|
||||
if (data[host] === null) return { ...item }
|
||||
return Object.assign(item, data[host])
|
||||
})
|
||||
})
|
||||
socketInstance.on('token_verify_fail', (message) => {
|
||||
console.log('token 验证失败:', message)
|
||||
// $router.push('/login')
|
||||
})
|
||||
})
|
||||
socketInstance.on('disconnect', () => {
|
||||
console.error('clients websocket 连接断开')
|
||||
})
|
||||
socketInstance.on('connect_error', (message) => {
|
||||
console.error('clients websocket 连接出错: ', message)
|
||||
})
|
||||
this.$patch({ hostList })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -37,14 +37,12 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onBeforeUnmount, getCurrentInstance, computed, watch, onMounted } from 'vue'
|
||||
import { io } from 'socket.io-client'
|
||||
import { ref, onBeforeUnmount, getCurrentInstance, computed, watch } from 'vue'
|
||||
import HostCard from './components/host-card.vue'
|
||||
import HostForm from './components/host-form.vue'
|
||||
|
||||
const { proxy: { $store, $notification, $router, $serviceURI, $message } } = getCurrentInstance()
|
||||
const { proxy: { $store, $message } } = getCurrentInstance()
|
||||
|
||||
const socket = ref(null)
|
||||
const updateHostData = ref(null)
|
||||
const hostFormVisible = ref(false)
|
||||
const hiddenIp = ref(Number(localStorage.getItem('hiddenIp') || 0))
|
||||
@ -53,7 +51,6 @@ const activeGroup = ref([])
|
||||
const handleUpdateList = async () => {
|
||||
try {
|
||||
await $store.getHostList()
|
||||
connectIo()
|
||||
} catch (err) {
|
||||
$message.error('获取实例列表失败')
|
||||
console.error('获取实例列表失败: ', err)
|
||||
@ -98,60 +95,6 @@ watch(groupHostList, () => {
|
||||
deep: false
|
||||
})
|
||||
|
||||
let hostList = computed(() => $store.hostList)
|
||||
|
||||
const unwatchHost = watch(hostList, () => {
|
||||
connectIo()
|
||||
})
|
||||
|
||||
const connectIo = () => {
|
||||
if (socket.value) socket.value.close()
|
||||
if (typeof(unwatchHost) === 'function') unwatchHost()
|
||||
let socketInstance = io($serviceURI, {
|
||||
path: '/clients',
|
||||
forceNew: true,
|
||||
reconnectionDelay: 5000,
|
||||
reconnectionAttempts: 2
|
||||
})
|
||||
socket.value = socketInstance
|
||||
socketInstance.on('connect', () => {
|
||||
let flag = 5
|
||||
console.log('clients websocket 已连接: ', socketInstance.id)
|
||||
let token = $store.token
|
||||
socketInstance.emit('init_clients_data', { token })
|
||||
socketInstance.on('clients_data', (data) => {
|
||||
if ((flag++ % 5) === 0) $store.getHostPing()
|
||||
$store.hostList.forEach(item => {
|
||||
const { host } = item
|
||||
if (data[host] === null) return { ...item }
|
||||
return Object.assign(item, data[host])
|
||||
})
|
||||
})
|
||||
socketInstance.on('token_verify_fail', (message) => {
|
||||
$notification({
|
||||
title: '鉴权失败',
|
||||
message,
|
||||
type: 'error'
|
||||
})
|
||||
$router.push('/login')
|
||||
})
|
||||
})
|
||||
socketInstance.on('disconnect', () => {
|
||||
console.error('clients websocket 连接断开')
|
||||
})
|
||||
socketInstance.on('connect_error', (message) => {
|
||||
console.error('clients websocket 连接出错: ', message)
|
||||
})
|
||||
}
|
||||
|
||||
// onMounted(() => {
|
||||
// connectIo()
|
||||
// })
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (socket.value) socket.value.close()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
@ -11,7 +11,7 @@
|
||||
/>
|
||||
</div> -->
|
||||
</header>
|
||||
<el-divider class="first-divider" content-position="center">POSITION</el-divider>
|
||||
<el-divider class="first-divider" content-position="center">地理位置</el-divider>
|
||||
<el-descriptions
|
||||
class="margin-top"
|
||||
:column="1"
|
||||
@ -47,7 +47,7 @@
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-divider content-position="center">INDICATOR</el-divider>
|
||||
<el-divider content-position="center">实时监控</el-divider>
|
||||
<el-descriptions
|
||||
class="margin-top"
|
||||
:column="1"
|
||||
@ -118,7 +118,7 @@
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<el-divider content-position="center">INFORMATION</el-divider>
|
||||
<el-divider content-position="center">系统信息</el-divider>
|
||||
<el-descriptions
|
||||
class="margin-top"
|
||||
:column="1"
|
||||
@ -208,16 +208,12 @@
|
||||
import { ref, onMounted, onBeforeUnmount, computed, getCurrentInstance } from 'vue'
|
||||
import socketIo from 'socket.io-client'
|
||||
|
||||
const { proxy: { $router, $serviceURI, $message, $notification, $tools } } = getCurrentInstance()
|
||||
const { proxy: { $router, $store, $serviceURI, $message, $notification, $tools } } = getCurrentInstance()
|
||||
|
||||
const props = defineProps({
|
||||
token: {
|
||||
hostInfo: {
|
||||
required: true,
|
||||
type: String
|
||||
},
|
||||
host: {
|
||||
required: true,
|
||||
type: String
|
||||
type: Object
|
||||
},
|
||||
visible: {
|
||||
required: true,
|
||||
@ -233,11 +229,13 @@ const emit = defineEmits(['update:inputCommandStyle', 'connect-sftp', 'click-inp
|
||||
|
||||
const socket = ref(null)
|
||||
const name = ref('')
|
||||
const hostData = ref(null)
|
||||
const ping = ref(0)
|
||||
const pingTimer = ref(null)
|
||||
const sftpStatus = ref(false)
|
||||
|
||||
const token = computed(() => $store.token)
|
||||
const hostData = computed(() => props.hostInfo)
|
||||
const host = computed(() => hostData.value.host)
|
||||
const ipInfo = computed(() => hostData.value?.ipInfo || {})
|
||||
// const isError = computed(() => !Boolean(hostData.value?.osInfo))
|
||||
const cpuInfo = computed(() => hostData.value?.cpuInfo || {})
|
||||
@ -280,7 +278,6 @@ const clickInputCommand = () => {
|
||||
}
|
||||
|
||||
const connectIO = () => {
|
||||
const { host, token } = props
|
||||
socket.value = socketIo($serviceURI, {
|
||||
path: '/host-status',
|
||||
forceNew: true,
|
||||
@ -291,8 +288,8 @@ const connectIO = () => {
|
||||
|
||||
socket.value.on('connect', () => {
|
||||
console.log('/host-status socket已连接:', socket.value.id)
|
||||
socket.value.emit('init_host_data', { token, host })
|
||||
getHostPing()
|
||||
socket.value.emit('init_host_data', { token: token.value, host: props.host })
|
||||
// getHostPing()
|
||||
socket.value.on('host_data', (data) => {
|
||||
if (!data) return hostData.value = null
|
||||
hostData.value = data
|
||||
@ -343,9 +340,9 @@ const getHostPing = () => {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
name.value = $router.currentRoute.value.query.name || ''
|
||||
if (!props.host || !name.value) return $message.error('参数错误')
|
||||
connectIO()
|
||||
// name.value = $router.currentRoute.value.query.name || ''
|
||||
// if (!props.host || !name.value) return $message.error('参数错误')
|
||||
// connectIO()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
|
@ -12,7 +12,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
|
||||
import { ref, onMounted, computed, onBeforeUnmount, getCurrentInstance } from 'vue'
|
||||
import { Terminal } from 'xterm'
|
||||
import 'xterm/css/xterm.css'
|
||||
import { FitAddon } from 'xterm-addon-fit'
|
||||
@ -22,20 +22,12 @@ import { WebLinksAddon } from 'xterm-addon-web-links'
|
||||
import socketIo from 'socket.io-client'
|
||||
|
||||
const { io } = socketIo
|
||||
const { proxy: { $api, $serviceURI, $notification, $router, $messageBox } } = getCurrentInstance()
|
||||
const { proxy: { $api, $store, $serviceURI, $notification, $router, $messageBox } } = getCurrentInstance()
|
||||
|
||||
const props = defineProps({
|
||||
token: {
|
||||
required: true,
|
||||
type: String
|
||||
},
|
||||
host: {
|
||||
required: true,
|
||||
type: String
|
||||
},
|
||||
tabKey: {
|
||||
required: true,
|
||||
type: String
|
||||
}
|
||||
})
|
||||
|
||||
@ -48,7 +40,7 @@ const searchBar = ref(null)
|
||||
const isManual = ref(false)
|
||||
const terminalRefs = ref(null)
|
||||
|
||||
const tabKey = ref(props.tabKey)
|
||||
const token = computed(() => $store.token)
|
||||
|
||||
const getCommand = async () => {
|
||||
let { data } = await $api.getCommand(props.host)
|
||||
@ -56,7 +48,7 @@ const getCommand = async () => {
|
||||
}
|
||||
|
||||
const connectIO = () => {
|
||||
const { host, token } = props
|
||||
const { host } = props
|
||||
socket.value = io($serviceURI, {
|
||||
path: '/terminal',
|
||||
forceNew: false,
|
||||
@ -65,7 +57,7 @@ const connectIO = () => {
|
||||
|
||||
socket.value.on('connect', () => {
|
||||
console.log('/terminal socket已连接:', socket.value.id)
|
||||
socket.value.emit('create', { host, token })
|
||||
socket.value.emit('create', { host, token: token.value })
|
||||
socket.value.on('connect_success', () => {
|
||||
onData()
|
||||
socket.value.on('connect_terminal', () => {
|
||||
@ -241,7 +233,7 @@ const handleInputCommand = (command) => {
|
||||
|
||||
onMounted(async () => {
|
||||
createLocalTerminal()
|
||||
await getCommand()
|
||||
// await getCommand()
|
||||
connectIO()
|
||||
})
|
||||
|
||||
@ -255,8 +247,7 @@ defineExpose({
|
||||
focusTab,
|
||||
handleResize,
|
||||
handleInputCommand,
|
||||
handleClear,
|
||||
tabKey
|
||||
handleClear
|
||||
})
|
||||
</script>
|
||||
|
||||
|
@ -3,8 +3,7 @@
|
||||
<InfoSide
|
||||
ref="infoSideRef"
|
||||
v-model:show-input-command="showInputCommand"
|
||||
:token="token"
|
||||
:host="host"
|
||||
:host-info="curHost"
|
||||
:visible="visible"
|
||||
@connect-sftp="connectSftp"
|
||||
@click-input-command="clickInputCommand"
|
||||
@ -18,26 +17,23 @@
|
||||
<svg-icon name="icon-jiantou_zuoyouqiehuan" class="svg-icon" />
|
||||
</div>
|
||||
<el-tabs
|
||||
v-model="activeTab"
|
||||
v-model="activeTabIndex"
|
||||
type="border-card"
|
||||
addable
|
||||
tab-position="top"
|
||||
@tab-remove="removeTab"
|
||||
@tab-change="tabChange"
|
||||
@tab-add="tabAdd"
|
||||
>
|
||||
<el-tab-pane
|
||||
v-for="item in terminalTabs"
|
||||
:key="item.key"
|
||||
:label="item.title"
|
||||
:name="item.key"
|
||||
:closable="closable"
|
||||
v-for="(item, index) in terminalTabs"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:name="index"
|
||||
:closable="true"
|
||||
>
|
||||
<TerminalTab
|
||||
ref="terminalTabRefs"
|
||||
:token="token"
|
||||
:host="host"
|
||||
:tab-key="item.key"
|
||||
:host="item.host"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
@ -51,7 +47,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, computed, onBeforeMount,defineProps, getCurrentInstance } from 'vue'
|
||||
import { ref, reactive, defineEmits, computed, onBeforeMount,defineProps, getCurrentInstance, watch } from 'vue'
|
||||
import TerminalTab from './terminal-tab.vue'
|
||||
import InfoSide from './info-side.vue'
|
||||
import SftpFooter from './sftp-footer.vue'
|
||||
@ -60,16 +56,16 @@ import InputCommand from '@/components/input-command/index.vue'
|
||||
const { proxy: { $store, $router, $route, $nextTick } } = getCurrentInstance()
|
||||
|
||||
const props = defineProps({
|
||||
ternimalTabs: {
|
||||
terminalTabs: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const name = ref('')
|
||||
const host = ref('')
|
||||
const activeTab = ref('')
|
||||
const terminalTabs = reactive([])
|
||||
const emit = defineEmits(['closed', 'removeTab',])
|
||||
|
||||
const activeTabIndex = ref(0)
|
||||
// const terminalTabs = reactive([])
|
||||
const isFullScreen = ref(false)
|
||||
const timer = ref(null)
|
||||
const showSftp = ref(false)
|
||||
@ -77,21 +73,24 @@ const showInputCommand = ref(false)
|
||||
const visible = ref(true)
|
||||
const infoSideRef = ref(null)
|
||||
const terminalTabRefs = ref([])
|
||||
|
||||
const token = computed(() => $store.token)
|
||||
const ternimalTabs = computed(() => props.ternimalTabs)
|
||||
const terminalTabs = computed(() => props.terminalTabs)
|
||||
const curHost = computed(() => terminalTabs.value[activeTabIndex.value])
|
||||
|
||||
const closable = computed(() => terminalTabs.length > 1)
|
||||
// const closable = computed(() => terminalTabs.length > 1)
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (!token.value) return $router.push('login')
|
||||
let { host: routeHost, name: routeName } = $route.query
|
||||
name.value = routeName
|
||||
host.value = routeHost
|
||||
document.title = `${ document.title }-${ routeName }`
|
||||
let key = Date.now().toString()
|
||||
terminalTabs.push({ title: routeName, key })
|
||||
activeTab.value = key
|
||||
registryDbClick()
|
||||
watch(terminalTabs, () => {
|
||||
console.log('add tab:', terminalTabs.value)
|
||||
let len = terminalTabs.value.length
|
||||
if (len > 0) {
|
||||
activeTabIndex.value = len - 1
|
||||
// registryDbClick()
|
||||
// tabChange(terminalTabs.value[0].key)
|
||||
}
|
||||
}, {
|
||||
immediate: true,
|
||||
deep: false
|
||||
})
|
||||
|
||||
// const windowBeforeUnload = () => {
|
||||
@ -114,23 +113,23 @@ const tabAdd = () => {
|
||||
timer.value = setTimeout(() => {
|
||||
let title = name.value
|
||||
let key = Date.now().toString()
|
||||
terminalTabs.push({ title, key })
|
||||
activeTab.value = key
|
||||
terminalTabs.value.push({ title, key })
|
||||
activeTabIndex.value = key
|
||||
tabChange(key)
|
||||
registryDbClick()
|
||||
// registryDbClick()
|
||||
}, 200)
|
||||
}
|
||||
|
||||
const removeTab = (removeKey) => {
|
||||
let idx = terminalTabs.findIndex(({ key }) => removeKey === key)
|
||||
terminalTabs.splice(idx, 1)
|
||||
if (removeKey !== activeTab.value) return
|
||||
activeTab.value = terminalTabs[0].key
|
||||
const removeTab = (index) => {
|
||||
// terminalTabs.value.splice(index, 1)
|
||||
emit('removeTab', index)
|
||||
if (index !== activeTabIndex.value) return
|
||||
activeTabIndex.value = 0
|
||||
}
|
||||
|
||||
const tabChange = async (key) => {
|
||||
const tabChange = async (index) => {
|
||||
await $nextTick()
|
||||
const curTabTerminal = terminalTabRefs.value.find(({ tabKey }) => key === tabKey)
|
||||
const curTabTerminal = terminalTabRefs.value[index]
|
||||
curTabTerminal?.focusTab()
|
||||
}
|
||||
|
||||
@ -140,23 +139,20 @@ const handleFullScreen = () => {
|
||||
isFullScreen.value = !isFullScreen.value
|
||||
}
|
||||
|
||||
const registryDbClick = () => {
|
||||
$nextTick(() => {
|
||||
let tabItems = Array.from(document.getElementsByClassName('el-tabs__item'))
|
||||
tabItems.forEach(item => {
|
||||
item.removeEventListener('dblclick', handleDblclick)
|
||||
item.addEventListener('dblclick', handleDblclick)
|
||||
})
|
||||
})
|
||||
}
|
||||
// const registryDbClick = () => {
|
||||
// $nextTick(() => {
|
||||
// let tabItems = Array.from(document.getElementsByClassName('el-tabs__item'))
|
||||
// tabItems.forEach(item => {
|
||||
// item.removeEventListener('dblclick', handleDblclick)
|
||||
// item.addEventListener('dblclick', handleDblclick)
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
|
||||
const handleDblclick = (e) => {
|
||||
if (terminalTabs.length > 1) {
|
||||
let key = e.target.id.substring(4)
|
||||
// console.log('dblclick', key)
|
||||
removeTab(key)
|
||||
}
|
||||
}
|
||||
// const handleDblclick = (e) => {
|
||||
// let key = e.target.id.substring(4)
|
||||
// removeTab(key)
|
||||
// }
|
||||
|
||||
const handleVisibleSidebar = () => {
|
||||
visible.value = !visible.value
|
||||
@ -171,7 +167,7 @@ const resizeTerminal = () => {
|
||||
}
|
||||
|
||||
const handleInputCommand = async (command) => {
|
||||
const curTabTerminal = terminalTabRefs.value.find(({ tabKey }) => activeTab.value === tabKey)
|
||||
const curTabTerminal = terminalTabRefs.value.find(({ tabKey }) => activeTabIndex.value === tabKey)
|
||||
await $nextTick()
|
||||
curTabTerminal?.focusTab()
|
||||
curTabTerminal.handleInputCommand(`${ command }\n`)
|
||||
|
@ -37,7 +37,7 @@
|
||||
</el-table>
|
||||
</div>
|
||||
<div v-else>
|
||||
<Terminal :ternimal-tabs="ternimalTabs" />
|
||||
<Terminal :terminal-tabs="terminalTabs" @remove-tab="handleRemoveTab" />
|
||||
</div>
|
||||
<HostForm
|
||||
v-model:show="hostFormVisible"
|
||||
@ -49,17 +49,17 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onActivated, getCurrentInstance } from 'vue'
|
||||
import { ref, computed, onActivated, getCurrentInstance, reactive } from 'vue'
|
||||
import Terminal from './components/terminal.vue'
|
||||
import HostForm from '../server/components/host-form.vue'
|
||||
|
||||
const { proxy: { $store, $message } } = getCurrentInstance()
|
||||
|
||||
let ternimalTabs = ref([])
|
||||
let terminalTabs = reactive([])
|
||||
const hostFormVisible = ref(false)
|
||||
const updateHostData = ref(null)
|
||||
|
||||
let showLinkTips = computed(() => !Boolean(ternimalTabs.value.length))
|
||||
let showLinkTips = computed(() => !Boolean(terminalTabs.length))
|
||||
|
||||
let hostList = computed(() => $store.hostList)
|
||||
|
||||
@ -69,7 +69,7 @@ let isAllConfssh = computed(() => {
|
||||
|
||||
function linkTerminal(row) {
|
||||
// console.log(row)
|
||||
ternimalTabs.value.push(row)
|
||||
terminalTabs.push(row)
|
||||
}
|
||||
|
||||
function handleUpdateHost(row) {
|
||||
@ -77,6 +77,10 @@ function handleUpdateHost(row) {
|
||||
updateHostData.value = { ...row }
|
||||
}
|
||||
|
||||
function handleRemoveTab(index) {
|
||||
terminalTabs.splice(index, 1)
|
||||
}
|
||||
|
||||
const handleUpdateList = async () => {
|
||||
try {
|
||||
await $store.getHostList()
|
||||
|
Loading…
x
Reference in New Issue
Block a user