/** * 初始设置页面 — openclaw 未安装时的引导 * 自动检测环境 → 版本选择 → 一键安装 → 自动跳转 */ import { api } from '../lib/tauri-api.js' import { showUpgradeModal } from '../components/modal.js' import { toast } from '../components/toast.js' import { setUpgrading, isMacPlatform } from '../lib/app-state.js' import { diagnoseInstallError } from '../lib/error-diagnosis.js' export async function render() { const page = document.createElement('div') page.className = 'page' page.innerHTML = `
ClawPanel

欢迎使用 ClawPanel

OpenClaw AI Agent 框架的桌面管理面板

` page.querySelector('#btn-recheck').addEventListener('click', () => runDetect(page)) runDetect(page) return page } async function runDetect(page) { const stepsEl = page.querySelector('#setup-steps') stepsEl.innerHTML = `
` // 并行检测 Node.js、OpenClaw CLI、配置文件 const [nodeRes, clawRes, configRes] = await Promise.allSettled([ api.checkNode(), api.getServicesStatus(), api.checkInstallation(), ]) const node = nodeRes.status === 'fulfilled' ? nodeRes.value : { installed: false } const cliOk = clawRes.status === 'fulfilled' && clawRes.value?.length > 0 && clawRes.value[0]?.cli_installed !== false const config = configRes.status === 'fulfilled' ? configRes.value : { installed: false } renderSteps(page, { node, cliOk, config }) } function stepIcon(ok) { const color = ok ? 'var(--success)' : 'var(--text-tertiary)' return `${ok ? '✓' : '✗'}` } function renderSteps(page, { node, cliOk, config }) { const stepsEl = page.querySelector('#setup-steps') const nodeOk = node.installed const allOk = nodeOk && cliOk && config.installed let html = '' // 第一步:Node.js html += `
${stepIcon(nodeOk)} Node.js 环境
${nodeOk ? `

已安装 ${node.version || ''}

` : `

OpenClaw 基于 Node.js 运行,请先安装。

下载 Node.js 安装后点击「重新检测」 ${isMacPlatform() ? `
已经装了但检测不到? macOS 上从 Finder 启动可能找不到 Node.js。试试关掉 ClawPanel 后从终端启动:
open /Applications/ClawPanel.app
` : ''}` }
` // 第二步:OpenClaw CLI html += `
${stepIcon(cliOk)} OpenClaw CLI
${cliOk ? `

CLI 可用

` : renderInstallSection() }
` // 第三步:配置文件 html += `
${stepIcon(config.installed)} 配置文件
${config.installed ? `

配置文件位于 ${config.path || ''}

` : `

安装 CLI 后会自动生成配置,也可手动执行 openclaw configure

` }
` // 全部就绪 → 进入面板 if (allOk) { html += `
` } stepsEl.innerHTML = html bindEvents(page, nodeOk) } function renderInstallSection() { return `

选择版本后点击安装,将自动执行 npm 全局安装。

` } function bindEvents(page, nodeOk) { // 进入面板 page.querySelector('#btn-enter')?.addEventListener('click', () => { window.location.hash = '/dashboard' }) // 一键安装 const installBtn = page.querySelector('#btn-install') if (!installBtn || !nodeOk) return installBtn.addEventListener('click', async () => { const source = page.querySelector('input[name="install-source"]:checked')?.value || 'chinese' const registry = page.querySelector('#registry-select')?.value const modal = showUpgradeModal() let unlistenLog, unlistenProgress setUpgrading(true) try { if (window.__TAURI_INTERNALS__) { try { const { listen } = await import('@tauri-apps/api/event') unlistenLog = await listen('upgrade-log', (e) => modal.appendLog(e.payload)) unlistenProgress = await listen('upgrade-progress', (e) => modal.setProgress(e.payload)) } catch { /* Web 模式无 Tauri event */ } } else { modal.appendLog('Web 模式:安装日志不可用,请等待完成...') } // 先设置镜像源 if (registry) { modal.appendLog(`设置 npm 镜像源: ${registry}`) try { await api.setNpmRegistry(registry) } catch {} } const msg = await api.upgradeOpenclaw(source) modal.setDone(msg) // 安装成功后自动安装 Gateway modal.appendLog('正在安装 Gateway 服务...') try { await api.installGateway() modal.appendLog('✅ Gateway 服务已安装') } catch (e) { modal.appendLog('⚠️ Gateway 安装失败: ' + e) } toast('OpenClaw 安装成功', 'success') setTimeout(() => window.location.reload(), 1500) } catch (e) { const errStr = String(e) modal.appendLog(errStr) const diagnosis = diagnoseInstallError(errStr) modal.setError(diagnosis.title) if (diagnosis.hint) modal.appendLog('') if (diagnosis.hint) modal.appendLog('ℹ️ ' + diagnosis.hint) if (diagnosis.command) modal.appendLog('💻 ' + diagnosis.command) } finally { setUpgrading(false) unlistenLog?.() unlistenProgress?.() } }) }