Files
u-claw/portable/lib/loading.html

198 lines
6.3 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>U-Claw 正在启动…</title>
<!--
启动首屏(移植自 v2 u-clawx 4.0 的 splash 思路)。
双击启动脚本后立刻打开本页,给用户即时反馈,消除"黑窗假死"体感。
本页每秒自查 gateway 是否就绪fetch /ready
就绪后【不自动跳转】,而是停在选择页,给两个大按钮:
🚀 进入 Dashboard开始聊天
⚙️ 配置 / 改模型(打开配置中心)
让用户自己决定去聊天还是改配置——避免"配过模型就被冲进 Dashboard、想改配置还得自己翻标签"。
端口通过 URL 查询参数传入loading.html?port=18789
(启动脚本打开时拼好。默认 18789。
-->
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { height: 100%; }
body {
font-family: -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
}
.box {
text-align: center;
max-width: 460px;
padding: 40px;
}
.logo { font-size: 64px; line-height: 1; margin-bottom: 18px; }
h1 { font-size: 1.7em; font-weight: 600; margin-bottom: 8px; }
.tip { opacity: .85; font-size: 1.02em; line-height: 1.6; margin-bottom: 28px; }
.spinner {
width: 46px; height: 46px;
margin: 0 auto 24px;
border: 4px solid rgba(255,255,255,.25);
border-top-color: #fff;
border-radius: 50%;
animation: spin .9s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.bar {
height: 6px; width: 100%;
background: rgba(255,255,255,.2);
border-radius: 999px;
overflow: hidden;
margin-bottom: 14px;
}
.bar > i {
display: block; height: 100%; width: 30%;
background: #fff; border-radius: 999px;
animation: slide 1.6s ease-in-out infinite;
}
@keyframes slide {
0% { margin-left: -30%; }
100% { margin-left: 100%; }
}
.status { font-size: .95em; opacity: .9; min-height: 1.4em; }
.elapsed { font-size: .82em; opacity: .6; margin-top: 6px; }
.note {
margin-top: 30px; font-size: .82em; opacity: .65; line-height: 1.6;
}
a.manual { color: #fff; text-decoration: underline; opacity: .9; }
/* —— 就绪后的选择页 —— */
.ready-wrap { display: none; }
body.ready .loading-wrap { display: none; }
body.ready .ready-wrap { display: block; }
.actions {
display: flex;
flex-direction: column;
gap: 16px;
margin-top: 26px;
}
.btn {
display: block;
text-decoration: none;
color: #fff;
border-radius: 14px;
padding: 20px 22px;
font-size: 1.15em;
font-weight: 600;
line-height: 1.35;
cursor: pointer;
border: 2px solid rgba(255,255,255,.35);
background: rgba(255,255,255,.12);
transition: transform .12s ease, background .2s ease, box-shadow .2s ease;
}
.btn:hover { transform: translateY(-2px); background: rgba(255,255,255,.22); box-shadow: 0 8px 24px rgba(0,0,0,.18); }
.btn:active { transform: translateY(0); }
.btn .sub { display: block; font-size: .68em; font-weight: 400; opacity: .8; margin-top: 4px; }
.btn-primary { background: #ff7a45; border-color: #ff7a45; }
.btn-primary:hover { background: #ff6a30; }
.foot { margin-top: 24px; font-size: .82em; opacity: .65; line-height: 1.6; }
</style>
</head>
<body>
<div class="box">
<!-- 启动中 -->
<div class="loading-wrap">
<div class="logo">🦞</div>
<h1>U-Claw 正在启动</h1>
<div class="tip">首次从 U 盘启动需要展开内置组件,<br>稍等片刻,就绪后会提示你下一步。</div>
<div class="spinner"></div>
<div class="bar"><i></i></div>
<div class="status" id="status">正在等待 OpenClaw 网关…</div>
<div class="elapsed" id="elapsed"></div>
<div class="note">
慢 U 盘首次启动通常 3090 秒。<br>
如果迟迟没反应,可先打开
<a class="manual" id="manual" href="#">配置中心</a>
</div>
</div>
<!-- 就绪后:让用户自己选 -->
<div class="ready-wrap">
<div class="logo">🦞</div>
<h1>U-Claw 已就绪</h1>
<div class="tip">选择下一步 — 直接开始聊天,或先去配置模型和渠道。</div>
<div class="actions">
<a class="btn btn-primary" id="goDash">🚀 进入 Dashboard
<span class="sub">开始和 AI 聊天</span>
</a>
<a class="btn" id="goConfig">⚙️ 配置 / 改模型
<span class="sub">填写或更换模型 Key、充值、连接微信等渠道</span>
</a>
</div>
<div class="foot">没配过模型或余额不足?先点「配置 / 改模型」处理 Key 或充值。</div>
</div>
</div>
<script>
(function () {
var params = new URLSearchParams(location.search);
var port = parseInt(params.get('port'), 10) || 18789;
var token = params.get('token') || 'uclaw';
var base = 'http://127.0.0.1:' + port;
var dashboard = base + '/#token=' + encodeURIComponent(token);
var configCenter = 'http://127.0.0.1:18788/';
document.getElementById('manual').href = configCenter;
document.getElementById('goDash').href = dashboard;
document.getElementById('goConfig').href = configCenter;
var startedAt = Date.now();
var ready = false;
function fmt(ms) {
var s = Math.floor(ms / 1000);
return '已等待 ' + s + ' 秒';
}
function tickElapsed() {
if (ready) return;
document.getElementById('elapsed').textContent = fmt(Date.now() - startedAt);
}
setInterval(tickElapsed, 1000);
tickElapsed();
function showChoice() {
if (ready) return;
ready = true;
document.body.classList.add('ready');
}
function poll() {
if (ready) return;
// /ready 就绪即显示选择页。no-cors 下拿不到 status但 fetch 成功 resolve 就说明端口活了。
fetch(base + '/ready', { mode: 'no-cors', cache: 'no-store' })
.then(function () { showChoice(); })
.catch(function () {
// 端口还没起,继续等
setTimeout(poll, 1000);
});
}
poll();
// 兜底5 分钟还没起来,提示去控制台
setTimeout(function () {
if (!ready) {
document.getElementById('status').innerHTML =
'启动较慢,可先打开 <a class="manual" href="' + configCenter + '">配置中心</a> 检查';
}
}, 300000);
})();
</script>
</body>
</html>