fix(intelligence): Heartbeat 统一健康系统 — 6处断链修复 + 健康面板 + SaaS自动恢复
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

Rust 后端 (heartbeat.rs):
- 告警实时推送: OnceLock<AppHandle> + Tauri emit heartbeat:alert
- 动态间隔: tokio::select! + Notify 替代不可变 interval
- Config 持久化: update_config 写入 VikingStorage
- heartbeat_init 从 VikingStorage 恢复 config
- 移除 dead code (subscribe, HeartbeatCheckFn)
- Memory stats fallback 分层处理

新增 health_snapshot.rs:
- HealthSnapshot Tauri 命令 — 按需查询引擎/记忆状态
- 注册到 lib.rs invoke_handler

前端修复:
- HeartbeatConfig handleSave 同步到 Rust 后端
- App.tsx 读 localStorage 持久化配置 + heartbeat:alert 监听 + toast
- saasStore 降级后指数退避探测恢复 + saas-recovered 事件
- 新增 HealthPanel.tsx 只读健康面板 (4卡片 + 告警列表)
- SettingsLayout 添加 health 导航入口

清理:
- 删除 intelligence-client/ 目录版 (9文件 -1640行, 单文件版是活跃代码)
This commit is contained in:
iven
2026-04-15 23:19:24 +08:00
parent 043824c722
commit 215c079d29
19 changed files with 1184 additions and 1678 deletions

View File

@@ -18,6 +18,7 @@ import {
Heart,
Key,
Database,
Activity,
Cloud,
CreditCard,
} from 'lucide-react';
@@ -37,6 +38,7 @@ import { SecurityStatus } from '../SecurityStatus';
import { SecurityLayersPanel } from '../SecurityLayersPanel';
import { TaskList } from '../TaskList';
import { HeartbeatConfig } from '../HeartbeatConfig';
import { HealthPanel } from '../HealthPanel';
import { SecureStorage } from './SecureStorage';
import { VikingPanel } from '../VikingPanel';
import { SaaSSettings } from '../SaaS/SaaSSettings';
@@ -65,6 +67,7 @@ type SettingsPage =
| 'audit'
| 'tasks'
| 'heartbeat'
| 'health'
| 'feedback'
| 'about';
@@ -89,6 +92,7 @@ const menuItems: { id: SettingsPage; label: string; icon: React.ReactNode; group
{ id: 'audit', label: '审计日志', icon: <ClipboardList className="w-4 h-4" />, group: 'advanced' },
{ id: 'tasks', label: '定时任务', icon: <Clock className="w-4 h-4" />, group: 'advanced' },
{ id: 'heartbeat', label: '心跳配置', icon: <Heart className="w-4 h-4" />, group: 'advanced' },
{ id: 'health', label: '系统健康', icon: <Activity className="w-4 h-4" />, group: 'advanced' },
// --- Footer ---
{ id: 'feedback', label: '提交反馈', icon: <HelpCircle className="w-4 h-4" /> },
{ id: 'about', label: '关于', icon: <Info className="w-4 h-4" /> },
@@ -175,6 +179,16 @@ export function SettingsLayout({ onBack }: SettingsLayoutProps) {
</div>
</ErrorBoundary>
);
case 'health': return (
<ErrorBoundary
fallback={<div className="p-6 text-center text-gray-500"></div>}
onError={(err, info) => console.error('[Settings] Health page error:', err, info.componentStack)}
>
<div className="max-w-3xl h-full">
<HealthPanel />
</div>
</ErrorBoundary>
);
case 'viking': return (
<ErrorBoundary
fallback={<div className="p-6 text-center text-gray-500"></div>}