# NestJS 后端项目分析报告

> 项目路径：`backend/`
> 分析日期：2026-03-28
> 项目类型：多租户竞赛/活动管理系统

---

## 一、技术栈概览

| 组件 | 技术选型 | 版本 |
|------|----------|------|
| **框架** | NestJS | 10.3.3 |
| **语言** | TypeScript | 5.3.3 |
| **数据库** | MySQL | 8.0+ |
| **ORM** | Prisma | 6.19.0 |
| **认证** | JWT + Passport | - |
| **加密** | bcrypt | 6.0.0 |
| **文件存储** | 腾讯云 COS | - |
| **部署** | PM2 | - |
| **AI 集成** | 腾讯混元 | - |

### 核心依赖

```json
{
  "@nestjs/common": "^10.3.3",
  "@nestjs/core": "^10.3.3",
  "@nestjs/jwt": "^10.2.0",
  "@nestjs/passport": "^10.0.3",
  "@prisma/client": "^6.19.0",
  "passport-jwt": "^4.0.1",
  "bcrypt": "^6.0.0",
  "class-validator": "^0.14.1",
  "class-transformer": "^0.5.1",
  "cos-nodejs-sdk-v5": "^2.15.4"
}
```

---

## 二、项目架构

### 目录结构

```
backend/
├── src/
│   ├── ai-3d/                    # AI 3D 生成模块
│   ├── auth/                     # 认证授权模块
│   ├── common/                   # 公共模块（过滤器、拦截器）
│   ├── config/                   # 系统配置模块
│   ├── contests/                 # 竞赛管理模块（核心）
│   │   ├── contests/             # 活动管理
│   │   ├── attachments/          # 附件管理
│   │   ├── judges/               # 评委管理
│   │   ├── notices/              # 公告管理
│   │   ├── preset-comments/      # 预设评语库
│   │   ├── registrations/        # 报名管理
│   │   ├── results/              # 结果管理
│   │   ├── review-rules/         # 评审规则
│   │   ├── reviews/              # 评审管理
│   │   ├── teams/                # 团队管理
│   │   └── works/                # 作品管理
│   ├── dict/                     # 数据字典模块
│   ├── homework/                 # 作业模块
│   │   ├── homeworks/            # 作业管理
│   │   ├── review-rules/         # 评审规则
│   │   ├── scores/               # 评分管理
│   │   └── submissions/          # 提交管理
│   ├── judges-management/        # 评委管理模块
│   ├── logs/                     # 日志模块
│   ├── menus/                    # 菜单管理模块
│   ├── oss/                      # 对象存储模块
│   ├── permissions/              # 权限管理模块
│   ├── prisma/                   # Prisma 服务
│   ├── public/                   # 公共接口模块
│   ├── roles/                    # 角色管理模块
│   ├── school/                   # 学校管理模块
│   │   ├── schools/              # 学校管理
│   │   ├── grades/               # 年级管理
│   │   ├── classes/              # 班级管理
│   │   ├── departments/          # 部门管理
│   │   ├── teachers/             # 教师管理
│   │   └── students/             # 学生管理
│   ├── tenants/                  # 租户管理模块
│   ├── upload/                   # 文件上传模块
│   ├── users/                    # 用户管理模块
│   ├── app.module.ts             # 根模块
│   └── main.ts                   # 入口文件
├── prisma/
│   ├── schema.prisma             # 数据库模型定义
│   └── migrations/               # 数据库迁移文件
├── scripts/                      # 初始化脚本
├── test/                         # 测试文件
└── package.json
```

---

## 三、核心功能模块详解

### 1. 认证授权模块 (`auth/`)

**文件结构：**
```
auth/
├── auth.controller.ts      # 认证控制器
├── auth.service.ts         # 认证服务
├── auth.module.ts          # 认证模块
├── decorators/             # 装饰器
│   ├── current-tenant-id.decorator.ts    # 当前租户 ID 装饰器
│   ├── public.decorator.ts               # 公开接口装饰器
│   ├── require-permission.decorator.ts   # 权限装饰器
│   └── roles.decorator.ts                # 角色装饰器
├── guards/                 # 守卫
│   ├── jwt-auth.guard.ts       # JWT 认证守卫
│   ├── roles.guard.ts          # 角色守卫
│   └── permissions.guard.ts    # 权限守卫
└── strategies/             # Passport 策略
    ├── jwt.strategy.ts         # JWT 策略
    └── local.strategy.ts       # 本地策略
```

**核心功能：**
- 用户名密码登录
- JWT Token 签发与验证
- 权限验证（基于装饰器）
- 角色验证
- 多租户识别

**核心代码示例：**

```typescript
// auth.service.ts - 登录逻辑
async login(user: any, tenantId?: number) {
  // 验证租户有效
  const tenant = await this.prisma.tenant.findUnique({
    where: { id: finalTenantId },
  });

  // 签发 JWT Token
  const payload = {
    username: user.username,
    sub: user.id,
    tenantId: finalTenantId,
  };

  return {
    token: this.jwtService.sign(payload),
    user: {
      id: user.id,
      username: user.username,
      roles: user.roles?.map((ur: any) => ur.role.code) || [],
      permissions: await this.getUserPermissions(user.id),
    },
  };
}
```

---

### 2. 用户管理模块 (`users/`)

**核心功能：**
- 用户 CRUD 操作
- 用户状态管理（启用/禁用）
- 关键字搜索（用户名、昵称、邮箱、手机号）
- 超级租户跨租户查询
- 用户统计分析

**接口列表：**

| 接口 | 方法 | 权限 | 说明 |
|------|------|------|------|
| `POST /users` | POST | `user:create` | 创建用户 |
| `GET /users` | GET | `user:view` | 用户列表（分页） |
| `GET /users/stats` | GET | `super_admin` | 用户统计 |
| `GET /users/:id` | GET | `user:view` | 用户详情 |
| `PUT /users/:id` | PUT | `user:update` | 更新用户 |
| `PUT /users/:id/status` | PUT | `user:manage` | 切换状态 |
| `DELETE /users/:id` | DELETE | `user:delete` | 删除用户 |

**特色功能：**
```typescript
// 用户类型统计（仅超管）
async getStats() {
  const superTenantIds = ...; // 平台租户 ID
  const orgTenantIds = ...;   // 机构租户 ID
  const judgeTenantIds = ...; // 评委租户 ID

  return {
    total,      // 总用户数
    platform,   // 平台用户数
    org,        // 机构用户数
    judge,      // 评委用户数
    public: publicCount, // 公共用户数
  };
}
```

---

### 3. 竞赛/活动管理模块 (`contests/`) ⭐核心业务

**模块结构：**
```
contests/
├── contests/              # 活动主体管理
├── registrations/         # 报名管理
├── teams/                 # 团队管理
├── works/                 # 作品管理
├── reviews/               # 评审管理
├── judges/                # 评委管理
├── results/               # 结果管理
├── review-rules/          # 评审规则
├── preset-comments/       # 预设评语库
├── notices/               # 公告管理
└── attachments/           # 附件管理
```

#### 3.1 活动管理 (`contests/contests/`)

**活动生命周期：**
```
┌─────────────┐
│  未发布      │
│ unpublished │
└──────┬──────┘
       │ 发布
       ▼
┌─────────────┐     ┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│  已发布      │ ──► │  报名中      │ ──► │  作品提交中  │ ──► │  评审中      │
│ published   │     │ registering │     │ submitting  │     │ reviewing   │
└─────────────┘     └─────────────┘     └─────────────┘     └──────┬──────┘
                                                                   │
                                  ┌─────────────┐                  │
                                  │  已完结      │ ◄────────────────┘
                                  │  finished   │
                                  └─────────────┘
```

**核心服务方法：**

```typescript
// 判断活动当前所处阶段
getContestStage(contest: any): string {
  const now = new Date();
  const regStart = new Date(contest.registerStartTime);
  const regEnd = new Date(contest.registerEndTime);
  const subStart = new Date(contest.submitStartTime);
  const subEnd = new Date(contest.submitEndTime);
  const revStart = new Date(contest.reviewStartTime);
  const revEnd = new Date(contest.reviewEndTime);

  if (now >= regStart && now <= regEnd) return 'registering';
  if (now >= subStart && now <= subEnd) return 'submitting';
  if (now >= revStart && now <= revEnd) return 'reviewing';
  if (revEnd && now > revEnd) return 'finished';
  return 'published';
}
```

#### 3.2 报名管理 (`registrations/`)

**功能：**
- 个人/团队报名
- 报名审核（需要审核的活动）
- 报名状态管理

#### 3.3 作品管理 (`works/`)

**功能：**
- 作品提交（支持多次提交配置）
- 作品版本管理（`isLatest` 标识最新版本）
- 作品状态流转

#### 3.4 评审管理 (`reviews/`)

**功能：**
- 评委分配（手动/批量/自动）
- 作品评分
- 分数统计

**评分 DTO：**
```typescript
// create-score.dto.ts
export class CreateScoreDto {
  @IsInt()
  workId: number;

  @IsInt()
  judgeId: number;

  @IsNumber()
  score: number;

  @IsString()
  @IsOptional()
  comment: string;  // 评语
}
```

#### 3.5 结果管理 (`results/`)

**功能：**
- 手动设置奖项
- 批量设置奖项
- 自动设置奖项（按分数排名）

```typescript
// 自动设置奖项 DTO
export class AutoSetAwardsDto {
  @IsInt()
  contestId: number;

  @IsInt()
  firstPrizeCount: number;   // 一等奖数量
  @IsInt()
  secondPrizeCount: number;  // 二等奖数量
  @IsInt()
  thirdPrizeCount: number;   // 三等奖数量
}
```

---

### 4. 学校管理模块 (`school/`)

**模块结构：**
```
school/
├── schools/           # 学校信息
├── grades/            # 年级管理
├── classes/           # 班级管理
├── departments/       # 部门管理
├── teachers/          # 教师管理
└── students/          # 学生管理
```

**数据库关系：**
```
Tenant (1) ── (1) School
Tenant (1) ── (N) Grade
Tenant (1) ── (N) Class
Tenant (1) ── (N) Teacher
Tenant (1) ── (N) Student
```

---

### 5. AI 3D 生成模块 (`ai-3d/`) ⭐特色功能

**文件结构：**
```
ai-3d/
├── ai-3d.controller.ts
├── ai-3d.service.ts
├── ai-3d.module.ts
├── providers/
│   ├── ai-3d-provider.interface.ts  # AI 提供商接口
│   ├── hunyuan.provider.ts          # 腾讯混元实现
│   └── mock.provider.ts             # Mock 实现
└── utils/
    ├── tencent-cloud-sign.ts        # 腾讯云签名
    └── zip-handler.ts               # ZIP 处理
```

**功能：**
- AI 生成 3D 模型（腾讯混元 API 集成）
- 任务创建与状态查询
- 模型文件压缩与下载

**DTO：**
```typescript
// create-task.dto.ts
export class CreateTaskDto {
  @IsString()
  prompt: string;      // 生成提示词

  @IsString()
  @IsOptional()
  style?: string;      // 风格（写实/卡通/低多边形）

  @IsString()
  @IsOptional()
  negativePrompt?: string;  // 负面提示词
}
```

---

### 6. 作业模块 (`homework/`)

**功能：**
- 作业发布与提交
- 作业评审
- 评分管理

**与竞赛模块的区别：**
- 作业更轻量化，适合日常教学场景
- 评审流程简化
- 支持班级维度布置

---

### 7. 系统管理模块

#### 7.1 角色权限 (`roles/`, `permissions/`)

**RBAC 模型：**
```
User ──(N)── UserRole ──(1)── Role
Role ──(N)── RolePermission ──(1)── Permission
```

**权限装饰器：**
```typescript
@RequirePermission('user:create')
async createUser(...) {
  // 只有拥有 user:create 权限的用户才能访问
}
```

#### 7.2 菜单管理 (`menus/`)

**功能：**
- 动态菜单配置
- 菜单权限绑定
- 租户菜单定制（`TenantMenu`）

#### 7.3 数据字典 (`dict/`)

**功能：**
- 常用数据字典配置
- 支持租户自定义字典

#### 7.4 系统配置 (`config/`)

**功能：**
- 系统参数配置
- 租户级配置隔离
- 配置验证接口

---

### 8. 文件存储模块 (`upload/`, `oss/`)

**腾讯云 COS 集成：**

```typescript
// oss.service.ts
async uploadFile(file: Express.Multer.File, dir: string) {
  const client = new COS({
    SecretId: this.secretId,
    SecretKey: this.secretKey,
  });

  const key = `${dir}/${Date.now()}-${file.originalname}`;

  await client.putObject({
    Bucket: this.bucket,
    Region: this.region,
    Key: key,
    Body: file.buffer,
  });

  return `https://${this.bucket}.cos.${this.region}.myqcloud.com/${key}`;
}
```

---

## 四、数据库设计

### 核心数据表

#### 1. 租户表 (`Tenant`)

```prisma
model Tenant {
  id           Int      @id @default(autoincrement())
  name         String   // 租户名称
  code         String   @unique // 租户编码
  domain       String?  @unique // 租户域名
  description  String?
  isSuper      Int      @default(0) // 是否超级租户
  tenantType   String   @default("other")
  validState   Int      @default(1)
  createTime   DateTime @default(now())
  modifyTime   DateTime @updatedAt

  users        User[]
  roles        Role[]
  contests     Contest[]
  school       School?
  // ...
}
```

#### 2. 用户表 (`User`)

```prisma
model User {
  id           Int      @id @default(autoincrement())
  tenantId     Int
  username     String
  password     String
  nickname     String?
  email        String?
  phone        String?
  avatar       String?
  status       String   @default("enabled")
  validState   Int      @default(1)
  createTime   DateTime @default(now())

  tenant       Tenant   @relation(fields: [tenantId], references: [id])
  roles        UserRole[]
  children     User[]          // 家长 - 孩子关联
  parent       User?     @relation("ParentChild", fields: [parentId], references: [id])
  contestRegistrations ContestRegistration[]
  contestWorks ContestWork[]
  // ...
}
```

#### 3. 活动表 (`Contest`)

```prisma
model Contest {
  id                  Int      @id @default(autoincrement())
  contestName         String
  contestType         String   // 竞赛类型
  contestState        String   @default("unpublished")
  status              String   @default("ongoing")
  visibility          String   @default("designated")
  contestTenants      String?  // JSON: 可见租户 ID 列表

  registerStartTime   DateTime
  registerEndTime     DateTime
  submitStartTime     DateTime
  submitEndTime       DateTime
  reviewStartTime     DateTime
  reviewEndTime       DateTime
  resultPublishTime   DateTime?

  teamMinMembers      Int      @default(1)
  teamMaxMembers      Int      @default(1)
  requireAudit        Boolean  @default(true)

  attachments         ContestAttachment[]
  registrations       ContestRegistration[]
  teams               ContestTeam[]
  works               ContestWork[]
  judges              ContestJudge[]
  reviewRule          ContestReviewRule?
  notices             ContestNotice[]
  // ...
}
```

#### 4. 作品表 (`ContestWork`)

```prisma
model ContestWork {
  id           Int      @id @default(autoincrement())
  contestId    Int
  userId       Int
  teamId       Int?
  title        String
  description  String?
  coverUrl     String?
  workUrl      String?
  workType     String   // 作品类型
  version      Int      @default(1)
  isLatest     Boolean  @default(true)
  status       String   @default("submitted")

  contest      Contest  @relation(fields: [contestId], references: [id])
  author       User     @relation(fields: [userId], references: [id])
  team         ContestTeam?
  scores       ContestWorkScore[]
  attachments  ContestWorkAttachment[]
  // ...
}
```

#### 5. 评分表 (`ContestWorkScore`)

```prisma
model ContestWorkScore {
  id           Int      @id @default(autoincrement())
  workId       Int
  judgeId      Int
  contestId    Int
  score        Decimal
  comment      String?

  work         ContestWork @relation(fields: [workId], references: [id])
  judge        User        @relation(fields: [judgeId], references: [id])
  contest      Contest     @relation(fields: [contestId], references: [id])

  @@unique([workId, judgeId])  // 同一评委对同一作品只能评分一次
}
```

### 完整 ER 图（核心部分）

```
┌─────────────┐
│   Tenant    │
│  (租户表)    │
└──────┬──────┘
       │
       ├───► ┌─────────────┐       ┌─────────────┐
       │     │    User     │──────►│    Role     │
       │     │  (用户表)    │       │  (角色表)    │
       │     └──────┬──────┘       └─────────────┘
       │            │
       │            ├───► ┌─────────────┐       ┌─────────────┐
       │            │     │  Contest    │──────►│ContestWork  │
       │            │     │  (活动表)   │       │  (作品表)   │
       │            │     └──────┬──────┘       └──────┬──────┘
       │            │            │                     │
       │            │            ├───► ┌─────────────┐ │
       │            │            │     │ContestTeam  │◄┘
       │            │            │     │  (团队表)   │
       │            │            │     └─────────────┘
       │            │            │
       │            │            ├───► ┌─────────────┐
       │            │            │     │ContestJudge │
       │            │            │     │  (评委表)   │
       │            │            │     └─────────────┘
       │            │            │
       │            │            └───► ┌─────────────┐
       │            │                  │ContestWork  │
       │            │                  │   Score     │
       │            │                  │  (评分表)   │
       │            │                  └─────────────┘
       │            │
       │            └───► ┌─────────────┐
       │                  │   School    │
       │                  │  (学校表)   │
       │                  └──────┬──────┘
       │                         │
       │                         ├───► ┌─────────────┐
       │                         │     │   Teacher   │
       │                         │     │  (教师表)   │
       │                         │     └─────────────┘
       │                         │
       │                         └───► ┌─────────────┐
       │                               │   Student   │
       │                               │  (学生表)   │
       │                               └─────────────┘
       │
       └───► ┌─────────────┐
             │  Permission │
             │  (权限表)   │
             └─────────────┘
```

---

## 五、核心业务流程

### 1. 活动创建流程

```
1. 管理员创建活动
   ↓
2. 配置报名参数（时间、人数限制、需审核等）
   ↓
3. 配置评审规则（评分维度、权重）
   ↓
4. 设置可见范围（公开/指定租户）
   ↓
5. 发布活动
```

### 2. 用户参赛流程

```
1. 用户查看活动列表
   ↓
2. 个人报名 / 创建团队
   ↓
3. 等待审核（如需）
   ↓
4. 提交作品（可多次提交，保留最新版本）
   ↓
5. 等待评审
   ↓
6. 查看结果
```

### 3. 作品评审流程

```
1. 系统/管理员分配评委到作品
   ↓
2. 评委登录系统查看分配的作品
   ↓
3. 评委评分（填写分数 + 评语）
   ↓
4. 系统统计总分/平均分
   ↓
5. 自动生成获奖名单
```

### 4. AI 3D 生成流程

```
1. 用户提交生成请求（提示词）
   ↓
2. 系统调用腾讯混元 API
   ↓
3. 轮询任务状态
   ↓
4. 下载生成的 3D 模型
   ↓
5. 可选：压缩为 ZIP 格式
```

---

## 六、多租户架构

### 租户类型

| 类型 | 说明 | 权限 |
|------|------|------|
| **超级租户** | 平台管理员 | 访问所有数据 |
| **机构租户** | 学校/图书馆等 | 访问本机构数据 |
| **评委租户** | 评委专用 | 访问评审相关数据 |
| **公共租户** | 公共资源 | 访问公开数据 |

### 数据隔离实现

```typescript
// 所有业务查询必须包含租户 ID
const contests = await prisma.contest.findMany({
  where: {
    tenantId: currentTenantId,
    validState: 1,
  },
});

// 超级租户跨租户查询
const allContests = await prisma.contest.findMany({
  where: isSuperTenant
    ? { validState: 1 }  // 超管查询全部
    : { tenantId: currentTenantId, validState: 1 },  // 普通租户仅查询本租户
});
```

---

## 七、中间件与拦截器

### 1. JWT 认证守卫 (`JwtAuthGuard`)

```typescript
@Injectable()
export class JwtAuthGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest();
    const token = this.extractTokenFromHeader(request);

    if (!token) throw new UnauthorizedException();

    try {
      const payload = this.jwtService.verify(token);
      request['user'] = payload;
    } catch {
      throw new UnauthorizedException();
    }

    return true;
  }
}
```

### 2. 权限守卫 (`PermissionsGuard`)

```typescript
@Injectable()
export class PermissionsGuard implements CanActivate {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    const requiredPermission = this.reflector.get<string[]>(
      REQUIRE_PERMISSION_KEY,
      context.getHandler()
    );

    if (!requiredPermission) return true;

    const { user } = context.switchToHttp().getRequest();
    const permissions = await this.authService.getUserPermissions(user.sub);

    return permissions.some(p => requiredPermission.includes(p));
  }
}
```

### 3. 响应转换拦截器 (`TransformInterceptor`)

```typescript
@Injectable()
export class TransformInterceptor<T>
  implements NestInterceptor<T, Response<T>> {
  intercept(
    context: ExecutionContext,
    next: CallHandler,
  ): Observable<Response<T>> {
    return next.handle().pipe(
      map(data => ({
        code: 200,
        message: '操作成功',
        data: data.data || data,
        total: data.total,
      })),
    );
  }
}
```

---

## 八、初始化脚本

项目提供了丰富的初始化脚本：

```bash
# 初始化管理员账户
pnpm init:admin

# 初始化菜单
pnpm init:menus

# 初始化超级租户
pnpm init:super-tenant

# 初始化租户管理员
pnpm init:tenant-admin

# 初始化角色权限
pnpm init:roles:all

# 数据库迁移
pnpm prisma:migrate

# Prisma Studio（数据库可视化）
pnpm prisma:studio
```

---

## 九、API 接口概览

### 认证相关
| 接口 | 方法 | 说明 |
|------|------|------|
| `POST /auth/login` | POST | 用户登录 |
| `POST /auth/logout` | POST | 用户登出 |
| `GET /auth/info` | GET | 获取当前用户信息 |

### 用户管理
| 接口 | 方法 | 说明 |
|------|------|------|
| `GET /users` | GET | 用户列表 |
| `POST /users` | POST | 创建用户 |
| `GET /users/:id` | GET | 用户详情 |
| `PUT /users/:id` | PUT | 更新用户 |
| `PUT /users/:id/status` | PUT | 切换状态 |
| `DELETE /users/:id` | DELETE | 删除用户 |

### 活动管理
| 接口 | 方法 | 说明 |
|------|------|------|
| `GET /contests` | GET | 活动列表 |
| `POST /contests` | POST | 创建活动 |
| `GET /contests/:id` | GET | 活动详情 |
| `PUT /contests/:id` | PUT | 更新活动 |
| `POST /contests/:id/publish` | POST | 发布/取消发布 |
| `DELETE /contests/:id` | DELETE | 删除活动 |

### 报名管理
| 接口 | 方法 | 说明 |
|------|------|------|
| `GET /contests/:contestId/registrations` | GET | 报名列表 |
| `POST /contests/:contestId/registrations` | POST | 创建报名 |
| `PUT /registrations/:id/review` | PUT | 审核报名 |

### 作品管理
| 接口 | 方法 | 说明 |
|------|------|------|
| `GET /contests/:contestId/works` | GET | 作品列表 |
| `POST /contests/:contestId/works` | POST | 提交作品 |
| `PUT /works/:id` | PUT | 更新作品 |

### 评审管理
| 接口 | 方法 | 说明 |
|------|------|------|
| `POST /contests/:contestId/reviews/assign` | POST | 分配评审 |
| `POST /reviews/scores` | POST | 提交评分 |
| `GET /contests/:contestId/reviews/stats` | GET | 评审统计 |

### 结果管理
| 接口 | 方法 | 说明 |
|------|------|------|
| `GET /contests/:contestId/results` | GET | 结果列表 |
| `POST /contests/:contestId/results/set-awards` | POST | 设置奖项 |
| `POST /contests/:contestId/results/auto-set-awards` | POST | 自动设置奖项 |

### AI 3D 生成
| 接口 | 方法 | 说明 |
|------|------|------|
| `POST /ai-3d/tasks` | POST | 创建生成任务 |
| `GET /ai-3d/tasks/:id` | GET | 查询任务状态 |

---

## 十、总结

### 项目特点

1. **完整的多租户 SaaS 架构** - 支持平台、机构、评委等多角色
2. **丰富的竞赛管理功能** - 从活动创建到评审颁奖全流程覆盖
3. **灵活的 RBAC 权限系统** - 支持细粒度权限控制
4. **AI 能力集成** - 腾讯混元 3D 模型生成
5. **完善的初始化脚本** - 快速部署和配置

### 适用场景

- 📚 图书馆绘本创作比赛
- 🏫 学校各类竞赛活动
- 🎨 艺术创作比赛
- 📖 作文/阅读比赛
- 🤖 科技创新大赛

### 技术亮点

- NestJS 模块化架构
- Prisma ORM 类型安全
- JWT 无状态认证
- 事务处理保证数据一致性
- 软删除保留数据追溯

---

> 文档生成时间：2026-03-28
> 分析人：AI Assistant
