wangdl 76f1dcbe8d
All checks were successful
Deploy Admin Frontend / build-and-deploy (push) Successful in 12s
fix: prevent infinite redirect loop on /login page
2026-07-08 19:45:14 +08:00

知习 Admin

企业知识管理中台 — 后台管理系统前端。

技术栈

类别 技术
框架 React 19 + TypeScript
构建 Vite 8
UI Ant Design 5 + @ant-design/pro-components 2.8
状态管理 @tanstack/react-query 5服务端状态+ Zustand客户端偏好
路由 react-router-dom v7
图表 ECharts 5 + echarts-for-react 3
HTTP Axios拦截器cookie 认证、自动刷新、错误通知)
安全 httpOnly cookie 认证token 不可被 JS 读取)

项目结构

src/
├── api/                 # 33 个 API 模块(纯函数,导出 API 对象 + DTO 类型)
│   └── index.ts         # 统一 barrel export
├── components/          # 11 个共享组件
│   ├── ErrorBoundary    # 渲染崩溃兜底
│   ├── AuthGuard        # 登录鉴权
│   ├── PermissionGuard  # 角色权限
│   └── ...
├── config/
│   └── menu.tsx         # 侧边栏菜单树 + 角色过滤
├── constants/
│   └── roles.ts         # 角色标签/颜色/层级
├── contexts/
│   └── AuthContext.tsx   # 认证上下文(唯一 Context
├── hooks/
│   └── use-auth-query.ts # 认证 TanStack Query hooks
├── layouts/
│   └── AdminLayout.tsx  # ProLayout 管理后台骨架
├── lib/
│   ├── api-client.ts    # Axios 实例withCredentials, 401 刷新, 错误通知)
│   ├── token.ts         # 用户信息缓存token 在 httpOnly cookie 中)
│   ├── antd-global.ts   # 全局 message/notification 引用
│   └── error-handler.ts # 统一错误格式化和 toast
├── pages/               # 39 个页面 + learning/ 子目录
│   ├── Dashboard        # 数据看板
│   ├── UserManagement   # 管理员 CRUD
│   ├── ImportMonitor    # 文档导入监控
│   ├── AiGateway        # AI 网关路由管理
│   ├── Servers          # 服务器运维监控
│   ├── TaskAssistant    # AI 任务助手(流式对话)
│   └── ...
├── services/
│   ├── ai-chat.ts       # SSE 流式聊天
│   ├── http-client.ts   # 向后兼容重导出
│   └── token-store.ts   # 向后兼容重导出
├── stores/
│   ├── index.ts         # Zustand store barrel
│   └── ui-store.ts      # 侧边栏偏好persist localStorage
├── types/               # 18 个领域类型文件,~80 个类型
│   ├── index.ts         # 统一 barrel export
│   ├── admin.ts         # AdminUser, AuditLog, DashboardStats
│   ├── knowledge.ts     # KnowledgeBase, ImportJob, Source
│   ├── learning.ts      # ReadingEvent, Session, Progress
│   ├── server.ts        # ServerInfo, ProcessInfo, Health
│   ├── ai.ts            # AiRoute, AiProvider, FallbackEvent
│   ├── billing.ts       # CostItem, CostSummary, BillingInfo
│   ├── ui.ts            # TypedColumn<T>, SortState, FilterState
│   └── ...
└── vite-env.d.ts        # 环境变量类型声明

快速开始

# 1. 安装依赖
npm install

# 2. 配置环境变量
cp .env.example .env
# 编辑 .env设置 VITE_API_BASE_URL本地开发指向 http://127.0.0.1:3000

# 3. 启动开发服务器
npm run dev      # → http://localhost:5174

# 4. 生产构建
npm run build    # → dist/

环境变量

变量 必需 默认值 说明
VITE_API_BASE_URL https://api.longde.cloud API 后端地址(仅开发模式使用)
  • 本地开发VITE_API_BASE_URL=http://127.0.0.1:3000Vite dev server 代理 /admin-api/ 到本地 API
  • 生产环境不需要设置Nginx 将 /admin-api/ 反向代理到后端
  • .env.example 已提交到 Git复制即可使用
  • .env.gitignore 中,不会被提交

认证架构

登录 POST /admin-api/auth/login
  → 后端 Set-Cookie: admin_access_token (httpOnly, Secure, SameSite=Strict)
  → 前端仅缓存 admin_user 信息到 localStorage非敏感

后续请求
  → axios withCredentials: true → 浏览器自动携带 cookie
  → 后端 AdminAuthGuard 从 cookie 读取 JWT
  → 401 → 自动调用 /admin-api/auth/refreshcookie 中的 refresh token
  → 刷新失败 → 清除缓存 → 跳转 /login

登出 POST /admin-api/auth/logout
  → 后端 Clear-Cookie
  → 前端清除 admin_user 缓存 + TanStack Query 缓存

角色体系

角色 说明 权限范围
SUPER_ADMIN 超级管理员 全部权限,可管理其他管理员
ADMIN 管理员 用户管理、仪表盘、审计日志
OPERATIONS 运营人员 仪表盘、审计日志(只读)
DEVELOPER 开发者 仪表盘(只读)
READONLY 只读用户 仪表盘(只读)

部署

CI/CDGitea Actions

推送到 main 分支自动触发 .gitea/workflows/deploy.yml

git clone → npm install → npm run build → rsync dist/ → /opt/zhixi/admin/dist/ → nginx reload

生产服务器架构

admin.longde.cloud (Nginx)
  ├── /               → /opt/zhixi/admin/dist/ (静态文件, SPA fallback)
  ├── /admin-api/     → proxy_pass http://127.0.0.1:3000
  └── /assets/        → 静态资源缓存 (1年, gzip)

手动部署

npm run build
rsync -av --delete dist/ ubuntu@120.53.227.155:/opt/zhixi/admin/dist/
ssh ubuntu@120.53.227.155 'sudo systemctl reload nginx'

开发规范

状态管理原则

TanStack Query → 服务端数据缓存、去重、refetch
Zustand        → 客户端全局状态UI 偏好)
AuthContext     → 认证(登录/登出/权限)
useState       → 页面局部 UI弹窗、表单、选中行
  • 不在组件内 useEffect + fetch — 一律用 useQuery
  • 不新建 Context — 除非是真正的全局状态
  • 页面局部的 useState 不需要提到 Store

错误处理

// 异步操作中使用 toastError
try { await something() } catch (err) { toastError(err, '操作失败') }

// 全局兜底
// - ErrorBoundary 包裹所有路由(渲染崩溃不白屏)
// - TanStack Query mutation 默认 onError → toastError
// - Axios 响应拦截器 → 网络/业务错误自动 notification.error

TypeScript

  • strict: truenoImplicitAnystrictNullChecks 待收紧)
  • 所有 API 模块有完整类型DTO + Response
  • Table 列使用具体记录类型,不用 (_: any, r: any)
  • 新增类型放在 src/types/ 对应领域文件,通过 index.ts 导出

新增页面 Checklist

  1. src/pages/ 创建页面组件
  2. src/types/ 补充缺失的领域类型
  3. src/api/ 添加对应 API 模块(如需要)
  4. App.tsx 添加路由(懒加载 + 角色守卫)
  5. config/menu.tsx 添加菜单项
Description
No description provided
Readme 1.7 MiB
Languages
TypeScript 99.7%
JavaScript 0.2%