章节目录
- 前言
- 已知BUG
- 什么是MVC模式?
- 零、项目图片
- 登录页面
- 图书管理页面
- 借阅图书页面
- 归还图书页面
- 超时查询页面
- 用户管理页面
- 一、项目结构
- 二、从0到1 (0 -> 1)
- 1.首先是
- 2.数据库设置
- 3.创建SpringBoot项目
- 4.配置数据库连接文件
- 三、登录页面
- 1.前端
- 2.后端
- 3.登录是如何实现的?
- 四、图书管理页面
- #.判断用户登录状态
- 1.前端
- 1.显示图书数据
- 2.搜索图书
- 3.添加图书
- 4.编辑图书
- 5.删除图书
- 2.后端
- 1.获取图书
- 2.搜索图书
- 3.添加图书
- 4.编辑图书
- 5.删除图书
- 3.页面是如何与数据库交互的?
- 1.获取图书数据
- 2.搜托图书
- 3.添加图书
- 4.编辑图书
- 5.删除图书
- 五、借阅图书页面
- 1.前端
- 2.后端
- 3.借阅图书是如何实现的?
- 六、归还图书页面
- 1.前端
- 2.后端
- 3.归还图书是如何实现的?
- 七、超时查询页面
- 1.前端
- 2.后端
- 3.超时查询是如何实现的?
- 八、用户管理页面
- 九、退出登录
- 1.前端
- 2.用户的退出是如何实现的?
- 总结与项目源码地址
- # Tooltip 小贴士
前言
在此次教程中,我会教大家如何写一套前后端分离图书管理系统:
前端技术栈:
HTML5+CSS3+JavaScript
后端技术栈:
Java+SpringBoot+MySQL
适合人群:未来做前端或后端或全栈有兴趣的技术人员
系统环境:
操作系统:Windows 10
前端工具:Visual Studio Code
后端工具:IDEA
数据库:MySQL 5.7.26
环境搭建:PHPStudy
本项目采用MVC模式书写
注意!!!本章节含有大量CV代码,慎重!!!只是简单的一些对数据库的处理操作,看看就行
已知BUG
1. 使用 MySQL 8 + 此项目在此项目有bug
BUG 产生原因
因为在 MySQL 8 中, 已将 groups 添加为关键字,所以导致查询,插入,修改图书表字段 groups 时会发生报错
修改 BUG 方式
将图书表的 groups 字段修改为 bookgroups 字段
前端图书管理页面,把 input 输入框为 groups 的输入框改为 bookgroups
后端 Book 实体类 groups 改为 bookgroups
什么是MVC模式?
引用runoob对MVC的介绍 源地址
零、项目图片
登录页面
图书管理页面
借阅图书页面
归还图书页面
超时查询页面
用户管理页面
一、项目结构
二、从0到1 (0 -> 1)
1.首先是
选择一个合适的硬盘创建自己的项目文件夹,在项目文件夹里创建HTML5和SpringBoot文件夹
HTML5文件夹用于存放前端显示页面
SpringBoot文件夹用于存放后端服务器代码
以上两个文件夹也可以按照自己喜欢的名字来进行创建,本篇教程之后会以这两个文件夹创建文件,请注意自己的文件存放位置
2.数据库设置
首先创建 library 数据库
create database library default character set utf8 collate utf8_general_ci;
然后进入 library 数据库里
use library;
创建图书表
CREATE TABLE `books` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`groups` varchar(255) NOT NULL DEFAULT '',
`name` varchar(255) NOT NULL DEFAULT '',
`author` varchar(255) NOT NULL DEFAULT '',
`press` varchar(255) NOT NULL DEFAULT '',
`price` double(10,2) NOT NULL DEFAULT '0.00',
`quantity` int(5) NOT NULL DEFAULT '0',
`ISBN` varchar(13) NOT NULL DEFAULT '',
PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
在图书表里添加书本
INSERT INTO `books` VALUES (1,'地理','房龙地理','房龙','文汇出版社',29.01,10,'9780000000001'),(2,'地理','地理学与生活','[美] 阿瑟·格蒂斯 ','世界图书出版公司',49.00,10,'9780000000002'),(3,'地理','古老阳光的末日','Thom Hartmann','上海远东出版社',20.00,10,'9780000000003'),(4,'法律','洞穴奇案','[美] 萨伯','生活.读书.新知三联书店',18.00,10,'9780000000004'),(5,'法律','西窗法雨','刘星','法律出版社',24.00,10,'9780000000005'),(6,'法律','审判为什么不公正','[英] 卡德里','新星出版社',49.50,10,'9780000000006'),(7,'军事','亮剑(舒适阅读版)','都梁','北京联合出版公司',45.00,10,'9780000000007'),(8,'军事','二战记忆 安妮日记','[德] 安妮·弗兰克','人民文学出版社',23.00,10,'9780000000008'),(9,'军事','亮剑','都梁','解放军文艺出版社',25.00,10,'9780000000009'),(10,'历史','历史是什么?','爱德华·霍列特·卡尔','商务印书馆',19.00,10,'9780000000010'),(11,'历史','中国史学史','金毓黻','商务印书馆',19.00,10,'9780000000011'),(12,'历史','史记选','[清] 储欣','商务印书馆',48.00,10,'9780000000012'),(13,'计算机','Java从入门到精通 ','明日科技','清华大学出版社',69.00,10,'9780000000013'),(14,'计算机','C++从入门到精通','李伟明','清华大学出版社',49.00,10,'9780000000014'),(15,'计算机','PHP从入门到精通','千锋教育高教产品研发部','清华大学出版社',59.00,10,'9780000000015');
创建用户表
CREATE TABLE `users` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`groups` varchar(255) NOT NULL DEFAULT 'user',
`username` varchar(255) NOT NULL DEFAULT '',
`password` varchar(255) NOT NULL DEFAULT '',
`gender` varchar(255) NOT NULL DEFAULT '',
`id_card` int(8) NOT NULL DEFAULT '0',
`phone` varchar(11) NOT NULL DEFAULT '0',
`identity` varchar(255) NOT NULL DEFAULT '学生',
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
插入一条管理员用户数据
INSERT INTO `users` VALUES (1,'admin','Admin','123456','男',0,0,'管理员');
Admin是用户名
123456是密码
可以自行修改用户名或密码,之后执行登录操作时需要用到
创建借书表
CREATE TABLE `borrow` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '',
`ISBN` varchar(13) NOT NULL DEFAULT '',
`username` varchar(255) NOT NULL DEFAULT '',
`id_card` varchar(8) NOT NULL DEFAULT '',
`phone` varchar(11) NOT NULL DEFAULT '',
`time` date NOT NULL DEFAULT '1970-01-01',
`r_time` date NOT NULL DEFAULT '1970-01-01',
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
存放借阅的图书信息
or
你可以选择下载此文件来自动导入到数据库中
网盘链接 提取码: 6666
3.创建SpringBoot项目
新建一个项目
选择Spring Initializr项目
设置以下信息
Group:组名
一般格式为 com.公司名.项目名.模块名 没有公司名就用自己的名字
Artifact:工程名
Type:项目类型
Language:使用语言
Packaging:包装类型
Java Version:JDK版本
Version:项目版本
Name:项目名
Description:项目描述
Package:包选择Spring要添加的组件
Lombok
Spring Web
Spring Data JPA 和 MySQL Driver
选择刚才创建的SpringBoot文件夹
在pom.xml文件下添加JSONObject依赖
<!-- JSONObject-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.28</version>
</dependency>
<!-- JSONObject依赖-->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
构建过程中最好使用代理构建项目
如果您的项目构建失败,您可以通过下面的链接下载我已经构建好的项目来开发
项目链接 提取码: 77tr
4.配置数据库连接文件
先删除src下的application.properties文件
在这里我用yml格式连接数据库
在resources文件夹新建一个application.yml文件
在文件里写入以下代码
spring:
datasource:
url: jdbc:mysql://localhost:3306/library?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root #用户名
password: 123456 #密码
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
show-sql: true
properties:
hibernate:
format_sql: true
server:
port: 8181 #服务器端口
以上就创建完了SpringBoot项目
三、登录页面
1.前端
创建完成后,就可以开始写第一个页面
在HTML5文件夹创建index.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图书管理系统</title>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
</body>
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdn.staticfile.org/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
</html>
分别在css文件夹和js文件夹创建 index.css和index.js
然后在index.html文件里引用这两个文件
<link rel="stylesheet" href="library/css/index.css">
<script src="library/js/index.js">
接下来创建一个登录面板
<div class="login-pane">
<form method="post" class="login-form">
<h3>图书管理系统</h3>
<input type="text" name="username" id="username" class="username-text" placeholder="用户名">
<input type="password" name="password" id="password" class="password-text" placeholder="密码">
<input type="submit" value="登录" class="login-button btn btn-primary" id="login-button">
</form>
</div>
在index.css写样式代码 美化登录面板
*{
margin:0;
padding: 0;
outline: none;
}
html,body{
width: 100%;
height: 100%;
}
body{
display: flex;
justify-content: center;
align-items: center;
background-color: rgb(249,249,249);
}
.login-pane{
display: flex;
justify-content: center;
align-items: center;
width: 375px;
height: 500px;
background-color: #fff;
border-radius: 4px;
box-shadow: 1px 1px 10px #b8b8b8;
}
.login-pane .login-form h3{
text-align: center;
margin-bottom: 50px;
}
.login-pane .login-form input{
display: block;
text-align: center;
width: 250px;
padding-top: 4px;
padding-bottom: 4px;
margin-bottom: 16px;
border: 1px solid gainsboro;
border-radius: 4px;
}
.login-pane .login-form .login-button{
padding-top: 4px;
padding-bottom: 4px;
width: 250px;
}
给登录面板绑定事件
在index.js写入
$(function(){
//判断用户是否登录过
var is_login = $.cookie("username");
if(is_login != null && is_login != "" && is_login != ''){
window.location.replace("/library/library.html");
}
//获取表单组件
var username = $('.username-text');
var password = $('.password-text');
var login_button = $('.login-button');
//登录按钮点击事件
login_button.click(function (e) {
e.preventDefault();
//判断输入框
if(username.val() == ""){
alert("请输入用户名");
}
else if(password.val() == ""){
alert("请输入密码");
}
else{
//事件执行
$.ajax({
type: "post",
url: "http://这里填你电脑的本地IP:这里填你SpringBoot服务端的端口/nav/login",
data: {"username":username.val(),"password":password.val()},
dataType: "json",
success:function(data){
//如果后端返回的code值为1则登录成功
if(data.code == "1"){
alert("登录成功");
$.cookie("username",data.username);
window.location.replace("/library/library.html");
}
//如果后端返回的code值为0则登录失败
if(data.code == "0"){
alert("账号或密码错误");
}
},
error:function(data){
//如果前端与后端交互出问题则报错
alert("系统错误");
}
});
}
});
});
2.后端
现在,登录页面就已经制作完成,现在开始制作后端登录模型
在SpringBoot项目中创建以下包与文件
包:
config ------------ 配置类
controller --------- 控制类
entity -------------- 实体类
repository -------- 储存类
类:
CrosConfig ------------ 解决跨域问题
UsersHandler ---------- 用户操作
Users --------------------- 用户实体
UsersRepository ------- 用户存储库
注意!这里的 Users 最好是对应上数据库的 users 表名,不然对数据库的操作会报错
在CrosConfig下写入
package com.ksamar.library.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CrosConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") //映射
.allowedOriginPatterns("*") //允许的模式
.allowedMethods("GET","HEAD","POST","PUT","DELETE","OPTIONS") //允许的请求
.allowCredentials(true) //允许凭据
.maxAge(3600) //最大请求
.allowedHeaders("*"); //允许的标头
}
}
在UsersHandler写入
package com.ksamar.library.controller;
import com.alibaba.fastjson.JSONObject;
import com.ksamar.library.entity.Users;
import com.ksamar.library.repository.UsersRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.web.bind.annotation.*;
import java.util.Optional;
@RestController
@RequestMapping("/nav") //这里是请求地址如 果要用这个类的方法就需要使用 http:// ip /nav 请求地址
public class UsersHandler {
@Autowired
private UsersRepository usersRepository; //用户存储库 用来装用户的数据
//用户登录
@PostMapping("/login") //这里是登录的请求地址和上面一样在 /nav 后面加上 /login 就能请求了
public Object findOne(Users users){
Example<Users> userExample = Example.of(users) ; //封装表单传过来的数据
Optional<Users> userOptional = usersRepository.findOne(userExample); //与数据库交互 去寻找表单所提交的用户存不存在
JSONObject jsonObject = new JSONObject(); //创建一个空JSONObject 对象
//0代表登录失败 1代表登录成功
//判断这个用户是否存在
if (userOptional.isPresent()){
Users userTemp = userOptional.get(); //获取用户数据
//判断这个用户是不是管理组的
if(userTemp.getGroups().equals("admin")){
//判断用户提交的用户名和数据库的是否一致
if(users.getUsername().equals(userTemp.getUsername())){
//判断用户提交的密码和数据库的是否一致
if(users.getPassword().equals(userTemp.getPassword())){
jsonObject.put("code","1");
jsonObject.put("username",userTemp.getUsername());
}
else{
jsonObject.put("code","0");
}
}
else{
jsonObject.put("code","0");
}
}
else{
jsonObject.put("code","0");
}
}
else{
jsonObject.put("code","0");
}
return jsonObject;
}
}
在Users里写入
package com.ksamar.library.entity;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
@Data
public class Users {
@Id
@GeneratedValue(strategy = GenerationType.AUTO) //设置Id自增
//这里就是与数据库对应字段就可以了 Integer代表int String代表varchar
private Integer id;
private String groups;
private String username;
private String password;
private String gender;
private String id_card;
private String phone;
private String identity;
}
在UsersRepository里写入
package com.ksamar.library.repository;
import com.ksamar.library.entity.Users;
import org.springframework.data.jpa.repository.JpaRepository;
//这里实现用户存储的接口
public interface UsersRepository extends JpaRepository<Users,Integer> {
}
运行一下SpringBoot然后打开之前写的登录页面就能食用了
最后,在library文件夹下新建一个library.html登录页面就制作完成了
是不是很简单呢?
当然,使用Cookie的方式存储用户登录是不安全的行为
3.登录是如何实现的?
首先是从View视图页面获取用户输入的表单信息,点击表单按钮后,表单信息利用Controller把信息传送 到后端的Model里,然后这些信息在Model里进行数据处理,数据处理完之后,再从后端的Model里面,返回一个json文件给Controller,然后Controller接收到Model的json返回文件,就去处理json文件里的信息,然后用View展示处理后的界面。
四、图书管理页面
弄好了登录页面后,登录成功将会切到图书管理页面
要做的工作:
#.判断用户登录状态
1.图书管理页面
2.借阅图书页面
3.归还图书页面
4.超时查询页面
5.用户管理页面
#.判断用户登录状态
Web进行登录操作时,登录成功后,用户的cookie信息会存留在浏览器里,用来判断用户登录,用户操作等等
在JS文件夹下创建 library.js 文件
在下面写入判断用户cookie登录信息
$(function(){
//获取cookie 判断用户登录状态
var is_login = $.cookie("username");
if(is_login == null || is_login == "" || is_login == ''){
alert("请登录!");
window.location.replace("/index.html");
}
});
这样就可以简易的实现判断用户是否处于登录状态
如果登录了,就可以访问当前页面,如果没有登录,则跳回登录页面让用户进行登录操作
1.前端
1.显示图书数据
这个是普遍后台的UI界面 (至少是我认为的
在 library.html 里写入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图书管理系统</title>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="/library/css/library.css">
</head>
<body>
<div class="main">
<div class="manage-nav bg-primary">
<nav class="navbar bg-primary navbar-dark">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="/library/library.html">图书管理</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">借阅图书</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">归还图书</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">超时查询</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">用户管理</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">退出系统</a>
</li>
</ul>
</nav>
</div>
<div class="main-pane">
<div class="user-nav">
<p class="username">Admin</p>
</div>
<div class="info-pane">
<div class="search-pane">
<button class="btn btn-success add-button">添加书籍</button>
<input type="text" name="search" id="search" placeholder="请输入搜索的内容">
<button class="btn btn-primary search-button">搜索</button>
</div>
<table class="table table-hover">
<thead>
<tr>
<th>Id</th>
<th>组名</th>
<th>书名</th>
<th>作者</th>
<th>出版社</th>
<th>价格(人民币)</th>
<th>数量(本)</th>
<th>ISBN号码</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</body>
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdn.staticfile.org/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
<script src="/library/js/library.js"></script>
</html>
在css文件夹创建 library.css 文件 写入
*{
margin:0;
padding: 0;
outline: none;
}
html,body,.main{
width: 100%;
height: 100%;
}
/* 主页面样式 */
.main{
display: flex;
}
/* 侧边导航栏样式 */
.manage-nav{
display: flex;
justify-content: center;
position: fixed;
min-width: 256px;
max-width: 256px;
height: 100%;
text-align: center;
}
/* 面板样式 */
.main-pane{
margin-left: 256px;
width: 100%;
height: 100%;
}
/* 用户导航栏样式 */
.user-nav{
display: flex;
align-items: center;
justify-content: flex-end;
position: fixed;
min-width: calc(100% - 256px);
height: 64px;
background-color: rgb(248, 248, 248);
}
.user-nav .username{
padding: 0;
margin: 0;
margin-right: 64px;
}
/* 信息面板样式 */
.info-pane{
margin-top: 64px;
min-width: calc(100% - 256px);
min-height: calc(100% - 64px);
height: calc(100% - 64px);
background-color: white;
}
.info-pane .search-pane{
display: flex;
justify-content: center;
width: 100%;
height: 32px;
margin-bottom: 16px;
}
.info-pane .search-pane button{
margin-right: 32px;
padding: 0;
padding-left: 16px;
padding-right: 16px;
}
.info-pane .search-pane #search{
width: 400px;
padding-left: 12px;
border: 1px solid #aaa;
border-radius: 4px;
}
在js文件夹创建 library.js 文件 写入
$(function(){
//获取cookie 判断用户登录状态
var is_login = $.cookie("username");
if(is_login == null || is_login == "" || is_login == ''){
alert("请登录!");
window.location.replace("/index.html");
}
//添加假数据
for(var i = 1; i < 51; i++){
var text = "<tr id='" + i + "'>" +
"<td>" + i + "</td>" +
"<td>基础书籍</td>" +
"<td>语文书</td>" +
"<td>张三</td>" +
"<td>无</td>" +
"<td>6.66</td>" +
"<td>6</td>" +
"<td>978000000006</td>" +
"<td><button class='btn btn-success btn-sm edit' name='" + i + "'>编辑</button><button class='btn btn-danger btn-sm delete' name='" + i + "'>删除</button></td>" +
"</tr>";
$("tbody").append(text);
}
});
至此,我们就创建好了前端的图书管理页面
现在这个图书页面也只是一个静态页面,那怎么让他动起来呢?
首先我们要知道,后台页面有些内容是不会经常进行变动,比如侧边的导航栏,顶部的用户栏,经常改变的内容是信息面板这一块,为了减少代码沉余,在后台页面我将添加一个iframe框架动态刷新信息内容,静态更改url就能访问其他页面,导航栏和用户栏相对也不会进行变化。
现在把导航栏需要的页面都给创建出来
在 library 文件夹创建下面的文件
后台 -> library.html
图书管理 -> books.html
借阅图书 -> borrow.html
归还图书 -> return.html
超时查询 -> overtime.html
用户管理 -> users.html
然后再给每一个html文件创建一个对应名字的css文件,js文件即可
创建文件完毕后,在library.html文件夹添加一个 iframe 框架
替换 <div class=“info-pane”> 下的代码,只用添加一个 iframe 写上 src 页面路径
<div class="info-pane">
<iframe src="/library/books.html" frameborder="0" name="info-iframe"></iframe>
</div>
给 ** library.css** 样式表添加 iframe 的样式
.info-pane iframe{
width: 100%;
height: 100%;
}
现在可以把原来写在 <div class=“info-pane”> 下的代码搬到 books.html 文件里
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图书管理系统</title>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="/library/css/books.css">
</head>
<body>
<div class="main">
<div class="search-pane">
<button class="btn btn-success add-button">添加书籍</button>
<input type="text" name="search" id="search" placeholder="请输入搜索的内容">
<button class="btn btn-primary search-button">搜索</button>
</div>
<table class="table table-hover">
<thead>
<tr>
<th>Id</th>
<th>组名</th>
<th>书名</th>
<th>作者</th>
<th>出版社</th>
<th>价格(人民币)</th>
<th>数量(本)</th>
<th>ISBN号码</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</body>
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdn.staticfile.org/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
<script src="/library/js/books.js"></script>
</html>
然后把 search-pane 的样式搬到 books.css 文件里
*{
margin:0;
padding: 0;
outline: none;
}
html,body,.main{
width: 100%;
height: 100%;
}
/* 主页面样式 */
.main{
display: flex;
flex-direction: column;
padding: 32px;
}
.search-pane{
display: flex;
justify-content: center;
width: 100%;
height: 32px;
margin-bottom: 16px;
}
.search-pane button{
margin-right: 32px;
padding: 0;
padding-left: 16px;
padding-right: 16px;
}
.search-pane #search{
width: 400px;
padding-left: 12px;
border: 1px solid #aaa;
border-radius: 4px;
}
把之前写的假数据代码搬到 books.js
$(function(){
//添加假数据
for(var i = 1; i < 51; i++){
var text = "<tr id='" + i + "'>" +
"<td>" + i + "</td>" +
"<td>基础书籍</td>" +
"<td>语文书</td>" +
"<td>张三</td>" +
"<td>无</td>" +
"<td>6.66</td>" +
"<td>6</td>" +
"<td>978000000006</td>" +
"<td><button class='btn btn-success btn-sm edit' name='" + i + "'>编辑</button><button class='btn btn-danger btn-sm delete' name='" + i + "'>删除</button></td>" +
"</tr>";
$("tbody").append(text);
}
});
现在把侧边导航栏的地址一一对应到每一个文件
<nav class="navbar bg-primary navbar-dark">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="/library/books.html" target="info-iframe">图书管理</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/library/borrow.html" target="info-iframe">借阅图书</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/library/return.html" target="info-iframe">归还图书</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/library/overtime.html" target="info-iframe">超时查询</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/library/users.html" target="info-iframe">用户管理</a>
</li>
<li class="nav-item">
<a class="nav-link exit" href="#">退出系统</a>
</li>
</ul>
</nav>
给侧边导航栏添加动态激活样式,在 library.js 写入
//侧边栏激活状态
$("ul>li").click(function (e) {
$("li").removeClass("active");
$(this).addClass("active");
});
退出系统的操作
//退出系统
$(".exit").click(function (e) {
var exit = $.removeCookie('username', { path: '/' });
if(exit){
window.location.replace("/index.html");
alert("您已退出系统");
}
else{
alert("系统错误");
}
});
在图书管理页面显示真数据,将原先的假数据代码替换成如下代码
$(function(){
$.ajax({
type: "get", //请求方式
url: "http://192.168.1.3:8181/nav/books", //请求地址
dataType: "json", //返回文件格式
success:function(data){
//添加数据
for(var i = 0; i < data.length; i++){
var text = "<tr id='" + data[i].id + "'>" +
"<td>" + data[i].id + "</td>" +
"<td>" + data[i].groups + "</td>" +
"<td>" + data[i].name + "</td>" +
"<td>" + data[i].author + "</td>" +
"<td>" + data[i].press + "</td>" +
"<td>" + data[i].price + "</td>" +
"<td>" + data[i].quantity + "</td>" +
"<td>" + data[i].isbn + "</td>" +
"<td><button class='btn btn-success btn-sm edit' name='" + data[i].id + "'>编辑</button><button class='btn btn-danger btn-sm delete' name='" + data[i].id + "'>删除</button></td>" +
"</tr>";
$("tbody").append(text);
}
},
error: function(data){
alert("系统错误");
}
});
});
2.搜索图书
添加一个新的请求,接收返回的数据,处理一下即可,更改 library.js 的代码为
$(function(){
//获取图书数据
$.ajax({
type: "get", //请求方式
url: "http://localhost:8181/nav/books", //请求地址
dataType: "json", //返回文件格式
success:function(data){
//添加数据
searchBook(data);
},
error: function(data){
alert("系统错误");
}
});
//搜索图书
var search_button = $('.search-button');
var input_text = $('#search');
$(search_button).click(function (e) {
e.preventDefault();
$.ajax({
type: "get",
url: "http://localhost:8181/nav/books/find",
data: {book:input_text.val()},
dataType: "json",
success:function(data){
$(".book").remove(); //删除原来的书
searchBook(data); //搜索图书
},
error:function(data){
alert("系统错误");
}
});
});
});
//显示图书信息函数
function searchBook(data){
for(var i = 0; i < data.length; i++){
var text = "<tr id='" + data[i].id + "' class='book'>" +
"<td name='id'>" + data[i].id + "</td>" +
"<td name='groups'>" + data[i].groups + "</td>" +
"<td name='name'>" + data[i].name + "</td>" +
"<td name='author'>" + data[i].author + "</td>" +
"<td name='press'>" + data[i].press + "</td>" +
"<td name='price'>" + data[i].price + "</td>" +
"<td name='quantity'>" + data[i].quantity + "</td>" +
"<td name='isbn'>" + data[i].isbn + "</td>" +
"<td><button class='btn btn-success btn-sm edit' name='" + data[i].id + "' data-toggle='modal' data-target='#book-modal'>编辑</button><button class='btn btn-danger btn-sm delete' name='" + data[i].id + "' data-toggle='modal' data-target='#delete-modal'>删除</button></td>" +
"</tr>";
$("tbody").append(text);
}
}
3.添加图书
在 books.html添加一个模态框,输入图书的信息
<!-- 给添加按钮写入打开模态框参数 -->
<button class="btn btn-success add-button" data-toggle="modal" data-target="#book-modal">添加书籍</button>
<!-- 模态框 -->
<div class="modal fade" id="book-modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title"></h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
<form id="book-form" name="book-form" class="book-form">
<div class="form-group">
<label for="groups">图书组名</label>
<input type="text" class="form-control" placeholder="请输入图书组名" id="groups" name="groups">
</div>
<div class="form-group">
<label for="name">图书名称</label>
<input type="text" class="form-control" placeholder="请输入图书名称" id="name" name="name">
</div>
<div class="form-group">
<label for="author">作者名称:</label>
<input type="text" class="form-control" placeholder="请输入作者名称" id="author" name="author">
</div>
<div class="form-group">
<label for="press">出版社名称:</label>
<input type="text" class="form-control" placeholder="请输入出版社名称" id="press" name="press">
</div>
<div class="form-group">
<label for="price">价格(人民币):</label>
<input type="text" class="form-control" placeholder="请输入价格" id="price" name="price" maxlength="10">
</div>
<div class="form-group">
<label for="quantity">数量(本):</label>
<input type="text" class="form-control" placeholder="请输入数量" id="quantity" name="quantity" maxlength="4">
</div>
<div class="form-group">
<label for="isbn">ISBN号码:</label>
<input type="text" class="form-control" placeholder="请输入ISBN号码" id="isbn" name="isbn" maxlength="13">
</div>
</form>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-success operate-button"></button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
在 library.js 添加
//表单组件
var book_title = $('#book-modal .modal-title'); //标题栏
var book_form = $('.book-form'); //表单
var operate_button= $('.operate-button'); //添加图书按钮
//添加图书
var add_button = $('.add-button'); //添加按钮
$(add_button).click(function (e) {
e.preventDefault();
book_title.text("添加图书"); //设置标题栏
book_form[0].reset(); //重置表单
operate_button.text("添加"); //设置按钮文本
});
//图书操作
$(operate_button).click(function (e) {
e.preventDefault();
if(book_title.text() == "添加图书"){
addBook(book_form);
}
});
//检查表单函数
function checkForm(){
var group = $('#groups');
var name = $('#name');
var author = $('#author');
var press = $('#press');
var price = $('#price');
var quantity = $('#quantity');
var isbn = $('#isbn');
if(group.val() == '' || group.val() == "" || group.val() == null){
alert("请输入图书组名");
}
else if(name.val() == '' || name.val() == "" || name.val() == null){
alert("请输入图书名称");
}
else if(author.val() == '' || author.val() == "" || author.val() == null){
alert("请输入作者名称");
}
else if(press.val() == '' || press.val() == "" || press.val() == null){
alert("请输入出版社名称");
}
else if(price.val() == '' || price.val() == "" || price.val() == null){
alert("请输入价格(人民币)");
}
else if(quantity.val() == '' || quantity.val() == "" || quantity.val() == null){
alert("请输入数量(本)");
}
else if(isbn.val() == '' || isbn.val() == "" || isbn.val() == null){
alert("请输入ISBN号码");
}
else if(isbn.val().length != 13){
alert("请输入正确的ISBN号码");
}
else{
return true;
}
return false;
}
//添加图书函数
function addBook(book_form){
//判断表单,返回false不能添加,返回true能添加
if(checkForm() != false){
$.ajax({
type: "post",
url: "http://localhost:8181/nav/books/save",
data: book_form.serialize(),
dataType: "json",
success:function(data){
if(data.resultCode == '-1'){
alert("添加失败,服务器错误");
}
if(data.resultCode == '0'){
alert("添加失败,此书已存在");
}
if(data.resultCode == '1'){
alert("添加成功");
window.location.reload();
}
},
error:function(data){
alert("错误");
}
});
}
}
4.编辑图书
在 books.js 添加
//编辑图书
$(document).on('click', '.edit', function (e) {
e.preventDefault();
book_title.text("编辑图书"); //设置标题
book_form[0].reset(); //重置表单
operate_button.text("编辑"); //设置按钮文本
operate_button.attr("name",$(this).attr("name")); //设置id
getBook($(this).attr("name")); //获取图书信息
});
//图书操作
$(operate_button).click(function (e) {
e.preventDefault();
if(book_title.text() == "添加图书"){
addBook(book_form);
}
if(book_title.text() == "编辑图书"){
editBook($(this).attr("name"), book_form);
}
});
//获取图书信息
function getBook(id){
$.ajax({
type: "get",
url: "http://localhost:8181/nav/books/find/" + id,
dataType: "json",
success: function (data) {
$('#groups').val(data.groups);
$('#name').val(data.name);
$('#author').val(data.author);
$('#press').val(data.press);
$('#price').val(data.price);
$('#quantity').val(data.quantity);
$('#isbn').val(data.isbn);
},
error: function (data){
alert("错误");
}
});
}
//编辑图书信息
function editBook(id, book_form){
if(checkForm() == true){
$.ajax({
type: "put",
url: "http://localhost:8181/nav/books/update/" + id,
data: book_form.serialize(),
dataType: "json",
success: function (data) {
if(data.resultCode == "-1"){
alert("修改失败,服务器错误");
}
if(data.resultCode == "0"){
alert("修改失败,要修改的ISBN号码已存在");
}
if(data.resultCode == "1"){
alert("修改成功");
window.location.reload();
}
},
error: function (data) {
alert("错误")
}
});
}
}
5.删除图书
在 books.html 添加一个模态框
<div class="modal fade" id="delete-modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">删除图书</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
<p class="tip"></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger delete-button">删除</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
在 books.js 写入
//删除图书
$(document).on('click', '.delete', function (e) {
e.preventDefault();
$('.delete-button').attr("name",$(this).attr("name")); //设置id
$('.tip').text("确定删除" + $('#' + $(this).attr("name") + '>td[name="name"]').text() + "?");
});
$('.delete-button').click(function (e){
e.preventDefault();
deleteBook($(this).attr("name"));
});
//删除书本函数
function deleteBook(id){
$.ajax({
type: "delete",
url: "http://localhost:8181/nav/books/delete/" + id,
dataType: "json",
success: function (data) {
if(data.resultCode == "-1"){
alert("服务器错误");
}
if(data.resultCode == "1"){
alert("删除成功");
window.location.reload();
}
},
error: function (data){
alert("错误");
}
});
}
2.后端
1.获取图书
在SpringBoot项目创建
类:
BooksHandler -------- 图书操作
Books ------------------- 图书实体
BooksRepository ----- 图书存储库
在 BooksHandler 写入
package com.ksamar.library.controller;
import com.ksamar.library.entity.Books;
import com.ksamar.library.repository.BooksRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;
@RestController
@RequestMapping("/nav") //请求地址
public class BooksHandler {
@Autowired
private BooksRepository booksRepository;
//搜索全部
@GetMapping("/books") //请求地址
public List<Books> findAll() {
return booksRepository.findAll();
}
}
在 Books 写入
package com.ksamar.library.entity;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
@Data
public class Books {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer Id;
private String groups;
private String name;
private String author;
private String press;
private Double price;
private Integer quantity;
private String isbn;
}
在 BooksRepository 写入
package com.ksamar.library.repository;
import com.ksamar.library.entity.Books;
import org.springframework.data.jpa.repository.JpaRepository;
public interface BooksRepository extends JpaRepository<Books,Integer> {
}
2.搜索图书
在 BooksHandler 里添加
//搜索单本图书
@GetMapping("/books/find")
public List<Books> findByNameLike(String book){
return booksRepository.findByNameLike("%" + book + "%");
}
在 BooksRepository 里添加
List<Books> findByNameLike(String book);
3.添加图书
在 BooksHandler 添加
/**
* -1:错误,添加失败
* 0:存在,添加失败
* 1:添加成功
*/
@PostMapping("/books/save")
public Object save(Books books){
List<Books> book1 = booksRepository.findByIsbn(books.getIsbn()); //搜索书籍是否存在
JSONObject jsonObject = new JSONObject(); //创建一个空JSONObject 对象
if(book1.size() == 0){
Books result = booksRepository.save(books); //保存书籍
if(result != null){
jsonObject.put("resultCode","1");
}
else{
jsonObject.put("resultCode","-1");
}
}
else{
jsonObject.put("resultCode","0");
}
return jsonObject;
}
在 BooksReposiitory 添加
List<Books> findByIsbn(String Isbn);
4.编辑图书
在 BooksHandler 添加
/**
* 修改图书
* -1:错误,修改失败
* 0:修改后的isbn存在,修改失败
* 1:修改成功
*/
@PutMapping("/books/update/{id}")
public Object update(Books books){
JSONObject jsonObject = new JSONObject();
List<Books> booksList = booksRepository.findByIsbn(books.getIsbn()); //搜索isbn是否存在
//存在
if(booksList.size() == 1){
int oldId = books.getId(); //获取旧id
int newId = booksList.get(0).getId(); //获取新id
//判断要修改的书的id是否和原来的书id一致
if(oldId == newId){
Books save = booksRepository.save(books);
if(save != null){
jsonObject.put("resultCode","1");
}
else{
jsonObject.put("resultCode","-1");
}
}
else{
jsonObject.put("resultCode","0");
}
}
//不存在
else if(booksList.size() == 0){
booksRepository.save(books);
jsonObject.put("resultCode","1");
}
//其他情况
else{
jsonObject.put("resultCode","0");
}
return jsonObject;
}
5.删除图书
在 Bookshandler 写入
/**
* 删除图书
* -1:删除失败
* 1:删除成功
*/
@DeleteMapping("/books/delete/{id}")
public Object deleteById(@PathVariable("id") Integer Id){
JSONObject jsonObject = new JSONObject();
if(booksRepository.existsById(Id)){
booksRepository.deleteById(Id);
jsonObject.put("resultCode","1");
}
else{
jsonObject.put("resultCode","-1");
}
return jsonObject;
}
3.页面是如何与数据库交互的?
1.获取图书数据
前端通过调用Ajax发送一个get请求到服务端,然后服务端返回一组json数据给Web前端,用JavaScript对json数据进行处理,然后将处理好的数据展示到Web前端
2.搜托图书
与上面方法类似,多添加了一个book的参数,作为查询的书名,后端接收到请求去查询数据库有没有该本书,有则返回书本信息,没有则返回空
3.添加图书
前端发送一个带表单信息post请求到服务端,然后由服务器检测这本书是否存在,如果存在则返回添加失败的Code,如果不存在则发返回添加成功的Code,如果服务器添加书本不成功则返回异常的Code
4.编辑图书
前端先发送一个请求获取该本书的信息 ,然后修改数据后再向服务器发送修改请求,服务器检测id和isbn号码,如果isbn没有变动可以直接修改,如果修改的isbn在数据库里没有则可以直接修改,如果修改新的isbn在数据库中存在,则判断原来的id与数据库搜索出来的isbn图书id是否一致,不一致则修改失败
5.删除图书
前端发送一个带id的删除请求,服务器接受删除请求,判断id是否在数据库中,如果存在就删除,不存在就不删除
五、借阅图书页面
1.前端
在borrow.html里写入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图书管理系统</title>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="/library/css/borrow.css">
</head>
<body>
<div class="main">
<h2>借阅图书</h2>
<div class="search-pane">
<input type="text" name="search-input" id="search-input" class="search-input" maxlength="13" placeholder="请搜索要借阅的图书ISBN号码">
<input type="submit" value="搜索" name="search-button" id="search-button" class="search-button">
</div>
<div class="info-pane">
<div class="book">
<h3>图书信息</h3>
<p>图书名称:<span class="book-name"></span></p>
<p>作者名称: <span class="book-author"></span></p>
<p>出版社名称:<span class="book-press"></span></p>
<p>ISBN号码: <span class="book-isbn"></span></p>
<p>库存(本): <span class="book-quantity"></span></p>
</div>
<div class="user">
<h3>用户信息</h3>
<input type="text" name="username" id="username" class="username" placeholder="借阅人名字">
<input type="text" name="id-card" id="id-card" class="id-card" placeholder="借阅人卡号">
<input type="text" name="phone" id="phone" class="phone" placeholder="借阅人手机号">
<input type="button" name="borrow-button" id="borrow-button" class="btn btn-primary borrow-button" value="借阅图书"></button>
</div>
</div>
</div>
</body>
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdn.staticfile.org/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
<script src="/library/js/config.js"></script>
<script src="/library/js/borrow.js"></script>
</html>
在borrow.css写入
* {
margin: 0;
padding: 0;
outline: none;
}
html,
body,
.main {
width: 100%;
height: 100%;
}
/* 主页面样式 */
.main {
display: flex;
flex-direction: column;
padding: 32px;
justify-content: center;
align-items: center;
}
/* 搜索栏样式 */
.search-pane{
display: flex;
margin-bottom: 32px;
}
.search-pane .search-input{
width: 480px;
height: 38px;
border-radius: 8px 0px 0px 8px;
border: 2px solid #007BFF;
padding-left: 12px;
}
.search-pane .search-button{
width: 70px;
border: transparent;
border-radius: 0px 8px 8px 0px;
background-color: #007BFF;
color: white;
}
/* 信息栏样式 */
.info-pane{
display: flex;
width: 550px;
}
.info-pane div{
display: flex;
width: 50%;
flex-direction: column;
}
.info-pane .user input{
margin-top: 12px;
padding: 4px;
border-radius: 4px;
}
.info-pane .user input[type=text]{
border: 1px solid rgb(77, 77, 77);
}
在borrow.js写入
$(function(){
//搜索图书
var search_button = $(".search-button");
$(search_button).click(function (e) {
e.preventDefault();
var isbn = $(".search-input").val();
if(isbn != '' && isbn != "" && isbn != null){
if(isbn.length == 13){
$.ajax({
type: "get",
url: ip + "/nav/books/find/isbn/" + isbn,
dataType: "json",
success:function(data){
if(!jQuery.isEmptyObject(data)){
$('.book-name').text(data[0].name);
$('.book-author').text(data[0].author);
$('.book-press').text(data[0].press);
$('.book-isbn').text(data[0].isbn);
$('.book-quantity').text(data[0].quantity);
}
else{
alert("查无此书");
}
},
error:function(data){
alert("系统错误");
}
});
}
else{
alert("请输入正确的ISBN号码");
}
}
else{
alert("请输入ISBN号码");
}
});
//借阅图书
var borrow_button = $('.borrow-button');
$(borrow_button).click(function (e) {
e.preventDefault();
var isbn = $('.book-isbn').text();
var username = $('.username').val();
var id_card = $('.id-card').val();
var phone = $('.phone').val();
if(isbn != '' && isbn != "" && isbn != null){
if(username != '' && username != "" && username != null){
if(id_card != '' && id_card != "" && id_card != null){
if(phone != '' && phone != "" && phone != null){
$.ajax({
type: "post",
url: ip + "/nav/books/borrow",
data: {isbn:isbn,username:username,id_card:id_card,phone:phone},
dataType: "json",
success: function (data) {
console.log(data);
if(data.resultCode == "-1"){
alert("借阅失败,系统错误");
}
if(data.resultCode == "0"){
alert("借阅失败,库存不足");
}
if(data.resultCode == "1"){
alert("借阅成功");
window.location.reload();
}
},
error: function (data){
alert("系统错误");
}
});
}
else{
alert("请输入借阅人手机");
}
}
else{
alert("请输入借阅人卡号");
}
}
else{
alert("请输入借阅人名字");
}
}
else{
alert("请先选择书籍!");
}
});
});
2.后端
在BookHandler里写入
//搜索单本图书 ISBN
@GetMapping("/books/find/isbn/{isbn}")
public List<Books> findByIsbn(@PathVariable("isbn") String isbn) {
return booksRepository.findByIsbn(isbn);
}
新建Borrow类,BorrowRepository接口,BorrowHandler类,分别写入
Borrow
package com.ksamar.library.entity;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.sql.Date;
@Entity
@Data
public class Borrow {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer Id;
private String name;
private String isbn;
private String username;
private String id_card;
private String phone;
private Date time;
private Date r_time;
}
BorrowRepository
package com.ksamar.library.repository;
import com.ksamar.library.entity.Borrow;
import org.springframework.data.jpa.repository.JpaRepository;
public interface BorrowRepository extends JpaRepository<Borrow,Integer> {
}
BorrowHandler
package com.ksamar.library.controller;
import com.alibaba.fastjson.JSONObject;
import com.ksamar.library.entity.Books;
import com.ksamar.library.entity.Borrow;
import com.ksamar.library.entity.Users;
import com.ksamar.library.repository.BooksRepository;
import com.ksamar.library.repository.BorrowRepository;
import com.ksamar.library.repository.UsersRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Calendar;
import java.util.List;
@RestController
@RequestMapping("/nav") //请求地址
public class BorrowHandler {
@Autowired
private BooksRepository booksRepository;
@Autowired
private BorrowRepository borrowRepository;
@Autowired
private UsersRepository usersRepository;
/**
* 借阅图书
* -1: 系统错误
* 0: 库存不足
* 1: 借阅成功
*/
@PostMapping("/books/borrow")
public Object bookBorrow(String isbn, String username, String id_card, String phone){
JSONObject jsonObject = new JSONObject();
if(!isbn.equals("") && !username.equals("") && !id_card.equals("") && !phone.equals("")){
List<Books> booksList = booksRepository.findByIsbn(isbn); //搜索图书
//判断有没有书
if(booksList.size() != 0){
Books books = booksList.get(0);
if(books.getQuantity() - 1 >= 0){
books.setQuantity(books.getQuantity() - 1);
Users users = usersRepository.findByPhone(phone); //搜索用户
//判断有没有用户 用户信息是否正确
if(users != null && users.getUsername().equals(username) && users.getId_card().equals(id_card) && users.getPhone().equals(phone)){
TimeZone.setDefault(TimeZone.getTimeZone("GMT")); //设置时区
Calendar calendar = Calendar.getInstance(); //获取时间
Date nowDate; //借阅时间
Date returnDate; //归还时间
nowDate = calendar.getTime(); //借阅时间
calendar.add(Calendar.DATE, 7); //添加时间
returnDate = calendar.getTime(); //归还时间
Borrow borrow = new Borrow();
borrow.setName(books.getName()); //图书名称
borrow.setIsbn(books.getIsbn()); //ISBN号码
borrow.setUsername(users.getUsername()); //借阅人名字
borrow.setId_card(users.getId_card()); //借阅人ID
borrow.setPhone(users.getPhone()); //借阅人手机号
borrow.setTime(nowDate); //设置借阅图书时间
borrow.setR_time(returnDate); //添加归还书本时间
Borrow save = borrowRepository.save(borrow); //保存数据
if(save != null){
jsonObject.put("resultCode","1");
}
else{
jsonObject.put("resultCode","-1");
}
}
else{
jsonObject.put("resultCode","-1");
}
}
else{
jsonObject.put("resultCode","0");
}
}
else{
jsonObject.put("resultCode","0");
}
}
else{
jsonObject.put("resultCode","-1");
}
return jsonObject;
}
3.借阅图书是如何实现的?
前端先发送一个搜索图书的请求,查询这本书是否存在,然后显示图书的信息,然后再填写好借阅人的信息,后端判断借阅人信息是否存在,若都存在,借阅图书成功
六、归还图书页面
1.前端
在return.html里写入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图书管理系统</title>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="/library/css/return.css">
</head>
<body>
<div class="main">
<div class="search-pane">
<input type="text" name="search" id="search" placeholder="请输入搜索的内容">
<button class="btn btn-primary search-button">搜索</button>
</div>
<table class="table table-hover">
<thead>
<tr>
<th>Id</th>
<th>书名</th>
<th>ISBN号码</th>
<th>借阅人名字</th>
<th>借阅人卡号</th>
<th>借阅人手机号</th>
<th>借阅时间</th>
<th>归还时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<!-- 模态框 -->
<div class="modal fade" id="return-modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">归还图书</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
<p class="tip"></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger return-button">归还</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
</body>
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdn.staticfile.org/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
<script src="/library//js/config.js"></script>
<script src="/library/js/return.js"></script>
</html>
在return.css里写入
* {
margin: 0;
padding: 0;
outline: none;
}
html,
body,
.main {
width: 100%;
height: 100%;
}
/* 主页面样式 */
.main {
display: flex;
flex-direction: column;
padding: 32px;
}
.search-pane {
display: flex;
justify-content: center;
width: 100%;
height: 32px;
margin-bottom: 16px;
}
.search-pane button {
margin-right: 32px;
padding: 0;
padding-left: 16px;
padding-right: 16px;
}
.search-pane #search {
width: 400px;
padding-left: 12px;
border: 1px solid #aaa;
border-radius: 4px;
}
在return.js里写入
$(function(){
//获取图书数据
$.ajax({
type: "get", //请求方式
url: ip + "/nav/books/borrow/find", //请求地址
dataType: "json", //返回文件格式
success:function(data){
//添加数据
searchBook(data);
},
error: function(data){
alert("系统错误");
}
});
//搜索图书
var search_button = $('.search-button');
var isbn = $('#search');
$(search_button).click(function (e) {
e.preventDefault();
$.ajax({
type: "get",
url: ip + "/nav/books/borrow/find/" + isbn.val(),
dataType: "json",
success:function(data){
$(".book").remove(); //删除原来的书
searchBook(data); //搜索图书
},
error:function(data){
alert("系统错误");
}
});
});
//归还图书
$(document).on('click', '.return', function (e) {
e.preventDefault();
$('.return-button').attr("name",$(this).attr("name")); //设置id
$('.tip').text("确定归还 " + $('#' + $(this).attr("name") + '>td[name="username"]').text() + " 的 " + $('#' + $(this).attr("name") + '>td[name="name"]').text() + " 书吗?");
});
$('.return-button').click(function (e){
e.preventDefault();
returnBook($(this).attr("name"));
});
});
//显示图书信息函数
function searchBook(data){
for(var i = 0; i < data.length; i++){
var text = "<tr id='" + data[i].id + "' class='book'>" +
"<td name='id'>" + data[i].id + "</td>" +
"<td name='name'>" + data[i].name + "</td>" +
"<td name='isbn'>" + data[i].isbn + "</td>" +
"<td name='username'>" + data[i].username + "</td>" +
"<td name='id_card'>" + data[i].id_card + "</td>" +
"<td name='phone'>" + data[i].phone + "</td>" +
"<td name='time'>" + data[i].time.substr(0,10) + "</td>" +
"<td name='r_time'>" + data[i].r_time.substr(0,10) + "</td>" +
"<td><button class='btn btn-warning btn-sm return' name='" + data[i].id + "' data-toggle='modal' data-target='#return-modal'>归还</button>" +
"</tr>";
$("tbody").append(text);
}
}
//归还书本函数
function returnBook(id){
$.ajax({
type: "delete",
url: ip + "/nav/books/borrow/return/" + id,
dataType: "json",
success: function (data) {
if(data.resultCode == "-1"){
alert("服务器错误");
}
if(data.resultCode == "0"){
alert("归还失败");
}
if(data.resultCode == "1"){
alert("归还成功");
window.location.reload();
}
},
error: function (data){
alert("错误");
}
});
}
2.后端
在BorrowHandler里写入
//搜索图书信息
@GetMapping("/books/borrow/find")
public List<Borrow> findAll() {
return borrowRepository.findAll();
}
//搜索图书信息 ISBN
@GetMapping("/books/borrow/find/{isbn}")
public List<Borrow> findByIsbn(@PathVariable("isbn") String isbn){
return borrowRepository.findByIsbn(isbn);
}
/**
* 归还图书
* -1:系统错误
* 0:归还失败
* 1:归还成功
*/
@DeleteMapping("/books/borrow/return/{id}")
public Object bookReturn(@PathVariable("id") int Id){
JSONObject jsonObject = new JSONObject();;
Borrow borrow = borrowRepository.getById(Id); //获取借阅信息
List<Books> booksList = booksRepository.findByIsbn(borrow.getIsbn()); //获取图书
if(booksList.size() != 0){
//删除信息
if(borrowRepository.existsById(Id)){
borrowRepository.deleteById(Id);
Books books = booksList.get(0); //获取图书信息
books.setQuantity(books.getQuantity() + 1); //图书数量加一
booksRepository.save(books);
jsonObject.put("resultCode","1");
}
else{
jsonObject.put("resultCode","0");
}
}
else{
jsonObject.put("resultCode","-1");
}
return jsonObject;
}
3.归还图书是如何实现的?
获取借阅图书表的信息,点击按钮发送归还请求,后端搜索数据ID,再用搜索出的ISBN号码再搜索图书表的书,归还成功后该书本数量加一
七、超时查询页面
1.前端
在overtime.html写入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图书管理系统</title>
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="/library/css/overtime.css">
</head>
<body>
<div class="main">
<div class="search-pane">
<input type="text" name="search" id="search" placeholder="请输入搜索的内容">
<button class="btn btn-primary search-button">搜索</button>
</div>
<table class="table table-hover">
<thead>
<tr>
<th>Id</th>
<th>书名</th>
<th>ISBN号码</th>
<th>借阅人名字</th>
<th>借阅人卡号</th>
<th>借阅人手机号</th>
<th>借阅时间</th>
<th>归还时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<!-- 模态框 -->
<div class="modal fade" id="return-modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">归还图书</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
<p class="tip"></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger return-button">归还</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
</body>
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdn.staticfile.org/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
<script src="/library//js/config.js"></script>
<script src="/library/js/overtime.js"></script>
</html>
在overtime.css写入
* {
margin: 0;
padding: 0;
outline: none;
}
html,
body,
.main {
width: 100%;
height: 100%;
}
/* 主页面样式 */
.main {
display: flex;
flex-direction: column;
padding: 32px;
}
.search-pane {
display: flex;
justify-content: center;
width: 100%;
height: 32px;
margin-bottom: 16px;
}
.search-pane button {
margin-right: 32px;
padding: 0;
padding-left: 16px;
padding-right: 16px;
}
.search-pane #search {
width: 400px;
padding-left: 12px;
border: 1px solid #aaa;
border-radius: 4px;
}
在overtime.js写入
$(function(){
//获取图书数据
$.ajax({
type: "get", //请求方式
url: ip + "/nav/books/overtime/find/0", //请求地址
dataType: "json", //返回文件格式
success:function(data){
//添加数据
searchBook(data);
},
error: function(data){
alert("系统错误");
}
});
//搜索图书
var search_button = $('.search-button');
var isbn = $('#search');
$(search_button).click(function (e) {
e.preventDefault();
$.ajax({
type: "get",
url: ip + "/nav/books/overtime/find/" + isbn.val(),
dataType: "json",
success:function(data){
$(".book").remove(); //删除原来的书
searchBook(data); //搜索图书
},
error:function(data){
alert("系统错误");
}
});
});
//归还图书
$(document).on('click', '.return', function (e) {
e.preventDefault();
$('.return-button').attr("name",$(this).attr("name")); //设置id
$('.tip').text("确定归还 " + $('#' + $(this).attr("name") + '>td[name="username"]').text() + " 的 " + $('#' + $(this).attr("name") + '>td[name="name"]').text() + " 书吗?");
});
$('.return-button').click(function (e){
e.preventDefault();
returnBook($(this).attr("name"));
});
});
//显示图书信息函数
function searchBook(data){
for(var i = 0; i < data.length; i++){
var text = "<tr id='" + data[i].id + "' class='book'>" +
"<td name='id'>" + data[i].id + "</td>" +
"<td name='name'>" + data[i].name + "</td>" +
"<td name='isbn'>" + data[i].isbn + "</td>" +
"<td name='username'>" + data[i].username + "</td>" +
"<td name='id_card'>" + data[i].id_card + "</td>" +
"<td name='phone'>" + data[i].phone + "</td>" +
"<td name='time'>" + data[i].time.substr(0,10) + "</td>" +
"<td name='r_time'>" + data[i].r_time.substr(0,10) + "</td>" +
"<td><button class='btn btn-warning btn-sm return' name='" + data[i].id + "' data-toggle='modal' data-target='#return-modal'>归还</button>" +
"</tr>";
$("tbody").append(text);
}
}
//归还书本函数
function returnBook(id){
$.ajax({
type: "delete",
url: ip + "/nav/books/borrow/return/" + id,
dataType: "json",
success: function (data) {
if(data.resultCode == "-1"){
alert("服务器错误");
}
if(data.resultCode == "0"){
alert("归还失败");
}
if(data.resultCode == "1"){
alert("归还成功");
window.location.reload();
}
},
error: function (data){
alert("错误");
}
});
}
2.后端
在BorrowHandler写入
//搜索超时信息
@GetMapping("/books/overtime/find/{isbn}")
public List<Borrow> findOverTime(@PathVariable("isbn") String isbn) {
List<Borrow> oldBorrowList;
List<Borrow> borrowList = new ArrayList<>();
TimeZone.setDefault(TimeZone.getTimeZone("GMT")); //设置时区
if(isbn.equals("0")){
oldBorrowList = borrowRepository.findAll(); //获取数据
}
else{
oldBorrowList = borrowRepository.findByIsbn(isbn);
}
//判断表里有没有数据
if(oldBorrowList.size() != 0){
//循环读取数据
for (Borrow borrow : oldBorrowList) {
Calendar calendar = Calendar.getInstance();
if(calendar.getTime().after(borrow.getR_time())){
borrowList.add(borrow); //添加超时归还的数据
}
}
}
return borrowList;
}
3.超时查询是如何实现的?
前端发送搜索请求,后端把表里的数据处理,超过归还时间的书就放到一个列表里然后返回,前端处理数据显示即可
八、用户管理页面
与图书管理页面是一模一样的,这里就不放出来了,在源码里有,想自己写的也可以试试
九、退出登录
1.前端
在library.js写入
//退出系统
$(".exit").click(function (e) {
var exit = $.removeCookie('username', { path: '/' });
if(exit){
window.location.replace("/index.html");
alert("您已退出系统");
}
else{
alert("系统错误");
}
});
2.用户的退出是如何实现的?
前端把Cookie删掉就退出了