From b9563ad43e2b75a8dfdd57fd73fa2f4049d74978 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 16 Jul 2020 10:45:39 +0800 Subject: [PATCH 01/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9readme=E6=8F=8F?= =?UTF-8?q?=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index e49b6e5..c15eec7 100644 --- a/README.md +++ b/README.md @@ -4,20 +4,34 @@ 图书管理系统 #### 软件架构 -软件架构说明 +软件架构说明: +后端: +- 基础框架: SpringBoot +- 简单数据操作: Spring Data Jpa +- 复杂数据操作: Mybatis +- 模板引擎: Thymeleaf +- API文档&测试: Swagger2 + +前端: +- javaEx, 其实就是对html,css,js的封装, 很简单, 10分钟就能上手。比较接近原生 +修改起来比较方便, 所以就用了。想了解的, 百度JavaEx即可 + +#### 如果有定制需求, 可以联系作者 +- 质量保证, 从高大上到原生, 你要的我都有 #### 安装教程 -1. xxxx -2. xxxx -3. xxxx +1. 本地搭建好java8环境, 克隆项目 +2. 配置maven +3. 启动访问http://localhost:8080 即可 +4. 默认登录: admin/123 #### 使用说明 -1. xxxx -2. xxxx -3. xxxx +1. 本项目适用于大学生实训, 或者个人学习使用 +2. 不要说为啥这个项目这个东西没加, 哪个东西没加, 针对的层次不一样, 要求也不一样 +3. 很多我也想加, 但是复杂起来了, 不适合目标人群使用 #### 参与贡献 @@ -25,6 +39,7 @@ 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request +5. 等待审核 #### 码云特技 -- Gitee From b5ca0ba5bc211ce2f2f7ad6e382bab08ffd5acdd Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 16 Jul 2020 19:25:01 +0800 Subject: [PATCH 02/21] =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=BC=80=E5=8F=91=E5=AE=8C=E6=88=90,=20?= =?UTF-8?q?=E6=9A=82=E6=97=B6=E6=B3=A8=E9=87=8A=E6=8B=A6=E6=88=AA,=20?= =?UTF-8?q?=E6=8F=90=E5=8D=87=E5=BC=80=E5=8F=91=E6=95=88=E7=8E=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../manager/controller/LoginController.java | 47 +++++++++++++++++++ .../manager/controller/RouteController.java | 4 +- .../book/manager/repos/UsersRepository.java | 7 +++ .../com/book/manager/service/UserService.java | 5 ++ .../com/book/manager/util/http/CodeEnum.java | 2 + src/main/resources/templates/index.html | 7 ++- src/main/resources/templates/login.html | 42 +++++++++++++---- 7 files changed, 101 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/book/manager/controller/LoginController.java diff --git a/src/main/java/com/book/manager/controller/LoginController.java b/src/main/java/com/book/manager/controller/LoginController.java new file mode 100644 index 0000000..beaf37f --- /dev/null +++ b/src/main/java/com/book/manager/controller/LoginController.java @@ -0,0 +1,47 @@ +package com.book.manager.controller; + +import cn.hutool.core.util.StrUtil; +import com.book.manager.entity.Users; +import com.book.manager.service.UserService; +import com.book.manager.util.R; +import com.book.manager.util.http.CodeEnum; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @Description TODO + * @Date 2020/7/16 15:50 + * @Author by 尘心 + */ +@Controller +public class LoginController { + + @Autowired + private UserService userService; + + /** + * 登录 + */ + @ResponseBody + @RequestMapping("/user/login") + public R login(HttpServletRequest request, HttpServletResponse response) throws IOException { + String username = request.getParameter("username"); + String password = request.getParameter("password"); + + if (StrUtil.isNotBlank(username)&&StrUtil.isNotBlank(password)) { + Users users = userService. login(username, password); + if (users!=null) { + request.getSession().setAttribute("username",username); + return R.success(CodeEnum.SUCCESS); + } + } + + return R.fail(CodeEnum.NAME_OR_PASS_ERROR); + } +} diff --git a/src/main/java/com/book/manager/controller/RouteController.java b/src/main/java/com/book/manager/controller/RouteController.java index b5d56ea..2ee5958 100644 --- a/src/main/java/com/book/manager/controller/RouteController.java +++ b/src/main/java/com/book/manager/controller/RouteController.java @@ -15,7 +15,7 @@ public class RouteController { /** * 跳转登录 */ - @RequestMapping({"/login","/"}) + @RequestMapping({"/login","/","logout"}) public String toLogin() { return "login"; } @@ -29,7 +29,7 @@ public class RouteController { } /** - * 跳转首页 + * 跳转欢迎页面 */ @RequestMapping({"/welcome"}) public String toWelcome() { diff --git a/src/main/java/com/book/manager/repos/UsersRepository.java b/src/main/java/com/book/manager/repos/UsersRepository.java index 557d877..15590d8 100644 --- a/src/main/java/com/book/manager/repos/UsersRepository.java +++ b/src/main/java/com/book/manager/repos/UsersRepository.java @@ -26,4 +26,11 @@ public interface UsersRepository extends JpaRepository{ */ @Query(value="select * from users where username like CONCAT('%',:keyword,'%') limit ",nativeQuery=true) Page findByUsernameLike(@Param(value = "keyword") String keyword,Pageable pageable); + + /** + * 用户登录 + * @param username 用户名 + * @param password 密码 + */ + Users findByUsernameAndPassword(@Param("username") String username,@Param("password") String password); } diff --git a/src/main/java/com/book/manager/service/UserService.java b/src/main/java/com/book/manager/service/UserService.java index db89367..296da87 100644 --- a/src/main/java/com/book/manager/service/UserService.java +++ b/src/main/java/com/book/manager/service/UserService.java @@ -39,6 +39,11 @@ public class UserService { return usersRepository.findByUsernameLike(keyword,pageable); } + public Users login(String username,String password) { + return usersRepository.findByUsernameAndPassword(username,password); + } + + /** * 添加用户 * @param users 用户 diff --git a/src/main/java/com/book/manager/util/http/CodeEnum.java b/src/main/java/com/book/manager/util/http/CodeEnum.java index 56746a3..5bc68a4 100644 --- a/src/main/java/com/book/manager/util/http/CodeEnum.java +++ b/src/main/java/com/book/manager/util/http/CodeEnum.java @@ -12,6 +12,8 @@ public enum CodeEnum { NOT_FOUND(404,"找不到资源!"), /** 请求参数错误 */ PARAM_ERROR(444,"请求参数错误!"), + /** 用户名或密码错误 */ + NAME_OR_PASS_ERROR(445,"用户名或密码错误!"), /** 服务器发生异常 */ FAIL(500,"服务器发生异常!"); diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 133995b..5a4cd52 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -34,7 +34,7 @@
  • 欢迎您,管理员
  • @@ -125,5 +125,10 @@ function page(url) { $("#page").attr("src", url); } + + $(document).ready(function(){ + // 页面一加载, 读取登录用户信息 + + }); \ No newline at end of file diff --git a/src/main/resources/templates/login.html b/src/main/resources/templates/login.html index 6c1c63c..03121d4 100644 --- a/src/main/resources/templates/login.html +++ b/src/main/resources/templates/login.html @@ -3,21 +3,21 @@ - + - + - + - + - + - + - + - + 后台管理 + + + +
    + +
    + + + + +
    +
    + +
    +
    *

    书名

    +
    + +
    +
    + +
    +
    *

    ISBN编号

    +
    + +
    +
    + +
    +
    *

    作者

    +
    + +
    +
    + + +
    +

    图书分类

    +
    + + +
    +
    + +
    +

    页数

    +
    + +
    +
    + +
    +

    定价

    +
    + +
    +
    + +
    +

    出版时间

    +
    + +
    +
    + +
    +

    出版社

    +
    + +
    +
    + + + +
    +

    库存数量

    +
    + +
    +
    + +
    +

    翻译

    +
    + +
    +
    + + + +
    +
    + + + +
    +
    +
    + +
    +
    +
    + + + + \ No newline at end of file diff --git a/src/main/resources/templates/empty.html b/src/main/resources/templates/empty.html index ec698b5..90bba72 100644 --- a/src/main/resources/templates/empty.html +++ b/src/main/resources/templates/empty.html @@ -25,6 +25,31 @@ - + + \ No newline at end of file diff --git a/src/test/java/com/book/manager/ManagerApplicationTests.java b/src/test/java/com/book/manager/ManagerApplicationTests.java index cc9a81f..ed96cd5 100644 --- a/src/test/java/com/book/manager/ManagerApplicationTests.java +++ b/src/test/java/com/book/manager/ManagerApplicationTests.java @@ -33,7 +33,7 @@ public class ManagerApplicationTests { book.setPublish("北京邮电出版社分社"+i); book.setSize(i); book.setTranslate("翻译者"+i); - book.setType(0); +// book.setType(0); book.setPublishTime(new Date()); bookService.addBook(book); -- Gitee From 838338065f86bb39f599bdf94020921221e8e354 Mon Sep 17 00:00:00 2001 From: Jason Date: Tue, 21 Jul 2020 11:32:32 +0800 Subject: [PATCH 06/21] =?UTF-8?q?=E4=BF=AE=E5=A4=8DpageHelper=E5=88=86?= =?UTF-8?q?=E9=A1=B5=E5=A4=B1=E6=95=88=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 + .../manager/controller/BookController.java | 9 +- .../com/book/manager/service/BookService.java | 15 +- .../resources/templates/book/book-list.html | 13 +- .../templates/borrow/book-search.html | 216 ++++++++++++------ 5 files changed, 172 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index 3175862..e474041 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ - jQuery , 讲真的jQuery用着还是很舒服, 突破各种前端框架的限制 +- 这里真的要吹一波jQuery插件库,强大,耦合性低,加入即用, 非常适合本项目 + #### 如果有定制需求, 可以联系作者 - 质量保证, 从高大上到原生, 你要的我都有 diff --git a/src/main/java/com/book/manager/controller/BookController.java b/src/main/java/com/book/manager/controller/BookController.java index 2a0e85c..afda4ae 100644 --- a/src/main/java/com/book/manager/controller/BookController.java +++ b/src/main/java/com/book/manager/controller/BookController.java @@ -36,15 +36,8 @@ public class BookController { if (pageIn == null) { return R.fail(CodeEnum.PARAM_ERROR); } - // 封装分页出参对象 - PageInfo outs = bookService.getBookList(pageIn); - PageOut pageOut = new PageOut(); - pageOut.setCurrPage(outs.getPageNum()); - pageOut.setPageSize(outs.getPageSize()); - pageOut.setTotal((int) outs.getTotal()); - pageOut.setList(outs.getList()); - return R.success(CodeEnum.SUCCESS,pageOut); + return R.success(CodeEnum.SUCCESS,bookService.getBookList(pageIn)); } @ApiOperation("添加图书") diff --git a/src/main/java/com/book/manager/service/BookService.java b/src/main/java/com/book/manager/service/BookService.java index a0025a1..18aa34e 100644 --- a/src/main/java/com/book/manager/service/BookService.java +++ b/src/main/java/com/book/manager/service/BookService.java @@ -10,6 +10,7 @@ import com.book.manager.entity.Users; import com.book.manager.repos.BookRepository; import com.book.manager.repos.UsersRepository; import com.book.manager.util.po.BookOut; +import com.book.manager.util.po.PageOut; import com.book.manager.util.vo.PageIn; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; @@ -87,19 +88,27 @@ public class BookService { * @param pageIn * @return */ - public PageInfo getBookList(PageIn pageIn) { + public PageOut getBookList(PageIn pageIn) { PageHelper.startPage(pageIn.getCurrPage(),pageIn.getPageSize()); List list = bookMapper.findBookListByLike(pageIn.getKeyword()); + PageInfo pageInfo = new PageInfo<>(list); + List bookOuts = new ArrayList<>(); - for (Book book : list) { + for (Book book : pageInfo.getList()) { BookOut out = new BookOut(); BeanUtil.copyProperties(book,out); out.setPublishTime(DateUtil.format(book.getPublishTime(),"yyyy-MM-dd")); bookOuts.add(out); } - return new PageInfo<>(bookOuts); + // 自定义分页返回对象 + PageOut pageOut = new PageOut(); + pageOut.setList(bookOuts); + pageOut.setTotal((int)pageInfo.getTotal()); + pageOut.setCurrPage(pageInfo.getPageNum()); + pageOut.setPageSize(pageInfo.getPageSize()); + return pageOut; } diff --git a/src/main/resources/templates/book/book-list.html b/src/main/resources/templates/book/book-list.html index 98f866b..d51becd 100644 --- a/src/main/resources/templates/book/book-list.html +++ b/src/main/resources/templates/book/book-list.html @@ -97,7 +97,6 @@ // 渲染数据表格 function rander(currPage,keyword,pageSize) { // 定义全局 分页属性 - var total = 0; $.ajax({ //请求方式 type : "POST", @@ -112,12 +111,11 @@ console.log(result); // 获取集合属性 var r = result.data; + var total = r.total; + var currPage = r.currPage; + var pageSize = r.pageSize; // 分页信息 - currPage = r.currPage; - pageSize = r.pageSize; - total = r.total; - - console.log("currPage:"+currPage+"pageSize:"+pageSize+"total:"+total); + console.log("currPage:"+r.currPage+"\t pageSize:"+r.pageSize+"\t total:"+r.total); var array = r.list; var text = ""; @@ -134,6 +132,7 @@ // 向上取整去总页数 var totalPage = Math.ceil(total/pageSize); + console.log("totalPage:"+totalPage); // 清空分页组件 $("#page").empty(); // 调用分页组件 @@ -141,7 +140,7 @@ id : "page", pageCount : totalPage, // 总页数 currentPage : currPage,// 默认选中第几页 - perPageCount : pageSize, // 每页显示多少条,不填时,不显示该条数选择控件 + perPageCount : pageSize , // 每页显示多少条,不填时,不显示该条数选择控件 isShowJumpPage : false, // 是否显示跳页 totalNum : total, // 总条数,不填时,不显示 position : "center", diff --git a/src/main/resources/templates/borrow/book-search.html b/src/main/resources/templates/borrow/book-search.html index 3f21672..61a63eb 100644 --- a/src/main/resources/templates/borrow/book-search.html +++ b/src/main/resources/templates/borrow/book-search.html @@ -18,11 +18,11 @@ -后台管理 + 后台管理 - +
    @@ -32,88 +32,174 @@ - +
    - + --> - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + -
    序号市区省区国别国别
    序号书名作者ISBN页数定价出版社出版时间库存数量翻译分类操作
    1苏州江苏省中国中国
    2无锡江苏省中国中国
    3常州江苏省中国中国
    - -
    -
      -
      + + +
      +
        +
        -
        +
        - \ No newline at end of file -- Gitee From c968528f7acf6ef2ccd1447a6f2d7c782fbd5a00 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 22 Jul 2020 16:51:35 +0800 Subject: [PATCH 07/21] =?UTF-8?q?=E9=9B=86=E6=88=90SpringSecurity=20?= =?UTF-8?q?=E8=BF=9B=E8=A1=8C=E7=99=BB=E5=BD=95=E6=8B=A6=E6=88=AA,?= =?UTF-8?q?=E4=BB=A5=E5=8F=8A=E8=B5=84=E6=BA=90=E4=BF=9D=E6=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 + pom.xml | 5 ++ .../com/book/manager/cache/UserCache.java | 56 +++++++++++++++ .../com/book/manager/config/WebConfig.java | 9 +-- .../manager/config/WebSecurityConfig.java | 71 +++++++++++++++++++ .../manager/controller/LoginController.java | 35 ++++----- .../book/manager/repos/UsersRepository.java | 7 ++ .../com/book/manager/service/UserService.java | 35 +++++++-- .../templates/borrow/book-search.html | 43 +++-------- src/main/resources/templates/login.html | 16 +++-- 10 files changed, 216 insertions(+), 64 deletions(-) create mode 100644 src/main/java/com/book/manager/cache/UserCache.java create mode 100644 src/main/java/com/book/manager/config/WebSecurityConfig.java diff --git a/README.md b/README.md index e474041..71334dd 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,9 @@ 2. 不要说为啥这个项目这个东西没加, 哪个东西没加, 针对的层次不一样, 要求也不一样 3. 很多我也想加, 但是复杂起来了, 不适合目标人群使用 +#### 作者介绍 +尘心, 英文名:Jason + #### 参与贡献 1. Fork 本仓库 diff --git a/pom.xml b/pom.xml index befc984..fdf6d6c 100644 --- a/pom.xml +++ b/pom.xml @@ -19,6 +19,11 @@ + + + org.springframework.boot + spring-boot-starter-security + org.springframework.boot diff --git a/src/main/java/com/book/manager/cache/UserCache.java b/src/main/java/com/book/manager/cache/UserCache.java new file mode 100644 index 0000000..9aa5423 --- /dev/null +++ b/src/main/java/com/book/manager/cache/UserCache.java @@ -0,0 +1,56 @@ +package com.book.manager.cache; + +import java.util.HashMap; + +/** + * @Description 用户缓存 + *

        + * 摒弃Session, 自己在服务器端维护一个会话 + * 1. 记录用户信息 + * 2. 用户URL地址拦截 + * 3. 方便多个使用同一个账户 + * + * 注意, 负载, 分布式情况下不适用, 可使用redis实现会话信息共享 + *

        + * @Date 2020/7/21 11:52 + * @Author by 尘心 + */ +public class UserCache{ + + private static HashMap userMap = new HashMap<>(); + + /** + * 用户登录时 放入缓存 + * @param username 用户名 + * @param password 密码 + */ + public static void login(String username, String password) { + userMap.put(username,password); + } + + /** + * 用户登出时 清除缓存 + * @param username 用户名 + */ + public static void logout(String username) { + userMap.remove(username); + } + + /** + * 获取用户信息 + * @param key 键 + * @return + */ + public static Object get(String key) { + return userMap.get(key); + } + + /** + * key 是否存在 + * @param key key + * @return + */ + public static boolean isExist(String key) { + return userMap.containsKey(key); + } +} diff --git a/src/main/java/com/book/manager/config/WebConfig.java b/src/main/java/com/book/manager/config/WebConfig.java index 8d08833..16b466a 100644 --- a/src/main/java/com/book/manager/config/WebConfig.java +++ b/src/main/java/com/book/manager/config/WebConfig.java @@ -19,11 +19,8 @@ public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { - // 添加拦截器 - registry.addInterceptor(loginInterceptor) - .addPathPatterns("/**") - .excludePathPatterns("/") - .excludePathPatterns("/login") - .excludePathPatterns("/login.html"); + // 添加拦截器 使用spring security 无需登录拦截 } + + } diff --git a/src/main/java/com/book/manager/config/WebSecurityConfig.java b/src/main/java/com/book/manager/config/WebSecurityConfig.java new file mode 100644 index 0000000..26c84a8 --- /dev/null +++ b/src/main/java/com/book/manager/config/WebSecurityConfig.java @@ -0,0 +1,71 @@ +package com.book.manager.config; + +import com.book.manager.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +import javax.sql.DataSource; + +/** + * @Description web security 安全配置 + * @Date 2020/7/21 15:19 + * @Author by 尘心 + */ +@EnableWebSecurity +public class WebSecurityConfig extends WebSecurityConfigurerAdapter{ + + + @Autowired + private UserService userService; + + @Override + protected void configure(HttpSecurity http) throws Exception { + //授权 + http.formLogin() + //自定义登陆页面 + .loginPage("/login") + //如果URL为loginPage,则用SpringSecurity中自带的过滤器去处理该请求 + .successForwardUrl("/index") + .loginProcessingUrl("/user/login") + .and() + //请求授权 + .authorizeRequests() + //在访问我们的URL时,我们是不需要省份认证,可以立即访问 + .antMatchers("/javaex/**","/","/login","/user/login").permitAll() + //所有请求都被拦截,都需认证 + .anyRequest().authenticated() + .and() + // 请求头允许X-Frame-Options, 否则所有iframe将失效 + .headers().frameOptions().disable() + // 注销, 回到首页 +// .logout().logoutSuccessUrl("/") + //SpringSecurity保护机制 + .and() + .csrf().disable(); + + // 开启记住我功能 + http.rememberMe().rememberMeParameter("remember"); + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // 认证 + auth.userDetailsService(userService).passwordEncoder(passwordEncoder()); + } + + + /** + * 指定加密方式 + */ + @Bean + public PasswordEncoder passwordEncoder(){ + // 使用BCrypt加密密码 + return new BCryptPasswordEncoder(); + } +} diff --git a/src/main/java/com/book/manager/controller/LoginController.java b/src/main/java/com/book/manager/controller/LoginController.java index 346d009..46d4b83 100644 --- a/src/main/java/com/book/manager/controller/LoginController.java +++ b/src/main/java/com/book/manager/controller/LoginController.java @@ -8,6 +8,7 @@ import com.book.manager.util.http.CodeEnum; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; @@ -26,22 +27,22 @@ public class LoginController { private UserService userService; /** - * 登录 + * 登录, 使用SpringSecurity 无需自己编写登录接口 */ - @ResponseBody - @RequestMapping("/user/login") - public R login(HttpServletRequest request, HttpServletResponse response) throws IOException { - String username = request.getParameter("username"); - String password = request.getParameter("password"); - - if (StrUtil.isNotBlank(username)&&StrUtil.isNotBlank(password)) { - Users users = userService. login(username, password); - if (users!=null) { - request.getSession().setAttribute("username",username); - return R.success(CodeEnum.SUCCESS); - } - } - - return R.fail(CodeEnum.NAME_OR_PASS_ERROR); - } +// @ResponseBody +// @RequestMapping(method = RequestMethod.POST,value = "/user/login") +// public R login(HttpServletRequest request, HttpServletResponse response) throws IOException { +// String username = request.getParameter("username"); +// String password = request.getParameter("password"); +// +// if (StrUtil.isNotBlank(username)&&StrUtil.isNotBlank(password)) { +// Users users = userService. login(username, password); +// if (users!=null) { +// request.getSession().setAttribute("username",username); +// return R.success(CodeEnum.SUCCESS); +// } +// } +// +// return R.fail(CodeEnum.NAME_OR_PASS_ERROR); +// } } diff --git a/src/main/java/com/book/manager/repos/UsersRepository.java b/src/main/java/com/book/manager/repos/UsersRepository.java index 15590d8..28387b3 100644 --- a/src/main/java/com/book/manager/repos/UsersRepository.java +++ b/src/main/java/com/book/manager/repos/UsersRepository.java @@ -33,4 +33,11 @@ public interface UsersRepository extends JpaRepository{ * @param password 密码 */ Users findByUsernameAndPassword(@Param("username") String username,@Param("password") String password); + + /** + * 用户名查询 + * @param username + * @return + */ + Users findByUsername(@Param("username") String username); } diff --git a/src/main/java/com/book/manager/service/UserService.java b/src/main/java/com/book/manager/service/UserService.java index 296da87..8d94c09 100644 --- a/src/main/java/com/book/manager/service/UserService.java +++ b/src/main/java/com/book/manager/service/UserService.java @@ -1,19 +1,25 @@ package com.book.manager.service; import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.util.StrUtil; import com.book.manager.dao.UsersMapper; import com.book.manager.entity.Users; import com.book.manager.repos.UsersRepository; import com.book.manager.util.vo.PageIn; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; -import org.apache.catalina.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; +import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -23,7 +29,7 @@ import java.util.Optional; * @Author by 尘心 */ @Service -public class UserService { +public class UserService implements UserDetailsService{ @Autowired private UsersRepository usersRepository; @@ -31,6 +37,9 @@ public class UserService { @Autowired private UsersMapper usersMapper; + @Autowired + private PasswordEncoder passwordEncoder; + /** * 获取所有用户, 分页 * @param pageable 分页对象 @@ -97,5 +106,23 @@ public class UserService { return new PageInfo<>(listByLike); } - + /** + * 用户鉴权 + * @param username + * @return + * @throws UsernameNotFoundException + */ + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + // 查找用户 + Users user = usersRepository.findByUsername(username); + // 获得角色 + String role = String.valueOf(user.getIsAdmin()); + // 角色集合 + List authorities = new ArrayList<>(); + // 角色必须以`ROLE_`开头,数据库中没有,则在这里加 + authorities.add(new SimpleGrantedAuthority("ROLE_" + role)); + // 数据库密码是明文, 需要加密进行比对 + return new User(user.getUsername(), passwordEncoder.encode(user.getPassword()), authorities); + } } diff --git a/src/main/resources/templates/borrow/book-search.html b/src/main/resources/templates/borrow/book-search.html index 61a63eb..2e2267f 100644 --- a/src/main/resources/templates/borrow/book-search.html +++ b/src/main/resources/templates/borrow/book-search.html @@ -36,9 +36,9 @@
        - +
        + 记住我 +
        @@ -62,17 +65,20 @@ $("#save").on("click", function(){ var username = $("#uname").val(); var password = $("#pass").val(); + // 记住我 + var remember = $("#remember").val(); - $.post("/user/login",{"username":username,"password": password},function(result) { - var code = result.code; - // alert(code); - // alert(JSON.stringify(result)); - if (code != 200) { + $.post("/user/login",{"username":username,"password": password,"remember":remember},function(result) { + // 由于SpringSecurity 框架返回的是HTML页面, 所以使用js形式登录只能以html页面元素判定是否登录成功 + var index = result.indexOf("remember"); + if (index>0) { + // 提示登录失败 javaex.optTip({ content : "用户名或密码错误!", type : "error" }); }else { + // 登录成功 跳转首页 window.location.href="/index"; } -- Gitee From 95f638ef0c41c3d7c395d434a0a86a51ae912200 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 22 Jul 2020 16:53:12 +0800 Subject: [PATCH 08/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9readme=20=E6=8F=8F?= =?UTF-8?q?=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 71334dd..6ca736f 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,11 @@ - 基础框架: SpringBoot - 简单数据操作: Spring Data Jpa - 复杂数据操作: Mybatis +- 安全框架: SpringSecurity - 模板引擎: Thymeleaf - API文档&测试: Swagger2 + 前端: - javaEx, 其实就是对html,css,js的封装, 很简单, 10分钟就能上手。比较接近原生 修改起来比较方便, 所以就用了。想了解的, 百度JavaEx即可。 -- Gitee From 22c585f2065ec018962d13b8877aa954f348d2c8 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 22 Jul 2020 17:08:58 +0800 Subject: [PATCH 09/21] =?UTF-8?q?=E6=B7=BB=E5=8A=A0jpa=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=A1=A8=E7=BB=93=E6=9E=84=E6=B3=A8=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/book/manager/entity/Book.java | 4 ++++ src/main/java/com/book/manager/entity/Borrow.java | 6 ++++++ src/main/java/com/book/manager/entity/Users.java | 4 ++++ src/main/resources/mapper/BorrowMapper.xml | 1 + 4 files changed, 15 insertions(+) diff --git a/src/main/java/com/book/manager/entity/Book.java b/src/main/java/com/book/manager/entity/Book.java index 38474be..c67a5cf 100644 --- a/src/main/java/com/book/manager/entity/Book.java +++ b/src/main/java/com/book/manager/entity/Book.java @@ -3,6 +3,8 @@ package com.book.manager.entity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; import org.springframework.format.annotation.DateTimeFormat; import javax.persistence.*; @@ -16,6 +18,8 @@ import java.util.Date; @Data @NoArgsConstructor @AllArgsConstructor +@DynamicUpdate +@DynamicInsert @Entity @Table(name = "book") public class Book { diff --git a/src/main/java/com/book/manager/entity/Borrow.java b/src/main/java/com/book/manager/entity/Borrow.java index dcd4cb8..7304991 100644 --- a/src/main/java/com/book/manager/entity/Borrow.java +++ b/src/main/java/com/book/manager/entity/Borrow.java @@ -3,6 +3,8 @@ package com.book.manager.entity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; import javax.persistence.*; import java.util.Date; @@ -15,6 +17,8 @@ import java.util.Date; @Data @NoArgsConstructor @AllArgsConstructor +@DynamicUpdate +@DynamicInsert @Entity @Table(name = "borrow") public class Borrow { @@ -29,5 +33,7 @@ public class Borrow { private Date createTime; + private Date endTime; + private Date updateTime; } diff --git a/src/main/java/com/book/manager/entity/Users.java b/src/main/java/com/book/manager/entity/Users.java index 35b24ad..104684d 100644 --- a/src/main/java/com/book/manager/entity/Users.java +++ b/src/main/java/com/book/manager/entity/Users.java @@ -3,6 +3,8 @@ package com.book.manager.entity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; import javax.persistence.*; import java.util.Date; @@ -15,6 +17,8 @@ import java.util.Date; @Data @NoArgsConstructor @AllArgsConstructor +@DynamicUpdate +@DynamicInsert @Entity @Table(name = "users") public class Users { diff --git a/src/main/resources/mapper/BorrowMapper.xml b/src/main/resources/mapper/BorrowMapper.xml index fa60b82..a5e5e92 100644 --- a/src/main/resources/mapper/BorrowMapper.xml +++ b/src/main/resources/mapper/BorrowMapper.xml @@ -6,6 +6,7 @@ + -- Gitee From 77ad288b0a4ad5b3b79fd2cea4ee7a38dfc2323d Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 23 Jul 2020 16:43:39 +0800 Subject: [PATCH 10/21] =?UTF-8?q?=E5=8A=A0=E5=85=A5Swagger=20=E7=BE=8E?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 6 ++++++ .../com/book/manager/ManagerApplication.java | 2 ++ .../java/com/book/manager/config/WebConfig.java | 2 +- .../book/manager/config/WebSecurityConfig.java | 10 ++++++++++ .../resources/templates/borrow/book-search.html | 17 ++++++++++------- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index fdf6d6c..fa74064 100644 --- a/pom.xml +++ b/pom.xml @@ -53,6 +53,12 @@ springfox-swagger-ui 2.7.0 + + + com.github.xiaoymin + swagger-bootstrap-ui + 1.9.3 + org.springframework.boot diff --git a/src/main/java/com/book/manager/ManagerApplication.java b/src/main/java/com/book/manager/ManagerApplication.java index 0a12306..81ffe22 100644 --- a/src/main/java/com/book/manager/ManagerApplication.java +++ b/src/main/java/com/book/manager/ManagerApplication.java @@ -1,9 +1,11 @@ package com.book.manager; +import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +@EnableSwaggerBootstrapUI @EnableJpaRepositories @SpringBootApplication public class ManagerApplication { diff --git a/src/main/java/com/book/manager/config/WebConfig.java b/src/main/java/com/book/manager/config/WebConfig.java index 16b466a..d106dc2 100644 --- a/src/main/java/com/book/manager/config/WebConfig.java +++ b/src/main/java/com/book/manager/config/WebConfig.java @@ -4,6 +4,7 @@ import com.book.manager.interceptor.LoginInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** @@ -22,5 +23,4 @@ public class WebConfig implements WebMvcConfigurer { // 添加拦截器 使用spring security 无需登录拦截 } - } diff --git a/src/main/java/com/book/manager/config/WebSecurityConfig.java b/src/main/java/com/book/manager/config/WebSecurityConfig.java index 26c84a8..890513b 100644 --- a/src/main/java/com/book/manager/config/WebSecurityConfig.java +++ b/src/main/java/com/book/manager/config/WebSecurityConfig.java @@ -5,6 +5,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -41,6 +42,9 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter{ //所有请求都被拦截,都需认证 .anyRequest().authenticated() .and() + // 请求头允许X-ContentType-Options + //.headers().contentTypeOptions().disable() + //.and() // 请求头允许X-Frame-Options, 否则所有iframe将失效 .headers().frameOptions().disable() // 注销, 回到首页 @@ -53,12 +57,18 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter{ http.rememberMe().rememberMeParameter("remember"); } + @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // 认证 auth.userDetailsService(userService).passwordEncoder(passwordEncoder()); } + @Override + public void configure(WebSecurity web) throws Exception { + // swagger 资源放行 + web.ignoring().antMatchers("/webjars/**","/v2/**","/swagger-resources/**","/doc.html","/docs.html","swagger-ui.html"); + } /** * 指定加密方式 diff --git a/src/main/resources/templates/borrow/book-search.html b/src/main/resources/templates/borrow/book-search.html index 2e2267f..ea65a0f 100644 --- a/src/main/resources/templates/borrow/book-search.html +++ b/src/main/resources/templates/borrow/book-search.html @@ -169,16 +169,19 @@ // 借阅图书 function borrowBook(id) { - console.log("update Book"+id); - - // 借阅, 用户可借数量减一, 图书数量减一 , 注意界限判断 - + javaex.confirm({ + content : "确定要借阅么", + callback : "forwardBorrow("+id+")" + }); + } + function forwardBorrow(id) { - // 借阅完成, 重新加载 - window.location.reload(); + var url = "/borrow/borrow?id="+id; + // 跳转借阅界面 + window.location.href = "/borrow/borrow?id="+id; + // $("#bb", parent.document).click(); } - \ No newline at end of file -- Gitee From 1ec8c1432cc3ce49df00625137326f8aeae9dcd9 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 23 Jul 2020 16:46:17 +0800 Subject: [PATCH 11/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9Readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6ca736f..96623be 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ - 安全框架: SpringSecurity - 模板引擎: Thymeleaf - API文档&测试: Swagger2 - +- API文档美化: Swagger-Bootstrap-UI, 这个很好看, 但是版本兼容性会有问题, 我试了很多版本, 最终1.9.3可以正常使用 前端: - javaEx, 其实就是对html,css,js的封装, 很简单, 10分钟就能上手。比较接近原生 -- Gitee From 3987041bfd2405ed8926912c7db918f971db2dc5 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 23 Jul 2020 16:48:36 +0800 Subject: [PATCH 12/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8C=85=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/book/manager/controller/BookController.java | 7 +------ .../book/manager/controller/BorrowController.java | 6 ------ .../com/book/manager/controller/UsersController.java | 9 ++------- src/main/java/com/book/manager/dao/BookMapper.java | 1 - .../java/com/book/manager/service/BookService.java | 12 +++--------- .../java/com/book/manager/service/UserService.java | 2 +- .../com/book/manager/util/{vo => ro}/PageIn.java | 2 +- .../com/book/manager/util/{po => vo}/BookOut.java | 2 +- .../com/book/manager/util/{po => vo}/PageOut.java | 2 +- 9 files changed, 10 insertions(+), 33 deletions(-) rename src/main/java/com/book/manager/util/{vo => ro}/PageIn.java (89%) rename src/main/java/com/book/manager/util/{po => vo}/BookOut.java (91%) rename src/main/java/com/book/manager/util/{po => vo}/PageOut.java (92%) diff --git a/src/main/java/com/book/manager/controller/BookController.java b/src/main/java/com/book/manager/controller/BookController.java index afda4ae..9ebd9ee 100644 --- a/src/main/java/com/book/manager/controller/BookController.java +++ b/src/main/java/com/book/manager/controller/BookController.java @@ -1,15 +1,10 @@ package com.book.manager.controller; import com.book.manager.entity.Book; -import com.book.manager.entity.Users; import com.book.manager.service.BookService; -import com.book.manager.service.UserService; import com.book.manager.util.R; import com.book.manager.util.http.CodeEnum; -import com.book.manager.util.po.BookOut; -import com.book.manager.util.po.PageOut; -import com.book.manager.util.vo.PageIn; -import com.github.pagehelper.PageInfo; +import com.book.manager.util.ro.PageIn; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/main/java/com/book/manager/controller/BorrowController.java b/src/main/java/com/book/manager/controller/BorrowController.java index 382fd93..763cfcf 100644 --- a/src/main/java/com/book/manager/controller/BorrowController.java +++ b/src/main/java/com/book/manager/controller/BorrowController.java @@ -1,15 +1,9 @@ package com.book.manager.controller; -import com.book.manager.entity.Book; import com.book.manager.entity.Borrow; -import com.book.manager.entity.Users; -import com.book.manager.service.BookService; import com.book.manager.service.BorrowService; import com.book.manager.util.R; import com.book.manager.util.http.CodeEnum; -import com.book.manager.util.po.PageOut; -import com.book.manager.util.vo.PageIn; -import com.github.pagehelper.PageInfo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/main/java/com/book/manager/controller/UsersController.java b/src/main/java/com/book/manager/controller/UsersController.java index 0cd12a2..5e182bc 100644 --- a/src/main/java/com/book/manager/controller/UsersController.java +++ b/src/main/java/com/book/manager/controller/UsersController.java @@ -4,20 +4,15 @@ import com.book.manager.entity.Users; import com.book.manager.service.UserService; import com.book.manager.util.R; import com.book.manager.util.http.CodeEnum; -import com.book.manager.util.po.PageOut; -import com.book.manager.util.vo.PageIn; +import com.book.manager.util.vo.PageOut; +import com.book.manager.util.ro.PageIn; import com.github.pagehelper.PageInfo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; -import java.util.List; - /** * @Description 用户管理 * @Date 2020/7/14 16:35 diff --git a/src/main/java/com/book/manager/dao/BookMapper.java b/src/main/java/com/book/manager/dao/BookMapper.java index d164b71..df5285d 100644 --- a/src/main/java/com/book/manager/dao/BookMapper.java +++ b/src/main/java/com/book/manager/dao/BookMapper.java @@ -1,7 +1,6 @@ package com.book.manager.dao; import com.book.manager.entity.Book; -import com.book.manager.util.po.BookOut; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/book/manager/service/BookService.java b/src/main/java/com/book/manager/service/BookService.java index 18aa34e..dfe2a92 100644 --- a/src/main/java/com/book/manager/service/BookService.java +++ b/src/main/java/com/book/manager/service/BookService.java @@ -1,22 +1,16 @@ package com.book.manager.service; import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import com.book.manager.dao.BookMapper; -import com.book.manager.dao.UsersMapper; import com.book.manager.entity.Book; -import com.book.manager.entity.Users; import com.book.manager.repos.BookRepository; -import com.book.manager.repos.UsersRepository; -import com.book.manager.util.po.BookOut; -import com.book.manager.util.po.PageOut; -import com.book.manager.util.vo.PageIn; +import com.book.manager.util.vo.BookOut; +import com.book.manager.util.vo.PageOut; +import com.book.manager.util.ro.PageIn; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import java.util.ArrayList; diff --git a/src/main/java/com/book/manager/service/UserService.java b/src/main/java/com/book/manager/service/UserService.java index 8d94c09..c5ff214 100644 --- a/src/main/java/com/book/manager/service/UserService.java +++ b/src/main/java/com/book/manager/service/UserService.java @@ -4,7 +4,7 @@ import cn.hutool.core.bean.BeanUtil; import com.book.manager.dao.UsersMapper; import com.book.manager.entity.Users; import com.book.manager.repos.UsersRepository; -import com.book.manager.util.vo.PageIn; +import com.book.manager.util.ro.PageIn; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/main/java/com/book/manager/util/vo/PageIn.java b/src/main/java/com/book/manager/util/ro/PageIn.java similarity index 89% rename from src/main/java/com/book/manager/util/vo/PageIn.java rename to src/main/java/com/book/manager/util/ro/PageIn.java index e279328..198f6ec 100644 --- a/src/main/java/com/book/manager/util/vo/PageIn.java +++ b/src/main/java/com/book/manager/util/ro/PageIn.java @@ -1,4 +1,4 @@ -package com.book.manager.util.vo; +package com.book.manager.util.ro; import lombok.Data; diff --git a/src/main/java/com/book/manager/util/po/BookOut.java b/src/main/java/com/book/manager/util/vo/BookOut.java similarity index 91% rename from src/main/java/com/book/manager/util/po/BookOut.java rename to src/main/java/com/book/manager/util/vo/BookOut.java index 572c812..c5d07df 100644 --- a/src/main/java/com/book/manager/util/po/BookOut.java +++ b/src/main/java/com/book/manager/util/vo/BookOut.java @@ -1,4 +1,4 @@ -package com.book.manager.util.po; +package com.book.manager.util.vo; import lombok.Data; diff --git a/src/main/java/com/book/manager/util/po/PageOut.java b/src/main/java/com/book/manager/util/vo/PageOut.java similarity index 92% rename from src/main/java/com/book/manager/util/po/PageOut.java rename to src/main/java/com/book/manager/util/vo/PageOut.java index c8e2f4a..7cc88b1 100644 --- a/src/main/java/com/book/manager/util/po/PageOut.java +++ b/src/main/java/com/book/manager/util/vo/PageOut.java @@ -1,4 +1,4 @@ -package com.book.manager.util.po; +package com.book.manager.util.vo; import io.swagger.annotations.ApiModelProperty; import lombok.Data; -- Gitee From f53643b9be3a09bef47c3ebde5f5029d3c88cc1b Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 23 Jul 2020 18:20:35 +0800 Subject: [PATCH 13/21] =?UTF-8?q?=E6=B7=BB=E5=8A=A0swagger=20=E6=B3=A8?= =?UTF-8?q?=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../book/manager/config/SwaggerConfiguration.java | 7 +++++-- .../book/manager/controller/RouteController.java | 9 ++++++++- src/main/java/com/book/manager/entity/Book.java | 12 ++++++++++++ src/main/java/com/book/manager/entity/Borrow.java | 7 +++++++ src/main/java/com/book/manager/entity/Users.java | 13 +++++++++++++ src/main/java/com/book/manager/util/R.java | 4 ++++ src/main/java/com/book/manager/util/ro/PageIn.java | 6 ++++++ 7 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/book/manager/config/SwaggerConfiguration.java b/src/main/java/com/book/manager/config/SwaggerConfiguration.java index 481f67b..831e49e 100644 --- a/src/main/java/com/book/manager/config/SwaggerConfiguration.java +++ b/src/main/java/com/book/manager/config/SwaggerConfiguration.java @@ -6,6 +6,7 @@ import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @@ -30,9 +31,11 @@ public class SwaggerConfiguration { } private ApiInfo apiInfo() { + Contact contact = new Contact("尘心(Jason)","http://www.diqiyuzhou.tk","amazingjava@163.com"); return new ApiInfoBuilder() - .title("服务:图书管理后台Swagger UI") - .description("服务:图书管理后台Swagger UI") + .title("【图书管理后台Swagger UI】") + .description("图书管理后台接口") + .contact(contact) .version("1.0") .build(); } diff --git a/src/main/java/com/book/manager/controller/RouteController.java b/src/main/java/com/book/manager/controller/RouteController.java index 79e9642..9c1ea52 100644 --- a/src/main/java/com/book/manager/controller/RouteController.java +++ b/src/main/java/com/book/manager/controller/RouteController.java @@ -1,5 +1,7 @@ package com.book.manager.controller; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -10,12 +12,14 @@ import org.springframework.web.bind.annotation.RequestMapping; * @Date 2020/7/16 9:25 * @Author by 尘心 */ +@Api(tags = "路由") @Controller public class RouteController { /** * 跳转登录 */ + @ApiOperation("跳转登录页") @GetMapping({"/login","/","logout"}) public String toLogin() { return "login"; @@ -24,6 +28,7 @@ public class RouteController { /** * 跳转首页 */ + @ApiOperation("跳转首页") @RequestMapping({"/index"}) public String toIndex() { return "index"; @@ -32,15 +37,17 @@ public class RouteController { /** * 跳转欢迎页面 */ + @ApiOperation("跳转欢迎页面") @RequestMapping({"/welcome"}) public String toWelcome() { return "welcome"; } /** - * 一级路由跳转 + * 二级路由跳转 * @param name 映射名称 */ + @ApiOperation("二级路由跳转") @RequestMapping("/{filename}/{name}") public String change(@PathVariable String filename,@PathVariable String name) { return filename+"/"+name; diff --git a/src/main/java/com/book/manager/entity/Book.java b/src/main/java/com/book/manager/entity/Book.java index c67a5cf..8d00ded 100644 --- a/src/main/java/com/book/manager/entity/Book.java +++ b/src/main/java/com/book/manager/entity/Book.java @@ -1,5 +1,6 @@ package com.book.manager.entity; +import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -24,28 +25,39 @@ import java.util.Date; @Table(name = "book") public class Book { + @ApiModelProperty("主键") @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; + @ApiModelProperty("图书ISBN编码") private String isbn; + @ApiModelProperty("图书名称") private String name; + @ApiModelProperty("图书作者") private String author; + @ApiModelProperty("图书页数") private Integer pages; + @ApiModelProperty("翻译") private String translate; + @ApiModelProperty("出版社") private String publish; + @ApiModelProperty("单价") private Double price; + @ApiModelProperty("库存") private Integer size; + @ApiModelProperty("分类") private String type; + @ApiModelProperty("出版时间") private Date publishTime; // json字符串: {"isbn":"isbn","name":"name","author":"author","pages":"pages","translate":"translate","publish":"publish","price":"price","size":"size","type":"type","publishTime":"publishTime"} diff --git a/src/main/java/com/book/manager/entity/Borrow.java b/src/main/java/com/book/manager/entity/Borrow.java index 7304991..1fbd873 100644 --- a/src/main/java/com/book/manager/entity/Borrow.java +++ b/src/main/java/com/book/manager/entity/Borrow.java @@ -1,5 +1,6 @@ package com.book.manager.entity; +import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -23,17 +24,23 @@ import java.util.Date; @Table(name = "borrow") public class Borrow { + @ApiModelProperty("主键ID") @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; + @ApiModelProperty("用户ID") private Integer userId; + @ApiModelProperty("图书ID") private Integer bookId; + @ApiModelProperty("借阅时间") private Date createTime; + @ApiModelProperty("归还时间") private Date endTime; + @ApiModelProperty("实际归还时间") private Date updateTime; } diff --git a/src/main/java/com/book/manager/entity/Users.java b/src/main/java/com/book/manager/entity/Users.java index 104684d..9e74db7 100644 --- a/src/main/java/com/book/manager/entity/Users.java +++ b/src/main/java/com/book/manager/entity/Users.java @@ -1,5 +1,6 @@ package com.book.manager.entity; +import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -23,30 +24,42 @@ import java.util.Date; @Table(name = "users") public class Users { + @ApiModelProperty("主键ID") @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; + @ApiModelProperty("头像") private String avatar; + @ApiModelProperty("昵称") private String nickname; + @ApiModelProperty("用户名") private String username; + @ApiModelProperty("密码") private String password; + @ApiModelProperty("生日") private Date birthday; + @ApiModelProperty("是否为管理员") private Integer isAdmin; + @ApiModelProperty("电话") private String tel; + @ApiModelProperty("邮箱") private String email; + @ApiModelProperty("地址") private String address; + @ApiModelProperty("可借数量") private Integer size; + @ApiModelProperty("身份") private Integer identity; } diff --git a/src/main/java/com/book/manager/util/R.java b/src/main/java/com/book/manager/util/R.java index 8b8fde8..9e72ebe 100644 --- a/src/main/java/com/book/manager/util/R.java +++ b/src/main/java/com/book/manager/util/R.java @@ -1,6 +1,7 @@ package com.book.manager.util; import com.book.manager.util.http.CodeEnum; +import io.swagger.annotations.ApiModelProperty; import java.io.Serializable; @@ -11,10 +12,13 @@ import java.io.Serializable; */ public class R implements Serializable{ + @ApiModelProperty("响应码") private Integer code; + @ApiModelProperty("响应信息") private String msg; + @ApiModelProperty("响应数据") private Object data; public R() { diff --git a/src/main/java/com/book/manager/util/ro/PageIn.java b/src/main/java/com/book/manager/util/ro/PageIn.java index 198f6ec..b53efb0 100644 --- a/src/main/java/com/book/manager/util/ro/PageIn.java +++ b/src/main/java/com/book/manager/util/ro/PageIn.java @@ -1,5 +1,6 @@ package com.book.manager.util.ro; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** @@ -11,9 +12,14 @@ import lombok.Data; public class PageIn { /** 搜索关键字 */ + @ApiModelProperty("搜索关键字") private String keyword; + /** 当前页 */ + @ApiModelProperty("当前页") private Integer currPage; + /** 当前页条数 */ + @ApiModelProperty("每页数量") private Integer pageSize; } -- Gitee From d64a34e932b1fcf7caa4bc5fe4bc7f8c3f1096ec Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 23 Jul 2020 20:09:22 +0800 Subject: [PATCH 14/21] =?UTF-8?q?=E5=9B=BE=E4=B9=A6=E5=80=9F=E9=98=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + .../com/book/manager/cache/UserCache.java | 2 +- .../manager/controller/BookController.java | 13 +- .../book/manager/repos/BookRepository.java | 7 +- .../com/book/manager/service/BookService.java | 16 + .../com/book/manager/service/UserService.java | 10 +- .../resources/templates/borrow/borrow.html | 290 ++++++++++++------ 7 files changed, 229 insertions(+), 110 deletions(-) diff --git a/README.md b/README.md index 96623be..9bd31cd 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ 1. 本项目适用于大学生实训, 或者个人学习使用 2. 不要说为啥这个项目这个东西没加, 哪个东西没加, 针对的层次不一样, 要求也不一样 3. 很多我也想加, 但是复杂起来了, 不适合目标人群使用 +4. 为了方便大家使用, 并未对密码进行加密, 想要加密的:大家可以在插入用户的时候对密码加密, 在loadByUsername中去除密码加密即可 #### 作者介绍 尘心, 英文名:Jason diff --git a/src/main/java/com/book/manager/cache/UserCache.java b/src/main/java/com/book/manager/cache/UserCache.java index 9aa5423..821163a 100644 --- a/src/main/java/com/book/manager/cache/UserCache.java +++ b/src/main/java/com/book/manager/cache/UserCache.java @@ -3,7 +3,7 @@ package com.book.manager.cache; import java.util.HashMap; /** - * @Description 用户缓存 + * @Description 用户缓存, new: 现已使用SpringSecurity , 弃用此类 *

        * 摒弃Session, 自己在服务器端维护一个会话 * 1. 记录用户信息 diff --git a/src/main/java/com/book/manager/controller/BookController.java b/src/main/java/com/book/manager/controller/BookController.java index 9ebd9ee..541482e 100644 --- a/src/main/java/com/book/manager/controller/BookController.java +++ b/src/main/java/com/book/manager/controller/BookController.java @@ -17,7 +17,7 @@ import org.springframework.web.bind.annotation.*; * @Author by 尘心 */ @Api(tags = "图书管理") -@Controller +@RestController @RequestMapping("/book") public class BookController { @@ -25,7 +25,6 @@ public class BookController { private BookService bookService; @ApiOperation("图书搜索列表") - @ResponseBody @PostMapping("/list") public R getBookList(@RequestBody PageIn pageIn) { if (pageIn == null) { @@ -36,14 +35,12 @@ public class BookController { } @ApiOperation("添加图书") - @ResponseBody @PostMapping("/add") public R addBook(@RequestBody Book book) { return R.success(CodeEnum.SUCCESS,bookService.addBook(book)); } @ApiOperation("编辑图书") - @ResponseBody @PostMapping("/update") public R modifyBook(@RequestBody Book book) { return R.success(CodeEnum.SUCCESS,bookService.updateBook(book)); @@ -51,14 +48,18 @@ public class BookController { @ApiOperation("图书详情") - @ResponseBody @GetMapping("/detail") public R bookDetail(Integer id) { return R.success(CodeEnum.SUCCESS,bookService.findBookById(id)); } + @ApiOperation("图书详情 根据ISBN获取") + @GetMapping("/detailByIsbn") + public R bookDetailByIsbn(String isbn) { + return R.success(CodeEnum.SUCCESS,bookService.findBookByIsbn(isbn)); + } + @ApiOperation("删除图书") - @ResponseBody @GetMapping("/delete") public R delBook(Integer id) { bookService.deleteBook(id); diff --git a/src/main/java/com/book/manager/repos/BookRepository.java b/src/main/java/com/book/manager/repos/BookRepository.java index 97849a6..2a0d403 100644 --- a/src/main/java/com/book/manager/repos/BookRepository.java +++ b/src/main/java/com/book/manager/repos/BookRepository.java @@ -12,5 +12,10 @@ import org.springframework.stereotype.Repository; @Repository public interface BookRepository extends JpaRepository { - + /** + * ISBN编码查询 + * @param isbn + * @return + */ + Book findByIsbn(String isbn); } diff --git a/src/main/java/com/book/manager/service/BookService.java b/src/main/java/com/book/manager/service/BookService.java index dfe2a92..e8abf30 100644 --- a/src/main/java/com/book/manager/service/BookService.java +++ b/src/main/java/com/book/manager/service/BookService.java @@ -67,6 +67,22 @@ public class BookService { return null; } + /** + * ISBN查询 + * @param isbn + * @return + */ + public BookOut findBookByIsbn(String isbn) { + Book book = bookRepository.findByIsbn(isbn); + BookOut out = new BookOut(); + if (book == null) { + return out; + } + BeanUtil.copyProperties(book,out); + out.setPublishTime(DateUtil.format(book.getPublishTime(),"yyyy-MM-dd")); + return out; + } + /** * 删除图书 * @param id 主键 diff --git a/src/main/java/com/book/manager/service/UserService.java b/src/main/java/com/book/manager/service/UserService.java index c5ff214..8129085 100644 --- a/src/main/java/com/book/manager/service/UserService.java +++ b/src/main/java/com/book/manager/service/UserService.java @@ -41,13 +41,18 @@ public class UserService implements UserDetailsService{ private PasswordEncoder passwordEncoder; /** - * 获取所有用户, 分页 + * 获取所有用户, 分页(鉴于jpa分页过于繁琐, 已使用mybatis, page helper分页, 此方法弃用) * @param pageable 分页对象 */ public Page getUsers(String keyword,Pageable pageable) { return usersRepository.findByUsernameLike(keyword,pageable); } + /** + * 登录 (使用SpringSecurity 此方法弃用) + * @param username 用户名 + * @param password 密码 + */ public Users login(String username,String password) { return usersRepository.findByUsernameAndPassword(username,password); } @@ -108,8 +113,7 @@ public class UserService implements UserDetailsService{ /** * 用户鉴权 - * @param username - * @return + * @param username 用户名 * @throws UsernameNotFoundException */ @Override diff --git a/src/main/resources/templates/borrow/borrow.html b/src/main/resources/templates/borrow/borrow.html index 695f081..29d46a7 100644 --- a/src/main/resources/templates/borrow/borrow.html +++ b/src/main/resources/templates/borrow/borrow.html @@ -1,31 +1,31 @@ - - - - - - - - - - - - - - - - - -图书借阅 + + + + + + + + + + + + + + + + + + 图书借阅 - +

        @@ -33,89 +33,81 @@ - +
        -
        -
        *

        登录账号

        +
        *

        ISBN编号

        +
        + +
        +
        + +
        +
        *

        书名

        - +
        - - +
        -

        性别

        +

        作者

        -
          -
        • -
        • -
        +
        - - +
        -

        兴趣

        +

        出版社

        -
          -
        • 吃饭
        • -
        • 睡觉
        • -
        • 打豆豆
        • -
        +
        - + +
        +

        借阅时间

        +
        + + +
        +
        +
        -

        学历

        +

        图书分类

        - +
        - - +
        -

        注册时间

        +

        页数

        - +
        - - +
        -

        简介

        +

        定价

        - - -

        请填写个人简介。简介中不得包含令人反感的信息,且长度应在10到255个字符之间。

        +
        - - +
        -

        标签

        +

        库存数量

        -
        - +
        - +
        - +
        @@ -124,42 +116,142 @@
        \ No newline at end of file -- Gitee From a896324c83b0ffd2237ee27b6610b23076faf877 Mon Sep 17 00:00:00 2001 From: jason <1141649370@qq.com> Date: Fri, 24 Jul 2020 00:09:59 +0800 Subject: [PATCH 15/21] =?UTF-8?q?=E5=9B=BE=E4=B9=A6=E5=80=9F=E9=98=85?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E9=80=BB=E8=BE=91=E5=8A=A0=E5=BC=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../manager/controller/BorrowController.java | 18 +++-- .../manager/controller/UsersController.java | 27 +++++-- .../com/book/manager/dao/BorrowMapper.java | 5 ++ .../java/com/book/manager/entity/Borrow.java | 4 + .../manager/interceptor/LoginInterceptor.java | 7 -- .../book/manager/repos/BorrowRepository.java | 8 ++ .../com/book/manager/service/BookService.java | 10 +++ .../book/manager/service/BorrowService.java | 69 +++++++++++++++- .../com/book/manager/service/UserService.java | 10 +++ .../book/manager/util/consts/Constants.java | 12 +++ .../com/book/manager/util/http/CodeEnum.java | 10 ++- src/main/resources/mapper/BorrowMapper.xml | 1 + .../resources/templates/borrow/borrow.html | 81 +++++++++++++++++-- 13 files changed, 231 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/book/manager/controller/BorrowController.java b/src/main/java/com/book/manager/controller/BorrowController.java index 763cfcf..4875362 100644 --- a/src/main/java/com/book/manager/controller/BorrowController.java +++ b/src/main/java/com/book/manager/controller/BorrowController.java @@ -3,6 +3,7 @@ package com.book.manager.controller; import com.book.manager.entity.Borrow; import com.book.manager.service.BorrowService; import com.book.manager.util.R; +import com.book.manager.util.consts.Constants; import com.book.manager.util.http.CodeEnum; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -16,7 +17,7 @@ import org.springframework.web.bind.annotation.*; * @Author by 尘心 */ @Api(tags = "借阅管理") -@Controller +@RestController @RequestMapping("/borrow") public class BorrowController { @@ -24,21 +25,26 @@ public class BorrowController { private BorrowService borrowService; @ApiOperation("借阅列表") - @ResponseBody @GetMapping("/list") public R getBorrowList(Integer userId) { return R.success(CodeEnum.SUCCESS,borrowService.findAllBorrowByUserId(userId)); } @ApiOperation("借阅图书") - @ResponseBody @PostMapping("/add") public R addBorrow(@RequestBody Borrow borrow) { - return R.success(CodeEnum.SUCCESS,borrowService.addBorrow(borrow)); + Integer result = borrowService.addBorrow(borrow); + if (result == Constants.BOOK_BORROWED) { + return R.success(CodeEnum.BOOK_BORROWED); + }else if (result == Constants.USER_SIZE_NOT_ENOUGH) { + return R.success(CodeEnum.USER_NOT_ENOUGH); + }else if (result == Constants.BOOK_SIZE_NOT_ENOUGH) { + return R.success(CodeEnum.BOOK_NOT_ENOUGH); + } + return R.success(CodeEnum.SUCCESS,Constants.OK); } @ApiOperation("编辑借阅") - @ResponseBody @PostMapping("/update") public R modifyBorrow(@RequestBody Borrow borrow) { return R.success(CodeEnum.SUCCESS,borrowService.updateBorrow(borrow)); @@ -46,14 +52,12 @@ public class BorrowController { @ApiOperation("借阅详情") - @ResponseBody @GetMapping("/detail") public R borrowDetail(Integer id) { return R.success(CodeEnum.SUCCESS,borrowService.findById(id)); } @ApiOperation("归还图书") - @ResponseBody @GetMapping("/delete") public R delBorrow(Integer id) { borrowService.deleteBorrow(id); diff --git a/src/main/java/com/book/manager/controller/UsersController.java b/src/main/java/com/book/manager/controller/UsersController.java index 5e182bc..8fee1f3 100644 --- a/src/main/java/com/book/manager/controller/UsersController.java +++ b/src/main/java/com/book/manager/controller/UsersController.java @@ -1,5 +1,7 @@ package com.book.manager.controller; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; import com.book.manager.entity.Users; import com.book.manager.service.UserService; import com.book.manager.util.R; @@ -10,16 +12,18 @@ import com.github.pagehelper.PageInfo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.*; +import java.util.Map; + /** * @Description 用户管理 * @Date 2020/7/14 16:35 * @Author by 尘心 */ @Api(tags = "用户管理") -@Controller +@RestController @RequestMapping("/user") public class UsersController { @@ -27,7 +31,6 @@ public class UsersController { private UserService userService; @ApiOperation("用户列表") - @ResponseBody @PostMapping("/list") public R getUsers(@RequestBody PageIn pageIn) { if (pageIn == null) { @@ -45,14 +48,12 @@ public class UsersController { } @ApiOperation("添加用户") - @ResponseBody @PostMapping("/add") public R getUsers(@RequestBody Users users) { return R.success(CodeEnum.SUCCESS,userService.addUser(users)); } @ApiOperation("编辑用户") - @ResponseBody @PostMapping("/update") public R modifyUsers(@RequestBody Users users) { return R.success(CodeEnum.SUCCESS,userService.updateUser(users)); @@ -60,18 +61,30 @@ public class UsersController { @ApiOperation("用户详情") - @ResponseBody @GetMapping("/detail") public R userDetail(Integer id) { return R.success(CodeEnum.SUCCESS,userService.findUserById(id)); } @ApiOperation("删除用户") - @ResponseBody @GetMapping("/delete") public R delUsers(Integer id) { userService.deleteUser(id); return R.success(CodeEnum.SUCCESS); } + @ApiOperation("获取当前用户登陆信息") + @GetMapping("/currUser") + public R getCurrUser() { + Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + if (principal!=null) { + Map map = BeanUtil.beanToMap(principal); + String username = (String) map.get("username"); + if (StrUtil.isNotBlank(username)) { + Users users = userService.findByUsername(username); + return R.success(CodeEnum.SUCCESS,users); + } + } + return R.fail(CodeEnum.USER_NOT_FOUND); + } } diff --git a/src/main/java/com/book/manager/dao/BorrowMapper.java b/src/main/java/com/book/manager/dao/BorrowMapper.java index 61269fe..544e205 100644 --- a/src/main/java/com/book/manager/dao/BorrowMapper.java +++ b/src/main/java/com/book/manager/dao/BorrowMapper.java @@ -2,6 +2,8 @@ package com.book.manager.dao; import com.book.manager.entity.Borrow; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; import org.springframework.stereotype.Component; @@ -16,4 +18,7 @@ public interface BorrowMapper { @Update("update borrow set user_id = #{userId},book_id = #{bookId},update_time = #{updateTime} where id = #{id}") int updateBorrow(Borrow borrow); + + @Select("select * from borrow where user_id = #{userId} and book_id = #{bookId}") + Borrow findBorrowByUserIdAndBookId(@Param("userId") Integer userId, @Param("bookId") Integer bookId); } diff --git a/src/main/java/com/book/manager/entity/Borrow.java b/src/main/java/com/book/manager/entity/Borrow.java index 1fbd873..961a052 100644 --- a/src/main/java/com/book/manager/entity/Borrow.java +++ b/src/main/java/com/book/manager/entity/Borrow.java @@ -43,4 +43,8 @@ public class Borrow { @ApiModelProperty("实际归还时间") private Date updateTime; + + @ApiModelProperty("是否归还? 0 已归还/1 未归还") + private Integer ret; + // json: {"userId":userId,"bookId":bookId,"createTime":createTime,"endTime":endTime,"updateTime":updateTime} } diff --git a/src/main/java/com/book/manager/interceptor/LoginInterceptor.java b/src/main/java/com/book/manager/interceptor/LoginInterceptor.java index eba02b2..729dc10 100644 --- a/src/main/java/com/book/manager/interceptor/LoginInterceptor.java +++ b/src/main/java/com/book/manager/interceptor/LoginInterceptor.java @@ -21,13 +21,6 @@ public class LoginInterceptor implements HandlerInterceptor{ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session = request.getSession(); // 查看用户session 是否已登录 - Object username = session.getAttribute("username"); - // 暂时去掉拦截 -// if (username == null) { -// // 未登录 直接跳转到登录页 -// response.sendRedirect("/login"); -// return false; -// } return true; } diff --git a/src/main/java/com/book/manager/repos/BorrowRepository.java b/src/main/java/com/book/manager/repos/BorrowRepository.java index 35ec4e3..2e8fbb7 100644 --- a/src/main/java/com/book/manager/repos/BorrowRepository.java +++ b/src/main/java/com/book/manager/repos/BorrowRepository.java @@ -2,6 +2,7 @@ package com.book.manager.repos; import com.book.manager.entity.Borrow; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import java.util.List; @@ -20,4 +21,11 @@ public interface BorrowRepository extends JpaRepository{ * @return */ List findBorrowByUserId(Integer userId); + + /** + * 查询用户某一条借阅信息 + * @param userId 用户id + * @param bookId 图书id + */ + Borrow findBorrowByUserIdAndBookId(@Param("userId") Integer userId, @Param("bookId") Integer bookId); } diff --git a/src/main/java/com/book/manager/service/BookService.java b/src/main/java/com/book/manager/service/BookService.java index e8abf30..01fff9b 100644 --- a/src/main/java/com/book/manager/service/BookService.java +++ b/src/main/java/com/book/manager/service/BookService.java @@ -12,6 +12,7 @@ import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; @@ -46,6 +47,7 @@ public class BookService { * @param book 图书对象 * @return true or false */ + @Transactional public boolean updateBook(Book book) { return bookMapper.updateBook(BeanUtil.beanToMap(book))>0; } @@ -67,6 +69,14 @@ public class BookService { return null; } + public Book findBook(Integer id) { + Optional optional = bookRepository.findById(id); + if (optional.isPresent()) { + return optional.get(); + } + return null; + } + /** * ISBN查询 * @param isbn diff --git a/src/main/java/com/book/manager/service/BorrowService.java b/src/main/java/com/book/manager/service/BorrowService.java index 0a91313..1648970 100644 --- a/src/main/java/com/book/manager/service/BorrowService.java +++ b/src/main/java/com/book/manager/service/BorrowService.java @@ -1,10 +1,19 @@ package com.book.manager.service; +import com.book.manager.dao.BookMapper; import com.book.manager.dao.BorrowMapper; +import com.book.manager.dao.UsersMapper; +import com.book.manager.entity.Book; import com.book.manager.entity.Borrow; +import com.book.manager.entity.Users; +import com.book.manager.repos.BookRepository; import com.book.manager.repos.BorrowRepository; +import com.book.manager.util.consts.Constants; +import com.book.manager.util.vo.BookOut; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Optional; @@ -23,11 +32,58 @@ public class BorrowService { @Autowired private BorrowMapper borrowMapper; + @Autowired + private BookService bookService; + + @Autowired + private UserService userService; + /** * 添加 + * (添加事物) */ - public Borrow addBorrow(Borrow borrow) { - return borrowRepository.saveAndFlush(borrow); + @Transactional + public Integer addBorrow(Borrow borrow) { + Book book = bookService.findBook(borrow.getBookId()); + Users users = userService.findUserById(borrow.getUserId()); + + // 查询是否已经借阅过该图书 + Borrow bor = findBorrowByUserIdAndBookId(users.getId(),book.getId()); + if (bor!=null) { + Integer ret = bor.getRet(); + if (ret!=null) { + // 已借阅, 未归还 不可再借 + if (ret == Constants.NO) { + return Constants.BOOK_BORROWED; + } + } + } + + // 库存数量减一 + int size = book.getSize(); + if (size>0) { + size--; + book.setSize(size); + bookService.updateBook(book); + }else { + return Constants.BOOK_SIZE_NOT_ENOUGH; + } + + // 用户可借数量减一 + int userSize = users.getSize(); + if (userSize>0) { + userSize --; + users.setSize(userSize); + userService.updateUser(users); + }else { + return Constants.USER_SIZE_NOT_ENOUGH; + } + + // 添加借阅信息 + borrowRepository.saveAndFlush(borrow); + + // 一切正常 + return Constants.OK; } /** @@ -61,4 +117,13 @@ public class BorrowService { public void deleteBorrow(Integer id) { borrowRepository.deleteById(id); } + + /** + * 查询用户某一条借阅信息 + * @param userId 用户id + * @param bookId 图书id + */ + public Borrow findBorrowByUserIdAndBookId(int userId,int bookId) { + return borrowMapper.findBorrowByUserIdAndBookId(userId,bookId); + } } diff --git a/src/main/java/com/book/manager/service/UserService.java b/src/main/java/com/book/manager/service/UserService.java index 8129085..dca8a41 100644 --- a/src/main/java/com/book/manager/service/UserService.java +++ b/src/main/java/com/book/manager/service/UserService.java @@ -18,6 +18,7 @@ import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; @@ -72,6 +73,7 @@ public class UserService implements UserDetailsService{ * @param users 用户对象 * @return true or false */ + @Transactional public boolean updateUser(Users users) { return usersMapper.updateUsers(BeanUtil.beanToMap(users))>0; } @@ -129,4 +131,12 @@ public class UserService implements UserDetailsService{ // 数据库密码是明文, 需要加密进行比对 return new User(user.getUsername(), passwordEncoder.encode(user.getPassword()), authorities); } + + /** + * 用户名查询用户信息 + * @param username 用户名 + */ + public Users findByUsername(String username) { + return usersRepository.findByUsername(username); + } } diff --git a/src/main/java/com/book/manager/util/consts/Constants.java b/src/main/java/com/book/manager/util/consts/Constants.java index 70bb261..4819788 100644 --- a/src/main/java/com/book/manager/util/consts/Constants.java +++ b/src/main/java/com/book/manager/util/consts/Constants.java @@ -6,4 +6,16 @@ package com.book.manager.util.consts; */ public final class Constants { + /** 用户可解数量不足 */ + public static final int USER_SIZE_NOT_ENOUGH = -101; + /** 图书库存数量不足 */ + public static final int BOOK_SIZE_NOT_ENOUGH = -102; + /** 用户已借过该图书 */ + public static final int BOOK_BORROWED = -201; + /** 是 */ + public static final int YES = 0; + /** 否 */ + public static final int NO = 1; + /** 一切正常 */ + public static final int OK = 1; } diff --git a/src/main/java/com/book/manager/util/http/CodeEnum.java b/src/main/java/com/book/manager/util/http/CodeEnum.java index 5bc68a4..0433253 100644 --- a/src/main/java/com/book/manager/util/http/CodeEnum.java +++ b/src/main/java/com/book/manager/util/http/CodeEnum.java @@ -1,19 +1,27 @@ package com.book.manager.util.http; /** - * @Description TODO + * @Description 响应状态码枚举类 * @Date 2020/7/14 18:49 * @Author by 尘心 */ public enum CodeEnum { /** 请求成功 */ SUCCESS(200,"成功!"), + /** 您已借阅过该图书, 且未归还 */ + BOOK_BORROWED(300,"您已借阅过该图书, 且未归还!"), + /** 图书库存不够,无法借阅! */ + BOOK_NOT_ENOUGH(301,"图书库存不够,无法借阅!"), + /** 用户可借数量不够,无法借阅! */ + USER_NOT_ENOUGH(302,"用户可借数量不够,无法借阅!"), /** 找不到资源 */ NOT_FOUND(404,"找不到资源!"), /** 请求参数错误 */ PARAM_ERROR(444,"请求参数错误!"), /** 用户名或密码错误 */ NAME_OR_PASS_ERROR(445,"用户名或密码错误!"), + /** 找不到用户 */ + USER_NOT_FOUND(446,"找不到用户!"), /** 服务器发生异常 */ FAIL(500,"服务器发生异常!"); diff --git a/src/main/resources/mapper/BorrowMapper.xml b/src/main/resources/mapper/BorrowMapper.xml index a5e5e92..f42ba18 100644 --- a/src/main/resources/mapper/BorrowMapper.xml +++ b/src/main/resources/mapper/BorrowMapper.xml @@ -8,6 +8,7 @@ + \ No newline at end of file diff --git a/src/main/resources/templates/borrow/borrow.html b/src/main/resources/templates/borrow/borrow.html index 29d46a7..1baa847 100644 --- a/src/main/resources/templates/borrow/borrow.html +++ b/src/main/resources/templates/borrow/borrow.html @@ -117,14 +117,12 @@ \ No newline at end of file diff --git a/src/main/resources/templates/borrow/borrow.html b/src/main/resources/templates/borrow/borrow.html index 1baa847..b3d634c 100644 --- a/src/main/resources/templates/borrow/borrow.html +++ b/src/main/resources/templates/borrow/borrow.html @@ -270,7 +270,7 @@ content : msg, type : "error" }); - setTimeout(function(){},1000) + setTimeout(function(){},1500) } }, @@ -294,8 +294,8 @@ // 监听点击返回按钮事件 $("#return").click(function() { - alert("返回"); - // window.location.href = document.referrer; + // alert("返回"); + window.location.href = "/borrow/book-search"; }); // 日期格式化 -- Gitee From e10c9591f159c4bb87f7ab5e3e33202721a10c2a Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 24 Jul 2020 14:11:51 +0800 Subject: [PATCH 17/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9readme=E6=8F=8F?= =?UTF-8?q?=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 858734c..99bc411 100644 --- a/README.md +++ b/README.md @@ -39,10 +39,13 @@ 2. 不要说为啥这个项目这个东西没加, 哪个东西没加, 针对的层次不一样, 要求也不一样 3. 很多我也想加, 但是复杂起来了, 不适合目标人群使用 4. 为了方便大家使用, 并未对密码进行加密, 想要加密的:大家可以在插入用户的时候对密码加密, 在loadByUsername中去除密码加密即可 - +5. 如果想要前后端分离的, 只需要把web资源相关的去掉, 保留后端接口即可, 接口文档看swagger即可 #### 作者介绍 尘心, 英文名:Jason +写此项目的初心: 管理项目大多大相径庭, 通过一个例子, 掌握之后, 其他管理项目自然信手拈来. 所以它不仅仅是一个图书管理项目, +它是给大家提供一种开发的范例, 在这个范例的基础上进行修改优化吸收变成自己的东西才是这个项目价值所在! + #### 参与贡献 1. Fork 本仓库 -- Gitee From 90ac1fb3c91fc308b74694558c9d31e29a0f57e5 Mon Sep 17 00:00:00 2001 From: Jason Date: Fri, 24 Jul 2020 19:24:01 +0800 Subject: [PATCH 18/21] =?UTF-8?q?=E5=BD=92=E8=BF=98=E5=9B=BE=E4=B9=A6,=20?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E9=97=AE=E9=A2=98=E6=9A=82=E6=9C=AA=E8=A7=A3?= =?UTF-8?q?=E5=86=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 24 +++---- .../manager/controller/BorrowController.java | 12 +++- .../manager/controller/UsersController.java | 19 +++++- .../com/book/manager/dao/BorrowMapper.java | 6 +- .../java/com/book/manager/entity/Users.java | 2 +- .../com/book/manager/service/BookService.java | 1 - .../book/manager/service/BorrowService.java | 42 +++++++++++- .../book/manager/util/consts/Constants.java | 13 ++++ .../com/book/manager/util/ro/RetBookIn.java | 19 ++++++ .../com/book/manager/util/vo/UserOut.java | 17 +++++ src/main/resources/mapper/BorrowMapper.xml | 24 +++++++ src/main/resources/templates/borrow/back.html | 68 ++++++++++++------- 12 files changed, 202 insertions(+), 45 deletions(-) create mode 100644 src/main/java/com/book/manager/util/ro/RetBookIn.java create mode 100644 src/main/java/com/book/manager/util/vo/UserOut.java diff --git a/README.md b/README.md index 99bc411..b6870c3 100644 --- a/README.md +++ b/README.md @@ -24,18 +24,21 @@ - 这里真的要吹一波jQuery插件库,强大,耦合性低,加入即用, 非常适合本项目 #### 如果有定制需求, 可以联系作者 -- 质量保证, 从高大上到原生, 你要的我都有 +- 质量保证: 从高大上到原生, 你要的我都有 +- 联系方式: amazingjava@163.com +- 有意向聊一聊也是可以的蛮, 或许我就是你要找的那个人呢? #### 安装教程 1. 本地搭建好java8环境, 克隆项目 2. 配置maven, 等待依赖下载完成 -3. 启动访问http://localhost:8080 即可 -4. 默认登录: admin/123 -5. swagger API在线文档, 启动访问:http://localhost:8080/doc.html +3. IDE安装好lombok插件 +4. 启动访问http://localhost:8080 即可 +5. 账号:【学生: stu/123】【教师: tea/123】【其他:other/123】【管理员:admin/123】 +6. swagger API在线文档, 启动访问:http://localhost:8080/doc.html #### 使用说明 -1. 本项目适用于大学生实训, 或者个人学习使用 +1. 本项目适用于大学生实训, 或者想要快速搭建一个后台管理类项目的朋友,或者个人学习使用 2. 不要说为啥这个项目这个东西没加, 哪个东西没加, 针对的层次不一样, 要求也不一样 3. 很多我也想加, 但是复杂起来了, 不适合目标人群使用 4. 为了方便大家使用, 并未对密码进行加密, 想要加密的:大家可以在插入用户的时候对密码加密, 在loadByUsername中去除密码加密即可 @@ -46,6 +49,7 @@ 写此项目的初心: 管理项目大多大相径庭, 通过一个例子, 掌握之后, 其他管理项目自然信手拈来. 所以它不仅仅是一个图书管理项目, 它是给大家提供一种开发的范例, 在这个范例的基础上进行修改优化吸收变成自己的东西才是这个项目价值所在! +由于工作比较忙, 此项目也是比较仓促写成, 很多地方没有增加限制希望大家能够理解, 或者自己进行优化 #### 参与贡献 1. Fork 本仓库 @@ -53,13 +57,3 @@ 3. 提交代码 4. 新建 Pull Request 5. 等待审核 - - -#### 码云特技 - -1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md -2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com) -3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解码云上的优秀开源项目 -4. [GVP](https://gitee.com/gvp) 全称是码云最有价值开源项目,是码云综合评定出的优秀开源项目 -5. 码云官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) -6. 码云封面人物是一档用来展示码云会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/src/main/java/com/book/manager/controller/BorrowController.java b/src/main/java/com/book/manager/controller/BorrowController.java index 2af3feb..7425c2a 100644 --- a/src/main/java/com/book/manager/controller/BorrowController.java +++ b/src/main/java/com/book/manager/controller/BorrowController.java @@ -7,6 +7,7 @@ import com.book.manager.service.BorrowService; import com.book.manager.util.R; import com.book.manager.util.consts.Constants; import com.book.manager.util.http.CodeEnum; +import com.book.manager.util.ro.RetBookIn; import com.book.manager.util.vo.BackOut; import com.book.manager.util.vo.BookOut; import io.swagger.annotations.Api; @@ -69,7 +70,7 @@ public class BorrowController { return R.success(CodeEnum.SUCCESS,borrowService.findById(id)); } - @ApiOperation("归还图书") + @ApiOperation("删除归还记录") @GetMapping("/delete") public R delBorrow(Integer id) { borrowService.deleteBorrow(id); @@ -109,4 +110,13 @@ public class BorrowController { return R.success(CodeEnum.SUCCESS,outs); } + @ApiOperation("归还书籍") + @PostMapping("/ret") + public R retBook(@RequestBody RetBookIn in) { + if (in == null) { + return R.fail(CodeEnum.PARAM_ERROR); + } + return R.success(CodeEnum.SUCCESS,borrowService.retBook(in.getUserId(),in.getBookId())); + } + } diff --git a/src/main/java/com/book/manager/controller/UsersController.java b/src/main/java/com/book/manager/controller/UsersController.java index 8fee1f3..a1ee98f 100644 --- a/src/main/java/com/book/manager/controller/UsersController.java +++ b/src/main/java/com/book/manager/controller/UsersController.java @@ -5,12 +5,15 @@ import cn.hutool.core.util.StrUtil; import com.book.manager.entity.Users; import com.book.manager.service.UserService; import com.book.manager.util.R; +import com.book.manager.util.consts.Constants; import com.book.manager.util.http.CodeEnum; import com.book.manager.util.vo.PageOut; import com.book.manager.util.ro.PageIn; +import com.book.manager.util.vo.UserOut; import com.github.pagehelper.PageInfo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.*; @@ -82,7 +85,21 @@ public class UsersController { String username = (String) map.get("username"); if (StrUtil.isNotBlank(username)) { Users users = userService.findByUsername(username); - return R.success(CodeEnum.SUCCESS,users); + UserOut out = new UserOut(); + BeanUtils.copyProperties(users,out); + Integer identity = users.getIdentity(); + String ident = ""; + if (identity == Constants.STUDENT) { + ident = Constants.STU_STR; + }else if (identity == Constants.TEACHER) { + ident = Constants.TEA_STR; + }else if (identity == Constants.OTHER) { + ident = Constants.OTHER_STR; + }else if (identity == Constants.ADMIN) { + ident = Constants.ADMIN_STR; + } + out.setIdent(ident); + return R.success(CodeEnum.SUCCESS,out); } } return R.fail(CodeEnum.USER_NOT_FOUND); diff --git a/src/main/java/com/book/manager/dao/BorrowMapper.java b/src/main/java/com/book/manager/dao/BorrowMapper.java index 544e205..c763f3e 100644 --- a/src/main/java/com/book/manager/dao/BorrowMapper.java +++ b/src/main/java/com/book/manager/dao/BorrowMapper.java @@ -7,6 +7,8 @@ import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; import org.springframework.stereotype.Component; +import java.util.Map; + /** * @Description 借阅管理 * @Date 2020/7/15 16:45 @@ -21,4 +23,6 @@ public interface BorrowMapper { @Select("select * from borrow where user_id = #{userId} and book_id = #{bookId}") Borrow findBorrowByUserIdAndBookId(@Param("userId") Integer userId, @Param("bookId") Integer bookId); -} + + int updateBor(Map map); +} \ No newline at end of file diff --git a/src/main/java/com/book/manager/entity/Users.java b/src/main/java/com/book/manager/entity/Users.java index 9e74db7..e7ebf8a 100644 --- a/src/main/java/com/book/manager/entity/Users.java +++ b/src/main/java/com/book/manager/entity/Users.java @@ -59,7 +59,7 @@ public class Users { @ApiModelProperty("可借数量") private Integer size; - @ApiModelProperty("身份") + @ApiModelProperty("身份:0 学生,1 教师,2 管理员") private Integer identity; } diff --git a/src/main/java/com/book/manager/service/BookService.java b/src/main/java/com/book/manager/service/BookService.java index 01fff9b..ad396e7 100644 --- a/src/main/java/com/book/manager/service/BookService.java +++ b/src/main/java/com/book/manager/service/BookService.java @@ -47,7 +47,6 @@ public class BookService { * @param book 图书对象 * @return true or false */ - @Transactional public boolean updateBook(Book book) { return bookMapper.updateBook(BeanUtil.beanToMap(book))>0; } diff --git a/src/main/java/com/book/manager/service/BorrowService.java b/src/main/java/com/book/manager/service/BorrowService.java index 6585dd2..59faade 100644 --- a/src/main/java/com/book/manager/service/BorrowService.java +++ b/src/main/java/com/book/manager/service/BorrowService.java @@ -1,5 +1,6 @@ package com.book.manager.service; +import cn.hutool.core.bean.BeanUtil; import com.book.manager.dao.BookMapper; import com.book.manager.dao.BorrowMapper; import com.book.manager.dao.UsersMapper; @@ -15,6 +16,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Date; import java.util.List; import java.util.Optional; @@ -79,7 +81,9 @@ public class BorrowService { return Constants.USER_SIZE_NOT_ENOUGH; } - // 添加借阅信息 + + // 添加借阅信息, 借阅默认为未归还状态 + borrow.setRet(Constants.NO); borrowRepository.saveAndFlush(borrow); // 一切正常 @@ -119,6 +123,14 @@ public class BorrowService { return borrowMapper.updateBorrow(borrow)>0; } + + /** + * 编辑 + */ + public Borrow updateBorrowByRepo(Borrow borrow) { + return borrowRepository.saveAndFlush(borrow); + } + /** * s删除 */ @@ -134,4 +146,32 @@ public class BorrowService { public Borrow findBorrowByUserIdAndBookId(int userId,int bookId) { return borrowMapper.findBorrowByUserIdAndBookId(userId,bookId); } + + /** + * 归还书籍, 使用事务保证 ACID + * @param userId 用户Id + * @param bookId 书籍id + */ + @Transactional(rollbackFor = Exception.class) + public boolean retBook(int userId,int bookId) { + // 用户可借数量加1 + Users user = userService.findUserById(userId); + Integer size = user.getSize(); + size++; + user.setSize(size); + userService.updateUser(user); + + + // 书籍库存加1 + Book book = bookService.findBook(bookId); + Integer bookSize = book.getSize(); + bookSize++; + book.setSize(bookSize); + bookService.updateBook(book); + // 借阅记录改为已归还,删除记录 + Borrow borrow = this.findBorrowByUserIdAndBookId(userId, bookId); + borrow.setRet(Constants.YES); + borrow.setUpdateTime(new Date()); + return borrowMapper.updateBor(BeanUtil.beanToMap(borrow))>0; + } } diff --git a/src/main/java/com/book/manager/util/consts/Constants.java b/src/main/java/com/book/manager/util/consts/Constants.java index 79677d9..0dd0276 100644 --- a/src/main/java/com/book/manager/util/consts/Constants.java +++ b/src/main/java/com/book/manager/util/consts/Constants.java @@ -24,4 +24,17 @@ public final class Constants { public static final String NO_STR = "否"; /** 日期格式 */ public static final String DATE_FORMAT = "yyyy-MM-dd"; + /** 学生 */ + public static final int STUDENT = 0; + /** 教师 */ + public static final int TEACHER = 1; + /** 其他 */ + public static final int OTHER = 2; + /** 管理员 */ + public static final int ADMIN = 3; + /** 身份 */ + public static final String STU_STR = "学生"; + public static final String TEA_STR = "教师"; + public static final String OTHER_STR = "其他"; + public static final String ADMIN_STR = "管理员"; } diff --git a/src/main/java/com/book/manager/util/ro/RetBookIn.java b/src/main/java/com/book/manager/util/ro/RetBookIn.java new file mode 100644 index 0000000..1de998d --- /dev/null +++ b/src/main/java/com/book/manager/util/ro/RetBookIn.java @@ -0,0 +1,19 @@ +package com.book.manager.util.ro; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description 图书归还 ro 对象 + * @Date 2020/7/24 15:09 + * @Author by 尘心 + */ +@Data +public class RetBookIn { + + @ApiModelProperty("用户ID") + private Integer userId; + + @ApiModelProperty("图书ID") + private Integer bookId; +} diff --git a/src/main/java/com/book/manager/util/vo/UserOut.java b/src/main/java/com/book/manager/util/vo/UserOut.java new file mode 100644 index 0000000..00c0e59 --- /dev/null +++ b/src/main/java/com/book/manager/util/vo/UserOut.java @@ -0,0 +1,17 @@ +package com.book.manager.util.vo; + +import com.book.manager.entity.Users; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description 用户vo类 + * @Date 2020/7/24 14:29 + * @Author by 尘心 + */ +@Data +public class UserOut extends Users{ + + @ApiModelProperty("身份(中文:学生/教师/管理员)") + private String ident; +} diff --git a/src/main/resources/mapper/BorrowMapper.xml b/src/main/resources/mapper/BorrowMapper.xml index f42ba18..f72bceb 100644 --- a/src/main/resources/mapper/BorrowMapper.xml +++ b/src/main/resources/mapper/BorrowMapper.xml @@ -11,4 +11,28 @@ + + update borrow + + + user_id = #{userId}, + + + book_id = #{bookId}, + + + create_time = #{createTime}, + + + end_time = #{endTime}, + + + update_time = #{updateTime}, + + + ret = #{ret}, + + + where id = #{id} + \ No newline at end of file diff --git a/src/main/resources/templates/borrow/back.html b/src/main/resources/templates/borrow/back.html index 7032377..fefd776 100644 --- a/src/main/resources/templates/borrow/back.html +++ b/src/main/resources/templates/borrow/back.html @@ -90,13 +90,13 @@ -
        -
        - - - -
        -
        + + + + + + +
        @@ -112,7 +112,7 @@ // 渲染用户数据 $("#username").val(user.username); $("#nickname").val(user.nickname); - $("#identity").val(user.identity); + $("#identity").val(user.ident); $("#size").val(user.size); // 2. 查询用户借阅信息, 并渲染借阅列表 @@ -126,7 +126,7 @@ text+= ""+num+""+value.name+""+value.author+""+value.isbn+"" + ""+value.pages+""+value.price+""+value.publish+""+value.type+"" + ""+value.borrowTime+""+value.endTime+""+value.late+""+ - "
        ",success:function(e,i){s.bigimg=e.find(".layui-layer-phimg"),s.imgsee=e.find(".layui-layer-imguide,.layui-layer-imgbar"),s.event(e),t.tab&&t.tab(u[d],e),"function"==typeof y&&y(e)},end:function(){s.end=!0,i(document).off("keyup",s.keyup)}},t))},function(){r.close(s.loadi),r.msg("当前图片地址异常
        是否继续查看下一张?",{time:3e4,btn:["下一张","不看了"],yes:function(){u.length>1&&s.imgnext(!0,!0)}})})}},o.run=function(t){i=t,n=i(e),l.html=i("html"),r.open=function(e){var t=new s(e);return t.index}},e.layui&&layui.define?(r.ready(),layui.define("jquery",function(t){r.path=layui.cache.dir,o.run(layui.$),e.layer=r,t("layer",r)})):"function"==typeof define&&define.amd?define(["jquery"],function(){return o.run(e.jQuery),r}):function(){o.run(e.jQuery),r.ready()}()}(window); \ No newline at end of file diff --git a/src/main/resources/static/layer/layer.js b/src/main/resources/static/layer/layer.js new file mode 100644 index 0000000..12cb6b5 --- /dev/null +++ b/src/main/resources/static/layer/layer.js @@ -0,0 +1,2 @@ +/*! layer-v3.1.1 Web弹层组件 MIT License http://layer.layui.com/ By 贤心 */ + ;!function(e,t){"use strict";var i,n,a=e.layui&&layui.define,o={getPath:function(){var e=document.currentScript?document.currentScript.src:function(){for(var e,t=document.scripts,i=t.length-1,n=i;n>0;n--)if("interactive"===t[n].readyState){e=t[n].src;break}return e||t[i].src}();return e.substring(0,e.lastIndexOf("/")+1)}(),config:{},end:{},minIndex:0,minLeft:[],btn:["确定","取消"],type:["dialog","page","iframe","loading","tips"],getStyle:function(t,i){var n=t.currentStyle?t.currentStyle:e.getComputedStyle(t,null);return n[n.getPropertyValue?"getPropertyValue":"getAttribute"](i)},link:function(t,i,n){if(r.path){var a=document.getElementsByTagName("head")[0],s=document.createElement("link");"string"==typeof i&&(n=i);var l=(n||t).replace(/\.|\//g,""),f="layuicss-"+l,c=0;s.rel="stylesheet",s.href=r.path+t,s.id=f,document.getElementById(f)||a.appendChild(s),"function"==typeof i&&!function u(){return++c>80?e.console&&console.error("layer.css: Invalid"):void(1989===parseInt(o.getStyle(document.getElementById(f),"width"))?i():setTimeout(u,100))}()}}},r={v:"3.1.1",ie:function(){var t=navigator.userAgent.toLowerCase();return!!(e.ActiveXObject||"ActiveXObject"in e)&&((t.match(/msie\s(\d+)/)||[])[1]||"11")}(),index:e.layer&&e.layer.v?1e5:0,path:o.getPath,config:function(e,t){return e=e||{},r.cache=o.config=i.extend({},o.config,e),r.path=o.config.path||r.path,"string"==typeof e.extend&&(e.extend=[e.extend]),o.config.path&&r.ready(),e.extend?(a?layui.addcss("modules/layer/"+e.extend):o.link("theme/"+e.extend),this):this},ready:function(e){var t="layer",i="",n=(a?"modules/layer/":"theme/")+"default/layer.css?v="+r.v+i;return a?layui.addcss(n,e,t):o.link(n,e,t),this},alert:function(e,t,n){var a="function"==typeof t;return a&&(n=t),r.open(i.extend({content:e,yes:n},a?{}:t))},confirm:function(e,t,n,a){var s="function"==typeof t;return s&&(a=n,n=t),r.open(i.extend({content:e,btn:o.btn,yes:n,btn2:a},s?{}:t))},msg:function(e,n,a){var s="function"==typeof n,f=o.config.skin,c=(f?f+" "+f+"-msg":"")||"layui-layer-msg",u=l.anim.length-1;return s&&(a=n),r.open(i.extend({content:e,time:3e3,shade:!1,skin:c,title:!1,closeBtn:!1,btn:!1,resize:!1,end:a},s&&!o.config.skin?{skin:c+" layui-layer-hui",anim:u}:function(){return n=n||{},(n.icon===-1||n.icon===t&&!o.config.skin)&&(n.skin=c+" "+(n.skin||"layui-layer-hui")),n}()))},load:function(e,t){return r.open(i.extend({type:3,icon:e||0,resize:!1,shade:.01},t))},tips:function(e,t,n){return r.open(i.extend({type:4,content:[e,t],closeBtn:!1,time:3e3,shade:!1,resize:!1,fixed:!1,maxWidth:210},n))}},s=function(e){var t=this;t.index=++r.index,t.config=i.extend({},t.config,o.config,e),document.body?t.creat():setTimeout(function(){t.creat()},30)};s.pt=s.prototype;var l=["layui-layer",".layui-layer-title",".layui-layer-main",".layui-layer-dialog","layui-layer-iframe","layui-layer-content","layui-layer-btn","layui-layer-close"];l.anim=["layer-anim-00","layer-anim-01","layer-anim-02","layer-anim-03","layer-anim-04","layer-anim-05","layer-anim-06"],s.pt.config={type:0,shade:.3,fixed:!0,move:l[1],title:"信息",offset:"auto",area:"auto",closeBtn:1,time:0,zIndex:19891014,maxWidth:360,anim:0,isOutAnim:!0,icon:-1,moveType:1,resize:!0,scrollbar:!0,tips:2},s.pt.vessel=function(e,t){var n=this,a=n.index,r=n.config,s=r.zIndex+a,f="object"==typeof r.title,c=r.maxmin&&(1===r.type||2===r.type),u=r.title?'
        '+(f?r.title[0]:r.title)+"
        ":"";return r.zIndex=s,t([r.shade?'
        ':"",'
        '+(e&&2!=r.type?"":u)+'
        '+(0==r.type&&r.icon!==-1?'':"")+(1==r.type&&e?"":r.content||"")+'
        '+function(){var e=c?'':"";return r.closeBtn&&(e+=''),e}()+""+(r.btn?function(){var e="";"string"==typeof r.btn&&(r.btn=[r.btn]);for(var t=0,i=r.btn.length;t'+r.btn[t]+"";return'
        '+e+"
        "}():"")+(r.resize?'':"")+"
        "],u,i('
        ')),n},s.pt.creat=function(){var e=this,t=e.config,a=e.index,s=t.content,f="object"==typeof s,c=i("body");if(!t.id||!i("#"+t.id)[0]){switch("string"==typeof t.area&&(t.area="auto"===t.area?["",""]:[t.area,""]),t.shift&&(t.anim=t.shift),6==r.ie&&(t.fixed=!1),t.type){case 0:t.btn="btn"in t?t.btn:o.btn[0],r.closeAll("dialog");break;case 2:var s=t.content=f?t.content:[t.content||"http://layer.layui.com","auto"];t.content='';break;case 3:delete t.title,delete t.closeBtn,t.icon===-1&&0===t.icon,r.closeAll("loading");break;case 4:f||(t.content=[t.content,"body"]),t.follow=t.content[1],t.content=t.content[0]+'',delete t.title,t.tips="object"==typeof t.tips?t.tips:[t.tips,!0],t.tipsMore||r.closeAll("tips")}if(e.vessel(f,function(n,r,u){c.append(n[0]),f?function(){2==t.type||4==t.type?function(){i("body").append(n[1])}():function(){s.parents("."+l[0])[0]||(s.data("display",s.css("display")).show().addClass("layui-layer-wrap").wrap(n[1]),i("#"+l[0]+a).find("."+l[5]).before(r))}()}():c.append(n[1]),i(".layui-layer-move")[0]||c.append(o.moveElem=u),e.layero=i("#"+l[0]+a),t.scrollbar||l.html.css("overflow","hidden").attr("layer-full",a)}).auto(a),i("#layui-layer-shade"+e.index).css({"background-color":t.shade[1]||"#000",opacity:t.shade[0]||t.shade}),2==t.type&&6==r.ie&&e.layero.find("iframe").attr("src",s[0]),4==t.type?e.tips():e.offset(),t.fixed&&n.on("resize",function(){e.offset(),(/^\d+%$/.test(t.area[0])||/^\d+%$/.test(t.area[1]))&&e.auto(a),4==t.type&&e.tips()}),t.time<=0||setTimeout(function(){r.close(e.index)},t.time),e.move().callback(),l.anim[t.anim]){var u="layer-anim "+l.anim[t.anim];e.layero.addClass(u).one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",function(){i(this).removeClass(u)})}t.isOutAnim&&e.layero.data("isOutAnim",!0)}},s.pt.auto=function(e){var t=this,a=t.config,o=i("#"+l[0]+e);""===a.area[0]&&a.maxWidth>0&&(r.ie&&r.ie<8&&a.btn&&o.width(o.innerWidth()),o.outerWidth()>a.maxWidth&&o.width(a.maxWidth));var s=[o.innerWidth(),o.innerHeight()],f=o.find(l[1]).outerHeight()||0,c=o.find("."+l[6]).outerHeight()||0,u=function(e){e=o.find(e),e.height(s[1]-f-c-2*(0|parseFloat(e.css("padding-top"))))};switch(a.type){case 2:u("iframe");break;default:""===a.area[1]?a.maxHeight>0&&o.outerHeight()>a.maxHeight?(s[1]=a.maxHeight,u("."+l[5])):a.fixed&&s[1]>=n.height()&&(s[1]=n.height(),u("."+l[5])):u("."+l[5])}return t},s.pt.offset=function(){var e=this,t=e.config,i=e.layero,a=[i.outerWidth(),i.outerHeight()],o="object"==typeof t.offset;e.offsetTop=(n.height()-a[1])/2,e.offsetLeft=(n.width()-a[0])/2,o?(e.offsetTop=t.offset[0],e.offsetLeft=t.offset[1]||e.offsetLeft):"auto"!==t.offset&&("t"===t.offset?e.offsetTop=0:"r"===t.offset?e.offsetLeft=n.width()-a[0]:"b"===t.offset?e.offsetTop=n.height()-a[1]:"l"===t.offset?e.offsetLeft=0:"lt"===t.offset?(e.offsetTop=0,e.offsetLeft=0):"lb"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=0):"rt"===t.offset?(e.offsetTop=0,e.offsetLeft=n.width()-a[0]):"rb"===t.offset?(e.offsetTop=n.height()-a[1],e.offsetLeft=n.width()-a[0]):e.offsetTop=t.offset),t.fixed||(e.offsetTop=/%$/.test(e.offsetTop)?n.height()*parseFloat(e.offsetTop)/100:parseFloat(e.offsetTop),e.offsetLeft=/%$/.test(e.offsetLeft)?n.width()*parseFloat(e.offsetLeft)/100:parseFloat(e.offsetLeft),e.offsetTop+=n.scrollTop(),e.offsetLeft+=n.scrollLeft()),i.attr("minLeft")&&(e.offsetTop=n.height()-(i.find(l[1]).outerHeight()||0),e.offsetLeft=i.css("left")),i.css({top:e.offsetTop,left:e.offsetLeft})},s.pt.tips=function(){var e=this,t=e.config,a=e.layero,o=[a.outerWidth(),a.outerHeight()],r=i(t.follow);r[0]||(r=i("body"));var s={width:r.outerWidth(),height:r.outerHeight(),top:r.offset().top,left:r.offset().left},f=a.find(".layui-layer-TipsG"),c=t.tips[0];t.tips[1]||f.remove(),s.autoLeft=function(){s.left+o[0]-n.width()>0?(s.tipLeft=s.left+s.width-o[0],f.css({right:12,left:"auto"})):s.tipLeft=s.left},s.where=[function(){s.autoLeft(),s.tipTop=s.top-o[1]-10,f.removeClass("layui-layer-TipsB").addClass("layui-layer-TipsT").css("border-right-color",t.tips[1])},function(){s.tipLeft=s.left+s.width+10,s.tipTop=s.top,f.removeClass("layui-layer-TipsL").addClass("layui-layer-TipsR").css("border-bottom-color",t.tips[1])},function(){s.autoLeft(),s.tipTop=s.top+s.height+10,f.removeClass("layui-layer-TipsT").addClass("layui-layer-TipsB").css("border-right-color",t.tips[1])},function(){s.tipLeft=s.left-o[0]-10,s.tipTop=s.top,f.removeClass("layui-layer-TipsR").addClass("layui-layer-TipsL").css("border-bottom-color",t.tips[1])}],s.where[c-1](),1===c?s.top-(n.scrollTop()+o[1]+16)<0&&s.where[2]():2===c?n.width()-(s.left+s.width+o[0]+16)>0||s.where[3]():3===c?s.top-n.scrollTop()+s.height+o[1]+16-n.height()>0&&s.where[0]():4===c&&o[0]+16-s.left>0&&s.where[1](),a.find("."+l[5]).css({"background-color":t.tips[1],"padding-right":t.closeBtn?"30px":""}),a.css({left:s.tipLeft-(t.fixed?n.scrollLeft():0),top:s.tipTop-(t.fixed?n.scrollTop():0)})},s.pt.move=function(){var e=this,t=e.config,a=i(document),s=e.layero,l=s.find(t.move),f=s.find(".layui-layer-resize"),c={};return t.move&&l.css("cursor","move"),l.on("mousedown",function(e){e.preventDefault(),t.move&&(c.moveStart=!0,c.offset=[e.clientX-parseFloat(s.css("left")),e.clientY-parseFloat(s.css("top"))],o.moveElem.css("cursor","move").show())}),f.on("mousedown",function(e){e.preventDefault(),c.resizeStart=!0,c.offset=[e.clientX,e.clientY],c.area=[s.outerWidth(),s.outerHeight()],o.moveElem.css("cursor","se-resize").show()}),a.on("mousemove",function(i){if(c.moveStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1],l="fixed"===s.css("position");if(i.preventDefault(),c.stX=l?0:n.scrollLeft(),c.stY=l?0:n.scrollTop(),!t.moveOut){var f=n.width()-s.outerWidth()+c.stX,u=n.height()-s.outerHeight()+c.stY;af&&(a=f),ou&&(o=u)}s.css({left:a,top:o})}if(t.resize&&c.resizeStart){var a=i.clientX-c.offset[0],o=i.clientY-c.offset[1];i.preventDefault(),r.style(e.index,{width:c.area[0]+a,height:c.area[1]+o}),c.isResize=!0,t.resizing&&t.resizing(s)}}).on("mouseup",function(e){c.moveStart&&(delete c.moveStart,o.moveElem.hide(),t.moveEnd&&t.moveEnd(s)),c.resizeStart&&(delete c.resizeStart,o.moveElem.hide())}),e},s.pt.callback=function(){function e(){var e=a.cancel&&a.cancel(t.index,n);e===!1||r.close(t.index)}var t=this,n=t.layero,a=t.config;t.openLayer(),a.success&&(2==a.type?n.find("iframe").on("load",function(){a.success(n,t.index)}):a.success(n,t.index)),6==r.ie&&t.IE6(n),n.find("."+l[6]).children("a").on("click",function(){var e=i(this).index();if(0===e)a.yes?a.yes(t.index,n):a.btn1?a.btn1(t.index,n):r.close(t.index);else{var o=a["btn"+(e+1)]&&a["btn"+(e+1)](t.index,n);o===!1||r.close(t.index)}}),n.find("."+l[7]).on("click",e),a.shadeClose&&i("#layui-layer-shade"+t.index).on("click",function(){r.close(t.index)}),n.find(".layui-layer-min").on("click",function(){var e=a.min&&a.min(n);e===!1||r.min(t.index,a)}),n.find(".layui-layer-max").on("click",function(){i(this).hasClass("layui-layer-maxmin")?(r.restore(t.index),a.restore&&a.restore(n)):(r.full(t.index,a),setTimeout(function(){a.full&&a.full(n)},100))}),a.end&&(o.end[t.index]=a.end)},o.reselect=function(){i.each(i("select"),function(e,t){var n=i(this);n.parents("."+l[0])[0]||1==n.attr("layer")&&i("."+l[0]).length<1&&n.removeAttr("layer").show(),n=null})},s.pt.IE6=function(e){i("select").each(function(e,t){var n=i(this);n.parents("."+l[0])[0]||"none"===n.css("display")||n.attr({layer:"1"}).hide(),n=null})},s.pt.openLayer=function(){var e=this;r.zIndex=e.config.zIndex,r.setTop=function(e){var t=function(){r.zIndex++,e.css("z-index",r.zIndex+1)};return r.zIndex=parseInt(e[0].style.zIndex),e.on("mousedown",t),r.zIndex}},o.record=function(e){var t=[e.width(),e.height(),e.position().top,e.position().left+parseFloat(e.css("margin-left"))];e.find(".layui-layer-max").addClass("layui-layer-maxmin"),e.attr({area:t})},o.rescollbar=function(e){l.html.attr("layer-full")==e&&(l.html[0].style.removeProperty?l.html[0].style.removeProperty("overflow"):l.html[0].style.removeAttribute("overflow"),l.html.removeAttr("layer-full"))},e.layer=r,r.getChildFrame=function(e,t){return t=t||i("."+l[4]).attr("times"),i("#"+l[0]+t).find("iframe").contents().find(e)},r.getFrameIndex=function(e){return i("#"+e).parents("."+l[4]).attr("times")},r.iframeAuto=function(e){if(e){var t=r.getChildFrame("html",e).outerHeight(),n=i("#"+l[0]+e),a=n.find(l[1]).outerHeight()||0,o=n.find("."+l[6]).outerHeight()||0;n.css({height:t+a+o}),n.find("iframe").css({height:t})}},r.iframeSrc=function(e,t){i("#"+l[0]+e).find("iframe").attr("src",t)},r.style=function(e,t,n){var a=i("#"+l[0]+e),r=a.find(".layui-layer-content"),s=a.attr("type"),f=a.find(l[1]).outerHeight()||0,c=a.find("."+l[6]).outerHeight()||0;a.attr("minLeft");s!==o.type[3]&&s!==o.type[4]&&(n||(parseFloat(t.width)<=260&&(t.width=260),parseFloat(t.height)-f-c<=64&&(t.height=64+f+c)),a.css(t),c=a.find("."+l[6]).outerHeight(),s===o.type[2]?a.find("iframe").css({height:parseFloat(t.height)-f-c}):r.css({height:parseFloat(t.height)-f-c-parseFloat(r.css("padding-top"))-parseFloat(r.css("padding-bottom"))}))},r.min=function(e,t){var a=i("#"+l[0]+e),s=a.find(l[1]).outerHeight()||0,f=a.attr("minLeft")||181*o.minIndex+"px",c=a.css("position");o.record(a),o.minLeft[0]&&(f=o.minLeft[0],o.minLeft.shift()),a.attr("position",c),r.style(e,{width:180,height:s,left:f,top:n.height()-s,position:"fixed",overflow:"hidden"},!0),a.find(".layui-layer-min").hide(),"page"===a.attr("type")&&a.find(l[4]).hide(),o.rescollbar(e),a.attr("minLeft")||o.minIndex++,a.attr("minLeft",f)},r.restore=function(e){var t=i("#"+l[0]+e),n=t.attr("area").split(",");t.attr("type");r.style(e,{width:parseFloat(n[0]),height:parseFloat(n[1]),top:parseFloat(n[2]),left:parseFloat(n[3]),position:t.attr("position"),overflow:"visible"},!0),t.find(".layui-layer-max").removeClass("layui-layer-maxmin"),t.find(".layui-layer-min").show(),"page"===t.attr("type")&&t.find(l[4]).show(),o.rescollbar(e)},r.full=function(e){var t,a=i("#"+l[0]+e);o.record(a),l.html.attr("layer-full")||l.html.css("overflow","hidden").attr("layer-full",e),clearTimeout(t),t=setTimeout(function(){var t="fixed"===a.css("position");r.style(e,{top:t?0:n.scrollTop(),left:t?0:n.scrollLeft(),width:n.width(),height:n.height()},!0),a.find(".layui-layer-min").hide()},100)},r.title=function(e,t){var n=i("#"+l[0]+(t||r.index)).find(l[1]);n.html(e)},r.close=function(e){var t=i("#"+l[0]+e),n=t.attr("type"),a="layer-anim-close";if(t[0]){var s="layui-layer-wrap",f=function(){if(n===o.type[1]&&"object"===t.attr("conType")){t.children(":not(."+l[5]+")").remove();for(var a=t.find("."+s),r=0;r<2;r++)a.unwrap();a.css("display",a.data("display")).removeClass(s)}else{if(n===o.type[2])try{var f=i("#"+l[4]+e)[0];f.contentWindow.document.write(""),f.contentWindow.close(),t.find("."+l[5])[0].removeChild(f)}catch(c){}t[0].innerHTML="",t.remove()}"function"==typeof o.end[e]&&o.end[e](),delete o.end[e]};t.data("isOutAnim")&&t.addClass("layer-anim "+a),i("#layui-layer-moves, #layui-layer-shade"+e).remove(),6==r.ie&&o.reselect(),o.rescollbar(e),t.attr("minLeft")&&(o.minIndex--,o.minLeft.push(t.attr("minLeft"))),r.ie&&r.ie<10||!t.data("isOutAnim")?f():setTimeout(function(){f()},200)}},r.closeAll=function(e){i.each(i("."+l[0]),function(){var t=i(this),n=e?t.attr("type")===e:1;n&&r.close(t.attr("times")),n=null})};var f=r.cache||{},c=function(e){return f.skin?" "+f.skin+" "+f.skin+"-"+e:""};r.prompt=function(e,t){var a="";if(e=e||{},"function"==typeof e&&(t=e),e.area){var o=e.area;a='style="width: '+o[0]+"; height: "+o[1]+';"',delete e.area}var s,l=2==e.formType?'":function(){return''}(),f=e.success;return delete e.success,r.open(i.extend({type:1,btn:["确定","取消"],content:l,skin:"layui-layer-prompt"+c("prompt"),maxWidth:n.width(),success:function(e){s=e.find(".layui-layer-input"),s.focus(),"function"==typeof f&&f(e)},resize:!1,yes:function(i){var n=s.val();""===n?s.focus():n.length>(e.maxlength||500)?r.tips("最多输入"+(e.maxlength||500)+"个字数",s,{tips:1}):t&&t(n,i,s)}},e))},r.tab=function(e){e=e||{};var t=e.tab||{},n="layui-this",a=e.success;return delete e.success,r.open(i.extend({type:1,skin:"layui-layer-tab"+c("tab"),resize:!1,title:function(){var e=t.length,i=1,a="";if(e>0)for(a=''+t[0].title+"";i"+t[i].title+"";return a}(),content:'
          '+function(){var e=t.length,i=1,a="";if(e>0)for(a='
        • '+(t[0].content||"no content")+"
        • ";i'+(t[i].content||"no content")+"";return a}()+"
        ",success:function(t){var o=t.find(".layui-layer-title").children(),r=t.find(".layui-layer-tabmain").children();o.on("mousedown",function(t){t.stopPropagation?t.stopPropagation():t.cancelBubble=!0;var a=i(this),o=a.index();a.addClass(n).siblings().removeClass(n),r.eq(o).show().siblings().hide(),"function"==typeof e.change&&e.change(o)}),"function"==typeof a&&a(t)}},e))},r.photos=function(t,n,a){function o(e,t,i){var n=new Image;return n.src=e,n.complete?t(n):(n.onload=function(){n.onload=null,t(n)},void(n.onerror=function(e){n.onerror=null,i(e)}))}var s={};if(t=t||{},t.photos){var l=t.photos.constructor===Object,f=l?t.photos:{},u=f.data||[],d=f.start||0;s.imgIndex=(0|d)+1,t.img=t.img||"img";var y=t.success;if(delete t.success,l){if(0===u.length)return r.msg("没有图片")}else{var p=i(t.photos),h=function(){u=[],p.find(t.img).each(function(e){var t=i(this);t.attr("layer-index",e),u.push({alt:t.attr("alt"),pid:t.attr("layer-pid"),src:t.attr("layer-src")||t.attr("src"),thumb:t.attr("src")})})};if(h(),0===u.length)return;if(n||p.on("click",t.img,function(){var e=i(this),n=e.attr("layer-index");r.photos(i.extend(t,{photos:{start:n,data:u,tab:t.tab},full:t.full}),!0),h()}),!n)return}s.imgprev=function(e){s.imgIndex--,s.imgIndex<1&&(s.imgIndex=u.length),s.tabimg(e)},s.imgnext=function(e,t){s.imgIndex++,s.imgIndex>u.length&&(s.imgIndex=1,t)||s.tabimg(e)},s.keyup=function(e){if(!s.end){var t=e.keyCode;e.preventDefault(),37===t?s.imgprev(!0):39===t?s.imgnext(!0):27===t&&r.close(s.index)}},s.tabimg=function(e){if(!(u.length<=1))return f.start=s.imgIndex-1,r.close(s.index),r.photos(t,!0,e)},s.event=function(){s.bigimg.hover(function(){s.imgsee.show()},function(){s.imgsee.hide()}),s.bigimg.find(".layui-layer-imgprev").on("click",function(e){e.preventDefault(),s.imgprev()}),s.bigimg.find(".layui-layer-imgnext").on("click",function(e){e.preventDefault(),s.imgnext()}),i(document).on("keyup",s.keyup)},s.loadi=r.load(1,{shade:!("shade"in t)&&.9,scrollbar:!1}),o(u[d].src,function(n){r.close(s.loadi),s.index=r.open(i.extend({type:1,id:"layui-layer-photos",area:function(){var a=[n.width,n.height],o=[i(e).width()-100,i(e).height()-100];if(!t.full&&(a[0]>o[0]||a[1]>o[1])){var r=[a[0]/o[0],a[1]/o[1]];r[0]>r[1]?(a[0]=a[0]/r[0],a[1]=a[1]/r[0]):r[0]'+(u[d].alt||
        '+(u.length>1?'':"")+'
        '+(u[d].alt||"")+""+s.imgIndex+"/"+u.length+"
        ",success:function(e,i){s.bigimg=e.find(".layui-layer-phimg"),s.imgsee=e.find(".layui-layer-imguide,.layui-layer-imgbar"),s.event(e),t.tab&&t.tab(u[d],e),"function"==typeof y&&y(e)},end:function(){s.end=!0,i(document).off("keyup",s.keyup)}},t))},function(){r.close(s.loadi),r.msg("当前图片地址异常
        是否继续查看下一张?",{time:3e4,btn:["下一张","不看了"],yes:function(){u.length>1&&s.imgnext(!0,!0)}})})}},o.run=function(t){i=t,n=i(e),l.html=i("html"),r.open=function(e){var t=new s(e);return t.index}},e.layui&&layui.define?(r.ready(),layui.define("jquery",function(t){r.path=layui.cache.dir,o.run(layui.$),e.layer=r,t("layer",r)})):"function"==typeof define&&define.amd?define(["jquery"],function(){return o.run(e.jQuery),r}):function(){o.run(e.jQuery),r.ready()}()}(window); \ No newline at end of file diff --git a/src/main/resources/static/layer/mobile/layer.js b/src/main/resources/static/layer/mobile/layer.js new file mode 100644 index 0000000..f9cf693 --- /dev/null +++ b/src/main/resources/static/layer/mobile/layer.js @@ -0,0 +1,2 @@ +/*! layer mobile-v2.0.0 Web弹层组件 MIT License http://layer.layui.com/mobile By 贤心 */ + ;!function(e){"use strict";var t=document,n="querySelectorAll",i="getElementsByClassName",a=function(e){return t[n](e)},s={type:0,shade:!0,shadeClose:!0,fixed:!0,anim:"scale"},l={extend:function(e){var t=JSON.parse(JSON.stringify(s));for(var n in e)t[n]=e[n];return t},timer:{},end:{}};l.touch=function(e,t){e.addEventListener("click",function(e){t.call(this,e)},!1)};var r=0,o=["layui-m-layer"],c=function(e){var t=this;t.config=l.extend(e),t.view()};c.prototype.view=function(){var e=this,n=e.config,s=t.createElement("div");e.id=s.id=o[0]+r,s.setAttribute("class",o[0]+" "+o[0]+(n.type||0)),s.setAttribute("index",r);var l=function(){var e="object"==typeof n.title;return n.title?'

        '+(e?n.title[0]:n.title)+"

        ":""}(),c=function(){"string"==typeof n.btn&&(n.btn=[n.btn]);var e,t=(n.btn||[]).length;return 0!==t&&n.btn?(e=''+n.btn[0]+"",2===t&&(e=''+n.btn[1]+""+e),'
        '+e+"
        "):""}();if(n.fixed||(n.top=n.hasOwnProperty("top")?n.top:100,n.style=n.style||"",n.style+=" top:"+(t.body.scrollTop+n.top)+"px"),2===n.type&&(n.content='

        '+(n.content||"")+"

        "),n.skin&&(n.anim="up"),"msg"===n.skin&&(n.shade=!1),s.innerHTML=(n.shade?"
        ':"")+'
        "+l+'
        '+n.content+"
        "+c+"
        ",!n.type||2===n.type){var d=t[i](o[0]+n.type),y=d.length;y>=1&&layer.close(d[0].getAttribute("index"))}document.body.appendChild(s);var u=e.elem=a("#"+e.id)[0];n.success&&n.success(u),e.index=r++,e.action(n,u)},c.prototype.action=function(e,t){var n=this;e.time&&(l.timer[n.index]=setTimeout(function(){layer.close(n.index)},1e3*e.time));var a=function(){var t=this.getAttribute("type");0==t?(e.no&&e.no(),layer.close(n.index)):e.yes?e.yes(n.index):layer.close(n.index)};if(e.btn)for(var s=t[i]("layui-m-layerbtn")[0].children,r=s.length,o=0;odiv{line-height:22px;padding-top:7px;margin-bottom:20px;font-size:14px}.layui-m-layerbtn{display:box;display:-moz-box;display:-webkit-box;width:100%;height:50px;line-height:50px;font-size:0;border-top:1px solid #D0D0D0;background-color:#F2F2F2}.layui-m-layerbtn span{display:block;-moz-box-flex:1;box-flex:1;-webkit-box-flex:1;font-size:14px;cursor:pointer}.layui-m-layerbtn span[yes]{color:#40AFFE}.layui-m-layerbtn span[no]{border-right:1px solid #D0D0D0;border-radius:0 0 0 5px}.layui-m-layerbtn span:active{background-color:#F6F6F6}.layui-m-layerend{position:absolute;right:7px;top:10px;width:30px;height:30px;border:0;font-weight:400;background:0 0;cursor:pointer;-webkit-appearance:none;font-size:30px}.layui-m-layerend::after,.layui-m-layerend::before{position:absolute;left:5px;top:15px;content:'';width:18px;height:1px;background-color:#999;transform:rotate(45deg);-webkit-transform:rotate(45deg);border-radius:3px}.layui-m-layerend::after{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}body .layui-m-layer .layui-m-layer-footer{position:fixed;width:95%;max-width:100%;margin:0 auto;left:0;right:0;bottom:10px;background:0 0}.layui-m-layer-footer .layui-m-layercont{padding:20px;border-radius:5px 5px 0 0;background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn{display:block;height:auto;background:0 0;border-top:none}.layui-m-layer-footer .layui-m-layerbtn span{background-color:rgba(255,255,255,.8)}.layui-m-layer-footer .layui-m-layerbtn span[no]{color:#FD482C;border-top:1px solid #c2c2c2;border-radius:0 0 5px 5px}.layui-m-layer-footer .layui-m-layerbtn span[yes]{margin-top:10px;border-radius:5px}body .layui-m-layer .layui-m-layer-msg{width:auto;max-width:90%;margin:0 auto;bottom:-150px;background-color:rgba(0,0,0,.7);color:#fff}.layui-m-layer-msg .layui-m-layercont{padding:10px 20px} \ No newline at end of file diff --git a/src/main/resources/static/layer/theme/default/icon-ext.png b/src/main/resources/static/layer/theme/default/icon-ext.png new file mode 100644 index 0000000000000000000000000000000000000000..bbbb669bb311514baa5db3a6a00b4644d0e280f1 GIT binary patch literal 5911 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 bWW^%>x7XlHV^#Q1uOX^B?ki3(VEg|7!QHuF literal 0 HcmV?d00001 diff --git a/src/main/resources/static/layer/theme/default/loading-1.gif b/src/main/resources/static/layer/theme/default/loading-1.gif new file mode 100644 index 0000000000000000000000000000000000000000..db3a483e4b74971fbfb1cc0fb6499852cedfe650 GIT binary patch literal 701 zcmZ?wbhEHbRAo?Qn8?Ji_w)@mZNLBj|1&T!DE{a6a}5c0b_{Se(lcOY1PT3QVdY|A zV$cDyff`g97?`@J^shYqmS1s(LX_+4yGox$4el*+Jm?ved2^25GBru=T^dGm#<906 za&AQCZ08H8P;Bd&{NT;vl&}c_^L4%p?g_hjBu{YB29{c>Ob}p@z~Ks3xCw+@!HClp xtZ<(QPf3`00FNu+VbOvoEE+h73k#4LIKl$IE8t;)<_eUs!0QU6uz&iJhvXcHF*h)T1OnEW1i^?zgDfop1p?usL*#PMGT;HQkSO{q6FlJyb$PWkPf|h*eTST}7h8z$}MF(XD(aQ)ZLZ zM?v0rT<1C4XHn<6PbNA{XL@>1^)apdD_@tcYDrW#m`k#MmslI7p^P;Az74wGs`!SI zLs$GEZHsafXsu1i-WleMzAL(yw$-LK{0hv;6hrx8kx!!4$``dAyBnY9Jz&DqJo2$A z!(L$H=KqBeY~CF_viHPz^tTglc?D97CqEBjzUwH}7GI zapg8YZM~>2Wk%E$d&r@9ly9b4Q zJpM7T@}r63I(OExUlG%Xcjz3MU+9U^r!SkpjNThDtaP)7>j6L5z%o5|^hlVOyI*uY zt^UU6NTuY?(Lb4ZIU2Zb5Vz}Pb7KF%ivf&j^CL>$cDz?rMNTQQ|NqDVD7mhghUp%h zhIA{gi{S8y9YhIIbSv$`B!JiPi!0#4#Jge0)p&YVPHchWcyAn zQhvb8ggXGXs9;k`u9Uq*YB>O+Q3Rq=2hlLFcG{Q3ORH_}JnY8C+r%@}6|%ySP%bWG zV~mA;?P`Q2L_Ss})nrJ{$TmeA9Tt*4=}X5x%RioM@_?ZsKSEST-f+GBv~Ya)xX3O{ z8!d=YthI-13OI;RN~`>|6u5L{z20oBp%9MIj)n$!Aw{Wpq&Rtr4~*_74Gjo@3el>B zz(Rk;;>2lp73<2;d=r*8z%WkdsG=vRuG_fvxO#uN^El|+5Qoz^X!2MfxJ3m}vyi?> zMLLDi8+${Z6YbUg?8GNR>-+SwHKdFyr%HqWcs|X_l*-DAC^bG&KCqWg7-_`UlwQ`EdOp_LJkr`L$mHHs75uP?fSgVfsDjuE#ft2b8HDt0yFt!+;C zEgL=)G9ZFt4wa+N3Xg7FGc0~`&EEt6_%7tyzmnb9B_h1~7~GD4V-Bhx7~QKRkF>&aT>(-!Us@aJxAY@8E?HW$G8g zSz@7Jcp>iCp;lU1ieF6n7!oAa-1E!rS0 zF1lBFVS%G#ZO}b@*+bIk+7@Q|iG60vIDVpV%4tW8rKyzwRo_<25;8*Ky@n z-sX>W*b;M){5lB_Edc@m1`VHy0@dg$PTR9uE$O2&a?KAe?xRlCj&Z$iZYw + + 图书归还 + + + +
        + +
        + + + + +
        +
        + +
        +
        *

        昵称

        +
        + +
        +
        + +
        +
        *

        用户名

        +
        + +
        +
        + +
        +
        *

        密码

        +
        + +
        +
        + +
        +

        生日

        +
        + +
        +
        + +
        +

        电话

        +
        + +
        +
        + + +
        +

        身份

        +
        + +
        +
        + +
        +

        邮箱

        +
        + +
        +
        + +
        +

        地址

        +
        + +
        +
        + +
        +

        可借数量

        +
        + +
        +
        +
        +
        + + + +
        +
        + + + +
        +
        +
        +
        +
        +
        + + + + \ No newline at end of file -- Gitee