图书管理系统练习项目源码-前后端分离-使用node.js来做后端开发

前端学习了这么久了,node.js 也有了一定的了解,知道使用node也可以来开发后端,今天给大家分享 使用node 来做后端,vue来写前端,做一个简单的图书管理系统。我们在刚开始学习编程的时候,需要自己写大量的项目来练习自己的编程技能,在开发中你会遇到各种各样的编程问题,这个时候 就可以根据自己学习到的编程知识来解决开发中遇到的问题,这样我们就会慢慢的掌握一门编程语言。
今天分享的就是我最近写的一个图书管理系统。
使用技术:
Node.js:后端使用Node.js平台,版本要求16.20以上,基于其高性能和跨平台特性,能够轻松支持大规模的API请求。

Express框架:简洁高效的后端框架,帮助快速搭建API服务。

MySQL 5.7:作为关系型数据库管理系统,MySQL用于存储用户和图书信息,并支持CRUD操作。

Vue2:前端使用Vue2框架,配合Element UI组件库,提供响应式页面和现代化用户界面。

Element UI:帮助实现简洁且功能丰富的UI设计,极大提高了前端开发效率。

系统功能
用户管理:可以新增、编辑、删除用户信息。

图书管理:添加、修改、删除图书,并能够查看图书列表。

借阅管理:记录图书借阅、归还情况。

数据展示:通过前端页面展示系统中的图书、用户信息,提供了简洁、易用的界面。
部分页面效果展示:
在这里插入图片描述
在这里插入图片描述
目录结构:
在这里插入图片描述
部分前端代码:

<template><div class="app-container"><!-- 搜索和操作栏 --><div class="filter-container"><el-inputv-model="listQuery.name"placeholder="请输入图书名称"style="width: 200px; margin-right: 10px"class="filter-item"@keyup.enter.native="handleFilter"/><el-button class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">搜索</el-button><el-button type="primary" @click="handleCreate" style="margin-left: 10px">新增图书</el-button></div><!-- 数据表格 --><el-tablev-loading="listLoading":data="list"element-loading-text="加载中..."borderfithighlight-current-rowstyle="margin-top: 20px;"><el-table-column label="图书编号" prop="book_no" align="center" /><el-table-column label="图书名称" prop="name" align="center" /><el-table-column label="分类" prop="category_name" align="center" /><el-table-column label="作者" prop="author" align="center" /><el-table-column label="使用状态" align="center"><template slot-scope="{row}"><el-tag :type="row.use_status === 0 ? 'info' : row.use_status === 1 ? 'success' : 'warning'">{{ row.use_status === 0 ? '在书架' : row.use_status === 1 ? '已买' : '已借出' }}</el-tag></template></el-table-column><el-table-column label="是否二手" align="center"><template slot-scope="{row}"><el-tag :type="row.is_second_hand === 1 ? 'warning' : 'info'">{{ row.is_second_hand === 1 ? '是' : '否' }}</el-tag></template></el-table-column><el-table-column label="状态" align="center"><template slot-scope="{row}"><el-tag :type="row.status === 1 ? 'success' : 'danger'"  style="cursor: pointer">{{ row.status === 1 ? '正常' : '维护' }}</el-tag></template></el-table-column><el-table-column label="备注" prop="remark" align="center" show-overflow-tooltip /><el-table-column label="创建时间" prop="created_at" align="center" /><el-table-column label="操作" align="center" width="160" fixed="right"><template slot-scope="{row}"><el-button type="primary" size="mini" @click="handleUpdate(row)">编辑</el-button><el-button type="danger" size="mini" @click="handleDelete(row)">删除</el-button></template></el-table-column></el-table><!-- 新增/编辑对话框 --><el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="600px"><el-formref="dataForm":model="temp":rules="rules"label-position="left"label-width="100px"style="margin-left: 50px; margin-right: 50px"><el-form-item label="图书编号" prop="book_no"><el-input v-model="temp.book_no" placeholder="请输入图书编号" /></el-form-item><el-form-item label="图书名称" prop="name"><el-input v-model="temp.name" placeholder="请输入图书名称" /></el-form-item><el-form-item label="图书分类" prop="category_id"><el-select v-model="temp.category_id" placeholder="请选择图书分类" style="width: 100%"><el-optionv-for="item in categories":key="item.id":label="item.name":value="item.id"/></el-select></el-form-item><el-form-item label="作者" prop="author"><el-input v-model="temp.author" placeholder="请输入作者" /></el-form-item><el-form-item label="出版日期" prop="publish_date"><el-date-pickerv-model="temp.publish_date"type="datetime"placeholder="请选择出版日期"style="width: 100%"/></el-form-item><el-form-item label="定价" prop="price"><el-input-numberv-model="temp.price":precision="2":step="0.1":min="0"style="width: 100%"/></el-form-item><el-form-item label="状态" prop="status"><el-select v-model="temp.status" placeholder="请选择状态" style="width: 100%"><el-option label="正常" :value="1" /><el-option label="维护" :value="0" /></el-select></el-form-item><el-form-item label="使用状态" prop="use_status"><el-select v-model="temp.use_status" placeholder="请选择使用状态" style="width: 100%"><el-option label="在书架" :value="0" /><el-option label="已买" :value="1" /><el-option label="已借出" :value="2" /></el-select></el-form-item><el-form-item label="是否二手" prop="is_second_hand"><el-select v-model="temp.is_second_hand" placeholder="请选择是否二手" style="width: 100%"><el-option label="否" :value="0" /><el-option label="是" :value="1" /></el-select></el-form-item><el-form-item label="备注" prop="remark"><el-inputv-model="temp.remark"type="textarea"placeholder="请输入备注信息":rows="3"/></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="dialogVisible = false">取消</el-button><el-button type="primary" @click="submitForm">确定</el-button></div></el-dialog></div>
</template><script>
import {getBookList,createBook,updateBook,deleteBook,updateBookStatus
} from '@/api/book'
import { getCategoryList } from '@/api/category'export default {name: 'BookList',data() {return {list: [], // 图书列表数据categories: [], // 分类列表数据listLoading: false, // 列表加载状态listQuery: { // 查询参数name: '' // 图书名称搜索关键词},dialogVisible: false, // 对话框显示状态dialogTitle: '', // 对话框标题temp: { // 临时数据对象id: undefined,book_no: '',name: '',category_id: undefined,author: '',publish_date: undefined,price: 0,status: 1,remark: '',use_status: 0,is_second_hand: 0},rules: { // 表单验证规则book_no: [{ required: true, message: '请输入图书编号', trigger: 'blur' }],name: [{ required: true, message: '请输入图书名称', trigger: 'blur' }],category_id: [{ required: true, message: '请选择图书分类', trigger: 'change' }],author: [{ required: true, message: '请输入作者', trigger: 'blur' }],publish_date: [{ required: true, message: '请选择出版日期', trigger: 'change' }],price: [{ required: true, message: '请输入定价', trigger: 'blur' }]}}},created() {this.getList()this.getCategories()},methods: {// 获取图书列表async getList() {try {this.listLoading = trueconst { data } = await getBookList(this.listQuery)this.list = data} catch (error) {console.error('获取图书列表失败:', error)} finally {this.listLoading = false}},// 处理搜索handleFilter() {this.getList()},// 获取分类列表async getCategories() {try {const { data } = await getCategoryList()this.categories = data} catch (error) {console.error('获取分类列表失败:', error)}},// 重置表单resetTemp() {this.temp = {id: undefined,book_no: '',name: '',category_id: undefined,author: '',publish_date: undefined,price: 0,status: 1,remark: '',use_status: 0,is_second_hand: 0}},// 打开新增对话框handleCreate() {this.resetTemp()this.dialogTitle = '新增图书'this.dialogVisible = truethis.$nextTick(() => {this.$refs['dataForm'].clearValidate()})},// 打开编辑对话框handleUpdate(row) {this.temp = Object.assign({}, row)this.dialogTitle = '编辑图书'this.dialogVisible = truethis.$nextTick(() => {this.$refs['dataForm'].clearValidate()})},// 提交表单submitForm() {this.$refs['dataForm'].validate(async (valid) => {if (valid) {try {if (this.temp.id) {// 更新await updateBook(this.temp.id, this.temp)this.$message.success('更新成功')} else {// 新增await createBook(this.temp)this.$message.success('创建成功')}this.dialogVisible = falsethis.getList()} catch (error) {console.error('保存图书失败:', error)}}})},// 删除图书handleDelete(row) {this.$confirm('确认删除该图书吗?', '提示', {type: 'warning'}).then(async () => {try {await deleteBook(row.id)this.$message.success('删除成功')this.getList()} catch (error) {console.error('删除图书失败:', error)}}).catch(() => {})},// 更新状态async handleStatusChange(row) {try {await updateBookStatus(row.id, row.status)this.$message.success('状态更新成功')} catch (error) {console.error('更新状态失败:', error)// 恢复原状态row.status = row.status === 1 ? 0 : 1}}}
}
</script><style lang="scss" scoped>
.filter-container {padding-bottom: 10px;.filter-item {margin-right: 10px;}
}
</style>

部分后端代码:

const BookModel = require('../models/book.model')
const Response = require('../utils/response')
const asyncHandler = require('../utils/asyncHandler')class BookController {/*** 获取图书列表*/getList = asyncHandler(async (req, res) => {const { name } = req.queryconst books = await BookModel.getAll({ name })res.json(Response.success(books))})/*** 获取图书详情*/getDetail = asyncHandler(async (req, res) => {const { id } = req.paramsconst book = await BookModel.findById(id)if (!book) {return res.json(Response.error('图书不存在'))}res.json(Response.success(book))})/*** 创建图书*/create = asyncHandler(async (req, res) => {const { book_no, name, category_id, author, publish_date, price, status, remark, use_status, is_second_hand } = req.body// 验证必填字段if (!book_no) {return res.json(Response.error('图书编号不能为空'))}if (!name) {return res.json(Response.error('图书名称不能为空'))}if (!category_id) {return res.json(Response.error('图书分类不能为空'))}if (!author) {return res.json(Response.error('作者不能为空'))}if (!publish_date) {return res.json(Response.error('出版日期不能为空'))}if (!price) {return res.json(Response.error('定价不能为空'))}const id = await BookModel.create({ book_no, name, category_id, author, publish_date, price, status, remark,use_status,is_second_hand})const book = await BookModel.findById(id)res.json(Response.success(book, '创建成功'))})/*** 更新图书*/update = asyncHandler(async (req, res) => {const { id } = req.paramsconst { book_no, name, category_id, author, publish_date, price, status, remark, use_status, is_second_hand } = req.bodyconst book = await BookModel.update(id, { book_no, name, category_id, author, publish_date, price, status, remark,use_status,is_second_hand})res.json(Response.success(book, '更新成功'))})/*** 删除图书*/delete = asyncHandler(async (req, res) => {const { id } = req.paramsawait BookModel.delete(id)res.json(Response.success(null, '删除成功'))})/*** 更新图书状态*/updateStatus = asyncHandler(async (req, res) => {const { id } = req.paramsconst { status } = req.bodyif (status === undefined) {return res.json(Response.error('状态不能为空'))}const book = await BookModel.updateStatus(id, status)res.json(Response.success(book, '状态更新成功'))})
}module.exports = new BookController()

代码量还是很多的,毕竟是一个管理系统,由于文章字数,这里就不一一复制粘贴代码了,如果你需要完整的项目源码,可以去下方网站了解。
https://wwwoop.com/home/Index/projectInfo?goodsId=97&typeParam=1&subKey=0

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【甲方安全视角】企业建设下的安全运营

文章目录 一、安全运营的概念与起源二、安全运营的职责与定位三、安全运营工程师的核心能力要求四、安全运营的典型场景与应对技巧1. 明确责任划分,避免“医生做保姆”2. 推动机制:自下而上 vs. 自上而下3. 宣传与内部影响力建设五、安全运营的战略意义六、为何需要安全原因在…

03认证原理自定义认证添加认证验证码

目录 大纲 一、自定义资源权限规则 二、自定义登录界面 三、自定义登录成功处理 四、显示登录失败信息 五、自定义登录失败处理 六、注销登录 七、登录用户数据获取 1. SecurityContextHolder 2. SecurityContextHolderStrategy 3. 代码中获取认证之后用户数据 4. 多…

IPLOOK 2025上半年足迹回顾:连接全球,步履不停

2025年上半年&#xff0c;IPLOOK积极活跃于全球通信舞台&#xff0c;足迹横跨亚洲、欧洲、非洲与北美洲&#xff0c;我们围绕5G核心网、私有网络、云化架构等方向&#xff0c;向来自不同地区的客户与合作伙伴展示了领先的端到端解决方案&#xff0c;深入了解各地市场需求与技术…

【Kafka】docker 中配置带 Kerberos 认证的 Kafka 环境(全过程)

1. 准备 docker 下载镜像 docker pull centos/systemd&#xff0c;该镜像是基于 centos7 增加了 systemd 的功能&#xff0c;可以更方便启动后台服务 启动镜像 使用 systemd 功能需要权限&#xff0c;如果是模拟 gitlab services 就不要使用 systemd 的方式启动 如果不使用 s…

用Python构建一个可扩展的多网盘聚合管理工具 (以阿里云盘为例)

摘要 本文旨在从开发者视角&#xff0c;探讨并实践如何构建一个命令行界面的、支持多网盘聚合管理的工具。我们将以阿里云盘为例&#xff0c;深入解析其API认证与核心操作&#xff0c;并用Python从零开始实现文件列表、重命名、分享等功能。更重要的是&#xff0c;本文将重点讨…

筑牢网络安全屏障

在数字化浪潮席卷全球的今天&#xff0c;网络空间已成为继陆、海、空、天之后的 “第五疆域”&#xff0c;深刻影响着国家政治、经济、军事等各个领域。“没有网络安全就没有国家安全”&#xff0c;这句论断精准道出了网络安全与国家安全之间密不可分的关系。​ 网络安全关乎国…

计算机网络(一)层

一、分层 分层的意义&#xff1a;简化复杂性、提高灵活性、促进标准化 &#xff08;1&#xff09;法律上国际标准——OSI体系结构 &#xff08;2&#xff09;事实上的网络标准——TCP/IP体系结构 TCP&#xff1a;运输层的协议 IP&#xff1a;网际层的一个协议 网络接口层&…

STM32 rs485实现中断DMA模式收发不定长数据

在STM32F103上使用TD301D485H模块通过USB转485/422串口线与电脑通信 TXD (TD301D485H) -> PA2 (STM32F103)RXD (TD301D485H) -> PA3 (STM32F103)CON (TD301D485H) -> PA1 (STM32F103) 由于485是半双工通信&#xff0c;需要在发送和接收时控制方向引脚&#xff08;CO…

DDL-8-小结

DDL 小结 DDL 小结 DDL 小结DDL - 数据库操作DDL - 表操作 DDL - 数据库操作 查看当前有哪些数据库 SHOW DATABASES;新建数据库 CREATE DATABASE 数据库名;使用数据库 USE 数据库名;查询当前数据库 SELECT DATABASE();删除数据库 DROP DATABASE 数据库名;DDL - 表操作 查看当前…

Redis 安装使用教程

一、Redis 简介 Redis 是一个开源&#xff08;BSD 许可&#xff09;、内存数据结构存储系统&#xff0c;可以用作数据库、缓存和消息中间件。支持字符串、哈希、列表、集合、有序集合等数据类型&#xff0c;广泛应用于分布式缓存、排行榜、实时数据分析等场景。 二、下载安装…

Go语言测试与调试:单元测试与基准测试

以下是《Go语言实战指南》中关于 测试与调试&#xff1a;单元测试与基准测试 的详细内容&#xff0c;涵盖测试编写、运行、覆盖率分析与性能测试&#xff0c;适用于实际项目开发与性能优化阶段。 一、Go 的测试体系概览 Go 提供原生的测试工具包 testing&#xff0c;无需第三方…

数字FIR-I型滤波器设计(窗函数法)

目录 一、实验目的 二、实验原理 2.1 概念辨析 2.2 代码实现逻辑与工具函数 三、实验内容 3.1 设计带通滤波器&#xff08;电平组合法&#xff0c;&#xff08;理想宽带低通-理想窄带低通&#xff09;x窗函数&#xff09; 3.2 高通滤波器&#xff08;…

RHCSA认证题目练习一(配置网络设置)

一. 题目 配置网络设置 解题过程&#xff1a; 注意&#xff1a;不可以在xshell中完成&#xff0c;否则会直接断联 这里用图形化解题&#xff0c;更加简单防止命令记错 1. 打开图形化视图 命令&#xff1a;nmtui 按回车确认 按回车确认 2.首先把IPv4配置 <自动> 改成 …

STL简介+string模拟实现

STL简介string模拟实现 1. 什么是STL2. STL的版本3. STL的六大组件4.STL的缺陷5. string5.1 C语言中的字符串5.2 1个OJ题 6.标准库中的string类6.1 string类(了解)6.2 string类的常用接口说明1.string类对象的常见构造函数2.析构函数(~string())3.赋值函数 (operator) 6.3 stri…

golang实现一个mysql中随机获取cookies的API

之前用FASTAPI写了一个随机cookies请求的接口,现在尝试用golang实现同样的效果 1.编写go代码 package mainimport ("database/sql""encoding/json""fmt"_ "github.com/go-sql-driver/mysql""log""net/http"&quo…

[Vue2组件]三角形角标

[Vue2组件]三角形角标 <template><div class"ys-subscript" :style"svgStyle"><svg width"200" height"200" viewBox"0 0 200 200" xmlns"http://www.w3.org/2000/svg"><!-- 三角形背景 - 右…

洛谷刷题4

B4354 [GESP202506 一级] 假期阅读 题目传送门 B4354 难度&#xff1a;入门 很简单的题&#xff0c;如果小A看的页数≤这本书的页数&#xff0c;输出他看的页数 否则&#xff0c;输出这本书的页数 AC代码&#xff1a; #include <iostream> using namespace std; in…

【基于Echarts的地图可视化】

<!DOCTYPE html> <html> <head><meta charset"utf-8"><title>中国牛只分布可视化</title><script src"https://cdn.jsdelivr.net/npm/echarts5.4.3/dist/echarts.min.js"></script><script src"h…

系统架构设计师备考之架构设计基础

1.计算机系统基础知识 1.1.计算机系统概述 计算机系统的定义与组成 计算机系统是指用于数据管理的计算机硬件、软件及网络组成的系统。 计算机系统可划分为硬件和软件两部分。硬件由机械、电子元器件、磁介质和光介质等物理实体构成&#xff1b; 软件是一系列按照特定顺序组织…

针对华为云服务器使用率过大

从这两张监控图可以看出&#xff0c;服务器在大约上午 10:30 前后经历了一次明显的负载变化&#xff1a; 1. 图表解读 CPU 使用率 从凌晨到上午约 10:00 前&#xff0c;CPU 基本处于 0–2% 的闲置状态。10:00–14:00 之间&#xff0c;CPU 利用率逐步攀升&#xff0c;多次冲击 3…