fix: flatten React Router structure — no nested Routes, each page is a top-level route
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
实现 Gateway 健康监控(P0-1)。后端 Hermes CLI 封装 + API + 前端页面。
|
||||
|
||||
## 第一部分: Hermes CLI 服务(真实数据源)
|
||||
|
||||
创建 backend/app/services/hermes_cli.py:
|
||||
- 封装 `hermes gateway status` CLI 调用
|
||||
- 用 subprocess.run 执行,解析 JSON 输出
|
||||
- 出错时返回空数据 + 日志告警,不抛异常
|
||||
- 函数: gateway_status_all() -> list[GatewayInfo]
|
||||
- 数据类型: id, name, status(online/offline/warn), downtime_minutes, restarts_today, last_event
|
||||
|
||||
## 第二部分: Gateway API
|
||||
|
||||
创建 backend/app/api/gateway.py,全部 require_auth
|
||||
|
||||
### GET /api/v1/gateway/status
|
||||
返回全部 Profile 的 Gateway 状态列表,支持:
|
||||
- query param `?status=online|offline|warn` 筛选
|
||||
- 每行: name, status(🟢/🔴/🟡), downtime, restarts_today, last_event, profile_type
|
||||
- 数据来源: hermes_cli.gateway_status_all()
|
||||
|
||||
### GET /api/v1/gateway/events
|
||||
返回最近 24h 异常事件:
|
||||
```json
|
||||
[
|
||||
{"time": "2026-07-22T18:45", "profile": "monitor", "type": "heartbeat_timeout", "detail": "连续 3 次心跳无响应"},
|
||||
{"time": "2026-07-22T14:20", "profile": "feishu-gw", "type": "feishu_disconnect", "detail": "WebSocket 断开 8 分钟"},
|
||||
{"time": "2026-07-22T10:30", "profile": "gateway-monitor", "type": "restart", "detail": "Gateway 重启"}
|
||||
]
|
||||
```
|
||||
数据来源: hermes CLI 日志或系统日志解析。暂用占位数据(TODO 标注)。
|
||||
|
||||
### POST /api/v1/gateway/{profile}/start, /stop, /restart
|
||||
Gateway 启停操作:
|
||||
- 执行 `hermes gateway start/stop/restart --profile {profile}`
|
||||
- 需要 operator 或 owner 角色(require_role("owner","operator"))
|
||||
- 返回操作结果 + 写入审计日志
|
||||
- 操作前二次确认(前端处理)
|
||||
|
||||
## 第三部分: 前端 Gateway 页面
|
||||
|
||||
修改 frontend/src/pages/GatewayPage.tsx:
|
||||
|
||||
### 顶部: 异常事件时间线
|
||||
- Timeline 组件,24h 横向展示
|
||||
- 事件类型: 🔴心跳超时 🟠飞书断连 🔵Gateway 重启
|
||||
- Hover 显示详情 tooltip
|
||||
|
||||
### 筛选栏
|
||||
- 状态筛选: 全部/在线/离线/异常
|
||||
- 蜂型筛选: 全部/工蜂/蜂王
|
||||
- 筛选器即时生效(前端过滤,不重新请求)
|
||||
|
||||
### 状态表
|
||||
- Table 组件,10s 轮询 (usePolling hook)
|
||||
- 列: Profile 名, 状态 Badge, 掉线时长, 今日重启, 最近异常, 操作
|
||||
- 异常行标红: Gateway 连续重启≥3次 或 掉线≥30分钟
|
||||
- 操作按钮: 启动/停止/重启 (二次确认 Modal)
|
||||
|
||||
### 四态覆盖
|
||||
- Loading: Skeleton (table 形状)
|
||||
- Empty: "全部 Gateway 正常运行 🎉"
|
||||
- Error: 错误 + 重试
|
||||
- Normal: 数据展示
|
||||
|
||||
### usePolling hook
|
||||
创建 frontend/src/hooks/usePolling.ts:
|
||||
```typescript
|
||||
import { useEffect, useRef } from 'react'
|
||||
export function usePolling(callback: () => void, intervalMs: number, enabled: boolean = true) {
|
||||
const savedCallback = useRef(callback)
|
||||
useEffect(() => { savedCallback.current = callback }, [callback])
|
||||
useEffect(() => {
|
||||
if (!enabled) return
|
||||
savedCallback.current() // 立即执行一次
|
||||
const id = setInterval(() => savedCallback.current(), intervalMs)
|
||||
return () => clearInterval(id)
|
||||
}, [intervalMs, enabled])
|
||||
}
|
||||
```
|
||||
|
||||
注册路由: main.py 添加 `from app.api import gateway; app.include_router(gateway.router, prefix="/api/v1")`
|
||||
|
||||
完成后提交。
|
||||
Reference in New Issue
Block a user