/**
* 初始设置页面 — 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
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?.()
}
})
}