1
0

feat: 优化前端布局为流动式响应式设计

- 移除 Dashboard max-width 限制,充分利用屏幕空间
- Summary Cards 和 Target Cards 改为 Flexbox wrap 流动布局
- 卡片固定宽度 280px,根据页面宽度自动调整单行数量
- 添加平滑过渡动画效果(0.3s ease)
- 移除移动端媒体查询覆盖规则
- 同步更新 card-dashboard 规格文档
This commit is contained in:
2026-05-11 16:26:51 +08:00
parent 80d5f4cdf4
commit d873484938
3 changed files with 59 additions and 37 deletions

View File

@@ -170,13 +170,13 @@ targets:
## API 端点
| 端点 | 说明 |
| ----------------------------------------------------- | --------------------------------------- |
| `GET /health` | 健康检查 |
| `GET /api/summary` | 总览统计total/up/down/lastCheckTime |
| `GET /api/targets` | 目标列表及最新状态、分组和采样数据 |
| `GET /api/targets/:id/history?from=ISO&to=ISO&page=1&pageSize=20` | 指定目标的拨测记录(时间范围 + 分页) |
| `GET /api/targets/:id/trend?from=ISO&to=ISO` | 指定目标的按小时聚合趋势 |
| 端点 | 说明 |
| ----------------------------------------------------------------- | --------------------------------------- |
| `GET /health` | 健康检查 |
| `GET /api/summary` | 总览统计total/up/down/lastCheckTime |
| `GET /api/targets` | 目标列表及最新状态、分组和采样数据 |
| `GET /api/targets/:id/history?from=ISO&to=ISO&page=1&pageSize=20` | 指定目标的拨测记录(时间范围 + 分页) |
| `GET /api/targets/:id/trend?from=ISO&to=ISO` | 指定目标的按小时聚合趋势 |
### 响应字段
@@ -204,11 +204,11 @@ API 错误返回 `ApiErrorResponse` 格式:
{ "error": "描述信息", "status": 400 }
```
| 状态码 | 触发场景 |
|--------|---------|
| 400 | 参数格式错误(无效 ID、from/to 缺失或格式错误、page/pageSize 非正整数) |
| 404 | 目标不存在、API 路由未匹配 |
| 405 | 非 GET 方法请求 API 路由 |
| 状态码 | 触发场景 |
| ------ | ----------------------------------------------------------------------- |
| 400 | 参数格式错误(无效 ID、from/to 缺失或格式错误、page/pageSize 非正整数) |
| 404 | 目标不存在、API 路由未匹配 |
| 405 | 非 GET 方法请求 API 路由 |
## 代码质量

View File

@@ -20,15 +20,27 @@ Dashboard SHALL 按分组展示所有拨测目标,每个分组包含带统计
- **THEN** 分组标题 SHALL 显示 "默认分组"
### Requirement: 响应式卡片网格
Dashboard SHALL 使用固定宽度的卡片配合响应式网格布局
Dashboard SHALL 使用固定宽度的卡片配合 Flexbox 流动布局,容器无最大宽度限制
#### Scenario: Dashboard 容器占满宽度
- **WHEN** 用户打开 Dashboard 页面
- **THEN** Dashboard 容器 SHALL 占满浏览器宽度,不设置 max-width 限制
#### Scenario: 卡片固定宽度
- **WHEN** 页面渲染卡片
- **THEN** 每个卡片 SHALL 固定宽度 280px
- **WHEN** 页面渲染卡片(包括 Summary Cards 和 Target Cards
- **THEN** 每个卡片 SHALL 固定宽度 280px,使用 `flex-shrink: 0` 防止收缩
#### Scenario: 响应式列数
#### Scenario: 流动式布局
- **WHEN** 视口宽度变化
- **THEN** 卡片网格 SHALL 自动调整列数,使用 CSS Grid auto-fill 适配可用空间
- **THEN** 卡片网格 SHALL 使用 Flexbox wrap 自动换行,根据可用宽度调整单行卡片数量
#### Scenario: 卡片左对齐
- **WHEN** 页面渲染卡片网格
- **THEN** 卡片 SHALL 左对齐排列,右侧自然留白
#### Scenario: 统一间距
- **WHEN** 页面渲染 Summary Cards 和 Target Cards
- **THEN** 两种卡片网格 SHALL 使用相同的 gap 间距16px
### Requirement: 目标卡片内容
每个目标卡片 SHALL 展示目标名称、当前状态、类型标签、状态条和迷你耗时趋势线。
@@ -61,3 +73,14 @@ Dashboard SHALL 使用固定宽度的卡片配合响应式网格布局。
#### Scenario: 卡片点击打开详情
- **WHEN** 用户点击某个目标卡片
- **THEN** 系统 SHALL 打开该目标的详情模态框
### Requirement: 平滑过渡动画
卡片 SHALL 具有平滑的交互过渡动画效果。
#### Scenario: 卡片悬停动画
- **WHEN** 鼠标悬停在卡片上
- **THEN** 卡片 SHALL 平滑过渡显示上浮效果(阴影加深、轻微上移),过渡时长 0.3s
#### Scenario: 布局变化过渡
- **WHEN** 视口宽度变化导致卡片重新排列
- **THEN** 卡片位置变化 SHALL 有平滑的过渡动画

View File

@@ -22,9 +22,8 @@ body {
}
.dashboard {
max-width: 1200px;
margin: 0 auto;
padding: 32px 24px;
width: 100%;
}
.dashboard-header {
@@ -54,18 +53,28 @@ body {
}
.summary-cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
display: flex;
flex-wrap: wrap;
gap: 16px;
margin-bottom: 32px;
}
.summary-card {
width: 280px;
flex-shrink: 0;
padding: 20px;
border: 1px solid rgba(49, 83, 126, 0.12);
border-radius: 16px;
background: rgba(255, 255, 255, 0.85);
box-shadow: 0 4px 16px rgba(34, 57, 91, 0.08);
transition:
transform 0.3s ease,
box-shadow 0.3s ease;
}
.summary-card:hover {
box-shadow: 0 8px 32px rgba(34, 57, 91, 0.12);
transform: translateY(-4px);
}
.card-value {
@@ -118,12 +127,14 @@ body {
}
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.target-card {
width: 280px;
flex-shrink: 0;
padding: 16px;
border: 1px solid rgba(49, 83, 126, 0.12);
border-radius: 12px;
@@ -131,8 +142,8 @@ body {
box-shadow: 0 2px 8px rgba(34, 57, 91, 0.06);
cursor: pointer;
transition:
box-shadow 0.15s,
transform 0.15s;
box-shadow 0.3s ease,
transform 0.3s ease;
}
.target-card:hover {
@@ -566,18 +577,6 @@ body {
padding: 16px;
}
.summary-cards {
grid-template-columns: repeat(2, 1fr);
}
.card-grid {
grid-template-columns: 1fr;
}
.target-card {
width: 100%;
}
.modal-content {
width: 95vw;
max-height: 90vh;