CREATE TABLE `sys_banner` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `image` varchar(255) DEFAULT NULL COMMENT '图片地址', `url` varchar(255) DEFAULT NULL COMMENT '跳转地址', `sort` int(1) DEFAULT '0' COMMENT '排序', `status` int(1) DEFAULT '1' COMMENT '状态 0=下架, 1=上架', `tenant_id` int(11) DEFAULT NULL COMMENT '租户ID', `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除', `creator` varchar(64) DEFAULT NULL COMMENT '创建者', `updater` varchar(64) DEFAULT NULL COMMENT '更新者', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_time` datetime DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='轮播图';1. 创建模块结构
使用 Nest CLI 快速生成 Banner 表模块:
命令行执行: nest g res banner
PS D:\Java\work\nodejs-demo\nest-admin> cd .\server\src\module\system\ PS D:\Java\work\nodejs-demo\nest-admin\server\src\module\system> nest g res banner ✔ What transport layer do you use? REST API ? Would you like to generate CRUD entry points? (Y/n) (按回车生成)按Enter回车
PS D:\Java\work\nodejs-demo\nest-admin> cd .\server\src\module\system\ PS D:\Java\work\nodejs-demo\nest-admin\server\src\module\system> nest g res banner ✔ What transport layer do you use? REST API ✔ Would you like to generate CRUD entry points? Yes CREATE banner/banner.controller.ts (959 bytes) CREATE banner/banner.controller.spec.ts (596 bytes) CREATE banner/banner.module.ts (264 bytes) CREATE banner/banner.service.ts (661 bytes) CREATE banner/banner.service.spec.ts (478 bytes) CREATE banner/dto/create-banner.dto.ts (33 bytes) CREATE banner/dto/update-banner.dto.ts (181 bytes) CREATE banner/entities/banner.entity.ts (24 bytes) UPDATE system.module.ts (965 bytes) PS D:\Java\work\nodejs-demo\nest-admin\server\src\module\system>选择配置:
Transport layer:REST API
Generate CRUD entry points:Yes
2. 生成的文件结构
banner/ ├── banner.controller.ts # 控制器 ├── banner.service.ts # 服务层 ├── banner.module.ts # 模块配置 ├── entities/ │ └── banner.entity.ts # 实体类 └── dto/ ├── create-banner.dto.ts # 创建 DTO └── update-banner.dto.ts # 更新 DTOspec是测试类, 可忽略
3. 配置数据库实体
修改banner.entity.ts,映射数据库表:
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; @Entity('sys_banner') export class Banner { @PrimaryGeneratedColumn() id: number; @Column({ length: 255, nullable: true, comment: '图片地址' }) image: string; @Column({ length: 255, nullable: true, comment: '跳转地址' }) url: string; @Column({ default: 0, comment: '排序' }) sort: number; @Column({ default: 1, comment: '状态 0=下架, 1=上架' }) status: number; @Column({ nullable: true, comment: '租户ID' }) tenant_id: number; @Column({ default: false, comment: '是否删除' }) deleted: boolean; @Column({ length: 64, nullable: true, comment: '创建者' }) creator: string; @Column({ length: 64, nullable: true, comment: '更新者' }) updater: string; @Column({ type: 'datetime', nullable: true, comment: '创建时间' }) create_time: Date; @Column({ type: 'datetime', nullable: true, comment: '更新时间' }) update_time: Date; }4. 配置 DTO 数据验证
create-banner.dto.ts:
import { IsString, IsOptional, IsInt, IsBoolean, IsUrl } from 'class-validator'; export class CreateBannerDto { @IsString() image: string; @IsOptional() @IsUrl() url?: string; @IsOptional() @IsInt() sort?: number; @IsOptional() @IsInt() status?: number; @IsOptional() @IsInt() tenant_id?: number; }update-banner.dto.ts:
已经继承CreateBannerDto
import { PartialType } from '@nestjs/mapped-types'; import { CreateBannerDto } from './create-banner.dto'; export class UpdateBannerDto extends PartialType(CreateBannerDto) {}5. 服务层逻辑
banner.service.ts核心方法:
import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { Banner } from './entities/banner.entity'; import { CreateBannerDto } from './dto/create-banner.dto'; import { UpdateBannerDto } from './dto/update-banner.dto'; @Injectable() export class BannerService { constructor( @InjectRepository(Banner) private bannerRepository: Repository<Banner>, ) {} create(createBannerDto: CreateBannerDto) { return this.bannerRepository.save(createBannerDto); } findAll() { return this.bannerRepository.find({ where: { deleted: false }, order: { sort: 'ASC' } }); } findOne(id: number) { return this.bannerRepository.findOneBy({ id, deleted: false }); } update(id: number, updateBannerDto: UpdateBannerDto) { return this.bannerRepository.update(id, { ...updateBannerDto, update_time: new Date() }); } remove(id: number) { // 软删除 return this.bannerRepository.update(id, { deleted: true, update_time: new Date() }); } }6. 控制器路由
banner.controller.ts:
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; import { BannerService } from './banner.service'; import { CreateBannerDto } from './dto/create-banner.dto'; import { UpdateBannerDto } from './dto/update-banner.dto'; @Controller('banner') export class BannerController { constructor(private readonly bannerService: BannerService) {} @Post() create(@Body() createBannerDto: CreateBannerDto) { return this.bannerService.create(createBannerDto); } @Get() findAll() { return this.bannerService.findAll(); } @Get(':id') findOne(@Param('id') id: string) { return this.bannerService.findOne(+id); } @Patch(':id') update(@Param('id') id: string, @Body() updateBannerDto: UpdateBannerDto) { return this.bannerService.update(+id, updateBannerDto); } @Delete(':id') remove(@Param('id') id: string) { return this.bannerService.remove(+id); } }7. 模块配置
banner.module.ts:
import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { BannerService } from './banner.service'; import { BannerController } from './banner.controller'; import { Banner } from './entities/banner.entity'; @Module({ imports: [TypeOrmModule.forFeature([Banner])], controllers: [BannerController], providers: [BannerService], }) export class BannerModule {}8. 自动注册到 SystemModule
Nest CLI 会自动更新system.module.ts:
import { Module } from '@nestjs/common'; import { BannerModule } from './banner/banner.module'; @Module({ imports: [BannerModule], // 自动添加 }) export class SystemModule {}9. 接口测试
生成的 REST API:
GET /banner # 获取所有轮播图 GET /banner/:id # 获取单个轮播图 POST /banner # 创建轮播图 PATCH /banner/:id # 更新轮播图 DELETE /banner/:id # 删除轮播图(软删除)总结
通过nest g res命令可以快速生成标准的 CRUD 模块,包含:
完整的 REST API 接口
TypeORM 实体映射
基本的 DTO 验证
模块化的代码结构
后续可根据业务需求添加:
权限控制(@Roles() 装饰器)
数据验证管道
日志记录
缓存机制
文件上传处理