# zero-admin-service **Repository Path**: zmmlet/zero-admin-service ## Basic Information - **Project Name**: zero-admin-service - **Description**: zero-admin-service 是一个后台管理后端服务,它基于Node、JWT、MySql、Nest 实现。包含了JWT token 认证和权限管理,基于Swagger UI 风格的接口文档,REST风格实现CURD接口,接口错误验证,路由装饰器,MySql操作等,为zero-admin后台管理模板提供接口服务支持 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 2 - **Created**: 2023-03-04 - **Last Updated**: 2025-05-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: TypeScript, Nestjs, Nodejs ## README ## 功能列表 - [x] 登录 - [x] 注册 - [x] 用户管理 - [x] 角色管理 - [x] 菜单管理 - [ ] 字典管理 - [ ] 文件上传 - [x] 定时任务 - [x] 邮箱推送 - [ ] Redis 集成 - [ ] 日志集成 - [ ] 消息队列 ## 参考文章 - https://pm2.fenxianglu.cn/docs/advanced/graceful-start-shutdown/ - https://juejin.cn/post/7080545204687765511#heading-12 ## 项目环境依赖 |环境|版本| |--|--| |Node.js|v14.21.1| |pnpm|v6.32.9| |MySQL|v5.7| ## 依赖安装 ```bash $ pnpm install ``` ## 运行应用程序 ```bash # development $ pnpm run start # watch mode $ pnpm run dev # production mode $ pnpm run start:prod ``` ## 测试 ```bash # unit tests $ pnpm run test # e2e tests $ pnpm run test:e2e # test coverage $ pnpm run test:cov ``` ## 传参方式 ```ts /** * @desc 带有单个路由的基本控制器 * */ // 使用@Controller装饰器来定义控制器 @ApiTags('测试接口') @Controller('app') export class AppController { constructor(private readonly appService: AppService) {} // @Get是请求方法的装饰器,对getHello方法进行修饰, 表示这个方法会被GET请求调用 // 1. 固定路径: // 可以匹配到 get请求,http://localhost:9030/app @Get() @ApiOperation({ summary: '请求地址:http://localhost:9030/app' }) getHello(): string { return this.appService.getHello(); } // 可以匹配到 post请求,http://localhost:9030/app/list @Post('list') @ApiOperation({ summary: '请求地址:http://localhost:9030/app/list' }) create(): string { return 'list'; } @Put('list/user') @ApiOperation({ summary: '请求地址:http://localhost:9030/app/list/user' }) updateUser() { return { userId: 1 }; } // 2.通配符路径(?+* 三种通配符 ) // 可以匹配到 get请求, http://localhost:9030/app/user_xxx @Get('user_*') @ApiOperation({ summary: '请求地址:http://localhost:9030/app/user_xxx' }) getUser() { return 'getUser'; } // 3.带参数路径 // 可以匹配到put请求,http://localhost:9030/app/list/xxxx @Put('list/:id') @ApiOperation({ summary: '请求地址:http://localhost:9030/app/list/xxxx' }) update() { return 'update'; } } ``` ## 新建数据库 > 数据库版本:**5.7** - 数据库名称:zero-admin-db - 根据实体自动创建数据库表 app.module.ts 文件第50行 ## 数据库连接 1. 项目根目录新建`.env`和`.env.prod`文件 2. src同级新建`config`文件夹,新建文件`.env.ts` 3. 安装依赖 `pnpm add @nestjs/typeorm typeorm mysql2 @nestjs/config` 4. 引入依赖 ```ts import { TypeOrmModule } from '@nestjs/typeorm'; import { ConfigService, ConfigModule } from '@nestjs/config'; ``` 5. 编写配置 ```ts // 设置数据库变量为全局 ConfigModule.forRoot({ isGlobal: true, // 设置为全局 envFilePath: [envConfig.path], }), // 使用 TypeORM 配置数据库 TypeOrmModule.forRootAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: async (configService: ConfigService) => ({ type: 'mysql', host: configService.get('DB_HOST', 'localhost'), // 主机,默认为localhost, port: configService.get('DB_PORT', 3306), // 端口号, username: configService.get('DB_USER', 'root'), // 用户名 password: configService.get('DB_PASSWORD', 'root'), // 密码 database: configService.get('DB_DATABASE'), //数据库名 entities: [ RolesEntity, UserEntity, PermissionEntity, UserRoleEntity, RolePermissionEntity, UploadEntity, ], // 数据表实体 timezone: '+08:00', //服务器上配置的时区 synchronize: true, //根据实体自动创建数据库表, 生产环境建议关闭 }), }), ``` ## CRUD编写 ## 接口过滤器 ```ts import { ArgumentsHost, Catch, ExceptionFilter, HttpException, } from '@nestjs/common'; import { Response } from 'express'; /** * @desc 接口过滤器 */ @Catch(HttpException) export class HttpExceptionFilter implements ExceptionFilter { catch(exception: HttpException, host: ArgumentsHost) { const ctx = host.switchToHttp(); // 获取请求上下文 const response = ctx.getResponse(); // 获取请求上下文中的 response 对象 const status = exception.getStatus(); // 获取异常状态 // 设置错误信息 const message = exception.message ? exception.message : `${status > 500 ? 'Service Error' : 'Client Error'}`; const errorResponse = { data: {}, message: message, code: -1, success: false, }; const exceptionResponse: any = exception.getResponse(); let validatorMessage = exceptionResponse; if (typeof validatorMessage === 'object') { validatorMessage = exceptionResponse.message[0]; } // 设置返回的状态码,请求头,发错误信息 response.status(status).json({ code: status, message: exceptionResponse || message, success: false, }); response.header('Content-Type', 'application/json; charset=utf-8'); response.send(errorResponse); } } ``` ## swagger 文档配置 1. 安装依赖 `pnpm add @nestjs/swagger swagger-ui-express -S` 2. 在 main.ts 文件中配置 ```ts import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; // 配置swagger文档 const swaggerConfig = new DocumentBuilder() .setTitle('管理后台') .setDescription('管理后台接口文档') .setVersion('v1.0') .addBearerAuth() .build(); const document = SwaggerModule.createDocument(app, swaggerConfig); SwaggerModule.setup('docs', app, document); // 设置端口 await app.listen(9030); ``` ## 数据验证 `pnpm add class-validator class-transformer -S` ## 注册密码加密 `pnpm install bcryptjs` ## 用户登录 ### local 本地认证 pnpm install @nestjs/passport passport passport-local pnpm install @types/passport @types/passport-local ### jwt鉴权 `pnpm install @nestjs/jwt` ### 实现token认证 `pnpm install passport-jwt @types/passport-jwt` ## 微信公众平台测试申请 https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login ## chalk.js(node终端样式库) 1. 安装依赖 `pnpm install chalk@4.1.2` 2. 使用 ```ts Chalk.green(`Zero-Admin-Service 服务启动成功 `) ``` ## web 安全,防常见漏洞 ```ts import helmet from 'helmet'; app.use(helmet()); ``` ## 定时任务 ```bash pnpm add @nestjs/schedule pnpm add @types/cron ``` tasks.service.ts ```ts import { Injectable, Logger } from '@nestjs/common'; import { Cron, Interval, Timeout } from '@nestjs/schedule'; @Injectable() export class TasksService { private readonly logger = new Logger(TasksService.name); @Cron('45 * * * * *') handleCron() { this.logger.debug('该方法将在45秒标记处每分钟运行一次'); } @Interval(10000) handleInterval() { this.logger.debug('2'); } @Timeout(5000) handleTimeout() { this.logger.debug('3'); } @Interval(10000) sendEmail() { this.logger.debug('4'); // this.emailService.sendEmail(); } } ``` tasks.module.ts ```ts import { Module } from '@nestjs/common'; import { TasksService } from './tasks.service'; import { ScheduleModule } from '@nestjs/schedule'; @Module({ providers: [TasksService], imports: [ScheduleModule.forRoot()], }) export class TasksModule {} ``` app.module.ts ```ts import { ScheduleModule } from '@nestjs/schedule'; import { TasksModule } from './modules/tasks/tasks.module'; @Module({ // imports:导入模块的列表,如果需要使用其他模块的服务,需要通过这里导入 imports: [ // ... // 定时任务 ScheduleModule.forRoot(), TasksModule, ], // ... }) export class AppModule {} ``` ## 邮箱服务 1. 邮箱模块 `pnpm install @nestjs-modules/mailer nodemailer` 2. 模板引擎 `pnpm install pug`