1
0
Files
DiAL/openspec/specs/target-detail-drawer/spec.md

230 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Purpose
定义目标详情 Drawer时间范围筛选TDesign RadioGroup + DateRangePicker 单行布局含快捷按钮联动概览和记录面板、Tabs 组织概览/记录两个面板、Metrics 数据查询 Hook、多维度统计图表4×2 Card 布局)和分页检查结果列表。
## Requirements
### Requirement: 目标详情 Drawer
Dashboard SHALL 在用户点击目标表格行后从右侧滑出 Drawer展示该目标的详细统计信息和检查记录。Drawer 标题栏和内容不使用内联 style。Drawer 内容 SHALL 拆分为独立的 Tab 组件。
#### Scenario: 打开 Drawer
- **WHEN** 用户点击某个目标表格行
- **THEN** 系统 SHALL 从右侧滑出 Drawerplacement="right"),宽度为 52%
#### Scenario: Drawer 标题栏
- **WHEN** Drawer 渲染
- **THEN** 标题栏 SHALL 使用 TDesign Space 组件align="center")布局,包含 StatusDot、目标名称TDesign Typography.Text strong和类型标签TDesign Tag直接显示 target.type 原始文本),以及内建关闭按钮。不使用内联 style 的 flex 布局
#### Scenario: 关闭 Drawer
- **WHEN** 用户点击关闭按钮、ESC 键或遮罩层
- **THEN** Drawer SHALL 关闭
#### Scenario: Drawer 无底部按钮
- **WHEN** Drawer 渲染
- **THEN** Drawer SHALL 不显示底部操作栏footer={false}
#### Scenario: Drawer 数据同步
- **WHEN** Drawer 打开期间后台轮询刷新了 targets 数据
- **THEN** Drawer 中 selectedTarget 的状态 SHALL 随之同步更新
#### Scenario: 切换目标重置 Tab
- **WHEN** 用户从目标 A 切换到目标 B点击不同的表格行
- **THEN** Drawer SHALL 重置为概览 Tab使用 key={target.id} 确保组件状态不残留
#### Scenario: Drawer 内容区间距
- **WHEN** Drawer 内容渲染
- **THEN** 时间选择器、Tabs 等区块之间的间距 SHALL 通过 TDesign Space 组件direction="vertical", size={16})统一管理,不使用内联 style 的 marginBottom
### Requirement: 概览面板组件化
概览 Tab SHALL 作为独立组件 `OverviewTab` 实现,展示基本信息、多维度统计(左右布局卡片)和趋势图。不再包含状态分布环形图。
#### Scenario: OverviewTab 组件职责
- **WHEN** 概览 Tab 渲染
- **THEN** `OverviewTab` 组件 SHALL 负责基本信息(直接展示 Descriptions、多维度统计卡片4×2 左右布局)和趋势图的渲染
#### Scenario: OverviewTab props
- **WHEN** OverviewTab 渲染
- **THEN** 组件 SHALL 接收 `target: TargetStatus``metricsData: TargetMetricsResponse | null``metricsLoading: boolean` 作为 props
### Requirement: 记录面板组件化
记录 Tab SHALL 作为独立组件 `HistoryTab` 实现。
#### Scenario: HistoryTab 组件职责
- **WHEN** 记录 Tab 渲染
- **THEN** `HistoryTab` 组件 SHALL 负责检查结果表格和分页的渲染
#### Scenario: HistoryTab props
- **WHEN** HistoryTab 渲染
- **THEN** 组件 SHALL 接收 `historyData: HistoryResponse``historyLoading: boolean``onPageChange: (page: number) => void` 作为 props
#### Scenario: 历史记录列定义外置
- **WHEN** HistoryTab 渲染表格
- **THEN** 列定义 SHALL 从 `constants/history-table-columns.tsx` 导入,不在组件内部定义
### Requirement: TrendChart 简化
TrendChart 组件 SHALL 仅接收数据 props不处理 loading 状态。
#### Scenario: TrendChart 无 loading prop
- **WHEN** TrendChart 渲染
- **THEN** 组件 SHALL 仅接收 `data: TrendPoint[]` prop不接收 `loading` prop
#### Scenario: TrendChart 空数据
- **WHEN** TrendChart 接收空数组
- **THEN** 组件 SHALL 显示"暂无趋势数据"占位文本
### Requirement: StatusBar 参数化
StatusBar 组件 SHALL 支持可配置的格数。
#### Scenario: maxSlots prop
- **WHEN** StatusBar 渲染
- **THEN** 组件 SHALL 接收可选的 `maxSlots` prop默认 30根据该值渲染对应数量的格子
#### Scenario: 格子渲染逻辑
- **WHEN** StatusBar 渲染且 samples 数量少于 maxSlots
- **THEN** 多余的格子 SHALL 显示为 empty 状态
### Requirement: Metrics 数据查询 Hook
系统 SHALL 提供 `useTargetMetrics` hook 查询单目标指标数据。
#### Scenario: metrics queryKey
- **WHEN** 查询某目标的指标数据
- **THEN** queryKey SHALL 为 ["metrics", targetId, from, to, bucket]
#### Scenario: metrics 条件查询
- **WHEN** 用户未选中任何目标
- **THEN** metrics 的 useQuery SHALL enabled=false不发起请求
#### Scenario: metrics 数据返回
- **WHEN** metrics 查询成功
- **THEN** hook SHALL 返回 `TargetMetricsResponse` 类型数据
#### Scenario: 时间范围变化时重新请求
- **WHEN** 用户更改时间范围
- **THEN** metrics 的 useQuery SHALL 因 queryKey 变化自动重新请求
#### Scenario: Drawer 关闭清理查询缓存
- **WHEN** 用户关闭 Drawer
- **THEN** 系统 MAY 清理 metrics 和 history 查询缓存,避免旧目标数据残留
### Requirement: 时间范围选择器
Drawer SHALL 在 Tabs 外层提供时间范围选择器,影响概览和记录两个面板的数据。
#### Scenario: 快捷时间按钮
- **WHEN** Drawer 渲染
- **THEN** 时间选择区第一行 SHALL 显示 TDesign RadioGroupvariant=default-filled快捷按钮1小时、6小时、24小时、7天
#### Scenario: 点击快捷按钮
- **WHEN** 用户点击快捷按钮(如 "24小时"
- **THEN** 系统 SHALL 自动设置对应的起止时间DateRangePicker 显示对应的时间范围,该按钮高亮
#### Scenario: 快捷按钮联动统计区
- **WHEN** 用户点击 1小时/6小时/24小时/7天 快捷按钮
- **THEN** 概览面板 SHALL 使用对应的时间窗口重新请求 `/api/targets/:id/metrics` 数据
#### Scenario: 快捷按钮联动历史记录
- **WHEN** 用户点击 1小时/6小时/24小时/7天 快捷按钮
- **THEN** 记录面板 SHALL 使用对应的时间窗口重新请求 `/api/targets/:id/history` 数据,并重置页码为 1
#### Scenario: 自定义日期时间范围
- **WHEN** 用户通过 TDesign DateRangePickermode=date, enableTimePicker, format="YYYY-MM-DD HH:mm")修改时间范围
- **THEN** 快捷按钮 SHALL 取消高亮,系统重新请求对应时间范围的数据
#### Scenario: 时间精度为分钟级
- **WHEN** 用户通过 DateRangePicker 选择时间
- **THEN** 选择器 SHALL 仅精确到分钟format="YYYY-MM-DD HH:mm"),秒列固定为 00
#### Scenario: DateRangePicker 全宽显示
- **WHEN** Drawer 渲染
- **THEN** DateRangePicker SHALL 通过 CSS 类 `.full-width` 占满时间选择区的宽度,不使用内联 style 的 width: 100%
#### Scenario: 默认时间范围
- **WHEN** Drawer 打开
- **THEN** 时间选择器 SHALL 默认选中 "24小时" 快捷按钮
#### Scenario: 筛选触发数据刷新
- **WHEN** 时间范围发生变化
- **THEN** 系统 SHALL 重新请求趋势数据和历史记录
### Requirement: Tabs 内容组织
Drawer 内部 SHALL 使用 TDesign Tabs 组织概览和记录两个面板。TabPanel 内边距通过 className prop 控制。
#### Scenario: Tab 标签
- **WHEN** Drawer 渲染
- **THEN** Tabs SHALL 显示两个标签:概览、记录
#### Scenario: Tab 面板内边距
- **WHEN** TabPanel 渲染
- **THEN** TabPanel SHALL 通过 `className` prop 传入自定义类名(`tab-panel-padded`)控制内边距,不通过入侵 TDesign 内部类名(`.t-tab-panel`)覆盖
### Requirement: 概览面板
概览 Tab SHALL 按区域展示基本信息、多维度统计和趋势图。
#### Scenario: 区域排列顺序
- **WHEN** 概览面板渲染
- **THEN** 面板 SHALL 按以下顺序展示区域:基本信息 → 统计 → 趋势,每个区域前 SHALL 显示 TDesign Divideralign="left")作为小标题
#### Scenario: 基本信息直接展示
- **WHEN** 概览面板渲染
- **THEN** 面板 SHALL 在"基本信息"区域直接使用 TDesign Descriptions 组件展示配置信息(不折叠)
#### Scenario: 基本信息内容
- **WHEN** 概览面板渲染
- **THEN** Descriptions SHALL 展示:目标地址、检查间隔、最新检查时间、状态详情
#### Scenario: 统计区左右布局卡片
- **WHEN** 概览面板渲染且有统计数据
- **THEN** 面板 SHALL 在"统计"区域使用 4 列 × 2 行的 Row/Col 布局,每个统计项使用 Card 包裹Card 内标题左对齐、数值右对齐,数值使用普通文本字号
#### Scenario: 统计区内容
- **WHEN** 概览面板渲染
- **THEN** 统计区 SHALL 展示可用率suffix="%"、平均延迟suffix="ms"、P95 延迟suffix="ms"、检查总数、MTTR动态单位、最长故障动态单位、故障次数suffix="次"、连续正常suffix="次"
#### Scenario: 趋势图
- **WHEN** 概览面板渲染且 metricsData.trend 可用
- **THEN** 面板 SHALL 在"趋势"区域展示 TrendChart 组件
#### Scenario: 统计区加载状态
- **WHEN** metricsData 正在加载
- **THEN** 统计区 SHALL 显示 TDesign Skeleton 加载占位
#### Scenario: 统计区无数据
- **WHEN** metricsData 为 null 且未处于加载状态
- **THEN** 统计区 SHALL 展示占位状态
#### Scenario: 趋势数据加载中
- **WHEN** metricsData 正在加载
- **THEN** "趋势"区域 SHALL 显示 TDesign Skeleton 加载占位
### Requirement: Drawer 宽度
Drawer 宽度 SHALL 设置为 52%。
#### Scenario: Drawer 宽度
- **WHEN** Drawer 打开
- **THEN** Drawer size SHALL 为 "52%"
### Requirement: 时间选择器单行布局
Drawer 顶部的时间范围快捷按钮和日期范围选择器 SHALL 在同一行展示。
#### Scenario: 单行布局
- **WHEN** Drawer 渲染时间选择区域
- **THEN** RadioGroup 和 DateRangePicker SHALL 使用 flex 布局在同一行水平排列
### Requirement: 记录面板
记录 Tab SHALL 展示分页检查结果列表,使用 TDesign PrimaryTable。
#### Scenario: 检查结果表格
- **WHEN** 记录面板渲染且数据可用
- **THEN** 面板 SHALL 使用 TDesign PrimaryTable 展示检查结果列包含状态StatusDot 圆点、时间YYYY-MM-DD HH:mm:ss 格式)、耗时(标题含 ms 单位单元格仅显示数值居中对齐、详情statusDetail 和 failure.message 用冒号拼接)
#### Scenario: 服务端分页
- **WHEN** 检查结果总数超过一页
- **THEN** 表格 SHALL 使用内建 paginationdisableDataPage=true分页器显示在表格底部
#### Scenario: 翻页触发请求
- **WHEN** 用户切换分页页码
- **THEN** 系统 SHALL 请求对应页码的服务端数据,表格更新
#### Scenario: 记录数据加载中
- **WHEN** 历史记录正在加载
- **THEN** 表格 SHALL 显示 loading 状态