## 新增功能 - 文件管理模块:分类树 + 文件上传/下载/删除 - 文件上传支持拖拽(Dragger)+ 手动上传(customRequest 模式) ## 页面布局统一(参照评测执行页) - 仪表盘/评测对象/评测场景/评测报告 全部改为全高 flex 布局 - 统一内联页头样式(h2 + 竖线分隔 + 描述) - 表格撑满高度、overflow 处理 - 每页添加刷新按钮 ## Bug 修复 - 分类树操作按钮 hover 不可见(CSS 规则缺失) - 文件上传失败(multipart boundary 缺失) - LLM API 响应 content blocks 数组格式支持(_extract_content_from_api_response) - response_time_max_ms 被静默忽略(隐式规则传空 params) - 空 messages 导致 IndexError 崩溃 - poll_reply 异常中止整个 run(缺 try/catch) - engine finally 未关闭 session - 3 个页面 UTC 时间戳解析偏差 8 小时 ## 后端 - EvalEngine: poll_reply 异常保护、空 dialog 保护、session 关闭 - LLM API 响应解析支持 content-block-array 格式 - 隐式 response_time 规则正确传递 max_ms 参数 ## 前端 - api.ts: 移除手动 Content-Type(让浏览器自动添加 boundary) - Files.tsx: customRequest 替代 beforeUpload、布局优化 - index.css: 分类树 hover 规则 - Targets/Scenarios/Home/Reports: 全高布局改造 - 3 个页面时间戳改用 formatDateTime()(修复 UTC 偏差) Co-Authored-By: Claude <noreply@anthropic.com>
7.3 KiB
AgentEvalTool 前端开发日志 — 评测执行页改版
日期: 2026-07-15
基线版本: v0.2.0-dev
状态: 已部署至 t480 开发线
作者: AgentEval Team
一、背景
本次开发在 v0.2.0-dev 基础上,对评测执行页(Runs)进行全面 UI 改版,同时修复了若干历史遗留的基础 Bug。
二、关键 Bug 修复
2.1 index.css 从未被引入(历史遗留)
症状: 所有全局 CSS(动画、hover、布局覆盖规则)完全无效,但无报错提示。
根因: main.tsx 缺少 import './index.css',Vite 不会自动包含未被引用的 CSS 文件,导致该文件从项目创建以来就从未生效。
修复: 在 main.tsx 顶部添加:
import './index.css'
影响: 修复后构建产物首次出现独立 .css 文件(dist/assets/index-*.css),全局 CSS 规则一次性全部生效。
2.2 UTC 时间戳显示偏差 8 小时
症状: 评测记录时间比实际时间早 8 小时(如显示 16:40 实为次日 00:40 北京时间)。
根因(三层叠加):
utc_now() → datetime(UTC)
↓ SQLite 不保存时区
"2026-07-14T16:40:00"(无 Z 后缀)
↓ ECMAScript 规范:无时区字符串按本地时间解析
new Date("2026-07-14T16:40:00") → 北京时间 16:40(比 UTC 多 8 小时)
修复: 在 frontend/web/src/utils/date.ts 添加 toDate() 工具函数:
export function toDate(iso: string): Date {
if (iso.endsWith('Z') || /[+-]\d{2}:\d{2}$/.test(iso)) return new Date(iso)
return new Date(iso + 'Z') // 追加 Z,强制按 UTC 解析
}
所有解析后端时间戳的地方统一使用 toDate(),不再直接 new Date(str)。
注意: 此问题根本解决方式是后端序列化时附带时区(如 datetime.isoformat() → +00:00),前端修复为应急兜底。
2.3 时间过滤器与显示时区不一致
症状: 今天发起的记录显示为正确的北京时间,但选择「当天」时过滤器找不到这些记录。
根因: shortDateTime() 已使用 toDate()(UTC 解析正确),但 RunList 过滤器仍用 new Date(r.started_at) 按本地时间解析,两者时间基准不一致,差了 8 小时导致过滤失败。
修复: 过滤器改用 toDate() 统一时间基准:
const t = r.started_at ? toDate(r.started_at).getTime() : null
三、评测执行页改版详情
3.1 全局布局修复
| 问题 | 修复方案 |
|---|---|
| 页面产生外层滚动条 | App.tsx tab 容器改为 height: 100%, boxSizing: border-box,消除 minHeight + padding 叠加导致的溢出 |
| 页面顶部出现空隙 | html, body { margin: 0; padding: 0 } + 覆盖 Ant Design editable-card Tabs 默认 paddingTop |
| Grid 子元素高度失效 | 增加 gridTemplateRows: '1fr',显式让单行撑满 Grid 高度 |
魔法数字 calc(100vh - 152px) |
用 PageWrapper fullHeight + flex 链代替,彻底去除硬编码数字 |
| 内容区未贴边 | Layout.Content 及所有容器 padding 归零,内容贴合浏览器边缘 |
3.2 左侧面板 — 启动区
- 两行布局: 第一行「评测对象」Select 全宽;第二行「评测场景 + 启动」并排
- Select 增强:
showSearch(输入过滤)+allowClear(清除按钮) - 背景色: 区域改为
colors.bgSubtle(#fafafa)浅底色,与列表区视觉分隔
3.3 左侧面板 — 筛选区
三行布局:
Row 1: [搜索框 full-width]
Row 2: [全部 进行中 成功 失败] [当天][1天][7天][30天] [N条]
时间快捷标签(替代 DatePicker):
- 当天:自然日 00:00 ~ 23:59(本地时间)
- 1天:昨天 + 今天
- 7天:最近 7 天含今天
- 30天:最近 30 天含今天
- 默认选中「当天」;再次点击取消(回到全部时间)
状态分段: 默认「全部」,选中态蓝底白字(ConfigProvider Segmented token)
时间标签颜色: 激活态蓝色实心背景 + 白字;未激活态深灰边框 + 深色文字
3.4 左侧面板 — 列表
| 项目 | 改动 |
|---|---|
| 行结构 | 三行固定(名称/元信息/进度条),等高不抖动 |
| 进度条 | pending/running 显示蓝色动态进度(来自 liveProgress);completed 显示通过率色阶 |
| 分页 | 每页 10 条,底部固定分页栏(始终占位,布局稳定) |
| 排序 | 去掉错误的 .reverse(),API 已按 started_at DESC 返回 |
| hover | 去掉 onMouseEnter/Leave 直接操作 DOM,改为 CSS .run-row:hover |
3.5 右侧面板 — Tab 滚动
问题: 三个 Tab(实时对话、规则总览、用例明细)内容区无法独立滚动。
根因: Ant Design v5 使用 CSS-in-JS(emotion)在运行时注入样式,覆盖了静态 CSS 文件中的 flex/height 规则,导致 Tab 内容区高度链断裂。
最终方案(导航与内容分离):
Tabs(.nav-only-tabs):只渲染导航头,内容区 display: none
↓
三个内容 div(直接 flex 子元素):
flex: 1, min-height: 0, overflowY: auto
→ 高度由 flex 算法直接确定,不经过 Ant Design 内部 DOM
.ant-tabs.nav-only-tabs .ant-tabs-content-holder {
display: none !important;
}
三个 Tab 的滚动各自独立,互不干扰。
四、其他优化
| 项目 | 内容 |
|---|---|
| 代码去重 | 提取 startRun() 函数,消除 handleStart 与 onRerun 重复逻辑 |
| 死代码清理 | 删除 sessionReducer 中从未被 dispatch 的 SET_RUN action |
| 工具函数复用 | RunList 改用 shortDateTime / elapsedStr,删除本地重复的 formatStart / durationStr |
| 类型安全 | run.summary as any 改为 Record<string, unknown> 类型收窄 |
| Bundle 瘦身 | 用时间标签替代 DatePicker,vendor chunk 缩小约 107KB |
| CSS 组件化 | Segmented 选中态、Run list hover 统一移入 ConfigProvider token / CSS 类,不再散落在组件 inline style |
五、t480 部署记录
部署前环境补全(首次排查发现):
.env 只有 1 个键(AGENTEVAL_ALLOWED_ORIGINS),缺失以下配置:
AGENTEVAL_API_KEY=
AGENTEVAL_OPENCLAW_UPSTREAM=http://openclaw-eval:18789
AGENTEVAL_OPENCLAW_WS_UPSTREAM=ws://openclaw-eval:18789
AGENTEVAL_OPENCLAW_PROXY_USER=agenteval
AGENTEVAL_OPENCLAW_AUTH_TOKEN=change-me-in-production
已通过 SSH 补全,OpenClaw 代理功能恢复正常。
六、遗留问题
| 问题 | 状态 | 说明 |
|---|---|---|
| case-001 无发送气泡 | 待查 | 只有智能体回复,无用户发送内容;需确认 DB 中 turn.sent_message 字段内容 |
| UTC 时间后缀 | 待优化 | 当前前端追加 Z 兜底;根本修复需后端序列化附带时区标记 |
七、文件变更清单
前端
src/main.tsx— 添加import './index.css'src/index.css— html/body 重置、nav-only-tabs、TabBar padding 覆盖、Segmented 样式src/App.tsx— 布局修复(overflow、padding),Segmented tokensrc/components/PageWrapper.tsx— 新增fullHeightpropsrc/pages/Runs.tsx— 完整重构:布局、启动区、内联头部、Tab 分离src/components/RunList.tsx— 筛选区三行布局、时间标签、toDate 对齐、分页src/utils/date.ts— 新增toDate()(export),修复时区src/hooks/sessionReducer.ts— 删除SET_RUN死代码