@TOC
springboot591图书大厦图书管理系统的设计与实现--论文
研究背景
近年来,由于计算机技术和互联网技术的快速发展,使得所有企事业单位内部都是数字化、信息化、无纸化的发展趋势,随着趋势的发展,各种决策系统、辅助系统也应运而生,其中图书大厦图书管理系统就是其中的重要组成部分。
图书大厦图书管理是工作中不可或缺的一部分,然而多年以来工作者大都习惯使用传统方法,即人工来完成图书大厦图书管理,但是这种方法存在着工作效率低以及保密性差的问题,同时还会生成大量的文本和数据,在检索数据时极大不便。随着科技发展进步,我们已进入了信息化社会,仅仅依靠传统的表格管理方式已不能适应时代的要求。因此使用计算机来进行接手传统方式的图书大厦图书管理已经势在必行。
通过计算机技术来实现的图书大厦图书管理系统拥有对信息的快速检索、保存了大量的图书大厦图书管理信息、信息系统保存的稳定性高和维护成本低等优点,对图书大厦图书管理的工作效率也能提高。如今,传统的人工管理方法、文件和图表打印等信息传输方法已经不能满足当下的发展需求,计算机科学与互联网技术的蓬勃发展,颠覆了人们的生活以及思维方式。图书大厦图书管理系统的出现,利用信息技术将图书大厦图书管理融于办公平台中,成为提高管理水平的有利手段,将会成为未来图书大厦图书管理的新模式。
1.2 课题研究意义
在当下,办公自动化以一种迅速并不可阻挡的速度在慢慢遍布到社会的每一个角落中,而图书大厦图书管理系统正是办公自动化的一个小小分支,解决了传统图书大厦图书管理中繁杂且重复的操作,提高了工作的效率。
图书大厦图书管理系统对于管理人员进行管理来说是非常重要的,应该做到让管理人员进行快捷的信息查询以及对信息的处理功能。然而,以往并没有使用电子化管理来进行图书大厦图书管理工作的意识,还是使用传统的人工管理方法。如今,伴随着计算机科学的不断发展,互联网科技的日渐成熟,计算机所带来的种种优势已经逐渐为人们所认识,它已经应用在社会中的各个领域中并且越来越重要,利用计算机将图书大厦图书管理信息进行电子化、系统化的管理能将图书大厦图书管理的效率提上一个台阶。所以,开发一套图书大厦图书管理系统,将信息进行电子化、系统化的管理,代替了传统的人工管理方式,提升了工作效率。
无纸化办公,节省了时间,减少了纸张的浪费同时节约了成本。
加快了信息传输的过程,使图书大厦图书管理更规范和科学。
利用计算机处理速度快、信息存储量大的特点,将管理工作信息化,可以积累和管理大量的数据。
对数据进行有效并且集中的管理,实现了用户信息的共享,使管理工作可以从传统的人工管理中解放出来,提升了工作的效率,使其有更多的时间去完成更多的工作,来提高自身的业务素质。
1.3 课题研究内容
本系统结合现今主流管理系统的功能模块以及设计方式进行分析,使用Java语言和Springboot框架进行开发设计,具体研究内容如下:
- 管理员主要对首页,个人中心,用户管理,图书分类管理,图书信息管理,图书借阅管理,图书续借管理,图书归还管理,反馈类型管理,需求反馈管理,归还入库管理,系统管理等功能进行管理。
- 用户主要对首页,个人中心,图书借阅管理,图书信息管理,图书归还管理,需求反馈管理等功能进行管理。
2 系统开发技术
图书大厦图书管理系统采用B/S(Browser/Server)架构和MVC模型进行设计开发。在B/S架构下,用户在浏览器端进行使用,主要工作通过服务器端进行实现,用户通过网站进行访问大大节约了成本。本系统使用Java等语言同时运用了Springboot框架进行开发,使用MySQL进行数据存储。
2.1 Java技术
Java是一种面向对象的静态式编程语言。Java编程语言具有多线程和对象定向的特点。其特点是根据方案的属性将方案分为几个不同的模块,这些模块是封闭的和多样化的,在申请过程中具有很强的独立性。Java语言在计算机软件开发过程中的运用可以达到交互操作的目的,通过各种形式的交换,可以有效地处理所需的数据,从而确保计算机软件开发的可控性和可见性。开发Java语言时,保留了网络接口,Java保留的缺省网络接口可以与web应用程序编程所依赖的类别库相匹配。为了使Java开发的应用程序更加稳定和强健,Java会自动收集程序中的垃圾,并处理程序中存在的异常。Java语言是日常开发过程中广泛使用的通用基本语言。其中Java语言课程库、句子、语法规则和关键字经常用于计算机软件的开发和编程。
面向对象编程是Java语言最显着的特点。它具有原始接口和补充接口以及继承,不仅可以实现相同类型的单个继承,而且还支持接口之间的多个继承,从而实现类、接口和接口之间以及类和接口之间的有效通信。Java的面向对象特性主要包括三个方面:继承、多态性和封装。封装是Java的核心,可以封装所有数据操作。多态性是指由面向对象行为派生的相关行为。继承作为特殊编程模式有两种类型:父类和子类,这两种类型的属性具有相同的功能和特性。对于父类的属性特性,子类可以实现继承和优化。
2.2 Springboot框架
Spring框架是Java平台上的一种开源应用框架,提供具有控制反转特性的容器。尽管Spring框架自身对编程模型没有限制,但其在Java应用中的频繁使用让它备受青睐,以至于后来让它作为EJB(EnterpriseJavaBeans)模型的补充,甚至是替补。Spring框架为开发提供了一系列的解决方案,比如利用控制反转的核心特性,并通过依赖注入实现控制反转来实现管理对象生命周期容器化,利用面向切面编程进行声明式的事务管理,整合多种持久化技术管理数据访问,提供大量优秀的Web框架方便开发等等。Spring框架具有控制反转(IOC)特性,IOC旨在方便项目维护和测试,它提供了一种通过Java的反射机制对Java对象进行统一的配置和管理的方法。Spring框架利用容器管理对象的生命周期,容器可以通过扫描XML文件或类上特定Java注解来配置对象,开发者可以通过依赖查找或依赖注入来获得对象。Spring框架具有面向切面编程(AOP)框架,SpringAOP框架基于代理模式,同时运行时可配置;AOP框架主要针对模块之间的交叉关注点进行模块化。Spring框架的AOP框架仅提供基本的AOP特性,虽无法与AspectJ框架相比,但通过与AspectJ的集成,也可以满足基本需求。
2.3 MySQL数据库
MySql做为瑞典公司MySql AB开发的中小型开源数据库智能管理系统,具备配备低、低成本、运作速度更快的优势。与此同时,因为社区版的开源系统性,变成了许多网址减少开发成本费的最佳选择。被甲骨文回收后,MySQL也发布了商业版。另外Mysql具有以下特性:
(1)使用C和C++编写,并使用了多种编译器进行测试,保证源代码的可移植性。
(2)为C、C++、Eiffel、Java、Perl、PHP、Python、Ruby和Tcl等多种编程语言提供了API。
(3)采用多线程并行的方法提高了CPU的利用率。
(4)改善算法,有效地提高查询速度。
2.4 B/S结构
B/S结构(Browser/Server,浏览器/服务器模式),是WEB兴起后的一种网络结构模式,WEB浏览器是客户端最主要的应用软件。这种模式统一了客户端,将系统功能实现的核心部分集中到服务器上,简化了系统的开发、维护和使用。客户机上只要安装一个浏览器,如Chrome、Safari、Microsoft Edge、Netscape Navigator或Internet Explorer,服务器安装SQL Server、Oracle、MYSQL等数据库。浏览器通过Web Server同数据库进行数据交互。
2.5 Tomcat服务器
Tomcat服务器属于轻量级应用服务器,在访问用户数量不是很大的中小型应用中经常被使用。Tomcat服务器主要由三个核心组件Web容器、servlet容器、JSP容器组成。其中,Web容器主要用于完成Web服务器的功能,servlet容器主要用于处理servlet代码,JSP容器主要用于将JSP动态网页翻译成servlet代码。Tomcat作为Web服务器和APP容器,其核心功能主要包括负责接受和反馈外部请求的连接器Connector和负责处理请求的容器Container。二者相辅相成,共同构成了基本的Web服务。Tomcat支持管理多个服务。Tomcat因其技术先进、性能也较为稳定,最重要的是因为其价格免费,故而收到了大量Java爱好者的偏爱,成为比较流行的Web应用服务器。
3 系统需求分析
需求分析在系统开发中有着十分重要的作用。软件项目凭借软件工程的思想和步骤可以大大的提高开发效率,缩短软件开发周期,保证了软件项目的质量。需求分析作为软件工程方法中的一步是至关重要的[6]。软件需求工程是一门分析并记录软件需求的学科。需求分析简单的来说就是用户需要什么,系统需要什么,对此进行问题的列举,等级的排列,需要缜密的思分析和大量的调研[7]。
2.1 可行性分析
根据图书大厦图书管理系统的功能,通过对经济可行性、技术可行性和法律可行性分析进行全面的分析,提供准确的可行性依据。以下是本系统的可行性分析:
- 经济可行性
就是分析在现有经济情况下能否完成本图书大厦图书管理系统的开发。下面对本系统开发、运行、维护的相关费用评估,以及投入到实际运用中完成图书大厦图书管理可能费用进行估算。网络资源丰富,本图书大厦图书管理系统只需使用任选一开源服务器即可,此方面无需投入费用。开发阶段,由于本图书大厦图书管理系统不属于大型系统,常规的电脑就可完成开发,不用购置相关硬件设备。软件方面,本图书大厦图书管理系统只需使用网上免费下载的软件即可完成开发,这些软件在使用时简单易懂,无需培训,因此在开发方面也无需投入费用。由于本图书大厦图书管理系统不属于大型系统,运行时候电费可以忽略不记。图书大厦图书管理系统作为自己毕设,由本人开发即可完成,无需人力费用。综上,整个系统开发花费很少,所以本图书大厦图书管理系统在经济上可行。
- 技术可行性
本系统的开发使用java作为系统开发的开发语言,开发工具选择 Eclipse,而 B/S架构决定了本系统的兼容性和多用户可操作性,此外选择MySql作为数据库不仅提高了数据安全性更保障了数据的可操作性。
- 法律可行性分析
法律可行性分析,即分析本校图书大厦图书管理系统是否与各类法律相悖。本校图书大厦图书管理系统使用市面开源免费软件开发,且作为个人毕设,无商用,均为本人自主开发,并且页面设计合理,发布的信息要求符合常规。整个系统无抵触法律法规的问题。因此在法律上,本校图书大厦图书管理系统可行。
3.2 功能需求分析
图书大厦图书管理系统综合网络空间开发设计要求。目的是将图书大厦图书管理通过网络平台将传统管理方式转换为在网上管理,完成图书大厦图书管理的方便快捷、安全性高障,目标明确。图书大厦图书管理系统可以将功能划分为管理员的使用功能和用户使用的功能。
(1)管理员的功能是最高的,可以对系统所在功能进行查看,修改和删除,包括用户功能。管理员用例如下:
图3-1管理员用例图
(2)用户关键功能包含个人中心,图书借阅管理,图书信息管理,图书归还管理,需求反馈管理等进行详细操作。用户用例如下:
图3-2 用户用例图
3.3 系统流程分析
3.3.1系统开发流程图:
图3-3 系统开发流程图
3.3.2管理员模块总体流程图:
图3-4 管理员模块总体流程图
3.3.3图书信息管理流程图:
图3-5 图书信息管理流程图
4 系统设计
4.1 功能模块设计
图书大厦图书管理系统按照权限的类型进行划分,分为管理员和用户共两个模块。系统实现首页,个人中心,用户管理,图书分类管理,图书信息管理,图书借阅管理,图书续借管理,图书归还管理,反馈类型管理,需求反馈管理,归还入库管理,系统管理等功能进行操作,增强了使用者的操作体验。管理员模块主要针对整个系统的管理进行设计,提高了管理的效率和标准。系统的总体模块设计如下图所示:
图4-1 系统总体模块设计
4.2 系统数据库设计
4.2.1 数据库系统
本系统采用MySQL来进行数据库的管理。MySQL数据库具有体积小、速度快、成本低等优点。具备同时处理数千万条记录,实现大型数据库的高并发读写和高效读写需求[9]。
4.2.2 数据库概念设计
概念模型用于对信息世界建模,并与指定的数据库管理系统分离。它有助于将真实世界的事物抽象为适合于数据库管理系统的数据库模型。人们倾向于将现实世界抽象为信息世界,再把信息世界变成机器世界。也就是说,将现实世界的目标抽象成独立于专用计算机软件和专用数据库管理系统的信息结构的数据模型,然后将物理模型转化为适合电子计算机的数据库管理系统。事实上,数据模型是从真实世界到机器世界的中间层。
信息世界的基本要素包括实体和关联。现实存在且彼此可区别的事物称为实体。实体可以是实际的人、事或物,还可以是抽象化的概念或联络。以下是对部分主要的关键实体如下:
图书归还实体属性如图4-2所示。
图4-2图书归还实体属性图
大厦公告实体属性如图4-3所示。
图4-3大厦公告实体属性图
归还入库实体属性如图4-4所示。
图4-4归还入库实体属性图
用户实体属性如图4-5所示。
图4-5用户实体属性图
需求反馈实体属性如图4-6所示。
图4-6需求反馈实体属性图
4.2.3 数据表设计
本设计根据数据表管理系统的具体流程进行管理,方便用户对数据的添加、删除、修改和查询等操作。
4.2.4 数据表的建立
系统采用Navicat Premium对数据库进行操作,数据库管理操作简单,数据处理能力强。数据表建立如下:
表4-1:关于我们
字段名称 | 类型 | 长度 | 字段说明 | 主键 | 默认值 |
---|---|---|---|---|---|
id | bigint | 主键 | 主键 | ||
addtime | timestamp | 创建时间 | CURRENT_TIMESTAMP | ||
title | varchar | 200 | 标题 | ||
subtitle | varchar | 200 | 副标题 | ||
content | longtext | 4294967295 | 内容 | ||
picture1 | longtext | 4294967295 | 图片1 | ||
picture2 | longtext | 4294967295 | 图片2 | ||
picture3 | longtext | 4294967295 | 图片3 |
表4-2:图书归还
字段名称 | 类型 | 长度 | 字段说明 | 主键 | 默认值 |
---|---|---|---|---|---|
id | bigint | 主键 | 主键 | ||
addtime | timestamp | 创建时间 | CURRENT_TIMESTAMP | ||
jieyuebianhao | varchar | 200 | 借阅编号 | ||
tushubianhao | varchar | 200 | 图书编号 | ||
tushumingcheng | varchar | 200 | 图书名称 | ||
shuliang | int | 数量 | |||
yonghuzhanghao | varchar | 200 | 用户账号 | ||
yonghuxingming | varchar | 200 | 用户姓名 | ||
guihaishijian | datetime | 归还时间 | |||
guihaibeizhu | varchar | 200 | 归还备注 | ||
sfsh | varchar | 200 | 是否审核 | 待审核 | |
shhf | longtext | 4294967295 | 审核回复 |
表4-3:图书分类
字段名称 | 类型 | 长度 | 字段说明 | 主键 | 默认值 |
---|---|---|---|---|---|
id | bigint | 主键 | 主键 | ||
addtime | timestamp | 创建时间 | CURRENT_TIMESTAMP | ||
tushufenlei | varchar | 200 | 图书分类 |
表4-4:token表
字段名称 | 类型 | 长度 | 字段说明 | 主键 | 默认值 |
---|---|---|---|---|---|
id | bigint | 主键 | 主键 | ||
userid | bigint | 用户id | |||
username | varchar | 100 | 用户名 | ||
tablename | varchar | 100 | 表名 | ||
role | varchar | 100 | 角色 | ||
token | varchar | 200 | 密码 | ||
addtime | timestamp | 新增时间 | CURRENT_TIMESTAMP | ||
expiratedtime | timestamp | 过期时间 | CURRENT_TIMESTAMP |
表4-5:收藏表
字段名称 | 类型 | 长度 | 字段说明 | 主键 | 默认值 |
---|---|---|---|---|---|
id | bigint | 主键 | 主键 | ||
addtime | timestamp | 创建时间 | CURRENT_TIMESTAMP | ||
userid | bigint | 用户id | |||
refid | bigint | 商品id | |||
tablename | varchar | 200 | 表名 | ||
name | varchar | 200 | 名称 | ||
picture | longtext | 4294967295 | 图片 | ||
type | varchar | 200 | 类型(1:收藏,21:赞,22:踩,31:竞拍参与,41:关注) | 1 | |
inteltype | varchar | 200 | 推荐类型 | ||
remark | varchar | 200 | 备注 |
表4-6:大厦公告
字段名称 | 类型 | 长度 | 字段说明 | 主键 | 默认值 |
---|---|---|---|---|---|
id | bigint | 主键 | 主键 | ||
addtime | timestamp | 创建时间 | CURRENT_TIMESTAMP | ||
title | varchar | 200 | 标题 | ||
introduction | longtext | 4294967295 | 简介 | ||
picture | longtext | 4294967295 | 图片 | ||
content | longtext | 4294967295 | 内容 |
表4-7:归还入库
字段名称 | 类型 | 长度 | 字段说明 | 主键 | 默认值 |
---|---|---|---|---|---|
id | bigint | 主键 | 主键 | ||
addtime | timestamp | 创建时间 | CURRENT_TIMESTAMP | ||
tushubianhao | varchar | 200 | 图书编号 | ||
tushumingcheng | varchar | 200 | 图书名称 | ||
tushufenlei | varchar | 200 | 图书分类 | ||
rukushijian | datetime | 入库时间 | |||
jieyuebianhao | varchar | 200 | 借阅编号 | ||
yonghuzhanghao | varchar | 200 | 用户账号 | ||
yonghuxingming | varchar | 200 | 用户姓名 | ||
shuliang | int | 归还数量 |
表4-8:用户
字段名称 | 类型 | 长度 | 字段说明 | 主键 | 默认值 |
---|---|---|---|---|---|
id | bigint | 主键 | 主键 | ||
addtime | timestamp | 创建时间 | CURRENT_TIMESTAMP | ||
yonghuzhanghao | varchar | 200 | 用户账号 | ||
mima | varchar | 200 | 密码 | ||
yonghuxingming | varchar | 200 | 用户姓名 | ||
xingbie | varchar | 200 | 性别 | ||
nianling | varchar | 200 | 年龄 | ||
touxiang | longtext | 4294967295 | 头像 | ||
yonghushouji | varchar | 200 | 用户手机 |
表4-9:反馈类型
字段名称 | 类型 | 长度 | 字段说明 | 主键 | 默认值 |
---|---|---|---|---|---|
id | bigint | 主键 | 主键 | ||
addtime | timestamp | 创建时间 | CURRENT_TIMESTAMP | ||
fankuileixing | varchar | 200 | 反馈类型 |
表4-10:图书续借
字段名称 | 类型 | 长度 | 字段说明 | 主键 | 默认值 |
---|---|---|---|---|---|
id | bigint | 主键 | 主键 | ||
addtime | timestamp | 创建时间 | CURRENT_TIMESTAMP | ||
jieyuebianhao | varchar | 200 | 借阅编号 | ||
tushubianhao | varchar | 200 | 图书编号 | ||
tushumingcheng | varchar | 200 | 图书名称 | ||
shuliang | int | 数量 | |||
yonghuzhanghao | varchar | 200 | 用户账号 | ||
yonghuxingming | varchar | 200 | 用户姓名 | ||
xujieshijian | date | 续借时间 | |||
xujietianshu | int | 续借天数 | |||
xujieshiyou | longtext | 4294967295 | 续借事由 | ||
crossuserid | bigint | 跨表用户id | |||
crossrefid | bigint | 跨表主键id | |||
sfsh | varchar | 200 | 是否审核 | 待审核 | |
shhf | longtext | 4294967295 | 审核回复 |
表4-11:需求反馈
字段名称 | 类型 | 长度 | 字段说明 | 主键 | 默认值 |
---|---|---|---|---|---|
id | bigint | 主键 | 主键 | ||
addtime | timestamp | 创建时间 | CURRENT_TIMESTAMP | ||
yonghuzhanghao | varchar | 200 | 用户账号 | ||
yonghuxingming | varchar | 200 | 用户姓名 | ||
fankuileixing | varchar | 200 | 反馈类型 | ||
fankuibiaoti | varchar | 200 | 反馈标题 | ||
fankuishijian | datetime | 反馈时间 | |||
fankuineirong | longtext | 4294967295 | 反馈内容 | ||
pingfen | int | 评分 | |||
shhf | longtext | 4294967295 | 回复内容 |
表4-12:图书信息评论表
字段名称 | 类型 | 长度 | 字段说明 | 主键 | 默认值 |
---|---|---|---|---|---|
id | bigint | 主键 | 主键 | ||
addtime | timestamp | 创建时间 | CURRENT_TIMESTAMP | ||
refid | bigint | 关联表id | |||
userid | bigint | 用户id | |||
avatarurl | longtext | 4294967295 | 头像 | ||
nickname | varchar | 200 | 用户名 | ||
content | longtext | 4294967295 | 评论内容 | ||
reply | longtext | 4294967295 | 回复内容 |
表4-13:用户表
字段名称 | 类型 | 长度 | 字段说明 | 主键 | 默认值 |
---|---|---|---|---|---|
id | bigint | 主键 | 主键 | ||
username | varchar | 100 | 用户名 | ||
password | varchar | 100 | 密码 | ||
role | varchar | 100 | 角色 | 管理员 | |
addtime | timestamp | 新增时间 | CURRENT_TIMESTAMP |
表4-14:图书信息
字段名称 | 类型 | 长度 | 字段说明 | 主键 | 默认值 |
---|---|---|---|---|---|
id | bigint | 主键 | 主键 | ||
addtime | timestamp | 创建时间 | CURRENT_TIMESTAMP | ||
tushubianhao | varchar | 200 | 图书编号 | ||
tushumingcheng | varchar | 200 | 图书名称 | ||
huojiaweizhi | varchar | 200 | 货架位置 | ||
tushufenlei | varchar | 200 | 图书分类 | ||
shuliang | int | 数量 | |||
chubanshe | varchar | 200 | 出版社 | ||
tushuzuozhe | varchar | 200 | 图书作者 | ||
tushugaiyao | longtext | 4294967295 | 图书概要 | ||
tushufengmian | longtext | 4294967295 | 图书封面 |
表4-15:配置文件
字段名称 | 类型 | 长度 | 字段说明 | 主键 | 默认值 |
---|---|---|---|---|---|
id | bigint | 主键 | 主键 | ||
name | varchar | 100 | 配置参数名称 | ||
value | varchar | 100 | 配置参数值 |
表4-16:图书借阅
字段名称 | 类型 | 长度 | 字段说明 | 主键 | 默认值 |
---|---|---|---|---|---|
id | bigint | 主键 | 主键 | ||
addtime | timestamp | 创建时间 | CURRENT_TIMESTAMP | ||
jieyuebianhao | varchar | 200 | 借阅编号 | ||
tushubianhao | varchar | 200 | 图书编号 | ||
tushumingcheng | varchar | 200 | 图书名称 | ||
tushufenlei | varchar | 200 | 图书分类 | ||
tushuzuozhe | varchar | 200 | 图书作者 | ||
guihaizhuangtai | varchar | 200 | 归还状态 | ||
shuliang | int | 数量 | |||
jieyueshijian | date | 借阅时间 | |||
guihaishijian | datetime | 归还时间 | |||
yonghuzhanghao | varchar | 200 | 用户账号 | ||
yonghuxingming | varchar | 200 | 用户姓名 | ||
yonghushouji | varchar | 200 | 用户手机 | ||
beizhu | varchar | 200 | 备注 | ||
sfsh | varchar | 200 | 是否审核 | 待审核 | |
shhf | longtext | 4294967295 | 审核回复 |
5 系统实现
5.1系统功能实现
当人们打开系统的网址后,首先看到的就是首页界面。在这里,人们能够看到系统的导航条,通过导航条导航进入各功能展示页面进行操作。系统首页界面如图5-1所示:
图5-1 系统首页界面
系统注册:在系统注册页面的输入栏中输入用户注册信息进行注册操作,系统注册页面如图5-2所示:
图5-2系统注册页面
图书信息:在图书信息页面的输入栏中输入书姓名,货架位置,选择图书分类和图书作者进行查询,可以查看到图书详细信息,并根据需要进行收藏,评论和借阅操作;图书信息页面如图5-3所示:
图5-3图书信息详细页面
个人中心:在个人中心页面可以对个人中心和我的收藏进行详细操作;个人中心页面如图5-4所示:
图5-4个人中心界面
5.2管理员模块实现
管理员进入主页面,主要功能包括对首页,个人中心,用户管理,图书分类管理,图书信息管理,图书借阅管理,图书续借管理,图书归还管理,反馈类型管理,需求反馈管理,归还入库管理,系统管理等进行操作。管理员主页面如图5-5所示:
图5-5 管理员主界面
管理员点击用户管理。进入用户列表输入用户账号可以查询、新增或删除用户列表,并根据需要对用户信息进行查看详情、修改或删除操作,如图5-6所示:
图5-6用户管理界面
管理员点击图书分类管理。进入图书分类列表输入图书分类可以查询、新增或删除图书分类列表,并根据需要对图书分类信息进行查看修改或删除操作,如图5-7所示:
图5-7图书分类管理界面
管理员点击图书续借管理。进入图书续借列表选择图书编号,用户姓名和选择是否通过可以查询图书续借列表,并根据需要对图书续借详细信息进行查看详情、修改或删除操作,如图5-8所示:
图5-8图书续借管理界面
管理员点击反馈类型管理。进入反馈类型列表选择反馈类型可以查询、新增或删除反馈类型列表,并根据需要对反馈类型详细信息进行修改或删除操作,如图5-9所示:
图5-9反馈类型管理界面
管理员点击需求反馈管理。进入需求反馈列表输入反馈类型和反馈标题可以查或删除需求反馈列表,并根据需要对需求反馈详细信息进行查看详情、修改或删除操作,如图5-10所示:
图5-10需求反馈管理界面
管理员点击归还入库管理。进入归还入库列表输入图书姓名和用户账号可以查询或删除归还入库列表,并根据需要对归还入库详细信息进行查看详情、修改或删除操作,如图5-11所示:
图5-11归还入库管理界面
管理员点击系统管理。进入系统简介列表输入标题可以查询系统简介员列表,并根据需要对系统简介详细信息进行查看详情或修改操作,还可以对轮播图管理、大厦公告和关于我们页面进行详细操作;如图5-12所示:
图5-12系统管理界面
5.3用户模块实现
用户进入系统可以对个人中心,图书借阅管理,图书信息管理,图书归还管理,需求反馈管理等功能进行操作。用户功能页面如图5-13所示:
图5-13 用户功能主界面
用户点击图书借阅管理。进入图书借阅列表输入图书名称,选择归还状态,用户姓名和选择是否通过可以查询或删除图书借阅列表,并根据需要对图书借阅详细信息进行查看详情、归还、借阅或删除操作,如图5-14所示:
图5-14图书借阅管理界面
系统测试
FileUtil.java
package com.utils;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* 类说明 :
*/
public class FileUtil {
public static byte[] FileToByte(File file) throws IOException {
// 将数据转为流
@SuppressWarnings("resource")
InputStream content = new FileInputStream(file);
ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
byte[] buff = new byte[100];
int rc = 0;
while ((rc = content.read(buff, 0, 100)) > 0) {
swapStream.write(buff, 0, rc);
}
// 获得二进制数组
return swapStream.toByteArray();
}
}
FankuileixingServiceImpl.java
package com.service.impl;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.List;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.utils.PageUtils;
import com.utils.Query;
import com.dao.FankuileixingDao;
import com.entity.FankuileixingEntity;
import com.service.FankuileixingService;
import com.entity.vo.FankuileixingVO;
import com.entity.view.FankuileixingView;
@Service("fankuileixingService")
public class FankuileixingServiceImpl extends ServiceImpl<FankuileixingDao, FankuileixingEntity> implements FankuileixingService {
@Override
public PageUtils queryPage(Map<String, Object> params) {
Page<FankuileixingEntity> page = this.selectPage(
new Query<FankuileixingEntity>(params).getPage(),
new EntityWrapper<FankuileixingEntity>()
);
return new PageUtils(page);
}
@Override
public PageUtils queryPage(Map<String, Object> params, Wrapper<FankuileixingEntity> wrapper) {
Page<FankuileixingView> page =new Query<FankuileixingView>(params).getPage();
page.setRecords(baseMapper.selectListView(page,wrapper));
PageUtils pageUtil = new PageUtils(page);
return pageUtil;
}
@Override
public List<FankuileixingVO> selectListVO(Wrapper<FankuileixingEntity> wrapper) {
return baseMapper.selectListVO(wrapper);
}
@Override
public FankuileixingVO selectVO(Wrapper<FankuileixingEntity> wrapper) {
return baseMapper.selectVO(wrapper);
}
@Override
public List<FankuileixingView> selectListView(Wrapper<FankuileixingEntity> wrapper) {
return baseMapper.selectListView(wrapper);
}
@Override
public FankuileixingView selectView(Wrapper<FankuileixingEntity> wrapper) {
return baseMapper.selectView(wrapper);
}
}
GuihairukuServiceImpl.java
package com.service.impl;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.List;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.utils.PageUtils;
import com.utils.Query;
import com.dao.GuihairukuDao;
import com.entity.GuihairukuEntity;
import com.service.GuihairukuService;
import com.entity.vo.GuihairukuVO;
import com.entity.view.GuihairukuView;
@Service("guihairukuService")
public class GuihairukuServiceImpl extends ServiceImpl<GuihairukuDao, GuihairukuEntity> implements GuihairukuService {
@Override
public PageUtils queryPage(Map<String, Object> params) {
Page<GuihairukuEntity> page = this.selectPage(
new Query<GuihairukuEntity>(params).getPage(),
new EntityWrapper<GuihairukuEntity>()
);
return new PageUtils(page);
}
@Override
public PageUtils queryPage(Map<String, Object> params, Wrapper<GuihairukuEntity> wrapper) {
Page<GuihairukuView> page =new Query<GuihairukuView>(params).getPage();
page.setRecords(baseMapper.selectListView(page,wrapper));
PageUtils pageUtil = new PageUtils(page);
return pageUtil;
}
@Override
public List<GuihairukuVO> selectListVO(Wrapper<GuihairukuEntity> wrapper) {
return baseMapper.selectListVO(wrapper);
}
@Override
public GuihairukuVO selectVO(Wrapper<GuihairukuEntity> wrapper) {
return baseMapper.selectVO(wrapper);
}
@Override
public List<GuihairukuView> selectListView(Wrapper<GuihairukuEntity> wrapper) {
return baseMapper.selectListView(wrapper);
}
@Override
public GuihairukuView selectView(Wrapper<GuihairukuEntity> wrapper) {
return baseMapper.selectView(wrapper);
}
}
add-or-update.vue
<template>
<div class="addEdit-block" style="width: 100%;">
<el-form
:style='{"borderRadius":"6px","padding":"30px","margin":"0 0 0 70px"}'
class="add-update-preview"
ref="ruleForm"
:model="ruleForm"
:rules="rules"
label-width="140px"
>
<template >
<el-form-item :style='{"width":"50%","margin":"0 0 20px 0","display":"inline-block"}' class="input" v-if="type!='info'" label="标题" prop="title">
<el-input v-model="ruleForm.title" placeholder="标题" clearable :readonly="ro.title"></el-input>
</el-form-item>
<el-form-item :style='{"width":"50%","margin":"0 0 20px 0","display":"inline-block"}' v-else class="input" label="标题" prop="title">
<el-input v-model="ruleForm.title" placeholder="标题" readonly></el-input>
</el-form-item>
<el-form-item :style='{"width":"50%","margin":"0 0 20px 0","display":"inline-block"}' class="input" v-if="type!='info'" label="副标题" prop="subtitle">
<el-input v-model="ruleForm.subtitle" placeholder="副标题" clearable :readonly="ro.subtitle"></el-input>
</el-form-item>
<el-form-item :style='{"width":"50%","margin":"0 0 20px 0","display":"inline-block"}' v-else class="input" label="副标题" prop="subtitle">
<el-input v-model="ruleForm.subtitle" placeholder="副标题" readonly></el-input>
</el-form-item>
<el-form-item :style='{"width":"50%","margin":"0 0 20px 0","display":"inline-block"}' class="upload" v-if="type!='info' && !ro.picture1" label="图片1" prop="picture1">
<file-upload
tip="点击上传图片1"
action="file/upload"
:limit="3"
:multiple="true"
:fileUrls="ruleForm.picture1?ruleForm.picture1:''"
@change="picture1UploadChange"
></file-upload>
</el-form-item>
<el-form-item :style='{"width":"50%","margin":"0 0 20px 0","display":"inline-block"}' class="upload" v-else-if="ruleForm.picture1" label="图片1" prop="picture1">
<img v-if="ruleForm.picture1.substring(0,4)=='http'" class="upload-img" style="margin-right:20px;" v-bind:key="index" :src="ruleForm.picture1.split(',')[0]" width="100" height="100">
<img v-else class="upload-img" style="margin-right:20px;" v-bind:key="index" v-for="(item,index) in ruleForm.picture1.split(',')" :src="$base.url+item" width="100" height="100">
</el-form-item>
<el-form-item :style='{"width":"50%","margin":"0 0 20px 0","display":"inline-block"}' class="upload" v-if="type!='info' && !ro.picture2" label="图片2" prop="picture2">
<file-upload
tip="点击上传图片2"
action="file/upload"
:limit="3"
:multiple="true"
:fileUrls="ruleForm.picture2?ruleForm.picture2:''"
@change="picture2UploadChange"
></file-upload>
</el-form-item>
<el-form-item :style='{"width":"50%","margin":"0 0 20px 0","display":"inline-block"}' class="upload" v-else-if="ruleForm.picture2" label="图片2" prop="picture2">
<img v-if="ruleForm.picture2.substring(0,4)=='http'" class="upload-img" style="margin-right:20px;" v-bind:key="index" :src="ruleForm.picture2.split(',')[0]" width="100" height="100">
<img v-else class="upload-img" style="margin-right:20px;" v-bind:key="index" v-for="(item,index) in ruleForm.picture2.split(',')" :src="$base.url+item" width="100" height="100">
</el-form-item>
<el-form-item :style='{"width":"50%","margin":"0 0 20px 0","display":"inline-block"}' class="upload" v-if="type!='info' && !ro.picture3" label="图片3" prop="picture3">
<file-upload
tip="点击上传图片3"
action="file/upload"
:limit="3"
:multiple="true"
:fileUrls="ruleForm.picture3?ruleForm.picture3:''"
@change="picture3UploadChange"
></file-upload>
</el-form-item>
<el-form-item :style='{"width":"50%","margin":"0 0 20px 0","display":"inline-block"}' class="upload" v-else-if="ruleForm.picture3" label="图片3" prop="picture3">
<img v-if="ruleForm.picture3.substring(0,4)=='http'" class="upload-img" style="margin-right:20px;" v-bind:key="index" :src="ruleForm.picture3.split(',')[0]" width="100" height="100">
<img v-else class="upload-img" style="margin-right:20px;" v-bind:key="index" v-for="(item,index) in ruleForm.picture3.split(',')" :src="$base.url+item" width="100" height="100">
</el-form-item>
</template>
<el-form-item :style='{"width":"50%","margin":"0 0 20px 0","display":"inline-block"}' v-if="type!='info'" label="内容" prop="content">
<editor
style="min-width: 200px; max-width: 600px;"
v-model="ruleForm.content"
class="editor"
action="file/upload">
</editor>
</el-form-item>
<el-form-item :style='{"width":"50%","margin":"0 0 20px 0","display":"inline-block"}' v-else-if="ruleForm.content" label="内容" prop="content">
<span :style='{"fontSize":"14px","lineHeight":"40px","color":"#000","fontWeight":"500","display":"inline-block"}' v-html="ruleForm.content"></span>
</el-form-item>
<el-form-item :style='{"padding":"0","margin":"0"}' class="btn">
<el-button :style='{"border":"0","cursor":"pointer","padding":"0","margin":"0 20px 0 0","outline":"none","color":"rgba(255, 255, 255, 1)","borderRadius":"4px","background":"#000000","width":"128px","lineHeight":"40px","fontSize":"14px","height":"40px"}' v-if="type!='info'" type="primary" class="btn-success" @click="onSubmit">提交</el-button>
<el-button :style='{"border":"1px solid #000000","cursor":"pointer","padding":"0","margin":"0","outline":"none","color":"#000000","borderRadius":"4px","background":"rgba(255, 255, 255, 1)","width":"128px","lineHeight":"40px","fontSize":"14px","height":"40px"}' v-if="type!='info'" class="btn-close" @click="back()">取消</el-button>
<el-button :style='{"border":"1px solid #000000","cursor":"pointer","padding":"0","margin":"0","outline":"none","color":"#000000","borderRadius":"4px","background":"rgba(255, 255, 255, 1)","width":"128px","lineHeight":"40px","fontSize":"14px","height":"40px"}' v-if="type=='info'" class="btn-close" @click="back()">返回</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
// 数字,邮件,手机,url,身份证校验
import { isNumber,isIntNumer,isEmail,isPhone, isMobile,isURL,checkIdCard } from "@/utils/validate";
export default {
data() {
let self = this
var validateIdCard = (rule, value, callback) => {
if(!value){
callback();
} else if (!checkIdCard(value)) {
callback(new Error("请输入正确的身份证号码"));
} else {
callback();
}
};
var validateUrl = (rule, value, callback) => {
if(!value){
callback();
} else if (!isURL(value)) {
callback(new Error("请输入正确的URL地址"));
} else {
callback();
}
};
var validateMobile = (rule, value, callback) => {
if(!value){
callback();
} else if (!isMobile(value)) {
callback(new Error("请输入正确的手机号码"));
} else {
callback();
}
};
var validatePhone = (rule, value, callback) => {
if(!value){
callback();
} else if (!isPhone(value)) {
callback(new Error("请输入正确的电话号码"));
} else {
callback();
}
};
var validateEmail = (rule, value, callback) => {
if(!value){
callback();
} else if (!isEmail(value)) {
callback(new Error("请输入正确的邮箱地址"));
} else {
callback();
}
};
var validateNumber = (rule, value, callback) => {
if(!value){
callback();
} else if (!isNumber(value)) {
callback(new Error("请输入数字"));
} else {
callback();
}
};
var validateIntNumber = (rule, value, callback) => {
if(!value){
callback();
} else if (!isIntNumer(value)) {
callback(new Error("请输入整数"));
} else {
callback();
}
};
return {
id: '',
type: '',
ro:{
title : false,
subtitle : false,
content : false,
picture1 : false,
picture2 : false,
picture3 : false,
},
ruleForm: {
title: '',
subtitle: '',
content: '',
picture1: '',
picture2: '',
picture3: '',
},
rules: {
title: [
{ required: true, message: '标题不能为空', trigger: 'blur' },
],
subtitle: [
],
content: [
{ required: true, message: '内容不能为空', trigger: 'blur' },
],
picture1: [
],
picture2: [
],
picture3: [
],
}
};
},
props: ["parent"],
computed: {
},
created() {
},
methods: {
// 下载
download(file){
window.open(`${file}`)
},
// 初始化
init(id,type) {
if (id) {
this.id = id;
this.type = type;
}
if(this.type=='info'||this.type=='else'){
this.info(id);
}else if(this.type=='logistics'){
this.logistics=false;
this.info(id);
}else if(this.type=='cross'){
var obj = this.$storage.getObj('crossObj');
for (var o in obj){
if(o=='title'){
this.ruleForm.title = obj[o];
this.ro.title = true;
continue;
}
if(o=='subtitle'){
this.ruleForm.subtitle = obj[o];
this.ro.subtitle = true;
continue;
}
if(o=='content'){
this.ruleForm.content = obj[o];
this.ro.content = true;
continue;
}
if(o=='picture1'){
this.ruleForm.picture1 = obj[o];
this.ro.picture1 = true;
continue;
}
if(o=='picture2'){
this.ruleForm.picture2 = obj[o];
this.ro.picture2 = true;
continue;
}
if(o=='picture3'){
this.ruleForm.picture3 = obj[o];
this.ro.picture3 = true;
continue;
}
}
}
},
// 多级联动参数
info(id) {
this.$http({
url: `systemintro/info/${id}`,
method: "get"
}).then(({ data }) => {
if (data && data.code === 0) {
this.ruleForm = data.data;
//解决前台上传图片后台不显示的问题
let reg=new RegExp('../../../upload','g')//g代表全部
this.ruleForm.content = this.ruleForm.content.replace(reg,'../../../springboot6a3bb/upload');
} else {
this.$message.error(data.msg);
}
});
},
// 提交
onSubmit() {
if(this.ruleForm.picture1!=null) {
this.ruleForm.picture1 = this.ruleForm.picture1.replace(new RegExp(this.$base.url,"g"),"");
}
if(this.ruleForm.picture2!=null) {
this.ruleForm.picture2 = this.ruleForm.picture2.replace(new RegExp(this.$base.url,"g"),"");
}
if(this.ruleForm.picture3!=null) {
this.ruleForm.picture3 = this.ruleForm.picture3.replace(new RegExp(this.$base.url,"g"),"");
}
var objcross = this.$storage.getObj('crossObj');
//更新跨表属性
var crossuserid;
var crossrefid;
var crossoptnum;
if(this.type=='cross'){
var statusColumnName = this.$storage.get('statusColumnName');
var statusColumnValue = this.$storage.get('statusColumnValue');
if(statusColumnName!='') {
var obj = this.$storage.getObj('crossObj');
if(statusColumnName && !statusColumnName.startsWith("[")) {
for (var o in obj){
if(o==statusColumnName){
obj[o] = statusColumnValue;
}
}
var table = this.$storage.get('crossTable');
this.$http({
url: `${table}/update`,
method: "post",
data: obj
}).then(({ data }) => {});
} else {
crossuserid=this.$storage.get('userid');
crossrefid=obj['id'];
crossoptnum=this.$storage.get('statusColumnName');
crossoptnum=crossoptnum.replace(/\[/,"").replace(/\]/,"");
}
}
}
this.$refs["ruleForm"].validate(valid => {
if (valid) {
if(crossrefid && crossuserid) {
this.ruleForm.crossuserid = crossuserid;
this.ruleForm.crossrefid = crossrefid;
let params = {
page: 1,
limit: 10,
crossuserid:this.ruleForm.crossuserid,
crossrefid:this.ruleForm.crossrefid,
}
this.$http({
url: "systemintro/page",
method: "get",
params: params
}).then(({
data
}) => {
if (data && data.code === 0) {
if(data.data.total>=crossoptnum) {
this.$message.error(this.$storage.get('tips'));
return false;
} else {
this.$http({
url: `systemintro/${!this.ruleForm.id ? "save" : "update"}`,
method: "post",
data: this.ruleForm
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: "操作成功",
type: "success",
duration: 1500,
onClose: () => {
this.parent.showFlag = true;
this.parent.addOrUpdateFlag = false;
this.parent.systemintroCrossAddOrUpdateFlag = false;
this.parent.search();
this.parent.contentStyleChange();
}
});
} else {
this.$message.error(data.msg);
}
});
}
} else {
}
});
} else {
this.$http({
url: `systemintro/${!this.ruleForm.id ? "save" : "update"}`,
method: "post",
data: this.ruleForm
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: "操作成功",
type: "success",
duration: 1500,
onClose: () => {
this.parent.showFlag = true;
this.parent.addOrUpdateFlag = false;
this.parent.systemintroCrossAddOrUpdateFlag = false;
this.parent.search();
this.parent.contentStyleChange();
}
});
} else {
this.$message.error(data.msg);
}
});
}
}
});
},
// 获取uuid
getUUID () {
return new Date().getTime();
},
// 返回
back() {
this.parent.showFlag = true;
this.parent.addOrUpdateFlag = false;
this.parent.systemintroCrossAddOrUpdateFlag = false;
this.parent.contentStyleChange();
},
picture1UploadChange(fileUrls) {
this.ruleForm.picture1 = fileUrls;
},
picture2UploadChange(fileUrls) {
this.ruleForm.picture2 = fileUrls;
},
picture3UploadChange(fileUrls) {
this.ruleForm.picture3 = fileUrls;
},
}
};
</script>
<style lang="scss" scoped>
.amap-wrapper {
width: 100%;
height: 500px;
}
.search-box {
position: absolute;
}
.el-date-editor.el-input {
width: auto;
}
.add-update-preview .el-form-item /deep/ .el-form-item__label {
padding: 0 10px 0 0;
color: #666;
font-weight: 600;
width: 140px;
font-size: 14px;
line-height: 40px;
text-align: right;
}
.add-update-preview .el-form-item /deep/ .el-form-item__content {
margin-left: 140px;
}
.add-update-preview .el-input /deep/ .el-input__inner {
border: 1px solid #000;
border-radius: 0;
padding: 0 12px;
outline: none;
color: #000;
width: 400px;
font-size: 14px;
height: 40px;
}
.add-update-preview .el-select /deep/ .el-input__inner {
border: 1px solid #000;
border-radius: 0;
padding: 0 10px;
outline: none;
color: #000;
width: 200px;
font-size: 14px;
height: 40px;
}
.add-update-preview .el-date-editor /deep/ .el-input__inner {
border: 1px solid #000;
border-radius: 0;
padding: 0 10px 0 30px;
outline: none;
color: #000;
width: 200px;
font-size: 14px;
height: 40px;
}
.add-update-preview /deep/ .el-upload--picture-card {
background: transparent;
border: 0;
border-radius: 0;
width: auto;
height: auto;
line-height: initial;
vertical-align: middle;
}
.add-update-preview /deep/ .upload .upload-img {
border: 1px dashed #000;
cursor: pointer;
border-radius: 0;
color: #000;
width: 150px;
font-size: 32px;
line-height: 150px;
text-align: center;
height: 150px;
}
.add-update-preview /deep/ .el-upload-list .el-upload-list__item {
border: 1px dashed #000;
cursor: pointer;
border-radius: 0;
color: #000;
width: 150px;
font-size: 32px;
line-height: 150px;
text-align: center;
height: 150px;
}
.add-update-preview /deep/ .el-upload .el-icon-plus {
border: 1px dashed #000;
cursor: pointer;
border-radius: 0;
color: #000;
width: 150px;
font-size: 32px;
line-height: 150px;
text-align: center;
height: 150px;
}
.add-update-preview .el-textarea /deep/ .el-textarea__inner {
border: 1px solid #000;
border-radius: 0;
padding: 12px;
outline: none;
color: #000;
width: 400px;
font-size: 14px;
height: 120px;
}
</style>