# Competition Management System - Cursor User Rules (DEPRECATED)

⚠️ **此文件已废弃** - 请使用新的规则系统：
- 项目规则：`.cursor/rules/*.mdc`
- 快速参考：`AGENTS.md`
- 说明文档：`.cursor/RULES_README.md`

---

以下内容保留作为备份，但不再使用：

# Competition Management System - Cursor User Rules

## 项目概述

这是一个多租户的竞赛管理系统，采用前后端分离架构：
- **后端**: NestJS + TypeScript + Prisma + MySQL
- **前端**: Vue 3 + TypeScript + Vite + Ant Design Vue + Pinia
- **认证**: JWT + RBAC (基于角色的访问控制)
- **架构**: 多租户架构，数据完全隔离

## 后端开发规范

### 1. 模块结构

- 每个功能模块应包含：`module.ts`, `controller.ts`, `service.ts`, `dto/` 目录
- 模块命名使用复数形式（如 `users`, `roles`, `contests`）
- 子模块放在父模块目录下（如 `contests/works/`, `contests/teams/`）

### 2. 服务层 (Service)

- 所有数据库操作必须通过 PrismaService，禁止直接使用 SQL
- 服务方法必须处理租户隔离：所有查询必须包含 `tenantId` 条件
- 使用 `@Injectable()` 装饰器
- 构造函数注入依赖，使用 private readonly
- 方法命名：`create`, `findAll`, `findOne`, `update`, `remove`
- 查询方法应支持分页：使用 `skip` 和 `take` 参数

### 3. 控制器层 (Controller)

- 使用 `@Controller()` 装饰器，路径使用复数形式
- 所有路由默认需要认证（除非使用 `@Public()` 装饰器）
- 使用 `@Get()`, `@Post()`, `@Put()`, `@Delete()`, `@Patch()` 装饰器
- 从请求中获取租户ID：使用 `@CurrentTenantId()` 装饰器或从 JWT token 中提取
- 使用 `@CurrentUser()` 装饰器获取当前用户信息
- 权限控制：使用 `@RequirePermission()` 装饰器
- 返回统一响应格式：使用 TransformInterceptor（自动处理）

### 4. DTO (Data Transfer Object)

- 所有 DTO 放在 `dto/` 目录下
- 使用 `class-validator` 进行验证
- 命名规范：
  - 创建：`CreateXxxDto`
  - 更新：`UpdateXxxDto`
  - 查询：`QueryXxxDto`
- 必填字段使用验证装饰器（如 `@IsString()`, `@IsNumber()`）
- 可选字段使用 `@IsOptional()`
- 数组字段使用 `@IsArray()` 和 `@IsNumber({}, { each: true })`

### 5. 数据库操作 (Prisma)

- 所有表必须包含 `tenantId` 字段（租户隔离）
- 所有表必须包含审计字段：`creator`, `modifier`, `createTime`, `modifyTime`
- 使用 Prisma 的 `include` 和 `select` 优化查询
- 关联查询使用嵌套 include，避免 N+1 问题
- 删除操作使用软删除（`validState` 字段）或级联删除
- 事务操作使用 `prisma.$transaction()`

### 6. 多租户处理

- **必须**：所有业务数据查询必须包含 `tenantId` 条件
- 从 JWT token 或请求头中获取租户ID
- 创建数据时自动设置 `tenantId`
- 更新/删除时验证数据属于当前租户
- 超级租户（`isSuper = 1`）可以访问所有租户数据

### 7. 权限控制

- 使用 `@RequirePermission()` 装饰器进行权限检查
- 权限字符串格式：`模块:操作`（如 `contest:create`, `user:update`）
- 角色权限通过 RolesGuard 自动检查
- 权限验证失败返回 403 Forbidden

### 8. 错误处理

- 使用 NestJS 内置异常：`NotFoundException`, `BadRequestException`, `UnauthorizedException`, `ForbiddenException`
- 自定义异常消息使用中文
- 错误信息要清晰明确，便于调试

### 9. 代码风格

- 使用 TypeScript 严格模式
- 使用 ESLint 和 Prettier 格式化代码
- 导入顺序：NestJS 核心 → 第三方库 → 本地模块
- 使用 async/await，避免 Promise.then()
- 使用解构赋值提高代码可读性

## 前端开发规范

### 1. 组件结构

- 页面组件放在 `views/` 目录下，按模块组织
- 公共组件放在 `components/` 目录下
- 使用 `<script setup lang="ts">` 语法
- 组件命名使用 PascalCase

### 2. API 调用

- 所有 API 调用放在 `api/` 目录下，按模块组织
- 使用 axios 实例（已配置拦截器）
- API 函数命名：`getXxx`, `createXxx`, `updateXxx`, `deleteXxx`
- 使用 TypeScript 类型定义请求和响应

### 3. 状态管理 (Pinia)

- Store 文件放在 `stores/` 目录下
- 使用 `defineStore()` 定义 store
- Store 命名使用 camelCase + Store 后缀（如 `authStore`）

### 4. 路由管理

- 路由配置在 `router/index.ts`
- 支持动态路由（基于菜单权限）
- 路由路径包含租户编码：`/:tenantCode/xxx`
- 路由 meta 包含权限信息：`permissions`, `roles`

### 5. 表单验证

- 使用 VeeValidate + Zod 进行表单验证
- 验证规则定义在组件内或单独的 schema 文件
- 错误提示使用中文

### 6. UI 组件

- 使用 Ant Design Vue 组件库
- 样式使用 Tailwind CSS + SCSS
- 响应式设计：移动端优先
- 组件要有 loading 和 error 状态

### 7. 类型定义

- TypeScript 类型定义放在 `types/` 目录下
- 接口类型使用 `interface`，数据模型使用 `type`
- 导出类型供其他模块使用

## 数据库设计规范

### 1. 表结构

- 所有业务表必须包含 `tenantId` 字段
- 所有表必须包含审计字段：
  - `creator`: Int? - 创建人ID
  - `modifier`: Int? - 修改人ID
  - `createTime`: DateTime @default(now()) - 创建时间
  - `modifyTime`: DateTime @updatedAt - 修改时间
- 状态字段使用 `validState`: Int @default(1)（1-有效，2-失效）
- 表名使用复数形式，映射使用 `@@map("table_name")`

### 2. 关系设计

- 使用 Prisma 关系定义外键
- 级联删除：`onDelete: Cascade`
- 可选关联：`onDelete: SetNull`
- 一对一关系：使用 `?` 标记可选

### 3. 索引

- 主键自动索引
- 外键字段自动索引
- 查询频繁的字段添加索引
- 唯一约束使用 `@unique`

### 4. 迁移

- 使用 Prisma Migrate 管理数据库迁移
- 迁移文件命名：`YYYYMMDDHHMMSS_description`
- 迁移前备份数据库
- 生产环境使用 `prisma migrate deploy`

## 通用开发规范

### 1. Git 提交

- 提交信息使用中文
- 格式：`类型: 描述`（如 `feat: 添加竞赛管理功能`）
- 类型：`feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`

### 2. 注释

- 复杂逻辑必须添加注释
- 函数注释说明参数和返回值
- 使用中文注释

### 3. 测试

- 单元测试文件命名：`*.spec.ts`
- 测试覆盖率要求：核心业务逻辑 > 80%
- 使用 Jest 进行测试

### 4. 环境配置

- 使用 `.env.development` 和 `.env.production`
- 敏感信息不要提交到 Git
- 配置项通过 `@nestjs/config` 管理

### 5. 日志

- 使用 NestJS Logger
- 日志级别：`error`, `warn`, `log`, `debug`, `verbose`
- 记录关键操作和错误信息

## 安全规范

### 1. 认证授权

- 所有 API 默认需要 JWT 认证
- 密码使用 bcrypt 加密（salt rounds: 10）
- Token 过期时间合理设置
- 敏感操作需要额外验证

### 2. 数据验证

- 前端和后端都要进行数据验证
- 使用 DTO 和 class-validator 验证输入
- 防止 SQL 注入：使用 Prisma（参数化查询）
- 防止 XSS：前端转义用户输入

### 3. 权限控制

- 最小权限原则
- 前端显示控制 + 后端权限验证
- 租户数据隔离必须严格检查

## 性能优化

### 1. 数据库查询

- 避免 N+1 查询，使用 `include` 预加载
- 使用 `select` 只查询需要的字段
- 分页查询必须实现
- 大表查询添加索引

### 2. API 响应

- 响应数据精简，避免返回不必要字段
- 使用分页减少单次数据量
- 长时间操作使用异步处理

### 3. 前端优化

- 路由懒加载
- 组件按需加载
- 图片使用 CDN 或压缩
- 避免不必要的重新渲染

## 代码审查检查清单

- [ ] 所有数据库查询包含 `tenantId` 条件
- [ ] DTO 验证规则完整
- [ ] 错误处理完善
- [ ] 权限检查正确
- [ ] 代码格式符合规范
- [ ] 注释清晰
- [ ] 无硬编码配置
- [ ] 类型定义完整
- [ ] 无控制台日志（生产环境）

## 常见问题

### Q: 如何获取当前租户ID？
A: 在控制器中使用 `@CurrentTenantId()` 装饰器，或在服务中从 JWT token 提取。

### Q: 如何创建新的业务模块？
A: 
1. 在 Prisma schema 中定义模型
2. 运行 `prisma migrate dev`
3. 创建模块目录和文件（module, controller, service, dto）
4. 在 `app.module.ts` 中注册模块
5. 创建前端 API 和页面

### Q: 如何处理多租户数据隔离？
A: 
- 查询时始终包含 `where: { tenantId }`
- 创建时自动设置 `tenantId`
- 更新/删除前验证数据属于当前租户

### Q: 如何添加新的权限？
A: 
1. 在数据库中创建权限记录
2. 在路由或控制器方法上使用 `@RequirePermission('module:action')`
3. 在前端路由 meta 中添加 `permissions` 字段

