- App.tsx: remove double-wrapped MainLayout from /notifications route
- NotificationBell.tsx: decouple SSE from popover open state using ref
- useNotifications.ts: fix interval leak in onerror via ref in cleanup
- notifications.controller.ts: unsubscribe on req.on('close') for SSE Subject
- schedules.controller.ts: use existing schedule values in conflict catch
245 lines
7.7 KiB
TypeScript
245 lines
7.7 KiB
TypeScript
import React from 'react';
|
|
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
|
|
import { ConfigProvider, App as AntdApp } from 'antd';
|
|
import zhCN from 'antd/es/locale/zh_CN';
|
|
import MainLayout from './layouts/MainLayout';
|
|
import LoginPage from './pages/Login';
|
|
import DashboardPage from './pages/Dashboard';
|
|
import StudentsPage from './pages/Students';
|
|
import RoomsPage from './pages/Rooms';
|
|
import OccupanciesPage from './pages/Occupancies';
|
|
import ExpensesPage from './pages/Expenses';
|
|
import BillsPage from './pages/Bills';
|
|
import RoomVisualPage from './pages/RoomVisual';
|
|
import OperationLogsPage from './pages/OperationLogs';
|
|
import UsersPage from './pages/Users';
|
|
import DepositsPage from './pages/Deposits';
|
|
import ClassroomsPage from './pages/Classrooms';
|
|
import ClassesPage from './pages/Classes';
|
|
import ClassDetailPage from './pages/Classes/detail';
|
|
import TenantsPage from './pages/Tenants';
|
|
import ClassroomRentalsPage from './pages/ClassroomRentals';
|
|
import ClassroomSchedulePage from './pages/ClassroomSchedule';
|
|
import SchedulesPage from './pages/Schedules';
|
|
import RolesPage from './pages/Roles';
|
|
import PermissionsPage from './pages/Permissions';
|
|
import AttendancePage from './pages/Attendance';
|
|
import TeacherWorkspacePage from './pages/TeacherWorkspace';
|
|
import NotificationsPage from './pages/Notifications';
|
|
import PermissionRoute from './components/PermissionRoute';
|
|
|
|
const PrivateRoute: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
const token = localStorage.getItem('token');
|
|
return token ? <>{children}</> : <Navigate to="/login" />;
|
|
};
|
|
|
|
const App: React.FC = () => {
|
|
return (
|
|
<ConfigProvider
|
|
locale={zhCN}
|
|
theme={{
|
|
token: {
|
|
colorPrimary: '#007AFF',
|
|
borderRadius: 10,
|
|
colorBgContainer: '#fff',
|
|
fontFamily:
|
|
"-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'SF Pro Text', 'Helvetica Neue', Arial, sans-serif",
|
|
},
|
|
}}
|
|
>
|
|
<AntdApp>
|
|
<BrowserRouter>
|
|
<Routes>
|
|
<Route path="/login" element={<LoginPage />} />
|
|
<Route
|
|
path="/"
|
|
element={
|
|
<PrivateRoute>
|
|
<MainLayout />
|
|
</PrivateRoute>
|
|
}
|
|
>
|
|
<Route index element={<Navigate to="/dashboard" />} />
|
|
<Route
|
|
path="dashboard"
|
|
element={
|
|
<PermissionRoute permission="dashboard:view">
|
|
<DashboardPage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="room-visual"
|
|
element={
|
|
<PermissionRoute permission="room:view">
|
|
<RoomVisualPage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="students"
|
|
element={
|
|
<PermissionRoute permission="student:view">
|
|
<StudentsPage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="rooms"
|
|
element={
|
|
<PermissionRoute permission="room:view">
|
|
<RoomsPage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="occupancies"
|
|
element={
|
|
<PermissionRoute permission="occupancy:view">
|
|
<OccupanciesPage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="expenses"
|
|
element={
|
|
<PermissionRoute permission="expense:view">
|
|
<ExpensesPage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="deposits"
|
|
element={
|
|
<PermissionRoute permission="deposit:view">
|
|
<DepositsPage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="bills"
|
|
element={
|
|
<PermissionRoute permission="bill:view">
|
|
<BillsPage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="classes"
|
|
element={
|
|
<PermissionRoute permission="class:view">
|
|
<ClassesPage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="classes/:id"
|
|
element={
|
|
<PermissionRoute permission="class:view">
|
|
<ClassDetailPage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="operation-logs"
|
|
element={
|
|
<PermissionRoute permission="log:view">
|
|
<OperationLogsPage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="roles"
|
|
element={
|
|
<PermissionRoute permission="role:view">
|
|
<RolesPage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="permissions"
|
|
element={
|
|
<PermissionRoute permission="role:view">
|
|
<PermissionsPage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="users"
|
|
element={
|
|
<PermissionRoute permission="user:view">
|
|
<UsersPage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="classrooms"
|
|
element={
|
|
<PermissionRoute permission="classroom:view">
|
|
<ClassroomsPage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="tenants"
|
|
element={
|
|
<PermissionRoute permission="tenant:view">
|
|
<TenantsPage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="classroom-rentals"
|
|
element={
|
|
<PermissionRoute permission="rental:view">
|
|
<ClassroomRentalsPage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="classroom-schedule"
|
|
element={
|
|
<PermissionRoute permission="classroom:view">
|
|
<ClassroomSchedulePage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
|
|
<Route
|
|
path="attendance"
|
|
element={
|
|
<PermissionRoute permission="attendance:view">
|
|
<AttendancePage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
|
|
<Route
|
|
path="schedules"
|
|
element={
|
|
<PermissionRoute permission="schedule:view">
|
|
<SchedulesPage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
|
|
<Route
|
|
path="teacher-workspace"
|
|
element={
|
|
<PermissionRoute permission="class:view">
|
|
<TeacherWorkspacePage />
|
|
</PermissionRoute>
|
|
}
|
|
/>
|
|
|
|
<Route path="notifications" element={<NotificationsPage />} />
|
|
</Route>
|
|
</Routes>
|
|
</BrowserRouter>
|
|
</AntdApp>
|
|
</ConfigProvider>
|
|
);
|
|
};
|
|
|
|
export default App;
|