图书管理系统

目录

系统开发的步骤

数据库相关

创建数据库与表

引入Mybatis和MySQL依赖

数据库连接

后端

用户相关

图书相关

添加翻页功能

分页插件jqPaginator

设置图书状态(枚举)

设置价格精度       

添加图书

接口定义

前后端实现

测试前后端

修改图书

接口定义

后端代码及测试

前端代码及测试

删除图书

接口定义

实现

批量删除

强制登录

统一功能处理

 登录校验

调整前端

​编辑

实现展示


系统开发的步骤

1.需求确认阶段:需求分析,需求评审

2.开发

  1)方案设计

  2)接口定义

  3)开发业务代码

  4)测试(自测+联调)

3.提测阶段

4.上线(发布阶段)

数据库设计:实体表(用户表、博客表、图书表)、关系表(一对多、多对多)

数据库相关

创建数据库与表

-- 创建数据库
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依赖

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

数据库连接

# 数据库连接配置
spring:
 datasource:
 url: jdbc:mysql://127.0.0.1:3306/book_test?characterEncoding=utf8&useSSL=false
 username: root #数据库用户名
 password: password #密码
 driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
 configuration:
 map-underscore-to-camel-case: true #配置驼峰⾃动转换
 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql语句
# 设置⽇志⽂件的⽂件名
logging:
 file:
 name: spring-book.log

后端

用户相关

UserController

@RequestMapping("/user")
@RestController
public class UserController {
    @Autowired
    public UserService userService;

    @RequestMapping("/login")
    public Boolean login(String userName, String password, HttpSession session){
        //校验参数
        if(!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)) {
            return false;
        }
        //if(userName.equals("admin")){}这种写法会报空指针异常0

        //校验账号密码是否正确
        //1.根据用户名查找用户信息
        UserInfo userInfo=userService.getUserInfoByName(userName);

        //比对密码是否正确
        if(userInfo==null||userInfo.getId()<=0){
            return false;
        }
        if(password.equals(userInfo.getPassword())){
            //账号密码正确
            //存session
            userInfo.setPassword("");
            session.setAttribute("userName",userInfo);
            return true;
        }
        return false;
    }
}

图书相关

添加翻页功能

第一次请求的时候,请求第一页的内容,后端只需要返回第一页的信息即可。翻页可以由后端完成,也可以有前端完成。

前端完成需要一次性拿到所有的数据。

缺点:1)第一次请求响应时间长

           2)数据如果要进行修改,前端无法感知

优点:后续响应快

后端完成,可以避免前端的缺点,但是需要多次请求。(本系统推荐后端,因为数据存在多次修改)

请求第一页的内容,后端只需要返回第一页的信息即可,请求第二页的内容,后端只需要返回第二页的内容。

select * from book_info limit ${offset},${limit}

在图书页添加一些数据以便展示

INSERT INTO `book_info` ( book_name, author, count, price, publish )
VALUES
( '图书2', '作者2', 29, 22.00, '出版社2' ),( '图书3', '作者2', 29, 22.00, '出版社3'),
( '图书4', '作者2', 29, 22.00, '出版社1' ),( '图书5', '作者2', 29, 22.00, '出版社1'),
( '图书6', '作者2', 29, 22.00, '出版社1' ),( '图书7', '作者2', 29, 22.00, '出版社1'),
( '图书8', '作者2', 29, 22.00, '出版社1' ),( '图书9', '作者2', 29, 22.00, '出版社1'),
( '图书10', '作者2', 29, 22.00, '出版社1'),( '图书11', '作者2', 29, 22.00, '出版社1'),
( '图书12', '作者2', 29, 22.00, '出版社1'),( '图书13', '作者2', 29, 22.00, '出版社1'),
( '图书14', '作者2', 29, 22.00, '出版社1'),( '图书15', '作者2', 29, 22.00, '出版社1'),
( '图书16', '作者2', 29, 22.00, '出版社1'),( '图书17', '作者2', 29, 22.00, '出版社1'),
( '图书18', '作者2', 29, 22.00, '出版社1'),( '图书19', '作者2', 29, 22.00, '出版社1'),
( '图书20', '作者2', 29, 22.00, '出版社1'),( '图书21', '作者2', 29, 22.00, '出版社1');

一共24条数据,设计一页展示10条,共三页。第一页返回1-10,第二页返回11-20,第三页返回21-24

通过MySQL语句实现

select * from book_info limit 0,10;
select * from book_info limit 10,10;
select * from book_info limit 20,4;

后端翻页select * from book_info limit ${offset},${limit}

limit就是每一页要显示的条数pageSize

前端需要告知的内容:

1.当前页:currentPage

2.每页显示的条数

后端返回结果:

1.当前页的内容:records

2.后端总条数

分页插件jqPaginator
jqPaginator分页组件icon-default.png?t=N7T8https://jqpaginator.keenwon.com/
$('#id').jqPaginator({
    totalPages: 100,
    visiblePages: 10,
    currentPage: 1,
    onPageChange: function (num, type) {
        $('#text').html('当前第' + num + '页');
    }
});

   前端:  引入此插件的使用:

     

设置图书状态(枚举)

设置价格精度       

添加图书

接口定义

/book/addBook

参数:BookInfo

返回结果:告诉前端是否添加成功

1)Boolean   true:添加成功    false:添加失败

2)String     " " 添加成功,不为空添加失败

3)对象  Boolean result 是否添加成功

               String errorMsg  出错时候的错误原因

这里采用第二种方式:返回字符串

前后端实现
BookInfoMapper.java
 @Insert("insert into book_info (book_name,author,count,price,publish,status)" +
            "values(#{bookName},#{author},#{count},#{price},#{publish},#{status})")
    Integer insertBook(BookInfo bookInfo);
BookController.java
@RequestMapping("/addBook")
    public String addBook(BookInfo bookInfo) {
        log.info("接收到添加图书请求,bookInfo:{}",bookInfo);
        //参数校验
        if (!StringUtils.hasLength(bookInfo.getBookName())
                || !StringUtils.hasLength(bookInfo.getAuthor())
                || bookInfo.getCount() < 0
                || bookInfo.getPrice() == null
                || !StringUtils.hasLength(bookInfo.getPublish())){
            return "参数校验失败,请检查输入";
    }
        Integer result=bookService.addBook(bookInfo);
        if(result<0){
            log.error("添加图书出错:bookInfo:{}",bookInfo);
            return "添加图书出错,请联系管理员";
        }
        return "";
    }
 BookService.java
//添加图书
    public Integer addBook(BookInfo bookInfo){
        Integer result=0;
        try{
            bookInfoMapper.insertBook(bookInfo);

        }catch (Exception e){
            log.error("添加图书出错,e:{}",e);
        }
       return result;
    }

前端book_add.html前后端交互部分

    <script>

        function add() {
            $.ajax({
                type:"post",
                url:"/book/addBook",
                data:$("#addBook").serialize(),//提交整个form表单
                success:function(result){
                    if(result==""){
                        //图书添加成功
                        location.href = "book_list.html";
                    }else{
                        alert(result); 
                    }
                }
            });
        }
    </script>
测试前后端

后端

测试添加图书,使用postman测试:

每次测试前端页面时,记得进入页面看前端代码是否已经修改成最新的。如果没有则按F12再右键网页刷新按键。

再次确认页面代码是否为修改的最新版本。

Fiddlere抓包测试

在线解码工具查看发送的url内容是否正确

修改图书

1.点击修改按钮时,希望把当前图书的信息显示出来

2.点击确定时把修改后的结果进行保存

接口定义

1.查询图书信息,根据id

/book/queryBookInfoById

参数:bookId

返回结果:对应的图书信息 BookInfo

2.修改图书

/book/updateBook

参数:BookInfo

返回结果:是否修改成功(String  " "空为成功。不为空,表示失败,返回错误信息。)

后端代码及测试
BookController.java
 @RequestMapping("/updateBook")
    public String updateBook(BookInfo bookInfo){
        log.info("更新图书,接受到更新图书的请求,bookInfo:{}",bookInfo);
        Integer result=bookService.updateBook(bookInfo);
        if(result==0){
          log.error("更新图书失败,请联系管理员");
          return "更新图书失败,请联系管理员";
        }
        return "";
    }
 BookService.java
public Integer updateBook(BookInfo bookInfo){
        Integer result=0;
        try {
            result=bookInfoMapper.updateBook(bookInfo);
        }catch (Exception e){
            log.error("更新图书失败,e:{}",e);
        }
        return result;
     }
BookInfoMapper.java
 Integer updateBook(BookInfo bookInfo);

使用xml配置文件动态操作数据库

application.properties文件中添加配置

mybatis.mapper-locations= classpath:mapper/**Mapper.xml

resource下建立文件目录结构

BookInfoMapper.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.SpringBookaliyun.mapper.BookInfoMapper">
<!--namespace是对应要操作的Mapper类下的包的路径+该Mapper类-->
</mapper>

BookInfoMapper.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.SpringBookaliyun.mapper.BookInfoMapper">
    <update id="updateBook">
        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>

测试:postman

前端代码及测试

前后端交互部分

 <script>
        $.ajax({
            type:"get",
            url:"/book/queryBookInfoById"+location.search,
            success:function(book){
                if(book!=null){
                    //页面输入框的填充
                    $("#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);
                }else{
                    alert("图书不存在")
                }
            }
        })
        function update() {
            $.ajax({
                type:"post",
                url:"book/updateBook",
                data:$("#updateBook").serialize(),
                success:function(result){
                    if(result==""){
                        location.href="book_list.html";
                    }else{
                        alert(result);
                    }
                }
            });
        }

删除图书

删除的几种方式:

1.物理删除:直接把数据删掉 delete

2.逻辑删除:软删除(假),通过字段标识,标识这个数据被删除掉了

3.物理删除+存档(逻辑删除+存档):存档表中的数据不会消失

实际开发中,删除选择逻辑删除,这里采用比较简单的逻辑删除

接口定义

当采用物理删除时

/book/deleteBook

参数:bookId

返回内容:" "空表示删除成功,不为空表示删除失败,并返回失败的原因。

逻辑删除

接口定义发生变化

book/updateBook

参数:

bookId=

status=0

返回:和updateBook保持一样

" "表示删除成功。不为空则表示删除失败,并返回失败原因

实现

使用update实现删除的逻辑思路:

后端其实已经实现了,就是update的代码,现在只需要完成前端的代码即可。

 function deleteBook(bookId) {
                var isDelete = confirm("确认删除?");
                if (isDelete) {
                    //删除图书
                    $.ajax({
                        type:"post",
                        url:"/book/updateBook",
                        data:{
                            id:bookId,
                            status:0
                        },
                        success:function(result){
                            if(result==""){
                            //删除成功
                            location.href="book_list.html";
                        }else{
                            alert(result);
                        }
                    }
                    });
                    
            }
        }

批量删除

因为采用逻辑删除,所以批量删除就是批量更新

ids:需要批量删除的图书的集合

接口定义:

book/batchDelete

参数:List<Integer> ids

返回结果:" "表示删除成功。不为空则表示删除失败,并返回失败原因

实现

后端

BookController.java

 @RequestMapping("/batchDelete")
    public String batchDelete(@RequestParam List<Integer> ids){
        log.info("接收请求,批量删除图书,图书ID:{}",ids);
       Integer result= bookService.batchDelete(ids);
       if(result<=0){
           log.error("批量删除失败,ids:{}",ids);
           return "批量删除失败,请联系管理员";
       }
      return "";
    }

BookService.java

public Integer batchDelete(List<Integer> ids){
        Integer result=0;
        try{
            result=bookInfoMapper.batchDelete(ids);
        }catch (Exception e){
            log.error("批量删除图书失败,ids:{}",ids);
        }
        return result;
     }

BookInfoMapper.java

Integer batchDelete(List<Integer> ids);

BookInfoMapper.xml

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

前端:

 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({
                        type:"post",
                        url:"book/batchDelete?ids="+ids,
                        success:function(result){
                            if(result==""){
                                //删除成功
                                location.href="book_list.html";
                            }else{
                                alert(result);
                            }
                        }
                    });

强制登录

为了让前端可以看见执行的状态,未登录、登录成功、登录失败。在controller层内写上各自的执行状态,代码会有许多重复的部分。因此我们可以把相同的部分提取成一个类。

@Data
public class Result {
    //业务状态码
    private ResultCode code;//0-成功 -1失败 -2未登录
    //错误信息
    private String errMsg;
    //数据
    private Object data;

    public static Result success(Object data){
        Result result=new Result();
        result.setCode(ResultCode.SUCCESS);
        result.setErrMsg("");
        result.setData(data);
        return result;
    }

    public static Result fail(String errMsg ){
        Result result=new Result();
        result.setCode(ResultCode.FAIL);
        result.setErrMsg(errMsg);
        result.setData(null);
        return result;
    }
    public static Result fail(String errMsg,Object data ){
        Result result=new Result();
        result.setCode(ResultCode.FAIL);
        result.setErrMsg(errMsg);
        result.setData(data);
        return result;
    }

    public static Result unLogin(){
        Result result=new Result();
        result.setCode(ResultCode.UNLOGIN);
        result.setErrMsg("用户未登录");
        result.setData(null);
        return result;
    }
}

同时修改controller中的代码

@Slf4j
@RequestMapping("/book")
@RestController

public class BookController {
    @Autowired
    private BookService bookService;

    @RequestMapping("/getBookListByPage")
    public Result getBookListByPage(PageRequest pageRequest, HttpSession session){
        //用户登录校验
        UserInfo userInfo=(UserInfo) session.getAttribute(Constants.SESSION_USER_KEY);
        if(userInfo==null||userInfo.getId()<=0||"".equals(userInfo.getUserName())){
            //用户未登录
           return Result.unLogin();
        }

        //校验成功
        log.info("查询翻页信息,pageRequest:{}",pageRequest);
        //校验失败
        if(pageRequest.getPageSize()<0 || pageRequest.getCurrentPage()<1){
            return Result.fail("参数校验失败");
        }
        PageResult<BookInfo> bookInfoPageResult=null;
        try {
            bookInfoPageResult= bookService.selectBookInfoByPage(pageRequest);
            return Result.success(bookInfoPageResult);
        }catch (Exception e){
            log.error("查询翻页信息错误,e:{}",e);
           return Result.fail(e.getMessage());
        }
    }

    @RequestMapping("/addBook")
    public String addBook(BookInfo bookInfo) {
        log.info("接收到添加图书请求,bookInfo:{}",bookInfo);
        //参数校验
        if (!StringUtils.hasLength(bookInfo.getBookName())
                || !StringUtils.hasLength(bookInfo.getAuthor())
                || bookInfo.getCount() < 0
                || bookInfo.getPrice() == null
                || !StringUtils.hasLength(bookInfo.getPublish())){
            return "参数校验失败,请检查输入";
    }
        Integer result=bookService.addBook(bookInfo);
        if(result<0){
            log.error("添加图书出错:bookInfo:{}",bookInfo);
            return "添加图书出错,请联系管理员";
        }
        return "";
    }
    @RequestMapping("/queryBookInfoById")
    public BookInfo queryBookInfoById(Integer bookId){
        log.info("根据ID查询图书,bookId:"+bookId);
        try {
            BookInfo bookInfo=bookService.queryBookInfoById(bookId);
            return bookInfo;
        }catch (Exception e){
            log.error("查询图书失败,e:{}",e);
        }
        return null;
    }
    @RequestMapping("/updateBook")
    public String updateBook(BookInfo bookInfo){
        log.info("更新图书,接受到更新图书的请求,bookInfo:{}",bookInfo);
        Integer result=bookService.updateBook(bookInfo);
        if(result==0){
          log.error("更新图书失败,请联系管理员");
          return "更新图书失败,请联系管理员";
        }
        return "";
    }

    @RequestMapping("/batchDelete")
    public String batchDelete(@RequestParam List<Integer> ids){
        log.info("接收请求,批量删除图书,图书ID:{}",ids);
       Integer result= bookService.batchDelete(ids);
       if(result<=0){
           log.error("批量删除失败,ids:{}",ids);
           return "批量删除失败,请联系管理员";
       }
      return "";
    }

}

统一功能处理

 登录校验

通过拦截器完成图书管理系统中的最后一步操作:通过拦截器完成图书管理系统中的登录校验功能。

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册拦截器
        //**表示给所有方法添加拦截器
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/user/login");//排除不进行拦截的

    }
}

把controller中的注册注释掉

拦截器内的工作内容

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("登录拦截器校验...");
        //返回true表示放行,返回false表示拦截
        //用户是否登录

            HttpSession session = request.getSession();
            UserInfo userInfo = (UserInfo) session.getAttribute(Constants.SESSION_USER_KEY);
            if (userInfo != null &&userInfo.getId() >= 0) {
                return true;
            }
            response.setStatus(401);
            return false;
            //401表示未认证登录
        }

        @Override
        public void postHandle (HttpServletRequest request, HttpServletResponse response, Object
        handler, @Nullable ModelAndView modelAndView) throws Exception {
            log.info("目标方法执行后");
        }
    }

以上拦截器只是排除拦截的后端的注册登录代码,这个时候拦截器拦截住了前端页面,此时我们还需要排除前端页面的代码。将所有的前端页面内容放入一个队列中,然后直接排除掉这个队列。

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;
    private static List<String> excludePath = Arrays.asList("/user/login",
            "/css/**",
            "/js/**",
            "/pic/**",
            "/**/*.html");
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册拦截器
        //**表示给所有方法添加拦截器
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")//表示给所有方法都添加拦截器
                .excludePathPatterns(excludePath);

    }
}

调整前端

调整前端代码,把返回的data类型和页面跳转部分进行测试和修改

login.html修改部分

 function login() {
            $.ajax({
                url:"user/login",
                type:"post",
                data:{
                    "userName":$("#userName").val(),
                    "password":$("#password").val()
                },
                success:function(result){
                    console.log(result);
                    if(result!=null&&result.code=="SUCCESS"&&result.data==true){
                       
                        location.href="book_list.html";
                    }else{
                       
                        alert("用户名或密码错误!");
                    }
                }
            })
            location.href = "book_list.html";
        }

book_add.html

 function add() {
            $.ajax({
                type:"post",
                url:"/book/addBook",
                data:$("#addBook").serialize(),//提交整个form表单
                success:function(result){
                    console.log(result);
                    console.log(typeof result);
                    if(result!=null && result.code=="SUCCESS" && result.data==""){
                        //图书添加成功
                        location.href = "book_list.html";
                    }else{
                        alert(result); 
                    }
                }
            });
        }

注意:如果后端返回的结果是String类型,当我们使用统一结果返回时,返回的是JSON字符串,而http请求的content-type是test/html,后端需要进行转换。

否则点击添加按钮时无法跳转到图书页面,而是弹出一个result框。

前端处理的方式:JSON.parse(result)

book_list.html

 function deleteBook(bookId) {
                var isDelete = confirm("确认删除?");
                if (isDelete) {
                    //删除图书
                    $.ajax({
                        type:"post",
                        url:"/book/updateBook",
                        data:{
                            id:bookId,
                            status:0
                        },
                        success:function(result){
                            if(result!=null && result.code=="SUCCESS" && result.data==""){
                            //删除成功
                            location.href="book_list.html";
                        }else{
                            alert(result);
                        }
                    },
                    error:function(error){
                    console.log(error);
                    //用户未登录
                    if(error!==null&&error.status==401){
                        location.href="login.html";
                    }
                    
                }
                    });
                    
            }
        }
            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({
                        type:"post",
                        url:"book/batchDelete?ids="+ids,
                        success:function(result){
                            if(result!=null && result.code=="SUCCESS" && result.data==""){
                                //删除成功
                                location.href="book_list.html";
                            }else{
                                alert(result);
                            }
                        },
                        error:function(error){
                        console.log(error);
                        if(error.status==401){
                            console.log("401");
                            location.href="login.html";
                        }
                    }
                    });
                  
                }
            }

book_update.html

<script>
        $.ajax({
            type:"get",
            url:"/book/queryBookInfoById"+location.search,
            success:function(result){
                if(result!=null && result.code=="SUCCESS"){
                    var book=result.data;
                if(book!=null){
                    //页面输入框的填充
                    $("#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);
                }else{
                    alert("图书不存在")
                }
            }else{
                alert(result.errMsg);
            }
                },
                error:function(error){
                    console.log(error);
                    //用户未登录
                    if(error!==null&&error.status==401){
                        location.href="login.html";
                    }
                    
                }
               
        });
        function update() {
            $.ajax({
                type:"post",
                url:"book/updateBook",
                data:$("#updateBook").serialize(),
                success:function(result){
                    if(result!=null && result.code=="SUCCESS" && result.data==""){
                        location.href="book_list.html"; 
                    }else{
                        alert(result);
                    }
                },
                error:function(error){
                    console.log(error);
                    //用户未登录
                    if(error!==null&&error.status==401){
                        location.href="login.html";
                    }
                    
                }
            });
        }
    </script>

实现展示

登录页

图书列表页

修改图书

添加图书

删除图书

批量删除图书

  • 28
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Roylelele

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值