你瞅啥呢

2025-11-29 NestJS菜单模块CRUD接口开发指南(deepseek)

在 NestJS 开发中,确实有一些可以遵循的"公式"或最佳实践模式。让我为你总结一套完整的 NestJS 接口开发公式:

🎯 NestJS 接口开发通用公式

1. 模块结构公式

src/modules/{模块名}/
├── {模块名}.controller.ts      # 控制器
├── {模块名}.service.ts         # 服务层  
├── {模块名}.module.ts          # 模块定义
├── dto/                        # 数据传输对象
│   ├── create-{模块名}.dto.ts
│   ├── update-{模块名}.dto.ts
│   └── query-{模块名}.dto.ts
├── entities/                   # 实体类
│   └── {模块名}.entity.ts
└── interfaces/                 # 接口定义(可选)
    └── {模块名}.interface.ts

2. 控制器开发公式

// 1. 导入依赖
import { 
  Controller, Get, Post, Put, Delete, Patch, 
  Body, Param, Query, UseGuards, UsePipes 
} from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from '@nestjs/swagger';

// 2. 定义控制器
@ApiTags('模块名')
@Controller('模块名')
@UseGuards(JwtAuthGuard, RolesGuard) // 守卫
@ApiBearerAuth('JWT-auth')
export class 模块名Controller {
  constructor(private readonly 模块名Service: 模块名Service) {}

  // 3. CRUD 方法模板
  @Post()
  @ApiOperation({ summary: '创建', description: '创建新记录' })
  async create(@Body() createDto: Create模块名Dto) {
    return this.模块名Service.create(createDto);
  }

  @Get()
  @ApiOperation({ summary: '获取列表', description: '获取记录列表' })
  async findAll(@Query() queryDto: Query模块名Dto) {
    return this.模块名Service.findAll(queryDto);
  }

  @Get(':id')
  @ApiOperation({ summary: '获取详情', description: '根据ID获取记录详情' })
  async findOne(@Param('id') id: number) {
    return this.模块名Service.findOne(id);
  }

  @Put(':id')
  @ApiOperation({ summary: '更新', description: '根据ID更新记录' })
  async update(@Param('id') id: number, @Body() updateDto: Update模块名Dto) {
    return this.模块名Service.update(id, updateDto);
  }

  @Delete(':id')
  @ApiOperation({ summary: '删除', description: '根据ID删除记录' })
  async remove(@Param('id') id: number) {
    return this.模块名Service.remove(id);
  }
}

3. 服务层开发公式

// 1. 导入依赖
import { Injectable, NotFoundException, ConflictException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Like, Between } from 'typeorm';

// 2. 定义服务
@Injectable()
export class 模块名Service {
  constructor(
    @InjectRepository(模块名Entity)
    private 模块名Repository: Repository<模块名Entity>,
  ) {}

  // 3. CRUD 方法实现模板
  async create(createDto: Create模块名Dto): Promise<模块名Entity> {
    // 验证唯一性
    const existing = await this.模块名Repository.findOne({ 
      where: { name: createDto.name } 
    });
    if (existing) throw new ConflictException('名称已存在');

    const entity = this.模块名Repository.create(createDto);
    return await this.模块名Repository.save(entity);
  }

  async findAll(query: Query模块名Dto): Promise<{ 
    items: 模块名Entity[]; 
    total: number; 
    page: number; 
    limit: number;
    totalPages: number;
  }> {
    const { page = 1, limit = 20, keyword, ...filters } = query;
    const skip = (page - 1) * limit;
    
    const where: any = {};
    if (keyword) where.name = Like(`%${keyword}%`);
    // 添加其他过滤条件...

    const [items, total] = await this.模块名Repository.findAndCount({
      where,
      order: { id: 'DESC' },
      skip,
      take: limit,
    });

    return { 
      items, 
      total, 
      page: Number(page), 
      limit: Number(limit), 
      totalPages: Math.ceil(total / limit) 
    };
  }

  async findOne(id: number): Promise<模块名Entity> {
    const entity = await this.模块名Repository.findOne({ where: { id } });
    if (!entity) throw new NotFoundException(`记录 ${id} 不存在`);
    return entity;
  }

  async update(id: number, updateDto: Update模块名Dto): Promise<模块名Entity> {
    const entity = await this.findOne(id);
    const updated = this.模块名Repository.merge(entity, updateDto);
    return await this.模块名Repository.save(updated);
  }

  async remove(id: number): Promise<void> {
    const entity = await this.findOne(id);
    await this.模块名Repository.remove(entity);
  }
}

4. DTO 开发公式

// Create DTO
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { 
  IsString, IsNotEmpty, IsOptional, IsNumber, 
  IsBoolean, IsEnum, MinLength, MaxLength 
} from 'class-validator';

export class Create模块名Dto {
  @ApiProperty({ description: '名称', example: '示例名称' })
  @IsString()
  @IsNotEmpty()
  @MaxLength(100)
  name: string;

  @ApiPropertyOptional({ description: '描述', example: '这是一个示例' })
  @IsString()
  @IsOptional()
  description?: string;

  @ApiProperty({ description: '状态', example: true })
  @IsBoolean()
  @IsOptional()
  enabled?: boolean;
}

// Update DTO
export class Update模块名Dto extends PartialType(Create模块名Dto) {}

// Query DTO
export class Query模块名Dto {
  @ApiPropertyOptional({ description: '页码', default: 1 })
  @IsNumber()
  @IsOptional()
  page?: number = 1;

  @ApiPropertyOptional({ description: '每页数量', default: 20 })
  @IsNumber()
  @IsOptional()
  limit?: number = 20;

  @ApiPropertyOptional({ description: '搜索关键词' })
  @IsString()
  @IsOptional()
  keyword?: string;
}

5. 实体类开发公式

import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';

@Entity('表名')
export class 模块名Entity {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({ length: 100 })
  name: string;

  @Column({ type: 'text', nullable: true })
  description: string;

  @Column({ type: 'boolean', default: true })
  enabled: boolean;

  @CreateDateColumn()
  createdAt: Date;

  @UpdateDateColumn()
  updatedAt: Date;
}

6. 模块定义公式

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { 模块名Controller } from './模块名.controller';
import { 模块名Service } from './模块名.service';
import { 模块名Entity } from './entities/模块名.entity';

@Module({
  imports: [TypeOrmModule.forFeature([模块名Entity])],
  controllers: [模块名Controller],
  providers: [模块名Service],
  exports: [模块名Service],
})
export class 模块名Module {}

🚀 快速生成模板

使用 Nest CLI

# 生成模块骨架
nest g resource 模块名

# 或分别生成
nest g controller 模块名
nest g service 模块名
nest g module 模块名

手动创建模板脚本

// generate-module.ts - 代码生成工具
function generateModule(moduleName: string) {
  const templates = {
    controller: `
import { Controller } from '@nestjs/common';
import { ${moduleName}Service } from './${moduleName.toLowerCase()}.service';

@Controller('${moduleName.toLowerCase()}')
export class ${moduleName}Controller {
  constructor(private readonly ${moduleName.toLowerCase()}Service: ${moduleName}Service) {}
}
    `,
    service: `
import { Injectable } from '@nestjs/common';

@Injectable()
export class ${moduleName}Service {}
    `
    // ... 其他模板
  };
  
  return templates;
}

📋 完整示例:用户模块

// user.controller.ts
@ApiTags('users')
@Controller('users')
@UseGuards(JwtAuthGuard, RolesGuard)
@ApiBearerAuth('JWT-auth')
export class UserController {
  constructor(private readonly userService: UserService) {}

  @Post()
  @Roles(UserRole.ADMIN)
  @ApiOperation({ summary: '创建用户' })
  async create(@Body() createUserDto: CreateUserDto) {
    return this.userService.create(createUserDto);
  }

  @Get()
  @ApiOperation({ summary: '获取用户列表' })
  async findAll(@Query() queryUserDto: QueryUserDto) {
    return this.userService.findAll(queryUserDto);
  }

  @Get(':id')
  @ApiOperation({ summary: '获取用户详情' })
  async findOne(@Param('id', ParseIntPipe) id: number) {
    return this.userService.findOne(id);
  }
}

🎯 开发流程公式

  1. 设计数据结构 → 实体类
  2. 定义数据格式 → DTO
  3. 实现业务逻辑 → Service
  4. 暴露API接口 → Controller
  5. 配置模块依赖 → Module
  6. 添加文档注释 → Swagger装饰器
  7. 设置权限控制 → Guards & Decorators

🔧 常用工具函数

// 通用响应格式
export interface ApiResponse<T> {
  data: T;
  code: number;
  message: string;
  success: boolean;
  timestamp: string;
}

// 分页响应格式
export interface PaginatedResponse<T> {
  items: T[];
  total: number;
  page: number;
  limit: number;
  totalPages: number;
}

// 通用服务方法
export class BaseService<T> {
  constructor(private repository: Repository<T>) {}

  async paginate(options: any): Promise<PaginatedResponse<T>> {
    // 通用分页逻辑
  }
}

记住这个公式,你就能快速开发出结构清晰、功能完整的 NestJS 接口!

posted @ 2025-11-29 17:12  叶乘风  阅读(11)  评论(0)    收藏  举报