13 KiB
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.2(strict: 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中的useRouteHook 根据用户权限过滤路由 - 组件级权限: 使用
<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;
}
适用范围
以下场景必须遵守此规范:
- 登录处理 (
src/pages/login/form.tsx) - 用户信息页面 (
src/pages/user-info/index.tsx) - 用户管理页面 (
src/pages/user-management/) - 所有调用后端 API 的业务代码
- 所有自定义的响应处理工具函数
常量定义
在 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,成功响应被判断为失败
解决方案:
- 将所有
===改为==进行宽松相等判断 - 修改了以下文件:
src/utils/request.tssrc/pages/login/form.tsxsrc/pages/user-info/index.tsxsrc/pages/user-management/UserFormModal.tsxsrc/pages/user-management/index.tsxsrc/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);
}
}
关键开发约定
页面组件开发
- 文件位置: 所有页面放在
src/pages/{module-name}/index.tsx - 路由注册: 在
src/routes.ts的routes数组中添加路由配置 - 权限控制: 通过
requiredPermissions和oneOfPerm配置权限 - 国际化: 页面标题使用
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 导入
已知技术债务
- TypeScript 严格模式未开启:
tsconfig.json中strict: false,建议开启以提升类型安全 - 依赖版本较旧:
- React 17(建议升级到 18)
- axios 0.24.0(存在安全漏洞,建议立即升级)
- React Router 5(建议升级到 v6)
- 缺少测试: 项目无单元测试和集成测试
- Redux 传统模式: 代码冗长,建议迁移到 Redux Toolkit
- 安全防护不足:
- localStorage 明文存储敏感信息
- 缺少 CSRF 防护
- 缺少输入验证和清洗
常见问题排查
API 响应成功但业务逻辑未执行
症状:
- API 请求返回成功(控制台显示
code: "0"或code: 0) - 但成功回调未执行,数据未更新
- 或登录成功但未跳转
原因:
使用了严格相等 === 判断响应码,导致字符串 "0" 和数字 0 类型不匹配
排查步骤:
- 打开浏览器开发者工具的 Network 标签页
- 查看 API 响应中的
code字段类型(字符串还是数字) - 检查业务代码中是否使用了
result.code === xxx - 将所有
===改为==
解决方案:
// ❌ 错误写法
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
权限控制不生效
- 检查 Redux Store 中的
userInfo.permissions是否正确 - 检查路由配置中的
requiredPermissions格式 - 检查
utils/authentication.ts的权限判断逻辑
主题色不生效
- 检查
src/settings.json中的themeColor配置 - 确保在应用启动时调用了
initThemeColor()(位于src/main.tsx:64-70) - 明暗模式切换时需重新调用
initThemeColor()
Vite 构建失败
- 检查 TypeScript 类型错误(虽然 noEmit: true,但仍需类型正确)
- 检查 Less 语法错误
- 检查路径别名配置是否正确
性能优化建议
- 大数据量表格使用虚拟滚动
- 图片较多时使用懒加载
- 搜索、滚动等高频操作添加防抖节流
- 使用
rollup-plugin-visualizer分析打包产物
安全注意事项
- 敏感信息(Token、用户数据)应加密后再存储到 localStorage
- 所有用户输入需进行验证和清洗
- 生产环境强制使用 HTTPS
- 定期运行
npm audit检查依赖漏洞
扩展开发指引
添加新页面
- 创建页面组件:
src/pages/new-page/index.tsx - 添加路由配置:
src/routes.ts - 添加国际化:
src/locale/zh-CN.ts和en-US.ts - 如需权限控制,配置
requiredPermissions
添加新组件
- 业务组件:
src/pages/{module}/components/ - 公共组件:
src/components/ - 组件应包含独立的样式文件(
.module.less)
添加新的 Redux 状态
在 src/store/index.ts 中:
- 扩展
GlobalState接口 - 更新
initialState - 在
reducer中添加新的 case