docs(项目文档): 添加项目指南和开发文档
- 添加 AGENTS.md 项目结构和开发指南 - 添加 CLAUDE.md AI辅助开发配置文档 - 更新 .gitignore 忽略 docs 和 .serena 目录
This commit is contained in:
parent
660ab2eb9c
commit
4a6a0c2209
6
.gitignore
vendored
6
.gitignore
vendored
@ -48,4 +48,8 @@ yarn-error.log*
|
||||
.vscode
|
||||
|
||||
# build output
|
||||
/dist
|
||||
/dist
|
||||
/docs/
|
||||
|
||||
# IDE and tool configs
|
||||
.serena/
|
||||
|
||||
39
AGENTS.md
Normal file
39
AGENTS.md
Normal file
@ -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'`,防止将虚拟数据发布到线上。
|
||||
517
CLAUDE.md
Normal file
517
CLAUDE.md
Normal file
@ -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 根据用户权限过滤路由
|
||||
- **组件级权限**: 使用 `<PermissionWrapper>` 组件包裹需要权限控制的元素
|
||||
- **权限验证**: `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<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` 中:
|
||||
|
||||
```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 <div>{t['key.name']}</div>;
|
||||
}
|
||||
```
|
||||
|
||||
### 主题色动态修改
|
||||
|
||||
```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/)
|
||||
Loading…
Reference in New Issue
Block a user