From 4a6a0c22095a6c130adfb8bc28efa6dc705f3c8e Mon Sep 17 00:00:00 2001 From: gaoziman <2942894660@qq.com> Date: Tue, 18 Nov 2025 21:20:10 +0800 Subject: [PATCH] =?UTF-8?q?docs(=E9=A1=B9=E7=9B=AE=E6=96=87=E6=A1=A3):=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE=E6=8C=87=E5=8D=97=E5=92=8C?= =?UTF-8?q?=E5=BC=80=E5=8F=91=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 AGENTS.md 项目结构和开发指南 - 添加 CLAUDE.md AI辅助开发配置文档 - 更新 .gitignore 忽略 docs 和 .serena 目录 --- .gitignore | 6 +- AGENTS.md | 39 ++++ CLAUDE.md | 517 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 561 insertions(+), 1 deletion(-) create mode 100644 AGENTS.md create mode 100644 CLAUDE.md diff --git a/.gitignore b/.gitignore index e777516..2d2bc98 100644 --- a/.gitignore +++ b/.gitignore @@ -48,4 +48,8 @@ yarn-error.log* .vscode # build output -/dist \ No newline at end of file +/dist +/docs/ + +# IDE and tool configs +.serena/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..bed67a3 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,39 @@ +# Repository Guidelines + +## 项目结构与模块组织 + +- `src/` 存放核心前端代码:`pages/` 管理业务页面(登录、用户管理、个人信息),`components/` 复用组件,`api/` 与后端交互封装,`store/` 保存全局设置与标签页状态,`utils/` 管理工具函数,`mock/` 仅在本地调试启用。 +- `docs/` 收录 API 对接与集成报告,提交前务必同步更新。 +- `dist/` 为 `pnpm run build` 产物,禁止手动修改;`.env.*` 提供环境变量,请按需复制调整。 + +## 构建与开发命令 + +| 命令 | 说明 | +| ---------------------------------------- | --------------------------------------------------------- | +| `pnpm install` | 安装依赖,项目首选 pnpm(若使用 npm,需同步更新锁文件)。 | +| `pnpm run dev` | 启动 Vite 开发服务器,默认走 `/api` 代理到本地 8080。 | +| `pnpm run build` | 生成产物到 `dist/`,用于联调或上线前校验。 | +| `pnpm run preview` | 以本地静态服务验证构建结果。 | +| `pnpm run eslint` / `pnpm run stylelint` | 校验并自动修复 TS/TSX 与 Less。 | +| `pnpm run pre-commit` | 执行 pretty-quick、ESLint、Stylelint,PR 前必跑。 | + +## 编码风格与命名 + +- 语法统一使用 TypeScript + React 17 Hooks,目录与文件采用小写连字符(示例:`user-management`)。 +- ESLint 继承 `plugin:@typescript-eslint/recommended` 与 `plugin:react-hooks/recommended`;Prettier 约定 2 空格缩进、单引号、强制分号。 +- 样式使用 Less + CSS Modules,遵循 `.module.less` 命名,Stylelint 规则在 `.stylelintrc` 中定义。 + +## 测试指引 + +- 当前仓库尚未集成自动化测试;提交复杂功能时,需给出手工测试步骤,并优先在 `src/__tests__`(或相应页面目录)补充 `*.spec.tsx`。 +- 覆盖重点:核心表单(登录、用户管理)与 API 适配层,可借助 Jest + @testing-library/react;命名遵循 `模块名.行为.spec.tsx`。 + +## 提交与 PR 规范 + +- Commit 信息遵循 `type(scope): 描述`,与现有记录(如 `feat(布局): ...`、`style(导航栏): ...`)保持一致,描述使用简体中文。 +- Pull Request 需包含:变更摘要、关联 Issue/需求编号、截图或命令输出、测试与 lint 结果;若改动 API 或配置,同步更新 `docs/` 与 `.env.*` 示例。 + +## 安全与配置提示 + +- `.env.development` 默认将 `VITE_API_BASE_URL` 指向 `/api`,生产环境务必更新为真实网关地址,避免调试代理泄漏。 +- Mock 入口在 `src/main.tsx` 引入,如需生产构建剔除,可通过环境变量包装 `import './mock'`,防止将虚拟数据发布到线上。 diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..eaa8b3f --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,517 @@ +# 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/)