codernew-api-frontend/CLAUDE.md
gaoziman 4a6a0c2209 docs(项目文档): 添加项目指南和开发文档
- 添加 AGENTS.md 项目结构和开发指南
- 添加 CLAUDE.md AI辅助开发配置文档
- 更新 .gitignore 忽略 docs 和 .serena 目录
2025-11-18 21:20:10 +08:00

13 KiB
Raw Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.


React Arco Design Pro 项目指南

项目概述

这是一个基于 React 17 + Arco Design + TypeScript + Vite 的企业级中后台管理系统模板项目。项目采用前后端分离架构,使用 Redux 进行状态管理,使用 Mock.js 模拟后端数据。

常用命令

开发与构建

# 启动开发服务器(推荐)
npm run dev
# 或
npm start

# 生产环境构建
npm run build

# 预览生产构建
npm run preview

代码质量检查

# ESLint 检查并自动修复
npm run eslint

# Stylelint 检查并自动修复
npm run stylelint

# Git 提交前检查(自动执行)
npm run pre-commit

注意: 建议在 .eslintrc.js 中配置规则,禁止在响应码判断时使用严格相等:

// 可选:配置 ESLint 规则提醒
rules: {
  // 其他规则...
  // 在代码审查时人工检查响应码判断逻辑
}

包管理

项目使用 pnpm 作为包管理器,但 npm/yarn 也兼容。建议使用 pnpm 以保持依赖一致性。

核心架构设计

技术栈核心

  • 构建工具: Vite 2.6.14(快速 HMR基于 ESM
  • UI 框架: React 17.0.2
  • UI 组件库: @arco-design/web-react 2.32.2(字节跳动开源)
  • 状态管理: Redux 4.1.2(传统模式,非 Redux Toolkit
  • 路由: React Router 5.2.0
  • HTTP 客户端: Axios 0.24.0
  • CSS 预处理: Less 4.1.2
  • 类型系统: TypeScript 4.5.2strict: false

架构分层

src/
├── pages/           # 页面组件(按功能模块组织,支持懒加载)
├── components/      # 公共组件NavBar, TabBar, Footer 等)
├── layout.tsx       # 主布局组件(侧边栏、标签页、内容区)
├── routes.ts        # 路由配置 + 权限过滤逻辑
├── store/           # Redux 状态管理settings, userInfo, tabs
├── utils/           # 工具函数(认证、主题、国际化等)
├── mock/            # Mock.js 数据模拟
├── locale/          # 国际化资源文件
└── main.tsx         # 应用入口

关键架构模式

1. 路由懒加载机制

  • 使用 import.meta.glob() 动态导入页面组件
  • 通过 @loadable/component 实现代码分割
  • 路由配置在 src/routes.ts,约定式路由:./pages/${route.key}/index.tsx

2. 权限控制系统

  • 路由级权限: routes.ts 中的 useRoute Hook 根据用户权限过滤路由
  • 组件级权限: 使用 <PermissionWrapper> 组件包裹需要权限控制的元素
  • 权限验证: utils/authentication.ts 提供权限判断逻辑
  • 角色系统: 简单的 Admin/User 角色,权限存储在 Redux Store

3. 状态管理架构

Redux Store 管理三类全局状态:

// src/store/index.ts
GlobalState {
  settings: {        // 系统设置(主题色、布局配置)
    themeColor,
    navbar,
    menu,
    footer
  },
  userInfo: {        // 用户信息
    name,
    avatar,
    permissions    // 权限映射表
  },
  tabs: {           // 多标签页状态
    activeKey,
    tabs[]
  }
}

重要: Redux 使用传统模式(非 Redux Toolkit所有 Action 通过字符串类型派发。

4. 主题系统

  • 主题配置: src/settings.json 定义默认主题色
  • 主题切换: utils/changeTheme.ts 切换明暗模式
  • 色值计算: utils/initThemeColor.ts 根据主题色自动生成 10 个梯度色
  • Vite 集成: vite.config.ts 通过 @arco-plugins/vite-react 注入主题变量

5. 多标签页系统

标签页状态由 Redux 管理,支持:

  • 添加/关闭标签页(tabs/addTab, tabs/removeTab
  • 切换标签页(tabs/setActiveTab
  • 右键菜单操作(关闭左侧/右侧/其他)

标签页与路由联动,在 layout.tsx 中实现。

数据流设计

用户交互 → Component
    ↓
dispatch Redux Action
    ↓
Reducer 更新 Store
    ↓
useSelector 订阅变化
    ↓
Component 重新渲染

HTTP 请求流:

Component → axios → Mock.js (开发环境) / Backend API (生产环境) → Component State/Redux

路径别名配置

// 在代码中使用 @/ 代替 src/
import utils from '@/utils/xxx';

配置位置:

  • tsconfig.json: "@/*": ["src/*"]
  • vite.config.ts: alias: [{ find: '@', replacement: '/src' }]

API 开发规范

响应码处理规范

【重要】必须使用宽松相等判断响应码,避免类型不一致问题

问题背景

后端不同接口可能返回不同类型的响应码:

  • 部分接口返回字符串 "0"
  • 部分接口返回数字 0

使用严格相等 === 判断时会导致类型不匹配,即使业务成功也会被判断为失败。

强制规范

1. 在所有业务代码中判断响应码时,必须使用宽松相等 ==

// ✅ 正确:使用宽松相等
if (result.code == SUCCESS_CODE) {
  // 处理成功逻辑
}

if (result.code == 0) {
  // 处理成功逻辑
}

// ❌ 错误:使用严格相等
if (result.code === SUCCESS_CODE) {
  // 可能导致字符串 "0" !== 数字 0
  // 处理成功逻辑
}

2. 响应拦截器中必须使用宽松相等

src/utils/request.ts 响应拦截器中:

// ✅ 正确
if (data.code == SUCCESS_CODE) {
  return response;
}

// ❌ 错误
if (data.code === SUCCESS_CODE) {
  return response;
}

3. 类型守卫函数中必须使用宽松相等

src/types/api.ts 中:

// ✅ 正确
export function isSuccessResponse<T>(response: R<T>): boolean {
  return response.code == 0;
}

// ❌ 错误
export function isSuccessResponse<T>(response: R<T>): boolean {
  return response.code === 0;
}

适用范围

以下场景必须遵守此规范:

  1. 登录处理 (src/pages/login/form.tsx)
  2. 用户信息页面 (src/pages/user-info/index.tsx)
  3. 用户管理页面 (src/pages/user-management/)
  4. 所有调用后端 API 的业务代码
  5. 所有自定义的响应处理工具函数

常量定义

src/constants/index.ts 中:

// 响应码定义为数字类型(推荐)
export const SUCCESS_CODE = 0;
export const ERROR_CODE = 1;

检查清单

在编写或修改 API 调用代码时,必须检查:

  • 所有 result.code === xxx 改为 result.code == xxx
  • 所有 response.code === xxx 改为 response.code == xxx
  • 响应拦截器使用宽松相等判断
  • 工具函数使用宽松相等判断

历史问题记录

问题日期: 2025-11-17

问题描述: 登录功能失效,用户管理页面空白

根本原因:

  • 后端登录接口返回 code: "0" (字符串)
  • 前端使用 result.code === 0 (严格相等判断数字)
  • 导致 "0" !== 0,成功响应被判断为失败

解决方案:

  1. 将所有 === 改为 == 进行宽松相等判断
  2. 修改了以下文件:
    • src/utils/request.ts
    • src/pages/login/form.tsx
    • src/pages/user-info/index.tsx
    • src/pages/user-management/UserFormModal.tsx
    • src/pages/user-management/index.tsx
    • src/types/api.ts

预防措施: 制定本规范文档,在代码审查时强制检查

API 调用最佳实践

// 1. 标准 API 调用模式
async function fetchData() {
  try {
    const result = await apiFunction(params);

    // ✅ 使用宽松相等判断
    if (result.code == SUCCESS_CODE) {
      // 处理成功逻辑
      setData(result.data);
    }
    // 错误消息已在拦截器中显示,无需额外处理
  } catch (error) {
    console.error('请求失败:', error);
    // 异常已在拦截器中提示,此处仅需记录日志
  }
}

// 2. 带加载状态的 API 调用
async function handleSubmit() {
  try {
    setLoading(true);
    const result = await apiFunction(params);

    if (result.code == SUCCESS_CODE) {
      Message.success('操作成功');
      onSuccess();
    }
  } catch (error) {
    console.error('操作失败:', error);
  } finally {
    setLoading(false);
  }
}

关键开发约定

页面组件开发

  1. 文件位置: 所有页面放在 src/pages/{module-name}/index.tsx
  2. 路由注册: 在 src/routes.tsroutes 数组中添加路由配置
  3. 权限控制: 通过 requiredPermissionsoneOfPerm 配置权限
  4. 国际化: 页面标题使用 locale 多语言 key

示例:

// src/routes.ts
{
  name: 'menu.moduleName',  // 国际化 key
  key: 'module-name',       // 对应 pages/module-name/index.tsx
  requiredPermissions: [    // 可选:需要的权限
    { resource: 'module', actions: ['read'] }
  ]
}

Redux 状态操作

// 获取状态
import { useSelector } from 'react-redux';
const { userInfo, settings } = useSelector((state: GlobalState) => state);

// 更新状态
import { useDispatch } from 'react-redux';
const dispatch = useDispatch();
dispatch({
  type: 'update-userInfo',
  payload: { userInfo: newUserInfo },
});

国际化使用

// 在组件中使用国际化
import useLocale from '@/utils/useLocale';
import locale from './locale'; // 本地语言文件

function MyComponent() {
  const t = useLocale(locale);
  return <div>{t['key.name']}</div>;
}

主题色动态修改

// 修改主题色(自动生成 10 个梯度色 CSS 变量)
import initThemeColor from '@/utils/initThemeColor';

initThemeColor('#026166', false); // (颜色值, 是否暗色模式)

Mock 数据开发

  • Mock 文件位置: src/mock/
  • 使用 Mock.js 拦截 axios 请求
  • src/main.tsx 中导入: import './mock'
  • 生产环境需移除 mock 导入

已知技术债务

  1. TypeScript 严格模式未开启: tsconfig.jsonstrict: false,建议开启以提升类型安全
  2. 依赖版本较旧:
    • React 17建议升级到 18
    • axios 0.24.0(存在安全漏洞,建议立即升级)
    • React Router 5建议升级到 v6
  3. 缺少测试: 项目无单元测试和集成测试
  4. Redux 传统模式: 代码冗长,建议迁移到 Redux Toolkit
  5. 安全防护不足:
    • localStorage 明文存储敏感信息
    • 缺少 CSRF 防护
    • 缺少输入验证和清洗

常见问题排查

API 响应成功但业务逻辑未执行

症状:

  • API 请求返回成功(控制台显示 code: "0"code: 0
  • 但成功回调未执行,数据未更新
  • 或登录成功但未跳转

原因: 使用了严格相等 === 判断响应码,导致字符串 "0" 和数字 0 类型不匹配

排查步骤:

  1. 打开浏览器开发者工具的 Network 标签页
  2. 查看 API 响应中的 code 字段类型(字符串还是数字)
  3. 检查业务代码中是否使用了 result.code === xxx
  4. 将所有 === 改为 ==

解决方案:

// ❌ 错误写法
if (result.code === SUCCESS_CODE) { ... }
if (result.code === 0) { ... }

// ✅ 正确写法
if (result.code == SUCCESS_CODE) { ... }
if (result.code == 0) { ... }

预防措施:

  • 遵守 API 开发规范 中的响应码处理规范
  • 代码审查时检查所有响应码判断逻辑

路由懒加载失败

检查页面组件路径是否符合约定:src/pages/{route.key}/index.tsx

权限控制不生效

  1. 检查 Redux Store 中的 userInfo.permissions 是否正确
  2. 检查路由配置中的 requiredPermissions 格式
  3. 检查 utils/authentication.ts 的权限判断逻辑

主题色不生效

  1. 检查 src/settings.json 中的 themeColor 配置
  2. 确保在应用启动时调用了 initThemeColor()(位于 src/main.tsx:64-70
  3. 明暗模式切换时需重新调用 initThemeColor()

Vite 构建失败

  1. 检查 TypeScript 类型错误(虽然 noEmit: true但仍需类型正确
  2. 检查 Less 语法错误
  3. 检查路径别名配置是否正确

性能优化建议

  • 大数据量表格使用虚拟滚动
  • 图片较多时使用懒加载
  • 搜索、滚动等高频操作添加防抖节流
  • 使用 rollup-plugin-visualizer 分析打包产物

安全注意事项

  • 敏感信息Token、用户数据应加密后再存储到 localStorage
  • 所有用户输入需进行验证和清洗
  • 生产环境强制使用 HTTPS
  • 定期运行 npm audit 检查依赖漏洞

扩展开发指引

添加新页面

  1. 创建页面组件: src/pages/new-page/index.tsx
  2. 添加路由配置: src/routes.ts
  3. 添加国际化: src/locale/zh-CN.tsen-US.ts
  4. 如需权限控制,配置 requiredPermissions

添加新组件

  • 业务组件: src/pages/{module}/components/
  • 公共组件: src/components/
  • 组件应包含独立的样式文件(.module.less

添加新的 Redux 状态

src/store/index.ts 中:

  1. 扩展 GlobalState 接口
  2. 更新 initialState
  3. reducer 中添加新的 case

参考文档