# 资产主机详情抽屉与终端窗口壳 | 字段 | 内容 | |------|------| | 状态 | Implemented | | 级别 | S2 | | 负责人 | Logan.Li | | 创建日期 | 2026-09-14 | | 最后更新 | 2026-09-14 | | 关联任务 | 服务器管理页右侧 Sheet 详情;SSH 终端 Dialog 借鉴 lite `/monitor` 窗口壳 | ## 1. 背景与证据 当前 `/servers` 点资产名称或编辑,进入的是 `ServerForm` 编辑弹窗,没有只读详情。Agent 监控有居中 `HostDetailDialog`,主机监控页是整页图表,都不适合在资产列表里扫一眼。 opsx-web-lite `/monitor` 右侧 560px `HostDetailDrawer`(规格网格 + 2×2 迷你曲线 + 进程 TOP 进度条)以及 macOS 风格终端壳(红黄绿 + `user@host:~` + 深蓝底)已在本地 `localhost:5184/monitor` 对照过。lite 曲线/进程是演示数据,本次只用其布局,数据走现有 `GET /servers` 列表字段与 `GET /agent/history/:hostname`。 ## 2. 目标与非目标 ### 目标 - 资产列表可打开右侧只读详情抽屉,不离开列表。 - 抽屉展示真实资产规格、最近 30 分钟迷你曲线、进程 TOP5;无 Agent 时给空态。 - SSH 终端弹窗采用 lite 窗口壳,保留真实 xterm / WebSocket / 全屏 / 凭证选择。 ### 非目标 - 不新增 API、表字段或权限码。 - 不移植 lite 假终端命令模拟器。 - 不改服务器编辑表单、不改主机监控整页。 - 不把窗口壳扩到 Kubectl / Pod exec / WebShell 整页(审计实时监控弹窗与 SSH 弹窗共用壳,因其注释已要求布局一致)。 ## 3. 用户场景 - 当运维在服务器列表点击资产名称或菜单「详情」时,系统必须从右侧滑出该主机只读详情,列表仍可见。 - 当该主机有 Agent 上报时,系统必须展示 CPU/内存/磁盘/网络迷你曲线与进程 TOP5。 - 当无 Agent 上报时,系统必须展示规格信息,并在曲线/进程区给出空态,不得伪造内核、CPU 型号或进程。 - 当运维从抽屉点终端(或列表原入口)打开 SSH 时,系统必须显示红黄绿标题栏与 `username@展示名:~`,红点关闭、绿点全屏。 ## 4. 需求 ### 功能需求 - `FR-01`:服务器列表资产名称与下拉「详情」打开右侧 Sheet(约 560px),关闭后回到列表。 - `FR-02`:抽屉标题为展示名(别名 > 云实例名 > hostname > IP)加资产状态徽章;副标题说明只读详情。 - `FR-03`:规格网格展示 OS、内核、CPU 核数、内存、磁盘、IP、区域、运行时长;有则展示公网 IP、云实例、Agent 状态/版本、标签。缺字段显示 `—`。 - `FR-04`:有 `hostname` 时请求最近 30 分钟 Agent 历史;用末尾至多 30 个点画 CPU/内存/磁盘/网络下行迷你曲线;网络最后一点用 B/s→KB/s→MB/s 换算,禁止把 bps 当 MB/s。 - `FR-05`:进程 TOP5 取最新上报 `process_top_info`,按 CPU% 降序,带 CPU/MEM 进度条;无数据给空态。 - `FR-06`:抽屉底部快捷操作:终端或 RDP、文件、监控(`/monitor-center?host=`)、编辑;受现有 `server:webshell` / `server:update` / `agent:monitor` 控制;编辑仍打开现有表单。 - `FR-07`:`TerminalDialog` 与 `LiveMonitorDialog` 标题栏改为红黄绿窗口壳 + 会话名,去掉与红点重复的右上角 X;绿点切换全屏,全屏时黄点退出全屏。 ### 非功能需求 - `NFR-01`:抽屉仅在打开时拉历史,失败时规格仍可用,曲线/进程空态。 - `NFR-02`:中英文文案走 i18n;主题色用 `var(--dg-*)`,终端内容区保持深蓝底。 - `NFR-03`:不引入规格外重构;新增 React 文件不超过 700 行。 ## 5. 设计与契约 ### 模块边界 - 新组件:`frontend/src/components/server/ServerDetailSheet.tsx` 及 `server-detail/` 辅助。 - 窗口壳:`frontend/src/components/common/TerminalWindowChrome.tsx`,SSH 与审计实时监控共用。 - 复用 `useHostHistory`、`getTags`、`getStatusBadge`、`isRdpServer`。 - 不改 `ServerForm` 的「更多详情」折叠编辑区。 ### API / 事件 - 无新接口。历史:`GET /api/v1/agent/history/:hostname?minutes=30`(已有 JWT `authorized` 组)。 - 资产字段来自当前列表行(`GET /servers` 已 Preload Region/Cloud)。 ### 数据与迁移 - 无。 ### UI / 交互 - 入口:资产名称、行菜单「详情」。原终端图标、编辑、删除不变。 - 抽屉打开时列表可被遮罩;终端 Dialog 叠在抽屉之上,关闭终端后抽屉仍在。 - 加载:曲线区 Spinner;空:无上报文案;错误:与空态相同(不弹阻塞框)。 ## 6. 风险与可观测性 | 风险/失败模式 | 防护或降级 | 观测信号 | |---------------|------------|----------| | 主机无 Agent / hostname 对不上 | 规格照常,曲线与进程空态 | 抽屉空态文案 | | 历史接口 4xx/5xx | TanStack Query error → 空态 | 浏览器网络错误 | | 网络单位误用 | helpers 统一按 bps 换算 | AC-04 | | 终端 ESC 被 Dialog 吃掉 | 保持现有 `onEscapeKeyDown` preventDefault | 现有 SSH 行为 | ## 7. 验收标准 - `AC-01`:给定已登录且列表有主机,当点击资产名称,则右侧出现详情抽屉,可见主机名与状态徽章。 - `AC-02`:给定主机缺内核/区域等字段,当打开抽屉,则对应值显示 `—`,不出现 Xeon/nginx 等写死演示值。 - `AC-03`:给定主机近 30 分钟有 Agent 上报,当打开抽屉,则出现 4 张迷你曲线,进程 TOP 来自上报而非固定进程名。 - `AC-04`:给定 `net_rx_bps` 为字节每秒,当展示网络卡片当前值,则单位为 B/s、KB/s 或 MB/s,数值与换算一致。 - `AC-05`:给定无 Agent 上报,当打开抽屉,则曲线与进程区为空态,规格区仍在。 - `AC-06`:给定 `server:webshell`,当点抽屉「终端」,则打开带红黄绿与 `user@host:~` 的 SSH 窗,红点关闭、绿点全屏。 - `AC-07`:`npx tsc --noEmit` 零错误。 ## 8. 验证追踪 | 验收标准 | 测试或检查 | 结果 | |----------|------------|------| | AC-01 | 浏览器:`/servers` 点资产名 | Pending(本机 5173/8080 未启动) | | AC-02 | 代码审查 helpers + 抽屉渲染;无 KERNELS/PROCESS_NAMES 常量 | Passed | | AC-03 | 有 Agent 主机打开抽屉 | Pending(本机未起 AIOps) | | AC-04 | `formatBps(933735.6)` → `911.9 KB/s`(非 MB/s) | Passed | | AC-05 | 无 Agent 主机打开抽屉 | Pending(本机未起 AIOps) | | AC-06 | 打开 SSH 终端对照窗口壳 | Pending(本机未起 AIOps) | | AC-07 | `npm exec -- tsc -p tsconfig.app.json --noEmit` | Passed | ## 9. 发布与回滚 前端静态变更,随版本发布。回滚该提交即可。无迁移。 ## 10. 决策记录 | 日期 | 决策 | 原因与影响 | |------|------|------------| | 2026-09-14 | 右侧 Sheet 而非居中 Dialog | 列表上下文不丢,对齐 lite 与云账号详情 | | 2026-09-14 | 曲线窗口 30 分钟、最多 30 点 | Agent 约 10s 上报,1 分钟点太少 | | 2026-09-14 | 终端去掉重复 X,红点关闭 | lite 红黄绿与右上 X 冲突 | | 2026-09-14 | LiveMonitorDialog 同步窗口壳 | 该组件已声明与 WebSSH 弹窗布局一致 | ## 11. 遗留事项 - Kubectl / Pod 终端是否统一窗口壳。 - 资产列表行内是否展示实时 CPU/内存条(lite 主机表已有,本次不做)。