- 技术栈:React 18 + TypeScript + Vite + Tailwind - API 层:ApiError + 401 自动刷新 + single-flight 重试 - 鉴权:内存 Access Token + Cookie Refresh + 启动 bootstrap - RBAC:权限映射 + RequireAuth/RequirePermission 路由守卫 - 布局:OA 工作台壳层 + 侧边栏 + 5 个占位页面 - 样式:复用 hyb-web 视觉 token(单向同步) - 文档:新增 client README,补充 server 联调说明
74 行
2.1 KiB
TypeScript
74 行
2.1 KiB
TypeScript
import { Navigate, Route, Routes } from "react-router-dom";
|
|
import { AppShellLayout } from "../layouts/AppShellLayout";
|
|
import { AuthLayout } from "../layouts/AuthLayout";
|
|
import { DashboardPage } from "../pages/DashboardPage";
|
|
import { ForbiddenPage } from "../pages/ForbiddenPage";
|
|
import { InvoicePoolPage } from "../pages/InvoicePoolPage";
|
|
import { LoginPage } from "../pages/LoginPage";
|
|
import { NotFoundPage } from "../pages/NotFoundPage";
|
|
import { ProfilePage } from "../pages/ProfilePage";
|
|
import { ReimbursementsPage } from "../pages/ReimbursementsPage";
|
|
import { WorkflowTasksPage } from "../pages/WorkflowTasksPage";
|
|
import { GuestOnly, RequireAuth, RequirePermission } from "./guards";
|
|
|
|
export function AppRouter() {
|
|
return (
|
|
<Routes>
|
|
<Route
|
|
path="/login"
|
|
element={
|
|
<GuestOnly>
|
|
<AuthLayout />
|
|
</GuestOnly>
|
|
}
|
|
>
|
|
<Route index element={<LoginPage />} />
|
|
</Route>
|
|
|
|
<Route
|
|
path="/"
|
|
element={
|
|
<RequireAuth>
|
|
<AppShellLayout />
|
|
</RequireAuth>
|
|
}
|
|
>
|
|
<Route index element={<Navigate to="/dashboard" replace />} />
|
|
<Route path="dashboard" element={<DashboardPage />} />
|
|
|
|
<Route
|
|
path="reimbursements"
|
|
element={
|
|
<RequirePermission anyOf={["expense.view_own", "expense.view_all"]}>
|
|
<ReimbursementsPage />
|
|
</RequirePermission>
|
|
}
|
|
/>
|
|
|
|
<Route
|
|
path="workflow/tasks"
|
|
element={
|
|
<RequirePermission anyOf={["expense.approve"]}>
|
|
<WorkflowTasksPage />
|
|
</RequirePermission>
|
|
}
|
|
/>
|
|
|
|
<Route
|
|
path="invoice-pool"
|
|
element={
|
|
<RequirePermission anyOf={["invoice.upload", "invoice.view_own", "invoice.manage"]}>
|
|
<InvoicePoolPage />
|
|
</RequirePermission>
|
|
}
|
|
/>
|
|
|
|
<Route path="settings/profile" element={<ProfilePage />} />
|
|
</Route>
|
|
|
|
<Route path="/403" element={<ForbiddenPage />} />
|
|
<Route path="*" element={<NotFoundPage />} />
|
|
</Routes>
|
|
);
|
|
}
|