Vue+NestJS项目实操(图书管理后台)

一、项目搭建

前端基于vben进行二次开发

在Github下载vben框架,搜索vben即可

下载地址:https://github.com/vbenjs/vue-vben-admin

下载完成后,进行安装依赖,使用命令:

// 下载依赖
pnpm install

// 运行项目
pnpm run dev

前端框架分析:

1、es module特性支持

2、

        

后端框架使用NestJS

 使用NestJS搭建后端框架

// 安装脚手架
npm i -g @nestjs/cli

// 新建项目
nest new 项目名

 选择npm工具,搭建完成后可以直接运行,执行命令

npm run start:dev

// 在源码的文件夹【src】->【main.ts】中可以看到监听3000端口。

 NestJS后端知识回顾:

// 控制器(XXX.controller.ts)
/*
    控制器负责处理传入的请求和向客户端返回响应

    控制器的目的是接收应用的特定请求,路由机制控制那个控制器接收那些请求。通常,每个控制器有多个路由,不同的路由可以执行不同的操作。

    为了创建一个基本的控制器,我们使用类和装饰器。装饰器将类和所需的元数据相关联,并使Nest能够创建路由映射(将请求绑定到相应的控制器)
*/

// Providers
/*
    Providers是Nest的一个基本概念,许多基本的Nest类可能被视为provider-service,repository,factory,helper等等。他们可以通过constructor注入依赖关系,这意味着对象可以彼此创建各种关系,并且“连接”对象实例的功能在很大程度上可以委托给Nest运行时系统。Providers只是一个用@Injectable()装饰器修饰的类。

    注入的对象,作为一个服务注入到controller
    使用@Injectable()修饰,表示可以被注入到controller之中
*/

//异常过滤器
/*
    内置的异常过滤器负责处理整个应用程序中所有抛出的异常。当捕获到未处理的异常时,最终用户将收到友好的响应。 
*/



// Restful API规则
/*

    Get:获取数据
    Post:插入数据
    Put:更新数据
    Delete:删除数据

    常用Get、Post

    Param:restful API参数
    Query:url 参数(Get 参数)
    Body:Post 参数

*/

二、业务分析

后端业务模块设计与拆分

// 使用脚手架创建模块
nest g module user
nest g controller user

// 具体使用的模块主要有user、book、auth三个模块

新建数据库,两种使用数据库的方法:

1、使用小皮面板进行开发,可以参考另一篇文章:

PhpStudy下载安装使用学习_php小皮下载-CSDN博客

2、下载MySQL数据库,MySQL官网:

MySQL :: MySQL Downloads

数据库连接

使用MySQL数据库,连接使用TypeORM工具

// 安装TypeORM
npm install --save @nestjs/typeorm typeorm mysql2

// 在全局的module中引入 TypeOrmModule ,即在【app.module.ts】中引入


具体代码如下:

// app.module.ts

import { Module } from '@nestjs/common';
// 引入TypeORM模块
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserModule } from './module/user/user.module';
import { AuthModule } from './module/auth/auth.module';
import { BookModule } from './module/book/book.module';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: '127.0.0.1',
      port: 3306,
      username: 'root',
      password: '123456',
      database: 'book_nest',
    }),
    UserModule,
    AuthModule,
    BookModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

运行项目,不报错,说明项目已经运行成功,连接数据库成功

数据库实体创建(entity)

在module/user文件夹创建【user.entity.ts】,数据库与表要一一对应

// user.entity.ts

// 进行数据库定义

import { Entity, Column, Unique, PrimaryGeneratedColumn } from 'typeorm';

// 数据映射关系绑定
@Entity('admin_user')
export class User {
  // 整型自增
  @PrimaryGeneratedColumn()
  id: number;

  // 属性
  @Column()
  // 唯一性
  @Unique(['username'])
  username: string;

  @Column()
  password: string;

  @Column()
  role: string;

  @Column()
  nickname: string;

  @Column()
  active: number;

  @Column()
  avatar: string;
}

在【user.module.ts】中引入TypeORM,进行实体关联

import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
// 引入User实体
import { User } from './user.entity';
// 引入UserService
import { UserService } from './user.service';

@Module({
  // 要引用的实体
  imports: [TypeOrmModule.forFeature([User])],
  controllers: [UserController],
  // 服务提供者
  providers: [UserService],
})
export class UserModule {}

新建module/user/user.service.ts,写服务代码

// 引入注入器
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { User } from './user.entity';
import { Repository } from 'typeorm';

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
  ) {}

  // 查找
  findOne(id: number): Promise<User> {
    // 可以执行sql语句
    // return this.userRepository.query(`SELECT * FROM user WHERE id = ${id}`);
    return this.userRepository.findOneBy({ id });
  }

  // 新增
  // 删除
  // 更新
}

以user功能为例,写查找、新增、删除功能逻辑

// user.service.ts

// 引入注入器
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { User } from './user.entity';
import { DeleteResult, Repository } from 'typeorm';
import { CreateUserDto } from './create-user.dto';

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
  ) {}

  // 查找
  findOne(id: number): Promise<User> {
    // 可以执行sql语句
    // return this.userRepository.query(`SELECT * FROM user WHERE id = ${id}`);
    return this.userRepository.findOneBy({ id });
  }

  // 查询所有
  findAll(): Promise<User[]> {
    return this.userRepository.find();
  }

  // 新增
  create(createUserDto: CreateUserDto): Promise<User> {
    const user = new User();
    user.username = createUserDto.username;
    user.password = createUserDto.password;
    user.role = createUserDto.role;
    user.avatar = createUserDto.avatar;
    user.active = 1;

    return this.userRepository.save(user);
  }

  // 删除
  remove(id: number): Promise<DeleteResult> {
    return this.userRepository['delete'](id);
  }
}
// user.controller.ts

import {
  Body,
  Controller,
  Get,
  Param,
  ParseIntPipe,
  Post,
  Delete,
} from '@nestjs/common';
import { UserService } from './user.service';

@Controller('user')
export class UserController {
  constructor(private readonly userService: UserService) {}
  @Get('id')
  getUser(@Param('id', ParseIntPipe) id: number) {
    return this.userService.findOne(id);
  }

  @Get()
  getAllUser() {
    return this.userService.findAll();
  }

  // 新增
  @Post()
  createUser(@Body() body) {
    return this.userService.create(body);
  }

  // 删除
  @Delete('id')
  remove(@Param('id', ParseIntPipe) id: number) {
    return this.userService.remove(id);
  }
}
// user.entity.ts

// 进行数据库定义

import { Entity, Column, Unique, PrimaryGeneratedColumn } from 'typeorm';

// 数据映射关系绑定
@Entity('admin_user')
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  @Unique(['username'])
  username: string;

  @Column()
  password: string;

  @Column()
  role: string;

  @Column()
  nickname: string;

  @Column()
  active: number;

  @Column()
  avatar: string;
}

写新增业务逻辑时,新建create-user.dto.ts,新建类模型 

// create-user.dto.ts

export class CreateUserDto {
  username: string;
  password: string;
  role: string;
  nickname: string;
  avatar: string;
}
// user.module.ts

import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
// 引入User实体
import { User } from './user.entity';
// 引入UserService
import { UserService } from './user.service';

@Module({
  // 要引用的实体
  imports: [TypeOrmModule.forFeature([User])],
  controllers: [UserController],
  // 服务提供者
  providers: [UserService],
})
export class UserModule {}

6-1

 

开发时的一些配置问题

解决代码报错

每次执行 git commit 时,lint-staged 会自动运行 ESLint 的 --fix 操作来修复暂存区中的文件

// 安装 husky 和 lint-staged
npm install husky lint-staged --save-dev

// 在 package.json 文件中添加 lint-staged 配置
{
  "lint-staged": {
    "*.js": "eslint --fix",
    "*.ts": "eslint --fix"
  }
}

// 设置 husky 钩子
{
  "husky": {
    "pre-commit": "lint-staged"
  }
}

在 VS Code 中设置 ESLint 以在保存文件时自动修复代码的步骤

// 安装ESLint
npm install eslint --save-dev

// 配置 package.json 
{
  "scripts": {
    "lint": "eslint . --fix",
    "prettier": "prettier --write ."
  }
}

// 在 VS Code 的 settings.json 文件中添加以下配置,以启用保存时的自动格式化
{
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  },
  "eslint.autoFixOnSave": true,
  "eslint.alwaysShowStatus": true,
  "eslint.options": {
    "cache": false
  }
}

//如果安装了 Prettier 或其他格式化工具,你可以在 settings.json 中配置 VS Code,使其在保存时运行
{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/887409.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

开源的云平台有哪些?

开源云平台为用户提供了构建、管理和运行云基础设施及应用的能力&#xff0c;同时允许社区参与开发和改进。以下是一些知名的开源云平台&#xff1a; 1. OpenStack 简介&#xff1a;OpenStack&#xff1a;一个广泛使用的开源云平台&#xff0c;它由多个组件组成&#xff0c;提…

HTML+CSS - 表单交互(一)

1. 前言 ​​​​​​​ Web 表单是用于和用户交互的强大工具——其常用于收集用户数据和控制用户界面。 web 表单是用户和 web 站点或应用程序之间交互的主要内容之一。它们允许用户输入数据&#xff0c;大多数情况下会将数据发送到 web 服务器进行处理和存储 2. form标签 …

Redis篇(Redis原理 - RESP协议)

目录 一、简介 二、Redis通信协议 基于Socket自定义Redis的客户端 三、Redis内存回收 1. 过期key处理 1.1. 惰性删除 1.2. 周期删除 1.3. 知识小结 2. 内存淘汰策略 一、简介 Redis是一个CS架构的软件&#xff0c;通信一般分两步&#xff08;不包括pipeline和PubSub&a…

AI不可尽信

看到某项目有类似这样的一段代码 leaves : make([]int, 10) leaves leaves[:0]没理解这样的连续两行,有何作用? 初始化一个长度和容量都为10的切片,接着把切片长度设置为0 即如下demo: (在线地址) package mainimport "fmt"func main() {leaves : make([]int, 1…

M3u8视频由手机拷贝到电脑之后,通过potplayer播放报错找不到文件地址怎么解决?

该文章前面三节主要介绍M3u8视频是什么&#xff0c;视频播放错误(找不到地址)的解决方法在后面 M3U8是一种多媒体播放列表文件格式&#xff0c;主要用于流媒体播放。 一、文件格式特点 1. 文本文件&#xff1a;M3U8是一个采用 UTF-8 编码的文本文件&#xff0c;这意味着它可…

【STM32开发之寄存器版】(三)-详解NVIC中断

一、前言 STM32F103ZET6具备强大的中断控制能力&#xff0c;其嵌套向量中断控制器(NVIC)和处理器核的接口紧密相连&#xff0c;可以实现低延迟的中断处理和高效地处理晚到的中断。NVIC主要具备以下特性&#xff1a; 68个可屏蔽中断通道(不包含16个Cortex™-M3的中断线)&#xf…

经典文献阅读之--WiROS(用于机器人的WiFi感知工具箱)

0. 简介 近期的许多研究探索了使用基于WiFi的感知技术来改善SLAM&#xff08;同时定位与地图构建&#xff09;、机器人操控或探索。此外&#xff0c;WiFi的广泛可用性使其成为最具优势的射频信号。但WiFi传感器缺乏一个准确、易处理、多功能的工具箱&#xff0c;这限制了它们与…

VUE2常见问题以及解决方案汇总(不断更新中)

解决vue项目中 el-table 的 row-click 事件与行内点击事件冲突&#xff0c;点击事件不生效&#xff08;表格行点击事件和行内元素点击事件冲突&#xff09;需要阻止事件冒泡 问题描述 1.点击列的编辑按钮&#xff0c;会触发按钮本身事件&#xff0c;同时会触发行点击事件 2.点…

SaaS 应用如何助长网络犯罪

过去十年&#xff0c;软件即服务 (SaaS)的采用呈爆炸式增长&#xff0c;彻底改变了我们的工作方式。 从电子邮件平台到通信和协作应用程序&#xff0c;再到文件存储和共享服务&#xff0c;这些工具有望为我们的日常工作生活带来更大的灵活性和效率&#xff0c;尤其是在当今的远…

Linux环境基础开发工具使用(2)

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 Linux环境基础开发工具使用(2) 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1. Li…

VS开发 - 静态编译和动态编译的基础实践与混用

目录 1. 基础概念 2. 直观感受一下静态编译和动态编译的体积与依赖项目 3. VS运行时库包含哪些主要文件&#xff08;从VS2015起&#xff09; 4. 动态库和静态库混用的情况 5. 感谢清单 1. 基础概念 所谓的运行时库&#xff08;Runtime Library&#xff09;就是WINDOWS系统…

防反接电路设计

方案1 串联二极管&#xff0c; 优点&#xff1a;成本低、设计简单 缺点&#xff1a;损耗大&#xff0c;P ui 方案2 串联自恢复保险丝 当电源反接的时候&#xff0c;D4导通&#xff0c;F2超过跳闸带你留&#xff0c;就会断开&#xff0c;从而保护了后级电路 方案3 H桥电路…

解决DHCP服务异常导致设备无法获取IP地址的方法

DHCP在网络环境中会自动为网络中的设备分配IP地址和其他关键网络参数&#xff0c;可以简化网络配置过程。但是&#xff0c;如果DHCP服务出现异常时&#xff0c;设备可能无法正常获取IP地址&#xff0c;会影响到网络通信。 本文讲述一些办法可以有效解决DHCP服务异常导致设备无法…

No.2 笔记 | 网络安全攻防:PC、CS工具与移动应用分析

引言 在当今数字化时代,网络安全已成为每个人都应该关注的重要话题。本文将总结一次关于网络安全攻防技术的学习内容,涵盖PC端和移动端的恶意程序利用,以及强大的渗透测试工具Cobalt Strike的使用。通过学习这些内容,我们不仅能够了解攻击者的手法,更能提高自身的安全意识和防…

Java编码方式:Base64编码与解码

1、Base64 算法介绍 Base64 是一种基于 64 个可打印字符来表示二进制数据的表示方法。它主要用于在不支持二进制数据的场合&#xff08;如电子邮件、URL、文件系统名等&#xff09;传输二进制数据。严格来说 Base64 并不是一种加密/解密算法&#xff0c;而是一种编码方式。Bas…

基于Springboot+Android的的电子书阅读器系统的设计与实现(含源码+数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 该系统…

二分查找一>山脉数组的峰顶索引

1.题目&#xff1a; 2.解析&#xff1a; 代码&#xff1a; public int peakIndexInMountainArray(int[] arr) {int left 1, right arr.length-2;while(left < right) {int mid left (right-left1) / 2;if(arr[mid] > arr[mid-1]) left mid;else right mid-1;}ret…

openpnp - 视觉原点的位置要离设备的软限制点远一点

文章目录 openpnp - 视觉原点的位置要离设备的软限制点远一点笔记备注END openpnp - 视觉原点的位置要离设备的软限制点远一点 笔记 最开始的视觉原点&#xff0c;是在设备X 0, Y 0的附近位置&#xff0c;粘了一块20x20x20的铝块&#xff0c;铝块上面贴着用黑塑料皮打印的1…

esp8266 at指令链接wifi时一直connect disconnest

那是你的连接wifi的名字密码有误或者热点有问题&#xff0c;看看热点是不是把设备拉入黑名单或者设置为5G或者连了校园网或者设置了最多链接设备

IntelliJ IDEA 2024.2 新特性概览

文章目录 1、重点特性:1.1 改进的 Spring Data JPA 支持1.2 改进的 cron 表达式支持1.3 使用 GraalJS 作为 HTTP 客户端的执行引擎1.4 更快的编码时间1.5 K2 模式下的 Kotlin 性能和稳定性改进 2、用户体验2.1 改进的全行代码补全2.2 新 UI 成为所有用户的默认界面2.3 Search E…