8.1 KiB
8.1 KiB
AGENTS.md
你是 JavaScript、Rsbuild 和 Web 应用开发方面的专家,编写可维护、高性能且无障碍的代码。
技术栈
- React 19 + TypeScript — 前端框架和类型系统
- Rsbuild 2 — 构建工具(基于 Rspack),配置文件为
rsbuild.config.ts - React Router v7(
react-router)— 客户端路由 - antd 6 + @ant-design/icons 6 — UI 组件库和图标集
- pnpm — 包管理器
常用命令
pnpm run dev— 启动开发服务器(自动打开 http://localhost:3000)pnpm run build— 构建生产版本(输出至dist/)pnpm run preview— 本地预览生产构建pnpm run lint— 使用 ESLint 检查 TypeScript/TSX 文件pnpm run format— 使用 Prettier 格式化所有文件
项目结构
src/
index.tsx # 应用入口,挂载 React 根节点 + 启动 MSW mock
App.tsx # 根组件,ConfigProvider / AntdApp / RouterProvider
App.css # 全局样式(reset)
router.tsx # createBrowserRouter,登录页独立路由 + 布局子路由
env.d.ts # Rsbuild 环境变量类型声明(ImportMetaEnv)
routes/
types.ts # RouteItem 类型定义
index.tsx # 路由树数据(唯一数据源),导出 routes / RouteItem
utils.tsx # toRouteObjects():将路由树转为 React Router RouteObject[]
layouts/
RootLayout.tsx # 根布局(Header + Sider + Content)
SystemLayout.tsx # 系统配置布局(<Outlet />,作为 /system 父路由容器)
api/
auth.ts # 登录接口
system/
user.ts # 部门 / 用户接口
role.ts # 角色接口
store/
index.ts # 统一导出入口
app.ts # 全局应用状态(侧边栏折叠等)
user.ts # 用户状态(userInfo / token)
mock/
index.ts # MSW worker 初始化,汇总所有 handlers
auth.ts # 登录 mock
system.ts # 部门 / 用户 / 角色 mock
pages/
login/
index.tsx # "/login" 登录页(不加载布局)
home/
index.tsx # "/" 首页
about/
index.tsx # "/about" 关于页
not-found/
index.tsx # "*" 兜底 404 页
system/
user/
index.tsx # "/system/user" 用户管理入口
DeptTree.tsx # 部门树组件
DeptModal.tsx # 部门弹窗组件
UserTable.tsx # 用户表格组件
UserModal.tsx # 用户弹窗组件
role/
index.tsx # "/system/role" 角色管理入口
RoleTable.tsx # 角色表格组件
RoleModal.tsx # 角色弹窗组件
types/
http.d.ts # 全局 API 命名空间(无需 import 直接使用 API.Response<T>)
utils/
request.ts # axios 实例封装,导出 get / post(自动附加 token)
.env # 本地环境变量(已 gitignore,勿提交)
.env.example # 环境变量模板(提交到仓库供参考)
public/
favicon.png
rsbuild.config.ts # 构建配置
eslint.config.mjs # ESLint 扁平配置(仅作用于 TS/TSX,忽略 dist/)
tsconfig.json
环境变量
- 变量文件:
.env(本地,已 gitignore) - 模板文件:
.env.example(提交到仓库) - 新成员初始化:
cp .env.example .env - Rsbuild 规则:以
PUBLIC_为前缀的变量会暴露给客户端,通过import.meta.env.PUBLIC_XXX读取
| 变量 | 说明 |
|---|---|
PUBLIC_BASE_URL |
后端接口 baseURL |
不同环境可创建 .env.development / .env.production 覆盖默认值,.env.example 中同步维护所有变量。
路由
使用 React Router v7(react-router)的 createBrowserRouter。
- 唯一数据源:
src/routes/index.tsx维护routes: RouteItem[]路由树 RouteItem字段:path/label/icon?/component?/hideInMenu?/redirect?/children?toRouteObjects(routes)将路由树转换为 React Router 所需的RouteObject[]- 菜单、面包屑等模块直接消费
routes数组,无需重复维护路由信息 - 添加新页面:在
src/pages/创建组件,在src/routes/index.tsx追加节点即可
TypeScript 配置
- 已启用
noUnusedLocals和noUnusedParameters,未使用的变量/参数会报错 - 已启用
verbatimModuleSyntax,纯类型导入必须使用import type moduleResolution: "bundler",使用打包器风格的模块解析
代码风格
- 单引号(
.prettierrc中singleQuote: true) - ESLint 仅作用于
**/*.{ts,tsx},启用了react-hooks和react-refresh插件
注释规范
所有代码都应附带必要的注释,说明意图而非重复代码本身。
- 函数 / Hook:用 JSDoc 说明用途、参数含义
- 复杂逻辑、非直觉的实现:行内注释解释原因
- 模拟数据 / 临时代码:标注
// TODO:或// FIXME:方便后续替换 - 类型字段:用 JSDoc 注释说明每个字段的含义
// ✅ 说明意图
// 用 cancelled 标志位防止组件卸载后的竞态更新
let cancelled = false;
/**
* 根据部门 ID 获取用户列表
* @param deptKey 部门节点 key
*/
const fetchUsersByDept = (deptKey: string): Promise<UserRecord[]> => { ... };
// TODO: 替换为真实接口
const mockData = [...];
UI 组件规范(antd)
页面 UI 优先使用 antd 组件,不自行实现已有组件的功能。
- 从
antd直接导入组件,从@ant-design/icons导入图标,自动 tree-shaking - 布局使用
Layout(Header/Sider/Content/Footer) - 导航使用
Menu,面包屑使用Breadcrumb - 表单使用
Form+Form.Item,不使用原生<form> - 按钮使用
Button,不使用原生<button> - 弹窗使用
Modal,消息提示使用message/notification - 数据展示使用
Table/List/Descriptions/Card - 空状态使用
Empty,加载状态使用Spin/Skeleton - 404 页面使用
Result status="404"
自定义主题通过 ConfigProvider 在 App.tsx 统一配置:
import { ConfigProvider } from 'antd';
<ConfigProvider theme={{ token: { colorPrimary: '#00b96b' } }}>
<RouterProvider router={router} />
</ConfigProvider>
HTTP 请求
- 所有请求通过
src/utils/request.ts封装的方法发出,不直接使用axios - 只使用
get和post两种方法,不使用put/delete等其他方法 - 编辑接口用
post,路径加/edit后缀;删除接口用post,路径加/del后缀 - 全局响应结构
API.Response<T>定义在src/types/http.d.ts,无需 import 直接使用 - 请求拦截器(添加 token)和响应拦截器(处理错误码)统一在
request.ts中维护 - 接口函数统一放在
src/api/下,按模块分文件管理(如src/api/system/user.ts)
接口函数命名规范:
| 操作 | 前缀 | 示例 |
|---|---|---|
| 新增 | add |
addDept |
| 编辑 | edit |
editDept |
| 删除 | del |
delDept |
| 获取列表 | list |
listUser |
| 获取详情 | detail |
detailUser |
| 特殊查询(树等) | 语义命名 | deptTree |
// 使用示例
import { get, post } from '../utils/request';
const res = await get<User[]>('/api/users');
// res.code / res.msg / res.data / res.ok / res.time
API 层规范
- 数据结构不导出:
src/api/目录下的 interface / type 不得加export,禁止其他模块 import - 组件自定类型:页面组件如需使用数据结构,在组件文件内自行定义,不依赖 API 层的类型
- mock 文件同理:
src/mock/下的文件也需自行定义类型,不导入src/api/中的类型 - API 函数可以内部使用类型,但签名中避免使用导出的复杂类型(可用
Record<string, unknown>或any代替)
参考文档
- Rsbuild: https://rsbuild.rs/llms.txt
- Rspack: https://rspack.rs/llms.txt
- antd v6 组件导航文档: https://ant.design/llms.txt