# 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 模拟后端数据。 ## 常用命令 ### 开发与构建 ```bash # 启动开发服务器(推荐) npm run dev # 或 npm start # 生产环境构建 npm run build # 预览生产构建 npm run preview ``` ### 代码质量检查 ```bash # ESLint 检查并自动修复 npm run eslint # Stylelint 检查并自动修复 npm run stylelint # Git 提交前检查(自动执行) npm run pre-commit ``` **注意**: 建议在 `.eslintrc.js` 中配置规则,禁止在响应码判断时使用严格相等: ```javascript // 可选:配置 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` 中的 `useRoute` Hook 根据用户权限过滤路由 - **组件级权限**: 使用 `` 组件包裹需要权限控制的元素 - **权限验证**: `utils/authentication.ts` 提供权限判断逻辑 - **角色系统**: 简单的 Admin/User 角色,权限存储在 Redux Store #### 3. 状态管理架构 Redux Store 管理三类全局状态: ```typescript // 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 ``` ### 路径别名配置 ```typescript // 在代码中使用 @/ 代替 src/ import utils from '@/utils/xxx'; ``` 配置位置: - `tsconfig.json`: `"@/*": ["src/*"]` - `vite.config.ts`: `alias: [{ find: '@', replacement: '/src' }]` ## API 开发规范 ### 响应码处理规范 **【重要】必须使用宽松相等判断响应码,避免类型不一致问题** #### 问题背景 后端不同接口可能返回不同类型的响应码: - 部分接口返回字符串 `"0"` - 部分接口返回数字 `0` 使用严格相等 `===` 判断时会导致类型不匹配,即使业务成功也会被判断为失败。 #### 强制规范 **1. 在所有业务代码中判断响应码时,必须使用宽松相等 `==`** ```typescript // ✅ 正确:使用宽松相等 if (result.code == SUCCESS_CODE) { // 处理成功逻辑 } if (result.code == 0) { // 处理成功逻辑 } // ❌ 错误:使用严格相等 if (result.code === SUCCESS_CODE) { // 可能导致字符串 "0" !== 数字 0 // 处理成功逻辑 } ``` **2. 响应拦截器中必须使用宽松相等** 在 `src/utils/request.ts` 响应拦截器中: ```typescript // ✅ 正确 if (data.code == SUCCESS_CODE) { return response; } // ❌ 错误 if (data.code === SUCCESS_CODE) { return response; } ``` **3. 类型守卫函数中必须使用宽松相等** 在 `src/types/api.ts` 中: ```typescript // ✅ 正确 export function isSuccessResponse(response: R): boolean { return response.code == 0; } // ❌ 错误 export function isSuccessResponse(response: R): 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` 中: ```typescript // 响应码定义为数字类型(推荐) 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 调用最佳实践 ```typescript // 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.ts` 的 `routes` 数组中添加路由配置 3. **权限控制**: 通过 `requiredPermissions` 和 `oneOfPerm` 配置权限 4. **国际化**: 页面标题使用 `locale` 多语言 key 示例: ```typescript // src/routes.ts { name: 'menu.moduleName', // 国际化 key key: 'module-name', // 对应 pages/module-name/index.tsx requiredPermissions: [ // 可选:需要的权限 { resource: 'module', actions: ['read'] } ] } ``` ### Redux 状态操作 ```typescript // 获取状态 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 }, }); ``` ### 国际化使用 ```typescript // 在组件中使用国际化 import useLocale from '@/utils/useLocale'; import locale from './locale'; // 本地语言文件 function MyComponent() { const t = useLocale(locale); return
{t['key.name']}
; } ``` ### 主题色动态修改 ```typescript // 修改主题色(自动生成 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.json` 中 `strict: 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. 将所有 `===` 改为 `==` **解决方案**: ```typescript // ❌ 错误写法 if (result.code === SUCCESS_CODE) { ... } if (result.code === 0) { ... } // ✅ 正确写法 if (result.code == SUCCESS_CODE) { ... } if (result.code == 0) { ... } ``` **预防措施**: - 遵守 [API 开发规范](#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.ts` 和 `en-US.ts` 4. 如需权限控制,配置 `requiredPermissions` ### 添加新组件 - 业务组件: `src/pages/{module}/components/` - 公共组件: `src/components/` - 组件应包含独立的样式文件(`.module.less`) ### 添加新的 Redux 状态 在 `src/store/index.ts` 中: 1. 扩展 `GlobalState` 接口 2. 更新 `initialState` 3. 在 `reducer` 中添加新的 case ## 参考文档 - [Arco Design 官方文档](https://arco.design/) - [Vite 官方文档](https://vitejs.dev/) - [React Router v5 文档](https://v5.reactrouter.com/)