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