Files
wangziqi 7987941a3c
CI / check (pull_request) Successful in 2m59s
Dependency Check / check (pull_request) Successful in 1m21s
docs: 补充仓库开发指南(AGENTS.md)
2026-08-12 09:36:10 +08:00

8.7 KiB
Raw Permalink Blame History

Repository Guidelines

恭学教育基地管理系统(gongxue-base)——教培公司集训基地管理系统:宿舍水电费「人天数加权」计费、学生/班级/排课/考勤管理、学生档案(报读/成绩/花名册)、AI 助手与导入向导。代码注释、用户可见文案、commit message 均为中文。

Project Overview

npm workspaces 单体仓库(monorepo),Turborepo 编排:

技术栈 说明
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 使用

远端:Giteagit.gongxue100.comwangziqi/gongxue-base)。main 为受保护分支,改动经分支 + PRtea 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(生产禁用)。全局前缀 /apiValidationPipe({ transform: true })/api/classes 路由放宽 body 上限 2mb(花名册批量导入)。
  • 权限:服务端 @RequirePermission('module:action') + CASL 策略守卫;前端 usePermission() + <PermissionButton permission="...">。权限码由 RbacSeedService 播种。
  • 前端react-router 懒加载页面;数据请求走 TanStack QueryuseApiQuery/useApiMutationapi/queryKeys.ts 统一 key);全局状态 zustandstore/user 存 tokenstore/permission 存权限)。
  • 认证JWTaxios 拦截器自动带 token401 跳登录。

Key Directories

  • apps/server/src/ — 按功能模块分目录:authrbacstudentsclassesexamsarchive(学生档案:报读/成绩/学习记录/附件/花名册同步)、attendanceroomsbillswalletsimports(导入向导)、ai-chatai-configagent-toolsintegrationsyncoperation-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.ymlPR 校验)、dependency-check.ymlnpm audit)、deploy.ymlPM2 部署)
  • 根目录 — deploy.sh(部署脚本)、ecosystem.config.cjspm2)、turbo.json

Development Commands

# 根目录(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 保留字列名要反引号。
  • DTOclass-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-messagemessage.success/error),不要在组件里重复 try/catch 弹窗。
  • 可编辑单元格EditableCell editor 类型 text|number|select|date|multi-select|tagsserializeEditableValue/normalizeEditableValue 负责提交/展示值转换;editableValuesEqual 判空提交。
  • 日期:后端 common/dayjs 固定 UTC+8dayjs().utcOffset(8).format('YYYY-MM-DD'));前端 dayjs 加载 zh-cn locale 与 antd 面板插件。
  • commit messagetype(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-backendapps/server/dist/main.js
  • deploy.sh / .gitea/workflows/deploy.yml — 部署(见下)
  • README.md — 功能模块总览

Runtime/Tooling Preferences

  • Node 22 + npm 11workspacespackageManager: npm@11.12.1CI 容器 node:22.22.0-bookworm),无 .nvmrc/engines 锁定
  • Turborepoturbo.json 任务 build/dev/lint/test/format/typecheck
  • MySQL 8,库名 dorm_billing_v2(生产 jidi.gongxue100.com 对应实例),utf8mb4,迁移记录在 migrations
  • TypeScript ~6.0.2server),共享配置 packages/typescript-configstrictNullChecks: true
  • Gitea Actionsrunner nonlocal-runner(个人作用域,标签 ubuntu-latest 等,宿主机直跑无容器——deploy job 依赖此访问 PM2/部署目录)。CI job 显式声明 container: node:22.22.0-bookworm
  • tea CLIPR 创建/合并(tea pr create/tea pr merge -s rebase)、触发 workflowtea 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-jesttestRegex: .*\.spec\.ts$,测试文件与源码同目录(*.spec.ts 就近放置)。Repo 约定:npm run test -w @gongxue/server -- --runInBand --forceExit(CI 用)。服务测试用 jest.fn 构造 repo mock(新增构造参数会破坏 spec,需同步补 {} as never 占位)。关键服务有边界测试(archive.boundaries.spec.tsarchive.enrollment-roster.spec.ts 等)。
  • 前端Vitest + @vitest/browser + Playwrightsrc/test/setup.ts),组件测试含截图快照(__screenshots__/)。
  • CI.gitea/workflows/ci.ymlPR → main 触发):npm ci → lint → typecheck → build admin → server tests
  • 变更验证惯例:UI 改动在浏览器验证;服务端逻辑跑相关 spec;迁移改动在本地库实跑并查 migrations 表;全量回归 npx jest --silentserver,约 155 suites/1200+ tests)。