# glm-monorepo > 企智通项目全栈开发。后端 NestJS + Prisma,前端 React + TanStack Router + Shadcn UI。核心约定:CRUD 用抽屉、头部含搜索/主题/i18n/用户、文本 i18n 化、@ApiTags 英文、分页响应用 data 字段。开发前后端功能时使用此技能。 - Author: shichenyang - Repository: Gyv12345/qzt - Version: 20260209122917 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-09 - Source: https://github.com/Gyv12345/qzt - Web: https://mule.run/skillshub/@@Gyv12345/qzt~glm-monorepo:20260209122917 --- --- name: glm-monorepo description: 企智通项目全栈开发。后端 NestJS + Prisma,前端 React + TanStack Router + Shadcn UI。核心约定:CRUD 用抽屉、头部含搜索/主题/i18n/用户、文本 i18n 化、@ApiTags 英文、分页响应用 data 字段。开发前后端功能时使用此技能。 --- ## 快速开始 ```bash ./start-dev.sh # 启动(前端 3456,后端 7890,网站 5180) ``` ## 开发流程 ``` 后端开发 API → 生成客户端 → 前端使用 ``` 1. 后端添加 `@ApiTags('tag-name')` **(必须英文)** 2. `cd frontend && pnpm run generate:api` 3. 前端使用生成的 API 和类型 **注意**:前端禁止手写 API 调用代码!必须使用 Orval 生成的类型安全 API。 ## 核心约定(强制) ### 后端 | 约定 | 规则 | |------|------| | 分页响应 | `{ data, total, page, pageSize, totalPages }` - 必须用 `data` 字段 | | @ApiTags | 英文:`@ApiTags('contacts')`,中文会导致跨平台问题 | | 错误信息 | `this.i18n.t('common.BAD_REQUEST')` | | HTTP 状态码 | `201` 创建 \| `200` 非创建 POST \| `204` 无返回 | ### 前端 | 约定 | 规则 | |------|------| | CRUD 表单 | **必须用 Sheet/Drawer 抽屉**,禁止 Dialog | | 页面头部 | **必须包含** Search + ThemeSwitch + LanguageSwitch + ConfigDrawer + ProfileDropdown | | 文本 i18n | `t("module.title")`,禁止硬编码中文 | | 分页数据 | `data?.data`(非 `items`/`records`) | | API 调用 | `getScrmApi().xxxControllerXxx()` - 不要再次调用工厂函数 | | 删除确认 | 用 AlertDialog,禁用 `window.confirm` | | Hooks 规则 | 所有 Hooks 顶层调用,条件渲染放最后 | ### React Hooks ```tsx // ✅ Hooks 始终在顶层 function Component() { const data = useQuery() const memoized = useMemo(...) if (isLoading) return // 条件放最后 } // ❌ 早期返回破坏 Hooks if (isLoading) return const memoized = useMemo(...) ``` ## 目录结构 ``` backend/src/modules/{module}/ ├── {module}.controller.ts ├── {module}.service.ts ├── {module}.module.ts └── dto/ ├── create-{module}.dto.ts ├── update-{module}.dto.ts └── query-{module}.dto.ts frontend/src/features/{module}/ ├── index.tsx ├── types/{module}.ts # Zod schema ├── hooks/use-{module}s.ts # API hooks └── components/ ├── {module}s-table.tsx ├── {module}s-columns.tsx ├── {module}s-primary-buttons.tsx ├── {module}-form-drawer.tsx # 表单抽屉 └── data-table-row-actions.tsx ``` ## 常用命令 ```bash # API 生成 cd frontend && pnpm run generate:api # 数据库 cd backend && pnpm prisma generate && pnpm prisma db push # 项目清理 rm -rf website/.next frontend/node_modules/.vite frontend/node_modules/.cache logs/* ``` ## 项目维护 ### 可安全删除 | 文件 | 说明 | |------|------| | `website/.next/` | 构建产物 | | `frontend/node_modules/.vite/` | Vite 缓存 | | `logs/*`, `.DS_Store`, `*.iml` | 日志/系统文件 | | `package-lock.json` | 冗余(用 pnpm) | ### 必须保留 | 目录 | 原因 | |------|------| | `.idea/` | IDE 配置(已入版本控制) | | `packages/shared-types/` | 共享类型 | ### 依赖版本 ```bash pnpm add -F backend|shadcn-admin|website|shared-types @ # 当前: Zod ^4.3.6, React ^19.2.3-4, Axios ^1.13.4 ``` ### Workspace 注意事项 - 子项目**不应有** `pnpm-workspace.yaml`(会导致 `@qzt/shared-types` 无法解析) - `.idea/` 误删:`git restore .idea/` ## 检查清单 ### 后端 - [ ] 分页用 `data` 字段 - [ ] `@ApiTags` 英文 - [ ] 错误用 `this.i18n.t()` ### 前端 - [ ] CRUD 用抽屉 - [ ] 头部含 Search/Theme/i18n/User - [ ] 文本用 `t()` i18n - [ ] 分页用 `data?.data` - [ ] Hooks 顶层调用 - [ ] 删除用 AlertDialog ## 参考文档 | 文档 | 内容 | |------|------| | [contacts-crud-template.md](./references/contacts-crud-template.md) | CRUD 完整模板 | | [pagination-response-standard.md](./references/pagination-response-standard.md) | 分页响应规范 | | [troubleshooting.md](./references/troubleshooting.md) | 故障排除 | ## Zod v4 关键知识 项目使用 Zod ^4.3.6,shared-types 包中的 schema 必须遵循 v4 语法: ### 枚举验证消息 ```typescript // ✅ Zod v4 export const statusSchema = z.enum(['ACTIVE', 'INACTIVE'], { message: '状态必须是 ACTIVE 或 INACTIVE', }) // ❌ Zod v3(已废弃) export const statusSchema = z.enum(['ACTIVE', 'INACTIVE'], { errorMap: () => ({ message: '状态必须是 ACTIVE 或 INACTIVE' }), }) ``` ### ZodError API ```typescript // ✅ Zod v4 result.error.issues // 错误列表 // ❌ Zod v3(已废弃) result.error.errors ``` ### record() 必须指定两个参数 ```typescript // ✅ Zod v4 context: z.record(z.string(), z.unknown()).optional() // ❌ Zod v3(已废弃) context: z.record(z.any()).optional() ``` ### shared-types 构建失败时 ```bash cd packages/shared-types && pnpm build ``` 如果构建失败,通常是因为: 1. schema 文件中存在 `errorMap` 语法 2. `z.record()` 只有一个参数 3. `z.ZodError.errors` 被使用 修复后需重启:`./start-dev.sh restart`