123 lines
7.7 KiB
Markdown
123 lines
7.7 KiB
Markdown
# AGENTS.md
|
||
|
||
## 项目约束
|
||
|
||
1. 写代码不要猜。遇到不确定的依赖版本、导出名称、组件 API、项目结构、样式约定,先查本地文件、`node_modules` 或实际命令输出。
|
||
2. 写前端或客户端项目时,不要添加无意义的描述文案。
|
||
3. 包管理器固定使用 `pnpm`,不要生成 npm/yarn 锁文件。
|
||
4. 基础 UI 使用 MUI,但视觉风格必须保持当前白色 HYApp 管理平台风格。
|
||
5. 修改 MUI 组件颜色、尺寸、hover、focus、active 状态时,优先通过 `src/theme.js` 或项目封装组件处理,避免在页面里硬写零散覆盖。
|
||
6. 图表必须使用图表库。本项目使用 ECharts,不手写业务图表。
|
||
7. 组件必须模块化。不要把页面、基础组件、图表、业务表格、抽屉混在单个文件里。
|
||
8. 页面加载必须有动画占位图,并且占位图要铺满内容区域。
|
||
9. 动画要覆盖页面切换、按钮、菜单、输入框、选择框、表格、图表、弹窗/抽屉等交互,同时保留 `prefers-reduced-motion` 降级。
|
||
10. Header 右侧放操作组件,左侧只放菜单展开/收起按钮和当前页 tab。
|
||
11. 时间筛选属于总览页面内容,不属于 Header。
|
||
12. 顶部搜索框点击后打开大搜索弹窗,输入后展示列表,列表项必须可点击。
|
||
13. 左侧菜单 active 样式优先级必须高于 hover 样式。
|
||
14. 侧边栏展开/收起按钮必须跟随状态切换图标。
|
||
15. 展开态 Logo 区域和侧边栏宽度保持 248px。
|
||
16. 所有逻辑功能配置默认打开;只有密钥、地址、三方账号等必须由环境提供的敏感值使用占位符或环境配置,不在默认配置里伪造可用凭证。
|
||
17. 所有业务逻辑、状态流转、权限判断、支付链路、异步流程都保持高密度逻辑注释,注释解释为什么这样处理和失败分支,不复述语法。
|
||
|
||
## 当前实现方式
|
||
|
||
- 框架:React + Vite。
|
||
- UI 组件库:MUI。
|
||
- 图表库:ECharts。
|
||
- 包管理器:pnpm。
|
||
- 页面:按业务放在 `src/features/*/pages/`。
|
||
- 应用壳:`src/app/App.jsx`、`src/app/layout/AdminLayout.jsx`、`src/app/router/routeConfig.ts`。
|
||
- 页面加载占位:`src/shared/ui/PageSkeleton.jsx`。
|
||
- 公共时间选择器:`src/shared/ui/TimeRangeFilter.jsx`,使用 `{ startMs, endMs }` 毫秒值作为输入输出。
|
||
- 全局资源组选择抽屉:`src/shared/ui/ResourceGroupSelectDrawer.jsx`,业务表单资源组字段统一使用其导出的 `ResourceGroupSelectField`,不在业务页面里重复手写普通下拉或资源组 ID 输入框。
|
||
- 顶部搜索弹窗:`src/features/search/components/SearchDialog.jsx`。
|
||
- MUI 主题:`src/theme.js`。
|
||
- CSS token:`src/styles/tokens.css`。
|
||
- 样式入口:`src/styles/app.css`,实际样式按 `src/styles/*.css`、`src/features/*/*.css` 和 `*.module.css` 拆分。
|
||
- 服务端状态:使用 `@tanstack/react-query`,共享入口在 `src/shared/query/` 和 `src/shared/hooks/useAdminQuery.js`。
|
||
- 接口契约:`contracts/admin-openapi.json` 是本仓库的前端 API 契约源;`pnpm gen:api` 只基于该契约生成 `src/shared/api/generated/schema.d.ts` 和 `src/shared/api/generated/endpoints.ts`。
|
||
|
||
## 目录规范
|
||
|
||
- `src/app/`:应用壳、Provider、鉴权上下文、路由守卫、统一路由配置和布局。
|
||
- `src/shared/`:跨业务共享的 API 基础层、UI 组件、hooks、工具和图表封装。
|
||
- `src/features/<module>/`:业务模块,内部放 `api.ts`、`routes.js`、`permissions.js`、`schema.ts`、`hooks/`、`components/`、`pages/`。
|
||
- 新增后台业务模块必须优先落在 `src/features/`,不要重新创建横向 `pages/`、`api/`、`components/` 目录。
|
||
- 新增模块优先复制 `admin-module.example.json`,改成业务配置后运行 `pnpm gen:module <config.json>`;它会生成 feature、权限常量、路由接入和 OpenAPI 契约。
|
||
- 只需要预览生成内容时运行 `pnpm gen:module <config.json> --dry-run`。
|
||
- `pnpm scaffold:feature <feature-name>` 是低层级骨架命令,只有在不需要权限/菜单/契约自动接入时使用。
|
||
- API 契约或权限变更后运行 `pnpm gen:api`。
|
||
- 前端 API 路径必须从 `src/shared/api/generated/endpoints.ts` 取,不要在 feature API 中重新手写路径。
|
||
- 表单提交前必须走模块内 `schema.ts` 或共享 schema 校验。
|
||
|
||
## 按需导入规则
|
||
|
||
- MUI 组件必须路径导入,例如:
|
||
|
||
```js
|
||
import Button from "@mui/material/Button";
|
||
```
|
||
|
||
- MUI 图标必须路径导入,例如:
|
||
|
||
```js
|
||
import Refresh from "@mui/icons-material/Refresh";
|
||
```
|
||
|
||
- 不要使用总入口:
|
||
|
||
```js
|
||
import { Button } from "@mui/material";
|
||
import { Refresh } from "@mui/icons-material";
|
||
```
|
||
|
||
- ECharts 只在 `src/shared/charts/` 内封装和加载,不要在页面里直接散落图表初始化逻辑。
|
||
- 页面和抽屉继续使用 `React.lazy` 做拆分加载。
|
||
- 顶部搜索弹窗继续使用 lazy 加载,不要静态塞进主入口。
|
||
|
||
## 样式规则
|
||
|
||
- 状态色不要随意改:
|
||
- `--success`:运行中
|
||
- `--warning`:警告
|
||
- `--danger`:异常/危险操作
|
||
- `--stopped`:已停止
|
||
- 新增颜色优先写入 token 或 theme,不要在多个组件里重复硬编码。
|
||
- 基础组件的视觉兼容优先改封装组件,不要让页面直接依赖 MUI 细节。
|
||
- 不添加卡片套卡片。
|
||
- 不添加无业务意义的说明区、营销区、空泛介绍区。
|
||
|
||
## 后台表格交互规则
|
||
|
||
- 表格空态只显示 `当前无数据`,创建入口放在页面工具栏,不放在空态里。
|
||
- 表格里的启用/禁用状态优先使用行内 Switch 快捷操作,不使用单独的启用/禁用图标按钮。
|
||
- 表格状态筛选使用 Select 下拉框,默认值为 `全部状态`,不使用状态 chip 组。
|
||
- 后台列表页的时间区间筛选必须使用统一的单入口时间区间筛选框(`src/shared/ui/TimeRangeFilter.jsx`);不要在工具栏里并排放两个开始/结束时间输入框,也不要使用浏览器原生日期/时间输入样式。时间区间弹层内使用快捷项、日历和时分下拉点选,不使用手写时间文本框。
|
||
- 后台表单里的生效时间、有效期、投放时间等时间区间必须使用统一公共时间选择器(`src/shared/ui/TimeRangeFilter.jsx`);不要并排放两个开始/结束时间输入框,也不要使用浏览器原生日期/时间输入样式。
|
||
- 资源组选择必须优先使用统一的 `src/shared/ui/ResourceGroupSelectDrawer.jsx` / `ResourceGroupSelectField`,点击输入框打开右侧资源组图标抽屉,点击资源组后自动回填并关闭,不要在业务页面里重复实现资源组 Select 下拉,也不要用普通文本框填写资源组 ID。
|
||
- 区域编辑弹窗必须同时包含区域基础字段和国家码字段;国家码使用可搜索多选下拉框,不再拆成独立“区域国家”弹窗。
|
||
- 头像、图片、封面等图片资源字段必须使用 `src/shared/ui/UploadField.jsx` 上传表单组件,不使用普通文本输入框承载 URL。
|
||
- 图片上传表单必须提供统一预览;`webp` 使用浏览器原生动效预览,`svga` 使用 SVGA 播放器预览,`pag` 使用 libpag + wasm 预览。
|
||
- BD Leader 创建弹窗不选择区域、不提交 `regionId`;创建结果按目标用户当前区域生成,若区域不对,先修复用户国家/区域映射,再创建 BD Leader。
|
||
- 区域创建和区域启用/禁用调用后台管理后端接口,不要求 user-service 新增对应 RPC。
|
||
- 国家创建和国家启用/禁用调用后台管理后端接口,不要求 user-service 新增对应 RPC。
|
||
|
||
## 验证要求
|
||
|
||
每次完成前端改动后至少运行:
|
||
|
||
```bash
|
||
pnpm check:contracts
|
||
pnpm typecheck
|
||
pnpm lint
|
||
pnpm test
|
||
pnpm build
|
||
```
|
||
|
||
如果需要本地预览:
|
||
|
||
```bash
|
||
pnpm dev
|
||
```
|