# re-sims **Repository Path**: bingyu123/re-sims ## Basic Information - **Project Name**: re-sims - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2022-05-16 - **Last Updated**: 2025-07-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: sims ## README # 后台流程 ## 技术选型 ### **选用nest开发原因** 1. 完善的生态 2. 有IOC支持,更接近后台语言规范 3. 支持 Typeorm,[实体类规范(opens new window)](https://typeorm.io/#/entities) [中文文档](https://typeorm.bootcss.com/connection) 4. 所有的node后台框架中 nestjs 是github星最高的 5. 对于流程控制更简洁 6. 命令式生成代码的支持(类似angular)比如 `nest g controller modules/user` 会自动在modules文件夹生成user.controller.ts这个文件 7. 采用MVC架构的解耦分离式开发 8. 完美支持 Typescript 9. 面向 AOP 编程 10. 高并发,异步非阻塞 IO 11. Node.js 版的 spring 12. 构建微服务应用 13. [官方文档(opens new window)](https://docs.nestjs.cn/) ## 使用流程 ### 项目位置 ![image-20211111005241844](https://cdn.jsdelivr.net/gh/IceRain-mvc/cdn/img/image-20211111005241844.png) ### 目录结构说明 > ```bash > server_exam > |--dist > |--node_modules > |--src > |--|--filter #过滤器 > |--|--interceptors #拦截器 > |--|--logger #处理日志 > |--|--middleware #中间件 > |--|--modules #核心模块 存放接口逻辑 > |--|--utils #存放utils > |--|--app.controller.spec.ts #模块单元测试 > |--|--app.controller.ts #核心文件 请求的入口 > |--|--app.module.ts #请求导出的模块 > |--|--app.service.ts #核心文件对逻辑的处理 > |--|--main.ts #入口文件 > |--test #单元测试 > |--.eslintrc.js #eslint配置文件 > |--.gitignore #git提交忽略文件 > |--.prettierrc #格式化文件 > |--nest-cli.json #nest配置文件 > |--package.json > |--package-lock.json > |--README.md > |--tsconfig.build.json > |--tsconfig.json #ts配置文件 > ``` ### 启动 > ```bash > // 开发模式 > npm run start:dev 这个命令 > ``` ### 编写接口流程 新建controller、service、entity、module文件 > ```bash > nest g controller modules/login > nest g service modules/login > nest g module modules/login > ``` 添加到根module中(如果是命令创建则会自动添加) 项目已经集成了orm规范 创建实体类 > ```bash > > ``` #### controller编写规范 以下包含了一个`controller`完整的请求装饰器规范 > ```ts > import { Controller, Get, Query, Post, Body, Put, Param, Delete } from '@nestjs/common'; > import { CreateCatDto, UpdateCatDto, ListAllEntities } from './dto'; > > @Controller('user') > export class AuthController { > constructor(private readonly authService: AuthService) {} > //设置swagger请求体参数 > @ApiBody({ description: '请求体', type: Question }) > @ApiHeader({ > name: 'token', > required: true, > description: '请求的时候 携带token', > }) > @ApiResponse({ status: HttpStatus.CREATED, description: '请求成功' }) > @ApiResponse({ status: HttpStatus.UNAUTHORIZED, description: 'token失效' }) > @ApiResponse({ > status: HttpStatus.FORBIDDEN, > description: '此角色无权限操作', > }) > @Post() > login(@Body() createCatDto: CreateCatDto) { > return 'This action adds a new cat'; > } > > @ApiQuery({ > name: 'count', > required: false, > description: '返回的条数', > }) > @Get() > findAll(@Query() query: ListAllEntities) { > return `This action returns all cats (limit: ${query.limit} items)`; > } > > @ApiParam({ > name: 'id', > required: false, > description: '对应动态路由的详情数据的请求', > }) > @Get(':id') > findOne(@Param('id') id: string) { > return `This action returns a #${id} cat`; > } > > @ApiParam({ > name: 'id', > required: false, > description: '对应动态路由的详情数据的请求', > }) > @Put(':id') > update(@Param('id') id: string, @Body() updateCatDto: UpdateCatDto) { > return `This action updates a #${id} cat`; > } > > @ApiParam({ > name: 'id', > required: false, > description: '对应动态路由的详情数据的请求', > }) > @Delete(':id') > remove(@Param('id') id: string) { > return `This action removes a #${id} cat`; > } > } > ``` #### service编写规范 > ```ts > import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; > import { User } from './user.entity'; > import { InjectRepository } from '@nestjs/typeorm'; > import { Repository } from 'typeorm'; > import { ConfigService } from '@nestjs/config'; > > @Injectable() > export class UserService { > constructor( > @InjectRepository(User) > private readonly userRepository: Repository, > private readonly configService: ConfigService, > ) { > const name = this.configService.get('ADMIN_USER', 'admin'); > const password = this.configService.get('ADMIN_PASSWD', 'admin'); > this.createUser({ name, password, role: 'admin' }) > .then(() => { > console.log(); > console.log( > `管理员账户创建成功,用户名:${name},密码:${password},请及时登录系统修改默认密码`, > ); > console.log(); > }) > .catch(() => { > console.log(); > console.log( > `管理员账户已经存在,用户名:${name},密码:${password},请及时登录系统修改默认密码`, > ); > console.log(); > }); > } > > async login(user: Partial) { > const { name, password } = user; > const existUser = await this.userRepository.findOne({ where: { name } }); > > if ( > !existUser || > !(await User.comparePassword(password, existUser.password)) > ) { > throw new HttpException( > '用户名或密码错误', > // tslint:disable-next-line: trailing-comma > HttpStatus.BAD_REQUEST, > ); > } > > if (existUser.status === 'locked') { > throw new HttpException( > '用户已锁定,无法登录', > // tslint:disable-next-line: trailing-comma > HttpStatus.BAD_REQUEST, > ); > } > > return existUser; > } > > /** > * 创建用户 > * @param user > */ > async createUser(user: Partial): Promise { > const { name, password } = user; > > if (!name || !password) { > throw new HttpException('请输入用户名和密码', HttpStatus.BAD_REQUEST); > } > > const existUser = await this.userRepository.findOne({ where: { name } }); > > if (existUser) { > throw new HttpException('用户已存在', HttpStatus.BAD_REQUEST); > } > > const newUser = await this.userRepository.create(user); > await this.userRepository.save(newUser); > return newUser; > } > } > ``` #### entity编写规范 > ```ts > import { > Column, > Entity, > PrimaryGeneratedColumn, > CreateDateColumn, > UpdateDateColumn, > BeforeInsert, > } from 'typeorm'; > import { ApiProperty } from '@nestjs/swagger'; > import { Exclude } from 'class-transformer'; > import * as bcrypt from 'bcryptjs'; > > @Entity() > export class User { > /** > * 检测密码是否一致 > * @param password0 加密前密码 > * @param password1 加密后密码 > */ > static async comparePassword(password0, password1) { > return bcrypt.compareSync(password0, password1); > } > > static encryptPassword(password) { > return bcrypt.hashSync(password, 10); > } > > @PrimaryGeneratedColumn('uuid') > id: number; > > @ApiProperty({ type: 'string', example: '用户名' }) > @Column({ length: 500 }) > name: string; > > @ApiProperty({ type: 'string', example: '密码' }) > @Exclude() > @Column({ length: 500 }) > password: string; > > @Column({ length: 500, default: null }) > avatar: string; // 头像 > > @Column({ length: 500, default: null }) > email: string; // 邮箱 > > @Column('simple-enum', { enum: ['admin', 'teacher'], default: 'teacher' }) > role: string; // 用户角色 > > @Column('simple-enum', { enum: ['locked', 'active'], default: 'active' }) > status: string; // 用户状态 > > @CreateDateColumn({ > type: 'datetime', > comment: '创建时间', > name: 'create_at', > }) > createAt: Date; > > @UpdateDateColumn({ > type: 'datetime', > comment: '更新时间', > name: 'update_at', > }) > updateAt: Date; > > /** > * 插入数据前,对密码进行加密 > */ > @BeforeInsert() > encrypt() { > this.password = bcrypt.hashSync(this.password, 10); > } > } > ``` #### module单个模块编写 > ```ts > import { Module } from '@nestjs/common'; > import { ExamController } from './exam.controller'; > import { ExamService } from './exam.service'; > import { ExamEntity } from './exam.entity'; > import { TypeOrmModule } from '@nestjs/typeorm'; > > @Module({ > imports: [TypeOrmModule.forFeature([ExamEntity])], > exports: [TypeOrmModule], > controllers: [ExamController], > providers: [ExamService], > }) > export class ExamModule {} > ```