docs: README 全面更新 — 环境变量 + 部署 + 认证 + 开发规范
All checks were successful
Deploy Admin Frontend / build-and-deploy (push) Successful in 13s

- 更新项目结构(反映 18 个 types 文件、33 个 API 模块、Zustand 等)
- 添加环境变量说明
- 添加认证架构(httpOnly cookie 流程)
- 添加部署文档(CI/CD + 服务器架构 + 手动部署)
- 添加开发规范(状态管理、错误处理、TypeScript)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
wangdl 2026-07-04 11:29:37 +08:00
parent 176593a8c2
commit d6b1df061d

212
README.md
View File

@ -4,78 +4,192 @@
## 技术栈
- React 19 + TypeScript 6
- Vite 8
- Ant Design 5 + @ant-design/pro-components 2.8
- @tanstack/react-query 5
- ECharts 5 + echarts-for-react 3
- dayjs
- react-router-dom v7
| 类别 | 技术 |
|------|------|
| 框架 | 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/
├── components/ # 共享组件
│ ├── AuditLogTable # 审计日志 ProTable
│ ├── ConfirmDangerModal # 高危操作确认弹窗
│ ├── DetailDrawer # 侧滑详情抽屉
│ ├── EChartsChartContainer # 图表容器
│ ├── EmptyState # 空状态占位
│ ├── MetricCard # 指标卡
│ ├── StatusTag # 状态标签
│ ├── AuthGuard # 登录鉴权守卫
│ ├── PageLoading # 路由懒加载 Spin
│ └── PermissionGuard # 角色权限守卫
├── api/ # 33 个 API 模块(纯函数,导出 API 对象 + DTO 类型)
│ └── index.ts # 统一 barrel export
├── components/ # 11 个共享组件
│ ├── ErrorBoundary # 渲染崩溃兜底
│ ├── AuthGuard # 登录鉴权
│ ├── PermissionGuard # 角色权限
│ └── ...
├── config/
│ └── menu.tsx # 菜单树与角色过滤
│ └── menu.tsx # 侧边栏菜单树 + 角色过滤
├── constants/
│ └── roles.ts # 角色标签/颜色/层级
├── contexts/
│ └── AuthContext.tsx # 认证上下文
│ └── AuthContext.tsx # 认证上下文(唯一 Context
├── hooks/
│ └── use-auth-query.ts # React Query 认证 hooks
│ └── use-auth-query.ts # 认证 TanStack Query hooks
├── layouts/
│ └── AdminLayout.tsx # 管理后台布局(侧边栏/顶栏/面包屑)
├── pages/
│ ├── Dashboard # 数据看板(指标卡 + 图表 + 审计日志)
│ └── 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
│ ├── Login # 登录页
│ ├── Placeholder # 占位页
│ ├── 403/404/500 # 错误页
├── routes/
│ └── index.tsx # 路由配置(懒加载 + 角色要求)
│ ├── ImportMonitor # 文档导入监控
│ ├── AiGateway # AI 网关路由管理
│ ├── Servers # 服务器运维监控
│ ├── TaskAssistant # AI 任务助手(流式对话)
│ └── ...
├── services/
│ ├── admin-api.ts # 类型化 API 函数
│ ├── http-client.ts # Fetch 封装401 自动刷新队列)
│ ├── token-store.ts # Token 本地存储
│ └── mock-data.ts # DEV 模式 Mock 数据
└── types/
├── admin.ts # AdminUser, DashboardStats, AuditLog 等
└── api.ts # PaginatedResult, ApiError
│ ├── 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 # 环境变量类型声明
```
## 启动
## 快速开始
```bash
# 1. 安装依赖
npm install
npm run dev # 开发模式,默认 http://localhost:5173
npm run build # 生产构建
# 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/
```
## 认证流程
## 环境变量
1. `AuthGuard` 检查登录状态,未登录跳转 `/login`
2. `PermissionGuard` 检查角色权限,不足跳转 `/403`
3. HTTP 客户端自动处理 401 → refresh token → 重试请求
4. refresh token 失败时强制退出到 `/login`
| 变量 | 必需 | 默认值 | 说明 |
|------|------|--------|------|
| `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/refreshcookie 中的 refresh token
→ 刷新失败 → 清除缓存 → 跳转 /login
登出 POST /admin-api/auth/logout
→ 后端 Clear-Cookie
→ 前端清除 admin_user 缓存 + TanStack Query 缓存
```
## 角色体系
| 角色 | 说明 | 权限范围 |
|------|------|---------|
| SUPER_ADMIN | 超级管理员 | 全部权限,可管理其他管理员 |
| ADMIN | 管理员 | 用户管理、仪表盘、审计日志 |
| OPERATIONS | 运营人员 | 仪表盘、审计日志(只读) |
| DEVELOPER | 开发者 | 仪表盘(只读) |
| READONLY | 只读用户 | 仪表盘(只读) |
| `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)
```
### 手动部署
```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` 添加菜单项