Files
goalfylearning-admin-web/QUICK_REFERENCE.md

9.9 KiB
Raw Blame History

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 分钟 步骤

# 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 服务函数

// 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}`);
};

创建新的类型定义

// 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 页面骨架

// 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. 提交代码

有用的命令

# 启动开发服务器
npm run dev

# 构建生产版本
npm run build

# 代码检查
npm run lint

# 预览生产构建
npm run preview

文档链接


常用类名和常量

用户等级配置

  • 页面:/system/user-level-configs
  • 菜单 keysystem-user-level-configs
  • 类型文件:userLevelConfig.ts
  • API 服务:userLevelConfigApi.ts

系统配置

  • 页面:/system/system-configs
  • 菜单 keysystem-system-configssystem-global-configs
  • 类型文件:systemConfig.ts
  • API 服务:systemConfigApi.ts

快速检查清单

创建新页面前,检查:

  • 后端 API 已实现
  • 类型定义完整
  • API 服务函数齐全CRUD 所有操作)
  • 页面组件遵循 CRUD 模式
  • 路由已注册
  • 菜单项已添加
  • 权限检查已配置(如需要)
  • 表单验证规则完整
  • 错误处理到位
  • 加载状态反馈清晰