release: v1.0.0 — LuCI 管理界面、一键安装、12+ AI 模型提供商

This commit is contained in:
10000ge10000
2026-03-02 16:23:52 +08:00
commit c1c3151a9f
28 changed files with 5260 additions and 0 deletions

View File

@@ -0,0 +1,121 @@
<%#
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-info-box {
padding: 12px 16px;
margin-bottom: 16px;
background: #f6f8fa;
border: 1px solid #e1e4e8;
border-left: 4px solid #4a90d9;
border-radius: 4px;
font-size: 13px;
line-height: 1.7;
color: #555;
}
.oc-info-box ul { margin: 6px 0 0 0; padding-left: 18px; list-style: none; }
.oc-info-box li { margin-bottom: 2px; }
.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 模型配置、消息渠道设置、健康检查等。</p>
</div>
<div class="oc-info-box">
<strong>💡 菜单功能说明:</strong>
<ul>
<li><strong>1)</strong> 查看当前配置 &nbsp; <strong>2)</strong> 配置 AI 模型提供商 &nbsp; <strong>3)</strong> 设定当前活跃模型</li>
<li><strong>4)</strong> 配置消息渠道 &nbsp; <strong>5)</strong> Telegram 配对向导 &nbsp; <strong>6)</strong> 健康检查 / 诊断</li>
<li><strong>7)</strong> 重启网关 &nbsp; <strong>8)</strong> 查看/编辑原始配置 &nbsp; <strong>9)</strong> 恢复默认配置</li>
</ul>
</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');
container.appendChild(iframe);
}
checkAndLoadTerminal();
})();
//]]>
</script>
<%+footer%>

View File

@@ -0,0 +1,168 @@
<%#
luci-app-openclaw — Web 控制台页面
嵌入 OpenClaw 官方 Web UI用户可在此配置模型/渠道并直接对话
-%>
<%+header%>
<%
local uci = require "luci.model.uci".cursor()
local port = uci:get("openclaw", "main", "port") or "18789"
%>
<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-console-info {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 16px;
margin-bottom: 16px;
background: #f6f8fa;
border: 1px solid #e1e4e8;
border-radius: 6px;
font-size: 13px;
color: #555;
flex-wrap: wrap;
}
.oc-console-info .label { color: #888; }
.oc-console-info .value { font-family: monospace; color: #333; font-weight: 500; }
.oc-console-info .sep { color: #ddd; }
.oc-console-info .btn-open {
margin-left: auto;
padding: 4px 14px;
background: #4a90d9;
color: #fff;
border: none;
border-radius: 4px;
font-size: 12px;
cursor: pointer;
text-decoration: none;
}
.oc-console-info .btn-open:hover { background: #357abd; }
.oc-console-wrap {
border: 2px solid #e0e0e0;
border-radius: 8px;
overflow: hidden;
background: #fff;
box-shadow: 0 1px 4px rgba(0,0,0,0.06);
}
#oc-console-iframe { width: 100%; height: 700px; border: none; display: block; }
.oc-console-loading {
display: flex; flex-direction: column; align-items: center; justify-content: center;
height: 300px; color: #666; font-size: 14px; background: #fafafa;
}
.oc-console-loading .spinner {
width: 32px; height: 32px; border: 3px solid #e0e0e0; border-top: 3px solid #4a90d9;
border-radius: 50%; animation: oc-spin .8s linear infinite; margin-bottom: 12px;
}
@keyframes oc-spin { to { transform: rotate(360deg); } }
</style>
<div class="oc-page-header">
<h2>🖥️ Web 控制台</h2>
<p>OpenClaw 官方 Web 管理界面 — 在这里可以配置 AI 模型、消息渠道,直接与 AI 进行对话,以及管理所有功能。</p>
</div>
<div class="oc-console-info">
<span class="label">网关地址:</span>
<span class="value" id="oc-console-addr">-</span>
<span class="sep">|</span>
<span class="label">状态:</span>
<span id="oc-console-status-text">检查中...</span>
<a id="oc-console-open-btn" class="btn-open" href="#" target="_blank" rel="noopener" style="display:none;">
↗ 新窗口打开
</a>
</div>
<div class="oc-console-wrap">
<div id="oc-console-container">
<div class="oc-console-loading" id="oc-console-loading">
<div class="spinner"></div>
<span>正在连接 OpenClaw 控制台...</span>
</div>
</div>
</div>
<script type="text/javascript">
//<![CDATA[
(function() {
var gwPort = '<%=port%>';
var gwToken = '';
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-console-container');
var loading = document.getElementById('oc-console-loading');
var addrEl = document.getElementById('oc-console-addr');
var statusTextEl = document.getElementById('oc-console-status-text');
var openBtn = document.getElementById('oc-console-open-btn');
function getConsoleUrl() {
var proto = window.location.protocol;
var host = window.location.hostname;
var url = proto + '//' + host + ':' + gwPort + '/';
if (gwToken) url += '#token=' + encodeURIComponent(gwToken);
return url;
}
function checkAndLoad() {
addrEl.textContent = window.location.hostname + ':' + gwPort;
// 先获取 token再检查状态
(new XHR()).get(tokenUrl, null, function(tx) {
try {
var td = JSON.parse(tx.responseText);
gwToken = td.token || '';
} catch(e) {}
(new XHR()).get(statusUrl, null, function(x) {
try {
var d = JSON.parse(x.responseText);
var url = getConsoleUrl();
if (d.gateway_running) {
statusTextEl.innerHTML = '<span style="color:#1a7f37;">● 网关运行中</span>';
openBtn.href = url;
openBtn.style.display = '';
showIframe(url);
} else {
statusTextEl.innerHTML = '<span style="color:#cf222e;">● 网关未运行</span>';
openBtn.style.display = 'none';
loading.innerHTML = '<div style="text-align:center;color:#666;">' +
'<div style="font-size:40px;margin-bottom:12px;">🧠</div>' +
'<div style="font-size:15px;margin-bottom:6px;">OpenClaw 网关未运行</div>' +
'<div style="font-size:12px;color:#999;">请先在「基本设置」页面启用服务并启动。</div>' +
'</div>';
}
} catch(e) {
statusTextEl.textContent = '查询失败';
}
});
});
}
function showIframe(url) {
loading.style.display = 'none';
var existing = document.getElementById('oc-console-iframe');
if (existing) return;
var iframe = document.createElement('iframe');
iframe.id = 'oc-console-iframe';
iframe.src = url;
iframe.style.width = '100%';
iframe.style.height = '700px';
iframe.style.border = 'none';
iframe.setAttribute('allowfullscreen', 'true');
container.appendChild(iframe);
}
checkAndLoad();
})();
//]]>
</script>
<%+footer%>

View File

@@ -0,0 +1,138 @@
<%#
luci-app-openclaw — 运行状态面板 (全面汉化 + 界面优化)
-%>
<style type="text/css">
#oc-status-panel {
margin: 0 0 20px 0;
padding: 0;
border: 1px solid #e0e0e0;
border-radius: 8px;
background: #fff;
overflow: hidden;
box-shadow: 0 1px 4px rgba(0,0,0,0.06);
}
#oc-status-panel .panel-title {
background: linear-gradient(135deg, #4a90d9, #357abd);
color: #fff;
padding: 10px 16px;
font-size: 14px;
font-weight: 600;
letter-spacing: 0.5px;
}
#oc-status-panel .panel-body {
padding: 0;
}
#oc-status-panel table {
width: 100%;
border-collapse: collapse;
}
#oc-status-panel td {
padding: 8px 16px;
border-bottom: 1px solid #f2f2f2;
font-size: 13px;
vertical-align: middle;
}
#oc-status-panel tr:last-child td {
border-bottom: none;
}
#oc-status-panel td:first-child {
width: 120px;
color: #888;
font-weight: 500;
white-space: nowrap;
}
#oc-status-panel td:last-child {
color: #333;
}
.oc-badge {
display: inline-block;
padding: 2px 12px;
border-radius: 12px;
font-size: 12px;
font-weight: 600;
}
.oc-badge-running { background: #e6f7e9; color: #1a7f37; }
.oc-badge-stopped { background: #ffeef0; color: #cf222e; }
.oc-badge-disabled { background: #f0f0f0; color: #656d76; }
.oc-badge-unknown { background: #fff8c5; color: #9a6700; }
.oc-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; vertical-align: middle; }
.oc-dot-green { background: #1a7f37; }
.oc-dot-red { background: #cf222e; }
.oc-dot-gray { background: #999; }
</style>
<div id="oc-status-panel">
<div class="panel-title">🦞 OpenClaw 服务状态</div>
<div class="panel-body">
<table>
<tr><td>运行状态</td><td id="oc-st-status"><span class="oc-badge oc-badge-unknown">加载中...</span></td></tr>
<tr><td>网关服务</td><td id="oc-st-gateway">-</td></tr>
<tr><td>配置终端</td><td id="oc-st-pty">-</td></tr>
<tr><td>进程 PID</td><td id="oc-st-pid">-</td></tr>
<tr><td>内存占用</td><td id="oc-st-mem">-</td></tr>
<tr><td>运行时间</td><td id="oc-st-uptime">-</td></tr>
<tr><td>Node.js</td><td id="oc-st-node">-</td></tr>
<tr><td>OpenClaw</td><td id="oc-st-ocver">-</td></tr>
</table>
</div>
</div>
<script type="text/javascript">
//<![CDATA[
(function() {
var statusUrl = '<%=luci.dispatcher.build_url("admin", "services", "openclaw", "status_api")%>';
function updateStatus() {
(new XHR()).get(statusUrl, null, function(x) {
try {
var d = JSON.parse(x.responseText);
var stEl = document.getElementById('oc-st-status');
if (d.enabled !== '1') {
stEl.innerHTML = '<span class="oc-badge oc-badge-disabled">已禁用</span>';
} else if (d.gateway_running) {
stEl.innerHTML = '<span class="oc-badge oc-badge-running">运行中</span>';
} else {
stEl.innerHTML = '<span class="oc-badge oc-badge-stopped">已停止</span>';
}
var gwEl = document.getElementById('oc-st-gateway');
if (d.gateway_running) {
gwEl.innerHTML = '<span class="oc-dot oc-dot-green"></span>监听中 :' + d.port;
} else {
gwEl.innerHTML = '<span class="oc-dot oc-dot-red"></span>未监听';
}
var ptyEl = document.getElementById('oc-st-pty');
if (d.pty_running) {
ptyEl.innerHTML = '<span class="oc-dot oc-dot-green"></span>监听中 :' + d.pty_port;
} else {
ptyEl.innerHTML = '<span class="oc-dot oc-dot-gray"></span>未监听';
}
document.getElementById('oc-st-pid').textContent = d.pid || '-';
var memEl = document.getElementById('oc-st-mem');
if (d.memory_kb > 0) {
var mb = (d.memory_kb / 1024).toFixed(1);
memEl.textContent = mb + ' MB';
} else {
memEl.textContent = '-';
}
document.getElementById('oc-st-uptime').textContent = d.uptime || '-';
document.getElementById('oc-st-node').textContent = d.node_version || '未安装';
document.getElementById('oc-st-ocver').textContent = d.openclaw_version || '未安装';
} catch(e) {
document.getElementById('oc-st-status').innerHTML = '<span class="oc-badge oc-badge-unknown">查询失败</span>';
}
});
}
updateStatus();
setInterval(updateStatus, 5000);
})();
//]]>
</script>