feat: v0.4.0 主题切换 + LLM 全面优化 + 登录会话 + 用户管理/LDAP
主题: - 深色/浅色/跟随系统(useTheme:本地缓存先行+远端同步+matchMedia), 侧边栏快捷切换,设置页三档即选即生效 LLM(参考 opsxdb/aiops): - llm.Client.ChatStream 流式(SSE 增量解析,透传 reasoning_content, ctx 控制超时);POST /api/ai/chat/stream(平台实时数据注入降幻觉, 未配 LLM 降级规则 JSON,指令解析 action 不变) - test-llm 支持草稿直测(保存前验证,apiKey 空/掩码回退已存) - 发布失败自动 AI 分析日志尾部(结论/根因/建议),发布记录与发布 Tab 展示分析卡片 - 设置页 Provider 预设(DeepSeek/GLM/GLM编码/Qwen/Kimi/Ollama/自定义) 自动填 endpoint+模型+获取 Key 直达链接 登录与会话: - HMAC 签名 token(7 天,密钥派生自 encryption.key); authMiddleware 保护 /api/*(豁免登录/健康/SSE日志流/入站webhook) - 登录页 /login + 未登录跳转 + 登出;401 自动清理跳登录 用户管理与 LDAP(借鉴 LokiStack): - /users 页面:本地用户 CRUD、一次性密码、角色切换、来源徽章 (本地·蓝 | LDAP导入·紫);LDAP 导入按钮仅在启用且配置齐备时显示 - LDAP 配置卡(未启用仅提示语)、测试连接草稿直测+可选测试账号 - go-ldap:管理 Bind/用户搜索(防注入)/用户 DN 直连验证; 批量导入冲突策略(已LDAP跳过/本地同名转LDAP/新建); 登录分流本地 argon2id 或 LDAP 目录验证 + 首登 JIT 建号
This commit is contained in:
1 parent
555934cc64
commit
97193eb090
24 files changed
+2422
-98
No files matched your search
@@ -13,18 +13,24 @@ import {
|
||||
Webhook,
|
||||
CloudSync,
|
||||
Puzzle,
|
||||
Settings
|
||||
Settings,
|
||||
Users,
|
||||
Sun,
|
||||
Moon,
|
||||
LogOut,
|
||||
} from 'lucide-react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { apiClient } from '@/lib/api';
|
||||
import { useTheme } from '@/providers/theme';
|
||||
|
||||
type ModuleType = 'pipelines' | 'gitops' | 'batch-release' | 'release-records' | 'environments' | 'credentials' | 'build-nodes' | 'tools' | 'jenkins-import' | 'webhooks' | 'plugins' | 'settings';
|
||||
type ModuleType = 'pipelines' | 'gitops' | 'batch-release' | 'release-records' | 'environments' | 'credentials' | 'build-nodes' | 'tools' | 'jenkins-import' | 'webhooks' | 'plugins' | 'users' | 'settings';
|
||||
|
||||
interface SidebarProps {
|
||||
activeModule: ModuleType;
|
||||
onModuleChange: (module: ModuleType) => void;
|
||||
collapsed: boolean;
|
||||
onToggleCollapse: () => void;
|
||||
onLogout?: () => void;
|
||||
}
|
||||
|
||||
const menuGroups: { label: string; items: { id: ModuleType; label: string; icon: typeof GitBranch; badge: string | null }[] }[] = [
|
||||
@@ -57,18 +63,20 @@ const menuGroups: { label: string; items: { id: ModuleType; label: string; icon:
|
||||
label: '系统',
|
||||
items: [
|
||||
{ id: 'plugins', label: '插件市场', icon: Puzzle, badge: '12' },
|
||||
{ id: 'users', label: '用户管理', icon: Users, badge: null },
|
||||
{ id: 'settings', label: '系统设置', icon: Settings, badge: null },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default function Sidebar({ activeModule, onModuleChange, collapsed, onToggleCollapse }: SidebarProps) {
|
||||
export default function Sidebar({ activeModule, onModuleChange, collapsed, onToggleCollapse, onLogout }: SidebarProps) {
|
||||
// 徽标数来自后端真实统计
|
||||
const { data: summary } = useQuery({
|
||||
queryKey: ['summary'],
|
||||
queryFn: apiClient.getSummary,
|
||||
refetchInterval: 15000,
|
||||
});
|
||||
const { toggle: themeToggle, isDark } = useTheme();
|
||||
|
||||
const badgeFor = (id: ModuleType): string | null => {
|
||||
if (id === 'build-nodes') return summary?.buildNodes != null ? String(summary.buildNodes) : null;
|
||||
@@ -167,11 +175,27 @@ export default function Sidebar({ activeModule, onModuleChange, collapsed, onTog
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Collapse toggle */}
|
||||
<div
|
||||
className="px-2 py-2 border-t flex justify-center"
|
||||
{/* Bottom bar: theme toggle + collapse */}
|
||||
<div
|
||||
className="px-2 py-2 border-t flex items-center justify-center gap-1"
|
||||
style={{ borderColor: 'var(--border-color)' }}
|
||||
>
|
||||
<button
|
||||
onClick={themeToggle}
|
||||
className="p-1.5 rounded-md transition-colors hover:bg-black/5"
|
||||
style={{ color: 'var(--text-tertiary)' }}
|
||||
title="切换深色/浅色主题"
|
||||
>
|
||||
{isDark ? <Sun className="w-4 h-4" /> : <Moon className="w-4 h-4" />}
|
||||
</button>
|
||||
<button
|
||||
onClick={onLogout}
|
||||
className="p-1.5 rounded-md transition-colors hover:bg-black/5"
|
||||
style={{ color: 'var(--text-tertiary)' }}
|
||||
title="退出登录"
|
||||
>
|
||||
<LogOut className="w-4 h-4" />
|
||||
</button>
|
||||
<button
|
||||
onClick={onToggleCollapse}
|
||||
className="p-1.5 rounded-md transition-colors hover:bg-black/5"
|
||||
|
||||
Reference in new issue
Block a user