图书管理系统(持久化存储数据以及增添新功能)

news2024/11/25 2:37:24

目录

一、数据库表设计

二、引入MyBatis 和MySQL 驱动依赖

三、配置数据库 & 日志

四、Model创建

五、枚举类 + 常量类用户登录

六、用户登录

七、添加图书

八、图书列表

九、修改图书

十、删除图书

十一、批量删除

十二、强制登录

十三、前端代码

(1)login.html

(2)book_add.html

(3)book_list.html

(4)book.update.html

十四、测试

(1)登录界面

(2)添加图书

(3)翻页,图书列表

(4)修改图书

(5)删除图书

(6)批量删除图书


        之前写的内容地址:综合性练习(后端代码练习4)——图书管理系统-CSDN博客 ,项目的gitte地址:https://gitee.com/cool_tao6/studying-java-ee-advanced/tree/master/Books_Management_System

一、数据库表设计

        数据库表是应用程序开发中的一个重要环节,数据库表的设计往往会决定我们的应用需求是否能顺利实现,甚至决定我们的实现方式。如何设计表以及这些表有哪些字段,这些表存在哪些关系 也是非常重要的。

        数据库表设计是依据业务需求来设计的。如何设计出优秀的数据库表,与经验有很大关系。

        数据库表通常分为两种:实体表 和 关系表。

        分析我们的需求,图书管理系统相对来说比较简单,只有两个实体:用户和图书,并且用户和图书之间没有关联关系。

        表的具体字段设计,也与需求有关。

        用户表有用户名和密码即可(复杂的业务可能还涉及昵称,年龄等资料)

        图书表有哪些字段,也是参考需求页面(通常不是一个页面决定的,而是要对整个系统进行全面分析观察后定的)。

        创建数据库 book_test,SQL如下:

-- 创建数据库
DROP DATABASE IF EXISTS book_test;

CREATE DATABASE book_test DEFAULT CHARACTER SET utf8mb4;

-- 用户表
DROP TABLE IF EXISTS user_info;
CREATE TABLE user_info (
        `id` INT NOT NULL AUTO_INCREMENT,
        `user_name` VARCHAR ( 128 ) NOT NULL,
        `password` VARCHAR ( 128 ) NOT NULL,
        `delete_flag` TINYINT ( 4 ) NULL DEFAULT 0,
        `create_time` DATETIME DEFAULT now(),
        `update_time` DATETIME DEFAULT now() ON UPDATE now(),
        PRIMARY KEY ( `id` ),
UNIQUE INDEX `user_name_UNIQUE` ( `user_name` ASC )) ENGINE = INNODB DEFAULT CHARACTER 
SET = utf8mb4 COMMENT = '用户表';

-- 图书表
DROP TABLE IF EXISTS book_info;
CREATE TABLE `book_info` (
        `id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
        `book_name` VARCHAR ( 127 ) NOT NULL,
        `author` VARCHAR ( 127 ) NOT NULL,
        `count` INT ( 11 ) NOT NULL,
        `price` DECIMAL (7,2 ) NOT NULL,
        `publish` VARCHAR ( 256 ) NOT NULL,
        `status` TINYINT ( 4 ) DEFAULT 1 COMMENT '0-无效, 1-正常, 2-不允许借阅',
        `create_time` DATETIME DEFAULT now(),
        `update_time` DATETIME DEFAULT now() ON UPDATE now(),
PRIMARY KEY ( `id` ) 
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;

-- 初始化数据
INSERT INTO user_info ( user_name, PASSWORD ) VALUES ( "admin", "admin" );
INSERT INTO user_info ( user_name, PASSWORD ) VALUES ( "zhangsan", "123456" );

-- 初始化图书数据
INSERT INTO `book_info` (book_name,author,count, price, publish) VALUES ('活着', '余华', 29, 22.00, '北京文艺出版社');
INSERT INTO `book_info` (book_name,author,count, price, publish) VALUES ('平凡的世界', '路遥', 5, 98.56, '北京十月文艺出版社');
INSERT INTO `book_info` (book_name,author,count, price, publish) VALUES ('三体', '刘慈欣', 9, 102.67, '重庆出版社');
INSERT INTO `book_info` (book_name,author,count, price, publish) VALUES ('金字塔原理', '麦肯锡', 16, 178.00, '民主与建设出版社');

二、引入MyBatis 和MySQL 驱动依赖

        修改pom.xml文件,内容如下:

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>

        或者使用Edit Starters添加,如图:


三、配置数据库 & 日志

        在properties.yml下添加如下内容:

spring.application.name:
  Books_Management_System

# 数据库连接配置
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
    username: root
    password: 1234
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
  configuration: #配置驼峰自动转换
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true #打印sql语句
  mapper-locations: classpath:mapper/*Mapper.xml

四、Model创建

        BookInfo类 实体书类:

@Data
public class BookInfo {
    private Integer id;
    private String bookName;
    private String author;
    private Integer count;
    private BigDecimal price;
    private String publish;
    private Integer status;//1-可借阅   2-不可借阅
    private String statusCN;
    private Date createTime;
    private Date update_time;
}

        UserInfo类 用户类:

@Data
public class UserInfo {
    private Integer id;
    private String userName;
    private String password;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}

        PageRequest类 查询图书列表 前端发来的请求类:

import lombok.Data;

@Data
public class PageRequest {
    private Integer pageNum = 1;
    private Integer pageSize = 10;
    private Integer offset;

    public Integer getOffset() {
        return (pageNum - 1) * pageSize;
    }
}

        PageResult类 查询图书列表 返回的结果类:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;
@AllArgsConstructor//全参构造函数
@NoArgsConstructor//无参构造函数
@Data
public class PageResult <T>{
    private List<T> records;
    private Integer count;
    private PageRequest pageRequest;
}

        Result类 查询图书列表 返回的结果类(对的PageResult 进行扩展):

import com.example.books_management_system.enums.ResultStatus;
import lombok.Data;

@Data
public class Result <T> {
    private ResultStatus code; //业务码, 200-成功, -2-失败, -1-失败未登录
    private String errMsg; //错误信息,如果业务成功,errMsg为空
    private T data;

    public static <T> Result success(T data) {
        Result<PageResult<BookInfo>> result = new Result<>();
        result.setCode(ResultStatus.SUCCESS);
        result.setData((PageResult<BookInfo>) data);
        return result;
    }

    public static <T> Result nologin() {
        Result<PageResult<BookInfo>> result = new Result<>();
        result.setCode(ResultStatus.NOLOGIN);
        result.setErrMsg("用户未登录");
        result.setData(null);
        return result;
    }

    public static <T> Result fail(String msg) {
        Result<PageResult<BookInfo>> result = new Result<>();
        result.setCode(ResultStatus.FAIL);
        result.setErrMsg(msg);
        return result;
    }

    public static <T> Result fail(ResultStatus resultStatus, String msg) {
        Result<PageResult<BookInfo>> result = new Result<>();
        result.setCode(resultStatus);
        result.setErrMsg(msg);
        return result;
    }
}

五、枚举类 + 常量类用户登录

        BookStatus枚举类 枚举图书的状态(删除、可借阅、不可借阅):

public enum BookStatus {
    DELETE(0, "删除"),
    NORMAL(1, "可借阅"),
    FORBIDDEN(2, "不可借阅")
    ;
    private Integer code;
    private String desc;

    BookStatus(Integer code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    /**
     * 根据code,返回描述信息
     *  其余两种写法:
     * //    public static String getDescByCode2(Integer code) {
     * //        switch (code) {
     * //            case 0: return DELETE.getDesc();
     * //            case 1: return NORMAL.getDesc();
     * //            case 2:
     * //            default:
     * //                return FORBIDDEN.getDesc();
     * //        }
     * //    }
     * //    static Map<Integer, String> map = new HashMap<>();
     * //    public static String getDescByCode3(Integer code) {
     * //        return map.get(code);
     * //    }
     */
    public static BookStatus getDescByCode(Integer code) {
        switch (code) {
            case 0: return DELETE;
            case 1: return NORMAL;
            case 2:
            default:
                return FORBIDDEN;
        }
    }


    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}

        ResultStatus枚举类 枚举返回结果的code(SUCCESS、FAIL、NOLOGIN):

public enum ResultStatus {
    SUCCESS(200),
    FAIL(-1),
    NOLOGIN(-2),
    ;

    private int code;

    ResultStatus(int code) {
        this.code = code;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }
}

        Constant常量类 session的常量值:

public class Constant {
    public static final String USER_SESSION_KEY = "user_session_key";
}

六、用户登录

        UserController类:

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @RequestMapping("/login")
    public String login(String userName, String password, HttpSession session) {
        //1、校验参数
        //2、校验密码是否正确

        //3、返回响应结果
        System.out.println(userName + " " + password);
        if(!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)) {
            return "用户名或者密码为空";
        }

        UserInfo userInfo = userService.getUserInfoByName(userName);

        if(userInfo == null) {
            return "用户不存在";
        }
        if(!password.equals(userInfo.getPassword())) {
            return "密码错误";
        }

        //根据用户名称,去数据库查询用户信息,如果未查询到,说明用户不存在
        //如果查询到用户信息,比对密码是否正确
        //正确的情况
        session.setAttribute(Constant.USER_SESSION_KEY, userInfo);
        return "";
    }
}

        UserService类:

@Service
public class UserService {
    @Autowired
    private UserInfoMapper userInfoMapper;
    public UserInfo getUserInfoByName(String userName) {
        return userInfoMapper.getUserInfoByName(userName);
    }
}

        UserInfoMapper类:

@Mapper
public interface UserInfoMapper {
    @Select("select * from user_info where user_name = #{name} and delete_flag = 0")
    UserInfo getUserInfoByName(String name);
}

七、添加图书

        BookController类:

@Slf4j
@RestController
@RequestMapping("/book")
public class BookController {
    @Autowired
    BookService bookService;

    /**
     * 添加图书
     */
    @RequestMapping("/addBook")
    public String addBook(BookInfo bookInfo) {
        //校验参数
        log.info("添加图书,接收到参数:bookInfo {}", bookInfo);
        if(!StringUtils.hasLength(bookInfo.getBookName())
                || !StringUtils.hasLength(bookInfo.getAuthor())
                || bookInfo.getCount() == null
                || bookInfo.getPrice() == null
                || !StringUtils.hasLength(bookInfo.getPublish())
                || bookInfo.getStatus() == null) {
            return "输入参数不合法";
        }
        //添加图书
        try {
            Integer result = bookService.insertBook(bookInfo);
            if(result > 0) {
                //添加成功
                return "";
            }
        }catch (Exception e) {
            log.error("添加图书异常, e: " +e);
        }

        return "添加失败";
    }
}

        BookService类:

@Slf4j
@Service
public class BookService {
    @Autowired
    BookMapper bookMapper;
    public Integer insertBook(BookInfo bookInfo) {
        return bookMapper.insertBook(bookInfo);
    }
}

         BookMapper类:

@Mapper
public interface BookMapper {
    /**
     * 插入图书
     */
    @Insert("insert into book_info(book_name, author, count, price, publish, `status`) " +
            "values (#{bookName}, #{author}, #{count}, #{price}, #{publish}, #{status})")
    Integer insertBook(BookInfo bookInfo);
}

八、图书列表

        BookController类:

@Slf4j
@RestController
@RequestMapping("/book")
public class BookController {
    @Autowired
    BookService bookService;

    /**
     * 查询图书列表
     */
    @RequestMapping("/getBookListByPage")
    public Result<PageResult<BookInfo>> getBookListByPage(PageRequest pageRequest, HttpSession session) {
        log.info("查询图书的列表, 请求参数pageRequest: {}", pageRequest);
        //从session中获取用户信息
        //如果用户信息为空, 说明用户未登录
        UserInfo loginUserInfo = (UserInfo) session.getAttribute(Constant.USER_SESSION_KEY);
        if(loginUserInfo == null || loginUserInfo.getId() < 0) {
            return Result.nologin();
        }
        //参数校验
        if(pageRequest.getPageNum() == null) {
            //返回默认第一页,如果pageSize也没设置,则会使用默认的10
            pageRequest.setPageNum(1);
        }
        PageResult<BookInfo> bookList = bookService.getBookListByPage(pageRequest);
        return Result.success(bookList);
    }
}

        BookService类:

@Slf4j
@Service
public class BookService {
    @Autowired
    BookMapper bookMapper;
   
    public PageResult<BookInfo> getBookListByPage(PageRequest pageRequest) {
        //1、获取总记录数
        Integer count = bookMapper.count();
        //2、获取当前页的记录
        List<BookInfo> bookInfos = bookMapper.queryBookByPage(pageRequest.getOffset(), pageRequest.getPageSize());
        //3、处理状态
        for(BookInfo bookInfo : bookInfos) {
              bookInfo.setStatusCN(BookStatus.getDescByCode(bookInfo.getStatus()).getDesc());//得到的是枚举类型

//            bookInfo.setStatusCN(BookStatus.getDescByCode3(bookInfo.getStatus()));//hash映射
//            bookInfo.setStatusCN(BookStatus.getDescByCode2(bookInfo.getStatus()));//得到的是字符串

//            if(bookInfo.getStatus() == 2) {
//                bookInfo.setStatusCN("不可借阅");
//            } else {
//                bookInfo.setStatusCN("可借阅");
//            }
        }
        return new PageResult<BookInfo>(bookInfos, count, pageRequest);
    }
}

         BookMapper类:

@Mapper
public interface BookMapper {
    /**
     * 查询列表
     */
    @Select("select * from  book_info where status != 0 order by id desc limit #{offset}, #{limit}")
    List<BookInfo> queryBookByPage(Integer offset, Integer limit);
}

九、修改图书

        BookController类:

@Slf4j
@RestController
@RequestMapping("/book")
public class BookController {
    @Autowired
    BookService bookService;
    /**
     * 更新图书
     */
    @RequestMapping("/updateBook")
    public String updateBook(BookInfo bookInfo) {
        log.info("更新图书, bookInfo: {}", bookInfo);
        try {
            Integer result = bookService.updateBookById(bookInfo);
            if(result > 0) {
                return "";
            }
            return "内部错误, 请练习管理员11111";
        }catch (Exception e) {
            log.error("更新图书失败, e: " + e);
            return "内部错误, 请练习管理员";
        }
    }

    /**
     * 查询图书信息
     * @param bookId
     * @return
     */
    @RequestMapping("/queryBookById")
    public BookInfo queryBookById(Integer bookId) {
        log.info("根据ID查询图书信息, id:" + bookId);
        return bookService.queryBookById(bookId);
    }

}

        BookService类:

@Slf4j
@Service
public class BookService {
    @Autowired
    BookMapper bookMapper;

    public Integer updateBookById(BookInfo bookInfo) {
        log.info("更新图书, bookInfo: {}", bookInfo);
        return bookMapper.updateBookById(bookInfo);
    }

  /**
     * 根据ID查询图书信息
     * @param bookId
     * @return
     */
    public BookInfo queryBookById(Integer bookId) {
        BookInfo bookInfo = bookMapper.queryBookById(bookId);
        bookInfo.setStatusCN(BookStatus.getDescByCode(bookInfo.getStatus()).getDesc());
        return bookInfo;
    }
}

        BookMapper类:

@Mapper
public interface BookMapper {
    /**
     * 更新图书
     */
    Integer updateBookById(BookInfo bookInfo);

    /**
     * 查询图书信息
     */
    @Select("select * from book_info where id = #{bookId}")
    BookInfo queryBookById(Integer bookId);
}

        更新图书的xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.books_management_system.mapper.BookMapper">

    <update id="updateBookById">
        update book_info
        <set>
            <if test="bookName != null">
                book_name = #{bookName},
            </if>
            <if test="author != null">
                author = #{author},
            </if>
            <if test="count != null">
                count = #{count},
            </if>
            <if test="price != null" >
                price = #{price},
            </if>
            <if test="publish != null">
                publish = #{publish},
            </if>
            <if test="status != null">
                status = #{status}
            </if>
        </set>
        where id = #{id}
    </update>

</mapper>

十、删除图书

        BookController类:

@Slf4j
@RestController
@RequestMapping("/book")
public class BookController {
    @Autowired
    BookService bookService;

    /**
     * 删除图书
     */
    @RequestMapping("/deleteBook")
    public String deleteBook(Integer bookId) {
        log.info("删除图书, bookId: {}", bookId);
        try{
            Integer result =  bookService.deleteBookById(bookId);
            if(result > 0) {
                return "";
            }
            return "内部错误, 请练习管理员11111";
        }catch (Exception e) {
            log.error("删除图书失败, e: " + e);
            return "内部错误, 请练习管理员";
        }
    }
}

        BookService类:

@Slf4j
@Service
public class BookService {
    @Autowired
    BookMapper bookMapper;

    /**
     * 删除图书
     */
    public Integer deleteBookById(Integer bookId) {
        log.info("删除图书, bookId: {}", bookId);
        BookInfo bookInfo = new BookInfo();
        bookInfo.setId(bookId);
        bookInfo.setStatus(0);
        return bookMapper.deleteBookById(bookInfo);
    }
}

        BookMapper类:

@Mapper
public interface BookMapper {
    /**
     * 删除图书
     */
    Integer deleteBookById(BookInfo bookInfo);
}

        删除图书的xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.books_management_system.mapper.BookMapper">

    <update id="deleteBookById">
        update book_info
        <set>
            <if test="status != null">
                status = #{status}
            </if>
        </set>
        where id = #{id}
    </update>

</mapper>

十一、批量删除

        BookController类:

@Slf4j
@RestController
@RequestMapping("/book")
public class BookController {
    @Autowired
    BookService bookService;

    /**
     * 批量删除图书
     */
    @RequestMapping("/batchDeleteBook")
    public String batchDeleteBook(@RequestParam List<Integer> ids) {
        log.info("批量删除图书, ids: {}", ids);
        try{
            Integer result = bookService.batchDeleteBookById(ids);
            if(result > 0) {
                return "";
            }
            return "内部错误, 请练习管理员11111";
        }catch (Exception e) {
            log.error("批量删除图书失败, e: " + e);
            return "内部错误, 请练习管理员";
        }
    }
}

        BookService类:

@Slf4j
@Service
public class BookService {
    @Autowired
    BookMapper bookMapper;

    public Integer batchDeleteBookById(List<Integer> ids) {
        return bookMapper.batchDeleteBookByIds(ids);
    }
}

        BookMapper类:

@Mapper
public interface BookMapper {
    /**
     * 批量删除
     */
    Integer batchDeleteBookByIds(List<Integer> ids);
}

        批量删除图书的xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.books_management_system.mapper.BookMapper">

    <delete id="batchDeleteBookByIds">
        update book_info set status = 0
        where id in
        <!--    (1, 2, 3, 4)-->
        <foreach collection="ids" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </delete>

</mapper>

十二、强制登录

        强制登录是指不让用户在没登录的情况下访问某一列表,会使用到session,如果没登录直接访问图书某一列表的url,则让用户跳转到登录界面进行强制登录所以不用这里每一个接口都要增添一个强制登录的功能,但已经写好了代码的接口,逐一添加会耗时好力这里只给 图书列表 接口增添这个功能后面学习了SpringBoot 统一功能处理再解决其他接口,添加强制登录

        图书列表也就是在Controller层进行修改,增添强制登录的功能,和上面图书列表的Controller代码一样:

@Slf4j
@RestController
@RequestMapping("/book")
public class BookController {
    @Autowired
    BookService bookService;

    /**
     * 查询图书列表
     */
    @RequestMapping("/getBookListByPage")
    public Result<PageResult<BookInfo>> getBookListByPage(PageRequest pageRequest, HttpSession session) {
        log.info("查询图书的列表, 请求参数pageRequest: {}", pageRequest);
        //从session中获取用户信息
        //如果用户信息为空, 说明用户未登录
        UserInfo loginUserInfo = (UserInfo) session.getAttribute(Constant.USER_SESSION_KEY);
        if(loginUserInfo == null || loginUserInfo.getId() < 0) {
            return Result.nologin();
        }
        //参数校验
        if(pageRequest.getPageNum() == null) {
            //返回默认第一页,如果pageSize也没设置,则会使用默认的10
            pageRequest.setPageNum(1);
        }
        PageResult<BookInfo> bookList = bookService.getBookListByPage(pageRequest);
        return Result.success(bookList);
    }
}

十三、前端代码

(1)login.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <link rel="stylesheet" href="css/login.css">
    <script type="text/javascript" src="js/jquery.min.js"></script>
</head>

<body>
    <div class="container-login">
        <div class="container-pic">
            <img src="pic/computer.png" width="350px">
        </div>
        <div class="login-dialog">
            <h3>登陆</h3>
            <div class="row">
                <span>用户名</span>
                <input type="text" name="userName" id="userName" class="form-control">
            </div>
            <div class="row">
                <span>密码</span>
                <input type="password" name="password" id="password" class="form-control">
            </div>
            <div class="row">
                <button type="button" class="btn btn-info btn-lg" onclick="login()">登录</button>
            </div>
        </div>
    </div>
    <script src="js/jquery.min.js"></script>
    <script>

        function login() {
            var userName = $("#userName").val();
            var password = $("#password").val();
            $.ajax({
                url: "/user/login",
                type: "post",
                data: {
                    userName: $("#userName").val(),
                    password: $("#password").val()
                },
                success: function(result) {
                    if(result == "") {
                    location.href = "book_list.html?pageNum=1";
                    } else{
                        alert(result);
                    }
                }
            });
        }
    </script>
</body>

</html>

(2)book_add.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>添加图书</title>
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <link rel="stylesheet" href="css/add.css">

</head>

<body>

    <div class="container">

        <div class="form-inline">
            <h2 style="text-align: left; margin-left: 10px;"><svg xmlns="http://www.w3.org/2000/svg" width="40"
                    fill="#17a2b8" class="bi bi-book-half" viewBox="0 0 16 16">
                    <path
                        d="M8.5 2.687c.654-.689 1.782-.886 3.112-.752 1.234.124 2.503.523 3.388.893v9.923c-.918-.35-2.107-.692-3.287-.81-1.094-.111-2.278-.039-3.213.492V2.687zM8 1.783C7.015.936 5.587.81 4.287.94c-1.514.153-3.042.672-3.994 1.105A.5.5 0 0 0 0 2.5v11a.5.5 0 0 0 .707.455c.882-.4 2.303-.881 3.68-1.02 1.409-.142 2.59.087 3.223.877a.5.5 0 0 0 .78 0c.633-.79 1.814-1.019 3.222-.877 1.378.139 2.8.62 3.681 1.02A.5.5 0 0 0 16 13.5v-11a.5.5 0 0 0-.293-.455c-.952-.433-2.48-.952-3.994-1.105C10.413.809 8.985.936 8 1.783z" />
                </svg>
                <span>添加图书</span>
            </h2>
        </div>

        <form id="addBook">
            <div class="form-group">
                <label for="bookName">图书名称:</label>
                <input type="text" class="form-control" placeholder="请输入图书名称" id="bookName" name="bookName">
            </div>
            <div class="form-group">
                <label for="bookAuthor">图书作者</label>
                <input type="text" class="form-control" placeholder="请输入图书作者" id="bookAuthor" name="author" />
            </div>
            <div class="form-group">
                <label for="bookStock">图书库存</label>
                <input type="text" class="form-control" placeholder="请输入图书库存" id="bookStock" name="count"/>
            </div>

            <div class="form-group">
                <label for="bookPrice">图书定价:</label>
                <input type="number" class="form-control" placeholder="请输入价格" id="bookPrice" name="price">
            </div>

            <div class="form-group">
                <label for="bookPublisher">出版社</label>
                <input type="text" id="bookPublisher" class="form-control" placeholder="请输入图书出版社" name="publish" />
            </div>
            <div class="form-group">
                <label for="bookStatus">图书状态</label>
                <select class="custom-select" id="bookStatus" name="status">
                    <option value="1" selected>可借阅</option>
                    <option value="2">不可借阅</option>
                </select>
            </div>

            <div class="form-group" style="text-align: right">
                <button type="button" class="btn btn-info btn-lg" onclick="add()">确定</button>
                <button type="button" class="btn btn-secondary btn-lg" onclick="javascript:history.back()">返回</button>
            </div>
        </form>
    </div>
    <script type="text/javascript" src="js/jquery.min.js"></script>
    <script>
        function add() {
            $.ajax({
                url: "/book/addBook",
                type: "post",
                data: $("#addBook").serialize(),
                success: function(result) {
                    if(result == "") {
                        //添加成功
                        location.href = "book_list.html";
                    } else {
                        alert(result);
                    }
                }
            })
        }
    </script>
</body>

</html>

(3)book_list.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>图书列表展示</title>
    <link rel="stylesheet" href="css/bootstrap.min.css">

    <link rel="stylesheet" href="css/list.css">
    <script type="text/javascript" src="js/jquery.min.js"></script>
    <script type="text/javascript" src="js/bootstrap.min.js"></script>
    <script src="js/jq-paginator.js"></script>

</head>

<body>
    <div class="bookContainer">
        <h2>图书列表展示</h2>
        <div class="navbar-justify-between">
            <div>
                <button class="btn btn-outline-info" type="button" onclick="location.href='book_add.html'">添加图书</button>
                <button class="btn btn-outline-info" type="button" onclick="batchDelete()">批量删除</button>
            </div>
        </div>

        <table>
            <thead>
                <tr>
                    <td>选择</td>
                    <td class="width100">图书ID</td>
                    <td>书名</td>
                    <td>作者</td>
                    <td>数量</td>
                    <td>定价</td>
                    <td>出版社</td>
                    <td>状态</td>
                    <td class="width200">操作</td>
                </tr>
            </thead>
            <tbody>

            </tbody>
        </table>

        <div class="demo">
            <ul id="pageContainer" class="pagination justify-content-center"></ul>
        </div>
        <script>

            getBookList();
            function getBookList() {
                $.ajax({
                    url: "/book/getBookListByPage" + location.search,
                    type: "get",
                    success: function (result) {
                        if (result.code == "NOLOGIN") {//用户登录
                            location.href = "login.html";
                        }

                        if (result.data != null && result.data.records != null) {
                            console.log("拿到参数")
                            var finalHtml = "";
                            for (book of result.data.records) {
                                finalHtml += '<tr>';
                                finalHtml += '<td><input type="checkbox" name="selectBook" value="' + book.id + '" id="' + book.id + '" class="book-select"></td>'
                                finalHtml += '<td>' + book.id + '</td>';
                                finalHtml += '<td>' + book.bookName + '</td>';
                                finalHtml += '<td>' + book.author + '</td>';
                                finalHtml += '<td>' + book.count + '</td>';
                                finalHtml += '<td>' + book.price + '</td>';
                                finalHtml += '<td>' + book.publish + '</td>';
                                finalHtml += '<td>' + book.statusCN + '</td>';
                                finalHtml += '<td>';
                                finalHtml += '<div class="op">';
                                finalHtml += '<a href="book_update.html?bookId=' + book.id + '">修改</a>';
                                finalHtml += '<a href="javascript:void(0)" onclick="deleteBook(' + book.id + ')">删除</a>';
                                finalHtml += '</div>';
                                finalHtml += '</td>';
                                finalHtml += '</tr>';
                            }
                            $("tbody").html(finalHtml);

                            var data = result.data;
                            //翻页信息
                            $("#pageContainer").jqPaginator({
                                totalCounts: data.count, //总记录数
                                pageSize: 10,    //每页的个数
                                visiblePages: 5, //可视页数
                                currentPage: data.pageRequest.pageNum,  //当前页码
                                first: '<li class="page-item"><a class="page-link">首页</a></li>',
                                prev: '<li class="page-item"><a class="page-link" href="javascript:void(0);">上一页<\/a><\/li>',
                                next: '<li class="page-item"><a class="page-link" href="javascript:void(0);">下一页<\/a><\/li>',
                                last: '<li class="page-item"><a class="page-link" href="javascript:void(0);">最后一页<\/a><\/li>',
                                page: '<li class="page-item"><a class="page-link" href="javascript:void(0);">{{page}}<\/a><\/li>',
                                //页面初始化和页码点击时都会执行
                                onPageChange: function (page, type) {
                                    console.log("第" + page + "页, 类型:" + type);
                                    if (type == "change") {
                                        location.href = "book_list.html?pageNum=" + page;
                                    }
                                }
                            });
                        }
                    }
                });
            }

            function deleteBook(id) {
                var isDelete = confirm("确认删除?");
                if (isDelete) {
                    //删除图书
                    $.ajax({
                        url: "/book/deleteBook",
                        type: "post",
                        data: {
                            bookId: id
                        },
                        success: function (result) {
                            if (result == "") {
                                // location.href = "book_list.html" + location.search;
                                location.href = "book_list.html";
                            } else {
                                alert(result);
                            }
                        }
                    });
                    // alert("删除成功");
                }
            }
            function batchDelete() {
                var isDelete = confirm("确认批量删除?");
                if (isDelete) {
                    //获取复选框的id
                    var ids = [];
                    $("input:checkbox[name='selectBook']:checked").each(function () {
                        ids.push($(this).val());
                    });
                    console.log(ids);
                    $.ajax({
                        url: "/book/batchDeleteBook?ids=" + ids,
                        type: "post",
                        success: function (result) {
                            if (result == "") {
                                //删除成功
                                location.href = "book_list.html";
                            } else {
                                alert(result);
                            }
                        }
                    });
                    // alert("批量删除成功");
                }
            }

        </script>
    </div>
</body>

</html>

(4)book.update.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>修改图书</title>
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <link rel="stylesheet" href="css/add.css">
</head>

<body>

    <div class="container">
        <div class="form-inline">
            <h2 style="text-align: left; margin-left: 10px;"><svg xmlns="http://www.w3.org/2000/svg" width="40"
                    fill="#17a2b8" class="bi bi-book-half" viewBox="0 0 16 16">
                    <path
                        d="M8.5 2.687c.654-.689 1.782-.886 3.112-.752 1.234.124 2.503.523 3.388.893v9.923c-.918-.35-2.107-.692-3.287-.81-1.094-.111-2.278-.039-3.213.492V2.687zM8 1.783C7.015.936 5.587.81 4.287.94c-1.514.153-3.042.672-3.994 1.105A.5.5 0 0 0 0 2.5v11a.5.5 0 0 0 .707.455c.882-.4 2.303-.881 3.68-1.02 1.409-.142 2.59.087 3.223.877a.5.5 0 0 0 .78 0c.633-.79 1.814-1.019 3.222-.877 1.378.139 2.8.62 3.681 1.02A.5.5 0 0 0 16 13.5v-11a.5.5 0 0 0-.293-.455c-.952-.433-2.48-.952-3.994-1.105C10.413.809 8.985.936 8 1.783z" />
                </svg>
                <span>修改图书</span>
            </h2>
        </div>

        <form id="updateBook">
            <input type="hidden" class="form-control" id="bookId" name="id">
            <div class="form-group">
                <label for="bookName">图书名称:</label>
                <input type="text" class="form-control" id="bookName" name="bookName">
            </div>
            <div class="form-group">
                <label for="bookAuthor">图书作者</label>
                <input type="text" class="form-control" id="bookAuthor" name="author"/>
            </div>
            <div class="form-group">
                <label for="bookStock">图书库存</label>
                <input type="text" class="form-control" id="bookStock" name="count"/>
            </div>
            <div class="form-group">
                <label for="bookPrice">图书定价:</label>
                <input type="number" class="form-control" id="bookPrice" name="price">
            </div>
            <div class="form-group">
                <label for="bookPublisher">出版社</label>
                <input type="text" id="bookPublisher" class="form-control" name="publish"/>
            </div>
            <div class="form-group">
                <label for="bookStatus">图书状态</label>
                <select class="custom-select" id="bookStatus" name="status">
                    <option value="1" selected>可借阅</option>
                    <option value="2">不可借阅</option>
                </select>
            </div>
            <div class="form-group" style="text-align: right">
                <button type="button" class="btn btn-info btn-lg" onclick="update()">确定</button>
                <button type="button" class="btn btn-secondary btn-lg" onclick="javascript:history.back()">返回</button>
            </div>
        </form>
    </div>
    <script type="text/javascript" src="js/jquery.min.js"></script>
    <script>
        $.ajax({
            url: "/book/queryBookById" + location.search,
            type: "get",
            success: function(book) {
                $("#bookId").val(book.id);
                $("#bookName").val(book.bookName);
                $("#bookAuthor").val(book.author);
                $("#bookStock").val(book.count);
                $("#bookPrice").val(book.price);
                $("#bookPublisher").val(book.publish);
                $("#bookStatus").val(book.status)
            }
        });

        function update() {
            $.ajax({
                url: "/book/updateBook",
                type: "post",
                data: $("#updateBook").serialize(),
                success: function(result) {
                    if(result == "") {
                        //更新成功
                        location.href = "book_list.html";
                    } else{
                        alert(result);
                    }
                }
            })
            // alert("更新成功");
            // location.href = "book_list.html"
        }
    </script>
</body>

</html>

十四、测试

(1)登录界面

        输入URL:http://127.0.0.1:8080/login.html

        不输入密码:

        输入错误密码:

        输入正确用户名、密码:

        登录成功,跳转到下面界面:

(2)添加图书

        不安规定,少输入信息进行添加,会出现下面结果:

        正确添加图书:

        多出现了刚刚添加的图书信息

        数据库内容:

(3)翻页,图书列表

        第一页:

        第二页:

(4)修改图书

        点击确定,成功修改:

        数据库内容:

(5)删除图书

        点击确定,删除成功:

        数据库内容:

(6)批量删除图书

        勾选图书ID为19、18、17、16、15

        点击批量删除,结果如下:

        数据库内容:

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

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

相关文章

【C语言】bool 关键字

在C语言中&#xff0c;bool类型用于表示布尔值&#xff0c;即真或假。C语言本身在标准库中并未提供布尔类型&#xff0c;直到C99标准引入了stdbool.h头文件。该头文件定义了bool类型&#xff0c;以及两个常量&#xff1a;true和false。在此之前&#xff0c;通常使用整数来表示布…

6.8应用进程跨网络通信

《计算机网络》第7版&#xff0c;谢希仁 理解socket通信

初入Node.js必备知识

Node.js因什么而生&#xff0c;作用是干什么&#xff1f; Node.js是一个用c和c打造的一个引擎&#xff0c;他能够读懂JavaScript&#xff0c;并且让JavaScript能够和操作系统打交道的能力 JavaScript 原本只能在浏览器中运行,但随着Web应用程序越来越复杂,仅靠客户端JavaScri…

35 智能指针

目录 为什么需要智能指针&#xff1f;内存泄露智能指针的使用及原理c11和boost中智能指针的关系RAII扩展学习 1. 为什么需要智能指针&#xff1f; 下面我们先分析一下下面这段程序有没有什么内存方面的问题&#xff1f; int div() {int a, b;cin >> a >> b;if (…

AutoPSA的应力加强系数

GD2000里的直连三通的应力加强系数是错误的&#xff0c;建议用户删除再使用。 当应力加强系数为空的时候&#xff0c;psa是会自已计算应力加强系数&#xff1b;当用户填了加强系数&#xff0c;软件就优先用填了的加强系数&#xff1b; 直连三通和假三通的作用一样&#xff0c…

JAVA医院绩效考核系统源码:绩效考核的重要性、绩效管理分配实践具体实操,基于B/S架构开发的一套(公立医院绩效考核系统源码)

JAVA医院绩效考核系统源码&#xff1a;绩效考核的重要性、绩效管理分配实践具体实操&#xff0c;基于B/S架构开发的一套&#xff08;公立医院绩效考核系统源码&#xff09; 系统开发环境 开发语言&#xff1a;java 技术架构&#xff1a;B/S架构 开发工具&#xff1a;maven、…

C++基础(五):类和对象(上)

从今天开始&#xff0c;我们正式进入面向对象编程&#xff0c;这是C与C语言的重要区别&#xff0c;编程思想发生变化&#xff0c;那到底什么是面向对象编程呢&#xff1f;接下来&#xff0c;我们慢慢的深入学习。 目录 一、面向过程和面向对象初步认识 1.1 面向过程 1.2 面…

[激光原理与应用-97]:激光焊接焊中检测系统系列介绍 - 1 - 什么是焊接以及传统的焊接方法

目录 一、什么是焊接 1.1 概述 1.2 基本原理 二、传统的焊接技术与方法 2.1 手工电弧焊&#xff1a; 1、定义与原理 2、特点 3、焊条类型 4、应用领域 5、安全注意事项 2.2 气体保护焊&#xff1a; 1、原理与特点 2、应用领域 3、气体选择 4、注意事项 2.3 电阻…

Zabbix 配置PING监控

Zabbix PING监控介绍 如果需要判断机房的网络或者主机是否正常&#xff0c;这就需要使用zabbix ping&#xff0c;Zabbix使用外部命令fping处理ICMP ping的请求&#xff0c;在基于ubuntu APT方式安装zabbix后默认已存在fping程序。另外zabinx_server配置文件参数FpingLocation默…

layui中添加上下文提示弹窗

<p context-tip"自定义上下文提示信息">段落内容...</p> <div context-tip"自定义上下文提示信息">div内容...</div>// 悬浮提示 $("body").on("mouseenter", "*[context-tip]", function () {v…

清华 PowerPaint:多功能局部重绘模型

PowerPaint 是清华和上海人工智能实验室推出的一个开源高质量多功能的图像修补模型&#xff0c;同时支持插入物体、移除物体、图像扩展、形状可控的物体生成功能。 可以在 清华 PowerPaint&#xff1a;多功能局部重绘模型

【大语言模型系列之Transformer】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

关键词搜索商品API的工作原理是什么?

关键词搜索商品API的工作原理基于复杂的数据处理和检索机制&#xff0c;通过爬虫抓取、数据预处理、数据索引等流程。 在网上购物成为日常生活的一部分&#xff0c;关键词搜索商品API成为了电子商务平台不可或缺的功能。通过这种API&#xff0c;消费者可以轻松地通过输入关键字…

南京观海微电子----AC/DC、DC/DC转换器知识

什么是AC&#xff1f; Alternating Current&#xff08;交流&#xff09;的首字母缩写。 AC是大小和极性&#xff08;方向&#xff09;随时间呈周期性变化的电流。 电流极性在1秒内的变化次数被称为频率&#xff0c;以Hz为单位表示。 什么是DC? Direct Current&#xff08;直流…

微深节能 煤码头自动化翻堆及取料集控系统 格雷母线

微深节能格雷母线高精度位移测量系统是一种先进的工业自动化位置检测解决方案&#xff0c;它被广泛应用于煤码头自动化翻堆及取料集控系统中&#xff0c;以实现对斗轮堆取料机等大型机械设备的精准定位和自动化控制。 系统原理简述&#xff1a; 格雷母线系统的工作原理基于电磁…

通过一个单相逆变器仿真深度学习PR控制器

目录 前言 ​编辑 PR控制器的理论 PR控制器不同表达式及其建模 PR控制器连续积分组合及模型 PR控制器连续传递函数及模型 PR控制器离散积分及模型 PR控制器离散传递函数及模型 PR控制器差分方程及模型 系统仿真效果 总结 前言 在项目开发中常用PI控制器&#xff0c;这次在…

【CT】LeetCode手撕—148. 排序链表

目录 题目1- 思路2- 实现⭐148. 排序链表——题解思路 3- ACM 实现 题目 原题连接&#xff1a;148. 排序链表 1- 思路 排序链表&#xff0c;将每个元素看做一个单独的链表 ——> 归并排序 ——> 每次将单独的链表合并 2- 实现 ⭐148. 排序链表——题解思路 class Solu…

成人高考本科何时报名-深职训学校帮您规划学习之路

你有想过继续深造自己的学历吗&#xff1f;也许你已经工作多年&#xff0c;但总觉得学历是一块心病&#xff0c;想要通过成人高考本科来提升自己。不用着急&#xff0c;今天我们来聊一聊成人高考本科的报名时间&#xff0c;以及深职训学校如何帮助你顺利完成报名。 深圳成人高…

若依前后端分离 前端路由登录页 如何进行跳转

路由守卫&#xff0c;看这篇文章 http://t.csdnimg.cn/HkypThttp://t.csdnimg.cn/HkypT

昇思25天学习打卡营第06天 | 网络构建

昇思25天学习打卡营第06天 | 网络构建 文章目录 昇思25天学习打卡营第06天 | 网络构建定义网络网络层模型预测 模型参数总结打卡 神经网络模型是由神经网络层和对Tensor的操作构成的。 在MindSpore&#xff0c; Cell类是网络的基本单元。一个神经网络模型表示为一个 Cell&…