Fix: 修复终端标签切换时重连问题
将终端工作区提升为主布局常驻层,离开终端路由时只隐藏不卸载组件。 新增活动终端显隐状态跟踪,页面恢复时自动重新适配尺寸和聚焦。 改动范围: - frontend/src/layouts/MainLayout.vue - frontend/src/views/TerminalWorkspaceView.vue - frontend/src/components/TerminalWidget.vue
This commit is contained in:
@@ -1,14 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import { Terminal } from 'xterm'
|
||||
import { AttachAddon } from '@xterm/addon-attach'
|
||||
import { FitAddon } from '@xterm/addon-fit'
|
||||
import { useAuthStore } from '../stores/auth'
|
||||
import 'xterm/css/xterm.css'
|
||||
|
||||
const props = defineProps<{
|
||||
connectionId: number
|
||||
}>()
|
||||
<script setup lang="ts">
|
||||
import { nextTick, ref, onMounted, onUnmounted, watch } from 'vue'
|
||||
import { Terminal } from 'xterm'
|
||||
import { AttachAddon } from '@xterm/addon-attach'
|
||||
import { FitAddon } from '@xterm/addon-fit'
|
||||
import { useAuthStore } from '../stores/auth'
|
||||
import 'xterm/css/xterm.css'
|
||||
|
||||
const props = defineProps<{
|
||||
connectionId: number
|
||||
active?: boolean
|
||||
}>()
|
||||
|
||||
const containerRef = ref<HTMLElement | null>(null)
|
||||
const status = ref<'connecting' | 'connected' | 'error'>('connecting')
|
||||
@@ -16,8 +17,23 @@ const errorMessage = ref('')
|
||||
|
||||
let term: Terminal | null = null
|
||||
let fitAddon: FitAddon | null = null
|
||||
let ws: WebSocket | null = null
|
||||
let resizeObserver: ResizeObserver | null = null
|
||||
let ws: WebSocket | null = null
|
||||
let resizeObserver: ResizeObserver | null = null
|
||||
|
||||
function fitTerminal() {
|
||||
fitAddon?.fit()
|
||||
}
|
||||
|
||||
function focusTerminal() {
|
||||
term?.focus()
|
||||
}
|
||||
|
||||
function refreshTerminalLayout() {
|
||||
nextTick(() => {
|
||||
fitTerminal()
|
||||
focusTerminal()
|
||||
})
|
||||
}
|
||||
|
||||
function getWsUrl(): string {
|
||||
const authStore = useAuthStore()
|
||||
@@ -71,8 +87,8 @@ onMounted(() => {
|
||||
|
||||
fitAddon = new FitAddon()
|
||||
term.loadAddon(fitAddon)
|
||||
term.open(containerRef.value)
|
||||
fitAddon.fit()
|
||||
term.open(containerRef.value)
|
||||
fitTerminal()
|
||||
|
||||
try {
|
||||
ws = new WebSocket(getWsUrl())
|
||||
@@ -83,11 +99,11 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
ws.onopen = () => {
|
||||
status.value = 'connected'
|
||||
const attachAddon = new AttachAddon(ws!)
|
||||
term!.loadAddon(attachAddon)
|
||||
fitAddon?.fit()
|
||||
}
|
||||
status.value = 'connected'
|
||||
const attachAddon = new AttachAddon(ws!)
|
||||
term!.loadAddon(attachAddon)
|
||||
refreshTerminalLayout()
|
||||
}
|
||||
|
||||
ws.onerror = () => {
|
||||
if (status.value === 'connecting') {
|
||||
@@ -102,11 +118,21 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
resizeObserver = new ResizeObserver(() => {
|
||||
fitAddon?.fit()
|
||||
})
|
||||
resizeObserver.observe(containerRef.value)
|
||||
})
|
||||
resizeObserver = new ResizeObserver(() => {
|
||||
fitTerminal()
|
||||
})
|
||||
resizeObserver.observe(containerRef.value)
|
||||
|
||||
if (props.active !== false) {
|
||||
refreshTerminalLayout()
|
||||
}
|
||||
})
|
||||
|
||||
watch(() => props.active, (active) => {
|
||||
if (active) {
|
||||
refreshTerminalLayout()
|
||||
}
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
cleanup()
|
||||
|
||||
Reference in New Issue
Block a user