企业级中后台管理系统
基于 React 19 + Next.js 15 App Router 构建,参考 BreezeAdmin Vue 3 版本实现
🌐 在线演示:https://react.breezeui.cn
|
指标卡片 + 销售趋势图 + 最近订单
|
RBAC 三角色 + 四层中间件防御
|
|
Chrome 风格 TabBar
|
|
|
动态主题 + 布局配置面板
|
|
📸 更多截图
截图待补充 — 欢迎运行项目体验完整功能
| 类别 | 技术 | 说明 |
|---|---|---|
| ⚛️ 框架 | React 19 + Next.js 15 | App Router, Server Components, 流式渲染 |
| 🎨 UI 组件 | shadcn/ui + Radix UI + Tailwind CSS | 可组合原子组件,完全可控样式 |
| 📦 状态管理 | Zustand | 轻量级,内置 persist middleware 持久化 |
| 🔄 数据获取 | TanStack Query v5 | 异步数据缓存、自动重试、乐观更新 |
| 📋 表单 | React Hook Form + Zod | 编译时类型推断 + 运行时校验 |
| 🌐 国际化 | i18next + react-i18next | 中英文切换,浏览器语言检测 |
| 🌗 主题 | next-themes + CSS 变量动态注入 | 亮色 / 暗色 / 系统三种模式 + 8 色预设 |
| 📊 图表 | @nivo/line | 响应式折线图,按需动态导入 |
| 🎯 图标 | lucide-react | 统一图标风格,Tree-shakable |
| ✋ 拖拽 | @dnd-kit | Tab 标签拖拽排序 |
| 🎬 动画 | Framer Motion | 页面过渡、侧边栏展开、进度条动效 |
| 🧪 Mock | MSW (Mock Service Worker) | 拦截网络请求,多角色数据模拟 |
| 🔍 代码规范 | ESLint + Prettier + Husky + lint-staged | 提交前自动 lint + 类型检查 |
| 工具 | 版本 |
|---|---|
| Node.js | >= 18 |
| pnpm | >= 9.0.0 |
# 克隆项目
git clone <repository-url>
cd BreezeReact
# 安装依赖
pnpm install
# 初始化 MSW (Mock Service Worker)
pnpm msw:init
# 启动开发服务器
pnpm dev启动后访问 http://localhost:3000
- Fork 或导入仓库到 Vercel
- 配置环境变量(参考
.env.production) - 一键部署,自动 CI/CD
Vercel 原生支持 Next.js App Router、SSR、ISR 及 Edge Functions。
| 👤 角色 | 📛 用户名 | 🔒 密码 | 📝 说明 |
|---|---|---|---|
| Admin | admin |
admin123 |
全部权限 |
| Manager | manager |
manager123 |
无系统设置 |
| User | user |
user123 |
无用户管理 |
| 命令 | 说明 |
|---|---|
pnpm dev |
启动开发服务器 (监听 0.0.0.0) |
pnpm build |
生产构建 |
pnpm start |
启动生产服务器 |
pnpm lint |
ESLint 代码检查 |
pnpm analyze |
Bundle 分析 (rollup-plugin-visualizer) |
src/
├── 📁 app/ # Next.js App Router
│ ├── 📁 (auth)/ # 🔓 认证路由组 (居中布局,无侧边栏)
│ │ └── login/page.tsx
│ ├── 📁 (dashboard)/ # 🔒 业务路由组 (侧边栏 + 顶栏 + TabBar)
│ │ ├── layout.tsx # Server Component: cookie → 角色注入
│ │ ├── dashboard-shell.tsx # Client Component: 零闪烁水合
│ │ └── 📁 {dashboard,orders,...}# 业务页面
│ ├── forbidden/page.tsx # 403 页面
│ ├── layout.tsx # 根布局 (Theme > I18n > Query)
│ └── providers.tsx # 客户端 Provider 集合
│
├── 📁 config/
│ └── routes.ts # 🗺️ 路由配置 (菜单 + 权限单一数据源)
│
├── 📁 features/ # 🎯 特性模块 (业务内聚)
│ ├── auth/ # 认证模块
│ └── dashboard/ # 仪表盘模块
│ └── components/
│ ├── DashboardLayout.tsx # 主布局 (侧边栏 + 顶栏 + TabBar + 进度条 + 设置面板)
│ ├── SettingsSheet.tsx # ⚙️ 工作区设置面板容器
│ ├── settings/ # ⚙️ 设置分区组件 (色彩/通用/顶栏/侧栏/标签栏/页脚)
│ ├── TabBar.tsx # Chrome 风格多标签导航栏
│ └── TabContextMenu.tsx # Tab 右键菜单
│
├── 📁 components/
│ └── ui/ # 🧱 shadcn/ui 原子组件 (Dumb)
│
├── 📁 types/
│ └── api-schema.ts # 📐 Zod Schema + TS 类型 (唯一来源)
│
├── 📁 api/ # 🌐 模块化 API 命名空间
│ ├── auth.ts # 认证 (login, getUserInfo)
│ ├── dashboard.ts # 仪表盘 (metrics, salesTrend, orders)
│ ├── orders.ts # 订单 (getOrders)
│ └── users.ts # 用户 (getUsers)
│
├── 📁 hooks/
│ ├── use-api.ts # 🪝 useApiQuery / useApiMutation + 业务 hooks
│ ├── use-apply-settings.ts # ⚙️ 设置应用 (防抖色彩注入 + 布局尺寸同步)
│ └── use-fullscreen.ts # 🖥️ 浏览器全屏 API 封装
│
├── 📁 stores/ # 📦 Zustand 状态管理
│ ├── auth-store.ts # 认证 (persist + cookie + tokenProvider)
│ ├── app-store.ts # UI 状态 (sidebar, theme, language)
│ ├── menu-store.ts # 权限菜单 (persist + role 过滤)
│ ├── settings-store.ts # ⚙️ 工作区设置 (persist + 版本迁移 + 数值钳制)
│ └── tab-store.ts # 多标签 (persist + 拖拽 + 固定)
│
├── 📁 utils/
│ └── request.ts # 🔧 BusinessError + fetcher + Zod 校验
│
├── 📁 mocks/ # 🧪 MSW Mock
│ ├── handlers.ts # 多角色 handlers + 随机延迟
│ └── browser.ts # Worker 初始化
│
├── 📁 locales/ # 🌍 国际化
│ ├── en.json # English
│ └── zh.json # 中文
│
└── 📁 lib/ # 🛠️ 工具库
├── auth-utils.ts # Token 编解码 + 角色守卫
├── color-preset.ts # 🎨 色彩预设 (8 命名色 + HSL 派生 + DOM 注入)
├── query-client.ts # QueryClient SSR 单例
├── i18n.ts # i18next 配置
└── utils.ts # cn() 等通用工具
.env # 全局共享 (APP_TITLE, APP_DESCRIPTION)
.env.development # 开发环境 (API_BASE_URL = localhost:3000)
.env.production # 生产环境 (API_BASE_URL = 线上地址)
src/env.d.ts # 环境变量 TypeScript 类型声明
所有 TypeScript 类型从 Zod Schema 推断,编译时类型安全 + 运行时校验一致:
📐 types/api-schema.ts ← Zod Schema (类型唯一真理来源)
│
▼
🔧 utils/request.ts ← BusinessError + fetcher + Zod 运行时校验
│
▼
🌐 api/* ← 模块化命名空间 (authApi, dashboardApi...)
│
▼
🪝 hooks/use-api.ts ← useApiQuery / useApiMutation + 401 拦截
│
▼
🎯 features/*/components ← Smart 组件 (调用 hooks,处理 UI 逻辑)
│
▼
🧱 components/ui/ ← Dumb 组件 (纯 UI,仅接收 props)
┌──────────────────────────────────────────────────────────┐
│ L1 · 公开路径白名单 │
│ /login, /forbidden → 直接放行 │
├──────────────────────────────────────────────────────────┤
│ L2 · Token 存在性校验 │
│ 无 token → 重定向 /login?redirect=pathname │
│ 已登录访问 /login → 重定向 /dashboard │
├──────────────────────────────────────────────────────────┤
│ L3 · 角色级权限拦截 │
│ extractRole(token) + routePermissions 匹配 │
│ 无权限 → rewrite /forbidden (403) │
├──────────────────────────────────────────────────────────┤
│ L4 · Header 注入 │
│ x-user-role → 供下游 Server Component 读取 │
└──────────────────────────────────────────────────────────┘
| 页面 | 🔴 admin | 🟡 manager | 🟢 user |
|---|---|---|---|
| Dashboard | ✅ | ✅ | ✅ |
| Orders | ✅ | ✅ | ✅ |
| Users | ✅ | ✅ | ❌ |
| Form Examples | ✅ | ✅ | ✅ |
| System → Requests | ✅ | ✅ | ✅ |
| System → Switch Role | ✅ | ✅ | ✅ |
| System → Admin Only | ✅ | ❌ | ❌ |
app/layout.tsx — 根布局 (ThemeProvider > I18nProvider > QueryClientProvider)
│
├── (auth)/ ──────────── 认证路由组
│ └── login/page.tsx 居中全屏,无侧边栏
│
└── (dashboard)/ ─────── 业务路由组
├── layout.tsx Server: cookie → extractRole → 注入
├── dashboard-shell.tsx Client: setMenuByRole(initialRole) 零闪烁
├── DashboardLayout 侧边栏 + 顶栏 + TabBar + 进度条
└── {dashboard, orders, users, form, system}/*
路由组
(auth)/(dashboard)不影响 URL 路径,仅用于共享布局。每个页面无需手动包裹<DashboardLayout>。
Chrome 浏览器风格的多标签导航系统:
| 功能 | 实现 |
|---|---|
| 🖱️ 拖拽排序 | @dnd-kit + SortableContext + horizontalListSortingStrategy |
| 📋 右键菜单 | 刷新 / 关闭 / 关闭其他 / 关闭左侧 / 关闭右侧 |
| 📌 固定标签 | Dashboard 标签始终存在,不可关闭或拖拽 |
| 📜 滚动导航 | 标签溢出时左右箭头导航 + 鼠标滚轮水平滚动 |
| 📑 标签列表 | ChevronDown 下拉展示全部标签 |
| 🔄 刷新页面 | 点击活动标签触发 refresh() 强制重渲染 |
| 💾 状态持久化 | tabs + activeTab 保存至 localStorage |
| 功能 | 说明 |
|---|---|
| 📐 折叠/展开 | 桌面端收缩为 64px 图标模式,展开 256px |
| 📂 多级菜单 | 嵌套子菜单,收起时 DropdownMenu 浮层展示 |
| 🎨 选中高亮 | 子级:主题色字体 + 淡色背景 · 父级:仅字体高亮 |
| 🔄 自动展开 | 选中子级时自动展开父级嵌套组 |
| 📱 移动端 | Sheet 侧滑抽屉,点击导航后自动收起 |
| 🎬 动画 | Framer Motion spring 弹簧动画展开/折叠 |
无需第三方 NProgress,自研 2px 顶部进度条:
用户点击菜单 → 30% (即时) → 90% (路由切换) → 100% (加载完成) → 淡出
├── 150ms ──┤──── 200ms ────┤
MSW 模拟完整 API 行为,支持三个角色同时测试:
// 多角色凭证
{ username: "admin", password: "admin123", role: "admin" }
{ username: "manager", password: "manager123", role: "manager" }
{ username: "user", password: "user123", role: "user" }
// 每个 handler 包含随机延迟 (50-300ms) 模拟真实网络完整的动态主题 + 布局配置系统,所有设置持久化到 localStorage:
| 分类 | 设置项 | 说明 |
|---|---|---|
| 🎨 色彩预设 | 8 命名色 + custom | CSS 变量运行时注入,零 React 重渲染 |
| 🌐 通用 | 语言/主题/全屏按钮 | 控制顶栏功能按钮可见性 |
| 📏 顶栏 | 高度滑块 + 面包屑开关 | 48-72px 可调 |
| 📐 侧栏 | 展开/折叠宽度滑块 | 展开 200-320px,折叠 48-80px |
| 🗂️ 标签栏 | 可见性 + 缓存 + 中键关闭 | TabBar 行为控制 |
| 📦 页脚 | 可见性 + 高度滑块 | 32-64px 可调 |
色彩切换原理: 选择预设 → color-preset.ts 派生 9 组 HSL 值 → applyColorsToDOM() 注入 document.documentElement → Tailwind hsl(var(--primary)) 实时响应 → 全局色彩瞬间更新。
🧱 Dumb (components/ui/) → 纯 UI,仅接收 props,不懂数据
│
▼
🎯 Smart (features/*/components/) → 调用 hooks,处理 UI 交互
│
▼
🏗️ Layout (DashboardLayout) → 读取 store,渲染侧边栏 + 顶栏 + TabBar
Zustand 选择器模式,精确订阅避免多余渲染:
// ✅ 推荐:精确订阅
const user = useAuthStore((s) => s.user);
const collapsed = useAppStore((s) => s.sidebarCollapsed);
// ✅ 推荐:多状态用 shallow
const { theme, language } = useAppStore(
(s) => ({ theme: s.theme, language: s.language }),
shallow
);
// ❌ 避免:订阅整个 store
const store = useAuthStore();Store 清单:
| Store | 持久化 | 说明 |
|---|---|---|
auth-store |
✅ cookie + localStorage | Token + 用户信息 + tokenProvider 注入 |
app-store |
❌ | Sidebar 折叠、主题、语言等 UI 状态 |
menu-store |
✅ localStorage | 角色过滤菜单(仅持久化 role) |
settings-store |
✅ localStorage (版本化) | 工作区设置(色彩/布局/功能开关) |
tab-store |
✅ localStorage | 多标签(排序/固定/缓存) |
Next.js 内置 .env 加载,NEXT_PUBLIC_* 前缀暴露给浏览器:
# .env — 所有环境共享
NEXT_PUBLIC_APP_TITLE=BreezeReact
NEXT_PUBLIC_APP_DESCRIPTION=Enterprise-grade admin dashboard
# .env.development
NEXT_PUBLIC_API_BASE_URL=http://localhost:3000
NEXT_PUBLIC_ENABLE_MSW=true
# .env.production
NEXT_PUBLIC_API_BASE_URL=https://api.yourdomain.com
NEXT_PUBLIC_ENABLE_MSW=false类型安全:src/env.d.ts 为 process.env 提供完整 TypeScript 提示。
所有类型从 @/types/api-schema 统一导入:
// ✅ 正确
import type { User, MetricsData } from "@/types/api-schema";
// ❌ 错误 — 禁止从 API 模块导入类型
import type { User } from "@/api/auth";1. 📐 config/routes.ts → 添加路由 (path, name, icon, permission)
2. 📁 app/(dashboard)/xxx/ → 创建 page.tsx
3. 🌍 locales/{zh,en}.json → 添加翻译 key
4. 🌐 api/*.ts → 如需数据,创建 API 模块
5. 🪝 hooks/use-api.ts → 创建业务 hook
完整的 API 添加链路:
types/api-schema.ts (Schema) → utils/request.ts (校验) → api/*.ts (接口) → hooks/use-api.ts (Hook) → 组件调用
| 资源 | 链接 |
|---|---|
| 📖 BreezeAdmin 文档 | docs.breezeui.cn |
| ⚛️ React 19 | react.dev |
| ▲ Next.js 15 | nextjs.org |
| 🎨 shadcn/ui | ui.shadcn.com |
| 🐻 Zustand | github.com/pmndrs/zustand |
| 🔄 TanStack Query | tanstack.com/query |
| 📐 Zod | zod.dev |
| 🧪 MSW | mswjs.io |
BreezeReact · Built with ❤️ using React + Next.js
MIT License © 2026 BL