From 9c564b575ee29fd586971f2213aa20f5533e8910 Mon Sep 17 00:00:00 2001 From: sinohqb Date: Tue, 28 Jul 2026 17:41:08 +0800 Subject: [PATCH] feat(frontend): v0.4 login page, dashboard rebuild, reports UX, keep-alive refresh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 登录页 + App 鉴权门 + X-Auth-Token 拦截器 + 菜单头部退出按钮 - 仪表盘重构:6 指标卡 / 趋势图 + 场景表现 / 最近记录 + 快捷操作 + 来源分布 - Reports 页重做:场景筛选、富选项下拉、allowClear、一键重置、同场景对比约束 - useOnTabActive:标签页激活自动刷新(根治 AI 助手评测记录"消失") - ModelConfigs 12 列合并为 6 列;来源 Tag;chunk 告警阈值修正并记录原因 --- frontend/web/package-lock.json | 4 +- frontend/web/package.json | 2 +- frontend/web/src/App.tsx | 52 ++++- frontend/web/src/api.ts | 52 +++++ frontend/web/src/components/RunList.tsx | 12 +- frontend/web/src/hooks/useOnTabActive.ts | 23 +++ frontend/web/src/pages/Home.tsx | 244 +++++++++++++++-------- frontend/web/src/pages/Login.tsx | 52 +++++ frontend/web/src/pages/ModelConfigs.tsx | 150 +++++++------- frontend/web/src/pages/Reports.tsx | 237 +++++++++++++++------- frontend/web/src/pages/Runs.tsx | 5 + frontend/web/src/tokens.ts | 12 ++ frontend/web/vite.config.ts | 12 +- 13 files changed, 626 insertions(+), 231 deletions(-) create mode 100644 frontend/web/src/hooks/useOnTabActive.ts create mode 100644 frontend/web/src/pages/Login.tsx diff --git a/frontend/web/package-lock.json b/frontend/web/package-lock.json index b68bf62..c08e8fa 100644 --- a/frontend/web/package-lock.json +++ b/frontend/web/package-lock.json @@ -1,12 +1,12 @@ { "name": "agenteval-web", - "version": "0.3.0-dev", + "version": "0.4.0-dev", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "agenteval-web", - "version": "0.3.0-dev", + "version": "0.4.0-dev", "dependencies": { "@ant-design/charts": "^2.6.7", "@ant-design/icons": "^6.3.2", diff --git a/frontend/web/package.json b/frontend/web/package.json index 8d7bbc0..8117c1e 100644 --- a/frontend/web/package.json +++ b/frontend/web/package.json @@ -1,6 +1,6 @@ { "name": "agenteval-web", - "version": "0.3.0-dev", + "version": "0.4.0-dev", "private": true, "type": "module", "scripts": { diff --git a/frontend/web/src/App.tsx b/frontend/web/src/App.tsx index 9134e89..c8337d5 100644 --- a/frontend/web/src/App.tsx +++ b/frontend/web/src/App.tsx @@ -1,6 +1,6 @@ -import { lazy, Suspense, useEffect } from 'react' +import { lazy, Suspense, useEffect, useState } from 'react' import { useLocation, useNavigate } from 'react-router-dom' -import { Layout, Menu, Spin } from 'antd' +import { Layout, Menu, Spin, Button, Tooltip } from 'antd' import type { MenuProps } from 'antd' import { DashboardOutlined, @@ -11,8 +11,11 @@ import { RobotOutlined, FolderOpenOutlined, CloudServerOutlined, + LogoutOutlined, } from '@ant-design/icons' import TabBar from './components/TabBar' +import LoginPage from './pages/Login' +import { authApi, authToken, setOnUnauthorized } from './api' import { useTabStore, type TabItem } from './stores/tabStore' import { colors } from './tokens' import type { ReactNode } from 'react' @@ -68,10 +71,30 @@ const menuItems: MenuProps['items'] = routeConfigs.map((r) => ({ label: r.name, })) +type AuthState = 'checking' | 'login' | 'ready' + function App() { const location = useLocation() const navigate = useNavigate() const { tabs, activeKey, openTab, setActiveTab } = useTabStore() + const [authState, setAuthState] = useState('checking') + const [authRequired, setAuthRequired] = useState(false) + + useEffect(() => { + setOnUnauthorized(() => setAuthState('login')) + authApi.status() + .then((res) => { + setAuthRequired(res.data.auth_required) + setAuthState(res.data.authenticated ? 'ready' : 'login') + }) + .catch(() => setAuthState('ready')) // 后端不可达时不锁死界面,由具体请求报错 + return () => setOnUnauthorized(null) + }, []) + + const logout = () => { + authToken.clear() + setAuthState('login') + } useEffect(() => { const config = routeConfigs.find((r) => r.path === location.pathname) @@ -102,6 +125,18 @@ function App() { navigate(key) } + if (authState === 'checking') { + return ( +
+ +
+ ) + } + + if (authState === 'login') { + return setAuthState('ready')} /> + } + return ( AgentEvalTool + {authRequired && ( + +