Update Terminal.vue

This commit is contained in:
Baobhan Sith
2025-05-12 20:51:02 +08:00
parent b3a945cf3f
commit 3104367a31
+67 -22
View File
@@ -28,6 +28,7 @@ let terminal: Terminal | null = null;
let fitAddon: FitAddon | null = null; let fitAddon: FitAddon | null = null;
let searchAddon: SearchAddon | null = null; // *** 添加 searchAddon 变量 *** let searchAddon: SearchAddon | null = null; // *** 添加 searchAddon 变量 ***
let resizeObserver: ResizeObserver | null = null; let resizeObserver: ResizeObserver | null = null;
let observedElement: HTMLElement | null = null; // +++ Store the observed element +++
let debounceTimer: number | null = null; // 用于防抖的计时器 ID let debounceTimer: number | null = null; // 用于防抖的计时器 ID
let selectionListenerDisposable: IDisposable | null = null; // +++ 提升声明并添加类型 +++ let selectionListenerDisposable: IDisposable | null = null; // +++ 提升声明并添加类型 +++
// const fontSize = ref(14); // 移除本地字体大小状态,将由 store 管理 // const fontSize = ref(14); // 移除本地字体大小状态,将由 store 管理
@@ -169,12 +170,15 @@ onMounted(() => {
// 监听终端大小变化 (通过 ResizeObserver) - 主要处理浏览器窗口大小变化等 // 监听终端大小变化 (通过 ResizeObserver) - 主要处理浏览器窗口大小变化等
if (terminalRef.value) { if (terminalRef.value) {
const container = terminalRef.value; // 捕获引用 observedElement = terminalRef.value; // +++ Store the element to be observed +++
resizeObserver = new ResizeObserver((entries) => { resizeObserver = new ResizeObserver((entries) => {
// Only process if the terminal is active
if (!props.isActive || !terminal) return;
const entry = entries[0]; const entry = entries[0];
const { height, width } = entry.contentRect; // 获取宽度和高度 const { height, width } = entry.contentRect; // 获取宽度和高度
// console.log(`[Terminal ${props.sessionId}] ResizeObserver triggered. Size: ${width}x${height}, isActive: ${props.isActive}`); // console.log(`[Terminal ${props.sessionId}] ResizeObserver triggered. Size: ${width}x${height}, isActive: ${props.isActive}`);
if (height > 0 && width > 0 && terminal) { // 确保宽度和高度都有效,并且终端实例存在 if (height > 0 && width > 0) { // 确保宽度和高度都有效
try { try {
// *** 恢复:立即调用 fit() 来适应前端容器 *** // *** 恢复:立即调用 fit() 来适应前端容器 ***
fitAddon?.fit(); fitAddon?.fit();
@@ -185,26 +189,55 @@ onMounted(() => {
} }
} }
}); });
resizeObserver.observe(container); // Observe only if initially active (or becomes active later)
if (props.isActive) {
resizeObserver.observe(observedElement);
console.log(`[Terminal ${props.sessionId}] Initial observe.`);
}
} }
// 监听 isActive prop 的变化,当标签变为活动时立即 fit 并发送 resize // 监听 isActive prop 的变化
watch(() => props.isActive, (newValue) => { watch(() => props.isActive, (newValue, oldValue) => {
if (newValue && terminal && terminalRef.value) { console.log(`[Terminal ${props.sessionId}] isActive changed from ${oldValue} to ${newValue}`);
// 当标签变为活动时,等待 DOM 更新和短暂延时后执行 fit if (resizeObserver && observedElement) {
console.log(`[Terminal ${props.sessionId}] 标签变为活动状态,准备调整尺寸。`); // 日志改为中文 if (newValue) {
nextTick(() => { // --- Become Active ---
// 添加短暂延时,确保元素完全可见且渲染稳定 console.log(`[Terminal ${props.sessionId}] Becoming active. Observing element and fitting.`);
setTimeout(() => { // Start observing
// 再次检查终端实例是否存在且容器可见 try {
if (terminal && terminalRef.value && terminalRef.value.offsetHeight > 0) { resizeObserver.observe(observedElement);
console.log(`[Terminal ${props.sessionId}] 执行延时后的 fit 和 resize。`); // 日志改为中文 } catch (e) {
fitAndEmitResizeNow(terminal); console.warn(`[Terminal ${props.sessionId}] Error observing element:`, e);
} else { }
console.log(`[Terminal ${props.sessionId}] 延时后检查:终端不可见或已销毁,跳过 fit。`); // 日志改为中文 // Perform fit after a delay to ensure visibility and layout stability
} nextTick(() => {
}, 50); // 50ms 延时,可以根据需要调整 setTimeout(() => {
}); // Re-check if still active and terminal exists
if (props.isActive && terminal && terminalRef.value && terminalRef.value.offsetHeight > 0) {
console.log(`[Terminal ${props.sessionId}] Executing delayed fit and resize.`);
fitAndEmitResizeNow(terminal);
// Also ensure focus when becoming active
terminal.focus();
} else {
console.log(`[Terminal ${props.sessionId}] Skipped delayed fit (inactive, destroyed, or not visible).`);
}
}, 50); // 50ms delay
});
} else {
// --- Become Inactive ---
console.log(`[Terminal ${props.sessionId}] Becoming inactive. Unobserving element.`);
// Stop observing
try {
resizeObserver.unobserve(observedElement);
} catch (e) {
console.warn(`[Terminal ${props.sessionId}] Error unobserving element:`, e);
}
// Optionally clear debounce timer if resize was pending for this inactive terminal
// (debouncedEmitResize already checks isActive, so maybe not strictly needed)
// if (debounceTimer) { clearTimeout(debounceTimer); debounceTimer = null; }
}
} else {
console.warn(`[Terminal ${props.sessionId}] Cannot handle isActive change: resizeObserver or observedElement missing.`);
} }
}); });
@@ -448,10 +481,22 @@ onMounted(() => {
// 组件卸载前清理资源 // 组件卸载前清理资源
onBeforeUnmount(() => { onBeforeUnmount(() => {
if (resizeObserver && terminalRef.value) { // Ensure observer is cleaned up
resizeObserver.unobserve(terminalRef.value); if (resizeObserver && observedElement) {
try {
resizeObserver.unobserve(observedElement);
console.log(`[Terminal ${props.sessionId}] Unobserved on unmount.`);
} catch (e) {
console.warn(`[Terminal ${props.sessionId}] Error unobserving on unmount:`, e);
}
resizeObserver.disconnect(); // Fully disconnect observer
console.log(`[Terminal ${props.sessionId}] ResizeObserver disconnected.`);
} }
resizeObserver = null;
observedElement = null;
if (terminal) { if (terminal) {
console.log(`[Terminal ${props.sessionId}] Disposing terminal instance.`);
terminal.dispose(); terminal.dispose();
terminal = null; terminal = null;
} }