前言:这将会是一片较长的博客,不奢望其他人能够看完,只是希望在很久以后,自己看到这篇博客的时候能够记得这样一段经历。在想做这样一个图书管理系统的时候,是自己大二的时候,当时希望能够将学校所有的二手书充分利用。也就是高年级的同学能够把这些书给低年级的同学,当时的设计是低年级发布需求,高年级发布资源,如果发现互相合适的,那么久自动对接。当时这个系统呢,设计图已经让人设计好了,但是还没有动手开始写。幸运的是,自己在一次课程上,偶然发现有人和我一样的想法,只是他不是技术性的,只是单纯的线下宣传高年级同学来捐书,低年级同学来领书,每本书通过Excel来记录,并且当时已经收集了一千多本书。作为一名有热血的信管人怎么能够容许身边有这样的事情发生,所以我决定给它做一个图书管理系统。自己在做这个系统的时候,从最开始的服务器购买到最后的上线运行,中间的需求,设计,开发都是自己一个人。有时候觉得挺辛苦,毕竟是无偿的,哈哈。但是真正在这个系统做完的时候,没有一丝的后悔,不仅自己学到了很多,也真正能够感受到赠人玫瑰,手留余香的快乐。
业务需求描述
用户需求
用户使用手机号码注册,注册的时候通过手机号码接受验证码
查询自己需要的书本,如果有自己想要的,可以去指定的地方领取
如果自己想要捐赠图书,可以去指定的地方捐赠
管理需求
通过调用微信扫一扫扫描书本后的isbn编码将数据录入数据库
通过扫码器扫描书本后的isbn编码将书籍录入数据库
查看书籍信息和库存量
修改库存量
查看用户信息,用户领书和捐书量以及活跃度
实现用户捐书和领书扫码操作
根据入库时间和数量作图
根据出库时间和数量作图
系统设计流程图
成果展示
用户界面
管理界面
前端总结
用户界面
关于用户界面布局这一块,之前一个朋友写了一些,我是在他的基础上修改的,重新规划了一下组件,引用了他的样式。他写的时候用了Vuex进行状态管理,但是我后面是采用的组件通信来完成的。因为用户界面相关状态管理不多,使用Vuex未免有些不划算。
1、文件的结构
2、用户界面的前端,最大的收获就是组件之间的通信,但是这个不是几句话能够说完的,后面我会单独写文章进行总结。
管理界面
1、分页操作,保证只出现5个页码,左4+右1或左1+右4或左1中3右1。主要思路为获取总页数,判断是否超过5页,如果不超过就全部显示,如果超过就判断当前页是多少页,如果小于3,那么就显示【最小页,2,3,4,最大页】;如果大于最大页码-2,那么就显示【最小页码,最大页-3,最大页码-2,最大页码-1,最大页码】;如果介于两者之间,那么就显示【最小页,当前页-1,当前页,当前页+1,最大页】。
核心代码如下:
/*html*/
<div class="page">
<ul>
<li @click="pre">上页</li>
<template v-if=" max_page<5 ">
<li v-for="n in max_page" :key="(n)" @click="goPage(n)" v-bind:class="{active: n===pagenum}">{{n}}</li>
</template>
<template v-else>
<li @click="goPage(1)" v-bind:class="{active: 1===pagenum}">1</li>
<li v-show="front">...</li>
<li v-for="n in indexs" :key="(n)" @click="goPage(n)" v-bind:class="{active: n===pagenum}">{{n}}</li>
<li v-show="end">...</li>
<li @click="goPage(max_page)" v-bind:class="{active: max_page===pagenum}">{{max_page}}</li>
</template>
<li @click="next">下页</li>
</ul>
</div>
/*js*/
indexs: function() {
if(this.max_page === 0){
return
}
var page = [];
if(this.pagenum < 3) {
page = [2, 3, 4];
}else if(this.pagenum > (this.max_page-2) ) {
page = [this.max_page-3, this.max_page-2, this.max_page-1];
}else{
page = [this.pagenum-1, this.pagenum, this.pagenum+1];
}
return page;
}
2、使用css3中的calc。在自己做模态框的时候,以前总是通过JavaScript来实现居中,这次巧妙的使用了calc,很轻松的实现了效果,值得注意的是,使用calc的时候,进行四则运算的时候中间一定要加空格,否则不会产生效果。代码如下:
.window {
position: fixed;
width: 400px;
height: 400px;
left: calc(50% - 200px);
top: 100px;
border-radius: 50%;
background: #CDAF95;
text-align: center;
line-height: 400px;
font-size: 33px;
color: white;
z-index: 999;
}
3、使用Chart插件绘图,关于这个插件的使用,可以看我另外一篇博客
http://blog.csdn.net/m0_37568521/article/details/78011731
后端总结
用户界面
1、实现短信验证码,这是第一次接触到这个东西,不过难度还是不大的,这里进行简单的总结。我使用的平台是云片网,不过其他平台相比也差不过,因为我只是想使用简单的短信验证,所以没有引入平台的sdk。下面是核心代码。
<?php
session_start();
$ch = curl_init();
$apikey = "*****";//登录平台可以获取apikey
$mobile = $_POST['phone_number'];//获取传递的电话号码
$code = rand(1000,9999);//生成随机函数
$text="您的本次验证码是".$code.",请勿泄露个人信息,欢迎来到伯牙书舍!一汪清泉石上流,知语桃花笑迎开。花雨琴声悄落处,伯牙子期再聚来。";//发送内容,这里需要和平台申请的模板一致
// 发送短信
$data=array('text'=>$text,'apikey'=>$apikey,'mobile'=>$mobile);
curl_setopt ($ch, CURLOPT_URL, 'https://sms.yunpian.com/v2/sms/single_send.json');
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
$json_data = curl_exec($ch);
//如果curl发生错误,打印出错误
if(curl_error($ch) != ""){
output(1,'验证过于频繁,请稍后再试');//output是我自己封装的一个输出函数
exit();
}
//解析返回结果(json格式字符串)
$array = json_decode($json_data,true);
$_SESSION['code'] = $code;
output(0,'获取验证码成功');
?>
管理界面
1、调用微信扫一扫遇到的问题以及解决方法可以看我这一篇博客
http://blog.csdn.net/m0_37568521/article/details/77948909
2、使用扫码器进行扫码入库。对于一个没有接触的东西,我们总是有自己的一些猜想,扫码器扫出来的东西到底是什么?管它的呢,先买一个来玩玩。其实扫码器就是一个简单的输入设备而已,扫码图书后面的ISBN码,然后将ISBN码显示在屏幕上。所以这个东西只是帮助我们快速获取ISBN码而已,获取到了ISBN码,然后调用豆瓣的API获取图书信息,但是最近豆瓣的API对于用户有限制,一个小时只能够调用100次。因为有些书籍豆瓣的API没有,所以我最开始处理的方法是先调用接口,查看是否这本书存在,如果不存在就不访问数据库了,后面发现这个限制以后只好先访问数据库,如果不存在再去调用豆瓣接口。关于通过ISBN调用扣板接口获取数据的核心代码如下:
date_default_timezone_set('prc');
$isbn = $_POST['isbn'];
$url = "https://api.douban.com//v2/book/isbn/$isbn";
$ch = curl_init();
$timeout = 5;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$content = curl_exec($ch);
curl_close($ch);
$bookInfo = json_decode($content, true);
$title = $bookInfo['title'];
if($title == '') {
echo '该书需要手动录入';
}else{
$author = $bookInfo['author'][0];
$pubdate = $bookInfo['pubdate'];
$image = $bookInfo['image'];
$pages = $bookInfo['pages'];
$publisher = $bookInfo['publisher'];
$summary = $bookInfo['summary'];
$time = date('y-m-d H:i:s',time());
$sql = "INSERT INTO books(title,author,pubdate,image,pages,publisher,summary,isbn,book_number,deliver_time) VALUES('$title','$author','$pubdate','$image','$pages','$publisher','$summary','$isbn',1,'$time')";
$con->query($sql);
if($con->affected_rows == 1){
$id = $con->insert_id;
$sql = "SELECT COUNT(*) as 'id' FROM books WHERE book_id <= $id";
$res = $con->query($sql);
$row = $res->fetch_assoc();
echo '录入成功,新书编码'.$row['id'];
}else{
echo '录入新书失败'.$con->errno;
}
}
不足与缺点
关于整个系统的构造,因为时间原因,对于系统的安全性考虑较少。后面需要多多注意