diff --git a/README.md b/README.md index b23085e..dc5d406 100644 --- a/README.md +++ b/README.md @@ -15,18 +15,21 @@ src/ types.ts 类型定义 config-loader.ts YAML 配置解析与校验 store.ts SQLite 数据存储 - http-runner.ts HTTP 拨测执行 + fetcher.ts HTTP 拨测执行 command-runner.ts 命令行拨测执行 - http-expect.ts HTTP 响应断言 - command-expect.ts 命令行输出断言 - failure.ts 失败信息类型 size.ts 大小单位解析 engine.ts 调度引擎(按 interval 分组、组内并发) + expect/ + http.ts HTTP 响应断言 + command.ts 命令行输出断言 + body.ts HTTP body 断言(JSONPath/XPath/CSS) + failure.ts 失败信息类型 shared/ api.ts 前后端共享 TypeScript 类型 web/ Vite + React 前端 Dashboard components/ UI 组件(卡片、分组、模态框、状态条等) hooks/ 数据轮询和详情管理 hooks + utils/ 前端工具函数 scripts/ 开发、构建和 smoke test 脚本 tests/ Bun test 测试 openspec/ OpenSpec 变更与规格文档 @@ -144,6 +147,8 @@ targets: - `command`: 命令行拨测配置(type 为 command 时必填) - `exec`: 可执行文件名或路径 - `args`: 命令行参数列表 + - `env`: 环境变量覆盖(可选,继承进程环境变量并合并覆盖) + - `cwd`: 工作目录(可选,相对于配置文件所在目录解析,默认 `.`) - `interval`、`timeout`: 覆盖全局默认值 - `expect`: 期望校验 - `status`: 可接受的状态码列表(HTTP) @@ -170,7 +175,7 @@ targets: | `GET /health` | 健康检查 | | `GET /api/summary` | 总览统计(total/up/down/lastCheckTime) | | `GET /api/targets` | 目标列表及最新状态、分组和采样数据 | -| `GET /api/targets/:id/history?from=ISO&to=ISO&page=1` | 指定目标的拨测记录(时间范围 + 分页) | +| `GET /api/targets/:id/history?from=ISO&to=ISO&page=1&pageSize=20` | 指定目标的拨测记录(时间范围 + 分页) | | `GET /api/targets/:id/trend?from=ISO&to=ISO` | 指定目标的按小时聚合趋势 | ### 响应字段 @@ -191,6 +196,20 @@ targets: **HistoryResponse**: `items`(CheckResult[])、`total`、`page`、`pageSize` +### 错误响应 + +API 错误返回 `ApiErrorResponse` 格式: + +```json +{ "error": "描述信息", "status": 400 } +``` + +| 状态码 | 触发场景 | +|--------|---------| +| 400 | 参数格式错误(无效 ID、from/to 缺失或格式错误、page/pageSize 非正整数) | +| 404 | 目标不存在、API 路由未匹配 | +| 405 | 非 GET 方法请求 API 路由 | + ## 代码质量 ```bash diff --git a/openspec/specs/command-checker/spec.md b/openspec/specs/command-checker/spec.md index a1a386e..50d7124 100644 --- a/openspec/specs/command-checker/spec.md +++ b/openspec/specs/command-checker/spec.md @@ -1,6 +1,6 @@ ## Purpose -TBD +定义 Command 类型拨测目标:通过 `type: command` 配置执行本地命令(如进程检查、脚本健康检测),捕获 exit code、stdout、stderr,按 expect 规则校验并生成 matched 判定。 ## Requirements diff --git a/openspec/specs/probe-dashboard/spec.md b/openspec/specs/probe-dashboard/spec.md index e32b039..14b151f 100644 --- a/openspec/specs/probe-dashboard/spec.md +++ b/openspec/specs/probe-dashboard/spec.md @@ -5,7 +5,7 @@ ## Requirements ### Requirement: 总览统计卡片 -Dashboard SHALL 在页面顶部展示总览统计卡片,包含总目标数、正常数和异常数(移除平均耗时)。 +Dashboard SHALL 在页面顶部展示总览统计卡片,包含总目标数、正常数和异常数。 #### Scenario: 展示统计卡片 - **WHEN** 用户打开 Dashboard 页面 @@ -18,6 +18,8 @@ Dashboard SHALL 在页面顶部展示总览统计卡片,包含总目标数、 ### Requirement: 卡片式分组布局 Dashboard SHALL 使用按分组展示的卡片式布局替代表格布局,每个分组包含带统计的分组标题和响应式卡片网格。 +> 卡片布局、响应式网格、卡片内容和交互的详细规范见 `card-dashboard`。 + #### Scenario: 按分组渲染卡片 - **WHEN** 用户打开 Dashboard 页面 - **THEN** 页面 SHALL 按 group 字段将目标分组展示,每组一个区域,"默认分组" 排在最上面 @@ -26,99 +28,19 @@ Dashboard SHALL 使用按分组展示的卡片式布局替代表格布局,每 - **WHEN** 所有目标均属于 "default" 分组 - **THEN** 页面 SHALL 显示一个 "默认分组" 区域,卡片正常展示 -### Requirement: 分组标题展示 -Dashboard SHALL 在每个分组区域上方显示带统计信息的分组标题。 - -#### Scenario: 显示分组统计 -- **WHEN** 渲染分组区域 -- **THEN** 分组标题 SHALL 显示格式为 `分组名 (N个, X UP / Y DOWN)` 的统计信息 - -#### Scenario: default 分组标题 -- **WHEN** 分组名为 "default" -- **THEN** 标题 SHALL 显示 "默认分组" - -### Requirement: 响应式卡片网格 -Dashboard SHALL 使用固定宽度的卡片配合响应式网格布局。 - -#### Scenario: 卡片固定宽度 -- **WHEN** 页面渲染卡片 -- **THEN** 每个卡片 SHALL 固定宽度 280px - -#### Scenario: 响应式列数 -- **WHEN** 视口宽度变化 -- **THEN** 卡片网格 SHALL 自动调整列数,使用 CSS Grid auto-fill 适配可用空间 - -### Requirement: 目标卡片内容 -每个目标卡片 SHALL 展示目标名称、当前状态、类型标签、状态条和迷你耗时趋势线。 - -#### Scenario: 卡片第一行内容 -- **WHEN** 卡片渲染 -- **THEN** 卡片第一行 SHALL 展示状态指示圆点(UP 绿色 / DOWN 红色)、目标名称和类型标签(HTTP / Command) - -#### Scenario: 卡片状态指示圆点 -- **WHEN** 目标最近一次拨测 matched=true -- **THEN** 卡片状态圆点 SHALL 显示为绿色 -- **WHEN** 目标最近一次拨测 matched=false -- **THEN** 卡片状态圆点 SHALL 显示为红色 - -#### Scenario: 卡片状态条可视化 -- **WHEN** 卡片渲染且 recentSamples 数据可用 -- **THEN** 卡片 SHALL 展示一条状态条,每个采样点为一个色块:UP 显示绿色(#1fbf75),DOWN 显示红色(#e5484d),无数据显示灰色(#e2e8f0) - -#### Scenario: 卡片迷你耗时趋势线 -- **WHEN** 卡片渲染且 recentSamples 中有 durationMs 数据 -- **THEN** 卡片 SHALL 展示基于 recharts 的迷你折线图(80x32px),展示最近 30 次检查的耗时趋势 - -### Requirement: 卡片交互 -卡片 SHALL 支持 hover 效果和点击打开模态框。 - -#### Scenario: 卡片 hover 效果 -- **WHEN** 鼠标悬停在卡片上 -- **THEN** 卡片 SHALL 显示上浮效果(阴影加深) - -#### Scenario: 卡片点击打开详情 -- **WHEN** 用户点击某个目标卡片 -- **THEN** 系统 SHALL 打开该目标的详情模态框 - ### Requirement: 目标详情模态框 Dashboard SHALL 提供模态框展示目标详情,包含时间范围筛选、多维统计图和分页检查记录列表。 +> 模态框的时间范围筛选、统计图表、检查结果列表和布局的详细规范见 `target-detail-modal`。 + #### Scenario: 打开模态框 - **WHEN** 用户点击某个目标卡片 - **THEN** 系统 SHALL 弹出模态框,占据视口 80% 宽度,展示该目标的详情 -#### Scenario: 模态框默认时间范围 -- **WHEN** 模态框打开 -- **THEN** 筛选器 SHALL 默认选中"最近 24 小时" - -#### Scenario: 模态框布局 -- **WHEN** 模态框打开 -- **THEN** 模态框 SHALL 占据视口 80% 宽度,图表区在上方展示统计图,检查记录列表在下方展示 - -#### Scenario: 快捷时间范围按钮 -- **WHEN** 模态框渲染 -- **THEN** 筛选栏 SHALL 显示快捷按钮:1h、6h、24h、7d,当前选中的按钮高亮显示 - -#### Scenario: 点击快捷按钮 -- **WHEN** 用户点击快捷按钮(如 "24h") -- **THEN** 筛选器 SHALL 自动设置对应的起止时间,日期选择器显示对应的时间范围,该按钮高亮 - -#### Scenario: 自定义日期时间选择 -- **WHEN** 用户通过日期时间选择器修改起止时间(分钟精度) -- **THEN** 快捷按钮 SHALL 取消高亮,表示当前为自定义时间范围 - #### Scenario: 关闭模态框 - **WHEN** 用户点击模态框关闭按钮或模态框外部区域 - **THEN** 模态框 SHALL 关闭 -#### Scenario: 统计图表 -- **WHEN** 模态框加载完成 -- **THEN** 图表区 SHALL 展示可用率趋势折线图、耗时趋势折线图和状态分布环形图 - -#### Scenario: 检查记录分页 -- **WHEN** 检查记录超过一页 -- **THEN** 检查记录列表底部 SHALL 展示分页器 - ### Requirement: 页面加载与错误状态 Dashboard SHALL 正确处理加载状态和 API 错误,适配卡片式布局。 diff --git a/openspec/specs/single-executable-packaging/spec.md b/openspec/specs/single-executable-packaging/spec.md index e6fe318..efca54f 100644 --- a/openspec/specs/single-executable-packaging/spec.md +++ b/openspec/specs/single-executable-packaging/spec.md @@ -37,9 +37,9 @@ - **WHEN** executable 收到前端根路径请求 - **THEN** 它 SHALL 从 executable 内包含的资源服务前端,且不需要外部 `dist/` 目录 -#### Scenario: 服务嵌入 demo API 和页面 +#### Scenario: 服务嵌入 API 和页面 - **WHEN** 生成的 executable 启动,且浏览器打开前端根路径 -- **THEN** 页面 SHALL 展示同一个 executable 进程中 `/api/demo` 返回的数据 +- **THEN** 页面 SHALL 展示同一个 executable 进程中 `/api/summary` 和 `/api/targets` 返回的数据 #### Scenario: 构建成功后清理中间产物 - **WHEN** 生产构建成功完成并输出 executable @@ -65,11 +65,11 @@ executable MUST 将环境相关运行时配置保留在嵌入的前端和 server #### Scenario: 验证 executable 路由 - **WHEN** 构建验证针对生成的 executable 运行 -- **THEN** 它 SHALL 检查 `/api/demo`、`/health`、前端根路径、静态资源、未知 API、未知静态资源和前端 fallback 请求 +- **THEN** 它 SHALL 检查 `/api/summary`、`/api/targets`、`/health`、前端根路径、静态资源、未知 API、未知静态资源和前端 fallback 请求 #### Scenario: 验证生产模式和响应头 - **WHEN** 构建验证针对生成的 executable 运行 -- **THEN** 它 SHALL 检查 demo 响应处于 production runtime mode,并验证代表性 HTML、JSON 和静态资源响应的缓存或低风险安全 headers +- **THEN** 它 SHALL 检查 API 响应处于 production runtime mode,并验证代表性 HTML、JSON 和静态资源响应的缓存或低风险安全 headers #### Scenario: 完整验证重新构建 executable - **WHEN** 开发者运行完整验证命令