@@ -101,7 +101,9 @@ export async function handleSshConnect(
|
|||||||
|
|
||||||
stream.on('data', (data: Buffer) => {
|
stream.on('data', (data: Buffer) => {
|
||||||
if (ws.readyState === WebSocket.OPEN) {
|
if (ws.readyState === WebSocket.OPEN) {
|
||||||
ws.send(JSON.stringify({ type: 'ssh:output', payload: data.toString('base64'), encoding: 'base64' }));
|
// 确保数据以 UTF-8 编码转换为 Base64
|
||||||
|
const utf8Data = data.toString('utf8');
|
||||||
|
ws.send(JSON.stringify({ type: 'ssh:output', payload: Buffer.from(utf8Data, 'utf8').toString('base64'), encoding: 'base64' }));
|
||||||
}
|
}
|
||||||
// 如果会话被标记为待挂起,则将输出写入日志
|
// 如果会话被标记为待挂起,则将输出写入日志
|
||||||
const currentState = clientStates.get(newSessionId); // 获取最新的状态
|
const currentState = clientStates.get(newSessionId); // 获取最新的状态
|
||||||
@@ -114,7 +116,9 @@ export async function handleSshConnect(
|
|||||||
stream.stderr.on('data', (data: Buffer) => {
|
stream.stderr.on('data', (data: Buffer) => {
|
||||||
console.error(`SSH Stderr (会话: ${newSessionId}): ${data.toString('utf8').substring(0, 100)}...`);
|
console.error(`SSH Stderr (会话: ${newSessionId}): ${data.toString('utf8').substring(0, 100)}...`);
|
||||||
if (ws.readyState === WebSocket.OPEN) {
|
if (ws.readyState === WebSocket.OPEN) {
|
||||||
ws.send(JSON.stringify({ type: 'ssh:output', payload: data.toString('base64'), encoding: 'base64' }));
|
// 确保数据以 UTF-8 编码转换为 Base64
|
||||||
|
const utf8ErrData = data.toString('utf8');
|
||||||
|
ws.send(JSON.stringify({ type: 'ssh:output', payload: Buffer.from(utf8ErrData, 'utf8').toString('base64'), encoding: 'base64' }));
|
||||||
}
|
}
|
||||||
// 同样,如果会话被标记为待挂起,则将 stderr 输出写入日志
|
// 同样,如果会话被标记为待挂起,则将 stderr 输出写入日志
|
||||||
const currentState = clientStates.get(newSessionId);
|
const currentState = clientStates.get(newSessionId);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export function createSshTerminalManager(sessionId: string, wsDeps: SshTerminalD
|
|||||||
// Removed search result state refs
|
// Removed search result state refs
|
||||||
// const searchResultCount = ref(0);
|
// const searchResultCount = ref(0);
|
||||||
// const currentSearchResultIndex = ref(-1);
|
// const currentSearchResultIndex = ref(-1);
|
||||||
const terminalOutputBuffer = ref<string[]>([]); // 缓冲 WebSocket 消息直到终端准备好
|
const terminalOutputBuffer = ref<(string | Uint8Array)[]>([]); // 缓冲 WebSocket 消息直到终端准备好
|
||||||
const isSshConnected = ref(false); // 跟踪 SSH 连接状态
|
const isSshConnected = ref(false); // 跟踪 SSH 连接状态
|
||||||
|
|
||||||
// 辅助函数:获取终端消息文本
|
// 辅助函数:获取终端消息文本
|
||||||
@@ -71,10 +71,8 @@ export function createSshTerminalManager(sessionId: string, wsDeps: SshTerminalD
|
|||||||
// 2. 将此管理器内部缓冲的输出 (terminalOutputBuffer, 来自 ssh:output) 写入终端
|
// 2. 将此管理器内部缓冲的输出 (terminalOutputBuffer, 来自 ssh:output) 写入终端
|
||||||
if (terminalOutputBuffer.value.length > 0) {
|
if (terminalOutputBuffer.value.length > 0) {
|
||||||
terminalOutputBuffer.value.forEach(data => {
|
terminalOutputBuffer.value.forEach(data => {
|
||||||
// console.log(`[会话 ${sessionId}][SSH前端] handleTerminalReady: 正在写入内部缓冲数据 (前100字符):`, data.substring(0, 100));
|
|
||||||
term.write(data);
|
term.write(data);
|
||||||
});
|
});
|
||||||
// console.log(`[会话 ${sessionId}][SSH前端] handleTerminalReady: 内部缓冲区处理完成。`);
|
|
||||||
terminalOutputBuffer.value = []; // 清空内部缓冲区
|
terminalOutputBuffer.value = []; // 清空内部缓冲区
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,27 +118,8 @@ export function createSshTerminalManager(sessionId: string, wsDeps: SshTerminalD
|
|||||||
for (let i = 0; i < binaryString.length; i++) {
|
for (let i = 0; i < binaryString.length; i++) {
|
||||||
bytes[i] = binaryString.charCodeAt(i);
|
bytes[i] = binaryString.charCodeAt(i);
|
||||||
}
|
}
|
||||||
// 使用TextDecoder确保UTF-8正确解码
|
// 直接使用原始二进制数据作为 Uint8Array 写入终端,避免编码转换问题
|
||||||
outputData = new TextDecoder('utf-8').decode(bytes);
|
outputData = bytes;
|
||||||
|
|
||||||
// 如果输出仍然包含乱码字符,尝试其他编码
|
|
||||||
if (outputData.includes('�')) {
|
|
||||||
console.warn(`[会话 ${sessionId}][SSH终端模块] UTF-8解码后仍有乱码,尝试其他编码...`);
|
|
||||||
// 尝试不同的编码
|
|
||||||
const encodings = ['gbk', 'gb18030', 'big5', 'iso-8859-1'];
|
|
||||||
for (const encoding of encodings) {
|
|
||||||
try {
|
|
||||||
const decoded = new TextDecoder(encoding).decode(bytes);
|
|
||||||
if (!decoded.includes('�')) {
|
|
||||||
outputData = decoded;
|
|
||||||
console.log(`[会话 ${sessionId}][SSH终端模块] 成功使用${encoding}解码`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (encErr) {
|
|
||||||
// 忽略不支持的编码错误
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`[会话 ${sessionId}][SSH终端模块] Base64 解码失败:`, e, '原始数据:', message.payload);
|
console.error(`[会话 ${sessionId}][SSH终端模块] Base64 解码失败:`, e, '原始数据:', message.payload);
|
||||||
outputData = `\r\n[解码错误: ${e}]\r\n`; // 在终端显示解码错误
|
outputData = `\r\n[解码错误: ${e}]\r\n`; // 在终端显示解码错误
|
||||||
@@ -156,52 +135,8 @@ export function createSshTerminalManager(sessionId: string, wsDeps: SshTerminalD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 尝试过滤掉非标准的 OSC 184 序列 (更强的过滤)
|
// 由于直接使用原始二进制数据,不再需要过滤 OSC 184 序列
|
||||||
if (typeof outputData === 'string' && outputData.includes('\x1b]184;')) {
|
// 相关代码已移除
|
||||||
const originalLength = outputData.length;
|
|
||||||
let cleanedData = '';
|
|
||||||
let currentIndex = 0;
|
|
||||||
let startIndex = outputData.indexOf('\x1b]184;');
|
|
||||||
|
|
||||||
while (startIndex !== -1) {
|
|
||||||
// 添加 OSC 序列之前的部分
|
|
||||||
cleanedData += outputData.substring(currentIndex, startIndex);
|
|
||||||
|
|
||||||
// 查找 OSC 序列的结束符 (BEL 或 ST)
|
|
||||||
const belIndex = outputData.indexOf('\x07', startIndex);
|
|
||||||
const stIndex = outputData.indexOf('\x1b\\', startIndex);
|
|
||||||
|
|
||||||
let endIndex = -1;
|
|
||||||
if (belIndex !== -1 && stIndex !== -1) {
|
|
||||||
endIndex = Math.min(belIndex, stIndex);
|
|
||||||
} else if (belIndex !== -1) {
|
|
||||||
endIndex = belIndex;
|
|
||||||
} else if (stIndex !== -1) {
|
|
||||||
endIndex = stIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (endIndex !== -1) {
|
|
||||||
// 找到结束符,跳过整个 OSC 序列
|
|
||||||
currentIndex = endIndex + (outputData[endIndex] === '\x07' ? 1 : 2); // 跳过 BEL(1) 或 ST(2)
|
|
||||||
} else {
|
|
||||||
// 未找到结束符,可能序列不完整,保留 OSC 开始之后的部分
|
|
||||||
currentIndex = startIndex + 6; // 跳过 '\x1b]184;'
|
|
||||||
console.warn(`[会话 ${sessionId}][SSH终端模块] 未找到 OSC 184 的结束符,可能序列不完整。`);
|
|
||||||
break; // 停止处理,避免潜在问题
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查找下一个 OSC 184 序列
|
|
||||||
startIndex = outputData.indexOf('\x1b]184;', currentIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加剩余的部分
|
|
||||||
cleanedData += outputData.substring(currentIndex);
|
|
||||||
outputData = cleanedData;
|
|
||||||
|
|
||||||
if (outputData.length < originalLength) {
|
|
||||||
console.warn(`[会话 ${sessionId}][SSH终端模块] 过滤掉 OSC 184 序列。`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- 添加前端日志 ---
|
// --- 添加前端日志 ---
|
||||||
// console.log(`[会话 ${sessionId}][SSH前端] 收到 ssh:output 原始 payload (解码前):`, payload);
|
// console.log(`[会话 ${sessionId}][SSH前端] 收到 ssh:output 原始 payload (解码前):`, payload);
|
||||||
@@ -214,7 +149,6 @@ export function createSshTerminalManager(sessionId: string, wsDeps: SshTerminalD
|
|||||||
// console.log(`[会话 ${sessionId}][SSH前端] 写入完成。`);
|
// console.log(`[会话 ${sessionId}][SSH前端] 写入完成。`);
|
||||||
} else {
|
} else {
|
||||||
// 如果终端还没准备好,先缓冲输出
|
// 如果终端还没准备好,先缓冲输出
|
||||||
console.log(`[会话 ${sessionId}][SSH前端] 终端实例不存在,缓冲数据...`);
|
|
||||||
terminalOutputBuffer.value.push(outputData);
|
terminalOutputBuffer.value.push(outputData);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user