feat: Windows 兼容性全面改进

- Windows Gateway 启动改为前台 spawn 模式(绕过 schtasks 管理员权限)
- 添加全局 Gateway 未启动引导横幅(黄色提示条 + 一键启动按钮)
- 所有页面加载动画改为脉冲效果
- 统一 Windows cmd /c 调用加 CREATE_NO_WINDOW 标志
- 托盘菜单复用 service.rs 逻辑
- 新增 utils.rs 封装 openclaw_command
- 修复 config 文件 UI 字段污染问题
- 添加 dev.ps1 启动脚本
This commit is contained in:
晴天
2026-03-02 13:00:16 +08:00
parent 5352337eaa
commit 53f46d8ef2
64 changed files with 4260 additions and 451 deletions

View File

@@ -1,9 +1,11 @@
/**
* ClawPanel 入口
*/
import { registerRoute, initRouter } from './router.js'
import { registerRoute, initRouter, navigate, setDefaultRoute } from './router.js'
import { renderSidebar } from './components/sidebar.js'
import { initTheme } from './lib/theme.js'
import { detectOpenclawStatus, isOpenclawReady, isGatewayRunning, onGatewayChange, startGatewayPoll } from './lib/app-state.js'
import { api } from './lib/tauri-api.js'
// 样式
import './style/variables.css'
@@ -14,24 +16,81 @@ import './style/pages.css'
import './style/chat.css'
import './style/agents.css'
// 注册页面路由(懒加载)
registerRoute('/dashboard', () => import('./pages/dashboard.js'))
registerRoute('/chat', () => import('./pages/chat.js'))
registerRoute('/services', () => import('./pages/services.js'))
registerRoute('/logs', () => import('./pages/logs.js'))
registerRoute('/models', () => import('./pages/models.js'))
registerRoute('/agents', () => import('./pages/agents.js'))
registerRoute('/gateway', () => import('./pages/gateway.js'))
registerRoute('/memory', () => import('./pages/memory.js'))
registerRoute('/extensions', () => import('./pages/extensions.js'))
registerRoute('/about', () => import('./pages/about.js'))
// 初始化主题
initTheme()
// 初始化
const sidebar = document.getElementById('sidebar')
const content = document.getElementById('content')
renderSidebar(sidebar)
initRouter(content)
async function boot() {
await detectOpenclawStatus()
if (isOpenclawReady()) {
// 正常模式:注册所有页面
registerRoute('/dashboard', () => import('./pages/dashboard.js'))
registerRoute('/chat', () => import('./pages/chat.js'))
registerRoute('/services', () => import('./pages/services.js'))
registerRoute('/logs', () => import('./pages/logs.js'))
registerRoute('/models', () => import('./pages/models.js'))
registerRoute('/agents', () => import('./pages/agents.js'))
registerRoute('/gateway', () => import('./pages/gateway.js'))
registerRoute('/memory', () => import('./pages/memory.js'))
registerRoute('/extensions', () => import('./pages/extensions.js'))
registerRoute('/about', () => import('./pages/about.js'))
} else {
// 未安装模式:只注册 setup、extensions、about
setDefaultRoute('/setup')
registerRoute('/setup', () => import('./pages/setup.js'))
registerRoute('/extensions', () => import('./pages/extensions.js'))
registerRoute('/about', () => import('./pages/about.js'))
}
renderSidebar(sidebar)
initRouter(content)
// 未安装时强制跳转到 setup
if (!isOpenclawReady()) {
navigate('/setup')
return
}
// Gateway 未启动引导横幅
setupGatewayBanner()
startGatewayPoll()
}
function setupGatewayBanner() {
const banner = document.getElementById('gw-banner')
if (!banner) return
function update(running) {
if (running) {
banner.classList.add('gw-banner-hidden')
} else {
banner.classList.remove('gw-banner-hidden')
banner.innerHTML = `
<div class="gw-banner-content">
<span class="gw-banner-icon">⚠</span>
<span>Gateway 未启动,部分功能不可用</span>
<button class="btn btn-sm btn-primary" id="btn-gw-start">启动 Gateway</button>
</div>
`
banner.querySelector('#btn-gw-start')?.addEventListener('click', async (e) => {
const btn = e.target
btn.disabled = true
btn.textContent = '启动中...'
try {
await api.startService('ai.openclaw.gateway')
} catch (err) {
btn.textContent = '启动失败,重试'
btn.disabled = false
}
})
}
}
update(isGatewayRunning())
onGatewayChange(update)
}
boot()