feat: 重构 Dashboard 为卡片式分组布局
表格布局替换为按分组展示的卡片式布局,新增 group 字段配置和 TargetBoard/TargetCard 等组件。模态框详情页支持时间范围筛选和分页,SummaryCards 减为 3 个。API 端点变更:trend/history 改用 from/to 参数,history 支持分页。recentSampleCount 硬编码为 30。
This commit is contained in:
@@ -1,48 +1,82 @@
|
||||
## Purpose
|
||||
|
||||
定义拨测系统的 REST API 端点:总览统计、目标列表含状态、历史记录和趋势聚合。
|
||||
定义拨测系统的 REST API 端点:总览统计、目标列表含分组和结构化采样数据、带时间范围和分页的历史记录、按时间范围的趋势聚合。
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: 总览统计 API
|
||||
系统 SHALL 提供 `GET /api/summary` 端点,返回所有目标的总体统计信息。
|
||||
系统 SHALL 提供 `GET /api/summary` 端点,返回所有目标的总体统计信息(不含平均耗时)。
|
||||
|
||||
#### Scenario: 获取总览统计
|
||||
- **WHEN** 客户端请求 `GET /api/summary`
|
||||
- **THEN** 系统 SHALL 返回 JSON 包含 total(总目标数)、up(正常数)、down(异常数)、avgDurationMs(所有目标平均耗时)、lastCheckTime(最近一次检查时间)
|
||||
- **THEN** 系统 SHALL 返回 JSON 包含 total(总目标数)、up(正常数)、down(异常数)、lastCheckTime(最近一次检查时间)
|
||||
|
||||
### Requirement: 目标列表 API
|
||||
系统 SHALL 提供 `GET /api/targets` 端点,返回所有 typed target 及其最新状态和统计摘要。
|
||||
系统 SHALL 提供 `GET /api/targets` 端点,返回所有 typed target 及其最新状态、分组信息和结构化采样数据。
|
||||
|
||||
#### Scenario: 获取目标列表
|
||||
- **WHEN** 客户端请求 `GET /api/targets`
|
||||
- **THEN** 系统 SHALL 返回 JSON 数组,每个元素包含目标基本信息(id、name、type、target、interval)、最近一次检查结果(timestamp、success、matched、durationMs、statusDetail、failure)和统计摘要(totalChecks、availability、avgDurationMs、p99DurationMs)
|
||||
- **THEN** 系统 SHALL 返回 JSON 数组,每个元素包含目标基本信息(id、name、group、type、target、interval)、最近一次检查结果(timestamp、success、matched、durationMs、statusDetail、failure)、统计摘要(totalChecks、availability)和结构化采样数据 recentSamples(代替原 sparkline)
|
||||
|
||||
#### Scenario: 目标无历史记录
|
||||
- **WHEN** 某目标尚未执行过任何拨测
|
||||
- **THEN** 其 latestCheck 为 null,stats 中 totalChecks 为 0
|
||||
- **THEN** 其 latestCheck 为 null,recentSamples 为空数组
|
||||
|
||||
### Requirement: 历史记录 API
|
||||
系统 SHALL 提供 `GET /api/targets/:id/history` 端点,返回指定目标的最近 N 条拨测记录。
|
||||
系统 SHALL 提供 `GET /api/targets/:id/history` 端点,支持时间范围筛选和分页返回指定目标的拨测记录。
|
||||
|
||||
#### Scenario: 获取最近历史记录
|
||||
- **WHEN** 客户端请求 `GET /api/targets/1/history?limit=20`
|
||||
- **THEN** 系统 SHALL 返回最多 20 条检查记录,按时间倒序排列,且每条包含 success、matched、durationMs、statusDetail 和 failure
|
||||
#### Scenario: 获取指定时间范围内的历史记录
|
||||
- **WHEN** 客户端请求 `GET /api/targets/1/history?from=ISO&to=ISO&page=1&pageSize=20`
|
||||
- **THEN** 系统 SHALL 返回带分页信息的历史记录,包含 items、total、page、pageSize,按时间倒序排列
|
||||
|
||||
#### Scenario: 使用默认 limit
|
||||
- **WHEN** 客户端请求 `GET /api/targets/1/history`(未指定 limit)
|
||||
- **THEN** 系统 SHALL 默认返回最近 20 条记录
|
||||
#### Scenario: 使用默认分页参数
|
||||
- **WHEN** 客户端请求 `GET /api/targets/1/history?from=ISO&to=ISO`(未指定 page 或 pageSize)
|
||||
- **THEN** 系统 SHALL 使用默认 page=1, pageSize=20
|
||||
|
||||
### Requirement: 趋势聚合 API
|
||||
系统 SHALL 提供 `GET /api/targets/:id/trend` 端点,返回指定目标按小时聚合的趋势数据。
|
||||
#### Scenario: from 或 to 参数缺失
|
||||
- **WHEN** 客户端请求 `GET /api/targets/1/history` 未提供 from 或 to 参数
|
||||
- **THEN** 系统 SHALL 返回 400 状态码和错误信息
|
||||
|
||||
#### Scenario: 获取 24 小时趋势
|
||||
- **WHEN** 客户端请求 `GET /api/targets/1/trend?hours=24`
|
||||
- **THEN** 系统 SHALL 返回按小时分组的聚合数据,每个数据点包含 hour、avgDurationMs、availability、totalChecks
|
||||
### Requirement: 趋势 API 支持时间范围
|
||||
系统 SHALL 提供 `GET /api/targets/:id/trend` 端点,支持 `from` 和 `to` 查询参数指定时间范围。
|
||||
|
||||
#### Scenario: 使用默认时间范围
|
||||
- **WHEN** 客户端请求 `GET /api/targets/1/trend`(未指定 hours)
|
||||
- **THEN** 系统 SHALL 默认返回最近 24 小时的趋势数据
|
||||
#### Scenario: 指定时间范围查询趋势
|
||||
- **WHEN** 客户端请求 `GET /api/targets/1/trend?from=ISO&to=ISO`
|
||||
- **THEN** 系统 SHALL 返回指定时间范围内按小时分组的聚合数据
|
||||
|
||||
#### Scenario: from 或 to 参数缺失
|
||||
- **WHEN** 客户端请求 `GET /api/targets/1/trend` 未提供 from 或 to 参数
|
||||
- **THEN** 系统 SHALL 返回 400 状态码和错误信息
|
||||
|
||||
### Requirement: 目标列表返回分组和采样数据
|
||||
`GET /api/targets` SHALL 返回每个目标的分组信息和结构化采样数据,替代原有 sparkline。
|
||||
|
||||
#### Scenario: 返回分组信息
|
||||
- **WHEN** 客户端请求 `GET /api/targets`
|
||||
- **THEN** 响应中每个目标 SHALL 包含 `group` 字段,值为该目标所属的分组名称
|
||||
|
||||
#### Scenario: 返回 recentSamples
|
||||
- **WHEN** 客户端请求 `GET /api/targets`
|
||||
- **THEN** 响应中每个目标 SHALL 包含 `recentSamples` 数组,每个元素包含 `timestamp`(ISO 8601)、`durationMs`(number | null)、`up`(boolean,success && matched)
|
||||
|
||||
#### Scenario: recentSamples 数量
|
||||
- **WHEN** 客户端请求 `GET /api/targets`
|
||||
- **THEN** 每个目标的 recentSamples SHALL 最多包含 30 个元素,按时间倒序排列
|
||||
|
||||
#### Scenario: 目标无历史记录
|
||||
- **WHEN** 某目标尚未执行过任何拨测
|
||||
- **THEN** 其 recentSamples SHALL 为空数组
|
||||
|
||||
### Requirement: 新增共享类型
|
||||
系统 SHALL 在 `src/shared/api.ts` 中定义 `RecentSample` 和 `HistoryResponse` 类型。
|
||||
|
||||
#### Scenario: RecentSample 类型
|
||||
- **WHEN** 前后端共享 `RecentSample` 类型
|
||||
- **THEN** 该类型 SHALL 包含 `timestamp: string`、`durationMs: number | null`、`up: boolean` 字段
|
||||
|
||||
#### Scenario: HistoryResponse 类型
|
||||
- **WHEN** 前后端共享 `HistoryResponse` 类型
|
||||
- **THEN** 该类型 SHALL 包含 `items: CheckResult[]`、`total: number`、`page: number`、`pageSize: number` 字段
|
||||
|
||||
### Requirement: 保留健康检查端点
|
||||
系统 SHALL 保留 `GET /health` 端点,不受拨测功能影响。
|
||||
@@ -58,8 +92,20 @@
|
||||
- **WHEN** 客户端请求 `GET /api/targets/999/history`
|
||||
- **THEN** 系统 SHALL 返回 404 状态码和错误信息
|
||||
|
||||
#### Scenario: 无效的 limit 参数
|
||||
- **WHEN** 客户端请求 `GET /api/targets/1/history?limit=abc`
|
||||
#### Scenario: 无效的 from/to 参数
|
||||
- **WHEN** 客户端请求 `GET /api/targets/1/history?from=invalid`
|
||||
- **THEN** 系统 SHALL 返回 400 状态码和错误信息
|
||||
|
||||
#### Scenario: 无效的分页参数
|
||||
- **WHEN** 客户端请求 `GET /api/targets/1/history?from=ISO&to=ISO&page=abc`
|
||||
- **THEN** 系统 SHALL 返回 400 状态码和错误信息
|
||||
|
||||
#### Scenario: from 或 to 参数缺失
|
||||
- **WHEN** 客户端请求 `GET /api/targets/1/trend` 未提供 from 或 to 参数
|
||||
- **THEN** 系统 SHALL 返回 400 状态码和错误信息
|
||||
|
||||
#### Scenario: 无效的目标 ID
|
||||
- **WHEN** 客户端请求 `GET /api/targets/abc/history`
|
||||
- **THEN** 系统 SHALL 返回 400 状态码和错误信息
|
||||
|
||||
### Requirement: 失败信息 API 契约
|
||||
|
||||
Reference in New Issue
Block a user