feat: 核心模块增强 — 加密 + 运行时配置 + 日志缓冲

- crypto.py: API Key 加密/解密工具
- runtime_config.py: 运行时动态配置管理
- log_buffer.py: 内存日志缓冲区
- config.py: 新增加密配置项
- http_client.py: 增强重试和错误处理
This commit is contained in:
shangfangjian
2026-09-19 11:58:03 +08:00
parent b3e2c52b49
commit 786f10aa11
57 changed files with 3178 additions and 488 deletions
+45
View File
@@ -7,7 +7,9 @@
import { useState, useEffect, useCallback } from 'react'
import { NavLink, Outlet, useLocation } from 'react-router-dom'
import { fetchAuthState, logout, UNAUTHORIZED_EVENT } from './api'
import { fetchHealth } from './dal'
import Login from './Login'
const NAV_ITEMS = [
{ to: '/admin', label: '仪表盘', icon: '◇', end: true },
@@ -18,6 +20,7 @@ const NAV_ITEMS = [
{ to: '/admin/data-sources', label: '数据源', icon: '◫' },
{ to: '/admin/llm-config', label: 'LLM 配置', icon: '◬' },
{ to: '/admin/config', label: '系统配置', icon: '◑' },
{ to: '/admin/logs', label: '系统日志', icon: '▤' },
]
/** 报眉日期行,与前台同款式 */
@@ -33,8 +36,32 @@ function dateLine(): string {
export default function AdminLayout() {
const [sidebarOpen, setSidebarOpen] = useState(false)
const [healthOk, setHealthOk] = useState<boolean | null>(null)
const [authed, setAuthed] = useState<boolean | null>(null)
const location = useLocation()
// 登录门禁:挂载时探测会话,收到 401 事件(会话过期)自动切回登录页
useEffect(() => {
let alive = true
fetchAuthState()
.then(s => alive && setAuthed(s.authenticated))
.catch(() => alive && setAuthed(false))
const onUnauthorized = () => setAuthed(false)
window.addEventListener(UNAUTHORIZED_EVENT, onUnauthorized)
return () => {
alive = false
window.removeEventListener(UNAUTHORIZED_EVENT, onUnauthorized)
}
}, [])
const handleLogout = useCallback(async () => {
try {
await logout()
} catch {
/* 会话可能已失效,直接切回登录页 */
}
setAuthed(false)
}, [])
const checkHealth = useCallback(async () => {
try {
const h = await fetchHealth()
@@ -65,6 +92,18 @@ export default function AdminLayout() {
return () => document.removeEventListener('keydown', handler)
}, [])
// 登录门禁:未登录只渲染登录页,不泄露后台任何内容
if (authed === null) {
return (
<div className="flex h-screen items-center justify-center bg-paper-50 text-xs text-ink-400">
</div>
)
}
if (!authed) {
return <Login onSuccess={() => setAuthed(true)} />
}
return (
<div className="flex h-screen overflow-hidden bg-paper-50 text-ink-800">
{/* ── 移动端遮罩层 ── */}
@@ -177,6 +216,12 @@ export default function AdminLayout() {
>
</a>
<button
onClick={handleLogout}
className="text-ink-500 transition-colors hover:text-press"
>
</button>
</div>
</header>