Files
chat-one-admin-web/docs/后台管理前端设计方案.md
alboped a09dcef3f1 feat: 初始化 ChatOne 管理后台前端
基于 React + Vite + Ant Design Pro 搭建登录、动态菜单、布局主题与数据总览,并补充按菜单整理的 UI 设计稿。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-25 23:57:53 +08:00

28 KiB
Raw Blame History

ChatOne 后台管理前端 — 设计方案

版本v1.1
适用范围中小型后台管理系统1030 个业务模块515 人前端团队)
更新日期2026-06-04


1. 设计目标

维度 目标
开发效率 脚手架开箱即用CRUD 页面可快速复制模板
可维护性 分层清晰、类型安全、模块边界明确
可扩展性 权限、路由、菜单由后端驱动,新增模块成本低
用户体验 统一布局、响应式、加载/错误状态一致
工程质量 自动化 lint/test/CI代码风格统一

2. 技术选型2026 主流方案)

2.1 推荐主栈React 生态

在国内中小型后台项目中,React 18 + Vite + TypeScript + Ant Design 5 + Zustand 是团队规模扩大后最主流、招聘与协作成本最低的组合,参考项目包括 Ant Design ProUmi Max

类别 选型 说明
框架 React 18+ 函数组件 + Hooks 为默认写法
构建 Vite 6 极速 HMR原生 ESMRollup 生产构建
语言 TypeScript 5.x 严格模式,接口类型与后端对齐
路由 React Router 6 支持动态路由、Loader/Guard 模式
状态 Zustand 轻量、TS 友好,无样板代码
服务端状态 TanStack Query (React Query) 请求缓存、重试、失效刷新(可选但推荐)
UI 库 Ant Design 5 表格/表单/弹窗等后台组件完备
高级组件 @ant-design/pro-components ProTable、ProForm、ProLayout 开箱即用
HTTP Axios 拦截器统一处理 Token、错误、重试
CSS CSS Modules + Ant Design Token 组件库主题 Token + 局部样式隔离
样式方案(可选) Tailwind CSS 与 Ant Design 共存,用于布局/间距
图标 @ant-design/icons + Iconify 内置图标 + 按需扩展
工具库 ahooksdayjslodash-es Hooks 工具、日期、数据处理
表单校验 Ant Design Form(内置 rules 声明式校验规则
图表 @ant-design/chartsECharts 5 与 Ant Design 风格一致
包管理 pnpm 磁盘占用小、依赖隔离好
代码规范 ESLint 9 (flat config) + Prettier + Stylelint 统一风格
Git 钩子 Husky + lint-staged + commitlint 提交前自动检查
单元测试 Vitest + React Testing Library 与 Vite 同源配置
E2E 测试 Playwright 覆盖登录、核心流程
API 类型 openapi-typescriptswagger-typescript-api 由 OpenAPI 自动生成 TS 类型

2.2 备选栈Vue 生态

若团队 Vue 经验更丰富,可选用 Vue 3 + Vite + TypeScript + Element Plus + Pinia,参考 Vben Admin。两套方案在架构层面等价,本文以 React 主栈展开。

2.3 不推荐的选型(中小型场景)

方案 原因
Next.js SSR 后台以 SPA 为主SSR 收益低、复杂度上升
微前端qiankun 等) 模块量 < 30 时过度设计,联调与部署成本高
自研 UI 组件库 投入大Ant Design / ProComponents 已足够
Redux Toolkit单独使用 中小型项目 Zustand 更轻量,除非团队已有 Redux 规范
JavaScript无 TS 中大型项目维护成本显著上升

3. 整体架构

┌─────────────────────────────────────────────────────────┐
│                      Browser (SPA)                       │
├──────────────┬──────────────────────────────────────────┤
│    Pages     │  页面组件(列表 / 表单 / 详情 / 仪表盘)      │
├──────────────┼──────────────────────────────────────────┤
│  Components  │  业务组件 + 通用组件Access、PageContainer│
├──────────────┼──────────────────────────────────────────┤
│    Hooks     │  可复用逻辑useTable、useAuth、usePermission│
├──────────────┼──────────────────────────────────────────┤
│   Stores     │  Zustanduser / permission / app / dict│
├──────────────┼──────────────────────────────────────────┤
│   Router     │  静态路由 + 动态路由(权限驱动)              │
├──────────────┼──────────────────────────────────────────┤
│   API Layer  │  按模块划分的 API + 统一 Request 封装       │
├──────────────┼──────────────────────────────────────────┤
│   Utils      │  工具函数、常量、枚举、类型定义               │
└──────────────┴──────────────────────────────────────────┘
                              │
                              ▼ HTTP / WebSocket
                    ┌──────────────────┐
                    │   Backend API    │
                    └──────────────────┘

3.1 核心设计原则

  1. 单向数据流View → Action → Store/API → View避免组件间隐式耦合。
  2. 权限后置:路由与按钮权限均来自后端,前端只做渲染控制。
  3. 页面薄、逻辑厚:页面组件负责组装,业务逻辑下沉到 Hooks 和 Stores。
  4. 约定优于配置CRUD 页面遵循 ProComponents 模板,减少决策成本。

4. 目录结构

chat-one-admin-web/
├── public/                     # 静态资源favicon、静态 JSON
├── src/
│   ├── api/                    # API 接口(按业务模块划分)
│   │   ├── auth.ts
│   │   ├── user.ts
│   │   └── types/              # 接口请求/响应类型
│   ├── assets/                 # 图片、字体等
│   ├── components/             # 全局通用组件
│   │   ├── Access/             # 权限控制组件
│   │   ├── Icon/               # 图标封装
│   │   └── ...
│   ├── hooks/                  # 自定义 Hooks
│   │   ├── useTable.ts
│   │   ├── useAuth.ts
│   │   └── usePermission.ts
│   ├── layouts/                # 布局
│   │   ├── BasicLayout/        # 侧边栏 + 顶栏 + 内容区ProLayout
│   │   │   └── index.tsx
│   │   └── BlankLayout/        # 登录页等无框架页面
│   │       └── index.tsx
│   ├── pages/                  # 页面(按业务模块划分,约定式路由)
│   │   ├── login/
│   │   │   └── index.tsx
│   │   ├── dashboard/
│   │   │   └── index.tsx
│   │   ├── system/
│   │   │   └── user/
│   │   │       ├── index.tsx   # 列表页
│   │   │       └── components/
│   │   │           └── UserForm.tsx
│   │   └── exception/
│   │       ├── 403.tsx
│   │       └── 404.tsx
│   ├── router/
│   │   ├── index.tsx           # 路由入口createBrowserRouter
│   │   ├── routes.tsx          # 静态路由登录、404
│   │   ├── AuthGuard.tsx       # 路由守卫(鉴权、动态路由加载)
│   │   └── utils.ts            # 菜单 → 路由转换工具
│   ├── stores/
│   │   ├── user.ts             # 用户信息、Token
│   │   ├── permission.ts       # 动态路由、菜单
│   │   ├── app.ts              # 侧边栏折叠、主题、语言
│   │   └── dict.ts             # 数据字典缓存
│   ├── styles/
│   │   ├── global.css          # 全局样式入口
│   │   └── theme.ts            # Ant Design 主题 Token 配置
│   ├── utils/
│   │   ├── request.ts          # Axios 封装
│   │   ├── auth.ts             # Token 存取
│   │   ├── storage.ts          # localStorage 封装
│   │   └── index.ts
│   ├── App.tsx
│   ├── main.tsx
│   └── vite-env.d.ts
├── .env                        # 公共环境变量
├── .env.development
├── .env.production
├── vite.config.ts
├── tsconfig.json
├── eslint.config.js
├── package.json
└── docs/                       # 项目文档

5. 核心模块设计

5.1 认证与鉴权

登录流程:
  用户输入账号密码
       ↓
  POST /api/auth/login → 返回 accessToken + refreshToken
       ↓
  存储 Token内存 + localStoragerefreshToken 建议 httpOnly Cookie 由后端设置)
       ↓
  GET /api/auth/userInfo → 用户信息 + 角色 + 权限码
       ↓
  GET /api/auth/menus → 动态菜单/路由配置
       ↓
  生成动态路由并注入 Router → 跳转首页

Token 策略(推荐):

项目 方案
Access Token 短期1530 min放 Authorization Header
Refresh Token 长期httpOnly Cookie 或安全存储
过期处理 401 拦截 → 尝试 refresh → 失败则跳转登录
多 Tab 通过 storage 事件或 BroadcastChannel 同步登出

权限模型RBAC角色 → 权限 → 资源)

  • 路由级:后端返回菜单树,前端转换为 RouteObject[] 动态注册。
  • 按钮级:权限码字符串(如 user:create),通过 <Access /> 组件或 usePermission Hook 控制。
  • 数据级:由后端接口过滤,前端不做数据权限逻辑。

5.2 路由设计

// 静态路由(无需权限)
const staticRoutes: RouteObject[] = [
  { path: '/login', element: <LoginPage />, handle: { hidden: true } },
  { path: '/404', element: <NotFoundPage />, handle: { hidden: true } },
]

// 动态路由(后端驱动,示例结构)
interface MenuRoute {
  path: string
  name: string
  component: string        // 组件路径,如 'system/user/index'
  meta: {
    title: string
    icon?: string
    permissions?: string[] // 页面级权限码
    keepAlive?: boolean
  }
  children?: MenuRoute[]
}

路由守卫AuthGuard职责

  1. 未登录 → 重定向 /login?redirect=原路径
  2. 已登录但未加载动态路由 → 拉取菜单 → 生成路由 → 渲染 <Outlet />
  3. 无权限 → 403 页面
  4. 切换路由 → NProgress 进度条
// router/AuthGuard.tsx 示意
function AuthGuard() {
  const { token } = useUserStore();
  const { routesLoaded, loadRoutes } = usePermissionStore();
  const location = useLocation();

  useEffect(() => {
    if (token && !routesLoaded) loadRoutes();
  }, [token, routesLoaded]);

  if (!token) return <Navigate to={`/login?redirect=${location.pathname}`} replace />;
  if (!routesLoaded) return <PageLoading />;

  return <Outlet />;
}

动态路由注入:

// 后端 component 字段 → React.lazy 懒加载
const modules = import.meta.glob('../pages/**/index.tsx');

function resolveComponent(path: string) {
  const key = `../pages/${path}/index.tsx`;
  return lazy(modules[key] as () => Promise<{ default: ComponentType }>);
}

5.3 状态管理Zustand

Store 职责 持久化
useUserStore Token、用户信息、登录/登出 Token → localStoragepersist 中间件)
usePermissionStore 动态路由、菜单树、权限码集合 否(每次登录重新拉取)
useAppStore 侧边栏状态、主题、语言、设备类型 部分 → localStorage
useDictStore 数据字典(状态枚举等) 会话级缓存
// stores/user.ts 示意
import { create } from 'zustand';
import { persist } from 'zustand/middleware';

interface UserState {
  token: string | null;
  userInfo: UserInfo | null;
  setToken: (token: string) => void;
  logout: () => void;
}

export const useUserStore = create<UserState>()(
  persist(
    set => ({
      token: null,
      userInfo: null,
      setToken: token => set({ token }),
      logout: () => set({ token: null, userInfo: null }),
    }),
    { name: 'user-store', partialize: s => ({ token: s.token }) },
  ),
);

原则: 只有跨页面共享的状态才进 Store页面私有状态用 useState/useReducer 即可。服务端列表数据优先用 TanStack Query 管理。

5.4 API 层

// utils/request.ts 核心能力
const service = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL, timeout: 15000 });

// 请求拦截:注入 Token
// 响应拦截统一错误码处理、Token 刷新、message 提示
// 取消重复请求可选AbortController
// 下载文件blob特殊处理

接口组织规范:

// api/user.ts
export function getUserList(params: UserQuery) {
  return request.get<PageResult<UserVO>>('/users', { params });
}
export function createUser(data: UserCreateDTO) {
  return request.post<UserVO>('/users', data);
}

与后端协作:

  • 统一响应格式:{ code: number, data: T, message: string }
  • 业务成功码约定(如 code === 0200
  • 提供 OpenAPI/Swagger 文档,前端用工具自动生成 TS 类型

5.5 布局系统

推荐使用 ProLayout@ant-design/pro-components)作为基础布局:

┌──────────────────────────────────────────────────────┐
│  Logo    面包屑 / 标签页(Tabs)          用户头像 ▼   │  ← Header
├────────┬─────────────────────────────────────────────┤
│        │                                             │
│  侧    │              Main Content                   │
│  边    │         Outlet + 页面缓存)                │
│  栏    │                                             │
│        │                                             │
├────────┴─────────────────────────────────────────────┤
│  折叠按钮                                            │
└──────────────────────────────────────────────────────┘

主流交互特性:

  • 侧边栏可折叠,移动端自动切换为 Drawer
  • 多标签页Tabs:缓存已访问页面,支持关闭/刷新(react-activation 或自研 Tab + 条件渲染)
  • 面包屑导航ProLayout 内置)
  • 全屏、主题切换(亮/暗)、国际化入口(可选)
// layouts/BasicLayout/index.tsx 示意
<ProLayout
  title="ChatOne"
  logo="/logo.svg"
  route={{ routes: menuRoutes }}
  location={{ pathname: location.pathname }}
  menuItemRender={(item, dom) => <Link to={item.path!}>{dom}</Link>}
>
  <TabLayout>
    <Outlet />
  </TabLayout>
</ProLayout>

5.6 通用业务组件

中小型项目的效率关键 — 优先使用 ProComponents必要时二次封装

ProTable表格页模板

┌─ 搜索区(可折叠)──────────────────────────┐
│  [关键词] [状态 ▼] [日期范围]  [搜索] [重置] │
├─ 工具栏 ────────────────────────────────────┤
│  [+ 新增]  [导出]  [批量删除]                │
├─ 数据表格 ──────────────────────────────────┤
│  ☐  姓名    状态    创建时间    操作         │
│  ☐  张三    启用    2026-01-01  编辑 删除    │
├─ 分页 ──────────────────────────────────────┤
│              < 1 2 3 ... 10 >               │
└─────────────────────────────────────────────┘

配置驱动:columnsrequest(返回 { data, total, success })两个核心 props。

// pages/system/user/index.tsx 示意
<ProTable<UserVO>
  columns={columns}
  request={async params => {
    const res = await getUserList(params);
    return { data: res.data.list, total: res.data.total, success: true };
  }}
  toolBarRender={() => [
    <Access key="create" permission="user:create">
      <Button type="primary" onClick={handleCreate}>
        新增
      </Button>
    </Access>,
  ]}
/>

ProForm表单弹窗/抽屉)

  • 支持 ModalForm / DrawerForm 两种模式
  • Schema 驱动字段渲染(ProFormTextProFormSelect 等)
  • 内置新增/编辑模式切换

Access权限组件

// components/Access/index.tsx
interface AccessProps {
  permission: string | string[];
  children: React.ReactNode;
}

function Access({ permission, children }: AccessProps) {
  const { hasPermission } = usePermission();
  if (!hasPermission(permission)) return null;
  return <>{children}</>;
}

5.7 典型 CRUD 页面模式

每个业务模块的标准文件:

pages/system/user/
├── index.tsx              # 列表页ProTable
├── components/
│   └── UserForm.tsx       # 新增/编辑表单ModalForm / DrawerForm
└── types.ts               # 页面级类型(可选)

列表页职责: 组装 ProTable 配置,处理新增/编辑/删除事件。
表单组件职责: 接收 record prop提交成功后回调 onSuccess


6. 横切关注点

6.1 错误处理

场景 处理方式
网络错误 message.error 提示 + 可选重试
401 未授权 刷新 Token 或跳转登录
403 无权限 提示 + 停留当前页
404 接口不存在 开发环境 console 详细日志
500 服务端错误 友好提示,上报 Sentry可选
表单校验失败 Ant Design Form 字段级红色提示
React 渲染错误 <ErrorBoundary> 捕获并展示降级 UI

6.2 加载状态

  • 全局:路由切换 NProgress 细条
  • 页面级<Spin><Skeleton>(首屏)
  • 按钮级<Button loading={submitting}>
  • 表格级ProTable 内置 loading 状态

6.3 国际化(可选)

  • 使用 react-i18next,语言包按模块拆分
  • Ant Design ConfigProvider 同步切换 locale
  • 中小型项目若仅中文,可暂不引入,预留 meta.title 的 i18n key

6.4 主题

  • 基于 Ant Design 5 Design Token + ConfigProvider 实现亮/暗主题
  • 主色、圆角、字体大小通过 theme.ts 统一管理
  • 暗色模式:algorithm: theme.darkAlgorithm
// App.tsx 示意
<ConfigProvider
  locale={zhCN}
  theme={{
    algorithm: isDark ? theme.darkAlgorithm : theme.defaultAlgorithm,
    token: { colorPrimary: '#1677ff', borderRadius: 6 },
  }}
>
  <App />
</ConfigProvider>

7. 开发规范

7.1 命名约定

类型 规范 示例
组件文件 PascalCase UserForm.tsx
页面入口 index.tsx pages/system/user/index.tsx
自定义 Hook camelCaseuse 前缀 useTable.ts
API 函数 camelCase动词开头 getUserList
常量 UPPER_SNAKE_CASE TOKEN_KEY
路由 path kebab-case /system/user-list

7.2 组件编写规范

  • 默认使用函数组件 + TypeScript
  • Props 使用 interfacetype 显式声明
  • 单文件组件不超过 300 行,超出则拆分
  • 样式优先 Ant Design Token局部样式用 CSS Modules
  • 列表渲染必须提供稳定的 rowKey
  • 避免在 render 中创建内联对象/函数(或使用 useMemo/useCallback

7.3 Git 提交规范Conventional Commits

feat: 新增用户管理页面
fix: 修复 Token 刷新后路由丢失
refactor: 重构 ProTable 搜索逻辑
docs: 更新设计方案文档

8. 环境配置

# .env.development
VITE_APP_TITLE=ChatOne 管理后台
VITE_API_BASE_URL=/api
VITE_MOCK=false

# .env.production
VITE_APP_TITLE=ChatOne 管理后台
VITE_API_BASE_URL=https://api.example.com

Vite 代理(开发环境):

// vite.config.ts
server: {
  proxy: {
    '/api': {
      target: 'http://localhost:8080',
      changeOrigin: true,
    },
  },
}

9. 构建与部署

9.1 构建命令

pnpm dev          # 本地开发
pnpm build        # 生产构建 → dist/
pnpm preview      # 预览构建产物
pnpm lint         # 代码检查
pnpm test         # 单元测试

9.2 构建优化

策略 手段
分包 manualChunks 分离 react、antd、echarts
按需引入 Ant Design 5 默认 Tree ShakingProComponents 按需导入
路由懒加载 React.lazy + import.meta.glob
压缩 gzip / brotliNginx 层)
缓存 文件名带 content hash
图片 小图 inline大图 CDN

9.3 部署架构

用户 → CDN/Nginx → 静态文件 (dist/)
                 → /api 反向代理 → 后端服务
  • SPA 需要 Nginx try_files $uri /index.html 配置
  • 推荐 Docker 多阶段构建,产物仅含 dist + Nginx

9.4 CI/CD 流水线

Push/PR → ESLint + TypeCheck → Vitest → Build → Deploy (staging/prod)

推荐 GitHub Actions 或 GitLab CIPR 必须通过 lint 和 build。


10. 安全要点

措施
XSS React 默认转义;dangerouslySetInnerHTML 必须消毒DOMPurify
CSRF Cookie 方案启用 CSRF TokenToken Header 方案风险较低
敏感信息 .env 不入库;生产环境变量由 CI 注入
权限 前端权限仅为 UX 优化,后端必须独立校验
依赖安全 定期 pnpm auditDependabot 自动 PR

11. 可选增强(按阶段引入)

阶段 能力 工具
MVP Mock 数据 MSW (Mock Service Worker)
V1.1 操作日志、消息通知 WebSocket / SSE
V1.2 错误监控 Sentry
V1.2 页面缓存 react-activation
V2.0 低代码表单 ProForm Schema + 自研表单设计器
V2.0 数据大屏 ECharts + 自适应方案

12. 实施路线图

Phase 1 — 基础脚手架12 周)

  • 初始化 Vite + React 18 + TS 项目
  • 集成 Ant Design 5、ProComponents、Zustand、React Router
  • 实现 ProLayout 布局(侧边栏 + 顶栏 + 内容区)
  • 实现登录页 + Token 认证流程
  • Axios 封装 + 环境变量配置
  • ESLint + Prettier + Husky 配置

Phase 2 — 权限与通用组件12 周)

  • 动态路由 + 菜单渲染
  • Access 权限组件 + usePermission Hook
  • 基于 ProTable / ProForm 封装业务模板
  • 多标签页Tabs+ 页面缓存
  • 数据字典 Store

Phase 3 — 业务模块开发(持续)

  • 按后端模块迭代 CRUD 页面
  • Dashboard 仪表盘
  • 完善错误处理与边界场景

Phase 4 — 质量与上线1 周)

  • 核心流程 E2E 测试
  • 构建优化 + CI/CD
  • 部署文档 + 运维手册

13. 参考资源

资源 链接
React 官方文档 https://react.dev
Vite 官方文档 https://vite.dev
Ant Design 5 https://ant.design
Ant Design Pro https://pro.ant.design
ProComponents https://procomponents.ant.design
Zustand https://zustand.docs.pmnd.rs
ahooks https://ahooks.js.org
TanStack Query https://tanstack.com/query

附录 AVue 技术栈映射表

React 主栈 Vue 等价
React 18 Vue 3
Zustand Pinia
React Router 6 Vue Router 4
Ant Design 5 Element Plus
ProComponents 自研 ProTable / ProForm
ahooks VueUse
函数组件 + Hooks <script setup>
<Access /> 组件 v-permission 指令

附录 B关键依赖版本参考

{
  "react": "^18.3",
  "react-dom": "^18.3",
  "react-router-dom": "^6.28",
  "antd": "^5.22",
  "@ant-design/pro-components": "^2.8",
  "@ant-design/icons": "^5.5",
  "zustand": "^5.0",
  "@tanstack/react-query": "^5.62",
  "axios": "^1.7",
  "ahooks": "^3.8",
  "dayjs": "^1.11",
  "vite": "^6.0",
  "typescript": "^5.7",
  "vitest": "^3.0",
  "@testing-library/react": "^16.0",
  "eslint": "^9.0"
}

本文档将随项目演进持续更新。