# 知习 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, SortState, FilterState │ └── ... └── vite-env.d.ts # 环境变量类型声明 ``` ## 快速开始 ```bash # 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:3000`(Vite 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/refresh(cookie 中的 refresh token) → 刷新失败 → 清除缓存 → 跳转 /login 登出 POST /admin-api/auth/logout → 后端 Clear-Cookie → 前端清除 admin_user 缓存 + TanStack Query 缓存 ``` ## 角色体系 | 角色 | 说明 | 权限范围 | |------|------|---------| | `SUPER_ADMIN` | 超级管理员 | 全部权限,可管理其他管理员 | | `ADMIN` | 管理员 | 用户管理、仪表盘、审计日志 | | `OPERATIONS` | 运营人员 | 仪表盘、审计日志(只读) | | `DEVELOPER` | 开发者 | 仪表盘(只读) | | `READONLY` | 只读用户 | 仪表盘(只读) | ## 部署 ### CI/CD(Gitea 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) ``` ### 手动部署 ```bash 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 ### 错误处理 ```typescript // 异步操作中使用 toastError try { await something() } catch (err) { toastError(err, '操作失败') } // 全局兜底 // - ErrorBoundary 包裹所有路由(渲染崩溃不白屏) // - TanStack Query mutation 默认 onError → toastError // - Axios 响应拦截器 → 网络/业务错误自动 notification.error ``` ### TypeScript - `strict: true`(`noImplicitAny` 和 `strictNullChecks` 待收紧) - 所有 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` 添加菜单项