## Purpose

定义 TanStack Query 数据层：QueryClient 配置、queryKey 工厂、轮询策略、条件查询和开发调试面板。

## Requirements

### Requirement: TanStack Query 数据层
前端 SHALL 使用 TanStack Query（@tanstack/react-query）管理所有 API 请求，数据层代码 SHALL 按职责拆分为独立 hook 文件。

#### Scenario: QueryClient 配置
- **WHEN** 应用启动
- **THEN** 系统 SHALL 创建 QueryClient，默认配置 retry=1、refetchOnWindowFocus=true、staleTime=5000

#### Scenario: QueryClientProvider 挂载
- **WHEN** 应用渲染
- **THEN** 根组件 SHALL 包裹在 QueryClientProvider 中，提供 QueryClient 实例

### Requirement: queryKey 工厂
系统 SHALL 提供统一的 queryKey 工厂函数，确保 queryKey 的唯一性和一致性。

#### Scenario: summary queryKey
- **WHEN** 查询 summary 数据
- **THEN** queryKey SHALL 为 ["summary"]

#### Scenario: targets queryKey
- **WHEN** 查询 targets 数据
- **THEN** queryKey SHALL 为 ["targets"]

#### Scenario: trend queryKey
- **WHEN** 查询某目标的趋势数据
- **THEN** queryKey SHALL 为 ["trend", targetId, from, to]

#### Scenario: history queryKey
- **WHEN** 查询某目标的历史记录
- **THEN** queryKey SHALL 为 ["history", targetId, from, to, page]

#### Scenario: meta queryKey
- **WHEN** 查询 meta 数据
- **THEN** queryKey SHALL 为 ["meta"]

### Requirement: Meta 查询
系统 SHALL 提供 `useMeta` hook 查询系统元数据。

#### Scenario: meta 查询配置
- **WHEN** 应用启动
- **THEN** `useMeta` SHALL 请求 `/api/meta`，配置 `staleTime: Infinity`（应用生命周期内只请求一次）

#### Scenario: meta 数据返回
- **WHEN** meta 查询成功
- **THEN** hook SHALL 返回 `MetaResponse` 类型数据，包含 `checkerTypes` 和 `version` 字段

### Requirement: Meta 版本数据
前端 SHALL 通过现有 `useMeta` hook 获取系统版本元数据，并将 `MetaResponse.version` 提供给需要展示版本号的组件。

#### Scenario: useMeta 返回版本字段
- **WHEN** `useMeta` 请求 `/api/meta` 成功
- **THEN** hook 返回的数据 SHALL 符合 `MetaResponse`，包含 `checkerTypes` 和 `version` 字段

#### Scenario: Header 复用 meta 查询
- **WHEN** Header 需要展示应用版本号
- **THEN** Header SHALL 复用 `useMeta` 的 `queryKey` 为 `["meta"]` 的查询结果，不得新增重复的版本专用请求

### Requirement: Hook 文件拆分
数据层 hook SHALL 按职责拆分为独立文件。

#### Scenario: 全局查询 hook 文件
- **WHEN** 开发者需要使用全局面板级查询
- **THEN** `useSummary`、`useTargets`、`useMeta` SHALL 从 `hooks/use-queries.ts` 导出

#### Scenario: Drawer 状态 hook 文件
- **WHEN** 开发者需要使用 Drawer 状态管理
- **THEN** `useTargetDetail` SHALL 从 `hooks/use-target-detail.ts` 导出

#### Scenario: fetchJson 不导出
- **WHEN** 数据层内部需要 fetch 封装
- **THEN** `fetchJson` SHALL 定义在 `use-queries.ts` 内部，不作为公共 API 导出

#### Scenario: queryKeys 不导出
- **WHEN** 数据层内部需要 query key
- **THEN** `queryKeys` 对象 SHALL 定义在 `use-queries.ts` 内部，不作为公共 API 导出

### Requirement: Summary 轮询查询
系统 SHALL 使用 useQuery 实现总览统计的自动轮询。

#### Scenario: summary 动态轮询间隔
- **WHEN** Dashboard 页面处于打开状态
- **THEN** 系统 SHALL 按用户选择的刷新间隔自动请求数据，`useDashboard` hook SHALL 接受 `refetchInterval` 参数（`false | number`），由调用方传入

#### Scenario: summary 禁用自动轮询
- **WHEN** 用户选择"手动"刷新模式
- **THEN** `useDashboard` SHALL 接收 `refetchInterval: false`，禁用自动轮询

#### Scenario: summary 后台刷新
- **WHEN** 页面处于后台标签页
- **THEN** 系统 SHALL 暂停轮询（refetchIntervalInBackground=false）

### Requirement: Targets 轮询查询
系统 SHALL 使用 useQuery 实现目标列表的自动轮询。

#### Scenario: targets 动态轮询间隔
- **WHEN** Dashboard 页面处于打开状态
- **THEN** 系统 SHALL 按用户选择的刷新间隔自动请求数据，轮询间隔与 summary 查询保持一致

### Requirement: 条件查询
详情指标和历史记录查询 SHALL 使用 enabled 条件控制。指标查询 SHALL 在目标和时间范围有效时触发；历史记录查询 SHALL 仅在目标、时间范围有效且"记录"Tab 激活后触发。

#### Scenario: 未选中目标时不请求
- **WHEN** 用户未点击任何目标表格行
- **THEN** metrics 和 history 的 useQuery SHALL enabled=false，不发起请求

#### Scenario: 打开 Drawer 默认只请求指标
- **WHEN** 用户点击目标表格行并打开 Drawer
- **THEN** metrics 的 useQuery SHALL enabled=true 并自动发起请求，history 的 useQuery SHALL enabled=false 且不发起请求

#### Scenario: 激活记录 Tab 时请求历史记录
- **WHEN** 用户切换到"记录"Tab 且目标与时间范围有效
- **THEN** history 的 useQuery SHALL enabled=true，并请求当前页码对应的 `/api/targets/:id/history` 数据

#### Scenario: 概览 Tab 时间范围变化时不请求历史记录
- **WHEN** 用户在"概览"Tab 修改时间范围
- **THEN** metrics 的 useQuery SHALL 因 queryKey 变化自动重新请求，history 的 useQuery SHALL 保持 enabled=false 且不发起请求

#### Scenario: 记录 Tab 时间范围变化时重新请求历史记录
- **WHEN** 用户在"记录"Tab 修改时间范围
- **THEN** metrics 和 history 的 useQuery SHALL 因 queryKey 变化自动重新请求，并将 history 页码重置为 1

### Requirement: 开发调试面板
开发环境下 SHALL 挂载 TanStack Query Devtools。

#### Scenario: 开发环境显示 Devtools
- **WHEN** 应用在开发模式下运行
- **THEN** 页面 SHALL 显示 ReactQueryDevtools 浮动面板

#### Scenario: 生产环境排除 Devtools
- **WHEN** 应用在生产模式下构建
- **THEN** ReactQueryDevtools SHALL 不被包含在产物中
