Files
opsxsql/frontend/src/App.tsx
T
logan 765d27f1e3 feat: 实例权限组系统 — 完整CRUD + 实例/用户关联 + 前端管理页面
后端:
- InstanceGroup 模型 (name/db_type/permissions JSON/is_active)
- user_groups 关联表 (用户-权限组 M2M + 权限覆盖)
- Instance 模型增加 group_id FK
- User 模型增加 groups 关系
- API: CRUD + 实例关联 + 用户分配 + 权限组过滤
- 15 个新测试 (CRUD/关联/权限检查/参数校验) — 217/217 passing

前端:
- InstanceGroupPage: 左右布局(列表+详情)
- 权限配置: 5类17项权限勾选 (查询/DDL/工单/数据操作/管理)
- 实例关联/用户关联弹框
- 侧边栏增加权限组菜单 (数据源分组下)
- 路由 + 权限注册
2026-05-23 00:09:34 +08:00

96 lines
3.6 KiB
TypeScript

import { BrowserRouter, Routes, Route, Navigate, Outlet } from 'react-router-dom';
import { AuthProvider, useAuth } from '@/hooks/useAuth';
import { ThemeProvider } from '@/hooks/useTheme';
import Layout from '@/components/Layout';
import LoginPage from '@/pages/LoginPage';
import Dashboard from '@/pages/Dashboard';
import InstancePage from '@/pages/InstancePage';
import TicketsPage from '@/pages/TicketsPage';
import QueriesPage from '@/pages/QueriesPage';
import RolesPage from '@/pages/RolesPage';
import UsersPage from '@/pages/UsersPage';
import DataPermissionPage from '@/pages/DataPermissionPage';
import AuditRulesPage from '@/pages/AuditRulesPage';
import WorkflowPage from '@/pages/WorkflowPage';
import AutoTaskPage from '@/pages/AutoTaskPage';
import SettingsPage from '@/pages/SettingsPage';
import AuditLogsPage from '@/pages/AuditLogsPage';
import DataDictionaryPage from '@/pages/DataDictionaryPage';
import InstanceDetailPage from '@/pages/InstanceDetailPage';
import RedisDetailPage from '@/pages/RedisDetailPage';
import TicketCreatePage from '@/pages/TicketCreatePage';
import TicketDetailPage from '@/pages/TicketDetailPage';
import InstanceGroupPage from '@/pages/InstanceGroupPage';
// 路由守卫:未登录跳转登录页,无权限跳转仪表盘
function RouteGuard() {
const { isLoggedIn, hasPermission } = useAuth();
const path = location.pathname.split('/')[1] || 'dashboard';
if (!isLoggedIn) {
return <Navigate to="/login" replace />;
}
// 检查当前路径是否有权限访问
if (path !== 'dashboard' && !hasPermission(path)) {
return <Navigate to="/dashboard" replace />;
}
return <Outlet />;
}
// 登录页守卫:已登录用户自动跳转到仪表盘
function LoginGuard() {
const { isLoggedIn } = useAuth();
if (isLoggedIn) {
return <Navigate to="/dashboard" replace />;
}
return <LoginPage />;
}
function AppRoutes() {
return (
<Routes>
<Route path="/login" element={<LoginGuard />} />
<Route element={<RouteGuard />}>
<Route path="/" element={<Layout />}>
<Route index element={<Navigate to="/dashboard" replace />} />
<Route path="dashboard" element={<Dashboard />} />
<Route path="instances" element={<InstancePage />} />
<Route path="instance-groups" element={<InstanceGroupPage />} />
<Route path="instances/:id" element={<InstanceDetailPage />} />
<Route path="redis/:id" element={<RedisDetailPage />} />
<Route path="data-dictionary" element={<DataDictionaryPage />} />
<Route path="tickets" element={<TicketsPage />} />
<Route path="tickets/create" element={<TicketCreatePage />} />
<Route path="tickets/:id" element={<TicketDetailPage />} />
<Route path="queries" element={<QueriesPage />} />
<Route path="roles" element={<RolesPage />} />
<Route path="users" element={<UsersPage />} />
<Route path="data-permission" element={<DataPermissionPage />} />
<Route path="audit-rules" element={<AuditRulesPage />} />
<Route path="audit-logs" element={<AuditLogsPage />} />
<Route path="workflow" element={<WorkflowPage />} />
<Route path="auto-task" element={<AutoTaskPage />} />
<Route path="settings" element={<SettingsPage />} />
<Route path="*" element={<Navigate to="/dashboard" replace />} />
</Route>
</Route>
</Routes>
);
}
function App() {
return (
<BrowserRouter>
<ThemeProvider>
<AuthProvider>
<AppRoutes />
</AuthProvider>
</ThemeProvider>
</BrowserRouter>
);
}
export default App;