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 && ( + +