/** * @file terminal.js * @brief 命令终端页面 — 按钮面板 + 输入框 * @details 连接后自动获取命令列表,按模块分组生成按钮。 * 点击按钮将命令名填充到输入框,用户可继续输入子命令参数。 * 回车执行,输出显示在下方窗口。 */ var TermCommands = []; Router.register('#terminal', function(c) { c.innerHTML = '
' + '
' + I18n.t('term.title') + '
' + '
' + '
' + '
' + (I18n.t('term.loading') || '正在加载命令列表...') + '
' + '
' + '
' + I18n.t('term.welcome') + '
' + '
' + ' RTU>' + ' ' + '
' + '
' + '
'; if (TermCommands.length > 0) { renderCmdPanels(TermCommands); } else { WsClient.send({ type: 'get_cmds' }); } }); /* ---- 命令分组 ---- */ function groupCommands(cmds) { var groups = {}; for (var i = 0; i < cmds.length; i++) { var mod = 'other'; var name = cmds[i].name; if (name.indexOf('datacenter') === 0) mod = 'datacenter'; else if (name.indexOf('iec') === 0) mod = 'iec'; else if (name.indexOf('plc') === 0) mod = 'plc'; else if (name.indexOf('self_ptl') === 0) mod = 'self_ptl'; else if (name.indexOf('modbus_m') === 0) mod = 'modbus_m'; else if (name === 'help' || name === 'version') mod = 'system'; if (!groups[mod]) groups[mod] = []; groups[mod].push(cmds[i]); } return groups; } var groupMeta = { 'datacenter': { icon: '📊', label: '数据中心' }, 'iec': { icon: '⚡', label: 'IEC-104' }, 'plc': { icon: '🎛', label: 'PLC 逻辑' }, 'self_ptl': { icon: '🔗', label: '自协议' }, 'modbus_m': { icon: '📡', label: 'Modbus 主站' }, 'system': { icon: '⚙', label: '系统' }, 'other': { icon: '📦', label: '其他' }, }; /* ---- 渲染命令面板 ---- */ function renderCmdPanels(cmds) { TermCommands = cmds; var panels = document.getElementById('cmd-panels'); if (!panels) return; var groups = groupCommands(cmds); var html = ''; for (var mod in groups) { var meta = groupMeta[mod] || { icon: '', label: mod }; html += '
'; html += '
' + meta.icon + ' ' + meta.label + '
'; html += '
'; for (var j = 0; j < groups[mod].length; j++) { var cmd = groups[mod][j]; html += ''; } html += '
'; } panels.innerHTML = html; } /* ---- 填充命令到输入框 ---- */ function fillTermCmd(cmd) { var input = document.getElementById('term-input'); if (!input) return; input.value = cmd + ' '; input.focus(); } /* ---- 回车执行 ---- */ function handleTermKey(e) { if (e.key !== 'Enter') return; var input = document.getElementById('term-input'); var out = document.getElementById('term-out'); if (!input || !out) return; var cmd = input.value.trim(); if (!cmd) return; /* 本地清屏 */ if (cmd === 'clear') { out.textContent = ''; input.value = ''; return; } /* 显示已执行命令 */ out.textContent += '\n> ' + cmd + '\n'; out.scrollTop = out.scrollHeight; /* 发送到后端 */ WsClient.send({ type: 'cmd', data: cmd }); input.value = ''; } /* ---- WebSocket 二进制消息追加到输出窗口 ---- */ function termOnBinary(text) { var out = document.getElementById('term-out'); if (!out) return; out.textContent += text; out.scrollTop = out.scrollHeight; }