docs: 补充仓库开发指南(AGENTS.md)
CI / check (pull_request) Successful in 2m59s
Dependency Check / check (pull_request) Successful in 1m21s

This commit is contained in:
2026-08-12 09:36:10 +08:00
parent d9cbaf0eda
commit 7987941a3c
+92 -9
View File
@@ -1,14 +1,97 @@
<!-- CODEGRAPH_START --> # Repository Guidelines
## CodeGraph
In repositories indexed by CodeGraph (a `.codegraph/` directory exists at the repo root), reach for it BEFORE grep/find or reading files when you need to understand or locate code: 恭学教育基地管理系统(gongxue-base)——教培公司集训基地管理系统:宿舍水电费「人天数加权」计费、学生/班级/排课/考勤管理、学生档案(报读/成绩/花名册)、AI 助手与导入向导。代码注释、用户可见文案、commit message 均为中文。
- **MCP tool** (when available): `codegraph_explore` answers most code questions in one call — the relevant symbols' verbatim source plus the call paths between them, including dynamic-dispatch hops grep can't follow. Name a file or symbol in the query to read its current line-numbered source. If it's listed but deferred, load it by name via tool search. ## Project Overview
- **Shell** (always works): `codegraph explore "<symbol names or question>"` prints the same output.
If there is no `.codegraph/` directory, skip CodeGraph entirely — indexing is the user's decision. npm workspaces 单体仓库(monorepo),Turborepo 编排:
<!-- CODEGRAPH_END -->
## Ant Design X | 包 | 技术栈 | 说明 |
|---|---|---|
| `apps/server` | NestJS 11 + TypeORM 0.3 + MySQL | REST APIJWT + RBAC 权限 |
| `apps/admin` | React + Vite + antd + TanStack Query + zustand | 管理后台 SPA |
| `packages/typescript-config` | 共享 tsconfigbase/nestjs/react-vite | 各包 extends 使用 |
修改 AI 助手、SSE 消息、运行时技能、附件或 Agent 工具前,先读取 `docs/skills/ant-design-x/SKILL.md`,优先使用项目已安装的 Ant Design X 组件与 SDK 远端:Gitea`git.gongxue100.com`wangziqi/gongxue-base)。`main` 为受保护分支,改动经分支 + PR`tea` CLI 合并,rebase 风格)
## Architecture & Data Flow
```
admin (axios /api, Bearer token) → NestJS controllers → services → TypeORM repos → MySQL (utf8mb4)
```
- **后端**`app.module.ts` 显式列出全部实体;TypeORM `migrationsRun: true` + glob 自动发现迁移;`synchronize` 仅当显式 `DB_SYNCHRONIZE=true`(生产禁用)。全局前缀 `/api``ValidationPipe({ transform: true })``/api/classes` 路由放宽 body 上限 2mb(花名册批量导入)。
- **权限**:服务端 `@RequirePermission('module:action')` + CASL 策略守卫;前端 `usePermission()` + `<PermissionButton permission="...">`。权限码由 RbacSeedService 播种。
- **前端**react-router 懒加载页面;数据请求走 TanStack Query`useApiQuery`/`useApiMutation``api/queryKeys.ts` 统一 key);全局状态 zustand`store/user` 存 token`store/permission` 存权限)。
- **认证**JWTaxios 拦截器自动带 token401 跳登录。
## Key Directories
- `apps/server/src/` — 按功能模块分目录:`auth``rbac``students``classes``exams``archive`(学生档案:报读/成绩/学习记录/附件/花名册同步)、`attendance``rooms``bills``wallets``imports`(导入向导)、`ai-chat``ai-config``agent-tools``integration``sync``operation-logs`
- `entities/` — 全部 TypeORM 实体;`migrations/` — 迁移文件(时间戳前缀);`common/` — dayjsUTC+8 固定)、mime、`with-audit-log`
- `apps/admin/src/``pages/`(路由页面)、`components/`(含 `EditableCell` 可编辑单元格体系)、`api/``hooks/``store/``layouts/``ui/``utils/``test/`
- `.gitea/workflows/``ci.yml`PR 校验)、`dependency-check.yml`npm audit)、`deploy.yml`PM2 部署)
- 根目录 — `deploy.sh`(部署脚本)、`ecosystem.config.cjs`pm2)、`turbo.json`
## Development Commands
```bash
# 根目录(turbo 透传)
npm run dev # 并行起 server(3000) + admin(3002)
npm run build / lint / typecheck / format / test
# 后端(apps/server
npm run dev -w @gongxue/server # SEED_DEV=true nest start --watch
npm run start:prod -w @gongxue/server # node dist/mainPM2 用这个)
npm run test -w @gongxue/server # jest,全部 *.spec.ts
npm run migration:generate -w @gongxue/server -- src/migrations/Name # 生成迁移(-d datasource.ts
npm run migration:run -w @gongxue/server # 执行迁移(部署时也跑)
# 前端(apps/admin
npm run dev -w @gongxue/admin # vite :3002,代理 /api → :3000
npm run test -w @gongxue/admin # vitest run
```
开发环境数据库:`.env`(gitignore,仅服务器保留生产版)。`apps/server/.env` 有本地开发配置(DB_PASSWORD 等),服务启动时 `dotenv` 加载。
## Code Conventions & Common Patterns
- **实体**:表名复数 snake_case;列用 `@Column({ name: 'snake_case' })``student` 关系多用 `eager: true`;状态枚举用 TS enum(如 `ClassStatus`);唯一约束用 `@Unique`
- **迁移**`MigrationInterface`,文件名 `{timestamp}-{Name}.ts`**必须幂等**——用 `hasColumn()`/`hasTable()`/`information_schema` 守卫再改结构。新增迁移文件零登记(glob 自动发现)。注意 `rank` 等 MySQL 保留字列名要反引号。
- **DTO**class-validator 装饰器链(`@IsOptional() @IsString()` 等),更新用 `PartialType(CreateXxxDto)`;数值上限与列宽对齐(如 `decimal(5,2)``@Max(999.99)`),否则超范围写库报 500。
- **服务**:构造器注入 `@InjectRepository(Entity)` + 服务类;跨表写操作用 `dataSource.transaction(async (manager) => ...)`;业务错误抛 `BadRequestException`/`NotFoundException`(中文消息)。
- **审计**controller 里包 `withAuditLog(this.logService, req, (result) => ({ module, action, targetId, targetType, detail }), () => service.method(...))`
- **权限**:路由 `@RequirePermission('student:edit')` 等;`student:view`/`student:edit` 是档案读写常用码。
- **前端数据流**:组件内 `useApiMutation(fn, { invalidate: [['archive', studentId]] })`——变更后按 query key 失效重取;错误提示统一走 `ui/app-message``message.success/error`),不要在组件里重复 try/catch 弹窗。
- **可编辑单元格**`EditableCell` editor 类型 `text|number|select|date|multi-select|tags``serializeEditableValue`/`normalizeEditableValue` 负责提交/展示值转换;`editableValuesEqual` 判空提交。
- **日期**:后端 `common/dayjs` 固定 UTC+8`dayjs().utcOffset(8).format('YYYY-MM-DD')`);前端 dayjs 加载 zh-cn locale 与 antd 面板插件。
- **commit message**`type(scope): 中文描述`(如 `feat(server):``fix(admin):``refactor(server):`),scope 为 `server`/`admin`
## Important Files
- `apps/server/src/main.ts` — bootstrap:全局前缀、ValidationPipe、body 上限、helmet/compression/cors
- `apps/server/src/app.module.ts` — 模块注册 + TypeORM 配置(entities 显式数组、migrations glob + `migrationsRun: true`
- `apps/server/datasource.ts` — CLI 迁移 DataSourceglob 实体/迁移,根目录 + 本地 `.env` 双加载)
- `apps/server/src/entities/student-enrollment.entity.ts` — 报读实体(`class_id` 关联班级,花名册同步的源)
- `apps/admin/src/api/index.ts` — axios 实例(baseURL `/api`、token 注入、401 登出)
- `apps/admin/src/App.tsx` — 路由表(lazy 页面 + `PermissionRoute`
- `ecosystem.config.cjs` — pm2 应用 `gongxue-backend``apps/server/dist/main.js`
- `deploy.sh` / `.gitea/workflows/deploy.yml` — 部署(见下)
- `README.md` — 功能模块总览
## Runtime/Tooling Preferences
- **Node 22 + npm 11**workspaces`packageManager: npm@11.12.1`CI 容器 `node:22.22.0-bookworm`),无 `.nvmrc`/engines 锁定
- **Turborepo**`turbo.json` 任务 `build`/`dev`/`lint`/`test`/`format`/`typecheck`
- **MySQL 8**,库名 `dorm_billing_v2`(生产 `jidi.gongxue100.com` 对应实例),`utf8mb4`,迁移记录在 `migrations`
- **TypeScript** `~6.0.2`server),共享配置 `packages/typescript-config``strictNullChecks: true`
- **Gitea Actions**runner `nonlocal-runner`(个人作用域,标签 `ubuntu-latest` 等,宿主机直跑无容器——deploy job 依赖此访问 PM2/部署目录)。CI job 显式声明 `container: node:22.22.0-bookworm`
- **tea CLI**PR 创建/合并(`tea pr create`/`tea pr merge -s rebase`)、触发 workflow`tea actions workflows dispatch`,需 Gitea ≥1.25;旧版用 API POST `actions/workflows/deploy.yml/dispatches`
- 部署:手动 dispatch「PM2 本地部署」workflow 或 `./deploy.sh <ssh_host>`;生产目录 `/www/wwwroot/jidi.gongxue100.com`(workflow 默认值,可用仓库变量 `REMOTE_DIR` 覆盖);顺序为 `git pull → npm ci → build → migration:run → pm2 startOrReload → 健康检查(401/200)`,迁移失败在 PM2 重载前中止
## Testing & QA
- **后端**Jest + ts-jest`testRegex: .*\.spec\.ts$`,测试文件与源码同目录(`*.spec.ts` 就近放置)。Repo 约定:`npm run test -w @gongxue/server -- --runInBand --forceExit`(CI 用)。服务测试用 jest.fn 构造 repo mock(新增构造参数会破坏 spec,需同步补 `{} as never` 占位)。关键服务有边界测试(`archive.boundaries.spec.ts``archive.enrollment-roster.spec.ts` 等)。
- **前端**Vitest + `@vitest/browser` + Playwright`src/test/setup.ts`),组件测试含截图快照(`__screenshots__/`)。
- **CI**`.gitea/workflows/ci.yml`PR → main 触发):`npm ci → lint → typecheck → build admin → server tests`
- **变更验证惯例**:UI 改动在浏览器验证;服务端逻辑跑相关 spec;迁移改动在本地库实跑并查 `migrations` 表;全量回归 `npx jest --silent`server,约 155 suites/1200+ tests)。