fix(auth): highlight failed server connections

This commit is contained in:
2026-07-22 23:13:55 +08:00
parent b01928a5e4
commit a564d48154
5 changed files with 72 additions and 1 deletions

View File

@@ -5,7 +5,7 @@ import {
IconFile, IconFolder, IconPlus, IconRefresh, IconRobot, IconSearch, IconSettings,
} from '@arco-design/web-react/icon'
import {
ApiError, createAISession, createCron, createProject, createTask, fetchAISessions, fetchExperts,
ApiError, checkServerConnection, createAISession, createCron, createProject, createTask, fetchAISessions, fetchExperts,
fetchProjects, fetchWorkspace, login, updateTask, uploadSource,
type AISession, type ApiSession, type Expert, type Project, type Workspace,
} from './api'
@@ -14,6 +14,7 @@ const { Text, Title } = Typography
type View = 'home' | 'tasks' | 'notes' | 'ai' | 'more'
type DockSide = 'left' | 'right'
type Action = 'project' | 'task' | 'cron' | null
type ConnectionStatus = 'checking' | 'online' | 'offline'
const navItems: Array<{ id: View; label: string; icon: React.ReactNode }> = [
{ id: 'home', label: '项目', icon: <IconApps /> },
@@ -311,6 +312,26 @@ function Login({ onLogin }: { onLogin: (session: ApiSession) => void }) {
const [password, setPassword] = useState('password123')
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
const [connection, setConnection] = useState<ConnectionStatus>('checking')
useEffect(() => {
const controller = new AbortController()
const timer = window.setTimeout(() => void checkConnection(controller.signal), 300)
return () => {
controller.abort()
window.clearTimeout(timer)
}
}, [server])
async function checkConnection(signal?: AbortSignal) {
setConnection('checking')
try {
const online = await checkServerConnection(server, signal)
if (!signal?.aborted) setConnection(online ? 'online' : 'offline')
} catch (requestError) {
if (!(requestError instanceof DOMException && requestError.name === 'AbortError')) setConnection('offline')
}
}
async function submitLogin() {
if (loading) return
@@ -332,6 +353,11 @@ function Login({ onLogin }: { onLogin: (session: ApiSession) => void }) {
<Title heading={3}>AI Mini</Title>
<Text type="secondary"></Text>
<label><Input value={server} onChange={setServer} /></label>
<div className={`mini-connection ${connection}`} role="status">
<i />
<strong>{connection === 'checking' ? '正在检查' : connection === 'online' ? '连接正常' : '连接异常'}</strong>
<button type="button" onClick={() => void checkConnection()}>{connection === 'checking' ? '检查中' : '重新检查'}</button>
</div>
<label><Input value={email} onChange={setEmail} /></label>
<label><Input.Password value={password} onChange={setPassword} /></label>
{error ? <Alert type="error" content={error} /> : null}