docs: README 全面更新 — 环境变量 + 部署 + 认证 + 开发规范
All checks were successful
Deploy Admin Frontend / build-and-deploy (push) Successful in 13s
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:
parent
176593a8c2
commit
d6b1df061d
212
README.md
212
README.md
@ -4,78 +4,192 @@
|
|||||||
|
|
||||||
## 技术栈
|
## 技术栈
|
||||||
|
|
||||||
- React 19 + TypeScript 6
|
| 类别 | 技术 |
|
||||||
- Vite 8
|
|------|------|
|
||||||
- Ant Design 5 + @ant-design/pro-components 2.8
|
| 框架 | React 19 + TypeScript |
|
||||||
- @tanstack/react-query 5
|
| 构建 | Vite 8 |
|
||||||
- ECharts 5 + echarts-for-react 3
|
| UI | Ant Design 5 + @ant-design/pro-components 2.8 |
|
||||||
- dayjs
|
| 状态管理 | @tanstack/react-query 5(服务端状态)+ Zustand(客户端偏好) |
|
||||||
- react-router-dom v7
|
| 路由 | react-router-dom v7 |
|
||||||
|
| 图表 | ECharts 5 + echarts-for-react 3 |
|
||||||
|
| HTTP | Axios(拦截器:cookie 认证、自动刷新、错误通知) |
|
||||||
|
| 安全 | httpOnly cookie 认证(token 不可被 JS 读取) |
|
||||||
|
|
||||||
## 项目结构
|
## 项目结构
|
||||||
|
|
||||||
```
|
```
|
||||||
src/
|
src/
|
||||||
├── components/ # 共享组件
|
├── api/ # 33 个 API 模块(纯函数,导出 API 对象 + DTO 类型)
|
||||||
│ ├── AuditLogTable # 审计日志 ProTable
|
│ └── index.ts # 统一 barrel export
|
||||||
│ ├── ConfirmDangerModal # 高危操作确认弹窗
|
├── components/ # 11 个共享组件
|
||||||
│ ├── DetailDrawer # 侧滑详情抽屉
|
│ ├── ErrorBoundary # 渲染崩溃兜底
|
||||||
│ ├── EChartsChartContainer # 图表容器
|
│ ├── AuthGuard # 登录鉴权
|
||||||
│ ├── EmptyState # 空状态占位
|
│ ├── PermissionGuard # 角色权限
|
||||||
│ ├── MetricCard # 指标卡
|
│ └── ...
|
||||||
│ ├── StatusTag # 状态标签
|
|
||||||
│ ├── AuthGuard # 登录鉴权守卫
|
|
||||||
│ ├── PageLoading # 路由懒加载 Spin
|
|
||||||
│ └── PermissionGuard # 角色权限守卫
|
|
||||||
├── config/
|
├── config/
|
||||||
│ └── menu.tsx # 菜单树与角色过滤
|
│ └── menu.tsx # 侧边栏菜单树 + 角色过滤
|
||||||
├── constants/
|
├── constants/
|
||||||
│ └── roles.ts # 角色标签/颜色/层级
|
│ └── roles.ts # 角色标签/颜色/层级
|
||||||
├── contexts/
|
├── contexts/
|
||||||
│ └── AuthContext.tsx # 认证上下文
|
│ └── AuthContext.tsx # 认证上下文(唯一 Context)
|
||||||
├── hooks/
|
├── hooks/
|
||||||
│ └── use-auth-query.ts # React Query 认证 hooks
|
│ └── use-auth-query.ts # 认证 TanStack Query hooks
|
||||||
├── layouts/
|
├── layouts/
|
||||||
│ └── AdminLayout.tsx # 管理后台布局(侧边栏/顶栏/面包屑)
|
│ └── AdminLayout.tsx # ProLayout 管理后台骨架
|
||||||
├── pages/
|
├── lib/
|
||||||
│ ├── Dashboard # 数据看板(指标卡 + 图表 + 审计日志)
|
│ ├── 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
|
│ ├── UserManagement # 管理员 CRUD
|
||||||
│ ├── Login # 登录页
|
│ ├── ImportMonitor # 文档导入监控
|
||||||
│ ├── Placeholder # 占位页
|
│ ├── AiGateway # AI 网关路由管理
|
||||||
│ ├── 403/404/500 # 错误页
|
│ ├── Servers # 服务器运维监控
|
||||||
├── routes/
|
│ ├── TaskAssistant # AI 任务助手(流式对话)
|
||||||
│ └── index.tsx # 路由配置(懒加载 + 角色要求)
|
│ └── ...
|
||||||
├── services/
|
├── services/
|
||||||
│ ├── admin-api.ts # 类型化 API 函数
|
│ ├── ai-chat.ts # SSE 流式聊天
|
||||||
│ ├── http-client.ts # Fetch 封装(401 自动刷新队列)
|
│ ├── http-client.ts # 向后兼容重导出
|
||||||
│ ├── token-store.ts # Token 本地存储
|
│ └── token-store.ts # 向后兼容重导出
|
||||||
│ └── mock-data.ts # DEV 模式 Mock 数据
|
├── stores/
|
||||||
└── types/
|
│ ├── index.ts # Zustand store barrel
|
||||||
├── admin.ts # AdminUser, DashboardStats, AuditLog 等
|
│ └── ui-store.ts # 侧边栏偏好(persist localStorage)
|
||||||
└── api.ts # PaginatedResult, ApiError
|
├── 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
|
```bash
|
||||||
|
# 1. 安装依赖
|
||||||
npm install
|
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 → 重试请求
|
| `VITE_API_BASE_URL` | 否 | `https://api.longde.cloud` | API 后端地址(仅开发模式使用) |
|
||||||
4. refresh token 失败时强制退出到 `/login`
|
|
||||||
|
- **本地开发**:`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 | 超级管理员 | 全部权限,可管理其他管理员 |
|
| `SUPER_ADMIN` | 超级管理员 | 全部权限,可管理其他管理员 |
|
||||||
| ADMIN | 管理员 | 用户管理、仪表盘、审计日志 |
|
| `ADMIN` | 管理员 | 用户管理、仪表盘、审计日志 |
|
||||||
| OPERATIONS | 运营人员 | 仪表盘、审计日志(只读) |
|
| `OPERATIONS` | 运营人员 | 仪表盘、审计日志(只读) |
|
||||||
| DEVELOPER | 开发者 | 仪表盘(只读) |
|
| `DEVELOPER` | 开发者 | 仪表盘(只读) |
|
||||||
| READONLY | 只读用户 | 仪表盘(只读) |
|
| `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` 添加菜单项
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user