springboot图书馆管理系统前端

March 26, 2019 · 开发 · 4520次阅读

本次图书馆管理系统开发过程:

分析表关系

表关系比较简单,图书与图书分类为多对一关系,借阅书目与用户为多对一关系,借阅书目与书籍为多对一关系(实际上并没有用到这层关系,因为并没有做前台的借书功能(′Д`))
sql语句贴出一个借阅书目的,数据库用的是MySQL:

create table orderbook(
   id int(11) not null auto_increment,
   name varchar(255) default null,
   uid int(11) default null,
   bid int(11) default null,
   borrowdate timestamp default CURRENT_TIMESTAMP,
   constraint pk_orderbook_user foreign key (uid) references user (id),
   constraint pk_orderbook_book foreign key (bid) references book (id),
   primary key(id)
)engine=innodb default charset=utf8;

建立之后如图:
TIM截图20190325211330.png

配置springboot配置文件

springboot的配置文件主要用来写入数据库驱动用户名密码和其他一些配置

#database
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/library_manage?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto = none

#thymeleaf
spring.thymeleaf.mode=LEGACYHTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.cache=false

#context,页面地址访问就以localhost:8080/开头,
#server.context-path=/library,则以localhost:8080/library开头
server.context-path=/

#设置上传文件大小,默认只有1 m
spring.http.multipart.maxFileSize=100Mb
spring.http.multipart.maxRequestSize=100Mb

#jpa对实体类的默认字段会把驼峰命名的属性,转换为字段名的时候自动加上下划线。 这个配置的作用就是去掉下划线
#比如属性名称是 createDate, jpa 默认转换为字段名 create_Date。 有了这个配置之后,就会转换为同名字段 createDate
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

#显示 hibernate运行的 sql 语句
spring.jpa.show-sql=true

前端部分

前端部分采用的是thymeleaf模板引擎和vue.js渲染页面数据和绑定数据(vue这里仅仅是用到了这两个功能,没有用到脚手架),前端样式采用的bootstrap。

thymeleaf将网页模块化

如图,页面目录如下:
TIM截图20190325213233.png

admin目录下的页面分别:

  • listCategory.html: 显示所有书籍分类的列表
  • editCategory.html: 编辑书籍名字的页面
  • listBook.html: 显示分类下书籍列表的页面
  • listOrderBook.html: 显示每个用户下借阅书籍列表的页面
  • listOrderAll.html: 显示所有借阅的书籍的页面
  • listUser.html:显示所有用户列表的页面
  • login.html: 登录页面

include/admin目录下的页面分别为:

  • adminHeader.html: 将所有前端页面中用到的一些函数统一写到了这个页面里
  • adminNavigator.html 基本每个页面都有的导航栏放在这个页面里
  • adminPage.html 分页跳转方法写在这个页面里
  • adminFooter.html 页脚

这样可以使得将页面中通用的部分单独拿出来,通过thymeleaf进行镶嵌


利用thymeleaf将include/admin中的页面嵌入到admin里的页面中,如下:

    <!DOCTYPE html>
        <html xmlns:th="http://www.thymeleaf.org">
        
        <head th:include="include/admin/adminHeader::html('分类管理')" ></head>  //在head中插入adminHeader.html
        <body>
        <div th:replace="include/admin/adminNavigator::html" ></div>  //在body的一开头插入导航栏adminNavigator.html
        <div id="workingplace">
            此处省略一万行
            <div th:replace="include/admin/adminPage::html" ></div> //插入分页
        </div>
            <div th:replace="include/admin/adminFooter::html" ></div>
        </body>

adminHeader内包含所需要的外部js文件已经css文件,代码如下:

    <template th:fragment="html(title)" > 
        <script src="js/jquery/2.0.0/jquery.min.js"></script>
        <link href="css/bootstrap/3.3.6/bootstrap.min.css" rel="stylesheet">
        <script src="js/bootstrap/3.3.6/bootstrap.min.js"></script>
        <script src="js/vue/2.5.16/vue.min.js"></script>
        <script src="js/axios/0.17.1/axios.min.js"></script>
        <script src="js/moment/2.22.2/moment.js"></script> <!-- vue.js 格式化日期用的 -->
        <link href="css/back/style.css" rel="stylesheet">
        <script>
        //判断是否为空
        function checkEmpty(value,text){
            
            if(null==value || value.length==0){
                alert(text+ "不能为空");
                return false;
            }
            return true;
        }    
        ...
        //此处省略
        ...
    
        </script>    
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">     
        <title th:text="${title}" ></title>
    </template>

template标签配合th:include可以实现加载template模板中的内容,template标签加载后自动忽略。
th:replace则是配合div标签自动将当前的div替换th:replace的div标签


adminNavigator.html的代码


    <div class="navitagorDiv" th:fragment="html">
        <nav class="navbar navbar-default navbar-fixed-top navbar-inverse">
            <div class="container-fluid">
            <div class="navbar-header">
                <img style="margin-left:10px;margin-right:0px" class="pull-left navbar-brand" src="img/site/library.jpg" height="45px">
                <a class="navbar-brand" href="/admin_login">图书馆管理后台</a>
                <a class="navbar-brand" href="admin_category_list">分类管理</a>
                <a class="navbar-brand" href="admin_user_list">用户管理</a>
                <a class="navbar-brand" href="/admin_orderall_list">借阅管理</a>
            </div>
            </div>
        </nav>
    </div>

分类列表中的代码片段:

    <head th:include="include/admin/adminHeader::html('分类管理')" ></head>
    <body>
    <div th:replace="include/admin/adminNavigator::html" ></div>

TIM截图20190326095920.png
如上,通过镶嵌,这样每个页面就有一个导航栏

vue进行页面数据渲染

以listCategory.hmtl书籍分类列表页面为例:
TIM截图20190326102748.png

上图部分html代码如下:

    <div id="workingArea" >
        <div class="listDataTableDiv">
            <table class="table table-striped table-bordered table-hover  table-condensed">
                <thead>
                <tr class="success">
                    <th>ID</th>
                    <th>分类名称</th>
                    <th>书籍管理</th>
                    <th>编辑</th>
                    <th>删除</th>
                </tr>
                </thead>
                <tbody>
                <tr v-for="bean in beans ">
                    <td>{{bean.id}}</td>
                    <td>
                        {{bean.name}}
                    </td>
                    <td>
                        <a :href="'admin_book_list?cid=' + bean.id "><span class="glyphicon glyphicon-shopping-cart"></span></a>
                    </td>
                    <td>
                        <a :href="'admin_category_edit?id=' + bean.id "><span class="glyphicon glyphicon-edit"></span></a>
                    </td>
                    <td>
                        <a href="#nowhere"  @click="deleteBean(bean.id)"><span class="   glyphicon glyphicon-trash"></span></a>
                    </td>
                </tr>
                </tbody>
            </table>
        </div>
        <div class="panel panel-warning addDiv">
            <div class="panel-heading">新增分类</div>
            <div class="panel-body">
                <table class="addTable">
                    <tr>
                        <td>分类名称</td>
                        <td><input  @keyup.enter="add" v-model.trim="bean.name" type="text" class="form-control"></td>
                    </tr>
                    <tr class="submitTR">
                        <td colspan="2" align="center">
                            <a href="#nowhere"  @click="add" class="btn btn-success">提交</a>
                        </td>
                    </tr>
                </table>
            </div>
        </div>
        <div th:replace="include/admin/adminPage::html" ></div>
    </div>

由一个存放书籍列表的表格table,和一个显示添加书籍的表格组成。


vue脚本部分:

    <script>
        $(function(){
            var data4Vue = {
                uri:'categories',
                pagination:{},
                beans: [],
                bean:{id:0,name:""},
                file:null,
                keyword:''
            };
    
            //ViewModel
            var vue = new Vue({
                el: '#workingArea',
                data: data4Vue,
                mounted:function(){ //mounted 表示这个 Vue 对象加载成功了
                    this.list(0);
                },
                methods: {
                    list:function(start){
                        var url =  this.uri+ "?start="+start;
                        axios.get(url).then(function(response) {
                            vue.pagination = response.data;
                            vue.beans = response.data.content;
                        });
                    },
                    listSearch:function () {
                        var url = "search?keyword="+vue.keyword;
                        axios.post(url).then(function (response) {
                            vue.beans = response.data;
                        })
                    },
                    jump: function(page){
                        jump(page,vue); //定义在adminHeader.html 中
                    },
                    jumpByNumber: function(start){
                        jumpByNumber(start,vue);
                    },
                    add: function () {
                        var url = this.uri;
                         axios.post(url,vue.bean).then(function () {
                            vue.list(0);
                            vue.bean = {id:0,name:'',hp:'0'};
                        })
                    },
                    deleteBean:function (id) {
                      if(!checkDeleteLink())
                          return;
                      var url = this.uri+"/"+id;
                      axios.delete(url).then(function (response) {
                          if (0!=response.data.length) //rest规范删除数据要求要会返回空字符串(控制器中delete返回null),所以进行判断
                              alert(response.data);
                          else
                              vue.list(0); //是空字符串则调第一页
                      })
                    }
                }
            });
        });
    </script>

页面渲染流程如下:

vue渲染页面流程.png

其中:

  • $()是jquery中的用法,表示页面html文档加载完毕后自动执行里面的脚本。
    $(function () {。。。})
  • var data4Vue是vue中定义的数据变量,也可以直接写在vue对象里

{% codeblock lang:JavaScript %}

var data4Vue = {
            uri:'categories',
            pagination:{},
            beans: [],
            bean:{id:0,name:""},
            keyword:''
        };


- vue里的el:#workingArea表示该vue对象是对id为workingArea的html标签区域进行数据渲染
- mounted表示对象加载完毕时自动执行mounted里面的函数
- methods在里面编写页面所需要的函数
- methods里的list函数中

{% codeblock lang:JavaScript %}
        list:function(start){
                            var url =  this.uri+ "?start="+start;
                            axios.get(url).then(function(response) {
                                vue.pagination = response.data;
                                vue.beans = response.data.content;
                            });
                        },

url为请求的地址,?后面为请求参数,服务器后端程序能通过注解自动识别?后的参数。
axios请求函数可以是get,post,delete等依情况定,请求成功后才会执行then里面的函数。then里面函数将返回的数据赋值给vue的数据变量中,vue通过在html标签中绑定的数据变量从而将数据渲染到页面中(请求的具体流程图在之后的后端部分给出),如下,beans变量

        <tbody>
            <tr v-for="bean in beans ">
                <td>{{bean.id}}</td>
                <td>
                    {{bean.name}}
                </td>
                <td>
                    <a :href="'admin_book_list?cid=' + bean.id "><span class="glyphicon glyphicon-shopping-cart"></span></a>
                </td>
                <td>
                    <a :href="'admin_category_edit?id=' + bean.id "><span class="glyphicon glyphicon-edit"></span></a>
                </td>
                <td>
                    <a href="#nowhere"  @click="deleteBean(bean.id)"><span class="   glyphicon glyphicon-trash"></span></a>
                </td>
            </tr>
        </tbody>

输入框等表单用v-model双向绑定,即输入的内容会绑定到v-model后的数据变量里,同时数据变量值的改变也会改变表单中的值。

页面样式

样式主要采用bootstrap,在adminHeader.html引入

  • adminNavigator.html中导航栏样式
        <nav class="navbar navbar-default navbar-fixed-top navbar-inverse">
                <div class="navbar-header">
                    <img style="margin-left:10px;margin-right:0px" class="pull-left navbar-brand" src="img/site/library.jpg" height="45px">
                    <a class="navbar-brand" href="/admin_login">图书馆管理后台</a>
                    <a class="navbar-brand" href="admin_category_list">分类管理</a>
                    <a class="navbar-brand" href="admin_user_list">用户管理</a>
                    <a class="navbar-brand" href="/admin_orderall_list">借阅管理</a>
                </div>
            </nav>

nav标签中的属性navbar navbar-default nvarbar-fixed-top navbar-inverse分别就是bootstrap样式中的导航栏,导航栏默认样式,固定不随页面滑动,颜色反转(本来是白色的)

TIM截图20190326095920.png


  • 页面中展示数据的表格所用的样式
    list.png
    <table class="table table-striped table-bordered table-hover  table-condensed">



    <tr class="success">

table:普通表格,table-striped:斑马线(颜色交替),table-border:列与列之间的分割线,table-hover:鼠标经过有效果,table-condensed:响应式效果,根据页面大小变换。
行标签中有集中颜色可选,其中success为绿色

  • 添加书籍分类的面板
    面板.png

    <div class="panel panel-warning addDiv">
            <div class="panel-heading">新增分类</div>
            <div class="panel-body">
            .....
            ...

panel:一个面板, panel-warning:颜色警告色(黄色)
panel-heading:面板标题,body为面板内容
面板里的内容为一个2x2的table构成

  • 登录页面
    TIM截图20190326202043.png

登录页面采用bootstrap中的栅格化布局(网上物色的登录界面,在css中改了背景)。基本思想是bootstrap将页面分成了12份利用class属性col-lg-xx来配置个标签所占位置 ,如图:
TIM截图20190326204248.png
所以标题输入框以及按钮class中都设置超过6的数值就会一行的一行的排列。
input中的required属性表示不能为空,autofocus表示页面加载后自动获得焦点

        <div id="form">
        <form>
            <div class="mycenter">
                <div class="mysign">
                    <div class="col-lg-12 text-center text-info">
                        <h2>
                            图书馆管理系统
                        </h2>
                    </div>
                    <div class="col-lg-11">
                        <input v-model="user.name" type="text" name="username" placeholder="请输入账户名" required autofocus/>
                    </div>
                    <div class="col-lg-10">
                    </div>
                    <div class="col-lg-10">
                        <input v-model="user.passWord" type="password" name="password" placeholder="请输入密码" required/>
                    </div>
                    <div class="col-lg-10">
                    </div>
                    <div class="col-lg-10">
                    </div>
                    <div class="col-lg-10">
                        <button @click="login" type="button" id="btn" class="btn btn-success col-lg-12">
                            登录</button>
                    </div>
                </div>
            </div>
        </form>
        </div>

静态文件路径设置

改写css,图片,以及前端框架js文件的路径到resource/webapp路径下,在idea中如下设置
setting -> project structure ->facets设置web resource directory
TIM截图20190326193812.png

这样外部静态文件能采用如下相对路径的方式引入:

    <script src="js/jquery/2.0.0/jquery.min.js"></script>
    <link href="css/bootstrap/3.3.6/bootstrap.min.css" rel="stylesheet">
    <script src="js/bootstrap/3.3.6/bootstrap.min.js"></script>
    <script src="js/vue/2.5.16/vue.min.js"></script>
    <script src="js/axios/0.17.1/axios.min.js"></script>
    <script src="js/moment/2.22.2/moment.js"></script> <!-- vue.js 格式化日期用的 -->
    <link href="css/back/style.css" rel="stylesheet">

标签:none

最后编辑于:2020/10/25 19:34

  1. 2020-09-20 20:00

    online slot games free slots slots games free free slots [url=http://onlinecasinouse.com/# ]casino blackjack [/url]

  2. 2020-09-26 22:45

    [url=https://silagrarx.com/]silagra tablets[/url]

  3. 2020-09-26 23:57

    [url=http://phenergansr.com/]phenergan 25mg tablets[/url] [url=http://elimitep.com/]order elimite online[/url] [url=http://cialisz.com/]purchase cialis 20 mg[/url] [url=http://hydroxychloroquina.com/]hydroxychloroquine cost[/url] [url=http://ahydroxychloroquine.com/]plaquenil 400 mg[/url]

  4. 2020-09-27 02:49

    [url=http://tadalafilhit.com/]generic tadalafil 5mg price[/url] [url=http://baclofen365.com/]how to get baclofen[/url] [url=http://periactinmed.com/]buy periactin appetite stimulant[/url] [url=http://zestoretic24.com/]zestoretic 5 mg[/url] [url=http://wellbutrin15.com/]zyban pills[/url]

  5. 2020-09-27 05:53

    [url=https://sildenefil.com/]sildenafil 20 mg tablet cost[/url] [url=https://sildenafilt.com/]sildenafil 50 mg buy online india[/url] [url=https://trimoxx.com/]amoxicillin 500 mg buy online[/url] [url=https://cephalexinlab.com/]cephalexin best price[/url] [url=https://glucophaghe.com/]can i buy metformin over the counter in australia[/url] [url=https://plavixm.com/]plavix[/url] [url=https://buyhydroxychloroquine.us.com/]hydroxychloroquine sulfate tab 200 mg[/url] [url=https://zoviraxz.com/]acyclovir cream singapore[/url] [url=https://sildenafil240.com/]where to buy generic sildenafil[/url] [url=https://lasixfuro.com/]furosemide uk[/url] [url=https://kamagrasr.com/]kamagra 50 mg oral jelly[/url] [url=https://benicar911.com/]generic benicar pills[/url] [url=https://buyviagaonline.com/]viagra tablet online india[/url] [url=https://ciprotab.com/]cipro cost usa[/url] [url=https://lanoxin24.com/]digoxin brand name[/url] [url=https://furosemide3.com/]furosemide brand name in india[/url] [url=https://elimitep.com/]where to buy elimite cream[/url] [url=https://albenzarx.com/]buy albendazole tablets[/url] [url=https://cytotectab.com/]cheap cytotec pills online[/url] [url=https://tadacialis.com/]cheap 5 mg tadalafil[/url]

  6. 2020-09-27 07:36

    [url=https://sildenafilt.com/]sildenafil 90 mg[/url] [url=https://tadalafilcs.com/]cialis usa pharmacy[/url] [url=https://plavixm.com/]price of plavix in india[/url] [url=https://ataraxmed.com/]atarax 25mg tab[/url] [url=https://suhagra1.com/]suhagra 50mg buy online india[/url] [url=https://dapoxetine360.com/]dapoxetine prescription[/url] [url=https://anafraniltab.com/]anafranil 25 mg tablet[/url] [url=https://buyhydroxychloroquine.us.org/]hydroxychloroquine 70 mg[/url]

  7. 2020-09-27 09:21

    [url=https://silagrarx.com/]silagra 100mg tablets[/url] [url=https://sildenaviagra.com/]sildenafil otc uk[/url] [url=https://viagraphrm.com/]viagra tablets in india price[/url] [url=https://buyhydroxychloroquine.us.com/]plaquenil 800 mg[/url] [url=https://vardemafil.com/]levitra uk buy[/url]

控制面板