refactor: 前后端目录结构模块化 + v2 优化移植与缺陷修复
前端: - src/srv/api → src/api,按域分文件夹(auth/cluster/host/storage/deployment/collector) - 新增 http.ts 引擎(http.get/post/put/delete),域模块改用语义化调用 - index.html 增加 favicon(匹配应用 logo 的 emerald + Activity 脉冲) 后端分层增强(保留包名): - 新增 repository/:从 models 拆出 JsonDB 持久化层(InitDB/GetDB/Shutdown/RequestSave) - 新增 dto/:从 controllers 抽出各域请求契约(带 binding 校验) - 新增 pkg/crypto、pkg/jwt:从 utils 拆出安全原语(外部 jwt 别名 jwtv5 避免冲突) - models 只留领域实体 + sanitizer;utils 只留 gin/应用相关(response/errors) v2 优化移植与缺陷修复: - 移植密钥分离/SSH TOFU/并发写安全/Loki 生产级配置/Docker 加固 - 修复 deployment.go 并发丢更新、Helm values 重复键、EncryptField 哨兵、loki-gateway 端点等审计缺陷 - 实现真正的优雅关停(main.go http.Server + signal + repository.Shutdown) - 修复登录契约:后端返回 accessToken,前端 auth.ts/Login.tsx 对齐 - 补 crypto/jwt/repository 单元测试(含并发写回归) 验证: go build/vet/test 全绿;npm run build 通过;登录→鉴权→优雅关停冒烟通过 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
fb8d10231a
commit
327e282356
93 files changed
+8433
-3089
No files matched your search
+88
-73
@@ -1,83 +1,98 @@
|
||||
import { lazy, Suspense, memo } from 'react'
|
||||
import { Routes, Route, Navigate } from 'react-router'
|
||||
import Layout from '@/components/Layout'
|
||||
import Login from '@/pages/Login'
|
||||
import Dashboard from '@/pages/Dashboard'
|
||||
import Clusters from '@/pages/Clusters'
|
||||
import Hosts from '@/pages/Hosts'
|
||||
import Storage from '@/pages/Storage'
|
||||
import Deployments from '@/pages/Deployments'
|
||||
import Collectors from '@/pages/Collectors'
|
||||
import Settings from '@/pages/Settings'
|
||||
import { Toaster } from '@/components/ui/sonner'
|
||||
import { LoadingSpinner } from '@/components/LoadingSpinner'
|
||||
|
||||
function RequireAuth({ children }: { children: React.ReactNode }) {
|
||||
// 路由守卫组件 - 独立定义,便于复用
|
||||
const RequireAuth = memo(function RequireAuth({ children }: { children: React.ReactNode }) {
|
||||
const token = localStorage.getItem('token')
|
||||
if (!token) {
|
||||
return <Navigate to="/login" replace />
|
||||
}
|
||||
return <Layout>{children}</Layout>
|
||||
}
|
||||
// 动态导入Layout以避免在登录页面加载它
|
||||
return <LazyLayout>{children}</LazyLayout>
|
||||
})
|
||||
|
||||
export default function App() {
|
||||
// 懒加载页面组件 - 实现代码分割
|
||||
const Login = lazy(() => import('@/pages/Login'))
|
||||
const Dashboard = lazy(() => import('@/pages/Dashboard'))
|
||||
const Clusters = lazy(() => import('@/pages/Clusters'))
|
||||
const Hosts = lazy(() => import('@/pages/Hosts'))
|
||||
const Storage = lazy(() => import('@/pages/Storage'))
|
||||
const Deployments = lazy(() => import('@/pages/Deployments'))
|
||||
const Collectors = lazy(() => import('@/pages/Collectors'))
|
||||
const Settings = lazy(() => import('@/pages/Settings'))
|
||||
const Layout = lazy(() => import('@/components/Layout'))
|
||||
|
||||
// 懒加载布局包装器
|
||||
function LazyLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<Routes>
|
||||
<Route path="/login" element={<Login />} />
|
||||
<Route
|
||||
path="/"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<Dashboard />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/clusters"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<Clusters />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/hosts"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<Hosts />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/storage"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<Storage />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/deployments"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<Deployments />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/collectors"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<Collectors />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/settings"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<Settings />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
<Route path="*" element={<Navigate to="/" replace />} />
|
||||
</Routes>
|
||||
<Suspense fallback={<PageLoadingFallback />}>
|
||||
<Layout>{children}</Layout>
|
||||
</Suspense>
|
||||
)
|
||||
}
|
||||
|
||||
// 页面加载中占位
|
||||
function PageLoadingFallback() {
|
||||
return (
|
||||
<div className="h-screen w-screen flex items-center justify-center bg-slate-50 dark:bg-slate-950">
|
||||
<LoadingSpinner size="lg" text="页面加载中..." />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// 路由配置 - 集中管理路由定义
|
||||
interface RouteConfig {
|
||||
path: string
|
||||
element: React.ReactNode
|
||||
auth?: boolean
|
||||
}
|
||||
|
||||
const routes: RouteConfig[] = [
|
||||
{ path: '/login', element: <Login />, auth: false },
|
||||
{ path: '/', element: <Dashboard />, auth: true },
|
||||
{ path: '/clusters', element: <Clusters />, auth: true },
|
||||
{ path: '/hosts', element: <Hosts />, auth: true },
|
||||
{ path: '/storage', element: <Storage />, auth: true },
|
||||
{ path: '/deployments', element: <Deployments />, auth: true },
|
||||
{ path: '/collectors', element: <Collectors />, auth: true },
|
||||
{ path: '/settings', element: <Settings />, auth: true },
|
||||
]
|
||||
|
||||
/**
|
||||
* App 根组件
|
||||
*
|
||||
* 优化点:
|
||||
* 1. 所有页面使用 React.lazy 懒加载,实现代码分割
|
||||
* 2. 路由守卫独立为 memo 组件
|
||||
* 3. Suspense 统一处理加载状态
|
||||
* 4. 路由配置集中管理
|
||||
*/
|
||||
const App = memo(function App() {
|
||||
return (
|
||||
<>
|
||||
<Routes>
|
||||
{routes.map((route) => (
|
||||
<Route
|
||||
key={route.path}
|
||||
path={route.path}
|
||||
element={
|
||||
route.auth ? (
|
||||
<RequireAuth>{route.element}</RequireAuth>
|
||||
) : (
|
||||
<Suspense fallback={<PageLoadingFallback />}>
|
||||
{route.element}
|
||||
</Suspense>
|
||||
)
|
||||
}
|
||||
/>
|
||||
))}
|
||||
<Route path="*" element={<Navigate to="/" replace />} />
|
||||
</Routes>
|
||||
<Toaster />
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
export default App
|
||||
Reference in new issue
Block a user