mirror of
https://github.com/hotwa/luci-app-openclaw.git
synced 2026-03-30 20:25:44 +00:00
123 lines
3.9 KiB
HTML
123 lines
3.9 KiB
HTML
<%#
|
||
luci-app-openclaw — 终端配置页面 (简洁版)
|
||
-%>
|
||
<%+header%>
|
||
|
||
<%
|
||
local uci = require "luci.model.uci".cursor()
|
||
local pty_port = uci:get("openclaw", "main", "pty_port") or "18793"
|
||
%>
|
||
|
||
<style type="text/css">
|
||
.oc-page-header { margin: 0 0 16px 0; }
|
||
.oc-page-header h2 { font-size: 18px; font-weight: 600; color: #333; margin: 0 0 6px 0; }
|
||
.oc-page-header p { font-size: 13px; color: #666; margin: 0; line-height: 1.6; }
|
||
|
||
.oc-terminal-wrap {
|
||
border: 2px solid #2d333b;
|
||
border-radius: 8px;
|
||
overflow: hidden;
|
||
background: #1a1b26;
|
||
}
|
||
|
||
#oc-terminal-iframe { width: 100%; height: 600px; border: none; display: block; }
|
||
|
||
.oc-terminal-loading {
|
||
display: flex; align-items: center; justify-content: center;
|
||
height: 200px; color: #7aa2f7; font-size: 14px; background: #1a1b26;
|
||
}
|
||
</style>
|
||
|
||
<div class="oc-page-header">
|
||
<h2>⚙️ 终端配置</h2>
|
||
<p>通过内嵌的交互式终端 (oc-config) 进行 OpenClaw 的完整配置管理。支持 AI 模型配置、消息渠道设置(QQ、Telegram、Discord 等)、健康检查等。</p>
|
||
</div>
|
||
|
||
<div class="oc-terminal-wrap">
|
||
<div id="oc-terminal-container">
|
||
<div class="oc-terminal-loading" id="oc-terminal-loading">
|
||
⏳ 正在连接配置终端...
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script type="text/javascript">
|
||
//<![CDATA[
|
||
(function() {
|
||
var ptyPort = '<%=pty_port%>';
|
||
var statusUrl = '<%=luci.dispatcher.build_url("admin", "services", "openclaw", "status_api")%>';
|
||
var tokenUrl = '<%=luci.dispatcher.build_url("admin", "services", "openclaw", "get_token")%>';
|
||
var container = document.getElementById('oc-terminal-container');
|
||
var loading = document.getElementById('oc-terminal-loading');
|
||
var ptyToken = '';
|
||
|
||
function checkAndLoadTerminal() {
|
||
// 先获取 PTY token
|
||
(new XHR()).get(tokenUrl, null, function(tx) {
|
||
try {
|
||
var td = JSON.parse(tx.responseText);
|
||
ptyToken = td.pty_token || '';
|
||
} catch(e) {}
|
||
|
||
(new XHR()).get(statusUrl, null, function(x) {
|
||
try {
|
||
var d = JSON.parse(x.responseText);
|
||
if (d.pty_running) {
|
||
showIframe();
|
||
} else {
|
||
loading.innerHTML = '❌ 配置终端未运行<br/>' +
|
||
'<span style="font-size:12px;color:#999;">请先在「基本设置」中启用并启动服务。</span>';
|
||
}
|
||
} catch(e) {
|
||
loading.textContent = '检查终端状态失败';
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
function showIframe() {
|
||
var proto = window.location.protocol;
|
||
var host = window.location.hostname;
|
||
var url = proto + '//' + host + ':' + ptyPort + '/';
|
||
if (ptyToken) url += '?pty_token=' + encodeURIComponent(ptyToken);
|
||
|
||
loading.style.display = 'none';
|
||
|
||
var iframe = document.createElement('iframe');
|
||
iframe.id = 'oc-terminal-iframe';
|
||
iframe.src = url;
|
||
iframe.setAttribute('allowfullscreen', 'true');
|
||
iframe.setAttribute('allow', 'clipboard-read; clipboard-write');
|
||
// 防止 LuCI 父页面键盘事件干扰 iframe 内的终端输入
|
||
iframe.addEventListener('load', function() {
|
||
try { iframe.contentWindow.focus(); } catch(e) {}
|
||
});
|
||
container.appendChild(iframe);
|
||
// 点击 iframe 区域时确保 focus 在 iframe 内
|
||
container.addEventListener('click', function() {
|
||
try { iframe.contentWindow.focus(); } catch(e) {}
|
||
});
|
||
|
||
// 当 iframe 获得焦点时,阻止 LuCI 父页面的键盘事件处理
|
||
// 防止按键(如 Enter/数字键)触发 LuCI 的导航或表单提交
|
||
var termWrap = document.querySelector('.oc-terminal-wrap');
|
||
if (termWrap) {
|
||
termWrap.addEventListener('keydown', function(e) { e.stopPropagation(); }, true);
|
||
termWrap.addEventListener('keypress', function(e) { e.stopPropagation(); }, true);
|
||
termWrap.addEventListener('keyup', function(e) { e.stopPropagation(); }, true);
|
||
}
|
||
|
||
// 停止 LuCI 的 XHR.poll (如果存在),防止 session 超时检测导致页面跳转
|
||
// LuCI 的 footer.htm 可能启动了 uci.changes 轮询
|
||
if (window.XHR && XHR.halt) {
|
||
try { XHR.halt(); } catch(e) {}
|
||
}
|
||
}
|
||
|
||
checkAndLoadTerminal();
|
||
})();
|
||
//]]>
|
||
</script>
|
||
|
||
<%+footer%>
|