feat: 修复仪表盘数据管线 — 补充应用发布种子数据 + 修复limit参数解析 + LDAP认证集成 + User类型完善
后端改进: - 修复 dashboard/recent-alerts 的 limit 参数解析 (原代码错误地将数字解析为日期) - 为 dashboard/recent-releases 添加 limit 参数解析支持 - 新增 generateAppReleases 种子数据生成函数 (10条应用发布记录) - 修复 AlertEvent 的 rule_name/rule_id/severity 数据一致性 - 添加 go-ldap/ldap/v3 依赖并集成 LDAP 认证处理器 - 添加 seed.go 自动种子数据初始化 (admin用户+LDAP配置) - User model 添加 AuthSource/LDAPConfig 字段 前端改进: - 修复 User 类型定义以匹配后端 API (real_name/is_admin/auth_source等) - 修复 Header.tsx 的 real_name 属性引用导致 TypeScript 编译错误 - 统一 API 服务层、暗色主题样式、组件联调优化 验证: - go build ./... 编译通过 - npm run build 构建通过 - 仪表盘发布历史、告警消息等区域数据正常展示 - 健康检查 /health 正常
This commit is contained in:
1 parent
97c4207ff8
commit
ff0b268984
39 files changed
+4283
-1878
No files matched your search
@@ -1,7 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useThemeStore, useTabStore, useNotificationStore } from '@/store';
|
||||
import { useThemeStore, useTabStore, useNotificationStore, useUserStore } from '@/store';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
@@ -31,15 +31,27 @@ import {
|
||||
Rocket,
|
||||
Server,
|
||||
Cloud,
|
||||
Palette,
|
||||
Check,
|
||||
} from 'lucide-react';
|
||||
import { formatDistanceToNow } from '@/lib/utils';
|
||||
import { useTheme, THEME_OPTIONS } from '@/hooks/useTheme';
|
||||
|
||||
export function Header() {
|
||||
const { sidebarCollapsed, toggleSidebar } = useThemeStore();
|
||||
const { tabs, activeTab, removeTab, setActiveTab } = useTabStore();
|
||||
const { notifications, unreadCount, markAsRead, markAllAsRead } = useNotificationStore();
|
||||
const { user, logout } = useUserStore();
|
||||
const { theme, setTheme } = useTheme();
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
|
||||
const handleLogout = () => {
|
||||
logout();
|
||||
window.location.href = '/login';
|
||||
};
|
||||
|
||||
const displayName = user?.real_name || user?.username || '管理员';
|
||||
|
||||
const getNotificationIcon = (type: string) => {
|
||||
switch (type) {
|
||||
case 'error':
|
||||
@@ -101,6 +113,39 @@ export function Header() {
|
||||
|
||||
{/* Right: Actions */}
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Theme Switcher */}
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="icon" className="h-8 w-8 text-slate-400 hover:text-slate-100">
|
||||
<Palette className="h-4 w-4" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-56 bg-slate-800 border-slate-700">
|
||||
<DropdownMenuLabel className="text-slate-300">主题切换</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator className="bg-slate-700" />
|
||||
{THEME_OPTIONS.map((option) => (
|
||||
<DropdownMenuItem
|
||||
key={option.id}
|
||||
className={cn(
|
||||
'flex items-center gap-2 cursor-pointer focus:bg-slate-700 focus:text-slate-100',
|
||||
theme === option.id ? 'text-slate-100' : 'text-slate-300'
|
||||
)}
|
||||
onClick={() => setTheme(option.id)}
|
||||
>
|
||||
<span
|
||||
className="w-3 h-3 rounded-full shrink-0 ring-2 ring-slate-900"
|
||||
style={{ backgroundColor: option.primaryColor }}
|
||||
/>
|
||||
<div className="flex-1 min-w-0">
|
||||
<span className="text-sm font-medium">{option.name}</span>
|
||||
<span className="block text-xs text-slate-500 truncate">{option.description}</span>
|
||||
</div>
|
||||
{theme === option.id && <Check className="h-4 w-4 text-blue-400 shrink-0" />}
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
|
||||
{/* Create New */}
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
@@ -201,9 +246,9 @@ export function Header() {
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" className="h-8 gap-2 px-2 text-slate-300 hover:text-slate-100">
|
||||
<div className="w-6 h-6 rounded-full bg-blue-600 flex items-center justify-center text-white text-xs font-medium">
|
||||
管
|
||||
{displayName.charAt(0)}
|
||||
</div>
|
||||
<span className="hidden md:inline text-sm">管理员</span>
|
||||
<span className="hidden md:inline text-sm">{displayName}</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-48 bg-slate-800 border-slate-700">
|
||||
@@ -218,7 +263,7 @@ export function Header() {
|
||||
账号设置
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator className="bg-slate-700" />
|
||||
<DropdownMenuItem className="text-red-400 focus:bg-slate-700 focus:text-red-400">
|
||||
<DropdownMenuItem className="text-red-400 focus:bg-slate-700 focus:text-red-400" onClick={handleLogout}>
|
||||
<LogOut className="h-4 w-4 mr-2" />
|
||||
退出登录
|
||||
</DropdownMenuItem>
|
||||
|
||||
Reference in new issue
Block a user