2026-05-20 14:34:41 +08:00

6.8 KiB
Raw Permalink Blame History

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。

当前实现方式

  • 框架React + Vite。
  • UI 组件库MUI。
  • 图表库ECharts。
  • 包管理器pnpm。
  • 页面:按业务放在 src/features/*/pages/
  • 应用壳:src/app/App.jsxsrc/app/layout/AdminLayout.jsxsrc/app/router/routeConfig.ts
  • 页面加载占位:src/shared/ui/PageSkeleton.jsx
  • 全局资源组选择抽屉:src/shared/ui/ResourceGroupSelectDrawer.jsx,资源组字段优先使用该组件,不在业务页面里重复手写普通下拉。
  • 顶部搜索弹窗:src/features/search/components/SearchDialog.jsx
  • MUI 主题:src/theme.js
  • CSS tokensrc/styles/tokens.css
  • 样式入口:src/styles/app.css,实际样式按 src/styles/*.csssrc/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.tssrc/shared/api/generated/endpoints.ts

目录规范

  • src/app/应用壳、Provider、鉴权上下文、路由守卫、统一路由配置和布局。
  • src/shared/:跨业务共享的 API 基础层、UI 组件、hooks、工具和图表封装。
  • src/features/<module>/:业务模块,内部放 api.tsroutes.jspermissions.jsschema.tshooks/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 组件必须路径导入,例如:
import Button from "@mui/material/Button";
  • MUI 图标必须路径导入,例如:
import Refresh from "@mui/icons-material/Refresh";
  • 不要使用总入口:
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/ResourceGroupSelectDrawer.jsx,点击输入框打开右侧资源组图标抽屉,点击资源组后自动回填并关闭,不要在业务页面里重复实现资源组 Select 下拉。
  • 区域编辑弹窗必须同时包含区域基础字段和国家码字段;国家码使用可搜索多选下拉框,不再拆成独立“区域国家”弹窗。
  • 头像、图片、封面等图片资源字段必须使用 src/shared/ui/UploadField.jsx 上传表单组件,不使用普通文本输入框承载 URL。
  • 图片上传表单必须提供统一预览;webp 使用浏览器原生动效预览,svga 使用 SVGA 播放器预览,pag 使用 libpag + wasm 预览。
  • BD Leader 创建弹窗必须使用区域下拉选择 regionId;目标用户原区域可以不同,创建成功后后端会把目标用户当前区域同步到所选区域。
  • 区域创建和区域启用/禁用调用后台管理后端接口,不要求 user-service 新增对应 RPC。
  • 国家创建和国家启用/禁用调用后台管理后端接口,不要求 user-service 新增对应 RPC。

验证要求

每次完成前端改动后至少运行:

pnpm check:contracts
pnpm typecheck
pnpm lint
pnpm test
pnpm build

如果需要本地预览:

pnpm dev