feat():learning后台管理前端页面初始化

This commit is contained in:
yuj
2025-12-04 17:51:24 +08:00
commit 83a614bd75
97 changed files with 23324 additions and 0 deletions

392
QUICK_REFERENCE.md Normal file
View File

@@ -0,0 +1,392 @@
# Goalfymax 管理后台 - 快速参考指南
## 项目信息
| 项目 | 说明 |
|------|------|
| **名称** | goalfymax-admin-web |
| **框架** | React 18.3.1 + TypeScript + Vite |
| **UI 库** | Ant Design 5.27.4 |
| **路由** | React Router 7.9.4 |
| **HTTP** | Axios 1.12.2 |
| **状态管理** | Jotai 2.15.0 |
| **总文件数** | 48 个 TS/TSX 文件 |
---
## 目录速查表
| 目录 | 用途 | 示例 |
|------|------|------|
| `src/pages/` | 页面组件 | UserLevelConfigs.tsx |
| `src/services/` | API 服务 | userLevelConfigApi.ts |
| `src/types/` | TypeScript 类型 | userLevelConfig.ts |
| `src/components/` | 可复用组件 | Layout.tsx, DynamicMenu.tsx |
| `src/hooks/` | 自定义 Hooks | useAuth.ts, usePagePermissions.ts |
| `src/atoms/` | Jotai 状态管理 | auth.ts |
| `src/routes/` | 路由配置 | DynamicRoutes.tsx |
| `src/utils/` | 工具函数 | storageMigration.ts |
---
## 关键概念速览
### 1. 双层路由系统
```
App.tsx (静态路由) + DynamicRoutes.tsx (权限感知路由)
Layout 组件 (侧边栏 + 菜单)
DynamicMenu (权限过滤菜单项)
```
### 2. API 调用流程
```
页面组件 → API 服务 → ApiClient → Axios → 后端 API
```
### 3. 权限检查层级
```
页面权限 (usePagePermissions) → 菜单权限 (DynamicMenu) → 操作权限 (usePermissions)
```
---
## 常见任务速查
### 添加新的配置管理页面
**所需文件数**3-4 个
**开发时间**:约 30-60 分钟
**步骤**
```bash
# 1. 创建类型定义
src/types/xxxConfig.ts
# 2. 创建 API 服务
src/services/xxxConfigApi.ts
# 3. 创建页面组件
src/pages/XxxConfigs.tsx
# 4. 更新路由 (src/App.tsx)
<Route path="/system/xxx-configs" element={<XxxConfigs />} />
# 5. 更新菜单 (src/components/DynamicMenu.tsx)
# 6. 更新子导航 (src/components/Layout.tsx)
```
### 快速复制模板
**UserLevelConfigs 类似的 CRUD 页面**
- 类型定义:`src/types/userLevelConfig.ts` (47 行)
- API 服务:`src/services/userLevelConfigApi.ts` (60 行)
- 页面组件:`src/pages/UserLevelConfigs.tsx` (292 行)
**SystemConfigs 类似的配置管理**
- 类型定义:`src/types/systemConfig.ts` (51 行)
- API 服务:`src/services/systemConfigApi.ts` (66 行)
- 页面组件:`src/pages/SystemConfigs.tsx` (284 行)
---
## 重要文件速查
### 核心基础设施
| 文件 | 行数 | 作用 |
|------|------|------|
| `src/App.tsx` | 68 | 主应用入口,静态路由定义 |
| `src/services/api.ts` | 587 | 核心 API 客户端 + 所有 API 服务导出 |
| `src/components/Layout.tsx` | 298 | 主布局(侧边栏 + 主区域 + 子导航) |
| `src/components/DynamicMenu.tsx` | 228 | 权限感知菜单 |
| `src/hooks/useAuth.ts` | ? | 认证管理 Hook |
| `src/hooks/usePagePermissions.ts` | ? | 页面权限 Hook |
### 配置管理示例
| 功能 | 页面 | 类型 | API 服务 |
|------|------|------|----------|
| 用户等级配置 | UserLevelConfigs.tsx | userLevelConfig.ts | userLevelConfigApi.ts |
| 系统配置 | SystemConfigs.tsx | systemConfig.ts | systemConfigApi.ts |
| GoalfyMax 用户 | GoalfyMaxUsers.tsx | - | api.ts (GoalfyMaxUsersApi) |
---
## API 端点速查
### 用户等级配置
```
GET /admin/user-level-configs 列表(分页)
GET /admin/user-level-configs/all 全部(不分页)
GET /admin/user-level-configs/:id 详情
POST /admin/user-level-configs 创建
PUT /admin/user-level-configs/:id 更新
PUT /admin/user-level-configs/:id/status 状态更新
DELETE /admin/user-level-configs/:id 删除
```
### 系统配置
```
GET /admin/system-configs 列表(分页)
GET /admin/system-configs/all 全部(不分页)
GET /admin/system-configs/:id 详情
GET /admin/system-configs/key/:key 按 Key 查询
POST /admin/system-configs 创建
PUT /admin/system-configs/:id 更新
PUT /admin/system-configs/:id/status 状态更新
DELETE /admin/system-configs/:id 删除
```
---
## 代码片段库
### 创建新的 API 服务函数
```typescript
// src/services/xxxConfigApi.ts
import { apiClient } from './api';
import type { XxxConfig, XxxConfigListRequest } from '../types/xxxConfig';
export const getXxxConfigList = async (params: XxxConfigListRequest) => {
const response = await apiClient.get('/admin/xxx-configs', { params });
return response.data;
};
export const createXxxConfig = async (data: any) => {
const response = await apiClient.post('/admin/xxx-configs', data);
return response.data;
};
export const updateXxxConfig = async (id: number, data: any) => {
const response = await apiClient.put(`/admin/xxx-configs/${id}`, data);
return response.data;
};
export const deleteXxxConfig = async (id: number) => {
await apiClient.delete(`/admin/xxx-configs/${id}`);
};
```
### 创建新的类型定义
```typescript
// src/types/xxxConfig.ts
export interface XxxConfig {
id: number;
name: string;
value: string;
status: number;
created_at: string;
updated_at: string;
}
export interface XxxConfigListRequest {
page?: number;
size?: number;
}
export interface XxxConfigListResponse {
data: XxxConfig[];
total: number;
}
```
### 创建 CRUD 页面骨架
```typescript
// src/pages/XxxConfigs.tsx
import React, { useEffect, useState } from 'react';
import { Table, Button, Modal, Form, Input, message } from 'antd';
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
import type { XxxConfig } from '../types/xxxConfig';
import { getXxxConfigList, createXxxConfig, updateXxxConfig, deleteXxxConfig } from '../services/xxxConfigApi';
export default function XxxConfigs() {
const [loading, setLoading] = useState(false);
const [list, setList] = useState<XxxConfig[]>([]);
const [total, setTotal] = useState(0);
const [page, setPage] = useState(1);
const [size, setSize] = useState(10);
const [editing, setEditing] = useState<XxxConfig | null>(null);
const [editOpen, setEditOpen] = useState(false);
const [createOpen, setCreateOpen] = useState(false);
const [form] = Form.useForm();
const [createForm] = Form.useForm();
const fetchList = async () => {
setLoading(true);
try {
const res = await getXxxConfigList({ page, size });
setList(res?.data ?? []);
setTotal(res?.total ?? 0);
} catch (e) {
message.error('获取列表失败');
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchList();
}, [page, size]);
// ... 其他 handlers
return (
<div>
<Button type="primary" icon={<PlusOutlined />} onClick={() => setCreateOpen(true)}>
新建
</Button>
<Table dataSource={list} loading={loading} pagination={{
current: page, pageSize: size, total,
onChange: (p, s) => { setPage(p); setSize(s); }
}} />
{/* 弹窗 */}
</div>
);
}
```
---
## 常见错误和解决方案
### 问题 1页面显示后没有数据
**原因**API 端点不正确或权限不足
**解决**
1. 检查 API 端点 URL
2. 检查用户权限
3. 查看浏览器控制台错误日志
### 问题 2菜单项不显示
**原因**:权限检查失败
**解决**
1. 检查 DynamicMenu.tsx 的权限逻辑
2. 验证用户权限是否包含该页面路径
3. 查看控制台的权限检查日志(带 🔍 标记)
### 问题 3创建/编辑后页面没有刷新
**原因**:未调用 fetchList()
**解决**
1. 确保在 submitCreate/submitEdit 中调用 fetchList()
2. 检查是否有错误导致代码未执行到刷新逻辑
### 问题 4Token 过期导致 401 错误
**原因**Token 已过期ApiClient 应该自动处理
**解决**
1. 检查 refreshToken 是否存在
2. 查看浏览器控制台的 token 刷新日志
3. 检查后端是否正确响应 token 刷新请求
---
## 性能优化建议
### 当前架构的瓶颈
1. **大型页面文件**
- UserLevelConfigs.tsx: 292 行
- SystemConfigs.tsx: 284 行
- 建议:拆分为表格、表单、操作等子组件
2. **重复的 CRUD 代码**
- 每个管理页面都有类似的列表、创建、编辑、删除逻辑
- 建议:提取通用的 CRUD Hook 或高阶组件
3. **API 响应处理不一致**
- userLevelConfigApi 返回 response.data
- systemConfigApi 返回 response
- 建议:统一响应处理方式
---
## 开发工作流
### 开发新功能的标准步骤
```
1. 分析需求,确定数据模型
2. 创建 TypeScript 类型定义 (src/types/)
3. 创建 API 服务函数 (src/services/)
4. 创建页面组件 (src/pages/)
5. 注册路由 (src/App.tsx)
6. 添加菜单项 (src/components/DynamicMenu.tsx)
7. 更新子导航(如需要) (src/components/Layout.tsx)
8. 本地测试
9. 提交代码
```
---
## 有用的命令
```bash
# 启动开发服务器
npm run dev
# 构建生产版本
npm run build
# 代码检查
npm run lint
# 预览生产构建
npm run preview
```
---
## 文档链接
- **项目架构概览**PROJECT_ARCHITECTURE.md
- **API 模式详解**API_PATTERNS.md
- **Ant Design 文档**https://ant.design/
- **React Router 文档**https://reactrouter.com/
- **Jotai 文档**https://jotai.org/
---
## 常用类名和常量
### 用户等级配置
- 页面:`/system/user-level-configs`
- 菜单 key`system-user-level-configs`
- 类型文件:`userLevelConfig.ts`
- API 服务:`userLevelConfigApi.ts`
### 系统配置
- 页面:`/system/system-configs`
- 菜单 key`system-system-configs``system-global-configs`
- 类型文件:`systemConfig.ts`
- API 服务:`systemConfigApi.ts`
---
## 快速检查清单
创建新页面前,检查:
- [ ] 后端 API 已实现
- [ ] 类型定义完整
- [ ] API 服务函数齐全CRUD 所有操作)
- [ ] 页面组件遵循 CRUD 模式
- [ ] 路由已注册
- [ ] 菜单项已添加
- [ ] 权限检查已配置(如需要)
- [ ] 表单验证规则完整
- [ ] 错误处理到位
- [ ] 加载状态反馈清晰