From 0ad5881259ba0ac6a13af35a44ed1cbc130ed5b4 Mon Sep 17 00:00:00 2001 From: kyx236 Date: Sat, 7 Feb 2026 14:29:55 +0800 Subject: [PATCH] feat(header): Display active S2A profile information in header - Add Server icon import from lucide-react for profile display - Import useConfig hook and S2AProfile type for configuration access - Implement activeProfile state to track currently selected S2A profile - Add useEffect hook to fetch and match S2A profiles against current API base configuration - Replace spacer div with active profile information display component - Show profile name and API base URL when profile is matched - Display API base URL directly when configured but profile not found - Add responsive styling with dark mode support for profile info badge - Use truncation and flex-shrink to prevent layout overflow on smaller screens - Provides users with clear visibility of which S2A profile is currently active --- frontend/src/components/layout/Header.tsx | 40 +++++++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/layout/Header.tsx b/frontend/src/components/layout/Header.tsx index 8240403..6f21ab7 100644 --- a/frontend/src/components/layout/Header.tsx +++ b/frontend/src/components/layout/Header.tsx @@ -1,6 +1,8 @@ -import { Menu, Moon, Sun, Database, UserPlus } from 'lucide-react' +import { Menu, Moon, Sun, Database, UserPlus, Server } from 'lucide-react' import { useState, useEffect } from 'react' import { useTeamStatus } from '../../hooks/useTeamStatus' +import { useConfig } from '../../hooks/useConfig' +import type { S2AProfile } from '../../types' interface HeaderProps { onMenuClick: () => void @@ -10,6 +12,25 @@ interface HeaderProps { export default function Header({ onMenuClick, isConnected = false }: HeaderProps) { const [isDark, setIsDark] = useState(false) const teamStatus = useTeamStatus() + const { config } = useConfig() + const [activeProfile, setActiveProfile] = useState(null) + + // 匹配当前活动配置对应的 profile 名称 + useEffect(() => { + if (!config.s2a.apiBase) { + setActiveProfile(null) + return + } + fetch('/api/s2a/profiles') + .then(res => res.json()) + .then(data => { + if (data.code === 0 && data.data) { + const match = (data.data as S2AProfile[]).find(p => p.api_base === config.s2a.apiBase) + setActiveProfile(match || null) + } + }) + .catch(() => setActiveProfile(null)) + }, [config.s2a.apiBase]) useEffect(() => { // Check for saved theme preference or system preference @@ -54,8 +75,21 @@ export default function Header({ onMenuClick, isConnected = false }: HeaderProps - {/* Spacer */} -
+ {/* Active S2A Profile Info */} +
+ {activeProfile ? ( +
+ + {activeProfile.name} + {activeProfile.api_base} +
+ ) : config.s2a.apiBase ? ( +
+ + {config.s2a.apiBase} +
+ ) : null} +
{/* Team Status Indicators */} {teamStatus.isProcessing && (