## ADDED Requirements ### 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: 趋势 API 支持时间范围 `GET /api/targets/:id/trend` SHALL 支持 `from` 和 `to` 查询参数指定时间范围。 #### Scenario: 指定时间范围查询趋势 - **WHEN** 客户端请求 `GET /api/targets/1/trend?from=2026-05-03T00:00:00Z&to=2026-05-10T00:00:00Z` - **THEN** 系统 SHALL 返回指定时间范围内按小时分组的聚合数据 #### Scenario: from 或 to 参数缺失 - **WHEN** 客户端请求 `GET /api/targets/1/trend` 未提供 from 或 to 参数 - **THEN** 系统 SHALL 返回 400 状态码和错误信息 #### Scenario: 无效的时间参数 - **WHEN** 客户端请求 `GET /api/targets/1/trend?from=invalid` - **THEN** 系统 SHALL 返回 400 状态码和错误信息 ### Requirement: 历史记录 API 支持时间范围和分页 `GET /api/targets/:id/history` SHALL 支持 `from`、`to` 时间范围参数和 `page`、`pageSize` 分页参数,返回带分页信息的结构。 #### Scenario: 指定时间范围和分页 - **WHEN** 客户端请求 `GET /api/targets/1/history?from=ISO&to=ISO&page=1&pageSize=20` - **THEN** 系统 SHALL 返回 JSON 包含 `items`(检查结果数组)、`total`(满足条件的总记录数)、`page`(当前页码)、`pageSize`(每页大小) #### Scenario: 使用默认分页参数 - **WHEN** 客户端请求 `GET /api/targets/1/history?from=ISO&to=ISO` 未指定 page 或 pageSize - **THEN** 系统 SHALL 使用默认 page=1, pageSize=20 #### Scenario: from 或 to 参数缺失 - **WHEN** 客户端请求 `GET /api/targets/1/history` 未提供 from 或 to 参数 - **THEN** 系统 SHALL 返回 400 状态码和错误信息 #### Scenario: 无效的分页参数 - **WHEN** 客户端请求 `GET /api/targets/1/history?from=ISO&to=ISO&page=abc` - **THEN** 系统 SHALL 返回 400 状态码和错误信息 ### 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` 字段 ## MODIFIED Requirements ### Requirement: 总览统计 API 系统 SHALL 提供 `GET /api/summary` 端点,返回所有目标的总体统计信息(不含平均耗时)。 #### Scenario: 获取总览统计 - **WHEN** 客户端请求 `GET /api/summary` - **THEN** 系统 SHALL 返回 JSON 包含 total(总目标数)、up(正常数)、down(异常数)、lastCheckTime(最近一次检查时间) ### Requirement: 目标列表 API 系统 SHALL 提供 `GET /api/targets` 端点,返回所有 typed target 及其最新状态、分组信息和结构化采样数据。 #### Scenario: 获取目标列表 - **WHEN** 客户端请求 `GET /api/targets` - **THEN** 系统 SHALL 返回 JSON 数组,每个元素包含目标基本信息(id、name、group、type、target、interval)、最近一次检查结果(timestamp、success、matched、durationMs、statusDetail、failure)和结构化采样数据 recentSamples(代替原 sparkline) #### Scenario: 目标无历史记录 - **WHEN** 某目标尚未执行过任何拨测 - **THEN** 其 latestCheck 为 null,recentSamples 为空数组 ### Requirement: 历史记录 API 系统 SHALL 提供 `GET /api/targets/:id/history` 端点,支持时间范围筛选和分页返回指定目标的拨测记录。 #### Scenario: 获取指定时间范围内的历史记录 - **WHEN** 客户端请求 `GET /api/targets/1/history?from=ISO&to=ISO&page=1&pageSize=20` - **THEN** 系统 SHALL 返回带分页信息的历史记录,包含 items、total、page、pageSize,按时间倒序排列 #### Scenario: 使用默认分页参数 - **WHEN** 客户端请求 `GET /api/targets/1/history?from=ISO&to=ISO`(未指定 page 或 pageSize) - **THEN** 系统 SHALL 使用默认 page=1, pageSize=20